pax_global_header00006660000000000000000000000064132525044710014515gustar00rootroot0000000000000052 comment=49def2432b398125d76ba328f7f00ab3b7ccd101 bind9-9.11.3+dfsg/000077500000000000000000000000001325250447100135345ustar00rootroot00000000000000bind9-9.11.3+dfsg/.gitattributes000066400000000000000000000001061325250447100164240ustar00rootroot00000000000000*.sln.in eol=crlf *.vcxproj.in eol=crlf *.vcxproj.filters.in eol=crlf bind9-9.11.3+dfsg/Atffile000066400000000000000000000001301325250447100150230ustar00rootroot00000000000000Content-Type: application/X-atf-atffile; version="1" prop: test-suite = bind9 tp: lib bind9-9.11.3+dfsg/CHANGES000066400000000000000000020243741325250447100145430ustar00rootroot00000000000000 --- 9.11.3 released --- --- 9.11.3rc2 released --- 4904. [bug] Temporarily revert change #4859. [GL #124] --- 9.11.3rc1 released --- 4889. [func] Warn about the use of old root keys without the new root key being present. Warn about dlv.isc.org's key being present. Warn about both managed and trusted root keys being present. [RT #43670] 4888. [test] Initialize sockets correctly in sample-update so that the nsupdate system test will run on Windows. [RT #47097] 4886. [doc] Document dig -u in manpage. [RT #47150] 4885. [security] update-policy rules that otherwise ignore the name field now require that it be set to "." to ensure that any type list present is properly interpreted. [RT #47126] 4882. [bug] Address potential memory leak in dns_update_signaturesinc. [RT #47084] 4881. [bug] Only include dst_openssl.h when OpenSSL is required. [RT #47068] 4879. [bug] dns_rdata_caa:value_len field was too small. [RT #47086] 4878. [bug] List 'ply' as a requirement for the 'isc' python package. [RT #47065] 4811. [bug] Revert api changes to use inline macros. Provide a alternative mechanism to turn on the use of inline macros when building BIND. [RT #46520] --- 9.11.3b1 released --- 4876. [bug] Address deadlock with accessing a keytable. [RT #47000] 4875. [bug] Address compile failures on older systems. [RT #47015] 4874. [bug] Wrong time display when reporting new keywarntime. [RT #47042] 4873. [doc] Grammars for named.conf included in the ARM are now automatically generated by the configuration parser itself. As a side effect of the work needed to separate zone type grammars from each other, this also makes checking of zone statements in named-checkconf more correct and consistent. [RT #36957] 4872. [bug] Don't permit loading meta RR types such as TKEY from master files. [RT #47009] 4871. [bug] Fix configure glitch in detecting stdatomic.h support on systems with multiple compilers. [RT #46959] 4870. [test] Update included ATF library to atf-0.21 preserving the ATF tool. [RT #46967] 4869. [bug] Address some cases where NULL with zero length could be passed to memmove which is undefined behaviour and can lead to bad optimisation. [RT #46888] 4867. [cleanup] Normalize rndc on/off commands (validation and querylog) so they accept the same synonyms for on/off (yes/no, true/false, enable/disable). Thanks to Tony Finch. [RT #47022] 4866. [port] DST library initialization verifies MD5 (when MD5 was not disabled) and SHA-1 hash and HMAC support. [RT #46764] 4864. [bug] named acting as a slave for a catalog zone crashed if the latter contained a master definition without an IP address. [RT #45999] 4863. [bug] Fix various other bugs reported by Valgrind's memcheck tool. [RT #46978] 4862. [bug] The rdata flags for RRSIG were not being properly set when constructing a rdataslab. [RT #46978] 4861. [bug] The isc_crc64 unit test was not endian independent. [RT #46973] 4860. [bug] isc_int8_t should be signed char. [RT #46973] 4859. [bug] A loop was possible when attempting to validate unsigned CNAME responses from secure zones; this caused a delay in returning SERVFAIL and also increased the chances of encountering CVE-2017-3145. [RT #46839] 4858. [security] Addresses could be referenced after being freed in resolver.c, causing an assertion failure. (CVE-2017-3145) [RT #46839] 4857. [bug] Maintain attach/detach semantics for event->db, event->node, event->rdataset and event->sigrdataset in query.c. [RT #46891] 4856. [bug] 'rndc zonestatus' reported the wrong underlying type for a inline slave zone. [RT #46875] 4852. [bug] Handle strftime() failing in isc_time_formatISO8601ms. Add REQUIRE's and INSIST's to isc_time_formattimestamp, isc_time_formathttptimestamp, isc_time_formatISO8601, isc_time_formatISO8601ms. [RT #46892] 4851. [port] Support using kyua as well as atf-run to run the unit tests. [RT #46853] 4850. [bug] Named failed to restart with multiple added zones in lmdb database. [RT #46889] 4849. [bug] Duplicate zones could appear in the .nzf file if addzone failed. [RT #46435] 4846. [test] Adjust timing values in runtime system test. Address named.pid removal races in runtime system test. [RT #46800] 4844. [test] Address memory leaks in libatf-c. [RT #46798] 4843. [bug] dnssec-signzone free hashlist on exit. [RT #46791] 4842. [bug] Conditionally compile opensslecdsa_link.c to avoid warnings about unused function. [RT #46790] 4841. [bug] Address -fsanitize=undefined warnings. [RT #46786] 4840. [test] Add tests to cover fallback to using ZSK on inactive KSK. [RT #46787] 4839. [bug] zone.c:zone_sign was not properly determining if there were active KSK and ZSK keys for a algorithm when update-check-ksk is true (default) leaving records unsigned with one or more DNSKEY algorithms. [RT #46774] 4838. [bug] zone.c:add_sigs was not properly determining if there were active KSK and ZSK keys for a algorithm when update-check-ksk is true (default) leaving records unsigned with one or more DNSKEY algorithms. [RT #46754] 4837. [bug] dns_update_signatures{inc} (add_sigs) was not properly determining if there were active KSK and ZSK keys for a algorithm when update-check-ksk is true (default) leaving records unsigned when there were multiple DNSKEY algorithms for the zone. [RT #46743] 4836. [bug] Zones created using "rndc addzone" could temporarily fail to inherit an "allow-transfer" ACL that had been configured in the options statement. [RT #46603] 4835. [cleanup] Clean up and refactor LMDB-related code. [RT #46718] 4834. [port] Fix LMDB support on OpenBSD. [RT #46718] 4833. [bug] isc_event_free should check that the event is not linked when called. [RT #46725] 4832. [bug] Events were not being removed from zone->rss_events. [RT #46725] 4831. [bug] Convert the RRSIG expirytime to 64 bits for comparisions in diff.c:resign. [RT #46710] 4830. [bug] Failure to configure ATF when requested did not cause an error in top-level configure script. [RT #46655] 4829. [bug] isc_heap_delete did not zero the index value when the heap was created with a callback to do that. [RT #46709] 4828. [bug] Do not use thread-local storage for storing LMDB reader locktable slots. [RT #46556] 4827. [misc] Add a precommit check script util/checklibs.sh [RT #46215] 4826. [cleanup] Prevent potential build failures in bin/confgen/ and bin/named/ when using parallel make. [RT #46648] 4825. [bug] Prevent a bogus "error during managed-keys processing (no more)" warning from being logged. [RT #46645] 4823. [test] Refactor reclimit system test to improve its reliability and speed. [RT #46632] 4822. [bug] Use resign_sooner in dns_db_setsigningtime. [RT #46473] 4821. [bug] When resigning ensure that the SOA's expire time is always later that the resigning time of other records. [RT #46473] 4820. [bug] dns_db_subtractrdataset should transfer the resigning information to the new header. [RT #46473] 4819. [bug] Fully backout the transaction when adding a RRset to the resigning / removal heaps fails. [RT #46473] 4818. [test] The logfileconfig system test could intermittently report false negatives on some platforms. [RT #46615] 4817. [cleanup] Use DNS_NAME_INITABSOLUTE and DNS_NAME_INITNONABSOLUTE. [RT #45433] 4816. [bug] Don't use a common array for storing EDNS options in DiG as it could fill up. [RT #45611] 4815. [bug] rbt_test.c:insert_and_delete needed to call dns_rbt_addnode instead of dns_rbt_addname. [RT #46553] 4814. [cleanup] Use AS_HELP_STRING for consistent help text. [RT #46521] 4812. [bug] Minor improvements to stability and consistency of code handling managed keys. [RT #46468] 4810. [test] The chain system test failed if the IPv6 interfaces were not configured. [RT #46508] 4809. [port] Check at configure time whether -latomic is needed for stdatomic.h. [RT #46324] 4808. [bug] Properly test for zlib.h. [RT #46504] 4805. [bug] TCP4Active and TCP6Active weren't being updated correctly. [RT #46454] 4804. [port] win32: access() does not work on directories as required by POSIX. Supply a alternative in isc_file_isdirwritable. [RT #46394] 4803. [bug] Backport parts of RT #45293 and RT #46267, specifically the fix for RT #46055 and mkeys system test improvements. [RT #46430] 4800. [bug] When processing delzone, write one zone config per line to the NZF. [RT #46323] 4799. [cleanup] Improve clarity of keytable unit tests. [RT #46407] 4792. [bug] Fix map file header correctness check. [RT #38418] 4791. [doc] Fixed outdated documentation about export libraries. [RT #46341] 4790. [bug] nsupdate could trigger a require when sending a update to the second address of the server. [RT #45731] 4788. [cleanup] When using "update-policy local", log a warning when an update matching the session key is received from a remote host. [RT #46213] 4787. [cleanup] Turn nsec3param_salt_totext() into a public function, dns_nsec3param_salttotext(), and add unit tests for it. [RT #46289] 4783. [test] dnssec: 'check that NOTIFY is sent at the end of NSEC3 chain generation failed' required more time on some machines for the IXFR to complete. [RT #46388] 4782. [test] dnssec: 'checking positive and negative validation with negative trust anchors' required more time to complete on some machines. [RT #46386] 4781. [maint] B.ROOT-SERVERS.NET is now 199.9.14.201. [RT #45889] 4780. [bug] When answering ANY queries, don't include the NS RRset in the authority section if it was already in the answer section. [RT #44543] 4779. [bug] Expire NTA at the start of the second. Don't update the expiry value if the record has already expired after a successful check. [RT #46368] 4777. [cleanup] Removed a redundant call to configure_view_acl(). [RT #46369] 4776. [bug] Improve portability of ht_test. [RT #46333] 4775. [bug] Address Coverity warnings in ht_test.c [RT #46281] 4774. [bug] was incorrectly included in several header files. [RT #46311] 4773. [doc] Fixed generating Doxygen documentation for functions annotated using certain macros. Miscellaneous Doxygen-related cleanups. [RT #46276] 4771. [bug] When sending RFC 5011 refresh queries, disregard cached DNSKEY rrsets. [RT #46251] 4770. [bug] Cache additional data from priming queries as glue. Previously they were ignored as unsigned non-answer data from a secure zone, and never actually got added to the cache, causing hints to be used frequently for root-server addresses, which triggered re-priming. [RT #45241] 4769. [bug] Enforce the requirement that the managed keys directory (specified by "managed-keys-directory", and defaulting to the working directory if not specified) must be writable. [RT #46077] 4766. [cleanup] Addresss Coverity warnings. [RT #46150] 4763. [contrib] Improve compatibility when building MySQL DLZ module by using mysql_config if available. [RT #45558] 4762. [func] "update-policy local" is now restricted to updates from local addresses. (Previously, other addresses were allowed so long as updates were signed by the local session key.) [RT #45492] 4761. [protocol] Add support for DOA. [RT #45612] 4759. [func] Add logging channel "trust-anchor-telementry" to record trust-anchor-telementry in incoming requests. Both _ta-XXXX./NULL and EDNS KEY-TAG options are logged. [RT #46124] 4758. [doc] Remove documentation of unimplemented "topology". [RT #46161] 4756. [bug] Interrupting dig could lead to an INSIST failure after certain errors were encountered while querying a host whose name resolved to more than one address. Change 4537 increased the odds of triggering this issue by causing dig to hang indefinitely when certain error paths were evaluated. dig now also retries TCP queries (once) if the server gracefully closes the connection before sending a response. [RT #42832, #45159] 4755. [cleanup] Silence unnecessary log message when NZF file doesn't exist. [RT #46186] 4754. [bug] dns_zone_setview needs a two stage commit to properly handle errors. [RT #45841] 4753. [contrib] Software obtainable from known upstream locations (i.e., zkt, nslint, query-loc) has been removed. Links to these and other packages can be found at https://www.isc.org/community/tools [RT #46182] 4752. [test] Add unit test for isc_net_pton. [RT #46171] 4749. [func] The ISC DLV service has been shut down, and all DLV records have been removed from dlv.isc.org. - Removed references to ISC DLV in documentation - Removed DLV key from bind.keys - No longer use ISC DLV by default in delv [RT #46155] 4748. [cleanup] Sprintf to snprintf coversions. [RT #46132] 4746. [cleanup] Add configured prefixes to configure summary output. [RT #46153] 4745. [test] Add color-coded pass/fail messages to system tests when running on terminals that support them. [RT #45977] 4744. [bug] Suppress trust-anchor-telementry queries if validation is disabled. [RT #46131] 4741. [bug] Make isc_refcount_current() atomically read the counter value. [RT #46074] 4740. [cleanup] Avoid triggering format-truncated warnings. [RT #46107] 4739. [cleanup] Address clang static analysis warnings. [RT #45952] 4738. [port] win32: strftime mishandles %Z. [RT #46039] 4737. [cleanup] Address Coverity warnings. [RT #46012] 4736. [cleanup] (a) Added comments to NSEC3-related functions in lib/dns/zone.c. (b) Refactored NSEC3 salt formatting code. (c) Minor tweaks to lock and result handling. [RT #46053] 4735. [bug] Add @ISC_OPENSSL_LIBS@ to isc-config. [RT #46078] 4734. [contrib] Added sample configuration for DNS-over-TLS in contrib/dnspriv. 4731. [bug] Fix use after free when closing an LMDB. [RT #46000] 4730. [bug] Fix out of bounds access in DHCID totext() method. [RT #46001] 4729. [bug] Don't use memset() to wipe memory, as it may be removed by compiler optimizations when the memset() occurs on automatic stack allocation just before function return. [RT #45947] 4728. [func] Use C11's stdatomic.h instead of isc_atomic where available. [RT #40668] 4727. [bug] Retransferring an inline-signed slave using NSEC3 around the time its NSEC3 salt was changed could result in an infinite signing loop. [RT #45080] 4726. [port] Prevent setsockopt() errors related to TCP_FASTOPEN from being logged on FreeBSD if the kernel does not support it. Notify the user when the kernel does support TCP_FASTOPEN, but it is disabled by sysctl. Add a new configure option, --disable-tcp-fastopen, to disable use of TCP_FASTOPEN altogether. [RT #44754] 4725. [bug] Nsupdate: "recvsoa" was incorrectly reported for failures in sending the update message. The correct location to be reported is "update_completed". [RT #46014] 4723. [bug] Statistics counter DNSTAPdropped was misidentified as DNSSECdropped. [RT #46002] 4722. [cleanup] Clean up uses of strcpy() and strcat() in favor of strlcpy() and strlcat() for safety. [RT #45981] 4719. [bug] Address PVS static analyzer warnings. [RT #45946] 4717. [bug] Treat replies with QCOUNT=0 as truncated if TC=1, FORMERR if TC=0, and log the error correctly. [RT #45836] 4715. [bug] TreeMemMax was mis-identified as a second HeapMemMax in the Json cache statistics. [RT #45980] 4714. [port] openbsd/libressl: add support for building with --enable-openssl-hash. [RT #45982] 4713. [cleanup] Minor revisions to RPZ code to reduce differences with the development branch. [RT #46037] 4712. [bug] "dig +domain" and "dig +search" didn't retain the search domain when retrying with TCP. [RT #45547] 4711. [test] Some RR types were missing from genzones.sh. [RT #45782] 4709. [cleanup] Use dns_name_fullhash() to hash names for RRL. [RT #45435] 4703. [bug] BINDInstall.exe was missing some buffer length checks. [RT #45898] 4698. [port] Add --with-python-install-dir configure option to allow specifying a nonstandard installation directory for Python modules. [RT #45407] 4697. [bug] Restore workaround for Microsoft Windows TSIG hash computation bug. [RT #45854] 4696. [port] Enable filter-aaaa support by default on Windows builds. [RT #45883] 4695. [bug] cookie-secrets were not being properly checked by named-checkconf. [RT #45886] 4692. [bug] Fix build failures with libressl introduced in 4676. [RT #45879] 4690. [bug] Command line options -4/-6 were handled inconsistently between tools. [RT #45632] 4689. [cleanup] Turn on minimal responses for CDNSKEY and CDS in addition to DNSKEY and DS. Thanks to Tony Finch. [RT #45690] 4688. [protocol] Check and display EDNS KEY TAG options (RFC 8145) in messages. [RT #44804] 4686. [bug] dnssec-settime -p could print a bogus warning about key deletion scheduled before its inactivation when a key had an inactivation date set but no deletion date set. [RT #45807] 4685. [bug] dnssec-settime incorrectly calculated publication and activation dates for a successor key. [RT #45806] 4684. [bug] delv could send bogus DNS queries when an explicit server address was specified on the command line along with -4/-6. [RT #45804] 4683. [bug] Prevent nsupdate from immediately exiting on invalid user input in interactive mode. [RT #28194] 4682. [bug] Don't report errors on records below a DNAME. [RT #44880] 4680. [bug] Fix failing over to another master server address when nsupdate is used with GSS-API. [RT #45380] 4679. [cleanup] Suggest using -o when dnssec-verify finds a SOA record not at top of zone and -o is not used. [RT #45519] 4678. [bug] geoip-use-ecs has the wrong type when geoip support is disabled at configure time. [RT #45763] 4677. [cleanup] Split up the main function in dig to better support the iOS app version. [RT #45508] 4676. [cleanup] Allow BIND to be built using OpenSSL 1.0.X with deprecated functions removed. [RT #45706] 4675. [cleanup] Don't use C++ keyword class. [RT #45726] 4673. [port] Silence GCC 7 warnings. [RT #45592] 4671. [bug] Fix a race condition that could cause the resolver to crash with assertion failure when chasing DS in specific conditions with a very short RTT to the upstream nameserver. [RT #45168] 4670. [cleanup] Ensure that a request MAC is never sent back in an XFR response unless the signature was verified. [RT #45494] 4668. [bug] Use localtime_r and gmtime_r for thread safety. [RT #45664] 4667. [cleanup] Refactor RDATA unit tests. [RT #45610] 4666. [bug] dnssec-keymgr: Domain names beginning with digits (0-9) could cause a parser error when reading the policy file. This now works correctly so long as the domain name is quoted. [RT #45641] 4665. [protocol] Added support for ED25519 and ED448 DNSSEC signing algorithms (RFC 8080). (Note: these algorithms depend on code currently in the development branch of OpenSSL which has not yet been released.) [RT #44696] 4663. [cleanup] Clarify error message printed by dnssec-dsfromkey. [RT #21731] 4662. [performance] Improve cache memory cleanup of zero TTL records by putting them at the tail of LRU header lists. [RT #45274] 4661. [bug] A race condition could occur if a zone was reloaded while resigning, triggering a crash in rbtdb.c:closeversion(). [RT #45276] 4660. [bug] Remove spurious "peer" from Windows socket log messages. [RT #45617] 4659. [bug] Remove spurious log message about lmdb-mapsize not being supported when parsing builtin configuration file. [RT #45618] 4658. [bug] Clean up build directory created by "setup.py install" immediately. [RT #45628] 4657. [bug] rrchecker system test result could be improperly determined. [RT #45602] 4656. [bug] Apply "port" and "dscp" values specified in catalog zone's "default-masters" option to the generated configuration of its member zones. [RT #45545] 4655. [bug] Lack of seccomp could be falsely reported. [RT #45599] 4654. [cleanup] Don't use C++ keywords delete, new and namespace. [RT #45538] 4652. [bug] Nsupdate could attempt to use a zeroed address on server timeout. [RT #45417] 4651. [test] Silence coverity warnings in tsig_test.c. [RT #45528] 4605. [performance] (partial backport) Improve general query performance. Improves performance of owner case restoration, hash function, etc. Uses inline buffer implementation by default. [RT #45637] --- 9.11.2 released --- --- 9.11.2rc2 released --- 4653. [bug] Reorder includes to move @DST_OPENSSL_INC@ and @ISC_OPENSSL_INC@ after shipped include directories. [RT #45581] --- 9.11.2rc1 released --- 4649. [bug] The wrong zone was logged when a catalog zone is added. [RT #45520] 4648. [bug] "rndc reconfig" on a slave no longer causes all member zones of configured catalog zones to be removed from configuration. [RT #45310] 4647. [bug] Change 4643 broke verification of TSIG signed TCP message sequences where not all the messages contain TSIG records. These may be used in AXFR and IXFR responses. [RT #45509] 4645. [bug] Fix PKCS#11 RSA parsing when MD5 is disabled. [RT #45300] --- 9.11.2b1 released --- 4643. [security] An error in TSIG handling could permit unauthorized zone transfers or zone updates. (CVE-2017-3142) (CVE-2017-3143) [RT #45383] 4642. [cleanup] Add more logging of RFC 5011 events affecting the status of managed keys: newly observed keys, deletion of revoked keys, etc. [RT #45354] 4641. [cleanup] Parallel builds (make -j) could fail with --with-atf / --enable-developer. [RT #45373] 4640. [bug] If query_findversion failed in query_getdb due to memory failure the error status was incorrectly discarded. [RT #45331] 4639. [bug] Fix a regression in --with-tuning reporting introduced by change 4488. [RT #45396] 4638. [bug] Reloading or reconfiguring named could fail on some platforms when LMDB was in use. [RT #45203] 4636. [bug] Normalize rpz policy zone names when checking for existence. [RT #45358] 4635. [bug] Fix RPZ NSDNAME logging that was logging failures as NSIP. [RT #45052] 4634. [contrib] check5011.pl needs to handle optional space before semi-colon in +multi-line output. [RT #45352] 4633. [maint] Updated AAAA (2001:500:200::b) for B.ROOT-SERVERS.NET. 4632. [security] The BIND installer on Windows used an unquoted service path, which can enable privilege escalation. (CVE-2017-3141) [RT #45229] 4631. [security] Some RPZ configurations could go into an infinite query loop when encountering responses with TTL=0. (CVE-2017-3140) [RT #45181] 4630. [bug] "dyndb" is dependent on dlopen existing / being enabled. [RT #45291] 4629. [bug] dns_client_startupdate could not be called with a running client. [RT #45277] 4628. [bug] Fixed a potential reference leak in query_getdb(). [RT #45247] 4626. [test] Added more tests for handling of different record ordering in CNAME and DNAME responses. [QA #430] 4625. [bug] Running "rndc addzone" and "rndc delzone" at close to the same time could trigger a deadlock if using LMDB. [RT #45209] 4623. [bug] Use --with-protobuf-c and --with-libfstrm to find protoc-c and fstrm_capture. [RT #45187] 4622. [bug] Remove unnecessary escaping of semicolon in CAA and URI records. [RT #45216] 4621. [port] Force alignment of oid arrays to silence loader warnings. [RT #45131] 4620. [port] Handle EPFNOSUPPORT being returned when probing to see if a socket type is supported. [RT #45214] 4619. [bug] Call isc_mem_put instead of isc_mem_free in bin/named/server.c:setup_newzones. [RT #45202] 4618. [bug] Check isc_mem_strdup results in dns_view_setnewzones. Add logging for lmdb call failures. [RT #45204] 4617. [test] Update rndc system test to be more delay tolerant. [RT #45177] 4616. [bug] When using LMDB, zones deleted using "rndc delzone" were not correctly removed from the new-zone database. [RT #45185] 4615. [bug] AD could be set on truncated answer with no records present in the answer and authority sections. [RT #45140] 4614. [test] Fixed an error in the sockaddr unit test. [RT #45146] 4612. [bug] Silence 'may be use uninitalised' warning and simplify the code in lwres/getaddinfo:process_answer. [RT #45158] 4611. [bug] The default LMDB mapsize was too low and caused errors after few thousand zones were added using rndc addzone. A new config option "lmdb-mapsize" has been introduced to configure the LMDB mapsize depending on operational needs. [RT #44954] 4609. [cleanup] Rearrange makefiles to enable parallel execution (i.e. "make -j"). [RT #45078] 4608. [func] DiG now warns about .local queries which are reserved for Multicast DNS. [RT #44783] 4606. [port] Stop using experimental "Experimental keys on scalar" feature of perl as it has been removed. [RT #45012] 4604. [bug] Don't use ERR_load_crypto_strings() when building with OpenSSL 1.1.0. [RT #45117] 4603. [doc] Automatically generate named.conf(5) man page from doc/misc/options. Thanks to Tony Finch. [RT #43525] 4602. [func] Threads are now set to human-readable names to assist debugging, when supported by the OS. [RT #43234] 4601. [bug] Reject incorrect RSA key lengths during key generation and and sign/verify context creation. [RT #45043] 4600. [bug] Adjust RPZ trigger counts only when the entry being deleted exists. [RT #43386] 4599. [bug] Fix inconsistencies in inline signing time comparison that were introduced with the introduction of rdatasetheader->resign_lsb. [RT #42112] 4597. [bug] The validator now ignores SHA-1 DS digest type when a DS record with SHA-384 digest type is present and is a supported digest type. [RT #45017] 4596. [bug] Validate glue before adding it to the additional section. This also fixes incorrect TTL capping when the RRSIG expired earlier than the TTL. [RT #45062] 4593. [doc] Update README using markdown, remove outdated FAQ file in favor of the knowledge base. 4592. [bug] A race condition on shutdown could trigger an assertion failure in dispatch.c. [RT #43822] 4591. [port] Addressed some python 3 compatibility issues. Thanks to Ville Skytta. [RT #44955] [RT #44956] 4590. [bug] Support for PTHREAD_MUTEX_ADAPTIVE_NP was not being properly detected. [RT #44871] 4589. [cleanup] "configure -q" is now silent. [RT #44829] 4588. [bug] nsupdate could send queries for TKEY to the wrong server when using GSSAPI. Thanks to Tomas Hozza. [RT #39893] 4587. [bug] named-checkzone failed to handle occulted data below DNAMEs correctly. [RT #44877] 4586. [func] dig, host and nslookup now use TCP for ANY queries. [RT #44687] 4585. [port] win32: Set CompileAS value. [RT #42474] 4584. [bug] A number of memory usage statistics were not properly reported when they exceeded 4G. [RT #44750] 4574. [bug] Dig leaked memory with multiple +subnet options. [RT #44683] 4555. [func] dig +ednsopt: EDNS options can now be specified by name in addition to numeric value. [RT #44461] --- 9.11.1 released --- --- 9.11.1rc3 released --- 4582. [security] 'rndc ""' could trigger a assertion failure in named. (CVE-2017-3138) [RT #44924] 4581. [port] Linux: Add getpid and getrandom to the list of system calls named uses for seccomp. [RT #44883] 4580. [bug] 4578 introduced a regression when handling CNAME to referral below the current domain. [RT #44850] --- 9.11.1rc2 released --- 4578. [security] Some chaining (CNAME or DNAME) responses to upstream queries could trigger assertion failures. (CVE-2017-3137) [RT #44734] 4575. [security] DNS64 with "break-dnssec yes;" can result in an assertion failure. (CVE-2017-3136) [RT #44653] --- 9.11.1rc1 released --- 4571. [bug] Out-of-tree builds of backtrace_test failed. 4570. [cleanup] named did not correctly fall back to the built-in initializing keys if the bind.keys file was present but empty. [RT #44531] 4569. [func] Store both local and remote addresses in dnstap logging, and modify dnstap-read output format to print them. [RT #43595] 4568. [contrib] Added a --with-bind option to the dnsperf configure script to specify BIND prefix path. 4567. [port] Call getprotobyname and getservbyname prior to calling chroot so that shared libraries get loaded. [RT #44537] 4565. [cleanup] The inline macro versions of isc_buffer_put*() did not implement automatic buffer reallocation. [RT #44216] 4564. [maint] Update the built in managed keys to include the upcoming root KSK. [RT #44579] 4563. [bug] Modified zones would occasionally fail to reload. [RT #39424] 4561. [port] Silence a warning in strict C99 compilers. [RT #44414] 4560. [bug] mdig: add -m option to enable memory debugging rather than having it on all the time. [RT #44509] 4559. [bug] openssl_link.c didn't compile if ISC_MEM_TRACKLINES was turned off. [RT #44509] 4558. [bug] Synthesised CNAME before matching DNAME was still being cached when it should not have been. [RT #44318] 4557. [security] Combining dns64 and rpz can result in dereferencing a NULL pointer (read). (CVE-2017-3135) [RT#44434] 4554. [bug] Remove double unlock in dns_dispatchmgr_setudp. [RT #44336] 4553. [bug] Named could deadlock there were multiple changes to NSEC/NSEC3 parameters for a zone being processed at the same time. [RT #42770] 4552. [bug] Named could trigger a assertion when sending notify messages. [RT #44019] 4551. [test] Add system tests for integrity checks of MX and SRV records. [RT #43953] 4550. [cleanup] Increased the number of available master file output style flags from 32 to 64. [RT #44043] 4547. [port] Add support for --enable-native-pkcs11 on the AEP Keyper HSM. [RT #42463] --- 9.11.1b1 released --- 4545. [func] Expand YAML output from dnstap-read to include a detailed breakdown of the DNS message contents. [RT #43642] 4544. [bug] Add message/payload size to dnstap-read YAML output. [RT #43622] 4543. [bug] dns_client_startupdate now delays sending the update request until isc_app_ctxrun has been called. [RT #43976] 4541. [bug] rndc addzone should properly reject non master/slave zones. [RT #43665] 4540. [bug] Correctly handle ecs entries in dns_acl_isinsecure. [RT #43601] 4539. [bug] Referencing a nonexistent zone with RPZ could lead to a assertion failure when configuring. [RT #43787] 4538. [bug] Call dns_client_startresolve from client->task. [RT #43896] 4537. [bug] Handle timeouts better in dig/host/nslookup. [RT #43576] 4536. [bug] ISC_SOCKEVENTATTR_USEMINMTU was not being cleared when reusing the event structure. [RT #43885] 4535. [bug] Address race condition in setting / testing of DNS_REQUEST_F_SENDING. [RT #43889] 4534. [bug] Only set RD, RA and CD in QUERY responses. [RT #43879] 4533. [bug] dns_client_update should terminate on prerequisite failures (NXDOMAIN, YXDOMAIN, NXRRSET, YXRRSET) and also on BADZONE. [RT #43865] 4532. [contrib] Make gen-data-queryperf.py python 3 compatible. [RT #43836] 4531. [security] 'is_zone' was not being properly updated by redirect2 and subsequently preserved leading to an assertion failure. (CVE-2016-9778) [RT #43837] 4530. [bug] Change 4489 broke the handling of CNAME -> DNAME in responses resulting in SERVFAIL being returned. [RT #43779] 4529. [cleanup] Silence noisy log warning when DSCP probe fails due to firewall rules. [RT #43847] 4528. [bug] Only set the flag bits for the i/o we are waiting for on EPOLLERR or EPOLLHUP. [RT #43617] 4527. [doc] Support DocBook XSL Stylesheets v1.79.1. [RT #43831] 4526. [doc] Corrected errors and improved formatting of grammar definitions in the ARM. [RT #43739] 4525. [doc] Fixed outdated documentation on managed-keys. [RT #43810] 4524. [bug] The net zero test was broken causing IPv4 servers with addresses ending in .0 to be rejected. [RT #43776] 4523. [doc] Expand config doc for and . [RT #43768] 4522. [bug] Handle big gaps in log file version numbers better. [RT #38688] 4521. [cleanup] Log it as an error if an entropy source is not found and there is no fallback available. [RT #43659] 4520. [cleanup] Alphabetize more of the grammar when printing it out. Fix unbalanced indenting. [RT #43755] 4519. [port] win32: handle ERROR_MORE_DATA. [RT #43534] 4517. [security] Named could mishandle authority sections that were missing RRSIGs triggering an assertion failure. (CVE-2016-9444) [RT # 43632] 4516. [bug] isc_socketmgr_renderjson was missing from the windows build. [RT #43602] 4515. [port] FreeBSD: Find readline headers when they are in edit/readline/ instead of readline/. [RT #43658] 4514. [port] NetBSD: strip -WL, from ld command line. [RT #43204] 4513. [cleanup] Minimum Python versions are now 2.7 and 3.2. [RT #43566] 4512. [bug] win32: @GEOIP_INC@ missing from delv.vcxproj.in. [RT #43556] 4511. [bug] win32: mdig.exe-BNFT was missing Configure. [RT #43554] 4510. [security] Named mishandled some responses where covering RRSIG records are returned without the requested data resulting in a assertion failure. (CVE-2016-9147) [RT #43548] 4509. [test] Make the rrl system test more reliable on slower machines by using mdig instead of dig. [RT #43280] 4508. [security] Named incorrectly tried to cache TKEY records which could trigger a assertion failure when there was a class mismatch. (CVE-2016-9131) [RT #43522] 4507. [bug] Named could incorrectly log 'allows updates by IP address, which is insecure' [RT #43432] 4505. [port] Use IP_PMTUDISC_OMIT if available. [RT #35494] 4504. [security] Allow the maximum number of records in a zone to be specified. This provides a control for issues raised in CVE-2016-6170. [RT #42143] 4503. [cleanup] "make uninstall" now removes files installed by BIND. (This currently excludes Python files due to lack of support in setup.py.) [RT #42192] 4502. [func] Report multiple and experimental options when printing grammar. [RT #43134] 4500. [bug] Support modifier I64 in isc__print_printf. [RT #43526] 4499. [port] MacOSX: silence deprecated function warning by using arc4random_stir() when available instead of arc4random_addrandom(). [RT #43503] 4498. [test] Simplify prerequisite checks in system tests. [RT #43516] 4497. [port] Add support for OpenSSL 1.1.0. [RT #41284] 4496. [func] dig: add +idnout to control whether labels are display in punycode or not. Requires idn support to be enabled at compile time. [RT #43398] 4495. [bug] A isc_mutex_init call was not being checked. [RT #43391] 4494. [bug] Look for . [RT #43429] 4493. [bug] bin/tests/system/dyndb/driver/Makefile.in should use SO_TARGETS. [RT# 43336] 4492. [bug] irs_resconf_load failed to initialize sortlistnxt causing bad writes if resolv.conf contained a sortlist directive. [RT #43459] 4491. [bug] Improve message emitted when testing whether sendmsg works with TOS/TCLASS fails. [RT #43483] 4490. [maint] Added AAAA (2001:500:12::d0d) for G.ROOT-SERVERS.NET. 4489. [security] It was possible to trigger assertions when processing a response containing a DNAME answer. (CVE-2016-8864) [RT #43465] 4488. [port] Darwin: use -framework for Kerberos. [RT #43418] 4487. [test] Make system tests work on Windows. [RT #42931] 4486. [bug] Look in $prefix/lib/pythonX.Y/site-packages for the python modules we install. [RT #43330] 4485. [bug] Failure to find readline when requested should be fatal to configure. [RT #43328] 4484. [func] Check prefixes in acls to make sure the address and prefix lengths are consistent. Warn only in BIND 9.11 and earlier. [RT #43367] 4483. [bug] Address use before require check and remove extraneous dns_message_gettsigkey call in dns_tsig_sign. [RT #43374] 4482. [cleanup] Change #4455 was incomplete. [RT #43252] 4478. [func] Add +continue option to mdig, allow continue on socket errors. [RT #43281] 4477. [test] Fix mkeys test timing issues. [RT #41028] 4476. [test] Fix reclimit test on slower machines. [RT #43283] 4475. [doc] Update named-checkconf documentation. [RT #43153] 4474. [bug] win32: call WSAStartup in fromtext_in_wks so that getprotobyname and getservbyname work. [RT #43197] 4473. [bug] Only call fsync / _commit on regular files. [RT #43196] 4472. [bug] Named could fail to find the correct NSEC3 records when a zone was updated between looking for the answer and looking for the NSEC3 records proving nonexistence of the answer. [RT #43247] --- 9.11.0 released --- --- 9.11.0rc3 released --- 4471. [cleanup] Render client/query logging format consistent for ease of log file parsing. (Note that this affects "querylog" format: there is now an additional field indicating the client object address.) [RT #43238] 4470. [bug] Reset message with intent parse before calling dns_dispatch_getnext. [RT #43229] --- 9.11.0rc2 released --- 4468. [bug] Address ECS option handling issues. [RT #43191] 4467. [security] It was possible to trigger an assertion when rendering a message. (CVE-2016-2776) [RT #43139] 4466. [bug] Interface scanning didn't work on a Windows system without a non local IPv6 addresses. [RT #43130] 4465. [bug] Don't use "%z" as Windows doesn't support it. [RT #43131] 4464. [bug] Fix windows python support. [RT #43173] 4463. [bug] The dnstap system test failed on some systems. [RT #43129] 4462. [bug] Don't describe a returned EDNS COOKIE as "good" when there isn't a valid server cookie. [RT #43167] 4461. [bug] win32: not all external data was properly marked as external data for windows dll. [RT #43161] --- 9.11.0rc1 released --- 4460. [test] Add system test for dnstap using unix domain sockets. [RT #42926] 4459. [bug] TCP client objects created to handle pipeline queries were not cleaned up correctly, causing uncontrolled memory growth. [RT #43106] 4458. [cleanup] Update assertions to be more correct, and also remove use of a reserved word. [RT #43090] 4457. [maint] Added AAAA (2001:500:a8::e) for E.ROOT-SERVERS.NET. 4456. [doc] Add DOCTYPE and lang attribute to tags. [RT #42587] 4455. [cleanup] Allow dyndb modules to correctly log the filename and line number when processing configuration text from named.conf. [RT #43050] 4454. [bug] 'rndc dnstap -reopen' had a race issue. [RT #43089] 4453. [bug] Prefetching of DS records failed to update their RRSIGs. [RT #42865] 4452. [bug] The default key manager policy file is now /dnssec-policy.conf (usually /etc/dnssec-policy.conf). [RT #43064] 4451. [cleanup] Log more useful information if a PKCS#11 provider library cannot be loaded. [RT #43076] 4450. [port] Provide more nuanced HSM support which better matches the specific PKCS11 providers capabilities. [RT #42458] 4449. [test] Fix catalog zones test on slower systems. [RT #42997] 4448. [bug] win32: ::1 was not being found when iterating interfaces. [RT #42993] 4447. [tuning] Allow the fstrm_iothr_init() options to be set using named.conf to control how dnstap manages the data flow. [RT #42974] 4446. [bug] The cache_find() and _findrdataset() functions could find rdatasets that had been marked stale. [RT #42853] 4445. [cleanup] isc_errno_toresult() can now be used to call the formerly private function isc__errno2result(). [RT #43050] 4444. [bug] Fixed some issues related to dyndb: A bug caused braces to be omitted when passing configuration text from named.conf to a dyndb driver, and there was a use-after-free in the sample dyndb driver. [RT #43050] 4443. [func] Set TCP_MAXSEG in addition to IPV6_USE_MIN_MTU on TCP sockets. [RT #42864] 4442. [bug] Fix RPZ CIDR tree insertion bug that corrupted tree data structure with overlapping networks (longest prefix match was ineffective). [RT #43035] 4441. [cleanup] Alphabetize host's help output. [RT #43031] 4440. [func] Enable TCP fast open support when available on the server side. [RT #42866] 4439. [bug] Address race conditions getting ownernames of nodes. [RT #43005] 4438. [func] Use LIFO rather than FIFO when processing startup notify and refresh queries. [RT #42825] 4437. [func] Minimal-responses now has two additional modes no-auth and no-auth-recursive which suppress adding the NS records to the authority section as well as the associated address records for the nameservers. [RT #42005] 4436. [func] Return TLSA records as additional data for MX and SRV lookups. [RT #42894] 4435. [tuning] Only set IPV6_USE_MIN_MTU for UDP when the message will not fit into a single IPv4 encapsulated IPv6 UDP packet when transmitted over a Ethernet link. [RT #42871] 4434. [protocol] Return EDNS EXPIRE option for master zones in addition to slave zones. [RT #43008] 4433. [cleanup] Report an error when passing an invalid option or view name to "rndc dumpdb". [RT #42958] 4432. [test] Hide rndc output on expected failures in logfileconfig system test. [RT #27996] 4431. [bug] named-checkconf now checks the rate-limit clause. [RT #42970] 4430. [bug] Lwresd died if a search list was not defined. Found by 0x710DDDD At Alibaba Security. [RT #42895] 4429. [bug] Address potential use after free on fclose() error. [RT #42976] 4428. [bug] The "test dispatch getnext" unit test could fail in a threaded build. [RT #42979] 4427. [bug] The "query" and "response" parameters to the "dnstap" option had their functions reversed. --- 9.11.0b3 released --- 4426. [bug] Addressed Coverity warnings. [RT #42908] 4425. [bug] arpaname, dnstap-read and named-rrchecker were not being installed into ${prefix}/bin. Tidy up installation issues with CHANGE 4421. [RT #42910] 4424. [experimental] Named now sends _ta-XXXX./NULL queries to provide feedback to the trust-anchor administrators about how key rollovers are progressing as per draft-ietf-dnsop-edns-key-tag-02. This can be disabled using 'trust-anchor-telemetry no;'. [RT #40583] 4423. [maint] Added missing IPv6 address 2001:500:84::b for B.ROOT-SERVERS.NET. [RT #42898] 4422. [port] Silence clang warnings in dig.c and dighost.c. [RT #42451] 4421. [func] When built with LMDB (Lightning Memory-mapped Database), named will now use a database to store the configuration for zones added by "rndc addzone" instead of using a flat NZF file. This improves performance of "rndc delzone" and "rndc modzone" significantly. Existing NZF files will automatically by converted to NZD databases. To view the contents of an NZD or to roll back to NZF format, use "named-nzd2nzf". To disable this feature, use "configure --without-lmdb". [RT #39837] 4420. [func] nslookup now looks for AAAA as well as A by default. [RT #40420] 4419. [bug] Don't cause undefined result if the label of an entry in catalog zone is changed. [RT #42708] 4418. [bug] Fix a compiler warning in GSSAPI code. [RT #42879] 4417. [bug] dnssec-keymgr could fail to create successor keys if the prepublication interval was set to a value smaller than the default. [RT #42820] 4416. [bug] dnssec-keymgr: Domain names in policy files could fail to match due to trailing dots. [RT #42807] 4415. [bug] dnssec-keymgr: Expired/deleted keys were not always excluded. [RT #42884] 4414. [bug] Corrected a bug in the MIPS implementation of isc_atomic_xadd(). [RT #41965] 4413. [bug] GSSAPI negotiation could fail if GSS_S_CONTINUE_NEEDED was returned. [RT #42733] --- 9.11.0b2 released --- 4412. [cleanup] Make fixes for GCC 6. ISC_OFFSET_MAXIMUM macro was removed. [RT #42721] 4411. [func] "rndc dnstap -roll" automatically rolls the dnstap output file; the previous version is saved with ".0" suffix, and earlier versions with ".1" and so on. An optional numeric argument indicates how many prior files to save. [RT #42830] 4410. [bug] Address use after free and memory leak with dnstap. [RT #42746] 4409. [bug] DNS64 should exclude mapped addresses by default when an exclude acl is not defined. [RT #42810] 4408. [func] Continue waiting for expected response when we the response we get does not match the request. [RT #41026] 4407. [performance] Use GCC builtin for clz in RPZ lookup code. [RT #42818] 4406. [security] getrrsetbyname with a non absolute name could trigger an infinite recursion bug in lwresd and named with lwres configured if when combined with a search list entry the resulting name is too long. (CVE-2016-2775) [RT #42694] 4405. [bug] Change 4342 introduced a regression where you could not remove a delegation in a NSEC3 signed zone using OPTOUT via nsupdate. [RT #42702] 4404. [misc] Allow krb5-config to be used when configuring gssapi. [RT #42580] 4403. [bug] Rename variables and arguments that shadow: basename, clone and gai_error. 4402. [bug] protoc-c is now a hard requirement for --enable-dnstap. --- 9.11.0b1 released --- 4401. [misc] Change LICENSE to MPL 2.0. 4400. [bug] ttl policy was not being inherited in policy.py. [RT #42718] 4399. [bug] policy.py 'ECCGOST', 'ECDSAP256SHA256', and 'ECDSAP384SHA384' don't have settable keysize. [RT #42718] 4398. [bug] Correct spelling of ECDSAP256SHA256 in policy.py. [RT #42718] 4397. [bug] Update Windows python support. [RT #42538] 4396. [func] dnssec-keymgr now takes a '-r randomfile' option. [RT #42455] 4395. [bug] Improve out-of-tree installation of python modules. [RT #42586] 4394. [func] Add rndc command "dnstap-reopen" to close and reopen dnstap output files. [RT #41803] 4393. [bug] Address potential NULL pointer dereferences in dnstap code. 4392. [func] Collect statistics for RSSAC02v3 traffic-volume, traffic-sizes and rcode-volume reporting. [RT #41475] 4391. [contrib] Fix leaks in contrib DLZ code. [RT #42707] 4390. [doc] Description of masters with TSIG, allow-query and allow-transfer options in catalog zones. [RT #42692] 4389. [test] Rewritten test suite for catalog zones. [RT #42676] 4388. [func] Support for master entries with TSIG keys in catalog zones. [RT #42577] 4387. [bug] Change 4336 was not complete leading to SERVFAIL being return as NS records expired. [RT #42683] 4386. [bug] Remove shadowed overmem function/variable. [RT #42706] 4385. [func] Add support for allow-query and allow-transfer ACLs to catalog zones. [RT #42578] 4384. [bug] Change 4256 accidentally disabled logging of the rndc command. [RT #42654] 4383. [bug] Correct spelling error in stats channel description of "EDNS client subnet option received". [RT #42633] 4382. [bug] rndc {addzone,modzone,delzone,showzone} should all compare the zone name using a canonical format. [RT #42630] 4381. [bug] Missing "zone-directory" option in catalog zone definition caused BIND to crash. [RT #42579] --- 9.11.0a3 released --- 4380. [experimental] Added a "zone-directory" option to "catalog-zones" syntax, allowing local masterfiles for slaves that are provisioned by catalog zones to be stored in a directory other than the server's working directory. [RT #42527] 4379. [bug] An INSIST could be triggered if a zone contains RRSIG records with expiry fields that loop using serial number arithmetic. [RT #40571] 4378. [contrib] #include for strlcat in zone2ldap.c. [RT #42525] 4377. [bug] Don't reuse zero TTL responses beyond the current client set (excludes ANY/SIG/RRSIG queries). [RT #42142] 4376. [experimental] Added support for Catalog Zones, a new method for provisioning secondary servers in which a list of zones to be served is stored in a DNS zone and can be propagated to slaves via AXFR/IXFR. [RT #41581] 4375. [func] Add support for automatic reallocation of isc_buffer to isc_buffer_put* functions. [RT #42394] 4374. [bug] Use SAVE/RESTORE macros in query.c to reduce the probability of reference counting errors as seen in 4365. [RT #42405] 4373. [bug] Address undefined behavior in getaddrinfo. [RT #42479] 4372. [bug] Address undefined behavior in libt_api. [RT #42480] 4371. [func] New "minimal-any" option reduces the size of UDP responses for qtype ANY by returning a single arbitrarily selected RRset instead of all RRsets. Thanks to Tony Finch. [RT #41615] 4370. [bug] Address python3 compatibility issues with RNDC module. [RT #42499] [RT #42506] --- 9.11.0a2 released --- 4369. [bug] Fix 'make' and 'make install' out-of-tree python support. [RT #42484] 4368. [bug] Fix a crash when calling "rndc stats" on some Windows builds because some Visual Studio compilers generated crashing code for the "%z" printf() format specifier. [RT #42380] 4367. [bug] Remove unnecessary assignment of loadtime in zone_touched. [RT #42440] 4366. [bug] Address race condition when updating rbtnode bit fields. [RT #42379] 4365. [bug] Address zone reference counting errors involving nxdomain-redirect. [RT #42258] 4364. [port] freebsd: add -Wl,-E to loader flags [RT #41690] 4363. [port] win32: Disable explicit triggering UAC when running BINDInstall. 4362. [func] Changed rndc reconfig behavior so that newly added zones are loaded asynchronously and the loading does not block the server. [RT #41934] 4361. [cleanup] Where supported, file modification times returned by isc_file_getmodtime() are now accurate to the nanosecond. [RT #41968] 4360. [bug] Silence spurious 'bad key type' message when there is a existing TSIG key. [RT #42195] 4359. [bug] Inherited 'also-notify' lists were not being checked by named-checkconf. [RT #42174] 4358. [test] Added American Fuzzy Lop harness that allows feeding fuzzed packets into BIND. [RT #41723] 4357. [func] Add the python RNDC module. [RT #42093] 4356. [func] Add the ability to specify whether to wait for nameserver addresses to be looked up or not to RPZ with a new modifying directive 'nsip-wait-recurse'. [RT #35009] 4355. [func] "pkcs11-list" now displays the extractability attribute of private or secret keys stored in an HSM, as either "true", "false", or "never" Thanks to Daniel Stirnimann. [RT #36557] 4354. [bug] Check that the received HMAC length matches the expected length prior to check the contents on the control channel. This prevents a OOB read error. This was reported by Lian Yihan, . [RT #42215] 4353. [cleanup] Update PKCS#11 header files. [RT #42175] 4352. [cleanup] The ISC DNSSEC Lookaside Validation (DLV) service is scheduled to be disabled in 2017. A warning is now logged when named is configured to use it, either explicitly or via "dnssec-lookaside auto;" [RT #42207] 4351. [bug] 'dig +noignore' didn't work. [RT #42273] 4350. [contrib] Declare result in dlz_filesystem_dynamic.c. 4349. [contrib] kasp2policy: A python script to create a DNSSEC policy file from an OpenDNSSEC KASP XML file. 4348. [func] dnssec-keymgr: A new python-based DNSSEC key management utility, which reads a policy definition file and can create or update DNSSEC keys as needed to ensure that a zone's keys match policy, roll over correctly on schedule, etc. Thanks to Sebastian Castro for assistance in development. [RT #39211] 4347. [port] Corrected a build error on x86_64 Solaris. [RT #42150] 4346. [bug] Fixed a regression introduced in change #4337 which caused signed domains with revoked KSKs to fail validation. [RT #42147] 4345. [contrib] perftcpdns mishandled the return values from clock_nanosleep. [RT #42131] 4344. [port] Address openssl version differences. [RT #42059] 4343. [bug] dns_dnssec_syncupdate mis-declared in . [RT #42090] 4342. [bug] 'rndc flushtree' could fail to clean the tree if there wasn't a node at the specified name. [RT #41846] --- 9.11.0a1 released --- 4341. [bug] Correct the handling of ECS options with address family 0. [RT #41377] 4340. [performance] Implement adaptive read-write locks, reducing the overhead of locks that are only held briefly. [RT #37329] 4339. [test] Use "mdig" to test pipelined queries. [RT #41929] 4338. [bug] Reimplement change 4324 as it wasn't properly doing all the required book keeping. [RT #41941] 4337. [bug] The previous change exposed a latent flaw in key refresh queries for managed-keys when a cached DNSKEY had TTL 0. [RT #41986] 4336. [bug] Don't emit records with zero ttl unless the records were learnt with a zero ttl. [RT #41687] 4335. [bug] zone->view could be detached too early. [RT #41942] 4334. [func] 'named -V' now reports zlib version. [RT #41913] 4333. [maint] L.ROOT-SERVERS.NET is now 199.7.83.42 and 2001:500:9f::42. 4332. [placeholder] 4331. [func] When loading managed signed zones detect if the RRSIG's inception time is in the future and regenerate the RRSIG immediately. [RT #41808] 4330. [protocol] Identify the PAD option as "PAD" when printing out a message. 4329. [func] Warn about a common misconfiguration when forwarding RFC 1918 zones. [RT #41441] 4328. [performance] Add dns_name_fromwire() benchmark test. [RT #41694] 4327. [func] Log query and depth counters during fetches when querytrace (./configure --enable-querytrace) is enabled (helps in diagnosing). [RT #41787] 4326. [protocol] Add support for AVC. [RT #41819] 4325. [func] Add a line to "rndc status" indicating the hostname and operating system details. [RT #41610] 4324. [bug] When deleting records from a zone database, interior nodes could be left empty but not deleted, damaging search performance afterward. [RT #40997] 4323. [bug] Improve HTTP header processing on statschannel. [RT #41674] 4322. [security] Duplicate EDNS COOKIE options in a response could trigger an assertion failure. (CVE-2016-2088) [RT #41809] 4321. [bug] Zones using mapped files containing out-of-zone data could return SERVFAIL instead of the expected NODATA or NXDOMAIN results. [RT #41596] 4320. [bug] Insufficient memory allocation when handling "none" ACL could cause an assertion failure in named when parsing ACL configuration. [RT #41745] 4319. [security] Fix resolver assertion failure due to improper DNAME handling when parsing fetch reply messages. (CVE-2016-1286) [RT #41753] 4318. [security] Malformed control messages can trigger assertions in named and rndc. (CVE-2016-1285) [RT #41666] 4317. [bug] Age all unused servers on fetch timeout. [RT #41597] 4316. [func] Add option to tools to print RRs in unknown presentation format [RT #41595]. 4315. [bug] Check that configured view class isn't a meta class. [RT #41572]. 4314. [contrib] Added 'dnsperf-2.1.0.0-1', a set of performance testing tools provided by Nominum, Inc. 4313. [bug] Handle ns_client_replace failures in test mode. [RT #41190] 4312. [bug] dig's unknown DNS and EDNS flags (MBZ value) logging was not consistent. [RT #41600] 4311. [bug] Prevent "rndc delzone" from being used on response-policy zones. [RT #41593] 4310. [performance] Use __builtin_expect() where available to annotate conditions with known behavior. [RT #41411] 4309. [cleanup] Remove the spurious "none" filename from log messages when processing built-in configuration. [RT #41594] 4308. [func] Added operating system details to "named -V" output. [RT #41452] 4307. [bug] "dig +subnet" and "mdig +subnet" could send incorrectly-formatted Client Subnet options if the prefix length was not divisible by 8. Also fixed a memory leak in "mdig". [RT #45178] 4306. [maint] Added a PKCS#11 openssl patch supporting version 1.0.2f [RT #38312] 4305. [bug] dnssec-signzone was not removing unnecessary rrsigs from the zone's apex. [RT #41483] 4304. [port] xfer system test failed as 'tail -n +value' is not portable. [RT #41315] 4303. [bug] "dig +subnet" was unable to send a prefix length of zero, as it was incorrectly changed to 32 for v4 prefixes or 128 for v6 prefixes. In addition to fixing this, "dig +subnet=0" has been added as a short form for 0.0.0.0/0. The same changes have also been made in "mdig". [RT #41553] 4302. [port] win32: fixed a build error in VS 2015. [RT #41426] 4301. [bug] dnssec-settime -p [DP]sync was not working. [RT #41534] 4300. [bug] A flag could be set in the wrong field when setting up non-recursive queries; this could cause the SERVFAIL cache to cache responses it shouldn't. New querytrace logging has been added which identified this error. [RT #41155] 4299. [bug] Check that exactly totallen bytes are read when reading a RRset from raw files in both single read and incremental modes. [RT #41402] 4298. [bug] dns_rpz_add errors in loadzone were not being propagated up the call stack. [RT #41425] 4297. [test] Ensure delegations in RPZ zones fail robustly. [RT #41518] 4296. [bug] TCP packet sizes were calculated incorrectly in the stats channel; they could be counted in the wrong histogram bucket. [RT #40587] 4295. [bug] An unchecked result in dns_message_pseudosectiontotext() could allow incorrect text formatting of EDNS EXPIRE options. [RT #41437] 4294. [bug] Fixed a regression in which "rndc stop -p" failed to print the PID. [RT #41513] 4293. [bug] Address memory leak on priming query creation failure. [RT #41512] 4292. [placeholder] 4291. [cleanup] Added a required include to dns/forward.h. [RT #41474] 4290. [func] The timers returned by the statistics channel (indicating current time, server boot time, and most recent reconfiguration time) are now reported with millisecond accuracy. [RT #40082] 4289. [bug] The server could crash due to memory being used after it was freed if a zone transfer timed out. [RT #41297] 4288. [bug] Fixed a regression in resolver.c:possibly_mark() which caused known-bogus servers to be queried anyway. [RT #41321] 4287. [bug] Silence an overly noisy log message when message parsing fails. [RT #41374] 4286. [security] render_ecs errors were mishandled when printing out a OPT record resulting in a assertion failure. (CVE-2015-8705) [RT #41397] 4285. [security] Specific APL data could trigger a INSIST. (CVE-2015-8704) [RT #41396] 4284. [bug] Some GeoIP options were incorrectly documented using abbreviated forms which were not accepted by named. The code has been updated to allow both long and abbreviated forms. [RT #41381] 4283. [bug] OPENSSL_config is no longer re-callable. [RT #41348] 4282. [func] 'dig +[no]mapped' determine whether the use of mapped IPv4 addresses over IPv6 is permitted or not. The default is +mapped. [RT #41307] 4281. [bug] Teach dns_message_totext about BADCOOKIE. [RT #41257] 4280. [performance] Use optimal message sizes to improve compression in AXFRs. This reduces network traffic. [RT #40996] 4279. [test] Don't use fixed ports when unit testing. [RT #41194] 4278. [bug] 'delv +short +[no]split[=##]' didn't work as expected. [RT #41238] 4277. [performance] Improve performance of the RBT, the central zone datastructure: The aux hashtable was improved, hash function was updated to perform more uniform mapping, uppernode was added to dns_rbtnode, and other cleanups and performance improvements were made. [RT #41165] 4276. [protocol] Add support for SMIMEA. [RT #40513] 4275. [performance] Lazily initialize dns_compress->table only when compression is enabled. [RT #41189] 4274. [performance] Speed up typemap processing from text. [RT #41196] 4273. [bug] Only call dns_test_begin() and dns_test_end() once each in nsec3_test as it fails with GOST if called multiple times. 4272. [bug] dig: the +norrcomments option didn't work with +multi. [RT #41234] 4271. [test] Unit tests could deadlock in isc__taskmgr_pause(). [RT #41235] 4270. [security] Update allowed OpenSSL versions as named is potentially vulnerable to CVE-2015-3193. 4269. [bug] Zones using "map" format master files currently don't work as policy zones. This limitation has now been documented; attempting to use such zones in "response-policy" statements is now a configuration error. [RT #38321] 4268. [func] "rndc status" now reports the path to the configuration file. [RT #36470] 4267. [test] Check sdlz error handling. [RT #41142] 4266. [placeholder] 4265. [bug] Address unchecked isc_mem_get calls. [RT #41187] 4264. [bug] Check const of strchr/strrchr assignments match argument's const status. [RT #41150] 4263. [contrib] Address compiler warnings in mysqldyn module. [RT #41130] 4262. [bug] Fixed a bug in epoll socket code that caused sockets to not be registered for ready notification in some cases, causing named to not read from or write to them, resulting in what appear to the user as blocked connections. [RT #41067] 4261. [maint] H.ROOT-SERVERS.NET is 198.97.190.53 and 2001:500:1::53. [RT #40556] 4260. [security] Insufficient testing when parsing a message allowed records with an incorrect class to be be accepted, triggering a REQUIRE failure when those records were subsequently cached. (CVE-2015-8000) [RT #40987] 4259. [func] Add an option for non-destructive control channel access using a "read-only" clause. In such cases, a restricted set of rndc commands are allowed for querying information from named. [RT #40498] 4258. [bug] Limit rndc query message sizes to 32 KiB. This should not break any legitimate rndc commands, but will prevent a rogue rndc query from allocating too much memory. [RT #41073] 4257. [cleanup] Python scripts reported incorrect version. [RT #41080] 4256. [bug] Allow rndc command arguments to be quoted so as to allow spaces. [RT #36665] 4255. [performance] Add 'message-compression' option to disable DNS compression in responses. [RT #40726] 4254. [bug] Address missing lock when getting zone's serial. [RT #41072] 4253. [security] Address fetch context reference count handling error on socket error. (CVE-2015-8461) [RT#40945] 4252. [func] Add support for automating the generation CDS and CDNSKEY rrsets to named and dnssec-signzone. [RT #40424] 4251. [bug] NTAs were deleted when the server was reconfigured or reloaded. [RT #41058] 4250. [func] Log the TSIG key in use during inbound zone transfers. [RT #41075] 4249. [func] Improve error reporting of TSIG / SIG(0) records in the wrong location. [RT #41030] 4248. [performance] Add an isc_atomic_storeq() function, use it in stats counters to improve performance. [RT #39972] [RT #39979] 4247. [port] Require both HAVE_JSON and JSON_C_VERSION to be defined to report json library version. [RT #41045] 4246. [test] Ensure the statschannel system test runs when BIND is not built with libjson. [RT #40944] 4245. [placeholder] 4244. [bug] The parser was not reporting that use-ixfr is obsolete. [RT #41010] 4243. [func] Improved stats reporting from Timothe Litt. [RT #38941] 4242. [bug] Replace the client if not already replaced when prefetching. [RT #41001] 4241. [doc] Improved the TSIG, TKEY, and SIG(0) sections in the ARM. [RT #40955] 4240. [port] Fix LibreSSL compatibility. [RT #40977] 4239. [func] Changed default servfail-ttl value to 1 second from 10. Also, the maximum value is now 30 instead of 300. [RT #37556] 4238. [bug] Don't send to servers on net zero (0.0.0.0/8). [RT #40947] 4237. [doc] Upgraded documentation toolchain to use DocBook 5 and dblatex. [RT #40766] 4236. [performance] On machines with 2 or more processors (CPU), the default value for the number of UDP listeners has been changed to the number of detected processors minus one. [RT #40761] 4235. [func] Added support in named for "dnstap", a fast method of capturing and logging DNS traffic, and a new command "dnstap-read" to read a dnstap log file. Use "configure --enable-dnstap" to enable this feature (note that this requires libprotobuf-c and libfstrm). See the ARM for configuration details. Thanks to Robert Edmonds of Farsight Security. [RT #40211] 4234. [func] Add deflate compression in statistics channel HTTP server. [RT #40861] 4233. [test] Add tests for CDS and CDNSKEY with delegation-only. [RT #40597] 4232. [contrib] Address unchecked memory allocation calls in query-loc and zone2ldap. [RT #40789] 4231. [contrib] Address unchecked calloc call in dlz_mysqldyn_mod.c. [RT #40840] 4230. [contrib] dlz_wildcard_dynamic.c:dlz_create could return a uninitialized result. [RT #40839] 4229. [bug] A variable could be used uninitialized in dns_update_signaturesinc. [RT #40784] 4228. [bug] Address race condition in dns_client_destroyrestrans. [RT #40605] 4227. [bug] Silence static analysis warnings. [RT #40828] 4226. [bug] Address a theoretical shutdown race in zone.c:notify_send_queue(). [RT #38958] 4225. [port] freebsd/openbsd: Use '${CC} -shared' for building shared libraries. [RT #39557] 4224. [func] Added support for "dyndb", a new interface for loading zone data from an external database, developed by Red Hat for the FreeIPA project. DynDB drivers fully implement the BIND database API, and are capable of significantly better performance and functionality than DLZ drivers, while taking advantage of advanced database features not available in BIND such as multi-master replication. Thanks to Adam Tkac and Petr Spacek of Red Hat. [RT #35271] 4223. [func] Add support for setting max-cache-size to percentage of available physical memory, set default to 90%. [RT #38442] 4222. [func] Bias IPv6 servers when selecting the next server to query. [RT #40836] 4221. [bug] Resource leak on DNS_R_NXDOMAIN in fctx_create. [RT #40583] 4220. [doc] Improve documentation for zone-statistics. [RT #36955] 4219. [bug] Set event->result to ISC_R_WOULDBLOCK on EWOULDBLOCK, EGAIN when these soft error are not retried for isc_socket_send*(). 4218. [bug] Potential null pointer dereference on out of memory if mmap is not supported. [RT #40777] 4217. [protocol] Add support for CSYNC. [RT #40532] 4216. [cleanup] Silence static analysis warnings. [RT #40649] 4215. [bug] nsupdate: skip to next request on GSSTKEY create failure. [RT #40685] 4214. [protocol] Add support for TALINK. [RT #40544] 4213. [bug] Don't reuse a cache across multiple classes. [RT #40205] 4212. [func] Re-query if we get a bad client cookie returned over UDP. [RT #40748] 4211. [bug] Ensure that lwresd gets at least one task to work with if enabled. [RT #40652] 4210. [cleanup] Silence use after free false positive. [RT #40743] 4209. [bug] Address resource leaks in dlz modules. [RT #40654] 4208. [bug] Address null pointer dereferences on out of memory. [RT #40764] 4207. [bug] Handle class mismatches with raw zone files. [RT #40746] 4206. [bug] contrib: fixed a possible NULL dereference in DLZ wildcard module. [RT #40745] 4205. [bug] 'named-checkconf -p' could include unwanted spaces when printing tuples with unset optional fields. [RT #40731] 4204. [bug] 'dig +trace' failed to lookup the correct type if the initial root NS query was retried. [RT #40296] 4203. [test] The rrchecker system test now tests conversion to and from unknown-type format. [RT #40584] 4202. [bug] isccc_cc_fromwire() could return an incorrect result. [RT #40614] 4201. [func] The default preferred-glue is now the address record type of the transport the query was received over. [RT #40468] 4200. [cleanup] win32: update BINDinstall to be BIND release independent. [RT #38915] 4199. [protocol] Add support for NINFO, RKEY, SINK, TA. [RT #40545] [RT #40547] [RT #40561] [RT #40563] 4198. [placeholder] 4197. [bug] 'named-checkconf -z' didn't handle 'in-view' clauses. [RT #40603] 4196. [doc] Improve how "enum + other" types are documented. [RT #40608] 4195. [bug] 'max-zone-ttl unlimited;' was broken. [RT #40608] 4194. [bug] named-checkconf -p failed to properly print a port range. [RT #40634] 4193. [bug] Handle broken servers that return BADVERS incorrectly. [RT #40427] 4192. [bug] The default rrset-order of random was not always being applied. [RT #40456] 4191. [protocol] Accept DNS-SD non LDH PTR records in reverse zones as per RFC 6763. [RT #37889] 4190. [protocol] Accept Active Directory gc._msdcs. name as valid with check-names. still needs to be LDH. [RT #40399] 4189. [cleanup] Don't exit on overly long tokens in named.conf. [RT #40418] 4188. [bug] Support HTTP/1.0 client properly on the statistics channel. [RT #40261] 4187. [func] When any RR type implementation doesn't implement totext() for the RDATA's wire representation and returns ISC_R_NOTIMPLEMENTED, such RDATA is now printed in unknown presentation format (RFC 3597). RR types affected include LOC(29) and APL(42). [RT #40317]. 4186. [bug] Fixed an RPZ bug where a QNAME would be matched against a policy RR with wildcard owner name (trigger) where the QNAME was the wildcard owner name's parent. For example, the bug caused a query with QNAME "example.com" to match a policy RR with "*.example.com" as trigger. [RT #40357] 4185. [bug] Fixed an RPZ bug where a policy RR with wildcard owner name (trigger) would prevent another policy RR with its parent owner name from being loaded. For example, the bug caused a policy RR with trigger "example.com" to not have any effect when a previous policy RR with trigger "*.example.com" existed in that RPZ zone. [RT #40357] 4184. [bug] Fixed a possible memory leak in name compression when rendering long messages. (Also, improved wire_test for testing such messages.) [RT #40375] 4183. [cleanup] Use timing-safe memory comparisons in cryptographic code. Also, the timing-safe comparison functions have been renamed to avoid possible confusion with memcmp(). Thanks to Loganaden Velvindron of AFRINIC. [RT #40148] 4182. [cleanup] Use mnemonics for RR class and type comparisons. [RT #40297] 4181. [bug] Queued notify messages could be dequeued from the wrong rate limiter queue. [RT #40350] 4180. [bug] Error responses in pipelined queries could cause a crash in client.c. [RT #40289] 4179. [bug] Fix double frees in getaddrinfo() in libirs. [RT #40209] 4178. [bug] Fix assertion failure in parsing UNSPEC(103) RR from text. [RT #40274] 4177. [bug] Fix assertion failure in parsing NSAP records from text. [RT #40285] 4176. [bug] Address race issues with lwresd. [RT #40284] 4175. [bug] TKEY with GSS-API keys needed bigger buffers. [RT #40333] 4174. [bug] "dnssec-coverage -r" didn't handle time unit suffixes correctly. [RT #38444] 4173. [bug] dig +sigchase was not properly matching the trusted key. [RT #40188] 4172. [bug] Named / named-checkconf didn't handle a view of CLASS0. [RT #40265] 4171. [bug] Fixed incorrect class checks in TSIG RR implementation. [RT #40287] 4170. [security] An incorrect boundary check in the OPENPGPKEY rdatatype could trigger an assertion failure. (CVE-2015-5986) [RT #40286] 4169. [test] Added a 'wire_test -d' option to read input as raw binary data, for use as a fuzzing harness. [RT #40312] 4168. [security] A buffer accounting error could trigger an assertion failure when parsing certain malformed DNSSEC keys. (CVE-2015-5722) [RT #40212] 4167. [func] Update rndc's usage output to include recently added commands. Thanks to Tony Finch for submitting a patch. [RT #40010] 4166. [func] Print informative output from rndc showzone when allow-new-zones is not enabled for a view. Thanks to Tony Finch for submitting a patch. [RT #40009] 4165. [security] A failure to reset a value to NULL in tkey.c could result in an assertion failure. (CVE-2015-5477) [RT #40046] 4164. [bug] Don't rename slave files and journals on out of memory. [RT #40033] 4163. [bug] Address compiler warnings. [RT #40024] 4162. [bug] httpdmgr->flags was not being initialized. [RT #40017] 4161. [test] Add JSON test for traffic size stats; also test for consistency between "rndc stats" and the XML and JSON statistics channel contents. [RT #38700] 4160. [placeholder] 4159. [cleanup] Alphabetize dig's help output. [RT #39966] 4158. [placeholder] 4157. [placeholder] 4156. [func] Added statistics counters to track the sizes of incoming queries and outgoing responses in histogram buckets, as specified in RSSAC002. [RT #39049] 4155. [func] Allow RPZ rewrite logging to be configured on a per-zone basis using a newly introduced log clause in the response-policy option. [RT #39754] 4154. [bug] A OPT record should be included with the FORMERR response when there is a malformed EDNS option. [RT #39647] 4153. [bug] Dig should zero non significant +subnet bits. Check that non significant ECS bits are zero on receipt. [RT #39647] 4152. [func] Implement DNS COOKIE option. This replaces the experimental SIT option of BIND 9.10. The following named.conf directives are available: send-cookie, cookie-secret, cookie-algorithm, nocookie-udp-size and require-server-cookie. The following dig options are available: +[no]cookie[=value] and +[no]badcookie. [RT #39928] 4151. [bug] 'rndc flush' could cause a deadlock. [RT #39835] 4150. [bug] win32: listen-on-v6 { any; }; was not working. Apply minimal fix. [RT #39667] 4149. [bug] Fixed a race condition in the getaddrinfo() implementation in libirs, which caused the delv utility to crash with an assertion failure when using the '@server' syntax with a hostname argument. [RT #39899] 4148. [bug] Fix a bug when printing zone names with '/' character in XML and JSON statistics output. [RT #39873] 4147. [bug] Filter-aaaa / filter-aaaa-on-v4 / filter-aaaa-on-v6 was returning referrals rather than nodata responses when the AAAA records were filtered. [RT #39843] 4146. [bug] Address reference leak that could prevent a clean shutdown. [RT #37125] 4145. [bug] Not all unassociated adb entries where being printed. [RT #37125] 4144. [func] Add statistics counters for nxdomain redirections. [RT #39790] 4143. [placeholder] 4142. [bug] rndc addzone with view specified saved NZF config that could not be read back by named. This has now been fixed. [RT #39845] 4141. [bug] A formatting bug caused rndc zonestatus to print negative numbers for large serial values. This has now been fixed. [RT #39854] 4140. [cleanup] Remove redundant nzf_remove() call during delzone. [RT #39844] 4139. [doc] Fix rpz-client-ip documentation. [RT #39783] 4138. [security] An uninitialized value in validator.c could result in an assertion failure. (CVE-2015-4620) [RT #39795] 4137. [bug] Make rndc reconfig report configuration errors the same way rndc reload does. [RT #39635] 4136. [bug] Stale statistics counters with the leading '#' prefix (such as #NXDOMAIN) were not being updated correctly. This has been fixed. [RT #39141] 4135. [cleanup] Log expired NTA at startup. [RT #39680] 4134. [cleanup] Include client-ip rules when logging the number of RPZ rules of each type. [RT #39670] 4133. [port] Update how various json libraries are handled. [RT #39646] 4132. [cleanup] dig: added +rd as a synonym for +recurse, added +class as an unabbreviated alternative to +cl. [RT #39686] 4131. [bug] Addressed further problems with reloading RPZ zones. [RT #39649] 4130. [bug] The compatibility shim for *printf() misprinted some large numbers. [RT #39586] 4129. [port] Address API changes in OpenSSL 1.1.0. [RT #39532] 4128. [bug] Address issues raised by Coverity 7.6. [RT #39537] 4127. [protocol] CDS and CDNSKEY need to be signed by the key signing key as per RFC 7344, Section 4.1. [RT #37215] 4126. [bug] Addressed a regression introduced in change #4121. [RT #39611] 4125. [test] Added tests for dig, renamed delv test to digdelv. [RT #39490] 4124. [func] Log errors or warnings encountered when parsing the internal default configuration. Clarify the logging of errors and warnings encountered in rndc addzone or modzone parameters. [RT #39440] 4123. [port] Added %z (size_t) format options to the portable internal printf/sprintf implementation. [RT #39586] 4122. [bug] The server could match a shorter prefix than what was available in CLIENT-IP policy triggers, and so, an unexpected action could be taken. This has been corrected. [RT #39481] 4121. [bug] On servers with one or more policy zones configured as slaves, if a policy zone updated during regular operation (rather than at startup) using a full zone reload, such as via AXFR, a bug could allow the RPZ summary data to fall out of sync, potentially leading to an assertion failure in rpz.c when further incremental updates were made to the zone, such as via IXFR. [RT #39567] 4120. [bug] A bug in RPZ could cause the server to crash if policy zones were updated while recursion was pending for RPZ processing of an active query. [RT #39415] 4119. [test] Allow dig to set the message opcode. [RT #39550] 4118. [bug] Teach isc-config.sh about irs. [RT #39213] 4117. [protocol] Add EMPTY.AS112.ARPA as per RFC 7534. 4116. [bug] Fix a bug in RPZ that could cause some policy zones that did not specifically require recursion to be treated as if they did; consequently, setting qname-wait-recurse no; was sometimes ineffective. [RT #39229] 4115. [func] "rndc -r" now prints the result code (e.g., ISC_R_SUCCESS, ISC_R_TIMEOUT, etc) after running the requested command. [RT #38913] 4114. [bug] Fix a regression in radix tree implementation introduced by ECS code. This bug was never released, but it was reported by a user testing master. [RT #38983] 4113. [test] Check for Net::DNS is some system test prerequisites. [RT #39369] 4112. [bug] Named failed to load when "root-delegation-only" was used without a list of domains to exclude. [RT #39380] 4111. [doc] Alphabetize rndc man page. [RT #39360] 4110. [bug] Address memory leaks / null pointer dereferences on out of memory. [RT #39310] 4109. [port] linux: support reading the local port range from net.ipv4.ip_local_port_range. [RT # 39379] 4108. [func] An additional NXDOMAIN redirect method (option "nxdomain-redirect") has been added, allowing redirection to a specified DNS namespace instead of a single redirect zone. [RT #37989] 4107. [bug] Address potential deadlock when updating zone content. [RT #39269] 4106. [port] Improve readline support. [RT #38938] 4105. [port] Misc fixes for Microsoft Visual Studio 2015 CTP6 in 64 bit mode. [RT #39308] 4104. [bug] Address uninitialized elements. [RT #39252] 4103. [port] Misc fixes for Microsoft Visual Studio 2015 CTP6. [RT #39267] 4102. [bug] Fix a use after free bug introduced in change #4094. [RT #39281] 4101. [bug] dig: the +split and +rrcomments options didn't work with +short. [RT #39291] 4100. [bug] Inherited owernames on the line immediately following a $INCLUDE were not working. [RT #39268] 4099. [port] clang: make unknown commandline options hard errors when determining what options are supported. [RT #39273] 4098. [bug] Address use-after-free issue when using a predecessor key with dnssec-settime. [RT #39272] 4097. [func] Add additional logging about xfrin transfer status. [RT #39170] 4096. [bug] Fix a use after free of query->sendevent. [RT #39132] 4095. [bug] zone->options2 was not being properly initialized. [RT #39228] 4094. [bug] A race during shutdown or reconfiguration could cause an assertion in mem.c. [RT #38979] 4093. [func] Dig now learns the SIT value from truncated responses when it retries over TCP. [RT #39047] 4092. [bug] 'in-view' didn't work for zones beneath a empty zone. [RT #39173] 4091. [cleanup] Some cleanups in isc mem code. [RT #38896] 4090. [bug] Fix a crash while parsing malformed CAA RRs in presentation format, i.e., from text such as from master files. Thanks to John Van de Meulebrouck Brendgard for discovering and reporting this problem. [RT #39003] 4089. [bug] Send notifies immediately for slave zones during startup. [RT #38843] 4088. [port] Fixed errors when building with libressl. [RT #38899] 4087. [bug] Fix a crash due to use-after-free due to sequencing of tasks actions. [RT #38495] 4086. [bug] Fix out-of-srcdir build with native pkcs11. [RT #38831] 4085. [bug] ISC_PLATFORM_HAVEXADDQ could be inconsistently set. [RT #38828] 4084. [bug] Fix a possible race in updating stats counters. [RT #38826] 4083. [cleanup] Print the number of CPUs and UDP listeners consistently in the log and in "rndc status" output; indicate whether threads are supported in "named -V" output. [RT #38811] 4082. [bug] Incrementally sign large inline zone deltas. [RT #37927] 4081. [cleanup] Use dns_rdatalist_init consistently. [RT #38759] 4080. [func] Completed change #4022, adding a "lock-file" option to named.conf to override the default lock file, in addition to the "named -X " command line option. Setting the lock file to "none" using either method disables the check completely. [RT #37908] 4079. [func] Preserve the case of the owner name of records to the RRset level. [RT #37442] 4078. [bug] Handle the case where CMSG_SPACE(sizeof(int)) != CMSG_SPACE(sizeof(char)). [RT #38621] 4077. [test] Add static-stub regression test for DS NXDOMAIN return making the static stub disappear. [RT #38564] 4076. [bug] Named could crash on shutdown with outstanding reload / reconfig events. [RT #38622] 4075. [placeholder] 4074. [cleanup] Cleaned up more warnings from gcc -Wshadow. [RT #38708] 4073. [cleanup] Add libjson-c version number reporting to "named -V"; normalize version number formatting. [RT #38056] 4072. [func] Add a --enable-querytrace configure switch for very verbose query trace logging. (This option has a negative performance impact and should be used only for debugging.) [RT #37520] 4071. [cleanup] Initialize pthread mutex attrs just once, instead of doing it per mutex creation. [RT #38547] 4070. [bug] Fix a segfault in nslookup in a query such as "nslookup isc.org AMS.SNS-PB.ISC.ORG -all". [RT #38548] 4069. [doc] Reorganize options in the nsupdate man page. [RT #38515] 4068. [bug] Omit unknown serial number from JSON zone statistics. [RT #38604] 4067. [cleanup] Reduce noise from RRL when query logging is disabled. [RT #38648] 4066. [doc] Reorganize options in the dig man page. [RT #38516] 4065. [test] Additional RFC 5011 tests. [RT #38569] 4064. [contrib] dnssec-keyset.sh: Generates a specified number of DNSSEC keys with timing set to implement a pre-publication key rollover strategy. Thanks to Jeffry A. Spain. [RT #38459] 4063. [bug] Asynchronous zone loads were not handled correctly when the zone load was already in progress; this could trigger a crash in zt.c. [RT #37573] 4062. [bug] Fix an out-of-bounds read in RPZ code. If the read succeeded, it doesn't result in a bug during operation. If the read failed, named could segfault. [RT #38559] 4061. [bug] Handle timeout in legacy system test. [RT #38573] 4060. [bug] dns_rdata_freestruct could be called on a uninitialized structure when handling a error. [RT #38568] 4059. [bug] Addressed valgrind warnings. [RT #38549] 4058. [bug] UDP dispatches could use the wrong pseudorandom number generator context. [RT #38578] 4057. [bug] 'dnssec-dsfromkey -T 0' failed to add ttl field. [RT #38565] 4056. [bug] Expanded automatic testing of trust anchor management and fixed several small bugs including a memory leak and a possible loss of key state information. [RT #38458] 4055. [func] "rndc managed-keys" can be used to check status of trust anchors or to force keys to be refreshed, Also, the managed keys data file has easier-to-read comments. [RT #38458] 4054. [func] Added a new tool 'mdig', a lightweight clone of dig able to send multiple pipelined queries. [RT #38261] 4053. [security] Revoking a managed trust anchor and supplying an untrusted replacement could cause named to crash with an assertion failure. (CVE-2015-1349) [RT #38344] 4052. [bug] Fix a leak of query fetchlock. [RT #38454] 4051. [bug] Fix a leak of pthread_mutexattr_t. [RT #38454] 4050. [bug] RPZ could send spurious SERVFAILs in response to duplicate queries. [RT #38510] 4049. [bug] CDS and CDNSKEY had the wrong attributes. [RT #38491] 4048. [bug] adb hash table was not being grown. [RT #38470] 4047. [cleanup] "named -V" now reports the current running versions of OpenSSL and the libxml2 libraries, in addition to the versions that were in use at build time. 4046. [bug] Accounting of "total use" in memory context statistics was not correct. [RT #38370] 4045. [bug] Skip to next master on dns_request_createvia4 failure. [RT #25185] 4044. [bug] Change 3955 was not complete, resulting in an assertion failure if the timing was just right. [RT #38352] 4043. [func] "rndc modzone" can be used to modify the configuration of an existing zone, using similar syntax to "rndc addzone". [RT #37895] 4042. [bug] zone.c:iszonesecure was being called too late. [RT #38371] 4041. [func] TCP sockets can now be shared while connecting. (This will be used to enable client-side support of pipelined queries.) [RT #38231] 4040. [func] Added server-side support for pipelined TCP queries. Clients may continue sending queries via TCP while previous queries are being processed in parallel. (The new "keep-response-order" option allows clients to be specified for which the old behavior will still be used.) [RT #37821] 4039. [cleanup] Cleaned up warnings from gcc -Wshadow. [RT #37381] 4038. [bug] Add 'rpz' flag to node and use it to determine whether to call dns_rpz_delete. This should prevent unbalanced add / delete calls. [RT #36888] 4037. [bug] also-notify was ignoring the tsig key when checking for duplicates resulting in some expected notify messages not being sent. [RT #38369] 4036. [bug] Make call to open a temporary file name safe during NZF creation. [RT #38331] 4035. [bug] Close temporary and NZF FILE pointers before moving the former into the latter's place, as required on Windows. [RT #38332] 4034. [func] When added, negative trust anchors (NTA) are now saved to files (viewname.nta), in order to persist across restarts of the named server. [RT #37087] 4033. [bug] Missing out of memory check in request.c:req_send. [RT #38311] 4032. [bug] Built-in "empty" zones did not correctly inherit the "allow-transfer" ACL from the options or view. [RT #38310] 4031. [bug] named-checkconf -z failed to report a missing file with a hint zone. [RT #38294] 4030. [func] "rndc delzone" is now applicable to zones that were configured in named.conf, as well as zones that were added via "rndc addzone". (Note, however, that if named.conf is not also modified, the deleted zone will return when named is reloaded.) [RT #37887] 4029. [func] "rndc showzone" displays the current configuration of a specified zone. [RT #37887] 4028. [bug] $GENERATE with a zero step was not being caught as a error. A $GENERATE with a / but no step was not being caught as a error. [RT #38262] 4027. [port] Net::DNS 0.81 compatibility. [RT #38165] 4026. [bug] Fix RFC 3658 reference in dig +sigchase. [RT #38173] 4025. [port] bsdi: failed to build. [RT #38047] 4024. [bug] dns_rdata_opt_first, dns_rdata_opt_next, dns_rdata_opt_current, dns_rdata_txt_first, dns_rdata_txt_next and dns_rdata_txt_current were documented but not implemented. These have now been implemented. dns_rdata_spf_first, dns_rdata_spf_next and dns_rdata_spf_current were documented but not implemented. The prototypes for these functions have been removed. [RT #38068] 4023. [bug] win32: socket handling with explicit ports and invoking named with -4 was broken for some configurations. [RT #38068] 4022. [func] Stop multiple spawns of named by limiting number of processes to 1. This is done by using a lockfile and checking whether we can listen on any configured TCP interfaces. [RT #37908] 4021. [bug] Adjust max-recursion-queries to accommodate the need for more queries when the cache is empty. [RT #38104] 4020. [bug] Change 3736 broke nsupdate's SOA MNAME discovery resulting in updates being sent to the wrong server. [RT #37925] 4019. [func] If named is not configured to validate the answer then allow fallback to plain DNS on timeout even when we know the server supports EDNS. [RT #37978] 4018. [placeholder] 4017. [test] Add system test to check lookups to legacy servers with broken DNS behavior. [RT #37965] 4016. [bug] Fix a dig segfault due to bad linked list usage. [RT #37591] 4015. [bug] Nameservers that are skipped due to them being CNAMEs were not being logged. They are now logged to category 'cname' as per BIND 8. [RT #37935] 4014. [bug] When including a master file origin_changed was not being properly set leading to a potentially spurious 'inherited owner' warning. [RT #37919] 4013. [func] Add a new tcp-only option to server (config) / peer (struct) to use TCP transport to send queries (in place of UDP transport with a TCP fallback on truncated (TC set) response). [RT #37800] 4012. [cleanup] Check returned status of OpenSSL digest and HMAC functions when they return one. Note this applies only to FIPS capable OpenSSL libraries put in FIPS mode and MD5. [RT #37944] 4011. [bug] master's list port and dscp inheritance was not properly implemented. [RT #37792] 4010. [cleanup] Clear the prefetchable state when initiating a prefetch. [RT #37399] 4009. [func] delv: added a +tcp option. [RT #37855] 4008. [contrib] Updated zkt to latest version (1.1.3). [RT #37886] 4007. [doc] Remove acl forward reference restriction. [RT #37772] 4006. [security] A flaw in delegation handling could be exploited to put named into an infinite loop. This has been addressed by placing limits on the number of levels of recursion named will allow (default 7), and the number of iterative queries that it will send (default 50) before terminating a recursive query (CVE-2014-8500). The recursion depth limit is configured via the "max-recursion-depth" option, and the query limit via the "max-recursion-queries" option. [RT #37580] 4005. [func] The buffer used for returning text from rndc commands is now dynamically resizable, allowing arbitrarily large amounts of text to be sent back to the client. (Prior to this change, it was possible for the output of "rndc tsig-list" to be truncated.) [RT #37731] 4004. [bug] When delegations had AAAA glue but not A, a reference could be leaked causing an assertion failure on shutdown. [RT #37796] 4003. [security] When geoip-directory was reconfigured during named run-time, the previously loaded GeoIP data could remain, potentially causing wrong ACLs to be used or wrong results to be served based on geolocation (CVE-2014-8680). [RT #37720] 4002. [security] Lookups in GeoIP databases that were not loaded could cause an assertion failure (CVE-2014-8680). [RT #37679] 4001. [security] The caching of GeoIP lookups did not always handle address families correctly, potentially resulting in an assertion failure (CVE-2014-8680). [RT #37672] 4000. [bug] NXDOMAIN redirection incorrectly handled NXRRSET from the redirect zone. [RT #37722] 3999. [func] "mkeys" and "nzf" files are now named after their corresponding views, unless the view name contains characters that would be incompatible with use in a filename (i.e., slash, backslash, or capital letters). If a view name does contain these characters, the files will still be named using a cryptographic hash of the view name. Regardless of this, if a file using the old name format is found to exist, it will continue to be used. [RT #37704] 3998. [bug] isc_radix_search was returning matches that were too precise. [RT #37680] 3997. [protocol] Add OPENGPGKEY record. [RT# 37671] 3996. [bug] Address use after free on out of memory error in keyring_add. [RT #37639] 3995. [bug] receive_secure_serial holds the zone lock for too long. [RT #37626] 3994. [func] Dig now supports setting the last unassigned DNS header flag bit (dig +zflag). [RT #37421] 3993. [func] Dig now supports EDNS negotiation by default. (dig +[no]ednsnegotiation). Note: This is disabled by default in BIND 9.10 and enabled by default in BIND 9.11. [RT #37604] 3992. [func] DiG can now send queries without questions (dig +header-only). [RT #37599] 3991. [func] Add the ability to buffer logging output by specifying "buffered yes;" when defining a channel. [RT #26561] 3990. [test] Add tests for unknown DNSSEC algorithm handling. [RT #37541] 3989. [cleanup] Remove redundant dns_db_resigned calls. [RT #35748] 3988. [func] Allow the zone serial of a dynamically updatable zone to be updated via "rndc signing -serial". [RT #37404] 3987. [port] Handle future Visual Studio 14 incompatible changes. [RT #37380] 3986. [doc] Add the BIND version number to page footers in the ARM. [RT #37398] 3985. [doc] Describe how +ndots and +search interact in dig. [RT #37529] 3984. [func] Accept 256 byte long PINs in native PKCS#11 crypto. [RT #37410] 3983. [bug] Change #3940 was incomplete: negative trust anchors could be set to last up to a week, but the "nta-lifetime" and "nta-recheck" options were still limited to one day. [RT #37522] 3982. [doc] Include release notes in product documentation. [RT #37272] 3981. [bug] Cache DS/NXDOMAIN independently of other query types. [RT #37467] 3980. [bug] Improve --with-tuning=large by self tuning of SO_RCVBUF size. [RT #37187] 3979. [bug] Negative trust anchor fetches were not properly managed. [RT #37488] 3978. [test] Added a unit test for Diffie-Hellman key computation, completing change #3974. [RT #37477] 3977. [cleanup] "rndc secroots" reported a "not found" error when there were no negative trust anchors set. [RT #37506] 3976. [bug] When refreshing managed-key trust anchors, clear any cached trust so that they will always be revalidated with the current set of secure roots. [RT #37506] 3975. [bug] Don't populate or use the bad cache for queries that don't request or use recursion. [RT #37466] 3974. [bug] Handle DH_compute_key() failure correctly in openssldh_link.c. [RT #37477] 3973. [test] Added hooks for Google Performance Tools CPU profiler, including real-time/wall-clock profiling. Use "configure --with-gperftools-profiler" to enable. [RT #37339] 3972. [bug] Fix host's usage statement. [RT #37397] 3971. [bug] Reduce the cascading failures due to a bad $TTL line in named-checkconf / named-checkzone. [RT #37138] 3970. [contrib] Fixed a use after free bug in the SDB LDAP driver. [RT #37237] 3969. [test] Added 'delv' system test. [RT #36901] 3968. [bug] Silence spurious log messages when using 'named -[46]'. [RT #37308] 3967. [test] Add test for inlined signed zone in multiple views with different DNSKEY sets. [RT #35759] 3966. [bug] Missing dns_db_closeversion call in receive_secure_db. [RT #35746] 3965. [func] Log outgoing packets and improve packet logging to support logging the remote address. [RT #36624] 3964. [func] nsupdate now performs check-names processing. [RT #36266] 3963. [test] Added NXRRSET test cases to the "dlzexternal" system test. [RT #37344] 3962. [bug] 'dig +topdown +trace +sigchase' address unhandled error conditions. [RT #34663] 3961. [bug] Forwarding of SIG(0) signed UPDATE messages failed with BADSIG. [RT #37216] 3960. [bug] 'dig +sigchase' could loop forever. [RT #37220] 3959. [bug] Updates could be lost if they arrived immediately after a rndc thaw. [RT #37233] 3958. [bug] Detect when writeable files have multiple references in named.conf. [RT #37172] 3957. [bug] "dnssec-keygen -S" failed for ECCGOST, ECDSAP256SHA256 and ECDSAP384SHA384. [RT #37183] 3956. [func] Notify messages are now rate limited by notify-rate and startup-notify-rate instead of serial-query-rate. [RT #24454] 3955. [bug] Notify messages due to changes are no longer queued behind startup notify messages. [RT #24454] 3954. [bug] Unchecked mutex init in dlz_dlopen_driver.c [RT #37112] 3953. [bug] Don't escape semi-colon in TXT fields. [RT #37159] 3952. [bug] dns_name_fullcompare failed to set *nlabelsp when the two name pointers were the same. [RT #37176] 3951. [func] Add the ability to set yet-to-be-defined EDNS flags to dig (+ednsflags=#). [RT #37142] 3950. [port] Changed the bin/python Makefile to work around a bmake bug in FreeBSD 10 and NetBSD 6. [RT #36993] 3949. [experimental] Experimental support for draft-andrews-edns1 by sending EDNS(1) queries (define DRAFT_ANDREWS_EDNS1 when building). Add support for limiting the EDNS version advertised to servers: server { edns-version 0; }; Log the EDNS version received in the query log. [RT #35864] 3948. [port] solaris: RCVBUFSIZE was too large on Solaris with --with-tuning=large. [RT #37059] 3947. [cleanup] Set the executable bit on libraries when using libtool. [RT #36786] 3946. [cleanup] Improved "configure" search for a python interpreter. [RT #36992] 3945. [bug] Invalid wildcard expansions could be incorrectly accepted by the validator. [RT #37093] 3944. [test] Added a regression test for "server-id". [RT #37057] 3943. [func] SERVFAIL responses can now be cached for a limited time (configured by "servfail-ttl", default 10 seconds, limit 30). This can reduce the frequency of retries when an authoritative server is known to be failing, e.g., due to ongoing DNSSEC validation problems. [RT #21347] 3942. [bug] Wildcard responses from a optout range should be marked as insecure. [RT #37072] 3941. [doc] Include the BIND version number in the ARM. [RT #37067] 3940. [func] "rndc nta" now allows negative trust anchors to be set for up to one week. [RT #37069] 3939. [func] Improve UPDATE forwarding performance by allowing TCP connections to be shared. [RT #37039] 3938. [func] Added quotas to be used in recursive resolvers that are under high query load for names in zones whose authoritative servers are nonresponsive or are experiencing a denial of service attack. - "fetches-per-server" limits the number of simultaneous queries that can be sent to any single authoritative server. The configured value is a starting point; it is automatically adjusted downward if the server is partially or completely non-responsive. The algorithm used to adjust the quota can be configured via the "fetch-quota-params" option. - "fetches-per-zone" limits the number of simultaneous queries that can be sent for names within a single domain. (Note: Unlike "fetches-per-server", this value is not self-tuning.) - New stats counters have been added to count queries spilled due to these quotas. See the ARM for details of these options. [RT #37125] 3937. [func] Added some debug logging to better indicate the conditions causing SERVFAILs when resolving. [RT #35538] 3936. [func] Added authoritative support for the EDNS Client Subnet (ECS) option. ACLs can now include "ecs" elements which specify an address or network prefix; if an ECS option is included in a DNS query, then the address encoded in the option will be matched against "ecs" ACL elements. Also, if an ECS address is included in a query, then it will be used instead of the client source address when matching "geoip" ACL elements. This behavior can be overridden with "geoip-use-ecs no;". (Note: to enable "geoip" ACLs, use "configure --with-geoip". This requires libGeoIP version 1.5.0 or higher.) When "ecs" or "geoip" ACL elements are used to select a view for a query, the response will include an ECS option to indicate which client network the answer is valid for. (Thanks to Vincent Bernat.) [RT #36781] 3935. [bug] "geoip asnum" ACL elements would not match unless the full organization name was specified. They can now match against the AS number alone (e.g., AS1234). [RT #36945] 3934. [bug] Catch bad 'sit-secret' in named-checkconf. Improve sit-secret documentation. [RT #36980] 3933. [bug] Corrected the implementation of dns_rdata_casecompare() for the HIP rdata type. [RT #36911] 3932. [test] Improved named-checkconf tests. [RT #36911] 3931. [cleanup] Cleanup how dlz grammar is defined. [RT #36879] 3930. [bug] "rndc nta -r" could cause a server hang if the NTA was not found. [RT #36909] 3929. [bug] 'host -a' needed to clear idnoptions. [RT #36963] 3928. [test] Improve rndc system test. [RT #36898] 3927. [bug] dig: report PKCS#11 error codes correctly when compiled with --enable-native-pkcs11. [RT #36956] 3926. [doc] Added doc for geoip-directory. [RT #36877] 3925. [bug] DS lookup of RFC 1918 empty zones failed. [RT #36917] 3924. [bug] Improve 'rndc addzone' error reporting. [RT #35187] 3923. [bug] Sanity check the xml2-config output. [RT #22246] 3922. [bug] When resigning, dnssec-signzone was removing all signatures from delegation nodes. It now retains DS and (if applicable) NSEC signatures. [RT #36946] 3921. [bug] AD was inappropriately set on RPZ responses. [RT #36833] 3920. [doc] Added doc for masterfile-style. [RT #36823] 3919. [bug] dig: continue to next line if a address lookup fails in batch mode. [RT #36755] 3918. [doc] Update check-spf documentation. [RT #36910] 3917. [bug] dig, nslookup and host now continue on names that are too long after applying a search list elements. [RT #36892] 3916. [contrib] zone2sqlite checked wrong result code. Address compiler warnings. [RT #36931] 3915. [bug] Address a assertion if a route event arrived while shutting down. [RT #36887] 3914. [bug] Allow the URI target and CAA value fields to be zero length. [RT #36737] 3913. [bug] Address race issue in dispatch. [RT #36731] 3912. [bug] Address some unrecoverable lookup failures. [RT #36330] 3911. [func] Implement EDNS EXPIRE option client side, allowing a slave server to set the expiration timer correctly when transferring zone data from another slave server. [RT #35925] 3910. [bug] Fix races to free event during shutdown. [RT #36720] 3909. [bug] When computing the number of elements required for a acl count_acl_elements could have a short count leading to a assertion failure. Also zero out new acl elements in dns_acl_merge. [RT #36675] 3908. [bug] rndc now differentiates between a zone in multiple views and a zone that doesn't exist at all. [RT #36691] 3907. [cleanup] Alphabetize rndc help. [RT #36683] 3906. [protocol] Update URI record format to comply with draft-faltstrom-uri-08. [RT #36642] 3905. [bug] Address deadlock between view.c and adb.c. [RT #36341] 3904. [func] Add the RPZ SOA to the additional section. [RT36507] 3903. [bug] Improve the accuracy of DiG's reported round trip time. [RT 36611] 3902. [bug] liblwres wasn't handling link-local addresses in nameserver clauses in resolv.conf. [RT #36039] 3901. [protocol] Added support for CAA record type (RFC 6844). [RT #36625] 3900. [bug] Fix a crash in PostgreSQL DLZ driver. [RT #36637] 3899. [bug] "request-ixfr" is only applicable to slave and redirect zones. [RT #36608] 3898. [bug] Too small a buffer in tohexstr() calls in test code. [RT #36598] 3897. [bug] RPZ summary information was not properly being updated after a AXFR resulting in changes sometimes being ignored. [RT #35885] 3896. [bug] Address performance issues with DSCP code on some platforms. [RT #36534] 3895. [func] Add the ability to set the DSCP code point to dig. [RT #36546] 3894. [bug] Buffers in isc_print_vsnprintf were not properly initialized leading to potential overflows when printing out quad values. [RT #36505] 3893. [bug] Peer DSCP values could be returned without being set. [RT #36538] 3892. [bug] Setting '-t aaaa' in .digrc had unintended side effects. [RT #36452] 3891. [bug] Use ${INSTALL_SCRIPT} rather than ${INSTALL_PROGRAM} to install python programs. 3890. [bug] RRSIG sets that were not loaded in a single transaction at start up where not being correctly added to re-signing heaps. [RT #36302] 3889. [port] hurd: configure fixes as per: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=746540 3888. [func] 'rndc status' now reports the number of automatic zones. [RT #36015] 3887. [cleanup] Make all static symbols in rbtdb64 end in "64" so they are easier to use in a debugger. [RT #36373] 3886. [bug] rbtdb_write_header should use a once to initialize FILE_VERSION. [RT #36374] 3885. [port] Use 'open()' rather than 'file()' to open files in python. 3884. [protocol] Add CDS and CDNSKEY record types. [RT #36333] 3883. [placeholder] 3882. [func] By default, negative trust anchors will be tested periodically to see whether data below them can be validated, and if so, they will be allowed to expire early. The "rndc nta -force" option overrides this behavior. The default NTA lifetime and the recheck frequency can be configured by the "nta-lifetime" and "nta-recheck" options. [RT #36146] 3881. [bug] Address memory leak with UPDATE error handling. [RT #36303] 3880. [test] Update ans.pl to work with new TSIG support in Net::DNS; add additional Net::DNS version prerequisite checks. [RT #36327] 3879. [func] Add version printing option to various BIND utilities. [RT #10686] 3878. [bug] Using the incorrect filename for a DLZ module caused a segmentation fault on startup. [RT #36286] 3877. [bug] Inserting and deleting parent and child nodes in response policy zones could trigger an assertion failure. [RT #36272] 3876. [bug] Improve efficiency of DLZ redirect zones by suppressing unnecessary database lookups. [RT #35835] 3875. [cleanup] Clarify log message when unable to read private key files. [RT #24702] 3874. [test] Check that only "check-names master" is needed for updates to be accepted. 3873. [protocol] Only warn for SPF without TXT spf record. [RT #36210] 3872. [bug] Address issues found by static analysis. [RT #36209] 3871. [bug] Don't publish an activated key automatically before its publish time. [RT #35063] 3870. [func] Updated the random number generator used in the resolver to use the updated ChaCha based one (similar to OpenBSD's changes). Also moved the RNG to libisc and added unit tests for it. [RT #35942] 3869. [doc] Document that in-view zones cannot be used for response policy zones. [RT #35941] 3868. [bug] isc_mem_setwater incorrectly cleared hi_called potentially leaving over memory cleaner running. [RT #35270] 3867. [func] "rndc nta" can now be used to set a temporary negative trust anchor, which disables DNSSEC validation below a specified name for a specified period of time (not exceeding 24 hours). This can be used when validation for a domain is known to be failing due to a configuration error on the part of the domain owner rather than a spoofing attack. [RT #29358] 3866. [bug] Named could die on disk full in generate_session_key. [RT #36119] 3865. [test] Improved testability of the red-black tree implementation and added unit tests. [RT #35904] 3864. [bug] RPZ didn't work well when being used as forwarder. [RT #36060] 3863. [bug] The "E" flag was missing from the query log as a unintended side effect of code rearrangement to support EDNS EXPIRE. [RT #36117] 3862. [cleanup] Return immediately if we are not going to log the message in ns_client_dumpmessage. 3861. [security] Missing isc_buffer_availablelength check results in a REQUIRE assertion when printing out a packet (CVE-2014-3859). [RT #36078] 3860. [bug] ioctl(DP_POLL) array size needs to be determined at run time as it is limited to {OPEN_MAX}. [RT #35878] 3859. [placeholder] 3858. [bug] Disable GCC 4.9 "delete null pointer check". [RT #35968] 3857. [bug] Make it harder for a incorrect NOEDNS classification to be made. [RT #36020] 3856. [bug] Configuring libjson without also configuring libxml resulted in a REQUIRE assertion when retrieving statistics using json. [RT #36009] 3855. [bug] Limit smoothed round trip time aging to no more than once a second. [RT #32909] 3854. [cleanup] Report unrecognized options, if any, in the final configure summary. [RT #36014] 3853. [cleanup] Refactor dns_rdataslab_fromrdataset to separate out the handling of a rdataset with no records. [RT #35968] 3852. [func] Increase the default number of clients available for servicing lightweight resolver queries, and make them configurable via the "lwres-tasks" and "lwres-clients" options. (Thanks to Tomas Hozza.) [RT #35857] 3851. [func] Allow libseccomp based system-call filtering on Linux; use "configure --enable-seccomp" to turn it on. Thanks to Loganaden Velvindron of AFRINIC for the contribution. [RT #35347] 3850. [bug] Disabling forwarding could trigger a REQUIRE assertion. [RT #35979] 3849. [doc] Alphabetized dig's +options. [RT #35992] 3848. [bug] Adjust 'statistics-channels specified but not effective' error message to account for JSON support. [RT #36008] 3847. [bug] 'configure --with-dlz-postgres' failed to fail when there is not support available. 3846. [bug] "dig +notcp ixfr=" should result in a UDP ixfr query. [RT #35980] 3845. [placeholder] 3844. [bug] Use the x64 version of the Microsoft Visual C++ Redistributable when built for 64 bit Windows. [RT #35973] 3843. [protocol] Check EDNS EXPIRE option in dns_rdata_fromwire. [RT #35969] 3842. [bug] Adjust RRL log-only logging category. [RT #35945] 3841. [cleanup] Refactor zone.c:add_opt to use dns_message_buildopt. [RT #35924] 3840. [port] Check for arc4random_addrandom() before using it; it's been removed from OpenBSD 5.5. [RT #35907] 3839. [test] Use only posix-compatible shell in system tests. [RT #35625] 3838. [protocol] EDNS EXPIRE as been assigned a code point of 9. 3837. [security] A NULL pointer is passed to query_prefetch resulting a REQUIRE assertion failure when a fetch is actually initiated (CVE-2014-3214). [RT #35899] 3836. [bug] Address C++ keyword usage in header file. 3835. [bug] Geoip ACL elements didn't work correctly when referenced via named or nested ACLs. [RT #35879] 3834. [bug] The re-signing heaps were not being updated soon enough leading to multiple re-generations of the same RRSIG when a zone transfer was in progress. [RT #35273] 3833. [bug] Cross compiling was broken due to calling genrandom at build time. [RT #35869] 3832. [func] "named -L " causes named to send log messages to the specified file by default instead of to the system log. (Thanks to Tony Finch.) [RT #35845] 3831. [cleanup] Reduce logging noise when EDNS state changes occur. [RT #35843] 3830. [func] When query logging is enabled, log query errors at the same level ('info') as the queries themselves. [RT #35844] 3829. [func] "dig +ttlunits" causes dig to print TTL values with time-unit suffixes: w, d, h, m, s for weeks, days, hours, minutes, and seconds. (Thanks to Tony Finch.) [RT #35823] 3828. [func] "dnssec-signzone -N date" updates serial number to the current date in YYYYMMDDNN format. [RT #35800] 3827. [placeholder] 3826. [bug] Corrected bad INSIST logic in isc_radix_remove(). [RT #35870] 3825. [bug] Address sign extension bug in isc_regex_validate. [RT #35758] 3824. [bug] A collision between two flag values could cause problems with cache cleaning when SIT was enabled. [RT #35858] 3823. [func] Log the rpz cname target when rewriting. [RT #35667] 3822. [bug] Log the correct type of static-stub zones when removing them. [RT #35842] 3821. [contrib] Added a new "mysqldyn" DLZ module with dynamic update and transaction support. Thanks to Marty Lee for the contribution. [RT #35656] 3820. [func] The DLZ API doesn't pass the database version to the lookup() function; this can cause DLZ modules that allow dynamic updates to mishandle prerequisite checks. This has been corrected by adding a 'dbversion' field to the dns_clientinfo_t structure. [RT #35656] 3819. [bug] NSEC3 hashes need to be able to be entered and displayed without padding. This is not a issue for currently defined algorithms but may be for future hash algorithms. [RT #27925] 3818. [bug] Stop lying to the optimizer that 'void *arg' is a constant in isc_event_allocate. 3817. [func] The "delve" command is now spelled "delv" to avoid a namespace collision with the Xapian project. [RT #35801] 3816. [func] "dig +qr" now reports query size. (Thanks to Tony Finch.) [RT #35822] 3815. [doc] Clarify "nsupdate -y" usage in man page. [RT #35808] 3814. [func] The "masterfile-style" zone option controls the formatting of dumped zone files. Options are "relative" (multiline format) and "full" (one record per line). The default is "relative". [RT #20798] 3813. [func] "host" now recognizes the "timeout", "attempts" and "debug" options when set in /etc/resolv.conf. (Thanks to Adam Tkac at RedHat.) [RT #21885] 3812. [func] Dig now supports sending arbitrary EDNS options from the command line (+ednsopt=code[:value]). [RT #35584] 3811. [func] "serial-update-method date;" sets serial number on dynamic update to today's date in YYYYMMDDNN format. (Thanks to Bradley Forschinger.) [RT #24903] 3810. [bug] Work around broken nameservers that fail to ignore unknown EDNS options. [RT #35766] 3809. [doc] Fix SIT and NSID documentation. 3808. [doc] Clean up "prefetch" documentation. [RT #35751] 3807. [bug] Fix sign extension bug in dns_name_fromtext when lowercase is set. [RT #35743] 3806. [test] Improved system test portability. [RT #35625] 3805. [contrib] Added contrib/perftcpdns, a performance testing tool for DNS over TCP. [RT #35710] --- 9.10.0rc1 released --- 3804. [bug] Corrected a race condition in dispatch.c in which portentry could be reset leading to an assertion failure in socket_search(). (Change #3708 addressed the same issue but was incomplete.) [RT #35128] 3803. [bug] "named-checkconf -z" incorrectly rejected zones using alternate data sources for not having a "file" option. [RT #35685] 3802. [bug] Various header files were not being installed. 3801. [port] Fix probing for gssapi support on FreeBSD. [RT #35615] 3800. [bug] A pending event on the route socket could cause an assertion failure when shutting down named. [RT #35674] 3799. [bug] Improve named's command line error reporting. [RT #35603] 3798. [bug] 'rndc zonestatus' was reporting the wrong re-signing time. [RT #35659] 3797. [port] netbsd: geoip support probing was broken. [RT #35642] 3796. [bug] Register dns and pkcs#11 error codes. [RT #35629] 3795. [bug] Make named-checkconf detect raw masterfiles for hint zones and reject them. [RT #35268] 3794. [maint] Added AAAA for C.ROOT-SERVERS.NET. 3793. [bug] zone.c:save_nsec3param() could assert when out of memory. [RT #35621] 3792. [func] Provide links to the alternate statistics views when displaying in a browser. [RT #35605] 3791. [placeholder] 3790. [bug] Handle broken nameservers that send BADVERS in response to unknown EDNS options. Maintain statistics on BADVERS responses. 3789. [bug] Null pointer dereference on rbt creation failure. 3788. [bug] dns_peer_getrequestsit was returning request_nsid by mistake. --- 9.10.0b2 released --- 3787. [bug] The code that checks whether "auto-dnssec" is allowed was ignoring "allow-update" ACLs set at the options or view level. [RT #29536] 3786. [func] Provide more detailed error codes when using native PKCS#11. "pkcs11-tokens" now fails robustly rather than asserting when run against an HSM with an incomplete PKCS#11 API implementation. [RT #35479] 3785. [bug] Debugging code dumphex didn't accept arbitrarily long input (only compiled with -DDEBUG). [RT #35544] 3784. [bug] Using "rrset-order fixed" when it had not been enabled at compile time caused inconsistent results. It now works as documented, defaulting to cyclic mode. [RT #28104] 3783. [func] "tsig-keygen" is now available as an alternate command name for "ddns-confgen". It generates a TSIG key in named.conf format without comments. [RT #35503] 3782. [func] Specifying "auto" as the salt when using "rndc signing -nsec3param" causes named to generate a 64-bit salt at random. [RT #35322] 3781. [tuning] Use adaptive mutex locks when available; this has been found to improve performance under load on many systems. "configure --with-locktype=standard" restores conventional mutex locks. [RT #32576] 3780. [bug] $GENERATE handled negative numbers incorrectly. [RT #25528] 3779. [cleanup] Clarify the error message when using an option that was not enabled at compile time. [RT #35504] 3778. [bug] Log a warning when the wrong address family is used in "listen-on" or "listen-on-v6". [RT #17848] 3777. [bug] EDNS EXPIRE code could dump core when processing DLZ queries. [RT #35493] 3776. [func] "rndc -q" suppresses output from successful rndc commands. Errors are printed on stderr. [RT #21393] 3775. [bug] dlz_dlopen driver could return the wrong error code on API version mismatch, leading to a segfault. [RT #35495] 3774. [func] When using "request-nsid", log the NSID value in printable form as well as hex. [RT #20864] 3773. [func] "host", "nslookup" and "nsupdate" now have options to print the version number and exit. [RT #26057] 3772. [contrib] Added sqlite3 dynamically-loadable DLZ module. (Based in part on a contribution from Tim Tessier.) [RT #20822] 3771. [cleanup] Adjusted log level for "using built-in key" messages. [RT #24383] 3770. [bug] "dig +trace" could fail with an assertion when it needed to fall back to TCP due to a truncated response. [RT #24660] 3769. [doc] Improved documentation of "rndc signing -list". [RT #30652] 3768. [bug] "dnssec-checkds" was missing the SHA-384 digest algorithm. [RT #34000] 3767. [func] Log explicitly when using rndc.key to configure command channel. [RT #35316] 3766. [cleanup] Fixed problems with building outside the source tree when using native PKCS#11. [RT #35459] 3765. [bug] Fixed a bug in "rndc secroots" that could crash named when dumping an empty keynode. [RT #35469] 3764. [bug] The dnssec-keygen/settime -S and -i options (to set up a successor key and set the prepublication interval) were missing from dnssec-keyfromlabel. [RT #35394] 3763. [bug] delve: Cache DNSSEC records to avoid the need to re-fetch them when restarting validation. [RT #35476] 3762. [bug] Address build problems with --pkcs11-native + --with-openssl with ECDSA support. [RT #35467] 3761. [bug] Address dangling reference bug in dns_keytable_add. [RT #35471] 3760. [bug] Improve SIT with native PKCS#11 and on Windows. [RT #35433] 3759. [port] Enable delve on Windows. [RT #35441] 3758. [port] Enable export library APIs on Windows. [RT #35382] 3757. [port] Enable Python tools (dnssec-coverage, dnssec-checkds) to run on Windows. [RT #34355] 3756. [bug] GSSAPI Kerberos realm checking was broken in check_config leading to spurious messages being logged. [RT #35443] --- 9.10.0b1 released --- 3755. [func] Add stats counters for known EDNS options + others. [RT #35447] 3754. [cleanup] win32: Installer now places files in the Program Files area rather than system services. [RT #35361] 3753. [bug] allow-notify was ignoring keys. [RT #35425] 3752. [bug] Address potential REQUIRE failure if DNS_STYLEFLAG_COMMENTDATA is set when printing out a rdataset. 3751. [tuning] The default setting for the -U option (setting the number of UDP listeners per interface) has been adjusted to improve performance. [RT #35417] 3750. [experimental] Partially implement EDNS EXPIRE option as described in draft-andrews-dnsext-expire-00. Retrieval of the remaining time until expiry for slave zones is supported. EXPIRE uses an experimental option code (65002), which is subject to change. [RT #35416] 3749. [func] "dig +subnet" sends an EDNS client subnet option containing the specified address/prefix when querying. (Thanks to Wilmer van der Gaast.) [RT #35415] 3748. [test] Use delve to test dns_client interfaces. [RT #35383] 3747. [bug] A race condition could lead to a core dump when destroying a resolver fetch object. [RT #35385] 3746. [func] New "max-zone-ttl" option enforces maximum TTLs for zones. If loading a zone containing a higher TTL, the load fails. DDNS updates with higher TTLs are accepted but the TTL is truncated. (Note: Currently supported for master zones only; inline-signing slaves will be added.) [RT #38405] 3745. [func] "configure --with-tuning=large" adjusts various compiled-in constants and default settings to values suited to large servers with abundant memory. [RT #29538] 3744. [experimental] SIT: send and process Source Identity Tokens (similar to DNS Cookies by Donald Eastlake 3rd), which are designed to help clients detect off-path spoofed responses and for servers to identify legitimate clients. SIT uses an experimental EDNS option code (65001), which will be changed to an IANA-assigned value if the experiment is deemed a success. SIT can be enabled via "configure --enable-sit" (or --enable-developer). It is enabled by default in Windows. Servers can be configured to send smaller responses to clients that have not identified themselves via SIT. RRL processing has also been updated; legitimate clients are not subject to rate limiting. [RT #35389] 3743. [bug] delegation-only flag wasn't working in forward zone declarations despite being documented. This is needed to support turning off forwarding and turning on delegation only at the same name. [RT #35392] 3742. [port] linux: libcap support: declare curval at start of block. [RT #35387] 3741. [func] "delve" (domain entity lookup and validation engine): A new tool with dig-like semantics for performing DNS lookups, with internal DNSSEC validation, using the same resolver and validator logic as named. This allows easy validation of DNSSEC data in environments with untrustworthy resolvers, and assists with troubleshooting of DNSSEC problems. [RT #32406] 3740. [contrib] Minor fixes to configure --with-dlz-bdb, --with-dlz-postgres and --with-dlz-odbc. [RT #35340] 3739. [func] Added per-zone stats counters to track TCP and UDP queries. [RT #35375] 3738. [bug] --enable-openssl-hash failed to build. [RT #35343] 3737. [bug] 'rndc retransfer' could trigger a assertion failure with inline zones. [RT #35353] 3736. [bug] nsupdate: When specifying a server by name, fall back to alternate addresses if the first address for that name is not reachable. [RT #25784] 3735. [cleanup] Merged the libiscpk11 library into libisc to simplify dependencies. [RT #35205] 3734. [bug] Improve building with libtool. [RT #35314] 3733. [func] Improve interface scanning support. Interface information will be automatically updated if the OS supports routing sockets (MacOS, *BSD, Linux). Use "automatic-interface-scan no;" to disable. Add "rndc scan" to trigger a scan. [RT #23027] 3732. [contrib] Fixed a type mismatch causing the ODBC DLZ driver to dump core on 64-bit systems. [RT #35324] 3731. [func] Added a "no-case-compress" ACL, which causes named to use case-insensitive compression (disabling change #3645) for specified clients. (This is useful when dealing with broken client implementations that use case-sensitive name comparisons, rejecting responses that fail to match the capitalization of the query that was sent.) [RT #35300] 3730. [cleanup] Added "never" as a synonym for "none" when configuring key event dates in the dnssec tools. [RT #35277] 3729. [bug] dnssec-keygen could set the publication date incorrectly when only the activation date was specified on the command line. [RT #35278] 3728. [doc] Expanded native-PKCS#11 documentation, specifically pkcs11: URI labels. [RT #35287] 3727. [func] The isc_bitstring API is no longer used and has been removed from libisc. [RT #35284] 3726. [cleanup] Clarified the error message when attempting to configure more than 32 response-policy zones. [RT #35283] 3725. [contrib] Updated zkt and nslint to newest versions, cleaned up and rearranged the contrib directory, and added a README. --- 9.10.0a2 released --- 3724. [bug] win32: Fixed a bug that prevented dig and host from exiting properly after completing a UDP query. [RT #35288] 3723. [cleanup] Imported keys are now handled the same way regardless of DNSSEC algorithm. [RT #35215] 3722. [bug] Using geoip ACLs in a blackhole statement could cause a segfault. [RT #35272] 3721. [doc] Improved documentation of the EDNS processing enhancements introduced in change #3593. [RT #35275] 3720. [bug] Address compiler warnings. [RT #35261] 3719. [bug] Address memory leak in in peer.c. [RT #35255] 3718. [bug] A missing ISC_LINK_INIT in log.c. [RT #35260] 3717. [port] hpux: Treat EOPNOTSUPP as a expected error code when probing to see if it is possible to set dscp values on a per packet basis. [RT #35252] 3716. [bug] The dns_request code was setting dcsp values when not requested. [RT #35252] 3715. [bug] The region and city databases could fail to initialize when using some versions of libGeoIP, causing assertion failures when named was configured to use them. [RT #35427] 3714. [test] System tests that need to test for cryptography support before running can now use a common "testcrypto.sh" script to do so. [RT #35213] 3713. [bug] Save memory by not storing "also-notify" addresses in zone objects that are configured not to send notify requests. [RT #35195] 3712. [placeholder] 3711. [placeholder] 3710. [bug] Address double dns_zone_detach when switching to using automatic empty zones from regular zones. [RT #35177] 3709. [port] Use built-in versions of strptime() and timegm() on all platforms to avoid portability issues. [RT #35183] 3708. [bug] Address a portentry locking issue in dispatch.c. [RT #35128] 3707. [bug] irs_resconf_load now returns ISC_R_FILENOTFOUND on a missing resolv.conf file and initializes the structure as if it had been configured with: nameserver ::1 nameserver 127.0.0.1 Note: Callers will need to be updated to treat ISC_R_FILENOTFOUND as a qualified success or else they will leak memory. The following code fragment will work with both old and new versions without changing the behaviour of the existing code. resconf = NULL; result = irs_resconf_load(mctx, "/etc/resolv.conf", &resconf); if (result != ISC_SUCCESS) { if (resconf != NULL) irs_resconf_destroy(&resconf); .... } [RT #35194] 3706. [contrib] queryperf: Fixed a possible integer overflow when printing results. [RT #35182] 3705. [func] "configure --enable-native-pkcs11" enables BIND to use the PKCS#11 API for all cryptographic functions, so that it can drive a hardware service module directly without the need to use a modified OpenSSL as intermediary (so long as the HSM's vendor provides a complete-enough implementation of the PKCS#11 interface). This has been tested successfully with the Thales nShield HSM and with SoftHSMv2 from the OpenDNSSEC project. [RT #29031] 3704. [protocol] Accept integer timestamps in RRSIG records. [RT #35185] 3703. [func] To improve recursive resolver performance, cache records which are still being requested by clients can now be automatically refreshed from the authoritative server before they expire, reducing or eliminating the time window in which no answer is available in the cache. See the "prefetch" option for more details. [RT #35041] 3702. [func] 'dnssec-coverage -l' option specifies a length of time to check for coverage; events further into the future are ignored. 'dnssec-coverage -z' checks only ZSK events, and 'dnssec-coverage -k' checks only KSK events. (Thanks to Peter Palfrader.) [RT #35168] 3701. [func] named-checkconf can now obscure shared secrets when printing by specifying '-x'. [RT #34465] 3700. [func] Allow access to subgroups of XML statistics via special URLs http://:/xml/v3/server, /zones, /net, /tasks, /mem, and /status. [RT #35115] 3699. [bug] Improvements to statistics channel XSL stylesheet: the stylesheet can now be cached by the browser; section headers are omitted from the stats display when there is no data in those sections to be displayed; counters are now right-justified for easier readability. [RT #35117] 3698. [cleanup] Replaced all uses of memcpy() with memmove(). [RT #35120] 3697. [bug] Handle "." as a search list element when IDN support is enabled. [RT #35133] 3696. [bug] dig failed to handle AXFR style IXFR responses which span multiple messages. [RT #35137] 3695. [bug] Address a possible race in dispatch.c. [RT #35107] 3694. [bug] Warn when a key-directory is configured for a zone, but does not exist or is not a directory. [RT #35108] 3693. [security] memcpy was incorrectly called with overlapping ranges resulting in malformed names being generated on some platforms. This could cause INSIST failures when serving NSEC3 signed zones (CVE-2014-0591). [RT #35120] 3692. [bug] Two calls to dns_db_getoriginnode were fatal if there was no data at the node. [RT #35080] 3691. [contrib] Address null pointer dereference in LDAP and MySQL DLZ modules. 3690. [bug] Iterative responses could be missed when the source port for an upstream query was the same as the listener port (53). [RT #34925] 3689. [bug] Fixed a bug causing an insecure delegation from one static-stub zone to another to fail with a broken trust chain. [RT #35081] 3688. [bug] loadnode could return a freed node on out of memory. [RT #35106] 3687. [bug] Address null pointer dereference in zone_xfrdone. [RT #35042] 3686. [func] "dnssec-signzone -Q" drops signatures from keys that are still published but no longer active. [RT #34990] 3685. [bug] "rndc refresh" didn't work correctly with slave zones using inline-signing. [RT #35105] 3684. [bug] The list of included files would grow on reload. [RT 35090] 3683. [cleanup] Add a more detailed "not found" message to rndc commands which specify a zone name. [RT #35059] 3682. [bug] Correct the behavior of rndc retransfer to allow inline-signing slave zones to retain NSEC3 parameters instead of reverting to NSEC. [RT #34745] 3681. [port] Update the Windows build system to support feature selection and WIN64 builds. This is a work in progress. [RT #34160] 3680. [bug] Ensure buffer space is available in "rndc zonestatus". [RT #35084] 3679. [bug] dig could fail to clean up TCP sockets still waiting on connect(). [RT #35074] 3678. [port] Update config.guess and config.sub. [RT #35060] 3677. [bug] 'nsupdate' leaked memory if 'realm' was used multiple times. [RT #35073] 3676. [bug] "named-checkconf -z" now checks zones of type hint and redirect as well as master. [RT #35046] 3675. [misc] Provide a place for third parties to add version information for their extensions in the version file by setting the EXTENSIONS variable. --- 9.10.0a1 released --- 3674. [bug] RPZ zeroed ttls if the query type was '*'. [RT #35026] 3673. [func] New "in-view" zone option allows direct sharing of zones between views. [RT #32968] 3672. [func] Local address can now be specified when using dns_client API. [RT #34811] 3671. [bug] Don't allow dnssec-importkey overwrite a existing non-imported private key. 3670. [bug] Address read after free in server side of lwres_getrrsetbyname. [RT #29075] 3669. [port] freebsd: --with-gssapi needs -lhx509. [RT #35001] 3668. [bug] Fix cast in lex.c which could see 0xff treated as eof. [RT #34993] 3667. [test] dig: add support to keep the TCP socket open between successive queries (+[no]keepopen). [RT #34918] 3666. [func] Add a tool, named-rrchecker, for checking the syntax of individual resource records. This tool is intended to be called by provisioning systems so that the front end does not need to be upgraded to support new DNS record types. [RT #34778] 3665. [bug] Failure to release lock on error in receive_secure_db. [RT #34944] 3664. [bug] Updated OpenSSL PKCS#11 patches to fix active list locking and other bugs. [RT #34855] 3663. [bug] Address bugs in dns_rdata_fromstruct and dns_rdata_tostruct for WKS and ISDN types. [RT #34910] 3662. [bug] 'host' could die if a UDP query timed out. [RT #34870] 3661. [bug] Address lock order reversal deadlock with inline zones. [RT #34856] 3660. [cleanup] Changed the name of "isc-config.sh" to "bind9-config". [RT #23825] 3659. [port] solaris: don't add explicit dependencies/rules for python programs as make won't use the implicit rules. [RT #34835] 3658. [port] linux: Address platform specific compilation issue when libcap-devel is installed. [RT #34838] 3657. [port] Some readline clones don't accept NULL pointers when calling add_history. [RT #34842] 3656. [security] Treat an all zero netmask as invalid when generating the localnets acl. (The prior behavior could allow unexpected matches when using some versions of Winsock: CVE-2013-6320.) [RT #34687] 3655. [cleanup] Simplify TCP message processing when requesting a zone transfer. [RT #34825] 3654. [bug] Address race condition with manual notify requests. [RT #34806] 3653. [func] Create delegations for all "children" of empty zones except "forward first". [RT #34826] 3652. [bug] Address bug with rpz-drop policy. [RT #34816] 3651. [tuning] Adjust when a master server is deemed unreachable. [RT #27075] 3650. [tuning] Use separate rate limiting queues for refresh and notify requests. [RT #30589] 3649. [cleanup] Include a comment in .nzf files, giving the name of the associated view. [RT #34765] 3648. [test] Updated the ATF test framework to version 0.17. [RT #25627] 3647. [bug] Address a race condition when shutting down a zone. [RT #34750] 3646. [bug] Journal filename string could be set incorrectly, causing garbage in log messages. [RT #34738] 3645. [protocol] Use case sensitive compression when responding to queries. [RT #34737] 3644. [protocol] Check that EDNS subnet client options are well formed. [RT #34718] 3643. [doc] Clarify RRL "slip" documentation. 3642. [func] Allow externally generated DNSKEY to be imported into the DNSKEY management framework. A new tool dnssec-importkey is used to do this. [RT #34698] 3641. [bug] Handle changes to sig-validity-interval settings better. [RT #34625] 3640. [bug] ndots was not being checked when searching. Only continue searching on NXDOMAIN responses. Add the ability to specify ndots to nslookup. [RT #34711] 3639. [bug] Treat type 65533 (KEYDATA) as opaque except when used in a key zone. [RT #34238] 3638. [cleanup] Add the ability to handle ENOPROTOOPT in case it is encountered. [RT #34668] 3637. [bug] 'allow-query-on' was checking the source address rather than the destination address. [RT #34590] 3636. [bug] Automatic empty zones now behave better with forward only "zones" beneath them. [RT #34583] 3635. [bug] Signatures were not being removed from a zone with only KSK keys for a algorithm. [RT #34439] 3634. [func] Report build-id in rndc status. Report build-id when building from a git repository. [RT #20422] 3633. [cleanup] Refactor OPT processing in named to make it easier to support new EDNS options. [RT #34414] 3632. [bug] Signature from newly inactive keys were not being removed. [RT #32178] 3631. [bug] Remove spurious warning about missing signatures when qtype is SIG. [RT #34600] 3630. [bug] Ensure correct ID computation for MD5 keys. [RT #33033] 3629. [func] Allow the printing of cryptographic fields in DNSSEC records by dig to be suppressed (dig +nocrypto). [RT #34534] 3628. [func] Report DNSKEY key id's when dumping the cache. [RT #34533] 3627. [bug] RPZ changes were not effective on slaves. [RT #34450] 3626. [func] dig: NSID output now easier to read. [RT #21160] 3625. [bug] Don't send notify messages to machines outside of the test setup. 3624. [bug] Look for 'json_object_new_int64' when looking for a the json library. [RT #34449] 3623. [placeholder] 3622. [tuning] Eliminate an unnecessary lock when incrementing cache statistics. [RT #34339] 3621. [security] Incorrect bounds checking on private type 'keydata' can lead to a remotely triggerable REQUIRE failure (CVE-2013-4854). [RT #34238] 3620. [func] Added "rpz-client-ip" policy triggers, enabling RPZ responses to be configured on the basis of the client IP address; this can be used, for example, to blacklist misbehaving recursive or stub resolvers. [RT #33605] 3619. [bug] Fixed a bug in RPZ with "recursive-only no;" [RT #33776] 3618. [func] "rndc reload" now checks modification times of include files as well as master files to determine whether to skip reloading a zone. [RT #33936] 3617. [bug] Named was failing to answer queries during "rndc reload" [RT #34098] 3616. [bug] Change #3613 was incomplete. [RT #34177] 3615. [cleanup] "configure" now finishes by printing a summary of optional BIND features and whether they are active or inactive. ("configure --enable-full-report" increases the verbosity of the summary.) [RT #31777] 3614. [port] Check for . [RT #34162] 3613. [bug] named could crash when deleting inline-signing zones with "rndc delzone". [RT #34066] 3612. [port] Check whether to use -ljson or -ljson-c. [RT #34115] 3611. [bug] Improved resistance to a theoretical authentication attack based on differential timing. [RT #33939] 3610. [cleanup] win32: Some executables had been omitted from the installer. [RT #34116] 3609. [bug] Corrected a possible deadlock in applications using the export version of the isc_app API. [RT #33967] 3608. [port] win32: added todos.pl script to ensure all text files the win32 build depends on are converted to DOS newline format. [RT #22067] 3607. [bug] dnssec-keygen had broken 'Invalid keyfile' error message. [RT #34045] 3606. [func] "rndc flushtree" now flushes matching records in the address database and bad cache as well as the DNS cache. (Previously only the DNS cache was flushed.) [RT #33970] 3605. [port] win32: Addressed several compatibility issues with newer versions of Visual Studio. [RT #33916] 3604. [bug] Fixed a compile-time error when building with JSON but not XML. [RT #33959] 3603. [bug] Install . [RT #33956] 3602. [contrib] Added DLZ Perl module, allowing Perl scripts to integrate with named and serve DNS data. (Contributed by John Eaglesham of Yahoo.) 3601. [bug] Added to PKCS#11 openssl patches a value len attribute in DH derive key. [RT #33928] 3600. [cleanup] dig: Fixed a typo in the warning output when receiving an oversized response. [RT #33910] 3599. [tuning] Check for pointer equivalence in name comparisons. [RT #18125] 3598. [cleanup] Improved portability of map file code. [RT #33820] 3597. [bug] Ensure automatic-resigning heaps are reconstructed when loading zones in map format. [RT #33381] 3596. [port] Updated win32 build documentation, added dnssec-verify. [RT #22067] 3595. [port] win32: Fix build problems introduced by change #3550. [RT #33807] 3594. [maint] Update config.guess and config.sub. [RT #33816] 3593. [func] Update EDNS processing to better track remote server capabilities. [RT #30655] 3592. [doc] Moved documentation of rndc command options to the rndc man page. [RT #33506] 3591. [func] Use CRC-64 to detect map file corruption at load time. [RT #33746] 3590. [bug] When using RRL on recursive servers, defer rate-limiting until after recursion is complete; also, use correct rcode for slipped NXDOMAIN responses. [RT #33604] 3589. [func] Report serial numbers in when starting zone transfers. Report accepted NOTIFY requests including serial. [RT #33037] 3588. [bug] dig: addressed a memory leak in the sigchase code that could cause a shutdown crash. [RT #33733] 3587. [func] 'named -g' now checks the logging configuration but does not use it. [RT #33473] 3586. [bug] Handle errors in xmlDocDumpFormatMemoryEnc. [RT #33706] 3585. [func] "rndc delzone -clean" option removes zone files when deleting a zone. [RT #33570] 3584. [security] Caching data from an incompletely signed zone could trigger an assertion failure in resolver.c (CVE-2013-3919). [RT #33690] 3583. [bug] Address memory leak in GSS-API processing [RT #33574] 3582. [bug] Silence false positive warning regarding missing file directive for inline slave zones. [RT #33662] 3581. [bug] Changed the tcp-listen-queue default to 10. [RT #33029] 3580. [bug] Addressed a possible race in acache.c [RT #33602] 3579. [maint] Updates to PKCS#11 openssl patches, supporting versions 0.9.8y, 1.0.0k, 1.0.1e [RT #33463] 3578. [bug] 'rndc -c file' now fails if 'file' does not exist. [RT #33571] 3577. [bug] Handle zero TTL values better. [RT #33411] 3576. [bug] Address a shutdown race when validating. [RT #33573] 3575. [func] Changed the logging category for RRL events from 'queries' to 'query-errors'. [RT #33540] 3574. [doc] The 'hostname' keyword was missing from server-id description in the named.conf man page. [RT #33476] 3573. [bug] "rndc addzone" and "rndc delzone" incorrectly handled zone names containing punctuation marks and other nonstandard characters. [RT #33419] 3572. [func] Threads are now enabled by default on most operating systems. [RT #25483] 3571. [bug] Address race condition in dns_client_startresolve(). [RT #33234] 3570. [bug] Check internal pointers are valid when loading map files. [RT #33403] 3569. [contrib] Ported mysql DLZ driver to dynamically-loadable module, and added multithread support. [RT #33394] 3568. [cleanup] Add a product description line to the version file, to be reported by named -v/-V. [RT #33366] 3567. [bug] Silence clang static analyzer warnings. [RT #33365] 3566. [func] Log when forwarding updates to master. [RT #33240] 3565. [placeholder] 3564. [bug] Improved handling of corrupted map files. [RT #33380] 3563. [contrib] zone2sqlite failed with some table names. [RT #33375] 3562. [func] Update map file header format to include a SHA-1 hash of the database content, so that corrupted map files can be rejected at load time. [RT #32459] 3561. [bug] dig: issue a warning if an EDNS query returns FORMERR or NOTIMP. Adjust usage message. [RT #33363] 3560. [bug] isc-config.sh did not honor includedir and libdir when set via configure. [RT #33345] 3559. [func] Check that both forms of Sender Policy Framework records exist or do not exist. [RT #33355] 3558. [bug] IXFR of a DLZ stored zone was broken. [RT #33331] 3557. [bug] Reloading redirect zones was broken. [RT #33292] 3556. [maint] Added AAAA for D.ROOT-SERVERS.NET. 3555. [bug] Address theoretical race conditions in acache.c (change #3553 was incomplete). [RT #33252] 3554. [bug] RRL failed to correctly rate-limit upward referrals and failed to count dropped error responses in the statistics. [RT #33225] 3553. [bug] Address suspected double free in acache. [RT #33252] 3552. [bug] Wrong getopt option string for 'nsupdate -r'. [RT #33280] 3551. [bug] resolver.querydscp[46] were uninitialized. [RT #32686] 3550. [func] Unified the internal and export versions of the BIND libraries, allowing external clients to use the same libraries as BIND. [RT #33131] 3549. [doc] Documentation for "request-nsid" was missing. [RT #33153] 3548. [bug] The NSID request code in resolver.c was broken resulting in invalid EDNS options being sent. [RT #33153] 3547. [bug] Some malformed unknown rdata records were not properly detected and rejected. [RT #33129] 3546. [func] Add EUI48 and EUI64 types. [RT #33082] 3545. [bug] RRL slip behavior was incorrect when set to 1. [RT #33111] 3544. [contrib] check5011.pl: Script to report the status of managed keys as recorded in managed-keys.bind. Contributed by Tony Finch 3543. [bug] Update socket structure before attaching to socket manager after accept. [RT #33084] 3542. [placeholder] 3541. [bug] Parts of libdns were not properly initialized when built in libexport mode. [RT #33028] 3540. [test] libt_api: t_info and t_assert were not thread safe. 3539. [port] win32: timestamp format didn't match other platforms. 3538. [test] Running "make test" now requires loopback interfaces to be set up. [RT #32452] 3537. [tuning] Slave zones, when updated, now send NOTIFY messages to peers before being dumped to disk rather than after. [RT #27242] 3536. [func] Add support for setting Differentiated Services Code Point (DSCP) values in named. Most configuration options which take a "port" option (e.g., listen-on, forwarders, also-notify, masters, notify-source, etc) can now also take a "dscp" option specifying a code point for use with outgoing traffic, if supported by the underlying OS. [RT #27596] 3535. [bug] Minor win32 cleanups. [RT #32962] 3534. [bug] Extra text after an embedded NULL was ignored when parsing zone files. [RT #32699] 3533. [contrib] query-loc-0.4.0: memory leaks. [RT #32960] 3532. [contrib] zkt: fixed buffer overrun, resource leaks. [RT #32960] 3531. [bug] win32: A uninitialized value could be returned on out of memory. [RT #32960] 3530. [contrib] Better RTT tracking in queryperf. [RT #30128] 3529. [func] Named now listens on both IPv4 and IPv6 interfaces by default. Named previously only listened on IPv4 interfaces by default unless named was running in IPv6 only mode. [RT #32945] 3528. [func] New "dnssec-coverage" command scans the timing metadata for a set of DNSSEC keys and reports if a lapse in signing coverage has been scheduled inadvertently. (Note: This tool depends on python; it will not be built or installed on systems that do not have a python interpreter.) [RT #28098] 3527. [compat] Add a URI to allow applications to explicitly request a particular XML schema from the statistics channel, returning 404 if not supported. [RT #32481] 3526. [cleanup] Set up dependencies for unit tests correctly during build. [RT #32803] 3525. [func] Support for additional signing algorithms in rndc: hmac-sha1, -sha224, -sha256, -sha384, and -sha512. The -A option to rndc-confgen can be used to select the algorithm for the generated key. (The default is still hmac-md5; this may change in a future release.) [RT #20363] 3524. [func] Added an alternate statistics channel in JSON format, when the server is built with the json-c library: http://[address]:[port]/json. [RT #32630] 3523. [contrib] Ported filesystem and ldap DLZ drivers to dynamically-loadable modules, and added the "wildcard" module based on a contribution from Vadim Goncharov . [RT #23569] 3522. [bug] DLZ lookups could fail to return SERVFAIL when they ought to. [RT #32685] 3521. [bug] Address memory leak in opensslecdsa_link.c. [RT #32249] 3520. [bug] 'mctx' was not being referenced counted in some places where it should have been. [RT #32794] 3519. [func] Full replay protection via four-way handshake is now mandatory for rndc clients. Very old versions of rndc will no longer work. [RT #32798] 3518. [bug] Increase the size of dns_rrl_key.s.rtype by one bit so that all dns_rrl_rtype_t enum values fit regardless of whether it is teated as signed or unsigned by the compiler. [RT #32792] 3517. [bug] Reorder destruction to avoid shutdown race. [RT #32777] 3516. [placeholder] 3515. [port] '%T' is not portable in strftime(). [RT #32763] 3514. [bug] The ranges for valid key sizes in ddns-confgen and rndc-confgen were too constrained. Keys up to 512 bits are now allowed for most algorithms, and up to 1024 bits for hmac-sha384 and hmac-sha512. [RT #32753] 3513. [func] "dig -u" prints times in microseconds rather than milliseconds. [RT #32704] 3512. [func] "rndc validation check" reports the current status of DNSSEC validation. [RT #21397] 3511. [doc] Improve documentation of redirect zones. [RT #32756] 3510. [func] "rndc status" and XML statistics channel now report server start and reconfiguration times. [RT #21048] 3509. [cleanup] Added a product line to version file to allow for easy naming of different products (BIND vs BIND ESV, for example). [RT #32755] 3508. [contrib] queryperf was incorrectly rejecting the -T option. [RT #32338] 3507. [bug] Statistics channel XSL had a glitch when attempting to chart query data before any queries had been received. [RT #32620] 3506. [func] When setting "max-cache-size" and "max-acache-size", the keyword "unlimited" is no longer defined as equal to 4 gigabytes (except on 32-bit platforms); it means literally unlimited. [RT #32358] 3505. [bug] When setting "max-cache-size" and "max-acache-size", larger values than 4 gigabytes could not be set explicitly, though larger sizes were available when setting cache size to 0. This has been corrected; the full range is now available. [RT #32358] 3504. [func] Add support for ACLs based on geographic location, using MaxMind GeoIP databases. Based on code contributed by Ken Brownfield . [RT #30681] 3503. [doc] Clarify size_spec syntax. [RT #32449] 3502. [func] zone-statistics: "no" is now a synonym for "none", instead of "terse". [RT #29165] 3501. [func] zone-statistics now takes three options: full, terse, and none. "yes" and "no" are retained as synonyms for full and terse, respectively. [RT #29165] 3500. [security] Support NAPTR regular expression validation on all platforms without using libregex, which can be vulnerable to memory exhaustion attack (CVE-2013-2266). [RT #32688] 3499. [doc] Corrected ARM documentation of built-in zones. [RT #32694] 3498. [bug] zone statistics for zones which matched a potential empty zone could have their zone-statistics setting overridden. 3497. [func] When deleting a slave/stub zone using 'rndc delzone' report the files that were being used so they can be cleaned up if desired. [RT #27899] 3496. [placeholder] 3495. [func] Support multiple response-policy zones (up to 32), while improving RPZ performance. "response-policy" syntax now includes a "min-ns-dots" clause, with default 1, to exclude top-level domains from NSIP and NSDNAME checking. --enable-rpz-nsip and --enable-rpz-nsdname are now the default. [RT #32251] 3494. [func] DNS RRL: Blunt the impact of DNS reflection and amplification attacks by rate-limiting substantially- identical responses. [RT #28130] 3493. [contrib] Added BDBHPT dynamically-loadable DLZ module, contributed by Mark Goldfinch. [RT #32549] 3492. [bug] Fixed a regression in zone loading performance due to lock contention. [RT #30399] 3491. [bug] Slave zones using inline-signing must specify a file name. [RT #31946] 3490. [bug] When logging RDATA during update, truncate if it's too long. [RT #32365] 3489. [bug] --enable-developer now turns on ISC_LIST_CHECKINIT. dns_dlzcreate() failed to properly initialize dlzdb.link. When cloning a rdataset do not copy the link contents. [RT #32651] 3488. [bug] Use after free error with DH generated keys. [RT #32649] 3487. [bug] Change 3444 was not complete. There was a additional place where the NOQNAME proof needed to be saved. [RT #32629] 3486. [bug] named could crash when using TKEY-negotiated keys that had been deleted and then recreated. [RT #32506] 3485. [cleanup] Only compile openssl_gostlink.c if we support GOST. 3484. [bug] Some statistics were incorrectly rendered in XML. [RT #32587] 3483. [placeholder] 3482. [func] dig +nssearch now prints name servers that don't have address records (missing AAAA or A, or the name doesn't exist). [RT #29348] 3481. [cleanup] Removed use of const const in atf. 3480. [bug] Silence logging noise when setting up zone statistics. [RT #32525] 3479. [bug] Address potential memory leaks in gssapi support code. [RT #32405] 3478. [port] Fix a build failure in strict C99 environments [RT #32475] 3477. [func] Expand logging when adding records via DDNS update [RT #32365] 3476. [bug] "rndc zonestatus" could report a spurious "not found" error on inline-signing zones. [RT #29226] 3475. [cleanup] Changed name of 'map' zone file format (previously 'fast'). [RT #32458] 3474. [bug] nsupdate could assert when the local and remote address families didn't match. [RT #22897] 3473. [bug] dnssec-signzone/verify could incorrectly report an error condition due to an empty node above an opt-out delegation lacking an NSEC3. [RT #32072] 3472. [bug] The active-connections counter in the socket statistics could underflow. [RT #31747] 3471. [bug] The number of UDP dispatches now defaults to the number of CPUs even if -n has been set to a higher value. [RT #30964] 3470. [bug] Slave zones could fail to dump when successfully refreshing after an initial failure. [RT #31276] 3469. [bug] Handle DLZ lookup failures more gracefully. Improve backward compatibility between versions of DLZ dlopen API. [RT #32275] 3468. [security] RPZ rules to generate A records (but not AAAA records) could trigger an assertion failure when used in conjunction with DNS64 (CVE-2012-5689). [RT #32141] 3467. [bug] Added checks in dnssec-keygen and dnssec-settime to check for delete date < inactive date. [RT #31719] 3466. [contrib] Corrected the DNS_CLIENTINFOMETHODS_VERSION check in DLZ example driver. [RT #32275] 3465. [bug] Handle isolated reserved ports. [RT #31778] 3464. [maint] Updates to PKCS#11 openssl patches, supporting versions 0.9.8x, 1.0.0j, 1.0.1c [RT #29749] 3463. [doc] Clarify managed-keys syntax in ARM. [RT #32232] 3462. [doc] Clarify server selection behavior of dig when using -4 or -6 options. [RT #32181] 3461. [bug] Negative responses could incorrectly have AD=1 set. [RT #32237] 3460. [bug] Only link against readline where needed. [RT #29810] 3459. [func] Added -J option to named-checkzone/named-compilezone to specify the path to the journal file. [RT #30958] 3458. [bug] Return FORMERR when presented with a overly long domain named in a request. [RT #29682] 3457. [protocol] Add ILNP records (NID, LP, L32, L64). [RT #31836] 3456. [port] g++47: ATF failed to compile. [RT #32012] 3455. [contrib] queryperf: fix getopt option list. [RT #32338] 3454. [port] sparc64: improve atomic support. [RT #25182] 3453. [bug] 'rndc addzone' of a zone with 'inline-signing yes;' failed. [RT #31960] 3452. [bug] Accept duplicate singleton records. [RT #32329] 3451. [port] Increase per thread stack size from 64K to 1M. [RT #32230] 3450. [bug] Stop logfileconfig system test spam system logs. [RT #32315] 3449. [bug] gen.c: use the pre-processor to construct format strings so that compiler can perform sanity checks; check the snprintf results. [RT #17576] 3448. [bug] The allow-query-on ACL was not processed correctly. [RT #29486] 3447. [port] Add support for libxml2-2.9.x [RT #32231] 3446. [port] win32: Add source ID (see change #3400) to build. [RT #31683] 3445. [bug] Warn about zone files with blank owner names immediately after $ORIGIN directives. [RT #31848] 3444. [bug] The NOQNAME proof was not being returned from cached insecure responses. [RT #21409] 3443. [bug] ddns-confgen: Some TSIG algorithms were incorrectly rejected when generating keys. [RT #31927] 3442. [port] Net::DNS 0.69 introduced a non backwards compatible change. [RT #32216] 3441. [maint] D.ROOT-SERVERS.NET is now 199.7.91.13. 3440. [bug] Reorder get_key_struct to not trigger a assertion when cleaning up due to out of memory error. [RT #32131] 3439. [placeholder] 3438. [bug] Don't accept unknown data escape in quotes. [RT #32031] 3437. [bug] isc_buffer_init -> isc_buffer_constinit to initialize buffers with constant data. [RT #32064] 3436. [bug] Check malloc/calloc return values. [RT #32088] 3435. [bug] Cross compilation support in configure was broken. [RT #32078] 3434. [bug] Pass client info to the DLZ findzone() entry point in addition to lookup(). This makes it possible for a database to answer differently whether it's authoritative for a name depending on the address of the client. [RT #31775] 3433. [bug] dlz_findzone() did not correctly handle ISC_R_NOMORE. [RT #31172] 3432. [func] Multiple DLZ databases can now be configured. DLZ databases are searched in the order configured, unless set to "search no", in which case a zone can be configured to be retrieved from a particular DLZ database by using a "dlz " option in the zone statement. DLZ databases can support type "master" and "redirect" zones. [RT #27597] 3431. [bug] ddns-confgen: Some valid key algorithms were not accepted. [RT #31927] 3430. [bug] win32: isc_time_formatISO8601 was missing the 'T' between the date and time. [RT #32044] 3429. [bug] dns_zone_getserial2 could a return success without returning a valid serial. [RT #32007] 3428. [cleanup] dig: Add timezone to date output. [RT #2269] 3427. [bug] dig +trace incorrectly displayed name server addresses instead of names. [RT #31641] 3426. [bug] dnssec-checkds: Clearer output when records are not found. [RT #31968] 3425. [bug] "acacheentry" reference counting was broken resulting in use after free. [RT #31908] 3424. [func] dnssec-dsfromkey now emits the hash without spaces. [RT #31951] 3423. [bug] "rndc signing -nsec3param" didn't accept the full range of possible values. Address portability issues. [RT #31938] 3422. [bug] Added a clear error message for when the SOA does not match the referral. [RT #31281] 3421. [bug] Named loops when re-signing if all keys are offline. [RT #31916] 3420. [bug] Address VPATH compilation issues. [RT #31879] 3419. [bug] Memory leak on validation cancel. [RT #31869] 3418. [func] New XML schema (version 3.0) for the statistics channel adds query type statistics at the zone level, and flattens the XML tree and uses compressed format to optimize parsing. Includes new XSL that permits charting via the Google Charts API on browsers that support javascript in XSL. The old XML schema has been deprecated. [RT #30023] 3417. [placeholder] 3416. [bug] Named could die on shutdown if running with 128 UDP dispatches per interface. [RT #31743] 3415. [bug] named could die with a REQUIRE failure if a validation was canceled. [RT #31804] 3414. [bug] Address locking issues found by Coverity. [RT #31626] 3413. [func] Record the number of DNS64 AAAA RRsets that have been synthesized. [RT #27636] 3412. [bug] Copy timeval structure from control message data. [RT #31548] 3411. [tuning] Use IPV6_USE_MIN_MTU or equivalent with TCP in addition to UDP. [RT #31690] 3410. [bug] Addressed Coverity warnings. [RT #31626] 3409. [contrib] contrib/dane/mkdane.sh: Tool to generate TLSA RR's from X.509 certificates, for use with DANE (DNS-based Authentication of Named Entities). [RT #30513] 3408. [bug] Some DNSSEC-related options (update-check-ksk, dnssec-loadkeys-interval, dnssec-dnskey-kskonly) are now legal in slave zones as long as inline-signing is in use. [RT #31078] 3407. [placeholder] 3406. [bug] mem.c: Fix compilation errors when building with ISC_MEM_TRACKLINES or ISC_MEMPOOL_NAMES disabled. Also, ISC_MEM_DEBUG is no longer optional. [RT #31559] 3405. [bug] Handle time going backwards in acache. [RT #31253] 3404. [bug] dnssec-signzone: When re-signing a zone, remove RRSIG and NSEC records from nodes that used to be in-zone but are now below a zone cut. [RT #31556] 3403. [bug] Silence noisy OpenSSL logging. [RT #31497] 3402. [test] The IPv6 interface numbers used for system tests were incorrect on some platforms. [RT #25085] 3401. [bug] Addressed Coverity warnings. [RT #31484] 3400. [cleanup] "named -V" can now report a source ID string, defined in the "srcid" file in the build tree and normally set to the most recent git hash. [RT #31494] 3399. [port] netbsd: rename 'bool' parameter to avoid namespace clash. [RT #31515] 3398. [bug] SOA parameters were not being updated with inline signed zones if the zone was modified while the server was offline. [RT #29272] 3397. [bug] dig crashed when using +nssearch with +tcp. [RT #25298] 3396. [bug] OPT records were incorrectly removed from signed, truncated responses. [RT #31439] 3395. [protocol] Add RFC 6598 reverse zones to built in empty zones list, 64.100.IN-ADDR.ARPA ... 127.100.IN-ADDR.ARPA. [RT #31336] 3394. [bug] Adjust 'successfully validated after lower casing signer' log level and category. [RT #31414] 3393. [bug] 'host -C' could core dump if REFUSED was received. [RT #31381] 3392. [func] Keep statistics on REFUSED responses. [RT #31412] 3391. [bug] A DNSKEY lookup that encountered a CNAME failed. [RT #31262] 3390. [bug] Silence clang compiler warnings. [RT #30417] 3389. [bug] Always return NOERROR (not 0) in TSIG. [RT #31275] 3388. [bug] Fixed several Coverity warnings. Note: This change includes a fix for a bug that was subsequently determined to be an exploitable security vulnerability, CVE-2012-5688: named could die on specific queries with dns64 enabled. [RT #30996] 3387. [func] DS digest can be disabled at runtime with disable-ds-digests. [RT #21581] 3386. [bug] Address locking violation when generating new NSEC / NSEC3 chains. [RT #31224] 3385. [bug] named-checkconf didn't detect missing master lists in also-notify clauses. [RT #30810] 3384. [bug] Improved logging of crypto errors. [RT #30963] 3383. [security] A certain combination of records in the RBT could cause named to hang while populating the additional section of a response. [RT #31090] 3382. [bug] SOA query from slave used use-v6-udp-ports range, if set, regardless of the address family in use. [RT #24173] 3381. [contrib] Update queryperf to support more RR types. [RT #30762] 3380. [bug] named could die if a nonexistent master list was referenced in a also-notify. [RT #31004] 3379. [bug] isc_interval_zero and isc_time_epoch should be "const (type)* const". [RT #31069] 3378. [bug] Handle missing 'managed-keys-directory' better. [RT #30625] 3377. [bug] Removed spurious newline from NSEC3 multiline output. [RT #31044] 3376. [bug] Lack of EDNS support was being recorded without a successful response. [RT #30811] 3375. [bug] 'rndc dumpdb' failed on empty caches. [RT #30808] 3374. [bug] isc_parse_uint32 failed to return a range error on systems with 64 bit longs. [RT #30232] 3373. [bug] win32: open raw files in binary mode. [RT #30944] 3372. [bug] Silence spurious "deleted from unreachable cache" messages. [RT #30501] 3371. [bug] AD=1 should behave like DO=1 when deciding whether to add NS RRsets to the additional section or not. [RT #30479] 3370. [bug] Address use after free while shutting down. [RT #30241] 3369. [bug] nsupdate terminated unexpectedly in interactive mode if built with readline support. [RT #29550] 3368. [bug] , and were not C++ safe. 3367. [bug] dns_dnsseckey_create() result was not being checked. [RT #30685] 3366. [bug] Fixed Read-After-Write dependency violation for IA64 atomic operations. [RT #25181] 3365. [bug] Removed spurious newlines from log messages in zone.c [RT #30675] 3364. [security] Named could die on specially crafted record. [RT #30416] 3363. [bug] Need to allow "forward" and "fowarders" options in static-stub zones; this had been overlooked. [RT #30482] 3362. [bug] Setting some option values to 0 in named.conf could trigger an assertion failure on startup. [RT #27730] 3361. [bug] "rndc signing -nsec3param" didn't work correctly when salt was set to '-' (no salt). [RT #30099] 3360. [bug] 'host -w' could die. [RT #18723] 3359. [bug] An improperly-formed TSIG secret could cause a memory leak. [RT #30607] 3358. [placeholder] 3357. [port] Add support for libxml2-2.8.x [RT #30440] 3356. [bug] Cap the TTL of signed RRsets when RRSIGs are approaching their expiry, so they don't remain in caches after expiry. [RT #26429] 3355. [port] Use more portable awk in verify system test. 3354. [func] Improve OpenSSL error logging. [RT #29932] 3353. [bug] Use a single task for task exclusive operations. [RT #29872] 3352. [bug] Ensure that learned server attributes timeout of the adb cache. [RT #29856] 3351. [bug] isc_mem_put and isc_mem_putanddetach didn't report caller if either ISC_MEM_DEBUGSIZE or ISC_MEM_DEBUGCTX memory debugging flags are set. [RT #30243] 3350. [bug] Memory read overrun in isc___mem_reallocate if ISC_MEM_DEBUGCTX memory debugging flag is set. [RT #30240] 3349. [bug] Change #3345 was incomplete. [RT #30233] 3348. [bug] Prevent RRSIG data from being cached if a negative record matching the covering type exists at a higher trust level. Such data already can't be retrieved from the cache since change 3218 -- this prevents it being inserted into the cache as well. [RT #26809] 3347. [bug] dnssec-settime: Issue a warning when writing a new private key file would cause a change in the permissions of the existing file. [RT #27724] 3346. [security] Bad-cache data could be used before it was initialized, causing an assert. [RT #30025] 3345. [bug] Addressed race condition when removing the last item or inserting the first item in an ISC_QUEUE. [RT #29539] 3344. [func] New "dnssec-checkds" command checks a zone to determine which DS records should be published in the parent zone, or which DLV records should be published in a DLV zone, and queries the DNS to ensure that it exists. (Note: This tool depends on python; it will not be built or installed on systems that do not have a python interpreter.) [RT #28099] 3343. [placeholder] 3342. [bug] Change #3314 broke saving of stub zones to disk resulting in excessive cpu usage in some cases. [RT #29952] 3341. [func] New "dnssec-verify" command checks a signed zone to ensure correctness of signatures and of NSEC/NSEC3 chains. [RT #23673] 3340. [func] Added new 'map' zone file format, which is an image of a zone database that can be loaded directly into memory via mmap(), allowing much faster zone loading. (Note: Because of pointer sizes and other considerations, this file format is platform-dependent; 'map' zone files cannot always be transferred from one server to another.) [RT #25419] 3339. [func] Allow the maximum supported rsa exponent size to be specified: "max-rsa-exponent-size ;" [RT #29228] 3338. [bug] Address race condition in units tests: asyncload_zone and asyncload_zt. [RT #26100] 3337. [bug] Change #3294 broke support for the multiple keys in controls. [RT #29694] 3336. [func] Maintain statistics for RRsets tagged as "stale". [RT #29514] 3335. [func] nslookup: return a nonzero exit code when unable to get an answer. [RT #29492] 3334. [bug] Hold a zone table reference while performing a asynchronous load of a zone. [RT #28326] 3333. [bug] Setting resolver-query-timeout too low can cause named to not recover if it loses connectivity. [RT #29623] 3332. [bug] Re-use cached DS rrsets if possible. [RT #29446] 3331. [security] dns_rdataslab_fromrdataset could produce bad rdataslabs. [RT #29644] 3330. [func] Fix missing signatures on NOERROR results despite RPZ rewriting. Also - add optional "recursive-only yes|no" to the response-policy statement - add optional "max-policy-ttl" to the response-policy statement to limit the false data that "recursive-only no" can introduce into resolvers' caches - add a RPZ performance test to bin/tests/system/rpz when queryperf is available. - the encoding of PASSTHRU action to "rpz-passthru". (The old encoding is still accepted.) [RT #26172] 3329. [bug] Handle RRSIG signer-name case consistently: We generate RRSIG records with the signer-name in lower case. We accept them with any case, but if they fail to validate, we try again in lower case. [RT #27451] 3328. [bug] Fixed inconsistent data checking in dst_parse.c. [RT #29401] 3327. [func] Added 'filter-aaaa-on-v6' option; this is similar to 'filter-aaaa-on-v4' but applies to IPv6 connections. (Use "configure --enable-filter-aaaa" to enable this option.) [RT #27308] 3326. [func] Added task list statistics: task model, worker threads, quantum, tasks running, tasks ready. [RT #27678] 3325. [func] Report cache statistics: memory use, number of nodes, number of hash buckets, hit and miss counts. [RT #27056] 3324. [test] Add better tests for ADB stats [RT #27057] 3323. [func] Report the number of buckets the resolver is using. [RT #27020] 3322. [func] Monitor the number of active TCP and UDP dispatches. [RT #27055] 3321. [func] Monitor the number of recursive fetches and the number of open sockets, and report these values in the statistics channel. [RT #27054] 3320. [func] Added support for monitoring of recursing client count. [RT #27009] 3319. [func] Added support for monitoring of ADB entry count and hash size. [RT #27057] 3318. [tuning] Reduce the amount of work performed while holding a bucket lock when finished with a fetch context. [RT #29239] 3317. [func] Add ECDSA support (RFC 6605). [RT #21918] 3316. [tuning] Improved locking performance when recursing. [RT #28836] 3315. [tuning] Use multiple dispatch objects for sending upstream queries; this can improve performance on busy multiprocessor systems by reducing lock contention. [RT #28605] 3314. [bug] The masters list could be updated while stub_callback or refresh_callback were using it. [RT #26732] 3313. [protocol] Add TLSA record type. [RT #28989] 3312. [bug] named-checkconf didn't detect a bad dns64 clients acl. [RT #27631] 3311. [bug] Abort the zone dump if zone->db is NULL in zone.c:zone_gotwritehandle. [RT #29028] 3310. [test] Increase table size for mutex profiling. [RT #28809] 3309. [bug] resolver.c:fctx_finddone() was not thread safe. [RT #27995] 3308. [placeholder] 3307. [bug] Add missing ISC_LANG_BEGINDECLS and ISC_LANG_ENDDECLS. [RT #28956] 3306. [bug] Improve DNS64 reverse zone performance. [RT #28563] 3305. [func] Add wire format lookup method to sdb. [RT #28563] 3304. [bug] Use hmctx, not mctx when freeing rbtdb->heaps. [RT #28571] 3303. [bug] named could die when reloading. [RT #28606] 3302. [bug] dns_dnssec_findmatchingkeys could fail to find keys if the zone name contained character that required special mappings. [RT #28600] 3301. [contrib] Update queryperf to build on darwin. Add -R flag for non-recursive queries. [RT #28565] 3300. [bug] Named could die if gssapi was enabled in named.conf but was not compiled in. [RT #28338] 3299. [bug] Make SDB handle errors from database drivers better. [RT #28534] 3298. [bug] Named could dereference a NULL pointer in zmgr_start_xfrin_ifquota if the zone was being removed. [RT #28419] 3297. [bug] Named could die on a malformed master file. [RT #28467] 3296. [bug] Named could die with a INSIST failure in client.c:exit_check. [RT #28346] 3295. [bug] Adjust isc_time_secondsastimet range check to be more portable. [RT # 26542] 3294. [bug] isccc/cc.c:table_fromwire failed to free alist on error. [RT #28265] 3293. [func] nsupdate: list supported type. [RT #28261] 3292. [func] Log messages in the axfr stream at debug 10. [RT #28040] 3291. [port] Fixed a build error on systems without ENOTSUP. [RT #28200] 3290. [bug] was not being installed. [RT #28169] 3289. [bug] 'rndc retransfer' failed for inline zones. [RT #28036] 3288. [bug] dlz_destroy() function wasn't correctly registered by the DLZ dlopen driver. [RT #28056] 3287. [port] Update ans.pl to work with Net::DNS 0.68. [RT #28028] 3286. [bug] Managed key maintenance timer could fail to start after 'rndc reconfig'. [RT #26786] 3285. [bug] val-frdataset was incorrectly disassociated in proveunsecure after calling startfinddlvsep. [RT #27928] 3284. [bug] Address race conditions with the handling of rbtnode.deadlink. [RT #27738] 3283. [bug] Raw zones with with more than 512 records in a RRset failed to load. [RT #27863] 3282. [bug] Restrict the TTL of NS RRset to no more than that of the old NS RRset when replacing it. [RT #27792] [RT #27884] 3281. [bug] SOA refresh queries could be treated as cancelled despite succeeding over the loopback interface. [RT #27782] 3280. [bug] Potential double free of a rdataset on out of memory with DNS64. [RT #27762] 3279. [bug] Hold a internal reference to the zone while performing a asynchronous load. Address potential memory leak if the asynchronous is cancelled. [RT #27750] 3278. [bug] Make sure automatic key maintenance is started when "auto-dnssec maintain" is turned on during "rndc reconfig". [RT #26805] 3277. [bug] win32: isc_socket_dup is not implemented. [RT #27696] 3276. [bug] win32: ns_os_openfile failed to return NULL on safe_open failure. [RT #27696] 3275. [bug] Corrected rndc -h output; the 'rndc sync -clean' option had been misspelled as '-clear'. (To avoid future confusion, both options now work.) [RT #27173] 3274. [placeholder] 3273. [bug] AAAA responses could be returned in the additional section even when filter-aaaa-on-v4 was in use. [RT #27292] 3272. [func] New "rndc zonestatus" command prints information about the specified zone. [RT #21671] 3271. [port] darwin: mksymtbl is not always stable, loop several times before giving up. mksymtbl was using non portable perl to covert 64 bit hex strings. [RT #27653] --- 9.9.0rc2 released --- 3270. [bug] "rndc reload" didn't reuse existing zones correctly when inline-signing was in use. [RT #27650] 3269. [port] darwin 11 and later now built threaded by default. 3268. [bug] Convert RRSIG expiry times to 64 timestamps to work out the earliest expiry time. [RT #23311] 3267. [bug] Memory allocation failures could be mis-reported as unexpected error. New ISC_R_UNSET result code. [RT #27336] 3266. [bug] The maximum number of NSEC3 iterations for a DNSKEY RRset was not being properly computed. [RT #26543] 3265. [bug] Corrected a problem with lock ordering in the inline-signing code. [RT #27557] 3264. [bug] Automatic regeneration of signatures in an inline-signing zone could stall when the server was restarted. [RT #27344] 3263. [bug] "rndc sync" did not affect the unsigned side of an inline-signing zone. [RT #27337] 3262. [bug] Signed responses were handled incorrectly by RPZ. [RT #27316] 3261. [func] RRset ordering now defaults to random. [RT #27174] 3260. [bug] "rrset-order cyclic" could appear not to rotate for some query patterns. [RT #27170/27185] --- 9.9.0rc1 released --- 3259. [bug] named-compilezone: Suppress "dump zone to " message when writing to stdout. [RT #27109] 3258. [test] Add "forcing full sign with unreadable keys" test. [RT #27153] 3257. [bug] Do not generate a error message when calling fsync() in a pipe or socket. [RT #27109] 3256. [bug] Disable empty zones for lwresd -C. [RT #27139] 3255. [func] No longer require that a empty zones be explicitly enabled or that a empty zone is disabled for RFC 1918 empty zones to be configured. [RT #27139] 3254. [bug] Set isc_socket_ipv6only() on the IPv6 control channels. [RT #22249] 3253. [bug] Return DNS_R_SYNTAX when the input to a text field is too long. [RT #26956] 3252. [bug] When master zones using inline-signing were updated while the server was offline, the source zone could fall out of sync with the signed copy. They can now resynchronize. [RT #26676] 3251. [bug] Enforce a upper bound (65535 bytes) on the amount of memory dns_sdlz_putrr() can allocate per record to prevent run away memory consumption on ISC_R_NOSPACE. [RT #26956] 3250. [func] 'configure --enable-developer'; turn on various configure options, normally off by default, that we want developers to build and test with. [RT #27103] 3249. [bug] Update log message when saving slave zones files for analysis after load failures. [RT #27087] 3248. [bug] Configure options --enable-fixed-rrset and --enable-exportlib were incompatible with each other. [RT #27087] 3247. [bug] 'raw' format zones failed to preserve load order breaking 'fixed' sort order. [RT #27087] 3246. [bug] Named failed to start with a empty also-notify list. [RT #27087] 3245. [bug] Don't report a error unchanged serials unless there were other changes when thawing a zone with ixfr-fromdifferences. [RT #26845] 3244. [func] Added readline support to nslookup and nsupdate. Also simplified nsupdate syntax to make "update" and "prereq" optional. [RT #24659] 3243. [port] freebsd,netbsd,bsdi: the thread defaults were not being properly set. 3242. [func] Extended the header of raw-format master files to include the serial number of the zone from which they were generated, if different (as in the case of inline-signing zones). This is to be used in inline-signing zones, to track changes between the unsigned and signed versions of the zone, which may have different serial numbers. (Note: raw zonefiles generated by this version of BIND are no longer compatible with prior versions. To generate a backward-compatible raw zonefile using dnssec-signzone or named-compilezone, specify output format "raw=0" instead of simply "raw".) [RT #26587] 3241. [bug] Address race conditions in the resolver code. [RT #26889] 3240. [bug] DNSKEY state change events could be missed. [RT #26874] 3239. [bug] dns_dnssec_findmatchingkeys needs to use a consistent timestamp. [RT #26883] 3238. [bug] keyrdata was not being reinitialized in lib/dns/rbtdb.c:iszonesecure. [RT #26913] 3237. [bug] dig -6 didn't work with +trace. [RT #26906] 3236. [bug] Backed out changes #3182 and #3202, related to EDNS(0) fallback behavior. [RT #26416] 3235. [func] dns_db_diffx, a extended dns_db_diff which returns the generated diff and optionally writes it to a journal. [RT #26386] 3234. [bug] 'make depend' produced invalid makefiles. [RT #26830] 3233. [bug] 'rndc freeze/thaw' didn't work for inline zones. [RT #26632] 3232. [bug] Zero zone->curmaster before return in dns_zone_setmasterswithkeys(). [RT #26732] 3231. [bug] named could fail to send a incompressible zone. [RT #26796] 3230. [bug] 'dig axfr' failed to properly handle a multi-message axfr with a serial of 0. [RT #26796] 3229. [bug] Fix local variable to struct var assignment found by CLANG warning. 3228. [tuning] Dynamically grow symbol table to improve zone loading performance. [RT #26523] 3227. [bug] Interim fix to make WKS's use of getprotobyname() and getservbyname() self thread safe. [RT #26232] 3226. [bug] Address minor resource leakages. [RT #26624] 3225. [bug] Silence spurious "setsockopt(517, IPV6_V6ONLY) failed" messages. [RT #26507] 3224. [bug] 'rndc signing' argument parsing was broken. [RT #26684] 3223. [bug] 'task_test privilege_drop' generated false positives. [RT #26766] 3222. [cleanup] Replace dns_journal_{get,set}_bitws with dns_journal_{get,set}_sourceserial. [RT #26634] 3221. [bug] Fixed a potential core dump on shutdown due to referencing fetch context after it's been freed. [RT #26720] --- 9.9.0b2 released --- 3220. [bug] Change #3186 was incomplete; dns_db_rpz_findips() could fail to set the database version correctly, causing an assertion failure. [RT #26180] 3219. [bug] Disable NOEDNS caching following a timeout. 3218. [security] Cache lookup could return RRSIG data associated with nonexistent records, leading to an assertion failure. [RT #26590] 3217. [cleanup] Fix build problem with --disable-static. [RT #26476] 3216. [bug] resolver.c:validated() was not thread-safe. [RT #26478] 3215. [bug] 'rndc recursing' could cause a core dump. [RT #26495] 3214. [func] Add 'named -U' option to set the number of UDP listener threads per interface. [RT #26485] 3213. [doc] Clarify ixfr-from-differences behavior. [RT #25188] 3212. [bug] rbtdb.c: failed to remove a node from the deadnodes list prior to adding a reference to it leading a possible assertion failure. [RT #23219] 3211. [func] dnssec-signzone: "-f -" prints to stdout; "-O full" option prints in single-line-per-record format. [RT #20287] 3210. [bug] Canceling the oldest query due to recursive-client overload could trigger an assertion failure. [RT #26463] 3209. [func] Add "dnssec-lookaside 'no'". [RT #24858] 3208. [bug] 'dig -y' handle unknown tsig algorithm better. [RT #25522] 3207. [contrib] Fixed build error in Berkeley DB DLZ module. [RT #26444] 3206. [cleanup] Add ISC information to log at start time. [RT #25484] 3205. [func] Upgrade dig's defaults to better reflect modern nameserver behavior. Enable "dig +adflag" and "dig +edns=0" by default. Enable "+dnssec" when running "dig +trace". [RT #23497] 3204. [bug] When a master server that has been marked as unreachable sends a NOTIFY, mark it reachable again. [RT #25960] 3203. [bug] Increase log level to 'info' for validation failures from expired or not-yet-valid RRSIGs. [RT #21796] 3202. [bug] NOEDNS caching on timeout was too aggressive. [RT #26416] 3201. [func] 'rndc querylog' can now be given an on/off parameter instead of only being used as a toggle. [RT #18351] 3200. [doc] Some rndc functions were undocumented or were missing from 'rndc -h' output. [RT #25555] 3199. [func] When logging client information, include the name being queried. [RT #25944] 3198. [doc] Clarified that dnssec-settime can alter keyfile permissions. [RT #24866] 3197. [bug] Don't try to log the filename and line number when the config parser can't open a file. [RT #22263] 3196. [bug] nsupdate: return nonzero exit code when target zone doesn't exist. [RT #25783] 3195. [cleanup] Silence "file not found" warnings when loading managed-keys zone. [RT #26340] 3194. [doc] Updated RFC references in the 'empty-zones-enable' documentation. [RT #25203] 3193. [cleanup] Changed MAXZONEKEYS to DNS_MAXZONEKEYS, moved to dnssec.h. [RT #26415] 3192. [bug] A query structure could be used after being freed. [RT #22208] 3191. [bug] Print NULL records using "unknown" format. [RT #26392] 3190. [bug] Underflow in error handling in isc_mutexblock_init. [RT #26397] 3189. [test] Added a summary report after system tests. [RT #25517] 3188. [bug] zone.c:zone_refreshkeys() could fail to detach references correctly when errors occurred, causing a hang on shutdown. [RT #26372] 3187. [port] win32: support for Visual Studio 2008. [RT #26356] --- 9.9.0b1 released --- 3186. [bug] Version/db mis-match in rpz code. [RT #26180] 3185. [func] New 'rndc signing' option for auto-dnssec zones: - 'rndc signing -list' displays the current state of signing operations - 'rndc signing -clear' clears the signing state records for keys that have fully signed the zone - 'rndc signing -nsec3param' sets the NSEC3 parameters for the zone The 'rndc keydone' syntax is removed. [RT #23729] 3184. [bug] named had excessive cpu usage when a redirect zone was configured. [RT #26013] 3183. [bug] Added RTLD_GLOBAL flag to dlopen call. [RT #26301] 3182. [bug] Auth servers behind firewalls which block packets greater than 512 bytes may cause other servers to perform poorly. Now, adb retains edns information and caches noedns servers. [RT #23392/24964] 3181. [func] Inline-signing is now supported for master zones. [RT #26224] 3180. [func] Local copies of slave zones are now saved in raw format by default, to improve startup performance. 'masterfile-format text;' can be used to override the default, if desired. [RT #25867] 3179. [port] kfreebsd: build issues. [RT #26273] 3178. [bug] A race condition introduced by change #3163 could cause an assertion failure on shutdown. [RT #26271] 3177. [func] 'rndc keydone', remove the indicator record that named has finished signing the zone with the corresponding key. [RT #26206] 3176. [doc] Corrected example code and added a README to the sample external DLZ module in contrib/dlz/example. [RT #26215] 3175. [bug] Fix how DNSSEC positive wildcard responses from a NSEC3 signed zone are validated. Stop sending a unnecessary NSEC3 record when generating such responses. [RT #26200] 3174. [bug] Always compute to revoked key tag from scratch. [RT #26186] 3173. [port] Correctly validate root DS responses. [RT #25726] 3172. [port] darwin 10.* and freebsd [89] are now built threaded by default. 3171. [bug] Exclusively lock the task when adding a zone using 'rndc addzone'. [RT #25600] --- 9.9.0a3 released --- 3170. [func] RPZ update: - fix precedence among competing rules - improve ARM text including documenting rule precedence - try to rewrite CNAME chains until first hit - new "rpz" logging channel - RDATA for CNAME rules can include wildcards - replace "NO-OP" named.conf policy override with "PASSTHRU" and add "DISABLED" override ("NO-OP" is still recognized) [RT #25172] 3169. [func] Catch db/version mis-matches when calling dns_db_*(). [RT #26017] 3168. [bug] Nxdomain redirection could trigger an assert with a ANY query. [RT #26017] 3167. [bug] Negative answers from forwarders were not being correctly tagged making them appear to not be cached. [RT #25380] 3166. [bug] Upgrading a zone to support inline-signing failed. [RT #26014] 3165. [bug] dnssec-signzone could generate new signatures when resigning, even when valid signatures were already present. [RT #26025] 3164. [func] Enable DLZ modules to retrieve client information, so that responses can be changed depending on the source address of the query. [RT #25768] 3163. [bug] Use finer-grained locking in client.c to address concurrency problems with large numbers of threads. [RT #26044] 3162. [test] start.pl: modified to allow for "named.args" in ns*/ subdirectory to override stock arguments to named. Largely from RT #26044, but no separate ticket. 3161. [bug] zone.c:del_sigs failed to always reset rdata leading assertion failures. [RT #25880] 3160. [bug] When printing out a NSEC3 record in multiline form the newline was not being printed causing type codes to be run together. [RT #25873] 3159. [bug] On some platforms, named could assert on startup when running in a chrooted environment without /proc. [RT #25863] 3158. [bug] Recursive servers would prefer a particular UDP socket instead of using all available sockets. [RT #26038] 3157. [tuning] Reduce the time spent in "rndc reconfig" by parsing the config file before pausing the server. [RT #21373] 3156. [placeholder] --- 9.9.0a2 released --- 3155. [bug] Fixed a build failure when using contrib DLZ drivers (e.g., mysql, postgresql, etc). [RT #25710] 3154. [bug] Attempting to print an empty rdataset could trigger an assert. [RT #25452] 3153. [func] Extend request-ixfr to zone level and remove the side effect of forcing an AXFR. [RT #25156] 3152. [cleanup] Some versions of gcc and clang failed due to incorrect use of __builtin_expect. [RT #25183] 3151. [bug] Queries for type RRSIG or SIG could be handled incorrectly. [RT #21050] 3150. [func] Improved startup and reconfiguration time by enabling zones to load in multiple threads. [RT #25333] 3149. [placeholder] 3148. [bug] Processing of normal queries could be stalled when forwarding a UPDATE message. [RT #24711] 3147. [func] Initial inline signing support. [RT #23657] --- 9.9.0a1 released --- 3146. [test] Fixed gcc4.6.0 errors in ATF. [RT #25598] 3145. [test] Capture output of ATF unit tests in "./atf.out" if there were any errors while running them. [RT #25527] 3144. [bug] dns_dbiterator_seek() could trigger an assert when used with a nonexistent database node. [RT #25358] 3143. [bug] Silence clang compiler warnings. [RT #25174] 3142. [bug] NAPTR is class agnostic. [RT #25429] 3141. [bug] Silence spurious "zone serial (0) unchanged" messages associated with empty zones. [RT #25079] 3140. [func] New command "rndc flushtree " clears the specified name from the server cache along with all names under it. [RT #19970] 3139. [test] Added tests from RFC 6234, RFC 2202, and RFC 1321 for the hashing algorithms (md5, sha1 - sha512, and their hmac counterparts). [RT #25067] 3138. [bug] Address memory leaks and out-of-order operations when shutting named down. [RT #25210] 3137. [func] Improve hardware scalability by allowing multiple worker threads to process incoming UDP packets. This can significantly increase query throughput on some systems. [RT #22992] 3136. [func] Add RFC 1918 reverse zones to the list of built-in empty zones switched on by the 'empty-zones-enable' option. [RT #24990] 3135. [port] FreeBSD: workaround broken IPV6_USE_MIN_MTU processing. See http://www.freebsd.org/cgi/query-pr.cgi?pr=158307 [RT #24950] 3134. [bug] Improve the accuracy of dnssec-signzone's signing statistics. [RT #16030] 3133. [bug] Change #3114 was incomplete. [RT #24577] 3132. [placeholder] 3131. [tuning] Improve scalability by allocating one zone task per 100 zones at startup time, rather than using a fixed-size task table. [RT #24406] 3130. [func] Support alternate methods for managing a dynamic zone's serial number. Two methods are currently defined using serial-update-method, "increment" (default) and "unixtime". [RT #23849] 3129. [bug] Named could crash on 'rndc reconfig' when allow-new-zones was set to yes and named ACLs were used. [RT #22739] 3128. [func] Inserting an NSEC3PARAM via dynamic update in an auto-dnssec zone that has not been signed yet will cause it to be signed with the specified NSEC3 parameters when keys are activated. The NSEC3PARAM record will not appear in the zone until it is signed, but the parameters will be stored. [RT #23684] 3127. [bug] 'rndc thaw' will now remove a zone's journal file if the zone serial number has been changed and ixfr-from-differences is not in use. [RT #24687] 3126. [security] Using DNAME record to generate replacements caused RPZ to exit with a assertion failure. [RT #24766] 3125. [security] Using wildcard CNAME records as a replacement with RPZ caused named to exit with a assertion failure. [RT #24715] 3124. [bug] Use an rdataset attribute flag to indicate negative-cache records rather than using rrtype 0; this will prevent problems when that rrtype is used in actual DNS packets. [RT #24777] 3123. [security] Change #2912 exposed a latent flaw in dns_rdataset_totext() that could cause named to crash with an assertion failure. [RT #24777] 3122. [cleanup] dnssec-settime: corrected usage message. [RT #24664] 3121. [security] An authoritative name server sending a negative response containing a very large RRset could trigger an off-by-one error in the ncache code and crash named. [RT #24650] 3120. [bug] Named could fail to validate zones listed in a DLV that validated insecure without using DLV and had DS records in the parent zone. [RT #24631] 3119. [bug] When rolling to a new DNSSEC key, a private-type record could be created and never marked complete. [RT #23253] 3118. [bug] nsupdate could dump core on shutdown when using SIG(0) keys. [RT #24604] 3117. [cleanup] Remove doc and parser references to the never-implemented 'auto-dnssec create' option. [RT #24533] 3116. [func] New 'dnssec-update-mode' option controls updates of DNSSEC records in signed dynamic zones. Set to 'no-resign' to disable automatic RRSIG regeneration while retaining the ability to sign new or changed data. [RT #24533] 3115. [bug] Named could fail to return requested data when following a CNAME that points into the same zone. [RT #24455] 3114. [bug] Retain expired RRSIGs in dynamic zones if key is inactive and there is no replacement key. [RT #23136] 3113. [doc] Document the relationship between serial-query-rate and NOTIFY messages. 3112. [doc] Add missing descriptions of the update policy name types "ms-self", "ms-subdomain", "krb5-self" and "krb5-subdomain", which allow machines to update their own records, to the BIND 9 ARM. 3111. [bug] Improved consistency checks for dnssec-enable and dnssec-validation, added test cases to the checkconf system test. [RT #24398] 3110. [bug] dnssec-signzone: Wrong error message could appear when attempting to sign with no KSK. [RT #24369] 3109. [func] The also-notify option now uses the same syntax as a zone's masters clause. This means it is now possible to specify a TSIG key to use when sending notifies to a given server, or to include an explicit named masters list in an also-notify statement. [RT #23508] 3108. [cleanup] dnssec-signzone: Clarified some error and warning messages; removed #ifdef ALLOW_KSKLESS_ZONES code (use -P instead). [RT #20852] 3107. [bug] dnssec-signzone: Report the correct number of ZSKs when using -x. [RT #20852] 3106. [func] When logging client requests, include the name of the TSIG key if any. [RT #23619] 3105. [bug] GOST support can be suppressed by "configure --without-gost" [RT #24367] 3104. [bug] Better support for cross-compiling. [RT #24367] 3103. [bug] Configuring 'dnssec-validation auto' in a view instead of in the options statement could trigger an assertion failure in named-checkconf. [RT #24382] 3102. [func] New 'dnssec-loadkeys-interval' option configures how often, in minutes, to check the key repository for updates when using automatic key maintenance. Default is every 60 minutes (formerly hard-coded to 12 hours). [RT #23744] 3101. [bug] Zones using automatic key maintenance could fail to check the key repository for updates. [RT #23744] 3100. [security] Certain response policy zone configurations could trigger an INSIST when receiving a query of type RRSIG. [RT #24280] 3099. [test] "dlz" system test now runs but gives R:SKIPPED if not compiled with --with-dlz-filesystem. [RT #24146] 3098. [bug] DLZ zones were answering without setting the AA bit. [RT #24146] 3097. [test] Add a tool to test handling of malformed packets. [RT #24096] 3096. [bug] Set KRB5_KTNAME before calling log_cred() in dst_gssapi_acceptctx(). [RT #24004] 3095. [bug] Handle isolated reserved ports in the port range. [RT #23957] 3094. [doc] Expand dns64 documentation. 3093. [bug] Fix gssapi/kerberos dependencies [RT #23836] 3092. [bug] Signatures for records at the zone apex could go stale due to an incorrect timer setting. [RT #23769] 3091. [bug] Fixed a bug in which zone keys that were published and then subsequently activated could fail to trigger automatic signing. [RT #22911] 3090. [func] Make --with-gssapi default [RT #23738] 3089. [func] dnssec-dsfromkey now supports reading keys from standard input "dnssec-dsfromkey -f -". [RT #20662] 3088. [bug] Remove bin/tests/system/logfileconfig/ns1/named.conf and add setup.sh in order to resolve changing named.conf issue. [RT #23687] 3087. [bug] DDNS updates using SIG(0) with update-policy match type "external" could cause a crash. [RT #23735] 3086. [bug] Running dnssec-settime -f on an old-style key will now force an update to the new key format even if no other change has been specified, using "-P now -A now" as default values. [RT #22474] 3085. [func] New '-R' option in dnssec-signzone forces removal of signatures which have not yet expired but were generated by a key that no longer exists. [RT #22471] 3084. [func] A new command "rndc sync" dumps pending changes in a dynamic zone to disk; "rndc sync -clean" also removes the journal file after syncing. Also, "rndc freeze" no longer removes journal files. [RT #22473] 3083. [bug] NOTIFY messages were not being sent when generating a NSEC3 chain incrementally. [RT #23702] 3082. [port] strtok_r is threads only. [RT #23747] 3081. [bug] Failure of DNAME substitution did not return YXDOMAIN. [RT #23591] 3080. [cleanup] Replaced compile time constant by STDTIME_ON_32BITS. [RT #23587] 3079. [bug] Handle isc_event_allocate failures in t_tasks. [RT #23572] 3078. [func] Added a new include file with function typedefs for the DLZ "dlopen" driver. [RT #23629] 3077. [bug] zone.c:zone_refreshkeys() incorrectly called dns_zone_attach(), use zone->irefs instead. [RT #23303] 3076. [func] New '-L' option in dnssec-keygen, dnsset-settime, and dnssec-keyfromlabel sets the default TTL of the key. When possible, automatic signing will use that TTL when the key is published. [RT #23304] 3075. [bug] dns_dnssec_findzonekeys{2} used a inconsistent timestamp when determining which keys are active. [RT #23642] 3074. [bug] Make the adb cache read through for zone data and glue learn for zone named is authoritative for. [RT #22842] 3073. [bug] managed-keys changes were not properly being recorded. [RT #20256] 3072. [bug] dns_dns64_aaaaok() potential NULL pointer dereference. [RT #20256] 3071. [bug] has_nsec could be used uninitialized in update.c:next_active. [RT #20256] 3070. [bug] dnssec-signzone potential NULL pointer dereference. [RT #20256] 3069. [cleanup] Silence warnings messages from clang static analysis. [RT #20256] 3068. [bug] Named failed to build with a OpenSSL without engine support. [RT #23473] 3067. [bug] ixfr-from-differences {master|slave}; failed to select the master/slave zones. [RT #23580] 3066. [func] The DLZ "dlopen" driver is now built by default, no longer requiring a configure option. To disable it, use "configure --without-dlopen". Driver also supported on win32. [RT #23467] 3065. [bug] RRSIG could have time stamps too far in the future. [RT #23356] 3064. [bug] powerpc: add sync instructions to the end of atomic operations. [RT #23469] 3063. [contrib] More verbose error reporting from DLZ LDAP. [RT #23402] 3062. [func] Made several changes to enhance human readability of DNSSEC data in dig output and in generated zone files: - DNSKEY record comments are more verbose, no longer used in multiline mode only - multiline RRSIG records reformatted - multiline output mode for NSEC3PARAM records - "dig +norrcomments" suppresses DNSKEY comments - "dig +split=X" breaks hex/base64 records into fields of width X; "dig +nosplit" disables this. [RT #22820] 3061. [func] New option "dnssec-signzone -D", only write out generated DNSSEC records. [RT #22896] 3060. [func] New option "dnssec-signzone -X " allows specification of a separate expiration date for DNSKEY RRSIGs and other RRSIGs. [RT #22141] 3059. [test] Added a regression test for change #3023. 3058. [bug] Cause named to terminate at startup or rndc reconfig/ reload to fail, if a log file specified in the conf file isn't a plain file. [RT #22771] 3057. [bug] "rndc secroots" would abort after the first error and so could miss some views. [RT #23488] 3056. [func] Added support for URI resource record. [RT #23386] 3055. [placeholder] 3054. [bug] Added elliptic curve support check in GOST OpenSSL engine detection. [RT #23485] 3053. [bug] Under a sustained high query load with a finite max-cache-size, it was possible for cache memory to be exhausted and not recovered. [RT #23371] 3052. [test] Fixed last autosign test report. [RT #23256] 3051. [bug] NS records obscure DNAME records at the bottom of the zone if both are present. [RT #23035] 3050. [bug] The autosign system test was timing dependent. Wait for the initial autosigning to complete before running the rest of the test. [RT #23035] 3049. [bug] Save and restore the gid when creating creating named.pid at startup. [RT #23290] 3048. [bug] Fully separate view key management. [RT #23419] 3047. [bug] DNSKEY NODATA responses not cached fixed in validator.c. Tests added to dnssec system test. [RT #22908] 3046. [bug] Use RRSIG original TTL to compute validated RRset and RRSIG TTL. [RT #23332] 3045. [removed] Replaced by change #3050. 3044. [bug] Hold the socket manager lock while freeing the socket. [RT #23333] 3043. [test] Merged in the NetBSD ATF test framework (currently version 0.12) for development of future unit tests. Use configure --with-atf to build ATF internally or configure --with-atf=prefix to use an external copy. [RT #23209] 3042. [bug] dig +trace could fail attempting to use IPv6 addresses on systems with only IPv4 connectivity. [RT #23297] 3041. [bug] dnssec-signzone failed to generate new signatures on ttl changes. [RT #23330] 3040. [bug] Named failed to validate insecure zones where a node with a CNAME existed between the trust anchor and the top of the zone. [RT #23338] 3039. [func] Redirect on NXDOMAIN support. [RT #23146] 3038. [bug] Install . [RT #23342] 3037. [doc] Update COPYRIGHT to contain all the individual copyright notices that cover various parts. 3036. [bug] Check built-in zone arguments to see if the zone is re-usable or not. [RT #21914] 3035. [cleanup] Simplify by using strlcpy. [RT #22521] 3034. [cleanup] nslookup: use strlcpy instead of safecopy. [RT #22521] 3033. [cleanup] Add two INSIST(bucket != DNS_ADB_INVALIDBUCKET). [RT #22521] 3032. [bug] rdatalist.c: add missing REQUIREs. [RT #22521] 3031. [bug] dns_rdataclass_format() handle a zero sized buffer. [RT #22521] 3030. [bug] dns_rdatatype_format() handle a zero sized buffer. [RT #22521] 3029. [bug] isc_netaddr_format() handle a zero sized buffer. [RT #22521] 3028. [bug] isc_sockaddr_format() handle a zero sized buffer. [RT #22521] 3027. [bug] Add documented REQUIREs to cfg_obj_asnetprefix() to catch NULL pointer dereferences before they happen. [RT #22521] 3026. [bug] lib/isc/httpd.c: check that we have enough space after calling grow_headerspace() and if not re-call grow_headerspace() until we do. [RT #22521] 3025. [bug] Fixed a possible deadlock due to zone resigning. [RT #22964] 3024. [func] RTT Banding removed due to minor security increase but major impact on resolver latency. [RT #23310] 3023. [bug] Named could be left in an inconsistent state when receiving multiple AXFR response messages that were not all TSIG-signed. [RT #23254] 3022. [bug] Fixed rpz SERVFAILs after failed zone transfers [RT #23246] 3021. [bug] Change #3010 was incomplete. [RT #22296] 3020. [bug] auto-dnssec failed to correctly update the zone when changing the DNSKEY RRset. [RT #23232] 3019. [test] Test: check apex NSEC3 records after adding DNSKEY record via UPDATE. [RT #23229] 3018. [bug] Named failed to check for the "none;" acl when deciding if a zone may need to be re-signed. [RT #23120] 3017. [doc] dnssec-keyfromlabel -I was not properly documented. [RT #22887] 3016. [bug] rndc usage missing '-b'. [RT #22937] 3015. [port] win32: fix IN6_IS_ADDR_LINKLOCAL and IN6_IS_ADDR_SITELOCAL macros. [RT #22724] 3014. [placeholder] 3013. [bug] The DNS64 ttl was not always being set as expected. [RT #23034] 3012. [bug] Remove DNSKEY TTL change pairs before generating signing records for any remaining DNSKEY changes. [RT #22590] 3011. [func] Change the default query timeout from 30 seconds to 10. Allow setting this in named.conf using the new 'resolver-query-timeout' option, which specifies a max time in seconds. 0 means 'default' and anything longer than 30 will be silently set to 30. [RT #22852] 3010. [bug] Fixed a bug where "rndc reconfig" stopped the timer for refreshing managed-keys. [RT #22296] 3009. [bug] clients-per-query code didn't work as expected with particular query patterns. [RT #22972] --- 9.8.0b1 released --- 3008. [func] Response policy zones (RPZ) support. [RT #21726] 3007. [bug] Named failed to preserve the case of domain names in rdata which is not compressible when writing master files. [RT #22863] 3006. [func] Allow dynamically generated TSIG keys to be preserved across restarts of named. Initially this is for TSIG keys generated using GSSAPI. [RT #22639] 3005. [port] Solaris: Work around the lack of gsskrb5_register_acceptor_identity() by setting the KRB5_KTNAME environment variable to the contents of tkey-gssapi-keytab. Also fixed test errors on MacOSX. [RT #22853] 3004. [func] DNS64 reverse support. [RT #22769] 3003. [experimental] Added update-policy match type "external", enabling named to defer the decision of whether to allow a dynamic update to an external daemon. (Contributed by Andrew Tridgell.) [RT #22758] 3002. [bug] isc_mutex_init_errcheck() failed to destroy attr. [RT #22766] 3001. [func] Added a default trust anchor for the root zone, which can be switched on by setting "dnssec-validation auto;" in the named.conf options. [RT #21727] 3000. [bug] More TKEY/GSS fixes: - nsupdate can now get the default realm from the user's Kerberos principal - corrected gsstest compilation flags - improved documentation - fixed some NULL dereferences [RT #22795] 2999. [func] Add GOST support (RFC 5933). [RT #20639] 2998. [func] Add isc_task_beginexclusive and isc_task_endexclusive to the task api. [RT #22776] 2997. [func] named -V now reports the OpenSSL and libxml2 verions it was compiled against. [RT #22687] 2996. [security] Temporarily disable SO_ACCEPTFILTER support. [RT #22589] 2995. [bug] The Kerberos realm was not being correctly extracted from the signer's identity. [RT #22770] 2994. [port] NetBSD: use pthreads by default on NetBSD >= 5.0, and do not use threads on earlier versions. Also kill the unproven-pthreads, mit-pthreads, and ptl2 support. 2993. [func] Dynamically grow adb hash tables. [RT #21186] 2992. [contrib] contrib/check-secure-delegation.pl: A simple tool for looking at a secure delegation. [RT #22059] 2991. [contrib] contrib/zone-edit.sh: A simple zone editing tool for dynamic zones. [RT #22365] 2990. [bug] 'dnssec-settime -S' no longer tests prepublication interval validity when the interval is set to 0. [RT #22761] 2989. [func] Added support for writable DLZ zones. (Contributed by Andrew Tridgell of the Samba project.) [RT #22629] 2988. [experimental] Added a "dlopen" DLZ driver, allowing the creation of external DLZ drivers that can be loaded as shared objects at runtime rather than linked with named. Currently this is switched on via a compile-time option, "configure --with-dlz-dlopen". Note: the syntax for configuring DLZ zones is likely to be refined in future releases. (Contributed by Andrew Tridgell of the Samba project.) [RT #22629] 2987. [func] Improve ease of configuring TKEY/GSS updates by adding a "tkey-gssapi-keytab" option. If set, updates will be allowed with any key matching a principal in the specified keytab file. "tkey-gssapi-credential" is no longer required and is expected to be deprecated. (Contributed by Andrew Tridgell of the Samba project.) [RT #22629] 2986. [func] Add new zone type "static-stub". It's like a stub zone, but the nameserver names and/or their IP addresses are statically configured. [RT #21474] 2985. [bug] Add a regression test for change #2896. [RT #21324] 2984. [bug] Don't run MX checks when the target of the MX record is ".". [RT #22645] 2983. [bug] Include "loadkeys" in rndc help output. [RT #22493] --- 9.8.0a1 released --- 2982. [bug] Reference count dst keys. dst_key_attach() can be used increment the reference count. Note: dns_tsigkey_createfromkey() callers should now always call dst_key_free() rather than setting it to NULL on success. [RT #22672] 2981. [func] Partial DNS64 support (AAAA synthesis). [RT #21991] 2980. [bug] named didn't properly handle UPDATES that changed the TTL of the NSEC3PARAM RRset. [RT #22363] 2979. [bug] named could deadlock during shutdown if two "rndc stop" commands were issued at the same time. [RT #22108] 2978. [port] hpux: look for [RT #21919] 2977. [bug] 'nsupdate -l' report if the session key is missing. [RT #21670] 2976. [bug] named could die on exit after negotiating a GSS-TSIG key. [RT #22573] 2975. [bug] rbtdb.c:cleanup_dead_nodes_callback() acquired the wrong lock which could lead to server deadlock. [RT #22614] 2974. [bug] Some valid UPDATE requests could fail due to a consistency check examining the existing version of the zone rather than the new version resulting from the UPDATE. [RT #22413] 2973. [bug] bind.keys.h was being removed by the "make clean" at the end of configure resulting in build failures where there is very old version of perl installed. Move it to "make maintainer-clean". [RT #22230] 2972. [bug] win32: address windows socket errors. [RT #21906] 2971. [bug] Fixed a bug that caused journal files not to be compacted on Windows systems as a result of non-POSIX-compliant rename() semantics. [RT #22434] 2970. [security] Adding a NO DATA negative cache entry failed to clear any matching RRSIG records. A subsequent lookup of of NO DATA cache entry could trigger a INSIST when the unexpected RRSIG was also returned with the NO DATA cache entry. CVE-2010-3613, VU#706148. [RT #22288] 2969. [security] Fix acl type processing so that allow-query works in options and view statements. Also add a new set of tests to verify proper functioning. CVE-2010-3615, VU#510208. [RT #22418] 2968. [security] Named could fail to prove a data set was insecure before marking it as insecure. One set of conditions that can trigger this occurs naturally when rolling DNSKEY algorithms. CVE-2010-3614, VU#837744. [RT #22309] 2967. [bug] 'host -D' now turns on debugging messages earlier. [RT #22361] 2966. [bug] isc_print_vsnprintf() failed to check if there was space available in the buffer when adding a left justified character with a non zero width, (e.g. "%-1c"). [RT #22270] 2965. [func] Test HMAC functions using test data from RFC 2104 and RFC 4634. [RT #21702] 2964. [placeholder] 2963. [security] The allow-query acl was being applied instead of the allow-query-cache acl to cache lookups. [RT #22114] 2962. [port] win32: add more dependencies to BINDBuild.dsw. [RT #22062] 2961. [bug] Be still more selective about the non-authoritative answers we apply change 2748 to. [RT #22074] 2960. [func] Check that named accepts non-authoritative answers. [RT #21594] 2959. [func] Check that named starts with a missing masterfile. [RT #22076] 2958. [bug] named failed to start with a missing master file. [RT #22076] 2957. [bug] entropy_get() and entropy_getpseudo() failed to match the API for RAND_bytes() and RAND_pseudo_bytes() respectively. [RT #21962] 2956. [port] Enable atomic operations on the PowerPC64. [RT #21899] 2955. [func] Provide more detail in the recursing log. [RT #22043] 2954. [bug] contrib: dlz_mysql_driver.c bad error handling on build_sqldbinstance failure. [RT #21623] 2953. [bug] Silence spurious "expected covering NSEC3, got an exact match" message when returning a wildcard no data response. [RT #21744] 2952. [port] win32: named-checkzone and named-checkconf failed to initialize winsock. [RT #21932] 2951. [bug] named failed to generate a correct signed response in a optout, delegation only zone with no secure delegations. [RT #22007] 2950. [bug] named failed to perform a SOA up to date check when falling back to TCP on UDP timeouts when ixfr-from-differences was set. [RT #21595] 2949. [bug] dns_view_setnewzones() contained a memory leak if it was called multiple times. [RT #21942] 2948. [port] MacOS: provide a mechanism to configure the test interfaces at reboot. See bin/tests/system/README for details. 2947. [placeholder] 2946. [doc] Document the default values for the minimum and maximum zone refresh and retry values in the ARM. [RT #21886] 2945. [doc] Update empty-zones list in ARM. [RT #21772] 2944. [maint] Remove ORCHID prefix from built in empty zones. [RT #21772] 2943. [func] Add support to load new keys into managed zones without signing immediately with "rndc loadkeys". Add support to link keys with "dnssec-keygen -S" and "dnssec-settime -S". [RT #21351] 2942. [contrib] zone2sqlite failed to setup the entropy sources. [RT #21610] 2941. [bug] sdb and sdlz (dlz's zone database) failed to support DNAME at the zone apex. [RT #21610] 2940. [port] Remove connection aborted error message on Windows. [RT #21549] 2939. [func] Check that named successfully skips NSEC3 records that fail to match the NSEC3PARAM record currently in use. [RT #21868] 2938. [bug] When generating signed responses, from a signed zone that uses NSEC3, named would use a uninitialized pointer if it needed to skip a NSEC3 record because it didn't match the selected NSEC3PARAM record for zone. [RT #21868] 2937. [bug] Worked around an apparent race condition in over memory conditions. Without this fix a DNS cache DB or ADB could incorrectly stay in an over memory state, effectively refusing further caching, which subsequently made a BIND 9 caching server unworkable. This fix prevents this problem from happening by polling the state of the memory context, rather than making a copy of the state, which appeared to cause a race. This is a "workaround" in that it doesn't solve the possible race per se, but several experiments proved this change solves the symptom. Also, the polling overhead hasn't been reported to be an issue. This bug should only affect a caching server that specifies a finite max-cache-size. It's also quite likely that the bug happens only when enabling threads, but it's not confirmed yet. [RT #21818] 2936. [func] Improved configuration syntax and multiple-view support for addzone/delzone feature (see change #2930). Removed "new-zone-file" option, replaced with "allow-new-zones (yes|no)". The new-zone-file for each view is now created automatically, with a filename generated from a hash of the view name. It is no longer necessary to "include" the new-zone-file in named.conf; this happens automatically. Zones that were not added via "rndc addzone" can no longer be removed with "rndc delzone". [RT #19447] 2935. [bug] nsupdate: improve 'file not found' error message. [RT #21871] 2934. [bug] Use ANSI C compliant shift range in lib/isc/entropy.c. [RT #21871] 2933. [bug] 'dig +nsid' used stack memory after it went out of scope. This could potentially result in a unknown, potentially malformed, EDNS option being sent instead of the desired NSID option. [RT #21781] 2932. [cleanup] Corrected a numbering error in the "dnssec" test. [RT #21597] 2931. [bug] Temporarily and partially disable change 2864 because it would cause infinite attempts of RRSIG queries. This is an urgent care fix; we'll revisit the issue and complete the fix later. [RT #21710] 2930. [experimental] New "rndc addzone" and "rndc delzone" commands allow dynamic addition and deletion of zones. To enable this feature, specify a "new-zone-file" option at the view or options level in named.conf. Zone configuration information for the new zones will be written into that file. To make the new zones persist after a restart, "include" the file into named.conf in the appropriate view. (Note: This feature is not yet documented, and its syntax is expected to change.) [RT #19447] 2929. [bug] Improved handling of GSS security contexts: - added LRU expiration for generated TSIGs - added the ability to use a non-default realm - added new "realm" keyword in nsupdate - limited lifetime of generated keys to 1 hour or the lifetime of the context (whichever is smaller) [RT #19737] 2928. [bug] Be more selective about the non-authoritative answer we apply change 2748 to. [RT #21594] 2927. [placeholder] 2926. [placeholder] 2925. [bug] Named failed to accept uncachable negative responses from insecure zones. [RT #21555] 2924. [func] 'rndc secroots' dump a combined summary of the current managed keys combined with trusted keys. [RT #20904] 2923. [bug] 'dig +trace' could drop core after "connection timeout". [RT #21514] 2922. [contrib] Update zkt to version 1.0. 2921. [bug] The resolver could attempt to destroy a fetch context too soon. [RT #19878] 2920. [func] Allow 'filter-aaaa-on-v4' to be applied selectively to IPv4 clients. New acl 'filter-aaaa' (default any). 2919. [func] Add autosign-ksk and autosign-zsk virtual time tests. [RT #20840] 2918. [maint] Add AAAA address for I.ROOT-SERVERS.NET. 2917. [func] Virtual time test framework. [RT #20801] 2916. [func] Add framework to use IPv6 in tests. fd92:7065:b8e:ffff::1 ... fd92:7065:b8e:ffff::7 2915. [cleanup] Be smarter about which objects we attempt to compile based on configure options. [RT #21444] 2914. [bug] Make the "autosign" system test more portable. [RT #20997] 2913. [func] Add pkcs#11 system tests. [RT #20784] 2912. [func] Windows clients don't like UPDATE responses that clear the zone section. [RT #20986] 2911. [bug] dnssec-signzone didn't handle out of zone records well. [RT #21367] 2910. [func] Sanity check Kerberos credentials. [RT #20986] 2909. [bug] named-checkconf -p could die if "update-policy local;" was specified in named.conf. [RT #21416] 2908. [bug] It was possible for re-signing to stop after removing a DNSKEY. [RT #21384] 2907. [bug] The export version of libdns had undefined references. [RT #21444] 2906. [bug] Address RFC 5011 implementation issues. [RT #20903] 2905. [port] aix: set use_atomic=yes with native compiler. [RT #21402] 2904. [bug] When using DLV, sub-zones of the zones in the DLV, could be incorrectly marked as insecure instead of secure leading to negative proofs failing. This was a unintended outcome from change 2890. [RT #21392] 2903. [bug] managed-keys-directory missing from namedconf.c. [RT #21370] 2902. [func] Add regression test for change 2897. [RT #21040] 2901. [port] Use AC_C_FLEXIBLE_ARRAY_MEMBER. [RT #21316] 2900. [bug] The placeholder negative caching element was not properly constructed triggering a INSIST in dns_ncache_towire(). [RT #21346] 2899. [port] win32: Support linking against OpenSSL 1.0.0. 2898. [bug] nslookup leaked memory when -domain=value was specified. [RT #21301] 2897. [bug] NSEC3 chains could be left behind when transitioning to insecure. [RT #21040] 2896. [bug] "rndc sign" failed to properly update the zone when adding a DNSKEY for publication only. [RT #21045] 2895. [func] genrandom: add support for the generation of multiple files. [RT #20917] 2894. [contrib] DLZ LDAP support now use '$' not '%'. [RT #21294] 2893. [bug] Improve managed keys support. New named.conf option managed-keys-directory. [RT #20924] 2892. [bug] Handle REVOKED keys better. [RT #20961] 2891. [maint] Update empty-zones list to match draft-ietf-dnsop-default-local-zones-13. [RT #21099] 2890. [bug] Handle the introduction of new trusted-keys and DS, DLV RRsets better. [RT #21097] 2889. [bug] Elements of the grammar where not properly reported. [RT #21046] 2888. [bug] Only the first EDNS option was displayed. [RT #21273] 2887. [bug] Report the keytag times in UTC in the .key file, local time is presented as a comment within the comment. [RT #21223] 2886. [bug] ctime() is not thread safe. [RT #21223] 2885. [bug] Improve -fno-strict-aliasing support probing in configure. [RT #21080] 2884. [bug] Insufficient validation in dns_name_getlabelsequence(). [RT #21283] 2883. [bug] 'dig +short' failed to handle really large datasets. [RT #21113] 2882. [bug] Remove memory context from list of active contexts before clearing 'magic'. [RT #21274] 2881. [bug] Reduce the amount of time the rbtdb write lock is held when closing a version. [RT #21198] 2880. [cleanup] Make the output of dnssec-keygen and dnssec-revoke consistent. [RT #21078] 2879. [contrib] DLZ bdbhpt driver fails to close correct cursor. [RT #21106] 2878. [func] Incrementally write the master file after performing a AXFR. [RT #21010] 2877. [bug] The validator failed to skip obviously mismatching RRSIGs. [RT #21138] 2876. [bug] Named could return SERVFAIL for negative responses from unsigned zones. [RT #21131] 2875. [bug] dns_time64_fromtext() could accept non digits. [RT #21033] 2874. [bug] Cache lack of EDNS support only after the server successfully responds to the query using plain DNS. [RT #20930] 2873. [bug] Canceling a dynamic update via the dns/client module could trigger an assertion failure. [RT #21133] 2872. [bug] Modify dns/client.c:dns_client_createx() to only require one of IPv4 or IPv6 rather than both. [RT #21122] 2871. [bug] Type mismatch in mem_api.c between the definition and the header file, causing build failure with --enable-exportlib. [RT #21138] 2870. [maint] Add AAAA address for L.ROOT-SERVERS.NET. 2869. [bug] Fix arguments to dns_keytable_findnextkeynode() call. [RT #20877] 2868. [cleanup] Run "make clean" at the end of configure to ensure any changes made by configure are integrated. Use --with-make-clean=no to disable. [RT #20994] 2867. [bug] Don't set GSS_C_SEQUENCE_FLAG as Windows DNS servers don't like it. [RT #20986] 2866. [bug] Windows does not like the TSIG name being compressed. [RT #20986] 2865. [bug] memset to zero event.data. [RT #20986] 2864. [bug] Direct SIG/RRSIG queries were not handled correctly. [RT #21050] 2863. [port] linux: disable IPv6 PMTUD and use network minimum MTU. [RT #21056] 2862. [bug] nsupdate didn't default to the parent zone when updating DS records. [RT #20896] 2861. [doc] dnssec-settime man pages didn't correctly document the inactivation time. [RT #21039] 2860. [bug] named-checkconf's usage was out of date. [RT #21039] 2859. [bug] When canceling validation it was possible to leak memory. [RT #20800] 2858. [bug] RTT estimates were not being adjusted on ICMP errors. [RT #20772] 2857. [bug] named-checkconf did not fail on a bad trusted key. [RT #20705] 2856. [bug] The size of a memory allocation was not always properly recorded. [RT #20927] 2855. [func] nsupdate will now preserve the entered case of domain names in update requests it sends. [RT #20928] 2854. [func] dig: allow the final soa record in a axfr response to be suppressed, dig +onesoa. [RT #20929] 2853. [bug] add_sigs() could run out of scratch space. [RT #21015] 2852. [bug] Handle broken DNSSEC trust chains better. [RT #15619] 2851. [doc] nslookup.1, removed from the docbook source as it produced bad nroff. [RT #21007] 2850. [bug] If isc_heap_insert() failed due to memory shortage the heap would have corrupted entries. [RT #20951] 2849. [bug] Don't treat errors from the xml2 library as fatal. [RT #20945] 2848. [doc] Moved README.dnssec, README.libdns, README.pkcs11 and README.rfc5011 into the ARM. [RT #20899] 2847. [cleanup] Corrected usage message in dnssec-settime. [RT #20921] 2846. [bug] EOF on unix domain sockets was not being handled correctly. [RT #20731] 2845. [bug] RFC 5011 client could crash on shutdown. [RT #20903] 2844. [doc] notify-delay default in ARM was wrong. It should have been five (5) seconds. 2843. [func] Prevent dnssec-keygen and dnssec-keyfromlabel from creating key files if there is a chance that the new key ID will collide with an existing one after either of the keys has been revoked. (To override this in the case of dnssec-keyfromlabel, use the -y option. dnssec-keygen will simply create a different, non-colliding key, so an override is not necessary.) [RT #20838] 2842. [func] Added "smartsign" and improved "autosign" and "dnssec" regression tests. [RT #20865] 2841. [bug] Change 2836 was not complete. [RT #20883] 2840. [bug] Temporary fixed pkcs11-destroy usage check. [RT #20760] 2839. [bug] A KSK revoked by named could not be deleted. [RT #20881] 2838. [placeholder] 2837. [port] Prevent Linux spurious warnings about fwrite(). [RT #20812] 2836. [bug] Keys that were scheduled to become active could be delayed. [RT #20874] 2835. [bug] Key inactivity dates were inadvertently stored in the private key file with the outdated tag "Unpublish" rather than "Inactive". This has been fixed; however, any existing keys that had Inactive dates set will now need to have them reset, using 'dnssec-settime -I'. [RT #20868] 2834. [bug] HMAC-SHA* keys that were longer than the algorithm digest length were used incorrectly, leading to interoperability problems with other DNS implementations. This has been corrected. (Note: If an oversize key is in use, and compatibility is needed with an older release of BIND, the new tool "isc-hmac-fixup" can convert the key secret to a form that will work with all versions.) [RT #20751] 2833. [cleanup] Fix usage messages in dnssec-keygen and dnssec-settime. [RT #20851] 2832. [bug] Modify "struct stat" in lib/export/samples/nsprobe.c to avoid redefinition in some OSs [RT 20831] 2831. [security] Do not attempt to validate or cache out-of-bailiwick data returned with a secure answer; it must be re-fetched from its original source and validated in that context. [RT #20819] 2830. [bug] Changing the OPTOUT setting could take multiple passes. [RT #20813] 2829. [bug] Fixed potential node inconsistency in rbtdb.c. [RT #20808] 2828. [security] Cached CNAME or DNAME RR could be returned to clients without DNSSEC validation. [RT #20737] 2827. [security] Bogus NXDOMAIN could be cached as if valid. [RT #20712] 2826. [bug] NSEC3->NSEC transitions could fail due to a lock not being released. [RT #20740] 2825. [bug] Changing the setting of OPTOUT in a NSEC3 chain that was in the process of being created was not properly recorded in the zone. [RT #20786] 2824. [bug] "rndc sign" was not being run by the correct task. [RT #20759] 2823. [bug] rbtdb.c:getsigningtime() was missing locks. [RT #20781] 2822. [bug] rbtdb.c:loadnode() could return the wrong result. [RT #20802] 2821. [doc] Add note that named-checkconf doesn't automatically read rndc.key and bind.keys [RT #20758] 2820. [func] Handle read access failure of OpenSSL configuration file more user friendly (PKCS#11 engine patch). [RT #20668] 2819. [cleanup] Removed unnecessary DNS_POINTER_MAXHOPS define. [RT #20771] 2818. [cleanup] rndc could return an incorrect error code when a zone was not found. [RT #20767] 2817. [cleanup] Removed unnecessary isc_task_endexclusive() calls. [RT #20768] 2816. [bug] previous_closest_nsec() could fail to return data for NSEC3 nodes [RT #29730] 2815. [bug] Exclusively lock the task when freezing a zone. [RT #19838] 2814. [func] Provide a definitive error message when a master zone is not loaded. [RT #20757] 2813. [bug] Better handling of unreadable DNSSEC key files. [RT #20710] 2812. [bug] Make sure updates can't result in a zone with NSEC-only keys and NSEC3 records. [RT #20748] 2811. [cleanup] Add "rndc sign" to list of commands in rndc usage output. [RT #20733] 2810. [doc] Clarified the process of transitioning an NSEC3 zone to insecure. [RT #20746] 2809. [cleanup] Restored accidentally-deleted text in usage output in dnssec-settime and dnssec-revoke [RT #20739] 2808. [bug] Remove the attempt to install atomic.h from lib/isc. atomic.h is correctly installed by the architecture specific subdirectories. [RT #20722] 2807. [bug] Fixed a possible ASSERT when reconfiguring zone keys. [RT #20720] --- 9.7.0rc1 released --- 2806. [bug] "rdnc sign" could delay re-signing the DNSKEY when it had changed. [RT #20703] 2805. [bug] Fixed namespace problems encountered when building external programs using non-exported BIND9 libraries (i.e., built without --enable-exportlib). [RT #20679] 2804. [bug] Send notifies when a zone is signed with "rndc sign" or as a result of a scheduled key change. [RT #20700] 2803. [port] win32: Install named-journalprint, nsec3hash, arpaname and genrandom under windows. [RT #20670] 2802. [cleanup] Rename journalprint to named-journalprint. [RT #20670] 2801. [func] Detect and report records that are different according to DNSSEC but are semantically equal according to plain DNS. Apply plain DNS comparisons rather than DNSSEC comparisons when processing UPDATE requests. dnssec-signzone now removes such semantically duplicate records prior to signing the RRset. named-checkzone -r {ignore|warn|fail} (default warn) named-compilezone -r {ignore|warn|fail} (default warn) named.conf: check-dup-records {ignore|warn|fail}; 2800. [func] Reject zones which have NS records which refer to CNAMEs, DNAMEs or don't have address record (class IN only). Reject UPDATEs which would cause the zone to fail the above checks if committed. [RT #20678] 2799. [cleanup] Changed the "secure-to-insecure" option to "dnssec-secure-to-insecure", and "dnskey-ksk-only" to "dnssec-dnskey-kskonly", for clarity. [RT #20586] 2798. [bug] Addressed bugs in managed-keys initialization and rollover. [RT #20683] 2797. [bug] Don't decrement the dispatch manager's maxbuffers. [RT #20613] 2796. [bug] Missing dns_rdataset_disassociate() call in dns_nsec3_delnsec3sx(). [RT #20681] 2795. [cleanup] Add text to differentiate "update with no effect" log messages. [RT #18889] 2794. [bug] Install . [RT #20677] 2793. [func] Add "autosign" and "metadata" tests to the automatic tests. [RT #19946] 2792. [func] "filter-aaaa-on-v4" can now be set in view options (if compiled in). [RT #20635] 2791. [bug] The installation of isc-config.sh was broken. [RT #20667] 2790. [bug] Handle DS queries to stub zones. [RT #20440] 2789. [bug] Fixed an INSIST in dispatch.c [RT #20576] 2788. [bug] dnssec-signzone could sign with keys that were not requested [RT #20625] 2787. [bug] Spurious log message when zone keys were dynamically reconfigured. [RT #20659] 2786. [bug] Additional could be promoted to answer. [RT #20663] --- 9.7.0b3 released --- 2785. [bug] Revoked keys could fail to self-sign [RT #20652] 2784. [bug] TC was not always being set when required glue was dropped. [RT #20655] 2783. [func] Return minimal responses to EDNS/UDP queries with a UDP buffer size of 512 or less. [RT #20654] 2782. [port] win32: use getaddrinfo() for hostname lookups. [RT #20650] 2781. [bug] Inactive keys could be used for signing. [RT #20649] 2780. [bug] dnssec-keygen -A none didn't properly unset the activation date in all cases. [RT #20648] 2779. [bug] Dynamic key revocation could fail. [RT #20644] 2778. [bug] dnssec-signzone could fail when a key was revoked without deleting the unrevoked version. [RT #20638] 2777. [contrib] DLZ MYSQL auto reconnect support discovery was wrong. 2776. [bug] Change #2762 was not correct. [RT #20647] 2775. [bug] Accept RSASHA256 and RSASHA512 as NSEC3 compatible in dnssec-keyfromlabel. [RT #20643] 2774. [bug] Existing cache DB wasn't being reused after reconfiguration. [RT #20629] 2773. [bug] In autosigned zones, the SOA could be signed with the KSK. [RT #20628] 2772. [security] When validating, track whether pending data was from the additional section or not and only return it if validates as secure. [RT #20438] 2771. [bug] dnssec-signzone: DNSKEY records could be corrupted when importing from key files [RT #20624] 2770. [cleanup] Add log messages to resolver.c to indicate events causing FORMERR responses. [RT #20526] 2769. [cleanup] Change #2742 was incomplete. [RT #19589] 2768. [bug] dnssec-signzone: -S no longer implies -g [RT #20568] 2767. [bug] named could crash on startup if a zone was configured with auto-dnssec and there was no key-directory. [RT #20615] 2766. [bug] isc_socket_fdwatchpoke() should only update the socketmgr state if the socket is not pending on a read or write. [RT #20603] 2765. [bug] Skip masters for which the TSIG key cannot be found. [RT #20595] 2764. [bug] "rndc-confgen -a" could trigger a REQUIRE. [RT #20610] 2763. [bug] "rndc sign" didn't create an NSEC chain. [RT #20591] 2762. [bug] DLV validation failed with a local slave DLV zone. [RT #20577] 2761. [cleanup] Enable internal symbol table for backtrace only for systems that are known to work. Currently, BSD variants, Linux and Solaris are supported. [RT #20202] 2760. [cleanup] Corrected named-compilezone usage summary. [RT #20533] 2759. [doc] Add information about .jbk/.jnw files to the ARM. [RT #20303] 2758. [bug] win32: Added a workaround for a windows 2008 bug that could cause the UDP client handler to shut down. [RT #19176] 2757. [bug] dig: assertion failure could occur in connect timeout. [RT #20599] 2756. [bug] Fixed corrupt logfile message in update.c. [RT #20597] 2755. [placeholder] 2754. [bug] Secure-to-insecure transitions failed when zone was signed with NSEC3. [RT #20587] 2753. [bug] Removed an unnecessary warning that could appear when building an NSEC chain. [RT #20589] 2752. [bug] Locking violation. [RT #20587] 2751. [bug] Fixed a memory leak in dnssec-keyfromlabel. [RT #20588] 2750. [bug] dig: assertion failure could occur when a server didn't have an address. [RT #20579] 2749. [bug] ixfr-from-differences generated a non-minimal ixfr for NSEC3 signed zones. [RT #20452] 2748. [func] Identify bad answers from GTLD servers and treat them as referrals. [RT #18884] 2747. [bug] Journal roll forwards failed to set the re-signing time of RRSIGs correctly. [RT #20541] 2746. [port] hpux: address signed/unsigned expansion mismatch of dns_rbtnode_t.nsec. [RT #20542] 2745. [bug] configure script didn't probe the return type of gai_strerror(3) correctly. [RT #20573] 2744. [func] Log if a query was over TCP. [RT #19961] 2743. [bug] RRSIG could be incorrectly set in the NSEC3 record for a insecure delegation. --- 9.7.0b2 released --- 2742. [cleanup] Clarify some DNSSEC-related log messages in validator.c. [RT #19589] 2741. [func] Allow the dnssec-keygen progress messages to be suppressed (dnssec-keygen -q). Automatically suppress the progress messages when stdin is not a tty. [RT #20474] 2740. [placeholder] 2739. [cleanup] Clean up API for initializing and clearing trust anchors for a view. [RT #20211] 2738. [func] Add RSASHA256 and RSASHA512 tests to the dnssec system test. [RT #20453] 2737. [func] UPDATE requests can leak existence information. [RT #17261] 2736. [func] Improve the performance of NSEC signed zones with more than a normal amount of glue below a delegation. [RT #20191] 2735. [bug] dnssec-signzone could fail to read keys that were specified on the command line with full paths, but weren't in the current directory. [RT #20421] 2734. [port] cygwin: arpaname did not compile. [RT #20473] 2733. [cleanup] Clean up coding style in pkcs11-* tools. [RT #20355] 2732. [func] Add optional filter-aaaa-on-v4 option, available if built with './configure --enable-filter-aaaa'. Filters out AAAA answers to clients connecting via IPv4. (This is NOT recommended for general use.) [RT #20339] 2731. [func] Additional work on change 2709. The key parser will now ignore unrecognized fields when the minor version number of the private key format has been increased. It will reject any key with the major version number increased. [RT #20310] 2730. [func] Have dnssec-keygen display a progress indication a la 'openssl genrsa' on standard error. Note when the first '.' is followed by a long stop one has the choice between slow generation vs. poor random quality, i.e., '-r /dev/urandom'. [RT #20284] 2729. [func] When constructing a CNAME from a DNAME use the DNAME TTL. [RT #20451] 2728. [bug] dnssec-keygen, dnssec-keyfromlabel and dnssec-signzone now warn immediately if asked to write into a nonexistent directory. [RT #20278] 2727. [func] The 'key-directory' option can now specify a relative path. [RT #20154] 2726. [func] Added support for SHA-2 DNSSEC algorithms, RSASHA256 and RSASHA512. [RT #20023] 2725. [doc] Added information about the file "managed-keys.bind" to the ARM. [RT #20235] 2724. [bug] Updates to a existing node in secure zone using NSEC were failing. [RT #20448] 2723. [bug] isc_base32_totext(), isc_base32hex_totext(), and isc_base64_totext(), didn't always mark regions of memory as fully consumed after conversion. [RT #20445] 2722. [bug] Ensure that the memory associated with the name of a node in a rbt tree is not altered during the life of the node. [RT #20431] 2721. [port] Have dst__entropy_status() prime the random number generator. [RT #20369] 2720. [bug] RFC 5011 trust anchor updates could trigger an assert if the DNSKEY record was unsigned. [RT #20406] 2719. [func] Skip trusted/managed keys for unsupported algorithms. [RT #20392] 2718. [bug] The space calculations in opensslrsa_todns() were incorrect. [RT #20394] 2717. [bug] named failed to update the NSEC/NSEC3 record when the last private type record was removed as a result of completing the signing the zone with a key. [RT #20399] 2716. [bug] nslookup debug mode didn't return the ttl. [RT #20414] --- 9.7.0b1 released --- 2715. [bug] Require OpenSSL support to be explicitly disabled. [RT #20288] 2714. [port] aix/powerpc: 'asm("ics");' needs non standard assembler flags. 2713. [bug] powerpc: atomic operations missing asm("ics") / __isync() calls. 2712. [func] New 'auto-dnssec' zone option allows zone signing to be fully automated in zones configured for dynamic DNS. 'auto-dnssec allow;' permits a zone to be signed by creating keys for it in the key-directory and using 'rndc sign '. 'auto-dnssec maintain;' allows that too, plus it also keeps the zone's DNSSEC keys up to date according to their timing metadata. [RT #19943] 2711. [port] win32: Add the bin/pkcs11 tools into the full build. [RT #20372] 2710. [func] New 'dnssec-signzone -x' flag and 'dnskey-ksk-only' zone option cause a zone to be signed with only KSKs signing the DNSKEY RRset, not ZSKs. This reduces the size of a DNSKEY answer. [RT #20340] 2709. [func] Added some data fields, currently unused, to the private key file format, to allow implementation of explicit key rollover in a future release without impairing backward or forward compatibility. [RT #20310] 2708. [func] Insecure to secure and NSEC3 parameter changes via update are now fully supported and no longer require defines to enable. We now no longer overload the NSEC3PARAM flag field, nor the NSEC OPT bit at the apex. Secure to insecure changes are controlled by by the named.conf option 'secure-to-insecure'. Warning: If you had previously enabled support by adding defines at compile time to BIND 9.6 you should ensure that all changes that are in progress have completed prior to upgrading to BIND 9.7. BIND 9.7 is not backwards compatible. 2707. [func] dnssec-keyfromlabel no longer require engine name to be specified in the label if there is a default engine or the -E option has been used. Also, it now uses default algorithms as dnssec-keygen does (i.e., RSASHA1, or NSEC3RSASHA1 if -3 is used). [RT #20371] 2706. [bug] Loading a zone with a very large NSEC3 salt could trigger an assert. [RT #20368] 2705. [placeholder] 2704. [bug] Serial of dynamic and stub zones could be inconsistent with their SOA serial. [RT #19387] 2703. [func] Introduce an OpenSSL "engine" argument with -E for all binaries which can take benefit of crypto hardware. [RT #20230] 2702. [func] Update PKCS#11 tools (bin/pkcs11) [RT #20225 & all] 2701. [doc] Correction to ARM: hmac-md5 is no longer the only supported TSIG key algorithm. [RT #18046] 2700. [doc] The match-mapped-addresses option is discouraged. [RT #12252] 2699. [bug] Missing lock in rbtdb.c. [RT #20037] 2698. [placeholder] 2697. [port] win32: ensure that S_IFMT, S_IFDIR, S_IFCHR and S_IFREG are defined after including . [RT #20309] 2696. [bug] named failed to successfully process some valid acl constructs. [RT #20308] 2695. [func] DHCP/DDNS - update fdwatch code for use by DHCP. Modify the api to isc_sockfdwatch_t (the callback function for isc_socket_fdwatchcreate) to include information about the direction (read or write) and add isc_socket_fdwatchpoke. [RT #20253] 2694. [bug] Reduce default NSEC3 iterations from 100 to 10. [RT #19970] 2693. [port] Add some noreturn attributes. [RT #20257] 2692. [port] win32: 32/64 bit cleanups. [RT #20335] 2691. [func] dnssec-signzone: retain the existing NSEC or NSEC3 chain when re-signing a previously-signed zone. Use -u to modify NSEC3 parameters or switch between NSEC and NSEC3. [RT #20304] 2690. [bug] win32: fix isc_thread_key_getspecific() prototype. [RT #20315] 2689. [bug] Correctly handle snprintf result. [RT #20306] 2688. [bug] Use INTERFACE_F_POINTTOPOINT, not IFF_POINTOPOINT, to decide to fetch the destination address. [RT #20305] 2687. [bug] Fixed dnssec-signzone -S handling of revoked keys. Also, added warnings when revoking a ZSK, as this is not defined by protocol (but is legal). [RT #19943] 2686. [bug] dnssec-signzone should clean the old NSEC chain when signing with NSEC3 and vice versa. [RT #20301] 2685. [contrib] Update contrib/zkt to version 0.99c. [RT #20054] 2684. [cleanup] dig: formalize +ad and +cd as synonyms for +adflag and +cdflag. [RT #19305] 2683. [bug] dnssec-signzone should clean out old NSEC3 chains when the NSEC3 parameters used to sign the zone change. [RT #20246] 2682. [bug] "configure --enable-symtable=all" failed to build. [RT #20282] 2681. [bug] IPSECKEY RR of gateway type 3 was not correctly decoded. [RT #20269] 2680. [func] Move contrib/pkcs11-keygen to bin/pkcs11. [RT #20067] 2679. [func] dig -k can now accept TSIG keys in named.conf format. [RT #20031] 2678. [func] Treat DS queries as if "minimal-response yes;" was set. [RT #20258] 2677. [func] Changes to key metadata behavior: - Keys without "publish" or "active" dates set will no longer be used for smart signing. However, those dates will be set to "now" by default when a key is created; to generate a key but not use it yet, use dnssec-keygen -G. - New "inactive" date (dnssec-keygen/settime -I) sets the time when a key is no longer used for signing but is still published. - The "unpublished" date (-U) is deprecated in favor of "deleted" (-D). [RT #20247] 2676. [bug] --with-export-installdir should have been --with-export-includedir. [RT #20252] 2675. [bug] dnssec-signzone could crash if the key directory did not exist. [RT #20232] --- 9.7.0a3 released --- 2674. [bug] "dnssec-lookaside auto;" crashed if named was built without openssl. [RT #20231] 2673. [bug] The managed-keys.bind zone file could fail to load due to a spurious result from sync_keyzone() [RT #20045] 2672. [bug] Don't enable searching in 'host' when doing reverse lookups. [RT #20218] 2671. [bug] Add support for PKCS#11 providers not returning the public exponent in RSA private keys (OpenCryptoki for instance) in dnssec-keyfromlabel. [RT #19294] 2670. [bug] Unexpected connect failures failed to log enough information to be useful. [RT #20205] 2669. [func] Update PKCS#11 support to support Keyper HSM. Update PKCS#11 patch to be against openssl-0.9.8i. 2668. [func] Several improvements to dnssec-* tools, including: - dnssec-keygen and dnssec-settime can now set key metadata fields 0 (to unset a value, use "none") - dnssec-revoke sets the revocation date in addition to the revoke bit - dnssec-settime can now print individual metadata fields instead of always printing all of them, and can print them in unix epoch time format for use by scripts [RT #19942] 2667. [func] Add support for logging stack backtrace on assertion failure (not available for all platforms). [RT #19780] 2666. [func] Added an 'options' argument to dns_name_fromstring() (API change from 9.7.0a2). [RT #20196] 2665. [func] Clarify syntax for managed-keys {} statement, add ARM documentation about RFC 5011 support. [RT #19874] 2664. [bug] create_keydata() and minimal_update() in zone.c didn't properly check return values for some functions. [RT #19956] 2663. [func] win32: allow named to run as a service using "NT AUTHORITY\LocalService" as the account. [RT #19977] 2662. [bug] lwres_getipnodebyname() and lwres_getipnodebyaddr() returned a misleading error code when lwresd was down. [RT #20028] 2661. [bug] Check whether socket fd exceeds FD_SETSIZE when creating lwres context. [RT #20029] 2660. [func] Add a new set of DNS libraries for non-BIND9 applications. See README.libdns. [RT #19369] 2659. [doc] Clarify dnssec-keygen doc: key name must match zone name for DNSSEC keys. [RT #19938] 2658. [bug] dnssec-settime and dnssec-revoke didn't process key file paths correctly. [RT #20078] 2657. [cleanup] Lower "journal file does not exist, creating it" log level to debug 1. [RT #20058] 2656. [func] win32: add a "tools only" check box to the installer which causes it to only install dig, host, nslookup, nsupdate and relevant DLLs. [RT #19998] 2655. [doc] Document that key-directory does not affect bind.keys, rndc.key or session.key. [RT #20155] 2654. [bug] Improve error reporting on duplicated names for deny-answer-xxx. [RT #20164] 2653. [bug] Treat ENGINE_load_private_key() failures as key not found rather than out of memory. [RT #18033] 2652. [func] Provide more detail about what record is being deleted. [RT #20061] 2651. [bug] Dates could print incorrectly in K*.key files on 64-bit systems. [RT #20076] 2650. [bug] Assertion failure in dnssec-signzone when trying to read keyset-* files. [RT #20075] 2649. [bug] Set the domain for forward only zones. [RT #19944] 2648. [port] win32: isc_time_seconds() was broken. [RT #19900] 2647. [bug] Remove unnecessary SOA updates when a new KSK is added. [RT #19913] 2646. [bug] Incorrect cleanup on error in socket.c. [RT #19987] 2645. [port] "gcc -m32" didn't work on amd64 and x86_64 platforms which default to 64 bits. [RT #19927] --- 9.7.0a2 released --- 2644. [bug] Change #2628 caused a regression on some systems; named was unable to write the PID file and would fail on startup. [RT #20001] 2643. [bug] Stub zones interacted badly with NSEC3 support. [RT #19777] 2642. [bug] nsupdate could dump core on solaris when reading improperly formatted key files. [RT #20015] 2641. [bug] Fixed an error in parsing update-policy syntax, added a regression test to check it. [RT #20007] 2640. [security] A specially crafted update packet will cause named to exit. [RT #20000] 2639. [bug] Silence compiler warnings in gssapi code. [RT #19954] 2638. [bug] Install arpaname. [RT #19957] 2637. [func] Rationalize dnssec-signzone's signwithkey() calling. [RT #19959] 2636. [func] Simplify zone signing and key maintenance with the dnssec-* tools. Major changes: - all dnssec-* tools now take a -K option to specify a directory in which key files will be stored - DNSSEC can now store metadata indicating when they are scheduled to be published, activated, revoked or removed; these values can be set by dnssec-keygen or overwritten by the new dnssec-settime command - dnssec-signzone -S (for "smart") option reads key metadata and uses it to determine automatically which keys to publish to the zone, use for signing, revoke, or remove from the zone [RT #19816] 2635. [bug] isc_inet_ntop() incorrectly handled 0.0/16 addresses. [RT #19716] 2634. [port] win32: Add support for libxml2, enable statschannel. [RT #19773] 2633. [bug] Handle 15 bit rand() functions. [RT #19783] 2632. [func] util/kit.sh: warn if documentation appears to be out of date. [RT #19922] 2631. [bug] Handle "//", "/./" and "/../" in mkdirpath(). [RT #19926 ] 2630. [func] Improved syntax for DDNS autoconfiguration: use "update-policy local;" to switch on local DDNS in a zone. (The "ddns-autoconf" option has been removed.) [RT #19875] 2629. [port] Check for seteuid()/setegid(), use setresuid()/ setresgid() if not present. [RT #19932] 2628. [port] linux: Allow /var/run/named/named.pid to be opened at startup with reduced capabilities in operation. [RT #19884] 2627. [bug] Named aborted if the same key was included in trusted-keys more than once. [RT #19918] 2626. [bug] Multiple trusted-keys could trigger an assertion failure. [RT #19914] 2625. [bug] Missing UNLOCK in rbtdb.c. [RT #19865] 2624. [func] 'named-checkconf -p' will print out the parsed configuration. [RT #18871] 2623. [bug] Named started searches for DS non-optimally. [RT #19915] 2622. [bug] Printing of named.conf grammar was broken. [RT #19919] 2621. [doc] Made copyright boilerplate consistent. [RT #19833] 2620. [bug] Delay thawing the zone until the reload of it has completed successfully. [RT #19750] 2619. [func] Add support for RFC 5011, automatic trust anchor maintenance. The new "managed-keys" statement can be used in place of "trusted-keys" for zones which support this protocol. (Note: this syntax is expected to change prior to 9.7.0 final.) [RT #19248] 2618. [bug] The sdb and sdlz db_interator_seek() methods could loop infinitely. [RT #19847] 2617. [bug] ifconfig.sh failed to emit an error message when run from the wrong location. [RT #19375] 2616. [bug] 'host' used the nameservers from resolv.conf even when a explicit nameserver was specified. [RT #19852] 2615. [bug] "__attribute__((unused))" was in the wrong place for ia64 gcc builds. [RT #19854] 2614. [port] win32: 'named -v' should automatically be executed in the foreground. [RT #19844] 2613. [placeholder] --- 9.7.0a1 released --- 2612. [func] Add default values for the arguments to dnssec-keygen. Without arguments, it will now generate a 1024-bit RSASHA1 zone-signing key, or with the -f KSK option, a 2048-bit RSASHA1 key-signing key. [RT #19300] 2611. [func] Add -l option to dnssec-dsfromkey to generate DLV records instead of DS records. [RT #19300] 2610. [port] sunos: Change #2363 was not complete. [RT #19796] 2609. [func] Simplify the configuration of dynamic zones: - add ddns-confgen command to generate configuration text for named.conf - add zone option "ddns-autoconf yes;", which causes named to generate a TSIG session key and allow updates to the zone using that key - add '-l' (localhost) option to nsupdate, which causes nsupdate to connect to a locally-running named process using the session key generated by named [RT #19284] 2608. [func] Perform post signing verification checks in dnssec-signzone. These can be disabled with -P. The post sign verification test ensures that for each algorithm in use there is at least one non revoked self signed KSK key. That all revoked KSK keys are self signed. That all records in the zone are signed by the algorithm. [RT #19653] 2607. [bug] named could incorrectly delete NSEC3 records for empty nodes when processing a update request. [RT #19749] 2606. [bug] "delegation-only" was not being accepted in delegation-only type zones. [RT #19717] 2605. [bug] Accept DS responses from delegation only zones. [RT # 19296] 2604. [func] Add support for DNS rebinding attack prevention through new options, deny-answer-addresses and deny-answer-aliases. Based on contributed code from JD Nurmi, Google. [RT #18192] 2603. [port] win32: handle .exe extension of named-checkzone and named-comilezone argv[0] names under windows. [RT #19767] 2602. [port] win32: fix debugging command line build of libisccfg. [RT #19767] 2601. [doc] Mention file creation mode mask in the named manual page. 2600. [doc] ARM: miscellaneous reformatting for different page widths. [RT #19574] 2599. [bug] Address rapid memory growth when validation fails. [RT #19654] 2598. [func] Reserve the -F flag. [RT #19657] 2597. [bug] Handle a validation failure with a insecure delegation from a NSEC3 signed master/slave zone. [RT #19464] 2596. [bug] Stale tree nodes of cache/dynamic rbtdb could stay long, leading to inefficient memory usage or rejecting newer cache entries in the worst case. [RT #19563] 2595. [bug] Fix unknown extended rcodes in dig. [RT #19625] 2594. [func] Have rndc warn if using its default configuration file when the key file also exists. [RT #19424] 2593. [bug] Improve a corner source of SERVFAILs [RT #19632] 2592. [bug] Treat "any" as a type in nsupdate. [RT #19455] 2591. [bug] named could die when processing a update in removed_orphaned_ds(). [RT #19507] 2590. [func] Report zone/class of "update with no effect". [RT #19542] 2589. [bug] dns_db_unregister() failed to clear '*dbimp'. [RT #19626] 2588. [bug] SO_REUSEADDR could be set unconditionally after failure of bind(2) call. This should be rare and mostly harmless, but may cause interference with other processes that happen to use the same port. [RT #19642] 2587. [func] Improve logging by reporting serial numbers for when zone serial has gone backwards or unchanged. [RT #19506] 2586. [bug] Missing cleanup of SIG rdataset in searching a DLZ DB or SDB. [RT #19577] 2585. [bug] Uninitialized socket name could be referenced via a statistics channel, triggering an assertion failure in XML rendering. [RT #19427] 2584. [bug] alpha: gcc optimization could break atomic operations. [RT #19227] 2583. [port] netbsd: provide a control to not add the compile date to the version string, -DNO_VERSION_DATE. 2582. [bug] Don't emit warning log message when we attempt to remove non-existent journal. [RT #19516] 2581. [contrib] dlz/mysql set MYSQL_OPT_RECONNECT option on connection. Requires MySQL 5.0.19 or later. [RT #19084] 2580. [bug] UpdateRej statistics counter could be incremented twice for one rejection. [RT #19476] 2579. [bug] DNSSEC lookaside validation failed to handle unknown algorithms. [RT #19479] 2578. [bug] Changed default sig-signing-type to 65534, because 65535 turns out to be reserved. [RT #19477] 2577. [doc] Clarified some statistics counters. [RT #19454] 2576. [bug] NSEC record were not being correctly signed when a zone transitions from insecure to secure. Handle such incorrectly signed zones. [RT #19114] 2575. [func] New functions dns_name_fromstring() and dns_name_tostring(), to simplify conversion of a string to a dns_name structure and vice versa. [RT #19451] 2574. [doc] Document nsupdate -g and -o. [RT #19351] 2573. [bug] Replacing a non-CNAME record with a CNAME record in a single transaction in a signed zone failed. [RT #19397] 2572. [func] Simplify DLV configuration, with a new option "dnssec-lookaside auto;" This is the equivalent of "dnssec-lookaside . trust-anchor dlv.isc.org;" plus setting a trusted-key for dlv.isc.org. Note: The trusted key is hard-coded into named, but is also stored in (and can be overridden by) $sysconfdir/bind.keys. As the ISC DLV key rolls over it can be kept up to date by replacing the bind.keys file with a key downloaded from https://www.isc.org/solutions/dlv. [RT #18685] 2571. [func] Add a new tool "arpaname" which translates IP addresses to the corresponding IN-ADDR.ARPA or IP6.ARPA name. [RT #18976] 2570. [func] Log the destination address the query was sent to. [RT #19209] 2569. [func] Move journalprint, nsec3hash, and genrandom commands from bin/tests into bin/tools; "make install" will put them in $sbindir. [RT #19301] 2568. [bug] Report when the write to indicate a otherwise successful start fails. [RT #19360] 2567. [bug] dst__privstruct_writefile() could miss write errors. write_public_key() could miss write errors. dnssec-dsfromkey could miss write errors. [RT #19360] 2566. [cleanup] Clarify logged message when an insecure DNSSEC response arrives from a zone thought to be secure: "insecurity proof failed" instead of "not insecure". [RT #19400] 2565. [func] Add support for HIP record. Includes new functions dns_rdata_hip_first(), dns_rdata_hip_next() and dns_rdata_hip_current(). [RT #19384] 2564. [bug] Only take EDNS fallback steps when processing timeouts. [RT #19405] 2563. [bug] Dig could leak a socket causing it to wait forever to exit. [RT #19359] 2562. [doc] ARM: miscellaneous improvements, reorganization, and some new content. 2561. [doc] Add isc-config.sh(1) man page. [RT #16378] 2560. [bug] Add #include to iptable.c. [RT #18258] 2559. [bug] dnssec-dsfromkey could compute bad DS records when reading from a K* files. [RT #19357] 2558. [func] Set the ownership of missing directories created for pid-file if -u has been specified on the command line. [RT #19328] 2557. [cleanup] PCI compliance: * new libisc log module file * isc_dir_chroot() now also changes the working directory to "/". * additional INSISTs * additional logging when files can't be removed. 2556. [port] Solaris: mkdir(2) on tmpfs filesystems does not do the error checks in the correct order resulting in the wrong error code sometimes being returned. [RT #19249] 2555. [func] dig: when emitting a hex dump also display the corresponding characters. [RT #19258] 2554. [bug] Validation of uppercase queries from NSEC3 zones could fail. [RT #19297] 2553. [bug] Reference leak on DNSSEC validation errors. [RT #19291] 2552. [bug] zero-no-soa-ttl-cache was not being honored. [RT #19340] 2551. [bug] Potential Reference leak on return. [RT #19341] 2550. [bug] Check --with-openssl= finds . [RT #19343] 2549. [port] linux: define NR_OPEN if not currently defined. [RT #19344] 2548. [bug] Install iterated_hash.h. [RT #19335] 2547. [bug] openssl_link.c:mem_realloc() could reference an out-of-range area of the source buffer. New public function isc_mem_reallocate() was introduced to address this bug. [RT #19313] 2546. [func] Add --enable-openssl-hash configure flag to use OpenSSL (in place of internal routine) for hash functions (MD5, SHA[12] and HMAC). [RT #18815] 2545. [doc] ARM: Legal hostname checking (check-names) is for SRV RDATA too. [RT #19304] 2544. [cleanup] Removed unused structure members in adb.c. [RT #19225] 2543. [contrib] Update contrib/zkt to version 0.98. [RT #19113] 2542. [doc] Update the description of dig +adflag. [RT #19290] 2541. [bug] Conditionally update dispatch manager statistics. [RT #19247] 2540. [func] Add a nibble mode to $GENERATE. [RT #18872] 2539. [security] Update the interaction between recursion, allow-query, allow-query-cache and allow-recursion. [RT #19198] 2538. [bug] cache/ADB memory could grow over max-cache-size, especially with threads and smaller max-cache-size values. [RT #19240] 2537. [func] Added more statistics counters including those on socket I/O events and query RTT histograms. [RT #18802] 2536. [cleanup] Silence some warnings when -Werror=format-security is specified. [RT #19083] 2535. [bug] dig +showsearch and +trace interacted badly. [RT #19091] 2534. [func] Check NAPTR records regular expressions and replacement strings to ensure they are syntactically valid and consistent. [RT #18168] 2533. [doc] ARM: document @ (at-sign). [RT #17144] 2532. [bug] dig: check the question section of the response to see if it matches the asked question. [RT #18495] 2531. [bug] Change #2207 was incomplete. [RT #19098] 2530. [bug] named failed to reject insecure to secure transitions via UPDATE. [RT #19101] 2529. [cleanup] Upgrade libtool to silence complaints from recent version of autoconf. [RT #18657] 2528. [cleanup] Silence spurious configure warning about --datarootdir [RT #19096] 2527. [placeholder] 2526. [func] New named option "attach-cache" that allows multiple views to share a single cache to save memory and improve lookup efficiency. Based on contributed code from Barclay Osborn, Google. [RT #18905] 2525. [func] New logging category "query-errors" to provide detailed internal information about query failures, especially about server failures. [RT #19027] 2524. [port] sunos: dnssec-signzone needs strtoul(). [RT #19129] 2523. [bug] Random type rdata freed by dns_nsec_typepresent(). [RT #19112] 2522. [security] Handle -1 from DSA_do_verify() and EVP_VerifyFinal(). 2521. [bug] Improve epoll cross compilation support. [RT #19047] 2520. [bug] Update xml statistics version number to 2.0 as change #2388 made the schema incompatible to the previous version. [RT #19080] 2519. [bug] dig/host with -4 or -6 didn't work if more than two nameserver addresses of the excluded address family preceded in resolv.conf. [RT #19081] 2518. [func] Add support for the new CERT types from RFC 4398. [RT #19077] 2517. [bug] dig +trace with -4 or -6 failed when it chose a nameserver address of the excluded address type. [RT #18843] 2516. [bug] glue sort for responses was performed even when not needed. [RT #19039] 2515. [port] win32: build dnssec-dsfromkey and dnssec-keyfromlabel. [RT #19063] 2514. [bug] dig/host failed with -4 or -6 when resolv.conf contains a nameserver of the excluded address family. [RT #18848] 2513. [bug] Fix windows cli build. [RT #19062] 2512. [func] Print a summary of the cached records which make up the negative response. [RT #18885] 2511. [cleanup] dns_rdata_tofmttext() add const to linebreak. [RT #18885] 2510. [bug] "dig +sigchase" could trigger REQUIRE failures. [RT #19033] 2509. [bug] Specifying a fixed query source port was broken. [RT #19051] 2508. [placeholder] 2507. [func] Log the recursion quota values when killing the oldest query or refusing to recurse due to quota. [RT #19022] 2506. [port] solaris: Check at configure time if hack_shutup_pthreadonceinit is needed. [RT #19037] 2505. [port] Treat amd64 similarly to x86_64 when determining atomic operation support. [RT #19031] 2504. [bug] Address race condition in the socket code. [RT #18899] 2503. [port] linux: improve compatibility with Linux Standard Base. [RT #18793] 2502. [cleanup] isc_radix: Improve compliance with coding style, document function in . [RT #18534] 2501. [func] $GENERATE now supports all rdata types. Multi-field rdata types need to be quoted. See the ARM for details. [RT #18368] 2500. [contrib] contrib/sdb/pgsql/zonetodb.c called non-existent function. [RT #18582] 2499. [port] solaris: lib/lwres/getaddrinfo.c namespace clash. [RT #18837] --- 9.6.0rc1 released --- 2498. [bug] Removed a bogus function argument used with ISC_SOCKET_USE_POLLWATCH: it could cause compiler warning or crash named with the debug 1 level of logging. [RT #18917] 2497. [bug] Don't add RRSIG bit to NSEC3 bit map for insecure delegation. 2496. [bug] Add sanity length checks to NSID option. [RT #18813] 2495. [bug] Tighten RRSIG checks. [RT #18795] 2494. [bug] isc/radix.h, dns/sdlz.h and dns/dlz.h were not being installed. [RT #18826] 2493. [bug] The linux capabilities code was not correctly cleaning up after itself. [RT #18767] 2492. [func] Rndc status now reports the number of cpus discovered and the number of worker threads when running multi-threaded. [RT #18273] 2491. [func] Attempt to re-use a local port if we are already using the port. [RT #18548] 2490. [port] aix: work around a kernel bug where IPV6_RECVPKTINFO is cleared when IPV6_V6ONLY is set. [RT #18785] 2489. [port] solaris: Workaround Solaris's kernel bug about /dev/poll: http://bugs.opensolaris.org/view_bug.do?bug_id=6724237 Define ISC_SOCKET_USE_POLLWATCH at build time to enable this workaround. [RT #18870] 2488. [func] Added a tool, dnssec-dsfromkey, to generate DS records from keyset and .key files. [RT #18694] 2487. [bug] Give TCP connections longer to complete. [RT #18675] 2486. [func] The default locations for named.pid and lwresd.pid are now /var/run/named/named.pid and /var/run/lwresd/lwresd.pid respectively. This allows the owner of the containing directory to be set, for "named -u" support, and allows there to be a permanent symbolic link in the path, for "named -t" support. [RT #18306] 2485. [bug] Change update's the handling of obscured RRSIG records. Not all orphaned DS records were being removed. [RT #18828] 2484. [bug] It was possible to trigger a REQUIRE failure when adding NSEC3 proofs to the response in query_addwildcardproof(). [RT #18828] 2483. [port] win32: chroot() is not supported. [RT #18805] 2482. [port] libxml2: support versions 2.7.* in addition to 2.6.*. [RT #18806] --- 9.6.0b1 released --- 2481. [bug] rbtdb.c:matchparams() failed to handle NSEC3 chain collisions. [RT #18812] 2480. [bug] named could fail to emit all the required NSEC3 records. [RT #18812] 2479. [bug] xfrout:covers was not properly initialized. [RT #18801] 2478. [bug] 'addresses' could be used uninitialized in configure_forward(). [RT #18800] 2477. [bug] dig: the global option to print the command line is +cmd not print_cmd. Update the output to reflect this. [RT #17008] 2476. [doc] ARM: improve documentation for max-journal-size and ixfr-from-differences. [RT #15909] [RT #18541] 2475. [bug] LRU cache cleanup under overmem condition could purge particular entries more aggressively. [RT #17628] 2474. [bug] ACL structures could be allocated with insufficient space, causing an array overrun. [RT #18765] 2473. [port] linux: raise the limit on open files to the possible maximum value before spawning threads; 'files' specified in named.conf doesn't seem to work with threads as expected. [RT #18784] 2472. [port] linux: check the number of available cpu's before calling chroot as it depends on "/proc". [RT #16923] 2471. [bug] named-checkzone was not reporting missing mandatory glue when sibling checks were disabled. [RT #18768] 2470. [bug] Elements of the isc_radix_node_t could be incorrectly overwritten. [RT #18719] 2469. [port] solaris: Work around Solaris's select() limitations. [RT #18769] 2468. [bug] Resolver could try unreachable servers multiple times. [RT #18739] 2467. [bug] Failure of fcntl(F_DUPFD) wasn't logged. [RT #18740] 2466. [doc] ARM: explain max-cache-ttl 0 SERVFAIL issue. [RT #18302] 2465. [bug] Adb's handling of lame addresses was different for IPv4 and IPv6. [RT #18738] 2464. [port] linux: check that a capability is present before trying to set it. [RT #18135] 2463. [port] linux: POSIX doesn't include the IPv6 Advanced Socket API and glibc hides parts of the IPv6 Advanced Socket API as a result. This is stupid as it breaks how the two halves (Basic and Advanced) of the IPv6 Socket API were designed to be used but we have to live with it. Define _GNU_SOURCE to pull in the IPv6 Advanced Socket API. [RT #18388] 2462. [doc] Document -m (enable memory usage debugging) option for dig. [RT #18757] 2461. [port] sunos: Change #2363 was not complete. [RT #17513] --- 9.6.0a1 released --- 2460. [bug] Don't call dns_db_getnsec3parameters() on the cache. [RT #18697] 2459. [contrib] Import dnssec-zkt to contrib/zkt. [RT #18448] 2458. [doc] ARM: update and correction for max-cache-size. [RT #18294] 2457. [tuning] max-cache-size is reverted to 0, the previous default. It should be safe because expired cache entries are also purged. [RT #18684] 2456. [bug] In ACLs, ::/0 and 0.0.0.0/0 would both match any address, regardless of family. They now correctly distinguish IPv4 from IPv6. [RT #18559] 2455. [bug] Stop metadata being transferred via axfr/ixfr. [RT #18639] 2454. [func] nsupdate: you can now set a default ttl. [RT #18317] 2453. [bug] Remove NULL pointer dereference in dns_journal_print(). [RT #18316] 2452. [func] Improve bin/test/journalprint. [RT #18316] 2451. [port] solaris: handle runtime linking better. [RT #18356] 2450. [doc] Fix lwresd docbook problem for manual page. [RT #18672] 2449. [placeholder] 2448. [func] Add NSEC3 support. [RT #15452] 2447. [cleanup] libbind has been split out as a separate product. 2446. [func] Add a new log message about build options on startup. A new command-line option '-V' for named is also provided to show this information. [RT #18645] 2445. [doc] ARM out-of-date on empty reverse zones (list includes RFC1918 address, but these are not yet compiled in). [RT #18578] 2444. [port] Linux, FreeBSD, AIX: Turn off path mtu discovery (clear DF) for UDP responses and requests. 2443. [bug] win32: UDP connect() would not generate an event, and so connected UDP sockets would never clean up. Fix this by doing an immediate WSAConnect() rather than an io completion port type for UDP. 2442. [bug] A lock could be destroyed twice. [RT #18626] 2441. [bug] isc_radix_insert() could copy radix tree nodes incompletely. [RT #18573] 2440. [bug] named-checkconf used an incorrect test to determine if an ACL was set to none. 2439. [bug] Potential NULL dereference in dns_acl_isanyornone(). [RT #18559] 2438. [bug] Timeouts could be logged incorrectly under win32. 2437. [bug] Sockets could be closed too early, leading to inconsistent states in the socket module. [RT #18298] 2436. [security] win32: UDP client handler can be shutdown. [RT #18576] 2435. [bug] Fixed an ACL memory leak affecting win32. 2434. [bug] Fixed a minor error-reporting bug in lib/isc/win32/socket.c. 2433. [tuning] Set initial timeout to 800ms. 2432. [bug] More Windows socket handling improvements. Stop using I/O events and use IO Completion Ports throughout. Rewrite the receive path logic to make it easier to support multiple simultaneous requesters in the future. Add stricter consistency checking as a compile-time option (define ISC_SOCKET_CONSISTENCY_CHECKS; defaults to off). 2431. [bug] Acl processing could leak memory. [RT #18323] 2430. [bug] win32: isc_interval_set() could round down to zero if the input was less than NS_INTERVAL nanoseconds. Round up instead. [RT #18549] 2429. [doc] nsupdate should be in section 1 of the man pages. [RT #18283] 2428. [bug] dns_iptable_merge() mishandled merges of negative tables. [RT #18409] 2427. [func] Treat DNSKEY queries as if "minimal-response yes;" was set. [RT #18528] 2426. [bug] libbind: inet_net_pton() can sometimes return the wrong value if excessively large net masks are supplied. [RT #18512] 2425. [bug] named didn't detect unavailable query source addresses at load time. [RT #18536] 2424. [port] configure now probes for a working epoll implementation. Allow the use of kqueue, epoll and /dev/poll to be selected at compile time. [RT #18277] 2423. [security] Randomize server selection on queries, so as to make forgery a little more difficult. Instead of always preferring the server with the lowest RTT, pick a server with RTT within the same 128 millisecond band. [RT #18441] 2422. [bug] Handle the special return value of a empty node as if it was a NXRRSET in the validator. [RT #18447] 2421. [func] Add new command line option '-S' for named to specify the max number of sockets. [RT #18493] Use caution: this option may not work for some operating systems without rebuilding named. 2420. [bug] Windows socket handling cleanup. Let the io completion event send out canceled read/write done events, which keeps us from writing to memory we no longer have ownership of. Add debugging socket_log() function. Rework TCP socket handling to not leak sockets. 2419. [cleanup] Document that isc_socket_create() and isc_socket_open() should not be used for isc_sockettype_fdwatch sockets. [RT #18521] 2418. [bug] AXFR request on a DLZ could trigger a REQUIRE failure [RT #18430] 2417. [bug] Connecting UDP sockets for outgoing queries could unexpectedly fail with an 'address already in use' error. [RT #18411] 2416. [func] Log file descriptors that cause exceeding the internal maximum. [RT #18460] 2415. [bug] 'rndc dumpdb' could trigger various assertion failures in rbtdb.c. [RT #18455] 2414. [bug] A masterdump context held the database lock too long, causing various troubles such as dead lock and recursive lock acquisition. [RT #18311, #18456] 2413. [bug] Fixed an unreachable code path in socket.c. [RT #18442] 2412. [bug] win32: address a resource leak. [RT #18374] 2411. [bug] Allow using a larger number of sockets than FD_SETSIZE for select(). To enable this, set ISC_SOCKET_MAXSOCKETS at compilation time. [RT #18433] Note: with changes #2469 and #2421 above, there is no need to tweak ISC_SOCKET_MAXSOCKETS at compilation time any more. 2410. [bug] Correctly delete m_versionInfo. [RT #18432] 2409. [bug] Only log that we disabled EDNS processing if we were subsequently successful. [RT #18029] 2408. [bug] A duplicate TCP dispatch event could be sent, which could then trigger an assertion failure in resquery_response(). [RT #18275] 2407. [port] hpux: test for sys/dyntune.h. [RT #18421] 2406. [placeholder] 2405. [cleanup] The default value for dnssec-validation was changed to "yes" in 9.5.0-P1 and all subsequent releases; this was inadvertently omitted from CHANGES at the time. 2404. [port] hpux: files unlimited support. 2403. [bug] TSIG context leak. [RT #18341] 2402. [port] Support Solaris 2.11 and over. [RT #18362] 2401. [bug] Expect to get E[MN]FILE errno internal_accept() (from accept() or fcntl() system calls). [RT #18358] 2400. [bug] Log if kqueue()/epoll_create()/open(/dev/poll) fails. [RT #18297] 2399. [placeholder] 2398. [bug] Improve file descriptor management. New, temporary, named.conf option reserved-sockets, default 512. [RT #18344] 2397. [bug] gssapi_functions had too many elements. [RT #18355] 2396. [bug] Don't set SO_REUSEADDR for randomized ports. [RT #18336] 2395. [port] Avoid warning and no effect from "files unlimited" on Linux when running as root. [RT #18335] 2394. [bug] Default configuration options set the limit for open files to 'unlimited' as described in the documentation. [RT #18331] 2393. [bug] nested acls containing keys could trigger an assertion in acl.c. [RT #18166] 2392. [bug] remove 'grep -q' from acl test script, some platforms don't support it. [RT #18253] 2391. [port] hpux: cover additional recvmsg() error codes. [RT #18301] 2390. [bug] dispatch.c could make a false warning on 'odd socket'. [RT #18301]. 2389. [bug] Move the "working directory writable" check to after the ns_os_changeuser() call. [RT #18326] 2388. [bug] Avoid using tables for layout purposes in statistics XSL [RT #18159]. 2387. [bug] Silence compiler warnings in lib/isc/radix.c. [RT #18147] [RT #18258] 2386. [func] Add warning about too small 'open files' limit. [RT #18269] 2385. [bug] A condition variable in socket.c could leak in rare error handling [RT #17968]. 2384. [security] Fully randomize UDP query ports to improve forgery resilience. [RT #17949, #18098] 2383. [bug] named could double queries when they resulted in SERVFAIL due to overkilling EDNS0 failure detection. [RT #18182] 2382. [doc] Add descriptions of DHCID, IPSECKEY, SPF and SSHFP to ARM. 2381. [port] dlz/mysql: support multiple install layouts for mysql. /include/{,mysql/}mysql.h and /lib/{,mysql/}. [RT #18152] 2380. [bug] dns_view_find() was not returning NXDOMAIN/NXRRSET proofs which, in turn, caused validation failures for insecure zones immediately below a secure zone the server was authoritative for. [RT #18112] 2379. [contrib] queryperf/gen-data-queryperf.py: removed redundant TLDs and supported RRs with TTLs [RT #17972] 2378. [bug] gssapi_functions{} had a redundant member in BIND 9.5. [RT #18169] 2377. [bug] Address race condition in dnssec-signzone. [RT #18142] 2376. [bug] Change #2144 was not complete. 2375. [placeholder] 2374. [bug] "blackhole" ACLs could cause named to segfault due to some uninitialized memory. [RT #18095] 2373. [bug] Default values of zone ACLs were re-parsed each time a new zone was configured, causing an overconsumption of memory. [RT #18092] 2372. [bug] Fixed incorrect TAG_HMACSHA256_BITS value [RT #18047] 2371. [doc] Add +nsid option to dig man page. [RT #18039] 2370. [bug] "rndc freeze" could trigger an assertion in named when called on a nonexistent zone. [RT #18050] 2369. [bug] libbind: Array bounds overrun on read in bitncmp(). [RT #18054] 2368. [port] Linux: use libcap for capability management if possible. [RT #18026] 2367. [bug] Improve counting of dns_resstatscounter_retry [RT #18030] 2366. [bug] Adb shutdown race. [RT #18021] 2365. [bug] Fix a bug that caused dns_acl_isany() to return spurious results. [RT #18000] 2364. [bug] named could trigger a assertion when serving a malformed signed zone. [RT #17828] 2363. [port] sunos: pre-set "lt_cv_sys_max_cmd_len=4096;". [RT #17513] 2362. [cleanup] Make "rrset-order fixed" a compile-time option. settable by "./configure --enable-fixed-rrset". Disabled by default. [RT #17977] 2361. [bug] "recursion" statistics counter could be counted multiple times for a single query. [RT #17990] 2360. [bug] Fix a condition where we release a database version (which may acquire a lock) while holding the lock. 2359. [bug] Fix NSID bug. [RT #17942] 2358. [doc] Update host's default query description. [RT #17934] 2357. [port] Don't use OpenSSL's engine support in versions before OpenSSL 0.9.7f. [RT #17922] 2356. [bug] Built in mutex profiler was not scalable enough. [RT #17436] 2355. [func] Extend the number statistics counters available. [RT #17590] 2354. [bug] Failed to initialize some rdatasetheader_t elements. [RT #17927] 2353. [func] Add support for Name Server ID (RFC 5001). 'dig +nsid' requests NSID from server. 'request-nsid yes;' causes recursive server to send NSID requests to upstream servers. Server responds to NSID requests with the string configured by 'server-id' option. [RT #17091] 2352. [bug] Various GSS_API fixups. [RT #17729] 2351. [bug] convertxsl.pl generated very long lines. [RT #17906] 2350. [port] win32: IPv6 support. [RT #17797] 2349. [func] Provide incremental re-signing support for secure dynamic zones. [RT #1091] 2348. [func] Use the EVP interface to OpenSSL. Add PKCS#11 support. Documentation is in the new README.pkcs11 file. New tool, dnssec-keyfromlabel, which takes the label of a key pair in a HSM and constructs a DNS key pair for use by named and dnssec-signzone. [RT #16844] 2347. [bug] Delete now traverses the RB tree in the canonical order. [RT #17451] 2346. [func] Memory statistics now cover all active memory contexts in increased detail. [RT #17580] 2345. [bug] named-checkconf failed to detect when forwarders were set at both the options/view level and in a root zone. [RT #17671] 2344. [bug] Improve "logging{ file ...; };" documentation. [RT #17888] 2343. [bug] (Seemingly) duplicate IPv6 entries could be created in ADB. [RT #17837] 2342. [func] Use getifaddrs() if available under Linux. [RT #17224] 2341. [bug] libbind: add missing -I../include for off source tree builds. [RT #17606] 2340. [port] openbsd: interface configuration. [RT #17700] 2339. [port] tru64: support for libbind. [RT #17589] 2338. [bug] check_ds() could be called with a non DS rdataset. [RT #17598] 2337. [bug] BUILD_LDFLAGS was not being correctly set. [RT #17614] 2336. [func] If "named -6" is specified then listen on all IPv6 interfaces if there are not listen-on-v6 clauses in named.conf. [RT #17581] 2335. [port] sunos: libbind and *printf() support for long long. [RT #17513] 2334. [bug] Bad REQUIRES in fromstruct_in_naptr(), off by one bug in fromstruct_txt(). [RT #17609] 2333. [bug] Fix off by one error in isc_time_nowplusinterval(). [RT #17608] 2332. [contrib] query-loc-0.4.0. [RT #17602] 2331. [bug] Failure to regenerate any signatures was not being reported nor being past back to the UPDATE client. [RT #17570] 2330. [bug] Remove potential race condition when handling over memory events. [RT #17572] WARNING: API CHANGE: over memory callback function now needs to call isc_mem_waterack(). See for details. 2329. [bug] Clearer help text for dig's '-x' and '-i' options. 2328. [maint] Add AAAA addresses for A.ROOT-SERVERS.NET, F.ROOT-SERVERS.NET, H.ROOT-SERVERS.NET, J.ROOT-SERVERS.NET, K.ROOT-SERVERS.NET and M.ROOT-SERVERS.NET. 2327. [bug] It was possible to dereference a NULL pointer in rbtdb.c. Implement dead node processing in zones as we do for caches. [RT #17312] 2326. [bug] It was possible to trigger a INSIST in the acache processing. 2325. [port] Linux: use capset() function if available. [RT #17557] 2324. [bug] Fix IPv6 matching against "any;". [RT #17533] 2323. [port] tru64: namespace clash. [RT #17547] 2322. [port] MacOS: work around the limitation of setrlimit() for RLIMIT_NOFILE. [RT #17526] 2321. [placeholder] 2320. [func] Make statistics counters thread-safe for platforms that support certain atomic operations. [RT #17466] 2319. [bug] Silence Coverity warnings in lib/dns/rdata/in_1/apl_42.c. [RT #17469] 2318. [port] sunos fixes for libbind. [RT #17514] 2317. [bug] "make distclean" removed bind9.xsl.h. [RT #17518] 2316. [port] Missing #include in lib/dns/gssapictx.c. [RT #17513] 2315. [bug] Used incorrect address family for mapped IPv4 addresses in acl.c. [RT #17519] 2314. [bug] Uninitialized memory use on error path in bin/named/lwdnoop.c. [RT #17476] 2313. [cleanup] Silence Coverity warnings. Handle private stacks. [RT #17447] [RT #17478] 2312. [cleanup] Silence Coverity warning in lib/isc/unix/socket.c. [RT #17458] 2311. [bug] IPv6 addresses could match IPv4 ACL entries and vice versa. [RT #17462] 2310. [bug] dig, host, nslookup: flush stdout before emitting debug/fatal messages. [RT #17501] 2309. [cleanup] Fix Coverity warnings in lib/dns/acl.c and iptable.c. [RT #17455] 2308. [cleanup] Silence Coverity warning in bin/named/controlconf.c. [RT #17495] 2307. [bug] Remove infinite loop from lib/dns/sdb.c. [RT #17496] 2306. [bug] Remove potential race from lib/dns/resolver.c. [RT #17470] 2305. [security] inet_network() buffer overflow. CVE-2008-0122. 2304. [bug] Check returns from all dns_rdata_tostruct() calls. [RT #17460] 2303. [bug] Remove unnecessary code from bin/named/lwdgnba.c. [RT #17471] 2302. [bug] Fix memset() calls in lib/tests/t_api.c. [RT #17472] 2301. [bug] Remove resource leak and fix error messages in bin/tests/system/lwresd/lwtest.c. [RT #17474] 2300. [bug] Fixed failure to close open file in bin/tests/names/t_names.c. [RT #17473] 2299. [bug] Remove unnecessary NULL check in bin/nsupdate/nsupdate.c. [RT #17475] 2298. [bug] isc_mutex_lock() failure not caught in bin/tests/timers/t_timers.c. [RT #17468] 2297. [bug] isc_entropy_createfilesource() failure not caught in bin/tests/dst/t_dst.c. [RT #17467] 2296. [port] Allow docbook stylesheet location to be specified to configure. [RT #17457] 2295. [bug] Silence static overrun error in bin/named/lwaddr.c. [RT #17459] 2294. [func] Allow the experimental statistics channels to have multiple connections and ACL. Note: the stats-server and stats-server-v6 options available in the previous beta releases are replaced with the generic statistics-channels statement. 2293. [func] Add ACL regression test. [RT #17375] 2292. [bug] Log if the working directory is not writable. [RT #17312] 2291. [bug] PR_SET_DUMPABLE may be set too late. Also report failure to set PR_SET_DUMPABLE. [RT #17312] 2290. [bug] Let AD in the query signal that the client wants AD set in the response. [RT #17301] 2289. [func] named-checkzone now reports the out-of-zone CNAME found. [RT #17309] 2288. [port] win32: mark service as running when we have finished loading. [RT #17441] 2287. [bug] Use 'volatile' if the compiler supports it. [RT #17413] 2286. [func] Allow a TCP connection to be used as a weak authentication method for reverse zones. New update-policy methods tcp-self and 6to4-self. [RT #17378] 2285. [func] Test framework for client memory context management. [RT #17377] 2284. [bug] Memory leak in UPDATE prerequisite processing. [RT #17377] 2283. [bug] TSIG keys were not attaching to the memory context. TSIG keys should use the rings memory context rather than the clients memory context. [RT #17377] 2282. [bug] Acl code fixups. [RT #17346] [RT #17374] 2281. [bug] Attempts to use undefined acls were not being logged. [RT #17307] 2280. [func] Allow the experimental http server to be reached over IPv6 as well as IPv4. [RT #17332] 2279. [bug] Use setsockopt(SO_NOSIGPIPE), when available, to protect applications from receiving spurious SIGPIPE signals when using the resolver. 2278. [bug] win32: handle the case where Windows returns no search list or DNS suffix. [RT #17354] 2277. [bug] Empty zone names were not correctly being caught at in the post parse checks. [RT #17357] 2276. [bug] Install . [RT #17359] 2275. [func] Add support to dig to perform IXFR queries over UDP. [RT #17235] 2274. [func] Log zone transfer statistics. [RT #17336] 2273. [bug] Adjust log level to WARNING when saving inconsistent stub/slave master and journal files. [RT #17279] 2272. [bug] Handle illegal dnssec-lookaside trust-anchor names. [RT #17262] 2271. [bug] Fix a memory leak in http server code [RT #17100] 2270. [bug] dns_db_closeversion() version->writer could be reset before it is tested. [RT #17290] 2269. [contrib] dbus memory leaks and missing va_end calls. [RT #17232] 2268. [bug] 0.IN-ADDR.ARPA was missing from the empty zones list. --- 9.5.0b1 released --- 2267. [bug] Radix tree node_num value could be set incorrectly, causing positive ACL matches to look like negative ones. [RT #17311] 2266. [bug] client.c:get_clientmctx() returned the same mctx once the pool of mctx's was filled. [RT #17218] 2265. [bug] Test that the memory context's basic_table is non NULL before freeing. [RT #17265] 2264. [bug] Server prefix length was being ignored. [RT #17308] 2263. [bug] "named-checkconf -z" failed to set default value for "check-integrity". [RT #17306] 2262. [bug] Error status from all but the last view could be lost. [RT #17292] 2261. [bug] Fix memory leak with "any" and "none" ACLs [RT #17272] 2260. [bug] Reported wrong clients-per-query when increasing the value. [RT #17236] 2259. [placeholder] --- 9.5.0a7 released --- 2258. [bug] Fallback from IXFR/TSIG to SOA/AXFR/TSIG broken. [RT #17241] 2257. [bug] win32: Use the full path to vcredist_x86.exe when calling it. [RT #17222] 2256. [bug] win32: Correctly register the installation location of bindevt.dll. [RT #17159] 2255. [maint] L.ROOT-SERVERS.NET is now 199.7.83.42. 2254. [bug] timer.c:dispatch() failed to lock timer->lock when reading timer->idle allowing it to see intermediate values as timer->idle was reset by isc_timer_touch(). [RT #17243] 2253. [func] "max-cache-size" defaults to 32M. "max-acache-size" defaults to 16M. 2252. [bug] Fixed errors in sortlist code [RT #17216] 2251. [placeholder] 2250. [func] New flag 'memstatistics' to state whether the memory statistics file should be written or not. Additionally named's -m option will cause the statistics file to be written. [RT #17113] 2249. [bug] Only set Authentic Data bit if client requested DNSSEC, per RFC 3655 [RT #17175] 2248. [cleanup] Fix several errors reported by Coverity. [RT #17160] 2247. [doc] Sort doc/misc/options. [RT #17067] 2246. [bug] Make the startup of test servers (ans.pl) more robust. [RT #17147] 2245. [bug] Validating lack of DS records at trust anchors wasn't working. [RT #17151] 2244. [func] Allow the check of nameserver names against the SOA MNAME field to be disabled by specifying 'notify-to-soa yes;'. [RT #17073] 2243. [func] Configuration files without a newline at the end now parse without error. [RT #17120] 2242. [bug] nsupdate: GSS-TSIG support using the Heimdal Kerberos library could require a source of random data. [RT #17127] 2241. [func] nsupdate: add a interactive 'help' command. [RT #17099] 2240. [bug] Cleanup nsupdates GSS-TSIG support. Convert a number of INSIST()s into plain fatal() errors which report the triggering result code. The 'key' command wasn't disabling GSS-TSIG. [RT #17099] 2239. [func] Ship a pre built bin/named/bind9.xsl.h. [RT #17114] 2238. [bug] It was possible to trigger a REQUIRE when a validation was canceled. [RT #17106] 2237. [bug] libbind: res_init() was not thread aware. [RT #17123] 2236. [bug] dnssec-signzone failed to preserve the case of of wildcard owner names. [RT #17085] 2235. [bug] was not being installed. [RT #17135] 2234. [port] Correct some compiler warnings on SCO OSr5 [RT #17134] 2233. [func] Add support for O(1) ACL processing, based on radix tree code originally written by Kevin Brintnall. [RT #16288] 2232. [bug] dns_adb_findaddrinfo() could fail and return ISC_R_SUCCESS. [RT #17137] 2231. [bug] Building dlzbdb (contrib/dlz/bin/dlzbdb) was broken. [RT #17088] 2230. [bug] We could INSIST reading a corrupted journal. [RT #17132] 2229. [bug] Null pointer dereference on query pool creation failure. [RT #17133] 2228. [contrib] contrib: Change 2188 was incomplete. 2227. [cleanup] Tidied up the FAQ. [RT #17121] 2226. [placeholder] 2225. [bug] More support for systems with no IPv4 addresses. [RT #17111] 2224. [bug] Defer journal compaction if a xfrin is in progress. [RT #17119] 2223. [bug] Make a new journal when compacting. [RT #17119] 2222. [func] named-checkconf now checks server key references. [RT #17097] 2221. [bug] Set the event result code to reflect the actual record turned to caller when a cache update is rejected due to a more credible answer existing. [RT #17017] 2220. [bug] win32: Address a race condition in final shutdown of the Windows socket code. [RT #17028] 2219. [bug] Apply zone consistency checks to additions, not removals, when updating. [RT #17049] 2218. [bug] Remove unnecessary REQUIRE from dns_validator_create(). [RT #16976] 2217. [func] Adjust update log levels. [RT #17092] 2216. [cleanup] Fix a number of errors reported by Coverity. [RT #17094] 2215. [bug] Bad REQUIRE check isc_hmacsha1_verify(). [RT #17094] 2214. [bug] Deregister OpenSSL lock callback when cleaning up. Reorder OpenSSL cleanup so that RAND_cleanup() is called before the locks are destroyed. [RT #17098] 2213. [bug] SIG0 diagnostic failure messages were looking at the wrong status code. [RT #17101] 2212. [func] 'host -m' now causes memory statistics and active memory to be printed at exit. [RT 17028] 2211. [func] Update "dynamic update temporarily disabled" message. [RT #17065] 2210. [bug] Deleting class specific records via UPDATE could fail. [RT #17074] 2209. [port] osx: linking against user supplied static OpenSSL libraries failed as the system ones were still being found. [RT #17078] 2208. [port] win32: make sure both build methods produce the same output. [RT #17058] 2207. [port] Some implementations of getaddrinfo() fail to set ai_canonname correctly. [RT #17061] --- 9.5.0a6 released --- 2206. [security] "allow-query-cache" and "allow-recursion" now cross inherit from each other. If allow-query-cache is not set in named.conf then allow-recursion is used if set, otherwise allow-query is used if set, otherwise the default (localnets; localhost;) is used. If allow-recursion is not set in named.conf then allow-query-cache is used if set, otherwise allow-query is used if set, otherwise the default (localnets; localhost;) is used. [RT #16987] 2205. [bug] libbind: change #2119 broke thread support. [RT #16982] 2204. [bug] "rndc flushname name unknown-view" caused named to crash. [RT #16984] 2203. [security] Query id generation was cryptographically weak. [RT # 16915] 2202. [security] The default acls for allow-query-cache and allow-recursion were not being applied. [RT #16960] 2201. [bug] The build failed in a separate object directory. [RT #16943] 2200. [bug] The search for cached NSEC records was stopping to early leading to excessive DLV queries. [RT #16930] 2199. [bug] win32: don't call WSAStartup() while loading dlls. [RT #16911] 2198. [bug] win32: RegCloseKey() could be called when RegOpenKeyEx() failed. [RT #16911] 2197. [bug] Add INSIST to catch negative responses which are not setting the event result code appropriately. [RT #16909] 2196. [port] win32: yield processor while waiting for once to to complete. [RT #16958] 2195. [func] dnssec-keygen now defaults to nametype "ZONE" when generating DNSKEYs. [RT #16954] 2194. [bug] Close journal before calling 'done' in xfrin.c. --- 9.5.0a5 released --- 2193. [port] win32: BINDInstall.exe is now linked statically. [RT #16906] 2192. [port] win32: use vcredist_x86.exe to install Visual Studio's redistributable dlls if building with Visual Stdio 2005 or later. 2191. [func] named-checkzone now allows dumping to stdout (-). named-checkconf now has -h for help. named-checkzone now has -h for help. rndc now has -h for help. Better handling of '-?' for usage summaries. [RT #16707] 2190. [func] Make fallback to plain DNS from EDNS due to timeouts more visible. New logging category "edns-disabled". [RT #16871] 2189. [bug] Handle socket() returning EINTR. [RT #15949] 2188. [contrib] queryperf: autoconf changes to make the search for libresolv or libbind more robust. [RT #16299] 2187. [bug] query_addds(), query_addwildcardproof() and query_addnxrrsetnsec() should take a version argument. [RT #16368] 2186. [port] cygwin: libbind: check for struct sockaddr_storage independently of IPv6. [RT #16482] 2185. [port] sunos: libbind: check for ssize_t, memmove() and memchr(). [RT #16463] 2184. [bug] bind9.xsl.h didn't build out of the source tree. [RT #16830] 2183. [bug] dnssec-signzone didn't handle offline private keys well. [RT #16832] 2182. [bug] dns_dispatch_createtcp() and dispatch_createudp() could return ISC_R_SUCCESS when they ran out of memory. [RT #16365] 2181. [port] sunos: libbind: add paths.h from BIND 8. [RT #16462] 2180. [cleanup] Remove bit test from 'compress_test' as they are no longer needed. [RT #16497] 2179. [func] 'rndc command zone' will now find 'zone' if it is unique to all the views. [RT #16821] 2178. [bug] 'rndc reload' of a slave or stub zone resulted in a reference leak. [RT #16867] 2177. [bug] Array bounds overrun on read (rcodetext) at debug level 10+. [RT #16798] 2176. [contrib] dbus update to handle race condition during initialization (Bugzilla 235809). [RT #16842] 2175. [bug] win32: windows broadcast condition variable support was broken. [RT #16592] 2174. [bug] I/O errors should always be fatal when reading master files. [RT #16825] 2173. [port] win32: When compiling with MSVS 2005 SP1 we also need to ship Microsoft.VC80.MFCLOC. --- 9.5.0a4 released --- 2172. [bug] query_addsoa() was being called with a non zone db. [RT #16834] 2171. [bug] Handle breaks in DNSSEC trust chains where the parent servers are not DS aware (DS queries to the parent return a referral to the child). 2170. [func] Add acache processing to test suite. [RT #16711] 2169. [bug] host, nslookup: when reporting NXDOMAIN report the given name and not the last name searched for. [RT #16763] 2168. [bug] nsupdate: in non-interactive mode treat syntax errors as fatal errors. [RT #16785] 2167. [bug] When re-using a automatic zone named failed to attach it to the new view. [RT #16786] --- 9.5.0a3 released --- 2166. [bug] When running in batch mode, dig could misinterpret a server address as a name to be looked up, causing unexpected output. [RT #16743] 2165. [func] Allow the destination address of a query to determine if we will answer the query or recurse. allow-query-on, allow-recursion-on and allow-query-cache-on. [RT #16291] 2164. [bug] The code to determine how named-checkzone / named-compilezone was called failed under windows. [RT #16764] 2163. [bug] If only one of query-source and query-source-v6 specified a port the query pools code broke (change 2129). [RT #16768] 2162. [func] Allow "rrset-order fixed" to be disabled at compile time. [RT #16665] 2161. [bug] Fix which log messages are emitted for 'rndc flush'. [RT #16698] 2160. [bug] libisc wasn't handling NULL ifa_addr pointers returned from getifaddrs(). [RT #16708] --- 9.5.0a2 released --- 2159. [bug] Array bounds overrun in acache processing. [RT #16710] 2158. [bug] ns_client_isself() failed to initialize key leading to a REQUIRE failure. [RT #16688] 2157. [func] dns_db_transfernode() created. [RT #16685] 2156. [bug] Fix node reference leaks in lookup.c:lookup_find(), resolver.c:validated() and resolver.c:cache_name(). Fix a memory leak in rbtdb.c:free_noqname(). Make lookup.c:lookup_find() robust against event leaks. [RT #16685] 2155. [contrib] SQLite sdb module from jaboydjr@netwalk.com. [RT #16694] 2154. [func] Scoped (e.g. IPv6 link-local) addresses may now be matched in acls by omitting the scope. [RT #16599] 2153. [bug] nsupdate could leak memory. [RT #16691] 2152. [cleanup] Use sizeof(buf) instead of fixed number in dighost.c:get_trusted_key(). [RT #16678] 2151. [bug] Missing newline in usage message for journalprint. [RT #16679] 2150. [bug] 'rrset-order cyclic' uniformly distribute the starting point for the first response for a given RRset. [RT #16655] 2149. [bug] isc_mem_checkdestroyed() failed to abort on if there were still active memory contexts. [RT #16672] 2148. [func] Add positive logging for rndc commands. [RT #14623] 2147. [bug] libbind: remove potential buffer overflow from hmac_link.c. [RT #16437] 2146. [cleanup] Silence Linux's spurious "obsolete setsockopt SO_BSDCOMPAT" message. [RT #16641] 2145. [bug] Check DS/DLV digest lengths for known digests. [RT #16622] 2144. [cleanup] Suppress logging of SERVFAIL from forwarders. [RT #16619] 2143. [bug] We failed to restart the IPv6 client when the kernel failed to return the destination the packet was sent to. [RT #16613] 2142. [bug] Handle master files with a modification time that matches the epoch. [RT #16612] 2141. [bug] dig/host should not be setting IDN_ASCCHECK (IDN equivalent of LDH checks). [RT #16609] 2140. [bug] libbind: missing unlock on pthread_key_create() failures. [RT #16654] 2139. [bug] dns_view_find() was being called with wrong type in adb.c. [RT #16670] 2138. [bug] Lock order reversal in resolver.c. [RT #16653] 2137. [port] Mips little endian and/or mips 64 bit are now supported for atomic operations. [RT #16648] 2136. [bug] nslookup/host looped if there was no search list and the host didn't exist. [RT #16657] 2135. [bug] Uninitialized rdataset in sdlz.c. [RT #16656] 2134. [func] Additional statistics support. [RT #16666] 2133. [port] powerpc: Support both IBM and MacOS Power PC assembler syntaxes. [RT #16647] 2132. [bug] Missing unlock on out of memory in dns_dispatchmgr_setudp(). 2131. [contrib] dlz/mysql: AXFR was broken. [RT #16630] 2130. [func] Log if CD or DO were set. [RT #16640] 2129. [func] Provide a pool of UDP sockets for queries to be made over. See use-queryport-pool, queryport-pool-ports and queryport-pool-updateinterval. [RT #16415] 2128. [doc] xsltproc --nonet, update DTD versions. [RT #16635] 2127. [port] Improved OpenSSL 0.9.8 support. [RT #16563] 2126. [security] Serialize validation of type ANY responses. [RT #16555] 2125. [bug] dns_zone_getzeronosoattl() REQUIRE failure if DLZ was defined. [RT #16574] 2124. [security] It was possible to dereference a freed fetch context. [RT #16584] --- 9.5.0a1 released --- 2123. [func] Use Doxygen to generate internal documentation. [RT #11398] 2122. [func] Experimental http server and statistics support for named via xml. 2121. [func] Add a 10 slot dead masters cache (LRU) with a 600 second timeout. [RT #16553] 2120. [doc] Fix markup on nsupdate man page. [RT #16556] 2119. [compat] libbind: allow res_init() to succeed enough to return the default domain even if it was unable to allocate memory. 2118. [bug] Handle response with long chains of domain name compression pointers which point to other compression pointers. [RT #16427] 2117. [bug] DNSSEC fixes: named could fail to cache NSEC records which could lead to validation failures. named didn't handle negative DS responses that were in the process of being validated. Check CNAME bit before accepting NODATA proof. To be able to ignore a child NSEC there must be SOA (and NS) set in the bitmap. [RT #16399] 2116. [bug] 'rndc reload' could cause the cache to continually be cleaned. [RT #16401] 2115. [bug] 'rndc reconfig' could trigger a INSIST if the number of masters for a zone was reduced. [RT #16444] 2114. [bug] dig/host/nslookup: searches for names with multiple labels were failing. [RT #16447] 2113. [bug] nsupdate: if a zone is specified it should be used for server discover. [RT #16455] 2112. [security] Warn if weak RSA exponent is used. [RT #16460] 2111. [bug] Fix a number of errors reported by Coverity. [RT #16507] 2110. [bug] "minimal-responses yes;" interacted badly with BIND 8 priming queries. [RT #16491] 2109. [port] libbind: silence aix 5.3 compiler warnings. [RT #16502] 2108. [func] DHCID support. [RT #16456] 2107. [bug] dighost.c: more cleanup of buffers. [RT #16499] 2106. [func] 'rndc status' now reports named's version. [RT #16426] 2105. [func] GSS-TSIG support (RFC 3645). 2104. [port] Fix Solaris SMF error message. 2103. [port] Add /usr/sfw to list of locations for OpenSSL under Solaris. 2102. [port] Silence Solaris 10 warnings. 2101. [bug] OpenSSL version checks were not quite right. [RT #16476] 2100. [port] win32: copy libeay32.dll to Build\Debug. Copy Debug\named-checkzone to Debug\named-compilezone. 2099. [port] win32: more manifest issues. 2098. [bug] Race in rbtdb.c:no_references(), which occasionally triggered an INSIST failure about the node lock reference. [RT #16411] 2097. [bug] named could reference a destroyed memory context after being reloaded / reconfigured. [RT #16428] 2096. [bug] libbind: handle applications that fail to detect res_init() failures better. 2095. [port] libbind: alway prototype inet_cidr_ntop_ipv6() and net_cidr_ntop_ipv6(). [RT #16388] 2094. [contrib] Update named-bootconf. [RT #16404] 2093. [bug] named-checkzone -s was broken. 2092. [bug] win32: dig, host, nslookup. Use registry config if resolv.conf does not exist or no nameservers listed. [RT #15877] 2091. [port] dighost.c: race condition on cleanup. [RT #16417] 2090. [port] win32: Visual C++ 2005 command line manifest support. [RT #16417] 2089. [security] Raise the minimum safe OpenSSL versions to OpenSSL 0.9.7l and OpenSSL 0.9.8d. Versions prior to these have known security flaws which are (potentially) exploitable in named. [RT #16391] 2088. [security] Change the default RSA exponent from 3 to 65537. [RT #16391] 2087. [port] libisc failed to compile on OS's w/o a vsnprintf. [RT #16382] 2086. [port] libbind: FreeBSD now has get*by*_r() functions. [RT #16403] 2085. [doc] win32: added index.html and README to zip. [RT #16201] 2084. [contrib] dbus update for 9.3.3rc2. 2083. [port] win32: Visual C++ 2005 support. 2082. [doc] Document 'cache-file' as a test only option. 2081. [port] libbind: minor 64-bit portability fix in memcluster.c. [RT #16360] 2080. [port] libbind: res_init.c did not compile on older versions of Solaris. [RT #16363] 2079. [bug] The lame cache was not handling multiple types correctly. [RT #16361] 2078. [bug] dnssec-checkzone output style "default" was badly named. It is now called "relative". [RT #16326] 2077. [bug] 'dnssec-signzone -O raw' wasn't outputting the complete signed zone. [RT #16326] 2076. [bug] Several files were missing #include causing build failures on OSF. [RT #16341] 2075. [bug] The spillat timer event hander could leak memory. [RT #16357] 2074. [bug] dns_request_createvia2(), dns_request_createvia3(), dns_request_createraw2() and dns_request_createraw3() failed to send multiple UDP requests. [RT #16349] 2073. [bug] Incorrect semantics check for update policy "wildcard". [RT #16353] 2072. [bug] We were not generating valid HMAC SHA digests. [RT #16320] 2071. [port] Test whether gcc accepts -fno-strict-aliasing. [RT #16324] 2070. [bug] The remote address was not always displayed when reporting dispatch failures. [RT #16315] 2069. [bug] Cross compiling was not working. [RT #16330] 2068. [cleanup] Lower incremental tuning message to debug 1. [RT #16319] 2067. [bug] 'rndc' could close the socket too early triggering a INSIST under Windows. [RT #16317] 2066. [security] Handle SIG queries gracefully. [RT #16300] 2065. [bug] libbind: probe for HPUX prototypes for endprotoent_r() and endservent_r(). [RT 16313] 2064. [bug] libbind: silence AIX compiler warnings. [RT #16218] 2063. [bug] Change #1955 introduced a bug which caused the first 'rndc flush' call to not free memory. [RT #16244] 2062. [bug] 'dig +nssearch' was reusing a buffer before it had been returned by the socket code. [RT #16307] 2061. [bug] Accept expired wildcard message reversed. [RT #16296] 2060. [bug] Enabling DLZ support could leave views partially configured. [RT #16295] 2059. [bug] Search into cache rbtdb could trigger an INSIST failure while cleaning up a stale rdataset. [RT #16292] 2058. [bug] Adjust how we calculate rtt estimates in the presence of authoritative servers that drop EDNS and/or CD requests. Also fallback to EDNS/512 and plain DNS faster for zones with less than 3 servers. [RT #16187] 2057. [bug] Make setting "ra" dependent on both allow-query-cache and allow-recursion. [RT #16290] 2056. [bug] dig: ixfr= was not being treated case insensitively at all times. [RT #15955] 2055. [bug] Missing goto after dropping multicast query. [RT #15944] 2054. [port] freebsd: do not explicitly link against -lpthread. [RT #16170] 2053. [port] netbsd:libbind: silence compiler warnings. [RT #16220] 2052. [bug] 'rndc' improve connect failed message to report the failing address. [RT #15978] 2051. [port] More strtol() fixes. [RT #16249] 2050. [bug] Parsing of NSAP records was not case insensitive. [RT #16287] 2049. [bug] Restore SOA before AXFR when falling back from a attempted IXFR when transferring in a zone. Allow a initial SOA query before attempting a AXFR to be requested. [RT #16156] 2048. [bug] It was possible to loop forever when using avoid-v4-udp-ports / avoid-v6-udp-ports when the OS always returned the same local port. [RT #16182] 2047. [bug] Failed to initialize the interface flags to zero. [RT #16245] 2046. [bug] rbtdb.c:rdataset_setadditional() could cause duplicate cleanup [RT #16247]. 2045. [func] Use lock buckets for acache entries to limit memory consumption. [RT #16183] 2044. [port] Add support for atomic operations for Itanium. [RT #16179] 2043. [port] nsupdate/nslookup: Force the flushing of the prompt for interactive sessions. [RT #16148] 2042. [bug] named-checkconf was incorrectly rejecting the logging category "config". [RT #16117] 2041. [bug] "configure --with-dlz-bdb=yes" produced a bad set of libraries to be linked. [RT #16129] 2040. [bug] rbtdb no_references() could trigger an INSIST failure with --enable-atomic. [RT #16022] 2039. [func] Check that all buffers passed to the socket code have been retrieved when the socket event is freed. [RT #16122] 2038. [bug] dig/nslookup/host was unlinking from wrong list when handling errors. [RT #16122] 2037. [func] When unlinking the first or last element in a list check that the list head points to the element to be unlinked. [RT #15959] 2036. [bug] 'rndc recursing' could cause trigger a REQUIRE. [RT #16075] 2035. [func] Make falling back to TCP on UDP refresh failure optional. Default "try-tcp-refresh yes;" for BIND 8 compatibility. [RT #16123] 2034. [bug] gcc: set -fno-strict-aliasing. [RT #16124] 2033. [bug] We weren't creating multiple client memory contexts on demand as expected. [RT #16095] 2032. [bug] Remove a INSIST in query_addadditional2(). [RT #16074] 2031. [bug] Emit a error message when "rndc refresh" is called on a non slave/stub zone. [RT # 16073] 2030. [bug] We were being overly conservative when disabling openssl engine support. [RT #16030] 2029. [bug] host printed out the server multiple times when specified on the command line. [RT #15992] 2028. [port] linux: socket.c compatibility for old systems. [RT #16015] 2027. [port] libbind: Solaris x86 support. [RT #16020] 2026. [bug] Rate limit the two recursive client exceeded messages. [RT #16044] 2025. [func] Update "zone serial unchanged" message. [RT #16026] 2024. [bug] named emitted spurious "zone serial unchanged" messages on reload. [RT #16027] 2023. [bug] "make install" should create ${localstatedir}/run and ${sysconfdir} if they do not exist. [RT #16033] 2022. [bug] If dnssec validation is disabled only assert CD if CD was requested. [RT #16037] 2021. [bug] dnssec-enable no; triggered a REQUIRE. [RT #16037] 2020. [bug] rdataset_setadditional() could leak memory. [RT #16034] 2019. [tuning] Reduce the amount of work performed per quantum when cleaning the cache. [RT #15986] 2018. [bug] Checking if the HMAC MD5 private file was broken. [RT #15960] 2017. [bug] allow-query default was not correct. [RT #15946] 2016. [bug] Return a partial answer if recursion is not allowed but requested and we had the answer to the original qname. [RT #15945] 2015. [cleanup] use-additional-cache is now acache-enable for consistency. Default acache-enable off in BIND 9.4 as it requires memory usage to be configured. It may be enabled by default in BIND 9.5 once we have more experience with it. 2014. [func] Statistics about acache now recorded and sent to log. [RT #15976] 2013. [bug] Handle unexpected TSIGs on unsigned AXFR/IXFR responses more gracefully. [RT #15941] 2012. [func] Don't insert new acache entries if acache is full. [RT #15970] 2011. [func] dnssec-signzone can now update the SOA record of the signed zone, either as an increment or as the system time(). [RT #15633] 2010. [placeholder] rt15958 2009. [bug] libbind: Coverity fixes. [RT #15808] 2008. [func] It is now possible to enable/disable DNSSEC validation from rndc. This is useful for the mobile hosts where the current connection point breaks DNSSEC (firewall/proxy). [RT #15592] rndc validation newstate [view] 2007. [func] It is now possible to explicitly enable DNSSEC validation. default dnssec-validation no; to be changed to yes in 9.5.0. [RT #15674] 2006. [security] Allow-query-cache and allow-recursion now default to the built in acls "localnets" and "localhost". This is being done to make caching servers less attractive as reflective amplifying targets for spoofed traffic. This still leave authoritative servers exposed. The best fix is for full BCP 38 deployment to remove spoofed traffic. 2005. [bug] libbind: Retransmission timeouts should be based on which attempt it is to the nameserver and not the nameserver itself. [RT #13548] 2004. [bug] dns_tsig_sign() could pass a NULL pointer to dst_context_destroy() when cleaning up after a error. [RT #15835] 2003. [bug] libbind: The DNS name/address lookup functions could occasionally follow a random pointer due to structures not being completely zeroed. [RT #15806] 2002. [bug] libbind: tighten the constraints on when struct addrinfo._ai_pad exists. [RT #15783] 2001. [func] Check the KSK flag when updating a secure dynamic zone. New zone option "update-check-ksk yes;". [RT #15817] 2000. [bug] memmove()/strtol() fix was incomplete. [RT #15812] 1999. [func] Implement "rrset-order fixed". [RT #13662] 1998. [bug] Restrict handling of fifos as sockets to just SunOS. This allows named to connect to entropy gathering daemons that use fifos instead of sockets. [RT #15840] 1997. [bug] Named was failing to replace negative cache entries when a positive one for the type was learnt. [RT #15818] 1996. [bug] nsupdate: if a zone has been specified it should appear in the output of 'show'. [RT #15797] 1995. [bug] 'host' was reporting multiple "is an alias" messages. [RT #15702] 1994. [port] OpenSSL 0.9.8 support. [RT #15694] 1993. [bug] Log messages, via syslog, were missing the space after the timestamp if "print-time yes" was specified. [RT #15844] 1992. [bug] Not all incoming zone transfer messages included the view. [RT #15825] 1991. [cleanup] The configuration data, once read, should be treated as read only. Expand the use of const to enforce this at compile time. [RT #15813] 1990. [bug] libbind: isc's override of broken gettimeofday() implementations was not always effective. [RT #15709] 1989. [bug] win32: don't check the service password when re-installing. [RT #15882] 1988. [bug] Remove a bus error from the SHA256/SHA512 support. [RT #15878] 1987. [func] DS/DLV SHA256 digest algorithm support. [RT #15608] 1986. [func] Report when a zone is removed. [RT #15849] 1985. [protocol] DLV has now been assigned a official type code of 32769. [RT #15807] Note: care should be taken to ensure you upgrade both named and dnssec-signzone at the same time for zones with DLV records where named is the master server for the zone. Also any zones that contain DLV records should be removed when upgrading a slave zone. You do not however have to upgrade all servers for a zone with DLV records simultaneously. 1984. [func] dig, nslookup and host now advertise a 4096 byte EDNS UDP buffer size by default. [RT #15855] 1983. [func] Two new update policies. "selfsub" and "selfwild". [RT #12895] 1982. [bug] DNSKEY was being accepted on the parent side of a delegation. KEY is still accepted there for RFC 3007 validated updates. [RT #15620] 1981. [bug] win32: condition.c:wait() could fail to reattain the mutex lock. 1980. [func] dnssec-signzone: output the SOA record as the first record in the signed zone. [RT #15758] 1979. [port] linux: allow named to drop core after changing user ids. [RT #15753] 1978. [port] Handle systems which have a broken recvmsg(). [RT #15742] 1977. [bug] Silence noisy log message. [RT #15704] 1976. [bug] Handle systems with no IPv4 addresses. [RT #15695] 1975. [bug] libbind: isc_gethexstring() could misparse multi-line hex strings with comments. [RT #15814] 1974. [doc] List each of the zone types and associated zone options separately in the ARM. 1973. [func] TSIG HMACSHA1, HMACSHA224, HMACSHA256, HMACSHA384 and HMACSHA512 support. [RT #13606] 1972. [contrib] DBUS dynamic forwarders integration from Jason Vas Dias . 1971. [port] linux: make detection of missing IF_NAMESIZE more robust. [RT #15443] 1970. [bug] nsupdate: adjust UDP timeout when falling back to unsigned SOA query. [RT #15775] 1969. [bug] win32: the socket code was freeing the socket structure too early. [RT #15776] 1968. [bug] Missing lock in resolver.c:validated(). [RT #15739] 1967. [func] dig/nslookup/host: warn about missing "QR". [RT #15779] 1966. [bug] Don't set CD when we have fallen back to plain DNS. [RT #15727] 1965. [func] Suppress spurious "recursion requested but not available" warning with 'dig +qr'. [RT #15780]. 1964. [func] Separate out MX and SRV to CNAME checks. [RT #15723] 1963. [port] Tru64 4.0E doesn't support send() and recv(). [RT #15586] 1962. [bug] Named failed to clear old update-policy when it was removed. [RT #15491] 1961. [bug] Check the port and address of responses forwarded to dispatch. [RT #15474] 1960. [bug] Update code should set NSEC ttls from SOA MINIMUM. [RT #15465] 1959. [func] Control the zeroing of the negative response TTL to a soa query. Defaults "zero-no-soa-ttl yes;" and "zero-no-soa-ttl-cache no;". [RT #15460] 1958. [bug] Named failed to update the zone's secure state until the zone was reloaded. [RT #15412] 1957. [bug] Dig mishandled responses to class ANY queries. [RT #15402] 1956. [bug] Improve cross compile support, 'gen' is now built by native compiler. See README for additional cross compile support information. [RT #15148] 1955. [bug] Pre-allocate the cache cleaning iterator. [RT #14998] 1954. [func] Named now falls back to advertising EDNS with a 512 byte receive buffer if the initial EDNS queries fail. [RT #14852] 1953. [func] The maximum EDNS UDP response named will send can now be set in named.conf (max-udp-size). This is independent of the advertised receive buffer (edns-udp-size). [RT #14852] 1952. [port] hpux: tell the linker to build a runtime link path "-Wl,+b:". [RT #14816]. 1951. [security] Drop queries from particular well known ports. Don't return FORMERR to queries from particular well known ports. [RT #15636] 1950. [port] Solaris 2.5.1 and earlier cannot bind() then connect() a TCP socket. This prevents the source address being set for TCP connections. [RT #15628] 1949. [func] Addition memory leakage checks. [RT #15544] 1948. [bug] If was possible to trigger a REQUIRE failure in xfrin.c:maybe_free() if named ran out of memory. [RT #15568] 1947. [func] It is now possible to configure named to accept expired RRSIGs. Default "dnssec-accept-expired no;". Setting "dnssec-accept-expired yes;" leaves named vulnerable to replay attacks. [RT #14685] 1946. [bug] resume_dslookup() could trigger a REQUIRE failure when using forwarders. [RT #15549] 1945. [cleanup] dnssec-keygen: RSA (RSAMD5) is no longer recommended. To generate a RSAMD5 key you must explicitly request RSAMD5. [RT #13780] 1944. [cleanup] isc_hash_create() does not need a read/write lock. [RT #15522] 1943. [bug] Set the loadtime after rolling forward the journal. [RT #15647] 1942. [bug] If the name of a DNSKEY match that of one in trusted-keys do not attempt to validate the DNSKEY using the parents DS RRset. [RT #15649] 1941. [bug] ncache_adderesult() should set eresult even if no rdataset is passed to it. [RT #15642] 1940. [bug] Fixed a number of error conditions reported by Coverity. 1939. [bug] The resolver could dereference a null pointer after validation if all the queries have timed out. [RT #15528] 1938. [bug] The validator was not correctly handling unsecure negative responses at or below a SEP. [RT #15528] 1937. [bug] sdlz doesn't handle RRSIG records. [RT #15564] 1936. [bug] The validator could leak memory. [RT #15544] 1935. [bug] 'acache' was DO sensitive. [RT #15430] 1934. [func] Validate pending NS RRsets, in the authority section, prior to returning them if it can be done without requiring DNSKEYs to be fetched. [RT #15430] 1933. [bug] dump_rdataset_raw() had a incorrect INSIST. [RT #15534] 1932. [bug] hpux: LDFLAGS was getting corrupted. [RT #15530] 1931. [bug] Per-client mctx could require a huge amount of memory, particularly for a busy caching server. [RT #15519] 1930. [port] HPUX: ia64 support. [RT #15473] 1929. [port] FreeBSD: extend use of PTHREAD_SCOPE_SYSTEM. 1928. [bug] Race in rbtdb.c:currentversion(). [RT #15517] 1927. [bug] Access to soanode or nsnode in rbtdb violated the lock order rule and could cause a dead lock. [RT #15518] 1926. [bug] The Windows installer did not check for empty passwords. BINDinstall was being installed in the wrong place. [RT #15483] 1925. [port] All outer level AC_TRY_RUNs need cross compiling defaults. [RT #15469] 1924. [port] libbind: hpux ia64 support. [RT #15473] 1923. [bug] ns_client_detach() called too early. [RT #15499] 1922. [bug] check-tool.c:setup_logging() missing call to dns_log_setcontext(). 1921. [bug] Client memory contexts were not using internal malloc. [RT #15434] 1920. [bug] The cache rbtdb lock array was too small to have the desired performance characteristics. [RT #15454] 1919. [contrib] queryperf: a set of new features: collecting/printing response delays, printing intermediate results, and adjusting query rate for the "target" qps. 1918. [bug] Memory leak when checking acls. [RT #15391] 1917. [doc] funcsynopsisinfo wasn't being treated as verbatim when generating man pages. [RT #15385] 1916. [func] Integrate contributed IDN code from JPNIC. [RT #15383] 1915. [bug] dig +ndots was broken. [RT #15215] 1914. [protocol] DS is required to accept mnemonic algorithms (RFC 4034). Still emit numeric algorithms for compatibility with RFC 3658. [RT #15354] 1913. [func] Integrate contributed DLZ code into named. [RT #11382] 1912. [port] aix: atomic locking for powerpc. [RT #15020] 1911. [bug] Update windows socket code. [RT #14965] 1910. [bug] dig's +sigchase code overhauled. [RT #14933] 1909. [bug] The DLV code has been re-worked to make no longer query order sensitive. [RT #14933] 1908. [func] dig now warns if 'RA' is not set in the answer when 'RD' was set in the query. host/nslookup skip servers that fail to set 'RA' when 'RD' is set unless a server is explicitly set. [RT #15005] 1907. [func] host/nslookup now continue (default)/fail on SERVFAIL. [RT #15006] 1906. [func] dig now has a '-q queryname' and '+showsearch' options. [RT #15034] 1905. [bug] Strings returned from cfg_obj_asstring() should be treated as read-only. The prototype for cfg_obj_asstring() has been updated to reflect this. [RT #15256] 1904. [func] Automatic empty zone creation for D.F.IP6.ARPA and friends. Note: RFC 1918 zones are not yet covered by this but are likely to be in a future release. New options: empty-server, empty-contact, empty-zones-enable and disable-empty-zone. 1903. [func] ISC string copy API. 1902. [func] Attempt to make the amount of work performed in a iteration self tuning. The covers nodes clean from the cache per iteration, nodes written to disk when rewriting a master file and nodes destroyed per iteration when destroying a zone or a cache. [RT #14996] 1901. [cleanup] Don't add DNSKEY records to the additional section. 1900. [bug] ixfr-from-differences failed to ensure that the serial number increased. [RT #15036] 1899. [func] named-checkconf now validates update-policy entries. [RT #14963] 1898. [bug] Extend ISC_SOCKADDR_FORMATSIZE and ISC_NETADDR_FORMATSIZE to allow for scope details. 1897. [func] x86 and x86_64 now have separate atomic locking implementations. 1896. [bug] Recursive clients soft quota support wasn't working as expected. [RT #15103] 1895. [bug] A escaped character is, potentially, converted to the output character set too early. [RT #14666] 1894. [doc] Review ARM for BIND 9.4. 1893. [port] Use uintptr_t if available. [RT #14606] 1892. [func] Support for SPF rdata type. [RT #15033] 1891. [port] freebsd: pthread_mutex_init can fail if it runs out of memory. [RT #14995] 1890. [func] Raise the UDP receive buffer size to 32k if it is less than 32k. [RT #14953] 1889. [port] sunos: non blocking i/o support. [RT #14951] 1888. [func] Support for IPSECKEY rdata type. [RT #14967] 1887. [bug] The cache could delete expired records too fast for clients with a virtual time in the past. [RT #14991] 1886. [bug] fctx_create() could return success even though it failed. [RT #14993] 1885. [func] dig: report the number of extra bytes still left in the packet after processing all the records. 1884. [cleanup] dighost.c: move external declarations into . 1883. [bug] dnssec-signzone, dnssec-keygen: handle negative debug levels. [RT #14962] 1882. [func] Limit the number of recursive clients that can be waiting for a single query () to resolve. New options clients-per-query and max-clients-per-query. 1881. [func] Add a system test for named-checkconf. [RT #14931] 1880. [func] The lame cache is now done on a basis as some servers only appear to be lame for certain query types. [RT #14916] 1879. [func] "USE INTERNAL MALLOC" is now runtime selectable. [RT #14892] 1878. [func] Detect duplicates of UDP queries we are recursing on and drop them. New stats category "duplicate". [RT #2471] 1877. [bug] Fix unreasonably low quantum on call to dns_rbt_destroy2(). Remove unnecessary unhash_node() call. [RT #14919] 1876. [func] Additional memory debugging support to track size and mctx arguments. [RT #14814] 1875. [bug] process_dhtkey() was using the wrong memory context to free some memory. [RT #14890] 1874. [port] sunos: portability fixes. [RT #14814] 1873. [port] win32: isc__errno2result() now reports its caller. [RT #13753] 1872. [port] win32: Handle ERROR_NETNAME_DELETED. [RT #13753] 1871. [placeholder] 1870. [func] Added framework for handling multiple EDNS versions. [RT #14873] 1869. [func] dig can now specify the EDNS version when making a query. [RT #14873] 1868. [func] edns-udp-size can now be overridden on a per server basis. [RT #14851] 1867. [bug] It was possible to trigger a INSIST in dlv_validatezonekey(). [RT #14846] 1866. [bug] resolv.conf parse errors were being ignored by dig/host/nslookup. [RT #14841] 1865. [bug] Silently ignore nameservers in /etc/resolv.conf with bad addresses. [RT #14841] 1864. [bug] Don't try the alternative transfer source if you got a answer / transfer with the main source address. [RT #14802] 1863. [bug] rrset-order "fixed" error messages not complete. 1862. [func] Add additional zone data constancy checks. named-checkzone has extended checking of NS, MX and SRV record and the hosts they reference. named has extended post zone load checks. New zone options: check-mx and integrity-check. [RT #4940] 1861. [bug] dig could trigger a INSIST on certain malformed responses. [RT #14801] 1860. [port] solaris 2.8: hack_shutup_pthreadmutexinit was incorrectly set. [RT #14775] 1859. [func] Add support for CH A record. [RT #14695] 1858. [bug] The flush-zones-on-shutdown option wasn't being parsed. [RT #14686] 1857. [bug] named could trigger a INSIST() if reconfigured / reloaded too fast. [RT #14673] 1856. [doc] Switch Docbook toolchain from DSSSL to XSL. [RT #11398] 1855. [bug] ixfr-from-differences was failing to detect changes of ttl due to dns_diff_subtract() was ignoring the ttl of records. [RT #14616] 1854. [bug] lwres also needs to know the print format for (long long). [RT #13754] 1853. [bug] Rework how DLV interacts with proveunsecure(). [RT #13605] 1852. [cleanup] Remove last vestiges of dnssec-signkey and dnssec-makekeyset (removed from Makefile years ago). 1851. [doc] Doxygen comment markup. [RT #11398] 1850. [bug] Memory leak in lwres_getipnodebyaddr(). [RT #14591] 1849. [doc] All forms of the man pages (docbook, man, html) should have consistent copyright dates. 1848. [bug] Improve SMF integration. [RT #13238] 1847. [bug] isc_ondestroy_init() is called too late in dns_rbtdb_create()/dns_rbtdb64_create(). [RT #13661] 1846. [contrib] query-loc-0.3.0 from Stephane Bortzmeyer . 1845. [bug] Improve error reporting to distinguish between accept()/fcntl() and socket()/fcntl() errors. [RT #13745] 1844. [bug] inet_pton() accepted more that 4 hexadecimal digits for each 16 bit piece of the IPv6 address. The text representation of a IPv6 address has been tightened to disallow this (draft-ietf-ipv6-addr-arch-v4-02.txt). [RT #5662] 1843. [cleanup] CINCLUDES takes precedence over CFLAGS. This helps when CFLAGS contains "-I /usr/local/include" resulting in old header files being used. 1842. [port] cmsg_len() could produce incorrect results on some platform. [RT #13744] 1841. [bug] "dig +nssearch" now makes a recursive query to find the list of nameservers to query. [RT #13694] 1840. [func] dnssec-signzone can now randomize signature end times (dnssec-signzone -j jitter). [RT #13609] 1839. [bug] was not being installed. 1838. [cleanup] Don't allow Linux capabilities to be inherited. [RT #13707] 1837. [bug] Compile time option ISC_FACILITY was not effective for 'named -u '. [RT #13714] 1836. [cleanup] Silence compiler warnings in hash_test.c. 1835. [bug] Update dnssec-signzone's usage message. [RT #13657] 1834. [bug] Bad memset in rdata_test.c. [RT #13658] 1833. [bug] Race condition in isc_mutex_lock_profile(). [RT #13660] 1832. [bug] named fails to return BADKEY on unknown TSIG algorithm. [RT #13620] 1831. [doc] Update named-checkzone documentation. [RT #13604] 1830. [bug] adb lame cache has sence of test reversed. [RT #13600] 1829. [bug] win32: "pid-file none;" broken. [RT #13563] 1828. [bug] isc_rwlock_init() failed to properly cleanup if it encountered a error. [RT #13549] 1827. [bug] host: update usage message for '-a'. [RT #37116] 1826. [bug] Missing DESTROYLOCK() in isc_mem_createx() on out of memory error. [RT #13537] 1825. [bug] Missing UNLOCK() on out of memory error from in rbtdb.c:subtractrdataset(). [RT #13519] 1824. [bug] Memory leak on dns_zone_setdbtype() failure. [RT #13510] 1823. [bug] Wrong macro used to check for point to point interface. [RT #13418] 1822. [bug] check-names test for RT was reversed. [RT #13382] 1821. [placeholder] 1820. [bug] Gracefully handle acl loops. [RT #13659] 1819. [bug] The validator needed to check both the algorithm and digest types of the DS to determine if it could be used to introduce a secure zone. [RT #13593] 1818. [bug] 'named-checkconf -z' triggered an INSIST. [RT #13599] 1817. [func] Add support for additional zone file formats for improving loading performance. The masterfile-format option in named.conf can be used to specify a non-default format. A separate command named-compilezone was provided to generate zone files in the new format. Additionally, the -I and -O options for dnssec-signzone specify the input and output formats. 1816. [port] UnixWare: failed to compile lib/isc/unix/net.c. [RT #13597] 1815. [bug] nsupdate triggered a REQUIRE if the server was set without also setting the zone and it encountered a CNAME and was using TSIG. [RT #13086] 1814. [func] UNIX domain controls are now supported. 1813. [func] Restructured the data locking framework using architecture dependent atomic operations (when available), improving response performance on multi-processor machines significantly. x86, x86_64, alpha, powerpc, and mips are currently supported. 1812. [port] win32: IN6_IS_ADDR_UNSPECIFIED macro is incorrect. [RT #13453] 1811. [func] Preserve the case of domain names in rdata during zone transfers. [RT #13547] 1810. [bug] configure, lib/bind/configure make different default decisions about whether to do a threaded build. [RT #13212] 1809. [bug] "make distclean" failed for libbind if the platform is not supported. 1808. [bug] zone.c:notify_zone() contained a race condition, zone->db could change underneath it. [RT #13511] 1807. [bug] When forwarding (forward only) set the active domain from the forward zone name. [RT #13526] 1806. [bug] The resolver returned the wrong result when a CNAME / DNAME was encountered when fetching glue from a secure namespace. [RT #13501] 1805. [bug] Pending status was not being cleared when DLV was active. [RT #13501] 1804. [bug] Ensure that if we are queried for glue that it fits in the additional section or TC is set to tell the client to retry using TCP. [RT #10114] 1803. [bug] dnssec-signzone sometimes failed to remove old RRSIGs. [RT #13483] 1802. [bug] Handle connection resets better. [RT #11280] 1801. [func] Report differences between hints and real NS rrset and associated address records. 1800. [bug] Changes #1719 allowed a INSIST to be triggered. [RT #13428] 1799. [bug] 'rndc flushname' failed to flush negative cache entries. [RT #13438] 1798. [func] The server syntax has been extended to support a range of servers. [RT #11132] 1797. [func] named-checkconf now check acls to verify that they only refer to existing acls. [RT #13101] 1796. [func] "rndc freeze/thaw" now freezes/thaws all zones. 1795. [bug] "rndc dumpdb" was not fully documented. Minor formating issues with "rndc dumpdb -all". [RT #13396] 1794. [func] Named and named-checkzone can now both check for non-terminal wildcard records. 1793. [func] Extend adjusting TTL warning messages. [RT #13378] 1792. [func] New zone option "notify-delay". Specify a minimum delay between sets of NOTIFY messages. 1791. [bug] 'host -t a' still printed out AAAA and MX records. [RT #13230] 1790. [cleanup] Move lib/dns/sec/dst up into lib/dns. This should allow parallel make to succeed. 1789. [bug] Prerequisite test for tkey and dnssec could fail with "configure --with-libtool". 1788. [bug] libbind9.la/libbind9.so needs to link against libisccfg.la/libisccfg.so. 1787. [port] HPUX: both "cc" and "gcc" need -Wl,+vnocompatwarnings. 1786. [port] AIX: libt_api needs to be taught to look for T_testlist in the main executable (--with-libtool). [RT #13239] 1785. [bug] libbind9.la/libbind9.so needs to link against libisc.la/libisc.so. 1784. [cleanup] "libtool -allow-undefined" is the default. Leave hooks in configure to allow it to be set if needed in the future. 1783. [cleanup] We only need one copy of libtool.m4, ltmain.sh in the source tree. 1782. [port] OSX: --with-libtool + --enable-libbind broke on __evOptMonoTime. [RT #13219] 1781. [port] FreeBSD 5.3: set PTHREAD_SCOPE_SYSTEM. [RT #12810] 1780. [bug] Update libtool to 1.5.10. 1779. [port] OSF 5.1: libtool didn't handle -pthread correctly. 1778. [port] HUX 11.11: fix broken IN6ADDR_ANY_INIT and IN6ADDR_LOOPBACK_INIT macros. 1777. [port] OSF 5.1: fix broken IN6ADDR_ANY_INIT and IN6ADDR_LOOPBACK_INIT macros. 1776. [port] Solaris 2.9: fix broken IN6ADDR_ANY_INIT and IN6ADDR_LOOPBACK_INIT macros. 1775. [bug] Only compile getnetent_r.c when threaded. [RT #13205] 1774. [port] Aix: Silence compiler warnings / build failures. [RT #13154] 1773. [bug] Fast retry on host / net unreachable. [RT #13153] 1772. [placeholder] 1771. [placeholder] 1770. [bug] named-checkconf failed to report missing a missing file clause for rbt{64} master/hint zones. [RT #13009] 1769. [port] win32: change compiler flags /MTd ==> /MDd, /MT ==> /MD. 1768. [bug] nsecnoexistnodata() could be called with a non-NSEC rdataset. [RT #12907] 1767. [port] Builds on IPv6 platforms without IPv6 Advanced API support for (struct in6_pktinfo) failed. [RT #13077] 1766. [bug] Update the master file timestamp on successful refresh as well as the journal's timestamp. [RT #13062] 1765. [bug] configure --with-openssl=auto failed. [RT #12937] 1764. [bug] dns_zone_replacedb failed to emit a error message if there was no SOA record in the replacement db. [RT #13016] 1763. [func] Perform sanity checks on NS records which refer to 'in zone' names. [RT #13002] 1762. [bug] isc_interfaceiter_create() could return ISC_R_SUCCESS even when it failed. [RT #12995] 1761. [bug] 'rndc dumpdb' didn't report unassociated entries. [RT #12971] 1760. [bug] Host / net unreachable was not penalising rtt estimates. [RT #12970] 1759. [bug] Named failed to startup if the OS supported IPv6 but had no IPv6 interfaces configured. [RT #12942] 1758. [func] Don't send notify messages to self. [RT #12933] 1757. [func] host now can turn on memory debugging flags with '-m'. 1756. [func] named-checkconf now checks the logging configuration. [RT #12352] 1755. [func] allow-update is now settable at the options / view level. [RT #6636] 1754. [bug] We weren't always attempting to query the parent server for the DS records at the zone cut. [RT #12774] 1753. [bug] Don't serve a slave zone which has no NS records. [RT #12894] 1752. [port] Move isc_app_start() to after ns_os_daemonise() as some fork() implementations unblock the signals that are blocked by isc_app_start(). [RT #12810] 1751. [bug] --enable-getifaddrs failed under linux. [RT #12867] 1750. [port] lib/bind/make/rules.in:subdirs was not bash friendly. [RT #12864] 1749. [bug] 'check-names response ignore;' failed to ignore. [RT #12866] 1748. [func] dig now returns the byte count for axfr/ixfr. 1747. [bug] BIND 8 compatibility: named/named-checkconf failed to parse "host-statistics-max" in named.conf. 1746. [func] Make public the function to read a key file, dst_key_read_public(). [RT #12450] 1745. [bug] Dig/host/nslookup accept replies from link locals regardless of scope if no scope was specified when query was sent. [RT #12745] 1744. [bug] If tuple2msgname() failed to convert a tuple to a name a REQUIRE could be triggered. [RT #12796] 1743. [bug] If isc_taskmgr_create() was not able to create the requested number of worker threads then destruction of the manager would trigger an INSIST() failure. [RT #12790] 1742. [bug] Deleting all records at a node then adding a previously existing record, in a single UPDATE transaction, failed to leave / regenerate the associated RRSIG records. [RT #12788] 1741. [bug] Deleting all records at a node in a secure zone using a update-policy grant failed. [RT #12787] 1740. [bug] Replace rbt's hash algorithm as it performed badly with certain zones. [RT #12729] NOTE: a hash context now needs to be established via isc_hash_create() if the application was not already doing this. 1739. [bug] dns_rbt_deletetree() could incorrectly return ISC_R_QUOTA. [RT #12695] 1738. [bug] Enable overrun checking by default. [RT #12695] 1737. [bug] named failed if more than 16 masters were specified. [RT #12627] 1736. [bug] dst_key_fromnamedfile() could fail to read a public key. [RT #12687] 1735. [bug] 'dig +sigtrace' could die with a REQUIRE failure. [RE #12688] 1734. [cleanup] 'rndc-confgen -a -t' remove extra '/' in path. [RT #12588] 1733. [bug] Return non-zero exit status on initial load failure. [RT #12658] 1732. [bug] 'rrset-order name "*"' wasn't being applied to ".". [RT #12467] 1731. [port] darwin: relax version test in ifconfig.sh. [RT #12581] 1730. [port] Determine the length type used by the socket API. [RT #12581] 1729. [func] Improve check-names error messages. 1728. [doc] Update check-names documentation. 1727. [bug] named-checkzone: check-names support didn't match documentation. 1726. [port] aix5: add support for aix5. 1725. [port] linux: update error message on interaction of threads, capabilities and setuid support (named -u). [RT #12541] 1724. [bug] Look for DNSKEY records with "dig +sigtrace". [RT #12557] 1723. [cleanup] Silence compiler warnings from t_tasks.c. [RT #12493] 1722. [bug] Don't commit the journal on malformed ixfr streams. [RT #12519] 1721. [bug] Error message from the journal processing were not always identifying the relevant journal. [RT #12519] 1720. [bug] 'dig +chase' did not terminate on a RFC 2308 Type 1 negative response. [RT #12506] 1719. [bug] named was not correctly caching a RFC 2308 Type 1 negative response. [RT #12506] 1718. [bug] nsupdate was not handling RFC 2308 Type 3 negative responses when looking for the zone / master server. [RT #12506] 1717. [port] solaris: ifconfig.sh did not support Solaris 10. "ifconfig.sh down" didn't work for Solaris 9. 1716. [doc] named.conf(5) was being installed in the wrong location. [RT #12441] 1715. [func] 'dig +trace' now randomly selects the next servers to try. Report if there is a bad delegation. 1714. [bug] dig/host/nslookup were only trying the first address when a nameserver was specified by name. [RT #12286] 1713. [port] linux: extend capset failure message to say: please ensure that the capset kernel module is loaded. see insmod(8) 1712. [bug] Missing FULLCHECK for "trusted-key" in dig. 1711. [func] 'rndc unfreeze' has been deprecated by 'rndc thaw'. 1710. [func] 'rndc notify zone [class [view]]' resend the NOTIFY messages for the specified zone. [RT #9479] 1709. [port] solaris: add SMF support from Sun. 1708. [cleanup] Replaced dns_fullname_hash() with dns_name_fullhash() for conformance to the name space convention. Binary backward compatibility to the old function name is provided. [RT #12376] 1707. [contrib] sdb/ldap updated to version 1.0-beta. 1706. [bug] 'rndc stop' failed to cause zones to be flushed sometimes. [RT #12328] 1705. [func] Allow the journal's name to be changed via named.conf. 1704. [port] lwres needed a snprintf() implementation for platforms without snprintf(). Add missing "#include ". [RT #12321] 1703. [bug] named would loop sending NOTIFY messages when it failed to receive a response. [RT #12322] 1702. [bug] also-notify should not be applied to built in zones. [RT #12323] 1701. [doc] A minimal named.conf man page. 1700. [func] nslookup is no longer to be treated as deprecated. Remove "deprecated" warning message. Add man page. 1699. [bug] dnssec-signzone can generate "not exact" errors when resigning. [RT #12281] 1698. [doc] Use reserved IPv6 documentation prefix. 1697. [bug] xxx-source{,-v6} was not effective when it specified one of listening addresses and a different port than the listening port. [RT #12257] 1696. [bug] dnssec-signzone failed to clean out nodes that consisted of only NSEC and RRSIG records. [RT #12154] 1695. [bug] DS records when forwarding require special handling. [RT #12133] 1694. [bug] Report if the builtin views of "_default" / "_bind" are defined in named.conf. [RT #12023] 1693. [bug] max-journal-size was not effective for master zones with ixfr-from-differences set. [RT #12024] 1692. [bug] Don't set -I, -L and -R flags when libcrypto is in /usr/lib. [RT #11971] 1691. [bug] sdb's attachversion was not complete. [RT #11990] 1690. [bug] Delay detaching view from the client until UPDATE processing completes when shutting down. [RT #11714] 1689. [bug] DNS_NAME_TOREGION() and DNS_NAME_SPLIT() macros contained gratuitous semicolons. [RT #11707] 1688. [bug] LDFLAGS was not supported. 1687. [bug] Race condition in dispatch. [RT #10272] 1686. [bug] Named sent a extraneous NOTIFY when it received a redundant UPDATE request. [RT #11943] 1685. [bug] Change #1679 loop tests weren't quite right. 1684. [func] ixfr-from-differences now takes master and slave in addition to yes and no at the options and view levels. 1683. [bug] dig +sigchase could leak memory. [RT #11445] 1682. [port] Update configure test for (long long) printf format. [RT #5066] 1681. [bug] Only set SO_REUSEADDR when a port is specified in isc_socket_bind(). [RT #11742] 1680. [func] rndc: the source address can now be specified. 1679. [bug] When there was a single nameserver with multiple addresses for a zone not all addresses were tried. [RT #11706] 1678. [bug] RRSIG should use TYPEXXXXX for unknown types. 1677. [bug] dig: +aaonly didn't work, +aaflag undocumented. 1676. [func] New option "allow-query-cache". This lets allow-query be used to specify the default zone access level rather than having to have every zone override the global value. allow-query-cache can be set at both the options and view levels. If allow-query-cache is not set allow-query applies. 1675. [bug] named would sometimes add extra NSEC records to the authority section. 1674. [port] linux: increase buffer size used to scan /proc/net/if_inet6. 1673. [port] linux: issue a error messages if IPv6 interface scans fails. 1672. [cleanup] Tests which only function in a threaded build now return R:THREADONLY (rather than R:UNTESTED) in a non-threaded build. 1671. [contrib] queryperf: add NAPTR to the list of known types. 1670. [func] Log UPDATE requests to slave zones without an acl as "disabled" at debug level 3. [RT #11657] 1669. [placeholder] 1668. [bug] DIG_SIGCHASE was making bin/dig/host dump core. 1667. [port] linux: not all versions have IF_NAMESIZE. 1666. [bug] The optional port on hostnames in dual-stack-servers was being ignored. 1665. [func] rndc now allows addresses to be set in the server clauses. 1664. [bug] nsupdate needed KEY for SIG(0), not DNSKEY. 1663. [func] Look for OpenSSL by default. 1662. [bug] Change #1658 failed to change one use of 'type' to 'keytype'. 1661. [bug] Restore dns_name_concatenate() call in adb.c:set_target(). [RT #11582] 1660. [bug] win32: connection_reset_fix() was being called unconditionally. [RT #11595] 1659. [cleanup] Cleanup some messages that were referring to KEY vs DNSKEY, NXT vs NSEC and SIG vs RRSIG. 1658. [func] Update dnssec-keygen to default to KEY for HMAC-MD5 and DH. Tighten which options apply to KEY and DNSKEY records. 1657. [doc] ARM: document query log output. 1656. [doc] Update DNSSEC description in ARM to cover DS, NSEC DNSKEY and RRSIG. [RT #11542] 1655. [bug] Logging multiple versions w/o a size was broken. [RT #11446] 1654. [bug] isc_result_totext() contained array bounds read error. 1653. [func] Add key type checking to dst_key_fromfilename(), DST_TYPE_KEY should be used to read TSIG, TKEY and SIG(0) keys. 1652. [bug] TKEY still uses KEY. 1651. [bug] dig: process multiple dash options. 1650. [bug] dig, nslookup: flush standard out after each command. 1649. [bug] Silence "unexpected non-minimal diff" message. [RT #11206] 1648. [func] Update dnssec-lookaside named.conf syntax to support multiple dnssec-lookaside namespaces (not yet implemented). 1647. [bug] It was possible trigger a INSIST when chasing a DS record that required walking back over a empty node. [RT #11445] 1646. [bug] win32: logging file versions didn't work with non-UNC filenames. [RT #11486] 1645. [bug] named could trigger a REQUIRE failure if multiple masters with keys are specified. 1644. [bug] Update the journal modification time after a successful refresh query. [RT #11436] 1643. [bug] dns_db_closeversion() could leak memory / node references. [RT #11163] 1642. [port] Support OpenSSL implementations which don't have DSA support. [RT #11360] 1641. [bug] Update the check-names description in ARM. [RT #11389] 1640. [bug] win32: isc_socket_cancel(ISC_SOCKCANCEL_ACCEPT) was incorrectly closing the socket. [RT #11291] 1639. [func] Initial dlv system test. 1638. [bug] "ixfr-from-differences" could generate a REQUIRE failure if the journal open failed. [RT #11347] 1637. [bug] Node reference leak on error in addnoqname(). 1636. [bug] The dump done callback could get ISC_R_SUCCESS even if a error had occurred. The database version no longer matched the version of the database that was dumped. 1635. [bug] Memory leak on error in query_addds(). 1634. [bug] named didn't supply a useful error message when it detected duplicate views. [RT #11208] 1633. [bug] named should return NOTIMP to update requests to a slaves without a allow-update-forwarding acl specified. [RT #11331] 1632. [bug] nsupdate failed to send prerequisite only UPDATE messages. [RT #11288] 1631. [bug] dns_journal_compact() could sometimes corrupt the journal. [RT #11124] 1630. [contrib] queryperf: add support for IPv6 transport. 1629. [func] dig now supports IPv6 scoped addresses with the extended format in the local-server part. [RT #8753] 1628. [bug] Typo in Compaq Trucluster support. [RT #11264] 1627. [bug] win32: sockets were not being closed when the last external reference was removed. [RT #11179] 1626. [bug] --enable-getifaddrs was broken. [RT #11259] 1625. [bug] named failed to load/transfer RFC2535 signed zones which contained CNAMES. [RT #11237] 1624. [bug] zonemgr_putio() call should be locked. [RT #11163] 1623. [bug] A serial number of zero was being displayed in the "sending notifies" log message when also-notify was used. [RT #11177] 1622. [func] probe the system to see if IPV6_(RECV)PKTINFO is available, and suppress wildcard binding if not. 1621. [bug] match-destinations did not work for IPv6 TCP queries. [RT #11156] 1620. [func] When loading a zone report if it is signed. [RT #11149] 1619. [bug] Missing ISC_LIST_UNLINK in end_reserved_dispatches(). [RT #11118] 1618. [bug] Fencepost errors in dns_name_ishostname() and dns_name_ismailbox() could trigger a INSIST(). 1617. [port] win32: VC++ 6.0 support. 1616. [compat] Ensure that named's version is visible in the core dump. [RT #11127] 1615. [port] Define ISC_SOCKADDR_LEN_T based on _BSD_SOCKLEN_T_ if it is defined. 1614. [port] win32: silence resource limit messages. [RT #11101] 1613. [bug] Builds would fail on machines w/o a if_nametoindex(). Missing #ifdef ISC_PLATFORM_HAVEIFNAMETOINDEX/#endif. [RT #11119] 1612. [bug] check-names at the option/view level could trigger an INSIST. [RT #11116] 1611. [bug] solaris: IPv6 interface scanning failed to cope with no active IPv6 interfaces. 1610. [bug] On dual stack machines "dig -b" failed to set the address type to be looked up with "@server". [RT #11069] 1609. [func] dig now has support to chase DNSSEC signature chains. Requires -DDIG_SIGCHASE=1 to be set in STD_CDEFINES. DNSSEC validation code in dig coded by Olivier Courtay (olivier.courtay@irisa.fr) for the IDsA project (http://idsa.irisa.fr). 1608. [func] dig and host now accept -4/-6 to select IP transport to use when making queries. 1607. [bug] dig, host and nslookup were still using random() to generate query ids. [RT #11013] 1606. [bug] DLV insecurity proof was failing. 1605. [func] New dns_db_find() option DNS_DBFIND_COVERINGNSEC. 1604. [bug] A xfrout_ctx_create() failure would result in xfrout_ctx_destroy() being called with a partially initialized structure. 1603. [bug] nsupdate: set interactive based on isatty(). [RT #10929] 1602. [bug] Logging to a file failed unless a size was specified. [RT #10925] 1601. [bug] Silence spurious warning 'both "recursion no;" and "allow-recursion" active' warning from view "_bind". [RT #10920] 1600. [bug] Duplicate zone pre-load checks were not case insensitive. 1599. [bug] Fix memory leak on error path when checking named.conf. 1598. [func] Specify that certain parts of the namespace must be secure (dnssec-must-be-secure). 1597. [func] Allow notify-source and query-source to be specified on a per server basis similar to transfer-source. [RT #6496] 1596. [func] Accept 'notify-source' style syntax for query-source. 1595. [func] New notify type 'master-only'. Enable notify for master zones only. 1594. [bug] 'rndc dumpdb' could prevent named from answering queries while the dump was in progress. [RT #10565] 1593. [bug] rndc should return "unknown command" to unknown commands. [RT #10642] 1592. [bug] configure_view() could leak a dispatch. [RT #10675] 1591. [bug] libbind: updated to BIND 8.4.5. 1590. [port] netbsd: update thread support. 1589. [func] DNSSEC lookaside validation. 1588. [bug] win32: TCP sockets could become blocked. [RT #10115] 1587. [bug] dns_message_settsigkey() failed to clear existing key. [RT #10590] 1586. [func] "check-names" is now implemented. 1585. [placeholder] 1584. [bug] "make test" failed with a read only source tree. [RT #10461] 1583. [bug] Records add via UPDATE failed to get the correct trust level. [RT #10452] 1582. [bug] rrset-order failed to work on RRsets with more than 32 elements. [RT #10381] 1581. [func] Disable DNSSEC support by default. To enable DNSSEC specify "dnssec-enable yes;" in named.conf. 1580. [bug] Zone destruction on final detach takes a long time. [RT #3746] 1579. [bug] Multiple task managers could not be created. 1578. [bug] Don't use CLASS E IPv4 addresses when resolving. [RT #10346] 1577. [bug] Use isc_uint32_t in ultrasparc optimizer bug workaround code. [RT #10331] 1576. [bug] Race condition in dns_dispatch_addresponse(). [RT #10272] 1575. [func] Log TSIG name on TSIG verify failure. [RT #4404] 1574. [bug] Don't attempt to open the controls socket(s) when running tests. [RT #9091] 1573. [port] linux: update to libtool 1.5.2 so that "make install DESTDIR=/xx" works with "configure --with-libtool". [RT #9941] 1572. [bug] nsupdate: sign the soa query to find the enclosing zone if the server is specified. [RT #10148] 1571. [bug] rbt:hash_node() could fail leaving the hash table in an inconsistent state. [RT #10208] 1570. [bug] nsupdate failed to handle classes other than IN. New keyword 'class' which sets the default class. [RT #10202] 1569. [func] nsupdate new command 'answer' which displays the complete answer message to the last update. 1568. [bug] nsupdate now reports that the update failed in interactive mode. [RT #10236] 1567. [maint] B.ROOT-SERVERS.NET is now 192.228.79.201. 1566. [port] Support for the cmsg framework on Solaris and HP/UX. This also solved the problem that match-destinations for IPv6 addresses did not work on these systems. [RT #10221] 1565. [bug] CD flag should be copied to outgoing queries unless the query is under a secure entry point in which case CD should be set. 1564. [func] Attempt to provide a fallback entropy source to be used if named is running chrooted and named is unable to open entropy source within the chroot area. [RT #10133] 1563. [bug] Gracefully fail when unable to obtain neither an IPv4 nor an IPv6 dispatch. [RT #10230] 1562. [bug] isc_socket_create() and isc_socket_accept() could leak memory under error conditions. [RT #10230] 1561. [bug] It was possible to release the same name twice if named ran out of memory. [RT #10197] 1560. [port] FreeBSD: work around FreeBSD 5.2 mapping EAI_NODATA and EAI_NONAME to the same value. 1559. [port] named should ignore SIGFSZ. 1558. [func] New DNSSEC 'disable-algorithms'. Support entry into child zones for which we don't have a supported algorithm. Such child zones are treated as unsigned. 1557. [func] Implement missing DNSSEC tests for * NOQNAME proof with wildcard answers. * NOWILDARD proof with NXDOMAIN. Cache and return NOQNAME with wildcard answers. 1556. [bug] nsupdate now treats all names as fully qualified. [RT #6427] 1555. [func] 'rrset-order cyclic' no longer has a random starting point per query. [RT #7572] 1554. [bug] dig, host, nslookup failed when no nameservers were specified in /etc/resolv.conf. [RT #8232] 1553. [bug] The windows socket code could stop accepting connections. [RT #10115] 1552. [bug] Accept NOTIFY requests from mapped masters if matched-mapped is set. [RT #10049] 1551. [port] Open "/dev/null" before calling chroot(). 1550. [port] Call tzset(), if available, before calling chroot(). 1549. [func] named-checkzone can now write out the zone contents in a easily parsable format (-D and -o). 1548. [bug] When parsing APL records it was possible to silently accept out of range ADDRESSFAMILY values. [RT #9979] 1547. [bug] Named wasted memory recording duplicate lame zone entries. [RT #9341] 1546. [bug] We were rejecting valid secure CNAME to negative answers. 1545. [bug] It was possible to leak memory if named was unable to bind to the specified transfer source and TSIG was being used. [RT #10120] 1544. [bug] Named would logged a single entry to a file despite it being over the specified size limit. 1543. [bug] Logging using "versions unlimited" did not work. 1542. [placeholder] 1541. [func] NSEC now uses new bitmap format. 1540. [bug] "rndc reload " was silently accepted. [RT #8934] 1539. [bug] Open UDP sockets for notify-source and transfer-source that use reserved ports at startup. [RT #9475] 1538. [placeholder] rt9997 1537. [func] New option "querylog". If set specify whether query logging is to be enabled or disabled at startup. 1536. [bug] Windows socket code failed to log a error description when returning ISC_R_UNEXPECTED. [RT #9998] 1535. [placeholder] 1534. [bug] Race condition when priming cache. [RT #9940] 1533. [func] Warn if both "recursion no;" and "allow-recursion" are active. [RT #4389] 1532. [port] netbsd: the configure test for requires . 1531. [port] AIX more libtool fixes. 1530. [bug] It was possible to trigger a INSIST() failure if a slave master file was removed at just the correct moment. [RT #9462] 1529. [bug] "notify explicit;" failed to log that NOTIFY messages were being sent for the zone. [RT #9442] 1528. [cleanup] Simplify some dns_name_ functions based on the deprecation of bitstring labels. 1527. [cleanup] Reduce the number of gettimeofday() calls without losing necessary timer granularity. 1526. [func] Implemented "additional section caching (or acache)", an internal cache framework for additional section content to improve response performance. Several configuration options were provided to control the behavior. 1525. [bug] dns_cache_create() could trigger a REQUIRE failure in isc_mem_put() during error cleanup. [RT #9360] 1524. [port] AIX needs to be able to resolve all symbols when creating shared libraries (--with-libtool). 1523. [bug] Fix race condition in rbtdb. [RT #9189] 1522. [bug] dns_db_findnode() relax the requirements on 'name'. [RT #9286] 1521. [bug] dns_view_createresolver() failed to check the result from isc_mem_create(). [RT #9294] 1520. [protocol] Add SSHFP (SSH Finger Print) type. 1519. [bug] dnssec-signzone:nsec_setbit() computed the wrong length of the new bitmap. 1518. [bug] dns_nsec_buildrdata(), and hence dns_nsec_build(), contained a off-by-one error when working out the number of octets in the bitmap. 1517. [port] Support for IPv6 interface scanning on HP/UX and TrueUNIX 5.1. 1516. [func] Roll the DNSSEC types to RRSIG, NSEC and DNSKEY. 1515. [func] Allow transfer source to be set in a server statement. [RT #6496] 1514. [bug] named: isc_hash_destroy() was being called too early. [RT #9160] 1513. [doc] Add "US" to root-delegation-only exclude list. 1512. [bug] Extend the delegation-only logging to return query type, class and responding nameserver. 1511. [bug] delegation-only was generating false positives on negative answers from sub-zones. 1510. [func] New view option "root-delegation-only". Apply delegation-only check to all TLDs and root. Note there are some TLDs that are NOT delegation only (e.g. DE, LV, US and MUSEUM) these can be excluded from the checks by using exclude. root-delegation-only exclude { "DE"; "LV"; "US"; "MUSEUM"; }; 1509. [bug] Hint zones should accept delegation-only. Forward zone should not accept delegation-only. 1508. [bug] Don't apply delegation-only checks to answers from forwarders. 1507. [bug] Handle BIND 8 style returns to NS queries to parents when making delegation-only checks. 1506. [bug] Wrong return type for dns_view_isdelegationonly(). 1505. [bug] Uninitialized rdataset in sdb. [RT #8750] 1504. [func] New zone type "delegation-only". 1503. [port] win32: install libeay32.dll outside of system32. 1502. [bug] nsupdate: adjust timeouts for UPDATE requests over TCP. 1501. [func] Allow TCP queue length to be specified via named.conf, tcp-listen-queue. 1500. [bug] host failed to lookup MX records. Also look up AAAA records. 1499. [bug] isc_random need to be seeded better if arc4random() is not used. 1498. [port] bsdos: 5.x support. 1497. [placeholder] 1496. [port] test for pthread_attr_setstacksize(). 1495. [cleanup] Replace hash functions with universal hash. 1494. [security] Turn on RSA BLINDING as a precaution. 1493. [placeholder] 1492. [cleanup] Preserve rwlock quota context when upgrading / downgrading. [RT #5599] 1491. [bug] dns_master_dump*() would produce extraneous $ORIGIN lines. [RT #6206] 1490. [bug] Accept reading state as well as working state in ns_client_next(). [RT #6813] 1489. [compat] Treat 'allow-update' on slave zones as a warning. [RT #3469] 1488. [bug] Don't override trust levels for glue addresses. [RT #5764] 1487. [bug] A REQUIRE() failure could be triggered if a zone was queued for transfer and the zone was then removed. [RT #6189] 1486. [bug] isc_print_snprintf() '%%' consumed one too many format characters. [RT #8230] 1485. [bug] gen failed to handle high type values. [RT #6225] 1484. [bug] The number of records reported after a AXFR was wrong. [RT #6229] 1483. [bug] dig axfr failed if the message id in the answer failed to match that in the request. Only the id in the first message is required to match. [RT #8138] 1482. [bug] named could fail to start if the kernel supports IPv6 but no interfaces are configured. Similarly for IPv4. [RT #6229] 1481. [bug] Refresh and stub queries failed to use masters keys if specified. [RT #7391] 1480. [bug] Provide replay protection for rndc commands. Full replay protection requires both rndc and named to be updated. Partial replay protection (limited exposure after restart) is provided if just named is updated. 1479. [bug] cfg_create_tuple() failed to handle out of memory cleanup. parse_list() would leak memory on syntax errors. 1478. [port] ifconfig.sh didn't account for other virtual interfaces. It now takes a optional argument to specify the first interface number. [RT #3907] 1477. [bug] memory leak using stub zones and TSIG. 1476. [placeholder] 1475. [port] Probe for old sprintf(). 1474. [port] Provide strtoul() and memmove() for platforms without them. 1473. [bug] create_map() and create_string() failed to handle out of memory cleanup. [RT #6813] 1472. [contrib] idnkit-1.0 from JPNIC, replaces mdnkit. 1471. [bug] libbind: updated to BIND 8.4.0. 1470. [bug] Incorrect length passed to snprintf. [RT #5966] 1469. [func] Log end of outgoing zone transfer at same level as the start of transfer is logged. [RT #4441] 1468. [func] Internal zones are no longer counted for 'rndc status'. [RT #4706] 1467. [func] $GENERATES now supports optional class and ttl. 1466. [bug] lwresd configuration errors resulted in memory and lock leaks. [RT #5228] 1465. [bug] isc_base64_decodestring() and isc_base64_tobuffer() failed to check that trailing bits were zero allowing some invalid base64 strings to be accepted. [RT #5397] 1464. [bug] Preserve "out of zone" data for outgoing zone transfers. [RT #5192] 1463. [bug] dns_rdata_from{wire,struct}() failed to catch bad NXT bit maps. [RT #5577] 1462. [bug] parse_sizeval() failed to check the token type. [RT #5586] 1461. [bug] Remove deadlock from rbtdb code. [RT #5599] 1460. [bug] inet_pton() failed to reject certain malformed IPv6 literals. 1459. [placeholder] 1458. [cleanup] sprintf() -> snprintf(). 1457. [port] Provide strlcat() and strlcpy() for platforms without them. 1456. [contrib] gen-data-queryperf.py from Stephane Bortzmeyer. 1455. [bug] missing from server grammar in doc/misc/options. [RT #5616] 1454. [port] Use getifaddrs() if available for interface scanning. --disable-getifaddrs to override. Glibc currently has a getifaddrs() that does not support IPv6. Use --enable-getifaddrs=glibc to force the use of this version under linux machines. 1453. [doc] ARM: $GENERATE example wasn't accurate. [RT #5298] 1452. [placeholder] 1451. [bug] rndc-confgen didn't exit with a error code for all failures. [RT #5209] 1450. [bug] Fetching expired glue failed under certain circumstances. [RT #5124] 1449. [bug] query_addbestns() didn't handle running out of memory gracefully. 1448. [bug] Handle empty wildcards labels. 1447. [bug] We were casting (unsigned int) to and from (void *). rdataset->private4 is now rdataset->privateuint4 to reflect a type change. 1446. [func] Implemented undocumented alternate transfer sources from BIND 8. See use-alt-transfer-source, alt-transfer-source and alt-transfer-source-v6. SECURITY: use-alt-transfer-source is ENABLED unless you are using views. This may cause a security risk resulting in accidental disclosure of wrong zone content if the master supplying different source content based on IP address. If you are not certain ISC recommends setting use-alt-transfer-source no; 1445. [bug] DNS_ADBFIND_STARTATROOT broke stub zones. This has been replaced with DNS_ADBFIND_STARTATZONE which causes the search to start using the closest zone. 1444. [func] dns_view_findzonecut2() allows you to specify if the cache should be searched for zone cuts. 1443. [func] Masters lists can now be specified and referenced in zone masters clauses and other masters lists. 1442. [func] New functions for manipulating port lists: dns_portlist_create(), dns_portlist_add(), dns_portlist_remove(), dns_portlist_match(), dns_portlist_attach() and dns_portlist_detach(). 1441. [func] It is now possible to tell dig to bind to a specific source port. 1440. [func] It is now possible to tell named to avoid using certain source ports (avoid-v4-udp-ports, avoid-v6-udp-ports). 1439. [bug] Named could return NOERROR with certain NOTIFY failures. Return NOTAUTH if the NOTIFY zone is not being served. 1438. [func] Log TSIG (if any) when logging NOTIFY requests. 1437. [bug] Leave space for stdio to work in. [RT #5033] 1436. [func] dns_zonemgr_resumexfrs() can be used to restart stalled transfers. 1435. [bug] zmgr_resume_xfrs() was being called read locked rather than write locked. zmgr_resume_xfrs() was not being called if the zone was being shutdown. 1434. [bug] "rndc reconfig" failed to initiate the initial zone transfer of new slave zones. 1433. [bug] named could trigger a REQUIRE failure if it could not get a file descriptor when attempting to write a master file. [RT #4347] 1432. [func] The advertised EDNS UDP buffer size can now be set via named.conf (edns-udp-size). 1431. [bug] isc_print_snprintf() "%s" with precision could walk off end of argument. [RT #5191] 1430. [port] linux: IPv6 interface scanning support. 1429. [bug] Prevent the cache getting locked to old servers. 1428. [placeholder] 1427. [bug] Race condition in adb with threaded build. 1426. [placeholder] 1425. [port] linux/libbind: define __USE_MISC when testing *_r() function prototypes in netdb.h. [RT #4921] 1424. [bug] EDNS version not being correctly printed. 1423. [contrib] queryperf: added A6 and SRV. 1422. [func] Log name/type/class when denying a query. [RT #4663] 1421. [func] Differentiate updates that don't succeed due to prerequisites (unsuccessful) vs other reasons (failed). 1420. [port] solaris: work around gcc optimizer bug. 1419. [port] openbsd: use /dev/arandom. [RT #4950] 1418. [bug] 'rndc reconfig' did not cause new slaves to load. 1417. [func] ID.SERVER/CHAOS is now a built in zone. See "server-id" for how to configure. 1416. [bug] Empty node should return NOERROR NODATA, not NXDOMAIN. [RT #4715] 1415. [func] DS TTL now derived from NS ttl. NXT TTL now derived from SOA MINIMUM. 1414. [func] Support for KSK flag. 1413. [func] Explicitly request the (re-)generation of DS records from keysets (dnssec-signzone -g). 1412. [func] You can now specify servers to be tried if a nameserver has IPv6 address and you only support IPv4 or the reverse. See dual-stack-servers. 1411. [bug] empty nodes should stop wildcard matches. [RT #4802] 1410. [func] Handle records that live in the parent zone, e.g. DS. 1409. [bug] DS should have attribute DNS_RDATATYPEATTR_DNSSEC. 1408. [bug] "make distclean" was not complete. [RT #4700] 1407. [bug] lfsr incorrectly implements the shift register. [RT #4617] 1406. [bug] dispatch initializes one of the LFSR's with a incorrect polynomial. [RT #4617] 1405. [func] Use arc4random() if available. 1404. [bug] libbind: ns_name_ntol() could overwrite a zero length buffer. 1403. [func] dnssec-signzone, dnssec-keygen, dnssec-makekeyset dnssec-signkey now report their version in the usage message. 1402. [cleanup] A6 has been moved to experimental and is no longer fully supported. 1401. [bug] adb wasn't clearing state when the timer expired. 1400. [bug] Block the addition of wildcard NS records by IXFR or UPDATE. [RT #3502] 1399. [bug] Use serial number arithmetic when testing SIG timestamps. [RT #4268] 1398. [doc] ARM: notify-also should have been also-notify. [RT #4345] 1397. [maint] J.ROOT-SERVERS.NET is now 192.58.128.30. 1396. [func] dnssec-signzone: adjust the default signing time by 1 hour to allow for clock skew. 1395. [port] OpenSSL 0.9.7 defines CRYPTO_LOCK_ENGINE but doesn't have a working implementation. [RT #4079] 1394. [func] It is now possible to check if a particular element is in a acl. Remove duplicate entries from the localnets acl. 1393. [port] Bind to individual IPv6 interfaces if IPV6_IPV6ONLY is not available in the kernel to prevent accidently listening on IPv4 interfaces. 1392. [bug] named-checkzone: update usage. 1391. [func] Add support for IPv6 scoped addresses in named. 1390. [func] host now supports ixfr. 1389. [bug] named could fail to rotate long log files. [RT #3666] 1388. [port] irix: check for sys/sysctl.h and NET_RT_IFLIST before defining HAVE_IFLIST_SYSCTL. [RT #3770] 1387. [bug] named could crash due to an access to invalid memory space (which caused an assertion failure) in incremental cleaning. [RT #3588] 1386. [bug] named-checkzone -z stopped on errors in a zone. [RT #3653] 1385. [bug] Setting serial-query-rate to 10 would trigger a REQUIRE failure. 1384. [bug] host was incompatible with BIND 8 in its exit code and in the output with the -l option. [RT #3536] 1383. [func] Track the serial number in a IXFR response and log if a mismatch occurs. This is a more specific error than "not exact". [RT #3445] 1382. [bug] make install failed with --enable-libbind. [RT #3656] 1381. [bug] named failed to correctly process answers that contained DNAME records where the resulting CNAME resulted in a negative answer. 1380. [func] 'rndc recursing' dump recursing queries to 'recursing-file = "named.recursing";'. 1379. [func] 'rndc status' now reports tcp and recursion quota states. 1378. [func] Improved positive feedback for 'rndc {reload|refresh}. 1377. [func] dns_zone_load{new}() now reports if the zone was loaded, queued for loading to up to date. 1376. [func] New function dns_zone_logc() to log to specified category. 1375. [func] 'rndc dumpdb' now dumps the adb cache along with the data cache. 1374. [func] dns_adb_dump() now logs the lame zones associated with each server. 1373. [bug] Recovery from expired glue failed under certain circumstances. 1372. [bug] named crashes with an assertion failure on exit when sharing the same port for listening and querying, and changing listening addresses several times. [RT #3509] 1371. [bug] notify-source-v6, transfer-source-v6 and query-source-v6 with explicit addresses and using the same ports as named was listening on could interfere with named's ability to answer queries sent to those addresses. 1370. [bug] dig '+[no]recurse' was incorrectly documented. 1369. [bug] Adding an NS record as the lexicographically last record in a secure zone didn't work. 1368. [func] remove support for bitstring labels. 1367. [func] Use response times to select forwarders. 1366. [contrib] queryperf usage was incomplete. Add '-h' for help. 1365. [func] "localhost" and "localnets" acls now include IPv6 addresses / prefixes. 1364. [func] Log file name when unable to open memory statistics and dump database files. [RT #3437] 1363. [func] Listen-on-v6 now supports specific addresses. 1362. [bug] remove IFF_RUNNING test when scanning interfaces. 1361. [func] log the reason for rejecting a server when resolving queries. 1360. [bug] --enable-libbind would fail when not built in the source tree for certain OS's. 1359. [security] Support patches OpenSSL libraries. http://www.cert.org/advisories/CA-2002-23.html 1358. [bug] It was possible to trigger a INSIST when debugging large dynamic updates. [RT #3390] 1357. [bug] nsupdate was extremely wasteful of memory. 1356. [tuning] Reduce the number of events / quantum for zone tasks. 1355. [bug] Fix DNSSEC wildcard proof for CNAME/DNAME. 1354. [doc] lwres man pages had illegal nroff. 1353. [contrib] sdb/ldap to version 0.9. 1352. [bug] dig, host, nslookup when falling back to TCP use the current search entry (if any). [RT #3374] 1351. [bug] lwres_getipnodebyname() returned the wrong name when given a IPv4 literal, af=AF_INET6 and AI_MAPPED was set. 1350. [bug] dns_name_fromtext() failed to handle too many labels gracefully. 1349. [security] Minimum OpenSSL version now 0.9.6e (was 0.9.5a). http://www.cert.org/advisories/CA-2002-23.html 1348. [port] win32: Rewrote code to use I/O Completion Ports in socket.c and eliminating a host of socket errors. Performance is enhanced. 1347. [placeholder] 1346. [placeholder] 1345. [port] Use a explicit -Wformat with gcc. Not all versions include it in -Wall. 1344. [func] Log if the serial number on the master has gone backwards. If you have multiple machines specified in the masters clause you may want to set 'multi-master yes;' to suppress this warning. 1343. [func] Log successful notifies received (info). Adjust log level for failed notifies to notice. 1342. [func] Log remote address with TCP dispatch failures. 1341. [func] Allow a rate limiter to be stalled. 1340. [bug] Delay and spread out the startup refresh load. 1339. [func] dig, host and nslookup now use IP6.ARPA for nibble lookups. Bit string lookups are no longer attempted. 1338. [placeholder] 1337. [placeholder] 1336. [func] Nibble lookups under IP6.ARPA are now supported by dns_byaddr_create(). dns_byaddr_createptrname() is deprecated, use dns_byaddr_createptrname2() instead. 1335. [bug] When performing a nonexistence proof, the validator should discard parent NXTs from higher in the DNS. 1334. [bug] When signing/verifying rdatasets, duplicate rdatas need to be suppressed. 1333. [contrib] queryperf now reports a summary of returned rcodes (-c), rcodes are printed in mnemonic form (-v). 1332. [func] Report the current serial with periodic commits when rolling forward the journal. 1331. [func] Generate DNSSEC wildcard proofs. 1330. [bug] When processing events (non-threaded) only allow the task one chance to use to use its quantum. 1329. [func] named-checkzone will now check if nameservers that appear to be IP addresses. Available modes "fail", "warn" (default) and "ignore" the results of the check. 1328. [bug] The validator could incorrectly verify an invalid negative proof. 1327. [bug] The validator would incorrectly mark data as insecure when seeing a bogus signature before a correct signature. 1326. [bug] DNAME/CNAME signatures were not being cached when validation was not being performed. [RT #3284] 1325. [bug] If the tcpquota was exhausted it was possible to to trigger a INSIST() failure. 1324. [port] darwin: ifconfig.sh now supports darwin. 1323. [port] linux: Slackware 4.0 needs . [RT #3205] 1322. [bug] dnssec-signzone usage message was misleading. 1321. [bug] If the last RRset in a zone is glue, dnssec-signzone would incorrectly duplicate its output and sign it. 1320. [doc] query-source-v6 was missing from options section. [RT #3218] 1319. [func] libbind: log attempts to exploit #1318. 1318. [bug] libbind: Remote buffer overrun. 1317. [port] libbind: TrueUNIX 5.1 does not like __align as a element name. 1316. [bug] libbind: gethostans() could get out of sync parsing the response if there was a very long CNAME chain. 1315. [bug] Options should apply to the internal _bind view. 1314. [port] Handle ECONNRESET from sendmsg() [unix]. 1313. [func] Query log now says if the query was signed (S) or if EDNS was used (E). 1312. [func] Log TSIG key used w/ outgoing zone transfers. 1311. [bug] lwres_getrrsetbyname leaked memory. [RT #3159] 1310. [bug] 'rndc stop' failed to cause zones to be flushed sometimes. [RT #3157] 1309. [func] Log that a zone transfer was covered by a TSIG. 1308. [func] DS (delegation signer) support. 1307. [bug] nsupdate: allow white space base64 key data. 1306. [bug] Badly encoded LOC record when the size, horizontal precision or vertical precision was 0.1m. 1305. [bug] Document that internal zones are included in the rndc status results. 1304. [func] New function: dns_zone_name(). 1303. [func] Option 'flush-zones-on-shutdown ;'. 1302. [func] Extended rndc dumpdb to support dumping of zones and view selection: 'dumpdb [-all|-zones|-cache] [view]'. 1301. [func] New category 'update-security'. 1300. [port] Compaq Trucluster support. 1299. [bug] Set AI_ADDRCONFIG when looking up addresses via getaddrinfo() (affects dig, host, nslookup, rndc and nsupdate). 1298. [bug] The CINCLUDES macro in lib/dns/sec/dst/Makefile could be left with a trailing "\" after configure has been run. 1297. [port] linux: make handling EINVAL from socket() no longer conditional on #ifdef LINUX. 1296. [bug] isc_log_closefilelogs() needed to lock the log context. 1295. [bug] isc_log_setdebuglevel() needed to lock the log context. 1294. [func] libbind: no longer attempts bit string labels for IPv6 reverse resolution. Try IP6.ARPA then IP6.INT for nibble style resolution. 1293. [func] Entropy can now be retrieved from EGDs. [RT #2438] 1292. [func] Enable IPv6 support when using ioctl style interface scanning and OS supports SIOCGLIFADDR using struct if_laddrreq. 1291. [func] Enable IPv6 support when using sysctl style interface scanning. 1290. [func] "dig axfr" now reports the number of messages as well as the number of records. 1289. [port] See if -ldl is required for OpenSSL? [RT #2672] 1288. [bug] Adjusted REQUIRE's in lib/dns/name.c to better reflect written requirements. 1287. [bug] REQUIRE that DNS_DBADD_MERGE only be set when adding a rdataset to a zone db in the rbtdb implementation of addrdataset. 1286. [bug] dns_name_downcase() enforce requirement that target != NULL or name->buffer != NULL. 1285. [func] lwres: probe the system to see what address families are currently in use. 1284. [bug] The RTT estimate on unused servers was not aged. [RT #2569] 1283. [func] Use "dataready" accept filter if available. 1282. [port] libbind: hpux 11.11 interface scanning. 1281. [func] Log zone when unable to get private keys to update zone. Log zone when NXT records are missing from secure zone. 1280. [bug] libbind: escape '(' and ')' when converting to presentation form. 1279. [port] Darwin uses (unsigned long) for size_t. [RT #2590] 1278. [func] dig: now supports +[no]cl +[no]ttlid. 1277. [func] You can now create your own customized printing styles: dns_master_stylecreate() and dns_master_styledestroy(). 1276. [bug] libbind: const pointer conflicts in res_debug.c. 1275. [port] libbind: hpux: treat all hpux systems as BIG_ENDIAN. 1274. [bug] Memory leak in lwres_gnbarequest_parse(). 1273. [port] libbind: solaris: 64 bit binary compatibility. 1272. [contrib] Berkeley DB 4.0 sdb implementation from Nuno Miguel Rodrigues . 1271. [bug] "recursion available: {denied,approved}" was too confusing. 1270. [bug] Check that system inet_pton() and inet_ntop() support AF_INET6. 1269. [port] Openserver: ifconfig.sh support. 1268. [port] Openserver: the value FD_SETSIZE depends on whether is included or not. Be consistent. 1267. [func] isc_file_openunique() now creates file using mode 0666 rather than 0600. 1266. [bug] ISC_LINK_INIT, ISC_LINK_UNLINK, ISC_LIST_DEQUEUE, __ISC_LINK_UNLINKUNSAFE and __ISC_LIST_DEQUEUEUNSAFE are not C++ compatible, use *_TYPE versions instead. 1265. [bug] libbind: LINK_INIT and UNLINK were not compatible with C++, use LINK_INIT_TYPE and UNLINK_TYPE instead. 1264. [placeholder] 1263. [bug] Reference after free error if dns_dispatchmgr_create() failed. 1262. [bug] ns_server_destroy() failed to set *serverp to NULL. 1261. [func] libbind: ns_sign2() and ns_sign_tcp() now provide support for compressed TSIG owner names. 1260. [func] libbind: res_update can now update IPv6 servers, new function res_findzonecut2(). 1259. [bug] libbind: get_salen() IPv6 support was broken for OSs w/o sa_len. 1258. [bug] libbind: res_nametotype() and res_nametoclass() were broken. 1257. [bug] Failure to write pid-file should not be fatal on reload. [RT #2861] 1256. [contrib] 'queryperf' now has EDNS (-e) + DNSSEC DO (-D) support. 1255. [bug] When verifying that an NXT proves nonexistence, check the rcode of the message and only do the matching NXT check. That is, for NXDOMAIN responses, check that the name is in the range between the NXT owner and next name, and for NOERROR NODATA responses, check that the type is not present in the NXT bitmap. 1254. [func] preferred-glue option from BIND 8.3. 1253. [bug] The dnssec system test failed to remove the correct files. 1252. [bug] Dig, host and nslookup were not checking the address the answer was coming from against the address it was sent to. [RT #2692] 1251. [port] win32: a make file contained absolute version specific references. 1250. [func] Nsupdate will report the address the update was sent to. 1249. [bug] Missing masters clause was not handled gracefully. [RT #2703] 1248. [bug] DESTDIR was not being propagated between makes. 1247. [bug] Don't reset the interface index for link/site local addresses. [RT #2576] 1246. [func] New functions isc_sockaddr_issitelocal(), isc_sockaddr_islinklocal(), isc_netaddr_issitelocal() and isc_netaddr_islinklocal(). 1245. [bug] Treat ENOBUFS, ENOMEM and ENFILE as soft errors for accept(). 1244. [bug] Receiving a TCP message from a blackhole address would prevent further messages being received over that interface. 1243. [bug] It was possible to trigger a REQUIRE() in dns_message_findtype(). [RT #2659] 1242. [bug] named-checkzone failed if a journal existed. [RT #2657] 1241. [bug] Drop received UDP messages with a zero source port as these are invariably forged. [RT #2621] 1240. [bug] It was possible to leak zone references by specifying an incorrect zone to rndc. 1239. [bug] Under certain circumstances named could continue to use a name after it had been freed triggering INSIST() failures. [RT #2614] 1238. [bug] It is possible to lockup the server when shutting down if notifies were being processed. [RT #2591] 1237. [bug] nslookup: "set q=type" failed. 1236. [bug] dns_rdata{class,type}_fromtext() didn't handle non NULL terminated text regions. [RT #2588] 1235. [func] Report 'out of memory' errors from openssl. 1234. [bug] contrib/sdb: 'zonetodb' failed to call dns_result_register(). DNS_R_SEENINCLUDE should not be fatal. 1233. [bug] The flags field of a KEY record can be expressed in hex as well as decimal. 1232. [bug] unix/errno2result() didn't handle EADDRNOTAVAIL. 1231. [port] HPUX 11.11 recvmsg() can return spurious EADDRNOTAVAIL. 1230. [bug] isccc_cc_isreply() and isccc_cc_isack() were broken. 1229. [bug] named would crash if it received a TSIG signed query as part of an AXFR response. [RT #2570] 1228. [bug] 'make install' did not depend on 'make all'. [RT #2559] 1227. [bug] dns_lex_getmastertoken() now returns ISC_R_BADNUMBER if a number was expected and some other token was found. [RT #2532] 1226. [func] Use EDNS for zone refresh queries. [RT #2551] 1225. [func] dns_message_setopt() no longer requires that dns_message_renderbegin() to have been called. 1224. [bug] 'rrset-order' and 'sortlist' should be additive not exclusive. 1223. [func] 'rrset-order' partially works 'cyclic' and 'random' are supported. 1222. [bug] Specifying 'port *' did not always result in a system selected (non-reserved) port being used. [RT #2537] 1221. [bug] Zone types 'master', 'slave' and 'stub' were not being compared case insensitively. [RT #2542] 1220. [func] Support for APL rdata type. 1219. [func] Named now reports the TSIG extended error code when signature verification fails. [RT #1651] 1218. [bug] Named incorrectly returned SERVFAIL rather than NOTAUTH when there was a TSIG BADTIME error. [RT #2519] 1217. [func] Report locations of previous key definition when a duplicate is detected. 1216. [bug] Multiple server clauses for the same server were not reported. [RT #2514] 1215. [port] solaris: add support to ifconfig.sh for x86 2.5.1 1214. [bug] Win32: isc_file_renameunique() could leave zero length files behind. 1213. [func] Report view associated with client if it is not a standard view (_default or _bind). 1212. [port] libbind: 64k answer buffers were causing stack space to be exceeded for certain OS. Use heap space instead. 1211. [bug] dns_name_fromtext() incorrectly handled certain valid octal bitlabels. [RT #2483] 1210. [bug] libbind: getnameinfo() failed to lookup IPv4 mapped / compatible addresses. [RT #2461] 1209. [bug] Dig, host, nslookup were not checking the message ids on the responses. [RT #2454] 1208. [bug] dns_master_load*() failed to log a error message if an error was detected when parsing the owner name of a record. [RT #2448] 1207. [bug] libbind: getaddrinfo() could call freeaddrinfo() with an invalid pointer. 1206. [bug] SERVFAIL and NOTIMP responses to an EDNS query should trigger a non-EDNS retry. 1205. [bug] OPT, TSIG and TKEY cannot be used to set the "class" of the message. [RT #2449] 1204. [bug] libbind: res_nupdate() failed to update the name server addresses before sending the update. 1203. [func] Report locations of previous acl and zone definitions when a duplicate is detected. 1202. [func] New functions: cfg_obj_line() and cfg_obj_file(). 1201. [bug] Require that if 'callbacks' is passed to dns_rdata_fromtext(), callbacks->error and callbacks->warn are initialized. 1200. [bug] Log 'errno' that we are unable to convert to isc_result_t. [RT #2404] 1199. [doc] ARM reference to RFC 2157 should have been RFC 1918. [RT #2436] 1198. [bug] OPT printing style was not consistent with the way the header fields are printed. The DO bit was not reported if set. Report if any of the MBZ bits are set. 1197. [bug] Attempts to define the same acl multiple times were not detected. 1196. [contrib] update mdnkit to 2.2.3. 1195. [bug] Attempts to redefine builtin acls should be caught. [RT #2403] 1194. [bug] Not all duplicate zone definitions were being detected at the named.conf checking stage. [RT #2431] 1193. [bug] dig +besteffort parsing didn't handle packet truncation. dns_message_parse() has new flag DNS_MESSAGE_IGNORETRUNCATION. 1192. [bug] The seconds fields in LOC records were restricted to three decimal places. More decimal places should be allowed but warned about. 1191. [bug] A dynamic update removing the last non-apex name in a secure zone would fail. [RT #2399] 1190. [func] Add the "rndc freeze" and "rndc unfreeze" commands. [RT #2394] 1189. [bug] On some systems, malloc(0) returns NULL, which could cause the caller to report an out of memory error. [RT #2398] 1188. [bug] Dynamic updates of a signed zone would fail if some of the zone private keys were unavailable. 1187. [bug] named was incorrectly returning DNSSEC records in negative responses when the DO bit was not set. 1186. [bug] isc_hex_tobuffer(,,length = 0) failed to unget the EOL token when reading to end of line. 1185. [bug] libbind: don't assume statp->_u._ext.ext is valid unless RES_INIT is set when calling res_*init(). 1184. [bug] libbind: call res_ndestroy() if RES_INIT is set when res_*init() is called. 1183. [bug] Handle ENOSR error when writing to the internal control pipe. [RT #2395] 1182. [bug] The server could throw an assertion failure when constructing a negative response packet. 1181. [func] Add the "key-directory" configuration statement, which allows the server to look for online signing keys in alternate directories. 1180. [func] dnssec-keygen should always generate keys with protocol 3 (DNSSEC), since it's less confusing that way. 1179. [func] Add SIG(0) support to nsupdate. 1178. [bug] Follow and cache (if appropriate) A6 and other data chains to completion in the additional section. 1177. [func] Report view when loading zones if it is not a standard view (_default or _bind). [RT #2270] 1176. [doc] Document that allow-v6-synthesis is only performed for clients that are supplied recursive service. [RT #2260] 1175. [bug] named-checkzone and named-checkconf failed to call dns_result_register() at startup which could result in runtime exceptions when printing "out of memory" errors. [RT #2335] 1174. [bug] Win32: add WSAECONNRESET to the expected errors from connect(). [RT #2308] 1173. [bug] Potential memory leaks in isc_log_create() and isc_log_settag(). [RT #2336] 1172. [doc] Add CERT, GPOS, KX, NAPTR, NSAP, PX and TXT to table of RR types in ARM. 1171. [func] Added function isc_region_compare(), updated files in lib/dns to use this function instead of local one. 1170. [bug] Don't attempt to print the token when a I/O error occurs when parsing named.conf. [RT #2275] 1169. [func] Identify recursive queries in the query log. 1168. [bug] Empty also-notify clauses were not handled. [RT #2309] 1167. [contrib] nslint-2.1a3 (from author). 1166. [bug] "Not Implemented" should be reported as NOTIMP, not NOTIMPL. [RT #2281] 1165. [bug] We were rejecting notify-source{-v6} in zone clauses. 1164. [bug] Empty masters clauses in slave / stub zones were not handled gracefully. [RT #2262] 1163. [func] isc_time_formattimestamp() now includes the year. 1162. [bug] The allow-notify option was not accepted in slave zone statements. 1161. [bug] named-checkzone looped on unbalanced brackets. [RT #2248] 1160. [bug] Generating Diffie-Hellman keys longer than 1024 bits could fail. [RT #2241] 1159. [bug] MD and MF are not permitted to be loaded by RFC1123. 1158. [func] Report the client's address when logging notify messages. 1157. [func] match-clients and match-destinations now accept keys. [RT #2045] 1156. [port] The configure test for strsep() incorrectly succeeded on certain patched versions of AIX 4.3.3. [RT #2190] 1155. [func] Recover from master files being removed from under us. 1154. [bug] Don't attempt to obtain the netmask of a interface if there is no address configured. [RT #2176] 1153. [func] 'rndc {stop|halt} -p' now reports the process id of the instance of named being shutdown. 1152. [bug] libbind: read buffer overflows. 1151. [bug] nslookup failed to check that the arguments to the port, timeout, and retry options were valid integers and in range. [RT #2099] 1150. [bug] named incorrectly accepted TTL values containing plus or minus signs, such as 1d+1h-1s. 1149. [func] New function isc_parse_uint32(). 1148. [func] 'rndc-confgen -a' now provides positive feedback. 1147. [func] Set IPV6_V6ONLY on IPv6 sockets if supported by the OS. listen-on-v6 { any; }; should no longer result in IPv4 queries be accepted. Similarly control { inet :: ... }; should no longer result in IPv4 connections being accepted. This can be overridden at compile time by defining ISC_ALLOW_MAPPED=1. 1146. [func] Allow IPV6_IPV6ONLY to be set/cleared on a socket if supported by the OS by a new function isc_socket_ipv6only(). 1145. [func] "host" no longer reports a NOERROR/NODATA response by printing nothing. [RT #2065] 1144. [bug] rndc-confgen would crash if both the -a and -t options were specified. [RT #2159] 1143. [bug] When a trusted-keys statement was present and named was built without crypto support, it would leak memory. 1142. [bug] dnssec-signzone would fail to delete temporary files in some failure cases. [RT #2144] 1141. [bug] When named rejected a control message, it would leak a file descriptor and memory. It would also fail to respond, causing rndc to hang. [RT #2139, #2164] 1140. [bug] rndc-confgen did not accept IPv6 addresses as arguments to the -s option. [RT #2138] 1139. [func] It is now possible to flush a given name from the cache(s) via 'rndc flushname name [view]'. [RT #2051] 1138. [func] It is now possible to flush a given name from the cache by calling the new function dns_cache_flushname(). 1137. [func] It is now possible to flush a given name from the ADB by calling the new function dns_adb_flushname(). 1136. [bug] CNAME records synthesized from DNAMEs did not have a TTL of zero as required by RFC2672. [RT #2129] 1135. [func] You can now override the default syslog() facility for named/lwresd at compile time. [RT #1982] 1134. [bug] Multi-threaded servers could deadlock in ferror() when reloading zone files. [RT #1951, #1998] 1133. [bug] IN6_IS_ADDR_LOOPBACK was not portably defined on platforms without IN6_IS_ADDR_LOOPBACK. [RT #2106] 1132. [func] Improve UPDATE prerequisite failure diagnostic messages. 1131. [bug] The match-destinations view option did not work with IPv6 destinations. [RT #2073, #2074] 1130. [bug] Log messages reporting an out-of-range serial number did not include the out-of-range number but the following token. [RT #2076] 1129. [bug] Multi-threaded servers could crash under heavy resolution load due to a race condition. [RT #2018] 1128. [func] sdb drivers can now provide RR data in either text or wire format, the latter using the new functions dns_sdb_putrdata() and dns_sdb_putnamedrdata(). 1127. [func] rndc: If the server to contact has multiple addresses, try all of them. 1126. [bug] The server could access a freed event if shut down while a client start event was pending delivery. [RT #2061] 1125. [bug] rndc: -k option was missing from usage message. [RT #2057] 1124. [doc] dig: +[no]dnssec, +[no]besteffort and +[no]fail are now documented. [RT #2052] 1123. [bug] dig +[no]fail did not match description. [RT #2052] 1122. [tuning] Resolution timeout reduced from 90 to 30 seconds. [RT #2046] 1121. [bug] The server could attempt to access a NULL zone table if shut down while resolving. [RT #1587, #2054] 1120. [bug] Errors in options were not fatal. [RT #2002] 1119. [func] Added support in Win32 for NTFS file/directory ACL's for access control. 1118. [bug] On multi-threaded servers, a race condition could cause an assertion failure in resolver.c during resolver shutdown. [RT #2029] 1117. [port] The configure check for in6addr_loopback incorrectly succeeded on AIX 4.3 when compiling with -O2 because the test code was optimized away. [RT #2016] 1116. [bug] Setting transfers in a server clause, transfers-in, or transfers-per-ns to a value greater than 2147483647 disabled transfers. [RT #2002] 1115. [func] Set maximum values for cleaning-interval, heartbeat-interval, interface-interval, max-transfer-idle-in, max-transfer-idle-out, max-transfer-time-in, max-transfer-time-out, statistics-interval of 28 days and sig-validity-interval of 3660 days. [RT #2002] 1114. [port] Ignore more accept() errors. [RT #2021] 1113. [bug] The allow-update-forwarding option was ignored when specified in a view. [RT #2014] 1112. [placeholder] 1111. [bug] Multi-threaded servers could deadlock processing recursive queries due to a locking hierarchy violation in adb.c. [RT #2017] 1110. [bug] dig should only accept valid abbreviations of +options. [RT #2003] 1109. [bug] nsupdate accepted illegal ttl values. 1108. [bug] On Win32, rndc was hanging when named was not running due to failure to select for exceptional conditions in select(). [RT #1870] 1107. [bug] nsupdate could catch an assertion failure if an invalid domain name was given as the argument to the "zone" command. 1106. [bug] After seeing an out of range TTL, nsupdate would treat all TTLs as out of range. [RT #2001] 1105. [port] OpenUNIX 8 enable threads by default. [RT #1970] 1104. [bug] Invalid arguments to the transfer-format option could cause an assertion failure. [RT #1995] 1103. [port] OpenUNIX 8 support (ifconfig.sh). [RT #1970] 1102. [doc] Note that query logging is enabled by directing the queries category to a channel. 1101. [bug] Array bounds read error in lwres_gai_strerror. 1100. [bug] libbind: DNSSEC key ids were computed incorrectly. 1099. [cleanup] libbind: defining REPORT_ERRORS in lib/bind/dst caused compile time errors. 1098. [bug] libbind: HMAC-MD5 key files are now mode 0600. 1097. [func] libbind: RES_PRF_TRUNC for dig. 1096. [func] libbind: "DNSSEC OK" (DO) support. 1095. [func] libbind: resolver option: no-tld-query. disables trying unqualified as a tld. no_tld_query is also supported for FreeBSD compatibility. 1094. [func] libbind: add support gcc's format string checking. 1093. [doc] libbind: miscellaneous nroff fixes. 1092. [bug] libbind: get*by*() failed to check if res_init() had been called. 1091. [bug] libbind: misplaced va_end(). 1090. [bug] libbind: dns_ho.c:add_hostent() was not returning the amount of memory consumed resulting in garbage address being returned. Alignment calculations were wasting space. We weren't suppressing duplicate addresses. 1089. [func] libbind: inet_{cidr,net}_{pton,ntop}() now have IPv6 support. 1088. [port] libbind: MPE/iX C.70 (incomplete) 1087. [bug] libbind: struct __res_state too large on 64 bit arch. 1086. [port] libbind: sunos: old sprintf. 1085. [port] libbind: solaris: sys_nerr and sys_errlist do not exist when compiling in 64 bit mode. 1084. [cleanup] libbind: gai_strerror() rewritten. 1083. [bug] The default control channel listened on the wildcard address, not the loopback as documented. [RT #1975] 1082. [bug] The -g option to named incorrectly caused logging to be sent to syslog in addition to stderr. [RT #1974] 1081. [bug] Multicast queries were incorrectly identified based on the source address, not the destination address. 1080. [bug] BIND 8 compatibility: accept bare IP prefixes as the second element of a two-element top level sort list statement. [RT #1964] 1079. [bug] BIND 8 compatibility: accept bare elements at top level of sort list treating them as if they were a single element list. [RT #1963] 1078. [bug] We failed to correct bad tv_usec values in one case. [RT #1966] 1077. [func] Do not accept further recursive clients when the total number of recursive lookups being processed exceeds max-recursive-clients, even if some of the lookups are internally generated. [RT #1915, #1938] 1076. [bug] A badly defined global key could trigger an assertion on load/reload if views were used. [RT #1947] 1075. [bug] Out-of-range network prefix lengths were not reported. [RT #1954] 1074. [bug] Running out of memory in dump_rdataset() could cause an assertion failure. [RT #1946] 1073. [bug] The ADB cache cleaning should also be space driven. [RT #1915, #1938] 1072. [bug] The TCP client quota could be exceeded when recursion occurred. [RT #1937] 1071. [bug] Sockets listening for TCP DNS connections specified an excessive listen backlog. [RT #1937] 1070. [bug] Copy DNSSEC OK (DO) to response as specified by draft-ietf-dnsext-dnssec-okbit-03.txt. 1069. [placeholder] 1068. [bug] errno could be overwritten by catgets(). [RT #1921] 1067. [func] Allow quotas to be soft, isc_quota_soft(). 1066. [bug] Provide a thread safe wrapper for strerror(). [RT #1689] 1065. [func] Runtime support to select new / old style interface scanning using ioctls. 1064. [bug] Do not shut down active network interfaces if we are unable to scan the interface list. [RT #1921] 1063. [bug] libbind: "make install" was failing on IRIX. [RT #1919] 1062. [bug] If the control channel listener socket was shut down before server exit, the listener object could be freed twice. [RT #1916] 1061. [bug] If periodic cache cleaning happened to start while cleaning due to reaching the configured maximum cache size was in progress, the server could catch an assertion failure. [RT #1912] 1060. [func] Move refresh, stub and notify UDP retry processing into dns_request. 1059. [func] dns_request now support will now retry UDP queries, dns_request_createvia2() and dns_request_createraw2(). 1058. [func] Limited lifetime ticker timers are now available, isc_timertype_limited. 1057. [bug] Reloading the server after adding a "file" clause to a zone statement could cause the server to crash due to a typo in change 1016. 1056. [bug] Rndc could catch an assertion failure on SIGINT due to an uninitialized variable. [RT #1908] 1055. [func] Version and hostname queries can now be disabled using "version none;" and "hostname none;", respectively. 1054. [bug] On Win32, cfg_categories and cfg_modules need to be exported from the libisccfg DLL. 1053. [bug] Dig did not increase its timeout when receiving AXFRs unless the +time option was used. [RT #1904] 1052. [bug] Journals were not being created in binary mode resulting in "journal format not recognized" error under Win32. [RT #1889] 1051. [bug] Do not ignore a network interface completely just because it has a noncontiguous netmask. Instead, omit it from the localnets ACL and issue a warning. [RT #1891] 1050. [bug] Log messages reporting malformed IP addresses in address lists such as that of the forwarders option failed to include the correct error code, file name, and line number. [RT #1890] 1049. [func] "pid-file none;" will disable writing a pid file. [RT #1848] 1048. [bug] Servers built with -DISC_MEM_USE_INTERNAL_MALLOC=1 didn't work. 1047. [bug] named was incorrectly refusing all requests signed with a TSIG key derived from an unsigned TKEY negotiation with a NOERROR response. [RT #1886] 1046. [bug] The help message for the --with-openssl configure option was inaccurate. [RT #1880] 1045. [bug] It was possible to skip saving glue for a nameserver for a stub zone. 1044. [bug] Specifying allow-transfer, notify-source, or notify-source-v6 in a stub zone was not treated as an error. 1043. [bug] Specifying a transfer-source or transfer-source-v6 option in the zone statement for a master zone was not treated as an error. [RT #1876] 1042. [bug] The "config" logging category did not work properly. [RT #1873] 1041. [bug] Dig/host/nslookup could catch an assertion failure on SIGINT due to an uninitialized variable. [RT #1867] 1040. [bug] Multiple listen-on-v6 options with different ports were not accepted. [RT #1875] 1039. [bug] Negative responses with CNAMEs in the answer section were cached incorrectly. [RT #1862] 1038. [bug] In servers configured with a tkey-domain option, TKEY queries with an owner name other than the root could cause an assertion failure. [RT #1866, #1869] 1037. [bug] Negative responses whose authority section contain SOA or NS records whose owner names are not equal equal to or parents of the query name should be rejected. [RT #1862] 1036. [func] Silently drop requests received via multicast as long as there is no final multicast DNS standard. 1035. [bug] If we respond to multicast queries (which we currently do not), respond from a unicast address as specified in RFC 1123. [RT #137] 1034. [bug] Ignore the RD bit on multicast queries as specified in RFC 1123. [RT #137] 1033. [bug] Always respond to requests with an unsupported opcode with NOTIMP, even if we don't have a matching view or cannot determine the class. 1032. [func] hostname.bind/txt/chaos now returns the name of the machine hosting the nameserver. This is useful in diagnosing problems with anycast servers. 1031. [bug] libbind.a: isc__gettimeofday() infinite recursion. [RT #1858] 1030. [bug] On systems with no resolv.conf file, nsupdate exited with an error rather than defaulting to using the loopback address. [RT #1836] 1029. [bug] Some named.conf errors did not cause the loading of the configuration file to return a failure status even though they were logged. [RT #1847] 1028. [bug] On Win32, dig/host/nslookup looked for resolv.conf in the wrong directory. [RT #1833] 1027. [bug] RRs having the reserved type 0 should be rejected. [RT #1471] 1026. [placeholder] 1025. [bug] Don't use multicast addresses to resolve iterative queries. [RT #101] 1024. [port] Compilation failed on HP-UX 11.11 due to incompatible use of the SIOCGLIFCONF macro name. [RT #1831] 1023. [func] Accept hints without TTLs. 1022. [bug] Don't report empty root hints as "extra data". [RT #1802] 1021. [bug] On Win32, log message timestamps were one month later than they should have been, and the server would exhibit unspecified behavior in December. 1020. [bug] IXFR log messages did not distinguish between true IXFRs, AXFR-style IXFRs, and mere version polls. [RT #1811] 1019. [bug] The value of the lame-ttl option was limited to 18000 seconds, not 1800 seconds as documented. [RT #1803] 1018. [bug] The default log channel was not always initialized correctly. [RT #1813] 1017. [bug] When specifying TSIG keys to dig and nsupdate using the -k option, they must be HMAC-MD5 keys. [RT #1810] 1016. [bug] Slave zones with no backup file were re-transferred on every server reload. 1015. [bug] Log channels that had a "versions" option but no "size" option failed to create numbered log files. [RT #1783] 1014. [bug] Some queries would cause statistics counters to increment more than once or not at all. [RT #1321] 1013. [bug] It was possible to cancel a query twice when marking a server as bogus or by having a blackhole acl. [RT #1776] 1012. [bug] The -p option to named did not behave as documented. 1011. [cleanup] Removed isc_dir_current(). 1010. [bug] The server could attempt to execute a command channel command after initiating server shutdown, causing an assertion failure. [RT #1766] 1009. [port] OpenUNIX 8 support. [RT #1728] 1008. [port] libtool.m4, ltmain.sh from libtool-1.4.2. 1007. [port] config.guess, config.sub from autoconf-2.52. 1006. [bug] If a KEY RR was found missing during DNSSEC validation, an assertion failure could subsequently be triggered in the resolver. [RT #1763] 1005. [bug] Don't copy nonzero RCODEs from request to response. [RT #1765] 1004. [port] Deal with recvfrom() returning EHOSTDOWN. [RT #1770] 1003. [func] Add the +retry option to dig. 1002. [bug] When reporting an unknown class name in named.conf, including the file name and line number. [RT #1759] 1001. [bug] win32 socket code doio_recv was not catching a WSACONNRESET error when a client was timing out the request and closing its socket. [RT #1745] 1000. [bug] BIND 8 compatibility: accept "HESIOD" as an alias for class "HS". [RT #1759] 999. [func] "rndc retransfer zone [class [view]]" added. [RT #1752] 998. [func] named-checkzone now has arguments to specify the chroot directory (-t) and working directory (-w). [RT #1755] 997. [func] Add support for RSA-SHA1 keys (RFC3110). 996. [func] Issue warning if the configuration filename contains the chroot path. 995. [bug] dig, host, nslookup: using a raw IPv6 address as a target address should be fatal on a IPv4 only system. 994. [func] Treat non-authoritative responses to queries for type NS as referrals even if the NS records are in the answer section, because BIND 8 servers incorrectly send them that way. This is necessary for DNSSEC validation of the NS records of a secure zone to succeed when the parent is a BIND 8 server. [RT #1706] 993. [func] dig: -v now reports the version. 992. [doc] dig: ~/.digrc is now documented. 991. [func] Lower UDP refresh timeout messages to level debug 1. 990. [bug] The rndc-confgen man page was not installed. 989. [bug] Report filename if $INCLUDE fails for file related errors. [RT #1736] 988. [bug] 'additional-from-auth no;' did not work reliably in the case of queries answered from the cache. [RT #1436] 987. [bug] "dig -help" didn't show "+[no]stats". 986. [bug] "dig +noall" failed to clear stats and command printing. 985. [func] Consider network interfaces to be up iff they have a nonzero IP address rather than based on the IFF_UP flag. [RT #1160] 984. [bug] Multi-threading should be enabled by default on Solaris 2.7 and newer, but it wasn't. 983. [func] The server now supports generating IXFR difference sequences for non-dynamic zones by comparing zone versions, when enabled using the new config option "ixfr-from-differences". [RT #1727] 982. [func] If "memstatistics-file" is set in options the memory statistics will be written to it. 981. [func] The dnssec tools can now take multiple '-r randomfile' arguments. 980. [bug] Incoming zone transfers restarting after an error could trigger an assertion failure. [RT #1692] 979. [func] Incremental master file dumping. dns_master_dumpinc(), dns_master_dumptostreaminc(), dns_dumpctx_attach(), dns_dumpctx_detach(), dns_dumpctx_cancel(), dns_dumpctx_db() and dns_dumpctx_version(). 978. [bug] dns_db_attachversion() had an invalid REQUIRE() condition. 977. [bug] Improve "not at top of zone" error message. 976. [func] named-checkconf can now test load master zones (named-checkconf -z). [RT #1468] 975. [bug] "max-cache-size default;" as a view option caused an assertion failure. 974. [bug] "max-cache-size unlimited;" as a global option was not accepted. 973. [bug] Failed to log the question name when logging: "bad zone transfer request: non-authoritative zone (NOTAUTH)". 972. [bug] The file modification time code in zone.c was using the wrong epoch. [RT #1667] 971. [placeholder] 970. [func] 'max-journal-size' can now be used to set a target size for a journal. 969. [func] dig now supports the undocumented dig 8 feature of allowing arbitrary labels, not just dotted decimal quads, with the -x option. This can be used to conveniently look up RFC2317 names as in "dig -x 10.0.0.0-127". [RT #827, #1576, #1598] 968. [bug] On win32, the isc_time_now() function was unnecessarily calling strtime(). [RT #1671] 967. [bug] On win32, the link for bindevt was not including the required resource file to enable the event viewer to interpret the error messages in the event log, [RT #1668] 966. [placeholder] 965. [bug] Including data other than root server NS and A records in the root hint file could cause a rbtdb node reference leak. [RT #1581, #1618] 964. [func] Warn if data other than root server NS and A records are found in the root hint file. [RT #1581, #1618] 963. [bug] Bad ISC_LANG_ENDDECLS. [RT #1645] 962. [bug] libbind: bad "#undef", don't attempt to install non-existent nlist.h. [RT #1640] 961. [bug] Tried to use a IPV6 feature when ISC_PLATFORM_HAVEIPV6 was not defined. [RT #1482] 960. [port] liblwres failed to build on systems with support for getrrsetbyname() in the OS. [RT #1592] 959. [port] On FreeBSD, determine the number of CPUs by calling sysctlbyname(). [RT #1584] 958. [port] ssize_t is not available on all platforms. [RT #1607] 957. [bug] sys/select.h inclusion was broken on older platforms. [RT #1607] 956. [bug] ns_g_autorndcfile changed to ns_g_keyfile in named/win32/os.c due to code changes in change #953. win32 .make file for rndc-confgen updated to add include path for os.h header. --- 9.2.0rc1 released --- 955. [bug] When using views, the zone's class was not being inherited from the view's class. [RT #1583] 954. [bug] When requesting AXFRs or IXFRs using dig, host, or nslookup, the RD bit should not be set as zone transfers are inherently non-recursive. [RT #1575] 953. [func] The /var/run/named.key file from change #843 has been replaced by /etc/rndc.key. Both named and rndc will look for this file and use it to configure a default control channel key if not already configured using a different method (rndc.conf / controls). Unlike named.key, rndc.key is not created automatically; it must be created by manually running "rndc-confgen -a". 952. [bug] The server required manual intervention to serve the affected zones if it died between creating a journal and committing the first change to it. 951. [bug] CFLAGS was not passed to the linker when linking some of the test programs under bin/tests. [RT #1555]. 950. [bug] Explicit TTLs did not properly override $TTL due to a bug in change 834. [RT #1558] 949. [bug] host was unable to print records larger than 512 bytes. [RT #1557] --- 9.2.0b2 released --- 948. [port] Integrated support for building on Windows NT / Windows 2000. 947. [bug] dns_rdata_soa_t had a badly named element "mname" which was really the RNAME field from RFC1035. To avoid confusion and silent errors that would occur it the "origin" and "mname" elements were given their correct names "mname" and "rname" respectively, the "mname" element is renamed to "contact". 946. [cleanup] doc/misc/options is now machine-generated from the configuration parser syntax tables, and therefore more likely to be correct. 945. [func] Add the new view-specific options "match-destinations" and "match-recursive-only". 944. [func] Check for expired signatures on load. 943. [bug] The server could crash when receiving a command via rndc if the configuration file listed only nonexistent keys in the controls statement. [RT #1530] 942. [port] libbind: GETNETBYADDR_ADDR_T was not correctly defined on some platforms. 941. [bug] The configuration checker crashed if a slave zone didn't contain a masters statement. [RT #1514] 940. [bug] Double zone locking failure on error path. [RT #1510] --- 9.2.0b1 released --- 939. [port] Add the --disable-linux-caps option to configure for systems that manage capabilities outside of named. [RT #1503] 938. [placeholder] 937. [bug] A race when shutting down a zone could trigger a INSIST() failure. [RT #1034] 936. [func] Warn about IPv4 addresses that are not complete dotted quads. [RT #1084] 935. [bug] inet_pton failed to reject leading zeros. 934. [port] Deal with systems where accept() spuriously returns ECONNRESET. 933. [bug] configure failed doing libbind on platforms not supported by BIND 8. [RT #1496] --- 9.2.0a3 released --- 932. [bug] Use INSTALL_SCRIPT, not INSTALL_PROGRAM, when installing isc-config.sh. [RT #198, #1466] 931. [bug] The controls statement only attempted to verify messages using the first key in the key list. (9.2.0a1/a2 only). 930. [func] Query performance testing tool added as contrib/queryperf. 929. [placeholder] 928. [bug] nsupdate would send empty update packets if the send (or empty line) command was run after another send but before any new updates or prerequisites were specified. It should simply ignore this command. 927. [bug] Don't hold the zone lock for the entire dump to disk. [RT #1423] 926. [bug] The resolver could deadlock with the ADB when shutting down (multi-threaded builds only). [RT #1324] 925. [cleanup] Remove openssl from the distribution; require that --with-openssl be specified if DNSSEC is needed. 924. [port] Extend support for pre-RFC2133 IPv6 implementation. [RT #987] 923. [bug] Multiline TSIG secrets (and other multiline strings) were not accepted in named.conf. [RT #1469] 922. [func] Added two new lwres_getrrsetbyname() result codes, ERR_NONAME and ERR_NODATA. 921. [bug] lwres returned an incorrect error code if it received a truncated message. 920. [func] Increase the lwres receive buffer size to 16K. [RT #1451] 919. [placeholder] 918. [func] In nsupdate, TSIG errors are no longer treated as fatal errors. 917. [func] New nsupdate command 'key', allowing TSIG keys to be specified in the nsupdate command stream rather than the command line. 916. [bug] Specifying type ixfr to dig without specifying a serial number failed in unexpected ways. 915. [func] The named-checkconf and named-checkzone programs now have a '-v' option for printing their version. [RT #1151] 914. [bug] Global 'server' statements were rejected when using views, even though they were accepted in 9.1. [RT #1368] 913. [bug] Cache cleaning was not sufficiently aggressive. [RT #1441, #1444] 912. [bug] Attempts to set the 'additional-from-cache' or 'additional-from-auth' option to 'no' in a server with recursion enabled will now be ignored and cause a warning message. [RT #1145] 911. [placeholder] 910. [port] Some pre-RFC2133 IPv6 implementations do not define IN6ADDR_ANY_INIT. [RT #1416] 909. [placeholder] 908. [func] New program, rndc-confgen, to simplify setting up rndc. 907. [func] The ability to get entropy from either the random device, a user-provided file or from the keyboard was migrated from the DNSSEC tools to libisc as isc_entropy_usebestsource(). 906. [port] Separated the system independent portion of lib/isc/unix/entropy.c into lib/isc/entropy.c and added lib/isc/win32/entropy.c. 905. [bug] Configuring a forward "zone" for the root domain did not work. [RT #1418] 904. [bug] The server would leak memory if attempting to use an expired TSIG key. [RT #1406] 903. [bug] dig should not crash when receiving a TCP packet of length 0. 902. [bug] The -d option was ignored if both -t and -g were also specified. 901. [placeholder] 900. [bug] A config.guess update changed the system identification string of FreeBSD systems; configure and bin/tests/system/ifconfig.sh now recognize the new string. --- 9.2.0a2 released --- 899. [bug] lib/dns/soa.c failed to compile on many platforms due to inappropriate use of a void value. [RT #1372, #1373, #1386, #1387, #1395] 898. [bug] "dig" failed to set a nonzero exit status on UDP query timeout. [RT #1323] 897. [bug] A config.guess update changed the system identification string of UnixWare systems; configure now recognizes the new string. 896. [bug] If a configuration file is set on named's command line and it has a relative pathname, the current directory (after any possible jailing resulting from named -t) will be prepended to it so that reloading works properly even when a directory option is present. 895. [func] New function, isc_dir_current(), akin to POSIX's getcwd(). 894. [bug] When using the DNSSEC tools, a message intended to warn when the keyboard was being used because of the lack of a suitable random device was not being printed. 893. [func] Removed isc_file_test() and added isc_file_exists() for the basic functionality that was being added with isc_file_test(). 892. [placeholder] 891. [bug] Return an error when a SIG(0) signed response to an unsigned query is seen. This should actually do the verification, but it's not currently possible. [RT #1391] 890. [cleanup] The man pages no longer require the mandoc macros and should now format cleanly using most versions of nroff, and HTML versions of the man pages have been added. Both are generated from DocBook source. 889. [port] Eliminated blank lines before .TH in nroff man pages since they cause problems with some versions of nroff. [RT #1390] 888. [bug] Don't die when using TKEY to delete a nonexistent TSIG key. [RT #1392] 887. [port] Detect broken compilers that can't call static functions from inline functions. [RT #1212] 886. [placeholder] 885. [placeholder] 884. [placeholder] 883. [placeholder] 882. [placeholder] 881. [placeholder] 880. [placeholder] 879. [placeholder] 878. [placeholder] 877. [placeholder] 876. [placeholder] 875. [placeholder] 874. [placeholder] 873. [placeholder] 872. [placeholder] 871. [placeholder] 870. [placeholder] 869. [placeholder] 868. [placeholder] 867. [placeholder] 866. [func] Close debug only file channels when debug is set to zero. [RT #1246] 865. [bug] The new configuration parser did not allow the optional debug level in a "severity debug" clause of a logging channel to be omitted. This is now allowed and treated as "severity debug 1;" like it does in BIND 8.2.4, not as "severity debug 0;" like it did in BIND 9.1. [RT #1367] 864. [cleanup] Multi-threading is now enabled by default on OSF1, Solaris 2.7 and newer, AIX, IRIX, and HP-UX. 863. [bug] If an error occurred while an outgoing zone transfer was starting up, the server could access a domain name that had already been freed when logging a message saying that the transfer was starting. [RT #1383] 862. [bug] Use after realloc(), non portable pointer arithmetic in grmerge(). 861. [port] Add support for Mac OS X, by making it equivalent to Darwin. This was derived from the config.guess file shipped with Mac OS X. [RT #1355] 860. [func] Drop cross class glue in zone transfers. 859. [bug] Cache cleaning now won't swamp the CPU if there is a persistent over limit condition. 858. [func] isc_mem_setwater() no longer requires that when the callback function is non-NULL then its hi_water argument must be greater than its lo_water argument (they can now be equal) or that they be non-zero. 857. [cleanup] Use ISC_MAGIC() to define all magic numbers for structs, for our friends in EBCDIC-land. 856. [func] Allow partial rdatasets to be returned in answer and authority sections to help non-TCP capable clients recover from truncation. [RT #1301] 855. [bug] Stop spurious "using RFC 1035 TTL semantics" warnings. 854. [bug] The config parser didn't properly handle config options that were specified in units of time other than seconds. [RT #1372] 853. [bug] configure_view_acl() failed to detach existing acls. [RT #1374] 852. [bug] Handle responses from servers which do not know about IXFR. 851. [cleanup] The obsolete support-ixfr option was not properly ignored. --- 9.2.0a1 released --- 850. [bug] dns_rbt_findnode() would not find nodes that were split on a bitstring label somewhere other than in the last label of the node. [RT #1351] 849. [func] will ensure INADDR_LOOPBACK is defined. 848. [func] A minimum max-cache-size of two megabytes is enforced by the cache cleaner. 847. [func] Added isc_file_test(), which currently only has some very basic functionality to test for the existence of a file, whether a pathname is absolute, or whether a pathname is the fundamental representation of the current directory. It is intended that this function can be expanded to test other things a programmer might want to know about a file. 846. [func] A non-zero 'param' to dst_key_generate() when making an hmac-md5 key means that good entropy is not required. 845. [bug] The access rights on the public file of a symmetric key are now restricted as soon as the file is opened, rather than after it has been written and closed. 844. [func] will ensure INADDR_LOOPBACK is defined, just as does. 843. [func] If no controls statement is present in named.conf, or if any inet phrase of a controls statement is lacking a keys clause, then a key will be automatically generated by named and an rndc.conf-style file named named.key will be written that uses it. rndc will use this file only if its normal configuration file, or one provided on the command line, does not exist. 842. [func] 'rndc flush' now takes an optional view. 841. [bug] When sdb modules were not declared threadsafe, their create and destroy functions were not serialized. 840. [bug] The config file parser could print the wrong file name if an error was detected after an included file was parsed. [RT #1353] 839. [func] Dump packets for which there was no view or that the class could not be determined to category "unmatched". 838. [port] UnixWare 7.x.x is now suported by bin/tests/system/ifconfig.sh. 837. [cleanup] Multi-threading is now enabled by default only on OSF1, Solaris 2.7 and newer, and AIX. 836. [func] Upgraded libtool to 1.4. 835. [bug] The dispatcher could enter a busy loop if it got an I/O error receiving on a UDP socket. [RT #1293] 834. [func] Accept (but warn about) master files beginning with an SOA record without an explicit TTL field and lacking a $TTL directive, by using the SOA MINTTL as a default TTL. This is for backwards compatibility with old versions of BIND 8, which accepted such files without warning although they are illegal according to RFC1035. 833. [cleanup] Moved dns_soa_*() from to , and extended them to support all the integer-valued fields of the SOA RR. 832. [bug] The default location for named.conf in named-checkconf should depend on --sysconfdir like it does in named. [RT #1258] 831. [placeholder] 830. [func] Implement 'rndc status'. 829. [bug] The DNS_R_ZONECUT result code should only be returned when an ANY query is made with DNS_DBFIND_GLUEOK set. In all other ANY query cases, returning the delegation is better. 828. [bug] The errno value from recvfrom() could be overwritten by logging code. [RT #1293] 827. [bug] When an IXFR protocol error occurs, the slave should retry with AXFR. 826. [bug] Some IXFR protocol errors were not detected. 825. [bug] zone.c:ns_query() detached from the wrong zone reference. [RT #1264] 824. [bug] Correct line numbers reported by dns_master_load(). [RT #1263] 823. [func] The output of "dig -h" now goes to stdout so that it can easily be piped through "more". [RT #1254] 822. [bug] Sending nxrrset prerequisites would crash nsupdate. [RT #1248] 821. [bug] The program name used when logging to syslog should be stripped of leading path components. [RT #1178, #1232] 820. [bug] Name server address lookups failed to follow A6 chains into the glue of local authoritative zones. 819. [bug] In certain cases, the resolver's attempts to restart an address lookup at the root could cause the fetch to deadlock (with itself) instead of restarting. [RT #1225] 818. [bug] Certain pathological responses to ANY queries could cause an assertion failure. [RT #1218] 817. [func] Adjust timeouts for dialup zone queries. 816. [bug] Report potential problems with log file accessibility at configuration time, since such problems can't reliably be reported at the time they actually occur. 815. [bug] If a log file was specified with a path separator character (i.e. "/") in its name and the directory did not exist, the log file's name was treated as though it were the directory name. [RT #1189] 814. [bug] Socket objects left over from accept() failures were incorrectly destroyed, causing corruption of socket manager data structures. 813. [bug] File descriptors exceeding FD_SETSIZE were handled badly. [RT #1192] 812. [bug] dig sometimes printed incomplete IXFR responses due to an uninitialized variable. [RT #1188] 811. [bug] Parentheses were not quoted in zone dumps. [RT #1194] 810. [bug] The signer name in SIG records was not properly down-cased when signing/verifying records. [RT #1186] 809. [bug] Configuring a non-local address as a transfer-source could cause an assertion failure during load. 808. [func] Add 'rndc flush' to flush the server's cache. 807. [bug] When setting up TCP connections for incoming zone transfers, the transfer-source port was not ignored like it should be. 806. [bug] DNS_R_SEENINCLUDE was failing to propagate back up the calling stack to the zone maintenance level, causing zones to not reload when an included file was touched but the top-level zone file was not. 805. [bug] When using "forward only", missing root hints should not cause queries to fail. [RT #1143] 804. [bug] Attempting to obtain entropy could fail in some situations. This would be most common on systems with user-space threads. [RT #1131] 803. [bug] Treat all SIG queries as if they have the CD bit set, otherwise no data will be returned [RT #749] 802. [bug] DNSSEC key tags were computed incorrectly in almost all cases. [RT #1146] 801. [bug] nsupdate should treat lines beginning with ';' as comments. [RT #1139] 800. [bug] dnssec-signzone produced incorrect statistics for large zones. [RT #1133] 799. [bug] The ADB didn't find AAAA glue in a zone unless A6 glue was also present. 798. [bug] nsupdate should be able to reject bad input lines and continue. [RT #1130] 797. [func] Issue a warning if the 'directory' option contains a relative path. [RT #269] 796. [func] When a size limit is associated with a log file, only roll it when the size is reached, not every time the log file is opened. [RT #1096] 795. [func] Add the +multiline option to dig. [RT #1095] 794. [func] Implement the "port" and "default-port" statements in rndc.conf. 793. [cleanup] The DNSSEC tools could create filenames that were illegal or contained shell meta-characters. They now use a different text encoding of names that doesn't have these problems. [RT #1101] 792. [cleanup] Replace the OMAPI command channel protocol with a simpler one. 791. [bug] The command channel now works over IPv6. 790. [bug] Wildcards created using dynamic update or IXFR could fail to match. [RT #1111] 789. [bug] The "localhost" and "localnets" ACLs did not match when used as the second element of a two-element sortlist item. 788. [func] Add the "match-mapped-addresses" option, which causes IPv6 v4mapped addresses to be treated as IPv4 addresses for the purpose of acl matching. 787. [bug] The DNSSEC tools failed to downcase domain names when mapping them into file names. 786. [bug] When DNSSEC signing/verifying data, owner names were not properly down-cased. 785. [bug] A race condition in the resolver could cause an assertion failure. [RT #673, #872, #1048] 784. [bug] nsupdate and other programs would not quit properly if some signals were blocked by the caller. [RT #1081] 783. [bug] Following CNAMEs could cause an assertion failure when either using an sdb database or under very rare conditions. 782. [func] Implement the "serial-query-rate" option. 781. [func] Avoid error packet loops by dropping duplicate FORMERR responses. [RT #1006] 780. [bug] Error handling code dealing with out of memory or other rare errors could lead to assertion failures by calling functions on uninitialized names. [RT #1065] 779. [func] Added the "minimal-responses" option. 778. [bug] When starting cache cleaning, cleaning_timer_action() returned without first pausing the iterator, which could cause deadlock. [RT #998] 777. [bug] An empty forwarders list in a zone failed to override global forwarders. [RT #995] 776. [func] Improved error reporting in denied messages. [RT #252] 775. [placeholder] 774. [func] max-cache-size is implemented. 773. [func] Added isc_rwlock_trylock() to attempt to lock without blocking. 772. [bug] Owner names could be incorrectly omitted from cache dumps in the presence of negative caching entries. [RT #991] 771. [cleanup] TSIG errors related to unsynchronized clocks are logged better. [RT #919] 770. [func] Add the "edns yes_or_no" statement to the server clause. [RT #524] 769. [func] Improved error reporting when parsing rdata. [RT #740] 768. [bug] The server did not emit an SOA when a CNAME or DNAME chain ended in NXDOMAIN in an authoritative zone. 767. [placeholder] 766. [bug] A few cases in query_find() could leak fname. This would trigger the mpctx->allocated == 0 assertion when the server exited. [RT #739, #776, #798, #812, #818, #821, #845, #892, #935, #966] 765. [func] ACL names are once again case insensitive, like in BIND 8. [RT #252] 764. [func] Configuration files now allow "include" directives in more places, such as inside the "view" statement. [RT #377, #728, #860] 763. [func] Configuration files no longer have reserved words. [RT #731, #753] 762. [cleanup] The named.conf and rndc.conf file parsers have been completely rewritten. 761. [bug] _REENTRANT was still defined when building with --disable-threads. 760. [contrib] Significant enhancements to the pgsql sdb driver. 759. [bug] The resolver didn't turn off "avoid fetches" mode when restarting, possibly causing resolution to fail when it should not. This bug only affected platforms which support both IPv4 and IPv6. [RT #927] 758. [bug] The "avoid fetches" code did not treat negative cache entries correctly, causing fetches that would be useful to be avoided. This bug only affected platforms which support both IPv4 and IPv6. [RT #927] 757. [func] Log zone transfers. 756. [bug] dns_zone_load() could "return" success when no master file was configured. 755. [bug] Fix incorrectly formatted log messages in zone.c. 754. [bug] Certain failure conditions sending UDP packets could cause the server to retry the transmission indefinitely. [RT #902] 753. [bug] dig, host, and nslookup would fail to contact a remote server if getaddrinfo() returned an IPv6 address on a system that doesn't support IPv6. [RT #917] 752. [func] Correct bad tv_usec elements returned by gettimeofday(). 751. [func] Log successful zone loads / transfers. [RT #898] 750. [bug] A query should not match a DNAME whose trust level is pending. [RT #916] 749. [bug] When a query matched a DNAME in a secure zone, the server did not return the signature of the DNAME. [RT #915] 748. [doc] List supported RFCs in doc/misc/rfc-compliance. [RT #781] 747. [bug] The code to determine whether an IXFR was possible did not properly check for a database that could not have a journal. [RT #865, #908] 746. [bug] The sdb didn't clone rdatasets properly, causing a crash when the server followed delegations. [RT #905] 745. [func] Report the owner name of records that fail semantic checks while loading. 744. [bug] When returning DNS_R_CNAME or DNS_R_DNAME as the result of an ANY or SIG query, the resolver failed to setup the return event's rdatasets, causing an assertion failure in the query code. [RT #881] 743. [bug] Receiving a large number of certain malformed answers could cause named to stop responding. [RT #861] 742. [placeholder] 741. [port] Support openssl-engine. [RT #709] 740. [port] Handle openssl library mismatches slightly better. 739. [port] Look for /dev/random in configure, rather than assuming it will be there for only a predefined set of OSes. 738. [bug] If a non-threadsafe sdb driver supported AXFR and received an AXFR request, it would deadlock or die with an assertion failure. [RT #852] 737. [port] stdtime.c failed to compile on certain platforms. 736. [func] New functions isc_task_{begin,end}exclusive(). 735. [doc] Add BIND 4 migration notes. 734. [bug] An attempt to re-lock the zone lock could occur if the server was shutdown during a zone transfer. [RT #830] 733. [bug] Reference counts of dns_acl_t objects need to be locked but were not. [RT #801, #821] 732. [bug] Glue with 0 TTL could also cause SERVFAIL. [RT #828] 731. [bug] Certain zone errors could cause named-checkzone to fail ungracefully. [RT #819] 730. [bug] lwres_getaddrinfo() returns the correct result when it fails to contact a server. [RT #768] 729. [port] pthread_setconcurrency() needs to be called on Solaris. 728. [bug] Fix comment processing on master file directives. [RT #757] 727. [port] Work around OS bug where accept() succeeds but fails to fill in the peer address of the accepted connection, by treating it as an error rather than an assertion failure. [RT #809] 726. [func] Implement the "trace" and "notrace" commands in rndc. 725. [bug] Installing man pages could fail. 724. [func] New libisc functions isc_netaddr_any(), isc_netaddr_any6(). 723. [bug] Referrals whose NS RRs had a 0 TTL caused the resolver to return DNS_R_SERVFAIL. [RT #783] 722. [func] Allow incremental loads to be canceled. 721. [cleanup] Load manager and dns_master_loadfilequota() are no more. 720. [bug] Server could enter infinite loop in dispatch.c:do_cancel(). [RT #733] 719. [bug] Rapid reloads could trigger an assertion failure. [RT #743, #763] 718. [cleanup] "internal" is no longer a reserved word in named.conf. [RT #753, #731] 717. [bug] Certain TKEY processing failure modes could reference an uninitialized variable, causing the server to crash. [RT #750] 716. [bug] The first line of a $INCLUDE master file was lost if an origin was specified. [RT #744] 715. [bug] Resolving some A6 chains could cause an assertion failure in adb.c. [RT #738] 714. [bug] Preserve interval timers across reloads unless changed. [RT #729] 713. [func] named-checkconf takes '-t directory' similar to named. [RT #726] 712. [bug] Sending a large signed update message caused an assertion failure. [RT #718] 711. [bug] The libisc and liblwres implementations of inet_ntop contained an off by one error. 710. [func] The forwarders statement now takes an optional port. [RT #418] 709. [bug] ANY or SIG queries for data with a TTL of 0 would return SERVFAIL. [RT #620] 708. [bug] When building with --with-openssl, the openssl headers included with BIND 9 should not be used. [RT #702] 707. [func] The "filename" argument to named-checkzone is no longer optional, to reduce confusion. [RT #612] 706. [bug] Zones with an explicit "allow-update { none; };" were considered dynamic and therefore not reloaded on SIGHUP or "rndc reload". 705. [port] Work out resource limit type for use where rlim_t is not available. [RT #695] 704. [port] RLIMIT_NOFILE is not available on all platforms. [RT #695] 703. [port] sys/select.h is needed on older platforms. [RT #695] 702. [func] If the address 0.0.0.0 is seen in resolv.conf, use 127.0.0.1 instead. [RT #693] 701. [func] Root hints are now fully optional. Class IN views use compiled-in hints by default, as before. Non-IN views with no root hints now provide authoritative service but not recursion. A warning is logged if a view has neither root hints nor authoritative data for the root. [RT #696] 700. [bug] $GENERATE range check was wrong. [RT #688] 699. [bug] The lexer mishandled empty quoted strings. [RT #694] 698. [bug] Aborting nsupdate with ^C would lead to several race conditions. 697. [bug] nsupdate was not compatible with the undocumented BIND 8 behavior of ignoring TTLs in "update delete" commands. [RT #693] 696. [bug] lwresd would die with an assertion failure when passed a zero-length name. [RT #692] 695. [bug] If the resolver attempted to query a blackholed or bogus server, the resolution would fail immediately. 694. [bug] $GENERATE did not produce the last entry. [RT #682, #683] 693. [bug] An empty lwres statement in named.conf caused the server to crash while loading. 692. [bug] Deal with systems that have getaddrinfo() but not gai_strerror(). [RT #679] 691. [bug] Configuring per-view forwarders caused an assertion failure. [RT #675, #734] 690. [func] $GENERATE now supports DNAME. [RT #654] 689. [doc] man pages are now installed. [RT #210] 688. [func] "make tags" now works on systems with the "Exuberant Ctags" etags. 687. [bug] Only say we have IPv6, with sufficient functionality, if it has actually been tested. [RT #586] 686. [bug] dig and nslookup can now be properly aborted during blocking operations. [RT #568] 685. [bug] nslookup should use the search list/domain options from resolv.conf by default. [RT #405, #630] 684. [bug] Memory leak with view forwarders. [RT #656] 683. [bug] File descriptor leak in isc_lex_openfile(). 682. [bug] nslookup displayed SOA records incorrectly. [RT #665] 681. [bug] $GENERATE specifying output format was broken. [RT #653] 680. [bug] dns_rdata_fromstruct() mishandled options bigger than 255 octets. 679. [bug] $INCLUDE could leak memory and file descriptors on reload. [RT #639] 678. [bug] "transfer-format one-answer;" could trigger an assertion failure. [RT #646] 677. [bug] dnssec-signzone would occasionally use the wrong ttl for database operations and fail. [RT #643] 676. [bug] Log messages about lame servers to category 'lame-servers' rather than 'resolver', so as not to be gratuitously incompatible with BIND 8. 675. [bug] TKEY queries could cause the server to leak memory. 674. [func] Allow messages to be TSIG signed / verified using a offset from the current time. 673. [func] The server can now convert RFC1886-style recursive lookup requests into RFC2874-style lookups, when enabled using the new option "allow-v6-synthesis". 672. [bug] The wrong time was in the "time signed" field when replying with BADTIME error. 671. [bug] The message code was failing to parse a message with no question section and a TSIG record. [RT #628] 670. [bug] The lwres replacements for getaddrinfo and getipnodebyname didn't properly check for the existence of the sockaddr sa_len field. 669. [bug] dnssec-keygen now makes the public key file non-world-readable for symmetric keys. [RT #403] 668. [func] named-checkzone now reports multiple errors in master files. 667. [bug] On Linux, running named with the -u option and a non-world-readable configuration file didn't work. [RT #626] 666. [bug] If a request sent by dig is longer than 512 bytes, use TCP. 665. [bug] Signed responses were not sent when the size of the TSIG + question exceeded the maximum message size. [RT #628] 664. [bug] The t_tasks and t_timers module tests are now skipped when building without threads, since they require threads. 663. [func] Accept a size_spec, not just an integer, in the (unimplemented and ignored) max-ixfr-log-size option for compatibility with recent versions of BIND 8. [RT #613] 662. [bug] dns_rdata_fromtext() failed to log certain errors. 661. [bug] Certain UDP IXFR requests caused an assertion failure (mpctx->allocated == 0). [RT #355, #394, #623] 660. [port] Detect multiple CPUs on HP-UX and IRIX. 659. [performance] Rewrite the name compression code to be much faster. 658. [cleanup] Remove all vestiges of 16 bit global compression. 657. [bug] When a listen-on statement in an lwres block does not specify a port, use 921, not 53. Also update the listen-on documentation. [RT #616] 656. [func] Treat an unescaped newline in a quoted string as an error. This means that TXT records with missing close quotes should have meaningful errors printed. 655. [bug] Improve error reporting on unexpected eof when loading zones. [RT #611] 654. [bug] Origin was being forgotten in TCP retries in dig. [RT #574] 653. [bug] +defname option in dig was reversed in sense. [RT #549] 652. [bug] zone_saveunique() did not report the new name. 651. [func] The AD bit in responses now has the meaning specified in . 650. [bug] SIG(0) records were being generated and verified incorrectly. [RT #606] 649. [bug] It was possible to join to an already running fctx after it had "cloned" its events, but before it sent them. In this case, the event of the newly joined fetch would not contain the answer, and would trigger the INSIST() in fctx_sendevents(). In BIND 9.0, this bug did not trigger an INSIST(), but caused the fetch to fail with a SERVFAIL result. [RT #588, #597, #605, #607] 648. [port] Add support for pre-RFC2133 IPv6 implementations. 647. [bug] Resolver queries sent after following multiple referrals had excessively long retransmission timeouts due to incorrectly counting the referrals as "restarts". 646. [bug] The UnixWare ISC_PLATFORM_FIXIN6INADDR fix in isc/net.h didn't _cleanly_ fix the problem it was trying to fix. 645. [port] BSD/OS 3.0 needs pthread_init(). [RT #603] 644. [bug] #622 needed more work. [RT #562] 643. [bug] xfrin error messages made more verbose, added class of the zone. [RT #599] 642. [bug] Break the exit_check() race in the zone module. [RT #598] --- 9.1.0b2 released --- 641. [bug] $GENERATE caused a uninitialized link to be used. [RT #595] 640. [bug] Memory leak in error path could cause "mpctx->allocated == 0" failure. [RT #584] 639. [bug] Reading entropy from the keyboard would sometimes fail. [RT #591] 638. [port] lib/isc/random.c needed to explicitly include time.h to get a prototype for time() when pthreads was not being used. [RT #592] 637. [port] Use isc_u?int64_t instead of (unsigned) long long in lib/isc/print.c. Also allow lib/isc/print.c to be compiled even if the platform does not need it. [RT #592] 636. [port] Shut up MSVC++ about a possible loss of precision in the ISC__BUFFER_PUTUINT*() macros. [RT #592] 635. [bug] Reloading a server with a configured blackhole list would cause an assertion. [RT #590] 634. [bug] A log file will completely stop being written when it reaches the maximum size in all cases, not just when versioning is also enabled. [RT #570] 633. [port] Cope with rlim_t missing on BSD/OS systems. [RT #575] 632. [bug] The index array of the journal file was corrupted as it was written to disk. 631. [port] Build without thread support on systems without pthreads. 630. [bug] Locking failure in zone code. [RT #582] 629. [bug] 9.1.0b1 dereferenced a null pointer and crashed when responding to a UDP IXFR request. 628. [bug] If the root hints contained only AAAA addresses, named would be unable to perform resolution. 627. [bug] The EDNS0 blackhole detection code of change 324 waited for three retransmissions to each server, which takes much too long when a domain has many name servers and all of them drop EDNS0 queries. Now we retry without EDNS0 after three consecutive timeouts, even if they are all from different servers. [RT #143] 626. [bug] The lightweight resolver daemon no longer crashes when asked for a SIG rrset. [RT #558] 625. [func] Zones now inherit their class from the enclosing view. 624. [bug] The zone object could get timer events after it had been destroyed, causing a server crash. [RT #571] 623. [func] Added "named-checkconf" and "named-checkzone" program for syntax checking named.conf files and zone files, respectively. 622. [bug] A canceled request could be destroyed before dns_request_destroy() was called. [RT #562] 621. [port] Disable IPv6 at runtime if IPv6 sockets are unusable. This mostly affects Red Hat Linux 7.0, which has conflicts between libc and the kernel. 620. [bug] dns_master_load*inc() now require 'task' and 'load' to be non-null. Also 'done' will not be called if dns_master_load*inc() fails immediately. [RT #565] 619. [placeholder] 618. [bug] Queries to a signed zone could sometimes cause an assertion failure. 617. [bug] When using dynamic update to add a new RR to an existing RRset with a different TTL, the journal entries generated from the update did not include explicit deletions and re-additions of the existing RRs to update their TTL to the new value. 616. [func] dnssec-signzone -t output now includes performance statistics. 615. [bug] dnssec-signzone did not like child keysets signed by multiple keys. 614. [bug] Checks for uninitialized link fields were prone to false positives, causing assertion failures. The checks are now disabled by default and may be re-enabled by defining ISC_LIST_CHECKINIT. 613. [bug] "rndc reload zone" now reloads primary zones. It previously only updated slave and stub zones, if an SOA query indicated an out of date serial. 612. [cleanup] Shutup a ridiculously noisy HP-UX compiler that complains relentlessly about how its treatment of 'const' has changed as well as how casting sometimes tightens alignment constraints. 611. [func] allow-notify can be used to permit processing of notify messages from hosts other than a slave's masters. 610. [func] rndc dumpdb is now supported. 609. [bug] getrrsetbyname() would crash lwresd if the server found more SIGs than answers. [RT #554] 608. [func] dnssec-signzone now adds a comment to the zone with the time the file was signed. 607. [bug] nsupdate would fail if it encountered a CNAME or DNAME in a response to an SOA query. [RT #515] 606. [bug] Compiling with --disable-threads failed due to isc_thread_self() being incorrectly defined as an integer rather than a function. 605. [func] New function isc_lex_getlasttokentext(). 604. [bug] The named.conf parser could print incorrect line numbers when long comments were present. 603. [bug] Make dig handle multiple types or classes on the same query more correctly. 602. [func] Cope automatically with UnixWare's broken IN6_IS_ADDR_* macros. [RT #539] 601. [func] Return a non-zero exit code if an update fails in nsupdate. 600. [bug] Reverse lookups sometimes failed in dig, etc... 599. [func] Added four new functions to the libisc log API to support i18n messages. isc_log_iwrite(), isc_log_ivwrite(), isc_log_iwrite1() and isc_log_ivwrite1() were added. 598. [bug] An update-policy statement would cause the server to assert while loading. [RT #536] 597. [func] dnssec-signzone is now multi-threaded. 596. [bug] DNS_RDATASLAB_FORCE and DNS_RDATASLAB_EXACT are not mutually exclusive. 595. [port] On Linux 2.2, socket() returns EINVAL when it should return EAFNOSUPPORT. Work around this. [RT #531] 594. [func] sdb drivers are now assumed to not be thread-safe unless the DNS_SDBFLAG_THREADSAFE flag is supplied. 593. [bug] If a secure zone was missing all its NXTs and a dynamic update was attempted, the server entered an infinite loop. 592. [bug] The sig-validity-interval option now specifies a number of days, not seconds. This matches the documentation. [RT #529] --- 9.1.0b1 released --- 591. [bug] Work around non-reentrancy in openssl by disabling pre-computation in keys. 590. [doc] There are now man pages for the lwres library in doc/man/lwres. 589. [bug] The server could deadlock if a zone was updated while being transferred out. 588. [bug] ctx->in_use was not being correctly initialized when when pushing a file for $INCLUDE. [RT #523] 587. [func] A warning is now printed if the "allow-update" option allows updates based on the source IP address, to alert users to the fact that this is insecure and becoming increasingly so as servers capable of update forwarding are being deployed. 586. [bug] multiple views with the same name were fatal. [RT #516] 585. [func] dns_db_addrdataset() and dns_rdataslab_merge() now support 'exact' additions in a similar manner to dns_db_subtractrdataset() and dns_rdataslab_subtract(). 584. [func] You can now say 'notify explicit'; to suppress notification of the servers listed in NS records and notify only those servers listed in the 'also-notify' option. 583. [func] "rndc querylog" will now toggle logging of queries, like "ndc querylog" in BIND 8. 582. [bug] dns_zone_idetach() failed to lock the zone. [RT #199, #463] 581. [bug] log severity was not being correctly processed. [RT #485] 580. [func] Ignore trailing garbage on incoming DNS packets, for interoperability with broken server implementations. [RT #491] 579. [bug] nsupdate did not take a filename to read update from. [RT #492] 578. [func] New config option "notify-source", to specify the source address for notify messages. 577. [func] Log illegal RDATA combinations. e.g. multiple singleton types, cname and other data. 576. [doc] isc_log_create() description did not match reality. 575. [bug] isc_log_create() was not setting internal state correctly to reflect the default channels created. 574. [bug] TSIG signed queries sent by the resolver would fail to have their responses validated and would leak memory. 573. [bug] The journal files of IXFRed slave zones were inadvertently discarded on server reload, causing "journal out of sync with zone" errors on subsequent reloads. [RT #482] 572. [bug] Quoted strings were not accepted as key names in address match lists. 571. [bug] It was possible to create an rdataset of singleton type which had more than one rdata. [RT #154] [RT #279] 570. [bug] rbtdb.c allowed zones containing nodes which had both a CNAME and "other data". [RT #154] 569. [func] The DNSSEC AD bit will not be set on queries which have not requested a DNSSEC response. 568. [func] Add sample simple database drivers in contrib/sdb. 567. [bug] Setting the zone transfer timeout to zero caused an assertion failure. [RT #302] 566. [func] New public function dns_timer_setidle(). 565. [func] Log queries more like BIND 8: query logging is now done to category "queries", level "info". [RT #169] 564. [func] Add sortlist support to lwresd. 563. [func] New public functions dns_rdatatype_format() and dns_rdataclass_format(), for convenient formatting of rdata type/class mnemonics in log messages. 562. [cleanup] Moved lib/dns/*conf.c to bin/named where they belong. 561. [func] The 'datasize', 'stacksize', 'coresize' and 'files' clauses of the options{} statement are now implemented. 560. [bug] dns_name_split did not properly the resulting prefix when a maximal length bitstring label was split which was preceded by another bitstring label. [RT #429] 559. [bug] dns_name_split did not properly create the suffix when splitting within a maximal length bitstring label. 558. [func] New functions, isc_resource_getlimit and isc_resource_setlimit. 557. [func] Symbolic constants for libisc integral types. 556. [func] The DNSSEC OK bit in the EDNS extended flags is now implemented. Responses to queries without this bit set will not contain any DNSSEC records. 555. [bug] A slave server attempting a zone transfer could crash with an assertion failure on certain malformed responses from the master. [RT #457] 554. [bug] In some cases, not all of the dnssec tools were properly installed. 553. [bug] Incoming zone transfers deferred due to quota were not started when quota was increased but only when a transfer in progress finished. [RT #456] 552. [bug] We were not correctly detecting the end of all c-style comments. [RT #455] 551. [func] Implemented the 'sortlist' option. 550. [func] Support unknown rdata types and classes. 549. [bug] "make" did not immediately abort the build when a subdirectory make failed [RT #450]. 548. [func] The lexer now ungets tokens more correctly. 547. [placeholder] 546. [func] Option 'lame-ttl' is now implemented. 545. [func] Name limit and counting options removed from dig; they didn't work properly, and cannot be correctly implemented without significant changes. 544. [func] Add statistics option, enable statistics-file option, add RNDC option "dump-statistics" to write out a query statistics file. 543. [doc] The 'port' option is now documented. 542. [func] Add support for update forwarding as required for full compliance with RFC2136. It is turned off by default and can be enabled using the 'allow-update-forwarding' option. 541. [func] Add bogus server support. 540. [func] Add dialup support. 539. [func] Support the blackhole option. 538. [bug] fix buffer overruns by 1 in lwres_getnameinfo(). 537. [placeholder] 536. [func] Use transfer-source{-v6} when sending refresh queries. Transfer-source{-v6} now take a optional port parameter for setting the UDP source port. The port parameter is ignored for TCP. 535. [func] Use transfer-source{-v6} when forwarding update requests. 534. [func] Ancestors have been removed from RBT chains. Ancestor information can be discerned via node parent pointers. 533. [func] Incorporated name hashing into the RBT database to improve search speed. 532. [func] Implement DNS UPDATE pseudo records using DNS_RDATA_UPDATE flag. 531. [func] Rdata really should be initialized before being assigned to (dns_rdata_fromwire(), dns_rdata_fromtext(), dns_rdata_clone(), dns_rdata_fromregion()), check that it is. 530. [func] New function dns_rdata_invalidate(). 529. [bug] 521 contained a bug which caused zones to always reload. [RT #410] 528. [func] The ISC_LIST_XXXX macros now perform sanity checks on their arguments. ISC_LIST_XXXXUNSAFE can be use to skip the checks however use with caution. 527. [func] New function dns_rdata_clone(). 526. [bug] nsupdate incorrectly refused to add RRs with a TTL of 0. 525. [func] New arguments 'options' for dns_db_subtractrdataset(), and 'flags' for dns_rdataslab_subtract() allowing you to request that the RR's must exist prior to deletion. DNS_R_NOTEXACT is returned if the condition is not met. 524. [func] The 'forward' and 'forwarders' statement in non-forward zones should work now. 523. [doc] The source to the Administrator Reference Manual is now an XML file using the DocBook DTD, and is included in the distribution. The plain text version of the ARM is temporarily unavailable while we figure out how to generate readable plain text from the XML. 522. [func] The lightweight resolver daemon can now use a real configuration file, and its functionality can be provided by a name server. Also, the -p and -P options to lwresd have been reversed. 521. [bug] Detect master files which contain $INCLUDE and always reload. [RT #196] 520. [bug] Upgraded libtool to 1.3.5, which makes shared library builds almost work on AIX (and possibly others). 519. [bug] dns_name_split() would improperly split some bitstring labels, zeroing a few of the least significant bits in the prefix part. When such an improperly created prefix was returned to the RBT database, the bogus label was dutifully stored, corrupting the tree. [RT #369] 518. [bug] The resolver did not realize that a DNAME which was "the answer" to the client's query was "the answer", and such queries would fail. [RT #399] 517. [bug] The resolver's DNAME code would trigger an assertion if there was more than one DNAME in the chain. [RT #399] 516. [bug] Cache lookups which had a NULL node pointer, e.g. those by dns_view_find(), and which would match a DNAME, would trigger an INSIST(!search.need_cleanup) assertion. [RT #399] 515. [bug] The ssu table was not being attached / detached by dns_zone_[sg]etssutable. [RT #397] 514. [func] Retry refresh and notify queries if they timeout. [RT #388] 513. [func] New functionality added to rdnc and server to allow individual zones to be refreshed or reloaded. 512. [bug] The zone transfer code could throw an exception with an invalid IXFR stream. 511. [bug] The message code could throw an assertion on an out of memory failure. [RT #392] 510. [bug] Remove spurious view notify warning. [RT #376] 509. [func] Add support for write of zone files on shutdown. 508. [func] dns_message_parse() can now do a best-effort attempt, which should allow dig to print more invalid messages. 507. [func] New functions dns_zone_flush(), dns_zt_flushanddetach() and dns_view_flushanddetach(). 506. [func] Do not fail to start on errors in zone files. 505. [bug] nsupdate was printing "unknown result code". [RT #373] 504. [bug] The zone was not being marked as dirty when updated via IXFR. 503. [bug] dumptime was not being set along with DNS_ZONEFLG_NEEDDUMP. 502. [func] On a SERVFAIL reply, DiG will now try the next server in the list, unless the +fail option is specified. 501. [bug] Incorrect port numbers were being displayed by nslookup. [RT #352] 500. [func] Nearly useless +details option removed from DiG. 499. [func] In DiG, specifying a class with -c or type with -t changes command-line parsing so that classes and types are only recognized if following -c or -t. This allows hosts with the same name as a class or type to be looked up. 498. [doc] There is now a man page for "dig" in doc/man/bin/dig.1. 497. [bug] The error messages printed when an IP match list contained a network address with a nonzero host part where not sufficiently detailed. [RT #365] 496. [bug] named didn't sanity check numeric parameters. [RT #361] 495. [bug] nsupdate was unable to handle large records. [RT #368] 494. [func] Do not cache NXDOMAIN responses for SOA queries. 493. [func] Return non-cachable (ttl = 0) NXDOMAIN responses for SOA queries. This makes it easier to locate the containing zone without polluting intermediate caches. 492. [bug] attempting to reload a zone caused the server fail to shutdown cleanly. [RT #360] 491. [bug] nsupdate would segfault when sending certain prerequisites with empty RDATA. [RT #356] 490. [func] When a slave/stub zone has not yet successfully obtained an SOA containing the zone's configured retry time, perform the SOA query retries using exponential backoff. [RT #337] 489. [func] The zone manager now has a "i/o" queue. 488. [bug] Locks weren't properly destroyed in some cases. 487. [port] flockfile() is not defined on all systems. 486. [bug] nslookup: "set all" and "server" commands showed the incorrect port number if a port other than 53 was specified. [RT #352] 485. [func] When dig had more than one server to query, it would send all of the messages at the same time. Add rate limiting of the transmitted messages. 484. [bug] When the server was reloaded after removing addresses from the named.conf "listen-on" statement, sockets were still listening on the removed addresses due to reference count loops. [RT #325] 483. [bug] nslookup: "set all" showed a "search" option but it was not settable. 482. [bug] nslookup: a plain "server" or "lserver" should be treated as a lookup. 481. [bug] nslookup:get_next_command() stack size could exceed per thread limit. 480. [bug] strtok() is not thread safe. [RT #349] 479. [func] The test suite can now be run by typing "make check" or "make test" at the top level. 478. [bug] "make install" failed if the directory specified with --prefix did not already exist. 477. [bug] The the isc-config.sh script could be installed before its directory was created. [RT #324] 476. [bug] A zone could expire while a zone transfer was in progress triggering a INSIST failure. [RT #329] 475. [bug] query_getzonedb() sometimes returned a non-null version on failure. This caused assertion failures when generating query responses where names subject to additional section processing pointed to a zone to which access had been denied by means of the allow-query option. [RT #336] 474. [bug] The mnemonic of the CHAOS class is CH according to RFC1035, but it was printed and read only as CHAOS. We now accept both forms as input, and print it as CH. [RT #305] 473. [bug] nsupdate overran the end of the list of name servers when no servers could be reached, typically causing it to print the error message "dns_request_create: not implemented". 472. [bug] Off-by-one error caused isc_time_add() to sometimes produce invalid time values. 471. [bug] nsupdate didn't compile on HP/UX 10.20 470. [func] $GENERATE is now supported. See also doc/misc/migration. 469. [bug] "query-source address * port 53;" now works. 468. [bug] dns_master_load*() failed to report file and line number in certain error conditions. 467. [bug] dns_master_load*() failed to log an error if pushfile() failed. 466. [bug] dns_master_load*() could return success when it failed. 465. [cleanup] Allow 0 to be set as an omapi_value_t value by omapi_value_storeint(). 464. [cleanup] Build with openssl's RSA code instead of dnssafe. 463. [bug] nsupdate sent malformed SOA queries to the second and subsequent name servers in resolv.conf if the query sent to the first one failed. 462. [bug] --disable-ipv6 should work now. 461. [bug] Specifying an unknown key in the "keys" clause of the "controls" statement caused a NULL pointer dereference. [RT #316] 460. [bug] Much of the DNSSEC code only worked with class IN. 459. [bug] Nslookup processed the "set" command incorrectly. 458. [bug] Nslookup didn't properly check class and type values. [RT #305] 457. [bug] Dig/host/hslookup didn't properly handle connect timeouts in certain situations, causing an unnecessary warning message to be printed. 456. [bug] Stub zones were not resetting the refresh and expire counters, loadtime or clearing the DNS_ZONE_REFRESH (refresh in progress) flag upon successful update. This disabled further refreshing of the stub zone, causing it to eventually expire. [RT #300] 455. [doc] Document IPv4 prefix notation does not require a dotted decimal quad but may be just dotted decimal. 454. [bug] Enforce dotted decimal and dotted decimal quad where documented as such in named.conf. [RT #304, RT #311] 453. [bug] Warn if the obsolete option "maintain-ixfr-base" is specified in named.conf. [RT #306] 452. [bug] Warn if the unimplemented option "statistics-file" is specified in named.conf. [RT #301] 451. [func] Update forwarding implemented. 450. [func] New function ns_client_sendraw(). 449. [bug] isc_bitstring_copy() only works correctly if the two bitstrings have the same lsb0 value, but this requirement was not documented, nor was there a REQUIRE for it. 448. [bug] Host output formatting change, to match v8. [RT #255] 447. [bug] Dig didn't properly retry in TCP mode after a truncated reply. [RT #277] 446. [bug] Confusing notify log message. [RT #298] 445. [bug] Doing a 0 bit isc_bitstring_copy() of an lsb0 bitstring triggered a REQUIRE statement. The REQUIRE statement was incorrect. [RT #297] 444. [func] "recursion denied" messages are always logged at debug level 1, now, rather than sometimes at ERROR. This silences these warnings in the usual case, where some clients set the RD bit in all queries. 443. [bug] When loading a master file failed because of an unrecognized RR type name, the error message did not include the file name and line number. [RT #285] 442. [bug] TSIG signed messages that did not match any view crashed the server. [RT #290] 441. [bug] Nodes obscured by a DNAME were inaccessible even when DNS_DBFIND_GLUEOK was set. 440. [func] New function dns_zone_forwardupdate(). 439. [func] New function dns_request_createraw(). 438. [func] New function dns_message_getrawmessage(). 437. [func] Log NOTIFY activity to the notify channel. 436. [bug] If recvmsg() returned EHOSTUNREACH or ENETUNREACH, which sometimes happens on Linux, named would enter a busy loop. Also, unexpected socket errors were not logged at a high enough logging level to be useful in diagnosing this situation. [RT #275] 435. [bug] dns_zone_dump() overwrote existing zone files rather than writing to a temporary file and renaming. This could lead to empty or partial zone files being left around in certain error conditions involving the initial transfer of a slave zone, interfering with subsequent server startup. [RT #282] 434. [func] New function isc_file_isabsolute(). 433. [func] isc_base64_decodestring() now accepts newlines within the base64 data. This makes it possible to break up the key data in a "trusted-keys" statement into multiple lines. [RT #284] 432. [func] Added refresh/retry jitter. The actual refresh/ retry time is now a random value between 75% and 100% of the configured value. 431. [func] Log at ISC_LOG_INFO when a zone is successfully loaded. 430. [bug] Rewrote the lightweight resolver client management code to handle shutdown correctly and general cleanup. 429. [bug] The space reserved for a TSIG record in a response was 2 bytes too short, leading to message generation failures. 428. [bug] rbtdb.c:find_closest_nxt() erroneously returned DNS_R_BADDB for nodes which had neither NXT nor SIG NXT (e.g. glue). This could cause SERVFAILs when generating negative responses in a secure zone. 427. [bug] Avoid going into an infinite loop when the validator gets a negative response to a key query where the records are signed by the missing key. 426. [bug] Attempting to generate an oversized RSA key could cause dnssec-keygen to dump core. 425. [bug] Warn about the auth-nxdomain default value change if there is no auth-nxdomain statement in the config file. [RT #287] 424. [bug] notify_createmessage() could trigger an assertion failure when creating the notify message failed, e.g. due to corrupt zones with multiple SOA records. [RT #279] 423. [bug] When responding to a recursive query, errors that occur after following a CNAME should cause the query to fail. [RT #274] 422. [func] get rid of isc_random_t, and make isc_random_get() and isc_random_jitter() use rand() internally instead of local state. Note that isc_random_*() functions are only for weak, non-critical "randomness" such as timing jitter and such. 421. [bug] nslookup would exit when given a blank line as input. 420. [bug] nslookup failed to implement the "exit" command. 419. [bug] The certificate type PKIX was misspelled as SKIX. 418. [bug] At debug levels >= 10, getting an unexpected socket receive error would crash the server while trying to log the error message. 417. [func] Add isc_app_block() and isc_app_unblock(), which allow an application to handle signals while blocking. 416. [bug] Slave zones with no master file tried to use a NULL pointer for a journal file name when they received an IXFR. [RT #273] 415. [bug] The logging code leaked file descriptors. 414. [bug] Server did not shut down until all incoming zone transfers were finished. 413. [bug] Notify could attempt to use the zone database after it had been unloaded. [RT #267] 412. [bug] named -v didn't print the version. 411. [bug] A typo in the HS A code caused an assertion failure. 410. [bug] lwres_gethostbyname() and company set lwres_h_errno to a random value on success. 409. [bug] If named was shut down early in the startup process, ns_omapi_shutdown() would attempt to lock an uninitialized mutex. [RT #262] 408. [bug] stub zones could leak memory and reference counts if all the masters were unreachable. 407. [bug] isc_rwlock_lock() would needlessly block readers when it reached the read quota even if no writers were waiting. 406. [bug] Log messages were occasionally lost or corrupted due to a race condition in isc_log_doit(). 405. [func] Add support for selective forwarding (forward zones) 404. [bug] The request library didn't completely work with IPv6. 403. [bug] "host" did not use the search list. 402. [bug] Treat undefined acls as errors, rather than warning and then later throwing an assertion. [RT #252] 401. [func] Added simple database API. 400. [bug] SIG(0) signing and verifying was done incorrectly. [RT #249] 399. [bug] When reloading the server with a config file containing a syntax error, it could catch an assertion failure trying to perform zone maintenance on, or sending notifies from, tentatively created zones whose views were never fully configured and lacked an address database and request manager. 398. [bug] "dig" sometimes caught an assertion failure when using TSIG, depending on the key length. 397. [func] Added utility functions dns_view_gettsig() and dns_view_getpeertsig(). 396. [doc] There is now a man page for "nsupdate" in doc/man/bin/nsupdate.8. 395. [bug] nslookup printed incorrect RR type mnemonics for RRs of type >= 21 [RT #237]. 394. [bug] Current name was not propagated via $INCLUDE. 393. [func] Initial answer while loading (awl) support. Entry points: dns_master_loadfileinc(), dns_master_loadstreaminc(), dns_master_loadbufferinc(). Note: calls to dns_master_load*inc() should be rate be rate limited so as to not use up all file descriptors. 392. [func] Add ISC_R_FAMILYNOSUPPORT. Returned when OS does not support the given address family requested. 391. [clarity] ISC_R_FAMILY -> ISC_R_FAMILYMISMATCH. 390. [func] The function dns_zone_setdbtype() now takes an argc/argv style vector of words and sets both the zone database type and its arguments, making the functions dns_zone_adddbarg() and dns_zone_cleardbargs() unnecessary. 389. [bug] Attempting to send a request over IPv6 using dns_request_create() on a system without IPv6 support caused an assertion failure [RT #235]. 388. [func] dig and host can now do reverse ipv6 lookups. 387. [func] Add dns_byaddr_createptrname(), which converts an address into the name used by a PTR query. 386. [bug] Missing strdup() of ACL name caused random ACL matching failures [RT #228]. 385. [cleanup] Removed functions dns_zone_equal(), dns_zone_print(), and dns_zt_print(). 384. [bug] nsupdate was incorrectly limiting TTLs to 65535 instead of 2147483647. 383. [func] When writing a master file, print the SOA and NS records (and their SIGs) before other records. 382. [bug] named -u failed on many Linux systems where the libc provided kernel headers do not match the current kernel. 381. [bug] Check for IPV6_RECVPKTINFO and use it instead of IPV6_PKTINFO if found. [RT #229] 380. [bug] nsupdate didn't work with IPv6. 379. [func] New library function isc_sockaddr_anyofpf(). 378. [func] named and lwresd will log the command line arguments they were started with in the "starting ..." message. 377. [bug] When additional data lookups were refused due to "allow-query", the databases were still being attached causing reference leaks. 376. [bug] The server should always use good entropy when performing cryptographic functions needing entropy. 375. [bug] Per-zone "allow-query" did not properly override the view/global one for CNAME targets and additional data [RT #220]. 374. [bug] SOA in authoritative negative responses had wrong TTL. 373. [func] nslookup is now installed by "make install". 372. [bug] Deal with Microsoft DNS servers appending two bytes of garbage to zone transfer requests. 371. [bug] At high debug levels, doing an outgoing zone transfer of a very large RRset could cause an assertion failure during logging. 370. [bug] The error messages for roll-forward failures were overly terse. 369. [func] Support new named.conf options, view and zone statements: max-retry-time, min-retry-time, max-refresh-time, min-refresh-time. 368. [func] Restructure the internal ".bind" view so that more zones can be added to it. 367. [bug] Allow proper selection of server on nslookup command line. 366. [func] Allow use of '-' batch file in dig for stdin. 365. [bug] nsupdate -k leaked memory. 364. [func] Added additional-from-{cache,auth} 363. [placeholder] 362. [bug] rndc no longer aborts if the configuration file is missing an options statement. [RT #209] 361. [func] When the RBT find or chain functions set the name and origin for a node that stores the root label the name is now set to an empty name, instead of ".", to simplify later use of the name and origin by dns_name_concatenate(), dns_name_totext() or dns_name_format(). 360. [func] dns_name_totext() and dns_name_format() now allow an empty name to be passed, which is formatted as "@". 359. [bug] dnssec-signzone occasionally signed glue records. 358. [cleanup] Rename the intermediate files used by the dnssec programs. 357. [bug] The zone file parser crashed if the argument to $INCLUDE was a quoted string. 356. [cleanup] isc_task_send no longer requires event->sender to be non-null. 355. [func] Added isc_dir_createunique(), similar to mkdtemp(). 354. [doc] Man pages for the dnssec tools are now included in the distribution, in doc/man/dnssec. 353. [bug] double increment in lwres/gethost.c:copytobuf(). [RT #187] 352. [bug] Race condition in dns_client_t startup could cause an assertion failure. 351. [bug] Constructing a response with rcode SERVFAIL to a TSIG signed query could crash the server. 350. [bug] Also-notify lists specified in the global options block were not correctly reference counted, causing a memory leak. 349. [bug] Processing a query with the CD bit set now works as expected. 348. [func] New boolean named.conf options 'additional-from-auth' and 'additional-from-cache' now supported in view and global options statement. 347. [bug] Don't crash if an argument is left off options in dig. 346. [placeholder] 345. [bug] Large-scale changes/cleanups to dig: * Significantly improve structure handling * Don't pre-load entire batch files * Add name/rr counting/limiting * Fix SIGINT handling * Shorten timeouts to match v8's behavior 344. [bug] When shutting down, lwresd sometimes tried to shut down its client tasks twice, triggering an assertion. 343. [bug] Although zone maintenance SOA queries and notify requests were signed with TSIG keys when configured for the server in case, the TSIG was not verified on the response. 342. [bug] The wrong name was being passed to dns_name_dup() when generating a TSIG key using TKEY. 341. [func] Support 'key' clause in named.conf zone masters statement to allow authentication via TSIG keys: masters { 10.0.0.1 port 5353 key "foo"; 10.0.0.2 ; }; 340. [bug] The top-level COPYRIGHT file was missing from the distribution. 339. [bug] DNSSEC validation of the response to an ANY query at a name with a CNAME RR in a secure zone triggered an assertion failure. 338. [bug] lwresd logged to syslog as named, not lwresd. 337. [bug] "dig" did not recognize "nsap-ptr" as an RR type on the command line. 336. [bug] "dig -f" used 64 k of memory for each line in the file. It now uses much less, though still proportionally to the file size. 335. [bug] named would occasionally attempt recursion when it was disallowed or undesired. 334. [func] Added hmac-md5 to libisc. 333. [bug] The resolver incorrectly accepted referrals to domains that were not parents of the query name, causing assertion failures. 332. [func] New function dns_name_reset(). 331. [bug] Only log "recursion denied" if RD is set. [RT #178] 330. [bug] Many debugging messages were partially formatted even when debugging was turned off, causing a significant decrease in query performance. 329. [func] omapi_auth_register() now takes a size_t argument for the length of a key's secret data. Previously OMAPI only stored secrets up to the first NUL byte. 328. [func] Added isc_base64_decodestring(). 327. [bug] rndc.conf parser wasn't correctly recognizing an IP address where a host specification was required. 326. [func] 'keys' in an 'inet' control statement is now required and must have at least one item in it. A "not supported" warning is now issued if a 'unix' control channel is defined. 325. [bug] isc_lex_gettoken was processing octal strings when ISC_LEXOPT_CNUMBER was not set. 324. [func] In the resolver, turn EDNS0 off if there is no response after a number of retransmissions. This is to allow queries some chance of succeeding even if all the authoritative servers of a zone silently discard EDNS0 requests instead of sending an error response like they ought to. 323. [bug] dns_rbt_findname() did not ignore empty rbt nodes. Because of this, servers authoritative for a parent and grandchild zone but not authoritative for the intervening child zone did not correctly issue referrals to the servers of the child zone. 322. [bug] Queries for KEY RRs are now sent to the parent server before the authoritative one, making DNSSEC insecurity proofs work in many cases where they previously didn't. 321. [bug] When synthesizing a CNAME RR for a DNAME response, query_addcname() failed to initialize the type and class of the CNAME dns_rdata_t, causing random failures. 320. [func] Multiple rndc changes: parses an rndc.conf file, uses authentication to talk to named, command line syntax changed. This will all be described in the ARM. 319. [func] The named.conf "controls" statement is now used to configure the OMAPI command channel. 318. [func] dns_c_ndcctx_destroy() could never return anything except ISC_R_SUCCESS; made it have void return instead. 317. [func] Use callbacks from libomapi to determine if a new connection is valid, and if a key requested to be used with that connection is valid. 316. [bug] Generate a warning if we detect an unexpected but treat as . 315. [bug] Handle non-empty blanks lines. [RT #163] 314. [func] The named.conf controls statement can now have more than one key specified for the inet clause. 313. [bug] When parsing resolv.conf, don't terminate on an error. Instead, parse as much as possible, but still return an error if one was found. 312. [bug] Increase the number of allowed elements in the resolv.conf search path from 6 to 8. If there are more than this, ignore the remainder rather than returning a failure in lwres_conf_parse. 311. [bug] lwres_conf_parse failed when the first line of resolv.conf was empty or a comment. 310. [func] Changes to named.conf "controls" statement (inet subtype only) - support "keys" clause controls { inet * port 1024 allow { any; } keys { "foo"; } } - allow "port xxx" to be left out of statement, in which case it defaults to omapi's default port of 953. 309. [bug] When sending a referral, the server did not look for name server addresses as glue in the zone holding the NS RRset in the case where this zone was not the same as the one where it looked for name server addresses as authoritative data. 308. [bug] Treat a SOA record not at top of zone as an error when loading a zone. [RT #154] 307. [bug] When canceling a query, the resolver didn't check for isc_socket_sendto() calls that did not yet have their completion events posted, so it could (rarely) end up destroying the query context and then want to use it again when the send event posted, triggering an assertion as it tried to cancel an already-canceled query. [RT #77] 306. [bug] Reading HMAC-MD5 private key files didn't work. 305. [bug] When reloading the server with a config file containing a syntax error, it could catch an assertion failure trying to perform zone maintenance on tentatively created zones whose views were never fully configured and lacked an address database. 304. [bug] If more than LWRES_CONFMAXNAMESERVERS servers are listed in resolv.conf, silently ignore them instead of returning failure. 303. [bug] Add additional sanity checks to differentiate a AXFR response vs a IXFR response. [RT #157] 302. [bug] In dig, host, and nslookup, MXNAME should be large enough to hold any legal domain name in presentation format + terminating NULL. 301. [bug] Uninitialized pointer in host:printmessage(). [RT #159] 300. [bug] Using both and didn't work on platforms lacking IPv6 because each included their own ipv6 header file for the missing definitions. Now each library's ipv6.h defines the wrapper symbol of the other (ISC_IPV6_H and LWRES_IPV6_H). 299. [cleanup] Get the user and group information before changing the root directory, so the administrator does not need to keep a copy of the user and group databases in the chroot'ed environment. Suggested by Hakan Olsson. 298. [bug] A mutex deadlock occurred during shutdown of the interface manager under certain conditions. Digital Unix systems were the most affected. 297. [bug] Specifying a key name that wasn't fully qualified in certain parts of the config file could cause an assertion failure. 296. [bug] "make install" from a separate build directory failed unless configure had been run in the source directory, too. 295. [bug] When invoked with type==CNAME and a message not constructed by dns_message_parse(), dns_message_findname() failed to find anything due to checking for attribute bits that are set only in dns_message_parse(). This caused an infinite loop when constructing the response to an ANY query at a CNAME in a secure zone. 294. [bug] If we run out of space in while processing glue when reading a master file and commit "current name" reverts to "name_current" instead of staying as "name_glue". 293. [port] Add support for FreeBSD 4.0 system tests. 292. [bug] Due to problems with the way some operating systems handle simultaneous listening on IPv4 and IPv6 addresses, the server no longer listens on IPv6 addresses by default. To revert to the previous behavior, specify "listen-on-v6 { any; };" in the config file. 291. [func] Caching servers no longer send outgoing queries over TCP just because the incoming recursive query was a TCP one. 290. [cleanup] +twiddle option to dig (for testing only) removed. 289. [cleanup] dig is now installed in $bindir instead of $sbindir. host is now installed in $bindir. (Be sure to remove any $sbindir/dig from a previous release.) 288. [func] rndc is now installed by "make install" into $sbindir. 287. [bug] rndc now works again as "rndc 127.1 reload" (for only that task). Parsing its configuration file and using digital signatures for authentication has been disabled until named supports the "controls" statement, post-9.0.0. 286. [bug] On Solaris 2, when named inherited a signal state where SIGHUP had the SIG_IGN action, SIGHUP would be ignored rather than causing the server to reload its configuration. 285. [bug] A change made to the dst API for beta4 inadvertently broke OMAPI's creation of a dst key from an incoming message, causing an assertion to be triggered. Fixed. 284. [func] The DNSSEC key generation and signing tools now generate randomness from keyboard input on systems that lack /dev/random. 283. [cleanup] The 'lwresd' program is now a link to 'named'. 282. [bug] The lexer now returns ISC_R_RANGE if parsed integer is too big for an unsigned long. 281. [bug] Fixed list of recognized config file category names. 280. [func] Add isc-config.sh, which can be used to more easily build applications that link with our libraries. 279. [bug] Private omapi function symbols shared between two or more files in libomapi.a were not namespace protected using the ISC convention of starting with the library name and two underscores ("omapi__"...) 278. [bug] bin/named/logconf.c:category_fromconf() didn't take note of when isc_log_categorybyname() wasn't able to find the category name and would then apply the channel list of the unknown category to all categories. 277. [bug] isc_log_categorybyname() and isc_log_modulebyname() would fail to find the first member of any category or module array apart from the internal defaults. Thus, for example, the "notify" category was improperly configured by named. 276. [bug] dig now supports maximum sized TCP messages. 275. [bug] The definition of lwres_gai_strerror() was missing the lwres_ prefix. 274. [bug] TSIG AXFR verify failed when talking to a BIND 8 server. 273. [func] The default for the 'transfer-format' option is now 'many-answers'. This will break zone transfers to BIND 4.9.5 and older unless there is an explicit 'one-answer' configuration. 272. [bug] The sending of large TCP responses was canceled in mid-transmission due to a race condition caused by the failure to set the client object's "newstate" variable correctly when transitioning to the "working" state. 271. [func] Attempt to probe the number of cpus in named if unspecified rather than defaulting to 1. 270. [func] Allow maximum sized TCP answers. 269. [bug] Failed DNSSEC validations could cause an assertion failure by causing clone_results() to be called with with hevent->node == NULL. 268. [doc] A plain text version of the Administrator Reference Manual is now included in the distribution, as doc/arm/Bv9ARM.txt. 267. [func] Nsupdate is now provided in the distribution. 266. [bug] zone.c:save_nsrrset() node was not initialized. 265. [bug] dns_request_create() now works for TCP. 264. [func] Dispatch can not take TCP sockets in connecting state. Set DNS_DISPATCHATTR_CONNECTED when calling dns_dispatch_createtcp() for connected TCP sockets or call dns_dispatch_starttcp() when the socket is connected. 263. [func] New logging channel type 'stderr' channel some-name { stderr; severity error; } 262. [bug] 'master' was not initialized in zone.c:stub_callback(). 261. [func] Add dns_zone_markdirty(). 260. [bug] Running named as a non-root user failed on Linux kernels new enough to support retaining capabilities after setuid(). 259. [func] New random-device and random-seed-file statements for global options block of named.conf. Both accept a single string argument. 258. [bug] Fixed printing of lwres_addr_t.address field. 257. [bug] The server detached the last zone manager reference too early, while it could still be in use by queries. This manifested itself as assertion failures during the shutdown process for busy name servers. [RT #133] 256. [func] isc_ratelimiter_t now has attach/detach semantics, and isc_ratelimiter_shutdown guarantees that the rate limiter is detached from its task. 255. [func] New function dns_zonemgr_attach(). 254. [bug] Suppress "query denied" messages on additional data lookups. --- 9.0.0b4 released --- 253. [func] resolv.conf parser now recognizes ';' and '#' as comments (anywhere in line, not just as the beginning). 252. [bug] resolv.conf parser mishandled masks on sortlists. It also aborted when an unrecognized keyword was seen, now it silently ignores the entire line. 251. [bug] lwresd caught an assertion failure on startup. 250. [bug] fixed handling of size+unit when value would be too large for internal representation. 249. [cleanup] max-cache-size config option now takes a size-spec like 'datasize', except 'default' is not allowed. 248. [bug] global lame-ttl option was not being printed when config structures were written out. 247. [cleanup] Rename cache-size config option to max-cache-size. 246. [func] Rename global option cachesize to cache-size and add corresponding option to view statement. 245. [bug] If an uncompressed name will take more than 255 bytes and the buffer is sufficiently long, dns_name_fromwire should return DNS_R_FORMERR, not ISC_R_NOSPACE. This bug caused cause the server to catch an assertion failure when it received a query for a name longer than 255 bytes. 244. [bug] empty named.conf file and empty options statement are now parsed properly. 243. [func] new cachesize option for named.conf 242. [cleanup] fixed incorrect warning about auth-nxdomain usage. 241. [cleanup] nscount and soacount have been removed from the dns_master_*() argument lists. 240. [func] databases now come in three flavours: zone, cache and stub. 239. [func] If ISC_MEM_DEBUG is enabled, the variable isc_mem_debugging controls whether messages are printed or not. 238. [cleanup] A few more compilation warnings have been quieted: + missing sigwait prototype on BSD/OS 4.0/4.0.1. + PTHREAD_ONCE_INIT unbraced initializer warnings on Solaris 2.8. + IN6ADDR_ANY_INIT unbraced initializer warnings on BSD/OS 4.*, Linux and Solaris 2.8. 237. [bug] If connect() returned ENOBUFS when the resolver was initiating a TCP query, the socket didn't get destroyed, and the server did not shut down cleanly. 236. [func] Added new listen-on-v6 config file statement. 235. [func] Consider it a config file error if a listen-on statement has an IPv6 address in it, or a listen-on-v6 statement has an IPv4 address in it. 234. [bug] Allow a trusted-key's first field (domain-name) be either a quoted or an unquoted string, instead of requiring a quoted string. 233. [cleanup] Convert all config structure integer values to unsigned integer (isc_uint32_t) to match grammar. 232. [bug] Allow slave zones to not have a file. 231. [func] Support new 'port' clause in config file options section. Causes 'listen-on', 'masters' and 'also-notify' statements to use its value instead of default (53). 230. [func] Replace the dst sign/verify API with a cleaner one. 229. [func] Support config file sig-validity-interval statement in options, views and zone statements (master zones only). 228. [cleanup] Logging messages in config module stripped of trailing period. 227. [cleanup] The enumerated identifiers dns_rdataclass_*, dns_rcode_*, dns_opcode_*, and dns_trust_* are also now cast to their appropriate types, as with dns_rdatatype_* in item number 225 below. 226. [func] dns_name_totext() now always prints the root name as '.', even when omit_final_dot is true. 225. [cleanup] The enumerated dns_rdatatype_* identifiers are now cast to dns_rdatatype_t via macros of their same name so that they are of the proper integral type wherever a dns_rdatatype_t is needed. 224. [cleanup] The entire project builds cleanly with gcc's -Wcast-qual and -Wwrite-strings warnings enabled, which is now the default when using gcc. (Warnings from confparser.c, because of yacc's code, are unfortunately to be expected.) 223. [func] Several functions were re-prototyped to qualify one or more of their arguments with "const". Similarly, several functions that return pointers now have those pointers qualified with const. 222. [bug] The global 'also-notify' option was ignored. 221. [bug] An uninitialized variable was sometimes passed to dns_rdata_freestruct() when loading a zone, causing an assertion failure. 220. [cleanup] Set the default outgoing port in the view, and set it in sockaddrs returned from the ADB. [31-May-2000 explorer] 219. [bug] Signed truncated messages more correctly follow the respective specs. 218. [func] When an rdataset is signed, its ttl is normalized based on the signature validity period. 217. [func] Also-notify and trusted-keys can now be used in the 'view' statement. 216. [func] The 'max-cache-ttl' and 'max-ncache-ttl' options now work. 215. [bug] Failures at certain points in request processing could cause the assertion INSIST(client->lockview == NULL) to be triggered. 214. [func] New public function isc_netaddr_format(), for formatting network addresses in log messages. 213. [bug] Don't leak memory when reloading the zone if an update-policy clause was present in the old zone. 212. [func] Added dns_message_get/settsigkey, to make TSIG key management reasonable. 211. [func] The 'key' and 'server' statements can now occur inside 'view' statements. 210. [bug] The 'allow-transfer' option was ignored for slave zones, and the 'transfers-per-ns' option was was ignored for all zones. 209. [cleanup] Upgraded openssl files to new version 0.9.5a 208. [func] Added ISC_OFFSET_MAXIMUM for the maximum value of an isc_offset_t. 207. [func] The dnssec tools properly use the logging subsystem. 206. [cleanup] dst now stores the key name as a dns_name_t, not a char *. 205. [cleanup] On IRIX, turn off the mostly harmless warnings 1692 ("prototyped function redeclared without prototype") and 1552 ("variable ... set but not used") when compiling in the lib/dns/sec/{dnssafe,openssl} directories, which contain code imported from outside sources. 204. [cleanup] On HP/UX, pass +vnocompatwarnings to the linker to quiet the warnings that "The linked output may not run on a PA 1.x system." 203. [func] notify and zone soa queries are now tsig signed when appropriate. 202. [func] isc_lex_getsourceline() changed from returning int to returning unsigned long, the type of its underlying counter. 201. [cleanup] Removed the test/sdig program, it has been replaced by bin/dig/dig. --- 9.0.0b3 released --- 200. [bug] Failures in sending query responses to clients (e.g., running out of network buffers) were not logged. 199. [bug] isc_heap_delete() sometimes violated the heap invariant, causing timer events not to be posted when due. 198. [func] Dispatch managers hold memory pools which any managed dispatcher may use. This allows us to avoid dipping into the memory context for most allocations. [19-May-2000 explorer] 197. [bug] When an incoming AXFR or IXFR completes, the zone's internal state is refreshed from the SOA data. [19-May-2000 explorer] 196. [func] Dispatchers can be shared easily between views and/or interfaces. [19-May-2000 explorer] 195. [bug] Including the NXT record of the root domain in a negative response caused an assertion failure. 194. [doc] The PDF version of the Administrator's Reference Manual is no longer included in the ISC BIND9 distribution. 193. [func] changed dst_key_free() prototype. 192. [bug] Zone configuration validation is now done at end of config file parsing, and before loading callbacks. 191. [func] Patched to compile on UnixWare 7.x. This platform is not directly supported by the ISC. 190. [cleanup] The DNSSEC tools have been moved to a separate directory dnssec/ and given the following new, more descriptive names: dnssec-keygen dnssec-signzone dnssec-signkey dnssec-makekeyset Their command line arguments have also been changed to be more consistent. dnssec-keygen now prints the name of the generated key files (sans extension) on standard output to simplify its use in automated scripts. 189. [func] isc_time_secondsastimet(), a new function, will ensure that the number of seconds in an isc_time_t does not exceed the range of a time_t, or return ISC_R_RANGE. Similarly, isc_time_now(), isc_time_nowplusinterval(), isc_time_add() and isc_time_subtract() now check the range for overflow/underflow. In the case of isc_time_subtract, this changed a calling requirement (ie, something that could generate an assertion) into merely a condition that returns an error result. isc_time_add() and isc_time_subtract() were void- valued before but now return isc_result_t. 188. [func] Log a warning message when an incoming zone transfer contains out-of-zone data. 187. [func] isc_ratelimiter_enqueue() has an additional argument 'task'. 186. [func] dns_request_getresponse() has an additional argument 'preserve_order'. 185. [bug] Fixed up handling of ISC_MEMCLUSTER_LEGACY. Several public functions did not have an isc__ prefix, and referred to functions that had previously been renamed. 184. [cleanup] Variables/functions which began with two leading underscores were made to conform to the ANSI/ISO standard, which says that such names are reserved. 183. [func] ISC_LOG_PRINTTAG option for log channels. Useful for logging the program name or other identifier. 182. [cleanup] New command-line parameters for dnssec tools 181. [func] Added dst_key_buildfilename and dst_key_parsefilename 180. [func] New isc_result_t ISC_R_RANGE. Supersedes DNS_R_RANGE. 179. [func] options named.conf statement *must* now come before any zone or view statements. 178. [func] Post-load of named.conf check verifies a slave zone has non-empty list of masters defined. 177. [func] New per-zone boolean: enable-zone yes | no ; intended to let a zone be disabled without having to comment out the entire zone statement. 176. [func] New global and per-view option: max-cache-ttl number 175. [func] New global and per-view option: additional-data internal | minimal | maximal; 174. [func] New public function isc_sockaddr_format(), for formatting socket addresses in log messages. 173. [func] Keep a queue of zones waiting for zone transfer quota so that a new transfer can be dispatched immediately whenever quota becomes available. 172. [bug] $TTL directive was sometimes missing from dumped master files because totext_ctx_init() failed to initialize ctx->current_ttl_valid. 171. [cleanup] On NetBSD systems, the mit-pthreads or unproven-pthreads library is now always used unless --with-ptl2 is explicitly specified on the configure command line. The --with-mit-pthreads option is no longer needed and has been removed. 170. [cleanup] Remove inter server consistency checks from zone, these should return as a separate module in 9.1. dns_zone_checkservers(), dns_zone_checkparents(), dns_zone_checkchildren(), dns_zone_checkglue(). Remove dns_zone_setadb(), dns_zone_setresolver(), dns_zone_setrequestmgr() these should now be found via the view. 169. [func] ratelimiter can now process N events per interval. 168. [bug] include statements in named.conf caused syntax errors due to not consuming the semicolon ending the include statement before switching input streams. 167. [bug] Make lack of masters for a slave zone a soft error. 166. [bug] Keygen was overwriting existing keys if key_id conflicted, now it will retry, and non-null keys with key_id == 0 are not generated anymore. Key was not able to generate NOAUTHCONF DSA key, increased RSA key size to 2048 bits. 165. [cleanup] Silence "end-of-loop condition not reached" warnings from Solaris compiler. 164. [func] Added functions isc_stdio_open(), isc_stdio_close(), isc_stdio_seek(), isc_stdio_read(), isc_stdio_write(), isc_stdio_flush(), isc_stdio_sync(), isc_file_remove() to encapsulate nonportable usage of errno and sync. 163. [func] Added result codes ISC_R_FILENOTFOUND and ISC_R_FILEEXISTS. 162. [bug] Ensure proper range for arguments to ctype.h functions. 161. [cleanup] error in yyparse prototype that only HPUX caught. 160. [cleanup] getnet*() are not going to be implemented at this stage. 159. [func] Redefinition of config file elements is now an error (instead of a warning). 158. [bug] Log channel and category list copy routines weren't assigning properly to output parameter. 157. [port] Fix missing prototype for getopt(). 156. [func] Support new 'database' statement in zone. database "quoted-string"; 155. [bug] ns_notify_start() was not detaching the found zone. 154. [func] The signer now logs libdns warnings to stderr even when not verbose, and in a nicer format. 153. [func] dns_rdata_tostruct() 'mctx' is now optional. If 'mctx' is NULL then you need to preserve the 'rdata' until you have finished using the structure as there may be references to the associated memory. If 'mctx' is non-NULL it is guaranteed that there are no references to memory associated with 'rdata'. dns_rdata_freestruct() must be called if 'mctx' was non-NULL and may safely be called if 'mctx' was NULL. 152. [bug] keygen dumped core if domain name argument was omitted from command line. 151. [func] Support 'disabled' statement in zone config (causes zone to be parsed and then ignored). Currently must come after the 'type' clause. 150. [func] Support optional ports in masters and also-notify statements: masters [ port xxx ] { y.y.y.y [ port zzz ] ; } 149. [cleanup] Removed unused argument 'olist' from dns_c_view_unsetordering(). 148. [cleanup] Stop issuing some warnings about some configuration file statements that were not implemented, but now are. 147. [bug] Changed yacc union size to be smaller for yaccs that put yacc-stack on the real stack. 146. [cleanup] More general redundant header file cleanup. Rather than continuing to itemize every header which changed, this changelog entry just notes that if a header file did not need another header file that it was including in order to provide its advertised functionality, the inclusion of the other header file was removed. See util/check-includes for how this was tested. 145. [cleanup] Added and ISC_LANG_BEGINDECLS/ ISC_LANG_ENDDECLS to header files that had function prototypes, and removed it from those that did not. 144. [cleanup] libdns header files too numerous to name were made to conform to the same style for multiple inclusion protection. 143. [func] Added function dns_rdatatype_isknown(). 142. [cleanup] does not need or . 141. [bug] Corrupt requests with multiple questions could cause an assertion failure. 140. [cleanup] does not need or . 139. [cleanup] now includes instead of and . 138. [cleanup] isc_strtouq moved from str.[ch] to string.[ch] and renamed isc_string_touint64. isc_strsep moved from strsep.c to string.c and renamed isc_string_separate. 137. [cleanup] , , , and made to conform to the same style for multiple inclusion protection. 136. [cleanup] , , and Win32's needed ISC_LANG_BEGINDECLS/ISC_LANG_ENDDECLS. 135. [cleanup] Win32's did not need or , now uses in place of , and needed ISC_LANG_BEGINDECLS and ISC_LANG_ENDDECLS. 134. [cleanup] does not need . 133. [cleanup] needs . 132. [cleanup] does not need , but does need . 131. [cleanup] and need for ISC_R_* codes used in macros. 130. [cleanup] does not need or , and now includes instead of . 129. [bug] The 'default_debug' log channel was not set up when 'category default' was present in the config file 128. [cleanup] had ISC_LANG_BEGINDECLS instead of ISC_LANG_ENDDECLS at end of header. 127. [cleanup] The contracts for the comparison routines dns_name_fullcompare(), dns_name_compare(), dns_name_rdatacompare(), and dns_rdata_compare() now specify that the order value returned is < 0, 0, or > 0 instead of -1, 0, or 1. 126. [cleanup] and need . 125. [cleanup] , , , , , , and do not need . 124. [func] signer now imports parent's zone key signature and creates null keys/sets zone status bit for children when necessary 123. [cleanup] does not need . 122. [cleanup] does not need or . 121. [cleanup] does not need or . Multiple inclusion protection symbol fixed from ISC_SYMBOL_H to ISC_SYMTAB_H. isc_symtab_t moved to . 120. [cleanup] does not need , , , or . 119. [cleanup] structure definitions for generic rdata structures do not have _generic_ in their names. 118. [cleanup] libdns.a is now namespace-clean, on NetBSD, excepting YACC crust (yyparse, etc) [2000-apr-27 explorer] 117. [cleanup] libdns.a changes: dns_zone_clearnotify() and dns_zone_addnotify() are replaced by dns_zone_setnotifyalso(). dns_zone_clearmasters() and dns_zone_addmaster() are replaced by dns_zone_setmasters(). 116. [func] Added for isc_offset_t (aka off_t on Unix systems). 115. [port] Shut up the -Wmissing-declarations warning about 's __sputaux on BSD/OS pre-4.1. 114. [cleanup] does not need or . 113. [func] Utility programs dig and host added. 112. [cleanup] does not need . 111. [cleanup] does not need or . 110. [cleanup] does not need or . 109. [bug] "make depend" did nothing for bin/tests/{db,mem,sockaddr,tasks,timers}/. 108. [cleanup] DNS_SETBIT/DNS_GETBIT/DNS_CLEARBIT moved from to and renamed to DNS_BIT_SET/DNS_BIT_GET/DNS_BIT_CLEAR. 107. [func] Add keysigner and keysettool. 106. [func] Allow dnssec verifications to ignore the validity period. Used by several of the dnssec tools. 105. [doc] doc/dev/coding.html expanded with other implicit conventions the developers have used. 104. [bug] Made compress_add and compress_find static to lib/dns/compress.c. 103. [func] libisc buffer API changes for : Added: isc_buffer_base(b) (pointer) isc_buffer_current(b) (pointer) isc_buffer_active(b) (pointer) isc_buffer_used(b) (pointer) isc_buffer_length(b) (int) isc_buffer_usedlength(b) (int) isc_buffer_consumedlength(b) (int) isc_buffer_remaininglength(b) (int) isc_buffer_activelength(b) (int) isc_buffer_availablelength(b) (int) Removed: ISC_BUFFER_USEDCOUNT(b) ISC_BUFFER_AVAILABLECOUNT(b) isc_buffer_type(b) Changed names: isc_buffer_used(b, r) -> isc_buffer_usedregion(b, r) isc_buffer_available(b, r) -> isc_buffer_available_region(b, r) isc_buffer_consumed(b, r) -> isc_buffer_consumedregion(b, r) isc_buffer_active(b, r) -> isc_buffer_activeregion(b, r) isc_buffer_remaining(b, r) -> isc_buffer_remainingregion(b, r) Buffer types were removed, so the ISC_BUFFERTYPE_* macros are no more, and the type argument to isc_buffer_init and isc_buffer_allocate were removed. isc_buffer_putstr is now void (instead of isc_result_t) and requires that the caller ensure that there is enough available buffer space for the string. 102. [port] Correctly detect inet_aton, inet_pton and inet_ptop on BSD/OS 4.1. 101. [cleanup] Quieted EGCS warnings from lib/isc/print.c. 100. [cleanup] does not need or . isc_random_t moved to . 99. [cleanup] Rate limiter now has separate shutdown() and destroy() functions, and it guarantees that all queued events are delivered even in the shutdown case. 98. [cleanup] does not need or unless ISC_PLATFORM_NEEDVSNPRINTF is defined. 97. [cleanup] does not need or . 96. [cleanup] does not need . 95. [cleanup] does not need . 94. [cleanup] Some installed header files did not compile as C++. 93. [cleanup] does not need . 92. [cleanup] does not need , , or . 91. [cleanup] does not need or . 90. [cleanup] Removed unneeded ISC_LANG_BEGINDECLS/ISC_LANG_ENDDECLS from . 89. [cleanup] does not need . 88. [cleanup] does not need or . isc_interface_t and isc_interfaceiter_t moved to . 87. [cleanup] does not need , or . 86. [cleanup] isc_bufferlist_t moved from to . 85. [cleanup] does not need , , , or . 84. [func] allow-query ACL checks now apply to all data added to a response. 83. [func] If the server is authoritative for both a delegating zone and its (nonsecure) delegatee, and a query is made for a KEY RR at the top of the delegatee, then the server will look for a KEY in the delegator if it is not found in the delegatee. 82. [cleanup] does not need . 81. [cleanup] and do not need . 80. [cleanup] does not need or . 79. [cleanup] does not need . 78. [cleanup] lwres_conftest renamed to lwresconf_test for consistency with other *_test programs. 77. [cleanup] typedef of isc_time_t and isc_interval_t moved from to . 76. [cleanup] Rewrote keygen. 75. [func] Don't load a zone if its database file is older than the last time the zone was loaded. 74. [cleanup] Removed mktemplate.o and ufile.o from libisc.a, subsumed by file.o. 73. [func] New "file" API in libisc, including new function isc_file_getmodtime, isc_mktemplate renamed to isc_file_mktemplate and isc_ufile renamed to isc_file_openunique. By no means an exhaustive API, it is just what's needed for now. 72. [func] DNS_RBTFIND_NOPREDECESSOR and DNS_RBTFIND_NOOPTIONS added for dns_rbt_findnode, the former to disable the setting of the chain to the predecessor, and the latter to make clear when no options are set. 71. [cleanup] Made explicit the implicit REQUIREs of isc_time_seconds, isc_time_nanoseconds, and isc_time_subtract. 70. [func] isc_time_set() added. 69. [bug] The zone object's master and also-notify lists grew longer with each server reload. 68. [func] Partial support for SIG(0) on incoming messages. 67. [performance] Allow use of alternate (compile-time supplied) OpenSSL libraries/headers. 66. [func] Data in authoritative zones should have a trust level beyond secure. 65. [cleanup] Removed obsolete typedef of dns_zone_callbackarg_t from . 64. [func] The RBT, DB, and zone table APIs now allow the caller find the most-enclosing superdomain of a name. 63. [func] Generate NOTIFY messages. 62. [func] Add UDP refresh support. 61. [cleanup] Use single quotes consistently in log messages. 60. [func] Catch and disallow singleton types on message parse. 59. [bug] Cause net/host unreachable to be a hard error when sending and receiving. 58. [bug] bin/named/query.c could sometimes trigger the (client->query.attributes & NS_QUERYATTR_NAMEBUFUSED) == 0 assertion in query_newname(). 57. [func] Added dns_nxt_typepresent() 56. [bug] SIG records were not properly returned in cached negative answers. 55. [bug] Responses containing multiple names in the authority section were not negatively cached. 54. [bug] If a fetch with sigrdataset==NULL joined one with sigrdataset!=NULL or vice versa, the resolver could catch an assertion or lose signature data, respectively. 53. [port] freebsd 4.0: lib/isc/unix/socket.c requires . 52. [bug] rndc: taskmgr and socketmgr were not initialized to NULL. 51. [cleanup] dns/compress.h and dns/zt.h did not need to include dns/rbt.h; it was needed only by compress.c and zt.c. 50. [func] RBT deletion no longer requires a valid chain to work, and dns_rbt_deletenode was added. 49. [func] Each cache now has its own mctx. 48. [func] isc_task_create() no longer takes an mctx. isc_task_mem() has been eliminated. 47. [func] A number of modules now use memory context reference counting. 46. [func] Memory contexts are now reference counted. Added isc_mem_inuse() and isc_mem_preallocate(). Renamed isc_mem_destroy_check() to isc_mem_setdestroycheck(). 45. [bug] The trusted-key statement incorrectly loaded keys. 44. [bug] Don't include authority data if it would force us to unset the AD bit in the message. 43. [bug] DNSSEC verification of cached rdatasets was failing. 42. [cleanup] Simplified logging of messages with embedded domain names by introducing a new convenience function dns_name_format(). 41. [func] Use PR_SET_KEEPCAPS on Linux 2.3.99-pre3 and later to allow 'named' to run as a non-root user while retaining the ability to bind() to privileged ports. 40. [func] Introduced new logging category "dnssec" and logging module "dns/validator". 39. [cleanup] Moved the typedefs for isc_region_t, isc_textregion_t, and isc_lex_t to . 38. [bug] TSIG signed incoming zone transfers work now. 37. [bug] If the first RR in an incoming zone transfer was not an SOA, the server died with an assertion failure instead of just reporting an error. 36. [cleanup] Change DNS_R_SUCCESS (and others) to ISC_R_SUCCESS 35. [performance] Log messages which are of a level too high to be logged by any channel in the logging configuration will not cause the log mutex to be locked. 34. [bug] Recursion was allowed even with 'recursion no'. 33. [func] The RBT now maintains a parent pointer at each node. 32. [cleanup] bin/lwresd/client.c needs for memset() prototype. 31. [bug] Use ${LIBTOOL} to compile bin/named/main.@O@. 30. [func] config file grammar change to support optional class type for a view. 29. [func] support new config file view options: auth-nxdomain recursion query-source query-source-v6 transfer-source transfer-source-v6 max-transfer-time-out max-transfer-idle-out transfer-format request-ixfr provide-ixfr cleaning-interval fetch-glue notify rfc2308-type1 lame-ttl max-ncache-ttl min-roots 28. [func] support lame-ttl, min-roots and serial-queries config global options. 27. [bug] Only include on BSD/OS 4.[01]*. Including it on other platforms (eg, NetBSD) can cause a forced #error from the C preprocessor. 26. [func] new match-clients statement in config file view. 25. [bug] make install failed to install and . 24. [cleanup] Eliminate some unnecessary #includes of header files from header files. 23. [cleanup] Provide more context in log messages about client requests, using a new function ns_client_log(). 22. [bug] SIGs weren't returned in the answer section when the query resulted in a fetch. 21. [port] Look at STD_CINCLUDES after CINCLUDES during compilation, so additional system include directories can be searched but header files in the bind9 source tree with conflicting names take precedence. This avoids issues with installed versions of dnssafe and openssl. 20. [func] Configuration file post-load validation of zones failed if there were no zones. 19. [bug] dns_zone_notifyreceive() failed to unlock the zone lock in certain error cases. 18. [bug] Use AC_TRY_LINK rather than AC_TRY_COMPILE in configure.in to check for presence of in6addr_any. 17. [func] Do configuration file post-load validation of zones. 16. [bug] put quotes around key names on config file output to avoid possible keyword clashes. 15. [func] Add dns_name_dupwithoffsets(). This function is improves comparison performance for duped names. 14. [bug] free_rbtdb() could have 'put' unallocated memory in an unlikely error path. 13. [bug] lib/dns/master.c and lib/dns/xfrin.c didn't ignore out-of-zone data. 12. [bug] Fixed possible uninitialized variable error. 11. [bug] axfr_rrstream_first() didn't check the result code of db_rr_iterator_first(), possibly causing an assertion to be triggered later. 10. [bug] A bug in the code which makes EDNS0 OPT records in bin/named/client.c and lib/dns/resolver.c could trigger an assertion. 9. [cleanup] replaced bit-setting code in confctx.c and replaced repeated code with macro calls. 8. [bug] Shutdown of incoming zone transfer accessed freed memory. 7. [cleanup] removed 'listen-on' from view statement. 6. [bug] quote RR names when generating config file to prevent possible clash with config file keywords (such as 'key'). 5. [func] syntax change to named.conf file: new ssu grant/deny statements must now be enclosed by an 'update-policy' block. 4. [port] bin/named/unix/os.c didn't compile on systems with linux 2.3 kernel includes due to conflicts between C library includes and the kernel includes. We now get only what we need from , and avoid pulling in other linux kernel .h files. 3. [bug] TKEYs go in the answer section of responses, not the additional section. 2. [bug] Generating cryptographic randomness failed on systems without /dev/random. 1. [bug] The installdirs rule in lib/isc/unix/include/isc/Makefile.in had a typo which prevented the isc directory from being created if it didn't exist. --- 9.0.0b2 released --- # This tells Emacs to use hard tabs in this file. # Local Variables: # indent-tabs-mode: t # End: bind9-9.11.3+dfsg/CONTRIBUTING000066400000000000000000000165551325250447100154020ustar00rootroot00000000000000BIND Source Access and Contributor Guidelines Feb 22, 2018 Contents 1. Access to source code 2. Reporting bugs 3. Contributing code Introduction Thank you for using BIND! BIND is open source software that implements the Domain Name System (DNS) protocols for the Internet. It is a reference implementation of those protocols, but it is also production-grade software, suitable for use in high-volume and high-reliability applications. It is by far the most widely used DNS software, providing a robust and stable platform on top of which organizations can build distributed computing systems with the knowledge that those systems are fully compliant with published DNS standards. BIND is and will always remain free and openly available. It can be used and modified in any way by anyone. BIND is maintained by the Internet Systems Consortium, a public-benefit 501(c)(3) nonprofit, using a "managed open source" approach: anyone can see the source, but only ISC employees have commit access. Until recently, the source could only be seen once ISC had published a release: read access to the source repository was restricted just as commit access was. That's now changing, with the opening of a public git mirror to the BIND source tree (see below). Access to source code Public BIND releases are always available from the ISC FTP site. A public-access GIT repository is also available at https://gitlab.isc.org . This repository is a mirror, updated several times per day, of the source repository maintained by ISC. It contains all the public release branches; upcoming releases can be viewed in their current state at any time. It does not contain development branches or unreviewed work in progress. Commits which address security vulnerablilities are withheld until after public disclosure. You can browse the source online via https://gitlab.isc.org/isc-projects/ bind9 To clone the repository, use: $ git clone https://gitlab.isc.org/isc-projects/bind9.git Release branch names are of the form v9_X, where X represents the second number in the BIND 9 version number. So, to check out the BIND 9.12 branch, use: $ git checkout v9_12 Whenever a branch is ready for publication, a tag will be placed of the form v9_X_Y. The 9.12.0 release, for instance, is tagged as v9_12_0. The branch in which the next major release is being developed is called master. Reporting bugs Reports of flaws in the BIND package, including software bugs, errors in the documentation, missing files in the tarball, suggested changes or requests for new features, etc, can be filed using https://gitlab.isc.org/ isc-projects/bind9/issues. Due to a large ticket backlog, we are sometimes slow to respond, especially if a bug is cosmetic or if a feature request is vague or low in priority, but we will try at least to acknowledge legitimate bug reports within a week. ISC's ticketing system is publicly readable; however, you must have an account to file a new issue. You can either register locally or use credentials from an existing account at GitHub, GitLab, Google, Twitter, or Facebook. Reporting possible security issues If you think you may be seeing a potential security vulnerability in BIND (for example, a crash with REQUIRE, INSIST, or ASSERT failure), please report it immediately by emailing to security-officer@isc.org. Plain-text e-mail is not a secure choice for communications concerning undisclosed security issues so please encrypt your communications to us if possible, using the ISC Security Officer public key. Do not discuss undisclosed security vulnerabilites on any public mailing list. ISC has a long history of handling reported vulnerabilities promptly and effectively and we respect and acknowledge responsible reporters. ISC's Security Vulnerability Disclosure Policy is documented at https:// kb.isc.org/article/AA-00861/0. If you have a crash, you may want to consult ?What to do if your BIND or DHCP server has crashed.? Contributing code BIND is licensed under the Mozilla Public License 2.0. Earier versions (BIND 9.10 and earlier) were licensed under the ISC License ISC does not require an explicit copyright assignment for patch contributions. However, by submitting a patch to ISC, you implicitly certify that you are the author of the code, that you intend to reliquish exclusive copyright, and that you grant permission to publish your work under the open source license used for the BIND version(s) to which your patch will be applied. BIND code Patches for BIND may be submitted directly via merge requests in ISC's Gitlab source repository for BIND. Patches can also be submitted as diffs against a specific version of BIND -- preferably the current top of the master branch. Diffs may be generated using either git format-patch or git diff. Those wanting to write code for BIND may be interested in the developer information page, which includes information about BIND design and coding practices, including discussion of internal APIs and overall system architecture. (This is a work in progress, and still quite preliminary.) Every patch submitted will be reviewed by ISC engineers following our code review process before it is merged. It may take considerable time to review patch submissions, especially if they don't meet ISC style and quality guidelines. If a patch is a good idea, we can and will do additional work to bring it up to par, but if we're busy with other work, it may take us a long time to get to it. To ensure your patch is acted on as promptly as possible, please: * Try to adhere to the BIND 9 coding style. * Run make check to ensure your change hasn't caused any functional regressions. * Document your work, both in the patch itself and in the accompanying email. * In patches that make non-trivial functional changes, include system tests if possible; when introducing or substantially altering a library API, include unit tests. See Testing for more information. Changes to configure If you need to make changes to configure, you should not edit it directly; instead, edit configure.in, then run autoconf. Similarly, instead of editing config.h.in directly, edit configure.in and run autoheader. When submitting a patch as a diff, it's fine to omit the configure diffs to save space. Just send the configure.in diffs and we'll generate the new configure during the review process. Documentation All functional changes should be documented. There are three types of documentation in the BIND source tree: * Man pages are kept alongside the source code for the commands they document, in files ending in .docbook; for example, the named man page is bin/named/named.docbook. * The BIND 9 Administrator Reference Manual is mostly in doc/arm/ Bv9ARM-book.xml, plus a few other XML files that are included in it. * API documentation is in the header file describing the API, in Doxygen-formatted comments. It is not necessary to edit any documentation files other than these; all PDF, HTML, and nroff-format man page files will be updated automatically from the docbook and XML files after merging. Patches to improve existing documentation are also very welcome! Tests BIND is a large and complex project. We rely heavily on continuous automated testing and cannot merge new code without adequate test coverage. Please see the 'Testing' section of doc/dev/dev.md for more information. Thanks Thank you for your interest in contributing to the ongoing development of BIND. bind9-9.11.3+dfsg/CONTRIBUTING.md000066400000000000000000000211621325250447100157670ustar00rootroot00000000000000 ## BIND Source Access and Contributor Guidelines *Feb 22, 2018* ### Contents 1. [Access to source code](#access) 1. [Reporting bugs](#bugs) 1. [Contributing code](#contrib) ### Introduction Thank you for using BIND! BIND is open source software that implements the Domain Name System (DNS) protocols for the Internet. It is a reference implementation of those protocols, but it is also production-grade software, suitable for use in high-volume and high-reliability applications. It is by far the most widely used DNS software, providing a robust and stable platform on top of which organizations can build distributed computing systems with the knowledge that those systems are fully compliant with published DNS standards. BIND is and will always remain free and openly available. It can be used and modified in any way by anyone. BIND is maintained by the [Internet Systems Consortium](https://www.isc.org), a public-benefit 501(c)(3) nonprofit, using a "managed open source" approach: anyone can see the source, but only ISC employees have commit access. Until recently, the source could only be seen once ISC had published a release: read access to the source repository was restricted just as commit access was. That's now changing, with the opening of a public git mirror to the BIND source tree (see below). ### Access to source code Public BIND releases are always available from the [ISC FTP site](ftp://ftp.isc.org/isc/bind9). A public-access GIT repository is also available at [https://gitlab.isc.org](https://gitlab.isc.org). This repository is a mirror, updated several times per day, of the source repository maintained by ISC. It contains all the public release branches; upcoming releases can be viewed in their current state at any time. It does *not* contain development branches or unreviewed work in progress. Commits which address security vulnerablilities are withheld until after public disclosure. You can browse the source online via [https://gitlab.isc.org/isc-projects/bind9](https://gitlab.isc.org/isc-projects/bind9) To clone the repository, use: > $ git clone https://gitlab.isc.org/isc-projects/bind9.git Release branch names are of the form `v9_X`, where X represents the second number in the BIND 9 version number. So, to check out the BIND 9.12 branch, use: > $ git checkout v9_12 Whenever a branch is ready for publication, a tag will be placed of the form `v9_X_Y`. The 9.12.0 release, for instance, is tagged as `v9_12_0`. The branch in which the next major release is being developed is called `master`. ### Reporting bugs Reports of flaws in the BIND package, including software bugs, errors in the documentation, missing files in the tarball, suggested changes or requests for new features, etc, can be filed using [https://gitlab.isc.org/isc-projects/bind9/issues](https://gitlab.isc.org/isc-projects/bind9/issues). Due to a large ticket backlog, we are sometimes slow to respond, especially if a bug is cosmetic or if a feature request is vague or low in priority, but we will try at least to acknowledge legitimate bug reports within a week. ISC's ticketing system is publicly readable; however, you must have an account to file a new issue. You can either register locally or use credentials from an existing account at GitHub, GitLab, Google, Twitter, or Facebook. ### Reporting possible security issues If you think you may be seeing a potential security vulnerability in BIND (for example, a crash with REQUIRE, INSIST, or ASSERT failure), please report it immediately by emailing to security-officer@isc.org. Plain-text e-mail is not a secure choice for communications concerning undisclosed security issues so please encrypt your communications to us if possible, using the [ISC Security Officer public key](https://www.isc.org/downloads/software-support-policy/openpgp-key/). Do not discuss undisclosed security vulnerabilites on any public mailing list. ISC has a long history of handling reported vulnerabilities promptly and effectively and we respect and acknowledge responsible reporters. ISC's Security Vulnerability Disclosure Policy is documented at [https://kb.isc.org/article/AA-00861/0](https://kb.isc.org/article/AA-00861/0). If you have a crash, you may want to consult [‘What to do if your BIND or DHCP server has crashed.’](https://kb.isc.org/article/AA-00340/89/What-to-do-if-your-BIND-or-DHCP-server-has-crashed.html) ### Contributing code BIND is licensed under the [Mozilla Public License 2.0](http://www.isc.org/downloads/software-support-policy/isc-license/). Earier versions (BIND 9.10 and earlier) were licensed under the [ISC License](http://www.isc.org/downloads/software-support-policy/isc-license/) ISC does not require an explicit copyright assignment for patch contributions. However, by submitting a patch to ISC, you implicitly certify that you are the author of the code, that you intend to reliquish exclusive copyright, and that you grant permission to publish your work under the open source license used for the BIND version(s) to which your patch will be applied. #### BIND code Patches for BIND may be submitted directly via merge requests in [ISC's Gitlab](https://gitlab.isc.org/isc-projects/bind9/) source repository for BIND. Patches can also be submitted as diffs against a specific version of BIND -- preferably the current top of the `master` branch. Diffs may be generated using either `git format-patch` or `git diff`. Those wanting to write code for BIND may be interested in the [developer information](doc/dev/dev.md) page, which includes information about BIND design and coding practices, including discussion of internal APIs and overall system architecture. (This is a work in progress, and still quite preliminary.) Every patch submitted will be reviewed by ISC engineers following our [code review process](doc/dev/dev.md#reviews) before it is merged. It may take considerable time to review patch submissions, especially if they don't meet ISC style and quality guidelines. If a patch is a good idea, we can and will do additional work to bring it up to par, but if we're busy with other work, it may take us a long time to get to it. To ensure your patch is acted on as promptly as possible, please: * Try to adhere to the [BIND 9 coding style](doc/dev/style.md). * Run `make` `check` to ensure your change hasn't caused any functional regressions. * Document your work, both in the patch itself and in the accompanying email. * In patches that make non-trivial functional changes, include system tests if possible; when introducing or substantially altering a library API, include unit tests. See [Testing](doc/dev/dev.md#testing) for more information. ##### Changes to `configure` If you need to make changes to `configure`, you should not edit it directly; instead, edit `configure.in`, then run `autoconf`. Similarly, instead of editing `config.h.in` directly, edit `configure.in` and run `autoheader`. When submitting a patch as a diff, it's fine to omit the `configure` diffs to save space. Just send the `configure.in` diffs and we'll generate the new `configure` during the review process. ##### Documentation All functional changes should be documented. There are three types of documentation in the BIND source tree: * Man pages are kept alongside the source code for the commands they document, in files ending in `.docbook`; for example, the `named` man page is `bin/named/named.docbook`. * The *BIND 9 Administrator Reference Manual* is mostly in `doc/arm/Bv9ARM-book.xml`, plus a few other XML files that are included in it. * API documentation is in the header file describing the API, in Doxygen-formatted comments. It is not necessary to edit any documentation files other than these; all PDF, HTML, and `nroff`-format man page files will be updated automatically from the `docbook` and `XML` files after merging. Patches to improve existing documentation are also very welcome! ##### Tests BIND is a large and complex project. We rely heavily on continuous automated testing and cannot merge new code without adequate test coverage. Please see [the 'Testing' section of doc/dev/dev.md](doc/dev/dev.md#testing) for more information. #### Thanks Thank you for your interest in contributing to the ongoing development of BIND. bind9-9.11.3+dfsg/COPYRIGHT000066400000000000000000000720171325250447100150360ustar00rootroot00000000000000Copyright (C) 1996-2018 Internet Systems Consortium, Inc. ("ISC") This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. ----------------------------------------------------------------------------- Portions of this code release fall under one or more of the following Copyright notices. Please see individual source files for details. For binary releases also see: OpenSSL-LICENSE. Copyright (C) 1996-2001 Nominum, Inc. Permission to use, copy, modify, and distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ----------------------------------------------------------------------------- Copyright (C) 1995-2000 by Network Associates, Inc. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ----------------------------------------------------------------------------- Copyright (C) 2002 Stichting NLnet, Netherlands, stichting@nlnet.nl. Permission to use, copy, modify, and distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. THE SOFTWARE IS PROVIDED "AS IS" AND STICHTING NLNET DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL STICHTING NLNET BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. The development of Dynamically Loadable Zones (DLZ) for Bind 9 was conceived and contributed by Rob Butler. Permission to use, copy, modify, and distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. THE SOFTWARE IS PROVIDED "AS IS" AND ROB BUTLER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ROB BUTLER BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ----------------------------------------------------------------------------- Copyright (c) 1987, 1990, 1993, 1994 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ----------------------------------------------------------------------------- Copyright (C) The Internet Society 2005. This version of this module is part of RFC 4178; see the RFC itself for full legal notices. (The above copyright notice is per RFC 3978 5.6 (a), q.v.) ----------------------------------------------------------------------------- Copyright (c) 2004 Masarykova universita (Masaryk University, Brno, Czech Republic) All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ----------------------------------------------------------------------------- Copyright (c) 1997 - 2003 Kungliga Tekniska Högskolan (Royal Institute of Technology, Stockholm, Sweden). All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Institute nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ----------------------------------------------------------------------------- Copyright (c) 1998 Doug Rabson All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ----------------------------------------------------------------------------- Copyright ((c)) 2002, Rice University All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Rice University (RICE) nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. This software is provided by RICE and the contributors on an "as is" basis, without any representations or warranties of any kind, express or implied including, but not limited to, representations or warranties of non-infringement, merchantability or fitness for a particular purpose. In no event shall RICE or contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage. ----------------------------------------------------------------------------- Copyright (c) 1993 by Digital Equipment Corporation. Permission to use, copy, modify, and distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies, and that the name of Digital Equipment Corporation not be used in advertising or publicity pertaining to distribution of the document or software without specific, written prior permission. THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ----------------------------------------------------------------------------- Copyright 2000 Aaron D. Gifford. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holder nor the names of contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTOR(S) ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ----------------------------------------------------------------------------- Copyright (c) 1998 Doug Rabson. Copyright (c) 2001 Jake Burkholder. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ----------------------------------------------------------------------------- Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the project nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ----------------------------------------------------------------------------- Copyright (c) 1999-2000 by Nortel Networks Corporation Permission to use, copy, modify, and distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. THE SOFTWARE IS PROVIDED "AS IS" AND NORTEL NETWORKS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NORTEL NETWORKS BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ----------------------------------------------------------------------------- Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved. By using this file, you agree to the terms and conditions set forth bellow. LICENSE TERMS AND CONDITIONS The following License Terms and Conditions apply, unless a different license is obtained from Japan Network Information Center ("JPNIC"), a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda, Chiyoda-ku, Tokyo 101-0047, Japan. 1. Use, Modification and Redistribution (including distribution of any modified or derived work) in source and/or binary forms is permitted under this License Terms and Conditions. 2. Redistribution of source code must retain the copyright notices as they appear in each source code file, this License Terms and Conditions. 3. Redistribution in binary form must reproduce the Copyright Notice, this License Terms and Conditions, in the documentation and/or other materials provided with the distribution. For the purposes of binary distribution the "Copyright Notice" refers to the following language: "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved." 4. The name of JPNIC may not be used to endorse or promote products derived from this Software without specific prior written approval of JPNIC. 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. ----------------------------------------------------------------------------- Copyright (C) 2004 Nominet, Ltd. Permission to use, copy, modify, and distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. THE SOFTWARE IS PROVIDED "AS IS" AND NOMINET DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ----------------------------------------------------------------------------- Portions Copyright RSA Security Inc. License to copy and use this software is granted provided that it is identified as "RSA Security Inc. PKCS #11 Cryptographic Token Interface (Cryptoki)" in all material mentioning or referencing this software. License is also granted to make and use derivative works provided that such works are identified as "derived from the RSA Security Inc. PKCS #11 Cryptographic Token Interface (Cryptoki)" in all material mentioning or referencing the derived work. RSA Security Inc. makes no representations concerning either the merchantability of this software or the suitability of this software for any particular purpose. It is provided "as is" without express or implied warranty of any kind. ----------------------------------------------------------------------------- Copyright (c) 1996, David Mazieres Copyright (c) 2008, Damien Miller Permission to use, copy, modify, and distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ----------------------------------------------------------------------------- Copyright (c) 2000-2001 The OpenSSL Project. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. All advertising materials mentioning features or use of this software must display the following acknowledgment: "This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to endorse or promote products derived from this software without prior written permission. For written permission, please contact licensing@OpenSSL.org. 5. Products derived from this software may not be called "OpenSSL" nor may "OpenSSL" appear in their names without prior written permission of the OpenSSL Project. 6. Redistributions of any form whatsoever must retain the following acknowledgment: "This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ----------------------------------------------------------------------------- Copyright (c) 1995, 1997, 1998 The NetBSD Foundation, Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ----------------------------------------------------------------------------- Copyright (C) 2008-2011 Red Hat, Inc. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. THE SOFTWARE IS PROVIDED "AS IS" AND Red Hat DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL Red Hat BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ----------------------------------------------------------------------------- Copyright (c) 2013-2014, Farsight Security, Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ----------------------------------------------------------------------------- Copyright (c) 2014 by Farsight Security, Inc. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. bind9-9.11.3+dfsg/HISTORY000066400000000000000000000506711325250447100146310ustar00rootroot00000000000000Functional enhancements from prior major releases of BIND 9 BIND 9.10.0 BIND 9.10.0 includes a number of changes from BIND 9.9 and earlier releases. New features include: * DNS Response-rate limiting (DNS RRL), which blunts the impact of reflection and amplification attacks, is always compiled in and no longer requires a compile-time option to enable it. * An experimental "Source Identity Token" (SIT) EDNS option is now available. Similar to DNS Cookies as invented by Donald Eastlake 3rd, these are designed to enable clients to detect off-path spoofed responses, and to enable servers to detect spoofed-source queries. Servers can be configured to send smaller responses to clients that have not identified themselves using a SIT option, reducing the effectiveness of amplification attacks. RRL processing has also been updated; clients proven to be legitimate via SIT are not subject to rate limiting. Use "configure --enable-sit" to enable this feature in BIND. * A new zone file format, "map", stores zone data in a format that can be mapped directly into memory, allowing significantly faster zone loading. * "delv" (domain entity lookup and validation) is a new tool with dig-like semantics for looking up DNS data and performing internal DNSSEC validation. This allows easy validation in environments where the resolver may not be trustworthy, and assists with troubleshooting of DNSSEC problems. (NOTE: In previous development releases of BIND 9.10, this utility was called "delve". The spelling has been changed to avoid confusion with the "delve" utility included with the Xapian search engine.) * Improved EDNS(0) processing for better resolver performance and reliability over slow or lossy connections. * A new "configure --with-tuning=large" option tunes certain compiled-in constants and default settings to values better suited to large servers with abundant memory. This can improve performance on such servers, but will consume more memory and may degrade performance on smaller systems. * Substantial improvement in response-policy zone (RPZ) performance. Up to 32 response-policy zones can be configured with minimal performance loss. * To improve recursive resolver performance, cache records which are still being requested by clients can now be automatically refreshed from the authoritative server before they expire, reducing or eliminating the time window in which no answer is available in the cache. * New "rpz-client-ip" triggers and drop policies allowing response policies based on the IP address of the client. * ACLs can now be specified based on geographic location using the MaxMind GeoIP databases. Use "configure --with-geoip" to enable. * Zone data can now be shared between views, allowing multiple views to serve the same zones authoritatively without storing multiple copies in memory. * New XML schema (version 3) for the statistics channel includes many new statistics and uses a flattened XML tree for faster parsing. The older schema is now deprecated. * A new stylesheet, based on the Google Charts API, displays XML statistics in charts and graphs on javascript-enabled browsers. * The statistics channel can now provide data in JSON format as well as XML. * New stats counters track TCP and UDP queries received per zone, and EDNS options received in total. * The internal and export versions of the BIND libraries (libisc, libdns, etc) have been unified so that external library clients can use the same libraries as BIND itself. * A new compile-time option, "configure --enable-native-pkcs11", allows BIND 9 cryptography functions to use the PKCS#11 API natively, so that BIND can drive a cryptographic hardware service module (HSM) directly instead of using a modified OpenSSL as an intermediary. (Note: This feature requires an HSM to have a full implementation of the PKCS#11 API; many current HSMs only have partial implementations. The new "pkcs11-tokens" command can be used to check API completeness. Native PKCS#11 is known to work with the Thales nShield HSM and with SoftHSM version 2 from the Open DNSSEC project.) * The new "max-zone-ttl" option enforces maximum TTLs for zones. This can simplify the process of rolling DNSSEC keys by guaranteeing that cached signatures will have expired within the specified amount of time. * "dig +subnet" sends an EDNS CLIENT-SUBNET option when querying. * "dig +expire" sends an EDNS EXPIRE option when querying. When this option is sent with an SOA query to a server that supports it, it will report the expiry time of a slave zone. * New "dnssec-coverage" tool to check DNSSEC key coverage for a zone and report if a lapse in signing coverage has been inadvertently scheduled. * Signing algorithm flexibility and other improvements for the "rndc" control channel. * "named-checkzone" and "named-compilezone" can now read journal files, allowing them to process dynamic zones. * Multiple DLZ databases can now be configured. Individual zones can be configured to be served from a specific DLZ database. DLZ databases now serve zones of type "master" and "redirect". * "rndc zonestatus" reports information about a specified zone. * "named" now listens on IPv6 as well as IPv4 interfaces by default. * "named" now preserves the capitalization of names when responding to queries: for instance, a query for "example.com" may be answered with "example.COM" if the name was configured that way in the zone file. Some clients have a bug causing them to depend on the older behavior, in which the case of the answer always matched the case of the query, rather than the case of the name configured in the DNS. Such clients can now be specified in the new "no-case-compress" ACL; this will restore the older behavior of "named" for those clients only. * new "dnssec-importkey" command allows the use of offline DNSSEC keys with automatic DNSKEY management. * New "named-rrchecker" tool to verify the syntactic correctness of individual resource records. * When re-signing a zone, the new "dnssec-signzone -Q" option drops signatures from keys that are still published but are no longer active. * "named-checkconf -px" will print the contents of configuration files with the shared secrets obscured, making it easier to share configuration (e.g. when submitting a bug report) without revealing private information. * "rndc scan" causes named to re-scan network interfaces for changes in local addresses. * On operating systems with support for routing sockets, network interfaces are re-scanned automatically whenever they change. * "tsig-keygen" is now available as an alternate command name to use for "ddns-confgen". BIND 9.9.0 BIND 9.9.0 includes a number of changes from BIND 9.8 and earlier releases. New features include: * Inline signing, allowing automatic DNSSEC signing of master zones without modification of the zonefile, or "bump in the wire" signing in slaves. * NXDOMAIN redirection. * New 'rndc flushtree' command clears all data under a given name from the DNS cache. * New 'rndc sync' command dumps pending changes in a dynamic zone to disk without a freeze/thaw cycle. * New 'rndc signing' command displays or clears signing status records in 'auto-dnssec' zones. * NSEC3 parameters for 'auto-dnssec' zones can now be set prior to signing, eliminating the need to initially sign with NSEC. * Startup time improvements on large authoritative servers. * Slave zones are now saved in raw format by default. * Several improvements to response policy zones (RPZ). * Improved hardware scalability by using multiple threads to listen for queries and using finer-grained client locking * The 'also-notify' option now takes the same syntax as 'masters', so it can used named masterlists and TSIG keys. * 'dnssec-signzone -D' writes an output file containing only DNSSEC data, which can be included by the primary zone file. * 'dnssec-signzone -R' forces removal of signatures that are not expired but were created by a key which no longer exists. * 'dnssec-signzone -X' allows a separate expiration date to be specified for DNSKEY signatures from other signatures. * New '-L' option to dnssec-keygen, dnssec-settime, and dnssec-keyfromlabel sets the default TTL for the key. * dnssec-dsfromkey now supports reading from standard input, to make it easier to convert DNSKEY to DS. * RFC 1918 reverse zones have been added to the empty-zones table per RFC 6303. * Dynamic updates can now optionally set the zone's SOA serial number to the current UNIX time. * DLZ modules can now retrieve the source IP address of the querying client. * 'request-ixfr' option can now be set at the per-zone level. * 'dig +rrcomments' turns on comments about DNSKEY records, indicating their key ID, algorithm and function * Simplified nsupdate syntax and added readline support BIND 9.8.0 BIND 9.8.0 includes a number of changes from BIND 9.7 and earlier releases. New features include: * Built-in trust anchor for the root zone, which can be switched on via "dnssec-validation auto;" * Support for DNS64. * Support for response policy zones (RPZ). * Support for writable DLZ zones. * Improved ease of configuration of GSS/TSIG for interoperability with Active Directory * Support for GOST signing algorithm for DNSSEC. * Removed RTT Banding from server selection algorithm. * New "static-stub" zone type. * Allow configuration of resolver timeouts via "resolver-query-timeout" option. * The DLZ "dlopen" driver is now built by default. * Added a new include file with function typedefs for the DLZ "dlopen" driver. * Made "--with-gssapi" default. * More verbose error reporting from DLZ LDAP. BIND 9.7.0 BIND 9.7.0 includes a number of changes from BIND 9.6 and earlier releases. Most are intended to simplify DNSSEC configuration. New features include: * Fully automatic signing of zones by "named". * Simplified configuration of DNSSEC Lookaside Validation (DLV). * Simplified configuration of Dynamic DNS, using the "ddns-confgen" command line tool or the "local" update-policy option. (As a side effect, this also makes it easier to configure automatic zone re-signing.) * New named option "attach-cache" that allows multiple views to share a single cache. * DNS rebinding attack prevention. * New default values for dnssec-keygen parameters. * Support for RFC 5011 automated trust anchor maintenance * Smart signing: simplified tools for zone signing and key maintenance. * The "statistics-channels" option is now available on Windows. * A new DNSSEC-aware libdns API for use by non-BIND9 applications * On some platforms, named and other binaries can now print out a stack backtrace on assertion failure, to aid in debugging. * A "tools only" installation mode on Windows, which only installs dig, host, nslookup and nsupdate. * Improved PKCS#11 support, including Keyper support and explicit OpenSSL engine selection. BIND 9.6.0 * Full NSEC3 support * Automatic zone re-signing * New update-policy methods tcp-self and 6to4-self * The BIND 8 resolver library, libbind, has been removed from the BIND 9 distribution and is now available as a separate download. * Change the default pid file location from /var/run to /var/run/ {named,lwresd} for improved chroot/setuid support. BIND 9.5.0 * GSS-TSIG support (RFC 3645). * DHCID support. * Experimental http server and statistics support for named via xml. * More detailed statistics counters including those supported in BIND 8. * Faster ACL processing. * Use Doxygen to generate internal documentation. * Efficient LRU cache-cleaning mechanism. * NSID support. BIND 9.4.0 * Implemented "additional section caching (or acache)", an internal cache framework for additional section content to improve response performance. Several configuration options were provided to control the behavior. * New notify type 'master-only'. Enable notify for master zones only. * Accept 'notify-source' style syntax for query-source. * rndc now allows addresses to be set in the server clauses. * New option "allow-query-cache". This lets "allow-query" be used to specify the default zone access level rather than having to have every zone override the global value. "allow-query-cache" can be set at both the options and view levels. If "allow-query-cache" is not set then "allow-recursion" is used if set, otherwise "allow-query" is used if set unless "recursion no;" is set in which case "none;" is used, otherwise the default (localhost; localnets;) is used. * rndc: the source address can now be specified. * ixfr-from-differences now takes master and slave in addition to yes and no at the options and view levels. * Allow the journal's name to be changed via named.conf. * 'rndc notify zone [class [view]]' resend the NOTIFY messages for the specified zone. * 'dig +trace' now randomly selects the next servers to try. Report if there is a bad delegation. * Improve check-names error messages. * Make public the function to read a key file, dst_key_read_public(). * dig now returns the byte count for axfr/ixfr. * allow-update is now settable at the options / view level. * named-checkconf now checks the logging configuration. * host now can turn on memory debugging flags with '-m'. * Don't send notify messages to self. * Perform sanity checks on NS records which refer to 'in zone' names. * New zone option "notify-delay". Specify a minimum delay between sets of NOTIFY messages. * Extend adjusting TTL warning messages. * Named and named-checkzone can now both check for non-terminal wildcard records. * "rndc freeze/thaw" now freezes/thaws all zones. * named-checkconf now check acls to verify that they only refer to existing acls. * The server syntax has been extended to support a range of servers. * Report differences between hints and real NS rrset and associated address records. * Preserve the case of domain names in rdata during zone transfers. * Restructured the data locking framework using architecture dependent atomic operations (when available), improving response performance on multi-processor machines significantly. x86, x86_64, alpha, powerpc, and mips are currently supported. * UNIX domain controls are now supported. * Add support for additional zone file formats for improving loading performance. The masterfile-format option in named.conf can be used to specify a non-default format. A separate command named-compilezone was provided to generate zone files in the new format. Additionally, the -I and -O options for dnssec-signzone specify the input and output formats. * dnssec-signzone can now randomize signature end times (dnssec-signzone -j jitter). * Add support for CH A record. * Add additional zone data constancy checks. named-checkzone has extended checking of NS, MX and SRV record and the hosts they reference. named has extended post zone load checks. New zone options: check-mx and integrity-check. * edns-udp-size can now be overridden on a per server basis. * dig can now specify the EDNS version when making a query. * Added framework for handling multiple EDNS versions. * Additional memory debugging support to track size and mctx arguments. * Detect duplicates of UDP queries we are recursing on and drop them. New stats category "duplicates". * "USE INTERNAL MALLOC" is now runtime selectable. * The lame cache is now done on a basis as some servers only appear to be lame for certain query types. * Limit the number of recursive clients that can be waiting for a single query () to resolve. New options clients-per-query and max-clients-per-query. * dig: report the number of extra bytes still left in the packet after processing all the records. * Support for IPSECKEY rdata type. * Raise the UDP recieve buffer size to 32k if it is less than 32k. * x86 and x86_64 now have seperate atomic locking implementations. * named-checkconf now validates update-policy entries. * Attempt to make the amount of work performed in a iteration self tuning. The covers nodes clean from the cache per iteration, nodes written to disk when rewriting a master file and nodes destroyed per iteration when destroying a zone or a cache. * ISC string copy API. * Automatic empty zone creation for D.F.IP6.ARPA and friends. Note: RFC 1918 zones are not yet covered by this but are likely to be in a future release. * New options: empty-server, empty-contact, empty-zones-enable and disable-empty-zone. * dig now has a '-q queryname' and '+showsearch' options. * host/nslookup now continue (default)/fail on SERVFAIL. * dig now warns if 'RA' is not set in the answer when 'RD' was set in the query. host/nslookup skip servers that fail to set 'RA' when 'RD' is set unless a server is explicitly set. * Integrate contibuted DLZ code into named. * Integrate contibuted IDN code from JPNIC. * libbind: corresponds to that from BIND 8.4.7. BIND 9.3.0 * DNSSEC is now DS based (RFC 3658). * DNSSEC lookaside validation. * check-names is now implemented. * rrset-order is more complete. * IPv4/IPv6 transition support, dual-stack-servers. * IXFR deltas can now be generated when loading master files, ixfr-from-differences. * It is now possible to specify the size of a journal, max-journal-size. * It is now possible to define a named set of master servers to be used in masters clause, masters. * The advertised EDNS UDP size can now be set, edns-udp-size. * allow-v6-synthesis has been obsoleted. * Zones containing MD and MF will now be rejected. * dig, nslookup name. now report "Not Implemented" as NOTIMP rather than NOTIMPL. This will have impact on scripts that are looking for NOTIMPL. * libbind: corresponds to that from BIND 8.4.5. BIND 9.2.0 * The size of the cache can now be limited using the "max-cache-size" option. * The server can now automatically convert RFC1886-style recursive lookup requests into RFC2874-style lookups, when enabled using the new option "allow-v6-synthesis". This allows stub resolvers that support AAAA records but not A6 record chains or binary labels to perform lookups in domains that make use of these IPv6 DNS features. * Performance has been improved. * The man pages now use the more portable "man" macros rather than the "mandoc" macros, and are installed by "make install". * The named.conf parser has been completely rewritten. It now supports "include" directives in more places such as inside "view" statements, and it no longer has any reserved words. * The "rndc status" command is now implemented. * rndc can now be configured automatically. * A BIND 8 compatible stub resolver library is now included in lib/bind. * OpenSSL has been removed from the distribution. This means that to use DNSSEC, OpenSSL must be installed and the --with-openssl option must be supplied to configure. This does not apply to the use of TSIG, which does not require OpenSSL. * The source distribution now builds on Windows. See win32utils/ readme1.txt and win32utils/win32-build.txt for details. * This distribution also includes a new lightweight stub resolver library and associated resolver daemon that fully support forward and reverse lookups of both IPv4 and IPv6 addresses. This library is considered experimental and is not a complete replacement for the BIND 8 resolver library. Applications that use the BIND 8 res_* functions to perform DNS lookups or dynamic updates still need to be linked against the BIND 8 libraries. For DNS lookups, they can also use the new "getrrsetbyname()" API. * BIND 9.2 is capable of acting as an authoritative server for DNSSEC secured zones. This functionality is believed to be stable and complete except for lacking support for verifications involving wildcard records in secure zones. * When acting as a caching server, BIND 9.2 can be configured to perform DNSSEC secure resolution on behalf of its clients. This part of the DNSSEC implementation is still considered experimental. For detailed information about the state of the DNSSEC implementation, see the file doc/misc/dnssec. bind9-9.11.3+dfsg/HISTORY.md000066400000000000000000000504371325250447100152300ustar00rootroot00000000000000 ### Functional enhancements from prior major releases of BIND 9 #### BIND 9.10.0 BIND 9.10.0 includes a number of changes from BIND 9.9 and earlier releases. New features include: - DNS Response-rate limiting (DNS RRL), which blunts the impact of reflection and amplification attacks, is always compiled in and no longer requires a compile-time option to enable it. - An experimental "Source Identity Token" (SIT) EDNS option is now available. Similar to DNS Cookies as invented by Donald Eastlake 3rd, these are designed to enable clients to detect off-path spoofed responses, and to enable servers to detect spoofed-source queries. Servers can be configured to send smaller responses to clients that have not identified themselves using a SIT option, reducing the effectiveness of amplification attacks. RRL processing has also been updated; clients proven to be legitimate via SIT are not subject to rate limiting. Use "configure --enable-sit" to enable this feature in BIND. - A new zone file format, "map", stores zone data in a format that can be mapped directly into memory, allowing significantly faster zone loading. - "delv" (domain entity lookup and validation) is a new tool with dig-like semantics for looking up DNS data and performing internal DNSSEC validation. This allows easy validation in environments where the resolver may not be trustworthy, and assists with troubleshooting of DNSSEC problems. (NOTE: In previous development releases of BIND 9.10, this utility was called "delve". The spelling has been changed to avoid confusion with the "delve" utility included with the Xapian search engine.) - Improved EDNS(0) processing for better resolver performance and reliability over slow or lossy connections. - A new "configure --with-tuning=large" option tunes certain compiled-in constants and default settings to values better suited to large servers with abundant memory. This can improve performance on such servers, but will consume more memory and may degrade performance on smaller systems. - Substantial improvement in response-policy zone (RPZ) performance. Up to 32 response-policy zones can be configured with minimal performance loss. - To improve recursive resolver performance, cache records which are still being requested by clients can now be automatically refreshed from the authoritative server before they expire, reducing or eliminating the time window in which no answer is available in the cache. - New "rpz-client-ip" triggers and drop policies allowing response policies based on the IP address of the client. - ACLs can now be specified based on geographic location using the MaxMind GeoIP databases. Use "configure --with-geoip" to enable. - Zone data can now be shared between views, allowing multiple views to serve the same zones authoritatively without storing multiple copies in memory. - New XML schema (version 3) for the statistics channel includes many new statistics and uses a flattened XML tree for faster parsing. The older schema is now deprecated. - A new stylesheet, based on the Google Charts API, displays XML statistics in charts and graphs on javascript-enabled browsers. - The statistics channel can now provide data in JSON format as well as XML. - New stats counters track TCP and UDP queries received per zone, and EDNS options received in total. - The internal and export versions of the BIND libraries (libisc, libdns, etc) have been unified so that external library clients can use the same libraries as BIND itself. - A new compile-time option, "configure --enable-native-pkcs11", allows BIND 9 cryptography functions to use the PKCS#11 API natively, so that BIND can drive a cryptographic hardware service module (HSM) directly instead of using a modified OpenSSL as an intermediary. (Note: This feature requires an HSM to have a full implementation of the PKCS#11 API; many current HSMs only have partial implementations. The new "pkcs11-tokens" command can be used to check API completeness. Native PKCS#11 is known to work with the Thales nShield HSM and with SoftHSM version 2 from the Open DNSSEC project.) - The new "max-zone-ttl" option enforces maximum TTLs for zones. This can simplify the process of rolling DNSSEC keys by guaranteeing that cached signatures will have expired within the specified amount of time. - "dig +subnet" sends an EDNS CLIENT-SUBNET option when querying. - "dig +expire" sends an EDNS EXPIRE option when querying. When this option is sent with an SOA query to a server that supports it, it will report the expiry time of a slave zone. - New "dnssec-coverage" tool to check DNSSEC key coverage for a zone and report if a lapse in signing coverage has been inadvertently scheduled. - Signing algorithm flexibility and other improvements for the "rndc" control channel. - "named-checkzone" and "named-compilezone" can now read journal files, allowing them to process dynamic zones. - Multiple DLZ databases can now be configured. Individual zones can be configured to be served from a specific DLZ database. DLZ databases now serve zones of type "master" and "redirect". - "rndc zonestatus" reports information about a specified zone. - "named" now listens on IPv6 as well as IPv4 interfaces by default. - "named" now preserves the capitalization of names when responding to queries: for instance, a query for "example.com" may be answered with "example.COM" if the name was configured that way in the zone file. Some clients have a bug causing them to depend on the older behavior, in which the case of the answer always matched the case of the query, rather than the case of the name configured in the DNS. Such clients can now be specified in the new "no-case-compress" ACL; this will restore the older behavior of "named" for those clients only. - new "dnssec-importkey" command allows the use of offline DNSSEC keys with automatic DNSKEY management. - New "named-rrchecker" tool to verify the syntactic correctness of individual resource records. - When re-signing a zone, the new "dnssec-signzone -Q" option drops signatures from keys that are still published but are no longer active. - "named-checkconf -px" will print the contents of configuration files with the shared secrets obscured, making it easier to share configuration (e.g. when submitting a bug report) without revealing private information. - "rndc scan" causes named to re-scan network interfaces for changes in local addresses. - On operating systems with support for routing sockets, network interfaces are re-scanned automatically whenever they change. - "tsig-keygen" is now available as an alternate command name to use for "ddns-confgen". #### BIND 9.9.0 BIND 9.9.0 includes a number of changes from BIND 9.8 and earlier releases. New features include: - Inline signing, allowing automatic DNSSEC signing of master zones without modification of the zonefile, or "bump in the wire" signing in slaves. - NXDOMAIN redirection. - New 'rndc flushtree' command clears all data under a given name from the DNS cache. - New 'rndc sync' command dumps pending changes in a dynamic zone to disk without a freeze/thaw cycle. - New 'rndc signing' command displays or clears signing status records in 'auto-dnssec' zones. - NSEC3 parameters for 'auto-dnssec' zones can now be set prior to signing, eliminating the need to initially sign with NSEC. - Startup time improvements on large authoritative servers. - Slave zones are now saved in raw format by default. - Several improvements to response policy zones (RPZ). - Improved hardware scalability by using multiple threads to listen for queries and using finer-grained client locking - The 'also-notify' option now takes the same syntax as 'masters', so it can used named masterlists and TSIG keys. - 'dnssec-signzone -D' writes an output file containing only DNSSEC data, which can be included by the primary zone file. - 'dnssec-signzone -R' forces removal of signatures that are not expired but were created by a key which no longer exists. - 'dnssec-signzone -X' allows a separate expiration date to be specified for DNSKEY signatures from other signatures. - New '-L' option to dnssec-keygen, dnssec-settime, and dnssec-keyfromlabel sets the default TTL for the key. - dnssec-dsfromkey now supports reading from standard input, to make it easier to convert DNSKEY to DS. - RFC 1918 reverse zones have been added to the empty-zones table per RFC 6303. - Dynamic updates can now optionally set the zone's SOA serial number to the current UNIX time. - DLZ modules can now retrieve the source IP address of the querying client. - 'request-ixfr' option can now be set at the per-zone level. - 'dig +rrcomments' turns on comments about DNSKEY records, indicating their key ID, algorithm and function - Simplified nsupdate syntax and added readline support #### BIND 9.8.0 BIND 9.8.0 includes a number of changes from BIND 9.7 and earlier releases. New features include: - Built-in trust anchor for the root zone, which can be switched on via "dnssec-validation auto;" - Support for DNS64. - Support for response policy zones (RPZ). - Support for writable DLZ zones. - Improved ease of configuration of GSS/TSIG for interoperability with Active Directory - Support for GOST signing algorithm for DNSSEC. - Removed RTT Banding from server selection algorithm. - New "static-stub" zone type. - Allow configuration of resolver timeouts via "resolver-query-timeout" option. - The DLZ "dlopen" driver is now built by default. - Added a new include file with function typedefs for the DLZ "dlopen" driver. - Made "--with-gssapi" default. - More verbose error reporting from DLZ LDAP. #### BIND 9.7.0 BIND 9.7.0 includes a number of changes from BIND 9.6 and earlier releases. Most are intended to simplify DNSSEC configuration. New features include: - Fully automatic signing of zones by "named". - Simplified configuration of DNSSEC Lookaside Validation (DLV). - Simplified configuration of Dynamic DNS, using the "ddns-confgen" command line tool or the "local" update-policy option. (As a side effect, this also makes it easier to configure automatic zone re-signing.) - New named option "attach-cache" that allows multiple views to share a single cache. - DNS rebinding attack prevention. - New default values for dnssec-keygen parameters. - Support for RFC 5011 automated trust anchor maintenance - Smart signing: simplified tools for zone signing and key maintenance. - The "statistics-channels" option is now available on Windows. - A new DNSSEC-aware libdns API for use by non-BIND9 applications - On some platforms, named and other binaries can now print out a stack backtrace on assertion failure, to aid in debugging. - A "tools only" installation mode on Windows, which only installs dig, host, nslookup and nsupdate. - Improved PKCS#11 support, including Keyper support and explicit OpenSSL engine selection. #### BIND 9.6.0 - Full NSEC3 support - Automatic zone re-signing - New update-policy methods tcp-self and 6to4-self - The BIND 8 resolver library, libbind, has been removed from the BIND 9 distribution and is now available as a separate download. - Change the default pid file location from /var/run to /var/run/{named,lwresd} for improved chroot/setuid support. #### BIND 9.5.0 - GSS-TSIG support (RFC 3645). - DHCID support. - Experimental http server and statistics support for named via xml. - More detailed statistics counters including those supported in BIND 8. - Faster ACL processing. - Use Doxygen to generate internal documentation. - Efficient LRU cache-cleaning mechanism. - NSID support. BIND 9.4.0 - Implemented "additional section caching (or acache)", an internal cache framework for additional section content to improve response performance. Several configuration options were provided to control the behavior. - New notify type 'master-only'. Enable notify for master zones only. - Accept 'notify-source' style syntax for query-source. - rndc now allows addresses to be set in the server clauses. - New option "allow-query-cache". This lets "allow-query" be used to specify the default zone access level rather than having to have every zone override the global value. "allow-query-cache" can be set at both the options and view levels. If "allow-query-cache" is not set then "allow-recursion" is used if set, otherwise "allow-query" is used if set unless "recursion no;" is set in which case "none;" is used, otherwise the default (localhost; localnets;) is used. - rndc: the source address can now be specified. - ixfr-from-differences now takes master and slave in addition to yes and no at the options and view levels. - Allow the journal's name to be changed via named.conf. - 'rndc notify zone [class [view]]' resend the NOTIFY messages for the specified zone. - 'dig +trace' now randomly selects the next servers to try. Report if there is a bad delegation. - Improve check-names error messages. - Make public the function to read a key file, dst_key_read_public(). - dig now returns the byte count for axfr/ixfr. - allow-update is now settable at the options / view level. - named-checkconf now checks the logging configuration. - host now can turn on memory debugging flags with '-m'. - Don't send notify messages to self. - Perform sanity checks on NS records which refer to 'in zone' names. - New zone option "notify-delay". Specify a minimum delay between sets of NOTIFY messages. - Extend adjusting TTL warning messages. - Named and named-checkzone can now both check for non-terminal wildcard records. - "rndc freeze/thaw" now freezes/thaws all zones. - named-checkconf now check acls to verify that they only refer to existing acls. - The server syntax has been extended to support a range of servers. - Report differences between hints and real NS rrset and associated address records. - Preserve the case of domain names in rdata during zone transfers. - Restructured the data locking framework using architecture dependent atomic operations (when available), improving response performance on multi-processor machines significantly. x86, x86_64, alpha, powerpc, and mips are currently supported. - UNIX domain controls are now supported. - Add support for additional zone file formats for improving loading performance. The masterfile-format option in named.conf can be used to specify a non-default format. A separate command named-compilezone was provided to generate zone files in the new format. Additionally, the -I and -O options for dnssec-signzone specify the input and output formats. - dnssec-signzone can now randomize signature end times (dnssec-signzone -j jitter). - Add support for CH A record. - Add additional zone data constancy checks. named-checkzone has extended checking of NS, MX and SRV record and the hosts they reference. named has extended post zone load checks. New zone options: check-mx and integrity-check. - edns-udp-size can now be overridden on a per server basis. - dig can now specify the EDNS version when making a query. - Added framework for handling multiple EDNS versions. - Additional memory debugging support to track size and mctx arguments. - Detect duplicates of UDP queries we are recursing on and drop them. New stats category "duplicates". - "USE INTERNAL MALLOC" is now runtime selectable. - The lame cache is now done on a basis as some servers only appear to be lame for certain query types. - Limit the number of recursive clients that can be waiting for a single query () to resolve. New options clients-per-query and max-clients-per-query. - dig: report the number of extra bytes still left in the packet after processing all the records. - Support for IPSECKEY rdata type. - Raise the UDP recieve buffer size to 32k if it is less than 32k. - x86 and x86_64 now have seperate atomic locking implementations. - named-checkconf now validates update-policy entries. - Attempt to make the amount of work performed in a iteration self tuning. The covers nodes clean from the cache per iteration, nodes written to disk when rewriting a master file and nodes destroyed per iteration when destroying a zone or a cache. - ISC string copy API. - Automatic empty zone creation for D.F.IP6.ARPA and friends. Note: RFC 1918 zones are not yet covered by this but are likely to be in a future release. - New options: empty-server, empty-contact, empty-zones-enable and disable-empty-zone. - dig now has a '-q queryname' and '+showsearch' options. - host/nslookup now continue (default)/fail on SERVFAIL. - dig now warns if 'RA' is not set in the answer when 'RD' was set in the query. host/nslookup skip servers that fail to set 'RA' when 'RD' is set unless a server is explicitly set. - Integrate contibuted DLZ code into named. - Integrate contibuted IDN code from JPNIC. - libbind: corresponds to that from BIND 8.4.7. #### BIND 9.3.0 - DNSSEC is now DS based (RFC 3658). - DNSSEC lookaside validation. - check-names is now implemented. - rrset-order is more complete. - IPv4/IPv6 transition support, dual-stack-servers. - IXFR deltas can now be generated when loading master files, ixfr-from-differences. - It is now possible to specify the size of a journal, max-journal-size. - It is now possible to define a named set of master servers to be used in masters clause, masters. - The advertised EDNS UDP size can now be set, edns-udp-size. - allow-v6-synthesis has been obsoleted. - Zones containing MD and MF will now be rejected. - dig, nslookup name. now report "Not Implemented" as NOTIMP rather than NOTIMPL. This will have impact on scripts that are looking for NOTIMPL. - libbind: corresponds to that from BIND 8.4.5. #### BIND 9.2.0 - The size of the cache can now be limited using the "max-cache-size" option. - The server can now automatically convert RFC1886-style recursive lookup requests into RFC2874-style lookups, when enabled using the new option "allow-v6-synthesis". This allows stub resolvers that support AAAA records but not A6 record chains or binary labels to perform lookups in domains that make use of these IPv6 DNS features. - Performance has been improved. - The man pages now use the more portable "man" macros rather than the "mandoc" macros, and are installed by "make install". - The named.conf parser has been completely rewritten. It now supports "include" directives in more places such as inside "view" statements, and it no longer has any reserved words. - The "rndc status" command is now implemented. - rndc can now be configured automatically. - A BIND 8 compatible stub resolver library is now included in lib/bind. - OpenSSL has been removed from the distribution. This means that to use DNSSEC, OpenSSL must be installed and the --with-openssl option must be supplied to configure. This does not apply to the use of TSIG, which does not require OpenSSL. - The source distribution now builds on Windows. See win32utils/readme1.txt and win32utils/win32-build.txt for details. - This distribution also includes a new lightweight stub resolver library and associated resolver daemon that fully support forward and reverse lookups of both IPv4 and IPv6 addresses. This library is considered experimental and is not a complete replacement for the BIND 8 resolver library. Applications that use the BIND 8 `res_*` functions to perform DNS lookups or dynamic updates still need to be linked against the BIND 8 libraries. For DNS lookups, they can also use the new "getrrsetbyname()" API. - BIND 9.2 is capable of acting as an authoritative server for DNSSEC secured zones. This functionality is believed to be stable and complete except for lacking support for verifications involving wildcard records in secure zones. - When acting as a caching server, BIND 9.2 can be configured to perform DNSSEC secure resolution on behalf of its clients. This part of the DNSSEC implementation is still considered experimental. For detailed information about the state of the DNSSEC implementation, see the file doc/misc/dnssec. bind9-9.11.3+dfsg/Kyuafile000066400000000000000000000000671325250447100152330ustar00rootroot00000000000000syntax(2) test_suite('bind9') include('lib/Kyuafile') bind9-9.11.3+dfsg/LICENSE000066400000000000000000000370611325250447100145500ustar00rootroot00000000000000Mozilla Public License, version 2.0 1. Definitions 1.1. "Contributor" means each individual or legal entity that creates, contributes to the creation of, or owns Covered Software. 1.2. "Contributor Version" means the combination of the Contributions of others (if any) used by a Contributor and that particular Contributor's Contribution. 1.3. "Contribution" means Covered Software of a particular Contributor. 1.4. "Covered Software" means Source Code Form to which the initial Contributor has attached the notice in Exhibit A, the Executable Form of such Source Code Form, and Modifications of such Source Code Form, in each case including portions thereof. 1.5. "Incompatible With Secondary Licenses" means a. that the initial Contributor has attached the notice described in Exhibit B to the Covered Software; or b. that the Covered Software was made available under the terms of version 1.1 or earlier of the License, but not also under the terms of a Secondary License. 1.6. "Executable Form" means any form of the work other than Source Code Form. 1.7. "Larger Work" means a work that combines Covered Software with other material, in a separate file or files, that is not Covered Software. 1.8. "License" means this document. 1.9. "Licensable" means having the right to grant, to the maximum extent possible, whether at the time of the initial grant or subsequently, any and all of the rights conveyed by this License. 1.10. "Modifications" means any of the following: a. any file in Source Code Form that results from an addition to, deletion from, or modification of the contents of Covered Software; or b. any new file in Source Code Form that contains any Covered Software. 1.11. "Patent Claims" of a Contributor means any patent claim(s), including without limitation, method, process, and apparatus claims, in any patent Licensable by such Contributor that would be infringed, but for the grant of the License, by the making, using, selling, offering for sale, having made, import, or transfer of either its Contributions or its Contributor Version. 1.12. "Secondary License" means either the GNU General Public License, Version 2.0, the GNU Lesser General Public License, Version 2.1, the GNU Affero General Public License, Version 3.0, or any later versions of those licenses. 1.13. "Source Code Form" means the form of the work preferred for making modifications. 1.14. "You" (or "Your") means an individual or a legal entity exercising rights under this License. For legal entities, "You" includes any entity that controls, is controlled by, or is under common control with You. For purposes of this definition, "control" means (a) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (b) ownership of more than fifty percent (50%) of the outstanding shares or beneficial ownership of such entity. 2. License Grants and Conditions 2.1. Grants Each Contributor hereby grants You a world-wide, royalty-free, non-exclusive license: a. under intellectual property rights (other than patent or trademark) Licensable by such Contributor to use, reproduce, make available, modify, display, perform, distribute, and otherwise exploit its Contributions, either on an unmodified basis, with Modifications, or as part of a Larger Work; and b. under Patent Claims of such Contributor to make, use, sell, offer for sale, have made, import, and otherwise transfer either its Contributions or its Contributor Version. 2.2. Effective Date The licenses granted in Section 2.1 with respect to any Contribution become effective for each Contribution on the date the Contributor first distributes such Contribution. 2.3. Limitations on Grant Scope The licenses granted in this Section 2 are the only rights granted under this License. No additional rights or licenses will be implied from the distribution or licensing of Covered Software under this License. Notwithstanding Section 2.1(b) above, no patent license is granted by a Contributor: a. for any code that a Contributor has removed from Covered Software; or b. for infringements caused by: (i) Your and any other third party's modifications of Covered Software, or (ii) the combination of its Contributions with other software (except as part of its Contributor Version); or c. under Patent Claims infringed by Covered Software in the absence of its Contributions. This License does not grant any rights in the trademarks, service marks, or logos of any Contributor (except as may be necessary to comply with the notice requirements in Section 3.4). 2.4. Subsequent Licenses No Contributor makes additional grants as a result of Your choice to distribute the Covered Software under a subsequent version of this License (see Section 10.2) or under the terms of a Secondary License (if permitted under the terms of Section 3.3). 2.5. Representation Each Contributor represents that the Contributor believes its Contributions are its original creation(s) or it has sufficient rights to grant the rights to its Contributions conveyed by this License. 2.6. Fair Use This License is not intended to limit any rights You have under applicable copyright doctrines of fair use, fair dealing, or other equivalents. 2.7. Conditions Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in Section 2.1. 3. Responsibilities 3.1. Distribution of Source Form All distribution of Covered Software in Source Code Form, including any Modifications that You create or to which You contribute, must be under the terms of this License. You must inform recipients that the Source Code Form of the Covered Software is governed by the terms of this License, and how they can obtain a copy of this License. You may not attempt to alter or restrict the recipients' rights in the Source Code Form. 3.2. Distribution of Executable Form If You distribute Covered Software in Executable Form then: a. such Covered Software must also be made available in Source Code Form, as described in Section 3.1, and You must inform recipients of the Executable Form how they can obtain a copy of such Source Code Form by reasonable means in a timely manner, at a charge no more than the cost of distribution to the recipient; and b. You may distribute such Executable Form under the terms of this License, or sublicense it under different terms, provided that the license for the Executable Form does not attempt to limit or alter the recipients' rights in the Source Code Form under this License. 3.3. Distribution of a Larger Work You may create and distribute a Larger Work under terms of Your choice, provided that You also comply with the requirements of this License for the Covered Software. If the Larger Work is a combination of Covered Software with a work governed by one or more Secondary Licenses, and the Covered Software is not Incompatible With Secondary Licenses, this License permits You to additionally distribute such Covered Software under the terms of such Secondary License(s), so that the recipient of the Larger Work may, at their option, further distribute the Covered Software under the terms of either this License or such Secondary License(s). 3.4. Notices You may not remove or alter the substance of any license notices (including copyright notices, patent notices, disclaimers of warranty, or limitations of liability) contained within the Source Code Form of the Covered Software, except that You may alter any license notices to the extent required to remedy known factual inaccuracies. 3.5. Application of Additional Terms You may choose to offer, and to charge a fee for, warranty, support, indemnity or liability obligations to one or more recipients of Covered Software. However, You may do so only on Your own behalf, and not on behalf of any Contributor. You must make it absolutely clear that any such warranty, support, indemnity, or liability obligation is offered by You alone, and You hereby agree to indemnify every Contributor for any liability incurred by such Contributor as a result of warranty, support, indemnity or liability terms You offer. You may include additional disclaimers of warranty and limitations of liability specific to any jurisdiction. 4. Inability to Comply Due to Statute or Regulation If it is impossible for You to comply with any of the terms of this License with respect to some or all of the Covered Software due to statute, judicial order, or regulation then You must: (a) comply with the terms of this License to the maximum extent possible; and (b) describe the limitations and the code they affect. Such description must be placed in a text file included with all distributions of the Covered Software under this License. Except to the extent prohibited by statute or regulation, such description must be sufficiently detailed for a recipient of ordinary skill to be able to understand it. 5. Termination 5.1. The rights granted under this License will terminate automatically if You fail to comply with any of its terms. However, if You become compliant, then the rights granted under this License from a particular Contributor are reinstated (a) provisionally, unless and until such Contributor explicitly and finally terminates Your grants, and (b) on an ongoing basis, if such Contributor fails to notify You of the non-compliance by some reasonable means prior to 60 days after You have come back into compliance. Moreover, Your grants from a particular Contributor are reinstated on an ongoing basis if such Contributor notifies You of the non-compliance by some reasonable means, this is the first time You have received notice of non-compliance with this License from such Contributor, and You become compliant prior to 30 days after Your receipt of the notice. 5.2. If You initiate litigation against any entity by asserting a patent infringement claim (excluding declaratory judgment actions, counter-claims, and cross-claims) alleging that a Contributor Version directly or indirectly infringes any patent, then the rights granted to You by any and all Contributors for the Covered Software under Section 2.1 of this License shall terminate. 5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user license agreements (excluding distributors and resellers) which have been validly granted by You or Your distributors under this License prior to termination shall survive termination. 6. Disclaimer of Warranty Covered Software is provided under this License on an "as is" basis, without warranty of any kind, either expressed, implied, or statutory, including, without limitation, warranties that the Covered Software is free of defects, merchantable, fit for a particular purpose or non-infringing. The entire risk as to the quality and performance of the Covered Software is with You. Should any Covered Software prove defective in any respect, You (not any Contributor) assume the cost of any necessary servicing, repair, or correction. This disclaimer of warranty constitutes an essential part of this License. No use of any Covered Software is authorized under this License except under this disclaimer. 7. Limitation of Liability Under no circumstances and under no legal theory, whether tort (including negligence), contract, or otherwise, shall any Contributor, or anyone who distributes Covered Software as permitted above, be liable to You for any direct, indirect, special, incidental, or consequential damages of any character including, without limitation, damages for lost profits, loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses, even if such party shall have been informed of the possibility of such damages. This limitation of liability shall not apply to liability for death or personal injury resulting from such party's negligence to the extent applicable law prohibits such limitation. Some jurisdictions do not allow the exclusion or limitation of incidental or consequential damages, so this exclusion and limitation may not apply to You. 8. Litigation Any litigation relating to this License may be brought only in the courts of a jurisdiction where the defendant maintains its principal place of business and such litigation shall be governed by laws of that jurisdiction, without reference to its conflict-of-law provisions. Nothing in this Section shall prevent a party's ability to bring cross-claims or counter-claims. 9. Miscellaneous This License represents the complete agreement concerning the subject matter hereof. If any provision of this License is held to be unenforceable, such provision shall be reformed only to the extent necessary to make it enforceable. Any law or regulation which provides that the language of a contract shall be construed against the drafter shall not be used to construe this License against a Contributor. 10. Versions of the License 10.1. New Versions Mozilla Foundation is the license steward. Except as provided in Section 10.3, no one other than the license steward has the right to modify or publish new versions of this License. Each version will be given a distinguishing version number. 10.2. Effect of New Versions You may distribute the Covered Software under the terms of the version of the License under which You originally received the Covered Software, or under the terms of any subsequent version published by the license steward. 10.3. Modified Versions If you create software not governed by this License, and you want to create a new license for such software, you may create and use a modified version of this License if you rename the license and remove any references to the name of the license steward (except to note that such modified license differs from this License). 10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses If You choose to distribute Source Code Form that is Incompatible With Secondary Licenses under the terms of this version of the License, the notice described in Exhibit B of this License must be attached. Exhibit A - Source Code Form License Notice This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. If it is not possible or desirable to put the notice in a particular file, then You may include the notice in a location (such as a LICENSE file in a relevant directory) where a recipient would be likely to look for such a notice. You may add additional accurate notices of copyright ownership. Exhibit B - "Incompatible With Secondary Licenses" Notice This Source Code Form is "Incompatible With Secondary Licenses", as defined by the Mozilla Public License, v. 2.0. bind9-9.11.3+dfsg/Makefile.in000066400000000000000000000067071325250447100156130ustar00rootroot00000000000000# Copyright (C) 1998-2002, 2004-2009, 2011-2017 Internet Systems Consortium, Inc. ("ISC") # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. srcdir = @srcdir@ VPATH = @srcdir@ top_srcdir = @top_srcdir@ VERSION=@BIND9_VERSION@ SUBDIRS = make unit lib bin doc TARGETS = PREREQS = bind.keys.h MANPAGES = isc-config.sh.1 HTMLPAGES = isc-config.sh.html MANOBJS = README HISTORY OPTIONS ${MANPAGES} ${HTMLPAGES} @BIND9_MAKE_RULES@ newrr: cd lib/dns; ${MAKE} newrr bind.keys.h: ${top_srcdir}/bind.keys ${srcdir}/util/bindkeys.pl ${PERL} ${srcdir}/util/bindkeys.pl < ${top_srcdir}/bind.keys > $@ distclean:: rm -f config.cache config.h config.log config.status TAGS rm -f libtool isc-config.sh configure.lineno rm -f util/conf.sh docutil/docbook2man-wrapper.sh # XXX we should clean libtool stuff too. Only do this after we add rules # to make it. maintainer-clean:: rm -f configure rm -f bind.keys.h docclean manclean maintainer-clean:: rm -f ${MANOBJS} doc man:: ${MANOBJS} installdirs: $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${bindir} \ ${DESTDIR}${localstatedir}/run ${DESTDIR}${sysconfdir} $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${mandir}/man1 install:: isc-config.sh installdirs ${INSTALL_SCRIPT} isc-config.sh ${DESTDIR}${bindir} rm -f ${DESTDIR}${bindir}/bind9-config @LN@ ${DESTDIR}${bindir}/isc-config.sh ${DESTDIR}${bindir}/bind9-config ${INSTALL_DATA} ${top_srcdir}/isc-config.sh.1 ${DESTDIR}${mandir}/man1 rm -f ${DESTDIR}${mandir}/man1/bind9-config.1 @LN@ ${DESTDIR}${mandir}/man1/isc-config.sh.1 ${DESTDIR}${mandir}/man1/bind9-config.1 ${INSTALL_DATA} ${top_srcdir}/bind.keys ${DESTDIR}${sysconfdir} uninstall:: rm -f ${DESTDIR}${sysconfdir}/bind.keys rm -f ${DESTDIR}${mandir}/man1/bind9-config.1 rm -f ${DESTDIR}${mandir}/man1/isc-config.sh.1 rm -f ${DESTDIR}${bindir}/bind9-config rm -f ${DESTDIR}${bindir}/isc-config.sh tags: rm -f TAGS find lib bin -name "*.[ch]" -print | @ETAGS@ - test check: @if test -n "`${PERL} ${top_srcdir}/bin/tests/system/testsock.pl 2>&- || echo fail`"; then \ echo I: NOTE: The tests were not run because they require that; \ echo I: the IP addresses 10.53.0.1 through 10.53.0.8 are configured; \ echo I: as alias addresses on the loopback interface. Please run; \ echo I: \'bin/tests/system/ifconfig.sh up\' as root to configure; \ echo I: them, then rerun the tests. Run make force-test to run the; \ echo I: tests anyway.; \ exit 1; \ fi ${MAKE} test-force force-test: test-force test-force: status=0; \ (cd bin/tests && ${MAKE} ${MAKEDEFS} test) || status=1; \ (test -f unit/unittest.sh && $(SHELL) unit/unittest.sh) || status=1; \ exit $$status README: README.md ${PANDOC} --email-obfuscation=none -s -t html README.md | \ ${W3M} -dump -cols 75 -O ascii -T text/html | \ sed -e '$${/^$$/d;}' > $@ HISTORY: HISTORY.md ${PANDOC} --email-obfuscation=none -s -t html HISTORY.md | \ ${W3M} -dump -cols 75 -O ascii -T text/html | \ sed -e '$${/^$$/d;}' > $@ OPTIONS: OPTIONS.md ${PANDOC} --email-obfuscation=none -s -t html OPTIONS.md | \ ${W3M} -dump -cols 75 -O ascii -T text/html | \ sed -e '$${/^$$/d;}' > $@ CONTRIBUTING: CONTRIBUTING.md ${PANDOC} --email-obfuscation=none -s -t html CONTRIBUTING.md | \ ${W3M} -dump -cols 75 -O ascii -T text/html | \ sed -e '$${/^$$/d;}' > $@ unit:: sh ${top_srcdir}/unit/unittest.sh clean:: bind9-9.11.3+dfsg/OPTIONS000066400000000000000000000034541325250447100146200ustar00rootroot00000000000000Setting the STD_CDEFINES environment variable before running configure can be used to enable certain compile-time options that are not explicitly defined in configure. Some of these settings are: Setting Description Don't ovewrite memory when allocating or freeing -DISC_MEM_FILL=0 it; this improves performance but makes debugging more difficult. Don't track memory allocations by file and line -DISC_MEM_TRACKLINES=0 number; this improves performance but makes debugging more difficult. -DISC_FACILITY=LOG_LOCAL0 Change the default syslog facility for named -DNS_CLIENT_DROPPORT=0 Disable dropping queries from particular well-known ports: -DCHECK_SIBLING=0 Don't check sibling glue in named-checkzone -DCHECK_LOCAL=0 Don't check out-of-zone addresses in named-checkzone -DNS_RUN_PID_DIR=0 Create default PID files in ${localstatedir}/run rather than ${localstatedir}/run/{named,lwresd}/ Enable DNSSEC signature chasing support in dig. -DDIG_SIGCHASE=1 (Note: This feature is deprecated. Use delv instead.) Increase the maximum number of configurable -DNS_RPZ_MAX_ZONES=64 response policy zones from 32 to 64; this is the highest possible setting -DISC_HEAP_CHECK Test heap consistency after every heap operation; used when debugging Disable the use of inline functions to implement -DISC_BUFFER_USEINLINE=0 the isc_buffer API: this reduces performance but may be useful when debugging bind9-9.11.3+dfsg/OPTIONS.md000066400000000000000000000035041325250447100152130ustar00rootroot00000000000000 Setting the `STD_CDEFINES` environment variable before running `configure` can be used to enable certain compile-time options that are not explicitly defined in `configure`. Some of these settings are: |Setting |Description | |-----------------------------------|----------------------------------------| |`-DISC_MEM_FILL=0`|Don't ovewrite memory when allocating or freeing it; this improves performance but makes debugging more difficult.| |`-DISC_MEM_TRACKLINES=0`|Don't track memory allocations by file and line number; this improves performance but makes debugging more difficult.| |`-DISC_FACILITY=LOG_LOCAL0`|Change the default syslog facility for `named`| |`-DNS_CLIENT_DROPPORT=0`|Disable dropping queries from particular well-known ports:| |`-DCHECK_SIBLING=0`|Don't check sibling glue in `named-checkzone`| |`-DCHECK_LOCAL=0`|Don't check out-of-zone addresses in `named-checkzone`| |`-DNS_RUN_PID_DIR=0`|Create default PID files in `${localstatedir}/run` rather than `${localstatedir}/run/{named,lwresd}/`| |`-DDIG_SIGCHASE=1`|Enable DNSSEC signature chasing support in `dig`. (Note: This feature is deprecated. Use `delv` instead.)| |`-DNS_RPZ_MAX_ZONES=64`|Increase the maximum number of configurable response policy zones from 32 to 64; this is the highest possible setting| |`-DISC_HEAP_CHECK`|Test heap consistency after every heap operation; used when debugging| |`-DISC_BUFFER_USEINLINE=0`|Disable the use of inline functions to implement the `isc_buffer` API: this reduces performance but may be useful when debugging | bind9-9.11.3+dfsg/README000066400000000000000000000543431325250447100144250ustar00rootroot00000000000000BIND 9 Contents 1. Introduction 2. Reporting bugs and getting help 3. Contributing to BIND 4. BIND 9.11 features 5. Building BIND 6. macOS 7. Compile-time options 8. Automated testing 9. Documentation 10. Change log 11. Acknowledgments Introduction BIND (Berkeley Internet Name Domain) is a complete, highly portable implementation of the DNS (Domain Name System) protocol. The BIND name server, named, is able to serve as an authoritative name server, recursive resolver, DNS forwarder, or all three simultaneously. It implements views for split-horizon DNS, automatic DNSSEC zone signing and key management, catalog zones to facilitate provisioning of zone data throughout a name server constellation, response policy zones (RPZ) to protect clients from malicious data, response rate limiting (RRL) and recursive query limits to reduce distributed denial of service attacks, and many other advanced DNS features. BIND also includes a suite of administrative tools, including the dig and delv DNS lookup tools, nsupdate for dynamic DNS zone updates, rndc for remote name server administration, and more. BIND 9 is a complete re-write of the BIND architecture that was used in versions 4 and 8. Internet Systems Consortium (https://www.isc.org), a 501 (c)(3) public benefit corporation dedicated to providing software and services in support of the Internet infrastructure, developed BIND 9 and is responsible for its ongoing maintenance and improvement. BIND is open source software licenced under the terms of ISC License for all versions up to and including BIND 9.10, and the Mozilla Public License version 2.0 for all subsequent verisons. For a summary of features introduced in past major releases of BIND, see the file HISTORY. For a detailed list of changes made throughout the history of BIND 9, see the file CHANGES. See below for details on the CHANGES file format. For up-to-date release notes and errata, see http://www.isc.org/software/ bind9/releasenotes Reporting bugs and getting help To report non-security-sensitive bugs or request new features, you may open an Issue in the BIND 9 project on the ISC GitLab server at https:// gitlab.isc.org/isc-projects/bind9. Please note that, unless you explicitly mark the newly created Issue as "confidential", it will be publicly readable. Please do not include any information in bug reports that you consider to be confidential unless the issue has been marked as such. In particular, if submitting the contents of your configuration file in a non-confidential Issue, it is advisable to obscure key secrets: this can be done automatically by using named-checkconf -px. If the bug you are reporting is a potential security issue, such as an assertion failure or other crash in named, please do NOT use GitLab to report it. Instead, please send mail to security-officer@isc.org. Professional support and training for BIND are available from ISC at https://www.isc.org/support. To join the BIND Users mailing list, or view the archives, visit https:// lists.isc.org/mailman/listinfo/bind-users. If you're planning on making changes to the BIND 9 source code, you may also want to join the BIND Workers mailing list, at https://lists.isc.org/ mailman/listinfo/bind-workers. Contributing to BIND ISC maintains a public git repository for BIND; details can be found at http://www.isc.org/git/, and also on Github at https://github.com/ isc-projects. Information for BIND contributors can be found in the following files: - General information: doc/dev/contrib.md - BIND 9 code style: doc/dev/ style.md - BIND architecture and developer guide: doc/dev/dev.md Patches for BIND may be submitted as Merge Requests in the ISC GitLab server at at https://gitlab.isc.org/isc-projects/bind9/merge_requests. By default, external contributors don't have ability to fork BIND in the GitLab server, but if you wish to contribute code to BIND, you may request permission to do so. Thereafter, you can create git branches and directly submit requests that they be reviewed and merged. If you prefer, you may also submit code by opening a GitLab Issue and including your patch as an attachment, preferably generated by git format-patch. BIND 9.11 features BIND 9.11.0 includes a number of changes from BIND 9.10 and earlier releases. New features include: * Added support for Catalog Zones, a new method for provisioning servers: a list of zones to be served is stored in a DNS zone, along with their configuration parameters. Changes to the catalog zone are propagated to slaves via normal AXFR/IXFR, whereupon the zones that are listed in it are automatically added, deleted or reconfigured. * Added support for "dnstap", a fast and flexible method of capturing and logging DNS traffic. * Added support for "dyndb", a new API for loading zone data from an external database, developed by Red Hat for the FreeIPA project. * "fetchlimit" quotas are now compiled in by default. These are for the use of recursive resolvers that are are under high query load for domains whose authoritative servers are nonresponsive or are experiencing a denial of service attack: + fetches-per-server limits the number of simultaneous queries that can be sent to any single authoritative server. The configured value is a starting point; it is automatically adjusted downward if the server is partially or completely non-responsive. The algorithm used to adjust the quota can be configured via the "fetch-quota-params" option. + fetches-per-zone limits the number of simultaneous queries that can be sent for names within a single domain. (Note: Unlike fetches-per-server, this value is not self-tuning.) + New stats counters have been added to count queries spilled due to these quotas. * Added a new dnssec-keymgr key mainenance utility, which can generate or update keys as needed to ensure that a zone's keys match a defined DNSSEC policy. * The experimental "SIT" feature in BIND 9.10 has been renamed "COOKIE" and is no longer optional. EDNS COOKIE is a mechanism enabling clients to detect off-path spoofed responses, and servers to detect spoofed-source queries. Clients that identify themselves using COOKIE options are not subject to response rate limiting (RRL) and can receive larger UDP responses. * SERVFAIL responses can now be cached for a limited time (defaulting to 1 second, with an upper limit of 30). This can reduce the frequency of retries when a query is persistently failing. * Added an nsip-wait-recurse switch to RPZ. This causes NSIP rules to be skipped if a name server IP address isn't in the cache yet; the address will be looked up and the rule will be applied on future queries. * Added a Python RNDC module. This allows multiple commands to sent over a persistent RNDC channel, which saves time. * The controls block in named.conf can now grant read-only rndc access to specified clients or keys. Read-only clients could, for example, check rndc status but could not reconfigure or shut down the server. * rndc commands can now return arbitrarily large amounts of text to the caller. * The zone serial number of a dynamically updatable zone can now be set via rndc signing -serial . This allows inline-signing zones to be set to a specific serial number. * The new rndc nta command can be used to set a Negative Trust Anchor (NTA), disabling DNSSEC validation for a specific domain; this can be used when responses from a domain are known to be failing validation due to administrative error rather than because of a spoofing attack. Negative trust anchors are strictly temporary; by default they expire after one hour, but can be configured to last up to one week. * rndc delzone can now be used on zones that were not originally created by "rndc addzone". * rndc modzone reconfigures a single zone, without requiring the entire server to be reconfigured. * rndc showzone displays the current configuration of a zone. * rndc managed-keys can be used to check the status of RFC 5001 managed trust anchors, or to force trust anchors to be refreshed. * max-cache-size can now be set to a percentage of available memory. The default is 90%. * Update forwarding performance has been improved by allowing a single TCP connection to be shared by multiple updates. * The EDNS Client Subnet (ECS) option is now supported for authoritative servers; if a query contains an ECS option then ACLs containing geoip or ecs elements can match against the the address encoded in the option. This can be used to select a view for a query, so that different answers can be provided depending on the client network. * The EDNS EXPIRE option has been implemented on the client side, allowing a slave server to set the expiration timer correctly when transferring zone data from another slave server. * The key generation and manipulation tools (dnssec-keygen, dnssec-settime, dnssec-importkey, dnssec-keyfromlabel) now take -Psync and -Dsync options to set the publication and deletion times of CDS and CDNSKEY parent-synchronization records. Both named and dnssec-signzone can now publish and remove these records at the scheduled times. * A new minimal-any option reduces the size of UDP responses for query type ANY by returning a single arbitrarily selected RRset instead of all RRsets. * A new masterfile-style zone option controls the formatting of text zone files: When set to full, a zone file is dumped in single-line-per-record format. * serial-update-method can now be set to date. On update, the serial number will be set to the current date in YYYYMMDDNN format. * dnssec-signzone -N date sets the serial number to YYYYMMDDNN. * named -L causes named to send log messages to the specified file by default instead of to the system log. * dig +ttlunits prints TTL values with time-unit suffixes: w, d, h, m, s for weeks, days, hours, minutes, and seconds. * dig +unknownformat prints dig output in RFC 3597 "unknown record" presentation format. * dig +ednsopt allows dig to set arbitrary EDNS options on requests. * dig +ednsflags allows dig to set yet-to-be-defined EDNS flags on requests. * mdig is an alternate version of dig which sends multiple pipelined TCP queries to a server. Instead of waiting for a response after sending a query, it sends all queries immediately and displays responses in the order received. * serial-query-rate no longer controls NOTIFY messages. These are separately controlled by notify-rate and startup-notify-rate. * nsupdate now performs check-names processing by default on records to be added. This can be disabled with check-names no. * The statistics channel now supports DEFLATE compression, reducing the size of the data sent over the network when querying statistics. * New counters have been added to the statistics channel to track the sizes of incoming queries and outgoing responses in histogram buckets, as specified in RSSAC002. * A new NXDOMAIN redirect method (option nxdomain-redirect) has been added, allowing redirection to a specified DNS namespace instead of a single redirect zone. * When starting up, named now ensures that no other named process is already running. * Files created by named to store information, including mkeys and nzf files, are now named after their corresponding views unless the view name contains characters incompatible with use as a filename. Old style filenames (based on the hash of the view name) will still work. BIND 9.11.1 BIND 9.11.1 is a maintenance release, and addresses the security flaws disclosed in CVE-2016-6170, CVE-2016-8864, CVE-2016-9131, CVE-2016-9147, CVE-2016-9444, CVE-2016-9778, CVE-2017-3135, CVE-2017-3136, CVE-2017-3137 and CVE-2017-3138. BIND 9.11.2 BIND 9.11.2 is a maintenance release, and addresses the security flaws disclosed in CVE-2017-3140, CVE-2017-3141, CVE-2017-3142 and CVE-2017-3143. It also addresses several bugs related to the use of an LMDB database to store data related to zones added via rndc addzone or catalog zones. BIND 9.11.3 BIND 9.11.3 is a maintenance release, and addresses the security flaw disclosed in CVE-2017-3145. Building BIND BIND requires a UNIX or Linux system with an ANSI C compiler, basic POSIX support, and a 64-bit integer type. Successful builds have been observed on many versions of Linux and UNIX, including RedHat, Fedora, Debian, Ubuntu, SuSE, Slackware, FreeBSD, NetBSD, OpenBSD, Mac OS X, Solaris, HP-UX, AIX, SCO OpenServer, and OpenWRT. BIND is also available for Windows XP, 2003, 2008, and higher. See win32utils/readme1st.txt for details on building for Windows systems. To build on a UNIX or Linux system, use: $ ./configure $ make If you're planning on making changes to the BIND 9 source, you should run make depend. If you're using Emacs, you might find make tags helpful. Several environment variables that can be set before running configure will affect compilation: Variable Description CC The C compiler to use. configure tries to figure out the right one for supported systems. C compiler flags. Defaults to include -g and/or -O2 as CFLAGS supported by the compiler. Please include '-g' if you need to set CFLAGS. System header file directories. Can be used to specify STD_CINCLUDES where add-on thread or IPv6 support is, for example. Defaults to empty string. Any additional preprocessor symbols you want defined. STD_CDEFINES Defaults to empty string. For a list of possible settings, see the file OPTIONS. LDFLAGS Linker flags. Defaults to empty string. BUILD_CC Needed when cross-compiling: the native C compiler to use when building for the target system. BUILD_CFLAGS Optional, used for cross-compiling BUILD_CPPFLAGS BUILD_LDFLAGS BUILD_LIBS macOS Building on macOS assumes that the "Command Tools for Xcode" is installed. This can be downloaded from https://developer.apple.com/download/more/ or if you have Xcode already installed you can run "xcode-select --install". This will add /usr/include to the system and install the compiler and other tools so that they can be easily found. Compile-time options To see a full list of configuration options, run configure --help. On most platforms, BIND 9 is built with multithreading support, allowing it to take advantage of multiple CPUs. You can configure this by specifying --enable-threads or --disable-threads on the configure command line. The default is to enable threads, except on some older operating systems on which threads are known to have had problems in the past. (Note: Prior to BIND 9.10, the default was to disable threads on Linux systems; this has now been reversed. On Linux systems, the threaded build is known to change BIND's behavior with respect to file permissions; it may be necessary to specify a user with the -u option when running named.) To build shared libraries, specify --with-libtool on the configure command line. Certain compiled-in constants and default settings can be increased to values better suited to large servers with abundant memory resources (e.g, 64-bit servers with 12G or more of memory) by specifying --with-tuning= large on the configure command line. This can improve performance on big servers, but will consume more memory and may degrade performance on smaller systems. For the server to support DNSSEC, you need to build it with crypto support. To use OpenSSL, you should have OpenSSL 1.0.2e or newer installed. If the OpenSSL library is installed in a nonstandard location, specify the prefix using "--with-openssl=" on the configure command line. To use a PKCS#11 hardware service module for cryptographic operations, specify the path to the PKCS#11 provider library using "--with-pkcs11=", and configure BIND with "--enable-native-pkcs11". To support the HTTP statistics channel, the server must be linked with at least one of the following: libxml2 http://xmlsoft.org or json-c https:// github.com/json-c. If these are installed at a nonstandard location, specify the prefix using --with-libxml2=/prefix or --with-libjson=/prefix. To support compression on the HTTP statistics channel, the server must be linked against libzlib. If this is installed in a nonstandard location, specify the prefix using --with-zlib=/prefix. To support storing configuration data for runtime-added zones in an LMDB database, the server must be linked with liblmdb. If this is installed in a nonstandard location, specify the prefix using "with-lmdb=/prefix". To support GeoIP location-based ACLs, the server must be linked with libGeoIP. This is not turned on by default; BIND must be configured with "--with-geoip". If the library is installed in a nonstandard location, use specify the prefix using "--with-geoip=/prefix". For DNSTAP packet logging, you must have installed libfstrm https:// github.com/farsightsec/fstrm and libprotobuf-c https:// developers.google.com/protocol-buffers, and BIND must be configured with "--enable-dnstap". Portions of BIND that are written in Python, including dnssec-keymgr, dnssec-coverage, dnssec-checkds, and some of the system tests, require the 'argparse' and 'ply' modules to be available. 'argparse' is a standard module as of Python 2.7 and Python 3.2. 'ply' is available from https:// pypi.python.org/pypi/ply. On some platforms it is necessary to explicitly request large file support to handle files bigger than 2GB. This can be done by using --enable-largefile on the configure command line. Support for the "fixed" rrset-order option can be enabled or disabled by specifying --enable-fixed-rrset or --disable-fixed-rrset on the configure command line. By default, fixed rrset-order is disabled to reduce memory footprint. If your operating system has integrated support for IPv6, it will be used automatically. If you have installed KAME IPv6 separately, use --with-kame [=PATH] to specify its location. make install will install named and the various BIND 9 libraries. By default, installation is into /usr/local, but this can be changed with the --prefix option when running configure. You may specify the option --sysconfdir to set the directory where configuration files like named.conf go by default, and --localstatedir to set the default parent directory of run/named.pid. For backwards compatibility with BIND 8, --sysconfdir defaults to /etc and --localstatedir defaults to /var if no --prefix option is given. If there is a --prefix option, sysconfdir defaults to $prefix/etc and localstatedir defaults to $prefix/var. Automated testing A system test suite can be run with make test. The system tests require you to configure a set of virtual IP addresses on your system (this allows multiple servers to run locally and communicate with one another). These IP addresses can be configured by running the command bin/tests/system/ ifconfig.sh up as root. Some tests require Perl and the Net::DNS and/or IO::Socket::INET6 modules, and will be skipped if these are not available. Some tests require Python and the 'dnspython' module and will be skipped if these are not available. See bin/tests/system/README for further details. Unit tests are implemented using Automated Testing Framework (ATF). To run them, use configure --with-atf, then run make test or make unit. Documentation The BIND 9 Administrator Reference Manual is included with the source distribution, in DocBook XML, HTML and PDF format, in the doc/arm directory. Some of the programs in the BIND 9 distribution have man pages in their directories. In particular, the command line options of named are documented in bin/named/named.8. Frequently (and not-so-frequently) asked questions and their answers can be found in the ISC Knowledge Base at https://kb.isc.org. Additional information on various subjects can be found in other README files throughout the source tree. Change log A detailed list of all changes that have been made throughout the development BIND 9 is included in the file CHANGES, with the most recent changes listed first. Change notes include tags indicating the category of the change that was made; these categories are: Category Description [func] New feature [bug] General bug fix [security] Fix for a significant security flaw [experimental] Used for new features when the syntax or other aspects of the design are still in flux and may change [port] Portability enhancement [maint] Updates to built-in data such as root server addresses and keys [tuning] Changes to built-in configuration defaults and constants to improve performance [performance] Other changes to improve server performance [protocol] Updates to the DNS protocol such as new RR types [test] Changes to the automatic tests, not affecting server functionality [cleanup] Minor corrections and refactoring [doc] Documentation [contrib] Changes to the contributed tools and libraries in the 'contrib' subdirectory Used in the master development branch to reserve change [placeholder] numbers for use in other branches, e.g. when fixing a bug that only exists in older releases In general, [func] and [experimental] tags will only appear in new-feature releases (i.e., those with version numbers ending in zero). Some new functionality may be backported to older releases on a case-by-case basis. All other change types may be applied to all currently-supported releases. Acknowledgments * The original development of BIND 9 was underwritten by the following organizations: Sun Microsystems, Inc. Hewlett Packard Compaq Computer Corporation IBM Process Software Corporation Silicon Graphics, Inc. Network Associates, Inc. U.S. Defense Information Systems Agency USENIX Association Stichting NLnet - NLnet Foundation Nominum, Inc. * This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit. http://www.OpenSSL.org/ * This product includes cryptographic software written by Eric Young (eay@cryptsoft.com) * This product includes software written by Tim Hudson (tjh@cryptsoft.com) bind9-9.11.3+dfsg/README.md000066400000000000000000000572631325250447100150300ustar00rootroot00000000000000 # BIND 9 ### Contents 1. [Introduction](#intro) 1. [Reporting bugs and getting help](#help) 1. [Contributing to BIND](#contrib) 1. [BIND 9.11 features](#features) 1. [Building BIND](#build) 1. [macOS](#macos) 1. [Compile-time options](#opts) 1. [Automated testing](#testing) 1. [Documentation](#doc) 1. [Change log](#changes) 1. [Acknowledgments](#ack) ### Introduction BIND (Berkeley Internet Name Domain) is a complete, highly portable implementation of the DNS (Domain Name System) protocol. The BIND name server, `named`, is able to serve as an authoritative name server, recursive resolver, DNS forwarder, or all three simultaneously. It implements views for split-horizon DNS, automatic DNSSEC zone signing and key management, catalog zones to facilitate provisioning of zone data throughout a name server constellation, response policy zones (RPZ) to protect clients from malicious data, response rate limiting (RRL) and recursive query limits to reduce distributed denial of service attacks, and many other advanced DNS features. BIND also includes a suite of administrative tools, including the `dig` and `delv` DNS lookup tools, `nsupdate` for dynamic DNS zone updates, `rndc` for remote name server administration, and more. BIND 9 is a complete re-write of the BIND architecture that was used in versions 4 and 8. Internet Systems Consortium ([https://www.isc.org](https://www.isc.org)), a 501(c)(3) public benefit corporation dedicated to providing software and services in support of the Internet infrastructure, developed BIND 9 and is responsible for its ongoing maintenance and improvement. BIND is open source software licenced under the terms of ISC License for all versions up to and including BIND 9.10, and the Mozilla Public License version 2.0 for all subsequent verisons. For a summary of features introduced in past major releases of BIND, see the file [HISTORY](HISTORY.md). For a detailed list of changes made throughout the history of BIND 9, see the file [CHANGES](CHANGES). See [below](#changes) for details on the CHANGES file format. For up-to-date release notes and errata, see [http://www.isc.org/software/bind9/releasenotes](http://www.isc.org/software/bind9/releasenotes) ### Reporting bugs and getting help To report non-security-sensitive bugs or request new features, you may open an Issue in the BIND 9 project on the [ISC GitLab server](https://gitlab.isc.org) at [https://gitlab.isc.org/isc-projects/bind9](https://gitlab.isc.org/isc-projects/bind9). Please note that, unless you explicitly mark the newly created Issue as "confidential", it will be publicly readable. Please do not include any information in bug reports that you consider to be confidential unless the issue has been marked as such. In particular, if submitting the contents of your configuration file in a non-confidential Issue, it is advisable to obscure key secrets: this can be done automatically by using `named-checkconf -px`. If the bug you are reporting is a potential security issue, such as an assertion failure or other crash in `named`, please do *NOT* use GitLab to report it. Instead, please send mail to [security-officer@isc.org](mailto:security-officer@isc.org). Professional support and training for BIND are available from ISC at [https://www.isc.org/support](https://www.isc.org/support). To join the __BIND Users__ mailing list, or view the archives, visit [https://lists.isc.org/mailman/listinfo/bind-users](https://lists.isc.org/mailman/listinfo/bind-users). If you're planning on making changes to the BIND 9 source code, you may also want to join the __BIND Workers__ mailing list, at [https://lists.isc.org/mailman/listinfo/bind-workers](https://lists.isc.org/mailman/listinfo/bind-workers). ### Contributing to BIND ISC maintains a public git repository for BIND; details can be found at [http://www.isc.org/git/](http://www.isc.org/git/), and also on Github at [https://github.com/isc-projects](https://github.com/isc-projects). Information for BIND contributors can be found in the following files: - General information: [doc/dev/contrib.md](doc/dev/contrib.md) - BIND 9 code style: [doc/dev/style.md](doc/dev/style.md) - BIND architecture and developer guide: [doc/dev/dev.md](doc/dev/dev.md) Patches for BIND may be submitted as [Merge Requests](https://gitlab.isc.org/isc-projects/bind9/merge_requests) in the [ISC GitLab server](https://gitlab.isc.org) at at [https://gitlab.isc.org/isc-projects/bind9/merge_requests](https://gitlab.isc.org/isc-projects/bind9/merge_requests). By default, external contributors don't have ability to fork BIND in the GitLab server, but if you wish to contribute code to BIND, you may request permission to do so. Thereafter, you can create git branches and directly submit requests that they be reviewed and merged. If you prefer, you may also submit code by opening a [GitLab Issue](https://gitlab.isc.org/isc-projects/bind9/issues) and including your patch as an attachment, preferably generated by `git format-patch`. ### BIND 9.11 features BIND 9.11.0 includes a number of changes from BIND 9.10 and earlier releases. New features include: * Added support for Catalog Zones, a new method for provisioning servers: a list of zones to be served is stored in a DNS zone, along with their configuration parameters. Changes to the catalog zone are propagated to slaves via normal AXFR/IXFR, whereupon the zones that are listed in it are automatically added, deleted or reconfigured. * Added support for "dnstap", a fast and flexible method of capturing and logging DNS traffic. * Added support for "dyndb", a new API for loading zone data from an external database, developed by Red Hat for the FreeIPA project. * "fetchlimit" quotas are now compiled in by default. These are for the use of recursive resolvers that are are under high query load for domains whose authoritative servers are nonresponsive or are experiencing a denial of service attack: * `fetches-per-server` limits the number of simultaneous queries that can be sent to any single authoritative server. The configured value is a starting point; it is automatically adjusted downward if the server is partially or completely non-responsive. The algorithm used to adjust the quota can be configured via the "fetch-quota-params" option. * `fetches-per-zone` limits the number of simultaneous queries that can be sent for names within a single domain. (Note: Unlike `fetches-per-server`, this value is not self-tuning.) * New stats counters have been added to count queries spilled due to these quotas. * Added a new `dnssec-keymgr` key mainenance utility, which can generate or update keys as needed to ensure that a zone's keys match a defined DNSSEC policy. * The experimental "SIT" feature in BIND 9.10 has been renamed "COOKIE" and is no longer optional. EDNS COOKIE is a mechanism enabling clients to detect off-path spoofed responses, and servers to detect spoofed-source queries. Clients that identify themselves using COOKIE options are not subject to response rate limiting (RRL) and can receive larger UDP responses. * SERVFAIL responses can now be cached for a limited time (defaulting to 1 second, with an upper limit of 30). This can reduce the frequency of retries when a query is persistently failing. * Added an `nsip-wait-recurse` switch to RPZ. This causes NSIP rules to be skipped if a name server IP address isn't in the cache yet; the address will be looked up and the rule will be applied on future queries. * Added a Python RNDC module. This allows multiple commands to sent over a persistent RNDC channel, which saves time. * The `controls` block in named.conf can now grant read-only `rndc` access to specified clients or keys. Read-only clients could, for example, check `rndc status` but could not reconfigure or shut down the server. * `rndc` commands can now return arbitrarily large amounts of text to the caller. * The zone serial number of a dynamically updatable zone can now be set via `rndc signing -serial `. This allows inline-signing zones to be set to a specific serial number. * The new `rndc nta` command can be used to set a Negative Trust Anchor (NTA), disabling DNSSEC validation for a specific domain; this can be used when responses from a domain are known to be failing validation due to administrative error rather than because of a spoofing attack. Negative trust anchors are strictly temporary; by default they expire after one hour, but can be configured to last up to one week. * `rndc delzone` can now be used on zones that were not originally created by "rndc addzone". * `rndc modzone` reconfigures a single zone, without requiring the entire server to be reconfigured. * `rndc showzone` displays the current configuration of a zone. * `rndc managed-keys` can be used to check the status of RFC 5001 managed trust anchors, or to force trust anchors to be refreshed. * `max-cache-size` can now be set to a percentage of available memory. The default is 90%. * Update forwarding performance has been improved by allowing a single TCP connection to be shared by multiple updates. * The EDNS Client Subnet (ECS) option is now supported for authoritative servers; if a query contains an ECS option then ACLs containing `geoip` or `ecs` elements can match against the the address encoded in the option. This can be used to select a view for a query, so that different answers can be provided depending on the client network. * The EDNS EXPIRE option has been implemented on the client side, allowing a slave server to set the expiration timer correctly when transferring zone data from another slave server. * The key generation and manipulation tools (`dnssec-keygen`, `dnssec-settime`, `dnssec-importkey`, `dnssec-keyfromlabel`) now take `-Psync` and `-Dsync` options to set the publication and deletion times of CDS and CDNSKEY parent-synchronization records. Both `named` and `dnssec-signzone` can now publish and remove these records at the scheduled times. * A new `minimal-any` option reduces the size of UDP responses for query type ANY by returning a single arbitrarily selected RRset instead of all RRsets. * A new `masterfile-style` zone option controls the formatting of text zone files: When set to `full`, a zone file is dumped in single-line-per-record format. * `serial-update-method` can now be set to `date`. On update, the serial number will be set to the current date in YYYYMMDDNN format. * `dnssec-signzone -N date` sets the serial number to YYYYMMDDNN. * `named -L ` causes named to send log messages to the specified file by default instead of to the system log. * `dig +ttlunits` prints TTL values with time-unit suffixes: w, d, h, m, s for weeks, days, hours, minutes, and seconds. * `dig +unknownformat` prints dig output in RFC 3597 "unknown record" presentation format. * `dig +ednsopt` allows dig to set arbitrary EDNS options on requests. * `dig +ednsflags` allows dig to set yet-to-be-defined EDNS flags on requests. * `mdig` is an alternate version of dig which sends multiple pipelined TCP queries to a server. Instead of waiting for a response after sending a query, it sends all queries immediately and displays responses in the order received. * `serial-query-rate` no longer controls NOTIFY messages. These are separately controlled by `notify-rate` and `startup-notify-rate`. * `nsupdate` now performs `check-names` processing by default on records to be added. This can be disabled with `check-names no`. * The statistics channel now supports DEFLATE compression, reducing the size of the data sent over the network when querying statistics. * New counters have been added to the statistics channel to track the sizes of incoming queries and outgoing responses in histogram buckets, as specified in RSSAC002. * A new NXDOMAIN redirect method (option `nxdomain-redirect`) has been added, allowing redirection to a specified DNS namespace instead of a single redirect zone. * When starting up, named now ensures that no other named process is already running. * Files created by named to store information, including `mkeys` and `nzf` files, are now named after their corresponding views unless the view name contains characters incompatible with use as a filename. Old style filenames (based on the hash of the view name) will still work. #### BIND 9.11.1 BIND 9.11.1 is a maintenance release, and addresses the security flaws disclosed in CVE-2016-6170, CVE-2016-8864, CVE-2016-9131, CVE-2016-9147, CVE-2016-9444, CVE-2016-9778, CVE-2017-3135, CVE-2017-3136, CVE-2017-3137 and CVE-2017-3138. #### BIND 9.11.2 BIND 9.11.2 is a maintenance release, and addresses the security flaws disclosed in CVE-2017-3140, CVE-2017-3141, CVE-2017-3142 and CVE-2017-3143. It also addresses several bugs related to the use of an LMDB database to store data related to zones added via `rndc addzone` or catalog zones. #### BIND 9.11.3 BIND 9.11.3 is a maintenance release, and addresses the security flaw disclosed in CVE-2017-3145. ### Building BIND BIND requires a UNIX or Linux system with an ANSI C compiler, basic POSIX support, and a 64-bit integer type. Successful builds have been observed on many versions of Linux and UNIX, including RedHat, Fedora, Debian, Ubuntu, SuSE, Slackware, FreeBSD, NetBSD, OpenBSD, Mac OS X, Solaris, HP-UX, AIX, SCO OpenServer, and OpenWRT. BIND is also available for Windows XP, 2003, 2008, and higher. See `win32utils/readme1st.txt` for details on building for Windows systems. To build on a UNIX or Linux system, use: $ ./configure $ make If you're planning on making changes to the BIND 9 source, you should run `make depend`. If you're using Emacs, you might find `make tags` helpful. Several environment variables that can be set before running `configure` will affect compilation: |Variable|Description | |--------------------|-----------------------------------------------| |`CC`|The C compiler to use. `configure` tries to figure out the right one for supported systems.| |`CFLAGS`|C compiler flags. Defaults to include -g and/or -O2 as supported by the compiler. Please include '-g' if you need to set `CFLAGS`. | |`STD_CINCLUDES`|System header file directories. Can be used to specify where add-on thread or IPv6 support is, for example. Defaults to empty string.| |`STD_CDEFINES`|Any additional preprocessor symbols you want defined. Defaults to empty string. For a list of possible settings, see the file [OPTIONS](OPTIONS.md).| |`LDFLAGS`|Linker flags. Defaults to empty string.| |`BUILD_CC`|Needed when cross-compiling: the native C compiler to use when building for the target system.| |`BUILD_CFLAGS`|Optional, used for cross-compiling| |`BUILD_CPPFLAGS`|| |`BUILD_LDFLAGS`|| |`BUILD_LIBS`|| #### macOS Building on macOS assumes that the "Command Tools for Xcode" is installed. This can be downloaded from https://developer.apple.com/download/more/ or if you have Xcode already installed you can run "xcode-select --install". This will add /usr/include to the system and install the compiler and other tools so that they can be easily found. #### Compile-time options To see a full list of configuration options, run `configure --help`. On most platforms, BIND 9 is built with multithreading support, allowing it to take advantage of multiple CPUs. You can configure this by specifying `--enable-threads` or `--disable-threads` on the `configure` command line. The default is to enable threads, except on some older operating systems on which threads are known to have had problems in the past. (Note: Prior to BIND 9.10, the default was to disable threads on Linux systems; this has now been reversed. On Linux systems, the threaded build is known to change BIND's behavior with respect to file permissions; it may be necessary to specify a user with the -u option when running `named`.) To build shared libraries, specify `--with-libtool` on the `configure` command line. Certain compiled-in constants and default settings can be increased to values better suited to large servers with abundant memory resources (e.g, 64-bit servers with 12G or more of memory) by specifying `--with-tuning=large` on the `configure` command line. This can improve performance on big servers, but will consume more memory and may degrade performance on smaller systems. For the server to support DNSSEC, you need to build it with crypto support. To use OpenSSL, you should have OpenSSL 1.0.2e or newer installed. If the OpenSSL library is installed in a nonstandard location, specify the prefix using "--with-openssl=<PREFIX>" on the configure command line. To use a PKCS#11 hardware service module for cryptographic operations, specify the path to the PKCS#11 provider library using "--with-pkcs11=<PREFIX>", and configure BIND with "--enable-native-pkcs11". To support the HTTP statistics channel, the server must be linked with at least one of the following: libxml2 [http://xmlsoft.org](http://xmlsoft.org) or json-c [https://github.com/json-c](https://github.com/json-c). If these are installed at a nonstandard location, specify the prefix using `--with-libxml2=/prefix` or `--with-libjson=/prefix`. To support compression on the HTTP statistics channel, the server must be linked against libzlib. If this is installed in a nonstandard location, specify the prefix using `--with-zlib=/prefix`. To support storing configuration data for runtime-added zones in an LMDB database, the server must be linked with liblmdb. If this is installed in a nonstandard location, specify the prefix using "with-lmdb=/prefix". To support GeoIP location-based ACLs, the server must be linked with libGeoIP. This is not turned on by default; BIND must be configured with "--with-geoip". If the library is installed in a nonstandard location, use specify the prefix using "--with-geoip=/prefix". For DNSTAP packet logging, you must have installed libfstrm [https://github.com/farsightsec/fstrm](https://github.com/farsightsec/fstrm) and libprotobuf-c [https://developers.google.com/protocol-buffers](https://developers.google.com/protocol-buffers), and BIND must be configured with "--enable-dnstap". Portions of BIND that are written in Python, including `dnssec-keymgr`, `dnssec-coverage`, `dnssec-checkds`, and some of the system tests, require the 'argparse' and 'ply' modules to be available. 'argparse' is a standard module as of Python 2.7 and Python 3.2. 'ply' is available from [https://pypi.python.org/pypi/ply](https://pypi.python.org/pypi/ply). On some platforms it is necessary to explicitly request large file support to handle files bigger than 2GB. This can be done by using `--enable-largefile` on the `configure` command line. Support for the "fixed" rrset-order option can be enabled or disabled by specifying `--enable-fixed-rrset` or `--disable-fixed-rrset` on the configure command line. By default, fixed rrset-order is disabled to reduce memory footprint. If your operating system has integrated support for IPv6, it will be used automatically. If you have installed KAME IPv6 separately, use `--with-kame[=PATH]` to specify its location. `make install` will install `named` and the various BIND 9 libraries. By default, installation is into /usr/local, but this can be changed with the `--prefix` option when running `configure`. You may specify the option `--sysconfdir` to set the directory where configuration files like `named.conf` go by default, and `--localstatedir` to set the default parent directory of `run/named.pid`. For backwards compatibility with BIND 8, `--sysconfdir` defaults to `/etc` and `--localstatedir` defaults to `/var` if no `--prefix` option is given. If there is a `--prefix` option, sysconfdir defaults to `$prefix/etc` and localstatedir defaults to `$prefix/var`. ### Automated testing A system test suite can be run with `make test`. The system tests require you to configure a set of virtual IP addresses on your system (this allows multiple servers to run locally and communicate with one another). These IP addresses can be configured by running the command `bin/tests/system/ifconfig.sh up` as root. Some tests require Perl and the Net::DNS and/or IO::Socket::INET6 modules, and will be skipped if these are not available. Some tests require Python and the 'dnspython' module and will be skipped if these are not available. See bin/tests/system/README for further details. Unit tests are implemented using Automated Testing Framework (ATF). To run them, use `configure --with-atf`, then run `make test` or `make unit`. ### Documentation The *BIND 9 Administrator Reference Manual* is included with the source distribution, in DocBook XML, HTML and PDF format, in the `doc/arm` directory. Some of the programs in the BIND 9 distribution have man pages in their directories. In particular, the command line options of `named` are documented in `bin/named/named.8`. Frequently (and not-so-frequently) asked questions and their answers can be found in the ISC Knowledge Base at [https://kb.isc.org](https://kb.isc.org). Additional information on various subjects can be found in other `README` files throughout the source tree. ### Change log A detailed list of all changes that have been made throughout the development BIND 9 is included in the file CHANGES, with the most recent changes listed first. Change notes include tags indicating the category of the change that was made; these categories are: |Category |Description | |-------------- |-----------------------------------------------| | [func] | New feature | | [bug] | General bug fix | | [security] | Fix for a significant security flaw | | [experimental] | Used for new features when the syntax or other aspects of the design are still in flux and may change | | [port] | Portability enhancement | | [maint] | Updates to built-in data such as root server addresses and keys | | [tuning] | Changes to built-in configuration defaults and constants to improve performance | | [performance] | Other changes to improve server performance | | [protocol] | Updates to the DNS protocol such as new RR types | | [test] | Changes to the automatic tests, not affecting server functionality | | [cleanup] | Minor corrections and refactoring | | [doc] | Documentation | | [contrib] | Changes to the contributed tools and libraries in the 'contrib' subdirectory | | [placeholder] | Used in the master development branch to reserve change numbers for use in other branches, e.g. when fixing a bug that only exists in older releases | In general, [func] and [experimental] tags will only appear in new-feature releases (i.e., those with version numbers ending in zero). Some new functionality may be backported to older releases on a case-by-case basis. All other change types may be applied to all currently-supported releases. ### Acknowledgments * The original development of BIND 9 was underwritten by the following organizations: Sun Microsystems, Inc. Hewlett Packard Compaq Computer Corporation IBM Process Software Corporation Silicon Graphics, Inc. Network Associates, Inc. U.S. Defense Information Systems Agency USENIX Association Stichting NLnet - NLnet Foundation Nominum, Inc. * This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit. [http://www.OpenSSL.org/](http://www.OpenSSL.org/) * This product includes cryptographic software written by Eric Young (eay@cryptsoft.com) * This product includes software written by Tim Hudson (tjh@cryptsoft.com) bind9-9.11.3+dfsg/acconfig.h000066400000000000000000000070111325250447100154550ustar00rootroot00000000000000/* * Copyright (C) 1999-2005, 2007, 2008, 2012, 2014, 2016 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /*! \file */ /*** *** This file is not to be included by any public header files, because *** it does not get installed. ***/ @TOP@ /** define on DEC OSF to enable 4.4BSD style sa_len support */ #undef _SOCKADDR_LEN /** define if your system needs pthread_init() before using pthreads */ #undef NEED_PTHREAD_INIT /** define if your system has sigwait() */ #undef HAVE_SIGWAIT /** define if sigwait() is the UnixWare flavor */ #undef HAVE_UNIXWARE_SIGWAIT /** define on Solaris to get sigwait() to work using pthreads semantics */ #undef _POSIX_PTHREAD_SEMANTICS /** define if LinuxThreads is in use */ #undef HAVE_LINUXTHREADS /** define if sysconf() is available */ #undef HAVE_SYSCONF /** define if sysctlbyname() is available */ #undef HAVE_SYSCTLBYNAME /** define if catgets() is available */ #undef HAVE_CATGETS /** define if getifaddrs() exists */ #undef HAVE_GETIFADDRS /** define if you have the NET_RT_IFLIST sysctl variable and sys/sysctl.h */ #undef HAVE_IFLIST_SYSCTL /** define if tzset() is available */ #undef HAVE_TZSET /** define if struct addrinfo exists */ #undef HAVE_ADDRINFO /** define if getaddrinfo() exists */ #undef HAVE_GETADDRINFO /** define if gai_strerror() exists */ #undef HAVE_GAISTRERROR /** * define if pthread_setconcurrency() should be called to tell the * OS how many threads we might want to run. */ #undef CALL_PTHREAD_SETCONCURRENCY /** define if IPv6 is not disabled */ #undef WANT_IPV6 /** define if flockfile() is available */ #undef HAVE_FLOCKFILE /** define if getc_unlocked() is available */ #undef HAVE_GETCUNLOCKED /** Shut up warnings about sputaux in stdio.h on BSD/OS pre-4.1 */ #undef SHUTUP_SPUTAUX #ifdef SHUTUP_SPUTAUX struct __sFILE; extern __inline int __sputaux(int _c, struct __sFILE *_p); #endif /** Shut up warnings about missing sigwait prototype on BSD/OS 4.0* */ #undef SHUTUP_SIGWAIT #ifdef SHUTUP_SIGWAIT int sigwait(const unsigned int *set, int *sig); #endif /** Shut up warnings from gcc -Wcast-qual on BSD/OS 4.1. */ #undef SHUTUP_STDARG_CAST #if defined(SHUTUP_STDARG_CAST) && defined(__GNUC__) #include /** Grr. Must be included *every time*. */ /** * The silly continuation line is to keep configure from * commenting out the #undef. */ #undef \ va_start #define va_start(ap, last) \ do { \ union { const void *konst; long *var; } _u; \ _u.konst = &(last); \ ap = (va_list)(_u.var + __va_words(__typeof(last))); \ } while (0) #endif /** SHUTUP_STDARG_CAST && __GNUC__ */ /** define if the system has a random number generating device */ #undef PATH_RANDOMDEV /** define if pthread_attr_getstacksize() is available */ #undef HAVE_PTHREAD_ATTR_GETSTACKSIZE /** define if pthread_attr_setstacksize() is available */ #undef HAVE_PTHREAD_ATTR_SETSTACKSIZE /** define if you have strerror in the C library. */ #undef HAVE_STRERROR /* Define if OpenSSL includes DSA support */ #undef HAVE_OPENSSL_DSA /* Define if you have getpassphrase in the C library. */ #undef HAVE_GETPASSPHRASE /* Define to the length type used by the socket API (socklen_t, size_t, int). */ #undef ISC_SOCKADDR_LEN_T /* Define if threads need PTHREAD_SCOPE_SYSTEM */ #undef NEED_PTHREAD_SCOPE_SYSTEM /* Define to 1 if you have the uname library function. */ #undef HAVE_UNAME bind9-9.11.3+dfsg/aclocal.m4000066400000000000000000000013151325250447100153740ustar00rootroot00000000000000sinclude(libtool.m4/libtool.m4)dnl sinclude(libtool.m4/ltoptions.m4)dnl sinclude(libtool.m4/ltsugar.m4)dnl sinclude(libtool.m4/ltversion.m4)dnl sinclude(libtool.m4/lt~obsolete.m4)dnl m4_divert_text(HELP_CANON, [[ NOTE: If PREFIX is not set, then the default values for --sysconfdir and --localstatedir are /etc and /var, respectively.]]) m4_divert_text(HELP_END, [[ Professional support for BIND is provided by Internet Systems Consortium, Inc. Information about paid support and training options is available at https://www.isc.org/support. Help can also often be found on the BIND Users mailing list (https://lists.isc.org/mailman/listinfo/bind-users) or in the #bind channel of the Freenode IRC service.]]) bind9-9.11.3+dfsg/autogen.sh000077500000000000000000000005571325250447100155440ustar00rootroot00000000000000#!/bin/sh # # Copyright (C) 2015, 2016 Internet Systems Consortium, Inc. ("ISC") # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. # Run this script after modifying configure.in to generate configure autoreconf -i bind9-9.11.3+dfsg/bin/000077500000000000000000000000001325250447100143045ustar00rootroot00000000000000bind9-9.11.3+dfsg/bin/Makefile.in000066400000000000000000000011021325250447100163430ustar00rootroot00000000000000# Copyright (C) 1998-2001, 2004, 2007, 2009, 2012-2014, 2016 Internet Systems Consortium, Inc. ("ISC") # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. # $Id: Makefile.in,v 1.29 2009/10/05 12:07:08 fdupont Exp $ srcdir = @srcdir@ VPATH = @srcdir@ top_srcdir = @top_srcdir@ SUBDIRS = named rndc dig delv dnssec tools tests nsupdate \ check confgen @NZD_TOOLS@ @PYTHON_TOOLS@ @PKCS11_TOOLS@ TARGETS = @BIND9_MAKE_RULES@ bind9-9.11.3+dfsg/bin/check/000077500000000000000000000000001325250447100153615ustar00rootroot00000000000000bind9-9.11.3+dfsg/bin/check/Makefile.in000066400000000000000000000064411325250447100174330ustar00rootroot00000000000000# Copyright (C) 2000-2007, 2009, 2012, 2014-2016 Internet Systems Consortium, Inc. ("ISC") # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. # $Id: Makefile.in,v 1.36 2009/12/05 23:31:40 each Exp $ srcdir = @srcdir@ VPATH = @srcdir@ top_srcdir = @top_srcdir@ VERSION=@BIND9_VERSION@ @BIND9_MAKE_INCLUDES@ CINCLUDES = ${BIND9_INCLUDES} ${DNS_INCLUDES} ${ISCCFG_INCLUDES} \ ${ISC_INCLUDES} @DST_OPENSSL_INC@ CDEFINES = @CRYPTO@ -DNAMED_CONFFILE=\"${sysconfdir}/named.conf\" CWARNINGS = DNSLIBS = ../../lib/dns/libdns.@A@ @DNS_CRYPTO_LIBS@ ISCCFGLIBS = ../../lib/isccfg/libisccfg.@A@ ISCLIBS = ../../lib/isc/libisc.@A@ ISCNOSYMLIBS = ../../lib/isc/libisc-nosymtbl.@A@ BIND9LIBS = ../../lib/bind9/libbind9.@A@ DNSDEPLIBS = ../../lib/dns/libdns.@A@ ISCCFGDEPLIBS = ../../lib/isccfg/libisccfg.@A@ ISCDEPLIBS = ../../lib/isc/libisc.@A@ BIND9DEPLIBS = ../../lib/bind9/libbind9.@A@ LIBS = ${ISCLIBS} @LIBS@ NOSYMLIBS = ${ISCNOSYMLIBS} @LIBS@ SUBDIRS = # Alphabetically TARGETS = named-checkconf@EXEEXT@ named-checkzone@EXEEXT@ # Alphabetically SRCS = named-checkconf.c named-checkzone.c check-tool.c MANPAGES = named-checkconf.8 named-checkzone.8 HTMLPAGES = named-checkconf.html named-checkzone.html MANOBJS = ${MANPAGES} ${HTMLPAGES} @BIND9_MAKE_RULES@ named-checkconf.@O@: named-checkconf.c ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} \ -DVERSION=\"${VERSION}\" \ -c ${srcdir}/named-checkconf.c named-checkzone.@O@: named-checkzone.c ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} \ -DVERSION=\"${VERSION}\" \ -c ${srcdir}/named-checkzone.c named-checkconf@EXEEXT@: named-checkconf.@O@ check-tool.@O@ ${ISCDEPLIBS} \ ${DNSDEPLIBS} ${ISCCFGDEPLIBS} ${BIND9DEPLIBS} export BASEOBJS="named-checkconf.@O@ check-tool.@O@"; \ export LIBS0="${BIND9LIBS} ${ISCCFGLIBS} ${DNSLIBS}"; \ ${FINALBUILDCMD} named-checkzone@EXEEXT@: named-checkzone.@O@ check-tool.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} export BASEOBJS="named-checkzone.@O@ check-tool.@O@"; \ export LIBS0="${ISCCFGLIBS} ${DNSLIBS}"; \ ${FINALBUILDCMD} doc man:: ${MANOBJS} docclean manclean maintainer-clean:: rm -f ${MANOBJS} installdirs: $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${sbindir} $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${mandir}/man8 install:: named-checkconf@EXEEXT@ named-checkzone@EXEEXT@ installdirs ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} named-checkconf@EXEEXT@ ${DESTDIR}${sbindir} ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} named-checkzone@EXEEXT@ ${DESTDIR}${sbindir} (cd ${DESTDIR}${sbindir}; rm -f named-compilezone@EXEEXT@; ${LINK_PROGRAM} named-checkzone@EXEEXT@ named-compilezone@EXEEXT@) for m in ${MANPAGES}; do ${INSTALL_DATA} ${srcdir}/$$m ${DESTDIR}${mandir}/man8; done (cd ${DESTDIR}${mandir}/man8; rm -f named-compilezone.8; ${LINK_PROGRAM} named-checkzone.8 named-compilezone.8) uninstall:: rm -f ${DESTDIR}${mandir}/man8/named-compilezone.8 for m in ${MANPAGES}; do rm -f ${DESTDIR}${mandir}/man8/$$m ; done rm -f ${DESTDIR}${sbindir}/named-compilezone@EXEEXT@ ${LIBTOOL_MODE_UNINSTALL} rm -f ${DESTDIR}${sbindir}/named-checkconf@EXEEXT@ ${LIBTOOL_MODE_UNINSTALL} rm -f ${DESTDIR}${sbindir}/named-checkzone@EXEEXT@ clean distclean:: rm -f ${TARGETS} r1.htm bind9-9.11.3+dfsg/bin/check/check-tool.c000066400000000000000000000500471325250447100175630ustar00rootroot00000000000000/* * Copyright (C) 2000-2002, 2004-2017 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* $Id: check-tool.c,v 1.44 2011/12/22 07:32:39 each Exp $ */ /*! \file */ #include #include #ifdef _WIN32 #include #endif #include "check-tool.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifndef CHECK_SIBLING #define CHECK_SIBLING 1 #endif #ifndef CHECK_LOCAL #define CHECK_LOCAL 1 #endif #ifdef HAVE_ADDRINFO #ifdef HAVE_GETADDRINFO #ifdef HAVE_GAISTRERROR #define USE_GETADDRINFO #endif #endif #endif #define CHECK(r) \ do { \ result = (r); \ if (result != ISC_R_SUCCESS) \ goto cleanup; \ } while (0) #define ERR_IS_CNAME 1 #define ERR_NO_ADDRESSES 2 #define ERR_LOOKUP_FAILURE 3 #define ERR_EXTRA_A 4 #define ERR_EXTRA_AAAA 5 #define ERR_MISSING_GLUE 5 #define ERR_IS_MXCNAME 6 #define ERR_IS_SRVCNAME 7 static const char *dbtype[] = { "rbt" }; int debug = 0; const char *journal = NULL; isc_boolean_t nomerge = ISC_TRUE; #if CHECK_LOCAL isc_boolean_t docheckmx = ISC_TRUE; isc_boolean_t dochecksrv = ISC_TRUE; isc_boolean_t docheckns = ISC_TRUE; #else isc_boolean_t docheckmx = ISC_FALSE; isc_boolean_t dochecksrv = ISC_FALSE; isc_boolean_t docheckns = ISC_FALSE; #endif unsigned int zone_options = DNS_ZONEOPT_CHECKNS | DNS_ZONEOPT_CHECKMX | DNS_ZONEOPT_MANYERRORS | DNS_ZONEOPT_CHECKNAMES | DNS_ZONEOPT_CHECKINTEGRITY | #if CHECK_SIBLING DNS_ZONEOPT_CHECKSIBLING | #endif DNS_ZONEOPT_CHECKWILDCARD | DNS_ZONEOPT_WARNMXCNAME | DNS_ZONEOPT_WARNSRVCNAME; unsigned int zone_options2 = 0; /* * This needs to match the list in bin/named/log.c. */ static isc_logcategory_t categories[] = { { "", 0 }, { "client", 0 }, { "network", 0 }, { "update", 0 }, { "queries", 0 }, { "unmatched", 0 }, { "update-security", 0 }, { "query-errors", 0 }, { "trust-anchor-telemetry", 0 }, { NULL, 0 } }; static isc_symtab_t *symtab = NULL; static isc_mem_t *sym_mctx; static void freekey(char *key, unsigned int type, isc_symvalue_t value, void *userarg) { UNUSED(type); UNUSED(value); isc_mem_free(userarg, key); } static void add(char *key, int value) { isc_result_t result; isc_symvalue_t symvalue; if (sym_mctx == NULL) { result = isc_mem_create(0, 0, &sym_mctx); if (result != ISC_R_SUCCESS) return; } if (symtab == NULL) { result = isc_symtab_create(sym_mctx, 100, freekey, sym_mctx, ISC_FALSE, &symtab); if (result != ISC_R_SUCCESS) return; } key = isc_mem_strdup(sym_mctx, key); if (key == NULL) return; symvalue.as_pointer = NULL; result = isc_symtab_define(symtab, key, value, symvalue, isc_symexists_reject); if (result != ISC_R_SUCCESS) isc_mem_free(sym_mctx, key); } static isc_boolean_t logged(char *key, int value) { isc_result_t result; if (symtab == NULL) return (ISC_FALSE); result = isc_symtab_lookup(symtab, key, value, NULL); if (result == ISC_R_SUCCESS) return (ISC_TRUE); return (ISC_FALSE); } static isc_boolean_t checkns(dns_zone_t *zone, dns_name_t *name, dns_name_t *owner, dns_rdataset_t *a, dns_rdataset_t *aaaa) { #ifdef USE_GETADDRINFO dns_rdataset_t *rdataset; dns_rdata_t rdata = DNS_RDATA_INIT; struct addrinfo hints, *ai, *cur; char namebuf[DNS_NAME_FORMATSIZE + 1]; char ownerbuf[DNS_NAME_FORMATSIZE]; char addrbuf[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:123.123.123.123")]; isc_boolean_t answer = ISC_TRUE; isc_boolean_t match; const char *type; void *ptr = NULL; int result; REQUIRE(a == NULL || !dns_rdataset_isassociated(a) || a->type == dns_rdatatype_a); REQUIRE(aaaa == NULL || !dns_rdataset_isassociated(aaaa) || aaaa->type == dns_rdatatype_aaaa); if (a == NULL || aaaa == NULL) return (answer); memset(&hints, 0, sizeof(hints)); hints.ai_flags = AI_CANONNAME; hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; dns_name_format(name, namebuf, sizeof(namebuf) - 1); /* * Turn off search. */ if (dns_name_countlabels(name) > 1U) { strlcat(namebuf, ".", sizeof(namebuf)); } dns_name_format(owner, ownerbuf, sizeof(ownerbuf)); result = getaddrinfo(namebuf, NULL, &hints, &ai); dns_name_format(name, namebuf, sizeof(namebuf) - 1); switch (result) { case 0: /* * Work around broken getaddrinfo() implementations that * fail to set ai_canonname on first entry. */ cur = ai; while (cur != NULL && cur->ai_canonname == NULL && cur->ai_next != NULL) cur = cur->ai_next; if (cur != NULL && cur->ai_canonname != NULL && strcasecmp(cur->ai_canonname, namebuf) != 0 && !logged(namebuf, ERR_IS_CNAME)) { dns_zone_log(zone, ISC_LOG_ERROR, "%s/NS '%s' (out of zone) " "is a CNAME '%s' (illegal)", ownerbuf, namebuf, cur->ai_canonname); /* XXX950 make fatal for 9.5.0 */ /* answer = ISC_FALSE; */ add(namebuf, ERR_IS_CNAME); } break; case EAI_NONAME: #if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME) case EAI_NODATA: #endif if (!logged(namebuf, ERR_NO_ADDRESSES)) { dns_zone_log(zone, ISC_LOG_ERROR, "%s/NS '%s' (out of zone) " "has no addresses records (A or AAAA)", ownerbuf, namebuf); add(namebuf, ERR_NO_ADDRESSES); } /* XXX950 make fatal for 9.5.0 */ return (ISC_TRUE); default: if (!logged(namebuf, ERR_LOOKUP_FAILURE)) { dns_zone_log(zone, ISC_LOG_WARNING, "getaddrinfo(%s) failed: %s", namebuf, gai_strerror(result)); add(namebuf, ERR_LOOKUP_FAILURE); } return (ISC_TRUE); } /* * Check that all glue records really exist. */ if (!dns_rdataset_isassociated(a)) goto checkaaaa; result = dns_rdataset_first(a); while (result == ISC_R_SUCCESS) { dns_rdataset_current(a, &rdata); match = ISC_FALSE; for (cur = ai; cur != NULL; cur = cur->ai_next) { if (cur->ai_family != AF_INET) continue; ptr = &((struct sockaddr_in *)(cur->ai_addr))->sin_addr; if (memcmp(ptr, rdata.data, rdata.length) == 0) { match = ISC_TRUE; break; } } if (!match && !logged(namebuf, ERR_EXTRA_A)) { dns_zone_log(zone, ISC_LOG_ERROR, "%s/NS '%s' " "extra GLUE A record (%s)", ownerbuf, namebuf, inet_ntop(AF_INET, rdata.data, addrbuf, sizeof(addrbuf))); add(namebuf, ERR_EXTRA_A); /* XXX950 make fatal for 9.5.0 */ /* answer = ISC_FALSE; */ } dns_rdata_reset(&rdata); result = dns_rdataset_next(a); } checkaaaa: if (!dns_rdataset_isassociated(aaaa)) goto checkmissing; result = dns_rdataset_first(aaaa); while (result == ISC_R_SUCCESS) { dns_rdataset_current(aaaa, &rdata); match = ISC_FALSE; for (cur = ai; cur != NULL; cur = cur->ai_next) { if (cur->ai_family != AF_INET6) continue; ptr = &((struct sockaddr_in6 *)(cur->ai_addr))->sin6_addr; if (memcmp(ptr, rdata.data, rdata.length) == 0) { match = ISC_TRUE; break; } } if (!match && !logged(namebuf, ERR_EXTRA_AAAA)) { dns_zone_log(zone, ISC_LOG_ERROR, "%s/NS '%s' " "extra GLUE AAAA record (%s)", ownerbuf, namebuf, inet_ntop(AF_INET6, rdata.data, addrbuf, sizeof(addrbuf))); add(namebuf, ERR_EXTRA_AAAA); /* XXX950 make fatal for 9.5.0. */ /* answer = ISC_FALSE; */ } dns_rdata_reset(&rdata); result = dns_rdataset_next(aaaa); } checkmissing: /* * Check that all addresses appear in the glue. */ if (!logged(namebuf, ERR_MISSING_GLUE)) { isc_boolean_t missing_glue = ISC_FALSE; for (cur = ai; cur != NULL; cur = cur->ai_next) { switch (cur->ai_family) { case AF_INET: rdataset = a; ptr = &((struct sockaddr_in *)(cur->ai_addr))->sin_addr; type = "A"; break; case AF_INET6: rdataset = aaaa; ptr = &((struct sockaddr_in6 *)(cur->ai_addr))->sin6_addr; type = "AAAA"; break; default: continue; } match = ISC_FALSE; if (dns_rdataset_isassociated(rdataset)) result = dns_rdataset_first(rdataset); else result = ISC_R_FAILURE; while (result == ISC_R_SUCCESS && !match) { dns_rdataset_current(rdataset, &rdata); if (memcmp(ptr, rdata.data, rdata.length) == 0) match = ISC_TRUE; dns_rdata_reset(&rdata); result = dns_rdataset_next(rdataset); } if (!match) { dns_zone_log(zone, ISC_LOG_ERROR, "%s/NS '%s' " "missing GLUE %s record (%s)", ownerbuf, namebuf, type, inet_ntop(cur->ai_family, ptr, addrbuf, sizeof(addrbuf))); /* XXX950 make fatal for 9.5.0. */ /* answer = ISC_FALSE; */ missing_glue = ISC_TRUE; } } if (missing_glue) add(namebuf, ERR_MISSING_GLUE); } freeaddrinfo(ai); return (answer); #else return (ISC_TRUE); #endif } static isc_boolean_t checkmx(dns_zone_t *zone, dns_name_t *name, dns_name_t *owner) { #ifdef USE_GETADDRINFO struct addrinfo hints, *ai, *cur; char namebuf[DNS_NAME_FORMATSIZE + 1]; char ownerbuf[DNS_NAME_FORMATSIZE]; int result; int level = ISC_LOG_ERROR; isc_boolean_t answer = ISC_TRUE; memset(&hints, 0, sizeof(hints)); hints.ai_flags = AI_CANONNAME; hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; dns_name_format(name, namebuf, sizeof(namebuf) - 1); /* * Turn off search. */ if (dns_name_countlabels(name) > 1U) { strlcat(namebuf, ".", sizeof(namebuf)); } dns_name_format(owner, ownerbuf, sizeof(ownerbuf)); result = getaddrinfo(namebuf, NULL, &hints, &ai); dns_name_format(name, namebuf, sizeof(namebuf) - 1); switch (result) { case 0: /* * Work around broken getaddrinfo() implementations that * fail to set ai_canonname on first entry. */ cur = ai; while (cur != NULL && cur->ai_canonname == NULL && cur->ai_next != NULL) cur = cur->ai_next; if (cur != NULL && cur->ai_canonname != NULL && strcasecmp(cur->ai_canonname, namebuf) != 0) { if ((zone_options & DNS_ZONEOPT_WARNMXCNAME) != 0) level = ISC_LOG_WARNING; if ((zone_options & DNS_ZONEOPT_IGNOREMXCNAME) == 0) { if (!logged(namebuf, ERR_IS_MXCNAME)) { dns_zone_log(zone, level, "%s/MX '%s' (out of zone)" " is a CNAME '%s' " "(illegal)", ownerbuf, namebuf, cur->ai_canonname); add(namebuf, ERR_IS_MXCNAME); } if (level == ISC_LOG_ERROR) answer = ISC_FALSE; } } freeaddrinfo(ai); return (answer); case EAI_NONAME: #if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME) case EAI_NODATA: #endif if (!logged(namebuf, ERR_NO_ADDRESSES)) { dns_zone_log(zone, ISC_LOG_ERROR, "%s/MX '%s' (out of zone) " "has no addresses records (A or AAAA)", ownerbuf, namebuf); add(namebuf, ERR_NO_ADDRESSES); } /* XXX950 make fatal for 9.5.0. */ return (ISC_TRUE); default: if (!logged(namebuf, ERR_LOOKUP_FAILURE)) { dns_zone_log(zone, ISC_LOG_WARNING, "getaddrinfo(%s) failed: %s", namebuf, gai_strerror(result)); add(namebuf, ERR_LOOKUP_FAILURE); } return (ISC_TRUE); } #else return (ISC_TRUE); #endif } static isc_boolean_t checksrv(dns_zone_t *zone, dns_name_t *name, dns_name_t *owner) { #ifdef USE_GETADDRINFO struct addrinfo hints, *ai, *cur; char namebuf[DNS_NAME_FORMATSIZE + 1]; char ownerbuf[DNS_NAME_FORMATSIZE]; int result; int level = ISC_LOG_ERROR; isc_boolean_t answer = ISC_TRUE; memset(&hints, 0, sizeof(hints)); hints.ai_flags = AI_CANONNAME; hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; dns_name_format(name, namebuf, sizeof(namebuf) - 1); /* * Turn off search. */ if (dns_name_countlabels(name) > 1U) { strlcat(namebuf, ".", sizeof(namebuf)); } dns_name_format(owner, ownerbuf, sizeof(ownerbuf)); result = getaddrinfo(namebuf, NULL, &hints, &ai); dns_name_format(name, namebuf, sizeof(namebuf) - 1); switch (result) { case 0: /* * Work around broken getaddrinfo() implementations that * fail to set ai_canonname on first entry. */ cur = ai; while (cur != NULL && cur->ai_canonname == NULL && cur->ai_next != NULL) cur = cur->ai_next; if (cur != NULL && cur->ai_canonname != NULL && strcasecmp(cur->ai_canonname, namebuf) != 0) { if ((zone_options & DNS_ZONEOPT_WARNSRVCNAME) != 0) level = ISC_LOG_WARNING; if ((zone_options & DNS_ZONEOPT_IGNORESRVCNAME) == 0) { if (!logged(namebuf, ERR_IS_SRVCNAME)) { dns_zone_log(zone, level, "%s/SRV '%s'" " (out of zone) is a " "CNAME '%s' (illegal)", ownerbuf, namebuf, cur->ai_canonname); add(namebuf, ERR_IS_SRVCNAME); } if (level == ISC_LOG_ERROR) answer = ISC_FALSE; } } freeaddrinfo(ai); return (answer); case EAI_NONAME: #if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME) case EAI_NODATA: #endif if (!logged(namebuf, ERR_NO_ADDRESSES)) { dns_zone_log(zone, ISC_LOG_ERROR, "%s/SRV '%s' (out of zone) " "has no addresses records (A or AAAA)", ownerbuf, namebuf); add(namebuf, ERR_NO_ADDRESSES); } /* XXX950 make fatal for 9.5.0. */ return (ISC_TRUE); default: if (!logged(namebuf, ERR_LOOKUP_FAILURE)) { dns_zone_log(zone, ISC_LOG_WARNING, "getaddrinfo(%s) failed: %s", namebuf, gai_strerror(result)); add(namebuf, ERR_LOOKUP_FAILURE); } return (ISC_TRUE); } #else return (ISC_TRUE); #endif } isc_result_t setup_logging(isc_mem_t *mctx, FILE *errout, isc_log_t **logp) { isc_logdestination_t destination; isc_logconfig_t *logconfig = NULL; isc_log_t *log = NULL; RUNTIME_CHECK(isc_log_create(mctx, &log, &logconfig) == ISC_R_SUCCESS); isc_log_registercategories(log, categories); isc_log_setcontext(log); dns_log_init(log); dns_log_setcontext(log); cfg_log_init(log); destination.file.stream = errout; destination.file.name = NULL; destination.file.versions = ISC_LOG_ROLLNEVER; destination.file.maximum_size = 0; RUNTIME_CHECK(isc_log_createchannel(logconfig, "stderr", ISC_LOG_TOFILEDESC, ISC_LOG_DYNAMIC, &destination, 0) == ISC_R_SUCCESS); RUNTIME_CHECK(isc_log_usechannel(logconfig, "stderr", NULL, NULL) == ISC_R_SUCCESS); *logp = log; return (ISC_R_SUCCESS); } /*% scan the zone for oversize TTLs */ static isc_result_t check_ttls(dns_zone_t *zone, dns_ttl_t maxttl) { isc_result_t result; dns_db_t *db = NULL; dns_dbversion_t *version = NULL; dns_dbnode_t *node = NULL; dns_dbiterator_t *dbiter = NULL; dns_rdatasetiter_t *rdsiter = NULL; dns_rdataset_t rdataset; dns_fixedname_t fname; dns_name_t *name; dns_fixedname_init(&fname); name = dns_fixedname_name(&fname); dns_rdataset_init(&rdataset); CHECK(dns_zone_getdb(zone, &db)); INSIST(db != NULL); CHECK(dns_db_newversion(db, &version)); CHECK(dns_db_createiterator(db, 0, &dbiter)); for (result = dns_dbiterator_first(dbiter); result == ISC_R_SUCCESS; result = dns_dbiterator_next(dbiter)) { result = dns_dbiterator_current(dbiter, &node, name); if (result == DNS_R_NEWORIGIN) result = ISC_R_SUCCESS; CHECK(result); CHECK(dns_db_allrdatasets(db, node, version, 0, &rdsiter)); for (result = dns_rdatasetiter_first(rdsiter); result == ISC_R_SUCCESS; result = dns_rdatasetiter_next(rdsiter)) { dns_rdatasetiter_current(rdsiter, &rdataset); if (rdataset.ttl > maxttl) { char nbuf[DNS_NAME_FORMATSIZE]; char tbuf[255]; isc_buffer_t b; isc_region_t r; dns_name_format(name, nbuf, sizeof(nbuf)); isc_buffer_init(&b, tbuf, sizeof(tbuf) - 1); CHECK(dns_rdatatype_totext(rdataset.type, &b)); isc_buffer_usedregion(&b, &r); r.base[r.length] = 0; dns_zone_log(zone, ISC_LOG_ERROR, "%s/%s TTL %d exceeds " "maximum TTL %d", nbuf, tbuf, rdataset.ttl, maxttl); dns_rdataset_disassociate(&rdataset); CHECK(ISC_R_RANGE); } dns_rdataset_disassociate(&rdataset); } if (result == ISC_R_NOMORE) result = ISC_R_SUCCESS; CHECK(result); dns_rdatasetiter_destroy(&rdsiter); dns_db_detachnode(db, &node); } if (result == ISC_R_NOMORE) result = ISC_R_SUCCESS; cleanup: if (node != NULL) dns_db_detachnode(db, &node); if (rdsiter != NULL) dns_rdatasetiter_destroy(&rdsiter); if (dbiter != NULL) dns_dbiterator_destroy(&dbiter); if (version != NULL) dns_db_closeversion(db, &version, ISC_FALSE); if (db != NULL) dns_db_detach(&db); return (result); } /*% load the zone */ isc_result_t load_zone(isc_mem_t *mctx, const char *zonename, const char *filename, dns_masterformat_t fileformat, const char *classname, dns_ttl_t maxttl, dns_zone_t **zonep) { isc_result_t result; dns_rdataclass_t rdclass; isc_textregion_t region; isc_buffer_t buffer; dns_fixedname_t fixorigin; dns_name_t *origin; dns_zone_t *zone = NULL; REQUIRE(zonep == NULL || *zonep == NULL); if (debug) fprintf(stderr, "loading \"%s\" from \"%s\" class \"%s\"\n", zonename, filename, classname); CHECK(dns_zone_create(&zone, mctx)); dns_zone_settype(zone, dns_zone_master); isc_buffer_constinit(&buffer, zonename, strlen(zonename)); isc_buffer_add(&buffer, strlen(zonename)); dns_fixedname_init(&fixorigin); origin = dns_fixedname_name(&fixorigin); CHECK(dns_name_fromtext(origin, &buffer, dns_rootname, 0, NULL)); CHECK(dns_zone_setorigin(zone, origin)); CHECK(dns_zone_setdbtype(zone, 1, (const char * const *) dbtype)); CHECK(dns_zone_setfile2(zone, filename, fileformat)); if (journal != NULL) CHECK(dns_zone_setjournal(zone, journal)); DE_CONST(classname, region.base); region.length = strlen(classname); CHECK(dns_rdataclass_fromtext(&rdclass, ®ion)); dns_zone_setclass(zone, rdclass); dns_zone_setoption(zone, zone_options, ISC_TRUE); dns_zone_setoption2(zone, zone_options2, ISC_TRUE); dns_zone_setoption(zone, DNS_ZONEOPT_NOMERGE, nomerge); dns_zone_setmaxttl(zone, maxttl); if (docheckmx) dns_zone_setcheckmx(zone, checkmx); if (docheckns) dns_zone_setcheckns(zone, checkns); if (dochecksrv) dns_zone_setchecksrv(zone, checksrv); CHECK(dns_zone_load(zone)); /* * When loading map files we can't catch oversize TTLs during * load, so we check for them here. */ if (fileformat == dns_masterformat_map && maxttl != 0) { CHECK(check_ttls(zone, maxttl)); } if (zonep != NULL) { *zonep = zone; zone = NULL; } cleanup: if (zone != NULL) dns_zone_detach(&zone); return (result); } /*% dump the zone */ isc_result_t dump_zone(const char *zonename, dns_zone_t *zone, const char *filename, dns_masterformat_t fileformat, const dns_master_style_t *style, const isc_uint32_t rawversion) { isc_result_t result; FILE *output = stdout; const char *flags; flags = (fileformat == dns_masterformat_text) ? "w+" : "wb+"; if (debug) { if (filename != NULL && strcmp(filename, "-") != 0) fprintf(stderr, "dumping \"%s\" to \"%s\"\n", zonename, filename); else fprintf(stderr, "dumping \"%s\"\n", zonename); } if (filename != NULL && strcmp(filename, "-") != 0) { result = isc_stdio_open(filename, flags, &output); if (result != ISC_R_SUCCESS) { fprintf(stderr, "could not open output " "file \"%s\" for writing\n", filename); return (ISC_R_FAILURE); } } result = dns_zone_dumptostream3(zone, output, fileformat, style, rawversion); if (output != stdout) (void)isc_stdio_close(output); return (result); } #ifdef _WIN32 void InitSockets(void) { WORD wVersionRequested; WSADATA wsaData; int err; wVersionRequested = MAKEWORD(2, 0); err = WSAStartup( wVersionRequested, &wsaData ); if (err != 0) { fprintf(stderr, "WSAStartup() failed: %d\n", err); exit(1); } } void DestroySockets(void) { WSACleanup(); } #endif bind9-9.11.3+dfsg/bin/check/check-tool.h000066400000000000000000000025511325250447100175650ustar00rootroot00000000000000/* * Copyright (C) 2000-2002, 2004, 2005, 2007, 2010, 2011, 2013, 2014, 2016 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* $Id: check-tool.h,v 1.18 2011/12/09 23:47:02 tbox Exp $ */ #ifndef CHECK_TOOL_H #define CHECK_TOOL_H /*! \file */ #include #include #include #include #include ISC_LANG_BEGINDECLS isc_result_t setup_logging(isc_mem_t *mctx, FILE *errout, isc_log_t **logp); isc_result_t load_zone(isc_mem_t *mctx, const char *zonename, const char *filename, dns_masterformat_t fileformat, const char *classname, dns_ttl_t maxttl, dns_zone_t **zonep); isc_result_t dump_zone(const char *zonename, dns_zone_t *zone, const char *filename, dns_masterformat_t fileformat, const dns_master_style_t *style, const isc_uint32_t rawversion); #ifdef _WIN32 void InitSockets(void); void DestroySockets(void); #endif extern int debug; extern const char *journal; extern isc_boolean_t nomerge; extern isc_boolean_t docheckmx; extern isc_boolean_t docheckns; extern isc_boolean_t dochecksrv; extern unsigned int zone_options; extern unsigned int zone_options2; ISC_LANG_ENDDECLS #endif bind9-9.11.3+dfsg/bin/check/named-checkconf.8000066400000000000000000000074761325250447100204750ustar00rootroot00000000000000.\" Copyright (C) 2000-2002, 2004, 2005, 2007, 2009, 2014-2016 Internet Systems Consortium, Inc. ("ISC") .\" .\" This Source Code Form is subject to the terms of the Mozilla Public .\" License, v. 2.0. If a copy of the MPL was not distributed with this .\" file, You can obtain one at http://mozilla.org/MPL/2.0/. .\" .hy 0 .ad l '\" t .\" Title: named-checkconf .\" Author: .\" Generator: DocBook XSL Stylesheets v1.78.1 .\" Date: 2014-01-10 .\" Manual: BIND9 .\" Source: ISC .\" Language: English .\" .TH "NAMED\-CHECKCONF" "8" "2014\-01\-10" "ISC" "BIND9" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" named-checkconf \- named configuration file syntax checking tool .SH "SYNOPSIS" .HP \w'\fBnamed\-checkconf\fR\ 'u \fBnamed\-checkconf\fR [\fB\-hjvz\fR] [\fB\-p\fR\ [\fB\-x\fR\ ]] [\fB\-t\ \fR\fB\fIdirectory\fR\fR] {filename} .SH "DESCRIPTION" .PP \fBnamed\-checkconf\fR checks the syntax, but not the semantics, of a \fBnamed\fR configuration file\&. The file is parsed and checked for syntax errors, along with all files included by it\&. If no file is specified, /etc/named\&.conf is read by default\&. .PP Note: files that \fBnamed\fR reads in separate parser contexts, such as rndc\&.key and bind\&.keys, are not automatically read by \fBnamed\-checkconf\fR\&. Configuration errors in these files may cause \fBnamed\fR to fail to run, even if \fBnamed\-checkconf\fR was successful\&. \fBnamed\-checkconf\fR can be run on these files explicitly, however\&. .SH "OPTIONS" .PP \-h .RS 4 Print the usage summary and exit\&. .RE .PP \-j .RS 4 When loading a zonefile read the journal if it exists\&. .RE .PP \-p .RS 4 Print out the named\&.conf and included files in canonical form if no errors were detected\&. See also the \fB\-x\fR option\&. .RE .PP \-t \fIdirectory\fR .RS 4 Chroot to directory so that include directives in the configuration file are processed as if run by a similarly chrooted \fBnamed\fR\&. .RE .PP \-v .RS 4 Print the version of the \fBnamed\-checkconf\fR program and exit\&. .RE .PP \-x .RS 4 When printing the configuration files in canonical form, obscure shared secrets by replacing them with strings of question marks (\*(Aq?\*(Aq)\&. This allows the contents of named\&.conf and related files to be shared \(em for example, when submitting bug reports \(em without compromising private data\&. This option cannot be used without \fB\-p\fR\&. .RE .PP \-z .RS 4 Perform a test load of all master zones found in named\&.conf\&. .RE .PP filename .RS 4 The name of the configuration file to be checked\&. If not specified, it defaults to /etc/named\&.conf\&. .RE .SH "RETURN VALUES" .PP \fBnamed\-checkconf\fR returns an exit status of 1 if errors were detected and 0 otherwise\&. .SH "SEE ALSO" .PP \fBnamed\fR(8), \fBnamed-checkzone\fR(8), BIND 9 Administrator Reference Manual\&. .SH "AUTHOR" .PP \fBInternet Systems Consortium, Inc\&.\fR .SH "COPYRIGHT" .br Copyright \(co 2000-2002, 2004, 2005, 2007, 2009, 2014-2016 Internet Systems Consortium, Inc. ("ISC") .br bind9-9.11.3+dfsg/bin/check/named-checkconf.c000066400000000000000000000416051325250447100205400ustar00rootroot00000000000000/* * Copyright (C) 1999-2002, 2004-2007, 2009-2016 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* $Id: named-checkconf.c,v 1.56 2011/03/12 04:59:46 tbox Exp $ */ /*! \file */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "check-tool.h" static const char *program = "named-checkconf"; isc_log_t *logc = NULL; #define CHECK(r)\ do { \ result = (r); \ if (result != ISC_R_SUCCESS) \ goto cleanup; \ } while (0) /*% usage */ ISC_PLATFORM_NORETURN_PRE static void usage(void) ISC_PLATFORM_NORETURN_POST; static void usage(void) { fprintf(stderr, "usage: %s [-hjvz] [-p [-x]] [-t directory] " "[named.conf]\n", program); exit(1); } /*% directory callback */ static isc_result_t directory_callback(const char *clausename, const cfg_obj_t *obj, void *arg) { isc_result_t result; const char *directory; REQUIRE(strcasecmp("directory", clausename) == 0); UNUSED(arg); UNUSED(clausename); /* * Change directory. */ directory = cfg_obj_asstring(obj); result = isc_dir_chdir(directory); if (result != ISC_R_SUCCESS) { cfg_obj_log(obj, logc, ISC_LOG_ERROR, "change directory to '%s' failed: %s\n", directory, isc_result_totext(result)); return (result); } return (ISC_R_SUCCESS); } static isc_boolean_t get_maps(const cfg_obj_t **maps, const char *name, const cfg_obj_t **obj) { int i; for (i = 0;; i++) { if (maps[i] == NULL) return (ISC_FALSE); if (cfg_map_get(maps[i], name, obj) == ISC_R_SUCCESS) return (ISC_TRUE); } } static isc_boolean_t get_checknames(const cfg_obj_t **maps, const cfg_obj_t **obj) { const cfg_listelt_t *element; const cfg_obj_t *checknames; const cfg_obj_t *type; const cfg_obj_t *value; isc_result_t result; int i; for (i = 0;; i++) { if (maps[i] == NULL) return (ISC_FALSE); checknames = NULL; result = cfg_map_get(maps[i], "check-names", &checknames); if (result != ISC_R_SUCCESS) continue; if (checknames != NULL && !cfg_obj_islist(checknames)) { *obj = checknames; return (ISC_TRUE); } for (element = cfg_list_first(checknames); element != NULL; element = cfg_list_next(element)) { value = cfg_listelt_value(element); type = cfg_tuple_get(value, "type"); if (strcasecmp(cfg_obj_asstring(type), "master") != 0) continue; *obj = cfg_tuple_get(value, "mode"); return (ISC_TRUE); } } } static isc_result_t configure_hint(const char *zfile, const char *zclass, isc_mem_t *mctx) { isc_result_t result; dns_db_t *db = NULL; dns_rdataclass_t rdclass; isc_textregion_t r; if (zfile == NULL) return (ISC_R_FAILURE); DE_CONST(zclass, r.base); r.length = strlen(zclass); result = dns_rdataclass_fromtext(&rdclass, &r); if (result != ISC_R_SUCCESS) return (result); result = dns_rootns_create(mctx, rdclass, zfile, &db); if (result != ISC_R_SUCCESS) return (result); dns_db_detach(&db); return (ISC_R_SUCCESS); } /*% configure the zone */ static isc_result_t configure_zone(const char *vclass, const char *view, const cfg_obj_t *zconfig, const cfg_obj_t *vconfig, const cfg_obj_t *config, isc_mem_t *mctx) { int i = 0; isc_result_t result; const char *zclass; const char *zname; const char *zfile = NULL; const cfg_obj_t *maps[4]; const cfg_obj_t *mastersobj = NULL; const cfg_obj_t *inviewobj = NULL; const cfg_obj_t *zoptions = NULL; const cfg_obj_t *classobj = NULL; const cfg_obj_t *typeobj = NULL; const cfg_obj_t *fileobj = NULL; const cfg_obj_t *dlzobj = NULL; const cfg_obj_t *dbobj = NULL; const cfg_obj_t *obj = NULL; const cfg_obj_t *fmtobj = NULL; dns_masterformat_t masterformat; dns_ttl_t maxttl = 0; zone_options = DNS_ZONEOPT_CHECKNS | DNS_ZONEOPT_MANYERRORS; zname = cfg_obj_asstring(cfg_tuple_get(zconfig, "name")); classobj = cfg_tuple_get(zconfig, "class"); if (!cfg_obj_isstring(classobj)) zclass = vclass; else zclass = cfg_obj_asstring(classobj); zoptions = cfg_tuple_get(zconfig, "options"); maps[i++] = zoptions; if (vconfig != NULL) maps[i++] = cfg_tuple_get(vconfig, "options"); if (config != NULL) { cfg_map_get(config, "options", &obj); if (obj != NULL) maps[i++] = obj; } maps[i] = NULL; cfg_map_get(zoptions, "in-view", &inviewobj); if (inviewobj != NULL) return (ISC_R_SUCCESS); cfg_map_get(zoptions, "type", &typeobj); if (typeobj == NULL) return (ISC_R_FAILURE); /* * Skip checks when using an alternate data source. */ cfg_map_get(zoptions, "database", &dbobj); if (dbobj != NULL && strcmp("rbt", cfg_obj_asstring(dbobj)) != 0 && strcmp("rbt64", cfg_obj_asstring(dbobj)) != 0) return (ISC_R_SUCCESS); cfg_map_get(zoptions, "dlz", &dlzobj); if (dlzobj != NULL) return (ISC_R_SUCCESS); cfg_map_get(zoptions, "file", &fileobj); if (fileobj != NULL) zfile = cfg_obj_asstring(fileobj); /* * Check hints files for hint zones. * Skip loading checks for any type other than * master and redirect */ if (strcasecmp(cfg_obj_asstring(typeobj), "hint") == 0) return (configure_hint(zfile, zclass, mctx)); else if ((strcasecmp(cfg_obj_asstring(typeobj), "master") != 0) && (strcasecmp(cfg_obj_asstring(typeobj), "redirect") != 0)) return (ISC_R_SUCCESS); /* * Is the redirect zone configured as a slave? */ if (strcasecmp(cfg_obj_asstring(typeobj), "redirect") == 0) { cfg_map_get(zoptions, "masters", &mastersobj); if (mastersobj != NULL) return (ISC_R_SUCCESS); } if (zfile == NULL) return (ISC_R_FAILURE); obj = NULL; if (get_maps(maps, "check-dup-records", &obj)) { if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) { zone_options |= DNS_ZONEOPT_CHECKDUPRR; zone_options &= ~DNS_ZONEOPT_CHECKDUPRRFAIL; } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) { zone_options |= DNS_ZONEOPT_CHECKDUPRR; zone_options |= DNS_ZONEOPT_CHECKDUPRRFAIL; } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) { zone_options &= ~DNS_ZONEOPT_CHECKDUPRR; zone_options &= ~DNS_ZONEOPT_CHECKDUPRRFAIL; } else INSIST(0); } else { zone_options |= DNS_ZONEOPT_CHECKDUPRR; zone_options &= ~DNS_ZONEOPT_CHECKDUPRRFAIL; } obj = NULL; if (get_maps(maps, "check-mx", &obj)) { if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) { zone_options |= DNS_ZONEOPT_CHECKMX; zone_options &= ~DNS_ZONEOPT_CHECKMXFAIL; } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) { zone_options |= DNS_ZONEOPT_CHECKMX; zone_options |= DNS_ZONEOPT_CHECKMXFAIL; } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) { zone_options &= ~DNS_ZONEOPT_CHECKMX; zone_options &= ~DNS_ZONEOPT_CHECKMXFAIL; } else INSIST(0); } else { zone_options |= DNS_ZONEOPT_CHECKMX; zone_options &= ~DNS_ZONEOPT_CHECKMXFAIL; } obj = NULL; if (get_maps(maps, "check-integrity", &obj)) { if (cfg_obj_asboolean(obj)) zone_options |= DNS_ZONEOPT_CHECKINTEGRITY; else zone_options &= ~DNS_ZONEOPT_CHECKINTEGRITY; } else zone_options |= DNS_ZONEOPT_CHECKINTEGRITY; obj = NULL; if (get_maps(maps, "check-mx-cname", &obj)) { if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) { zone_options |= DNS_ZONEOPT_WARNMXCNAME; zone_options &= ~DNS_ZONEOPT_IGNOREMXCNAME; } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) { zone_options &= ~DNS_ZONEOPT_WARNMXCNAME; zone_options &= ~DNS_ZONEOPT_IGNOREMXCNAME; } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) { zone_options |= DNS_ZONEOPT_WARNMXCNAME; zone_options |= DNS_ZONEOPT_IGNOREMXCNAME; } else INSIST(0); } else { zone_options |= DNS_ZONEOPT_WARNMXCNAME; zone_options &= ~DNS_ZONEOPT_IGNOREMXCNAME; } obj = NULL; if (get_maps(maps, "check-srv-cname", &obj)) { if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) { zone_options |= DNS_ZONEOPT_WARNSRVCNAME; zone_options &= ~DNS_ZONEOPT_IGNORESRVCNAME; } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) { zone_options &= ~DNS_ZONEOPT_WARNSRVCNAME; zone_options &= ~DNS_ZONEOPT_IGNORESRVCNAME; } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) { zone_options |= DNS_ZONEOPT_WARNSRVCNAME; zone_options |= DNS_ZONEOPT_IGNORESRVCNAME; } else INSIST(0); } else { zone_options |= DNS_ZONEOPT_WARNSRVCNAME; zone_options &= ~DNS_ZONEOPT_IGNORESRVCNAME; } obj = NULL; if (get_maps(maps, "check-sibling", &obj)) { if (cfg_obj_asboolean(obj)) zone_options |= DNS_ZONEOPT_CHECKSIBLING; else zone_options &= ~DNS_ZONEOPT_CHECKSIBLING; } obj = NULL; if (get_maps(maps, "check-spf", &obj)) { if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) { zone_options |= DNS_ZONEOPT_CHECKSPF; } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) { zone_options &= ~DNS_ZONEOPT_CHECKSPF; } else INSIST(0); } else { zone_options |= DNS_ZONEOPT_CHECKSPF; } obj = NULL; if (get_checknames(maps, &obj)) { if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) { zone_options |= DNS_ZONEOPT_CHECKNAMES; zone_options &= ~DNS_ZONEOPT_CHECKNAMESFAIL; } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) { zone_options |= DNS_ZONEOPT_CHECKNAMES; zone_options |= DNS_ZONEOPT_CHECKNAMESFAIL; } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) { zone_options &= ~DNS_ZONEOPT_CHECKNAMES; zone_options &= ~DNS_ZONEOPT_CHECKNAMESFAIL; } else INSIST(0); } else { zone_options |= DNS_ZONEOPT_CHECKNAMES; zone_options |= DNS_ZONEOPT_CHECKNAMESFAIL; } masterformat = dns_masterformat_text; fmtobj = NULL; if (get_maps(maps, "masterfile-format", &fmtobj)) { const char *masterformatstr = cfg_obj_asstring(fmtobj); if (strcasecmp(masterformatstr, "text") == 0) masterformat = dns_masterformat_text; else if (strcasecmp(masterformatstr, "raw") == 0) masterformat = dns_masterformat_raw; else if (strcasecmp(masterformatstr, "map") == 0) masterformat = dns_masterformat_map; else INSIST(0); } obj = NULL; if (get_maps(maps, "max-zone-ttl", &obj)) { maxttl = cfg_obj_asuint32(obj); zone_options2 |= DNS_ZONEOPT2_CHECKTTL; } result = load_zone(mctx, zname, zfile, masterformat, zclass, maxttl, NULL); if (result != ISC_R_SUCCESS) fprintf(stderr, "%s/%s/%s: %s\n", view, zname, zclass, dns_result_totext(result)); return (result); } /*% configure a view */ static isc_result_t configure_view(const char *vclass, const char *view, const cfg_obj_t *config, const cfg_obj_t *vconfig, isc_mem_t *mctx) { const cfg_listelt_t *element; const cfg_obj_t *voptions; const cfg_obj_t *zonelist; isc_result_t result = ISC_R_SUCCESS; isc_result_t tresult; voptions = NULL; if (vconfig != NULL) voptions = cfg_tuple_get(vconfig, "options"); zonelist = NULL; if (voptions != NULL) (void)cfg_map_get(voptions, "zone", &zonelist); else (void)cfg_map_get(config, "zone", &zonelist); for (element = cfg_list_first(zonelist); element != NULL; element = cfg_list_next(element)) { const cfg_obj_t *zconfig = cfg_listelt_value(element); tresult = configure_zone(vclass, view, zconfig, vconfig, config, mctx); if (tresult != ISC_R_SUCCESS) result = tresult; } return (result); } static isc_result_t config_getclass(const cfg_obj_t *classobj, dns_rdataclass_t defclass, dns_rdataclass_t *classp) { isc_textregion_t r; if (!cfg_obj_isstring(classobj)) { *classp = defclass; return (ISC_R_SUCCESS); } DE_CONST(cfg_obj_asstring(classobj), r.base); r.length = strlen(r.base); return (dns_rdataclass_fromtext(classp, &r)); } /*% load zones from the configuration */ static isc_result_t load_zones_fromconfig(const cfg_obj_t *config, isc_mem_t *mctx) { const cfg_listelt_t *element; const cfg_obj_t *views; const cfg_obj_t *vconfig; isc_result_t result = ISC_R_SUCCESS; isc_result_t tresult; views = NULL; (void)cfg_map_get(config, "view", &views); for (element = cfg_list_first(views); element != NULL; element = cfg_list_next(element)) { const cfg_obj_t *classobj; dns_rdataclass_t viewclass; const char *vname; char buf[sizeof("CLASS65535")]; vconfig = cfg_listelt_value(element); if (vconfig == NULL) continue; classobj = cfg_tuple_get(vconfig, "class"); CHECK(config_getclass(classobj, dns_rdataclass_in, &viewclass)); if (dns_rdataclass_ismeta(viewclass)) CHECK(ISC_R_FAILURE); dns_rdataclass_format(viewclass, buf, sizeof(buf)); vname = cfg_obj_asstring(cfg_tuple_get(vconfig, "name")); tresult = configure_view(buf, vname, config, vconfig, mctx); if (tresult != ISC_R_SUCCESS) result = tresult; } if (views == NULL) { tresult = configure_view("IN", "_default", config, NULL, mctx); if (tresult != ISC_R_SUCCESS) result = tresult; } cleanup: return (result); } static void output(void *closure, const char *text, int textlen) { UNUSED(closure); if (fwrite(text, 1, textlen, stdout) != (size_t)textlen) { perror("fwrite"); exit(1); } } /*% The main processing routine */ int main(int argc, char **argv) { int c; cfg_parser_t *parser = NULL; cfg_obj_t *config = NULL; const char *conffile = NULL; isc_mem_t *mctx = NULL; isc_result_t result; int exit_status = 0; isc_entropy_t *ectx = NULL; isc_boolean_t load_zones = ISC_FALSE; isc_boolean_t print = ISC_FALSE; unsigned int flags = 0; isc_commandline_errprint = ISC_FALSE; /* * Process memory debugging argument first. */ #define CMDLINE_FLAGS "dhjm:t:pvxz" while ((c = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) { switch (c) { case 'm': if (strcasecmp(isc_commandline_argument, "record") == 0) isc_mem_debugging |= ISC_MEM_DEBUGRECORD; if (strcasecmp(isc_commandline_argument, "trace") == 0) isc_mem_debugging |= ISC_MEM_DEBUGTRACE; if (strcasecmp(isc_commandline_argument, "usage") == 0) isc_mem_debugging |= ISC_MEM_DEBUGUSAGE; if (strcasecmp(isc_commandline_argument, "size") == 0) isc_mem_debugging |= ISC_MEM_DEBUGSIZE; if (strcasecmp(isc_commandline_argument, "mctx") == 0) isc_mem_debugging |= ISC_MEM_DEBUGCTX; break; default: break; } } isc_commandline_reset = ISC_TRUE; RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS); while ((c = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != EOF) { switch (c) { case 'd': debug++; break; case 'j': nomerge = ISC_FALSE; break; case 'm': break; case 't': result = isc_dir_chroot(isc_commandline_argument); if (result != ISC_R_SUCCESS) { fprintf(stderr, "isc_dir_chroot: %s\n", isc_result_totext(result)); exit(1); } break; case 'p': print = ISC_TRUE; break; case 'v': printf(VERSION "\n"); exit(0); case 'x': flags |= CFG_PRINTER_XKEY; break; case 'z': load_zones = ISC_TRUE; docheckmx = ISC_FALSE; docheckns = ISC_FALSE; dochecksrv = ISC_FALSE; break; case '?': if (isc_commandline_option != '?') fprintf(stderr, "%s: invalid argument -%c\n", program, isc_commandline_option); /* FALLTHROUGH */ case 'h': usage(); default: fprintf(stderr, "%s: unhandled option -%c\n", program, isc_commandline_option); exit(1); } } if (((flags & CFG_PRINTER_XKEY) != 0) && !print) { fprintf(stderr, "%s: -x cannot be used without -p\n", program); exit(1); } if (isc_commandline_index + 1 < argc) usage(); if (argv[isc_commandline_index] != NULL) conffile = argv[isc_commandline_index]; if (conffile == NULL || conffile[0] == '\0') conffile = NAMED_CONFFILE; #ifdef _WIN32 InitSockets(); #endif RUNTIME_CHECK(setup_logging(mctx, stdout, &logc) == ISC_R_SUCCESS); RUNTIME_CHECK(isc_entropy_create(mctx, &ectx) == ISC_R_SUCCESS); RUNTIME_CHECK(isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE) == ISC_R_SUCCESS); dns_result_register(); RUNTIME_CHECK(cfg_parser_create(mctx, logc, &parser) == ISC_R_SUCCESS); cfg_parser_setcallback(parser, directory_callback, NULL); if (cfg_parse_file(parser, conffile, &cfg_type_namedconf, &config) != ISC_R_SUCCESS) exit(1); result = bind9_check_namedconf(config, logc, mctx); if (result != ISC_R_SUCCESS) exit_status = 1; if (result == ISC_R_SUCCESS && load_zones) { result = load_zones_fromconfig(config, mctx); if (result != ISC_R_SUCCESS) exit_status = 1; } if (print && exit_status == 0) cfg_printx(config, flags, output, NULL); cfg_obj_destroy(parser, &config); cfg_parser_destroy(&parser); dns_name_destroy(); isc_log_destroy(&logc); isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); #ifdef _WIN32 DestroySockets(); #endif return (exit_status); } bind9-9.11.3+dfsg/bin/check/named-checkconf.docbook000066400000000000000000000136171325250447100217400ustar00rootroot00000000000000]> 2014-01-10 ISC Internet Systems Consortium, Inc. named-checkconf 8 BIND9 2000 2001 2002 2004 2005 2007 2009 2014 2015 2016 Internet Systems Consortium, Inc. ("ISC") named-checkconf named configuration file syntax checking tool named-checkconf filename DESCRIPTION named-checkconf checks the syntax, but not the semantics, of a named configuration file. The file is parsed and checked for syntax errors, along with all files included by it. If no file is specified, /etc/named.conf is read by default. Note: files that named reads in separate parser contexts, such as rndc.key and bind.keys, are not automatically read by named-checkconf. Configuration errors in these files may cause named to fail to run, even if named-checkconf was successful. named-checkconf can be run on these files explicitly, however. OPTIONS -h Print the usage summary and exit. -j When loading a zonefile read the journal if it exists. -p Print out the named.conf and included files in canonical form if no errors were detected. See also the option. -t directory Chroot to directory so that include directives in the configuration file are processed as if run by a similarly chrooted named. -v Print the version of the named-checkconf program and exit. -x When printing the configuration files in canonical form, obscure shared secrets by replacing them with strings of question marks ('?'). This allows the contents of named.conf and related files to be shared — for example, when submitting bug reports — without compromising private data. This option cannot be used without . -z Perform a test load of all master zones found in named.conf. filename The name of the configuration file to be checked. If not specified, it defaults to /etc/named.conf. RETURN VALUES named-checkconf returns an exit status of 1 if errors were detected and 0 otherwise. SEE ALSO named8 , named-checkzone8 , BIND 9 Administrator Reference Manual. bind9-9.11.3+dfsg/bin/check/named-checkconf.html000066400000000000000000000125161325250447100212610ustar00rootroot00000000000000 named-checkconf

Name

named-checkconf — named configuration file syntax checking tool

Synopsis

named-checkconf [-hjvz] [-p [-x ]] [-t directory] {filename}

DESCRIPTION

named-checkconf checks the syntax, but not the semantics, of a named configuration file. The file is parsed and checked for syntax errors, along with all files included by it. If no file is specified, /etc/named.conf is read by default.

Note: files that named reads in separate parser contexts, such as rndc.key and bind.keys, are not automatically read by named-checkconf. Configuration errors in these files may cause named to fail to run, even if named-checkconf was successful. named-checkconf can be run on these files explicitly, however.

OPTIONS

-h

Print the usage summary and exit.

-j

When loading a zonefile read the journal if it exists.

-p

Print out the named.conf and included files in canonical form if no errors were detected. See also the -x option.

-t directory

Chroot to directory so that include directives in the configuration file are processed as if run by a similarly chrooted named.

-v

Print the version of the named-checkconf program and exit.

-x

When printing the configuration files in canonical form, obscure shared secrets by replacing them with strings of question marks ('?'). This allows the contents of named.conf and related files to be shared — for example, when submitting bug reports — without compromising private data. This option cannot be used without -p.

-z

Perform a test load of all master zones found in named.conf.

filename

The name of the configuration file to be checked. If not specified, it defaults to /etc/named.conf.

RETURN VALUES

named-checkconf returns an exit status of 1 if errors were detected and 0 otherwise.

SEE ALSO

named(8) , named-checkzone(8) , BIND 9 Administrator Reference Manual.

bind9-9.11.3+dfsg/bin/check/named-checkzone.8000066400000000000000000000236441325250447100205160ustar00rootroot00000000000000.\" Copyright (C) 2000-2002, 2004-2007, 2009-2016 Internet Systems Consortium, Inc. ("ISC") .\" .\" This Source Code Form is subject to the terms of the Mozilla Public .\" License, v. 2.0. If a copy of the MPL was not distributed with this .\" file, You can obtain one at http://mozilla.org/MPL/2.0/. .\" .hy 0 .ad l '\" t .\" Title: named-checkzone .\" Author: .\" Generator: DocBook XSL Stylesheets v1.78.1 .\" Date: 2014-02-19 .\" Manual: BIND9 .\" Source: ISC .\" Language: English .\" .TH "NAMED\-CHECKZONE" "8" "2014\-02\-19" "ISC" "BIND9" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" named-checkzone, named-compilezone \- zone file validity checking or converting tool .SH "SYNOPSIS" .HP \w'\fBnamed\-checkzone\fR\ 'u \fBnamed\-checkzone\fR [\fB\-d\fR] [\fB\-h\fR] [\fB\-j\fR] [\fB\-q\fR] [\fB\-v\fR] [\fB\-c\ \fR\fB\fIclass\fR\fR] [\fB\-f\ \fR\fB\fIformat\fR\fR] [\fB\-F\ \fR\fB\fIformat\fR\fR] [\fB\-J\ \fR\fB\fIfilename\fR\fR] [\fB\-i\ \fR\fB\fImode\fR\fR] [\fB\-k\ \fR\fB\fImode\fR\fR] [\fB\-m\ \fR\fB\fImode\fR\fR] [\fB\-M\ \fR\fB\fImode\fR\fR] [\fB\-n\ \fR\fB\fImode\fR\fR] [\fB\-l\ \fR\fB\fIttl\fR\fR] [\fB\-L\ \fR\fB\fIserial\fR\fR] [\fB\-o\ \fR\fB\fIfilename\fR\fR] [\fB\-r\ \fR\fB\fImode\fR\fR] [\fB\-s\ \fR\fB\fIstyle\fR\fR] [\fB\-S\ \fR\fB\fImode\fR\fR] [\fB\-t\ \fR\fB\fIdirectory\fR\fR] [\fB\-T\ \fR\fB\fImode\fR\fR] [\fB\-w\ \fR\fB\fIdirectory\fR\fR] [\fB\-D\fR] [\fB\-W\ \fR\fB\fImode\fR\fR] {zonename} {filename} .HP \w'\fBnamed\-compilezone\fR\ 'u \fBnamed\-compilezone\fR [\fB\-d\fR] [\fB\-j\fR] [\fB\-q\fR] [\fB\-v\fR] [\fB\-c\ \fR\fB\fIclass\fR\fR] [\fB\-C\ \fR\fB\fImode\fR\fR] [\fB\-f\ \fR\fB\fIformat\fR\fR] [\fB\-F\ \fR\fB\fIformat\fR\fR] [\fB\-J\ \fR\fB\fIfilename\fR\fR] [\fB\-i\ \fR\fB\fImode\fR\fR] [\fB\-k\ \fR\fB\fImode\fR\fR] [\fB\-m\ \fR\fB\fImode\fR\fR] [\fB\-n\ \fR\fB\fImode\fR\fR] [\fB\-l\ \fR\fB\fIttl\fR\fR] [\fB\-L\ \fR\fB\fIserial\fR\fR] [\fB\-r\ \fR\fB\fImode\fR\fR] [\fB\-s\ \fR\fB\fIstyle\fR\fR] [\fB\-t\ \fR\fB\fIdirectory\fR\fR] [\fB\-T\ \fR\fB\fImode\fR\fR] [\fB\-w\ \fR\fB\fIdirectory\fR\fR] [\fB\-D\fR] [\fB\-W\ \fR\fB\fImode\fR\fR] {\fB\-o\ \fR\fB\fIfilename\fR\fR} {zonename} {filename} .SH "DESCRIPTION" .PP \fBnamed\-checkzone\fR checks the syntax and integrity of a zone file\&. It performs the same checks as \fBnamed\fR does when loading a zone\&. This makes \fBnamed\-checkzone\fR useful for checking zone files before configuring them into a name server\&. .PP \fBnamed\-compilezone\fR is similar to \fBnamed\-checkzone\fR, but it always dumps the zone contents to a specified file in a specified format\&. Additionally, it applies stricter check levels by default, since the dump output will be used as an actual zone file loaded by \fBnamed\fR\&. When manually specified otherwise, the check levels must at least be as strict as those specified in the \fBnamed\fR configuration file\&. .SH "OPTIONS" .PP \-d .RS 4 Enable debugging\&. .RE .PP \-h .RS 4 Print the usage summary and exit\&. .RE .PP \-q .RS 4 Quiet mode \- exit code only\&. .RE .PP \-v .RS 4 Print the version of the \fBnamed\-checkzone\fR program and exit\&. .RE .PP \-j .RS 4 When loading a zone file, read the journal if it exists\&. The journal file name is assumed to be the zone file name appended with the string \&.jnl\&. .RE .PP \-J \fIfilename\fR .RS 4 When loading the zone file read the journal from the given file, if it exists\&. (Implies \-j\&.) .RE .PP \-c \fIclass\fR .RS 4 Specify the class of the zone\&. If not specified, "IN" is assumed\&. .RE .PP \-i \fImode\fR .RS 4 Perform post\-load zone integrity checks\&. Possible modes are \fB"full"\fR (default), \fB"full\-sibling"\fR, \fB"local"\fR, \fB"local\-sibling"\fR and \fB"none"\fR\&. .sp Mode \fB"full"\fR checks that MX records refer to A or AAAA record (both in\-zone and out\-of\-zone hostnames)\&. Mode \fB"local"\fR only checks MX records which refer to in\-zone hostnames\&. .sp Mode \fB"full"\fR checks that SRV records refer to A or AAAA record (both in\-zone and out\-of\-zone hostnames)\&. Mode \fB"local"\fR only checks SRV records which refer to in\-zone hostnames\&. .sp Mode \fB"full"\fR checks that delegation NS records refer to A or AAAA record (both in\-zone and out\-of\-zone hostnames)\&. It also checks that glue address records in the zone match those advertised by the child\&. Mode \fB"local"\fR only checks NS records which refer to in\-zone hostnames or that some required glue exists, that is when the nameserver is in a child zone\&. .sp Mode \fB"full\-sibling"\fR and \fB"local\-sibling"\fR disable sibling glue checks but are otherwise the same as \fB"full"\fR and \fB"local"\fR respectively\&. .sp Mode \fB"none"\fR disables the checks\&. .RE .PP \-f \fIformat\fR .RS 4 Specify the format of the zone file\&. Possible formats are \fB"text"\fR (default), \fB"raw"\fR, and \fB"map"\fR\&. .RE .PP \-F \fIformat\fR .RS 4 Specify the format of the output file specified\&. For \fBnamed\-checkzone\fR, this does not cause any effects unless it dumps the zone contents\&. .sp Possible formats are \fB"text"\fR (default), which is the standard textual representation of the zone, and \fB"map"\fR, \fB"raw"\fR, and \fB"raw=N"\fR, which store the zone in a binary format for rapid loading by \fBnamed\fR\&. \fB"raw=N"\fR specifies the format version of the raw zone file: if N is 0, the raw file can be read by any version of \fBnamed\fR; if N is 1, the file can be read by release 9\&.9\&.0 or higher; the default is 1\&. .RE .PP \-k \fImode\fR .RS 4 Perform \fB"check\-names"\fR checks with the specified failure mode\&. Possible modes are \fB"fail"\fR (default for \fBnamed\-compilezone\fR), \fB"warn"\fR (default for \fBnamed\-checkzone\fR) and \fB"ignore"\fR\&. .RE .PP \-l \fIttl\fR .RS 4 Sets a maximum permissible TTL for the input file\&. Any record with a TTL higher than this value will cause the zone to be rejected\&. This is similar to using the \fBmax\-zone\-ttl\fR option in named\&.conf\&. .RE .PP \-L \fIserial\fR .RS 4 When compiling a zone to "raw" or "map" format, set the "source serial" value in the header to the specified serial number\&. (This is expected to be used primarily for testing purposes\&.) .RE .PP \-m \fImode\fR .RS 4 Specify whether MX records should be checked to see if they are addresses\&. Possible modes are \fB"fail"\fR, \fB"warn"\fR (default) and \fB"ignore"\fR\&. .RE .PP \-M \fImode\fR .RS 4 Check if a MX record refers to a CNAME\&. Possible modes are \fB"fail"\fR, \fB"warn"\fR (default) and \fB"ignore"\fR\&. .RE .PP \-n \fImode\fR .RS 4 Specify whether NS records should be checked to see if they are addresses\&. Possible modes are \fB"fail"\fR (default for \fBnamed\-compilezone\fR), \fB"warn"\fR (default for \fBnamed\-checkzone\fR) and \fB"ignore"\fR\&. .RE .PP \-o \fIfilename\fR .RS 4 Write zone output to filename\&. If filename is \- then write to standard out\&. This is mandatory for \fBnamed\-compilezone\fR\&. .RE .PP \-r \fImode\fR .RS 4 Check for records that are treated as different by DNSSEC but are semantically equal in plain DNS\&. Possible modes are \fB"fail"\fR, \fB"warn"\fR (default) and \fB"ignore"\fR\&. .RE .PP \-s \fIstyle\fR .RS 4 Specify the style of the dumped zone file\&. Possible styles are \fB"full"\fR (default) and \fB"relative"\fR\&. The full format is most suitable for processing automatically by a separate script\&. On the other hand, the relative format is more human\-readable and is thus suitable for editing by hand\&. For \fBnamed\-checkzone\fR this does not cause any effects unless it dumps the zone contents\&. It also does not have any meaning if the output format is not text\&. .RE .PP \-S \fImode\fR .RS 4 Check if a SRV record refers to a CNAME\&. Possible modes are \fB"fail"\fR, \fB"warn"\fR (default) and \fB"ignore"\fR\&. .RE .PP \-t \fIdirectory\fR .RS 4 Chroot to directory so that include directives in the configuration file are processed as if run by a similarly chrooted \fBnamed\fR\&. .RE .PP \-T \fImode\fR .RS 4 Check if Sender Policy Framework (SPF) records exist and issues a warning if an SPF\-formatted TXT record is not also present\&. Possible modes are \fB"warn"\fR (default), \fB"ignore"\fR\&. .RE .PP \-w \fIdirectory\fR .RS 4 chdir to directory so that relative filenames in master file $INCLUDE directives work\&. This is similar to the directory clause in named\&.conf\&. .RE .PP \-D .RS 4 Dump zone file in canonical format\&. This is always enabled for \fBnamed\-compilezone\fR\&. .RE .PP \-W \fImode\fR .RS 4 Specify whether to check for non\-terminal wildcards\&. Non\-terminal wildcards are almost always the result of a failure to understand the wildcard matching algorithm (RFC 1034)\&. Possible modes are \fB"warn"\fR (default) and \fB"ignore"\fR\&. .RE .PP zonename .RS 4 The domain name of the zone being checked\&. .RE .PP filename .RS 4 The name of the zone file\&. .RE .SH "RETURN VALUES" .PP \fBnamed\-checkzone\fR returns an exit status of 1 if errors were detected and 0 otherwise\&. .SH "SEE ALSO" .PP \fBnamed\fR(8), \fBnamed-checkconf\fR(8), RFC 1035, BIND 9 Administrator Reference Manual\&. .SH "AUTHOR" .PP \fBInternet Systems Consortium, Inc\&.\fR .SH "COPYRIGHT" .br Copyright \(co 2000-2002, 2004-2007, 2009-2016 Internet Systems Consortium, Inc. ("ISC") .br bind9-9.11.3+dfsg/bin/check/named-checkzone.c000066400000000000000000000336601325250447100205700ustar00rootroot00000000000000/* * Copyright (C) 1999-2016 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* $Id: named-checkzone.c,v 1.65.32.2 2012/02/07 02:45:21 each Exp $ */ /*! \file */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "check-tool.h" static int quiet = 0; static isc_mem_t *mctx = NULL; static isc_entropy_t *ectx = NULL; dns_zone_t *zone = NULL; dns_zonetype_t zonetype = dns_zone_master; static int dumpzone = 0; static const char *output_filename; static const char *prog_name = NULL; static const dns_master_style_t *outputstyle = NULL; static enum { progmode_check, progmode_compile } progmode; #define ERRRET(result, function) \ do { \ if (result != ISC_R_SUCCESS) { \ if (!quiet) \ fprintf(stderr, "%s() returned %s\n", \ function, dns_result_totext(result)); \ return (result); \ } \ } while (0) ISC_PLATFORM_NORETURN_PRE static void usage(void) ISC_PLATFORM_NORETURN_POST; static void usage(void) { fprintf(stderr, "usage: %s [-djqvD] [-c class] " "[-f inputformat] [-F outputformat] [-J filename] " "[-t directory] [-w directory] [-k (ignore|warn|fail)] " "[-n (ignore|warn|fail)] [-m (ignore|warn|fail)] " "[-r (ignore|warn|fail)] " "[-i (full|full-sibling|local|local-sibling|none)] " "[-M (ignore|warn|fail)] [-S (ignore|warn|fail)] " "[-W (ignore|warn)] " "%s zonename filename\n", prog_name, progmode == progmode_check ? "[-o filename]" : "-o filename"); exit(1); } static void destroy(void) { if (zone != NULL) dns_zone_detach(&zone); dns_name_destroy(); } /*% main processing routine */ int main(int argc, char **argv) { int c; char *origin = NULL; char *filename = NULL; isc_log_t *lctx = NULL; isc_result_t result; char classname_in[] = "IN"; char *classname = classname_in; const char *workdir = NULL; const char *inputformatstr = NULL; const char *outputformatstr = NULL; dns_masterformat_t inputformat = dns_masterformat_text; dns_masterformat_t outputformat = dns_masterformat_text; dns_masterrawheader_t header; isc_uint32_t rawversion = 1, serialnum = 0; dns_ttl_t maxttl = 0; isc_boolean_t snset = ISC_FALSE; isc_boolean_t logdump = ISC_FALSE; FILE *errout = stdout; char *endp; /* * Uncomment the following line if memory debugging is needed: * isc_mem_debugging |= ISC_MEM_DEBUGRECORD; */ outputstyle = &dns_master_style_full; prog_name = strrchr(argv[0], '/'); if (prog_name == NULL) prog_name = strrchr(argv[0], '\\'); if (prog_name != NULL) prog_name++; else prog_name = argv[0]; /* * Libtool doesn't preserve the program name prior to final * installation. Remove the libtool prefix ("lt-"). */ if (strncmp(prog_name, "lt-", 3) == 0) prog_name += 3; #define PROGCMP(X) \ (strcasecmp(prog_name, X) == 0 || strcasecmp(prog_name, X ".exe") == 0) if (PROGCMP("named-checkzone")) progmode = progmode_check; else if (PROGCMP("named-compilezone")) progmode = progmode_compile; else INSIST(0); /* Compilation specific defaults */ if (progmode == progmode_compile) { zone_options |= (DNS_ZONEOPT_CHECKNS | DNS_ZONEOPT_FATALNS | DNS_ZONEOPT_CHECKSPF | DNS_ZONEOPT_CHECKDUPRR | DNS_ZONEOPT_CHECKNAMES | DNS_ZONEOPT_CHECKNAMESFAIL | DNS_ZONEOPT_CHECKWILDCARD); } else zone_options |= (DNS_ZONEOPT_CHECKDUPRR | DNS_ZONEOPT_CHECKSPF); #define ARGCMP(X) (strcmp(isc_commandline_argument, X) == 0) isc_commandline_errprint = ISC_FALSE; while ((c = isc_commandline_parse(argc, argv, "c:df:hi:jJ:k:L:l:m:n:qr:s:t:o:vw:DF:M:S:T:W:")) != EOF) { switch (c) { case 'c': classname = isc_commandline_argument; break; case 'd': debug++; break; case 'i': if (ARGCMP("full")) { zone_options |= DNS_ZONEOPT_CHECKINTEGRITY | DNS_ZONEOPT_CHECKSIBLING; docheckmx = ISC_TRUE; docheckns = ISC_TRUE; dochecksrv = ISC_TRUE; } else if (ARGCMP("full-sibling")) { zone_options |= DNS_ZONEOPT_CHECKINTEGRITY; zone_options &= ~DNS_ZONEOPT_CHECKSIBLING; docheckmx = ISC_TRUE; docheckns = ISC_TRUE; dochecksrv = ISC_TRUE; } else if (ARGCMP("local")) { zone_options |= DNS_ZONEOPT_CHECKINTEGRITY; zone_options |= DNS_ZONEOPT_CHECKSIBLING; docheckmx = ISC_FALSE; docheckns = ISC_FALSE; dochecksrv = ISC_FALSE; } else if (ARGCMP("local-sibling")) { zone_options |= DNS_ZONEOPT_CHECKINTEGRITY; zone_options &= ~DNS_ZONEOPT_CHECKSIBLING; docheckmx = ISC_FALSE; docheckns = ISC_FALSE; dochecksrv = ISC_FALSE; } else if (ARGCMP("none")) { zone_options &= ~DNS_ZONEOPT_CHECKINTEGRITY; zone_options &= ~DNS_ZONEOPT_CHECKSIBLING; docheckmx = ISC_FALSE; docheckns = ISC_FALSE; dochecksrv = ISC_FALSE; } else { fprintf(stderr, "invalid argument to -i: %s\n", isc_commandline_argument); exit(1); } break; case 'f': inputformatstr = isc_commandline_argument; break; case 'F': outputformatstr = isc_commandline_argument; break; case 'j': nomerge = ISC_FALSE; break; case 'J': journal = isc_commandline_argument; nomerge = ISC_FALSE; break; case 'k': if (ARGCMP("warn")) { zone_options |= DNS_ZONEOPT_CHECKNAMES; zone_options &= ~DNS_ZONEOPT_CHECKNAMESFAIL; } else if (ARGCMP("fail")) { zone_options |= DNS_ZONEOPT_CHECKNAMES | DNS_ZONEOPT_CHECKNAMESFAIL; } else if (ARGCMP("ignore")) { zone_options &= ~(DNS_ZONEOPT_CHECKNAMES | DNS_ZONEOPT_CHECKNAMESFAIL); } else { fprintf(stderr, "invalid argument to -k: %s\n", isc_commandline_argument); exit(1); } break; case 'L': snset = ISC_TRUE; endp = NULL; serialnum = strtol(isc_commandline_argument, &endp, 0); if (*endp != '\0') { fprintf(stderr, "source serial number " "must be numeric"); exit(1); } break; case 'l': zone_options2 |= DNS_ZONEOPT2_CHECKTTL; endp = NULL; maxttl = strtol(isc_commandline_argument, &endp, 0); if (*endp != '\0') { fprintf(stderr, "maximum TTL " "must be numeric"); exit(1); } break; case 'n': if (ARGCMP("ignore")) { zone_options &= ~(DNS_ZONEOPT_CHECKNS| DNS_ZONEOPT_FATALNS); } else if (ARGCMP("warn")) { zone_options |= DNS_ZONEOPT_CHECKNS; zone_options &= ~DNS_ZONEOPT_FATALNS; } else if (ARGCMP("fail")) { zone_options |= DNS_ZONEOPT_CHECKNS| DNS_ZONEOPT_FATALNS; } else { fprintf(stderr, "invalid argument to -n: %s\n", isc_commandline_argument); exit(1); } break; case 'm': if (ARGCMP("warn")) { zone_options |= DNS_ZONEOPT_CHECKMX; zone_options &= ~DNS_ZONEOPT_CHECKMXFAIL; } else if (ARGCMP("fail")) { zone_options |= DNS_ZONEOPT_CHECKMX | DNS_ZONEOPT_CHECKMXFAIL; } else if (ARGCMP("ignore")) { zone_options &= ~(DNS_ZONEOPT_CHECKMX | DNS_ZONEOPT_CHECKMXFAIL); } else { fprintf(stderr, "invalid argument to -m: %s\n", isc_commandline_argument); exit(1); } break; case 'o': output_filename = isc_commandline_argument; break; case 'q': quiet++; break; case 'r': if (ARGCMP("warn")) { zone_options |= DNS_ZONEOPT_CHECKDUPRR; zone_options &= ~DNS_ZONEOPT_CHECKDUPRRFAIL; } else if (ARGCMP("fail")) { zone_options |= DNS_ZONEOPT_CHECKDUPRR | DNS_ZONEOPT_CHECKDUPRRFAIL; } else if (ARGCMP("ignore")) { zone_options &= ~(DNS_ZONEOPT_CHECKDUPRR | DNS_ZONEOPT_CHECKDUPRRFAIL); } else { fprintf(stderr, "invalid argument to -r: %s\n", isc_commandline_argument); exit(1); } break; case 's': if (ARGCMP("full")) outputstyle = &dns_master_style_full; else if (ARGCMP("relative")) { outputstyle = &dns_master_style_default; } else { fprintf(stderr, "unknown or unsupported style: %s\n", isc_commandline_argument); exit(1); } break; case 't': result = isc_dir_chroot(isc_commandline_argument); if (result != ISC_R_SUCCESS) { fprintf(stderr, "isc_dir_chroot: %s: %s\n", isc_commandline_argument, isc_result_totext(result)); exit(1); } break; case 'v': printf(VERSION "\n"); exit(0); case 'w': workdir = isc_commandline_argument; break; case 'D': dumpzone++; break; case 'M': if (ARGCMP("fail")) { zone_options &= ~DNS_ZONEOPT_WARNMXCNAME; zone_options &= ~DNS_ZONEOPT_IGNOREMXCNAME; } else if (ARGCMP("warn")) { zone_options |= DNS_ZONEOPT_WARNMXCNAME; zone_options &= ~DNS_ZONEOPT_IGNOREMXCNAME; } else if (ARGCMP("ignore")) { zone_options |= DNS_ZONEOPT_WARNMXCNAME; zone_options |= DNS_ZONEOPT_IGNOREMXCNAME; } else { fprintf(stderr, "invalid argument to -M: %s\n", isc_commandline_argument); exit(1); } break; case 'S': if (ARGCMP("fail")) { zone_options &= ~DNS_ZONEOPT_WARNSRVCNAME; zone_options &= ~DNS_ZONEOPT_IGNORESRVCNAME; } else if (ARGCMP("warn")) { zone_options |= DNS_ZONEOPT_WARNSRVCNAME; zone_options &= ~DNS_ZONEOPT_IGNORESRVCNAME; } else if (ARGCMP("ignore")) { zone_options |= DNS_ZONEOPT_WARNSRVCNAME; zone_options |= DNS_ZONEOPT_IGNORESRVCNAME; } else { fprintf(stderr, "invalid argument to -S: %s\n", isc_commandline_argument); exit(1); } break; case 'T': if (ARGCMP("warn")) { zone_options |= DNS_ZONEOPT_CHECKSPF; } else if (ARGCMP("ignore")) { zone_options &= ~DNS_ZONEOPT_CHECKSPF; } else { fprintf(stderr, "invalid argument to -T: %s\n", isc_commandline_argument); exit(1); } break; case 'W': if (ARGCMP("warn")) zone_options |= DNS_ZONEOPT_CHECKWILDCARD; else if (ARGCMP("ignore")) zone_options &= ~DNS_ZONEOPT_CHECKWILDCARD; break; case '?': if (isc_commandline_option != '?') fprintf(stderr, "%s: invalid argument -%c\n", prog_name, isc_commandline_option); /* FALLTHROUGH */ case 'h': usage(); default: fprintf(stderr, "%s: unhandled option -%c\n", prog_name, isc_commandline_option); exit(1); } } if (workdir != NULL) { result = isc_dir_chdir(workdir); if (result != ISC_R_SUCCESS) { fprintf(stderr, "isc_dir_chdir: %s: %s\n", workdir, isc_result_totext(result)); exit(1); } } if (inputformatstr != NULL) { if (strcasecmp(inputformatstr, "text") == 0) inputformat = dns_masterformat_text; else if (strcasecmp(inputformatstr, "raw") == 0) inputformat = dns_masterformat_raw; else if (strncasecmp(inputformatstr, "raw=", 4) == 0) { inputformat = dns_masterformat_raw; fprintf(stderr, "WARNING: input format raw, version ignored\n"); } else if (strcasecmp(inputformatstr, "map") == 0) { inputformat = dns_masterformat_map; } else { fprintf(stderr, "unknown file format: %s\n", inputformatstr); exit(1); } } if (outputformatstr != NULL) { if (strcasecmp(outputformatstr, "text") == 0) { outputformat = dns_masterformat_text; } else if (strcasecmp(outputformatstr, "raw") == 0) { outputformat = dns_masterformat_raw; } else if (strncasecmp(outputformatstr, "raw=", 4) == 0) { char *end; outputformat = dns_masterformat_raw; rawversion = strtol(outputformatstr + 4, &end, 10); if (end == outputformatstr + 4 || *end != '\0' || rawversion > 1U) { fprintf(stderr, "unknown raw format version\n"); exit(1); } } else if (strcasecmp(outputformatstr, "map") == 0) { outputformat = dns_masterformat_map; } else { fprintf(stderr, "unknown file format: %s\n", outputformatstr); exit(1); } } if (progmode == progmode_compile) { dumpzone = 1; /* always dump */ logdump = !quiet; if (output_filename == NULL) { fprintf(stderr, "output file required, but not specified\n"); usage(); } } if (output_filename != NULL) dumpzone = 1; /* * If we are outputing to stdout then send the informational * output to stderr. */ if (dumpzone && (output_filename == NULL || strcmp(output_filename, "-") == 0 || strcmp(output_filename, "/dev/fd/1") == 0 || strcmp(output_filename, "/dev/stdout") == 0)) { errout = stderr; logdump = ISC_FALSE; } if (isc_commandline_index + 2 != argc) usage(); #ifdef _WIN32 InitSockets(); #endif RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS); if (!quiet) RUNTIME_CHECK(setup_logging(mctx, errout, &lctx) == ISC_R_SUCCESS); RUNTIME_CHECK(isc_entropy_create(mctx, &ectx) == ISC_R_SUCCESS); RUNTIME_CHECK(isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE) == ISC_R_SUCCESS); dns_result_register(); origin = argv[isc_commandline_index++]; filename = argv[isc_commandline_index++]; result = load_zone(mctx, origin, filename, inputformat, classname, maxttl, &zone); if (snset) { dns_master_initrawheader(&header); header.flags = DNS_MASTERRAW_SOURCESERIALSET; header.sourceserial = serialnum; dns_zone_setrawdata(zone, &header); } if (result == ISC_R_SUCCESS && dumpzone) { if (logdump) { fprintf(errout, "dump zone to %s...", output_filename); fflush(errout); } result = dump_zone(origin, zone, output_filename, outputformat, outputstyle, rawversion); if (logdump) fprintf(errout, "done\n"); } if (!quiet && result == ISC_R_SUCCESS) fprintf(errout, "OK\n"); destroy(); if (lctx != NULL) isc_log_destroy(&lctx); isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); #ifdef _WIN32 DestroySockets(); #endif return ((result == ISC_R_SUCCESS) ? 0 : 1); } bind9-9.11.3+dfsg/bin/check/named-checkzone.docbook000066400000000000000000000501621325250447100217620ustar00rootroot00000000000000 2014-02-19 ISC Internet Systems Consortium, Inc. named-checkzone 8 BIND9 2000 2001 2002 2004 2005 2006 2007 2009 2010 2011 2012 2013 2014 2015 2016 Internet Systems Consortium, Inc. ("ISC") named-checkzone named-compilezone zone file validity checking or converting tool named-checkzone zonename filename named-compilezone zonename filename DESCRIPTION named-checkzone checks the syntax and integrity of a zone file. It performs the same checks as named does when loading a zone. This makes named-checkzone useful for checking zone files before configuring them into a name server. named-compilezone is similar to named-checkzone, but it always dumps the zone contents to a specified file in a specified format. Additionally, it applies stricter check levels by default, since the dump output will be used as an actual zone file loaded by named. When manually specified otherwise, the check levels must at least be as strict as those specified in the named configuration file. OPTIONS -d Enable debugging. -h Print the usage summary and exit. -q Quiet mode - exit code only. -v Print the version of the named-checkzone program and exit. -j When loading a zone file, read the journal if it exists. The journal file name is assumed to be the zone file name appended with the string .jnl. -J filename When loading the zone file read the journal from the given file, if it exists. (Implies -j.) -c class Specify the class of the zone. If not specified, "IN" is assumed. -i mode Perform post-load zone integrity checks. Possible modes are "full" (default), "full-sibling", "local", "local-sibling" and "none". Mode "full" checks that MX records refer to A or AAAA record (both in-zone and out-of-zone hostnames). Mode "local" only checks MX records which refer to in-zone hostnames. Mode "full" checks that SRV records refer to A or AAAA record (both in-zone and out-of-zone hostnames). Mode "local" only checks SRV records which refer to in-zone hostnames. Mode "full" checks that delegation NS records refer to A or AAAA record (both in-zone and out-of-zone hostnames). It also checks that glue address records in the zone match those advertised by the child. Mode "local" only checks NS records which refer to in-zone hostnames or that some required glue exists, that is when the nameserver is in a child zone. Mode "full-sibling" and "local-sibling" disable sibling glue checks but are otherwise the same as "full" and "local" respectively. Mode "none" disables the checks. -f format Specify the format of the zone file. Possible formats are "text" (default), "raw", and "map". -F format Specify the format of the output file specified. For named-checkzone, this does not cause any effects unless it dumps the zone contents. Possible formats are "text" (default), which is the standard textual representation of the zone, and "map", "raw", and "raw=N", which store the zone in a binary format for rapid loading by named. "raw=N" specifies the format version of the raw zone file: if N is 0, the raw file can be read by any version of named; if N is 1, the file can be read by release 9.9.0 or higher; the default is 1. -k mode Perform "check-names" checks with the specified failure mode. Possible modes are "fail" (default for named-compilezone), "warn" (default for named-checkzone) and "ignore". -l ttl Sets a maximum permissible TTL for the input file. Any record with a TTL higher than this value will cause the zone to be rejected. This is similar to using the max-zone-ttl option in named.conf. -L serial When compiling a zone to "raw" or "map" format, set the "source serial" value in the header to the specified serial number. (This is expected to be used primarily for testing purposes.) -m mode Specify whether MX records should be checked to see if they are addresses. Possible modes are "fail", "warn" (default) and "ignore". -M mode Check if a MX record refers to a CNAME. Possible modes are "fail", "warn" (default) and "ignore". -n mode Specify whether NS records should be checked to see if they are addresses. Possible modes are "fail" (default for named-compilezone), "warn" (default for named-checkzone) and "ignore". -o filename Write zone output to filename. If filename is - then write to standard out. This is mandatory for named-compilezone. -r mode Check for records that are treated as different by DNSSEC but are semantically equal in plain DNS. Possible modes are "fail", "warn" (default) and "ignore". -s style Specify the style of the dumped zone file. Possible styles are "full" (default) and "relative". The full format is most suitable for processing automatically by a separate script. On the other hand, the relative format is more human-readable and is thus suitable for editing by hand. For named-checkzone this does not cause any effects unless it dumps the zone contents. It also does not have any meaning if the output format is not text. -S mode Check if a SRV record refers to a CNAME. Possible modes are "fail", "warn" (default) and "ignore". -t directory Chroot to directory so that include directives in the configuration file are processed as if run by a similarly chrooted named. -T mode Check if Sender Policy Framework (SPF) records exist and issues a warning if an SPF-formatted TXT record is not also present. Possible modes are "warn" (default), "ignore". -w directory chdir to directory so that relative filenames in master file $INCLUDE directives work. This is similar to the directory clause in named.conf. -D Dump zone file in canonical format. This is always enabled for named-compilezone. -W mode Specify whether to check for non-terminal wildcards. Non-terminal wildcards are almost always the result of a failure to understand the wildcard matching algorithm (RFC 1034). Possible modes are "warn" (default) and "ignore". zonename The domain name of the zone being checked. filename The name of the zone file. RETURN VALUES named-checkzone returns an exit status of 1 if errors were detected and 0 otherwise. SEE ALSO named8 , named-checkconf8 , RFC 1035, BIND 9 Administrator Reference Manual. bind9-9.11.3+dfsg/bin/check/named-checkzone.html000066400000000000000000000453251325250447100213130ustar00rootroot00000000000000 named-checkzone

Name

named-checkzone, named-compilezone — zone file validity checking or converting tool

Synopsis

named-checkzone [-d] [-h] [-j] [-q] [-v] [-c class] [-f format] [-F format] [-J filename] [-i mode] [-k mode] [-m mode] [-M mode] [-n mode] [-l ttl] [-L serial] [-o filename] [-r mode] [-s style] [-S mode] [-t directory] [-T mode] [-w directory] [-D] [-W mode] {zonename} {filename}

named-compilezone [-d] [-j] [-q] [-v] [-c class] [-C mode] [-f format] [-F format] [-J filename] [-i mode] [-k mode] [-m mode] [-n mode] [-l ttl] [-L serial] [-r mode] [-s style] [-t directory] [-T mode] [-w directory] [-D] [-W mode] {-o filename} {zonename} {filename}

DESCRIPTION

named-checkzone checks the syntax and integrity of a zone file. It performs the same checks as named does when loading a zone. This makes named-checkzone useful for checking zone files before configuring them into a name server.

named-compilezone is similar to named-checkzone, but it always dumps the zone contents to a specified file in a specified format. Additionally, it applies stricter check levels by default, since the dump output will be used as an actual zone file loaded by named. When manually specified otherwise, the check levels must at least be as strict as those specified in the named configuration file.

OPTIONS

-d

Enable debugging.

-h

Print the usage summary and exit.

-q

Quiet mode - exit code only.

-v

Print the version of the named-checkzone program and exit.

-j

When loading a zone file, read the journal if it exists. The journal file name is assumed to be the zone file name appended with the string .jnl.

-J filename

When loading the zone file read the journal from the given file, if it exists. (Implies -j.)

-c class

Specify the class of the zone. If not specified, "IN" is assumed.

-i mode

Perform post-load zone integrity checks. Possible modes are "full" (default), "full-sibling", "local", "local-sibling" and "none".

Mode "full" checks that MX records refer to A or AAAA record (both in-zone and out-of-zone hostnames). Mode "local" only checks MX records which refer to in-zone hostnames.

Mode "full" checks that SRV records refer to A or AAAA record (both in-zone and out-of-zone hostnames). Mode "local" only checks SRV records which refer to in-zone hostnames.

Mode "full" checks that delegation NS records refer to A or AAAA record (both in-zone and out-of-zone hostnames). It also checks that glue address records in the zone match those advertised by the child. Mode "local" only checks NS records which refer to in-zone hostnames or that some required glue exists, that is when the nameserver is in a child zone.

Mode "full-sibling" and "local-sibling" disable sibling glue checks but are otherwise the same as "full" and "local" respectively.

Mode "none" disables the checks.

-f format

Specify the format of the zone file. Possible formats are "text" (default), "raw", and "map".

-F format

Specify the format of the output file specified. For named-checkzone, this does not cause any effects unless it dumps the zone contents.

Possible formats are "text" (default), which is the standard textual representation of the zone, and "map", "raw", and "raw=N", which store the zone in a binary format for rapid loading by named. "raw=N" specifies the format version of the raw zone file: if N is 0, the raw file can be read by any version of named; if N is 1, the file can be read by release 9.9.0 or higher; the default is 1.

-k mode

Perform "check-names" checks with the specified failure mode. Possible modes are "fail" (default for named-compilezone), "warn" (default for named-checkzone) and "ignore".

-l ttl

Sets a maximum permissible TTL for the input file. Any record with a TTL higher than this value will cause the zone to be rejected. This is similar to using the max-zone-ttl option in named.conf.

-L serial

When compiling a zone to "raw" or "map" format, set the "source serial" value in the header to the specified serial number. (This is expected to be used primarily for testing purposes.)

-m mode

Specify whether MX records should be checked to see if they are addresses. Possible modes are "fail", "warn" (default) and "ignore".

-M mode

Check if a MX record refers to a CNAME. Possible modes are "fail", "warn" (default) and "ignore".

-n mode

Specify whether NS records should be checked to see if they are addresses. Possible modes are "fail" (default for named-compilezone), "warn" (default for named-checkzone) and "ignore".

-o filename

Write zone output to filename. If filename is - then write to standard out. This is mandatory for named-compilezone.

-r mode

Check for records that are treated as different by DNSSEC but are semantically equal in plain DNS. Possible modes are "fail", "warn" (default) and "ignore".

-s style

Specify the style of the dumped zone file. Possible styles are "full" (default) and "relative". The full format is most suitable for processing automatically by a separate script. On the other hand, the relative format is more human-readable and is thus suitable for editing by hand. For named-checkzone this does not cause any effects unless it dumps the zone contents. It also does not have any meaning if the output format is not text.

-S mode

Check if a SRV record refers to a CNAME. Possible modes are "fail", "warn" (default) and "ignore".

-t directory

Chroot to directory so that include directives in the configuration file are processed as if run by a similarly chrooted named.

-T mode

Check if Sender Policy Framework (SPF) records exist and issues a warning if an SPF-formatted TXT record is not also present. Possible modes are "warn" (default), "ignore".

-w directory

chdir to directory so that relative filenames in master file $INCLUDE directives work. This is similar to the directory clause in named.conf.

-D

Dump zone file in canonical format. This is always enabled for named-compilezone.

-W mode

Specify whether to check for non-terminal wildcards. Non-terminal wildcards are almost always the result of a failure to understand the wildcard matching algorithm (RFC 1034). Possible modes are "warn" (default) and "ignore".

zonename

The domain name of the zone being checked.

filename

The name of the zone file.

RETURN VALUES

named-checkzone returns an exit status of 1 if errors were detected and 0 otherwise.

SEE ALSO

named(8) , named-checkconf(8) , RFC 1035, BIND 9 Administrator Reference Manual.

bind9-9.11.3+dfsg/bin/check/win32/000077500000000000000000000000001325250447100163235ustar00rootroot00000000000000bind9-9.11.3+dfsg/bin/check/win32/checkconf.dsp.in000066400000000000000000000116611325250447100213700ustar00rootroot00000000000000# Microsoft Developer Studio Project File - Name="checkconf" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "@PLATFORM@ (x86) Console Application" 0x0103 CFG=checkconf - @PLATFORM@ Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "checkconf.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "checkconf.mak" CFG="checkconf - @PLATFORM@ Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "checkconf - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE "checkconf - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "checkconf - @PLATFORM@ Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 @COPTX@ @COPTI@ /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c # ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /I "../../../lib/isccfg/include" @CRYPTO@ /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__STDC__" /FR @COPTY@ /FD /c # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console @MACHINE@ # ADD LINK32 user32.lib advapi32.lib ws2_32.lib Release/checktool.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib ../../../lib/isccfg/win32/Release/libisccfg.lib ../../../lib/bind9/win32/Release/libbind9.lib /nologo /subsystem:console @MACHINE@ /out:"../../../Build/Release/named-checkconf.exe" !ELSEIF "$(CFG)" == "checkconf - @PLATFORM@ Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /GZ /c # ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /I "../../../lib/isccfg/include" @CRYPTO@ /D "_DEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c # SUBTRACT CPP /X @COPTY@ # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug @MACHINE@ /pdbtype:sept # ADD LINK32 user32.lib advapi32.lib ws2_32.lib Debug/checktool.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib ../../../lib/isccfg/win32/Debug/libisccfg.lib ../../../lib/bind9/win32/Debug/libbind9.lib ../../../lib/bind9/win32/Debug/libbind9.lib /nologo /subsystem:console /debug @MACHINE@ /out:"../../../Build/Debug/named-checkconf.exe" /pdbtype:sept !ENDIF # Begin Target # Name "checkconf - @PLATFORM@ Release" # Name "checkconf - @PLATFORM@ Debug" # Begin Group "Source Files" # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" # Begin Source File SOURCE="..\named-checkconf.c" # End Source File # End Group # Begin Group "Header Files" # PROP Default_Filter "h;hpp;hxx;hm;inl" # Begin Source File SOURCE="..\check-tool.h" # End Source File # End Group # Begin Group "Resource Files" # PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" # End Group # End Target # End Project bind9-9.11.3+dfsg/bin/check/win32/checkconf.dsw000066400000000000000000000010371325250447100207660ustar00rootroot00000000000000Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "checkconf"=".\checkconf.dsp" - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### bind9-9.11.3+dfsg/bin/check/win32/checkconf.mak.in000066400000000000000000000307761325250447100213620ustar00rootroot00000000000000# Microsoft Developer Studio Generated NMAKE File, Based on checkconf.dsp !IF "$(CFG)" == "" CFG=checkconf - @PLATFORM@ Debug !MESSAGE No configuration specified. Defaulting to checkconf - @PLATFORM@ Debug. !ENDIF !IF "$(CFG)" != "checkconf - @PLATFORM@ Release" && "$(CFG)" != "checkconf - @PLATFORM@ Debug" !MESSAGE Invalid configuration "$(CFG)" specified. !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "checkconf.mak" CFG="checkconf - @PLATFORM@ Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "checkconf - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE "checkconf - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE !ERROR An invalid configuration is specified. !ENDIF !IF "$(OS)" == "Windows_NT" NULL= !ELSE NULL=nul !ENDIF CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "checkconf - @PLATFORM@ Release" _VC_MANIFEST_INC=0 _VC_MANIFEST_BASENAME=__VC80 !ELSE _VC_MANIFEST_INC=1 _VC_MANIFEST_BASENAME=__VC80.Debug !ENDIF #################################################### # Specifying name of temporary resource file used only in incremental builds: !if "$(_VC_MANIFEST_INC)" == "1" _VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res !else _VC_MANIFEST_AUTO_RES= !endif #################################################### # _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE: !if "$(_VC_MANIFEST_INC)" == "1" #MT_SPECIAL_RETURN=1090650113 #MT_SPECIAL_SWITCH=-notify_resource_update MT_SPECIAL_RETURN=0 MT_SPECIAL_SWITCH= _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \ if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \ rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \ link $** /out:$@ $(LFLAGS) !else _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1 !endif #################################################### # _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL: !if "$(_VC_MANIFEST_INC)" == "1" #MT_SPECIAL_RETURN=1090650113 #MT_SPECIAL_SWITCH=-notify_resource_update MT_SPECIAL_RETURN=0 MT_SPECIAL_SWITCH= _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \ if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \ rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \ link $** /out:$@ $(LFLAGS) !else _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2 !endif #################################################### # _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily: !if "$(_VC_MANIFEST_INC)" == "1" _VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \ $(_VC_MANIFEST_BASENAME).auto.rc \ $(_VC_MANIFEST_BASENAME).auto.manifest !else _VC_MANIFEST_CLEAN= !endif !IF "$(CFG)" == "checkconf - @PLATFORM@ Release" OUTDIR=.\Release INTDIR=.\Release # Begin Custom Macros OutDir=.\Release # End Custom Macros !IF "$(RECURSE)" == "0" ALL : "..\..\..\Build\Release\named-checkconf.exe" "$(OUTDIR)\checkconf.bsc" !ELSE ALL : "libdns - @PLATFORM@ Release" "libisccfg - @PLATFORM@ Release" "libisc - @PLATFORM@ Release" "..\..\..\Build\Release\named-checkconf.exe" "$(OUTDIR)\checkconf.bsc" !ENDIF !IF "$(RECURSE)" == "1" CLEAN :"libisc - @PLATFORM@ ReleaseCLEAN" "libisccfg - @PLATFORM@ ReleaseCLEAN" "libdns - @PLATFORM@ ReleaseCLEAN" !ELSE CLEAN : !ENDIF -@erase "$(INTDIR)\check-tool.obj" -@erase "$(INTDIR)\check-tool.sbr" -@erase "$(INTDIR)\named-checkconf.obj" -@erase "$(INTDIR)\named-checkconf.sbr" -@erase "$(INTDIR)\vc60.idb" -@erase "$(OUTDIR)\checkconf.bsc" -@erase "..\..\..\Build\Release\named-checkconf.exe" -@$(_VC_MANIFEST_CLEAN) "$(OUTDIR)" : if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" CPP_PROJ=/nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /I "../../../lib/isccfg/include" @CRYPTO@ /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__STDC__" /FR"$(INTDIR)\\" /Fp"$(INTDIR)\checkconf.pch" @COPTY@ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c BSC32=bscmake.exe BSC32_FLAGS=/nologo /o"$(OUTDIR)\checkconf.bsc" BSC32_SBRS= \ "$(INTDIR)\check-tool.sbr" \ "$(INTDIR)\named-checkconf.sbr" "$(OUTDIR)\checkconf.bsc" : "$(OUTDIR)" $(BSC32_SBRS) $(BSC32) @<< $(BSC32_FLAGS) $(BSC32_SBRS) << LINK32=link.exe LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib ../../../lib/isccfg/win32/Release/libisccfg.lib ../../../lib/bind9/win32/Release/libbind9.lib /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\named-checkconf.pdb" @MACHINE@ /out:"../../../Build/Release/named-checkconf.exe" LINK32_OBJS= \ "$(INTDIR)\check-tool.obj" \ "$(INTDIR)\named-checkconf.obj" \ "..\..\..\lib\isc\win32\Release\libisc.lib" \ "..\..\..\lib\isccfg\win32\Release\libisccfg.lib" \ "..\..\..\lib\dns\win32\Release\libdns.lib" "..\..\..\Build\Release\named-checkconf.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) $(LINK32) @<< $(LINK32_FLAGS) $(LINK32_OBJS) << $(_VC_MANIFEST_EMBED_EXE) !ELSEIF "$(CFG)" == "checkconf - @PLATFORM@ Debug" OUTDIR=.\Debug INTDIR=.\Debug # Begin Custom Macros OutDir=.\Debug # End Custom Macros !IF "$(RECURSE)" == "0" ALL : "..\..\..\Build\Debug\named-checkconf.exe" "$(OUTDIR)\checkconf.bsc" !ELSE ALL : "libdns - @PLATFORM@ Debug" "libisccfg - @PLATFORM@ Debug" "libisc - @PLATFORM@ Debug" "..\..\..\Build\Debug\named-checkconf.exe" "$(OUTDIR)\checkconf.bsc" !ENDIF !IF "$(RECURSE)" == "1" CLEAN :"libisc - @PLATFORM@ DebugCLEAN" "libisccfg - @PLATFORM@ DebugCLEAN" "libdns - @PLATFORM@ DebugCLEAN" !ELSE CLEAN : !ENDIF -@erase "$(INTDIR)\check-tool.obj" -@erase "$(INTDIR)\check-tool.sbr" -@erase "$(INTDIR)\named-checkconf.obj" -@erase "$(INTDIR)\named-checkconf.sbr" -@erase "$(INTDIR)\vc60.idb" -@erase "$(INTDIR)\vc60.pdb" -@erase "$(OUTDIR)\named-checkconf.pdb" -@erase "$(OUTDIR)\checkconf.bsc" -@erase "..\..\..\Build\Debug\named-checkconf.exe" -@erase "..\..\..\Build\Debug\named-checkconf.ilk" -@$(_VC_MANIFEST_CLEAN) "$(OUTDIR)" : if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" CPP_PROJ=/nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /I "../../../lib/isccfg/include" @CRYPTO@ /D "_DEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c BSC32=bscmake.exe BSC32_FLAGS=/nologo /o"$(OUTDIR)\checkconf.bsc" BSC32_SBRS= \ "$(INTDIR)\check-tool.sbr" \ "$(INTDIR)\named-checkconf.sbr" "$(OUTDIR)\checkconf.bsc" : "$(OUTDIR)" $(BSC32_SBRS) $(BSC32) @<< $(BSC32_FLAGS) $(BSC32_SBRS) << LINK32=link.exe LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib ../../../lib/isccfg/win32/Debug/libisccfg.lib ../../../lib/bind9/win32/Debug/libbind9.lib ../../../lib/bind9/win32/Debug/libbind9.lib /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\named-checkconf.pdb" /debug @MACHINE@ /out:"../../../Build/Debug/named-checkconf.exe" /pdbtype:sept LINK32_OBJS= \ "$(INTDIR)\check-tool.obj" \ "$(INTDIR)\named-checkconf.obj" \ "..\..\..\lib\isc\win32\Debug\libisc.lib" \ "..\..\..\lib\isccfg\win32\Debug\libisccfg.lib" \ "..\..\..\lib\dns\win32\Debug\libdns.lib" "..\..\..\Build\Debug\named-checkconf.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) $(LINK32) @<< $(LINK32_FLAGS) $(LINK32_OBJS) << $(_VC_MANIFEST_EMBED_EXE) !ENDIF .c{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .c{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << !IF "$(NO_EXTERNAL_DEPS)" != "1" !IF EXISTS("checkconf.dep") !INCLUDE "checkconf.dep" !ELSE !MESSAGE Warning: cannot find "checkconf.dep" !ENDIF !ENDIF !IF "$(CFG)" == "checkconf - @PLATFORM@ Release" || "$(CFG)" == "checkconf - @PLATFORM@ Debug" SOURCE="..\check-tool.c" "$(INTDIR)\check-tool.obj" "$(INTDIR)\check-tool.sbr" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) SOURCE="..\named-checkconf.c" "$(INTDIR)\named-checkconf.obj" "$(INTDIR)\named-checkconf.sbr" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !IF "$(CFG)" == "checkconf - @PLATFORM@ Release" "libisc - @PLATFORM@ Release" : cd "..\..\..\lib\isc\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Release" cd "..\..\..\bin\check\win32" "libisc - @PLATFORM@ ReleaseCLEAN" : cd "..\..\..\lib\isc\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Release" RECURSE=1 CLEAN cd "..\..\..\bin\check\win32" !ELSEIF "$(CFG)" == "checkconf - @PLATFORM@ Debug" "libisc - @PLATFORM@ Debug" : cd "..\..\..\lib\isc\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Debug" cd "..\..\..\bin\check\win32" "libisc - @PLATFORM@ DebugCLEAN" : cd "..\..\..\lib\isc\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Debug" RECURSE=1 CLEAN cd "..\..\..\bin\check\win32" !ENDIF !IF "$(CFG)" == "checkconf - @PLATFORM@ Release" "libisccfg - @PLATFORM@ Release" : cd "..\..\..\lib\isccfg\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libisccfg.mak" CFG="libisccfg - @PLATFORM@ Release" cd "..\..\..\bin\check\win32" "libisccfg - @PLATFORM@ ReleaseCLEAN" : cd "..\..\..\lib\isccfg\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libisccfg.mak" CFG="libisccfg - @PLATFORM@ Release" RECURSE=1 CLEAN cd "..\..\..\bin\check\win32" !ELSEIF "$(CFG)" == "checkconf - @PLATFORM@ Debug" "libisccfg - @PLATFORM@ Debug" : cd "..\..\..\lib\isccfg\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libisccfg.mak" CFG="libisccfg - @PLATFORM@ Debug" cd "..\..\..\bin\check\win32" "libisccfg - @PLATFORM@ DebugCLEAN" : cd "..\..\..\lib\isccfg\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libisccfg.mak" CFG="libisccfg - @PLATFORM@ Debug" RECURSE=1 CLEAN cd "..\..\..\bin\check\win32" !ENDIF !IF "$(CFG)" == "checkconf - @PLATFORM@ Release" "libdns - @PLATFORM@ Release" : cd "..\..\..\lib\dns\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Release" cd "..\..\..\bin\check\win32" "libdns - @PLATFORM@ ReleaseCLEAN" : cd "..\..\..\lib\dns\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Release" RECURSE=1 CLEAN cd "..\..\..\bin\check\win32" !ELSEIF "$(CFG)" == "checkconf - @PLATFORM@ Debug" "libdns - @PLATFORM@ Debug" : cd "..\..\..\lib\dns\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Debug" cd "..\..\..\bin\check\win32" "libdns - @PLATFORM@ DebugCLEAN" : cd "..\..\..\lib\dns\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Debug" RECURSE=1 CLEAN cd "..\..\..\bin\check\win32" !ENDIF !ENDIF #################################################### # Commands to generate initial empty manifest file and the RC file # that references it, and for generating the .res file: $(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc $(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest type <<$@ #include 1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest" << KEEP $(_VC_MANIFEST_BASENAME).auto.manifest : type <<$@ << KEEP #################################################### # Commands to generate initial empty manifest file and the RC file # that references it, and for generating the .res file: $(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc $(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest type <<$@ #include 1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest" << KEEP $(_VC_MANIFEST_BASENAME).auto.manifest : type <<$@ << KEEP bind9-9.11.3+dfsg/bin/check/win32/checkconf.vcxproj.filters.in000066400000000000000000000021061325250447100237360ustar00rootroot00000000000000 {4FC737F1-C7A5-4376-A066-2A32D752A2FF} cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx {93995380-89BD-4b04-88EB-625FBE52EBFB} h;hpp;hxx;hm;inl;inc;xsd {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms Header Files Source Files bind9-9.11.3+dfsg/bin/check/win32/checkconf.vcxproj.in000066400000000000000000000161251325250447100222750ustar00rootroot00000000000000 Debug @PLATFORM@ Release @PLATFORM@ {03A96113-CB14-43AA-AEB2-48950E3915C5} Win32Proj checkconf Application true MultiByte Application false true MultiByte true ..\..\..\Build\$(Configuration)\ .\$(Configuration)\ named-$(ProjectName) false ..\..\..\Build\$(Configuration)\ .\$(Configuration)\ named-$(ProjectName) Level3 Disabled WIN32;@CRYPTO@_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true .\$(Configuration)\$(ProjectName).pch .\$(Configuration)\ .\$(Configuration)\ $(OutDir)$(TargetName).pdb true .\;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;..\..\..\lib\bind9\include;..\..\..\lib\isccfg\include;%(AdditionalIncludeDirectories) CompileAsC Console true ..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt) $(Configuration);..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);..\..\..\lib\isccfg\win32\$(Configuration);..\..\..\lib\isccc\win32\$(Configuration);..\..\..\lib\bind9\win32\$(Configuration);%(AdditionalLibraryDirectories) checktool.lib;libisc.lib;libdns.lib;libisccfg.lib;libisccc.lib;libbind9.lib;ws2_32.lib;%(AdditionalDependencies) Level3 MaxSpeed true @INTRINSIC@ WIN32;@CRYPTO@NDEBUG;_CONSOLE;%(PreprocessorDefinitions) OnlyExplicitInline false true .\$(Configuration)\$(ProjectName).pch .\$(Configuration)\ .\$(Configuration)\ $(OutDir)$(TargetName).pdb .\;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;..\..\..\lib\bind9\include;..\..\..\lib\isccfg\include;%(AdditionalIncludeDirectories) CompileAsC Console false true true ..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt) $(Configuration);..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);..\..\..\lib\isccfg\win32\$(Configuration);..\..\..\lib\isccc\win32\$(Configuration);..\..\..\lib\bind9\win32\$(Configuration);%(AdditionalLibraryDirectories) checktool.lib;libisc.lib;libdns.lib;libisccfg.lib;libisccc.lib;libbind9.lib;ws2_32.lib;%(AdditionalDependencies) Default bind9-9.11.3+dfsg/bin/check/win32/checkconf.vcxproj.user000066400000000000000000000002171325250447100226400ustar00rootroot00000000000000 bind9-9.11.3+dfsg/bin/check/win32/checktool.dsp.in000066400000000000000000000076371325250447100214300ustar00rootroot00000000000000# Microsoft Developer Studio Project File - Name="checktool" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "@PLATFORM@ (x86) Static-Link Library" 0x0104 CFG=checktool - @PLATFORM@ Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "checktool.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "checktool.mak" CFG="checktool - @PLATFORM@ Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "checktool - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Static-Link Library") !MESSAGE "checktool - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Static-Link Library") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe MTL=midl.exe RSC=rc.exe !IF "$(CFG)" == "checktool - @PLATFORM@ Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MT /W3 @COPTX@ @COPTI@ /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" @COPTY@ /FD /c # ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../include" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isccfg/include" /I "../../../lib/dns/include" @CRYPTO@ /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "__STDC__" /D "_MBCS" @COPTY@ /FD /c /Fdchecktool # SUBTRACT CPP /X # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 # ADD LINK32 /out:"Release/checktool.lib" !ELSEIF "$(CFG)" == "checktool - @PLATFORM@ Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MTd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" @COPTY@ /FD /GZ /c # ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../include" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isccfg/include" /I "../../../lib/dns/include" @CRYPTO@ /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "__STDC__" /D "_MBCS" /FR @COPTY@ /FD /GZ /c /Fdchecktool # SUBTRACT CPP /X # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 # ADD LINK32 /debug out:"Debug/checktool.lib" !ENDIF # Begin Target # Name "checktool - @PLATFORM@ Release" # Name "checktool - @PLATFORM@ Debug" # Begin Group "Source Files" # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" # End Group # Begin Group "Header Files" # PROP Default_Filter "h;hpp;hxx;hm;inl" # End Group # Begin Group "Resource Files" # PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" # End Group # Begin Group "Main Dns Lib" # PROP Default_Filter "c" # Begin Source File SOURCE=..\check-tool.c # End Source File # End Group # End Target # End Project bind9-9.11.3+dfsg/bin/check/win32/checktool.dsw000066400000000000000000000010371325250447100210160ustar00rootroot00000000000000Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "checktool"=".\checktool.dsp" - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### bind9-9.11.3+dfsg/bin/check/win32/checktool.vcxproj.filters.in000066400000000000000000000014001325250447100237620ustar00rootroot00000000000000 {4FC737F1-C7A5-4376-A066-2A32D752A2FF} cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms Source Files bind9-9.11.3+dfsg/bin/check/win32/checktool.vcxproj.in000066400000000000000000000131361325250447100223240ustar00rootroot00000000000000 Debug @PLATFORM@ Release @PLATFORM@ {2C1F7096-C5B5-48D4-846F-A7ACA454335D} Win32Proj checktool StaticLibrary true MultiByte StaticLibrary false true MultiByte .\$(Configuration)\ .\$(Configuration)\ .\$(Configuration)\ .\$(Configuration)\ Level3 Disabled WIN32;@CRYPTO@_DEBUG;_LIB;%(PreprocessorDefinitions) true .\$(Configuration)\$(TargetName).pch .\$(Configuration)\ .\$(Configuration)\ $(OutDir)$(TargetName).pdb true .\;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@..\include;..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\isccfg\include;..\..\..\lib\dns\include;%(AdditionalIncludeDirectories) CompileAsC .\$(Configuration)\$(TargetName)$(TargetExt) Level3 MaxSpeed true @INTRINSIC@ WIN32;@CRYPTO@NDEBUG;_LIB;%(PreprocessorDefinitions) OnlyExplicitInline false true .\$(Configuration)\$(TargetName).pch .\$(Configuration)\ .\$(Configuration)\ $(OutDir)$(TargetName).pdb .\;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@..\include;..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\isccfg\include;..\..\..\lib\dns\include;%(AdditionalIncludeDirectories) CompileAsC .\$(Configuration)\$(TargetName)$(TargetExt) bind9-9.11.3+dfsg/bin/check/win32/checktool.vcxproj.user000066400000000000000000000002171325250447100226700ustar00rootroot00000000000000 bind9-9.11.3+dfsg/bin/check/win32/checkzone.dsp.in000066400000000000000000000113721325250447100214150ustar00rootroot00000000000000# Microsoft Developer Studio Project File - Name="checkzone" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "@PLATFORM@ (x86) Console Application" 0x0103 CFG=checkzone - @PLATFORM@ Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "checkzone.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "checkzone.mak" CFG="checkzone - @PLATFORM@ Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "checkzone - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE "checkzone - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "checkzone - @PLATFORM@ Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 @COPTX@ @COPTI@ /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c # ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" /I "../../../lib/isccfg/include" @CRYPTO@ /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__STDC__" @COPTY@ /FD /c # SUBTRACT CPP /Fr # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console @MACHINE@ # ADD LINK32 user32.lib advapi32.lib ws2_32.lib Release/checktool.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/isccfg/win32/Release/libisccfg.lib ../../../lib/dns/win32/Release/libdns.lib /nologo /subsystem:console @MACHINE@ /out:"../../../Build/Release/named-checkzone.exe" !ELSEIF "$(CFG)" == "checkzone - @PLATFORM@ Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /GZ /c # ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" /I "../../../lib/isccfg/include" @CRYPTO@ /D "_DEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c # SUBTRACT CPP /X @COPTY@ # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug @MACHINE@ /pdbtype:sept # ADD LINK32 user32.lib advapi32.lib ws2_32.lib Debug/checktool.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/isccfg/win32/Debug/libisccfg.lib ../../../lib/dns/win32/Debug/libdns.lib /nologo /subsystem:console /debug @MACHINE@ /out:"../../../Build/Debug/named-checkzone.exe" /pdbtype:sept !ENDIF # Begin Target # Name "checkzone - @PLATFORM@ Release" # Name "checkzone - @PLATFORM@ Debug" # Begin Group "Source Files" # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" # Begin Source File SOURCE="..\named-checkzone.c" # End Source File # End Group # Begin Group "Header Files" # PROP Default_Filter "h;hpp;hxx;hm;inl" # Begin Source File SOURCE="..\check-tool.h" # End Source File # End Group # Begin Group "Resource Files" # PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" # End Group # End Target # End Project bind9-9.11.3+dfsg/bin/check/win32/checkzone.dsw000066400000000000000000000010371325250447100210140ustar00rootroot00000000000000Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "checkzone"=".\checkzone.dsp" - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### bind9-9.11.3+dfsg/bin/check/win32/checkzone.mak.in000066400000000000000000000260501325250447100213760ustar00rootroot00000000000000# Microsoft Developer Studio Generated NMAKE File, Based on checkzone.dsp !IF "$(CFG)" == "" CFG=checkzone - @PLATFORM@ Debug !MESSAGE No configuration specified. Defaulting to checkzone - @PLATFORM@ Debug. !ENDIF !IF "$(CFG)" != "checkzone - @PLATFORM@ Release" && "$(CFG)" != "checkzone - @PLATFORM@ Debug" !MESSAGE Invalid configuration "$(CFG)" specified. !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "checkzone.mak" CFG="checkzone - @PLATFORM@ Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "checkzone - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE "checkzone - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE !ERROR An invalid configuration is specified. !ENDIF !IF "$(OS)" == "Windows_NT" NULL= !ELSE NULL=nul !ENDIF !IF "$(CFG)" == "checkzone - @PLATFORM@ Release" _VC_MANIFEST_INC=0 _VC_MANIFEST_BASENAME=__VC80 !ELSE _VC_MANIFEST_INC=1 _VC_MANIFEST_BASENAME=__VC80.Debug !ENDIF #################################################### # Specifying name of temporary resource file used only in incremental builds: !if "$(_VC_MANIFEST_INC)" == "1" _VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res !else _VC_MANIFEST_AUTO_RES= !endif #################################################### # _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE: !if "$(_VC_MANIFEST_INC)" == "1" #MT_SPECIAL_RETURN=1090650113 #MT_SPECIAL_SWITCH=-notify_resource_update MT_SPECIAL_RETURN=0 MT_SPECIAL_SWITCH= _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \ if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \ rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \ link $** /out:$@ $(LFLAGS) !else _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1 !endif #################################################### # _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL: !if "$(_VC_MANIFEST_INC)" == "1" #MT_SPECIAL_RETURN=1090650113 #MT_SPECIAL_SWITCH=-notify_resource_update MT_SPECIAL_RETURN=0 MT_SPECIAL_SWITCH= _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \ if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \ rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \ link $** /out:$@ $(LFLAGS) !else _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2 !endif #################################################### # _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily: !if "$(_VC_MANIFEST_INC)" == "1" _VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \ $(_VC_MANIFEST_BASENAME).auto.rc \ $(_VC_MANIFEST_BASENAME).auto.manifest !else _VC_MANIFEST_CLEAN= !endif !IF "$(CFG)" == "checkzone - @PLATFORM@ Release" OUTDIR=.\Release INTDIR=.\Release !IF "$(RECURSE)" == "0" ALL : "..\..\..\Build\Release\named-checkzone.exe" !ELSE ALL : "libisc - @PLATFORM@ Release" "libdns - @PLATFORM@ Release" "..\..\..\Build\Release\named-checkzone.exe" !ENDIF !IF "$(RECURSE)" == "1" CLEAN :"libdns - @PLATFORM@ ReleaseCLEAN" "libisc - @PLATFORM@ ReleaseCLEAN" !ELSE CLEAN : !ENDIF -@erase "$(INTDIR)\check-tool.obj" -@erase "$(INTDIR)\named-checkzone.obj" -@erase "$(INTDIR)\vc60.idb" -@erase "..\..\..\Build\Release\named-checkzone.exe" -@$(_VC_MANIFEST_CLEAN) "$(OUTDIR)" : if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" CPP=cl.exe CPP_PROJ=/nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" /I "../../../lib/isccfg/include" @CRYPTO@ /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__STDC__" /Fp"$(INTDIR)\checkzone.pch" @COPTY@ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c .c{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .c{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << RSC=rc.exe BSC32=bscmake.exe BSC32_FLAGS=/nologo /o"$(OUTDIR)\checkzone.bsc" BSC32_SBRS= \ LINK32=link.exe LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/isccfg/win32/Release/libisccfg.lib ../../../lib/dns/win32/Release/libdns.lib /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\named-checkzone.pdb" @MACHINE@ /out:"../../../Build/Release/named-checkzone.exe" LINK32_OBJS= \ "$(INTDIR)\check-tool.obj" \ "$(INTDIR)\named-checkzone.obj" \ "..\..\..\lib\dns\win32\Release\libdns.lib" \ "..\..\..\lib\isccfg\win32\Release\libisccfg.lib" \ "..\..\..\lib\isc\win32\Release\libisc.lib" "..\..\..\Build\Release\named-checkzone.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) $(LINK32) @<< $(LINK32_FLAGS) $(LINK32_OBJS) << $(_VC_MANIFEST_EMBED_EXE) !ELSEIF "$(CFG)" == "checkzone - @PLATFORM@ Debug" OUTDIR=.\Debug INTDIR=.\Debug # Begin Custom Macros OutDir=.\Debug # End Custom Macros !IF "$(RECURSE)" == "0" ALL : "..\..\..\Build\Debug\named-checkzone.exe" "$(OUTDIR)\checkzone.bsc" !ELSE ALL : "libisc - @PLATFORM@ Debug" "libdns - @PLATFORM@ Debug" "..\..\..\Build\Debug\named-checkzone.exe" "$(OUTDIR)\checkzone.bsc" !ENDIF !IF "$(RECURSE)" == "1" CLEAN :"libdns - @PLATFORM@ DebugCLEAN" "libisc - @PLATFORM@ DebugCLEAN" !ELSE CLEAN : !ENDIF -@erase "$(INTDIR)\check-tool.obj" -@erase "$(INTDIR)\check-tool.sbr" -@erase "$(INTDIR)\named-checkzone.obj" -@erase "$(INTDIR)\named-checkzone.sbr" -@erase "$(INTDIR)\vc60.idb" -@erase "$(INTDIR)\vc60.pdb" -@erase "$(OUTDIR)\named-checkzone.pdb" -@erase "$(OUTDIR)\checkzone.bsc" -@erase "..\..\..\Build\Debug\named-checkzone.exe" -@erase "..\..\..\Build\Debug\named-checkzone.ilk" -@$(_VC_MANIFEST_CLEAN) "$(OUTDIR)" : if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" CPP=cl.exe CPP_PROJ=/nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" /I "../../../lib/isccfg/include" @CRYPTO@ /D "_DEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c .c{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .c{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << RSC=rc.exe BSC32=bscmake.exe BSC32_FLAGS=/nologo /o"$(OUTDIR)\checkzone.bsc" BSC32_SBRS= \ "$(INTDIR)\check-tool.sbr" \ "$(INTDIR)\named-checkzone.sbr" "$(OUTDIR)\checkzone.bsc" : "$(OUTDIR)" $(BSC32_SBRS) $(BSC32) @<< $(BSC32_FLAGS) $(BSC32_SBRS) << LINK32=link.exe LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/isccfg/win32/Debug/libisccfg.lib ../../../lib/dns/win32/Debug/libdns.lib /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\named-checkzone.pdb" /debug @MACHINE@ /out:"../../../Build/Debug/named-checkzone.exe" /pdbtype:sept LINK32_OBJS= \ "$(INTDIR)\check-tool.obj" \ "$(INTDIR)\named-checkzone.obj" \ "..\..\..\lib\dns\win32\Debug\libdns.lib" \ "..\..\..\lib\isccfg\win32\Debug\libisccfg.lib" \ "..\..\..\lib\isc\win32\Debug\libisc.lib" "..\..\..\Build\Debug\named-checkzone.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) $(LINK32) @<< $(LINK32_FLAGS) $(LINK32_OBJS) << $(_VC_MANIFEST_EMBED_EXE) !ENDIF !IF "$(NO_EXTERNAL_DEPS)" != "1" !IF EXISTS("checkzone.dep") !INCLUDE "checkzone.dep" !ELSE !MESSAGE Warning: cannot find "checkzone.dep" !ENDIF !ENDIF !IF "$(CFG)" == "checkzone - @PLATFORM@ Release" || "$(CFG)" == "checkzone - @PLATFORM@ Debug" SOURCE="..\check-tool.c" !IF "$(CFG)" == "checkzone - @PLATFORM@ Release" "$(INTDIR)\check-tool.obj" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ELSEIF "$(CFG)" == "checkzone - @PLATFORM@ Debug" "$(INTDIR)\check-tool.obj" "$(INTDIR)\check-tool.sbr" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ENDIF SOURCE="..\named-checkzone.c" !IF "$(CFG)" == "checkzone - @PLATFORM@ Release" "$(INTDIR)\named-checkzone.obj" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ELSEIF "$(CFG)" == "checkzone - @PLATFORM@ Debug" "$(INTDIR)\named-checkzone.obj" "$(INTDIR)\named-checkzone.sbr" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ENDIF !IF "$(CFG)" == "checkzone - @PLATFORM@ Release" "libdns - @PLATFORM@ Release" : cd "..\..\..\lib\dns\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Release" cd "..\..\..\bin\check\win32" "libdns - @PLATFORM@ ReleaseCLEAN" : cd "..\..\..\lib\dns\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Release" RECURSE=1 CLEAN cd "..\..\..\bin\check\win32" !ELSEIF "$(CFG)" == "checkzone - @PLATFORM@ Debug" "libdns - @PLATFORM@ Debug" : cd "..\..\..\lib\dns\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Debug" cd "..\..\..\bin\check\win32" "libdns - @PLATFORM@ DebugCLEAN" : cd "..\..\..\lib\dns\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Debug" RECURSE=1 CLEAN cd "..\..\..\bin\check\win32" !ENDIF !IF "$(CFG)" == "checkzone - @PLATFORM@ Release" "libisc - @PLATFORM@ Release" : cd "..\..\..\lib\isc\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Release" cd "..\..\..\bin\check\win32" "libisc - @PLATFORM@ ReleaseCLEAN" : cd "..\..\..\lib\isc\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Release" RECURSE=1 CLEAN cd "..\..\..\bin\check\win32" !ELSEIF "$(CFG)" == "checkzone - @PLATFORM@ Debug" "libisc - @PLATFORM@ Debug" : cd "..\..\..\lib\isc\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Debug" cd "..\..\..\bin\check\win32" "libisc - @PLATFORM@ DebugCLEAN" : cd "..\..\..\lib\isc\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Debug" RECURSE=1 CLEAN cd "..\..\..\bin\check\win32" !ENDIF !ENDIF #################################################### # Commands to generate initial empty manifest file and the RC file # that references it, and for generating the .res file: $(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc $(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest type <<$@ #include 1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest" << KEEP $(_VC_MANIFEST_BASENAME).auto.manifest : type <<$@ << KEEP bind9-9.11.3+dfsg/bin/check/win32/checkzone.vcxproj.filters.in000066400000000000000000000021061325250447100237640ustar00rootroot00000000000000 {4FC737F1-C7A5-4376-A066-2A32D752A2FF} cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx {93995380-89BD-4b04-88EB-625FBE52EBFB} h;hpp;hxx;hm;inl;inc;xsd {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms Header Files Source Files bind9-9.11.3+dfsg/bin/check/win32/checkzone.vcxproj.in000066400000000000000000000164401325250447100223230ustar00rootroot00000000000000 Debug @PLATFORM@ Release @PLATFORM@ {66028555-7DD5-4016-B601-9EF9A1EE8BFA} Win32Proj checkzone Application true MultiByte Application false true MultiByte true ..\..\..\Build\$(Configuration)\ .\$(Configuration)\ named-$(ProjectName) false ..\..\..\Build\$(Configuration)\ .\$(Configuration)\ named-$(ProjectName) Level3 Disabled WIN32;@CRYPTO@_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true .\$(Configuration)\$(ProjectName).pch .\$(Configuration)\ .\$(Configuration)\ $(OutDir)$(TargetName).pdb true .\;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;..\..\..\lib\bind9\include;%(AdditionalIncludeDirectories) CompileAsC Console true ..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt) $(Configuration);..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);..\..\..\lib\isccfg\win32\$(Configuration);..\..\..\lib\bind9\win32\$(Configuration);%(AdditionalLibraryDirectories) checktool.lib;libisc.lib;libdns.lib;libisccfg.lib;libbind9.lib;ws2_32.lib;%(AdditionalDependencies) cd ..\..\..\Build\$(Configuration) copy /Y named-checkzone.exe named-compilezone.exe copy /Y named-checkzone.ilk named-compilezone.ilk Level3 MaxSpeed true @INTRINSIC@ WIN32;@CRYPTO@NDEBUG;_CONSOLE;%(PreprocessorDefinitions) OnlyExplicitInline false true .\$(Configuration)\$(ProjectName).pch .\$(Configuration)\ .\$(Configuration)\ $(OutDir)$(TargetName).pdb .\;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;..\..\..\lib\bind9\include;%(AdditionalIncludeDirectories) CompileAsC Console false true true ..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt) $(Configuration);..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);..\..\..\lib\isccfg\win32\$(Configuration);..\..\..\lib\bind9\win32\$(Configuration);%(AdditionalLibraryDirectories) checktool.lib;libisc.lib;libdns.lib;libisccfg.lib;libbind9.lib;ws2_32.lib;%(AdditionalDependencies) Default cd ..\..\..\Build\$(Configuration) copy /Y named-checkzone.exe named-compilezone.exe bind9-9.11.3+dfsg/bin/check/win32/checkzone.vcxproj.user000066400000000000000000000002171325250447100226660ustar00rootroot00000000000000 bind9-9.11.3+dfsg/bin/confgen/000077500000000000000000000000001325250447100157235ustar00rootroot00000000000000bind9-9.11.3+dfsg/bin/confgen/Makefile.in000066400000000000000000000072021325250447100177710ustar00rootroot00000000000000# Copyright (C) 2009, 2012, 2014-2017 Internet Systems Consortium, Inc. ("ISC") # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. # $Id: Makefile.in,v 1.8 2009/12/05 23:31:40 each Exp $ srcdir = @srcdir@ VPATH = @srcdir@ top_srcdir = @top_srcdir@ # Attempt to disable parallel processing. .NOTPARALLEL: .NO_PARALLEL: VERSION=@BIND9_VERSION@ @BIND9_MAKE_INCLUDES@ CINCLUDES = -I${srcdir}/include ${ISC_INCLUDES} ${ISCCC_INCLUDES} \ ${ISCCFG_INCLUDES} ${DNS_INCLUDES} ${BIND9_INCLUDES} CDEFINES = CWARNINGS = ISCCFGLIBS = ../../lib/isccfg/libisccfg.@A@ ISCCCLIBS = ../../lib/isccc/libisccc.@A@ ISCLIBS = ../../lib/isc/libisc.@A@ ISCNOSYMLIBS = ../../lib/isc/libisc-nosymtbl.@A@ DNSLIBS = ../../lib/dns/libdns.@A@ @DNS_CRYPTO_LIBS@ BIND9LIBS = ../../lib/bind9/libbind9.@A@ ISCCFGDEPLIBS = ../../lib/isccfg/libisccfg.@A@ ISCCCDEPLIBS = ../../lib/isccc/libisccc.@A@ ISCDEPLIBS = ../../lib/isc/libisc.@A@ DNSDEPLIBS = ../../lib/dns/libdns.@A@ BIND9DEPLIBS = ../../lib/bind9/libbind9.@A@ RNDCLIBS = ${ISCCFGLIBS} ${ISCCCLIBS} ${BIND9LIBS} ${DNSLIBS} ${ISCLIBS} @LIBS@ RNDCDEPLIBS = ${ISCCFGDEPLIBS} ${ISCCCDEPLIBS} ${BIND9DEPLIBS} ${DNSDEPLIBS} ${ISCDEPLIBS} LIBS = ${DNSLIBS} ${ISCLIBS} @LIBS@ NOSYMLIBS = ${DNSLIBS} ${ISCNOSYMLIBS} @LIBS@ CONFDEPLIBS = ${DNSDEPLIBS} ${ISCDEPLIBS} SRCS= rndc-confgen.c ddns-confgen.c SUBDIRS = unix TARGETS = rndc-confgen@EXEEXT@ ddns-confgen@EXEEXT@ tsig-keygen@EXEEXT@ MANPAGES = rndc-confgen.8 ddns-confgen.8 HTMLPAGES = rndc-confgen.html ddns-confgen.html MANOBJS = ${MANPAGES} ${HTMLPAGES} UOBJS = unix/os.@O@ @BIND9_MAKE_RULES@ rndc-confgen.@O@: rndc-confgen.c ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} \ -DRNDC_KEYFILE=\"${sysconfdir}/rndc.key\" \ -c ${srcdir}/rndc-confgen.c ddns-confgen.@O@: ddns-confgen.c ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} -c ${srcdir}/ddns-confgen.c rndc-confgen@EXEEXT@: rndc-confgen.@O@ util.@O@ keygen.@O@ ${CONFDEPLIBS} export BASEOBJS="rndc-confgen.@O@ util.@O@ keygen.@O@ ${UOBJS}"; \ ${FINALBUILDCMD} ddns-confgen@EXEEXT@: ddns-confgen.@O@ util.@O@ keygen.@O@ ${CONFDEPLIBS} export BASEOBJS="ddns-confgen.@O@ util.@O@ keygen.@O@ ${UOBJS}"; \ ${FINALBUILDCMD} # make a link in the build directory to assist with testing tsig-keygen@EXEEXT@: ddns-confgen@EXEEXT@ rm -f tsig-keygen@EXEEXT@ ${LINK_PROGRAM} ddns-confgen@EXEEXT@ tsig-keygen@EXEEXT@ doc man:: ${MANOBJS} docclean manclean maintainer-clean:: rm -f ${MANOBJS} installdirs: $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${sbindir} $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${mandir}/man8 install:: rndc-confgen@EXEEXT@ ddns-confgen@EXEEXT@ installdirs ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} rndc-confgen@EXEEXT@ ${DESTDIR}${sbindir} ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} ddns-confgen@EXEEXT@ ${DESTDIR}${sbindir} ${INSTALL_DATA} ${srcdir}/rndc-confgen.8 ${DESTDIR}${mandir}/man8 ${INSTALL_DATA} ${srcdir}/ddns-confgen.8 ${DESTDIR}${mandir}/man8 (cd ${DESTDIR}${sbindir}; rm -f tsig-keygen@EXEEXT@; ${LINK_PROGRAM} ddns-confgen@EXEEXT@ tsig-keygen@EXEEXT@) (cd ${DESTDIR}${mandir}/man8; rm -f tsig-keygen.8; ${LINK_PROGRAM} ddns-confgen.8 tsig-keygen.8) uninstall:: rm -f ${DESTDIR}${mandir}/man8/tsig-keygen.8 rm -f ${DESTDIR}${sbindir}/tsig-keygen@EXEEXT@ rm -f ${DESTDIR}${mandir}/man8/ddns-confgen.8 rm -f ${DESTDIR}${mandir}/man8/rndc-confgen.8 ${LIBTOOL_MODE_UNINSTALL} rm -f ${DESTDIR}${sbindir}/ddns-confgen@EXEEXT@ ${LIBTOOL_MODE_UNINSTALL} rm -f ${DESTDIR}${sbindir}/rndc-confgen@EXEEXT@ clean distclean maintainer-clean:: rm -f ${TARGETS} bind9-9.11.3+dfsg/bin/confgen/ddns-confgen.8000066400000000000000000000127251325250447100203700ustar00rootroot00000000000000.\" Copyright (C) 2009, 2014-2016 Internet Systems Consortium, Inc. ("ISC") .\" .\" This Source Code Form is subject to the terms of the Mozilla Public .\" License, v. 2.0. If a copy of the MPL was not distributed with this .\" file, You can obtain one at http://mozilla.org/MPL/2.0/. .\" .hy 0 .ad l '\" t .\" Title: ddns-confgen .\" Author: .\" Generator: DocBook XSL Stylesheets v1.78.1 .\" Date: 2014-03-06 .\" Manual: BIND9 .\" Source: ISC .\" Language: English .\" .TH "DDNS\-CONFGEN" "8" "2014\-03\-06" "ISC" "BIND9" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" ddns-confgen \- ddns key generation tool .SH "SYNOPSIS" .HP \w'\fBtsig\-keygen\fR\ 'u \fBtsig\-keygen\fR [\fB\-a\ \fR\fB\fIalgorithm\fR\fR] [\fB\-h\fR] [\fB\-r\ \fR\fB\fIrandomfile\fR\fR] [name] .HP \w'\fBddns\-confgen\fR\ 'u \fBddns\-confgen\fR [\fB\-a\ \fR\fB\fIalgorithm\fR\fR] [\fB\-h\fR] [\fB\-k\ \fR\fB\fIkeyname\fR\fR] [\fB\-q\fR] [\fB\-r\ \fR\fB\fIrandomfile\fR\fR] [\-s\ \fIname\fR | \-z\ \fIzone\fR] .SH "DESCRIPTION" .PP \fBtsig\-keygen\fR and \fBddns\-confgen\fR are invocation methods for a utility that generates keys for use in TSIG signing\&. The resulting keys can be used, for example, to secure dynamic DNS updates to a zone or for the \fBrndc\fR command channel\&. .PP When run as \fBtsig\-keygen\fR, a domain name can be specified on the command line which will be used as the name of the generated key\&. If no name is specified, the default is \fBtsig\-key\fR\&. .PP When run as \fBddns\-confgen\fR, the generated key is accompanied by configuration text and instructions that can be used with \fBnsupdate\fR and \fBnamed\fR when setting up dynamic DNS, including an example \fBupdate\-policy\fR statement\&. (This usage similar to the \fBrndc\-confgen\fR command for setting up command channel security\&.) .PP Note that \fBnamed\fR itself can configure a local DDNS key for use with \fBnsupdate \-l\fR: it does this when a zone is configured with \fBupdate\-policy local;\fR\&. \fBddns\-confgen\fR is only needed when a more elaborate configuration is required: for instance, if \fBnsupdate\fR is to be used from a remote system\&. .SH "OPTIONS" .PP \-a \fIalgorithm\fR .RS 4 Specifies the algorithm to use for the TSIG key\&. Available choices are: hmac\-md5, hmac\-sha1, hmac\-sha224, hmac\-sha256, hmac\-sha384 and hmac\-sha512\&. The default is hmac\-sha256\&. Options are case\-insensitive, and the "hmac\-" prefix may be omitted\&. .RE .PP \-h .RS 4 Prints a short summary of options and arguments\&. .RE .PP \-k \fIkeyname\fR .RS 4 Specifies the key name of the DDNS authentication key\&. The default is \fBddns\-key\fR when neither the \fB\-s\fR nor \fB\-z\fR option is specified; otherwise, the default is \fBddns\-key\fR as a separate label followed by the argument of the option, e\&.g\&., \fBddns\-key\&.example\&.com\&.\fR The key name must have the format of a valid domain name, consisting of letters, digits, hyphens and periods\&. .RE .PP \-q .RS 4 (\fBddns\-confgen\fR only\&.) Quiet mode: Print only the key, with no explanatory text or usage examples; This is essentially identical to \fBtsig\-keygen\fR\&. .RE .PP \-r \fIrandomfile\fR .RS 4 Specifies a source of random data for generating the authorization\&. If the operating system does not provide a /dev/random or equivalent device, the default source of randomness is keyboard input\&. randomdev specifies the name of a character device or file containing random data to be used instead of the default\&. The special value keyboard indicates that keyboard input should be used\&. .RE .PP \-s \fIname\fR .RS 4 (\fBddns\-confgen\fR only\&.) Generate configuration example to allow dynamic updates of a single hostname\&. The example \fBnamed\&.conf\fR text shows how to set an update policy for the specified \fIname\fR using the "name" nametype\&. The default key name is ddns\-key\&.\fIname\fR\&. Note that the "self" nametype cannot be used, since the name to be updated may differ from the key name\&. This option cannot be used with the \fB\-z\fR option\&. .RE .PP \-z \fIzone\fR .RS 4 (\fBddns\-confgen\fR only\&.) Generate configuration example to allow dynamic updates of a zone: The example \fBnamed\&.conf\fR text shows how to set an update policy for the specified \fIzone\fR using the "zonesub" nametype, allowing updates to all subdomain names within that \fIzone\fR\&. This option cannot be used with the \fB\-s\fR option\&. .RE .SH "SEE ALSO" .PP \fBnsupdate\fR(1), \fBnamed.conf\fR(5), \fBnamed\fR(8), BIND 9 Administrator Reference Manual\&. .SH "AUTHOR" .PP \fBInternet Systems Consortium, Inc\&.\fR .SH "COPYRIGHT" .br Copyright \(co 2009, 2014-2016 Internet Systems Consortium, Inc. ("ISC") .br bind9-9.11.3+dfsg/bin/confgen/ddns-confgen.c000066400000000000000000000165501325250447100204430ustar00rootroot00000000000000/* * Copyright (C) 2009, 2011, 2014, 2016 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /*! \file */ /** * ddns-confgen generates configuration files for dynamic DNS. It can * be used as a convenient alternative to writing the ddns.key file * and the corresponding key and update-policy statements in named.conf. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef PKCS11CRYPTO #include #endif #include #include #include #include #include #include "util.h" #include "keygen.h" #define KEYGEN_DEFAULT "tsig-key" #define CONFGEN_DEFAULT "ddns-key" static char program[256]; const char *progname; static enum { progmode_keygen, progmode_confgen} progmode; isc_boolean_t verbose = ISC_FALSE; /* needed by util.c but not used here */ ISC_PLATFORM_NORETURN_PRE static void usage(int status) ISC_PLATFORM_NORETURN_POST; static void usage(int status) { if (progmode == progmode_confgen) { fprintf(stderr, "\ Usage:\n\ %s [-a alg] [-k keyname] [-r randomfile] [-q] [-s name | -z zone]\n\ -a alg: algorithm (default hmac-sha256)\n\ -k keyname: name of the key as it will be used in named.conf\n\ -r randomfile: source of random data (use \"keyboard\" for key timing)\n\ -s name: domain name to be updated using the created key\n\ -z zone: name of the zone as it will be used in named.conf\n\ -q: quiet mode: print the key, with no explanatory text\n", progname); } else { fprintf(stderr, "\ Usage:\n\ %s [-a alg] [-r randomfile] [keyname]\n\ -a alg: algorithm (default hmac-sha256)\n\ -r randomfile: source of random data (use \"keyboard\" for key timing)\n", progname); } exit (status); } int main(int argc, char **argv) { isc_result_t result = ISC_R_SUCCESS; isc_boolean_t show_final_mem = ISC_FALSE; isc_boolean_t quiet = ISC_FALSE; isc_buffer_t key_txtbuffer; char key_txtsecret[256]; isc_mem_t *mctx = NULL; const char *randomfile = NULL; const char *keyname = NULL; const char *zone = NULL; const char *self_domain = NULL; char *keybuf = NULL; dns_secalg_t alg = DST_ALG_HMACSHA256; const char *algname; int keysize = 256; int len = 0; int ch; #ifdef PKCS11CRYPTO pk11_result_register(); #endif dns_result_register(); result = isc_file_progname(*argv, program, sizeof(program)); if (result != ISC_R_SUCCESS) memmove(program, "tsig-keygen", 11); progname = program; /* * Libtool doesn't preserve the program name prior to final * installation. Remove the libtool prefix ("lt-"). */ if (strncmp(progname, "lt-", 3) == 0) progname += 3; #define PROGCMP(X) \ (strcasecmp(progname, X) == 0 || strcasecmp(progname, X ".exe") == 0) if (PROGCMP("tsig-keygen")) { progmode = progmode_keygen; quiet = ISC_TRUE; } else if (PROGCMP("ddns-confgen")) progmode = progmode_confgen; else INSIST(0); isc_commandline_errprint = ISC_FALSE; while ((ch = isc_commandline_parse(argc, argv, "a:hk:Mmr:qs:y:z:")) != -1) { switch (ch) { case 'a': algname = isc_commandline_argument; alg = alg_fromtext(algname); if (alg == DST_ALG_UNKNOWN) fatal("Unsupported algorithm '%s'", algname); keysize = alg_bits(alg); break; case 'h': usage(0); case 'k': case 'y': if (progmode == progmode_confgen) keyname = isc_commandline_argument; else usage(1); break; case 'M': isc_mem_debugging = ISC_MEM_DEBUGTRACE; break; case 'm': show_final_mem = ISC_TRUE; break; case 'q': if (progmode == progmode_confgen) quiet = ISC_TRUE; else usage(1); break; case 'r': randomfile = isc_commandline_argument; break; case 's': if (progmode == progmode_confgen) self_domain = isc_commandline_argument; else usage(1); break; case 'z': if (progmode == progmode_confgen) zone = isc_commandline_argument; else usage(1); break; case '?': if (isc_commandline_option != '?') { fprintf(stderr, "%s: invalid argument -%c\n", program, isc_commandline_option); usage(1); } else usage(0); break; default: fprintf(stderr, "%s: unhandled option -%c\n", program, isc_commandline_option); exit(1); } } if (progmode == progmode_keygen) keyname = argv[isc_commandline_index++]; POST(argv); if (self_domain != NULL && zone != NULL) usage(1); /* -s and -z cannot coexist */ if (argc > isc_commandline_index) usage(1); /* Use canonical algorithm name */ algname = alg_totext(alg); DO("create memory context", isc_mem_create(0, 0, &mctx)); if (keyname == NULL) { const char *suffix = NULL; keyname = ((progmode == progmode_keygen) ? KEYGEN_DEFAULT : CONFGEN_DEFAULT); if (self_domain != NULL) suffix = self_domain; else if (zone != NULL) suffix = zone; if (suffix != NULL) { len = strlen(keyname) + strlen(suffix) + 2; keybuf = isc_mem_get(mctx, len); if (keybuf == NULL) fatal("failed to allocate memory for keyname"); snprintf(keybuf, len, "%s.%s", keyname, suffix); keyname = (const char *) keybuf; } } isc_buffer_init(&key_txtbuffer, &key_txtsecret, sizeof(key_txtsecret)); generate_key(mctx, randomfile, alg, keysize, &key_txtbuffer); if (!quiet) printf("\ # To activate this key, place the following in named.conf, and\n\ # in a separate keyfile on the system or systems from which nsupdate\n\ # will be run:\n"); printf("\ key \"%s\" {\n\ algorithm %s;\n\ secret \"%.*s\";\n\ };\n", keyname, algname, (int)isc_buffer_usedlength(&key_txtbuffer), (char *)isc_buffer_base(&key_txtbuffer)); if (!quiet) { if (self_domain != NULL) { printf("\n\ # Then, in the \"zone\" statement for the zone containing the\n\ # name \"%s\", place an \"update-policy\" statement\n\ # like this one, adjusted as needed for your preferred permissions:\n\ update-policy {\n\ grant %s name %s ANY;\n\ };\n", self_domain, keyname, self_domain); } else if (zone != NULL) { printf("\n\ # Then, in the \"zone\" definition statement for \"%s\",\n\ # place an \"update-policy\" statement like this one, adjusted as \n\ # needed for your preferred permissions:\n\ update-policy {\n\ grant %s zonesub ANY;\n\ };\n", zone, keyname); } else { printf("\n\ # Then, in the \"zone\" statement for each zone you wish to dynamically\n\ # update, place an \"update-policy\" statement granting update permission\n\ # to this key. For example, the following statement grants this key\n\ # permission to update any name within the zone:\n\ update-policy {\n\ grant %s zonesub ANY;\n\ };\n", keyname); } printf("\n\ # After the keyfile has been placed, the following command will\n\ # execute nsupdate using this key:\n\ nsupdate -k \n"); } if (keybuf != NULL) isc_mem_put(mctx, keybuf, len); if (show_final_mem) isc_mem_stats(mctx, stderr); isc_mem_destroy(&mctx); return (0); } bind9-9.11.3+dfsg/bin/confgen/ddns-confgen.docbook000066400000000000000000000204251325250447100216350ustar00rootroot00000000000000 2014-03-06 ISC Internet Systems Consortium, Inc. ddns-confgen 8 BIND9 ddns-confgen ddns key generation tool 2009 2014 2015 2016 Internet Systems Consortium, Inc. ("ISC") tsig-keygen name ddns-confgen -s name -z zone DESCRIPTION tsig-keygen and ddns-confgen are invocation methods for a utility that generates keys for use in TSIG signing. The resulting keys can be used, for example, to secure dynamic DNS updates to a zone or for the rndc command channel. When run as tsig-keygen, a domain name can be specified on the command line which will be used as the name of the generated key. If no name is specified, the default is tsig-key. When run as ddns-confgen, the generated key is accompanied by configuration text and instructions that can be used with nsupdate and named when setting up dynamic DNS, including an example update-policy statement. (This usage similar to the rndc-confgen command for setting up command channel security.) Note that named itself can configure a local DDNS key for use with nsupdate -l: it does this when a zone is configured with update-policy local;. ddns-confgen is only needed when a more elaborate configuration is required: for instance, if nsupdate is to be used from a remote system. OPTIONS -a algorithm Specifies the algorithm to use for the TSIG key. Available choices are: hmac-md5, hmac-sha1, hmac-sha224, hmac-sha256, hmac-sha384 and hmac-sha512. The default is hmac-sha256. Options are case-insensitive, and the "hmac-" prefix may be omitted. -h Prints a short summary of options and arguments. -k keyname Specifies the key name of the DDNS authentication key. The default is ddns-key when neither the nor option is specified; otherwise, the default is ddns-key as a separate label followed by the argument of the option, e.g., ddns-key.example.com. The key name must have the format of a valid domain name, consisting of letters, digits, hyphens and periods. -q (ddns-confgen only.) Quiet mode: Print only the key, with no explanatory text or usage examples; This is essentially identical to tsig-keygen. -r randomfile Specifies a source of random data for generating the authorization. If the operating system does not provide a /dev/random or equivalent device, the default source of randomness is keyboard input. randomdev specifies the name of a character device or file containing random data to be used instead of the default. The special value keyboard indicates that keyboard input should be used. -s name (ddns-confgen only.) Generate configuration example to allow dynamic updates of a single hostname. The example named.conf text shows how to set an update policy for the specified name using the "name" nametype. The default key name is ddns-key.name. Note that the "self" nametype cannot be used, since the name to be updated may differ from the key name. This option cannot be used with the option. -z zone (ddns-confgen only.) Generate configuration example to allow dynamic updates of a zone: The example named.conf text shows how to set an update policy for the specified zone using the "zonesub" nametype, allowing updates to all subdomain names within that zone. This option cannot be used with the option. SEE ALSO nsupdate1 , named.conf5 , named8 , BIND 9 Administrator Reference Manual. bind9-9.11.3+dfsg/bin/confgen/ddns-confgen.html000066400000000000000000000200661325250447100211620ustar00rootroot00000000000000 ddns-confgen

Name

ddns-confgen — ddns key generation tool

Synopsis

tsig-keygen [-a algorithm] [-h] [-r randomfile] [name]

ddns-confgen [-a algorithm] [-h] [-k keyname] [-q] [-r randomfile] [ -s name | -z zone ]

DESCRIPTION

tsig-keygen and ddns-confgen are invocation methods for a utility that generates keys for use in TSIG signing. The resulting keys can be used, for example, to secure dynamic DNS updates to a zone or for the rndc command channel.

When run as tsig-keygen, a domain name can be specified on the command line which will be used as the name of the generated key. If no name is specified, the default is tsig-key.

When run as ddns-confgen, the generated key is accompanied by configuration text and instructions that can be used with nsupdate and named when setting up dynamic DNS, including an example update-policy statement. (This usage similar to the rndc-confgen command for setting up command channel security.)

Note that named itself can configure a local DDNS key for use with nsupdate -l: it does this when a zone is configured with update-policy local;. ddns-confgen is only needed when a more elaborate configuration is required: for instance, if nsupdate is to be used from a remote system.

OPTIONS

-a algorithm

Specifies the algorithm to use for the TSIG key. Available choices are: hmac-md5, hmac-sha1, hmac-sha224, hmac-sha256, hmac-sha384 and hmac-sha512. The default is hmac-sha256. Options are case-insensitive, and the "hmac-" prefix may be omitted.

-h

Prints a short summary of options and arguments.

-k keyname

Specifies the key name of the DDNS authentication key. The default is ddns-key when neither the -s nor -z option is specified; otherwise, the default is ddns-key as a separate label followed by the argument of the option, e.g., ddns-key.example.com. The key name must have the format of a valid domain name, consisting of letters, digits, hyphens and periods.

-q

(ddns-confgen only.) Quiet mode: Print only the key, with no explanatory text or usage examples; This is essentially identical to tsig-keygen.

-r randomfile

Specifies a source of random data for generating the authorization. If the operating system does not provide a /dev/random or equivalent device, the default source of randomness is keyboard input. randomdev specifies the name of a character device or file containing random data to be used instead of the default. The special value keyboard indicates that keyboard input should be used.

-s name

(ddns-confgen only.) Generate configuration example to allow dynamic updates of a single hostname. The example named.conf text shows how to set an update policy for the specified name using the "name" nametype. The default key name is ddns-key.name. Note that the "self" nametype cannot be used, since the name to be updated may differ from the key name. This option cannot be used with the -z option.

-z zone

(ddns-confgen only.) Generate configuration example to allow dynamic updates of a zone: The example named.conf text shows how to set an update policy for the specified zone using the "zonesub" nametype, allowing updates to all subdomain names within that zone. This option cannot be used with the -s option.

SEE ALSO

nsupdate(1) , named.conf(5) , named(8) , BIND 9 Administrator Reference Manual.

bind9-9.11.3+dfsg/bin/confgen/include/000077500000000000000000000000001325250447100173465ustar00rootroot00000000000000bind9-9.11.3+dfsg/bin/confgen/include/confgen/000077500000000000000000000000001325250447100207655ustar00rootroot00000000000000bind9-9.11.3+dfsg/bin/confgen/include/confgen/os.h000066400000000000000000000012511325250447100215560ustar00rootroot00000000000000/* * Copyright (C) 2009, 2016 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* $Id: os.h,v 1.3 2009/06/11 23:47:55 tbox Exp $ */ /*! \file */ #ifndef RNDC_OS_H #define RNDC_OS_H 1 #include #include ISC_LANG_BEGINDECLS int set_user(FILE *fd, const char *user); /*%< * Set the owner of the file referenced by 'fd' to 'user'. * Returns: * 0 success * -1 insufficient permissions, or 'user' does not exist. */ ISC_LANG_ENDDECLS #endif bind9-9.11.3+dfsg/bin/confgen/keygen.c000066400000000000000000000125421325250447100173550ustar00rootroot00000000000000/* * Copyright (C) 2009, 2012-2016 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* $Id: keygen.c,v 1.4 2009/11/12 14:02:38 marka Exp $ */ /*! \file */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "util.h" #include "keygen.h" /*% * Convert algorithm type to string. */ const char * alg_totext(dns_secalg_t alg) { switch (alg) { #ifndef PK11_MD5_DISABLE case DST_ALG_HMACMD5: return "hmac-md5"; #endif case DST_ALG_HMACSHA1: return "hmac-sha1"; case DST_ALG_HMACSHA224: return "hmac-sha224"; case DST_ALG_HMACSHA256: return "hmac-sha256"; case DST_ALG_HMACSHA384: return "hmac-sha384"; case DST_ALG_HMACSHA512: return "hmac-sha512"; default: return "(unknown)"; } } /*% * Convert string to algorithm type. */ dns_secalg_t alg_fromtext(const char *name) { const char *p = name; if (strncasecmp(p, "hmac-", 5) == 0) p = &name[5]; #ifndef PK11_MD5_DISABLE if (strcasecmp(p, "md5") == 0) return DST_ALG_HMACMD5; #endif if (strcasecmp(p, "sha1") == 0) return DST_ALG_HMACSHA1; if (strcasecmp(p, "sha224") == 0) return DST_ALG_HMACSHA224; if (strcasecmp(p, "sha256") == 0) return DST_ALG_HMACSHA256; if (strcasecmp(p, "sha384") == 0) return DST_ALG_HMACSHA384; if (strcasecmp(p, "sha512") == 0) return DST_ALG_HMACSHA512; return DST_ALG_UNKNOWN; } /*% * Return default keysize for a given algorithm type. */ int alg_bits(dns_secalg_t alg) { switch (alg) { case DST_ALG_HMACMD5: return 128; case DST_ALG_HMACSHA1: return 160; case DST_ALG_HMACSHA224: return 224; case DST_ALG_HMACSHA256: return 256; case DST_ALG_HMACSHA384: return 384; case DST_ALG_HMACSHA512: return 512; default: return 0; } } /*% * Generate a key of size 'keysize' using entropy source 'randomfile', * and place it in 'key_txtbuffer' */ void generate_key(isc_mem_t *mctx, const char *randomfile, dns_secalg_t alg, int keysize, isc_buffer_t *key_txtbuffer) { isc_result_t result = ISC_R_SUCCESS; isc_entropysource_t *entropy_source = NULL; int open_keyboard = ISC_ENTROPY_KEYBOARDMAYBE; int entropy_flags = 0; isc_entropy_t *ectx = NULL; isc_buffer_t key_rawbuffer; isc_region_t key_rawregion; char key_rawsecret[64]; dst_key_t *key = NULL; switch (alg) { #ifndef PK11_MD5_DISABLE case DST_ALG_HMACMD5: #endif case DST_ALG_HMACSHA1: case DST_ALG_HMACSHA224: case DST_ALG_HMACSHA256: if (keysize < 1 || keysize > 512) fatal("keysize %d out of range (must be 1-512)\n", keysize); break; case DST_ALG_HMACSHA384: case DST_ALG_HMACSHA512: if (keysize < 1 || keysize > 1024) fatal("keysize %d out of range (must be 1-1024)\n", keysize); break; default: fatal("unsupported algorithm %d\n", alg); } DO("create entropy context", isc_entropy_create(mctx, &ectx)); if (randomfile != NULL && strcmp(randomfile, "keyboard") == 0) { randomfile = NULL; open_keyboard = ISC_ENTROPY_KEYBOARDYES; } DO("start entropy source", isc_entropy_usebestsource(ectx, &entropy_source, randomfile, open_keyboard)); entropy_flags = ISC_ENTROPY_BLOCKING | ISC_ENTROPY_GOODONLY; DO("initialize dst library", dst_lib_init(mctx, ectx, entropy_flags)); DO("generate key", dst_key_generate(dns_rootname, alg, keysize, 0, 0, DNS_KEYPROTO_ANY, dns_rdataclass_in, mctx, &key)); isc_buffer_init(&key_rawbuffer, &key_rawsecret, sizeof(key_rawsecret)); DO("dump key to buffer", dst_key_tobuffer(key, &key_rawbuffer)); isc_buffer_usedregion(&key_rawbuffer, &key_rawregion); DO("bsse64 encode secret", isc_base64_totext(&key_rawregion, -1, "", key_txtbuffer)); /* * Shut down the entropy source now so the "stop typing" message * does not muck with the output. */ if (entropy_source != NULL) isc_entropy_destroysource(&entropy_source); if (key != NULL) dst_key_free(&key); isc_entropy_detach(&ectx); dst_lib_destroy(); } /*% * Write a key file to 'keyfile'. If 'user' is non-NULL, * make that user the owner of the file. The key will have * the name 'keyname' and the secret in the buffer 'secret'. */ void write_key_file(const char *keyfile, const char *user, const char *keyname, isc_buffer_t *secret, dns_secalg_t alg) { isc_result_t result; const char *algname = alg_totext(alg); FILE *fd = NULL; DO("create keyfile", isc_file_safecreate(keyfile, &fd)); if (user != NULL) { if (set_user(fd, user) == -1) fatal("unable to set file owner\n"); } fprintf(fd, "key \"%s\" {\n\talgorithm %s;\n" "\tsecret \"%.*s\";\n};\n", keyname, algname, (int)isc_buffer_usedlength(secret), (char *)isc_buffer_base(secret)); fflush(fd); if (ferror(fd)) fatal("write to %s failed\n", keyfile); if (fclose(fd)) fatal("fclose(%s) failed\n", keyfile); fprintf(stderr, "wrote key file \"%s\"\n", keyfile); } bind9-9.11.3+dfsg/bin/confgen/keygen.h000066400000000000000000000015501325250447100173570ustar00rootroot00000000000000/* * Copyright (C) 2009, 2016 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* $Id: keygen.h,v 1.3 2009/06/11 23:47:55 tbox Exp $ */ #ifndef RNDC_KEYGEN_H #define RNDC_KEYGEN_H 1 /*! \file */ #include ISC_LANG_BEGINDECLS void generate_key(isc_mem_t *mctx, const char *randomfile, dns_secalg_t alg, int keysize, isc_buffer_t *key_txtbuffer); void write_key_file(const char *keyfile, const char *user, const char *keyname, isc_buffer_t *secret, dns_secalg_t alg); const char *alg_totext(dns_secalg_t alg); dns_secalg_t alg_fromtext(const char *name); int alg_bits(dns_secalg_t alg); ISC_LANG_ENDDECLS #endif /* RNDC_KEYGEN_H */ bind9-9.11.3+dfsg/bin/confgen/rndc-confgen.8000066400000000000000000000132501325250447100203600ustar00rootroot00000000000000.\" Copyright (C) 2001, 2003-2005, 2007, 2009, 2013-2016 Internet Systems Consortium, Inc. ("ISC") .\" .\" This Source Code Form is subject to the terms of the Mozilla Public .\" License, v. 2.0. If a copy of the MPL was not distributed with this .\" file, You can obtain one at http://mozilla.org/MPL/2.0/. .\" .hy 0 .ad l '\" t .\" Title: rndc-confgen .\" Author: .\" Generator: DocBook XSL Stylesheets v1.78.1 .\" Date: 2013-03-14 .\" Manual: BIND9 .\" Source: ISC .\" Language: English .\" .TH "RNDC\-CONFGEN" "8" "2013\-03\-14" "ISC" "BIND9" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" rndc-confgen \- rndc key generation tool .SH "SYNOPSIS" .HP \w'\fBrndc\-confgen\fR\ 'u \fBrndc\-confgen\fR [\fB\-a\fR] [\fB\-A\ \fR\fB\fIalgorithm\fR\fR] [\fB\-b\ \fR\fB\fIkeysize\fR\fR] [\fB\-c\ \fR\fB\fIkeyfile\fR\fR] [\fB\-h\fR] [\fB\-k\ \fR\fB\fIkeyname\fR\fR] [\fB\-p\ \fR\fB\fIport\fR\fR] [\fB\-r\ \fR\fB\fIrandomfile\fR\fR] [\fB\-s\ \fR\fB\fIaddress\fR\fR] [\fB\-t\ \fR\fB\fIchrootdir\fR\fR] [\fB\-u\ \fR\fB\fIuser\fR\fR] .SH "DESCRIPTION" .PP \fBrndc\-confgen\fR generates configuration files for \fBrndc\fR\&. It can be used as a convenient alternative to writing the rndc\&.conf file and the corresponding \fBcontrols\fR and \fBkey\fR statements in named\&.conf by hand\&. Alternatively, it can be run with the \fB\-a\fR option to set up a rndc\&.key file and avoid the need for a rndc\&.conf file and a \fBcontrols\fR statement altogether\&. .SH "OPTIONS" .PP \-a .RS 4 Do automatic \fBrndc\fR configuration\&. This creates a file rndc\&.key in /etc (or whatever \fIsysconfdir\fR was specified as when BIND was built) that is read by both \fBrndc\fR and \fBnamed\fR on startup\&. The rndc\&.key file defines a default command channel and authentication key allowing \fBrndc\fR to communicate with \fBnamed\fR on the local host with no further configuration\&. .sp Running \fBrndc\-confgen \-a\fR allows BIND 9 and \fBrndc\fR to be used as drop\-in replacements for BIND 8 and \fBndc\fR, with no changes to the existing BIND 8 named\&.conf file\&. .sp If a more elaborate configuration than that generated by \fBrndc\-confgen \-a\fR is required, for example if rndc is to be used remotely, you should run \fBrndc\-confgen\fR without the \fB\-a\fR option and set up a rndc\&.conf and named\&.conf as directed\&. .RE .PP \-A \fIalgorithm\fR .RS 4 Specifies the algorithm to use for the TSIG key\&. Available choices are: hmac\-md5, hmac\-sha1, hmac\-sha224, hmac\-sha256, hmac\-sha384 and hmac\-sha512\&. The default is hmac\-md5 or if MD5 was disabled hmac\-sha256\&. .RE .PP \-b \fIkeysize\fR .RS 4 Specifies the size of the authentication key in bits\&. Must be between 1 and 512 bits; the default is the hash size\&. .RE .PP \-c \fIkeyfile\fR .RS 4 Used with the \fB\-a\fR option to specify an alternate location for rndc\&.key\&. .RE .PP \-h .RS 4 Prints a short summary of the options and arguments to \fBrndc\-confgen\fR\&. .RE .PP \-k \fIkeyname\fR .RS 4 Specifies the key name of the rndc authentication key\&. This must be a valid domain name\&. The default is \fBrndc\-key\fR\&. .RE .PP \-p \fIport\fR .RS 4 Specifies the command channel port where \fBnamed\fR listens for connections from \fBrndc\fR\&. The default is 953\&. .RE .PP \-r \fIrandomfile\fR .RS 4 Specifies a source of random data for generating the authorization\&. If the operating system does not provide a /dev/random or equivalent device, the default source of randomness is keyboard input\&. randomdev specifies the name of a character device or file containing random data to be used instead of the default\&. The special value keyboard indicates that keyboard input should be used\&. .RE .PP \-s \fIaddress\fR .RS 4 Specifies the IP address where \fBnamed\fR listens for command channel connections from \fBrndc\fR\&. The default is the loopback address 127\&.0\&.0\&.1\&. .RE .PP \-t \fIchrootdir\fR .RS 4 Used with the \fB\-a\fR option to specify a directory where \fBnamed\fR will run chrooted\&. An additional copy of the rndc\&.key will be written relative to this directory so that it will be found by the chrooted \fBnamed\fR\&. .RE .PP \-u \fIuser\fR .RS 4 Used with the \fB\-a\fR option to set the owner of the rndc\&.key file generated\&. If \fB\-t\fR is also specified only the file in the chroot area has its owner changed\&. .RE .SH "EXAMPLES" .PP To allow \fBrndc\fR to be used with no manual configuration, run .PP \fBrndc\-confgen \-a\fR .PP To print a sample rndc\&.conf file and corresponding \fBcontrols\fR and \fBkey\fR statements to be manually inserted into named\&.conf, run .PP \fBrndc\-confgen\fR .SH "SEE ALSO" .PP \fBrndc\fR(8), \fBrndc.conf\fR(5), \fBnamed\fR(8), BIND 9 Administrator Reference Manual\&. .SH "AUTHOR" .PP \fBInternet Systems Consortium, Inc\&.\fR .SH "COPYRIGHT" .br Copyright \(co 2001, 2003-2005, 2007, 2009, 2013-2016 Internet Systems Consortium, Inc. ("ISC") .br bind9-9.11.3+dfsg/bin/confgen/rndc-confgen.c000066400000000000000000000172711325250447100204420ustar00rootroot00000000000000/* * Copyright (C) 2001, 2003-2005, 2007-2009, 2011, 2013, 2014, 2016 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* $Id: rndc-confgen.c,v 1.7 2011/03/12 04:59:46 tbox Exp $ */ /*! \file */ /** * rndc-confgen generates configuration files for rndc. It can be used * as a convenient alternative to writing the rndc.conf file and the * corresponding controls and key statements in named.conf by hand. * Alternatively, it can be run with the -a option to set up a * rndc.key file and avoid the need for a rndc.conf file and a * controls statement altogether. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "util.h" #include "keygen.h" #define DEFAULT_KEYNAME "rndc-key" #define DEFAULT_SERVER "127.0.0.1" #define DEFAULT_PORT 953 static char program[256]; const char *progname; isc_boolean_t verbose = ISC_FALSE; const char *keyfile, *keydef; ISC_PLATFORM_NORETURN_PRE static void usage(int status) ISC_PLATFORM_NORETURN_POST; static void usage(int status) { #ifndef PK11_MD5_DISABLE fprintf(stderr, "\ Usage:\n\ %s [-a] [-b bits] [-c keyfile] [-k keyname] [-p port] [-r randomfile] \ [-s addr] [-t chrootdir] [-u user]\n\ -a: generate just the key clause and write it to keyfile (%s)\n\ -A alg: algorithm (default hmac-md5)\n\ -b bits: from 1 through 512, default 256; total length of the secret\n\ -c keyfile: specify an alternate key file (requires -a)\n\ -k keyname: the name as it will be used in named.conf and rndc.conf\n\ -p port: the port named will listen on and rndc will connect to\n\ -r randomfile: source of random data (use \"keyboard\" for key timing)\n\ -s addr: the address to which rndc should connect\n\ -t chrootdir: write a keyfile in chrootdir as well (requires -a)\n\ -u user: set the keyfile owner to \"user\" (requires -a)\n", progname, keydef); #else fprintf(stderr, "\ Usage:\n\ %s [-a] [-b bits] [-c keyfile] [-k keyname] [-p port] [-r randomfile] \ [-s addr] [-t chrootdir] [-u user]\n\ -a: generate just the key clause and write it to keyfile (%s)\n\ -A alg: algorithm (default hmac-sha256)\n\ -b bits: from 1 through 512, default 256; total length of the secret\n\ -c keyfile: specify an alternate key file (requires -a)\n\ -k keyname: the name as it will be used in named.conf and rndc.conf\n\ -p port: the port named will listen on and rndc will connect to\n\ -r randomfile: source of random data (use \"keyboard\" for key timing)\n\ -s addr: the address to which rndc should connect\n\ -t chrootdir: write a keyfile in chrootdir as well (requires -a)\n\ -u user: set the keyfile owner to \"user\" (requires -a)\n", progname, keydef); #endif exit (status); } int main(int argc, char **argv) { isc_boolean_t show_final_mem = ISC_FALSE; isc_buffer_t key_txtbuffer; char key_txtsecret[256]; isc_mem_t *mctx = NULL; isc_result_t result = ISC_R_SUCCESS; const char *keyname = NULL; const char *randomfile = NULL; const char *serveraddr = NULL; dns_secalg_t alg; const char *algname; char *p; int ch; int port; int keysize = -1; struct in_addr addr4_dummy; struct in6_addr addr6_dummy; char *chrootdir = NULL; char *user = NULL; isc_boolean_t keyonly = ISC_FALSE; int len; keydef = keyfile = RNDC_KEYFILE; result = isc_file_progname(*argv, program, sizeof(program)); if (result != ISC_R_SUCCESS) memmove(program, "rndc-confgen", 13); progname = program; keyname = DEFAULT_KEYNAME; #ifndef PK11_MD5_DISABLE alg = DST_ALG_HMACMD5; #else alg = DST_ALG_HMACSHA256; #endif serveraddr = DEFAULT_SERVER; port = DEFAULT_PORT; isc_commandline_errprint = ISC_FALSE; while ((ch = isc_commandline_parse(argc, argv, "aA:b:c:hk:Mmp:r:s:t:u:Vy")) != -1) { switch (ch) { case 'a': keyonly = ISC_TRUE; break; case 'A': algname = isc_commandline_argument; alg = alg_fromtext(algname); if (alg == DST_ALG_UNKNOWN) fatal("Unsupported algorithm '%s'", algname); break; case 'b': keysize = strtol(isc_commandline_argument, &p, 10); if (*p != '\0' || keysize < 0) fatal("-b requires a non-negative number"); break; case 'c': keyfile = isc_commandline_argument; break; case 'h': usage(0); case 'k': case 'y': /* Compatible with rndc -y. */ keyname = isc_commandline_argument; break; case 'M': isc_mem_debugging = ISC_MEM_DEBUGTRACE; break; case 'm': show_final_mem = ISC_TRUE; break; case 'p': port = strtol(isc_commandline_argument, &p, 10); if (*p != '\0' || port < 0 || port > 65535) fatal("port '%s' out of range", isc_commandline_argument); break; case 'r': randomfile = isc_commandline_argument; break; case 's': serveraddr = isc_commandline_argument; if (inet_pton(AF_INET, serveraddr, &addr4_dummy) != 1 && inet_pton(AF_INET6, serveraddr, &addr6_dummy) != 1) fatal("-s should be an IPv4 or IPv6 address"); break; case 't': chrootdir = isc_commandline_argument; break; case 'u': user = isc_commandline_argument; break; case 'V': verbose = ISC_TRUE; break; case '?': if (isc_commandline_option != '?') { fprintf(stderr, "%s: invalid argument -%c\n", program, isc_commandline_option); usage(1); } else usage(0); break; default: fprintf(stderr, "%s: unhandled option -%c\n", program, isc_commandline_option); exit(1); } } argc -= isc_commandline_index; argv += isc_commandline_index; POST(argv); if (argc > 0) usage(1); if (keysize < 0) keysize = alg_bits(alg); algname = alg_totext(alg); DO("create memory context", isc_mem_create(0, 0, &mctx)); isc_buffer_init(&key_txtbuffer, &key_txtsecret, sizeof(key_txtsecret)); generate_key(mctx, randomfile, alg, keysize, &key_txtbuffer); if (keyonly) { write_key_file(keyfile, chrootdir == NULL ? user : NULL, keyname, &key_txtbuffer, alg); if (chrootdir != NULL) { char *buf; len = strlen(chrootdir) + strlen(keyfile) + 2; buf = isc_mem_get(mctx, len); if (buf == NULL) fatal("isc_mem_get(%d) failed\n", len); snprintf(buf, len, "%s%s%s", chrootdir, (*keyfile != '/') ? "/" : "", keyfile); write_key_file(buf, user, keyname, &key_txtbuffer, alg); isc_mem_put(mctx, buf, len); } } else { printf("\ # Start of rndc.conf\n\ key \"%s\" {\n\ algorithm %s;\n\ secret \"%.*s\";\n\ };\n\ \n\ options {\n\ default-key \"%s\";\n\ default-server %s;\n\ default-port %d;\n\ };\n\ # End of rndc.conf\n\ \n\ # Use with the following in named.conf, adjusting the allow list as needed:\n\ # key \"%s\" {\n\ # algorithm %s;\n\ # secret \"%.*s\";\n\ # };\n\ # \n\ # controls {\n\ # inet %s port %d\n\ # allow { %s; } keys { \"%s\"; };\n\ # };\n\ # End of named.conf\n", keyname, algname, (int)isc_buffer_usedlength(&key_txtbuffer), (char *)isc_buffer_base(&key_txtbuffer), keyname, serveraddr, port, keyname, algname, (int)isc_buffer_usedlength(&key_txtbuffer), (char *)isc_buffer_base(&key_txtbuffer), serveraddr, port, serveraddr, keyname); } if (show_final_mem) isc_mem_stats(mctx, stderr); isc_mem_destroy(&mctx); return (0); } bind9-9.11.3+dfsg/bin/confgen/rndc-confgen.docbook000066400000000000000000000243771325250447100216450ustar00rootroot00000000000000 2013-03-14 ISC Internet Systems Consortium, Inc. rndc-confgen 8 BIND9 rndc-confgen rndc key generation tool 2001 2003 2004 2005 2007 2009 2013 2014 2015 2016 Internet Systems Consortium, Inc. ("ISC") rndc-confgen DESCRIPTION rndc-confgen generates configuration files for rndc. It can be used as a convenient alternative to writing the rndc.conf file and the corresponding controls and key statements in named.conf by hand. Alternatively, it can be run with the -a option to set up a rndc.key file and avoid the need for a rndc.conf file and a controls statement altogether. OPTIONS -a Do automatic rndc configuration. This creates a file rndc.key in /etc (or whatever sysconfdir was specified as when BIND was built) that is read by both rndc and named on startup. The rndc.key file defines a default command channel and authentication key allowing rndc to communicate with named on the local host with no further configuration. Running rndc-confgen -a allows BIND 9 and rndc to be used as drop-in replacements for BIND 8 and ndc, with no changes to the existing BIND 8 named.conf file. If a more elaborate configuration than that generated by rndc-confgen -a is required, for example if rndc is to be used remotely, you should run rndc-confgen without the -a option and set up a rndc.conf and named.conf as directed. -A algorithm Specifies the algorithm to use for the TSIG key. Available choices are: hmac-md5, hmac-sha1, hmac-sha224, hmac-sha256, hmac-sha384 and hmac-sha512. The default is hmac-md5 or if MD5 was disabled hmac-sha256. -b keysize Specifies the size of the authentication key in bits. Must be between 1 and 512 bits; the default is the hash size. -c keyfile Used with the -a option to specify an alternate location for rndc.key. -h Prints a short summary of the options and arguments to rndc-confgen. -k keyname Specifies the key name of the rndc authentication key. This must be a valid domain name. The default is rndc-key. -p port Specifies the command channel port where named listens for connections from rndc. The default is 953. -r randomfile Specifies a source of random data for generating the authorization. If the operating system does not provide a /dev/random or equivalent device, the default source of randomness is keyboard input. randomdev specifies the name of a character device or file containing random data to be used instead of the default. The special value keyboard indicates that keyboard input should be used. -s address Specifies the IP address where named listens for command channel connections from rndc. The default is the loopback address 127.0.0.1. -t chrootdir Used with the -a option to specify a directory where named will run chrooted. An additional copy of the rndc.key will be written relative to this directory so that it will be found by the chrooted named. -u user Used with the -a option to set the owner of the rndc.key file generated. If -t is also specified only the file in the chroot area has its owner changed. EXAMPLES To allow rndc to be used with no manual configuration, run rndc-confgen -a To print a sample rndc.conf file and corresponding controls and key statements to be manually inserted into named.conf, run rndc-confgen SEE ALSO rndc8 , rndc.conf5 , named8 , BIND 9 Administrator Reference Manual. bind9-9.11.3+dfsg/bin/confgen/rndc-confgen.html000066400000000000000000000240641325250447100211620ustar00rootroot00000000000000 rndc-confgen

Name

rndc-confgen — rndc key generation tool

Synopsis

rndc-confgen [-a] [-A algorithm] [-b keysize] [-c keyfile] [-h] [-k keyname] [-p port] [-r randomfile] [-s address] [-t chrootdir] [-u user]

DESCRIPTION

rndc-confgen generates configuration files for rndc. It can be used as a convenient alternative to writing the rndc.conf file and the corresponding controls and key statements in named.conf by hand. Alternatively, it can be run with the -a option to set up a rndc.key file and avoid the need for a rndc.conf file and a controls statement altogether.

OPTIONS

-a

Do automatic rndc configuration. This creates a file rndc.key in /etc (or whatever sysconfdir was specified as when BIND was built) that is read by both rndc and named on startup. The rndc.key file defines a default command channel and authentication key allowing rndc to communicate with named on the local host with no further configuration.

Running rndc-confgen -a allows BIND 9 and rndc to be used as drop-in replacements for BIND 8 and ndc, with no changes to the existing BIND 8 named.conf file.

If a more elaborate configuration than that generated by rndc-confgen -a is required, for example if rndc is to be used remotely, you should run rndc-confgen without the -a option and set up a rndc.conf and named.conf as directed.

-A algorithm

Specifies the algorithm to use for the TSIG key. Available choices are: hmac-md5, hmac-sha1, hmac-sha224, hmac-sha256, hmac-sha384 and hmac-sha512. The default is hmac-md5 or if MD5 was disabled hmac-sha256.

-b keysize

Specifies the size of the authentication key in bits. Must be between 1 and 512 bits; the default is the hash size.

-c keyfile

Used with the -a option to specify an alternate location for rndc.key.

-h

Prints a short summary of the options and arguments to rndc-confgen.

-k keyname

Specifies the key name of the rndc authentication key. This must be a valid domain name. The default is rndc-key.

-p port

Specifies the command channel port where named listens for connections from rndc. The default is 953.

-r randomfile

Specifies a source of random data for generating the authorization. If the operating system does not provide a /dev/random or equivalent device, the default source of randomness is keyboard input. randomdev specifies the name of a character device or file containing random data to be used instead of the default. The special value keyboard indicates that keyboard input should be used.

-s address

Specifies the IP address where named listens for command channel connections from rndc. The default is the loopback address 127.0.0.1.

-t chrootdir

Used with the -a option to specify a directory where named will run chrooted. An additional copy of the rndc.key will be written relative to this directory so that it will be found by the chrooted named.

-u user

Used with the -a option to set the owner of the rndc.key file generated. If -t is also specified only the file in the chroot area has its owner changed.

EXAMPLES

To allow rndc to be used with no manual configuration, run

rndc-confgen -a

To print a sample rndc.conf file and corresponding controls and key statements to be manually inserted into named.conf, run

rndc-confgen

SEE ALSO

rndc(8) , rndc.conf(5) , named(8) , BIND 9 Administrator Reference Manual.

bind9-9.11.3+dfsg/bin/confgen/unix/000077500000000000000000000000001325250447100167065ustar00rootroot00000000000000bind9-9.11.3+dfsg/bin/confgen/unix/Makefile.in000066400000000000000000000011351325250447100207530ustar00rootroot00000000000000# Copyright (C) 2009, 2012, 2016 Internet Systems Consortium, Inc. ("ISC") # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. # $Id: Makefile.in,v 1.3 2009/06/11 23:47:55 tbox Exp $ srcdir = @srcdir@ VPATH = @srcdir@ top_srcdir = @top_srcdir@ @BIND9_MAKE_INCLUDES@ CINCLUDES = -I${srcdir}/include -I${srcdir}/../include \ ${DNS_INCLUDES} ${ISC_INCLUDES} CDEFINES = CWARNINGS = OBJS = os.@O@ SRCS = os.c TARGETS = ${OBJS} @BIND9_MAKE_RULES@ bind9-9.11.3+dfsg/bin/confgen/unix/os.c000066400000000000000000000013271325250447100174760ustar00rootroot00000000000000/* * Copyright (C) 2009, 2016 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* $Id: os.c,v 1.3 2009/06/11 23:47:55 tbox Exp $ */ /*! \file */ #include #include #include #include #include #include #include #include #include int set_user(FILE *fd, const char *user) { struct passwd *pw; pw = getpwnam(user); if (pw == NULL) { errno = EINVAL; return (-1); } return (fchown(fileno(fd), pw->pw_uid, -1)); } bind9-9.11.3+dfsg/bin/confgen/util.c000066400000000000000000000016371325250447100170530ustar00rootroot00000000000000/* * Copyright (C) 2009, 2015, 2016 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* $Id: util.c,v 1.3 2009/06/11 23:47:55 tbox Exp $ */ /*! \file */ #include #include #include #include #include #include #include "util.h" extern isc_boolean_t verbose; extern const char *progname; void notify(const char *fmt, ...) { va_list ap; if (verbose) { va_start(ap, fmt); vfprintf(stderr, fmt, ap); va_end(ap); fputs("\n", stderr); } } void fatal(const char *format, ...) { va_list args; fprintf(stderr, "%s: ", progname); va_start(args, format); vfprintf(stderr, format, args); va_end(args); fprintf(stderr, "\n"); exit(1); } bind9-9.11.3+dfsg/bin/confgen/util.h000066400000000000000000000016731325250447100170600ustar00rootroot00000000000000/* * Copyright (C) 2009, 2016 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* $Id: util.h,v 1.4 2009/09/29 15:06:05 fdupont Exp $ */ #ifndef RNDC_UTIL_H #define RNDC_UTIL_H 1 /*! \file */ #include #include #include #define NS_CONTROL_PORT 953 #undef DO #define DO(name, function) \ do { \ result = function; \ if (result != ISC_R_SUCCESS) \ fatal("%s: %s", name, isc_result_totext(result)); \ else \ notify("%s", name); \ } while (0) ISC_LANG_BEGINDECLS void notify(const char *fmt, ...) ISC_FORMAT_PRINTF(1, 2); ISC_PLATFORM_NORETURN_PRE void fatal(const char *format, ...) ISC_FORMAT_PRINTF(1, 2) ISC_PLATFORM_NORETURN_POST; ISC_LANG_ENDDECLS #endif /* RNDC_UTIL_H */ bind9-9.11.3+dfsg/bin/confgen/win32/000077500000000000000000000000001325250447100166655ustar00rootroot00000000000000bind9-9.11.3+dfsg/bin/confgen/win32/confgentool.dsp.in000066400000000000000000000102731325250447100223220ustar00rootroot00000000000000# Microsoft Developer Studio Project File - Name="confgentool" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "@PLATFORM@ (x86) Static-Link Library" 0x0104 CFG=confgentool - @PLATFORM@ Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "confgentool.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "confgentool.mak" CFG="confgentool - @PLATFORM@ Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "confgentool - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Static-Link Library") !MESSAGE "confgentool - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Static-Link Library") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe MTL=midl.exe RSC=rc.exe !IF "$(CFG)" == "confgentool - @PLATFORM@ Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MT /W3 @COPTX@ @COPTI@ /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" @COPTY@ /FD /c # ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" @LIBXML2_INC@ /I "../include" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "__STDC__" /D "_MBCS" @COPTY@ /FD /c /Fdconfgentool # SUBTRACT CPP /X # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 # ADD LINK32 /out:"Release/confgentool.lib" LIB32=lib.exe # ADD BASE LIB32 # ADD LIB32 /out:"Release/confgentool.lib" !ELSEIF "$(CFG)" == "confgentool - @PLATFORM@ Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MTd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" @COPTY@ /FD /GZ /c # ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" @LIBXML2_INC@ /I "../include" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "__STDC__" /D "_MBCS" /FR @COPTY@ /FD /GZ /c /Fdconfgentool # SUBTRACT CPP /X # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 # ADD LINK32 /debug /out:"Debug/confgentool.lib" LIB32=lib.exe # ADD BASE LIB32 # ADD LIB32 /out:"Debug/confgentool.lib" !ENDIF # Begin Target # Name "confgentool - @PLATFORM@ Release" # Name "confgentool - @PLATFORM@ Debug" # Begin Group "Source Files" # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" # End Group # Begin Group "Header Files" # PROP Default_Filter "h;hpp;hxx;hm;inl" # Begin Source File SOURCE=..\keygen.h # End Source File # Begin Source File SOURCE=..\util.h # End Source File # End Group # Begin Group "Resource Files" # PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" # End Group # Begin Group "Main Dns Lib" # PROP Default_Filter "c" # Begin Source File SOURCE=..\keygen.c # End Source File # Begin Source File SOURCE=..\util.c # End Source File # Begin Source File SOURCE=.\os.c # End Source File # End Group # End Target # End Project bind9-9.11.3+dfsg/bin/confgen/win32/confgentool.dsw000066400000000000000000000010431325250447100217170ustar00rootroot00000000000000Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "confgentool"=".\confgentool.dsp" - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### bind9-9.11.3+dfsg/bin/confgen/win32/confgentool.vcxproj.filters.in000066400000000000000000000026621325250447100247010ustar00rootroot00000000000000 {4FC737F1-C7A5-4376-A066-2A32D752A2FF} cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx {93995380-89BD-4b04-88EB-625FBE52EBFB} h;hpp;hxx;hm;inl;inc;xsd {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms Header Files Header Files Header Files Source Files Source Files Source Files bind9-9.11.3+dfsg/bin/confgen/win32/confgentool.vcxproj.in000066400000000000000000000135361325250447100232340ustar00rootroot00000000000000 Debug @PLATFORM@ Release @PLATFORM@ {64964B03-4815-41F0-9057-E766A94AF197} Win32Proj confgentool StaticLibrary true MultiByte StaticLibrary false true MultiByte true .\$(Configuration)\ .\$(Configuration)\ false .\$(Configuration)\ .\$(Configuration)\ Level3 Disabled WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true .\$(Configuration)\$(TargetName).pch .\$(Configuration)\ .\$(Configuration)\ $(OutDir)$(TargetName).pdb true .\;..\..\..\;@LIBXML2_INC@..\include;..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;%(AdditionalIncludeDirectories) CompileAsC Console true Level3 MaxSpeed true @INTRINSIC@ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) OnlyExplicitInline false true .\$(Configuration)\$(TargetName).pch .\$(Configuration)\ .\$(Configuration)\ $(OutDir)$(TargetName).pdb .\;..\..\..\;@LIBXML2_INC@..\include;..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;%(AdditionalIncludeDirectories) CompileAsC Console true true true false bind9-9.11.3+dfsg/bin/confgen/win32/confgentool.vcxproj.user000066400000000000000000000002171325250447100235740ustar00rootroot00000000000000 bind9-9.11.3+dfsg/bin/confgen/win32/ddnsconfgen.dsp.in000066400000000000000000000115761325250447100223040ustar00rootroot00000000000000# Microsoft Developer Studio Project File - Name="ddnsconfgen" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "@PLATFORM@ (x86) Console Application" 0x0103 CFG=ddnsconfgen - @PLATFORM@ Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "ddnsconfgen.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "ddnsconfgen.mak" CFG="ddnsconfgen - @PLATFORM@ Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "ddnsconfgen - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE "ddnsconfgen - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "ddnsconfgen - @PLATFORM@ Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 @COPTX@ @COPTI@ /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c # ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" @LIBXML2_INC@ /I "../include" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/win32/include" /I "../../../lib/dns/include" /I "../../../lib/isccc/include" /I "../../../lib/isccfg/include" /D "WIN32" /D "NDEBUG" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console @MACHINE@ # ADD LINK32 user32.lib advapi32.lib ws2_32.lib Release/confgentool.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib ../../../lib/isccfg/win32/Release/libisccfg.lib ../../../lib/isccc/win32/Release/libisccc.lib /nologo /subsystem:console @MACHINE@ /out:"../../../Build/Release/ddns-confgen.exe" !ELSEIF "$(CFG)" == "ddnsconfgen - @PLATFORM@ Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /GZ /c # ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" @LIBXML2_INC@ /I "../include" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/win32/include" /I "../../../lib/dns/include" /I "../../../lib/isccc/include" /I "../../../lib/isccfg/include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c # SUBTRACT CPP /X @COPTY@ # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug @MACHINE@ /pdbtype:sept # ADD LINK32 user32.lib advapi32.lib ws2_32.lib Debug/confgentool.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib ../../../lib/isccfg/win32/Debug/libisccfg.lib ../../../lib/isccc/win32/Debug/libisccc.lib /nologo /subsystem:console /debug @MACHINE@ /out:"../../../Build/Debug/ddns-confgen.exe" /pdbtype:sept !ENDIF # Begin Target # Name "ddnsconfgen - @PLATFORM@ Release" # Name "ddnsconfgen - @PLATFORM@ Debug" # Begin Group "Source Files" # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" # Begin Source File SOURCE="..\ddns-confgen.c" # End Source File # End Group # Begin Group "Header Files" # PROP Default_Filter "h;hpp;hxx;hm;inl" # End Group # Begin Group "Resource Files" # PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" # End Group # End Target # End Project bind9-9.11.3+dfsg/bin/confgen/win32/ddnsconfgen.dsw000066400000000000000000000010431325250447100216720ustar00rootroot00000000000000Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "ddnsconfgen"=".\ddnsconfgen.dsp" - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### bind9-9.11.3+dfsg/bin/confgen/win32/ddnsconfgen.mak.in000066400000000000000000000222601325250447100222560ustar00rootroot00000000000000# Microsoft Developer Studio Generated NMAKE File, Based on ddnsconfgen.dsp !IF "$(CFG)" == "" CFG=ddnsconfgen - @PLATFORM@ Debug !MESSAGE No configuration specified. Defaulting to ddnsconfgen - @PLATFORM@ Debug. !ENDIF !IF "$(CFG)" != "ddnsconfgen - @PLATFORM@ Release" && "$(CFG)" != "ddnsconfgen - @PLATFORM@ Debug" !MESSAGE Invalid configuration "$(CFG)" specified. !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "ddnsconfgen.mak" CFG="ddnsconfgen - @PLATFORM@ Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "ddnsconfgen - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE "ddnsconfgen - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE !ERROR An invalid configuration is specified. !ENDIF !IF "$(OS)" == "Windows_NT" NULL= !ELSE NULL=nul !ENDIF CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "ddnsconfgen - @PLATFORM@ Release" _VC_MANIFEST_INC=0 _VC_MANIFEST_BASENAME=__VC80 !ELSE _VC_MANIFEST_INC=1 _VC_MANIFEST_BASENAME=__VC80.Debug !ENDIF #################################################### # Specifying name of temporary resource file used only in incremental builds: !if "$(_VC_MANIFEST_INC)" == "1" _VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res !else _VC_MANIFEST_AUTO_RES= !endif #################################################### # _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE: !if "$(_VC_MANIFEST_INC)" == "1" #MT_SPECIAL_RETURN=1090650113 #MT_SPECIAL_SWITCH=-notify_resource_update MT_SPECIAL_RETURN=0 MT_SPECIAL_SWITCH= _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \ if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \ rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \ link $** /out:$@ $(LFLAGS) !else _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1 !endif #################################################### # _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL: !if "$(_VC_MANIFEST_INC)" == "1" #MT_SPECIAL_RETURN=1090650113 #MT_SPECIAL_SWITCH=-notify_resource_update MT_SPECIAL_RETURN=0 MT_SPECIAL_SWITCH= _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \ if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \ rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \ link $** /out:$@ $(LFLAGS) !else _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2 !endif #################################################### # _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily: !if "$(_VC_MANIFEST_INC)" == "1" _VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \ $(_VC_MANIFEST_BASENAME).auto.rc \ $(_VC_MANIFEST_BASENAME).auto.manifest !else _VC_MANIFEST_CLEAN= !endif !IF "$(CFG)" == "ddnsconfgen - @PLATFORM@ Release" OUTDIR=.\Release INTDIR=.\Release ALL : "..\..\..\Build\Release\ddns-confgen.exe" CLEAN : -@erase "$(INTDIR)\os.obj" -@erase "$(INTDIR)\ddns-confgen.obj" -@erase "$(INTDIR)\keygen.obj" -@erase "$(INTDIR)\util.obj" -@erase "$(INTDIR)\vc60.idb" -@erase "..\..\..\Build\Release\ddns-confgen.exe" -@$(_VC_MANIFEST_CLEAN) "$(OUTDIR)" : if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" CPP_PROJ=/nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" @LIBXML2_INC@ /I "../include" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/win32/include" /I "../../../lib/dns/include" /I "../../../lib/isccc/include" /I "../../../lib/isccfg/include" /D "WIN32" /D "NDEBUG" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\ddnsconfgen.pch" @COPTY@ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c BSC32=bscmake.exe BSC32_FLAGS=/nologo /o"$(OUTDIR)\ddnsconfgen.bsc" BSC32_SBRS= \ LINK32=link.exe LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib ../../../lib/isccfg/win32/Release/libisccfg.lib ../../../lib/isccc/win32/Release/libisccc.lib /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\ddns-confgen.pdb" @MACHINE@ /out:"../../../Build/Release/ddns-confgen.exe" LINK32_OBJS= \ "$(INTDIR)\os.obj" \ "$(INTDIR)\ddns-confgen.obj" \ "$(INTDIR)\keygen.obj" \ "$(INTDIR)\util.obj" "..\..\..\Build\Release\ddns-confgen.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) $(LINK32) @<< $(LINK32_FLAGS) $(LINK32_OBJS) << $(_VC_MANIFEST_EMBED_EXE) !ELSEIF "$(CFG)" == "ddnsconfgen - @PLATFORM@ Debug" OUTDIR=.\Debug INTDIR=.\Debug # Begin Custom Macros OutDir=.\Debug # End Custom Macros ALL : "..\..\..\Build\Debug\ddns-confgen.exe" "$(OUTDIR)\ddnsconfgen.bsc" CLEAN : -@erase "$(INTDIR)\os.obj" -@erase "$(INTDIR)\os.sbr" -@erase "$(INTDIR)\ddns-confgen.obj" -@erase "$(INTDIR)\ddns-confgen.sbr" -@erase "$(INTDIR)\keygen.obj" -@erase "$(INTDIR)\keygen.sbr" -@erase "$(INTDIR)\util.obj" -@erase "$(INTDIR)\util.sbr" -@erase "$(INTDIR)\vc60.idb" -@erase "$(INTDIR)\vc60.pdb" -@erase "$(OUTDIR)\ddnsconfgen.bsc" -@erase "$(OUTDIR)\ddns-confgen.pdb" -@erase "..\..\..\Build\Debug\ddns-confgen.exe" -@erase "..\..\..\Build\Debug\ddns-confgen.ilk" -@$(_VC_MANIFEST_CLEAN) "$(OUTDIR)" : if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" CPP_PROJ=/nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" @LIBXML2_INC@ /I "../include" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/win32/include" /I "../../../lib/dns/include" /I "../../../lib/isccc/include" /I "../../../lib/isccfg/include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c BSC32=bscmake.exe BSC32_FLAGS=/nologo /o"$(OUTDIR)\ddnsconfgen.bsc" BSC32_SBRS= \ "$(INTDIR)\os.sbr" \ "$(INTDIR)\ddns-confgen.sbr" \ "$(INTDIR)\keygen.sbr" \ "$(INTDIR)\util.sbr" "$(OUTDIR)\ddnsconfgen.bsc" : "$(OUTDIR)" $(BSC32_SBRS) $(BSC32) @<< $(BSC32_FLAGS) $(BSC32_SBRS) << LINK32=link.exe LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib ../../../lib/isccfg/win32/Debug/libisccfg.lib ../../../lib/isccc/win32/Debug/libisccc.lib /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\ddns-confgen.pdb" /debug @MACHINE@ /out:"../../../Build/Debug/ddns-confgen.exe" /pdbtype:sept LINK32_OBJS= \ "$(INTDIR)\os.obj" \ "$(INTDIR)\ddns-confgen.obj" \ "$(INTDIR)\keygen.obj" \ "$(INTDIR)\util.obj" "..\..\..\Build\Debug\ddns-confgen.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) $(LINK32) @<< $(LINK32_FLAGS) $(LINK32_OBJS) << $(_VC_MANIFEST_EMBED_EXE) !ENDIF .c{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .c{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << !IF "$(NO_EXTERNAL_DEPS)" != "1" !IF EXISTS("ddnsconfgen.dep") !INCLUDE "ddnsconfgen.dep" !ELSE !MESSAGE Warning: cannot find "ddnsconfgen.dep" !ENDIF !ENDIF !IF "$(CFG)" == "ddnsconfgen - @PLATFORM@ Release" || "$(CFG)" == "ddnsconfgen - @PLATFORM@ Debug" SOURCE=.\os.c !IF "$(CFG)" == "ddnsconfgen - @PLATFORM@ Release" "$(INTDIR)\os.obj" : $(SOURCE) "$(INTDIR)" !ELSEIF "$(CFG)" == "ddnsconfgen - @PLATFORM@ Debug" "$(INTDIR)\os.obj" "$(INTDIR)\os.sbr" : $(SOURCE) "$(INTDIR)" !ENDIF SOURCE="..\ddns-confgen.c" !IF "$(CFG)" == "ddnsconfgen - @PLATFORM@ Release" "$(INTDIR)\ddns-confgen.obj" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ELSEIF "$(CFG)" == "ddnsconfgen - @PLATFORM@ Debug" "$(INTDIR)\ddns-confgen.obj" "$(INTDIR)\ddns-confgen.sbr" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ENDIF SOURCE=..\keygen.c !IF "$(CFG)" == "ddnsconfgen - @PLATFORM@ Release" "$(INTDIR)\keygen.obj" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ELSEIF "$(CFG)" == "ddnsconfgen - @PLATFORM@ Debug" "$(INTDIR)\keygen.obj" "$(INTDIR)\keygen.sbr" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ENDIF SOURCE=..\util.c !IF "$(CFG)" == "ddnsconfgen - @PLATFORM@ Release" "$(INTDIR)\util.obj" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ELSEIF "$(CFG)" == "ddnsconfgen - @PLATFORM@ Debug" "$(INTDIR)\util.obj" "$(INTDIR)\util.sbr" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ENDIF !ENDIF #################################################### # Commands to generate initial empty manifest file and the RC file # that references it, and for generating the .res file: $(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc $(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest type <<$@ #include 1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest" << KEEP $(_VC_MANIFEST_BASENAME).auto.manifest : type <<$@ << KEEP bind9-9.11.3+dfsg/bin/confgen/win32/ddnsconfgen.vcxproj.filters.in000066400000000000000000000014021325250447100246430ustar00rootroot00000000000000 {4FC737F1-C7A5-4376-A066-2A32D752A2FF} cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms Source Files bind9-9.11.3+dfsg/bin/confgen/win32/ddnsconfgen.vcxproj.in000066400000000000000000000163201325250447100232010ustar00rootroot00000000000000 Debug @PLATFORM@ Release @PLATFORM@ {1EA4FC64-F33B-4A50-970A-EA052BBE9CF1} Win32Proj ddnsconfgen Application true MultiByte Application false true MultiByte true ..\..\..\Build\$(Configuration)\ .\$(Configuration)\ ddns-confgen false ..\..\..\Build\$(Configuration)\ .\$(Configuration)\ ddns-confgen Level3 Disabled WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true .\$(Configuration)\$(ProjectName).pch .\$(Configuration)\ .\$(Configuration)\ $(OutDir)$(TargetName).pdb true .\;..\..\..\;@LIBXML2_INC@..\include;..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;..\..\..\lib\isccc\include;..\..\..\lib\isccfg\include;%(AdditionalIncludeDirectories) CompileAsC Console true ..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt) $(Configuration);..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);..\..\..\lib\isccfg\win32\$(Configuration);..\..\..\lib\isccc\win32\$(Configuration);%(AdditionalLibraryDirectories) confgentool.lib;libisc.lib;libdns.lib;libisccfg.lib;libisccc.lib;ws2_32.lib;%(AdditionalDependencies) cd ..\..\..\Build\$(Configuration) copy /Y ddns-confgen.exe tsig-keygen.exe copy /Y ddns-confgen.ilk tsig-keygen.ilk Level3 MaxSpeed true @INTRINSIC@ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) OnlyExplicitInline false true .\$(Configuration)\$(ProjectName).pch .\$(Configuration)\ .\$(Configuration)\ $(OutDir)$(TargetName).pdb .\;..\..\..\;@LIBXML2_INC@..\include;..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;..\..\..\lib\isccc\include;..\..\..\lib\isccfg\include;%(AdditionalIncludeDirectories) CompileAsC Console false true true ..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt) Default $(Configuration);..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);..\..\..\lib\isccfg\win32\$(Configuration);..\..\..\lib\isccc\win32\$(Configuration);%(AdditionalLibraryDirectories) confgentool.lib;libisc.lib;libdns.lib;libisccfg.lib;libisccc.lib;ws2_32.lib;%(AdditionalDependencies) cd ..\..\..\Build\$(Configuration) copy /Y ddns-confgen.exe tsig-keygen.exe bind9-9.11.3+dfsg/bin/confgen/win32/ddnsconfgen.vcxproj.user000066400000000000000000000002171325250447100235470ustar00rootroot00000000000000 bind9-9.11.3+dfsg/bin/confgen/win32/os.c000066400000000000000000000011051325250447100174470ustar00rootroot00000000000000/* * Copyright (C) 2009, 2016 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* $Id: os.c,v 1.3 2009/06/11 23:47:55 tbox Exp $ */ #include #include #include #include #include #include #include #include #include int set_user(FILE *fd, const char *user) { return (0); } bind9-9.11.3+dfsg/bin/confgen/win32/rndcconfgen.dsp.in000066400000000000000000000115761325250447100223020ustar00rootroot00000000000000# Microsoft Developer Studio Project File - Name="rndcconfgen" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "@PLATFORM@ (x86) Console Application" 0x0103 CFG=rndcconfgen - @PLATFORM@ Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "rndcconfgen.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "rndcconfgen.mak" CFG="rndcconfgen - @PLATFORM@ Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "rndcconfgen - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE "rndcconfgen - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "rndcconfgen - @PLATFORM@ Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 @COPTX@ @COPTI@ /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c # ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" @LIBXML2_INC@ /I "../include" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/win32/include" /I "../../../lib/dns/include" /I "../../../lib/isccc/include" /I "../../../lib/isccfg/include" /D "WIN32" /D "NDEBUG" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console @MACHINE@ # ADD LINK32 user32.lib advapi32.lib ws2_32.lib Release/confgentool.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib ../../../lib/isccfg/win32/Release/libisccfg.lib ../../../lib/isccc/win32/Release/libisccc.lib /nologo /subsystem:console @MACHINE@ /out:"../../../Build/Release/rndc-confgen.exe" !ELSEIF "$(CFG)" == "rndcconfgen - @PLATFORM@ Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /GZ /c # ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" @LIBXML2_INC@ /I "../include" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/win32/include" /I "../../../lib/dns/include" /I "../../../lib/isccc/include" /I "../../../lib/isccfg/include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c # SUBTRACT CPP /X @COPTY@ # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug @MACHINE@ /pdbtype:sept # ADD LINK32 user32.lib advapi32.lib ws2_32.lib Debug/confgentool.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib ../../../lib/isccfg/win32/Debug/libisccfg.lib ../../../lib/isccc/win32/Debug/libisccc.lib /nologo /subsystem:console /debug @MACHINE@ /out:"../../../Build/Debug/rndc-confgen.exe" /pdbtype:sept !ENDIF # Begin Target # Name "rndcconfgen - @PLATFORM@ Release" # Name "rndcconfgen - @PLATFORM@ Debug" # Begin Group "Source Files" # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" # Begin Source File SOURCE="..\rndc-confgen.c" # End Source File # End Group # Begin Group "Header Files" # PROP Default_Filter "h;hpp;hxx;hm;inl" # End Group # Begin Group "Resource Files" # PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" # End Group # End Target # End Project bind9-9.11.3+dfsg/bin/confgen/win32/rndcconfgen.dsw000066400000000000000000000010411325250447100216660ustar00rootroot00000000000000Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "rndconfgen"=".\rndconfgen.dsp" - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### bind9-9.11.3+dfsg/bin/confgen/win32/rndcconfgen.mak.in000066400000000000000000000222071325250447100222550ustar00rootroot00000000000000# Microsoft Developer Studio Generated NMAKE File, Based on confgen.dsp !IF "$(CFG)" == "" CFG=rndcconfgen - @PLATFORM@ Debug !MESSAGE No configuration specified. Defaulting to rndcconfgen - @PLATFORM@ Debug. !ENDIF !IF "$(CFG)" != "rndcconfgen - @PLATFORM@ Release" && "$(CFG)" != "rndcconfgen - @PLATFORM@ Debug" !MESSAGE Invalid configuration "$(CFG)" specified. !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "rndcconfgen.mak" CFG="rndcconfgen - @PLATFORM@ Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "rndcconfgen - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE "rndcconfgen - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE !ERROR An invalid configuration is specified. !ENDIF !IF "$(OS)" == "Windows_NT" NULL= !ELSE NULL=nul !ENDIF CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "rndcconfgen - @PLATFORM@ Release" _VC_MANIFEST_INC=0 _VC_MANIFEST_BASENAME=__VC80 !ELSE _VC_MANIFEST_INC=1 _VC_MANIFEST_BASENAME=__VC80.Debug !ENDIF #################################################### # Specifying name of temporary resource file used only in incremental builds: !if "$(_VC_MANIFEST_INC)" == "1" _VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res !else _VC_MANIFEST_AUTO_RES= !endif #################################################### # _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE: !if "$(_VC_MANIFEST_INC)" == "1" #MT_SPECIAL_RETURN=1090650113 #MT_SPECIAL_SWITCH=-notify_resource_update MT_SPECIAL_RETURN=0 MT_SPECIAL_SWITCH= _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \ if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \ rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \ link $** /out:$@ $(LFLAGS) !else _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1 !endif #################################################### # _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL: !if "$(_VC_MANIFEST_INC)" == "1" #MT_SPECIAL_RETURN=1090650113 #MT_SPECIAL_SWITCH=-notify_resource_update MT_SPECIAL_RETURN=0 MT_SPECIAL_SWITCH= _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \ if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \ rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \ link $** /out:$@ $(LFLAGS) !else _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2 !endif #################################################### # _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily: !if "$(_VC_MANIFEST_INC)" == "1" _VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \ $(_VC_MANIFEST_BASENAME).auto.rc \ $(_VC_MANIFEST_BASENAME).auto.manifest !else _VC_MANIFEST_CLEAN= !endif !IF "$(CFG)" == "rndcconfgen - @PLATFORM@ Release" OUTDIR=.\Release INTDIR=.\Release ALL : "..\..\..\Build\Release\rndc-confgen.exe" CLEAN : -@erase "$(INTDIR)\os.obj" -@erase "$(INTDIR)\rndc-confgen.obj" -@erase "$(INTDIR)\keygen.obj" -@erase "$(INTDIR)\util.obj" -@erase "$(INTDIR)\vc60.idb" -@erase "..\..\..\Build\Release\rndc-confgen.exe" -@$(_VC_MANIFEST_CLEAN) "$(OUTDIR)" : if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" CPP_PROJ=/nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" @LIBXML2_INC@ /I "../include" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/win32/include" /I "../../../lib/dns/include" /I "../../../lib/isccc/include" /I "../../../lib/isccfg/include" /D "WIN32" /D "NDEBUG" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\confgen.pch" @COPTY@ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c BSC32=bscmake.exe BSC32_FLAGS=/nologo /o"$(OUTDIR)\confgen.bsc" BSC32_SBRS= \ LINK32=link.exe LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib ../../../lib/isccfg/win32/Release/libisccfg.lib ../../../lib/isccc/win32/Release/libisccc.lib /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\rndc-confgen.pdb" @MACHINE@ /out:"../../../Build/Release/rndc-confgen.exe" LINK32_OBJS= \ "$(INTDIR)\os.obj" \ "$(INTDIR)\rndc-confgen.obj" \ "$(INTDIR)\keygen.obj" \ "$(INTDIR)\util.obj" "..\..\..\Build\Release\rndc-confgen.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) $(LINK32) @<< $(LINK32_FLAGS) $(LINK32_OBJS) << $(_VC_MANIFEST_EMBED_EXE) !ELSEIF "$(CFG)" == "rndcconfgen - @PLATFORM@ Debug" OUTDIR=.\Debug INTDIR=.\Debug # Begin Custom Macros OutDir=.\Debug # End Custom Macros ALL : "..\..\..\Build\Debug\rndc-confgen.exe" "$(OUTDIR)\confgen.bsc" CLEAN : -@erase "$(INTDIR)\os.obj" -@erase "$(INTDIR)\os.sbr" -@erase "$(INTDIR)\rndc-confgen.obj" -@erase "$(INTDIR)\rndc-confgen.sbr" -@erase "$(INTDIR)\keygen.obj" -@erase "$(INTDIR)\keygen.sbr" -@erase "$(INTDIR)\util.obj" -@erase "$(INTDIR)\util.sbr" -@erase "$(INTDIR)\vc60.idb" -@erase "$(INTDIR)\vc60.pdb" -@erase "$(OUTDIR)\confgen.bsc" -@erase "$(OUTDIR)\rndc-confgen.pdb" -@erase "..\..\..\Build\Debug\rndc-confgen.exe" -@erase "..\..\..\Build\Debug\rndc-confgen.ilk" -@$(_VC_MANIFEST_CLEAN) "$(OUTDIR)" : if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" CPP_PROJ=/nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" @LIBXML2_INC@ /I "../include" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/win32/include" /I "../../../lib/dns/include" /I "../../../lib/isccc/include" /I "../../../lib/isccfg/include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c BSC32=bscmake.exe BSC32_FLAGS=/nologo /o"$(OUTDIR)\confgen.bsc" BSC32_SBRS= \ "$(INTDIR)\os.sbr" \ "$(INTDIR)\rndc-confgen.sbr" \ "$(INTDIR)\keygen.sbr" \ "$(INTDIR)\util.sbr" "$(OUTDIR)\confgen.bsc" : "$(OUTDIR)" $(BSC32_SBRS) $(BSC32) @<< $(BSC32_FLAGS) $(BSC32_SBRS) << LINK32=link.exe LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib ../../../lib/isccfg/win32/Debug/libisccfg.lib ../../../lib/isccc/win32/Debug/libisccc.lib /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\rndc-confgen.pdb" /debug @MACHINE@ /out:"../../../Build/Debug/rndc-confgen.exe" /pdbtype:sept LINK32_OBJS= \ "$(INTDIR)\os.obj" \ "$(INTDIR)\rndc-confgen.obj" \ "$(INTDIR)\keygen.obj" \ "$(INTDIR)\util.obj" "..\..\..\Build\Debug\rndc-confgen.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) $(LINK32) @<< $(LINK32_FLAGS) $(LINK32_OBJS) << $(_VC_MANIFEST_EMBED_EXE) !ENDIF .c{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .c{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << !IF "$(NO_EXTERNAL_DEPS)" != "1" !IF EXISTS("confgen.dep") !INCLUDE "confgen.dep" !ELSE !MESSAGE Warning: cannot find "confgen.dep" !ENDIF !ENDIF !IF "$(CFG)" == "rndcconfgen - @PLATFORM@ Release" || "$(CFG)" == "rndcconfgen - @PLATFORM@ Debug" SOURCE=.\os.c !IF "$(CFG)" == "rndcconfgen - @PLATFORM@ Release" "$(INTDIR)\os.obj" : $(SOURCE) "$(INTDIR)" !ELSEIF "$(CFG)" == "rndcconfgen - @PLATFORM@ Debug" "$(INTDIR)\os.obj" "$(INTDIR)\os.sbr" : $(SOURCE) "$(INTDIR)" !ENDIF SOURCE="..\rndc-confgen.c" !IF "$(CFG)" == "rndcconfgen - @PLATFORM@ Release" "$(INTDIR)\rndc-confgen.obj" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ELSEIF "$(CFG)" == "rndcconfgen - @PLATFORM@ Debug" "$(INTDIR)\rndc-confgen.obj" "$(INTDIR)\rndc-confgen.sbr" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ENDIF SOURCE=..\keygen.c !IF "$(CFG)" == "rndcconfgen - @PLATFORM@ Release" "$(INTDIR)\keygen.obj" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ELSEIF "$(CFG)" == "rndcconfgen - @PLATFORM@ Debug" "$(INTDIR)\keygen.obj" "$(INTDIR)\keygen.sbr" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ENDIF SOURCE=..\util.c !IF "$(CFG)" == "rndcconfgen - @PLATFORM@ Release" "$(INTDIR)\util.obj" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ELSEIF "$(CFG)" == "rndcconfgen - @PLATFORM@ Debug" "$(INTDIR)\util.obj" "$(INTDIR)\util.sbr" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ENDIF !ENDIF #################################################### # Commands to generate initial empty manifest file and the RC file # that references it, and for generating the .res file: $(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc $(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest type <<$@ #include 1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest" << KEEP $(_VC_MANIFEST_BASENAME).auto.manifest : type <<$@ << KEEP bind9-9.11.3+dfsg/bin/confgen/win32/rndcconfgen.vcxproj.filters.in000066400000000000000000000014021325250447100246410ustar00rootroot00000000000000 {4FC737F1-C7A5-4376-A066-2A32D752A2FF} cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms Source Files bind9-9.11.3+dfsg/bin/confgen/win32/rndcconfgen.vcxproj.in000066400000000000000000000155721325250447100232070ustar00rootroot00000000000000 Debug @PLATFORM@ Release @PLATFORM@ {1E2C1635-3093-4D59-80E7-4743AC10F22F} Win32Proj rndcconfgen Application true MultiByte Application false true MultiByte true ..\..\..\Build\$(Configuration)\ .\$(Configuration)\ rndc-confgen false ..\..\..\Build\$(Configuration)\ .\$(Configuration)\ rndc-confgen Level3 Disabled WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true .\$(Configuration)\$(ProjectName).pch .\$(Configuration)\ .\$(Configuration)\ $(OutDir)$(TargetName).pdb true .\;..\..\..\;@LIBXML2_INC@..\include;..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;..\..\..\lib\isccc\include;..\..\..\lib\isccfg\include;%(AdditionalIncludeDirectories) CompileAsC Console true ..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt) $(Configuration);..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);..\..\..\lib\isccfg\win32\$(Configuration);..\..\..\lib\isccc\win32\$(Configuration);%(AdditionalLibraryDirectories) confgentool.lib;libisc.lib;libdns.lib;libisccfg.lib;libisccc.lib;ws2_32.lib;%(AdditionalDependencies) Level3 MaxSpeed true @INTRINSIC@ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) OnlyExplicitInline false true .\$(Configuration)\$(ProjectName).pch .\$(Configuration)\ .\$(Configuration)\ $(OutDir)$(TargetName).pdb .\;..\..\..\;@LIBXML2_INC@..\include;..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;..\..\..\lib\isccc\include;..\..\..\lib\isccfg\include;%(AdditionalIncludeDirectories) CompileAsC Console false true true ..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt) Default $(Configuration);..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);..\..\..\lib\isccfg\win32\$(Configuration);..\..\..\lib\isccc\win32\$(Configuration);%(AdditionalLibraryDirectories) confgentool.lib;libisc.lib;libdns.lib;libisccfg.lib;libisccc.lib;ws2_32.lib;%(AdditionalDependencies) bind9-9.11.3+dfsg/bin/confgen/win32/rndcconfgen.vcxproj.user000066400000000000000000000002171325250447100235450ustar00rootroot00000000000000 bind9-9.11.3+dfsg/bin/delv/000077500000000000000000000000001325250447100152365ustar00rootroot00000000000000bind9-9.11.3+dfsg/bin/delv/Makefile.in000066400000000000000000000037451325250447100173140ustar00rootroot00000000000000# Copyright (C) 2014-2017 Internet Systems Consortium, Inc. ("ISC") # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. srcdir = @srcdir@ VPATH = @srcdir@ top_srcdir = @top_srcdir@ VERSION=@BIND9_VERSION@ @BIND9_MAKE_INCLUDES@ CINCLUDES = -I${srcdir}/include ${DNS_INCLUDES} ${ISC_INCLUDES} \ ${IRS_INCLUDES} ${ISCCFG_INCLUDES} @DST_OPENSSL_INC@ CDEFINES = @CRYPTO@ -DVERSION=\"${VERSION}\" \ -DSYSCONFDIR=\"${sysconfdir}\" CWARNINGS = ISCCFGLIBS = ../../lib/isccfg/libisccfg.@A@ DNSLIBS = ../../lib/dns/libdns.@A@ @DNS_CRYPTO_LIBS@ ISCNOSYMLIBS = ../../lib/isc/libisc-nosymtbl.@A@ ISCLIBS = ../../lib/isc/libisc.@A@ IRSLIBS = ../../lib/irs/libirs.@A@ ISCCFGDEPLIBS = ../../lib/isccfg/libisccfg.@A@ DNSDEPLIBS = ../../lib/dns/libdns.@A@ ISCDEPLIBS = ../../lib/isc/libisc.@A@ IRSDEPLIBS = ../../lib/irs/libirs.@A@ DEPLIBS = ${DNSDEPLIBS} ${IRSDEPLIBS} ${ISCCFGDEPLIBS} ${ISCDEPLIBS} LIBS = ${DNSLIBS} ${IRSLIBS} ${ISCCFGLIBS} ${ISCLIBS} @LIBS@ NOSYMLIBS = ${DNSLIBS} ${IRSLIBS} ${ISCCFGLIBS} ${ISCNOSYMLIBS} @LIBS@ SUBDIRS = TARGETS = delv@EXEEXT@ OBJS = delv.@O@ SRCS = delv.c MANPAGES = delv.1 HTMLPAGES = delv.html MANOBJS = ${MANPAGES} ${HTMLPAGES} @BIND9_MAKE_RULES@ delv@EXEEXT@: delv.@O@ ${DEPLIBS} export BASEOBJS="delv.@O@"; \ export LIBS0="${DNSLIBS}"; \ ${FINALBUILDCMD} installdirs: $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${bindir} $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${mandir}/man1 install:: delv@EXEEXT@ installdirs ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} \ delv@EXEEXT@ ${DESTDIR}${bindir} ${INSTALL_DATA} ${srcdir}/delv.1 ${DESTDIR}${mandir}/man1 uninstall:: rm -f ${DESTDIR}${mandir}/man1/delv.1 ${LIBTOOL_MODE_UNINSTALL} rm -f ${DESTDIR}${bindir}/delv@EXEEXT@ doc man:: ${MANOBJS} docclean manclean maintainer-clean:: rm -f ${MANOBJS} clean distclean maintainer-clean:: rm -f ${TARGETS} bind9-9.11.3+dfsg/bin/delv/delv.1000066400000000000000000000353361325250447100162640ustar00rootroot00000000000000.\" Copyright (C) 2014-2017 Internet Systems Consortium, Inc. ("ISC") .\" .\" This Source Code Form is subject to the terms of the Mozilla Public .\" License, v. 2.0. If a copy of the MPL was not distributed with this .\" file, You can obtain one at http://mozilla.org/MPL/2.0/. .\" .hy 0 .ad l '\" t .\" Title: delv .\" Author: .\" Generator: DocBook XSL Stylesheets v1.78.1 .\" Date: 2014-04-23 .\" Manual: BIND9 .\" Source: ISC .\" Language: English .\" .TH "DELV" "1" "2014\-04\-23" "ISC" "BIND9" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" delv \- DNS lookup and validation utility .SH "SYNOPSIS" .HP \w'\fBdelv\fR\ 'u \fBdelv\fR [@server] [[\fB\-4\fR] | [\fB\-6\fR]] [\fB\-a\ \fR\fB\fIanchor\-file\fR\fR] [\fB\-b\ \fR\fB\fIaddress\fR\fR] [\fB\-c\ \fR\fB\fIclass\fR\fR] [\fB\-d\ \fR\fB\fIlevel\fR\fR] [\fB\-i\fR] [\fB\-m\fR] [\fB\-p\ \fR\fB\fIport#\fR\fR] [\fB\-q\ \fR\fB\fIname\fR\fR] [\fB\-t\ \fR\fB\fItype\fR\fR] [\fB\-x\ \fR\fB\fIaddr\fR\fR] [name] [type] [class] [queryopt...] .HP \w'\fBdelv\fR\ 'u \fBdelv\fR [\fB\-h\fR] .HP \w'\fBdelv\fR\ 'u \fBdelv\fR [\fB\-v\fR] .HP \w'\fBdelv\fR\ 'u \fBdelv\fR [queryopt...] [query...] .SH "DESCRIPTION" .PP \fBdelv\fR is a tool for sending DNS queries and validating the results, using the same internal resolver and validator logic as \fBnamed\fR\&. .PP \fBdelv\fR will send to a specified name server all queries needed to fetch and validate the requested data; this includes the original requested query, subsequent queries to follow CNAME or DNAME chains, and queries for DNSKEY, DS and DLV records to establish a chain of trust for DNSSEC validation\&. It does not perform iterative resolution, but simulates the behavior of a name server configured for DNSSEC validating and forwarding\&. .PP By default, responses are validated using built\-in DNSSEC trust anchor for the root zone ("\&.")\&. Records returned by \fBdelv\fR are either fully validated or were not signed\&. If validation fails, an explanation of the failure is included in the output; the validation process can be traced in detail\&. Because \fBdelv\fR does not rely on an external server to carry out validation, it can be used to check the validity of DNS responses in environments where local name servers may not be trustworthy\&. .PP Unless it is told to query a specific name server, \fBdelv\fR will try each of the servers listed in /etc/resolv\&.conf\&. If no usable server addresses are found, \fBdelv\fR will send queries to the localhost addresses (127\&.0\&.0\&.1 for IPv4, ::1 for IPv6)\&. .PP When no command line arguments or options are given, \fBdelv\fR will perform an NS query for "\&." (the root zone)\&. .SH "SIMPLE USAGE" .PP A typical invocation of \fBdelv\fR looks like: .sp .if n \{\ .RS 4 .\} .nf delv @server name type .fi .if n \{\ .RE .\} .sp where: .PP \fBserver\fR .RS 4 is the name or IP address of the name server to query\&. This can be an IPv4 address in dotted\-decimal notation or an IPv6 address in colon\-delimited notation\&. When the supplied \fIserver\fR argument is a hostname, \fBdelv\fR resolves that name before querying that name server (note, however, that this initial lookup is \fInot\fR validated by DNSSEC)\&. .sp If no \fIserver\fR argument is provided, \fBdelv\fR consults /etc/resolv\&.conf; if an address is found there, it queries the name server at that address\&. If either of the \fB\-4\fR or \fB\-6\fR options are in use, then only addresses for the corresponding transport will be tried\&. If no usable addresses are found, \fBdelv\fR will send queries to the localhost addresses (127\&.0\&.0\&.1 for IPv4, ::1 for IPv6)\&. .RE .PP \fBname\fR .RS 4 is the domain name to be looked up\&. .RE .PP \fBtype\fR .RS 4 indicates what type of query is required \(em ANY, A, MX, etc\&. \fItype\fR can be any valid query type\&. If no \fItype\fR argument is supplied, \fBdelv\fR will perform a lookup for an A record\&. .RE .SH "OPTIONS" .PP \-a \fIanchor\-file\fR .RS 4 Specifies a file from which to read DNSSEC trust anchors\&. The default is /etc/bind\&.keys, which is included with BIND 9 and contains one or more trust anchors for the root zone ("\&.")\&. .sp Keys that do not match the root zone name are ignored\&. An alternate key name can be specified using the \fB+root=NAME\fR options\&. DNSSEC Lookaside Validation can also be turned on by using the \fB+dlv=NAME\fR to specify the name of a zone containing DLV records\&. .sp Note: When reading the trust anchor file, \fBdelv\fR treats \fBmanaged\-keys\fR statements and \fBtrusted\-keys\fR statements identically\&. That is, for a managed key, it is the \fIinitial\fR key that is trusted; RFC 5011 key management is not supported\&. \fBdelv\fR will not consult the managed\-keys database maintained by \fBnamed\fR\&. This means that if either of the keys in /etc/bind\&.keys is revoked and rolled over, it will be necessary to update /etc/bind\&.keys to use DNSSEC validation in \fBdelv\fR\&. .RE .PP \-b \fIaddress\fR .RS 4 Sets the source IP address of the query to \fIaddress\fR\&. This must be a valid address on one of the host\*(Aqs network interfaces or "0\&.0\&.0\&.0" or "::"\&. An optional source port may be specified by appending "#" .RE .PP \-c \fIclass\fR .RS 4 Sets the query class for the requested data\&. Currently, only class "IN" is supported in \fBdelv\fR and any other value is ignored\&. .RE .PP \-d \fIlevel\fR .RS 4 Set the systemwide debug level to \fBlevel\fR\&. The allowed range is from 0 to 99\&. The default is 0 (no debugging)\&. Debugging traces from \fBdelv\fR become more verbose as the debug level increases\&. See the \fB+mtrace\fR, \fB+rtrace\fR, and \fB+vtrace\fR options below for additional debugging details\&. .RE .PP \-h .RS 4 Display the \fBdelv\fR help usage output and exit\&. .RE .PP \-i .RS 4 Insecure mode\&. This disables internal DNSSEC validation\&. (Note, however, this does not set the CD bit on upstream queries\&. If the server being queried is performing DNSSEC validation, then it will not return invalid data; this can cause \fBdelv\fR to time out\&. When it is necessary to examine invalid data to debug a DNSSEC problem, use \fBdig +cd\fR\&.) .RE .PP \-m .RS 4 Enables memory usage debugging\&. .RE .PP \-p \fIport#\fR .RS 4 Specifies a destination port to use for queries instead of the standard DNS port number 53\&. This option would be used with a name server that has been configured to listen for queries on a non\-standard port number\&. .RE .PP \-q \fIname\fR .RS 4 Sets the query name to \fIname\fR\&. While the query name can be specified without using the \fB\-q\fR, it is sometimes necessary to disambiguate names from types or classes (for example, when looking up the name "ns", which could be misinterpreted as the type NS, or "ch", which could be misinterpreted as class CH)\&. .RE .PP \-t \fItype\fR .RS 4 Sets the query type to \fItype\fR, which can be any valid query type supported in BIND 9 except for zone transfer types AXFR and IXFR\&. As with \fB\-q\fR, this is useful to distinguish query name type or class when they are ambiguous\&. it is sometimes necessary to disambiguate names from types\&. .sp The default query type is "A", unless the \fB\-x\fR option is supplied to indicate a reverse lookup, in which case it is "PTR"\&. .RE .PP \-v .RS 4 Print the \fBdelv\fR version and exit\&. .RE .PP \-x \fIaddr\fR .RS 4 Performs a reverse lookup, mapping an addresses to a name\&. \fIaddr\fR is an IPv4 address in dotted\-decimal notation, or a colon\-delimited IPv6 address\&. When \fB\-x\fR is used, there is no need to provide the \fIname\fR or \fItype\fR arguments\&. \fBdelv\fR automatically performs a lookup for a name like 11\&.12\&.13\&.10\&.in\-addr\&.arpa and sets the query type to PTR\&. IPv6 addresses are looked up using nibble format under the IP6\&.ARPA domain\&. .RE .PP \-4 .RS 4 Forces \fBdelv\fR to only use IPv4\&. .RE .PP \-6 .RS 4 Forces \fBdelv\fR to only use IPv6\&. .RE .SH "QUERY OPTIONS" .PP \fBdelv\fR provides a number of query options which affect the way results are displayed, and in some cases the way lookups are performed\&. .PP Each query option is identified by a keyword preceded by a plus sign (+)\&. Some keywords set or reset an option\&. These may be preceded by the string no to negate the meaning of that keyword\&. Other keywords assign values to options like the timeout interval\&. They have the form \fB+keyword=value\fR\&. The query options are: .PP \fB+[no]cdflag\fR .RS 4 Controls whether to set the CD (checking disabled) bit in queries sent by \fBdelv\fR\&. This may be useful when troubleshooting DNSSEC problems from behind a validating resolver\&. A validating resolver will block invalid responses, making it difficult to retrieve them for analysis\&. Setting the CD flag on queries will cause the resolver to return invalid responses, which \fBdelv\fR can then validate internally and report the errors in detail\&. .RE .PP \fB+[no]class\fR .RS 4 Controls whether to display the CLASS when printing a record\&. The default is to display the CLASS\&. .RE .PP \fB+[no]ttl\fR .RS 4 Controls whether to display the TTL when printing a record\&. The default is to display the TTL\&. .RE .PP \fB+[no]rtrace\fR .RS 4 Toggle resolver fetch logging\&. This reports the name and type of each query sent by \fBdelv\fR in the process of carrying out the resolution and validation process: this includes including the original query and all subsequent queries to follow CNAMEs and to establish a chain of trust for DNSSEC validation\&. .sp This is equivalent to setting the debug level to 1 in the "resolver" logging category\&. Setting the systemwide debug level to 1 using the \fB\-d\fR option will product the same output (but will affect other logging categories as well)\&. .RE .PP \fB+[no]mtrace\fR .RS 4 Toggle message logging\&. This produces a detailed dump of the responses received by \fBdelv\fR in the process of carrying out the resolution and validation process\&. .sp This is equivalent to setting the debug level to 10 for the "packets" module of the "resolver" logging category\&. Setting the systemwide debug level to 10 using the \fB\-d\fR option will produce the same output (but will affect other logging categories as well)\&. .RE .PP \fB+[no]vtrace\fR .RS 4 Toggle validation logging\&. This shows the internal process of the validator as it determines whether an answer is validly signed, unsigned, or invalid\&. .sp This is equivalent to setting the debug level to 3 for the "validator" module of the "dnssec" logging category\&. Setting the systemwide debug level to 3 using the \fB\-d\fR option will produce the same output (but will affect other logging categories as well)\&. .RE .PP \fB+[no]short\fR .RS 4 Provide a terse answer\&. The default is to print the answer in a verbose form\&. .RE .PP \fB+[no]comments\fR .RS 4 Toggle the display of comment lines in the output\&. The default is to print comments\&. .RE .PP \fB+[no]rrcomments\fR .RS 4 Toggle the display of per\-record comments in the output (for example, human\-readable key information about DNSKEY records)\&. The default is to print per\-record comments\&. .RE .PP \fB+[no]crypto\fR .RS 4 Toggle the display of cryptographic fields in DNSSEC records\&. The contents of these field are unnecessary to debug most DNSSEC validation failures and removing them makes it easier to see the common failures\&. The default is to display the fields\&. When omitted they are replaced by the string "[omitted]" or in the DNSKEY case the key id is displayed as the replacement, e\&.g\&. "[ key id = value ]"\&. .RE .PP \fB+[no]trust\fR .RS 4 Controls whether to display the trust level when printing a record\&. The default is to display the trust level\&. .RE .PP \fB+[no]split[=W]\fR .RS 4 Split long hex\- or base64\-formatted fields in resource records into chunks of \fIW\fR characters (where \fIW\fR is rounded up to the nearest multiple of 4)\&. \fI+nosplit\fR or \fI+split=0\fR causes fields not to be split at all\&. The default is 56 characters, or 44 characters when multiline mode is active\&. .RE .PP \fB+[no]all\fR .RS 4 Set or clear the display options \fB+[no]comments\fR, \fB+[no]rrcomments\fR, and \fB+[no]trust\fR as a group\&. .RE .PP \fB+[no]multiline\fR .RS 4 Print long records (such as RRSIG, DNSKEY, and SOA records) in a verbose multi\-line format with human\-readable comments\&. The default is to print each record on a single line, to facilitate machine parsing of the \fBdelv\fR output\&. .RE .PP \fB+[no]dnssec\fR .RS 4 Indicates whether to display RRSIG records in the \fBdelv\fR output\&. The default is to do so\&. Note that (unlike in \fBdig\fR) this does \fInot\fR control whether to request DNSSEC records or whether to validate them\&. DNSSEC records are always requested, and validation will always occur unless suppressed by the use of \fB\-i\fR or \fB+noroot\fR and \fB+nodlv\fR\&. .RE .PP \fB+[no]root[=ROOT]\fR .RS 4 Indicates whether to perform conventional (non\-lookaside) DNSSEC validation, and if so, specifies the name of a trust anchor\&. The default is to validate using a trust anchor of "\&." (the root zone), for which there is a built\-in key\&. If specifying a different trust anchor, then \fB\-a\fR must be used to specify a file containing the key\&. .RE .PP \fB+[no]dlv[=DLV]\fR .RS 4 Indicates whether to perform DNSSEC lookaside validation, and if so, specifies the name of the DLV trust anchor\&. The \fB\-a\fR option must also be used to specify a file containing the DLV key\&. .RE .PP \fB+[no]tcp\fR .RS 4 Controls whether to use TCP when sending queries\&. The default is to use UDP unless a truncated response has been received\&. .RE .PP \fB+[no]unknownformat\fR .RS 4 Print all RDATA in unknown RR type presentation format (RFC 3597)\&. The default is to print RDATA for known types in the type\*(Aqs presentation format\&. .RE .SH "FILES" .PP /etc/bind\&.keys .PP /etc/resolv\&.conf .SH "SEE ALSO" .PP \fBdig\fR(1), \fBnamed\fR(8), RFC4034, RFC4035, RFC4431, RFC5074, RFC5155\&. .SH "AUTHOR" .PP \fBInternet Systems Consortium, Inc\&.\fR .SH "COPYRIGHT" .br Copyright \(co 2014-2017 Internet Systems Consortium, Inc. ("ISC") .br bind9-9.11.3+dfsg/bin/delv/delv.c000066400000000000000000001241321325250447100163370ustar00rootroot00000000000000/* * Copyright (C) 2014-2017 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include #include #ifndef WIN32 #include #include #include #include #include #include #endif #include #include #include #include #include #include #include #include #include #include #ifdef WIN32 #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define CHECK(r) \ do { \ result = (r); \ if (result != ISC_R_SUCCESS) \ goto cleanup; \ } while (0) #define MAXNAME (DNS_NAME_MAXTEXT+1) /* Variables used internally by delv. */ char *progname; static isc_mem_t *mctx = NULL; static isc_log_t *lctx = NULL; /* Configurables */ static char *server = NULL; static const char *port = "53"; static isc_sockaddr_t *srcaddr4 = NULL, *srcaddr6 = NULL; static isc_sockaddr_t a4, a6; static char *curqname = NULL, *qname = NULL; static isc_boolean_t classset = ISC_FALSE; static dns_rdatatype_t qtype = dns_rdatatype_none; static isc_boolean_t typeset = ISC_FALSE; static unsigned int styleflags = 0; static isc_uint32_t splitwidth = 0xffffffff; static isc_boolean_t showcomments = ISC_TRUE, showdnssec = ISC_TRUE, showtrust = ISC_TRUE, rrcomments = ISC_TRUE, noclass = ISC_FALSE, nocrypto = ISC_FALSE, nottl = ISC_FALSE, multiline = ISC_FALSE, short_form = ISC_FALSE, print_unknown_format = ISC_FALSE; static isc_boolean_t resolve_trace = ISC_FALSE, validator_trace = ISC_FALSE, message_trace = ISC_FALSE; static isc_boolean_t use_ipv4 = ISC_TRUE, use_ipv6 = ISC_TRUE; static isc_boolean_t cdflag = ISC_FALSE, no_sigs = ISC_FALSE, root_validation = ISC_TRUE, dlv_validation = ISC_TRUE; static isc_boolean_t use_tcp = ISC_FALSE; static char *anchorfile = NULL; static char *trust_anchor = NULL; static char *dlv_anchor = NULL; static int trusted_keys = 0; static dns_fixedname_t afn, dfn; static dns_name_t *anchor_name = NULL, *dlv_name = NULL; /* Default bind.keys contents */ static char anchortext[] = MANAGED_KEYS; /* * Static function prototypes */ static isc_result_t get_reverse(char *reverse, size_t len, char *value, isc_boolean_t strict); static isc_result_t parse_uint(isc_uint32_t *uip, const char *value, isc_uint32_t max, const char *desc); static void usage(void) { fputs( "Usage: delv [@server] {q-opt} {d-opt} [domain] [q-type] [q-class]\n" "Where: domain is in the Domain Name System\n" " q-class is one of (in,hs,ch,...) [default: in]\n" " q-type is one of (a,any,mx,ns,soa,hinfo,axfr,txt,...) [default:a]\n" " q-opt is one of:\n" " -x dot-notation (shortcut for reverse lookups)\n" " -d level (set debugging level)\n" " -a anchor-file (specify root and dlv trust anchors)\n" " -b address[#port] (bind to source address/port)\n" " -p port (specify port number)\n" " -q name (specify query name)\n" " -t type (specify query type)\n" " -c class (option included for compatibility;\n" " only IN is supported)\n" " -4 (use IPv4 query transport only)\n" " -6 (use IPv6 query transport only)\n" " -i (disable DNSSEC validation)\n" " -m (enable memory usage debugging)\n" " d-opt is of the form +keyword[=value], where keyword is:\n" " +[no]all (Set or clear all display flags)\n" " +[no]class (Control display of class)\n" " +[no]crypto (Control display of cryptographic\n" " fields in records)\n" " +[no]multiline (Print records in an expanded format)\n" " +[no]comments (Control display of comment lines)\n" " +[no]rrcomments (Control display of per-record " "comments)\n" " +[no]unknownformat (Print RDATA in RFC 3597 \"unknown\" format)\n" " +[no]short (Short form answer)\n" " +[no]split=## (Split hex/base64 fields into chunks)\n" " +[no]tcp (TCP mode)\n" " +[no]ttl (Control display of ttls in records)\n" " +[no]trust (Control display of trust level)\n" " +[no]rtrace (Trace resolver fetches)\n" " +[no]mtrace (Trace messages received)\n" " +[no]vtrace (Trace validation process)\n" " +[no]dlv (DNSSEC lookaside validation anchor)\n" " +[no]root (DNSSEC validation trust anchor)\n" " +[no]dnssec (Display DNSSEC records)\n" " -h (print help and exit)\n" " -v (print version and exit)\n", stderr); exit(1); } ISC_PLATFORM_NORETURN_PRE static void fatal(const char *format, ...) ISC_FORMAT_PRINTF(1, 2) ISC_PLATFORM_NORETURN_POST; static void fatal(const char *format, ...) { va_list args; fflush(stdout); fprintf(stderr, "%s: ", progname); va_start(args, format); vfprintf(stderr, format, args); va_end(args); fprintf(stderr, "\n"); exit(1); } static void warn(const char *format, ...) ISC_FORMAT_PRINTF(1, 2); static void warn(const char *format, ...) { va_list args; fflush(stdout); fprintf(stderr, "%s: warning: ", progname); va_start(args, format); vfprintf(stderr, format, args); va_end(args); fprintf(stderr, "\n"); } static isc_logcategory_t categories[] = { { "delv", 0 }, { NULL, 0 } }; #define LOGCATEGORY_DEFAULT (&categories[0]) #define LOGMODULE_DEFAULT (&modules[0]) static isc_logmodule_t modules[] = { { "delv", 0 }, { NULL, 0 } }; static void delv_log(int level, const char *fmt, ...) ISC_FORMAT_PRINTF(2, 3); static void delv_log(int level, const char *fmt, ...) { va_list ap; char msgbuf[2048]; if (! isc_log_wouldlog(lctx, level)) return; va_start(ap, fmt); vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap); isc_log_write(lctx, LOGCATEGORY_DEFAULT, LOGMODULE_DEFAULT, level, "%s", msgbuf); va_end(ap); } static int loglevel = 0; static void setup_logging(FILE *errout) { isc_result_t result; isc_logdestination_t destination; isc_logconfig_t *logconfig = NULL; result = isc_log_create(mctx, &lctx, &logconfig); if (result != ISC_R_SUCCESS) fatal("Couldn't set up logging"); isc_log_registercategories(lctx, categories); isc_log_registermodules(lctx, modules); isc_log_setcontext(lctx); dns_log_init(lctx); dns_log_setcontext(lctx); cfg_log_init(lctx); destination.file.stream = errout; destination.file.name = NULL; destination.file.versions = ISC_LOG_ROLLNEVER; destination.file.maximum_size = 0; result = isc_log_createchannel(logconfig, "stderr", ISC_LOG_TOFILEDESC, ISC_LOG_DYNAMIC, &destination, ISC_LOG_PRINTPREFIX); if (result != ISC_R_SUCCESS) fatal("Couldn't set up log channel 'stderr'"); isc_log_setdebuglevel(lctx, loglevel); result = isc_log_settag(logconfig, ";; "); if (result != ISC_R_SUCCESS) fatal("Couldn't set log tag"); result = isc_log_usechannel(logconfig, "stderr", ISC_LOGCATEGORY_DEFAULT, NULL); if (result != ISC_R_SUCCESS) fatal("Couldn't attach to log channel 'stderr'"); if (resolve_trace && loglevel < 1) { result = isc_log_createchannel(logconfig, "resolver", ISC_LOG_TOFILEDESC, ISC_LOG_DEBUG(1), &destination, ISC_LOG_PRINTPREFIX); if (result != ISC_R_SUCCESS) fatal("Couldn't set up log channel 'resolver'"); result = isc_log_usechannel(logconfig, "resolver", DNS_LOGCATEGORY_RESOLVER, DNS_LOGMODULE_RESOLVER); if (result != ISC_R_SUCCESS) fatal("Couldn't attach to log channel 'resolver'"); } if (validator_trace && loglevel < 3) { result = isc_log_createchannel(logconfig, "validator", ISC_LOG_TOFILEDESC, ISC_LOG_DEBUG(3), &destination, ISC_LOG_PRINTPREFIX); if (result != ISC_R_SUCCESS) fatal("Couldn't set up log channel 'validator'"); result = isc_log_usechannel(logconfig, "validator", DNS_LOGCATEGORY_DNSSEC, DNS_LOGMODULE_VALIDATOR); if (result != ISC_R_SUCCESS) fatal("Couldn't attach to log channel 'validator'"); } if (message_trace && loglevel < 10) { result = isc_log_createchannel(logconfig, "messages", ISC_LOG_TOFILEDESC, ISC_LOG_DEBUG(10), &destination, ISC_LOG_PRINTPREFIX); if (result != ISC_R_SUCCESS) fatal("Couldn't set up log channel 'messages'"); result = isc_log_usechannel(logconfig, "messages", DNS_LOGCATEGORY_RESOLVER, DNS_LOGMODULE_PACKETS); if (result != ISC_R_SUCCESS) fatal("Couldn't attach to log channel 'messagse'"); } } static void print_status(dns_rdataset_t *rdataset) { const char *astr = "", *tstr = ""; REQUIRE(rdataset != NULL); if (!showtrust || !dns_rdataset_isassociated(rdataset)) return; if ((rdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0) astr = "negative response, "; switch (rdataset->trust) { case dns_trust_none: tstr = "untrusted"; break; case dns_trust_pending_additional: tstr = "signed additional data, pending validation"; break; case dns_trust_pending_answer: tstr = "signed answer, pending validation"; break; case dns_trust_additional: tstr = "unsigned additional data"; break; case dns_trust_glue: tstr = "glue data"; break; case dns_trust_answer: if (root_validation || dlv_validation) tstr = "unsigned answer"; else tstr = "answer not validated"; break; case dns_trust_authauthority: tstr = "authority data"; break; case dns_trust_authanswer: tstr = "authoritative"; break; case dns_trust_secure: tstr = "fully validated"; break; case dns_trust_ultimate: tstr = "ultimate trust"; break; } printf("; %s%s\n", astr, tstr); } static isc_result_t printdata(dns_rdataset_t *rdataset, dns_name_t *owner, dns_master_style_t *style) { isc_result_t result = ISC_R_SUCCESS; static dns_trust_t trust; static isc_boolean_t first = ISC_TRUE; isc_buffer_t target; isc_region_t r; char *t = NULL; int len = 2048; if (!dns_rdataset_isassociated(rdataset)) { char namebuf[DNS_NAME_FORMATSIZE]; dns_name_format(owner, namebuf, sizeof(namebuf)); delv_log(ISC_LOG_DEBUG(4), "WARN: empty rdataset %s", namebuf); return (ISC_R_SUCCESS); } if (!showdnssec && rdataset->type == dns_rdatatype_rrsig) return (ISC_R_SUCCESS); if (first || rdataset->trust != trust) { if (!first && showtrust && !short_form) putchar('\n'); print_status(rdataset); trust = rdataset->trust; first = ISC_FALSE; } do { t = isc_mem_get(mctx, len); if (t == NULL) return (ISC_R_NOMEMORY); isc_buffer_init(&target, t, len); if (short_form) { dns_rdata_t rdata = DNS_RDATA_INIT; for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS; result = dns_rdataset_next(rdataset)) { if ((rdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0) continue; dns_rdataset_current(rdataset, &rdata); result = dns_rdata_tofmttext(&rdata, dns_rootname, styleflags, 0, splitwidth, " ", &target); if (result != ISC_R_SUCCESS) break; if (isc_buffer_availablelength(&target) < 1) { result = ISC_R_NOSPACE; break; } isc_buffer_putstr(&target, "\n"); dns_rdata_reset(&rdata); } } else { if ((rdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0) isc_buffer_putstr(&target, "; "); result = dns_master_rdatasettotext(owner, rdataset, style, &target); } if (result == ISC_R_NOSPACE) { isc_mem_put(mctx, t, len); len += 1024; } else if (result == ISC_R_NOMORE) result = ISC_R_SUCCESS; else CHECK(result); } while (result == ISC_R_NOSPACE); isc_buffer_usedregion(&target, &r); printf("%.*s", (int)r.length, (char *)r.base); cleanup: if (t != NULL) isc_mem_put(mctx, t, len); return (ISC_R_SUCCESS); } static isc_result_t setup_style(dns_master_style_t **stylep) { isc_result_t result; dns_master_style_t *style = NULL; REQUIRE(stylep != NULL || *stylep == NULL); styleflags |= DNS_STYLEFLAG_REL_OWNER; if (showcomments) styleflags |= DNS_STYLEFLAG_COMMENT; if (print_unknown_format) styleflags |= DNS_STYLEFLAG_UNKNOWNFORMAT; if (rrcomments) styleflags |= DNS_STYLEFLAG_RRCOMMENT; if (nottl) styleflags |= DNS_STYLEFLAG_NO_TTL; if (noclass) styleflags |= DNS_STYLEFLAG_NO_CLASS; if (nocrypto) styleflags |= DNS_STYLEFLAG_NOCRYPTO; if (multiline) { styleflags |= DNS_STYLEFLAG_MULTILINE; styleflags |= DNS_STYLEFLAG_COMMENT; } if (multiline || (nottl && noclass)) result = dns_master_stylecreate2(&style, styleflags, 24, 24, 24, 32, 80, 8, splitwidth, mctx); else if (nottl || noclass) result = dns_master_stylecreate2(&style, styleflags, 24, 24, 32, 40, 80, 8, splitwidth, mctx); else result = dns_master_stylecreate2(&style, styleflags, 24, 32, 40, 48, 80, 8, splitwidth, mctx); if (result == ISC_R_SUCCESS) *stylep = style; return (result); } static isc_result_t convert_name(dns_fixedname_t *fn, dns_name_t **name, const char *text) { isc_result_t result; isc_buffer_t b; dns_name_t *n; unsigned int len; REQUIRE(fn != NULL && name != NULL && text != NULL); len = strlen(text); isc_buffer_constinit(&b, text, len); isc_buffer_add(&b, len); dns_fixedname_init(fn); n = dns_fixedname_name(fn); result = dns_name_fromtext(n, &b, dns_rootname, 0, NULL); if (result != ISC_R_SUCCESS) { delv_log(ISC_LOG_ERROR, "failed to convert QNAME %s: %s", text, isc_result_totext(result)); return (result); } *name = n; return (ISC_R_SUCCESS); } static isc_result_t key_fromconfig(const cfg_obj_t *key, dns_client_t *client) { dns_rdata_dnskey_t keystruct; isc_uint32_t flags, proto, alg; const char *keystr, *keynamestr; unsigned char keydata[4096]; isc_buffer_t keydatabuf; unsigned char rrdata[4096]; isc_buffer_t rrdatabuf; isc_region_t r; dns_fixedname_t fkeyname; dns_name_t *keyname; isc_result_t result; isc_boolean_t match_root = ISC_FALSE, match_dlv = ISC_FALSE; keynamestr = cfg_obj_asstring(cfg_tuple_get(key, "name")); CHECK(convert_name(&fkeyname, &keyname, keynamestr)); if (!root_validation && !dlv_validation) return (ISC_R_SUCCESS); if (anchor_name) match_root = dns_name_equal(keyname, anchor_name); if (dlv_name) match_dlv = dns_name_equal(keyname, dlv_name); if (!match_root && !match_dlv) return (ISC_R_SUCCESS); if ((!root_validation && match_root) || (!dlv_validation && match_dlv)) return (ISC_R_SUCCESS); if (match_root) delv_log(ISC_LOG_DEBUG(3), "adding trust anchor %s", trust_anchor); if (match_dlv) delv_log(ISC_LOG_DEBUG(3), "adding DLV trust anchor %s", dlv_anchor); flags = cfg_obj_asuint32(cfg_tuple_get(key, "flags")); proto = cfg_obj_asuint32(cfg_tuple_get(key, "protocol")); alg = cfg_obj_asuint32(cfg_tuple_get(key, "algorithm")); keystruct.common.rdclass = dns_rdataclass_in; keystruct.common.rdtype = dns_rdatatype_dnskey; /* * The key data in keystruct is not dynamically allocated. */ keystruct.mctx = NULL; ISC_LINK_INIT(&keystruct.common, link); if (flags > 0xffff) CHECK(ISC_R_RANGE); if (proto > 0xff) CHECK(ISC_R_RANGE); if (alg > 0xff) CHECK(ISC_R_RANGE); keystruct.flags = (isc_uint16_t)flags; keystruct.protocol = (isc_uint8_t)proto; keystruct.algorithm = (isc_uint8_t)alg; isc_buffer_init(&keydatabuf, keydata, sizeof(keydata)); isc_buffer_init(&rrdatabuf, rrdata, sizeof(rrdata)); keystr = cfg_obj_asstring(cfg_tuple_get(key, "key")); CHECK(isc_base64_decodestring(keystr, &keydatabuf)); isc_buffer_usedregion(&keydatabuf, &r); keystruct.datalen = r.length; keystruct.data = r.base; CHECK(dns_rdata_fromstruct(NULL, keystruct.common.rdclass, keystruct.common.rdtype, &keystruct, &rrdatabuf)); CHECK(dns_client_addtrustedkey(client, dns_rdataclass_in, keyname, &rrdatabuf)); trusted_keys++; cleanup: if (result == DST_R_NOCRYPTO) cfg_obj_log(key, lctx, ISC_LOG_ERROR, "no crypto support"); else if (result == DST_R_UNSUPPORTEDALG) { cfg_obj_log(key, lctx, ISC_LOG_WARNING, "skipping trusted key '%s': %s", keynamestr, isc_result_totext(result)); result = ISC_R_SUCCESS; } else if (result != ISC_R_SUCCESS) { cfg_obj_log(key, lctx, ISC_LOG_ERROR, "failed to add trusted key '%s': %s", keynamestr, isc_result_totext(result)); result = ISC_R_FAILURE; } return (result); } static isc_result_t load_keys(const cfg_obj_t *keys, dns_client_t *client) { const cfg_listelt_t *elt, *elt2; const cfg_obj_t *key, *keylist; isc_result_t result = ISC_R_SUCCESS; for (elt = cfg_list_first(keys); elt != NULL; elt = cfg_list_next(elt)) { keylist = cfg_listelt_value(elt); for (elt2 = cfg_list_first(keylist); elt2 != NULL; elt2 = cfg_list_next(elt2)) { key = cfg_listelt_value(elt2); CHECK(key_fromconfig(key, client)); } } cleanup: if (result == DST_R_NOCRYPTO) result = ISC_R_SUCCESS; return (result); } static isc_result_t setup_dnsseckeys(dns_client_t *client) { isc_result_t result; cfg_parser_t *parser = NULL; const cfg_obj_t *keys = NULL; const cfg_obj_t *managed_keys = NULL; cfg_obj_t *bindkeys = NULL; const char *filename = anchorfile; if (!root_validation && !dlv_validation) return (ISC_R_SUCCESS); if (filename == NULL) { #ifndef WIN32 filename = SYSCONFDIR "/bind.keys"; #else static char buf[MAX_PATH]; strlcpy(buf, isc_ntpaths_get(SYS_CONF_DIR), sizeof(buf)); strlcat(buf, "\\bind.keys", sizeof(buf)); filename = buf; #endif } if (trust_anchor == NULL) { trust_anchor = isc_mem_strdup(mctx, "."); if (trust_anchor == NULL) fatal("out of memory"); } if (trust_anchor != NULL) CHECK(convert_name(&afn, &anchor_name, trust_anchor)); if (dlv_anchor != NULL) CHECK(convert_name(&dfn, &dlv_name, dlv_anchor)); CHECK(cfg_parser_create(mctx, dns_lctx, &parser)); if (access(filename, R_OK) != 0) { if (anchorfile != NULL) fatal("Unable to read key file '%s'", anchorfile); } else { result = cfg_parse_file(parser, filename, &cfg_type_bindkeys, &bindkeys); if (result != ISC_R_SUCCESS) if (anchorfile != NULL) fatal("Unable to load keys from '%s'", anchorfile); } if (bindkeys == NULL) { isc_buffer_t b; isc_buffer_init(&b, anchortext, sizeof(anchortext) - 1); isc_buffer_add(&b, sizeof(anchortext) - 1); result = cfg_parse_buffer(parser, &b, &cfg_type_bindkeys, &bindkeys); if (result != ISC_R_SUCCESS) fatal("Unable to parse built-in keys"); } INSIST(bindkeys != NULL); cfg_map_get(bindkeys, "trusted-keys", &keys); cfg_map_get(bindkeys, "managed-keys", &managed_keys); if (keys != NULL) CHECK(load_keys(keys, client)); if (managed_keys != NULL) CHECK(load_keys(managed_keys, client)); result = ISC_R_SUCCESS; if (trusted_keys == 0) fatal("No trusted keys were loaded"); if (dlv_validation) dns_client_setdlv(client, dns_rdataclass_in, dlv_anchor); cleanup: if (result != ISC_R_SUCCESS) delv_log(ISC_LOG_ERROR, "setup_dnsseckeys: %s", isc_result_totext(result)); return (result); } static isc_result_t addserver(dns_client_t *client) { struct addrinfo hints, *res, *cur; int gaierror; struct in_addr in4; struct in6_addr in6; isc_sockaddr_t *sa; isc_sockaddrlist_t servers; isc_uint32_t destport; isc_result_t result; dns_name_t *name = NULL; result = parse_uint(&destport, port, 0xffff, "port"); if (result != ISC_R_SUCCESS) fatal("Couldn't parse port number"); ISC_LIST_INIT(servers); if (inet_pton(AF_INET, server, &in4) == 1) { if (!use_ipv4) { fatal("Use of IPv4 disabled by -6"); } sa = isc_mem_get(mctx, sizeof(*sa)); if (sa == NULL) return (ISC_R_NOMEMORY); ISC_LINK_INIT(sa, link); isc_sockaddr_fromin(sa, &in4, destport); ISC_LIST_APPEND(servers, sa, link); } else if (inet_pton(AF_INET6, server, &in6) == 1) { if (!use_ipv6) { fatal("Use of IPv6 disabled by -4"); } sa = isc_mem_get(mctx, sizeof(*sa)); if (sa == NULL) return (ISC_R_NOMEMORY); ISC_LINK_INIT(sa, link); isc_sockaddr_fromin6(sa, &in6, destport); ISC_LIST_APPEND(servers, sa, link); } else { memset(&hints, 0, sizeof(hints)); if (!use_ipv6) hints.ai_family = AF_INET; else if (!use_ipv4) hints.ai_family = AF_INET6; else hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_DGRAM; hints.ai_protocol = IPPROTO_UDP; gaierror = getaddrinfo(server, port, &hints, &res); if (gaierror != 0) { delv_log(ISC_LOG_ERROR, "getaddrinfo failed: %s", gai_strerror(gaierror)); return (ISC_R_FAILURE); } result = ISC_R_SUCCESS; for (cur = res; cur != NULL; cur = cur->ai_next) { if (cur->ai_family != AF_INET && cur->ai_family != AF_INET6) continue; sa = isc_mem_get(mctx, sizeof(*sa)); if (sa == NULL) { result = ISC_R_NOMEMORY; break; } memset(sa, 0, sizeof(*sa)); ISC_LINK_INIT(sa, link); memmove(&sa->type, cur->ai_addr, cur->ai_addrlen); sa->length = (unsigned int)cur->ai_addrlen; ISC_LIST_APPEND(servers, sa, link); } freeaddrinfo(res); CHECK(result); } CHECK(dns_client_setservers(client, dns_rdataclass_in, name, &servers)); cleanup: while (!ISC_LIST_EMPTY(servers)) { sa = ISC_LIST_HEAD(servers); ISC_LIST_UNLINK(servers, sa, link); isc_mem_put(mctx, sa, sizeof(*sa)); } if (result != ISC_R_SUCCESS) delv_log(ISC_LOG_ERROR, "addserver: %s", isc_result_totext(result)); return (result); } static isc_result_t findserver(dns_client_t *client) { isc_result_t result; irs_resconf_t *resconf = NULL; isc_sockaddrlist_t *nameservers; isc_sockaddr_t *sa, *next; isc_uint32_t destport; result = parse_uint(&destport, port, 0xffff, "port"); if (result != ISC_R_SUCCESS) fatal("Couldn't parse port number"); result = irs_resconf_load(mctx, "/etc/resolv.conf", &resconf); if (result != ISC_R_SUCCESS && result != ISC_R_FILENOTFOUND) { delv_log(ISC_LOG_ERROR, "irs_resconf_load: %s", isc_result_totext(result)); goto cleanup; } /* Get nameservers from resolv.conf */ nameservers = irs_resconf_getnameservers(resconf); for (sa = ISC_LIST_HEAD(*nameservers); sa != NULL; sa = next) { next = ISC_LIST_NEXT(sa, link); /* Set destination port */ if (sa->type.sa.sa_family == AF_INET && use_ipv4) { sa->type.sin.sin_port = htons(destport); continue; } if (sa->type.sa.sa_family == AF_INET6 && use_ipv6) { sa->type.sin6.sin6_port = htons(destport); continue; } /* Incompatible protocol family */ ISC_LIST_UNLINK(*nameservers, sa, link); isc_mem_put(mctx, sa, sizeof(*sa)); } /* None found, use localhost */ if (ISC_LIST_EMPTY(*nameservers)) { if (use_ipv4) { struct in_addr localhost; localhost.s_addr = htonl(INADDR_LOOPBACK); sa = isc_mem_get(mctx, sizeof(*sa)); if (sa == NULL) { result = ISC_R_NOMEMORY; goto cleanup; } isc_sockaddr_fromin(sa, &localhost, destport); ISC_LINK_INIT(sa, link); ISC_LIST_APPEND(*nameservers, sa, link); } if (use_ipv6) { sa = isc_mem_get(mctx, sizeof(*sa)); if (sa == NULL) { result = ISC_R_NOMEMORY; goto cleanup; } isc_sockaddr_fromin6(sa, &in6addr_loopback, destport); ISC_LINK_INIT(sa, link); ISC_LIST_APPEND(*nameservers, sa, link); } } result = dns_client_setservers(client, dns_rdataclass_in, NULL, nameservers); if (result != ISC_R_SUCCESS) delv_log(ISC_LOG_ERROR, "dns_client_setservers: %s", isc_result_totext(result)); cleanup: if (resconf != NULL) irs_resconf_destroy(&resconf); return (result); } static char * next_token(char **stringp, const char *delim) { char *res; do { res = strsep(stringp, delim); if (res == NULL) break; } while (*res == '\0'); return (res); } static isc_result_t parse_uint(isc_uint32_t *uip, const char *value, isc_uint32_t max, const char *desc) { isc_uint32_t n; isc_result_t result = isc_parse_uint32(&n, value, 10); if (result == ISC_R_SUCCESS && n > max) result = ISC_R_RANGE; if (result != ISC_R_SUCCESS) { printf("invalid %s '%s': %s\n", desc, value, isc_result_totext(result)); return (result); } *uip = n; return (ISC_R_SUCCESS); } static void plus_option(char *option) { isc_result_t result; char option_store[256]; char *cmd, *value, *ptr; isc_boolean_t state = ISC_TRUE; strlcpy(option_store, option, sizeof(option_store)); ptr = option_store; cmd = next_token(&ptr,"="); if (cmd == NULL) { printf(";; Invalid option %s\n", option_store); return; } value = ptr; if (strncasecmp(cmd, "no", 2)==0) { cmd += 2; state = ISC_FALSE; } #define FULLCHECK(A) \ do { \ size_t _l = strlen(cmd); \ if (_l >= sizeof(A) || strncasecmp(cmd, A, _l) != 0) \ goto invalid_option; \ } while (0) switch (cmd[0]) { case 'a': /* all */ FULLCHECK("all"); showcomments = state; rrcomments = state; showtrust = state; break; case 'c': switch (cmd[1]) { case 'd': /* cdflag */ FULLCHECK("cdflag"); cdflag = state; break; case 'l': /* class */ FULLCHECK("class"); noclass = ISC_TF(!state); break; case 'o': /* comments */ FULLCHECK("comments"); showcomments = state; break; case 'r': /* crypto */ FULLCHECK("crypto"); nocrypto = ISC_TF(!state); break; default: goto invalid_option; } break; case 'd': switch (cmd[1]) { case 'l': /* dlv */ FULLCHECK("dlv"); if (state && no_sigs) break; dlv_validation = state; if (value != NULL) { dlv_anchor = isc_mem_strdup(mctx, value); if (dlv_anchor == NULL) fatal("out of memory"); } break; case 'n': /* dnssec */ FULLCHECK("dnssec"); showdnssec = state; break; default: goto invalid_option; } break; case 'm': switch (cmd[1]) { case 't': /* mtrace */ message_trace = state; if (state) resolve_trace = state; break; case 'u': /* multiline */ FULLCHECK("multiline"); multiline = state; break; default: goto invalid_option; } break; case 'r': switch (cmd[1]) { case 'o': /* root */ FULLCHECK("root"); if (state && no_sigs) break; root_validation = state; if (value != NULL) { trust_anchor = isc_mem_strdup(mctx, value); if (trust_anchor == NULL) fatal("out of memory"); } break; case 'r': /* rrcomments */ FULLCHECK("rrcomments"); rrcomments = state; break; case 't': /* rtrace */ FULLCHECK("rtrace"); resolve_trace = state; break; default: goto invalid_option; } break; case 's': switch (cmd[1]) { case 'h': /* short */ FULLCHECK("short"); short_form = state; if (short_form) { multiline = ISC_FALSE; showcomments = ISC_FALSE; showtrust = ISC_FALSE; showdnssec = ISC_FALSE; } break; case 'p': /* split */ FULLCHECK("split"); if (value != NULL && !state) goto invalid_option; if (!state) { splitwidth = 0; break; } else if (value == NULL) break; result = parse_uint(&splitwidth, value, 1023, "split"); if (splitwidth % 4 != 0) { splitwidth = ((splitwidth + 3) / 4) * 4; warn("split must be a multiple of 4; " "adjusting to %d", splitwidth); } /* * There is an adjustment done in the * totext_() functions which causes * splitwidth to shrink. This is okay when we're * using the default width but incorrect in this * case, so we correct for it */ if (splitwidth) splitwidth += 3; if (result != ISC_R_SUCCESS) fatal("Couldn't parse split"); break; default: goto invalid_option; } break; case 'u': FULLCHECK("unknownformat"); print_unknown_format = state; break; case 't': switch (cmd[1]) { case 'c': /* tcp */ FULLCHECK("tcp"); use_tcp = state; break; case 'r': /* trust */ FULLCHECK("trust"); showtrust = state; break; case 't': /* ttl */ FULLCHECK("ttl"); nottl = ISC_TF(!state); break; default: goto invalid_option; } break; case 'v': /* vtrace */ FULLCHECK("vtrace"); validator_trace = state; if (state) resolve_trace = state; break; default: invalid_option: /* * We can also add a "need_value:" case here if we ever * add a plus-option that requires a specified value */ fprintf(stderr, "Invalid option: +%s\n", option); usage(); } return; } /* * options: "46a:b:c:d:himp:q:t:vx:"; */ static const char *single_dash_opts = "46himv"; static isc_boolean_t dash_option(char *option, char *next, isc_boolean_t *open_type_class) { char opt, *value; isc_result_t result; isc_boolean_t value_from_next; isc_textregion_t tr; dns_rdatatype_t rdtype; dns_rdataclass_t rdclass; char textname[MAXNAME]; struct in_addr in4; struct in6_addr in6; in_port_t srcport; isc_uint32_t num; char *hash; while (strpbrk(option, single_dash_opts) == &option[0]) { /* * Since the -[46himv] options do not take an argument, * account for them (in any number and/or combination) * if they appear as the first character(s) of a q-opt. */ opt = option[0]; switch (opt) { case '4': if (isc_net_probeipv4() != ISC_R_SUCCESS) fatal("IPv4 networking not available"); if (use_ipv6) { isc_net_disableipv6(); use_ipv6 = ISC_FALSE; } break; case '6': if (isc_net_probeipv6() != ISC_R_SUCCESS) fatal("IPv6 networking not available"); if (use_ipv4) { isc_net_disableipv4(); use_ipv4 = ISC_FALSE; } break; case 'h': usage(); exit(0); /* NOTREACHED */ case 'i': no_sigs = ISC_TRUE; dlv_validation = ISC_FALSE; root_validation = ISC_FALSE; break; case 'm': /* handled in preparse_args() */ break; case 'v': fputs("delv " VERSION "\n", stderr); exit(0); /* NOTREACHED */ default: INSIST(0); } if (strlen(option) > 1U) option = &option[1]; else return (ISC_FALSE); } opt = option[0]; if (strlen(option) > 1U) { value_from_next = ISC_FALSE; value = &option[1]; } else { value_from_next = ISC_TRUE; value = next; } if (value == NULL) goto invalid_option; switch (opt) { case 'a': anchorfile = isc_mem_strdup(mctx, value); if (anchorfile == NULL) fatal("out of memory"); return (value_from_next); case 'b': hash = strchr(value, '#'); if (hash != NULL) { result = parse_uint(&num, hash + 1, 0xffff, "port"); if (result != ISC_R_SUCCESS) fatal("Couldn't parse port number"); srcport = num; *hash = '\0'; } else srcport = 0; if (inet_pton(AF_INET, value, &in4) == 1) { if (srcaddr4 != NULL) fatal("Only one local address per family " "can be specified\n"); isc_sockaddr_fromin(&a4, &in4, srcport); srcaddr4 = &a4; } else if (inet_pton(AF_INET6, value, &in6) == 1) { if (srcaddr6 != NULL) fatal("Only one local address per family " "can be specified\n"); isc_sockaddr_fromin6(&a6, &in6, srcport); srcaddr6 = &a6; } else { if (hash != NULL) *hash = '#'; fatal("Invalid address %s", value); } if (hash != NULL) *hash = '#'; return (value_from_next); case 'c': if (classset) warn("extra query class"); *open_type_class = ISC_FALSE; tr.base = value; tr.length = strlen(value); result = dns_rdataclass_fromtext(&rdclass, (isc_textregion_t *)&tr); if (result == ISC_R_SUCCESS) classset = ISC_TRUE; else if (rdclass != dns_rdataclass_in) warn("ignoring non-IN query class"); else warn("ignoring invalid class"); return (value_from_next); case 'd': result = parse_uint(&num, value, 99, "debug level"); if (result != ISC_R_SUCCESS) fatal("Couldn't parse debug level"); loglevel = num; return (value_from_next); case 'p': port = value; return (value_from_next); case 'q': if (curqname != NULL) { warn("extra query name"); isc_mem_free(mctx, curqname); } curqname = isc_mem_strdup(mctx, value); if (curqname == NULL) fatal("out of memory"); return (value_from_next); case 't': *open_type_class = ISC_FALSE; tr.base = value; tr.length = strlen(value); result = dns_rdatatype_fromtext(&rdtype, (isc_textregion_t *)&tr); if (result == ISC_R_SUCCESS) { if (typeset) warn("extra query type"); if (rdtype == dns_rdatatype_ixfr || rdtype == dns_rdatatype_axfr) fatal("Transfer not supported"); qtype = rdtype; typeset = ISC_TRUE; } else warn("ignoring invalid type"); return (value_from_next); case 'x': result = get_reverse(textname, sizeof(textname), value, ISC_FALSE); if (result == ISC_R_SUCCESS) { if (curqname != NULL) { isc_mem_free(mctx, curqname); warn("extra query name"); } curqname = isc_mem_strdup(mctx, textname); if (curqname == NULL) fatal("out of memory"); if (typeset) warn("extra query type"); qtype = dns_rdatatype_ptr; typeset = ISC_TRUE; } else { fprintf(stderr, "Invalid IP address %s\n", value); exit(1); } return (value_from_next); invalid_option: default: fprintf(stderr, "Invalid option: -%s\n", option); usage(); } /* NOTREACHED */ return (ISC_FALSE); } /* * Check for -m first to determine whether to enable * memory debugging when setting up the memory context. */ static void preparse_args(int argc, char **argv) { isc_boolean_t ipv4only = ISC_FALSE, ipv6only = ISC_FALSE; char *option; for (argc--, argv++; argc > 0; argc--, argv++) { if (argv[0][0] != '-') continue; option = &argv[0][1]; while (strpbrk(option, single_dash_opts) == &option[0]) { switch (option[0]) { case 'm': isc_mem_debugging = ISC_MEM_DEBUGTRACE | ISC_MEM_DEBUGRECORD; break; case '4': if (ipv6only) { fatal("only one of -4 and -6 allowed"); } ipv4only = ISC_TRUE; break; case '6': if (ipv4only) { fatal("only one of -4 and -6 allowed"); } ipv6only = ISC_TRUE; break; } option = &option[1]; } } } /* * Argument parsing is based on dig, but simplified: only one * QNAME/QCLASS/QTYPE tuple can be specified, and options have * been removed that aren't applicable to delv. The interface * should be familiar to dig users, however. */ static void parse_args(int argc, char **argv) { isc_result_t result; isc_textregion_t tr; dns_rdatatype_t rdtype; dns_rdataclass_t rdclass; isc_boolean_t open_type_class = ISC_TRUE; for (; argc > 0; argc--, argv++) { if (argv[0][0] == '@') { server = &argv[0][1]; } else if (argv[0][0] == '+') { plus_option(&argv[0][1]); } else if (argv[0][0] == '-') { if (argc <= 1) { if (dash_option(&argv[0][1], NULL, &open_type_class)) { argc--; argv++; } } else { if (dash_option(&argv[0][1], argv[1], &open_type_class)) { argc--; argv++; } } } else { /* * Anything which isn't an option */ if (open_type_class) { tr.base = argv[0]; tr.length = strlen(argv[0]); result = dns_rdatatype_fromtext(&rdtype, (isc_textregion_t *)&tr); if (result == ISC_R_SUCCESS) { if (typeset) warn("extra query type"); if (rdtype == dns_rdatatype_ixfr || rdtype == dns_rdatatype_axfr) fatal("Transfer not supported"); qtype = rdtype; typeset = ISC_TRUE; continue; } result = dns_rdataclass_fromtext(&rdclass, (isc_textregion_t *)&tr); if (result == ISC_R_SUCCESS) { if (classset) warn("extra query class"); else if (rdclass != dns_rdataclass_in) warn("ignoring non-IN " "query class"); continue; } } if (curqname == NULL) { curqname = isc_mem_strdup(mctx, argv[0]); if (curqname == NULL) fatal("out of memory"); } } } /* * If no qname or qtype specified, search for root/NS * If no qtype specified, use A */ if (!typeset) qtype = dns_rdatatype_a; if (curqname == NULL) { qname = isc_mem_strdup(mctx, "."); if (qname == NULL) fatal("out of memory"); if (!typeset) qtype = dns_rdatatype_ns; } else qname = curqname; } static isc_result_t append_str(const char *text, int len, char **p, char *end) { if (len > end - *p) return (ISC_R_NOSPACE); memmove(*p, text, len); *p += len; return (ISC_R_SUCCESS); } static isc_result_t reverse_octets(const char *in, char **p, char *end) { char *dot = strchr(in, '.'); int len; if (dot != NULL) { isc_result_t result; result = reverse_octets(dot + 1, p, end); if (result != ISC_R_SUCCESS) return (result); result = append_str(".", 1, p, end); if (result != ISC_R_SUCCESS) return (result); len = (int)(dot - in); } else len = strlen(in); return (append_str(in, len, p, end)); } static isc_result_t get_reverse(char *reverse, size_t len, char *value, isc_boolean_t strict) { int r; isc_result_t result; isc_netaddr_t addr; addr.family = AF_INET6; r = inet_pton(AF_INET6, value, &addr.type.in6); if (r > 0) { /* This is a valid IPv6 address. */ dns_fixedname_t fname; dns_name_t *name; unsigned int options = 0; dns_fixedname_init(&fname); name = dns_fixedname_name(&fname); result = dns_byaddr_createptrname2(&addr, options, name); if (result != ISC_R_SUCCESS) return (result); dns_name_format(name, reverse, (unsigned int)len); return (ISC_R_SUCCESS); } else { /* * Not a valid IPv6 address. Assume IPv4. * If 'strict' is not set, construct the * in-addr.arpa name by blindly reversing * octets whether or not they look like integers, * so that this can be used for RFC2317 names * and such. */ char *p = reverse; char *end = reverse + len; if (strict && inet_pton(AF_INET, value, &addr.type.in) != 1) return (DNS_R_BADDOTTEDQUAD); result = reverse_octets(value, &p, end); if (result != ISC_R_SUCCESS) return (result); result = append_str(".in-addr.arpa.", 15, &p, end); if (result != ISC_R_SUCCESS) return (result); return (ISC_R_SUCCESS); } } int main(int argc, char *argv[]) { dns_client_t *client = NULL; isc_result_t result; dns_fixedname_t qfn; dns_name_t *query_name, *response_name; dns_rdataset_t *rdataset; dns_namelist_t namelist; unsigned int resopt, clopt; isc_appctx_t *actx = NULL; isc_taskmgr_t *taskmgr = NULL; isc_socketmgr_t *socketmgr = NULL; isc_timermgr_t *timermgr = NULL; dns_master_style_t *style = NULL; #ifndef WIN32 struct sigaction sa; #endif progname = argv[0]; preparse_args(argc, argv); argc--; argv++; isc_lib_register(); result = dns_lib_init(); if (result != ISC_R_SUCCESS) fatal("dns_lib_init failed: %d", result); result = isc_mem_create(0, 0, &mctx); if (result != ISC_R_SUCCESS) fatal("failed to create mctx"); CHECK(isc_appctx_create(mctx, &actx)); CHECK(isc_taskmgr_createinctx(mctx, actx, 1, 0, &taskmgr)); CHECK(isc_socketmgr_createinctx(mctx, actx, &socketmgr)); CHECK(isc_timermgr_createinctx(mctx, actx, &timermgr)); parse_args(argc, argv); CHECK(setup_style(&style)); setup_logging(stderr); CHECK(isc_app_ctxstart(actx)); #ifndef WIN32 /* Unblock SIGINT if it's been blocked by isc_app_ctxstart() */ memset(&sa, 0, sizeof(sa)); sa.sa_handler = SIG_DFL; if (sigfillset(&sa.sa_mask) != 0 || sigaction(SIGINT, &sa, NULL) < 0) fatal("Couldn't set up signal handler"); #endif /* Create client */ clopt = DNS_CLIENTCREATEOPT_USECACHE; result = dns_client_createx2(mctx, actx, taskmgr, socketmgr, timermgr, clopt, &client, srcaddr4, srcaddr6); if (result != ISC_R_SUCCESS) { delv_log(ISC_LOG_ERROR, "dns_client_create: %s", isc_result_totext(result)); goto cleanup; } /* Set the nameserver */ if (server != NULL) addserver(client); else findserver(client); CHECK(setup_dnsseckeys(client)); /* Construct QNAME */ CHECK(convert_name(&qfn, &query_name, qname)); /* Set up resolution options */ resopt = DNS_CLIENTRESOPT_ALLOWRUN | DNS_CLIENTRESOPT_NOCDFLAG; if (no_sigs) resopt |= DNS_CLIENTRESOPT_NODNSSEC; if (!root_validation && !dlv_validation) resopt |= DNS_CLIENTRESOPT_NOVALIDATE; if (cdflag) resopt &= ~DNS_CLIENTRESOPT_NOCDFLAG; if (use_tcp) resopt |= DNS_CLIENTRESOPT_TCP; /* Perform resolution */ ISC_LIST_INIT(namelist); result = dns_client_resolve(client, query_name, dns_rdataclass_in, qtype, resopt, &namelist); if (result != ISC_R_SUCCESS) delv_log(ISC_LOG_ERROR, "resolution failed: %s", isc_result_totext(result)); for (response_name = ISC_LIST_HEAD(namelist); response_name != NULL; response_name = ISC_LIST_NEXT(response_name, link)) { for (rdataset = ISC_LIST_HEAD(response_name->list); rdataset != NULL; rdataset = ISC_LIST_NEXT(rdataset, link)) { result = printdata(rdataset, response_name, style); if (result != ISC_R_SUCCESS) delv_log(ISC_LOG_ERROR, "print data failed"); } } dns_client_freeresanswer(client, &namelist); cleanup: if (dlv_anchor != NULL) isc_mem_free(mctx, dlv_anchor); if (trust_anchor != NULL) isc_mem_free(mctx, trust_anchor); if (anchorfile != NULL) isc_mem_free(mctx, anchorfile); if (qname != NULL) isc_mem_free(mctx, qname); if (style != NULL) dns_master_styledestroy(&style, mctx); if (client != NULL) dns_client_destroy(&client); if (taskmgr != NULL) isc_taskmgr_destroy(&taskmgr); if (timermgr != NULL) isc_timermgr_destroy(&timermgr); if (socketmgr != NULL) isc_socketmgr_destroy(&socketmgr); if (actx != NULL) isc_appctx_destroy(&actx); if (lctx != NULL) isc_log_destroy(&lctx); isc_mem_detach(&mctx); dns_lib_shutdown(); return (0); } bind9-9.11.3+dfsg/bin/delv/delv.docbook000066400000000000000000000556121325250447100175430ustar00rootroot00000000000000]> 2014-04-23 ISC Internet Systems Consortium, Inc. delv 1 BIND9 delv DNS lookup and validation utility 2014 2015 2016 2017 Internet Systems Consortium, Inc. ("ISC") delv @server name type class queryopt delv delv delv queryopt query DESCRIPTION delv is a tool for sending DNS queries and validating the results, using the same internal resolver and validator logic as named. delv will send to a specified name server all queries needed to fetch and validate the requested data; this includes the original requested query, subsequent queries to follow CNAME or DNAME chains, and queries for DNSKEY, DS and DLV records to establish a chain of trust for DNSSEC validation. It does not perform iterative resolution, but simulates the behavior of a name server configured for DNSSEC validating and forwarding. By default, responses are validated using built-in DNSSEC trust anchor for the root zone ("."). Records returned by delv are either fully validated or were not signed. If validation fails, an explanation of the failure is included in the output; the validation process can be traced in detail. Because delv does not rely on an external server to carry out validation, it can be used to check the validity of DNS responses in environments where local name servers may not be trustworthy. Unless it is told to query a specific name server, delv will try each of the servers listed in /etc/resolv.conf. If no usable server addresses are found, delv will send queries to the localhost addresses (127.0.0.1 for IPv4, ::1 for IPv6). When no command line arguments or options are given, delv will perform an NS query for "." (the root zone). SIMPLE USAGE A typical invocation of delv looks like: delv @server name type where: server is the name or IP address of the name server to query. This can be an IPv4 address in dotted-decimal notation or an IPv6 address in colon-delimited notation. When the supplied server argument is a hostname, delv resolves that name before querying that name server (note, however, that this initial lookup is not validated by DNSSEC). If no server argument is provided, delv consults /etc/resolv.conf; if an address is found there, it queries the name server at that address. If either of the or options are in use, then only addresses for the corresponding transport will be tried. If no usable addresses are found, delv will send queries to the localhost addresses (127.0.0.1 for IPv4, ::1 for IPv6). name is the domain name to be looked up. type indicates what type of query is required — ANY, A, MX, etc. type can be any valid query type. If no type argument is supplied, delv will perform a lookup for an A record. OPTIONS -a anchor-file Specifies a file from which to read DNSSEC trust anchors. The default is /etc/bind.keys, which is included with BIND 9 and contains one or more trust anchors for the root zone ("."). Keys that do not match the root zone name are ignored. An alternate key name can be specified using the options. DNSSEC Lookaside Validation can also be turned on by using the to specify the name of a zone containing DLV records. Note: When reading the trust anchor file, delv treats statements and statements identically. That is, for a managed key, it is the initial key that is trusted; RFC 5011 key management is not supported. delv will not consult the managed-keys database maintained by named. This means that if either of the keys in /etc/bind.keys is revoked and rolled over, it will be necessary to update /etc/bind.keys to use DNSSEC validation in delv. -b address Sets the source IP address of the query to address. This must be a valid address on one of the host's network interfaces or "0.0.0.0" or "::". An optional source port may be specified by appending "#<port>" -c class Sets the query class for the requested data. Currently, only class "IN" is supported in delv and any other value is ignored. -d level Set the systemwide debug level to . The allowed range is from 0 to 99. The default is 0 (no debugging). Debugging traces from delv become more verbose as the debug level increases. See the , , and options below for additional debugging details. -h Display the delv help usage output and exit. -i Insecure mode. This disables internal DNSSEC validation. (Note, however, this does not set the CD bit on upstream queries. If the server being queried is performing DNSSEC validation, then it will not return invalid data; this can cause delv to time out. When it is necessary to examine invalid data to debug a DNSSEC problem, use dig +cd.) -m Enables memory usage debugging. -p port# Specifies a destination port to use for queries instead of the standard DNS port number 53. This option would be used with a name server that has been configured to listen for queries on a non-standard port number. -q name Sets the query name to name. While the query name can be specified without using the , it is sometimes necessary to disambiguate names from types or classes (for example, when looking up the name "ns", which could be misinterpreted as the type NS, or "ch", which could be misinterpreted as class CH). -t type Sets the query type to type, which can be any valid query type supported in BIND 9 except for zone transfer types AXFR and IXFR. As with , this is useful to distinguish query name type or class when they are ambiguous. it is sometimes necessary to disambiguate names from types. The default query type is "A", unless the option is supplied to indicate a reverse lookup, in which case it is "PTR". -v Print the delv version and exit. -x addr Performs a reverse lookup, mapping an addresses to a name. addr is an IPv4 address in dotted-decimal notation, or a colon-delimited IPv6 address. When is used, there is no need to provide the name or type arguments. delv automatically performs a lookup for a name like 11.12.13.10.in-addr.arpa and sets the query type to PTR. IPv6 addresses are looked up using nibble format under the IP6.ARPA domain. -4 Forces delv to only use IPv4. -6 Forces delv to only use IPv6. QUERY OPTIONS delv provides a number of query options which affect the way results are displayed, and in some cases the way lookups are performed. Each query option is identified by a keyword preceded by a plus sign (+). Some keywords set or reset an option. These may be preceded by the string no to negate the meaning of that keyword. Other keywords assign values to options like the timeout interval. They have the form . The query options are: Controls whether to set the CD (checking disabled) bit in queries sent by delv. This may be useful when troubleshooting DNSSEC problems from behind a validating resolver. A validating resolver will block invalid responses, making it difficult to retrieve them for analysis. Setting the CD flag on queries will cause the resolver to return invalid responses, which delv can then validate internally and report the errors in detail. Controls whether to display the CLASS when printing a record. The default is to display the CLASS. Controls whether to display the TTL when printing a record. The default is to display the TTL. Toggle resolver fetch logging. This reports the name and type of each query sent by delv in the process of carrying out the resolution and validation process: this includes including the original query and all subsequent queries to follow CNAMEs and to establish a chain of trust for DNSSEC validation. This is equivalent to setting the debug level to 1 in the "resolver" logging category. Setting the systemwide debug level to 1 using the option will product the same output (but will affect other logging categories as well). Toggle message logging. This produces a detailed dump of the responses received by delv in the process of carrying out the resolution and validation process. This is equivalent to setting the debug level to 10 for the "packets" module of the "resolver" logging category. Setting the systemwide debug level to 10 using the option will produce the same output (but will affect other logging categories as well). Toggle validation logging. This shows the internal process of the validator as it determines whether an answer is validly signed, unsigned, or invalid. This is equivalent to setting the debug level to 3 for the "validator" module of the "dnssec" logging category. Setting the systemwide debug level to 3 using the option will produce the same output (but will affect other logging categories as well). Provide a terse answer. The default is to print the answer in a verbose form. Toggle the display of comment lines in the output. The default is to print comments. Toggle the display of per-record comments in the output (for example, human-readable key information about DNSKEY records). The default is to print per-record comments. Toggle the display of cryptographic fields in DNSSEC records. The contents of these field are unnecessary to debug most DNSSEC validation failures and removing them makes it easier to see the common failures. The default is to display the fields. When omitted they are replaced by the string "[omitted]" or in the DNSKEY case the key id is displayed as the replacement, e.g. "[ key id = value ]". Controls whether to display the trust level when printing a record. The default is to display the trust level. Split long hex- or base64-formatted fields in resource records into chunks of W characters (where W is rounded up to the nearest multiple of 4). +nosplit or +split=0 causes fields not to be split at all. The default is 56 characters, or 44 characters when multiline mode is active. Set or clear the display options , , and as a group. Print long records (such as RRSIG, DNSKEY, and SOA records) in a verbose multi-line format with human-readable comments. The default is to print each record on a single line, to facilitate machine parsing of the delv output. Indicates whether to display RRSIG records in the delv output. The default is to do so. Note that (unlike in dig) this does not control whether to request DNSSEC records or whether to validate them. DNSSEC records are always requested, and validation will always occur unless suppressed by the use of or and . Indicates whether to perform conventional (non-lookaside) DNSSEC validation, and if so, specifies the name of a trust anchor. The default is to validate using a trust anchor of "." (the root zone), for which there is a built-in key. If specifying a different trust anchor, then must be used to specify a file containing the key. Indicates whether to perform DNSSEC lookaside validation, and if so, specifies the name of the DLV trust anchor. The option must also be used to specify a file containing the DLV key. Controls whether to use TCP when sending queries. The default is to use UDP unless a truncated response has been received. Print all RDATA in unknown RR type presentation format (RFC 3597). The default is to print RDATA for known types in the type's presentation format. FILES /etc/bind.keys /etc/resolv.conf SEE ALSO dig1 , named8 , RFC4034, RFC4035, RFC4431, RFC5074, RFC5155. bind9-9.11.3+dfsg/bin/delv/delv.html000066400000000000000000000550721325250447100170670ustar00rootroot00000000000000 delv

Name

delv — DNS lookup and validation utility

Synopsis

delv [@server] [ [-4] | [-6] ] [-a anchor-file] [-b address] [-c class] [-d level] [-i] [-m] [-p port#] [-q name] [-t type] [-x addr] [name] [type] [class] [queryopt...]

delv [-h]

delv [-v]

delv [queryopt...] [query...]

DESCRIPTION

delv is a tool for sending DNS queries and validating the results, using the same internal resolver and validator logic as named.

delv will send to a specified name server all queries needed to fetch and validate the requested data; this includes the original requested query, subsequent queries to follow CNAME or DNAME chains, and queries for DNSKEY, DS and DLV records to establish a chain of trust for DNSSEC validation. It does not perform iterative resolution, but simulates the behavior of a name server configured for DNSSEC validating and forwarding.

By default, responses are validated using built-in DNSSEC trust anchor for the root zone ("."). Records returned by delv are either fully validated or were not signed. If validation fails, an explanation of the failure is included in the output; the validation process can be traced in detail. Because delv does not rely on an external server to carry out validation, it can be used to check the validity of DNS responses in environments where local name servers may not be trustworthy.

Unless it is told to query a specific name server, delv will try each of the servers listed in /etc/resolv.conf. If no usable server addresses are found, delv will send queries to the localhost addresses (127.0.0.1 for IPv4, ::1 for IPv6).

When no command line arguments or options are given, delv will perform an NS query for "." (the root zone).

SIMPLE USAGE

A typical invocation of delv looks like:

 delv @server name type 

where:

server

is the name or IP address of the name server to query. This can be an IPv4 address in dotted-decimal notation or an IPv6 address in colon-delimited notation. When the supplied server argument is a hostname, delv resolves that name before querying that name server (note, however, that this initial lookup is not validated by DNSSEC).

If no server argument is provided, delv consults /etc/resolv.conf; if an address is found there, it queries the name server at that address. If either of the -4 or -6 options are in use, then only addresses for the corresponding transport will be tried. If no usable addresses are found, delv will send queries to the localhost addresses (127.0.0.1 for IPv4, ::1 for IPv6).

name

is the domain name to be looked up.

type

indicates what type of query is required — ANY, A, MX, etc. type can be any valid query type. If no type argument is supplied, delv will perform a lookup for an A record.

OPTIONS

-a anchor-file

Specifies a file from which to read DNSSEC trust anchors. The default is /etc/bind.keys, which is included with BIND 9 and contains one or more trust anchors for the root zone (".").

Keys that do not match the root zone name are ignored. An alternate key name can be specified using the +root=NAME options. DNSSEC Lookaside Validation can also be turned on by using the +dlv=NAME to specify the name of a zone containing DLV records.

Note: When reading the trust anchor file, delv treats managed-keys statements and trusted-keys statements identically. That is, for a managed key, it is the initial key that is trusted; RFC 5011 key management is not supported. delv will not consult the managed-keys database maintained by named. This means that if either of the keys in /etc/bind.keys is revoked and rolled over, it will be necessary to update /etc/bind.keys to use DNSSEC validation in delv.

-b address

Sets the source IP address of the query to address. This must be a valid address on one of the host's network interfaces or "0.0.0.0" or "::". An optional source port may be specified by appending "#<port>"

-c class

Sets the query class for the requested data. Currently, only class "IN" is supported in delv and any other value is ignored.

-d level

Set the systemwide debug level to level. The allowed range is from 0 to 99. The default is 0 (no debugging). Debugging traces from delv become more verbose as the debug level increases. See the +mtrace, +rtrace, and +vtrace options below for additional debugging details.

-h

Display the delv help usage output and exit.

-i

Insecure mode. This disables internal DNSSEC validation. (Note, however, this does not set the CD bit on upstream queries. If the server being queried is performing DNSSEC validation, then it will not return invalid data; this can cause delv to time out. When it is necessary to examine invalid data to debug a DNSSEC problem, use dig +cd.)

-m

Enables memory usage debugging.

-p port#

Specifies a destination port to use for queries instead of the standard DNS port number 53. This option would be used with a name server that has been configured to listen for queries on a non-standard port number.

-q name

Sets the query name to name. While the query name can be specified without using the -q, it is sometimes necessary to disambiguate names from types or classes (for example, when looking up the name "ns", which could be misinterpreted as the type NS, or "ch", which could be misinterpreted as class CH).

-t type

Sets the query type to type, which can be any valid query type supported in BIND 9 except for zone transfer types AXFR and IXFR. As with -q, this is useful to distinguish query name type or class when they are ambiguous. it is sometimes necessary to disambiguate names from types.

The default query type is "A", unless the -x option is supplied to indicate a reverse lookup, in which case it is "PTR".

-v

Print the delv version and exit.

-x addr

Performs a reverse lookup, mapping an addresses to a name. addr is an IPv4 address in dotted-decimal notation, or a colon-delimited IPv6 address. When -x is used, there is no need to provide the name or type arguments. delv automatically performs a lookup for a name like 11.12.13.10.in-addr.arpa and sets the query type to PTR. IPv6 addresses are looked up using nibble format under the IP6.ARPA domain.

-4

Forces delv to only use IPv4.

-6

Forces delv to only use IPv6.

QUERY OPTIONS

delv provides a number of query options which affect the way results are displayed, and in some cases the way lookups are performed.

Each query option is identified by a keyword preceded by a plus sign (+). Some keywords set or reset an option. These may be preceded by the string no to negate the meaning of that keyword. Other keywords assign values to options like the timeout interval. They have the form +keyword=value. The query options are:

+[no]cdflag

Controls whether to set the CD (checking disabled) bit in queries sent by delv. This may be useful when troubleshooting DNSSEC problems from behind a validating resolver. A validating resolver will block invalid responses, making it difficult to retrieve them for analysis. Setting the CD flag on queries will cause the resolver to return invalid responses, which delv can then validate internally and report the errors in detail.

+[no]class

Controls whether to display the CLASS when printing a record. The default is to display the CLASS.

+[no]ttl

Controls whether to display the TTL when printing a record. The default is to display the TTL.

+[no]rtrace

Toggle resolver fetch logging. This reports the name and type of each query sent by delv in the process of carrying out the resolution and validation process: this includes including the original query and all subsequent queries to follow CNAMEs and to establish a chain of trust for DNSSEC validation.

This is equivalent to setting the debug level to 1 in the "resolver" logging category. Setting the systemwide debug level to 1 using the -d option will product the same output (but will affect other logging categories as well).

+[no]mtrace

Toggle message logging. This produces a detailed dump of the responses received by delv in the process of carrying out the resolution and validation process.

This is equivalent to setting the debug level to 10 for the "packets" module of the "resolver" logging category. Setting the systemwide debug level to 10 using the -d option will produce the same output (but will affect other logging categories as well).

+[no]vtrace

Toggle validation logging. This shows the internal process of the validator as it determines whether an answer is validly signed, unsigned, or invalid.

This is equivalent to setting the debug level to 3 for the "validator" module of the "dnssec" logging category. Setting the systemwide debug level to 3 using the -d option will produce the same output (but will affect other logging categories as well).

+[no]short

Provide a terse answer. The default is to print the answer in a verbose form.

+[no]comments

Toggle the display of comment lines in the output. The default is to print comments.

+[no]rrcomments

Toggle the display of per-record comments in the output (for example, human-readable key information about DNSKEY records). The default is to print per-record comments.

+[no]crypto

Toggle the display of cryptographic fields in DNSSEC records. The contents of these field are unnecessary to debug most DNSSEC validation failures and removing them makes it easier to see the common failures. The default is to display the fields. When omitted they are replaced by the string "[omitted]" or in the DNSKEY case the key id is displayed as the replacement, e.g. "[ key id = value ]".

+[no]trust

Controls whether to display the trust level when printing a record. The default is to display the trust level.

+[no]split[=W]

Split long hex- or base64-formatted fields in resource records into chunks of W characters (where W is rounded up to the nearest multiple of 4). +nosplit or +split=0 causes fields not to be split at all. The default is 56 characters, or 44 characters when multiline mode is active.

+[no]all

Set or clear the display options +[no]comments, +[no]rrcomments, and +[no]trust as a group.

+[no]multiline

Print long records (such as RRSIG, DNSKEY, and SOA records) in a verbose multi-line format with human-readable comments. The default is to print each record on a single line, to facilitate machine parsing of the delv output.

+[no]dnssec

Indicates whether to display RRSIG records in the delv output. The default is to do so. Note that (unlike in dig) this does not control whether to request DNSSEC records or whether to validate them. DNSSEC records are always requested, and validation will always occur unless suppressed by the use of -i or +noroot and +nodlv.

+[no]root[=ROOT]

Indicates whether to perform conventional (non-lookaside) DNSSEC validation, and if so, specifies the name of a trust anchor. The default is to validate using a trust anchor of "." (the root zone), for which there is a built-in key. If specifying a different trust anchor, then -a must be used to specify a file containing the key.

+[no]dlv[=DLV]

Indicates whether to perform DNSSEC lookaside validation, and if so, specifies the name of the DLV trust anchor. The -a option must also be used to specify a file containing the DLV key.

+[no]tcp

Controls whether to use TCP when sending queries. The default is to use UDP unless a truncated response has been received.

+[no]unknownformat

Print all RDATA in unknown RR type presentation format (RFC 3597). The default is to print RDATA for known types in the type's presentation format.

FILES

/etc/bind.keys

/etc/resolv.conf

SEE ALSO

dig(1) , named(8) , RFC4034, RFC4035, RFC4431, RFC5074, RFC5155.

bind9-9.11.3+dfsg/bin/delv/win32/000077500000000000000000000000001325250447100162005ustar00rootroot00000000000000bind9-9.11.3+dfsg/bin/delv/win32/delv.dsp.in000066400000000000000000000114631325250447100202540ustar00rootroot00000000000000# Microsoft Developer Studio Project File - Name="delv" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "@PLATFORM@ (x86) Console Application" 0x0103 CFG=delv - @PLATFORM@ Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "delv.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "delv.mak" CFG="delv - @PLATFORM@ Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "delv - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE "delv - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "delv - @PLATFORM@ Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 @COPTX@ @COPTI@ /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c # ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isccfg/include" /I "../../../lib/dns/win32/include" /I "../../../lib/dns/include" /I "../../../lib/irs/win32/include" /I "../../../lib/irs/include" @CRYPTO@ /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console @MACHINE@ # ADD LINK32 user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib ../../../lib/isccfg/win32/Release/libisccfg.lib ../../../lib/irs/win32/Release/libirs.lib /nologo /subsystem:console @MACHINE@ /out:"../../../Build/Release/delv.exe" !ELSEIF "$(CFG)" == "delv - @PLATFORM@ Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /GZ /c # ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isccfg/include" /I "../../../lib/dns/win32/include" /I "../../../lib/dns/include" /I "../../../lib/irs/win32/include" /I "../../../lib/irs/include" @CRYPTO@ /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c # SUBTRACT CPP /X @COPTY@ # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug @MACHINE@ /pdbtype:sept # ADD LINK32 user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib ../../../lib/isccfg/win32/Debug/libisccfg.lib ../../../lib/irs/win32/Debug/libirs.lib /nologo /subsystem:console /debug @MACHINE@ /out:"../../../Build/Debug/delv.exe" /pdbtype:sept !ENDIF # Begin Target # Name "delv - @PLATFORM@ Release" # Name "delv - @PLATFORM@ Debug" # Begin Group "Source Files" # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" # Begin Source File SOURCE="..\delv.c" # End Source File # End Group # Begin Group "Header Files" # PROP Default_Filter "h;hpp;hxx;hm;inl" # End Group # Begin Group "Resource Files" # PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" # End Group # End Target # End Project bind9-9.11.3+dfsg/bin/delv/win32/delv.dsw000066400000000000000000000010251325250447100176470ustar00rootroot00000000000000Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "delv"=".\delv.dsp" - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### bind9-9.11.3+dfsg/bin/delv/win32/delv.mak.in000066400000000000000000000176741325250447100202500ustar00rootroot00000000000000# Microsoft Developer Studio Generated NMAKE File, Based on delv.dsp !IF "$(CFG)" == "" CFG=delv - @PLATFORM@ Debug !MESSAGE No configuration specified. Defaulting to delv - @PLATFORM@ Debug. !ENDIF !IF "$(CFG)" != "delv - @PLATFORM@ Release" && "$(CFG)" != "delv - @PLATFORM@ Debug" !MESSAGE Invalid configuration "$(CFG)" specified. !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "delv.mak" CFG="delv - @PLATFORM@ Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "delv - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE "delv - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE !ERROR An invalid configuration is specified. !ENDIF !IF "$(OS)" == "Windows_NT" NULL= !ELSE NULL=nul !ENDIF !IF "$(CFG)" == "delv - @PLATFORM@ Release" _VC_MANIFEST_INC=0 _VC_MANIFEST_BASENAME=__VC80 !ELSE _VC_MANIFEST_INC=1 _VC_MANIFEST_BASENAME=__VC80.Debug !ENDIF #################################################### # Specifying name of temporary resource file used only in incremental builds: !if "$(_VC_MANIFEST_INC)" == "1" _VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res !else _VC_MANIFEST_AUTO_RES= !endif #################################################### # _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE: !if "$(_VC_MANIFEST_INC)" == "1" #MT_SPECIAL_RETURN=1090650113 #MT_SPECIAL_SWITCH=-notify_resource_update MT_SPECIAL_RETURN=0 MT_SPECIAL_SWITCH= _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \ if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \ rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \ link $** /out:$@ $(LFLAGS) !else _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1 !endif #################################################### # _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL: !if "$(_VC_MANIFEST_INC)" == "1" #MT_SPECIAL_RETURN=1090650113 #MT_SPECIAL_SWITCH=-notify_resource_update MT_SPECIAL_RETURN=0 MT_SPECIAL_SWITCH= _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \ if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \ rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \ link $** /out:$@ $(LFLAGS) !else _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2 !endif #################################################### # _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily: !if "$(_VC_MANIFEST_INC)" == "1" _VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \ $(_VC_MANIFEST_BASENAME).auto.rc \ $(_VC_MANIFEST_BASENAME).auto.manifest !else _VC_MANIFEST_CLEAN= !endif !IF "$(CFG)" == "delv - @PLATFORM@ Release" OUTDIR=.\Release INTDIR=.\Release ALL : "..\..\..\Build\Release\delv.exe" CLEAN : -@erase "$(INTDIR)\delv.obj" -@erase "$(INTDIR)\vc60.idb" -@erase "..\..\..\Build\Release\delv.exe" -@$(_VC_MANIFEST_CLEAN) "$(OUTDIR)" : if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" CPP=cl.exe CPP_PROJ=/nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isccfg/include" /I "../../../lib/dns/win32/include" /I "../../../lib/dns/include" /I "../../../lib/irs/win32/include" /I "../../../lib/irs/include" @CRYPTO@ /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\delv.pch" @COPTY@ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c .c{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .c{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << RSC=rc.exe BSC32=bscmake.exe BSC32_FLAGS=/nologo /o"$(OUTDIR)\delv.bsc" BSC32_SBRS= \ LINK32=link.exe LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib ../../../lib/isccfg/win32/Release/libisccfg.lib ../../../lib/irs/win32/Release/libirs.lib /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\delv.pdb" @MACHINE@ /out:"../../../Build/Release/delv.exe" LINK32_OBJS= \ "$(INTDIR)\delv.obj" "..\..\..\Build\Release\delv.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) $(LINK32) @<< $(LINK32_FLAGS) $(LINK32_OBJS) << $(_VC_MANIFEST_EMBED_EXE) !ELSEIF "$(CFG)" == "delv - @PLATFORM@ Debug" OUTDIR=.\Debug INTDIR=.\Debug # Begin Custom Macros OutDir=.\Debug # End Custom Macros ALL : "..\..\..\Build\Debug\delv.exe" "$(OUTDIR)\delv.bsc" CLEAN : -@erase "$(INTDIR)\delv.obj" -@erase "$(INTDIR)\delv.sbr" -@erase "$(INTDIR)\vc60.idb" -@erase "$(INTDIR)\vc60.pdb" -@erase "$(OUTDIR)\delv.pdb" -@erase "$(OUTDIR)\delv.bsc" -@erase "..\..\..\Build\Debug\delv.exe" -@erase "..\..\..\Build\Debug\delv.ilk" -@$(_VC_MANIFEST_CLEAN) "$(OUTDIR)" : if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" CPP=cl.exe CPP_PROJ=/nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isccfg/include" /I "../../../lib/dns/win32/include" /I "../../../lib/dns/include" /I "../../../lib/irs/win32/include" /I "../../../lib/irs/include" @CRYPTO@ /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c .c{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .c{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << RSC=rc.exe BSC32=bscmake.exe BSC32_FLAGS=/nologo /o"$(OUTDIR)\delv.bsc" BSC32_SBRS= \ "$(INTDIR)\delv.sbr" "$(OUTDIR)\delv.bsc" : "$(OUTDIR)" $(BSC32_SBRS) $(BSC32) @<< $(BSC32_FLAGS) $(BSC32_SBRS) << LINK32=link.exe LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib ../../../lib/isccfg/win32/Debug/libisccfg.lib ../../../lib/irs/win32/Debug/libirs.lib /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\delv.pdb" /debug @MACHINE@ /out:"../../../Build/Debug/delv.exe" /pdbtype:sept LINK32_OBJS= \ "$(INTDIR)\delv.obj" "..\..\..\Build\Debug\delv.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) $(LINK32) @<< $(LINK32_FLAGS) $(LINK32_OBJS) << $(_VC_MANIFEST_EMBED_EXE) !ENDIF !IF "$(NO_EXTERNAL_DEPS)" != "1" !IF EXISTS("delv.dep") !INCLUDE "delv.dep" !ELSE !MESSAGE Warning: cannot find "delv.dep" !ENDIF !ENDIF !IF "$(CFG)" == "delv - @PLATFORM@ Release" || "$(CFG)" == "delv - @PLATFORM@ Debug" SOURCE="..\delv.c" !IF "$(CFG)" == "delv - @PLATFORM@ Release" "$(INTDIR)\delv.obj" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ELSEIF "$(CFG)" == "delv - @PLATFORM@ Debug" "$(INTDIR)\delv.obj" "$(INTDIR)\delv.sbr" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ENDIF !ENDIF #################################################### # Commands to generate initial empty manifest file and the RC file # that references it, and for generating the .res file: $(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc $(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest type <<$@ #include 1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest" << KEEP $(_VC_MANIFEST_BASENAME).auto.manifest : type <<$@ << KEEP bind9-9.11.3+dfsg/bin/delv/win32/delv.vcxproj.filters.in000066400000000000000000000016741325250447100226330ustar00rootroot00000000000000 {4FC737F1-C7A5-4376-A066-2A32D752A2FF} cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx {93995380-89BD-4b04-88EB-625FBE52EBFB} h;hpp;hxx;hm;inl;inc;xsd {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms Source Files bind9-9.11.3+dfsg/bin/delv/win32/delv.vcxproj.in000066400000000000000000000155451325250447100211660ustar00rootroot00000000000000 Debug @PLATFORM@ Release @PLATFORM@ {BE172EFE-C1DC-4812-BFB9-8C5F8ADB7E9F} Win32Proj delv Application true MultiByte Application false true MultiByte true ..\..\..\Build\$(Configuration)\ .\$(Configuration)\ false ..\..\..\Build\$(Configuration)\ .\$(Configuration)\ Level3 Disabled WIN32;@CRYPTO@_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true .\$(Configuration)\$(TargetName).pch .\$(Configuration)\ .\$(Configuration)\ $(OutDir)$(TargetName).pdb true ..\..\..\;@LIBXML2_INC@@OPENSSL_INC@@GEOIP_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\isccfg\include;..\..\..\lib\dns\win32\include;..\..\..\lib\dns\include;..\..\..\lib\irs\win32\include;..\..\..\lib\irs\include;%(AdditionalIncludeDirectories) CompileAsC Console true ..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt) ..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);..\..\..\lib\isccfg\win32\$(Configuration);..\..\..\lib\irs\win32\$(Configuration);%(AdditionalLibraryDirectories) libisc.lib;libdns.lib;libisccfg.lib;libirs.lib;ws2_32.lib;%(AdditionalDependencies) Level3 MaxSpeed true @INTRINSIC@ WIN32;@CRYPTO@NDEBUG;_CONSOLE;%(PreprocessorDefinitions) OnlyExplicitInline false true .\$(Configuration)\$(TargetName).pch .\$(Configuration)\ .\$(Configuration)\ $(OutDir)$(TargetName).pdb ..\..\..\;@LIBXML2_INC@@OPENSSL_INC@@GEOIP_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\isccfg\include;..\..\..\lib\dns\win32\include;..\..\..\lib\dns\include;..\..\..\lib\irs\win32\include;..\..\..\lib\irs\include;%(AdditionalIncludeDirectories) CompileAsC Console false true true ..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt) Default ..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);..\..\..\lib\isccfg\win32\$(Configuration);..\..\..\lib\irs\win32\$(Configuration);%(AdditionalLibraryDirectories) libisc.lib;libdns.lib;libisccfg.lib;libirs.lib;ws2_32.lib;%(AdditionalDependencies) bind9-9.11.3+dfsg/bin/delv/win32/delv.vcxproj.user000066400000000000000000000002171325250447100215240ustar00rootroot00000000000000 bind9-9.11.3+dfsg/bin/dig/000077500000000000000000000000001325250447100150475ustar00rootroot00000000000000bind9-9.11.3+dfsg/bin/dig/Makefile.in000066400000000000000000000061161325250447100171200ustar00rootroot00000000000000# Copyright (C) 2000-2002, 2004, 2005, 2007, 2009, 2012-2017 Internet Systems Consortium, Inc. ("ISC") # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. srcdir = @srcdir@ VPATH = @srcdir@ top_srcdir = @top_srcdir@ VERSION=@BIND9_VERSION@ @BIND9_MAKE_INCLUDES@ READLINE_LIB = @READLINE_LIB@ CINCLUDES = -I${srcdir}/include ${DNS_INCLUDES} \ ${BIND9_INCLUDES} ${ISC_INCLUDES} \ ${LWRES_INCLUDES} ${ISCCFG_INCLUDES} @DST_OPENSSL_INC@ CDEFINES = -DVERSION=\"${VERSION}\" @CRYPTO@ CWARNINGS = ISCCFGLIBS = ../../lib/isccfg/libisccfg.@A@ DNSLIBS = ../../lib/dns/libdns.@A@ @DNS_CRYPTO_LIBS@ BIND9LIBS = ../../lib/bind9/libbind9.@A@ ISCLIBS = ../../lib/isc/libisc.@A@ ISCNOSYMLIBS = ../../lib/isc/libisc-nosymtbl.@A@ LWRESLIBS = ../../lib/lwres/liblwres.@A@ ISCCFGDEPLIBS = ../../lib/isccfg/libisccfg.@A@ DNSDEPLIBS = ../../lib/dns/libdns.@A@ BIND9DEPLIBS = ../../lib/bind9/libbind9.@A@ ISCDEPLIBS = ../../lib/isc/libisc.@A@ LWRESDEPLIBS = ../../lib/lwres/liblwres.@A@ DEPLIBS = ${DNSDEPLIBS} ${BIND9DEPLIBS} ${ISCDEPLIBS} \ ${ISCCFGDEPLIBS} ${LWRESDEPLIBS} LIBS = ${LWRESLIBS} ${BIND9LIBS} ${ISCCFGLIBS} \ ${ISCLIBS} @IDNLIBS@ @LIBS@ NOSYMLIBS = ${LWRESLIBS} ${BIND9LIBS} ${ISCCFGLIBS} \ ${ISCNOSYMLIBS} @IDNLIBS@ @LIBS@ SUBDIRS = TARGETS = dig@EXEEXT@ host@EXEEXT@ nslookup@EXEEXT@ OBJS = dig.@O@ dighost.@O@ host.@O@ nslookup.@O@ UOBJS = SRCS = dig.c dighost.c host.c nslookup.c MANPAGES = dig.1 host.1 nslookup.1 HTMLPAGES = dig.html host.html nslookup.html MANOBJS = ${MANPAGES} ${HTMLPAGES} @BIND9_MAKE_RULES@ dig@EXEEXT@: dig.@O@ dighost.@O@ ${UOBJS} ${DEPLIBS} export BASEOBJS="dig.@O@ dighost.@O@ ${UOBJS}"; \ export LIBS0="${DNSLIBS}"; \ ${FINALBUILDCMD} host@EXEEXT@: host.@O@ dighost.@O@ ${UOBJS} ${DEPLIBS} export BASEOBJS="host.@O@ dighost.@O@ ${UOBJS}"; \ export LIBS0="${DNSLIBS}"; \ ${FINALBUILDCMD} nslookup@EXEEXT@: nslookup.@O@ dighost.@O@ ${UOBJS} ${DEPLIBS} export BASEOBJS="nslookup.@O@ dighost.@O@ ${READLINE_LIB} ${UOBJS}"; \ export LIBS0="${DNSLIBS}"; \ ${FINALBUILDCMD} doc man:: ${MANOBJS} docclean manclean maintainer-clean:: rm -f ${MANOBJS} clean distclean maintainer-clean:: rm -f ${TARGETS} installdirs: $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${bindir} $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${mandir}/man1 install:: dig@EXEEXT@ host@EXEEXT@ nslookup@EXEEXT@ installdirs ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} \ dig@EXEEXT@ ${DESTDIR}${bindir} ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} \ host@EXEEXT@ ${DESTDIR}${bindir} ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} \ nslookup@EXEEXT@ ${DESTDIR}${bindir} for m in ${MANPAGES}; do \ ${INSTALL_DATA} ${srcdir}/$$m ${DESTDIR}${mandir}/man1; \ done uninstall:: for m in ${MANPAGES}; do \ rm -f ${DESTDIR}${mandir}/man1/$$m ; \ done ${LIBTOOL_MODE_UNINSTALL} rm -f ${DESTDIR}${bindir}/nslookup@EXEEXT@ ${LIBTOOL_MODE_UNINSTALL} rm -f ${DESTDIR}${bindir}/host@EXEEXT@ ${LIBTOOL_MODE_UNINSTALL} rm -f ${DESTDIR}${bindir}/dig@EXEEXT@ bind9-9.11.3+dfsg/bin/dig/dig.1000066400000000000000000000601131325250447100156750ustar00rootroot00000000000000.\" Copyright (C) 2000-2011, 2013-2018 Internet Systems Consortium, Inc. ("ISC") .\" .\" This Source Code Form is subject to the terms of the Mozilla Public .\" License, v. 2.0. If a copy of the MPL was not distributed with this .\" file, You can obtain one at http://mozilla.org/MPL/2.0/. .\" .hy 0 .ad l '\" t .\" Title: dig .\" Author: .\" Generator: DocBook XSL Stylesheets v1.78.1 .\" Date: 2014-02-19 .\" Manual: BIND9 .\" Source: ISC .\" Language: English .\" .TH "DIG" "1" "2014\-02\-19" "ISC" "BIND9" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" dig \- DNS lookup utility .SH "SYNOPSIS" .HP \w'\fBdig\fR\ 'u \fBdig\fR [@server] [\fB\-b\ \fR\fB\fIaddress\fR\fR] [\fB\-c\ \fR\fB\fIclass\fR\fR] [\fB\-f\ \fR\fB\fIfilename\fR\fR] [\fB\-k\ \fR\fB\fIfilename\fR\fR] [\fB\-m\fR] [\fB\-p\ \fR\fB\fIport#\fR\fR] [\fB\-q\ \fR\fB\fIname\fR\fR] [\fB\-t\ \fR\fB\fItype\fR\fR] [\fB\-v\fR] [\fB\-x\ \fR\fB\fIaddr\fR\fR] [\fB\-y\ \fR\fB\fI[hmac:]\fR\fIname:key\fR\fR] [[\fB\-4\fR] | [\fB\-6\fR]] [name] [type] [class] [queryopt...] .HP \w'\fBdig\fR\ 'u \fBdig\fR [\fB\-h\fR] .HP \w'\fBdig\fR\ 'u \fBdig\fR [global\-queryopt...] [query...] .SH "DESCRIPTION" .PP \fBdig\fR is a flexible tool for interrogating DNS name servers\&. It performs DNS lookups and displays the answers that are returned from the name server(s) that were queried\&. Most DNS administrators use \fBdig\fR to troubleshoot DNS problems because of its flexibility, ease of use and clarity of output\&. Other lookup tools tend to have less functionality than \fBdig\fR\&. .PP Although \fBdig\fR is normally used with command\-line arguments, it also has a batch mode of operation for reading lookup requests from a file\&. A brief summary of its command\-line arguments and options is printed when the \fB\-h\fR option is given\&. Unlike earlier versions, the BIND 9 implementation of \fBdig\fR allows multiple lookups to be issued from the command line\&. .PP Unless it is told to query a specific name server, \fBdig\fR will try each of the servers listed in /etc/resolv\&.conf\&. If no usable server addresses are found, \fBdig\fR will send the query to the local host\&. .PP When no command line arguments or options are given, \fBdig\fR will perform an NS query for "\&." (the root)\&. .PP It is possible to set per\-user defaults for \fBdig\fR via ${HOME}/\&.digrc\&. This file is read and any options in it are applied before the command line arguments\&. .PP The IN and CH class names overlap with the IN and CH top level domain names\&. Either use the \fB\-t\fR and \fB\-c\fR options to specify the type and class, use the \fB\-q\fR the specify the domain name, or use "IN\&." and "CH\&." when looking up these top level domains\&. .SH "SIMPLE USAGE" .PP A typical invocation of \fBdig\fR looks like: .sp .if n \{\ .RS 4 .\} .nf dig @server name type .fi .if n \{\ .RE .\} .sp where: .PP \fBserver\fR .RS 4 is the name or IP address of the name server to query\&. This can be an IPv4 address in dotted\-decimal notation or an IPv6 address in colon\-delimited notation\&. When the supplied \fIserver\fR argument is a hostname, \fBdig\fR resolves that name before querying that name server\&. .sp If no \fIserver\fR argument is provided, \fBdig\fR consults /etc/resolv\&.conf; if an address is found there, it queries the name server at that address\&. If either of the \fB\-4\fR or \fB\-6\fR options are in use, then only addresses for the corresponding transport will be tried\&. If no usable addresses are found, \fBdig\fR will send the query to the local host\&. The reply from the name server that responds is displayed\&. .RE .PP \fBname\fR .RS 4 is the name of the resource record that is to be looked up\&. .RE .PP \fBtype\fR .RS 4 indicates what type of query is required \(em ANY, A, MX, SIG, etc\&. \fItype\fR can be any valid query type\&. If no \fItype\fR argument is supplied, \fBdig\fR will perform a lookup for an A record\&. .RE .SH "OPTIONS" .PP \-4 .RS 4 Use IPv4 only\&. .RE .PP \-6 .RS 4 Use IPv6 only\&. .RE .PP \-b \fIaddress\fR\fI[#port]\fR .RS 4 Set the source IP address of the query\&. The \fIaddress\fR must be a valid address on one of the host\*(Aqs network interfaces, or "0\&.0\&.0\&.0" or "::"\&. An optional port may be specified by appending "#" .RE .PP \-c \fIclass\fR .RS 4 Set the query class\&. The default \fIclass\fR is IN; other classes are HS for Hesiod records or CH for Chaosnet records\&. .RE .PP \-f \fIfile\fR .RS 4 Batch mode: \fBdig\fR reads a list of lookup requests to process from the given \fIfile\fR\&. Each line in the file should be organized in the same way they would be presented as queries to \fBdig\fR using the command\-line interface\&. .RE .PP \-i .RS 4 Do reverse IPv6 lookups using the obsolete RFC1886 IP6\&.INT domain, which is no longer in use\&. Obsolete bit string label queries (RFC2874) are not attempted\&. .RE .PP \-k \fIkeyfile\fR .RS 4 Sign queries using TSIG using a key read from the given file\&. Key files can be generated using \fBtsig-keygen\fR(8)\&. When using TSIG authentication with \fBdig\fR, the name server that is queried needs to know the key and algorithm that is being used\&. In BIND, this is done by providing appropriate \fBkey\fR and \fBserver\fR statements in named\&.conf\&. .RE .PP \-m .RS 4 Enable memory usage debugging\&. .RE .PP \-p \fIport\fR .RS 4 Send the query to a non\-standard port on the server, instead of the default port 53\&. This option would be used to test a name server that has been configured to listen for queries on a non\-standard port number\&. .RE .PP \-q \fIname\fR .RS 4 The domain name to query\&. This is useful to distinguish the \fIname\fR from other arguments\&. .RE .PP \-t \fItype\fR .RS 4 The resource record type to query\&. It can be any valid query type which is supported in BIND 9\&. The default query type is "A", unless the \fB\-x\fR option is supplied to indicate a reverse lookup\&. A zone transfer can be requested by specifying a type of AXFR\&. When an incremental zone transfer (IXFR) is required, set the \fItype\fR to ixfr=N\&. The incremental zone transfer will contain the changes made to the zone since the serial number in the zone\*(Aqs SOA record was \fIN\fR\&. .RE .PP \-u .RS 4 Print query times in microseconds instead of milliseconds\&. .RE .PP \-v .RS 4 Print the version number and exit\&. .RE .PP \-x \fIaddr\fR .RS 4 Simplified reverse lookups, for mapping addresses to names\&. The \fIaddr\fR is an IPv4 address in dotted\-decimal notation, or a colon\-delimited IPv6 address\&. When the \fB\-x\fR is used, there is no need to provide the \fIname\fR, \fIclass\fR and \fItype\fR arguments\&. \fBdig\fR automatically performs a lookup for a name like 94\&.2\&.0\&.192\&.in\-addr\&.arpa and sets the query type and class to PTR and IN respectively\&. IPv6 addresses are looked up using nibble format under the IP6\&.ARPA domain (but see also the \fB\-i\fR option)\&. .RE .PP \-y \fI[hmac:]\fR\fIkeyname:secret\fR .RS 4 Sign queries using TSIG with the given authentication key\&. \fIkeyname\fR is the name of the key, and \fIsecret\fR is the base64 encoded shared secret\&. \fIhmac\fR is the name of the key algorithm; valid choices are hmac\-md5, hmac\-sha1, hmac\-sha224, hmac\-sha256, hmac\-sha384, or hmac\-sha512\&. If \fIhmac\fR is not specified, the default is hmac\-md5 or if MD5 was disabled hmac\-sha256\&. .sp NOTE: You should use the \fB\-k\fR option and avoid the \fB\-y\fR option, because with \fB\-y\fR the shared secret is supplied as a command line argument in clear text\&. This may be visible in the output from \fBps\fR(1) or in a history file maintained by the user\*(Aqs shell\&. .RE .SH "QUERY OPTIONS" .PP \fBdig\fR provides a number of query options which affect the way in which lookups are made and the results displayed\&. Some of these set or reset flag bits in the query header, some determine which sections of the answer get printed, and others determine the timeout and retry strategies\&. .PP Each query option is identified by a keyword preceded by a plus sign (+)\&. Some keywords set or reset an option\&. These may be preceded by the string no to negate the meaning of that keyword\&. Other keywords assign values to options like the timeout interval\&. They have the form \fB+keyword=value\fR\&. Keywords may be abbreviated, provided the abbreviation is unambiguous; for example, +cd is equivalent to +cdflag\&. The query options are: .PP \fB+[no]aaflag\fR .RS 4 A synonym for \fI+[no]aaonly\fR\&. .RE .PP \fB+[no]aaonly\fR .RS 4 Sets the "aa" flag in the query\&. .RE .PP \fB+[no]additional\fR .RS 4 Display [do not display] the additional section of a reply\&. The default is to display it\&. .RE .PP \fB+[no]adflag\fR .RS 4 Set [do not set] the AD (authentic data) bit in the query\&. This requests the server to return whether all of the answer and authority sections have all been validated as secure according to the security policy of the server\&. AD=1 indicates that all records have been validated as secure and the answer is not from a OPT\-OUT range\&. AD=0 indicate that some part of the answer was insecure or not validated\&. This bit is set by default\&. .RE .PP \fB+[no]all\fR .RS 4 Set or clear all display flags\&. .RE .PP \fB+[no]answer\fR .RS 4 Display [do not display] the answer section of a reply\&. The default is to display it\&. .RE .PP \fB+[no]authority\fR .RS 4 Display [do not display] the authority section of a reply\&. The default is to display it\&. .RE .PP \fB+[no]badcookie\fR .RS 4 Retry lookup with the new server cookie if a BADCOOKIE response is received\&. .RE .PP \fB+[no]besteffort\fR .RS 4 Attempt to display the contents of messages which are malformed\&. The default is to not display malformed answers\&. .RE .PP \fB+bufsize=B\fR .RS 4 Set the UDP message buffer size advertised using EDNS0 to \fIB\fR bytes\&. The maximum and minimum sizes of this buffer are 65535 and 0 respectively\&. Values outside this range are rounded up or down appropriately\&. Values other than zero will cause a EDNS query to be sent\&. .RE .PP \fB+[no]cdflag\fR .RS 4 Set [do not set] the CD (checking disabled) bit in the query\&. This requests the server to not perform DNSSEC validation of responses\&. .RE .PP \fB+[no]class\fR .RS 4 Display [do not display] the CLASS when printing the record\&. .RE .PP \fB+[no]cmd\fR .RS 4 Toggles the printing of the initial comment in the output identifying the version of \fBdig\fR and the query options that have been applied\&. This comment is printed by default\&. .RE .PP \fB+[no]comments\fR .RS 4 Toggle the display of comment lines in the output\&. The default is to print comments\&. .RE .PP \fB+[no]cookie\fR\fB[=####]\fR .RS 4 Send a COOKIE EDNS option, with optional value\&. Replaying a COOKIE from a previous response will allow the server to identify a previous client\&. The default is \fB+cookie\fR\&. .sp \fB+cookie\fR is also set when +trace is set to better emulate the default queries from a nameserver\&. .RE .PP \fB+[no]crypto\fR .RS 4 Toggle the display of cryptographic fields in DNSSEC records\&. The contents of these field are unnecessary to debug most DNSSEC validation failures and removing them makes it easier to see the common failures\&. The default is to display the fields\&. When omitted they are replaced by the string "[omitted]" or in the DNSKEY case the key id is displayed as the replacement, e\&.g\&. "[ key id = value ]"\&. .RE .PP \fB+[no]defname\fR .RS 4 Deprecated, treated as a synonym for \fI+[no]search\fR .RE .PP \fB+[no]dnssec\fR .RS 4 Requests DNSSEC records be sent by setting the DNSSEC OK bit (DO) in the OPT record in the additional section of the query\&. .RE .PP \fB+domain=somename\fR .RS 4 Set the search list to contain the single domain \fIsomename\fR, as if specified in a \fBdomain\fR directive in /etc/resolv\&.conf, and enable search list processing as if the \fI+search\fR option were given\&. .RE .PP \fB+dscp=value\fR .RS 4 Set the DSCP code point to be used when sending the query\&. Valid DSCP code points are in the range [0\&.\&.63]\&. By default no code point is explicitly set\&. .RE .PP \fB+[no]edns[=#]\fR .RS 4 Specify the EDNS version to query with\&. Valid values are 0 to 255\&. Setting the EDNS version will cause a EDNS query to be sent\&. \fB+noedns\fR clears the remembered EDNS version\&. EDNS is set to 0 by default\&. .RE .PP \fB+[no]ednsflags[=#]\fR .RS 4 Set the must\-be\-zero EDNS flags bits (Z bits) to the specified value\&. Decimal, hex and octal encodings are accepted\&. Setting a named flag (e\&.g\&. DO) will silently be ignored\&. By default, no Z bits are set\&. .RE .PP \fB+[no]ednsnegotiation\fR .RS 4 Enable / disable EDNS version negotiation\&. By default EDNS version negotiation is enabled\&. .RE .PP \fB+[no]ednsopt[=code[:value]]\fR .RS 4 Specify EDNS option with code point \fBcode\fR and optionally payload of \fBvalue\fR as a hexadecimal string\&. \fBcode\fR can be either an EDNS option name (for example, NSID or ECS), or an arbitrary numeric value\&. \fB+noednsopt\fR clears the EDNS options to be sent\&. .RE .PP \fB+[no]expire\fR .RS 4 Send an EDNS Expire option\&. .RE .PP \fB+[no]fail\fR .RS 4 Do not try the next server if you receive a SERVFAIL\&. The default is to not try the next server which is the reverse of normal stub resolver behavior\&. .RE .PP \fB+[no]header\-only\fR .RS 4 Send a query with a DNS header without a question section\&. The default is to add a question section\&. The query type and query name are ignored when this is set\&. .RE .PP \fB+[no]identify\fR .RS 4 Show [or do not show] the IP address and port number that supplied the answer when the \fI+short\fR option is enabled\&. If short form answers are requested, the default is not to show the source address and port number of the server that provided the answer\&. .RE .PP \fB+[no]idnout\fR .RS 4 Convert [do not convert] puny code on output\&. This requires IDN SUPPORT to have been enabled at compile time\&. The default is to convert output\&. .RE .PP \fB+[no]ignore\fR .RS 4 Ignore truncation in UDP responses instead of retrying with TCP\&. By default, TCP retries are performed\&. .RE .PP \fB+[no]keepopen\fR .RS 4 Keep the TCP socket open between queries and reuse it rather than creating a new TCP socket for each lookup\&. The default is \fB+nokeepopen\fR\&. .RE .PP \fB+[no]mapped\fR .RS 4 Allow mapped IPv4 over IPv6 addresses to be used\&. The default is \fB+mapped\fR\&. .RE .PP \fB+[no]multiline\fR .RS 4 Print records like the SOA records in a verbose multi\-line format with human\-readable comments\&. The default is to print each record on a single line, to facilitate machine parsing of the \fBdig\fR output\&. .RE .PP \fB+ndots=D\fR .RS 4 Set the number of dots that have to appear in \fIname\fR to \fID\fR for it to be considered absolute\&. The default value is that defined using the ndots statement in /etc/resolv\&.conf, or 1 if no ndots statement is present\&. Names with fewer dots are interpreted as relative names and will be searched for in the domains listed in the \fBsearch\fR or \fBdomain\fR directive in /etc/resolv\&.conf if \fB+search\fR is set\&. .RE .PP \fB+[no]nsid\fR .RS 4 Include an EDNS name server ID request when sending a query\&. .RE .PP \fB+[no]nssearch\fR .RS 4 When this option is set, \fBdig\fR attempts to find the authoritative name servers for the zone containing the name being looked up and display the SOA record that each name server has for the zone\&. .RE .PP \fB+[no]onesoa\fR .RS 4 Print only one (starting) SOA record when performing an AXFR\&. The default is to print both the starting and ending SOA records\&. .RE .PP \fB+[no]opcode=value\fR .RS 4 Set [restore] the DNS message opcode to the specified value\&. The default value is QUERY (0)\&. .RE .PP \fB+[no]qr\fR .RS 4 Print [do not print] the query as it is sent\&. By default, the query is not printed\&. .RE .PP \fB+[no]question\fR .RS 4 Print [do not print] the question section of a query when an answer is returned\&. The default is to print the question section as a comment\&. .RE .PP \fB+[no]rdflag\fR .RS 4 A synonym for \fI+[no]recurse\fR\&. .RE .PP \fB+[no]recurse\fR .RS 4 Toggle the setting of the RD (recursion desired) bit in the query\&. This bit is set by default, which means \fBdig\fR normally sends recursive queries\&. Recursion is automatically disabled when the \fI+nssearch\fR or \fI+trace\fR query options are used\&. .RE .PP \fB+retry=T\fR .RS 4 Sets the number of times to retry UDP queries to server to \fIT\fR instead of the default, 2\&. Unlike \fI+tries\fR, this does not include the initial query\&. .RE .PP \fB+[no]rrcomments\fR .RS 4 Toggle the display of per\-record comments in the output (for example, human\-readable key information about DNSKEY records)\&. The default is not to print record comments unless multiline mode is active\&. .RE .PP \fB+[no]search\fR .RS 4 Use [do not use] the search list defined by the searchlist or domain directive in resolv\&.conf (if any)\&. The search list is not used by default\&. .sp \*(Aqndots\*(Aq from resolv\&.conf (default 1) which may be overridden by \fI+ndots\fR determines if the name will be treated as relative or not and hence whether a search is eventually performed or not\&. .RE .PP \fB+[no]short\fR .RS 4 Provide a terse answer\&. The default is to print the answer in a verbose form\&. .RE .PP \fB+[no]showsearch\fR .RS 4 Perform [do not perform] a search showing intermediate results\&. .RE .PP \fB+[no]sigchase\fR .RS 4 Chase DNSSEC signature chains\&. Requires dig be compiled with \-DDIG_SIGCHASE\&. This feature is deprecated\&. Use \fBdelv\fR instead\&. .RE .PP \fB+split=W\fR .RS 4 Split long hex\- or base64\-formatted fields in resource records into chunks of \fIW\fR characters (where \fIW\fR is rounded up to the nearest multiple of 4)\&. \fI+nosplit\fR or \fI+split=0\fR causes fields not to be split at all\&. The default is 56 characters, or 44 characters when multiline mode is active\&. .RE .PP \fB+[no]stats\fR .RS 4 This query option toggles the printing of statistics: when the query was made, the size of the reply and so on\&. The default behavior is to print the query statistics\&. .RE .PP \fB+[no]subnet=addr[/prefix\-length]\fR .RS 4 Send (don\*(Aqt send) an EDNS Client Subnet option with the specified IP address or network prefix\&. .sp \fBdig +subnet=0\&.0\&.0\&.0/0\fR, or simply \fBdig +subnet=0\fR for short, sends an EDNS CLIENT\-SUBNET option with an empty address and a source prefix\-length of zero, which signals a resolver that the client\*(Aqs address information must \fInot\fR be used when resolving this query\&. .RE .PP \fB+[no]tcp\fR .RS 4 Use [do not use] TCP when querying name servers\&. The default behavior is to use UDP unless a type any or ixfr=N query is requested, in which case the default is TCP\&. AXFR queries always use TCP\&. .RE .PP \fB+timeout=T\fR .RS 4 Sets the timeout for a query to \fIT\fR seconds\&. The default timeout is 5 seconds\&. An attempt to set \fIT\fR to less than 1 will result in a query timeout of 1 second being applied\&. .RE .PP \fB+[no]topdown\fR .RS 4 When chasing DNSSEC signature chains perform a top\-down validation\&. Requires dig be compiled with \-DDIG_SIGCHASE\&. This feature is deprecated\&. Use \fBdelv\fR instead\&. .RE .PP \fB+[no]trace\fR .RS 4 Toggle tracing of the delegation path from the root name servers for the name being looked up\&. Tracing is disabled by default\&. When tracing is enabled, \fBdig\fR makes iterative queries to resolve the name being looked up\&. It will follow referrals from the root servers, showing the answer from each server that was used to resolve the lookup\&. .sp If @server is also specified, it affects only the initial query for the root zone name servers\&. .sp \fB+dnssec\fR is also set when +trace is set to better emulate the default queries from a nameserver\&. .RE .PP \fB+tries=T\fR .RS 4 Sets the number of times to try UDP queries to server to \fIT\fR instead of the default, 3\&. If \fIT\fR is less than or equal to zero, the number of tries is silently rounded up to 1\&. .RE .PP \fB+trusted\-key=####\fR .RS 4 Specifies a file containing trusted keys to be used with \fB+sigchase\fR\&. Each DNSKEY record must be on its own line\&. .sp If not specified, \fBdig\fR will look for /etc/trusted\-key\&.key then trusted\-key\&.key in the current directory\&. .sp Requires dig be compiled with \-DDIG_SIGCHASE\&. This feature is deprecated\&. Use \fBdelv\fR instead\&. .RE .PP \fB+[no]ttlid\fR .RS 4 Display [do not display] the TTL when printing the record\&. .RE .PP \fB+[no]ttlunits\fR .RS 4 Display [do not display] the TTL in friendly human\-readable time units of "s", "m", "h", "d", and "w", representing seconds, minutes, hours, days and weeks\&. Implies +ttlid\&. .RE .PP \fB+[no]unknownformat\fR .RS 4 Print all RDATA in unknown RR type presentation format (RFC 3597)\&. The default is to print RDATA for known types in the type\*(Aqs presentation format\&. .RE .PP \fB+[no]vc\fR .RS 4 Use [do not use] TCP when querying name servers\&. This alternate syntax to \fI+[no]tcp\fR is provided for backwards compatibility\&. The "vc" stands for "virtual circuit"\&. .RE .PP \fB+[no]zflag\fR .RS 4 Set [do not set] the last unassigned DNS header flag in a DNS query\&. This flag is off by default\&. .RE .SH "MULTIPLE QUERIES" .PP The BIND 9 implementation of \fBdig \fR supports specifying multiple queries on the command line (in addition to supporting the \fB\-f\fR batch file option)\&. Each of those queries can be supplied with its own set of flags, options and query options\&. .PP In this case, each \fIquery\fR argument represent an individual query in the command\-line syntax described above\&. Each consists of any of the standard options and flags, the name to be looked up, an optional query type and class and any query options that should be applied to that query\&. .PP A global set of query options, which should be applied to all queries, can also be supplied\&. These global query options must precede the first tuple of name, class, type, options, flags, and query options supplied on the command line\&. Any global query options (except the \fB+[no]cmd\fR option) can be overridden by a query\-specific set of query options\&. For example: .sp .if n \{\ .RS 4 .\} .nf dig +qr www\&.isc\&.org any \-x 127\&.0\&.0\&.1 isc\&.org ns +noqr .fi .if n \{\ .RE .\} .sp shows how \fBdig\fR could be used from the command line to make three lookups: an ANY query for www\&.isc\&.org, a reverse lookup of 127\&.0\&.0\&.1 and a query for the NS records of isc\&.org\&. A global query option of \fI+qr\fR is applied, so that \fBdig\fR shows the initial query it made for each lookup\&. The final query has a local query option of \fI+noqr\fR which means that \fBdig\fR will not print the initial query when it looks up the NS records for isc\&.org\&. .SH "IDN SUPPORT" .PP If \fBdig\fR has been built with IDN (internationalized domain name) support, it can accept and display non\-ASCII domain names\&. \fBdig\fR appropriately converts character encoding of domain name before sending a request to DNS server or displaying a reply from the server\&. If you\*(Aqd like to turn off the IDN support for some reason, defines the \fBIDN_DISABLE\fR environment variable\&. The IDN support is disabled if the variable is set when \fBdig\fR runs\&. .SH "FILES" .PP /etc/resolv\&.conf .PP ${HOME}/\&.digrc .SH "SEE ALSO" .PP \fBdelv\fR(1), \fBhost\fR(1), \fBnamed\fR(8), \fBdnssec-keygen\fR(8), RFC1035\&. .SH "BUGS" .PP There are probably too many query options\&. .SH "AUTHOR" .PP \fBInternet Systems Consortium, Inc\&.\fR .SH "COPYRIGHT" .br Copyright \(co 2000-2011, 2013-2018 Internet Systems Consortium, Inc. ("ISC") .br bind9-9.11.3+dfsg/bin/dig/dig.c000066400000000000000000001655261325250447100157750ustar00rootroot00000000000000/* * Copyright (C) 2000-2017 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /*! \file */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define ADD_STRING(b, s) { \ if (strlen(s) >= isc_buffer_availablelength(b)) \ return (ISC_R_NOSPACE); \ else \ isc_buffer_putstr(b, s); \ } #define DIG_MAX_ADDRESSES 20 dig_lookup_t *default_lookup = NULL; static char *batchname = NULL; static FILE *batchfp = NULL; static char *argv0; static int addresscount = 0; static char domainopt[DNS_NAME_MAXTEXT]; static char hexcookie[81]; static isc_boolean_t short_form = ISC_FALSE, printcmd = ISC_TRUE, ip6_int = ISC_FALSE, plusquest = ISC_FALSE, pluscomm = ISC_FALSE, multiline = ISC_FALSE, nottl = ISC_FALSE, noclass = ISC_FALSE, onesoa = ISC_FALSE, use_usec = ISC_FALSE, nocrypto = ISC_FALSE, ttlunits = ISC_FALSE, ipv4only = ISC_FALSE, ipv6only = ISC_FALSE; static isc_uint32_t splitwidth = 0xffffffff; /*% rrcomments are neither explicitly enabled nor disabled by default */ static int rrcomments = 0; /*% opcode text */ static const char * const opcodetext[] = { "QUERY", "IQUERY", "STATUS", "RESERVED3", "NOTIFY", "UPDATE", "RESERVED6", "RESERVED7", "RESERVED8", "RESERVED9", "RESERVED10", "RESERVED11", "RESERVED12", "RESERVED13", "RESERVED14", "RESERVED15" }; static const char * rcode_totext(dns_rcode_t rcode) { static char buf[64]; isc_buffer_t b; isc_result_t result; memset(buf, 0, sizeof(buf)); isc_buffer_init(&b, buf + 1, sizeof(buf) - 2); result = dns_rcode_totext(rcode, &b); RUNTIME_CHECK(result == ISC_R_SUCCESS); if (strspn(buf + 1, "0123456789") == strlen(buf + 1)) { buf[0] = '?'; return(buf); } return (buf + 1); } /*% print usage */ static void print_usage(FILE *fp) { fputs( "Usage: dig [@global-server] [domain] [q-type] [q-class] {q-opt}\n" " {global-d-opt} host [@local-server] {local-d-opt}\n" " [ host [@local-server] {local-d-opt} [...]]\n", fp); } ISC_PLATFORM_NORETURN_PRE static void usage(void) ISC_PLATFORM_NORETURN_POST; static void usage(void) { print_usage(stderr); fputs("\nUse \"dig -h\" (or \"dig -h | more\") " "for complete list of options\n", stderr); exit(1); } /*% version */ static void version(void) { fputs("DiG " VERSION "\n", stderr); } /*% help */ static void help(void) { print_usage(stdout); fputs( "Where: domain is in the Domain Name System\n" " q-class is one of (in,hs,ch,...) [default: in]\n" " q-type is one of (a,any,mx,ns,soa,hinfo,axfr,txt,...) [default:a]\n" " (Use ixfr=version for type ixfr)\n" " q-opt is one of:\n" " -4 (use IPv4 query transport only)\n" " -6 (use IPv6 query transport only)\n" " -b address[#port] (bind to source address/port)\n" " -c class (specify query class)\n" " -f filename (batch mode)\n" " -i (use IP6.INT for IPv6 reverse lookups)\n" " -k keyfile (specify tsig key file)\n" " -m (enable memory usage debugging)\n" " -p port (specify port number)\n" " -q name (specify query name)\n" " -t type (specify query type)\n" " -u (display times in usec instead of msec)\n" " -x dot-notation (shortcut for reverse lookups)\n" " -y [hmac:]name:key (specify named base64 tsig key)\n" " d-opt is of the form +keyword[=value], where keyword is:\n" " +[no]aaflag (Set AA flag in query (+[no]aaflag))\n" " +[no]aaonly (Set AA flag in query (+[no]aaflag))\n" " +[no]additional (Control display of additional section)\n" " +[no]adflag (Set AD flag in query (default on))\n" " +[no]all (Set or clear all display flags)\n" " +[no]answer (Control display of answer section)\n" " +[no]authority (Control display of authority section)\n" " +[no]badcookie (Retry BADCOOKIE responses)\n" " +[no]besteffort (Try to parse even illegal messages)\n" " +bufsize=### (Set EDNS0 Max UDP packet size)\n" " +[no]cdflag (Set checking disabled flag in query)\n" " +[no]class (Control display of class in records)\n" " +[no]cmd (Control display of command line)\n" " +[no]comments (Control display of comment lines)\n" " +[no]cookie (Add a COOKIE option to the request)\n" " +[no]crypto (Control display of cryptographic " "fields in records)\n" " +[no]defname (Use search list (+[no]search))\n" " +[no]dnssec (Request DNSSEC records)\n" " +domain=### (Set default domainname)\n" " +[no]dscp[=###] (Set the DSCP value to ### [0..63])\n" " +[no]edns[=###] (Set EDNS version) [0]\n" " +ednsflags=### (Set EDNS flag bits)\n" " +[no]ednsnegotiation (Set EDNS version negotiation)\n" " +ednsopt=###[:value] (Send specified EDNS option)\n" " +noednsopt (Clear list of +ednsopt options)\n" " +[no]expire (Request time to expire)\n" " +[no]fail (Don't try next server on SERVFAIL)\n" " +[no]header-only (Send query without a question section)\n" " +[no]identify (ID responders in short answers)\n" " +[no]idnout (convert IDN response)\n" " +[no]ignore (Don't revert to TCP for TC responses.)\n" " +[no]keepopen (Keep the TCP socket open between queries)\n" " +[no]mapped (Allow mapped IPv4 over IPv6)\n" " +[no]multiline (Print records in an expanded format)\n" " +ndots=### (Set search NDOTS value)\n" " +[no]nsid (Request Name Server ID)\n" " +[no]nssearch (Search all authoritative nameservers)\n" " +[no]onesoa (AXFR prints only one soa record)\n" " +[no]opcode=### (Set the opcode of the request)\n" " +[no]qr (Print question before sending)\n" " +[no]question (Control display of question section)\n" " +[no]rdflag (Recursive mode (+[no]recurse))\n" " +[no]recurse (Recursive mode (+[no]rdflag))\n" " +retry=### (Set number of UDP retries) [2]\n" " +[no]rrcomments (Control display of per-record " "comments)\n" " +[no]search (Set whether to use searchlist)\n" " +[no]short (Display nothing except short\n" " form of answer)\n" " +[no]showsearch (Search with intermediate results)\n" #ifdef DIG_SIGCHASE " +[no]sigchase (Chase DNSSEC signatures)\n" #endif " +[no]split=## (Split hex/base64 fields into chunks)\n" " +[no]stats (Control display of statistics)\n" " +subnet=addr (Set edns-client-subnet option)\n" " +[no]tcp (TCP mode (+[no]vc))\n" " +timeout=### (Set query timeout) [5]\n" #if defined(DIG_SIGCHASE) && DIG_SIGCHASE_TD " +[no]topdown (Do +sigchase in top-down mode)\n" #endif " +[no]trace (Trace delegation down from root [+dnssec])\n" #ifdef DIG_SIGCHASE " +trusted-key=#### (Trusted Key to use with +sigchase)\n" #endif " +tries=### (Set number of UDP attempts) [3]\n" " +[no]ttlid (Control display of ttls in records)\n" " +[no]ttlunits (Display TTLs in human-readable units)\n" " +[no]unknownformat (Print RDATA in RFC 3597 \"unknown\" format)\n" " +[no]vc (TCP mode (+[no]tcp))\n" " +[no]zflag (Set Z flag in query)\n" " global d-opts and servers (before host name) affect all queries.\n" " local d-opts and servers (after host name) affect only that lookup.\n" " -h (print help and exit)\n" " -v (print version and exit)\n", stdout); } /*% * Callback from dighost.c to print the received message. */ static void received(int bytes, isc_sockaddr_t *from, dig_query_t *query) { isc_uint64_t diff; time_t tnow; struct tm tmnow; #ifdef WIN32 wchar_t time_str[100]; #else char time_str[100]; #endif char fromtext[ISC_SOCKADDR_FORMATSIZE]; isc_sockaddr_format(from, fromtext, sizeof(fromtext)); if (query->lookup->stats && !short_form) { diff = isc_time_microdiff(&query->time_recv, &query->time_sent); if (use_usec) printf(";; Query time: %ld usec\n", (long) diff); else printf(";; Query time: %ld msec\n", (long) diff / 1000); printf(";; SERVER: %s(%s)\n", fromtext, query->servname); time(&tnow); #if defined(ISC_PLATFORM_USETHREADS) && !defined(WIN32) (void)localtime_r(&tnow, &tmnow); #else tmnow = *localtime(&tnow); #endif #ifdef WIN32 /* * On Windows, time zone name ("%Z") may be a localized * wide-character string, which strftime() handles incorrectly. */ if (wcsftime(time_str, sizeof(time_str)/sizeof(time_str[0]), L"%a %b %d %H:%M:%S %Z %Y", &tmnow) > 0U) printf(";; WHEN: %ls\n", time_str); #else if (strftime(time_str, sizeof(time_str), "%a %b %d %H:%M:%S %Z %Y", &tmnow) > 0U) printf(";; WHEN: %s\n", time_str); #endif if (query->lookup->doing_xfr) { printf(";; XFR size: %u records (messages %u, " "bytes %" ISC_PRINT_QUADFORMAT "u)\n", query->rr_count, query->msg_count, query->byte_count); } else { printf(";; MSG SIZE rcvd: %u\n", bytes); } if (key != NULL) { if (!validated) puts(";; WARNING -- Some TSIG could not " "be validated"); } if ((key == NULL) && (keysecret[0] != 0)) { puts(";; WARNING -- TSIG key was not used."); } puts(""); } else if (query->lookup->identify && !short_form) { diff = isc_time_microdiff(&query->time_recv, &query->time_sent); if (use_usec) printf(";; Received %" ISC_PRINT_QUADFORMAT "u bytes " "from %s(%s) in %ld us\n\n", query->lookup->doing_xfr ? query->byte_count : (isc_uint64_t)bytes, fromtext, query->userarg, (long) diff); else printf(";; Received %" ISC_PRINT_QUADFORMAT "u bytes " "from %s(%s) in %ld ms\n\n", query->lookup->doing_xfr ? query->byte_count : (isc_uint64_t)bytes, fromtext, query->userarg, (long) diff / 1000); } } /* * Callback from dighost.c to print that it is trying a server. * Not used in dig. * XXX print_trying */ static void trying(char *frm, dig_lookup_t *lookup) { UNUSED(frm); UNUSED(lookup); } /*% * Internal print routine used to print short form replies. */ static isc_result_t say_message(dns_rdata_t *rdata, dig_query_t *query, isc_buffer_t *buf) { isc_result_t result; isc_uint64_t diff; char store[sizeof(" in 18446744073709551616 us.")]; unsigned int styleflags = 0; if (query->lookup->trace || query->lookup->ns_search_only) { result = dns_rdatatype_totext(rdata->type, buf); if (result != ISC_R_SUCCESS) return (result); ADD_STRING(buf, " "); } /* Turn on rrcomments if explicitly enabled */ if (rrcomments > 0) styleflags |= DNS_STYLEFLAG_RRCOMMENT; if (nocrypto) styleflags |= DNS_STYLEFLAG_NOCRYPTO; if (query->lookup->print_unknown_format) styleflags |= DNS_STYLEFLAG_UNKNOWNFORMAT; result = dns_rdata_tofmttext(rdata, NULL, styleflags, 0, splitwidth, " ", buf); if (result == ISC_R_NOSPACE) return (result); check_result(result, "dns_rdata_totext"); if (query->lookup->identify) { diff = isc_time_microdiff(&query->time_recv, &query->time_sent); ADD_STRING(buf, " from server "); ADD_STRING(buf, query->servname); if (use_usec) snprintf(store, sizeof(store), " in %" ISC_PLATFORM_QUADFORMAT "u us.", diff); else snprintf(store, sizeof(store), " in %" ISC_PLATFORM_QUADFORMAT "u ms.", diff / 1000); ADD_STRING(buf, store); } ADD_STRING(buf, "\n"); return (ISC_R_SUCCESS); } /*% * short_form message print handler. Calls above say_message() */ static isc_result_t short_answer(dns_message_t *msg, dns_messagetextflag_t flags, isc_buffer_t *buf, dig_query_t *query) { dns_name_t *name; dns_rdataset_t *rdataset; isc_result_t result, loopresult; dns_name_t empty_name; dns_rdata_t rdata = DNS_RDATA_INIT; UNUSED(flags); dns_name_init(&empty_name, NULL); result = dns_message_firstname(msg, DNS_SECTION_ANSWER); if (result == ISC_R_NOMORE) return (ISC_R_SUCCESS); else if (result != ISC_R_SUCCESS) return (result); for (;;) { name = NULL; dns_message_currentname(msg, DNS_SECTION_ANSWER, &name); for (rdataset = ISC_LIST_HEAD(name->list); rdataset != NULL; rdataset = ISC_LIST_NEXT(rdataset, link)) { loopresult = dns_rdataset_first(rdataset); while (loopresult == ISC_R_SUCCESS) { dns_rdataset_current(rdataset, &rdata); result = say_message(&rdata, query, buf); if (result == ISC_R_NOSPACE) return (result); check_result(result, "say_message"); loopresult = dns_rdataset_next(rdataset); dns_rdata_reset(&rdata); } } result = dns_message_nextname(msg, DNS_SECTION_ANSWER); if (result == ISC_R_NOMORE) break; else if (result != ISC_R_SUCCESS) return (result); } return (ISC_R_SUCCESS); } #ifdef DIG_SIGCHASE static isc_result_t printrdataset(dns_name_t *owner_name, dns_rdataset_t *rdataset, isc_buffer_t *target) { isc_result_t result; dns_master_style_t *style = NULL; unsigned int styleflags = 0; if (rdataset == NULL || owner_name == NULL || target == NULL) return(ISC_FALSE); styleflags |= DNS_STYLEFLAG_REL_OWNER; if (ttlunits) styleflags |= DNS_STYLEFLAG_TTL_UNITS; if (nottl) styleflags |= DNS_STYLEFLAG_NO_TTL; if (noclass) styleflags |= DNS_STYLEFLAG_NO_CLASS; if (nocrypto) styleflags |= DNS_STYLEFLAG_NOCRYPTO; /* Turn on rrcomments if explicitly enabled */ if (rrcomments > 0) styleflags |= DNS_STYLEFLAG_RRCOMMENT; if (multiline) { styleflags |= DNS_STYLEFLAG_OMIT_OWNER; styleflags |= DNS_STYLEFLAG_OMIT_CLASS; styleflags |= DNS_STYLEFLAG_REL_DATA; styleflags |= DNS_STYLEFLAG_OMIT_TTL; styleflags |= DNS_STYLEFLAG_TTL; styleflags |= DNS_STYLEFLAG_MULTILINE; styleflags |= DNS_STYLEFLAG_COMMENT; /* Turn on rrcomments if not explicitly disabled */ if (rrcomments >= 0) styleflags |= DNS_STYLEFLAG_RRCOMMENT; } if (multiline || (nottl && noclass)) result = dns_master_stylecreate2(&style, styleflags, 24, 24, 24, 32, 80, 8, splitwidth, mctx); else if (nottl || noclass) result = dns_master_stylecreate2(&style, styleflags, 24, 24, 32, 40, 80, 8, splitwidth, mctx); else result = dns_master_stylecreate2(&style, styleflags, 24, 32, 40, 48, 80, 8, splitwidth, mctx); check_result(result, "dns_master_stylecreate"); result = dns_master_rdatasettotext(owner_name, rdataset, style, target); if (style != NULL) dns_master_styledestroy(&style, mctx); return(result); } #endif static isc_boolean_t isdotlocal(dns_message_t *msg) { isc_result_t result; static unsigned char local_ndata[] = { "\005local\0" }; static unsigned char local_offsets[] = { 0, 6 }; static dns_name_t local = DNS_NAME_INITABSOLUTE(local_ndata, local_offsets); for (result = dns_message_firstname(msg, DNS_SECTION_QUESTION); result == ISC_R_SUCCESS; result = dns_message_nextname(msg, DNS_SECTION_QUESTION)) { dns_name_t *name = NULL; dns_message_currentname(msg, DNS_SECTION_QUESTION, &name); if (dns_name_issubdomain(name, &local)) return (ISC_TRUE); } return (ISC_FALSE); } /* * Callback from dighost.c to print the reply from a server */ static isc_result_t printmessage(dig_query_t *query, dns_message_t *msg, isc_boolean_t headers) { isc_result_t result; dns_messagetextflag_t flags; isc_buffer_t *buf = NULL; unsigned int len = OUTPUTBUF; dns_master_style_t *style = NULL; unsigned int styleflags = 0; styleflags |= DNS_STYLEFLAG_REL_OWNER; if (query->lookup->comments) styleflags |= DNS_STYLEFLAG_COMMENT; if (query->lookup->print_unknown_format) styleflags |= DNS_STYLEFLAG_UNKNOWNFORMAT; /* Turn on rrcomments if explicitly enabled */ if (rrcomments > 0) styleflags |= DNS_STYLEFLAG_RRCOMMENT; if (ttlunits) styleflags |= DNS_STYLEFLAG_TTL_UNITS; if (nottl) styleflags |= DNS_STYLEFLAG_NO_TTL; if (noclass) styleflags |= DNS_STYLEFLAG_NO_CLASS; if (nocrypto) styleflags |= DNS_STYLEFLAG_NOCRYPTO; if (multiline) { styleflags |= DNS_STYLEFLAG_OMIT_OWNER; styleflags |= DNS_STYLEFLAG_OMIT_CLASS; styleflags |= DNS_STYLEFLAG_REL_DATA; styleflags |= DNS_STYLEFLAG_OMIT_TTL; styleflags |= DNS_STYLEFLAG_TTL; styleflags |= DNS_STYLEFLAG_MULTILINE; /* Turn on rrcomments unless explicitly disabled */ if (rrcomments >= 0) styleflags |= DNS_STYLEFLAG_RRCOMMENT; } if (multiline || (nottl && noclass)) result = dns_master_stylecreate2(&style, styleflags, 24, 24, 24, 32, 80, 8, splitwidth, mctx); else if (nottl || noclass) result = dns_master_stylecreate2(&style, styleflags, 24, 24, 32, 40, 80, 8, splitwidth, mctx); else result = dns_master_stylecreate2(&style, styleflags, 24, 32, 40, 48, 80, 8, splitwidth, mctx); check_result(result, "dns_master_stylecreate"); if (query->lookup->cmdline[0] != 0) { if (!short_form) fputs(query->lookup->cmdline, stdout); query->lookup->cmdline[0]=0; } debug("printmessage(%s %s %s)", headers ? "headers" : "noheaders", query->lookup->comments ? "comments" : "nocomments", short_form ? "short_form" : "long_form"); flags = 0; if (!headers) { flags |= DNS_MESSAGETEXTFLAG_NOHEADERS; flags |= DNS_MESSAGETEXTFLAG_NOCOMMENTS; } if (onesoa && query->lookup->rdtype == dns_rdatatype_axfr) flags |= (query->msg_count == 0) ? DNS_MESSAGETEXTFLAG_ONESOA : DNS_MESSAGETEXTFLAG_OMITSOA; if (!query->lookup->comments) flags |= DNS_MESSAGETEXTFLAG_NOCOMMENTS; result = isc_buffer_allocate(mctx, &buf, len); check_result(result, "isc_buffer_allocate"); if (query->lookup->comments && !short_form) { if (query->lookup->cmdline[0] != 0) printf("; %s\n", query->lookup->cmdline); if (msg == query->lookup->sendmsg) printf(";; Sending:\n"); else printf(";; Got answer:\n"); if (headers) { if (isdotlocal(msg)) { printf(";; WARNING: .local is reserved for " "Multicast DNS\n;; You are currently " "testing what happens when an mDNS " "query is leaked to DNS\n"); } printf(";; ->>HEADER<<- opcode: %s, status: %s, " "id: %u\n", opcodetext[msg->opcode], rcode_totext(msg->rcode), msg->id); printf(";; flags:"); if ((msg->flags & DNS_MESSAGEFLAG_QR) != 0) printf(" qr"); if ((msg->flags & DNS_MESSAGEFLAG_AA) != 0) printf(" aa"); if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) printf(" tc"); if ((msg->flags & DNS_MESSAGEFLAG_RD) != 0) printf(" rd"); if ((msg->flags & DNS_MESSAGEFLAG_RA) != 0) printf(" ra"); if ((msg->flags & DNS_MESSAGEFLAG_AD) != 0) printf(" ad"); if ((msg->flags & DNS_MESSAGEFLAG_CD) != 0) printf(" cd"); if ((msg->flags & 0x0040U) != 0) printf("; MBZ: 0x4"); printf("; QUERY: %u, ANSWER: %u, " "AUTHORITY: %u, ADDITIONAL: %u\n", msg->counts[DNS_SECTION_QUESTION], msg->counts[DNS_SECTION_ANSWER], msg->counts[DNS_SECTION_AUTHORITY], msg->counts[DNS_SECTION_ADDITIONAL]); if (msg != query->lookup->sendmsg && (msg->flags & DNS_MESSAGEFLAG_RD) != 0 && (msg->flags & DNS_MESSAGEFLAG_RA) == 0) printf(";; WARNING: recursion requested " "but not available\n"); } if (msg != query->lookup->sendmsg && query->lookup->edns != -1 && msg->opt == NULL && (msg->rcode == dns_rcode_formerr || msg->rcode == dns_rcode_notimp)) printf("\n;; WARNING: EDNS query returned status " "%s - retry with '%s+noedns'\n", rcode_totext(msg->rcode), query->lookup->dnssec ? "+nodnssec ": ""); if (msg != query->lookup->sendmsg && extrabytes != 0U) printf(";; WARNING: Message has %u extra byte%s at " "end\n", extrabytes, extrabytes != 0 ? "s" : ""); } repopulate_buffer: if (query->lookup->comments && headers && !short_form) { result = dns_message_pseudosectiontotext(msg, DNS_PSEUDOSECTION_OPT, style, flags, buf); if (result == ISC_R_NOSPACE) { buftoosmall: len += OUTPUTBUF; isc_buffer_free(&buf); result = isc_buffer_allocate(mctx, &buf, len); if (result == ISC_R_SUCCESS) goto repopulate_buffer; else goto cleanup; } check_result(result, "dns_message_pseudosectiontotext"); } if (query->lookup->section_question && headers) { if (!short_form) { result = dns_message_sectiontotext(msg, DNS_SECTION_QUESTION, style, flags, buf); if (result == ISC_R_NOSPACE) goto buftoosmall; check_result(result, "dns_message_sectiontotext"); } } if (query->lookup->section_answer) { if (!short_form) { result = dns_message_sectiontotext(msg, DNS_SECTION_ANSWER, style, flags, buf); if (result == ISC_R_NOSPACE) goto buftoosmall; check_result(result, "dns_message_sectiontotext"); } else { result = short_answer(msg, flags, buf, query); if (result == ISC_R_NOSPACE) goto buftoosmall; check_result(result, "short_answer"); } } if (query->lookup->section_authority) { if (!short_form) { result = dns_message_sectiontotext(msg, DNS_SECTION_AUTHORITY, style, flags, buf); if (result == ISC_R_NOSPACE) goto buftoosmall; check_result(result, "dns_message_sectiontotext"); } } if (query->lookup->section_additional) { if (!short_form) { result = dns_message_sectiontotext(msg, DNS_SECTION_ADDITIONAL, style, flags, buf); if (result == ISC_R_NOSPACE) goto buftoosmall; check_result(result, "dns_message_sectiontotext"); /* * Only print the signature on the first record. */ if (headers) { result = dns_message_pseudosectiontotext( msg, DNS_PSEUDOSECTION_TSIG, style, flags, buf); if (result == ISC_R_NOSPACE) goto buftoosmall; check_result(result, "dns_message_pseudosectiontotext"); result = dns_message_pseudosectiontotext( msg, DNS_PSEUDOSECTION_SIG0, style, flags, buf); if (result == ISC_R_NOSPACE) goto buftoosmall; check_result(result, "dns_message_pseudosectiontotext"); } } } if (headers && query->lookup->comments && !short_form) printf("\n"); printf("%.*s", (int)isc_buffer_usedlength(buf), (char *)isc_buffer_base(buf)); isc_buffer_free(&buf); cleanup: if (style != NULL) dns_master_styledestroy(&style, mctx); return (result); } /*% * print the greeting message when the program first starts up. */ static void printgreeting(int argc, char **argv, dig_lookup_t *lookup) { int i; static isc_boolean_t first = ISC_TRUE; char append[MXNAME]; if (printcmd) { snprintf(lookup->cmdline, sizeof(lookup->cmdline), "%s; <<>> DiG " VERSION " <<>>", first?"\n":""); i = 1; while (i < argc) { snprintf(append, sizeof(append), " %s", argv[i++]); strlcat(lookup->cmdline, append, sizeof(lookup->cmdline)); } strlcat(lookup->cmdline, "\n", sizeof(lookup->cmdline)); if (first && addresscount != 0) { snprintf(append, sizeof(append), "; (%d server%s found)\n", addresscount, addresscount > 1 ? "s" : ""); strlcat(lookup->cmdline, append, sizeof(lookup->cmdline)); } if (first) { snprintf(append, sizeof(append), ";; global options:%s%s\n", short_form ? " +short" : "", printcmd ? " +cmd" : ""); first = ISC_FALSE; strlcat(lookup->cmdline, append, sizeof(lookup->cmdline)); } } } /*% * We're not using isc_commandline_parse() here since the command line * syntax of dig is quite a bit different from that which can be described * by that routine. * XXX doc options */ static void plus_option(const char *option, isc_boolean_t is_batchfile, dig_lookup_t *lookup) { isc_result_t result; char option_store[256]; char *cmd, *value, *ptr, *code; isc_uint32_t num; isc_boolean_t state = ISC_TRUE; size_t n; strlcpy(option_store, option, sizeof(option_store)); ptr = option_store; cmd = next_token(&ptr, "="); if (cmd == NULL) { printf(";; Invalid option %s\n", option_store); return; } value = ptr; if (strncasecmp(cmd, "no", 2)==0) { cmd += 2; state = ISC_FALSE; } #define FULLCHECK(A) \ do { \ size_t _l = strlen(cmd); \ if (_l >= sizeof(A) || strncasecmp(cmd, A, _l) != 0) \ goto invalid_option; \ } while (0) #define FULLCHECK2(A, B) \ do { \ size_t _l = strlen(cmd); \ if ((_l >= sizeof(A) || strncasecmp(cmd, A, _l) != 0) && \ (_l >= sizeof(B) || strncasecmp(cmd, B, _l) != 0)) \ goto invalid_option; \ } while (0) switch (cmd[0]) { case 'a': switch (cmd[1]) { case 'a': /* aaonly / aaflag */ FULLCHECK2("aaonly", "aaflag"); lookup->aaonly = state; break; case 'd': switch (cmd[2]) { case 'd': /* additional */ FULLCHECK("additional"); lookup->section_additional = state; break; case 'f': /* adflag */ case '\0': /* +ad is a synonym for +adflag */ FULLCHECK("adflag"); lookup->adflag = state; break; default: goto invalid_option; } break; case 'l': /* all */ FULLCHECK("all"); lookup->section_question = state; lookup->section_authority = state; lookup->section_answer = state; lookup->section_additional = state; lookup->comments = state; lookup->stats = state; printcmd = state; break; case 'n': /* answer */ FULLCHECK("answer"); lookup->section_answer = state; break; case 'u': /* authority */ FULLCHECK("authority"); lookup->section_authority = state; break; default: goto invalid_option; } break; case 'b': switch (cmd[1]) { case 'a':/* badcookie */ FULLCHECK("badcookie"); lookup->badcookie = state; break; case 'e':/* besteffort */ FULLCHECK("besteffort"); lookup->besteffort = state; break; case 'u':/* bufsize */ FULLCHECK("bufsize"); if (value == NULL) goto need_value; if (!state) goto invalid_option; result = parse_uint(&num, value, COMMSIZE, "buffer size"); if (result != ISC_R_SUCCESS) fatal("Couldn't parse buffer size"); lookup->udpsize = num; break; default: goto invalid_option; } break; case 'c': switch (cmd[1]) { case 'd':/* cdflag */ switch (cmd[2]) { case 'f': /* cdflag */ case '\0': /* +cd is a synonym for +cdflag */ FULLCHECK("cdflag"); lookup->cdflag = state; break; default: goto invalid_option; } break; case 'l': /* class */ /* keep +cl for backwards compatibility */ FULLCHECK2("cl", "class"); noclass = ISC_TF(!state); break; case 'm': /* cmd */ FULLCHECK("cmd"); printcmd = state; break; case 'o': /* comments */ switch (cmd[2]) { case 'm': FULLCHECK("comments"); lookup->comments = state; if (lookup == default_lookup) pluscomm = state; break; case 'o': /* cookie */ FULLCHECK("cookie"); if (state && lookup->edns == -1) lookup->edns = 0; lookup->sendcookie = state; if (value != NULL) { n = strlcpy(hexcookie, value, sizeof(hexcookie)); if (n >= sizeof(hexcookie)) fatal("COOKIE data too large"); lookup->cookie = hexcookie; } else lookup->cookie = NULL; break; default: goto invalid_option; } break; case 'r': FULLCHECK("crypto"); nocrypto = ISC_TF(!state); break; default: goto invalid_option; } break; case 'd': switch (cmd[1]) { case 'e': /* defname */ FULLCHECK("defname"); if (!lookup->trace) { usesearch = state; } break; case 'n': /* dnssec */ FULLCHECK("dnssec"); if (state && lookup->edns == -1) lookup->edns = 0; lookup->dnssec = state; break; case 'o': /* domain */ FULLCHECK("domain"); if (value == NULL) goto need_value; if (!state) goto invalid_option; strlcpy(domainopt, value, sizeof(domainopt)); break; case 's': /* dscp */ FULLCHECK("dscp"); if (!state) { lookup->dscp = -1; break; } if (value == NULL) goto need_value; result = parse_uint(&num, value, 0x3f, "DSCP"); if (result != ISC_R_SUCCESS) fatal("Couldn't parse DSCP value"); lookup->dscp = num; break; default: goto invalid_option; } break; case 'e': switch (cmd[1]) { case 'd': switch(cmd[2]) { case 'n': switch (cmd[3]) { case 's': switch (cmd[4]) { case 0: FULLCHECK("edns"); if (!state) { lookup->edns = -1; break; } if (value == NULL) { lookup->edns = 0; break; } result = parse_uint(&num, value, 255, "edns"); if (result != ISC_R_SUCCESS) fatal("Couldn't parse " "edns"); lookup->edns = num; break; case 'f': FULLCHECK("ednsflags"); if (!state) { lookup->ednsflags = 0; break; } if (value == NULL) { lookup->ednsflags = 0; break; } result = parse_xint(&num, value, 0xffff, "ednsflags"); if (result != ISC_R_SUCCESS) fatal("Couldn't parse " "ednsflags"); lookup->ednsflags = num; break; case 'n': FULLCHECK("ednsnegotiation"); lookup->ednsneg = state; break; case 'o': FULLCHECK("ednsopt"); if (!state) { lookup->ednsoptscnt = 0; break; } if (value == NULL) fatal("ednsopt no " "code point " "specified"); code = next_token(&value, ":"); save_opt(lookup, code, value); break; default: goto invalid_option; } break; default: goto invalid_option; } break; default: goto invalid_option; } break; case 'x': FULLCHECK("expire"); lookup->expire = state; break; default: goto invalid_option; } break; case 'f': /* fail */ FULLCHECK("fail"); lookup->servfail_stops = state; break; case 'h': FULLCHECK("header-only"); lookup->header_only = state; break; case 'i': switch (cmd[1]) { case 'd': /* identify */ switch (cmd[2]) { case 'e': FULLCHECK("identify"); lookup->identify = state; break; case 'n': FULLCHECK("idnout"); #ifndef WITH_IDN fprintf(stderr, ";; IDN support not enabled\n"); #else lookup->idnout = state; #endif break; default: goto invalid_option; } break; case 'g': /* ignore */ default: /* * Inherits default for compatibility (+[no]i*). */ FULLCHECK("ignore"); lookup->ignore = state; } break; case 'k': FULLCHECK("keepopen"); keep_open = state; break; case 'm': /* multiline */ switch (cmd[1]) { case 'a': FULLCHECK("mapped"); lookup->mapped = state; break; case 'u': FULLCHECK("multiline"); multiline = state; break; default: goto invalid_option; } break; case 'n': switch (cmd[1]) { case 'd': /* ndots */ FULLCHECK("ndots"); if (value == NULL) goto need_value; if (!state) goto invalid_option; result = parse_uint(&num, value, MAXNDOTS, "ndots"); if (result != ISC_R_SUCCESS) fatal("Couldn't parse ndots"); ndots = num; break; case 's': switch (cmd[2]) { case 'i': /* nsid */ FULLCHECK("nsid"); if (state && lookup->edns == -1) lookup->edns = 0; lookup->nsid = state; break; case 's': /* nssearch */ FULLCHECK("nssearch"); lookup->ns_search_only = state; if (state) { lookup->trace_root = ISC_TRUE; lookup->recurse = ISC_TRUE; lookup->identify = ISC_TRUE; lookup->stats = ISC_FALSE; lookup->comments = ISC_FALSE; lookup->section_additional = ISC_FALSE; lookup->section_authority = ISC_FALSE; lookup->section_question = ISC_FALSE; lookup->rdtype = dns_rdatatype_ns; lookup->rdtypeset = ISC_TRUE; short_form = ISC_TRUE; rrcomments = 0; } break; default: goto invalid_option; } break; default: goto invalid_option; } break; case 'o': switch (cmd[1]) { case 'n': FULLCHECK("onesoa"); onesoa = state; break; case 'p': FULLCHECK("opcode"); if (!state) { lookup->opcode = 0; /* default - query */ break; } if (value == NULL) goto need_value; for (num = 0; num < sizeof(opcodetext)/sizeof(opcodetext[0]); num++) { if (strcasecmp(opcodetext[num], value) == 0) break; } if (num < 16) { lookup->opcode = (dns_opcode_t)num; break; } result = parse_uint(&num, value, 15, "opcode"); if (result != ISC_R_SUCCESS) fatal("Couldn't parse opcode"); lookup->opcode = (dns_opcode_t)num; break; default: goto invalid_option; } break; case 'q': switch (cmd[1]) { case 'r': /* qr */ FULLCHECK("qr"); qr = state; break; case 'u': /* question */ FULLCHECK("question"); lookup->section_question = state; if (lookup == default_lookup) plusquest = state; break; default: goto invalid_option; } break; case 'r': switch (cmd[1]) { case 'd': /* rdflag */ FULLCHECK("rdflag"); lookup->recurse = state; break; case 'e': switch (cmd[2]) { case 'c': /* recurse */ FULLCHECK("recurse"); lookup->recurse = state; break; case 't': /* retry / retries */ FULLCHECK2("retry", "retries"); if (value == NULL) goto need_value; if (!state) goto invalid_option; result = parse_uint(&lookup->retries, value, MAXTRIES - 1, "retries"); if (result != ISC_R_SUCCESS) fatal("Couldn't parse retries"); lookup->retries++; break; default: goto invalid_option; } break; case 'r': /* rrcomments */ FULLCHECK("rrcomments"); rrcomments = state ? 1 : -1; break; default: goto invalid_option; } break; case 's': switch (cmd[1]) { case 'e': /* search */ FULLCHECK("search"); if (!lookup->trace) { usesearch = state; } break; case 'h': if (cmd[2] != 'o') goto invalid_option; switch (cmd[3]) { case 'r': /* short */ FULLCHECK("short"); short_form = state; if (state) { printcmd = ISC_FALSE; lookup->section_additional = ISC_FALSE; lookup->section_answer = ISC_TRUE; lookup->section_authority = ISC_FALSE; lookup->section_question = ISC_FALSE; lookup->comments = ISC_FALSE; lookup->stats = ISC_FALSE; rrcomments = -1; } break; case 'w': /* showsearch */ FULLCHECK("showsearch"); if (!lookup->trace) { showsearch = state; usesearch = state; } break; default: goto invalid_option; } break; #ifdef DIG_SIGCHASE case 'i': /* sigchase */ FULLCHECK("sigchase"); lookup->sigchase = state; if (lookup->sigchase) lookup->dnssec = ISC_TRUE; break; #endif case 'p': /* split */ FULLCHECK("split"); if (value != NULL && !state) goto invalid_option; if (!state) { splitwidth = 0; break; } else if (value == NULL) break; result = parse_uint(&splitwidth, value, 1023, "split"); if (splitwidth % 4 != 0) { splitwidth = ((splitwidth + 3) / 4) * 4; fprintf(stderr, ";; Warning, split must be " "a multiple of 4; adjusting " "to %d\n", splitwidth); } /* * There is an adjustment done in the * totext_() functions which causes * splitwidth to shrink. This is okay when we're * using the default width but incorrect in this * case, so we correct for it */ if (splitwidth) splitwidth += 3; if (result != ISC_R_SUCCESS) fatal("Couldn't parse split"); break; case 't': /* stats */ FULLCHECK("stats"); lookup->stats = state; break; case 'u': /* subnet */ FULLCHECK("subnet"); if (state && value == NULL) goto need_value; if (!state) { if (lookup->ecs_addr != NULL) { isc_mem_free(mctx, lookup->ecs_addr); lookup->ecs_addr = NULL; } break; } if (lookup->edns == -1) lookup->edns = 0; if (lookup->ecs_addr != NULL) { isc_mem_free(mctx, lookup->ecs_addr); lookup->ecs_addr = NULL; } result = parse_netprefix(&lookup->ecs_addr, value); if (result != ISC_R_SUCCESS) fatal("Couldn't parse client"); break; default: goto invalid_option; } break; case 't': switch (cmd[1]) { case 'c': /* tcp */ FULLCHECK("tcp"); if (!is_batchfile) { lookup->tcp_mode = state; lookup->tcp_mode_set = ISC_TRUE; } break; case 'i': /* timeout */ FULLCHECK("timeout"); if (value == NULL) goto need_value; if (!state) goto invalid_option; result = parse_uint(&timeout, value, MAXTIMEOUT, "timeout"); if (result != ISC_R_SUCCESS) fatal("Couldn't parse timeout"); if (timeout == 0) timeout = 1; break; #if DIG_SIGCHASE_TD case 'o': /* topdown */ FULLCHECK("topdown"); lookup->do_topdown = state; break; #endif case 'r': switch (cmd[2]) { case 'a': /* trace */ FULLCHECK("trace"); lookup->trace = state; lookup->trace_root = state; if (state) { lookup->recurse = ISC_FALSE; lookup->identify = ISC_TRUE; lookup->comments = ISC_FALSE; rrcomments = 0; lookup->stats = ISC_FALSE; lookup->section_additional = ISC_FALSE; lookup->section_authority = ISC_TRUE; lookup->section_question = ISC_FALSE; lookup->dnssec = ISC_TRUE; lookup->sendcookie = ISC_TRUE; usesearch = ISC_FALSE; } break; case 'i': /* tries */ FULLCHECK("tries"); if (value == NULL) goto need_value; if (!state) goto invalid_option; result = parse_uint(&lookup->retries, value, MAXTRIES, "tries"); if (result != ISC_R_SUCCESS) fatal("Couldn't parse tries"); if (lookup->retries == 0) lookup->retries = 1; break; #ifdef DIG_SIGCHASE case 'u': /* trusted-key */ FULLCHECK("trusted-key"); if (value == NULL) goto need_value; if (!state) goto invalid_option; n = strlcpy(trustedkey, ptr, sizeof(trustedkey)); if (n >= sizeof(trustedkey)) fatal("trusted key too large"); break; #endif default: goto invalid_option; } break; case 't': switch (cmd[2]) { case 'l': switch (cmd[3]) { case 0: case 'i': /* ttlid */ FULLCHECK2("ttl", "ttlid"); nottl = ISC_TF(!state); break; case 'u': /* ttlunits */ FULLCHECK("ttlunits"); nottl = ISC_FALSE; ttlunits = ISC_TF(state); break; default: goto invalid_option; } break; default: goto invalid_option; } break; default: goto invalid_option; } break; case 'u': FULLCHECK("unknownformat"); lookup->print_unknown_format = state; break; case 'v': FULLCHECK("vc"); if (!is_batchfile) { lookup->tcp_mode = state; lookup->tcp_mode_set = ISC_TRUE; } break; case 'z': /* zflag */ FULLCHECK("zflag"); lookup->zflag = state; break; default: invalid_option: need_value: fprintf(stderr, "Invalid option: +%s\n", option); usage(); } return; } /*% * #ISC_TRUE returned if value was used */ static const char *single_dash_opts = "46dhimnuv"; static const char *dash_opts = "46bcdfhikmnptvyx"; static isc_boolean_t dash_option(char *option, char *next, dig_lookup_t **lookup, isc_boolean_t *open_type_class, isc_boolean_t *need_clone, isc_boolean_t config_only, int argc, char **argv, isc_boolean_t *firstarg) { char opt, *value, *ptr, *ptr2, *ptr3; isc_result_t result; isc_boolean_t value_from_next; isc_textregion_t tr; dns_rdatatype_t rdtype; dns_rdataclass_t rdclass; char textname[MXNAME]; struct in_addr in4; struct in6_addr in6; in_port_t srcport; char *hash, *cmd; isc_uint32_t num; while (strpbrk(option, single_dash_opts) == &option[0]) { /* * Since the -[46dhimnuv] options do not take an argument, * account for them (in any number and/or combination) * if they appear as the first character(s) of a q-opt. */ opt = option[0]; switch (opt) { case '4': if (have_ipv4) { isc_net_disableipv6(); have_ipv6 = ISC_FALSE; } else { fatal("can't find IPv4 networking"); /* NOTREACHED */ return (ISC_FALSE); } break; case '6': if (have_ipv6) { isc_net_disableipv4(); have_ipv4 = ISC_FALSE; } else { fatal("can't find IPv6 networking"); /* NOTREACHED */ return (ISC_FALSE); } break; case 'd': ptr = strpbrk(&option[1], dash_opts); if (ptr != &option[1]) { cmd = option; FULLCHECK("debug"); debugging = ISC_TRUE; return (ISC_FALSE); } else debugging = ISC_TRUE; break; case 'h': help(); exit(0); break; case 'i': ip6_int = ISC_TRUE; break; case 'm': /* memdebug */ /* memdebug is handled in preparse_args() */ break; case 'n': /* deprecated */ break; case 'u': use_usec = ISC_TRUE; break; case 'v': version(); exit(0); break; } if (strlen(option) > 1U) option = &option[1]; else return (ISC_FALSE); } opt = option[0]; if (strlen(option) > 1U) { value_from_next = ISC_FALSE; value = &option[1]; } else { value_from_next = ISC_TRUE; value = next; } if (value == NULL) goto invalid_option; switch (opt) { case 'b': hash = strchr(value, '#'); if (hash != NULL) { result = parse_uint(&num, hash + 1, MAXPORT, "port number"); if (result != ISC_R_SUCCESS) fatal("Couldn't parse port number"); srcport = num; *hash = '\0'; } else srcport = 0; if (have_ipv6 && inet_pton(AF_INET6, value, &in6) == 1) { isc_sockaddr_fromin6(&bind_address, &in6, srcport); isc_net_disableipv4(); } else if (have_ipv4 && inet_pton(AF_INET, value, &in4) == 1) { isc_sockaddr_fromin(&bind_address, &in4, srcport); isc_net_disableipv6(); } else { if (hash != NULL) *hash = '#'; fatal("invalid address %s", value); } if (hash != NULL) *hash = '#'; specified_source = ISC_TRUE; return (value_from_next); case 'c': if ((*lookup)->rdclassset) { fprintf(stderr, ";; Warning, extra class option\n"); } *open_type_class = ISC_FALSE; tr.base = value; tr.length = (unsigned int) strlen(value); result = dns_rdataclass_fromtext(&rdclass, (isc_textregion_t *)&tr); if (result == ISC_R_SUCCESS) { (*lookup)->rdclass = rdclass; (*lookup)->rdclassset = ISC_TRUE; } else fprintf(stderr, ";; Warning, ignoring " "invalid class %s\n", value); return (value_from_next); case 'f': batchname = value; return (value_from_next); case 'k': strlcpy(keyfile, value, sizeof(keyfile)); return (value_from_next); case 'p': result = parse_uint(&num, value, MAXPORT, "port number"); if (result != ISC_R_SUCCESS) fatal("Couldn't parse port number"); port = num; return (value_from_next); case 'q': if (!config_only) { if (*need_clone) (*lookup) = clone_lookup(default_lookup, ISC_TRUE); *need_clone = ISC_TRUE; strlcpy((*lookup)->textname, value, sizeof((*lookup)->textname)); (*lookup)->trace_root = ISC_TF((*lookup)->trace || (*lookup)->ns_search_only); (*lookup)->new_search = ISC_TRUE; if (*firstarg) { printgreeting(argc, argv, *lookup); *firstarg = ISC_FALSE; } ISC_LIST_APPEND(lookup_list, (*lookup), link); debug("looking up %s", (*lookup)->textname); } return (value_from_next); case 't': *open_type_class = ISC_FALSE; if (strncasecmp(value, "ixfr=", 5) == 0) { rdtype = dns_rdatatype_ixfr; result = ISC_R_SUCCESS; } else { tr.base = value; tr.length = (unsigned int) strlen(value); result = dns_rdatatype_fromtext(&rdtype, (isc_textregion_t *)&tr); if (result == ISC_R_SUCCESS && rdtype == dns_rdatatype_ixfr) { result = DNS_R_UNKNOWN; } } if (result == ISC_R_SUCCESS) { if ((*lookup)->rdtypeset) { fprintf(stderr, ";; Warning, " "extra type option\n"); } if (rdtype == dns_rdatatype_ixfr) { isc_uint32_t serial; (*lookup)->rdtype = dns_rdatatype_ixfr; (*lookup)->rdtypeset = ISC_TRUE; result = parse_uint(&serial, &value[5], MAXSERIAL, "serial number"); if (result != ISC_R_SUCCESS) fatal("Couldn't parse serial number"); (*lookup)->ixfr_serial = serial; (*lookup)->section_question = plusquest; (*lookup)->comments = pluscomm; if (!(*lookup)->tcp_mode_set) (*lookup)->tcp_mode = ISC_TRUE; } else { (*lookup)->rdtype = rdtype; if (!config_only) (*lookup)->rdtypeset = ISC_TRUE; if (rdtype == dns_rdatatype_axfr) { (*lookup)->section_question = plusquest; (*lookup)->comments = pluscomm; } else if (rdtype == dns_rdatatype_any) { if (!(*lookup)->tcp_mode_set) (*lookup)->tcp_mode = ISC_TRUE; } (*lookup)->ixfr_serial = ISC_FALSE; } } else fprintf(stderr, ";; Warning, ignoring " "invalid type %s\n", value); return (value_from_next); case 'y': ptr = next_token(&value, ":"); /* hmac type or name */ if (ptr == NULL) { usage(); } ptr2 = next_token(&value, ":"); /* name or secret */ if (ptr2 == NULL) usage(); ptr3 = next_token(&value, ":"); /* secret or NULL */ if (ptr3 != NULL) { parse_hmac(ptr); ptr = ptr2; ptr2 = ptr3; } else { #ifndef PK11_MD5_DISABLE hmacname = DNS_TSIG_HMACMD5_NAME; #else hmacname = DNS_TSIG_HMACSHA256_NAME; #endif digestbits = 0; } strlcpy(keynametext, ptr, sizeof(keynametext)); strlcpy(keysecret, ptr2, sizeof(keysecret)); return (value_from_next); case 'x': if (*need_clone) *lookup = clone_lookup(default_lookup, ISC_TRUE); *need_clone = ISC_TRUE; if (get_reverse(textname, sizeof(textname), value, ip6_int, ISC_FALSE) == ISC_R_SUCCESS) { strlcpy((*lookup)->textname, textname, sizeof((*lookup)->textname)); debug("looking up %s", (*lookup)->textname); (*lookup)->trace_root = ISC_TF((*lookup)->trace || (*lookup)->ns_search_only); (*lookup)->ip6_int = ip6_int; if (!(*lookup)->rdtypeset) (*lookup)->rdtype = dns_rdatatype_ptr; if (!(*lookup)->rdclassset) (*lookup)->rdclass = dns_rdataclass_in; (*lookup)->new_search = ISC_TRUE; if (*firstarg) { printgreeting(argc, argv, *lookup); *firstarg = ISC_FALSE; } ISC_LIST_APPEND(lookup_list, *lookup, link); } else { fprintf(stderr, "Invalid IP address %s\n", value); exit(1); } return (value_from_next); invalid_option: default: fprintf(stderr, "Invalid option: -%s\n", option); usage(); } /* NOTREACHED */ return (ISC_FALSE); } /*% * Because we may be trying to do memory allocation recording, we're going * to need to parse the arguments for the -m *before* we start the main * argument parsing routine. * * I'd prefer not to have to do this, but I am not quite sure how else to * fix the problem. Argument parsing in dig involves memory allocation * by its nature, so it can't be done in the main argument parser. */ static void preparse_args(int argc, char **argv) { int rc; char **rv; char *option; rc = argc; rv = argv; for (rc--, rv++; rc > 0; rc--, rv++) { if (rv[0][0] != '-') continue; option = &rv[0][1]; while (strpbrk(option, single_dash_opts) == &option[0]) { switch (option[0]) { case 'm': memdebugging = ISC_TRUE; isc_mem_debugging = ISC_MEM_DEBUGTRACE | ISC_MEM_DEBUGRECORD; break; case '4': if (ipv6only) fatal("only one of -4 and -6 allowed"); ipv4only = ISC_TRUE; break; case '6': if (ipv4only) fatal("only one of -4 and -6 allowed"); ipv6only = ISC_TRUE; break; } option = &option[1]; } } } static void parse_args(isc_boolean_t is_batchfile, isc_boolean_t config_only, int argc, char **argv) { isc_result_t result; isc_textregion_t tr; isc_boolean_t firstarg = ISC_TRUE; dig_lookup_t *lookup = NULL; dns_rdatatype_t rdtype; dns_rdataclass_t rdclass; isc_boolean_t open_type_class = ISC_TRUE; char batchline[MXNAME]; int bargc; char *bargv[64]; int rc; char **rv; #ifndef NOPOSIX char *homedir; char rcfile[256]; #endif char *input; int i; isc_boolean_t need_clone = ISC_TRUE; /* * The semantics for parsing the args is a bit complex; if * we don't have a host yet, make the arg apply globally, * otherwise make it apply to the latest host. This is * a bit different than the previous versions, but should * form a consistent user interface. * * First, create a "default lookup" which won't actually be used * anywhere, except for cloning into new lookups */ debug("parse_args()"); if (!is_batchfile) { debug("making new lookup"); default_lookup = make_empty_lookup(); default_lookup->adflag = ISC_TRUE; default_lookup->edns = 0; default_lookup->sendcookie = ISC_TRUE; #ifndef NOPOSIX /* * Treat ${HOME}/.digrc as a special batchfile */ INSIST(batchfp == NULL); homedir = getenv("HOME"); if (homedir != NULL) { unsigned int n; n = snprintf(rcfile, sizeof(rcfile), "%s/.digrc", homedir); if (n < sizeof(rcfile)) batchfp = fopen(rcfile, "r"); } if (batchfp != NULL) { while (fgets(batchline, sizeof(batchline), batchfp) != 0) { debug("config line %s", batchline); bargc = 1; input = batchline; bargv[bargc] = next_token(&input, " \t\r\n"); while ((bargv[bargc] != NULL) && (bargc < 62)) { bargc++; bargv[bargc] = next_token(&input, " \t\r\n"); } bargv[0] = argv[0]; argv0 = argv[0]; for(i = 0; i < bargc; i++) debug(".digrc argv %d: %s", i, bargv[i]); parse_args(ISC_TRUE, ISC_TRUE, bargc, (char **)bargv); } fclose(batchfp); } #endif } if (is_batchfile && !config_only) { /* Processing '-f batchfile'. */ lookup = clone_lookup(default_lookup, ISC_TRUE); need_clone = ISC_FALSE; } else lookup = default_lookup; rc = argc; rv = argv; for (rc--, rv++; rc > 0; rc--, rv++) { debug("main parsing %s", rv[0]); if (strncmp(rv[0], "%", 1) == 0) break; if (rv[0][0] == '@') { if (is_batchfile && !config_only) { addresscount = getaddresses(lookup, &rv[0][1], &result); if (addresscount == 0) { fprintf(stderr, "couldn't get address " "for '%s': %s: skipping " "lookup\n", &rv[0][1], isc_result_totext(result)); if (ISC_LINK_LINKED(lookup, link)) ISC_LIST_DEQUEUE(lookup_list, lookup, link); destroy_lookup(lookup); return; } } else { addresscount = getaddresses(lookup, &rv[0][1], NULL); if (addresscount == 0) fatal("no valid addresses for '%s'\n", &rv[0][1]); } } else if (rv[0][0] == '+') { plus_option(&rv[0][1], is_batchfile, lookup); } else if (rv[0][0] == '-') { if (rc <= 1) { if (dash_option(&rv[0][1], NULL, &lookup, &open_type_class, &need_clone, config_only, argc, argv, &firstarg)) { rc--; rv++; } } else { if (dash_option(&rv[0][1], rv[1], &lookup, &open_type_class, &need_clone, config_only, argc, argv, &firstarg)) { rc--; rv++; } } } else { /* * Anything which isn't an option */ if (open_type_class) { if (strncasecmp(rv[0], "ixfr=", 5) == 0) { rdtype = dns_rdatatype_ixfr; result = ISC_R_SUCCESS; } else { tr.base = rv[0]; tr.length = (unsigned int) strlen(rv[0]); result = dns_rdatatype_fromtext(&rdtype, (isc_textregion_t *)&tr); if (result == ISC_R_SUCCESS && rdtype == dns_rdatatype_ixfr) { fprintf(stderr, ";; Warning, " "ixfr requires a " "serial number\n"); continue; } } if (result == ISC_R_SUCCESS) { if (lookup->rdtypeset) { fprintf(stderr, ";; Warning, " "extra type option\n"); } if (rdtype == dns_rdatatype_ixfr) { isc_uint32_t serial; lookup->rdtype = dns_rdatatype_ixfr; lookup->rdtypeset = ISC_TRUE; result = parse_uint(&serial, &rv[0][5], MAXSERIAL, "serial number"); if (result != ISC_R_SUCCESS) fatal("Couldn't parse " "serial number"); lookup->ixfr_serial = serial; lookup->section_question = plusquest; lookup->comments = pluscomm; if (!lookup->tcp_mode_set) lookup->tcp_mode = ISC_TRUE; } else { lookup->rdtype = rdtype; lookup->rdtypeset = ISC_TRUE; if (rdtype == dns_rdatatype_axfr) { lookup->section_question = plusquest; lookup->comments = pluscomm; } if (rdtype == dns_rdatatype_any && !lookup->tcp_mode_set) lookup->tcp_mode = ISC_TRUE; lookup->ixfr_serial = ISC_FALSE; } continue; } result = dns_rdataclass_fromtext(&rdclass, (isc_textregion_t *)&tr); if (result == ISC_R_SUCCESS) { if (lookup->rdclassset) { fprintf(stderr, ";; Warning, " "extra class option\n"); } lookup->rdclass = rdclass; lookup->rdclassset = ISC_TRUE; continue; } } if (!config_only) { if (need_clone) lookup = clone_lookup(default_lookup, ISC_TRUE); need_clone = ISC_TRUE; strlcpy(lookup->textname, rv[0], sizeof(lookup->textname)); lookup->trace_root = ISC_TF(lookup->trace || lookup->ns_search_only); lookup->new_search = ISC_TRUE; if (firstarg) { printgreeting(argc, argv, lookup); firstarg = ISC_FALSE; } ISC_LIST_APPEND(lookup_list, lookup, link); debug("looking up %s", lookup->textname); } /* XXX Error message */ } } /* * If we have a batchfile, seed the lookup list with the * first entry, then trust the callback in dighost_shutdown * to get the rest */ if ((batchname != NULL) && !(is_batchfile)) { if (strcmp(batchname, "-") == 0) batchfp = stdin; else batchfp = fopen(batchname, "r"); if (batchfp == NULL) { perror(batchname); if (exitcode < 8) exitcode = 8; fatal("couldn't open specified batch file"); } /* XXX Remove code dup from shutdown code */ next_line: if (fgets(batchline, sizeof(batchline), batchfp) != 0) { bargc = 1; debug("batch line %s", batchline); if (batchline[0] == '\r' || batchline[0] == '\n' || batchline[0] == '#' || batchline[0] == ';') goto next_line; input = batchline; bargv[bargc] = next_token(&input, " \t\r\n"); while ((bargv[bargc] != NULL) && (bargc < 14)) { bargc++; bargv[bargc] = next_token(&input, " \t\r\n"); } bargv[0] = argv[0]; argv0 = argv[0]; for(i = 0; i < bargc; i++) debug("batch argv %d: %s", i, bargv[i]); parse_args(ISC_TRUE, ISC_FALSE, bargc, (char **)bargv); return; } return; } /* * If no lookup specified, search for root */ if ((lookup_list.head == NULL) && !config_only) { if (need_clone) lookup = clone_lookup(default_lookup, ISC_TRUE); need_clone = ISC_TRUE; lookup->trace_root = ISC_TF(lookup->trace || lookup->ns_search_only); lookup->new_search = ISC_TRUE; strlcpy(lookup->textname, ".", sizeof(lookup->textname)); lookup->rdtype = dns_rdatatype_ns; lookup->rdtypeset = ISC_TRUE; if (firstarg) { printgreeting(argc, argv, lookup); firstarg = ISC_FALSE; } ISC_LIST_APPEND(lookup_list, lookup, link); } if (!need_clone) destroy_lookup(lookup); } /* * Callback from dighost.c to allow program-specific shutdown code. * Here, we're possibly reading from a batch file, then shutting down * for real if there's nothing in the batch file to read. */ static void query_finished(void) { char batchline[MXNAME]; int bargc; char *bargv[16]; char *input; int i; if (batchname == NULL) { isc_app_shutdown(); return; } fflush(stdout); if (feof(batchfp)) { batchname = NULL; isc_app_shutdown(); if (batchfp != stdin) fclose(batchfp); return; } if (fgets(batchline, sizeof(batchline), batchfp) != 0) { debug("batch line %s", batchline); bargc = 1; input = batchline; bargv[bargc] = next_token(&input, " \t\r\n"); while ((bargv[bargc] != NULL) && (bargc < 14)) { bargc++; bargv[bargc] = next_token(&input, " \t\r\n"); } bargv[0] = argv0; for(i = 0; i < bargc; i++) debug("batch argv %d: %s", i, bargv[i]); parse_args(ISC_TRUE, ISC_FALSE, bargc, (char **)bargv); start_lookup(); } else { batchname = NULL; if (batchfp != stdin) fclose(batchfp); isc_app_shutdown(); return; } } void dig_setup(int argc, char **argv) { isc_result_t result; ISC_LIST_INIT(lookup_list); ISC_LIST_INIT(server_list); ISC_LIST_INIT(search_list); debug("dig_setup()"); /* setup dighost callbacks */ #ifdef DIG_SIGCHASE dighost_printrdataset = printrdataset; #endif dighost_printmessage = printmessage; dighost_received = received; dighost_trying = trying; dighost_shutdown = query_finished; progname = argv[0]; preparse_args(argc, argv); result = isc_app_start(); check_result(result, "isc_app_start"); setup_libs(); setup_system(ipv4only, ipv6only); } void dig_query_setup(isc_boolean_t is_batchfile, isc_boolean_t config_only, int argc, char **argv) { debug("dig_query_setup"); parse_args(is_batchfile, config_only, argc, argv); if (keyfile[0] != 0) setup_file_key(); else if (keysecret[0] != 0) setup_text_key(); if (domainopt[0] != '\0') { set_search_domain(domainopt); usesearch = ISC_TRUE; } } void dig_startup() { isc_result_t result; debug("dig_startup()"); result = isc_app_onrun(mctx, global_task, onrun_callback, NULL); check_result(result, "isc_app_onrun"); isc_app_run(); } void dig_query_start() { start_lookup(); } void dig_shutdown() { destroy_lookup(default_lookup); if (batchname != NULL) { if (batchfp != stdin) fclose(batchfp); batchname = NULL; } #ifdef DIG_SIGCHASE clean_trustedkey(); #endif cancel_all(); destroy_libs(); isc_app_finish(); } /*% Main processing routine for dig */ int main(int argc, char **argv) { dig_setup(argc, argv); dig_query_setup(ISC_FALSE, ISC_FALSE, argc, argv); dig_startup(); dig_shutdown(); return (exitcode); } bind9-9.11.3+dfsg/bin/dig/dig.docbook000066400000000000000000001173361325250447100171670ustar00rootroot00000000000000]> 2014-02-19 ISC Internet Systems Consortium, Inc. dig 1 BIND9 dig DNS lookup utility 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2013 2014 2015 2016 2017 2018 Internet Systems Consortium, Inc. ("ISC") dig @server name type class queryopt dig dig global-queryopt query DESCRIPTION dig is a flexible tool for interrogating DNS name servers. It performs DNS lookups and displays the answers that are returned from the name server(s) that were queried. Most DNS administrators use dig to troubleshoot DNS problems because of its flexibility, ease of use and clarity of output. Other lookup tools tend to have less functionality than dig. Although dig is normally used with command-line arguments, it also has a batch mode of operation for reading lookup requests from a file. A brief summary of its command-line arguments and options is printed when the option is given. Unlike earlier versions, the BIND 9 implementation of dig allows multiple lookups to be issued from the command line. Unless it is told to query a specific name server, dig will try each of the servers listed in /etc/resolv.conf. If no usable server addresses are found, dig will send the query to the local host. When no command line arguments or options are given, dig will perform an NS query for "." (the root). It is possible to set per-user defaults for dig via ${HOME}/.digrc. This file is read and any options in it are applied before the command line arguments. The IN and CH class names overlap with the IN and CH top level domain names. Either use the and options to specify the type and class, use the the specify the domain name, or use "IN." and "CH." when looking up these top level domains. SIMPLE USAGE A typical invocation of dig looks like: dig @server name type where: server is the name or IP address of the name server to query. This can be an IPv4 address in dotted-decimal notation or an IPv6 address in colon-delimited notation. When the supplied server argument is a hostname, dig resolves that name before querying that name server. If no server argument is provided, dig consults /etc/resolv.conf; if an address is found there, it queries the name server at that address. If either of the or options are in use, then only addresses for the corresponding transport will be tried. If no usable addresses are found, dig will send the query to the local host. The reply from the name server that responds is displayed. name is the name of the resource record that is to be looked up. type indicates what type of query is required — ANY, A, MX, SIG, etc. type can be any valid query type. If no type argument is supplied, dig will perform a lookup for an A record. OPTIONS -4 Use IPv4 only. -6 Use IPv6 only. -b address#port Set the source IP address of the query. The address must be a valid address on one of the host's network interfaces, or "0.0.0.0" or "::". An optional port may be specified by appending "#<port>" -c class Set the query class. The default class is IN; other classes are HS for Hesiod records or CH for Chaosnet records. -f file Batch mode: dig reads a list of lookup requests to process from the given file. Each line in the file should be organized in the same way they would be presented as queries to dig using the command-line interface. -i Do reverse IPv6 lookups using the obsolete RFC1886 IP6.INT domain, which is no longer in use. Obsolete bit string label queries (RFC2874) are not attempted. -k keyfile Sign queries using TSIG using a key read from the given file. Key files can be generated using tsig-keygen8 . When using TSIG authentication with dig, the name server that is queried needs to know the key and algorithm that is being used. In BIND, this is done by providing appropriate key and server statements in named.conf. -m Enable memory usage debugging. -p port Send the query to a non-standard port on the server, instead of the default port 53. This option would be used to test a name server that has been configured to listen for queries on a non-standard port number. -q name The domain name to query. This is useful to distinguish the name from other arguments. -t type The resource record type to query. It can be any valid query type which is supported in BIND 9. The default query type is "A", unless the option is supplied to indicate a reverse lookup. A zone transfer can be requested by specifying a type of AXFR. When an incremental zone transfer (IXFR) is required, set the type to ixfr=N. The incremental zone transfer will contain the changes made to the zone since the serial number in the zone's SOA record was N. -u Print query times in microseconds instead of milliseconds. -v Print the version number and exit. -x addr Simplified reverse lookups, for mapping addresses to names. The addr is an IPv4 address in dotted-decimal notation, or a colon-delimited IPv6 address. When the is used, there is no need to provide the name, class and type arguments. dig automatically performs a lookup for a name like 94.2.0.192.in-addr.arpa and sets the query type and class to PTR and IN respectively. IPv6 addresses are looked up using nibble format under the IP6.ARPA domain (but see also the option). -y hmac:keyname:secret Sign queries using TSIG with the given authentication key. keyname is the name of the key, and secret is the base64 encoded shared secret. hmac is the name of the key algorithm; valid choices are hmac-md5, hmac-sha1, hmac-sha224, hmac-sha256, hmac-sha384, or hmac-sha512. If hmac is not specified, the default is hmac-md5 or if MD5 was disabled hmac-sha256. NOTE: You should use the option and avoid the option, because with the shared secret is supplied as a command line argument in clear text. This may be visible in the output from ps1 or in a history file maintained by the user's shell. QUERY OPTIONS dig provides a number of query options which affect the way in which lookups are made and the results displayed. Some of these set or reset flag bits in the query header, some determine which sections of the answer get printed, and others determine the timeout and retry strategies. Each query option is identified by a keyword preceded by a plus sign (+). Some keywords set or reset an option. These may be preceded by the string no to negate the meaning of that keyword. Other keywords assign values to options like the timeout interval. They have the form . Keywords may be abbreviated, provided the abbreviation is unambiguous; for example, +cd is equivalent to +cdflag. The query options are: A synonym for +[no]aaonly. Sets the "aa" flag in the query. Display [do not display] the additional section of a reply. The default is to display it. Set [do not set] the AD (authentic data) bit in the query. This requests the server to return whether all of the answer and authority sections have all been validated as secure according to the security policy of the server. AD=1 indicates that all records have been validated as secure and the answer is not from a OPT-OUT range. AD=0 indicate that some part of the answer was insecure or not validated. This bit is set by default. Set or clear all display flags. Display [do not display] the answer section of a reply. The default is to display it. Display [do not display] the authority section of a reply. The default is to display it. Retry lookup with the new server cookie if a BADCOOKIE response is received. Attempt to display the contents of messages which are malformed. The default is to not display malformed answers. Set the UDP message buffer size advertised using EDNS0 to B bytes. The maximum and minimum sizes of this buffer are 65535 and 0 respectively. Values outside this range are rounded up or down appropriately. Values other than zero will cause a EDNS query to be sent. Set [do not set] the CD (checking disabled) bit in the query. This requests the server to not perform DNSSEC validation of responses. Display [do not display] the CLASS when printing the record. Toggles the printing of the initial comment in the output identifying the version of dig and the query options that have been applied. This comment is printed by default. Toggle the display of comment lines in the output. The default is to print comments. Send a COOKIE EDNS option, with optional value. Replaying a COOKIE from a previous response will allow the server to identify a previous client. The default is . +cookie is also set when +trace is set to better emulate the default queries from a nameserver. Toggle the display of cryptographic fields in DNSSEC records. The contents of these field are unnecessary to debug most DNSSEC validation failures and removing them makes it easier to see the common failures. The default is to display the fields. When omitted they are replaced by the string "[omitted]" or in the DNSKEY case the key id is displayed as the replacement, e.g. "[ key id = value ]". Deprecated, treated as a synonym for +[no]search Requests DNSSEC records be sent by setting the DNSSEC OK bit (DO) in the OPT record in the additional section of the query. Set the search list to contain the single domain somename, as if specified in a domain directive in /etc/resolv.conf, and enable search list processing as if the +search option were given. Set the DSCP code point to be used when sending the query. Valid DSCP code points are in the range [0..63]. By default no code point is explicitly set. Specify the EDNS version to query with. Valid values are 0 to 255. Setting the EDNS version will cause a EDNS query to be sent. clears the remembered EDNS version. EDNS is set to 0 by default. Set the must-be-zero EDNS flags bits (Z bits) to the specified value. Decimal, hex and octal encodings are accepted. Setting a named flag (e.g. DO) will silently be ignored. By default, no Z bits are set. Enable / disable EDNS version negotiation. By default EDNS version negotiation is enabled. Specify EDNS option with code point and optionally payload of as a hexadecimal string. can be either an EDNS option name (for example, NSID or ECS), or an arbitrary numeric value. clears the EDNS options to be sent. Send an EDNS Expire option. Do not try the next server if you receive a SERVFAIL. The default is to not try the next server which is the reverse of normal stub resolver behavior. Send a query with a DNS header without a question section. The default is to add a question section. The query type and query name are ignored when this is set. Show [or do not show] the IP address and port number that supplied the answer when the +short option is enabled. If short form answers are requested, the default is not to show the source address and port number of the server that provided the answer. Convert [do not convert] puny code on output. This requires IDN SUPPORT to have been enabled at compile time. The default is to convert output. Ignore truncation in UDP responses instead of retrying with TCP. By default, TCP retries are performed. Keep the TCP socket open between queries and reuse it rather than creating a new TCP socket for each lookup. The default is . Allow mapped IPv4 over IPv6 addresses to be used. The default is . Print records like the SOA records in a verbose multi-line format with human-readable comments. The default is to print each record on a single line, to facilitate machine parsing of the dig output. Set the number of dots that have to appear in name to D for it to be considered absolute. The default value is that defined using the ndots statement in /etc/resolv.conf, or 1 if no ndots statement is present. Names with fewer dots are interpreted as relative names and will be searched for in the domains listed in the or directive in /etc/resolv.conf if is set. Include an EDNS name server ID request when sending a query. When this option is set, dig attempts to find the authoritative name servers for the zone containing the name being looked up and display the SOA record that each name server has for the zone. Print only one (starting) SOA record when performing an AXFR. The default is to print both the starting and ending SOA records. Set [restore] the DNS message opcode to the specified value. The default value is QUERY (0). Print [do not print] the query as it is sent. By default, the query is not printed. Print [do not print] the question section of a query when an answer is returned. The default is to print the question section as a comment. A synonym for +[no]recurse. Toggle the setting of the RD (recursion desired) bit in the query. This bit is set by default, which means dig normally sends recursive queries. Recursion is automatically disabled when the +nssearch or +trace query options are used. Sets the number of times to retry UDP queries to server to T instead of the default, 2. Unlike +tries, this does not include the initial query. Toggle the display of per-record comments in the output (for example, human-readable key information about DNSKEY records). The default is not to print record comments unless multiline mode is active. Use [do not use] the search list defined by the searchlist or domain directive in resolv.conf (if any). The search list is not used by default. 'ndots' from resolv.conf (default 1) which may be overridden by +ndots determines if the name will be treated as relative or not and hence whether a search is eventually performed or not. Provide a terse answer. The default is to print the answer in a verbose form. Perform [do not perform] a search showing intermediate results. Chase DNSSEC signature chains. Requires dig be compiled with -DDIG_SIGCHASE. This feature is deprecated. Use delv instead. Split long hex- or base64-formatted fields in resource records into chunks of W characters (where W is rounded up to the nearest multiple of 4). +nosplit or +split=0 causes fields not to be split at all. The default is 56 characters, or 44 characters when multiline mode is active. This query option toggles the printing of statistics: when the query was made, the size of the reply and so on. The default behavior is to print the query statistics. Send (don't send) an EDNS Client Subnet option with the specified IP address or network prefix. dig +subnet=0.0.0.0/0, or simply dig +subnet=0 for short, sends an EDNS CLIENT-SUBNET option with an empty address and a source prefix-length of zero, which signals a resolver that the client's address information must not be used when resolving this query. Use [do not use] TCP when querying name servers. The default behavior is to use UDP unless a type any or ixfr=N query is requested, in which case the default is TCP. AXFR queries always use TCP. Sets the timeout for a query to T seconds. The default timeout is 5 seconds. An attempt to set T to less than 1 will result in a query timeout of 1 second being applied. When chasing DNSSEC signature chains perform a top-down validation. Requires dig be compiled with -DDIG_SIGCHASE. This feature is deprecated. Use delv instead. Toggle tracing of the delegation path from the root name servers for the name being looked up. Tracing is disabled by default. When tracing is enabled, dig makes iterative queries to resolve the name being looked up. It will follow referrals from the root servers, showing the answer from each server that was used to resolve the lookup. If @server is also specified, it affects only the initial query for the root zone name servers. +dnssec is also set when +trace is set to better emulate the default queries from a nameserver. Sets the number of times to try UDP queries to server to T instead of the default, 3. If T is less than or equal to zero, the number of tries is silently rounded up to 1. Specifies a file containing trusted keys to be used with . Each DNSKEY record must be on its own line. If not specified, dig will look for /etc/trusted-key.key then trusted-key.key in the current directory. Requires dig be compiled with -DDIG_SIGCHASE. This feature is deprecated. Use delv instead. Display [do not display] the TTL when printing the record. Display [do not display] the TTL in friendly human-readable time units of "s", "m", "h", "d", and "w", representing seconds, minutes, hours, days and weeks. Implies +ttlid. Print all RDATA in unknown RR type presentation format (RFC 3597). The default is to print RDATA for known types in the type's presentation format. Use [do not use] TCP when querying name servers. This alternate syntax to +[no]tcp is provided for backwards compatibility. The "vc" stands for "virtual circuit". Set [do not set] the last unassigned DNS header flag in a DNS query. This flag is off by default. MULTIPLE QUERIES The BIND 9 implementation of dig supports specifying multiple queries on the command line (in addition to supporting the batch file option). Each of those queries can be supplied with its own set of flags, options and query options. In this case, each query argument represent an individual query in the command-line syntax described above. Each consists of any of the standard options and flags, the name to be looked up, an optional query type and class and any query options that should be applied to that query. A global set of query options, which should be applied to all queries, can also be supplied. These global query options must precede the first tuple of name, class, type, options, flags, and query options supplied on the command line. Any global query options (except the option) can be overridden by a query-specific set of query options. For example: dig +qr www.isc.org any -x 127.0.0.1 isc.org ns +noqr shows how dig could be used from the command line to make three lookups: an ANY query for www.isc.org, a reverse lookup of 127.0.0.1 and a query for the NS records of isc.org. A global query option of +qr is applied, so that dig shows the initial query it made for each lookup. The final query has a local query option of +noqr which means that dig will not print the initial query when it looks up the NS records for isc.org. IDN SUPPORT If dig has been built with IDN (internationalized domain name) support, it can accept and display non-ASCII domain names. dig appropriately converts character encoding of domain name before sending a request to DNS server or displaying a reply from the server. If you'd like to turn off the IDN support for some reason, defines the IDN_DISABLE environment variable. The IDN support is disabled if the variable is set when dig runs. FILES /etc/resolv.conf ${HOME}/.digrc SEE ALSO delv1 , host1 , named8 , dnssec-keygen8 , RFC1035. BUGS There are probably too many query options. bind9-9.11.3+dfsg/bin/dig/dig.html000066400000000000000000001153651325250447100165130ustar00rootroot00000000000000 dig

Name

dig — DNS lookup utility

Synopsis

dig [@server] [-b address] [-c class] [-f filename] [-k filename] [-m] [-p port#] [-q name] [-t type] [-v] [-x addr] [-y [hmac:]name:key] [ [-4] | [-6] ] [name] [type] [class] [queryopt...]

dig [-h]

dig [global-queryopt...] [query...]

DESCRIPTION

dig is a flexible tool for interrogating DNS name servers. It performs DNS lookups and displays the answers that are returned from the name server(s) that were queried. Most DNS administrators use dig to troubleshoot DNS problems because of its flexibility, ease of use and clarity of output. Other lookup tools tend to have less functionality than dig.

Although dig is normally used with command-line arguments, it also has a batch mode of operation for reading lookup requests from a file. A brief summary of its command-line arguments and options is printed when the -h option is given. Unlike earlier versions, the BIND 9 implementation of dig allows multiple lookups to be issued from the command line.

Unless it is told to query a specific name server, dig will try each of the servers listed in /etc/resolv.conf. If no usable server addresses are found, dig will send the query to the local host.

When no command line arguments or options are given, dig will perform an NS query for "." (the root).

It is possible to set per-user defaults for dig via ${HOME}/.digrc. This file is read and any options in it are applied before the command line arguments.

The IN and CH class names overlap with the IN and CH top level domain names. Either use the -t and -c options to specify the type and class, use the -q the specify the domain name, or use "IN." and "CH." when looking up these top level domains.

SIMPLE USAGE

A typical invocation of dig looks like:

 dig @server name type 

where:

server

is the name or IP address of the name server to query. This can be an IPv4 address in dotted-decimal notation or an IPv6 address in colon-delimited notation. When the supplied server argument is a hostname, dig resolves that name before querying that name server.

If no server argument is provided, dig consults /etc/resolv.conf; if an address is found there, it queries the name server at that address. If either of the -4 or -6 options are in use, then only addresses for the corresponding transport will be tried. If no usable addresses are found, dig will send the query to the local host. The reply from the name server that responds is displayed.

name

is the name of the resource record that is to be looked up.

type

indicates what type of query is required — ANY, A, MX, SIG, etc. type can be any valid query type. If no type argument is supplied, dig will perform a lookup for an A record.

OPTIONS

-4

Use IPv4 only.

-6

Use IPv6 only.

-b address[#port]

Set the source IP address of the query. The address must be a valid address on one of the host's network interfaces, or "0.0.0.0" or "::". An optional port may be specified by appending "#<port>"

-c class

Set the query class. The default class is IN; other classes are HS for Hesiod records or CH for Chaosnet records.

-f file

Batch mode: dig reads a list of lookup requests to process from the given file. Each line in the file should be organized in the same way they would be presented as queries to dig using the command-line interface.

-i

Do reverse IPv6 lookups using the obsolete RFC1886 IP6.INT domain, which is no longer in use. Obsolete bit string label queries (RFC2874) are not attempted.

-k keyfile

Sign queries using TSIG using a key read from the given file. Key files can be generated using tsig-keygen(8) . When using TSIG authentication with dig, the name server that is queried needs to know the key and algorithm that is being used. In BIND, this is done by providing appropriate key and server statements in named.conf.

-m

Enable memory usage debugging.

-p port

Send the query to a non-standard port on the server, instead of the default port 53. This option would be used to test a name server that has been configured to listen for queries on a non-standard port number.

-q name

The domain name to query. This is useful to distinguish the name from other arguments.

-t type

The resource record type to query. It can be any valid query type which is supported in BIND 9. The default query type is "A", unless the -x option is supplied to indicate a reverse lookup. A zone transfer can be requested by specifying a type of AXFR. When an incremental zone transfer (IXFR) is required, set the type to ixfr=N. The incremental zone transfer will contain the changes made to the zone since the serial number in the zone's SOA record was N.

-u

Print query times in microseconds instead of milliseconds.

-v

Print the version number and exit.

-x addr

Simplified reverse lookups, for mapping addresses to names. The addr is an IPv4 address in dotted-decimal notation, or a colon-delimited IPv6 address. When the -x is used, there is no need to provide the name, class and type arguments. dig automatically performs a lookup for a name like 94.2.0.192.in-addr.arpa and sets the query type and class to PTR and IN respectively. IPv6 addresses are looked up using nibble format under the IP6.ARPA domain (but see also the -i option).

-y [hmac:]keyname:secret

Sign queries using TSIG with the given authentication key. keyname is the name of the key, and secret is the base64 encoded shared secret. hmac is the name of the key algorithm; valid choices are hmac-md5, hmac-sha1, hmac-sha224, hmac-sha256, hmac-sha384, or hmac-sha512. If hmac is not specified, the default is hmac-md5 or if MD5 was disabled hmac-sha256.

NOTE: You should use the -k option and avoid the -y option, because with -y the shared secret is supplied as a command line argument in clear text. This may be visible in the output from ps(1) or in a history file maintained by the user's shell.

QUERY OPTIONS

dig provides a number of query options which affect the way in which lookups are made and the results displayed. Some of these set or reset flag bits in the query header, some determine which sections of the answer get printed, and others determine the timeout and retry strategies.

Each query option is identified by a keyword preceded by a plus sign (+). Some keywords set or reset an option. These may be preceded by the string no to negate the meaning of that keyword. Other keywords assign values to options like the timeout interval. They have the form +keyword=value. Keywords may be abbreviated, provided the abbreviation is unambiguous; for example, +cd is equivalent to +cdflag. The query options are:

+[no]aaflag

A synonym for +[no]aaonly.

+[no]aaonly

Sets the "aa" flag in the query.

+[no]additional

Display [do not display] the additional section of a reply. The default is to display it.

+[no]adflag

Set [do not set] the AD (authentic data) bit in the query. This requests the server to return whether all of the answer and authority sections have all been validated as secure according to the security policy of the server. AD=1 indicates that all records have been validated as secure and the answer is not from a OPT-OUT range. AD=0 indicate that some part of the answer was insecure or not validated. This bit is set by default.

+[no]all

Set or clear all display flags.

+[no]answer

Display [do not display] the answer section of a reply. The default is to display it.

+[no]authority

Display [do not display] the authority section of a reply. The default is to display it.

+[no]badcookie

Retry lookup with the new server cookie if a BADCOOKIE response is received.

+[no]besteffort

Attempt to display the contents of messages which are malformed. The default is to not display malformed answers.

+bufsize=B

Set the UDP message buffer size advertised using EDNS0 to B bytes. The maximum and minimum sizes of this buffer are 65535 and 0 respectively. Values outside this range are rounded up or down appropriately. Values other than zero will cause a EDNS query to be sent.

+[no]cdflag

Set [do not set] the CD (checking disabled) bit in the query. This requests the server to not perform DNSSEC validation of responses.

+[no]class

Display [do not display] the CLASS when printing the record.

+[no]cmd

Toggles the printing of the initial comment in the output identifying the version of dig and the query options that have been applied. This comment is printed by default.

+[no]comments

Toggle the display of comment lines in the output. The default is to print comments.

+[no]cookie[=####]

Send a COOKIE EDNS option, with optional value. Replaying a COOKIE from a previous response will allow the server to identify a previous client. The default is +cookie.

+cookie is also set when +trace is set to better emulate the default queries from a nameserver.

+[no]crypto

Toggle the display of cryptographic fields in DNSSEC records. The contents of these field are unnecessary to debug most DNSSEC validation failures and removing them makes it easier to see the common failures. The default is to display the fields. When omitted they are replaced by the string "[omitted]" or in the DNSKEY case the key id is displayed as the replacement, e.g. "[ key id = value ]".

+[no]defname

Deprecated, treated as a synonym for +[no]search

+[no]dnssec

Requests DNSSEC records be sent by setting the DNSSEC OK bit (DO) in the OPT record in the additional section of the query.

+domain=somename

Set the search list to contain the single domain somename, as if specified in a domain directive in /etc/resolv.conf, and enable search list processing as if the +search option were given.

+dscp=value

Set the DSCP code point to be used when sending the query. Valid DSCP code points are in the range [0..63]. By default no code point is explicitly set.

+[no]edns[=#]

Specify the EDNS version to query with. Valid values are 0 to 255. Setting the EDNS version will cause a EDNS query to be sent. +noedns clears the remembered EDNS version. EDNS is set to 0 by default.

+[no]ednsflags[=#]

Set the must-be-zero EDNS flags bits (Z bits) to the specified value. Decimal, hex and octal encodings are accepted. Setting a named flag (e.g. DO) will silently be ignored. By default, no Z bits are set.

+[no]ednsnegotiation

Enable / disable EDNS version negotiation. By default EDNS version negotiation is enabled.

+[no]ednsopt[=code[:value]]

Specify EDNS option with code point code and optionally payload of value as a hexadecimal string. code can be either an EDNS option name (for example, NSID or ECS), or an arbitrary numeric value. +noednsopt clears the EDNS options to be sent.

+[no]expire

Send an EDNS Expire option.

+[no]fail

Do not try the next server if you receive a SERVFAIL. The default is to not try the next server which is the reverse of normal stub resolver behavior.

+[no]header-only

Send a query with a DNS header without a question section. The default is to add a question section. The query type and query name are ignored when this is set.

+[no]identify

Show [or do not show] the IP address and port number that supplied the answer when the +short option is enabled. If short form answers are requested, the default is not to show the source address and port number of the server that provided the answer.

+[no]idnout

Convert [do not convert] puny code on output. This requires IDN SUPPORT to have been enabled at compile time. The default is to convert output.

+[no]ignore

Ignore truncation in UDP responses instead of retrying with TCP. By default, TCP retries are performed.

+[no]keepopen

Keep the TCP socket open between queries and reuse it rather than creating a new TCP socket for each lookup. The default is +nokeepopen.

+[no]mapped

Allow mapped IPv4 over IPv6 addresses to be used. The default is +mapped.

+[no]multiline

Print records like the SOA records in a verbose multi-line format with human-readable comments. The default is to print each record on a single line, to facilitate machine parsing of the dig output.

+ndots=D

Set the number of dots that have to appear in name to D for it to be considered absolute. The default value is that defined using the ndots statement in /etc/resolv.conf, or 1 if no ndots statement is present. Names with fewer dots are interpreted as relative names and will be searched for in the domains listed in the search or domain directive in /etc/resolv.conf if +search is set.

+[no]nsid

Include an EDNS name server ID request when sending a query.

+[no]nssearch

When this option is set, dig attempts to find the authoritative name servers for the zone containing the name being looked up and display the SOA record that each name server has for the zone.

+[no]onesoa

Print only one (starting) SOA record when performing an AXFR. The default is to print both the starting and ending SOA records.

+[no]opcode=value

Set [restore] the DNS message opcode to the specified value. The default value is QUERY (0).

+[no]qr

Print [do not print] the query as it is sent. By default, the query is not printed.

+[no]question

Print [do not print] the question section of a query when an answer is returned. The default is to print the question section as a comment.

+[no]rdflag

A synonym for +[no]recurse.

+[no]recurse

Toggle the setting of the RD (recursion desired) bit in the query. This bit is set by default, which means dig normally sends recursive queries. Recursion is automatically disabled when the +nssearch or +trace query options are used.

+retry=T

Sets the number of times to retry UDP queries to server to T instead of the default, 2. Unlike +tries, this does not include the initial query.

+[no]rrcomments

Toggle the display of per-record comments in the output (for example, human-readable key information about DNSKEY records). The default is not to print record comments unless multiline mode is active.

+[no]search

Use [do not use] the search list defined by the searchlist or domain directive in resolv.conf (if any). The search list is not used by default.

'ndots' from resolv.conf (default 1) which may be overridden by +ndots determines if the name will be treated as relative or not and hence whether a search is eventually performed or not.

+[no]short

Provide a terse answer. The default is to print the answer in a verbose form.

+[no]showsearch

Perform [do not perform] a search showing intermediate results.

+[no]sigchase

Chase DNSSEC signature chains. Requires dig be compiled with -DDIG_SIGCHASE. This feature is deprecated. Use delv instead.

+split=W

Split long hex- or base64-formatted fields in resource records into chunks of W characters (where W is rounded up to the nearest multiple of 4). +nosplit or +split=0 causes fields not to be split at all. The default is 56 characters, or 44 characters when multiline mode is active.

+[no]stats

This query option toggles the printing of statistics: when the query was made, the size of the reply and so on. The default behavior is to print the query statistics.

+[no]subnet=addr[/prefix-length]

Send (don't send) an EDNS Client Subnet option with the specified IP address or network prefix.

dig +subnet=0.0.0.0/0, or simply dig +subnet=0 for short, sends an EDNS CLIENT-SUBNET option with an empty address and a source prefix-length of zero, which signals a resolver that the client's address information must not be used when resolving this query.

+[no]tcp

Use [do not use] TCP when querying name servers. The default behavior is to use UDP unless a type any or ixfr=N query is requested, in which case the default is TCP. AXFR queries always use TCP.

+timeout=T

Sets the timeout for a query to T seconds. The default timeout is 5 seconds. An attempt to set T to less than 1 will result in a query timeout of 1 second being applied.

+[no]topdown

When chasing DNSSEC signature chains perform a top-down validation. Requires dig be compiled with -DDIG_SIGCHASE. This feature is deprecated. Use delv instead.

+[no]trace

Toggle tracing of the delegation path from the root name servers for the name being looked up. Tracing is disabled by default. When tracing is enabled, dig makes iterative queries to resolve the name being looked up. It will follow referrals from the root servers, showing the answer from each server that was used to resolve the lookup.

If @server is also specified, it affects only the initial query for the root zone name servers.

+dnssec is also set when +trace is set to better emulate the default queries from a nameserver.

+tries=T

Sets the number of times to try UDP queries to server to T instead of the default, 3. If T is less than or equal to zero, the number of tries is silently rounded up to 1.

+trusted-key=####

Specifies a file containing trusted keys to be used with +sigchase. Each DNSKEY record must be on its own line.

If not specified, dig will look for /etc/trusted-key.key then trusted-key.key in the current directory.

Requires dig be compiled with -DDIG_SIGCHASE. This feature is deprecated. Use delv instead.

+[no]ttlid

Display [do not display] the TTL when printing the record.

+[no]ttlunits

Display [do not display] the TTL in friendly human-readable time units of "s", "m", "h", "d", and "w", representing seconds, minutes, hours, days and weeks. Implies +ttlid.

+[no]unknownformat

Print all RDATA in unknown RR type presentation format (RFC 3597). The default is to print RDATA for known types in the type's presentation format.

+[no]vc

Use [do not use] TCP when querying name servers. This alternate syntax to +[no]tcp is provided for backwards compatibility. The "vc" stands for "virtual circuit".

+[no]zflag

Set [do not set] the last unassigned DNS header flag in a DNS query. This flag is off by default.

MULTIPLE QUERIES

The BIND 9 implementation of dig supports specifying multiple queries on the command line (in addition to supporting the -f batch file option). Each of those queries can be supplied with its own set of flags, options and query options.

In this case, each query argument represent an individual query in the command-line syntax described above. Each consists of any of the standard options and flags, the name to be looked up, an optional query type and class and any query options that should be applied to that query.

A global set of query options, which should be applied to all queries, can also be supplied. These global query options must precede the first tuple of name, class, type, options, flags, and query options supplied on the command line. Any global query options (except the +[no]cmd option) can be overridden by a query-specific set of query options. For example:

dig +qr www.isc.org any -x 127.0.0.1 isc.org ns +noqr

shows how dig could be used from the command line to make three lookups: an ANY query for www.isc.org, a reverse lookup of 127.0.0.1 and a query for the NS records of isc.org. A global query option of +qr is applied, so that dig shows the initial query it made for each lookup. The final query has a local query option of +noqr which means that dig will not print the initial query when it looks up the NS records for isc.org.

IDN SUPPORT

If dig has been built with IDN (internationalized domain name) support, it can accept and display non-ASCII domain names. dig appropriately converts character encoding of domain name before sending a request to DNS server or displaying a reply from the server. If you'd like to turn off the IDN support for some reason, defines the IDN_DISABLE environment variable. The IDN support is disabled if the variable is set when dig runs.

FILES

/etc/resolv.conf

${HOME}/.digrc

SEE ALSO

delv(1) , host(1) , named(8) , dnssec-keygen(8) , RFC1035.

BUGS

There are probably too many query options.

bind9-9.11.3+dfsg/bin/dig/dighost.c000066400000000000000000005222311325250447100166610ustar00rootroot00000000000000/* * Copyright (C) 2000-2017 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /*! \file * \note * Notice to programmers: Do not use this code as an example of how to * use the ISC library to perform DNS lookups. Dig and Host both operate * on the request level, since they allow fine-tuning of output and are * intended as debugging tools. As a result, they perform many of the * functions which could be better handled using the dns_resolver * functions in most applications. */ #include #include #include #include #include #ifdef HAVE_LOCALE_H #include #endif #ifdef WITH_IDN #include #include #include #include #endif #include #ifdef DIG_SIGCHASE #include #include #include #include #include #include #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef PKCS11CRYPTO #include #endif #if ! defined(NS_INADDRSZ) #define NS_INADDRSZ 4 #endif #if ! defined(NS_IN6ADDRSZ) #define NS_IN6ADDRSZ 16 #endif static lwres_context_t *lwctx = NULL; static lwres_conf_t *lwconf; dig_lookuplist_t lookup_list; dig_serverlist_t server_list; dig_searchlistlist_t search_list; isc_boolean_t check_ra = ISC_FALSE, have_ipv4 = ISC_FALSE, have_ipv6 = ISC_FALSE, specified_source = ISC_FALSE, free_now = ISC_FALSE, cancel_now = ISC_FALSE, usesearch = ISC_FALSE, showsearch = ISC_FALSE, qr = ISC_FALSE, is_dst_up = ISC_FALSE, keep_open = ISC_FALSE, verbose = ISC_FALSE; in_port_t port = 53; unsigned int timeout = 0; unsigned int extrabytes; isc_mem_t *mctx = NULL; isc_log_t *lctx = NULL; isc_taskmgr_t *taskmgr = NULL; isc_task_t *global_task = NULL; isc_timermgr_t *timermgr = NULL; isc_socketmgr_t *socketmgr = NULL; isc_sockaddr_t bind_address; isc_sockaddr_t bind_any; int sendcount = 0; int recvcount = 0; int sockcount = 0; int ndots = -1; int tries = 3; int lookup_counter = 0; static char servercookie[256]; #ifdef WITH_IDN static void initialize_idn(void); static isc_result_t output_filter(isc_buffer_t *buffer, unsigned int used_org, isc_boolean_t absolute); static idn_result_t append_textname(char *name, const char *origin, size_t namesize); static void idn_check_result(idn_result_t r, const char *msg); #define MAXDLEN 256 int idnoptions = 0; #endif isc_socket_t *keep = NULL; isc_sockaddr_t keepaddr; /*% * Exit Codes: * *\li 0 Everything went well, including things like NXDOMAIN *\li 1 Usage error *\li 7 Got too many RR's or Names *\li 8 Couldn't open batch file *\li 9 No reply from server *\li 10 Internal error */ int exitcode = 0; int fatalexit = 0; char keynametext[MXNAME]; char keyfile[MXNAME] = ""; char keysecret[MXNAME] = ""; unsigned char cookie_secret[33]; unsigned char cookie[8]; dns_name_t *hmacname = NULL; unsigned int digestbits = 0; isc_buffer_t *namebuf = NULL; dns_tsigkey_t *key = NULL; isc_boolean_t validated = ISC_TRUE; isc_entropy_t *entp = NULL; isc_mempool_t *commctx = NULL; isc_boolean_t debugging = ISC_FALSE; isc_boolean_t debugtiming = ISC_FALSE; isc_boolean_t memdebugging = ISC_FALSE; char *progname = NULL; isc_mutex_t lookup_lock; dig_lookup_t *current_lookup = NULL; #ifdef DIG_SIGCHASE isc_result_t get_trusted_key(void); dns_rdataset_t * sigchase_scanname(dns_rdatatype_t type, dns_rdatatype_t covers, isc_boolean_t *lookedup, dns_name_t *rdata_name); dns_rdataset_t * chase_scanname_section(dns_message_t *msg, dns_name_t *name, dns_rdatatype_t type, dns_rdatatype_t covers, int section); isc_result_t advanced_rrsearch(dns_rdataset_t **rdataset, dns_name_t *name, dns_rdatatype_t type, dns_rdatatype_t covers, isc_boolean_t *lookedup); isc_result_t sigchase_verify_sig_key(dns_name_t *name, dns_rdataset_t *rdataset, dst_key_t* dnsseckey, dns_rdataset_t *sigrdataset); isc_result_t sigchase_verify_sig(dns_name_t *name, dns_rdataset_t *rdataset, dns_rdataset_t *keyrdataset, dns_rdataset_t *sigrdataset); isc_result_t sigchase_verify_ds(dns_name_t *name, dns_rdataset_t *keyrdataset, dns_rdataset_t *dsrdataset); void sigchase(dns_message_t *msg); void print_rdata(dns_rdata_t *rdata, isc_mem_t *mctx); void print_rdataset(dns_name_t *name, dns_rdataset_t *rdataset); void dup_name(dns_name_t *source, dns_name_t* target); void free_name(dns_name_t *name); void dump_database(void); void dump_database_section(dns_message_t *msg, int section); dns_rdataset_t * search_type(dns_name_t *name, dns_rdatatype_t type, dns_rdatatype_t covers); isc_result_t contains_trusted_key(dns_name_t *name, dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset); void print_type(dns_rdatatype_t type); isc_result_t prove_nx_domain(dns_message_t * msg, dns_name_t * name, dns_name_t * rdata_name, dns_rdataset_t ** rdataset, dns_rdataset_t ** sigrdataset); isc_result_t prove_nx_type(dns_message_t * msg, dns_name_t *name, dns_rdataset_t *nsec, dns_rdataclass_t rdclass, dns_rdatatype_t type, dns_name_t * rdata_name, dns_rdataset_t ** rdataset, dns_rdataset_t ** sigrdataset); isc_result_t prove_nx(dns_message_t * msg, dns_name_t * name, dns_rdataclass_t rdclass, dns_rdatatype_t type, dns_name_t * rdata_name, dns_rdataset_t ** rdataset, dns_rdataset_t ** sigrdataset); static void nameFromString(const char *str, dns_name_t *p_ret); int inf_name(dns_name_t * name1, dns_name_t * name2); isc_result_t removetmpkey(const char *file); void clean_trustedkey(void); isc_result_t insert_trustedkey(void *arg, dns_name_t *name, dns_rdataset_t *rdataset); #if DIG_SIGCHASE_BU isc_result_t getneededrr(dns_message_t *msg); void sigchase_bottom_up(dns_message_t *msg); void sigchase_bu(dns_message_t *msg); #endif #if DIG_SIGCHASE_TD isc_result_t initialization(dns_name_t *name); isc_result_t prepare_lookup(dns_name_t *name); isc_result_t grandfather_pb_test(dns_name_t * zone_name, dns_rdataset_t *sigrdataset); isc_result_t child_of_zone(dns_name_t *name, dns_name_t *zone_name, dns_name_t *child_name); void sigchase_td(dns_message_t *msg); #endif char trustedkey[MXNAME] = ""; dns_rdataset_t *chase_rdataset = NULL; dns_rdataset_t *chase_sigrdataset = NULL; dns_rdataset_t *chase_dsrdataset = NULL; dns_rdataset_t *chase_sigdsrdataset = NULL; dns_rdataset_t *chase_keyrdataset = NULL; dns_rdataset_t *chase_sigkeyrdataset = NULL; dns_rdataset_t *chase_nsrdataset = NULL; dns_name_t chase_name; /* the query name */ #if DIG_SIGCHASE_TD /* * the current name is the parent name when we follow delegation */ dns_name_t chase_current_name; /* * the child name is used for delegation (NS DS responses in AUTHORITY section) */ dns_name_t chase_authority_name; #endif #if DIG_SIGCHASE_BU dns_name_t chase_signame; #endif isc_boolean_t chase_siglookedup = ISC_FALSE; isc_boolean_t chase_keylookedup = ISC_FALSE; isc_boolean_t chase_sigkeylookedup = ISC_FALSE; isc_boolean_t chase_dslookedup = ISC_FALSE; isc_boolean_t chase_sigdslookedup = ISC_FALSE; #if DIG_SIGCHASE_TD isc_boolean_t chase_nslookedup = ISC_FALSE; isc_boolean_t chase_lookedup = ISC_FALSE; isc_boolean_t delegation_follow = ISC_FALSE; isc_boolean_t grandfather_pb = ISC_FALSE; isc_boolean_t have_response = ISC_FALSE; isc_boolean_t have_delegation_ns = ISC_FALSE; dns_message_t * error_message = NULL; #endif isc_boolean_t dsvalidating = ISC_FALSE; isc_boolean_t chase_name_dup = ISC_FALSE; ISC_LIST(dig_message_t) chase_message_list; ISC_LIST(dig_message_t) chase_message_list2; #define MAX_TRUSTED_KEY 5 typedef struct struct_trusted_key_list { dst_key_t * key[MAX_TRUSTED_KEY]; int nb_tk; } struct_tk_list; struct_tk_list tk_list = { {NULL, NULL, NULL, NULL, NULL}, 0}; #endif #define DIG_MAX_ADDRESSES 20 /*% * Apply and clear locks at the event level in global task. * Can I get rid of these using shutdown events? XXX */ #define LOCK_LOOKUP {\ debug("lock_lookup %s:%d", __FILE__, __LINE__);\ check_result(isc_mutex_lock((&lookup_lock)), "isc_mutex_lock");\ debug("success");\ } #define UNLOCK_LOOKUP {\ debug("unlock_lookup %s:%d", __FILE__, __LINE__);\ check_result(isc_mutex_unlock((&lookup_lock)),\ "isc_mutex_unlock");\ } /* dynamic callbacks */ #ifdef DIG_SIGCHASE isc_result_t (*dighost_printrdataset)(dns_name_t *owner_name, dns_rdataset_t *rdataset, isc_buffer_t *target); #endif isc_result_t (*dighost_printmessage)(dig_query_t *query, dns_message_t *msg, isc_boolean_t headers); void (*dighost_received)(int bytes, isc_sockaddr_t *from, dig_query_t *query); void (*dighost_trying)(char *frm, dig_lookup_t *lookup); void (*dighost_shutdown)(void); /* forward declarations */ static void cancel_lookup(dig_lookup_t *lookup); static void recv_done(isc_task_t *task, isc_event_t *event); static void send_udp(dig_query_t *query); static void connect_timeout(isc_task_t *task, isc_event_t *event); static void launch_next_query(dig_query_t *query, isc_boolean_t include_question); static void check_next_lookup(dig_lookup_t *lookup); static isc_boolean_t next_origin(dig_lookup_t *oldlookup); static void * mem_alloc(void *arg, size_t size) { return (isc_mem_get(arg, size)); } static void mem_free(void *arg, void *mem, size_t size) { isc_mem_put(arg, mem, size); } char * next_token(char **stringp, const char *delim) { char *res; do { res = strsep(stringp, delim); if (res == NULL) break; } while (*res == '\0'); return (res); } static int count_dots(char *string) { char *s; int i = 0; s = string; while (*s != '\0') { if (*s == '.') i++; s++; } return (i); } static void hex_dump(isc_buffer_t *b) { unsigned int len, i; isc_region_t r; isc_buffer_usedregion(b, &r); printf("%d bytes\n", r.length); for (len = 0; len < r.length; len++) { printf("%02x ", r.base[len]); if (len % 16 == 15) { fputs(" ", stdout); for (i = len - 15; i <= len; i++) { if (r.base[i] >= '!' && r.base[i] <= '}') putchar(r.base[i]); else putchar('.'); } printf("\n"); } } if (len % 16 != 0) { for (i = len; (i % 16) != 0; i++) fputs(" ", stdout); fputs(" ", stdout); for (i = ((len>>4)<<4); i < len; i++) { if (r.base[i] >= '!' && r.base[i] <= '}') putchar(r.base[i]); else putchar('.'); } printf("\n"); } } /*% * Append 'len' bytes of 'text' at '*p', failing with * ISC_R_NOSPACE if that would advance p past 'end'. */ static isc_result_t append(const char *text, size_t len, char **p, char *end) { if (*p + len > end) return (ISC_R_NOSPACE); memmove(*p, text, len); *p += len; return (ISC_R_SUCCESS); } static isc_result_t reverse_octets(const char *in, char **p, char *end) { const char *dot = strchr(in, '.'); size_t len; if (dot != NULL) { isc_result_t result; result = reverse_octets(dot + 1, p, end); if (result != ISC_R_SUCCESS) return (result); result = append(".", 1, p, end); if (result != ISC_R_SUCCESS) return (result); len = (int) (dot - in); } else { len = (int) strlen(in); } return (append(in, len, p, end)); } isc_result_t get_reverse(char *reverse, size_t len, char *value, isc_boolean_t ip6_int, isc_boolean_t strict) { int r; isc_result_t result; isc_netaddr_t addr; addr.family = AF_INET6; r = inet_pton(AF_INET6, value, &addr.type.in6); if (r > 0) { /* This is a valid IPv6 address. */ dns_fixedname_t fname; dns_name_t *name; unsigned int options = 0; if (ip6_int) options |= DNS_BYADDROPT_IPV6INT; dns_fixedname_init(&fname); name = dns_fixedname_name(&fname); result = dns_byaddr_createptrname2(&addr, options, name); if (result != ISC_R_SUCCESS) return (result); dns_name_format(name, reverse, (unsigned int)len); return (ISC_R_SUCCESS); } else { /* * Not a valid IPv6 address. Assume IPv4. * If 'strict' is not set, construct the * in-addr.arpa name by blindly reversing * octets whether or not they look like integers, * so that this can be used for RFC2317 names * and such. */ char *p = reverse; char *end = reverse + len; if (strict && inet_pton(AF_INET, value, &addr.type.in) != 1) return (DNS_R_BADDOTTEDQUAD); result = reverse_octets(value, &p, end); if (result != ISC_R_SUCCESS) return (result); /* Append .in-addr.arpa. and a terminating NUL. */ result = append(".in-addr.arpa.", 15, &p, end); if (result != ISC_R_SUCCESS) return (result); return (ISC_R_SUCCESS); } } void fatal(const char *format, ...) { va_list args; fflush(stdout); fprintf(stderr, "%s: ", progname); va_start(args, format); vfprintf(stderr, format, args); va_end(args); fprintf(stderr, "\n"); if (exitcode < 10) exitcode = 10; if (fatalexit != 0) exitcode = fatalexit; exit(exitcode); } void debug(const char *format, ...) { va_list args; isc_time_t t; if (debugging) { fflush(stdout); if (debugtiming) { TIME_NOW(&t); fprintf(stderr, "%d.%06d: ", isc_time_seconds(&t), isc_time_nanoseconds(&t) / 1000); } va_start(args, format); vfprintf(stderr, format, args); va_end(args); fprintf(stderr, "\n"); } } void check_result(isc_result_t result, const char *msg) { if (result != ISC_R_SUCCESS) { fatal("%s: %s", msg, isc_result_totext(result)); } } /*% * Create a server structure, which is part of the lookup structure. * This is little more than a linked list of servers to query in hopes * of finding the answer the user is looking for */ dig_server_t * make_server(const char *servname, const char *userarg) { dig_server_t *srv; REQUIRE(servname != NULL); debug("make_server(%s)", servname); srv = isc_mem_allocate(mctx, sizeof(struct dig_server)); if (srv == NULL) fatal("memory allocation failure in %s:%d", __FILE__, __LINE__); strlcpy(srv->servername, servname, MXNAME); strlcpy(srv->userarg, userarg, MXNAME); ISC_LINK_INIT(srv, link); return (srv); } static int addr2af(int lwresaddrtype) { int af = 0; switch (lwresaddrtype) { case LWRES_ADDRTYPE_V4: af = AF_INET; break; case LWRES_ADDRTYPE_V6: af = AF_INET6; break; } return (af); } /*% * Create a copy of the server list from the lwres configuration structure. * The dest list must have already had ISC_LIST_INIT applied. */ static void copy_server_list(lwres_conf_t *confdata, dig_serverlist_t *dest) { dig_server_t *newsrv; char tmp[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255") + sizeof("%4000000000")]; int af; int i; debug("copy_server_list()"); for (i = 0; i < confdata->nsnext; i++) { af = addr2af(confdata->nameservers[i].family); if (af == AF_INET && !have_ipv4) continue; if (af == AF_INET6 && !have_ipv6) continue; lwres_net_ntop(af, confdata->nameservers[i].address, tmp, sizeof(tmp)); if (af == AF_INET6 && confdata->nameservers[i].zone != 0) { char buf[sizeof("%4000000000")]; snprintf(buf, sizeof(buf), "%%%u", confdata->nameservers[i].zone); strlcat(tmp, buf, sizeof(tmp)); } newsrv = make_server(tmp, tmp); ISC_LINK_INIT(newsrv, link); ISC_LIST_ENQUEUE(*dest, newsrv, link); } } void flush_server_list(void) { dig_server_t *s, *ps; debug("flush_server_list()"); s = ISC_LIST_HEAD(server_list); while (s != NULL) { ps = s; s = ISC_LIST_NEXT(s, link); ISC_LIST_DEQUEUE(server_list, ps, link); isc_mem_free(mctx, ps); } } void set_nameserver(char *opt) { isc_result_t result; isc_sockaddr_t sockaddrs[DIG_MAX_ADDRESSES]; isc_netaddr_t netaddr; int count, i; dig_server_t *srv; char tmp[ISC_NETADDR_FORMATSIZE]; if (opt == NULL) return; result = bind9_getaddresses(opt, 0, sockaddrs, DIG_MAX_ADDRESSES, &count); if (result != ISC_R_SUCCESS) fatal("couldn't get address for '%s': %s", opt, isc_result_totext(result)); flush_server_list(); for (i = 0; i < count; i++) { isc_netaddr_fromsockaddr(&netaddr, &sockaddrs[i]); isc_netaddr_format(&netaddr, tmp, sizeof(tmp)); srv = make_server(tmp, opt); if (srv == NULL) fatal("memory allocation failure"); ISC_LIST_APPEND(server_list, srv, link); } } static isc_result_t add_nameserver(lwres_conf_t *confdata, const char *addr, int af) { int i = confdata->nsnext; if (confdata->nsnext >= LWRES_CONFMAXNAMESERVERS) return (ISC_R_FAILURE); switch (af) { case AF_INET: confdata->nameservers[i].family = LWRES_ADDRTYPE_V4; confdata->nameservers[i].length = NS_INADDRSZ; break; case AF_INET6: confdata->nameservers[i].family = LWRES_ADDRTYPE_V6; confdata->nameservers[i].length = NS_IN6ADDRSZ; break; default: return (ISC_R_FAILURE); } if (lwres_net_pton(af, addr, &confdata->nameservers[i].address) == 1) { confdata->nsnext++; return (ISC_R_SUCCESS); } return (ISC_R_FAILURE); } /*% * Produce a cloned server list. The dest list must have already had * ISC_LIST_INIT applied. */ void clone_server_list(dig_serverlist_t src, dig_serverlist_t *dest) { dig_server_t *srv, *newsrv; debug("clone_server_list()"); srv = ISC_LIST_HEAD(src); while (srv != NULL) { newsrv = make_server(srv->servername, srv->userarg); ISC_LINK_INIT(newsrv, link); ISC_LIST_ENQUEUE(*dest, newsrv, link); srv = ISC_LIST_NEXT(srv, link); } } /*% * Create an empty lookup structure, which holds all the information needed * to get an answer to a user's question. This structure contains two * linked lists: the server list (servers to query) and the query list * (outstanding queries which have been made to the listed servers). */ dig_lookup_t * make_empty_lookup(void) { dig_lookup_t *looknew; debug("make_empty_lookup()"); INSIST(!free_now); looknew = isc_mem_allocate(mctx, sizeof(struct dig_lookup)); if (looknew == NULL) fatal("memory allocation failure in %s:%d", __FILE__, __LINE__); looknew->pending = ISC_TRUE; looknew->textname[0] = 0; looknew->cmdline[0] = 0; looknew->rdtype = dns_rdatatype_a; looknew->qrdtype = dns_rdatatype_a; looknew->rdclass = dns_rdataclass_in; looknew->rdtypeset = ISC_FALSE; looknew->rdclassset = ISC_FALSE; looknew->sendspace = NULL; looknew->sendmsg = NULL; looknew->name = NULL; looknew->oname = NULL; looknew->xfr_q = NULL; looknew->current_query = NULL; looknew->doing_xfr = ISC_FALSE; looknew->ixfr_serial = 0; looknew->trace = ISC_FALSE; looknew->trace_root = ISC_FALSE; looknew->identify = ISC_FALSE; looknew->identify_previous_line = ISC_FALSE; looknew->ignore = ISC_FALSE; looknew->servfail_stops = ISC_TRUE; looknew->besteffort = ISC_TRUE; looknew->dnssec = ISC_FALSE; looknew->ednsflags = 0; looknew->opcode = dns_opcode_query; looknew->expire = ISC_FALSE; looknew->nsid = ISC_FALSE; looknew->header_only = ISC_FALSE; looknew->sendcookie = ISC_FALSE; looknew->seenbadcookie = ISC_FALSE; looknew->badcookie = ISC_TRUE; #ifdef WITH_IDN looknew->idnout = ISC_TRUE; #else looknew->idnout = ISC_FALSE; #endif #ifdef DIG_SIGCHASE looknew->sigchase = ISC_FALSE; #if DIG_SIGCHASE_TD looknew->do_topdown = ISC_FALSE; looknew->trace_root_sigchase = ISC_FALSE; looknew->rdtype_sigchaseset = ISC_FALSE; looknew->rdtype_sigchase = dns_rdatatype_any; looknew->qrdtype_sigchase = dns_rdatatype_any; looknew->rdclass_sigchase = dns_rdataclass_in; looknew->rdclass_sigchaseset = ISC_FALSE; #endif #endif looknew->udpsize = 0; looknew->edns = -1; looknew->recurse = ISC_TRUE; looknew->aaonly = ISC_FALSE; looknew->adflag = ISC_FALSE; looknew->cdflag = ISC_FALSE; looknew->print_unknown_format = ISC_FALSE; looknew->zflag = ISC_FALSE; looknew->ns_search_only = ISC_FALSE; looknew->origin = NULL; looknew->tsigctx = NULL; looknew->querysig = NULL; looknew->retries = tries; looknew->nsfound = 0; looknew->tcp_mode = ISC_FALSE; looknew->tcp_mode_set = ISC_FALSE; looknew->ip6_int = ISC_FALSE; looknew->comments = ISC_TRUE; looknew->stats = ISC_TRUE; looknew->section_question = ISC_TRUE; looknew->section_answer = ISC_TRUE; looknew->section_authority = ISC_TRUE; looknew->section_additional = ISC_TRUE; looknew->new_search = ISC_FALSE; looknew->done_as_is = ISC_FALSE; looknew->need_search = ISC_FALSE; looknew->ecs_addr = NULL; looknew->cookie = NULL; looknew->ednsopts = NULL; looknew->ednsoptscnt = 0; looknew->ednsneg = ISC_TRUE; looknew->mapped = ISC_TRUE; looknew->dscp = -1; looknew->eoferr = 0; dns_fixedname_init(&looknew->fdomain); ISC_LINK_INIT(looknew, link); ISC_LIST_INIT(looknew->q); ISC_LIST_INIT(looknew->connecting); ISC_LIST_INIT(looknew->my_server_list); return (looknew); } #define EDNSOPT_OPTIONS 100U static void cloneopts(dig_lookup_t *looknew, dig_lookup_t *lookold) { size_t len = sizeof(looknew->ednsopts[0]) * EDNSOPT_OPTIONS; size_t i; looknew->ednsopts = isc_mem_allocate(mctx, len); if (looknew->ednsopts == NULL) fatal("out of memory"); for (i = 0; i < EDNSOPT_OPTIONS; i++) { looknew->ednsopts[i].code = 0; looknew->ednsopts[i].length = 0; looknew->ednsopts[i].value = NULL; } looknew->ednsoptscnt = 0; if (lookold == NULL || lookold->ednsopts == NULL) return; for (i = 0; i < lookold->ednsoptscnt; i++) { len = lookold->ednsopts[i].length; if (len != 0) { INSIST(lookold->ednsopts[i].value != NULL); looknew->ednsopts[i].value = isc_mem_allocate(mctx, len); if (looknew->ednsopts[i].value == NULL) fatal("out of memory"); memmove(looknew->ednsopts[i].value, lookold->ednsopts[i].value, len); } looknew->ednsopts[i].code = lookold->ednsopts[i].code; looknew->ednsopts[i].length = len; } looknew->ednsoptscnt = lookold->ednsoptscnt; } /*% * Clone a lookup, perhaps copying the server list. This does not clone * the query list, since it will be regenerated by the setup_lookup() * function, nor does it queue up the new lookup for processing. * Caution: If you don't clone the servers, you MUST clone the server * list separately from somewhere else, or construct it by hand. */ dig_lookup_t * clone_lookup(dig_lookup_t *lookold, isc_boolean_t servers) { dig_lookup_t *looknew; debug("clone_lookup()"); INSIST(!free_now); looknew = make_empty_lookup(); INSIST(looknew != NULL); strlcpy(looknew->textname, lookold->textname, MXNAME); #if DIG_SIGCHASE_TD strlcpy(looknew->textnamesigchase, lookold->textnamesigchase, MXNAME); #endif strlcpy(looknew->cmdline, lookold->cmdline, MXNAME); looknew->textname[MXNAME-1] = 0; looknew->rdtype = lookold->rdtype; looknew->qrdtype = lookold->qrdtype; looknew->rdclass = lookold->rdclass; looknew->rdtypeset = lookold->rdtypeset; looknew->rdclassset = lookold->rdclassset; looknew->doing_xfr = lookold->doing_xfr; looknew->ixfr_serial = lookold->ixfr_serial; looknew->trace = lookold->trace; looknew->trace_root = lookold->trace_root; looknew->identify = lookold->identify; looknew->identify_previous_line = lookold->identify_previous_line; looknew->ignore = lookold->ignore; looknew->servfail_stops = lookold->servfail_stops; looknew->besteffort = lookold->besteffort; looknew->dnssec = lookold->dnssec; looknew->ednsflags = lookold->ednsflags; looknew->opcode = lookold->opcode; looknew->expire = lookold->expire; looknew->nsid = lookold->nsid; looknew->header_only = lookold->header_only; looknew->sendcookie = lookold->sendcookie; looknew->seenbadcookie = lookold->seenbadcookie; looknew->badcookie = lookold->badcookie; looknew->cookie = lookold->cookie; if (lookold->ednsopts != NULL) { cloneopts(looknew, lookold); } else { looknew->ednsopts = NULL; looknew->ednsoptscnt = 0; } looknew->ednsneg = lookold->ednsneg; looknew->mapped = lookold->mapped; looknew->idnout = lookold->idnout; #ifdef DIG_SIGCHASE looknew->sigchase = lookold->sigchase; #if DIG_SIGCHASE_TD looknew->do_topdown = lookold->do_topdown; looknew->trace_root_sigchase = lookold->trace_root_sigchase; looknew->rdtype_sigchaseset = lookold->rdtype_sigchaseset; looknew->rdtype_sigchase = lookold->rdtype_sigchase; looknew->qrdtype_sigchase = lookold->qrdtype_sigchase; looknew->rdclass_sigchase = lookold->rdclass_sigchase; looknew->rdclass_sigchaseset = lookold->rdclass_sigchaseset; #endif #endif looknew->udpsize = lookold->udpsize; looknew->edns = lookold->edns; looknew->recurse = lookold->recurse; looknew->aaonly = lookold->aaonly; looknew->adflag = lookold->adflag; looknew->cdflag = lookold->cdflag; looknew->print_unknown_format = lookold->print_unknown_format; looknew->zflag = lookold->zflag; looknew->ns_search_only = lookold->ns_search_only; looknew->tcp_mode = lookold->tcp_mode; looknew->tcp_mode_set = lookold->tcp_mode_set; looknew->comments = lookold->comments; looknew->stats = lookold->stats; looknew->section_question = lookold->section_question; looknew->section_answer = lookold->section_answer; looknew->section_authority = lookold->section_authority; looknew->section_additional = lookold->section_additional; looknew->origin = lookold->origin; looknew->retries = lookold->retries; looknew->tsigctx = NULL; looknew->need_search = lookold->need_search; looknew->done_as_is = lookold->done_as_is; looknew->dscp = lookold->dscp; looknew->eoferr = lookold->eoferr; if (lookold->ecs_addr != NULL) { size_t len = sizeof(isc_sockaddr_t); looknew->ecs_addr = isc_mem_allocate(mctx, len); if (looknew->ecs_addr == NULL) fatal("out of memory"); memmove(looknew->ecs_addr, lookold->ecs_addr, len); } dns_name_copy(dns_fixedname_name(&lookold->fdomain), dns_fixedname_name(&looknew->fdomain), NULL); if (servers) clone_server_list(lookold->my_server_list, &looknew->my_server_list); return (looknew); } /*% * Requeue a lookup for further processing, perhaps copying the server * list. The new lookup structure is returned to the caller, and is * queued for processing. If servers are not cloned in the requeue, they * must be added before allowing the current event to complete, since the * completion of the event may result in the next entry on the lookup * queue getting run. */ dig_lookup_t * requeue_lookup(dig_lookup_t *lookold, isc_boolean_t servers) { dig_lookup_t *looknew; debug("requeue_lookup()"); lookup_counter++; if (lookup_counter > LOOKUP_LIMIT) fatal("too many lookups"); looknew = clone_lookup(lookold, servers); INSIST(looknew != NULL); debug("before insertion, init@%p -> %p, new@%p -> %p", lookold, lookold->link.next, looknew, looknew->link.next); ISC_LIST_PREPEND(lookup_list, looknew, link); debug("after insertion, init -> %p, new = %p, new -> %p", lookold, looknew, looknew->link.next); return (looknew); } void setup_text_key(void) { isc_result_t result; dns_name_t keyname; isc_buffer_t secretbuf; unsigned int secretsize; unsigned char *secretstore; debug("setup_text_key()"); result = isc_buffer_allocate(mctx, &namebuf, MXNAME); check_result(result, "isc_buffer_allocate"); dns_name_init(&keyname, NULL); check_result(result, "dns_name_init"); isc_buffer_putstr(namebuf, keynametext); secretsize = (unsigned int) strlen(keysecret) * 3 / 4; secretstore = isc_mem_allocate(mctx, secretsize); if (secretstore == NULL) fatal("memory allocation failure in %s:%d", __FILE__, __LINE__); isc_buffer_init(&secretbuf, secretstore, secretsize); result = isc_base64_decodestring(keysecret, &secretbuf); if (result != ISC_R_SUCCESS) goto failure; secretsize = isc_buffer_usedlength(&secretbuf); if (hmacname == NULL) { result = DST_R_UNSUPPORTEDALG; goto failure; } result = dns_name_fromtext(&keyname, namebuf, dns_rootname, 0, namebuf); if (result != ISC_R_SUCCESS) goto failure; result = dns_tsigkey_create(&keyname, hmacname, secretstore, (int)secretsize, ISC_FALSE, NULL, 0, 0, mctx, NULL, &key); failure: if (result != ISC_R_SUCCESS) printf(";; Couldn't create key %s: %s\n", keynametext, isc_result_totext(result)); else dst_key_setbits(key->key, digestbits); isc_mem_free(mctx, secretstore); dns_name_invalidate(&keyname); isc_buffer_free(&namebuf); } static isc_result_t parse_uint_helper(isc_uint32_t *uip, const char *value, isc_uint32_t max, const char *desc, int base) { isc_uint32_t n; isc_result_t result = isc_parse_uint32(&n, value, base); if (result == ISC_R_SUCCESS && n > max) result = ISC_R_RANGE; if (result != ISC_R_SUCCESS) { printf("invalid %s '%s': %s\n", desc, value, isc_result_totext(result)); return (result); } *uip = n; return (ISC_R_SUCCESS); } isc_result_t parse_uint(isc_uint32_t *uip, const char *value, isc_uint32_t max, const char *desc) { return (parse_uint_helper(uip, value, max, desc, 10)); } isc_result_t parse_xint(isc_uint32_t *uip, const char *value, isc_uint32_t max, const char *desc) { return (parse_uint_helper(uip, value, max, desc, 0)); } static isc_uint32_t parse_bits(char *arg, const char *desc, isc_uint32_t max) { isc_result_t result; isc_uint32_t tmp; result = parse_uint(&tmp, arg, max, desc); if (result != ISC_R_SUCCESS) fatal("couldn't parse digest bits"); tmp = (tmp + 7) & ~0x7U; return (tmp); } isc_result_t parse_netprefix(isc_sockaddr_t **sap, const char *value) { isc_result_t result = ISC_R_SUCCESS; isc_sockaddr_t *sa = NULL; struct in_addr in4; struct in6_addr in6; isc_uint32_t prefix_length = 0xffffffff; char *slash = NULL; isc_boolean_t parsed = ISC_FALSE; isc_boolean_t prefix_parsed = ISC_FALSE; char buf[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:XXX.XXX.XXX.XXX/128")]; REQUIRE(sap != NULL && *sap == NULL); if (strlcpy(buf, value, sizeof(buf)) >= sizeof(buf)) fatal("invalid prefix '%s'\n", value); sa = isc_mem_allocate(mctx, sizeof(*sa)); if (sa == NULL) fatal("out of memory"); memset(sa, 0, sizeof(*sa)); if (strcmp(buf, "0") == 0) { sa->type.sa.sa_family = AF_UNSPEC; prefix_length = 0; goto done; } slash = strchr(buf, '/'); if (slash != NULL) { *slash = '\0'; result = isc_parse_uint32(&prefix_length, slash + 1, 10); if (result != ISC_R_SUCCESS) { fatal("invalid prefix length in '%s': %s\n", value, isc_result_totext(result)); } prefix_parsed = ISC_TRUE; } if (inet_pton(AF_INET6, buf, &in6) == 1) { parsed = ISC_TRUE; isc_sockaddr_fromin6(sa, &in6, 0); if (prefix_length > 128) prefix_length = 128; } else if (inet_pton(AF_INET, buf, &in4) == 1) { parsed = ISC_TRUE; isc_sockaddr_fromin(sa, &in4, 0); if (prefix_length > 32) prefix_length = 32; } else if (prefix_parsed) { int i; for (i = 0; i < 3 && strlen(buf) < sizeof(buf) - 2; i++) { strlcat(buf, ".0", sizeof(buf)); if (inet_pton(AF_INET, buf, &in4) == 1) { parsed = ISC_TRUE; isc_sockaddr_fromin(sa, &in4, 0); break; } } if (prefix_length > 32) prefix_length = 32; } if (!parsed) fatal("invalid address '%s'", value); done: sa->length = prefix_length; *sap = sa; return (ISC_R_SUCCESS); } /* * Parse HMAC algorithm specification */ void parse_hmac(const char *hmac) { char buf[20]; size_t len; REQUIRE(hmac != NULL); len = strlen(hmac); if (len >= sizeof(buf)) fatal("unknown key type '%.*s'", (int)len, hmac); strlcpy(buf, hmac, sizeof(buf)); digestbits = 0; #ifndef PK11_MD5_DISABLE if (strcasecmp(buf, "hmac-md5") == 0) { hmacname = DNS_TSIG_HMACMD5_NAME; } else if (strncasecmp(buf, "hmac-md5-", 9) == 0) { hmacname = DNS_TSIG_HMACMD5_NAME; digestbits = parse_bits(&buf[9], "digest-bits [0..128]", 128); } else #endif if (strcasecmp(buf, "hmac-sha1") == 0) { hmacname = DNS_TSIG_HMACSHA1_NAME; digestbits = 0; } else if (strncasecmp(buf, "hmac-sha1-", 10) == 0) { hmacname = DNS_TSIG_HMACSHA1_NAME; digestbits = parse_bits(&buf[10], "digest-bits [0..160]", 160); } else if (strcasecmp(buf, "hmac-sha224") == 0) { hmacname = DNS_TSIG_HMACSHA224_NAME; } else if (strncasecmp(buf, "hmac-sha224-", 12) == 0) { hmacname = DNS_TSIG_HMACSHA224_NAME; digestbits = parse_bits(&buf[12], "digest-bits [0..224]", 224); } else if (strcasecmp(buf, "hmac-sha256") == 0) { hmacname = DNS_TSIG_HMACSHA256_NAME; } else if (strncasecmp(buf, "hmac-sha256-", 12) == 0) { hmacname = DNS_TSIG_HMACSHA256_NAME; digestbits = parse_bits(&buf[12], "digest-bits [0..256]", 256); } else if (strcasecmp(buf, "hmac-sha384") == 0) { hmacname = DNS_TSIG_HMACSHA384_NAME; } else if (strncasecmp(buf, "hmac-sha384-", 12) == 0) { hmacname = DNS_TSIG_HMACSHA384_NAME; digestbits = parse_bits(&buf[12], "digest-bits [0..384]", 384); } else if (strcasecmp(buf, "hmac-sha512") == 0) { hmacname = DNS_TSIG_HMACSHA512_NAME; } else if (strncasecmp(buf, "hmac-sha512-", 12) == 0) { hmacname = DNS_TSIG_HMACSHA512_NAME; digestbits = parse_bits(&buf[12], "digest-bits [0..512]", 512); } else { fprintf(stderr, ";; Warning, ignoring " "invalid TSIG algorithm %s\n", buf); } } /* * Get a key from a named.conf format keyfile */ static isc_result_t read_confkey(void) { cfg_parser_t *pctx = NULL; cfg_obj_t *file = NULL; const cfg_obj_t *keyobj = NULL; const cfg_obj_t *secretobj = NULL; const cfg_obj_t *algorithmobj = NULL; const char *keyname; const char *secretstr; const char *algorithm; isc_result_t result; if (! isc_file_exists(keyfile)) return (ISC_R_FILENOTFOUND); result = cfg_parser_create(mctx, NULL, &pctx); if (result != ISC_R_SUCCESS) goto cleanup; result = cfg_parse_file(pctx, keyfile, &cfg_type_sessionkey, &file); if (result != ISC_R_SUCCESS) goto cleanup; result = cfg_map_get(file, "key", &keyobj); if (result != ISC_R_SUCCESS) goto cleanup; (void) cfg_map_get(keyobj, "secret", &secretobj); (void) cfg_map_get(keyobj, "algorithm", &algorithmobj); if (secretobj == NULL || algorithmobj == NULL) fatal("key must have algorithm and secret"); keyname = cfg_obj_asstring(cfg_map_getname(keyobj)); secretstr = cfg_obj_asstring(secretobj); algorithm = cfg_obj_asstring(algorithmobj); strlcpy(keynametext, keyname, sizeof(keynametext)); strlcpy(keysecret, secretstr, sizeof(keysecret)); parse_hmac(algorithm); setup_text_key(); cleanup: if (pctx != NULL) { if (file != NULL) cfg_obj_destroy(pctx, &file); cfg_parser_destroy(&pctx); } return (result); } void setup_file_key(void) { isc_result_t result; dst_key_t *dstkey = NULL; debug("setup_file_key()"); /* Try reading the key from a K* pair */ result = dst_key_fromnamedfile(keyfile, NULL, DST_TYPE_PRIVATE | DST_TYPE_KEY, mctx, &dstkey); /* If that didn't work, try reading it as a session.key keyfile */ if (result != ISC_R_SUCCESS) { result = read_confkey(); if (result == ISC_R_SUCCESS) return; } if (result != ISC_R_SUCCESS) { fprintf(stderr, "Couldn't read key from %s: %s\n", keyfile, isc_result_totext(result)); goto failure; } switch (dst_key_alg(dstkey)) { #ifndef PK11_MD5_DISABLE case DST_ALG_HMACMD5: hmacname = DNS_TSIG_HMACMD5_NAME; break; #endif case DST_ALG_HMACSHA1: hmacname = DNS_TSIG_HMACSHA1_NAME; break; case DST_ALG_HMACSHA224: hmacname = DNS_TSIG_HMACSHA224_NAME; break; case DST_ALG_HMACSHA256: hmacname = DNS_TSIG_HMACSHA256_NAME; break; case DST_ALG_HMACSHA384: hmacname = DNS_TSIG_HMACSHA384_NAME; break; case DST_ALG_HMACSHA512: hmacname = DNS_TSIG_HMACSHA512_NAME; break; default: printf(";; Couldn't create key %s: bad algorithm\n", keynametext); goto failure; } result = dns_tsigkey_createfromkey(dst_key_name(dstkey), hmacname, dstkey, ISC_FALSE, NULL, 0, 0, mctx, NULL, &key); if (result != ISC_R_SUCCESS) { printf(";; Couldn't create key %s: %s\n", keynametext, isc_result_totext(result)); goto failure; } failure: if (dstkey != NULL) dst_key_free(&dstkey); } static dig_searchlist_t * make_searchlist_entry(char *domain) { dig_searchlist_t *search; search = isc_mem_allocate(mctx, sizeof(*search)); if (search == NULL) fatal("memory allocation failure in %s:%d", __FILE__, __LINE__); strlcpy(search->origin, domain, MXNAME); search->origin[MXNAME-1] = 0; ISC_LINK_INIT(search, link); return (search); } static void clear_searchlist(void) { dig_searchlist_t *search; while ((search = ISC_LIST_HEAD(search_list)) != NULL) { ISC_LIST_UNLINK(search_list, search, link); isc_mem_free(mctx, search); } } static void create_search_list(lwres_conf_t *confdata) { int i; dig_searchlist_t *search; debug("create_search_list()"); clear_searchlist(); for (i = 0; i < confdata->searchnxt; i++) { search = make_searchlist_entry(confdata->search[i]); ISC_LIST_APPEND(search_list, search, link); } } /*% * Setup the system as a whole, reading key information and resolv.conf * settings. */ void setup_system(isc_boolean_t ipv4only, isc_boolean_t ipv6only) { dig_searchlist_t *domain = NULL; lwres_result_t lwresult; unsigned int lwresflags; isc_result_t result; debug("setup_system()"); if (ipv4only) { if (have_ipv4) { isc_net_disableipv6(); have_ipv6 = ISC_FALSE; } else { fatal("can't find IPv4 networking"); } } if (ipv6only) { if (have_ipv6) { isc_net_disableipv4(); have_ipv4 = ISC_FALSE; } else { fatal("can't find IPv6 networking"); } } lwresflags = LWRES_CONTEXT_SERVERMODE; if (have_ipv4) lwresflags |= LWRES_CONTEXT_USEIPV4; if (have_ipv6) lwresflags |= LWRES_CONTEXT_USEIPV6; lwresult = lwres_context_create(&lwctx, mctx, mem_alloc, mem_free, lwresflags); if (lwresult != LWRES_R_SUCCESS) fatal("lwres_context_create failed"); lwresult = lwres_conf_parse(lwctx, RESOLV_CONF); if (lwresult != LWRES_R_SUCCESS && lwresult != LWRES_R_NOTFOUND) fatal("parse of %s failed", RESOLV_CONF); lwconf = lwres_conf_get(lwctx); /* Make the search list */ if (lwconf->searchnxt > 0) create_search_list(lwconf); else { /* No search list. Use the domain name if any */ if (lwconf->domainname != NULL) { domain = make_searchlist_entry(lwconf->domainname); ISC_LIST_APPEND(search_list, domain, link); domain = NULL; } } if (lwconf->resdebug) { verbose = ISC_TRUE; debug("verbose is on"); } if (ndots == -1) { ndots = lwconf->ndots; debug("ndots is %d.", ndots); } if (lwconf->attempts) { tries = lwconf->attempts + 1; if (tries < 2) tries = 2; debug("tries is %d.", tries); } if (lwconf->timeout) { timeout = lwconf->timeout; debug("timeout is %d.", timeout); } /* If user doesn't specify server use nameservers from resolv.conf. */ if (ISC_LIST_EMPTY(server_list)) copy_server_list(lwconf, &server_list); /* If we don't find a nameserver fall back to localhost */ if (ISC_LIST_EMPTY(server_list)) { if (have_ipv4) { lwresult = add_nameserver(lwconf, "127.0.0.1", AF_INET); if (lwresult != ISC_R_SUCCESS) fatal("add_nameserver failed"); } if (have_ipv6) { lwresult = add_nameserver(lwconf, "::1", AF_INET6); if (lwresult != ISC_R_SUCCESS) fatal("add_nameserver failed"); } copy_server_list(lwconf, &server_list); } #ifdef WITH_IDN initialize_idn(); #endif if (keyfile[0] != 0) setup_file_key(); else if (keysecret[0] != 0) setup_text_key(); #ifdef DIG_SIGCHASE /* Setup the list of messages for +sigchase */ ISC_LIST_INIT(chase_message_list); ISC_LIST_INIT(chase_message_list2); dns_name_init(&chase_name, NULL); #if DIG_SIGCHASE_TD dns_name_init(&chase_current_name, NULL); dns_name_init(&chase_authority_name, NULL); #endif #if DIG_SIGCHASE_BU dns_name_init(&chase_signame, NULL); #endif #endif result = isc_entropy_getdata(entp, cookie_secret, sizeof(cookie_secret), NULL, 0); if (result != ISC_R_SUCCESS) fatal("unable to generate cookie secret"); } /*% * Override the search list derived from resolv.conf by 'domain'. */ void set_search_domain(char *domain) { dig_searchlist_t *search; clear_searchlist(); search = make_searchlist_entry(domain); ISC_LIST_APPEND(search_list, search, link); } /*% * Setup the ISC and DNS libraries for use by the system. */ void setup_libs(void) { isc_result_t result; isc_logconfig_t *logconfig = NULL; debug("setup_libs()"); #ifdef PKCS11CRYPTO pk11_result_register(); #endif dns_result_register(); result = isc_net_probeipv4(); if (result == ISC_R_SUCCESS) have_ipv4 = ISC_TRUE; result = isc_net_probeipv6(); if (result == ISC_R_SUCCESS) have_ipv6 = ISC_TRUE; if (!have_ipv6 && !have_ipv4) fatal("can't find either v4 or v6 networking"); result = isc_mem_create(0, 0, &mctx); check_result(result, "isc_mem_create"); isc_mem_setname(mctx, "dig", NULL); result = isc_log_create(mctx, &lctx, &logconfig); check_result(result, "isc_log_create"); isc_log_setcontext(lctx); dns_log_init(lctx); dns_log_setcontext(lctx); result = isc_log_usechannel(logconfig, "default_debug", NULL, NULL); check_result(result, "isc_log_usechannel"); isc_log_setdebuglevel(lctx, 0); result = isc_taskmgr_create(mctx, 1, 0, &taskmgr); check_result(result, "isc_taskmgr_create"); result = isc_task_create(taskmgr, 0, &global_task); check_result(result, "isc_task_create"); isc_task_setname(global_task, "dig", NULL); result = isc_timermgr_create(mctx, &timermgr); check_result(result, "isc_timermgr_create"); result = isc_socketmgr_create(mctx, &socketmgr); check_result(result, "isc_socketmgr_create"); result = isc_entropy_create(mctx, &entp); check_result(result, "isc_entropy_create"); result = dst_lib_init(mctx, entp, 0); check_result(result, "dst_lib_init"); is_dst_up = ISC_TRUE; result = isc_mempool_create(mctx, COMMSIZE, &commctx); check_result(result, "isc_mempool_create"); isc_mempool_setname(commctx, "COMMPOOL"); /* * 6 and 2 set as reasonable parameters for 3 or 4 nameserver * systems. */ isc_mempool_setfreemax(commctx, 6); isc_mempool_setfillcount(commctx, 2); result = isc_mutex_init(&lookup_lock); check_result(result, "isc_mutex_init"); } typedef struct dig_ednsoptname { isc_uint32_t code; const char *name; } dig_ednsoptname_t; dig_ednsoptname_t optnames[] = { { 3, "NSID" }, /* RFC 5001 */ { 5, "DAU" }, /* RFC 6975 */ { 6, "DHU" }, /* RFC 6975 */ { 7, "N3U" }, /* RFC 6975 */ { 8, "ECS" }, /* RFC 7871 */ { 9, "EXPIRE" }, /* RFC 7314 */ { 10, "COOKIE" }, /* RFC 7873 */ { 11, "KEEPALIVE" }, /* RFC 7828 */ { 12, "PADDING" }, /* RFC 7830 */ { 12, "PAD" }, /* shorthand */ { 13, "CHAIN" }, /* RFC 7901 */ { 14, "KEY-TAG" }, /* RFC 8145 */ { 26946, "DEVICEID" }, /* Brian Hartvigsen */ }; #define N_EDNS_OPTNAMES (sizeof(optnames) / sizeof(optnames[0])) void save_opt(dig_lookup_t *lookup, char *code, char *value) { isc_result_t result; isc_uint32_t num = 0; isc_buffer_t b; isc_boolean_t found = ISC_FALSE; unsigned int i; if (lookup->ednsoptscnt >= EDNSOPT_OPTIONS) fatal("too many ednsopts"); for (i = 0; i < N_EDNS_OPTNAMES; i++) { if (strcasecmp(code, optnames[i].name) == 0) { num = optnames[i].code; found = ISC_TRUE; break; } } if (!found) { result = parse_uint(&num, code, 65535, "ednsopt"); if (result != ISC_R_SUCCESS) fatal("bad edns code point: %s", code); } if (lookup->ednsopts == NULL) { cloneopts(lookup, NULL); } if (lookup->ednsopts[lookup->ednsoptscnt].value != NULL) isc_mem_free(mctx, lookup->ednsopts[lookup->ednsoptscnt].value); lookup->ednsopts[lookup->ednsoptscnt].code = num; lookup->ednsopts[lookup->ednsoptscnt].length = 0; lookup->ednsopts[lookup->ednsoptscnt].value = NULL; if (value != NULL) { char *buf; buf = isc_mem_allocate(mctx, strlen(value)/2 + 1); if (buf == NULL) fatal("out of memory"); isc_buffer_init(&b, buf, (unsigned int) strlen(value)/2 + 1); result = isc_hex_decodestring(value, &b); check_result(result, "isc_hex_decodestring"); lookup->ednsopts[lookup->ednsoptscnt].value = isc_buffer_base(&b); lookup->ednsopts[lookup->ednsoptscnt].length = isc_buffer_usedlength(&b); } lookup->ednsoptscnt++; } /*% * Add EDNS0 option record to a message. Currently, the only supported * options are UDP buffer size, the DO bit, and EDNS options * (e.g., NSID, COOKIE, client-subnet) */ static void add_opt(dns_message_t *msg, isc_uint16_t udpsize, isc_uint16_t edns, unsigned int flags, dns_ednsopt_t *opts, size_t count) { dns_rdataset_t *rdataset = NULL; isc_result_t result; debug("add_opt()"); result = dns_message_buildopt(msg, &rdataset, edns, udpsize, flags, opts, count); check_result(result, "dns_message_buildopt"); result = dns_message_setopt(msg, rdataset); check_result(result, "dns_message_setopt"); } /*% * Add a question section to a message, asking for the specified name, * type, and class. */ static void add_question(dns_message_t *message, dns_name_t *name, dns_rdataclass_t rdclass, dns_rdatatype_t rdtype) { dns_rdataset_t *rdataset; isc_result_t result; debug("add_question()"); rdataset = NULL; result = dns_message_gettemprdataset(message, &rdataset); check_result(result, "dns_message_gettemprdataset()"); dns_rdataset_makequestion(rdataset, rdclass, rdtype); ISC_LIST_APPEND(name->list, rdataset, link); } /*% * Check if we're done with all the queued lookups, which is true iff * all sockets, sends, and recvs are accounted for (counters == 0), * and the lookup list is empty. * If we are done, pass control back out to dighost_shutdown() (which is * part of dig.c, host.c, or nslookup.c) to either shutdown the system as * a whole or reseed the lookup list. */ static void check_if_done(void) { debug("check_if_done()"); debug("list %s", ISC_LIST_EMPTY(lookup_list) ? "empty" : "full"); if (ISC_LIST_EMPTY(lookup_list) && current_lookup == NULL && sendcount == 0) { INSIST(sockcount == 0); INSIST(recvcount == 0); debug("shutting down"); dighost_shutdown(); } } /*% * Clear out a query when we're done with it. WARNING: This routine * WILL invalidate the query pointer. */ static void clear_query(dig_query_t *query) { dig_lookup_t *lookup; REQUIRE(query != NULL); debug("clear_query(%p)", query); if (query->timer != NULL) isc_timer_detach(&query->timer); lookup = query->lookup; if (lookup->current_query == query) lookup->current_query = NULL; if (ISC_LINK_LINKED(query, link)) ISC_LIST_UNLINK(lookup->q, query, link); if (ISC_LINK_LINKED(query, clink)) ISC_LIST_UNLINK(lookup->connecting, query, clink); if (ISC_LINK_LINKED(&query->recvbuf, link)) ISC_LIST_DEQUEUE(query->recvlist, &query->recvbuf, link); if (ISC_LINK_LINKED(&query->lengthbuf, link)) ISC_LIST_DEQUEUE(query->lengthlist, &query->lengthbuf, link); INSIST(query->recvspace != NULL); if (query->sock != NULL) { isc_socket_detach(&query->sock); sockcount--; debug("sockcount=%d", sockcount); } isc_mempool_put(commctx, query->recvspace); isc_buffer_invalidate(&query->recvbuf); isc_buffer_invalidate(&query->lengthbuf); if (query->waiting_senddone) query->pending_free = ISC_TRUE; else isc_mem_free(mctx, query); } /*% * Try and clear out a lookup if we're done with it. Return ISC_TRUE if * the lookup was successfully cleared. If ISC_TRUE is returned, the * lookup pointer has been invalidated. */ static isc_boolean_t try_clear_lookup(dig_lookup_t *lookup) { dig_query_t *q; REQUIRE(lookup != NULL); debug("try_clear_lookup(%p)", lookup); if (ISC_LIST_HEAD(lookup->q) != NULL || ISC_LIST_HEAD(lookup->connecting) != NULL) { if (debugging) { q = ISC_LIST_HEAD(lookup->q); while (q != NULL) { debug("query to %s still pending", q->servname); q = ISC_LIST_NEXT(q, link); } q = ISC_LIST_HEAD(lookup->connecting); while (q != NULL) { debug("query to %s still connecting", q->servname); q = ISC_LIST_NEXT(q, clink); } } return (ISC_FALSE); } /* * At this point, we know there are no queries on the lookup, * so can make it go away also. */ destroy_lookup(lookup); return (ISC_TRUE); } void destroy_lookup(dig_lookup_t *lookup) { dig_server_t *s; void *ptr; debug("destroy"); s = ISC_LIST_HEAD(lookup->my_server_list); while (s != NULL) { debug("freeing server %p belonging to %p", s, lookup); ptr = s; s = ISC_LIST_NEXT(s, link); ISC_LIST_DEQUEUE(lookup->my_server_list, (dig_server_t *)ptr, link); isc_mem_free(mctx, ptr); } if (lookup->sendmsg != NULL) dns_message_destroy(&lookup->sendmsg); if (lookup->querysig != NULL) { debug("freeing buffer %p", lookup->querysig); isc_buffer_free(&lookup->querysig); } if (lookup->sendspace != NULL) isc_mempool_put(commctx, lookup->sendspace); if (lookup->tsigctx != NULL) dst_context_destroy(&lookup->tsigctx); if (lookup->ecs_addr != NULL) isc_mem_free(mctx, lookup->ecs_addr); if (lookup->ednsopts != NULL) { size_t i; for (i = 0; i < EDNSOPT_OPTIONS; i++) { if (lookup->ednsopts[i].value != NULL) isc_mem_free(mctx, lookup->ednsopts[i].value); } isc_mem_free(mctx, lookup->ednsopts); } isc_mem_free(mctx, lookup); } /*% * If we can, start the next lookup in the queue running. * This assumes that the lookup on the head of the queue hasn't been * started yet. It also removes the lookup from the head of the queue, * setting the current_lookup pointer pointing to it. */ void start_lookup(void) { debug("start_lookup()"); if (cancel_now) return; /* * If there's a current lookup running, we really shouldn't get * here. */ INSIST(current_lookup == NULL); current_lookup = ISC_LIST_HEAD(lookup_list); /* * Put the current lookup somewhere so cancel_all can find it */ if (current_lookup != NULL) { ISC_LIST_DEQUEUE(lookup_list, current_lookup, link); #if DIG_SIGCHASE_TD if (current_lookup->do_topdown && !current_lookup->rdtype_sigchaseset) { dst_key_t *dstkey = NULL; isc_buffer_t *b = NULL; isc_region_t r; isc_result_t result; dns_name_t query_name; dns_name_t *key_name; int i; result = get_trusted_key(); if (result != ISC_R_SUCCESS) { printf("\n;; No trusted key, " "+sigchase option is disabled\n"); current_lookup->sigchase = ISC_FALSE; goto novalidation; } dns_name_init(&query_name, NULL); nameFromString(current_lookup->textname, &query_name); for (i = 0; i < tk_list.nb_tk; i++) { key_name = dst_key_name(tk_list.key[i]); if (dns_name_issubdomain(&query_name, key_name) == ISC_TRUE) dstkey = tk_list.key[i]; /* * Verify temp is really the lowest * WARNING */ } if (dstkey == NULL) { printf("\n;; The queried zone: "); dns_name_print(&query_name, stdout); printf(" isn't a subdomain of any Trusted Keys" ": +sigchase option is disable\n"); current_lookup->sigchase = ISC_FALSE; free_name(&query_name); goto novalidation; } free_name(&query_name); current_lookup->rdtype_sigchase = current_lookup->rdtype; current_lookup->rdtype_sigchaseset = current_lookup->rdtypeset; current_lookup->rdtype = dns_rdatatype_ns; current_lookup->qrdtype_sigchase = current_lookup->qrdtype; current_lookup->qrdtype = dns_rdatatype_ns; current_lookup->rdclass_sigchase = current_lookup->rdclass; current_lookup->rdclass_sigchaseset = current_lookup->rdclassset; current_lookup->rdclass = dns_rdataclass_in; strlcpy(current_lookup->textnamesigchase, current_lookup->textname, MXNAME); current_lookup->trace_root_sigchase = ISC_TRUE; result = isc_buffer_allocate(mctx, &b, BUFSIZE); check_result(result, "isc_buffer_allocate"); result = dns_name_totext(dst_key_name(dstkey), ISC_FALSE, b); check_result(result, "dns_name_totext"); isc_buffer_usedregion(b, &r); r.base[r.length] = '\0'; strlcpy(current_lookup->textname, (char*)r.base, MXNAME); isc_buffer_free(&b); nameFromString(current_lookup->textnamesigchase, &chase_name); dns_name_init(&chase_authority_name, NULL); } novalidation: #endif if (setup_lookup(current_lookup)) do_lookup(current_lookup); else if (next_origin(current_lookup)) check_next_lookup(current_lookup); } else { check_if_done(); } } /*% * If we can, clear the current lookup and start the next one running. * This calls try_clear_lookup, so may invalidate the lookup pointer. */ static void check_next_lookup(dig_lookup_t *lookup) { INSIST(!free_now); debug("check_next_lookup(%p)", lookup); if (ISC_LIST_HEAD(lookup->q) != NULL) { debug("still have a worker"); return; } if (try_clear_lookup(lookup)) { current_lookup = NULL; start_lookup(); } } /*% * Create and queue a new lookup as a followup to the current lookup, * based on the supplied message and section. This is used in trace and * name server search modes to start a new lookup using servers from * NS records in a reply. Returns the number of followup lookups made. */ static int followup_lookup(dns_message_t *msg, dig_query_t *query, dns_section_t section) { dig_lookup_t *lookup = NULL; dig_server_t *srv = NULL; dns_rdataset_t *rdataset = NULL; dns_rdata_t rdata = DNS_RDATA_INIT; dns_name_t *name = NULL; isc_result_t result; isc_boolean_t success = ISC_FALSE; int numLookups = 0; int num; isc_result_t lresult, addresses_result; char bad_namestr[DNS_NAME_FORMATSIZE]; dns_name_t *domain; isc_boolean_t horizontal = ISC_FALSE, bad = ISC_FALSE; INSIST(!free_now); debug("following up %s", query->lookup->textname); addresses_result = ISC_R_SUCCESS; bad_namestr[0] = '\0'; for (result = dns_message_firstname(msg, section); result == ISC_R_SUCCESS; result = dns_message_nextname(msg, section)) { name = NULL; dns_message_currentname(msg, section, &name); if (section == DNS_SECTION_AUTHORITY) { rdataset = NULL; result = dns_message_findtype(name, dns_rdatatype_soa, 0, &rdataset); if (result == ISC_R_SUCCESS) return (0); } rdataset = NULL; result = dns_message_findtype(name, dns_rdatatype_ns, 0, &rdataset); if (result != ISC_R_SUCCESS) continue; debug("found NS set"); if (query->lookup->trace && !query->lookup->trace_root) { dns_namereln_t namereln; unsigned int nlabels; int order; domain = dns_fixedname_name(&query->lookup->fdomain); namereln = dns_name_fullcompare(name, domain, &order, &nlabels); if (namereln == dns_namereln_equal) { if (!horizontal) printf(";; BAD (HORIZONTAL) REFERRAL\n"); horizontal = ISC_TRUE; } else if (namereln != dns_namereln_subdomain) { if (!bad) printf(";; BAD REFERRAL\n"); bad = ISC_TRUE; continue; } } for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS; result = dns_rdataset_next(rdataset)) { char namestr[DNS_NAME_FORMATSIZE]; dns_rdata_ns_t ns; if (query->lookup->trace_root && query->lookup->nsfound >= MXSERV) break; dns_rdataset_current(rdataset, &rdata); query->lookup->nsfound++; result = dns_rdata_tostruct(&rdata, &ns, NULL); check_result(result, "dns_rdata_tostruct"); dns_name_format(&ns.name, namestr, sizeof(namestr)); dns_rdata_freestruct(&ns); /* Initialize lookup if we've not yet */ debug("found NS %s", namestr); if (!success) { success = ISC_TRUE; lookup_counter++; lookup = requeue_lookup(query->lookup, ISC_FALSE); cancel_lookup(query->lookup); lookup->doing_xfr = ISC_FALSE; if (!lookup->trace_root && section == DNS_SECTION_ANSWER) lookup->trace = ISC_FALSE; else lookup->trace = query->lookup->trace; lookup->ns_search_only = query->lookup->ns_search_only; lookup->trace_root = ISC_FALSE; if (lookup->ns_search_only) lookup->recurse = ISC_FALSE; domain = dns_fixedname_name(&lookup->fdomain); dns_name_copy(name, domain, NULL); } debug("adding server %s", namestr); num = getaddresses(lookup, namestr, &lresult); if (lresult != ISC_R_SUCCESS) { printf("couldn't get address for '%s': %s\n", namestr, isc_result_totext(lresult)); if (addresses_result == ISC_R_SUCCESS) { addresses_result = lresult; strlcpy(bad_namestr, namestr, sizeof(bad_namestr)); } } numLookups += num; dns_rdata_reset(&rdata); } } if (numLookups == 0 && addresses_result != ISC_R_SUCCESS) { fatal("couldn't get address for '%s': %s", bad_namestr, isc_result_totext(result)); } if (lookup == NULL && section == DNS_SECTION_ANSWER && (query->lookup->trace || query->lookup->ns_search_only)) return (followup_lookup(msg, query, DNS_SECTION_AUTHORITY)); /* * Randomize the order the nameserver will be tried. */ if (numLookups > 1) { isc_uint32_t i, j; dig_serverlist_t my_server_list; dig_server_t *next; ISC_LIST_INIT(my_server_list); i = numLookups; for (srv = ISC_LIST_HEAD(lookup->my_server_list); srv != NULL; srv = ISC_LIST_HEAD(lookup->my_server_list)) { INSIST(i > 0); isc_random_get(&j); j %= i; next = ISC_LIST_NEXT(srv, link); while (j-- > 0 && next != NULL) { srv = next; next = ISC_LIST_NEXT(srv, link); } ISC_LIST_DEQUEUE(lookup->my_server_list, srv, link); ISC_LIST_APPEND(my_server_list, srv, link); i--; } ISC_LIST_APPENDLIST(lookup->my_server_list, my_server_list, link); } return (numLookups); } /*% * Create and queue a new lookup using the next origin from the search * list, read in setup_system(). * * Return ISC_TRUE iff there was another searchlist entry. */ static isc_boolean_t next_origin(dig_lookup_t *oldlookup) { dig_lookup_t *newlookup; dig_searchlist_t *search; dns_fixedname_t fixed; dns_name_t *name; isc_result_t result; INSIST(!free_now); debug("next_origin()"); debug("following up %s", oldlookup->textname); if (!usesearch) /* * We're not using a search list, so don't even think * about finding the next entry. */ return (ISC_FALSE); /* * Check for a absolute name or ndots being met. */ dns_fixedname_init(&fixed); name = dns_fixedname_name(&fixed); result = dns_name_fromstring2(name, oldlookup->textname, NULL, 0, NULL); if (result == ISC_R_SUCCESS && (dns_name_isabsolute(name) || (int)dns_name_countlabels(name) > ndots)) return (ISC_FALSE); if (oldlookup->origin == NULL && !oldlookup->need_search) /* * Then we just did rootorg; there's nothing left. */ return (ISC_FALSE); if (oldlookup->origin == NULL && oldlookup->need_search) { newlookup = requeue_lookup(oldlookup, ISC_TRUE); newlookup->origin = ISC_LIST_HEAD(search_list); newlookup->need_search = ISC_FALSE; } else { search = ISC_LIST_NEXT(oldlookup->origin, link); if (search == NULL && oldlookup->done_as_is) return (ISC_FALSE); newlookup = requeue_lookup(oldlookup, ISC_TRUE); newlookup->origin = search; } cancel_lookup(oldlookup); return (ISC_TRUE); } /*% * Insert an SOA record into the sendmessage in a lookup. Used for * creating IXFR queries. */ static void insert_soa(dig_lookup_t *lookup) { isc_result_t result; dns_rdata_soa_t soa; dns_rdata_t *rdata = NULL; dns_rdatalist_t *rdatalist = NULL; dns_rdataset_t *rdataset = NULL; dns_name_t *soaname = NULL; debug("insert_soa()"); soa.mctx = mctx; soa.serial = lookup->ixfr_serial; soa.refresh = 0; soa.retry = 0; soa.expire = 0; soa.minimum = 0; soa.common.rdclass = lookup->rdclass; soa.common.rdtype = dns_rdatatype_soa; dns_name_init(&soa.origin, NULL); dns_name_init(&soa.contact, NULL); dns_name_clone(dns_rootname, &soa.origin); dns_name_clone(dns_rootname, &soa.contact); isc_buffer_init(&lookup->rdatabuf, lookup->rdatastore, sizeof(lookup->rdatastore)); result = dns_message_gettemprdata(lookup->sendmsg, &rdata); check_result(result, "dns_message_gettemprdata"); result = dns_rdata_fromstruct(rdata, lookup->rdclass, dns_rdatatype_soa, &soa, &lookup->rdatabuf); check_result(result, "isc_rdata_fromstruct"); result = dns_message_gettemprdatalist(lookup->sendmsg, &rdatalist); check_result(result, "dns_message_gettemprdatalist"); result = dns_message_gettemprdataset(lookup->sendmsg, &rdataset); check_result(result, "dns_message_gettemprdataset"); dns_rdatalist_init(rdatalist); rdatalist->type = dns_rdatatype_soa; rdatalist->rdclass = lookup->rdclass; ISC_LIST_APPEND(rdatalist->rdata, rdata, link); dns_rdatalist_tordataset(rdatalist, rdataset); result = dns_message_gettempname(lookup->sendmsg, &soaname); check_result(result, "dns_message_gettempname"); dns_name_init(soaname, NULL); dns_name_clone(lookup->name, soaname); ISC_LIST_INIT(soaname->list); ISC_LIST_APPEND(soaname->list, rdataset, link); dns_message_addname(lookup->sendmsg, soaname, DNS_SECTION_AUTHORITY); } static void compute_cookie(unsigned char *clientcookie, size_t len) { /* XXXMPA need to fix, should be per server. */ INSIST(len >= 8U); memmove(clientcookie, cookie_secret, 8); } /*% * Setup the supplied lookup structure, making it ready to start sending * queries to servers. Create and initialize the message to be sent as * well as the query structures and buffer space for the replies. If the * server list is empty, clone it from the system default list. */ isc_boolean_t setup_lookup(dig_lookup_t *lookup) { isc_result_t result; isc_uint32_t id; unsigned int len; dig_server_t *serv; dig_query_t *query; isc_buffer_t b; dns_compress_t cctx; char store[MXNAME]; char ecsbuf[20]; char cookiebuf[256]; #ifdef WITH_IDN idn_result_t mr; char utf8_textname[MXNAME], utf8_origin[MXNAME], idn_textname[MXNAME]; #endif #ifdef WITH_IDN result = dns_name_settotextfilter(lookup->idnout ? output_filter : NULL); check_result(result, "dns_name_settotextfilter"); #endif REQUIRE(lookup != NULL); INSIST(!free_now); debug("setup_lookup(%p)", lookup); result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, &lookup->sendmsg); check_result(result, "dns_message_create"); if (lookup->new_search) { debug("resetting lookup counter."); lookup_counter = 0; } if (ISC_LIST_EMPTY(lookup->my_server_list)) { debug("cloning server list"); clone_server_list(server_list, &lookup->my_server_list); } result = dns_message_gettempname(lookup->sendmsg, &lookup->name); check_result(result, "dns_message_gettempname"); dns_name_init(lookup->name, NULL); isc_buffer_init(&lookup->namebuf, lookup->name_space, sizeof(lookup->name_space)); isc_buffer_init(&lookup->onamebuf, lookup->oname_space, sizeof(lookup->oname_space)); #ifdef WITH_IDN /* * We cannot convert `textname' and `origin' separately. * `textname' doesn't contain TLD, but local mapping needs * TLD. */ mr = idn_encodename(IDN_LOCALCONV | IDN_DELIMMAP, lookup->textname, utf8_textname, sizeof(utf8_textname)); idn_check_result(mr, "convert textname to UTF-8"); #endif /* * If the name has too many dots, force the origin to be NULL * (which produces an absolute lookup). Otherwise, take the origin * we have if there's one in the struct already. If it's NULL, * take the first entry in the searchlist iff either usesearch * is TRUE or we got a domain line in the resolv.conf file. */ if (lookup->new_search) { #ifdef WITH_IDN if ((count_dots(utf8_textname) >= ndots) || !usesearch) { lookup->origin = NULL; /* Force abs lookup */ lookup->done_as_is = ISC_TRUE; lookup->need_search = usesearch; } else if (lookup->origin == NULL && usesearch) { lookup->origin = ISC_LIST_HEAD(search_list); lookup->need_search = ISC_FALSE; } #else if ((count_dots(lookup->textname) >= ndots) || !usesearch) { lookup->origin = NULL; /* Force abs lookup */ lookup->done_as_is = ISC_TRUE; lookup->need_search = usesearch; } else if (lookup->origin == NULL && usesearch) { lookup->origin = ISC_LIST_HEAD(search_list); lookup->need_search = ISC_FALSE; } #endif } #ifdef WITH_IDN if (lookup->origin != NULL) { mr = idn_encodename(IDN_LOCALCONV | IDN_DELIMMAP, lookup->origin->origin, utf8_origin, sizeof(utf8_origin)); idn_check_result(mr, "convert origin to UTF-8"); mr = append_textname(utf8_textname, utf8_origin, sizeof(utf8_textname)); idn_check_result(mr, "append origin to textname"); } mr = idn_encodename(idnoptions | IDN_LOCALMAP | IDN_NAMEPREP | IDN_IDNCONV | IDN_LENCHECK, utf8_textname, idn_textname, sizeof(idn_textname)); idn_check_result(mr, "convert UTF-8 textname to IDN encoding"); #else if (lookup->origin != NULL) { debug("trying origin %s", lookup->origin->origin); result = dns_message_gettempname(lookup->sendmsg, &lookup->oname); check_result(result, "dns_message_gettempname"); dns_name_init(lookup->oname, NULL); /* XXX Helper funct to conv char* to name? */ len = (unsigned int) strlen(lookup->origin->origin); isc_buffer_init(&b, lookup->origin->origin, len); isc_buffer_add(&b, len); result = dns_name_fromtext(lookup->oname, &b, dns_rootname, 0, &lookup->onamebuf); if (result != ISC_R_SUCCESS) { dns_message_puttempname(lookup->sendmsg, &lookup->name); dns_message_puttempname(lookup->sendmsg, &lookup->oname); fatal("'%s' is not in legal name syntax (%s)", lookup->origin->origin, isc_result_totext(result)); } if (lookup->trace && lookup->trace_root) { dns_name_clone(dns_rootname, lookup->name); } else { dns_fixedname_t fixed; dns_name_t *name; dns_fixedname_init(&fixed); name = dns_fixedname_name(&fixed); len = (unsigned int) strlen(lookup->textname); isc_buffer_init(&b, lookup->textname, len); isc_buffer_add(&b, len); result = dns_name_fromtext(name, &b, NULL, 0, NULL); if (result == ISC_R_SUCCESS && !dns_name_isabsolute(name)) result = dns_name_concatenate(name, lookup->oname, lookup->name, &lookup->namebuf); else if (result == ISC_R_SUCCESS) result = dns_name_copy(name, lookup->name, &lookup->namebuf); if (result != ISC_R_SUCCESS) { dns_message_puttempname(lookup->sendmsg, &lookup->name); dns_message_puttempname(lookup->sendmsg, &lookup->oname); if (result == DNS_R_NAMETOOLONG) return (ISC_FALSE); fatal("'%s' is not in legal name syntax (%s)", lookup->textname, isc_result_totext(result)); } } dns_message_puttempname(lookup->sendmsg, &lookup->oname); } else #endif { debug("using root origin"); if (lookup->trace && lookup->trace_root) dns_name_clone(dns_rootname, lookup->name); else { #ifdef WITH_IDN len = (unsigned int) strlen(idn_textname); isc_buffer_init(&b, idn_textname, len); isc_buffer_add(&b, len); result = dns_name_fromtext(lookup->name, &b, dns_rootname, 0, &lookup->namebuf); #else len = (unsigned int) strlen(lookup->textname); isc_buffer_init(&b, lookup->textname, len); isc_buffer_add(&b, len); result = dns_name_fromtext(lookup->name, &b, dns_rootname, 0, &lookup->namebuf); #endif } if (result != ISC_R_SUCCESS) { dns_message_puttempname(lookup->sendmsg, &lookup->name); fatal("'%s' is not a legal name " "(%s)", lookup->textname, isc_result_totext(result)); } } dns_name_format(lookup->name, store, sizeof(store)); dighost_trying(store, lookup); INSIST(dns_name_isabsolute(lookup->name)); isc_random_get(&id); lookup->sendmsg->id = (unsigned short)id & 0xFFFF; lookup->sendmsg->opcode = lookup->opcode; lookup->msgcounter = 0; /* * If this is a trace request, completely disallow recursion, since * it's meaningless for traces. */ if (lookup->trace || (lookup->ns_search_only && !lookup->trace_root)) lookup->recurse = ISC_FALSE; if (lookup->recurse && lookup->rdtype != dns_rdatatype_axfr && lookup->rdtype != dns_rdatatype_ixfr) { debug("recursive query"); lookup->sendmsg->flags |= DNS_MESSAGEFLAG_RD; } /* XXX aaflag */ if (lookup->aaonly) { debug("AA query"); lookup->sendmsg->flags |= DNS_MESSAGEFLAG_AA; } if (lookup->adflag) { debug("AD query"); lookup->sendmsg->flags |= DNS_MESSAGEFLAG_AD; } if (lookup->cdflag) { debug("CD query"); lookup->sendmsg->flags |= DNS_MESSAGEFLAG_CD; } if (lookup->zflag) { debug("Z query"); lookup->sendmsg->flags |= 0x0040U; } dns_message_addname(lookup->sendmsg, lookup->name, DNS_SECTION_QUESTION); if (lookup->trace && lookup->trace_root) { lookup->qrdtype = lookup->rdtype; lookup->rdtype = dns_rdatatype_ns; } if ((lookup->rdtype == dns_rdatatype_axfr) || (lookup->rdtype == dns_rdatatype_ixfr)) { /* * Force TCP mode if we're doing an axfr. */ if (lookup->rdtype == dns_rdatatype_axfr) { lookup->doing_xfr = ISC_TRUE; lookup->tcp_mode = ISC_TRUE; } else if (lookup->tcp_mode) { lookup->doing_xfr = ISC_TRUE; } } if (!lookup->header_only) add_question(lookup->sendmsg, lookup->name, lookup->rdclass, lookup->rdtype); /* add_soa */ if (lookup->rdtype == dns_rdatatype_ixfr) insert_soa(lookup); /* XXX Insist this? */ lookup->tsigctx = NULL; lookup->querysig = NULL; if (key != NULL) { debug("initializing keys"); result = dns_message_settsigkey(lookup->sendmsg, key); check_result(result, "dns_message_settsigkey"); } lookup->sendspace = isc_mempool_get(commctx); if (lookup->sendspace == NULL) fatal("memory allocation failure"); result = dns_compress_init(&cctx, -1, mctx); check_result(result, "dns_compress_init"); debug("starting to render the message"); isc_buffer_init(&lookup->renderbuf, lookup->sendspace, COMMSIZE); result = dns_message_renderbegin(lookup->sendmsg, &cctx, &lookup->renderbuf); check_result(result, "dns_message_renderbegin"); if (lookup->udpsize > 0 || lookup->dnssec || lookup->edns > -1 || lookup->ecs_addr != NULL) { #define MAXOPTS (EDNSOPT_OPTIONS + DNS_EDNSOPTIONS) dns_ednsopt_t opts[MAXOPTS]; unsigned int flags; unsigned int i = 0; if (lookup->udpsize == 0) lookup->udpsize = 4096; if (lookup->edns < 0) lookup->edns = 0; if (lookup->nsid) { INSIST(i < MAXOPTS); opts[i].code = DNS_OPT_NSID; opts[i].length = 0; opts[i].value = NULL; i++; } if (lookup->ecs_addr != NULL) { isc_uint8_t addr[16]; isc_uint16_t family; isc_uint32_t plen; struct sockaddr *sa; struct sockaddr_in *sin; struct sockaddr_in6 *sin6; size_t addrl; sa = &lookup->ecs_addr->type.sa; plen = lookup->ecs_addr->length; /* Round up prefix len to a multiple of 8 */ addrl = (plen + 7) / 8; INSIST(i < MAXOPTS); opts[i].code = DNS_OPT_CLIENT_SUBNET; opts[i].length = (isc_uint16_t) addrl + 4; check_result(result, "isc_buffer_allocate"); /* * XXXMUKS: According to RFC7871, "If there is * no ADDRESS set, i.e., SOURCE PREFIX-LENGTH is * set to 0, then FAMILY SHOULD be set to the * transport over which the query is sent." * * However, at this point we don't know what * transport(s) we'll be using, so we can't * set the value now. For now, we're using * IPv4 as the default the +subnet option * used an IPv4 prefix, or for +subnet=0, * and IPv6 if the +subnet option used an * IPv6 prefix. * * (For future work: preserve the offset into * the buffer where the family field is; * that way we can update it in send_udp() * or send_tcp_connect() once we know * what it outght to be.) */ switch (sa->sa_family) { case AF_UNSPEC: INSIST(plen == 0); family = 1; break; case AF_INET: INSIST(plen <= 32); family = 1; sin = (struct sockaddr_in *) sa; memmove(addr, &sin->sin_addr, addrl); break; case AF_INET6: INSIST(plen <= 128); family = 2; sin6 = (struct sockaddr_in6 *) sa; memmove(addr, &sin6->sin6_addr, addrl); break; default: INSIST(0); } isc_buffer_init(&b, ecsbuf, sizeof(ecsbuf)); /* family */ isc_buffer_putuint16(&b, family); /* source prefix-length */ isc_buffer_putuint8(&b, plen); /* scope prefix-length */ isc_buffer_putuint8(&b, 0); /* address */ if (addrl > 0) { /* Mask off last address byte */ if ((plen % 8) != 0) addr[addrl - 1] &= ~0U << (8 - (plen % 8)); isc_buffer_putmem(&b, addr, (unsigned)addrl); } opts[i].value = (isc_uint8_t *) ecsbuf; i++; } if (lookup->sendcookie) { INSIST(i < MAXOPTS); opts[i].code = DNS_OPT_COOKIE; if (lookup->cookie != NULL) { isc_buffer_init(&b, cookiebuf, sizeof(cookiebuf)); result = isc_hex_decodestring(lookup->cookie, &b); check_result(result, "isc_hex_decodestring"); opts[i].value = isc_buffer_base(&b); opts[i].length = isc_buffer_usedlength(&b); } else { compute_cookie(cookie, sizeof(cookie)); opts[i].length = 8; opts[i].value = cookie; } i++; } if (lookup->expire) { INSIST(i < MAXOPTS); opts[i].code = DNS_OPT_EXPIRE; opts[i].length = 0; opts[i].value = NULL; i++; } if (lookup->ednsoptscnt != 0) { INSIST(i + lookup->ednsoptscnt <= MAXOPTS); memmove(&opts[i], lookup->ednsopts, sizeof(dns_ednsopt_t) * lookup->ednsoptscnt); i += lookup->ednsoptscnt; } flags = lookup->ednsflags; flags &= ~DNS_MESSAGEEXTFLAG_DO; if (lookup->dnssec) flags |= DNS_MESSAGEEXTFLAG_DO; add_opt(lookup->sendmsg, lookup->udpsize, lookup->edns, flags, opts, i); } result = dns_message_rendersection(lookup->sendmsg, DNS_SECTION_QUESTION, 0); check_result(result, "dns_message_rendersection"); result = dns_message_rendersection(lookup->sendmsg, DNS_SECTION_AUTHORITY, 0); check_result(result, "dns_message_rendersection"); result = dns_message_renderend(lookup->sendmsg); check_result(result, "dns_message_renderend"); debug("done rendering"); dns_compress_invalidate(&cctx); /* * Force TCP mode if the request is larger than 512 bytes. */ if (isc_buffer_usedlength(&lookup->renderbuf) > 512) lookup->tcp_mode = ISC_TRUE; lookup->pending = ISC_FALSE; for (serv = ISC_LIST_HEAD(lookup->my_server_list); serv != NULL; serv = ISC_LIST_NEXT(serv, link)) { query = isc_mem_allocate(mctx, sizeof(dig_query_t)); if (query == NULL) fatal("memory allocation failure in %s:%d", __FILE__, __LINE__); debug("create query %p linked to lookup %p", query, lookup); query->lookup = lookup; query->timer = NULL; query->waiting_connect = ISC_FALSE; query->waiting_senddone = ISC_FALSE; query->pending_free = ISC_FALSE; query->recv_made = ISC_FALSE; query->first_pass = ISC_TRUE; query->first_soa_rcvd = ISC_FALSE; query->second_rr_rcvd = ISC_FALSE; query->first_repeat_rcvd = ISC_FALSE; query->warn_id = ISC_TRUE; query->timedout = ISC_FALSE; query->first_rr_serial = 0; query->second_rr_serial = 0; query->servname = serv->servername; query->userarg = serv->userarg; query->rr_count = 0; query->msg_count = 0; query->byte_count = 0; query->ixfr_axfr = ISC_FALSE; ISC_LIST_INIT(query->recvlist); ISC_LIST_INIT(query->lengthlist); query->sock = NULL; query->recvspace = isc_mempool_get(commctx); if (query->recvspace == NULL) fatal("memory allocation failure"); isc_buffer_init(&query->recvbuf, query->recvspace, COMMSIZE); isc_buffer_init(&query->lengthbuf, query->lengthspace, 2); isc_buffer_init(&query->slbuf, query->slspace, 2); query->sendbuf = lookup->renderbuf; ISC_LINK_INIT(query, clink); ISC_LINK_INIT(query, link); ISC_LIST_ENQUEUE(lookup->q, query, link); } /* XXX qrflag, print_query, etc... */ if (!ISC_LIST_EMPTY(lookup->q) && qr) { extrabytes = 0; dighost_printmessage(ISC_LIST_HEAD(lookup->q), lookup->sendmsg, ISC_TRUE); if (lookup->stats) printf(";; QUERY SIZE: %u\n\n", isc_buffer_usedlength(&lookup->renderbuf)); } return (ISC_TRUE); } /*% * Event handler for send completion. Track send counter, and clear out * the query if the send was canceled. */ static void send_done(isc_task_t *_task, isc_event_t *event) { isc_socketevent_t *sevent = (isc_socketevent_t *)event; isc_buffer_t *b = NULL; dig_query_t *query, *next; dig_lookup_t *l; REQUIRE(event->ev_type == ISC_SOCKEVENT_SENDDONE); UNUSED(_task); LOCK_LOOKUP; debug("send_done()"); sendcount--; debug("sendcount=%d", sendcount); INSIST(sendcount >= 0); for (b = ISC_LIST_HEAD(sevent->bufferlist); b != NULL; b = ISC_LIST_HEAD(sevent->bufferlist)) { ISC_LIST_DEQUEUE(sevent->bufferlist, b, link); isc_mem_free(mctx, b); } query = event->ev_arg; query->waiting_senddone = ISC_FALSE; l = query->lookup; if (l->ns_search_only && !l->trace_root && !l->tcp_mode) { debug("sending next, since searching"); next = ISC_LIST_NEXT(query, link); if (next != NULL) send_udp(next); } isc_event_free(&event); if (query->pending_free) isc_mem_free(mctx, query); check_if_done(); UNLOCK_LOOKUP; } /*% * Cancel a lookup, sending isc_socket_cancel() requests to all outstanding * IO sockets. The cancel handlers should take care of cleaning up the * query and lookup structures */ static void cancel_lookup(dig_lookup_t *lookup) { dig_query_t *query, *next; debug("cancel_lookup()"); query = ISC_LIST_HEAD(lookup->q); while (query != NULL) { next = ISC_LIST_NEXT(query, link); if (query->sock != NULL) { isc_socket_cancel(query->sock, global_task, ISC_SOCKCANCEL_ALL); check_if_done(); } else { clear_query(query); } query = next; } lookup->pending = ISC_FALSE; lookup->retries = 0; } static void bringup_timer(dig_query_t *query, unsigned int default_timeout) { dig_lookup_t *l; unsigned int local_timeout; isc_result_t result; debug("bringup_timer()"); /* * If the timer already exists, that means we're calling this * a second time (for a retry). Don't need to recreate it, * just reset it. */ l = query->lookup; if (ISC_LINK_LINKED(query, link) && ISC_LIST_NEXT(query, link) != NULL) local_timeout = SERVER_TIMEOUT; else { if (timeout == 0) local_timeout = default_timeout; else local_timeout = timeout; } debug("have local timeout of %d", local_timeout); isc_interval_set(&l->interval, local_timeout, 0); if (query->timer != NULL) isc_timer_detach(&query->timer); result = isc_timer_create(timermgr, isc_timertype_once, NULL, &l->interval, global_task, connect_timeout, query, &query->timer); check_result(result, "isc_timer_create"); } static void force_timeout(dig_query_t *query) { isc_event_t *event; debug("force_timeout ()"); event = isc_event_allocate(mctx, query, ISC_TIMEREVENT_IDLE, connect_timeout, query, sizeof(isc_event_t)); if (event == NULL) { fatal("isc_event_allocate: %s", isc_result_totext(ISC_R_NOMEMORY)); } isc_task_send(global_task, &event); /* * The timer may have expired if, for example, get_address() takes * long time and the timer was running on a different thread. * We need to cancel the possible timeout event not to confuse * ourselves due to the duplicate events. */ if (query->timer != NULL) isc_timer_detach(&query->timer); } static void connect_done(isc_task_t *task, isc_event_t *event); /*% * Unlike send_udp, this can't be called multiple times with the same * query. When we retry TCP, we requeue the whole lookup, which should * start anew. */ static void send_tcp_connect(dig_query_t *query) { isc_result_t result; dig_query_t *next; dig_lookup_t *l; debug("send_tcp_connect(%p)", query); l = query->lookup; query->waiting_connect = ISC_TRUE; query->lookup->current_query = query; result = get_address(query->servname, port, &query->sockaddr); if (result != ISC_R_SUCCESS) { /* * This servname doesn't have an address. Try the next server * by triggering an immediate 'timeout' (we lie, but the effect * is the same). */ force_timeout(query); return; } if (!l->mapped && isc_sockaddr_pf(&query->sockaddr) == AF_INET6 && IN6_IS_ADDR_V4MAPPED(&query->sockaddr.type.sin6.sin6_addr)) { isc_netaddr_t netaddr; char buf[ISC_NETADDR_FORMATSIZE]; isc_netaddr_fromsockaddr(&netaddr, &query->sockaddr); isc_netaddr_format(&netaddr, buf, sizeof(buf)); printf(";; Skipping mapped address '%s'\n", buf); query->waiting_connect = ISC_FALSE; if (ISC_LINK_LINKED(query, link)) next = ISC_LIST_NEXT(query, link); else next = NULL; l = query->lookup; clear_query(query); if (next == NULL) { printf(";; No acceptable nameservers\n"); check_next_lookup(l); return; } send_tcp_connect(next); return; } if (specified_source && (isc_sockaddr_pf(&query->sockaddr) != isc_sockaddr_pf(&bind_address))) { printf(";; Skipping server %s, incompatible " "address family\n", query->servname); query->waiting_connect = ISC_FALSE; if (ISC_LINK_LINKED(query, link)) next = ISC_LIST_NEXT(query, link); else next = NULL; l = query->lookup; clear_query(query); if (next == NULL) { printf(";; No acceptable nameservers\n"); check_next_lookup(l); return; } send_tcp_connect(next); return; } INSIST(query->sock == NULL); if (keep != NULL && isc_sockaddr_equal(&keepaddr, &query->sockaddr)) { sockcount++; isc_socket_attach(keep, &query->sock); query->waiting_connect = ISC_FALSE; launch_next_query(query, ISC_TRUE); goto search; } result = isc_socket_create(socketmgr, isc_sockaddr_pf(&query->sockaddr), isc_sockettype_tcp, &query->sock); check_result(result, "isc_socket_create"); sockcount++; debug("sockcount=%d", sockcount); if (query->lookup->dscp != -1) isc_socket_dscp(query->sock, query->lookup->dscp); isc_socket_ipv6only(query->sock, ISC_TF(!query->lookup->mapped)); if (specified_source) result = isc_socket_bind(query->sock, &bind_address, ISC_SOCKET_REUSEADDRESS); else { if ((isc_sockaddr_pf(&query->sockaddr) == AF_INET) && have_ipv4) isc_sockaddr_any(&bind_any); else isc_sockaddr_any6(&bind_any); result = isc_socket_bind(query->sock, &bind_any, 0); } check_result(result, "isc_socket_bind"); bringup_timer(query, TCP_TIMEOUT); result = isc_socket_connect(query->sock, &query->sockaddr, global_task, connect_done, query); check_result(result, "isc_socket_connect"); search: /* * If we're at the endgame of a nameserver search, we need to * immediately bring up all the queries. Do it here. */ if (l->ns_search_only && !l->trace_root) { debug("sending next, since searching"); if (ISC_LINK_LINKED(query, link)) { next = ISC_LIST_NEXT(query, link); ISC_LIST_DEQUEUE(l->q, query, link); } else next = NULL; ISC_LIST_ENQUEUE(l->connecting, query, clink); if (next != NULL) send_tcp_connect(next); } } static isc_buffer_t * clone_buffer(isc_buffer_t *source) { isc_buffer_t *buffer; buffer = isc_mem_allocate(mctx, sizeof(*buffer)); if (buffer == NULL) fatal("memory allocation failure in %s:%d", __FILE__, __LINE__); *buffer = *source; return (buffer); } /*% * Send a UDP packet to the remote nameserver, possible starting the * recv action as well. Also make sure that the timer is running and * is properly reset. */ static void send_udp(dig_query_t *query) { dig_lookup_t *l = NULL; isc_result_t result; isc_buffer_t *sendbuf; dig_query_t *next; debug("send_udp(%p)", query); l = query->lookup; bringup_timer(query, UDP_TIMEOUT); l->current_query = query; debug("working on lookup %p, query %p", query->lookup, query); if (!query->recv_made) { /* XXX Check the sense of this, need assertion? */ query->waiting_connect = ISC_FALSE; result = get_address(query->servname, port, &query->sockaddr); if (result != ISC_R_SUCCESS) { /* This servname doesn't have an address. */ force_timeout(query); return; } if (!l->mapped && isc_sockaddr_pf(&query->sockaddr) == AF_INET6 && IN6_IS_ADDR_V4MAPPED(&query->sockaddr.type.sin6.sin6_addr)) { isc_netaddr_t netaddr; char buf[ISC_NETADDR_FORMATSIZE]; isc_netaddr_fromsockaddr(&netaddr, &query->sockaddr); isc_netaddr_format(&netaddr, buf, sizeof(buf)); printf(";; Skipping mapped address '%s'\n", buf); next = ISC_LIST_NEXT(query, link); l = query->lookup; clear_query(query); if (next == NULL) { printf(";; No acceptable nameservers\n"); check_next_lookup(l); } else { send_udp(next); } return; } result = isc_socket_create(socketmgr, isc_sockaddr_pf(&query->sockaddr), isc_sockettype_udp, &query->sock); check_result(result, "isc_socket_create"); sockcount++; debug("sockcount=%d", sockcount); if (query->lookup->dscp != -1) isc_socket_dscp(query->sock, query->lookup->dscp); isc_socket_ipv6only(query->sock, ISC_TF(!query->lookup->mapped)); if (specified_source) { result = isc_socket_bind(query->sock, &bind_address, ISC_SOCKET_REUSEADDRESS); } else { isc_sockaddr_anyofpf(&bind_any, isc_sockaddr_pf(&query->sockaddr)); result = isc_socket_bind(query->sock, &bind_any, 0); } check_result(result, "isc_socket_bind"); query->recv_made = ISC_TRUE; ISC_LINK_INIT(&query->recvbuf, link); ISC_LIST_ENQUEUE(query->recvlist, &query->recvbuf, link); debug("recving with lookup=%p, query=%p, sock=%p", query->lookup, query, query->sock); result = isc_socket_recvv(query->sock, &query->recvlist, 1, global_task, recv_done, query); check_result(result, "isc_socket_recvv"); recvcount++; debug("recvcount=%d", recvcount); } ISC_LIST_INIT(query->sendlist); sendbuf = clone_buffer(&query->sendbuf); ISC_LIST_ENQUEUE(query->sendlist, sendbuf, link); debug("sending a request"); TIME_NOW(&query->time_sent); INSIST(query->sock != NULL); query->waiting_senddone = ISC_TRUE; result = isc_socket_sendtov2(query->sock, &query->sendlist, global_task, send_done, query, &query->sockaddr, NULL, ISC_SOCKFLAG_NORETRY); check_result(result, "isc_socket_sendtov"); sendcount++; } /*% * IO timeout handler, used for both connect and recv timeouts. If * retries are still allowed, either resend the UDP packet or queue a * new TCP lookup. Otherwise, cancel the lookup. */ static void connect_timeout(isc_task_t *task, isc_event_t *event) { dig_lookup_t *l = NULL; dig_query_t *query = NULL, *cq; UNUSED(task); REQUIRE(event->ev_type == ISC_TIMEREVENT_IDLE); debug("connect_timeout()"); LOCK_LOOKUP; query = event->ev_arg; l = query->lookup; isc_event_free(&event); INSIST(!free_now); if ((query != NULL) && (query->lookup->current_query != NULL) && ISC_LINK_LINKED(query->lookup->current_query, link) && (ISC_LIST_NEXT(query->lookup->current_query, link) != NULL)) { debug("trying next server..."); cq = query->lookup->current_query; if (!l->tcp_mode) send_udp(ISC_LIST_NEXT(cq, link)); else { if (query->sock != NULL) isc_socket_cancel(query->sock, NULL, ISC_SOCKCANCEL_ALL); send_tcp_connect(ISC_LIST_NEXT(cq, link)); } UNLOCK_LOOKUP; return; } if (l->tcp_mode && query->sock != NULL) { query->timedout = ISC_TRUE; isc_socket_cancel(query->sock, NULL, ISC_SOCKCANCEL_ALL); } if (l->retries > 1) { if (!l->tcp_mode) { l->retries--; debug("resending UDP request to first server"); send_udp(ISC_LIST_HEAD(l->q)); } else { debug("making new TCP request, %d tries left", l->retries); l->retries--; requeue_lookup(l, ISC_TRUE); cancel_lookup(l); check_next_lookup(l); } } else { if (!l->ns_search_only) { fputs(l->cmdline, stdout); printf(";; connection timed out; no servers could be " "reached\n"); } cancel_lookup(l); check_next_lookup(l); if (exitcode < 9) exitcode = 9; } UNLOCK_LOOKUP; } /*% * Event handler for the TCP recv which gets the length header of TCP * packets. Start the next recv of length bytes. */ static void tcp_length_done(isc_task_t *task, isc_event_t *event) { isc_socketevent_t *sevent; isc_buffer_t *b = NULL; isc_result_t result; dig_query_t *query = NULL; dig_lookup_t *l, *n; isc_uint16_t length; REQUIRE(event->ev_type == ISC_SOCKEVENT_RECVDONE); INSIST(!free_now); UNUSED(task); debug("tcp_length_done()"); LOCK_LOOKUP; sevent = (isc_socketevent_t *)event; query = event->ev_arg; recvcount--; INSIST(recvcount >= 0); b = ISC_LIST_HEAD(sevent->bufferlist); INSIST(b == &query->lengthbuf); ISC_LIST_DEQUEUE(sevent->bufferlist, b, link); if (sevent->result == ISC_R_CANCELED) { isc_event_free(&event); l = query->lookup; clear_query(query); check_next_lookup(l); UNLOCK_LOOKUP; return; } if (sevent->result != ISC_R_SUCCESS) { char sockstr[ISC_SOCKADDR_FORMATSIZE]; isc_sockaddr_format(&query->sockaddr, sockstr, sizeof(sockstr)); printf(";; communications error to %s: %s\n", sockstr, isc_result_totext(sevent->result)); if (keep != NULL) isc_socket_detach(&keep); l = query->lookup; isc_socket_detach(&query->sock); sockcount--; debug("sockcount=%d", sockcount); INSIST(sockcount >= 0); if (sevent->result == ISC_R_EOF && l->eoferr == 0U) { n = requeue_lookup(l, ISC_TRUE); n->eoferr++; } isc_event_free(&event); clear_query(query); cancel_lookup(l); check_next_lookup(l); UNLOCK_LOOKUP; return; } length = isc_buffer_getuint16(b); if (length == 0) { isc_event_free(&event); launch_next_query(query, ISC_FALSE); UNLOCK_LOOKUP; return; } /* * Even though the buffer was already init'ed, we need * to redo it now, to force the length we want. */ isc_buffer_invalidate(&query->recvbuf); isc_buffer_init(&query->recvbuf, query->recvspace, length); ENSURE(ISC_LIST_EMPTY(query->recvlist)); ISC_LINK_INIT(&query->recvbuf, link); ISC_LIST_ENQUEUE(query->recvlist, &query->recvbuf, link); debug("recving with lookup=%p, query=%p", query->lookup, query); result = isc_socket_recvv(query->sock, &query->recvlist, length, task, recv_done, query); check_result(result, "isc_socket_recvv"); recvcount++; debug("resubmitted recv request with length %d, recvcount=%d", length, recvcount); isc_event_free(&event); UNLOCK_LOOKUP; } /*% * For transfers that involve multiple recvs (XFR's in particular), * launch the next recv. */ static void launch_next_query(dig_query_t *query, isc_boolean_t include_question) { isc_result_t result; dig_lookup_t *l; isc_buffer_t *buffer; INSIST(!free_now); debug("launch_next_query()"); if (!query->lookup->pending) { debug("ignoring launch_next_query because !pending"); isc_socket_detach(&query->sock); sockcount--; debug("sockcount=%d", sockcount); INSIST(sockcount >= 0); query->waiting_connect = ISC_FALSE; l = query->lookup; clear_query(query); check_next_lookup(l); return; } isc_buffer_clear(&query->slbuf); isc_buffer_clear(&query->lengthbuf); isc_buffer_putuint16(&query->slbuf, (isc_uint16_t) query->sendbuf.used); ISC_LIST_INIT(query->sendlist); ISC_LINK_INIT(&query->slbuf, link); if (!query->first_soa_rcvd) { buffer = clone_buffer(&query->slbuf); ISC_LIST_ENQUEUE(query->sendlist, buffer, link); if (include_question) { buffer = clone_buffer(&query->sendbuf); ISC_LIST_ENQUEUE(query->sendlist, buffer, link); } } ISC_LINK_INIT(&query->lengthbuf, link); ISC_LIST_ENQUEUE(query->lengthlist, &query->lengthbuf, link); result = isc_socket_recvv(query->sock, &query->lengthlist, 0, global_task, tcp_length_done, query); check_result(result, "isc_socket_recvv"); recvcount++; debug("recvcount=%d", recvcount); if (!query->first_soa_rcvd) { debug("sending a request in launch_next_query"); TIME_NOW(&query->time_sent); query->waiting_senddone = ISC_TRUE; result = isc_socket_sendv(query->sock, &query->sendlist, global_task, send_done, query); check_result(result, "isc_socket_sendv"); sendcount++; debug("sendcount=%d", sendcount); } query->waiting_connect = ISC_FALSE; #if 0 check_next_lookup(query->lookup); #endif return; } /*% * Event handler for TCP connect complete. Make sure the connection was * successful, then pass into launch_next_query to actually send the * question. */ static void connect_done(isc_task_t *task, isc_event_t *event) { char sockstr[ISC_SOCKADDR_FORMATSIZE]; isc_socketevent_t *sevent = NULL; dig_query_t *query = NULL, *next; dig_lookup_t *l; UNUSED(task); REQUIRE(event->ev_type == ISC_SOCKEVENT_CONNECT); INSIST(!free_now); debug("connect_done()"); LOCK_LOOKUP; sevent = (isc_socketevent_t *)event; query = sevent->ev_arg; INSIST(query->waiting_connect); query->waiting_connect = ISC_FALSE; if (sevent->result == ISC_R_CANCELED) { debug("in cancel handler"); isc_sockaddr_format(&query->sockaddr, sockstr, sizeof(sockstr)); if (query->timedout) printf(";; Connection to %s(%s) for %s failed: %s.\n", sockstr, query->servname, query->lookup->textname, isc_result_totext(ISC_R_TIMEDOUT)); isc_socket_detach(&query->sock); INSIST(sockcount > 0); sockcount--; debug("sockcount=%d", sockcount); query->waiting_connect = ISC_FALSE; isc_event_free(&event); l = query->lookup; clear_query(query); check_next_lookup(l); UNLOCK_LOOKUP; return; } if (sevent->result != ISC_R_SUCCESS) { debug("unsuccessful connection: %s", isc_result_totext(sevent->result)); isc_sockaddr_format(&query->sockaddr, sockstr, sizeof(sockstr)); if (sevent->result != ISC_R_CANCELED) printf(";; Connection to %s(%s) for %s failed: " "%s.\n", sockstr, query->servname, query->lookup->textname, isc_result_totext(sevent->result)); isc_socket_detach(&query->sock); INSIST(sockcount > 0); sockcount--; /* XXX Clean up exitcodes */ if (exitcode < 9) exitcode = 9; debug("sockcount=%d", sockcount); query->waiting_connect = ISC_FALSE; isc_event_free(&event); l = query->lookup; if ((l->current_query != NULL) && (ISC_LINK_LINKED(l->current_query, link))) next = ISC_LIST_NEXT(l->current_query, link); else next = NULL; clear_query(query); if (next != NULL) { bringup_timer(next, TCP_TIMEOUT); send_tcp_connect(next); } else check_next_lookup(l); UNLOCK_LOOKUP; return; } if (keep_open) { if (keep != NULL) isc_socket_detach(&keep); isc_socket_attach(query->sock, &keep); keepaddr = query->sockaddr; } launch_next_query(query, ISC_TRUE); isc_event_free(&event); UNLOCK_LOOKUP; } /*% * Check if the ongoing XFR needs more data before it's complete, using * the semantics of IXFR and AXFR protocols. Much of the complexity of * this routine comes from determining when an IXFR is complete. * ISC_FALSE means more data is on the way, and the recv has been issued. */ static isc_boolean_t check_for_more_data(dig_query_t *query, dns_message_t *msg, isc_socketevent_t *sevent) { dns_rdataset_t *rdataset = NULL; dns_rdata_t rdata = DNS_RDATA_INIT; dns_rdata_soa_t soa; isc_uint32_t ixfr_serial = query->lookup->ixfr_serial, serial; isc_result_t result; isc_boolean_t ixfr = query->lookup->rdtype == dns_rdatatype_ixfr; isc_boolean_t axfr = query->lookup->rdtype == dns_rdatatype_axfr; if (ixfr) axfr = query->ixfr_axfr; debug("check_for_more_data()"); /* * By the time we're in this routine, we know we're doing * either an AXFR or IXFR. If there's no second_rr_type, * then we don't yet know which kind of answer we got back * from the server. Here, we're going to walk through the * rr's in the message, acting as necessary whenever we hit * an SOA rr. */ query->msg_count++; query->byte_count += sevent->n; result = dns_message_firstname(msg, DNS_SECTION_ANSWER); if (result != ISC_R_SUCCESS) { puts("; Transfer failed."); return (ISC_TRUE); } do { dns_name_t *name; name = NULL; dns_message_currentname(msg, DNS_SECTION_ANSWER, &name); for (rdataset = ISC_LIST_HEAD(name->list); rdataset != NULL; rdataset = ISC_LIST_NEXT(rdataset, link)) { result = dns_rdataset_first(rdataset); if (result != ISC_R_SUCCESS) continue; do { query->rr_count++; dns_rdata_reset(&rdata); dns_rdataset_current(rdataset, &rdata); /* * If this is the first rr, make sure * it's an SOA */ if ((!query->first_soa_rcvd) && (rdata.type != dns_rdatatype_soa)) { puts("; Transfer failed. " "Didn't start with SOA answer."); return (ISC_TRUE); } if ((!query->second_rr_rcvd) && (rdata.type != dns_rdatatype_soa)) { query->second_rr_rcvd = ISC_TRUE; query->second_rr_serial = 0; debug("got the second rr as nonsoa"); axfr = query->ixfr_axfr = ISC_TRUE; goto next_rdata; } /* * If the record is anything except an SOA * now, just continue on... */ if (rdata.type != dns_rdatatype_soa) goto next_rdata; /* Now we have an SOA. Work with it. */ debug("got an SOA"); result = dns_rdata_tostruct(&rdata, &soa, NULL); check_result(result, "dns_rdata_tostruct"); serial = soa.serial; dns_rdata_freestruct(&soa); if (!query->first_soa_rcvd) { query->first_soa_rcvd = ISC_TRUE; query->first_rr_serial = serial; debug("this is the first serial %u", serial); if (ixfr && isc_serial_ge(ixfr_serial, serial)) { debug("got up to date " "response"); goto doexit; } goto next_rdata; } if (axfr) { debug("doing axfr, got second SOA"); goto doexit; } if (!query->second_rr_rcvd) { if (query->first_rr_serial == serial) { debug("doing ixfr, got " "empty zone"); goto doexit; } debug("this is the second serial %u", serial); query->second_rr_rcvd = ISC_TRUE; query->second_rr_serial = serial; goto next_rdata; } /* * If we get to this point, we're doing an * IXFR and have to start really looking * at serial numbers. */ if (query->first_rr_serial == serial) { debug("got a match for ixfr"); if (!query->first_repeat_rcvd) { query->first_repeat_rcvd = ISC_TRUE; goto next_rdata; } debug("done with ixfr"); goto doexit; } debug("meaningless soa %u", serial); next_rdata: result = dns_rdataset_next(rdataset); } while (result == ISC_R_SUCCESS); } result = dns_message_nextname(msg, DNS_SECTION_ANSWER); } while (result == ISC_R_SUCCESS); launch_next_query(query, ISC_FALSE); return (ISC_FALSE); doexit: dighost_received(sevent->n, &sevent->address, query); return (ISC_TRUE); } static void process_cookie(dig_lookup_t *l, dns_message_t *msg, isc_buffer_t *optbuf, size_t optlen) { char bb[256]; isc_buffer_t hexbuf; size_t len; const unsigned char *sent; isc_boolean_t copy = ISC_TRUE; isc_result_t result; if (l->cookie != NULL) { isc_buffer_init(&hexbuf, bb, sizeof(bb)); result = isc_hex_decodestring(l->cookie, &hexbuf); check_result(result, "isc_hex_decodestring"); sent = isc_buffer_base(&hexbuf); len = isc_buffer_usedlength(&hexbuf); } else { sent = cookie; len = sizeof(cookie); } INSIST(msg->cc_ok == 0 && msg->cc_bad == 0); if (optlen >= len && optlen >= 8U) { if (isc_safe_memequal(isc_buffer_current(optbuf), sent, 8)) { msg->cc_ok = 1; } else { printf(";; Warning: Client COOKIE mismatch\n"); msg->cc_bad = 1; copy = ISC_FALSE; } } else { printf(";; Warning: COOKIE bad token (too short)\n"); msg->cc_bad = 1; copy = ISC_FALSE; } if (copy) { isc_region_t r; r.base = isc_buffer_current(optbuf); r.length = (unsigned int)optlen; isc_buffer_init(&hexbuf, servercookie, sizeof(servercookie)); result = isc_hex_totext(&r, 2, "", &hexbuf); check_result(result, "isc_hex_totext"); if (isc_buffer_availablelength(&hexbuf) > 0) { isc_buffer_putuint8(&hexbuf, 0); l->cookie = servercookie; } } isc_buffer_forward(optbuf, (unsigned int)optlen); } static void process_opt(dig_lookup_t *l, dns_message_t *msg) { dns_rdata_t rdata; isc_result_t result; isc_buffer_t optbuf; isc_uint16_t optcode, optlen; dns_rdataset_t *opt = msg->opt; isc_boolean_t seen_cookie = ISC_FALSE; result = dns_rdataset_first(opt); if (result == ISC_R_SUCCESS) { dns_rdata_init(&rdata); dns_rdataset_current(opt, &rdata); isc_buffer_init(&optbuf, rdata.data, rdata.length); isc_buffer_add(&optbuf, rdata.length); while (isc_buffer_remaininglength(&optbuf) >= 4) { optcode = isc_buffer_getuint16(&optbuf); optlen = isc_buffer_getuint16(&optbuf); switch (optcode) { case DNS_OPT_COOKIE: /* * Only process the first cookie option. */ if (seen_cookie) { isc_buffer_forward(&optbuf, optlen); break; } process_cookie(l, msg, &optbuf, optlen); seen_cookie = ISC_TRUE; break; default: isc_buffer_forward(&optbuf, optlen); break; } } } } static int ednsvers(dns_rdataset_t *opt) { return ((opt->ttl >> 16) & 0xff); } /*% * Event handler for recv complete. Perform whatever actions are necessary, * based on the specifics of the user's request. */ static void recv_done(isc_task_t *task, isc_event_t *event) { isc_socketevent_t *sevent = NULL; dig_query_t *query = NULL; isc_buffer_t *b = NULL; dns_message_t *msg = NULL; #ifdef DIG_SIGCHASE dig_message_t *chase_msg = NULL; dig_message_t *chase_msg2 = NULL; #endif isc_result_t result; dig_lookup_t *n, *l; isc_boolean_t docancel = ISC_FALSE; isc_boolean_t match = ISC_TRUE; unsigned int parseflags; dns_messageid_t id; unsigned int msgflags; #ifdef DIG_SIGCHASE isc_result_t do_sigchase = ISC_FALSE; dns_message_t *msg_temp = NULL; isc_region_t r; isc_buffer_t *buf = NULL; #endif int newedns; UNUSED(task); INSIST(!free_now); debug("recv_done()"); LOCK_LOOKUP; recvcount--; debug("recvcount=%d", recvcount); INSIST(recvcount >= 0); query = event->ev_arg; TIME_NOW(&query->time_recv); debug("lookup=%p, query=%p", query->lookup, query); l = query->lookup; REQUIRE(event->ev_type == ISC_SOCKEVENT_RECVDONE); sevent = (isc_socketevent_t *)event; b = ISC_LIST_HEAD(sevent->bufferlist); INSIST(b == &query->recvbuf); ISC_LIST_DEQUEUE(sevent->bufferlist, &query->recvbuf, link); if ((l->tcp_mode) && (query->timer != NULL)) isc_timer_touch(query->timer); if ((!l->pending && !l->ns_search_only) || cancel_now) { debug("no longer pending. Got %s", isc_result_totext(sevent->result)); query->waiting_connect = ISC_FALSE; isc_event_free(&event); clear_query(query); check_next_lookup(l); UNLOCK_LOOKUP; return; } if (sevent->result != ISC_R_SUCCESS) { if (sevent->result == ISC_R_CANCELED) { debug("in recv cancel handler"); query->waiting_connect = ISC_FALSE; } else { printf(";; communications error: %s\n", isc_result_totext(sevent->result)); if (keep != NULL) isc_socket_detach(&keep); isc_socket_detach(&query->sock); sockcount--; debug("sockcount=%d", sockcount); INSIST(sockcount >= 0); } if (sevent->result == ISC_R_EOF && l->eoferr == 0U) { n = requeue_lookup(l, ISC_TRUE); n->eoferr++; } isc_event_free(&event); clear_query(query); cancel_lookup(l); check_next_lookup(l); UNLOCK_LOOKUP; return; } if (!l->tcp_mode && !isc_sockaddr_compare(&sevent->address, &query->sockaddr, ISC_SOCKADDR_CMPADDR| ISC_SOCKADDR_CMPPORT| ISC_SOCKADDR_CMPSCOPE| ISC_SOCKADDR_CMPSCOPEZERO)) { char buf1[ISC_SOCKADDR_FORMATSIZE]; char buf2[ISC_SOCKADDR_FORMATSIZE]; isc_sockaddr_t any; if (isc_sockaddr_pf(&query->sockaddr) == AF_INET) isc_sockaddr_any(&any); else isc_sockaddr_any6(&any); /* * We don't expect a match when the packet is * sent to 0.0.0.0, :: or to a multicast addresses. * XXXMPA broadcast needs to be handled here as well. */ if ((!isc_sockaddr_eqaddr(&query->sockaddr, &any) && !isc_sockaddr_ismulticast(&query->sockaddr)) || isc_sockaddr_getport(&query->sockaddr) != isc_sockaddr_getport(&sevent->address)) { isc_sockaddr_format(&sevent->address, buf1, sizeof(buf1)); isc_sockaddr_format(&query->sockaddr, buf2, sizeof(buf2)); printf(";; reply from unexpected source: %s," " expected %s\n", buf1, buf2); match = ISC_FALSE; } } result = dns_message_peekheader(b, &id, &msgflags); if (result != ISC_R_SUCCESS || l->sendmsg->id != id) { match = ISC_FALSE; if (l->tcp_mode) { isc_boolean_t fail = ISC_TRUE; if (result == ISC_R_SUCCESS) { if (!query->first_soa_rcvd || query->warn_id) printf(";; %s: ID mismatch: " "expected ID %u, got %u\n", query->first_soa_rcvd ? "WARNING" : "ERROR", l->sendmsg->id, id); if (query->first_soa_rcvd) fail = ISC_FALSE; query->warn_id = ISC_FALSE; } else printf(";; ERROR: short " "(< header size) message\n"); if (fail) { isc_event_free(&event); clear_query(query); cancel_lookup(l); check_next_lookup(l); UNLOCK_LOOKUP; return; } match = ISC_TRUE; } else if (result == ISC_R_SUCCESS) printf(";; Warning: ID mismatch: " "expected ID %u, got %u\n", l->sendmsg->id, id); else printf(";; Warning: short " "(< header size) message received\n"); } if (result == ISC_R_SUCCESS && (msgflags & DNS_MESSAGEFLAG_QR) == 0) printf(";; Warning: query response not set\n"); if (!match) goto udp_mismatch; result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &msg); check_result(result, "dns_message_create"); if (key != NULL) { if (l->querysig == NULL) { debug("getting initial querysig"); result = dns_message_getquerytsig(l->sendmsg, mctx, &l->querysig); check_result(result, "dns_message_getquerytsig"); } result = dns_message_setquerytsig(msg, l->querysig); check_result(result, "dns_message_setquerytsig"); result = dns_message_settsigkey(msg, key); check_result(result, "dns_message_settsigkey"); msg->tsigctx = l->tsigctx; l->tsigctx = NULL; if (l->msgcounter != 0) msg->tcp_continuation = 1; l->msgcounter++; } debug("before parse starts"); parseflags = DNS_MESSAGEPARSE_PRESERVEORDER; #ifdef DIG_SIGCHASE if (!l->sigchase) { do_sigchase = ISC_FALSE; } else { parseflags = 0; do_sigchase = ISC_TRUE; } #endif if (l->besteffort) { parseflags |= DNS_MESSAGEPARSE_BESTEFFORT; parseflags |= DNS_MESSAGEPARSE_IGNORETRUNCATION; } result = dns_message_parse(msg, b, parseflags); if (result == DNS_R_RECOVERABLE) { printf(";; Warning: Message parser reports malformed " "message packet.\n"); result = ISC_R_SUCCESS; } if (result != ISC_R_SUCCESS) { printf(";; Got bad packet: %s\n", isc_result_totext(result)); hex_dump(b); query->waiting_connect = ISC_FALSE; dns_message_destroy(&msg); isc_event_free(&event); clear_query(query); cancel_lookup(l); check_next_lookup(l); UNLOCK_LOOKUP; return; } if (msg->counts[DNS_SECTION_QUESTION] != 0) { match = ISC_TRUE; for (result = dns_message_firstname(msg, DNS_SECTION_QUESTION); result == ISC_R_SUCCESS && match; result = dns_message_nextname(msg, DNS_SECTION_QUESTION)) { dns_name_t *name = NULL; dns_rdataset_t *rdataset; dns_message_currentname(msg, DNS_SECTION_QUESTION, &name); for (rdataset = ISC_LIST_HEAD(name->list); rdataset != NULL; rdataset = ISC_LIST_NEXT(rdataset, link)) { if (l->rdtype != rdataset->type || l->rdclass != rdataset->rdclass || !dns_name_equal(l->name, name)) { char namestr[DNS_NAME_FORMATSIZE]; char typebuf[DNS_RDATATYPE_FORMATSIZE]; char classbuf[DNS_RDATACLASS_FORMATSIZE]; dns_name_format(name, namestr, sizeof(namestr)); dns_rdatatype_format(rdataset->type, typebuf, sizeof(typebuf)); dns_rdataclass_format(rdataset->rdclass, classbuf, sizeof(classbuf)); printf(";; Question section mismatch: " "got %s/%s/%s\n", namestr, typebuf, classbuf); match = ISC_FALSE; } } } if (!match) { dns_message_destroy(&msg); if (l->tcp_mode) { isc_event_free(&event); clear_query(query); cancel_lookup(l); check_next_lookup(l); UNLOCK_LOOKUP; return; } else goto udp_mismatch; } } if (msg->rcode == dns_rcode_badvers && msg->opt != NULL && (newedns = ednsvers(msg->opt)) < l->edns && l->ednsneg) { /* * Add minimum EDNS version required checks here if needed. */ if (l->comments) printf(";; BADVERS, retrying with EDNS version %u.\n", newedns); l->edns = newedns; n = requeue_lookup(l, ISC_TRUE); if (l->trace && l->trace_root) n->rdtype = l->qrdtype; dns_message_destroy(&msg); isc_event_free(&event); clear_query(query); cancel_lookup(l); check_next_lookup(l); UNLOCK_LOOKUP; return; } if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0 && !l->ignore && !l->tcp_mode) { if (l->cookie == NULL && l->sendcookie && msg->opt != NULL) process_opt(l, msg); if (l->comments) printf(";; Truncated, retrying in TCP mode.\n"); n = requeue_lookup(l, ISC_TRUE); n->tcp_mode = ISC_TRUE; if (l->trace && l->trace_root) n->rdtype = l->qrdtype; dns_message_destroy(&msg); isc_event_free(&event); clear_query(query); cancel_lookup(l); check_next_lookup(l); UNLOCK_LOOKUP; return; } if (msg->rcode == dns_rcode_badcookie && !l->tcp_mode && l->sendcookie && l->badcookie) { process_opt(l, msg); if (msg->cc_ok) { if (l->comments) printf(";; BADCOOKIE, retrying%s.\n", l->seenbadcookie ? " in TCP mode" : ""); n = requeue_lookup(l, ISC_TRUE); if (l->seenbadcookie) n->tcp_mode = ISC_TRUE; n->seenbadcookie = ISC_TRUE; if (l->trace && l->trace_root) n->rdtype = l->qrdtype; dns_message_destroy(&msg); isc_event_free(&event); clear_query(query); cancel_lookup(l); check_next_lookup(l); UNLOCK_LOOKUP; return; } } if ((msg->rcode == dns_rcode_servfail && !l->servfail_stops) || (check_ra && (msg->flags & DNS_MESSAGEFLAG_RA) == 0 && l->recurse)) { dig_query_t *next = ISC_LIST_NEXT(query, link); if (l->current_query == query) l->current_query = NULL; if (next != NULL) { debug("sending query %p\n", next); if (l->tcp_mode) send_tcp_connect(next); else send_udp(next); } /* * If our query is at the head of the list and there * is no next, we're the only one left, so fall * through to print the message. */ if ((ISC_LIST_HEAD(l->q) != query) || (ISC_LIST_NEXT(query, link) != NULL)) { if (l->comments) printf(";; Got %s from %s, " "trying next server\n", msg->rcode == dns_rcode_servfail ? "SERVFAIL reply" : "recursion not available", query->servname); clear_query(query); check_next_lookup(l); dns_message_destroy(&msg); isc_event_free(&event); UNLOCK_LOOKUP; return; } } if (key != NULL) { result = dns_tsig_verify(&query->recvbuf, msg, NULL, NULL); if (result != ISC_R_SUCCESS) { printf(";; Couldn't verify signature: %s\n", isc_result_totext(result)); validated = ISC_FALSE; } l->tsigctx = msg->tsigctx; msg->tsigctx = NULL; if (l->querysig != NULL) { debug("freeing querysig buffer %p", l->querysig); isc_buffer_free(&l->querysig); } result = dns_message_getquerytsig(msg, mctx, &l->querysig); check_result(result,"dns_message_getquerytsig"); } extrabytes = isc_buffer_remaininglength(b); debug("after parse"); if (l->doing_xfr && l->xfr_q == NULL) { l->xfr_q = query; /* * Once we are in the XFR message, increase * the timeout to much longer, so brief network * outages won't cause the XFR to abort */ if (timeout != INT_MAX && query->timer != NULL) { unsigned int local_timeout; if (timeout == 0) { if (l->tcp_mode) local_timeout = TCP_TIMEOUT * 4; else local_timeout = UDP_TIMEOUT * 4; } else { if (timeout < (INT_MAX / 4)) local_timeout = timeout * 4; else local_timeout = INT_MAX; } debug("have local timeout of %d", local_timeout); isc_interval_set(&l->interval, local_timeout, 0); result = isc_timer_reset(query->timer, isc_timertype_once, NULL, &l->interval, ISC_FALSE); check_result(result, "isc_timer_reset"); } } if (l->cookie != NULL) { if (msg->opt == NULL) printf(";; expected opt record in response\n"); else process_opt(l, msg); } else if (l->sendcookie && msg->opt != NULL) process_opt(l, msg); if (!l->doing_xfr || l->xfr_q == query) { if (msg->rcode == dns_rcode_nxdomain && (l->origin != NULL || l->need_search)) { if (!next_origin(query->lookup) || showsearch) { dighost_printmessage(query, msg, ISC_TRUE); dighost_received(b->used, &sevent->address, query); } } else if (!l->trace && !l->ns_search_only) { #ifdef DIG_SIGCHASE if (!do_sigchase) #endif dighost_printmessage(query, msg, ISC_TRUE); } else if (l->trace) { int nl = 0; int count = msg->counts[DNS_SECTION_ANSWER]; debug("in TRACE code"); if (!l->ns_search_only) dighost_printmessage(query, msg, ISC_TRUE); l->rdtype = l->qrdtype; if (l->trace_root || (l->ns_search_only && count > 0)) { if (!l->trace_root) l->rdtype = dns_rdatatype_soa; nl = followup_lookup(msg, query, DNS_SECTION_ANSWER); l->trace_root = ISC_FALSE; } else if (count == 0) nl = followup_lookup(msg, query, DNS_SECTION_AUTHORITY); if (nl == 0) docancel = ISC_TRUE; } else { debug("in NSSEARCH code"); if (l->trace_root) { /* * This is the initial NS query. */ int nl; l->rdtype = dns_rdatatype_soa; nl = followup_lookup(msg, query, DNS_SECTION_ANSWER); if (nl == 0) docancel = ISC_TRUE; l->trace_root = ISC_FALSE; usesearch = ISC_FALSE; } else #ifdef DIG_SIGCHASE if (!do_sigchase) #endif dighost_printmessage(query, msg, ISC_TRUE); } #ifdef DIG_SIGCHASE if (do_sigchase) { chase_msg = isc_mem_allocate(mctx, sizeof(dig_message_t)); if (chase_msg == NULL) { fatal("Memory allocation failure in %s:%d", __FILE__, __LINE__); } ISC_LIST_INITANDAPPEND(chase_message_list, chase_msg, link); if (dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &msg_temp) != ISC_R_SUCCESS) { fatal("dns_message_create in %s:%d", __FILE__, __LINE__); } isc_buffer_usedregion(b, &r); result = isc_buffer_allocate(mctx, &buf, r.length); check_result(result, "isc_buffer_allocate"); result = isc_buffer_copyregion(buf, &r); check_result(result, "isc_buffer_copyregion"); result = dns_message_parse(msg_temp, buf, 0); isc_buffer_free(&buf); chase_msg->msg = msg_temp; chase_msg2 = isc_mem_allocate(mctx, sizeof(dig_message_t)); if (chase_msg2 == NULL) { fatal("Memory allocation failure in %s:%d", __FILE__, __LINE__); } ISC_LIST_INITANDAPPEND(chase_message_list2, chase_msg2, link); chase_msg2->msg = msg; } #endif } #ifdef DIG_SIGCHASE if (l->sigchase && ISC_LIST_EMPTY(lookup_list)) { sigchase(msg_temp); } #endif if (l->pending) debug("still pending."); if (l->doing_xfr) { if (query != l->xfr_q) { dns_message_destroy(&msg); isc_event_free(&event); query->waiting_connect = ISC_FALSE; UNLOCK_LOOKUP; return; } if (!docancel) docancel = check_for_more_data(query, msg, sevent); if (docancel) { dns_message_destroy(&msg); clear_query(query); cancel_lookup(l); check_next_lookup(l); } } else { if (msg->rcode == dns_rcode_noerror || l->origin == NULL) { #ifdef DIG_SIGCHASE if (!l->sigchase) #endif dighost_received(b->used, &sevent->address, query); } if (!query->lookup->ns_search_only) query->lookup->pending = ISC_FALSE; if (!query->lookup->ns_search_only || query->lookup->trace_root || docancel) { #ifdef DIG_SIGCHASE if (!do_sigchase) #endif dns_message_destroy(&msg); cancel_lookup(l); } clear_query(query); check_next_lookup(l); } if (msg != NULL) { #ifdef DIG_SIGCHASE if (do_sigchase) msg = NULL; else #endif dns_message_destroy(&msg); } isc_event_free(&event); UNLOCK_LOOKUP; return; udp_mismatch: isc_buffer_invalidate(&query->recvbuf); isc_buffer_init(&query->recvbuf, query->recvspace, COMMSIZE); ISC_LIST_ENQUEUE(query->recvlist, &query->recvbuf, link); result = isc_socket_recvv(query->sock, &query->recvlist, 1, global_task, recv_done, query); check_result(result, "isc_socket_recvv"); recvcount++; isc_event_free(&event); UNLOCK_LOOKUP; return; } /*% * Turn a name into an address, using system-supplied routines. This is * used in looking up server names, etc... and needs to use system-supplied * routines, since they may be using a non-DNS system for these lookups. */ isc_result_t get_address(char *host, in_port_t myport, isc_sockaddr_t *sockaddr) { int count; isc_result_t result; isc_boolean_t is_running; is_running = isc_app_isrunning(); if (is_running) isc_app_block(); result = bind9_getaddresses(host, myport, sockaddr, 1, &count); if (is_running) isc_app_unblock(); if (result != ISC_R_SUCCESS) return (result); INSIST(count == 1); return (ISC_R_SUCCESS); } int getaddresses(dig_lookup_t *lookup, const char *host, isc_result_t *resultp) { isc_result_t result; isc_sockaddr_t sockaddrs[DIG_MAX_ADDRESSES]; isc_netaddr_t netaddr; int count, i; dig_server_t *srv; char tmp[ISC_NETADDR_FORMATSIZE]; result = bind9_getaddresses(host, 0, sockaddrs, DIG_MAX_ADDRESSES, &count); if (resultp != NULL) *resultp = result; if (result != ISC_R_SUCCESS) { if (resultp == NULL) fatal("couldn't get address for '%s': %s", host, isc_result_totext(result)); return (0); } for (i = 0; i < count; i++) { isc_netaddr_fromsockaddr(&netaddr, &sockaddrs[i]); isc_netaddr_format(&netaddr, tmp, sizeof(tmp)); srv = make_server(tmp, host); ISC_LIST_APPEND(lookup->my_server_list, srv, link); } return (count); } /*% * Initiate either a TCP or UDP lookup */ void do_lookup(dig_lookup_t *lookup) { dig_query_t *query; REQUIRE(lookup != NULL); debug("do_lookup()"); lookup->pending = ISC_TRUE; query = ISC_LIST_HEAD(lookup->q); if (query != NULL) { if (lookup->tcp_mode) send_tcp_connect(query); else send_udp(query); } } /*% * Start everything in action upon task startup. */ void onrun_callback(isc_task_t *task, isc_event_t *event) { UNUSED(task); isc_event_free(&event); LOCK_LOOKUP; start_lookup(); UNLOCK_LOOKUP; } /*% * Make everything on the lookup queue go away. Mainly used by the * SIGINT handler. */ void cancel_all(void) { dig_lookup_t *l, *n; dig_query_t *q, *nq; debug("cancel_all()"); LOCK_LOOKUP; if (free_now) { UNLOCK_LOOKUP; return; } cancel_now = ISC_TRUE; if (current_lookup != NULL) { for (q = ISC_LIST_HEAD(current_lookup->q); q != NULL; q = nq) { nq = ISC_LIST_NEXT(q, link); debug("canceling pending query %p, belonging to %p", q, current_lookup); if (q->sock != NULL) isc_socket_cancel(q->sock, NULL, ISC_SOCKCANCEL_ALL); else clear_query(q); } for (q = ISC_LIST_HEAD(current_lookup->connecting); q != NULL; q = nq) { nq = ISC_LIST_NEXT(q, clink); debug("canceling connecting query %p, belonging to %p", q, current_lookup); if (q->sock != NULL) isc_socket_cancel(q->sock, NULL, ISC_SOCKCANCEL_ALL); else clear_query(q); } } l = ISC_LIST_HEAD(lookup_list); while (l != NULL) { n = ISC_LIST_NEXT(l, link); ISC_LIST_DEQUEUE(lookup_list, l, link); try_clear_lookup(l); l = n; } UNLOCK_LOOKUP; } /*% * Destroy all of the libs we are using, and get everything ready for a * clean shutdown. */ void destroy_libs(void) { #ifdef DIG_SIGCHASE void * ptr; dig_message_t *chase_msg; #endif #ifdef WITH_IDN isc_result_t result; #endif if (keep != NULL) isc_socket_detach(&keep); debug("destroy_libs()"); if (global_task != NULL) { debug("freeing task"); isc_task_detach(&global_task); } /* * The taskmgr_destroy() call blocks until all events are cleared * from the task. */ if (taskmgr != NULL) { debug("freeing taskmgr"); isc_taskmgr_destroy(&taskmgr); } LOCK_LOOKUP; REQUIRE(sockcount == 0); REQUIRE(recvcount == 0); REQUIRE(sendcount == 0); INSIST(ISC_LIST_HEAD(lookup_list) == NULL); INSIST(current_lookup == NULL); INSIST(!free_now); free_now = ISC_TRUE; lwres_conf_clear(lwctx); lwres_context_destroy(&lwctx); flush_server_list(); clear_searchlist(); #ifdef WITH_IDN result = dns_name_settotextfilter(NULL); check_result(result, "dns_name_settotextfilter"); #endif dns_name_destroy(); if (commctx != NULL) { debug("freeing commctx"); isc_mempool_destroy(&commctx); } if (socketmgr != NULL) { debug("freeing socketmgr"); isc_socketmgr_destroy(&socketmgr); } if (timermgr != NULL) { debug("freeing timermgr"); isc_timermgr_destroy(&timermgr); } if (key != NULL) { debug("freeing key %p", key); dns_tsigkey_detach(&key); } if (namebuf != NULL) isc_buffer_free(&namebuf); if (is_dst_up) { debug("destroy DST lib"); dst_lib_destroy(); is_dst_up = ISC_FALSE; } if (entp != NULL) { debug("detach from entropy"); isc_entropy_detach(&entp); } UNLOCK_LOOKUP; DESTROYLOCK(&lookup_lock); #ifdef DIG_SIGCHASE debug("Destroy the messages kept for sigchase"); /* Destroy the messages kept for sigchase */ chase_msg = ISC_LIST_HEAD(chase_message_list); while (chase_msg != NULL) { INSIST(chase_msg->msg != NULL); dns_message_destroy(&(chase_msg->msg)); ptr = chase_msg; chase_msg = ISC_LIST_NEXT(chase_msg, link); isc_mem_free(mctx, ptr); } chase_msg = ISC_LIST_HEAD(chase_message_list2); while (chase_msg != NULL) { INSIST(chase_msg->msg != NULL); dns_message_destroy(&(chase_msg->msg)); ptr = chase_msg; chase_msg = ISC_LIST_NEXT(chase_msg, link); isc_mem_free(mctx, ptr); } if (dns_name_dynamic(&chase_name)) free_name(&chase_name); #if DIG_SIGCHASE_TD if (dns_name_dynamic(&chase_current_name)) free_name(&chase_current_name); if (dns_name_dynamic(&chase_authority_name)) free_name(&chase_authority_name); #endif #if DIG_SIGCHASE_BU if (dns_name_dynamic(&chase_signame)) free_name(&chase_signame); #endif #endif debug("Removing log context"); isc_log_destroy(&lctx); debug("Destroy memory"); if (memdebugging != 0) isc_mem_stats(mctx, stderr); if (mctx != NULL) isc_mem_destroy(&mctx); } #ifdef WITH_IDN static void initialize_idn(void) { idn_result_t r; isc_result_t result; #ifdef HAVE_SETLOCALE /* Set locale */ (void)setlocale(LC_ALL, ""); #endif /* Create configuration context. */ r = idn_nameinit(1); if (r != idn_success) fatal("idn api initialization failed: %s", idn_result_tostring(r)); /* Set domain name -> text post-conversion filter. */ result = dns_name_settotextfilter(output_filter); check_result(result, "dns_name_settotextfilter"); } static isc_result_t output_filter(isc_buffer_t *buffer, unsigned int used_org, isc_boolean_t absolute) { char tmp1[MAXDLEN], tmp2[MAXDLEN]; size_t fromlen, tolen; isc_boolean_t end_with_dot; /* * Copy contents of 'buffer' to 'tmp1', supply trailing dot * if 'absolute' is true, and terminate with NUL. */ fromlen = isc_buffer_usedlength(buffer) - used_org; if (fromlen >= MAXDLEN) return (ISC_R_SUCCESS); memmove(tmp1, (char *)isc_buffer_base(buffer) + used_org, fromlen); end_with_dot = (tmp1[fromlen - 1] == '.') ? ISC_TRUE : ISC_FALSE; if (absolute && !end_with_dot) { fromlen++; if (fromlen >= MAXDLEN) return (ISC_R_SUCCESS); tmp1[fromlen - 1] = '.'; } tmp1[fromlen] = '\0'; /* * Convert contents of 'tmp1' to local encoding. */ if (idn_decodename(IDN_DECODE_APP, tmp1, tmp2, MAXDLEN) != idn_success) return (ISC_R_SUCCESS); strlcpy(tmp1, tmp2, MAXDLEN); /* * Copy the converted contents in 'tmp1' back to 'buffer'. * If we have appended trailing dot, remove it. */ tolen = strlen(tmp1); if (absolute && !end_with_dot && tmp1[tolen - 1] == '.') tolen--; if (isc_buffer_length(buffer) < used_org + tolen) return (ISC_R_NOSPACE); isc_buffer_subtract(buffer, isc_buffer_usedlength(buffer) - used_org); memmove(isc_buffer_used(buffer), tmp1, tolen); isc_buffer_add(buffer, (unsigned int)tolen); return (ISC_R_SUCCESS); } static idn_result_t append_textname(char *name, const char *origin, size_t namesize) { size_t namelen = strlen(name); size_t originlen = strlen(origin); /* Already absolute? */ if (namelen > 0 && name[namelen - 1] == '.') return (idn_success); /* Append dot and origin */ if (namelen + 1 + originlen >= namesize) return (idn_buffer_overflow); if (*origin != '.') name[namelen++] = '.'; (void)strlcpy(name + namelen, origin, namesize - namelen); return (idn_success); } static void idn_check_result(idn_result_t r, const char *msg) { if (r != idn_success) { exitcode = 1; fatal("%s: %s", msg, idn_result_tostring(r)); } } #endif /* WITH_IDN */ #ifdef DIG_SIGCHASE void print_type(dns_rdatatype_t type) { isc_buffer_t * b = NULL; isc_result_t result; isc_region_t r; result = isc_buffer_allocate(mctx, &b, 4000); check_result(result, "isc_buffer_allocate"); result = dns_rdatatype_totext(type, b); check_result(result, "print_type"); isc_buffer_usedregion(b, &r); r.base[r.length] = '\0'; printf("%s", r.base); isc_buffer_free(&b); } void dump_database_section(dns_message_t *msg, int section) { dns_name_t *msg_name=NULL; dns_rdataset_t *rdataset; do { dns_message_currentname(msg, section, &msg_name); for (rdataset = ISC_LIST_HEAD(msg_name->list); rdataset != NULL; rdataset = ISC_LIST_NEXT(rdataset, link)) { dns_name_print(msg_name, stdout); printf("\n"); print_rdataset(msg_name, rdataset); printf("end\n"); } msg_name = NULL; } while (dns_message_nextname(msg, section) == ISC_R_SUCCESS); } void dump_database(void) { dig_message_t * msg; for (msg = ISC_LIST_HEAD(chase_message_list); msg != NULL; msg = ISC_LIST_NEXT(msg, link)) { if (dns_message_firstname(msg->msg, DNS_SECTION_ANSWER) == ISC_R_SUCCESS) dump_database_section(msg->msg, DNS_SECTION_ANSWER); if (dns_message_firstname(msg->msg, DNS_SECTION_AUTHORITY) == ISC_R_SUCCESS) dump_database_section(msg->msg, DNS_SECTION_AUTHORITY); if (dns_message_firstname(msg->msg, DNS_SECTION_ADDITIONAL) == ISC_R_SUCCESS) dump_database_section(msg->msg, DNS_SECTION_ADDITIONAL); } } dns_rdataset_t * search_type(dns_name_t *name, dns_rdatatype_t type, dns_rdatatype_t covers) { dns_rdataset_t *rdataset; dns_rdata_sig_t siginfo; dns_rdata_t sigrdata = DNS_RDATA_INIT; isc_result_t result; for (rdataset = ISC_LIST_HEAD(name->list); rdataset != NULL; rdataset = ISC_LIST_NEXT(rdataset, link)) { if (type == dns_rdatatype_any) { if (rdataset->type != dns_rdatatype_rrsig) return (rdataset); } else if ((type == dns_rdatatype_rrsig) && (rdataset->type == dns_rdatatype_rrsig)) { result = dns_rdataset_first(rdataset); check_result(result, "empty rdataset"); dns_rdataset_current(rdataset, &sigrdata); result = dns_rdata_tostruct(&sigrdata, &siginfo, NULL); check_result(result, "sigrdata tostruct siginfo"); if ((siginfo.covered == covers) || (covers == dns_rdatatype_any)) { dns_rdata_reset(&sigrdata); dns_rdata_freestruct(&siginfo); return (rdataset); } dns_rdata_reset(&sigrdata); dns_rdata_freestruct(&siginfo); } else if (rdataset->type == type) return (rdataset); } return (NULL); } dns_rdataset_t * chase_scanname_section(dns_message_t *msg, dns_name_t *name, dns_rdatatype_t type, dns_rdatatype_t covers, int section) { dns_rdataset_t *rdataset; dns_name_t *msg_name = NULL; if (msg->counts[section] == 0) return (NULL); do { dns_message_currentname(msg, section, &msg_name); if (dns_name_compare(msg_name, name) == 0) { rdataset = search_type(msg_name, type, covers); if (rdataset != NULL) return (rdataset); } msg_name = NULL; } while (dns_message_nextname(msg, section) == ISC_R_SUCCESS); return (NULL); } dns_rdataset_t * chase_scanname(dns_name_t *name, dns_rdatatype_t type, dns_rdatatype_t covers) { dns_rdataset_t *rdataset = NULL; dig_message_t * msg; for (msg = ISC_LIST_HEAD(chase_message_list2); msg != NULL; msg = ISC_LIST_NEXT(msg, link)) { if (dns_message_firstname(msg->msg, DNS_SECTION_ANSWER) == ISC_R_SUCCESS) { rdataset = chase_scanname_section(msg->msg, name, type, covers, DNS_SECTION_ANSWER); if (rdataset != NULL) return (rdataset); } if (dns_message_firstname(msg->msg, DNS_SECTION_AUTHORITY) == ISC_R_SUCCESS) { rdataset = chase_scanname_section(msg->msg, name, type, covers, DNS_SECTION_AUTHORITY); if (rdataset != NULL) return (rdataset); } if (dns_message_firstname(msg->msg, DNS_SECTION_ADDITIONAL) == ISC_R_SUCCESS) { rdataset = chase_scanname_section(msg->msg, name, type, covers, DNS_SECTION_ADDITIONAL); if (rdataset != NULL) return (rdataset); } } return (NULL); } dns_rdataset_t * sigchase_scanname(dns_rdatatype_t type, dns_rdatatype_t covers, isc_boolean_t * lookedup, dns_name_t *rdata_name) { dig_lookup_t *lookup; isc_buffer_t *b = NULL; isc_region_t r; isc_result_t result; dns_rdataset_t * temp; dns_rdatatype_t querytype; temp = chase_scanname(rdata_name, type, covers); if (temp != NULL) return (temp); if (*lookedup == ISC_TRUE) return (NULL); lookup = clone_lookup(current_lookup, ISC_TRUE); lookup->trace_root = ISC_FALSE; lookup->new_search = ISC_TRUE; result = isc_buffer_allocate(mctx, &b, BUFSIZE); check_result(result, "isc_buffer_allocate"); result = dns_name_totext(rdata_name, ISC_FALSE, b); check_result(result, "dns_name_totext"); isc_buffer_usedregion(b, &r); r.base[r.length] = '\0'; strlcpy(lookup->textname, (char*)r.base, sizeof(lookup->textname)); isc_buffer_free(&b); if (type == dns_rdatatype_rrsig) querytype = covers; else querytype = type; if (querytype == 0 || querytype == 255) { printf("Error in the queried type: %d\n", querytype); return (NULL); } lookup->rdtype = querytype; lookup->rdtypeset = ISC_TRUE; lookup->qrdtype = querytype; *lookedup = ISC_TRUE; ISC_LIST_APPEND(lookup_list, lookup, link); printf("\n\nLaunch a query to find a RRset of type "); print_type(type); printf(" for zone: %s\n", lookup->textname); return (NULL); } isc_result_t insert_trustedkey(void *arg, dns_name_t *name, dns_rdataset_t *rdataset) { isc_result_t result; dst_key_t *dstkey; UNUSED(arg); if (rdataset == NULL || rdataset->type != dns_rdatatype_dnskey) return (ISC_R_SUCCESS); for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS; result = dns_rdataset_next(rdataset)) { dns_rdata_t rdata = DNS_RDATA_INIT; isc_buffer_t b; dns_rdataset_current(rdataset, &rdata); isc_buffer_init(&b, rdata.data, rdata.length); isc_buffer_add(&b, rdata.length); if (tk_list.nb_tk >= MAX_TRUSTED_KEY) return (ISC_R_SUCCESS); dstkey = NULL; result = dst_key_fromdns(name, rdata.rdclass, &b, mctx, &dstkey); if (result != ISC_R_SUCCESS) continue; tk_list.key[tk_list.nb_tk++] = dstkey; } return (ISC_R_SUCCESS); } void clean_trustedkey() { int i = 0; for (i= 0; i < MAX_TRUSTED_KEY; i++) { if (tk_list.key[i] != NULL) { dst_key_free(&tk_list.key[i]); tk_list.key[i] = NULL; } else break; } tk_list.nb_tk = 0; return; } char alphnum[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; isc_result_t removetmpkey(const char *file) { char *tempnamekey = NULL; int tempnamekeylen; isc_result_t result; tempnamekeylen = strlen(file)+10; tempnamekey = isc_mem_allocate(mctx, tempnamekeylen); if (tempnamekey == NULL) return (ISC_R_NOMEMORY); memset(tempnamekey, 0, tempnamekeylen); strcat(tempnamekey, file); strcat(tempnamekey,".key"); isc_file_remove(tempnamekey); result = isc_file_remove(tempnamekey); isc_mem_free(mctx, tempnamekey); return (result); } isc_result_t get_trusted_key(void) { isc_result_t result; const char *filename = NULL; dns_rdatacallbacks_t callbacks; result = isc_file_exists(trustedkey); if (result != ISC_TRUE) { result = isc_file_exists("/etc/trusted-key.key"); if (result != ISC_TRUE) { result = isc_file_exists("./trusted-key.key"); if (result != ISC_TRUE) return (ISC_R_FAILURE); else filename = "./trusted-key.key"; } else filename = "/etc/trusted-key.key"; } else filename = trustedkey; if (filename == NULL) { printf("No trusted key\n"); return (ISC_R_FAILURE); } dns_rdatacallbacks_init_stdio(&callbacks); callbacks.add = insert_trustedkey; return (dns_master_loadfile(filename, dns_rootname, dns_rootname, current_lookup->rdclass, DNS_MASTER_NOTTL, &callbacks, mctx)); } static void nameFromString(const char *str, dns_name_t *p_ret) { size_t len = strlen(str); isc_result_t result; isc_buffer_t buffer; dns_fixedname_t fixedname; REQUIRE(p_ret != NULL); REQUIRE(str != NULL); isc_buffer_constinit(&buffer, str, len); isc_buffer_add(&buffer, len); dns_fixedname_init(&fixedname); result = dns_name_fromtext(dns_fixedname_name(&fixedname), &buffer, dns_rootname, DNS_NAME_DOWNCASE, NULL); check_result(result, "nameFromString"); if (dns_name_dynamic(p_ret)) free_name(p_ret); result = dns_name_dup(dns_fixedname_name(&fixedname), mctx, p_ret); check_result(result, "nameFromString"); } #if DIG_SIGCHASE_TD isc_result_t prepare_lookup(dns_name_t *name) { isc_result_t result; dig_lookup_t *lookup = NULL; dig_server_t *s; void *ptr; lookup = clone_lookup(current_lookup, ISC_TRUE); lookup->trace_root = ISC_FALSE; lookup->new_search = ISC_TRUE; lookup->trace_root_sigchase = ISC_FALSE; strlcpy(lookup->textname, lookup->textnamesigchase, MXNAME); lookup->rdtype = lookup->rdtype_sigchase; lookup->rdtypeset = ISC_TRUE; lookup->qrdtype = lookup->qrdtype_sigchase; s = ISC_LIST_HEAD(lookup->my_server_list); while (s != NULL) { debug("freeing server %p belonging to %p", s, lookup); ptr = s; s = ISC_LIST_NEXT(s, link); ISC_LIST_DEQUEUE(lookup->my_server_list, (dig_server_t *)ptr, link); isc_mem_free(mctx, ptr); } for (result = dns_rdataset_first(chase_nsrdataset); result == ISC_R_SUCCESS; result = dns_rdataset_next(chase_nsrdataset)) { char namestr[DNS_NAME_FORMATSIZE]; dns_rdata_ns_t ns; dns_rdata_t rdata = DNS_RDATA_INIT; dig_server_t * srv = NULL; #define __FOLLOW_GLUE__ #ifdef __FOLLOW_GLUE__ isc_buffer_t *b = NULL; isc_region_t r; dns_rdataset_t *rdataset = NULL; isc_boolean_t true = ISC_TRUE; #endif memset(namestr, 0, DNS_NAME_FORMATSIZE); dns_rdataset_current(chase_nsrdataset, &rdata); result = dns_rdata_tostruct(&rdata, &ns, NULL); check_result(result, "dns_rdata_tostruct"); #ifdef __FOLLOW_GLUE__ result = advanced_rrsearch(&rdataset, &ns.name, dns_rdatatype_aaaa, dns_rdatatype_any, &true); if (result == ISC_R_SUCCESS) { for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS; result = dns_rdataset_next(rdataset)) { dns_rdata_t aaaa = DNS_RDATA_INIT; dns_rdataset_current(rdataset, &aaaa); result = isc_buffer_allocate(mctx, &b, 80); check_result(result, "isc_buffer_allocate"); dns_rdata_totext(&aaaa, &ns.name, b); isc_buffer_usedregion(b, &r); r.base[r.length] = '\0'; strlcpy(namestr, (char*)r.base, DNS_NAME_FORMATSIZE); isc_buffer_free(&b); dns_rdata_reset(&aaaa); srv = make_server(namestr, namestr); ISC_LIST_APPEND(lookup->my_server_list, srv, link); } } rdataset = NULL; result = advanced_rrsearch(&rdataset, &ns.name, dns_rdatatype_a, dns_rdatatype_any, &true); if (result == ISC_R_SUCCESS) { for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS; result = dns_rdataset_next(rdataset)) { dns_rdata_t a = DNS_RDATA_INIT; dns_rdataset_current(rdataset, &a); result = isc_buffer_allocate(mctx, &b, 80); check_result(result, "isc_buffer_allocate"); dns_rdata_totext(&a, &ns.name, b); isc_buffer_usedregion(b, &r); r.base[r.length] = '\0'; strlcpy(namestr, (char*)r.base, DNS_NAME_FORMATSIZE); isc_buffer_free(&b); dns_rdata_reset(&a); printf("ns name: %s\n", namestr); srv = make_server(namestr, namestr); ISC_LIST_APPEND(lookup->my_server_list, srv, link); } } #else dns_name_format(&ns.name, namestr, sizeof(namestr)); printf("ns name: "); dns_name_print(&ns.name, stdout); printf("\n"); srv = make_server(namestr, namestr); ISC_LIST_APPEND(lookup->my_server_list, srv, link); #endif dns_rdata_freestruct(&ns); dns_rdata_reset(&rdata); } ISC_LIST_APPEND(lookup_list, lookup, link); printf("\nLaunch a query to find a RRset of type "); print_type(lookup->rdtype); printf(" for zone: %s", lookup->textname); printf(" with nameservers:"); printf("\n"); print_rdataset(name, chase_nsrdataset); return (ISC_R_SUCCESS); } isc_result_t child_of_zone(dns_name_t * name, dns_name_t * zone_name, dns_name_t * child_name) { dns_namereln_t name_reln; int orderp; unsigned int nlabelsp; name_reln = dns_name_fullcompare(name, zone_name, &orderp, &nlabelsp); if (name_reln != dns_namereln_subdomain || dns_name_countlabels(name) <= dns_name_countlabels(zone_name) + 1) { printf("\n;; ERROR : "); dns_name_print(name, stdout); printf(" is not a subdomain of: "); dns_name_print(zone_name, stdout); printf(" FAILED\n\n"); return (ISC_R_FAILURE); } dns_name_getlabelsequence(name, dns_name_countlabels(name) - dns_name_countlabels(zone_name) -1, dns_name_countlabels(zone_name) +1, child_name); return (ISC_R_SUCCESS); } isc_result_t grandfather_pb_test(dns_name_t *zone_name, dns_rdataset_t *sigrdataset) { dns_rdata_sig_t siginfo; dns_rdataset_t mysigrdataset; isc_result_t result; dns_rdataset_init(&mysigrdataset); dns_rdataset_clone(sigrdataset, &mysigrdataset); result = dns_rdataset_first(&mysigrdataset); check_result(result, "empty RRSIG dataset"); do { dns_rdata_t sigrdata = DNS_RDATA_INIT; dns_rdataset_current(&mysigrdataset, &sigrdata); result = dns_rdata_tostruct(&sigrdata, &siginfo, NULL); check_result(result, "sigrdata tostruct siginfo"); if (dns_name_compare(&siginfo.signer, zone_name) == 0) { result = ISC_R_SUCCESS; goto cleanup; } } while (dns_rdataset_next(&mysigrdataset) == ISC_R_SUCCESS); result = ISC_R_FAILURE; cleanup: dns_rdataset_disassociate(&mysigrdataset); return (result); } isc_result_t initialization(dns_name_t *name) { isc_result_t result; isc_boolean_t true = ISC_TRUE; chase_nsrdataset = NULL; result = advanced_rrsearch(&chase_nsrdataset, name, dns_rdatatype_ns, dns_rdatatype_any, &true); if (result != ISC_R_SUCCESS) { printf("\n;; NS RRset is missing to continue validation:" " FAILED\n\n"); return (ISC_R_FAILURE); } INSIST(chase_nsrdataset != NULL); prepare_lookup(name); dup_name(name, &chase_current_name); return (ISC_R_SUCCESS); } #endif void print_rdataset(dns_name_t *name, dns_rdataset_t *rdataset) { isc_buffer_t *b = NULL; isc_result_t result; isc_region_t r; result = isc_buffer_allocate(mctx, &b, 9000); check_result(result, "isc_buffer_allocate"); dighost_printrdataset(name, rdataset, b); isc_buffer_usedregion(b, &r); r.base[r.length] = '\0'; printf("%s\n", r.base); isc_buffer_free(&b); } void dup_name(dns_name_t *source, dns_name_t *target) { isc_result_t result; if (dns_name_dynamic(target)) free_name(target); result = dns_name_dup(source, mctx, target); check_result(result, "dns_name_dup"); } void free_name(dns_name_t *name) { dns_name_free(name, mctx); dns_name_init(name, NULL); } /* * * take a DNSKEY RRset and the RRSIG RRset corresponding in parameter * return ISC_R_SUCCESS if the DNSKEY RRset contains a trusted_key * and the RRset is valid * return ISC_R_NOTFOUND if not contains trusted key or if the RRset isn't valid * return ISC_R_FAILURE if problem * */ isc_result_t contains_trusted_key(dns_name_t *name, dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) { dns_rdataset_t myrdataset; dst_key_t *dnsseckey = NULL; int i; isc_result_t result; if (name == NULL || rdataset == NULL) return (ISC_R_FAILURE); dns_rdataset_init(&myrdataset); dns_rdataset_clone(rdataset, &myrdataset); result = dns_rdataset_first(&myrdataset); check_result(result, "empty rdataset"); do { dns_rdata_t rdata = DNS_RDATA_INIT; dns_rdataset_current(&myrdataset, &rdata); INSIST(rdata.type == dns_rdatatype_dnskey); result = dns_dnssec_keyfromrdata(name, &rdata, mctx, &dnsseckey); check_result(result, "dns_dnssec_keyfromrdata"); for (i = 0; i < tk_list.nb_tk; i++) { if (dst_key_compare(tk_list.key[i], dnsseckey) == ISC_TRUE) { dns_rdata_reset(&rdata); printf(";; Ok, find a Trusted Key in the " "DNSKEY RRset: %d\n", dst_key_id(dnsseckey)); result = sigchase_verify_sig_key(name, rdataset, dnsseckey, sigrdataset); if (result == ISC_R_SUCCESS) goto cleanup; } } dst_key_free(&dnsseckey); } while (dns_rdataset_next(&myrdataset) == ISC_R_SUCCESS); result = ISC_R_NOTFOUND; cleanup: if (dnsseckey != NULL) dst_key_free(&dnsseckey); dns_rdataset_disassociate(&myrdataset); return (result); } isc_result_t sigchase_verify_sig(dns_name_t *name, dns_rdataset_t *rdataset, dns_rdataset_t *keyrdataset, dns_rdataset_t *sigrdataset) { dns_rdataset_t mykeyrdataset; dst_key_t *dnsseckey = NULL; isc_result_t result; dns_rdataset_init(&mykeyrdataset); dns_rdataset_clone(keyrdataset, &mykeyrdataset); result = dns_rdataset_first(&mykeyrdataset); check_result(result, "empty DNSKEY dataset"); do { dns_rdata_t keyrdata = DNS_RDATA_INIT; dns_rdataset_current(&mykeyrdataset, &keyrdata); INSIST(keyrdata.type == dns_rdatatype_dnskey); result = dns_dnssec_keyfromrdata(name, &keyrdata, mctx, &dnsseckey); check_result(result, "dns_dnssec_keyfromrdata"); result = sigchase_verify_sig_key(name, rdataset, dnsseckey, sigrdataset); if (result == ISC_R_SUCCESS) goto cleanup; dst_key_free(&dnsseckey); } while (dns_rdataset_next(&mykeyrdataset) == ISC_R_SUCCESS); result = ISC_R_NOTFOUND; cleanup: if (dnsseckey != NULL) dst_key_free(&dnsseckey); dns_rdataset_disassociate(&mykeyrdataset); return (result); } isc_result_t sigchase_verify_sig_key(dns_name_t *name, dns_rdataset_t *rdataset, dst_key_t *dnsseckey, dns_rdataset_t *sigrdataset) { dns_rdata_sig_t siginfo; dns_rdataset_t myrdataset; dns_rdataset_t mysigrdataset; isc_result_t result; dns_rdataset_init(&myrdataset); dns_rdataset_clone(rdataset, &myrdataset); dns_rdataset_init(&mysigrdataset); dns_rdataset_clone(sigrdataset, &mysigrdataset); result = dns_rdataset_first(&mysigrdataset); check_result(result, "empty RRSIG dataset"); do { dns_rdata_t sigrdata = DNS_RDATA_INIT; dns_rdataset_current(&mysigrdataset, &sigrdata); result = dns_rdata_tostruct(&sigrdata, &siginfo, NULL); check_result(result, "sigrdata tostruct siginfo"); /* * Test if the id of the DNSKEY is * the id of the DNSKEY signer's */ if (siginfo.keyid == dst_key_id(dnsseckey)) { result = dns_rdataset_first(&myrdataset); check_result(result, "empty DS dataset"); result = dns_dnssec_verify(name, &myrdataset, dnsseckey, ISC_FALSE, mctx, &sigrdata); printf(";; VERIFYING "); print_type(rdataset->type); printf(" RRset for "); dns_name_print(name, stdout); printf(" with DNSKEY:%d: %s\n", dst_key_id(dnsseckey), isc_result_totext(result)); if (result == ISC_R_SUCCESS) goto cleanup; } } while (dns_rdataset_next(&mysigrdataset) == ISC_R_SUCCESS); result = ISC_R_NOTFOUND; cleanup: dns_rdataset_disassociate(&myrdataset); dns_rdataset_disassociate(&mysigrdataset); return (result); } isc_result_t sigchase_verify_ds(dns_name_t *name, dns_rdataset_t *keyrdataset, dns_rdataset_t *dsrdataset) { dns_rdata_ds_t dsinfo; dns_rdataset_t mydsrdataset; dns_rdataset_t mykeyrdataset; dst_key_t *dnsseckey = NULL; isc_result_t result; unsigned char dsbuf[DNS_DS_BUFFERSIZE]; dns_rdataset_init(&mydsrdataset); dns_rdataset_clone(dsrdataset, &mydsrdataset); dns_rdataset_init(&mykeyrdataset); dns_rdataset_clone(keyrdataset, &mykeyrdataset); result = dns_rdataset_first(&mydsrdataset); check_result(result, "empty DSset dataset"); do { dns_rdata_t dsrdata = DNS_RDATA_INIT; dns_rdataset_current(&mydsrdataset, &dsrdata); result = dns_rdata_tostruct(&dsrdata, &dsinfo, NULL); check_result(result, "dns_rdata_tostruct for DS"); result = dns_rdataset_first(&mykeyrdataset); check_result(result, "empty KEY dataset"); do { dns_rdata_t keyrdata = DNS_RDATA_INIT; dns_rdataset_current(&mykeyrdataset, &keyrdata); INSIST(keyrdata.type == dns_rdatatype_dnskey); result = dns_dnssec_keyfromrdata(name, &keyrdata, mctx, &dnsseckey); check_result(result, "dns_dnssec_keyfromrdata"); /* * Test if the id of the DNSKEY is the * id of DNSKEY referenced by the DS */ if (dsinfo.key_tag == dst_key_id(dnsseckey)) { dns_rdata_t newdsrdata = DNS_RDATA_INIT; result = dns_ds_buildrdata(name, &keyrdata, dsinfo.digest_type, dsbuf, &newdsrdata); dns_rdata_freestruct(&dsinfo); if (result != ISC_R_SUCCESS) { printf("Oops: impossible to build" " new DS rdata\n"); goto cleanup; } if (dns_rdata_compare(&dsrdata, &newdsrdata) == 0) { printf(";; OK a DS valids a DNSKEY" " in the RRset\n"); printf(";; Now verify that this" " DNSKEY validates the " "DNSKEY RRset\n"); result = sigchase_verify_sig_key(name, keyrdataset, dnsseckey, chase_sigkeyrdataset); if (result == ISC_R_SUCCESS) goto cleanup; } else { printf(";; This DS is NOT the DS for" " the chasing KEY: FAILED\n"); } } dst_key_free(&dnsseckey); } while (dns_rdataset_next(&mykeyrdataset) == ISC_R_SUCCESS); } while (dns_rdataset_next(&mydsrdataset) == ISC_R_SUCCESS); result = ISC_R_NOTFOUND; cleanup: if (dnsseckey != NULL) dst_key_free(&dnsseckey); dns_rdataset_disassociate(&mydsrdataset); dns_rdataset_disassociate(&mykeyrdataset); return (result); } /* * * take a pointer on a rdataset in parameter and try to resolv it. * the searched rrset is a rrset on 'name' with type 'type' * (and if the type is a rrsig the signature cover 'covers'). * the lookedup is to known if you have already done the query on the net. * ISC_R_SUCCESS: if we found the rrset * ISC_R_NOTFOUND: we do not found the rrset in cache * and we do a query on the net * ISC_R_FAILURE: rrset not found */ isc_result_t advanced_rrsearch(dns_rdataset_t **rdataset, dns_name_t *name, dns_rdatatype_t type, dns_rdatatype_t covers, isc_boolean_t *lookedup) { isc_boolean_t tmplookedup; INSIST(rdataset != NULL); if (*rdataset != NULL) return (ISC_R_SUCCESS); tmplookedup = *lookedup; if ((*rdataset = sigchase_scanname(type, covers, lookedup, name)) == NULL) { if (tmplookedup) return (ISC_R_FAILURE); return (ISC_R_NOTFOUND); } *lookedup = ISC_FALSE; return (ISC_R_SUCCESS); } #if DIG_SIGCHASE_TD void sigchase_td(dns_message_t *msg) { isc_result_t result; dns_name_t *name = NULL; isc_boolean_t have_answer = ISC_FALSE; isc_boolean_t true = ISC_TRUE; if (msg->rcode != dns_rcode_noerror && msg->rcode != dns_rcode_nxdomain) { char buf[20]; isc_buffer_t b; isc_buffer_init(&b, buf, sizeof(buf)); result = dns_rcode_totext(msg->rcode, &b); check_result(result, "dns_rcode_totext failed"); printf("error response code %.*s\n", (int)isc_buffer_usedlength(&b), buf); error_message = msg; return; } if ((result = dns_message_firstname(msg, DNS_SECTION_ANSWER)) == ISC_R_SUCCESS) { dns_message_currentname(msg, DNS_SECTION_ANSWER, &name); if (current_lookup->trace_root_sigchase) { initialization(name); return; } have_answer = true; } else { if (!current_lookup->trace_root_sigchase) { result = dns_message_firstname(msg, DNS_SECTION_AUTHORITY); if (result != ISC_R_SUCCESS) { printf("no answer or authority section\n"); error_message = msg; return; } dns_message_currentname(msg, DNS_SECTION_AUTHORITY, &name); chase_nsrdataset = chase_scanname_section(msg, name, dns_rdatatype_ns, dns_rdatatype_any, DNS_SECTION_AUTHORITY); dup_name(name, &chase_authority_name); if (chase_nsrdataset != NULL) { have_delegation_ns = ISC_TRUE; printf("no response but there is a delegation" " in authority section: "); dns_name_print(name, stdout); printf("\n"); } else { printf("no response and no delegation in " "authority section but a reference" " to: "); dns_name_print(name, stdout); printf("\n"); error_message = msg; } } else { printf(";; NO ANSWERS: %s\n", isc_result_totext(result)); free_name(&chase_name); clean_trustedkey(); return; } } if (have_answer) { chase_rdataset = chase_scanname_section(msg, &chase_name, current_lookup ->rdtype_sigchase, dns_rdatatype_any, DNS_SECTION_ANSWER); if (chase_rdataset != NULL) have_response = ISC_TRUE; } result = advanced_rrsearch(&chase_keyrdataset, &chase_current_name, dns_rdatatype_dnskey, dns_rdatatype_any, &chase_keylookedup); if (result == ISC_R_FAILURE) { printf("\n;; DNSKEY is missing to continue validation:" " FAILED\n\n"); goto cleanandgo; } if (result == ISC_R_NOTFOUND) return; INSIST(chase_keyrdataset != NULL); printf("\n;; DNSKEYset:\n"); print_rdataset(&chase_current_name , chase_keyrdataset); result = advanced_rrsearch(&chase_sigkeyrdataset, &chase_current_name, dns_rdatatype_rrsig, dns_rdatatype_dnskey, &chase_sigkeylookedup); if (result == ISC_R_FAILURE) { printf("\n;; RRSIG of DNSKEY is missing to continue validation:" " FAILED\n\n"); goto cleanandgo; } if (result == ISC_R_NOTFOUND) return; INSIST(chase_sigkeyrdataset != NULL); printf("\n;; RRSIG of the DNSKEYset:\n"); print_rdataset(&chase_current_name , chase_sigkeyrdataset); if (!chase_dslookedup && !chase_nslookedup) { if (!delegation_follow) { result = contains_trusted_key(&chase_current_name, chase_keyrdataset, chase_sigkeyrdataset); } else { INSIST(chase_dsrdataset != NULL); INSIST(chase_sigdsrdataset != NULL); result = sigchase_verify_ds(&chase_current_name, chase_keyrdataset, chase_dsrdataset); } if (result != ISC_R_SUCCESS) { printf("\n;; chain of trust can't be validated:" " FAILED\n\n"); goto cleanandgo; } else { chase_dsrdataset = NULL; chase_sigdsrdataset = NULL; } } if (have_response || (!have_delegation_ns && !have_response)) { /* test if it's a grand father case */ if (have_response) { result = advanced_rrsearch(&chase_sigrdataset, &chase_name, dns_rdatatype_rrsig, current_lookup ->rdtype_sigchase, &true); if (result == ISC_R_FAILURE) { printf("\n;; RRset is missing to continue" " validation SHOULD NOT APPEND:" " FAILED\n\n"); goto cleanandgo; } } else { result = advanced_rrsearch(&chase_sigrdataset, &chase_authority_name, dns_rdatatype_rrsig, dns_rdatatype_any, &true); if (result == ISC_R_FAILURE) { printf("\n;; RRSIG is missing to continue" " validation SHOULD NOT APPEND:" " FAILED\n\n"); goto cleanandgo; } } result = grandfather_pb_test(&chase_current_name, chase_sigrdataset); if (result != ISC_R_SUCCESS) { dns_name_t tmp_name; printf("\n;; We are in a Grand Father Problem:" " See 2.2.1 in RFC 3658\n"); chase_rdataset = NULL; chase_sigrdataset = NULL; have_response = ISC_FALSE; have_delegation_ns = ISC_FALSE; dns_name_init(&tmp_name, NULL); result = child_of_zone(&chase_name, &chase_current_name, &tmp_name); if (dns_name_dynamic(&chase_authority_name)) free_name(&chase_authority_name); dup_name(&tmp_name, &chase_authority_name); printf(";; and we try to continue chain of trust" " validation of the zone: "); dns_name_print(&chase_authority_name, stdout); printf("\n"); have_delegation_ns = ISC_TRUE; } else { if (have_response) goto finalstep; else chase_sigrdataset = NULL; } } if (have_delegation_ns) { chase_nsrdataset = NULL; result = advanced_rrsearch(&chase_nsrdataset, &chase_authority_name, dns_rdatatype_ns, dns_rdatatype_any, &chase_nslookedup); if (result == ISC_R_FAILURE) { printf("\n;;NSset is missing to continue validation:" " FAILED\n\n"); goto cleanandgo; } if (result == ISC_R_NOTFOUND) { return; } INSIST(chase_nsrdataset != NULL); result = advanced_rrsearch(&chase_dsrdataset, &chase_authority_name, dns_rdatatype_ds, dns_rdatatype_any, &chase_dslookedup); if (result == ISC_R_FAILURE) { printf("\n;; DSset is missing to continue validation:" " FAILED\n\n"); goto cleanandgo; } if (result == ISC_R_NOTFOUND) return; INSIST(chase_dsrdataset != NULL); printf("\n;; DSset:\n"); print_rdataset(&chase_authority_name , chase_dsrdataset); result = advanced_rrsearch(&chase_sigdsrdataset, &chase_authority_name, dns_rdatatype_rrsig, dns_rdatatype_ds, &true); if (result != ISC_R_SUCCESS) { printf("\n;; DSset is missing to continue validation:" " FAILED\n\n"); goto cleanandgo; } printf("\n;; RRSIGset of DSset\n"); print_rdataset(&chase_authority_name, chase_sigdsrdataset); INSIST(chase_sigdsrdataset != NULL); result = sigchase_verify_sig(&chase_authority_name, chase_dsrdataset, chase_keyrdataset, chase_sigdsrdataset); if (result != ISC_R_SUCCESS) { printf("\n;; Impossible to verify the DSset:" " FAILED\n\n"); goto cleanandgo; } chase_keyrdataset = NULL; chase_sigkeyrdataset = NULL; prepare_lookup(&chase_authority_name); have_response = ISC_FALSE; have_delegation_ns = ISC_FALSE; delegation_follow = ISC_TRUE; error_message = NULL; dup_name(&chase_authority_name, &chase_current_name); free_name(&chase_authority_name); return; } if (error_message != NULL) { dns_rdataset_t *rdataset; dns_rdataset_t *sigrdataset; dns_name_t rdata_name; isc_result_t ret = ISC_R_FAILURE; dns_name_init(&rdata_name, NULL); result = prove_nx(error_message, &chase_name, current_lookup->rdclass_sigchase, current_lookup->rdtype_sigchase, &rdata_name, &rdataset, &sigrdataset); if (rdataset == NULL || sigrdataset == NULL || dns_name_countlabels(&rdata_name) == 0) { printf("\n;; Impossible to verify the non-existence," " the NSEC RRset can't be validated:" " FAILED\n\n"); goto cleanandgo; } ret = sigchase_verify_sig(&rdata_name, rdataset, chase_keyrdataset, sigrdataset); if (ret != ISC_R_SUCCESS) { free_name(&rdata_name); printf("\n;; Impossible to verify the NSEC RR to prove" " the non-existence : FAILED\n\n"); goto cleanandgo; } free_name(&rdata_name); if (result != ISC_R_SUCCESS) { printf("\n;; Impossible to verify the non-existence:" " FAILED\n\n"); goto cleanandgo; } else { printf("\n;; OK the query doesn't have response but" " we have validate this fact : SUCCESS\n\n"); goto cleanandgo; } } cleanandgo: printf(";; cleanandgo \n"); if (dns_name_dynamic(&chase_current_name)) free_name(&chase_current_name); if (dns_name_dynamic(&chase_authority_name)) free_name(&chase_authority_name); clean_trustedkey(); return; finalstep : result = advanced_rrsearch(&chase_rdataset, &chase_name, current_lookup->rdtype_sigchase, dns_rdatatype_any , &true); if (result == ISC_R_FAILURE) { printf("\n;; RRsig of RRset is missing to continue validation" " SHOULD NOT APPEND: FAILED\n\n"); goto cleanandgo; } result = sigchase_verify_sig(&chase_name, chase_rdataset, chase_keyrdataset, chase_sigrdataset); if (result != ISC_R_SUCCESS) { printf("\n;; Impossible to verify the RRset : FAILED\n\n"); /* printf("RRset:\n"); print_rdataset(&chase_name , chase_rdataset); printf("DNSKEYset:\n"); print_rdataset(&chase_name , chase_keyrdataset); printf("RRSIG of RRset:\n"); print_rdataset(&chase_name , chase_sigrdataset); printf("\n"); */ goto cleanandgo; } else { printf("\n;; The Answer:\n"); print_rdataset(&chase_name , chase_rdataset); printf("\n;; FINISH : we have validate the DNSSEC chain" " of trust: SUCCESS\n\n"); goto cleanandgo; } } #endif #if DIG_SIGCHASE_BU isc_result_t getneededrr(dns_message_t *msg) { isc_result_t result; dns_name_t *name = NULL; dns_rdata_t sigrdata = DNS_RDATA_INIT; dns_rdata_sig_t siginfo; isc_boolean_t true = ISC_TRUE; if ((result = dns_message_firstname(msg, DNS_SECTION_ANSWER)) != ISC_R_SUCCESS) { printf(";; NO ANSWERS: %s\n", isc_result_totext(result)); if (chase_name.ndata == NULL) return (ISC_R_ADDRNOTAVAIL); } else { dns_message_currentname(msg, DNS_SECTION_ANSWER, &name); } /* What do we chase? */ if (chase_rdataset == NULL) { result = advanced_rrsearch(&chase_rdataset, name, dns_rdatatype_any, dns_rdatatype_any, &true); if (result != ISC_R_SUCCESS) { printf("\n;; No Answers: Validation FAILED\n\n"); return (ISC_R_NOTFOUND); } dup_name(name, &chase_name); printf(";; RRset to chase:\n"); print_rdataset(&chase_name, chase_rdataset); } INSIST(chase_rdataset != NULL); if (chase_sigrdataset == NULL) { result = advanced_rrsearch(&chase_sigrdataset, name, dns_rdatatype_rrsig, chase_rdataset->type, &chase_siglookedup); if (result == ISC_R_FAILURE) { printf("\n;; RRSIG is missing for continue validation:" " FAILED\n\n"); if (dns_name_dynamic(&chase_name)) free_name(&chase_name); return (ISC_R_NOTFOUND); } if (result == ISC_R_NOTFOUND) { return (ISC_R_NOTFOUND); } printf("\n;; RRSIG of the RRset to chase:\n"); print_rdataset(&chase_name, chase_sigrdataset); } INSIST(chase_sigrdataset != NULL); /* first find the DNSKEY name */ result = dns_rdataset_first(chase_sigrdataset); check_result(result, "empty RRSIG dataset"); dns_rdataset_current(chase_sigrdataset, &sigrdata); result = dns_rdata_tostruct(&sigrdata, &siginfo, NULL); check_result(result, "sigrdata tostruct siginfo"); dup_name(&siginfo.signer, &chase_signame); dns_rdata_freestruct(&siginfo); dns_rdata_reset(&sigrdata); /* Do we have a key? */ if (chase_keyrdataset == NULL) { result = advanced_rrsearch(&chase_keyrdataset, &chase_signame, dns_rdatatype_dnskey, dns_rdatatype_any, &chase_keylookedup); if (result == ISC_R_FAILURE) { printf("\n;; DNSKEY is missing to continue validation:" " FAILED\n\n"); free_name(&chase_signame); if (dns_name_dynamic(&chase_name)) free_name(&chase_name); return (ISC_R_NOTFOUND); } if (result == ISC_R_NOTFOUND) { free_name(&chase_signame); return (ISC_R_NOTFOUND); } printf("\n;; DNSKEYset that signs the RRset to chase:\n"); print_rdataset(&chase_signame, chase_keyrdataset); } INSIST(chase_keyrdataset != NULL); if (chase_sigkeyrdataset == NULL) { result = advanced_rrsearch(&chase_sigkeyrdataset, &chase_signame, dns_rdatatype_rrsig, dns_rdatatype_dnskey, &chase_sigkeylookedup); if (result == ISC_R_FAILURE) { printf("\n;; RRSIG for DNSKEY is missing to continue" " validation : FAILED\n\n"); free_name(&chase_signame); if (dns_name_dynamic(&chase_name)) free_name(&chase_name); return (ISC_R_NOTFOUND); } if (result == ISC_R_NOTFOUND) { free_name(&chase_signame); return (ISC_R_NOTFOUND); } printf("\n;; RRSIG of the DNSKEYset that signs the " "RRset to chase:\n"); print_rdataset(&chase_signame, chase_sigkeyrdataset); } INSIST(chase_sigkeyrdataset != NULL); if (chase_dsrdataset == NULL) { result = advanced_rrsearch(&chase_dsrdataset, &chase_signame, dns_rdatatype_ds, dns_rdatatype_any, &chase_dslookedup); if (result == ISC_R_FAILURE) { printf("\n;; WARNING There is no DS for the zone: "); dns_name_print(&chase_signame, stdout); printf("\n"); } if (result == ISC_R_NOTFOUND) { free_name(&chase_signame); return (ISC_R_NOTFOUND); } if (chase_dsrdataset != NULL) { printf("\n;; DSset of the DNSKEYset\n"); print_rdataset(&chase_signame, chase_dsrdataset); } } if (chase_dsrdataset != NULL) { /* * if there is no RRSIG of DS, * we don't want to search on the network */ result = advanced_rrsearch(&chase_sigdsrdataset, &chase_signame, dns_rdatatype_rrsig, dns_rdatatype_ds, &true); if (result == ISC_R_FAILURE) { printf(";; WARNING : NO RRSIG DS : RRSIG DS" " should come with DS\n"); /* * We continue even the DS couldn't be validated, * because the DNSKEY could be a Trusted Key. */ chase_dsrdataset = NULL; } else { printf("\n;; RRSIG of the DSset of the DNSKEYset\n"); print_rdataset(&chase_signame, chase_sigdsrdataset); } } return (1); } void sigchase_bu(dns_message_t *msg) { isc_result_t result; int ret; if (tk_list.nb_tk == 0) { result = get_trusted_key(); if (result != ISC_R_SUCCESS) { printf("No trusted keys present\n"); return; } } ret = getneededrr(msg); if (ret == ISC_R_NOTFOUND) return; if (ret == ISC_R_ADDRNOTAVAIL) { /* We have no response */ dns_rdataset_t *rdataset; dns_rdataset_t *sigrdataset; dns_name_t rdata_name; dns_name_t query_name; dns_name_init(&query_name, NULL); dns_name_init(&rdata_name, NULL); nameFromString(current_lookup->textname, &query_name); result = prove_nx(msg, &query_name, current_lookup->rdclass, current_lookup->rdtype, &rdata_name, &rdataset, &sigrdataset); free_name(&query_name); if (rdataset == NULL || sigrdataset == NULL || dns_name_countlabels(&rdata_name) == 0) { printf("\n;; Impossible to verify the Non-existence," " the NSEC RRset can't be validated: " "FAILED\n\n"); clean_trustedkey(); return; } if (result != ISC_R_SUCCESS) { printf("\n No Answers and impossible to prove the" " unsecurity : Validation FAILED\n\n"); clean_trustedkey(); return; } printf(";; An NSEC prove the non-existence of a answers," " Now we want validate this NSEC\n"); dup_name(&rdata_name, &chase_name); free_name(&rdata_name); chase_rdataset = rdataset; chase_sigrdataset = sigrdataset; chase_keyrdataset = NULL; chase_sigkeyrdataset = NULL; chase_dsrdataset = NULL; chase_sigdsrdataset = NULL; chase_siglookedup = ISC_FALSE; chase_keylookedup = ISC_FALSE; chase_dslookedup = ISC_FALSE; chase_sigdslookedup = ISC_FALSE; sigchase(msg); clean_trustedkey(); return; } printf("\n\n\n;; WE HAVE MATERIAL, WE NOW DO VALIDATION\n"); result = sigchase_verify_sig(&chase_name, chase_rdataset, chase_keyrdataset, chase_sigrdataset); if (result != ISC_R_SUCCESS) { free_name(&chase_name); free_name(&chase_signame); printf(";; No DNSKEY is valid to check the RRSIG" " of the RRset: FAILED\n"); clean_trustedkey(); return; } printf(";; OK We found DNSKEY (or more) to validate the RRset\n"); result = contains_trusted_key(&chase_signame, chase_keyrdataset, chase_sigkeyrdataset); if (result == ISC_R_SUCCESS) { free_name(&chase_name); free_name(&chase_signame); printf("\n;; Ok this DNSKEY is a Trusted Key," " DNSSEC validation is ok: SUCCESS\n\n"); clean_trustedkey(); return; } printf(";; Now, we are going to validate this DNSKEY by the DS\n"); if (chase_dsrdataset == NULL) { free_name(&chase_name); free_name(&chase_signame); printf(";; the DNSKEY isn't trusted-key and there isn't" " DS to validate the DNSKEY: FAILED\n"); clean_trustedkey(); return; } result = sigchase_verify_ds(&chase_signame, chase_keyrdataset, chase_dsrdataset); if (result != ISC_R_SUCCESS) { free_name(&chase_signame); free_name(&chase_name); printf(";; ERROR no DS validates a DNSKEY in the" " DNSKEY RRset: FAILED\n"); clean_trustedkey(); return; } else printf(";; OK this DNSKEY (validated by the DS) validates" " the RRset of the DNSKEYs, thus the DNSKEY validates" " the RRset\n"); INSIST(chase_sigdsrdataset != NULL); dup_name(&chase_signame, &chase_name); free_name(&chase_signame); chase_rdataset = chase_dsrdataset; chase_sigrdataset = chase_sigdsrdataset; chase_keyrdataset = NULL; chase_sigkeyrdataset = NULL; chase_dsrdataset = NULL; chase_sigdsrdataset = NULL; chase_siglookedup = chase_keylookedup = ISC_FALSE; chase_dslookedup = chase_sigdslookedup = ISC_FALSE; printf(";; Now, we want to validate the DS : recursive call\n"); sigchase(msg); return; } #endif void sigchase(dns_message_t *msg) { #if DIG_SIGCHASE_TD if (current_lookup->do_topdown) { sigchase_td(msg); return; } #endif #if DIG_SIGCHASE_BU sigchase_bu(msg); return; #endif } /* * return 1 if name1 < name2 * 0 if name1 == name2 * -1 if name1 > name2 * and -2 if problem */ int inf_name(dns_name_t *name1, dns_name_t *name2) { dns_label_t label1; dns_label_t label2; unsigned int nblabel1; unsigned int nblabel2; int min_lum_label; int i; int ret = -2; nblabel1 = dns_name_countlabels(name1); nblabel2 = dns_name_countlabels(name2); if (nblabel1 >= nblabel2) min_lum_label = nblabel2; else min_lum_label = nblabel1; for (i=1 ; i < min_lum_label; i++) { dns_name_getlabel(name1, nblabel1 -1 - i, &label1); dns_name_getlabel(name2, nblabel2 -1 - i, &label2); if ((ret = isc_region_compare(&label1, &label2)) != 0) { if (ret < 0) return (-1); else if (ret > 0) return (1); } } if (nblabel1 == nblabel2) return (0); if (nblabel1 < nblabel2) return (-1); else return (1); } /** * * * */ isc_result_t prove_nx_domain(dns_message_t *msg, dns_name_t *name, dns_name_t *rdata_name, dns_rdataset_t **rdataset, dns_rdataset_t **sigrdataset) { isc_result_t ret = ISC_R_FAILURE; isc_result_t result = ISC_R_NOTFOUND; dns_rdataset_t *nsecset = NULL; dns_rdataset_t *signsecset = NULL ; dns_rdata_t nsec = DNS_RDATA_INIT; dns_name_t *nsecname; dns_rdata_nsec_t nsecstruct; if ((result = dns_message_firstname(msg, DNS_SECTION_AUTHORITY)) != ISC_R_SUCCESS) { printf(";; nothing in authority section : impossible to" " validate the non-existence : FAILED\n"); return (ISC_R_FAILURE); } do { nsecname = NULL; dns_message_currentname(msg, DNS_SECTION_AUTHORITY, &nsecname); nsecset = search_type(nsecname, dns_rdatatype_nsec, dns_rdatatype_any); if (nsecset == NULL) continue; printf("There is a NSEC for this zone in the" " AUTHORITY section:\n"); print_rdataset(nsecname, nsecset); for (result = dns_rdataset_first(nsecset); result == ISC_R_SUCCESS; result = dns_rdataset_next(nsecset)) { dns_rdataset_current(nsecset, &nsec); signsecset = chase_scanname_section(msg, nsecname, dns_rdatatype_rrsig, dns_rdatatype_nsec, DNS_SECTION_AUTHORITY); if (signsecset == NULL) { printf(";; no RRSIG NSEC in authority section:" " impossible to validate the " "non-existence: FAILED\n"); return (ISC_R_FAILURE); } ret = dns_rdata_tostruct(&nsec, &nsecstruct, NULL); check_result(ret,"dns_rdata_tostruct"); if ((inf_name(nsecname, &nsecstruct.next) == 1 && inf_name(name, &nsecstruct.next) == 1) || (inf_name(name, nsecname) == 1 && inf_name(&nsecstruct.next, name) == 1)) { dns_rdata_freestruct(&nsecstruct); *rdataset = nsecset; *sigrdataset = signsecset; dup_name(nsecname, rdata_name); return (ISC_R_SUCCESS); } dns_rdata_freestruct(&nsecstruct); dns_rdata_reset(&nsec); } } while (dns_message_nextname(msg, DNS_SECTION_AUTHORITY) == ISC_R_SUCCESS); *rdataset = NULL; *sigrdataset = NULL; rdata_name = NULL; return (ISC_R_FAILURE); } /** * * * * * */ isc_result_t prove_nx_type(dns_message_t *msg, dns_name_t *name, dns_rdataset_t *nsecset, dns_rdataclass_t rdclass, dns_rdatatype_t type, dns_name_t *rdata_name, dns_rdataset_t **rdataset, dns_rdataset_t **sigrdataset) { isc_result_t ret; dns_rdataset_t *signsecset; dns_rdata_t nsec = DNS_RDATA_INIT; UNUSED(rdclass); ret = dns_rdataset_first(nsecset); check_result(ret,"dns_rdataset_first"); dns_rdataset_current(nsecset, &nsec); ret = dns_nsec_typepresent(&nsec, type); if (ret == ISC_R_SUCCESS) printf("OK the NSEC said that the type doesn't exist \n"); signsecset = chase_scanname_section(msg, name, dns_rdatatype_rrsig, dns_rdatatype_nsec, DNS_SECTION_AUTHORITY); if (signsecset == NULL) { printf("There isn't RRSIG NSEC for the zone \n"); return (ISC_R_FAILURE); } dup_name(name, rdata_name); *rdataset = nsecset; *sigrdataset = signsecset; return (ret); } /** * * * * */ isc_result_t prove_nx(dns_message_t *msg, dns_name_t *name, dns_rdataclass_t rdclass, dns_rdatatype_t type, dns_name_t *rdata_name, dns_rdataset_t **rdataset, dns_rdataset_t **sigrdataset) { isc_result_t ret; dns_rdataset_t *nsecset = NULL; printf("We want to prove the non-existence of a type of rdata %d" " or of the zone: \n", type); if ((ret = dns_message_firstname(msg, DNS_SECTION_AUTHORITY)) != ISC_R_SUCCESS) { printf(";; nothing in authority section : impossible to" " validate the non-existence : FAILED\n"); return (ISC_R_FAILURE); } nsecset = chase_scanname_section(msg, name, dns_rdatatype_nsec, dns_rdatatype_any, DNS_SECTION_AUTHORITY); if (nsecset != NULL) { printf("We have a NSEC for this zone :OK\n"); ret = prove_nx_type(msg, name, nsecset, rdclass, type, rdata_name, rdataset, sigrdataset); if (ret != ISC_R_SUCCESS) { printf("prove_nx: ERROR type exist\n"); return (ret); } else { printf("prove_nx: OK type does not exist\n"); return (ISC_R_SUCCESS); } } else { printf("there is no NSEC for this zone: validating " "that the zone doesn't exist\n"); ret = prove_nx_domain(msg, name, rdata_name, rdataset, sigrdataset); return (ret); } /* Never get here */ } #endif bind9-9.11.3+dfsg/bin/dig/host.1000066400000000000000000000171621325250447100161150ustar00rootroot00000000000000.\" Copyright (C) 2000-2002, 2004, 2005, 2007-2009, 2014-2017 Internet Systems Consortium, Inc. ("ISC") .\" .\" This Source Code Form is subject to the terms of the Mozilla Public .\" License, v. 2.0. If a copy of the MPL was not distributed with this .\" file, You can obtain one at http://mozilla.org/MPL/2.0/. .\" .hy 0 .ad l '\" t .\" Title: host .\" Author: .\" Generator: DocBook XSL Stylesheets v1.78.1 .\" Date: 2009-01-20 .\" Manual: BIND9 .\" Source: ISC .\" Language: English .\" .TH "HOST" "1" "2009\-01\-20" "ISC" "BIND9" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" host \- DNS lookup utility .SH "SYNOPSIS" .HP \w'\fBhost\fR\ 'u \fBhost\fR [\fB\-aCdlnrsTUwv\fR] [\fB\-c\ \fR\fB\fIclass\fR\fR] [\fB\-N\ \fR\fB\fIndots\fR\fR] [\fB\-R\ \fR\fB\fInumber\fR\fR] [\fB\-t\ \fR\fB\fItype\fR\fR] [\fB\-W\ \fR\fB\fIwait\fR\fR] [\fB\-m\ \fR\fB\fIflag\fR\fR] [[\fB\-4\fR] | [\fB\-6\fR]] [\fB\-v\fR] [\fB\-V\fR] {name} [server] .SH "DESCRIPTION" .PP \fBhost\fR is a simple utility for performing DNS lookups\&. It is normally used to convert names to IP addresses and vice versa\&. When no arguments or options are given, \fBhost\fR prints a short summary of its command line arguments and options\&. .PP \fIname\fR is the domain name that is to be looked up\&. It can also be a dotted\-decimal IPv4 address or a colon\-delimited IPv6 address, in which case \fBhost\fR will by default perform a reverse lookup for that address\&. \fIserver\fR is an optional argument which is either the name or IP address of the name server that \fBhost\fR should query instead of the server or servers listed in /etc/resolv\&.conf\&. .SH "OPTIONS" .PP \-4 .RS 4 Use IPv4 only for query transport\&. See also the \fB\-6\fR option\&. .RE .PP \-6 .RS 4 Use IPv6 only for query transport\&. See also the \fB\-4\fR option\&. .RE .PP \-a .RS 4 "All"\&. The \fB\-a\fR option is normally equivalent to \fB\-v \-t \fR\fBANY\fR\&. It also affects the behaviour of the \fB\-l\fR list zone option\&. .RE .PP \-c \fIclass\fR .RS 4 Query class: This can be used to lookup HS (Hesiod) or CH (Chaosnet) class resource records\&. The default class is IN (Internet)\&. .RE .PP \-C .RS 4 Check consistency: \fBhost\fR will query the SOA records for zone \fIname\fR from all the listed authoritative name servers for that zone\&. The list of name servers is defined by the NS records that are found for the zone\&. .RE .PP \-d .RS 4 Print debugging traces\&. Equivalent to the \fB\-v\fR verbose option\&. .RE .PP \-i .RS 4 Obsolete\&. Use the IP6\&.INT domain for reverse lookups of IPv6 addresses as defined in RFC1886 and deprecated in RFC4159\&. The default is to use IP6\&.ARPA as specified in RFC3596\&. .RE .PP \-l .RS 4 List zone: The \fBhost\fR command performs a zone transfer of zone \fIname\fR and prints out the NS, PTR and address records (A/AAAA)\&. .sp Together, the \fB\-l \-a\fR options print all records in the zone\&. .RE .PP \-N \fIndots\fR .RS 4 The number of dots that have to be in \fIname\fR for it to be considered absolute\&. The default value is that defined using the ndots statement in /etc/resolv\&.conf, or 1 if no ndots statement is present\&. Names with fewer dots are interpreted as relative names and will be searched for in the domains listed in the \fBsearch\fR or \fBdomain\fR directive in /etc/resolv\&.conf\&. .RE .PP \-r .RS 4 Non\-recursive query: Setting this option clears the RD (recursion desired) bit in the query\&. This should mean that the name server receiving the query will not attempt to resolve \fIname\fR\&. The \fB\-r\fR option enables \fBhost\fR to mimic the behavior of a name server by making non\-recursive queries and expecting to receive answers to those queries that can be referrals to other name servers\&. .RE .PP \-R \fInumber\fR .RS 4 Number of retries for UDP queries: If \fInumber\fR is negative or zero, the number of retries will default to 1\&. The default value is 1, or the value of the \fIattempts\fR option in /etc/resolv\&.conf, if set\&. .RE .PP \-s .RS 4 Do \fInot\fR send the query to the next nameserver if any server responds with a SERVFAIL response, which is the reverse of normal stub resolver behavior\&. .RE .PP \-t \fItype\fR .RS 4 Query type: The \fItype\fR argument can be any recognized query type: CNAME, NS, SOA, TXT, DNSKEY, AXFR, etc\&. .sp When no query type is specified, \fBhost\fR automatically selects an appropriate query type\&. By default, it looks for A, AAAA, and MX records\&. If the \fB\-C\fR option is given, queries will be made for SOA records\&. If \fIname\fR is a dotted\-decimal IPv4 address or colon\-delimited IPv6 address, \fBhost\fR will query for PTR records\&. .sp If a query type of IXFR is chosen the starting serial number can be specified by appending an equal followed by the starting serial number (like \fB\-t \fR\fBIXFR=12345678\fR)\&. .RE .PP \-T, \-U .RS 4 TCP/UDP: By default, \fBhost\fR uses UDP when making queries\&. The \fB\-T\fR option makes it use a TCP connection when querying the name server\&. TCP will be automatically selected for queries that require it, such as zone transfer (AXFR) requests\&. Type ANY queries default to TCP but can be forced to UDP initially using \fB\-U\fR\&. .RE .PP \-m \fIflag\fR .RS 4 Memory usage debugging: the flag can be \fIrecord\fR, \fIusage\fR, or \fItrace\fR\&. You can specify the \fB\-m\fR option more than once to set multiple flags\&. .RE .PP \-v .RS 4 Verbose output\&. Equivalent to the \fB\-d\fR debug option\&. Verbose output can also be enabled by setting the \fIdebug\fR option in /etc/resolv\&.conf\&. .RE .PP \-V .RS 4 Print the version number and exit\&. .RE .PP \-w .RS 4 Wait forever: The query timeout is set to the maximum possible\&. See also the \fB\-W\fR option\&. .RE .PP \-W \fIwait\fR .RS 4 Timeout: Wait for up to \fIwait\fR seconds for a reply\&. If \fIwait\fR is less than one, the wait interval is set to one second\&. .sp By default, \fBhost\fR will wait for 5 seconds for UDP responses and 10 seconds for TCP connections\&. These defaults can be overridden by the \fItimeout\fR option in /etc/resolv\&.conf\&. .sp See also the \fB\-w\fR option\&. .RE .SH "IDN SUPPORT" .PP If \fBhost\fR has been built with IDN (internationalized domain name) support, it can accept and display non\-ASCII domain names\&. \fBhost\fR appropriately converts character encoding of domain name before sending a request to DNS server or displaying a reply from the server\&. If you\*(Aqd like to turn off the IDN support for some reason, defines the \fBIDN_DISABLE\fR environment variable\&. The IDN support is disabled if the variable is set when \fBhost\fR runs\&. .SH "FILES" .PP /etc/resolv\&.conf .SH "SEE ALSO" .PP \fBdig\fR(1), \fBnamed\fR(8)\&. .SH "AUTHOR" .PP \fBInternet Systems Consortium, Inc\&.\fR .SH "COPYRIGHT" .br Copyright \(co 2000-2002, 2004, 2005, 2007-2009, 2014-2017 Internet Systems Consortium, Inc. ("ISC") .br bind9-9.11.3+dfsg/bin/dig/host.c000066400000000000000000000554001325250447100161740ustar00rootroot00000000000000/* * Copyright (C) 2000-2007, 2009-2017 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /*! \file */ #include #include #include #ifdef HAVE_LOCALE_H #include #endif #ifdef WITH_IDN #include #include #include #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static isc_boolean_t short_form = ISC_TRUE, listed_server = ISC_FALSE; static isc_boolean_t default_lookups = ISC_TRUE; static int seen_error = -1; static isc_boolean_t list_addresses = ISC_TRUE; static dns_rdatatype_t list_type = dns_rdatatype_a; static isc_boolean_t printed_server = ISC_FALSE; static isc_boolean_t ipv4only = ISC_FALSE, ipv6only = ISC_FALSE; static const char *opcodetext[] = { "QUERY", "IQUERY", "STATUS", "RESERVED3", "NOTIFY", "UPDATE", "RESERVED6", "RESERVED7", "RESERVED8", "RESERVED9", "RESERVED10", "RESERVED11", "RESERVED12", "RESERVED13", "RESERVED14", "RESERVED15" }; static const char *rcodetext[] = { "NOERROR", "FORMERR", "SERVFAIL", "NXDOMAIN", "NOTIMP", "REFUSED", "YXDOMAIN", "YXRRSET", "NXRRSET", "NOTAUTH", "NOTZONE", "RESERVED11", "RESERVED12", "RESERVED13", "RESERVED14", "RESERVED15", "BADVERS" }; struct rtype { unsigned int type; const char *text; }; struct rtype rtypes[] = { { 1, "has address" }, { 2, "name server" }, { 5, "is an alias for" }, { 11, "has well known services" }, { 12, "domain name pointer" }, { 13, "host information" }, { 15, "mail is handled by" }, { 16, "descriptive text" }, { 19, "x25 address" }, { 20, "ISDN address" }, { 24, "has signature" }, { 25, "has key" }, { 28, "has IPv6 address" }, { 29, "location" }, { 0, NULL } }; static char * rcode_totext(dns_rcode_t rcode) { static char buf[sizeof("?65535")]; union { const char *consttext; char *deconsttext; } totext; if (rcode >= (sizeof(rcodetext)/sizeof(rcodetext[0]))) { snprintf(buf, sizeof(buf), "?%u", rcode); totext.deconsttext = buf; } else totext.consttext = rcodetext[rcode]; return totext.deconsttext; } ISC_PLATFORM_NORETURN_PRE static void show_usage(void) ISC_PLATFORM_NORETURN_POST; static void show_usage(void) { fputs( "Usage: host [-aCdilrTvVw] [-c class] [-N ndots] [-t type] [-W time]\n" " [-R number] [-m flag] hostname [server]\n" " -a is equivalent to -v -t ANY\n" " -c specifies query class for non-IN data\n" " -C compares SOA records on authoritative nameservers\n" " -d is equivalent to -v\n" " -i IP6.INT reverse lookups\n" " -l lists all hosts in a domain, using AXFR\n" " -m set memory debugging flag (trace|record|usage)\n" " -N changes the number of dots allowed before root lookup is done\n" " -r disables recursive processing\n" " -R specifies number of retries for UDP packets\n" " -s a SERVFAIL response should stop query\n" " -t specifies the query type\n" " -T enables TCP/IP mode\n" " -v enables verbose output\n" " -V print version number and exit\n" " -w specifies to wait forever for a reply\n" " -W specifies how long to wait for a reply\n" " -4 use IPv4 query transport only\n" " -6 use IPv6 query transport only\n", stderr); exit(1); } static void host_shutdown(void) { (void) isc_app_shutdown(); } static void received(int bytes, isc_sockaddr_t *from, dig_query_t *query) { isc_time_t now; int diff; if (!short_form) { char fromtext[ISC_SOCKADDR_FORMATSIZE]; isc_sockaddr_format(from, fromtext, sizeof(fromtext)); TIME_NOW(&now); diff = (int) isc_time_microdiff(&now, &query->time_sent); printf("Received %u bytes from %s in %d ms\n", bytes, fromtext, diff/1000); } } static void trying(char *frm, dig_lookup_t *lookup) { UNUSED(lookup); if (!short_form) printf("Trying \"%s\"\n", frm); } static void say_message(dns_name_t *name, const char *msg, dns_rdata_t *rdata, dig_query_t *query) { isc_buffer_t *b = NULL; char namestr[DNS_NAME_FORMATSIZE]; isc_region_t r; isc_result_t result; unsigned int bufsize = BUFSIZ; dns_name_format(name, namestr, sizeof(namestr)); retry: result = isc_buffer_allocate(mctx, &b, bufsize); check_result(result, "isc_buffer_allocate"); result = dns_rdata_totext(rdata, NULL, b); if (result == ISC_R_NOSPACE) { isc_buffer_free(&b); bufsize *= 2; goto retry; } check_result(result, "dns_rdata_totext"); isc_buffer_usedregion(b, &r); if (query->lookup->identify_previous_line) { printf("Nameserver %s:\n\t", query->servname); } printf("%s %s %.*s", namestr, msg, (int)r.length, (char *)r.base); if (query->lookup->identify) { printf(" on server %s", query->servname); } printf("\n"); isc_buffer_free(&b); } #ifdef DIG_SIGCHASE /* Just for compatibility : not use in host program */ static isc_result_t printrdataset(dns_name_t *owner_name, dns_rdataset_t *rdataset, isc_buffer_t *target) { UNUSED(owner_name); UNUSED(rdataset); UNUSED(target); return(ISC_FALSE); } #endif static isc_result_t printsection(dns_message_t *msg, dns_section_t sectionid, const char *section_name, isc_boolean_t headers, dig_query_t *query) { dns_name_t *name, *print_name; dns_rdataset_t *rdataset; dns_rdata_t rdata = DNS_RDATA_INIT; isc_buffer_t target; isc_result_t result, loopresult; isc_region_t r; dns_name_t empty_name; char tbuf[4096]; isc_boolean_t first; isc_boolean_t no_rdata; if (sectionid == DNS_SECTION_QUESTION) no_rdata = ISC_TRUE; else no_rdata = ISC_FALSE; if (headers) printf(";; %s SECTION:\n", section_name); dns_name_init(&empty_name, NULL); result = dns_message_firstname(msg, sectionid); if (result == ISC_R_NOMORE) return (ISC_R_SUCCESS); else if (result != ISC_R_SUCCESS) return (result); for (;;) { name = NULL; dns_message_currentname(msg, sectionid, &name); isc_buffer_init(&target, tbuf, sizeof(tbuf)); first = ISC_TRUE; print_name = name; for (rdataset = ISC_LIST_HEAD(name->list); rdataset != NULL; rdataset = ISC_LIST_NEXT(rdataset, link)) { if (query->lookup->rdtype == dns_rdatatype_axfr && !((!list_addresses && (list_type == dns_rdatatype_any || rdataset->type == list_type)) || (list_addresses && (rdataset->type == dns_rdatatype_a || rdataset->type == dns_rdatatype_aaaa || rdataset->type == dns_rdatatype_ns || rdataset->type == dns_rdatatype_ptr)))) continue; if (!short_form) { result = dns_rdataset_totext(rdataset, print_name, ISC_FALSE, no_rdata, &target); if (result != ISC_R_SUCCESS) return (result); #ifdef USEINITALWS if (first) { print_name = &empty_name; first = ISC_FALSE; } #else UNUSED(first); /* Shut up compiler. */ #endif } else { loopresult = dns_rdataset_first(rdataset); while (loopresult == ISC_R_SUCCESS) { struct rtype *t; const char *rtt; char typebuf[DNS_RDATATYPE_FORMATSIZE]; char typebuf2[DNS_RDATATYPE_FORMATSIZE + 20]; dns_rdataset_current(rdataset, &rdata); for (t = rtypes; t->text != NULL; t++) { if (t->type == rdata.type) { rtt = t->text; goto found; } } dns_rdatatype_format(rdata.type, typebuf, sizeof(typebuf)); snprintf(typebuf2, sizeof(typebuf2), "has %s record", typebuf); rtt = typebuf2; found: say_message(print_name, rtt, &rdata, query); dns_rdata_reset(&rdata); loopresult = dns_rdataset_next(rdataset); } } } if (!short_form) { isc_buffer_usedregion(&target, &r); if (no_rdata) printf(";%.*s", (int)r.length, (char *)r.base); else printf("%.*s", (int)r.length, (char *)r.base); } result = dns_message_nextname(msg, sectionid); if (result == ISC_R_NOMORE) break; else if (result != ISC_R_SUCCESS) return (result); } return (ISC_R_SUCCESS); } static isc_result_t printrdata(dns_message_t *msg, dns_rdataset_t *rdataset, dns_name_t *owner, const char *set_name, isc_boolean_t headers) { isc_buffer_t target; isc_result_t result; isc_region_t r; char tbuf[4096]; UNUSED(msg); if (headers) printf(";; %s SECTION:\n", set_name); isc_buffer_init(&target, tbuf, sizeof(tbuf)); result = dns_rdataset_totext(rdataset, owner, ISC_FALSE, ISC_FALSE, &target); if (result != ISC_R_SUCCESS) return (result); isc_buffer_usedregion(&target, &r); printf("%.*s", (int)r.length, (char *)r.base); return (ISC_R_SUCCESS); } static void chase_cnamechain(dns_message_t *msg, dns_name_t *qname) { isc_result_t result; dns_rdataset_t *rdataset; dns_rdata_cname_t cname; dns_rdata_t rdata = DNS_RDATA_INIT; unsigned int i = msg->counts[DNS_SECTION_ANSWER]; while (i-- > 0) { rdataset = NULL; result = dns_message_findname(msg, DNS_SECTION_ANSWER, qname, dns_rdatatype_cname, 0, NULL, &rdataset); if (result != ISC_R_SUCCESS) return; result = dns_rdataset_first(rdataset); check_result(result, "dns_rdataset_first"); dns_rdata_reset(&rdata); dns_rdataset_current(rdataset, &rdata); result = dns_rdata_tostruct(&rdata, &cname, NULL); check_result(result, "dns_rdata_tostruct"); dns_name_copy(&cname.cname, qname, NULL); dns_rdata_freestruct(&cname); } } static isc_result_t printmessage(dig_query_t *query, dns_message_t *msg, isc_boolean_t headers) { isc_boolean_t did_flag = ISC_FALSE; dns_rdataset_t *opt, *tsig = NULL; dns_name_t *tsigname; isc_result_t result = ISC_R_SUCCESS; int force_error; UNUSED(headers); /* * We get called multiple times. * Preserve any existing error status. */ force_error = (seen_error == 1) ? 1 : 0; seen_error = 1; if (listed_server && !printed_server) { char sockstr[ISC_SOCKADDR_FORMATSIZE]; printf("Using domain server:\n"); printf("Name: %s\n", query->userarg); isc_sockaddr_format(&query->sockaddr, sockstr, sizeof(sockstr)); printf("Address: %s\n", sockstr); printf("Aliases: \n\n"); printed_server = ISC_TRUE; } if (msg->rcode != 0) { char namestr[DNS_NAME_FORMATSIZE]; dns_name_format(query->lookup->name, namestr, sizeof(namestr)); if (query->lookup->identify_previous_line) printf("Nameserver %s:\n\t%s not found: %d(%s)\n", query->servname, (msg->rcode != dns_rcode_nxdomain) ? namestr : query->lookup->textname, msg->rcode, rcode_totext(msg->rcode)); else printf("Host %s not found: %d(%s)\n", (msg->rcode != dns_rcode_nxdomain) ? namestr : query->lookup->textname, msg->rcode, rcode_totext(msg->rcode)); return (ISC_R_SUCCESS); } if (default_lookups && query->lookup->rdtype == dns_rdatatype_a) { char namestr[DNS_NAME_FORMATSIZE]; dig_lookup_t *lookup; dns_fixedname_t fixed; dns_name_t *name; /* Add AAAA and MX lookups. */ dns_fixedname_init(&fixed); name = dns_fixedname_name(&fixed); dns_name_copy(query->lookup->name, name, NULL); chase_cnamechain(msg, name); dns_name_format(name, namestr, sizeof(namestr)); lookup = clone_lookup(query->lookup, ISC_FALSE); if (lookup != NULL) { strlcpy(lookup->textname, namestr, sizeof(lookup->textname)); lookup->rdtype = dns_rdatatype_aaaa; lookup->rdtypeset = ISC_TRUE; lookup->origin = NULL; lookup->retries = tries; ISC_LIST_APPEND(lookup_list, lookup, link); } lookup = clone_lookup(query->lookup, ISC_FALSE); if (lookup != NULL) { strlcpy(lookup->textname, namestr, sizeof(lookup->textname)); lookup->rdtype = dns_rdatatype_mx; lookup->rdtypeset = ISC_TRUE; lookup->origin = NULL; lookup->retries = tries; ISC_LIST_APPEND(lookup_list, lookup, link); } } if (!short_form) { printf(";; ->>HEADER<<- opcode: %s, status: %s, id: %u\n", opcodetext[msg->opcode], rcode_totext(msg->rcode), msg->id); printf(";; flags: "); if ((msg->flags & DNS_MESSAGEFLAG_QR) != 0) { printf("qr"); did_flag = ISC_TRUE; } if ((msg->flags & DNS_MESSAGEFLAG_AA) != 0) { printf("%saa", did_flag ? " " : ""); did_flag = ISC_TRUE; } if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) { printf("%stc", did_flag ? " " : ""); did_flag = ISC_TRUE; } if ((msg->flags & DNS_MESSAGEFLAG_RD) != 0) { printf("%srd", did_flag ? " " : ""); did_flag = ISC_TRUE; } if ((msg->flags & DNS_MESSAGEFLAG_RA) != 0) { printf("%sra", did_flag ? " " : ""); did_flag = ISC_TRUE; } if ((msg->flags & DNS_MESSAGEFLAG_AD) != 0) { printf("%sad", did_flag ? " " : ""); did_flag = ISC_TRUE; } if ((msg->flags & DNS_MESSAGEFLAG_CD) != 0) { printf("%scd", did_flag ? " " : ""); did_flag = ISC_TRUE; POST(did_flag); } printf("; QUERY: %u, ANSWER: %u, " "AUTHORITY: %u, ADDITIONAL: %u\n", msg->counts[DNS_SECTION_QUESTION], msg->counts[DNS_SECTION_ANSWER], msg->counts[DNS_SECTION_AUTHORITY], msg->counts[DNS_SECTION_ADDITIONAL]); opt = dns_message_getopt(msg); if (opt != NULL) printf(";; EDNS: version: %u, udp=%u\n", (unsigned int)((opt->ttl & 0x00ff0000) >> 16), (unsigned int)opt->rdclass); tsigname = NULL; tsig = dns_message_gettsig(msg, &tsigname); if (tsig != NULL) printf(";; PSEUDOSECTIONS: TSIG\n"); } if (! ISC_LIST_EMPTY(msg->sections[DNS_SECTION_QUESTION]) && !short_form) { printf("\n"); result = printsection(msg, DNS_SECTION_QUESTION, "QUESTION", ISC_TRUE, query); if (result != ISC_R_SUCCESS) return (result); } if (! ISC_LIST_EMPTY(msg->sections[DNS_SECTION_ANSWER])) { if (!short_form) printf("\n"); result = printsection(msg, DNS_SECTION_ANSWER, "ANSWER", ISC_TF(!short_form), query); if (result != ISC_R_SUCCESS) return (result); } if (! ISC_LIST_EMPTY(msg->sections[DNS_SECTION_AUTHORITY]) && !short_form) { printf("\n"); result = printsection(msg, DNS_SECTION_AUTHORITY, "AUTHORITY", ISC_TRUE, query); if (result != ISC_R_SUCCESS) return (result); } if (! ISC_LIST_EMPTY(msg->sections[DNS_SECTION_ADDITIONAL]) && !short_form) { printf("\n"); result = printsection(msg, DNS_SECTION_ADDITIONAL, "ADDITIONAL", ISC_TRUE, query); if (result != ISC_R_SUCCESS) return (result); } if ((tsig != NULL) && !short_form) { printf("\n"); result = printrdata(msg, tsig, tsigname, "PSEUDOSECTION TSIG", ISC_TRUE); if (result != ISC_R_SUCCESS) return (result); } if (!short_form) printf("\n"); if (short_form && !default_lookups && ISC_LIST_EMPTY(msg->sections[DNS_SECTION_ANSWER])) { char namestr[DNS_NAME_FORMATSIZE]; char typestr[DNS_RDATATYPE_FORMATSIZE]; dns_name_format(query->lookup->name, namestr, sizeof(namestr)); dns_rdatatype_format(query->lookup->rdtype, typestr, sizeof(typestr)); printf("%s has no %s record\n", namestr, typestr); } seen_error = force_error; return (result); } static const char * optstring = "46ac:dilnm:rst:vVwCDN:R:TUW:"; /*% version */ static void version(void) { fputs("host " VERSION "\n", stderr); } static void pre_parse_args(int argc, char **argv) { int c; while ((c = isc_commandline_parse(argc, argv, optstring)) != -1) { switch (c) { case 'm': memdebugging = ISC_TRUE; if (strcasecmp("trace", isc_commandline_argument) == 0) isc_mem_debugging |= ISC_MEM_DEBUGTRACE; else if (strcasecmp("record", isc_commandline_argument) == 0) isc_mem_debugging |= ISC_MEM_DEBUGRECORD; else if (strcasecmp("usage", isc_commandline_argument) == 0) isc_mem_debugging |= ISC_MEM_DEBUGUSAGE; break; case '4': if (ipv6only) fatal("only one of -4 and -6 allowed"); ipv4only = ISC_TRUE; break; case '6': if (ipv4only) fatal("only one of -4 and -6 allowed"); ipv6only = ISC_TRUE; break; case 'a': break; case 'c': break; case 'd': break; case 'i': break; case 'l': break; case 'n': break; case 'r': break; case 's': break; case 't': break; case 'v': break; case 'V': version(); exit(0); break; case 'w': break; case 'C': break; case 'D': if (debugging) debugtiming = ISC_TRUE; debugging = ISC_TRUE; break; case 'N': break; case 'R': break; case 'T': break; case 'W': break; default: show_usage(); } } isc_commandline_reset = ISC_TRUE; isc_commandline_index = 1; } static void parse_args(isc_boolean_t is_batchfile, int argc, char **argv) { char hostname[MXNAME]; dig_lookup_t *lookup; int c; char store[MXNAME]; isc_textregion_t tr; isc_result_t result = ISC_R_SUCCESS; dns_rdatatype_t rdtype; dns_rdataclass_t rdclass; isc_uint32_t serial = 0; UNUSED(is_batchfile); lookup = make_empty_lookup(); lookup->servfail_stops = ISC_FALSE; lookup->comments = ISC_FALSE; short_form = !verbose; while ((c = isc_commandline_parse(argc, argv, optstring)) != -1) { switch (c) { case 'l': lookup->tcp_mode = ISC_TRUE; lookup->rdtype = dns_rdatatype_axfr; lookup->rdtypeset = ISC_TRUE; fatalexit = 3; break; case 'v': case 'd': short_form = ISC_FALSE; break; case 'r': lookup->recurse = ISC_FALSE; break; case 't': if (strncasecmp(isc_commandline_argument, "ixfr=", 5) == 0) { rdtype = dns_rdatatype_ixfr; /* XXXMPA add error checking */ serial = strtoul(isc_commandline_argument + 5, NULL, 10); result = ISC_R_SUCCESS; } else { tr.base = isc_commandline_argument; tr.length = strlen(isc_commandline_argument); result = dns_rdatatype_fromtext(&rdtype, (isc_textregion_t *)&tr); } if (result != ISC_R_SUCCESS) { fatalexit = 2; fatal("invalid type: %s\n", isc_commandline_argument); } if (!lookup->rdtypeset || lookup->rdtype != dns_rdatatype_axfr) lookup->rdtype = rdtype; lookup->rdtypeset = ISC_TRUE; #ifdef WITH_IDN idnoptions = 0; #endif if (rdtype == dns_rdatatype_axfr) { /* -l -t any -v */ list_type = dns_rdatatype_any; short_form = ISC_FALSE; lookup->tcp_mode = ISC_TRUE; } else if (rdtype == dns_rdatatype_ixfr) { lookup->ixfr_serial = serial; lookup->tcp_mode = ISC_TRUE; list_type = rdtype; } else if (rdtype == dns_rdatatype_any) { if (!lookup->tcp_mode_set) lookup->tcp_mode = ISC_TRUE; #ifdef WITH_IDN } else if (rdtype == dns_rdatatype_a || rdtype == dns_rdatatype_aaaa || rdtype == dns_rdatatype_mx) { idnoptions = IDN_ASCCHECK; list_type = rdtype; #endif } else list_type = rdtype; list_addresses = ISC_FALSE; default_lookups = ISC_FALSE; break; case 'c': tr.base = isc_commandline_argument; tr.length = strlen(isc_commandline_argument); result = dns_rdataclass_fromtext(&rdclass, (isc_textregion_t *)&tr); if (result != ISC_R_SUCCESS) { fatalexit = 2; fatal("invalid class: %s\n", isc_commandline_argument); } else { lookup->rdclass = rdclass; lookup->rdclassset = ISC_TRUE; } default_lookups = ISC_FALSE; break; case 'a': if (!lookup->rdtypeset || lookup->rdtype != dns_rdatatype_axfr) lookup->rdtype = dns_rdatatype_any; #ifdef WITH_IDN idnoptions = 0; #endif list_type = dns_rdatatype_any; list_addresses = ISC_FALSE; lookup->rdtypeset = ISC_TRUE; short_form = ISC_FALSE; default_lookups = ISC_FALSE; break; case 'i': lookup->ip6_int = ISC_TRUE; break; case 'n': /* deprecated */ break; case 'm': /* Handled by pre_parse_args(). */ break; case 'w': /* * The timer routines are coded such that * timeout==MAXINT doesn't enable the timer */ timeout = INT_MAX; break; case 'W': timeout = atoi(isc_commandline_argument); if (timeout < 1) timeout = 1; break; case 'R': tries = atoi(isc_commandline_argument) + 1; if (tries < 2) tries = 2; break; case 'T': lookup->tcp_mode = ISC_TRUE; lookup->tcp_mode_set = ISC_TRUE; break; case 'U': lookup->tcp_mode = ISC_FALSE; lookup->tcp_mode_set = ISC_TRUE; break; case 'C': debug("showing all SOAs"); lookup->rdtype = dns_rdatatype_ns; lookup->rdtypeset = ISC_TRUE; lookup->rdclass = dns_rdataclass_in; lookup->rdclassset = ISC_TRUE; lookup->ns_search_only = ISC_TRUE; lookup->trace_root = ISC_TRUE; lookup->identify_previous_line = ISC_TRUE; default_lookups = ISC_FALSE; break; case 'N': debug("setting NDOTS to %s", isc_commandline_argument); ndots = atoi(isc_commandline_argument); break; case 'D': /* Handled by pre_parse_args(). */ break; case '4': /* Handled by pre_parse_args(). */ break; case '6': /* Handled by pre_parse_args(). */ break; case 's': lookup->servfail_stops = ISC_TRUE; break; } } lookup->retries = tries; if (isc_commandline_index >= argc) show_usage(); strlcpy(hostname, argv[isc_commandline_index], sizeof(hostname)); if (argc > isc_commandline_index + 1) { set_nameserver(argv[isc_commandline_index+1]); debug("server is %s", argv[isc_commandline_index+1]); listed_server = ISC_TRUE; } else check_ra = ISC_TRUE; lookup->pending = ISC_FALSE; if (get_reverse(store, sizeof(store), hostname, lookup->ip6_int, ISC_TRUE) == ISC_R_SUCCESS) { strlcpy(lookup->textname, store, sizeof(lookup->textname)); lookup->rdtype = dns_rdatatype_ptr; lookup->rdtypeset = ISC_TRUE; default_lookups = ISC_FALSE; } else { strlcpy(lookup->textname, hostname, sizeof(lookup->textname)); usesearch = ISC_TRUE; } lookup->new_search = ISC_TRUE; ISC_LIST_APPEND(lookup_list, lookup, link); } int main(int argc, char **argv) { isc_result_t result; tries = 2; ISC_LIST_INIT(lookup_list); ISC_LIST_INIT(server_list); ISC_LIST_INIT(search_list); fatalexit = 1; #ifdef WITH_IDN idnoptions = IDN_ASCCHECK; #endif /* setup dighost callbacks */ #ifdef DIG_SIGCHASE dighost_printrdataset = printrdataset; #endif dighost_printmessage = printmessage; dighost_received = received; dighost_trying = trying; dighost_shutdown = host_shutdown; debug("main()"); progname = argv[0]; pre_parse_args(argc, argv); result = isc_app_start(); check_result(result, "isc_app_start"); setup_libs(); setup_system(ipv4only, ipv6only); parse_args(ISC_FALSE, argc, argv); if (keyfile[0] != 0) setup_file_key(); else if (keysecret[0] != 0) setup_text_key(); result = isc_app_onrun(mctx, global_task, onrun_callback, NULL); check_result(result, "isc_app_onrun"); isc_app_run(); cancel_all(); destroy_libs(); isc_app_finish(); return ((seen_error == 0) ? 0 : 1); } bind9-9.11.3+dfsg/bin/dig/host.docbook000066400000000000000000000301111325250447100173620ustar00rootroot00000000000000]> 2009-01-20 ISC Internet Systems Consortium, Inc. host 1 BIND9 host DNS lookup utility 2000 2001 2002 2004 2005 2007 2008 2009 2014 2015 2016 2017 Internet Systems Consortium, Inc. ("ISC") host name server DESCRIPTION host is a simple utility for performing DNS lookups. It is normally used to convert names to IP addresses and vice versa. When no arguments or options are given, host prints a short summary of its command line arguments and options. name is the domain name that is to be looked up. It can also be a dotted-decimal IPv4 address or a colon-delimited IPv6 address, in which case host will by default perform a reverse lookup for that address. server is an optional argument which is either the name or IP address of the name server that host should query instead of the server or servers listed in /etc/resolv.conf. OPTIONS -4 Use IPv4 only for query transport. See also the option. -6 Use IPv6 only for query transport. See also the option. -a "All". The option is normally equivalent to . It also affects the behaviour of the list zone option. -c class Query class: This can be used to lookup HS (Hesiod) or CH (Chaosnet) class resource records. The default class is IN (Internet). -C Check consistency: host will query the SOA records for zone name from all the listed authoritative name servers for that zone. The list of name servers is defined by the NS records that are found for the zone. -d Print debugging traces. Equivalent to the verbose option. -i Obsolete. Use the IP6.INT domain for reverse lookups of IPv6 addresses as defined in RFC1886 and deprecated in RFC4159. The default is to use IP6.ARPA as specified in RFC3596. -l List zone: The host command performs a zone transfer of zone name and prints out the NS, PTR and address records (A/AAAA). Together, the options print all records in the zone. -N ndots The number of dots that have to be in name for it to be considered absolute. The default value is that defined using the ndots statement in /etc/resolv.conf, or 1 if no ndots statement is present. Names with fewer dots are interpreted as relative names and will be searched for in the domains listed in the search or domain directive in /etc/resolv.conf. -r Non-recursive query: Setting this option clears the RD (recursion desired) bit in the query. This should mean that the name server receiving the query will not attempt to resolve name. The option enables host to mimic the behavior of a name server by making non-recursive queries and expecting to receive answers to those queries that can be referrals to other name servers. -R number Number of retries for UDP queries: If number is negative or zero, the number of retries will default to 1. The default value is 1, or the value of the attempts option in /etc/resolv.conf, if set. -s Do not send the query to the next nameserver if any server responds with a SERVFAIL response, which is the reverse of normal stub resolver behavior. -t type Query type: The type argument can be any recognized query type: CNAME, NS, SOA, TXT, DNSKEY, AXFR, etc. When no query type is specified, host automatically selects an appropriate query type. By default, it looks for A, AAAA, and MX records. If the option is given, queries will be made for SOA records. If name is a dotted-decimal IPv4 address or colon-delimited IPv6 address, host will query for PTR records. If a query type of IXFR is chosen the starting serial number can be specified by appending an equal followed by the starting serial number (like ). -T -U TCP/UDP: By default, host uses UDP when making queries. The option makes it use a TCP connection when querying the name server. TCP will be automatically selected for queries that require it, such as zone transfer (AXFR) requests. Type ANY queries default to TCP but can be forced to UDP initially using . -m flag Memory usage debugging: the flag can be record, usage, or trace. You can specify the option more than once to set multiple flags. -v Verbose output. Equivalent to the debug option. Verbose output can also be enabled by setting the debug option in /etc/resolv.conf. -V Print the version number and exit. -w Wait forever: The query timeout is set to the maximum possible. See also the option. -W wait Timeout: Wait for up to wait seconds for a reply. If wait is less than one, the wait interval is set to one second. By default, host will wait for 5 seconds for UDP responses and 10 seconds for TCP connections. These defaults can be overridden by the timeout option in /etc/resolv.conf. See also the option. IDN SUPPORT If host has been built with IDN (internationalized domain name) support, it can accept and display non-ASCII domain names. host appropriately converts character encoding of domain name before sending a request to DNS server or displaying a reply from the server. If you'd like to turn off the IDN support for some reason, defines the IDN_DISABLE environment variable. The IDN support is disabled if the variable is set when host runs. FILES /etc/resolv.conf SEE ALSO dig1 , named8 . bind9-9.11.3+dfsg/bin/dig/host.html000066400000000000000000000267211325250447100167220ustar00rootroot00000000000000 host

Name

host — DNS lookup utility

Synopsis

host [-aCdlnrsTUwv] [-c class] [-N ndots] [-R number] [-t type] [-W wait] [-m flag] [ [-4] | [-6] ] [-v] [-V] {name} [server]

DESCRIPTION

host is a simple utility for performing DNS lookups. It is normally used to convert names to IP addresses and vice versa. When no arguments or options are given, host prints a short summary of its command line arguments and options.

name is the domain name that is to be looked up. It can also be a dotted-decimal IPv4 address or a colon-delimited IPv6 address, in which case host will by default perform a reverse lookup for that address. server is an optional argument which is either the name or IP address of the name server that host should query instead of the server or servers listed in /etc/resolv.conf.

OPTIONS

-4

Use IPv4 only for query transport. See also the -6 option.

-6

Use IPv6 only for query transport. See also the -4 option.

-a

"All". The -a option is normally equivalent to -v -t ANY. It also affects the behaviour of the -l list zone option.

-c class

Query class: This can be used to lookup HS (Hesiod) or CH (Chaosnet) class resource records. The default class is IN (Internet).

-C

Check consistency: host will query the SOA records for zone name from all the listed authoritative name servers for that zone. The list of name servers is defined by the NS records that are found for the zone.

-d

Print debugging traces. Equivalent to the -v verbose option.

-i

Obsolete. Use the IP6.INT domain for reverse lookups of IPv6 addresses as defined in RFC1886 and deprecated in RFC4159. The default is to use IP6.ARPA as specified in RFC3596.

-l

List zone: The host command performs a zone transfer of zone name and prints out the NS, PTR and address records (A/AAAA).

Together, the -l -a options print all records in the zone.

-N ndots

The number of dots that have to be in name for it to be considered absolute. The default value is that defined using the ndots statement in /etc/resolv.conf, or 1 if no ndots statement is present. Names with fewer dots are interpreted as relative names and will be searched for in the domains listed in the search or domain directive in /etc/resolv.conf.

-r

Non-recursive query: Setting this option clears the RD (recursion desired) bit in the query. This should mean that the name server receiving the query will not attempt to resolve name. The -r option enables host to mimic the behavior of a name server by making non-recursive queries and expecting to receive answers to those queries that can be referrals to other name servers.

-R number

Number of retries for UDP queries: If number is negative or zero, the number of retries will default to 1. The default value is 1, or the value of the attempts option in /etc/resolv.conf, if set.

-s

Do not send the query to the next nameserver if any server responds with a SERVFAIL response, which is the reverse of normal stub resolver behavior.

-t type

Query type: The type argument can be any recognized query type: CNAME, NS, SOA, TXT, DNSKEY, AXFR, etc.

When no query type is specified, host automatically selects an appropriate query type. By default, it looks for A, AAAA, and MX records. If the -C option is given, queries will be made for SOA records. If name is a dotted-decimal IPv4 address or colon-delimited IPv6 address, host will query for PTR records.

If a query type of IXFR is chosen the starting serial number can be specified by appending an equal followed by the starting serial number (like -t IXFR=12345678).

-T, -U

TCP/UDP: By default, host uses UDP when making queries. The -T option makes it use a TCP connection when querying the name server. TCP will be automatically selected for queries that require it, such as zone transfer (AXFR) requests. Type ANY queries default to TCP but can be forced to UDP initially using -U.

-m flag

Memory usage debugging: the flag can be record, usage, or trace. You can specify the -m option more than once to set multiple flags.

-v

Verbose output. Equivalent to the -d debug option. Verbose output can also be enabled by setting the debug option in /etc/resolv.conf.

-V

Print the version number and exit.

-w

Wait forever: The query timeout is set to the maximum possible. See also the -W option.

-W wait

Timeout: Wait for up to wait seconds for a reply. If wait is less than one, the wait interval is set to one second.

By default, host will wait for 5 seconds for UDP responses and 10 seconds for TCP connections. These defaults can be overridden by the timeout option in /etc/resolv.conf.

See also the -w option.

IDN SUPPORT

If host has been built with IDN (internationalized domain name) support, it can accept and display non-ASCII domain names. host appropriately converts character encoding of domain name before sending a request to DNS server or displaying a reply from the server. If you'd like to turn off the IDN support for some reason, defines the IDN_DISABLE environment variable. The IDN support is disabled if the variable is set when host runs.

FILES

/etc/resolv.conf

SEE ALSO

dig(1) , named(8) .

bind9-9.11.3+dfsg/bin/dig/include/000077500000000000000000000000001325250447100164725ustar00rootroot00000000000000bind9-9.11.3+dfsg/bin/dig/include/dig/000077500000000000000000000000001325250447100172355ustar00rootroot00000000000000bind9-9.11.3+dfsg/bin/dig/include/dig/dig.h000066400000000000000000000240711325250447100201550ustar00rootroot00000000000000/* * Copyright (C) 2000-2009, 2011-2017 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef DIG_H #define DIG_H /*! \file */ #include #include #include #include #include #include #include #include #include #include #include #include #define MXSERV 20 #define MXNAME (DNS_NAME_MAXTEXT+1) #define MXRD 32 /*% Buffer Size */ #define BUFSIZE 512 #define COMMSIZE 0xffff #ifndef RESOLV_CONF /*% location of resolve.conf */ #define RESOLV_CONF "/etc/resolv.conf" #endif /*% output buffer */ #define OUTPUTBUF 32767 /*% Max RR Limit */ #define MAXRRLIMIT 0xffffffff #define MAXTIMEOUT 0xffff /*% Max number of tries */ #define MAXTRIES 0xffffffff /*% Max number of dots */ #define MAXNDOTS 0xffff /*% Max number of ports */ #define MAXPORT 0xffff /*% Max serial number */ #define MAXSERIAL 0xffffffff /*% Default TCP Timeout */ #define TCP_TIMEOUT 10 /*% Default UDP Timeout */ #define UDP_TIMEOUT 5 #define SERVER_TIMEOUT 1 #define LOOKUP_LIMIT 64 /*% * Lookup_limit is just a limiter, keeping too many lookups from being * created. It's job is mainly to prevent the program from running away * in a tight loop of constant lookups. It's value is arbitrary. */ /* * Defaults for the sigchase suboptions. Consolidated here because * these control the layout of dig_lookup_t (among other things). */ #ifdef DIG_SIGCHASE #ifndef DIG_SIGCHASE_BU #define DIG_SIGCHASE_BU 1 #endif #ifndef DIG_SIGCHASE_TD #define DIG_SIGCHASE_TD 1 #endif #endif ISC_LANG_BEGINDECLS typedef struct dig_lookup dig_lookup_t; typedef struct dig_query dig_query_t; typedef struct dig_server dig_server_t; #ifdef DIG_SIGCHASE typedef struct dig_message dig_message_t; #endif typedef ISC_LIST(dig_server_t) dig_serverlist_t; typedef struct dig_searchlist dig_searchlist_t; /*% The dig_lookup structure */ struct dig_lookup { isc_boolean_t pending, /*%< Pending a successful answer */ waiting_connect, doing_xfr, ns_search_only, /*%< dig +nssearch, host -C */ identify, /*%< Append an "on server " message */ identify_previous_line, /*% Prepend a "Nameserver :" message, with newline and tab */ ignore, recurse, aaonly, adflag, cdflag, zflag, trace, /*% dig +trace */ trace_root, /*% initial query for either +trace or +nssearch */ tcp_mode, tcp_mode_set, ip6_int, comments, stats, section_question, section_answer, section_authority, section_additional, servfail_stops, new_search, need_search, done_as_is, besteffort, dnssec, expire, sendcookie, seenbadcookie, badcookie, nsid, /*% Name Server ID (RFC 5001) */ header_only, ednsneg, mapped, print_unknown_format, idnout; #ifdef DIG_SIGCHASE isc_boolean_t sigchase; #if DIG_SIGCHASE_TD isc_boolean_t do_topdown, trace_root_sigchase, rdtype_sigchaseset, rdclass_sigchaseset; /* Name we are going to validate RRset */ char textnamesigchase[MXNAME]; #endif #endif char textname[MXNAME]; /*% Name we're going to be looking up */ char cmdline[MXNAME]; dns_rdatatype_t rdtype; dns_rdatatype_t qrdtype; #if DIG_SIGCHASE_TD dns_rdatatype_t rdtype_sigchase; dns_rdatatype_t qrdtype_sigchase; dns_rdataclass_t rdclass_sigchase; #endif dns_rdataclass_t rdclass; isc_boolean_t rdtypeset; isc_boolean_t rdclassset; char name_space[BUFSIZE]; char oname_space[BUFSIZE]; isc_buffer_t namebuf; isc_buffer_t onamebuf; isc_buffer_t renderbuf; char *sendspace; dns_name_t *name; isc_interval_t interval; dns_message_t *sendmsg; dns_name_t *oname; ISC_LINK(dig_lookup_t) link; ISC_LIST(dig_query_t) q; ISC_LIST(dig_query_t) connecting; dig_query_t *current_query; dig_serverlist_t my_server_list; dig_searchlist_t *origin; dig_query_t *xfr_q; isc_uint32_t retries; int nsfound; isc_uint16_t udpsize; isc_int16_t edns; isc_uint32_t ixfr_serial; isc_buffer_t rdatabuf; char rdatastore[MXNAME]; dst_context_t *tsigctx; isc_buffer_t *querysig; isc_uint32_t msgcounter; dns_fixedname_t fdomain; isc_sockaddr_t *ecs_addr; char *cookie; dns_ednsopt_t *ednsopts; unsigned int ednsoptscnt; isc_dscp_t dscp; unsigned int ednsflags; dns_opcode_t opcode; unsigned int eoferr; }; /*% The dig_query structure */ struct dig_query { dig_lookup_t *lookup; isc_boolean_t waiting_connect, pending_free, waiting_senddone, first_pass, first_soa_rcvd, second_rr_rcvd, first_repeat_rcvd, recv_made, warn_id, timedout; isc_uint32_t first_rr_serial; isc_uint32_t second_rr_serial; isc_uint32_t msg_count; isc_uint32_t rr_count; isc_boolean_t ixfr_axfr; char *servname; char *userarg; isc_bufferlist_t sendlist, recvlist, lengthlist; isc_buffer_t recvbuf, lengthbuf, slbuf; char *recvspace, lengthspace[4], slspace[4]; isc_socket_t *sock; ISC_LINK(dig_query_t) link; ISC_LINK(dig_query_t) clink; isc_sockaddr_t sockaddr; isc_time_t time_sent; isc_time_t time_recv; isc_uint64_t byte_count; isc_buffer_t sendbuf; isc_timer_t *timer; }; struct dig_server { char servername[MXNAME]; char userarg[MXNAME]; ISC_LINK(dig_server_t) link; }; struct dig_searchlist { char origin[MXNAME]; ISC_LINK(dig_searchlist_t) link; }; #ifdef DIG_SIGCHASE struct dig_message { dns_message_t *msg; ISC_LINK(dig_message_t) link; }; #endif typedef ISC_LIST(dig_searchlist_t) dig_searchlistlist_t; typedef ISC_LIST(dig_lookup_t) dig_lookuplist_t; /* * Externals from dighost.c */ extern dig_lookuplist_t lookup_list; extern dig_serverlist_t server_list; extern dig_searchlistlist_t search_list; extern unsigned int extrabytes; extern isc_boolean_t check_ra, have_ipv4, have_ipv6, specified_source, usesearch, showsearch, qr; extern in_port_t port; extern unsigned int timeout; extern isc_mem_t *mctx; extern int sendcount; extern int ndots; extern int lookup_counter; extern int exitcode; extern isc_sockaddr_t bind_address; extern char keynametext[MXNAME]; extern char keyfile[MXNAME]; extern char keysecret[MXNAME]; extern dns_name_t *hmacname; extern unsigned int digestbits; #ifdef DIG_SIGCHASE extern char trustedkey[MXNAME]; #endif extern dns_tsigkey_t *key; extern isc_boolean_t validated; extern isc_taskmgr_t *taskmgr; extern isc_task_t *global_task; extern isc_boolean_t free_now; extern isc_boolean_t debugging, debugtiming, memdebugging; extern isc_boolean_t keep_open; extern char *progname; extern int tries; extern int fatalexit; extern isc_boolean_t verbose; #ifdef WITH_IDN extern int idnoptions; #endif /* * Routines in dighost.c. */ isc_result_t get_address(char *host, in_port_t myport, isc_sockaddr_t *sockaddr); int getaddresses(dig_lookup_t *lookup, const char *host, isc_result_t *resultp); isc_result_t get_reverse(char *reverse, size_t len, char *value, isc_boolean_t ip6_int, isc_boolean_t strict); ISC_PLATFORM_NORETURN_PRE void fatal(const char *format, ...) ISC_FORMAT_PRINTF(1, 2) ISC_PLATFORM_NORETURN_POST; void debug(const char *format, ...) ISC_FORMAT_PRINTF(1, 2); void check_result(isc_result_t result, const char *msg); isc_boolean_t setup_lookup(dig_lookup_t *lookup); void destroy_lookup(dig_lookup_t *lookup); void do_lookup(dig_lookup_t *lookup); void start_lookup(void); void onrun_callback(isc_task_t *task, isc_event_t *event); int dhmain(int argc, char **argv); void setup_libs(void); void setup_system(isc_boolean_t ipv4only, isc_boolean_t ipv6only); isc_result_t parse_uint(isc_uint32_t *uip, const char *value, isc_uint32_t max, const char *desc); isc_result_t parse_xint(isc_uint32_t *uip, const char *value, isc_uint32_t max, const char *desc); isc_result_t parse_netprefix(isc_sockaddr_t **sap, const char *value); void parse_hmac(const char *hmacstr); dig_lookup_t * requeue_lookup(dig_lookup_t *lookold, isc_boolean_t servers); dig_lookup_t * make_empty_lookup(void); dig_lookup_t * clone_lookup(dig_lookup_t *lookold, isc_boolean_t servers); dig_server_t * make_server(const char *servname, const char *userarg); void flush_server_list(void); void set_nameserver(char *opt); void clone_server_list(dig_serverlist_t src, dig_serverlist_t *dest); void cancel_all(void); void destroy_libs(void); void set_search_domain(char *domain); #ifdef DIG_SIGCHASE void clean_trustedkey(void); #endif char * next_token(char **stringp, const char *delim); /* * Routines to be defined in dig.c, host.c, and nslookup.c. and * then assigned to the appropriate function pointer */ #ifdef DIG_SIGCHASE extern isc_result_t (*dighost_printrdataset)(dns_name_t *owner_name, dns_rdataset_t *rdataset, isc_buffer_t *target); #endif extern isc_result_t (*dighost_printmessage)(dig_query_t *query, dns_message_t *msg, isc_boolean_t headers); /*%< * Print the final result of the lookup. */ extern void (*dighost_received)(int bytes, isc_sockaddr_t *from, dig_query_t *query); /*%< * Print a message about where and when the response * was received from, like the final comment in the * output of "dig". */ extern void (*dighost_trying)(char *frm, dig_lookup_t *lookup); extern void (*dighost_shutdown)(void); #ifdef DIG_SIGCHASE /* Chasing functions */ dns_rdataset_t * chase_scanname(dns_name_t *name, dns_rdatatype_t type, dns_rdatatype_t covers); void chase_sig(dns_message_t *msg); #endif void save_opt(dig_lookup_t *lookup, char *code, char *value); void setup_file_key(void); void setup_text_key(void); /* * Routines exported from dig.c for use by dig for iOS */ /*%< * Call once only to set up libraries, parse global * parameters and initial command line query parameters */ void dig_setup(int argc, char **argv); /*%< * Call to supply new parameters for the next lookup */ void dig_query_setup(isc_boolean_t, isc_boolean_t, int argc, char **argv); /*%< * set the main application event cycle running */ void dig_startup(void); /*%< * Initiates the next lookup cycle */ void dig_query_start(void); /*%< * Cleans up the application */ void dig_shutdown(void); ISC_LANG_ENDDECLS #endif bind9-9.11.3+dfsg/bin/dig/nslookup.1000066400000000000000000000156321325250447100170120ustar00rootroot00000000000000.\" Copyright (C) 2004-2007, 2010, 2013-2017 Internet Systems Consortium, Inc. ("ISC") .\" .\" This Source Code Form is subject to the terms of the Mozilla Public .\" License, v. 2.0. If a copy of the MPL was not distributed with this .\" file, You can obtain one at http://mozilla.org/MPL/2.0/. .\" .hy 0 .ad l '\" t .\" Title: nslookup .\" Author: .\" Generator: DocBook XSL Stylesheets v1.78.1 .\" Date: 2014-01-24 .\" Manual: BIND9 .\" Source: ISC .\" Language: English .\" .TH "NSLOOKUP" "1" "2014\-01\-24" "ISC" "BIND9" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" nslookup \- query Internet name servers interactively .SH "SYNOPSIS" .HP \w'\fBnslookup\fR\ 'u \fBnslookup\fR [\fB\-option\fR] [name\ |\ \-] [server] .SH "DESCRIPTION" .PP \fBNslookup\fR is a program to query Internet domain name servers\&. \fBNslookup\fR has two modes: interactive and non\-interactive\&. Interactive mode allows the user to query name servers for information about various hosts and domains or to print a list of hosts in a domain\&. Non\-interactive mode is used to print just the name and requested information for a host or domain\&. .SH "ARGUMENTS" .PP Interactive mode is entered in the following cases: .sp .RS 4 .ie n \{\ \h'-04' 1.\h'+01'\c .\} .el \{\ .sp -1 .IP " 1." 4.2 .\} when no arguments are given (the default name server will be used) .RE .sp .RS 4 .ie n \{\ \h'-04' 2.\h'+01'\c .\} .el \{\ .sp -1 .IP " 2." 4.2 .\} when the first argument is a hyphen (\-) and the second argument is the host name or Internet address of a name server\&. .RE .PP Non\-interactive mode is used when the name or Internet address of the host to be looked up is given as the first argument\&. The optional second argument specifies the host name or address of a name server\&. .PP Options can also be specified on the command line if they precede the arguments and are prefixed with a hyphen\&. For example, to change the default query type to host information, and the initial timeout to 10 seconds, type: .sp .if n \{\ .RS 4 .\} .nf nslookup \-query=hinfo \-timeout=10 .fi .if n \{\ .RE .\} .PP The \fB\-version\fR option causes \fBnslookup\fR to print the version number and immediately exits\&. .SH "INTERACTIVE COMMANDS" .PP \fBhost\fR [server] .RS 4 Look up information for host using the current default server or using server, if specified\&. If host is an Internet address and the query type is A or PTR, the name of the host is returned\&. If host is a name and does not have a trailing period, the search list is used to qualify the name\&. .sp To look up a host not in the current domain, append a period to the name\&. .RE .PP \fBserver\fR \fIdomain\fR .RS 4 .RE .PP \fBlserver\fR \fIdomain\fR .RS 4 Change the default server to \fIdomain\fR; \fBlserver\fR uses the initial server to look up information about \fIdomain\fR, while \fBserver\fR uses the current default server\&. If an authoritative answer can\*(Aqt be found, the names of servers that might have the answer are returned\&. .RE .PP \fBroot\fR .RS 4 not implemented .RE .PP \fBfinger\fR .RS 4 not implemented .RE .PP \fBls\fR .RS 4 not implemented .RE .PP \fBview\fR .RS 4 not implemented .RE .PP \fBhelp\fR .RS 4 not implemented .RE .PP \fB?\fR .RS 4 not implemented .RE .PP \fBexit\fR .RS 4 Exits the program\&. .RE .PP \fBset\fR \fIkeyword\fR\fI[=value]\fR .RS 4 This command is used to change state information that affects the lookups\&. Valid keywords are: .PP \fBall\fR .RS 4 Prints the current values of the frequently used options to \fBset\fR\&. Information about the current default server and host is also printed\&. .RE .PP \fBclass=\fR\fIvalue\fR .RS 4 Change the query class to one of: .PP \fBIN\fR .RS 4 the Internet class .RE .PP \fBCH\fR .RS 4 the Chaos class .RE .PP \fBHS\fR .RS 4 the Hesiod class .RE .PP \fBANY\fR .RS 4 wildcard .RE .sp The class specifies the protocol group of the information\&. .sp (Default = IN; abbreviation = cl) .RE .PP \fB\fI[no]\fR\fR\fBdebug\fR .RS 4 Turn on or off the display of the full response packet and any intermediate response packets when searching\&. .sp (Default = nodebug; abbreviation = [no]deb) .RE .PP \fB\fI[no]\fR\fR\fBd2\fR .RS 4 Turn debugging mode on or off\&. This displays more about what nslookup is doing\&. .sp (Default = nod2) .RE .PP \fBdomain=\fR\fIname\fR .RS 4 Sets the search list to \fIname\fR\&. .RE .PP \fB\fI[no]\fR\fR\fBsearch\fR .RS 4 If the lookup request contains at least one period but doesn\*(Aqt end with a trailing period, append the domain names in the domain search list to the request until an answer is received\&. .sp (Default = search) .RE .PP \fBport=\fR\fIvalue\fR .RS 4 Change the default TCP/UDP name server port to \fIvalue\fR\&. .sp (Default = 53; abbreviation = po) .RE .PP \fBquerytype=\fR\fIvalue\fR .RS 4 .RE .PP \fBtype=\fR\fIvalue\fR .RS 4 Change the type of the information query\&. .sp (Default = A; abbreviations = q, ty) .RE .PP \fB\fI[no]\fR\fR\fBrecurse\fR .RS 4 Tell the name server to query other servers if it does not have the information\&. .sp (Default = recurse; abbreviation = [no]rec) .RE .PP \fBndots=\fR\fInumber\fR .RS 4 Set the number of dots (label separators) in a domain that will disable searching\&. Absolute names always stop searching\&. .RE .PP \fBretry=\fR\fInumber\fR .RS 4 Set the number of retries to number\&. .RE .PP \fBtimeout=\fR\fInumber\fR .RS 4 Change the initial timeout interval for waiting for a reply to number seconds\&. .RE .PP \fB\fI[no]\fR\fR\fBvc\fR .RS 4 Always use a virtual circuit when sending requests to the server\&. .sp (Default = novc) .RE .PP \fB\fI[no]\fR\fR\fBfail\fR .RS 4 Try the next nameserver if a nameserver responds with SERVFAIL or a referral (nofail) or terminate query (fail) on such a response\&. .sp (Default = nofail) .RE .sp .RE .SH "RETURN VALUES" .PP \fBnslookup\fR returns with an exit status of 1 if any query failed, and 0 otherwise\&. .SH "FILES" .PP /etc/resolv\&.conf .SH "SEE ALSO" .PP \fBdig\fR(1), \fBhost\fR(1), \fBnamed\fR(8)\&. .SH "AUTHOR" .PP \fBInternet Systems Consortium, Inc\&.\fR .SH "COPYRIGHT" .br Copyright \(co 2004-2007, 2010, 2013-2017 Internet Systems Consortium, Inc. ("ISC") .br bind9-9.11.3+dfsg/bin/dig/nslookup.c000066400000000000000000000636121325250447100170750ustar00rootroot00000000000000/* * Copyright (C) 2000-2017 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if defined(HAVE_READLINE) #if defined(HAVE_EDIT_READLINE_READLINE_H) #include #if defined(HAVE_EDIT_READLINE_HISTORY_H) #include #endif #elif defined(HAVE_EDITLINE_READLINE_H) #include #elif defined(HAVE_READLINE_READLINE_H) #include #if defined (HAVE_READLINE_HISTORY_H) #include #endif #endif #endif static isc_boolean_t short_form = ISC_TRUE, tcpmode = ISC_FALSE, tcpmode_set = ISC_FALSE, identify = ISC_FALSE, stats = ISC_TRUE, comments = ISC_TRUE, section_question = ISC_TRUE, section_answer = ISC_TRUE, section_authority = ISC_TRUE, section_additional = ISC_TRUE, recurse = ISC_TRUE, aaonly = ISC_FALSE, nofail = ISC_TRUE, default_lookups = ISC_TRUE, a_noanswer = ISC_FALSE; static isc_boolean_t interactive; static isc_boolean_t in_use = ISC_FALSE; static char defclass[MXRD] = "IN"; static char deftype[MXRD] = "A"; static isc_event_t *global_event = NULL; static int query_error = 1, print_error = 0; static char domainopt[DNS_NAME_MAXTEXT]; static const char *rcodetext[] = { "NOERROR", "FORMERR", "SERVFAIL", "NXDOMAIN", "NOTIMP", "REFUSED", "YXDOMAIN", "YXRRSET", "NXRRSET", "NOTAUTH", "NOTZONE", "RESERVED11", "RESERVED12", "RESERVED13", "RESERVED14", "RESERVED15", "BADVERS" }; static const char *rtypetext[] = { "rtype_0 = ", /* 0 */ "internet address = ", /* 1 */ "nameserver = ", /* 2 */ "md = ", /* 3 */ "mf = ", /* 4 */ "canonical name = ", /* 5 */ "soa = ", /* 6 */ "mb = ", /* 7 */ "mg = ", /* 8 */ "mr = ", /* 9 */ "rtype_10 = ", /* 10 */ "protocol = ", /* 11 */ "name = ", /* 12 */ "hinfo = ", /* 13 */ "minfo = ", /* 14 */ "mail exchanger = ", /* 15 */ "text = ", /* 16 */ "rp = ", /* 17 */ "afsdb = ", /* 18 */ "x25 address = ", /* 19 */ "isdn address = ", /* 20 */ "rt = ", /* 21 */ "nsap = ", /* 22 */ "nsap_ptr = ", /* 23 */ "signature = ", /* 24 */ "key = ", /* 25 */ "px = ", /* 26 */ "gpos = ", /* 27 */ "has AAAA address ", /* 28 */ "loc = ", /* 29 */ "next = ", /* 30 */ "rtype_31 = ", /* 31 */ "rtype_32 = ", /* 32 */ "service = ", /* 33 */ "rtype_34 = ", /* 34 */ "naptr = ", /* 35 */ "kx = ", /* 36 */ "cert = ", /* 37 */ "v6 address = ", /* 38 */ "dname = ", /* 39 */ "rtype_40 = ", /* 40 */ "optional = " /* 41 */ }; #define N_KNOWN_RRTYPES (sizeof(rtypetext) / sizeof(rtypetext[0])) static void flush_lookup_list(void); static void getinput(isc_task_t *task, isc_event_t *event); static char * rcode_totext(dns_rcode_t rcode) { static char buf[sizeof("?65535")]; union { const char *consttext; char *deconsttext; } totext; if (rcode >= (sizeof(rcodetext)/sizeof(rcodetext[0]))) { snprintf(buf, sizeof(buf), "?%u", rcode); totext.deconsttext = buf; } else totext.consttext = rcodetext[rcode]; return totext.deconsttext; } static void query_finished(void) { isc_event_t *event = global_event; flush_lookup_list(); debug("dighost_shutdown()"); if (!in_use) { isc_app_shutdown(); return; } isc_task_send(global_task, &event); } static void printsoa(dns_rdata_t *rdata) { dns_rdata_soa_t soa; isc_result_t result; char namebuf[DNS_NAME_FORMATSIZE]; result = dns_rdata_tostruct(rdata, &soa, NULL); check_result(result, "dns_rdata_tostruct"); dns_name_format(&soa.origin, namebuf, sizeof(namebuf)); printf("\torigin = %s\n", namebuf); dns_name_format(&soa.contact, namebuf, sizeof(namebuf)); printf("\tmail addr = %s\n", namebuf); printf("\tserial = %u\n", soa.serial); printf("\trefresh = %u\n", soa.refresh); printf("\tretry = %u\n", soa.retry); printf("\texpire = %u\n", soa.expire); printf("\tminimum = %u\n", soa.minimum); dns_rdata_freestruct(&soa); } static void printaddr(dns_rdata_t *rdata) { isc_result_t result; char text[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")]; isc_buffer_t b; isc_buffer_init(&b, text, sizeof(text)); result = dns_rdata_totext(rdata, NULL, &b); check_result(result, "dns_rdata_totext"); printf("Address: %.*s\n", (int)isc_buffer_usedlength(&b), (char *)isc_buffer_base(&b)); } #ifdef DIG_SIGCHASE /* Just for compatibility : not use in host program */ static isc_result_t printrdataset(dns_name_t *owner_name, dns_rdataset_t *rdataset, isc_buffer_t *target) { UNUSED(owner_name); UNUSED(rdataset); UNUSED(target); return(ISC_FALSE); } #endif static void printrdata(dns_rdata_t *rdata) { isc_result_t result; isc_buffer_t *b = NULL; unsigned int size = 1024; isc_boolean_t done = ISC_FALSE; if (rdata->type < N_KNOWN_RRTYPES) printf("%s", rtypetext[rdata->type]); else printf("rdata_%d = ", rdata->type); while (!done) { result = isc_buffer_allocate(mctx, &b, size); if (result != ISC_R_SUCCESS) check_result(result, "isc_buffer_allocate"); result = dns_rdata_totext(rdata, NULL, b); if (result == ISC_R_SUCCESS) { printf("%.*s\n", (int)isc_buffer_usedlength(b), (char *)isc_buffer_base(b)); done = ISC_TRUE; } else if (result != ISC_R_NOSPACE) check_result(result, "dns_rdata_totext"); isc_buffer_free(&b); size *= 2; } } static isc_result_t printsection(dig_query_t *query, dns_message_t *msg, isc_boolean_t headers, dns_section_t section) { isc_result_t result, loopresult; dns_name_t *name; dns_rdataset_t *rdataset = NULL; dns_rdata_t rdata = DNS_RDATA_INIT; char namebuf[DNS_NAME_FORMATSIZE]; UNUSED(query); UNUSED(headers); debug("printsection()"); result = dns_message_firstname(msg, section); if (result == ISC_R_NOMORE) return (ISC_R_SUCCESS); else if (result != ISC_R_SUCCESS) return (result); for (;;) { name = NULL; dns_message_currentname(msg, section, &name); for (rdataset = ISC_LIST_HEAD(name->list); rdataset != NULL; rdataset = ISC_LIST_NEXT(rdataset, link)) { loopresult = dns_rdataset_first(rdataset); while (loopresult == ISC_R_SUCCESS) { dns_rdataset_current(rdataset, &rdata); switch (rdata.type) { case dns_rdatatype_a: case dns_rdatatype_aaaa: if (section != DNS_SECTION_ANSWER) goto def_short_section; dns_name_format(name, namebuf, sizeof(namebuf)); printf("Name:\t%s\n", namebuf); printaddr(&rdata); break; case dns_rdatatype_soa: dns_name_format(name, namebuf, sizeof(namebuf)); printf("%s\n", namebuf); printsoa(&rdata); break; default: def_short_section: dns_name_format(name, namebuf, sizeof(namebuf)); printf("%s\t", namebuf); printrdata(&rdata); break; } dns_rdata_reset(&rdata); loopresult = dns_rdataset_next(rdataset); } } result = dns_message_nextname(msg, section); if (result == ISC_R_NOMORE) break; else if (result != ISC_R_SUCCESS) { return (result); } } return (ISC_R_SUCCESS); } static isc_result_t detailsection(dig_query_t *query, dns_message_t *msg, isc_boolean_t headers, dns_section_t section) { isc_result_t result, loopresult; dns_name_t *name; dns_rdataset_t *rdataset = NULL; dns_rdata_t rdata = DNS_RDATA_INIT; char namebuf[DNS_NAME_FORMATSIZE]; UNUSED(query); debug("detailsection()"); if (headers) { switch (section) { case DNS_SECTION_QUESTION: puts(" QUESTIONS:"); break; case DNS_SECTION_ANSWER: puts(" ANSWERS:"); break; case DNS_SECTION_AUTHORITY: puts(" AUTHORITY RECORDS:"); break; case DNS_SECTION_ADDITIONAL: puts(" ADDITIONAL RECORDS:"); break; } } result = dns_message_firstname(msg, section); if (result == ISC_R_NOMORE) return (ISC_R_SUCCESS); else if (result != ISC_R_SUCCESS) return (result); for (;;) { name = NULL; dns_message_currentname(msg, section, &name); for (rdataset = ISC_LIST_HEAD(name->list); rdataset != NULL; rdataset = ISC_LIST_NEXT(rdataset, link)) { if (section == DNS_SECTION_QUESTION) { dns_name_format(name, namebuf, sizeof(namebuf)); printf("\t%s, ", namebuf); dns_rdatatype_format(rdataset->type, namebuf, sizeof(namebuf)); printf("type = %s, ", namebuf); dns_rdataclass_format(rdataset->rdclass, namebuf, sizeof(namebuf)); printf("class = %s\n", namebuf); } loopresult = dns_rdataset_first(rdataset); while (loopresult == ISC_R_SUCCESS) { dns_rdataset_current(rdataset, &rdata); dns_name_format(name, namebuf, sizeof(namebuf)); printf(" -> %s\n", namebuf); switch (rdata.type) { case dns_rdatatype_soa: printsoa(&rdata); break; default: printf("\t"); printrdata(&rdata); } dns_rdata_reset(&rdata); printf("\tttl = %u\n", rdataset->ttl); loopresult = dns_rdataset_next(rdataset); } } result = dns_message_nextname(msg, section); if (result == ISC_R_NOMORE) break; else if (result != ISC_R_SUCCESS) { return (result); } } return (ISC_R_SUCCESS); } static void received(int bytes, isc_sockaddr_t *from, dig_query_t *query) { UNUSED(bytes); UNUSED(from); UNUSED(query); } static void trying(char *frm, dig_lookup_t *lookup) { UNUSED(frm); UNUSED(lookup); } static void chase_cnamechain(dns_message_t *msg, dns_name_t *qname) { isc_result_t result; dns_rdataset_t *rdataset; dns_rdata_cname_t cname; dns_rdata_t rdata = DNS_RDATA_INIT; unsigned int i = msg->counts[DNS_SECTION_ANSWER]; while (i-- > 0) { rdataset = NULL; result = dns_message_findname(msg, DNS_SECTION_ANSWER, qname, dns_rdatatype_cname, 0, NULL, &rdataset); if (result != ISC_R_SUCCESS) return; result = dns_rdataset_first(rdataset); check_result(result, "dns_rdataset_first"); dns_rdata_reset(&rdata); dns_rdataset_current(rdataset, &rdata); result = dns_rdata_tostruct(&rdata, &cname, NULL); check_result(result, "dns_rdata_tostruct"); dns_name_copy(&cname.cname, qname, NULL); dns_rdata_freestruct(&cname); } } static isc_result_t printmessage(dig_query_t *query, dns_message_t *msg, isc_boolean_t headers) { char servtext[ISC_SOCKADDR_FORMATSIZE]; /* I've we've gotten this far, we've reached a server. */ query_error = 0; debug("printmessage()"); if(!default_lookups || query->lookup->rdtype == dns_rdatatype_a) { isc_sockaddr_format(&query->sockaddr, servtext, sizeof(servtext)); printf("Server:\t\t%s\n", query->userarg); printf("Address:\t%s\n", servtext); puts(""); } if (!short_form) { puts("------------"); /* detailheader(query, msg);*/ detailsection(query, msg, ISC_TRUE, DNS_SECTION_QUESTION); detailsection(query, msg, ISC_TRUE, DNS_SECTION_ANSWER); detailsection(query, msg, ISC_TRUE, DNS_SECTION_AUTHORITY); detailsection(query, msg, ISC_TRUE, DNS_SECTION_ADDITIONAL); puts("------------"); } if (msg->rcode != 0) { char nametext[DNS_NAME_FORMATSIZE]; dns_name_format(query->lookup->name, nametext, sizeof(nametext)); printf("** server can't find %s: %s\n", nametext, rcode_totext(msg->rcode)); debug("returning with rcode == 0"); /* the lookup failed */ print_error |= 1; return (ISC_R_SUCCESS); } if ( default_lookups && query->lookup->rdtype == dns_rdatatype_a) { char namestr[DNS_NAME_FORMATSIZE]; dig_lookup_t *lookup; dns_fixedname_t fixed; dns_name_t *name; /* Add AAAA lookup. */ dns_fixedname_init(&fixed); name = dns_fixedname_name(&fixed); dns_name_copy(query->lookup->name, name, NULL); chase_cnamechain(msg, name); dns_name_format(name, namestr, sizeof(namestr)); lookup = clone_lookup(query->lookup, ISC_FALSE); if (lookup != NULL) { strlcpy(lookup->textname, namestr, sizeof(lookup->textname)); lookup->rdtype = dns_rdatatype_aaaa; lookup->rdtypeset = ISC_TRUE; lookup->origin = NULL; lookup->retries = tries; ISC_LIST_APPEND(lookup_list, lookup, link); } } if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0 && ( !default_lookups || query->lookup->rdtype == dns_rdatatype_a) ) puts("Non-authoritative answer:"); if (!ISC_LIST_EMPTY(msg->sections[DNS_SECTION_ANSWER])) printsection(query, msg, headers, DNS_SECTION_ANSWER); else { if (default_lookups && query->lookup->rdtype == dns_rdatatype_a) a_noanswer = ISC_TRUE; else if (!default_lookups || (query->lookup->rdtype == dns_rdatatype_aaaa && a_noanswer ) ) printf("*** Can't find %s: No answer\n", query->lookup->textname); } if (((msg->flags & DNS_MESSAGEFLAG_AA) == 0) && (query->lookup->rdtype != dns_rdatatype_a) && (query->lookup->rdtype != dns_rdatatype_aaaa) ) { puts("\nAuthoritative answers can be found from:"); printsection(query, msg, headers, DNS_SECTION_AUTHORITY); printsection(query, msg, headers, DNS_SECTION_ADDITIONAL); } return (ISC_R_SUCCESS); } static void show_settings(isc_boolean_t full, isc_boolean_t serv_only) { dig_server_t *srv; isc_sockaddr_t sockaddr; dig_searchlist_t *listent; isc_result_t result; srv = ISC_LIST_HEAD(server_list); while (srv != NULL) { char sockstr[ISC_SOCKADDR_FORMATSIZE]; result = get_address(srv->servername, port, &sockaddr); check_result(result, "get_address"); isc_sockaddr_format(&sockaddr, sockstr, sizeof(sockstr)); printf("Default server: %s\nAddress: %s\n", srv->userarg, sockstr); if (!full) return; srv = ISC_LIST_NEXT(srv, link); } if (serv_only) return; printf("\nSet options:\n"); printf(" %s\t\t\t%s\t\t%s\n", tcpmode ? "vc" : "novc", short_form ? "nodebug" : "debug", debugging ? "d2" : "nod2"); printf(" %s\t\t%s\n", usesearch ? "search" : "nosearch", recurse ? "recurse" : "norecurse"); printf(" timeout = %d\t\tretry = %d\tport = %d\tndots = %d\n", timeout, tries, port, ndots); printf(" querytype = %-8s\tclass = %s\n", deftype, defclass); printf(" srchlist = "); for (listent = ISC_LIST_HEAD(search_list); listent != NULL; listent = ISC_LIST_NEXT(listent, link)) { printf("%s", listent->origin); if (ISC_LIST_NEXT(listent, link) != NULL) printf("/"); } printf("\n"); } static isc_boolean_t testtype(char *typetext) { isc_result_t result; isc_textregion_t tr; dns_rdatatype_t rdtype; tr.base = typetext; tr.length = strlen(typetext); result = dns_rdatatype_fromtext(&rdtype, &tr); if (result == ISC_R_SUCCESS) return (ISC_TRUE); else { printf("unknown query type: %s\n", typetext); return (ISC_FALSE); } } static isc_boolean_t testclass(char *typetext) { isc_result_t result; isc_textregion_t tr; dns_rdataclass_t rdclass; tr.base = typetext; tr.length = strlen(typetext); result = dns_rdataclass_fromtext(&rdclass, &tr); if (result == ISC_R_SUCCESS) return (ISC_TRUE); else { printf("unknown query class: %s\n", typetext); return (ISC_FALSE); } } static void set_port(const char *value) { isc_uint32_t n; isc_result_t result = parse_uint(&n, value, 65535, "port"); if (result == ISC_R_SUCCESS) port = (isc_uint16_t) n; } static void set_timeout(const char *value) { isc_uint32_t n; isc_result_t result = parse_uint(&n, value, UINT_MAX, "timeout"); if (result == ISC_R_SUCCESS) timeout = n; } static void set_tries(const char *value) { isc_uint32_t n; isc_result_t result = parse_uint(&n, value, INT_MAX, "tries"); if (result == ISC_R_SUCCESS) tries = n; } static void set_ndots(const char *value) { isc_uint32_t n; isc_result_t result = parse_uint(&n, value, 128, "ndots"); if (result == ISC_R_SUCCESS) ndots = n; } static void version(void) { fputs("nslookup " VERSION "\n", stderr); } static void setoption(char *opt) { size_t l = strlen(opt); #define CHECKOPT(A, N) \ ((l >= N) && (l < sizeof(A)) && (strncasecmp(opt, A, l) == 0)) if (CHECKOPT("all", 3)) { show_settings(ISC_TRUE, ISC_FALSE); } else if (strncasecmp(opt, "class=", 6) == 0) { if (testclass(&opt[6])) strlcpy(defclass, &opt[6], sizeof(defclass)); } else if (strncasecmp(opt, "cl=", 3) == 0) { if (testclass(&opt[3])) strlcpy(defclass, &opt[3], sizeof(defclass)); } else if (strncasecmp(opt, "type=", 5) == 0) { if (testtype(&opt[5])) { strlcpy(deftype, &opt[5], sizeof(deftype)); default_lookups = ISC_FALSE; } } else if (strncasecmp(opt, "ty=", 3) == 0) { if (testtype(&opt[3])) { strlcpy(deftype, &opt[3], sizeof(deftype)); default_lookups = ISC_FALSE; } } else if (strncasecmp(opt, "querytype=", 10) == 0) { if (testtype(&opt[10])) { strlcpy(deftype, &opt[10], sizeof(deftype)); default_lookups = ISC_FALSE; } } else if (strncasecmp(opt, "query=", 6) == 0) { if (testtype(&opt[6])) { strlcpy(deftype, &opt[6], sizeof(deftype)); default_lookups = ISC_FALSE; } } else if (strncasecmp(opt, "qu=", 3) == 0) { if (testtype(&opt[3])) { strlcpy(deftype, &opt[3], sizeof(deftype)); default_lookups = ISC_FALSE; } } else if (strncasecmp(opt, "q=", 2) == 0) { if (testtype(&opt[2])) { strlcpy(deftype, &opt[2], sizeof(deftype)); default_lookups = ISC_FALSE; } } else if (strncasecmp(opt, "domain=", 7) == 0) { strlcpy(domainopt, &opt[7], sizeof(domainopt)); set_search_domain(domainopt); usesearch = ISC_TRUE; } else if (strncasecmp(opt, "do=", 3) == 0) { strlcpy(domainopt, &opt[3], sizeof(domainopt)); set_search_domain(domainopt); usesearch = ISC_TRUE; } else if (strncasecmp(opt, "port=", 5) == 0) { set_port(&opt[5]); } else if (strncasecmp(opt, "po=", 3) == 0) { set_port(&opt[3]); } else if (strncasecmp(opt, "timeout=", 8) == 0) { set_timeout(&opt[8]); } else if (strncasecmp(opt, "t=", 2) == 0) { set_timeout(&opt[2]); } else if (CHECKOPT("recurse", 3)) { recurse = ISC_TRUE; } else if (CHECKOPT("norecurse", 5)) { recurse = ISC_FALSE; } else if (strncasecmp(opt, "retry=", 6) == 0) { set_tries(&opt[6]); } else if (strncasecmp(opt, "ret=", 4) == 0) { set_tries(&opt[4]); } else if (CHECKOPT("defname", 3)) { usesearch = ISC_TRUE; } else if (CHECKOPT("nodefname", 5)) { usesearch = ISC_FALSE; } else if (CHECKOPT("vc", 2) == 0) { tcpmode = ISC_TRUE; tcpmode_set = ISC_TRUE; } else if (CHECKOPT("novc", 4) == 0) { tcpmode = ISC_FALSE; tcpmode_set = ISC_TRUE; } else if (CHECKOPT("debug", 3) == 0) { short_form = ISC_FALSE; showsearch = ISC_TRUE; } else if (CHECKOPT("nodebug", 5) == 0) { short_form = ISC_TRUE; showsearch = ISC_FALSE; } else if (CHECKOPT("d2", 2) == 0) { debugging = ISC_TRUE; } else if (CHECKOPT("nod2", 4) == 0) { debugging = ISC_FALSE; } else if (CHECKOPT("search", 3) == 0) { usesearch = ISC_TRUE; } else if (CHECKOPT("nosearch", 5) == 0) { usesearch = ISC_FALSE; } else if (CHECKOPT("sil", 3) == 0) { /* deprecation_msg = ISC_FALSE; */ } else if (CHECKOPT("fail", 3) == 0) { nofail=ISC_FALSE; } else if (CHECKOPT("nofail", 5) == 0) { nofail=ISC_TRUE; } else if (strncasecmp(opt, "ndots=", 6) == 0) { set_ndots(&opt[6]); } else { printf("*** Invalid option: %s\n", opt); } } static void addlookup(char *opt) { dig_lookup_t *lookup; isc_result_t result; isc_textregion_t tr; dns_rdatatype_t rdtype; dns_rdataclass_t rdclass; char store[MXNAME]; debug("addlookup()"); a_noanswer = ISC_FALSE; tr.base = deftype; tr.length = strlen(deftype); result = dns_rdatatype_fromtext(&rdtype, &tr); if (result != ISC_R_SUCCESS) { printf("unknown query type: %s\n", deftype); rdclass = dns_rdatatype_a; } tr.base = defclass; tr.length = strlen(defclass); result = dns_rdataclass_fromtext(&rdclass, &tr); if (result != ISC_R_SUCCESS) { printf("unknown query class: %s\n", defclass); rdclass = dns_rdataclass_in; } lookup = make_empty_lookup(); if (get_reverse(store, sizeof(store), opt, lookup->ip6_int, ISC_TRUE) == ISC_R_SUCCESS) { strlcpy(lookup->textname, store, sizeof(lookup->textname)); lookup->rdtype = dns_rdatatype_ptr; lookup->rdtypeset = ISC_TRUE; } else { strlcpy(lookup->textname, opt, sizeof(lookup->textname)); lookup->rdtype = rdtype; lookup->rdtypeset = ISC_TRUE; } lookup->rdclass = rdclass; lookup->rdclassset = ISC_TRUE; lookup->trace = ISC_FALSE; lookup->trace_root = lookup->trace; lookup->ns_search_only = ISC_FALSE; lookup->identify = identify; lookup->recurse = recurse; lookup->aaonly = aaonly; lookup->retries = tries; lookup->udpsize = 0; lookup->comments = comments; if (lookup->rdtype == dns_rdatatype_any && !tcpmode_set) lookup->tcp_mode = ISC_TRUE; else lookup->tcp_mode = tcpmode; lookup->stats = stats; lookup->section_question = section_question; lookup->section_answer = section_answer; lookup->section_authority = section_authority; lookup->section_additional = section_additional; lookup->new_search = ISC_TRUE; if (nofail) lookup->servfail_stops = ISC_FALSE; ISC_LIST_INIT(lookup->q); ISC_LINK_INIT(lookup, link); ISC_LIST_APPEND(lookup_list, lookup, link); lookup->origin = NULL; ISC_LIST_INIT(lookup->my_server_list); debug("looking up %s", lookup->textname); } static void do_next_command(char *input) { char *ptr, *arg; ptr = next_token(&input, " \t\r\n"); if (ptr == NULL) return; arg = next_token(&input, " \t\r\n"); if ((strcasecmp(ptr, "set") == 0) && (arg != NULL)) setoption(arg); else if ((strcasecmp(ptr, "server") == 0) || (strcasecmp(ptr, "lserver") == 0)) { isc_app_block(); set_nameserver(arg); check_ra = ISC_FALSE; isc_app_unblock(); show_settings(ISC_TRUE, ISC_TRUE); } else if (strcasecmp(ptr, "exit") == 0) { in_use = ISC_FALSE; } else if (strcasecmp(ptr, "help") == 0 || strcasecmp(ptr, "?") == 0) { printf("The '%s' command is not yet implemented.\n", ptr); } else if (strcasecmp(ptr, "finger") == 0 || strcasecmp(ptr, "root") == 0 || strcasecmp(ptr, "ls") == 0 || strcasecmp(ptr, "view") == 0) { printf("The '%s' command is not implemented.\n", ptr); } else addlookup(ptr); } static void get_next_command(void) { char *buf; char *ptr; fflush(stdout); buf = isc_mem_allocate(mctx, COMMSIZE); if (buf == NULL) fatal("memory allocation failure"); isc_app_block(); if (interactive) { #ifdef HAVE_READLINE ptr = readline("> "); if (ptr != NULL) add_history(ptr); #else fputs("> ", stderr); fflush(stderr); ptr = fgets(buf, COMMSIZE, stdin); #endif } else ptr = fgets(buf, COMMSIZE, stdin); isc_app_unblock(); if (ptr == NULL) { in_use = ISC_FALSE; } else do_next_command(ptr); #ifdef HAVE_READLINE if (interactive) free(ptr); #endif isc_mem_free(mctx, buf); } static void parse_args(int argc, char **argv) { isc_boolean_t have_lookup = ISC_FALSE; usesearch = ISC_TRUE; for (argc--, argv++; argc > 0; argc--, argv++) { debug("main parsing %s", argv[0]); if (argv[0][0] == '-') { if (strncasecmp(argv[0], "-ver", 4) == 0) { version(); exit(0); } else if (argv[0][1] != 0) { setoption(&argv[0][1]); } else have_lookup = ISC_TRUE; } else { if (!have_lookup) { have_lookup = ISC_TRUE; in_use = ISC_TRUE; addlookup(argv[0]); } else { set_nameserver(argv[0]); check_ra = ISC_FALSE; } } } } static void flush_lookup_list(void) { dig_lookup_t *l, *lp; dig_query_t *q, *qp; dig_server_t *s, *sp; lookup_counter = 0; l = ISC_LIST_HEAD(lookup_list); while (l != NULL) { q = ISC_LIST_HEAD(l->q); while (q != NULL) { if (q->sock != NULL) { isc_socket_cancel(q->sock, NULL, ISC_SOCKCANCEL_ALL); isc_socket_detach(&q->sock); } if (ISC_LINK_LINKED(&q->recvbuf, link)) ISC_LIST_DEQUEUE(q->recvlist, &q->recvbuf, link); if (ISC_LINK_LINKED(&q->lengthbuf, link)) ISC_LIST_DEQUEUE(q->lengthlist, &q->lengthbuf, link); isc_buffer_invalidate(&q->recvbuf); isc_buffer_invalidate(&q->lengthbuf); qp = q; q = ISC_LIST_NEXT(q, link); ISC_LIST_DEQUEUE(l->q, qp, link); isc_mem_free(mctx, qp); } s = ISC_LIST_HEAD(l->my_server_list); while (s != NULL) { sp = s; s = ISC_LIST_NEXT(s, link); ISC_LIST_DEQUEUE(l->my_server_list, sp, link); isc_mem_free(mctx, sp); } if (l->sendmsg != NULL) dns_message_destroy(&l->sendmsg); lp = l; l = ISC_LIST_NEXT(l, link); ISC_LIST_DEQUEUE(lookup_list, lp, link); isc_mem_free(mctx, lp); } } static void getinput(isc_task_t *task, isc_event_t *event) { UNUSED(task); if (global_event == NULL) global_event = event; while (in_use) { get_next_command(); if (ISC_LIST_HEAD(lookup_list) != NULL) { start_lookup(); return; } } isc_app_shutdown(); } int main(int argc, char **argv) { isc_result_t result; interactive = ISC_TF(isatty(0)); ISC_LIST_INIT(lookup_list); ISC_LIST_INIT(server_list); ISC_LIST_INIT(search_list); check_ra = ISC_TRUE; /* setup dighost callbacks */ #ifdef DIG_SIGCHASE dighost_printrdataset = printrdataset; #endif dighost_printmessage = printmessage; dighost_received = received; dighost_trying = trying; dighost_shutdown = query_finished; result = isc_app_start(); check_result(result, "isc_app_start"); setup_libs(); progname = argv[0]; setup_system(ISC_FALSE, ISC_FALSE); parse_args(argc, argv); if (keyfile[0] != 0) setup_file_key(); else if (keysecret[0] != 0) setup_text_key(); if (domainopt[0] != '\0') set_search_domain(domainopt); if (in_use) result = isc_app_onrun(mctx, global_task, onrun_callback, NULL); else result = isc_app_onrun(mctx, global_task, getinput, NULL); check_result(result, "isc_app_onrun"); in_use = ISC_TF(!in_use); (void)isc_app_run(); puts(""); debug("done, and starting to shut down"); if (global_event != NULL) isc_event_free(&global_event); cancel_all(); destroy_libs(); isc_app_finish(); return (query_error | print_error); } bind9-9.11.3+dfsg/bin/dig/nslookup.docbook000066400000000000000000000413451325250447100202720ustar00rootroot00000000000000 2014-01-24 ISC Internet Systems Consortium, Inc. nslookup 1 BIND9 nslookup query Internet name servers interactively 2004 2005 2006 2007 2010 2013 2014 2015 2016 2017 Internet Systems Consortium, Inc. ("ISC") nslookup name | - server DESCRIPTION Nslookup is a program to query Internet domain name servers. Nslookup has two modes: interactive and non-interactive. Interactive mode allows the user to query name servers for information about various hosts and domains or to print a list of hosts in a domain. Non-interactive mode is used to print just the name and requested information for a host or domain. ARGUMENTS Interactive mode is entered in the following cases: when no arguments are given (the default name server will be used) when the first argument is a hyphen (-) and the second argument is the host name or Internet address of a name server. Non-interactive mode is used when the name or Internet address of the host to be looked up is given as the first argument. The optional second argument specifies the host name or address of a name server. Options can also be specified on the command line if they precede the arguments and are prefixed with a hyphen. For example, to change the default query type to host information, and the initial timeout to 10 seconds, type: nslookup -query=hinfo -timeout=10 The option causes nslookup to print the version number and immediately exits. INTERACTIVE COMMANDS host server Look up information for host using the current default server or using server, if specified. If host is an Internet address and the query type is A or PTR, the name of the host is returned. If host is a name and does not have a trailing period, the search list is used to qualify the name. To look up a host not in the current domain, append a period to the name. server domain lserver domain Change the default server to domain; lserver uses the initial server to look up information about domain, while server uses the current default server. If an authoritative answer can't be found, the names of servers that might have the answer are returned. root not implemented finger not implemented ls not implemented view not implemented help not implemented ? not implemented exit Exits the program. set keyword=value This command is used to change state information that affects the lookups. Valid keywords are: all Prints the current values of the frequently used options to set. Information about the current default server and host is also printed. class=value Change the query class to one of: IN the Internet class CH the Chaos class HS the Hesiod class ANY wildcard The class specifies the protocol group of the information. (Default = IN; abbreviation = cl) nodebug Turn on or off the display of the full response packet and any intermediate response packets when searching. (Default = nodebug; abbreviation = nodeb) nod2 Turn debugging mode on or off. This displays more about what nslookup is doing. (Default = nod2) domain=name Sets the search list to name. nosearch If the lookup request contains at least one period but doesn't end with a trailing period, append the domain names in the domain search list to the request until an answer is received. (Default = search) port=value Change the default TCP/UDP name server port to value. (Default = 53; abbreviation = po) querytype=value type=value Change the type of the information query. (Default = A; abbreviations = q, ty) norecurse Tell the name server to query other servers if it does not have the information. (Default = recurse; abbreviation = [no]rec) ndots=number Set the number of dots (label separators) in a domain that will disable searching. Absolute names always stop searching. retry=number Set the number of retries to number. timeout=number Change the initial timeout interval for waiting for a reply to number seconds. novc Always use a virtual circuit when sending requests to the server. (Default = novc) nofail Try the next nameserver if a nameserver responds with SERVFAIL or a referral (nofail) or terminate query (fail) on such a response. (Default = nofail) RETURN VALUES nslookup returns with an exit status of 1 if any query failed, and 0 otherwise. FILES /etc/resolv.conf SEE ALSO dig1 , host1 , named8 . bind9-9.11.3+dfsg/bin/dig/nslookup.html000066400000000000000000000322001325250447100176040ustar00rootroot00000000000000 nslookup

Name

nslookup — query Internet name servers interactively

Synopsis

nslookup [-option] [name | -] [server]

DESCRIPTION

Nslookup is a program to query Internet domain name servers. Nslookup has two modes: interactive and non-interactive. Interactive mode allows the user to query name servers for information about various hosts and domains or to print a list of hosts in a domain. Non-interactive mode is used to print just the name and requested information for a host or domain.

ARGUMENTS

Interactive mode is entered in the following cases:

  1. when no arguments are given (the default name server will be used)

  2. when the first argument is a hyphen (-) and the second argument is the host name or Internet address of a name server.

Non-interactive mode is used when the name or Internet address of the host to be looked up is given as the first argument. The optional second argument specifies the host name or address of a name server.

Options can also be specified on the command line if they precede the arguments and are prefixed with a hyphen. For example, to change the default query type to host information, and the initial timeout to 10 seconds, type:

nslookup -query=hinfo  -timeout=10

The -version option causes nslookup to print the version number and immediately exits.

INTERACTIVE COMMANDS

host [server]

Look up information for host using the current default server or using server, if specified. If host is an Internet address and the query type is A or PTR, the name of the host is returned. If host is a name and does not have a trailing period, the search list is used to qualify the name.

To look up a host not in the current domain, append a period to the name.

server domain

lserver domain

Change the default server to domain; lserver uses the initial server to look up information about domain, while server uses the current default server. If an authoritative answer can't be found, the names of servers that might have the answer are returned.

root

not implemented

finger

not implemented

ls

not implemented

view

not implemented

help

not implemented

?

not implemented

exit

Exits the program.

set keyword[=value]

This command is used to change state information that affects the lookups. Valid keywords are:

all

Prints the current values of the frequently used options to set. Information about the current default server and host is also printed.

class=value

Change the query class to one of:

IN

the Internet class

CH

the Chaos class

HS

the Hesiod class

ANY

wildcard

The class specifies the protocol group of the information.

(Default = IN; abbreviation = cl)

[no]debug

Turn on or off the display of the full response packet and any intermediate response packets when searching.

(Default = nodebug; abbreviation = [no]deb)

[no]d2

Turn debugging mode on or off. This displays more about what nslookup is doing.

(Default = nod2)

domain=name

Sets the search list to name.

[no]search

If the lookup request contains at least one period but doesn't end with a trailing period, append the domain names in the domain search list to the request until an answer is received.

(Default = search)

port=value

Change the default TCP/UDP name server port to value.

(Default = 53; abbreviation = po)

querytype=value

type=value

Change the type of the information query.

(Default = A; abbreviations = q, ty)

[no]recurse

Tell the name server to query other servers if it does not have the information.

(Default = recurse; abbreviation = [no]rec)

ndots=number

Set the number of dots (label separators) in a domain that will disable searching. Absolute names always stop searching.

retry=number

Set the number of retries to number.

timeout=number

Change the initial timeout interval for waiting for a reply to number seconds.

[no]vc

Always use a virtual circuit when sending requests to the server.

(Default = novc)

[no]fail

Try the next nameserver if a nameserver responds with SERVFAIL or a referral (nofail) or terminate query (fail) on such a response.

(Default = nofail)

RETURN VALUES

nslookup returns with an exit status of 1 if any query failed, and 0 otherwise.

FILES

/etc/resolv.conf

SEE ALSO

dig(1) , host(1) , named(8) .

bind9-9.11.3+dfsg/bin/dig/win32/000077500000000000000000000000001325250447100160115ustar00rootroot00000000000000bind9-9.11.3+dfsg/bin/dig/win32/dig.dsp.in000066400000000000000000000120731325250447100176740ustar00rootroot00000000000000# Microsoft Developer Studio Project File - Name="dig" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "@PLATFORM@ (x86) Console Application" 0x0103 CFG=dig - @PLATFORM@ Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "dig.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "dig.mak" CFG="dig - @PLATFORM@ Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "dig - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE "dig - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "dig - @PLATFORM@ Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 @COPTX@ @COPTI@ /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c # ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../include" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ @IDN_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isccfg/include" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" @CRYPTO@ /D "WIN32" /D "__STDC__" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console @MACHINE@ # ADD LINK32 user32.lib advapi32.lib ws2_32.lib Release/dighost.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/isccfg/win32/Release/libisccfg.lib ../../../lib/dns/win32/Release/libdns.lib ../../../lib/bind9/win32/Release/libbind9.lib ../../../lib/lwres/win32/Release/liblwres.lib @IDN_LIB@ /nologo /subsystem:console @MACHINE@ /out:"../../../Build/Release/dig.exe" !ELSEIF "$(CFG)" == "dig - @PLATFORM@ Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /GZ /c # ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../include" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ @IDN_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isccfg/include" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" @CRYPTO@ /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c # SUBTRACT CPP /X /u @COPTY@ # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug @MACHINE@ /pdbtype:sept # ADD LINK32 user32.lib advapi32.lib ws2_32.lib Debug/dighost.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/isccfg/win32/Debug/libisccfg.lib ../../../lib/dns/win32/Debug/libdns.lib ../../../lib/bind9/win32/Debug/libbind9.lib ../../../lib/lwres/win32/Debug/liblwres.lib @IDN_LIB@ /nologo /subsystem:console /debug @MACHINE@ /out:"../../../Build/Debug/dig.exe" /pdbtype:sept !ENDIF # Begin Target # Name "dig - @PLATFORM@ Release" # Name "dig - @PLATFORM@ Debug" # Begin Group "Source Files" # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" # Begin Source File SOURCE=..\dig.c # End Source File # End Group # Begin Group "Header Files" # PROP Default_Filter "h;hpp;hxx;hm;inl" # Begin Source File SOURCE=..\include\dig\dig.h # End Source File # End Group # Begin Group "Resource Files" # PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" # End Group # End Target # End Project bind9-9.11.3+dfsg/bin/dig/win32/dig.dsw000066400000000000000000000010231325250447100172670ustar00rootroot00000000000000Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "dig"=".\dig.dsp" - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### bind9-9.11.3+dfsg/bin/dig/win32/dig.mak.in000066400000000000000000000313551325250447100176620ustar00rootroot00000000000000# Microsoft Developer Studio Generated NMAKE File, Based on dig.dsp !IF "$(CFG)" == "" CFG=dig - @PLATFORM@ Debug !MESSAGE No configuration specified. Defaulting to dig - @PLATFORM@ Debug. !ENDIF !IF "$(CFG)" != "dig - @PLATFORM@ Release" && "$(CFG)" != "dig - @PLATFORM@ Debug" !MESSAGE Invalid configuration "$(CFG)" specified. !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "dig.mak" CFG="dig - @PLATFORM@ Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "dig - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE "dig - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE !ERROR An invalid configuration is specified. !ENDIF !IF "$(OS)" == "Windows_NT" NULL= !ELSE NULL=nul !ENDIF CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "dig - @PLATFORM@ Release" _VC_MANIFEST_INC=0 _VC_MANIFEST_BASENAME=__VC80 !ELSE _VC_MANIFEST_INC=1 _VC_MANIFEST_BASENAME=__VC80.Debug !ENDIF #################################################### # Specifying name of temporary resource file used only in incremental builds: !if "$(_VC_MANIFEST_INC)" == "1" _VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res !else _VC_MANIFEST_AUTO_RES= !endif #################################################### # _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE: !if "$(_VC_MANIFEST_INC)" == "1" #MT_SPECIAL_RETURN=1090650113 #MT_SPECIAL_SWITCH=-notify_resource_update MT_SPECIAL_RETURN=0 MT_SPECIAL_SWITCH= _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \ if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \ rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \ link $** /out:$@ $(LFLAGS) !else _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1 !endif #################################################### # _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL: !if "$(_VC_MANIFEST_INC)" == "1" #MT_SPECIAL_RETURN=1090650113 #MT_SPECIAL_SWITCH=-notify_resource_update MT_SPECIAL_RETURN=0 MT_SPECIAL_SWITCH= _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \ if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \ rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \ link $** /out:$@ $(LFLAGS) !else _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2 !endif #################################################### # _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily: !if "$(_VC_MANIFEST_INC)" == "1" _VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \ $(_VC_MANIFEST_BASENAME).auto.rc \ $(_VC_MANIFEST_BASENAME).auto.manifest !else _VC_MANIFEST_CLEAN= !endif !IF "$(CFG)" == "dig - @PLATFORM@ Release" OUTDIR=.\Release INTDIR=.\Release !IF "$(RECURSE)" == "0" ALL : "..\..\..\Build\Release\dig.exe" !ELSE ALL : "liblwres - @PLATFORM@ Release" "libbind9 - @PLATFORM@ Release" "libisc - @PLATFORM@ Release" "libdns - @PLATFORM@ Release" "..\..\..\Build\Release\dig.exe" !ENDIF !IF "$(RECURSE)" == "1" CLEAN :"libdns - @PLATFORM@ ReleaseCLEAN" "libisc - @PLATFORM@ ReleaseCLEAN" "libbind9 - @PLATFORM@ ReleaseCLEAN" "liblwres - @PLATFORM@ ReleaseCLEAN" !ELSE CLEAN : !ENDIF -@erase "$(INTDIR)\dig.obj" -@erase "$(INTDIR)\dighost.obj" -@erase "$(INTDIR)\vc60.idb" -@erase "..\..\..\Build\Release\dig.exe" -@$(_VC_MANIFEST_CLEAN) "$(OUTDIR)" : if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" CPP_PROJ=/nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../include" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ @IDN_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isccfg/include" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" @CRYPTO@ /D "WIN32" /D "__STDC__" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\dig.pch" @COPTY@ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c BSC32=bscmake.exe BSC32_FLAGS=/nologo /o"$(OUTDIR)\dig.bsc" BSC32_SBRS= \ LINK32=link.exe LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/isccfg/win32/Release/libisccfg.lib ../../../lib/dns/win32/Release/libdns.lib ../../../lib/bind9/win32/Release/libbind9.lib ../../../lib/lwres/win32/Release/liblwres.lib @IDN_LIB@ /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\dig.pdb" @MACHINE@ /out:"../../../Build/Release/dig.exe" LINK32_OBJS= \ "$(INTDIR)\dig.obj" \ "$(INTDIR)\dighost.obj" \ "..\..\..\lib\dns\win32\Release\libdns.lib" \ "..\..\..\lib\isc\win32\Release\libisc.lib" \ "..\..\..\lib\isccfg\win32\Release\libisccfg.lib" \ "..\..\..\lib\bind9\win32\Release\libbind9.lib" \ "..\..\..\lib\lwres\win32\Release\liblwres.lib" "..\..\..\Build\Release\dig.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) $(LINK32) @<< $(LINK32_FLAGS) $(LINK32_OBJS) << $(_VC_MANIFEST_EMBED_EXE) !ELSEIF "$(CFG)" == "dig - @PLATFORM@ Debug" OUTDIR=.\Debug INTDIR=.\Debug # Begin Custom Macros OutDir=.\Debug # End Custom Macros !IF "$(RECURSE)" == "0" ALL : "..\..\..\Build\Debug\dig.exe" "$(OUTDIR)\dig.bsc" !ELSE ALL : "liblwres - @PLATFORM@ Debug" "libbind9 - @PLATFORM@ Debug" "libisc - @PLATFORM@ Debug" "libdns - @PLATFORM@ Debug" "..\..\..\Build\Debug\dig.exe" "$(OUTDIR)\dig.bsc" !ENDIF !IF "$(RECURSE)" == "1" CLEAN :"libdns - @PLATFORM@ DebugCLEAN" "libisc - @PLATFORM@ DebugCLEAN" "libbind9 - @PLATFORM@ DebugCLEAN" "liblwres - @PLATFORM@ DebugCLEAN" !ELSE CLEAN : !ENDIF -@erase "$(INTDIR)\dig.obj" -@erase "$(INTDIR)\dig.sbr" -@erase "$(INTDIR)\dighost.obj" -@erase "$(INTDIR)\dighost.sbr" -@erase "$(INTDIR)\vc60.idb" -@erase "$(INTDIR)\vc60.pdb" -@erase "$(OUTDIR)\dig.bsc" -@erase "$(OUTDIR)\dig.pdb" -@erase "..\..\..\Build\Debug\dig.exe" -@erase "..\..\..\Build\Debug\dig.ilk" -@$(_VC_MANIFEST_CLEAN) "$(OUTDIR)" : if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" CPP_PROJ=/nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../include" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ @IDN_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isccfg/include" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" @CRYPTO@ /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c BSC32=bscmake.exe BSC32_FLAGS=/nologo /o"$(OUTDIR)\dig.bsc" BSC32_SBRS= \ "$(INTDIR)\dig.sbr" \ "$(INTDIR)\dighost.sbr" "$(OUTDIR)\dig.bsc" : "$(OUTDIR)" $(BSC32_SBRS) $(BSC32) @<< $(BSC32_FLAGS) $(BSC32_SBRS) << LINK32=link.exe LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/isccfg/win32/Debug/libisccfg.lib ../../../lib/dns/win32/Debug/libdns.lib ../../../lib/bind9/win32/Debug/libbind9.lib ../../../lib/lwres/win32/Debug/liblwres.lib @IDN_LIB@ /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\dig.pdb" /debug @MACHINE@ /out:"../../../Build/Debug/dig.exe" /pdbtype:sept LINK32_OBJS= \ "$(INTDIR)\dig.obj" \ "$(INTDIR)\dighost.obj" \ "..\..\..\lib\dns\win32\Debug\libdns.lib" \ "..\..\..\lib\isc\win32\Debug\libisc.lib" \ "..\..\..\lib\isccfg\win32\Debug\libisccfg.lib" \ "..\..\..\lib\bind9\win32\Debug\libbind9.lib" \ "..\..\..\lib\lwres\win32\Debug\liblwres.lib" "..\..\..\Build\Debug\dig.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) $(LINK32) @<< $(LINK32_FLAGS) $(LINK32_OBJS) << $(_VC_MANIFEST_EMBED_EXE) !ENDIF .c{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .c{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << !IF "$(NO_EXTERNAL_DEPS)" != "1" !IF EXISTS("dig.dep") !INCLUDE "dig.dep" !ELSE !MESSAGE Warning: cannot find "dig.dep" !ENDIF !ENDIF !IF "$(CFG)" == "dig - @PLATFORM@ Release" || "$(CFG)" == "dig - @PLATFORM@ Debug" SOURCE=..\dig.c !IF "$(CFG)" == "dig - @PLATFORM@ Release" "$(INTDIR)\dig.obj" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ELSEIF "$(CFG)" == "dig - @PLATFORM@ Debug" "$(INTDIR)\dig.obj" "$(INTDIR)\dig.sbr" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ENDIF SOURCE=..\dighost.c !IF "$(CFG)" == "dig - @PLATFORM@ Release" "$(INTDIR)\dighost.obj" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ELSEIF "$(CFG)" == "dig - @PLATFORM@ Debug" "$(INTDIR)\dighost.obj" "$(INTDIR)\dighost.sbr" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ENDIF !IF "$(CFG)" == "dig - @PLATFORM@ Release" "libdns - @PLATFORM@ Release" : cd "..\..\..\lib\dns\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Release" cd "..\..\..\bin\dig\win32" "libdns - @PLATFORM@ ReleaseCLEAN" : cd "..\..\..\lib\dns\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Release" RECURSE=1 CLEAN cd "..\..\..\bin\dig\win32" !ELSEIF "$(CFG)" == "dig - @PLATFORM@ Debug" "libdns - @PLATFORM@ Debug" : cd "..\..\..\lib\dns\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Debug" cd "..\..\..\bin\dig\win32" "libdns - @PLATFORM@ DebugCLEAN" : cd "..\..\..\lib\dns\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Debug" RECURSE=1 CLEAN cd "..\..\..\bin\dig\win32" !ENDIF !IF "$(CFG)" == "dig - @PLATFORM@ Release" "libisc - @PLATFORM@ Release" : cd "..\..\..\lib\isc\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Release" cd "..\..\..\bin\dig\win32" "libisc - @PLATFORM@ ReleaseCLEAN" : cd "..\..\..\lib\isc\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Release" RECURSE=1 CLEAN cd "..\..\..\bin\dig\win32" !ELSEIF "$(CFG)" == "dig - @PLATFORM@ Debug" "libisc - @PLATFORM@ Debug" : cd "..\..\..\lib\isc\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Debug" cd "..\..\..\bin\dig\win32" "libisc - @PLATFORM@ DebugCLEAN" : cd "..\..\..\lib\isc\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Debug" RECURSE=1 CLEAN cd "..\..\..\bin\dig\win32" !ENDIF !IF "$(CFG)" == "dig - @PLATFORM@ Release" "libbind9 - @PLATFORM@ Release" : cd "..\..\..\lib\bind9\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - @PLATFORM@ Release" cd "..\..\..\bin\dig\win32" "libbind9 - @PLATFORM@ ReleaseCLEAN" : cd "..\..\..\lib\bind9\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - @PLATFORM@ Release" RECURSE=1 CLEAN cd "..\..\..\bin\dig\win32" !ELSEIF "$(CFG)" == "dig - @PLATFORM@ Debug" "libbind9 - @PLATFORM@ Debug" : cd "..\..\..\lib\bind9\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - @PLATFORM@ Debug" cd "..\..\..\bin\dig\win32" "libbind9 - @PLATFORM@ DebugCLEAN" : cd "..\..\..\lib\bind9\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - @PLATFORM@ Debug" RECURSE=1 CLEAN cd "..\..\..\bin\dig\win32" !ENDIF !IF "$(CFG)" == "dig - @PLATFORM@ Release" "liblwres - @PLATFORM@ Release" : cd "..\..\..\lib\lwres\win32" $(MAKE) /$(MAKEFLAGS) /F ".\liblwres.mak" CFG="liblwres - @PLATFORM@ Release" cd "..\..\..\bin\dig\win32" "liblwres - @PLATFORM@ ReleaseCLEAN" : cd "..\..\..\lib\lwres\win32" $(MAKE) /$(MAKEFLAGS) /F ".\liblwres.mak" CFG="liblwres - @PLATFORM@ Release" RECURSE=1 CLEAN cd "..\..\..\bin\dig\win32" !ELSEIF "$(CFG)" == "dig - @PLATFORM@ Debug" "liblwres - @PLATFORM@ Debug" : cd "..\..\..\lib\lwres\win32" $(MAKE) /$(MAKEFLAGS) /F ".\liblwres.mak" CFG="liblwres - @PLATFORM@ Debug" cd "..\..\..\bin\dig\win32" "liblwres - @PLATFORM@ DebugCLEAN" : cd "..\..\..\lib\lwres\win32" $(MAKE) /$(MAKEFLAGS) /F ".\liblwres.mak" CFG="liblwres - @PLATFORM@ Debug" RECURSE=1 CLEAN cd "..\..\..\bin\dig\win32" !ENDIF !ENDIF #################################################### # Commands to generate initial empty manifest file and the RC file # that references it, and for generating the .res file: $(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc $(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest type <<$@ #include 1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest" << KEEP $(_VC_MANIFEST_BASENAME).auto.manifest : type <<$@ << KEEP bind9-9.11.3+dfsg/bin/dig/win32/dig.vcxproj.filters.in000066400000000000000000000020771325250447100222530ustar00rootroot00000000000000 {4FC737F1-C7A5-4376-A066-2A32D752A2FF} cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx {93995380-89BD-4b04-88EB-625FBE52EBFB} h;hpp;hxx;hm;inl;inc;xsd {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms Header Files Source Files bind9-9.11.3+dfsg/bin/dig/win32/dig.vcxproj.in000066400000000000000000000162161325250447100206040ustar00rootroot00000000000000 Debug @PLATFORM@ Release @PLATFORM@ {F938F9B8-D395-4A40-BEC7-0122D289C692} Win32Proj dig Application true MultiByte Application false true MultiByte true ..\..\..\Build\$(Configuration)\ .\$(Configuration)\ false ..\..\..\Build\$(Configuration)\ .\$(Configuration)\ Level3 Disabled WIN32;@CRYPTO@_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true .\$(Configuration)\$(TargetName).pch .\$(Configuration)\ .\$(Configuration)\ $(OutDir)$(TargetName).pdb true .\;..\include;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@@IDN_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\isccfg\include;..\..\..\lib\dns\include;..\..\..\lib\bind9\include;..\..\..\lib\lwres\win32\include;..\..\..\lib\lwres\include;%(AdditionalIncludeDirectories) CompileAsC Console true ..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt) $(Configuration);..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\isccfg\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);..\..\..\lib\bind9\win32\$(Configuration);..\..\..\lib\lwres\win32\$(Configuration);%(AdditionalLibraryDirectories) dighost.lib;libisc.lib;libisccfg.lib;libdns.lib;libbind9.lib;liblwres.lib;@IDN_LIB@ws2_32.lib;%(AdditionalDependencies) Level3 MaxSpeed true @INTRINSIC@ WIN32;@CRYPTO@NDEBUG;_CONSOLE;%(PreprocessorDefinitions) OnlyExplicitInline false true .\$(Configuration)\$(TargetName).pch .\$(Configuration)\ .\$(Configuration)\ $(OutDir)$(TargetName).pdb .\;..\include;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@@IDN_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\isccfg\include;..\..\..\lib\dns\include;..\..\..\lib\bind9\include;..\..\..\lib\lwres\win32\include;..\..\..\lib\lwres\include;%(AdditionalIncludeDirectories) CompileAsC Console false true true ..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt) Default $(Configuration);..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\isccfg\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);..\..\..\lib\bind9\win32\$(Configuration);..\..\..\lib\lwres\win32\$(Configuration);%(AdditionalLibraryDirectories) dighost.lib;libisc.lib;libisccfg.lib;libdns.lib;libbind9.lib;liblwres.lib;@IDN_LIB@ws2_32.lib;%(AdditionalDependencies) bind9-9.11.3+dfsg/bin/dig/win32/dig.vcxproj.user000066400000000000000000000002171325250447100211460ustar00rootroot00000000000000 bind9-9.11.3+dfsg/bin/dig/win32/dighost.dsp.in000066400000000000000000000101361325250447100205700ustar00rootroot00000000000000# Microsoft Developer Studio Project File - Name="dighost" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "@PLATFORM@ (x86) Static-Link Library" 0x0104 CFG=dighost - @PLATFORM@ Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "dighost.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "dighost.mak" CFG="dighost - @PLATFORM@ Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "dighost - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Static-Link Library") !MESSAGE "dighost - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Static-Link Library") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe MTL=midl.exe RSC=rc.exe !IF "$(CFG)" == "dighost - @PLATFORM@ Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MT /W3 @COPTX@ @COPTI@ /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" @COPTY@ /FD /c # ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ @IDN_INC@ /I "../include" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isccfg/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /D "NDEBUG" @CRYPTO@ /D "WIN32" /D "_WINDOWS" /D "__STDC__" /D "_MBCS" @COPTY@ /FD /c /Fddighost # SUBTRACT CPP /X # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 # ADD LINK32 /out:"Release/dighost.lib" !ELSEIF "$(CFG)" == "dighost - @PLATFORM@ Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MTd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" @COPTY@ /FD /GZ /c # ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ @IDN_INC@ /I "../include" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isccfg/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" @CRYPTO@ /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "__STDC__" /D "_MBCS" /FR @COPTY@ /FD /GZ /c /Fddighost # SUBTRACT CPP /X # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 # ADD LINK32 /debug out:"Debug/dighost.lib" !ENDIF # Begin Target # Name "dighost - @PLATFORM@ Release" # Name "dighost - @PLATFORM@ Debug" # Begin Group "Source Files" # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" # End Group # Begin Group "Header Files" # PROP Default_Filter "h;hpp;hxx;hm;inl" # End Group # Begin Group "Resource Files" # PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" # End Group # Begin Group "Main Dns Lib" # PROP Default_Filter "c" # Begin Source File SOURCE=..\dighost.c # End Source File # End Group # End Target # End Project bind9-9.11.3+dfsg/bin/dig/win32/dighost.dsw000066400000000000000000000010331325250447100201660ustar00rootroot00000000000000Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "dighost"=".\dighost.dsp" - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### bind9-9.11.3+dfsg/bin/dig/win32/dighost.vcxproj.filters.in000066400000000000000000000013751325250447100231510ustar00rootroot00000000000000 {4FC737F1-C7A5-4376-A066-2A32D752A2FF} cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms Source Files bind9-9.11.3+dfsg/bin/dig/win32/dighost.vcxproj.in000066400000000000000000000141051325250447100214750ustar00rootroot00000000000000 Debug @PLATFORM@ Release @PLATFORM@ {140DE800-E552-43CC-B0C7-A33A92E368CA} Win32Proj dighost StaticLibrary true MultiByte StaticLibrary false true MultiByte true .\$(Configuration)\ .\$(Configuration)\ false .\$(Configuration)\ .\$(Configuration)\ Level3 Disabled WIN32;@CRYPTO@_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true .\$(Configuration)\$(TargetName).pch .\$(Configuration)\ .\$(Configuration)\ $(OutDir)$(TargetName).pdb true .\;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@@IDN_INC@..\include;..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\isccfg\include;..\..\..\lib\lwres\win32\include;..\..\..\lib\lwres\include;..\..\..\lib\dns\include;..\..\..\lib\bind9\include;%(AdditionalIncludeDirectories) CompileAsC Console true ..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt) Level3 MaxSpeed true @INTRINSIC@ WIN32;@CRYPTO@NDEBUG;_CONSOLE;%(PreprocessorDefinitions) OnlyExplicitInline false true .\$(Configuration)\$(TargetName).pch .\$(Configuration)\ .\$(Configuration)\ $(OutDir)$(TargetName).pdb .\;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@@IDN_INC@..\include;..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\isccfg\include;..\..\..\lib\lwres\win32\include;..\..\..\lib\lwres\include;..\..\..\lib\dns\include;..\..\..\lib\bind9\include;%(AdditionalIncludeDirectories) CompileAsC Console false true true ..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt) false bind9-9.11.3+dfsg/bin/dig/win32/dighost.vcxproj.user000066400000000000000000000002171325250447100220440ustar00rootroot00000000000000 bind9-9.11.3+dfsg/bin/dig/win32/host.dsp.in000066400000000000000000000120061325250447100201020ustar00rootroot00000000000000# Microsoft Developer Studio Project File - Name="host" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "@PLATFORM@ (x86) Console Application" 0x0103 CFG=host - @PLATFORM@ Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "host.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "host.mak" CFG="host - @PLATFORM@ Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "host - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE "host - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "host - @PLATFORM@ Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 @COPTX@ @COPTI@ /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c # ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../include" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ @IDN_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isccfg/include" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" @CRYPTO@ /D "WIN32" /D "__STDC__" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console @MACHINE@ # ADD LINK32 user32.lib advapi32.lib ws2_32.lib Release/dighost.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/isccfg/win32/Release/libisccfg.lib ../../../lib/dns/win32/Release/libdns.lib ../../../lib/bind9/win32/Release/libbind9.lib ../../../lib/lwres/win32/Release/liblwres.lib @IDN_LIB@ /nologo /subsystem:console @MACHINE@ /out:"../../../Build/Release/host.exe" !ELSEIF "$(CFG)" == "host - @PLATFORM@ Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /GZ /c # ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../include" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ @IDN_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isccfg/include" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" @CRYPTO@ /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c # SUBTRACT CPP /X /u @COPTY@ # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug @MACHINE@ /pdbtype:sept # ADD LINK32 user32.lib advapi32.lib ws2_32.lib Debug/dighost.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/isccfg/win32/Debug/libisccfg.lib ../../../lib/dns/win32/Debug/libdns.lib ../../../lib/bind9/win32/Debug/libbind9.lib ../../../lib/lwres/win32/Debug/liblwres.lib @IDN_LIB@ /nologo /subsystem:console /debug @MACHINE@ /out:"../../../Build/Debug/host.exe" /pdbtype:sept !ENDIF # Begin Target # Name "host - @PLATFORM@ Release" # Name "host - @PLATFORM@ Debug" # Begin Group "Source Files" # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" # Begin Source File SOURCE=..\host.c # End Source File # End Group # Begin Group "Header Files" # PROP Default_Filter "h;hpp;hxx;hm;inl" # End Group # Begin Group "Resource Files" # PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" # End Group # End Target # End Project bind9-9.11.3+dfsg/bin/dig/win32/host.dsw000066400000000000000000000010251325250447100175030ustar00rootroot00000000000000Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "host"=".\host.dsp" - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### bind9-9.11.3+dfsg/bin/dig/win32/host.mak.in000066400000000000000000000314531325250447100200730ustar00rootroot00000000000000# Microsoft Developer Studio Generated NMAKE File, Based on host.dsp !IF "$(CFG)" == "" CFG=host - @PLATFORM@ Debug !MESSAGE No configuration specified. Defaulting to host - @PLATFORM@ Debug. !ENDIF !IF "$(CFG)" != "host - @PLATFORM@ Release" && "$(CFG)" != "host - @PLATFORM@ Debug" !MESSAGE Invalid configuration "$(CFG)" specified. !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "host.mak" CFG="host - @PLATFORM@ Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "host - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE "host - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE !ERROR An invalid configuration is specified. !ENDIF !IF "$(OS)" == "Windows_NT" NULL= !ELSE NULL=nul !ENDIF CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "host - @PLATFORM@ Release" _VC_MANIFEST_INC=0 _VC_MANIFEST_BASENAME=__VC80 !ELSE _VC_MANIFEST_INC=1 _VC_MANIFEST_BASENAME=__VC80.Debug !ENDIF #################################################### # Specifying name of temporary resource file used only in incremental builds: !if "$(_VC_MANIFEST_INC)" == "1" _VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res !else _VC_MANIFEST_AUTO_RES= !endif #################################################### # _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE: !if "$(_VC_MANIFEST_INC)" == "1" #MT_SPECIAL_RETURN=1090650113 #MT_SPECIAL_SWITCH=-notify_resource_update MT_SPECIAL_RETURN=0 MT_SPECIAL_SWITCH= _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \ if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \ rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \ link $** /out:$@ $(LFLAGS) !else _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1 !endif #################################################### # _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL: !if "$(_VC_MANIFEST_INC)" == "1" #MT_SPECIAL_RETURN=1090650113 #MT_SPECIAL_SWITCH=-notify_resource_update MT_SPECIAL_RETURN=0 MT_SPECIAL_SWITCH= _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \ if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \ rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \ link $** /out:$@ $(LFLAGS) !else _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2 !endif #################################################### # _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily: !if "$(_VC_MANIFEST_INC)" == "1" _VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \ $(_VC_MANIFEST_BASENAME).auto.rc \ $(_VC_MANIFEST_BASENAME).auto.manifest !else _VC_MANIFEST_CLEAN= !endif !IF "$(CFG)" == "host - @PLATFORM@ Release" OUTDIR=.\Release INTDIR=.\Release !IF "$(RECURSE)" == "0" ALL : "..\..\..\Build\Release\host.exe" !ELSE ALL : "liblwres - @PLATFORM@ Release" "libbind9 - @PLATFORM@ Release" "libisc - @PLATFORM@ Release" "libdns - @PLATFORM@ Release" "..\..\..\Build\Release\host.exe" !ENDIF !IF "$(RECURSE)" == "1" CLEAN :"libdns - @PLATFORM@ ReleaseCLEAN" "libisc - @PLATFORM@ ReleaseCLEAN" "libbind9 - @PLATFORM@ ReleaseCLEAN" "liblwres - @PLATFORM@ ReleaseCLEAN" !ELSE CLEAN : !ENDIF -@erase "$(INTDIR)\dighost.obj" -@erase "$(INTDIR)\host.obj" -@erase "$(INTDIR)\vc60.idb" -@erase "..\..\..\Build\Release\host.exe" -@$(_VC_MANIFEST_CLEAN) "$(OUTDIR)" : if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" CPP_PROJ=/nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../include" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ @IDN_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isccfg/include" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" @CRYPTO@ /D "WIN32" /D "__STDC__" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\host.pch" @COPTY@ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c BSC32=bscmake.exe BSC32_FLAGS=/nologo /o"$(OUTDIR)\host.bsc" BSC32_SBRS= \ LINK32=link.exe LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/isccfg/win32/Release/libisccfg.lib ../../../lib/dns/win32/Release/libdns.lib ../../../lib/bind9/win32/Release/libbind9.lib ../../../lib/lwres/win32/Release/liblwres.lib @IDN_LIB@ /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\host.pdb" @MACHINE@ /out:"../../../Build/Release/host.exe" LINK32_OBJS= \ "$(INTDIR)\dighost.obj" \ "$(INTDIR)\host.obj" \ "..\..\..\lib\dns\win32\Release\libdns.lib" \ "..\..\..\lib\isc\win32\Release\libisc.lib" \ "..\..\..\lib\isccfg\win32\Release\libisccfg.lib" \ "..\..\..\lib\bind9\win32\Release\libbind9.lib" \ "..\..\..\lib\lwres\win32\Release\liblwres.lib" "..\..\..\Build\Release\host.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) $(LINK32) @<< $(LINK32_FLAGS) $(LINK32_OBJS) << $(_VC_MANIFEST_EMBED_EXE) !ELSEIF "$(CFG)" == "host - @PLATFORM@ Debug" OUTDIR=.\Debug INTDIR=.\Debug # Begin Custom Macros OutDir=.\Debug # End Custom Macros !IF "$(RECURSE)" == "0" ALL : "..\..\..\Build\Debug\host.exe" "$(OUTDIR)\host.bsc" !ELSE ALL : "liblwres - @PLATFORM@ Debug" "libbind9 - @PLATFORM@ Debug" "libisc - @PLATFORM@ Debug" "libdns - @PLATFORM@ Debug" "..\..\..\Build\Debug\host.exe" "$(OUTDIR)\host.bsc" !ENDIF !IF "$(RECURSE)" == "1" CLEAN :"libdns - @PLATFORM@ DebugCLEAN" "libisc - @PLATFORM@ DebugCLEAN" "libbind9 - @PLATFORM@ DebugCLEAN" "liblwres - @PLATFORM@ DebugCLEAN" !ELSE CLEAN : !ENDIF -@erase "$(INTDIR)\dighost.obj" -@erase "$(INTDIR)\dighost.sbr" -@erase "$(INTDIR)\host.obj" -@erase "$(INTDIR)\host.sbr" -@erase "$(INTDIR)\vc60.idb" -@erase "$(INTDIR)\vc60.pdb" -@erase "$(OUTDIR)\host.bsc" -@erase "$(OUTDIR)\host.pdb" -@erase "..\..\..\Build\Debug\host.exe" -@erase "..\..\..\Build\Debug\host.ilk" -@$(_VC_MANIFEST_CLEAN) "$(OUTDIR)" : if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" CPP_PROJ=/nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../include" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ @IDN_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isccfg/include" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" @CRYPTO@ /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c BSC32=bscmake.exe BSC32_FLAGS=/nologo /o"$(OUTDIR)\host.bsc" BSC32_SBRS= \ "$(INTDIR)\dighost.sbr" \ "$(INTDIR)\host.sbr" "$(OUTDIR)\host.bsc" : "$(OUTDIR)" $(BSC32_SBRS) $(BSC32) @<< $(BSC32_FLAGS) $(BSC32_SBRS) << LINK32=link.exe LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/isccfg/win32/Debug/libisccfg.lib ../../../lib/dns/win32/Debug/libdns.lib ../../../lib/bind9/win32/Debug/libbind9.lib ../../../lib/lwres/win32/Debug/liblwres.lib @IDN_LIB@ /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\host.pdb" /debug @MACHINE@ /out:"../../../Build/Debug/host.exe" /pdbtype:sept LINK32_OBJS= \ "$(INTDIR)\dighost.obj" \ "$(INTDIR)\host.obj" \ "..\..\..\lib\dns\win32\Debug\libdns.lib" \ "..\..\..\lib\isc\win32\Debug\libisc.lib" \ "..\..\..\lib\isccfg\win32\Debug\libisccfg.lib" \ "..\..\..\lib\bind9\win32\Debug\libbind9.lib" \ "..\..\..\lib\lwres\win32\Debug\liblwres.lib" "..\..\..\Build\Debug\host.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) $(LINK32) @<< $(LINK32_FLAGS) $(LINK32_OBJS) << $(_VC_MANIFEST_EMBED_EXE) !ENDIF .c{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .c{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << !IF "$(NO_EXTERNAL_DEPS)" != "1" !IF EXISTS("host.dep") !INCLUDE "host.dep" !ELSE !MESSAGE Warning: cannot find "host.dep" !ENDIF !ENDIF !IF "$(CFG)" == "host - @PLATFORM@ Release" || "$(CFG)" == "host - @PLATFORM@ Debug" SOURCE=..\dighost.c !IF "$(CFG)" == "host - @PLATFORM@ Release" "$(INTDIR)\dighost.obj" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ELSEIF "$(CFG)" == "host - @PLATFORM@ Debug" "$(INTDIR)\dighost.obj" "$(INTDIR)\dighost.sbr" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ENDIF SOURCE=..\host.c !IF "$(CFG)" == "host - @PLATFORM@ Release" "$(INTDIR)\host.obj" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ELSEIF "$(CFG)" == "host - @PLATFORM@ Debug" "$(INTDIR)\host.obj" "$(INTDIR)\host.sbr" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ENDIF !IF "$(CFG)" == "host - @PLATFORM@ Release" "libdns - @PLATFORM@ Release" : cd "..\..\..\lib\dns\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Release" cd "..\..\..\bin\dig\win32" "libdns - @PLATFORM@ ReleaseCLEAN" : cd "..\..\..\lib\dns\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Release" RECURSE=1 CLEAN cd "..\..\..\bin\dig\win32" !ELSEIF "$(CFG)" == "host - @PLATFORM@ Debug" "libdns - @PLATFORM@ Debug" : cd "..\..\..\lib\dns\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Debug" cd "..\..\..\bin\dig\win32" "libdns - @PLATFORM@ DebugCLEAN" : cd "..\..\..\lib\dns\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Debug" RECURSE=1 CLEAN cd "..\..\..\bin\dig\win32" !ENDIF !IF "$(CFG)" == "host - @PLATFORM@ Release" "libisc - @PLATFORM@ Release" : cd "..\..\..\lib\isc\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Release" cd "..\..\..\bin\dig\win32" "libisc - @PLATFORM@ ReleaseCLEAN" : cd "..\..\..\lib\isc\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Release" RECURSE=1 CLEAN cd "..\..\..\bin\dig\win32" !ELSEIF "$(CFG)" == "host - @PLATFORM@ Debug" "libisc - @PLATFORM@ Debug" : cd "..\..\..\lib\isc\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Debug" cd "..\..\..\bin\dig\win32" "libisc - @PLATFORM@ DebugCLEAN" : cd "..\..\..\lib\isc\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Debug" RECURSE=1 CLEAN cd "..\..\..\bin\dig\win32" !ENDIF !IF "$(CFG)" == "host - @PLATFORM@ Release" "libbind9 - @PLATFORM@ Release" : cd "..\..\..\lib\bind9\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - @PLATFORM@ Release" cd "..\..\..\bin\dig\win32" "libbind9 - @PLATFORM@ ReleaseCLEAN" : cd "..\..\..\lib\bind9\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - @PLATFORM@ Release" RECURSE=1 CLEAN cd "..\..\..\bin\dig\win32" !ELSEIF "$(CFG)" == "host - @PLATFORM@ Debug" "libbind9 - @PLATFORM@ Debug" : cd "..\..\..\lib\bind9\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - @PLATFORM@ Debug" cd "..\..\..\bin\dig\win32" "libbind9 - @PLATFORM@ DebugCLEAN" : cd "..\..\..\lib\bind9\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - @PLATFORM@ Debug" RECURSE=1 CLEAN cd "..\..\..\bin\dig\win32" !ENDIF !IF "$(CFG)" == "host - @PLATFORM@ Release" "liblwres - @PLATFORM@ Release" : cd "..\..\..\lib\lwres\win32" $(MAKE) /$(MAKEFLAGS) /F ".\liblwres.mak" CFG="liblwres - @PLATFORM@ Release" cd "..\..\..\bin\dig\win32" "liblwres - @PLATFORM@ ReleaseCLEAN" : cd "..\..\..\lib\lwres\win32" $(MAKE) /$(MAKEFLAGS) /F ".\liblwres.mak" CFG="liblwres - @PLATFORM@ Release" RECURSE=1 CLEAN cd "..\..\..\bin\dig\win32" !ELSEIF "$(CFG)" == "host - @PLATFORM@ Debug" "liblwres - @PLATFORM@ Debug" : cd "..\..\..\lib\lwres\win32" $(MAKE) /$(MAKEFLAGS) /F ".\liblwres.mak" CFG="liblwres - @PLATFORM@ Debug" cd "..\..\..\bin\dig\win32" "liblwres - @PLATFORM@ DebugCLEAN" : cd "..\..\..\lib\lwres\win32" $(MAKE) /$(MAKEFLAGS) /F ".\liblwres.mak" CFG="liblwres - @PLATFORM@ Debug" RECURSE=1 CLEAN cd "..\..\..\bin\dig\win32" !ENDIF !ENDIF #################################################### # Commands to generate initial empty manifest file and the RC file # that references it, and for generating the .res file: $(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc $(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest type <<$@ #include 1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest" << KEEP $(_VC_MANIFEST_BASENAME).auto.manifest : type <<$@ << KEEP bind9-9.11.3+dfsg/bin/dig/win32/host.vcxproj.filters.in000066400000000000000000000013721325250447100224620ustar00rootroot00000000000000 {4FC737F1-C7A5-4376-A066-2A32D752A2FF} cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms Source Files bind9-9.11.3+dfsg/bin/dig/win32/host.vcxproj.in000066400000000000000000000160771325250447100210230ustar00rootroot00000000000000 Debug @PLATFORM@ Release @PLATFORM@ {BA1048A8-6961-4A20-BE12-08BE20611C9D} Win32Proj host Application true MultiByte Application false true MultiByte true ..\..\..\Build\$(Configuration)\ .\$(Configuration)\ false ..\..\..\Build\$(Configuration)\ .\$(Configuration)\ Level3 Disabled WIN32;@CRYPTO@_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true .\$(Configuration)\$(TargetName).pch .\$(Configuration)\ .\$(Configuration)\ $(OutDir)$(TargetName).pdb true .\;..\include;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@@IDN_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\isccfg\include;..\..\..\lib\dns\include;..\..\..\lib\bind9\include;..\..\..\lib\lwres\win32\include;..\..\..\lib\lwres\include;%(AdditionalIncludeDirectories) CompileAsC Console true ..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt) $(Configuration);..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\isccfg\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);..\..\..\lib\bind9\win32\$(Configuration);..\..\..\lib\lwres\win32\$(Configuration);%(AdditionalLibraryDirectories) dighost.lib;@IDN_LIB@libisc.lib;libisccfg.lib;libdns.lib;libbind9.lib;liblwres.lib;ws2_32.lib;%(AdditionalDependencies) Level3 MaxSpeed true @INTRINSIC@ WIN32;@CRYPTO@NDEBUG;_CONSOLE;%(PreprocessorDefinitions) OnlyExplicitInline false true .\$(Configuration)\$(TargetName).pch .\$(Configuration)\ .\$(Configuration)\ $(OutDir)$(TargetName).pdb .\;..\include;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@@IDN_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\isccfg\include;..\..\..\lib\dns\include;..\..\..\lib\bind9\include;..\..\..\lib\lwres\win32\include;..\..\..\lib\lwres\include;%(AdditionalIncludeDirectories) CompileAsC Console false true true ..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt) Default $(Configuration);..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\isccfg\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);..\..\..\lib\bind9\win32\$(Configuration);..\..\..\lib\lwres\win32\$(Configuration);%(AdditionalLibraryDirectories) dighost.lib;@IDN_LIB@libisc.lib;libisccfg.lib;libdns.lib;libbind9.lib;liblwres.lib;ws2_32.lib;%(AdditionalDependencies) bind9-9.11.3+dfsg/bin/dig/win32/host.vcxproj.user000066400000000000000000000002171325250447100213600ustar00rootroot00000000000000 bind9-9.11.3+dfsg/bin/dig/win32/nslookup.dsp.in000066400000000000000000000122561325250447100210060ustar00rootroot00000000000000# Microsoft Developer Studio Project File - Name="nslookup" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "@PLATFORM@ (x86) Console Application" 0x0103 CFG=nslookup - @PLATFORM@ Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "nslookup.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "nslookup.mak" CFG="nslookup - @PLATFORM@ Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "nslookup - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE "nslookup - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "nslookup - @PLATFORM@ Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 @COPTX@ @COPTI@ /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c # ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../include" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ @READLINE_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isccfg/include" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" @CRYPTO@ /D "WIN32" /D "USE_READLINE_STATIC" /D "__STDC__" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console @MACHINE@ # ADD LINK32 @READLINE_LIB@ @IDN_LIB@ user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/isccfg/win32/Release/libisccfg.lib ../../../lib/dns/win32/Release/libdns.lib ../../../lib/bind9/win32/Release/libbind9.lib ../../../lib/lwres/win32/Release/liblwres.lib /nologo /subsystem:console @MACHINE@ /out:"../../../Build/Release/nslookup.exe" !ELSEIF "$(CFG)" == "nslookup - @PLATFORM@ Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /GZ /c # ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../include" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ @READLINE_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isccfg/include" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" @CRYPTO@ /D "WIN32" /D "USE_READLINE_STATIC" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c # SUBTRACT CPP /X /u @COPTY@ # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug @MACHINE@ /pdbtype:sept # ADD LINK32 @READLINE_LIBD@ @IDN_LIB@ user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/isccfg/win32/Debug/libisccfg.lib ../../../lib/dns/win32/Debug/libdns.lib ../../../lib/bind9/win32/Debug/libbind9.lib ../../../lib/lwres/win32/Debug/liblwres.lib /nologo /subsystem:console /debug @MACHINE@ /out:"../../../Build/Debug/nslookup.exe" /pdbtype:sept !ENDIF # Begin Target # Name "nslookup - @PLATFORM@ Release" # Name "nslookup - @PLATFORM@ Debug" # Begin Group "Source Files" # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" # Begin Source File SOURCE=..\dighost.c # End Source File # Begin Source File SOURCE=..\nslookup.c # End Source File # End Group # Begin Group "Header Files" # PROP Default_Filter "h;hpp;hxx;hm;inl" # End Group # Begin Group "Resource Files" # PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" # End Group # End Target # End Project bind9-9.11.3+dfsg/bin/dig/win32/nslookup.dsw000066400000000000000000000010351325250447100204010ustar00rootroot00000000000000Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "nslookup"=".\nslookup.dsp" - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### bind9-9.11.3+dfsg/bin/dig/win32/nslookup.mak.in000066400000000000000000000321661325250447100207720ustar00rootroot00000000000000# Microsoft Developer Studio Generated NMAKE File, Based on nslookup.dsp !IF "$(CFG)" == "" CFG=nslookup - @PLATFORM@ Debug !MESSAGE No configuration specified. Defaulting to nslookup - @PLATFORM@ Debug. !ENDIF !IF "$(CFG)" != "nslookup - @PLATFORM@ Release" && "$(CFG)" != "nslookup - @PLATFORM@ Debug" !MESSAGE Invalid configuration "$(CFG)" specified. !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "nslookup.mak" CFG="nslookup - @PLATFORM@ Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "nslookup - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE "nslookup - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE !ERROR An invalid configuration is specified. !ENDIF !IF "$(OS)" == "Windows_NT" NULL= !ELSE NULL=nul !ENDIF CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "nslookup - @PLATFORM@ Release" _VC_MANIFEST_INC=0 _VC_MANIFEST_BASENAME=__VC80 !ELSE _VC_MANIFEST_INC=1 _VC_MANIFEST_BASENAME=__VC80.Debug !ENDIF #################################################### # Specifying name of temporary resource file used only in incremental builds: !if "$(_VC_MANIFEST_INC)" == "1" _VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res !else _VC_MANIFEST_AUTO_RES= !endif #################################################### # _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE: !if "$(_VC_MANIFEST_INC)" == "1" #MT_SPECIAL_RETURN=1090650113 #MT_SPECIAL_SWITCH=-notify_resource_update MT_SPECIAL_RETURN=0 MT_SPECIAL_SWITCH= _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \ if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \ rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \ link $** /out:$@ $(LFLAGS) !else _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1 !endif #################################################### # _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL: !if "$(_VC_MANIFEST_INC)" == "1" #MT_SPECIAL_RETURN=1090650113 #MT_SPECIAL_SWITCH=-notify_resource_update MT_SPECIAL_RETURN=0 MT_SPECIAL_SWITCH= _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \ if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \ rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \ link $** /out:$@ $(LFLAGS) !else _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2 !endif #################################################### # _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily: !if "$(_VC_MANIFEST_INC)" == "1" _VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \ $(_VC_MANIFEST_BASENAME).auto.rc \ $(_VC_MANIFEST_BASENAME).auto.manifest !else _VC_MANIFEST_CLEAN= !endif !IF "$(CFG)" == "nslookup - @PLATFORM@ Release" OUTDIR=.\Release INTDIR=.\Release !IF "$(RECURSE)" == "0" ALL : "..\..\..\Build\Release\nslookup.exe" !ELSE ALL : "liblwres - @PLATFORM@ Release" "libbind9 - @PLATFORM@ Release" "libisc - @PLATFORM@ Release" "libdns - @PLATFORM@ Release" "..\..\..\Build\Release\nslookup.exe" !ENDIF !IF "$(RECURSE)" == "1" CLEAN :"libdns - @PLATFORM@ ReleaseCLEAN" "libisc - @PLATFORM@ ReleaseCLEAN" "libbind9 - @PLATFORM@ ReleaseCLEAN" "liblwres - @PLATFORM@ ReleaseCLEAN" !ELSE CLEAN : !ENDIF -@erase "$(INTDIR)\dighost.obj" -@erase "$(INTDIR)\nslookup.obj" -@erase "$(INTDIR)\vc60.idb" -@erase "..\..\..\Build\Release\nslookup.exe" -@$(_VC_MANIFEST_CLEAN) "$(OUTDIR)" : if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" CPP_PROJ=/nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../include" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ @READLINE_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isccfg/include" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" @CRYPTO@ /D "WIN32" /D "USE_READLINE_STATIC" /D "__STDC__" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\nslookup.pch" @COPTY@ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c BSC32=bscmake.exe BSC32_FLAGS=/nologo /o"$(OUTDIR)\nslookup.bsc" BSC32_SBRS= \ LINK32=link.exe LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/isccfg/win32/Release/libisccfg.lib ../../../lib/dns/win32/Release/libdns.lib ../../../lib/bind9/win32/Release/libbind9.lib ../../../lib/lwres/win32/Release/liblwres.lib @READLINE_LIB@ @IDN_LIB@ /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\nslookup.pdb" @MACHINE@ /out:"../../../Build/Release/nslookup.exe" LINK32_OBJS= \ "$(INTDIR)\dighost.obj" \ "$(INTDIR)\nslookup.obj" \ "..\..\..\lib\dns\win32\Release\libdns.lib" \ "..\..\..\lib\isc\win32\Release\libisc.lib" \ "..\..\..\lib\isccfg\win32\Release\libisccfg.lib" \ "..\..\..\lib\bind9\win32\Release\libbind9.lib" \ "..\..\..\lib\lwres\win32\Release\liblwres.lib" "..\..\..\Build\Release\nslookup.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) $(LINK32) @<< $(LINK32_FLAGS) $(LINK32_OBJS) << $(_VC_MANIFEST_EMBED_EXE) !ELSEIF "$(CFG)" == "nslookup - @PLATFORM@ Debug" OUTDIR=.\Debug INTDIR=.\Debug # Begin Custom Macros OutDir=.\Debug # End Custom Macros !IF "$(RECURSE)" == "0" ALL : "..\..\..\Build\Debug\nslookup.exe" "$(OUTDIR)\nslookup.bsc" !ELSE ALL : "liblwres - @PLATFORM@ Debug" "libbind9 - @PLATFORM@ Debug" "libisc - @PLATFORM@ Debug" "libdns - @PLATFORM@ Debug" "..\..\..\Build\Debug\nslookup.exe" "$(OUTDIR)\nslookup.bsc" !ENDIF !IF "$(RECURSE)" == "1" CLEAN :"libdns - @PLATFORM@ DebugCLEAN" "libisc - @PLATFORM@ DebugCLEAN" "libbind9 - @PLATFORM@ DebugCLEAN" "liblwres - @PLATFORM@ DebugCLEAN" !ELSE CLEAN : !ENDIF -@erase "$(INTDIR)\dighost.obj" -@erase "$(INTDIR)\dighost.sbr" -@erase "$(INTDIR)\nslookup.obj" -@erase "$(INTDIR)\nslookup.sbr" -@erase "$(INTDIR)\vc60.idb" -@erase "$(INTDIR)\vc60.pdb" -@erase "$(OUTDIR)\nslookup.bsc" -@erase "$(OUTDIR)\nslookup.pdb" -@erase "..\..\..\Build\Debug\nslookup.exe" -@erase "..\..\..\Build\Debug\nslookup.ilk" -@$(_VC_MANIFEST_CLEAN) "$(OUTDIR)" : if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" CPP_PROJ=/nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../include" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ @READLINE_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isccfg/include" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" @CRYPTO@ /D "WIN32" /D "USE_READLINE_STATIC" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c BSC32=bscmake.exe BSC32_FLAGS=/nologo /o"$(OUTDIR)\nslookup.bsc" BSC32_SBRS= \ "$(INTDIR)\dighost.sbr" \ "$(INTDIR)\nslookup.sbr" "$(OUTDIR)\nslookup.bsc" : "$(OUTDIR)" $(BSC32_SBRS) $(BSC32) @<< $(BSC32_FLAGS) $(BSC32_SBRS) << LINK32=link.exe LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/isccfg/win32/Debug/libisccfg.lib ../../../lib/dns/win32/Debug/libdns.lib ../../../lib/bind9/win32/Debug/libbind9.lib ../../../lib/lwres/win32/Debug/liblwres.lib @READLINE_LIBD@ @IDN_LIB@ /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\nslookup.pdb" /debug @MACHINE@ /out:"../../../Build/Debug/nslookup.exe" /pdbtype:sept LINK32_OBJS= \ "$(INTDIR)\dighost.obj" \ "$(INTDIR)\nslookup.obj" \ "..\..\..\lib\dns\win32\Debug\libdns.lib" \ "..\..\..\lib\isc\win32\Debug\libisc.lib" \ "..\..\..\lib\isccfg\win32\Debug\libisccfg.lib" \ "..\..\..\lib\bind9\win32\Debug\libbind9.lib" \ "..\..\..\lib\lwres\win32\Debug\liblwres.lib" "..\..\..\Build\Debug\nslookup.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) $(LINK32) @<< $(LINK32_FLAGS) $(LINK32_OBJS) << $(_VC_MANIFEST_EMBED_EXE) !ENDIF .c{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .c{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << !IF "$(NO_EXTERNAL_DEPS)" != "1" !IF EXISTS("nslookup.dep") !INCLUDE "nslookup.dep" !ELSE !MESSAGE Warning: cannot find "nslookup.dep" !ENDIF !ENDIF !IF "$(CFG)" == "nslookup - @PLATFORM@ Release" || "$(CFG)" == "nslookup - @PLATFORM@ Debug" SOURCE=..\dighost.c !IF "$(CFG)" == "nslookup - @PLATFORM@ Release" "$(INTDIR)\dighost.obj" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ELSEIF "$(CFG)" == "nslookup - @PLATFORM@ Debug" "$(INTDIR)\dighost.obj" "$(INTDIR)\dighost.sbr" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ENDIF SOURCE=..\nslookup.c !IF "$(CFG)" == "nslookup - @PLATFORM@ Release" "$(INTDIR)\nslookup.obj" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ELSEIF "$(CFG)" == "nslookup - @PLATFORM@ Debug" "$(INTDIR)\nslookup.obj" "$(INTDIR)\nslookup.sbr" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ENDIF !IF "$(CFG)" == "nslookup - @PLATFORM@ Release" "libdns - @PLATFORM@ Release" : cd "..\..\..\lib\dns\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Release" cd "..\..\..\bin\dig\win32" "libdns - @PLATFORM@ ReleaseCLEAN" : cd "..\..\..\lib\dns\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Release" RECURSE=1 CLEAN cd "..\..\..\bin\dig\win32" !ELSEIF "$(CFG)" == "nslookup - @PLATFORM@ Debug" "libdns - @PLATFORM@ Debug" : cd "..\..\..\lib\dns\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Debug" cd "..\..\..\bin\dig\win32" "libdns - @PLATFORM@ DebugCLEAN" : cd "..\..\..\lib\dns\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Debug" RECURSE=1 CLEAN cd "..\..\..\bin\dig\win32" !ENDIF !IF "$(CFG)" == "nslookup - @PLATFORM@ Release" "libisc - @PLATFORM@ Release" : cd "..\..\..\lib\isc\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Release" cd "..\..\..\bin\dig\win32" "libisc - @PLATFORM@ ReleaseCLEAN" : cd "..\..\..\lib\isc\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Release" RECURSE=1 CLEAN cd "..\..\..\bin\dig\win32" !ELSEIF "$(CFG)" == "nslookup - @PLATFORM@ Debug" "libisc - @PLATFORM@ Debug" : cd "..\..\..\lib\isc\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Debug" cd "..\..\..\bin\dig\win32" "libisc - @PLATFORM@ DebugCLEAN" : cd "..\..\..\lib\isc\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Debug" RECURSE=1 CLEAN cd "..\..\..\bin\dig\win32" !ENDIF !IF "$(CFG)" == "nslookup - @PLATFORM@ Release" "libbind9 - @PLATFORM@ Release" : cd "..\..\..\lib\bind9\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - @PLATFORM@ Release" cd "..\..\..\bin\dig\win32" "libbind9 - @PLATFORM@ ReleaseCLEAN" : cd "..\..\..\lib\bind9\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - @PLATFORM@ Release" RECURSE=1 CLEAN cd "..\..\..\bin\dig\win32" !ELSEIF "$(CFG)" == "nslookup - @PLATFORM@ Debug" "libbind9 - @PLATFORM@ Debug" : cd "..\..\..\lib\bind9\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - @PLATFORM@ Debug" cd "..\..\..\bin\dig\win32" "libbind9 - @PLATFORM@ DebugCLEAN" : cd "..\..\..\lib\bind9\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - @PLATFORM@ Debug" RECURSE=1 CLEAN cd "..\..\..\bin\dig\win32" !ENDIF !IF "$(CFG)" == "nslookup - @PLATFORM@ Release" "liblwres - @PLATFORM@ Release" : cd "..\..\..\lib\lwres\win32" $(MAKE) /$(MAKEFLAGS) /F ".\liblwres.mak" CFG="liblwres - @PLATFORM@ Release" cd "..\..\..\bin\dig\win32" "liblwres - @PLATFORM@ ReleaseCLEAN" : cd "..\..\..\lib\lwres\win32" $(MAKE) /$(MAKEFLAGS) /F ".\liblwres.mak" CFG="liblwres - @PLATFORM@ Release" RECURSE=1 CLEAN cd "..\..\..\bin\dig\win32" !ELSEIF "$(CFG)" == "nslookup - @PLATFORM@ Debug" "liblwres - @PLATFORM@ Debug" : cd "..\..\..\lib\lwres\win32" $(MAKE) /$(MAKEFLAGS) /F ".\liblwres.mak" CFG="liblwres - @PLATFORM@ Debug" cd "..\..\..\bin\dig\win32" "liblwres - @PLATFORM@ DebugCLEAN" : cd "..\..\..\lib\lwres\win32" $(MAKE) /$(MAKEFLAGS) /F ".\liblwres.mak" CFG="liblwres - @PLATFORM@ Debug" RECURSE=1 CLEAN cd "..\..\..\bin\dig\win32" !ENDIF !ENDIF #################################################### # Commands to generate initial empty manifest file and the RC file # that references it, and for generating the .res file: $(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc $(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest type <<$@ #include 1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest" << KEEP $(_VC_MANIFEST_BASENAME).auto.manifest : type <<$@ << KEEP bind9-9.11.3+dfsg/bin/dig/win32/nslookup.vcxproj.filters.in000066400000000000000000000015351325250447100233600ustar00rootroot00000000000000 {4FC737F1-C7A5-4376-A066-2A32D752A2FF} cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms Source Files Source Files bind9-9.11.3+dfsg/bin/dig/win32/nslookup.vcxproj.in000066400000000000000000000162061325250447100217120ustar00rootroot00000000000000 Debug @PLATFORM@ Release @PLATFORM@ {C15A6E1A-94CE-4686-99F9-6BC5FD623EB5} Win32Proj nslookup Application true MultiByte Application false true MultiByte true ..\..\..\Build\$(Configuration)\ .\$(Configuration)\ false ..\..\..\Build\$(Configuration)\ .\$(Configuration)\ Level3 Disabled WIN32;@CRYPTO@USE_READLINE_STATIC;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true .\$(Configuration)\$(TargetName).pch .\$(Configuration)\ .\$(Configuration)\ $(OutDir)$(TargetName).pdb true .\;..\include;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@@READLINE_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\isccfg\include;..\..\..\lib\dns\include;..\..\..\lib\bind9\include;..\..\..\lib\lwres\win32\include;..\..\..\lib\lwres\include;%(AdditionalIncludeDirectories) CompileAsC Console true ..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt) ..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\isccfg\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);..\..\..\lib\bind9\win32\$(Configuration);..\..\..\lib\lwres\win32\$(Configuration);%(AdditionalLibraryDirectories) @READLINE_LIBD@@IDN_LIB@libisc.lib;libisccfg.lib;libdns.lib;libbind9.lib;liblwres.lib;ws2_32.lib;%(AdditionalDependencies) Level3 MaxSpeed true @INTRINSIC@ WIN32;@CRYPTO@USE_READLINE_STATIC;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) OnlyExplicitInline false true .\$(Configuration)\$(TargetName).pch .\$(Configuration)\ .\$(Configuration)\ $(OutDir)$(TargetName).pdb .\;..\include;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@@READLINE_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\isccfg\include;..\..\..\lib\dns\include;..\..\..\lib\bind9\include;..\..\..\lib\lwres\win32\include;..\..\..\lib\lwres\include;%(AdditionalIncludeDirectories) CompileAsC Console false true true ..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt) Default ..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\isccfg\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);..\..\..\lib\bind9\win32\$(Configuration);..\..\..\lib\lwres\win32\$(Configuration);%(AdditionalLibraryDirectories) @READLINE_LIB@@IDN_LIB@libisc.lib;libisccfg.lib;libdns.lib;libbind9.lib;liblwres.lib;ws2_32.lib;%(AdditionalDependencies) bind9-9.11.3+dfsg/bin/dig/win32/nslookup.vcxproj.user000066400000000000000000000002171325250447100222550ustar00rootroot00000000000000 bind9-9.11.3+dfsg/bin/dnssec/000077500000000000000000000000001325250447100155635ustar00rootroot00000000000000bind9-9.11.3+dfsg/bin/dnssec/Makefile.in000066400000000000000000000075541325250447100176430ustar00rootroot00000000000000# Copyright (C) 2000-2002, 2004, 2005, 2007-2009, 2012-2016 Internet Systems Consortium, Inc. ("ISC") # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. # $Id: Makefile.in,v 1.42.332.1 2011/03/16 06:37:51 each Exp $ srcdir = @srcdir@ VPATH = @srcdir@ top_srcdir = @top_srcdir@ VERSION=@BIND9_VERSION@ @BIND9_MAKE_INCLUDES@ CINCLUDES = ${DNS_INCLUDES} ${ISC_INCLUDES} @DST_OPENSSL_INC@ CDEFINES = -DVERSION=\"${VERSION}\" @USE_PKCS11@ @PKCS11_ENGINE@ \ @CRYPTO@ -DPK11_LIB_LOCATION=\"@PKCS11_PROVIDER@\" CWARNINGS = DNSLIBS = ../../lib/dns/libdns.@A@ @DNS_CRYPTO_LIBS@ ISCLIBS = ../../lib/isc/libisc.@A@ ISCNOSYMLIBS = ../../lib/isc/libisc-nosymtbl.@A@ DNSDEPLIBS = ../../lib/dns/libdns.@A@ ISCDEPLIBS = ../../lib/isc/libisc.@A@ DEPLIBS = ${DNSDEPLIBS} ${ISCDEPLIBS} LIBS = ${DNSLIBS} ${ISCLIBS} @LIBS@ NOSYMLIBS = ${DNSLIBS} ${ISCNOSYMLIBS} @LIBS@ # Alphabetically TARGETS = dnssec-keygen@EXEEXT@ dnssec-signzone@EXEEXT@ \ dnssec-keyfromlabel@EXEEXT@ dnssec-dsfromkey@EXEEXT@ \ dnssec-revoke@EXEEXT@ dnssec-settime@EXEEXT@ \ dnssec-verify@EXEEXT@ dnssec-importkey@EXEEXT@ OBJS = dnssectool.@O@ SRCS = dnssec-dsfromkey.c dnssec-keyfromlabel.c dnssec-keygen.c \ dnssec-revoke.c dnssec-settime.c dnssec-signzone.c \ dnssec-verify.c dnssec-importkey.c dnssectool.c MANPAGES = dnssec-dsfromkey.8 dnssec-keyfromlabel.8 dnssec-keygen.8 \ dnssec-revoke.8 dnssec-settime.8 dnssec-signzone.8 \ dnssec-verify.8 dnssec-importkey.8 HTMLPAGES = dnssec-dsfromkey.html dnssec-keyfromlabel.html \ dnssec-keygen.html dnssec-revoke.html \ dnssec-settime.html dnssec-signzone.html \ dnssec-verify.html dnssec-importkey.html MANOBJS = ${MANPAGES} ${HTMLPAGES} @BIND9_MAKE_RULES@ dnssec-dsfromkey@EXEEXT@: dnssec-dsfromkey.@O@ ${OBJS} ${DEPLIBS} export BASEOBJS="dnssec-dsfromkey.@O@ ${OBJS}"; \ ${FINALBUILDCMD} dnssec-keyfromlabel@EXEEXT@: dnssec-keyfromlabel.@O@ ${OBJS} ${DEPLIBS} export BASEOBJS="dnssec-keyfromlabel.@O@ ${OBJS}"; \ ${FINALBUILDCMD} dnssec-keygen@EXEEXT@: dnssec-keygen.@O@ ${OBJS} ${DEPLIBS} export BASEOBJS="dnssec-keygen.@O@ ${OBJS}"; \ ${FINALBUILDCMD} dnssec-signzone.@O@: dnssec-signzone.c ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} -DVERSION=\"${VERSION}\" \ -c ${srcdir}/dnssec-signzone.c dnssec-signzone@EXEEXT@: dnssec-signzone.@O@ ${OBJS} ${DEPLIBS} export BASEOBJS="dnssec-signzone.@O@ ${OBJS}"; \ ${FINALBUILDCMD} dnssec-verify.@O@: dnssec-verify.c ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} -DVERSION=\"${VERSION}\" \ -c ${srcdir}/dnssec-verify.c dnssec-verify@EXEEXT@: dnssec-verify.@O@ ${OBJS} ${DEPLIBS} export BASEOBJS="dnssec-verify.@O@ ${OBJS}"; \ ${FINALBUILDCMD} dnssec-revoke@EXEEXT@: dnssec-revoke.@O@ ${OBJS} ${DEPLIBS} ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ dnssec-revoke.@O@ ${OBJS} ${LIBS} dnssec-settime@EXEEXT@: dnssec-settime.@O@ ${OBJS} ${DEPLIBS} ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ dnssec-settime.@O@ ${OBJS} ${LIBS} dnssec-importkey@EXEEXT@: dnssec-importkey.@O@ ${OBJS} ${DEPLIBS} ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ dnssec-importkey.@O@ ${OBJS} ${LIBS} doc man:: ${MANOBJS} docclean manclean maintainer-clean:: rm -f ${MANOBJS} installdirs: $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${sbindir} $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${mandir}/man8 install:: ${TARGETS} installdirs for t in ${TARGETS}; do ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} $$t ${DESTDIR}${sbindir}; done for m in ${MANPAGES}; do ${INSTALL_DATA} ${srcdir}/$$m ${DESTDIR}${mandir}/man8; done uninstall:: for m in ${MANPAGES}; do rm -f ${DESTDIR}${mandir}/man8/$$m ; done for t in ${TARGETS}; do ${LIBTOOL_MODE_UNINSTALL} rm -f ${DESTDIR}${sbindir}/$$t ; done clean distclean:: rm -f ${TARGETS} bind9-9.11.3+dfsg/bin/dnssec/dnssec-dsfromkey.8000066400000000000000000000124741325250447100211440ustar00rootroot00000000000000.\" Copyright (C) 2008-2012, 2014-2016 Internet Systems Consortium, Inc. ("ISC") .\" .\" This Source Code Form is subject to the terms of the Mozilla Public .\" License, v. 2.0. If a copy of the MPL was not distributed with this .\" file, You can obtain one at http://mozilla.org/MPL/2.0/. .\" .hy 0 .ad l '\" t .\" Title: dnssec-dsfromkey .\" Author: .\" Generator: DocBook XSL Stylesheets v1.78.1 .\" Date: 2012-05-02 .\" Manual: BIND9 .\" Source: ISC .\" Language: English .\" .TH "DNSSEC\-DSFROMKEY" "8" "2012\-05\-02" "ISC" "BIND9" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" dnssec-dsfromkey \- DNSSEC DS RR generation tool .SH "SYNOPSIS" .HP \w'\fBdnssec\-dsfromkey\fR\ 'u \fBdnssec\-dsfromkey\fR [\fB\-v\ \fR\fB\fIlevel\fR\fR] [\fB\-1\fR] [\fB\-2\fR] [\fB\-a\ \fR\fB\fIalg\fR\fR] [\fB\-C\fR] [\fB\-l\ \fR\fB\fIdomain\fR\fR] [\fB\-T\ \fR\fB\fITTL\fR\fR] {keyfile} .HP \w'\fBdnssec\-dsfromkey\fR\ 'u \fBdnssec\-dsfromkey\fR {\-s} [\fB\-1\fR] [\fB\-2\fR] [\fB\-a\ \fR\fB\fIalg\fR\fR] [\fB\-K\ \fR\fB\fIdirectory\fR\fR] [\fB\-l\ \fR\fB\fIdomain\fR\fR] [\fB\-s\fR] [\fB\-c\ \fR\fB\fIclass\fR\fR] [\fB\-T\ \fR\fB\fITTL\fR\fR] [\fB\-f\ \fR\fB\fIfile\fR\fR] [\fB\-A\fR] [\fB\-v\ \fR\fB\fIlevel\fR\fR] {dnsname} .HP \w'\fBdnssec\-dsfromkey\fR\ 'u \fBdnssec\-dsfromkey\fR [\fB\-h\fR] [\fB\-V\fR] .SH "DESCRIPTION" .PP \fBdnssec\-dsfromkey\fR outputs the Delegation Signer (DS) resource record (RR), as defined in RFC 3658 and RFC 4509, for the given key(s)\&. .SH "OPTIONS" .PP \-1 .RS 4 Use SHA\-1 as the digest algorithm (the default is to use both SHA\-1 and SHA\-256)\&. .RE .PP \-2 .RS 4 Use SHA\-256 as the digest algorithm\&. .RE .PP \-a \fIalgorithm\fR .RS 4 Select the digest algorithm\&. The value of \fBalgorithm\fR must be one of SHA\-1 (SHA1), SHA\-256 (SHA256), GOST or SHA\-384 (SHA384)\&. These values are case insensitive\&. .RE .PP \-C .RS 4 Generate CDS records rather than DS records\&. This is mutually exclusive with generating lookaside records\&. .RE .PP \-T \fITTL\fR .RS 4 Specifies the TTL of the DS records\&. .RE .PP \-K \fIdirectory\fR .RS 4 Look for key files (or, in keyset mode, keyset\- files) in \fBdirectory\fR\&. .RE .PP \-f \fIfile\fR .RS 4 Zone file mode: in place of the keyfile name, the argument is the DNS domain name of a zone master file, which can be read from \fBfile\fR\&. If the zone name is the same as \fBfile\fR, then it may be omitted\&. .sp If \fBfile\fR is set to "\-", then the zone data is read from the standard input\&. This makes it possible to use the output of the \fBdig\fR command as input, as in: .sp \fBdig dnskey example\&.com | dnssec\-dsfromkey \-f \- example\&.com\fR .RE .PP \-A .RS 4 Include ZSKs when generating DS records\&. Without this option, only keys which have the KSK flag set will be converted to DS records and printed\&. Useful only in zone file mode\&. .RE .PP \-l \fIdomain\fR .RS 4 Generate a DLV set instead of a DS set\&. The specified \fBdomain\fR is appended to the name for each record in the set\&. The DNSSEC Lookaside Validation (DLV) RR is described in RFC 4431\&. This is mutually exclusive with generating CDS records\&. .RE .PP \-s .RS 4 Keyset mode: in place of the keyfile name, the argument is the DNS domain name of a keyset file\&. .RE .PP \-c \fIclass\fR .RS 4 Specifies the DNS class (default is IN)\&. Useful only in keyset or zone file mode\&. .RE .PP \-v \fIlevel\fR .RS 4 Sets the debugging level\&. .RE .PP \-h .RS 4 Prints usage information\&. .RE .PP \-V .RS 4 Prints version information\&. .RE .SH "EXAMPLE" .PP To build the SHA\-256 DS RR from the \fBKexample\&.com\&.+003+26160\fR keyfile name, the following command would be issued: .PP \fBdnssec\-dsfromkey \-2 Kexample\&.com\&.+003+26160\fR .PP The command would print something like: .PP \fBexample\&.com\&. IN DS 26160 5 2 3A1EADA7A74B8D0BA86726B0C227AA85AB8BBD2B2004F41A868A54F0 C5EA0B94\fR .SH "FILES" .PP The keyfile can be designed by the key identification Knnnn\&.+aaa+iiiii or the full file name Knnnn\&.+aaa+iiiii\&.key as generated by dnssec\-keygen(8)\&. .PP The keyset file name is built from the \fBdirectory\fR, the string keyset\- and the \fBdnsname\fR\&. .SH "CAVEAT" .PP A keyfile error can give a "file not found" even if the file exists\&. .SH "SEE ALSO" .PP \fBdnssec-keygen\fR(8), \fBdnssec-signzone\fR(8), BIND 9 Administrator Reference Manual, RFC 3658, RFC 4431\&. RFC 4509\&. .SH "AUTHOR" .PP \fBInternet Systems Consortium, Inc\&.\fR .SH "COPYRIGHT" .br Copyright \(co 2008-2012, 2014-2016 Internet Systems Consortium, Inc. ("ISC") .br bind9-9.11.3+dfsg/bin/dnssec/dnssec-dsfromkey.c000066400000000000000000000354451325250447100212220ustar00rootroot00000000000000/* * Copyright (C) 2008-2012, 2014-2017 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /*! \file */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef PKCS11CRYPTO #include #endif #include "dnssectool.h" #ifndef PATH_MAX #define PATH_MAX 1024 /* AIX, WIN32, and others don't define this. */ #endif const char *program = "dnssec-dsfromkey"; int verbose; static dns_rdataclass_t rdclass; static dns_fixedname_t fixed; static dns_name_t *name = NULL; static isc_mem_t *mctx = NULL; static isc_uint32_t ttl; static isc_boolean_t emitttl = ISC_FALSE; static isc_result_t initname(char *setname) { isc_result_t result; isc_buffer_t buf; dns_fixedname_init(&fixed); name = dns_fixedname_name(&fixed); isc_buffer_init(&buf, setname, strlen(setname)); isc_buffer_add(&buf, strlen(setname)); result = dns_name_fromtext(name, &buf, dns_rootname, 0, NULL); return (result); } static void db_load_from_stream(dns_db_t *db, FILE *fp) { isc_result_t result; dns_rdatacallbacks_t callbacks; dns_rdatacallbacks_init(&callbacks); result = dns_db_beginload(db, &callbacks); if (result != ISC_R_SUCCESS) fatal("dns_db_beginload failed: %s", isc_result_totext(result)); result = dns_master_loadstream(fp, name, name, rdclass, 0, &callbacks, mctx); if (result != ISC_R_SUCCESS) fatal("can't load from input: %s", isc_result_totext(result)); result = dns_db_endload(db, &callbacks); if (result != ISC_R_SUCCESS) fatal("dns_db_endload failed: %s", isc_result_totext(result)); } static isc_result_t loadset(const char *filename, dns_rdataset_t *rdataset) { isc_result_t result; dns_db_t *db = NULL; dns_dbnode_t *node = NULL; char setname[DNS_NAME_FORMATSIZE]; dns_name_format(name, setname, sizeof(setname)); result = dns_db_create(mctx, "rbt", name, dns_dbtype_zone, rdclass, 0, NULL, &db); if (result != ISC_R_SUCCESS) fatal("can't create database"); if (strcmp(filename, "-") == 0) { db_load_from_stream(db, stdin); filename = "input"; } else { result = dns_db_load(db, filename); if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE) fatal("can't load %s: %s", filename, isc_result_totext(result)); } result = dns_db_findnode(db, name, ISC_FALSE, &node); if (result != ISC_R_SUCCESS) fatal("can't find %s node in %s", setname, filename); result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_dnskey, 0, 0, rdataset, NULL); if (result == ISC_R_NOTFOUND) fatal("no DNSKEY RR for %s in %s", setname, filename); else if (result != ISC_R_SUCCESS) fatal("dns_db_findrdataset"); if (node != NULL) dns_db_detachnode(db, &node); if (db != NULL) dns_db_detach(&db); return (result); } static isc_result_t loadkeyset(char *dirname, dns_rdataset_t *rdataset) { isc_result_t result; char filename[PATH_MAX + 1]; isc_buffer_t buf; dns_rdataset_init(rdataset); isc_buffer_init(&buf, filename, sizeof(filename)); if (dirname != NULL) { /* allow room for a trailing slash */ if (strlen(dirname) >= isc_buffer_availablelength(&buf)) return (ISC_R_NOSPACE); isc_buffer_putstr(&buf, dirname); if (dirname[strlen(dirname) - 1] != '/') isc_buffer_putstr(&buf, "/"); } if (isc_buffer_availablelength(&buf) < 7) return (ISC_R_NOSPACE); isc_buffer_putstr(&buf, "keyset-"); result = dns_name_tofilenametext(name, ISC_FALSE, &buf); check_result(result, "dns_name_tofilenametext()"); if (isc_buffer_availablelength(&buf) == 0) return (ISC_R_NOSPACE); isc_buffer_putuint8(&buf, 0); return (loadset(filename, rdataset)); } static void loadkey(char *filename, unsigned char *key_buf, unsigned int key_buf_size, dns_rdata_t *rdata) { isc_result_t result; dst_key_t *key = NULL; isc_buffer_t keyb; isc_region_t r; dns_rdata_init(rdata); isc_buffer_init(&keyb, key_buf, key_buf_size); result = dst_key_fromnamedfile(filename, NULL, DST_TYPE_PUBLIC, mctx, &key); if (result != ISC_R_SUCCESS) fatal("can't load %s.key: %s", filename, isc_result_totext(result)); if (verbose > 2) { char keystr[DST_KEY_FORMATSIZE]; dst_key_format(key, keystr, sizeof(keystr)); fprintf(stderr, "%s: %s\n", program, keystr); } result = dst_key_todns(key, &keyb); if (result != ISC_R_SUCCESS) fatal("can't decode key"); isc_buffer_usedregion(&keyb, &r); dns_rdata_fromregion(rdata, dst_key_class(key), dns_rdatatype_dnskey, &r); rdclass = dst_key_class(key); dns_fixedname_init(&fixed); name = dns_fixedname_name(&fixed); result = dns_name_copy(dst_key_name(key), name, NULL); if (result != ISC_R_SUCCESS) fatal("can't copy name"); dst_key_free(&key); } static void logkey(dns_rdata_t *rdata) { isc_result_t result; dst_key_t *key = NULL; isc_buffer_t buf; char keystr[DST_KEY_FORMATSIZE]; isc_buffer_init(&buf, rdata->data, rdata->length); isc_buffer_add(&buf, rdata->length); result = dst_key_fromdns(name, rdclass, &buf, mctx, &key); if (result != ISC_R_SUCCESS) return; dst_key_format(key, keystr, sizeof(keystr)); fprintf(stderr, "%s: %s\n", program, keystr); dst_key_free(&key); } static void emit(unsigned int dtype, isc_boolean_t showall, char *lookaside, isc_boolean_t cds, dns_rdata_t *rdata) { isc_result_t result; unsigned char buf[DNS_DS_BUFFERSIZE]; char text_buf[DST_KEY_MAXTEXTSIZE]; char name_buf[DNS_NAME_MAXWIRE]; char class_buf[10]; isc_buffer_t textb, nameb, classb; isc_region_t r; dns_rdata_t ds; dns_rdata_dnskey_t dnskey; isc_buffer_init(&textb, text_buf, sizeof(text_buf)); isc_buffer_init(&nameb, name_buf, sizeof(name_buf)); isc_buffer_init(&classb, class_buf, sizeof(class_buf)); dns_rdata_init(&ds); result = dns_rdata_tostruct(rdata, &dnskey, NULL); if (result != ISC_R_SUCCESS) fatal("can't convert DNSKEY"); if ((dnskey.flags & DNS_KEYFLAG_KSK) == 0 && !showall) return; result = dns_ds_buildrdata(name, rdata, dtype, buf, &ds); if (result != ISC_R_SUCCESS) fatal("can't build record"); result = dns_name_totext(name, ISC_FALSE, &nameb); if (result != ISC_R_SUCCESS) fatal("can't print name"); /* Add lookaside origin, if set */ if (lookaside != NULL) { if (isc_buffer_availablelength(&nameb) < strlen(lookaside)) fatal("DLV origin '%s' is too long", lookaside); isc_buffer_putstr(&nameb, lookaside); if (lookaside[strlen(lookaside) - 1] != '.') { if (isc_buffer_availablelength(&nameb) < 1) fatal("DLV origin '%s' is too long", lookaside); isc_buffer_putstr(&nameb, "."); } } result = dns_rdata_tofmttext(&ds, (dns_name_t *) NULL, 0, 0, 0, "", &textb); if (result != ISC_R_SUCCESS) fatal("can't print rdata"); result = dns_rdataclass_totext(rdclass, &classb); if (result != ISC_R_SUCCESS) fatal("can't print class"); isc_buffer_usedregion(&nameb, &r); printf("%.*s ", (int)r.length, r.base); if (emitttl) printf("%u ", ttl); isc_buffer_usedregion(&classb, &r); printf("%.*s", (int)r.length, r.base); if (lookaside == NULL) { if (cds) printf(" CDS "); else printf(" DS "); } else printf(" DLV "); isc_buffer_usedregion(&textb, &r); printf("%.*s\n", (int)r.length, r.base); } ISC_PLATFORM_NORETURN_PRE static void usage(void) ISC_PLATFORM_NORETURN_POST; static void usage(void) { fprintf(stderr, "Usage:\n"); fprintf(stderr, " %s options [-K dir] keyfile\n\n", program); fprintf(stderr, " %s options [-K dir] [-c class] -s dnsname\n\n", program); fprintf(stderr, " %s options -f zonefile (as zone name)\n\n", program); fprintf(stderr, " %s options -f zonefile zonename\n\n", program); fprintf(stderr, "Version: %s\n", VERSION); fprintf(stderr, "Options:\n"); fprintf(stderr, " -v \n"); fprintf(stderr, " -V: print version information\n"); fprintf(stderr, " -K : directory in which to find " "key file or keyset file\n"); fprintf(stderr, " -a algorithm: digest algorithm " "(SHA-1, SHA-256, GOST or SHA-384)\n"); fprintf(stderr, " -1: use SHA-1\n"); fprintf(stderr, " -2: use SHA-256\n"); fprintf(stderr, " -C: print CDS record\n"); fprintf(stderr, " -l: add lookaside zone and print DLV records\n"); fprintf(stderr, " -s: read keyset from keyset- file\n"); fprintf(stderr, " -c class: rdata class for DS set (default: IN)\n"); fprintf(stderr, " -T TTL\n"); fprintf(stderr, " -f file: read keyset from zone file\n"); fprintf(stderr, " -A: when used with -f, " "include all keys in DS set, not just KSKs\n"); fprintf(stderr, "Output: DS or DLV RRs\n"); exit (-1); } int main(int argc, char **argv) { char *algname = NULL, *classname = NULL; char *filename = NULL, *dir = NULL, *namestr; char *lookaside = NULL; char *endp; int ch; unsigned int dtype = DNS_DSDIGEST_SHA1; isc_boolean_t cds = ISC_FALSE; isc_boolean_t both = ISC_TRUE; isc_boolean_t usekeyset = ISC_FALSE; isc_boolean_t showall = ISC_FALSE; isc_result_t result; isc_log_t *log = NULL; isc_entropy_t *ectx = NULL; dns_rdataset_t rdataset; dns_rdata_t rdata; dns_rdata_init(&rdata); if (argc == 1) usage(); result = isc_mem_create(0, 0, &mctx); if (result != ISC_R_SUCCESS) fatal("out of memory"); #ifdef PKCS11CRYPTO pk11_result_register(); #endif dns_result_register(); isc_commandline_errprint = ISC_FALSE; #define OPTIONS "12Aa:Cc:d:Ff:K:l:sT:v:hV" while ((ch = isc_commandline_parse(argc, argv, OPTIONS)) != -1) { switch (ch) { case '1': dtype = DNS_DSDIGEST_SHA1; both = ISC_FALSE; break; case '2': dtype = DNS_DSDIGEST_SHA256; both = ISC_FALSE; break; case 'A': showall = ISC_TRUE; break; case 'a': algname = isc_commandline_argument; both = ISC_FALSE; break; case 'C': if (lookaside != NULL) fatal("lookaside and CDS are mutually" " exclusive"); cds = ISC_TRUE; break; case 'c': classname = isc_commandline_argument; break; case 'd': fprintf(stderr, "%s: the -d option is deprecated; " "use -K\n", program); /* fall through */ case 'K': dir = isc_commandline_argument; if (strlen(dir) == 0U) fatal("directory must be non-empty string"); break; case 'f': filename = isc_commandline_argument; break; case 'l': if (cds) fatal("lookaside and CDS are mutually" " exclusive"); lookaside = isc_commandline_argument; if (strlen(lookaside) == 0U) fatal("lookaside must be a non-empty string"); break; case 's': usekeyset = ISC_TRUE; break; case 'T': emitttl = ISC_TRUE; ttl = atol(isc_commandline_argument); break; case 'v': verbose = strtol(isc_commandline_argument, &endp, 0); if (*endp != '\0') fatal("-v must be followed by a number"); break; case 'F': /* Reserved for FIPS mode */ /* FALLTHROUGH */ case '?': if (isc_commandline_option != '?') fprintf(stderr, "%s: invalid argument -%c\n", program, isc_commandline_option); /* FALLTHROUGH */ case 'h': /* Does not return. */ usage(); case 'V': /* Does not return. */ version(program); default: fprintf(stderr, "%s: unhandled option -%c\n", program, isc_commandline_option); exit(1); } } if (algname != NULL) { if (strcasecmp(algname, "SHA1") == 0 || strcasecmp(algname, "SHA-1") == 0) dtype = DNS_DSDIGEST_SHA1; else if (strcasecmp(algname, "SHA256") == 0 || strcasecmp(algname, "SHA-256") == 0) dtype = DNS_DSDIGEST_SHA256; #if defined(HAVE_OPENSSL_GOST) || defined(HAVE_PKCS11_GOST) else if (strcasecmp(algname, "GOST") == 0) dtype = DNS_DSDIGEST_GOST; #endif else if (strcasecmp(algname, "SHA384") == 0 || strcasecmp(algname, "SHA-384") == 0) dtype = DNS_DSDIGEST_SHA384; else fatal("unknown algorithm %s", algname); } rdclass = strtoclass(classname); if (usekeyset && filename != NULL) fatal("cannot use both -s and -f"); /* When not using -f, -A is implicit */ if (filename == NULL) showall = ISC_TRUE; if (argc < isc_commandline_index + 1 && filename == NULL) fatal("the key file name was not specified"); if (argc > isc_commandline_index + 1) fatal("extraneous arguments"); if (ectx == NULL) setup_entropy(mctx, NULL, &ectx); result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE); if (result != ISC_R_SUCCESS) fatal("could not initialize hash"); result = dst_lib_init(mctx, ectx, ISC_ENTROPY_BLOCKING | ISC_ENTROPY_GOODONLY); if (result != ISC_R_SUCCESS) fatal("could not initialize dst: %s", isc_result_totext(result)); isc_entropy_stopcallbacksources(ectx); setup_logging(mctx, &log); dns_rdataset_init(&rdataset); if (usekeyset || filename != NULL) { if (argc < isc_commandline_index + 1 && filename != NULL) { /* using zone name as the zone file name */ namestr = filename; } else namestr = argv[isc_commandline_index]; result = initname(namestr); if (result != ISC_R_SUCCESS) fatal("could not initialize name %s", namestr); if (usekeyset) result = loadkeyset(dir, &rdataset); else result = loadset(filename, &rdataset); if (result != ISC_R_SUCCESS) fatal("could not load DNSKEY set: %s\n", isc_result_totext(result)); for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS; result = dns_rdataset_next(&rdataset)) { dns_rdata_init(&rdata); dns_rdataset_current(&rdataset, &rdata); if (verbose > 2) logkey(&rdata); if (both) { emit(DNS_DSDIGEST_SHA1, showall, lookaside, cds, &rdata); emit(DNS_DSDIGEST_SHA256, showall, lookaside, cds, &rdata); } else emit(dtype, showall, lookaside, cds, &rdata); } } else { unsigned char key_buf[DST_KEY_MAXSIZE]; loadkey(argv[isc_commandline_index], key_buf, DST_KEY_MAXSIZE, &rdata); if (both) { emit(DNS_DSDIGEST_SHA1, showall, lookaside, cds, &rdata); emit(DNS_DSDIGEST_SHA256, showall, lookaside, cds, &rdata); } else emit(dtype, showall, lookaside, cds, &rdata); } if (dns_rdataset_isassociated(&rdataset)) dns_rdataset_disassociate(&rdataset); cleanup_logging(&log); dst_lib_destroy(); isc_hash_destroy(); cleanup_entropy(&ectx); dns_name_destroy(); if (verbose > 10) isc_mem_stats(mctx, stdout); isc_mem_destroy(&mctx); fflush(stdout); if (ferror(stdout)) { fprintf(stderr, "write error\n"); return (1); } else return (0); } bind9-9.11.3+dfsg/bin/dnssec/dnssec-dsfromkey.docbook000066400000000000000000000226211325250447100224100ustar00rootroot00000000000000 2012-05-02 ISC Internet Systems Consortium, Inc. dnssec-dsfromkey 8 BIND9 dnssec-dsfromkey DNSSEC DS RR generation tool 2008 2009 2010 2011 2012 2014 2015 2016 Internet Systems Consortium, Inc. ("ISC") dnssec-dsfromkey keyfile dnssec-dsfromkey -s dnsname dnssec-dsfromkey DESCRIPTION dnssec-dsfromkey outputs the Delegation Signer (DS) resource record (RR), as defined in RFC 3658 and RFC 4509, for the given key(s). OPTIONS -1 Use SHA-1 as the digest algorithm (the default is to use both SHA-1 and SHA-256). -2 Use SHA-256 as the digest algorithm. -a algorithm Select the digest algorithm. The value of must be one of SHA-1 (SHA1), SHA-256 (SHA256), GOST or SHA-384 (SHA384). These values are case insensitive. -C Generate CDS records rather than DS records. This is mutually exclusive with generating lookaside records. -T TTL Specifies the TTL of the DS records. -K directory Look for key files (or, in keyset mode, keyset- files) in . -f file Zone file mode: in place of the keyfile name, the argument is the DNS domain name of a zone master file, which can be read from . If the zone name is the same as , then it may be omitted. If is set to "-", then the zone data is read from the standard input. This makes it possible to use the output of the dig command as input, as in: dig dnskey example.com | dnssec-dsfromkey -f - example.com -A Include ZSKs when generating DS records. Without this option, only keys which have the KSK flag set will be converted to DS records and printed. Useful only in zone file mode. -l domain Generate a DLV set instead of a DS set. The specified is appended to the name for each record in the set. The DNSSEC Lookaside Validation (DLV) RR is described in RFC 4431. This is mutually exclusive with generating CDS records. -s Keyset mode: in place of the keyfile name, the argument is the DNS domain name of a keyset file. -c class Specifies the DNS class (default is IN). Useful only in keyset or zone file mode. -v level Sets the debugging level. -h Prints usage information. -V Prints version information. EXAMPLE To build the SHA-256 DS RR from the Kexample.com.+003+26160 keyfile name, the following command would be issued: dnssec-dsfromkey -2 Kexample.com.+003+26160 The command would print something like: example.com. IN DS 26160 5 2 3A1EADA7A74B8D0BA86726B0C227AA85AB8BBD2B2004F41A868A54F0 C5EA0B94 FILES The keyfile can be designed by the key identification Knnnn.+aaa+iiiii or the full file name Knnnn.+aaa+iiiii.key as generated by dnssec-keygen8. The keyset file name is built from the , the string keyset- and the . CAVEAT A keyfile error can give a "file not found" even if the file exists. SEE ALSO dnssec-keygen8 , dnssec-signzone8 , BIND 9 Administrator Reference Manual, RFC 3658, RFC 4431. RFC 4509. bind9-9.11.3+dfsg/bin/dnssec/dnssec-dsfromkey.html000066400000000000000000000202671325250447100217400ustar00rootroot00000000000000 dnssec-dsfromkey

Name

dnssec-dsfromkey — DNSSEC DS RR generation tool

Synopsis

dnssec-dsfromkey [-v level] [-1] [-2] [-a alg] [-C] [-l domain] [-T TTL] {keyfile}

dnssec-dsfromkey {-s} [-1] [-2] [-a alg] [-K directory] [-l domain] [-s] [-c class] [-T TTL] [-f file] [-A] [-v level] {dnsname}

dnssec-dsfromkey [-h] [-V]

DESCRIPTION

dnssec-dsfromkey outputs the Delegation Signer (DS) resource record (RR), as defined in RFC 3658 and RFC 4509, for the given key(s).

OPTIONS

-1

Use SHA-1 as the digest algorithm (the default is to use both SHA-1 and SHA-256).

-2

Use SHA-256 as the digest algorithm.

-a algorithm

Select the digest algorithm. The value of algorithm must be one of SHA-1 (SHA1), SHA-256 (SHA256), GOST or SHA-384 (SHA384). These values are case insensitive.

-C

Generate CDS records rather than DS records. This is mutually exclusive with generating lookaside records.

-T TTL

Specifies the TTL of the DS records.

-K directory

Look for key files (or, in keyset mode, keyset- files) in directory.

-f file

Zone file mode: in place of the keyfile name, the argument is the DNS domain name of a zone master file, which can be read from file. If the zone name is the same as file, then it may be omitted.

If file is set to "-", then the zone data is read from the standard input. This makes it possible to use the output of the dig command as input, as in:

dig dnskey example.com | dnssec-dsfromkey -f - example.com

-A

Include ZSKs when generating DS records. Without this option, only keys which have the KSK flag set will be converted to DS records and printed. Useful only in zone file mode.

-l domain

Generate a DLV set instead of a DS set. The specified domain is appended to the name for each record in the set. The DNSSEC Lookaside Validation (DLV) RR is described in RFC 4431. This is mutually exclusive with generating CDS records.

-s

Keyset mode: in place of the keyfile name, the argument is the DNS domain name of a keyset file.

-c class

Specifies the DNS class (default is IN). Useful only in keyset or zone file mode.

-v level

Sets the debugging level.

-h

Prints usage information.

-V

Prints version information.

EXAMPLE

To build the SHA-256 DS RR from the Kexample.com.+003+26160 keyfile name, the following command would be issued:

dnssec-dsfromkey -2 Kexample.com.+003+26160

The command would print something like:

example.com. IN DS 26160 5 2 3A1EADA7A74B8D0BA86726B0C227AA85AB8BBD2B2004F41A868A54F0 C5EA0B94

FILES

The keyfile can be designed by the key identification Knnnn.+aaa+iiiii or the full file name Knnnn.+aaa+iiiii.key as generated by dnssec-keygen(8).

The keyset file name is built from the directory, the string keyset- and the dnsname.

CAVEAT

A keyfile error can give a "file not found" even if the file exists.

SEE ALSO

dnssec-keygen(8) , dnssec-signzone(8) , BIND 9 Administrator Reference Manual, RFC 3658, RFC 4431. RFC 4509.

bind9-9.11.3+dfsg/bin/dnssec/dnssec-importkey.8000066400000000000000000000133011325250447100211520ustar00rootroot00000000000000.\" Copyright (C) 2013-2016 Internet Systems Consortium, Inc. ("ISC") .\" .\" This Source Code Form is subject to the terms of the Mozilla Public .\" License, v. 2.0. If a copy of the MPL was not distributed with this .\" file, You can obtain one at http://mozilla.org/MPL/2.0/. .\" .hy 0 .ad l '\" t .\" Title: dnssec-importkey .\" Author: .\" Generator: DocBook XSL Stylesheets v1.78.1 .\" Date: August 21, 2015 .\" Manual: BIND9 .\" Source: ISC .\" Language: English .\" .TH "DNSSEC\-IMPORTKEY" "8" "August 21, 2015" "ISC" "BIND9" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" dnssec-importkey \- import DNSKEY records from external systems so they can be managed .SH "SYNOPSIS" .HP \w'\fBdnssec\-importkey\fR\ 'u \fBdnssec\-importkey\fR [\fB\-K\ \fR\fB\fIdirectory\fR\fR] [\fB\-L\ \fR\fB\fIttl\fR\fR] [\fB\-P\ \fR\fB\fIdate/offset\fR\fR] [\fB\-P\ sync\ \fR\fB\fIdate/offset\fR\fR] [\fB\-D\ \fR\fB\fIdate/offset\fR\fR] [\fB\-D\ sync\ \fR\fB\fIdate/offset\fR\fR] [\fB\-h\fR] [\fB\-v\ \fR\fB\fIlevel\fR\fR] [\fB\-V\fR] {\fBkeyfile\fR} .HP \w'\fBdnssec\-importkey\fR\ 'u \fBdnssec\-importkey\fR {\fB\-f\ \fR\fB\fIfilename\fR\fR} [\fB\-K\ \fR\fB\fIdirectory\fR\fR] [\fB\-L\ \fR\fB\fIttl\fR\fR] [\fB\-P\ \fR\fB\fIdate/offset\fR\fR] [\fB\-P\ sync\ \fR\fB\fIdate/offset\fR\fR] [\fB\-D\ \fR\fB\fIdate/offset\fR\fR] [\fB\-D\ sync\ \fR\fB\fIdate/offset\fR\fR] [\fB\-h\fR] [\fB\-v\ \fR\fB\fIlevel\fR\fR] [\fB\-V\fR] [\fBdnsname\fR] .SH "DESCRIPTION" .PP \fBdnssec\-importkey\fR reads a public DNSKEY record and generates a pair of \&.key/\&.private files\&. The DNSKEY record may be read from an existing \&.key file, in which case a corresponding \&.private file will be generated, or it may be read from any other file or from the standard input, in which case both \&.key and \&.private files will be generated\&. .PP The newly\-created \&.private file does \fInot\fR contain private key data, and cannot be used for signing\&. However, having a \&.private file makes it possible to set publication (\fB\-P\fR) and deletion (\fB\-D\fR) times for the key, which means the public key can be added to and removed from the DNSKEY RRset on schedule even if the true private key is stored offline\&. .SH "OPTIONS" .PP \-f \fIfilename\fR .RS 4 Zone file mode: instead of a public keyfile name, the argument is the DNS domain name of a zone master file, which can be read from \fBfile\fR\&. If the domain name is the same as \fBfile\fR, then it may be omitted\&. .sp If \fBfile\fR is set to "\-", then the zone data is read from the standard input\&. .RE .PP \-K \fIdirectory\fR .RS 4 Sets the directory in which the key files are to reside\&. .RE .PP \-L \fIttl\fR .RS 4 Sets the default TTL to use for this key when it is converted into a DNSKEY RR\&. If the key is imported into a zone, this is the TTL that will be used for it, unless there was already a DNSKEY RRset in place, in which case the existing TTL would take precedence\&. Setting the default TTL to 0 or none removes it\&. .RE .PP \-h .RS 4 Emit usage message and exit\&. .RE .PP \-v \fIlevel\fR .RS 4 Sets the debugging level\&. .RE .PP \-V .RS 4 Prints version information\&. .RE .SH "TIMING OPTIONS" .PP Dates can be expressed in the format YYYYMMDD or YYYYMMDDHHMMSS\&. If the argument begins with a \*(Aq+\*(Aq or \*(Aq\-\*(Aq, it is interpreted as an offset from the present time\&. For convenience, if such an offset is followed by one of the suffixes \*(Aqy\*(Aq, \*(Aqmo\*(Aq, \*(Aqw\*(Aq, \*(Aqd\*(Aq, \*(Aqh\*(Aq, or \*(Aqmi\*(Aq, then the offset is computed in years (defined as 365 24\-hour days, ignoring leap years), months (defined as 30 24\-hour days), weeks, days, hours, or minutes, respectively\&. Without a suffix, the offset is computed in seconds\&. To explicitly prevent a date from being set, use \*(Aqnone\*(Aq or \*(Aqnever\*(Aq\&. .PP \-P \fIdate/offset\fR .RS 4 Sets the date on which a key is to be published to the zone\&. After that date, the key will be included in the zone but will not be used to sign it\&. .RE .PP \-P sync \fIdate/offset\fR .RS 4 Sets the date on which CDS and CDNSKEY records that match this key are to be published to the zone\&. .RE .PP \-D \fIdate/offset\fR .RS 4 Sets the date on which the key is to be deleted\&. After that date, the key will no longer be included in the zone\&. (It may remain in the key repository, however\&.) .RE .PP \-D sync \fIdate/offset\fR .RS 4 Sets the date on which the CDS and CDNSKEY records that match this key are to be deleted\&. .RE .SH "FILES" .PP A keyfile can be designed by the key identification Knnnn\&.+aaa+iiiii or the full file name Knnnn\&.+aaa+iiiii\&.key as generated by dnssec\-keygen(8)\&. .SH "SEE ALSO" .PP \fBdnssec-keygen\fR(8), \fBdnssec-signzone\fR(8), BIND 9 Administrator Reference Manual, RFC 5011\&. .SH "AUTHOR" .PP \fBInternet Systems Consortium, Inc\&.\fR .SH "COPYRIGHT" .br Copyright \(co 2013-2016 Internet Systems Consortium, Inc. ("ISC") .br bind9-9.11.3+dfsg/bin/dnssec/dnssec-importkey.c000066400000000000000000000303231325250447100212300ustar00rootroot00000000000000/* * Copyright (C) 2013-2016 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /*! \file */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef PKCS11CRYPTO #include #endif #include "dnssectool.h" #ifndef PATH_MAX #define PATH_MAX 1024 /* AIX, WIN32, and others don't define this. */ #endif const char *program = "dnssec-importkey"; int verbose; static dns_rdataclass_t rdclass; static dns_fixedname_t fixed; static dns_name_t *name = NULL; static isc_mem_t *mctx = NULL; static isc_boolean_t setpub = ISC_FALSE, setdel = ISC_FALSE; static isc_boolean_t setttl = ISC_FALSE; static isc_stdtime_t pub = 0, del = 0; static dns_ttl_t ttl = 0; static isc_stdtime_t syncadd = 0, syncdel = 0; static isc_boolean_t setsyncadd = ISC_FALSE; static isc_boolean_t setsyncdel = ISC_FALSE; static isc_result_t initname(char *setname) { isc_result_t result; isc_buffer_t buf; dns_fixedname_init(&fixed); name = dns_fixedname_name(&fixed); isc_buffer_init(&buf, setname, strlen(setname)); isc_buffer_add(&buf, strlen(setname)); result = dns_name_fromtext(name, &buf, dns_rootname, 0, NULL); return (result); } static void db_load_from_stream(dns_db_t *db, FILE *fp) { isc_result_t result; dns_rdatacallbacks_t callbacks; dns_rdatacallbacks_init(&callbacks); result = dns_db_beginload(db, &callbacks); if (result != ISC_R_SUCCESS) fatal("dns_db_beginload failed: %s", isc_result_totext(result)); result = dns_master_loadstream(fp, name, name, rdclass, 0, &callbacks, mctx); if (result != ISC_R_SUCCESS) fatal("can't load from input: %s", isc_result_totext(result)); result = dns_db_endload(db, &callbacks); if (result != ISC_R_SUCCESS) fatal("dns_db_endload failed: %s", isc_result_totext(result)); } static isc_result_t loadset(const char *filename, dns_rdataset_t *rdataset) { isc_result_t result; dns_db_t *db = NULL; dns_dbnode_t *node = NULL; char setname[DNS_NAME_FORMATSIZE]; dns_name_format(name, setname, sizeof(setname)); result = dns_db_create(mctx, "rbt", name, dns_dbtype_zone, rdclass, 0, NULL, &db); if (result != ISC_R_SUCCESS) fatal("can't create database"); if (strcmp(filename, "-") == 0) { db_load_from_stream(db, stdin); filename = "input"; } else { result = dns_db_load3(db, filename, dns_masterformat_text, DNS_MASTER_NOTTL); if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE) fatal("can't load %s: %s", filename, isc_result_totext(result)); } result = dns_db_findnode(db, name, ISC_FALSE, &node); if (result != ISC_R_SUCCESS) fatal("can't find %s node in %s", setname, filename); result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_dnskey, 0, 0, rdataset, NULL); if (result == ISC_R_NOTFOUND) fatal("no DNSKEY RR for %s in %s", setname, filename); else if (result != ISC_R_SUCCESS) fatal("dns_db_findrdataset"); if (node != NULL) dns_db_detachnode(db, &node); if (db != NULL) dns_db_detach(&db); return (result); } static void loadkey(char *filename, unsigned char *key_buf, unsigned int key_buf_size, dns_rdata_t *rdata) { isc_result_t result; dst_key_t *key = NULL; isc_buffer_t keyb; isc_region_t r; dns_rdata_init(rdata); isc_buffer_init(&keyb, key_buf, key_buf_size); result = dst_key_fromnamedfile(filename, NULL, DST_TYPE_PUBLIC, mctx, &key); if (result != ISC_R_SUCCESS) fatal("invalid keyfile name %s: %s", filename, isc_result_totext(result)); if (verbose > 2) { char keystr[DST_KEY_FORMATSIZE]; dst_key_format(key, keystr, sizeof(keystr)); fprintf(stderr, "%s: %s\n", program, keystr); } result = dst_key_todns(key, &keyb); if (result != ISC_R_SUCCESS) fatal("can't decode key"); isc_buffer_usedregion(&keyb, &r); dns_rdata_fromregion(rdata, dst_key_class(key), dns_rdatatype_dnskey, &r); rdclass = dst_key_class(key); dns_fixedname_init(&fixed); name = dns_fixedname_name(&fixed); result = dns_name_copy(dst_key_name(key), name, NULL); if (result != ISC_R_SUCCESS) fatal("can't copy name"); dst_key_free(&key); } static void emit(const char *dir, dns_rdata_t *rdata) { isc_result_t result; char keystr[DST_KEY_FORMATSIZE]; char pubname[1024]; char priname[1024]; isc_buffer_t buf; dst_key_t *key = NULL, *tmp = NULL; isc_buffer_init(&buf, rdata->data, rdata->length); isc_buffer_add(&buf, rdata->length); result = dst_key_fromdns(name, rdclass, &buf, mctx, &key); if (result != ISC_R_SUCCESS) { fatal("dst_key_fromdns: %s", isc_result_totext(result)); } isc_buffer_init(&buf, pubname, sizeof(pubname)); result = dst_key_buildfilename(key, DST_TYPE_PUBLIC, dir, &buf); if (result != ISC_R_SUCCESS) { fatal("Failed to build public key filename: %s", isc_result_totext(result)); } isc_buffer_init(&buf, priname, sizeof(priname)); result = dst_key_buildfilename(key, DST_TYPE_PRIVATE, dir, &buf); if (result != ISC_R_SUCCESS) { fatal("Failed to build private key filename: %s", isc_result_totext(result)); } result = dst_key_fromfile(dst_key_name(key), dst_key_id(key), dst_key_alg(key), DST_TYPE_PUBLIC | DST_TYPE_PRIVATE, dir, mctx, &tmp); if (result == ISC_R_SUCCESS) { if (dst_key_isprivate(tmp) && !dst_key_isexternal(tmp)) fatal("Private key already exists in %s", priname); dst_key_free(&tmp); } dst_key_setexternal(key, ISC_TRUE); if (setpub) dst_key_settime(key, DST_TIME_PUBLISH, pub); if (setdel) dst_key_settime(key, DST_TIME_DELETE, del); if (setsyncadd) dst_key_settime(key, DST_TIME_SYNCPUBLISH, syncadd); if (setsyncdel) dst_key_settime(key, DST_TIME_SYNCDELETE, syncdel); if (setttl) dst_key_setttl(key, ttl); result = dst_key_tofile(key, DST_TYPE_PUBLIC|DST_TYPE_PRIVATE, dir); if (result != ISC_R_SUCCESS) { dst_key_format(key, keystr, sizeof(keystr)); fatal("Failed to write key %s: %s", keystr, isc_result_totext(result)); } printf("%s\n", pubname); isc_buffer_clear(&buf); result = dst_key_buildfilename(key, DST_TYPE_PRIVATE, dir, &buf); if (result != ISC_R_SUCCESS) { fatal("Failed to build private key filename: %s", isc_result_totext(result)); } printf("%s\n", priname); dst_key_free(&key); } ISC_PLATFORM_NORETURN_PRE static void usage(void) ISC_PLATFORM_NORETURN_POST; static void usage(void) { fprintf(stderr, "Usage:\n"); fprintf(stderr, " %s options [-K dir] keyfile\n\n", program); fprintf(stderr, " %s options -f file [keyname]\n\n", program); fprintf(stderr, "Version: %s\n", VERSION); fprintf(stderr, "Options:\n"); fprintf(stderr, " -f file: read key from zone file\n"); fprintf(stderr, " -K : directory in which to store " "the key files\n"); fprintf(stderr, " -L ttl: set default key TTL\n"); fprintf(stderr, " -v \n"); fprintf(stderr, " -V: print version information\n"); fprintf(stderr, " -h: print usage and exit\n"); fprintf(stderr, "Timing options:\n"); fprintf(stderr, " -P date/[+-]offset/none: set/unset key " "publication date\n"); fprintf(stderr, " -P sync date/[+-]offset/none: set/unset " "CDS and CDNSKEY publication date\n"); fprintf(stderr, " -D date/[+-]offset/none: set/unset key " "deletion date\n"); fprintf(stderr, " -D sync date/[+-]offset/none: set/unset " "CDS and CDNSKEY deletion date\n"); exit (-1); } int main(int argc, char **argv) { char *classname = NULL; char *filename = NULL, *dir = NULL, *namestr; char *endp; int ch; isc_result_t result; isc_log_t *log = NULL; isc_entropy_t *ectx = NULL; dns_rdataset_t rdataset; dns_rdata_t rdata; isc_stdtime_t now; dns_rdata_init(&rdata); isc_stdtime_get(&now); if (argc == 1) usage(); result = isc_mem_create(0, 0, &mctx); if (result != ISC_R_SUCCESS) fatal("out of memory"); #ifdef PKCS11CRYPTO pk11_result_register(); #endif dns_result_register(); isc_commandline_errprint = ISC_FALSE; #define CMDLINE_FLAGS "D:f:hK:L:P:v:V" while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) { switch (ch) { case 'D': /* -Dsync ? */ if (isoptarg("sync", argv, usage)) { if (setsyncdel) fatal("-D sync specified more than " "once"); syncdel = strtotime(isc_commandline_argument, now, now, &setsyncdel); break; } /* -Ddnskey ? */ (void)isoptarg("dnskey", argv, usage); if (setdel) fatal("-D specified more than once"); del = strtotime(isc_commandline_argument, now, now, &setdel); break; case 'K': dir = isc_commandline_argument; if (strlen(dir) == 0U) fatal("directory must be non-empty string"); break; case 'L': ttl = strtottl(isc_commandline_argument); setttl = ISC_TRUE; break; case 'P': /* -Psync ? */ if (isoptarg("sync", argv, usage)) { if (setsyncadd) fatal("-P sync specified more than " "once"); syncadd = strtotime(isc_commandline_argument, now, now, &setsyncadd); break; } /* -Pdnskey ? */ (void)isoptarg("dnskey", argv, usage); if (setpub) fatal("-P specified more than once"); pub = strtotime(isc_commandline_argument, now, now, &setpub); break; case 'f': filename = isc_commandline_argument; break; case 'v': verbose = strtol(isc_commandline_argument, &endp, 0); if (*endp != '\0') fatal("-v must be followed by a number"); break; case '?': if (isc_commandline_option != '?') fprintf(stderr, "%s: invalid argument -%c\n", program, isc_commandline_option); /* FALLTHROUGH */ case 'h': /* Does not return. */ usage(); case 'V': /* Does not return. */ version(program); default: fprintf(stderr, "%s: unhandled option -%c\n", program, isc_commandline_option); exit(1); } } rdclass = strtoclass(classname); if (argc < isc_commandline_index + 1 && filename == NULL) fatal("the key file name was not specified"); if (argc > isc_commandline_index + 1) fatal("extraneous arguments"); if (ectx == NULL) setup_entropy(mctx, NULL, &ectx); result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE); if (result != ISC_R_SUCCESS) fatal("could not initialize hash"); result = dst_lib_init(mctx, ectx, ISC_ENTROPY_BLOCKING | ISC_ENTROPY_GOODONLY); if (result != ISC_R_SUCCESS) fatal("could not initialize dst: %s", isc_result_totext(result)); isc_entropy_stopcallbacksources(ectx); setup_logging(mctx, &log); dns_rdataset_init(&rdataset); if (filename != NULL) { if (argc < isc_commandline_index + 1) { /* using filename as zone name */ namestr = filename; } else namestr = argv[isc_commandline_index]; result = initname(namestr); if (result != ISC_R_SUCCESS) fatal("could not initialize name %s", namestr); result = loadset(filename, &rdataset); if (result != ISC_R_SUCCESS) fatal("could not load DNSKEY set: %s\n", isc_result_totext(result)); for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS; result = dns_rdataset_next(&rdataset)) { dns_rdata_init(&rdata); dns_rdataset_current(&rdataset, &rdata); emit(dir, &rdata); } } else { unsigned char key_buf[DST_KEY_MAXSIZE]; loadkey(argv[isc_commandline_index], key_buf, DST_KEY_MAXSIZE, &rdata); emit(dir, &rdata); } if (dns_rdataset_isassociated(&rdataset)) dns_rdataset_disassociate(&rdataset); cleanup_logging(&log); dst_lib_destroy(); isc_hash_destroy(); cleanup_entropy(&ectx); dns_name_destroy(); if (verbose > 10) isc_mem_stats(mctx, stdout); isc_mem_destroy(&mctx); fflush(stdout); if (ferror(stdout)) { fprintf(stderr, "write error\n"); return (1); } else return (0); } bind9-9.11.3+dfsg/bin/dnssec/dnssec-importkey.docbook000066400000000000000000000220711325250447100224270ustar00rootroot00000000000000 2014-02-20 August 21, 2015 ISC Internet Systems Consortium, Inc. dnssec-importkey 8 BIND9 dnssec-importkey import DNSKEY records from external systems so they can be managed 2013 2014 2015 2016 Internet Systems Consortium, Inc. ("ISC") dnssec-importkey dnssec-importkey DESCRIPTION dnssec-importkey reads a public DNSKEY record and generates a pair of .key/.private files. The DNSKEY record may be read from an existing .key file, in which case a corresponding .private file will be generated, or it may be read from any other file or from the standard input, in which case both .key and .private files will be generated. The newly-created .private file does not contain private key data, and cannot be used for signing. However, having a .private file makes it possible to set publication () and deletion () times for the key, which means the public key can be added to and removed from the DNSKEY RRset on schedule even if the true private key is stored offline. OPTIONS -f filename Zone file mode: instead of a public keyfile name, the argument is the DNS domain name of a zone master file, which can be read from . If the domain name is the same as , then it may be omitted. If is set to "-", then the zone data is read from the standard input. -K directory Sets the directory in which the key files are to reside. -L ttl Sets the default TTL to use for this key when it is converted into a DNSKEY RR. If the key is imported into a zone, this is the TTL that will be used for it, unless there was already a DNSKEY RRset in place, in which case the existing TTL would take precedence. Setting the default TTL to 0 or none removes it. -h Emit usage message and exit. -v level Sets the debugging level. -V Prints version information. TIMING OPTIONS Dates can be expressed in the format YYYYMMDD or YYYYMMDDHHMMSS. If the argument begins with a '+' or '-', it is interpreted as an offset from the present time. For convenience, if such an offset is followed by one of the suffixes 'y', 'mo', 'w', 'd', 'h', or 'mi', then the offset is computed in years (defined as 365 24-hour days, ignoring leap years), months (defined as 30 24-hour days), weeks, days, hours, or minutes, respectively. Without a suffix, the offset is computed in seconds. To explicitly prevent a date from being set, use 'none' or 'never'. -P date/offset Sets the date on which a key is to be published to the zone. After that date, the key will be included in the zone but will not be used to sign it. -P sync date/offset Sets the date on which CDS and CDNSKEY records that match this key are to be published to the zone. -D date/offset Sets the date on which the key is to be deleted. After that date, the key will no longer be included in the zone. (It may remain in the key repository, however.) -D sync date/offset Sets the date on which the CDS and CDNSKEY records that match this key are to be deleted. FILES A keyfile can be designed by the key identification Knnnn.+aaa+iiiii or the full file name Knnnn.+aaa+iiiii.key as generated by dnssec-keygen8. SEE ALSO dnssec-keygen8 , dnssec-signzone8 , BIND 9 Administrator Reference Manual, RFC 5011. bind9-9.11.3+dfsg/bin/dnssec/dnssec-importkey.html000066400000000000000000000200531325250447100217510ustar00rootroot00000000000000 dnssec-importkey

Name

dnssec-importkey — import DNSKEY records from external systems so they can be managed

Synopsis

dnssec-importkey [-K directory] [-L ttl] [-P date/offset] [-P sync date/offset] [-D date/offset] [-D sync date/offset] [-h] [-v level] [-V] {keyfile}

dnssec-importkey {-f filename} [-K directory] [-L ttl] [-P date/offset] [-P sync date/offset] [-D date/offset] [-D sync date/offset] [-h] [-v level] [-V] [dnsname]

DESCRIPTION

dnssec-importkey reads a public DNSKEY record and generates a pair of .key/.private files. The DNSKEY record may be read from an existing .key file, in which case a corresponding .private file will be generated, or it may be read from any other file or from the standard input, in which case both .key and .private files will be generated.

The newly-created .private file does not contain private key data, and cannot be used for signing. However, having a .private file makes it possible to set publication (-P) and deletion (-D) times for the key, which means the public key can be added to and removed from the DNSKEY RRset on schedule even if the true private key is stored offline.

OPTIONS

-f filename

Zone file mode: instead of a public keyfile name, the argument is the DNS domain name of a zone master file, which can be read from file. If the domain name is the same as file, then it may be omitted.

If file is set to "-", then the zone data is read from the standard input.

-K directory

Sets the directory in which the key files are to reside.

-L ttl

Sets the default TTL to use for this key when it is converted into a DNSKEY RR. If the key is imported into a zone, this is the TTL that will be used for it, unless there was already a DNSKEY RRset in place, in which case the existing TTL would take precedence. Setting the default TTL to 0 or none removes it.

-h

Emit usage message and exit.

-v level

Sets the debugging level.

-V

Prints version information.

TIMING OPTIONS

Dates can be expressed in the format YYYYMMDD or YYYYMMDDHHMMSS. If the argument begins with a '+' or '-', it is interpreted as an offset from the present time. For convenience, if such an offset is followed by one of the suffixes 'y', 'mo', 'w', 'd', 'h', or 'mi', then the offset is computed in years (defined as 365 24-hour days, ignoring leap years), months (defined as 30 24-hour days), weeks, days, hours, or minutes, respectively. Without a suffix, the offset is computed in seconds. To explicitly prevent a date from being set, use 'none' or 'never'.

-P date/offset

Sets the date on which a key is to be published to the zone. After that date, the key will be included in the zone but will not be used to sign it.

-P sync date/offset

Sets the date on which CDS and CDNSKEY records that match this key are to be published to the zone.

-D date/offset

Sets the date on which the key is to be deleted. After that date, the key will no longer be included in the zone. (It may remain in the key repository, however.)

-D sync date/offset

Sets the date on which the CDS and CDNSKEY records that match this key are to be deleted.

FILES

A keyfile can be designed by the key identification Knnnn.+aaa+iiiii or the full file name Knnnn.+aaa+iiiii.key as generated by dnssec-keygen(8).

SEE ALSO

dnssec-keygen(8) , dnssec-signzone(8) , BIND 9 Administrator Reference Manual, RFC 5011.

bind9-9.11.3+dfsg/bin/dnssec/dnssec-keyfromlabel.8000066400000000000000000000311661325250447100216140ustar00rootroot00000000000000.\" Copyright (C) 2008-2012, 2014-2017 Internet Systems Consortium, Inc. ("ISC") .\" .\" This Source Code Form is subject to the terms of the Mozilla Public .\" License, v. 2.0. If a copy of the MPL was not distributed with this .\" file, You can obtain one at http://mozilla.org/MPL/2.0/. .\" .hy 0 .ad l '\" t .\" Title: dnssec-keyfromlabel .\" Author: .\" Generator: DocBook XSL Stylesheets v1.78.1 .\" Date: August 27, 2015 .\" Manual: BIND9 .\" Source: ISC .\" Language: English .\" .TH "DNSSEC\-KEYFROMLABEL" "8" "August 27, 2015" "ISC" "BIND9" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" dnssec-keyfromlabel \- DNSSEC key generation tool .SH "SYNOPSIS" .HP \w'\fBdnssec\-keyfromlabel\fR\ 'u \fBdnssec\-keyfromlabel\fR {\-l\ \fIlabel\fR} [\fB\-3\fR] [\fB\-a\ \fR\fB\fIalgorithm\fR\fR] [\fB\-A\ \fR\fB\fIdate/offset\fR\fR] [\fB\-c\ \fR\fB\fIclass\fR\fR] [\fB\-D\ \fR\fB\fIdate/offset\fR\fR] [\fB\-D\ sync\ \fR\fB\fIdate/offset\fR\fR] [\fB\-E\ \fR\fB\fIengine\fR\fR] [\fB\-f\ \fR\fB\fIflag\fR\fR] [\fB\-G\fR] [\fB\-I\ \fR\fB\fIdate/offset\fR\fR] [\fB\-i\ \fR\fB\fIinterval\fR\fR] [\fB\-k\fR] [\fB\-K\ \fR\fB\fIdirectory\fR\fR] [\fB\-L\ \fR\fB\fIttl\fR\fR] [\fB\-n\ \fR\fB\fInametype\fR\fR] [\fB\-P\ \fR\fB\fIdate/offset\fR\fR] [\fB\-P\ sync\ \fR\fB\fIdate/offset\fR\fR] [\fB\-p\ \fR\fB\fIprotocol\fR\fR] [\fB\-R\ \fR\fB\fIdate/offset\fR\fR] [\fB\-S\ \fR\fB\fIkey\fR\fR] [\fB\-t\ \fR\fB\fItype\fR\fR] [\fB\-v\ \fR\fB\fIlevel\fR\fR] [\fB\-V\fR] [\fB\-y\fR] {name} .SH "DESCRIPTION" .PP \fBdnssec\-keyfromlabel\fR generates a key pair of files that referencing a key object stored in a cryptographic hardware service module (HSM)\&. The private key file can be used for DNSSEC signing of zone data as if it were a conventional signing key created by \fBdnssec\-keygen\fR, but the key material is stored within the HSM, and the actual signing takes place there\&. .PP The \fBname\fR of the key is specified on the command line\&. This must match the name of the zone for which the key is being generated\&. .SH "OPTIONS" .PP \-a \fIalgorithm\fR .RS 4 Selects the cryptographic algorithm\&. The value of \fBalgorithm\fR must be one of RSAMD5, RSASHA1, DSA, NSEC3RSASHA1, NSEC3DSA, RSASHA256, RSASHA512, ECCGOST, ECDSAP256SHA256, ECDSAP384SHA384, ED25519 or ED448\&. These values are case insensitive\&. .sp If no algorithm is specified, then RSASHA1 will be used by default, unless the \fB\-3\fR option is specified, in which case NSEC3RSASHA1 will be used instead\&. (If \fB\-3\fR is used and an algorithm is specified, that algorithm will be checked for compatibility with NSEC3\&.) .sp Note 1: that for DNSSEC, RSASHA1 is a mandatory to implement algorithm, and DSA is recommended\&. .sp Note 2: DH automatically sets the \-k flag\&. .RE .PP \-3 .RS 4 Use an NSEC3\-capable algorithm to generate a DNSSEC key\&. If this option is used and no algorithm is explicitly set on the command line, NSEC3RSASHA1 will be used by default\&. .RE .PP \-E \fIengine\fR .RS 4 Specifies the cryptographic hardware to use\&. .sp When BIND is built with OpenSSL PKCS#11 support, this defaults to the string "pkcs11", which identifies an OpenSSL engine that can drive a cryptographic accelerator or hardware service module\&. When BIND is built with native PKCS#11 cryptography (\-\-enable\-native\-pkcs11), it defaults to the path of the PKCS#11 provider library specified via "\-\-with\-pkcs11"\&. .RE .PP \-l \fIlabel\fR .RS 4 Specifies the label for a key pair in the crypto hardware\&. .sp When BIND 9 is built with OpenSSL\-based PKCS#11 support, the label is an arbitrary string that identifies a particular key\&. It may be preceded by an optional OpenSSL engine name, followed by a colon, as in "pkcs11:\fIkeylabel\fR"\&. .sp When BIND 9 is built with native PKCS#11 support, the label is a PKCS#11 URI string in the format "pkcs11:\fBkeyword\fR=\fIvalue\fR[;\fBkeyword\fR=\fIvalue\fR;\&.\&.\&.]" Keywords include "token", which identifies the HSM; "object", which identifies the key; and "pin\-source", which identifies a file from which the HSM\*(Aqs PIN code can be obtained\&. The label will be stored in the on\-disk "private" file\&. .sp If the label contains a \fBpin\-source\fR field, tools using the generated key files will be able to use the HSM for signing and other operations without any need for an operator to manually enter a PIN\&. Note: Making the HSM\*(Aqs PIN accessible in this manner may reduce the security advantage of using an HSM; be sure this is what you want to do before making use of this feature\&. .RE .PP \-n \fInametype\fR .RS 4 Specifies the owner type of the key\&. The value of \fBnametype\fR must either be ZONE (for a DNSSEC zone key (KEY/DNSKEY)), HOST or ENTITY (for a key associated with a host (KEY)), USER (for a key associated with a user(KEY)) or OTHER (DNSKEY)\&. These values are case insensitive\&. .RE .PP \-C .RS 4 Compatibility mode: generates an old\-style key, without any metadata\&. By default, \fBdnssec\-keyfromlabel\fR will include the key\*(Aqs creation date in the metadata stored with the private key, and other dates may be set there as well (publication date, activation date, etc)\&. Keys that include this data may be incompatible with older versions of BIND; the \fB\-C\fR option suppresses them\&. .RE .PP \-c \fIclass\fR .RS 4 Indicates that the DNS record containing the key should have the specified class\&. If not specified, class IN is used\&. .RE .PP \-f \fIflag\fR .RS 4 Set the specified flag in the flag field of the KEY/DNSKEY record\&. The only recognized flags are KSK (Key Signing Key) and REVOKE\&. .RE .PP \-G .RS 4 Generate a key, but do not publish it or sign with it\&. This option is incompatible with \-P and \-A\&. .RE .PP \-h .RS 4 Prints a short summary of the options and arguments to \fBdnssec\-keyfromlabel\fR\&. .RE .PP \-K \fIdirectory\fR .RS 4 Sets the directory in which the key files are to be written\&. .RE .PP \-k .RS 4 Generate KEY records rather than DNSKEY records\&. .RE .PP \-L \fIttl\fR .RS 4 Sets the default TTL to use for this key when it is converted into a DNSKEY RR\&. If the key is imported into a zone, this is the TTL that will be used for it, unless there was already a DNSKEY RRset in place, in which case the existing TTL would take precedence\&. Setting the default TTL to 0 or none removes it\&. .RE .PP \-p \fIprotocol\fR .RS 4 Sets the protocol value for the key\&. The protocol is a number between 0 and 255\&. The default is 3 (DNSSEC)\&. Other possible values for this argument are listed in RFC 2535 and its successors\&. .RE .PP \-S \fIkey\fR .RS 4 Generate a key as an explicit successor to an existing key\&. The name, algorithm, size, and type of the key will be set to match the predecessor\&. The activation date of the new key will be set to the inactivation date of the existing one\&. The publication date will be set to the activation date minus the prepublication interval, which defaults to 30 days\&. .RE .PP \-t \fItype\fR .RS 4 Indicates the use of the key\&. \fBtype\fR must be one of AUTHCONF, NOAUTHCONF, NOAUTH, or NOCONF\&. The default is AUTHCONF\&. AUTH refers to the ability to authenticate data, and CONF the ability to encrypt data\&. .RE .PP \-v \fIlevel\fR .RS 4 Sets the debugging level\&. .RE .PP \-V .RS 4 Prints version information\&. .RE .PP \-y .RS 4 Allows DNSSEC key files to be generated even if the key ID would collide with that of an existing key, in the event of either key being revoked\&. (This is only safe to use if you are sure you won\*(Aqt be using RFC 5011 trust anchor maintenance with either of the keys involved\&.) .RE .SH "TIMING OPTIONS" .PP Dates can be expressed in the format YYYYMMDD or YYYYMMDDHHMMSS\&. If the argument begins with a \*(Aq+\*(Aq or \*(Aq\-\*(Aq, it is interpreted as an offset from the present time\&. For convenience, if such an offset is followed by one of the suffixes \*(Aqy\*(Aq, \*(Aqmo\*(Aq, \*(Aqw\*(Aq, \*(Aqd\*(Aq, \*(Aqh\*(Aq, or \*(Aqmi\*(Aq, then the offset is computed in years (defined as 365 24\-hour days, ignoring leap years), months (defined as 30 24\-hour days), weeks, days, hours, or minutes, respectively\&. Without a suffix, the offset is computed in seconds\&. To explicitly prevent a date from being set, use \*(Aqnone\*(Aq or \*(Aqnever\*(Aq\&. .PP \-P \fIdate/offset\fR .RS 4 Sets the date on which a key is to be published to the zone\&. After that date, the key will be included in the zone but will not be used to sign it\&. If not set, and if the \-G option has not been used, the default is "now"\&. .RE .PP \-P sync \fIdate/offset\fR .RS 4 Sets the date on which the CDS and CDNSKEY records which match this key are to be published to the zone\&. .RE .PP \-A \fIdate/offset\fR .RS 4 Sets the date on which the key is to be activated\&. After that date, the key will be included in the zone and used to sign it\&. If not set, and if the \-G option has not been used, the default is "now"\&. .RE .PP \-R \fIdate/offset\fR .RS 4 Sets the date on which the key is to be revoked\&. After that date, the key will be flagged as revoked\&. It will be included in the zone and will be used to sign it\&. .RE .PP \-I \fIdate/offset\fR .RS 4 Sets the date on which the key is to be retired\&. After that date, the key will still be included in the zone, but it will not be used to sign it\&. .RE .PP \-D \fIdate/offset\fR .RS 4 Sets the date on which the key is to be deleted\&. After that date, the key will no longer be included in the zone\&. (It may remain in the key repository, however\&.) .RE .PP \-D sync \fIdate/offset\fR .RS 4 Sets the date on which the CDS and CDNSKEY records which match this key are to be deleted\&. .RE .PP \-i \fIinterval\fR .RS 4 Sets the prepublication interval for a key\&. If set, then the publication and activation dates must be separated by at least this much time\&. If the activation date is specified but the publication date isn\*(Aqt, then the publication date will default to this much time before the activation date; conversely, if the publication date is specified but activation date isn\*(Aqt, then activation will be set to this much time after publication\&. .sp If the key is being created as an explicit successor to another key, then the default prepublication interval is 30 days; otherwise it is zero\&. .sp As with date offsets, if the argument is followed by one of the suffixes \*(Aqy\*(Aq, \*(Aqmo\*(Aq, \*(Aqw\*(Aq, \*(Aqd\*(Aq, \*(Aqh\*(Aq, or \*(Aqmi\*(Aq, then the interval is measured in years, months, weeks, days, hours, or minutes, respectively\&. Without a suffix, the interval is measured in seconds\&. .RE .SH "GENERATED KEY FILES" .PP When \fBdnssec\-keyfromlabel\fR completes successfully, it prints a string of the form Knnnn\&.+aaa+iiiii to the standard output\&. This is an identification string for the key files it has generated\&. .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} nnnn is the key name\&. .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} aaa is the numeric representation of the algorithm\&. .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} iiiii is the key identifier (or footprint)\&. .RE .PP \fBdnssec\-keyfromlabel\fR creates two files, with names based on the printed string\&. Knnnn\&.+aaa+iiiii\&.key contains the public key, and Knnnn\&.+aaa+iiiii\&.private contains the private key\&. .PP The \&.key file contains a DNS KEY record that can be inserted into a zone file (directly or with a $INCLUDE statement)\&. .PP The \&.private file contains algorithm\-specific fields\&. For obvious security reasons, this file does not have general read permission\&. .SH "SEE ALSO" .PP \fBdnssec-keygen\fR(8), \fBdnssec-signzone\fR(8), BIND 9 Administrator Reference Manual, RFC 4034, The PKCS#11 URI Scheme (draft\-pechanec\-pkcs11uri\-13)\&. .SH "AUTHOR" .PP \fBInternet Systems Consortium, Inc\&.\fR .SH "COPYRIGHT" .br Copyright \(co 2008-2012, 2014-2017 Internet Systems Consortium, Inc. ("ISC") .br bind9-9.11.3+dfsg/bin/dnssec/dnssec-keyfromlabel.c000066400000000000000000000524671325250447100216760ustar00rootroot00000000000000/* * Copyright (C) 2007-2012, 2014-2018 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /*! \file */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef PKCS11CRYPTO #include #endif #include "dnssectool.h" #define MAX_RSA 4096 /* should be long enough... */ const char *program = "dnssec-keyfromlabel"; int verbose; #define DEFAULT_ALGORITHM "RSASHA1" #define DEFAULT_NSEC3_ALGORITHM "NSEC3RSASHA1" static const char *algs = "RSA | RSAMD5 | DH | DSA | RSASHA1 |" " NSEC3DSA | NSEC3RSASHA1 |" " RSASHA256 | RSASHA512 | ECCGOST |" " ECDSAP256SHA256 | ECDSAP384SHA384 |" " ED25519 | ED448"; ISC_PLATFORM_NORETURN_PRE static void usage(void) ISC_PLATFORM_NORETURN_POST; static void usage(void) { fprintf(stderr, "Usage:\n"); fprintf(stderr, " %s -l label [options] name\n\n", program); fprintf(stderr, "Version: %s\n", VERSION); fprintf(stderr, "Required options:\n"); fprintf(stderr, " -l label: label of the key pair\n"); fprintf(stderr, " name: owner of the key\n"); fprintf(stderr, "Other options:\n"); fprintf(stderr, " -a algorithm: %s\n", algs); fprintf(stderr, " (default: RSASHA1, or " "NSEC3RSASHA1 if using -3)\n"); fprintf(stderr, " -3: use NSEC3-capable algorithm\n"); fprintf(stderr, " -c class (default: IN)\n"); fprintf(stderr, " -E :\n"); #if defined(PKCS11CRYPTO) fprintf(stderr, " path to PKCS#11 provider library " "(default is %s)\n", PK11_LIB_LOCATION); #elif defined(USE_PKCS11) fprintf(stderr, " name of an OpenSSL engine to use " "(default is \"pkcs11\")\n"); #else fprintf(stderr, " name of an OpenSSL engine to use\n"); #endif fprintf(stderr, " -f keyflag: KSK | REVOKE\n"); fprintf(stderr, " -K directory: directory in which to place " "key files\n"); fprintf(stderr, " -k: generate a TYPE=KEY key\n"); fprintf(stderr, " -L ttl: default key TTL\n"); fprintf(stderr, " -n nametype: ZONE | HOST | ENTITY | USER | OTHER\n"); fprintf(stderr, " (DNSKEY generation defaults to ZONE\n"); fprintf(stderr, " -p protocol: default: 3 [dnssec]\n"); fprintf(stderr, " -t type: " "AUTHCONF | NOAUTHCONF | NOAUTH | NOCONF " "(default: AUTHCONF)\n"); fprintf(stderr, " -y: permit keys that might collide\n"); fprintf(stderr, " -v verbose level\n"); fprintf(stderr, " -V: print version information\n"); fprintf(stderr, "Date options:\n"); fprintf(stderr, " -P date/[+-]offset: set key publication date\n"); fprintf(stderr, " -P sync date/[+-]offset: set CDS and CDNSKEY " "publication date\n"); fprintf(stderr, " -A date/[+-]offset: set key activation date\n"); fprintf(stderr, " -R date/[+-]offset: set key revocation date\n"); fprintf(stderr, " -I date/[+-]offset: set key inactivation date\n"); fprintf(stderr, " -D date/[+-]offset: set key deletion date\n"); fprintf(stderr, " -D sync date/[+-]offset: set CDS and CDNSKEY " "deletion date\n"); fprintf(stderr, " -G: generate key only; do not set -P or -A\n"); fprintf(stderr, " -C: generate a backward-compatible key, omitting" " all dates\n"); fprintf(stderr, " -S : generate a successor to an existing " "key\n"); fprintf(stderr, " -i : prepublication interval for " "successor key " "(default: 30 days)\n"); fprintf(stderr, "Output:\n"); fprintf(stderr, " K++.key, " "K++.private\n"); exit (-1); } int main(int argc, char **argv) { char *algname = NULL, *freeit = NULL; char *nametype = NULL, *type = NULL; const char *directory = NULL; const char *predecessor = NULL; dst_key_t *prevkey = NULL; #ifdef USE_PKCS11 const char *engine = PKCS11_ENGINE; #else const char *engine = NULL; #endif char *classname = NULL; char *endp; dst_key_t *key = NULL; dns_fixedname_t fname; dns_name_t *name; isc_uint16_t flags = 0, kskflag = 0, revflag = 0; dns_secalg_t alg; isc_boolean_t oldstyle = ISC_FALSE; isc_mem_t *mctx = NULL; int ch; int protocol = -1, signatory = 0; isc_result_t ret; isc_textregion_t r; char filename[255]; isc_buffer_t buf; isc_log_t *log = NULL; isc_entropy_t *ectx = NULL; dns_rdataclass_t rdclass; int options = DST_TYPE_PRIVATE | DST_TYPE_PUBLIC; char *label = NULL; dns_ttl_t ttl = 0; isc_stdtime_t publish = 0, activate = 0, revoke = 0; isc_stdtime_t inactive = 0, deltime = 0; isc_stdtime_t now; int prepub = -1; isc_boolean_t setpub = ISC_FALSE, setact = ISC_FALSE; isc_boolean_t setrev = ISC_FALSE, setinact = ISC_FALSE; isc_boolean_t setdel = ISC_FALSE, setttl = ISC_FALSE; isc_boolean_t unsetpub = ISC_FALSE, unsetact = ISC_FALSE; isc_boolean_t unsetrev = ISC_FALSE, unsetinact = ISC_FALSE; isc_boolean_t unsetdel = ISC_FALSE; isc_boolean_t genonly = ISC_FALSE; isc_boolean_t use_nsec3 = ISC_FALSE; isc_boolean_t avoid_collisions = ISC_TRUE; isc_boolean_t exact; unsigned char c; isc_stdtime_t syncadd = 0, syncdel = 0; isc_boolean_t unsetsyncadd = ISC_FALSE, setsyncadd = ISC_FALSE; isc_boolean_t unsetsyncdel = ISC_FALSE, setsyncdel = ISC_FALSE; if (argc == 1) usage(); RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS); #ifdef PKCS11CRYPTO pk11_result_register(); #endif dns_result_register(); isc_commandline_errprint = ISC_FALSE; isc_stdtime_get(&now); #define CMDLINE_FLAGS "3A:a:Cc:D:E:Ff:GhI:i:kK:L:l:n:P:p:R:S:t:v:Vy" while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) { switch (ch) { case '3': use_nsec3 = ISC_TRUE; break; case 'a': algname = isc_commandline_argument; break; case 'C': oldstyle = ISC_TRUE; break; case 'c': classname = isc_commandline_argument; break; case 'E': engine = isc_commandline_argument; break; case 'f': c = (unsigned char)(isc_commandline_argument[0]); if (toupper(c) == 'K') kskflag = DNS_KEYFLAG_KSK; else if (toupper(c) == 'R') revflag = DNS_KEYFLAG_REVOKE; else fatal("unknown flag '%s'", isc_commandline_argument); break; case 'K': directory = isc_commandline_argument; ret = try_dir(directory); if (ret != ISC_R_SUCCESS) fatal("cannot open directory %s: %s", directory, isc_result_totext(ret)); break; case 'k': options |= DST_TYPE_KEY; break; case 'L': ttl = strtottl(isc_commandline_argument); setttl = ISC_TRUE; break; case 'l': label = isc_mem_strdup(mctx, isc_commandline_argument); break; case 'n': nametype = isc_commandline_argument; break; case 'p': protocol = strtol(isc_commandline_argument, &endp, 10); if (*endp != '\0' || protocol < 0 || protocol > 255) fatal("-p must be followed by a number " "[0..255]"); break; case 't': type = isc_commandline_argument; break; case 'v': verbose = strtol(isc_commandline_argument, &endp, 0); if (*endp != '\0') fatal("-v must be followed by a number"); break; case 'y': avoid_collisions = ISC_FALSE; break; case 'G': genonly = ISC_TRUE; break; case 'P': /* -Psync ? */ if (isoptarg("sync", argv, usage)) { if (unsetsyncadd || setsyncadd) fatal("-P sync specified more than " "once"); syncadd = strtotime(isc_commandline_argument, now, now, &setsyncadd); unsetsyncadd = !setsyncadd; break; } /* -Pdnskey ? */ (void)isoptarg("dnskey", argv, usage); if (setpub || unsetpub) fatal("-P specified more than once"); publish = strtotime(isc_commandline_argument, now, now, &setpub); unsetpub = !setpub; break; case 'A': if (setact || unsetact) fatal("-A specified more than once"); activate = strtotime(isc_commandline_argument, now, now, &setact); unsetact = !setact; break; case 'R': if (setrev || unsetrev) fatal("-R specified more than once"); revoke = strtotime(isc_commandline_argument, now, now, &setrev); unsetrev = !setrev; break; case 'I': if (setinact || unsetinact) fatal("-I specified more than once"); inactive = strtotime(isc_commandline_argument, now, now, &setinact); unsetinact = !setinact; break; case 'D': /* -Dsync ? */ if (isoptarg("sync", argv, usage)) { if (unsetsyncdel || setsyncdel) fatal("-D sync specified more than " "once"); syncdel = strtotime(isc_commandline_argument, now, now, &setsyncdel); unsetsyncdel = !setsyncdel; break; } /* -Ddnskey ? */ (void)isoptarg("dnskey", argv, usage); if (setdel || unsetdel) fatal("-D specified more than once"); deltime = strtotime(isc_commandline_argument, now, now, &setdel); unsetdel = !setdel; break; case 'S': predecessor = isc_commandline_argument; break; case 'i': prepub = strtottl(isc_commandline_argument); break; case 'F': /* Reserved for FIPS mode */ /* FALLTHROUGH */ case '?': if (isc_commandline_option != '?') fprintf(stderr, "%s: invalid argument -%c\n", program, isc_commandline_option); /* FALLTHROUGH */ case 'h': /* Does not return. */ usage(); case 'V': /* Does not return. */ version(program); default: fprintf(stderr, "%s: unhandled option -%c\n", program, isc_commandline_option); exit(1); } } if (ectx == NULL) setup_entropy(mctx, NULL, &ectx); ret = dst_lib_init2(mctx, ectx, engine, ISC_ENTROPY_BLOCKING | ISC_ENTROPY_GOODONLY); if (ret != ISC_R_SUCCESS) fatal("could not initialize dst: %s", isc_result_totext(ret)); setup_logging(mctx, &log); if (predecessor == NULL) { if (label == NULL) fatal("the key label was not specified"); if (argc < isc_commandline_index + 1) fatal("the key name was not specified"); if (argc > isc_commandline_index + 1) fatal("extraneous arguments"); dns_fixedname_init(&fname); name = dns_fixedname_name(&fname); isc_buffer_init(&buf, argv[isc_commandline_index], strlen(argv[isc_commandline_index])); isc_buffer_add(&buf, strlen(argv[isc_commandline_index])); ret = dns_name_fromtext(name, &buf, dns_rootname, 0, NULL); if (ret != ISC_R_SUCCESS) fatal("invalid key name %s: %s", argv[isc_commandline_index], isc_result_totext(ret)); if (strchr(label, ':') == NULL) { char *l; int len; len = strlen(label) + 8; l = isc_mem_allocate(mctx, len); if (l == NULL) fatal("cannot allocate memory"); snprintf(l, len, "pkcs11:%s", label); isc_mem_free(mctx, label); label = l; } if (algname == NULL) { if (use_nsec3) algname = strdup(DEFAULT_NSEC3_ALGORITHM); else algname = strdup(DEFAULT_ALGORITHM); if (algname == NULL) fatal("strdup failed"); freeit = algname; if (verbose > 0) fprintf(stderr, "no algorithm specified; " "defaulting to %s\n", algname); } if (strcasecmp(algname, "RSA") == 0) { #ifndef PK11_MD5_DISABLE fprintf(stderr, "The use of RSA (RSAMD5) is not " "recommended.\nIf you still wish to " "use RSA (RSAMD5) please specify " "\"-a RSAMD5\"\n"); #else fprintf(stderr, "The use of RSA (RSAMD5) was disabled\n"); if (freeit != NULL) free(freeit); return (1); } else if (strcasecmp(algname, "RSAMD5") == 0) { fprintf(stderr, "The use of RSAMD5 was disabled\n"); #endif if (freeit != NULL) free(freeit); return (1); } else { r.base = algname; r.length = strlen(algname); ret = dns_secalg_fromtext(&alg, &r); if (ret != ISC_R_SUCCESS) fatal("unknown algorithm %s", algname); if (alg == DST_ALG_DH) options |= DST_TYPE_KEY; } if (use_nsec3 && alg != DST_ALG_NSEC3DSA && alg != DST_ALG_NSEC3RSASHA1 && alg != DST_ALG_RSASHA256 && alg != DST_ALG_RSASHA512 && alg != DST_ALG_ECCGOST && alg != DST_ALG_ECDSA256 && alg != DST_ALG_ECDSA384 && alg != DST_ALG_ED25519 && alg != DST_ALG_ED448) { fatal("%s is incompatible with NSEC3; " "do not use the -3 option", algname); } if (type != NULL && (options & DST_TYPE_KEY) != 0) { if (strcasecmp(type, "NOAUTH") == 0) flags |= DNS_KEYTYPE_NOAUTH; else if (strcasecmp(type, "NOCONF") == 0) flags |= DNS_KEYTYPE_NOCONF; else if (strcasecmp(type, "NOAUTHCONF") == 0) flags |= (DNS_KEYTYPE_NOAUTH | DNS_KEYTYPE_NOCONF); else if (strcasecmp(type, "AUTHCONF") == 0) /* nothing */; else fatal("invalid type %s", type); } if (!oldstyle && prepub > 0) { if (setpub && setact && (activate - prepub) < publish) fatal("Activation and publication dates " "are closer together than the\n\t" "prepublication interval."); if (!setpub && !setact) { setpub = setact = ISC_TRUE; publish = now; activate = now + prepub; } else if (setpub && !setact) { setact = ISC_TRUE; activate = publish + prepub; } else if (setact && !setpub) { setpub = ISC_TRUE; publish = activate - prepub; } if ((activate - prepub) < now) fatal("Time until activation is shorter " "than the\n\tprepublication interval."); } } else { char keystr[DST_KEY_FORMATSIZE]; isc_stdtime_t when; int major, minor; if (prepub == -1) prepub = (30 * 86400); if (algname != NULL) fatal("-S and -a cannot be used together"); if (nametype != NULL) fatal("-S and -n cannot be used together"); if (type != NULL) fatal("-S and -t cannot be used together"); if (setpub || unsetpub) fatal("-S and -P cannot be used together"); if (setact || unsetact) fatal("-S and -A cannot be used together"); if (use_nsec3) fatal("-S and -3 cannot be used together"); if (oldstyle) fatal("-S and -C cannot be used together"); if (genonly) fatal("-S and -G cannot be used together"); ret = dst_key_fromnamedfile(predecessor, directory, DST_TYPE_PUBLIC | DST_TYPE_PRIVATE, mctx, &prevkey); if (ret != ISC_R_SUCCESS) fatal("Invalid keyfile %s: %s", predecessor, isc_result_totext(ret)); if (!dst_key_isprivate(prevkey)) fatal("%s is not a private key", predecessor); name = dst_key_name(prevkey); alg = dst_key_alg(prevkey); flags = dst_key_flags(prevkey); #ifdef PK11_MD5_DISABLE if (alg == DST_ALG_RSAMD5) fatal("Key %s uses disabled RSAMD5", predecessor); #endif dst_key_format(prevkey, keystr, sizeof(keystr)); dst_key_getprivateformat(prevkey, &major, &minor); if (major != DST_MAJOR_VERSION || minor < DST_MINOR_VERSION) fatal("Key %s has incompatible format version %d.%d\n\t" "It is not possible to generate a successor key.", keystr, major, minor); ret = dst_key_gettime(prevkey, DST_TIME_ACTIVATE, &when); if (ret != ISC_R_SUCCESS) fatal("Key %s has no activation date.\n\t" "You must use dnssec-settime -A to set one " "before generating a successor.", keystr); ret = dst_key_gettime(prevkey, DST_TIME_INACTIVE, &activate); if (ret != ISC_R_SUCCESS) fatal("Key %s has no inactivation date.\n\t" "You must use dnssec-settime -I to set one " "before generating a successor.", keystr); publish = activate - prepub; if (publish < now) fatal("Key %s becomes inactive\n\t" "sooner than the prepublication period " "for the new key ends.\n\t" "Either change the inactivation date with " "dnssec-settime -I,\n\t" "or use the -i option to set a shorter " "prepublication interval.", keystr); ret = dst_key_gettime(prevkey, DST_TIME_DELETE, &when); if (ret != ISC_R_SUCCESS) fprintf(stderr, "%s: WARNING: Key %s has no removal " "date;\n\t it will remain in the zone " "indefinitely after rollover.\n\t " "You can use dnssec-settime -D to " "change this.\n", program, keystr); setpub = setact = ISC_TRUE; } if (nametype == NULL) { if ((options & DST_TYPE_KEY) != 0) /* KEY */ fatal("no nametype specified"); flags |= DNS_KEYOWNER_ZONE; /* DNSKEY */ } else if (strcasecmp(nametype, "zone") == 0) flags |= DNS_KEYOWNER_ZONE; else if ((options & DST_TYPE_KEY) != 0) { /* KEY */ if (strcasecmp(nametype, "host") == 0 || strcasecmp(nametype, "entity") == 0) flags |= DNS_KEYOWNER_ENTITY; else if (strcasecmp(nametype, "user") == 0) flags |= DNS_KEYOWNER_USER; else fatal("invalid KEY nametype %s", nametype); } else if (strcasecmp(nametype, "other") != 0) /* DNSKEY */ fatal("invalid DNSKEY nametype %s", nametype); rdclass = strtoclass(classname); if (directory == NULL) directory = "."; if ((options & DST_TYPE_KEY) != 0) /* KEY */ flags |= signatory; else if ((flags & DNS_KEYOWNER_ZONE) != 0) { /* DNSKEY */ flags |= kskflag; flags |= revflag; } if (protocol == -1) protocol = DNS_KEYPROTO_DNSSEC; else if ((options & DST_TYPE_KEY) == 0 && protocol != DNS_KEYPROTO_DNSSEC) fatal("invalid DNSKEY protocol: %d", protocol); if ((flags & DNS_KEYFLAG_TYPEMASK) == DNS_KEYTYPE_NOKEY) { if ((flags & DNS_KEYFLAG_SIGNATORYMASK) != 0) fatal("specified null key with signing authority"); } if ((flags & DNS_KEYFLAG_OWNERMASK) == DNS_KEYOWNER_ZONE && alg == DNS_KEYALG_DH) fatal("a key with algorithm '%s' cannot be a zone key", algname); isc_buffer_init(&buf, filename, sizeof(filename) - 1); /* associate the key */ ret = dst_key_fromlabel(name, alg, flags, protocol, rdclass, #ifdef PKCS11CRYPTO "pkcs11", #else engine, #endif label, NULL, mctx, &key); isc_entropy_stopcallbacksources(ectx); if (ret != ISC_R_SUCCESS) { char namestr[DNS_NAME_FORMATSIZE]; char algstr[DNS_SECALG_FORMATSIZE]; dns_name_format(name, namestr, sizeof(namestr)); dns_secalg_format(alg, algstr, sizeof(algstr)); fatal("failed to get key %s/%s: %s", namestr, algstr, isc_result_totext(ret)); /* NOTREACHED */ exit(-1); } /* * Set key timing metadata (unless using -C) * * Publish and activation dates are set to "now" by default, but * can be overridden. Creation date is always set to "now". */ if (!oldstyle) { dst_key_settime(key, DST_TIME_CREATED, now); if (genonly && (setpub || setact)) fatal("cannot use -G together with -P or -A options"); if (setpub) dst_key_settime(key, DST_TIME_PUBLISH, publish); else if (setact) dst_key_settime(key, DST_TIME_PUBLISH, activate); else if (!genonly && !unsetpub) dst_key_settime(key, DST_TIME_PUBLISH, now); if (setact) dst_key_settime(key, DST_TIME_ACTIVATE, activate); else if (!genonly && !unsetact) dst_key_settime(key, DST_TIME_ACTIVATE, now); if (setrev) { if (kskflag == 0) fprintf(stderr, "%s: warning: Key is " "not flagged as a KSK, but -R " "was used. Revoking a ZSK is " "legal, but undefined.\n", program); dst_key_settime(key, DST_TIME_REVOKE, revoke); } if (setinact) dst_key_settime(key, DST_TIME_INACTIVE, inactive); if (setdel) dst_key_settime(key, DST_TIME_DELETE, deltime); if (setsyncadd) dst_key_settime(key, DST_TIME_SYNCPUBLISH, syncadd); if (setsyncdel) dst_key_settime(key, DST_TIME_SYNCDELETE, syncdel); } else { if (setpub || setact || setrev || setinact || setdel || unsetpub || unsetact || unsetrev || unsetinact || unsetdel || genonly || setsyncadd || setsyncdel) fatal("cannot use -C together with " "-P, -A, -R, -I, -D, or -G options"); /* * Compatibility mode: Private-key-format * should be set to 1.2. */ dst_key_setprivateformat(key, 1, 2); } /* Set default key TTL */ if (setttl) dst_key_setttl(key, ttl); /* * Do not overwrite an existing key. Warn LOUDLY if there * is a risk of ID collision due to this key or another key * being revoked. */ if (key_collision(key, name, directory, mctx, &exact)) { isc_buffer_clear(&buf); ret = dst_key_buildfilename(key, 0, directory, &buf); if (ret != ISC_R_SUCCESS) fatal("dst_key_buildfilename returned: %s\n", isc_result_totext(ret)); if (exact) fatal("%s: %s already exists\n", program, filename); if (avoid_collisions) fatal("%s: %s could collide with another key upon " "revokation\n", program, filename); fprintf(stderr, "%s: WARNING: Key %s could collide with " "another key upon revokation. If you plan " "to revoke keys, destroy this key and " "generate a different one.\n", program, filename); } ret = dst_key_tofile(key, options, directory); if (ret != ISC_R_SUCCESS) { char keystr[DST_KEY_FORMATSIZE]; dst_key_format(key, keystr, sizeof(keystr)); fatal("failed to write key %s: %s\n", keystr, isc_result_totext(ret)); } isc_buffer_clear(&buf); ret = dst_key_buildfilename(key, 0, NULL, &buf); if (ret != ISC_R_SUCCESS) fatal("dst_key_buildfilename returned: %s\n", isc_result_totext(ret)); printf("%s\n", filename); dst_key_free(&key); if (prevkey != NULL) dst_key_free(&prevkey); cleanup_logging(&log); cleanup_entropy(&ectx); dst_lib_destroy(); dns_name_destroy(); if (verbose > 10) isc_mem_stats(mctx, stdout); isc_mem_free(mctx, label); isc_mem_destroy(&mctx); if (freeit != NULL) free(freeit); return (0); } bind9-9.11.3+dfsg/bin/dnssec/dnssec-keyfromlabel.docbook000066400000000000000000000466021325250447100230660ustar00rootroot00000000000000 2014-02-27 August 27, 2015 ISC Internet Systems Consortium, Inc. dnssec-keyfromlabel 8 BIND9 dnssec-keyfromlabel DNSSEC key generation tool 2008 2009 2010 2011 2012 2014 2015 2016 2017 Internet Systems Consortium, Inc. ("ISC") dnssec-keyfromlabel -l label name DESCRIPTION dnssec-keyfromlabel generates a key pair of files that referencing a key object stored in a cryptographic hardware service module (HSM). The private key file can be used for DNSSEC signing of zone data as if it were a conventional signing key created by dnssec-keygen, but the key material is stored within the HSM, and the actual signing takes place there. The of the key is specified on the command line. This must match the name of the zone for which the key is being generated. OPTIONS -a algorithm Selects the cryptographic algorithm. The value of must be one of RSAMD5, RSASHA1, DSA, NSEC3RSASHA1, NSEC3DSA, RSASHA256, RSASHA512, ECCGOST, ECDSAP256SHA256, ECDSAP384SHA384, ED25519 or ED448. These values are case insensitive. If no algorithm is specified, then RSASHA1 will be used by default, unless the option is specified, in which case NSEC3RSASHA1 will be used instead. (If is used and an algorithm is specified, that algorithm will be checked for compatibility with NSEC3.) Note 1: that for DNSSEC, RSASHA1 is a mandatory to implement algorithm, and DSA is recommended. Note 2: DH automatically sets the -k flag. -3 Use an NSEC3-capable algorithm to generate a DNSSEC key. If this option is used and no algorithm is explicitly set on the command line, NSEC3RSASHA1 will be used by default. -E engine Specifies the cryptographic hardware to use. When BIND is built with OpenSSL PKCS#11 support, this defaults to the string "pkcs11", which identifies an OpenSSL engine that can drive a cryptographic accelerator or hardware service module. When BIND is built with native PKCS#11 cryptography (--enable-native-pkcs11), it defaults to the path of the PKCS#11 provider library specified via "--with-pkcs11". -l label Specifies the label for a key pair in the crypto hardware. When BIND 9 is built with OpenSSL-based PKCS#11 support, the label is an arbitrary string that identifies a particular key. It may be preceded by an optional OpenSSL engine name, followed by a colon, as in "pkcs11:keylabel". When BIND 9 is built with native PKCS#11 support, the label is a PKCS#11 URI string in the format "pkcs11:=value;=value;..." Keywords include "token", which identifies the HSM; "object", which identifies the key; and "pin-source", which identifies a file from which the HSM's PIN code can be obtained. The label will be stored in the on-disk "private" file. If the label contains a field, tools using the generated key files will be able to use the HSM for signing and other operations without any need for an operator to manually enter a PIN. Note: Making the HSM's PIN accessible in this manner may reduce the security advantage of using an HSM; be sure this is what you want to do before making use of this feature. -n nametype Specifies the owner type of the key. The value of must either be ZONE (for a DNSSEC zone key (KEY/DNSKEY)), HOST or ENTITY (for a key associated with a host (KEY)), USER (for a key associated with a user(KEY)) or OTHER (DNSKEY). These values are case insensitive. -C Compatibility mode: generates an old-style key, without any metadata. By default, dnssec-keyfromlabel will include the key's creation date in the metadata stored with the private key, and other dates may be set there as well (publication date, activation date, etc). Keys that include this data may be incompatible with older versions of BIND; the option suppresses them. -c class Indicates that the DNS record containing the key should have the specified class. If not specified, class IN is used. -f flag Set the specified flag in the flag field of the KEY/DNSKEY record. The only recognized flags are KSK (Key Signing Key) and REVOKE. -G Generate a key, but do not publish it or sign with it. This option is incompatible with -P and -A. -h Prints a short summary of the options and arguments to dnssec-keyfromlabel. -K directory Sets the directory in which the key files are to be written. -k Generate KEY records rather than DNSKEY records. -L ttl Sets the default TTL to use for this key when it is converted into a DNSKEY RR. If the key is imported into a zone, this is the TTL that will be used for it, unless there was already a DNSKEY RRset in place, in which case the existing TTL would take precedence. Setting the default TTL to 0 or none removes it. -p protocol Sets the protocol value for the key. The protocol is a number between 0 and 255. The default is 3 (DNSSEC). Other possible values for this argument are listed in RFC 2535 and its successors. -S key Generate a key as an explicit successor to an existing key. The name, algorithm, size, and type of the key will be set to match the predecessor. The activation date of the new key will be set to the inactivation date of the existing one. The publication date will be set to the activation date minus the prepublication interval, which defaults to 30 days. -t type Indicates the use of the key. must be one of AUTHCONF, NOAUTHCONF, NOAUTH, or NOCONF. The default is AUTHCONF. AUTH refers to the ability to authenticate data, and CONF the ability to encrypt data. -v level Sets the debugging level. -V Prints version information. -y Allows DNSSEC key files to be generated even if the key ID would collide with that of an existing key, in the event of either key being revoked. (This is only safe to use if you are sure you won't be using RFC 5011 trust anchor maintenance with either of the keys involved.) TIMING OPTIONS Dates can be expressed in the format YYYYMMDD or YYYYMMDDHHMMSS. If the argument begins with a '+' or '-', it is interpreted as an offset from the present time. For convenience, if such an offset is followed by one of the suffixes 'y', 'mo', 'w', 'd', 'h', or 'mi', then the offset is computed in years (defined as 365 24-hour days, ignoring leap years), months (defined as 30 24-hour days), weeks, days, hours, or minutes, respectively. Without a suffix, the offset is computed in seconds. To explicitly prevent a date from being set, use 'none' or 'never'. -P date/offset Sets the date on which a key is to be published to the zone. After that date, the key will be included in the zone but will not be used to sign it. If not set, and if the -G option has not been used, the default is "now". -P sync date/offset Sets the date on which the CDS and CDNSKEY records which match this key are to be published to the zone. -A date/offset Sets the date on which the key is to be activated. After that date, the key will be included in the zone and used to sign it. If not set, and if the -G option has not been used, the default is "now". -R date/offset Sets the date on which the key is to be revoked. After that date, the key will be flagged as revoked. It will be included in the zone and will be used to sign it. -I date/offset Sets the date on which the key is to be retired. After that date, the key will still be included in the zone, but it will not be used to sign it. -D date/offset Sets the date on which the key is to be deleted. After that date, the key will no longer be included in the zone. (It may remain in the key repository, however.) -D sync date/offset Sets the date on which the CDS and CDNSKEY records which match this key are to be deleted. -i interval Sets the prepublication interval for a key. If set, then the publication and activation dates must be separated by at least this much time. If the activation date is specified but the publication date isn't, then the publication date will default to this much time before the activation date; conversely, if the publication date is specified but activation date isn't, then activation will be set to this much time after publication. If the key is being created as an explicit successor to another key, then the default prepublication interval is 30 days; otherwise it is zero. As with date offsets, if the argument is followed by one of the suffixes 'y', 'mo', 'w', 'd', 'h', or 'mi', then the interval is measured in years, months, weeks, days, hours, or minutes, respectively. Without a suffix, the interval is measured in seconds. GENERATED KEY FILES When dnssec-keyfromlabel completes successfully, it prints a string of the form Knnnn.+aaa+iiiii to the standard output. This is an identification string for the key files it has generated. nnnn is the key name. aaa is the numeric representation of the algorithm. iiiii is the key identifier (or footprint). dnssec-keyfromlabel creates two files, with names based on the printed string. Knnnn.+aaa+iiiii.key contains the public key, and Knnnn.+aaa+iiiii.private contains the private key. The .key file contains a DNS KEY record that can be inserted into a zone file (directly or with a $INCLUDE statement). The .private file contains algorithm-specific fields. For obvious security reasons, this file does not have general read permission. SEE ALSO dnssec-keygen8 , dnssec-signzone8 , BIND 9 Administrator Reference Manual, RFC 4034, The PKCS#11 URI Scheme (draft-pechanec-pkcs11uri-13). bind9-9.11.3+dfsg/bin/dnssec/dnssec-keyfromlabel.html000066400000000000000000000431771325250447100224160ustar00rootroot00000000000000 dnssec-keyfromlabel

Name

dnssec-keyfromlabel — DNSSEC key generation tool

Synopsis

dnssec-keyfromlabel {-l label} [-3] [-a algorithm] [-A date/offset] [-c class] [-D date/offset] [-D sync date/offset] [-E engine] [-f flag] [-G] [-I date/offset] [-i interval] [-k] [-K directory] [-L ttl] [-n nametype] [-P date/offset] [-P sync date/offset] [-p protocol] [-R date/offset] [-S key] [-t type] [-v level] [-V] [-y] {name}

DESCRIPTION

dnssec-keyfromlabel generates a key pair of files that referencing a key object stored in a cryptographic hardware service module (HSM). The private key file can be used for DNSSEC signing of zone data as if it were a conventional signing key created by dnssec-keygen, but the key material is stored within the HSM, and the actual signing takes place there.

The name of the key is specified on the command line. This must match the name of the zone for which the key is being generated.

OPTIONS

-a algorithm

Selects the cryptographic algorithm. The value of algorithm must be one of RSAMD5, RSASHA1, DSA, NSEC3RSASHA1, NSEC3DSA, RSASHA256, RSASHA512, ECCGOST, ECDSAP256SHA256, ECDSAP384SHA384, ED25519 or ED448. These values are case insensitive.

If no algorithm is specified, then RSASHA1 will be used by default, unless the -3 option is specified, in which case NSEC3RSASHA1 will be used instead. (If -3 is used and an algorithm is specified, that algorithm will be checked for compatibility with NSEC3.)

Note 1: that for DNSSEC, RSASHA1 is a mandatory to implement algorithm, and DSA is recommended.

Note 2: DH automatically sets the -k flag.

-3

Use an NSEC3-capable algorithm to generate a DNSSEC key. If this option is used and no algorithm is explicitly set on the command line, NSEC3RSASHA1 will be used by default.

-E engine

Specifies the cryptographic hardware to use.

When BIND is built with OpenSSL PKCS#11 support, this defaults to the string "pkcs11", which identifies an OpenSSL engine that can drive a cryptographic accelerator or hardware service module. When BIND is built with native PKCS#11 cryptography (--enable-native-pkcs11), it defaults to the path of the PKCS#11 provider library specified via "--with-pkcs11".

-l label

Specifies the label for a key pair in the crypto hardware.

When BIND 9 is built with OpenSSL-based PKCS#11 support, the label is an arbitrary string that identifies a particular key. It may be preceded by an optional OpenSSL engine name, followed by a colon, as in "pkcs11:keylabel".

When BIND 9 is built with native PKCS#11 support, the label is a PKCS#11 URI string in the format "pkcs11:keyword=value[;keyword=value;...]" Keywords include "token", which identifies the HSM; "object", which identifies the key; and "pin-source", which identifies a file from which the HSM's PIN code can be obtained. The label will be stored in the on-disk "private" file.

If the label contains a pin-source field, tools using the generated key files will be able to use the HSM for signing and other operations without any need for an operator to manually enter a PIN. Note: Making the HSM's PIN accessible in this manner may reduce the security advantage of using an HSM; be sure this is what you want to do before making use of this feature.

-n nametype

Specifies the owner type of the key. The value of nametype must either be ZONE (for a DNSSEC zone key (KEY/DNSKEY)), HOST or ENTITY (for a key associated with a host (KEY)), USER (for a key associated with a user(KEY)) or OTHER (DNSKEY). These values are case insensitive.

-C

Compatibility mode: generates an old-style key, without any metadata. By default, dnssec-keyfromlabel will include the key's creation date in the metadata stored with the private key, and other dates may be set there as well (publication date, activation date, etc). Keys that include this data may be incompatible with older versions of BIND; the -C option suppresses them.

-c class

Indicates that the DNS record containing the key should have the specified class. If not specified, class IN is used.

-f flag

Set the specified flag in the flag field of the KEY/DNSKEY record. The only recognized flags are KSK (Key Signing Key) and REVOKE.

-G

Generate a key, but do not publish it or sign with it. This option is incompatible with -P and -A.

-h

Prints a short summary of the options and arguments to dnssec-keyfromlabel.

-K directory

Sets the directory in which the key files are to be written.

-k

Generate KEY records rather than DNSKEY records.

-L ttl

Sets the default TTL to use for this key when it is converted into a DNSKEY RR. If the key is imported into a zone, this is the TTL that will be used for it, unless there was already a DNSKEY RRset in place, in which case the existing TTL would take precedence. Setting the default TTL to 0 or none removes it.

-p protocol

Sets the protocol value for the key. The protocol is a number between 0 and 255. The default is 3 (DNSSEC). Other possible values for this argument are listed in RFC 2535 and its successors.

-S key

Generate a key as an explicit successor to an existing key. The name, algorithm, size, and type of the key will be set to match the predecessor. The activation date of the new key will be set to the inactivation date of the existing one. The publication date will be set to the activation date minus the prepublication interval, which defaults to 30 days.

-t type

Indicates the use of the key. type must be one of AUTHCONF, NOAUTHCONF, NOAUTH, or NOCONF. The default is AUTHCONF. AUTH refers to the ability to authenticate data, and CONF the ability to encrypt data.

-v level

Sets the debugging level.

-V

Prints version information.

-y

Allows DNSSEC key files to be generated even if the key ID would collide with that of an existing key, in the event of either key being revoked. (This is only safe to use if you are sure you won't be using RFC 5011 trust anchor maintenance with either of the keys involved.)

TIMING OPTIONS

Dates can be expressed in the format YYYYMMDD or YYYYMMDDHHMMSS. If the argument begins with a '+' or '-', it is interpreted as an offset from the present time. For convenience, if such an offset is followed by one of the suffixes 'y', 'mo', 'w', 'd', 'h', or 'mi', then the offset is computed in years (defined as 365 24-hour days, ignoring leap years), months (defined as 30 24-hour days), weeks, days, hours, or minutes, respectively. Without a suffix, the offset is computed in seconds. To explicitly prevent a date from being set, use 'none' or 'never'.

-P date/offset

Sets the date on which a key is to be published to the zone. After that date, the key will be included in the zone but will not be used to sign it. If not set, and if the -G option has not been used, the default is "now".

-P sync date/offset

Sets the date on which the CDS and CDNSKEY records which match this key are to be published to the zone.

-A date/offset

Sets the date on which the key is to be activated. After that date, the key will be included in the zone and used to sign it. If not set, and if the -G option has not been used, the default is "now".

-R date/offset

Sets the date on which the key is to be revoked. After that date, the key will be flagged as revoked. It will be included in the zone and will be used to sign it.

-I date/offset

Sets the date on which the key is to be retired. After that date, the key will still be included in the zone, but it will not be used to sign it.

-D date/offset

Sets the date on which the key is to be deleted. After that date, the key will no longer be included in the zone. (It may remain in the key repository, however.)

-D sync date/offset

Sets the date on which the CDS and CDNSKEY records which match this key are to be deleted.

-i interval

Sets the prepublication interval for a key. If set, then the publication and activation dates must be separated by at least this much time. If the activation date is specified but the publication date isn't, then the publication date will default to this much time before the activation date; conversely, if the publication date is specified but activation date isn't, then activation will be set to this much time after publication.

If the key is being created as an explicit successor to another key, then the default prepublication interval is 30 days; otherwise it is zero.

As with date offsets, if the argument is followed by one of the suffixes 'y', 'mo', 'w', 'd', 'h', or 'mi', then the interval is measured in years, months, weeks, days, hours, or minutes, respectively. Without a suffix, the interval is measured in seconds.

GENERATED KEY FILES

When dnssec-keyfromlabel completes successfully, it prints a string of the form Knnnn.+aaa+iiiii to the standard output. This is an identification string for the key files it has generated.

  • nnnn is the key name.

  • aaa is the numeric representation of the algorithm.

  • iiiii is the key identifier (or footprint).

dnssec-keyfromlabel creates two files, with names based on the printed string. Knnnn.+aaa+iiiii.key contains the public key, and Knnnn.+aaa+iiiii.private contains the private key.

The .key file contains a DNS KEY record that can be inserted into a zone file (directly or with a $INCLUDE statement).

The .private file contains algorithm-specific fields. For obvious security reasons, this file does not have general read permission.

SEE ALSO

dnssec-keygen(8) , dnssec-signzone(8) , BIND 9 Administrator Reference Manual, RFC 4034, The PKCS#11 URI Scheme (draft-pechanec-pkcs11uri-13).

bind9-9.11.3+dfsg/bin/dnssec/dnssec-keygen.8000066400000000000000000000354111325250447100204170ustar00rootroot00000000000000.\" Copyright (C) 2000-2005, 2007-2012, 2014-2017 Internet Systems Consortium, Inc. ("ISC") .\" .\" This Source Code Form is subject to the terms of the Mozilla Public .\" License, v. 2.0. If a copy of the MPL was not distributed with this .\" file, You can obtain one at http://mozilla.org/MPL/2.0/. .\" .hy 0 .ad l '\" t .\" Title: dnssec-keygen .\" Author: .\" Generator: DocBook XSL Stylesheets v1.78.1 .\" Date: August 21, 2015 .\" Manual: BIND9 .\" Source: ISC .\" Language: English .\" .TH "DNSSEC\-KEYGEN" "8" "August 21, 2015" "ISC" "BIND9" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" dnssec-keygen \- DNSSEC key generation tool .SH "SYNOPSIS" .HP \w'\fBdnssec\-keygen\fR\ 'u \fBdnssec\-keygen\fR [\fB\-a\ \fR\fB\fIalgorithm\fR\fR] [\fB\-b\ \fR\fB\fIkeysize\fR\fR] [\fB\-n\ \fR\fB\fInametype\fR\fR] [\fB\-3\fR] [\fB\-A\ \fR\fB\fIdate/offset\fR\fR] [\fB\-C\fR] [\fB\-c\ \fR\fB\fIclass\fR\fR] [\fB\-D\ \fR\fB\fIdate/offset\fR\fR] [\fB\-D\ sync\ \fR\fB\fIdate/offset\fR\fR] [\fB\-E\ \fR\fB\fIengine\fR\fR] [\fB\-f\ \fR\fB\fIflag\fR\fR] [\fB\-G\fR] [\fB\-g\ \fR\fB\fIgenerator\fR\fR] [\fB\-h\fR] [\fB\-I\ \fR\fB\fIdate/offset\fR\fR] [\fB\-i\ \fR\fB\fIinterval\fR\fR] [\fB\-K\ \fR\fB\fIdirectory\fR\fR] [\fB\-k\fR] [\fB\-L\ \fR\fB\fIttl\fR\fR] [\fB\-P\ \fR\fB\fIdate/offset\fR\fR] [\fB\-P\ sync\ \fR\fB\fIdate/offset\fR\fR] [\fB\-p\ \fR\fB\fIprotocol\fR\fR] [\fB\-q\fR] [\fB\-R\ \fR\fB\fIdate/offset\fR\fR] [\fB\-r\ \fR\fB\fIrandomdev\fR\fR] [\fB\-S\ \fR\fB\fIkey\fR\fR] [\fB\-s\ \fR\fB\fIstrength\fR\fR] [\fB\-t\ \fR\fB\fItype\fR\fR] [\fB\-V\fR] [\fB\-v\ \fR\fB\fIlevel\fR\fR] [\fB\-z\fR] {name} .SH "DESCRIPTION" .PP \fBdnssec\-keygen\fR generates keys for DNSSEC (Secure DNS), as defined in RFC 2535 and RFC 4034\&. It can also generate keys for use with TSIG (Transaction Signatures) as defined in RFC 2845, or TKEY (Transaction Key) as defined in RFC 2930\&. .PP The \fBname\fR of the key is specified on the command line\&. For DNSSEC keys, this must match the name of the zone for which the key is being generated\&. .SH "OPTIONS" .PP \-a \fIalgorithm\fR .RS 4 Selects the cryptographic algorithm\&. For DNSSEC keys, the value of \fBalgorithm\fR must be one of RSAMD5, RSASHA1, DSA, NSEC3RSASHA1, NSEC3DSA, RSASHA256, RSASHA512, ECCGOST, ECDSAP256SHA256, ECDSAP384SHA384, ED25519 or ED448\&. For TSIG/TKEY, the value must be DH (Diffie Hellman), HMAC\-MD5, HMAC\-SHA1, HMAC\-SHA224, HMAC\-SHA256, HMAC\-SHA384, or HMAC\-SHA512\&. These values are case insensitive\&. .sp If no algorithm is specified, then RSASHA1 will be used by default, unless the \fB\-3\fR option is specified, in which case NSEC3RSASHA1 will be used instead\&. (If \fB\-3\fR is used and an algorithm is specified, that algorithm will be checked for compatibility with NSEC3\&.) .sp Note 1: that for DNSSEC, RSASHA1 is a mandatory to implement algorithm, and DSA is recommended\&. For TSIG, HMAC\-MD5 is mandatory\&. .sp Note 2: DH, HMAC\-MD5, and HMAC\-SHA1 through HMAC\-SHA512 automatically set the \-T KEY option\&. .RE .PP \-b \fIkeysize\fR .RS 4 Specifies the number of bits in the key\&. The choice of key size depends on the algorithm used\&. RSA keys must be between 512 and 2048 bits\&. Diffie Hellman keys must be between 128 and 4096 bits\&. DSA keys must be between 512 and 1024 bits and an exact multiple of 64\&. HMAC keys must be between 1 and 512 bits\&. Elliptic curve algorithms don\*(Aqt need this parameter\&. .sp The key size does not need to be specified if using a default algorithm\&. The default key size is 1024 bits for zone signing keys (ZSKs) and 2048 bits for key signing keys (KSKs, generated with \fB\-f KSK\fR)\&. However, if an algorithm is explicitly specified with the \fB\-a\fR, then there is no default key size, and the \fB\-b\fR must be used\&. .RE .PP \-n \fInametype\fR .RS 4 Specifies the owner type of the key\&. The value of \fBnametype\fR must either be ZONE (for a DNSSEC zone key (KEY/DNSKEY)), HOST or ENTITY (for a key associated with a host (KEY)), USER (for a key associated with a user(KEY)) or OTHER (DNSKEY)\&. These values are case insensitive\&. Defaults to ZONE for DNSKEY generation\&. .RE .PP \-3 .RS 4 Use an NSEC3\-capable algorithm to generate a DNSSEC key\&. If this option is used and no algorithm is explicitly set on the command line, NSEC3RSASHA1 will be used by default\&. Note that RSASHA256, RSASHA512, ECCGOST, ECDSAP256SHA256, ECDSAP384SHA384, ED25519 and ED448 algorithms are NSEC3\-capable\&. .RE .PP \-C .RS 4 Compatibility mode: generates an old\-style key, without any metadata\&. By default, \fBdnssec\-keygen\fR will include the key\*(Aqs creation date in the metadata stored with the private key, and other dates may be set there as well (publication date, activation date, etc)\&. Keys that include this data may be incompatible with older versions of BIND; the \fB\-C\fR option suppresses them\&. .RE .PP \-c \fIclass\fR .RS 4 Indicates that the DNS record containing the key should have the specified class\&. If not specified, class IN is used\&. .RE .PP \-E \fIengine\fR .RS 4 Specifies the cryptographic hardware to use, when applicable\&. .sp When BIND is built with OpenSSL PKCS#11 support, this defaults to the string "pkcs11", which identifies an OpenSSL engine that can drive a cryptographic accelerator or hardware service module\&. When BIND is built with native PKCS#11 cryptography (\-\-enable\-native\-pkcs11), it defaults to the path of the PKCS#11 provider library specified via "\-\-with\-pkcs11"\&. .RE .PP \-f \fIflag\fR .RS 4 Set the specified flag in the flag field of the KEY/DNSKEY record\&. The only recognized flags are KSK (Key Signing Key) and REVOKE\&. .RE .PP \-G .RS 4 Generate a key, but do not publish it or sign with it\&. This option is incompatible with \-P and \-A\&. .RE .PP \-g \fIgenerator\fR .RS 4 If generating a Diffie Hellman key, use this generator\&. Allowed values are 2 and 5\&. If no generator is specified, a known prime from RFC 2539 will be used if possible; otherwise the default is 2\&. .RE .PP \-h .RS 4 Prints a short summary of the options and arguments to \fBdnssec\-keygen\fR\&. .RE .PP \-K \fIdirectory\fR .RS 4 Sets the directory in which the key files are to be written\&. .RE .PP \-k .RS 4 Deprecated in favor of \-T KEY\&. .RE .PP \-L \fIttl\fR .RS 4 Sets the default TTL to use for this key when it is converted into a DNSKEY RR\&. If the key is imported into a zone, this is the TTL that will be used for it, unless there was already a DNSKEY RRset in place, in which case the existing TTL would take precedence\&. If this value is not set and there is no existing DNSKEY RRset, the TTL will default to the SOA TTL\&. Setting the default TTL to 0 or none is the same as leaving it unset\&. .RE .PP \-p \fIprotocol\fR .RS 4 Sets the protocol value for the generated key\&. The protocol is a number between 0 and 255\&. The default is 3 (DNSSEC)\&. Other possible values for this argument are listed in RFC 2535 and its successors\&. .RE .PP \-q .RS 4 Quiet mode: Suppresses unnecessary output, including progress indication\&. Without this option, when \fBdnssec\-keygen\fR is run interactively to generate an RSA or DSA key pair, it will print a string of symbols to stderr indicating the progress of the key generation\&. A \*(Aq\&.\*(Aq indicates that a random number has been found which passed an initial sieve test; \*(Aq+\*(Aq means a number has passed a single round of the Miller\-Rabin primality test; a space means that the number has passed all the tests and is a satisfactory key\&. .RE .PP \-r \fIrandomdev\fR .RS 4 Specifies the source of randomness\&. If the operating system does not provide a /dev/random or equivalent device, the default source of randomness is keyboard input\&. randomdev specifies the name of a character device or file containing random data to be used instead of the default\&. The special value keyboard indicates that keyboard input should be used\&. .RE .PP \-S \fIkey\fR .RS 4 Create a new key which is an explicit successor to an existing key\&. The name, algorithm, size, and type of the key will be set to match the existing key\&. The activation date of the new key will be set to the inactivation date of the existing one\&. The publication date will be set to the activation date minus the prepublication interval, which defaults to 30 days\&. .RE .PP \-s \fIstrength\fR .RS 4 Specifies the strength value of the key\&. The strength is a number between 0 and 15, and currently has no defined purpose in DNSSEC\&. .RE .PP \-T \fIrrtype\fR .RS 4 Specifies the resource record type to use for the key\&. \fBrrtype\fR must be either DNSKEY or KEY\&. The default is DNSKEY when using a DNSSEC algorithm, but it can be overridden to KEY for use with SIG(0)\&. Using any TSIG algorithm (HMAC\-* or DH) forces this option to KEY\&. .RE .PP \-t \fItype\fR .RS 4 Indicates the use of the key\&. \fBtype\fR must be one of AUTHCONF, NOAUTHCONF, NOAUTH, or NOCONF\&. The default is AUTHCONF\&. AUTH refers to the ability to authenticate data, and CONF the ability to encrypt data\&. .RE .PP \-v \fIlevel\fR .RS 4 Sets the debugging level\&. .RE .PP \-V .RS 4 Prints version information\&. .RE .SH "TIMING OPTIONS" .PP Dates can be expressed in the format YYYYMMDD or YYYYMMDDHHMMSS\&. If the argument begins with a \*(Aq+\*(Aq or \*(Aq\-\*(Aq, it is interpreted as an offset from the present time\&. For convenience, if such an offset is followed by one of the suffixes \*(Aqy\*(Aq, \*(Aqmo\*(Aq, \*(Aqw\*(Aq, \*(Aqd\*(Aq, \*(Aqh\*(Aq, or \*(Aqmi\*(Aq, then the offset is computed in years (defined as 365 24\-hour days, ignoring leap years), months (defined as 30 24\-hour days), weeks, days, hours, or minutes, respectively\&. Without a suffix, the offset is computed in seconds\&. To explicitly prevent a date from being set, use \*(Aqnone\*(Aq or \*(Aqnever\*(Aq\&. .PP \-P \fIdate/offset\fR .RS 4 Sets the date on which a key is to be published to the zone\&. After that date, the key will be included in the zone but will not be used to sign it\&. If not set, and if the \-G option has not been used, the default is "now"\&. .RE .PP \-P sync \fIdate/offset\fR .RS 4 Sets the date on which CDS and CDNSKEY records that match this key are to be published to the zone\&. .RE .PP \-A \fIdate/offset\fR .RS 4 Sets the date on which the key is to be activated\&. After that date, the key will be included in the zone and used to sign it\&. If not set, and if the \-G option has not been used, the default is "now"\&. If set, if and \-P is not set, then the publication date will be set to the activation date minus the prepublication interval\&. .RE .PP \-R \fIdate/offset\fR .RS 4 Sets the date on which the key is to be revoked\&. After that date, the key will be flagged as revoked\&. It will be included in the zone and will be used to sign it\&. .RE .PP \-I \fIdate/offset\fR .RS 4 Sets the date on which the key is to be retired\&. After that date, the key will still be included in the zone, but it will not be used to sign it\&. .RE .PP \-D \fIdate/offset\fR .RS 4 Sets the date on which the key is to be deleted\&. After that date, the key will no longer be included in the zone\&. (It may remain in the key repository, however\&.) .RE .PP \-D sync \fIdate/offset\fR .RS 4 Sets the date on which the CDS and CDNSKEY records that match this key are to be deleted\&. .RE .PP \-i \fIinterval\fR .RS 4 Sets the prepublication interval for a key\&. If set, then the publication and activation dates must be separated by at least this much time\&. If the activation date is specified but the publication date isn\*(Aqt, then the publication date will default to this much time before the activation date; conversely, if the publication date is specified but activation date isn\*(Aqt, then activation will be set to this much time after publication\&. .sp If the key is being created as an explicit successor to another key, then the default prepublication interval is 30 days; otherwise it is zero\&. .sp As with date offsets, if the argument is followed by one of the suffixes \*(Aqy\*(Aq, \*(Aqmo\*(Aq, \*(Aqw\*(Aq, \*(Aqd\*(Aq, \*(Aqh\*(Aq, or \*(Aqmi\*(Aq, then the interval is measured in years, months, weeks, days, hours, or minutes, respectively\&. Without a suffix, the interval is measured in seconds\&. .RE .SH "GENERATED KEYS" .PP When \fBdnssec\-keygen\fR completes successfully, it prints a string of the form Knnnn\&.+aaa+iiiii to the standard output\&. This is an identification string for the key it has generated\&. .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} nnnn is the key name\&. .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} aaa is the numeric representation of the algorithm\&. .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} iiiii is the key identifier (or footprint)\&. .RE .PP \fBdnssec\-keygen\fR creates two files, with names based on the printed string\&. Knnnn\&.+aaa+iiiii\&.key contains the public key, and Knnnn\&.+aaa+iiiii\&.private contains the private key\&. .PP The \&.key file contains a DNS KEY record that can be inserted into a zone file (directly or with a $INCLUDE statement)\&. .PP The \&.private file contains algorithm\-specific fields\&. For obvious security reasons, this file does not have general read permission\&. .PP Both \&.key and \&.private files are generated for symmetric cryptography algorithms such as HMAC\-MD5, even though the public and private key are equivalent\&. .SH "EXAMPLE" .PP To generate a 768\-bit DSA key for the domain \fBexample\&.com\fR, the following command would be issued: .PP \fBdnssec\-keygen \-a DSA \-b 768 \-n ZONE example\&.com\fR .PP The command would print a string of the form: .PP \fBKexample\&.com\&.+003+26160\fR .PP In this example, \fBdnssec\-keygen\fR creates the files Kexample\&.com\&.+003+26160\&.key and Kexample\&.com\&.+003+26160\&.private\&. .SH "SEE ALSO" .PP \fBdnssec-signzone\fR(8), BIND 9 Administrator Reference Manual, RFC 2539, RFC 2845, RFC 4034\&. .SH "AUTHOR" .PP \fBInternet Systems Consortium, Inc\&.\fR .SH "COPYRIGHT" .br Copyright \(co 2000-2005, 2007-2012, 2014-2017 Internet Systems Consortium, Inc. ("ISC") .br bind9-9.11.3+dfsg/bin/dnssec/dnssec-keygen.c000066400000000000000000001006431325250447100204720ustar00rootroot00000000000000/* * Portions Copyright (C) 1999-2017 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * Portions Copyright (C) 1995-2000 by Network Associates, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /*! \file */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef PKCS11CRYPTO #include #endif #include "dnssectool.h" #define MAX_RSA 4096 /* should be long enough... */ const char *program = "dnssec-keygen"; int verbose; #define DEFAULT_ALGORITHM "RSASHA1" #define DEFAULT_NSEC3_ALGORITHM "NSEC3RSASHA1" ISC_PLATFORM_NORETURN_PRE static void usage(void) ISC_PLATFORM_NORETURN_POST; static void progress(int p); static void usage(void) { fprintf(stderr, "Usage:\n"); fprintf(stderr, " %s [options] name\n\n", program); fprintf(stderr, "Version: %s\n", VERSION); fprintf(stderr, " name: owner of the key\n"); fprintf(stderr, "Options:\n"); fprintf(stderr, " -K : write keys into directory\n"); fprintf(stderr, " -a :\n"); fprintf(stderr, " RSA | RSAMD5 | DSA | RSASHA1 | NSEC3RSASHA1" " | NSEC3DSA |\n"); fprintf(stderr, " RSASHA256 | RSASHA512 | ECCGOST |\n"); fprintf(stderr, " ECDSAP256SHA256 | ECDSAP384SHA384 |\n"); fprintf(stderr, " ED25519 | ED448 | DH |\n"); fprintf(stderr, " HMAC-MD5 | HMAC-SHA1 | HMAC-SHA224 | " "HMAC-SHA256 | \n"); fprintf(stderr, " HMAC-SHA384 | HMAC-SHA512\n"); fprintf(stderr, " (default: RSASHA1, or " "NSEC3RSASHA1 if using -3)\n"); fprintf(stderr, " -3: use NSEC3-capable algorithm\n"); fprintf(stderr, " -b :\n"); fprintf(stderr, " RSAMD5:\t[512..%d]\n", MAX_RSA); fprintf(stderr, " RSASHA1:\t[512..%d]\n", MAX_RSA); fprintf(stderr, " NSEC3RSASHA1:\t[512..%d]\n", MAX_RSA); fprintf(stderr, " RSASHA256:\t[512..%d]\n", MAX_RSA); fprintf(stderr, " RSASHA512:\t[1024..%d]\n", MAX_RSA); fprintf(stderr, " DH:\t\t[128..4096]\n"); fprintf(stderr, " DSA:\t\t[512..1024] and divisible by 64\n"); fprintf(stderr, " NSEC3DSA:\t[512..1024] and divisible " "by 64\n"); fprintf(stderr, " ECCGOST:\tignored\n"); fprintf(stderr, " ECDSAP256SHA256:\tignored\n"); fprintf(stderr, " ECDSAP384SHA384:\tignored\n"); fprintf(stderr, " ED25519:\tignored\n"); fprintf(stderr, " ED448:\tignored\n"); fprintf(stderr, " HMAC-MD5:\t[1..512]\n"); fprintf(stderr, " HMAC-SHA1:\t[1..160]\n"); fprintf(stderr, " HMAC-SHA224:\t[1..224]\n"); fprintf(stderr, " HMAC-SHA256:\t[1..256]\n"); fprintf(stderr, " HMAC-SHA384:\t[1..384]\n"); fprintf(stderr, " HMAC-SHA512:\t[1..512]\n"); fprintf(stderr, " (if using the default algorithm, key size\n" " defaults to 2048 for KSK, or 1024 for all " "others)\n"); fprintf(stderr, " -n : ZONE | HOST | ENTITY | " "USER | OTHER\n"); fprintf(stderr, " (DNSKEY generation defaults to ZONE)\n"); fprintf(stderr, " -c : (default: IN)\n"); fprintf(stderr, " -d (0 => max, default)\n"); fprintf(stderr, " -E :\n"); #if defined(PKCS11CRYPTO) fprintf(stderr, " path to PKCS#11 provider library " "(default is %s)\n", PK11_LIB_LOCATION); #elif defined(USE_PKCS11) fprintf(stderr, " name of an OpenSSL engine to use " "(default is \"pkcs11\")\n"); #else fprintf(stderr, " name of an OpenSSL engine to use\n"); #endif fprintf(stderr, " -f : KSK | REVOKE\n"); fprintf(stderr, " -g : use specified generator " "(DH only)\n"); fprintf(stderr, " -L : default key TTL\n"); fprintf(stderr, " -p : (default: 3 [dnssec])\n"); fprintf(stderr, " -r : a file containing random data\n"); fprintf(stderr, " -s : strength value this key signs DNS " "records with (default: 0)\n"); fprintf(stderr, " -T : DNSKEY | KEY (default: DNSKEY; " "use KEY for SIG(0))\n"); fprintf(stderr, " -t : " "AUTHCONF | NOAUTHCONF | NOAUTH | NOCONF " "(default: AUTHCONF)\n"); fprintf(stderr, " -h: print usage and exit\n"); fprintf(stderr, " -m :\n"); fprintf(stderr, " usage | trace | record | size | mctx\n"); fprintf(stderr, " -v : set verbosity level (0 - 10)\n"); fprintf(stderr, " -V: print version information\n"); fprintf(stderr, "Timing options:\n"); fprintf(stderr, " -P date/[+-]offset/none: set key publication date " "(default: now)\n"); fprintf(stderr, " -P sync date/[+-]offset/none: set CDS and CDNSKEY " "publication date\n"); fprintf(stderr, " -A date/[+-]offset/none: set key activation date " "(default: now)\n"); fprintf(stderr, " -R date/[+-]offset/none: set key " "revocation date\n"); fprintf(stderr, " -I date/[+-]offset/none: set key " "inactivation date\n"); fprintf(stderr, " -D date/[+-]offset/none: set key deletion date\n"); fprintf(stderr, " -D sync date/[+-]offset/none: set CDS and CDNSKEY " "deletion date\n"); fprintf(stderr, " -G: generate key only; do not set -P or -A\n"); fprintf(stderr, " -C: generate a backward-compatible key, omitting " "all dates\n"); fprintf(stderr, " -S : generate a successor to an existing " "key\n"); fprintf(stderr, " -i : prepublication interval for " "successor key " "(default: 30 days)\n"); fprintf(stderr, "Output:\n"); fprintf(stderr, " K++.key, " "K++.private\n"); exit (-1); } static isc_boolean_t dsa_size_ok(int size) { return (ISC_TF(size >= 512 && size <= 1024 && size % 64 == 0)); } static void progress(int p) { char c = '*'; switch (p) { case 0: c = '.'; break; case 1: c = '+'; break; case 2: c = '*'; break; case 3: c = ' '; break; default: break; } (void) putc(c, stderr); (void) fflush(stderr); } int main(int argc, char **argv) { char *algname = NULL, *freeit = NULL; char *nametype = NULL, *type = NULL; char *classname = NULL; char *endp; dst_key_t *key = NULL; dns_fixedname_t fname; dns_name_t *name; isc_uint16_t flags = 0, kskflag = 0, revflag = 0; dns_secalg_t alg; isc_boolean_t conflict = ISC_FALSE, null_key = ISC_FALSE; isc_boolean_t oldstyle = ISC_FALSE; isc_mem_t *mctx = NULL; int ch, generator = 0, param = 0; int protocol = -1, size = -1, signatory = 0; isc_result_t ret; isc_textregion_t r; char filename[255]; const char *directory = NULL; const char *predecessor = NULL; dst_key_t *prevkey = NULL; isc_buffer_t buf; isc_log_t *log = NULL; isc_entropy_t *ectx = NULL; #ifdef USE_PKCS11 const char *engine = PKCS11_ENGINE; #else const char *engine = NULL; #endif dns_rdataclass_t rdclass; int options = DST_TYPE_PRIVATE | DST_TYPE_PUBLIC; int dbits = 0; dns_ttl_t ttl = 0; isc_boolean_t use_default = ISC_FALSE, use_nsec3 = ISC_FALSE; isc_stdtime_t publish = 0, activate = 0, revokekey = 0; isc_stdtime_t inactive = 0, deltime = 0; isc_stdtime_t now; int prepub = -1; isc_boolean_t setpub = ISC_FALSE, setact = ISC_FALSE; isc_boolean_t setrev = ISC_FALSE, setinact = ISC_FALSE; isc_boolean_t setdel = ISC_FALSE, setttl = ISC_FALSE; isc_boolean_t unsetpub = ISC_FALSE, unsetact = ISC_FALSE; isc_boolean_t unsetrev = ISC_FALSE, unsetinact = ISC_FALSE; isc_boolean_t unsetdel = ISC_FALSE; isc_boolean_t genonly = ISC_FALSE; isc_boolean_t quiet = ISC_FALSE; isc_boolean_t show_progress = ISC_FALSE; unsigned char c; isc_stdtime_t syncadd = 0, syncdel = 0; isc_boolean_t setsyncadd = ISC_FALSE; isc_boolean_t setsyncdel = ISC_FALSE; if (argc == 1) usage(); #ifdef PKCS11CRYPTO pk11_result_register(); #endif dns_result_register(); isc_commandline_errprint = ISC_FALSE; /* * Process memory debugging argument first. */ #define CMDLINE_FLAGS "3A:a:b:Cc:D:d:E:eFf:Gg:hI:i:K:kL:m:n:P:p:qR:r:S:s:T:t:" \ "v:V" while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) { switch (ch) { case 'm': if (strcasecmp(isc_commandline_argument, "record") == 0) isc_mem_debugging |= ISC_MEM_DEBUGRECORD; if (strcasecmp(isc_commandline_argument, "trace") == 0) isc_mem_debugging |= ISC_MEM_DEBUGTRACE; if (strcasecmp(isc_commandline_argument, "usage") == 0) isc_mem_debugging |= ISC_MEM_DEBUGUSAGE; if (strcasecmp(isc_commandline_argument, "size") == 0) isc_mem_debugging |= ISC_MEM_DEBUGSIZE; if (strcasecmp(isc_commandline_argument, "mctx") == 0) isc_mem_debugging |= ISC_MEM_DEBUGCTX; break; default: break; } } isc_commandline_reset = ISC_TRUE; RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS); isc_stdtime_get(&now); while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) { switch (ch) { case '3': use_nsec3 = ISC_TRUE; break; case 'a': algname = isc_commandline_argument; break; case 'b': size = strtol(isc_commandline_argument, &endp, 10); if (*endp != '\0' || size < 0) fatal("-b requires a non-negative number"); break; case 'C': oldstyle = ISC_TRUE; break; case 'c': classname = isc_commandline_argument; break; case 'd': dbits = strtol(isc_commandline_argument, &endp, 10); if (*endp != '\0' || dbits < 0) fatal("-d requires a non-negative number"); break; case 'E': engine = isc_commandline_argument; break; case 'e': fprintf(stderr, "phased-out option -e " "(was 'use (RSA) large exponent)\n"); break; case 'f': c = (unsigned char)(isc_commandline_argument[0]); if (toupper(c) == 'K') kskflag = DNS_KEYFLAG_KSK; else if (toupper(c) == 'R') revflag = DNS_KEYFLAG_REVOKE; else fatal("unknown flag '%s'", isc_commandline_argument); break; case 'g': generator = strtol(isc_commandline_argument, &endp, 10); if (*endp != '\0' || generator <= 0) fatal("-g requires a positive number"); break; case 'K': directory = isc_commandline_argument; ret = try_dir(directory); if (ret != ISC_R_SUCCESS) fatal("cannot open directory %s: %s", directory, isc_result_totext(ret)); break; case 'k': fatal("The -k option has been deprecated.\n" "To generate a key-signing key, use -f KSK.\n" "To generate a key with TYPE=KEY, use -T KEY.\n"); break; case 'L': ttl = strtottl(isc_commandline_argument); setttl = ISC_TRUE; break; case 'n': nametype = isc_commandline_argument; break; case 'm': break; case 'p': protocol = strtol(isc_commandline_argument, &endp, 10); if (*endp != '\0' || protocol < 0 || protocol > 255) fatal("-p must be followed by a number " "[0..255]"); break; case 'q': quiet = ISC_TRUE; break; case 'r': setup_entropy(mctx, isc_commandline_argument, &ectx); break; case 's': signatory = strtol(isc_commandline_argument, &endp, 10); if (*endp != '\0' || signatory < 0 || signatory > 15) fatal("-s must be followed by a number " "[0..15]"); break; case 'T': if (strcasecmp(isc_commandline_argument, "KEY") == 0) options |= DST_TYPE_KEY; else if (strcasecmp(isc_commandline_argument, "DNSKEY") == 0) /* default behavior */ ; else fatal("unknown type '%s'", isc_commandline_argument); break; case 't': type = isc_commandline_argument; break; case 'v': endp = NULL; verbose = strtol(isc_commandline_argument, &endp, 0); if (*endp != '\0') fatal("-v must be followed by a number"); break; case 'z': /* already the default */ break; case 'G': genonly = ISC_TRUE; break; case 'P': /* -Psync ? */ if (isoptarg("sync", argv, usage)) { if (setsyncadd) fatal("-P sync specified more than " "once"); syncadd = strtotime(isc_commandline_argument, now, now, &setsyncadd); break; } (void)isoptarg("dnskey", argv, usage); if (setpub || unsetpub) fatal("-P specified more than once"); publish = strtotime(isc_commandline_argument, now, now, &setpub); unsetpub = !setpub; break; case 'A': if (setact || unsetact) fatal("-A specified more than once"); activate = strtotime(isc_commandline_argument, now, now, &setact); unsetact = !setact; break; case 'R': if (setrev || unsetrev) fatal("-R specified more than once"); revokekey = strtotime(isc_commandline_argument, now, now, &setrev); unsetrev = !setrev; break; case 'I': if (setinact || unsetinact) fatal("-I specified more than once"); inactive = strtotime(isc_commandline_argument, now, now, &setinact); unsetinact = !setinact; break; case 'D': /* -Dsync ? */ if (isoptarg("sync", argv, usage)) { if (setsyncdel) fatal("-D sync specified more than " "once"); syncdel = strtotime(isc_commandline_argument, now, now, &setsyncdel); break; } (void)isoptarg("dnskey", argv, usage); if (setdel || unsetdel) fatal("-D specified more than once"); deltime = strtotime(isc_commandline_argument, now, now, &setdel); unsetdel = !setdel; break; case 'S': predecessor = isc_commandline_argument; break; case 'i': prepub = strtottl(isc_commandline_argument); break; case 'F': /* Reserved for FIPS mode */ /* FALLTHROUGH */ case '?': if (isc_commandline_option != '?') fprintf(stderr, "%s: invalid argument -%c\n", program, isc_commandline_option); /* FALLTHROUGH */ case 'h': /* Does not return. */ usage(); case 'V': /* Does not return. */ version(program); default: fprintf(stderr, "%s: unhandled option -%c\n", program, isc_commandline_option); exit(1); } } if (!isatty(0)) quiet = ISC_TRUE; if (ectx == NULL) setup_entropy(mctx, NULL, &ectx); ret = dst_lib_init2(mctx, ectx, engine, ISC_ENTROPY_BLOCKING | ISC_ENTROPY_GOODONLY); if (ret != ISC_R_SUCCESS) fatal("could not initialize dst: %s", isc_result_totext(ret)); setup_logging(mctx, &log); if (predecessor == NULL) { if (prepub == -1) prepub = 0; if (argc < isc_commandline_index + 1) fatal("the key name was not specified"); if (argc > isc_commandline_index + 1) fatal("extraneous arguments"); dns_fixedname_init(&fname); name = dns_fixedname_name(&fname); isc_buffer_init(&buf, argv[isc_commandline_index], strlen(argv[isc_commandline_index])); isc_buffer_add(&buf, strlen(argv[isc_commandline_index])); ret = dns_name_fromtext(name, &buf, dns_rootname, 0, NULL); if (ret != ISC_R_SUCCESS) fatal("invalid key name %s: %s", argv[isc_commandline_index], isc_result_totext(ret)); if (algname == NULL) { use_default = ISC_TRUE; if (use_nsec3) algname = strdup(DEFAULT_NSEC3_ALGORITHM); else algname = strdup(DEFAULT_ALGORITHM); if (algname == NULL) fatal("strdup failed"); freeit = algname; if (verbose > 0) fprintf(stderr, "no algorithm specified; " "defaulting to %s\n", algname); } if (strcasecmp(algname, "RSA") == 0) { #ifndef PK11_MD5_DISABLE fprintf(stderr, "The use of RSA (RSAMD5) is not " "recommended.\nIf you still wish to " "use RSA (RSAMD5) please specify " "\"-a RSAMD5\"\n"); INSIST(freeit == NULL); return (1); } else if (strcasecmp(algname, "HMAC-MD5") == 0) { alg = DST_ALG_HMACMD5; #else fprintf(stderr, "The use of RSA (RSAMD5) was disabled\n"); INSIST(freeit == NULL); return (1); } else if (strcasecmp(algname, "RSAMD5") == 0) { fprintf(stderr, "The use of RSAMD5 was disabled\n"); INSIST(freeit == NULL); return (1); } else if (strcasecmp(algname, "HMAC-MD5") == 0) { fprintf(stderr, "The use of HMAC-MD5 was disabled\n"); return (1); #endif } else if (strcasecmp(algname, "HMAC-SHA1") == 0) alg = DST_ALG_HMACSHA1; else if (strcasecmp(algname, "HMAC-SHA224") == 0) alg = DST_ALG_HMACSHA224; else if (strcasecmp(algname, "HMAC-SHA256") == 0) alg = DST_ALG_HMACSHA256; else if (strcasecmp(algname, "HMAC-SHA384") == 0) alg = DST_ALG_HMACSHA384; else if (strcasecmp(algname, "HMAC-SHA512") == 0) alg = DST_ALG_HMACSHA512; else { r.base = algname; r.length = strlen(algname); ret = dns_secalg_fromtext(&alg, &r); if (ret != ISC_R_SUCCESS) fatal("unknown algorithm %s", algname); if (alg == DST_ALG_DH) options |= DST_TYPE_KEY; } #ifdef PK11_MD5_DISABLE INSIST((alg != DNS_KEYALG_RSAMD5) && (alg != DST_ALG_HMACMD5)); #endif if (!dst_algorithm_supported(alg)) fatal("unsupported algorithm: %d", alg); if (use_nsec3 && alg != DST_ALG_NSEC3DSA && alg != DST_ALG_NSEC3RSASHA1 && alg != DST_ALG_RSASHA256 && alg!= DST_ALG_RSASHA512 && alg != DST_ALG_ECCGOST && alg != DST_ALG_ECDSA256 && alg != DST_ALG_ECDSA384 && alg != DST_ALG_ED25519 && alg != DST_ALG_ED448) { fatal("%s is incompatible with NSEC3; " "do not use the -3 option", algname); } if (type != NULL && (options & DST_TYPE_KEY) != 0) { if (strcasecmp(type, "NOAUTH") == 0) flags |= DNS_KEYTYPE_NOAUTH; else if (strcasecmp(type, "NOCONF") == 0) flags |= DNS_KEYTYPE_NOCONF; else if (strcasecmp(type, "NOAUTHCONF") == 0) { flags |= (DNS_KEYTYPE_NOAUTH | DNS_KEYTYPE_NOCONF); if (size < 0) size = 0; } else if (strcasecmp(type, "AUTHCONF") == 0) /* nothing */; else fatal("invalid type %s", type); } if (size < 0) { if (use_default) { if ((kskflag & DNS_KEYFLAG_KSK) != 0) size = 2048; else size = 1024; if (verbose > 0) fprintf(stderr, "key size not " "specified; defaulting" " to %d\n", size); } else if (alg != DST_ALG_ECCGOST && alg != DST_ALG_ECDSA256 && alg != DST_ALG_ECDSA384 && alg != DST_ALG_ED25519 && alg != DST_ALG_ED448) fatal("key size not specified (-b option)"); } if (!oldstyle && prepub > 0) { if (setpub && setact && (activate - prepub) < publish) fatal("Activation and publication dates " "are closer together than the\n\t" "prepublication interval."); if (!setpub && !setact) { setpub = setact = ISC_TRUE; publish = now; activate = now + prepub; } else if (setpub && !setact) { setact = ISC_TRUE; activate = publish + prepub; } else if (setact && !setpub) { setpub = ISC_TRUE; publish = activate - prepub; } if ((activate - prepub) < now) fatal("Time until activation is shorter " "than the\n\tprepublication interval."); } } else { char keystr[DST_KEY_FORMATSIZE]; isc_stdtime_t when; int major, minor; if (prepub == -1) prepub = (30 * 86400); if (algname != NULL) fatal("-S and -a cannot be used together"); if (size >= 0) fatal("-S and -b cannot be used together"); if (nametype != NULL) fatal("-S and -n cannot be used together"); if (type != NULL) fatal("-S and -t cannot be used together"); if (setpub || unsetpub) fatal("-S and -P cannot be used together"); if (setact || unsetact) fatal("-S and -A cannot be used together"); if (use_nsec3) fatal("-S and -3 cannot be used together"); if (oldstyle) fatal("-S and -C cannot be used together"); if (genonly) fatal("-S and -G cannot be used together"); ret = dst_key_fromnamedfile(predecessor, directory, DST_TYPE_PUBLIC | DST_TYPE_PRIVATE, mctx, &prevkey); if (ret != ISC_R_SUCCESS) fatal("Invalid keyfile %s: %s", predecessor, isc_result_totext(ret)); if (!dst_key_isprivate(prevkey)) fatal("%s is not a private key", predecessor); name = dst_key_name(prevkey); alg = dst_key_alg(prevkey); size = dst_key_size(prevkey); flags = dst_key_flags(prevkey); dst_key_format(prevkey, keystr, sizeof(keystr)); dst_key_getprivateformat(prevkey, &major, &minor); if (major != DST_MAJOR_VERSION || minor < DST_MINOR_VERSION) fatal("Key %s has incompatible format version %d.%d\n\t" "It is not possible to generate a successor key.", keystr, major, minor); ret = dst_key_gettime(prevkey, DST_TIME_ACTIVATE, &when); if (ret != ISC_R_SUCCESS) fatal("Key %s has no activation date.\n\t" "You must use dnssec-settime -A to set one " "before generating a successor.", keystr); ret = dst_key_gettime(prevkey, DST_TIME_INACTIVE, &activate); if (ret != ISC_R_SUCCESS) fatal("Key %s has no inactivation date.\n\t" "You must use dnssec-settime -I to set one " "before generating a successor.", keystr); publish = activate - prepub; if (publish < now) fatal("Key %s becomes inactive\n\t" "sooner than the prepublication period " "for the new key ends.\n\t" "Either change the inactivation date with " "dnssec-settime -I,\n\t" "or use the -i option to set a shorter " "prepublication interval.", keystr); ret = dst_key_gettime(prevkey, DST_TIME_DELETE, &when); if (ret != ISC_R_SUCCESS) fprintf(stderr, "%s: WARNING: Key %s has no removal " "date;\n\t it will remain in the zone " "indefinitely after rollover.\n\t " "You can use dnssec-settime -D to " "change this.\n", program, keystr); setpub = setact = ISC_TRUE; } switch (alg) { case DNS_KEYALG_RSAMD5: case DNS_KEYALG_RSASHA1: case DNS_KEYALG_NSEC3RSASHA1: case DNS_KEYALG_RSASHA256: if (size != 0 && (size < 512 || size > MAX_RSA)) fatal("RSA key size %d out of range", size); break; case DNS_KEYALG_RSASHA512: if (size != 0 && (size < 1024 || size > MAX_RSA)) fatal("RSA key size %d out of range", size); break; case DNS_KEYALG_DH: if (size != 0 && (size < 128 || size > 4096)) fatal("DH key size %d out of range", size); break; case DNS_KEYALG_DSA: case DNS_KEYALG_NSEC3DSA: if (size != 0 && !dsa_size_ok(size)) fatal("invalid DSS key size: %d", size); break; case DST_ALG_ECCGOST: size = 256; break; case DST_ALG_ECDSA256: size = 256; break; case DST_ALG_ECDSA384: size = 384; break; case DST_ALG_ED25519: size = 256; break; case DST_ALG_ED448: size = 456; break; case DST_ALG_HMACMD5: options |= DST_TYPE_KEY; if (size < 1 || size > 512) fatal("HMAC-MD5 key size %d out of range", size); if (dbits != 0 && (dbits < 80 || dbits > 128)) fatal("HMAC-MD5 digest bits %d out of range", dbits); if ((dbits % 8) != 0) fatal("HMAC-MD5 digest bits %d not divisible by 8", dbits); break; case DST_ALG_HMACSHA1: options |= DST_TYPE_KEY; if (size < 1 || size > 160) fatal("HMAC-SHA1 key size %d out of range", size); if (dbits != 0 && (dbits < 80 || dbits > 160)) fatal("HMAC-SHA1 digest bits %d out of range", dbits); if ((dbits % 8) != 0) fatal("HMAC-SHA1 digest bits %d not divisible by 8", dbits); break; case DST_ALG_HMACSHA224: options |= DST_TYPE_KEY; if (size < 1 || size > 224) fatal("HMAC-SHA224 key size %d out of range", size); if (dbits != 0 && (dbits < 112 || dbits > 224)) fatal("HMAC-SHA224 digest bits %d out of range", dbits); if ((dbits % 8) != 0) fatal("HMAC-SHA224 digest bits %d not divisible by 8", dbits); break; case DST_ALG_HMACSHA256: options |= DST_TYPE_KEY; if (size < 1 || size > 256) fatal("HMAC-SHA256 key size %d out of range", size); if (dbits != 0 && (dbits < 128 || dbits > 256)) fatal("HMAC-SHA256 digest bits %d out of range", dbits); if ((dbits % 8) != 0) fatal("HMAC-SHA256 digest bits %d not divisible by 8", dbits); break; case DST_ALG_HMACSHA384: options |= DST_TYPE_KEY; if (size < 1 || size > 384) fatal("HMAC-384 key size %d out of range", size); if (dbits != 0 && (dbits < 192 || dbits > 384)) fatal("HMAC-SHA384 digest bits %d out of range", dbits); if ((dbits % 8) != 0) fatal("HMAC-SHA384 digest bits %d not divisible by 8", dbits); break; case DST_ALG_HMACSHA512: options |= DST_TYPE_KEY; if (size < 1 || size > 512) fatal("HMAC-SHA512 key size %d out of range", size); if (dbits != 0 && (dbits < 256 || dbits > 512)) fatal("HMAC-SHA512 digest bits %d out of range", dbits); if ((dbits % 8) != 0) fatal("HMAC-SHA512 digest bits %d not divisible by 8", dbits); break; } if (alg != DNS_KEYALG_DH && generator != 0) fatal("specified DH generator for a non-DH key"); if (nametype == NULL) { if ((options & DST_TYPE_KEY) != 0) /* KEY / HMAC */ fatal("no nametype specified"); flags |= DNS_KEYOWNER_ZONE; /* DNSKEY */ } else if (strcasecmp(nametype, "zone") == 0) flags |= DNS_KEYOWNER_ZONE; else if ((options & DST_TYPE_KEY) != 0) { /* KEY / HMAC */ if (strcasecmp(nametype, "host") == 0 || strcasecmp(nametype, "entity") == 0) flags |= DNS_KEYOWNER_ENTITY; else if (strcasecmp(nametype, "user") == 0) flags |= DNS_KEYOWNER_USER; else fatal("invalid KEY nametype %s", nametype); } else if (strcasecmp(nametype, "other") != 0) /* DNSKEY */ fatal("invalid DNSKEY nametype %s", nametype); rdclass = strtoclass(classname); if (directory == NULL) directory = "."; if ((options & DST_TYPE_KEY) != 0) /* KEY / HMAC */ flags |= signatory; else if ((flags & DNS_KEYOWNER_ZONE) != 0) { /* DNSKEY */ flags |= kskflag; flags |= revflag; } if (protocol == -1) protocol = DNS_KEYPROTO_DNSSEC; else if ((options & DST_TYPE_KEY) == 0 && protocol != DNS_KEYPROTO_DNSSEC) fatal("invalid DNSKEY protocol: %d", protocol); if ((flags & DNS_KEYFLAG_TYPEMASK) == DNS_KEYTYPE_NOKEY) { if (size > 0) fatal("specified null key with non-zero size"); if ((flags & DNS_KEYFLAG_SIGNATORYMASK) != 0) fatal("specified null key with signing authority"); } if ((flags & DNS_KEYFLAG_OWNERMASK) == DNS_KEYOWNER_ZONE && (alg == DNS_KEYALG_DH || alg == DST_ALG_HMACMD5 || alg == DST_ALG_HMACSHA1 || alg == DST_ALG_HMACSHA224 || alg == DST_ALG_HMACSHA256 || alg == DST_ALG_HMACSHA384 || alg == DST_ALG_HMACSHA512)) fatal("a key with algorithm '%s' cannot be a zone key", algname); switch(alg) { case DNS_KEYALG_RSAMD5: case DNS_KEYALG_RSASHA1: case DNS_KEYALG_NSEC3RSASHA1: case DNS_KEYALG_RSASHA256: case DNS_KEYALG_RSASHA512: show_progress = ISC_TRUE; break; case DNS_KEYALG_DH: param = generator; break; case DNS_KEYALG_DSA: case DNS_KEYALG_NSEC3DSA: case DST_ALG_ECCGOST: case DST_ALG_ECDSA256: case DST_ALG_ECDSA384: case DST_ALG_ED25519: case DST_ALG_ED448: show_progress = ISC_TRUE; /* fall through */ case DST_ALG_HMACMD5: case DST_ALG_HMACSHA1: case DST_ALG_HMACSHA224: case DST_ALG_HMACSHA256: case DST_ALG_HMACSHA384: case DST_ALG_HMACSHA512: param = 0; break; } if ((flags & DNS_KEYFLAG_TYPEMASK) == DNS_KEYTYPE_NOKEY) null_key = ISC_TRUE; isc_buffer_init(&buf, filename, sizeof(filename) - 1); do { conflict = ISC_FALSE; if (!quiet && show_progress) { fprintf(stderr, "Generating key pair."); ret = dst_key_generate2(name, alg, size, param, flags, protocol, rdclass, mctx, &key, &progress); putc('\n', stderr); fflush(stderr); } else { ret = dst_key_generate2(name, alg, size, param, flags, protocol, rdclass, mctx, &key, NULL); } isc_entropy_stopcallbacksources(ectx); if (ret != ISC_R_SUCCESS) { char namestr[DNS_NAME_FORMATSIZE]; char algstr[DNS_SECALG_FORMATSIZE]; dns_name_format(name, namestr, sizeof(namestr)); dns_secalg_format(alg, algstr, sizeof(algstr)); fatal("failed to generate key %s/%s: %s\n", namestr, algstr, isc_result_totext(ret)); /* NOTREACHED */ exit(-1); } dst_key_setbits(key, dbits); /* * Set key timing metadata (unless using -C) * * Creation date is always set to "now". * * For a new key without an explicit predecessor, publish * and activation dates are set to "now" by default, but * can both be overridden. * * For a successor key, activation is set to match the * predecessor's inactivation date. Publish is set to 30 * days earlier than that (XXX: this should be configurable). * If either of the resulting dates are in the past, that's * an error; the inactivation date of the predecessor key * must be updated before a successor key can be created. */ if (!oldstyle) { dst_key_settime(key, DST_TIME_CREATED, now); if (genonly && (setpub || setact)) fatal("cannot use -G together with " "-P or -A options"); if (setpub) dst_key_settime(key, DST_TIME_PUBLISH, publish); else if (setact && !unsetpub) dst_key_settime(key, DST_TIME_PUBLISH, activate - prepub); else if (!genonly && !unsetpub) dst_key_settime(key, DST_TIME_PUBLISH, now); if (setact) dst_key_settime(key, DST_TIME_ACTIVATE, activate); else if (!genonly && !unsetact) dst_key_settime(key, DST_TIME_ACTIVATE, now); if (setrev) { if (kskflag == 0) fprintf(stderr, "%s: warning: Key is " "not flagged as a KSK, but -R " "was used. Revoking a ZSK is " "legal, but undefined.\n", program); dst_key_settime(key, DST_TIME_REVOKE, revokekey); } if (setinact) dst_key_settime(key, DST_TIME_INACTIVE, inactive); if (setdel) { if (setinact && deltime < inactive) fprintf(stderr, "%s: warning: Key is " "scheduled to be deleted " "before it is scheduled to be " "made inactive.\n", program); dst_key_settime(key, DST_TIME_DELETE, deltime); } if (setsyncadd) dst_key_settime(key, DST_TIME_SYNCPUBLISH, syncadd); if (setsyncdel) dst_key_settime(key, DST_TIME_SYNCDELETE, syncdel); } else { if (setpub || setact || setrev || setinact || setdel || unsetpub || unsetact || unsetrev || unsetinact || unsetdel || genonly || setsyncadd || setsyncdel) fatal("cannot use -C together with " "-P, -A, -R, -I, -D, or -G options"); /* * Compatibility mode: Private-key-format * should be set to 1.2. */ dst_key_setprivateformat(key, 1, 2); } /* Set the default key TTL */ if (setttl) dst_key_setttl(key, ttl); /* * Do not overwrite an existing key, or create a key * if there is a risk of ID collision due to this key * or another key being revoked. */ if (key_collision(key, name, directory, mctx, NULL)) { conflict = ISC_TRUE; if (null_key) { dst_key_free(&key); break; } if (verbose > 0) { isc_buffer_clear(&buf); ret = dst_key_buildfilename(key, 0, directory, &buf); if (ret == ISC_R_SUCCESS) fprintf(stderr, "%s: %s already exists, or " "might collide with another " "key upon revokation. " "Generating a new key\n", program, filename); } dst_key_free(&key); } } while (conflict == ISC_TRUE); if (conflict) fatal("cannot generate a null key due to possible key ID " "collision"); ret = dst_key_tofile(key, options, directory); if (ret != ISC_R_SUCCESS) { char keystr[DST_KEY_FORMATSIZE]; dst_key_format(key, keystr, sizeof(keystr)); fatal("failed to write key %s: %s\n", keystr, isc_result_totext(ret)); } isc_buffer_clear(&buf); ret = dst_key_buildfilename(key, 0, NULL, &buf); if (ret != ISC_R_SUCCESS) fatal("dst_key_buildfilename returned: %s\n", isc_result_totext(ret)); printf("%s\n", filename); dst_key_free(&key); if (prevkey != NULL) dst_key_free(&prevkey); cleanup_logging(&log); cleanup_entropy(&ectx); dst_lib_destroy(); dns_name_destroy(); if (verbose > 10) isc_mem_stats(mctx, stdout); isc_mem_destroy(&mctx); if (freeit != NULL) free(freeit); return (0); } bind9-9.11.3+dfsg/bin/dnssec/dnssec-keygen.docbook000066400000000000000000000557161325250447100217020ustar00rootroot00000000000000 2014-02-06 August 21, 2015 ISC Internet Systems Consortium, Inc. dnssec-keygen 8 BIND9 dnssec-keygen DNSSEC key generation tool 2000 2001 2002 2003 2004 2005 2007 2008 2009 2010 2011 2012 2014 2015 2016 2017 Internet Systems Consortium, Inc. ("ISC") dnssec-keygen name DESCRIPTION dnssec-keygen generates keys for DNSSEC (Secure DNS), as defined in RFC 2535 and RFC 4034. It can also generate keys for use with TSIG (Transaction Signatures) as defined in RFC 2845, or TKEY (Transaction Key) as defined in RFC 2930. The of the key is specified on the command line. For DNSSEC keys, this must match the name of the zone for which the key is being generated. OPTIONS -a algorithm Selects the cryptographic algorithm. For DNSSEC keys, the value of must be one of RSAMD5, RSASHA1, DSA, NSEC3RSASHA1, NSEC3DSA, RSASHA256, RSASHA512, ECCGOST, ECDSAP256SHA256, ECDSAP384SHA384, ED25519 or ED448. For TSIG/TKEY, the value must be DH (Diffie Hellman), HMAC-MD5, HMAC-SHA1, HMAC-SHA224, HMAC-SHA256, HMAC-SHA384, or HMAC-SHA512. These values are case insensitive. If no algorithm is specified, then RSASHA1 will be used by default, unless the option is specified, in which case NSEC3RSASHA1 will be used instead. (If is used and an algorithm is specified, that algorithm will be checked for compatibility with NSEC3.) Note 1: that for DNSSEC, RSASHA1 is a mandatory to implement algorithm, and DSA is recommended. For TSIG, HMAC-MD5 is mandatory. Note 2: DH, HMAC-MD5, and HMAC-SHA1 through HMAC-SHA512 automatically set the -T KEY option. -b keysize Specifies the number of bits in the key. The choice of key size depends on the algorithm used. RSA keys must be between 512 and 2048 bits. Diffie Hellman keys must be between 128 and 4096 bits. DSA keys must be between 512 and 1024 bits and an exact multiple of 64. HMAC keys must be between 1 and 512 bits. Elliptic curve algorithms don't need this parameter. The key size does not need to be specified if using a default algorithm. The default key size is 1024 bits for zone signing keys (ZSKs) and 2048 bits for key signing keys (KSKs, generated with ). However, if an algorithm is explicitly specified with the , then there is no default key size, and the must be used. -n nametype Specifies the owner type of the key. The value of must either be ZONE (for a DNSSEC zone key (KEY/DNSKEY)), HOST or ENTITY (for a key associated with a host (KEY)), USER (for a key associated with a user(KEY)) or OTHER (DNSKEY). These values are case insensitive. Defaults to ZONE for DNSKEY generation. -3 Use an NSEC3-capable algorithm to generate a DNSSEC key. If this option is used and no algorithm is explicitly set on the command line, NSEC3RSASHA1 will be used by default. Note that RSASHA256, RSASHA512, ECCGOST, ECDSAP256SHA256, ECDSAP384SHA384, ED25519 and ED448 algorithms are NSEC3-capable. -C Compatibility mode: generates an old-style key, without any metadata. By default, dnssec-keygen will include the key's creation date in the metadata stored with the private key, and other dates may be set there as well (publication date, activation date, etc). Keys that include this data may be incompatible with older versions of BIND; the option suppresses them. -c class Indicates that the DNS record containing the key should have the specified class. If not specified, class IN is used. -E engine Specifies the cryptographic hardware to use, when applicable. When BIND is built with OpenSSL PKCS#11 support, this defaults to the string "pkcs11", which identifies an OpenSSL engine that can drive a cryptographic accelerator or hardware service module. When BIND is built with native PKCS#11 cryptography (--enable-native-pkcs11), it defaults to the path of the PKCS#11 provider library specified via "--with-pkcs11". -f flag Set the specified flag in the flag field of the KEY/DNSKEY record. The only recognized flags are KSK (Key Signing Key) and REVOKE. -G Generate a key, but do not publish it or sign with it. This option is incompatible with -P and -A. -g generator If generating a Diffie Hellman key, use this generator. Allowed values are 2 and 5. If no generator is specified, a known prime from RFC 2539 will be used if possible; otherwise the default is 2. -h Prints a short summary of the options and arguments to dnssec-keygen. -K directory Sets the directory in which the key files are to be written. -k Deprecated in favor of -T KEY. -L ttl Sets the default TTL to use for this key when it is converted into a DNSKEY RR. If the key is imported into a zone, this is the TTL that will be used for it, unless there was already a DNSKEY RRset in place, in which case the existing TTL would take precedence. If this value is not set and there is no existing DNSKEY RRset, the TTL will default to the SOA TTL. Setting the default TTL to 0 or none is the same as leaving it unset. -p protocol Sets the protocol value for the generated key. The protocol is a number between 0 and 255. The default is 3 (DNSSEC). Other possible values for this argument are listed in RFC 2535 and its successors. -q Quiet mode: Suppresses unnecessary output, including progress indication. Without this option, when dnssec-keygen is run interactively to generate an RSA or DSA key pair, it will print a string of symbols to stderr indicating the progress of the key generation. A '.' indicates that a random number has been found which passed an initial sieve test; '+' means a number has passed a single round of the Miller-Rabin primality test; a space means that the number has passed all the tests and is a satisfactory key. -r randomdev Specifies the source of randomness. If the operating system does not provide a /dev/random or equivalent device, the default source of randomness is keyboard input. randomdev specifies the name of a character device or file containing random data to be used instead of the default. The special value keyboard indicates that keyboard input should be used. -S key Create a new key which is an explicit successor to an existing key. The name, algorithm, size, and type of the key will be set to match the existing key. The activation date of the new key will be set to the inactivation date of the existing one. The publication date will be set to the activation date minus the prepublication interval, which defaults to 30 days. -s strength Specifies the strength value of the key. The strength is a number between 0 and 15, and currently has no defined purpose in DNSSEC. -T rrtype Specifies the resource record type to use for the key. must be either DNSKEY or KEY. The default is DNSKEY when using a DNSSEC algorithm, but it can be overridden to KEY for use with SIG(0). Using any TSIG algorithm (HMAC-* or DH) forces this option to KEY. -t type Indicates the use of the key. must be one of AUTHCONF, NOAUTHCONF, NOAUTH, or NOCONF. The default is AUTHCONF. AUTH refers to the ability to authenticate data, and CONF the ability to encrypt data. -v level Sets the debugging level. -V Prints version information. TIMING OPTIONS Dates can be expressed in the format YYYYMMDD or YYYYMMDDHHMMSS. If the argument begins with a '+' or '-', it is interpreted as an offset from the present time. For convenience, if such an offset is followed by one of the suffixes 'y', 'mo', 'w', 'd', 'h', or 'mi', then the offset is computed in years (defined as 365 24-hour days, ignoring leap years), months (defined as 30 24-hour days), weeks, days, hours, or minutes, respectively. Without a suffix, the offset is computed in seconds. To explicitly prevent a date from being set, use 'none' or 'never'. -P date/offset Sets the date on which a key is to be published to the zone. After that date, the key will be included in the zone but will not be used to sign it. If not set, and if the -G option has not been used, the default is "now". -P sync date/offset Sets the date on which CDS and CDNSKEY records that match this key are to be published to the zone. -A date/offset Sets the date on which the key is to be activated. After that date, the key will be included in the zone and used to sign it. If not set, and if the -G option has not been used, the default is "now". If set, if and -P is not set, then the publication date will be set to the activation date minus the prepublication interval. -R date/offset Sets the date on which the key is to be revoked. After that date, the key will be flagged as revoked. It will be included in the zone and will be used to sign it. -I date/offset Sets the date on which the key is to be retired. After that date, the key will still be included in the zone, but it will not be used to sign it. -D date/offset Sets the date on which the key is to be deleted. After that date, the key will no longer be included in the zone. (It may remain in the key repository, however.) -D sync date/offset Sets the date on which the CDS and CDNSKEY records that match this key are to be deleted. -i interval Sets the prepublication interval for a key. If set, then the publication and activation dates must be separated by at least this much time. If the activation date is specified but the publication date isn't, then the publication date will default to this much time before the activation date; conversely, if the publication date is specified but activation date isn't, then activation will be set to this much time after publication. If the key is being created as an explicit successor to another key, then the default prepublication interval is 30 days; otherwise it is zero. As with date offsets, if the argument is followed by one of the suffixes 'y', 'mo', 'w', 'd', 'h', or 'mi', then the interval is measured in years, months, weeks, days, hours, or minutes, respectively. Without a suffix, the interval is measured in seconds. GENERATED KEYS When dnssec-keygen completes successfully, it prints a string of the form Knnnn.+aaa+iiiii to the standard output. This is an identification string for the key it has generated. nnnn is the key name. aaa is the numeric representation of the algorithm. iiiii is the key identifier (or footprint). dnssec-keygen creates two files, with names based on the printed string. Knnnn.+aaa+iiiii.key contains the public key, and Knnnn.+aaa+iiiii.private contains the private key. The .key file contains a DNS KEY record that can be inserted into a zone file (directly or with a $INCLUDE statement). The .private file contains algorithm-specific fields. For obvious security reasons, this file does not have general read permission. Both .key and .private files are generated for symmetric cryptography algorithms such as HMAC-MD5, even though the public and private key are equivalent. EXAMPLE To generate a 768-bit DSA key for the domain example.com, the following command would be issued: dnssec-keygen -a DSA -b 768 -n ZONE example.com The command would print a string of the form: Kexample.com.+003+26160 In this example, dnssec-keygen creates the files Kexample.com.+003+26160.key and Kexample.com.+003+26160.private. SEE ALSO dnssec-signzone8 , BIND 9 Administrator Reference Manual, RFC 2539, RFC 2845, RFC 4034. bind9-9.11.3+dfsg/bin/dnssec/dnssec-keygen.html000066400000000000000000000515001325250447100212110ustar00rootroot00000000000000 dnssec-keygen

Name

dnssec-keygen — DNSSEC key generation tool

Synopsis

dnssec-keygen [-a algorithm] [-b keysize] [-n nametype] [-3] [-A date/offset] [-C] [-c class] [-D date/offset] [-D sync date/offset] [-E engine] [-f flag] [-G] [-g generator] [-h] [-I date/offset] [-i interval] [-K directory] [-k] [-L ttl] [-P date/offset] [-P sync date/offset] [-p protocol] [-q] [-R date/offset] [-r randomdev] [-S key] [-s strength] [-t type] [-V] [-v level] [-z] {name}

DESCRIPTION

dnssec-keygen generates keys for DNSSEC (Secure DNS), as defined in RFC 2535 and RFC 4034. It can also generate keys for use with TSIG (Transaction Signatures) as defined in RFC 2845, or TKEY (Transaction Key) as defined in RFC 2930.

The name of the key is specified on the command line. For DNSSEC keys, this must match the name of the zone for which the key is being generated.

OPTIONS

-a algorithm

Selects the cryptographic algorithm. For DNSSEC keys, the value of algorithm must be one of RSAMD5, RSASHA1, DSA, NSEC3RSASHA1, NSEC3DSA, RSASHA256, RSASHA512, ECCGOST, ECDSAP256SHA256, ECDSAP384SHA384, ED25519 or ED448. For TSIG/TKEY, the value must be DH (Diffie Hellman), HMAC-MD5, HMAC-SHA1, HMAC-SHA224, HMAC-SHA256, HMAC-SHA384, or HMAC-SHA512. These values are case insensitive.

If no algorithm is specified, then RSASHA1 will be used by default, unless the -3 option is specified, in which case NSEC3RSASHA1 will be used instead. (If -3 is used and an algorithm is specified, that algorithm will be checked for compatibility with NSEC3.)

Note 1: that for DNSSEC, RSASHA1 is a mandatory to implement algorithm, and DSA is recommended. For TSIG, HMAC-MD5 is mandatory.

Note 2: DH, HMAC-MD5, and HMAC-SHA1 through HMAC-SHA512 automatically set the -T KEY option.

-b keysize

Specifies the number of bits in the key. The choice of key size depends on the algorithm used. RSA keys must be between 512 and 2048 bits. Diffie Hellman keys must be between 128 and 4096 bits. DSA keys must be between 512 and 1024 bits and an exact multiple of 64. HMAC keys must be between 1 and 512 bits. Elliptic curve algorithms don't need this parameter.

The key size does not need to be specified if using a default algorithm. The default key size is 1024 bits for zone signing keys (ZSKs) and 2048 bits for key signing keys (KSKs, generated with -f KSK). However, if an algorithm is explicitly specified with the -a, then there is no default key size, and the -b must be used.

-n nametype

Specifies the owner type of the key. The value of nametype must either be ZONE (for a DNSSEC zone key (KEY/DNSKEY)), HOST or ENTITY (for a key associated with a host (KEY)), USER (for a key associated with a user(KEY)) or OTHER (DNSKEY). These values are case insensitive. Defaults to ZONE for DNSKEY generation.

-3

Use an NSEC3-capable algorithm to generate a DNSSEC key. If this option is used and no algorithm is explicitly set on the command line, NSEC3RSASHA1 will be used by default. Note that RSASHA256, RSASHA512, ECCGOST, ECDSAP256SHA256, ECDSAP384SHA384, ED25519 and ED448 algorithms are NSEC3-capable.

-C

Compatibility mode: generates an old-style key, without any metadata. By default, dnssec-keygen will include the key's creation date in the metadata stored with the private key, and other dates may be set there as well (publication date, activation date, etc). Keys that include this data may be incompatible with older versions of BIND; the -C option suppresses them.

-c class

Indicates that the DNS record containing the key should have the specified class. If not specified, class IN is used.

-E engine

Specifies the cryptographic hardware to use, when applicable.

When BIND is built with OpenSSL PKCS#11 support, this defaults to the string "pkcs11", which identifies an OpenSSL engine that can drive a cryptographic accelerator or hardware service module. When BIND is built with native PKCS#11 cryptography (--enable-native-pkcs11), it defaults to the path of the PKCS#11 provider library specified via "--with-pkcs11".

-f flag

Set the specified flag in the flag field of the KEY/DNSKEY record. The only recognized flags are KSK (Key Signing Key) and REVOKE.

-G

Generate a key, but do not publish it or sign with it. This option is incompatible with -P and -A.

-g generator

If generating a Diffie Hellman key, use this generator. Allowed values are 2 and 5. If no generator is specified, a known prime from RFC 2539 will be used if possible; otherwise the default is 2.

-h

Prints a short summary of the options and arguments to dnssec-keygen.

-K directory

Sets the directory in which the key files are to be written.

-k

Deprecated in favor of -T KEY.

-L ttl

Sets the default TTL to use for this key when it is converted into a DNSKEY RR. If the key is imported into a zone, this is the TTL that will be used for it, unless there was already a DNSKEY RRset in place, in which case the existing TTL would take precedence. If this value is not set and there is no existing DNSKEY RRset, the TTL will default to the SOA TTL. Setting the default TTL to 0 or none is the same as leaving it unset.

-p protocol

Sets the protocol value for the generated key. The protocol is a number between 0 and 255. The default is 3 (DNSSEC). Other possible values for this argument are listed in RFC 2535 and its successors.

-q

Quiet mode: Suppresses unnecessary output, including progress indication. Without this option, when dnssec-keygen is run interactively to generate an RSA or DSA key pair, it will print a string of symbols to stderr indicating the progress of the key generation. A '.' indicates that a random number has been found which passed an initial sieve test; '+' means a number has passed a single round of the Miller-Rabin primality test; a space means that the number has passed all the tests and is a satisfactory key.

-r randomdev

Specifies the source of randomness. If the operating system does not provide a /dev/random or equivalent device, the default source of randomness is keyboard input. randomdev specifies the name of a character device or file containing random data to be used instead of the default. The special value keyboard indicates that keyboard input should be used.

-S key

Create a new key which is an explicit successor to an existing key. The name, algorithm, size, and type of the key will be set to match the existing key. The activation date of the new key will be set to the inactivation date of the existing one. The publication date will be set to the activation date minus the prepublication interval, which defaults to 30 days.

-s strength

Specifies the strength value of the key. The strength is a number between 0 and 15, and currently has no defined purpose in DNSSEC.

-T rrtype

Specifies the resource record type to use for the key. rrtype must be either DNSKEY or KEY. The default is DNSKEY when using a DNSSEC algorithm, but it can be overridden to KEY for use with SIG(0).

Using any TSIG algorithm (HMAC-* or DH) forces this option to KEY.

-t type

Indicates the use of the key. type must be one of AUTHCONF, NOAUTHCONF, NOAUTH, or NOCONF. The default is AUTHCONF. AUTH refers to the ability to authenticate data, and CONF the ability to encrypt data.

-v level

Sets the debugging level.

-V

Prints version information.

TIMING OPTIONS

Dates can be expressed in the format YYYYMMDD or YYYYMMDDHHMMSS. If the argument begins with a '+' or '-', it is interpreted as an offset from the present time. For convenience, if such an offset is followed by one of the suffixes 'y', 'mo', 'w', 'd', 'h', or 'mi', then the offset is computed in years (defined as 365 24-hour days, ignoring leap years), months (defined as 30 24-hour days), weeks, days, hours, or minutes, respectively. Without a suffix, the offset is computed in seconds. To explicitly prevent a date from being set, use 'none' or 'never'.

-P date/offset

Sets the date on which a key is to be published to the zone. After that date, the key will be included in the zone but will not be used to sign it. If not set, and if the -G option has not been used, the default is "now".

-P sync date/offset

Sets the date on which CDS and CDNSKEY records that match this key are to be published to the zone.

-A date/offset

Sets the date on which the key is to be activated. After that date, the key will be included in the zone and used to sign it. If not set, and if the -G option has not been used, the default is "now". If set, if and -P is not set, then the publication date will be set to the activation date minus the prepublication interval.

-R date/offset

Sets the date on which the key is to be revoked. After that date, the key will be flagged as revoked. It will be included in the zone and will be used to sign it.

-I date/offset

Sets the date on which the key is to be retired. After that date, the key will still be included in the zone, but it will not be used to sign it.

-D date/offset

Sets the date on which the key is to be deleted. After that date, the key will no longer be included in the zone. (It may remain in the key repository, however.)

-D sync date/offset

Sets the date on which the CDS and CDNSKEY records that match this key are to be deleted.

-i interval

Sets the prepublication interval for a key. If set, then the publication and activation dates must be separated by at least this much time. If the activation date is specified but the publication date isn't, then the publication date will default to this much time before the activation date; conversely, if the publication date is specified but activation date isn't, then activation will be set to this much time after publication.

If the key is being created as an explicit successor to another key, then the default prepublication interval is 30 days; otherwise it is zero.

As with date offsets, if the argument is followed by one of the suffixes 'y', 'mo', 'w', 'd', 'h', or 'mi', then the interval is measured in years, months, weeks, days, hours, or minutes, respectively. Without a suffix, the interval is measured in seconds.

GENERATED KEYS

When dnssec-keygen completes successfully, it prints a string of the form Knnnn.+aaa+iiiii to the standard output. This is an identification string for the key it has generated.

  • nnnn is the key name.

  • aaa is the numeric representation of the algorithm.

  • iiiii is the key identifier (or footprint).

dnssec-keygen creates two files, with names based on the printed string. Knnnn.+aaa+iiiii.key contains the public key, and Knnnn.+aaa+iiiii.private contains the private key.

The .key file contains a DNS KEY record that can be inserted into a zone file (directly or with a $INCLUDE statement).

The .private file contains algorithm-specific fields. For obvious security reasons, this file does not have general read permission.

Both .key and .private files are generated for symmetric cryptography algorithms such as HMAC-MD5, even though the public and private key are equivalent.

EXAMPLE

To generate a 768-bit DSA key for the domain example.com, the following command would be issued:

dnssec-keygen -a DSA -b 768 -n ZONE example.com

The command would print a string of the form:

Kexample.com.+003+26160

In this example, dnssec-keygen creates the files Kexample.com.+003+26160.key and Kexample.com.+003+26160.private.

SEE ALSO

dnssec-signzone(8) , BIND 9 Administrator Reference Manual, RFC 2539, RFC 2845, RFC 4034.

bind9-9.11.3+dfsg/bin/dnssec/dnssec-revoke.8000066400000000000000000000063511325250447100204310ustar00rootroot00000000000000.\" Copyright (C) 2009, 2011, 2014-2016 Internet Systems Consortium, Inc. ("ISC") .\" .\" This Source Code Form is subject to the terms of the Mozilla Public .\" License, v. 2.0. If a copy of the MPL was not distributed with this .\" file, You can obtain one at http://mozilla.org/MPL/2.0/. .\" .hy 0 .ad l '\" t .\" Title: dnssec-revoke .\" Author: .\" Generator: DocBook XSL Stylesheets v1.78.1 .\" Date: 2014-01-15 .\" Manual: BIND9 .\" Source: ISC .\" Language: English .\" .TH "DNSSEC\-REVOKE" "8" "2014\-01\-15" "ISC" "BIND9" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" dnssec-revoke \- set the REVOKED bit on a DNSSEC key .SH "SYNOPSIS" .HP \w'\fBdnssec\-revoke\fR\ 'u \fBdnssec\-revoke\fR [\fB\-hr\fR] [\fB\-v\ \fR\fB\fIlevel\fR\fR] [\fB\-V\fR] [\fB\-K\ \fR\fB\fIdirectory\fR\fR] [\fB\-E\ \fR\fB\fIengine\fR\fR] [\fB\-f\fR] [\fB\-R\fR] {keyfile} .SH "DESCRIPTION" .PP \fBdnssec\-revoke\fR reads a DNSSEC key file, sets the REVOKED bit on the key as defined in RFC 5011, and creates a new pair of key files containing the now\-revoked key\&. .SH "OPTIONS" .PP \-h .RS 4 Emit usage message and exit\&. .RE .PP \-K \fIdirectory\fR .RS 4 Sets the directory in which the key files are to reside\&. .RE .PP \-r .RS 4 After writing the new keyset files remove the original keyset files\&. .RE .PP \-v \fIlevel\fR .RS 4 Sets the debugging level\&. .RE .PP \-V .RS 4 Prints version information\&. .RE .PP \-E \fIengine\fR .RS 4 Specifies the cryptographic hardware to use, when applicable\&. .sp When BIND is built with OpenSSL PKCS#11 support, this defaults to the string "pkcs11", which identifies an OpenSSL engine that can drive a cryptographic accelerator or hardware service module\&. When BIND is built with native PKCS#11 cryptography (\-\-enable\-native\-pkcs11), it defaults to the path of the PKCS#11 provider library specified via "\-\-with\-pkcs11"\&. .RE .PP \-f .RS 4 Force overwrite: Causes \fBdnssec\-revoke\fR to write the new key pair even if a file already exists matching the algorithm and key ID of the revoked key\&. .RE .PP \-R .RS 4 Print the key tag of the key with the REVOKE bit set but do not revoke the key\&. .RE .SH "SEE ALSO" .PP \fBdnssec-keygen\fR(8), BIND 9 Administrator Reference Manual, RFC 5011\&. .SH "AUTHOR" .PP \fBInternet Systems Consortium, Inc\&.\fR .SH "COPYRIGHT" .br Copyright \(co 2009, 2011, 2014-2016 Internet Systems Consortium, Inc. ("ISC") .br bind9-9.11.3+dfsg/bin/dnssec/dnssec-revoke.c000066400000000000000000000157331325250447100205100ustar00rootroot00000000000000/* * Copyright (C) 2009-2012, 2014-2017 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /*! \file */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef PKCS11CRYPTO #include #endif #include "dnssectool.h" const char *program = "dnssec-revoke"; int verbose; static isc_mem_t *mctx = NULL; ISC_PLATFORM_NORETURN_PRE static void usage(void) ISC_PLATFORM_NORETURN_POST; static void usage(void) { fprintf(stderr, "Usage:\n"); fprintf(stderr, " %s [options] keyfile\n\n", program); fprintf(stderr, "Version: %s\n", VERSION); #if defined(PKCS11CRYPTO) fprintf(stderr, " -E engine: specify PKCS#11 provider " "(default: %s)\n", PK11_LIB_LOCATION); #elif defined(USE_PKCS11) fprintf(stderr, " -E engine: specify OpenSSL engine " "(default \"pkcs11\")\n"); #else fprintf(stderr, " -E engine: specify OpenSSL engine\n"); #endif fprintf(stderr, " -f: force overwrite\n"); fprintf(stderr, " -K directory: use directory for key files\n"); fprintf(stderr, " -h: help\n"); fprintf(stderr, " -r: remove old keyfiles after " "creating revoked version\n"); fprintf(stderr, " -v level: set level of verbosity\n"); fprintf(stderr, " -V: print version information\n"); fprintf(stderr, "Output:\n"); fprintf(stderr, " K++.key, " "K++.private\n"); exit (-1); } int main(int argc, char **argv) { isc_result_t result; #ifdef USE_PKCS11 const char *engine = PKCS11_ENGINE; #else const char *engine = NULL; #endif char const *filename = NULL; char *dir = NULL; char newname[1024], oldname[1024]; char keystr[DST_KEY_FORMATSIZE]; char *endp; int ch; isc_entropy_t *ectx = NULL; dst_key_t *key = NULL; isc_uint32_t flags; isc_buffer_t buf; isc_boolean_t force = ISC_FALSE; isc_boolean_t removefile = ISC_FALSE; isc_boolean_t id = ISC_FALSE; if (argc == 1) usage(); result = isc_mem_create(0, 0, &mctx); if (result != ISC_R_SUCCESS) fatal("Out of memory"); #ifdef PKCS11CRYPTO pk11_result_register(); #endif dns_result_register(); isc_commandline_errprint = ISC_FALSE; while ((ch = isc_commandline_parse(argc, argv, "E:fK:rRhv:V")) != -1) { switch (ch) { case 'E': engine = isc_commandline_argument; break; case 'f': force = ISC_TRUE; break; case 'K': /* * We don't have to copy it here, but do it to * simplify cleanup later */ dir = isc_mem_strdup(mctx, isc_commandline_argument); if (dir == NULL) { fatal("Failed to allocate memory for " "directory"); } break; case 'r': removefile = ISC_TRUE; break; case 'R': id = ISC_TRUE; break; case 'v': verbose = strtol(isc_commandline_argument, &endp, 0); if (*endp != '\0') fatal("-v must be followed by a number"); break; case '?': if (isc_commandline_option != '?') fprintf(stderr, "%s: invalid argument -%c\n", program, isc_commandline_option); /* FALLTHROUGH */ case 'h': /* Does not return. */ usage(); case 'V': /* Does not return. */ version(program); default: fprintf(stderr, "%s: unhandled option -%c\n", program, isc_commandline_option); exit(1); } } if (argc < isc_commandline_index + 1 || argv[isc_commandline_index] == NULL) fatal("The key file name was not specified"); if (argc > isc_commandline_index + 1) fatal("Extraneous arguments"); if (dir != NULL) { filename = argv[isc_commandline_index]; } else { result = isc_file_splitpath(mctx, argv[isc_commandline_index], &dir, &filename); if (result != ISC_R_SUCCESS) fatal("cannot process filename %s: %s", argv[isc_commandline_index], isc_result_totext(result)); if (strcmp(dir, ".") == 0) { isc_mem_free(mctx, dir); dir = NULL; } } if (ectx == NULL) setup_entropy(mctx, NULL, &ectx); result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE); if (result != ISC_R_SUCCESS) fatal("Could not initialize hash"); result = dst_lib_init2(mctx, ectx, engine, ISC_ENTROPY_BLOCKING | ISC_ENTROPY_GOODONLY); if (result != ISC_R_SUCCESS) fatal("Could not initialize dst: %s", isc_result_totext(result)); isc_entropy_stopcallbacksources(ectx); result = dst_key_fromnamedfile(filename, dir, DST_TYPE_PUBLIC|DST_TYPE_PRIVATE, mctx, &key); if (result != ISC_R_SUCCESS) fatal("Invalid keyfile name %s: %s", filename, isc_result_totext(result)); if (id) { fprintf(stdout, "%u\n", dst_key_rid(key)); goto cleanup; } dst_key_format(key, keystr, sizeof(keystr)); if (verbose > 2) fprintf(stderr, "%s: %s\n", program, keystr); if (force) set_keyversion(key); else check_keyversion(key, keystr); flags = dst_key_flags(key); if ((flags & DNS_KEYFLAG_REVOKE) == 0) { isc_stdtime_t now; if ((flags & DNS_KEYFLAG_KSK) == 0) fprintf(stderr, "%s: warning: Key is not flagged " "as a KSK. Revoking a ZSK is " "legal, but undefined.\n", program); isc_stdtime_get(&now); dst_key_settime(key, DST_TIME_REVOKE, now); dst_key_setflags(key, flags | DNS_KEYFLAG_REVOKE); isc_buffer_init(&buf, newname, sizeof(newname)); dst_key_buildfilename(key, DST_TYPE_PUBLIC, dir, &buf); if (access(newname, F_OK) == 0 && !force) { fatal("Key file %s already exists; " "use -f to force overwrite", newname); } result = dst_key_tofile(key, DST_TYPE_PUBLIC|DST_TYPE_PRIVATE, dir); if (result != ISC_R_SUCCESS) { dst_key_format(key, keystr, sizeof(keystr)); fatal("Failed to write key %s: %s", keystr, isc_result_totext(result)); } isc_buffer_clear(&buf); dst_key_buildfilename(key, 0, dir, &buf); printf("%s\n", newname); /* * Remove old key file, if told to (and if * it isn't the same as the new file) */ if (removefile && dst_key_alg(key) != DST_ALG_RSAMD5) { isc_buffer_init(&buf, oldname, sizeof(oldname)); dst_key_setflags(key, flags & ~DNS_KEYFLAG_REVOKE); dst_key_buildfilename(key, DST_TYPE_PRIVATE, dir, &buf); if (strcmp(oldname, newname) == 0) goto cleanup; (void)unlink(oldname); isc_buffer_clear(&buf); dst_key_buildfilename(key, DST_TYPE_PUBLIC, dir, &buf); (void)unlink(oldname); } } else { dst_key_format(key, keystr, sizeof(keystr)); fatal("Key %s is already revoked", keystr); } cleanup: dst_key_free(&key); dst_lib_destroy(); isc_hash_destroy(); cleanup_entropy(&ectx); if (verbose > 10) isc_mem_stats(mctx, stdout); if (dir != NULL) isc_mem_free(mctx, dir); isc_mem_destroy(&mctx); return (0); } bind9-9.11.3+dfsg/bin/dnssec/dnssec-revoke.docbook000066400000000000000000000116361325250447100217040ustar00rootroot00000000000000 2014-01-15 ISC Internet Systems Consortium, Inc. dnssec-revoke 8 BIND9 dnssec-revoke set the REVOKED bit on a DNSSEC key 2009 2011 2014 2015 2016 Internet Systems Consortium, Inc. ("ISC") dnssec-revoke keyfile DESCRIPTION dnssec-revoke reads a DNSSEC key file, sets the REVOKED bit on the key as defined in RFC 5011, and creates a new pair of key files containing the now-revoked key. OPTIONS -h Emit usage message and exit. -K directory Sets the directory in which the key files are to reside. -r After writing the new keyset files remove the original keyset files. -v level Sets the debugging level. -V Prints version information. -E engine Specifies the cryptographic hardware to use, when applicable. When BIND is built with OpenSSL PKCS#11 support, this defaults to the string "pkcs11", which identifies an OpenSSL engine that can drive a cryptographic accelerator or hardware service module. When BIND is built with native PKCS#11 cryptography (--enable-native-pkcs11), it defaults to the path of the PKCS#11 provider library specified via "--with-pkcs11". -f Force overwrite: Causes dnssec-revoke to write the new key pair even if a file already exists matching the algorithm and key ID of the revoked key. -R Print the key tag of the key with the REVOKE bit set but do not revoke the key. SEE ALSO dnssec-keygen8 , BIND 9 Administrator Reference Manual, RFC 5011. bind9-9.11.3+dfsg/bin/dnssec/dnssec-revoke.html000066400000000000000000000102301325250447100212150ustar00rootroot00000000000000 dnssec-revoke

Name

dnssec-revoke — set the REVOKED bit on a DNSSEC key

Synopsis

dnssec-revoke [-hr] [-v level] [-V] [-K directory] [-E engine] [-f] [-R] {keyfile}

DESCRIPTION

dnssec-revoke reads a DNSSEC key file, sets the REVOKED bit on the key as defined in RFC 5011, and creates a new pair of key files containing the now-revoked key.

OPTIONS

-h

Emit usage message and exit.

-K directory

Sets the directory in which the key files are to reside.

-r

After writing the new keyset files remove the original keyset files.

-v level

Sets the debugging level.

-V

Prints version information.

-E engine

Specifies the cryptographic hardware to use, when applicable.

When BIND is built with OpenSSL PKCS#11 support, this defaults to the string "pkcs11", which identifies an OpenSSL engine that can drive a cryptographic accelerator or hardware service module. When BIND is built with native PKCS#11 cryptography (--enable-native-pkcs11), it defaults to the path of the PKCS#11 provider library specified via "--with-pkcs11".

-f

Force overwrite: Causes dnssec-revoke to write the new key pair even if a file already exists matching the algorithm and key ID of the revoked key.

-R

Print the key tag of the key with the REVOKE bit set but do not revoke the key.

SEE ALSO

dnssec-keygen(8) , BIND 9 Administrator Reference Manual, RFC 5011.

bind9-9.11.3+dfsg/bin/dnssec/dnssec-settime.8000066400000000000000000000215231325250447100206060ustar00rootroot00000000000000.\" Copyright (C) 2009-2011, 2014-2017 Internet Systems Consortium, Inc. ("ISC") .\" .\" This Source Code Form is subject to the terms of the Mozilla Public .\" License, v. 2.0. If a copy of the MPL was not distributed with this .\" file, You can obtain one at http://mozilla.org/MPL/2.0/. .\" .hy 0 .ad l '\" t .\" Title: dnssec-settime .\" Author: .\" Generator: DocBook XSL Stylesheets v1.78.1 .\" Date: 2015-08-21 .\" Manual: BIND9 .\" Source: ISC .\" Language: English .\" .TH "DNSSEC\-SETTIME" "8" "2015\-08\-21" "ISC" "BIND9" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" dnssec-settime \- set the key timing metadata for a DNSSEC key .SH "SYNOPSIS" .HP \w'\fBdnssec\-settime\fR\ 'u \fBdnssec\-settime\fR [\fB\-f\fR] [\fB\-K\ \fR\fB\fIdirectory\fR\fR] [\fB\-L\ \fR\fB\fIttl\fR\fR] [\fB\-P\ \fR\fB\fIdate/offset\fR\fR] [\fB\-P\ sync\ \fR\fB\fIdate/offset\fR\fR] [\fB\-A\ \fR\fB\fIdate/offset\fR\fR] [\fB\-R\ \fR\fB\fIdate/offset\fR\fR] [\fB\-I\ \fR\fB\fIdate/offset\fR\fR] [\fB\-D\ \fR\fB\fIdate/offset\fR\fR] [\fB\-D\ sync\ \fR\fB\fIdate/offset\fR\fR] [\fB\-S\ \fR\fB\fIkey\fR\fR] [\fB\-i\ \fR\fB\fIinterval\fR\fR] [\fB\-h\fR] [\fB\-V\fR] [\fB\-v\ \fR\fB\fIlevel\fR\fR] [\fB\-E\ \fR\fB\fIengine\fR\fR] {keyfile} .SH "DESCRIPTION" .PP \fBdnssec\-settime\fR reads a DNSSEC private key file and sets the key timing metadata as specified by the \fB\-P\fR, \fB\-A\fR, \fB\-R\fR, \fB\-I\fR, and \fB\-D\fR options\&. The metadata can then be used by \fBdnssec\-signzone\fR or other signing software to determine when a key is to be published, whether it should be used for signing a zone, etc\&. .PP If none of these options is set on the command line, then \fBdnssec\-settime\fR simply prints the key timing metadata already stored in the key\&. .PP When key metadata fields are changed, both files of a key pair (Knnnn\&.+aaa+iiiii\&.key and Knnnn\&.+aaa+iiiii\&.private) are regenerated\&. Metadata fields are stored in the private file\&. A human\-readable description of the metadata is also placed in comments in the key file\&. The private file\*(Aqs permissions are always set to be inaccessible to anyone other than the owner (mode 0600)\&. .SH "OPTIONS" .PP \-f .RS 4 Force an update of an old\-format key with no metadata fields\&. Without this option, \fBdnssec\-settime\fR will fail when attempting to update a legacy key\&. With this option, the key will be recreated in the new format, but with the original key data retained\&. The key\*(Aqs creation date will be set to the present time\&. If no other values are specified, then the key\*(Aqs publication and activation dates will also be set to the present time\&. .RE .PP \-K \fIdirectory\fR .RS 4 Sets the directory in which the key files are to reside\&. .RE .PP \-L \fIttl\fR .RS 4 Sets the default TTL to use for this key when it is converted into a DNSKEY RR\&. If the key is imported into a zone, this is the TTL that will be used for it, unless there was already a DNSKEY RRset in place, in which case the existing TTL would take precedence\&. If this value is not set and there is no existing DNSKEY RRset, the TTL will default to the SOA TTL\&. Setting the default TTL to 0 or none removes it from the key\&. .RE .PP \-h .RS 4 Emit usage message and exit\&. .RE .PP \-V .RS 4 Prints version information\&. .RE .PP \-v \fIlevel\fR .RS 4 Sets the debugging level\&. .RE .PP \-E \fIengine\fR .RS 4 Specifies the cryptographic hardware to use, when applicable\&. .sp When BIND is built with OpenSSL PKCS#11 support, this defaults to the string "pkcs11", which identifies an OpenSSL engine that can drive a cryptographic accelerator or hardware service module\&. When BIND is built with native PKCS#11 cryptography (\-\-enable\-native\-pkcs11), it defaults to the path of the PKCS#11 provider library specified via "\-\-with\-pkcs11"\&. .RE .SH "TIMING OPTIONS" .PP Dates can be expressed in the format YYYYMMDD or YYYYMMDDHHMMSS\&. If the argument begins with a \*(Aq+\*(Aq or \*(Aq\-\*(Aq, it is interpreted as an offset from the present time\&. For convenience, if such an offset is followed by one of the suffixes \*(Aqy\*(Aq, \*(Aqmo\*(Aq, \*(Aqw\*(Aq, \*(Aqd\*(Aq, \*(Aqh\*(Aq, or \*(Aqmi\*(Aq, then the offset is computed in years (defined as 365 24\-hour days, ignoring leap years), months (defined as 30 24\-hour days), weeks, days, hours, or minutes, respectively\&. Without a suffix, the offset is computed in seconds\&. To unset a date, use \*(Aqnone\*(Aq or \*(Aqnever\*(Aq\&. .PP \-P \fIdate/offset\fR .RS 4 Sets the date on which a key is to be published to the zone\&. After that date, the key will be included in the zone but will not be used to sign it\&. .RE .PP \-P sync \fIdate/offset\fR .RS 4 Sets the date on which CDS and CDNSKEY records that match this key are to be published to the zone\&. .RE .PP \-A \fIdate/offset\fR .RS 4 Sets the date on which the key is to be activated\&. After that date, the key will be included in the zone and used to sign it\&. .RE .PP \-R \fIdate/offset\fR .RS 4 Sets the date on which the key is to be revoked\&. After that date, the key will be flagged as revoked\&. It will be included in the zone and will be used to sign it\&. .RE .PP \-I \fIdate/offset\fR .RS 4 Sets the date on which the key is to be retired\&. After that date, the key will still be included in the zone, but it will not be used to sign it\&. .RE .PP \-D \fIdate/offset\fR .RS 4 Sets the date on which the key is to be deleted\&. After that date, the key will no longer be included in the zone\&. (It may remain in the key repository, however\&.) .RE .PP \-D sync \fIdate/offset\fR .RS 4 Sets the date on which the CDS and CDNSKEY records that match this key are to be deleted\&. .RE .PP \-S \fIpredecessor key\fR .RS 4 Select a key for which the key being modified will be an explicit successor\&. The name, algorithm, size, and type of the predecessor key must exactly match those of the key being modified\&. The activation date of the successor key will be set to the inactivation date of the predecessor\&. The publication date will be set to the activation date minus the prepublication interval, which defaults to 30 days\&. .RE .PP \-i \fIinterval\fR .RS 4 Sets the prepublication interval for a key\&. If set, then the publication and activation dates must be separated by at least this much time\&. If the activation date is specified but the publication date isn\*(Aqt, then the publication date will default to this much time before the activation date; conversely, if the publication date is specified but activation date isn\*(Aqt, then activation will be set to this much time after publication\&. .sp If the key is being set to be an explicit successor to another key, then the default prepublication interval is 30 days; otherwise it is zero\&. .sp As with date offsets, if the argument is followed by one of the suffixes \*(Aqy\*(Aq, \*(Aqmo\*(Aq, \*(Aqw\*(Aq, \*(Aqd\*(Aq, \*(Aqh\*(Aq, or \*(Aqmi\*(Aq, then the interval is measured in years, months, weeks, days, hours, or minutes, respectively\&. Without a suffix, the interval is measured in seconds\&. .RE .SH "PRINTING OPTIONS" .PP \fBdnssec\-settime\fR can also be used to print the timing metadata associated with a key\&. .PP \-u .RS 4 Print times in UNIX epoch format\&. .RE .PP \-p \fIC/P/Psync/A/R/I/D/Dsync/all\fR .RS 4 Print a specific metadata value or set of metadata values\&. The \fB\-p\fR option may be followed by one or more of the following letters or strings to indicate which value or values to print: \fBC\fR for the creation date, \fBP\fR for the publication date, \fBPsync\fR for the CDS and CDNSKEY publication date, \fBA\fR for the activation date, \fBR\fR for the revocation date, \fBI\fR for the inactivation date, \fBD\fR for the deletion date, and \fBDsync\fR for the CDS and CDNSKEY deletion date To print all of the metadata, use \fB\-p all\fR\&. .RE .SH "SEE ALSO" .PP \fBdnssec-keygen\fR(8), \fBdnssec-signzone\fR(8), BIND 9 Administrator Reference Manual, RFC 5011\&. .SH "AUTHOR" .PP \fBInternet Systems Consortium, Inc\&.\fR .SH "COPYRIGHT" .br Copyright \(co 2009-2011, 2014-2017 Internet Systems Consortium, Inc. ("ISC") .br bind9-9.11.3+dfsg/bin/dnssec/dnssec-settime.c000066400000000000000000000444721325250447100206710ustar00rootroot00000000000000/* * Copyright (C) 2009-2017 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /*! \file */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef PKCS11CRYPTO #include #endif #include "dnssectool.h" const char *program = "dnssec-settime"; int verbose; static isc_mem_t *mctx = NULL; ISC_PLATFORM_NORETURN_PRE static void usage(void) ISC_PLATFORM_NORETURN_POST; static void usage(void) { fprintf(stderr, "Usage:\n"); fprintf(stderr, " %s [options] keyfile\n\n", program); fprintf(stderr, "Version: %s\n", VERSION); fprintf(stderr, "General options:\n"); #if defined(PKCS11CRYPTO) fprintf(stderr, " -E engine: specify PKCS#11 provider " "(default: %s)\n", PK11_LIB_LOCATION); #elif defined(USE_PKCS11) fprintf(stderr, " -E engine: specify OpenSSL engine " "(default \"pkcs11\")\n"); #else fprintf(stderr, " -E engine: specify OpenSSL engine\n"); #endif fprintf(stderr, " -f: force update of old-style " "keys\n"); fprintf(stderr, " -K directory: set key file location\n"); fprintf(stderr, " -L ttl: set default key TTL\n"); fprintf(stderr, " -v level: set level of verbosity\n"); fprintf(stderr, " -V: print version information\n"); fprintf(stderr, " -h: help\n"); fprintf(stderr, "Timing options:\n"); fprintf(stderr, " -P date/[+-]offset/none: set/unset key " "publication date\n"); fprintf(stderr, " -P sync date/[+-]offset/none: set/unset " "CDS and CDNSKEY publication date\n"); fprintf(stderr, " -A date/[+-]offset/none: set/unset key " "activation date\n"); fprintf(stderr, " -R date/[+-]offset/none: set/unset key " "revocation date\n"); fprintf(stderr, " -I date/[+-]offset/none: set/unset key " "inactivation date\n"); fprintf(stderr, " -D date/[+-]offset/none: set/unset key " "deletion date\n"); fprintf(stderr, " -D sync date/[+-]offset/none: set/unset " "CDS and CDNSKEY deletion date\n"); fprintf(stderr, " -S : generate a successor to an existing " "key\n"); fprintf(stderr, " -i : prepublication interval for " "successor key " "(default: 30 days)\n"); fprintf(stderr, "Printing options:\n"); fprintf(stderr, " -p C/P/Psync/A/R/I/D/Dsync/all: print a " "particular time value or values\n"); fprintf(stderr, " -u: print times in unix epoch " "format\n"); fprintf(stderr, "Output:\n"); fprintf(stderr, " K++.key, " "K++.private\n"); exit (-1); } static void printtime(dst_key_t *key, int type, const char *tag, isc_boolean_t epoch, FILE *stream) { isc_result_t result; const char *output = NULL; isc_stdtime_t when; if (tag != NULL) fprintf(stream, "%s: ", tag); result = dst_key_gettime(key, type, &when); if (result == ISC_R_NOTFOUND) { fprintf(stream, "UNSET\n"); } else if (epoch) { fprintf(stream, "%d\n", (int) when); } else { time_t timet = when; output = ctime(&timet); fprintf(stream, "%s", output); } } int main(int argc, char **argv) { isc_result_t result; #ifdef USE_PKCS11 const char *engine = PKCS11_ENGINE; #else const char *engine = NULL; #endif const char *filename = NULL; char *directory = NULL; char newname[1024]; char keystr[DST_KEY_FORMATSIZE]; char *endp, *p; int ch; isc_entropy_t *ectx = NULL; const char *predecessor = NULL; dst_key_t *prevkey = NULL; dst_key_t *key = NULL; isc_buffer_t buf; dns_name_t *name = NULL; dns_secalg_t alg = 0; unsigned int size = 0; isc_uint16_t flags = 0; int prepub = -1; dns_ttl_t ttl = 0; isc_stdtime_t now; isc_stdtime_t pub = 0, act = 0, rev = 0, inact = 0, del = 0; isc_stdtime_t prevact = 0, previnact = 0, prevdel = 0; isc_boolean_t setpub = ISC_FALSE, setact = ISC_FALSE; isc_boolean_t setrev = ISC_FALSE, setinact = ISC_FALSE; isc_boolean_t setdel = ISC_FALSE, setttl = ISC_FALSE; isc_boolean_t unsetpub = ISC_FALSE, unsetact = ISC_FALSE; isc_boolean_t unsetrev = ISC_FALSE, unsetinact = ISC_FALSE; isc_boolean_t unsetdel = ISC_FALSE; isc_boolean_t printcreate = ISC_FALSE, printpub = ISC_FALSE; isc_boolean_t printact = ISC_FALSE, printrev = ISC_FALSE; isc_boolean_t printinact = ISC_FALSE, printdel = ISC_FALSE; isc_boolean_t force = ISC_FALSE; isc_boolean_t epoch = ISC_FALSE; isc_boolean_t changed = ISC_FALSE; isc_log_t *log = NULL; isc_stdtime_t syncadd = 0, syncdel = 0; isc_boolean_t unsetsyncadd = ISC_FALSE, setsyncadd = ISC_FALSE; isc_boolean_t unsetsyncdel = ISC_FALSE, setsyncdel = ISC_FALSE; isc_boolean_t printsyncadd = ISC_FALSE, printsyncdel = ISC_FALSE; if (argc == 1) usage(); result = isc_mem_create(0, 0, &mctx); if (result != ISC_R_SUCCESS) fatal("Out of memory"); setup_logging(mctx, &log); #ifdef PKCS11CRYPTO pk11_result_register(); #endif dns_result_register(); isc_commandline_errprint = ISC_FALSE; isc_stdtime_get(&now); #define CMDLINE_FLAGS "A:D:E:fhI:i:K:L:P:p:R:S:uv:V" while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) { switch (ch) { case 'E': engine = isc_commandline_argument; break; case 'f': force = ISC_TRUE; break; case 'p': p = isc_commandline_argument; if (!strcasecmp(p, "all")) { printcreate = ISC_TRUE; printpub = ISC_TRUE; printact = ISC_TRUE; printrev = ISC_TRUE; printinact = ISC_TRUE; printdel = ISC_TRUE; printsyncadd = ISC_TRUE; printsyncdel = ISC_TRUE; break; } do { switch (*p++) { case 'C': printcreate = ISC_TRUE; break; case 'P': if (!strncmp(p, "sync", 4)) { p += 4; printsyncadd = ISC_TRUE; break; } printpub = ISC_TRUE; break; case 'A': printact = ISC_TRUE; break; case 'R': printrev = ISC_TRUE; break; case 'I': printinact = ISC_TRUE; break; case 'D': if (!strncmp(p, "sync", 4)) { p += 4; printsyncdel = ISC_TRUE; break; } printdel = ISC_TRUE; break; case ' ': break; default: usage(); break; } } while (*p != '\0'); break; case 'u': epoch = ISC_TRUE; break; case 'K': /* * We don't have to copy it here, but do it to * simplify cleanup later */ directory = isc_mem_strdup(mctx, isc_commandline_argument); if (directory == NULL) { fatal("Failed to allocate memory for " "directory"); } break; case 'L': ttl = strtottl(isc_commandline_argument); setttl = ISC_TRUE; break; case 'v': verbose = strtol(isc_commandline_argument, &endp, 0); if (*endp != '\0') fatal("-v must be followed by a number"); break; case 'P': /* -Psync ? */ if (isoptarg("sync", argv, usage)) { if (unsetsyncadd || setsyncadd) fatal("-P sync specified more than " "once"); changed = ISC_TRUE; syncadd = strtotime(isc_commandline_argument, now, now, &setsyncadd); unsetsyncadd = !setsyncadd; break; } (void)isoptarg("dnskey", argv, usage); if (setpub || unsetpub) fatal("-P specified more than once"); changed = ISC_TRUE; pub = strtotime(isc_commandline_argument, now, now, &setpub); unsetpub = !setpub; break; case 'A': if (setact || unsetact) fatal("-A specified more than once"); changed = ISC_TRUE; act = strtotime(isc_commandline_argument, now, now, &setact); unsetact = !setact; break; case 'R': if (setrev || unsetrev) fatal("-R specified more than once"); changed = ISC_TRUE; rev = strtotime(isc_commandline_argument, now, now, &setrev); unsetrev = !setrev; break; case 'I': if (setinact || unsetinact) fatal("-I specified more than once"); changed = ISC_TRUE; inact = strtotime(isc_commandline_argument, now, now, &setinact); unsetinact = !setinact; break; case 'D': /* -Dsync ? */ if (isoptarg("sync", argv, usage)) { if (unsetsyncdel || setsyncdel) fatal("-D sync specified more than " "once"); changed = ISC_TRUE; syncdel = strtotime(isc_commandline_argument, now, now, &setsyncdel); unsetsyncdel = !setsyncdel; break; } /* -Ddnskey ? */ (void)isoptarg("dnskey", argv, usage); if (setdel || unsetdel) fatal("-D specified more than once"); changed = ISC_TRUE; del = strtotime(isc_commandline_argument, now, now, &setdel); unsetdel = !setdel; break; case 'S': predecessor = isc_commandline_argument; break; case 'i': prepub = strtottl(isc_commandline_argument); break; case '?': if (isc_commandline_option != '?') fprintf(stderr, "%s: invalid argument -%c\n", program, isc_commandline_option); /* FALLTHROUGH */ case 'h': /* Does not return. */ usage(); case 'V': /* Does not return. */ version(program); default: fprintf(stderr, "%s: unhandled option -%c\n", program, isc_commandline_option); exit(1); } } if (argc < isc_commandline_index + 1 || argv[isc_commandline_index] == NULL) fatal("The key file name was not specified"); if (argc > isc_commandline_index + 1) fatal("Extraneous arguments"); if (ectx == NULL) setup_entropy(mctx, NULL, &ectx); result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE); if (result != ISC_R_SUCCESS) fatal("Could not initialize hash"); result = dst_lib_init2(mctx, ectx, engine, ISC_ENTROPY_BLOCKING | ISC_ENTROPY_GOODONLY); if (result != ISC_R_SUCCESS) fatal("Could not initialize dst: %s", isc_result_totext(result)); isc_entropy_stopcallbacksources(ectx); if (predecessor != NULL) { int major, minor; if (prepub == -1) prepub = (30 * 86400); if (setpub || unsetpub) fatal("-S and -P cannot be used together"); if (setact || unsetact) fatal("-S and -A cannot be used together"); result = dst_key_fromnamedfile(predecessor, directory, DST_TYPE_PUBLIC | DST_TYPE_PRIVATE, mctx, &prevkey); if (result != ISC_R_SUCCESS) fatal("Invalid keyfile %s: %s", filename, isc_result_totext(result)); if (!dst_key_isprivate(prevkey) && !dst_key_isexternal(prevkey)) fatal("%s is not a private key", filename); name = dst_key_name(prevkey); alg = dst_key_alg(prevkey); size = dst_key_size(prevkey); flags = dst_key_flags(prevkey); dst_key_format(prevkey, keystr, sizeof(keystr)); dst_key_getprivateformat(prevkey, &major, &minor); if (major != DST_MAJOR_VERSION || minor < DST_MINOR_VERSION) fatal("Predecessor has incompatible format " "version %d.%d\n\t", major, minor); result = dst_key_gettime(prevkey, DST_TIME_ACTIVATE, &prevact); if (result != ISC_R_SUCCESS) fatal("Predecessor has no activation date. " "You must set one before\n\t" "generating a successor."); result = dst_key_gettime(prevkey, DST_TIME_INACTIVE, &previnact); if (result != ISC_R_SUCCESS) fatal("Predecessor has no inactivation date. " "You must set one before\n\t" "generating a successor."); pub = previnact - prepub; act = previnact; if ((previnact - prepub) < now && prepub != 0) fatal("Time until predecessor inactivation is\n\t" "shorter than the prepublication interval. " "Either change\n\t" "predecessor inactivation date, or use the -i " "option to set\n\t" "a shorter prepublication interval."); result = dst_key_gettime(prevkey, DST_TIME_DELETE, &prevdel); if (result != ISC_R_SUCCESS) fprintf(stderr, "%s: warning: Predecessor has no " "removal date;\n\t" "it will remain in the zone " "indefinitely after rollover.\n", program); else if (prevdel < previnact) fprintf(stderr, "%s: warning: Predecessor is " "scheduled to be deleted\n\t" "before it is scheduled to be " "inactive.\n", program); changed = setpub = setact = ISC_TRUE; } else { if (prepub < 0) prepub = 0; if (prepub > 0) { if (setpub && setact && (act - prepub) < pub) fatal("Activation and publication dates " "are closer together than the\n\t" "prepublication interval."); if (setpub && !setact) { setact = ISC_TRUE; act = pub + prepub; } else if (setact && !setpub) { setpub = ISC_TRUE; pub = act - prepub; } if ((act - prepub) < now) fatal("Time until activation is shorter " "than the\n\tprepublication interval."); } } if (directory != NULL) { filename = argv[isc_commandline_index]; } else { result = isc_file_splitpath(mctx, argv[isc_commandline_index], &directory, &filename); if (result != ISC_R_SUCCESS) fatal("cannot process filename %s: %s", argv[isc_commandline_index], isc_result_totext(result)); } result = dst_key_fromnamedfile(filename, directory, DST_TYPE_PUBLIC | DST_TYPE_PRIVATE, mctx, &key); if (result != ISC_R_SUCCESS) fatal("Invalid keyfile %s: %s", filename, isc_result_totext(result)); if (!dst_key_isprivate(key) && !dst_key_isexternal(key)) fatal("%s is not a private key", filename); dst_key_format(key, keystr, sizeof(keystr)); if (predecessor != NULL) { if (!dns_name_equal(name, dst_key_name(key))) fatal("Key name mismatch"); if (alg != dst_key_alg(key)) fatal("Key algorithm mismatch"); if (size != dst_key_size(key)) fatal("Key size mismatch"); if (flags != dst_key_flags(key)) fatal("Key flags mismatch"); } prevdel = previnact = 0; if ((setdel && setinact && del < inact) || (dst_key_gettime(key, DST_TIME_INACTIVE, &previnact) == ISC_R_SUCCESS && setdel && !setinact && !unsetinact && del < previnact) || (dst_key_gettime(key, DST_TIME_DELETE, &prevdel) == ISC_R_SUCCESS && setinact && !setdel && !unsetdel && prevdel < inact) || (!setdel && !unsetdel && !setinact && !unsetinact && prevdel != 0 && prevdel < previnact)) fprintf(stderr, "%s: warning: Key is scheduled to " "be deleted before it is\n\t" "scheduled to be inactive.\n", program); if (force) set_keyversion(key); else check_keyversion(key, keystr); if (verbose > 2) fprintf(stderr, "%s: %s\n", program, keystr); /* * Set time values. */ if (setpub) dst_key_settime(key, DST_TIME_PUBLISH, pub); else if (unsetpub) dst_key_unsettime(key, DST_TIME_PUBLISH); if (setact) dst_key_settime(key, DST_TIME_ACTIVATE, act); else if (unsetact) dst_key_unsettime(key, DST_TIME_ACTIVATE); if (setrev) { if ((dst_key_flags(key) & DNS_KEYFLAG_REVOKE) != 0) fprintf(stderr, "%s: warning: Key %s is already " "revoked; changing the revocation date " "will not affect this.\n", program, keystr); if ((dst_key_flags(key) & DNS_KEYFLAG_KSK) == 0) fprintf(stderr, "%s: warning: Key %s is not flagged as " "a KSK, but -R was used. Revoking a " "ZSK is legal, but undefined.\n", program, keystr); dst_key_settime(key, DST_TIME_REVOKE, rev); } else if (unsetrev) { if ((dst_key_flags(key) & DNS_KEYFLAG_REVOKE) != 0) fprintf(stderr, "%s: warning: Key %s is already " "revoked; removing the revocation date " "will not affect this.\n", program, keystr); dst_key_unsettime(key, DST_TIME_REVOKE); } if (setinact) dst_key_settime(key, DST_TIME_INACTIVE, inact); else if (unsetinact) dst_key_unsettime(key, DST_TIME_INACTIVE); if (setdel) dst_key_settime(key, DST_TIME_DELETE, del); else if (unsetdel) dst_key_unsettime(key, DST_TIME_DELETE); if (setsyncadd) dst_key_settime(key, DST_TIME_SYNCPUBLISH, syncadd); else if (unsetsyncadd) dst_key_unsettime(key, DST_TIME_SYNCPUBLISH); if (setsyncdel) dst_key_settime(key, DST_TIME_SYNCDELETE, syncdel); else if (unsetsyncdel) dst_key_unsettime(key, DST_TIME_SYNCDELETE); if (setttl) dst_key_setttl(key, ttl); /* * No metadata changes were made but we're forcing an upgrade * to the new format anyway: use "-P now -A now" as the default */ if (force && !changed) { dst_key_settime(key, DST_TIME_PUBLISH, now); dst_key_settime(key, DST_TIME_ACTIVATE, now); changed = ISC_TRUE; } if (!changed && setttl) changed = ISC_TRUE; /* * Print out time values, if -p was used. */ if (printcreate) printtime(key, DST_TIME_CREATED, "Created", epoch, stdout); if (printpub) printtime(key, DST_TIME_PUBLISH, "Publish", epoch, stdout); if (printact) printtime(key, DST_TIME_ACTIVATE, "Activate", epoch, stdout); if (printrev) printtime(key, DST_TIME_REVOKE, "Revoke", epoch, stdout); if (printinact) printtime(key, DST_TIME_INACTIVE, "Inactive", epoch, stdout); if (printdel) printtime(key, DST_TIME_DELETE, "Delete", epoch, stdout); if (printsyncadd) printtime(key, DST_TIME_SYNCPUBLISH, "SYNC Publish", epoch, stdout); if (printsyncdel) printtime(key, DST_TIME_SYNCDELETE, "SYNC Delete", epoch, stdout); if (changed) { isc_buffer_init(&buf, newname, sizeof(newname)); result = dst_key_buildfilename(key, DST_TYPE_PUBLIC, directory, &buf); if (result != ISC_R_SUCCESS) { fatal("Failed to build public key filename: %s", isc_result_totext(result)); } result = dst_key_tofile(key, DST_TYPE_PUBLIC|DST_TYPE_PRIVATE, directory); if (result != ISC_R_SUCCESS) { dst_key_format(key, keystr, sizeof(keystr)); fatal("Failed to write key %s: %s", keystr, isc_result_totext(result)); } printf("%s\n", newname); isc_buffer_clear(&buf); result = dst_key_buildfilename(key, DST_TYPE_PRIVATE, directory, &buf); if (result != ISC_R_SUCCESS) { fatal("Failed to build private key filename: %s", isc_result_totext(result)); } printf("%s\n", newname); } if (prevkey != NULL) dst_key_free(&prevkey); dst_key_free(&key); dst_lib_destroy(); isc_hash_destroy(); cleanup_entropy(&ectx); if (verbose > 10) isc_mem_stats(mctx, stdout); cleanup_logging(&log); isc_mem_free(mctx, directory); isc_mem_destroy(&mctx); return (0); } bind9-9.11.3+dfsg/bin/dnssec/dnssec-settime.docbook000066400000000000000000000346461325250447100220710ustar00rootroot00000000000000 2015-08-21 ISC Internet Systems Consortium, Inc. dnssec-settime 8 BIND9 dnssec-settime set the key timing metadata for a DNSSEC key 2009 2010 2011 2014 2015 2016 2017 Internet Systems Consortium, Inc. ("ISC") dnssec-settime keyfile DESCRIPTION dnssec-settime reads a DNSSEC private key file and sets the key timing metadata as specified by the , , , , and options. The metadata can then be used by dnssec-signzone or other signing software to determine when a key is to be published, whether it should be used for signing a zone, etc. If none of these options is set on the command line, then dnssec-settime simply prints the key timing metadata already stored in the key. When key metadata fields are changed, both files of a key pair (Knnnn.+aaa+iiiii.key and Knnnn.+aaa+iiiii.private) are regenerated. Metadata fields are stored in the private file. A human-readable description of the metadata is also placed in comments in the key file. The private file's permissions are always set to be inaccessible to anyone other than the owner (mode 0600). OPTIONS -f Force an update of an old-format key with no metadata fields. Without this option, dnssec-settime will fail when attempting to update a legacy key. With this option, the key will be recreated in the new format, but with the original key data retained. The key's creation date will be set to the present time. If no other values are specified, then the key's publication and activation dates will also be set to the present time. -K directory Sets the directory in which the key files are to reside. -L ttl Sets the default TTL to use for this key when it is converted into a DNSKEY RR. If the key is imported into a zone, this is the TTL that will be used for it, unless there was already a DNSKEY RRset in place, in which case the existing TTL would take precedence. If this value is not set and there is no existing DNSKEY RRset, the TTL will default to the SOA TTL. Setting the default TTL to 0 or none removes it from the key. -h Emit usage message and exit. -V Prints version information. -v level Sets the debugging level. -E engine Specifies the cryptographic hardware to use, when applicable. When BIND is built with OpenSSL PKCS#11 support, this defaults to the string "pkcs11", which identifies an OpenSSL engine that can drive a cryptographic accelerator or hardware service module. When BIND is built with native PKCS#11 cryptography (--enable-native-pkcs11), it defaults to the path of the PKCS#11 provider library specified via "--with-pkcs11". TIMING OPTIONS Dates can be expressed in the format YYYYMMDD or YYYYMMDDHHMMSS. If the argument begins with a '+' or '-', it is interpreted as an offset from the present time. For convenience, if such an offset is followed by one of the suffixes 'y', 'mo', 'w', 'd', 'h', or 'mi', then the offset is computed in years (defined as 365 24-hour days, ignoring leap years), months (defined as 30 24-hour days), weeks, days, hours, or minutes, respectively. Without a suffix, the offset is computed in seconds. To unset a date, use 'none' or 'never'. -P date/offset Sets the date on which a key is to be published to the zone. After that date, the key will be included in the zone but will not be used to sign it. -P sync date/offset Sets the date on which CDS and CDNSKEY records that match this key are to be published to the zone. -A date/offset Sets the date on which the key is to be activated. After that date, the key will be included in the zone and used to sign it. -R date/offset Sets the date on which the key is to be revoked. After that date, the key will be flagged as revoked. It will be included in the zone and will be used to sign it. -I date/offset Sets the date on which the key is to be retired. After that date, the key will still be included in the zone, but it will not be used to sign it. -D date/offset Sets the date on which the key is to be deleted. After that date, the key will no longer be included in the zone. (It may remain in the key repository, however.) -D sync date/offset Sets the date on which the CDS and CDNSKEY records that match this key are to be deleted. -S predecessor key Select a key for which the key being modified will be an explicit successor. The name, algorithm, size, and type of the predecessor key must exactly match those of the key being modified. The activation date of the successor key will be set to the inactivation date of the predecessor. The publication date will be set to the activation date minus the prepublication interval, which defaults to 30 days. -i interval Sets the prepublication interval for a key. If set, then the publication and activation dates must be separated by at least this much time. If the activation date is specified but the publication date isn't, then the publication date will default to this much time before the activation date; conversely, if the publication date is specified but activation date isn't, then activation will be set to this much time after publication. If the key is being set to be an explicit successor to another key, then the default prepublication interval is 30 days; otherwise it is zero. As with date offsets, if the argument is followed by one of the suffixes 'y', 'mo', 'w', 'd', 'h', or 'mi', then the interval is measured in years, months, weeks, days, hours, or minutes, respectively. Without a suffix, the interval is measured in seconds. PRINTING OPTIONS dnssec-settime can also be used to print the timing metadata associated with a key. -u Print times in UNIX epoch format. -p C/P/Psync/A/R/I/D/Dsync/all Print a specific metadata value or set of metadata values. The option may be followed by one or more of the following letters or strings to indicate which value or values to print: for the creation date, for the publication date, for the CDS and CDNSKEY publication date, for the activation date, for the revocation date, for the inactivation date, for the deletion date, and for the CDS and CDNSKEY deletion date To print all of the metadata, use . SEE ALSO dnssec-keygen8 , dnssec-signzone8 , BIND 9 Administrator Reference Manual, RFC 5011. bind9-9.11.3+dfsg/bin/dnssec/dnssec-settime.html000066400000000000000000000321041325250447100214000ustar00rootroot00000000000000 dnssec-settime

Name

dnssec-settime — set the key timing metadata for a DNSSEC key

Synopsis

dnssec-settime [-f] [-K directory] [-L ttl] [-P date/offset] [-P sync date/offset] [-A date/offset] [-R date/offset] [-I date/offset] [-D date/offset] [-D sync date/offset] [-S key] [-i interval] [-h] [-V] [-v level] [-E engine] {keyfile}

DESCRIPTION

dnssec-settime reads a DNSSEC private key file and sets the key timing metadata as specified by the -P, -A, -R, -I, and -D options. The metadata can then be used by dnssec-signzone or other signing software to determine when a key is to be published, whether it should be used for signing a zone, etc.

If none of these options is set on the command line, then dnssec-settime simply prints the key timing metadata already stored in the key.

When key metadata fields are changed, both files of a key pair (Knnnn.+aaa+iiiii.key and Knnnn.+aaa+iiiii.private) are regenerated. Metadata fields are stored in the private file. A human-readable description of the metadata is also placed in comments in the key file. The private file's permissions are always set to be inaccessible to anyone other than the owner (mode 0600).

OPTIONS

-f

Force an update of an old-format key with no metadata fields. Without this option, dnssec-settime will fail when attempting to update a legacy key. With this option, the key will be recreated in the new format, but with the original key data retained. The key's creation date will be set to the present time. If no other values are specified, then the key's publication and activation dates will also be set to the present time.

-K directory

Sets the directory in which the key files are to reside.

-L ttl

Sets the default TTL to use for this key when it is converted into a DNSKEY RR. If the key is imported into a zone, this is the TTL that will be used for it, unless there was already a DNSKEY RRset in place, in which case the existing TTL would take precedence. If this value is not set and there is no existing DNSKEY RRset, the TTL will default to the SOA TTL. Setting the default TTL to 0 or none removes it from the key.

-h

Emit usage message and exit.

-V

Prints version information.

-v level

Sets the debugging level.

-E engine

Specifies the cryptographic hardware to use, when applicable.

When BIND is built with OpenSSL PKCS#11 support, this defaults to the string "pkcs11", which identifies an OpenSSL engine that can drive a cryptographic accelerator or hardware service module. When BIND is built with native PKCS#11 cryptography (--enable-native-pkcs11), it defaults to the path of the PKCS#11 provider library specified via "--with-pkcs11".

TIMING OPTIONS

Dates can be expressed in the format YYYYMMDD or YYYYMMDDHHMMSS. If the argument begins with a '+' or '-', it is interpreted as an offset from the present time. For convenience, if such an offset is followed by one of the suffixes 'y', 'mo', 'w', 'd', 'h', or 'mi', then the offset is computed in years (defined as 365 24-hour days, ignoring leap years), months (defined as 30 24-hour days), weeks, days, hours, or minutes, respectively. Without a suffix, the offset is computed in seconds. To unset a date, use 'none' or 'never'.

-P date/offset

Sets the date on which a key is to be published to the zone. After that date, the key will be included in the zone but will not be used to sign it.

-P sync date/offset

Sets the date on which CDS and CDNSKEY records that match this key are to be published to the zone.

-A date/offset

Sets the date on which the key is to be activated. After that date, the key will be included in the zone and used to sign it.

-R date/offset

Sets the date on which the key is to be revoked. After that date, the key will be flagged as revoked. It will be included in the zone and will be used to sign it.

-I date/offset

Sets the date on which the key is to be retired. After that date, the key will still be included in the zone, but it will not be used to sign it.

-D date/offset

Sets the date on which the key is to be deleted. After that date, the key will no longer be included in the zone. (It may remain in the key repository, however.)

-D sync date/offset

Sets the date on which the CDS and CDNSKEY records that match this key are to be deleted.

-S predecessor key

Select a key for which the key being modified will be an explicit successor. The name, algorithm, size, and type of the predecessor key must exactly match those of the key being modified. The activation date of the successor key will be set to the inactivation date of the predecessor. The publication date will be set to the activation date minus the prepublication interval, which defaults to 30 days.

-i interval

Sets the prepublication interval for a key. If set, then the publication and activation dates must be separated by at least this much time. If the activation date is specified but the publication date isn't, then the publication date will default to this much time before the activation date; conversely, if the publication date is specified but activation date isn't, then activation will be set to this much time after publication.

If the key is being set to be an explicit successor to another key, then the default prepublication interval is 30 days; otherwise it is zero.

As with date offsets, if the argument is followed by one of the suffixes 'y', 'mo', 'w', 'd', 'h', or 'mi', then the interval is measured in years, months, weeks, days, hours, or minutes, respectively. Without a suffix, the interval is measured in seconds.

PRINTING OPTIONS

dnssec-settime can also be used to print the timing metadata associated with a key.

-u

Print times in UNIX epoch format.

-p C/P/Psync/A/R/I/D/Dsync/all

Print a specific metadata value or set of metadata values. The -p option may be followed by one or more of the following letters or strings to indicate which value or values to print: C for the creation date, P for the publication date, Psync for the CDS and CDNSKEY publication date, A for the activation date, R for the revocation date, I for the inactivation date, D for the deletion date, and Dsync for the CDS and CDNSKEY deletion date To print all of the metadata, use -p all.

SEE ALSO

dnssec-keygen(8) , dnssec-signzone(8) , BIND 9 Administrator Reference Manual, RFC 5011.

bind9-9.11.3+dfsg/bin/dnssec/dnssec-signzone.8000066400000000000000000000436771325250447100210060ustar00rootroot00000000000000.\" Copyright (C) 2000-2009, 2011-2017 Internet Systems Consortium, Inc. ("ISC") .\" .\" This Source Code Form is subject to the terms of the Mozilla Public .\" License, v. 2.0. If a copy of the MPL was not distributed with this .\" file, You can obtain one at http://mozilla.org/MPL/2.0/. .\" .hy 0 .ad l '\" t .\" Title: dnssec-signzone .\" Author: .\" Generator: DocBook XSL Stylesheets v1.78.1 .\" Date: 2014-02-18 .\" Manual: BIND9 .\" Source: ISC .\" Language: English .\" .TH "DNSSEC\-SIGNZONE" "8" "2014\-02\-18" "ISC" "BIND9" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" dnssec-signzone \- DNSSEC zone signing tool .SH "SYNOPSIS" .HP \w'\fBdnssec\-signzone\fR\ 'u \fBdnssec\-signzone\fR [\fB\-a\fR] [\fB\-c\ \fR\fB\fIclass\fR\fR] [\fB\-d\ \fR\fB\fIdirectory\fR\fR] [\fB\-D\fR] [\fB\-E\ \fR\fB\fIengine\fR\fR] [\fB\-e\ \fR\fB\fIend\-time\fR\fR] [\fB\-f\ \fR\fB\fIoutput\-file\fR\fR] [\fB\-g\fR] [\fB\-h\fR] [\fB\-i\ \fR\fB\fIinterval\fR\fR] [\fB\-I\ \fR\fB\fIinput\-format\fR\fR] [\fB\-j\ \fR\fB\fIjitter\fR\fR] [\fB\-K\ \fR\fB\fIdirectory\fR\fR] [\fB\-k\ \fR\fB\fIkey\fR\fR] [\fB\-L\ \fR\fB\fIserial\fR\fR] [\fB\-l\ \fR\fB\fIdomain\fR\fR] [\fB\-M\ \fR\fB\fImaxttl\fR\fR] [\fB\-N\ \fR\fB\fIsoa\-serial\-format\fR\fR] [\fB\-o\ \fR\fB\fIorigin\fR\fR] [\fB\-O\ \fR\fB\fIoutput\-format\fR\fR] [\fB\-P\fR] [\fB\-p\fR] [\fB\-Q\fR] [\fB\-R\fR] [\fB\-r\ \fR\fB\fIrandomdev\fR\fR] [\fB\-S\fR] [\fB\-s\ \fR\fB\fIstart\-time\fR\fR] [\fB\-T\ \fR\fB\fIttl\fR\fR] [\fB\-t\fR] [\fB\-u\fR] [\fB\-v\ \fR\fB\fIlevel\fR\fR] [\fB\-V\fR] [\fB\-X\ \fR\fB\fIextended\ end\-time\fR\fR] [\fB\-x\fR] [\fB\-z\fR] [\fB\-3\ \fR\fB\fIsalt\fR\fR] [\fB\-H\ \fR\fB\fIiterations\fR\fR] [\fB\-A\fR] {zonefile} [key...] .SH "DESCRIPTION" .PP \fBdnssec\-signzone\fR signs a zone\&. It generates NSEC and RRSIG records and produces a signed version of the zone\&. The security status of delegations from the signed zone (that is, whether the child zones are secure or not) is determined by the presence or absence of a keyset file for each child zone\&. .SH "OPTIONS" .PP \-a .RS 4 Verify all generated signatures\&. .RE .PP \-c \fIclass\fR .RS 4 Specifies the DNS class of the zone\&. .RE .PP \-C .RS 4 Compatibility mode: Generate a keyset\-\fIzonename\fR file in addition to dsset\-\fIzonename\fR when signing a zone, for use by older versions of \fBdnssec\-signzone\fR\&. .RE .PP \-d \fIdirectory\fR .RS 4 Look for dsset\- or keyset\- files in \fBdirectory\fR\&. .RE .PP \-D .RS 4 Output only those record types automatically managed by \fBdnssec\-signzone\fR, i\&.e\&. RRSIG, NSEC, NSEC3 and NSEC3PARAM records\&. If smart signing (\fB\-S\fR) is used, DNSKEY records are also included\&. The resulting file can be included in the original zone file with \fB$INCLUDE\fR\&. This option cannot be combined with \fB\-O raw\fR, \fB\-O map\fR, or serial number updating\&. .RE .PP \-E \fIengine\fR .RS 4 When applicable, specifies the hardware to use for cryptographic operations, such as a secure key store used for signing\&. .sp When BIND is built with OpenSSL PKCS#11 support, this defaults to the string "pkcs11", which identifies an OpenSSL engine that can drive a cryptographic accelerator or hardware service module\&. When BIND is built with native PKCS#11 cryptography (\-\-enable\-native\-pkcs11), it defaults to the path of the PKCS#11 provider library specified via "\-\-with\-pkcs11"\&. .RE .PP \-g .RS 4 Generate DS records for child zones from dsset\- or keyset\- file\&. Existing DS records will be removed\&. .RE .PP \-K \fIdirectory\fR .RS 4 Key repository: Specify a directory to search for DNSSEC keys\&. If not specified, defaults to the current directory\&. .RE .PP \-k \fIkey\fR .RS 4 Treat specified key as a key signing key ignoring any key flags\&. This option may be specified multiple times\&. .RE .PP \-l \fIdomain\fR .RS 4 Generate a DLV set in addition to the key (DNSKEY) and DS sets\&. The domain is appended to the name of the records\&. .RE .PP \-M \fImaxttl\fR .RS 4 Sets the maximum TTL for the signed zone\&. Any TTL higher than \fImaxttl\fR in the input zone will be reduced to \fImaxttl\fR in the output\&. This provides certainty as to the largest possible TTL in the signed zone, which is useful to know when rolling keys because it is the longest possible time before signatures that have been retrieved by resolvers will expire from resolver caches\&. Zones that are signed with this option should be configured to use a matching \fBmax\-zone\-ttl\fR in named\&.conf\&. (Note: This option is incompatible with \fB\-D\fR, because it modifies non\-DNSSEC data in the output zone\&.) .RE .PP \-s \fIstart\-time\fR .RS 4 Specify the date and time when the generated RRSIG records become valid\&. This can be either an absolute or relative time\&. An absolute start time is indicated by a number in YYYYMMDDHHMMSS notation; 20000530144500 denotes 14:45:00 UTC on May 30th, 2000\&. A relative start time is indicated by +N, which is N seconds from the current time\&. If no \fBstart\-time\fR is specified, the current time minus 1 hour (to allow for clock skew) is used\&. .RE .PP \-e \fIend\-time\fR .RS 4 Specify the date and time when the generated RRSIG records expire\&. As with \fBstart\-time\fR, an absolute time is indicated in YYYYMMDDHHMMSS notation\&. A time relative to the start time is indicated with +N, which is N seconds from the start time\&. A time relative to the current time is indicated with now+N\&. If no \fBend\-time\fR is specified, 30 days from the start time is used as a default\&. \fBend\-time\fR must be later than \fBstart\-time\fR\&. .RE .PP \-X \fIextended end\-time\fR .RS 4 Specify the date and time when the generated RRSIG records for the DNSKEY RRset will expire\&. This is to be used in cases when the DNSKEY signatures need to persist longer than signatures on other records; e\&.g\&., when the private component of the KSK is kept offline and the KSK signature is to be refreshed manually\&. .sp As with \fBstart\-time\fR, an absolute time is indicated in YYYYMMDDHHMMSS notation\&. A time relative to the start time is indicated with +N, which is N seconds from the start time\&. A time relative to the current time is indicated with now+N\&. If no \fBextended end\-time\fR is specified, the value of \fBend\-time\fR is used as the default\&. (\fBend\-time\fR, in turn, defaults to 30 days from the start time\&.) \fBextended end\-time\fR must be later than \fBstart\-time\fR\&. .RE .PP \-f \fIoutput\-file\fR .RS 4 The name of the output file containing the signed zone\&. The default is to append \&.signed to the input filename\&. If \fBoutput\-file\fR is set to "\-", then the signed zone is written to the standard output, with a default output format of "full"\&. .RE .PP \-h .RS 4 Prints a short summary of the options and arguments to \fBdnssec\-signzone\fR\&. .RE .PP \-V .RS 4 Prints version information\&. .RE .PP \-i \fIinterval\fR .RS 4 When a previously\-signed zone is passed as input, records may be resigned\&. The \fBinterval\fR option specifies the cycle interval as an offset from the current time (in seconds)\&. If a RRSIG record expires after the cycle interval, it is retained\&. Otherwise, it is considered to be expiring soon, and it will be replaced\&. .sp The default cycle interval is one quarter of the difference between the signature end and start times\&. So if neither \fBend\-time\fR or \fBstart\-time\fR are specified, \fBdnssec\-signzone\fR generates signatures that are valid for 30 days, with a cycle interval of 7\&.5 days\&. Therefore, if any existing RRSIG records are due to expire in less than 7\&.5 days, they would be replaced\&. .RE .PP \-I \fIinput\-format\fR .RS 4 The format of the input zone file\&. Possible formats are \fB"text"\fR (default), \fB"raw"\fR, and \fB"map"\fR\&. This option is primarily intended to be used for dynamic signed zones so that the dumped zone file in a non\-text format containing updates can be signed directly\&. The use of this option does not make much sense for non\-dynamic zones\&. .RE .PP \-j \fIjitter\fR .RS 4 When signing a zone with a fixed signature lifetime, all RRSIG records issued at the time of signing expires simultaneously\&. If the zone is incrementally signed, i\&.e\&. a previously\-signed zone is passed as input to the signer, all expired signatures have to be regenerated at about the same time\&. The \fBjitter\fR option specifies a jitter window that will be used to randomize the signature expire time, thus spreading incremental signature regeneration over time\&. .sp Signature lifetime jitter also to some extent benefits validators and servers by spreading out cache expiration, i\&.e\&. if large numbers of RRSIGs don\*(Aqt expire at the same time from all caches there will be less congestion than if all validators need to refetch at mostly the same time\&. .RE .PP \-L \fIserial\fR .RS 4 When writing a signed zone to "raw" or "map" format, set the "source serial" value in the header to the specified serial number\&. (This is expected to be used primarily for testing purposes\&.) .RE .PP \-n \fIncpus\fR .RS 4 Specifies the number of threads to use\&. By default, one thread is started for each detected CPU\&. .RE .PP \-N \fIsoa\-serial\-format\fR .RS 4 The SOA serial number format of the signed zone\&. Possible formats are \fB"keep"\fR (default), \fB"increment"\fR, \fB"unixtime"\fR, and \fB"date"\fR\&. .PP \fB"keep"\fR .RS 4 Do not modify the SOA serial number\&. .RE .PP \fB"increment"\fR .RS 4 Increment the SOA serial number using RFC 1982 arithmetics\&. .RE .PP \fB"unixtime"\fR .RS 4 Set the SOA serial number to the number of seconds since epoch\&. .RE .PP \fB"date"\fR .RS 4 Set the SOA serial number to today\*(Aqs date in YYYYMMDDNN format\&. .RE .RE .PP \-o \fIorigin\fR .RS 4 The zone origin\&. If not specified, the name of the zone file is assumed to be the origin\&. .RE .PP \-O \fIoutput\-format\fR .RS 4 The format of the output file containing the signed zone\&. Possible formats are \fB"text"\fR (default), which is the standard textual representation of the zone; \fB"full"\fR, which is text output in a format suitable for processing by external scripts; and \fB"map"\fR, \fB"raw"\fR, and \fB"raw=N"\fR, which store the zone in binary formats for rapid loading by \fBnamed\fR\&. \fB"raw=N"\fR specifies the format version of the raw zone file: if N is 0, the raw file can be read by any version of \fBnamed\fR; if N is 1, the file can be read by release 9\&.9\&.0 or higher; the default is 1\&. .RE .PP \-p .RS 4 Use pseudo\-random data when signing the zone\&. This is faster, but less secure, than using real random data\&. This option may be useful when signing large zones or when the entropy source is limited\&. .RE .PP \-P .RS 4 Disable post sign verification tests\&. .sp The post sign verification test ensures that for each algorithm in use there is at least one non revoked self signed KSK key, that all revoked KSK keys are self signed, and that all records in the zone are signed by the algorithm\&. This option skips these tests\&. .RE .PP \-Q .RS 4 Remove signatures from keys that are no longer active\&. .sp Normally, when a previously\-signed zone is passed as input to the signer, and a DNSKEY record has been removed and replaced with a new one, signatures from the old key that are still within their validity period are retained\&. This allows the zone to continue to validate with cached copies of the old DNSKEY RRset\&. The \fB\-Q\fR forces \fBdnssec\-signzone\fR to remove signatures from keys that are no longer active\&. This enables ZSK rollover using the procedure described in RFC 4641, section 4\&.2\&.1\&.1 ("Pre\-Publish Key Rollover")\&. .RE .PP \-R .RS 4 Remove signatures from keys that are no longer published\&. .sp This option is similar to \fB\-Q\fR, except it forces \fBdnssec\-signzone\fR to signatures from keys that are no longer published\&. This enables ZSK rollover using the procedure described in RFC 4641, section 4\&.2\&.1\&.2 ("Double Signature Zone Signing Key Rollover")\&. .RE .PP \-r \fIrandomdev\fR .RS 4 Specifies the source of randomness\&. If the operating system does not provide a /dev/random or equivalent device, the default source of randomness is keyboard input\&. randomdev specifies the name of a character device or file containing random data to be used instead of the default\&. The special value keyboard indicates that keyboard input should be used\&. .RE .PP \-S .RS 4 Smart signing: Instructs \fBdnssec\-signzone\fR to search the key repository for keys that match the zone being signed, and to include them in the zone if appropriate\&. .sp When a key is found, its timing metadata is examined to determine how it should be used, according to the following rules\&. Each successive rule takes priority over the prior ones: .PP .RS 4 If no timing metadata has been set for the key, the key is published in the zone and used to sign the zone\&. .RE .PP .RS 4 If the key\*(Aqs publication date is set and is in the past, the key is published in the zone\&. .RE .PP .RS 4 If the key\*(Aqs activation date is set and in the past, the key is published (regardless of publication date) and used to sign the zone\&. .RE .PP .RS 4 If the key\*(Aqs revocation date is set and in the past, and the key is published, then the key is revoked, and the revoked key is used to sign the zone\&. .RE .PP .RS 4 If either of the key\*(Aqs unpublication or deletion dates are set and in the past, the key is NOT published or used to sign the zone, regardless of any other metadata\&. .RE .RE .PP \-T \fIttl\fR .RS 4 Specifies a TTL to be used for new DNSKEY records imported into the zone from the key repository\&. If not specified, the default is the TTL value from the zone\*(Aqs SOA record\&. This option is ignored when signing without \fB\-S\fR, since DNSKEY records are not imported from the key repository in that case\&. It is also ignored if there are any pre\-existing DNSKEY records at the zone apex, in which case new records\*(Aq TTL values will be set to match them, or if any of the imported DNSKEY records had a default TTL value\&. In the event of a a conflict between TTL values in imported keys, the shortest one is used\&. .RE .PP \-t .RS 4 Print statistics at completion\&. .RE .PP \-u .RS 4 Update NSEC/NSEC3 chain when re\-signing a previously signed zone\&. With this option, a zone signed with NSEC can be switched to NSEC3, or a zone signed with NSEC3 can be switch to NSEC or to NSEC3 with different parameters\&. Without this option, \fBdnssec\-signzone\fR will retain the existing chain when re\-signing\&. .RE .PP \-v \fIlevel\fR .RS 4 Sets the debugging level\&. .RE .PP \-x .RS 4 Only sign the DNSKEY RRset with key\-signing keys, and omit signatures from zone\-signing keys\&. (This is similar to the \fBdnssec\-dnskey\-kskonly yes;\fR zone option in \fBnamed\fR\&.) .RE .PP \-z .RS 4 Ignore KSK flag on key when determining what to sign\&. This causes KSK\-flagged keys to sign all records, not just the DNSKEY RRset\&. (This is similar to the \fBupdate\-check\-ksk no;\fR zone option in \fBnamed\fR\&.) .RE .PP \-3 \fIsalt\fR .RS 4 Generate an NSEC3 chain with the given hex encoded salt\&. A dash (\fIsalt\fR) can be used to indicate that no salt is to be used when generating the NSEC3 chain\&. .RE .PP \-H \fIiterations\fR .RS 4 When generating an NSEC3 chain, use this many iterations\&. The default is 10\&. .RE .PP \-A .RS 4 When generating an NSEC3 chain set the OPTOUT flag on all NSEC3 records and do not generate NSEC3 records for insecure delegations\&. .sp Using this option twice (i\&.e\&., \fB\-AA\fR) turns the OPTOUT flag off for all records\&. This is useful when using the \fB\-u\fR option to modify an NSEC3 chain which previously had OPTOUT set\&. .RE .PP zonefile .RS 4 The file containing the zone to be signed\&. .RE .PP key .RS 4 Specify which keys should be used to sign the zone\&. If no keys are specified, then the zone will be examined for DNSKEY records at the zone apex\&. If these are found and there are matching private keys, in the current directory, then these will be used for signing\&. .RE .SH "EXAMPLE" .PP The following command signs the \fBexample\&.com\fR zone with the DSA key generated by \fBdnssec\-keygen\fR (Kexample\&.com\&.+003+17247)\&. Because the \fB\-S\fR option is not being used, the zone\*(Aqs keys must be in the master file (db\&.example\&.com)\&. This invocation looks for dsset files, in the current directory, so that DS records can be imported from them (\fB\-g\fR)\&. .sp .if n \{\ .RS 4 .\} .nf % dnssec\-signzone \-g \-o example\&.com db\&.example\&.com \e Kexample\&.com\&.+003+17247 db\&.example\&.com\&.signed % .fi .if n \{\ .RE .\} .PP In the above example, \fBdnssec\-signzone\fR creates the file db\&.example\&.com\&.signed\&. This file should be referenced in a zone statement in a named\&.conf file\&. .PP This example re\-signs a previously signed zone with default parameters\&. The private keys are assumed to be in the current directory\&. .sp .if n \{\ .RS 4 .\} .nf % cp db\&.example\&.com\&.signed db\&.example\&.com % dnssec\-signzone \-o example\&.com db\&.example\&.com db\&.example\&.com\&.signed % .fi .if n \{\ .RE .\} .SH "SEE ALSO" .PP \fBdnssec-keygen\fR(8), BIND 9 Administrator Reference Manual, RFC 4033, RFC 4641\&. .SH "AUTHOR" .PP \fBInternet Systems Consortium, Inc\&.\fR .SH "COPYRIGHT" .br Copyright \(co 2000-2009, 2011-2017 Internet Systems Consortium, Inc. ("ISC") .br bind9-9.11.3+dfsg/bin/dnssec/dnssec-signzone.c000066400000000000000000003266731325250447100210610ustar00rootroot00000000000000/* * Portions Copyright (C) 1999-2017 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * Portions Copyright (C) 1995-2000 by Network Associates, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /*! \file */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef PKCS11CRYPTO #include #endif #include "dnssectool.h" #ifndef PATH_MAX #define PATH_MAX 1024 /* AIX, WIN32, and others don't define this. */ #endif const char *program = "dnssec-signzone"; int verbose; typedef struct hashlist hashlist_t; static int nsec_datatype = dns_rdatatype_nsec; #define IS_NSEC3 (nsec_datatype == dns_rdatatype_nsec3) #define OPTOUT(x) (((x) & DNS_NSEC3FLAG_OPTOUT) != 0) #define REVOKE(x) ((dst_key_flags(x) & DNS_KEYFLAG_REVOKE) != 0) #define BUFSIZE 2048 #define MAXDSKEYS 8 #define SIGNER_EVENTCLASS ISC_EVENTCLASS(0x4453) #define SIGNER_EVENT_WRITE (SIGNER_EVENTCLASS + 0) #define SIGNER_EVENT_WORK (SIGNER_EVENTCLASS + 1) #define SOA_SERIAL_KEEP 0 #define SOA_SERIAL_INCREMENT 1 #define SOA_SERIAL_UNIXTIME 2 #define SOA_SERIAL_DATE 3 typedef struct signer_event sevent_t; struct signer_event { ISC_EVENT_COMMON(sevent_t); dns_fixedname_t *fname; dns_dbnode_t *node; }; static dns_dnsseckeylist_t keylist; static unsigned int keycount = 0; isc_rwlock_t keylist_lock; static isc_stdtime_t starttime = 0, endtime = 0, dnskey_endtime = 0, now; static int cycle = -1; static int jitter = 0; static isc_boolean_t tryverify = ISC_FALSE; static isc_boolean_t printstats = ISC_FALSE; static isc_mem_t *mctx = NULL; static isc_entropy_t *ectx = NULL; static dns_ttl_t zone_soa_min_ttl; static dns_ttl_t soa_ttl; static FILE *outfp = NULL; static char *tempfile = NULL; static const dns_master_style_t *masterstyle; static dns_masterformat_t inputformat = dns_masterformat_text; static dns_masterformat_t outputformat = dns_masterformat_text; static isc_uint32_t rawversion = 1, serialnum = 0; static isc_boolean_t snset = ISC_FALSE; static unsigned int nsigned = 0, nretained = 0, ndropped = 0; static unsigned int nverified = 0, nverifyfailed = 0; static const char *directory = NULL, *dsdir = NULL; static isc_mutex_t namelock, statslock; static isc_taskmgr_t *taskmgr = NULL; static dns_db_t *gdb; /* The database */ static dns_dbversion_t *gversion; /* The database version */ static dns_dbiterator_t *gdbiter; /* The database iterator */ static dns_rdataclass_t gclass; /* The class */ static dns_name_t *gorigin; /* The database origin */ static int nsec3flags = 0; static dns_iterations_t nsec3iter = 10U; static unsigned char saltbuf[255]; static unsigned char *gsalt = saltbuf; static size_t salt_length = 0; static isc_task_t *master = NULL; static unsigned int ntasks = 0; static isc_boolean_t shuttingdown = ISC_FALSE, finished = ISC_FALSE; static isc_boolean_t nokeys = ISC_FALSE; static isc_boolean_t removefile = ISC_FALSE; static isc_boolean_t generateds = ISC_FALSE; static isc_boolean_t ignore_kskflag = ISC_FALSE; static isc_boolean_t keyset_kskonly = ISC_FALSE; static dns_name_t *dlv = NULL; static dns_fixedname_t dlv_fixed; static dns_master_style_t *dsstyle = NULL; static unsigned int serialformat = SOA_SERIAL_KEEP; static unsigned int hash_length = 0; static isc_boolean_t unknownalg = ISC_FALSE; static isc_boolean_t disable_zone_check = ISC_FALSE; static isc_boolean_t update_chain = ISC_FALSE; static isc_boolean_t set_keyttl = ISC_FALSE; static dns_ttl_t keyttl; static isc_boolean_t smartsign = ISC_FALSE; static isc_boolean_t remove_orphansigs = ISC_FALSE; static isc_boolean_t remove_inactkeysigs = ISC_FALSE; static isc_boolean_t output_dnssec_only = ISC_FALSE; static isc_boolean_t output_stdout = ISC_FALSE; isc_boolean_t set_maxttl = ISC_FALSE; static dns_ttl_t maxttl = 0; #define INCSTAT(counter) \ if (printstats) { \ LOCK(&statslock); \ counter++; \ UNLOCK(&statslock); \ } static void sign(isc_task_t *task, isc_event_t *event); static void dumpnode(dns_name_t *name, dns_dbnode_t *node) { dns_rdataset_t rds; dns_rdatasetiter_t *iter = NULL; isc_buffer_t *buffer = NULL; isc_region_t r; isc_result_t result; unsigned bufsize = 4096; if (outputformat != dns_masterformat_text) return; if (!output_dnssec_only) { result = dns_master_dumpnodetostream(mctx, gdb, gversion, node, name, masterstyle, outfp); check_result(result, "dns_master_dumpnodetostream"); return; } result = dns_db_allrdatasets(gdb, node, gversion, 0, &iter); check_result(result, "dns_db_allrdatasets"); dns_rdataset_init(&rds); result = isc_buffer_allocate(mctx, &buffer, bufsize); check_result(result, "isc_buffer_allocate"); for (result = dns_rdatasetiter_first(iter); result == ISC_R_SUCCESS; result = dns_rdatasetiter_next(iter)) { dns_rdatasetiter_current(iter, &rds); if (rds.type != dns_rdatatype_rrsig && rds.type != dns_rdatatype_nsec && rds.type != dns_rdatatype_nsec3 && rds.type != dns_rdatatype_nsec3param && (!smartsign || rds.type != dns_rdatatype_dnskey)) { dns_rdataset_disassociate(&rds); continue; } for (;;) { result = dns_master_rdatasettotext(name, &rds, masterstyle, buffer); if (result != ISC_R_NOSPACE) break; bufsize <<= 1; isc_buffer_free(&buffer); result = isc_buffer_allocate(mctx, &buffer, bufsize); check_result(result, "isc_buffer_allocate"); } check_result(result, "dns_master_rdatasettotext"); isc_buffer_usedregion(buffer, &r); result = isc_stdio_write(r.base, 1, r.length, outfp, NULL); check_result(result, "isc_stdio_write"); isc_buffer_clear(buffer); dns_rdataset_disassociate(&rds); } isc_buffer_free(&buffer); dns_rdatasetiter_destroy(&iter); } /*% * Sign the given RRset with given key, and add the signature record to the * given tuple. */ static void signwithkey(dns_name_t *name, dns_rdataset_t *rdataset, dst_key_t *key, dns_ttl_t ttl, dns_diff_t *add, const char *logmsg) { isc_result_t result; isc_stdtime_t jendtime, expiry; char keystr[DST_KEY_FORMATSIZE]; dns_rdata_t trdata = DNS_RDATA_INIT; unsigned char array[BUFSIZE]; isc_buffer_t b; dns_difftuple_t *tuple; dst_key_format(key, keystr, sizeof(keystr)); vbprintf(1, "\t%s %s\n", logmsg, keystr); if (rdataset->type == dns_rdatatype_dnskey) expiry = dnskey_endtime; else expiry = endtime; jendtime = (jitter != 0) ? isc_random_jitter(expiry, jitter) : expiry; isc_buffer_init(&b, array, sizeof(array)); result = dns_dnssec_sign(name, rdataset, key, &starttime, &jendtime, mctx, &b, &trdata); isc_entropy_stopcallbacksources(ectx); if (result != ISC_R_SUCCESS) { fatal("dnskey '%s' failed to sign data: %s", keystr, isc_result_totext(result)); } INCSTAT(nsigned); if (tryverify) { result = dns_dnssec_verify(name, rdataset, key, ISC_TRUE, mctx, &trdata); if (result == ISC_R_SUCCESS) { vbprintf(3, "\tsignature verified\n"); INCSTAT(nverified); } else { vbprintf(3, "\tsignature failed to verify\n"); INCSTAT(nverifyfailed); } } tuple = NULL; result = dns_difftuple_create(mctx, DNS_DIFFOP_ADDRESIGN, name, ttl, &trdata, &tuple); check_result(result, "dns_difftuple_create"); dns_diff_append(add, &tuple); } static inline isc_boolean_t issigningkey(dns_dnsseckey_t *key) { return (key->force_sign || key->hint_sign); } static inline isc_boolean_t ispublishedkey(dns_dnsseckey_t *key) { return ((key->force_publish || key->hint_publish) && !key->hint_remove); } static inline isc_boolean_t iszonekey(dns_dnsseckey_t *key) { return (ISC_TF(dns_name_equal(dst_key_name(key->key), gorigin) && dst_key_iszonekey(key->key))); } static inline isc_boolean_t isksk(dns_dnsseckey_t *key) { return (key->ksk); } static inline isc_boolean_t iszsk(dns_dnsseckey_t *key) { return (ignore_kskflag || !key->ksk); } /*% * Find the key that generated an RRSIG, if it is in the key list. If * so, return a pointer to it, otherwise return NULL. * * No locking is performed here, this must be done by the caller. */ static dns_dnsseckey_t * keythatsigned_unlocked(dns_rdata_rrsig_t *rrsig) { dns_dnsseckey_t *key; for (key = ISC_LIST_HEAD(keylist); key != NULL; key = ISC_LIST_NEXT(key, link)) { if (rrsig->keyid == dst_key_id(key->key) && rrsig->algorithm == dst_key_alg(key->key) && dns_name_equal(&rrsig->signer, dst_key_name(key->key))) return (key); } return (NULL); } /*% * Finds the key that generated a RRSIG, if possible. First look at the keys * that we've loaded already, and then see if there's a key on disk. */ static dns_dnsseckey_t * keythatsigned(dns_rdata_rrsig_t *rrsig) { isc_result_t result; dst_key_t *pubkey = NULL, *privkey = NULL; dns_dnsseckey_t *key = NULL; isc_rwlock_lock(&keylist_lock, isc_rwlocktype_read); key = keythatsigned_unlocked(rrsig); isc_rwlock_unlock(&keylist_lock, isc_rwlocktype_read); if (key != NULL) return (key); /* * We did not find the key in our list. Get a write lock now, since * we may be modifying the bits. We could do the tryupgrade() dance, * but instead just get a write lock and check once again to see if * it is on our list. It's possible someone else may have added it * after all. */ isc_rwlock_lock(&keylist_lock, isc_rwlocktype_write); key = keythatsigned_unlocked(rrsig); if (key != NULL) { isc_rwlock_unlock(&keylist_lock, isc_rwlocktype_write); return (key); } result = dst_key_fromfile(&rrsig->signer, rrsig->keyid, rrsig->algorithm, DST_TYPE_PUBLIC, directory, mctx, &pubkey); if (result != ISC_R_SUCCESS) { isc_rwlock_unlock(&keylist_lock, isc_rwlocktype_write); return (NULL); } result = dst_key_fromfile(&rrsig->signer, rrsig->keyid, rrsig->algorithm, DST_TYPE_PUBLIC | DST_TYPE_PRIVATE, directory, mctx, &privkey); if (result == ISC_R_SUCCESS) { dst_key_free(&pubkey); result = dns_dnsseckey_create(mctx, &privkey, &key); } else result = dns_dnsseckey_create(mctx, &pubkey, &key); if (result == ISC_R_SUCCESS) { key->force_publish = ISC_FALSE; key->force_sign = ISC_FALSE; key->index = keycount++; ISC_LIST_APPEND(keylist, key, link); } isc_rwlock_unlock(&keylist_lock, isc_rwlocktype_write); return (key); } /*% * Check to see if we expect to find a key at this name. If we see a RRSIG * and can't find the signing key that we expect to find, we drop the rrsig. * I'm not sure if this is completely correct, but it seems to work. */ static isc_boolean_t expecttofindkey(dns_name_t *name) { unsigned int options = DNS_DBFIND_NOWILD; dns_fixedname_t fname; isc_result_t result; char namestr[DNS_NAME_FORMATSIZE]; dns_fixedname_init(&fname); result = dns_db_find(gdb, name, gversion, dns_rdatatype_dnskey, options, 0, NULL, dns_fixedname_name(&fname), NULL, NULL); switch (result) { case ISC_R_SUCCESS: case DNS_R_NXDOMAIN: case DNS_R_NXRRSET: return (ISC_TRUE); case DNS_R_DELEGATION: case DNS_R_CNAME: case DNS_R_DNAME: return (ISC_FALSE); } dns_name_format(name, namestr, sizeof(namestr)); fatal("failure looking for '%s DNSKEY' in database: %s", namestr, isc_result_totext(result)); /* NOTREACHED */ return (ISC_FALSE); /* removes a warning */ } static inline isc_boolean_t setverifies(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key, dns_rdata_t *rrsig) { isc_result_t result; result = dns_dnssec_verify(name, set, key, ISC_FALSE, mctx, rrsig); if (result == ISC_R_SUCCESS) { INCSTAT(nverified); return (ISC_TRUE); } else { INCSTAT(nverifyfailed); return (ISC_FALSE); } } /*% * Signs a set. Goes through contortions to decide if each RRSIG should * be dropped or retained, and then determines if any new SIGs need to * be generated. */ static void signset(dns_diff_t *del, dns_diff_t *add, dns_dbnode_t *node, dns_name_t *name, dns_rdataset_t *set) { dns_rdataset_t sigset; dns_rdata_t sigrdata = DNS_RDATA_INIT; dns_rdata_rrsig_t rrsig; dns_dnsseckey_t *key; isc_result_t result; isc_boolean_t nosigs = ISC_FALSE; isc_boolean_t *wassignedby, *nowsignedby; int arraysize; dns_difftuple_t *tuple; dns_ttl_t ttl; int i; char namestr[DNS_NAME_FORMATSIZE]; char typestr[TYPE_FORMATSIZE]; char sigstr[SIG_FORMATSIZE]; dns_name_format(name, namestr, sizeof(namestr)); type_format(set->type, typestr, sizeof(typestr)); ttl = ISC_MIN(set->ttl, endtime - starttime); dns_rdataset_init(&sigset); result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_rrsig, set->type, 0, &sigset, NULL); if (result == ISC_R_NOTFOUND) { vbprintf(2, "no existing signatures for %s/%s\n", namestr, typestr); result = ISC_R_SUCCESS; nosigs = ISC_TRUE; } if (result != ISC_R_SUCCESS) fatal("failed while looking for '%s RRSIG %s': %s", namestr, typestr, isc_result_totext(result)); vbprintf(1, "%s/%s:\n", namestr, typestr); arraysize = keycount; if (!nosigs) arraysize += dns_rdataset_count(&sigset); wassignedby = isc_mem_get(mctx, arraysize * sizeof(isc_boolean_t)); nowsignedby = isc_mem_get(mctx, arraysize * sizeof(isc_boolean_t)); if (wassignedby == NULL || nowsignedby == NULL) fatal("out of memory"); for (i = 0; i < arraysize; i++) wassignedby[i] = nowsignedby[i] = ISC_FALSE; if (nosigs) result = ISC_R_NOMORE; else result = dns_rdataset_first(&sigset); while (result == ISC_R_SUCCESS) { isc_boolean_t expired, future; isc_boolean_t keep = ISC_FALSE, resign = ISC_FALSE; dns_rdataset_current(&sigset, &sigrdata); result = dns_rdata_tostruct(&sigrdata, &rrsig, NULL); check_result(result, "dns_rdata_tostruct"); future = isc_serial_lt(now, rrsig.timesigned); key = keythatsigned(&rrsig); sig_format(&rrsig, sigstr, sizeof(sigstr)); if (key != NULL && issigningkey(key)) expired = isc_serial_gt(now + cycle, rrsig.timeexpire); else expired = isc_serial_gt(now, rrsig.timeexpire); if (isc_serial_gt(rrsig.timesigned, rrsig.timeexpire)) { /* rrsig is dropped and not replaced */ vbprintf(2, "\trrsig by %s dropped - " "invalid validity period\n", sigstr); } else if (key == NULL && !future && expecttofindkey(&rrsig.signer)) { /* rrsig is dropped and not replaced */ vbprintf(2, "\trrsig by %s dropped - " "private dnskey not found\n", sigstr); } else if (key == NULL || future) { keep = (!expired && !remove_orphansigs); vbprintf(2, "\trrsig by %s %s - dnskey not found\n", keep ? "retained" : "dropped", sigstr); } else if (!dns_dnssec_keyactive(key->key, now) && remove_inactkeysigs) { keep = ISC_FALSE; vbprintf(2, "\trrsig by %s dropped - key inactive\n", sigstr); } else if (issigningkey(key)) { wassignedby[key->index] = ISC_TRUE; if (!expired && rrsig.originalttl == set->ttl && setverifies(name, set, key->key, &sigrdata)) { vbprintf(2, "\trrsig by %s retained\n", sigstr); keep = ISC_TRUE; } else { vbprintf(2, "\trrsig by %s dropped - %s\n", sigstr, expired ? "expired" : rrsig.originalttl != set->ttl ? "ttl change" : "failed to verify"); resign = ISC_TRUE; } } else if (!ispublishedkey(key) && remove_orphansigs) { vbprintf(2, "\trrsig by %s dropped - dnskey removed\n", sigstr); } else if (iszonekey(key)) { wassignedby[key->index] = ISC_TRUE; if (!expired && rrsig.originalttl == set->ttl && setverifies(name, set, key->key, &sigrdata)) { vbprintf(2, "\trrsig by %s retained\n", sigstr); keep = ISC_TRUE; } else { vbprintf(2, "\trrsig by %s dropped - %s\n", sigstr, expired ? "expired" : rrsig.originalttl != set->ttl ? "ttl change" : "failed to verify"); } } else if (!expired) { vbprintf(2, "\trrsig by %s retained\n", sigstr); keep = ISC_TRUE; } else { vbprintf(2, "\trrsig by %s expired\n", sigstr); } if (keep) { if (key != NULL) nowsignedby[key->index] = ISC_TRUE; INCSTAT(nretained); if (sigset.ttl != ttl) { vbprintf(2, "\tfixing ttl %s\n", sigstr); tuple = NULL; result = dns_difftuple_create(mctx, DNS_DIFFOP_DELRESIGN, name, sigset.ttl, &sigrdata, &tuple); check_result(result, "dns_difftuple_create"); dns_diff_append(del, &tuple); result = dns_difftuple_create(mctx, DNS_DIFFOP_ADDRESIGN, name, ttl, &sigrdata, &tuple); check_result(result, "dns_difftuple_create"); dns_diff_append(add, &tuple); } } else { tuple = NULL; vbprintf(2, "removing signature by %s\n", sigstr); result = dns_difftuple_create(mctx, DNS_DIFFOP_DELRESIGN, name, sigset.ttl, &sigrdata, &tuple); check_result(result, "dns_difftuple_create"); dns_diff_append(del, &tuple); INCSTAT(ndropped); } if (resign) { INSIST(!keep); signwithkey(name, set, key->key, ttl, add, "resigning with dnskey"); nowsignedby[key->index] = ISC_TRUE; } dns_rdata_reset(&sigrdata); dns_rdata_freestruct(&rrsig); result = dns_rdataset_next(&sigset); } if (result == ISC_R_NOMORE) result = ISC_R_SUCCESS; check_result(result, "dns_rdataset_first/next"); if (dns_rdataset_isassociated(&sigset)) dns_rdataset_disassociate(&sigset); for (key = ISC_LIST_HEAD(keylist); key != NULL; key = ISC_LIST_NEXT(key, link)) { if (nowsignedby[key->index]) continue; if (!issigningkey(key)) continue; if (set->type == dns_rdatatype_dnskey && dns_name_equal(name, gorigin)) { isc_boolean_t have_ksk; dns_dnsseckey_t *tmpkey; have_ksk = isksk(key); for (tmpkey = ISC_LIST_HEAD(keylist); tmpkey != NULL; tmpkey = ISC_LIST_NEXT(tmpkey, link)) { if (dst_key_alg(key->key) != dst_key_alg(tmpkey->key)) continue; if (REVOKE(tmpkey->key)) continue; if (isksk(tmpkey)) have_ksk = ISC_TRUE; } if (isksk(key) || !have_ksk || (iszsk(key) && !keyset_kskonly)) signwithkey(name, set, key->key, ttl, add, "signing with dnskey"); } else if (set->type == dns_rdatatype_cds || set->type == dns_rdatatype_cdnskey || iszsk(key)) { signwithkey(name, set, key->key, ttl, add, "signing with dnskey"); } } isc_mem_put(mctx, wassignedby, arraysize * sizeof(isc_boolean_t)); isc_mem_put(mctx, nowsignedby, arraysize * sizeof(isc_boolean_t)); } struct hashlist { unsigned char *hashbuf; size_t entries; size_t size; size_t length; }; static void hashlist_init(hashlist_t *l, unsigned int nodes, unsigned int length) { l->entries = 0; l->length = length + 1; if (nodes != 0) { l->size = nodes; l->hashbuf = malloc(l->size * l->length); if (l->hashbuf == NULL) l->size = 0; } else { l->size = 0; l->hashbuf = NULL; } } static void hashlist_free(hashlist_t *l) { if (l->hashbuf) { free(l->hashbuf); l->hashbuf = NULL; l->entries = 0; l->length = 0; l->size = 0; } } static void hashlist_add(hashlist_t *l, const unsigned char *hash, size_t len) { REQUIRE(len <= l->length); if (l->entries == l->size) { l->size = l->size * 2 + 100; l->hashbuf = realloc(l->hashbuf, l->size * l->length); if (l->hashbuf == NULL) fatal("unable to grow hashlist: out of memory"); } memset(l->hashbuf + l->entries * l->length, 0, l->length); memmove(l->hashbuf + l->entries * l->length, hash, len); l->entries++; } static void hashlist_add_dns_name(hashlist_t *l, /*const*/ dns_name_t *name, unsigned int hashalg, unsigned int iterations, const unsigned char *salt, size_t salt_len, isc_boolean_t speculative) { char nametext[DNS_NAME_FORMATSIZE]; unsigned char hash[NSEC3_MAX_HASH_LENGTH + 1]; unsigned int len; size_t i; len = isc_iterated_hash(hash, hashalg, iterations, salt, (int)salt_len, name->ndata, name->length); if (verbose) { dns_name_format(name, nametext, sizeof nametext); for (i = 0 ; i < len; i++) fprintf(stderr, "%02x", hash[i]); fprintf(stderr, " %s\n", nametext); } hash[len++] = speculative ? 1 : 0; hashlist_add(l, hash, len); } static int hashlist_comp(const void *a, const void *b) { return (isc_safe_memcompare(a, b, hash_length + 1)); } static void hashlist_sort(hashlist_t *l) { qsort(l->hashbuf, l->entries, l->length, hashlist_comp); } static isc_boolean_t hashlist_hasdup(hashlist_t *l) { unsigned char *current; unsigned char *next = l->hashbuf; size_t entries = l->entries; /* * Skip initial speculative wild card hashs. */ while (entries > 0U && next[l->length-1] != 0U) { next += l->length; entries--; } current = next; while (entries-- > 1U) { next += l->length; if (next[l->length-1] != 0) continue; if (isc_safe_memequal(current, next, l->length - 1)) return (ISC_TRUE); current = next; } return (ISC_FALSE); } static const unsigned char * hashlist_findnext(const hashlist_t *l, const unsigned char hash[NSEC3_MAX_HASH_LENGTH]) { size_t entries = l->entries; const unsigned char *next = bsearch(hash, l->hashbuf, l->entries, l->length, hashlist_comp); INSIST(next != NULL); do { if (next < l->hashbuf + (l->entries - 1) * l->length) next += l->length; else next = l->hashbuf; if (next[l->length - 1] == 0) break; } while (entries-- > 1U); INSIST(entries != 0U); return (next); } static isc_boolean_t hashlist_exists(const hashlist_t *l, const unsigned char hash[NSEC3_MAX_HASH_LENGTH]) { if (bsearch(hash, l->hashbuf, l->entries, l->length, hashlist_comp)) return (ISC_TRUE); else return (ISC_FALSE); } static void addnowildcardhash(hashlist_t *l, /*const*/ dns_name_t *name, unsigned int hashalg, unsigned int iterations, const unsigned char *salt, size_t salt_len) { dns_fixedname_t fixed; dns_name_t *wild; dns_dbnode_t *node = NULL; isc_result_t result; char namestr[DNS_NAME_FORMATSIZE]; dns_fixedname_init(&fixed); wild = dns_fixedname_name(&fixed); result = dns_name_concatenate(dns_wildcardname, name, wild, NULL); if (result == ISC_R_NOSPACE) return; check_result(result,"addnowildcardhash: dns_name_concatenate()"); result = dns_db_findnode(gdb, wild, ISC_FALSE, &node); if (result == ISC_R_SUCCESS) { dns_db_detachnode(gdb, &node); return; } if (verbose) { dns_name_format(wild, namestr, sizeof(namestr)); fprintf(stderr, "adding no-wildcardhash for %s\n", namestr); } hashlist_add_dns_name(l, wild, hashalg, iterations, salt, salt_len, ISC_TRUE); } static void opendb(const char *prefix, dns_name_t *name, dns_rdataclass_t rdclass, dns_db_t **dbp) { char filename[PATH_MAX]; isc_buffer_t b; isc_result_t result; isc_buffer_init(&b, filename, sizeof(filename)); if (dsdir != NULL) { /* allow room for a trailing slash */ if (strlen(dsdir) >= isc_buffer_availablelength(&b)) fatal("path '%s' is too long", dsdir); isc_buffer_putstr(&b, dsdir); if (dsdir[strlen(dsdir) - 1] != '/') isc_buffer_putstr(&b, "/"); } if (strlen(prefix) > isc_buffer_availablelength(&b)) fatal("path '%s' is too long", dsdir); isc_buffer_putstr(&b, prefix); result = dns_name_tofilenametext(name, ISC_FALSE, &b); check_result(result, "dns_name_tofilenametext()"); if (isc_buffer_availablelength(&b) == 0) { char namestr[DNS_NAME_FORMATSIZE]; dns_name_format(name, namestr, sizeof(namestr)); fatal("name '%s' is too long", namestr); } isc_buffer_putuint8(&b, 0); result = dns_db_create(mctx, "rbt", dns_rootname, dns_dbtype_zone, rdclass, 0, NULL, dbp); check_result(result, "dns_db_create()"); result = dns_db_load3(*dbp, filename, inputformat, DNS_MASTER_HINT); if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE) dns_db_detach(dbp); } /*% * Load the DS set for a child zone, if a dsset-* file can be found. * If not, try to find a keyset-* file from an earlier version of * dnssec-signzone, and build DS records from that. */ static isc_result_t loadds(dns_name_t *name, isc_uint32_t ttl, dns_rdataset_t *dsset) { dns_db_t *db = NULL; dns_dbversion_t *ver = NULL; dns_dbnode_t *node = NULL; isc_result_t result; dns_rdataset_t keyset; dns_rdata_t key, ds; unsigned char dsbuf[DNS_DS_BUFFERSIZE]; dns_diff_t diff; dns_difftuple_t *tuple = NULL; opendb("dsset-", name, gclass, &db); if (db != NULL) { result = dns_db_findnode(db, name, ISC_FALSE, &node); if (result == ISC_R_SUCCESS) { dns_rdataset_init(dsset); result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_ds, 0, 0, dsset, NULL); dns_db_detachnode(db, &node); if (result == ISC_R_SUCCESS) { vbprintf(2, "found DS records\n"); dsset->ttl = ttl; dns_db_detach(&db); return (result); } } dns_db_detach(&db); } /* No DS records found; try again, looking for DNSKEY records */ opendb("keyset-", name, gclass, &db); if (db == NULL) { return (ISC_R_NOTFOUND); } result = dns_db_findnode(db, name, ISC_FALSE, &node); if (result != ISC_R_SUCCESS) { dns_db_detach(&db); return (result); } dns_rdataset_init(&keyset); result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_dnskey, 0, 0, &keyset, NULL); if (result != ISC_R_SUCCESS) { dns_db_detachnode(db, &node); dns_db_detach(&db); return (result); } vbprintf(2, "found DNSKEY records\n"); result = dns_db_newversion(db, &ver); check_result(result, "dns_db_newversion"); dns_diff_init(mctx, &diff); for (result = dns_rdataset_first(&keyset); result == ISC_R_SUCCESS; result = dns_rdataset_next(&keyset)) { dns_rdata_init(&key); dns_rdata_init(&ds); dns_rdataset_current(&keyset, &key); result = dns_ds_buildrdata(name, &key, DNS_DSDIGEST_SHA1, dsbuf, &ds); check_result(result, "dns_ds_buildrdata"); result = dns_difftuple_create(mctx, DNS_DIFFOP_ADDRESIGN, name, ttl, &ds, &tuple); check_result(result, "dns_difftuple_create"); dns_diff_append(&diff, &tuple); dns_rdata_reset(&ds); result = dns_ds_buildrdata(name, &key, DNS_DSDIGEST_SHA256, dsbuf, &ds); check_result(result, "dns_ds_buildrdata"); result = dns_difftuple_create(mctx, DNS_DIFFOP_ADDRESIGN, name, ttl, &ds, &tuple); check_result(result, "dns_difftuple_create"); dns_diff_append(&diff, &tuple); } result = dns_diff_apply(&diff, db, ver); check_result(result, "dns_diff_apply"); dns_diff_clear(&diff); dns_db_closeversion(db, &ver, ISC_TRUE); result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_ds, 0, 0, dsset, NULL); check_result(result, "dns_db_findrdataset"); dns_rdataset_disassociate(&keyset); dns_db_detachnode(db, &node); dns_db_detach(&db); return (result); } static isc_boolean_t secure(dns_name_t *name, dns_dbnode_t *node) { dns_rdataset_t dsset; isc_result_t result; if (dns_name_equal(name, gorigin)) return (ISC_FALSE); dns_rdataset_init(&dsset); result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_ds, 0, 0, &dsset, NULL); if (dns_rdataset_isassociated(&dsset)) dns_rdataset_disassociate(&dsset); return (ISC_TF(result == ISC_R_SUCCESS)); } /*% * Signs all records at a name. */ static void signname(dns_dbnode_t *node, dns_name_t *name) { isc_result_t result; dns_rdataset_t rdataset; dns_rdatasetiter_t *rdsiter; isc_boolean_t isdelegation = ISC_FALSE; dns_diff_t del, add; char namestr[DNS_NAME_FORMATSIZE]; dns_rdataset_init(&rdataset); dns_name_format(name, namestr, sizeof(namestr)); /* * Determine if this is a delegation point. */ if (is_delegation(gdb, gversion, gorigin, name, node, NULL)) isdelegation = ISC_TRUE; /* * Now iterate through the rdatasets. */ dns_diff_init(mctx, &del); dns_diff_init(mctx, &add); rdsiter = NULL; result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter); check_result(result, "dns_db_allrdatasets()"); result = dns_rdatasetiter_first(rdsiter); while (result == ISC_R_SUCCESS) { dns_rdatasetiter_current(rdsiter, &rdataset); /* If this is a RRSIG set, skip it. */ if (rdataset.type == dns_rdatatype_rrsig) goto skip; /* * If this name is a delegation point, skip all records * except NSEC and DS sets. Otherwise check that there * isn't a DS record. */ if (isdelegation) { if (rdataset.type != nsec_datatype && rdataset.type != dns_rdatatype_ds) goto skip; } else if (rdataset.type == dns_rdatatype_ds) { char namebuf[DNS_NAME_FORMATSIZE]; dns_name_format(name, namebuf, sizeof(namebuf)); fatal("'%s': found DS RRset without NS RRset\n", namebuf); } signset(&del, &add, node, name, &rdataset); skip: dns_rdataset_disassociate(&rdataset); result = dns_rdatasetiter_next(rdsiter); } if (result != ISC_R_NOMORE) fatal("rdataset iteration for name '%s' failed: %s", namestr, isc_result_totext(result)); dns_rdatasetiter_destroy(&rdsiter); result = dns_diff_applysilently(&del, gdb, gversion); if (result != ISC_R_SUCCESS) fatal("failed to delete SIGs at node '%s': %s", namestr, isc_result_totext(result)); result = dns_diff_applysilently(&add, gdb, gversion); if (result != ISC_R_SUCCESS) fatal("failed to add SIGs at node '%s': %s", namestr, isc_result_totext(result)); dns_diff_clear(&del); dns_diff_clear(&add); } /* * See if the node contains any non RRSIG/NSEC records and report to * caller. Clean out extranous RRSIG records for node. */ static inline isc_boolean_t active_node(dns_dbnode_t *node) { dns_rdatasetiter_t *rdsiter = NULL; dns_rdatasetiter_t *rdsiter2 = NULL; isc_boolean_t active = ISC_FALSE; isc_result_t result; dns_rdataset_t rdataset; dns_rdatatype_t type; dns_rdatatype_t covers; isc_boolean_t found; dns_rdataset_init(&rdataset); result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter); check_result(result, "dns_db_allrdatasets()"); result = dns_rdatasetiter_first(rdsiter); while (result == ISC_R_SUCCESS) { dns_rdatasetiter_current(rdsiter, &rdataset); if (rdataset.type != dns_rdatatype_nsec && rdataset.type != dns_rdatatype_nsec3 && rdataset.type != dns_rdatatype_rrsig) active = ISC_TRUE; dns_rdataset_disassociate(&rdataset); if (!active) result = dns_rdatasetiter_next(rdsiter); else result = ISC_R_NOMORE; } if (result != ISC_R_NOMORE) fatal("rdataset iteration failed: %s", isc_result_totext(result)); if (!active && nsec_datatype == dns_rdatatype_nsec) { /*% * The node is empty of everything but NSEC / RRSIG records. */ for (result = dns_rdatasetiter_first(rdsiter); result == ISC_R_SUCCESS; result = dns_rdatasetiter_next(rdsiter)) { dns_rdatasetiter_current(rdsiter, &rdataset); result = dns_db_deleterdataset(gdb, node, gversion, rdataset.type, rdataset.covers); check_result(result, "dns_db_deleterdataset()"); dns_rdataset_disassociate(&rdataset); } if (result != ISC_R_NOMORE) fatal("rdataset iteration failed: %s", isc_result_totext(result)); } else { /* * Delete RRSIGs for types that no longer exist. */ result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter2); check_result(result, "dns_db_allrdatasets()"); for (result = dns_rdatasetiter_first(rdsiter); result == ISC_R_SUCCESS; result = dns_rdatasetiter_next(rdsiter)) { dns_rdatasetiter_current(rdsiter, &rdataset); type = rdataset.type; covers = rdataset.covers; dns_rdataset_disassociate(&rdataset); /* * Delete the NSEC chain if we are signing with * NSEC3. */ if (nsec_datatype == dns_rdatatype_nsec3 && (type == dns_rdatatype_nsec || covers == dns_rdatatype_nsec)) { result = dns_db_deleterdataset(gdb, node, gversion, type, covers); check_result(result, "dns_db_deleterdataset(nsec/rrsig)"); continue; } if (type != dns_rdatatype_rrsig) continue; found = ISC_FALSE; for (result = dns_rdatasetiter_first(rdsiter2); !found && result == ISC_R_SUCCESS; result = dns_rdatasetiter_next(rdsiter2)) { dns_rdatasetiter_current(rdsiter2, &rdataset); if (rdataset.type == covers) found = ISC_TRUE; dns_rdataset_disassociate(&rdataset); } if (!found) { if (result != ISC_R_NOMORE) fatal("rdataset iteration failed: %s", isc_result_totext(result)); result = dns_db_deleterdataset(gdb, node, gversion, type, covers); check_result(result, "dns_db_deleterdataset(rrsig)"); } else if (result != ISC_R_NOMORE && result != ISC_R_SUCCESS) fatal("rdataset iteration failed: %s", isc_result_totext(result)); } if (result != ISC_R_NOMORE) fatal("rdataset iteration failed: %s", isc_result_totext(result)); dns_rdatasetiter_destroy(&rdsiter2); } dns_rdatasetiter_destroy(&rdsiter); return (active); } /*% * Extracts the minimum TTL from the SOA record, and the SOA record's TTL. */ static void get_soa_ttls(void) { dns_rdataset_t soaset; dns_fixedname_t fname; dns_name_t *name; isc_result_t result; dns_rdata_t rdata = DNS_RDATA_INIT; dns_fixedname_init(&fname); name = dns_fixedname_name(&fname); dns_rdataset_init(&soaset); result = dns_db_find(gdb, gorigin, gversion, dns_rdatatype_soa, 0, 0, NULL, name, &soaset, NULL); if (result != ISC_R_SUCCESS) fatal("failed to find an SOA at the zone apex: %s", isc_result_totext(result)); result = dns_rdataset_first(&soaset); check_result(result, "dns_rdataset_first"); dns_rdataset_current(&soaset, &rdata); zone_soa_min_ttl = dns_soa_getminimum(&rdata); soa_ttl = soaset.ttl; if (set_maxttl) { zone_soa_min_ttl = ISC_MIN(zone_soa_min_ttl, maxttl); soa_ttl = ISC_MIN(soa_ttl, maxttl); } dns_rdataset_disassociate(&soaset); } /*% * Increment (or set if nonzero) the SOA serial */ static isc_result_t setsoaserial(isc_uint32_t serial, dns_updatemethod_t method) { isc_result_t result; dns_dbnode_t *node = NULL; dns_rdataset_t rdataset; dns_rdata_t rdata = DNS_RDATA_INIT; isc_uint32_t old_serial, new_serial; result = dns_db_getoriginnode(gdb, &node); if (result != ISC_R_SUCCESS) return result; dns_rdataset_init(&rdataset); result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_soa, 0, 0, &rdataset, NULL); if (result != ISC_R_SUCCESS) goto cleanup; result = dns_rdataset_first(&rdataset); RUNTIME_CHECK(result == ISC_R_SUCCESS); dns_rdataset_current(&rdataset, &rdata); old_serial = dns_soa_getserial(&rdata); if (method == dns_updatemethod_date || method == dns_updatemethod_unixtime) { new_serial = dns_update_soaserial(old_serial, method); } else if (serial != 0 || method == dns_updatemethod_none) { /* Set SOA serial to the value provided. */ new_serial = serial; } else { /* Increment SOA serial using RFC 1982 arithmetics */ new_serial = (old_serial + 1) & 0xFFFFFFFF; if (new_serial == 0) new_serial = 1; } /* If the new serial is not likely to cause a zone transfer * (a/ixfr) from servers having the old serial, warn the user. * * RFC1982 section 7 defines the maximum increment to be * (2^(32-1))-1. Using u_int32_t arithmetic, we can do a single * comparison. (5 - 6 == (2^32)-1, not negative-one) */ if (new_serial == old_serial || (new_serial - old_serial) > 0x7fffffffU) fprintf(stderr, "%s: warning: Serial number not advanced, " "zone may not transfer\n", program); dns_soa_setserial(new_serial, &rdata); result = dns_db_deleterdataset(gdb, node, gversion, dns_rdatatype_soa, 0); check_result(result, "dns_db_deleterdataset"); if (result != ISC_R_SUCCESS) goto cleanup; result = dns_db_addrdataset(gdb, node, gversion, 0, &rdataset, 0, NULL); check_result(result, "dns_db_addrdataset"); if (result != ISC_R_SUCCESS) goto cleanup; cleanup: dns_rdataset_disassociate(&rdataset); if (node != NULL) dns_db_detachnode(gdb, &node); dns_rdata_reset(&rdata); return (result); } /*% * Delete any RRSIG records at a node. */ static void cleannode(dns_db_t *db, dns_dbversion_t *dbversion, dns_dbnode_t *node) { dns_rdatasetiter_t *rdsiter = NULL; dns_rdataset_t set; isc_result_t result, dresult; if (outputformat != dns_masterformat_text || !disable_zone_check) return; dns_rdataset_init(&set); result = dns_db_allrdatasets(db, node, dbversion, 0, &rdsiter); check_result(result, "dns_db_allrdatasets"); result = dns_rdatasetiter_first(rdsiter); while (result == ISC_R_SUCCESS) { isc_boolean_t destroy = ISC_FALSE; dns_rdatatype_t covers = 0; dns_rdatasetiter_current(rdsiter, &set); if (set.type == dns_rdatatype_rrsig) { covers = set.covers; destroy = ISC_TRUE; } dns_rdataset_disassociate(&set); result = dns_rdatasetiter_next(rdsiter); if (destroy) { dresult = dns_db_deleterdataset(db, node, dbversion, dns_rdatatype_rrsig, covers); check_result(dresult, "dns_db_deleterdataset"); } } if (result != ISC_R_NOMORE) fatal("rdataset iteration failed: %s", isc_result_totext(result)); dns_rdatasetiter_destroy(&rdsiter); } /*% * Set up the iterator and global state before starting the tasks. */ static void presign(void) { isc_result_t result; gdbiter = NULL; result = dns_db_createiterator(gdb, 0, &gdbiter); check_result(result, "dns_db_createiterator()"); } /*% * Clean up the iterator and global state after the tasks complete. */ static void postsign(void) { dns_dbiterator_destroy(&gdbiter); } /*% * Sign the apex of the zone. * Note the origin may not be the first node if there are out of zone * records. */ static void signapex(void) { dns_dbnode_t *node = NULL; dns_fixedname_t fixed; dns_name_t *name; isc_result_t result; dns_fixedname_init(&fixed); name = dns_fixedname_name(&fixed); result = dns_dbiterator_seek(gdbiter, gorigin); check_result(result, "dns_dbiterator_seek()"); result = dns_dbiterator_current(gdbiter, &node, name); check_dns_dbiterator_current(result); signname(node, name); dumpnode(name, node); cleannode(gdb, gversion, node); dns_db_detachnode(gdb, &node); result = dns_dbiterator_first(gdbiter); if (result == ISC_R_NOMORE) finished = ISC_TRUE; else if (result != ISC_R_SUCCESS) fatal("failure iterating database: %s", isc_result_totext(result)); } /*% * Assigns a node to a worker thread. This is protected by the master task's * lock. */ static void assignwork(isc_task_t *task, isc_task_t *worker) { dns_fixedname_t *fname; dns_name_t *name; dns_dbnode_t *node; sevent_t *sevent; dns_rdataset_t nsec; isc_boolean_t found; isc_result_t result; static dns_name_t *zonecut = NULL; /* Protected by namelock. */ static dns_fixedname_t fzonecut; /* Protected by namelock. */ static unsigned int ended = 0; /* Protected by namelock. */ if (shuttingdown) return; LOCK(&namelock); if (finished) { ended++; if (ended == ntasks) { isc_task_detach(&task); isc_app_shutdown(); } goto unlock; } fname = isc_mem_get(mctx, sizeof(dns_fixedname_t)); if (fname == NULL) fatal("out of memory"); dns_fixedname_init(fname); name = dns_fixedname_name(fname); node = NULL; found = ISC_FALSE; while (!found) { result = dns_dbiterator_current(gdbiter, &node, name); check_dns_dbiterator_current(result); /* * The origin was handled by signapex(). */ if (dns_name_equal(name, gorigin)) { dns_db_detachnode(gdb, &node); goto next; } /* * Sort the zone data from the glue and out-of-zone data. * For NSEC zones nodes with zone data have NSEC records. * For NSEC3 zones the NSEC3 nodes are zone data but * outside of the zone name space. For the rest we need * to track the bottom of zone cuts. * Nodes which don't need to be signed are dumped here. */ dns_rdataset_init(&nsec); result = dns_db_findrdataset(gdb, node, gversion, nsec_datatype, 0, 0, &nsec, NULL); if (dns_rdataset_isassociated(&nsec)) dns_rdataset_disassociate(&nsec); if (result == ISC_R_SUCCESS) { found = ISC_TRUE; } else if (nsec_datatype == dns_rdatatype_nsec3) { if (dns_name_issubdomain(name, gorigin) && (zonecut == NULL || !dns_name_issubdomain(name, zonecut))) { if (is_delegation(gdb, gversion, gorigin, name, node, NULL)) { dns_fixedname_init(&fzonecut); zonecut = dns_fixedname_name(&fzonecut); dns_name_copy(name, zonecut, NULL); if (!OPTOUT(nsec3flags) || secure(name, node)) found = ISC_TRUE; } else found = ISC_TRUE; } } if (!found) { dumpnode(name, node); dns_db_detachnode(gdb, &node); } next: result = dns_dbiterator_next(gdbiter); if (result == ISC_R_NOMORE) { finished = ISC_TRUE; break; } else if (result != ISC_R_SUCCESS) fatal("failure iterating database: %s", isc_result_totext(result)); } if (!found) { ended++; if (ended == ntasks) { isc_task_detach(&task); isc_app_shutdown(); } isc_mem_put(mctx, fname, sizeof(dns_fixedname_t)); goto unlock; } sevent = (sevent_t *) isc_event_allocate(mctx, task, SIGNER_EVENT_WORK, sign, NULL, sizeof(sevent_t)); if (sevent == NULL) fatal("failed to allocate event\n"); sevent->node = node; sevent->fname = fname; isc_task_send(worker, ISC_EVENT_PTR(&sevent)); unlock: UNLOCK(&namelock); } /*% * Start a worker task */ static void startworker(isc_task_t *task, isc_event_t *event) { isc_task_t *worker; worker = (isc_task_t *)event->ev_arg; assignwork(task, worker); isc_event_free(&event); } /*% * Write a node to the output file, and restart the worker task. */ static void writenode(isc_task_t *task, isc_event_t *event) { isc_task_t *worker; sevent_t *sevent = (sevent_t *)event; worker = (isc_task_t *)event->ev_sender; dumpnode(dns_fixedname_name(sevent->fname), sevent->node); cleannode(gdb, gversion, sevent->node); dns_db_detachnode(gdb, &sevent->node); isc_mem_put(mctx, sevent->fname, sizeof(dns_fixedname_t)); assignwork(task, worker); isc_event_free(&event); } /*% * Sign a database node. */ static void sign(isc_task_t *task, isc_event_t *event) { dns_fixedname_t *fname; dns_dbnode_t *node; sevent_t *sevent, *wevent; sevent = (sevent_t *)event; node = sevent->node; fname = sevent->fname; isc_event_free(&event); signname(node, dns_fixedname_name(fname)); wevent = (sevent_t *) isc_event_allocate(mctx, task, SIGNER_EVENT_WRITE, writenode, NULL, sizeof(sevent_t)); if (wevent == NULL) fatal("failed to allocate event\n"); wevent->node = node; wevent->fname = fname; isc_task_send(master, ISC_EVENT_PTR(&wevent)); } /*% * Update / remove the DS RRset. Preserve RRSIG(DS) if possible. */ static void add_ds(dns_name_t *name, dns_dbnode_t *node, isc_uint32_t nsttl) { dns_rdataset_t dsset; dns_rdataset_t sigdsset; isc_result_t result; dns_rdataset_init(&dsset); dns_rdataset_init(&sigdsset); result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_ds, 0, 0, &dsset, &sigdsset); if (result == ISC_R_SUCCESS) { dns_rdataset_disassociate(&dsset); result = dns_db_deleterdataset(gdb, node, gversion, dns_rdatatype_ds, 0); check_result(result, "dns_db_deleterdataset"); } result = loadds(name, nsttl, &dsset); if (result == ISC_R_SUCCESS) { result = dns_db_addrdataset(gdb, node, gversion, 0, &dsset, 0, NULL); check_result(result, "dns_db_addrdataset"); dns_rdataset_disassociate(&dsset); if (dns_rdataset_isassociated(&sigdsset)) dns_rdataset_disassociate(&sigdsset); } else if (dns_rdataset_isassociated(&sigdsset)) { result = dns_db_deleterdataset(gdb, node, gversion, dns_rdatatype_rrsig, dns_rdatatype_ds); check_result(result, "dns_db_deleterdataset"); dns_rdataset_disassociate(&sigdsset); } } /* * Remove records of the given type and their signatures. */ static void remove_records(dns_dbnode_t *node, dns_rdatatype_t which, isc_boolean_t checknsec) { isc_result_t result; dns_rdatatype_t type, covers; dns_rdatasetiter_t *rdsiter = NULL; dns_rdataset_t rdataset; dns_rdataset_init(&rdataset); /* * Delete any records of the given type at the apex. */ result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter); check_result(result, "dns_db_allrdatasets()"); for (result = dns_rdatasetiter_first(rdsiter); result == ISC_R_SUCCESS; result = dns_rdatasetiter_next(rdsiter)) { dns_rdatasetiter_current(rdsiter, &rdataset); type = rdataset.type; covers = rdataset.covers; dns_rdataset_disassociate(&rdataset); if (type == which || covers == which) { if (which == dns_rdatatype_nsec && checknsec && !update_chain) fatal("Zone contains NSEC records. Use -u " "to update to NSEC3."); if (which == dns_rdatatype_nsec3param && checknsec && !update_chain) fatal("Zone contains NSEC3 chains. Use -u " "to update to NSEC."); result = dns_db_deleterdataset(gdb, node, gversion, type, covers); check_result(result, "dns_db_deleterdataset()"); continue; } } dns_rdatasetiter_destroy(&rdsiter); } /* * Remove signatures covering the given type. If type == 0, * then remove all signatures, unless this is a delegation, in * which case remove all signatures except for DS or nsec_datatype */ static void remove_sigs(dns_dbnode_t *node, isc_boolean_t delegation, dns_rdatatype_t which) { isc_result_t result; dns_rdatatype_t type, covers; dns_rdatasetiter_t *rdsiter = NULL; dns_rdataset_t rdataset; dns_rdataset_init(&rdataset); result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter); check_result(result, "dns_db_allrdatasets()"); for (result = dns_rdatasetiter_first(rdsiter); result == ISC_R_SUCCESS; result = dns_rdatasetiter_next(rdsiter)) { dns_rdatasetiter_current(rdsiter, &rdataset); type = rdataset.type; covers = rdataset.covers; dns_rdataset_disassociate(&rdataset); if (type != dns_rdatatype_rrsig) continue; if (which == 0 && delegation && (dns_rdatatype_atparent(covers) || (nsec_datatype == dns_rdatatype_nsec && covers == nsec_datatype))) continue; if (which != 0 && covers != which) continue; result = dns_db_deleterdataset(gdb, node, gversion, type, covers); check_result(result, "dns_db_deleterdataset()"); } dns_rdatasetiter_destroy(&rdsiter); } /*% * Generate NSEC records for the zone and remove NSEC3/NSEC3PARAM records. */ static void nsecify(void) { dns_dbiterator_t *dbiter = NULL; dns_dbnode_t *node = NULL, *nextnode = NULL; dns_fixedname_t fname, fnextname, fzonecut; dns_name_t *name, *nextname, *zonecut; dns_rdataset_t rdataset; dns_rdatasetiter_t *rdsiter = NULL; dns_rdatatype_t type, covers; isc_boolean_t done = ISC_FALSE; isc_result_t result; isc_uint32_t nsttl = 0; dns_rdataset_init(&rdataset); dns_fixedname_init(&fname); name = dns_fixedname_name(&fname); dns_fixedname_init(&fnextname); nextname = dns_fixedname_name(&fnextname); dns_fixedname_init(&fzonecut); zonecut = NULL; /* * Remove any NSEC3 chains. */ result = dns_db_createiterator(gdb, DNS_DB_NSEC3ONLY, &dbiter); check_result(result, "dns_db_createiterator()"); for (result = dns_dbiterator_first(dbiter); result == ISC_R_SUCCESS; result = dns_dbiterator_next(dbiter)) { result = dns_dbiterator_current(dbiter, &node, name); check_dns_dbiterator_current(result); result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter); check_result(result, "dns_db_allrdatasets()"); for (result = dns_rdatasetiter_first(rdsiter); result == ISC_R_SUCCESS; result = dns_rdatasetiter_next(rdsiter)) { dns_rdatasetiter_current(rdsiter, &rdataset); type = rdataset.type; covers = rdataset.covers; dns_rdataset_disassociate(&rdataset); result = dns_db_deleterdataset(gdb, node, gversion, type, covers); check_result(result, "dns_db_deleterdataset(nsec3param/rrsig)"); } dns_rdatasetiter_destroy(&rdsiter); dns_db_detachnode(gdb, &node); } dns_dbiterator_destroy(&dbiter); result = dns_db_createiterator(gdb, DNS_DB_NONSEC3, &dbiter); check_result(result, "dns_db_createiterator()"); result = dns_dbiterator_first(dbiter); check_result(result, "dns_dbiterator_first()"); while (!done) { result = dns_dbiterator_current(dbiter, &node, name); check_dns_dbiterator_current(result); /* * Skip out-of-zone records. */ if (!dns_name_issubdomain(name, gorigin)) { result = dns_dbiterator_next(dbiter); if (result == ISC_R_NOMORE) done = ISC_TRUE; else check_result(result, "dns_dbiterator_next()"); dns_db_detachnode(gdb, &node); continue; } if (dns_name_equal(name, gorigin)) { remove_records(node, dns_rdatatype_nsec3param, ISC_TRUE); /* Clean old rrsigs at apex. */ (void)active_node(node); } if (is_delegation(gdb, gversion, gorigin, name, node, &nsttl)) { zonecut = dns_fixedname_name(&fzonecut); dns_name_copy(name, zonecut, NULL); remove_sigs(node, ISC_TRUE, 0); if (generateds) add_ds(name, node, nsttl); } result = dns_dbiterator_next(dbiter); nextnode = NULL; while (result == ISC_R_SUCCESS) { isc_boolean_t active = ISC_FALSE; result = dns_dbiterator_current(dbiter, &nextnode, nextname); check_dns_dbiterator_current(result); active = active_node(nextnode); if (!active) { dns_db_detachnode(gdb, &nextnode); result = dns_dbiterator_next(dbiter); continue; } if (!dns_name_issubdomain(nextname, gorigin) || (zonecut != NULL && dns_name_issubdomain(nextname, zonecut))) { remove_sigs(nextnode, ISC_FALSE, 0); remove_records(nextnode, dns_rdatatype_nsec, ISC_FALSE); dns_db_detachnode(gdb, &nextnode); result = dns_dbiterator_next(dbiter); continue; } dns_db_detachnode(gdb, &nextnode); break; } if (result == ISC_R_NOMORE) { dns_name_clone(gorigin, nextname); done = ISC_TRUE; } else if (result != ISC_R_SUCCESS) fatal("iterating through the database failed: %s", isc_result_totext(result)); dns_dbiterator_pause(dbiter); result = dns_nsec_build(gdb, gversion, node, nextname, zone_soa_min_ttl); check_result(result, "dns_nsec_build()"); dns_db_detachnode(gdb, &node); } dns_dbiterator_destroy(&dbiter); } static void addnsec3param(const unsigned char *salt, size_t salt_len, dns_iterations_t iterations) { dns_dbnode_t *node = NULL; dns_rdata_nsec3param_t nsec3param; unsigned char nsec3parambuf[5 + 255]; dns_rdatalist_t rdatalist; dns_rdataset_t rdataset; dns_rdata_t rdata = DNS_RDATA_INIT; isc_buffer_t b; isc_result_t result; dns_rdataset_init(&rdataset); nsec3param.common.rdclass = gclass; nsec3param.common.rdtype = dns_rdatatype_nsec3param; ISC_LINK_INIT(&nsec3param.common, link); nsec3param.mctx = NULL; nsec3param.flags = 0; nsec3param.hash = unknownalg ? DNS_NSEC3_UNKNOWNALG : dns_hash_sha1; nsec3param.iterations = iterations; nsec3param.salt_length = (unsigned char)salt_len; DE_CONST(salt, nsec3param.salt); isc_buffer_init(&b, nsec3parambuf, sizeof(nsec3parambuf)); result = dns_rdata_fromstruct(&rdata, gclass, dns_rdatatype_nsec3param, &nsec3param, &b); check_result(result, "dns_rdata_fromstruct()"); dns_rdatalist_init(&rdatalist); rdatalist.rdclass = rdata.rdclass; rdatalist.type = rdata.type; ISC_LIST_APPEND(rdatalist.rdata, &rdata, link); result = dns_rdatalist_tordataset(&rdatalist, &rdataset); check_result(result, "dns_rdatalist_tordataset()"); result = dns_db_findnode(gdb, gorigin, ISC_TRUE, &node); check_result(result, "dns_db_find(gorigin)"); /* * Delete any current NSEC3PARAM records. */ result = dns_db_deleterdataset(gdb, node, gversion, dns_rdatatype_nsec3param, 0); if (result == DNS_R_UNCHANGED) result = ISC_R_SUCCESS; check_result(result, "dddnsec3param: dns_db_deleterdataset()"); result = dns_db_addrdataset(gdb, node, gversion, 0, &rdataset, DNS_DBADD_MERGE, NULL); if (result == DNS_R_UNCHANGED) result = ISC_R_SUCCESS; check_result(result, "addnsec3param: dns_db_addrdataset()"); dns_db_detachnode(gdb, &node); } static void addnsec3(dns_name_t *name, dns_dbnode_t *node, const unsigned char *salt, size_t salt_len, unsigned int iterations, hashlist_t *hashlist, dns_ttl_t ttl) { unsigned char hash[NSEC3_MAX_HASH_LENGTH]; const unsigned char *nexthash; unsigned char nsec3buffer[DNS_NSEC3_BUFFERSIZE]; dns_fixedname_t hashname; dns_rdatalist_t rdatalist; dns_rdataset_t rdataset; dns_rdata_t rdata = DNS_RDATA_INIT; isc_result_t result; dns_dbnode_t *nsec3node = NULL; char namebuf[DNS_NAME_FORMATSIZE]; size_t hash_len; dns_name_format(name, namebuf, sizeof(namebuf)); dns_fixedname_init(&hashname); dns_rdataset_init(&rdataset); dns_name_downcase(name, name, NULL); result = dns_nsec3_hashname(&hashname, hash, &hash_len, name, gorigin, dns_hash_sha1, iterations, salt, salt_len); check_result(result, "addnsec3: dns_nsec3_hashname()"); nexthash = hashlist_findnext(hashlist, hash); result = dns_nsec3_buildrdata(gdb, gversion, node, unknownalg ? DNS_NSEC3_UNKNOWNALG : dns_hash_sha1, nsec3flags, iterations, salt, salt_len, nexthash, ISC_SHA1_DIGESTLENGTH, nsec3buffer, &rdata); check_result(result, "addnsec3: dns_nsec3_buildrdata()"); dns_rdatalist_init(&rdatalist); rdatalist.rdclass = rdata.rdclass; rdatalist.type = rdata.type; rdatalist.ttl = ttl; ISC_LIST_APPEND(rdatalist.rdata, &rdata, link); result = dns_rdatalist_tordataset(&rdatalist, &rdataset); check_result(result, "dns_rdatalist_tordataset()"); result = dns_db_findnsec3node(gdb, dns_fixedname_name(&hashname), ISC_TRUE, &nsec3node); check_result(result, "addnsec3: dns_db_findnode()"); result = dns_db_addrdataset(gdb, nsec3node, gversion, 0, &rdataset, 0, NULL); if (result == DNS_R_UNCHANGED) result = ISC_R_SUCCESS; check_result(result, "addnsec3: dns_db_addrdataset()"); dns_db_detachnode(gdb, &nsec3node); } /*% * Clean out NSEC3 record and RRSIG(NSEC3) that are not in the hash list. * * Extract the hash from the first label of 'name' then see if it * is in hashlist. If 'name' is not in the hashlist then delete the * any NSEC3 records which have the same parameters as the chain we * are building. * * XXXMPA Should we also check that it of the form <hash>.<origin>? */ static void nsec3clean(dns_name_t *name, dns_dbnode_t *node, unsigned int hashalg, unsigned int iterations, const unsigned char *salt, size_t salt_len, hashlist_t *hashlist) { dns_label_t label; dns_rdata_nsec3_t nsec3; dns_rdata_t rdata, delrdata; dns_rdatalist_t rdatalist; dns_rdataset_t rdataset, delrdataset; isc_boolean_t delete_rrsigs = ISC_FALSE; isc_buffer_t target; isc_result_t result; unsigned char hash[NSEC3_MAX_HASH_LENGTH + 1]; isc_boolean_t exists; /* * Get the first label. */ dns_name_getlabel(name, 0, &label); /* * We want just the label contents. */ isc_region_consume(&label, 1); /* * Decode base32hex string. */ isc_buffer_init(&target, hash, sizeof(hash) - 1); result = isc_base32hex_decoderegion(&label, &target); if (result != ISC_R_SUCCESS) return; hash[isc_buffer_usedlength(&target)] = 0; exists = hashlist_exists(hashlist, hash); /* * Verify that the NSEC3 parameters match the current ones * otherwise we are dealing with a different NSEC3 chain. */ dns_rdataset_init(&rdataset); dns_rdataset_init(&delrdataset); result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_nsec3, 0, 0, &rdataset, NULL); if (result != ISC_R_SUCCESS) return; /* * Delete any NSEC3 records which are not part of the current * NSEC3 chain. */ for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS; result = dns_rdataset_next(&rdataset)) { dns_rdata_init(&rdata); dns_rdataset_current(&rdataset, &rdata); result = dns_rdata_tostruct(&rdata, &nsec3, NULL); check_result(result, "dns_rdata_tostruct"); if (exists && nsec3.hash == hashalg && nsec3.iterations == iterations && nsec3.salt_length == salt_len && isc_safe_memequal(nsec3.salt, salt, salt_len)) continue; dns_rdatalist_init(&rdatalist); rdatalist.rdclass = rdata.rdclass; rdatalist.type = rdata.type; if (set_maxttl) rdatalist.ttl = ISC_MIN(rdataset.ttl, maxttl); dns_rdata_init(&delrdata); dns_rdata_clone(&rdata, &delrdata); ISC_LIST_APPEND(rdatalist.rdata, &delrdata, link); result = dns_rdatalist_tordataset(&rdatalist, &delrdataset); check_result(result, "dns_rdatalist_tordataset()"); result = dns_db_subtractrdataset(gdb, node, gversion, &delrdataset, 0, NULL); dns_rdataset_disassociate(&delrdataset); if (result != ISC_R_SUCCESS && result != DNS_R_NXRRSET) check_result(result, "dns_db_subtractrdataset(NSEC3)"); delete_rrsigs = ISC_TRUE; } dns_rdataset_disassociate(&rdataset); if (result != ISC_R_NOMORE) check_result(result, "dns_rdataset_first/next"); if (!delete_rrsigs) return; /* * Delete the NSEC3 RRSIGs */ result = dns_db_deleterdataset(gdb, node, gversion, dns_rdatatype_rrsig, dns_rdatatype_nsec3); if (result != ISC_R_SUCCESS && result != DNS_R_UNCHANGED) check_result(result, "dns_db_deleterdataset(RRSIG(NSEC3))"); } static void rrset_cleanup(dns_name_t *name, dns_rdataset_t *rdataset, dns_diff_t *add, dns_diff_t *del) { isc_result_t result; unsigned int count1 = 0; dns_rdataset_t tmprdataset; char namestr[DNS_NAME_FORMATSIZE]; char typestr[TYPE_FORMATSIZE]; dns_name_format(name, namestr, sizeof(namestr)); type_format(rdataset->type, typestr, sizeof(typestr)); dns_rdataset_init(&tmprdataset); for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS; result = dns_rdataset_next(rdataset)) { dns_rdata_t rdata1 = DNS_RDATA_INIT; unsigned int count2 = 0; count1++; dns_rdataset_current(rdataset, &rdata1); dns_rdataset_clone(rdataset, &tmprdataset); for (result = dns_rdataset_first(&tmprdataset); result == ISC_R_SUCCESS; result = dns_rdataset_next(&tmprdataset)) { dns_rdata_t rdata2 = DNS_RDATA_INIT; dns_difftuple_t *tuple = NULL; count2++; dns_rdataset_current(&tmprdataset, &rdata2); if (count1 < count2 && dns_rdata_casecompare(&rdata1, &rdata2) == 0) { vbprintf(2, "removing duplicate at %s/%s\n", namestr, typestr); result = dns_difftuple_create(mctx, DNS_DIFFOP_DELRESIGN, name, rdataset->ttl, &rdata2, &tuple); check_result(result, "dns_difftuple_create"); dns_diff_append(del, &tuple); } else if (set_maxttl && rdataset->ttl > maxttl) { vbprintf(2, "reducing ttl of %s/%s " "from %d to %d\n", namestr, typestr, rdataset->ttl, maxttl); result = dns_difftuple_create(mctx, DNS_DIFFOP_DELRESIGN, name, rdataset->ttl, &rdata2, &tuple); check_result(result, "dns_difftuple_create"); dns_diff_append(del, &tuple); tuple = NULL; result = dns_difftuple_create(mctx, DNS_DIFFOP_ADDRESIGN, name, maxttl, &rdata2, &tuple); check_result(result, "dns_difftuple_create"); dns_diff_append(add, &tuple); } } dns_rdataset_disassociate(&tmprdataset); } } static void cleanup_zone(void) { isc_result_t result; dns_dbiterator_t *dbiter = NULL; dns_rdatasetiter_t *rdsiter = NULL; dns_diff_t add, del; dns_dbnode_t *node = NULL; dns_rdataset_t rdataset; dns_fixedname_t fname; dns_name_t *name; dns_diff_init(mctx, &add); dns_diff_init(mctx, &del); dns_fixedname_init(&fname); name = dns_fixedname_name(&fname); dns_rdataset_init(&rdataset); result = dns_db_createiterator(gdb, 0, &dbiter); check_result(result, "dns_db_createiterator()"); for (result = dns_dbiterator_first(dbiter); result == ISC_R_SUCCESS; result = dns_dbiterator_next(dbiter)) { result = dns_dbiterator_current(dbiter, &node, name); check_dns_dbiterator_current(result); result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter); check_result(result, "dns_db_allrdatasets()"); for (result = dns_rdatasetiter_first(rdsiter); result == ISC_R_SUCCESS; result = dns_rdatasetiter_next(rdsiter)) { dns_rdatasetiter_current(rdsiter, &rdataset); rrset_cleanup(name, &rdataset, &add, &del); dns_rdataset_disassociate(&rdataset); } if (result != ISC_R_NOMORE) fatal("rdatasets iteration failed."); dns_rdatasetiter_destroy(&rdsiter); dns_db_detachnode(gdb, &node); } if (result != ISC_R_NOMORE) fatal("zone iteration failed."); result = dns_diff_applysilently(&del, gdb, gversion); check_result(result, "dns_diff_applysilently"); result = dns_diff_applysilently(&add, gdb, gversion); check_result(result, "dns_diff_applysilently"); dns_diff_clear(&del); dns_diff_clear(&add); dns_dbiterator_destroy(&dbiter); } /* * Generate NSEC3 records for the zone. */ static void nsec3ify(unsigned int hashalg, dns_iterations_t iterations, const unsigned char *salt, size_t salt_len, hashlist_t *hashlist) { dns_dbiterator_t *dbiter = NULL; dns_dbnode_t *node = NULL, *nextnode = NULL; dns_fixedname_t fname, fnextname, fzonecut; dns_name_t *name, *nextname, *zonecut; dns_rdataset_t rdataset; int order; isc_boolean_t active; isc_boolean_t done = ISC_FALSE; isc_result_t result; isc_uint32_t nsttl = 0; unsigned int count, nlabels; dns_rdataset_init(&rdataset); dns_fixedname_init(&fname); name = dns_fixedname_name(&fname); dns_fixedname_init(&fnextname); nextname = dns_fixedname_name(&fnextname); dns_fixedname_init(&fzonecut); zonecut = NULL; /* * Walk the zone generating the hash names. */ result = dns_db_createiterator(gdb, DNS_DB_NONSEC3, &dbiter); check_result(result, "dns_db_createiterator()"); result = dns_dbiterator_first(dbiter); check_result(result, "dns_dbiterator_first()"); while (!done) { result = dns_dbiterator_current(dbiter, &node, name); check_dns_dbiterator_current(result); /* * Skip out-of-zone records. */ if (!dns_name_issubdomain(name, gorigin)) { result = dns_dbiterator_next(dbiter); if (result == ISC_R_NOMORE) done = ISC_TRUE; else check_result(result, "dns_dbiterator_next()"); dns_db_detachnode(gdb, &node); continue; } if (dns_name_equal(name, gorigin)) { remove_records(node, dns_rdatatype_nsec, ISC_TRUE); /* Clean old rrsigs at apex. */ (void)active_node(node); } result = dns_dbiterator_next(dbiter); nextnode = NULL; while (result == ISC_R_SUCCESS) { result = dns_dbiterator_current(dbiter, &nextnode, nextname); check_dns_dbiterator_current(result); active = active_node(nextnode); if (!active) { dns_db_detachnode(gdb, &nextnode); result = dns_dbiterator_next(dbiter); continue; } if (!dns_name_issubdomain(nextname, gorigin) || (zonecut != NULL && dns_name_issubdomain(nextname, zonecut))) { remove_sigs(nextnode, ISC_FALSE, 0); dns_db_detachnode(gdb, &nextnode); result = dns_dbiterator_next(dbiter); continue; } if (is_delegation(gdb, gversion, gorigin, nextname, nextnode, &nsttl)) { zonecut = dns_fixedname_name(&fzonecut); dns_name_copy(nextname, zonecut, NULL); remove_sigs(nextnode, ISC_TRUE, 0); if (generateds) add_ds(nextname, nextnode, nsttl); if (OPTOUT(nsec3flags) && !secure(nextname, nextnode)) { dns_db_detachnode(gdb, &nextnode); result = dns_dbiterator_next(dbiter); continue; } } dns_db_detachnode(gdb, &nextnode); break; } if (result == ISC_R_NOMORE) { dns_name_copy(gorigin, nextname, NULL); done = ISC_TRUE; } else if (result != ISC_R_SUCCESS) fatal("iterating through the database failed: %s", isc_result_totext(result)); dns_name_downcase(name, name, NULL); hashlist_add_dns_name(hashlist, name, hashalg, iterations, salt, salt_len, ISC_FALSE); dns_db_detachnode(gdb, &node); /* * Add hashs for empty nodes. Use closest encloser logic. * The closest encloser either has data or is a empty * node for another span so we don't add * it here. Empty labels on nextname are within the span. */ dns_name_downcase(nextname, nextname, NULL); dns_name_fullcompare(name, nextname, &order, &nlabels); addnowildcardhash(hashlist, name, hashalg, iterations, salt, salt_len); count = dns_name_countlabels(nextname); while (count > nlabels + 1) { count--; dns_name_split(nextname, count, NULL, nextname); hashlist_add_dns_name(hashlist, nextname, hashalg, iterations, salt, salt_len, ISC_FALSE); addnowildcardhash(hashlist, nextname, hashalg, iterations, salt, salt_len); } } dns_dbiterator_destroy(&dbiter); /* * We have all the hashes now so we can sort them. */ hashlist_sort(hashlist); /* * Check for duplicate hashes. If found the salt needs to * be changed. */ if (hashlist_hasdup(hashlist)) fatal("Duplicate hash detected. Pick a different salt."); /* * Generate the nsec3 records. */ zonecut = NULL; done = ISC_FALSE; addnsec3param(salt, salt_len, iterations); /* * Clean out NSEC3 records which don't match this chain. */ result = dns_db_createiterator(gdb, DNS_DB_NSEC3ONLY, &dbiter); check_result(result, "dns_db_createiterator()"); for (result = dns_dbiterator_first(dbiter); result == ISC_R_SUCCESS; result = dns_dbiterator_next(dbiter)) { result = dns_dbiterator_current(dbiter, &node, name); check_dns_dbiterator_current(result); nsec3clean(name, node, hashalg, iterations, salt, salt_len, hashlist); dns_db_detachnode(gdb, &node); } dns_dbiterator_destroy(&dbiter); /* * Generate / complete the new chain. */ result = dns_db_createiterator(gdb, DNS_DB_NONSEC3, &dbiter); check_result(result, "dns_db_createiterator()"); result = dns_dbiterator_first(dbiter); check_result(result, "dns_dbiterator_first()"); while (!done) { result = dns_dbiterator_current(dbiter, &node, name); check_dns_dbiterator_current(result); /* * Skip out-of-zone records. */ if (!dns_name_issubdomain(name, gorigin)) { result = dns_dbiterator_next(dbiter); if (result == ISC_R_NOMORE) done = ISC_TRUE; else check_result(result, "dns_dbiterator_next()"); dns_db_detachnode(gdb, &node); continue; } result = dns_dbiterator_next(dbiter); nextnode = NULL; while (result == ISC_R_SUCCESS) { result = dns_dbiterator_current(dbiter, &nextnode, nextname); check_dns_dbiterator_current(result); active = active_node(nextnode); if (!active) { dns_db_detachnode(gdb, &nextnode); result = dns_dbiterator_next(dbiter); continue; } if (!dns_name_issubdomain(nextname, gorigin) || (zonecut != NULL && dns_name_issubdomain(nextname, zonecut))) { dns_db_detachnode(gdb, &nextnode); result = dns_dbiterator_next(dbiter); continue; } if (is_delegation(gdb, gversion, gorigin, nextname, nextnode, NULL)) { zonecut = dns_fixedname_name(&fzonecut); dns_name_copy(nextname, zonecut, NULL); if (OPTOUT(nsec3flags) && !secure(nextname, nextnode)) { dns_db_detachnode(gdb, &nextnode); result = dns_dbiterator_next(dbiter); continue; } } dns_db_detachnode(gdb, &nextnode); break; } if (result == ISC_R_NOMORE) { dns_name_copy(gorigin, nextname, NULL); done = ISC_TRUE; } else if (result != ISC_R_SUCCESS) fatal("iterating through the database failed: %s", isc_result_totext(result)); /* * We need to pause here to release the lock on the database. */ dns_dbiterator_pause(dbiter); addnsec3(name, node, salt, salt_len, iterations, hashlist, zone_soa_min_ttl); dns_db_detachnode(gdb, &node); /* * Add NSEC3's for empty nodes. Use closest encloser logic. */ dns_name_fullcompare(name, nextname, &order, &nlabels); count = dns_name_countlabels(nextname); while (count > nlabels + 1) { count--; dns_name_split(nextname, count, NULL, nextname); addnsec3(nextname, NULL, salt, salt_len, iterations, hashlist, zone_soa_min_ttl); } } dns_dbiterator_destroy(&dbiter); } /*% * Load the zone file from disk */ static void loadzone(char *file, char *origin, dns_rdataclass_t rdclass, dns_db_t **db) { isc_buffer_t b; int len; dns_fixedname_t fname; dns_name_t *name; isc_result_t result; len = strlen(origin); isc_buffer_init(&b, origin, len); isc_buffer_add(&b, len); dns_fixedname_init(&fname); name = dns_fixedname_name(&fname); result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL); if (result != ISC_R_SUCCESS) fatal("failed converting name '%s' to dns format: %s", origin, isc_result_totext(result)); result = dns_db_create(mctx, "rbt", name, dns_dbtype_zone, rdclass, 0, NULL, db); check_result(result, "dns_db_create()"); result = dns_db_load2(*db, file, inputformat); if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE) fatal("failed loading zone from '%s': %s", file, isc_result_totext(result)); } /*% * Finds all public zone keys in the zone, and attempts to load the * private keys from disk. */ static void loadzonekeys(isc_boolean_t preserve_keys, isc_boolean_t load_public) { dns_dbnode_t *node; dns_dbversion_t *currentversion = NULL; isc_result_t result; dns_rdataset_t rdataset, keysigs, soasigs; node = NULL; result = dns_db_findnode(gdb, gorigin, ISC_FALSE, &node); if (result != ISC_R_SUCCESS) fatal("failed to find the zone's origin: %s", isc_result_totext(result)); dns_db_currentversion(gdb, ¤tversion); dns_rdataset_init(&rdataset); dns_rdataset_init(&soasigs); dns_rdataset_init(&keysigs); /* Make note of the keys which signed the SOA, if any */ result = dns_db_findrdataset(gdb, node, currentversion, dns_rdatatype_soa, 0, 0, &rdataset, &soasigs); if (result != ISC_R_SUCCESS) goto cleanup; /* Preserve the TTL of the DNSKEY RRset, if any */ dns_rdataset_disassociate(&rdataset); result = dns_db_findrdataset(gdb, node, currentversion, dns_rdatatype_dnskey, 0, 0, &rdataset, &keysigs); if (result != ISC_R_SUCCESS) goto cleanup; if (set_keyttl && keyttl != rdataset.ttl) { fprintf(stderr, "User-specified TTL %d conflicts " "with existing DNSKEY RRset TTL.\n", keyttl); fprintf(stderr, "Imported keys will use the RRSet " "TTL %d instead.\n", rdataset.ttl); } keyttl = rdataset.ttl; /* Load keys corresponding to the existing DNSKEY RRset. */ result = dns_dnssec_keylistfromrdataset(gorigin, directory, mctx, &rdataset, &keysigs, &soasigs, preserve_keys, load_public, &keylist); if (result != ISC_R_SUCCESS) fatal("failed to load the zone keys: %s", isc_result_totext(result)); cleanup: if (dns_rdataset_isassociated(&rdataset)) dns_rdataset_disassociate(&rdataset); if (dns_rdataset_isassociated(&keysigs)) dns_rdataset_disassociate(&keysigs); if (dns_rdataset_isassociated(&soasigs)) dns_rdataset_disassociate(&soasigs); dns_db_detachnode(gdb, &node); dns_db_closeversion(gdb, ¤tversion, ISC_FALSE); } static void loadexplicitkeys(char *keyfiles[], int n, isc_boolean_t setksk) { isc_result_t result; int i; for (i = 0; i < n; i++) { dns_dnsseckey_t *key = NULL; dst_key_t *newkey = NULL; result = dst_key_fromnamedfile(keyfiles[i], directory, DST_TYPE_PUBLIC | DST_TYPE_PRIVATE, mctx, &newkey); if (result != ISC_R_SUCCESS) fatal("cannot load dnskey %s: %s", keyfiles[i], isc_result_totext(result)); if (!dns_name_equal(gorigin, dst_key_name(newkey))) fatal("key %s not at origin\n", keyfiles[i]); if (!dst_key_isprivate(newkey)) fatal("cannot sign zone with non-private dnskey %s", keyfiles[i]); /* Skip any duplicates */ for (key = ISC_LIST_HEAD(keylist); key != NULL; key = ISC_LIST_NEXT(key, link)) { if (dst_key_id(key->key) == dst_key_id(newkey) && dst_key_alg(key->key) == dst_key_alg(newkey)) break; } if (key == NULL) { /* We haven't seen this key before */ dns_dnsseckey_create(mctx, &newkey, &key); ISC_LIST_APPEND(keylist, key, link); key->source = dns_keysource_user; } else { dst_key_free(&key->key); key->key = newkey; } key->force_publish = ISC_TRUE; key->force_sign = ISC_TRUE; if (setksk) key->ksk = ISC_TRUE; } } static void report(const char *format, ...) { va_list args; va_start(args, format); vfprintf(stderr, format, args); va_end(args); putc('\n', stderr); } static void build_final_keylist(void) { isc_result_t result; dns_dbversion_t *ver = NULL; dns_diff_t diff; dns_dnsseckeylist_t matchkeys; char name[DNS_NAME_FORMATSIZE]; /* * Find keys that match this zone in the key repository. */ ISC_LIST_INIT(matchkeys); result = dns_dnssec_findmatchingkeys(gorigin, directory, mctx, &matchkeys); if (result == ISC_R_NOTFOUND) result = ISC_R_SUCCESS; check_result(result, "dns_dnssec_findmatchingkeys"); result = dns_db_newversion(gdb, &ver); check_result(result, "dns_db_newversion"); dns_diff_init(mctx, &diff); /* * Update keylist with information from from the key repository. */ dns_dnssec_updatekeys(&keylist, &matchkeys, NULL, gorigin, keyttl, &diff, ignore_kskflag, mctx, report); dns_name_format(gorigin, name, sizeof(name)); result = dns_diff_applysilently(&diff, gdb, ver); if (result != ISC_R_SUCCESS) fatal("failed to update DNSKEY RRset at node '%s': %s", name, isc_result_totext(result)); dns_db_closeversion(gdb, &ver, ISC_TRUE); dns_diff_clear(&diff); } static void warnifallksk(dns_db_t *db) { dns_dbversion_t *currentversion = NULL; dns_dbnode_t *node = NULL; dns_rdataset_t rdataset; dns_rdata_t rdata = DNS_RDATA_INIT; isc_result_t result; dns_rdata_dnskey_t dnskey; isc_boolean_t have_non_ksk = ISC_FALSE; dns_db_currentversion(db, ¤tversion); result = dns_db_findnode(db, gorigin, ISC_FALSE, &node); if (result != ISC_R_SUCCESS) fatal("failed to find the zone's origin: %s", isc_result_totext(result)); dns_rdataset_init(&rdataset); result = dns_db_findrdataset(db, node, currentversion, dns_rdatatype_dnskey, 0, 0, &rdataset, NULL); if (result != ISC_R_SUCCESS) fatal("failed to find keys at the zone apex: %s", isc_result_totext(result)); result = dns_rdataset_first(&rdataset); check_result(result, "dns_rdataset_first"); while (result == ISC_R_SUCCESS) { dns_rdata_reset(&rdata); dns_rdataset_current(&rdataset, &rdata); result = dns_rdata_tostruct(&rdata, &dnskey, NULL); check_result(result, "dns_rdata_tostruct"); if ((dnskey.flags & DNS_KEYFLAG_KSK) == 0) { have_non_ksk = ISC_TRUE; result = ISC_R_NOMORE; } else result = dns_rdataset_next(&rdataset); dns_rdata_freestruct(&dnskey); } dns_rdataset_disassociate(&rdataset); dns_db_detachnode(db, &node); dns_db_closeversion(db, ¤tversion, ISC_FALSE); if (!have_non_ksk && !ignore_kskflag) { if (disable_zone_check) fprintf(stderr, "%s: warning: No non-KSK DNSKEY found; " "supply a ZSK or use '-z'.\n", program); else fatal("No non-KSK DNSKEY found; " "supply a ZSK or use '-z'."); } } static void set_nsec3params(isc_boolean_t update, isc_boolean_t set_salt, isc_boolean_t set_optout, isc_boolean_t set_iter) { isc_result_t result; dns_dbversion_t *ver = NULL; dns_dbnode_t *node = NULL; dns_rdataset_t rdataset; dns_rdata_t rdata = DNS_RDATA_INIT; dns_rdata_nsec3_t nsec3; dns_fixedname_t fname; dns_name_t *hashname; unsigned char orig_salt[255]; size_t orig_saltlen; dns_hash_t orig_hash; isc_uint16_t orig_iter; dns_db_currentversion(gdb, &ver); dns_rdataset_init(&rdataset); orig_saltlen = sizeof(orig_salt); result = dns_db_getnsec3parameters(gdb, ver, &orig_hash, NULL, &orig_iter, orig_salt, &orig_saltlen); if (result != ISC_R_SUCCESS) goto cleanup; nsec_datatype = dns_rdatatype_nsec3; if (!update && set_salt) { if (salt_length != orig_saltlen || !isc_safe_memequal(saltbuf, orig_salt, salt_length)) fatal("An NSEC3 chain exists with a different salt. " "Use -u to update it."); } else if (!set_salt) { salt_length = orig_saltlen; memmove(saltbuf, orig_salt, orig_saltlen); gsalt = saltbuf; } if (!update && set_iter) { if (nsec3iter != orig_iter) fatal("An NSEC3 chain exists with different " "iterations. Use -u to update it."); } else if (!set_iter) nsec3iter = orig_iter; /* * Find an NSEC3 record to get the current OPTOUT value. * (This assumes all NSEC3 records agree.) */ dns_fixedname_init(&fname); hashname = dns_fixedname_name(&fname); result = dns_nsec3_hashname(&fname, NULL, NULL, gorigin, gorigin, dns_hash_sha1, orig_iter, orig_salt, orig_saltlen); check_result(result, "dns_nsec3_hashname"); result = dns_db_findnsec3node(gdb, hashname, ISC_FALSE, &node); if (result != ISC_R_SUCCESS) goto cleanup; result = dns_db_findrdataset(gdb, node, ver, dns_rdatatype_nsec3, 0, 0, &rdataset, NULL); if (result != ISC_R_SUCCESS) goto cleanup; result = dns_rdataset_first(&rdataset); check_result(result, "dns_rdataset_first"); dns_rdataset_current(&rdataset, &rdata); result = dns_rdata_tostruct(&rdata, &nsec3, NULL); check_result(result, "dns_rdata_tostruct"); if (!update && set_optout) { if (nsec3flags != nsec3.flags) fatal("An NSEC3 chain exists with%s OPTOUT. " "Use -u -%s to %s it.", OPTOUT(nsec3.flags) ? "" : "out", OPTOUT(nsec3.flags) ? "AA" : "A", OPTOUT(nsec3.flags) ? "clear" : "set"); } else if (!set_optout) nsec3flags = nsec3.flags; dns_rdata_freestruct(&nsec3); cleanup: if (dns_rdataset_isassociated(&rdataset)) dns_rdataset_disassociate(&rdataset); if (node != NULL) dns_db_detachnode(gdb, &node); dns_db_closeversion(gdb, &ver, ISC_FALSE); } static void writeset(const char *prefix, dns_rdatatype_t type) { char *filename; char namestr[DNS_NAME_FORMATSIZE]; dns_db_t *db = NULL; dns_dbversion_t *dbversion = NULL; dns_diff_t diff; dns_difftuple_t *tuple = NULL; dns_fixedname_t fixed; dns_name_t *name; dns_rdata_t rdata, ds; isc_boolean_t have_ksk = ISC_FALSE; isc_boolean_t have_non_ksk = ISC_FALSE; isc_buffer_t b; isc_buffer_t namebuf; isc_region_t r; isc_result_t result; dns_dnsseckey_t *key, *tmpkey; unsigned char dsbuf[DNS_DS_BUFFERSIZE]; unsigned char keybuf[DST_KEY_MAXSIZE]; unsigned int filenamelen; const dns_master_style_t *style = (type == dns_rdatatype_dnskey) ? masterstyle : dsstyle; isc_buffer_init(&namebuf, namestr, sizeof(namestr)); result = dns_name_tofilenametext(gorigin, ISC_FALSE, &namebuf); check_result(result, "dns_name_tofilenametext"); isc_buffer_putuint8(&namebuf, 0); filenamelen = strlen(prefix) + strlen(namestr) + 1; if (dsdir != NULL) filenamelen += strlen(dsdir) + 1; filename = isc_mem_get(mctx, filenamelen); if (filename == NULL) fatal("out of memory"); if (dsdir != NULL) snprintf(filename, filenamelen, "%s/", dsdir); else filename[0] = 0; strlcat(filename, prefix, filenamelen); strlcat(filename, namestr, filenamelen); dns_diff_init(mctx, &diff); if (type == dns_rdatatype_dlv) { dns_name_t tname; unsigned int labels; dns_name_init(&tname, NULL); dns_fixedname_init(&fixed); name = dns_fixedname_name(&fixed); labels = dns_name_countlabels(gorigin); dns_name_getlabelsequence(gorigin, 0, labels - 1, &tname); result = dns_name_concatenate(&tname, dlv, name, NULL); check_result(result, "dns_name_concatenate"); } else name = gorigin; for (key = ISC_LIST_HEAD(keylist); key != NULL; key = ISC_LIST_NEXT(key, link)) { if (REVOKE(key->key)) continue; if (isksk(key)) { have_ksk = ISC_TRUE; have_non_ksk = ISC_FALSE; } else { have_ksk = ISC_FALSE; have_non_ksk = ISC_TRUE; } for (tmpkey = ISC_LIST_HEAD(keylist); tmpkey != NULL; tmpkey = ISC_LIST_NEXT(tmpkey, link)) { if (dst_key_alg(key->key) != dst_key_alg(tmpkey->key)) continue; if (REVOKE(tmpkey->key)) continue; if (isksk(tmpkey)) have_ksk = ISC_TRUE; else have_non_ksk = ISC_TRUE; } if (have_ksk && have_non_ksk && !isksk(key)) continue; dns_rdata_init(&rdata); dns_rdata_init(&ds); isc_buffer_init(&b, keybuf, sizeof(keybuf)); result = dst_key_todns(key->key, &b); check_result(result, "dst_key_todns"); isc_buffer_usedregion(&b, &r); dns_rdata_fromregion(&rdata, gclass, dns_rdatatype_dnskey, &r); if (type != dns_rdatatype_dnskey) { result = dns_ds_buildrdata(gorigin, &rdata, DNS_DSDIGEST_SHA1, dsbuf, &ds); check_result(result, "dns_ds_buildrdata"); if (type == dns_rdatatype_dlv) ds.type = dns_rdatatype_dlv; result = dns_difftuple_create(mctx, DNS_DIFFOP_ADDRESIGN, name, 0, &ds, &tuple); check_result(result, "dns_difftuple_create"); dns_diff_append(&diff, &tuple); dns_rdata_reset(&ds); result = dns_ds_buildrdata(gorigin, &rdata, DNS_DSDIGEST_SHA256, dsbuf, &ds); check_result(result, "dns_ds_buildrdata"); if (type == dns_rdatatype_dlv) ds.type = dns_rdatatype_dlv; result = dns_difftuple_create(mctx, DNS_DIFFOP_ADDRESIGN, name, 0, &ds, &tuple); } else result = dns_difftuple_create(mctx, DNS_DIFFOP_ADDRESIGN, gorigin, zone_soa_min_ttl, &rdata, &tuple); check_result(result, "dns_difftuple_create"); dns_diff_append(&diff, &tuple); } result = dns_db_create(mctx, "rbt", dns_rootname, dns_dbtype_zone, gclass, 0, NULL, &db); check_result(result, "dns_db_create"); result = dns_db_newversion(db, &dbversion); check_result(result, "dns_db_newversion"); result = dns_diff_apply(&diff, db, dbversion); check_result(result, "dns_diff_apply"); dns_diff_clear(&diff); result = dns_master_dump(mctx, db, dbversion, style, filename); check_result(result, "dns_master_dump"); isc_mem_put(mctx, filename, filenamelen); dns_db_closeversion(db, &dbversion, ISC_FALSE); dns_db_detach(&db); } static void print_time(FILE *fp) { time_t currenttime; if (outputformat != dns_masterformat_text) return; currenttime = time(NULL); fprintf(fp, "; File written on %s", ctime(¤ttime)); } static void print_version(FILE *fp) { if (outputformat != dns_masterformat_text) return; fprintf(fp, "; dnssec_signzone version " VERSION "\n"); } ISC_PLATFORM_NORETURN_PRE static void usage(void) ISC_PLATFORM_NORETURN_POST; static void usage(void) { fprintf(stderr, "Usage:\n"); fprintf(stderr, "\t%s [options] zonefile [keys]\n", program); fprintf(stderr, "\n"); fprintf(stderr, "Version: %s\n", VERSION); fprintf(stderr, "Options: (default value in parenthesis) \n"); fprintf(stderr, "\t-S:\tsmart signing: automatically finds key files\n" "\t\tfor the zone and determines how they are to " "be used\n"); fprintf(stderr, "\t-K directory:\n"); fprintf(stderr, "\t\tdirectory to find key files (.)\n"); fprintf(stderr, "\t-d directory:\n"); fprintf(stderr, "\t\tdirectory to find dsset-* files (.)\n"); fprintf(stderr, "\t-g:\t"); fprintf(stderr, "update DS records based on child zones' " "dsset-* files\n"); fprintf(stderr, "\t-s [YYYYMMDDHHMMSS|+offset]:\n"); fprintf(stderr, "\t\tRRSIG start time " "- absolute|offset (now - 1 hour)\n"); fprintf(stderr, "\t-e [YYYYMMDDHHMMSS|+offset|\"now\"+offset]:\n"); fprintf(stderr, "\t\tRRSIG end time " "- absolute|from start|from now " "(now + 30 days)\n"); fprintf(stderr, "\t-X [YYYYMMDDHHMMSS|+offset|\"now\"+offset]:\n"); fprintf(stderr, "\t\tDNSKEY RRSIG end " "- absolute|from start|from now " "(matches -e)\n"); fprintf(stderr, "\t-i interval:\n"); fprintf(stderr, "\t\tcycle interval - resign " "if < interval from end ( (end-start)/4 )\n"); fprintf(stderr, "\t-j jitter:\n"); fprintf(stderr, "\t\trandomize signature end time up to jitter seconds\n"); fprintf(stderr, "\t-v debuglevel (0)\n"); fprintf(stderr, "\t-V:\tprint version information\n"); fprintf(stderr, "\t-o origin:\n"); fprintf(stderr, "\t\tzone origin (name of zonefile)\n"); fprintf(stderr, "\t-f outfile:\n"); fprintf(stderr, "\t\tfile the signed zone is written in " "(zonefile + .signed)\n"); fprintf(stderr, "\t-I format:\n"); fprintf(stderr, "\t\tfile format of input zonefile (text)\n"); fprintf(stderr, "\t-O format:\n"); fprintf(stderr, "\t\tfile format of signed zone file (text)\n"); fprintf(stderr, "\t-N format:\n"); fprintf(stderr, "\t\tsoa serial format of signed zone file (keep)\n"); fprintf(stderr, "\t-D:\n"); fprintf(stderr, "\t\toutput only DNSSEC-related records\n"); fprintf(stderr, "\t-r randomdev:\n"); fprintf(stderr, "\t\ta file containing random data\n"); fprintf(stderr, "\t-a:\t"); fprintf(stderr, "verify generated signatures\n"); fprintf(stderr, "\t-c class (IN)\n"); fprintf(stderr, "\t-E engine:\n"); #if defined(PKCS11CRYPTO) fprintf(stderr, "\t\tpath to PKCS#11 provider library " "(default is %s)\n", PK11_LIB_LOCATION); #elif defined(USE_PKCS11) fprintf(stderr, "\t\tname of an OpenSSL engine to use " "(default is \"pkcs11\")\n"); #else fprintf(stderr, "\t\tname of an OpenSSL engine to use\n"); #endif fprintf(stderr, "\t-p:\t"); fprintf(stderr, "use pseudorandom data (faster but less secure)\n"); fprintf(stderr, "\t-P:\t"); fprintf(stderr, "disable post-sign verification\n"); fprintf(stderr, "\t-Q:\t"); fprintf(stderr, "remove signatures from keys that are no " "longer active\n"); fprintf(stderr, "\t-R:\t"); fprintf(stderr, "remove signatures from keys that no longer exist\n"); fprintf(stderr, "\t-T TTL:\tTTL for newly added DNSKEYs\n"); fprintf(stderr, "\t-t:\t"); fprintf(stderr, "print statistics\n"); fprintf(stderr, "\t-u:\t"); fprintf(stderr, "update or replace an existing NSEC/NSEC3 chain\n"); fprintf(stderr, "\t-x:\tsign DNSKEY record with KSKs only, not ZSKs\n"); fprintf(stderr, "\t-z:\tsign all records with KSKs\n"); fprintf(stderr, "\t-C:\tgenerate a keyset file, for compatibility\n" "\t\twith older versions of dnssec-signzone -g\n"); fprintf(stderr, "\t-n ncpus (number of cpus present)\n"); fprintf(stderr, "\t-k key_signing_key\n"); fprintf(stderr, "\t-l lookasidezone\n"); fprintf(stderr, "\t-3 NSEC3 salt\n"); fprintf(stderr, "\t-H NSEC3 iterations (10)\n"); fprintf(stderr, "\t-A NSEC3 optout\n"); fprintf(stderr, "\n"); fprintf(stderr, "Signing Keys: "); fprintf(stderr, "(default: all zone keys that have private keys)\n"); fprintf(stderr, "\tkeyfile (Kname+alg+tag)\n"); exit(0); } static void removetempfile(void) { if (removefile) isc_file_remove(tempfile); } static void print_stats(isc_time_t *timer_start, isc_time_t *timer_finish, isc_time_t *sign_start, isc_time_t *sign_finish) { isc_uint64_t time_us; /* Time in microseconds */ isc_uint64_t time_ms; /* Time in milliseconds */ isc_uint64_t sig_ms; /* Signatures per millisecond */ FILE *out = output_stdout ? stderr : stdout; fprintf(out, "Signatures generated: %10d\n", nsigned); fprintf(out, "Signatures retained: %10d\n", nretained); fprintf(out, "Signatures dropped: %10d\n", ndropped); fprintf(out, "Signatures successfully verified: %10d\n", nverified); fprintf(out, "Signatures unsuccessfully " "verified: %10d\n", nverifyfailed); time_us = isc_time_microdiff(sign_finish, sign_start); time_ms = time_us / 1000; fprintf(out, "Signing time in seconds: %7u.%03u\n", (unsigned int) (time_ms / 1000), (unsigned int) (time_ms % 1000)); if (time_us > 0) { sig_ms = ((isc_uint64_t)nsigned * 1000000000) / time_us; fprintf(out, "Signatures per second: %7u.%03u\n", (unsigned int) sig_ms / 1000, (unsigned int) sig_ms % 1000); } time_us = isc_time_microdiff(timer_finish, timer_start); time_ms = time_us / 1000; fprintf(out, "Runtime in seconds: %7u.%03u\n", (unsigned int) (time_ms / 1000), (unsigned int) (time_ms % 1000)); } int main(int argc, char *argv[]) { int i, ch; char *startstr = NULL, *endstr = NULL, *classname = NULL; char *dnskey_endstr = NULL; char *origin = NULL, *file = NULL, *output = NULL; char *inputformatstr = NULL, *outputformatstr = NULL; char *serialformatstr = NULL; char *dskeyfile[MAXDSKEYS]; int ndskeys = 0; char *endp; isc_time_t timer_start, timer_finish; isc_time_t sign_start, sign_finish; dns_dnsseckey_t *key; isc_result_t result; isc_log_t *log = NULL; isc_boolean_t pseudorandom = ISC_FALSE; #ifdef USE_PKCS11 const char *engine = PKCS11_ENGINE; #else const char *engine = NULL; #endif unsigned int eflags; isc_boolean_t free_output = ISC_FALSE; int tempfilelen = 0; dns_rdataclass_t rdclass; isc_task_t **tasks = NULL; isc_buffer_t b; int len; hashlist_t hashlist; isc_boolean_t make_keyset = ISC_FALSE; isc_boolean_t set_salt = ISC_FALSE; isc_boolean_t set_optout = ISC_FALSE; isc_boolean_t set_iter = ISC_FALSE; isc_boolean_t nonsecify = ISC_FALSE; /* Unused letters: Bb G J q Yy (and F is reserved). */ #define CMDLINE_FLAGS \ "3:AaCc:Dd:E:e:f:FghH:i:I:j:K:k:L:l:m:M:n:N:o:O:PpQRr:s:ST:tuUv:VX:xzZ:" /* * Process memory debugging argument first. */ while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) { switch (ch) { case 'm': if (strcasecmp(isc_commandline_argument, "record") == 0) isc_mem_debugging |= ISC_MEM_DEBUGRECORD; if (strcasecmp(isc_commandline_argument, "trace") == 0) isc_mem_debugging |= ISC_MEM_DEBUGTRACE; if (strcasecmp(isc_commandline_argument, "usage") == 0) isc_mem_debugging |= ISC_MEM_DEBUGUSAGE; if (strcasecmp(isc_commandline_argument, "size") == 0) isc_mem_debugging |= ISC_MEM_DEBUGSIZE; if (strcasecmp(isc_commandline_argument, "mctx") == 0) isc_mem_debugging |= ISC_MEM_DEBUGCTX; break; default: break; } } isc_commandline_reset = ISC_TRUE; #ifdef _WIN32 InitSockets(); #endif masterstyle = &dns_master_style_explicitttl; check_result(isc_app_start(), "isc_app_start"); result = isc_mem_create(0, 0, &mctx); if (result != ISC_R_SUCCESS) fatal("out of memory"); #ifdef PKCS11CRYPTO pk11_result_register(); #endif dns_result_register(); isc_commandline_errprint = ISC_FALSE; while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) { switch (ch) { case '3': set_salt = ISC_TRUE; nsec_datatype = dns_rdatatype_nsec3; if (strcmp(isc_commandline_argument, "-") != 0) { isc_buffer_t target; char *sarg; sarg = isc_commandline_argument; isc_buffer_init(&target, saltbuf, sizeof(saltbuf)); result = isc_hex_decodestring(sarg, &target); check_result(result, "isc_hex_decodestring(salt)"); salt_length = isc_buffer_usedlength(&target); } break; case 'A': set_optout = ISC_TRUE; if (OPTOUT(nsec3flags)) nsec3flags &= ~DNS_NSEC3FLAG_OPTOUT; else nsec3flags |= DNS_NSEC3FLAG_OPTOUT; break; case 'a': tryverify = ISC_TRUE; break; case 'C': make_keyset = ISC_TRUE; break; case 'c': classname = isc_commandline_argument; break; case 'd': dsdir = isc_commandline_argument; if (strlen(dsdir) == 0U) fatal("DS directory must be non-empty string"); result = try_dir(dsdir); if (result != ISC_R_SUCCESS) fatal("cannot open directory %s: %s", dsdir, isc_result_totext(result)); break; case 'D': output_dnssec_only = ISC_TRUE; break; case 'E': engine = isc_commandline_argument; break; case 'e': endstr = isc_commandline_argument; break; case 'f': output = isc_commandline_argument; if (strcmp(output, "-") == 0) output_stdout = ISC_TRUE; break; case 'g': generateds = ISC_TRUE; break; case 'H': set_iter = ISC_TRUE; nsec3iter = strtoul(isc_commandline_argument, &endp, 0); if (*endp != '\0') fatal("iterations must be numeric"); if (nsec3iter > 0xffffU) fatal("iterations too big"); break; case 'I': inputformatstr = isc_commandline_argument; break; case 'i': endp = NULL; cycle = strtol(isc_commandline_argument, &endp, 0); if (*endp != '\0' || cycle < 0) fatal("cycle period must be numeric and " "positive"); break; case 'j': endp = NULL; jitter = strtol(isc_commandline_argument, &endp, 0); if (*endp != '\0' || jitter < 0) fatal("jitter must be numeric and positive"); break; case 'K': directory = isc_commandline_argument; break; case 'k': if (ndskeys == MAXDSKEYS) fatal("too many key-signing keys specified"); dskeyfile[ndskeys++] = isc_commandline_argument; break; case 'L': snset = ISC_TRUE; endp = NULL; serialnum = strtol(isc_commandline_argument, &endp, 0); if (*endp != '\0') { fprintf(stderr, "source serial number " "must be numeric"); exit(1); } break; case 'l': len = strlen(isc_commandline_argument); isc_buffer_init(&b, isc_commandline_argument, len); isc_buffer_add(&b, len); dns_fixedname_init(&dlv_fixed); dlv = dns_fixedname_name(&dlv_fixed); result = dns_name_fromtext(dlv, &b, dns_rootname, 0, NULL); check_result(result, "dns_name_fromtext(dlv)"); break; case 'M': endp = NULL; set_maxttl = ISC_TRUE; maxttl = strtol(isc_commandline_argument, &endp, 0); if (*endp != '\0') { fprintf(stderr, "maximum TTL " "must be numeric"); exit(1); } break; case 'm': break; case 'N': serialformatstr = isc_commandline_argument; break; case 'n': endp = NULL; ntasks = strtol(isc_commandline_argument, &endp, 0); if (*endp != '\0' || ntasks > ISC_INT32_MAX) fatal("number of cpus must be numeric"); break; case 'O': outputformatstr = isc_commandline_argument; break; case 'o': origin = isc_commandline_argument; break; case 'P': disable_zone_check = ISC_TRUE; break; case 'p': pseudorandom = ISC_TRUE; break; case 'Q': remove_inactkeysigs = ISC_TRUE; break; case 'R': remove_orphansigs = ISC_TRUE; break; case 'r': setup_entropy(mctx, isc_commandline_argument, &ectx); break; case 'S': smartsign = ISC_TRUE; break; case 's': startstr = isc_commandline_argument; break; case 'T': endp = NULL; set_keyttl = ISC_TRUE; keyttl = strtottl(isc_commandline_argument); break; case 't': printstats = ISC_TRUE; break; case 'U': /* Undocumented for testing only. */ unknownalg = ISC_TRUE; break; case 'u': update_chain = ISC_TRUE; break; case 'v': endp = NULL; verbose = strtol(isc_commandline_argument, &endp, 0); if (*endp != '\0') fatal("verbose level must be numeric"); break; case 'X': dnskey_endstr = isc_commandline_argument; break; case 'x': keyset_kskonly = ISC_TRUE; break; case 'z': ignore_kskflag = ISC_TRUE; break; case 'F': /* Reserved for FIPS mode */ /* FALLTHROUGH */ case '?': if (isc_commandline_option != '?') fprintf(stderr, "%s: invalid argument -%c\n", program, isc_commandline_option); /* FALLTHROUGH */ case 'h': /* Does not return. */ usage(); case 'V': /* Does not return. */ version(program); case 'Z': /* Undocumented test options */ if (!strcmp(isc_commandline_argument, "nonsecify")) nonsecify = ISC_TRUE; break; default: fprintf(stderr, "%s: unhandled option -%c\n", program, isc_commandline_option); exit(1); } } if (ectx == NULL) setup_entropy(mctx, NULL, &ectx); eflags = ISC_ENTROPY_BLOCKING; if (!pseudorandom) eflags |= ISC_ENTROPY_GOODONLY; result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE); if (result != ISC_R_SUCCESS) fatal("could not create hash context"); result = dst_lib_init2(mctx, ectx, engine, eflags); if (result != ISC_R_SUCCESS) fatal("could not initialize dst: %s", isc_result_totext(result)); isc_stdtime_get(&now); if (startstr != NULL) { starttime = strtotime(startstr, now, now, NULL); } else starttime = now - 3600; /* Allow for some clock skew. */ if (endstr != NULL) endtime = strtotime(endstr, now, starttime, NULL); else endtime = starttime + (30 * 24 * 60 * 60); if (dnskey_endstr != NULL) { dnskey_endtime = strtotime(dnskey_endstr, now, starttime, NULL); if (endstr != NULL && dnskey_endtime == endtime) fprintf(stderr, "WARNING: -e and -X were both set, " "but have identical values.\n"); } else dnskey_endtime = endtime; if (cycle == -1) cycle = (endtime - starttime) / 4; if (ntasks == 0) ntasks = isc_os_ncpus() * 2; vbprintf(4, "using %d cpus\n", ntasks); rdclass = strtoclass(classname); if (directory == NULL) directory = "."; setup_logging(mctx, &log); argc -= isc_commandline_index; argv += isc_commandline_index; if (argc < 1) usage(); file = argv[0]; argc -= 1; argv += 1; if (origin == NULL) origin = file; if (output == NULL) { size_t size; free_output = ISC_TRUE; size = strlen(file) + strlen(".signed") + 1; output = isc_mem_allocate(mctx, size); if (output == NULL) fatal("out of memory"); snprintf(output, size, "%s.signed", file); } if (inputformatstr != NULL) { if (strcasecmp(inputformatstr, "text") == 0) inputformat = dns_masterformat_text; else if (strcasecmp(inputformatstr, "map") == 0) inputformat = dns_masterformat_map; else if (strcasecmp(inputformatstr, "raw") == 0) inputformat = dns_masterformat_raw; else if (strncasecmp(inputformatstr, "raw=", 4) == 0) { inputformat = dns_masterformat_raw; fprintf(stderr, "WARNING: input format version ignored\n"); } else fatal("unknown file format: %s", inputformatstr); } if (outputformatstr != NULL) { if (strcasecmp(outputformatstr, "text") == 0) { outputformat = dns_masterformat_text; } else if (strcasecmp(outputformatstr, "full") == 0) { outputformat = dns_masterformat_text; masterstyle = &dns_master_style_full; } else if (strcasecmp(outputformatstr, "map") == 0) { outputformat = dns_masterformat_map; } else if (strcasecmp(outputformatstr, "raw") == 0) { outputformat = dns_masterformat_raw; } else if (strncasecmp(outputformatstr, "raw=", 4) == 0) { char *end; outputformat = dns_masterformat_raw; outputformat = dns_masterformat_raw; rawversion = strtol(outputformatstr + 4, &end, 10); if (end == outputformatstr + 4 || *end != '\0' || rawversion > 1U) { fprintf(stderr, "unknown raw format version\n"); exit(1); } } else fatal("unknown file format: %s", outputformatstr); } if (serialformatstr != NULL) { if (strcasecmp(serialformatstr, "keep") == 0) serialformat = SOA_SERIAL_KEEP; else if (strcasecmp(serialformatstr, "increment") == 0 || strcasecmp(serialformatstr, "incr") == 0) serialformat = SOA_SERIAL_INCREMENT; else if (strcasecmp(serialformatstr, "unixtime") == 0) serialformat = SOA_SERIAL_UNIXTIME; else if (strcasecmp(serialformatstr, "date") == 0) serialformat = SOA_SERIAL_DATE; else fatal("unknown soa serial format: %s", serialformatstr); } if (output_dnssec_only && outputformat != dns_masterformat_text) fatal("option -D can only be used with \"-O text\""); if (output_dnssec_only && serialformat != SOA_SERIAL_KEEP) fatal("option -D can only be used with \"-N keep\""); if (output_dnssec_only && set_maxttl) fatal("option -D cannot be used with -M"); result = dns_master_stylecreate(&dsstyle, DNS_STYLEFLAG_NO_TTL, 0, 24, 0, 0, 0, 8, mctx); check_result(result, "dns_master_stylecreate"); gdb = NULL; TIME_NOW(&timer_start); loadzone(file, origin, rdclass, &gdb); gorigin = dns_db_origin(gdb); gclass = dns_db_class(gdb); get_soa_ttls(); if (set_maxttl && set_keyttl && keyttl > maxttl) { fprintf(stderr, "%s: warning: Specified key TTL %d " "exceeds maximum zone TTL; reducing to %d\n", program, keyttl, maxttl); keyttl = maxttl; } if (!set_keyttl) keyttl = soa_ttl; /* * Check for any existing NSEC3 parameters in the zone, * and use them as defaults if -u was not specified. */ if (update_chain && !set_optout && !set_iter && !set_salt) nsec_datatype = dns_rdatatype_nsec; else set_nsec3params(update_chain, set_salt, set_optout, set_iter); /* * We need to do this early on, as we start messing with the list * of keys rather early. */ ISC_LIST_INIT(keylist); result = isc_rwlock_init(&keylist_lock, 0, 0); if (result != ISC_R_SUCCESS) fatal("could not initialize keylist_lock: %s", isc_result_totext(result)); /* * Fill keylist with: * 1) Keys listed in the DNSKEY set that have * private keys associated, *if* no keys were * set on the command line. * 2) ZSKs set on the command line * 3) KSKs set on the command line * 4) Any keys remaining in the DNSKEY set which * do not have private keys associated and were * not specified on the command line. */ if (argc == 0 || smartsign) loadzonekeys(!smartsign, ISC_FALSE); loadexplicitkeys(argv, argc, ISC_FALSE); loadexplicitkeys(dskeyfile, ndskeys, ISC_TRUE); loadzonekeys(!smartsign, ISC_TRUE); /* * If we're doing smart signing, look in the key repository for * key files with metadata, and merge them with the keylist * we have now. */ if (smartsign) build_final_keylist(); /* Now enumerate the key list */ for (key = ISC_LIST_HEAD(keylist); key != NULL; key = ISC_LIST_NEXT(key, link)) { key->index = keycount++; } if (keycount == 0) { if (disable_zone_check) fprintf(stderr, "%s: warning: No keys specified " "or found\n", program); else fatal("No signing keys specified or found."); nokeys = ISC_TRUE; } warnifallksk(gdb); if (IS_NSEC3) { unsigned int max; isc_boolean_t answer; hash_length = dns_nsec3_hashlength(dns_hash_sha1); hashlist_init(&hashlist, dns_db_nodecount(gdb) * 2, hash_length); result = dns_nsec_nseconly(gdb, gversion, &answer); if (result == ISC_R_NOTFOUND) fprintf(stderr, "%s: warning: NSEC3 generation " "requested with no DNSKEY; ignoring\n", program); else if (result != ISC_R_SUCCESS) check_result(result, "dns_nsec_nseconly"); else if (answer) fatal("NSEC3 generation requested with " "NSEC-only DNSKEY"); result = dns_nsec3_maxiterations(gdb, NULL, mctx, &max); check_result(result, "dns_nsec3_maxiterations()"); if (nsec3iter > max) fatal("NSEC3 iterations too big for weakest DNSKEY " "strength. Maximum iterations allowed %u.", max); } else { hashlist_init(&hashlist, 0, 0); /* silence clang */ } gversion = NULL; result = dns_db_newversion(gdb, &gversion); check_result(result, "dns_db_newversion()"); switch (serialformat) { case SOA_SERIAL_INCREMENT: setsoaserial(0, dns_updatemethod_increment); break; case SOA_SERIAL_UNIXTIME: setsoaserial(now, dns_updatemethod_unixtime); break; case SOA_SERIAL_DATE: setsoaserial(now, dns_updatemethod_date); break; case SOA_SERIAL_KEEP: default: /* do nothing */ break; } /* Remove duplicates and cap TTLs at maxttl */ cleanup_zone(); if (!nonsecify) { if (IS_NSEC3) nsec3ify(dns_hash_sha1, nsec3iter, gsalt, salt_length, &hashlist); else nsecify(); } if (!nokeys) { writeset("dsset-", dns_rdatatype_ds); if (make_keyset) writeset("keyset-", dns_rdatatype_dnskey); if (dlv != NULL) { writeset("dlvset-", dns_rdatatype_dlv); } } if (output_stdout) { outfp = stdout; if (outputformatstr == NULL) masterstyle = &dns_master_style_full; } else { tempfilelen = strlen(output) + 20; tempfile = isc_mem_get(mctx, tempfilelen); if (tempfile == NULL) fatal("out of memory"); result = isc_file_mktemplate(output, tempfile, tempfilelen); check_result(result, "isc_file_mktemplate"); if (outputformat == dns_masterformat_text) result = isc_file_openunique(tempfile, &outfp); else result = isc_file_bopenunique(tempfile, &outfp); if (result != ISC_R_SUCCESS) fatal("failed to open temporary output file: %s", isc_result_totext(result)); removefile = ISC_TRUE; setfatalcallback(&removetempfile); } print_time(outfp); print_version(outfp); result = isc_taskmgr_create(mctx, ntasks, 0, &taskmgr); if (result != ISC_R_SUCCESS) fatal("failed to create task manager: %s", isc_result_totext(result)); master = NULL; result = isc_task_create(taskmgr, 0, &master); if (result != ISC_R_SUCCESS) fatal("failed to create task: %s", isc_result_totext(result)); tasks = isc_mem_get(mctx, ntasks * sizeof(isc_task_t *)); if (tasks == NULL) fatal("out of memory"); for (i = 0; i < (int)ntasks; i++) { tasks[i] = NULL; result = isc_task_create(taskmgr, 0, &tasks[i]); if (result != ISC_R_SUCCESS) fatal("failed to create task: %s", isc_result_totext(result)); } RUNTIME_CHECK(isc_mutex_init(&namelock) == ISC_R_SUCCESS); if (printstats) RUNTIME_CHECK(isc_mutex_init(&statslock) == ISC_R_SUCCESS); presign(); TIME_NOW(&sign_start); signapex(); if (!finished) { /* * There is more work to do. Spread it out over multiple * processors if possible. */ for (i = 0; i < (int)ntasks; i++) { result = isc_app_onrun(mctx, master, startworker, tasks[i]); if (result != ISC_R_SUCCESS) fatal("failed to start task: %s", isc_result_totext(result)); } (void)isc_app_run(); if (!finished) fatal("process aborted by user"); } else isc_task_detach(&master); shuttingdown = ISC_TRUE; for (i = 0; i < (int)ntasks; i++) isc_task_detach(&tasks[i]); isc_taskmgr_destroy(&taskmgr); isc_mem_put(mctx, tasks, ntasks * sizeof(isc_task_t *)); postsign(); TIME_NOW(&sign_finish); if (!disable_zone_check) verifyzone(gdb, gversion, gorigin, mctx, ignore_kskflag, keyset_kskonly); if (outputformat != dns_masterformat_text) { dns_masterrawheader_t header; dns_master_initrawheader(&header); if (rawversion == 0U) header.flags = DNS_MASTERRAW_COMPAT; else if (snset) { header.flags = DNS_MASTERRAW_SOURCESERIALSET; header.sourceserial = serialnum; } result = dns_master_dumptostream3(mctx, gdb, gversion, masterstyle, outputformat, &header, outfp); check_result(result, "dns_master_dumptostream3"); } DESTROYLOCK(&namelock); if (printstats) DESTROYLOCK(&statslock); if (!output_stdout) { result = isc_stdio_close(outfp); check_result(result, "isc_stdio_close"); removefile = ISC_FALSE; result = isc_file_rename(tempfile, output); if (result != ISC_R_SUCCESS) fatal("failed to rename temp file to %s: %s", output, isc_result_totext(result)); printf("%s\n", output); } dns_db_closeversion(gdb, &gversion, ISC_FALSE); dns_db_detach(&gdb); hashlist_free(&hashlist); while (!ISC_LIST_EMPTY(keylist)) { key = ISC_LIST_HEAD(keylist); ISC_LIST_UNLINK(keylist, key, link); dns_dnsseckey_destroy(mctx, &key); } if (tempfilelen != 0) isc_mem_put(mctx, tempfile, tempfilelen); if (free_output) isc_mem_free(mctx, output); dns_master_styledestroy(&dsstyle, mctx); cleanup_logging(&log); dst_lib_destroy(); isc_hash_destroy(); cleanup_entropy(&ectx); dns_name_destroy(); if (verbose > 10) isc_mem_stats(mctx, stdout); isc_mem_destroy(&mctx); (void) isc_app_finish(); if (printstats) { TIME_NOW(&timer_finish); print_stats(&timer_start, &timer_finish, &sign_start, &sign_finish); } #ifdef _WIN32 DestroySockets(); #endif return (0); } bind9-9.11.3+dfsg/bin/dnssec/dnssec-signzone.docbook000066400000000000000000001002641325250447100222410ustar00rootroot00000000000000 2014-02-18 ISC Internet Systems Consortium, Inc. dnssec-signzone 8 BIND9 dnssec-signzone DNSSEC zone signing tool 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2011 2012 2013 2014 2015 2016 2017 Internet Systems Consortium, Inc. ("ISC") dnssec-signzone zonefile key DESCRIPTION dnssec-signzone signs a zone. It generates NSEC and RRSIG records and produces a signed version of the zone. The security status of delegations from the signed zone (that is, whether the child zones are secure or not) is determined by the presence or absence of a keyset file for each child zone. OPTIONS -a Verify all generated signatures. -c class Specifies the DNS class of the zone. -C Compatibility mode: Generate a keyset-zonename file in addition to dsset-zonename when signing a zone, for use by older versions of dnssec-signzone. -d directory Look for dsset- or keyset- files in . -D Output only those record types automatically managed by dnssec-signzone, i.e. RRSIG, NSEC, NSEC3 and NSEC3PARAM records. If smart signing () is used, DNSKEY records are also included. The resulting file can be included in the original zone file with $INCLUDE. This option cannot be combined with , , or serial number updating. -E engine When applicable, specifies the hardware to use for cryptographic operations, such as a secure key store used for signing. When BIND is built with OpenSSL PKCS#11 support, this defaults to the string "pkcs11", which identifies an OpenSSL engine that can drive a cryptographic accelerator or hardware service module. When BIND is built with native PKCS#11 cryptography (--enable-native-pkcs11), it defaults to the path of the PKCS#11 provider library specified via "--with-pkcs11". -g Generate DS records for child zones from dsset- or keyset- file. Existing DS records will be removed. -K directory Key repository: Specify a directory to search for DNSSEC keys. If not specified, defaults to the current directory. -k key Treat specified key as a key signing key ignoring any key flags. This option may be specified multiple times. -l domain Generate a DLV set in addition to the key (DNSKEY) and DS sets. The domain is appended to the name of the records. -M maxttl Sets the maximum TTL for the signed zone. Any TTL higher than maxttl in the input zone will be reduced to maxttl in the output. This provides certainty as to the largest possible TTL in the signed zone, which is useful to know when rolling keys because it is the longest possible time before signatures that have been retrieved by resolvers will expire from resolver caches. Zones that are signed with this option should be configured to use a matching in named.conf. (Note: This option is incompatible with , because it modifies non-DNSSEC data in the output zone.) -s start-time Specify the date and time when the generated RRSIG records become valid. This can be either an absolute or relative time. An absolute start time is indicated by a number in YYYYMMDDHHMMSS notation; 20000530144500 denotes 14:45:00 UTC on May 30th, 2000. A relative start time is indicated by +N, which is N seconds from the current time. If no is specified, the current time minus 1 hour (to allow for clock skew) is used. -e end-time Specify the date and time when the generated RRSIG records expire. As with , an absolute time is indicated in YYYYMMDDHHMMSS notation. A time relative to the start time is indicated with +N, which is N seconds from the start time. A time relative to the current time is indicated with now+N. If no is specified, 30 days from the start time is used as a default. must be later than . -X extended end-time Specify the date and time when the generated RRSIG records for the DNSKEY RRset will expire. This is to be used in cases when the DNSKEY signatures need to persist longer than signatures on other records; e.g., when the private component of the KSK is kept offline and the KSK signature is to be refreshed manually. As with , an absolute time is indicated in YYYYMMDDHHMMSS notation. A time relative to the start time is indicated with +N, which is N seconds from the start time. A time relative to the current time is indicated with now+N. If no is specified, the value of is used as the default. (, in turn, defaults to 30 days from the start time.) must be later than . -f output-file The name of the output file containing the signed zone. The default is to append .signed to the input filename. If is set to "-", then the signed zone is written to the standard output, with a default output format of "full". -h Prints a short summary of the options and arguments to dnssec-signzone. -V Prints version information. -i interval When a previously-signed zone is passed as input, records may be resigned. The option specifies the cycle interval as an offset from the current time (in seconds). If a RRSIG record expires after the cycle interval, it is retained. Otherwise, it is considered to be expiring soon, and it will be replaced. The default cycle interval is one quarter of the difference between the signature end and start times. So if neither or are specified, dnssec-signzone generates signatures that are valid for 30 days, with a cycle interval of 7.5 days. Therefore, if any existing RRSIG records are due to expire in less than 7.5 days, they would be replaced. -I input-format The format of the input zone file. Possible formats are "text" (default), "raw", and "map". This option is primarily intended to be used for dynamic signed zones so that the dumped zone file in a non-text format containing updates can be signed directly. The use of this option does not make much sense for non-dynamic zones. -j jitter When signing a zone with a fixed signature lifetime, all RRSIG records issued at the time of signing expires simultaneously. If the zone is incrementally signed, i.e. a previously-signed zone is passed as input to the signer, all expired signatures have to be regenerated at about the same time. The option specifies a jitter window that will be used to randomize the signature expire time, thus spreading incremental signature regeneration over time. Signature lifetime jitter also to some extent benefits validators and servers by spreading out cache expiration, i.e. if large numbers of RRSIGs don't expire at the same time from all caches there will be less congestion than if all validators need to refetch at mostly the same time. -L serial When writing a signed zone to "raw" or "map" format, set the "source serial" value in the header to the specified serial number. (This is expected to be used primarily for testing purposes.) -n ncpus Specifies the number of threads to use. By default, one thread is started for each detected CPU. -N soa-serial-format The SOA serial number format of the signed zone. Possible formats are "keep" (default), "increment", "unixtime", and "date". "keep" Do not modify the SOA serial number. "increment" Increment the SOA serial number using RFC 1982 arithmetics. "unixtime" Set the SOA serial number to the number of seconds since epoch. "date" Set the SOA serial number to today's date in YYYYMMDDNN format. -o origin The zone origin. If not specified, the name of the zone file is assumed to be the origin. -O output-format The format of the output file containing the signed zone. Possible formats are "text" (default), which is the standard textual representation of the zone; "full", which is text output in a format suitable for processing by external scripts; and "map", "raw", and "raw=N", which store the zone in binary formats for rapid loading by named. "raw=N" specifies the format version of the raw zone file: if N is 0, the raw file can be read by any version of named; if N is 1, the file can be read by release 9.9.0 or higher; the default is 1. -p Use pseudo-random data when signing the zone. This is faster, but less secure, than using real random data. This option may be useful when signing large zones or when the entropy source is limited. -P Disable post sign verification tests. The post sign verification test ensures that for each algorithm in use there is at least one non revoked self signed KSK key, that all revoked KSK keys are self signed, and that all records in the zone are signed by the algorithm. This option skips these tests. -Q Remove signatures from keys that are no longer active. Normally, when a previously-signed zone is passed as input to the signer, and a DNSKEY record has been removed and replaced with a new one, signatures from the old key that are still within their validity period are retained. This allows the zone to continue to validate with cached copies of the old DNSKEY RRset. The forces dnssec-signzone to remove signatures from keys that are no longer active. This enables ZSK rollover using the procedure described in RFC 4641, section 4.2.1.1 ("Pre-Publish Key Rollover"). -R Remove signatures from keys that are no longer published. This option is similar to , except it forces dnssec-signzone to signatures from keys that are no longer published. This enables ZSK rollover using the procedure described in RFC 4641, section 4.2.1.2 ("Double Signature Zone Signing Key Rollover"). -r randomdev Specifies the source of randomness. If the operating system does not provide a /dev/random or equivalent device, the default source of randomness is keyboard input. randomdev specifies the name of a character device or file containing random data to be used instead of the default. The special value keyboard indicates that keyboard input should be used. -S Smart signing: Instructs dnssec-signzone to search the key repository for keys that match the zone being signed, and to include them in the zone if appropriate. When a key is found, its timing metadata is examined to determine how it should be used, according to the following rules. Each successive rule takes priority over the prior ones: If no timing metadata has been set for the key, the key is published in the zone and used to sign the zone. If the key's publication date is set and is in the past, the key is published in the zone. If the key's activation date is set and in the past, the key is published (regardless of publication date) and used to sign the zone. If the key's revocation date is set and in the past, and the key is published, then the key is revoked, and the revoked key is used to sign the zone. If either of the key's unpublication or deletion dates are set and in the past, the key is NOT published or used to sign the zone, regardless of any other metadata. -T ttl Specifies a TTL to be used for new DNSKEY records imported into the zone from the key repository. If not specified, the default is the TTL value from the zone's SOA record. This option is ignored when signing without , since DNSKEY records are not imported from the key repository in that case. It is also ignored if there are any pre-existing DNSKEY records at the zone apex, in which case new records' TTL values will be set to match them, or if any of the imported DNSKEY records had a default TTL value. In the event of a a conflict between TTL values in imported keys, the shortest one is used. -t Print statistics at completion. -u Update NSEC/NSEC3 chain when re-signing a previously signed zone. With this option, a zone signed with NSEC can be switched to NSEC3, or a zone signed with NSEC3 can be switch to NSEC or to NSEC3 with different parameters. Without this option, dnssec-signzone will retain the existing chain when re-signing. -v level Sets the debugging level. -x Only sign the DNSKEY RRset with key-signing keys, and omit signatures from zone-signing keys. (This is similar to the dnssec-dnskey-kskonly yes; zone option in named.) -z Ignore KSK flag on key when determining what to sign. This causes KSK-flagged keys to sign all records, not just the DNSKEY RRset. (This is similar to the update-check-ksk no; zone option in named.) -3 salt Generate an NSEC3 chain with the given hex encoded salt. A dash (salt) can be used to indicate that no salt is to be used when generating the NSEC3 chain. -H iterations When generating an NSEC3 chain, use this many iterations. The default is 10. -A When generating an NSEC3 chain set the OPTOUT flag on all NSEC3 records and do not generate NSEC3 records for insecure delegations. Using this option twice (i.e., ) turns the OPTOUT flag off for all records. This is useful when using the option to modify an NSEC3 chain which previously had OPTOUT set. zonefile The file containing the zone to be signed. key Specify which keys should be used to sign the zone. If no keys are specified, then the zone will be examined for DNSKEY records at the zone apex. If these are found and there are matching private keys, in the current directory, then these will be used for signing. EXAMPLE The following command signs the example.com zone with the DSA key generated by dnssec-keygen (Kexample.com.+003+17247). Because the -S option is not being used, the zone's keys must be in the master file (db.example.com). This invocation looks for dsset files, in the current directory, so that DS records can be imported from them (-g). % dnssec-signzone -g -o example.com db.example.com \ Kexample.com.+003+17247 db.example.com.signed % In the above example, dnssec-signzone creates the file db.example.com.signed. This file should be referenced in a zone statement in a named.conf file. This example re-signs a previously signed zone with default parameters. The private keys are assumed to be in the current directory. % cp db.example.com.signed db.example.com % dnssec-signzone -o example.com db.example.com db.example.com.signed % SEE ALSO dnssec-keygen8 , BIND 9 Administrator Reference Manual, RFC 4033, RFC 4641. bind9-9.11.3+dfsg/bin/dnssec/dnssec-signzone.html000066400000000000000000000723311325250447100215700ustar00rootroot00000000000000 dnssec-signzone

Name

dnssec-signzone — DNSSEC zone signing tool

Synopsis

dnssec-signzone [-a] [-c class] [-d directory] [-D] [-E engine] [-e end-time] [-f output-file] [-g] [-h] [-i interval] [-I input-format] [-j jitter] [-K directory] [-k key] [-L serial] [-l domain] [-M maxttl] [-N soa-serial-format] [-o origin] [-O output-format] [-P] [-p] [-Q] [-R] [-r randomdev] [-S] [-s start-time] [-T ttl] [-t] [-u] [-v level] [-V] [-X extended end-time] [-x] [-z] [-3 salt] [-H iterations] [-A] {zonefile} [key...]

DESCRIPTION

dnssec-signzone signs a zone. It generates NSEC and RRSIG records and produces a signed version of the zone. The security status of delegations from the signed zone (that is, whether the child zones are secure or not) is determined by the presence or absence of a keyset file for each child zone.

OPTIONS

-a

Verify all generated signatures.

-c class

Specifies the DNS class of the zone.

-C

Compatibility mode: Generate a keyset-zonename file in addition to dsset-zonename when signing a zone, for use by older versions of dnssec-signzone.

-d directory

Look for dsset- or keyset- files in directory.

-D

Output only those record types automatically managed by dnssec-signzone, i.e. RRSIG, NSEC, NSEC3 and NSEC3PARAM records. If smart signing (-S) is used, DNSKEY records are also included. The resulting file can be included in the original zone file with $INCLUDE. This option cannot be combined with -O raw, -O map, or serial number updating.

-E engine

When applicable, specifies the hardware to use for cryptographic operations, such as a secure key store used for signing.

When BIND is built with OpenSSL PKCS#11 support, this defaults to the string "pkcs11", which identifies an OpenSSL engine that can drive a cryptographic accelerator or hardware service module. When BIND is built with native PKCS#11 cryptography (--enable-native-pkcs11), it defaults to the path of the PKCS#11 provider library specified via "--with-pkcs11".

-g

Generate DS records for child zones from dsset- or keyset- file. Existing DS records will be removed.

-K directory

Key repository: Specify a directory to search for DNSSEC keys. If not specified, defaults to the current directory.

-k key

Treat specified key as a key signing key ignoring any key flags. This option may be specified multiple times.

-l domain

Generate a DLV set in addition to the key (DNSKEY) and DS sets. The domain is appended to the name of the records.

-M maxttl

Sets the maximum TTL for the signed zone. Any TTL higher than maxttl in the input zone will be reduced to maxttl in the output. This provides certainty as to the largest possible TTL in the signed zone, which is useful to know when rolling keys because it is the longest possible time before signatures that have been retrieved by resolvers will expire from resolver caches. Zones that are signed with this option should be configured to use a matching max-zone-ttl in named.conf. (Note: This option is incompatible with -D, because it modifies non-DNSSEC data in the output zone.)

-s start-time

Specify the date and time when the generated RRSIG records become valid. This can be either an absolute or relative time. An absolute start time is indicated by a number in YYYYMMDDHHMMSS notation; 20000530144500 denotes 14:45:00 UTC on May 30th, 2000. A relative start time is indicated by +N, which is N seconds from the current time. If no start-time is specified, the current time minus 1 hour (to allow for clock skew) is used.

-e end-time

Specify the date and time when the generated RRSIG records expire. As with start-time, an absolute time is indicated in YYYYMMDDHHMMSS notation. A time relative to the start time is indicated with +N, which is N seconds from the start time. A time relative to the current time is indicated with now+N. If no end-time is specified, 30 days from the start time is used as a default. end-time must be later than start-time.

-X extended end-time

Specify the date and time when the generated RRSIG records for the DNSKEY RRset will expire. This is to be used in cases when the DNSKEY signatures need to persist longer than signatures on other records; e.g., when the private component of the KSK is kept offline and the KSK signature is to be refreshed manually.

As with start-time, an absolute time is indicated in YYYYMMDDHHMMSS notation. A time relative to the start time is indicated with +N, which is N seconds from the start time. A time relative to the current time is indicated with now+N. If no extended end-time is specified, the value of end-time is used as the default. (end-time, in turn, defaults to 30 days from the start time.) extended end-time must be later than start-time.

-f output-file

The name of the output file containing the signed zone. The default is to append .signed to the input filename. If output-file is set to "-", then the signed zone is written to the standard output, with a default output format of "full".

-h

Prints a short summary of the options and arguments to dnssec-signzone.

-V

Prints version information.

-i interval

When a previously-signed zone is passed as input, records may be resigned. The interval option specifies the cycle interval as an offset from the current time (in seconds). If a RRSIG record expires after the cycle interval, it is retained. Otherwise, it is considered to be expiring soon, and it will be replaced.

The default cycle interval is one quarter of the difference between the signature end and start times. So if neither end-time or start-time are specified, dnssec-signzone generates signatures that are valid for 30 days, with a cycle interval of 7.5 days. Therefore, if any existing RRSIG records are due to expire in less than 7.5 days, they would be replaced.

-I input-format

The format of the input zone file. Possible formats are "text" (default), "raw", and "map". This option is primarily intended to be used for dynamic signed zones so that the dumped zone file in a non-text format containing updates can be signed directly. The use of this option does not make much sense for non-dynamic zones.

-j jitter

When signing a zone with a fixed signature lifetime, all RRSIG records issued at the time of signing expires simultaneously. If the zone is incrementally signed, i.e. a previously-signed zone is passed as input to the signer, all expired signatures have to be regenerated at about the same time. The jitter option specifies a jitter window that will be used to randomize the signature expire time, thus spreading incremental signature regeneration over time.

Signature lifetime jitter also to some extent benefits validators and servers by spreading out cache expiration, i.e. if large numbers of RRSIGs don't expire at the same time from all caches there will be less congestion than if all validators need to refetch at mostly the same time.

-L serial

When writing a signed zone to "raw" or "map" format, set the "source serial" value in the header to the specified serial number. (This is expected to be used primarily for testing purposes.)

-n ncpus

Specifies the number of threads to use. By default, one thread is started for each detected CPU.

-N soa-serial-format

The SOA serial number format of the signed zone. Possible formats are "keep" (default), "increment", "unixtime", and "date".

"keep"

Do not modify the SOA serial number.

"increment"

Increment the SOA serial number using RFC 1982 arithmetics.

"unixtime"

Set the SOA serial number to the number of seconds since epoch.

"date"

Set the SOA serial number to today's date in YYYYMMDDNN format.

-o origin

The zone origin. If not specified, the name of the zone file is assumed to be the origin.

-O output-format

The format of the output file containing the signed zone. Possible formats are "text" (default), which is the standard textual representation of the zone; "full", which is text output in a format suitable for processing by external scripts; and "map", "raw", and "raw=N", which store the zone in binary formats for rapid loading by named. "raw=N" specifies the format version of the raw zone file: if N is 0, the raw file can be read by any version of named; if N is 1, the file can be read by release 9.9.0 or higher; the default is 1.

-p

Use pseudo-random data when signing the zone. This is faster, but less secure, than using real random data. This option may be useful when signing large zones or when the entropy source is limited.

-P

Disable post sign verification tests.

The post sign verification test ensures that for each algorithm in use there is at least one non revoked self signed KSK key, that all revoked KSK keys are self signed, and that all records in the zone are signed by the algorithm. This option skips these tests.

-Q

Remove signatures from keys that are no longer active.

Normally, when a previously-signed zone is passed as input to the signer, and a DNSKEY record has been removed and replaced with a new one, signatures from the old key that are still within their validity period are retained. This allows the zone to continue to validate with cached copies of the old DNSKEY RRset. The -Q forces dnssec-signzone to remove signatures from keys that are no longer active. This enables ZSK rollover using the procedure described in RFC 4641, section 4.2.1.1 ("Pre-Publish Key Rollover").

-R

Remove signatures from keys that are no longer published.

This option is similar to -Q, except it forces dnssec-signzone to signatures from keys that are no longer published. This enables ZSK rollover using the procedure described in RFC 4641, section 4.2.1.2 ("Double Signature Zone Signing Key Rollover").

-r randomdev

Specifies the source of randomness. If the operating system does not provide a /dev/random or equivalent device, the default source of randomness is keyboard input. randomdev specifies the name of a character device or file containing random data to be used instead of the default. The special value keyboard indicates that keyboard input should be used.

-S

Smart signing: Instructs dnssec-signzone to search the key repository for keys that match the zone being signed, and to include them in the zone if appropriate.

When a key is found, its timing metadata is examined to determine how it should be used, according to the following rules. Each successive rule takes priority over the prior ones:

If no timing metadata has been set for the key, the key is published in the zone and used to sign the zone.

If the key's publication date is set and is in the past, the key is published in the zone.

If the key's activation date is set and in the past, the key is published (regardless of publication date) and used to sign the zone.

If the key's revocation date is set and in the past, and the key is published, then the key is revoked, and the revoked key is used to sign the zone.

If either of the key's unpublication or deletion dates are set and in the past, the key is NOT published or used to sign the zone, regardless of any other metadata.

-T ttl

Specifies a TTL to be used for new DNSKEY records imported into the zone from the key repository. If not specified, the default is the TTL value from the zone's SOA record. This option is ignored when signing without -S, since DNSKEY records are not imported from the key repository in that case. It is also ignored if there are any pre-existing DNSKEY records at the zone apex, in which case new records' TTL values will be set to match them, or if any of the imported DNSKEY records had a default TTL value. In the event of a a conflict between TTL values in imported keys, the shortest one is used.

-t

Print statistics at completion.

-u

Update NSEC/NSEC3 chain when re-signing a previously signed zone. With this option, a zone signed with NSEC can be switched to NSEC3, or a zone signed with NSEC3 can be switch to NSEC or to NSEC3 with different parameters. Without this option, dnssec-signzone will retain the existing chain when re-signing.

-v level

Sets the debugging level.

-x

Only sign the DNSKEY RRset with key-signing keys, and omit signatures from zone-signing keys. (This is similar to the dnssec-dnskey-kskonly yes; zone option in named.)

-z

Ignore KSK flag on key when determining what to sign. This causes KSK-flagged keys to sign all records, not just the DNSKEY RRset. (This is similar to the update-check-ksk no; zone option in named.)

-3 salt

Generate an NSEC3 chain with the given hex encoded salt. A dash (salt) can be used to indicate that no salt is to be used when generating the NSEC3 chain.

-H iterations

When generating an NSEC3 chain, use this many iterations. The default is 10.

-A

When generating an NSEC3 chain set the OPTOUT flag on all NSEC3 records and do not generate NSEC3 records for insecure delegations.

Using this option twice (i.e., -AA) turns the OPTOUT flag off for all records. This is useful when using the -u option to modify an NSEC3 chain which previously had OPTOUT set.

zonefile

The file containing the zone to be signed.

key

Specify which keys should be used to sign the zone. If no keys are specified, then the zone will be examined for DNSKEY records at the zone apex. If these are found and there are matching private keys, in the current directory, then these will be used for signing.

EXAMPLE

The following command signs the example.com zone with the DSA key generated by dnssec-keygen (Kexample.com.+003+17247). Because the -S option is not being used, the zone's keys must be in the master file (db.example.com). This invocation looks for dsset files, in the current directory, so that DS records can be imported from them (-g).

% dnssec-signzone -g -o example.com db.example.com \
Kexample.com.+003+17247
db.example.com.signed
%

In the above example, dnssec-signzone creates the file db.example.com.signed. This file should be referenced in a zone statement in a named.conf file.

This example re-signs a previously signed zone with default parameters. The private keys are assumed to be in the current directory.

% cp db.example.com.signed db.example.com
% dnssec-signzone -o example.com db.example.com
db.example.com.signed
%

SEE ALSO

dnssec-keygen(8) , BIND 9 Administrator Reference Manual, RFC 4033, RFC 4641.

bind9-9.11.3+dfsg/bin/dnssec/dnssec-verify.8000066400000000000000000000107331325250447100204410ustar00rootroot00000000000000.\" Copyright (C) 2012, 2014-2016 Internet Systems Consortium, Inc. ("ISC") .\" .\" This Source Code Form is subject to the terms of the Mozilla Public .\" License, v. 2.0. If a copy of the MPL was not distributed with this .\" file, You can obtain one at http://mozilla.org/MPL/2.0/. .\" .hy 0 .ad l '\" t .\" Title: dnssec-verify .\" Author: .\" Generator: DocBook XSL Stylesheets v1.78.1 .\" Date: 2014-01-15 .\" Manual: BIND9 .\" Source: ISC .\" Language: English .\" .TH "DNSSEC\-VERIFY" "8" "2014\-01\-15" "ISC" "BIND9" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" dnssec-verify \- DNSSEC zone verification tool .SH "SYNOPSIS" .HP \w'\fBdnssec\-verify\fR\ 'u \fBdnssec\-verify\fR [\fB\-c\ \fR\fB\fIclass\fR\fR] [\fB\-E\ \fR\fB\fIengine\fR\fR] [\fB\-I\ \fR\fB\fIinput\-format\fR\fR] [\fB\-o\ \fR\fB\fIorigin\fR\fR] [\fB\-v\ \fR\fB\fIlevel\fR\fR] [\fB\-V\fR] [\fB\-x\fR] [\fB\-z\fR] {zonefile} .SH "DESCRIPTION" .PP \fBdnssec\-verify\fR verifies that a zone is fully signed for each algorithm found in the DNSKEY RRset for the zone, and that the NSEC / NSEC3 chains are complete\&. .SH "OPTIONS" .PP \-c \fIclass\fR .RS 4 Specifies the DNS class of the zone\&. .RE .PP \-E \fIengine\fR .RS 4 Specifies the cryptographic hardware to use, when applicable\&. .sp When BIND is built with OpenSSL PKCS#11 support, this defaults to the string "pkcs11", which identifies an OpenSSL engine that can drive a cryptographic accelerator or hardware service module\&. When BIND is built with native PKCS#11 cryptography (\-\-enable\-native\-pkcs11), it defaults to the path of the PKCS#11 provider library specified via "\-\-with\-pkcs11"\&. .RE .PP \-I \fIinput\-format\fR .RS 4 The format of the input zone file\&. Possible formats are \fB"text"\fR (default) and \fB"raw"\fR\&. This option is primarily intended to be used for dynamic signed zones so that the dumped zone file in a non\-text format containing updates can be verified independently\&. The use of this option does not make much sense for non\-dynamic zones\&. .RE .PP \-o \fIorigin\fR .RS 4 The zone origin\&. If not specified, the name of the zone file is assumed to be the origin\&. .RE .PP \-v \fIlevel\fR .RS 4 Sets the debugging level\&. .RE .PP \-V .RS 4 Prints version information\&. .RE .PP \-x .RS 4 Only verify that the DNSKEY RRset is signed with key\-signing keys\&. Without this flag, it is assumed that the DNSKEY RRset will be signed by all active keys\&. When this flag is set, it will not be an error if the DNSKEY RRset is not signed by zone\-signing keys\&. This corresponds to the \fB\-x\fR option in \fBdnssec\-signzone\fR\&. .RE .PP \-z .RS 4 Ignore the KSK flag on the keys when determining whether the zone if correctly signed\&. Without this flag it is assumed that there will be a non\-revoked, self\-signed DNSKEY with the KSK flag set for each algorithm and that RRsets other than DNSKEY RRset will be signed with a different DNSKEY without the KSK flag set\&. .sp With this flag set, we only require that for each algorithm, there will be at least one non\-revoked, self\-signed DNSKEY, regardless of the KSK flag state, and that other RRsets will be signed by a non\-revoked key for the same algorithm that includes the self\-signed key; the same key may be used for both purposes\&. This corresponds to the \fB\-z\fR option in \fBdnssec\-signzone\fR\&. .RE .PP zonefile .RS 4 The file containing the zone to be signed\&. .RE .SH "SEE ALSO" .PP \fBdnssec-signzone\fR(8), BIND 9 Administrator Reference Manual, RFC 4033\&. .SH "AUTHOR" .PP \fBInternet Systems Consortium, Inc\&.\fR .SH "COPYRIGHT" .br Copyright \(co 2012, 2014-2016 Internet Systems Consortium, Inc. ("ISC") .br bind9-9.11.3+dfsg/bin/dnssec/dnssec-verify.c000066400000000000000000000204371325250447100205160ustar00rootroot00000000000000/* * Copyright (C) 2012, 2014-2017 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /*! \file */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef PKCS11CRYPTO #include #endif #include "dnssectool.h" const char *program = "dnssec-verify"; int verbose; static isc_stdtime_t now; static isc_mem_t *mctx = NULL; static isc_entropy_t *ectx = NULL; static dns_masterformat_t inputformat = dns_masterformat_text; static dns_db_t *gdb; /* The database */ static dns_dbversion_t *gversion; /* The database version */ static dns_rdataclass_t gclass; /* The class */ static dns_name_t *gorigin; /* The database origin */ static isc_boolean_t ignore_kskflag = ISC_FALSE; static isc_boolean_t keyset_kskonly = ISC_FALSE; /*% * Load the zone file from disk */ static void loadzone(char *file, char *origin, dns_rdataclass_t rdclass, dns_db_t **db) { isc_buffer_t b; int len; dns_fixedname_t fname; dns_name_t *name; isc_result_t result; len = strlen(origin); isc_buffer_init(&b, origin, len); isc_buffer_add(&b, len); dns_fixedname_init(&fname); name = dns_fixedname_name(&fname); result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL); if (result != ISC_R_SUCCESS) fatal("failed converting name '%s' to dns format: %s", origin, isc_result_totext(result)); result = dns_db_create(mctx, "rbt", name, dns_dbtype_zone, rdclass, 0, NULL, db); check_result(result, "dns_db_create()"); result = dns_db_load2(*db, file, inputformat); switch (result) { case DNS_R_SEENINCLUDE: case ISC_R_SUCCESS: break; case DNS_R_NOTZONETOP: /* * Comparing pointers (vs. using strcmp()) is intentional: we * want to check whether -o was supplied on the command line, * not whether origin and file contain the same string. */ if (origin == file) { fatal("failed loading zone '%s' from file '%s': " "use -o to specify a different zone origin", origin, file); } /* FALLTHROUGH */ default: fatal("failed loading zone from '%s': %s", file, isc_result_totext(result)); } } ISC_PLATFORM_NORETURN_PRE static void usage(void) ISC_PLATFORM_NORETURN_POST; static void usage(void) { fprintf(stderr, "Usage:\n"); fprintf(stderr, "\t%s [options] zonefile [keys]\n", program); fprintf(stderr, "\n"); fprintf(stderr, "Version: %s\n", VERSION); fprintf(stderr, "Options: (default value in parenthesis) \n"); fprintf(stderr, "\t-v debuglevel (0)\n"); fprintf(stderr, "\t-V:\tprint version information\n"); fprintf(stderr, "\t-o origin:\n"); fprintf(stderr, "\t\tzone origin (name of zonefile)\n"); fprintf(stderr, "\t-I format:\n"); fprintf(stderr, "\t\tfile format of input zonefile (text)\n"); fprintf(stderr, "\t-c class (IN)\n"); fprintf(stderr, "\t-E engine:\n"); #if defined(PKCS11CRYPTO) fprintf(stderr, "\t\tpath to PKCS#11 provider library " "(default is %s)\n", PK11_LIB_LOCATION); #elif defined(USE_PKCS11) fprintf(stderr, "\t\tname of an OpenSSL engine to use " "(default is \"pkcs11\")\n"); #else fprintf(stderr, "\t\tname of an OpenSSL engine to use\n"); #endif fprintf(stderr, "\t-x:\tDNSKEY record signed with KSKs only, " "not ZSKs\n"); fprintf(stderr, "\t-z:\tAll records signed with KSKs\n"); exit(0); } int main(int argc, char *argv[]) { char *origin = NULL, *file = NULL; char *inputformatstr = NULL; isc_result_t result; isc_log_t *log = NULL; #ifdef USE_PKCS11 const char *engine = PKCS11_ENGINE; #else const char *engine = NULL; #endif char *classname = NULL; dns_rdataclass_t rdclass; char *endp; int ch; #define CMDLINE_FLAGS \ "hm:o:I:c:E:v:Vxz" /* * Process memory debugging argument first. */ while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) { switch (ch) { case 'm': if (strcasecmp(isc_commandline_argument, "record") == 0) isc_mem_debugging |= ISC_MEM_DEBUGRECORD; if (strcasecmp(isc_commandline_argument, "trace") == 0) isc_mem_debugging |= ISC_MEM_DEBUGTRACE; if (strcasecmp(isc_commandline_argument, "usage") == 0) isc_mem_debugging |= ISC_MEM_DEBUGUSAGE; if (strcasecmp(isc_commandline_argument, "size") == 0) isc_mem_debugging |= ISC_MEM_DEBUGSIZE; if (strcasecmp(isc_commandline_argument, "mctx") == 0) isc_mem_debugging |= ISC_MEM_DEBUGCTX; break; default: break; } } isc_commandline_reset = ISC_TRUE; check_result(isc_app_start(), "isc_app_start"); result = isc_mem_create(0, 0, &mctx); if (result != ISC_R_SUCCESS) fatal("out of memory"); #ifdef PKCS11CRYPTO pk11_result_register(); #endif dns_result_register(); isc_commandline_errprint = ISC_FALSE; while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) { switch (ch) { case 'c': classname = isc_commandline_argument; break; case 'E': engine = isc_commandline_argument; break; case 'I': inputformatstr = isc_commandline_argument; break; case 'm': break; case 'o': origin = isc_commandline_argument; break; case 'v': endp = NULL; verbose = strtol(isc_commandline_argument, &endp, 0); if (*endp != '\0') fatal("verbose level must be numeric"); break; case 'x': keyset_kskonly = ISC_TRUE; break; case 'z': ignore_kskflag = ISC_TRUE; break; case '?': if (isc_commandline_option != '?') fprintf(stderr, "%s: invalid argument -%c\n", program, isc_commandline_option); /* FALLTHROUGH */ case 'h': /* Does not return. */ usage(); case 'V': /* Does not return. */ version(program); default: fprintf(stderr, "%s: unhandled option -%c\n", program, isc_commandline_option); exit(1); } } if (ectx == NULL) setup_entropy(mctx, NULL, &ectx); result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE); if (result != ISC_R_SUCCESS) fatal("could not create hash context"); result = dst_lib_init2(mctx, ectx, engine, ISC_ENTROPY_BLOCKING); if (result != ISC_R_SUCCESS) fatal("could not initialize dst: %s", isc_result_totext(result)); isc_stdtime_get(&now); rdclass = strtoclass(classname); setup_logging(mctx, &log); argc -= isc_commandline_index; argv += isc_commandline_index; if (argc < 1) usage(); file = argv[0]; argc -= 1; argv += 1; POST(argc); POST(argv); if (origin == NULL) origin = file; if (inputformatstr != NULL) { if (strcasecmp(inputformatstr, "text") == 0) inputformat = dns_masterformat_text; else if (strcasecmp(inputformatstr, "raw") == 0) inputformat = dns_masterformat_raw; else fatal("unknown file format: %s\n", inputformatstr); } gdb = NULL; fprintf(stderr, "Loading zone '%s' from file '%s'\n", origin, file); loadzone(file, origin, rdclass, &gdb); gorigin = dns_db_origin(gdb); gclass = dns_db_class(gdb); gversion = NULL; result = dns_db_newversion(gdb, &gversion); check_result(result, "dns_db_newversion()"); verifyzone(gdb, gversion, gorigin, mctx, ignore_kskflag, keyset_kskonly); dns_db_closeversion(gdb, &gversion, ISC_FALSE); dns_db_detach(&gdb); cleanup_logging(&log); dst_lib_destroy(); isc_hash_destroy(); cleanup_entropy(&ectx); dns_name_destroy(); if (verbose > 10) isc_mem_stats(mctx, stdout); isc_mem_destroy(&mctx); (void) isc_app_finish(); return (0); } bind9-9.11.3+dfsg/bin/dnssec/dnssec-verify.docbook000066400000000000000000000153321325250447100217120ustar00rootroot00000000000000 2014-01-15 ISC Internet Systems Consortium, Inc. dnssec-verify 8 BIND9 dnssec-verify DNSSEC zone verification tool 2012 2014 2015 2016 Internet Systems Consortium, Inc. ("ISC") dnssec-verify zonefile DESCRIPTION dnssec-verify verifies that a zone is fully signed for each algorithm found in the DNSKEY RRset for the zone, and that the NSEC / NSEC3 chains are complete. OPTIONS -c class Specifies the DNS class of the zone. -E engine Specifies the cryptographic hardware to use, when applicable. When BIND is built with OpenSSL PKCS#11 support, this defaults to the string "pkcs11", which identifies an OpenSSL engine that can drive a cryptographic accelerator or hardware service module. When BIND is built with native PKCS#11 cryptography (--enable-native-pkcs11), it defaults to the path of the PKCS#11 provider library specified via "--with-pkcs11". -I input-format The format of the input zone file. Possible formats are "text" (default) and "raw". This option is primarily intended to be used for dynamic signed zones so that the dumped zone file in a non-text format containing updates can be verified independently. The use of this option does not make much sense for non-dynamic zones. -o origin The zone origin. If not specified, the name of the zone file is assumed to be the origin. -v level Sets the debugging level. -V Prints version information. -x Only verify that the DNSKEY RRset is signed with key-signing keys. Without this flag, it is assumed that the DNSKEY RRset will be signed by all active keys. When this flag is set, it will not be an error if the DNSKEY RRset is not signed by zone-signing keys. This corresponds to the option in dnssec-signzone. -z Ignore the KSK flag on the keys when determining whether the zone if correctly signed. Without this flag it is assumed that there will be a non-revoked, self-signed DNSKEY with the KSK flag set for each algorithm and that RRsets other than DNSKEY RRset will be signed with a different DNSKEY without the KSK flag set. With this flag set, we only require that for each algorithm, there will be at least one non-revoked, self-signed DNSKEY, regardless of the KSK flag state, and that other RRsets will be signed by a non-revoked key for the same algorithm that includes the self-signed key; the same key may be used for both purposes. This corresponds to the option in dnssec-signzone. zonefile The file containing the zone to be signed. SEE ALSO dnssec-signzone8 , BIND 9 Administrator Reference Manual, RFC 4033. bind9-9.11.3+dfsg/bin/dnssec/dnssec-verify.html000066400000000000000000000137601325250447100212410ustar00rootroot00000000000000 dnssec-verify

Name

dnssec-verify — DNSSEC zone verification tool

Synopsis

dnssec-verify [-c class] [-E engine] [-I input-format] [-o origin] [-v level] [-V] [-x] [-z] {zonefile}

DESCRIPTION

dnssec-verify verifies that a zone is fully signed for each algorithm found in the DNSKEY RRset for the zone, and that the NSEC / NSEC3 chains are complete.

OPTIONS

-c class

Specifies the DNS class of the zone.

-E engine

Specifies the cryptographic hardware to use, when applicable.

When BIND is built with OpenSSL PKCS#11 support, this defaults to the string "pkcs11", which identifies an OpenSSL engine that can drive a cryptographic accelerator or hardware service module. When BIND is built with native PKCS#11 cryptography (--enable-native-pkcs11), it defaults to the path of the PKCS#11 provider library specified via "--with-pkcs11".

-I input-format

The format of the input zone file. Possible formats are "text" (default) and "raw". This option is primarily intended to be used for dynamic signed zones so that the dumped zone file in a non-text format containing updates can be verified independently. The use of this option does not make much sense for non-dynamic zones.

-o origin

The zone origin. If not specified, the name of the zone file is assumed to be the origin.

-v level

Sets the debugging level.

-V

Prints version information.

-x

Only verify that the DNSKEY RRset is signed with key-signing keys. Without this flag, it is assumed that the DNSKEY RRset will be signed by all active keys. When this flag is set, it will not be an error if the DNSKEY RRset is not signed by zone-signing keys. This corresponds to the -x option in dnssec-signzone.

-z

Ignore the KSK flag on the keys when determining whether the zone if correctly signed. Without this flag it is assumed that there will be a non-revoked, self-signed DNSKEY with the KSK flag set for each algorithm and that RRsets other than DNSKEY RRset will be signed with a different DNSKEY without the KSK flag set.

With this flag set, we only require that for each algorithm, there will be at least one non-revoked, self-signed DNSKEY, regardless of the KSK flag state, and that other RRsets will be signed by a non-revoked key for the same algorithm that includes the self-signed key; the same key may be used for both purposes. This corresponds to the -z option in dnssec-signzone.

zonefile

The file containing the zone to be signed.

SEE ALSO

dnssec-signzone(8) , BIND 9 Administrator Reference Manual, RFC 4033.

bind9-9.11.3+dfsg/bin/dnssec/dnssectool.c000066400000000000000000001515111325250447100201100ustar00rootroot00000000000000/* * Copyright (C) 2000, 2001, 2003-2005, 2007, 2009-2017 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /*! \file */ /*% * DNSSEC Support Routines. */ #include #include #ifdef _WIN32 #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "dnssectool.h" static isc_heap_t *expected_chains, *found_chains; struct nsec3_chain_fixed { isc_uint8_t hash; isc_uint8_t salt_length; isc_uint8_t next_length; isc_uint16_t iterations; /* unsigned char salt[0]; */ /* unsigned char owner[0]; */ /* unsigned char next[0]; */ }; extern int verbose; extern const char *program; typedef struct entropysource entropysource_t; struct entropysource { isc_entropysource_t *source; isc_mem_t *mctx; ISC_LINK(entropysource_t) link; }; static ISC_LIST(entropysource_t) sources; static fatalcallback_t *fatalcallback = NULL; void fatal(const char *format, ...) { va_list args; fprintf(stderr, "%s: fatal: ", program); va_start(args, format); vfprintf(stderr, format, args); va_end(args); fprintf(stderr, "\n"); if (fatalcallback != NULL) (*fatalcallback)(); exit(1); } void setfatalcallback(fatalcallback_t *callback) { fatalcallback = callback; } void check_result(isc_result_t result, const char *message) { if (result != ISC_R_SUCCESS) fatal("%s: %s", message, isc_result_totext(result)); } void vbprintf(int level, const char *fmt, ...) { va_list ap; if (level > verbose) return; va_start(ap, fmt); fprintf(stderr, "%s: ", program); vfprintf(stderr, fmt, ap); va_end(ap); } void version(const char *name) { fprintf(stderr, "%s %s\n", name, VERSION); exit(0); } void type_format(const dns_rdatatype_t type, char *cp, unsigned int size) { isc_buffer_t b; isc_region_t r; isc_result_t result; isc_buffer_init(&b, cp, size - 1); result = dns_rdatatype_totext(type, &b); check_result(result, "dns_rdatatype_totext()"); isc_buffer_usedregion(&b, &r); r.base[r.length] = 0; } void sig_format(dns_rdata_rrsig_t *sig, char *cp, unsigned int size) { char namestr[DNS_NAME_FORMATSIZE]; char algstr[DNS_NAME_FORMATSIZE]; dns_name_format(&sig->signer, namestr, sizeof(namestr)); dns_secalg_format(sig->algorithm, algstr, sizeof(algstr)); snprintf(cp, size, "%s/%s/%d", namestr, algstr, sig->keyid); } void setup_logging(isc_mem_t *mctx, isc_log_t **logp) { isc_result_t result; isc_logdestination_t destination; isc_logconfig_t *logconfig = NULL; isc_log_t *log = NULL; int level; if (verbose < 0) verbose = 0; switch (verbose) { case 0: /* * We want to see warnings about things like out-of-zone * data in the master file even when not verbose. */ level = ISC_LOG_WARNING; break; case 1: level = ISC_LOG_INFO; break; default: level = ISC_LOG_DEBUG(verbose - 2 + 1); break; } RUNTIME_CHECK(isc_log_create(mctx, &log, &logconfig) == ISC_R_SUCCESS); isc_log_setcontext(log); dns_log_init(log); dns_log_setcontext(log); RUNTIME_CHECK(isc_log_settag(logconfig, program) == ISC_R_SUCCESS); /* * Set up a channel similar to default_stderr except: * - the logging level is passed in * - the program name and logging level are printed * - no time stamp is printed */ destination.file.stream = stderr; destination.file.name = NULL; destination.file.versions = ISC_LOG_ROLLNEVER; destination.file.maximum_size = 0; result = isc_log_createchannel(logconfig, "stderr", ISC_LOG_TOFILEDESC, level, &destination, ISC_LOG_PRINTTAG|ISC_LOG_PRINTLEVEL); check_result(result, "isc_log_createchannel()"); RUNTIME_CHECK(isc_log_usechannel(logconfig, "stderr", NULL, NULL) == ISC_R_SUCCESS); *logp = log; } void cleanup_logging(isc_log_t **logp) { isc_log_t *log; REQUIRE(logp != NULL); log = *logp; if (log == NULL) return; isc_log_destroy(&log); isc_log_setcontext(NULL); dns_log_setcontext(NULL); logp = NULL; } void setup_entropy(isc_mem_t *mctx, const char *randomfile, isc_entropy_t **ectx) { isc_result_t result; isc_entropysource_t *source = NULL; entropysource_t *elt; int usekeyboard = ISC_ENTROPY_KEYBOARDMAYBE; REQUIRE(ectx != NULL); if (*ectx == NULL) { result = isc_entropy_create(mctx, ectx); if (result != ISC_R_SUCCESS) fatal("could not create entropy object"); ISC_LIST_INIT(sources); } if (randomfile != NULL && strcmp(randomfile, "keyboard") == 0) { usekeyboard = ISC_ENTROPY_KEYBOARDYES; randomfile = NULL; } result = isc_entropy_usebestsource(*ectx, &source, randomfile, usekeyboard); if (result != ISC_R_SUCCESS) fatal("could not initialize entropy source: %s", isc_result_totext(result)); if (source != NULL) { elt = isc_mem_get(mctx, sizeof(*elt)); if (elt == NULL) fatal("out of memory"); elt->source = source; elt->mctx = mctx; ISC_LINK_INIT(elt, link); ISC_LIST_APPEND(sources, elt, link); } } void cleanup_entropy(isc_entropy_t **ectx) { entropysource_t *source; while (!ISC_LIST_EMPTY(sources)) { source = ISC_LIST_HEAD(sources); ISC_LIST_UNLINK(sources, source, link); isc_entropy_destroysource(&source->source); isc_mem_put(source->mctx, source, sizeof(*source)); } isc_entropy_detach(ectx); } static isc_stdtime_t time_units(isc_stdtime_t offset, char *suffix, const char *str) { switch (suffix[0]) { case 'Y': case 'y': return (offset * (365 * 24 * 3600)); case 'M': case 'm': switch (suffix[1]) { case 'O': case 'o': return (offset * (30 * 24 * 3600)); case 'I': case 'i': return (offset * 60); case '\0': fatal("'%s' ambiguous: use 'mi' for minutes " "or 'mo' for months", str); default: fatal("time value %s is invalid", str); } /* NOTREACHED */ break; case 'W': case 'w': return (offset * (7 * 24 * 3600)); case 'D': case 'd': return (offset * (24 * 3600)); case 'H': case 'h': return (offset * 3600); case 'S': case 's': case '\0': return (offset); default: fatal("time value %s is invalid", str); } /* NOTREACHED */ return(0); /* silence compiler warning */ } static inline isc_boolean_t isnone(const char *str) { return (ISC_TF((strcasecmp(str, "none") == 0) || (strcasecmp(str, "never") == 0))); } dns_ttl_t strtottl(const char *str) { const char *orig = str; dns_ttl_t ttl; char *endp; if (isnone(str)) return ((dns_ttl_t) 0); ttl = strtol(str, &endp, 0); if (ttl == 0 && endp == str) fatal("TTL must be numeric"); ttl = time_units(ttl, endp, orig); return (ttl); } isc_stdtime_t strtotime(const char *str, isc_int64_t now, isc_int64_t base, isc_boolean_t *setp) { isc_int64_t val, offset; isc_result_t result; const char *orig = str; char *endp; size_t n; if (isnone(str)) { if (setp != NULL) *setp = ISC_FALSE; return ((isc_stdtime_t) 0); } if (setp != NULL) *setp = ISC_TRUE; if ((str[0] == '0' || str[0] == '-') && str[1] == '\0') return ((isc_stdtime_t) 0); /* * We accept times in the following formats: * now([+-]offset) * YYYYMMDD([+-]offset) * YYYYMMDDhhmmss([+-]offset) * [+-]offset */ n = strspn(str, "0123456789"); if ((n == 8u || n == 14u) && (str[n] == '\0' || str[n] == '-' || str[n] == '+')) { char timestr[15]; strlcpy(timestr, str, sizeof(timestr)); timestr[n] = 0; if (n == 8u) strlcat(timestr, "000000", sizeof(timestr)); result = dns_time64_fromtext(timestr, &val); if (result != ISC_R_SUCCESS) fatal("time value %s is invalid: %s", orig, isc_result_totext(result)); base = val; str += n; } else if (strncmp(str, "now", 3) == 0) { base = now; str += 3; } if (str[0] == '\0') return ((isc_stdtime_t) base); else if (str[0] == '+') { offset = strtol(str + 1, &endp, 0); offset = time_units((isc_stdtime_t) offset, endp, orig); val = base + offset; } else if (str[0] == '-') { offset = strtol(str + 1, &endp, 0); offset = time_units((isc_stdtime_t) offset, endp, orig); val = base - offset; } else fatal("time value %s is invalid", orig); return ((isc_stdtime_t) val); } dns_rdataclass_t strtoclass(const char *str) { isc_textregion_t r; dns_rdataclass_t rdclass; isc_result_t ret; if (str == NULL) return dns_rdataclass_in; DE_CONST(str, r.base); r.length = strlen(str); ret = dns_rdataclass_fromtext(&rdclass, &r); if (ret != ISC_R_SUCCESS) fatal("unknown class %s", str); return (rdclass); } isc_result_t try_dir(const char *dirname) { isc_result_t result; isc_dir_t d; isc_dir_init(&d); result = isc_dir_open(&d, dirname); if (result == ISC_R_SUCCESS) { isc_dir_close(&d); } return (result); } /* * Check private key version compatibility. */ void check_keyversion(dst_key_t *key, char *keystr) { int major, minor; dst_key_getprivateformat(key, &major, &minor); INSIST(major <= DST_MAJOR_VERSION); /* invalid private key */ if (major < DST_MAJOR_VERSION || minor < DST_MINOR_VERSION) fatal("Key %s has incompatible format version %d.%d, " "use -f to force upgrade to new version.", keystr, major, minor); if (minor > DST_MINOR_VERSION) fatal("Key %s has incompatible format version %d.%d, " "use -f to force downgrade to current version.", keystr, major, minor); } void set_keyversion(dst_key_t *key) { int major, minor; dst_key_getprivateformat(key, &major, &minor); INSIST(major <= DST_MAJOR_VERSION); if (major != DST_MAJOR_VERSION || minor != DST_MINOR_VERSION) dst_key_setprivateformat(key, DST_MAJOR_VERSION, DST_MINOR_VERSION); /* * If the key is from a version older than 1.3, set * set the creation date */ if (major < 1 || (major == 1 && minor <= 2)) { isc_stdtime_t now; isc_stdtime_get(&now); dst_key_settime(key, DST_TIME_CREATED, now); } } isc_boolean_t key_collision(dst_key_t *dstkey, dns_name_t *name, const char *dir, isc_mem_t *mctx, isc_boolean_t *exact) { isc_result_t result; isc_boolean_t conflict = ISC_FALSE; dns_dnsseckeylist_t matchkeys; dns_dnsseckey_t *key = NULL; isc_uint16_t id, oldid; isc_uint32_t rid, roldid; dns_secalg_t alg; char filename[ISC_DIR_NAMEMAX]; isc_buffer_t fileb; if (exact != NULL) *exact = ISC_FALSE; id = dst_key_id(dstkey); rid = dst_key_rid(dstkey); alg = dst_key_alg(dstkey); /* * For HMAC and Diffie Hellman just check if there is a * direct collision as they can't be revoked. Additionally * dns_dnssec_findmatchingkeys only handles DNSKEY which is * not used for HMAC. */ switch (alg) { case DST_ALG_HMACMD5: case DST_ALG_HMACSHA1: case DST_ALG_HMACSHA224: case DST_ALG_HMACSHA256: case DST_ALG_HMACSHA384: case DST_ALG_HMACSHA512: case DST_ALG_DH: isc_buffer_init(&fileb, filename, sizeof(filename)); result = dst_key_buildfilename(dstkey, DST_TYPE_PRIVATE, dir, &fileb); if (result != ISC_R_SUCCESS) return (ISC_TRUE); return (isc_file_exists(filename)); } ISC_LIST_INIT(matchkeys); result = dns_dnssec_findmatchingkeys(name, dir, mctx, &matchkeys); if (result == ISC_R_NOTFOUND) return (ISC_FALSE); while (!ISC_LIST_EMPTY(matchkeys) && !conflict) { key = ISC_LIST_HEAD(matchkeys); if (dst_key_alg(key->key) != alg) goto next; oldid = dst_key_id(key->key); roldid = dst_key_rid(key->key); if (oldid == rid || roldid == id || id == oldid) { conflict = ISC_TRUE; if (id != oldid) { if (verbose > 1) fprintf(stderr, "Key ID %d could " "collide with %d\n", id, oldid); } else { if (exact != NULL) *exact = ISC_TRUE; if (verbose > 1) fprintf(stderr, "Key ID %d exists\n", id); } } next: ISC_LIST_UNLINK(matchkeys, key, link); dns_dnsseckey_destroy(mctx, &key); } /* Finish freeing the list */ while (!ISC_LIST_EMPTY(matchkeys)) { key = ISC_LIST_HEAD(matchkeys); ISC_LIST_UNLINK(matchkeys, key, link); dns_dnsseckey_destroy(mctx, &key); } return (conflict); } isc_boolean_t is_delegation(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *origin, dns_name_t *name, dns_dbnode_t *node, isc_uint32_t *ttlp) { dns_rdataset_t nsset; isc_result_t result; if (dns_name_equal(name, origin)) return (ISC_FALSE); dns_rdataset_init(&nsset); result = dns_db_findrdataset(db, node, ver, dns_rdatatype_ns, 0, 0, &nsset, NULL); if (dns_rdataset_isassociated(&nsset)) { if (ttlp != NULL) *ttlp = nsset.ttl; dns_rdataset_disassociate(&nsset); } return (ISC_TF(result == ISC_R_SUCCESS)); } static isc_boolean_t goodsig(dns_name_t *origin, dns_rdata_t *sigrdata, dns_name_t *name, dns_rdataset_t *keyrdataset, dns_rdataset_t *rdataset, isc_mem_t *mctx) { dns_rdata_dnskey_t key; dns_rdata_rrsig_t sig; dst_key_t *dstkey = NULL; isc_result_t result; result = dns_rdata_tostruct(sigrdata, &sig, NULL); check_result(result, "dns_rdata_tostruct()"); for (result = dns_rdataset_first(keyrdataset); result == ISC_R_SUCCESS; result = dns_rdataset_next(keyrdataset)) { dns_rdata_t rdata = DNS_RDATA_INIT; dns_rdataset_current(keyrdataset, &rdata); result = dns_rdata_tostruct(&rdata, &key, NULL); check_result(result, "dns_rdata_tostruct()"); result = dns_dnssec_keyfromrdata(origin, &rdata, mctx, &dstkey); if (result != ISC_R_SUCCESS) return (ISC_FALSE); if (sig.algorithm != key.algorithm || sig.keyid != dst_key_id(dstkey) || !dns_name_equal(&sig.signer, origin)) { dst_key_free(&dstkey); continue; } result = dns_dnssec_verify(name, rdataset, dstkey, ISC_FALSE, mctx, sigrdata); dst_key_free(&dstkey); if (result == ISC_R_SUCCESS) return(ISC_TRUE); } return (ISC_FALSE); } static isc_result_t verifynsec(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, dns_dbnode_t *node, dns_name_t *nextname) { unsigned char buffer[DNS_NSEC_BUFFERSIZE]; char namebuf[DNS_NAME_FORMATSIZE]; char nextbuf[DNS_NAME_FORMATSIZE]; char found[DNS_NAME_FORMATSIZE]; dns_rdataset_t rdataset; dns_rdata_t rdata = DNS_RDATA_INIT; dns_rdata_t tmprdata = DNS_RDATA_INIT; dns_rdata_nsec_t nsec; isc_result_t result; dns_rdataset_init(&rdataset); result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec, 0, 0, &rdataset, NULL); if (result != ISC_R_SUCCESS) { dns_name_format(name, namebuf, sizeof(namebuf)); fprintf(stderr, "Missing NSEC record for %s\n", namebuf); goto failure; } result = dns_rdataset_first(&rdataset); check_result(result, "dns_rdataset_first()"); dns_rdataset_current(&rdataset, &rdata); result = dns_rdata_tostruct(&rdata, &nsec, NULL); check_result(result, "dns_rdata_tostruct()"); /* Check bit next name is consistent */ if (!dns_name_equal(&nsec.next, nextname)) { dns_name_format(name, namebuf, sizeof(namebuf)); dns_name_format(nextname, nextbuf, sizeof(nextbuf)); dns_name_format(&nsec.next, found, sizeof(found)); fprintf(stderr, "Bad NSEC record for %s, next name " "mismatch (expected:%s, found:%s)\n", namebuf, nextbuf, found); goto failure; } /* Check bit map is consistent */ result = dns_nsec_buildrdata(db, ver, node, nextname, buffer, &tmprdata); check_result(result, "dns_nsec_buildrdata()"); if (dns_rdata_compare(&rdata, &tmprdata) != 0) { dns_name_format(name, namebuf, sizeof(namebuf)); fprintf(stderr, "Bad NSEC record for %s, bit map " "mismatch\n", namebuf); goto failure; } result = dns_rdataset_next(&rdataset); if (result != ISC_R_NOMORE) { dns_name_format(name, namebuf, sizeof(namebuf)); fprintf(stderr, "Multipe NSEC records for %s\n", namebuf); goto failure; } dns_rdataset_disassociate(&rdataset); return (ISC_R_SUCCESS); failure: if (dns_rdataset_isassociated(&rdataset)) dns_rdataset_disassociate(&rdataset); return (ISC_R_FAILURE); } static void check_no_rrsig(dns_db_t *db, dns_dbversion_t *ver, dns_rdataset_t *rdataset, dns_name_t *name, dns_dbnode_t *node) { char namebuf[DNS_NAME_FORMATSIZE]; char typebuf[80]; dns_rdataset_t sigrdataset; dns_rdatasetiter_t *rdsiter = NULL; isc_result_t result; dns_rdataset_init(&sigrdataset); result = dns_db_allrdatasets(db, node, ver, 0, &rdsiter); check_result(result, "dns_db_allrdatasets()"); for (result = dns_rdatasetiter_first(rdsiter); result == ISC_R_SUCCESS; result = dns_rdatasetiter_next(rdsiter)) { dns_rdatasetiter_current(rdsiter, &sigrdataset); if (sigrdataset.type == dns_rdatatype_rrsig && sigrdataset.covers == rdataset->type) break; dns_rdataset_disassociate(&sigrdataset); } if (result == ISC_R_SUCCESS) { dns_name_format(name, namebuf, sizeof(namebuf)); type_format(rdataset->type, typebuf, sizeof(typebuf)); fprintf(stderr, "Warning: Found unexpected signatures for " "%s/%s\n", namebuf, typebuf); } if (dns_rdataset_isassociated(&sigrdataset)) dns_rdataset_disassociate(&sigrdataset); dns_rdatasetiter_destroy(&rdsiter); } static isc_boolean_t chain_compare(void *arg1, void *arg2) { struct nsec3_chain_fixed *e1 = arg1, *e2 = arg2; size_t len; /* * Do each element in turn to get a stable sort. */ if (e1->hash < e2->hash) return (ISC_TRUE); if (e1->hash > e2->hash) return (ISC_FALSE); if (e1->iterations < e2->iterations) return (ISC_TRUE); if (e1->iterations > e2->iterations) return (ISC_FALSE); if (e1->salt_length < e2->salt_length) return (ISC_TRUE); if (e1->salt_length > e2->salt_length) return (ISC_FALSE); if (e1->next_length < e2->next_length) return (ISC_TRUE); if (e1->next_length > e2->next_length) return (ISC_FALSE); len = e1->salt_length + 2 * e1->next_length; if (memcmp(e1 + 1, e2 + 1, len) < 0) return (ISC_TRUE); return (ISC_FALSE); } static isc_boolean_t chain_equal(struct nsec3_chain_fixed *e1, struct nsec3_chain_fixed *e2) { size_t len; if (e1->hash != e2->hash) return (ISC_FALSE); if (e1->iterations != e2->iterations) return (ISC_FALSE); if (e1->salt_length != e2->salt_length) return (ISC_FALSE); if (e1->next_length != e2->next_length) return (ISC_FALSE); len = e1->salt_length + 2 * e1->next_length; if (memcmp(e1 + 1, e2 + 1, len) != 0) return (ISC_FALSE); return (ISC_TRUE); } static isc_result_t record_nsec3(const unsigned char *rawhash, const dns_rdata_nsec3_t *nsec3, isc_mem_t *mctx, isc_heap_t *chains) { struct nsec3_chain_fixed *element; size_t len; unsigned char *cp; isc_result_t result; len = sizeof(*element) + nsec3->next_length * 2 + nsec3->salt_length; element = isc_mem_get(mctx, len); if (element == NULL) return (ISC_R_NOMEMORY); memset(element, 0, len); element->hash = nsec3->hash; element->salt_length = nsec3->salt_length; element->next_length = nsec3->next_length; element->iterations = nsec3->iterations; cp = (unsigned char *)(element + 1); memmove(cp, nsec3->salt, nsec3->salt_length); cp += nsec3->salt_length; memmove(cp, rawhash, nsec3->next_length); cp += nsec3->next_length; memmove(cp, nsec3->next, nsec3->next_length); result = isc_heap_insert(chains, element); if (result != ISC_R_SUCCESS) { fprintf(stderr, "isc_heap_insert failed: %s\n", isc_result_totext(result)); isc_mem_put(mctx, element, len); } return (result); } static isc_result_t match_nsec3(dns_name_t *name, isc_mem_t *mctx, dns_rdata_nsec3param_t *nsec3param, dns_rdataset_t *rdataset, unsigned char types[8192], unsigned int maxtype, unsigned char *rawhash, size_t rhsize) { unsigned char cbm[8244]; char namebuf[DNS_NAME_FORMATSIZE]; dns_rdata_nsec3_t nsec3; isc_result_t result; unsigned int len; /* * Find matching NSEC3 record. */ for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS; result = dns_rdataset_next(rdataset)) { dns_rdata_t rdata = DNS_RDATA_INIT; dns_rdataset_current(rdataset, &rdata); result = dns_rdata_tostruct(&rdata, &nsec3, NULL); check_result(result, "dns_rdata_tostruct()"); if (nsec3.hash == nsec3param->hash && nsec3.next_length == rhsize && nsec3.iterations == nsec3param->iterations && nsec3.salt_length == nsec3param->salt_length && memcmp(nsec3.salt, nsec3param->salt, nsec3param->salt_length) == 0) break; } if (result != ISC_R_SUCCESS) { dns_name_format(name, namebuf, sizeof(namebuf)); fprintf(stderr, "Missing NSEC3 record for %s\n", namebuf); return (result); } /* * Check the type list. */ len = dns_nsec_compressbitmap(cbm, types, maxtype); if (nsec3.len != len || memcmp(cbm, nsec3.typebits, len) != 0) { dns_name_format(name, namebuf, sizeof(namebuf)); fprintf(stderr, "Bad NSEC3 record for %s, bit map " "mismatch\n", namebuf); return (ISC_R_FAILURE); } /* * Record chain. */ result = record_nsec3(rawhash, &nsec3, mctx, expected_chains); check_result(result, "record_nsec3()"); /* * Make sure there is only one NSEC3 record with this set of * parameters. */ for (result = dns_rdataset_next(rdataset); result == ISC_R_SUCCESS; result = dns_rdataset_next(rdataset)) { dns_rdata_t rdata = DNS_RDATA_INIT; dns_rdataset_current(rdataset, &rdata); result = dns_rdata_tostruct(&rdata, &nsec3, NULL); check_result(result, "dns_rdata_tostruct()"); if (nsec3.hash == nsec3param->hash && nsec3.iterations == nsec3param->iterations && nsec3.salt_length == nsec3param->salt_length && memcmp(nsec3.salt, nsec3param->salt, nsec3.salt_length) == 0) { dns_name_format(name, namebuf, sizeof(namebuf)); fprintf(stderr, "Multiple NSEC3 records with the " "same parameter set for %s", namebuf); result = DNS_R_DUPLICATE; break; } } if (result != ISC_R_NOMORE) return (result); result = ISC_R_SUCCESS; return (result); } static isc_boolean_t innsec3params(dns_rdata_nsec3_t *nsec3, dns_rdataset_t *nsec3paramset) { dns_rdata_nsec3param_t nsec3param; isc_result_t result; for (result = dns_rdataset_first(nsec3paramset); result == ISC_R_SUCCESS; result = dns_rdataset_next(nsec3paramset)) { dns_rdata_t rdata = DNS_RDATA_INIT; dns_rdataset_current(nsec3paramset, &rdata); result = dns_rdata_tostruct(&rdata, &nsec3param, NULL); check_result(result, "dns_rdata_tostruct()"); if (nsec3param.flags == 0 && nsec3param.hash == nsec3->hash && nsec3param.iterations == nsec3->iterations && nsec3param.salt_length == nsec3->salt_length && memcmp(nsec3param.salt, nsec3->salt, nsec3->salt_length) == 0) return (ISC_TRUE); } return (ISC_FALSE); } static isc_result_t record_found(dns_db_t *db, dns_dbversion_t *ver, isc_mem_t *mctx, dns_name_t *name, dns_dbnode_t *node, dns_rdataset_t *nsec3paramset) { unsigned char owner[NSEC3_MAX_HASH_LENGTH]; dns_rdata_nsec3_t nsec3; dns_rdataset_t rdataset; dns_label_t hashlabel; isc_buffer_t b; isc_result_t result; if (nsec3paramset == NULL || !dns_rdataset_isassociated(nsec3paramset)) return (ISC_R_SUCCESS); dns_rdataset_init(&rdataset); result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3, 0, 0, &rdataset, NULL); if (result != ISC_R_SUCCESS) return (ISC_R_SUCCESS); dns_name_getlabel(name, 0, &hashlabel); isc_region_consume(&hashlabel, 1); isc_buffer_init(&b, owner, sizeof(owner)); result = isc_base32hex_decoderegion(&hashlabel, &b); if (result != ISC_R_SUCCESS) goto cleanup; for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS; result = dns_rdataset_next(&rdataset)) { dns_rdata_t rdata = DNS_RDATA_INIT; dns_rdataset_current(&rdataset, &rdata); result = dns_rdata_tostruct(&rdata, &nsec3, NULL); check_result(result, "dns_rdata_tostruct()"); if (nsec3.next_length != isc_buffer_usedlength(&b)) continue; /* * We only care about NSEC3 records that match a NSEC3PARAM * record. */ if (!innsec3params(&nsec3, nsec3paramset)) continue; /* * Record chain. */ result = record_nsec3(owner, &nsec3, mctx, found_chains); check_result(result, "record_nsec3()"); } cleanup: dns_rdataset_disassociate(&rdataset); return (ISC_R_SUCCESS); } static isc_boolean_t isoptout(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *origin, dns_rdata_t *nsec3rdata) { dns_rdataset_t rdataset; dns_rdata_t rdata = DNS_RDATA_INIT; dns_rdata_nsec3_t nsec3; dns_rdata_nsec3param_t nsec3param; dns_fixedname_t fixed; dns_name_t *hashname; isc_result_t result; dns_dbnode_t *node = NULL; unsigned char rawhash[NSEC3_MAX_HASH_LENGTH]; size_t rhsize = sizeof(rawhash); isc_boolean_t ret; result = dns_rdata_tostruct(nsec3rdata, &nsec3param, NULL); check_result(result, "dns_rdata_tostruct()"); dns_fixedname_init(&fixed); result = dns_nsec3_hashname(&fixed, rawhash, &rhsize, origin, origin, nsec3param.hash, nsec3param.iterations, nsec3param.salt, nsec3param.salt_length); check_result(result, "dns_nsec3_hashname()"); dns_rdataset_init(&rdataset); hashname = dns_fixedname_name(&fixed); result = dns_db_findnsec3node(db, hashname, ISC_FALSE, &node); if (result == ISC_R_SUCCESS) result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3, 0, 0, &rdataset, NULL); if (result != ISC_R_SUCCESS) return (ISC_FALSE); result = dns_rdataset_first(&rdataset); check_result(result, "dns_rdataset_first()"); dns_rdataset_current(&rdataset, &rdata); result = dns_rdata_tostruct(&rdata, &nsec3, NULL); if (result != ISC_R_SUCCESS) ret = ISC_FALSE; else ret = ISC_TF((nsec3.flags & DNS_NSEC3FLAG_OPTOUT) != 0); if (dns_rdataset_isassociated(&rdataset)) dns_rdataset_disassociate(&rdataset); if (node != NULL) dns_db_detachnode(db, &node); return (ret); } static isc_result_t verifynsec3(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *origin, isc_mem_t *mctx, dns_name_t *name, dns_rdata_t *rdata, isc_boolean_t delegation, isc_boolean_t empty, unsigned char types[8192], unsigned int maxtype) { char namebuf[DNS_NAME_FORMATSIZE]; char hashbuf[DNS_NAME_FORMATSIZE]; dns_rdataset_t rdataset; dns_rdata_nsec3param_t nsec3param; dns_fixedname_t fixed; dns_name_t *hashname; isc_result_t result; dns_dbnode_t *node = NULL; unsigned char rawhash[NSEC3_MAX_HASH_LENGTH]; size_t rhsize = sizeof(rawhash); isc_boolean_t optout; result = dns_rdata_tostruct(rdata, &nsec3param, NULL); check_result(result, "dns_rdata_tostruct()"); if (nsec3param.flags != 0) return (ISC_R_SUCCESS); if (!dns_nsec3_supportedhash(nsec3param.hash)) return (ISC_R_SUCCESS); optout = isoptout(db, ver, origin, rdata); dns_fixedname_init(&fixed); result = dns_nsec3_hashname(&fixed, rawhash, &rhsize, name, origin, nsec3param.hash, nsec3param.iterations, nsec3param.salt, nsec3param.salt_length); check_result(result, "dns_nsec3_hashname()"); /* * We don't use dns_db_find() here as it works with the choosen * nsec3 chain and we may also be called with uncommitted data * from dnssec-signzone so the secure status of the zone may not * be up to date. */ dns_rdataset_init(&rdataset); hashname = dns_fixedname_name(&fixed); result = dns_db_findnsec3node(db, hashname, ISC_FALSE, &node); if (result == ISC_R_SUCCESS) result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3, 0, 0, &rdataset, NULL); if (result != ISC_R_SUCCESS && (!delegation || (empty && !optout) || (!empty && dns_nsec_isset(types, dns_rdatatype_ds)))) { dns_name_format(name, namebuf, sizeof(namebuf)); dns_name_format(hashname, hashbuf, sizeof(hashbuf)); fprintf(stderr, "Missing NSEC3 record for %s (%s)\n", namebuf, hashbuf); } else if (result == ISC_R_NOTFOUND && delegation && (!empty || optout)) { result = ISC_R_SUCCESS; } else if (result == ISC_R_SUCCESS) { result = match_nsec3(name, mctx, &nsec3param, &rdataset, types, maxtype, rawhash, rhsize); } if (dns_rdataset_isassociated(&rdataset)) dns_rdataset_disassociate(&rdataset); if (node != NULL) dns_db_detachnode(db, &node); return (result); } static isc_result_t verifynsec3s(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *origin, isc_mem_t *mctx, dns_name_t *name, dns_rdataset_t *nsec3paramset, isc_boolean_t delegation, isc_boolean_t empty, unsigned char types[8192], unsigned int maxtype) { isc_result_t result; for (result = dns_rdataset_first(nsec3paramset); result == ISC_R_SUCCESS; result = dns_rdataset_next(nsec3paramset)) { dns_rdata_t rdata = DNS_RDATA_INIT; dns_rdataset_current(nsec3paramset, &rdata); result = verifynsec3(db, ver, origin, mctx, name, &rdata, delegation, empty, types, maxtype); if (result != ISC_R_SUCCESS) break; } if (result == ISC_R_NOMORE) result = ISC_R_SUCCESS; return (result); } static void verifyset(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *origin, isc_mem_t *mctx, dns_rdataset_t *rdataset, dns_name_t *name, dns_dbnode_t *node, dns_rdataset_t *keyrdataset, unsigned char *act_algorithms, unsigned char *bad_algorithms) { unsigned char set_algorithms[256]; char namebuf[DNS_NAME_FORMATSIZE]; char algbuf[80]; char typebuf[80]; dns_rdataset_t sigrdataset; dns_rdatasetiter_t *rdsiter = NULL; isc_result_t result; int i; dns_rdataset_init(&sigrdataset); result = dns_db_allrdatasets(db, node, ver, 0, &rdsiter); check_result(result, "dns_db_allrdatasets()"); for (result = dns_rdatasetiter_first(rdsiter); result == ISC_R_SUCCESS; result = dns_rdatasetiter_next(rdsiter)) { dns_rdatasetiter_current(rdsiter, &sigrdataset); if (sigrdataset.type == dns_rdatatype_rrsig && sigrdataset.covers == rdataset->type) break; dns_rdataset_disassociate(&sigrdataset); } if (result != ISC_R_SUCCESS) { dns_name_format(name, namebuf, sizeof(namebuf)); type_format(rdataset->type, typebuf, sizeof(typebuf)); fprintf(stderr, "No signatures for %s/%s\n", namebuf, typebuf); for (i = 0; i < 256; i++) if (act_algorithms[i] != 0) bad_algorithms[i] = 1; dns_rdatasetiter_destroy(&rdsiter); return; } memset(set_algorithms, 0, sizeof(set_algorithms)); for (result = dns_rdataset_first(&sigrdataset); result == ISC_R_SUCCESS; result = dns_rdataset_next(&sigrdataset)) { dns_rdata_t rdata = DNS_RDATA_INIT; dns_rdata_rrsig_t sig; dns_rdataset_current(&sigrdataset, &rdata); result = dns_rdata_tostruct(&rdata, &sig, NULL); check_result(result, "dns_rdata_tostruct()"); if (rdataset->ttl != sig.originalttl) { dns_name_format(name, namebuf, sizeof(namebuf)); type_format(rdataset->type, typebuf, sizeof(typebuf)); fprintf(stderr, "TTL mismatch for %s %s keytag %u\n", namebuf, typebuf, sig.keyid); continue; } if ((set_algorithms[sig.algorithm] != 0) || (act_algorithms[sig.algorithm] == 0)) continue; if (goodsig(origin, &rdata, name, keyrdataset, rdataset, mctx)) set_algorithms[sig.algorithm] = 1; } dns_rdatasetiter_destroy(&rdsiter); if (memcmp(set_algorithms, act_algorithms, sizeof(set_algorithms))) { dns_name_format(name, namebuf, sizeof(namebuf)); type_format(rdataset->type, typebuf, sizeof(typebuf)); for (i = 0; i < 256; i++) if ((act_algorithms[i] != 0) && (set_algorithms[i] == 0)) { dns_secalg_format(i, algbuf, sizeof(algbuf)); fprintf(stderr, "No correct %s signature for " "%s %s\n", algbuf, namebuf, typebuf); bad_algorithms[i] = 1; } } dns_rdataset_disassociate(&sigrdataset); } static isc_result_t verifynode(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *origin, isc_mem_t *mctx, dns_name_t *name, dns_dbnode_t *node, isc_boolean_t delegation, dns_rdataset_t *keyrdataset, unsigned char *act_algorithms, unsigned char *bad_algorithms, dns_rdataset_t *nsecset, dns_rdataset_t *nsec3paramset, dns_name_t *nextname) { unsigned char types[8192]; unsigned int maxtype = 0; dns_rdataset_t rdataset; dns_rdatasetiter_t *rdsiter = NULL; isc_result_t result, tresult; memset(types, 0, sizeof(types)); result = dns_db_allrdatasets(db, node, ver, 0, &rdsiter); check_result(result, "dns_db_allrdatasets()"); result = dns_rdatasetiter_first(rdsiter); dns_rdataset_init(&rdataset); while (result == ISC_R_SUCCESS) { dns_rdatasetiter_current(rdsiter, &rdataset); /* * If we are not at a delegation then everything should be * signed. If we are at a delegation then only the DS set * is signed. The NS set is not signed at a delegation but * its existance is recorded in the bit map. Anything else * other than NSEC and DS is not signed at a delegation. */ if (rdataset.type != dns_rdatatype_rrsig && rdataset.type != dns_rdatatype_dnskey && (!delegation || rdataset.type == dns_rdatatype_ds || rdataset.type == dns_rdatatype_nsec)) { verifyset(db, ver, origin, mctx, &rdataset, name, node, keyrdataset, act_algorithms, bad_algorithms); dns_nsec_setbit(types, rdataset.type, 1); if (rdataset.type > maxtype) maxtype = rdataset.type; } else if (rdataset.type != dns_rdatatype_rrsig && rdataset.type != dns_rdatatype_dnskey) { if (rdataset.type == dns_rdatatype_ns) dns_nsec_setbit(types, rdataset.type, 1); check_no_rrsig(db, ver, &rdataset, name, node); } else dns_nsec_setbit(types, rdataset.type, 1); dns_rdataset_disassociate(&rdataset); result = dns_rdatasetiter_next(rdsiter); } if (result != ISC_R_NOMORE) fatal("rdataset iteration failed: %s", isc_result_totext(result)); dns_rdatasetiter_destroy(&rdsiter); result = ISC_R_SUCCESS; if (nsecset != NULL && dns_rdataset_isassociated(nsecset)) result = verifynsec(db, ver, name, node, nextname); if (nsec3paramset != NULL && dns_rdataset_isassociated(nsec3paramset)) { tresult = verifynsec3s(db, ver, origin, mctx, name, nsec3paramset, delegation, ISC_FALSE, types, maxtype); if (result == ISC_R_SUCCESS && tresult != ISC_R_SUCCESS) result = tresult; } return (result); } static isc_boolean_t is_empty(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node) { dns_rdatasetiter_t *rdsiter = NULL; isc_result_t result; result = dns_db_allrdatasets(db, node, ver, 0, &rdsiter); check_result(result, "dns_db_allrdatasets()"); result = dns_rdatasetiter_first(rdsiter); dns_rdatasetiter_destroy(&rdsiter); if (result == ISC_R_NOMORE) return (ISC_TRUE); return (ISC_FALSE); } static void check_no_nsec(dns_name_t *name, dns_dbnode_t *node, dns_db_t *db, dns_dbversion_t *ver) { dns_rdataset_t rdataset; isc_result_t result; dns_rdataset_init(&rdataset); result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec, 0, 0, &rdataset, NULL); if (result != ISC_R_NOTFOUND) { char namebuf[DNS_NAME_FORMATSIZE]; dns_name_format(name, namebuf, sizeof(namebuf)); fatal("unexpected NSEC RRset at %s\n", namebuf); } if (dns_rdataset_isassociated(&rdataset)) dns_rdataset_disassociate(&rdataset); } static isc_boolean_t newchain(const struct nsec3_chain_fixed *first, const struct nsec3_chain_fixed *e) { if (first->hash != e->hash || first->iterations != e->iterations || first->salt_length != e->salt_length || first->next_length != e->next_length || memcmp(first + 1, e + 1, first->salt_length) != 0) return (ISC_TRUE); return (ISC_FALSE); } static void free_element(isc_mem_t *mctx, struct nsec3_chain_fixed *e) { size_t len; len = sizeof(*e) + e->salt_length + 2 * e->next_length; isc_mem_put(mctx, e, len); } static isc_boolean_t checknext(const struct nsec3_chain_fixed *first, const struct nsec3_chain_fixed *e) { char buf[512]; const unsigned char *d1 = (const unsigned char *)(first + 1); const unsigned char *d2 = (const unsigned char *)(e + 1); isc_buffer_t b; isc_region_t sr; d1 += first->salt_length + first->next_length; d2 += e->salt_length; if (memcmp(d1, d2, first->next_length) == 0) return (ISC_TRUE); DE_CONST(d1 - first->next_length, sr.base); sr.length = first->next_length; isc_buffer_init(&b, buf, sizeof(buf)); isc_base32hex_totext(&sr, 1, "", &b); fprintf(stderr, "Break in NSEC3 chain at: %.*s\n", (int) isc_buffer_usedlength(&b), buf); DE_CONST(d1, sr.base); sr.length = first->next_length; isc_buffer_init(&b, buf, sizeof(buf)); isc_base32hex_totext(&sr, 1, "", &b); fprintf(stderr, "Expected: %.*s\n", (int) isc_buffer_usedlength(&b), buf); DE_CONST(d2, sr.base); sr.length = first->next_length; isc_buffer_init(&b, buf, sizeof(buf)); isc_base32hex_totext(&sr, 1, "", &b); fprintf(stderr, "Found: %.*s\n", (int) isc_buffer_usedlength(&b), buf); return (ISC_FALSE); } #define EXPECTEDANDFOUND "Expected and found NSEC3 chains not equal\n" static isc_result_t verify_nsec3_chains(isc_mem_t *mctx) { isc_result_t result = ISC_R_SUCCESS; struct nsec3_chain_fixed *e, *f = NULL; struct nsec3_chain_fixed *first = NULL, *prev = NULL; while ((e = isc_heap_element(expected_chains, 1)) != NULL) { isc_heap_delete(expected_chains, 1); if (f == NULL) f = isc_heap_element(found_chains, 1); if (f != NULL) { isc_heap_delete(found_chains, 1); /* * Check that they match. */ if (chain_equal(e, f)) { free_element(mctx, f); f = NULL; } else { if (result == ISC_R_SUCCESS) fprintf(stderr, EXPECTEDANDFOUND); result = ISC_R_FAILURE; /* * Attempt to resync found_chain. */ while (f != NULL && !chain_compare(e, f)) { free_element(mctx, f); f = isc_heap_element(found_chains, 1); if (f != NULL) isc_heap_delete(found_chains, 1); if (f != NULL && chain_equal(e, f)) { free_element(mctx, f); f = NULL; break; } } } } else if (result == ISC_R_SUCCESS) { fprintf(stderr, EXPECTEDANDFOUND); result = ISC_R_FAILURE; } if (first == NULL || newchain(first, e)) { if (prev != NULL) { if (!checknext(prev, first)) result = ISC_R_FAILURE; if (prev != first) free_element(mctx, prev); } if (first != NULL) free_element(mctx, first); prev = first = e; continue; } if (!checknext(prev, e)) result = ISC_R_FAILURE; if (prev != first) free_element(mctx, prev); prev = e; } if (prev != NULL) { if (!checknext(prev, first)) result = ISC_R_FAILURE; if (prev != first) free_element(mctx, prev); } if (first != NULL) free_element(mctx, first); do { if (f != NULL) { if (result == ISC_R_SUCCESS) { fprintf(stderr, EXPECTEDANDFOUND); result = ISC_R_FAILURE; } free_element(mctx, f); } f = isc_heap_element(found_chains, 1); if (f != NULL) isc_heap_delete(found_chains, 1); } while (f != NULL); return (result); } static isc_result_t verifyemptynodes(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *origin, isc_mem_t *mctx, dns_name_t *name, dns_name_t *prevname, isc_boolean_t isdelegation, dns_rdataset_t *nsec3paramset) { dns_namereln_t reln; int order; unsigned int labels, nlabels, i; dns_name_t suffix; isc_result_t result = ISC_R_SUCCESS, tresult; reln = dns_name_fullcompare(prevname, name, &order, &labels); if (order >= 0) return (result); nlabels = dns_name_countlabels(name); if (reln == dns_namereln_commonancestor || reln == dns_namereln_contains) { dns_name_init(&suffix, NULL); for (i = labels + 1; i < nlabels; i++) { dns_name_getlabelsequence(name, nlabels - i, i, &suffix); if (nsec3paramset != NULL && dns_rdataset_isassociated(nsec3paramset)) { tresult = verifynsec3s(db, ver, origin, mctx, &suffix, nsec3paramset, isdelegation, ISC_TRUE, NULL, 0); if (result == ISC_R_SUCCESS && tresult != ISC_R_SUCCESS) result = tresult; } } } return (result); } /*% * Verify that certain things are sane: * * The apex has a DNSKEY record with at least one KSK, and at least * one ZSK if the -x flag was not used. * * The DNSKEY record was signed with at least one of the KSKs in this * set. * * The rest of the zone was signed with at least one of the ZSKs * present in the DNSKEY RRSET. */ void verifyzone(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *origin, isc_mem_t *mctx, isc_boolean_t ignore_kskflag, isc_boolean_t keyset_kskonly) { char algbuf[80]; dns_dbiterator_t *dbiter = NULL; dns_dbnode_t *node = NULL, *nextnode = NULL; dns_fixedname_t fname, fnextname, fprevname, fzonecut; dns_name_t *name, *nextname, *prevname, *zonecut; dns_rdata_dnskey_t dnskey; dns_rdata_t rdata = DNS_RDATA_INIT; dns_rdataset_t keyset, soaset; dns_rdataset_t keysigs, soasigs; dns_rdataset_t nsecset, nsecsigs; dns_rdataset_t nsec3paramset, nsec3paramsigs; int i; isc_boolean_t done = ISC_FALSE; isc_boolean_t first = ISC_TRUE; isc_boolean_t goodksk = ISC_FALSE; isc_boolean_t goodzsk = ISC_FALSE; isc_result_t result, vresult = ISC_R_UNSET; unsigned char revoked_ksk[256]; unsigned char revoked_zsk[256]; unsigned char standby_ksk[256]; unsigned char standby_zsk[256]; unsigned char ksk_algorithms[256]; unsigned char zsk_algorithms[256]; unsigned char bad_algorithms[256]; unsigned char act_algorithms[256]; result = isc_heap_create(mctx, chain_compare, NULL, 1024, &expected_chains); check_result(result, "isc_heap_create()"); result = isc_heap_create(mctx, chain_compare, NULL, 1024, &found_chains); check_result(result, "isc_heap_create()"); result = dns_db_findnode(db, origin, ISC_FALSE, &node); if (result != ISC_R_SUCCESS) fatal("failed to find the zone's origin: %s", isc_result_totext(result)); dns_rdataset_init(&keyset); dns_rdataset_init(&keysigs); dns_rdataset_init(&soaset); dns_rdataset_init(&soasigs); dns_rdataset_init(&nsecset); dns_rdataset_init(&nsecsigs); dns_rdataset_init(&nsec3paramset); dns_rdataset_init(&nsec3paramsigs); result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey, 0, 0, &keyset, &keysigs); if (result != ISC_R_SUCCESS) fatal("Zone contains no DNSSEC keys\n"); result = dns_db_findrdataset(db, node, ver, dns_rdatatype_soa, 0, 0, &soaset, &soasigs); if (result != ISC_R_SUCCESS) fatal("Zone contains no SOA record\n"); result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec, 0, 0, &nsecset, &nsecsigs); if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) fatal("NSEC lookup failed\n"); result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param, 0, 0, &nsec3paramset, &nsec3paramsigs); if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) fatal("NSEC3PARAM lookup failed\n"); if (!dns_rdataset_isassociated(&keysigs)) fatal("DNSKEY is not signed (keys offline or inactive?)\n"); if (!dns_rdataset_isassociated(&soasigs)) fatal("SOA is not signed (keys offline or inactive?)\n"); if (dns_rdataset_isassociated(&nsecset) && !dns_rdataset_isassociated(&nsecsigs)) fatal("NSEC is not signed (keys offline or inactive?)\n"); if (dns_rdataset_isassociated(&nsec3paramset) && !dns_rdataset_isassociated(&nsec3paramsigs)) fatal("NSEC3PARAM is not signed (keys offline or inactive?)\n"); if (!dns_rdataset_isassociated(&nsecset) && !dns_rdataset_isassociated(&nsec3paramset)) fatal("No valid NSEC/NSEC3 chain for testing\n"); dns_db_detachnode(db, &node); memset(revoked_ksk, 0, sizeof(revoked_ksk)); memset(revoked_zsk, 0, sizeof(revoked_zsk)); memset(standby_ksk, 0, sizeof(standby_ksk)); memset(standby_zsk, 0, sizeof(standby_zsk)); memset(ksk_algorithms, 0, sizeof(ksk_algorithms)); memset(zsk_algorithms, 0, sizeof(zsk_algorithms)); memset(bad_algorithms, 0, sizeof(bad_algorithms)); memset(act_algorithms, 0, sizeof(act_algorithms)); /* * Check that the DNSKEY RR has at least one self signing KSK * and one ZSK per algorithm in it (or, if -x was used, one * self-signing KSK). */ for (result = dns_rdataset_first(&keyset); result == ISC_R_SUCCESS; result = dns_rdataset_next(&keyset)) { dns_rdataset_current(&keyset, &rdata); result = dns_rdata_tostruct(&rdata, &dnskey, NULL); check_result(result, "dns_rdata_tostruct"); if ((dnskey.flags & DNS_KEYOWNER_ZONE) == 0) ; else if ((dnskey.flags & DNS_KEYFLAG_REVOKE) != 0) { if ((dnskey.flags & DNS_KEYFLAG_KSK) != 0 && !dns_dnssec_selfsigns(&rdata, origin, &keyset, &keysigs, ISC_FALSE, mctx)) { char namebuf[DNS_NAME_FORMATSIZE]; char buffer[1024]; isc_buffer_t buf; dns_name_format(origin, namebuf, sizeof(namebuf)); isc_buffer_init(&buf, buffer, sizeof(buffer)); result = dns_rdata_totext(&rdata, NULL, &buf); check_result(result, "dns_rdata_totext"); fatal("revoked KSK is not self signed:\n" "%s DNSKEY %.*s", namebuf, (int)isc_buffer_usedlength(&buf), buffer); } if ((dnskey.flags & DNS_KEYFLAG_KSK) != 0 && revoked_ksk[dnskey.algorithm] != 255) revoked_ksk[dnskey.algorithm]++; else if ((dnskey.flags & DNS_KEYFLAG_KSK) == 0 && revoked_zsk[dnskey.algorithm] != 255) revoked_zsk[dnskey.algorithm]++; } else if ((dnskey.flags & DNS_KEYFLAG_KSK) != 0) { if (dns_dnssec_selfsigns(&rdata, origin, &keyset, &keysigs, ISC_FALSE, mctx)) { if (ksk_algorithms[dnskey.algorithm] != 255) ksk_algorithms[dnskey.algorithm]++; goodksk = ISC_TRUE; } else { if (standby_ksk[dnskey.algorithm] != 255) standby_ksk[dnskey.algorithm]++; } } else if (dns_dnssec_selfsigns(&rdata, origin, &keyset, &keysigs, ISC_FALSE, mctx)) { if (zsk_algorithms[dnskey.algorithm] != 255) zsk_algorithms[dnskey.algorithm]++; goodzsk = ISC_TRUE; } else if (dns_dnssec_signs(&rdata, origin, &soaset, &soasigs, ISC_FALSE, mctx)) { if (zsk_algorithms[dnskey.algorithm] != 255) zsk_algorithms[dnskey.algorithm]++; } else { if (standby_zsk[dnskey.algorithm] != 255) standby_zsk[dnskey.algorithm]++; } dns_rdata_freestruct(&dnskey); dns_rdata_reset(&rdata); } dns_rdataset_disassociate(&keysigs); dns_rdataset_disassociate(&soaset); dns_rdataset_disassociate(&soasigs); if (dns_rdataset_isassociated(&nsecsigs)) dns_rdataset_disassociate(&nsecsigs); if (dns_rdataset_isassociated(&nsec3paramsigs)) dns_rdataset_disassociate(&nsec3paramsigs); if (ignore_kskflag ) { if (!goodksk && !goodzsk) fatal("No self-signed DNSKEY found."); } else if (!goodksk) fatal("No self-signed KSK DNSKEY found. Supply an active\n" "key with the KSK flag set, or use '-P'."); fprintf(stderr, "Verifying the zone using the following algorithms:"); for (i = 0; i < 256; i++) { if (ignore_kskflag) act_algorithms[i] = (ksk_algorithms[i] != 0 || zsk_algorithms[i] != 0) ? 1 : 0; else act_algorithms[i] = ksk_algorithms[i] != 0 ? 1 : 0; if (act_algorithms[i] != 0) { dns_secalg_format(i, algbuf, sizeof(algbuf)); fprintf(stderr, " %s", algbuf); } } fprintf(stderr, ".\n"); if (!ignore_kskflag && !keyset_kskonly) { for (i = 0; i < 256; i++) { /* * The counts should both be zero or both be non-zero. * Mark the algorithm as bad if this is not met. */ if ((ksk_algorithms[i] != 0) == (zsk_algorithms[i] != 0)) continue; dns_secalg_format(i, algbuf, sizeof(algbuf)); fprintf(stderr, "Missing %s for algorithm %s\n", (ksk_algorithms[i] != 0) ? "ZSK" : "self-signed KSK", algbuf); bad_algorithms[i] = 1; } } /* * Check that all the other records were signed by keys that are * present in the DNSKEY RRSET. */ dns_fixedname_init(&fname); name = dns_fixedname_name(&fname); dns_fixedname_init(&fnextname); nextname = dns_fixedname_name(&fnextname); dns_fixedname_init(&fprevname); prevname = NULL; dns_fixedname_init(&fzonecut); zonecut = NULL; result = dns_db_createiterator(db, DNS_DB_NONSEC3, &dbiter); check_result(result, "dns_db_createiterator()"); result = dns_dbiterator_first(dbiter); check_result(result, "dns_dbiterator_first()"); while (!done) { isc_boolean_t isdelegation = ISC_FALSE; result = dns_dbiterator_current(dbiter, &node, name); check_dns_dbiterator_current(result); if (!dns_name_issubdomain(name, origin)) { check_no_nsec(name, node, db, ver); dns_db_detachnode(db, &node); result = dns_dbiterator_next(dbiter); if (result == ISC_R_NOMORE) done = ISC_TRUE; else check_result(result, "dns_dbiterator_next()"); continue; } if (is_delegation(db, ver, origin, name, node, NULL)) { zonecut = dns_fixedname_name(&fzonecut); dns_name_copy(name, zonecut, NULL); isdelegation = ISC_TRUE; } nextnode = NULL; result = dns_dbiterator_next(dbiter); while (result == ISC_R_SUCCESS) { result = dns_dbiterator_current(dbiter, &nextnode, nextname); check_dns_dbiterator_current(result); if (!dns_name_issubdomain(nextname, origin) || (zonecut != NULL && dns_name_issubdomain(nextname, zonecut))) { check_no_nsec(nextname, nextnode, db, ver); dns_db_detachnode(db, &nextnode); result = dns_dbiterator_next(dbiter); continue; } if (is_empty(db, ver, nextnode)) { dns_db_detachnode(db, &nextnode); result = dns_dbiterator_next(dbiter); continue; } dns_db_detachnode(db, &nextnode); break; } if (result == ISC_R_NOMORE) { done = ISC_TRUE; nextname = origin; } else if (result != ISC_R_SUCCESS) fatal("iterating through the database failed: %s", isc_result_totext(result)); result = verifynode(db, ver, origin, mctx, name, node, isdelegation, &keyset, act_algorithms, bad_algorithms, &nsecset, &nsec3paramset, nextname); if (vresult == ISC_R_UNSET) vresult = ISC_R_SUCCESS; if (vresult == ISC_R_SUCCESS && result != ISC_R_SUCCESS) vresult = result; if (prevname != NULL) { result = verifyemptynodes(db, ver, origin, mctx, name, prevname, isdelegation, &nsec3paramset); } else prevname = dns_fixedname_name(&fprevname); dns_name_copy(name, prevname, NULL); if (vresult == ISC_R_SUCCESS && result != ISC_R_SUCCESS) vresult = result; dns_db_detachnode(db, &node); } dns_dbiterator_destroy(&dbiter); result = dns_db_createiterator(db, DNS_DB_NSEC3ONLY, &dbiter); check_result(result, "dns_db_createiterator()"); for (result = dns_dbiterator_first(dbiter); result == ISC_R_SUCCESS; result = dns_dbiterator_next(dbiter) ) { result = dns_dbiterator_current(dbiter, &node, name); check_dns_dbiterator_current(result); result = verifynode(db, ver, origin, mctx, name, node, ISC_FALSE, &keyset, act_algorithms, bad_algorithms, NULL, NULL, NULL); check_result(result, "verifynode"); record_found(db, ver, mctx, name, node, &nsec3paramset); dns_db_detachnode(db, &node); } dns_dbiterator_destroy(&dbiter); dns_rdataset_disassociate(&keyset); if (dns_rdataset_isassociated(&nsecset)) dns_rdataset_disassociate(&nsecset); if (dns_rdataset_isassociated(&nsec3paramset)) dns_rdataset_disassociate(&nsec3paramset); result = verify_nsec3_chains(mctx); if (vresult == ISC_R_UNSET) vresult = ISC_R_SUCCESS; if (result != ISC_R_SUCCESS && vresult == ISC_R_SUCCESS) vresult = result; isc_heap_destroy(&expected_chains); isc_heap_destroy(&found_chains); /* * If we made it this far, we have what we consider a properly signed * zone. Set the good flag. */ for (i = 0; i < 256; i++) { if (bad_algorithms[i] != 0) { if (first) fprintf(stderr, "The zone is not fully signed " "for the following algorithms:"); dns_secalg_format(i, algbuf, sizeof(algbuf)); fprintf(stderr, " %s", algbuf); first = ISC_FALSE; } } if (!first) { fprintf(stderr, ".\n"); fatal("DNSSEC completeness test failed."); } if (vresult != ISC_R_SUCCESS) fatal("DNSSEC completeness test failed (%s).", dns_result_totext(vresult)); if (goodksk || ignore_kskflag) { /* * Print the success summary. */ fprintf(stderr, "Zone fully signed:\n"); for (i = 0; i < 256; i++) { if ((ksk_algorithms[i] != 0) || (standby_ksk[i] != 0) || (revoked_ksk[i] != 0) || (zsk_algorithms[i] != 0) || (standby_zsk[i] != 0) || (revoked_zsk[i] != 0)) { dns_secalg_format(i, algbuf, sizeof(algbuf)); fprintf(stderr, "Algorithm: %s: KSKs: " "%u active, %u stand-by, %u revoked\n", algbuf, ksk_algorithms[i], standby_ksk[i], revoked_ksk[i]); fprintf(stderr, "%*sZSKs: " "%u active, %u %s, %u revoked\n", (int) strlen(algbuf) + 13, "", zsk_algorithms[i], standby_zsk[i], keyset_kskonly ? "present" : "stand-by", revoked_zsk[i]); } } } } isc_boolean_t isoptarg(const char *arg, char **argv, void(*usage)(void)) { if (!strcasecmp(isc_commandline_argument, arg)) { if (argv[isc_commandline_index] == NULL) { fprintf(stderr, "%s: missing argument -%c %s\n", program, isc_commandline_option, isc_commandline_argument); usage(); } isc_commandline_argument = argv[isc_commandline_index]; /* skip to next arguement */ isc_commandline_index++; return (ISC_TRUE); } return (ISC_FALSE); } #ifdef _WIN32 void InitSockets(void) { WORD wVersionRequested; WSADATA wsaData; int err; wVersionRequested = MAKEWORD(2, 0); err = WSAStartup( wVersionRequested, &wsaData ); if (err != 0) { fprintf(stderr, "WSAStartup() failed: %d\n", err); exit(1); } } void DestroySockets(void) { WSACleanup(); } #endif bind9-9.11.3+dfsg/bin/dnssec/dnssectool.h000066400000000000000000000047521325250447100201210ustar00rootroot00000000000000/* * Copyright (C) 2000, 2001, 2003, 2004, 2007-2012, 2014-2017 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* $Id: dnssectool.h,v 1.33 2011/10/20 23:46:51 tbox Exp $ */ #ifndef DNSSECTOOL_H #define DNSSECTOOL_H 1 #include #include #include #include #define check_dns_dbiterator_current(result) \ check_result((result == DNS_R_NEWORIGIN) ? ISC_R_SUCCESS : result, \ "dns_dbiterator_current()") typedef void (fatalcallback_t)(void); ISC_PLATFORM_NORETURN_PRE void fatal(const char *format, ...) ISC_FORMAT_PRINTF(1, 2) ISC_PLATFORM_NORETURN_POST; void setfatalcallback(fatalcallback_t *callback); void check_result(isc_result_t result, const char *message); void vbprintf(int level, const char *fmt, ...) ISC_FORMAT_PRINTF(2, 3); ISC_PLATFORM_NORETURN_PRE void version(const char *program) ISC_PLATFORM_NORETURN_POST; void type_format(const dns_rdatatype_t type, char *cp, unsigned int size); #define TYPE_FORMATSIZE 20 void sig_format(dns_rdata_rrsig_t *sig, char *cp, unsigned int size); #define SIG_FORMATSIZE (DNS_NAME_FORMATSIZE + DNS_SECALG_FORMATSIZE + sizeof("65535")) void setup_logging(isc_mem_t *mctx, isc_log_t **logp); void cleanup_logging(isc_log_t **logp); void setup_entropy(isc_mem_t *mctx, const char *randomfile, isc_entropy_t **ectx); void cleanup_entropy(isc_entropy_t **ectx); dns_ttl_t strtottl(const char *str); isc_stdtime_t strtotime(const char *str, isc_int64_t now, isc_int64_t base, isc_boolean_t *setp); dns_rdataclass_t strtoclass(const char *str); isc_result_t try_dir(const char *dirname); void check_keyversion(dst_key_t *key, char *keystr); void set_keyversion(dst_key_t *key); isc_boolean_t key_collision(dst_key_t *key, dns_name_t *name, const char *dir, isc_mem_t *mctx, isc_boolean_t *exact); isc_boolean_t is_delegation(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *origin, dns_name_t *name, dns_dbnode_t *node, isc_uint32_t *ttlp); void verifyzone(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *origin, isc_mem_t *mctx, isc_boolean_t ignore_kskflag, isc_boolean_t keyset_kskonly); isc_boolean_t isoptarg(const char *arg, char **argv, void (*usage)(void)); #ifdef _WIN32 void InitSockets(void); void DestroySockets(void); #endif #endif /* DNSSEC_DNSSECTOOL_H */ bind9-9.11.3+dfsg/bin/dnssec/win32/000077500000000000000000000000001325250447100165255ustar00rootroot00000000000000bind9-9.11.3+dfsg/bin/dnssec/win32/dnssectool.dsp.in000066400000000000000000000075541325250447100220320ustar00rootroot00000000000000# Microsoft Developer Studio Project File - Name="dnssectool" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "@PLATFORM@ (x86) Static-Link Library" 0x0104 CFG=dnssectool - @PLATFORM@ Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "dnssectool.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "dnssectool.mak" CFG="dnssectool - @PLATFORM@ Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "dnssectool - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Static-Link Library") !MESSAGE "dnssectool - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Static-Link Library") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe MTL=midl.exe RSC=rc.exe !IF "$(CFG)" == "dnssectool - @PLATFORM@ Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MT /W3 @COPTX@ @COPTI@ /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" @COPTY@ /FD /c # ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../include" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" @CRYPTO@ /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "__STDC__" /D "_MBCS" @COPTY@ /FD /c /Fddnssectool # SUBTRACT CPP /X # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 # ADD LINK32 /out:"Release/dnssectool.lib" !ELSEIF "$(CFG)" == "dnssectool - @PLATFORM@ Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MTd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" @COPTY@ /FD /GZ /c # ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../include" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" @CRYPTO@ /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "__STDC__" /D "_MBCS" /FR @COPTY@ /FD /GZ /c /Fddnssectool # SUBTRACT CPP /X # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 # ADD LINK32 /debug out:"Debug/dnssectool.lib" !ENDIF # Begin Target # Name "dnssectool - @PLATFORM@ Release" # Name "dnssectool - @PLATFORM@ Debug" # Begin Group "Source Files" # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" # End Group # Begin Group "Header Files" # PROP Default_Filter "h;hpp;hxx;hm;inl" # End Group # Begin Group "Resource Files" # PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" # End Group # Begin Group "Main Dns Lib" # PROP Default_Filter "c" # Begin Source File SOURCE=..\dnssectool.c # End Source File # End Group # End Target # End Project bind9-9.11.3+dfsg/bin/dnssec/win32/dnssectool.dsw000066400000000000000000000010411325250447100214150ustar00rootroot00000000000000Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "dnssectool"=".\dnssectool.dsp" - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### bind9-9.11.3+dfsg/bin/dnssec/win32/dnssectool.vcxproj.filters.in000066400000000000000000000021011325250447100243650ustar00rootroot00000000000000 {4FC737F1-C7A5-4376-A066-2A32D752A2FF} cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx {93995380-89BD-4b04-88EB-625FBE52EBFB} h;hpp;hxx;hm;inl;inc;xsd {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms Header Files Source Files bind9-9.11.3+dfsg/bin/dnssec/win32/dnssectool.vcxproj.in000066400000000000000000000135251325250447100227320ustar00rootroot00000000000000 Debug @PLATFORM@ Release @PLATFORM@ {2CB7DC75-023B-4AA3-AF3A-AE5046A4EE70} Win32Proj dnssectool StaticLibrary true MultiByte StaticLibrary false true MultiByte .\$(Configuration)\ .\$(Configuration)\ .\$(Configuration)\ .\$(Configuration)\ Level3 Disabled WIN32;@CRYPTO@_DEBUG;_LIB;%(PreprocessorDefinitions) true .\$(Configuration)\$(TargetName).pch .\$(Configuration)\ .\$(Configuration)\ $(OutDir)$(TargetName).pdb true .\;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@..\include;..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;%(AdditionalIncludeDirectories) CompileAsC Windows true Level3 MaxSpeed true @INTRINSIC@ WIN32;@CRYPTO@NDEBUG;_LIB;%(PreprocessorDefinitions) OnlyExplicitInline false true .\$(Configuration)\$(TargetName).pch .\$(Configuration)\ .\$(Configuration)\ $(OutDir)$(TargetName).pdb .\;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@..\include;..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;%(AdditionalIncludeDirectories) CompileAsC Windows true true true false bind9-9.11.3+dfsg/bin/dnssec/win32/dnssectool.vcxproj.user000066400000000000000000000002171325250447100232740ustar00rootroot00000000000000 bind9-9.11.3+dfsg/bin/dnssec/win32/dsfromkey.dsp.in000066400000000000000000000110141325250447100216420ustar00rootroot00000000000000# Microsoft Developer Studio Project File - Name="dsfromkey" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "@PLATFORM@ (x86) Console Application" 0x0103 CFG=dsfromkey - @PLATFORM@ Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "dsfromkey.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "dsfromkey.mak" CFG="dsfromkey - @PLATFORM@ Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "dsfromkey - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE "dsfromkey - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "dsfromkey - @PLATFORM@ Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 @COPTX@ @COPTI@ /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c # ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" @CRYPTO@ /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console @MACHINE@ # ADD LINK32 user32.lib advapi32.lib Release/dnssectool.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib ws2_32.lib /nologo /subsystem:console @MACHINE@ /out:"../../../Build/Release/dnssec-dsfromkey.exe" !ELSEIF "$(CFG)" == "dsfromkey - @PLATFORM@ Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /GZ /c # ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" @CRYPTO@ /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c # SUBTRACT CPP /X @COPTY@ # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug @MACHINE@ /pdbtype:sept # ADD LINK32 user32.lib advapi32.lib Debug/dnssectool.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib ws2_32.lib /nologo /subsystem:console /debug @MACHINE@ /out:"../../../Build/Debug/dnssec-dsfromkey.exe" /pdbtype:sept !ENDIF # Begin Target # Name "dsfromkey - @PLATFORM@ Release" # Name "dsfromkey - @PLATFORM@ Debug" # Begin Group "Source Files" # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" # Begin Source File SOURCE="..\dnssec-dsfromkey.c" # End Source File # End Group # Begin Group "Header Files" # PROP Default_Filter "h;hpp;hxx;hm;inl" # End Group # Begin Group "Resource Files" # PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" # End Group # End Target # End Project bind9-9.11.3+dfsg/bin/dnssec/win32/dsfromkey.dsw000066400000000000000000000010371325250447100212500ustar00rootroot00000000000000Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "dsfromkey"=".\dsfromkey.dsp" - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### bind9-9.11.3+dfsg/bin/dnssec/win32/dsfromkey.mak.in000066400000000000000000000206461325250447100216370ustar00rootroot00000000000000# Microsoft Developer Studio Generated NMAKE File, Based on dsfromkey.dsp !IF "$(CFG)" == "" CFG=dsfromkey - @PLATFORM@ Debug !MESSAGE No configuration specified. Defaulting to dsfromkey - @PLATFORM@ Debug. !ENDIF !IF "$(CFG)" != "dsfromkey - @PLATFORM@ Release" && "$(CFG)" != "dsfromkey - @PLATFORM@ Debug" !MESSAGE Invalid configuration "$(CFG)" specified. !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "dsfromkey.mak" CFG="dsfromkey - @PLATFORM@ Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "dsfromkey - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE "dsfromkey - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE !ERROR An invalid configuration is specified. !ENDIF !IF "$(OS)" == "Windows_NT" NULL= !ELSE NULL=nul !ENDIF !IF "$(CFG)" == "dsfromkey - @PLATFORM@ Release" _VC_MANIFEST_INC=0 _VC_MANIFEST_BASENAME=__VC80 !ELSE _VC_MANIFEST_INC=1 _VC_MANIFEST_BASENAME=__VC80.Debug !ENDIF #################################################### # Specifying name of temporary resource file used only in incremental builds: !if "$(_VC_MANIFEST_INC)" == "1" _VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res !else _VC_MANIFEST_AUTO_RES= !endif #################################################### # _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE: !if "$(_VC_MANIFEST_INC)" == "1" #MT_SPECIAL_RETURN=1090650113 #MT_SPECIAL_SWITCH=-notify_resource_update MT_SPECIAL_RETURN=0 MT_SPECIAL_SWITCH= _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \ if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \ rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \ link $** /out:$@ $(LFLAGS) !else _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1 !endif #################################################### # _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL: !if "$(_VC_MANIFEST_INC)" == "1" #MT_SPECIAL_RETURN=1090650113 #MT_SPECIAL_SWITCH=-notify_resource_update MT_SPECIAL_RETURN=0 MT_SPECIAL_SWITCH= _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \ if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \ rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \ link $** /out:$@ $(LFLAGS) !else _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2 !endif #################################################### # _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily: !if "$(_VC_MANIFEST_INC)" == "1" _VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \ $(_VC_MANIFEST_BASENAME).auto.rc \ $(_VC_MANIFEST_BASENAME).auto.manifest !else _VC_MANIFEST_CLEAN= !endif !IF "$(CFG)" == "dsfromkey - @PLATFORM@ Release" OUTDIR=.\Release INTDIR=.\Release ALL : "..\..\..\Build\Release\dnssec-dsfromkey.exe" CLEAN : -@erase "$(INTDIR)\dnssec-dsfromkey.obj" -@erase "$(INTDIR)\dnssectool.obj" -@erase "$(INTDIR)\vc60.idb" -@erase "..\..\..\Build\Release\dnssec-dsfromkey.exe" -@$(_VC_MANIFEST_CLEAN) "$(OUTDIR)" : if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" CPP=cl.exe CPP_PROJ=/nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" @CRYPTO@ /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\dsfromkey.pch" @COPTY@ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c .c{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .c{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << RSC=rc.exe BSC32=bscmake.exe BSC32_FLAGS=/nologo /o"$(OUTDIR)\dsfromkey.bsc" BSC32_SBRS= \ LINK32=link.exe LINK32_FLAGS=user32.lib advapi32.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib ws2_32.lib /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\dnssec-dsfromkey.pdb" @MACHINE@ /out:"../../../Build/Release/dnssec-dsfromkey.exe" LINK32_OBJS= \ "$(INTDIR)\dnssec-dsfromkey.obj" \ "$(INTDIR)\dnssectool.obj" "..\..\..\Build\Release\dnssec-dsfromkey.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) $(LINK32) @<< $(LINK32_FLAGS) $(LINK32_OBJS) << $(_VC_MANIFEST_EMBED_EXE) !ELSEIF "$(CFG)" == "dsfromkey - @PLATFORM@ Debug" OUTDIR=.\Debug INTDIR=.\Debug # Begin Custom Macros OutDir=.\Debug # End Custom Macros ALL : "..\..\..\Build\Debug\dnssec-dsfromkey.exe" "$(OUTDIR)\dsfromkey.bsc" CLEAN : -@erase "$(INTDIR)\dnssec-dsfromkey.obj" -@erase "$(INTDIR)\dnssec-dsfromkey.sbr" -@erase "$(INTDIR)\dnssectool.obj" -@erase "$(INTDIR)\dnssectool.sbr" -@erase "$(INTDIR)\vc60.idb" -@erase "$(INTDIR)\vc60.pdb" -@erase "$(OUTDIR)\dnssec-dsfromkey.pdb" -@erase "$(OUTDIR)\dsfromkey.bsc" -@erase "..\..\..\Build\Debug\dnssec-dsfromkey.exe" -@erase "..\..\..\Build\Debug\dnssec-dsfromkey.ilk" -@$(_VC_MANIFEST_CLEAN) "$(OUTDIR)" : if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" CPP=cl.exe CPP_PROJ=/nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" @CRYPTO@ /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c .c{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .c{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << RSC=rc.exe BSC32=bscmake.exe BSC32_FLAGS=/nologo /o"$(OUTDIR)\dsfromkey.bsc" BSC32_SBRS= \ "$(INTDIR)\dnssec-dsfromkey.sbr" \ "$(INTDIR)\dnssectool.sbr" "$(OUTDIR)\dsfromkey.bsc" : "$(OUTDIR)" $(BSC32_SBRS) $(BSC32) @<< $(BSC32_FLAGS) $(BSC32_SBRS) << LINK32=link.exe LINK32_FLAGS=user32.lib advapi32.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib ws2_32.lib /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\dnssec-dsfromkey.pdb" /debug @MACHINE@ /out:"../../../Build/Debug/dnssec-dsfromkey.exe" /pdbtype:sept LINK32_OBJS= \ "$(INTDIR)\dnssec-dsfromkey.obj" \ "$(INTDIR)\dnssectool.obj" "..\..\..\Build\Debug\dnssec-dsfromkey.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) $(LINK32) @<< $(LINK32_FLAGS) $(LINK32_OBJS) << $(_VC_MANIFEST_EMBED_EXE) !ENDIF !IF "$(NO_EXTERNAL_DEPS)" != "1" !IF EXISTS("dsfromkey.dep") !INCLUDE "dsfromkey.dep" !ELSE !MESSAGE Warning: cannot find "dsfromkey.dep" !ENDIF !ENDIF !IF "$(CFG)" == "dsfromkey - @PLATFORM@ Release" || "$(CFG)" == "dsfromkey - @PLATFORM@ Debug" SOURCE="..\dnssec-dsfromkey.c" !IF "$(CFG)" == "dsfromkey - @PLATFORM@ Release" "$(INTDIR)\dnssec-dsfromkey.obj" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ELSEIF "$(CFG)" == "dsfromkey - @PLATFORM@ Debug" "$(INTDIR)\dnssec-dsfromkey.obj" "$(INTDIR)\dnssec-dsfromkey.sbr" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ENDIF SOURCE=..\dnssectool.c !IF "$(CFG)" == "dsfromkey - @PLATFORM@ Release" "$(INTDIR)\dnssectool.obj" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ELSEIF "$(CFG)" == "dsfromkey - @PLATFORM@ Debug" "$(INTDIR)\dnssectool.obj" "$(INTDIR)\dnssectool.sbr" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ENDIF !ENDIF #################################################### # Commands to generate initial empty manifest file and the RC file # that references it, and for generating the .res file: $(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc $(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest type <<$@ #include 1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest" << KEEP $(_VC_MANIFEST_BASENAME).auto.manifest : type <<$@ << KEEP bind9-9.11.3+dfsg/bin/dnssec/win32/dsfromkey.vcxproj.filters.in000066400000000000000000000014061325250447100242220ustar00rootroot00000000000000 {4FC737F1-C7A5-4376-A066-2A32D752A2FF} cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms Source Files bind9-9.11.3+dfsg/bin/dnssec/win32/dsfromkey.vcxproj.in000066400000000000000000000166441325250447100225650ustar00rootroot00000000000000 Debug @PLATFORM@ Release @PLATFORM@ {6E6297F4-69D7-4533-85E1-BD17C30017C8} Win32Proj dsfromkey Application true MultiByte Application false true MultiByte true ..\..\..\Build\$(Configuration)\ .\$(Configuration)\ dnssec-$(ProjectName) false ..\..\..\Build\$(Configuration)\ .\$(Configuration)\ dnssec-$(ProjectName) Level3 Disabled WIN32;@CRYPTO@_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true .\$(Configuration)\$(ProjectName).pch .\$(Configuration)\ .\$(Configuration)\ $(OutDir)$(TargetName).pdb true .\;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;%(AdditionalIncludeDirectories) CompileAsC Console true ..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt) $(Configuration);..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);%(AdditionalLibraryDirectories) dnssectool.lib;libisc.lib;libdns.lib;ws2_32.lib;%(AdditionalDependencies) @IF PYTHON cd ..\..\python copy /Y dnssec-checkds.py ..\..\Build\$(Configuration)\dnssec-checkds.py copy /Y dnssec-coverage.py ..\..\Build\$(Configuration)\dnssec-coverage.py copy /Y dnssec-keymgr.py ..\..\Build\$(Configuration)\dnssec-keymgr.py cd isc @PYTHON@ policy.py parse \dev\nul > nul set PYTHONPATH=. @PYTHON@ -m parsetab @END PYTHON Level3 MaxSpeed true @INTRINSIC@ WIN32;@CRYPTO@NDEBUG;_CONSOLE;%(PreprocessorDefinitions) OnlyExplicitInline false true .\$(Configuration)\$(ProjectName).pch .\$(Configuration)\ .\$(Configuration)\ $(OutDir)$(TargetName).pdb .\;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;%(AdditionalIncludeDirectories) CompileAsC Console false true true ..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt) Default $(Configuration);..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);%(AdditionalLibraryDirectories) dnssectool.lib;libisc.lib;libdns.lib;ws2_32.lib;%(AdditionalDependencies) @IF PYTHON cd ..\..\python copy /Y dnssec-checkds.py ..\..\Build\$(Configuration)\dnssec-checkds.py copy /Y dnssec-coverage.py ..\..\Build\$(Configuration)\dnssec-coverage.py copy /Y dnssec-keymgr.py ..\..\Build\$(Configuration)\dnssec-keymgr.py cd isc @PYTHON@ policy.py parse \dev\nul > nul set PYTHONPATH=. @PYTHON@ -m parsetab @END PYTHON bind9-9.11.3+dfsg/bin/dnssec/win32/dsfromkey.vcxproj.user000066400000000000000000000002171325250447100231220ustar00rootroot00000000000000 bind9-9.11.3+dfsg/bin/dnssec/win32/importkey.dsp.in000066400000000000000000000110141325250447100216620ustar00rootroot00000000000000# Microsoft Developer Studio Project File - Name="importkey" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "@PLATFORM@ (x86) Console Application" 0x0103 CFG=importkey - @PLATFORM@ Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "importkey.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "importkey.mak" CFG="importkey - @PLATFORM@ Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "importkey - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE "importkey - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "importkey - @PLATFORM@ Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 @COPTX@ @COPTI@ /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c # ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" @CRYPTO@ /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console @MACHINE@ # ADD LINK32 user32.lib advapi32.lib Release/dnssectool.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib ws2_32.lib /nologo /subsystem:console @MACHINE@ /out:"../../../Build/Release/dnssec-importkey.exe" !ELSEIF "$(CFG)" == "importkey - @PLATFORM@ Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /GZ /c # ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" @CRYPTO@ /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c # SUBTRACT CPP /X @COPTY@ # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug @MACHINE@ /pdbtype:sept # ADD LINK32 user32.lib advapi32.lib Debug/dnssectool.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib ws2_32.lib /nologo /subsystem:console /debug @MACHINE@ /out:"../../../Build/Debug/dnssec-importkey.exe" /pdbtype:sept !ENDIF # Begin Target # Name "importkey - @PLATFORM@ Release" # Name "importkey - @PLATFORM@ Debug" # Begin Group "Source Files" # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" # Begin Source File SOURCE="..\dnssec-importkey.c" # End Source File # End Group # Begin Group "Header Files" # PROP Default_Filter "h;hpp;hxx;hm;inl" # End Group # Begin Group "Resource Files" # PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" # End Group # End Target # End Project bind9-9.11.3+dfsg/bin/dnssec/win32/importkey.dsw000066400000000000000000000010371325250447100212700ustar00rootroot00000000000000Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "importkey"=".\importkey.dsp" - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### bind9-9.11.3+dfsg/bin/dnssec/win32/importkey.mak.in000066400000000000000000000206461325250447100216570ustar00rootroot00000000000000# Microsoft Developer Studio Generated NMAKE File, Based on importkey.dsp !IF "$(CFG)" == "" CFG=importkey - @PLATFORM@ Debug !MESSAGE No configuration specified. Defaulting to importkey - @PLATFORM@ Debug. !ENDIF !IF "$(CFG)" != "importkey - @PLATFORM@ Release" && "$(CFG)" != "importkey - @PLATFORM@ Debug" !MESSAGE Invalid configuration "$(CFG)" specified. !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "importkey.mak" CFG="importkey - @PLATFORM@ Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "importkey - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE "importkey - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE !ERROR An invalid configuration is specified. !ENDIF !IF "$(OS)" == "Windows_NT" NULL= !ELSE NULL=nul !ENDIF !IF "$(CFG)" == "importkey - @PLATFORM@ Release" _VC_MANIFEST_INC=0 _VC_MANIFEST_BASENAME=__VC80 !ELSE _VC_MANIFEST_INC=1 _VC_MANIFEST_BASENAME=__VC80.Debug !ENDIF #################################################### # Specifying name of temporary resource file used only in incremental builds: !if "$(_VC_MANIFEST_INC)" == "1" _VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res !else _VC_MANIFEST_AUTO_RES= !endif #################################################### # _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE: !if "$(_VC_MANIFEST_INC)" == "1" #MT_SPECIAL_RETURN=1090650113 #MT_SPECIAL_SWITCH=-notify_resource_update MT_SPECIAL_RETURN=0 MT_SPECIAL_SWITCH= _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \ if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \ rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \ link $** /out:$@ $(LFLAGS) !else _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1 !endif #################################################### # _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL: !if "$(_VC_MANIFEST_INC)" == "1" #MT_SPECIAL_RETURN=1090650113 #MT_SPECIAL_SWITCH=-notify_resource_update MT_SPECIAL_RETURN=0 MT_SPECIAL_SWITCH= _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \ if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \ rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \ link $** /out:$@ $(LFLAGS) !else _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2 !endif #################################################### # _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily: !if "$(_VC_MANIFEST_INC)" == "1" _VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \ $(_VC_MANIFEST_BASENAME).auto.rc \ $(_VC_MANIFEST_BASENAME).auto.manifest !else _VC_MANIFEST_CLEAN= !endif !IF "$(CFG)" == "importkey - @PLATFORM@ Release" OUTDIR=.\Release INTDIR=.\Release ALL : "..\..\..\Build\Release\dnssec-importkey.exe" CLEAN : -@erase "$(INTDIR)\dnssec-importkey.obj" -@erase "$(INTDIR)\dnssectool.obj" -@erase "$(INTDIR)\vc60.idb" -@erase "..\..\..\Build\Release\dnssec-importkey.exe" -@$(_VC_MANIFEST_CLEAN) "$(OUTDIR)" : if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" CPP=cl.exe CPP_PROJ=/nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" @CRYPTO@ /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\importkey.pch" @COPTY@ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c .c{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .c{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << RSC=rc.exe BSC32=bscmake.exe BSC32_FLAGS=/nologo /o"$(OUTDIR)\importkey.bsc" BSC32_SBRS= \ LINK32=link.exe LINK32_FLAGS=user32.lib advapi32.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib ws2_32.lib /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\dnssec-importkey.pdb" @MACHINE@ /out:"../../../Build/Release/dnssec-importkey.exe" LINK32_OBJS= \ "$(INTDIR)\dnssec-importkey.obj" \ "$(INTDIR)\dnssectool.obj" "..\..\..\Build\Release\dnssec-importkey.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) $(LINK32) @<< $(LINK32_FLAGS) $(LINK32_OBJS) << $(_VC_MANIFEST_EMBED_EXE) !ELSEIF "$(CFG)" == "importkey - @PLATFORM@ Debug" OUTDIR=.\Debug INTDIR=.\Debug # Begin Custom Macros OutDir=.\Debug # End Custom Macros ALL : "..\..\..\Build\Debug\dnssec-importkey.exe" "$(OUTDIR)\importkey.bsc" CLEAN : -@erase "$(INTDIR)\dnssec-importkey.obj" -@erase "$(INTDIR)\dnssec-importkey.sbr" -@erase "$(INTDIR)\dnssectool.obj" -@erase "$(INTDIR)\dnssectool.sbr" -@erase "$(INTDIR)\vc60.idb" -@erase "$(INTDIR)\vc60.pdb" -@erase "$(OUTDIR)\dnssec-importkey.pdb" -@erase "$(OUTDIR)\importkey.bsc" -@erase "..\..\..\Build\Debug\dnssec-importkey.exe" -@erase "..\..\..\Build\Debug\dnssec-importkey.ilk" -@$(_VC_MANIFEST_CLEAN) "$(OUTDIR)" : if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" CPP=cl.exe CPP_PROJ=/nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" @CRYPTO@ /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c .c{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .c{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << RSC=rc.exe BSC32=bscmake.exe BSC32_FLAGS=/nologo /o"$(OUTDIR)\importkey.bsc" BSC32_SBRS= \ "$(INTDIR)\dnssec-importkey.sbr" \ "$(INTDIR)\dnssectool.sbr" "$(OUTDIR)\importkey.bsc" : "$(OUTDIR)" $(BSC32_SBRS) $(BSC32) @<< $(BSC32_FLAGS) $(BSC32_SBRS) << LINK32=link.exe LINK32_FLAGS=user32.lib advapi32.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib ws2_32.lib /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\dnssec-importkey.pdb" /debug @MACHINE@ /out:"../../../Build/Debug/dnssec-importkey.exe" /pdbtype:sept LINK32_OBJS= \ "$(INTDIR)\dnssec-importkey.obj" \ "$(INTDIR)\dnssectool.obj" "..\..\..\Build\Debug\dnssec-importkey.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) $(LINK32) @<< $(LINK32_FLAGS) $(LINK32_OBJS) << $(_VC_MANIFEST_EMBED_EXE) !ENDIF !IF "$(NO_EXTERNAL_DEPS)" != "1" !IF EXISTS("importkey.dep") !INCLUDE "importkey.dep" !ELSE !MESSAGE Warning: cannot find "importkey.dep" !ENDIF !ENDIF !IF "$(CFG)" == "importkey - @PLATFORM@ Release" || "$(CFG)" == "importkey - @PLATFORM@ Debug" SOURCE="..\dnssec-importkey.c" !IF "$(CFG)" == "importkey - @PLATFORM@ Release" "$(INTDIR)\dnssec-importkey.obj" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ELSEIF "$(CFG)" == "importkey - @PLATFORM@ Debug" "$(INTDIR)\dnssec-importkey.obj" "$(INTDIR)\dnssec-importkey.sbr" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ENDIF SOURCE=..\dnssectool.c !IF "$(CFG)" == "importkey - @PLATFORM@ Release" "$(INTDIR)\dnssectool.obj" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ELSEIF "$(CFG)" == "importkey - @PLATFORM@ Debug" "$(INTDIR)\dnssectool.obj" "$(INTDIR)\dnssectool.sbr" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ENDIF !ENDIF #################################################### # Commands to generate initial empty manifest file and the RC file # that references it, and for generating the .res file: $(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc $(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest type <<$@ #include 1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest" << KEEP $(_VC_MANIFEST_BASENAME).auto.manifest : type <<$@ << KEEP bind9-9.11.3+dfsg/bin/dnssec/win32/importkey.vcxproj.filters.in000066400000000000000000000014101325250447100242350ustar00rootroot00000000000000 {4FC737F1-C7A5-4376-A066-2A32D752A2FF} cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms Source Files bind9-9.11.3+dfsg/bin/dnssec/win32/importkey.vcxproj.in000066400000000000000000000151221325250447100225730ustar00rootroot00000000000000 Debug @PLATFORM@ Release @PLATFORM@ {AB6690A0-055E-458f-BAC5-BF38BCC5834F} Win32Proj importkey Application true MultiByte Application false true MultiByte true ..\..\..\Build\$(Configuration)\ .\$(Configuration)\ dnssec-$(ProjectName) false ..\..\..\Build\$(Configuration)\ .\$(Configuration)\ dnssec-$(ProjectName) Level3 Disabled WIN32;@CRYPTO@_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true .\$(Configuration)\$(ProjectName).pch .\$(Configuration)\ .\$(Configuration)\ $(OutDir)$(TargetName).pdb true .\;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;%(AdditionalIncludeDirectories) CompileAsC Console true ..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt) $(Configuration);..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);%(AdditionalLibraryDirectories) dnssectool.lib;libisc.lib;libdns.lib;ws2_32.lib;%(AdditionalDependencies) Level3 MaxSpeed true @INTRINSIC@ WIN32;@CRYPTO@NDEBUG;_CONSOLE;%(PreprocessorDefinitions) OnlyExplicitInline false true .\$(Configuration)\$(ProjectName).pch .\$(Configuration)\ .\$(Configuration)\ $(OutDir)$(TargetName).pdb .\;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;%(AdditionalIncludeDirectories) CompileAsC Console false true true ..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt) Default $(Configuration);..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);%(AdditionalLibraryDirectories) dnssectool.lib;libisc.lib;libdns.lib;ws2_32.lib;%(AdditionalDependencies) bind9-9.11.3+dfsg/bin/dnssec/win32/importkey.vcxproj.user000066400000000000000000000002171325250447100231420ustar00rootroot00000000000000 bind9-9.11.3+dfsg/bin/dnssec/win32/keyfromlabel.dsp.in000066400000000000000000000110661325250447100223220ustar00rootroot00000000000000# Microsoft Developer Studio Project File - Name="keyfromlabel" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "@PLATFORM@ (x86) Console Application" 0x0103 CFG=keyfromlabel - @PLATFORM@ Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "keyfromlabel.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "keyfromlabel.mak" CFG="keyfromlabel - @PLATFORM@ Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "keyfromlabel - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE "keyfromlabel - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "keyfromlabel - @PLATFORM@ Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 @COPTX@ @COPTI@ /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c # ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" @CRYPTO@ /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console @MACHINE@ # ADD LINK32 user32.lib advapi32.lib Release/dnssectool.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib ws2_32.lib /nologo /subsystem:console @MACHINE@ /out:"../../../Build/Release/dnssec-keyfromlabel.exe" !ELSEIF "$(CFG)" == "keyfromlabel - @PLATFORM@ Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /GZ /c # ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" @CRYPTO@ /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c # SUBTRACT CPP /X @COPTY@ # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug @MACHINE@ /pdbtype:sept # ADD LINK32 user32.lib advapi32.lib Debug/dnssectool.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib ws2_32.lib /nologo /subsystem:console /debug @MACHINE@ /out:"../../../Build/Debug/dnssec-keyfromlabel.exe" /pdbtype:sept !ENDIF # Begin Target # Name "keyfromlabel - @PLATFORM@ Release" # Name "keyfromlabel - @PLATFORM@ Debug" # Begin Group "Source Files" # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" # Begin Source File SOURCE="..\dnssec-keyfromlabel.c" # End Source File # End Group # Begin Group "Header Files" # PROP Default_Filter "h;hpp;hxx;hm;inl" # End Group # Begin Group "Resource Files" # PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" # End Group # End Target # End Project bind9-9.11.3+dfsg/bin/dnssec/win32/keyfromlabel.dsw000066400000000000000000000010451325250447100217200ustar00rootroot00000000000000Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "keyfromlabel"=".\keyfromlabel.dsp" - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### bind9-9.11.3+dfsg/bin/dnssec/win32/keyfromlabel.mak.in000066400000000000000000000210711325250447100223010ustar00rootroot00000000000000# Microsoft Developer Studio Generated NMAKE File, Based on keyfromlabel.dsp !IF "$(CFG)" == "" CFG=keyfromlabel - @PLATFORM@ Debug !MESSAGE No configuration specified. Defaulting to keyfromlabel - @PLATFORM@ Debug. !ENDIF !IF "$(CFG)" != "keyfromlabel - @PLATFORM@ Release" && "$(CFG)" != "keyfromlabel - @PLATFORM@ Debug" !MESSAGE Invalid configuration "$(CFG)" specified. !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "keyfromlabel.mak" CFG="keyfromlabel - @PLATFORM@ Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "keyfromlabel - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE "keyfromlabel - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE !ERROR An invalid configuration is specified. !ENDIF !IF "$(OS)" == "Windows_NT" NULL= !ELSE NULL=nul !ENDIF !IF "$(CFG)" == "keyfromlabel - @PLATFORM@ Release" _VC_MANIFEST_INC=0 _VC_MANIFEST_BASENAME=__VC80 !ELSE _VC_MANIFEST_INC=1 _VC_MANIFEST_BASENAME=__VC80.Debug !ENDIF #################################################### # Specifying name of temporary resource file used only in incremental builds: !if "$(_VC_MANIFEST_INC)" == "1" _VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res !else _VC_MANIFEST_AUTO_RES= !endif #################################################### # _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE: !if "$(_VC_MANIFEST_INC)" == "1" #MT_SPECIAL_RETURN=1090650113 #MT_SPECIAL_SWITCH=-notify_resource_update MT_SPECIAL_RETURN=0 MT_SPECIAL_SWITCH= _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \ if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \ rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \ link $** /out:$@ $(LFLAGS) !else _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1 !endif #################################################### # _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL: !if "$(_VC_MANIFEST_INC)" == "1" #MT_SPECIAL_RETURN=1090650113 #MT_SPECIAL_SWITCH=-notify_resource_update MT_SPECIAL_RETURN=0 MT_SPECIAL_SWITCH= _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \ if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \ rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \ link $** /out:$@ $(LFLAGS) !else _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2 !endif #################################################### # _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily: !if "$(_VC_MANIFEST_INC)" == "1" _VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \ $(_VC_MANIFEST_BASENAME).auto.rc \ $(_VC_MANIFEST_BASENAME).auto.manifest !else _VC_MANIFEST_CLEAN= !endif !IF "$(CFG)" == "keyfromlabel - @PLATFORM@ Release" OUTDIR=.\Release INTDIR=.\Release ALL : "..\..\..\Build\Release\dnssec-keyfromlabel.exe" CLEAN : -@erase "$(INTDIR)\dnssec-keyfromlabel.obj" -@erase "$(INTDIR)\dnssectool.obj" -@erase "$(INTDIR)\vc60.idb" -@erase "..\..\..\Build\Release\dnssec-keyfromlabel.exe" -@$(_VC_MANIFEST_CLEAN) "$(OUTDIR)" : if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" CPP=cl.exe CPP_PROJ=/nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" @CRYPTO@ /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\keyfromlabel.pch" @COPTY@ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c .c{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .c{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << RSC=rc.exe BSC32=bscmake.exe BSC32_FLAGS=/nologo /o"$(OUTDIR)\keyfromlabel.bsc" BSC32_SBRS= \ LINK32=link.exe LINK32_FLAGS=user32.lib advapi32.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib ws2_32.lib /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\dnssec-keyfromlabel.pdb" @MACHINE@ /out:"../../../Build/Release/dnssec-keyfromlabel.exe" LINK32_OBJS= \ "$(INTDIR)\dnssec-keyfromlabel.obj" \ "$(INTDIR)\dnssectool.obj" "..\..\..\Build\Release\dnssec-keyfromlabel.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) $(LINK32) @<< $(LINK32_FLAGS) $(LINK32_OBJS) << $(_VC_MANIFEST_EMBED_EXE) !ELSEIF "$(CFG)" == "keyfromlabel - @PLATFORM@ Debug" OUTDIR=.\Debug INTDIR=.\Debug # Begin Custom Macros OutDir=.\Debug # End Custom Macros ALL : "..\..\..\Build\Debug\dnssec-keyfromlabel.exe" "$(OUTDIR)\keyfromlabel.bsc" CLEAN : -@erase "$(INTDIR)\dnssec-keyfromlabel.obj" -@erase "$(INTDIR)\dnssec-keyfromlabel.sbr" -@erase "$(INTDIR)\dnssectool.obj" -@erase "$(INTDIR)\dnssectool.sbr" -@erase "$(INTDIR)\vc60.idb" -@erase "$(INTDIR)\vc60.pdb" -@erase "$(OUTDIR)\dnssec-keyfromlabel.pdb" -@erase "$(OUTDIR)\keyfromlabel.bsc" -@erase "..\..\..\Build\Debug\dnssec-keyfromlabel.exe" -@erase "..\..\..\Build\Debug\dnssec-keyfromlabel.ilk" -@$(_VC_MANIFEST_CLEAN) "$(OUTDIR)" : if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" CPP=cl.exe CPP_PROJ=/nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" @CRYPTO@ /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c .c{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .c{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << RSC=rc.exe BSC32=bscmake.exe BSC32_FLAGS=/nologo /o"$(OUTDIR)\keyfromlabel.bsc" BSC32_SBRS= \ "$(INTDIR)\dnssec-keyfromlabel.sbr" \ "$(INTDIR)\dnssectool.sbr" "$(OUTDIR)\keyfromlabel.bsc" : "$(OUTDIR)" $(BSC32_SBRS) $(BSC32) @<< $(BSC32_FLAGS) $(BSC32_SBRS) << LINK32=link.exe LINK32_FLAGS=user32.lib advapi32.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib ws2_32.lib /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\dnssec-keyfromlabel.pdb" /debug @MACHINE@ /out:"../../../Build/Debug/dnssec-keyfromlabel.exe" /pdbtype:sept LINK32_OBJS= \ "$(INTDIR)\dnssec-keyfromlabel.obj" \ "$(INTDIR)\dnssectool.obj" "..\..\..\Build\Debug\dnssec-keyfromlabel.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) $(LINK32) @<< $(LINK32_FLAGS) $(LINK32_OBJS) << $(_VC_MANIFEST_EMBED_EXE) !ENDIF !IF "$(NO_EXTERNAL_DEPS)" != "1" !IF EXISTS("keyfromlabel.dep") !INCLUDE "keyfromlabel.dep" !ELSE !MESSAGE Warning: cannot find "keyfromlabel.dep" !ENDIF !ENDIF !IF "$(CFG)" == "keyfromlabel - @PLATFORM@ Release" || "$(CFG)" == "keyfromlabel - @PLATFORM@ Debug" SOURCE="..\dnssec-keyfromlabel.c" !IF "$(CFG)" == "keyfromlabel - @PLATFORM@ Release" "$(INTDIR)\dnssec-keyfromlabel.obj" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ELSEIF "$(CFG)" == "keyfromlabel - @PLATFORM@ Debug" "$(INTDIR)\dnssec-keyfromlabel.obj" "$(INTDIR)\dnssec-keyfromlabel.sbr" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ENDIF SOURCE=..\dnssectool.c !IF "$(CFG)" == "keyfromlabel - @PLATFORM@ Release" "$(INTDIR)\dnssectool.obj" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ELSEIF "$(CFG)" == "keyfromlabel - @PLATFORM@ Debug" "$(INTDIR)\dnssectool.obj" "$(INTDIR)\dnssectool.sbr" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ENDIF !ENDIF #################################################### # Commands to generate initial empty manifest file and the RC file # that references it, and for generating the .res file: $(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc $(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest type <<$@ #include 1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest" << KEEP $(_VC_MANIFEST_BASENAME).auto.manifest : type <<$@ << KEEP bind9-9.11.3+dfsg/bin/dnssec/win32/keyfromlabel.vcxproj.filters.in000066400000000000000000000014111325250447100246670ustar00rootroot00000000000000 {4FC737F1-C7A5-4376-A066-2A32D752A2FF} cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms Source Files bind9-9.11.3+dfsg/bin/dnssec/win32/keyfromlabel.vcxproj.in000066400000000000000000000151301325250447100232230ustar00rootroot00000000000000 Debug @PLATFORM@ Release @PLATFORM@ {17455DC6-5FBB-47C3-8F44-7DB574A188D3} Win32Proj keyfromlabel Application true MultiByte Application false true MultiByte true ..\..\..\Build\$(Configuration)\ .\$(Configuration)\ dnssec-$(ProjectName) false ..\..\..\Build\$(Configuration)\ .\$(Configuration)\ dnssec-$(ProjectName) Level3 Disabled WIN32;@CRYPTO@_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true .\$(Configuration)\$(ProjectName).pch .\$(Configuration)\ .\$(Configuration)\ $(OutDir)$(TargetName).pdb true .\;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;%(AdditionalIncludeDirectories) CompileAsC Console true ..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt) $(Configuration);..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);%(AdditionalLibraryDirectories) dnssectool.lib;libisc.lib;libdns.lib;ws2_32.lib;%(AdditionalDependencies) Level3 MaxSpeed true @INTRINSIC@ WIN32;@CRYPTO@NDEBUG;_CONSOLE;%(PreprocessorDefinitions) OnlyExplicitInline false true .\$(Configuration)\$(ProjectName).pch .\$(Configuration)\ .\$(Configuration)\ $(OutDir)$(TargetName).pdb .\;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;%(AdditionalIncludeDirectories) CompileAsC Console false true true ..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt) Default $(Configuration);..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);%(AdditionalLibraryDirectories) dnssectool.lib;libisc.lib;libdns.lib;ws2_32.lib;%(AdditionalDependencies) bind9-9.11.3+dfsg/bin/dnssec/win32/keyfromlabel.vcxproj.user000066400000000000000000000002171325250447100235730ustar00rootroot00000000000000 bind9-9.11.3+dfsg/bin/dnssec/win32/keygen.dsp.in000066400000000000000000000107421325250447100211300ustar00rootroot00000000000000# Microsoft Developer Studio Project File - Name="keygen" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "@PLATFORM@ (x86) Console Application" 0x0103 CFG=keygen - @PLATFORM@ Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "keygen.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "keygen.mak" CFG="keygen - @PLATFORM@ Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "keygen - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE "keygen - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "keygen - @PLATFORM@ Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 @COPTX@ @COPTI@ /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c # ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" @CRYPTO@ /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console @MACHINE@ # ADD LINK32 user32.lib advapi32.lib Release/dnssectool.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib ws2_32.lib /nologo /subsystem:console @MACHINE@ /out:"../../../Build/Release/dnssec-keygen.exe" !ELSEIF "$(CFG)" == "keygen - @PLATFORM@ Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /GZ /c # ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" @CRYPTO@ /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c # SUBTRACT CPP /X @COPTY@ # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug @MACHINE@ /pdbtype:sept # ADD LINK32 user32.lib advapi32.lib Debug/dnssectool.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib ws2_32.lib /nologo /subsystem:console /debug @MACHINE@ /out:"../../../Build/Debug/dnssec-keygen.exe" /pdbtype:sept !ENDIF # Begin Target # Name "keygen - @PLATFORM@ Release" # Name "keygen - @PLATFORM@ Debug" # Begin Group "Source Files" # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" # Begin Source File SOURCE="..\dnssec-keygen.c" # End Source File # End Group # Begin Group "Header Files" # PROP Default_Filter "h;hpp;hxx;hm;inl" # End Group # Begin Group "Resource Files" # PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" # End Group # End Target # End Project bind9-9.11.3+dfsg/bin/dnssec/win32/keygen.dsw000066400000000000000000000010311325250447100205210ustar00rootroot00000000000000Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "keygen"=".\keygen.dsp" - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### bind9-9.11.3+dfsg/bin/dnssec/win32/keygen.mak.in000066400000000000000000000204231325250447100211070ustar00rootroot00000000000000# Microsoft Developer Studio Generated NMAKE File, Based on keygen.dsp !IF "$(CFG)" == "" CFG=keygen - @PLATFORM@ Debug !MESSAGE No configuration specified. Defaulting to keygen - @PLATFORM@ Debug. !ENDIF !IF "$(CFG)" != "keygen - @PLATFORM@ Release" && "$(CFG)" != "keygen - @PLATFORM@ Debug" !MESSAGE Invalid configuration "$(CFG)" specified. !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "keygen.mak" CFG="keygen - @PLATFORM@ Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "keygen - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE "keygen - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE !ERROR An invalid configuration is specified. !ENDIF !IF "$(OS)" == "Windows_NT" NULL= !ELSE NULL=nul !ENDIF !IF "$(CFG)" == "keygen - @PLATFORM@ Release" _VC_MANIFEST_INC=0 _VC_MANIFEST_BASENAME=__VC80 !ELSE _VC_MANIFEST_INC=1 _VC_MANIFEST_BASENAME=__VC80.Debug !ENDIF #################################################### # Specifying name of temporary resource file used only in incremental builds: !if "$(_VC_MANIFEST_INC)" == "1" _VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res !else _VC_MANIFEST_AUTO_RES= !endif #################################################### # _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE: !if "$(_VC_MANIFEST_INC)" == "1" #MT_SPECIAL_RETURN=1090650113 #MT_SPECIAL_SWITCH=-notify_resource_update MT_SPECIAL_RETURN=0 MT_SPECIAL_SWITCH= _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \ if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \ rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \ link $** /out:$@ $(LFLAGS) !else _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1 !endif #################################################### # _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL: !if "$(_VC_MANIFEST_INC)" == "1" #MT_SPECIAL_RETURN=1090650113 #MT_SPECIAL_SWITCH=-notify_resource_update MT_SPECIAL_RETURN=0 MT_SPECIAL_SWITCH= _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \ if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \ rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \ link $** /out:$@ $(LFLAGS) !else _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2 !endif #################################################### # _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily: !if "$(_VC_MANIFEST_INC)" == "1" _VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \ $(_VC_MANIFEST_BASENAME).auto.rc \ $(_VC_MANIFEST_BASENAME).auto.manifest !else _VC_MANIFEST_CLEAN= !endif !IF "$(CFG)" == "keygen - @PLATFORM@ Release" OUTDIR=.\Release INTDIR=.\Release ALL : "..\..\..\Build\Release\dnssec-keygen.exe" CLEAN : -@erase "$(INTDIR)\dnssec-keygen.obj" -@erase "$(INTDIR)\dnssectool.obj" -@erase "$(INTDIR)\vc60.idb" -@erase "..\..\..\Build\Release\dnssec-keygen.exe" -@$(_VC_MANIFEST_CLEAN) "$(OUTDIR)" : if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" CPP=cl.exe CPP_PROJ=/nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" @CRYPTO@ /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\keygen.pch" @COPTY@ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c .c{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .c{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << RSC=rc.exe BSC32=bscmake.exe BSC32_FLAGS=/nologo /o"$(OUTDIR)\keygen.bsc" BSC32_SBRS= \ LINK32=link.exe LINK32_FLAGS=user32.lib advapi32.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib ws2_32.lib /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\dnssec-keygen.pdb" @MACHINE@ /out:"../../../Build/Release/dnssec-keygen.exe" LINK32_OBJS= \ "$(INTDIR)\dnssec-keygen.obj" \ "$(INTDIR)\dnssectool.obj" "..\..\..\Build\Release\dnssec-keygen.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) $(LINK32) @<< $(LINK32_FLAGS) $(LINK32_OBJS) << $(_VC_MANIFEST_EMBED_EXE) !ELSEIF "$(CFG)" == "keygen - @PLATFORM@ Debug" OUTDIR=.\Debug INTDIR=.\Debug # Begin Custom Macros OutDir=.\Debug # End Custom Macros ALL : "..\..\..\Build\Debug\dnssec-keygen.exe" "$(OUTDIR)\keygen.bsc" CLEAN : -@erase "$(INTDIR)\dnssec-keygen.obj" -@erase "$(INTDIR)\dnssec-keygen.sbr" -@erase "$(INTDIR)\dnssectool.obj" -@erase "$(INTDIR)\dnssectool.sbr" -@erase "$(INTDIR)\vc60.idb" -@erase "$(INTDIR)\vc60.pdb" -@erase "$(OUTDIR)\dnssec-keygen.pdb" -@erase "$(OUTDIR)\keygen.bsc" -@erase "..\..\..\Build\Debug\dnssec-keygen.exe" -@erase "..\..\..\Build\Debug\dnssec-keygen.ilk" -@$(_VC_MANIFEST_CLEAN) "$(OUTDIR)" : if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" CPP=cl.exe CPP_PROJ=/nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" @CRYPTO@ /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c .c{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .c{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << RSC=rc.exe BSC32=bscmake.exe BSC32_FLAGS=/nologo /o"$(OUTDIR)\keygen.bsc" BSC32_SBRS= \ "$(INTDIR)\dnssec-keygen.sbr" \ "$(INTDIR)\dnssectool.sbr" "$(OUTDIR)\keygen.bsc" : "$(OUTDIR)" $(BSC32_SBRS) $(BSC32) @<< $(BSC32_FLAGS) $(BSC32_SBRS) << LINK32=link.exe LINK32_FLAGS=user32.lib advapi32.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib ws2_32.lib /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\dnssec-keygen.pdb" /debug @MACHINE@ /out:"../../../Build/Debug/dnssec-keygen.exe" /pdbtype:sept LINK32_OBJS= \ "$(INTDIR)\dnssec-keygen.obj" \ "$(INTDIR)\dnssectool.obj" "..\..\..\Build\Debug\dnssec-keygen.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) $(LINK32) @<< $(LINK32_FLAGS) $(LINK32_OBJS) << $(_VC_MANIFEST_EMBED_EXE) !ENDIF !IF "$(NO_EXTERNAL_DEPS)" != "1" !IF EXISTS("keygen.dep") !INCLUDE "keygen.dep" !ELSE !MESSAGE Warning: cannot find "keygen.dep" !ENDIF !ENDIF !IF "$(CFG)" == "keygen - @PLATFORM@ Release" || "$(CFG)" == "keygen - @PLATFORM@ Debug" SOURCE="..\dnssec-keygen.c" !IF "$(CFG)" == "keygen - @PLATFORM@ Release" "$(INTDIR)\dnssec-keygen.obj" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ELSEIF "$(CFG)" == "keygen - @PLATFORM@ Debug" "$(INTDIR)\dnssec-keygen.obj" "$(INTDIR)\dnssec-keygen.sbr" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ENDIF SOURCE=..\dnssectool.c !IF "$(CFG)" == "keygen - @PLATFORM@ Release" "$(INTDIR)\dnssectool.obj" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ELSEIF "$(CFG)" == "keygen - @PLATFORM@ Debug" "$(INTDIR)\dnssectool.obj" "$(INTDIR)\dnssectool.sbr" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ENDIF !ENDIF #################################################### # Commands to generate initial empty manifest file and the RC file # that references it, and for generating the .res file: $(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc $(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest type <<$@ #include 1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest" << KEEP $(_VC_MANIFEST_BASENAME).auto.manifest : type <<$@ << KEEP bind9-9.11.3+dfsg/bin/dnssec/win32/keygen.vcxproj.filters.in000066400000000000000000000014031325250447100234760ustar00rootroot00000000000000 {4FC737F1-C7A5-4376-A066-2A32D752A2FF} cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms Source Files bind9-9.11.3+dfsg/bin/dnssec/win32/keygen.vcxproj.in000066400000000000000000000151141325250447100220330ustar00rootroot00000000000000 Debug @PLATFORM@ Release @PLATFORM@ {0BF11E21-168C-4CAA-B784-429D126BBAE5} Win32Proj keygen Application true MultiByte Application false true MultiByte true ..\..\..\Build\$(Configuration)\ .\$(Configuration)\ dnssec-$(ProjectName) false ..\..\..\Build\$(Configuration)\ .\$(Configuration)\ dnssec-$(ProjectName) Level3 Disabled WIN32;@CRYPTO@_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true .\$(Configuration)\$(ProjectName).pch .\$(Configuration)\ .\$(Configuration)\ $(OutDir)$(TargetName).pdb true .\;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;%(AdditionalIncludeDirectories) CompileAsC Console true ..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt) dnssectool.lib;libisc.lib;libdns.lib;ws2_32.lib;%(AdditionalDependencies) $(Configuration);..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);%(AdditionalLibraryDirectories) Level3 MaxSpeed true @INTRINSIC@ WIN32;@CRYPTO@NDEBUG;_CONSOLE;%(PreprocessorDefinitions) OnlyExplicitInline false true .\$(Configuration)\$(ProjectName).pch .\$(Configuration)\ .\$(Configuration)\ $(OutDir)$(TargetName).pdb .\;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;%(AdditionalIncludeDirectories) CompileAsC Console false true true ..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt) Default dnssectool.lib;libisc.lib;libdns.lib;ws2_32.lib;%(AdditionalDependencies) $(Configuration);..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);%(AdditionalLibraryDirectories) bind9-9.11.3+dfsg/bin/dnssec/win32/keygen.vcxproj.user000066400000000000000000000002171325250447100224010ustar00rootroot00000000000000 bind9-9.11.3+dfsg/bin/dnssec/win32/revoke.dsp.in000066400000000000000000000107421325250447100211410ustar00rootroot00000000000000# Microsoft Developer Studio Project File - Name="revoke" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "@PLATFORM@ (x86) Console Application" 0x0103 CFG=revoke - @PLATFORM@ Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "revoke.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "revoke.mak" CFG="revoke - @PLATFORM@ Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "revoke - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE "revoke - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "revoke - @PLATFORM@ Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 @COPTX@ @COPTI@ /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c # ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" @CRYPTO@ /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console @MACHINE@ # ADD LINK32 user32.lib advapi32.lib Release/dnssectool.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib ws2_32.lib /nologo /subsystem:console @MACHINE@ /out:"../../../Build/Release/dnssec-revoke.exe" !ELSEIF "$(CFG)" == "revoke - @PLATFORM@ Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /GZ /c # ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" @CRYPTO@ /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c # SUBTRACT CPP /X @COPTY@ # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug @MACHINE@ /pdbtype:sept # ADD LINK32 user32.lib advapi32.lib Debug/dnssectool.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib ws2_32.lib /nologo /subsystem:console /debug @MACHINE@ /out:"../../../Build/Debug/dnssec-revoke.exe" /pdbtype:sept !ENDIF # Begin Target # Name "revoke - @PLATFORM@ Release" # Name "revoke - @PLATFORM@ Debug" # Begin Group "Source Files" # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" # Begin Source File SOURCE="..\dnssec-revoke.c" # End Source File # End Group # Begin Group "Header Files" # PROP Default_Filter "h;hpp;hxx;hm;inl" # End Group # Begin Group "Resource Files" # PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" # End Group # End Target # End Project bind9-9.11.3+dfsg/bin/dnssec/win32/revoke.dsw000066400000000000000000000010311325250447100205320ustar00rootroot00000000000000Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "revoke"=".\revoke.dsp" - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### bind9-9.11.3+dfsg/bin/dnssec/win32/revoke.mak.in000066400000000000000000000204231325250447100211200ustar00rootroot00000000000000# Microsoft Developer Studio Generated NMAKE File, Based on revoke.dsp !IF "$(CFG)" == "" CFG=revoke - @PLATFORM@ Debug !MESSAGE No configuration specified. Defaulting to revoke - @PLATFORM@ Debug. !ENDIF !IF "$(CFG)" != "revoke - @PLATFORM@ Release" && "$(CFG)" != "revoke - @PLATFORM@ Debug" !MESSAGE Invalid configuration "$(CFG)" specified. !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "revoke.mak" CFG="revoke - @PLATFORM@ Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "revoke - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE "revoke - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE !ERROR An invalid configuration is specified. !ENDIF !IF "$(OS)" == "Windows_NT" NULL= !ELSE NULL=nul !ENDIF !IF "$(CFG)" == "revoke - @PLATFORM@ Release" _VC_MANIFEST_INC=0 _VC_MANIFEST_BASENAME=__VC80 !ELSE _VC_MANIFEST_INC=1 _VC_MANIFEST_BASENAME=__VC80.Debug !ENDIF #################################################### # Specifying name of temporary resource file used only in incremental builds: !if "$(_VC_MANIFEST_INC)" == "1" _VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res !else _VC_MANIFEST_AUTO_RES= !endif #################################################### # _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE: !if "$(_VC_MANIFEST_INC)" == "1" #MT_SPECIAL_RETURN=1090650113 #MT_SPECIAL_SWITCH=-notify_resource_update MT_SPECIAL_RETURN=0 MT_SPECIAL_SWITCH= _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \ if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \ rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \ link $** /out:$@ $(LFLAGS) !else _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1 !endif #################################################### # _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL: !if "$(_VC_MANIFEST_INC)" == "1" #MT_SPECIAL_RETURN=1090650113 #MT_SPECIAL_SWITCH=-notify_resource_update MT_SPECIAL_RETURN=0 MT_SPECIAL_SWITCH= _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \ if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \ rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \ link $** /out:$@ $(LFLAGS) !else _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2 !endif #################################################### # _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily: !if "$(_VC_MANIFEST_INC)" == "1" _VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \ $(_VC_MANIFEST_BASENAME).auto.rc \ $(_VC_MANIFEST_BASENAME).auto.manifest !else _VC_MANIFEST_CLEAN= !endif !IF "$(CFG)" == "revoke - @PLATFORM@ Release" OUTDIR=.\Release INTDIR=.\Release ALL : "..\..\..\Build\Release\dnssec-revoke.exe" CLEAN : -@erase "$(INTDIR)\dnssec-revoke.obj" -@erase "$(INTDIR)\dnssectool.obj" -@erase "$(INTDIR)\vc60.idb" -@erase "..\..\..\Build\Release\dnssec-revoke.exe" -@$(_VC_MANIFEST_CLEAN) "$(OUTDIR)" : if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" CPP=cl.exe CPP_PROJ=/nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" @CRYPTO@ /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\revoke.pch" @COPTY@ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c .c{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .c{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << RSC=rc.exe BSC32=bscmake.exe BSC32_FLAGS=/nologo /o"$(OUTDIR)\revoke.bsc" BSC32_SBRS= \ LINK32=link.exe LINK32_FLAGS=user32.lib advapi32.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib ws2_32.lib /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\dnssec-revoke.pdb" @MACHINE@ /out:"../../../Build/Release/dnssec-revoke.exe" LINK32_OBJS= \ "$(INTDIR)\dnssec-revoke.obj" \ "$(INTDIR)\dnssectool.obj" "..\..\..\Build\Release\dnssec-revoke.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) $(LINK32) @<< $(LINK32_FLAGS) $(LINK32_OBJS) << $(_VC_MANIFEST_EMBED_EXE) !ELSEIF "$(CFG)" == "revoke - @PLATFORM@ Debug" OUTDIR=.\Debug INTDIR=.\Debug # Begin Custom Macros OutDir=.\Debug # End Custom Macros ALL : "..\..\..\Build\Debug\dnssec-revoke.exe" "$(OUTDIR)\revoke.bsc" CLEAN : -@erase "$(INTDIR)\dnssec-revoke.obj" -@erase "$(INTDIR)\dnssec-revoke.sbr" -@erase "$(INTDIR)\dnssectool.obj" -@erase "$(INTDIR)\dnssectool.sbr" -@erase "$(INTDIR)\vc60.idb" -@erase "$(INTDIR)\vc60.pdb" -@erase "$(OUTDIR)\dnssec-revoke.pdb" -@erase "$(OUTDIR)\revoke.bsc" -@erase "..\..\..\Build\Debug\dnssec-revoke.exe" -@erase "..\..\..\Build\Debug\dnssec-revoke.ilk" -@$(_VC_MANIFEST_CLEAN) "$(OUTDIR)" : if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" CPP=cl.exe CPP_PROJ=/nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" @CRYPTO@ /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c .c{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .c{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << RSC=rc.exe BSC32=bscmake.exe BSC32_FLAGS=/nologo /o"$(OUTDIR)\revoke.bsc" BSC32_SBRS= \ "$(INTDIR)\dnssec-revoke.sbr" \ "$(INTDIR)\dnssectool.sbr" "$(OUTDIR)\revoke.bsc" : "$(OUTDIR)" $(BSC32_SBRS) $(BSC32) @<< $(BSC32_FLAGS) $(BSC32_SBRS) << LINK32=link.exe LINK32_FLAGS=user32.lib advapi32.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib ws2_32.lib /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\dnssec-revoke.pdb" /debug @MACHINE@ /out:"../../../Build/Debug/dnssec-revoke.exe" /pdbtype:sept LINK32_OBJS= \ "$(INTDIR)\dnssec-revoke.obj" \ "$(INTDIR)\dnssectool.obj" "..\..\..\Build\Debug\dnssec-revoke.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) $(LINK32) @<< $(LINK32_FLAGS) $(LINK32_OBJS) << $(_VC_MANIFEST_EMBED_EXE) !ENDIF !IF "$(NO_EXTERNAL_DEPS)" != "1" !IF EXISTS("revoke.dep") !INCLUDE "revoke.dep" !ELSE !MESSAGE Warning: cannot find "revoke.dep" !ENDIF !ENDIF !IF "$(CFG)" == "revoke - @PLATFORM@ Release" || "$(CFG)" == "revoke - @PLATFORM@ Debug" SOURCE="..\dnssec-revoke.c" !IF "$(CFG)" == "revoke - @PLATFORM@ Release" "$(INTDIR)\dnssec-revoke.obj" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ELSEIF "$(CFG)" == "revoke - @PLATFORM@ Debug" "$(INTDIR)\dnssec-revoke.obj" "$(INTDIR)\dnssec-revoke.sbr" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ENDIF SOURCE=..\dnssectool.c !IF "$(CFG)" == "revoke - @PLATFORM@ Release" "$(INTDIR)\dnssectool.obj" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ELSEIF "$(CFG)" == "revoke - @PLATFORM@ Debug" "$(INTDIR)\dnssectool.obj" "$(INTDIR)\dnssectool.sbr" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ENDIF !ENDIF #################################################### # Commands to generate initial empty manifest file and the RC file # that references it, and for generating the .res file: $(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc $(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest type <<$@ #include 1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest" << KEEP $(_VC_MANIFEST_BASENAME).auto.manifest : type <<$@ << KEEP bind9-9.11.3+dfsg/bin/dnssec/win32/revoke.vcxproj.filters.in000066400000000000000000000014031325250447100235070ustar00rootroot00000000000000 {4FC737F1-C7A5-4376-A066-2A32D752A2FF} cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms Source Files bind9-9.11.3+dfsg/bin/dnssec/win32/revoke.vcxproj.in000066400000000000000000000151141325250447100220440ustar00rootroot00000000000000 Debug @PLATFORM@ Release @PLATFORM@ {D171F185-D3C2-4463-9CF3-ED1D0B1D6832} Win32Proj revoke Application true MultiByte Application false true MultiByte true ..\..\..\Build\$(Configuration)\ .\$(Configuration)\ dnssec-$(ProjectName) false ..\..\..\Build\$(Configuration)\ .\$(Configuration)\ dnssec-$(ProjectName) Level3 Disabled WIN32;@CRYPTO@_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true .\$(Configuration)\$(ProjectName).pch .\$(Configuration)\ .\$(Configuration)\ $(OutDir)$(TargetName).pdb true .\;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;%(AdditionalIncludeDirectories) CompileAsC Console true ..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt) $(Configuration);..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);%(AdditionalLibraryDirectories) dnssectool.lib;libisc.lib;libdns.lib;ws2_32.lib;%(AdditionalDependencies) Level3 MaxSpeed true @INTRINSIC@ WIN32;@CRYPTO@NDEBUG;_CONSOLE;%(PreprocessorDefinitions) OnlyExplicitInline false true .\$(Configuration)\$(ProjectName).pch .\$(Configuration)\ .\$(Configuration)\ $(OutDir)$(TargetName).pdb .\;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;%(AdditionalIncludeDirectories) CompileAsC Console false true true ..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt) Default $(Configuration);..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);%(AdditionalLibraryDirectories) dnssectool.lib;libisc.lib;libdns.lib;ws2_32.lib;%(AdditionalDependencies) bind9-9.11.3+dfsg/bin/dnssec/win32/revoke.vcxproj.user000066400000000000000000000002171325250447100224120ustar00rootroot00000000000000 bind9-9.11.3+dfsg/bin/dnssec/win32/settime.dsp.in000066400000000000000000000107601325250447100213200ustar00rootroot00000000000000# Microsoft Developer Studio Project File - Name="settime" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "@PLATFORM@ (x86) Console Application" 0x0103 CFG=settime - @PLATFORM@ Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "settime.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "settime.mak" CFG="settime - @PLATFORM@ Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "settime - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE "settime - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "settime - @PLATFORM@ Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 @COPTX@ @COPTI@ /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c # ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" @CRYPTO@ /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console @MACHINE@ # ADD LINK32 user32.lib advapi32.lib Release/dnssectool.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib ws2_32.lib /nologo /subsystem:console @MACHINE@ /out:"../../../Build/Release/dnssec-settime.exe" !ELSEIF "$(CFG)" == "settime - @PLATFORM@ Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /GZ /c # ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" @CRYPTO@ /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c # SUBTRACT CPP /X @COPTY@ # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug @MACHINE@ /pdbtype:sept # ADD LINK32 user32.lib advapi32.lib Debug/dnssectool.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib ws2_32.lib /nologo /subsystem:console /debug @MACHINE@ /out:"../../../Build/Debug/dnssec-settime.exe" /pdbtype:sept !ENDIF # Begin Target # Name "settime - @PLATFORM@ Release" # Name "settime - @PLATFORM@ Debug" # Begin Group "Source Files" # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" # Begin Source File SOURCE="..\dnssec-settime.c" # End Source File # End Group # Begin Group "Header Files" # PROP Default_Filter "h;hpp;hxx;hm;inl" # End Group # Begin Group "Resource Files" # PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" # End Group # End Target # End Project bind9-9.11.3+dfsg/bin/dnssec/win32/settime.dsw000066400000000000000000000010331325250447100207130ustar00rootroot00000000000000Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "settime"=".\settime.dsp" - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### bind9-9.11.3+dfsg/bin/dnssec/win32/settime.mak.in000066400000000000000000000205041325250447100212770ustar00rootroot00000000000000# Microsoft Developer Studio Generated NMAKE File, Based on settime.dsp !IF "$(CFG)" == "" CFG=settime - @PLATFORM@ Debug !MESSAGE No configuration specified. Defaulting to settime - @PLATFORM@ Debug. !ENDIF !IF "$(CFG)" != "settime - @PLATFORM@ Release" && "$(CFG)" != "settime - @PLATFORM@ Debug" !MESSAGE Invalid configuration "$(CFG)" specified. !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "settime.mak" CFG="settime - @PLATFORM@ Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "settime - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE "settime - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE !ERROR An invalid configuration is specified. !ENDIF !IF "$(OS)" == "Windows_NT" NULL= !ELSE NULL=nul !ENDIF !IF "$(CFG)" == "settime - @PLATFORM@ Release" _VC_MANIFEST_INC=0 _VC_MANIFEST_BASENAME=__VC80 !ELSE _VC_MANIFEST_INC=1 _VC_MANIFEST_BASENAME=__VC80.Debug !ENDIF #################################################### # Specifying name of temporary resource file used only in incremental builds: !if "$(_VC_MANIFEST_INC)" == "1" _VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res !else _VC_MANIFEST_AUTO_RES= !endif #################################################### # _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE: !if "$(_VC_MANIFEST_INC)" == "1" #MT_SPECIAL_RETURN=1090650113 #MT_SPECIAL_SWITCH=-notify_resource_update MT_SPECIAL_RETURN=0 MT_SPECIAL_SWITCH= _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \ if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \ rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \ link $** /out:$@ $(LFLAGS) !else _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1 !endif #################################################### # _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL: !if "$(_VC_MANIFEST_INC)" == "1" #MT_SPECIAL_RETURN=1090650113 #MT_SPECIAL_SWITCH=-notify_resource_update MT_SPECIAL_RETURN=0 MT_SPECIAL_SWITCH= _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \ if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \ rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \ link $** /out:$@ $(LFLAGS) !else _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2 !endif #################################################### # _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily: !if "$(_VC_MANIFEST_INC)" == "1" _VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \ $(_VC_MANIFEST_BASENAME).auto.rc \ $(_VC_MANIFEST_BASENAME).auto.manifest !else _VC_MANIFEST_CLEAN= !endif !IF "$(CFG)" == "settime - @PLATFORM@ Release" OUTDIR=.\Release INTDIR=.\Release ALL : "..\..\..\Build\Release\dnssec-settime.exe" CLEAN : -@erase "$(INTDIR)\dnssec-settime.obj" -@erase "$(INTDIR)\dnssectool.obj" -@erase "$(INTDIR)\vc60.idb" -@erase "..\..\..\Build\Release\dnssec-settime.exe" -@$(_VC_MANIFEST_CLEAN) "$(OUTDIR)" : if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" CPP=cl.exe CPP_PROJ=/nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" @CRYPTO@ /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\settime.pch" @COPTY@ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c .c{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .c{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << RSC=rc.exe BSC32=bscmake.exe BSC32_FLAGS=/nologo /o"$(OUTDIR)\settime.bsc" BSC32_SBRS= \ LINK32=link.exe LINK32_FLAGS=user32.lib advapi32.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib ws2_32.lib /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\dnssec-settime.pdb" @MACHINE@ /out:"../../../Build/Release/dnssec-settime.exe" LINK32_OBJS= \ "$(INTDIR)\dnssec-settime.obj" \ "$(INTDIR)\dnssectool.obj" "..\..\..\Build\Release\dnssec-settime.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) $(LINK32) @<< $(LINK32_FLAGS) $(LINK32_OBJS) << $(_VC_MANIFEST_EMBED_EXE) !ELSEIF "$(CFG)" == "settime - @PLATFORM@ Debug" OUTDIR=.\Debug INTDIR=.\Debug # Begin Custom Macros OutDir=.\Debug # End Custom Macros ALL : "..\..\..\Build\Debug\dnssec-settime.exe" "$(OUTDIR)\settime.bsc" CLEAN : -@erase "$(INTDIR)\dnssec-settime.obj" -@erase "$(INTDIR)\dnssec-settime.sbr" -@erase "$(INTDIR)\dnssectool.obj" -@erase "$(INTDIR)\dnssectool.sbr" -@erase "$(INTDIR)\vc60.idb" -@erase "$(INTDIR)\vc60.pdb" -@erase "$(OUTDIR)\dnssec-settime.pdb" -@erase "$(OUTDIR)\settime.bsc" -@erase "..\..\..\Build\Debug\dnssec-settime.exe" -@erase "..\..\..\Build\Debug\dnssec-settime.ilk" -@$(_VC_MANIFEST_CLEAN) "$(OUTDIR)" : if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" CPP=cl.exe CPP_PROJ=/nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" @CRYPTO@ /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c .c{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .c{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << RSC=rc.exe BSC32=bscmake.exe BSC32_FLAGS=/nologo /o"$(OUTDIR)\settime.bsc" BSC32_SBRS= \ "$(INTDIR)\dnssec-settime.sbr" \ "$(INTDIR)\dnssectool.sbr" "$(OUTDIR)\settime.bsc" : "$(OUTDIR)" $(BSC32_SBRS) $(BSC32) @<< $(BSC32_FLAGS) $(BSC32_SBRS) << LINK32=link.exe LINK32_FLAGS=user32.lib advapi32.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib ws2_32.lib /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\dnssec-settime.pdb" /debug @MACHINE@ /out:"../../../Build/Debug/dnssec-settime.exe" /pdbtype:sept LINK32_OBJS= \ "$(INTDIR)\dnssec-settime.obj" \ "$(INTDIR)\dnssectool.obj" "..\..\..\Build\Debug\dnssec-settime.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) $(LINK32) @<< $(LINK32_FLAGS) $(LINK32_OBJS) << $(_VC_MANIFEST_EMBED_EXE) !ENDIF !IF "$(NO_EXTERNAL_DEPS)" != "1" !IF EXISTS("settime.dep") !INCLUDE "settime.dep" !ELSE !MESSAGE Warning: cannot find "settime.dep" !ENDIF !ENDIF !IF "$(CFG)" == "settime - @PLATFORM@ Release" || "$(CFG)" == "settime - @PLATFORM@ Debug" SOURCE="..\dnssec-settime.c" !IF "$(CFG)" == "settime - @PLATFORM@ Release" "$(INTDIR)\dnssec-settime.obj" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ELSEIF "$(CFG)" == "settime - @PLATFORM@ Debug" "$(INTDIR)\dnssec-settime.obj" "$(INTDIR)\dnssec-settime.sbr" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ENDIF SOURCE=..\dnssectool.c !IF "$(CFG)" == "settime - @PLATFORM@ Release" "$(INTDIR)\dnssectool.obj" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ELSEIF "$(CFG)" == "settime - @PLATFORM@ Debug" "$(INTDIR)\dnssectool.obj" "$(INTDIR)\dnssectool.sbr" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ENDIF !ENDIF #################################################### # Commands to generate initial empty manifest file and the RC file # that references it, and for generating the .res file: $(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc $(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest type <<$@ #include 1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest" << KEEP $(_VC_MANIFEST_BASENAME).auto.manifest : type <<$@ << KEEP bind9-9.11.3+dfsg/bin/dnssec/win32/settime.vcxproj.filters.in000066400000000000000000000014041325250447100236670ustar00rootroot00000000000000 {4FC737F1-C7A5-4376-A066-2A32D752A2FF} cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms Source Files bind9-9.11.3+dfsg/bin/dnssec/win32/settime.vcxproj.in000066400000000000000000000151161325250447100222250ustar00rootroot00000000000000 Debug @PLATFORM@ Release @PLATFORM@ {03FB7588-C5A7-4572-968F-14F1206BC69C} Win32Proj settime Application true MultiByte Application false true MultiByte true ..\..\..\Build\$(Configuration)\ .\$(Configuration)\ dnssec-$(ProjectName) false ..\..\..\Build\$(Configuration)\ .\$(Configuration)\ dnssec-$(ProjectName) Level3 Disabled WIN32;@CRYPTO@_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true .\$(Configuration)\$(ProjectName).pch .\$(Configuration)\ .\$(Configuration)\ $(OutDir)$(TargetName).pdb true .\;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;%(AdditionalIncludeDirectories) CompileAsC Console true ..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt) dnssectool.lib;libisc.lib;libdns.lib;ws2_32.lib;%(AdditionalDependencies) $(Configuration);..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);%(AdditionalLibraryDirectories) Level3 MaxSpeed true @INTRINSIC@ WIN32;@CRYPTO@NDEBUG;_CONSOLE;%(PreprocessorDefinitions) OnlyExplicitInline false true .\$(Configuration)\$(ProjectName).pch .\$(Configuration)\ .\$(Configuration)\ $(OutDir)$(TargetName).pdb .\;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;%(AdditionalIncludeDirectories) CompileAsC Console false true true ..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt) Default dnssectool.lib;libisc.lib;libdns.lib;ws2_32.lib;%(AdditionalDependencies) $(Configuration);..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);%(AdditionalLibraryDirectories) bind9-9.11.3+dfsg/bin/dnssec/win32/settime.vcxproj.user000066400000000000000000000002171325250447100225710ustar00rootroot00000000000000 bind9-9.11.3+dfsg/bin/dnssec/win32/signzone.dsp.in000066400000000000000000000107761325250447100215110ustar00rootroot00000000000000# Microsoft Developer Studio Project File - Name="signzone" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "@PLATFORM@ (x86) Console Application" 0x0103 CFG=signzone - @PLATFORM@ Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "signzone.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "signzone.mak" CFG="signzone - @PLATFORM@ Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "signzone - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE "signzone - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "signzone - @PLATFORM@ Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 @COPTX@ @COPTI@ /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c # ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" @CRYPTO@ /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console @MACHINE@ # ADD LINK32 user32.lib advapi32.lib Release/dnssectool.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib ws2_32.lib /nologo /subsystem:console @MACHINE@ /out:"../../../Build/Release/dnssec-signzone.exe" !ELSEIF "$(CFG)" == "signzone - @PLATFORM@ Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /GZ /c # ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" @CRYPTO@ /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c # SUBTRACT CPP /X @COPTY@ # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug @MACHINE@ /pdbtype:sept # ADD LINK32 user32.lib advapi32.lib Debug/dnssectool.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib ws2_32.lib /nologo /subsystem:console /debug @MACHINE@ /out:"../../../Build/Debug/dnssec-signzone.exe" /pdbtype:sept !ENDIF # Begin Target # Name "signzone - @PLATFORM@ Release" # Name "signzone - @PLATFORM@ Debug" # Begin Group "Source Files" # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" # Begin Source File SOURCE="..\dnssec-signzone.c" # End Source File # End Group # Begin Group "Header Files" # PROP Default_Filter "h;hpp;hxx;hm;inl" # End Group # Begin Group "Resource Files" # PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" # End Group # End Target # End Project bind9-9.11.3+dfsg/bin/dnssec/win32/signzone.dsw000066400000000000000000000010351325250447100210770ustar00rootroot00000000000000Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "signzone"=".\signzone.dsp" - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### bind9-9.11.3+dfsg/bin/dnssec/win32/signzone.mak.in000066400000000000000000000205651325250447100214700ustar00rootroot00000000000000# Microsoft Developer Studio Generated NMAKE File, Based on signzone.dsp !IF "$(CFG)" == "" CFG=signzone - @PLATFORM@ Debug !MESSAGE No configuration specified. Defaulting to signzone - @PLATFORM@ Debug. !ENDIF !IF "$(CFG)" != "signzone - @PLATFORM@ Release" && "$(CFG)" != "signzone - @PLATFORM@ Debug" !MESSAGE Invalid configuration "$(CFG)" specified. !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "signzone.mak" CFG="signzone - @PLATFORM@ Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "signzone - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE "signzone - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE !ERROR An invalid configuration is specified. !ENDIF !IF "$(OS)" == "Windows_NT" NULL= !ELSE NULL=nul !ENDIF !IF "$(CFG)" == "signzone - @PLATFORM@ Release" _VC_MANIFEST_INC=0 _VC_MANIFEST_BASENAME=__VC80 !ELSE _VC_MANIFEST_INC=1 _VC_MANIFEST_BASENAME=__VC80.Debug !ENDIF #################################################### # Specifying name of temporary resource file used only in incremental builds: !if "$(_VC_MANIFEST_INC)" == "1" _VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res !else _VC_MANIFEST_AUTO_RES= !endif #################################################### # _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE: !if "$(_VC_MANIFEST_INC)" == "1" #MT_SPECIAL_RETURN=1090650113 #MT_SPECIAL_SWITCH=-notify_resource_update MT_SPECIAL_RETURN=0 MT_SPECIAL_SWITCH= _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \ if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \ rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \ link $** /out:$@ $(LFLAGS) !else _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1 !endif #################################################### # _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL: !if "$(_VC_MANIFEST_INC)" == "1" #MT_SPECIAL_RETURN=1090650113 #MT_SPECIAL_SWITCH=-notify_resource_update MT_SPECIAL_RETURN=0 MT_SPECIAL_SWITCH= _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \ if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \ rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \ link $** /out:$@ $(LFLAGS) !else _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2 !endif #################################################### # _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily: !if "$(_VC_MANIFEST_INC)" == "1" _VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \ $(_VC_MANIFEST_BASENAME).auto.rc \ $(_VC_MANIFEST_BASENAME).auto.manifest !else _VC_MANIFEST_CLEAN= !endif !IF "$(CFG)" == "signzone - @PLATFORM@ Release" OUTDIR=.\Release INTDIR=.\Release ALL : "..\..\..\Build\Release\dnssec-signzone.exe" CLEAN : -@erase "$(INTDIR)\dnssec-signzone.obj" -@erase "$(INTDIR)\dnssectool.obj" -@erase "$(INTDIR)\vc60.idb" -@erase "..\..\..\Build\Release\dnssec-signzone.exe" -@$(_VC_MANIFEST_CLEAN) "$(OUTDIR)" : if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" CPP=cl.exe CPP_PROJ=/nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" @CRYPTO@ /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\signzone.pch" @COPTY@ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c .c{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .c{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << RSC=rc.exe BSC32=bscmake.exe BSC32_FLAGS=/nologo /o"$(OUTDIR)\signzone.bsc" BSC32_SBRS= \ LINK32=link.exe LINK32_FLAGS=user32.lib advapi32.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib ws2_32.lib /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\dnssec-signzone.pdb" @MACHINE@ /out:"../../../Build/Release/dnssec-signzone.exe" LINK32_OBJS= \ "$(INTDIR)\dnssec-signzone.obj" \ "$(INTDIR)\dnssectool.obj" "..\..\..\Build\Release\dnssec-signzone.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) $(LINK32) @<< $(LINK32_FLAGS) $(LINK32_OBJS) << $(_VC_MANIFEST_EMBED_EXE) !ELSEIF "$(CFG)" == "signzone - @PLATFORM@ Debug" OUTDIR=.\Debug INTDIR=.\Debug # Begin Custom Macros OutDir=.\Debug # End Custom Macros ALL : "..\..\..\Build\Debug\dnssec-signzone.exe" "$(OUTDIR)\signzone.bsc" CLEAN : -@erase "$(INTDIR)\dnssec-signzone.obj" -@erase "$(INTDIR)\dnssec-signzone.sbr" -@erase "$(INTDIR)\dnssectool.obj" -@erase "$(INTDIR)\dnssectool.sbr" -@erase "$(INTDIR)\vc60.idb" -@erase "$(INTDIR)\vc60.pdb" -@erase "$(OUTDIR)\dnssec-signzone.pdb" -@erase "$(OUTDIR)\signzone.bsc" -@erase "..\..\..\Build\Debug\dnssec-signzone.exe" -@erase "..\..\..\Build\Debug\dnssec-signzone.ilk" -@$(_VC_MANIFEST_CLEAN) "$(OUTDIR)" : if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" CPP=cl.exe CPP_PROJ=/nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" @CRYPTO@ /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c .c{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .c{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << RSC=rc.exe BSC32=bscmake.exe BSC32_FLAGS=/nologo /o"$(OUTDIR)\signzone.bsc" BSC32_SBRS= \ "$(INTDIR)\dnssec-signzone.sbr" \ "$(INTDIR)\dnssectool.sbr" "$(OUTDIR)\signzone.bsc" : "$(OUTDIR)" $(BSC32_SBRS) $(BSC32) @<< $(BSC32_FLAGS) $(BSC32_SBRS) << LINK32=link.exe LINK32_FLAGS=user32.lib advapi32.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib ws2_32.lib /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\dnssec-signzone.pdb" /debug @MACHINE@ /out:"../../../Build/Debug/dnssec-signzone.exe" /pdbtype:sept LINK32_OBJS= \ "$(INTDIR)\dnssec-signzone.obj" \ "$(INTDIR)\dnssectool.obj" "..\..\..\Build\Debug\dnssec-signzone.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) $(LINK32) @<< $(LINK32_FLAGS) $(LINK32_OBJS) << $(_VC_MANIFEST_EMBED_EXE) !ENDIF !IF "$(NO_EXTERNAL_DEPS)" != "1" !IF EXISTS("signzone.dep") !INCLUDE "signzone.dep" !ELSE !MESSAGE Warning: cannot find "signzone.dep" !ENDIF !ENDIF !IF "$(CFG)" == "signzone - @PLATFORM@ Release" || "$(CFG)" == "signzone - @PLATFORM@ Debug" SOURCE="..\dnssec-signzone.c" !IF "$(CFG)" == "signzone - @PLATFORM@ Release" "$(INTDIR)\dnssec-signzone.obj" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ELSEIF "$(CFG)" == "signzone - @PLATFORM@ Debug" "$(INTDIR)\dnssec-signzone.obj" "$(INTDIR)\dnssec-signzone.sbr" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ENDIF SOURCE=..\dnssectool.c !IF "$(CFG)" == "signzone - @PLATFORM@ Release" "$(INTDIR)\dnssectool.obj" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ELSEIF "$(CFG)" == "signzone - @PLATFORM@ Debug" "$(INTDIR)\dnssectool.obj" "$(INTDIR)\dnssectool.sbr" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ENDIF !ENDIF #################################################### # Commands to generate initial empty manifest file and the RC file # that references it, and for generating the .res file: $(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc $(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest type <<$@ #include 1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest" << KEEP $(_VC_MANIFEST_BASENAME).auto.manifest : type <<$@ << KEEP bind9-9.11.3+dfsg/bin/dnssec/win32/signzone.vcxproj.filters.in000066400000000000000000000014051325250447100240520ustar00rootroot00000000000000 {4FC737F1-C7A5-4376-A066-2A32D752A2FF} cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms Source Files bind9-9.11.3+dfsg/bin/dnssec/win32/signzone.vcxproj.in000066400000000000000000000151201325250447100224020ustar00rootroot00000000000000 Debug @PLATFORM@ Release @PLATFORM@ {205ED8A9-2E4C-41CC-9385-F3613402AA90} Win32Proj signzone Application true MultiByte Application false true MultiByte true ..\..\..\Build\$(Configuration)\ .\$(Configuration)\ dnssec-$(ProjectName) false ..\..\..\Build\$(Configuration)\ .\$(Configuration)\ dnssec-$(ProjectName) Level3 Disabled WIN32;@CRYPTO@_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true .\$(Configuration)\$(ProjectName).pch .\$(Configuration)\ .\$(Configuration)\ $(OutDir)$(TargetName).pdb true .\;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;%(AdditionalIncludeDirectories) CompileAsC Console true ..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt) $(Configuration);..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);%(AdditionalLibraryDirectories) dnssectool.lib;libisc.lib;libdns.lib;ws2_32.lib;%(AdditionalDependencies) Level3 MaxSpeed true @INTRINSIC@ WIN32;@CRYPTO@NDEBUG;_CONSOLE;%(PreprocessorDefinitions) OnlyExplicitInline false true .\$(Configuration)\$(ProjectName).pch .\$(Configuration)\ .\$(Configuration)\ $(OutDir)$(TargetName).pdb .\;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;%(AdditionalIncludeDirectories) CompileAsC Console false true true ..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt) Default $(Configuration);..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);%(AdditionalLibraryDirectories) dnssectool.lib;libisc.lib;libdns.lib;ws2_32.lib;%(AdditionalDependencies) bind9-9.11.3+dfsg/bin/dnssec/win32/signzone.vcxproj.user000066400000000000000000000002171325250447100227530ustar00rootroot00000000000000 bind9-9.11.3+dfsg/bin/dnssec/win32/verify.dsp.in000066400000000000000000000107421325250447100211520ustar00rootroot00000000000000# Microsoft Developer Studio Project File - Name="verify" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "@PLATFORM@ (x86) Console Application" 0x0103 CFG=verify - @PLATFORM@ Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "verify.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "verify.mak" CFG="verify - @PLATFORM@ Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "verify - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE "verify - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "verify - @PLATFORM@ Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 @COPTX@ @COPTI@ /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c # ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" @CRYPTO@ /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console @MACHINE@ # ADD LINK32 user32.lib advapi32.lib Release/dnssectool.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib ws2_32.lib /nologo /subsystem:console @MACHINE@ /out:"../../../Build/Release/dnssec-verify.exe" !ELSEIF "$(CFG)" == "verify - @PLATFORM@ Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /GZ /c # ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" @CRYPTO@ /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c # SUBTRACT CPP /X @COPTY@ # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug @MACHINE@ /pdbtype:sept # ADD LINK32 user32.lib advapi32.lib Debug/dnssectool.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib ws2_32.lib /nologo /subsystem:console /debug @MACHINE@ /out:"../../../Build/Debug/dnssec-verify.exe" /pdbtype:sept !ENDIF # Begin Target # Name "verify - @PLATFORM@ Release" # Name "verify - @PLATFORM@ Debug" # Begin Group "Source Files" # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" # Begin Source File SOURCE="..\dnssec-verify.c" # End Source File # End Group # Begin Group "Header Files" # PROP Default_Filter "h;hpp;hxx;hm;inl" # End Group # Begin Group "Resource Files" # PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" # End Group # End Target # End Project bind9-9.11.3+dfsg/bin/dnssec/win32/verify.dsw000066400000000000000000000010311325250447100205430ustar00rootroot00000000000000Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "verify"=".\verify.dsp" - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### bind9-9.11.3+dfsg/bin/dnssec/win32/verify.mak.in000066400000000000000000000204231325250447100211310ustar00rootroot00000000000000# Microsoft Developer Studio Generated NMAKE File, Based on verify.dsp !IF "$(CFG)" == "" CFG=verify - @PLATFORM@ Debug !MESSAGE No configuration specified. Defaulting to verify - @PLATFORM@ Debug. !ENDIF !IF "$(CFG)" != "verify - @PLATFORM@ Release" && "$(CFG)" != "verify - @PLATFORM@ Debug" !MESSAGE Invalid configuration "$(CFG)" specified. !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "verify.mak" CFG="verify - @PLATFORM@ Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "verify - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE "verify - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE !ERROR An invalid configuration is specified. !ENDIF !IF "$(OS)" == "Windows_NT" NULL= !ELSE NULL=nul !ENDIF !IF "$(CFG)" == "verify - @PLATFORM@ Release" _VC_MANIFEST_INC=0 _VC_MANIFEST_BASENAME=__VC80 !ELSE _VC_MANIFEST_INC=1 _VC_MANIFEST_BASENAME=__VC80.Debug !ENDIF #################################################### # Specifying name of temporary resource file used only in incremental builds: !if "$(_VC_MANIFEST_INC)" == "1" _VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res !else _VC_MANIFEST_AUTO_RES= !endif #################################################### # _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE: !if "$(_VC_MANIFEST_INC)" == "1" #MT_SPECIAL_RETURN=1090650113 #MT_SPECIAL_SWITCH=-notify_resource_update MT_SPECIAL_RETURN=0 MT_SPECIAL_SWITCH= _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \ if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \ rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \ link $** /out:$@ $(LFLAGS) !else _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1 !endif #################################################### # _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL: !if "$(_VC_MANIFEST_INC)" == "1" #MT_SPECIAL_RETURN=1090650113 #MT_SPECIAL_SWITCH=-notify_resource_update MT_SPECIAL_RETURN=0 MT_SPECIAL_SWITCH= _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \ if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \ rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \ link $** /out:$@ $(LFLAGS) !else _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2 !endif #################################################### # _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily: !if "$(_VC_MANIFEST_INC)" == "1" _VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \ $(_VC_MANIFEST_BASENAME).auto.rc \ $(_VC_MANIFEST_BASENAME).auto.manifest !else _VC_MANIFEST_CLEAN= !endif !IF "$(CFG)" == "verify - @PLATFORM@ Release" OUTDIR=.\Release INTDIR=.\Release ALL : "..\..\..\Build\Release\dnssec-verify.exe" CLEAN : -@erase "$(INTDIR)\dnssec-verify.obj" -@erase "$(INTDIR)\dnssectool.obj" -@erase "$(INTDIR)\vc60.idb" -@erase "..\..\..\Build\Release\dnssec-verify.exe" -@$(_VC_MANIFEST_CLEAN) "$(OUTDIR)" : if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" CPP=cl.exe CPP_PROJ=/nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" @CRYPTO@ /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\verify.pch" @COPTY@ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c .c{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .c{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << RSC=rc.exe BSC32=bscmake.exe BSC32_FLAGS=/nologo /o"$(OUTDIR)\verify.bsc" BSC32_SBRS= \ LINK32=link.exe LINK32_FLAGS=user32.lib advapi32.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib ws2_32.lib /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\dnssec-verify.pdb" @MACHINE@ /out:"../../../Build/Release/dnssec-verify.exe" LINK32_OBJS= \ "$(INTDIR)\dnssec-verify.obj" \ "$(INTDIR)\dnssectool.obj" "..\..\..\Build\Release\dnssec-verify.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) $(LINK32) @<< $(LINK32_FLAGS) $(LINK32_OBJS) << $(_VC_MANIFEST_EMBED_EXE) !ELSEIF "$(CFG)" == "verify - @PLATFORM@ Debug" OUTDIR=.\Debug INTDIR=.\Debug # Begin Custom Macros OutDir=.\Debug # End Custom Macros ALL : "..\..\..\Build\Debug\dnssec-verify.exe" "$(OUTDIR)\verify.bsc" CLEAN : -@erase "$(INTDIR)\dnssec-verify.obj" -@erase "$(INTDIR)\dnssec-verify.sbr" -@erase "$(INTDIR)\dnssectool.obj" -@erase "$(INTDIR)\dnssectool.sbr" -@erase "$(INTDIR)\vc60.idb" -@erase "$(INTDIR)\vc60.pdb" -@erase "$(OUTDIR)\dnssec-verify.pdb" -@erase "$(OUTDIR)\verify.bsc" -@erase "..\..\..\Build\Debug\dnssec-verify.exe" -@erase "..\..\..\Build\Debug\dnssec-verify.ilk" -@$(_VC_MANIFEST_CLEAN) "$(OUTDIR)" : if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" CPP=cl.exe CPP_PROJ=/nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" @CRYPTO@ /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c .c{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .c{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << RSC=rc.exe BSC32=bscmake.exe BSC32_FLAGS=/nologo /o"$(OUTDIR)\verify.bsc" BSC32_SBRS= \ "$(INTDIR)\dnssec-verify.sbr" \ "$(INTDIR)\dnssectool.sbr" "$(OUTDIR)\verify.bsc" : "$(OUTDIR)" $(BSC32_SBRS) $(BSC32) @<< $(BSC32_FLAGS) $(BSC32_SBRS) << LINK32=link.exe LINK32_FLAGS=user32.lib advapi32.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib ws2_32.lib /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\dnssec-verify.pdb" /debug @MACHINE@ /out:"../../../Build/Debug/dnssec-verify.exe" /pdbtype:sept LINK32_OBJS= \ "$(INTDIR)\dnssec-verify.obj" \ "$(INTDIR)\dnssectool.obj" "..\..\..\Build\Debug\dnssec-verify.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) $(LINK32) @<< $(LINK32_FLAGS) $(LINK32_OBJS) << $(_VC_MANIFEST_EMBED_EXE) !ENDIF !IF "$(NO_EXTERNAL_DEPS)" != "1" !IF EXISTS("verify.dep") !INCLUDE "verify.dep" !ELSE !MESSAGE Warning: cannot find "verify.dep" !ENDIF !ENDIF !IF "$(CFG)" == "verify - @PLATFORM@ Release" || "$(CFG)" == "verify - @PLATFORM@ Debug" SOURCE="..\dnssec-verify.c" !IF "$(CFG)" == "verify - @PLATFORM@ Release" "$(INTDIR)\dnssec-verify.obj" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ELSEIF "$(CFG)" == "verify - @PLATFORM@ Debug" "$(INTDIR)\dnssec-verify.obj" "$(INTDIR)\dnssec-verify.sbr" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ENDIF SOURCE=..\dnssectool.c !IF "$(CFG)" == "verify - @PLATFORM@ Release" "$(INTDIR)\dnssectool.obj" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ELSEIF "$(CFG)" == "verify - @PLATFORM@ Debug" "$(INTDIR)\dnssectool.obj" "$(INTDIR)\dnssectool.sbr" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ENDIF !ENDIF #################################################### # Commands to generate initial empty manifest file and the RC file # that references it, and for generating the .res file: $(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc $(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest type <<$@ #include 1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest" << KEEP $(_VC_MANIFEST_BASENAME).auto.manifest : type <<$@ << KEEP bind9-9.11.3+dfsg/bin/dnssec/win32/verify.vcxproj.filters.in000066400000000000000000000014031325250447100235200ustar00rootroot00000000000000 {4FC737F1-C7A5-4376-A066-2A32D752A2FF} cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms Source Files bind9-9.11.3+dfsg/bin/dnssec/win32/verify.vcxproj.in000066400000000000000000000151141325250447100220550ustar00rootroot00000000000000 Debug @PLATFORM@ Release @PLATFORM@ {FD653434-F1A8-44A9-85B2-A7468491DA6D} Win32Proj verify Application true MultiByte Application false true MultiByte true ..\..\..\Build\$(Configuration)\ .\$(Configuration)\ dnssec-$(ProjectName) false ..\..\..\Build\$(Configuration)\ .\$(Configuration)\ dnssec-$(ProjectName) Level3 Disabled WIN32;@CRYPTO@_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true .\$(Configuration)\$(ProjectName).pch .\$(Configuration)\ .\$(Configuration)\ $(OutDir)$(TargetName).pdb true .\;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;%(AdditionalIncludeDirectories) CompileAsC Console true ..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt) dnssectool.lib;libisc.lib;libdns.lib;ws2_32.lib;%(AdditionalDependencies) $(Configuration);..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);%(AdditionalLibraryDirectories) Level3 MaxSpeed true @INTRINSIC@ WIN32;@CRYPTO@NDEBUG;_CONSOLE;%(PreprocessorDefinitions) OnlyExplicitInline false true .\$(Configuration)\$(ProjectName).pch .\$(Configuration)\ .\$(Configuration)\ $(OutDir)$(TargetName).pdb .\;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;%(AdditionalIncludeDirectories) CompileAsC Console false true true ..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt) Default dnssectool.lib;libisc.lib;libdns.lib;ws2_32.lib;%(AdditionalDependencies) $(Configuration);..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);%(AdditionalLibraryDirectories) bind9-9.11.3+dfsg/bin/dnssec/win32/verify.vcxproj.user000066400000000000000000000002171325250447100224230ustar00rootroot00000000000000 bind9-9.11.3+dfsg/bin/named/000077500000000000000000000000001325250447100153705ustar00rootroot00000000000000bind9-9.11.3+dfsg/bin/named/Makefile.in000066400000000000000000000126641325250447100174460ustar00rootroot00000000000000# Copyright (C) 1998-2002, 2004-2017 Internet Systems Consortium, Inc. ("ISC") # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. srcdir = @srcdir@ VPATH = @srcdir@ top_srcdir = @top_srcdir@ # Attempt to disable parallel processing. .NOTPARALLEL: .NO_PARALLEL: VERSION=@BIND9_VERSION@ @BIND9_PRODUCT@ @BIND9_DESCRIPTION@ @BIND9_SRCID@ @BIND9_CONFIGARGS@ @BIND9_MAKE_INCLUDES@ # # Add database drivers here. # DBDRIVER_OBJS = DBDRIVER_SRCS = DBDRIVER_INCLUDES = DBDRIVER_LIBS = DLZ_DRIVER_DIR = ${top_srcdir}/contrib/dlz/drivers DLZDRIVER_OBJS = @DLZ_DRIVER_OBJS@ DLZDRIVER_SRCS = @DLZ_DRIVER_SRCS@ DLZDRIVER_INCLUDES = @DLZ_DRIVER_INCLUDES@ DLZDRIVER_LIBS = @DLZ_DRIVER_LIBS@ CINCLUDES = -I${srcdir}/include -I${srcdir}/unix/include -I. \ ${LWRES_INCLUDES} ${DNS_INCLUDES} ${BIND9_INCLUDES} \ ${ISCCFG_INCLUDES} ${ISCCC_INCLUDES} ${ISC_INCLUDES} \ ${DLZDRIVER_INCLUDES} ${DBDRIVER_INCLUDES} @DST_OPENSSL_INC@ CDEFINES = @CONTRIB_DLZ@ @USE_PKCS11@ @PKCS11_ENGINE@ @CRYPTO@ CWARNINGS = DNSLIBS = ../../lib/dns/libdns.@A@ @DNS_CRYPTO_LIBS@ ISCCFGLIBS = ../../lib/isccfg/libisccfg.@A@ ISCCCLIBS = ../../lib/isccc/libisccc.@A@ ISCLIBS = ../../lib/isc/libisc.@A@ ISCNOSYMLIBS = ../../lib/isc/libisc-nosymtbl.@A@ LWRESLIBS = ../../lib/lwres/liblwres.@A@ BIND9LIBS = ../../lib/bind9/libbind9.@A@ DNSDEPLIBS = ../../lib/dns/libdns.@A@ ISCCFGDEPLIBS = ../../lib/isccfg/libisccfg.@A@ ISCCCDEPLIBS = ../../lib/isccc/libisccc.@A@ ISCDEPLIBS = ../../lib/isc/libisc.@A@ LWRESDEPLIBS = ../../lib/lwres/liblwres.@A@ BIND9DEPLIBS = ../../lib/bind9/libbind9.@A@ DEPLIBS = ${LWRESDEPLIBS} ${DNSDEPLIBS} ${BIND9DEPLIBS} \ ${ISCCFGDEPLIBS} ${ISCCCDEPLIBS} ${ISCDEPLIBS} LIBS = ${LWRESLIBS} ${DNSLIBS} ${BIND9LIBS} \ ${ISCCFGLIBS} ${ISCCCLIBS} ${ISCLIBS} \ ${DLZDRIVER_LIBS} ${DBDRIVER_LIBS} @LIBS@ NOSYMLIBS = ${LWRESLIBS} ${DNSLIBS} ${BIND9LIBS} \ ${ISCCFGLIBS} ${ISCCCLIBS} ${ISCNOSYMLIBS} \ ${DLZDRIVER_LIBS} ${DBDRIVER_LIBS} @LIBS@ SUBDIRS = unix TARGETS = named@EXEEXT@ lwresd@EXEEXT@ GEOIPLINKOBJS = geoip.@O@ OBJS = builtin.@O@ client.@O@ config.@O@ control.@O@ \ controlconf.@O@ fuzz.@O@ @GEOIPLINKOBJS@ interfacemgr.@O@ \ listenlist.@O@ log.@O@ logconf.@O@ main.@O@ notify.@O@ \ query.@O@ server.@O@ sortlist.@O@ statschannel.@O@ \ tkeyconf.@O@ tsigconf.@O@ update.@O@ xfrout.@O@ \ zoneconf.@O@ \ lwaddr.@O@ lwresd.@O@ lwdclient.@O@ lwderror.@O@ lwdgabn.@O@ \ lwdgnba.@O@ lwdgrbn.@O@ lwdnoop.@O@ lwsearch.@O@ \ ${DLZDRIVER_OBJS} ${DBDRIVER_OBJS} UOBJS = unix/os.@O@ unix/dlz_dlopen_driver.@O@ SYMOBJS = symtbl.@O@ GEOIPLINKSRCS = geoip.c SRCS = builtin.c client.c config.c control.c \ controlconf.c fuzz.c @GEOIPLINKSRCS@ interfacemgr.c \ listenlist.c log.c logconf.c main.c notify.c \ query.c server.c sortlist.c statschannel.c \ tkeyconf.c tsigconf.c update.c xfrout.c \ zoneconf.c \ lwaddr.c lwresd.c lwdclient.c lwderror.c lwdgabn.c \ lwdgnba.c lwdgrbn.c lwdnoop.c lwsearch.c \ ${DLZDRIVER_SRCS} ${DBDRIVER_SRCS} MANPAGES = named.8 lwresd.8 named.conf.5 HTMLPAGES = named.html lwresd.html named.conf.html MANOBJS = ${MANPAGES} ${HTMLPAGES} @BIND9_MAKE_RULES@ main.@O@: main.c ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} \ -DVERSION=\"${VERSION}\" \ -DPRODUCT=\"${PRODUCT}\" \ -DDESCRIPTION=\"${DESCRIPTION}\" \ -DSRCID=\"${SRCID}\" \ -DCONFIGARGS="\"${CONFIGARGS}\"" \ -DBUILDER="\"make\"" \ -DNS_LOCALSTATEDIR=\"${localstatedir}\" \ -DNS_SYSCONFDIR=\"${sysconfdir}\" -c ${srcdir}/main.c config.@O@: config.c ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} \ -DVERSION=\"${VERSION}\" \ -DSRCID=\"${SRCID}\" \ -DDYNDB_LIBDIR=\"@libdir@/bind\" \ -DNS_LOCALSTATEDIR=\"${localstatedir}\" \ -DNS_SYSCONFDIR=\"${sysconfdir}\" \ -c ${srcdir}/config.c server.@O@: server.c ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} \ -DPRODUCT=\"${PRODUCT}\" \ -DVERSION=\"${VERSION}\" -c ${srcdir}/server.c named@EXEEXT@: ${OBJS} ${DEPLIBS} export MAKE_SYMTABLE="yes"; \ export BASEOBJS="${OBJS} ${UOBJS}"; \ ${FINALBUILDCMD} lwresd@EXEEXT@: named@EXEEXT@ rm -f lwresd@EXEEXT@ @LN@ named@EXEEXT@ lwresd@EXEEXT@ doc man:: ${MANOBJS} docclean manclean maintainer-clean:: rm -f ${MANOBJS} clean distclean maintainer-clean:: rm -f ${TARGETS} ${OBJS} maintainer-clean:: bind9.xsl.h: bind9.xsl ${srcdir}/convertxsl.pl ${PERL} ${srcdir}/convertxsl.pl < ${srcdir}/bind9.xsl > bind9.xsl.h depend: bind9.xsl.h statschannel.@O@: bind9.xsl.h installdirs: $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${sbindir} $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${mandir}/man5 $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${mandir}/man8 install:: named@EXEEXT@ lwresd@EXEEXT@ installdirs ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} named@EXEEXT@ ${DESTDIR}${sbindir} (cd ${DESTDIR}${sbindir}; rm -f lwresd@EXEEXT@; @LN@ named@EXEEXT@ lwresd@EXEEXT@) ${INSTALL_DATA} ${srcdir}/named.8 ${DESTDIR}${mandir}/man8 ${INSTALL_DATA} ${srcdir}/lwresd.8 ${DESTDIR}${mandir}/man8 ${INSTALL_DATA} ${srcdir}/named.conf.5 ${DESTDIR}${mandir}/man5 uninstall:: rm -f ${DESTDIR}${mandir}/man5/named.conf.5 rm -f ${DESTDIR}${mandir}/man8/lwresd.8 rm -f ${DESTDIR}${mandir}/man8/named.8 rm -f ${DESTDIR}${sbindir}/lwresd@EXEEXT@ ${LIBTOOL_MODE_UNINSTALL} rm -f ${DESTDIR}${sbindir}/named@EXEEXT@ @DLZ_DRIVER_RULES@ named-symtbl.@O@: named-symtbl.c ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} -c named-symtbl.c bind9-9.11.3+dfsg/bin/named/bind9.xsl000066400000000000000000001065461325250447100171410ustar00rootroot00000000000000 ISC BIND 9 Statistics

ISC Bind 9 Configuration and Statistics

Alternate statistics views: All, Status, Server, Zones, Network, Tasks, Memory and Traffic Size


Server Status

Boot time:
Last reconfigured:
Current time:
Server version:

Incoming Requests by DNS Opcode

[cannot display chart]
Total:

Incoming Queries by Query Type

[cannot display chart]
even odd
Total:

Outgoing Queries per view

View

[no data to display]
even odd

Server Statistics

[no data to display]
even odd

Zone Maintenance Statistics

[no data to display]
even odd

Resolver Statistics (Common)

even odd

Resolver Statistics for View

even odd

ADB Statistics for View

even odd

Cache Statistics for View

even odd

Cache DB RRsets for View

even odd

Traffic Size Statistics

UDP Requests Received

even odd

UDP Responses Sent

even odd

TCP Requests Received

even odd

TCP Responses Sent

even odd

Socket I/O Statistics

even odd

Received QTYPES per view/zone

View

Zone

[no data to display]
even odd

Response Codes per view/zone

View

Zone

[no data to display]
even odd

Network Status

even odd
ID Name Type References LocalAddress PeerAddress State

Task Manager Configuration

Thread-Model
Worker Threads
Default Quantum
Tasks Running
Tasks Ready

Tasks

even odd
ID Name References State Quantum Events

Memory Usage Summary

even odd

Memory Contexts

even odd
ID Name References TotalUse InUse MaxUse BlockSize Pools HiWater LoWater

bind9-9.11.3+dfsg/bin/named/bind9.xsl.h000066400000000000000000000754221325250447100173650ustar00rootroot00000000000000/* * Generated by convertxsl.pl 1.14 2008/07/17 23:43:26 jinmei Exp * From unknown */ static char xslmsg[] = "\n" "\n" "\n" "\n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " ISC BIND 9 Statistics\n" " \n" " \n" "
\n" "

ISC Bind 9 Configuration and Statistics

\n" "
\n" "

Alternate statistics views: All,\n" " Status,\n" " Server,\n" " Zones,\n" " Network,\n" " Tasks,\n" " Memory and\n" " Traffic Size

\n" "
\n" "

Server Status

\n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" "
Boot time:\n" " \n" "
Last reconfigured:\n" " \n" "
Current time:\n" " \n" "
Server version:\n" " \n" "
\n" "
\n" " \n" " \n" "

Incoming Requests by DNS Opcode

\n" " \n" "
\n" " [cannot display chart]\n" "
\n" "
\n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" "
\n" " \n" " \n" " \n" "
Total:\n" " \n" "
\n" "
\n" "
\n" " \n" " \n" " \n" "

Incoming Queries by Query Type

\n" "
\n" " [cannot display chart]\n" "
\n" "
\n" " \n" " \n" " \n" " \n" " \n" " even\n" " odd\n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" "
\n" " \n" " \n" " \n" "
Total:\n" " \n" "
\n" "
\n" "
\n" " \n" "

Outgoing Queries per view

\n" " \n" "

View

\n" " \n" " \n" " \n" " \n" " \n" " \n" "
[no data to display]
\n" "
\n" " \n" " \n" " \n" " \n" " \n" " even\n" " odd\n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" "
\n" " \n" " \n" " \n" "
\n" "
\n" "
\n" "
\n" " \n" "

Server Statistics

\n" " \n" " \n" " \n" "
[no data to display]
\n" "
\n" " \n" " \n" " \n" " \n" " \n" " even\n" " odd\n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" "
\n" " \n" " \n" " \n" "
\n" "
\n" "
\n" " \n" " \n" "

Zone Maintenance Statistics

\n" " \n" " \n" "
[no data to display]
\n" "
\n" " \n" " \n" " \n" " \n" " \n" " even\n" " odd\n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" "
\n" " \n" " \n" " \n" "
\n" "
\n" " \n" "

Resolver Statistics (Common)

\n" " \n" " \n" " \n" " \n" " \n" " even\n" " odd\n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" "
\n" " \n" " \n" " \n" "
\n" "
\n" " \n" " \n" "

Resolver Statistics for View

\n" " \n" " \n" " \n" " \n" " \n" " even\n" " odd\n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" "
\n" " \n" " \n" " \n" "
\n" "
\n" "
\n" " \n" " \n" "

ADB Statistics for View

\n" " \n" " \n" " \n" " \n" " \n" " even\n" " odd\n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" "
\n" " \n" " \n" " \n" "
\n" "
\n" "
\n" " \n" " \n" "

Cache Statistics for View

\n" " \n" " \n" " \n" " \n" " \n" " even\n" " odd\n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" "
\n" " \n" " \n" " \n" "
\n" "
\n" "
\n" " \n" " \n" "

Cache DB RRsets for View

\n" " \n" " \n" " \n" " \n" " even\n" " odd\n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" "
\n" " \n" " \n" " \n" "
\n" "
\n" "
\n" "
\n" " \n" "

Traffic Size Statistics

\n" "
\n" " \n" "

UDP Requests Received

\n" " \n" " \n" " \n" " \n" " even\n" " odd\n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" "
\n" " \n" " \n" " \n" "
\n" "
\n" "
\n" " \n" "

UDP Responses Sent

\n" " \n" " \n" " \n" " \n" " even\n" " odd\n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" "
\n" " \n" " \n" " \n" "
\n" "
\n" "
\n" " \n" "

TCP Requests Received

\n" " \n" " \n" " \n" " \n" " even\n" " odd\n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" "
\n" " \n" " \n" " \n" "
\n" "
\n" "
\n" " \n" "

TCP Responses Sent

\n" " \n" " \n" " \n" " \n" " even\n" " odd\n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" "
\n" " \n" " \n" " \n" "
\n" "
\n" "
\n" " \n" "

Socket I/O Statistics

\n" " \n" " \n" " \n" " \n" " even\n" " odd\n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" "
\n" " \n" " \n" " \n" "
\n" "
\n" "
\n" " \n" "

Received QTYPES per view/zone

\n" " \n" "

View

\n" " \n" " \n" " \n" " \n" " \n" "

Zone

\n" " \n" " \n" " \n" " \n" " \n" " \n" "
[no data to display]
\n" "
\n" " \n" " \n" " \n" " \n" " \n" " even\n" " odd\n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" "
\n" " \n" " \n" " \n" "
\n" "
\n" "
\n" "
\n" "
\n" " \n" "

Response Codes per view/zone

\n" " \n" "

View

\n" " \n" " \n" " \n" " \n" " \n" "

Zone

\n" " \n" " \n" " \n" " \n" " \n" " \n" "
[no data to display]
\n" "
\n" " \n" " \n" " \n" " \n" " \n" " even\n" " odd\n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" "
\n" " \n" " \n" " \n" "
\n" "
\n" "
\n" "
\n" "
\n" " \n" "

Network Status

\n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " even\n" " odd\n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" "
IDNameTypeReferencesLocalAddressPeerAddressState
\n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" "
\n" "
\n" "
\n" " \n" "

Task Manager Configuration

\n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" "
Thread-Model\n" " \n" "
Worker Threads\n" " \n" "
Default Quantum\n" " \n" "
Tasks Running\n" " \n" "
Tasks Ready\n" " \n" "
\n" "
\n" "
\n" " \n" "

Tasks

\n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " even\n" " odd\n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" "
IDNameReferencesStateQuantumEvents
\n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" "
\n" "
\n" "
\n" " \n" "

Memory Usage Summary

\n" " \n" " \n" " \n" " \n" " even\n" " odd\n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" "
\n" " \n" " \n" " \n" "
\n" "
\n" "
\n" " \n" "

Memory Contexts

\n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " even\n" " odd\n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" "
IDNameReferencesTotalUseInUseMaxUseBlockSizePoolsHiWaterLoWater
\n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" "
\n" "
\n" "
\n" "

Internet Systems Consortium Inc.
http://www.isc.org

\n" " \n" " \n" "
\n" "
\n"; bind9-9.11.3+dfsg/bin/named/builtin.c000066400000000000000000000353111325250447100172050ustar00rootroot00000000000000/* * Copyright (C) 2001-2005, 2007, 2009-2016 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* $Id: builtin.c,v 1.26 2012/01/21 19:44:18 each Exp $ */ /*! \file * \brief * The built-in "version", "hostname", "id", "authors" and "empty" databases. */ #include #include #include #include #include #include #include #include #include #include #include #include #include typedef struct builtin builtin_t; static isc_result_t do_version_lookup(dns_sdblookup_t *lookup); static isc_result_t do_hostname_lookup(dns_sdblookup_t *lookup); static isc_result_t do_authors_lookup(dns_sdblookup_t *lookup); static isc_result_t do_id_lookup(dns_sdblookup_t *lookup); static isc_result_t do_empty_lookup(dns_sdblookup_t *lookup); static isc_result_t do_dns64_lookup(dns_sdblookup_t *lookup); /* * We can't use function pointers as the db_data directly * because ANSI C does not guarantee that function pointers * can safely be cast to void pointers and back. */ struct builtin { isc_result_t (*do_lookup)(dns_sdblookup_t *lookup); char *server; char *contact; }; static builtin_t version_builtin = { do_version_lookup, NULL, NULL }; static builtin_t hostname_builtin = { do_hostname_lookup, NULL, NULL }; static builtin_t authors_builtin = { do_authors_lookup, NULL, NULL }; static builtin_t id_builtin = { do_id_lookup, NULL, NULL }; static builtin_t empty_builtin = { do_empty_lookup, NULL, NULL }; static builtin_t dns64_builtin = { do_dns64_lookup, NULL, NULL }; static dns_sdbimplementation_t *builtin_impl; static dns_sdbimplementation_t *dns64_impl; /* * Pre computed HEX * 16 or 1 table. */ static const unsigned char hex16[256] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*00*/ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*10*/ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*20*/ 0, 16, 32, 48, 64, 80, 96,112,128,144, 1, 1, 1, 1, 1, 1, /*30*/ 1,160,176,192,208,224,240, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*40*/ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*50*/ 1,160,176,192,208,224,240, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*60*/ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*70*/ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*80*/ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*90*/ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*A0*/ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*B0*/ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*C0*/ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*D0*/ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*E0*/ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 /*F0*/ }; const unsigned char decimal[] = "0123456789"; static size_t dns64_rdata(unsigned char *v, size_t start, unsigned char *rdata) { size_t i, j = 0; for (i = 0; i < 4U; i++) { unsigned char c = v[start++]; if (start == 7U) start++; if (c > 99) { rdata[j++] = 3; rdata[j++] = decimal[c/100]; c = c % 100; rdata[j++] = decimal[c/10]; c = c % 10; rdata[j++] = decimal[c]; } else if (c > 9) { rdata[j++] = 2; rdata[j++] = decimal[c/10]; c = c % 10; rdata[j++] = decimal[c]; } else { rdata[j++] = 1; rdata[j++] = decimal[c]; } } memmove(&rdata[j], "\07in-addr\04arpa", 14); return (j + 14); } static isc_result_t dns64_cname(const dns_name_t *zone, const dns_name_t *name, dns_sdblookup_t *lookup) { size_t zlen, nlen, j, len; unsigned char v[16], n; unsigned int i; unsigned char rdata[sizeof("123.123.123.123.in-addr.arpa.")]; unsigned char *ndata; /* * The combined length of the zone and name is 74. * * The minimum zone length is 10 ((3)ip6(4)arpa(0)). * * The length of name should always be even as we are expecting * a series of nibbles. */ zlen = zone->length; nlen = name->length; if ((zlen + nlen) > 74U || zlen < 10U || (nlen % 2) != 0U) return (ISC_R_NOTFOUND); /* * We assume the zone name is well formed. */ /* * XXXMPA We could check the dns64 suffix here if we need to. */ /* * Check that name is a series of nibbles. * Compute the byte values that correspond to the nibbles as we go. * * Shift the final result 4 bits, by setting 'i' to 1, if we if we * have a odd number of nibbles so that "must be zero" tests below * are byte aligned and we correctly return ISC_R_NOTFOUND or * ISC_R_SUCCESS. We will not generate a CNAME in this case. */ ndata = name->ndata; i = (nlen % 4) == 2U ? 1 : 0; j = nlen; memset(v, 0, sizeof(v)); while (j != 0U) { INSIST((i/2) < sizeof(v)); if (ndata[0] != 1) return (ISC_R_NOTFOUND); n = hex16[ndata[1]&0xff]; if (n == 1) return (ISC_R_NOTFOUND); v[i/2] = n | (v[i/2]>>4); j -= 2; ndata += 2; i++; } /* * If we get here then we know name only consisted of nibbles. * Now we need to determine if the name exists or not and whether * it corresponds to a empty node in the zone or there should be * a CNAME. */ #define ZLEN(x) (10 + (x)/2) switch (zlen) { case ZLEN(32): /* prefix len 32 */ /* * The nibbles that map to this byte must be zero for 'name' * to exist in the zone. */ if (nlen > 16U && v[(nlen-1)/4 - 4] != 0) return (ISC_R_NOTFOUND); /* * If the total length is not 74 then this is a empty node * so return success. */ if (nlen + zlen != 74U) return (ISC_R_SUCCESS); len = dns64_rdata(v, 8, rdata); break; case ZLEN(40): /* prefix len 40 */ /* * The nibbles that map to this byte must be zero for 'name' * to exist in the zone. */ if (nlen > 12U && v[(nlen-1)/4 - 3] != 0) return (ISC_R_NOTFOUND); /* * If the total length is not 74 then this is a empty node * so return success. */ if (nlen + zlen != 74U) return (ISC_R_SUCCESS); len = dns64_rdata(v, 6, rdata); break; case ZLEN(48): /* prefix len 48 */ /* * The nibbles that map to this byte must be zero for 'name' * to exist in the zone. */ if (nlen > 8U && v[(nlen-1)/4 - 2] != 0) return (ISC_R_NOTFOUND); /* * If the total length is not 74 then this is a empty node * so return success. */ if (nlen + zlen != 74U) return (ISC_R_SUCCESS); len = dns64_rdata(v, 5, rdata); break; case ZLEN(56): /* prefix len 56 */ /* * The nibbles that map to this byte must be zero for 'name' * to exist in the zone. */ if (nlen > 4U && v[(nlen-1)/4 - 1] != 0) return (ISC_R_NOTFOUND); /* * If the total length is not 74 then this is a empty node * so return success. */ if (nlen + zlen != 74U) return (ISC_R_SUCCESS); len = dns64_rdata(v, 4, rdata); break; case ZLEN(64): /* prefix len 64 */ /* * The nibbles that map to this byte must be zero for 'name' * to exist in the zone. */ if (v[(nlen-1)/4] != 0) return (ISC_R_NOTFOUND); /* * If the total length is not 74 then this is a empty node * so return success. */ if (nlen + zlen != 74U) return (ISC_R_SUCCESS); len = dns64_rdata(v, 3, rdata); break; case ZLEN(96): /* prefix len 96 */ /* * If the total length is not 74 then this is a empty node * so return success. */ if (nlen + zlen != 74U) return (ISC_R_SUCCESS); len = dns64_rdata(v, 0, rdata); break; default: /* * This should never be reached unless someone adds a * zone declaration with this internal type to named.conf. */ return (ISC_R_NOTFOUND); } return (dns_sdb_putrdata(lookup, dns_rdatatype_cname, 600, rdata, (unsigned int)len)); } static isc_result_t builtin_lookup(const char *zone, const char *name, void *dbdata, dns_sdblookup_t *lookup, dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo) { builtin_t *b = (builtin_t *) dbdata; UNUSED(zone); UNUSED(methods); UNUSED(clientinfo); if (strcmp(name, "@") == 0) return (b->do_lookup(lookup)); else return (ISC_R_NOTFOUND); } static isc_result_t dns64_lookup(const dns_name_t *zone, const dns_name_t *name, void *dbdata, dns_sdblookup_t *lookup, dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo) { builtin_t *b = (builtin_t *) dbdata; UNUSED(methods); UNUSED(clientinfo); if (name->labels == 0 && name->length == 0) return (b->do_lookup(lookup)); else return (dns64_cname(zone, name, lookup)); } static isc_result_t put_txt(dns_sdblookup_t *lookup, const char *text) { unsigned char buf[256]; unsigned int len = strlen(text); if (len > 255) len = 255; /* Silently truncate */ buf[0] = len; memmove(&buf[1], text, len); return (dns_sdb_putrdata(lookup, dns_rdatatype_txt, 0, buf, len + 1)); } static isc_result_t do_version_lookup(dns_sdblookup_t *lookup) { if (ns_g_server->version_set) { if (ns_g_server->version == NULL) return (ISC_R_SUCCESS); else return (put_txt(lookup, ns_g_server->version)); } else { return (put_txt(lookup, ns_g_version)); } } static isc_result_t do_hostname_lookup(dns_sdblookup_t *lookup) { if (ns_g_server->hostname_set) { if (ns_g_server->hostname == NULL) return (ISC_R_SUCCESS); else return (put_txt(lookup, ns_g_server->hostname)); } else { char buf[256]; isc_result_t result = ns_os_gethostname(buf, sizeof(buf)); if (result != ISC_R_SUCCESS) return (result); return (put_txt(lookup, buf)); } } static isc_result_t do_authors_lookup(dns_sdblookup_t *lookup) { isc_result_t result; const char **p; static const char *authors[] = { "Mark Andrews", "Curtis Blackburn", "James Brister", "Ben Cottrell", "John H. DuBois III", "Francis Dupont", "Michael Graff", "Andreas Gustafsson", "Bob Halley", "Evan Hunt", "JINMEI Tatuya", "Witold Krecicki", "David Lawrence", "Scott Mann", "Danny Mayer", "Damien Neil", "Matt Nelson", "Jeremy C. Reed", "Michael Sawyer", "Brian Wellington", NULL }; /* * If a version string is specified, disable the authors.bind zone. */ if (ns_g_server->version_set) return (ISC_R_SUCCESS); for (p = authors; *p != NULL; p++) { result = put_txt(lookup, *p); if (result != ISC_R_SUCCESS) return (result); } return (ISC_R_SUCCESS); } static isc_result_t do_id_lookup(dns_sdblookup_t *lookup) { if (ns_g_server->server_usehostname) { char buf[256]; isc_result_t result = ns_os_gethostname(buf, sizeof(buf)); if (result != ISC_R_SUCCESS) return (result); return (put_txt(lookup, buf)); } if (ns_g_server->server_id == NULL) return (ISC_R_SUCCESS); else return (put_txt(lookup, ns_g_server->server_id)); } static isc_result_t do_dns64_lookup(dns_sdblookup_t *lookup) { UNUSED(lookup); return (ISC_R_SUCCESS); } static isc_result_t do_empty_lookup(dns_sdblookup_t *lookup) { UNUSED(lookup); return (ISC_R_SUCCESS); } static isc_result_t builtin_authority(const char *zone, void *dbdata, dns_sdblookup_t *lookup) { isc_result_t result; const char *contact = "hostmaster"; const char *server = "@"; builtin_t *b = (builtin_t *) dbdata; UNUSED(zone); UNUSED(dbdata); if (b == &empty_builtin) { server = "."; contact = "."; } else { if (b->server != NULL) server = b->server; if (b->contact != NULL) contact = b->contact; } result = dns_sdb_putsoa(lookup, server, contact, 0); if (result != ISC_R_SUCCESS) return (ISC_R_FAILURE); result = dns_sdb_putrr(lookup, "ns", 0, server); if (result != ISC_R_SUCCESS) return (ISC_R_FAILURE); return (ISC_R_SUCCESS); } static isc_result_t builtin_create(const char *zone, int argc, char **argv, void *driverdata, void **dbdata) { REQUIRE(argc >= 1); UNUSED(zone); UNUSED(driverdata); if (strcmp(argv[0], "empty") == 0 || strcmp(argv[0], "dns64") == 0) { if (argc != 3) return (DNS_R_SYNTAX); } else if (argc != 1) return (DNS_R_SYNTAX); if (strcmp(argv[0], "version") == 0) *dbdata = &version_builtin; else if (strcmp(argv[0], "hostname") == 0) *dbdata = &hostname_builtin; else if (strcmp(argv[0], "authors") == 0) *dbdata = &authors_builtin; else if (strcmp(argv[0], "id") == 0) *dbdata = &id_builtin; else if (strcmp(argv[0], "empty") == 0 || strcmp(argv[0], "dns64") == 0) { builtin_t *empty; char *server; char *contact; /* * We don't want built-in zones to fail. Fallback to * the static configuration if memory allocation fails. */ empty = isc_mem_get(ns_g_mctx, sizeof(*empty)); server = isc_mem_strdup(ns_g_mctx, argv[1]); contact = isc_mem_strdup(ns_g_mctx, argv[2]); if (empty == NULL || server == NULL || contact == NULL) { if (strcmp(argv[0], "empty") == 0) *dbdata = &empty_builtin; else *dbdata = &dns64_builtin; if (server != NULL) isc_mem_free(ns_g_mctx, server); if (contact != NULL) isc_mem_free(ns_g_mctx, contact); if (empty != NULL) isc_mem_put(ns_g_mctx, empty, sizeof (*empty)); } else { if (strcmp(argv[0], "empty") == 0) memmove(empty, &empty_builtin, sizeof (empty_builtin)); else memmove(empty, &dns64_builtin, sizeof (empty_builtin)); empty->server = server; empty->contact = contact; *dbdata = empty; } } else return (ISC_R_NOTIMPLEMENTED); return (ISC_R_SUCCESS); } static void builtin_destroy(const char *zone, void *driverdata, void **dbdata) { builtin_t *b = (builtin_t *) *dbdata; UNUSED(zone); UNUSED(driverdata); /* * Don't free the static versions. */ if (*dbdata == &version_builtin || *dbdata == &hostname_builtin || *dbdata == &authors_builtin || *dbdata == &id_builtin || *dbdata == &empty_builtin || *dbdata == &dns64_builtin) return; isc_mem_free(ns_g_mctx, b->server); isc_mem_free(ns_g_mctx, b->contact); isc_mem_put(ns_g_mctx, b, sizeof (*b)); } static dns_sdbmethods_t builtin_methods = { builtin_lookup, builtin_authority, NULL, /* allnodes */ builtin_create, builtin_destroy, NULL }; static dns_sdbmethods_t dns64_methods = { NULL, builtin_authority, NULL, /* allnodes */ builtin_create, builtin_destroy, dns64_lookup, }; isc_result_t ns_builtin_init(void) { RUNTIME_CHECK(dns_sdb_register("_builtin", &builtin_methods, NULL, DNS_SDBFLAG_RELATIVEOWNER | DNS_SDBFLAG_RELATIVERDATA, ns_g_mctx, &builtin_impl) == ISC_R_SUCCESS); RUNTIME_CHECK(dns_sdb_register("_dns64", &dns64_methods, NULL, DNS_SDBFLAG_RELATIVEOWNER | DNS_SDBFLAG_RELATIVERDATA | DNS_SDBFLAG_DNS64, ns_g_mctx, &dns64_impl) == ISC_R_SUCCESS); return (ISC_R_SUCCESS); } void ns_builtin_deinit(void) { dns_sdb_unregister(&builtin_impl); dns_sdb_unregister(&dns64_impl); } bind9-9.11.3+dfsg/bin/named/client.c000066400000000000000000003171551325250447100170260ustar00rootroot00000000000000/* * Copyright (C) 1999-2018 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /*** *** Client ***/ /*! \file * Client Routines * * Important note! * * All client state changes, other than that from idle to listening, occur * as a result of events. This guarantees serialization and avoids the * need for locking. * * If a routine is ever created that allows someone other than the client's * task to change the client, then the client will have to be locked. */ #define NS_CLIENT_TRACE #ifdef NS_CLIENT_TRACE #define CTRACE(m) ns_client_log(client, \ NS_LOGCATEGORY_CLIENT, \ NS_LOGMODULE_CLIENT, \ ISC_LOG_DEBUG(3), \ "%s", (m)) #define MTRACE(m) isc_log_write(ns_g_lctx, \ NS_LOGCATEGORY_GENERAL, \ NS_LOGMODULE_CLIENT, \ ISC_LOG_DEBUG(3), \ "clientmgr @%p: %s", manager, (m)) #else #define CTRACE(m) ((void)(m)) #define MTRACE(m) ((void)(m)) #endif #define TCP_CLIENT(c) (((c)->attributes & NS_CLIENTATTR_TCP) != 0) #define TCP_BUFFER_SIZE (65535 + 2) #define SEND_BUFFER_SIZE 4096 #define RECV_BUFFER_SIZE 4096 #ifdef ISC_PLATFORM_USETHREADS #define NMCTXS 100 /*%< * Number of 'mctx pools' for clients. (Should this be configurable?) * When enabling threads, we use a pool of memory contexts shared by * client objects, since concurrent access to a shared context would cause * heavy contentions. The above constant is expected to be enough for * completely avoiding contentions among threads for an authoritative-only * server. */ #else #define NMCTXS 0 /*%< * If named with built without thread, simply share manager's context. Using * a separate context in this case would simply waste memory. */ #endif #define COOKIE_SIZE 24U /* 8 + 4 + 4 + 8 */ #define ECS_SIZE 20U /* 2 + 1 + 1 + [0..16] */ #define WANTNSID(x) (((x)->attributes & NS_CLIENTATTR_WANTNSID) != 0) #define WANTEXPIRE(x) (((x)->attributes & NS_CLIENTATTR_WANTEXPIRE) != 0) /*% nameserver client manager structure */ struct ns_clientmgr { /* Unlocked. */ unsigned int magic; /* The queue object has its own locks */ client_queue_t inactive; /*%< To be recycled */ isc_mem_t * mctx; isc_taskmgr_t * taskmgr; isc_timermgr_t * timermgr; /* Lock covers manager state. */ isc_mutex_t lock; isc_boolean_t exiting; /* Lock covers the clients list */ isc_mutex_t listlock; client_list_t clients; /*%< All active clients */ /* Lock covers the recursing list */ isc_mutex_t reclock; client_list_t recursing; /*%< Recursing clients */ #if NMCTXS > 0 /*%< mctx pool for clients. */ unsigned int nextmctx; isc_mem_t * mctxpool[NMCTXS]; #endif }; #define MANAGER_MAGIC ISC_MAGIC('N', 'S', 'C', 'm') #define VALID_MANAGER(m) ISC_MAGIC_VALID(m, MANAGER_MAGIC) /*! * Client object states. Ordering is significant: higher-numbered * states are generally "more active", meaning that the client can * have more dynamically allocated data, outstanding events, etc. * In the list below, any such properties listed for state N * also apply to any state > N. * * To force the client into a less active state, set client->newstate * to that state and call exit_check(). This will cause any * activities defined for higher-numbered states to be aborted. */ #define NS_CLIENTSTATE_FREED 0 /*%< * The client object no longer exists. */ #define NS_CLIENTSTATE_INACTIVE 1 /*%< * The client object exists and has a task and timer. * Its "query" struct and sendbuf are initialized. * It is on the client manager's list of inactive clients. * It has a message and OPT, both in the reset state. */ #define NS_CLIENTSTATE_READY 2 /*%< * The client object is either a TCP or a UDP one, and * it is associated with a network interface. It is on the * client manager's list of active clients. * * If it is a TCP client object, it has a TCP listener socket * and an outstanding TCP listen request. * * If it is a UDP client object, it has a UDP listener socket * and an outstanding UDP receive request. */ #define NS_CLIENTSTATE_READING 3 /*%< * The client object is a TCP client object that has received * a connection. It has a tcpsocket, tcpmsg, TCP quota, and an * outstanding TCP read request. This state is not used for * UDP client objects. */ #define NS_CLIENTSTATE_WORKING 4 /*%< * The client object has received a request and is working * on it. It has a view, and it may have any of a non-reset OPT, * recursion quota, and an outstanding write request. */ #define NS_CLIENTSTATE_RECURSING 5 /*%< * The client object is recursing. It will be on the 'recursing' * list. */ #define NS_CLIENTSTATE_MAX 9 /*%< * Sentinel value used to indicate "no state". When client->newstate * has this value, we are not attempting to exit the current state. * Must be greater than any valid state. */ /* * Enable ns_client_dropport() by default. */ #ifndef NS_CLIENT_DROPPORT #define NS_CLIENT_DROPPORT 1 #endif unsigned int ns_client_requests; static void client_read(ns_client_t *client); static void client_accept(ns_client_t *client); static void client_udprecv(ns_client_t *client); static void clientmgr_destroy(ns_clientmgr_t *manager); static isc_boolean_t exit_check(ns_client_t *client); static void ns_client_endrequest(ns_client_t *client); static void client_start(isc_task_t *task, isc_event_t *event); static void client_request(isc_task_t *task, isc_event_t *event); static void ns_client_dumpmessage(ns_client_t *client, const char *reason); static isc_result_t get_client(ns_clientmgr_t *manager, ns_interface_t *ifp, dns_dispatch_t *disp, isc_boolean_t tcp); static isc_result_t get_worker(ns_clientmgr_t *manager, ns_interface_t *ifp, isc_socket_t *sock); static inline isc_boolean_t allowed(isc_netaddr_t *addr, dns_name_t *signer, isc_netaddr_t *ecs_addr, isc_uint8_t ecs_addrlen, isc_uint8_t *ecs_scope, dns_acl_t *acl); static void compute_cookie(ns_client_t *client, isc_uint32_t when, isc_uint32_t nonce, isc_buffer_t *buf); void ns_client_recursing(ns_client_t *client) { REQUIRE(NS_CLIENT_VALID(client)); REQUIRE(client->state == NS_CLIENTSTATE_WORKING); LOCK(&client->manager->reclock); client->newstate = client->state = NS_CLIENTSTATE_RECURSING; ISC_LIST_APPEND(client->manager->recursing, client, rlink); UNLOCK(&client->manager->reclock); } void ns_client_killoldestquery(ns_client_t *client) { ns_client_t *oldest; REQUIRE(NS_CLIENT_VALID(client)); LOCK(&client->manager->reclock); oldest = ISC_LIST_HEAD(client->manager->recursing); if (oldest != NULL) { ISC_LIST_UNLINK(client->manager->recursing, oldest, rlink); UNLOCK(&client->manager->reclock); ns_query_cancel(oldest); } else UNLOCK(&client->manager->reclock); } void ns_client_settimeout(ns_client_t *client, unsigned int seconds) { isc_result_t result; isc_interval_t interval; isc_interval_set(&interval, seconds, 0); result = isc_timer_reset(client->timer, isc_timertype_once, NULL, &interval, ISC_FALSE); client->timerset = ISC_TRUE; if (result != ISC_R_SUCCESS) { ns_client_log(client, NS_LOGCATEGORY_CLIENT, NS_LOGMODULE_CLIENT, ISC_LOG_ERROR, "setting timeout: %s", isc_result_totext(result)); /* Continue anyway. */ } } /*% * Check for a deactivation or shutdown request and take appropriate * action. Returns ISC_TRUE if either is in progress; in this case * the caller must no longer use the client object as it may have been * freed. */ static isc_boolean_t exit_check(ns_client_t *client) { isc_boolean_t destroy_manager = ISC_FALSE; ns_clientmgr_t *manager = NULL; REQUIRE(NS_CLIENT_VALID(client)); manager = client->manager; if (client->state <= client->newstate) return (ISC_FALSE); /* Business as usual. */ INSIST(client->newstate < NS_CLIENTSTATE_RECURSING); /* * We need to detach from the view early when shutting down * the server to break the following vicious circle: * * - The resolver will not shut down until the view refcount is zero * - The view refcount does not go to zero until all clients detach * - The client does not detach from the view until references is zero * - references does not go to zero until the resolver has shut down * * Keep the view attached until any outstanding updates complete. */ if (client->nupdates == 0 && client->newstate == NS_CLIENTSTATE_FREED && client->view != NULL) dns_view_detach(&client->view); if (client->state == NS_CLIENTSTATE_WORKING || client->state == NS_CLIENTSTATE_RECURSING) { INSIST(client->newstate <= NS_CLIENTSTATE_READING); /* * Let the update processing complete. */ if (client->nupdates > 0) return (ISC_TRUE); /* * We are trying to abort request processing. */ if (client->nsends > 0) { isc_socket_t *sock; if (TCP_CLIENT(client)) sock = client->tcpsocket; else sock = client->udpsocket; isc_socket_cancel(sock, client->task, ISC_SOCKCANCEL_SEND); } if (! (client->nsends == 0 && client->nrecvs == 0 && client->references == 0)) { /* * Still waiting for I/O cancel completion. * or lingering references. */ return (ISC_TRUE); } /* * I/O cancel is complete. Burn down all state * related to the current request. Ensure that * the client is no longer on the recursing list. * * We need to check whether the client is still linked, * because it may already have been removed from the * recursing list by ns_client_killoldestquery() */ if (client->state == NS_CLIENTSTATE_RECURSING) { LOCK(&manager->reclock); if (ISC_LINK_LINKED(client, rlink)) ISC_LIST_UNLINK(manager->recursing, client, rlink); UNLOCK(&manager->reclock); } ns_client_endrequest(client); client->state = NS_CLIENTSTATE_READING; INSIST(client->recursionquota == NULL); if (NS_CLIENTSTATE_READING == client->newstate) { if (!client->pipelined) { client_read(client); client->newstate = NS_CLIENTSTATE_MAX; return (ISC_TRUE); /* We're done. */ } else if (client->mortal) { client->newstate = NS_CLIENTSTATE_INACTIVE; } else return (ISC_FALSE); } } if (client->state == NS_CLIENTSTATE_READING) { /* * We are trying to abort the current TCP connection, * if any. */ INSIST(client->recursionquota == NULL); INSIST(client->newstate <= NS_CLIENTSTATE_READY); if (client->nreads > 0) dns_tcpmsg_cancelread(&client->tcpmsg); if (client->nreads != 0) { /* Still waiting for read cancel completion. */ return (ISC_TRUE); } if (client->tcpmsg_valid) { dns_tcpmsg_invalidate(&client->tcpmsg); client->tcpmsg_valid = ISC_FALSE; } if (client->tcpsocket != NULL) { CTRACE("closetcp"); isc_socket_detach(&client->tcpsocket); } if (client->tcpquota != NULL) isc_quota_detach(&client->tcpquota); if (client->timerset) { (void)isc_timer_reset(client->timer, isc_timertype_inactive, NULL, NULL, ISC_TRUE); client->timerset = ISC_FALSE; } client->pipelined = ISC_FALSE; client->peeraddr_valid = ISC_FALSE; client->state = NS_CLIENTSTATE_READY; INSIST(client->recursionquota == NULL); /* * Now the client is ready to accept a new TCP connection * or UDP request, but we may have enough clients doing * that already. Check whether this client needs to remain * active and force it to go inactive if not. * * UDP clients go inactive at this point, but TCP clients * may remain active if we have fewer active TCP client * objects than desired due to an earlier quota exhaustion. */ if (client->mortal && TCP_CLIENT(client) && !ns_g_clienttest) { LOCK(&client->interface->lock); if (client->interface->ntcpcurrent < client->interface->ntcptarget) client->mortal = ISC_FALSE; UNLOCK(&client->interface->lock); } /* * We don't need the client; send it to the inactive * queue for recycling. */ if (client->mortal) { if (client->newstate > NS_CLIENTSTATE_INACTIVE) client->newstate = NS_CLIENTSTATE_INACTIVE; } if (NS_CLIENTSTATE_READY == client->newstate) { if (TCP_CLIENT(client)) { client_accept(client); } else client_udprecv(client); client->newstate = NS_CLIENTSTATE_MAX; return (ISC_TRUE); } } if (client->state == NS_CLIENTSTATE_READY) { INSIST(client->newstate <= NS_CLIENTSTATE_INACTIVE); /* * We are trying to enter the inactive state. */ if (client->naccepts > 0) isc_socket_cancel(client->tcplistener, client->task, ISC_SOCKCANCEL_ACCEPT); /* Still waiting for accept cancel completion. */ if (! (client->naccepts == 0)) return (ISC_TRUE); /* Accept cancel is complete. */ if (client->nrecvs > 0) isc_socket_cancel(client->udpsocket, client->task, ISC_SOCKCANCEL_RECV); /* Still waiting for recv cancel completion. */ if (! (client->nrecvs == 0)) return (ISC_TRUE); /* Still waiting for control event to be delivered */ if (client->nctls > 0) return (ISC_TRUE); /* Deactivate the client. */ if (client->interface) ns_interface_detach(&client->interface); INSIST(client->naccepts == 0); INSIST(client->recursionquota == NULL); if (client->tcplistener != NULL) isc_socket_detach(&client->tcplistener); if (client->udpsocket != NULL) isc_socket_detach(&client->udpsocket); if (client->dispatch != NULL) dns_dispatch_detach(&client->dispatch); client->attributes = 0; client->mortal = ISC_FALSE; if (client->keytag != NULL) { isc_mem_put(client->mctx, client->keytag, client->keytag_len); client->keytag_len = 0; } /* * Put the client on the inactive list. If we are aiming for * the "freed" state, it will be removed from the inactive * list shortly, and we need to keep the manager locked until * that has been done, lest the manager decide to reactivate * the dying client inbetween. */ client->state = NS_CLIENTSTATE_INACTIVE; INSIST(client->recursionquota == NULL); if (client->state == client->newstate) { client->newstate = NS_CLIENTSTATE_MAX; if (!ns_g_clienttest && manager != NULL && !manager->exiting) ISC_QUEUE_PUSH(manager->inactive, client, ilink); if (client->needshutdown) isc_task_shutdown(client->task); return (ISC_TRUE); } } if (client->state == NS_CLIENTSTATE_INACTIVE) { INSIST(client->newstate == NS_CLIENTSTATE_FREED); /* * We are trying to free the client. * * When "shuttingdown" is true, either the task has received * its shutdown event or no shutdown event has ever been * set up. Thus, we have no outstanding shutdown * event at this point. */ REQUIRE(client->state == NS_CLIENTSTATE_INACTIVE); INSIST(client->recursionquota == NULL); INSIST(!ISC_QLINK_LINKED(client, ilink)); if (manager != NULL) { LOCK(&manager->listlock); ISC_LIST_UNLINK(manager->clients, client, link); LOCK(&manager->lock); if (manager->exiting && ISC_LIST_EMPTY(manager->clients)) destroy_manager = ISC_TRUE; UNLOCK(&manager->lock); UNLOCK(&manager->listlock); } ns_query_free(client); isc_mem_put(client->mctx, client->recvbuf, RECV_BUFFER_SIZE); isc_event_free((isc_event_t **)&client->sendevent); isc_event_free((isc_event_t **)&client->recvevent); isc_timer_detach(&client->timer); if (client->delaytimer != NULL) isc_timer_detach(&client->delaytimer); if (client->tcpbuf != NULL) isc_mem_put(client->mctx, client->tcpbuf, TCP_BUFFER_SIZE); if (client->opt != NULL) { INSIST(dns_rdataset_isassociated(client->opt)); dns_rdataset_disassociate(client->opt); dns_message_puttemprdataset(client->message, &client->opt); } if (client->keytag != NULL) { isc_mem_put(client->mctx, client->keytag, client->keytag_len); client->keytag_len = 0; } dns_message_destroy(&client->message); /* * Detaching the task must be done after unlinking from * the manager's lists because the manager accesses * client->task. */ if (client->task != NULL) isc_task_detach(&client->task); CTRACE("free"); client->magic = 0; /* * Check that there are no other external references to * the memory context. */ if (ns_g_clienttest && isc_mem_references(client->mctx) != 1) { isc_mem_stats(client->mctx, stderr); INSIST(0); } /* * Destroy the fetchlock mutex that was created in * ns_query_init(). */ DESTROYLOCK(&client->query.fetchlock); isc_mem_putanddetach(&client->mctx, client, sizeof(*client)); } if (destroy_manager && manager != NULL) clientmgr_destroy(manager); return (ISC_TRUE); } /*% * The client's task has received the client's control event * as part of the startup process. */ static void client_start(isc_task_t *task, isc_event_t *event) { ns_client_t *client = (ns_client_t *) event->ev_arg; INSIST(task == client->task); UNUSED(task); INSIST(client->nctls == 1); client->nctls--; if (exit_check(client)) return; if (TCP_CLIENT(client)) { if (client->pipelined) { client_read(client); } else { client_accept(client); } } else { client_udprecv(client); } } /*% * The client's task has received a shutdown event. */ static void client_shutdown(isc_task_t *task, isc_event_t *event) { ns_client_t *client; REQUIRE(event != NULL); REQUIRE(event->ev_type == ISC_TASKEVENT_SHUTDOWN); client = event->ev_arg; REQUIRE(NS_CLIENT_VALID(client)); REQUIRE(task == client->task); UNUSED(task); CTRACE("shutdown"); isc_event_free(&event); if (client->shutdown != NULL) { (client->shutdown)(client->shutdown_arg, ISC_R_SHUTTINGDOWN); client->shutdown = NULL; client->shutdown_arg = NULL; } if (ISC_QLINK_LINKED(client, ilink)) ISC_QUEUE_UNLINK(client->manager->inactive, client, ilink); client->newstate = NS_CLIENTSTATE_FREED; client->needshutdown = ISC_FALSE; (void)exit_check(client); } static void ns_client_endrequest(ns_client_t *client) { INSIST(client->naccepts == 0); INSIST(client->nreads == 0); INSIST(client->nsends == 0); INSIST(client->nrecvs == 0); INSIST(client->nupdates == 0); INSIST(client->state == NS_CLIENTSTATE_WORKING || client->state == NS_CLIENTSTATE_RECURSING); CTRACE("endrequest"); if (client->next != NULL) { (client->next)(client); client->next = NULL; } if (client->view != NULL) { #ifdef ENABLE_AFL if (ns_g_fuzz_type == ns_fuzz_resolver) { dns_cache_clean(client->view->cache, INT_MAX); dns_adb_flush(client->view->adb); } #endif dns_view_detach(&client->view); } if (client->opt != NULL) { INSIST(dns_rdataset_isassociated(client->opt)); dns_rdataset_disassociate(client->opt); dns_message_puttemprdataset(client->message, &client->opt); } client->signer = NULL; client->udpsize = 512; client->extflags = 0; client->ednsversion = -1; dns_message_reset(client->message, DNS_MESSAGE_INTENTPARSE); if (client->recursionquota != NULL) { isc_quota_detach(&client->recursionquota); isc_stats_decrement(ns_g_server->nsstats, dns_nsstatscounter_recursclients); } /* * Clear all client attributes that are specific to * the request; that's all except the TCP flag. */ client->attributes &= NS_CLIENTATTR_TCP; #ifdef ENABLE_AFL if (ns_g_fuzz_type == ns_fuzz_client || ns_g_fuzz_type == ns_fuzz_tcpclient || ns_g_fuzz_type == ns_fuzz_resolver) { named_fuzz_notify(); } #endif /* ENABLE_AFL */ } void ns_client_next(ns_client_t *client, isc_result_t result) { int newstate; REQUIRE(NS_CLIENT_VALID(client)); REQUIRE(client->state == NS_CLIENTSTATE_WORKING || client->state == NS_CLIENTSTATE_RECURSING || client->state == NS_CLIENTSTATE_READING); CTRACE("next"); if (result != ISC_R_SUCCESS) ns_client_log(client, DNS_LOGCATEGORY_SECURITY, NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3), "request failed: %s", isc_result_totext(result)); /* * An error processing a TCP request may have left * the connection out of sync. To be safe, we always * sever the connection when result != ISC_R_SUCCESS. */ if (result == ISC_R_SUCCESS && TCP_CLIENT(client)) newstate = NS_CLIENTSTATE_READING; else newstate = NS_CLIENTSTATE_READY; if (client->newstate > newstate) client->newstate = newstate; (void)exit_check(client); } static void client_senddone(isc_task_t *task, isc_event_t *event) { ns_client_t *client; isc_socketevent_t *sevent = (isc_socketevent_t *) event; REQUIRE(sevent != NULL); REQUIRE(sevent->ev_type == ISC_SOCKEVENT_SENDDONE); client = sevent->ev_arg; REQUIRE(NS_CLIENT_VALID(client)); REQUIRE(task == client->task); REQUIRE(sevent == client->sendevent); UNUSED(task); CTRACE("senddone"); if (sevent->result != ISC_R_SUCCESS) ns_client_log(client, NS_LOGCATEGORY_CLIENT, NS_LOGMODULE_CLIENT, ISC_LOG_WARNING, "error sending response: %s", isc_result_totext(sevent->result)); INSIST(client->nsends > 0); client->nsends--; if (client->tcpbuf != NULL) { INSIST(TCP_CLIENT(client)); isc_mem_put(client->mctx, client->tcpbuf, TCP_BUFFER_SIZE); client->tcpbuf = NULL; } ns_client_next(client, ISC_R_SUCCESS); } /*% * We only want to fail with ISC_R_NOSPACE when called from * ns_client_sendraw() and not when called from ns_client_send(), * tcpbuffer is NULL when called from ns_client_sendraw() and * length != 0. tcpbuffer != NULL when called from ns_client_send() * and length == 0. */ static isc_result_t client_allocsendbuf(ns_client_t *client, isc_buffer_t *buffer, isc_buffer_t *tcpbuffer, isc_uint32_t length, unsigned char *sendbuf, unsigned char **datap) { unsigned char *data; isc_uint32_t bufsize; isc_result_t result; INSIST(datap != NULL); INSIST((tcpbuffer == NULL && length != 0) || (tcpbuffer != NULL && length == 0)); if (TCP_CLIENT(client)) { INSIST(client->tcpbuf == NULL); if (length + 2 > TCP_BUFFER_SIZE) { result = ISC_R_NOSPACE; goto done; } client->tcpbuf = isc_mem_get(client->mctx, TCP_BUFFER_SIZE); if (client->tcpbuf == NULL) { result = ISC_R_NOMEMORY; goto done; } data = client->tcpbuf; if (tcpbuffer != NULL) { isc_buffer_init(tcpbuffer, data, TCP_BUFFER_SIZE); isc_buffer_init(buffer, data + 2, TCP_BUFFER_SIZE - 2); } else { isc_buffer_init(buffer, data, TCP_BUFFER_SIZE); INSIST(length <= 0xffff); isc_buffer_putuint16(buffer, (isc_uint16_t)length); } } else { data = sendbuf; if ((client->attributes & NS_CLIENTATTR_HAVECOOKIE) == 0) { if (client->view != NULL) bufsize = client->view->nocookieudp; else bufsize = 512; } else bufsize = client->udpsize; if (bufsize > client->udpsize) bufsize = client->udpsize; if (bufsize > SEND_BUFFER_SIZE) bufsize = SEND_BUFFER_SIZE; if (length > bufsize) { result = ISC_R_NOSPACE; goto done; } isc_buffer_init(buffer, data, bufsize); } *datap = data; result = ISC_R_SUCCESS; done: return (result); } static isc_result_t client_sendpkg(ns_client_t *client, isc_buffer_t *buffer) { struct in6_pktinfo *pktinfo; isc_result_t result; isc_region_t r; isc_sockaddr_t *address; isc_socket_t *sock; isc_netaddr_t netaddr; int match; unsigned int sockflags = ISC_SOCKFLAG_IMMEDIATE; isc_dscp_t dispdscp = -1; if (TCP_CLIENT(client)) { sock = client->tcpsocket; address = NULL; } else { sock = client->udpsocket; address = &client->peeraddr; isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr); if (ns_g_server->blackholeacl != NULL && dns_acl_match(&netaddr, NULL, ns_g_server->blackholeacl, &ns_g_server->aclenv, &match, NULL) == ISC_R_SUCCESS && match > 0) return (DNS_R_BLACKHOLED); sockflags |= ISC_SOCKFLAG_NORETRY; } if ((client->attributes & NS_CLIENTATTR_PKTINFO) != 0 && (client->attributes & NS_CLIENTATTR_MULTICAST) == 0) pktinfo = &client->pktinfo; else pktinfo = NULL; if (client->dispatch != NULL) { dispdscp = dns_dispatch_getdscp(client->dispatch); if (dispdscp != -1) client->dscp = dispdscp; } if (client->dscp == -1) { client->sendevent->attributes &= ~ISC_SOCKEVENTATTR_DSCP; client->sendevent->dscp = 0; } else { client->sendevent->attributes |= ISC_SOCKEVENTATTR_DSCP; client->sendevent->dscp = client->dscp; } isc_buffer_usedregion(buffer, &r); /* * If this is a UDP client and the IPv6 packet can't be * encapsulated without generating a PTB on a 1500 octet * MTU link force fragmentation at 1280 if it is a IPv6 * response. */ client->sendevent->attributes &= ~ISC_SOCKEVENTATTR_USEMINMTU; if (!TCP_CLIENT(client) && r.length > 1432) client->sendevent->attributes |= ISC_SOCKEVENTATTR_USEMINMTU; CTRACE("sendto"); result = isc_socket_sendto2(sock, &r, client->task, address, pktinfo, client->sendevent, sockflags); if (result == ISC_R_SUCCESS || result == ISC_R_INPROGRESS) { client->nsends++; if (result == ISC_R_SUCCESS) client_senddone(client->task, (isc_event_t *)client->sendevent); result = ISC_R_SUCCESS; } return (result); } void ns_client_sendraw(ns_client_t *client, dns_message_t *message) { isc_result_t result; unsigned char *data; isc_buffer_t buffer; isc_region_t r; isc_region_t *mr; unsigned char sendbuf[SEND_BUFFER_SIZE]; REQUIRE(NS_CLIENT_VALID(client)); CTRACE("sendraw"); mr = dns_message_getrawmessage(message); if (mr == NULL) { result = ISC_R_UNEXPECTEDEND; goto done; } result = client_allocsendbuf(client, &buffer, NULL, mr->length, sendbuf, &data); if (result != ISC_R_SUCCESS) goto done; /* * Copy message to buffer and fixup id. */ isc_buffer_availableregion(&buffer, &r); result = isc_buffer_copyregion(&buffer, mr); if (result != ISC_R_SUCCESS) goto done; r.base[0] = (client->message->id >> 8) & 0xff; r.base[1] = client->message->id & 0xff; result = client_sendpkg(client, &buffer); if (result == ISC_R_SUCCESS) return; done: if (client->tcpbuf != NULL) { isc_mem_put(client->mctx, client->tcpbuf, TCP_BUFFER_SIZE); client->tcpbuf = NULL; } ns_client_next(client, result); } static void client_send(ns_client_t *client) { isc_result_t result; unsigned char *data; isc_buffer_t buffer; isc_buffer_t tcpbuffer; isc_region_t r; dns_compress_t cctx; isc_boolean_t cleanup_cctx = ISC_FALSE; unsigned char sendbuf[SEND_BUFFER_SIZE]; unsigned int render_opts; unsigned int preferred_glue; isc_boolean_t opt_included = ISC_FALSE; size_t respsize; #ifdef HAVE_DNSTAP unsigned char zone[DNS_NAME_MAXWIRE]; dns_dtmsgtype_t dtmsgtype; isc_region_t zr; #endif /* HAVE_DNSTAP */ REQUIRE(NS_CLIENT_VALID(client)); CTRACE("send"); if (client->message->opcode == dns_opcode_query && (client->attributes & NS_CLIENTATTR_RA) != 0) client->message->flags |= DNS_MESSAGEFLAG_RA; if ((client->attributes & NS_CLIENTATTR_WANTDNSSEC) != 0) render_opts = 0; else render_opts = DNS_MESSAGERENDER_OMITDNSSEC; preferred_glue = 0; if (client->view != NULL) { if (client->view->preferred_glue == dns_rdatatype_a) preferred_glue = DNS_MESSAGERENDER_PREFER_A; else if (client->view->preferred_glue == dns_rdatatype_aaaa) preferred_glue = DNS_MESSAGERENDER_PREFER_AAAA; } if (preferred_glue == 0) { if (isc_sockaddr_pf(&client->peeraddr) == AF_INET) preferred_glue = DNS_MESSAGERENDER_PREFER_A; else preferred_glue = DNS_MESSAGERENDER_PREFER_AAAA; } #ifdef ALLOW_FILTER_AAAA /* * filter-aaaa-on-v4 yes or break-dnssec option to suppress * AAAA records. * * We already know that request came via IPv4, * that we have both AAAA and A records, * and that we either have no signatures that the client wants * or we are supposed to break DNSSEC. * * Override preferred glue if necessary. */ if ((client->attributes & NS_CLIENTATTR_FILTER_AAAA) != 0) { render_opts |= DNS_MESSAGERENDER_FILTER_AAAA; if (preferred_glue == DNS_MESSAGERENDER_PREFER_AAAA) preferred_glue = DNS_MESSAGERENDER_PREFER_A; } #endif /* * Create an OPT for our reply. */ if ((client->attributes & NS_CLIENTATTR_WANTOPT) != 0) { result = ns_client_addopt(client, client->message, &client->opt); if (result != ISC_R_SUCCESS) goto done; } /* * XXXRTH The following doesn't deal with TCP buffer resizing. */ result = client_allocsendbuf(client, &buffer, &tcpbuffer, 0, sendbuf, &data); if (result != ISC_R_SUCCESS) goto done; result = dns_compress_init(&cctx, -1, client->mctx); if (result != ISC_R_SUCCESS) goto done; if (client->peeraddr_valid && client->view != NULL) { isc_netaddr_t netaddr; dns_name_t *name = NULL; isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr); if (client->message->tsigkey != NULL) name = &client->message->tsigkey->name; if (client->view->nocasecompress == NULL || !allowed(&netaddr, name, NULL, 0, NULL, client->view->nocasecompress)) { dns_compress_setsensitive(&cctx, ISC_TRUE); } if (client->view->msgcompression == ISC_FALSE) { dns_compress_disable(&cctx); } } cleanup_cctx = ISC_TRUE; result = dns_message_renderbegin(client->message, &cctx, &buffer); if (result != ISC_R_SUCCESS) goto done; if (client->opt != NULL) { result = dns_message_setopt(client->message, client->opt); opt_included = ISC_TRUE; client->opt = NULL; if (result != ISC_R_SUCCESS) goto done; } result = dns_message_rendersection(client->message, DNS_SECTION_QUESTION, 0); if (result == ISC_R_NOSPACE) { client->message->flags |= DNS_MESSAGEFLAG_TC; goto renderend; } if (result != ISC_R_SUCCESS) goto done; /* * Stop after the question if TC was set for rate limiting. */ if ((client->message->flags & DNS_MESSAGEFLAG_TC) != 0) goto renderend; result = dns_message_rendersection(client->message, DNS_SECTION_ANSWER, DNS_MESSAGERENDER_PARTIAL | render_opts); if (result == ISC_R_NOSPACE) { client->message->flags |= DNS_MESSAGEFLAG_TC; goto renderend; } if (result != ISC_R_SUCCESS) goto done; result = dns_message_rendersection(client->message, DNS_SECTION_AUTHORITY, DNS_MESSAGERENDER_PARTIAL | render_opts); if (result == ISC_R_NOSPACE) { client->message->flags |= DNS_MESSAGEFLAG_TC; goto renderend; } if (result != ISC_R_SUCCESS) goto done; result = dns_message_rendersection(client->message, DNS_SECTION_ADDITIONAL, preferred_glue | render_opts); if (result != ISC_R_SUCCESS && result != ISC_R_NOSPACE) goto done; renderend: result = dns_message_renderend(client->message); if (result != ISC_R_SUCCESS) goto done; #ifdef HAVE_DNSTAP memset(&zr, 0, sizeof(zr)); if (((client->message->flags & DNS_MESSAGEFLAG_AA) != 0) && (client->query.authzone != NULL)) { isc_buffer_t b; dns_name_t *zo = dns_zone_getorigin(client->query.authzone); isc_buffer_init(&b, zone, sizeof(zone)); dns_compress_setmethods(&cctx, DNS_COMPRESS_NONE); result = dns_name_towire(zo, &cctx, &b); if (result == ISC_R_SUCCESS) isc_buffer_usedregion(&b, &zr); } if ((client->message->flags & DNS_MESSAGEFLAG_RD) != 0) dtmsgtype = DNS_DTTYPE_CR; else dtmsgtype = DNS_DTTYPE_AR; #endif /* HAVE_DNSTAP */ if (cleanup_cctx) { dns_compress_invalidate(&cctx); cleanup_cctx = ISC_FALSE; } if (TCP_CLIENT(client)) { isc_buffer_usedregion(&buffer, &r); isc_buffer_putuint16(&tcpbuffer, (isc_uint16_t) r.length); isc_buffer_add(&tcpbuffer, r.length); #ifdef HAVE_DNSTAP if (client->view != NULL) { dns_dt_send(client->view, dtmsgtype, &client->peeraddr, &client->interface->addr, ISC_TRUE, &zr, &client->requesttime, NULL, &buffer); } #endif /* HAVE_DNSTAP */ /* don't count the 2-octet length header */ respsize = isc_buffer_usedlength(&tcpbuffer) - 2; result = client_sendpkg(client, &tcpbuffer); switch (isc_sockaddr_pf(&client->peeraddr)) { case AF_INET: isc_stats_increment(ns_g_server->tcpoutstats4, ISC_MIN((int)respsize / 16, 256)); break; case AF_INET6: isc_stats_increment(ns_g_server->tcpoutstats6, ISC_MIN((int)respsize / 16, 256)); break; default: INSIST(0); break; } } else { respsize = isc_buffer_usedlength(&buffer); result = client_sendpkg(client, &buffer); #ifdef HAVE_DNSTAP if (client->view != NULL) { dns_dt_send(client->view, dtmsgtype, &client->peeraddr, &client->interface->addr, ISC_FALSE, &zr, &client->requesttime, NULL, &buffer); } #endif /* HAVE_DNSTAP */ switch (isc_sockaddr_pf(&client->peeraddr)) { case AF_INET: isc_stats_increment(ns_g_server->udpoutstats4, ISC_MIN((int)respsize / 16, 256)); break; case AF_INET6: isc_stats_increment(ns_g_server->udpoutstats6, ISC_MIN((int)respsize / 16, 256)); break; default: INSIST(0); break; } } /* update statistics (XXXJT: is it okay to access message->xxxkey?) */ isc_stats_increment(ns_g_server->nsstats, dns_nsstatscounter_response); dns_rcodestats_increment(ns_g_server->rcodestats, client->message->rcode); if (opt_included) { isc_stats_increment(ns_g_server->nsstats, dns_nsstatscounter_edns0out); } if (client->message->tsigkey != NULL) { isc_stats_increment(ns_g_server->nsstats, dns_nsstatscounter_tsigout); } if (client->message->sig0key != NULL) { isc_stats_increment(ns_g_server->nsstats, dns_nsstatscounter_sig0out); } if ((client->message->flags & DNS_MESSAGEFLAG_TC) != 0) isc_stats_increment(ns_g_server->nsstats, dns_nsstatscounter_truncatedresp); if (result == ISC_R_SUCCESS) return; done: if (client->tcpbuf != NULL) { isc_mem_put(client->mctx, client->tcpbuf, TCP_BUFFER_SIZE); client->tcpbuf = NULL; } if (cleanup_cctx) dns_compress_invalidate(&cctx); ns_client_next(client, result); } /* * Completes the sending of a delayed client response. */ static void client_delay(isc_task_t *task, isc_event_t *event) { ns_client_t *client; REQUIRE(event != NULL); REQUIRE(event->ev_type == ISC_TIMEREVENT_LIFE || event->ev_type == ISC_TIMEREVENT_IDLE); client = event->ev_arg; REQUIRE(NS_CLIENT_VALID(client)); REQUIRE(task == client->task); REQUIRE(client->delaytimer != NULL); UNUSED(task); CTRACE("client_delay"); isc_event_free(&event); isc_timer_detach(&client->delaytimer); client_send(client); ns_client_detach(&client); } void ns_client_send(ns_client_t *client) { /* * Delay the response by ns_g_delay ms. */ if (ns_g_delay != 0) { ns_client_t *dummy = NULL; isc_result_t result; isc_interval_t interval; /* * Replace ourselves if we have not already been replaced. */ if (!client->mortal) { result = ns_client_replace(client); if (result != ISC_R_SUCCESS) goto nodelay; } ns_client_attach(client, &dummy); if (ns_g_delay >= 1000) isc_interval_set(&interval, ns_g_delay / 1000, (ns_g_delay % 1000) * 1000000); else isc_interval_set(&interval, 0, ns_g_delay * 1000000); result = isc_timer_create(client->manager->timermgr, isc_timertype_once, NULL, &interval, client->task, client_delay, client, &client->delaytimer); if (result == ISC_R_SUCCESS) return; ns_client_detach(&dummy); } nodelay: client_send(client); } #if NS_CLIENT_DROPPORT #define DROPPORT_NO 0 #define DROPPORT_REQUEST 1 #define DROPPORT_RESPONSE 2 /*% * ns_client_dropport determines if certain requests / responses * should be dropped based on the port number. * * Returns: * \li 0: Don't drop. * \li 1: Drop request. * \li 2: Drop (error) response. */ static int ns_client_dropport(in_port_t port) { switch (port) { case 7: /* echo */ case 13: /* daytime */ case 19: /* chargen */ case 37: /* time */ return (DROPPORT_REQUEST); case 464: /* kpasswd */ return (DROPPORT_RESPONSE); } return (DROPPORT_NO); } #endif void ns_client_error(ns_client_t *client, isc_result_t result) { dns_rcode_t rcode; dns_message_t *message; REQUIRE(NS_CLIENT_VALID(client)); CTRACE("error"); message = client->message; rcode = dns_result_torcode(result); #if NS_CLIENT_DROPPORT /* * Don't send FORMERR to ports on the drop port list. */ if (rcode == dns_rcode_formerr && ns_client_dropport(isc_sockaddr_getport(&client->peeraddr)) != DROPPORT_NO) { char buf[64]; isc_buffer_t b; isc_buffer_init(&b, buf, sizeof(buf) - 1); if (dns_rcode_totext(rcode, &b) != ISC_R_SUCCESS) isc_buffer_putstr(&b, "UNKNOWN RCODE"); ns_client_log(client, DNS_LOGCATEGORY_SECURITY, NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10), "dropped error (%.*s) response: suspicious port", (int)isc_buffer_usedlength(&b), buf); ns_client_next(client, ISC_R_SUCCESS); return; } #endif /* * Try to rate limit error responses. */ if (client->view != NULL && client->view->rrl != NULL) { isc_boolean_t wouldlog; char log_buf[DNS_RRL_LOG_BUF_LEN]; dns_rrl_result_t rrl_result; int loglevel; INSIST(rcode != dns_rcode_noerror && rcode != dns_rcode_nxdomain); if (ns_g_server->log_queries) loglevel = DNS_RRL_LOG_DROP; else loglevel = ISC_LOG_DEBUG(1); wouldlog = isc_log_wouldlog(ns_g_lctx, loglevel); rrl_result = dns_rrl(client->view, &client->peeraddr, TCP_CLIENT(client), dns_rdataclass_in, dns_rdatatype_none, NULL, result, client->now, wouldlog, log_buf, sizeof(log_buf)); if (rrl_result != DNS_RRL_RESULT_OK) { /* * Log dropped errors in the query category * so that they are not lost in silence. * Starts of rate-limited bursts are logged in * NS_LOGCATEGORY_RRL. */ if (wouldlog) { ns_client_log(client, NS_LOGCATEGORY_QUERY_ERRORS, NS_LOGMODULE_CLIENT, loglevel, "%s", log_buf); } /* * Some error responses cannot be 'slipped', * so don't try to slip any error responses. */ if (!client->view->rrl->log_only) { isc_stats_increment(ns_g_server->nsstats, dns_nsstatscounter_ratedropped); isc_stats_increment(ns_g_server->nsstats, dns_nsstatscounter_dropped); ns_client_next(client, DNS_R_DROP); return; } } } /* * Message may be an in-progress reply that we had trouble * with, in which case QR will be set. We need to clear QR before * calling dns_message_reply() to avoid triggering an assertion. */ message->flags &= ~DNS_MESSAGEFLAG_QR; /* * AA and AD shouldn't be set. */ message->flags &= ~(DNS_MESSAGEFLAG_AA | DNS_MESSAGEFLAG_AD); result = dns_message_reply(message, ISC_TRUE); if (result != ISC_R_SUCCESS) { /* * It could be that we've got a query with a good header, * but a bad question section, so we try again with * want_question_section set to ISC_FALSE. */ result = dns_message_reply(message, ISC_FALSE); if (result != ISC_R_SUCCESS) { ns_client_next(client, result); return; } } message->rcode = rcode; if (rcode == dns_rcode_formerr) { /* * FORMERR loop avoidance: If we sent a FORMERR message * with the same ID to the same client less than two * seconds ago, assume that we are in an infinite error * packet dialog with a server for some protocol whose * error responses look enough like DNS queries to * elicit a FORMERR response. Drop a packet to break * the loop. */ if (isc_sockaddr_equal(&client->peeraddr, &client->formerrcache.addr) && message->id == client->formerrcache.id && (isc_time_seconds(&client->requesttime) - client->formerrcache.time) < 2) { /* Drop packet. */ ns_client_log(client, NS_LOGCATEGORY_CLIENT, NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1), "possible error packet loop, " "FORMERR dropped"); ns_client_next(client, result); return; } client->formerrcache.addr = client->peeraddr; client->formerrcache.time = isc_time_seconds(&client->requesttime); client->formerrcache.id = message->id; } else if (rcode == dns_rcode_servfail && client->query.qname != NULL && client->view != NULL && client->view->fail_ttl != 0 && ((client->attributes & NS_CLIENTATTR_NOSETFC) == 0)) { /* * SERVFAIL caching: store qname/qtype of failed queries */ isc_time_t expire; isc_interval_t i; isc_uint32_t flags = 0; if ((message->flags & DNS_MESSAGEFLAG_CD) != 0) flags = NS_FAILCACHE_CD; isc_interval_set(&i, client->view->fail_ttl, 0); result = isc_time_nowplusinterval(&expire, &i); if (result == ISC_R_SUCCESS) dns_badcache_add(client->view->failcache, client->query.qname, client->query.qtype, ISC_TRUE, flags, &expire); } ns_client_send(client); } isc_result_t ns_client_addopt(ns_client_t *client, dns_message_t *message, dns_rdataset_t **opt) { unsigned char ecs[ECS_SIZE]; char nsid[BUFSIZ], *nsidp; unsigned char cookie[COOKIE_SIZE]; isc_result_t result; dns_view_t *view; dns_resolver_t *resolver; isc_uint16_t udpsize; dns_ednsopt_t ednsopts[DNS_EDNSOPTIONS]; int count = 0; unsigned int flags; unsigned char expire[4]; REQUIRE(NS_CLIENT_VALID(client)); REQUIRE(opt != NULL && *opt == NULL); REQUIRE(message != NULL); view = client->view; resolver = (view != NULL) ? view->resolver : NULL; if (resolver != NULL) udpsize = dns_resolver_getudpsize(resolver); else udpsize = ns_g_udpsize; flags = client->extflags & DNS_MESSAGEEXTFLAG_REPLYPRESERVE; /* Set EDNS options if applicable */ if (WANTNSID(client) && (ns_g_server->server_id != NULL || ns_g_server->server_usehostname)) { if (ns_g_server->server_usehostname) { result = ns_os_gethostname(nsid, sizeof(nsid)); if (result != ISC_R_SUCCESS) { goto no_nsid; } nsidp = nsid; } else nsidp = ns_g_server->server_id; INSIST(count < DNS_EDNSOPTIONS); ednsopts[count].code = DNS_OPT_NSID; ednsopts[count].length = (isc_uint16_t)strlen(nsidp); ednsopts[count].value = (unsigned char *)nsidp; count++; } no_nsid: if ((client->attributes & NS_CLIENTATTR_WANTCOOKIE) != 0) { isc_buffer_t buf; isc_stdtime_t now; isc_uint32_t nonce; isc_buffer_init(&buf, cookie, sizeof(cookie)); isc_stdtime_get(&now); isc_random_get(&nonce); compute_cookie(client, now, nonce, &buf); INSIST(count < DNS_EDNSOPTIONS); ednsopts[count].code = DNS_OPT_COOKIE; ednsopts[count].length = COOKIE_SIZE; ednsopts[count].value = cookie; count++; } if ((client->attributes & NS_CLIENTATTR_HAVEEXPIRE) != 0) { isc_buffer_t buf; INSIST(count < DNS_EDNSOPTIONS); isc_buffer_init(&buf, expire, sizeof(expire)); isc_buffer_putuint32(&buf, client->expire); ednsopts[count].code = DNS_OPT_EXPIRE; ednsopts[count].length = 4; ednsopts[count].value = expire; count++; } if (((client->attributes & NS_CLIENTATTR_HAVEECS) != 0) && (client->ecs_addr.family == AF_INET || client->ecs_addr.family == AF_INET6 || client->ecs_addr.family == AF_UNSPEC)) { isc_buffer_t buf; isc_uint8_t addr[16]; isc_uint32_t plen, addrl; isc_uint16_t family; /* Add CLIENT-SUBNET option. */ plen = client->ecs_addrlen; /* Round up prefix len to a multiple of 8 */ addrl = (plen + 7) / 8; switch (client->ecs_addr.family) { case AF_UNSPEC: INSIST(plen == 0); family = 0; break; case AF_INET: INSIST(plen <= 32); family = 1; memmove(addr, &client->ecs_addr.type, addrl); break; case AF_INET6: INSIST(plen <= 128); family = 2; memmove(addr, &client->ecs_addr.type, addrl); break; default: INSIST(0); } isc_buffer_init(&buf, ecs, sizeof(ecs)); /* family */ isc_buffer_putuint16(&buf, family); /* source prefix-length */ isc_buffer_putuint8(&buf, client->ecs_addrlen); /* scope prefix-length */ isc_buffer_putuint8(&buf, client->ecs_scope); /* address */ if (addrl > 0) { /* Mask off last address byte */ if ((plen % 8) != 0) addr[addrl - 1] &= ~0U << (8 - (plen % 8)); isc_buffer_putmem(&buf, addr, (unsigned) addrl); } ednsopts[count].code = DNS_OPT_CLIENT_SUBNET; ednsopts[count].length = addrl + 4; ednsopts[count].value = ecs; count++; } result = dns_message_buildopt(message, opt, 0, udpsize, flags, ednsopts, count); return (result); } static inline isc_boolean_t allowed(isc_netaddr_t *addr, dns_name_t *signer, isc_netaddr_t *ecs_addr, isc_uint8_t ecs_addrlen, isc_uint8_t *ecs_scope, dns_acl_t *acl) { int match; isc_result_t result; if (acl == NULL) return (ISC_TRUE); result = dns_acl_match2(addr, signer, ecs_addr, ecs_addrlen, ecs_scope, acl, &ns_g_server->aclenv, &match, NULL); if (result == ISC_R_SUCCESS && match > 0) return (ISC_TRUE); return (ISC_FALSE); } /* * Callback to see if a non-recursive query coming from 'srcaddr' to * 'destaddr', with optional key 'mykey' for class 'rdclass' would be * delivered to 'myview'. * * We run this unlocked as both the view list and the interface list * are updated when the appropriate task has exclusivity. */ isc_boolean_t ns_client_isself(dns_view_t *myview, dns_tsigkey_t *mykey, isc_sockaddr_t *srcaddr, isc_sockaddr_t *dstaddr, dns_rdataclass_t rdclass, void *arg) { dns_view_t *view; dns_tsigkey_t *key = NULL; dns_name_t *tsig = NULL; isc_netaddr_t netsrc; isc_netaddr_t netdst; UNUSED(arg); /* * ns_g_server->interfacemgr is task exclusive locked. */ if (ns_g_server->interfacemgr == NULL) return (ISC_TRUE); if (!ns_interfacemgr_listeningon(ns_g_server->interfacemgr, dstaddr)) return (ISC_FALSE); isc_netaddr_fromsockaddr(&netsrc, srcaddr); isc_netaddr_fromsockaddr(&netdst, dstaddr); for (view = ISC_LIST_HEAD(ns_g_server->viewlist); view != NULL; view = ISC_LIST_NEXT(view, link)) { if (view->matchrecursiveonly) continue; if (rdclass != view->rdclass) continue; if (mykey != NULL) { isc_boolean_t match; isc_result_t result; result = dns_view_gettsig(view, &mykey->name, &key); if (result != ISC_R_SUCCESS) continue; match = dst_key_compare(mykey->key, key->key); dns_tsigkey_detach(&key); if (!match) continue; tsig = dns_tsigkey_identity(mykey); } if (allowed(&netsrc, tsig, NULL, 0, NULL, view->matchclients) && allowed(&netdst, tsig, NULL, 0, NULL, view->matchdestinations)) break; } return (ISC_TF(view == myview)); } static void compute_cookie(ns_client_t *client, isc_uint32_t when, isc_uint32_t nonce, isc_buffer_t *buf) { switch (ns_g_server->cookiealg) { #if defined(HAVE_OPENSSL_AES) || defined(HAVE_OPENSSL_EVP_AES) case ns_cookiealg_aes: { unsigned char digest[ISC_AES_BLOCK_LENGTH]; unsigned char input[4 + 4 + 16]; isc_netaddr_t netaddr; unsigned char *cp; unsigned int i; memset(input, 0, sizeof(input)); cp = isc_buffer_used(buf); isc_buffer_putmem(buf, client->cookie, 8); isc_buffer_putuint32(buf, nonce); isc_buffer_putuint32(buf, when); memmove(input, cp, 16); isc_aes128_crypt(ns_g_server->secret, input, digest); for (i = 0; i < 8; i++) input[i] = digest[i] ^ digest[i + 8]; isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr); switch (netaddr.family) { case AF_INET: cp = (unsigned char *)&netaddr.type.in; memmove(input + 8, cp, 4); memset(input + 12, 0, 4); isc_aes128_crypt(ns_g_server->secret, input, digest); break; case AF_INET6: cp = (unsigned char *)&netaddr.type.in6; memmove(input + 8, cp, 16); isc_aes128_crypt(ns_g_server->secret, input, digest); for (i = 0; i < 8; i++) input[i + 8] = digest[i] ^ digest[i + 8]; isc_aes128_crypt(ns_g_server->secret, input + 8, digest); break; } for (i = 0; i < 8; i++) digest[i] ^= digest[i + 8]; isc_buffer_putmem(buf, digest, 8); break; } #endif case ns_cookiealg_sha1: { unsigned char digest[ISC_SHA1_DIGESTLENGTH]; isc_netaddr_t netaddr; unsigned char *cp; isc_hmacsha1_t hmacsha1; unsigned int length; cp = isc_buffer_used(buf); isc_buffer_putmem(buf, client->cookie, 8); isc_buffer_putuint32(buf, nonce); isc_buffer_putuint32(buf, when); isc_hmacsha1_init(&hmacsha1, ns_g_server->secret, ISC_SHA1_DIGESTLENGTH); isc_hmacsha1_update(&hmacsha1, cp, 16); isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr); switch (netaddr.family) { case AF_INET: cp = (unsigned char *)&netaddr.type.in; length = 4; break; case AF_INET6: cp = (unsigned char *)&netaddr.type.in6; length = 16; break; default: INSIST(0); } isc_hmacsha1_update(&hmacsha1, cp, length); isc_hmacsha1_update(&hmacsha1, client->cookie, sizeof(client->cookie)); isc_hmacsha1_sign(&hmacsha1, digest, sizeof(digest)); isc_buffer_putmem(buf, digest, 8); isc_hmacsha1_invalidate(&hmacsha1); break; } case ns_cookiealg_sha256: { unsigned char digest[ISC_SHA256_DIGESTLENGTH]; isc_netaddr_t netaddr; unsigned char *cp; isc_hmacsha256_t hmacsha256; unsigned int length; cp = isc_buffer_used(buf); isc_buffer_putmem(buf, client->cookie, 8); isc_buffer_putuint32(buf, nonce); isc_buffer_putuint32(buf, when); isc_hmacsha256_init(&hmacsha256, ns_g_server->secret, ISC_SHA256_DIGESTLENGTH); isc_hmacsha256_update(&hmacsha256, cp, 16); isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr); switch (netaddr.family) { case AF_INET: cp = (unsigned char *)&netaddr.type.in; length = 4; break; case AF_INET6: cp = (unsigned char *)&netaddr.type.in6; length = 16; break; default: INSIST(0); } isc_hmacsha256_update(&hmacsha256, cp, length); isc_hmacsha256_update(&hmacsha256, client->cookie, sizeof(client->cookie)); isc_hmacsha256_sign(&hmacsha256, digest, sizeof(digest)); isc_buffer_putmem(buf, digest, 8); isc_hmacsha256_invalidate(&hmacsha256); break; } default: INSIST(0); } } static void process_cookie(ns_client_t *client, isc_buffer_t *buf, size_t optlen) { unsigned char dbuf[COOKIE_SIZE]; unsigned char *old; isc_stdtime_t now; isc_uint32_t when; isc_uint32_t nonce; isc_buffer_t db; /* * If we have already seen a cookie option skip this cookie option. */ if ((client->attributes & NS_CLIENTATTR_WANTCOOKIE) != 0) { isc_buffer_forward(buf, (unsigned int)optlen); return; } client->attributes |= NS_CLIENTATTR_WANTCOOKIE; isc_stats_increment(ns_g_server->nsstats, dns_nsstatscounter_cookiein); if (optlen != COOKIE_SIZE) { /* * Not our token. */ INSIST(optlen >= 8U); memmove(client->cookie, isc_buffer_current(buf), 8); isc_buffer_forward(buf, (unsigned int)optlen); if (optlen == 8U) isc_stats_increment(ns_g_server->nsstats, dns_nsstatscounter_cookienew); else isc_stats_increment(ns_g_server->nsstats, dns_nsstatscounter_cookiebadsize); return; } /* * Process all of the incoming buffer. */ old = isc_buffer_current(buf); memmove(client->cookie, old, 8); isc_buffer_forward(buf, 8); nonce = isc_buffer_getuint32(buf); when = isc_buffer_getuint32(buf); isc_buffer_forward(buf, 8); /* * Allow for a 5 minute clock skew between servers sharing a secret. * Only accept COOKIE if we have talked to the client in the last hour. */ isc_stdtime_get(&now); if (isc_serial_gt(when, (now + 300)) || /* In the future. */ isc_serial_lt(when, (now - 3600))) { /* In the past. */ isc_stats_increment(ns_g_server->nsstats, dns_nsstatscounter_cookiebadtime); return; } isc_buffer_init(&db, dbuf, sizeof(dbuf)); compute_cookie(client, when, nonce, &db); if (!isc_safe_memequal(old, dbuf, COOKIE_SIZE)) { isc_stats_increment(ns_g_server->nsstats, dns_nsstatscounter_cookienomatch); return; } isc_stats_increment(ns_g_server->nsstats, dns_nsstatscounter_cookiematch); client->attributes |= NS_CLIENTATTR_HAVECOOKIE; } static isc_result_t process_ecs(ns_client_t *client, isc_buffer_t *buf, size_t optlen) { isc_uint16_t family; isc_uint8_t addrlen, addrbytes, scope, *paddr; isc_netaddr_t caddr; /* * If we have already seen a ECS option skip this ECS option. */ if ((client->attributes & NS_CLIENTATTR_HAVEECS) != 0) { isc_buffer_forward(buf, (unsigned int)optlen); return (ISC_R_SUCCESS); } /* * XXXMUKS: Is there any need to repeat these checks here * (except query's scope length) when they are done in the OPT * RDATA fromwire code? */ if (optlen < 4U) { ns_client_log(client, NS_LOGCATEGORY_CLIENT, NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(2), "EDNS client-subnet option too short"); return (DNS_R_FORMERR); } family = isc_buffer_getuint16(buf); addrlen = isc_buffer_getuint8(buf); scope = isc_buffer_getuint8(buf); optlen -= 4; if (scope != 0U) { ns_client_log(client, NS_LOGCATEGORY_CLIENT, NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(2), "EDNS client-subnet option: invalid scope"); return (DNS_R_OPTERR); } memset(&caddr, 0, sizeof(caddr)); switch (family) { case 0: /* * XXXMUKS: In queries, if FAMILY is set to 0, SOURCE * PREFIX-LENGTH must be 0 and ADDRESS should not be * present as the address and prefix lengths don't make * sense because the family is unknown. */ if (addrlen != 0U) { ns_client_log(client, NS_LOGCATEGORY_CLIENT, NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(2), "EDNS client-subnet option: invalid " "address length (%u) for FAMILY=0", addrlen); return (DNS_R_OPTERR); } caddr.family = AF_UNSPEC; break; case 1: if (addrlen > 32U) { ns_client_log(client, NS_LOGCATEGORY_CLIENT, NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(2), "EDNS client-subnet option: invalid " "address length (%u) for IPv4", addrlen); return (DNS_R_OPTERR); } caddr.family = AF_INET; break; case 2: if (addrlen > 128U) { ns_client_log(client, NS_LOGCATEGORY_CLIENT, NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(2), "EDNS client-subnet option: invalid " "address length (%u) for IPv6", addrlen); return (DNS_R_OPTERR); } caddr.family = AF_INET6; break; default: ns_client_log(client, NS_LOGCATEGORY_CLIENT, NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(2), "EDNS client-subnet option: invalid family"); return (DNS_R_OPTERR); } addrbytes = (addrlen + 7) / 8; if (isc_buffer_remaininglength(buf) < addrbytes) { ns_client_log(client, NS_LOGCATEGORY_CLIENT, NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(2), "EDNS client-subnet option: address too short"); return (DNS_R_OPTERR); } paddr = (isc_uint8_t *) &caddr.type; if (addrbytes != 0U) { memmove(paddr, isc_buffer_current(buf), addrbytes); isc_buffer_forward(buf, addrbytes); optlen -= addrbytes; if ((addrlen % 8) != 0) { isc_uint8_t bits = ~0U << (8 - (addrlen % 8)); bits &= paddr[addrbytes - 1]; if (bits != paddr[addrbytes - 1]) return (DNS_R_OPTERR); } } memmove(&client->ecs_addr, &caddr, sizeof(caddr)); client->ecs_addrlen = addrlen; client->ecs_scope = 0; client->attributes |= NS_CLIENTATTR_HAVEECS; isc_buffer_forward(buf, (unsigned int)optlen); return (ISC_R_SUCCESS); } static isc_result_t process_keytag(ns_client_t *client, isc_buffer_t *buf, size_t optlen) { if (optlen == 0 || (optlen % 2) != 0) { isc_buffer_forward(buf, (unsigned int)optlen); return (DNS_R_OPTERR); } client->keytag = isc_mem_get(client->mctx, optlen); if (client->keytag != NULL) { client->keytag_len = (isc_uint16_t)optlen; memmove(client->keytag, isc_buffer_current(buf), optlen); } isc_buffer_forward(buf, (unsigned int)optlen); return (ISC_R_SUCCESS); } static isc_result_t process_opt(ns_client_t *client, dns_rdataset_t *opt) { dns_rdata_t rdata; isc_buffer_t optbuf; isc_result_t result; isc_uint16_t optcode; isc_uint16_t optlen; /* * Set the client's UDP buffer size. */ client->udpsize = opt->rdclass; /* * If the requested UDP buffer size is less than 512, * ignore it and use 512. */ if (client->udpsize < 512) client->udpsize = 512; /* * Get the flags out of the OPT record. */ client->extflags = (isc_uint16_t)(opt->ttl & 0xFFFF); /* * Do we understand this version of EDNS? * * XXXRTH need library support for this! */ client->ednsversion = (opt->ttl & 0x00FF0000) >> 16; if (client->ednsversion > DNS_EDNS_VERSION) { isc_stats_increment(ns_g_server->nsstats, dns_nsstatscounter_badednsver); result = ns_client_addopt(client, client->message, &client->opt); if (result == ISC_R_SUCCESS) result = DNS_R_BADVERS; ns_client_error(client, result); goto cleanup; } /* Check for NSID request */ result = dns_rdataset_first(opt); if (result == ISC_R_SUCCESS) { dns_rdata_init(&rdata); dns_rdataset_current(opt, &rdata); isc_buffer_init(&optbuf, rdata.data, rdata.length); isc_buffer_add(&optbuf, rdata.length); while (isc_buffer_remaininglength(&optbuf) >= 4) { optcode = isc_buffer_getuint16(&optbuf); optlen = isc_buffer_getuint16(&optbuf); switch (optcode) { case DNS_OPT_NSID: if (!WANTNSID(client)) isc_stats_increment( ns_g_server->nsstats, dns_nsstatscounter_nsidopt); client->attributes |= NS_CLIENTATTR_WANTNSID; isc_buffer_forward(&optbuf, optlen); break; case DNS_OPT_COOKIE: process_cookie(client, &optbuf, optlen); break; case DNS_OPT_EXPIRE: if (!WANTEXPIRE(client)) isc_stats_increment( ns_g_server->nsstats, dns_nsstatscounter_expireopt); client->attributes |= NS_CLIENTATTR_WANTEXPIRE; isc_buffer_forward(&optbuf, optlen); break; case DNS_OPT_CLIENT_SUBNET: result = process_ecs(client, &optbuf, optlen); if (result != ISC_R_SUCCESS) { ns_client_error(client, result); goto cleanup; } isc_stats_increment(ns_g_server->nsstats, dns_nsstatscounter_ecsopt); break; case DNS_OPT_KEY_TAG: result = process_keytag(client, &optbuf, optlen); if (result != ISC_R_SUCCESS) { ns_client_error(client, result); return (result); } isc_stats_increment(ns_g_server->nsstats, dns_nsstatscounter_keytagopt); break; default: isc_stats_increment(ns_g_server->nsstats, dns_nsstatscounter_otheropt); isc_buffer_forward(&optbuf, optlen); break; } } } isc_stats_increment(ns_g_server->nsstats, dns_nsstatscounter_edns0in); client->attributes |= NS_CLIENTATTR_WANTOPT; cleanup: return (result); } /* * Handle an incoming request event from the socket (UDP case) * or tcpmsg (TCP case). */ static void client_request(isc_task_t *task, isc_event_t *event) { ns_client_t *client; isc_socketevent_t *sevent; isc_result_t result; isc_result_t sigresult = ISC_R_SUCCESS; isc_buffer_t *buffer; isc_buffer_t tbuffer; dns_view_t *view; dns_rdataset_t *opt; dns_name_t *signame; isc_boolean_t ra; /* Recursion available. */ isc_netaddr_t netaddr; int match; dns_messageid_t id; unsigned int flags; isc_boolean_t notimp; size_t reqsize; #ifdef HAVE_DNSTAP dns_dtmsgtype_t dtmsgtype; #endif REQUIRE(event != NULL); client = event->ev_arg; REQUIRE(NS_CLIENT_VALID(client)); REQUIRE(task == client->task); INSIST(client->recursionquota == NULL); INSIST(client->state == (TCP_CLIENT(client) ? NS_CLIENTSTATE_READING : NS_CLIENTSTATE_READY)); ns_client_requests++; if (event->ev_type == ISC_SOCKEVENT_RECVDONE) { INSIST(!TCP_CLIENT(client)); sevent = (isc_socketevent_t *)event; REQUIRE(sevent == client->recvevent); isc_buffer_init(&tbuffer, sevent->region.base, sevent->n); isc_buffer_add(&tbuffer, sevent->n); buffer = &tbuffer; result = sevent->result; if (result == ISC_R_SUCCESS) { client->peeraddr = sevent->address; client->peeraddr_valid = ISC_TRUE; } if ((sevent->attributes & ISC_SOCKEVENTATTR_DSCP) != 0) { ns_client_log(client, NS_LOGCATEGORY_CLIENT, NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(90), "received DSCP %d", sevent->dscp); if (client->dscp == -1) client->dscp = sevent->dscp; } if ((sevent->attributes & ISC_SOCKEVENTATTR_PKTINFO) != 0) { client->attributes |= NS_CLIENTATTR_PKTINFO; client->pktinfo = sevent->pktinfo; } if ((sevent->attributes & ISC_SOCKEVENTATTR_MULTICAST) != 0) client->attributes |= NS_CLIENTATTR_MULTICAST; client->nrecvs--; } else { INSIST(TCP_CLIENT(client)); REQUIRE(event->ev_type == DNS_EVENT_TCPMSG); REQUIRE(event->ev_sender == &client->tcpmsg); buffer = &client->tcpmsg.buffer; result = client->tcpmsg.result; INSIST(client->nreads == 1); /* * client->peeraddr was set when the connection was accepted. */ client->nreads--; } reqsize = isc_buffer_usedlength(buffer); /* don't count the length header */ if (TCP_CLIENT(client)) reqsize -= 2; if (exit_check(client)) goto cleanup; client->state = client->newstate = NS_CLIENTSTATE_WORKING; isc_task_getcurrenttimex(task, &client->requesttime); client->tnow = client->requesttime; client->now = isc_time_seconds(&client->tnow); if (result != ISC_R_SUCCESS) { if (TCP_CLIENT(client)) { ns_client_next(client, result); } else { if (result != ISC_R_CANCELED) isc_log_write(ns_g_lctx, NS_LOGCATEGORY_CLIENT, NS_LOGMODULE_CLIENT, ISC_LOG_ERROR, "UDP client handler shutting " "down due to fatal receive " "error: %s", isc_result_totext(result)); isc_task_shutdown(client->task); } goto cleanup; } isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr); #if NS_CLIENT_DROPPORT if (ns_client_dropport(isc_sockaddr_getport(&client->peeraddr)) == DROPPORT_REQUEST) { ns_client_log(client, DNS_LOGCATEGORY_SECURITY, NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10), "dropped request: suspicious port"); ns_client_next(client, ISC_R_SUCCESS); goto cleanup; } #endif ns_client_log(client, NS_LOGCATEGORY_CLIENT, NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3), "%s request", TCP_CLIENT(client) ? "TCP" : "UDP"); /* * Check the blackhole ACL for UDP only, since TCP is done in * client_newconn. */ if (!TCP_CLIENT(client)) { if (ns_g_server->blackholeacl != NULL && dns_acl_match(&netaddr, NULL, ns_g_server->blackholeacl, &ns_g_server->aclenv, &match, NULL) == ISC_R_SUCCESS && match > 0) { ns_client_log(client, DNS_LOGCATEGORY_SECURITY, NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10), "blackholed UDP datagram"); ns_client_next(client, ISC_R_SUCCESS); goto cleanup; } } /* * Silently drop multicast requests for the present. * XXXMPA revisit this as mDNS spec was published. */ if ((client->attributes & NS_CLIENTATTR_MULTICAST) != 0) { ns_client_log(client, NS_LOGCATEGORY_CLIENT, NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(2), "dropping multicast request"); ns_client_next(client, DNS_R_REFUSED); goto cleanup; } result = dns_message_peekheader(buffer, &id, &flags); if (result != ISC_R_SUCCESS) { /* * There isn't enough header to determine whether * this was a request or a response. Drop it. */ ns_client_next(client, result); goto cleanup; } /* * The client object handles requests, not responses. * If this is a UDP response, forward it to the dispatcher. * If it's a TCP response, discard it here. */ if ((flags & DNS_MESSAGEFLAG_QR) != 0) { if (TCP_CLIENT(client)) { CTRACE("unexpected response"); ns_client_next(client, DNS_R_FORMERR); goto cleanup; } else { dns_dispatch_importrecv(client->dispatch, event); ns_client_next(client, ISC_R_SUCCESS); goto cleanup; } } /* * Update some statistics counters. Don't count responses. */ if (isc_sockaddr_pf(&client->peeraddr) == PF_INET) { isc_stats_increment(ns_g_server->nsstats, dns_nsstatscounter_requestv4); } else { isc_stats_increment(ns_g_server->nsstats, dns_nsstatscounter_requestv6); } if (TCP_CLIENT(client)) { isc_stats_increment(ns_g_server->nsstats, dns_nsstatscounter_requesttcp); switch (isc_sockaddr_pf(&client->peeraddr)) { case AF_INET: isc_stats_increment(ns_g_server->tcpinstats4, ISC_MIN((int)reqsize / 16, 18)); break; case AF_INET6: isc_stats_increment(ns_g_server->tcpinstats6, ISC_MIN((int)reqsize / 16, 18)); break; default: INSIST(0); break; } } else { switch (isc_sockaddr_pf(&client->peeraddr)) { case AF_INET: isc_stats_increment(ns_g_server->udpinstats4, ISC_MIN((int)reqsize / 16, 18)); break; case AF_INET6: isc_stats_increment(ns_g_server->udpinstats6, ISC_MIN((int)reqsize / 16, 18)); break; default: INSIST(0); break; } } /* * It's a request. Parse it. */ result = dns_message_parse(client->message, buffer, 0); if (result != ISC_R_SUCCESS) { /* * Parsing the request failed. Send a response * (typically FORMERR or SERVFAIL). */ if (result == DNS_R_OPTERR) (void)ns_client_addopt(client, client->message, &client->opt); ns_client_log(client, NS_LOGCATEGORY_CLIENT, NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1), "message parsing failed: %s", isc_result_totext(result)); ns_client_error(client, result); goto cleanup; } /* * Pipeline TCP query processing. */ if (client->message->opcode != dns_opcode_query) client->pipelined = ISC_FALSE; if (TCP_CLIENT(client) && client->pipelined) { result = isc_quota_reserve(&ns_g_server->tcpquota); if (result == ISC_R_SUCCESS) result = ns_client_replace(client); if (result != ISC_R_SUCCESS) { ns_client_log(client, NS_LOGCATEGORY_CLIENT, NS_LOGMODULE_CLIENT, ISC_LOG_WARNING, "no more TCP clients(read): %s", isc_result_totext(result)); client->pipelined = ISC_FALSE; } } dns_opcodestats_increment(ns_g_server->opcodestats, client->message->opcode); switch (client->message->opcode) { case dns_opcode_query: case dns_opcode_update: case dns_opcode_notify: notimp = ISC_FALSE; break; case dns_opcode_iquery: default: notimp = ISC_TRUE; break; } client->message->rcode = dns_rcode_noerror; /* RFC1123 section 6.1.3.2 */ if ((client->attributes & NS_CLIENTATTR_MULTICAST) != 0) client->message->flags &= ~DNS_MESSAGEFLAG_RD; /* * Deal with EDNS. */ if (ns_g_noedns) opt = NULL; else opt = dns_message_getopt(client->message); client->ecs_addrlen = 0; client->ecs_scope = 0; if (opt != NULL) { /* * Are we dropping all EDNS queries? */ if (ns_g_dropedns) { ns_client_next(client, ISC_R_SUCCESS); goto cleanup; } result = process_opt(client, opt); if (result != ISC_R_SUCCESS) goto cleanup; } if (client->message->rdclass == 0) { if ((client->attributes & NS_CLIENTATTR_WANTCOOKIE) != 0 || (client->message->opcode == dns_opcode_query && client->message->counts[DNS_SECTION_QUESTION] == 0U)) { result = dns_message_reply(client->message, ISC_TRUE); if (result != ISC_R_SUCCESS) { ns_client_error(client, result); return; } if (notimp) client->message->rcode = dns_rcode_notimp; ns_client_send(client); return; } ns_client_log(client, NS_LOGCATEGORY_CLIENT, NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1), "message class could not be determined"); ns_client_dumpmessage(client, "message class could not be determined"); ns_client_error(client, notimp ? DNS_R_NOTIMP : DNS_R_FORMERR); goto cleanup; } /* * Determine the destination address. If the receiving interface is * bound to a specific address, we simply use it regardless of the * address family. All IPv4 queries should fall into this case. * Otherwise, if this is a TCP query, get the address from the * receiving socket (this needs a system call and can be heavy). * For IPv6 UDP queries, we get this from the pktinfo structure (if * supported). * If all the attempts fail (this can happen due to memory shortage, * etc), we regard this as an error for safety. */ if ((client->interface->flags & NS_INTERFACEFLAG_ANYADDR) == 0) isc_netaddr_fromsockaddr(&client->destaddr, &client->interface->addr); else { isc_sockaddr_t sockaddr; result = ISC_R_FAILURE; if (TCP_CLIENT(client)) result = isc_socket_getsockname(client->tcpsocket, &sockaddr); if (result == ISC_R_SUCCESS) isc_netaddr_fromsockaddr(&client->destaddr, &sockaddr); if (result != ISC_R_SUCCESS && client->interface->addr.type.sa.sa_family == AF_INET6 && (client->attributes & NS_CLIENTATTR_PKTINFO) != 0) { /* * XXXJT technically, we should convert the receiving * interface ID to a proper scope zone ID. However, * due to the fact there is no standard API for this, * we only handle link-local addresses and use the * interface index as link ID. Despite the assumption, * it should cover most typical cases. */ isc_netaddr_fromin6(&client->destaddr, &client->pktinfo.ipi6_addr); if (IN6_IS_ADDR_LINKLOCAL(&client->pktinfo.ipi6_addr)) isc_netaddr_setzone(&client->destaddr, client->pktinfo.ipi6_ifindex); result = ISC_R_SUCCESS; } if (result != ISC_R_SUCCESS) { UNEXPECTED_ERROR(__FILE__, __LINE__, "failed to get request's " "destination: %s", isc_result_totext(result)); ns_client_next(client, ISC_R_SUCCESS); goto cleanup; } } isc_sockaddr_fromnetaddr(&client->destsockaddr, &client->destaddr, 0); /* * Find a view that matches the client's source address. */ for (view = ISC_LIST_HEAD(ns_g_server->viewlist); view != NULL; view = ISC_LIST_NEXT(view, link)) { if (client->message->rdclass == view->rdclass || client->message->rdclass == dns_rdataclass_any) { dns_name_t *tsig = NULL; isc_netaddr_t *addr = NULL; isc_uint8_t *scope = NULL; sigresult = dns_message_rechecksig(client->message, view); if (sigresult == ISC_R_SUCCESS) { dns_tsigkey_t *tsigkey; tsigkey = client->message->tsigkey; tsig = dns_tsigkey_identity(tsigkey); } if ((client->attributes & NS_CLIENTATTR_HAVEECS) != 0) { addr = &client->ecs_addr; scope = &client->ecs_scope; } if (allowed(&netaddr, tsig, addr, client->ecs_addrlen, scope, view->matchclients) && allowed(&client->destaddr, tsig, NULL, 0, NULL, view->matchdestinations) && !(view->matchrecursiveonly && (client->message->flags & DNS_MESSAGEFLAG_RD) == 0)) { dns_view_attach(view, &client->view); break; } } } if (view == NULL) { char classname[DNS_RDATACLASS_FORMATSIZE]; /* * Do a dummy TSIG verification attempt so that the * response will have a TSIG if the query did, as * required by RFC2845. */ isc_buffer_t b; isc_region_t *r; dns_message_resetsig(client->message); r = dns_message_getrawmessage(client->message); isc_buffer_init(&b, r->base, r->length); isc_buffer_add(&b, r->length); (void)dns_tsig_verify(&b, client->message, NULL, NULL); dns_rdataclass_format(client->message->rdclass, classname, sizeof(classname)); ns_client_log(client, NS_LOGCATEGORY_CLIENT, NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1), "no matching view in class '%s'", classname); ns_client_dumpmessage(client, "no matching view in class"); ns_client_error(client, notimp ? DNS_R_NOTIMP : DNS_R_REFUSED); goto cleanup; } ns_client_log(client, NS_LOGCATEGORY_CLIENT, NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(5), "using view '%s'", view->name); /* * Check for a signature. We log bad signatures regardless of * whether they ultimately cause the request to be rejected or * not. We do not log the lack of a signature unless we are * debugging. */ client->signer = NULL; dns_name_init(&client->signername, NULL); result = dns_message_signer(client->message, &client->signername); if (result != ISC_R_NOTFOUND) { signame = NULL; if (dns_message_gettsig(client->message, &signame) != NULL) { isc_stats_increment(ns_g_server->nsstats, dns_nsstatscounter_tsigin); } else { isc_stats_increment(ns_g_server->nsstats, dns_nsstatscounter_sig0in); } } if (result == ISC_R_SUCCESS) { char namebuf[DNS_NAME_FORMATSIZE]; dns_name_format(&client->signername, namebuf, sizeof(namebuf)); ns_client_log(client, DNS_LOGCATEGORY_SECURITY, NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3), "request has valid signature: %s", namebuf); client->signer = &client->signername; } else if (result == ISC_R_NOTFOUND) { ns_client_log(client, DNS_LOGCATEGORY_SECURITY, NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3), "request is not signed"); } else if (result == DNS_R_NOIDENTITY) { ns_client_log(client, DNS_LOGCATEGORY_SECURITY, NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3), "request is signed by a nonauthoritative key"); } else { char tsigrcode[64]; isc_buffer_t b; dns_rcode_t status; isc_result_t tresult; /* There is a signature, but it is bad. */ isc_stats_increment(ns_g_server->nsstats, dns_nsstatscounter_invalidsig); signame = NULL; if (dns_message_gettsig(client->message, &signame) != NULL) { char namebuf[DNS_NAME_FORMATSIZE]; char cnamebuf[DNS_NAME_FORMATSIZE]; dns_name_format(signame, namebuf, sizeof(namebuf)); status = client->message->tsigstatus; isc_buffer_init(&b, tsigrcode, sizeof(tsigrcode) - 1); tresult = dns_tsigrcode_totext(status, &b); INSIST(tresult == ISC_R_SUCCESS); tsigrcode[isc_buffer_usedlength(&b)] = '\0'; if (client->message->tsigkey->generated) { dns_name_format(client->message->tsigkey->creator, cnamebuf, sizeof(cnamebuf)); ns_client_log(client, DNS_LOGCATEGORY_SECURITY, NS_LOGMODULE_CLIENT, ISC_LOG_ERROR, "request has invalid signature: " "TSIG %s (%s): %s (%s)", namebuf, cnamebuf, isc_result_totext(result), tsigrcode); } else { ns_client_log(client, DNS_LOGCATEGORY_SECURITY, NS_LOGMODULE_CLIENT, ISC_LOG_ERROR, "request has invalid signature: " "TSIG %s: %s (%s)", namebuf, isc_result_totext(result), tsigrcode); } } else { status = client->message->sig0status; isc_buffer_init(&b, tsigrcode, sizeof(tsigrcode) - 1); tresult = dns_tsigrcode_totext(status, &b); INSIST(tresult == ISC_R_SUCCESS); tsigrcode[isc_buffer_usedlength(&b)] = '\0'; ns_client_log(client, DNS_LOGCATEGORY_SECURITY, NS_LOGMODULE_CLIENT, ISC_LOG_ERROR, "request has invalid signature: %s (%s)", isc_result_totext(result), tsigrcode); } /* * Accept update messages signed by unknown keys so that * update forwarding works transparently through slaves * that don't have all the same keys as the master. */ if (!(client->message->tsigstatus == dns_tsigerror_badkey && client->message->opcode == dns_opcode_update)) { ns_client_error(client, sigresult); goto cleanup; } } /* * Decide whether recursive service is available to this client. * We do this here rather than in the query code so that we can * set the RA bit correctly on all kinds of responses, not just * responses to ordinary queries. Note if you can't query the * cache there is no point in setting RA. */ ra = ISC_FALSE; if (client->view->resolver != NULL && client->view->recursion == ISC_TRUE && ns_client_checkaclsilent(client, NULL, client->view->recursionacl, ISC_TRUE) == ISC_R_SUCCESS && ns_client_checkaclsilent(client, NULL, client->view->cacheacl, ISC_TRUE) == ISC_R_SUCCESS && ns_client_checkaclsilent(client, &client->destaddr, client->view->recursiononacl, ISC_TRUE) == ISC_R_SUCCESS && ns_client_checkaclsilent(client, &client->destaddr, client->view->cacheonacl, ISC_TRUE) == ISC_R_SUCCESS) ra = ISC_TRUE; if (ra == ISC_TRUE) client->attributes |= NS_CLIENTATTR_RA; ns_client_log(client, DNS_LOGCATEGORY_SECURITY, NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3), ra ? "recursion available" : "recursion not available"); /* * Adjust maximum UDP response size for this client. */ if (client->udpsize > 512) { dns_peer_t *peer = NULL; isc_uint16_t udpsize = view->maxudp; (void) dns_peerlist_peerbyaddr(view->peers, &netaddr, &peer); if (peer != NULL) dns_peer_getmaxudp(peer, &udpsize); if (client->udpsize > udpsize) client->udpsize = udpsize; } /* * Dispatch the request. */ switch (client->message->opcode) { case dns_opcode_query: CTRACE("query"); #ifdef HAVE_DNSTAP if ((client->message->flags & DNS_MESSAGEFLAG_RD) != 0) dtmsgtype = DNS_DTTYPE_CQ; else dtmsgtype = DNS_DTTYPE_AQ; dns_dt_send(view, dtmsgtype, &client->peeraddr, &client->interface->addr, TCP_CLIENT(client), NULL, &client->requesttime, NULL, buffer); #endif /* HAVE_DNSTAP */ ns_query_start(client); break; case dns_opcode_update: CTRACE("update"); ns_client_settimeout(client, 60); ns_update_start(client, sigresult); break; case dns_opcode_notify: CTRACE("notify"); ns_client_settimeout(client, 60); ns_notify_start(client); break; case dns_opcode_iquery: CTRACE("iquery"); ns_client_error(client, DNS_R_NOTIMP); break; default: CTRACE("unknown opcode"); ns_client_error(client, DNS_R_NOTIMP); } cleanup: return; } static void client_timeout(isc_task_t *task, isc_event_t *event) { ns_client_t *client; REQUIRE(event != NULL); REQUIRE(event->ev_type == ISC_TIMEREVENT_LIFE || event->ev_type == ISC_TIMEREVENT_IDLE); client = event->ev_arg; REQUIRE(NS_CLIENT_VALID(client)); REQUIRE(task == client->task); REQUIRE(client->timer != NULL); UNUSED(task); CTRACE("timeout"); isc_event_free(&event); if (client->shutdown != NULL) { (client->shutdown)(client->shutdown_arg, ISC_R_TIMEDOUT); client->shutdown = NULL; client->shutdown_arg = NULL; } if (client->newstate > NS_CLIENTSTATE_READY) client->newstate = NS_CLIENTSTATE_READY; (void)exit_check(client); } static isc_result_t get_clientmctx(ns_clientmgr_t *manager, isc_mem_t **mctxp) { isc_mem_t *clientmctx; isc_result_t result; #if NMCTXS > 0 unsigned int nextmctx; #endif MTRACE("clientmctx"); /* * Caller must be holding the manager lock. */ if (ns_g_clienttest) { result = isc_mem_create(0, 0, mctxp); if (result == ISC_R_SUCCESS) isc_mem_setname(*mctxp, "client", NULL); return (result); } #if NMCTXS > 0 nextmctx = manager->nextmctx++; if (manager->nextmctx == NMCTXS) manager->nextmctx = 0; INSIST(nextmctx < NMCTXS); clientmctx = manager->mctxpool[nextmctx]; if (clientmctx == NULL) { result = isc_mem_create(0, 0, &clientmctx); if (result != ISC_R_SUCCESS) return (result); isc_mem_setname(clientmctx, "client", NULL); manager->mctxpool[nextmctx] = clientmctx; } #else clientmctx = manager->mctx; #endif isc_mem_attach(clientmctx, mctxp); return (ISC_R_SUCCESS); } static isc_result_t client_create(ns_clientmgr_t *manager, ns_client_t **clientp) { ns_client_t *client; isc_result_t result; isc_mem_t *mctx = NULL; /* * Caller must be holding the manager lock. * * Note: creating a client does not add the client to the * manager's client list or set the client's manager pointer. * The caller is responsible for that. */ REQUIRE(clientp != NULL && *clientp == NULL); result = get_clientmctx(manager, &mctx); if (result != ISC_R_SUCCESS) return (result); client = isc_mem_get(mctx, sizeof(*client)); if (client == NULL) { isc_mem_detach(&mctx); return (ISC_R_NOMEMORY); } client->mctx = mctx; client->task = NULL; result = isc_task_create(manager->taskmgr, 0, &client->task); if (result != ISC_R_SUCCESS) goto cleanup_client; isc_task_setname(client->task, "client", client); client->timer = NULL; result = isc_timer_create(manager->timermgr, isc_timertype_inactive, NULL, NULL, client->task, client_timeout, client, &client->timer); if (result != ISC_R_SUCCESS) goto cleanup_task; client->timerset = ISC_FALSE; client->delaytimer = NULL; client->message = NULL; result = dns_message_create(client->mctx, DNS_MESSAGE_INTENTPARSE, &client->message); if (result != ISC_R_SUCCESS) goto cleanup_timer; /* XXXRTH Hardwired constants */ client->sendevent = isc_socket_socketevent(client->mctx, client, ISC_SOCKEVENT_SENDDONE, client_senddone, client); if (client->sendevent == NULL) { result = ISC_R_NOMEMORY; goto cleanup_message; } client->recvbuf = isc_mem_get(client->mctx, RECV_BUFFER_SIZE); if (client->recvbuf == NULL) { result = ISC_R_NOMEMORY; goto cleanup_sendevent; } client->recvevent = isc_socket_socketevent(client->mctx, client, ISC_SOCKEVENT_RECVDONE, client_request, client); if (client->recvevent == NULL) { result = ISC_R_NOMEMORY; goto cleanup_recvbuf; } client->magic = NS_CLIENT_MAGIC; client->manager = NULL; client->state = NS_CLIENTSTATE_INACTIVE; client->newstate = NS_CLIENTSTATE_MAX; client->naccepts = 0; client->nreads = 0; client->nsends = 0; client->nrecvs = 0; client->nupdates = 0; client->nctls = 0; client->references = 0; client->attributes = 0; client->view = NULL; client->dispatch = NULL; client->udpsocket = NULL; client->tcplistener = NULL; client->tcpsocket = NULL; client->tcpmsg_valid = ISC_FALSE; client->tcpbuf = NULL; client->opt = NULL; client->udpsize = 512; client->dscp = -1; client->extflags = 0; client->ednsversion = -1; client->next = NULL; client->shutdown = NULL; client->shutdown_arg = NULL; client->signer = NULL; dns_name_init(&client->signername, NULL); client->mortal = ISC_FALSE; client->pipelined = ISC_FALSE; client->tcpquota = NULL; client->recursionquota = NULL; client->interface = NULL; client->peeraddr_valid = ISC_FALSE; client->ecs_addrlen = 0; client->ecs_scope = 0; #ifdef ALLOW_FILTER_AAAA client->filter_aaaa = dns_aaaa_ok; #endif client->needshutdown = ns_g_clienttest; ISC_EVENT_INIT(&client->ctlevent, sizeof(client->ctlevent), 0, NULL, NS_EVENT_CLIENTCONTROL, client_start, client, client, NULL, NULL); /* * Initialize FORMERR cache to sentinel value that will not match * any actual FORMERR response. */ isc_sockaddr_any(&client->formerrcache.addr); client->formerrcache.time = 0; client->formerrcache.id = 0; ISC_LINK_INIT(client, link); ISC_LINK_INIT(client, rlink); ISC_QLINK_INIT(client, ilink); client->keytag = NULL; client->keytag_len = 0; /* * We call the init routines for the various kinds of client here, * after we have created an otherwise valid client, because some * of them call routines that REQUIRE(NS_CLIENT_VALID(client)). */ result = ns_query_init(client); if (result != ISC_R_SUCCESS) goto cleanup_recvevent; result = isc_task_onshutdown(client->task, client_shutdown, client); if (result != ISC_R_SUCCESS) goto cleanup_query; CTRACE("create"); *clientp = client; return (ISC_R_SUCCESS); cleanup_query: ns_query_free(client); cleanup_recvevent: isc_event_free((isc_event_t **)&client->recvevent); cleanup_recvbuf: isc_mem_put(client->mctx, client->recvbuf, RECV_BUFFER_SIZE); cleanup_sendevent: isc_event_free((isc_event_t **)&client->sendevent); client->magic = 0; cleanup_message: dns_message_destroy(&client->message); cleanup_timer: isc_timer_detach(&client->timer); cleanup_task: isc_task_detach(&client->task); cleanup_client: isc_mem_putanddetach(&client->mctx, client, sizeof(*client)); return (result); } static void client_read(ns_client_t *client) { isc_result_t result; CTRACE("read"); result = dns_tcpmsg_readmessage(&client->tcpmsg, client->task, client_request, client); if (result != ISC_R_SUCCESS) goto fail; /* * Set a timeout to limit the amount of time we will wait * for a request on this TCP connection. */ ns_client_settimeout(client, 30); client->state = client->newstate = NS_CLIENTSTATE_READING; INSIST(client->nreads == 0); INSIST(client->recursionquota == NULL); client->nreads++; return; fail: ns_client_next(client, result); } static void client_newconn(isc_task_t *task, isc_event_t *event) { ns_client_t *client = event->ev_arg; isc_socket_newconnev_t *nevent = (isc_socket_newconnev_t *)event; isc_result_t result; REQUIRE(event->ev_type == ISC_SOCKEVENT_NEWCONN); REQUIRE(NS_CLIENT_VALID(client)); REQUIRE(client->task == task); UNUSED(task); INSIST(client->state == NS_CLIENTSTATE_READY); INSIST(client->naccepts == 1); client->naccepts--; LOCK(&client->interface->lock); INSIST(client->interface->ntcpcurrent > 0); client->interface->ntcpcurrent--; UNLOCK(&client->interface->lock); /* * We must take ownership of the new socket before the exit * check to make sure it gets destroyed if we decide to exit. */ if (nevent->result == ISC_R_SUCCESS) { client->tcpsocket = nevent->newsocket; isc_socket_setname(client->tcpsocket, "client-tcp", NULL); client->state = NS_CLIENTSTATE_READING; INSIST(client->recursionquota == NULL); (void)isc_socket_getpeername(client->tcpsocket, &client->peeraddr); client->peeraddr_valid = ISC_TRUE; ns_client_log(client, NS_LOGCATEGORY_CLIENT, NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3), "new TCP connection"); } else { /* * XXXRTH What should we do? We're trying to accept but * it didn't work. If we just give up, then TCP * service may eventually stop. * * For now, we just go idle. * * Going idle is probably the right thing if the * I/O was canceled. */ ns_client_log(client, NS_LOGCATEGORY_CLIENT, NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3), "accept failed: %s", isc_result_totext(nevent->result)); } if (exit_check(client)) goto freeevent; if (nevent->result == ISC_R_SUCCESS) { int match; isc_netaddr_t netaddr; isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr); if (ns_g_server->blackholeacl != NULL && dns_acl_match(&netaddr, NULL, ns_g_server->blackholeacl, &ns_g_server->aclenv, &match, NULL) == ISC_R_SUCCESS && match > 0) { ns_client_log(client, DNS_LOGCATEGORY_SECURITY, NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10), "blackholed connection attempt"); client->newstate = NS_CLIENTSTATE_READY; (void)exit_check(client); goto freeevent; } INSIST(client->tcpmsg_valid == ISC_FALSE); dns_tcpmsg_init(client->mctx, client->tcpsocket, &client->tcpmsg); client->tcpmsg_valid = ISC_TRUE; /* * Let a new client take our place immediately, before * we wait for a request packet. If we don't, * telnetting to port 53 (once per CPU) will * deny service to legitimate TCP clients. */ client->pipelined = ISC_FALSE; result = isc_quota_attach(&ns_g_server->tcpquota, &client->tcpquota); if (result == ISC_R_SUCCESS) result = ns_client_replace(client); if (result != ISC_R_SUCCESS) { ns_client_log(client, NS_LOGCATEGORY_CLIENT, NS_LOGMODULE_CLIENT, ISC_LOG_WARNING, "no more TCP clients(accept): %s", isc_result_totext(result)); } else if (ns_g_server->keepresporder == NULL || !allowed(&netaddr, NULL, NULL, 0, NULL, ns_g_server->keepresporder)) { client->pipelined = ISC_TRUE; } client_read(client); } freeevent: isc_event_free(&event); } static void client_accept(ns_client_t *client) { isc_result_t result; CTRACE("accept"); result = isc_socket_accept(client->tcplistener, client->task, client_newconn, client); if (result != ISC_R_SUCCESS) { UNEXPECTED_ERROR(__FILE__, __LINE__, "isc_socket_accept() failed: %s", isc_result_totext(result)); /* * XXXRTH What should we do? We're trying to accept but * it didn't work. If we just give up, then TCP * service may eventually stop. * * For now, we just go idle. */ return; } INSIST(client->naccepts == 0); client->naccepts++; LOCK(&client->interface->lock); client->interface->ntcpcurrent++; UNLOCK(&client->interface->lock); } static void client_udprecv(ns_client_t *client) { isc_result_t result; isc_region_t r; CTRACE("udprecv"); r.base = client->recvbuf; r.length = RECV_BUFFER_SIZE; result = isc_socket_recv2(client->udpsocket, &r, 1, client->task, client->recvevent, 0); if (result != ISC_R_SUCCESS) { UNEXPECTED_ERROR(__FILE__, __LINE__, "isc_socket_recv2() failed: %s", isc_result_totext(result)); /* * This cannot happen in the current implementation, since * isc_socket_recv2() cannot fail if flags == 0. * * If this does fail, we just go idle. */ return; } INSIST(client->nrecvs == 0); client->nrecvs++; } void ns_client_attach(ns_client_t *source, ns_client_t **targetp) { REQUIRE(NS_CLIENT_VALID(source)); REQUIRE(targetp != NULL && *targetp == NULL); source->references++; ns_client_log(source, NS_LOGCATEGORY_CLIENT, NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10), "ns_client_attach: ref = %d", source->references); *targetp = source; } void ns_client_detach(ns_client_t **clientp) { ns_client_t *client = *clientp; client->references--; INSIST(client->references >= 0); *clientp = NULL; ns_client_log(client, NS_LOGCATEGORY_CLIENT, NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10), "ns_client_detach: ref = %d", client->references); (void)exit_check(client); } isc_boolean_t ns_client_shuttingdown(ns_client_t *client) { return (ISC_TF(client->newstate == NS_CLIENTSTATE_FREED)); } isc_result_t ns_client_replace(ns_client_t *client) { isc_result_t result; isc_boolean_t tcp; CTRACE("replace"); REQUIRE(client != NULL); REQUIRE(client->manager != NULL); tcp = TCP_CLIENT(client); if (tcp && client->pipelined) { result = get_worker(client->manager, client->interface, client->tcpsocket); } else { result = get_client(client->manager, client->interface, client->dispatch, tcp); } if (result != ISC_R_SUCCESS) return (result); /* * The responsibility for listening for new requests is hereby * transferred to the new client. Therefore, the old client * should refrain from listening for any more requests. */ client->mortal = ISC_TRUE; return (ISC_R_SUCCESS); } /*** *** Client Manager ***/ static void clientmgr_destroy(ns_clientmgr_t *manager) { #if NMCTXS > 0 int i; #endif REQUIRE(ISC_LIST_EMPTY(manager->clients)); MTRACE("clientmgr_destroy"); #if NMCTXS > 0 for (i = 0; i < NMCTXS; i++) { if (manager->mctxpool[i] != NULL) isc_mem_detach(&manager->mctxpool[i]); } #endif ISC_QUEUE_DESTROY(manager->inactive); DESTROYLOCK(&manager->lock); DESTROYLOCK(&manager->listlock); DESTROYLOCK(&manager->reclock); manager->magic = 0; isc_mem_put(manager->mctx, manager, sizeof(*manager)); } isc_result_t ns_clientmgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr, isc_timermgr_t *timermgr, ns_clientmgr_t **managerp) { ns_clientmgr_t *manager; isc_result_t result; #if NMCTXS > 0 int i; #endif manager = isc_mem_get(mctx, sizeof(*manager)); if (manager == NULL) return (ISC_R_NOMEMORY); result = isc_mutex_init(&manager->lock); if (result != ISC_R_SUCCESS) goto cleanup_manager; result = isc_mutex_init(&manager->listlock); if (result != ISC_R_SUCCESS) goto cleanup_lock; result = isc_mutex_init(&manager->reclock); if (result != ISC_R_SUCCESS) goto cleanup_listlock; manager->mctx = mctx; manager->taskmgr = taskmgr; manager->timermgr = timermgr; manager->exiting = ISC_FALSE; ISC_LIST_INIT(manager->clients); ISC_LIST_INIT(manager->recursing); ISC_QUEUE_INIT(manager->inactive, ilink); #if NMCTXS > 0 manager->nextmctx = 0; for (i = 0; i < NMCTXS; i++) manager->mctxpool[i] = NULL; /* will be created on-demand */ #endif manager->magic = MANAGER_MAGIC; MTRACE("create"); *managerp = manager; return (ISC_R_SUCCESS); cleanup_listlock: (void) isc_mutex_destroy(&manager->listlock); cleanup_lock: (void) isc_mutex_destroy(&manager->lock); cleanup_manager: isc_mem_put(manager->mctx, manager, sizeof(*manager)); return (result); } void ns_clientmgr_destroy(ns_clientmgr_t **managerp) { isc_result_t result; ns_clientmgr_t *manager; ns_client_t *client; isc_boolean_t need_destroy = ISC_FALSE, unlock = ISC_FALSE; REQUIRE(managerp != NULL); manager = *managerp; REQUIRE(VALID_MANAGER(manager)); MTRACE("destroy"); /* * Check for success because we may already be task-exclusive * at this point. Only if we succeed at obtaining an exclusive * lock now will we need to relinquish it later. */ result = isc_task_beginexclusive(ns_g_server->task); if (result == ISC_R_SUCCESS) unlock = ISC_TRUE; manager->exiting = ISC_TRUE; for (client = ISC_LIST_HEAD(manager->clients); client != NULL; client = ISC_LIST_NEXT(client, link)) isc_task_shutdown(client->task); if (ISC_LIST_EMPTY(manager->clients)) need_destroy = ISC_TRUE; if (unlock) isc_task_endexclusive(ns_g_server->task); if (need_destroy) clientmgr_destroy(manager); *managerp = NULL; } static isc_result_t get_client(ns_clientmgr_t *manager, ns_interface_t *ifp, dns_dispatch_t *disp, isc_boolean_t tcp) { isc_result_t result = ISC_R_SUCCESS; isc_event_t *ev; ns_client_t *client; MTRACE("get client"); REQUIRE(manager != NULL); if (manager->exiting) return (ISC_R_SHUTTINGDOWN); /* * Allocate a client. First try to get a recycled one; * if that fails, make a new one. */ client = NULL; if (!ns_g_clienttest) ISC_QUEUE_POP(manager->inactive, ilink, client); if (client != NULL) MTRACE("recycle"); else { MTRACE("create new"); LOCK(&manager->lock); result = client_create(manager, &client); UNLOCK(&manager->lock); if (result != ISC_R_SUCCESS) return (result); LOCK(&manager->listlock); ISC_LIST_APPEND(manager->clients, client, link); UNLOCK(&manager->listlock); } client->manager = manager; ns_interface_attach(ifp, &client->interface); client->state = NS_CLIENTSTATE_READY; INSIST(client->recursionquota == NULL); client->dscp = ifp->dscp; if (tcp) { client->attributes |= NS_CLIENTATTR_TCP; isc_socket_attach(ifp->tcpsocket, &client->tcplistener); } else { isc_socket_t *sock; dns_dispatch_attach(disp, &client->dispatch); sock = dns_dispatch_getsocket(client->dispatch); isc_socket_attach(sock, &client->udpsocket); } INSIST(client->nctls == 0); client->nctls++; ev = &client->ctlevent; isc_task_send(client->task, &ev); return (ISC_R_SUCCESS); } static isc_result_t get_worker(ns_clientmgr_t *manager, ns_interface_t *ifp, isc_socket_t *sock) { isc_result_t result = ISC_R_SUCCESS; isc_event_t *ev; ns_client_t *client; MTRACE("get worker"); REQUIRE(manager != NULL); if (manager->exiting) return (ISC_R_SHUTTINGDOWN); /* * Allocate a client. First try to get a recycled one; * if that fails, make a new one. */ client = NULL; if (!ns_g_clienttest) ISC_QUEUE_POP(manager->inactive, ilink, client); if (client != NULL) MTRACE("recycle"); else { MTRACE("create new"); LOCK(&manager->lock); result = client_create(manager, &client); UNLOCK(&manager->lock); if (result != ISC_R_SUCCESS) return (result); LOCK(&manager->listlock); ISC_LIST_APPEND(manager->clients, client, link); UNLOCK(&manager->listlock); } client->manager = manager; ns_interface_attach(ifp, &client->interface); client->newstate = client->state = NS_CLIENTSTATE_WORKING; INSIST(client->recursionquota == NULL); client->tcpquota = &ns_g_server->tcpquota; client->dscp = ifp->dscp; client->attributes |= NS_CLIENTATTR_TCP; client->pipelined = ISC_TRUE; client->mortal = ISC_TRUE; isc_socket_attach(ifp->tcpsocket, &client->tcplistener); isc_socket_attach(sock, &client->tcpsocket); isc_socket_setname(client->tcpsocket, "worker-tcp", NULL); (void)isc_socket_getpeername(client->tcpsocket, &client->peeraddr); client->peeraddr_valid = ISC_TRUE; INSIST(client->tcpmsg_valid == ISC_FALSE); dns_tcpmsg_init(client->mctx, client->tcpsocket, &client->tcpmsg); client->tcpmsg_valid = ISC_TRUE; INSIST(client->nctls == 0); client->nctls++; ev = &client->ctlevent; isc_task_send(client->task, &ev); return (ISC_R_SUCCESS); } isc_result_t ns_clientmgr_createclients(ns_clientmgr_t *manager, unsigned int n, ns_interface_t *ifp, isc_boolean_t tcp) { isc_result_t result = ISC_R_SUCCESS; unsigned int disp; REQUIRE(VALID_MANAGER(manager)); REQUIRE(n > 0); MTRACE("createclients"); for (disp = 0; disp < n; disp++) { result = get_client(manager, ifp, ifp->udpdispatch[disp], tcp); if (result != ISC_R_SUCCESS) break; } return (result); } isc_sockaddr_t * ns_client_getsockaddr(ns_client_t *client) { return (&client->peeraddr); } isc_sockaddr_t * ns_client_getdestaddr(ns_client_t *client) { return (&client->destsockaddr); } isc_result_t ns_client_checkaclsilent(ns_client_t *client, isc_netaddr_t *netaddr, dns_acl_t *acl, isc_boolean_t default_allow) { isc_result_t result; isc_netaddr_t tmpnetaddr; isc_netaddr_t *ecs_addr = NULL; isc_uint8_t ecs_addrlen = 0; int match; if (acl == NULL) { if (default_allow) goto allow; else goto deny; } if (netaddr == NULL) { isc_netaddr_fromsockaddr(&tmpnetaddr, &client->peeraddr); netaddr = &tmpnetaddr; } if ((client->attributes & NS_CLIENTATTR_HAVEECS) != 0) { ecs_addr = &client->ecs_addr; ecs_addrlen = client->ecs_addrlen; } result = dns_acl_match2(netaddr, client->signer, ecs_addr, ecs_addrlen, NULL, acl, &ns_g_server->aclenv, &match, NULL); if (result != ISC_R_SUCCESS) goto deny; /* Internal error, already logged. */ if (match > 0) goto allow; goto deny; /* Negative match or no match. */ allow: return (ISC_R_SUCCESS); deny: return (DNS_R_REFUSED); } isc_result_t ns_client_checkacl(ns_client_t *client, isc_sockaddr_t *sockaddr, const char *opname, dns_acl_t *acl, isc_boolean_t default_allow, int log_level) { isc_result_t result; isc_netaddr_t netaddr; if (sockaddr != NULL) isc_netaddr_fromsockaddr(&netaddr, sockaddr); result = ns_client_checkaclsilent(client, sockaddr ? &netaddr : NULL, acl, default_allow); if (result == ISC_R_SUCCESS) ns_client_log(client, DNS_LOGCATEGORY_SECURITY, NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3), "%s approved", opname); else ns_client_log(client, DNS_LOGCATEGORY_SECURITY, NS_LOGMODULE_CLIENT, log_level, "%s denied", opname); return (result); } static void ns_client_name(ns_client_t *client, char *peerbuf, size_t len) { if (client->peeraddr_valid) isc_sockaddr_format(&client->peeraddr, peerbuf, (unsigned int)len); else snprintf(peerbuf, len, "@%p", client); } void ns_client_logv(ns_client_t *client, isc_logcategory_t *category, isc_logmodule_t *module, int level, const char *fmt, va_list ap) { char msgbuf[4096]; char signerbuf[DNS_NAME_FORMATSIZE], qnamebuf[DNS_NAME_FORMATSIZE]; char peerbuf[ISC_SOCKADDR_FORMATSIZE]; const char *viewname = ""; const char *sep1 = "", *sep2 = "", *sep3 = "", *sep4 = ""; const char *signer = "", *qname = ""; dns_name_t *q = NULL; vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap); if (client->signer != NULL) { dns_name_format(client->signer, signerbuf, sizeof(signerbuf)); sep1 = "/key "; signer = signerbuf; } q = client->query.origqname != NULL ? client->query.origqname : client->query.qname; if (q != NULL) { dns_name_format(q, qnamebuf, sizeof(qnamebuf)); sep2 = " ("; sep3 = ")"; qname = qnamebuf; } if (client->view != NULL && strcmp(client->view->name, "_bind") != 0 && strcmp(client->view->name, "_default") != 0) { sep4 = ": view "; viewname = client->view->name; } if (client->peeraddr_valid) { isc_sockaddr_format(&client->peeraddr, peerbuf, sizeof(peerbuf)); } else { snprintf(peerbuf, sizeof(peerbuf), "(no-peer)"); } isc_log_write(ns_g_lctx, category, module, level, "client @%p %s%s%s%s%s%s%s%s: %s", client, peerbuf, sep1, signer, sep2, qname, sep3, sep4, viewname, msgbuf); } void ns_client_log(ns_client_t *client, isc_logcategory_t *category, isc_logmodule_t *module, int level, const char *fmt, ...) { va_list ap; if (! isc_log_wouldlog(ns_g_lctx, level)) return; va_start(ap, fmt); ns_client_logv(client, category, module, level, fmt, ap); va_end(ap); } void ns_client_aclmsg(const char *msg, dns_name_t *name, dns_rdatatype_t type, dns_rdataclass_t rdclass, char *buf, size_t len) { char namebuf[DNS_NAME_FORMATSIZE]; char typebuf[DNS_RDATATYPE_FORMATSIZE]; char classbuf[DNS_RDATACLASS_FORMATSIZE]; dns_name_format(name, namebuf, sizeof(namebuf)); dns_rdatatype_format(type, typebuf, sizeof(typebuf)); dns_rdataclass_format(rdclass, classbuf, sizeof(classbuf)); (void)snprintf(buf, len, "%s '%s/%s/%s'", msg, namebuf, typebuf, classbuf); } static void ns_client_dumpmessage(ns_client_t *client, const char *reason) { isc_buffer_t buffer; char *buf = NULL; int len = 1024; isc_result_t result; if (!isc_log_wouldlog(ns_g_lctx, ISC_LOG_DEBUG(1))) return; /* * Note that these are multiline debug messages. We want a newline * to appear in the log after each message. */ do { buf = isc_mem_get(client->mctx, len); if (buf == NULL) break; isc_buffer_init(&buffer, buf, len); result = dns_message_totext(client->message, &dns_master_style_debug, 0, &buffer); if (result == ISC_R_NOSPACE) { isc_mem_put(client->mctx, buf, len); len += 1024; } else if (result == ISC_R_SUCCESS) ns_client_log(client, NS_LOGCATEGORY_UNMATCHED, NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1), "%s\n%.*s", reason, (int)isc_buffer_usedlength(&buffer), buf); } while (result == ISC_R_NOSPACE); if (buf != NULL) isc_mem_put(client->mctx, buf, len); } void ns_client_dumprecursing(FILE *f, ns_clientmgr_t *manager) { ns_client_t *client; char namebuf[DNS_NAME_FORMATSIZE]; char original[DNS_NAME_FORMATSIZE]; char peerbuf[ISC_SOCKADDR_FORMATSIZE]; char typebuf[DNS_RDATATYPE_FORMATSIZE]; char classbuf[DNS_RDATACLASS_FORMATSIZE]; const char *name; const char *sep; const char *origfor; dns_rdataset_t *rdataset; REQUIRE(VALID_MANAGER(manager)); LOCK(&manager->reclock); client = ISC_LIST_HEAD(manager->recursing); while (client != NULL) { INSIST(client->state == NS_CLIENTSTATE_RECURSING); ns_client_name(client, peerbuf, sizeof(peerbuf)); if (client->view != NULL && strcmp(client->view->name, "_bind") != 0 && strcmp(client->view->name, "_default") != 0) { name = client->view->name; sep = ": view "; } else { name = ""; sep = ""; } LOCK(&client->query.fetchlock); INSIST(client->query.qname != NULL); dns_name_format(client->query.qname, namebuf, sizeof(namebuf)); if (client->query.qname != client->query.origqname && client->query.origqname != NULL) { origfor = " for "; dns_name_format(client->query.origqname, original, sizeof(original)); } else { origfor = ""; original[0] = '\0'; } rdataset = ISC_LIST_HEAD(client->query.qname->list); if (rdataset == NULL && client->query.origqname != NULL) rdataset = ISC_LIST_HEAD(client->query.origqname->list); if (rdataset != NULL) { dns_rdatatype_format(rdataset->type, typebuf, sizeof(typebuf)); dns_rdataclass_format(rdataset->rdclass, classbuf, sizeof(classbuf)); } else { strlcpy(typebuf, "-", sizeof(typebuf)); strlcpy(classbuf, "-", sizeof(classbuf)); } UNLOCK(&client->query.fetchlock); fprintf(f, "; client %s%s%s: id %u '%s/%s/%s'%s%s " "requesttime %d\n", peerbuf, sep, name, client->message->id, namebuf, typebuf, classbuf, origfor, original, isc_time_seconds(&client->requesttime)); client = ISC_LIST_NEXT(client, rlink); } UNLOCK(&manager->reclock); } void ns_client_qnamereplace(ns_client_t *client, dns_name_t *name) { LOCK(&client->query.fetchlock); if (client->query.restarts > 0) { /* * client->query.qname was dynamically allocated. */ dns_message_puttempname(client->message, &client->query.qname); } client->query.qname = name; client->query.attributes &= ~NS_QUERYATTR_REDIRECT; UNLOCK(&client->query.fetchlock); } isc_result_t ns_client_sourceip(dns_clientinfo_t *ci, isc_sockaddr_t **addrp) { ns_client_t *client = (ns_client_t *) ci->data; REQUIRE(NS_CLIENT_VALID(client)); REQUIRE(addrp != NULL); *addrp = &client->peeraddr; return (ISC_R_SUCCESS); } bind9-9.11.3+dfsg/bin/named/config.c000066400000000000000000000616711325250447100170140ustar00rootroot00000000000000/* * Copyright (C) 2001-2017 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /*! \file */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /*% default configuration */ static char defaultconf[] = "\ options {\n\ automatic-interface-scan yes;\n\ bindkeys-file \"" NS_SYSCONFDIR "/bind.keys\";\n\ # blackhole {none;};\n" #if defined(HAVE_OPENSSL_AES) || defined(HAVE_OPENSSL_EVP_AES) " cookie-algorithm aes;\n" #else " cookie-algorithm sha256;\n" #endif #ifndef WIN32 " coresize default;\n\ datasize default;\n" #endif "\ # deallocate-on-exit ;\n\ # directory \n\ dump-file \"named_dump.db\";\n\ edns-udp-size 4096;\n\ # fake-iquery ;\n" #ifndef WIN32 " files unlimited;\n" #endif "\ # has-old-clients ;\n\ heartbeat-interval 60;\n\ # host-statistics ;\n\ interface-interval 60;\n\ # keep-response-order {none;};\n\ listen-on {any;};\n\ listen-on-v6 {any;};\n\ # lock-file \"" NS_LOCALSTATEDIR "/run/named/named.lock\";\n\ match-mapped-addresses no;\n\ max-rsa-exponent-size 0; /* no limit */\n\ max-udp-size 4096;\n\ memstatistics-file \"named.memstats\";\n\ # multiple-cnames ;\n\ # named-xfer ;\n\ nocookie-udp-size 4096;\n\ notify-rate 20;\n\ nta-lifetime 3600;\n\ nta-recheck 300;\n\ # pid-file \"" NS_LOCALSTATEDIR "/run/named/named.pid\"; /* or /lwresd.pid */\n\ port 53;\n\ prefetch 2 9;\n" #ifdef PATH_RANDOMDEV " random-device \"" PATH_RANDOMDEV "\";\n" #endif " recursing-file \"named.recursing\";\n\ recursive-clients 1000;\n\ request-nsid false;\n\ reserved-sockets 512;\n\ resolver-query-timeout 10;\n\ rrset-order { order random; };\n\ secroots-file \"named.secroots\";\n\ send-cookie true;\n\ # serial-queries ;\n\ serial-query-rate 20;\n\ server-id none;\n\ session-keyalg hmac-sha256;\n\ # session-keyfile \"" NS_LOCALSTATEDIR "/run/named/session.key\";\n\ session-keyname local-ddns;\n" #ifndef WIN32 " stacksize default;\n" #endif " startup-notify-rate 20;\n\ statistics-file \"named.stats\";\n\ # statistics-interval ;\n\ tcp-clients 150;\n\ tcp-listen-queue 10;\n\ # tkey-dhkey \n\ # tkey-domain \n\ # tkey-gssapi-credential \n\ transfer-message-size 20480;\n\ transfers-in 10;\n\ transfers-out 10;\n\ transfers-per-ns 2;\n\ # treat-cr-as-space ;\n\ trust-anchor-telemetry yes;\n\ # use-id-pool ;\n\ # use-ixfr ;\n\ \n\ /* view */\n\ acache-cleaning-interval 60;\n\ acache-enable no;\n\ additional-from-auth true;\n\ additional-from-cache true;\n\ allow-new-zones no;\n\ allow-notify {none;};\n\ allow-query-cache { localnets; localhost; };\n\ allow-query-cache-on { any; };\n\ allow-recursion { localnets; localhost; };\n\ allow-recursion-on { any; };\n\ allow-update-forwarding {none;};\n\ # allow-v6-synthesis ;\n\ auth-nxdomain false;\n\ check-dup-records warn;\n\ check-mx warn;\n\ check-names master fail;\n\ check-names response ignore;\n\ check-names slave warn;\n\ check-spf warn;\n\ cleaning-interval 0; /* now meaningless */\n\ clients-per-query 10;\n\ dnssec-accept-expired no;\n\ dnssec-enable yes;\n\ dnssec-validation yes; \n" #ifdef HAVE_DNSTAP " dnstap-identity hostname;\n" #endif "\ # fetch-glue ;\n\ fetch-quota-params 100 0.1 0.3 0.7;\n\ fetches-per-server 0;\n\ fetches-per-zone 0;\n" #ifdef ALLOW_FILTER_AAAA " filter-aaaa-on-v4 no;\n\ filter-aaaa-on-v6 no;\n\ filter-aaaa { any; };\n" #endif #ifdef HAVE_GEOIP " geoip-use-ecs yes;\n" #endif " lame-ttl 600;\n" #ifdef HAVE_LMDB " lmdb-mapsize 32M;\n" #endif " max-acache-size 16M;\n\ max-cache-size 90%;\n\ max-cache-ttl 604800; /* 1 week */\n\ max-clients-per-query 100;\n\ max-ncache-ttl 10800; /* 3 hours */\n\ max-recursion-depth 7;\n\ max-recursion-queries 75;\n\ message-compression yes;\n\ # min-roots ;\n\ minimal-any false;\n\ minimal-responses false;\n\ notify-source *;\n\ notify-source-v6 *;\n\ nsec3-test-zone no;\n\ provide-ixfr true;\n\ query-source address *;\n\ query-source-v6 address *;\n\ recursion true;\n\ request-expire true;\n\ request-ixfr true;\n\ require-server-cookie no;\n\ # rfc2308-type1 ;\n\ servfail-ttl 1;\n\ # sortlist \n\ # topology \n\ transfer-format many-answers;\n\ v6-bias 50;\n\ zero-no-soa-ttl-cache no;\n\ \n\ /* zone */\n\ allow-query {any;};\n\ allow-query-on {any;};\n\ allow-transfer {any;};\n\ # also-notify \n\ alt-transfer-source *;\n\ alt-transfer-source-v6 *;\n\ check-integrity yes;\n\ check-mx-cname warn;\n\ check-sibling yes;\n\ check-srv-cname warn;\n\ check-wildcard yes;\n\ dialup no;\n\ dnssec-dnskey-kskonly no;\n\ dnssec-loadkeys-interval 60;\n\ dnssec-secure-to-insecure no;\n\ dnssec-update-mode maintain;\n\ # forward \n\ # forwarders \n\ inline-signing no;\n\ ixfr-from-differences false;\n\ # maintain-ixfr-base ;\n\ # max-ixfr-log-size \n\ max-journal-size unlimited;\n\ max-records 0;\n\ max-refresh-time 2419200; /* 4 weeks */\n\ max-retry-time 1209600; /* 2 weeks */\n\ max-transfer-idle-in 60;\n\ max-transfer-idle-out 60;\n\ max-transfer-time-in 120;\n\ max-transfer-time-out 120;\n\ min-refresh-time 300;\n\ min-retry-time 500;\n\ multi-master no;\n\ notify yes;\n\ notify-delay 5;\n\ notify-to-soa no;\n\ serial-update-method increment;\n\ sig-signing-nodes 100;\n\ sig-signing-signatures 10;\n\ sig-signing-type 65534;\n\ sig-validity-interval 30; /* days */\n\ transfer-source *;\n\ transfer-source-v6 *;\n\ try-tcp-refresh yes; /* BIND 8 compat */\n\ update-check-ksk yes;\n\ zero-no-soa-ttl yes;\n\ zone-statistics terse;\n\ };\n\ " "#\n\ # Zones in the \"_bind\" view are NOT counted in the count of zones.\n\ #\n\ view \"_bind\" chaos {\n\ recursion no;\n\ notify no;\n\ allow-new-zones no;\n\ \n\ # Prevent use of this zone in DNS amplified reflection DoS attacks\n\ rate-limit {\n\ responses-per-second 3;\n\ slip 0;\n\ min-table-size 10;\n\ };\n\ \n\ zone \"version.bind\" chaos {\n\ type master;\n\ database \"_builtin version\";\n\ };\n\ \n\ zone \"hostname.bind\" chaos {\n\ type master;\n\ database \"_builtin hostname\";\n\ };\n\ \n\ zone \"authors.bind\" chaos {\n\ type master;\n\ database \"_builtin authors\";\n\ };\n\ \n\ zone \"id.server\" chaos {\n\ type master;\n\ database \"_builtin id\";\n\ };\n\ };\n\ " "#\n\ # Default trusted key(s), used if \n\ # \"dnssec-validation auto;\" is set and\n\ # sysconfdir/bind.keys doesn't exist).\n\ #\n\ # BEGIN MANAGED KEYS\n" /* Imported from bind.keys.h: */ MANAGED_KEYS "# END MANAGED KEYS\n\ "; isc_result_t ns_config_parsedefaults(cfg_parser_t *parser, cfg_obj_t **conf) { isc_buffer_t b; isc_buffer_init(&b, defaultconf, sizeof(defaultconf) - 1); isc_buffer_add(&b, sizeof(defaultconf) - 1); return (cfg_parse_buffer3(parser, &b, __FILE__, 0, &cfg_type_namedconf, conf)); } isc_result_t ns_config_get(cfg_obj_t const * const *maps, const char *name, const cfg_obj_t **obj) { int i; for (i = 0;; i++) { if (maps[i] == NULL) return (ISC_R_NOTFOUND); if (cfg_map_get(maps[i], name, obj) == ISC_R_SUCCESS) return (ISC_R_SUCCESS); } } isc_result_t ns_checknames_get(const cfg_obj_t **maps, const char *which, const cfg_obj_t **obj) { const cfg_listelt_t *element; const cfg_obj_t *checknames; const cfg_obj_t *type; const cfg_obj_t *value; int i; for (i = 0;; i++) { if (maps[i] == NULL) return (ISC_R_NOTFOUND); checknames = NULL; if (cfg_map_get(maps[i], "check-names", &checknames) == ISC_R_SUCCESS) { /* * Zone map entry is not a list. */ if (checknames != NULL && !cfg_obj_islist(checknames)) { *obj = checknames; return (ISC_R_SUCCESS); } for (element = cfg_list_first(checknames); element != NULL; element = cfg_list_next(element)) { value = cfg_listelt_value(element); type = cfg_tuple_get(value, "type"); if (strcasecmp(cfg_obj_asstring(type), which) == 0) { *obj = cfg_tuple_get(value, "mode"); return (ISC_R_SUCCESS); } } } } } int ns_config_listcount(const cfg_obj_t *list) { const cfg_listelt_t *e; int i = 0; for (e = cfg_list_first(list); e != NULL; e = cfg_list_next(e)) i++; return (i); } isc_result_t ns_config_getclass(const cfg_obj_t *classobj, dns_rdataclass_t defclass, dns_rdataclass_t *classp) { isc_textregion_t r; isc_result_t result; if (!cfg_obj_isstring(classobj)) { *classp = defclass; return (ISC_R_SUCCESS); } DE_CONST(cfg_obj_asstring(classobj), r.base); r.length = strlen(r.base); result = dns_rdataclass_fromtext(classp, &r); if (result != ISC_R_SUCCESS) cfg_obj_log(classobj, ns_g_lctx, ISC_LOG_ERROR, "unknown class '%s'", r.base); return (result); } isc_result_t ns_config_gettype(const cfg_obj_t *typeobj, dns_rdatatype_t deftype, dns_rdatatype_t *typep) { isc_textregion_t r; isc_result_t result; if (!cfg_obj_isstring(typeobj)) { *typep = deftype; return (ISC_R_SUCCESS); } DE_CONST(cfg_obj_asstring(typeobj), r.base); r.length = strlen(r.base); result = dns_rdatatype_fromtext(typep, &r); if (result != ISC_R_SUCCESS) cfg_obj_log(typeobj, ns_g_lctx, ISC_LOG_ERROR, "unknown type '%s'", r.base); return (result); } dns_zonetype_t ns_config_getzonetype(const cfg_obj_t *zonetypeobj) { dns_zonetype_t ztype = dns_zone_none; const char *str; str = cfg_obj_asstring(zonetypeobj); if (strcasecmp(str, "master") == 0) ztype = dns_zone_master; else if (strcasecmp(str, "slave") == 0) ztype = dns_zone_slave; else if (strcasecmp(str, "stub") == 0) ztype = dns_zone_stub; else if (strcasecmp(str, "static-stub") == 0) ztype = dns_zone_staticstub; else if (strcasecmp(str, "redirect") == 0) ztype = dns_zone_redirect; else INSIST(0); return (ztype); } isc_result_t ns_config_getiplist(const cfg_obj_t *config, const cfg_obj_t *list, in_port_t defport, isc_mem_t *mctx, isc_sockaddr_t **addrsp, isc_dscp_t **dscpsp, isc_uint32_t *countp) { int count, i = 0; const cfg_obj_t *addrlist; const cfg_obj_t *portobj, *dscpobj; const cfg_listelt_t *element; isc_sockaddr_t *addrs; in_port_t port; isc_dscp_t dscp = -1, *dscps = NULL; isc_result_t result; INSIST(addrsp != NULL && *addrsp == NULL); INSIST(dscpsp == NULL || *dscpsp == NULL); INSIST(countp != NULL); addrlist = cfg_tuple_get(list, "addresses"); count = ns_config_listcount(addrlist); portobj = cfg_tuple_get(list, "port"); if (cfg_obj_isuint32(portobj)) { isc_uint32_t val = cfg_obj_asuint32(portobj); if (val > ISC_UINT16_MAX) { cfg_obj_log(portobj, ns_g_lctx, ISC_LOG_ERROR, "port '%u' out of range", val); return (ISC_R_RANGE); } port = (in_port_t) val; } else if (defport != 0) port = defport; else { result = ns_config_getport(config, &port); if (result != ISC_R_SUCCESS) return (result); } if (dscpsp != NULL) { dscpobj = cfg_tuple_get(list, "dscp"); if (dscpobj != NULL && cfg_obj_isuint32(dscpobj)) { if (cfg_obj_asuint32(dscpobj) > 63) { cfg_obj_log(dscpobj, ns_g_lctx, ISC_LOG_ERROR, "dscp value '%u' is out of range", cfg_obj_asuint32(dscpobj)); return (ISC_R_RANGE); } dscp = (isc_dscp_t)cfg_obj_asuint32(dscpobj); } dscps = isc_mem_get(mctx, count * sizeof(isc_dscp_t)); if (dscps == NULL) return (ISC_R_NOMEMORY); } addrs = isc_mem_get(mctx, count * sizeof(isc_sockaddr_t)); if (addrs == NULL) { if (dscps != NULL) isc_mem_put(mctx, dscps, count * sizeof(isc_dscp_t)); return (ISC_R_NOMEMORY); } for (element = cfg_list_first(addrlist); element != NULL; element = cfg_list_next(element), i++) { const cfg_obj_t *addr; INSIST(i < count); addr = cfg_listelt_value(element); addrs[i] = *cfg_obj_assockaddr(addr); if (dscpsp != NULL) { isc_dscp_t innerdscp; innerdscp = cfg_obj_getdscp(addr); if (innerdscp == -1) innerdscp = dscp; dscps[i] = innerdscp; } if (isc_sockaddr_getport(&addrs[i]) == 0) isc_sockaddr_setport(&addrs[i], port); } INSIST(i == count); *addrsp = addrs; *countp = count; if (dscpsp != NULL) *dscpsp = dscps; return (ISC_R_SUCCESS); } void ns_config_putiplist(isc_mem_t *mctx, isc_sockaddr_t **addrsp, isc_dscp_t **dscpsp, isc_uint32_t count) { INSIST(addrsp != NULL && *addrsp != NULL); INSIST(dscpsp == NULL || *dscpsp != NULL); isc_mem_put(mctx, *addrsp, count * sizeof(isc_sockaddr_t)); *addrsp = NULL; if (dscpsp != NULL) { isc_mem_put(mctx, *dscpsp, count * sizeof(isc_dscp_t)); *dscpsp = NULL; } } static isc_result_t get_masters_def(const cfg_obj_t *cctx, const char *name, const cfg_obj_t **ret) { isc_result_t result; const cfg_obj_t *masters = NULL; const cfg_listelt_t *elt; result = cfg_map_get(cctx, "masters", &masters); if (result != ISC_R_SUCCESS) return (result); for (elt = cfg_list_first(masters); elt != NULL; elt = cfg_list_next(elt)) { const cfg_obj_t *list; const char *listname; list = cfg_listelt_value(elt); listname = cfg_obj_asstring(cfg_tuple_get(list, "name")); if (strcasecmp(listname, name) == 0) { *ret = list; return (ISC_R_SUCCESS); } } return (ISC_R_NOTFOUND); } isc_result_t ns_config_getipandkeylist(const cfg_obj_t *config, const cfg_obj_t *list, isc_mem_t *mctx, dns_ipkeylist_t *ipkl) { isc_uint32_t addrcount = 0, dscpcount = 0, keycount = 0, i = 0; isc_uint32_t listcount = 0, l = 0, j; isc_uint32_t stackcount = 0, pushed = 0; isc_result_t result; const cfg_listelt_t *element; const cfg_obj_t *addrlist; const cfg_obj_t *portobj; const cfg_obj_t *dscpobj; in_port_t port; isc_dscp_t dscp = -1; dns_fixedname_t fname; isc_sockaddr_t *addrs = NULL; isc_dscp_t *dscps = NULL; dns_name_t **keys = NULL; struct { const char *name; } *lists = NULL; struct { const cfg_listelt_t *element; in_port_t port; isc_dscp_t dscp; } *stack = NULL; REQUIRE(ipkl != NULL); REQUIRE(ipkl->count == 0); REQUIRE(ipkl->addrs == NULL); REQUIRE(ipkl->keys == NULL); REQUIRE(ipkl->dscps == NULL); REQUIRE(ipkl->labels == NULL); REQUIRE(ipkl->allocated == 0); /* * Get system defaults. */ result = ns_config_getport(config, &port); if (result != ISC_R_SUCCESS) goto cleanup; result = ns_config_getdscp(config, &dscp); if (result != ISC_R_SUCCESS) goto cleanup; newlist: addrlist = cfg_tuple_get(list, "addresses"); portobj = cfg_tuple_get(list, "port"); dscpobj = cfg_tuple_get(list, "dscp"); if (cfg_obj_isuint32(portobj)) { isc_uint32_t val = cfg_obj_asuint32(portobj); if (val > ISC_UINT16_MAX) { cfg_obj_log(portobj, ns_g_lctx, ISC_LOG_ERROR, "port '%u' out of range", val); result = ISC_R_RANGE; goto cleanup; } port = (in_port_t) val; } if (dscpobj != NULL && cfg_obj_isuint32(dscpobj)) { if (cfg_obj_asuint32(dscpobj) > 63) { cfg_obj_log(dscpobj, ns_g_lctx, ISC_LOG_ERROR, "dscp value '%u' is out of range", cfg_obj_asuint32(dscpobj)); result = ISC_R_RANGE; goto cleanup; } dscp = (isc_dscp_t)cfg_obj_asuint32(dscpobj); } result = ISC_R_NOMEMORY; element = cfg_list_first(addrlist); resume: for ( ; element != NULL; element = cfg_list_next(element)) { const cfg_obj_t *addr; const cfg_obj_t *key; const char *keystr; isc_buffer_t b; addr = cfg_tuple_get(cfg_listelt_value(element), "masterselement"); key = cfg_tuple_get(cfg_listelt_value(element), "key"); if (!cfg_obj_issockaddr(addr)) { const char *listname = cfg_obj_asstring(addr); isc_result_t tresult; /* Grow lists? */ if (listcount == l) { void * tmp; isc_uint32_t newlen = listcount + 16; size_t newsize, oldsize; newsize = newlen * sizeof(*lists); oldsize = listcount * sizeof(*lists); tmp = isc_mem_get(mctx, newsize); if (tmp == NULL) goto cleanup; if (listcount != 0) { memmove(tmp, lists, oldsize); isc_mem_put(mctx, lists, oldsize); } lists = tmp; listcount = newlen; } /* Seen? */ for (j = 0; j < l; j++) if (strcasecmp(lists[j].name, listname) == 0) break; if (j < l) continue; tresult = get_masters_def(config, listname, &list); if (tresult == ISC_R_NOTFOUND) { cfg_obj_log(addr, ns_g_lctx, ISC_LOG_ERROR, "masters \"%s\" not found", listname); result = tresult; goto cleanup; } if (tresult != ISC_R_SUCCESS) goto cleanup; lists[l++].name = listname; /* Grow stack? */ if (stackcount == pushed) { void * tmp; isc_uint32_t newlen = stackcount + 16; size_t newsize, oldsize; newsize = newlen * sizeof(*stack); oldsize = stackcount * sizeof(*stack); tmp = isc_mem_get(mctx, newsize); if (tmp == NULL) goto cleanup; if (stackcount != 0) { memmove(tmp, stack, oldsize); isc_mem_put(mctx, stack, oldsize); } stack = tmp; stackcount = newlen; } /* * We want to resume processing this list on the * next element. */ stack[pushed].element = cfg_list_next(element); stack[pushed].port = port; stack[pushed].dscp = dscp; pushed++; goto newlist; } if (i == addrcount) { void * tmp; isc_uint32_t newlen = addrcount + 16; size_t newsize, oldsize; newsize = newlen * sizeof(isc_sockaddr_t); oldsize = addrcount * sizeof(isc_sockaddr_t); tmp = isc_mem_get(mctx, newsize); if (tmp == NULL) goto cleanup; if (addrcount != 0) { memmove(tmp, addrs, oldsize); isc_mem_put(mctx, addrs, oldsize); } addrs = tmp; addrcount = newlen; newsize = newlen * sizeof(isc_dscp_t); oldsize = dscpcount * sizeof(isc_dscp_t); tmp = isc_mem_get(mctx, newsize); if (tmp == NULL) goto cleanup; if (dscpcount != 0) { memmove(tmp, dscps, oldsize); isc_mem_put(mctx, dscps, oldsize); } dscps = tmp; dscpcount = newlen; newsize = newlen * sizeof(dns_name_t *); oldsize = keycount * sizeof(dns_name_t *); tmp = isc_mem_get(mctx, newsize); if (tmp == NULL) goto cleanup; if (keycount != 0) { memmove(tmp, keys, oldsize); isc_mem_put(mctx, keys, oldsize); } keys = tmp; keycount = newlen; } addrs[i] = *cfg_obj_assockaddr(addr); if (isc_sockaddr_getport(&addrs[i]) == 0) isc_sockaddr_setport(&addrs[i], port); dscps[i] = cfg_obj_getdscp(addr); if (dscps[i] == -1) dscps[i] = dscp; keys[i] = NULL; i++; /* Increment here so that cleanup on error works. */ if (!cfg_obj_isstring(key)) continue; keys[i - 1] = isc_mem_get(mctx, sizeof(dns_name_t)); if (keys[i - 1] == NULL) goto cleanup; dns_name_init(keys[i - 1], NULL); keystr = cfg_obj_asstring(key); isc_buffer_constinit(&b, keystr, strlen(keystr)); isc_buffer_add(&b, strlen(keystr)); dns_fixedname_init(&fname); result = dns_name_fromtext(dns_fixedname_name(&fname), &b, dns_rootname, 0, NULL); if (result != ISC_R_SUCCESS) goto cleanup; result = dns_name_dup(dns_fixedname_name(&fname), mctx, keys[i - 1]); if (result != ISC_R_SUCCESS) goto cleanup; } if (pushed != 0) { pushed--; element = stack[pushed].element; port = stack[pushed].port; dscp = stack[pushed].dscp; goto resume; } if (i < addrcount) { void * tmp; size_t newsize, oldsize; newsize = i * sizeof(isc_sockaddr_t); oldsize = addrcount * sizeof(isc_sockaddr_t); if (i != 0) { tmp = isc_mem_get(mctx, newsize); if (tmp == NULL) goto cleanup; memmove(tmp, addrs, newsize); } else tmp = NULL; isc_mem_put(mctx, addrs, oldsize); addrs = tmp; addrcount = i; newsize = i * sizeof(isc_dscp_t); oldsize = dscpcount * sizeof(isc_dscp_t); if (i != 0) { tmp = isc_mem_get(mctx, newsize); if (tmp == NULL) goto cleanup; memmove(tmp, dscps, newsize); } else tmp = NULL; isc_mem_put(mctx, dscps, oldsize); dscps = tmp; dscpcount = i; newsize = i * sizeof(dns_name_t *); oldsize = keycount * sizeof(dns_name_t *); if (i != 0) { tmp = isc_mem_get(mctx, newsize); if (tmp == NULL) goto cleanup; memmove(tmp, keys, newsize); } else tmp = NULL; isc_mem_put(mctx, keys, oldsize); keys = tmp; keycount = i; } if (lists != NULL) isc_mem_put(mctx, lists, listcount * sizeof(*lists)); if (stack != NULL) isc_mem_put(mctx, stack, stackcount * sizeof(*stack)); INSIST(keycount == addrcount); ipkl->addrs = addrs; ipkl->dscps = dscps; ipkl->keys = keys; ipkl->count = addrcount; ipkl->allocated = addrcount; return (ISC_R_SUCCESS); cleanup: if (addrs != NULL) isc_mem_put(mctx, addrs, addrcount * sizeof(isc_sockaddr_t)); if (dscps != NULL) isc_mem_put(mctx, dscps, dscpcount * sizeof(isc_dscp_t)); if (keys != NULL) { for (j = 0; j < i; j++) { if (keys[j] == NULL) continue; if (dns_name_dynamic(keys[j])) dns_name_free(keys[j], mctx); isc_mem_put(mctx, keys[j], sizeof(dns_name_t)); } isc_mem_put(mctx, keys, keycount * sizeof(dns_name_t *)); } if (lists != NULL) isc_mem_put(mctx, lists, listcount * sizeof(*lists)); if (stack != NULL) isc_mem_put(mctx, stack, stackcount * sizeof(*stack)); return (result); } isc_result_t ns_config_getport(const cfg_obj_t *config, in_port_t *portp) { const cfg_obj_t *maps[3]; const cfg_obj_t *options = NULL; const cfg_obj_t *portobj = NULL; isc_result_t result; int i; (void)cfg_map_get(config, "options", &options); i = 0; if (options != NULL) maps[i++] = options; maps[i++] = ns_g_defaults; maps[i] = NULL; result = ns_config_get(maps, "port", &portobj); INSIST(result == ISC_R_SUCCESS); if (cfg_obj_asuint32(portobj) >= ISC_UINT16_MAX) { cfg_obj_log(portobj, ns_g_lctx, ISC_LOG_ERROR, "port '%u' out of range", cfg_obj_asuint32(portobj)); return (ISC_R_RANGE); } *portp = (in_port_t)cfg_obj_asuint32(portobj); return (ISC_R_SUCCESS); } isc_result_t ns_config_getdscp(const cfg_obj_t *config, isc_dscp_t *dscpp) { const cfg_obj_t *options = NULL; const cfg_obj_t *dscpobj = NULL; isc_result_t result; (void)cfg_map_get(config, "options", &options); if (options == NULL) return (ISC_R_SUCCESS); result = cfg_map_get(options, "dscp", &dscpobj); if (result != ISC_R_SUCCESS || dscpobj == NULL) { *dscpp = -1; return (ISC_R_SUCCESS); } if (cfg_obj_asuint32(dscpobj) >= 64) { cfg_obj_log(dscpobj, ns_g_lctx, ISC_LOG_ERROR, "dscp '%u' out of range", cfg_obj_asuint32(dscpobj)); return (ISC_R_RANGE); } *dscpp = (isc_dscp_t)cfg_obj_asuint32(dscpobj); return (ISC_R_SUCCESS); } struct keyalgorithms { const char *str; enum { hmacnone, hmacmd5, hmacsha1, hmacsha224, hmacsha256, hmacsha384, hmacsha512 } hmac; unsigned int type; isc_uint16_t size; } algorithms[] = { #ifndef PK11_MD5_DISABLE { "hmac-md5", hmacmd5, DST_ALG_HMACMD5, 128 }, { "hmac-md5.sig-alg.reg.int", hmacmd5, DST_ALG_HMACMD5, 0 }, { "hmac-md5.sig-alg.reg.int.", hmacmd5, DST_ALG_HMACMD5, 0 }, #endif { "hmac-sha1", hmacsha1, DST_ALG_HMACSHA1, 160 }, { "hmac-sha224", hmacsha224, DST_ALG_HMACSHA224, 224 }, { "hmac-sha256", hmacsha256, DST_ALG_HMACSHA256, 256 }, { "hmac-sha384", hmacsha384, DST_ALG_HMACSHA384, 384 }, { "hmac-sha512", hmacsha512, DST_ALG_HMACSHA512, 512 }, { NULL, hmacnone, DST_ALG_UNKNOWN, 0 } }; isc_result_t ns_config_getkeyalgorithm(const char *str, dns_name_t **name, isc_uint16_t *digestbits) { return (ns_config_getkeyalgorithm2(str, name, NULL, digestbits)); } isc_result_t ns_config_getkeyalgorithm2(const char *str, dns_name_t **name, unsigned int *typep, isc_uint16_t *digestbits) { int i; size_t len = 0; isc_uint16_t bits; isc_result_t result; for (i = 0; algorithms[i].str != NULL; i++) { len = strlen(algorithms[i].str); if (strncasecmp(algorithms[i].str, str, len) == 0 && (str[len] == '\0' || (algorithms[i].size != 0 && str[len] == '-'))) break; } if (algorithms[i].str == NULL) return (ISC_R_NOTFOUND); if (str[len] == '-') { result = isc_parse_uint16(&bits, str + len + 1, 10); if (result != ISC_R_SUCCESS) return (result); if (bits > algorithms[i].size) return (ISC_R_RANGE); } else if (algorithms[i].size == 0) bits = 128; else bits = algorithms[i].size; if (name != NULL) { switch (algorithms[i].hmac) { #ifndef PK11_MD5_DISABLE case hmacmd5: *name = dns_tsig_hmacmd5_name; break; #endif case hmacsha1: *name = dns_tsig_hmacsha1_name; break; case hmacsha224: *name = dns_tsig_hmacsha224_name; break; case hmacsha256: *name = dns_tsig_hmacsha256_name; break; case hmacsha384: *name = dns_tsig_hmacsha384_name; break; case hmacsha512: *name = dns_tsig_hmacsha512_name; break; default: INSIST(0); } } if (typep != NULL) *typep = algorithms[i].type; if (digestbits != NULL) *digestbits = bits; return (ISC_R_SUCCESS); } bind9-9.11.3+dfsg/bin/named/control.c000066400000000000000000000225551325250447100172250ustar00rootroot00000000000000/* * Copyright (C) 2001-2007, 2009-2016 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* $Id: control.c,v 1.49 2012/01/31 23:47:31 tbox Exp $ */ /*! \file */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_LIBSCF #include #endif static isc_result_t getcommand(isc_lex_t *lex, char **cmdp) { isc_result_t result; isc_token_t token; REQUIRE(cmdp != NULL && *cmdp == NULL); result = isc_lex_gettoken(lex, ISC_LEXOPT_EOF, &token); if (result != ISC_R_SUCCESS) return (result); isc_lex_ungettoken(lex, &token); if (token.type != isc_tokentype_string) return (ISC_R_FAILURE); *cmdp = token.value.as_textregion.base; return (ISC_R_SUCCESS); } static inline isc_boolean_t command_compare(const char *str, const char *command) { return ISC_TF(strcasecmp(str, command) == 0); } /*% * This function is called to process the incoming command * when a control channel message is received. */ isc_result_t ns_control_docommand(isccc_sexpr_t *message, isc_boolean_t readonly, isc_buffer_t **text) { isccc_sexpr_t *data; char *cmdline = NULL; char *command = NULL; isc_result_t result; int log_level; isc_buffer_t src; isc_lex_t *lex = NULL; #ifdef HAVE_LIBSCF ns_smf_want_disable = 0; #endif data = isccc_alist_lookup(message, "_data"); if (!isccc_alist_alistp(data)) { /* * No data section. */ return (ISC_R_FAILURE); } result = isccc_cc_lookupstring(data, "type", &cmdline); if (result != ISC_R_SUCCESS) { /* * We have no idea what this is. */ return (result); } result = isc_lex_create(ns_g_mctx, strlen(cmdline), &lex); if (result != ISC_R_SUCCESS) return (result); isc_buffer_init(&src, cmdline, strlen(cmdline)); isc_buffer_add(&src, strlen(cmdline)); result = isc_lex_openbuffer(lex, &src); if (result != ISC_R_SUCCESS) goto cleanup; result = getcommand(lex, &command); if (result != ISC_R_SUCCESS) goto cleanup; /* * Compare the 'command' parameter against all known control commands. */ if (command_compare(command, NS_COMMAND_NULL) || command_compare(command, NS_COMMAND_STATUS)) { log_level = ISC_LOG_DEBUG(1); } else { log_level = ISC_LOG_INFO; } /* * If this listener should have read-only access, reject * restricted commands here. rndc nta is handled specially * below. */ if (readonly && !command_compare(command, NS_COMMAND_NTA) && !command_compare(command, NS_COMMAND_NULL) && !command_compare(command, NS_COMMAND_STATUS) && !command_compare(command, NS_COMMAND_SHOWZONE) && !command_compare(command, NS_COMMAND_TESTGEN) && !command_compare(command, NS_COMMAND_ZONESTATUS)) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_CONTROL, log_level, "rejecting restricted control channel " "command '%s'", cmdline); result = ISC_R_FAILURE; goto cleanup; } isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_CONTROL, log_level, "received control channel command '%s'", cmdline); if (command_compare(command, NS_COMMAND_RELOAD)) { result = ns_server_reloadcommand(ns_g_server, lex, text); } else if (command_compare(command, NS_COMMAND_RECONFIG)) { result = ns_server_reconfigcommand(ns_g_server); } else if (command_compare(command, NS_COMMAND_REFRESH)) { result = ns_server_refreshcommand(ns_g_server, lex, text); } else if (command_compare(command, NS_COMMAND_RETRANSFER)) { result = ns_server_retransfercommand(ns_g_server, lex, text); } else if (command_compare(command, NS_COMMAND_HALT)) { #ifdef HAVE_LIBSCF /* * If we are managed by smf(5), AND in chroot, then * we cannot connect to the smf repository, so just * return with an appropriate message back to rndc. */ if (ns_smf_got_instance == 1 && ns_smf_chroot == 1) { result = ns_smf_add_message(text); goto cleanup; } /* * If we are managed by smf(5) but not in chroot, * try to disable ourselves the smf way. */ if (ns_smf_got_instance == 1 && ns_smf_chroot == 0) ns_smf_want_disable = 1; /* * If ns_smf_got_instance = 0, ns_smf_chroot * is not relevant and we fall through to * isc_app_shutdown below. */ #endif /* Do not flush master files */ ns_server_flushonshutdown(ns_g_server, ISC_FALSE); ns_os_shutdownmsg(cmdline, *text); isc_app_shutdown(); result = ISC_R_SUCCESS; } else if (command_compare(command, NS_COMMAND_STOP)) { /* * "stop" is the same as "halt" except it does * flush master files. */ #ifdef HAVE_LIBSCF if (ns_smf_got_instance == 1 && ns_smf_chroot == 1) { result = ns_smf_add_message(text); goto cleanup; } if (ns_smf_got_instance == 1 && ns_smf_chroot == 0) ns_smf_want_disable = 1; #endif ns_server_flushonshutdown(ns_g_server, ISC_TRUE); ns_os_shutdownmsg(cmdline, *text); isc_app_shutdown(); result = ISC_R_SUCCESS; } else if (command_compare(command, NS_COMMAND_DUMPSTATS)) { result = ns_server_dumpstats(ns_g_server); } else if (command_compare(command, NS_COMMAND_QUERYLOG)) { result = ns_server_togglequerylog(ns_g_server, lex); } else if (command_compare(command, NS_COMMAND_DUMPDB)) { ns_server_dumpdb(ns_g_server, lex, text); result = ISC_R_SUCCESS; } else if (command_compare(command, NS_COMMAND_SECROOTS)) { result = ns_server_dumpsecroots(ns_g_server, lex, text); } else if (command_compare(command, NS_COMMAND_TRACE)) { result = ns_server_setdebuglevel(ns_g_server, lex); } else if (command_compare(command, NS_COMMAND_NOTRACE)) { ns_g_debuglevel = 0; isc_log_setdebuglevel(ns_g_lctx, ns_g_debuglevel); result = ISC_R_SUCCESS; } else if (command_compare(command, NS_COMMAND_FLUSH)) { result = ns_server_flushcache(ns_g_server, lex); } else if (command_compare(command, NS_COMMAND_FLUSHNAME)) { result = ns_server_flushnode(ns_g_server, lex, ISC_FALSE); } else if (command_compare(command, NS_COMMAND_FLUSHTREE)) { result = ns_server_flushnode(ns_g_server, lex, ISC_TRUE); } else if (command_compare(command, NS_COMMAND_STATUS)) { result = ns_server_status(ns_g_server, text); } else if (command_compare(command, NS_COMMAND_TSIGLIST)) { result = ns_server_tsiglist(ns_g_server, text); } else if (command_compare(command, NS_COMMAND_TSIGDELETE)) { result = ns_server_tsigdelete(ns_g_server, lex, text); } else if (command_compare(command, NS_COMMAND_FREEZE)) { result = ns_server_freeze(ns_g_server, ISC_TRUE, lex, text); } else if (command_compare(command, NS_COMMAND_UNFREEZE) || command_compare(command, NS_COMMAND_THAW)) { result = ns_server_freeze(ns_g_server, ISC_FALSE, lex, text); } else if (command_compare(command, NS_COMMAND_SCAN)) { result = ISC_R_SUCCESS; ns_server_scan_interfaces(ns_g_server); } else if (command_compare(command, NS_COMMAND_SYNC)) { result = ns_server_sync(ns_g_server, lex, text); } else if (command_compare(command, NS_COMMAND_RECURSING)) { result = ns_server_dumprecursing(ns_g_server); } else if (command_compare(command, NS_COMMAND_TIMERPOKE)) { result = ISC_R_SUCCESS; isc_timermgr_poke(ns_g_timermgr); } else if (command_compare(command, NS_COMMAND_NULL)) { result = ISC_R_SUCCESS; } else if (command_compare(command, NS_COMMAND_NOTIFY)) { result = ns_server_notifycommand(ns_g_server, lex, text); } else if (command_compare(command, NS_COMMAND_VALIDATION)) { result = ns_server_validation(ns_g_server, lex, text); } else if (command_compare(command, NS_COMMAND_SIGN) || command_compare(command, NS_COMMAND_LOADKEYS)) { result = ns_server_rekey(ns_g_server, lex, text); } else if (command_compare(command, NS_COMMAND_ADDZONE) || command_compare(command, NS_COMMAND_MODZONE)) { result = ns_server_changezone(ns_g_server, cmdline, text); } else if (command_compare(command, NS_COMMAND_DELZONE)) { result = ns_server_delzone(ns_g_server, lex, text); } else if (command_compare(command, NS_COMMAND_SHOWZONE)) { result = ns_server_showzone(ns_g_server, lex, text); } else if (command_compare(command, NS_COMMAND_SIGNING)) { result = ns_server_signing(ns_g_server, lex, text); } else if (command_compare(command, NS_COMMAND_ZONESTATUS)) { result = ns_server_zonestatus(ns_g_server, lex, text); } else if (command_compare(command, NS_COMMAND_NTA)) { result = ns_server_nta(ns_g_server, lex, readonly, text); } else if (command_compare(command, NS_COMMAND_TESTGEN)) { result = ns_server_testgen(lex, text); } else if (command_compare(command, NS_COMMAND_MKEYS)) { result = ns_server_mkeys(ns_g_server, lex, text); } else if (command_compare(command, NS_COMMAND_DNSTAP) || command_compare(command, NS_COMMAND_DNSTAPREOPEN)) { result = ns_server_dnstap(ns_g_server, lex, text); } else { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_CONTROL, ISC_LOG_WARNING, "unknown control channel command '%s'", command); result = DNS_R_UNKNOWNCOMMAND; } cleanup: if (lex != NULL) isc_lex_destroy(&lex); return (result); } bind9-9.11.3+dfsg/bin/named/controlconf.c000066400000000000000000001212021325250447100200600ustar00rootroot00000000000000/* * Copyright (C) 2001-2008, 2011-2016 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /*! \file */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* * Note: Listeners and connections are not locked. All event handlers are * executed by the server task, and all callers of exported routines must * be running under the server task. */ typedef struct controlkey controlkey_t; typedef ISC_LIST(controlkey_t) controlkeylist_t; typedef struct controlconnection controlconnection_t; typedef ISC_LIST(controlconnection_t) controlconnectionlist_t; typedef struct controllistener controllistener_t; typedef ISC_LIST(controllistener_t) controllistenerlist_t; struct controlkey { char * keyname; isc_uint32_t algorithm; isc_region_t secret; ISC_LINK(controlkey_t) link; }; struct controlconnection { isc_socket_t * sock; isccc_ccmsg_t ccmsg; isc_boolean_t ccmsg_valid; isc_boolean_t sending; isc_timer_t * timer; isc_buffer_t * buffer; controllistener_t * listener; isc_uint32_t nonce; ISC_LINK(controlconnection_t) link; }; struct controllistener { ns_controls_t * controls; isc_mem_t * mctx; isc_task_t * task; isc_sockaddr_t address; isc_socket_t * sock; dns_acl_t * acl; isc_boolean_t listening; isc_boolean_t exiting; controlkeylist_t keys; controlconnectionlist_t connections; isc_sockettype_t type; isc_uint32_t perm; isc_uint32_t owner; isc_uint32_t group; isc_boolean_t readonly; ISC_LINK(controllistener_t) link; }; struct ns_controls { ns_server_t *server; controllistenerlist_t listeners; isc_boolean_t shuttingdown; isccc_symtab_t *symtab; }; static void control_newconn(isc_task_t *task, isc_event_t *event); static void control_recvmessage(isc_task_t *task, isc_event_t *event); #define CLOCKSKEW 300 static void free_controlkey(controlkey_t *key, isc_mem_t *mctx) { if (key->keyname != NULL) isc_mem_free(mctx, key->keyname); if (key->secret.base != NULL) isc_mem_put(mctx, key->secret.base, key->secret.length); isc_mem_put(mctx, key, sizeof(*key)); } static void free_controlkeylist(controlkeylist_t *keylist, isc_mem_t *mctx) { while (!ISC_LIST_EMPTY(*keylist)) { controlkey_t *key = ISC_LIST_HEAD(*keylist); ISC_LIST_UNLINK(*keylist, key, link); free_controlkey(key, mctx); } } static void free_listener(controllistener_t *listener) { INSIST(listener->exiting); INSIST(!listener->listening); INSIST(ISC_LIST_EMPTY(listener->connections)); if (listener->sock != NULL) isc_socket_detach(&listener->sock); free_controlkeylist(&listener->keys, listener->mctx); if (listener->acl != NULL) dns_acl_detach(&listener->acl); isc_mem_putanddetach(&listener->mctx, listener, sizeof(*listener)); } static void maybe_free_listener(controllistener_t *listener) { if (listener->exiting && !listener->listening && ISC_LIST_EMPTY(listener->connections)) free_listener(listener); } static void maybe_free_connection(controlconnection_t *conn) { controllistener_t *listener = conn->listener; if (conn->buffer != NULL) isc_buffer_free(&conn->buffer); if (conn->timer != NULL) isc_timer_detach(&conn->timer); if (conn->ccmsg_valid) { isccc_ccmsg_cancelread(&conn->ccmsg); return; } if (conn->sending) { isc_socket_cancel(conn->sock, listener->task, ISC_SOCKCANCEL_SEND); return; } ISC_LIST_UNLINK(listener->connections, conn, link); #ifdef ENABLE_AFL if (ns_g_fuzz_type == ns_fuzz_rndc) { named_fuzz_notify(); } #endif isc_mem_put(listener->mctx, conn, sizeof(*conn)); } static void shutdown_listener(controllistener_t *listener) { controlconnection_t *conn; controlconnection_t *next; if (!listener->exiting) { char socktext[ISC_SOCKADDR_FORMATSIZE]; ISC_LIST_UNLINK(listener->controls->listeners, listener, link); isc_sockaddr_format(&listener->address, socktext, sizeof(socktext)); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_CONTROL, ISC_LOG_NOTICE, "stopping command channel on %s", socktext); if (listener->type == isc_sockettype_unix) isc_socket_cleanunix(&listener->address, ISC_TRUE); listener->exiting = ISC_TRUE; } for (conn = ISC_LIST_HEAD(listener->connections); conn != NULL; conn = next) { next = ISC_LIST_NEXT(conn, link); maybe_free_connection(conn); } if (listener->listening) isc_socket_cancel(listener->sock, listener->task, ISC_SOCKCANCEL_ACCEPT); maybe_free_listener(listener); } static isc_boolean_t address_ok(isc_sockaddr_t *sockaddr, dns_acl_t *acl) { isc_netaddr_t netaddr; isc_result_t result; int match; isc_netaddr_fromsockaddr(&netaddr, sockaddr); result = dns_acl_match(&netaddr, NULL, acl, &ns_g_server->aclenv, &match, NULL); if (result != ISC_R_SUCCESS || match <= 0) return (ISC_FALSE); else return (ISC_TRUE); } static isc_result_t control_accept(controllistener_t *listener) { isc_result_t result; result = isc_socket_accept(listener->sock, listener->task, control_newconn, listener); if (result != ISC_R_SUCCESS) UNEXPECTED_ERROR(__FILE__, __LINE__, "isc_socket_accept() failed: %s", isc_result_totext(result)); else listener->listening = ISC_TRUE; return (result); } static isc_result_t control_listen(controllistener_t *listener) { isc_result_t result; result = isc_socket_listen(listener->sock, 0); if (result != ISC_R_SUCCESS) UNEXPECTED_ERROR(__FILE__, __LINE__, "isc_socket_listen() failed: %s", isc_result_totext(result)); return (result); } static void control_next(controllistener_t *listener) { (void)control_accept(listener); } static void control_senddone(isc_task_t *task, isc_event_t *event) { isc_socketevent_t *sevent = (isc_socketevent_t *) event; controlconnection_t *conn = event->ev_arg; controllistener_t *listener = conn->listener; isc_socket_t *sock = (isc_socket_t *)sevent->ev_sender; isc_result_t result; REQUIRE(conn->sending); UNUSED(task); conn->sending = ISC_FALSE; if (sevent->result != ISC_R_SUCCESS && sevent->result != ISC_R_CANCELED) { char socktext[ISC_SOCKADDR_FORMATSIZE]; isc_sockaddr_t peeraddr; (void)isc_socket_getpeername(sock, &peeraddr); isc_sockaddr_format(&peeraddr, socktext, sizeof(socktext)); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_CONTROL, ISC_LOG_WARNING, "error sending command response to %s: %s", socktext, isc_result_totext(sevent->result)); } isc_event_free(&event); result = isccc_ccmsg_readmessage(&conn->ccmsg, listener->task, control_recvmessage, conn); if (result != ISC_R_SUCCESS) { isc_socket_detach(&conn->sock); maybe_free_connection(conn); maybe_free_listener(listener); } } static inline void log_invalid(isccc_ccmsg_t *ccmsg, isc_result_t result) { char socktext[ISC_SOCKADDR_FORMATSIZE]; isc_sockaddr_t peeraddr; (void)isc_socket_getpeername(ccmsg->sock, &peeraddr); isc_sockaddr_format(&peeraddr, socktext, sizeof(socktext)); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_CONTROL, ISC_LOG_ERROR, "invalid command from %s: %s", socktext, isc_result_totext(result)); } static void control_recvmessage(isc_task_t *task, isc_event_t *event) { controlconnection_t *conn; controllistener_t *listener; controlkey_t *key; isccc_sexpr_t *request = NULL; isccc_sexpr_t *response = NULL; isc_uint32_t algorithm; isccc_region_t secret; isc_stdtime_t now; isc_buffer_t b; isc_region_t r; isc_buffer_t *text; isc_result_t result; isc_result_t eresult; isccc_sexpr_t *_ctrl; isccc_time_t sent; isccc_time_t exp; isc_uint32_t nonce; isccc_sexpr_t *data; REQUIRE(event->ev_type == ISCCC_EVENT_CCMSG); conn = event->ev_arg; listener = conn->listener; algorithm = DST_ALG_UNKNOWN; secret.rstart = NULL; text = NULL; /* Is the server shutting down? */ if (listener->controls->shuttingdown) goto cleanup; if (conn->ccmsg.result != ISC_R_SUCCESS) { if (conn->ccmsg.result != ISC_R_CANCELED && conn->ccmsg.result != ISC_R_EOF) log_invalid(&conn->ccmsg, conn->ccmsg.result); goto cleanup; } request = NULL; for (key = ISC_LIST_HEAD(listener->keys); key != NULL; key = ISC_LIST_NEXT(key, link)) { isccc_region_t ccregion; ccregion.rstart = isc_buffer_base(&conn->ccmsg.buffer); ccregion.rend = isc_buffer_used(&conn->ccmsg.buffer); secret.rstart = isc_mem_get(listener->mctx, key->secret.length); if (secret.rstart == NULL) goto cleanup; memmove(secret.rstart, key->secret.base, key->secret.length); secret.rend = secret.rstart + key->secret.length; algorithm = key->algorithm; result = isccc_cc_fromwire(&ccregion, &request, algorithm, &secret); if (result == ISC_R_SUCCESS) break; isc_mem_put(listener->mctx, secret.rstart, REGION_SIZE(secret)); if (result != ISCCC_R_BADAUTH) { log_invalid(&conn->ccmsg, result); goto cleanup; } } if (key == NULL) { log_invalid(&conn->ccmsg, ISCCC_R_BADAUTH); goto cleanup; } /* We shouldn't be getting a reply. */ if (isccc_cc_isreply(request)) { log_invalid(&conn->ccmsg, ISC_R_FAILURE); goto cleanup_request; } isc_stdtime_get(&now); /* * Limit exposure to replay attacks. */ _ctrl = isccc_alist_lookup(request, "_ctrl"); if (!isccc_alist_alistp(_ctrl)) { log_invalid(&conn->ccmsg, ISC_R_FAILURE); goto cleanup_request; } if (isccc_cc_lookupuint32(_ctrl, "_tim", &sent) == ISC_R_SUCCESS) { if ((sent + CLOCKSKEW) < now || (sent - CLOCKSKEW) > now) { log_invalid(&conn->ccmsg, ISCCC_R_CLOCKSKEW); goto cleanup_request; } } else { log_invalid(&conn->ccmsg, ISC_R_FAILURE); goto cleanup_request; } /* * Expire messages that are too old. */ if (isccc_cc_lookupuint32(_ctrl, "_exp", &exp) == ISC_R_SUCCESS && now > exp) { log_invalid(&conn->ccmsg, ISCCC_R_EXPIRED); goto cleanup_request; } /* * Duplicate suppression (required for UDP). */ isccc_cc_cleansymtab(listener->controls->symtab, now); result = isccc_cc_checkdup(listener->controls->symtab, request, now); if (result != ISC_R_SUCCESS) { if (result == ISC_R_EXISTS) result = ISCCC_R_DUPLICATE; log_invalid(&conn->ccmsg, result); goto cleanup_request; } if (conn->nonce != 0 && (isccc_cc_lookupuint32(_ctrl, "_nonce", &nonce) != ISC_R_SUCCESS || conn->nonce != nonce)) { log_invalid(&conn->ccmsg, ISCCC_R_BADAUTH); goto cleanup_request; } result = isc_buffer_allocate(listener->mctx, &text, 2 * 2048); if (result != ISC_R_SUCCESS) goto cleanup_request; /* * Establish nonce. */ if (conn->nonce == 0) { while (conn->nonce == 0) isc_random_get(&conn->nonce); eresult = ISC_R_SUCCESS; } else eresult = ns_control_docommand(request, listener->readonly, &text); result = isccc_cc_createresponse(request, now, now + 60, &response); if (result != ISC_R_SUCCESS) goto cleanup_request; data = isccc_alist_lookup(response, "_data"); if (data != NULL) { if (isccc_cc_defineuint32(data, "result", eresult) == NULL) goto cleanup_response; } if (eresult != ISC_R_SUCCESS) { if (data != NULL) { const char *estr = isc_result_totext(eresult); if (isccc_cc_definestring(data, "err", estr) == NULL) goto cleanup_response; } } if (isc_buffer_usedlength(text) > 0) { if (data != NULL) { char *str = (char *)isc_buffer_base(text); if (isccc_cc_definestring(data, "text", str) == NULL) goto cleanup_response; } } _ctrl = isccc_alist_lookup(response, "_ctrl"); if (_ctrl == NULL || isccc_cc_defineuint32(_ctrl, "_nonce", conn->nonce) == NULL) goto cleanup_response; if (conn->buffer == NULL) { result = isc_buffer_allocate(listener->mctx, &conn->buffer, 2 * 2048); if (result != ISC_R_SUCCESS) goto cleanup_response; } isc_buffer_clear(conn->buffer); /* Skip the length field (4 bytes) */ isc_buffer_add(conn->buffer, 4); result = isccc_cc_towire(response, &conn->buffer, algorithm, &secret); if (result != ISC_R_SUCCESS) goto cleanup_response; isc_buffer_init(&b, conn->buffer->base, 4); isc_buffer_putuint32(&b, conn->buffer->used - 4); r.base = conn->buffer->base; r.length = conn->buffer->used; result = isc_socket_send(conn->sock, &r, task, control_senddone, conn); if (result != ISC_R_SUCCESS) goto cleanup_response; conn->sending = ISC_TRUE; isc_mem_put(listener->mctx, secret.rstart, REGION_SIZE(secret)); isccc_sexpr_free(&request); isccc_sexpr_free(&response); isc_buffer_free(&text); return; cleanup_response: isccc_sexpr_free(&response); cleanup_request: isccc_sexpr_free(&request); isc_mem_put(listener->mctx, secret.rstart, REGION_SIZE(secret)); if (text != NULL) isc_buffer_free(&text); cleanup: isc_socket_detach(&conn->sock); isccc_ccmsg_invalidate(&conn->ccmsg); conn->ccmsg_valid = ISC_FALSE; maybe_free_connection(conn); maybe_free_listener(listener); } static void control_timeout(isc_task_t *task, isc_event_t *event) { controlconnection_t *conn = event->ev_arg; UNUSED(task); isc_timer_detach(&conn->timer); maybe_free_connection(conn); isc_event_free(&event); } static isc_result_t newconnection(controllistener_t *listener, isc_socket_t *sock) { controlconnection_t *conn; isc_interval_t interval; isc_result_t result; conn = isc_mem_get(listener->mctx, sizeof(*conn)); if (conn == NULL) return (ISC_R_NOMEMORY); conn->sock = sock; isccc_ccmsg_init(listener->mctx, sock, &conn->ccmsg); /* Set a 32 KiB upper limit on incoming message. */ isccc_ccmsg_setmaxsize(&conn->ccmsg, 32768); conn->ccmsg_valid = ISC_TRUE; conn->sending = ISC_FALSE; conn->buffer = NULL; conn->timer = NULL; isc_interval_set(&interval, 60, 0); result = isc_timer_create(ns_g_timermgr, isc_timertype_once, NULL, &interval, listener->task, control_timeout, conn, &conn->timer); if (result != ISC_R_SUCCESS) goto cleanup; conn->listener = listener; conn->nonce = 0; ISC_LINK_INIT(conn, link); result = isccc_ccmsg_readmessage(&conn->ccmsg, listener->task, control_recvmessage, conn); if (result != ISC_R_SUCCESS) goto cleanup; ISC_LIST_APPEND(listener->connections, conn, link); return (ISC_R_SUCCESS); cleanup: if (conn->buffer != NULL) isc_buffer_free(&conn->buffer); isccc_ccmsg_invalidate(&conn->ccmsg); if (conn->timer != NULL) isc_timer_detach(&conn->timer); isc_mem_put(listener->mctx, conn, sizeof(*conn)); #ifdef ENABLE_AFL if (ns_g_fuzz_type == ns_fuzz_rndc) { named_fuzz_notify(); } #endif return (result); } static void control_newconn(isc_task_t *task, isc_event_t *event) { isc_socket_newconnev_t *nevent = (isc_socket_newconnev_t *)event; controllistener_t *listener = event->ev_arg; isc_socket_t *sock; isc_sockaddr_t peeraddr; isc_result_t result; UNUSED(task); listener->listening = ISC_FALSE; if (nevent->result != ISC_R_SUCCESS) { if (nevent->result == ISC_R_CANCELED) { shutdown_listener(listener); goto cleanup; } goto restart; } sock = nevent->newsocket; isc_socket_setname(sock, "control", NULL); (void)isc_socket_getpeername(sock, &peeraddr); if (listener->type == isc_sockettype_tcp && !address_ok(&peeraddr, listener->acl)) { char socktext[ISC_SOCKADDR_FORMATSIZE]; isc_sockaddr_format(&peeraddr, socktext, sizeof(socktext)); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_CONTROL, ISC_LOG_WARNING, "rejected command channel message from %s", socktext); isc_socket_detach(&sock); goto restart; } result = newconnection(listener, sock); if (result != ISC_R_SUCCESS) { char socktext[ISC_SOCKADDR_FORMATSIZE]; isc_sockaddr_format(&peeraddr, socktext, sizeof(socktext)); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_CONTROL, ISC_LOG_WARNING, "dropped command channel from %s: %s", socktext, isc_result_totext(result)); isc_socket_detach(&sock); goto restart; } restart: control_next(listener); cleanup: isc_event_free(&event); } static void controls_shutdown(ns_controls_t *controls) { controllistener_t *listener; controllistener_t *next; for (listener = ISC_LIST_HEAD(controls->listeners); listener != NULL; listener = next) { /* * This is asynchronous. As listeners shut down, they will * call their callbacks. */ next = ISC_LIST_NEXT(listener, link); shutdown_listener(listener); } } void ns_controls_shutdown(ns_controls_t *controls) { controls_shutdown(controls); controls->shuttingdown = ISC_TRUE; } static isc_result_t cfgkeylist_find(const cfg_obj_t *keylist, const char *keyname, const cfg_obj_t **objp) { const cfg_listelt_t *element; const char *str; const cfg_obj_t *obj; for (element = cfg_list_first(keylist); element != NULL; element = cfg_list_next(element)) { obj = cfg_listelt_value(element); str = cfg_obj_asstring(cfg_map_getname(obj)); if (strcasecmp(str, keyname) == 0) break; } if (element == NULL) return (ISC_R_NOTFOUND); obj = cfg_listelt_value(element); *objp = obj; return (ISC_R_SUCCESS); } static isc_result_t controlkeylist_fromcfg(const cfg_obj_t *keylist, isc_mem_t *mctx, controlkeylist_t *keyids) { const cfg_listelt_t *element; char *newstr = NULL; const char *str; const cfg_obj_t *obj; controlkey_t *key; for (element = cfg_list_first(keylist); element != NULL; element = cfg_list_next(element)) { obj = cfg_listelt_value(element); str = cfg_obj_asstring(obj); newstr = isc_mem_strdup(mctx, str); if (newstr == NULL) goto cleanup; key = isc_mem_get(mctx, sizeof(*key)); if (key == NULL) goto cleanup; key->keyname = newstr; key->algorithm = DST_ALG_UNKNOWN; key->secret.base = NULL; key->secret.length = 0; ISC_LINK_INIT(key, link); ISC_LIST_APPEND(*keyids, key, link); newstr = NULL; } return (ISC_R_SUCCESS); cleanup: if (newstr != NULL) isc_mem_free(mctx, newstr); free_controlkeylist(keyids, mctx); return (ISC_R_NOMEMORY); } static void register_keys(const cfg_obj_t *control, const cfg_obj_t *keylist, controlkeylist_t *keyids, isc_mem_t *mctx, const char *socktext) { controlkey_t *keyid, *next; const cfg_obj_t *keydef; char secret[1024]; isc_buffer_t b; isc_result_t result; /* * Find the keys corresponding to the keyids used by this listener. */ for (keyid = ISC_LIST_HEAD(*keyids); keyid != NULL; keyid = next) { next = ISC_LIST_NEXT(keyid, link); result = cfgkeylist_find(keylist, keyid->keyname, &keydef); if (result != ISC_R_SUCCESS) { cfg_obj_log(control, ns_g_lctx, ISC_LOG_WARNING, "couldn't find key '%s' for use with " "command channel %s", keyid->keyname, socktext); ISC_LIST_UNLINK(*keyids, keyid, link); free_controlkey(keyid, mctx); } else { const cfg_obj_t *algobj = NULL; const cfg_obj_t *secretobj = NULL; const char *algstr = NULL; const char *secretstr = NULL; unsigned int algtype; (void)cfg_map_get(keydef, "algorithm", &algobj); (void)cfg_map_get(keydef, "secret", &secretobj); INSIST(algobj != NULL && secretobj != NULL); algstr = cfg_obj_asstring(algobj); secretstr = cfg_obj_asstring(secretobj); if (ns_config_getkeyalgorithm2(algstr, NULL, &algtype, NULL) != ISC_R_SUCCESS) { cfg_obj_log(control, ns_g_lctx, ISC_LOG_WARNING, "unsupported algorithm '%s' in " "key '%s' for use with command " "channel %s", algstr, keyid->keyname, socktext); ISC_LIST_UNLINK(*keyids, keyid, link); free_controlkey(keyid, mctx); continue; } keyid->algorithm = algtype; isc_buffer_init(&b, secret, sizeof(secret)); result = isc_base64_decodestring(secretstr, &b); if (result != ISC_R_SUCCESS) { cfg_obj_log(keydef, ns_g_lctx, ISC_LOG_WARNING, "secret for key '%s' on " "command channel %s: %s", keyid->keyname, socktext, isc_result_totext(result)); ISC_LIST_UNLINK(*keyids, keyid, link); free_controlkey(keyid, mctx); continue; } keyid->secret.length = isc_buffer_usedlength(&b); keyid->secret.base = isc_mem_get(mctx, keyid->secret.length); if (keyid->secret.base == NULL) { cfg_obj_log(keydef, ns_g_lctx, ISC_LOG_WARNING, "couldn't register key '%s': " "out of memory", keyid->keyname); ISC_LIST_UNLINK(*keyids, keyid, link); free_controlkey(keyid, mctx); break; } memmove(keyid->secret.base, isc_buffer_base(&b), keyid->secret.length); } } } #define CHECK(x) \ do { \ result = (x); \ if (result != ISC_R_SUCCESS) \ goto cleanup; \ } while (0) static isc_result_t get_rndckey(isc_mem_t *mctx, controlkeylist_t *keyids) { isc_result_t result; cfg_parser_t *pctx = NULL; cfg_obj_t *config = NULL; const cfg_obj_t *key = NULL; const cfg_obj_t *algobj = NULL; const cfg_obj_t *secretobj = NULL; const char *algstr = NULL; const char *secretstr = NULL; controlkey_t *keyid = NULL; char secret[1024]; unsigned int algtype; isc_buffer_t b; isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_CONTROL, ISC_LOG_INFO, "configuring command channel from '%s'", ns_g_keyfile); if (! isc_file_exists(ns_g_keyfile)) return (ISC_R_FILENOTFOUND); CHECK(cfg_parser_create(mctx, ns_g_lctx, &pctx)); CHECK(cfg_parse_file(pctx, ns_g_keyfile, &cfg_type_rndckey, &config)); CHECK(cfg_map_get(config, "key", &key)); keyid = isc_mem_get(mctx, sizeof(*keyid)); if (keyid == NULL) CHECK(ISC_R_NOMEMORY); keyid->keyname = isc_mem_strdup(mctx, cfg_obj_asstring(cfg_map_getname(key))); keyid->secret.base = NULL; keyid->secret.length = 0; keyid->algorithm = DST_ALG_UNKNOWN; ISC_LINK_INIT(keyid, link); if (keyid->keyname == NULL) CHECK(ISC_R_NOMEMORY); CHECK(bind9_check_key(key, ns_g_lctx)); (void)cfg_map_get(key, "algorithm", &algobj); (void)cfg_map_get(key, "secret", &secretobj); INSIST(algobj != NULL && secretobj != NULL); algstr = cfg_obj_asstring(algobj); secretstr = cfg_obj_asstring(secretobj); if (ns_config_getkeyalgorithm2(algstr, NULL, &algtype, NULL) != ISC_R_SUCCESS) { cfg_obj_log(key, ns_g_lctx, ISC_LOG_WARNING, "unsupported algorithm '%s' in " "key '%s' for use with command " "channel", algstr, keyid->keyname); goto cleanup; } keyid->algorithm = algtype; isc_buffer_init(&b, secret, sizeof(secret)); result = isc_base64_decodestring(secretstr, &b); if (result != ISC_R_SUCCESS) { cfg_obj_log(key, ns_g_lctx, ISC_LOG_WARNING, "secret for key '%s' on command channel: %s", keyid->keyname, isc_result_totext(result)); goto cleanup; } keyid->secret.length = isc_buffer_usedlength(&b); keyid->secret.base = isc_mem_get(mctx, keyid->secret.length); if (keyid->secret.base == NULL) { cfg_obj_log(key, ns_g_lctx, ISC_LOG_WARNING, "couldn't register key '%s': " "out of memory", keyid->keyname); CHECK(ISC_R_NOMEMORY); } memmove(keyid->secret.base, isc_buffer_base(&b), keyid->secret.length); ISC_LIST_APPEND(*keyids, keyid, link); keyid = NULL; result = ISC_R_SUCCESS; cleanup: if (keyid != NULL) free_controlkey(keyid, mctx); if (config != NULL) cfg_obj_destroy(pctx, &config); if (pctx != NULL) cfg_parser_destroy(&pctx); return (result); } /* * Ensures that both '*global_keylistp' and '*control_keylistp' are * valid or both are NULL. */ static void get_key_info(const cfg_obj_t *config, const cfg_obj_t *control, const cfg_obj_t **global_keylistp, const cfg_obj_t **control_keylistp) { isc_result_t result; const cfg_obj_t *control_keylist = NULL; const cfg_obj_t *global_keylist = NULL; REQUIRE(global_keylistp != NULL && *global_keylistp == NULL); REQUIRE(control_keylistp != NULL && *control_keylistp == NULL); control_keylist = cfg_tuple_get(control, "keys"); if (!cfg_obj_isvoid(control_keylist) && cfg_list_first(control_keylist) != NULL) { result = cfg_map_get(config, "key", &global_keylist); if (result == ISC_R_SUCCESS) { *global_keylistp = global_keylist; *control_keylistp = control_keylist; } } } static void update_listener(ns_controls_t *cp, controllistener_t **listenerp, const cfg_obj_t *control, const cfg_obj_t *config, isc_sockaddr_t *addr, cfg_aclconfctx_t *aclconfctx, const char *socktext, isc_sockettype_t type) { controllistener_t *listener; const cfg_obj_t *allow; const cfg_obj_t *global_keylist = NULL; const cfg_obj_t *control_keylist = NULL; dns_acl_t *new_acl = NULL; controlkeylist_t keys; isc_result_t result = ISC_R_SUCCESS; for (listener = ISC_LIST_HEAD(cp->listeners); listener != NULL; listener = ISC_LIST_NEXT(listener, link)) if (isc_sockaddr_equal(addr, &listener->address)) break; if (listener == NULL) { *listenerp = NULL; return; } /* * There is already a listener for this sockaddr. * Update the access list and key information. * * First try to deal with the key situation. There are a few * possibilities: * (a) It had an explicit keylist and still has an explicit keylist. * (b) It had an automagic key and now has an explicit keylist. * (c) It had an explicit keylist and now needs an automagic key. * (d) It has an automagic key and still needs the automagic key. * * (c) and (d) are the annoying ones. The caller needs to know * that it should use the automagic configuration for key information * in place of the named.conf configuration. * * XXXDCL There is one other hazard that has not been dealt with, * the problem that if a key change is being caused by a control * channel reload, then the response will be with the new key * and not able to be decrypted by the client. */ if (control != NULL) get_key_info(config, control, &global_keylist, &control_keylist); if (control_keylist != NULL) { INSIST(global_keylist != NULL); ISC_LIST_INIT(keys); result = controlkeylist_fromcfg(control_keylist, listener->mctx, &keys); if (result == ISC_R_SUCCESS) { free_controlkeylist(&listener->keys, listener->mctx); listener->keys = keys; register_keys(control, global_keylist, &listener->keys, listener->mctx, socktext); } } else { free_controlkeylist(&listener->keys, listener->mctx); result = get_rndckey(listener->mctx, &listener->keys); } if (result != ISC_R_SUCCESS && global_keylist != NULL) { /* * This message might be a little misleading since the * "new keys" might in fact be identical to the old ones, * but tracking whether they are identical just for the * sake of avoiding this message would be too much trouble. */ if (control != NULL) cfg_obj_log(control, ns_g_lctx, ISC_LOG_WARNING, "couldn't install new keys for " "command channel %s: %s", socktext, isc_result_totext(result)); else isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_CONTROL, ISC_LOG_WARNING, "couldn't install new keys for " "command channel %s: %s", socktext, isc_result_totext(result)); } /* * Now, keep the old access list unless a new one can be made. */ if (control != NULL && type == isc_sockettype_tcp) { allow = cfg_tuple_get(control, "allow"); result = cfg_acl_fromconfig(allow, config, ns_g_lctx, aclconfctx, listener->mctx, 0, &new_acl); } else { result = dns_acl_any(listener->mctx, &new_acl); } if (control != NULL) { const cfg_obj_t *readonly; readonly = cfg_tuple_get(control, "read-only"); if (!cfg_obj_isvoid(readonly)) listener->readonly = cfg_obj_asboolean(readonly); } if (result == ISC_R_SUCCESS) { dns_acl_detach(&listener->acl); dns_acl_attach(new_acl, &listener->acl); dns_acl_detach(&new_acl); /* XXXDCL say the old acl is still used? */ } else if (control != NULL) cfg_obj_log(control, ns_g_lctx, ISC_LOG_WARNING, "couldn't install new acl for " "command channel %s: %s", socktext, isc_result_totext(result)); else isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_CONTROL, ISC_LOG_WARNING, "couldn't install new acl for " "command channel %s: %s", socktext, isc_result_totext(result)); if (result == ISC_R_SUCCESS && type == isc_sockettype_unix) { isc_uint32_t perm, owner, group; perm = cfg_obj_asuint32(cfg_tuple_get(control, "perm")); owner = cfg_obj_asuint32(cfg_tuple_get(control, "owner")); group = cfg_obj_asuint32(cfg_tuple_get(control, "group")); result = ISC_R_SUCCESS; if (listener->perm != perm || listener->owner != owner || listener->group != group) result = isc_socket_permunix(&listener->address, perm, owner, group); if (result == ISC_R_SUCCESS) { listener->perm = perm; listener->owner = owner; listener->group = group; } else if (control != NULL) cfg_obj_log(control, ns_g_lctx, ISC_LOG_WARNING, "couldn't update ownership/permission for " "command channel %s", socktext); } *listenerp = listener; } static void add_listener(ns_controls_t *cp, controllistener_t **listenerp, const cfg_obj_t *control, const cfg_obj_t *config, isc_sockaddr_t *addr, cfg_aclconfctx_t *aclconfctx, const char *socktext, isc_sockettype_t type) { isc_mem_t *mctx = cp->server->mctx; controllistener_t *listener; const cfg_obj_t *allow; const cfg_obj_t *global_keylist = NULL; const cfg_obj_t *control_keylist = NULL; dns_acl_t *new_acl = NULL; isc_result_t result = ISC_R_SUCCESS; listener = isc_mem_get(mctx, sizeof(*listener)); if (listener == NULL) result = ISC_R_NOMEMORY; if (result == ISC_R_SUCCESS) { listener->mctx = NULL; isc_mem_attach(mctx, &listener->mctx); listener->controls = cp; listener->task = cp->server->task; listener->address = *addr; listener->sock = NULL; listener->listening = ISC_FALSE; listener->exiting = ISC_FALSE; listener->acl = NULL; listener->type = type; listener->perm = 0; listener->owner = 0; listener->group = 0; listener->readonly = ISC_FALSE; ISC_LINK_INIT(listener, link); ISC_LIST_INIT(listener->keys); ISC_LIST_INIT(listener->connections); /* * Make the acl. */ if (control != NULL && type == isc_sockettype_tcp) { allow = cfg_tuple_get(control, "allow"); result = cfg_acl_fromconfig(allow, config, ns_g_lctx, aclconfctx, mctx, 0, &new_acl); } else { result = dns_acl_any(mctx, &new_acl); } } if ((result == ISC_R_SUCCESS) && (control != NULL)) { const cfg_obj_t *readonly; readonly = cfg_tuple_get(control, "read-only"); if (!cfg_obj_isvoid(readonly)) listener->readonly = cfg_obj_asboolean(readonly); } if (result == ISC_R_SUCCESS) { dns_acl_attach(new_acl, &listener->acl); dns_acl_detach(&new_acl); if (config != NULL) get_key_info(config, control, &global_keylist, &control_keylist); if (control_keylist != NULL) { result = controlkeylist_fromcfg(control_keylist, listener->mctx, &listener->keys); if (result == ISC_R_SUCCESS) register_keys(control, global_keylist, &listener->keys, listener->mctx, socktext); } else result = get_rndckey(mctx, &listener->keys); if (result != ISC_R_SUCCESS && control != NULL) cfg_obj_log(control, ns_g_lctx, ISC_LOG_WARNING, "couldn't install keys for " "command channel %s: %s", socktext, isc_result_totext(result)); } if (result == ISC_R_SUCCESS) { int pf = isc_sockaddr_pf(&listener->address); if ((pf == AF_INET && isc_net_probeipv4() != ISC_R_SUCCESS) || #ifdef ISC_PLATFORM_HAVESYSUNH (pf == AF_UNIX && isc_net_probeunix() != ISC_R_SUCCESS) || #endif (pf == AF_INET6 && isc_net_probeipv6() != ISC_R_SUCCESS)) result = ISC_R_FAMILYNOSUPPORT; } if (result == ISC_R_SUCCESS && type == isc_sockettype_unix) isc_socket_cleanunix(&listener->address, ISC_FALSE); if (result == ISC_R_SUCCESS) result = isc_socket_create(ns_g_socketmgr, isc_sockaddr_pf(&listener->address), type, &listener->sock); if (result == ISC_R_SUCCESS) isc_socket_setname(listener->sock, "control", NULL); #ifndef ISC_ALLOW_MAPPED if (result == ISC_R_SUCCESS) isc_socket_ipv6only(listener->sock, ISC_TRUE); #endif if (result == ISC_R_SUCCESS) result = isc_socket_bind(listener->sock, &listener->address, ISC_SOCKET_REUSEADDRESS); if (result == ISC_R_SUCCESS && type == isc_sockettype_unix) { listener->perm = cfg_obj_asuint32(cfg_tuple_get(control, "perm")); listener->owner = cfg_obj_asuint32(cfg_tuple_get(control, "owner")); listener->group = cfg_obj_asuint32(cfg_tuple_get(control, "group")); result = isc_socket_permunix(&listener->address, listener->perm, listener->owner, listener->group); } if (result == ISC_R_SUCCESS) result = control_listen(listener); if (result == ISC_R_SUCCESS) result = control_accept(listener); if (result == ISC_R_SUCCESS) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_CONTROL, ISC_LOG_NOTICE, "command channel listening on %s", socktext); *listenerp = listener; } else { if (listener != NULL) { listener->exiting = ISC_TRUE; free_listener(listener); } if (control != NULL) cfg_obj_log(control, ns_g_lctx, ISC_LOG_WARNING, "couldn't add command channel %s: %s", socktext, isc_result_totext(result)); else isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_CONTROL, ISC_LOG_NOTICE, "couldn't add command channel %s: %s", socktext, isc_result_totext(result)); *listenerp = NULL; } /* XXXDCL return error results? fail hard? */ } isc_result_t ns_controls_configure(ns_controls_t *cp, const cfg_obj_t *config, cfg_aclconfctx_t *aclconfctx) { controllistener_t *listener; controllistenerlist_t new_listeners; const cfg_obj_t *controlslist = NULL; const cfg_listelt_t *element, *element2; char socktext[ISC_SOCKADDR_FORMATSIZE]; ISC_LIST_INIT(new_listeners); /* * Get the list of named.conf 'controls' statements. */ (void)cfg_map_get(config, "controls", &controlslist); /* * Run through the new control channel list, noting sockets that * are already being listened on and moving them to the new list. * * Identifying duplicate addr/port combinations is left to either * the underlying config code, or to the bind attempt getting an * address-in-use error. */ if (controlslist != NULL) { for (element = cfg_list_first(controlslist); element != NULL; element = cfg_list_next(element)) { const cfg_obj_t *controls; const cfg_obj_t *inetcontrols = NULL; controls = cfg_listelt_value(element); (void)cfg_map_get(controls, "inet", &inetcontrols); if (inetcontrols == NULL) continue; for (element2 = cfg_list_first(inetcontrols); element2 != NULL; element2 = cfg_list_next(element2)) { const cfg_obj_t *control; const cfg_obj_t *obj; isc_sockaddr_t addr; /* * The parser handles BIND 8 configuration file * syntax, so it allows unix phrases as well * inet phrases with no keys{} clause. */ control = cfg_listelt_value(element2); obj = cfg_tuple_get(control, "address"); addr = *cfg_obj_assockaddr(obj); if (isc_sockaddr_getport(&addr) == 0) isc_sockaddr_setport(&addr, NS_CONTROL_PORT); isc_sockaddr_format(&addr, socktext, sizeof(socktext)); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_CONTROL, ISC_LOG_DEBUG(9), "processing control channel %s", socktext); update_listener(cp, &listener, control, config, &addr, aclconfctx, socktext, isc_sockettype_tcp); if (listener != NULL) /* * Remove the listener from the old * list, so it won't be shut down. */ ISC_LIST_UNLINK(cp->listeners, listener, link); else /* * This is a new listener. */ add_listener(cp, &listener, control, config, &addr, aclconfctx, socktext, isc_sockettype_tcp); if (listener != NULL) ISC_LIST_APPEND(new_listeners, listener, link); } } for (element = cfg_list_first(controlslist); element != NULL; element = cfg_list_next(element)) { const cfg_obj_t *controls; const cfg_obj_t *unixcontrols = NULL; controls = cfg_listelt_value(element); (void)cfg_map_get(controls, "unix", &unixcontrols); if (unixcontrols == NULL) continue; for (element2 = cfg_list_first(unixcontrols); element2 != NULL; element2 = cfg_list_next(element2)) { const cfg_obj_t *control; const cfg_obj_t *path; isc_sockaddr_t addr; isc_result_t result; /* * The parser handles BIND 8 configuration file * syntax, so it allows unix phrases as well * inet phrases with no keys{} clause. */ control = cfg_listelt_value(element2); path = cfg_tuple_get(control, "path"); result = isc_sockaddr_frompath(&addr, cfg_obj_asstring(path)); if (result != ISC_R_SUCCESS) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_CONTROL, ISC_LOG_DEBUG(9), "control channel '%s': %s", cfg_obj_asstring(path), isc_result_totext(result)); continue; } isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_CONTROL, ISC_LOG_DEBUG(9), "processing control channel '%s'", cfg_obj_asstring(path)); update_listener(cp, &listener, control, config, &addr, aclconfctx, cfg_obj_asstring(path), isc_sockettype_unix); if (listener != NULL) /* * Remove the listener from the old * list, so it won't be shut down. */ ISC_LIST_UNLINK(cp->listeners, listener, link); else /* * This is a new listener. */ add_listener(cp, &listener, control, config, &addr, aclconfctx, cfg_obj_asstring(path), isc_sockettype_unix); if (listener != NULL) ISC_LIST_APPEND(new_listeners, listener, link); } } } else { int i; for (i = 0; i < 2; i++) { isc_sockaddr_t addr; if (i == 0) { struct in_addr localhost; if (isc_net_probeipv4() != ISC_R_SUCCESS) continue; localhost.s_addr = htonl(INADDR_LOOPBACK); isc_sockaddr_fromin(&addr, &localhost, 0); } else { if (isc_net_probeipv6() != ISC_R_SUCCESS) continue; isc_sockaddr_fromin6(&addr, &in6addr_loopback, 0); } isc_sockaddr_setport(&addr, NS_CONTROL_PORT); isc_sockaddr_format(&addr, socktext, sizeof(socktext)); update_listener(cp, &listener, NULL, NULL, &addr, NULL, socktext, isc_sockettype_tcp); if (listener != NULL) /* * Remove the listener from the old * list, so it won't be shut down. */ ISC_LIST_UNLINK(cp->listeners, listener, link); else /* * This is a new listener. */ add_listener(cp, &listener, NULL, NULL, &addr, NULL, socktext, isc_sockettype_tcp); if (listener != NULL) ISC_LIST_APPEND(new_listeners, listener, link); } } /* * ns_control_shutdown() will stop whatever is on the global * listeners list, which currently only has whatever sockaddrs * were in the previous configuration (if any) that do not * remain in the current configuration. */ controls_shutdown(cp); /* * Put all of the valid listeners on the listeners list. * Anything already on listeners in the process of shutting * down will be taken care of by listen_done(). */ ISC_LIST_APPENDLIST(cp->listeners, new_listeners, link); return (ISC_R_SUCCESS); } isc_result_t ns_controls_create(ns_server_t *server, ns_controls_t **ctrlsp) { isc_mem_t *mctx = server->mctx; isc_result_t result; ns_controls_t *controls = isc_mem_get(mctx, sizeof(*controls)); if (controls == NULL) return (ISC_R_NOMEMORY); controls->server = server; ISC_LIST_INIT(controls->listeners); controls->shuttingdown = ISC_FALSE; controls->symtab = NULL; result = isccc_cc_createsymtab(&controls->symtab); if (result != ISC_R_SUCCESS) { isc_mem_put(server->mctx, controls, sizeof(*controls)); return (result); } *ctrlsp = controls; return (ISC_R_SUCCESS); } void ns_controls_destroy(ns_controls_t **ctrlsp) { ns_controls_t *controls = *ctrlsp; REQUIRE(ISC_LIST_EMPTY(controls->listeners)); isccc_symtab_destroy(&controls->symtab); isc_mem_put(controls->server->mctx, controls, sizeof(*controls)); *ctrlsp = NULL; } bind9-9.11.3+dfsg/bin/named/convertxsl.pl000077500000000000000000000022311325250447100201350ustar00rootroot00000000000000#!/usr/bin/env perl # # Copyright (C) 2006-2008, 2012, 2014, 2016 Internet Systems Consortium, Inc. ("ISC") # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. # $Id: convertxsl.pl,v 1.14 2008/07/17 23:43:26 jinmei Exp $ use strict; use warnings; my $rev = '$Id: convertxsl.pl,v 1.14 2008/07/17 23:43:26 jinmei Exp $'; $rev =~ s/\$//g; $rev =~ s/,v//g; $rev =~ s/Id: //; my $xsl = "unknown"; my $lines = ''; while (<>) { chomp; # pickout the id for comment. $xsl = $_ if (//); # convert Id string to a form not recognisable by cvs. $_ =~ s///; s/[\ \t]+/ /g; s/\>\ \\.*//; $xsl =~ s/,v//; print "/*\n * Generated by $rev \n * From $xsl\n */\n"; print 'static char xslmsg[] =',"\n"; print $lines; print ';', "\n"; bind9-9.11.3+dfsg/bin/named/fuzz.c000066400000000000000000000240721325250447100165370ustar00rootroot00000000000000/* * Copyright (C) 2016 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "config.h" #include #ifdef ENABLE_AFL #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifndef __AFL_LOOP #error To use American Fuzzy Lop you have to set CC to afl-clang-fast!!! #endif /* * We are using pthreads directly because we might be using it with unthreaded * version of BIND, where all thread functions are mocks. Since AFL for now only * works on Linux it's not a problem. */ static pthread_cond_t cond; static pthread_mutex_t mutex; static isc_boolean_t ready; static void * fuzz_main_client(void *arg) { char *host; char *port; struct sockaddr_in servaddr; int sockfd; int loop; void *buf; UNUSED(arg); /* * Parse named -A argument in the "address:port" syntax. Due to * the syntax used, this only supports IPv4 addresses. */ host = strdup(ns_g_fuzz_named_addr); RUNTIME_CHECK(host != NULL); port = strchr(host, ':'); RUNTIME_CHECK(port != NULL); *port = 0; ++port; memset(&servaddr, 0, sizeof (servaddr)); servaddr.sin_family = AF_INET; RUNTIME_CHECK(inet_pton(AF_INET, host, &servaddr.sin_addr) == 1); servaddr.sin_port = htons(atoi(port)); free(host); /* Wait for named to start. */ while (!ns_g_run_done) { usleep(10000); } sockfd = socket(AF_INET, SOCK_DGRAM, 0); RUNTIME_CHECK(sockfd != -1); buf = malloc(65536); RUNTIME_CHECK(buf != NULL); loop = 100000; while (loop--) { ssize_t length; length = read(0, buf, 65536); if (length <= 0) { usleep(1000000); continue; } if (length > 4096) { if (getenv("AFL_CMIN")) { ns_server_flushonshutdown(ns_g_server, ISC_FALSE); isc_app_shutdown(); return (NULL); } raise(SIGSTOP); continue; } RUNTIME_CHECK(pthread_mutex_lock(&mutex) == ISC_R_SUCCESS); ready = ISC_FALSE; ssize_t sent; sent = sendto(sockfd, buf, length, 0, (struct sockaddr *) &servaddr, sizeof(servaddr)); RUNTIME_CHECK(sent == length); /* unclog */ recvfrom(sockfd, buf, 65536, MSG_DONTWAIT, NULL, NULL); while (!ready) pthread_cond_wait(&cond, &mutex); RUNTIME_CHECK(pthread_mutex_unlock(&mutex) == ISC_R_SUCCESS); } free(buf); close(sockfd); ns_server_flushonshutdown(ns_g_server, ISC_FALSE); isc_app_shutdown(); return (NULL); } static void * fuzz_main_resolver(void *arg) { char *shost, *sport, *rhost, *rport; /* Query for A? aaaaaaaaaa.example. */ char respacket[] = "\0\0\1 \0\1\0\0\0\0\0\0\naaaaaaaaaa\7example\0\0\1\0\1"; struct sockaddr_in servaddr, recaddr, recvaddr; int sockfd; int listenfd; int loop; char *buf, *rbuf; UNUSED(arg); /* * Parse named -A argument in the "laddress:sport:raddress:rport" * syntax. Due to the syntax used, this only supports IPv4 addresses. */ shost = strdup(ns_g_fuzz_named_addr); RUNTIME_CHECK(shost != NULL); sport = strchr(shost, ':'); RUNTIME_CHECK(sport != NULL); *sport = 0; sport++; rhost = strchr(sport, ':'); RUNTIME_CHECK(rhost != NULL); *rhost = 0; rhost++; rport = strchr(rhost, ':'); RUNTIME_CHECK(rport != NULL); *rport = 0; rport++; memset(&servaddr, 0, sizeof (servaddr)); servaddr.sin_family = AF_INET; RUNTIME_CHECK(inet_pton(AF_INET, shost, &servaddr.sin_addr) == 1); servaddr.sin_port = htons(atoi(sport)); memset(&recaddr, 0, sizeof (recaddr)); recaddr.sin_family = AF_INET; RUNTIME_CHECK(inet_pton(AF_INET, rhost, &recaddr.sin_addr) == 1); recaddr.sin_port = htons(atoi(rport)); free(shost); /* Wait for named to start */ while (!ns_g_run_done) { usleep(10000); } sockfd = socket(AF_INET, SOCK_DGRAM, 0); RUNTIME_CHECK(sockfd != -1); listenfd = socket(AF_INET, SOCK_DGRAM, 0); RUNTIME_CHECK(listenfd != -1); RUNTIME_CHECK(bind(listenfd, (struct sockaddr *)&recaddr, sizeof(struct sockaddr_in)) == 0); buf = malloc(65536); rbuf = malloc(65536); RUNTIME_CHECK(buf != NULL); RUNTIME_CHECK(rbuf != NULL); loop = 100000; while (loop--) { ssize_t length; memset(buf, 0, 16); length = read(0, buf, 65536); if (length <= 0) { usleep(1000000); continue; } if (length > 4096) { if (getenv("AFL_CMIN")) { ns_server_flushonshutdown(ns_g_server, ISC_FALSE); isc_app_shutdown(); return (NULL); } raise(SIGSTOP); continue; } if (length < 16) { length = 16; } RUNTIME_CHECK(pthread_mutex_lock(&mutex) == ISC_R_SUCCESS); ready = ISC_FALSE; ssize_t sent; /* Randomize query ID. */ int id = random(); respacket[0] = id >> 8; respacket[1] = id & 0xff; /* flush */ socklen_t socklen = sizeof(recvaddr); sent = recvfrom(listenfd, rbuf, 65536, MSG_DONTWAIT, (struct sockaddr *) &recvaddr, &socklen); sent = sendto(sockfd, respacket, sizeof(respacket), 0, (struct sockaddr *) &servaddr, sizeof(servaddr)); RUNTIME_CHECK(sent == sizeof(respacket)); socklen = sizeof(recvaddr); sent = recvfrom(listenfd, rbuf, 65536, 0, (struct sockaddr *) &recvaddr, &socklen); RUNTIME_CHECK(sent > 0); /* Copy QID and set QR so that response is always processed. */ buf[0] = rbuf[0]; buf[1] = rbuf[1]; buf[2] |= 0x80; sent = sendto(listenfd, buf, length, 0, (struct sockaddr *) &recvaddr, sizeof(recvaddr)); RUNTIME_CHECK(sent == length); /* We might get additional questions here (e.g. for CNAME). */ for (;;) { fd_set fds; struct timeval tv; int rv; int max; FD_ZERO(&fds); FD_SET(listenfd, &fds); FD_SET(sockfd, &fds); tv.tv_sec = 10; tv.tv_usec = 0; max = (listenfd > sockfd ? listenfd : sockfd)+1; rv = select(max, &fds, NULL, NULL, &tv); RUNTIME_CHECK(rv > 0); if (FD_ISSET(sockfd, &fds)) { /* It's the reply, we're done. */ recvfrom(sockfd, buf, 65536, 0, NULL, NULL); break; } /* * We've got additional question (eg. cname chain) * We are bouncing it - setting QR flag and NOERROR * rcode and sending it back. */ length = recvfrom(listenfd, buf, 65536, 0, (struct sockaddr *) &recvaddr, &socklen); buf[2] |= 0x80; buf[3] &= 0xF0; sent = sendto(listenfd, buf, length, 0, (struct sockaddr *) &recvaddr, sizeof(recvaddr)); RUNTIME_CHECK(sent == length); } while (!ready) pthread_cond_wait(&cond, &mutex); RUNTIME_CHECK(pthread_mutex_unlock(&mutex) == 0); } free(buf); close(sockfd); ns_server_flushonshutdown(ns_g_server, ISC_FALSE); isc_app_shutdown(); /* * It's here just for the signature, that's how AFL detects if it's * a 'persistent mode' binary. */ __AFL_LOOP(0); return (NULL); } static void * fuzz_main_tcp(void *arg) { char *host; char *port; struct sockaddr_in servaddr; int sockfd; char *buf; int loop; UNUSED(arg); /* * Parse named -A argument in the "address:port" syntax. Due to * the syntax used, this only supports IPv4 addresses. */ host = strdup(ns_g_fuzz_named_addr); RUNTIME_CHECK(host != NULL); port = strchr(host, ':'); RUNTIME_CHECK(port != NULL); *port = 0; ++port; memset(&servaddr, 0, sizeof (servaddr)); servaddr.sin_family = AF_INET; RUNTIME_CHECK(inet_pton(AF_INET, host, &servaddr.sin_addr) == 1); servaddr.sin_port = htons(atoi(port)); free(host); /* Wait for named to start */ while (!ns_g_run_done) { usleep(10000); } buf = malloc(65539); RUNTIME_CHECK(buf != NULL); loop = 100000; while (loop--) { ssize_t length; if (ns_g_fuzz_type == ns_fuzz_tcpclient) { /* * To fuzz TCP client we have to put length at * the start of packet. */ length = read(0, buf+2, 65535); buf[0] = length >> 8; buf[1] = length & 0xff; length += 2; } else { length = read(0, buf, 65535); } if (length <= 0) { usleep(1000000); continue; } if (ns_g_fuzz_type == ns_fuzz_http) { /* * This guarantees that the request will be processed. */ buf[length++]='\r'; buf[length++]='\n'; buf[length++]='\r'; buf[length++]='\n'; } RUNTIME_CHECK(pthread_mutex_lock(&mutex) == ISC_R_SUCCESS); ready = ISC_FALSE; ssize_t sent; int yes = 1; int r; sockfd = socket(AF_INET, SOCK_STREAM, 0); RUNTIME_CHECK(sockfd != -1); RUNTIME_CHECK(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == 0); do { r = connect(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr)); } while (r != 0); sent = write(sockfd, buf, length); RUNTIME_CHECK(sent == length); close(sockfd); /* unclog */ recvfrom(sockfd, buf, 65537, MSG_DONTWAIT, NULL, NULL); while (!ready) pthread_cond_wait(&cond, &mutex); RUNTIME_CHECK(pthread_mutex_unlock(&mutex) == ISC_R_SUCCESS); } free(buf); close(sockfd); ns_server_flushonshutdown(ns_g_server, ISC_FALSE); isc_app_shutdown(); return (NULL); } #endif /* ENABLE_AFL */ void named_fuzz_notify(void) { #ifdef ENABLE_AFL if (getenv("AFL_CMIN")) { ns_server_flushonshutdown(ns_g_server, ISC_FALSE); isc_app_shutdown(); return; } raise(SIGSTOP); RUNTIME_CHECK(pthread_mutex_lock(&mutex) == 0); ready = ISC_TRUE; RUNTIME_CHECK(pthread_cond_signal(&cond) == 0); RUNTIME_CHECK(pthread_mutex_unlock(&mutex) == 0); #endif /* ENABLE_AFL */ } void named_fuzz_setup(void) { #ifdef ENABLE_AFL if (getenv("__AFL_PERSISTENT") || getenv("AFL_CMIN")) { pthread_t thread; void *(fn) = NULL; switch (ns_g_fuzz_type) { case ns_fuzz_client: fn = fuzz_main_client; break; case ns_fuzz_http: case ns_fuzz_tcpclient: case ns_fuzz_rndc: fn = fuzz_main_tcp; break; case ns_fuzz_resolver: fn = fuzz_main_resolver; break; default: RUNTIME_CHECK(fn != NULL); } RUNTIME_CHECK(pthread_mutex_init(&mutex, NULL) == 0); RUNTIME_CHECK(pthread_cond_init(&cond, NULL) == 0); RUNTIME_CHECK(pthread_create(&thread, NULL, fn, NULL) == 0); } #endif /* ENABLE_AFL */ } bind9-9.11.3+dfsg/bin/named/geoip.c000066400000000000000000000065471325250447100166530ustar00rootroot00000000000000/* * Copyright (C) 2013, 2014, 2016 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /*! \file */ #include #include #include #include #include #ifdef HAVE_GEOIP static dns_geoip_databases_t geoip_table = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; static void init_geoip_db(GeoIP **dbp, GeoIPDBTypes edition, GeoIPDBTypes fallback, GeoIPOptions method, const char *name) { char *info; GeoIP *db; REQUIRE(dbp != NULL); db = *dbp; if (db != NULL) { GeoIP_delete(db); db = *dbp = NULL; } if (! GeoIP_db_avail(edition)) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_INFO, "GeoIP %s (type %d) DB not available", name, edition); goto fail; } isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_INFO, "initializing GeoIP %s (type %d) DB", name, edition); db = GeoIP_open_type(edition, method); if (db == NULL) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, "failed to initialize GeoIP %s (type %d) DB%s", name, edition, fallback == 0 ? "geoip matches using this database will fail" : ""); goto fail; } info = GeoIP_database_info(db); if (info != NULL) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_INFO, "%s", info); free(info); } *dbp = db; return; fail: if (fallback != 0) init_geoip_db(dbp, fallback, 0, method, name); } #endif /* HAVE_GEOIP */ void ns_geoip_init(void) { #ifndef HAVE_GEOIP return; #else GeoIP_cleanup(); if (ns_g_geoip == NULL) ns_g_geoip = &geoip_table; #endif } void ns_geoip_load(char *dir) { #ifndef HAVE_GEOIP UNUSED(dir); return; #else GeoIPOptions method; #ifdef _WIN32 method = GEOIP_STANDARD; #else method = GEOIP_MMAP_CACHE; #endif ns_geoip_init(); if (dir != NULL) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_INFO, "using \"%s\" as GeoIP directory", dir); GeoIP_setup_custom_directory(dir); } init_geoip_db(&ns_g_geoip->country_v4, GEOIP_COUNTRY_EDITION, 0, method, "Country (IPv4)"); #ifdef HAVE_GEOIP_V6 init_geoip_db(&ns_g_geoip->country_v6, GEOIP_COUNTRY_EDITION_V6, 0, method, "Country (IPv6)"); #endif init_geoip_db(&ns_g_geoip->city_v4, GEOIP_CITY_EDITION_REV1, GEOIP_CITY_EDITION_REV0, method, "City (IPv4)"); #if defined(HAVE_GEOIP_V6) && defined(HAVE_GEOIP_CITY_V6) init_geoip_db(&ns_g_geoip->city_v6, GEOIP_CITY_EDITION_REV1_V6, GEOIP_CITY_EDITION_REV0_V6, method, "City (IPv6)"); #endif init_geoip_db(&ns_g_geoip->region, GEOIP_REGION_EDITION_REV1, GEOIP_REGION_EDITION_REV0, method, "Region"); init_geoip_db(&ns_g_geoip->isp, GEOIP_ISP_EDITION, 0, method, "ISP"); init_geoip_db(&ns_g_geoip->org, GEOIP_ORG_EDITION, 0, method, "Org"); init_geoip_db(&ns_g_geoip->as, GEOIP_ASNUM_EDITION, 0, method, "AS"); init_geoip_db(&ns_g_geoip->domain, GEOIP_DOMAIN_EDITION, 0, method, "Domain"); init_geoip_db(&ns_g_geoip->netspeed, GEOIP_NETSPEED_EDITION, 0, method, "NetSpeed"); #endif /* HAVE_GEOIP */ } bind9-9.11.3+dfsg/bin/named/include/000077500000000000000000000000001325250447100170135ustar00rootroot00000000000000bind9-9.11.3+dfsg/bin/named/include/dlz/000077500000000000000000000000001325250447100176045ustar00rootroot00000000000000bind9-9.11.3+dfsg/bin/named/include/dlz/dlz_dlopen_driver.h000066400000000000000000000007611325250447100234660ustar00rootroot00000000000000/* * Copyright (C) 2011, 2016 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* $Id: dlz_dlopen_driver.h,v 1.4 2011/03/17 09:25:53 fdupont Exp $ */ #ifndef DLZ_DLOPEN_DRIVER_H #define DLZ_DLOPEN_DRIVER_H isc_result_t dlz_dlopen_init(isc_mem_t *mctx); void dlz_dlopen_clear(void); #endif bind9-9.11.3+dfsg/bin/named/include/named/000077500000000000000000000000001325250447100200775ustar00rootroot00000000000000bind9-9.11.3+dfsg/bin/named/include/named/builtin.h000066400000000000000000000010431325250447100217140ustar00rootroot00000000000000/* * Copyright (C) 2001, 2004, 2005, 2007, 2016 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* $Id: builtin.h,v 1.6 2007/06/19 23:46:59 tbox Exp $ */ #ifndef NAMED_BUILTIN_H #define NAMED_BUILTIN_H 1 /*! \file */ #include isc_result_t ns_builtin_init(void); void ns_builtin_deinit(void); #endif /* NAMED_BUILTIN_H */ bind9-9.11.3+dfsg/bin/named/include/named/client.h000066400000000000000000000271701325250447100215350ustar00rootroot00000000000000/* * Copyright (C) 1999-2009, 2011-2018 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* $Id: client.h,v 1.96 2012/01/31 23:47:31 tbox Exp $ */ #ifndef NAMED_CLIENT_H #define NAMED_CLIENT_H 1 /***** ***** Module Info *****/ /*! \file * \brief * This module defines two objects, ns_client_t and ns_clientmgr_t. * * An ns_client_t object handles incoming DNS requests from clients * on a given network interface. * * Each ns_client_t object can handle only one TCP connection or UDP * request at a time. Therefore, several ns_client_t objects are * typically created to serve each network interface, e.g., one * for handling TCP requests and a few (one per CPU) for handling * UDP requests. * * Incoming requests are classified as queries, zone transfer * requests, update requests, notify requests, etc, and handed off * to the appropriate request handler. When the request has been * fully handled (which can be much later), the ns_client_t must be * notified of this by calling one of the following functions * exactly once in the context of its task: * \code * ns_client_send() (sending a non-error response) * ns_client_sendraw() (sending a raw response) * ns_client_error() (sending an error response) * ns_client_next() (sending no response) *\endcode * This will release any resources used by the request and * and allow the ns_client_t to listen for the next request. * * A ns_clientmgr_t manages a number of ns_client_t objects. * New ns_client_t objects are created by calling * ns_clientmgr_createclients(). They are destroyed by * destroying their manager. */ /*** *** Imports ***/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include /*** *** Types ***/ /*% nameserver client structure */ struct ns_client { unsigned int magic; isc_mem_t * mctx; ns_clientmgr_t * manager; int state; int newstate; int naccepts; int nreads; int nsends; int nrecvs; int nupdates; int nctls; int references; isc_boolean_t needshutdown; /* * Used by clienttest to get * the client to go from * inactive to free state * by shutting down the * client's task. */ unsigned int attributes; isc_task_t * task; dns_view_t * view; dns_dispatch_t * dispatch; isc_socket_t * udpsocket; isc_socket_t * tcplistener; isc_socket_t * tcpsocket; unsigned char * tcpbuf; dns_tcpmsg_t tcpmsg; isc_boolean_t tcpmsg_valid; isc_timer_t * timer; isc_timer_t * delaytimer; isc_boolean_t timerset; dns_message_t * message; isc_socketevent_t * sendevent; isc_socketevent_t * recvevent; unsigned char * recvbuf; dns_rdataset_t * opt; isc_uint16_t udpsize; isc_uint16_t extflags; isc_int16_t ednsversion; /* -1 noedns */ void (*next)(ns_client_t *); void (*shutdown)(void *arg, isc_result_t result); void *shutdown_arg; ns_query_t query; isc_time_t requesttime; isc_stdtime_t now; isc_time_t tnow; dns_name_t signername; /*%< [T]SIG key name */ dns_name_t * signer; /*%< NULL if not valid sig */ isc_boolean_t mortal; /*%< Die after handling request */ isc_boolean_t pipelined; /*%< TCP queries not in sequence */ isc_quota_t *tcpquota; isc_quota_t *recursionquota; ns_interface_t *interface; isc_sockaddr_t peeraddr; isc_boolean_t peeraddr_valid; isc_netaddr_t destaddr; isc_sockaddr_t destsockaddr; isc_netaddr_t ecs_addr; /*%< EDNS client subnet */ isc_uint8_t ecs_addrlen; isc_uint8_t ecs_scope; struct in6_pktinfo pktinfo; isc_dscp_t dscp; isc_event_t ctlevent; #ifdef ALLOW_FILTER_AAAA dns_aaaa_t filter_aaaa; #endif /*% * Information about recent FORMERR response(s), for * FORMERR loop avoidance. This is separate for each * client object rather than global only to avoid * the need for locking. */ struct { isc_sockaddr_t addr; isc_stdtime_t time; dns_messageid_t id; } formerrcache; ISC_LINK(ns_client_t) link; ISC_LINK(ns_client_t) rlink; ISC_QLINK(ns_client_t) ilink; unsigned char cookie[8]; isc_uint32_t expire; unsigned char *keytag; isc_uint16_t keytag_len; }; typedef ISC_QUEUE(ns_client_t) client_queue_t; typedef ISC_LIST(ns_client_t) client_list_t; #define NS_CLIENT_MAGIC ISC_MAGIC('N','S','C','c') #define NS_CLIENT_VALID(c) ISC_MAGIC_VALID(c, NS_CLIENT_MAGIC) #define NS_CLIENTATTR_TCP 0x0001 #define NS_CLIENTATTR_RA 0x0002 /*%< Client gets recursive service */ #define NS_CLIENTATTR_PKTINFO 0x0004 /*%< pktinfo is valid */ #define NS_CLIENTATTR_MULTICAST 0x0008 /*%< recv'd from multicast */ #define NS_CLIENTATTR_WANTDNSSEC 0x0010 /*%< include dnssec records */ #define NS_CLIENTATTR_WANTNSID 0x0020 /*%< include nameserver ID */ #ifdef ALLOW_FILTER_AAAA #define NS_CLIENTATTR_FILTER_AAAA 0x0040 /*%< suppress AAAAs */ #define NS_CLIENTATTR_FILTER_AAAA_RC 0x0080 /*%< recursing for A against AAAA */ #endif #define NS_CLIENTATTR_WANTAD 0x0100 /*%< want AD in response if possible */ #define NS_CLIENTATTR_WANTCOOKIE 0x0200 /*%< return a COOKIE */ #define NS_CLIENTATTR_HAVECOOKIE 0x0400 /*%< has a valid COOKIE */ #define NS_CLIENTATTR_WANTEXPIRE 0x0800 /*%< return seconds to expire */ #define NS_CLIENTATTR_HAVEEXPIRE 0x1000 /*%< return seconds to expire */ #define NS_CLIENTATTR_WANTOPT 0x2000 /*%< add opt to reply */ #define NS_CLIENTATTR_HAVEECS 0x4000 /*%< received an ECS option */ #define NS_CLIENTATTR_NOSETFC 0x8000 /*%< don't set servfail cache */ /* * Flag to use with the SERVFAIL cache to indicate * that a query had the CD bit set. */ #define NS_FAILCACHE_CD 0x01 extern unsigned int ns_client_requests; /*** *** Functions ***/ /*% * Note! These ns_client_ routines MUST be called ONLY from the client's * task in order to ensure synchronization. */ void ns_client_send(ns_client_t *client); /*% * Finish processing the current client request and * send client->message as a response. * \brief * Note! These ns_client_ routines MUST be called ONLY from the client's * task in order to ensure synchronization. */ void ns_client_sendraw(ns_client_t *client, dns_message_t *msg); /*% * Finish processing the current client request and * send msg as a response using client->message->id for the id. */ void ns_client_error(ns_client_t *client, isc_result_t result); /*% * Finish processing the current client request and return * an error response to the client. The error response * will have an RCODE determined by 'result'. */ void ns_client_next(ns_client_t *client, isc_result_t result); /*% * Finish processing the current client request, * return no response to the client. */ isc_boolean_t ns_client_shuttingdown(ns_client_t *client); /*% * Return ISC_TRUE iff the client is currently shutting down. */ void ns_client_attach(ns_client_t *source, ns_client_t **target); /*% * Attach '*targetp' to 'source'. */ void ns_client_detach(ns_client_t **clientp); /*% * Detach '*clientp' from its client. */ isc_result_t ns_client_replace(ns_client_t *client); /*% * Try to replace the current client with a new one, so that the * current one can go off and do some lengthy work without * leaving the dispatch/socket without service. */ void ns_client_settimeout(ns_client_t *client, unsigned int seconds); /*% * Set a timer in the client to go off in the specified amount of time. */ isc_result_t ns_clientmgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr, isc_timermgr_t *timermgr, ns_clientmgr_t **managerp); /*% * Create a client manager. */ void ns_clientmgr_destroy(ns_clientmgr_t **managerp); /*% * Destroy a client manager and all ns_client_t objects * managed by it. */ isc_result_t ns_clientmgr_createclients(ns_clientmgr_t *manager, unsigned int n, ns_interface_t *ifp, isc_boolean_t tcp); /*% * Create up to 'n' clients listening on interface 'ifp'. * If 'tcp' is ISC_TRUE, the clients will listen for TCP connections, * otherwise for UDP requests. */ isc_sockaddr_t * ns_client_getsockaddr(ns_client_t *client); /*% * Get the socket address of the client whose request is * currently being processed. */ isc_sockaddr_t * ns_client_getdestaddr(ns_client_t *client); /*%< * Get the destination address (server) for the request that is * currently being processed. */ isc_result_t ns_client_checkaclsilent(ns_client_t *client, isc_netaddr_t *netaddr, dns_acl_t *acl, isc_boolean_t default_allow); /*% * Convenience function for client request ACL checking. * * Check the current client request against 'acl'. If 'acl' * is NULL, allow the request iff 'default_allow' is ISC_TRUE. * If netaddr is NULL, check the ACL against client->peeraddr; * otherwise check it against netaddr. * * Notes: *\li This is appropriate for checking allow-update, * allow-query, allow-transfer, etc. It is not appropriate * for checking the blackhole list because we treat positive * matches as "allow" and negative matches as "deny"; in * the case of the blackhole list this would be backwards. * * Requires: *\li 'client' points to a valid client. *\li 'netaddr' points to a valid address, or is NULL. *\li 'acl' points to a valid ACL, or is NULL. * * Returns: *\li ISC_R_SUCCESS if the request should be allowed * \li DNS_R_REFUSED if the request should be denied *\li No other return values are possible. */ isc_result_t ns_client_checkacl(ns_client_t *client, isc_sockaddr_t *sockaddr, const char *opname, dns_acl_t *acl, isc_boolean_t default_allow, int log_level); /*% * Like ns_client_checkaclsilent, except the outcome of the check is * logged at log level 'log_level' if denied, and at debug 3 if approved. * Log messages will refer to the request as an 'opname' request. * * Requires: *\li 'client' points to a valid client. *\li 'sockaddr' points to a valid address, or is NULL. *\li 'acl' points to a valid ACL, or is NULL. *\li 'opname' points to a null-terminated string. */ void ns_client_log(ns_client_t *client, isc_logcategory_t *category, isc_logmodule_t *module, int level, const char *fmt, ...) ISC_FORMAT_PRINTF(5, 6); void ns_client_logv(ns_client_t *client, isc_logcategory_t *category, isc_logmodule_t *module, int level, const char *fmt, va_list ap) ISC_FORMAT_PRINTF(5, 0); void ns_client_aclmsg(const char *msg, dns_name_t *name, dns_rdatatype_t type, dns_rdataclass_t rdclass, char *buf, size_t len); #define NS_CLIENT_ACLMSGSIZE(x) \ (DNS_NAME_FORMATSIZE + DNS_RDATATYPE_FORMATSIZE + \ DNS_RDATACLASS_FORMATSIZE + sizeof(x) + sizeof("'/'")) void ns_client_recursing(ns_client_t *client); /*% * Add client to end of th recursing list. */ void ns_client_killoldestquery(ns_client_t *client); /*% * Kill the oldest recursive query (recursing list head). */ void ns_client_dumprecursing(FILE *f, ns_clientmgr_t *manager); /*% * Dump the outstanding recursive queries to 'f'. */ void ns_client_qnamereplace(ns_client_t *client, dns_name_t *name); /*% * Replace the qname. */ isc_boolean_t ns_client_isself(dns_view_t *myview, dns_tsigkey_t *mykey, isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr, dns_rdataclass_t rdclass, void *arg); /*% * Isself callback. */ isc_result_t ns_client_sourceip(dns_clientinfo_t *ci, isc_sockaddr_t **addrp); isc_result_t ns_client_addopt(ns_client_t *client, dns_message_t *message, dns_rdataset_t **opt); #endif /* NAMED_CLIENT_H */ bind9-9.11.3+dfsg/bin/named/include/named/config.h000066400000000000000000000037421325250447100215230ustar00rootroot00000000000000/* * Copyright (C) 2001, 2002, 2004-2007, 2009, 2013, 2016 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* $Id: config.h,v 1.16 2009/06/11 23:47:55 tbox Exp $ */ #ifndef NAMED_CONFIG_H #define NAMED_CONFIG_H 1 /*! \file */ #include #include #include isc_result_t ns_config_parsedefaults(cfg_parser_t *parser, cfg_obj_t **conf); isc_result_t ns_config_get(cfg_obj_t const * const *maps, const char *name, const cfg_obj_t **obj); isc_result_t ns_checknames_get(const cfg_obj_t **maps, const char *name, const cfg_obj_t **obj); int ns_config_listcount(const cfg_obj_t *list); isc_result_t ns_config_getclass(const cfg_obj_t *classobj, dns_rdataclass_t defclass, dns_rdataclass_t *classp); isc_result_t ns_config_gettype(const cfg_obj_t *typeobj, dns_rdatatype_t deftype, dns_rdatatype_t *typep); dns_zonetype_t ns_config_getzonetype(const cfg_obj_t *zonetypeobj); isc_result_t ns_config_getiplist(const cfg_obj_t *config, const cfg_obj_t *list, in_port_t defport, isc_mem_t *mctx, isc_sockaddr_t **addrsp, isc_dscp_t **dscpsp, isc_uint32_t *countp); void ns_config_putiplist(isc_mem_t *mctx, isc_sockaddr_t **addrsp, isc_dscp_t **dscpsp, isc_uint32_t count); isc_result_t ns_config_getipandkeylist(const cfg_obj_t *config, const cfg_obj_t *list, isc_mem_t *mctx, dns_ipkeylist_t *ipkl); isc_result_t ns_config_getport(const cfg_obj_t *config, in_port_t *portp); isc_result_t ns_config_getkeyalgorithm(const char *str, dns_name_t **name, isc_uint16_t *digestbits); isc_result_t ns_config_getkeyalgorithm2(const char *str, dns_name_t **name, unsigned int *typep, isc_uint16_t *digestbits); isc_result_t ns_config_getdscp(const cfg_obj_t *config, isc_dscp_t *dscpp); #endif /* NAMED_CONFIG_H */ bind9-9.11.3+dfsg/bin/named/include/named/control.h000066400000000000000000000057051325250447100217370ustar00rootroot00000000000000/* * Copyright (C) 2001-2007, 2009-2012, 2014-2016 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* $Id: control.h,v 1.38 2012/01/31 23:47:31 tbox Exp $ */ #ifndef NAMED_CONTROL_H #define NAMED_CONTROL_H 1 /*! \file * \brief * The name server command channel. */ #include #include #include #define NS_CONTROL_PORT 953 #define NS_COMMAND_STOP "stop" #define NS_COMMAND_HALT "halt" #define NS_COMMAND_RELOAD "reload" #define NS_COMMAND_RECONFIG "reconfig" #define NS_COMMAND_REFRESH "refresh" #define NS_COMMAND_RETRANSFER "retransfer" #define NS_COMMAND_DUMPSTATS "stats" #define NS_COMMAND_QUERYLOG "querylog" #define NS_COMMAND_DUMPDB "dumpdb" #define NS_COMMAND_SECROOTS "secroots" #define NS_COMMAND_TRACE "trace" #define NS_COMMAND_NOTRACE "notrace" #define NS_COMMAND_FLUSH "flush" #define NS_COMMAND_FLUSHNAME "flushname" #define NS_COMMAND_FLUSHTREE "flushtree" #define NS_COMMAND_STATUS "status" #define NS_COMMAND_TSIGLIST "tsig-list" #define NS_COMMAND_TSIGDELETE "tsig-delete" #define NS_COMMAND_FREEZE "freeze" #define NS_COMMAND_UNFREEZE "unfreeze" #define NS_COMMAND_THAW "thaw" #define NS_COMMAND_TIMERPOKE "timerpoke" #define NS_COMMAND_RECURSING "recursing" #define NS_COMMAND_NULL "null" #define NS_COMMAND_NOTIFY "notify" #define NS_COMMAND_VALIDATION "validation" #define NS_COMMAND_SCAN "scan" #define NS_COMMAND_SIGN "sign" #define NS_COMMAND_LOADKEYS "loadkeys" #define NS_COMMAND_ADDZONE "addzone" #define NS_COMMAND_MODZONE "modzone" #define NS_COMMAND_DELZONE "delzone" #define NS_COMMAND_SHOWZONE "showzone" #define NS_COMMAND_SYNC "sync" #define NS_COMMAND_SIGNING "signing" #define NS_COMMAND_ZONESTATUS "zonestatus" #define NS_COMMAND_NTA "nta" #define NS_COMMAND_TESTGEN "testgen" #define NS_COMMAND_MKEYS "managed-keys" #define NS_COMMAND_DNSTAPREOPEN "dnstap-reopen" #define NS_COMMAND_DNSTAP "dnstap" isc_result_t ns_controls_create(ns_server_t *server, ns_controls_t **ctrlsp); /*%< * Create an initial, empty set of command channels for 'server'. */ void ns_controls_destroy(ns_controls_t **ctrlsp); /*%< * Destroy a set of command channels. * * Requires: * Shutdown of the channels has completed. */ isc_result_t ns_controls_configure(ns_controls_t *controls, const cfg_obj_t *config, cfg_aclconfctx_t *aclconfctx); /*%< * Configure zero or more command channels into 'controls' * as defined in the configuration parse tree 'config'. * The channels will evaluate ACLs in the context of * 'aclconfctx'. */ void ns_controls_shutdown(ns_controls_t *controls); /*%< * Initiate shutdown of all the command channels in 'controls'. */ isc_result_t ns_control_docommand(isccc_sexpr_t *message, isc_boolean_t readonly, isc_buffer_t **text); #endif /* NAMED_CONTROL_H */ bind9-9.11.3+dfsg/bin/named/include/named/fuzz.h000066400000000000000000000010311325250447100212410ustar00rootroot00000000000000/* * Copyright (C) 2016 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef NAMED_FUZZ_H #define NAMED_FUZZ_H void named_fuzz_notify(void); void named_fuzz_setup(void); typedef enum { ns_fuzz_none, ns_fuzz_client, ns_fuzz_tcpclient, ns_fuzz_resolver, ns_fuzz_http, ns_fuzz_rndc } ns_fuzz_t; #endif /* NAMED_FUZZ_H */ bind9-9.11.3+dfsg/bin/named/include/named/geoip.h000066400000000000000000000010511325250447100213500ustar00rootroot00000000000000/* * Copyright (C) 2013, 2016 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef _GEOIP_H #define _GEOIP_H #ifdef HAVE_GEOIP #include #include #endif /* HAVE_GEOIP */ void ns_geoip_init(void); void ns_geoip_load(char *dir); #ifdef HAVE_GEOIP extern dns_geoip_databases_t *ns_g_geoip; #endif /* HAVE_GEOIP */ #endif bind9-9.11.3+dfsg/bin/named/include/named/globals.h000066400000000000000000000137231325250447100217010ustar00rootroot00000000000000/* * Copyright (C) 1999-2017 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef NAMED_GLOBALS_H #define NAMED_GLOBALS_H 1 /*! \file */ #include #include #include #include #include #include #include #include #include #include #undef EXTERN #undef INIT #ifdef NS_MAIN #define EXTERN #define INIT(v) = (v) #else #define EXTERN extern #define INIT(v) #endif #ifndef NS_RUN_PID_DIR #define NS_RUN_PID_DIR 1 #endif EXTERN isc_mem_t * ns_g_mctx INIT(NULL); EXTERN unsigned int ns_g_cpus INIT(0); EXTERN unsigned int ns_g_udpdisp INIT(0); EXTERN isc_taskmgr_t * ns_g_taskmgr INIT(NULL); EXTERN dns_dispatchmgr_t * ns_g_dispatchmgr INIT(NULL); EXTERN isc_entropy_t * ns_g_entropy INIT(NULL); EXTERN isc_entropy_t * ns_g_fallbackentropy INIT(NULL); EXTERN unsigned int ns_g_cpus_detected INIT(1); #ifdef ENABLE_AFL EXTERN isc_boolean_t ns_g_run_done INIT(ISC_FALSE); #endif /* * XXXRTH We're going to want multiple timer managers eventually. One * for really short timers, another for client timers, and one * for zone timers. */ EXTERN isc_timermgr_t * ns_g_timermgr INIT(NULL); EXTERN isc_socketmgr_t * ns_g_socketmgr INIT(NULL); EXTERN cfg_parser_t * ns_g_parser INIT(NULL); EXTERN cfg_parser_t * ns_g_addparser INIT(NULL); EXTERN const char * ns_g_version INIT(VERSION); EXTERN const char * ns_g_product INIT(PRODUCT); EXTERN const char * ns_g_description INIT(DESCRIPTION); EXTERN const char * ns_g_srcid INIT(SRCID); EXTERN const char * ns_g_configargs INIT(CONFIGARGS); EXTERN const char * ns_g_builder INIT(BUILDER); EXTERN in_port_t ns_g_port INIT(0); EXTERN isc_dscp_t ns_g_dscp INIT(-1); EXTERN in_port_t lwresd_g_listenport INIT(0); EXTERN ns_server_t * ns_g_server INIT(NULL); EXTERN isc_boolean_t ns_g_lwresdonly INIT(ISC_FALSE); /* * Logging. */ EXTERN isc_log_t * ns_g_lctx INIT(NULL); EXTERN isc_logcategory_t * ns_g_categories INIT(NULL); EXTERN isc_logmodule_t * ns_g_modules INIT(NULL); EXTERN unsigned int ns_g_debuglevel INIT(0); /* * Current configuration information. */ EXTERN cfg_obj_t * ns_g_config INIT(NULL); EXTERN const cfg_obj_t * ns_g_defaults INIT(NULL); EXTERN const char * ns_g_conffile INIT(NS_SYSCONFDIR "/named.conf"); EXTERN cfg_obj_t * ns_g_bindkeys INIT(NULL); EXTERN const char * ns_g_keyfile INIT(NS_SYSCONFDIR "/rndc.key"); EXTERN dns_tsigkey_t * ns_g_sessionkey INIT(NULL); EXTERN dns_name_t ns_g_sessionkeyname; EXTERN const char * lwresd_g_conffile INIT(NS_SYSCONFDIR "/lwresd.conf"); EXTERN const char * lwresd_g_resolvconffile INIT("/etc" "/resolv.conf"); EXTERN isc_boolean_t ns_g_conffileset INIT(ISC_FALSE); EXTERN isc_boolean_t lwresd_g_useresolvconf INIT(ISC_FALSE); EXTERN isc_uint16_t ns_g_udpsize INIT(4096); EXTERN cfg_aclconfctx_t * ns_g_aclconfctx INIT(NULL); /* * Initial resource limits. */ EXTERN isc_resourcevalue_t ns_g_initstacksize INIT(0); EXTERN isc_resourcevalue_t ns_g_initdatasize INIT(0); EXTERN isc_resourcevalue_t ns_g_initcoresize INIT(0); EXTERN isc_resourcevalue_t ns_g_initopenfiles INIT(0); /* * Misc. */ EXTERN isc_boolean_t ns_g_coreok INIT(ISC_TRUE); EXTERN const char * ns_g_chrootdir INIT(NULL); EXTERN isc_boolean_t ns_g_foreground INIT(ISC_FALSE); EXTERN isc_boolean_t ns_g_logstderr INIT(ISC_FALSE); EXTERN isc_boolean_t ns_g_nosyslog INIT(ISC_FALSE); EXTERN const char * ns_g_logfile INIT(NULL); EXTERN const char * ns_g_defaultsessionkeyfile INIT(NS_LOCALSTATEDIR "/run/named/" "session.key"); EXTERN const char * ns_g_defaultlockfile INIT(NS_LOCALSTATEDIR "/run/named/" "named.lock"); EXTERN isc_boolean_t ns_g_forcelock INIT(ISC_FALSE); #if NS_RUN_PID_DIR EXTERN const char * ns_g_defaultpidfile INIT(NS_LOCALSTATEDIR "/run/named/" "named.pid"); EXTERN const char * lwresd_g_defaultpidfile INIT(NS_LOCALSTATEDIR "/run/lwresd/" "lwresd.pid"); #else EXTERN const char * ns_g_defaultpidfile INIT(NS_LOCALSTATEDIR "/run/named.pid"); EXTERN const char * lwresd_g_defaultpidfile INIT(NS_LOCALSTATEDIR "/run/lwresd.pid"); #endif #ifdef HAVE_DNSTAP EXTERN const char * ns_g_defaultdnstap INIT(NS_LOCALSTATEDIR "/run/named/" "dnstap.sock"); #else EXTERN const char * ns_g_defaultdnstap INIT(NULL); #endif /* HAVE_DNSTAP */ EXTERN const char * ns_g_username INIT(NULL); #if defined(USE_PKCS11) EXTERN const char * ns_g_engine INIT(PKCS11_ENGINE); #else EXTERN const char * ns_g_engine INIT(NULL); #endif EXTERN int ns_g_listen INIT(3); EXTERN isc_time_t ns_g_boottime; EXTERN isc_time_t ns_g_configtime; EXTERN isc_boolean_t ns_g_memstatistics INIT(ISC_FALSE); EXTERN isc_boolean_t ns_g_clienttest INIT(ISC_FALSE); EXTERN isc_boolean_t ns_g_dropedns INIT(ISC_FALSE); EXTERN isc_boolean_t ns_g_noedns INIT(ISC_FALSE); EXTERN isc_boolean_t ns_g_nosoa INIT(ISC_FALSE); EXTERN isc_boolean_t ns_g_noaa INIT(ISC_FALSE); EXTERN isc_boolean_t ns_g_keepstderr INIT(ISC_FALSE); EXTERN unsigned int ns_g_delay INIT(0); EXTERN isc_boolean_t ns_g_nonearest INIT(ISC_FALSE); EXTERN isc_boolean_t ns_g_notcp INIT(ISC_FALSE); EXTERN isc_boolean_t ns_g_disable6 INIT(ISC_FALSE); EXTERN isc_boolean_t ns_g_disable4 INIT(ISC_FALSE); EXTERN unsigned int ns_g_tat_interval INIT(24*3600); EXTERN isc_boolean_t ns_g_fixedlocal INIT(ISC_FALSE); #ifdef HAVE_GEOIP EXTERN dns_geoip_databases_t *ns_g_geoip INIT(NULL); #endif EXTERN const char * ns_g_fuzz_named_addr INIT(NULL); EXTERN ns_fuzz_t ns_g_fuzz_type INIT(ns_fuzz_none); EXTERN dns_acl_t * ns_g_mapped INIT(NULL); #undef EXTERN #undef INIT #endif /* NAMED_GLOBALS_H */ bind9-9.11.3+dfsg/bin/named/include/named/interfacemgr.h000066400000000000000000000116101325250447100227150ustar00rootroot00000000000000/* * Copyright (C) 1999-2002, 2004, 2005, 2007, 2011, 2013, 2014, 2016 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* $Id: interfacemgr.h,v 1.35 2011/07/28 23:47:58 tbox Exp $ */ #ifndef NAMED_INTERFACEMGR_H #define NAMED_INTERFACEMGR_H 1 /***** ***** Module Info *****/ /*! \file * \brief * The interface manager monitors the operating system's list * of network interfaces, creating and destroying listeners * as needed. * * Reliability: *\li No impact expected. * * Resources: * * Security: * \li The server will only be able to bind to the DNS port on * newly discovered interfaces if it is running as root. * * Standards: *\li The API for scanning varies greatly among operating systems. * This module attempts to hide the differences. */ /*** *** Imports ***/ #include #include #include #include #include #include /*** *** Types ***/ #define IFACE_MAGIC ISC_MAGIC('I',':','-',')') #define NS_INTERFACE_VALID(t) ISC_MAGIC_VALID(t, IFACE_MAGIC) #define NS_INTERFACEFLAG_ANYADDR 0x01U /*%< bound to "any" address */ #define MAX_UDP_DISPATCH 128 /*%< Maximum number of UDP dispatchers to start per interface */ /*% The nameserver interface structure */ struct ns_interface { unsigned int magic; /*%< Magic number. */ ns_interfacemgr_t * mgr; /*%< Interface manager. */ isc_mutex_t lock; int references; /*%< Locked */ unsigned int generation; /*%< Generation number. */ isc_sockaddr_t addr; /*%< Address and port. */ unsigned int flags; /*%< Interface characteristics */ char name[32]; /*%< Null terminated. */ dns_dispatch_t * udpdispatch[MAX_UDP_DISPATCH]; /*%< UDP dispatchers. */ isc_socket_t * tcpsocket; /*%< TCP socket. */ isc_dscp_t dscp; /*%< "listen-on" DSCP value */ int ntcptarget; /*%< Desired number of concurrent TCP accepts */ int ntcpcurrent; /*%< Current ditto, locked */ int nudpdispatch; /*%< Number of UDP dispatches */ ns_clientmgr_t * clientmgr; /*%< Client manager. */ ISC_LINK(ns_interface_t) link; }; /*** *** Functions ***/ isc_result_t ns_interfacemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr, isc_socketmgr_t *socketmgr, dns_dispatchmgr_t *dispatchmgr, isc_task_t *task, ns_interfacemgr_t **mgrp); /*% * Create a new interface manager. * * Initially, the new manager will not listen on any interfaces. * Call ns_interfacemgr_setlistenon() and/or ns_interfacemgr_setlistenon6() * to set nonempty listen-on lists. */ void ns_interfacemgr_attach(ns_interfacemgr_t *source, ns_interfacemgr_t **target); void ns_interfacemgr_detach(ns_interfacemgr_t **targetp); void ns_interfacemgr_shutdown(ns_interfacemgr_t *mgr); isc_boolean_t ns_interfacemgr_islistening(ns_interfacemgr_t *mgr); /*% * Return if the manager is listening on any interface. It can be called * after a scan or adjust. */ isc_result_t ns_interfacemgr_scan(ns_interfacemgr_t *mgr, isc_boolean_t verbose); /*% * Scan the operatings system's list of network interfaces * and create listeners when new interfaces are discovered. * Shut down the sockets for interfaces that go away. * * This should be called once on server startup and then * periodically according to the 'interface-interval' option * in named.conf. */ isc_result_t ns_interfacemgr_adjust(ns_interfacemgr_t *mgr, ns_listenlist_t *list, isc_boolean_t verbose); /*% * Similar to ns_interfacemgr_scan(), but this function also tries to see the * need for an explicit listen-on when a list element in 'list' is going to * override an already-listening a wildcard interface. * * This function does not update localhost and localnets ACLs. * * This should be called once on server startup, after configuring views and * zones. */ void ns_interfacemgr_setlistenon4(ns_interfacemgr_t *mgr, ns_listenlist_t *value); /*% * Set the IPv4 "listen-on" list of 'mgr' to 'value'. * The previous IPv4 listen-on list is freed. */ void ns_interfacemgr_setlistenon6(ns_interfacemgr_t *mgr, ns_listenlist_t *value); /*% * Set the IPv6 "listen-on" list of 'mgr' to 'value'. * The previous IPv6 listen-on list is freed. */ dns_aclenv_t * ns_interfacemgr_getaclenv(ns_interfacemgr_t *mgr); void ns_interface_attach(ns_interface_t *source, ns_interface_t **target); void ns_interface_detach(ns_interface_t **targetp); void ns_interface_shutdown(ns_interface_t *ifp); /*% * Stop listening for queries on interface 'ifp'. * May safely be called multiple times. */ void ns_interfacemgr_dumprecursing(FILE *f, ns_interfacemgr_t *mgr); isc_boolean_t ns_interfacemgr_listeningon(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr); #endif /* NAMED_INTERFACEMGR_H */ bind9-9.11.3+dfsg/bin/named/include/named/listenlist.h000066400000000000000000000037201325250447100224440ustar00rootroot00000000000000/* * Copyright (C) 2000, 2001, 2004, 2005, 2007, 2013, 2016 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* $Id: listenlist.h,v 1.15 2007/06/19 23:46:59 tbox Exp $ */ #ifndef NAMED_LISTENLIST_H #define NAMED_LISTENLIST_H 1 /***** ***** Module Info *****/ /*! \file * \brief * "Listen lists", as in the "listen-on" configuration statement. */ /*** *** Imports ***/ #include #include /*** *** Types ***/ typedef struct ns_listenelt ns_listenelt_t; typedef struct ns_listenlist ns_listenlist_t; struct ns_listenelt { isc_mem_t * mctx; in_port_t port; isc_dscp_t dscp; /* -1 = not set, 0..63 */ dns_acl_t * acl; ISC_LINK(ns_listenelt_t) link; }; struct ns_listenlist { isc_mem_t * mctx; int refcount; ISC_LIST(ns_listenelt_t) elts; }; /*** *** Functions ***/ isc_result_t ns_listenelt_create(isc_mem_t *mctx, in_port_t port, isc_dscp_t dscp, dns_acl_t *acl, ns_listenelt_t **target); /*% * Create a listen-on list element. */ void ns_listenelt_destroy(ns_listenelt_t *elt); /*% * Destroy a listen-on list element. */ isc_result_t ns_listenlist_create(isc_mem_t *mctx, ns_listenlist_t **target); /*% * Create a new, empty listen-on list. */ void ns_listenlist_attach(ns_listenlist_t *source, ns_listenlist_t **target); /*% * Attach '*target' to '*source'. */ void ns_listenlist_detach(ns_listenlist_t **listp); /*% * Detach 'listp'. */ isc_result_t ns_listenlist_default(isc_mem_t *mctx, in_port_t port, isc_dscp_t dscp, isc_boolean_t enabled, ns_listenlist_t **target); /*% * Create a listen-on list with default contents, matching * all addresses with port 'port' (if 'enabled' is ISC_TRUE), * or no addresses (if 'enabled' is ISC_FALSE). */ #endif /* NAMED_LISTENLIST_H */ bind9-9.11.3+dfsg/bin/named/include/named/log.h000066400000000000000000000052201325250447100210300ustar00rootroot00000000000000/* * Copyright (C) 1999-2002, 2004, 2005, 2007, 2009, 2015-2017 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* $Id: log.h,v 1.27 2009/01/07 23:47:46 tbox Exp $ */ #ifndef NAMED_LOG_H #define NAMED_LOG_H 1 /*! \file */ #include #include #include #include /* Required for ns_g_(categories|modules). */ /* Unused slot 0. */ #define NS_LOGCATEGORY_CLIENT (&ns_g_categories[1]) #define NS_LOGCATEGORY_NETWORK (&ns_g_categories[2]) #define NS_LOGCATEGORY_UPDATE (&ns_g_categories[3]) #define NS_LOGCATEGORY_QUERIES (&ns_g_categories[4]) #define NS_LOGCATEGORY_UNMATCHED (&ns_g_categories[5]) #define NS_LOGCATEGORY_UPDATE_SECURITY (&ns_g_categories[6]) #define NS_LOGCATEGORY_QUERY_ERRORS (&ns_g_categories[7]) #define NS_LOGCATEGORY_TAT (&ns_g_categories[8]) /* * Backwards compatibility. */ #define NS_LOGCATEGORY_GENERAL ISC_LOGCATEGORY_GENERAL #define NS_LOGMODULE_MAIN (&ns_g_modules[0]) #define NS_LOGMODULE_CLIENT (&ns_g_modules[1]) #define NS_LOGMODULE_SERVER (&ns_g_modules[2]) #define NS_LOGMODULE_QUERY (&ns_g_modules[3]) #define NS_LOGMODULE_INTERFACEMGR (&ns_g_modules[4]) #define NS_LOGMODULE_UPDATE (&ns_g_modules[5]) #define NS_LOGMODULE_XFER_IN (&ns_g_modules[6]) #define NS_LOGMODULE_XFER_OUT (&ns_g_modules[7]) #define NS_LOGMODULE_NOTIFY (&ns_g_modules[8]) #define NS_LOGMODULE_CONTROL (&ns_g_modules[9]) #define NS_LOGMODULE_LWRESD (&ns_g_modules[10]) isc_result_t ns_log_init(isc_boolean_t safe); /*% * Initialize the logging system and set up an initial default * logging default configuration that will be used until the * config file has been read. * * If 'safe' is true, use a default configuration that refrains * from opening files. This is to avoid creating log files * as root. */ isc_result_t ns_log_setdefaultchannels(isc_logconfig_t *lcfg); /*% * Set up logging channels according to the named defaults, which * may differ from the logging library defaults. Currently, * this just means setting up default_debug. */ isc_result_t ns_log_setsafechannels(isc_logconfig_t *lcfg); /*% * Like ns_log_setdefaultchannels(), but omits any logging to files. */ isc_result_t ns_log_setdefaultcategory(isc_logconfig_t *lcfg); /*% * Set up "category default" to go to the right places. */ isc_result_t ns_log_setunmatchedcategory(isc_logconfig_t *lcfg); /*% * Set up "category unmatched" to go to the right places. */ void ns_log_shutdown(void); #endif /* NAMED_LOG_H */ bind9-9.11.3+dfsg/bin/named/include/named/logconf.h000066400000000000000000000012351325250447100217000ustar00rootroot00000000000000/* * Copyright (C) 1999-2001, 2004-2007, 2016 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* $Id: logconf.h,v 1.17 2007/06/19 23:46:59 tbox Exp $ */ #ifndef NAMED_LOGCONF_H #define NAMED_LOGCONF_H 1 /*! \file */ #include isc_result_t ns_log_configure(isc_logconfig_t *logconf, const cfg_obj_t *logstmt); /*%< * Set up the logging configuration in '*logconf' according to * the named.conf data in 'logstmt'. */ #endif /* NAMED_LOGCONF_H */ bind9-9.11.3+dfsg/bin/named/include/named/lwaddr.h000066400000000000000000000014151325250447100215260ustar00rootroot00000000000000/* * Copyright (C) 2000, 2001, 2004, 2005, 2007, 2016 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* $Id: lwaddr.h,v 1.8 2007/06/19 23:46:59 tbox Exp $ */ /*! \file */ #include #include isc_result_t lwaddr_netaddr_fromlwresaddr(isc_netaddr_t *na, lwres_addr_t *la); isc_result_t lwaddr_sockaddr_fromlwresaddr(isc_sockaddr_t *sa, lwres_addr_t *la, in_port_t port); isc_result_t lwaddr_lwresaddr_fromnetaddr(lwres_addr_t *la, isc_netaddr_t *na); isc_result_t lwaddr_lwresaddr_fromsockaddr(lwres_addr_t *la, isc_sockaddr_t *sa); bind9-9.11.3+dfsg/bin/named/include/named/lwdclient.h000066400000000000000000000145651325250447100222500ustar00rootroot00000000000000/* * Copyright (C) 2000, 2001, 2004, 2005, 2007, 2009, 2015, 2016 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* $Id: lwdclient.h,v 1.20 2009/01/17 23:47:42 tbox Exp $ */ #ifndef NAMED_LWDCLIENT_H #define NAMED_LWDCLIENT_H 1 /*! \file */ #include #include #include #include #include #include #include #include #include #define LWRD_EVENTCLASS ISC_EVENTCLASS(4242) #define LWRD_SHUTDOWN (LWRD_EVENTCLASS + 0x0001) /*% Lightweight Resolver Daemon Client */ struct ns_lwdclient { isc_sockaddr_t address; /*%< where to reply */ struct in6_pktinfo pktinfo; isc_boolean_t pktinfo_valid; ns_lwdclientmgr_t *clientmgr; /*%< our parent */ ISC_LINK(ns_lwdclient_t) link; unsigned int state; void *arg; /*%< packet processing state */ /* * Received data info. */ unsigned char buffer[LWRES_RECVLENGTH]; /*%< receive buffer */ isc_uint32_t recvlength; /*%< length recv'd */ lwres_lwpacket_t pkt; /*% * Send data state. If sendbuf != buffer (that is, the send buffer * isn't our receive buffer) it will be freed to the lwres_context_t. */ unsigned char *sendbuf; isc_uint32_t sendlength; isc_buffer_t recv_buffer; /*% * gabn (get address by name) state info. */ dns_adbfind_t *find; dns_adbfind_t *v4find; dns_adbfind_t *v6find; unsigned int find_wanted; /*%< Addresses we want */ dns_fixedname_t query_name; dns_fixedname_t target_name; ns_lwsearchctx_t searchctx; lwres_gabnresponse_t gabn; /*% * gnba (get name by address) state info. */ lwres_gnbaresponse_t gnba; dns_byaddr_t *byaddr; unsigned int options; isc_netaddr_t na; /*% * grbn (get rrset by name) state info. * * Note: this also uses target_name and searchctx. */ lwres_grbnresponse_t grbn; dns_lookup_t *lookup; dns_rdatatype_t rdtype; /*% * Alias and address info. This is copied up to the gabn/gnba * structures eventually. * * XXXMLG We can keep all of this in a client since we only service * three packet types right now. If we started handling more, * we'd need to use "arg" above and allocate/destroy things. */ char *aliases[LWRES_MAX_ALIASES]; isc_uint16_t aliaslen[LWRES_MAX_ALIASES]; lwres_addr_t addrs[LWRES_MAX_ADDRS]; }; /*% * Client states. * * _IDLE The client is not doing anything at all. * * _RECV The client is waiting for data after issuing a socket recv(). * * _RECVDONE Data has been received, and is being processed. * * _FINDWAIT An adb (or other) request was made that cannot be satisfied * immediately. An event will wake the client up. * * _SEND All data for a response has completed, and a reply was * sent via a socket send() call. * * Badly formatted state table: * * IDLE -> RECV when client has a recv() queued. * * RECV -> RECVDONE when recvdone event received. * * RECVDONE -> SEND if the data for a reply is at hand. * RECVDONE -> FINDWAIT if more searching is needed, and events will * eventually wake us up again. * * FINDWAIT -> SEND when enough data was received to reply. * * SEND -> IDLE when a senddone event was received. * * At any time -> IDLE on error. Sometimes this will be -> SEND * instead, if enough data is on hand to reply with a meaningful * error. * * Packets which are badly formatted may or may not get error returns. */ #define NS_LWDCLIENT_STATEIDLE 1 #define NS_LWDCLIENT_STATERECV 2 #define NS_LWDCLIENT_STATERECVDONE 3 #define NS_LWDCLIENT_STATEFINDWAIT 4 #define NS_LWDCLIENT_STATESEND 5 #define NS_LWDCLIENT_STATESENDDONE 6 #define NS_LWDCLIENT_ISIDLE(c) \ ((c)->state == NS_LWDCLIENT_STATEIDLE) #define NS_LWDCLIENT_ISRECV(c) \ ((c)->state == NS_LWDCLIENT_STATERECV) #define NS_LWDCLIENT_ISRECVDONE(c) \ ((c)->state == NS_LWDCLIENT_STATERECVDONE) #define NS_LWDCLIENT_ISFINDWAIT(c) \ ((c)->state == NS_LWDCLIENT_STATEFINDWAIT) #define NS_LWDCLIENT_ISSEND(c) \ ((c)->state == NS_LWDCLIENT_STATESEND) /*% * Overall magic test that means we're not idle. */ #define NS_LWDCLIENT_ISRUNNING(c) (!NS_LWDCLIENT_ISIDLE(c)) #define NS_LWDCLIENT_SETIDLE(c) \ ((c)->state = NS_LWDCLIENT_STATEIDLE) #define NS_LWDCLIENT_SETRECV(c) \ ((c)->state = NS_LWDCLIENT_STATERECV) #define NS_LWDCLIENT_SETRECVDONE(c) \ ((c)->state = NS_LWDCLIENT_STATERECVDONE) #define NS_LWDCLIENT_SETFINDWAIT(c) \ ((c)->state = NS_LWDCLIENT_STATEFINDWAIT) #define NS_LWDCLIENT_SETSEND(c) \ ((c)->state = NS_LWDCLIENT_STATESEND) #define NS_LWDCLIENT_SETSENDDONE(c) \ ((c)->state = NS_LWDCLIENT_STATESENDDONE) /*% lightweight daemon client manager */ struct ns_lwdclientmgr { ns_lwreslistener_t *listener; isc_mem_t *mctx; isc_socket_t *sock; /*%< socket to use */ dns_view_t *view; lwres_context_t *lwctx; /*%< lightweight proto context */ isc_task_t *task; /*%< owning task */ unsigned int flags; isc_mutex_t lock; ISC_LINK(ns_lwdclientmgr_t) link; ISC_LIST(ns_lwdclient_t) idle; /*%< idle client slots */ ISC_LIST(ns_lwdclient_t) running; /*%< running clients */ }; #define NS_LWDCLIENTMGR_FLAGRECVPENDING 0x00000001 #define NS_LWDCLIENTMGR_FLAGSHUTTINGDOWN 0x00000002 isc_result_t ns_lwdclientmgr_create(ns_lwreslistener_t *, unsigned int, isc_taskmgr_t *); void ns_lwdclient_initialize(ns_lwdclient_t *, ns_lwdclientmgr_t *); isc_result_t ns_lwdclient_startrecv(ns_lwdclientmgr_t *); void ns_lwdclient_stateidle(ns_lwdclient_t *); void ns_lwdclient_recv(isc_task_t *, isc_event_t *); void ns_lwdclient_shutdown(isc_task_t *, isc_event_t *); void ns_lwdclient_send(isc_task_t *, isc_event_t *); isc_result_t ns_lwdclient_sendreply(ns_lwdclient_t *client, isc_region_t *r); /* * Processing functions of various types. */ void ns_lwdclient_processgabn(ns_lwdclient_t *, lwres_buffer_t *); void ns_lwdclient_processgnba(ns_lwdclient_t *, lwres_buffer_t *); void ns_lwdclient_processgrbn(ns_lwdclient_t *, lwres_buffer_t *); void ns_lwdclient_processnoop(ns_lwdclient_t *, lwres_buffer_t *); void ns_lwdclient_errorpktsend(ns_lwdclient_t *, isc_uint32_t); void ns_lwdclient_log(int level, const char *format, ...) ISC_FORMAT_PRINTF(2, 3); #endif /* NAMED_LWDCLIENT_H */ bind9-9.11.3+dfsg/bin/named/include/named/lwresd.h000066400000000000000000000043331325250447100215530ustar00rootroot00000000000000/* * Copyright (C) 2000, 2001, 2004-2007, 2014, 2016 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* $Id: lwresd.h,v 1.19 2007/06/19 23:46:59 tbox Exp $ */ #ifndef NAMED_LWRESD_H #define NAMED_LWRESD_H 1 /*! \file */ #include #include #include #include struct ns_lwresd { unsigned int magic; isc_mutex_t lock; dns_view_t *view; ns_lwsearchlist_t *search; unsigned int ndots; unsigned int ntasks; unsigned int nclients; isc_mem_t *mctx; isc_boolean_t shutting_down; unsigned int refs; }; struct ns_lwreslistener { unsigned int magic; isc_mutex_t lock; isc_mem_t *mctx; isc_sockaddr_t address; ns_lwresd_t *manager; isc_socket_t *sock; unsigned int refs; ISC_LIST(ns_lwdclientmgr_t) cmgrs; ISC_LINK(ns_lwreslistener_t) link; }; /*% * Configure lwresd. */ isc_result_t ns_lwresd_configure(isc_mem_t *mctx, const cfg_obj_t *config); isc_result_t ns_lwresd_parseeresolvconf(isc_mem_t *mctx, cfg_parser_t *pctx, cfg_obj_t **configp); /*% * Trigger shutdown. */ void ns_lwresd_shutdown(void); /* * Manager functions */ /*% create manager */ isc_result_t ns_lwdmanager_create(isc_mem_t *mctx, const cfg_obj_t *lwres, ns_lwresd_t **lwresdp); /*% attach to manager */ void ns_lwdmanager_attach(ns_lwresd_t *source, ns_lwresd_t **targetp); /*% detach from manager */ void ns_lwdmanager_detach(ns_lwresd_t **lwresdp); /* * Listener functions */ /*% attach to listener */ void ns_lwreslistener_attach(ns_lwreslistener_t *source, ns_lwreslistener_t **targetp); /*% detach from lister */ void ns_lwreslistener_detach(ns_lwreslistener_t **listenerp); /*% link client manager */ void ns_lwreslistener_unlinkcm(ns_lwreslistener_t *listener, ns_lwdclientmgr_t *cm); /*% unlink client manager */ void ns_lwreslistener_linkcm(ns_lwreslistener_t *listener, ns_lwdclientmgr_t *cm); /* * INTERNAL FUNCTIONS. */ void * ns__lwresd_memalloc(void *arg, size_t size); void ns__lwresd_memfree(void *arg, void *mem, size_t size); #endif /* NAMED_LWRESD_H */ bind9-9.11.3+dfsg/bin/named/include/named/lwsearch.h000066400000000000000000000047221325250447100220650ustar00rootroot00000000000000/* * Copyright (C) 2000, 2001, 2004, 2005, 2007, 2016 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* $Id: lwsearch.h,v 1.9 2007/06/19 23:46:59 tbox Exp $ */ #ifndef NAMED_LWSEARCH_H #define NAMED_LWSEARCH_H 1 #include #include #include #include #include /*! \file * \brief * Lightweight resolver search list types and routines. * * An ns_lwsearchlist_t holds a list of search path elements. * * An ns_lwsearchctx stores the state of search list during a lookup * operation. */ /*% An ns_lwsearchlist_t holds a list of search path elements. */ struct ns_lwsearchlist { unsigned int magic; isc_mutex_t lock; isc_mem_t *mctx; unsigned int refs; dns_namelist_t names; }; /*% An ns_lwsearchctx stores the state of search list during a lookup operation. */ struct ns_lwsearchctx { dns_name_t *relname; dns_name_t *searchname; unsigned int ndots; ns_lwsearchlist_t *list; isc_boolean_t doneexact; isc_boolean_t exactfirst; }; isc_result_t ns_lwsearchlist_create(isc_mem_t *mctx, ns_lwsearchlist_t **listp); /*%< * Create an empty search list object. */ void ns_lwsearchlist_attach(ns_lwsearchlist_t *source, ns_lwsearchlist_t **target); /*%< * Attach to a search list object. */ void ns_lwsearchlist_detach(ns_lwsearchlist_t **listp); /*%< * Detach from a search list object. */ isc_result_t ns_lwsearchlist_append(ns_lwsearchlist_t *list, dns_name_t *name); /*%< * Append an element to a search list. This creates a copy of the name. */ void ns_lwsearchctx_init(ns_lwsearchctx_t *sctx, ns_lwsearchlist_t *list, dns_name_t *name, unsigned int ndots); /*%< * Creates a search list context structure. */ void ns_lwsearchctx_first(ns_lwsearchctx_t *sctx); /*%< * Moves the search list context iterator to the first element, which * is usually the exact name. */ isc_result_t ns_lwsearchctx_next(ns_lwsearchctx_t *sctx); /*%< * Moves the search list context iterator to the next element. */ isc_result_t ns_lwsearchctx_current(ns_lwsearchctx_t *sctx, dns_name_t *absname); /*%< * Obtains the current name to be looked up. This involves either * concatenating the name with a search path element, making an * exact name absolute, or doing nothing. */ #endif /* NAMED_LWSEARCH_H */ bind9-9.11.3+dfsg/bin/named/include/named/main.h000066400000000000000000000015671325250447100212050ustar00rootroot00000000000000/* * Copyright (C) 1999-2002, 2004, 2005, 2007, 2009, 2013, 2015, 2016 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef NAMED_MAIN_H #define NAMED_MAIN_H 1 /*! \file */ #ifdef ISC_MAIN_HOOK #define main(argc, argv) bindmain(argc, argv) #endif /* * Commandline arguments for named; also referenced in win32/ntservice.c */ #define NS_MAIN_ARGS "46A:c:C:d:D:E:fFgi:lL:M:m:n:N:p:P:sS:t:T:U:u:vVx:X:" ISC_PLATFORM_NORETURN_PRE void ns_main_earlyfatal(const char *format, ...) ISC_FORMAT_PRINTF(1, 2) ISC_PLATFORM_NORETURN_POST; void ns_main_earlywarning(const char *format, ...) ISC_FORMAT_PRINTF(1, 2); void ns_main_setmemstats(const char *); #endif /* NAMED_MAIN_H */ bind9-9.11.3+dfsg/bin/named/include/named/notify.h000066400000000000000000000017761325250447100215730ustar00rootroot00000000000000/* * Copyright (C) 1999-2001, 2004, 2005, 2007, 2009, 2016 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* $Id: notify.h,v 1.16 2009/01/17 23:47:42 tbox Exp $ */ #ifndef NAMED_NOTIFY_H #define NAMED_NOTIFY_H 1 #include #include /*** *** Module Info ***/ /*! \file * \brief * RFC1996 * A Mechanism for Prompt Notification of Zone Changes (DNS NOTIFY) */ /*** *** Functions. ***/ void ns_notify_start(ns_client_t *client); /*%< * Examines the incoming message to determine appropriate zone. * Returns FORMERR if there is not exactly one question. * Returns REFUSED if we do not serve the listed zone. * Pass the message to the zone module for processing * and returns the return status. * * Requires *\li client to be valid. */ #endif /* NAMED_NOTIFY_H */ bind9-9.11.3+dfsg/bin/named/include/named/ns_smf_globals.h000066400000000000000000000016001325250447100232350ustar00rootroot00000000000000/* * Copyright (C) 2005, 2007, 2014, 2016 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* $Id: ns_smf_globals.h,v 1.7 2007/06/19 23:46:59 tbox Exp $ */ #ifndef NS_SMF_GLOBALS_H #define NS_SMF_GLOBALS_H 1 #include #undef EXTERN #undef INIT #ifdef NS_MAIN #define EXTERN #define INIT(v) = (v) #else #define EXTERN extern #define INIT(v) #endif EXTERN unsigned int ns_smf_got_instance INIT(0); EXTERN unsigned int ns_smf_chroot INIT(0); EXTERN unsigned int ns_smf_want_disable INIT(0); isc_result_t ns_smf_add_message(isc_buffer_t **text); isc_result_t ns_smf_get_instance(char **name, int debug, isc_mem_t *mctx); #undef EXTERN #undef INIT #endif /* NS_SMF_GLOBALS_H */ bind9-9.11.3+dfsg/bin/named/include/named/query.h000066400000000000000000000054211325250447100214170ustar00rootroot00000000000000/* * Copyright (C) 1999-2002, 2004, 2005, 2007, 2010, 2011, 2013-2016 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef NAMED_QUERY_H #define NAMED_QUERY_H 1 /*! \file */ #include #include #include #include #include #include #include /*% nameserver database version structure */ typedef struct ns_dbversion { dns_db_t *db; dns_dbversion_t *version; isc_boolean_t acl_checked; isc_boolean_t queryok; ISC_LINK(struct ns_dbversion) link; } ns_dbversion_t; /*% nameserver query structure */ struct ns_query { unsigned int attributes; unsigned int restarts; isc_boolean_t timerset; dns_name_t * qname; dns_name_t * origqname; dns_rdatatype_t qtype; unsigned int dboptions; unsigned int fetchoptions; dns_db_t * gluedb; dns_db_t * authdb; dns_zone_t * authzone; isc_boolean_t authdbset; isc_boolean_t isreferral; isc_mutex_t fetchlock; dns_fetch_t * fetch; dns_fetch_t * prefetch; dns_rpz_st_t * rpz_st; isc_bufferlist_t namebufs; ISC_LIST(ns_dbversion_t) activeversions; ISC_LIST(ns_dbversion_t) freeversions; dns_rdataset_t * dns64_aaaa; dns_rdataset_t * dns64_sigaaaa; isc_boolean_t * dns64_aaaaok; unsigned int dns64_aaaaoklen; unsigned int dns64_options; unsigned int dns64_ttl; struct { dns_db_t * db; dns_zone_t * zone; dns_dbnode_t * node; dns_rdatatype_t qtype; dns_name_t * fname; dns_fixedname_t fixed; isc_result_t result; dns_rdataset_t * rdataset; dns_rdataset_t * sigrdataset; isc_boolean_t authoritative; isc_boolean_t is_zone; } redirect; }; #define NS_QUERYATTR_RECURSIONOK 0x0001 #define NS_QUERYATTR_CACHEOK 0x0002 #define NS_QUERYATTR_PARTIALANSWER 0x0004 #define NS_QUERYATTR_NAMEBUFUSED 0x0008 #define NS_QUERYATTR_RECURSING 0x0010 #define NS_QUERYATTR_CACHEGLUEOK 0x0020 #define NS_QUERYATTR_QUERYOKVALID 0x0040 #define NS_QUERYATTR_QUERYOK 0x0080 #define NS_QUERYATTR_WANTRECURSION 0x0100 #define NS_QUERYATTR_SECURE 0x0200 #define NS_QUERYATTR_NOAUTHORITY 0x0400 #define NS_QUERYATTR_NOADDITIONAL 0x0800 #define NS_QUERYATTR_CACHEACLOKVALID 0x1000 #define NS_QUERYATTR_CACHEACLOK 0x2000 #define NS_QUERYATTR_DNS64 0x4000 #define NS_QUERYATTR_DNS64EXCLUDE 0x8000 #define NS_QUERYATTR_RRL_CHECKED 0x10000 #define NS_QUERYATTR_REDIRECT 0x20000 isc_result_t ns_query_init(ns_client_t *client); void ns_query_free(ns_client_t *client); void ns_query_start(ns_client_t *client); void ns_query_cancel(ns_client_t *client); #endif /* NAMED_QUERY_H */ bind9-9.11.3+dfsg/bin/named/include/named/seccomp.h000066400000000000000000000101451325250447100217020ustar00rootroot00000000000000/* * Copyright (C) 2014, 2016, 2017 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef NAMED_SECCOMP_H #define NAMED_SECCOMP_H 1 /*! \file */ #ifdef HAVE_LIBSECCOMP #include #include #include #include #include /*% * For each architecture, the scmp_syscalls and * scmp_syscall_names arrays MUST be kept in sync. */ #ifdef __x86_64__ int scmp_syscalls[] = { SCMP_SYS(access), SCMP_SYS(open), SCMP_SYS(openat), SCMP_SYS(lseek), SCMP_SYS(clock_gettime), SCMP_SYS(time), SCMP_SYS(read), SCMP_SYS(write), SCMP_SYS(close), SCMP_SYS(brk), SCMP_SYS(poll), SCMP_SYS(select), SCMP_SYS(madvise), SCMP_SYS(mmap), SCMP_SYS(munmap), SCMP_SYS(exit_group), SCMP_SYS(rt_sigprocmask), SCMP_SYS(rt_sigaction), SCMP_SYS(fsync), SCMP_SYS(rt_sigreturn), SCMP_SYS(setsid), SCMP_SYS(chdir), SCMP_SYS(futex), SCMP_SYS(stat), SCMP_SYS(rt_sigsuspend), SCMP_SYS(fstat), SCMP_SYS(epoll_ctl), SCMP_SYS(gettimeofday), SCMP_SYS(getpid), #ifdef HAVE_GETRANDOM SCMP_SYS(getrandom), #endif SCMP_SYS(rename), SCMP_SYS(unlink), SCMP_SYS(socket), SCMP_SYS(sendto), #ifndef ISC_PLATFORM_USETHREADS SCMP_SYS(bind), SCMP_SYS(accept), SCMP_SYS(connect), SCMP_SYS(listen), SCMP_SYS(fcntl), SCMP_SYS(sendmsg), SCMP_SYS(recvmsg), SCMP_SYS(uname), SCMP_SYS(setrlimit), SCMP_SYS(getrlimit), SCMP_SYS(setsockopt), SCMP_SYS(getsockopt), SCMP_SYS(getsockname), SCMP_SYS(lstat), SCMP_SYS(getgid), SCMP_SYS(getegid), SCMP_SYS(getuid), SCMP_SYS(geteuid), SCMP_SYS(setresgid), SCMP_SYS(setresuid), SCMP_SYS(setgid), SCMP_SYS(setuid), SCMP_SYS(prctl), SCMP_SYS(epoll_wait), SCMP_SYS(getdents), SCMP_SYS(utimes), SCMP_SYS(dup), #endif }; const char *scmp_syscall_names[] = { "access", "open", "openat", "lseek", "clock_gettime", "time", "read", "write", "close", "brk", "poll", "select", "madvise", "mmap", "munmap", "exit_group", "rt_sigprocmask", "rt_sigaction", "fsync", "rt_sigreturn", "setsid", "chdir", "futex", "stat", "rt_sigsuspend", "fstat", "epoll_ctl", "gettimeofday", "getpid", #ifdef HAVE_GETRANDOM "getrandom", #endif "rename", "unlink", "socket", "sendto", #ifndef ISC_PLATFORM_USETHREADS "bind", "accept", "connect", "listen", "fcntl", "sendmsg", "recvmsg", "uname", "setrlimit", "getrlimit", "setsockopt", "getsockopt", "getsockname", "lstat", "getgid", "getegid", "getuid", "geteuid", "setresgid", "setresuid", "setgid", "setuid", "prctl", "epoll_wait", "getdents", "utimes", "dup", #endif }; #endif /* __x86_64__ */ #ifdef __i386__ int scmp_syscalls[] = { SCMP_SYS(access), SCMP_SYS(open), SCMP_SYS(clock_gettime), SCMP_SYS(time), SCMP_SYS(read), SCMP_SYS(write), SCMP_SYS(close), SCMP_SYS(brk), SCMP_SYS(poll), SCMP_SYS(_newselect), SCMP_SYS(select), SCMP_SYS(madvise), SCMP_SYS(mmap2), SCMP_SYS(mmap), SCMP_SYS(munmap), SCMP_SYS(exit_group), SCMP_SYS(rt_sigprocmask), SCMP_SYS(sigprocmask), SCMP_SYS(rt_sigaction), SCMP_SYS(socketcall), SCMP_SYS(fsync), SCMP_SYS(sigreturn), SCMP_SYS(setsid), SCMP_SYS(chdir), SCMP_SYS(futex), SCMP_SYS(stat64), SCMP_SYS(rt_sigsuspend), SCMP_SYS(fstat64), SCMP_SYS(epoll_ctl), SCMP_SYS(gettimeofday), SCMP_SYS(getpid), #ifdef HAVE_GETRANDOM SCMP_SYS(getrandom), #endif SCMP_SYS(unlink), #ifndef ISC_PLATFORM_USETHREADS SCMP_SYS(fcntl64), #endif }; const char *scmp_syscall_names[] = { "access", "open", "clock_gettime", "time", "read", "write", "close", "brk", "poll", "_newselect", "select", "madvise", "mmap2", "mmap", "munmap", "exit_group", "rt_sigprocmask", "sigprocmask", "rt_sigaction", "socketcall", "fsync", "sigreturn", "setsid", "chdir", "futex", "stat64", "rt_sigsuspend", "fstat64", "epoll_ctl", "gettimeofday", "getpid", #ifdef HAVE_GETRANDOM "getrandom", #endif "unlink", #ifndef ISC_PLATFORM_USETHREADS "fcntl64", #endif }; #endif /* __i386__ */ #endif /* HAVE_LIBSECCOMP */ #endif /* NAMED_SECCOMP_H */ bind9-9.11.3+dfsg/bin/named/include/named/server.h000066400000000000000000000516411325250447100215650ustar00rootroot00000000000000/* * Copyright (C) 1999-2017 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef NAMED_SERVER_H #define NAMED_SERVER_H 1 /*! \file */ #include #include #include #include #include #include #include #include #include #include #define NS_EVENTCLASS ISC_EVENTCLASS(0x4E43) #define NS_EVENT_RELOAD (NS_EVENTCLASS + 0) #define NS_EVENT_CLIENTCONTROL (NS_EVENTCLASS + 1) #define NS_EVENT_DELZONE (NS_EVENTCLASS + 2) /*% * Name server state. Better here than in lots of separate global variables. */ struct ns_server { unsigned int magic; isc_mem_t * mctx; isc_task_t * task; /* Configurable data. */ isc_quota_t xfroutquota; isc_quota_t tcpquota; isc_quota_t recursionquota; dns_acl_t *blackholeacl; dns_acl_t *keepresporder; char * statsfile; /*%< Statistics file name */ char * dumpfile; /*%< Dump file name */ char * secrootsfile; /*%< Secroots file name */ char * bindkeysfile; /*%< bind.keys file name */ char * recfile; /*%< Recursive file name */ isc_boolean_t version_set; /*%< User has set version */ char * version; /*%< User-specified version */ isc_boolean_t hostname_set; /*%< User has set hostname */ char * hostname; /*%< User-specified hostname */ /*% Use hostname for server id */ isc_boolean_t server_usehostname; char * server_id; /*%< User-specified server id */ /*% * Current ACL environment. This defines the * current values of the localhost and localnets * ACLs. */ dns_aclenv_t aclenv; /* Server data structures. */ dns_loadmgr_t * loadmgr; dns_zonemgr_t * zonemgr; dns_viewlist_t viewlist; ns_interfacemgr_t * interfacemgr; dns_db_t * in_roothints; dns_tkeyctx_t * tkeyctx; isc_timer_t * interface_timer; isc_timer_t * heartbeat_timer; isc_timer_t * pps_timer; isc_timer_t * tat_timer; isc_uint32_t interface_interval; isc_uint32_t heartbeat_interval; isc_mutex_t reload_event_lock; isc_event_t * reload_event; isc_boolean_t flushonshutdown; isc_boolean_t log_queries; /*%< For BIND 8 compatibility */ ns_cachelist_t cachelist; /*%< Possibly shared caches */ isc_stats_t * nsstats; /*%< Server stats */ dns_stats_t * rcvquerystats; /*% Incoming query stats */ dns_stats_t * opcodestats; /*%< Incoming message stats */ isc_stats_t * zonestats; /*% Zone management stats */ isc_stats_t * resolverstats; /*% Resolver stats */ isc_stats_t * sockstats; /*%< Socket stats */ isc_stats_t * udpinstats4; /*%< Traffic size: UDPv4 in */ isc_stats_t * udpoutstats4; /*%< Traffic size: UDPv4 out */ isc_stats_t * udpinstats6; /*%< Traffic size: UDPv6 in */ isc_stats_t * udpoutstats6; /*%< Traffic size: UDPv6 out */ isc_stats_t * tcpinstats4; /*%< Traffic size: TCPv4 in */ isc_stats_t * tcpoutstats4; /*%< Traffic size: TCPv4 out */ isc_stats_t * tcpinstats6; /*%< Traffic size: TCPv6 in */ isc_stats_t * tcpoutstats6; /*%< Traffic size: TCPv6 out */ dns_stats_t * rcodestats; /*%< Sent Response code stats */ ns_controls_t * controls; /*%< Control channels */ unsigned int dispatchgen; ns_dispatchlist_t dispatches; dns_acache_t *acache; ns_statschannellist_t statschannels; dns_tsigkey_t *sessionkey; char *session_keyfile; dns_name_t *session_keyname; unsigned int session_keyalg; isc_uint16_t session_keybits; isc_boolean_t interface_auto; unsigned char secret[32]; /*%< Server Cookie Secret */ ns_cookiealg_t cookiealg; dns_dtenv_t *dtenv; /*%< Dnstap environment */ char * lockfile; isc_uint16_t transfer_tcp_message_size; }; #define NS_SERVER_MAGIC ISC_MAGIC('S','V','E','R') #define NS_SERVER_VALID(s) ISC_MAGIC_VALID(s, NS_SERVER_MAGIC) /*% * Server statistics counters. Used as isc_statscounter_t values. */ enum { dns_nsstatscounter_requestv4 = 0, dns_nsstatscounter_requestv6 = 1, dns_nsstatscounter_edns0in = 2, dns_nsstatscounter_badednsver = 3, dns_nsstatscounter_tsigin = 4, dns_nsstatscounter_sig0in = 5, dns_nsstatscounter_invalidsig = 6, dns_nsstatscounter_requesttcp = 7, dns_nsstatscounter_authrej = 8, dns_nsstatscounter_recurserej = 9, dns_nsstatscounter_xfrrej = 10, dns_nsstatscounter_updaterej = 11, dns_nsstatscounter_response = 12, dns_nsstatscounter_truncatedresp = 13, dns_nsstatscounter_edns0out = 14, dns_nsstatscounter_tsigout = 15, dns_nsstatscounter_sig0out = 16, dns_nsstatscounter_success = 17, dns_nsstatscounter_authans = 18, dns_nsstatscounter_nonauthans = 19, dns_nsstatscounter_referral = 20, dns_nsstatscounter_nxrrset = 21, dns_nsstatscounter_servfail = 22, dns_nsstatscounter_formerr = 23, dns_nsstatscounter_nxdomain = 24, dns_nsstatscounter_recursion = 25, dns_nsstatscounter_duplicate = 26, dns_nsstatscounter_dropped = 27, dns_nsstatscounter_failure = 28, dns_nsstatscounter_xfrdone = 29, dns_nsstatscounter_updatereqfwd = 30, dns_nsstatscounter_updaterespfwd = 31, dns_nsstatscounter_updatefwdfail = 32, dns_nsstatscounter_updatedone = 33, dns_nsstatscounter_updatefail = 34, dns_nsstatscounter_updatebadprereq = 35, dns_nsstatscounter_recursclients = 36, dns_nsstatscounter_dns64 = 37, dns_nsstatscounter_ratedropped = 38, dns_nsstatscounter_rateslipped = 39, dns_nsstatscounter_rpz_rewrites = 40, dns_nsstatscounter_udp = 41, dns_nsstatscounter_tcp = 42, dns_nsstatscounter_nsidopt = 43, dns_nsstatscounter_expireopt = 44, dns_nsstatscounter_otheropt = 45, dns_nsstatscounter_ecsopt = 46, dns_nsstatscounter_nxdomainredirect = 47, dns_nsstatscounter_nxdomainredirect_rlookup = 48, dns_nsstatscounter_cookiein = 49, dns_nsstatscounter_cookiebadsize = 50, dns_nsstatscounter_cookiebadtime = 51, dns_nsstatscounter_cookienomatch = 52, dns_nsstatscounter_cookiematch = 53, dns_nsstatscounter_cookienew = 54, dns_nsstatscounter_badcookie = 55, dns_nsstatscounter_keytagopt = 56, dns_nsstatscounter_max = 57 }; /*% * Traffic size statistics counters. Used as isc_statscounter_t values. */ enum { dns_sizecounter_in_0 = 0, dns_sizecounter_in_16 = 1, dns_sizecounter_in_32 = 2, dns_sizecounter_in_48 = 3, dns_sizecounter_in_64 = 4, dns_sizecounter_in_80 = 5, dns_sizecounter_in_96 = 6, dns_sizecounter_in_112 = 7, dns_sizecounter_in_128 = 8, dns_sizecounter_in_144 = 9, dns_sizecounter_in_160 = 10, dns_sizecounter_in_176 = 11, dns_sizecounter_in_192 = 12, dns_sizecounter_in_208 = 13, dns_sizecounter_in_224 = 14, dns_sizecounter_in_240 = 15, dns_sizecounter_in_256 = 16, dns_sizecounter_in_272 = 17, dns_sizecounter_in_288 = 18, dns_sizecounter_in_max = 19, }; enum { dns_sizecounter_out_0 = 0, dns_sizecounter_out_16 = 1, dns_sizecounter_out_32 = 2, dns_sizecounter_out_48 = 3, dns_sizecounter_out_64 = 4, dns_sizecounter_out_80 = 5, dns_sizecounter_out_96 = 6, dns_sizecounter_out_112 = 7, dns_sizecounter_out_128 = 8, dns_sizecounter_out_144 = 9, dns_sizecounter_out_160 = 10, dns_sizecounter_out_176 = 11, dns_sizecounter_out_192 = 12, dns_sizecounter_out_208 = 13, dns_sizecounter_out_224 = 14, dns_sizecounter_out_240 = 15, dns_sizecounter_out_256 = 16, dns_sizecounter_out_272 = 17, dns_sizecounter_out_288 = 18, dns_sizecounter_out_304 = 19, dns_sizecounter_out_320 = 20, dns_sizecounter_out_336 = 21, dns_sizecounter_out_352 = 22, dns_sizecounter_out_368 = 23, dns_sizecounter_out_384 = 24, dns_sizecounter_out_400 = 25, dns_sizecounter_out_416 = 26, dns_sizecounter_out_432 = 27, dns_sizecounter_out_448 = 28, dns_sizecounter_out_464 = 29, dns_sizecounter_out_480 = 30, dns_sizecounter_out_496 = 31, dns_sizecounter_out_512 = 32, dns_sizecounter_out_528 = 33, dns_sizecounter_out_544 = 34, dns_sizecounter_out_560 = 35, dns_sizecounter_out_576 = 36, dns_sizecounter_out_592 = 37, dns_sizecounter_out_608 = 38, dns_sizecounter_out_624 = 39, dns_sizecounter_out_640 = 40, dns_sizecounter_out_656 = 41, dns_sizecounter_out_672 = 42, dns_sizecounter_out_688 = 43, dns_sizecounter_out_704 = 44, dns_sizecounter_out_720 = 45, dns_sizecounter_out_736 = 46, dns_sizecounter_out_752 = 47, dns_sizecounter_out_768 = 48, dns_sizecounter_out_784 = 49, dns_sizecounter_out_800 = 50, dns_sizecounter_out_816 = 51, dns_sizecounter_out_832 = 52, dns_sizecounter_out_848 = 53, dns_sizecounter_out_864 = 54, dns_sizecounter_out_880 = 55, dns_sizecounter_out_896 = 56, dns_sizecounter_out_912 = 57, dns_sizecounter_out_928 = 58, dns_sizecounter_out_944 = 59, dns_sizecounter_out_960 = 60, dns_sizecounter_out_976 = 61, dns_sizecounter_out_992 = 62, dns_sizecounter_out_1008 = 63, dns_sizecounter_out_1024 = 64, dns_sizecounter_out_1040 = 65, dns_sizecounter_out_1056 = 66, dns_sizecounter_out_1072 = 67, dns_sizecounter_out_1088 = 68, dns_sizecounter_out_1104 = 69, dns_sizecounter_out_1120 = 70, dns_sizecounter_out_1136 = 71, dns_sizecounter_out_1152 = 72, dns_sizecounter_out_1168 = 73, dns_sizecounter_out_1184 = 74, dns_sizecounter_out_1200 = 75, dns_sizecounter_out_1216 = 76, dns_sizecounter_out_1232 = 77, dns_sizecounter_out_1248 = 78, dns_sizecounter_out_1264 = 79, dns_sizecounter_out_1280 = 80, dns_sizecounter_out_1296 = 81, dns_sizecounter_out_1312 = 82, dns_sizecounter_out_1328 = 83, dns_sizecounter_out_1344 = 84, dns_sizecounter_out_1360 = 85, dns_sizecounter_out_1376 = 86, dns_sizecounter_out_1392 = 87, dns_sizecounter_out_1408 = 88, dns_sizecounter_out_1424 = 89, dns_sizecounter_out_1440 = 90, dns_sizecounter_out_1456 = 91, dns_sizecounter_out_1472 = 92, dns_sizecounter_out_1488 = 93, dns_sizecounter_out_1504 = 94, dns_sizecounter_out_1520 = 95, dns_sizecounter_out_1536 = 96, dns_sizecounter_out_1552 = 97, dns_sizecounter_out_1568 = 98, dns_sizecounter_out_1584 = 99, dns_sizecounter_out_1600 = 100, dns_sizecounter_out_1616 = 101, dns_sizecounter_out_1632 = 102, dns_sizecounter_out_1648 = 103, dns_sizecounter_out_1664 = 104, dns_sizecounter_out_1680 = 105, dns_sizecounter_out_1696 = 106, dns_sizecounter_out_1712 = 107, dns_sizecounter_out_1728 = 108, dns_sizecounter_out_1744 = 109, dns_sizecounter_out_1760 = 110, dns_sizecounter_out_1776 = 111, dns_sizecounter_out_1792 = 112, dns_sizecounter_out_1808 = 113, dns_sizecounter_out_1824 = 114, dns_sizecounter_out_1840 = 115, dns_sizecounter_out_1856 = 116, dns_sizecounter_out_1872 = 117, dns_sizecounter_out_1888 = 118, dns_sizecounter_out_1904 = 119, dns_sizecounter_out_1920 = 120, dns_sizecounter_out_1936 = 121, dns_sizecounter_out_1952 = 122, dns_sizecounter_out_1968 = 123, dns_sizecounter_out_1984 = 124, dns_sizecounter_out_2000 = 125, dns_sizecounter_out_2016 = 126, dns_sizecounter_out_2032 = 127, dns_sizecounter_out_2048 = 128, dns_sizecounter_out_2064 = 129, dns_sizecounter_out_2080 = 130, dns_sizecounter_out_2096 = 131, dns_sizecounter_out_2112 = 132, dns_sizecounter_out_2128 = 133, dns_sizecounter_out_2144 = 134, dns_sizecounter_out_2160 = 135, dns_sizecounter_out_2176 = 136, dns_sizecounter_out_2192 = 137, dns_sizecounter_out_2208 = 138, dns_sizecounter_out_2224 = 139, dns_sizecounter_out_2240 = 140, dns_sizecounter_out_2256 = 141, dns_sizecounter_out_2272 = 142, dns_sizecounter_out_2288 = 143, dns_sizecounter_out_2304 = 144, dns_sizecounter_out_2320 = 145, dns_sizecounter_out_2336 = 146, dns_sizecounter_out_2352 = 147, dns_sizecounter_out_2368 = 148, dns_sizecounter_out_2384 = 149, dns_sizecounter_out_2400 = 150, dns_sizecounter_out_2416 = 151, dns_sizecounter_out_2432 = 152, dns_sizecounter_out_2448 = 153, dns_sizecounter_out_2464 = 154, dns_sizecounter_out_2480 = 155, dns_sizecounter_out_2496 = 156, dns_sizecounter_out_2512 = 157, dns_sizecounter_out_2528 = 158, dns_sizecounter_out_2544 = 159, dns_sizecounter_out_2560 = 160, dns_sizecounter_out_2576 = 161, dns_sizecounter_out_2592 = 162, dns_sizecounter_out_2608 = 163, dns_sizecounter_out_2624 = 164, dns_sizecounter_out_2640 = 165, dns_sizecounter_out_2656 = 166, dns_sizecounter_out_2672 = 167, dns_sizecounter_out_2688 = 168, dns_sizecounter_out_2704 = 169, dns_sizecounter_out_2720 = 170, dns_sizecounter_out_2736 = 171, dns_sizecounter_out_2752 = 172, dns_sizecounter_out_2768 = 173, dns_sizecounter_out_2784 = 174, dns_sizecounter_out_2800 = 175, dns_sizecounter_out_2816 = 176, dns_sizecounter_out_2832 = 177, dns_sizecounter_out_2848 = 178, dns_sizecounter_out_2864 = 179, dns_sizecounter_out_2880 = 180, dns_sizecounter_out_2896 = 181, dns_sizecounter_out_2912 = 182, dns_sizecounter_out_2928 = 183, dns_sizecounter_out_2944 = 184, dns_sizecounter_out_2960 = 185, dns_sizecounter_out_2976 = 186, dns_sizecounter_out_2992 = 187, dns_sizecounter_out_3008 = 188, dns_sizecounter_out_3024 = 189, dns_sizecounter_out_3040 = 190, dns_sizecounter_out_3056 = 191, dns_sizecounter_out_3072 = 192, dns_sizecounter_out_3088 = 193, dns_sizecounter_out_3104 = 194, dns_sizecounter_out_3120 = 195, dns_sizecounter_out_3136 = 196, dns_sizecounter_out_3152 = 197, dns_sizecounter_out_3168 = 198, dns_sizecounter_out_3184 = 199, dns_sizecounter_out_3200 = 200, dns_sizecounter_out_3216 = 201, dns_sizecounter_out_3232 = 202, dns_sizecounter_out_3248 = 203, dns_sizecounter_out_3264 = 204, dns_sizecounter_out_3280 = 205, dns_sizecounter_out_3296 = 206, dns_sizecounter_out_3312 = 207, dns_sizecounter_out_3328 = 208, dns_sizecounter_out_3344 = 209, dns_sizecounter_out_3360 = 210, dns_sizecounter_out_3376 = 211, dns_sizecounter_out_3392 = 212, dns_sizecounter_out_3408 = 213, dns_sizecounter_out_3424 = 214, dns_sizecounter_out_3440 = 215, dns_sizecounter_out_3456 = 216, dns_sizecounter_out_3472 = 217, dns_sizecounter_out_3488 = 218, dns_sizecounter_out_3504 = 219, dns_sizecounter_out_3520 = 220, dns_sizecounter_out_3536 = 221, dns_sizecounter_out_3552 = 222, dns_sizecounter_out_3568 = 223, dns_sizecounter_out_3584 = 224, dns_sizecounter_out_3600 = 225, dns_sizecounter_out_3616 = 226, dns_sizecounter_out_3632 = 227, dns_sizecounter_out_3648 = 228, dns_sizecounter_out_3664 = 229, dns_sizecounter_out_3680 = 230, dns_sizecounter_out_3696 = 231, dns_sizecounter_out_3712 = 232, dns_sizecounter_out_3728 = 233, dns_sizecounter_out_3744 = 234, dns_sizecounter_out_3760 = 235, dns_sizecounter_out_3776 = 236, dns_sizecounter_out_3792 = 237, dns_sizecounter_out_3808 = 238, dns_sizecounter_out_3824 = 239, dns_sizecounter_out_3840 = 240, dns_sizecounter_out_3856 = 241, dns_sizecounter_out_3872 = 242, dns_sizecounter_out_3888 = 243, dns_sizecounter_out_3904 = 244, dns_sizecounter_out_3920 = 245, dns_sizecounter_out_3936 = 246, dns_sizecounter_out_3952 = 247, dns_sizecounter_out_3968 = 248, dns_sizecounter_out_3984 = 249, dns_sizecounter_out_4000 = 250, dns_sizecounter_out_4016 = 251, dns_sizecounter_out_4032 = 252, dns_sizecounter_out_4048 = 253, dns_sizecounter_out_4064 = 254, dns_sizecounter_out_4080 = 255, dns_sizecounter_out_4096 = 256, dns_sizecounter_out_max = 257 }; void ns_server_create(isc_mem_t *mctx, ns_server_t **serverp); /*%< * Create a server object with default settings. * This function either succeeds or causes the program to exit * with a fatal error. */ void ns_server_destroy(ns_server_t **serverp); /*%< * Destroy a server object, freeing its memory. */ void ns_server_reloadwanted(ns_server_t *server); /*%< * Inform a server that a reload is wanted. This function * may be called asynchronously, from outside the server's task. * If a reload is already scheduled or in progress, the call * is ignored. */ void ns_server_scan_interfaces(ns_server_t *server); /*%< * Trigger a interface scan. * Must only be called when running under server->task. */ void ns_server_flushonshutdown(ns_server_t *server, isc_boolean_t flush); /*%< * Inform the server that the zones should be flushed to disk on shutdown. */ isc_result_t ns_server_reloadcommand(ns_server_t *server, isc_lex_t *lex, isc_buffer_t **text); /*%< * Act on a "reload" command from the command channel. */ isc_result_t ns_server_reconfigcommand(ns_server_t *server); /*%< * Act on a "reconfig" command from the command channel. */ isc_result_t ns_server_notifycommand(ns_server_t *server, isc_lex_t *lex, isc_buffer_t **text); /*%< * Act on a "notify" command from the command channel. */ isc_result_t ns_server_refreshcommand(ns_server_t *server, isc_lex_t *lex, isc_buffer_t **text); /*%< * Act on a "refresh" command from the command channel. */ isc_result_t ns_server_retransfercommand(ns_server_t *server, isc_lex_t *lex, isc_buffer_t **text); /*%< * Act on a "retransfer" command from the command channel. */ isc_result_t ns_server_togglequerylog(ns_server_t *server, isc_lex_t *lex); /*%< * Enable/disable logging of queries. (Takes "yes" or "no" argument, * but can also be used as a toggle for backward comptibility.) */ /*% * Save the current NTAs for all views to files. */ isc_result_t ns_server_saventa(ns_server_t *server); /*% * Load NTAs for all views from files. */ isc_result_t ns_server_loadnta(ns_server_t *server); /*% * Dump the current statistics to the statistics file. */ isc_result_t ns_server_dumpstats(ns_server_t *server); /*% * Dump the current cache to the dump file. */ isc_result_t ns_server_dumpdb(ns_server_t *server, isc_lex_t *lex, isc_buffer_t **text); /*% * Dump the current security roots to the secroots file. */ isc_result_t ns_server_dumpsecroots(ns_server_t *server, isc_lex_t *lex, isc_buffer_t **text); /*% * Change or increment the server debug level. */ isc_result_t ns_server_setdebuglevel(ns_server_t *server, isc_lex_t *lex); /*% * Flush the server's cache(s) */ isc_result_t ns_server_flushcache(ns_server_t *server, isc_lex_t *lex); /*% * Flush a particular name from the server's cache. If 'tree' is false, * also flush the name from the ADB and badcache. If 'tree' is true, also * flush all the names under the specified name. */ isc_result_t ns_server_flushnode(ns_server_t *server, isc_lex_t *lex, isc_boolean_t tree); /*% * Report the server's status. */ isc_result_t ns_server_status(ns_server_t *server, isc_buffer_t **text); /*% * Report a list of dynamic and static tsig keys, per view. */ isc_result_t ns_server_tsiglist(ns_server_t *server, isc_buffer_t **text); /*% * Delete a specific key (with optional view). */ isc_result_t ns_server_tsigdelete(ns_server_t *server, isc_lex_t *lex, isc_buffer_t **text); /*% * Enable or disable updates for a zone. */ isc_result_t ns_server_freeze(ns_server_t *server, isc_boolean_t freeze, isc_lex_t *lex, isc_buffer_t **text); /*% * Dump zone updates to disk, optionally removing the journal file */ isc_result_t ns_server_sync(ns_server_t *server, isc_lex_t *lex, isc_buffer_t **text); /*% * Update a zone's DNSKEY set from the key repository. If * the command that triggered the call to this function was "sign", * then force a full signing of the zone. If it was "loadkeys", * then don't sign the zone; any needed changes to signatures can * take place incrementally. */ isc_result_t ns_server_rekey(ns_server_t *server, isc_lex_t *lex, isc_buffer_t **text); /*% * Dump the current recursive queries. */ isc_result_t ns_server_dumprecursing(ns_server_t *server); /*% * Maintain a list of dispatches that require reserved ports. */ void ns_add_reserved_dispatch(ns_server_t *server, const isc_sockaddr_t *addr); /*% * Enable or disable dnssec validation. */ isc_result_t ns_server_validation(ns_server_t *server, isc_lex_t *lex, isc_buffer_t **text); /*% * Add a zone to a running process, or modify an existing zone */ isc_result_t ns_server_changezone(ns_server_t *server, char *command, isc_buffer_t **text); /*% * Deletes a zone from a running process */ isc_result_t ns_server_delzone(ns_server_t *server, isc_lex_t *lex, isc_buffer_t **text); /*% * Show current configuration for a given zone */ isc_result_t ns_server_showzone(ns_server_t *server, isc_lex_t *lex, isc_buffer_t **text); /*% * Lists the status of the signing records for a given zone. */ isc_result_t ns_server_signing(ns_server_t *server, isc_lex_t *lex, isc_buffer_t **text); /*% * Lists status information for a given zone (e.g., name, type, files, * load time, expiry, etc). */ isc_result_t ns_server_zonestatus(ns_server_t *server, isc_lex_t *lex, isc_buffer_t **text); /*% * Adds/updates a Negative Trust Anchor (NTA) for a specified name and * duration, in a particular view if specified, or in all views. */ isc_result_t ns_server_nta(ns_server_t *server, isc_lex_t *lex, isc_boolean_t readonly, isc_buffer_t **text); /*% * Generates a test sequence that is only for use in system tests. The * argument is the size of required output in bytes. */ isc_result_t ns_server_testgen(isc_lex_t *lex, isc_buffer_t **text); /*% * Force fefresh or print status for managed keys zones. */ isc_result_t ns_server_mkeys(ns_server_t *server, isc_lex_t *lex, isc_buffer_t **text); /*% * Close and reopen DNSTAP output file. */ isc_result_t ns_server_dnstap(ns_server_t *server, isc_lex_t *lex, isc_buffer_t **text); #endif /* NAMED_SERVER_H */ bind9-9.11.3+dfsg/bin/named/include/named/sortlist.h000066400000000000000000000043611325250447100221370ustar00rootroot00000000000000/* * Copyright (C) 2000, 2001, 2004-2007, 2016 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* $Id: sortlist.h,v 1.11 2007/06/19 23:46:59 tbox Exp $ */ #ifndef NAMED_SORTLIST_H #define NAMED_SORTLIST_H 1 /*! \file */ #include #include /*% * Type for callback functions that rank addresses. */ typedef int (*dns_addressorderfunc_t)(const isc_netaddr_t *address, const void *arg); /*% * Return value type for setup_sortlist. */ typedef enum { NS_SORTLISTTYPE_NONE, NS_SORTLISTTYPE_1ELEMENT, NS_SORTLISTTYPE_2ELEMENT } ns_sortlisttype_t; ns_sortlisttype_t ns_sortlist_setup(dns_acl_t *acl, isc_netaddr_t *clientaddr, const void **argp); /*%< * Find the sortlist statement in 'acl' that applies to 'clientaddr', if any. * * If a 1-element sortlist item applies, return NS_SORTLISTTYPE_1ELEMENT and * make '*argp' point to the matching subelement. * * If a 2-element sortlist item applies, return NS_SORTLISTTYPE_2ELEMENT and * make '*argp' point to ACL that forms the second element. * * If no sortlist item applies, return NS_SORTLISTTYPE_NONE and set '*argp' * to NULL. */ int ns_sortlist_addrorder1(const isc_netaddr_t *addr, const void *arg); /*%< * Find the sort order of 'addr' in 'arg', the matching element * of a 1-element top-level sortlist statement. */ int ns_sortlist_addrorder2(const isc_netaddr_t *addr, const void *arg); /*%< * Find the sort order of 'addr' in 'arg', a topology-like * ACL forming the second element in a 2-element top-level * sortlist statement. */ void ns_sortlist_byaddrsetup(dns_acl_t *sortlist_acl, isc_netaddr_t *client_addr, dns_addressorderfunc_t *orderp, const void **argp); /*%< * Find the sortlist statement in 'acl' that applies to 'clientaddr', if any. * If a sortlist statement applies, return in '*orderp' a pointer to a function * for ranking network addresses based on that sortlist statement, and in * '*argp' an argument to pass to said function. If no sortlist statement * applies, set '*orderp' and '*argp' to NULL. */ #endif /* NAMED_SORTLIST_H */ bind9-9.11.3+dfsg/bin/named/include/named/statschannel.h000066400000000000000000000023441325250447100227420ustar00rootroot00000000000000/* * Copyright (C) 2008, 2016 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* $Id: statschannel.h,v 1.3 2008/04/03 05:55:51 marka Exp $ */ #ifndef NAMED_STATSCHANNEL_H #define NAMED_STATSCHANNEL_H 1 /*! \file * \brief * The statistics channels built-in the name server. */ #include #include #include #define NS_STATSCHANNEL_HTTPPORT 80 isc_result_t ns_statschannels_configure(ns_server_t *server, const cfg_obj_t *config, cfg_aclconfctx_t *aclconfctx); /*%< * [Re]configure the statistics channels. * * If it is no longer there but was previously configured, destroy * it here. * * If the IP address or port has changed, destroy the old server * and create a new one. */ void ns_statschannels_shutdown(ns_server_t *server); /*%< * Initiate shutdown of all the statistics channel listeners. */ isc_result_t ns_stats_dump(ns_server_t *server, FILE *fp); /*%< * Dump statistics counters managed by the server to the file fp. */ #endif /* NAMED_STATSCHANNEL_H */ bind9-9.11.3+dfsg/bin/named/include/named/tkeyconf.h000066400000000000000000000020321325250447100220670ustar00rootroot00000000000000/* * Copyright (C) 1999-2001, 2004-2007, 2016 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* $Id: tkeyconf.h,v 1.16 2007/06/19 23:46:59 tbox Exp $ */ #ifndef NS_TKEYCONF_H #define NS_TKEYCONF_H 1 /*! \file */ #include #include #include ISC_LANG_BEGINDECLS isc_result_t ns_tkeyctx_fromconfig(const cfg_obj_t *options, isc_mem_t *mctx, isc_entropy_t *ectx, dns_tkeyctx_t **tctxp); /*%< * Create a TKEY context and configure it, including the default DH key * and default domain, according to 'options'. * * Requires: *\li 'cfg' is a valid configuration options object. *\li 'mctx' is not NULL *\li 'ectx' is not NULL *\li 'tctx' is not NULL *\li '*tctx' is NULL * * Returns: *\li ISC_R_SUCCESS *\li ISC_R_NOMEMORY */ ISC_LANG_ENDDECLS #endif /* NS_TKEYCONF_H */ bind9-9.11.3+dfsg/bin/named/include/named/tsigconf.h000066400000000000000000000020021325250447100220560ustar00rootroot00000000000000/* * Copyright (C) 1999-2001, 2004-2007, 2009, 2016 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* $Id: tsigconf.h,v 1.18 2009/06/11 23:47:55 tbox Exp $ */ #ifndef NS_TSIGCONF_H #define NS_TSIGCONF_H 1 /*! \file */ #include #include ISC_LANG_BEGINDECLS isc_result_t ns_tsigkeyring_fromconfig(const cfg_obj_t *config, const cfg_obj_t *vconfig, isc_mem_t *mctx, dns_tsig_keyring_t **ringp); /*%< * Create a TSIG key ring and configure it according to the 'key' * statements in the global and view configuration objects. * * Requires: * \li 'config' is not NULL. * \li 'vconfig' is not NULL. * \li 'mctx' is not NULL * \li 'ringp' is not NULL, and '*ringp' is NULL * * Returns: * \li ISC_R_SUCCESS * \li ISC_R_NOMEMORY */ ISC_LANG_ENDDECLS #endif /* NS_TSIGCONF_H */ bind9-9.11.3+dfsg/bin/named/include/named/types.h000066400000000000000000000027671325250447100214300ustar00rootroot00000000000000/* * Copyright (C) 1999-2001, 2004-2009, 2015, 2016 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* $Id: types.h,v 1.31 2009/01/09 23:47:45 tbox Exp $ */ #ifndef NAMED_TYPES_H #define NAMED_TYPES_H 1 /*! \file */ #include typedef struct ns_cache ns_cache_t; typedef ISC_LIST(ns_cache_t) ns_cachelist_t; typedef struct ns_client ns_client_t; typedef struct ns_clientmgr ns_clientmgr_t; typedef struct ns_query ns_query_t; typedef struct ns_server ns_server_t; typedef struct ns_xmld ns_xmld_t; typedef struct ns_xmldmgr ns_xmldmgr_t; typedef struct ns_interface ns_interface_t; typedef struct ns_interfacemgr ns_interfacemgr_t; typedef struct ns_lwresd ns_lwresd_t; typedef struct ns_lwreslistener ns_lwreslistener_t; typedef struct ns_lwdclient ns_lwdclient_t; typedef struct ns_lwdclientmgr ns_lwdclientmgr_t; typedef struct ns_lwsearchlist ns_lwsearchlist_t; typedef struct ns_lwsearchctx ns_lwsearchctx_t; typedef struct ns_controls ns_controls_t; typedef struct ns_dispatch ns_dispatch_t; typedef ISC_LIST(ns_dispatch_t) ns_dispatchlist_t; typedef struct ns_statschannel ns_statschannel_t; typedef ISC_LIST(ns_statschannel_t) ns_statschannellist_t; typedef enum { ns_cookiealg_aes, ns_cookiealg_sha1, ns_cookiealg_sha256 } ns_cookiealg_t; #endif /* NAMED_TYPES_H */ bind9-9.11.3+dfsg/bin/named/include/named/update.h000066400000000000000000000013211325250447100215270ustar00rootroot00000000000000/* * Copyright (C) 1999-2001, 2004, 2005, 2007, 2016 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* $Id: update.h,v 1.13 2007/06/19 23:46:59 tbox Exp $ */ #ifndef NAMED_UPDATE_H #define NAMED_UPDATE_H 1 /***** ***** Module Info *****/ /*! \file * \brief * RFC2136 Dynamic Update */ /*** *** Imports ***/ #include #include /*** *** Types. ***/ /*** *** Functions ***/ void ns_update_start(ns_client_t *client, isc_result_t sigresult); #endif /* NAMED_UPDATE_H */ bind9-9.11.3+dfsg/bin/named/include/named/xfrout.h000066400000000000000000000011761325250447100216040ustar00rootroot00000000000000/* * Copyright (C) 1999-2001, 2004, 2005, 2007, 2016 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* $Id: xfrout.h,v 1.12 2007/06/19 23:46:59 tbox Exp $ */ #ifndef NAMED_XFROUT_H #define NAMED_XFROUT_H 1 /***** ***** Module Info *****/ /*! \file * \brief * Outgoing zone transfers (AXFR + IXFR). */ /*** *** Functions ***/ void ns_xfr_start(ns_client_t *client, dns_rdatatype_t xfrtype); #endif /* NAMED_XFROUT_H */ bind9-9.11.3+dfsg/bin/named/include/named/zoneconf.h000066400000000000000000000036761325250447100221050ustar00rootroot00000000000000/* * Copyright (C) 1999-2002, 2004-2007, 2010, 2011, 2015, 2016 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* $Id: zoneconf.h,v 1.30 2011/08/30 23:46:51 tbox Exp $ */ #ifndef NS_ZONECONF_H #define NS_ZONECONF_H 1 /*! \file */ #include #include #include #include ISC_LANG_BEGINDECLS isc_result_t ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, const cfg_obj_t *zconfig, cfg_aclconfctx_t *ac, dns_zone_t *zone, dns_zone_t *raw); /*%< * Configure or reconfigure a zone according to the named.conf * data in 'cctx' and 'czone'. * * The zone origin is not configured, it is assumed to have been set * at zone creation time. * * Require: * \li 'lctx' to be initialized or NULL. * \li 'cctx' to be initialized or NULL. * \li 'ac' to point to an initialized ns_aclconfctx_t. * \li 'czone' to be initialized. * \li 'zone' to be initialized. */ isc_boolean_t ns_zone_reusable(dns_zone_t *zone, const cfg_obj_t *zconfig); /*%< * If 'zone' can be safely reconfigured according to the configuration * data in 'zconfig', return ISC_TRUE. If the configuration data is so * different from the current zone state that the zone needs to be destroyed * and recreated, return ISC_FALSE. */ isc_result_t ns_zone_configure_writeable_dlz(dns_dlzdb_t *dlzdatabase, dns_zone_t *zone, dns_rdataclass_t rdclass, dns_name_t *name); /*%> * configure a DLZ zone, setting up the database methods and calling * postload to load the origin values * * Require: * \li 'dlzdatabase' to be a valid dlz database * \li 'zone' to be initialized. * \li 'rdclass' to be a valid rdataclass * \li 'name' to be a valid zone origin name */ ISC_LANG_ENDDECLS #endif /* NS_ZONECONF_H */ bind9-9.11.3+dfsg/bin/named/interfacemgr.c000066400000000000000000000766001325250447100202130ustar00rootroot00000000000000/* * Copyright (C) 1999-2002, 2004-2009, 2011-2017 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /*! \file */ #include #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_NET_ROUTE_H #include #if defined(RTM_VERSION) && defined(RTM_NEWADDR) && defined(RTM_DELADDR) #define USE_ROUTE_SOCKET 1 #define ROUTE_SOCKET_PROTOCOL PF_ROUTE #define MSGHDR rt_msghdr #define MSGTYPE rtm_type #endif #endif #if defined(HAVE_LINUX_NETLINK_H) && defined(HAVE_LINUX_RTNETLINK_H) #include #include #if defined(RTM_NEWADDR) && defined(RTM_DELADDR) #define USE_ROUTE_SOCKET 1 #define ROUTE_SOCKET_PROTOCOL PF_NETLINK #define MSGHDR nlmsghdr #define MSGTYPE nlmsg_type #endif #endif #ifdef TUNE_LARGE #define UDPBUFFERS 32768 #else #define UDPBUFFERS 1000 #endif /* TUNE_LARGE */ #define IFMGR_MAGIC ISC_MAGIC('I', 'F', 'M', 'G') #define NS_INTERFACEMGR_VALID(t) ISC_MAGIC_VALID(t, IFMGR_MAGIC) #define IFMGR_COMMON_LOGARGS \ ns_g_lctx, NS_LOGCATEGORY_NETWORK, NS_LOGMODULE_INTERFACEMGR /*% nameserver interface manager structure */ struct ns_interfacemgr { unsigned int magic; /*%< Magic number. */ int references; isc_mutex_t lock; isc_mem_t * mctx; /*%< Memory context. */ isc_taskmgr_t * taskmgr; /*%< Task manager. */ isc_socketmgr_t * socketmgr; /*%< Socket manager. */ dns_dispatchmgr_t * dispatchmgr; unsigned int generation; /*%< Current generation no. */ ns_listenlist_t * listenon4; ns_listenlist_t * listenon6; dns_aclenv_t aclenv; /*%< Localhost/localnets ACLs */ ISC_LIST(ns_interface_t) interfaces; /*%< List of interfaces. */ ISC_LIST(isc_sockaddr_t) listenon; #ifdef USE_ROUTE_SOCKET isc_task_t * task; isc_socket_t * route; unsigned char buf[2048]; #endif }; static void purge_old_interfaces(ns_interfacemgr_t *mgr); static void clearlistenon(ns_interfacemgr_t *mgr); #ifdef USE_ROUTE_SOCKET static void route_event(isc_task_t *task, isc_event_t *event) { isc_socketevent_t *sevent = NULL; ns_interfacemgr_t *mgr = NULL; isc_region_t r; isc_result_t result; struct MSGHDR *rtm; isc_boolean_t done = ISC_TRUE; UNUSED(task); REQUIRE(event->ev_type == ISC_SOCKEVENT_RECVDONE); mgr = event->ev_arg; sevent = (isc_socketevent_t *)event; if (sevent->result != ISC_R_SUCCESS) { if (sevent->result != ISC_R_CANCELED) isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR, "automatic interface scanning " "terminated: %s", isc_result_totext(sevent->result)); ns_interfacemgr_detach(&mgr); isc_event_free(&event); return; } rtm = (struct MSGHDR *)mgr->buf; #ifdef RTM_VERSION if (rtm->rtm_version != RTM_VERSION) { isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR, "automatic interface rescanning disabled: " "rtm->rtm_version mismatch (%u != %u) " "recompile required", rtm->rtm_version, RTM_VERSION); ns_interfacemgr_detach(&mgr); isc_event_free(&event); return; } #endif switch (rtm->MSGTYPE) { case RTM_NEWADDR: case RTM_DELADDR: if (mgr->route != NULL && ns_g_server->interface_auto) ns_server_scan_interfaces(ns_g_server); break; default: break; } LOCK(&mgr->lock); if (mgr->route != NULL) { /* * Look for next route event. */ r.base = mgr->buf; r.length = sizeof(mgr->buf); result = isc_socket_recv(mgr->route, &r, 1, mgr->task, route_event, mgr); if (result == ISC_R_SUCCESS) done = ISC_FALSE; } UNLOCK(&mgr->lock); if (done) ns_interfacemgr_detach(&mgr); isc_event_free(&event); return; } #endif isc_result_t ns_interfacemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr, isc_socketmgr_t *socketmgr, dns_dispatchmgr_t *dispatchmgr, isc_task_t *task, ns_interfacemgr_t **mgrp) { isc_result_t result; ns_interfacemgr_t *mgr; #ifndef USE_ROUTE_SOCKET UNUSED(task); #endif REQUIRE(mctx != NULL); REQUIRE(mgrp != NULL); REQUIRE(*mgrp == NULL); mgr = isc_mem_get(mctx, sizeof(*mgr)); if (mgr == NULL) return (ISC_R_NOMEMORY); mgr->mctx = NULL; isc_mem_attach(mctx, &mgr->mctx); result = isc_mutex_init(&mgr->lock); if (result != ISC_R_SUCCESS) goto cleanup_mem; mgr->taskmgr = taskmgr; mgr->socketmgr = socketmgr; mgr->dispatchmgr = dispatchmgr; mgr->generation = 1; mgr->listenon4 = NULL; mgr->listenon6 = NULL; ISC_LIST_INIT(mgr->interfaces); ISC_LIST_INIT(mgr->listenon); /* * The listen-on lists are initially empty. */ result = ns_listenlist_create(mctx, &mgr->listenon4); if (result != ISC_R_SUCCESS) goto cleanup_mem; ns_listenlist_attach(mgr->listenon4, &mgr->listenon6); result = dns_aclenv_init(mctx, &mgr->aclenv); if (result != ISC_R_SUCCESS) goto cleanup_listenon; #ifdef HAVE_GEOIP mgr->aclenv.geoip = ns_g_geoip; #endif #ifdef USE_ROUTE_SOCKET mgr->route = NULL; result = isc_socket_create(mgr->socketmgr, ROUTE_SOCKET_PROTOCOL, isc_sockettype_raw, &mgr->route); switch (result) { case ISC_R_NOPERM: case ISC_R_SUCCESS: case ISC_R_NOTIMPLEMENTED: case ISC_R_FAMILYNOSUPPORT: break; default: goto cleanup_aclenv; } mgr->task = NULL; if (mgr->route != NULL) isc_task_attach(task, &mgr->task); mgr->references = (mgr->route != NULL) ? 2 : 1; #else mgr->references = 1; #endif mgr->magic = IFMGR_MAGIC; *mgrp = mgr; #ifdef USE_ROUTE_SOCKET if (mgr->route != NULL) { isc_region_t r = { mgr->buf, sizeof(mgr->buf) }; result = isc_socket_recv(mgr->route, &r, 1, mgr->task, route_event, mgr); if (result != ISC_R_SUCCESS) { isc_task_detach(&mgr->task); isc_socket_detach(&mgr->route); ns_interfacemgr_detach(&mgr); } } #endif return (ISC_R_SUCCESS); #ifdef USE_ROUTE_SOCKET cleanup_aclenv: dns_aclenv_destroy(&mgr->aclenv); #endif cleanup_listenon: ns_listenlist_detach(&mgr->listenon4); ns_listenlist_detach(&mgr->listenon6); cleanup_mem: isc_mem_putanddetach(&mgr->mctx, mgr, sizeof(*mgr)); return (result); } static void ns_interfacemgr_destroy(ns_interfacemgr_t *mgr) { REQUIRE(NS_INTERFACEMGR_VALID(mgr)); #ifdef USE_ROUTE_SOCKET if (mgr->route != NULL) isc_socket_detach(&mgr->route); if (mgr->task != NULL) isc_task_detach(&mgr->task); #endif dns_aclenv_destroy(&mgr->aclenv); ns_listenlist_detach(&mgr->listenon4); ns_listenlist_detach(&mgr->listenon6); clearlistenon(mgr); DESTROYLOCK(&mgr->lock); mgr->magic = 0; isc_mem_putanddetach(&mgr->mctx, mgr, sizeof(*mgr)); } dns_aclenv_t * ns_interfacemgr_getaclenv(ns_interfacemgr_t *mgr) { return (&mgr->aclenv); } void ns_interfacemgr_attach(ns_interfacemgr_t *source, ns_interfacemgr_t **target) { REQUIRE(NS_INTERFACEMGR_VALID(source)); LOCK(&source->lock); INSIST(source->references > 0); source->references++; UNLOCK(&source->lock); *target = source; } void ns_interfacemgr_detach(ns_interfacemgr_t **targetp) { isc_result_t need_destroy = ISC_FALSE; ns_interfacemgr_t *target = *targetp; REQUIRE(target != NULL); REQUIRE(NS_INTERFACEMGR_VALID(target)); LOCK(&target->lock); REQUIRE(target->references > 0); target->references--; if (target->references == 0) need_destroy = ISC_TRUE; UNLOCK(&target->lock); if (need_destroy) ns_interfacemgr_destroy(target); *targetp = NULL; } void ns_interfacemgr_shutdown(ns_interfacemgr_t *mgr) { REQUIRE(NS_INTERFACEMGR_VALID(mgr)); /*% * Shut down and detach all interfaces. * By incrementing the generation count, we make purge_old_interfaces() * consider all interfaces "old". */ mgr->generation++; #ifdef USE_ROUTE_SOCKET LOCK(&mgr->lock); if (mgr->route != NULL) { isc_socket_cancel(mgr->route, mgr->task, ISC_SOCKCANCEL_RECV); isc_socket_detach(&mgr->route); isc_task_detach(&mgr->task); } UNLOCK(&mgr->lock); #endif purge_old_interfaces(mgr); } static isc_result_t ns_interface_create(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr, const char *name, ns_interface_t **ifpret) { ns_interface_t *ifp; isc_result_t result; int disp; REQUIRE(NS_INTERFACEMGR_VALID(mgr)); ifp = isc_mem_get(mgr->mctx, sizeof(*ifp)); if (ifp == NULL) return (ISC_R_NOMEMORY); ifp->mgr = NULL; ifp->generation = mgr->generation; ifp->addr = *addr; ifp->flags = 0; strlcpy(ifp->name, name, sizeof(ifp->name)); ifp->clientmgr = NULL; result = isc_mutex_init(&ifp->lock); if (result != ISC_R_SUCCESS) goto lock_create_failure; result = ns_clientmgr_create(mgr->mctx, mgr->taskmgr, ns_g_timermgr, &ifp->clientmgr); if (result != ISC_R_SUCCESS) { isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR, "ns_clientmgr_create() failed: %s", isc_result_totext(result)); goto clientmgr_create_failure; } for (disp = 0; disp < MAX_UDP_DISPATCH; disp++) ifp->udpdispatch[disp] = NULL; ifp->tcpsocket = NULL; /* * Create a single TCP client object. It will replace itself * with a new one as soon as it gets a connection, so the actual * connections will be handled in parallel even though there is * only one client initially. */ ifp->ntcptarget = 1; ifp->ntcpcurrent = 0; ifp->nudpdispatch = 0; ifp->dscp = -1; ISC_LINK_INIT(ifp, link); ns_interfacemgr_attach(mgr, &ifp->mgr); ISC_LIST_APPEND(mgr->interfaces, ifp, link); ifp->references = 1; ifp->magic = IFACE_MAGIC; *ifpret = ifp; return (ISC_R_SUCCESS); clientmgr_create_failure: DESTROYLOCK(&ifp->lock); lock_create_failure: ifp->magic = 0; isc_mem_put(mgr->mctx, ifp, sizeof(*ifp)); return (ISC_R_UNEXPECTED); } static isc_result_t ns_interface_listenudp(ns_interface_t *ifp) { isc_result_t result; unsigned int attrs; unsigned int attrmask; int disp, i; attrs = 0; attrs |= DNS_DISPATCHATTR_UDP; if (isc_sockaddr_pf(&ifp->addr) == AF_INET) attrs |= DNS_DISPATCHATTR_IPV4; else attrs |= DNS_DISPATCHATTR_IPV6; attrs |= DNS_DISPATCHATTR_NOLISTEN; attrmask = 0; attrmask |= DNS_DISPATCHATTR_UDP | DNS_DISPATCHATTR_TCP; attrmask |= DNS_DISPATCHATTR_IPV4 | DNS_DISPATCHATTR_IPV6; ifp->nudpdispatch = ISC_MIN(ns_g_udpdisp, MAX_UDP_DISPATCH); for (disp = 0; disp < ifp->nudpdispatch; disp++) { result = dns_dispatch_getudp_dup(ifp->mgr->dispatchmgr, ns_g_socketmgr, ns_g_taskmgr, &ifp->addr, 4096, UDPBUFFERS, 32768, 8219, 8237, attrs, attrmask, &ifp->udpdispatch[disp], disp == 0 ? NULL : ifp->udpdispatch[0]); if (result != ISC_R_SUCCESS) { isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR, "could not listen on UDP socket: %s", isc_result_totext(result)); goto udp_dispatch_failure; } } result = ns_clientmgr_createclients(ifp->clientmgr, ifp->nudpdispatch, ifp, ISC_FALSE); if (result != ISC_R_SUCCESS) { UNEXPECTED_ERROR(__FILE__, __LINE__, "UDP ns_clientmgr_createclients(): %s", isc_result_totext(result)); goto addtodispatch_failure; } return (ISC_R_SUCCESS); addtodispatch_failure: for (i = disp - 1; i >= 0; i--) { dns_dispatch_changeattributes(ifp->udpdispatch[i], 0, DNS_DISPATCHATTR_NOLISTEN); dns_dispatch_detach(&(ifp->udpdispatch[i])); } ifp->nudpdispatch = 0; udp_dispatch_failure: return (result); } static isc_result_t ns_interface_accepttcp(ns_interface_t *ifp) { isc_result_t result; /* * Open a TCP socket. */ result = isc_socket_create(ifp->mgr->socketmgr, isc_sockaddr_pf(&ifp->addr), isc_sockettype_tcp, &ifp->tcpsocket); if (result != ISC_R_SUCCESS) { isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR, "creating TCP socket: %s", isc_result_totext(result)); goto tcp_socket_failure; } isc_socket_setname(ifp->tcpsocket, "dispatcher", NULL); #ifndef ISC_ALLOW_MAPPED isc_socket_ipv6only(ifp->tcpsocket, ISC_TRUE); #endif result = isc_socket_bind(ifp->tcpsocket, &ifp->addr, ISC_SOCKET_REUSEADDRESS); if (result != ISC_R_SUCCESS) { isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR, "binding TCP socket: %s", isc_result_totext(result)); goto tcp_bind_failure; } if (ifp->dscp != -1) isc_socket_dscp(ifp->tcpsocket, ifp->dscp); result = isc_socket_listen(ifp->tcpsocket, ns_g_listen); if (result != ISC_R_SUCCESS) { isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR, "listening on TCP socket: %s", isc_result_totext(result)); goto tcp_listen_failure; } /* * If/when there a multiple filters listen to the * result. */ (void)isc_socket_filter(ifp->tcpsocket, "dataready"); result = ns_clientmgr_createclients(ifp->clientmgr, ifp->ntcptarget, ifp, ISC_TRUE); if (result != ISC_R_SUCCESS) { UNEXPECTED_ERROR(__FILE__, __LINE__, "TCP ns_clientmgr_createclients(): %s", isc_result_totext(result)); goto accepttcp_failure; } return (ISC_R_SUCCESS); accepttcp_failure: tcp_listen_failure: tcp_bind_failure: isc_socket_detach(&ifp->tcpsocket); tcp_socket_failure: return (result); } static isc_result_t ns_interface_setup(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr, const char *name, ns_interface_t **ifpret, isc_boolean_t accept_tcp, isc_dscp_t dscp, isc_boolean_t *addr_in_use) { isc_result_t result; ns_interface_t *ifp = NULL; REQUIRE(ifpret != NULL && *ifpret == NULL); REQUIRE(addr_in_use == NULL || *addr_in_use == ISC_FALSE); result = ns_interface_create(mgr, addr, name, &ifp); if (result != ISC_R_SUCCESS) return (result); ifp->dscp = dscp; result = ns_interface_listenudp(ifp); if (result != ISC_R_SUCCESS) { if ((result == ISC_R_ADDRINUSE) && (addr_in_use != NULL)) *addr_in_use = ISC_TRUE; goto cleanup_interface; } if (!ns_g_notcp && accept_tcp == ISC_TRUE) { result = ns_interface_accepttcp(ifp); if (result != ISC_R_SUCCESS) { if ((result == ISC_R_ADDRINUSE) && (addr_in_use != NULL)) *addr_in_use = ISC_TRUE; /* * XXXRTH We don't currently have a way to easily stop * dispatch service, so we currently return * ISC_R_SUCCESS (the UDP stuff will work even if TCP * creation failed). This will be fixed later. */ result = ISC_R_SUCCESS; } } *ifpret = ifp; return (result); cleanup_interface: ISC_LIST_UNLINK(ifp->mgr->interfaces, ifp, link); ns_interface_detach(&ifp); return (result); } void ns_interface_shutdown(ns_interface_t *ifp) { if (ifp->clientmgr != NULL) ns_clientmgr_destroy(&ifp->clientmgr); } static void ns_interface_destroy(ns_interface_t *ifp) { isc_mem_t *mctx = ifp->mgr->mctx; int disp; REQUIRE(NS_INTERFACE_VALID(ifp)); ns_interface_shutdown(ifp); for (disp = 0; disp < ifp->nudpdispatch; disp++) if (ifp->udpdispatch[disp] != NULL) { dns_dispatch_changeattributes(ifp->udpdispatch[disp], 0, DNS_DISPATCHATTR_NOLISTEN); dns_dispatch_detach(&(ifp->udpdispatch[disp])); } if (ifp->tcpsocket != NULL) isc_socket_detach(&ifp->tcpsocket); DESTROYLOCK(&ifp->lock); ns_interfacemgr_detach(&ifp->mgr); ifp->magic = 0; isc_mem_put(mctx, ifp, sizeof(*ifp)); } void ns_interface_attach(ns_interface_t *source, ns_interface_t **target) { REQUIRE(NS_INTERFACE_VALID(source)); LOCK(&source->lock); INSIST(source->references > 0); source->references++; UNLOCK(&source->lock); *target = source; } void ns_interface_detach(ns_interface_t **targetp) { isc_result_t need_destroy = ISC_FALSE; ns_interface_t *target = *targetp; REQUIRE(target != NULL); REQUIRE(NS_INTERFACE_VALID(target)); LOCK(&target->lock); REQUIRE(target->references > 0); target->references--; if (target->references == 0) need_destroy = ISC_TRUE; UNLOCK(&target->lock); if (need_destroy) ns_interface_destroy(target); *targetp = NULL; } /*% * Search the interface list for an interface whose address and port * both match those of 'addr'. Return a pointer to it, or NULL if not found. */ static ns_interface_t * find_matching_interface(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr) { ns_interface_t *ifp; for (ifp = ISC_LIST_HEAD(mgr->interfaces); ifp != NULL; ifp = ISC_LIST_NEXT(ifp, link)) { if (isc_sockaddr_equal(&ifp->addr, addr)) break; } return (ifp); } /*% * Remove any interfaces whose generation number is not the current one. */ static void purge_old_interfaces(ns_interfacemgr_t *mgr) { ns_interface_t *ifp, *next; for (ifp = ISC_LIST_HEAD(mgr->interfaces); ifp != NULL; ifp = next) { INSIST(NS_INTERFACE_VALID(ifp)); next = ISC_LIST_NEXT(ifp, link); if (ifp->generation != mgr->generation) { char sabuf[256]; ISC_LIST_UNLINK(ifp->mgr->interfaces, ifp, link); isc_sockaddr_format(&ifp->addr, sabuf, sizeof(sabuf)); isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_INFO, "no longer listening on %s", sabuf); ns_interface_shutdown(ifp); ns_interface_detach(&ifp); } } } static isc_result_t clearacl(isc_mem_t *mctx, dns_acl_t **aclp) { dns_acl_t *newacl = NULL; isc_result_t result; result = dns_acl_create(mctx, 0, &newacl); if (result != ISC_R_SUCCESS) return (result); dns_acl_detach(aclp); dns_acl_attach(newacl, aclp); dns_acl_detach(&newacl); return (ISC_R_SUCCESS); } static isc_boolean_t listenon_is_ip6_any(ns_listenelt_t *elt) { REQUIRE(elt && elt->acl); return dns_acl_isany(elt->acl); } static isc_result_t setup_locals(ns_interfacemgr_t *mgr, isc_interface_t *interface) { isc_result_t result; unsigned int prefixlen; isc_netaddr_t *netaddr; netaddr = &interface->address; /* First add localhost address */ prefixlen = (netaddr->family == AF_INET) ? 32 : 128; result = dns_iptable_addprefix(mgr->aclenv.localhost->iptable, netaddr, prefixlen, ISC_TRUE); if (result != ISC_R_SUCCESS) return (result); /* Then add localnets prefix */ result = isc_netaddr_masktoprefixlen(&interface->netmask, &prefixlen); /* Non contiguous netmasks not allowed by IPv6 arch. */ if (result != ISC_R_SUCCESS && netaddr->family == AF_INET6) return (result); if (result != ISC_R_SUCCESS) { isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_WARNING, "omitting IPv4 interface %s from " "localnets ACL: %s", interface->name, isc_result_totext(result)); return (ISC_R_SUCCESS); } if (prefixlen == 0U) { isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_WARNING, "omitting %s interface %s from localnets ACL: " "zero prefix length detected", (netaddr->family == AF_INET) ? "IPv4" : "IPv6", interface->name); return (ISC_R_SUCCESS); } result = dns_iptable_addprefix(mgr->aclenv.localnets->iptable, netaddr, prefixlen, ISC_TRUE); if (result != ISC_R_SUCCESS) return (result); return (ISC_R_SUCCESS); } static void setup_listenon(ns_interfacemgr_t *mgr, isc_interface_t *interface, in_port_t port) { isc_sockaddr_t *addr; isc_sockaddr_t *old; addr = isc_mem_get(mgr->mctx, sizeof(*addr)); if (addr == NULL) return; isc_sockaddr_fromnetaddr(addr, &interface->address, port); for (old = ISC_LIST_HEAD(mgr->listenon); old != NULL; old = ISC_LIST_NEXT(old, link)) if (isc_sockaddr_equal(addr, old)) break; if (old != NULL) isc_mem_put(mgr->mctx, addr, sizeof(*addr)); else ISC_LIST_APPEND(mgr->listenon, addr, link); } static void clearlistenon(ns_interfacemgr_t *mgr) { isc_sockaddr_t *old; old = ISC_LIST_HEAD(mgr->listenon); while (old != NULL) { ISC_LIST_UNLINK(mgr->listenon, old, link); isc_mem_put(mgr->mctx, old, sizeof(*old)); old = ISC_LIST_HEAD(mgr->listenon); } } static isc_result_t do_scan(ns_interfacemgr_t *mgr, ns_listenlist_t *ext_listen, isc_boolean_t verbose) { isc_interfaceiter_t *iter = NULL; isc_boolean_t scan_ipv4 = ISC_FALSE; isc_boolean_t scan_ipv6 = ISC_FALSE; isc_boolean_t adjusting = ISC_FALSE; isc_boolean_t ipv6only = ISC_TRUE; isc_boolean_t ipv6pktinfo = ISC_TRUE; isc_result_t result; isc_netaddr_t zero_address, zero_address6; ns_listenelt_t *le; isc_sockaddr_t listen_addr; ns_interface_t *ifp; isc_boolean_t log_explicit = ISC_FALSE; isc_boolean_t dolistenon; char sabuf[ISC_SOCKADDR_FORMATSIZE]; isc_boolean_t tried_listening; isc_boolean_t all_addresses_in_use; if (ext_listen != NULL) adjusting = ISC_TRUE; if (isc_net_probeipv6() == ISC_R_SUCCESS) scan_ipv6 = ISC_TRUE; #ifdef WANT_IPV6 else if (!ns_g_disable6) isc_log_write(IFMGR_COMMON_LOGARGS, verbose ? ISC_LOG_INFO : ISC_LOG_DEBUG(1), "no IPv6 interfaces found"); #endif if (isc_net_probeipv4() == ISC_R_SUCCESS) scan_ipv4 = ISC_TRUE; else if (!ns_g_disable4) isc_log_write(IFMGR_COMMON_LOGARGS, verbose ? ISC_LOG_INFO : ISC_LOG_DEBUG(1), "no IPv4 interfaces found"); /* * A special, but typical case; listen-on-v6 { any; }. * When we can make the socket IPv6-only, open a single wildcard * socket for IPv6 communication. Otherwise, make separate socket * for each IPv6 address in order to avoid accepting IPv4 packets * as the form of mapped addresses unintentionally unless explicitly * allowed. */ #ifndef ISC_ALLOW_MAPPED if (scan_ipv6 == ISC_TRUE && isc_net_probe_ipv6only() != ISC_R_SUCCESS) { ipv6only = ISC_FALSE; log_explicit = ISC_TRUE; } #endif if (scan_ipv6 == ISC_TRUE && isc_net_probe_ipv6pktinfo() != ISC_R_SUCCESS) { ipv6pktinfo = ISC_FALSE; log_explicit = ISC_TRUE; } if (scan_ipv6 == ISC_TRUE && ipv6only && ipv6pktinfo) { for (le = ISC_LIST_HEAD(mgr->listenon6->elts); le != NULL; le = ISC_LIST_NEXT(le, link)) { struct in6_addr in6a; if (!listenon_is_ip6_any(le)) continue; in6a = in6addr_any; isc_sockaddr_fromin6(&listen_addr, &in6a, le->port); ifp = find_matching_interface(mgr, &listen_addr); if (ifp != NULL) { ifp->generation = mgr->generation; if (le->dscp != -1 && ifp->dscp == -1) ifp->dscp = le->dscp; else if (le->dscp != ifp->dscp) { isc_sockaddr_format(&listen_addr, sabuf, sizeof(sabuf)); isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_WARNING, "%s: conflicting DSCP " "values, using %d", sabuf, ifp->dscp); } } else { isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_INFO, "listening on IPv6 " "interfaces, port %u", le->port); result = ns_interface_setup(mgr, &listen_addr, "", &ifp, ISC_TRUE, le->dscp, NULL); if (result == ISC_R_SUCCESS) ifp->flags |= NS_INTERFACEFLAG_ANYADDR; else isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR, "listening on all IPv6 " "interfaces failed"); /* Continue. */ } } } isc_netaddr_any(&zero_address); isc_netaddr_any6(&zero_address6); result = isc_interfaceiter_create(mgr->mctx, &iter); if (result != ISC_R_SUCCESS) return (result); if (adjusting == ISC_FALSE) { result = clearacl(mgr->mctx, &mgr->aclenv.localhost); if (result != ISC_R_SUCCESS) goto cleanup_iter; result = clearacl(mgr->mctx, &mgr->aclenv.localnets); if (result != ISC_R_SUCCESS) goto cleanup_iter; clearlistenon(mgr); } tried_listening = ISC_FALSE; all_addresses_in_use = ISC_TRUE; for (result = isc_interfaceiter_first(iter); result == ISC_R_SUCCESS; result = isc_interfaceiter_next(iter)) { isc_interface_t interface; ns_listenlist_t *ll; unsigned int family; result = isc_interfaceiter_current(iter, &interface); if (result != ISC_R_SUCCESS) break; family = interface.address.family; if (family != AF_INET && family != AF_INET6) continue; if (scan_ipv4 == ISC_FALSE && family == AF_INET) continue; if (scan_ipv6 == ISC_FALSE && family == AF_INET6) continue; /* * Test for the address being nonzero rather than testing * INTERFACE_F_UP, because on some systems the latter * follows the media state and we could end up ignoring * the interface for an entire rescan interval due to * a temporary media glitch at rescan time. */ if (family == AF_INET && isc_netaddr_equal(&interface.address, &zero_address)) { continue; } if (family == AF_INET6 && isc_netaddr_equal(&interface.address, &zero_address6)) { continue; } if (adjusting == ISC_FALSE) { /* * If running with -T fixedlocal, then we only * want 127.0.0.1 and ::1 in the localhost ACL. */ if (ns_g_fixedlocal && !isc_netaddr_isloopback(&interface.address)) { goto listenon; } result = setup_locals(mgr, &interface); if (result != ISC_R_SUCCESS) goto ignore_interface; } listenon: ll = (family == AF_INET) ? mgr->listenon4 : mgr->listenon6; dolistenon = ISC_TRUE; for (le = ISC_LIST_HEAD(ll->elts); le != NULL; le = ISC_LIST_NEXT(le, link)) { int match; isc_boolean_t ipv6_wildcard = ISC_FALSE; isc_netaddr_t listen_netaddr; isc_sockaddr_t listen_sockaddr; /* * Construct a socket address for this IP/port * combination. */ if (family == AF_INET) { isc_netaddr_fromin(&listen_netaddr, &interface.address.type.in); } else { isc_netaddr_fromin6(&listen_netaddr, &interface.address.type.in6); isc_netaddr_setzone(&listen_netaddr, interface.address.zone); } isc_sockaddr_fromnetaddr(&listen_sockaddr, &listen_netaddr, le->port); /* * See if the address matches the listen-on statement; * if not, ignore the interface. */ (void)dns_acl_match(&listen_netaddr, NULL, le->acl, &mgr->aclenv, &match, NULL); if (match <= 0) continue; if (adjusting == ISC_FALSE && dolistenon == ISC_TRUE) { setup_listenon(mgr, &interface, le->port); dolistenon = ISC_FALSE; } /* * The case of "any" IPv6 address will require * special considerations later, so remember it. */ if (family == AF_INET6 && ipv6only && ipv6pktinfo && listenon_is_ip6_any(le)) ipv6_wildcard = ISC_TRUE; /* * When adjusting interfaces with extra a listening * list, see if the address matches the extra list. * If it does, and is also covered by a wildcard * interface, we need to listen on the address * explicitly. */ if (adjusting == ISC_TRUE) { ns_listenelt_t *ele; match = 0; for (ele = ISC_LIST_HEAD(ext_listen->elts); ele != NULL; ele = ISC_LIST_NEXT(ele, link)) { (void)dns_acl_match(&listen_netaddr, NULL, ele->acl, NULL, &match, NULL); if (match > 0 && (ele->port == le->port || ele->port == 0)) break; else match = 0; } if (ipv6_wildcard == ISC_TRUE && match == 0) continue; } ifp = find_matching_interface(mgr, &listen_sockaddr); if (ifp != NULL) { ifp->generation = mgr->generation; if (le->dscp != -1 && ifp->dscp == -1) ifp->dscp = le->dscp; else if (le->dscp != ifp->dscp) { isc_sockaddr_format(&listen_sockaddr, sabuf, sizeof(sabuf)); isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_WARNING, "%s: conflicting DSCP " "values, using %d", sabuf, ifp->dscp); } } else { isc_boolean_t addr_in_use = ISC_FALSE; if (adjusting == ISC_FALSE && ipv6_wildcard == ISC_TRUE) continue; if (log_explicit && family == AF_INET6 && !adjusting && listenon_is_ip6_any(le)) { isc_log_write(IFMGR_COMMON_LOGARGS, verbose ? ISC_LOG_INFO : ISC_LOG_DEBUG(1), "IPv6 socket API is " "incomplete; explicitly " "binding to each IPv6 " "address separately"); log_explicit = ISC_FALSE; } isc_sockaddr_format(&listen_sockaddr, sabuf, sizeof(sabuf)); isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_INFO, "%s" "listening on %s interface " "%s, %s", (adjusting == ISC_TRUE) ? "additionally " : "", (family == AF_INET) ? "IPv4" : "IPv6", interface.name, sabuf); result = ns_interface_setup(mgr, &listen_sockaddr, interface.name, &ifp, (adjusting == ISC_TRUE) ? ISC_FALSE : ISC_TRUE, le->dscp, &addr_in_use); tried_listening = ISC_TRUE; if (!addr_in_use) all_addresses_in_use = ISC_FALSE; if (result != ISC_R_SUCCESS) { isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR, "creating %s interface " "%s failed; interface " "ignored", (family == AF_INET) ? "IPv4" : "IPv6", interface.name); } /* Continue. */ } } continue; ignore_interface: isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR, "ignoring %s interface %s: %s", (family == AF_INET) ? "IPv4" : "IPv6", interface.name, isc_result_totext(result)); continue; } if (result != ISC_R_NOMORE) UNEXPECTED_ERROR(__FILE__, __LINE__, "interface iteration failed: %s", isc_result_totext(result)); else result = ((tried_listening && all_addresses_in_use) ? ISC_R_ADDRINUSE : ISC_R_SUCCESS); cleanup_iter: isc_interfaceiter_destroy(&iter); return (result); } static isc_result_t ns_interfacemgr_scan0(ns_interfacemgr_t *mgr, ns_listenlist_t *ext_listen, isc_boolean_t verbose) { isc_result_t result; isc_boolean_t purge = ISC_TRUE; REQUIRE(NS_INTERFACEMGR_VALID(mgr)); mgr->generation++; /* Increment the generation count. */ result = do_scan(mgr, ext_listen, verbose); if ((result != ISC_R_SUCCESS) && (result != ISC_R_ADDRINUSE)) purge = ISC_FALSE; /* * Now go through the interface list and delete anything that * does not have the current generation number. This is * how we catch interfaces that go away or change their * addresses. */ if (purge) purge_old_interfaces(mgr); /* * Warn if we are not listening on any interface, unless * we're in lwresd-only mode, in which case that is to * be expected. */ if (ext_listen == NULL && ISC_LIST_EMPTY(mgr->interfaces) && ! ns_g_lwresdonly) { isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_WARNING, "not listening on any interfaces"); } return (result); } isc_boolean_t ns_interfacemgr_islistening(ns_interfacemgr_t *mgr) { REQUIRE(NS_INTERFACEMGR_VALID(mgr)); return (ISC_LIST_EMPTY(mgr->interfaces) ? ISC_FALSE : ISC_TRUE); } isc_result_t ns_interfacemgr_scan(ns_interfacemgr_t *mgr, isc_boolean_t verbose) { return (ns_interfacemgr_scan0(mgr, NULL, verbose)); } isc_result_t ns_interfacemgr_adjust(ns_interfacemgr_t *mgr, ns_listenlist_t *list, isc_boolean_t verbose) { return (ns_interfacemgr_scan0(mgr, list, verbose)); } void ns_interfacemgr_setlistenon4(ns_interfacemgr_t *mgr, ns_listenlist_t *value) { LOCK(&mgr->lock); ns_listenlist_detach(&mgr->listenon4); ns_listenlist_attach(value, &mgr->listenon4); UNLOCK(&mgr->lock); } void ns_interfacemgr_setlistenon6(ns_interfacemgr_t *mgr, ns_listenlist_t *value) { LOCK(&mgr->lock); ns_listenlist_detach(&mgr->listenon6); ns_listenlist_attach(value, &mgr->listenon6); UNLOCK(&mgr->lock); } void ns_interfacemgr_dumprecursing(FILE *f, ns_interfacemgr_t *mgr) { ns_interface_t *interface; LOCK(&mgr->lock); interface = ISC_LIST_HEAD(mgr->interfaces); while (interface != NULL) { if (interface->clientmgr != NULL) ns_client_dumprecursing(f, interface->clientmgr); interface = ISC_LIST_NEXT(interface, link); } UNLOCK(&mgr->lock); } isc_boolean_t ns_interfacemgr_listeningon(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr) { isc_sockaddr_t *old; for (old = ISC_LIST_HEAD(mgr->listenon); old != NULL; old = ISC_LIST_NEXT(old, link)) if (isc_sockaddr_equal(old, addr)) return (ISC_TRUE); return (ISC_FALSE); } bind9-9.11.3+dfsg/bin/named/listenlist.c000066400000000000000000000056231325250447100177340ustar00rootroot00000000000000/* * Copyright (C) 2000, 2001, 2004, 2005, 2007, 2013, 2016 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* $Id: listenlist.c,v 1.14 2007/06/19 23:46:59 tbox Exp $ */ /*! \file */ #include #include #include #include #include static void destroy(ns_listenlist_t *list); isc_result_t ns_listenelt_create(isc_mem_t *mctx, in_port_t port, isc_dscp_t dscp, dns_acl_t *acl, ns_listenelt_t **target) { ns_listenelt_t *elt = NULL; REQUIRE(target != NULL && *target == NULL); elt = isc_mem_get(mctx, sizeof(*elt)); if (elt == NULL) return (ISC_R_NOMEMORY); elt->mctx = mctx; ISC_LINK_INIT(elt, link); elt->port = port; elt->dscp = dscp; elt->acl = acl; *target = elt; return (ISC_R_SUCCESS); } void ns_listenelt_destroy(ns_listenelt_t *elt) { if (elt->acl != NULL) dns_acl_detach(&elt->acl); isc_mem_put(elt->mctx, elt, sizeof(*elt)); } isc_result_t ns_listenlist_create(isc_mem_t *mctx, ns_listenlist_t **target) { ns_listenlist_t *list = NULL; REQUIRE(target != NULL && *target == NULL); list = isc_mem_get(mctx, sizeof(*list)); if (list == NULL) return (ISC_R_NOMEMORY); list->mctx = mctx; list->refcount = 1; ISC_LIST_INIT(list->elts); *target = list; return (ISC_R_SUCCESS); } static void destroy(ns_listenlist_t *list) { ns_listenelt_t *elt, *next; for (elt = ISC_LIST_HEAD(list->elts); elt != NULL; elt = next) { next = ISC_LIST_NEXT(elt, link); ns_listenelt_destroy(elt); } isc_mem_put(list->mctx, list, sizeof(*list)); } void ns_listenlist_attach(ns_listenlist_t *source, ns_listenlist_t **target) { INSIST(source->refcount > 0); source->refcount++; *target = source; } void ns_listenlist_detach(ns_listenlist_t **listp) { ns_listenlist_t *list = *listp; INSIST(list->refcount > 0); list->refcount--; if (list->refcount == 0) destroy(list); *listp = NULL; } isc_result_t ns_listenlist_default(isc_mem_t *mctx, in_port_t port, isc_dscp_t dscp, isc_boolean_t enabled, ns_listenlist_t **target) { isc_result_t result; dns_acl_t *acl = NULL; ns_listenelt_t *elt = NULL; ns_listenlist_t *list = NULL; REQUIRE(target != NULL && *target == NULL); if (enabled) result = dns_acl_any(mctx, &acl); else result = dns_acl_none(mctx, &acl); if (result != ISC_R_SUCCESS) goto cleanup; result = ns_listenelt_create(mctx, port, dscp, acl, &elt); if (result != ISC_R_SUCCESS) goto cleanup_acl; result = ns_listenlist_create(mctx, &list); if (result != ISC_R_SUCCESS) goto cleanup_listenelt; ISC_LIST_APPEND(list->elts, elt, link); *target = list; return (ISC_R_SUCCESS); cleanup_listenelt: ns_listenelt_destroy(elt); cleanup_acl: dns_acl_detach(&acl); cleanup: return (result); } bind9-9.11.3+dfsg/bin/named/log.c000066400000000000000000000140521325250447100163170ustar00rootroot00000000000000/* * Copyright (C) 1999-2002, 2004-2007, 2009, 2013, 2014, 2016, 2017 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* $Id: log.c,v 1.49 2009/01/07 01:46:40 jinmei Exp $ */ /*! \file */ #include #include #include #include #ifndef ISC_FACILITY #define ISC_FACILITY LOG_DAEMON #endif /*% * When adding a new category, be sure to add the appropriate * \#define to and to update the list in * bin/check/check-tool.c. */ static isc_logcategory_t categories[] = { { "", 0 }, { "client", 0 }, { "network", 0 }, { "update", 0 }, { "queries", 0 }, { "unmatched", 0 }, { "update-security", 0 }, { "query-errors", 0 }, { "trust-anchor-telementry", 0 }, { NULL, 0 } }; /*% * When adding a new module, be sure to add the appropriate * \#define to . */ static isc_logmodule_t modules[] = { { "main", 0 }, { "client", 0 }, { "server", 0 }, { "query", 0 }, { "interfacemgr", 0 }, { "update", 0 }, { "xfer-in", 0 }, { "xfer-out", 0 }, { "notify", 0 }, { "control", 0 }, { "lwresd", 0 }, { NULL, 0 } }; isc_result_t ns_log_init(isc_boolean_t safe) { isc_result_t result; isc_logconfig_t *lcfg = NULL; ns_g_categories = categories; ns_g_modules = modules; /* * Setup a logging context. */ result = isc_log_create(ns_g_mctx, &ns_g_lctx, &lcfg); if (result != ISC_R_SUCCESS) return (result); /* * named-checktool.c:setup_logging() needs to be kept in sync. */ isc_log_registercategories(ns_g_lctx, ns_g_categories); isc_log_registermodules(ns_g_lctx, ns_g_modules); isc_log_setcontext(ns_g_lctx); dns_log_init(ns_g_lctx); dns_log_setcontext(ns_g_lctx); cfg_log_init(ns_g_lctx); if (safe) result = ns_log_setsafechannels(lcfg); else result = ns_log_setdefaultchannels(lcfg); if (result != ISC_R_SUCCESS) goto cleanup; result = ns_log_setdefaultcategory(lcfg); if (result != ISC_R_SUCCESS) goto cleanup; return (ISC_R_SUCCESS); cleanup: isc_log_destroy(&ns_g_lctx); isc_log_setcontext(NULL); dns_log_setcontext(NULL); return (result); } isc_result_t ns_log_setdefaultchannels(isc_logconfig_t *lcfg) { isc_result_t result; isc_logdestination_t destination; /* * By default, the logging library makes "default_debug" log to * stderr. In BIND, we want to override this and log to named.run * instead, unless the -g option was given. */ if (! ns_g_logstderr) { destination.file.stream = NULL; destination.file.name = "named.run"; destination.file.versions = ISC_LOG_ROLLNEVER; destination.file.maximum_size = 0; result = isc_log_createchannel(lcfg, "default_debug", ISC_LOG_TOFILE, ISC_LOG_DYNAMIC, &destination, ISC_LOG_PRINTTIME| ISC_LOG_DEBUGONLY); if (result != ISC_R_SUCCESS) goto cleanup; } if (ns_g_logfile != NULL) { destination.file.stream = NULL; destination.file.name = ns_g_logfile; destination.file.versions = ISC_LOG_ROLLNEVER; destination.file.maximum_size = 0; result = isc_log_createchannel(lcfg, "default_logfile", ISC_LOG_TOFILE, ISC_LOG_DYNAMIC, &destination, ISC_LOG_PRINTTIME| ISC_LOG_PRINTCATEGORY| ISC_LOG_PRINTLEVEL); if (result != ISC_R_SUCCESS) goto cleanup; } #if ISC_FACILITY != LOG_DAEMON destination.facility = ISC_FACILITY; result = isc_log_createchannel(lcfg, "default_syslog", ISC_LOG_TOSYSLOG, ISC_LOG_INFO, &destination, 0); if (result != ISC_R_SUCCESS) goto cleanup; #endif /* * Set the initial debug level. */ isc_log_setdebuglevel(ns_g_lctx, ns_g_debuglevel); result = ISC_R_SUCCESS; cleanup: return (result); } isc_result_t ns_log_setsafechannels(isc_logconfig_t *lcfg) { isc_result_t result; isc_logdestination_t destination; if (! ns_g_logstderr) { result = isc_log_createchannel(lcfg, "default_debug", ISC_LOG_TONULL, ISC_LOG_DYNAMIC, NULL, 0); if (result != ISC_R_SUCCESS) goto cleanup; /* * Setting the debug level to zero should get the output * discarded a bit faster. */ isc_log_setdebuglevel(ns_g_lctx, 0); } else { isc_log_setdebuglevel(ns_g_lctx, ns_g_debuglevel); } if (ns_g_logfile != NULL) { destination.file.stream = NULL; destination.file.name = ns_g_logfile; destination.file.versions = ISC_LOG_ROLLNEVER; destination.file.maximum_size = 0; result = isc_log_createchannel(lcfg, "default_logfile", ISC_LOG_TOFILE, ISC_LOG_DYNAMIC, &destination, ISC_LOG_PRINTTIME| ISC_LOG_PRINTCATEGORY| ISC_LOG_PRINTLEVEL); if (result != ISC_R_SUCCESS) goto cleanup; } #if ISC_FACILITY != LOG_DAEMON destination.facility = ISC_FACILITY; result = isc_log_createchannel(lcfg, "default_syslog", ISC_LOG_TOSYSLOG, ISC_LOG_INFO, &destination, 0); if (result != ISC_R_SUCCESS) goto cleanup; #endif result = ISC_R_SUCCESS; cleanup: return (result); } isc_result_t ns_log_setdefaultcategory(isc_logconfig_t *lcfg) { isc_result_t result = ISC_R_SUCCESS; result = isc_log_usechannel(lcfg, "default_debug", ISC_LOGCATEGORY_DEFAULT, NULL); if (result != ISC_R_SUCCESS) goto cleanup; if (! ns_g_logstderr) { if (ns_g_logfile != NULL) result = isc_log_usechannel(lcfg, "default_logfile", ISC_LOGCATEGORY_DEFAULT, NULL); else if (! ns_g_nosyslog) result = isc_log_usechannel(lcfg, "default_syslog", ISC_LOGCATEGORY_DEFAULT, NULL); } cleanup: return (result); } isc_result_t ns_log_setunmatchedcategory(isc_logconfig_t *lcfg) { isc_result_t result; result = isc_log_usechannel(lcfg, "null", NS_LOGCATEGORY_UNMATCHED, NULL); return (result); } void ns_log_shutdown(void) { isc_log_destroy(&ns_g_lctx); isc_log_setcontext(NULL); dns_log_setcontext(NULL); } bind9-9.11.3+dfsg/bin/named/logconf.c000066400000000000000000000220661325250447100171710ustar00rootroot00000000000000/* * Copyright (C) 1999-2001, 2004-2007, 2011, 2013-2017 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* $Id: logconf.c,v 1.45 2011/03/05 23:52:29 tbox Exp $ */ /*! \file */ #include #include #include #include #include #include #include #include #include #include #include #include #include #define CHECK(op) \ do { result = (op); \ if (result != ISC_R_SUCCESS) goto cleanup; \ } while (0) /*% * Set up a logging category according to the named.conf data * in 'ccat' and add it to 'logconfig'. */ static isc_result_t category_fromconf(const cfg_obj_t *ccat, isc_logconfig_t *logconfig) { isc_result_t result; const char *catname; isc_logcategory_t *category; isc_logmodule_t *module; const cfg_obj_t *destinations = NULL; const cfg_listelt_t *element = NULL; catname = cfg_obj_asstring(cfg_tuple_get(ccat, "name")); category = isc_log_categorybyname(ns_g_lctx, catname); if (category == NULL) { cfg_obj_log(ccat, ns_g_lctx, ISC_LOG_ERROR, "unknown logging category '%s' ignored", catname); /* * Allow further processing by returning success. */ return (ISC_R_SUCCESS); } if (logconfig == NULL) return (ISC_R_SUCCESS); module = NULL; destinations = cfg_tuple_get(ccat, "destinations"); for (element = cfg_list_first(destinations); element != NULL; element = cfg_list_next(element)) { const cfg_obj_t *channel = cfg_listelt_value(element); const char *channelname = cfg_obj_asstring(channel); result = isc_log_usechannel(logconfig, channelname, category, module); if (result != ISC_R_SUCCESS) { isc_log_write(ns_g_lctx, CFG_LOGCATEGORY_CONFIG, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, "logging channel '%s': %s", channelname, isc_result_totext(result)); return (result); } } return (ISC_R_SUCCESS); } /*% * Set up a logging channel according to the named.conf data * in 'cchan' and add it to 'logconfig'. */ static isc_result_t channel_fromconf(const cfg_obj_t *channel, isc_logconfig_t *logconfig) { isc_result_t result; isc_logdestination_t dest; unsigned int type; unsigned int flags = 0; int level; const char *channelname; const cfg_obj_t *fileobj = NULL; const cfg_obj_t *syslogobj = NULL; const cfg_obj_t *nullobj = NULL; const cfg_obj_t *stderrobj = NULL; const cfg_obj_t *severity = NULL; int i; channelname = cfg_obj_asstring(cfg_map_getname(channel)); (void)cfg_map_get(channel, "file", &fileobj); (void)cfg_map_get(channel, "syslog", &syslogobj); (void)cfg_map_get(channel, "null", &nullobj); (void)cfg_map_get(channel, "stderr", &stderrobj); i = 0; if (fileobj != NULL) i++; if (syslogobj != NULL) i++; if (nullobj != NULL) i++; if (stderrobj != NULL) i++; if (i != 1) { cfg_obj_log(channel, ns_g_lctx, ISC_LOG_ERROR, "channel '%s': exactly one of file, syslog, " "null, and stderr must be present", channelname); return (ISC_R_FAILURE); } type = ISC_LOG_TONULL; if (fileobj != NULL) { const cfg_obj_t *pathobj = cfg_tuple_get(fileobj, "file"); const cfg_obj_t *sizeobj = cfg_tuple_get(fileobj, "size"); const cfg_obj_t *versionsobj = cfg_tuple_get(fileobj, "versions"); isc_int32_t versions = ISC_LOG_ROLLNEVER; isc_offset_t size = 0; isc_uint64_t maxoffset; /* * isc_offset_t is a signed integer type, so the maximum * value is all 1s except for the MSB. */ switch (sizeof(isc_offset_t)) { case 4: maxoffset = 0x7fffffffULL; break; case 8: maxoffset = 0x7fffffffffffffffULL; break; default: INSIST(0); } type = ISC_LOG_TOFILE; if (versionsobj != NULL && cfg_obj_isuint32(versionsobj)) versions = cfg_obj_asuint32(versionsobj); if (versionsobj != NULL && cfg_obj_isstring(versionsobj) && strcasecmp(cfg_obj_asstring(versionsobj), "unlimited") == 0) versions = ISC_LOG_ROLLINFINITE; if (sizeobj != NULL && cfg_obj_isuint64(sizeobj) && cfg_obj_asuint64(sizeobj) < maxoffset) size = (isc_offset_t)cfg_obj_asuint64(sizeobj); dest.file.stream = NULL; dest.file.name = cfg_obj_asstring(pathobj); dest.file.versions = versions; dest.file.maximum_size = size; } else if (syslogobj != NULL) { int facility = LOG_DAEMON; type = ISC_LOG_TOSYSLOG; if (cfg_obj_isstring(syslogobj)) { const char *facilitystr = cfg_obj_asstring(syslogobj); (void)isc_syslog_facilityfromstring(facilitystr, &facility); } dest.facility = facility; } else if (stderrobj != NULL) { type = ISC_LOG_TOFILEDESC; dest.file.stream = stderr; dest.file.name = NULL; dest.file.versions = ISC_LOG_ROLLNEVER; dest.file.maximum_size = 0; } /* * Munge flags. */ { const cfg_obj_t *printcat = NULL; const cfg_obj_t *printsev = NULL; const cfg_obj_t *printtime = NULL; const cfg_obj_t *buffered = NULL; (void)cfg_map_get(channel, "print-category", &printcat); (void)cfg_map_get(channel, "print-severity", &printsev); (void)cfg_map_get(channel, "print-time", &printtime); (void)cfg_map_get(channel, "buffered", &buffered); if (printcat != NULL && cfg_obj_asboolean(printcat)) flags |= ISC_LOG_PRINTCATEGORY; if (printtime != NULL && cfg_obj_asboolean(printtime)) flags |= ISC_LOG_PRINTTIME; if (printsev != NULL && cfg_obj_asboolean(printsev)) flags |= ISC_LOG_PRINTLEVEL; if (buffered != NULL && cfg_obj_asboolean(buffered)) flags |= ISC_LOG_BUFFERED; } level = ISC_LOG_INFO; if (cfg_map_get(channel, "severity", &severity) == ISC_R_SUCCESS) { if (cfg_obj_isstring(severity)) { const char *str = cfg_obj_asstring(severity); if (strcasecmp(str, "critical") == 0) level = ISC_LOG_CRITICAL; else if (strcasecmp(str, "error") == 0) level = ISC_LOG_ERROR; else if (strcasecmp(str, "warning") == 0) level = ISC_LOG_WARNING; else if (strcasecmp(str, "notice") == 0) level = ISC_LOG_NOTICE; else if (strcasecmp(str, "info") == 0) level = ISC_LOG_INFO; else if (strcasecmp(str, "dynamic") == 0) level = ISC_LOG_DYNAMIC; } else /* debug */ level = cfg_obj_asuint32(severity); } if (logconfig == NULL) result = ISC_R_SUCCESS; else result = isc_log_createchannel(logconfig, channelname, type, level, &dest, flags); if (result == ISC_R_SUCCESS && type == ISC_LOG_TOFILE) { FILE *fp; /* * Test to make sure that file is a plain file. * Fix defect #22771 */ result = isc_file_isplainfile(dest.file.name); if (result == ISC_R_SUCCESS || result == ISC_R_FILENOTFOUND) { /* * Test that the file can be opened, since * isc_log_open() can't effectively report * failures when called in isc_log_doit(). */ result = isc_stdio_open(dest.file.name, "a", &fp); if (result != ISC_R_SUCCESS) { if (logconfig != NULL && !ns_g_nosyslog) syslog(LOG_ERR, "isc_stdio_open '%s' failed: " "%s", dest.file.name, isc_result_totext(result)); fprintf(stderr, "isc_stdio_open '%s' failed: %s\n", dest.file.name, isc_result_totext(result)); } else (void)isc_stdio_close(fp); goto done; } if (logconfig != NULL && !ns_g_nosyslog) syslog(LOG_ERR, "isc_file_isplainfile '%s' failed: %s", dest.file.name, isc_result_totext(result)); fprintf(stderr, "isc_file_isplainfile '%s' failed: %s\n", dest.file.name, isc_result_totext(result)); } done: return (result); } isc_result_t ns_log_configure(isc_logconfig_t *logconfig, const cfg_obj_t *logstmt) { isc_result_t result; const cfg_obj_t *channels = NULL; const cfg_obj_t *categories = NULL; const cfg_listelt_t *element; isc_boolean_t default_set = ISC_FALSE; isc_boolean_t unmatched_set = ISC_FALSE; const cfg_obj_t *catname; if (logconfig != NULL) CHECK(ns_log_setdefaultchannels(logconfig)); (void)cfg_map_get(logstmt, "channel", &channels); for (element = cfg_list_first(channels); element != NULL; element = cfg_list_next(element)) { const cfg_obj_t *channel = cfg_listelt_value(element); CHECK(channel_fromconf(channel, logconfig)); } (void)cfg_map_get(logstmt, "category", &categories); for (element = cfg_list_first(categories); element != NULL; element = cfg_list_next(element)) { const cfg_obj_t *category = cfg_listelt_value(element); CHECK(category_fromconf(category, logconfig)); if (!default_set) { catname = cfg_tuple_get(category, "name"); if (strcmp(cfg_obj_asstring(catname), "default") == 0) default_set = ISC_TRUE; } if (!unmatched_set) { catname = cfg_tuple_get(category, "name"); if (strcmp(cfg_obj_asstring(catname), "unmatched") == 0) unmatched_set = ISC_TRUE; } } if (logconfig != NULL && !default_set) CHECK(ns_log_setdefaultcategory(logconfig)); if (logconfig != NULL && !unmatched_set) CHECK(ns_log_setunmatchedcategory(logconfig)); return (ISC_R_SUCCESS); cleanup: return (result); } bind9-9.11.3+dfsg/bin/named/lwaddr.c000066400000000000000000000040351325250447100170130ustar00rootroot00000000000000/* * Copyright (C) 2000, 2001, 2004, 2005, 2007, 2008, 2014, 2016 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* $Id: lwaddr.c,v 1.10 2008/01/11 23:46:56 tbox Exp $ */ /*! \file */ #include #include #include #include #include #include #include /*% * Convert addresses from lwres to isc format. */ isc_result_t lwaddr_netaddr_fromlwresaddr(isc_netaddr_t *na, lwres_addr_t *la) { if (la->family != LWRES_ADDRTYPE_V4 && la->family != LWRES_ADDRTYPE_V6) return (ISC_R_FAMILYNOSUPPORT); if (la->family == LWRES_ADDRTYPE_V4) { struct in_addr ina; memmove(&ina.s_addr, la->address, 4); isc_netaddr_fromin(na, &ina); } else { struct in6_addr ina6; memmove(&ina6.s6_addr, la->address, 16); isc_netaddr_fromin6(na, &ina6); } return (ISC_R_SUCCESS); } isc_result_t lwaddr_sockaddr_fromlwresaddr(isc_sockaddr_t *sa, lwres_addr_t *la, in_port_t port) { isc_netaddr_t na; isc_result_t result; result = lwaddr_netaddr_fromlwresaddr(&na, la); if (result != ISC_R_SUCCESS) return (result); isc_sockaddr_fromnetaddr(sa, &na, port); return (ISC_R_SUCCESS); } /*% * Convert addresses from isc to lwres format. */ isc_result_t lwaddr_lwresaddr_fromnetaddr(lwres_addr_t *la, isc_netaddr_t *na) { if (na->family != AF_INET && na->family != AF_INET6) return (ISC_R_FAMILYNOSUPPORT); if (na->family == AF_INET) { la->family = LWRES_ADDRTYPE_V4; la->length = 4; memmove(la->address, &na->type.in, 4); } else { la->family = LWRES_ADDRTYPE_V6; la->length = 16; memmove(la->address, &na->type.in6, 16); } return (ISC_R_SUCCESS); } isc_result_t lwaddr_lwresaddr_fromsockaddr(lwres_addr_t *la, isc_sockaddr_t *sa) { isc_netaddr_t na; isc_netaddr_fromsockaddr(&na, sa); return (lwaddr_lwresaddr_fromnetaddr(la, &na)); } bind9-9.11.3+dfsg/bin/named/lwdclient.c000066400000000000000000000273111325250447100175250ustar00rootroot00000000000000/* * Copyright (C) 2000, 2001, 2004, 2005, 2007, 2015, 2016 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* $Id: lwdclient.c,v 1.22 2007/06/18 23:47:18 tbox Exp $ */ /*! \file */ #include #include #include #include #include #include #include #include #include #include #include #include #define SHUTTINGDOWN(cm) ((cm->flags & NS_LWDCLIENTMGR_FLAGSHUTTINGDOWN) != 0) static void lwdclientmgr_shutdown_callback(isc_task_t *task, isc_event_t *ev); void ns_lwdclient_log(int level, const char *format, ...) { va_list args; va_start(args, format); isc_log_vwrite(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_ADB, ISC_LOG_DEBUG(level), format, args); va_end(args); } isc_result_t ns_lwdclientmgr_create(ns_lwreslistener_t *listener, unsigned int nclients, isc_taskmgr_t *taskmgr) { ns_lwresd_t *lwresd = listener->manager; ns_lwdclientmgr_t *cm; ns_lwdclient_t *client; unsigned int i; isc_result_t result; cm = isc_mem_get(lwresd->mctx, sizeof(ns_lwdclientmgr_t)); if (cm == NULL) return (ISC_R_NOMEMORY); result = isc_mutex_init(&cm->lock); if (result != ISC_R_SUCCESS) goto freecm; cm->listener = NULL; ns_lwreslistener_attach(listener, &cm->listener); cm->mctx = lwresd->mctx; cm->sock = NULL; isc_socket_attach(listener->sock, &cm->sock); cm->view = lwresd->view; cm->lwctx = NULL; cm->task = NULL; cm->flags = 0; ISC_LINK_INIT(cm, link); ISC_LIST_INIT(cm->idle); ISC_LIST_INIT(cm->running); result = lwres_context_create(&cm->lwctx, cm->mctx, ns__lwresd_memalloc, ns__lwresd_memfree, LWRES_CONTEXT_SERVERMODE); if (result != ISC_R_SUCCESS) goto errout; for (i = 0; i < nclients; i++) { client = isc_mem_get(lwresd->mctx, sizeof(ns_lwdclient_t)); if (client != NULL) { ns_lwdclient_log(50, "created client %p, manager %p", client, cm); ns_lwdclient_initialize(client, cm); } } /* * If we could create no clients, clean up and return. */ if (ISC_LIST_EMPTY(cm->idle)) { result = ISC_R_NOMEMORY; goto errout; } result = isc_task_create(taskmgr, 0, &cm->task); if (result != ISC_R_SUCCESS) goto errout; isc_task_setname(cm->task, "lwdclient", NULL); /* * This MUST be last, since there is no way to cancel an onshutdown... */ result = isc_task_onshutdown(cm->task, lwdclientmgr_shutdown_callback, cm); if (result != ISC_R_SUCCESS) goto errout; ns_lwreslistener_linkcm(listener, cm); return (ISC_R_SUCCESS); errout: client = ISC_LIST_HEAD(cm->idle); while (client != NULL) { ISC_LIST_UNLINK(cm->idle, client, link); isc_mem_put(lwresd->mctx, client, sizeof(*client)); client = ISC_LIST_HEAD(cm->idle); } if (cm->task != NULL) isc_task_detach(&cm->task); if (cm->lwctx != NULL) lwres_context_destroy(&cm->lwctx); DESTROYLOCK(&cm->lock); freecm: isc_mem_put(lwresd->mctx, cm, sizeof(*cm)); return (result); } static void lwdclientmgr_destroy(ns_lwdclientmgr_t *cm) { ns_lwdclient_t *client; ns_lwreslistener_t *listener; LOCK(&cm->lock); if (!SHUTTINGDOWN(cm)) { UNLOCK(&cm->lock); return; } /* * Run through the idle list and free the clients there. Idle * clients do not have a recv running nor do they have any finds * or similar running. */ client = ISC_LIST_HEAD(cm->idle); while (client != NULL) { ns_lwdclient_log(50, "destroying client %p, manager %p", client, cm); ISC_LIST_UNLINK(cm->idle, client, link); isc_mem_put(cm->mctx, client, sizeof(*client)); client = ISC_LIST_HEAD(cm->idle); } if (!ISC_LIST_EMPTY(cm->running)) { UNLOCK(&cm->lock); return; } UNLOCK(&cm->lock); lwres_context_destroy(&cm->lwctx); cm->view = NULL; isc_socket_detach(&cm->sock); isc_task_detach(&cm->task); DESTROYLOCK(&cm->lock); listener = cm->listener; ns_lwreslistener_unlinkcm(listener, cm); ns_lwdclient_log(50, "destroying manager %p", cm); isc_mem_put(cm->mctx, cm, sizeof(*cm)); ns_lwreslistener_detach(&listener); } static void process_request(ns_lwdclient_t *client) { lwres_buffer_t b; isc_result_t result; lwres_buffer_init(&b, client->buffer, client->recvlength); lwres_buffer_add(&b, client->recvlength); result = lwres_lwpacket_parseheader(&b, &client->pkt); if (result != ISC_R_SUCCESS) { ns_lwdclient_log(50, "invalid packet header received"); goto restart; } ns_lwdclient_log(50, "opcode %08x", client->pkt.opcode); switch (client->pkt.opcode) { case LWRES_OPCODE_GETADDRSBYNAME: ns_lwdclient_processgabn(client, &b); return; case LWRES_OPCODE_GETNAMEBYADDR: ns_lwdclient_processgnba(client, &b); return; case LWRES_OPCODE_GETRDATABYNAME: ns_lwdclient_processgrbn(client, &b); return; case LWRES_OPCODE_NOOP: ns_lwdclient_processnoop(client, &b); return; default: ns_lwdclient_log(50, "unknown opcode %08x", client->pkt.opcode); goto restart; } /* * Drop the packet. */ restart: ns_lwdclient_log(50, "restarting client %p...", client); ns_lwdclient_stateidle(client); } void ns_lwdclient_recv(isc_task_t *task, isc_event_t *ev) { isc_result_t result; ns_lwdclient_t *client = ev->ev_arg; ns_lwdclientmgr_t *cm = client->clientmgr; isc_socketevent_t *dev = (isc_socketevent_t *)ev; INSIST(dev->region.base == client->buffer); INSIST(NS_LWDCLIENT_ISRECV(client)); NS_LWDCLIENT_SETRECVDONE(client); LOCK(&cm->lock); INSIST((cm->flags & NS_LWDCLIENTMGR_FLAGRECVPENDING) != 0); cm->flags &= ~NS_LWDCLIENTMGR_FLAGRECVPENDING; UNLOCK(&cm->lock); ns_lwdclient_log(50, "event received: task %p, length %u, result %u (%s)", task, dev->n, dev->result, isc_result_totext(dev->result)); if (dev->result != ISC_R_SUCCESS) { isc_event_free(&ev); dev = NULL; /* * Go idle. */ ns_lwdclient_stateidle(client); return; } client->recvlength = dev->n; client->address = dev->address; if ((dev->attributes & ISC_SOCKEVENTATTR_PKTINFO) != 0) { client->pktinfo = dev->pktinfo; client->pktinfo_valid = ISC_TRUE; } else client->pktinfo_valid = ISC_FALSE; isc_event_free(&ev); dev = NULL; result = ns_lwdclient_startrecv(cm); if (result != ISC_R_SUCCESS) isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_LWRESD, ISC_LOG_ERROR, "could not start lwres " "client handler: %s", isc_result_totext(result)); process_request(client); } /* * This function will start a new recv() on a socket for this client manager. */ isc_result_t ns_lwdclient_startrecv(ns_lwdclientmgr_t *cm) { ns_lwdclient_t *client; isc_result_t result; isc_region_t r; isc_boolean_t destroy = ISC_FALSE; LOCK(&cm->lock); if (SHUTTINGDOWN(cm)) { destroy = ISC_TRUE; result = ISC_R_SUCCESS; goto unlock; } /* * If a recv is already running, don't bother. */ if ((cm->flags & NS_LWDCLIENTMGR_FLAGRECVPENDING) != 0) { result = ISC_R_SUCCESS; goto unlock; } /* * If we have no idle slots, just return success. */ client = ISC_LIST_HEAD(cm->idle); if (client == NULL) { result = ISC_R_SUCCESS; goto unlock; } INSIST(NS_LWDCLIENT_ISIDLE(client)); /* * Set the flag to say there is a recv pending. If isc_socket_recv * fails we will clear the flag otherwise it will be cleared by * ns_lwdclient_recv. */ cm->flags |= NS_LWDCLIENTMGR_FLAGRECVPENDING; /* * Issue the recv. If it fails, return that it did. */ r.base = client->buffer; r.length = LWRES_RECVLENGTH; result = isc_socket_recv(cm->sock, &r, 0, cm->task, ns_lwdclient_recv, client); if (result != ISC_R_SUCCESS) { cm->flags &= ~NS_LWDCLIENTMGR_FLAGRECVPENDING; goto unlock; } /* * Remove the client from the idle list, and put it on the running * list. */ NS_LWDCLIENT_SETRECV(client); ISC_LIST_UNLINK(cm->idle, client, link); ISC_LIST_APPEND(cm->running, client, link); unlock: UNLOCK(&cm->lock); if (destroy) lwdclientmgr_destroy(cm); return (result); } static void lwdclientmgr_shutdown_callback(isc_task_t *task, isc_event_t *ev) { ns_lwdclientmgr_t *cm = ev->ev_arg; ns_lwdclient_t *client; REQUIRE(!SHUTTINGDOWN(cm)); ns_lwdclient_log(50, "got shutdown event, task %p, lwdclientmgr %p", task, cm); /* * run through the idle list and free the clients there. Idle * clients do not have a recv running nor do they have any finds * or similar running. */ LOCK(&cm->lock); client = ISC_LIST_HEAD(cm->idle); while (client != NULL) { ns_lwdclient_log(50, "destroying client %p, manager %p", client, cm); ISC_LIST_UNLINK(cm->idle, client, link); isc_mem_put(cm->mctx, client, sizeof(*client)); client = ISC_LIST_HEAD(cm->idle); } UNLOCK(&cm->lock); /* * Cancel any pending I/O. */ isc_socket_cancel(cm->sock, task, ISC_SOCKCANCEL_ALL); /* * Run through the running client list and kill off any finds * in progress. */ LOCK(&cm->lock); client = ISC_LIST_HEAD(cm->running); while (client != NULL) { if (client->find != client->v4find && client->find != client->v6find) dns_adb_cancelfind(client->find); if (client->v4find != NULL) dns_adb_cancelfind(client->v4find); if (client->v6find != NULL) dns_adb_cancelfind(client->v6find); client = ISC_LIST_NEXT(client, link); } cm->flags |= NS_LWDCLIENTMGR_FLAGSHUTTINGDOWN; UNLOCK(&cm->lock); isc_event_free(&ev); } /* * Do all the crap needed to move a client from the run queue to the idle * queue. */ void ns_lwdclient_stateidle(ns_lwdclient_t *client) { ns_lwdclientmgr_t *cm; isc_result_t result; cm = client->clientmgr; INSIST(client->sendbuf == NULL); INSIST(client->sendlength == 0); INSIST(client->arg == NULL); INSIST(client->v4find == NULL); INSIST(client->v6find == NULL); LOCK(&cm->lock); ISC_LIST_UNLINK(cm->running, client, link); ISC_LIST_PREPEND(cm->idle, client, link); UNLOCK(&cm->lock); NS_LWDCLIENT_SETIDLE(client); result = ns_lwdclient_startrecv(cm); if (result != ISC_R_SUCCESS) isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_LWRESD, ISC_LOG_ERROR, "could not start lwres " "client handler: %s", isc_result_totext(result)); } void ns_lwdclient_send(isc_task_t *task, isc_event_t *ev) { ns_lwdclient_t *client = ev->ev_arg; ns_lwdclientmgr_t *cm = client->clientmgr; isc_socketevent_t *dev = (isc_socketevent_t *)ev; UNUSED(task); UNUSED(dev); INSIST(NS_LWDCLIENT_ISSEND(client)); INSIST(client->sendbuf == dev->region.base); ns_lwdclient_log(50, "task %p for client %p got send-done event", task, client); if (client->sendbuf != client->buffer) lwres_context_freemem(cm->lwctx, client->sendbuf, client->sendlength); client->sendbuf = NULL; client->sendlength = 0; ns_lwdclient_stateidle(client); isc_event_free(&ev); } isc_result_t ns_lwdclient_sendreply(ns_lwdclient_t *client, isc_region_t *r) { struct in6_pktinfo *pktinfo; ns_lwdclientmgr_t *cm = client->clientmgr; if (client->pktinfo_valid) pktinfo = &client->pktinfo; else pktinfo = NULL; return (isc_socket_sendto(cm->sock, r, cm->task, ns_lwdclient_send, client, &client->address, pktinfo)); } void ns_lwdclient_initialize(ns_lwdclient_t *client, ns_lwdclientmgr_t *cmgr) { client->clientmgr = cmgr; ISC_LINK_INIT(client, link); NS_LWDCLIENT_SETIDLE(client); client->arg = NULL; client->recvlength = 0; client->sendbuf = NULL; client->sendlength = 0; client->find = NULL; client->v4find = NULL; client->v6find = NULL; client->find_wanted = 0; client->options = 0; client->byaddr = NULL; client->lookup = NULL; client->pktinfo_valid = ISC_FALSE; LOCK(&cmgr->lock); ISC_LIST_APPEND(cmgr->idle, client, link); UNLOCK(&cmgr->lock); } bind9-9.11.3+dfsg/bin/named/lwderror.c000066400000000000000000000040601325250447100173740ustar00rootroot00000000000000/* * Copyright (C) 2000, 2001, 2004, 2005, 2007, 2016 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* $Id: lwderror.c,v 1.12 2007/06/19 23:46:59 tbox Exp $ */ /*! \file */ #include #include #include #include #include /*% * Generate an error packet for the client, schedule a send, and put us in * the SEND state. * * The client->pkt structure will be modified to form an error return. * The receiver needs to verify that it is in fact an error, and do the * right thing with it. The opcode will be unchanged. The result needs * to be set before calling this function. * * The only change this code makes is to set the receive buffer size to the * size we use, set the reply bit, and recompute any security information. */ void ns_lwdclient_errorpktsend(ns_lwdclient_t *client, isc_uint32_t _result) { isc_result_t result; int lwres; isc_region_t r; lwres_buffer_t b; REQUIRE(NS_LWDCLIENT_ISRUNNING(client)); /* * Since we are only sending the packet header, we can safely toss * the receive buffer. This means we won't need to allocate space * for sending an error reply. This is a Good Thing. */ client->pkt.length = LWRES_LWPACKET_LENGTH; client->pkt.pktflags |= LWRES_LWPACKETFLAG_RESPONSE; client->pkt.recvlength = LWRES_RECVLENGTH; client->pkt.authtype = 0; /* XXXMLG */ client->pkt.authlength = 0; client->pkt.result = _result; lwres_buffer_init(&b, client->buffer, LWRES_RECVLENGTH); lwres = lwres_lwpacket_renderheader(&b, &client->pkt); if (lwres != LWRES_R_SUCCESS) { ns_lwdclient_stateidle(client); return; } r.base = client->buffer; r.length = b.used; client->sendbuf = client->buffer; result = ns_lwdclient_sendreply(client, &r); if (result != ISC_R_SUCCESS) { ns_lwdclient_stateidle(client); return; } NS_LWDCLIENT_SETSEND(client); } bind9-9.11.3+dfsg/bin/named/lwdgabn.c000066400000000000000000000376051325250447100171650ustar00rootroot00000000000000/* * Copyright (C) 2000, 2001, 2004-2007, 2009, 2016 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* $Id: lwdgabn.c,v 1.24 2009/09/02 23:48:01 tbox Exp $ */ /*! \file */ #include #include #include #include #include #include /* Required for HP/UX (and others?) */ #include #include #include #include #include #include #include #include #include #include #define NEED_V4(c) ((((c)->find_wanted & LWRES_ADDRTYPE_V4) != 0) \ && ((c)->v4find == NULL)) #define NEED_V6(c) ((((c)->find_wanted & LWRES_ADDRTYPE_V6) != 0) \ && ((c)->v6find == NULL)) static isc_result_t start_find(ns_lwdclient_t *); static void restart_find(ns_lwdclient_t *); static void init_gabn(ns_lwdclient_t *); /*% * Destroy any finds. This can be used to "start over from scratch" and * should only be called when events are _not_ being generated by the finds. */ static void cleanup_gabn(ns_lwdclient_t *client) { ns_lwdclient_log(50, "cleaning up client %p", client); if (client->v6find != NULL) { if (client->v6find == client->v4find) client->v6find = NULL; else dns_adb_destroyfind(&client->v6find); } if (client->v4find != NULL) dns_adb_destroyfind(&client->v4find); } static void setup_addresses(ns_lwdclient_t *client, dns_adbfind_t *find, unsigned int at) { dns_adbaddrinfo_t *ai; lwres_addr_t *addr; int af; const struct sockaddr *sa; isc_result_t result; if (at == DNS_ADBFIND_INET) af = AF_INET; else af = AF_INET6; ai = ISC_LIST_HEAD(find->list); while (ai != NULL && client->gabn.naddrs < LWRES_MAX_ADDRS) { sa = &ai->sockaddr.type.sa; if (sa->sa_family != af) goto next; addr = &client->addrs[client->gabn.naddrs]; result = lwaddr_lwresaddr_fromsockaddr(addr, &ai->sockaddr); if (result != ISC_R_SUCCESS) goto next; ns_lwdclient_log(50, "adding address %p, family %d, length %d", addr->address, addr->family, addr->length); client->gabn.naddrs++; REQUIRE(!LWRES_LINK_LINKED(addr, link)); LWRES_LIST_APPEND(client->gabn.addrs, addr, link); next: ai = ISC_LIST_NEXT(ai, publink); } } typedef struct { isc_netaddr_t address; int rank; } rankedaddress; static int addr_compare(const void *av, const void *bv) { const rankedaddress *a = (const rankedaddress *) av; const rankedaddress *b = (const rankedaddress *) bv; return (a->rank - b->rank); } static void sort_addresses(ns_lwdclient_t *client) { unsigned int naddrs; rankedaddress *addrs; isc_netaddr_t remote; dns_addressorderfunc_t order; const void *arg; ns_lwresd_t *lwresd = client->clientmgr->listener->manager; unsigned int i; isc_result_t result; naddrs = client->gabn.naddrs; if (naddrs <= 1 || lwresd->view->sortlist == NULL) return; addrs = isc_mem_get(lwresd->mctx, sizeof(rankedaddress) * naddrs); if (addrs == NULL) return; isc_netaddr_fromsockaddr(&remote, &client->address); ns_sortlist_byaddrsetup(lwresd->view->sortlist, &remote, &order, &arg); if (order == NULL) { isc_mem_put(lwresd->mctx, addrs, sizeof(rankedaddress) * naddrs); return; } for (i = 0; i < naddrs; i++) { result = lwaddr_netaddr_fromlwresaddr(&addrs[i].address, &client->addrs[i]); INSIST(result == ISC_R_SUCCESS); addrs[i].rank = (*order)(&addrs[i].address, arg); } qsort(addrs, naddrs, sizeof(rankedaddress), addr_compare); for (i = 0; i < naddrs; i++) { result = lwaddr_lwresaddr_fromnetaddr(&client->addrs[i], &addrs[i].address); INSIST(result == ISC_R_SUCCESS); } isc_mem_put(lwresd->mctx, addrs, sizeof(rankedaddress) * naddrs); } static void generate_reply(ns_lwdclient_t *client) { isc_result_t result; int lwres; isc_region_t r; lwres_buffer_t lwb; ns_lwdclientmgr_t *cm; cm = client->clientmgr; lwb.base = NULL; ns_lwdclient_log(50, "generating gabn reply for client %p", client); /* * We must make certain the client->find is not still active. * If it is either the v4 or v6 answer, just set it to NULL and * let the cleanup code destroy it. Otherwise, destroy it now. */ if (client->find == client->v4find || client->find == client->v6find) client->find = NULL; else if (client->find != NULL) dns_adb_destroyfind(&client->find); /* * perhaps there are some here? */ if (NEED_V6(client) && client->v4find != NULL) client->v6find = client->v4find; /* * Run through the finds we have and wire them up to the gabn * structure. */ LWRES_LIST_INIT(client->gabn.addrs); if (client->v4find != NULL) setup_addresses(client, client->v4find, DNS_ADBFIND_INET); if (client->v6find != NULL) setup_addresses(client, client->v6find, DNS_ADBFIND_INET6); /* * If there are no addresses, try the next element in the search * path, if there are any more. Otherwise, fall through into * the error handling code below. */ if (client->gabn.naddrs == 0) { do { result = ns_lwsearchctx_next(&client->searchctx); if (result == ISC_R_SUCCESS) { cleanup_gabn(client); result = start_find(client); if (result == ISC_R_SUCCESS) return; } } while (result == ISC_R_SUCCESS); } /* * Render the packet. */ client->pkt.recvlength = LWRES_RECVLENGTH; client->pkt.authtype = 0; /* XXXMLG */ client->pkt.authlength = 0; /* * If there are no addresses, return failure. */ if (client->gabn.naddrs != 0) client->pkt.result = LWRES_R_SUCCESS; else client->pkt.result = LWRES_R_NOTFOUND; sort_addresses(client); lwres = lwres_gabnresponse_render(cm->lwctx, &client->gabn, &client->pkt, &lwb); if (lwres != LWRES_R_SUCCESS) goto out; r.base = lwb.base; r.length = lwb.used; client->sendbuf = r.base; client->sendlength = r.length; result = ns_lwdclient_sendreply(client, &r); if (result != ISC_R_SUCCESS) goto out; NS_LWDCLIENT_SETSEND(client); /* * All done! */ cleanup_gabn(client); return; out: cleanup_gabn(client); if (lwb.base != NULL) lwres_context_freemem(client->clientmgr->lwctx, lwb.base, lwb.length); ns_lwdclient_errorpktsend(client, LWRES_R_FAILURE); } /* * Take the current real name, move it to an alias slot (if any are * open) then put this new name in as the real name for the target. * * Return success if it can be rendered, otherwise failure. Note that * not having enough alias slots open is NOT a failure. */ static isc_result_t add_alias(ns_lwdclient_t *client) { isc_buffer_t b; isc_result_t result; isc_uint16_t naliases; b = client->recv_buffer; /* * Render the new name to the buffer. */ result = dns_name_totext(dns_fixedname_name(&client->target_name), ISC_TRUE, &client->recv_buffer); if (result != ISC_R_SUCCESS) return (result); /* * Are there any open slots? */ naliases = client->gabn.naliases; if (naliases < LWRES_MAX_ALIASES) { client->gabn.aliases[naliases] = client->gabn.realname; client->gabn.aliaslen[naliases] = client->gabn.realnamelen; client->gabn.naliases++; } /* * Save this name away as the current real name. */ client->gabn.realname = (char *)(b.base) + b.used; client->gabn.realnamelen = client->recv_buffer.used - b.used; return (ISC_R_SUCCESS); } static isc_result_t store_realname(ns_lwdclient_t *client) { isc_buffer_t b; isc_result_t result; dns_name_t *tname; b = client->recv_buffer; tname = dns_fixedname_name(&client->target_name); result = ns_lwsearchctx_current(&client->searchctx, tname); if (result != ISC_R_SUCCESS) return (result); /* * Render the new name to the buffer. */ result = dns_name_totext(tname, ISC_TRUE, &client->recv_buffer); if (result != ISC_R_SUCCESS) return (result); /* * Save this name away as the current real name. */ client->gabn.realname = (char *) b.base + b.used; client->gabn.realnamelen = client->recv_buffer.used - b.used; return (ISC_R_SUCCESS); } static void process_gabn_finddone(isc_task_t *task, isc_event_t *ev) { ns_lwdclient_t *client = ev->ev_arg; isc_eventtype_t evtype; isc_boolean_t claimed; ns_lwdclient_log(50, "find done for task %p, client %p", task, client); evtype = ev->ev_type; isc_event_free(&ev); /* * No more info to be had? If so, we have all the good stuff * right now, so we can render things. */ claimed = ISC_FALSE; if (evtype == DNS_EVENT_ADBNOMOREADDRESSES) { if (NEED_V4(client)) { client->v4find = client->find; claimed = ISC_TRUE; } if (NEED_V6(client)) { client->v6find = client->find; claimed = ISC_TRUE; } if (client->find != NULL) { if (claimed) client->find = NULL; else dns_adb_destroyfind(&client->find); } generate_reply(client); return; } /* * We probably don't need this find anymore. We're either going to * reissue it, or an error occurred. Either way, we're done with * it. */ if ((client->find != client->v4find) && (client->find != client->v6find)) { dns_adb_destroyfind(&client->find); } else { client->find = NULL; } /* * We have some new information we can gather. Run off and fetch * it. */ if (evtype == DNS_EVENT_ADBMOREADDRESSES) { restart_find(client); return; } /* * An error or other strangeness happened. Drop this query. */ cleanup_gabn(client); ns_lwdclient_errorpktsend(client, LWRES_R_FAILURE); } static void restart_find(ns_lwdclient_t *client) { unsigned int options; isc_result_t result; isc_boolean_t claimed; ns_lwdclient_log(50, "starting find for client %p", client); /* * Issue a find for the name contained in the request. We won't * set the bit that says "anything is good enough" -- we want it * all. */ options = 0; options |= DNS_ADBFIND_WANTEVENT; options |= DNS_ADBFIND_RETURNLAME; /* * Set the bits up here to mark that we want this address family * and that we do not currently have a find pending. We will * set that bit again below if it turns out we will get an event. */ if (NEED_V4(client)) options |= DNS_ADBFIND_INET; if (NEED_V6(client)) options |= DNS_ADBFIND_INET6; find_again: INSIST(client->find == NULL); result = dns_adb_createfind(client->clientmgr->view->adb, client->clientmgr->task, process_gabn_finddone, client, dns_fixedname_name(&client->target_name), dns_rootname, 0, options, 0, dns_fixedname_name(&client->target_name), client->clientmgr->view->dstport, &client->find); /* * Did we get an alias? If so, save it and re-issue the query. */ if (result == DNS_R_ALIAS) { ns_lwdclient_log(50, "found alias, restarting query"); dns_adb_destroyfind(&client->find); cleanup_gabn(client); result = add_alias(client); if (result != ISC_R_SUCCESS) { ns_lwdclient_log(50, "out of buffer space adding alias"); ns_lwdclient_errorpktsend(client, LWRES_R_FAILURE); return; } goto find_again; } ns_lwdclient_log(50, "find returned %d (%s)", result, isc_result_totext(result)); /* * Did we get an error? */ if (result != ISC_R_SUCCESS) { if (client->find != NULL) dns_adb_destroyfind(&client->find); cleanup_gabn(client); ns_lwdclient_errorpktsend(client, LWRES_R_FAILURE); return; } claimed = ISC_FALSE; /* * Did we get our answer to V4 addresses? */ if (NEED_V4(client) && ((client->find->query_pending & DNS_ADBFIND_INET) == 0)) { ns_lwdclient_log(50, "client %p ipv4 satisfied by find %p", client, client->find); claimed = ISC_TRUE; client->v4find = client->find; } /* * Did we get our answer to V6 addresses? */ if (NEED_V6(client) && ((client->find->query_pending & DNS_ADBFIND_INET6) == 0)) { ns_lwdclient_log(50, "client %p ipv6 satisfied by find %p", client, client->find); claimed = ISC_TRUE; client->v6find = client->find; } /* * If we're going to get an event, set our internal pending flag * and return. When we get an event back we'll do the right * thing, basically by calling this function again, perhaps with a * new target name. * * If we have both v4 and v6, and we are still getting an event, * we have a programming error, so die hard. */ if ((client->find->options & DNS_ADBFIND_WANTEVENT) != 0) { ns_lwdclient_log(50, "event will be sent"); INSIST(client->v4find == NULL || client->v6find == NULL); return; } ns_lwdclient_log(50, "no event will be sent"); if (claimed) client->find = NULL; else dns_adb_destroyfind(&client->find); /* * We seem to have everything we asked for, or at least we are * able to respond with things we've learned. */ generate_reply(client); } static isc_result_t start_find(ns_lwdclient_t *client) { isc_result_t result; /* * Initialize the real name and alias arrays in the reply we're * going to build up. */ init_gabn(client); result = store_realname(client); if (result != ISC_R_SUCCESS) return (result); restart_find(client); return (ISC_R_SUCCESS); } static void init_gabn(ns_lwdclient_t *client) { int i; /* * Initialize the real name and alias arrays in the reply we're * going to build up. */ for (i = 0; i < LWRES_MAX_ALIASES; i++) { client->aliases[i] = NULL; client->aliaslen[i] = 0; } for (i = 0; i < LWRES_MAX_ADDRS; i++) { client->addrs[i].family = 0; client->addrs[i].length = 0; memset(client->addrs[i].address, 0, LWRES_ADDR_MAXLEN); LWRES_LINK_INIT(&client->addrs[i], link); } client->gabn.naliases = 0; client->gabn.naddrs = 0; client->gabn.realname = NULL; client->gabn.aliases = client->aliases; client->gabn.realnamelen = 0; client->gabn.aliaslen = client->aliaslen; LWRES_LIST_INIT(client->gabn.addrs); client->gabn.base = NULL; client->gabn.baselen = 0; /* * Set up the internal buffer to point to the receive region. */ isc_buffer_init(&client->recv_buffer, client->buffer, LWRES_RECVLENGTH); } /* * When we are called, we can be assured that: * * client->sockaddr contains the address we need to reply to, * * client->pkt contains the packet header data, * * the packet "checks out" overall -- any MD5 hashes or crypto * bits have been verified, * * "b" points to the remaining data after the packet header * was parsed off. * * We are in a the RECVDONE state. * * From this state we will enter the SEND state if we happen to have * everything we need or we need to return an error packet, or to the * FINDWAIT state if we need to look things up. */ void ns_lwdclient_processgabn(ns_lwdclient_t *client, lwres_buffer_t *b) { isc_result_t result; lwres_gabnrequest_t *req; ns_lwdclientmgr_t *cm; isc_buffer_t namebuf; REQUIRE(NS_LWDCLIENT_ISRECVDONE(client)); cm = client->clientmgr; req = NULL; result = lwres_gabnrequest_parse(client->clientmgr->lwctx, b, &client->pkt, &req); if (result != LWRES_R_SUCCESS) goto out; if (req->name == NULL) goto out; isc_buffer_init(&namebuf, req->name, req->namelen); isc_buffer_add(&namebuf, req->namelen); dns_fixedname_init(&client->target_name); dns_fixedname_init(&client->query_name); result = dns_name_fromtext(dns_fixedname_name(&client->query_name), &namebuf, NULL, 0, NULL); if (result != ISC_R_SUCCESS) goto out; ns_lwsearchctx_init(&client->searchctx, cm->listener->manager->search, dns_fixedname_name(&client->query_name), cm->listener->manager->ndots); ns_lwsearchctx_first(&client->searchctx); client->find_wanted = req->addrtypes; ns_lwdclient_log(50, "client %p looking for addrtypes %08x", client, client->find_wanted); /* * We no longer need to keep this around. */ lwres_gabnrequest_free(client->clientmgr->lwctx, &req); /* * Start the find. */ result = start_find(client); if (result != ISC_R_SUCCESS) goto out; return; /* * We're screwed. Return an error packet to our caller. */ out: if (req != NULL) lwres_gabnrequest_free(client->clientmgr->lwctx, &req); ns_lwdclient_errorpktsend(client, LWRES_R_FAILURE); } bind9-9.11.3+dfsg/bin/named/lwdgnba.c000066400000000000000000000140541325250447100171560ustar00rootroot00000000000000/* * Copyright (C) 2000-2002, 2004, 2005, 2007, 2008, 2014, 2016 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* $Id: lwdgnba.c,v 1.22 2008/01/14 23:46:56 tbox Exp $ */ /*! \file */ #include #include #include /* Required for HP/UX (and others?) */ #include #include #include #include #include #include static void start_byaddr(ns_lwdclient_t *); static void byaddr_done(isc_task_t *task, isc_event_t *event) { ns_lwdclient_t *client; ns_lwdclientmgr_t *cm; dns_byaddrevent_t *bevent; int lwres; lwres_buffer_t lwb; dns_name_t *name; isc_result_t result; lwres_result_t lwresult; isc_region_t r; isc_buffer_t b; lwres_gnbaresponse_t *gnba; isc_uint16_t naliases; UNUSED(task); lwb.base = NULL; client = event->ev_arg; cm = client->clientmgr; INSIST(client->byaddr == (dns_byaddr_t *)event->ev_sender); bevent = (dns_byaddrevent_t *)event; gnba = &client->gnba; ns_lwdclient_log(50, "byaddr event result = %s", isc_result_totext(bevent->result)); result = bevent->result; if (result != ISC_R_SUCCESS) { dns_byaddr_destroy(&client->byaddr); isc_event_free(&event); bevent = NULL; if (client->na.family != AF_INET6 || (client->options & DNS_BYADDROPT_IPV6INT) != 0) { if (result == DNS_R_NCACHENXDOMAIN || result == DNS_R_NCACHENXRRSET || result == DNS_R_NXDOMAIN || result == DNS_R_NXRRSET) lwresult = LWRES_R_NOTFOUND; else lwresult = LWRES_R_FAILURE; ns_lwdclient_errorpktsend(client, lwresult); return; } /* * Fall back to ip6.int reverse if the default ip6.arpa * fails. */ client->options |= DNS_BYADDROPT_IPV6INT; start_byaddr(client); return; } for (name = ISC_LIST_HEAD(bevent->names); name != NULL; name = ISC_LIST_NEXT(name, link)) { b = client->recv_buffer; result = dns_name_totext(name, ISC_TRUE, &client->recv_buffer); if (result != ISC_R_SUCCESS) goto out; ns_lwdclient_log(50, "found name '%.*s'", (int)(client->recv_buffer.used - b.used), (char *)(b.base) + b.used); if (gnba->realname == NULL) { gnba->realname = (char *)(b.base) + b.used; gnba->realnamelen = client->recv_buffer.used - b.used; } else { naliases = gnba->naliases; if (naliases >= LWRES_MAX_ALIASES) break; gnba->aliases[naliases] = (char *)(b.base) + b.used; gnba->aliaslen[naliases] = client->recv_buffer.used - b.used; gnba->naliases++; } } dns_byaddr_destroy(&client->byaddr); isc_event_free(&event); /* * Render the packet. */ client->pkt.recvlength = LWRES_RECVLENGTH; client->pkt.authtype = 0; /* XXXMLG */ client->pkt.authlength = 0; client->pkt.result = LWRES_R_SUCCESS; lwres = lwres_gnbaresponse_render(cm->lwctx, gnba, &client->pkt, &lwb); if (lwres != LWRES_R_SUCCESS) goto out; r.base = lwb.base; r.length = lwb.used; client->sendbuf = r.base; client->sendlength = r.length; result = ns_lwdclient_sendreply(client, &r); if (result != ISC_R_SUCCESS) goto out; NS_LWDCLIENT_SETSEND(client); return; out: if (client->byaddr != NULL) dns_byaddr_destroy(&client->byaddr); if (lwb.base != NULL) lwres_context_freemem(cm->lwctx, lwb.base, lwb.length); if (event != NULL) isc_event_free(&event); } static void start_byaddr(ns_lwdclient_t *client) { isc_result_t result; ns_lwdclientmgr_t *cm; cm = client->clientmgr; INSIST(client->byaddr == NULL); result = dns_byaddr_create(cm->mctx, &client->na, cm->view, client->options, cm->task, byaddr_done, client, &client->byaddr); if (result != ISC_R_SUCCESS) { ns_lwdclient_errorpktsend(client, LWRES_R_FAILURE); return; } } static void init_gnba(ns_lwdclient_t *client) { int i; /* * Initialize the real name and alias arrays in the reply we're * going to build up. */ for (i = 0; i < LWRES_MAX_ALIASES; i++) { client->aliases[i] = NULL; client->aliaslen[i] = 0; } for (i = 0; i < LWRES_MAX_ADDRS; i++) { client->addrs[i].family = 0; client->addrs[i].length = 0; memset(client->addrs[i].address, 0, LWRES_ADDR_MAXLEN); LWRES_LINK_INIT(&client->addrs[i], link); } client->gnba.naliases = 0; client->gnba.realname = NULL; client->gnba.aliases = client->aliases; client->gnba.realnamelen = 0; client->gnba.aliaslen = client->aliaslen; client->gnba.base = NULL; client->gnba.baselen = 0; isc_buffer_init(&client->recv_buffer, client->buffer, LWRES_RECVLENGTH); } void ns_lwdclient_processgnba(ns_lwdclient_t *client, lwres_buffer_t *b) { lwres_gnbarequest_t *req; isc_result_t result; isc_sockaddr_t sa; ns_lwdclientmgr_t *cm; REQUIRE(NS_LWDCLIENT_ISRECVDONE(client)); INSIST(client->byaddr == NULL); cm = client->clientmgr; req = NULL; result = lwres_gnbarequest_parse(cm->lwctx, b, &client->pkt, &req); if (result != LWRES_R_SUCCESS) goto out; client->options = 0; if (req->addr.family == LWRES_ADDRTYPE_V4) { client->na.family = AF_INET; if (req->addr.length != 4) goto out; memmove(&client->na.type.in, req->addr.address, 4); } else if (req->addr.family == LWRES_ADDRTYPE_V6) { client->na.family = AF_INET6; if (req->addr.length != 16) goto out; memmove(&client->na.type.in6, req->addr.address, 16); } else { goto out; } isc_sockaddr_fromnetaddr(&sa, &client->na, 53); ns_lwdclient_log(50, "client %p looking for addrtype %08x", client, req->addr.family); /* * We no longer need to keep this around. */ lwres_gnbarequest_free(cm->lwctx, &req); /* * Initialize the real name and alias arrays in the reply we're * going to build up. */ init_gnba(client); client->options = 0; /* * Start the find. */ start_byaddr(client); return; /* * We're screwed. Return an error packet to our caller. */ out: if (req != NULL) lwres_gnbarequest_free(cm->lwctx, &req); ns_lwdclient_errorpktsend(client, LWRES_R_FAILURE); } bind9-9.11.3+dfsg/bin/named/lwdgrbn.c000066400000000000000000000311601325250447100171740ustar00rootroot00000000000000/* * Copyright (C) 2000, 2001, 2003-2007, 2009, 2013-2016 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* $Id: lwdgrbn.c,v 1.22 2009/09/02 23:48:01 tbox Exp $ */ /*! \file */ #include #include #include #include /* Required for HP/UX (and others?) */ #include #include #include #include #include #include #include #include #include #include #include #include static void start_lookup(ns_lwdclient_t *); static isc_result_t fill_array(int *pos, dns_rdataset_t *rdataset, int size, unsigned char **rdatas, lwres_uint16_t *rdatalen) { dns_rdata_t rdata; isc_result_t result; isc_region_t r; UNUSED(size); dns_rdata_init(&rdata); for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS; result = dns_rdataset_next(rdataset)) { INSIST(*pos < size); dns_rdataset_current(rdataset, &rdata); dns_rdata_toregion(&rdata, &r); rdatas[*pos] = r.base; rdatalen[*pos] = r.length; dns_rdata_reset(&rdata); (*pos)++; } if (result == ISC_R_NOMORE) result = ISC_R_SUCCESS; return (result); } static isc_result_t iterate_node(lwres_grbnresponse_t *grbn, dns_db_t *db, dns_dbnode_t *node, isc_mem_t *mctx) { int used = 0, count; int size = 8, oldsize = 0; unsigned char **rdatas = NULL, **oldrdatas = NULL, **newrdatas = NULL; lwres_uint16_t *lens = NULL, *oldlens = NULL, *newlens = NULL; dns_rdatasetiter_t *iter = NULL; dns_rdataset_t set; dns_ttl_t ttl = ISC_INT32_MAX; lwres_uint32_t flags = LWRDATA_VALIDATED; isc_result_t result = ISC_R_NOMEMORY; result = dns_db_allrdatasets(db, node, NULL, 0, &iter); if (result != ISC_R_SUCCESS) goto out; rdatas = isc_mem_get(mctx, size * sizeof(*rdatas)); if (rdatas == NULL) goto out; lens = isc_mem_get(mctx, size * sizeof(*lens)); if (lens == NULL) goto out; for (result = dns_rdatasetiter_first(iter); result == ISC_R_SUCCESS; result = dns_rdatasetiter_next(iter)) { result = ISC_R_NOMEMORY; dns_rdataset_init(&set); dns_rdatasetiter_current(iter, &set); if (set.type != dns_rdatatype_rrsig) { dns_rdataset_disassociate(&set); continue; } count = dns_rdataset_count(&set); if (used + count > size) { /* copy & reallocate */ oldsize = size; oldrdatas = rdatas; oldlens = lens; rdatas = NULL; lens = NULL; size *= 2; rdatas = isc_mem_get(mctx, size * sizeof(*rdatas)); if (rdatas == NULL) goto out; lens = isc_mem_get(mctx, size * sizeof(*lens)); if (lens == NULL) goto out; memmove(rdatas, oldrdatas, used * sizeof(*rdatas)); memmove(lens, oldlens, used * sizeof(*lens)); isc_mem_put(mctx, oldrdatas, oldsize * sizeof(*oldrdatas)); isc_mem_put(mctx, oldlens, oldsize * sizeof(*oldlens)); oldrdatas = NULL; oldlens = NULL; } if (set.ttl < ttl) ttl = set.ttl; if (set.trust != dns_trust_secure) flags &= (~LWRDATA_VALIDATED); result = fill_array(&used, &set, size, rdatas, lens); dns_rdataset_disassociate(&set); if (result != ISC_R_SUCCESS) goto out; } if (result == ISC_R_NOMORE) result = ISC_R_SUCCESS; if (result != ISC_R_SUCCESS) goto out; dns_rdatasetiter_destroy(&iter); /* * If necessary, shrink and copy the arrays. */ if (size != used) { result = ISC_R_NOMEMORY; newrdatas = isc_mem_get(mctx, used * sizeof(*rdatas)); if (newrdatas == NULL) goto out; newlens = isc_mem_get(mctx, used * sizeof(*lens)); if (newlens == NULL) goto out; memmove(newrdatas, rdatas, used * sizeof(*rdatas)); memmove(newlens, lens, used * sizeof(*lens)); isc_mem_put(mctx, rdatas, size * sizeof(*rdatas)); isc_mem_put(mctx, lens, size * sizeof(*lens)); grbn->rdatas = newrdatas; grbn->rdatalen = newlens; } else { grbn->rdatas = rdatas; grbn->rdatalen = lens; } grbn->nrdatas = used; grbn->ttl = ttl; grbn->flags = flags; return (ISC_R_SUCCESS); out: dns_rdatasetiter_destroy(&iter); if (rdatas != NULL) isc_mem_put(mctx, rdatas, size * sizeof(*rdatas)); if (lens != NULL) isc_mem_put(mctx, lens, size * sizeof(*lens)); if (oldrdatas != NULL) isc_mem_put(mctx, oldrdatas, oldsize * sizeof(*oldrdatas)); if (oldlens != NULL) isc_mem_put(mctx, oldlens, oldsize * sizeof(*oldlens)); if (newrdatas != NULL) isc_mem_put(mctx, newrdatas, used * sizeof(*newrdatas)); return (result); } static void lookup_done(isc_task_t *task, isc_event_t *event) { ns_lwdclient_t *client; ns_lwdclientmgr_t *cm; dns_lookupevent_t *levent; lwres_buffer_t lwb; dns_name_t *name; dns_rdataset_t *rdataset; dns_rdataset_t *sigrdataset; isc_result_t result; lwres_result_t lwresult; isc_region_t r; isc_buffer_t b; lwres_grbnresponse_t *grbn; int i; REQUIRE(event != NULL); UNUSED(task); lwb.base = NULL; client = event->ev_arg; cm = client->clientmgr; INSIST(client->lookup == (dns_lookup_t *)event->ev_sender); levent = (dns_lookupevent_t *)event; grbn = &client->grbn; ns_lwdclient_log(50, "lookup event result = %s", isc_result_totext(levent->result)); result = levent->result; if (result != ISC_R_SUCCESS) { dns_lookup_destroy(&client->lookup); isc_event_free(&event); levent = NULL; switch (result) { case DNS_R_NXDOMAIN: case DNS_R_NCACHENXDOMAIN: result = ns_lwsearchctx_next(&client->searchctx); if (result != ISC_R_SUCCESS) lwresult = LWRES_R_NOTFOUND; else { start_lookup(client); return; } break; case DNS_R_NXRRSET: case DNS_R_NCACHENXRRSET: lwresult = LWRES_R_TYPENOTFOUND; break; default: lwresult = LWRES_R_FAILURE; } ns_lwdclient_errorpktsend(client, lwresult); return; } name = levent->name; b = client->recv_buffer; grbn->flags = 0; grbn->nrdatas = 0; grbn->rdatas = NULL; grbn->rdatalen = NULL; grbn->nsigs = 0; grbn->sigs = NULL; grbn->siglen = NULL; result = dns_name_totext(name, ISC_TRUE, &client->recv_buffer); if (result != ISC_R_SUCCESS) goto out; grbn->realname = (char *)isc_buffer_used(&b); grbn->realnamelen = isc_buffer_usedlength(&client->recv_buffer) - isc_buffer_usedlength(&b); ns_lwdclient_log(50, "found name '%.*s'", grbn->realnamelen, grbn->realname); grbn->rdclass = cm->view->rdclass; grbn->rdtype = client->rdtype; rdataset = levent->rdataset; if (rdataset != NULL) { /* The normal case */ grbn->nrdatas = dns_rdataset_count(rdataset); grbn->rdatas = isc_mem_get(cm->mctx, grbn->nrdatas * sizeof(unsigned char *)); if (grbn->rdatas == NULL) goto out; grbn->rdatalen = isc_mem_get(cm->mctx, grbn->nrdatas * sizeof(lwres_uint16_t)); if (grbn->rdatalen == NULL) goto out; i = 0; result = fill_array(&i, rdataset, grbn->nrdatas, grbn->rdatas, grbn->rdatalen); if (result != ISC_R_SUCCESS) goto out; INSIST(i == grbn->nrdatas); grbn->ttl = rdataset->ttl; if (rdataset->trust == dns_trust_secure) grbn->flags |= LWRDATA_VALIDATED; } else { /* The SIG query case */ result = iterate_node(grbn, levent->db, levent->node, cm->mctx); if (result != ISC_R_SUCCESS) goto out; } ns_lwdclient_log(50, "filled in %d rdata%s", grbn->nrdatas, (grbn->nrdatas == 1) ? "" : "s"); sigrdataset = levent->sigrdataset; if (sigrdataset != NULL) { grbn->nsigs = dns_rdataset_count(sigrdataset); grbn->sigs = isc_mem_get(cm->mctx, grbn->nsigs * sizeof(unsigned char *)); if (grbn->sigs == NULL) goto out; grbn->siglen = isc_mem_get(cm->mctx, grbn->nsigs * sizeof(lwres_uint16_t)); if (grbn->siglen == NULL) goto out; i = 0; result = fill_array(&i, sigrdataset, grbn->nsigs, grbn->sigs, grbn->siglen); if (result != ISC_R_SUCCESS) goto out; INSIST(i == grbn->nsigs); ns_lwdclient_log(50, "filled in %d signature%s", grbn->nsigs, (grbn->nsigs == 1) ? "" : "s"); } /* * Render the packet. */ client->pkt.recvlength = LWRES_RECVLENGTH; client->pkt.authtype = 0; /* XXXMLG */ client->pkt.authlength = 0; client->pkt.result = LWRES_R_SUCCESS; lwresult = lwres_grbnresponse_render(cm->lwctx, grbn, &client->pkt, &lwb); if (lwresult != LWRES_R_SUCCESS) goto out; isc_mem_put(cm->mctx, grbn->rdatas, grbn->nrdatas * sizeof(unsigned char *)); isc_mem_put(cm->mctx, grbn->rdatalen, grbn->nrdatas * sizeof(lwres_uint16_t)); if (grbn->sigs != NULL) isc_mem_put(cm->mctx, grbn->sigs, grbn->nsigs * sizeof(unsigned char *)); if (grbn->siglen != NULL) isc_mem_put(cm->mctx, grbn->siglen, grbn->nsigs * sizeof(lwres_uint16_t)); r.base = lwb.base; r.length = lwb.used; client->sendbuf = r.base; client->sendlength = r.length; result = ns_lwdclient_sendreply(client, &r); if (result != ISC_R_SUCCESS) goto out2; NS_LWDCLIENT_SETSEND(client); dns_lookup_destroy(&client->lookup); isc_event_free(&event); return; out: if (grbn->rdatas != NULL) isc_mem_put(cm->mctx, grbn->rdatas, grbn->nrdatas * sizeof(unsigned char *)); if (grbn->rdatalen != NULL) isc_mem_put(cm->mctx, grbn->rdatalen, grbn->nrdatas * sizeof(lwres_uint16_t)); if (grbn->sigs != NULL) isc_mem_put(cm->mctx, grbn->sigs, grbn->nsigs * sizeof(unsigned char *)); if (grbn->siglen != NULL) isc_mem_put(cm->mctx, grbn->siglen, grbn->nsigs * sizeof(lwres_uint16_t)); out2: if (client->lookup != NULL) dns_lookup_destroy(&client->lookup); if (lwb.base != NULL) lwres_context_freemem(cm->lwctx, lwb.base, lwb.length); isc_event_free(&event); ns_lwdclient_log(50, "error constructing getrrsetbyname response"); ns_lwdclient_errorpktsend(client, LWRES_R_FAILURE); } static void start_lookup(ns_lwdclient_t *client) { isc_result_t result; ns_lwdclientmgr_t *cm; dns_fixedname_t absname; cm = client->clientmgr; INSIST(client->lookup == NULL); dns_fixedname_init(&absname); /* * Perform search across all search domains until success * is returned. Return in case of failure. */ while (ns_lwsearchctx_current(&client->searchctx, dns_fixedname_name(&absname)) != ISC_R_SUCCESS) { if (ns_lwsearchctx_next(&client->searchctx) != ISC_R_SUCCESS) { ns_lwdclient_errorpktsend(client, LWRES_R_FAILURE); return; } } result = dns_lookup_create(cm->mctx, dns_fixedname_name(&absname), client->rdtype, cm->view, client->options, cm->task, lookup_done, client, &client->lookup); if (result != ISC_R_SUCCESS) { ns_lwdclient_errorpktsend(client, LWRES_R_FAILURE); return; } } static void init_grbn(ns_lwdclient_t *client) { client->grbn.rdclass = 0; client->grbn.rdtype = 0; client->grbn.ttl = 0; client->grbn.nrdatas = 0; client->grbn.realname = NULL; client->grbn.realnamelen = 0; client->grbn.rdatas = 0; client->grbn.rdatalen = 0; client->grbn.base = NULL; client->grbn.baselen = 0; isc_buffer_init(&client->recv_buffer, client->buffer, LWRES_RECVLENGTH); } void ns_lwdclient_processgrbn(ns_lwdclient_t *client, lwres_buffer_t *b) { lwres_grbnrequest_t *req; isc_result_t result; ns_lwdclientmgr_t *cm; isc_buffer_t namebuf; REQUIRE(NS_LWDCLIENT_ISRECVDONE(client)); INSIST(client->byaddr == NULL); cm = client->clientmgr; req = NULL; result = lwres_grbnrequest_parse(cm->lwctx, b, &client->pkt, &req); if (result != LWRES_R_SUCCESS) goto out; if (req->name == NULL) goto out; client->options = 0; if (req->rdclass != cm->view->rdclass) goto out; if (req->rdclass == dns_rdataclass_any || req->rdtype == dns_rdatatype_any) goto out; client->rdtype = req->rdtype; isc_buffer_init(&namebuf, req->name, req->namelen); isc_buffer_add(&namebuf, req->namelen); dns_fixedname_init(&client->query_name); result = dns_name_fromtext(dns_fixedname_name(&client->query_name), &namebuf, NULL, 0, NULL); if (result != ISC_R_SUCCESS) goto out; ns_lwsearchctx_init(&client->searchctx, cm->listener->manager->search, dns_fixedname_name(&client->query_name), cm->listener->manager->ndots); ns_lwsearchctx_first(&client->searchctx); ns_lwdclient_log(50, "client %p looking for type %d", client, client->rdtype); /* * We no longer need to keep this around. */ lwres_grbnrequest_free(cm->lwctx, &req); /* * Initialize the real name and alias arrays in the reply we're * going to build up. */ init_grbn(client); /* * Start the find. */ start_lookup(client); return; /* * We're screwed. Return an error packet to our caller. */ out: if (req != NULL) lwres_grbnrequest_free(cm->lwctx, &req); ns_lwdclient_errorpktsend(client, LWRES_R_FAILURE); } bind9-9.11.3+dfsg/bin/named/lwdnoop.c000066400000000000000000000035361325250447100172250ustar00rootroot00000000000000/* * Copyright (C) 2000, 2001, 2004, 2005, 2007, 2008, 2016 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* $Id: lwdnoop.c,v 1.13 2008/01/22 23:28:04 tbox Exp $ */ /*! \file */ #include #include #include #include #include void ns_lwdclient_processnoop(ns_lwdclient_t *client, lwres_buffer_t *b) { lwres_nooprequest_t *req; lwres_noopresponse_t resp; isc_result_t result; lwres_result_t lwres; isc_region_t r; lwres_buffer_t lwb; REQUIRE(NS_LWDCLIENT_ISRECVDONE(client)); INSIST(client->byaddr == NULL); req = NULL; result = lwres_nooprequest_parse(client->clientmgr->lwctx, b, &client->pkt, &req); if (result != LWRES_R_SUCCESS) goto send_error; client->pkt.recvlength = LWRES_RECVLENGTH; client->pkt.authtype = 0; /* XXXMLG */ client->pkt.authlength = 0; client->pkt.result = LWRES_R_SUCCESS; resp.datalength = req->datalength; resp.data = req->data; lwres = lwres_noopresponse_render(client->clientmgr->lwctx, &resp, &client->pkt, &lwb); if (lwres != LWRES_R_SUCCESS) goto cleanup_req; r.base = lwb.base; r.length = lwb.used; client->sendbuf = r.base; client->sendlength = r.length; result = ns_lwdclient_sendreply(client, &r); if (result != ISC_R_SUCCESS) goto cleanup_lwb; /* * We can now destroy request. */ lwres_nooprequest_free(client->clientmgr->lwctx, &req); NS_LWDCLIENT_SETSEND(client); return; cleanup_lwb: lwres_context_freemem(client->clientmgr->lwctx, lwb.base, lwb.length); cleanup_req: lwres_nooprequest_free(client->clientmgr->lwctx, &req); send_error: ns_lwdclient_errorpktsend(client, LWRES_R_FAILURE); } bind9-9.11.3+dfsg/bin/named/lwresd.8000066400000000000000000000151151325250447100167640ustar00rootroot00000000000000.\" Copyright (C) 2000, 2001, 2004, 2005, 2007-2009, 2014-2017 Internet Systems Consortium, Inc. ("ISC") .\" .\" This Source Code Form is subject to the terms of the Mozilla Public .\" License, v. 2.0. If a copy of the MPL was not distributed with this .\" file, You can obtain one at http://mozilla.org/MPL/2.0/. .\" .hy 0 .ad l '\" t .\" Title: lwresd .\" Author: .\" Generator: DocBook XSL Stylesheets v1.78.1 .\" Date: 2009-01-20 .\" Manual: BIND9 .\" Source: ISC .\" Language: English .\" .TH "LWRESD" "8" "2009\-01\-20" "ISC" "BIND9" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" lwresd \- lightweight resolver daemon .SH "SYNOPSIS" .HP \w'\fBlwresd\fR\ 'u \fBlwresd\fR [\fB\-c\ \fR\fB\fIconfig\-file\fR\fR] [\fB\-C\ \fR\fB\fIconfig\-file\fR\fR] [\fB\-d\ \fR\fB\fIdebug\-level\fR\fR] [\fB\-f\fR] [\fB\-g\fR] [\fB\-i\ \fR\fB\fIpid\-file\fR\fR] [\fB\-m\ \fR\fB\fIflag\fR\fR] [\fB\-n\ \fR\fB\fI#cpus\fR\fR] [\fB\-P\ \fR\fB\fIport\fR\fR] [\fB\-p\ \fR\fB\fIport\fR\fR] [\fB\-s\fR] [\fB\-t\ \fR\fB\fIdirectory\fR\fR] [\fB\-u\ \fR\fB\fIuser\fR\fR] [\fB\-v\fR] [[\fB\-4\fR] | [\fB\-6\fR]] .SH "DESCRIPTION" .PP \fBlwresd\fR is the daemon providing name lookup services to clients that use the BIND 9 lightweight resolver library\&. It is essentially a stripped\-down, caching\-only name server that answers queries using the BIND 9 lightweight resolver protocol rather than the DNS protocol\&. .PP \fBlwresd\fR listens for resolver queries on a UDP port on the IPv4 loopback interface, 127\&.0\&.0\&.1\&. This means that \fBlwresd\fR can only be used by processes running on the local machine\&. By default, UDP port number 921 is used for lightweight resolver requests and responses\&. .PP Incoming lightweight resolver requests are decoded by the server which then resolves them using the DNS protocol\&. When the DNS lookup completes, \fBlwresd\fR encodes the answers in the lightweight resolver format and returns them to the client that made the request\&. .PP If /etc/resolv\&.conf contains any \fBnameserver\fR entries, \fBlwresd\fR sends recursive DNS queries to those servers\&. This is similar to the use of forwarders in a caching name server\&. If no \fBnameserver\fR entries are present, or if forwarding fails, \fBlwresd\fR resolves the queries autonomously starting at the root name servers, using a built\-in list of root server hints\&. .SH "OPTIONS" .PP \-4 .RS 4 Use IPv4 only even if the host machine is capable of IPv6\&. \fB\-4\fR and \fB\-6\fR are mutually exclusive\&. .RE .PP \-6 .RS 4 Use IPv6 only even if the host machine is capable of IPv4\&. \fB\-4\fR and \fB\-6\fR are mutually exclusive\&. .RE .PP \-c \fIconfig\-file\fR .RS 4 Use \fIconfig\-file\fR as the configuration file instead of the default, /etc/lwresd\&.conf\&. \fB\-c\fR can not be used with \fB\-C\fR\&. .RE .PP \-C \fIconfig\-file\fR .RS 4 Use \fIconfig\-file\fR as the configuration file instead of the default, /etc/resolv\&.conf\&. \fB\-C\fR can not be used with \fB\-c\fR\&. .RE .PP \-d \fIdebug\-level\fR .RS 4 Set the daemon\*(Aqs debug level to \fIdebug\-level\fR\&. Debugging traces from \fBlwresd\fR become more verbose as the debug level increases\&. .RE .PP \-f .RS 4 Run the server in the foreground (i\&.e\&. do not daemonize)\&. .RE .PP \-g .RS 4 Run the server in the foreground and force all logging to stderr\&. .RE .PP \-i \fIpid\-file\fR .RS 4 Use \fIpid\-file\fR as the PID file instead of the default, /var/run/lwresd/lwresd\&.pid\&. .RE .PP \-m \fIflag\fR .RS 4 Turn on memory usage debugging flags\&. Possible flags are \fIusage\fR, \fItrace\fR, \fIrecord\fR, \fIsize\fR, and \fImctx\fR\&. These correspond to the ISC_MEM_DEBUGXXXX flags described in \&. .RE .PP \-n \fI#cpus\fR .RS 4 Create \fI#cpus\fR worker threads to take advantage of multiple CPUs\&. If not specified, \fBlwresd\fR will try to determine the number of CPUs present and create one thread per CPU\&. If it is unable to determine the number of CPUs, a single worker thread will be created\&. .RE .PP \-P \fIport\fR .RS 4 Listen for lightweight resolver queries on port \fIport\fR\&. If not specified, the default is port 921\&. .RE .PP \-p \fIport\fR .RS 4 Send DNS lookups to port \fIport\fR\&. If not specified, the default is port 53\&. This provides a way of testing the lightweight resolver daemon with a name server that listens for queries on a non\-standard port number\&. .RE .PP \-s .RS 4 Write memory usage statistics to stdout on exit\&. .if n \{\ .sp .\} .RS 4 .it 1 an-trap .nr an-no-space-flag 1 .nr an-break-flag 1 .br .ps +1 \fBNote\fR .ps -1 .br This option is mainly of interest to BIND 9 developers and may be removed or changed in a future release\&. .sp .5v .RE .RE .PP \-t \fIdirectory\fR .RS 4 Chroot to \fIdirectory\fR after processing the command line arguments, but before reading the configuration file\&. .if n \{\ .sp .\} .RS 4 .it 1 an-trap .nr an-no-space-flag 1 .nr an-break-flag 1 .br .ps +1 \fBWarning\fR .ps -1 .br This option should be used in conjunction with the \fB\-u\fR option, as chrooting a process running as root doesn\*(Aqt enhance security on most systems; the way \fBchroot(2)\fR is defined allows a process with root privileges to escape a chroot jail\&. .sp .5v .RE .RE .PP \-u \fIuser\fR .RS 4 Setuid to \fIuser\fR after completing privileged operations, such as creating sockets that listen on privileged ports\&. .RE .PP \-v .RS 4 Report the version number and exit\&. .RE .SH "FILES" .PP /etc/resolv\&.conf .RS 4 The default configuration file\&. .RE .PP /var/run/lwresd\&.pid .RS 4 The default process\-id file\&. .RE .SH "SEE ALSO" .PP \fBnamed\fR(8), \fBlwres\fR(3), \fBresolver\fR(5)\&. .SH "AUTHOR" .PP \fBInternet Systems Consortium, Inc\&.\fR .SH "COPYRIGHT" .br Copyright \(co 2000, 2001, 2004, 2005, 2007-2009, 2014-2017 Internet Systems Consortium, Inc. ("ISC") .br bind9-9.11.3+dfsg/bin/named/lwresd.c000066400000000000000000000533251325250447100170440ustar00rootroot00000000000000/* * Copyright (C) 2000-2009, 2012-2016 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* $Id: lwresd.c,v 1.60 2009/09/02 23:48:01 tbox Exp $ */ /*! \file * \brief * Main program for the Lightweight Resolver Daemon. * * To paraphrase the old saying about X11, "It's not a lightweight deamon * for resolvers, it's a deamon for lightweight resolvers". */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define LWRESD_MAGIC ISC_MAGIC('L', 'W', 'R', 'D') #define VALID_LWRESD(l) ISC_MAGIC_VALID(l, LWRESD_MAGIC) #define LWRESLISTENER_MAGIC ISC_MAGIC('L', 'W', 'R', 'L') #define VALID_LWRESLISTENER(l) ISC_MAGIC_VALID(l, LWRESLISTENER_MAGIC) #define LWRESD_NCLIENTS_MAX 32768 /*%< max clients per task */ typedef ISC_LIST(ns_lwreslistener_t) ns_lwreslistenerlist_t; static ns_lwreslistenerlist_t listeners; static isc_mutex_t listeners_lock; static isc_once_t once = ISC_ONCE_INIT; static void initialize_mutex(void) { RUNTIME_CHECK(isc_mutex_init(&listeners_lock) == ISC_R_SUCCESS); } /*% * Wrappers around our memory management stuff, for the lwres functions. */ void * ns__lwresd_memalloc(void *arg, size_t size) { return (isc_mem_get(arg, size)); } void ns__lwresd_memfree(void *arg, void *mem, size_t size) { isc_mem_put(arg, mem, size); } #define CHECK(op) \ do { result = (op); \ if (result != ISC_R_SUCCESS) goto cleanup; \ } while (0) static isc_result_t buffer_putstr(isc_buffer_t *b, const char *s) { unsigned int len = strlen(s); if (isc_buffer_availablelength(b) <= len) return (ISC_R_NOSPACE); isc_buffer_putmem(b, (const unsigned char *)s, len); return (ISC_R_SUCCESS); } /* * Convert a resolv.conf file into a config structure. */ isc_result_t ns_lwresd_parseeresolvconf(isc_mem_t *mctx, cfg_parser_t *pctx, cfg_obj_t **configp) { char text[4096]; char str[16]; isc_buffer_t b; lwres_context_t *lwctx = NULL; lwres_conf_t *lwc = NULL; isc_sockaddr_t sa; isc_netaddr_t na; int i; isc_result_t result; lwres_result_t lwresult; lwctx = NULL; lwresult = lwres_context_create(&lwctx, mctx, ns__lwresd_memalloc, ns__lwresd_memfree, LWRES_CONTEXT_SERVERMODE); if (lwresult != LWRES_R_SUCCESS) { result = ISC_R_NOMEMORY; goto cleanup; } lwresult = lwres_conf_parse(lwctx, lwresd_g_resolvconffile); if (lwresult != LWRES_R_SUCCESS) { result = DNS_R_SYNTAX; goto cleanup; } lwc = lwres_conf_get(lwctx); INSIST(lwc != NULL); isc_buffer_init(&b, text, sizeof(text)); CHECK(buffer_putstr(&b, "options {\n")); /* * Build the list of forwarders. */ if (lwc->nsnext > 0) { CHECK(buffer_putstr(&b, "\tforwarders {\n")); for (i = 0; i < lwc->nsnext; i++) { CHECK(lwaddr_sockaddr_fromlwresaddr( &sa, &lwc->nameservers[i], ns_g_port)); isc_netaddr_fromsockaddr(&na, &sa); CHECK(buffer_putstr(&b, "\t\t")); CHECK(isc_netaddr_totext(&na, &b)); CHECK(buffer_putstr(&b, ";\n")); } CHECK(buffer_putstr(&b, "\t};\n")); } /* * Build the sortlist */ if (lwc->sortlistnxt > 0) { CHECK(buffer_putstr(&b, "\tsortlist {\n")); CHECK(buffer_putstr(&b, "\t\t{\n")); CHECK(buffer_putstr(&b, "\t\t\tany;\n")); CHECK(buffer_putstr(&b, "\t\t\t{\n")); for (i = 0; i < lwc->sortlistnxt; i++) { lwres_addr_t *lwaddr = &lwc->sortlist[i].addr; lwres_addr_t *lwmask = &lwc->sortlist[i].mask; unsigned int mask; CHECK(lwaddr_sockaddr_fromlwresaddr(&sa, lwmask, 0)); isc_netaddr_fromsockaddr(&na, &sa); result = isc_netaddr_masktoprefixlen(&na, &mask); if (result != ISC_R_SUCCESS) { char addrtext[ISC_NETADDR_FORMATSIZE]; isc_netaddr_format(&na, addrtext, sizeof(addrtext)); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_LWRESD, ISC_LOG_ERROR, "processing sortlist: '%s' is " "not a valid netmask", addrtext); goto cleanup; } CHECK(lwaddr_sockaddr_fromlwresaddr(&sa, lwaddr, 0)); isc_netaddr_fromsockaddr(&na, &sa); CHECK(buffer_putstr(&b, "\t\t\t\t")); CHECK(isc_netaddr_totext(&na, &b)); snprintf(str, sizeof(str), "%u", mask); CHECK(buffer_putstr(&b, "/")); CHECK(buffer_putstr(&b, str)); CHECK(buffer_putstr(&b, ";\n")); } CHECK(buffer_putstr(&b, "\t\t\t};\n")); CHECK(buffer_putstr(&b, "\t\t};\n")); CHECK(buffer_putstr(&b, "\t};\n")); } CHECK(buffer_putstr(&b, "};\n\n")); CHECK(buffer_putstr(&b, "lwres {\n")); /* * Build the search path */ if (lwc->searchnxt > 0) { if (lwc->searchnxt > 0) { CHECK(buffer_putstr(&b, "\tsearch {\n")); for (i = 0; i < lwc->searchnxt; i++) { CHECK(buffer_putstr(&b, "\t\t\"")); CHECK(buffer_putstr(&b, lwc->search[i])); CHECK(buffer_putstr(&b, "\";\n")); } CHECK(buffer_putstr(&b, "\t};\n")); } } /* * Build the ndots line */ if (lwc->ndots != 1) { CHECK(buffer_putstr(&b, "\tndots ")); snprintf(str, sizeof(str), "%u", lwc->ndots); CHECK(buffer_putstr(&b, str)); CHECK(buffer_putstr(&b, ";\n")); } /* * Build the listen-on line */ if (lwc->lwnext > 0) { CHECK(buffer_putstr(&b, "\tlisten-on {\n")); for (i = 0; i < lwc->lwnext; i++) { CHECK(lwaddr_sockaddr_fromlwresaddr(&sa, &lwc->lwservers[i], 0)); isc_netaddr_fromsockaddr(&na, &sa); CHECK(buffer_putstr(&b, "\t\t")); CHECK(isc_netaddr_totext(&na, &b)); CHECK(buffer_putstr(&b, ";\n")); } CHECK(buffer_putstr(&b, "\t};\n")); } CHECK(buffer_putstr(&b, "};\n")); #if 0 printf("%.*s\n", (int)isc_buffer_usedlength(&b), (char *)isc_buffer_base(&b)); #endif lwres_conf_clear(lwctx); lwres_context_destroy(&lwctx); return (cfg_parse_buffer(pctx, &b, &cfg_type_namedconf, configp)); cleanup: if (lwctx != NULL) { lwres_conf_clear(lwctx); lwres_context_destroy(&lwctx); } return (result); } /* * Handle lwresd manager objects */ isc_result_t ns_lwdmanager_create(isc_mem_t *mctx, const cfg_obj_t *lwres, ns_lwresd_t **lwresdp) { ns_lwresd_t *lwresd; const char *vname; dns_rdataclass_t vclass; const cfg_obj_t *obj, *viewobj, *searchobj; const cfg_listelt_t *element; isc_result_t result; INSIST(lwresdp != NULL && *lwresdp == NULL); lwresd = isc_mem_get(mctx, sizeof(ns_lwresd_t)); if (lwresd == NULL) return (ISC_R_NOMEMORY); lwresd->mctx = NULL; isc_mem_attach(mctx, &lwresd->mctx); lwresd->view = NULL; lwresd->search = NULL; lwresd->refs = 1; obj = NULL; (void)cfg_map_get(lwres, "ndots", &obj); if (obj != NULL) lwresd->ndots = cfg_obj_asuint32(obj); else lwresd->ndots = 1; RUNTIME_CHECK(isc_mutex_init(&lwresd->lock) == ISC_R_SUCCESS); lwresd->shutting_down = ISC_FALSE; viewobj = NULL; (void)cfg_map_get(lwres, "view", &viewobj); if (viewobj != NULL) { vname = cfg_obj_asstring(cfg_tuple_get(viewobj, "name")); obj = cfg_tuple_get(viewobj, "class"); result = ns_config_getclass(obj, dns_rdataclass_in, &vclass); if (result != ISC_R_SUCCESS) goto fail; } else { vname = "_default"; vclass = dns_rdataclass_in; } result = dns_viewlist_find(&ns_g_server->viewlist, vname, vclass, &lwresd->view); if (result != ISC_R_SUCCESS) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_LWRESD, ISC_LOG_WARNING, "couldn't find view %s", vname); goto fail; } searchobj = NULL; (void)cfg_map_get(lwres, "search", &searchobj); if (searchobj != NULL) { lwresd->search = NULL; result = ns_lwsearchlist_create(lwresd->mctx, &lwresd->search); if (result != ISC_R_SUCCESS) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_LWRESD, ISC_LOG_WARNING, "couldn't create searchlist"); goto fail; } for (element = cfg_list_first(searchobj); element != NULL; element = cfg_list_next(element)) { const cfg_obj_t *search; const char *searchstr; isc_buffer_t namebuf; dns_fixedname_t fname; dns_name_t *name; search = cfg_listelt_value(element); searchstr = cfg_obj_asstring(search); dns_fixedname_init(&fname); name = dns_fixedname_name(&fname); isc_buffer_constinit(&namebuf, searchstr, strlen(searchstr)); isc_buffer_add(&namebuf, strlen(searchstr)); result = dns_name_fromtext(name, &namebuf, dns_rootname, 0, NULL); if (result != ISC_R_SUCCESS) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_LWRESD, ISC_LOG_WARNING, "invalid name %s in searchlist", searchstr); continue; } result = ns_lwsearchlist_append(lwresd->search, name); if (result != ISC_R_SUCCESS) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_LWRESD, ISC_LOG_WARNING, "couldn't update searchlist"); goto fail; } } } obj = NULL; (void)cfg_map_get(lwres, "lwres-tasks", &obj); if (obj != NULL) lwresd->ntasks = cfg_obj_asuint32(obj); else lwresd->ntasks = ns_g_cpus; if (lwresd->ntasks == 0) lwresd->ntasks = 1; obj = NULL; (void)cfg_map_get(lwres, "lwres-clients", &obj); if (obj != NULL) { lwresd->nclients = cfg_obj_asuint32(obj); if (lwresd->nclients > LWRESD_NCLIENTS_MAX) lwresd->nclients = LWRESD_NCLIENTS_MAX; } else if (ns_g_lwresdonly) lwresd->nclients = 1024; else lwresd->nclients = 256; lwresd->magic = LWRESD_MAGIC; *lwresdp = lwresd; return (ISC_R_SUCCESS); fail: if (lwresd->view != NULL) dns_view_detach(&lwresd->view); if (lwresd->search != NULL) ns_lwsearchlist_detach(&lwresd->search); if (lwresd->mctx != NULL) isc_mem_detach(&lwresd->mctx); isc_mem_put(mctx, lwresd, sizeof(ns_lwresd_t)); return (result); } void ns_lwdmanager_attach(ns_lwresd_t *source, ns_lwresd_t **targetp) { INSIST(VALID_LWRESD(source)); INSIST(targetp != NULL && *targetp == NULL); LOCK(&source->lock); source->refs++; UNLOCK(&source->lock); *targetp = source; } void ns_lwdmanager_detach(ns_lwresd_t **lwresdp) { ns_lwresd_t *lwresd; isc_mem_t *mctx; isc_boolean_t done = ISC_FALSE; INSIST(lwresdp != NULL && *lwresdp != NULL); INSIST(VALID_LWRESD(*lwresdp)); lwresd = *lwresdp; *lwresdp = NULL; LOCK(&lwresd->lock); INSIST(lwresd->refs > 0); lwresd->refs--; if (lwresd->refs == 0) done = ISC_TRUE; UNLOCK(&lwresd->lock); if (!done) return; dns_view_detach(&lwresd->view); if (lwresd->search != NULL) ns_lwsearchlist_detach(&lwresd->search); mctx = lwresd->mctx; lwresd->magic = 0; isc_mem_put(mctx, lwresd, sizeof(*lwresd)); isc_mem_detach(&mctx); } /* * Handle listener objects */ void ns_lwreslistener_attach(ns_lwreslistener_t *source, ns_lwreslistener_t **targetp) { INSIST(VALID_LWRESLISTENER(source)); INSIST(targetp != NULL && *targetp == NULL); LOCK(&source->lock); source->refs++; UNLOCK(&source->lock); *targetp = source; } void ns_lwreslistener_detach(ns_lwreslistener_t **listenerp) { ns_lwreslistener_t *listener; isc_mem_t *mctx; isc_boolean_t done = ISC_FALSE; INSIST(listenerp != NULL && *listenerp != NULL); INSIST(VALID_LWRESLISTENER(*listenerp)); listener = *listenerp; LOCK(&listener->lock); INSIST(listener->refs > 0); listener->refs--; if (listener->refs == 0) done = ISC_TRUE; UNLOCK(&listener->lock); if (!done) return; if (listener->manager != NULL) ns_lwdmanager_detach(&listener->manager); if (listener->sock != NULL) isc_socket_detach(&listener->sock); listener->magic = 0; mctx = listener->mctx; isc_mem_put(mctx, listener, sizeof(*listener)); isc_mem_detach(&mctx); listenerp = NULL; } static isc_result_t listener_create(isc_mem_t *mctx, ns_lwresd_t *lwresd, ns_lwreslistener_t **listenerp) { ns_lwreslistener_t *listener; isc_result_t result; REQUIRE(listenerp != NULL && *listenerp == NULL); listener = isc_mem_get(mctx, sizeof(ns_lwreslistener_t)); if (listener == NULL) return (ISC_R_NOMEMORY); result = isc_mutex_init(&listener->lock); if (result != ISC_R_SUCCESS) { isc_mem_put(mctx, listener, sizeof(ns_lwreslistener_t)); return (result); } listener->magic = LWRESLISTENER_MAGIC; listener->refs = 1; listener->sock = NULL; listener->manager = NULL; ns_lwdmanager_attach(lwresd, &listener->manager); listener->mctx = NULL; isc_mem_attach(mctx, &listener->mctx); ISC_LINK_INIT(listener, link); ISC_LIST_INIT(listener->cmgrs); *listenerp = listener; return (ISC_R_SUCCESS); } static isc_result_t listener_bind(ns_lwreslistener_t *listener, isc_sockaddr_t *address) { isc_socket_t *sock = NULL; isc_result_t result = ISC_R_SUCCESS; int pf; pf = isc_sockaddr_pf(address); if ((pf == AF_INET && isc_net_probeipv4() != ISC_R_SUCCESS) || (pf == AF_INET6 && isc_net_probeipv6() != ISC_R_SUCCESS)) return (ISC_R_FAMILYNOSUPPORT); listener->address = *address; if (isc_sockaddr_getport(&listener->address) == 0) { in_port_t port; port = lwresd_g_listenport; if (port == 0) port = LWRES_UDP_PORT; isc_sockaddr_setport(&listener->address, port); } sock = NULL; result = isc_socket_create(ns_g_socketmgr, pf, isc_sockettype_udp, &sock); if (result != ISC_R_SUCCESS) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_LWRESD, ISC_LOG_WARNING, "failed to create lwres socket: %s", isc_result_totext(result)); return (result); } result = isc_socket_bind(sock, &listener->address, ISC_SOCKET_REUSEADDRESS); if (result != ISC_R_SUCCESS) { char socktext[ISC_SOCKADDR_FORMATSIZE]; isc_sockaddr_format(&listener->address, socktext, sizeof(socktext)); isc_socket_detach(&sock); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_LWRESD, ISC_LOG_WARNING, "failed to add lwres socket: %s: %s", socktext, isc_result_totext(result)); return (result); } listener->sock = sock; return (ISC_R_SUCCESS); } static void listener_copysock(ns_lwreslistener_t *oldlistener, ns_lwreslistener_t *newlistener) { newlistener->address = oldlistener->address; isc_socket_attach(oldlistener->sock, &newlistener->sock); } static isc_result_t listener_startclients(ns_lwreslistener_t *listener) { ns_lwdclientmgr_t *cm, *next; unsigned int i; isc_result_t result = ISC_R_SUCCESS; isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_LWRESD, ISC_LOG_DEBUG(6), "listener_startclients: creating %d " "managers with %d clients each", listener->manager->ntasks, listener->manager->nclients); /* * Create the client managers. */ for (i = 0; i < listener->manager->ntasks; i++) { result = ns_lwdclientmgr_create(listener, listener->manager->nclients, ns_g_taskmgr); if (result != ISC_R_SUCCESS) break; } /* * If the list is empty return now with the previous * ns_lwdclientmgr_create() result. */ if (ISC_LIST_EMPTY(listener->cmgrs)) return (result); /* * Walk the list of clients and start each one up. */ LOCK(&listener->lock); cm = ISC_LIST_HEAD(listener->cmgrs); while (cm != NULL) { next = ISC_LIST_NEXT(cm, link); result = ns_lwdclient_startrecv(cm); if (result != ISC_R_SUCCESS) isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_LWRESD, ISC_LOG_ERROR, "could not start lwres " "client handler: %s", isc_result_totext(result)); cm = next; } UNLOCK(&listener->lock); return (ISC_R_SUCCESS); } static void listener_shutdown(ns_lwreslistener_t *listener) { ns_lwdclientmgr_t *cm; cm = ISC_LIST_HEAD(listener->cmgrs); while (cm != NULL) { isc_task_shutdown(cm->task); cm = ISC_LIST_NEXT(cm, link); } } static isc_result_t find_listener(isc_sockaddr_t *address, ns_lwreslistener_t **listenerp) { ns_lwreslistener_t *listener; INSIST(listenerp != NULL && *listenerp == NULL); for (listener = ISC_LIST_HEAD(listeners); listener != NULL; listener = ISC_LIST_NEXT(listener, link)) { if (!isc_sockaddr_equal(address, &listener->address)) continue; *listenerp = listener; return (ISC_R_SUCCESS); } return (ISC_R_NOTFOUND); } void ns_lwreslistener_unlinkcm(ns_lwreslistener_t *listener, ns_lwdclientmgr_t *cm) { REQUIRE(VALID_LWRESLISTENER(listener)); LOCK(&listener->lock); ISC_LIST_UNLINK(listener->cmgrs, cm, link); UNLOCK(&listener->lock); } void ns_lwreslistener_linkcm(ns_lwreslistener_t *listener, ns_lwdclientmgr_t *cm) { REQUIRE(VALID_LWRESLISTENER(listener)); /* * This does no locking, since it's called early enough that locking * isn't needed. */ ISC_LIST_APPEND(listener->cmgrs, cm, link); } static isc_result_t configure_listener(isc_sockaddr_t *address, ns_lwresd_t *lwresd, isc_mem_t *mctx, ns_lwreslistenerlist_t *newlisteners) { ns_lwreslistener_t *listener, *oldlistener = NULL; char socktext[ISC_SOCKADDR_FORMATSIZE]; isc_result_t result; (void)find_listener(address, &oldlistener); listener = NULL; result = listener_create(mctx, lwresd, &listener); if (result != ISC_R_SUCCESS) { isc_sockaddr_format(address, socktext, sizeof(socktext)); isc_log_write(ns_g_lctx, ISC_LOGCATEGORY_GENERAL, NS_LOGMODULE_LWRESD, ISC_LOG_WARNING, "lwres failed to configure %s: %s", socktext, isc_result_totext(result)); return (result); } /* * If there's already a listener, don't rebind the socket. */ if (oldlistener == NULL) { result = listener_bind(listener, address); if (result != ISC_R_SUCCESS) { ns_lwreslistener_detach(&listener); return (ISC_R_SUCCESS); } } else listener_copysock(oldlistener, listener); result = listener_startclients(listener); if (result != ISC_R_SUCCESS) { isc_sockaddr_format(address, socktext, sizeof(socktext)); isc_log_write(ns_g_lctx, ISC_LOGCATEGORY_GENERAL, NS_LOGMODULE_LWRESD, ISC_LOG_WARNING, "lwres: failed to start %s: %s", socktext, isc_result_totext(result)); ns_lwreslistener_detach(&listener); return (ISC_R_SUCCESS); } if (oldlistener != NULL) { /* * Remove the old listener from the old list and shut it down. */ ISC_LIST_UNLINK(listeners, oldlistener, link); listener_shutdown(oldlistener); ns_lwreslistener_detach(&oldlistener); } else { isc_sockaddr_format(address, socktext, sizeof(socktext)); isc_log_write(ns_g_lctx, ISC_LOGCATEGORY_GENERAL, NS_LOGMODULE_LWRESD, ISC_LOG_NOTICE, "lwres listening on %s", socktext); } ISC_LIST_APPEND(*newlisteners, listener, link); return (result); } isc_result_t ns_lwresd_configure(isc_mem_t *mctx, const cfg_obj_t *config) { const cfg_obj_t *lwreslist = NULL; const cfg_obj_t *lwres = NULL; const cfg_obj_t *listenerslist = NULL; const cfg_listelt_t *element = NULL; ns_lwreslistener_t *listener; ns_lwreslistenerlist_t newlisteners; isc_result_t result; char socktext[ISC_SOCKADDR_FORMATSIZE]; isc_sockaddr_t *addrs = NULL; ns_lwresd_t *lwresd = NULL; isc_uint32_t count = 0; REQUIRE(mctx != NULL); REQUIRE(config != NULL); RUNTIME_CHECK(isc_once_do(&once, initialize_mutex) == ISC_R_SUCCESS); ISC_LIST_INIT(newlisteners); result = cfg_map_get(config, "lwres", &lwreslist); if (result != ISC_R_SUCCESS) return (ISC_R_SUCCESS); LOCK(&listeners_lock); /* * Run through the new lwres address list, noting sockets that * are already being listened on and moving them to the new list. * * Identifying duplicates addr/port combinations is left to either * the underlying config code, or to the bind attempt getting an * address-in-use error. */ for (element = cfg_list_first(lwreslist); element != NULL; element = cfg_list_next(element)) { in_port_t port; lwres = cfg_listelt_value(element); CHECK(ns_lwdmanager_create(mctx, lwres, &lwresd)); port = lwresd_g_listenport; if (port == 0) port = LWRES_UDP_PORT; listenerslist = NULL; (void)cfg_map_get(lwres, "listen-on", &listenerslist); if (listenerslist == NULL) { struct in_addr localhost; isc_sockaddr_t address; localhost.s_addr = htonl(INADDR_LOOPBACK); isc_sockaddr_fromin(&address, &localhost, port); CHECK(configure_listener(&address, lwresd, mctx, &newlisteners)); } else { isc_uint32_t i; CHECK(ns_config_getiplist(config, listenerslist, port, mctx, &addrs, NULL, &count)); for (i = 0; i < count; i++) CHECK(configure_listener(&addrs[i], lwresd, mctx, &newlisteners)); ns_config_putiplist(mctx, &addrs, NULL, count); } ns_lwdmanager_detach(&lwresd); } /* * Shutdown everything on the listeners list, and remove them from * the list. Then put all of the new listeners on it. */ while (!ISC_LIST_EMPTY(listeners)) { listener = ISC_LIST_HEAD(listeners); ISC_LIST_UNLINK(listeners, listener, link); isc_sockaddr_format(&listener->address, socktext, sizeof(socktext)); listener_shutdown(listener); ns_lwreslistener_detach(&listener); isc_log_write(ns_g_lctx, ISC_LOGCATEGORY_GENERAL, NS_LOGMODULE_LWRESD, ISC_LOG_NOTICE, "lwres no longer listening on %s", socktext); } cleanup: ISC_LIST_APPENDLIST(listeners, newlisteners, link); if (addrs != NULL) ns_config_putiplist(mctx, &addrs, NULL, count); if (lwresd != NULL) ns_lwdmanager_detach(&lwresd); UNLOCK(&listeners_lock); return (result); } void ns_lwresd_shutdown(void) { ns_lwreslistener_t *listener; RUNTIME_CHECK(isc_once_do(&once, initialize_mutex) == ISC_R_SUCCESS); while (!ISC_LIST_EMPTY(listeners)) { listener = ISC_LIST_HEAD(listeners); ISC_LIST_UNLINK(listeners, listener, link); ns_lwreslistener_detach(&listener); } } bind9-9.11.3+dfsg/bin/named/lwresd.docbook000066400000000000000000000306441325250447100202410ustar00rootroot00000000000000 2009-01-20 ISC Internet Systems Consortium, Inc. lwresd 8 BIND9 lwresd lightweight resolver daemon 2000 2001 2004 2005 2007 2008 2009 2014 2015 2016 2017 Internet Systems Consortium, Inc. ("ISC") lwresd DESCRIPTION lwresd is the daemon providing name lookup services to clients that use the BIND 9 lightweight resolver library. It is essentially a stripped-down, caching-only name server that answers queries using the BIND 9 lightweight resolver protocol rather than the DNS protocol. lwresd listens for resolver queries on a UDP port on the IPv4 loopback interface, 127.0.0.1. This means that lwresd can only be used by processes running on the local machine. By default, UDP port number 921 is used for lightweight resolver requests and responses. Incoming lightweight resolver requests are decoded by the server which then resolves them using the DNS protocol. When the DNS lookup completes, lwresd encodes the answers in the lightweight resolver format and returns them to the client that made the request. If /etc/resolv.conf contains any entries, lwresd sends recursive DNS queries to those servers. This is similar to the use of forwarders in a caching name server. If no entries are present, or if forwarding fails, lwresd resolves the queries autonomously starting at the root name servers, using a built-in list of root server hints. OPTIONS -4 Use IPv4 only even if the host machine is capable of IPv6. and are mutually exclusive. -6 Use IPv6 only even if the host machine is capable of IPv4. and are mutually exclusive. -c config-file Use config-file as the configuration file instead of the default, /etc/lwresd.conf. can not be used with . -C config-file Use config-file as the configuration file instead of the default, /etc/resolv.conf. can not be used with . -d debug-level Set the daemon's debug level to debug-level. Debugging traces from lwresd become more verbose as the debug level increases. -f Run the server in the foreground (i.e. do not daemonize). -g Run the server in the foreground and force all logging to stderr. -i pid-file Use pid-file as the PID file instead of the default, /var/run/lwresd/lwresd.pid. -m flag Turn on memory usage debugging flags. Possible flags are usage, trace, record, size, and mctx. These correspond to the ISC_MEM_DEBUGXXXX flags described in <isc/mem.h>. -n #cpus Create #cpus worker threads to take advantage of multiple CPUs. If not specified, lwresd will try to determine the number of CPUs present and create one thread per CPU. If it is unable to determine the number of CPUs, a single worker thread will be created. -P port Listen for lightweight resolver queries on port port. If not specified, the default is port 921. -p port Send DNS lookups to port port. If not specified, the default is port 53. This provides a way of testing the lightweight resolver daemon with a name server that listens for queries on a non-standard port number. -s Write memory usage statistics to stdout on exit. This option is mainly of interest to BIND 9 developers and may be removed or changed in a future release. -t directory Chroot to directory after processing the command line arguments, but before reading the configuration file. This option should be used in conjunction with the option, as chrooting a process running as root doesn't enhance security on most systems; the way chroot(2) is defined allows a process with root privileges to escape a chroot jail. -u user Setuid to user after completing privileged operations, such as creating sockets that listen on privileged ports. -v Report the version number and exit. FILES /etc/resolv.conf The default configuration file. /var/run/lwresd.pid The default process-id file. SEE ALSO named8 , lwres3 , resolver5 . bind9-9.11.3+dfsg/bin/named/lwresd.html000066400000000000000000000260561325250447100175670ustar00rootroot00000000000000 lwresd

Name

lwresd — lightweight resolver daemon

Synopsis

lwresd [-c config-file] [-C config-file] [-d debug-level] [-f] [-g] [-i pid-file] [-m flag] [-n #cpus] [-P port] [-p port] [-s] [-t directory] [-u user] [-v] [ [-4] | [-6] ]

DESCRIPTION

lwresd is the daemon providing name lookup services to clients that use the BIND 9 lightweight resolver library. It is essentially a stripped-down, caching-only name server that answers queries using the BIND 9 lightweight resolver protocol rather than the DNS protocol.

lwresd listens for resolver queries on a UDP port on the IPv4 loopback interface, 127.0.0.1. This means that lwresd can only be used by processes running on the local machine. By default, UDP port number 921 is used for lightweight resolver requests and responses.

Incoming lightweight resolver requests are decoded by the server which then resolves them using the DNS protocol. When the DNS lookup completes, lwresd encodes the answers in the lightweight resolver format and returns them to the client that made the request.

If /etc/resolv.conf contains any nameserver entries, lwresd sends recursive DNS queries to those servers. This is similar to the use of forwarders in a caching name server. If no nameserver entries are present, or if forwarding fails, lwresd resolves the queries autonomously starting at the root name servers, using a built-in list of root server hints.

OPTIONS

-4

Use IPv4 only even if the host machine is capable of IPv6. -4 and -6 are mutually exclusive.

-6

Use IPv6 only even if the host machine is capable of IPv4. -4 and -6 are mutually exclusive.

-c config-file

Use config-file as the configuration file instead of the default, /etc/lwresd.conf. -c can not be used with -C.

-C config-file

Use config-file as the configuration file instead of the default, /etc/resolv.conf. -C can not be used with -c.

-d debug-level

Set the daemon's debug level to debug-level. Debugging traces from lwresd become more verbose as the debug level increases.

-f

Run the server in the foreground (i.e. do not daemonize).

-g

Run the server in the foreground and force all logging to stderr.

-i pid-file

Use pid-file as the PID file instead of the default, /var/run/lwresd/lwresd.pid.

-m flag

Turn on memory usage debugging flags. Possible flags are usage, trace, record, size, and mctx. These correspond to the ISC_MEM_DEBUGXXXX flags described in <isc/mem.h>.

-n #cpus

Create #cpus worker threads to take advantage of multiple CPUs. If not specified, lwresd will try to determine the number of CPUs present and create one thread per CPU. If it is unable to determine the number of CPUs, a single worker thread will be created.

-P port

Listen for lightweight resolver queries on port port. If not specified, the default is port 921.

-p port

Send DNS lookups to port port. If not specified, the default is port 53. This provides a way of testing the lightweight resolver daemon with a name server that listens for queries on a non-standard port number.

-s

Write memory usage statistics to stdout on exit.

Note

This option is mainly of interest to BIND 9 developers and may be removed or changed in a future release.

-t directory

Chroot to directory after processing the command line arguments, but before reading the configuration file.

Warning

This option should be used in conjunction with the -u option, as chrooting a process running as root doesn't enhance security on most systems; the way chroot(2) is defined allows a process with root privileges to escape a chroot jail.

-u user

Setuid to user after completing privileged operations, such as creating sockets that listen on privileged ports.

-v

Report the version number and exit.

FILES

/etc/resolv.conf

The default configuration file.

/var/run/lwresd.pid

The default process-id file.

SEE ALSO

named(8) , lwres(3) , resolver(5) .

bind9-9.11.3+dfsg/bin/named/lwsearch.c000066400000000000000000000110021325250447100173360ustar00rootroot00000000000000/* * Copyright (C) 2000, 2001, 2004, 2005, 2007, 2016 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* $Id: lwsearch.c,v 1.13 2007/06/19 23:46:59 tbox Exp $ */ /*! \file */ #include #include #include #include #include #include #include #include #include #include #include #define LWSEARCHLIST_MAGIC ISC_MAGIC('L', 'W', 'S', 'L') #define VALID_LWSEARCHLIST(l) ISC_MAGIC_VALID(l, LWSEARCHLIST_MAGIC) isc_result_t ns_lwsearchlist_create(isc_mem_t *mctx, ns_lwsearchlist_t **listp) { ns_lwsearchlist_t *list; isc_result_t result; REQUIRE(mctx != NULL); REQUIRE(listp != NULL && *listp == NULL); list = isc_mem_get(mctx, sizeof(ns_lwsearchlist_t)); if (list == NULL) return (ISC_R_NOMEMORY); result = isc_mutex_init(&list->lock); if (result != ISC_R_SUCCESS) { isc_mem_put(mctx, list, sizeof(ns_lwsearchlist_t)); return (result); } list->mctx = NULL; isc_mem_attach(mctx, &list->mctx); list->refs = 1; ISC_LIST_INIT(list->names); list->magic = LWSEARCHLIST_MAGIC; *listp = list; return (ISC_R_SUCCESS); } void ns_lwsearchlist_attach(ns_lwsearchlist_t *source, ns_lwsearchlist_t **target) { REQUIRE(VALID_LWSEARCHLIST(source)); REQUIRE(target != NULL && *target == NULL); LOCK(&source->lock); INSIST(source->refs > 0); source->refs++; INSIST(source->refs != 0); UNLOCK(&source->lock); *target = source; } void ns_lwsearchlist_detach(ns_lwsearchlist_t **listp) { ns_lwsearchlist_t *list; isc_mem_t *mctx; REQUIRE(listp != NULL); list = *listp; REQUIRE(VALID_LWSEARCHLIST(list)); LOCK(&list->lock); INSIST(list->refs > 0); list->refs--; UNLOCK(&list->lock); *listp = NULL; if (list->refs != 0) return; mctx = list->mctx; while (!ISC_LIST_EMPTY(list->names)) { dns_name_t *name = ISC_LIST_HEAD(list->names); ISC_LIST_UNLINK(list->names, name, link); dns_name_free(name, list->mctx); isc_mem_put(list->mctx, name, sizeof(dns_name_t)); } list->magic = 0; isc_mem_put(mctx, list, sizeof(ns_lwsearchlist_t)); isc_mem_detach(&mctx); } isc_result_t ns_lwsearchlist_append(ns_lwsearchlist_t *list, dns_name_t *name) { dns_name_t *newname; isc_result_t result; REQUIRE(VALID_LWSEARCHLIST(list)); REQUIRE(name != NULL); newname = isc_mem_get(list->mctx, sizeof(dns_name_t)); if (newname == NULL) return (ISC_R_NOMEMORY); dns_name_init(newname, NULL); result = dns_name_dup(name, list->mctx, newname); if (result != ISC_R_SUCCESS) { isc_mem_put(list->mctx, newname, sizeof(dns_name_t)); return (result); } ISC_LINK_INIT(newname, link); ISC_LIST_APPEND(list->names, newname, link); return (ISC_R_SUCCESS); } void ns_lwsearchctx_init(ns_lwsearchctx_t *sctx, ns_lwsearchlist_t *list, dns_name_t *name, unsigned int ndots) { INSIST(sctx != NULL); sctx->relname = name; sctx->searchname = NULL; sctx->doneexact = ISC_FALSE; sctx->exactfirst = ISC_FALSE; sctx->ndots = ndots; if (dns_name_isabsolute(name) || list == NULL) { sctx->list = NULL; return; } sctx->list = list; sctx->searchname = ISC_LIST_HEAD(sctx->list->names); if (dns_name_countlabels(name) > ndots) sctx->exactfirst = ISC_TRUE; } void ns_lwsearchctx_first(ns_lwsearchctx_t *sctx) { REQUIRE(sctx != NULL); UNUSED(sctx); } isc_result_t ns_lwsearchctx_next(ns_lwsearchctx_t *sctx) { REQUIRE(sctx != NULL); if (sctx->list == NULL) return (ISC_R_NOMORE); if (sctx->searchname == NULL) { if (sctx->exactfirst || sctx->doneexact) return (ISC_R_NOMORE); sctx->doneexact = ISC_TRUE; } else { if (sctx->exactfirst && !sctx->doneexact) sctx->doneexact = ISC_TRUE; else { sctx->searchname = ISC_LIST_NEXT(sctx->searchname, link); if (sctx->searchname == NULL && sctx->doneexact) return (ISC_R_NOMORE); } } return (ISC_R_SUCCESS); } isc_result_t ns_lwsearchctx_current(ns_lwsearchctx_t *sctx, dns_name_t *absname) { dns_name_t *tname; isc_boolean_t useexact = ISC_FALSE; REQUIRE(sctx != NULL); if (sctx->list == NULL || sctx->searchname == NULL || (sctx->exactfirst && !sctx->doneexact)) useexact = ISC_TRUE; if (useexact) { if (dns_name_isabsolute(sctx->relname)) tname = NULL; else tname = dns_rootname; } else tname = sctx->searchname; return (dns_name_concatenate(sctx->relname, tname, absname, NULL)); } bind9-9.11.3+dfsg/bin/named/main.c000066400000000000000000001133261325250447100164660ustar00rootroot00000000000000/* * Copyright (C) 1999-2017 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /*! \file */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef PKCS11CRYPTO #include #endif #include #ifdef HAVE_GPERFTOOLS_PROFILER #include #endif /* * Defining NS_MAIN provides storage declarations (rather than extern) * for variables in named/globals.h. */ #define NS_MAIN 1 #include #include #include #include /* Explicit, though named/log.h includes it. */ #include #include #include #include #include #include #include #ifdef HAVE_LIBSCF #include #endif #ifdef OPENSSL #include #include #endif #ifdef HAVE_LIBXML2 #include #endif #ifdef HAVE_ZLIB #include #endif /* * Include header files for database drivers here. */ /* #include "xxdb.h" */ #ifdef CONTRIB_DLZ /* * Include contributed DLZ drivers if appropriate. */ #include #endif /* * The maximum number of stack frames to dump on assertion failure. */ #ifndef BACKTRACE_MAXFRAME #define BACKTRACE_MAXFRAME 128 #endif LIBISC_EXTERNAL_DATA extern int isc_dscp_check_value; LIBDNS_EXTERNAL_DATA extern unsigned int dns_zone_mkey_hour; LIBDNS_EXTERNAL_DATA extern unsigned int dns_zone_mkey_day; LIBDNS_EXTERNAL_DATA extern unsigned int dns_zone_mkey_month; static isc_boolean_t want_stats = ISC_FALSE; static char program_name[ISC_DIR_NAMEMAX] = "named"; static char absolute_conffile[ISC_DIR_PATHMAX]; static char saved_command_line[512]; static char version[512]; static unsigned int maxsocks = 0; static int maxudp = 0; void ns_main_earlywarning(const char *format, ...) { va_list args; va_start(args, format); if (ns_g_lctx != NULL) { isc_log_vwrite(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, ISC_LOG_WARNING, format, args); } else { fprintf(stderr, "%s: ", program_name); vfprintf(stderr, format, args); fprintf(stderr, "\n"); fflush(stderr); } va_end(args); } void ns_main_earlyfatal(const char *format, ...) { va_list args; va_start(args, format); if (ns_g_lctx != NULL) { isc_log_vwrite(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, ISC_LOG_CRITICAL, format, args); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, ISC_LOG_CRITICAL, "exiting (due to early fatal error)"); } else { fprintf(stderr, "%s: ", program_name); vfprintf(stderr, format, args); fprintf(stderr, "\n"); fflush(stderr); } va_end(args); exit(1); } ISC_PLATFORM_NORETURN_PRE static void assertion_failed(const char *file, int line, isc_assertiontype_t type, const char *cond) ISC_PLATFORM_NORETURN_POST; static void assertion_failed(const char *file, int line, isc_assertiontype_t type, const char *cond) { void *tracebuf[BACKTRACE_MAXFRAME]; int i, nframes; isc_result_t result; const char *logsuffix = ""; const char *fname; /* * Handle assertion failures. */ if (ns_g_lctx != NULL) { /* * Reset the assertion callback in case it is the log * routines causing the assertion. */ isc_assertion_setcallback(NULL); result = isc_backtrace_gettrace(tracebuf, BACKTRACE_MAXFRAME, &nframes); if (result == ISC_R_SUCCESS && nframes > 0) logsuffix = ", back trace"; isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, ISC_LOG_CRITICAL, "%s:%d: %s(%s) failed%s", file, line, isc_assertion_typetotext(type), cond, logsuffix); if (result == ISC_R_SUCCESS) { for (i = 0; i < nframes; i++) { unsigned long offset; fname = NULL; result = isc_backtrace_getsymbol(tracebuf[i], &fname, &offset); if (result == ISC_R_SUCCESS) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, ISC_LOG_CRITICAL, "#%d %p in %s()+0x%lx", i, tracebuf[i], fname, offset); } else { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, ISC_LOG_CRITICAL, "#%d %p in ??", i, tracebuf[i]); } } } isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, ISC_LOG_CRITICAL, "exiting (due to assertion failure)"); } else { fprintf(stderr, "%s:%d: %s(%s) failed\n", file, line, isc_assertion_typetotext(type), cond); fflush(stderr); } if (ns_g_coreok) abort(); exit(1); } ISC_PLATFORM_NORETURN_PRE static void library_fatal_error(const char *file, int line, const char *format, va_list args) ISC_FORMAT_PRINTF(3, 0) ISC_PLATFORM_NORETURN_POST; static void library_fatal_error(const char *file, int line, const char *format, va_list args) { /* * Handle isc_error_fatal() calls from our libraries. */ if (ns_g_lctx != NULL) { /* * Reset the error callback in case it is the log * routines causing the assertion. */ isc_error_setfatal(NULL); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, ISC_LOG_CRITICAL, "%s:%d: fatal error:", file, line); isc_log_vwrite(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, ISC_LOG_CRITICAL, format, args); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, ISC_LOG_CRITICAL, "exiting (due to fatal error in library)"); } else { fprintf(stderr, "%s:%d: fatal error: ", file, line); vfprintf(stderr, format, args); fprintf(stderr, "\n"); fflush(stderr); } if (ns_g_coreok) abort(); exit(1); } static void library_unexpected_error(const char *file, int line, const char *format, va_list args) ISC_FORMAT_PRINTF(3, 0); static void library_unexpected_error(const char *file, int line, const char *format, va_list args) { /* * Handle isc_error_unexpected() calls from our libraries. */ if (ns_g_lctx != NULL) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, ISC_LOG_ERROR, "%s:%d: unexpected error:", file, line); isc_log_vwrite(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, ISC_LOG_ERROR, format, args); } else { fprintf(stderr, "%s:%d: fatal error: ", file, line); vfprintf(stderr, format, args); fprintf(stderr, "\n"); fflush(stderr); } } static void lwresd_usage(void) { fprintf(stderr, "usage: lwresd [-4|-6] [-c conffile | -C resolvconffile] " "[-d debuglevel] [-f|-g]\n" " [-i pidfile] [-n number_of_cpus] " "[-p port] [-P listen-port]\n" " [-s] [-S sockets] [-t chrootdir] [-u username] " "[-U listeners]\n" " [-m {usage|trace|record|size|mctx}]\n" "usage: lwresd [-v|-V]\n"); } static void usage(void) { if (ns_g_lwresdonly) { lwresd_usage(); return; } fprintf(stderr, "usage: named [-4|-6] [-c conffile] [-d debuglevel] " "[-E engine] [-f|-g]\n" " [-n number_of_cpus] [-p port] [-s] " "[-S sockets] [-t chrootdir]\n" " [-u username] [-U listeners] " "[-m {usage|trace|record|size|mctx}]\n" "usage: named [-v|-V]\n"); } static void save_command_line(int argc, char *argv[]) { int i; char *src; char *dst; char *eob; const char truncated[] = "..."; isc_boolean_t quoted = ISC_FALSE; dst = saved_command_line; eob = saved_command_line + sizeof(saved_command_line); for (i = 1; i < argc && dst < eob; i++) { *dst++ = ' '; src = argv[i]; while (*src != '\0' && dst < eob) { /* * This won't perfectly produce a shell-independent * pastable command line in all circumstances, but * comes close, and for practical purposes will * nearly always be fine. */ if (quoted || isalnum(*src & 0xff) || *src == '-' || *src == '_' || *src == '.' || *src == '/') { *dst++ = *src++; quoted = ISC_FALSE; } else { *dst++ = '\\'; quoted = ISC_TRUE; } } } INSIST(sizeof(saved_command_line) >= sizeof(truncated)); if (dst == eob) strcpy(eob - sizeof(truncated), truncated); else *dst = '\0'; } static int parse_int(char *arg, const char *desc) { char *endp; int tmp; long int ltmp; ltmp = strtol(arg, &endp, 10); tmp = (int) ltmp; if (*endp != '\0') ns_main_earlyfatal("%s '%s' must be numeric", desc, arg); if (tmp < 0 || tmp != ltmp) ns_main_earlyfatal("%s '%s' out of range", desc, arg); return (tmp); } static struct flag_def { const char *name; unsigned int value; } mem_debug_flags[] = { { "none", 0}, { "trace", ISC_MEM_DEBUGTRACE }, { "record", ISC_MEM_DEBUGRECORD }, { "usage", ISC_MEM_DEBUGUSAGE }, { "size", ISC_MEM_DEBUGSIZE }, { "mctx", ISC_MEM_DEBUGCTX }, { NULL, 0 } }; static void set_flags(const char *arg, struct flag_def *defs, unsigned int *ret) { isc_boolean_t clear = ISC_FALSE; for (;;) { const struct flag_def *def; const char *end = strchr(arg, ','); int arglen; if (end == NULL) end = arg + strlen(arg); arglen = (int)(end - arg); for (def = defs; def->name != NULL; def++) { if (arglen == (int)strlen(def->name) && memcmp(arg, def->name, arglen) == 0) { if (def->value == 0) clear = ISC_TRUE; *ret |= def->value; goto found; } } ns_main_earlyfatal("unrecognized flag '%.*s'", arglen, arg); found: if (clear || (*end == '\0')) break; arg = end + 1; } if (clear) *ret = 0; } static void parse_fuzz_arg(void) { if (!strncmp(isc_commandline_argument, "client:", 7)) { ns_g_fuzz_named_addr = isc_commandline_argument + 7; ns_g_fuzz_type = ns_fuzz_client; } else if (!strncmp(isc_commandline_argument, "tcp:", 4)) { ns_g_fuzz_named_addr = isc_commandline_argument + 4; ns_g_fuzz_type = ns_fuzz_tcpclient; } else if (!strncmp(isc_commandline_argument, "resolver:", 9)) { ns_g_fuzz_named_addr = isc_commandline_argument + 9; ns_g_fuzz_type = ns_fuzz_resolver; } else if (!strncmp(isc_commandline_argument, "http:", 5)) { ns_g_fuzz_named_addr = isc_commandline_argument + 5; ns_g_fuzz_type = ns_fuzz_http; } else if (!strncmp(isc_commandline_argument, "rndc:", 5)) { ns_g_fuzz_named_addr = isc_commandline_argument + 5; ns_g_fuzz_type = ns_fuzz_rndc; } else { ns_main_earlyfatal("unknown fuzzing type '%s'", isc_commandline_argument); } } static void parse_command_line(int argc, char *argv[]) { int ch; int port; const char *p; save_command_line(argc, argv); /* * NS_MAIN_ARGS is defined in main.h, so that it can be used * both by named and by ntservice hooks. */ isc_commandline_errprint = ISC_FALSE; while ((ch = isc_commandline_parse(argc, argv, NS_MAIN_ARGS)) != -1) { switch (ch) { case '4': if (ns_g_disable4) ns_main_earlyfatal("cannot specify -4 and -6"); if (isc_net_probeipv4() != ISC_R_SUCCESS) ns_main_earlyfatal("IPv4 not supported by OS"); isc_net_disableipv6(); ns_g_disable6 = ISC_TRUE; break; case '6': if (ns_g_disable6) ns_main_earlyfatal("cannot specify -4 and -6"); if (isc_net_probeipv6() != ISC_R_SUCCESS) ns_main_earlyfatal("IPv6 not supported by OS"); isc_net_disableipv4(); ns_g_disable4 = ISC_TRUE; break; case 'A': parse_fuzz_arg(); break; case 'c': ns_g_conffile = isc_commandline_argument; lwresd_g_conffile = isc_commandline_argument; if (lwresd_g_useresolvconf) ns_main_earlyfatal("cannot specify -c and -C"); ns_g_conffileset = ISC_TRUE; break; case 'C': lwresd_g_resolvconffile = isc_commandline_argument; if (ns_g_conffileset) ns_main_earlyfatal("cannot specify -c and -C"); lwresd_g_useresolvconf = ISC_TRUE; break; case 'd': ns_g_debuglevel = parse_int(isc_commandline_argument, "debug level"); break; case 'D': /* Descriptive comment for 'ps'. */ break; case 'E': ns_g_engine = isc_commandline_argument; break; case 'f': ns_g_foreground = ISC_TRUE; break; case 'g': ns_g_foreground = ISC_TRUE; ns_g_logstderr = ISC_TRUE; break; /* XXXBEW -i should be removed */ case 'i': lwresd_g_defaultpidfile = isc_commandline_argument; break; case 'l': ns_g_lwresdonly = ISC_TRUE; break; case 'L': ns_g_logfile = isc_commandline_argument; break; case 'M': if (strcmp(isc_commandline_argument, "external") == 0) isc_mem_defaultflags = 0; break; case 'm': set_flags(isc_commandline_argument, mem_debug_flags, &isc_mem_debugging); break; case 'N': /* Deprecated. */ case 'n': ns_g_cpus = parse_int(isc_commandline_argument, "number of cpus"); if (ns_g_cpus == 0) ns_g_cpus = 1; break; case 'p': port = parse_int(isc_commandline_argument, "port"); if (port < 1 || port > 65535) ns_main_earlyfatal("port '%s' out of range", isc_commandline_argument); ns_g_port = port; break; /* XXXBEW Should -P be removed? */ case 'P': port = parse_int(isc_commandline_argument, "port"); if (port < 1 || port > 65535) ns_main_earlyfatal("port '%s' out of range", isc_commandline_argument); lwresd_g_listenport = port; break; case 's': /* XXXRTH temporary syntax */ want_stats = ISC_TRUE; break; case 'S': maxsocks = parse_int(isc_commandline_argument, "max number of sockets"); break; case 't': /* XXXJAB should we make a copy? */ ns_g_chrootdir = isc_commandline_argument; break; case 'T': /* NOT DOCUMENTED */ /* * force the server to behave (or misbehave) in * specified ways for testing purposes. * * clienttest: make clients single shot with their * own memory context. * delay=xxxx: delay client responses by xxxx ms to * simulate remote servers. * dscp=x: check that dscp values are as * expected and assert otherwise. */ if (!strcmp(isc_commandline_argument, "clienttest")) ns_g_clienttest = ISC_TRUE; else if (!strcmp(isc_commandline_argument, "nosoa")) ns_g_nosoa = ISC_TRUE; else if (!strcmp(isc_commandline_argument, "noaa")) ns_g_noaa = ISC_TRUE; else if (!strcmp(isc_commandline_argument, "maxudp512")) maxudp = 512; else if (!strcmp(isc_commandline_argument, "maxudp1460")) maxudp = 1460; else if (!strcmp(isc_commandline_argument, "dropedns")) ns_g_dropedns = ISC_TRUE; else if (!strcmp(isc_commandline_argument, "noedns")) ns_g_noedns = ISC_TRUE; else if (!strncmp(isc_commandline_argument, "maxudp=", 7)) maxudp = atoi(isc_commandline_argument + 7); else if (!strncmp(isc_commandline_argument, "delay=", 6)) ns_g_delay = atoi(isc_commandline_argument + 6); else if (!strcmp(isc_commandline_argument, "nosyslog")) ns_g_nosyslog = ISC_TRUE; else if (!strcmp(isc_commandline_argument, "nonearest")) ns_g_nonearest = ISC_TRUE; else if (!strncmp(isc_commandline_argument, "dscp=", 5)) isc_dscp_check_value = atoi(isc_commandline_argument + 5); else if (!strncmp(isc_commandline_argument, "mkeytimers=", 11)) { p = strtok(isc_commandline_argument + 11, "/"); if (p == NULL) ns_main_earlyfatal("bad mkeytimer"); dns_zone_mkey_hour = atoi(p); if (dns_zone_mkey_hour == 0) ns_main_earlyfatal("bad mkeytimer"); p = strtok(NULL, "/"); if (p == NULL) { dns_zone_mkey_day = (24 * dns_zone_mkey_hour); dns_zone_mkey_month = (30 * dns_zone_mkey_day); break; } dns_zone_mkey_day = atoi(p); if (dns_zone_mkey_day < dns_zone_mkey_hour) ns_main_earlyfatal("bad mkeytimer"); p = strtok(NULL, "/"); if (p == NULL) { dns_zone_mkey_month = (30 * dns_zone_mkey_day); break; } dns_zone_mkey_month = atoi(p); if (dns_zone_mkey_month < dns_zone_mkey_day) ns_main_earlyfatal("bad mkeytimer"); } else if (!strcmp(isc_commandline_argument, "notcp")) { ns_g_notcp = ISC_TRUE; } else if (!strncmp(isc_commandline_argument, "tat=", 4)) { ns_g_tat_interval = atoi(isc_commandline_argument + 4); } else if (!strcmp(isc_commandline_argument, "keepstderr")) { ns_g_keepstderr = ISC_TRUE; } else if (!strcmp(isc_commandline_argument, "fixedlocal")) { ns_g_fixedlocal = ISC_TRUE; } else { fprintf(stderr, "unknown -T flag '%s\n", isc_commandline_argument); } break; case 'U': ns_g_udpdisp = parse_int(isc_commandline_argument, "number of UDP listeners " "per interface"); break; case 'u': ns_g_username = isc_commandline_argument; break; case 'v': printf("%s %s%s%s \n", ns_g_product, ns_g_version, (*ns_g_description != '\0') ? " " : "", ns_g_description, ns_g_srcid); exit(0); case 'V': printf("%s %s%s%s \n", ns_g_product, ns_g_version, (*ns_g_description != '\0') ? " " : "", ns_g_description, ns_g_srcid); printf("running on %s\n", ns_os_uname()); printf("built by %s with %s\n", ns_g_builder, ns_g_configargs); #ifdef __clang__ printf("compiled by CLANG %s\n", __VERSION__); #else #if defined(__ICC) || defined(__INTEL_COMPILER) printf("compiled by ICC %s\n", __VERSION__); #else #ifdef __GNUC__ printf("compiled by GCC %s\n", __VERSION__); #endif #endif #endif #ifdef _MSC_VER printf("compiled by MSVC %d\n", _MSC_VER); #endif #ifdef __SUNPRO_C printf("compiled by Solaris Studio %x\n", __SUNPRO_C); #endif #ifdef OPENSSL printf("compiled with OpenSSL version: %s\n", OPENSSL_VERSION_TEXT); #if !defined(LIBRESSL_VERSION_NUMBER) && \ OPENSSL_VERSION_NUMBER >= 0x10100000L /* 1.1.0 or higher */ printf("linked to OpenSSL version: %s\n", OpenSSL_version(OPENSSL_VERSION)); #else printf("linked to OpenSSL version: %s\n", SSLeay_version(SSLEAY_VERSION)); #endif /* OPENSSL_VERSION_NUMBER >= 0x10100000L */ #endif #ifdef HAVE_LIBXML2 printf("compiled with libxml2 version: %s\n", LIBXML_DOTTED_VERSION); printf("linked to libxml2 version: %s\n", xmlParserVersion); #endif #if defined(HAVE_JSON) && defined(JSON_C_VERSION) printf("compiled with libjson-c version: %s\n", JSON_C_VERSION); printf("linked to libjson-c version: %s\n", json_c_version()); #endif #if defined(HAVE_ZLIB) && defined(ZLIB_VERSION) printf("compiled with zlib version: %s\n", ZLIB_VERSION); printf("linked to zlib version: %s\n", zlibVersion()); #endif #ifdef ISC_PLATFORM_USETHREADS printf("threads support is enabled\n"); #else printf("threads support is disabled\n"); #endif exit(0); case 'x': /* Obsolete. No longer in use. Ignore. */ break; case 'X': ns_g_forcelock = ISC_TRUE; if (strcasecmp(isc_commandline_argument, "none") != 0) ns_g_defaultlockfile = isc_commandline_argument; else ns_g_defaultlockfile = NULL; break; case 'F': /* Reserved for FIPS mode */ /* FALLTHROUGH */ case '?': usage(); if (isc_commandline_option == '?') exit(0); p = strchr(NS_MAIN_ARGS, isc_commandline_option); if (p == NULL || *++p != ':') ns_main_earlyfatal("unknown option '-%c'", isc_commandline_option); else ns_main_earlyfatal("option '-%c' requires " "an argument", isc_commandline_option); /* FALLTHROUGH */ default: ns_main_earlyfatal("parsing options returned %d", ch); } } argc -= isc_commandline_index; argv += isc_commandline_index; POST(argv); if (argc > 0) { usage(); ns_main_earlyfatal("extra command line arguments"); } } static isc_result_t create_managers(void) { isc_result_t result; unsigned int socks; INSIST(ns_g_cpus_detected > 0); #ifdef ISC_PLATFORM_USETHREADS if (ns_g_cpus == 0) ns_g_cpus = ns_g_cpus_detected; isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_INFO, "found %u CPU%s, using %u worker thread%s", ns_g_cpus_detected, ns_g_cpus_detected == 1 ? "" : "s", ns_g_cpus, ns_g_cpus == 1 ? "" : "s"); #else ns_g_cpus = 1; #endif #ifdef WIN32 ns_g_udpdisp = 1; #else if (ns_g_udpdisp == 0) { if (ns_g_cpus_detected == 1) ns_g_udpdisp = 1; else ns_g_udpdisp = ns_g_cpus_detected - 1; } if (ns_g_udpdisp > ns_g_cpus) ns_g_udpdisp = ns_g_cpus; #endif #ifdef ISC_PLATFORM_USETHREADS isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_INFO, "using %u UDP listener%s per interface", ns_g_udpdisp, ns_g_udpdisp == 1 ? "" : "s"); #endif result = isc_taskmgr_create(ns_g_mctx, ns_g_cpus, 0, &ns_g_taskmgr); if (result != ISC_R_SUCCESS) { UNEXPECTED_ERROR(__FILE__, __LINE__, "isc_taskmgr_create() failed: %s", isc_result_totext(result)); return (ISC_R_UNEXPECTED); } result = isc_timermgr_create(ns_g_mctx, &ns_g_timermgr); if (result != ISC_R_SUCCESS) { UNEXPECTED_ERROR(__FILE__, __LINE__, "isc_timermgr_create() failed: %s", isc_result_totext(result)); return (ISC_R_UNEXPECTED); } result = isc_socketmgr_create2(ns_g_mctx, &ns_g_socketmgr, maxsocks); if (result != ISC_R_SUCCESS) { UNEXPECTED_ERROR(__FILE__, __LINE__, "isc_socketmgr_create() failed: %s", isc_result_totext(result)); return (ISC_R_UNEXPECTED); } isc__socketmgr_maxudp(ns_g_socketmgr, maxudp); result = isc_socketmgr_getmaxsockets(ns_g_socketmgr, &socks); if (result == ISC_R_SUCCESS) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_INFO, "using up to %u sockets", socks); } result = isc_entropy_create(ns_g_mctx, &ns_g_entropy); if (result != ISC_R_SUCCESS) { UNEXPECTED_ERROR(__FILE__, __LINE__, "isc_entropy_create() failed: %s", isc_result_totext(result)); return (ISC_R_UNEXPECTED); } result = isc_hash_create(ns_g_mctx, ns_g_entropy, DNS_NAME_MAXWIRE); if (result != ISC_R_SUCCESS) { UNEXPECTED_ERROR(__FILE__, __LINE__, "isc_hash_create() failed: %s", isc_result_totext(result)); return (ISC_R_UNEXPECTED); } return (ISC_R_SUCCESS); } static void destroy_managers(void) { ns_lwresd_shutdown(); /* * isc_taskmgr_destroy() will block until all tasks have exited, */ isc_taskmgr_destroy(&ns_g_taskmgr); isc_timermgr_destroy(&ns_g_timermgr); isc_socketmgr_destroy(&ns_g_socketmgr); /* * isc_hash_destroy() cannot be called as long as a resolver may be * running. Calling this after isc_taskmgr_destroy() ensures the * call is safe. */ isc_hash_destroy(); } static void dump_symboltable(void) { int i; isc_result_t result; const char *fname; const void *addr; if (isc__backtrace_nsymbols == 0) return; if (!isc_log_wouldlog(ns_g_lctx, ISC_LOG_DEBUG(99))) return; isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, ISC_LOG_DEBUG(99), "Symbol table:"); for (i = 0, result = ISC_R_SUCCESS; result == ISC_R_SUCCESS; i++) { addr = NULL; fname = NULL; result = isc_backtrace_getsymbolfromindex(i, &addr, &fname); if (result == ISC_R_SUCCESS) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, ISC_LOG_DEBUG(99), "[%d] %p %s", i, addr, fname); } } } #ifdef HAVE_LIBSECCOMP static void setup_seccomp() { scmp_filter_ctx ctx; unsigned int i; int ret; /* Make sure the lists are in sync */ INSIST((sizeof(scmp_syscalls) / sizeof(int)) == (sizeof(scmp_syscall_names) / sizeof(const char *))); ctx = seccomp_init(SCMP_ACT_KILL); if (ctx == NULL) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, ISC_LOG_WARNING, "libseccomp activation failed"); return; } for (i = 0 ; i < sizeof(scmp_syscalls)/sizeof(*(scmp_syscalls)); i++) { ret = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, scmp_syscalls[i], 0); if (ret < 0) isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, ISC_LOG_WARNING, "libseccomp rule failed: %s", scmp_syscall_names[i]); else isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, ISC_LOG_DEBUG(9), "added libseccomp rule: %s", scmp_syscall_names[i]); } ret = seccomp_load(ctx); if (ret < 0) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, ISC_LOG_WARNING, "libseccomp unable to load filter"); } else { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, ISC_LOG_NOTICE, "libseccomp sandboxing active"); } /* * Release filter in ctx. Filters already loaded are not * affected. */ seccomp_release(ctx); } #endif /* HAVE_LIBSECCOMP */ static void setup(void) { isc_result_t result; isc_resourcevalue_t old_openfiles; #ifdef HAVE_LIBSCF char *instance = NULL; #endif /* * Get the user and group information before changing the root * directory, so the administrator does not need to keep a copy * of the user and group databases in the chroot'ed environment. */ ns_os_inituserinfo(ns_g_username); /* * Initialize time conversion information */ ns_os_tzset(); ns_os_opendevnull(); #ifdef HAVE_LIBSCF /* Check if named is under smf control, before chroot. */ result = ns_smf_get_instance(&instance, 0, ns_g_mctx); /* We don't care about instance, just check if we got one. */ if (result == ISC_R_SUCCESS) ns_smf_got_instance = 1; else ns_smf_got_instance = 0; if (instance != NULL) isc_mem_free(ns_g_mctx, instance); #endif /* HAVE_LIBSCF */ #ifdef PATH_RANDOMDEV /* * Initialize system's random device as fallback entropy source * if running chroot'ed. */ if (ns_g_chrootdir != NULL) { result = isc_entropy_create(ns_g_mctx, &ns_g_fallbackentropy); if (result != ISC_R_SUCCESS) ns_main_earlyfatal("isc_entropy_create() failed: %s", isc_result_totext(result)); result = isc_entropy_createfilesource(ns_g_fallbackentropy, PATH_RANDOMDEV); if (result != ISC_R_SUCCESS) { ns_main_earlywarning("could not open pre-chroot " "entropy source %s: %s", PATH_RANDOMDEV, isc_result_totext(result)); isc_entropy_detach(&ns_g_fallbackentropy); } } #endif #ifdef ISC_PLATFORM_USETHREADS /* * Check for the number of cpu's before ns_os_chroot(). */ ns_g_cpus_detected = isc_os_ncpus(); #endif ns_os_chroot(ns_g_chrootdir); /* * For operating systems which have a capability mechanism, now * is the time to switch to minimal privs and change our user id. * On traditional UNIX systems, this call will be a no-op, and we * will change the user ID after reading the config file the first * time. (We need to read the config file to know which possibly * privileged ports to bind() to.) */ ns_os_minprivs(); result = ns_log_init(ISC_TF(ns_g_username != NULL)); if (result != ISC_R_SUCCESS) ns_main_earlyfatal("ns_log_init() failed: %s", isc_result_totext(result)); /* * Now is the time to daemonize (if we're not running in the * foreground). We waited until now because we wanted to get * a valid logging context setup. We cannot daemonize any later, * because calling create_managers() will create threads, which * would be lost after fork(). */ if (!ns_g_foreground) ns_os_daemonize(); /* * We call isc_app_start() here as some versions of FreeBSD's fork() * destroys all the signal handling it sets up. */ result = isc_app_start(); if (result != ISC_R_SUCCESS) ns_main_earlyfatal("isc_app_start() failed: %s", isc_result_totext(result)); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, ISC_LOG_NOTICE, "starting %s %s%s%s ", ns_g_product, ns_g_version, *ns_g_description ? " " : "", ns_g_description, ns_g_srcid); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, ISC_LOG_NOTICE, "running on %s", ns_os_uname()); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, ISC_LOG_NOTICE, "built with %s", ns_g_configargs); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, ISC_LOG_NOTICE, "running as: %s%s", program_name, saved_command_line); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, ISC_LOG_NOTICE, "----------------------------------------------------"); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, ISC_LOG_NOTICE, "BIND 9 is maintained by Internet Systems Consortium,"); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, ISC_LOG_NOTICE, "Inc. (ISC), a non-profit 501(c)(3) public-benefit "); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, ISC_LOG_NOTICE, "corporation. Support and training for BIND 9 are "); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, ISC_LOG_NOTICE, "available at https://www.isc.org/support"); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, ISC_LOG_NOTICE, "----------------------------------------------------"); dump_symboltable(); /* * Get the initial resource limits. */ (void)isc_resource_getlimit(isc_resource_stacksize, &ns_g_initstacksize); (void)isc_resource_getlimit(isc_resource_datasize, &ns_g_initdatasize); (void)isc_resource_getlimit(isc_resource_coresize, &ns_g_initcoresize); (void)isc_resource_getlimit(isc_resource_openfiles, &ns_g_initopenfiles); /* * System resources cannot effectively be tuned on some systems. * Raise the limit in such cases for safety. */ old_openfiles = ns_g_initopenfiles; ns_os_adjustnofile(); (void)isc_resource_getlimit(isc_resource_openfiles, &ns_g_initopenfiles); if (old_openfiles != ns_g_initopenfiles) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, ISC_LOG_NOTICE, "adjusted limit on open files from " "%" ISC_PRINT_QUADFORMAT "u to " "%" ISC_PRINT_QUADFORMAT "u", old_openfiles, ns_g_initopenfiles); } /* * If the named configuration filename is relative, prepend the current * directory's name before possibly changing to another directory. */ if (! isc_file_isabsolute(ns_g_conffile)) { result = isc_file_absolutepath(ns_g_conffile, absolute_conffile, sizeof(absolute_conffile)); if (result != ISC_R_SUCCESS) ns_main_earlyfatal("could not construct absolute path " "of configuration file: %s", isc_result_totext(result)); ns_g_conffile = absolute_conffile; } /* * Record the server's startup time. */ result = isc_time_now(&ns_g_boottime); if (result != ISC_R_SUCCESS) ns_main_earlyfatal("isc_time_now() failed: %s", isc_result_totext(result)); result = create_managers(); if (result != ISC_R_SUCCESS) ns_main_earlyfatal("create_managers() failed: %s", isc_result_totext(result)); ns_builtin_init(); /* * Add calls to register sdb drivers here. */ /* xxdb_init(); */ #ifdef ISC_DLZ_DLOPEN /* * Register the DLZ "dlopen" driver. */ result = dlz_dlopen_init(ns_g_mctx); if (result != ISC_R_SUCCESS) ns_main_earlyfatal("dlz_dlopen_init() failed: %s", isc_result_totext(result)); #endif #if CONTRIB_DLZ /* * Register any other contributed DLZ drivers. */ result = dlz_drivers_init(); if (result != ISC_R_SUCCESS) ns_main_earlyfatal("dlz_drivers_init() failed: %s", isc_result_totext(result)); #endif ns_server_create(ns_g_mctx, &ns_g_server); #ifdef HAVE_LIBSECCOMP setup_seccomp(); #endif /* HAVE_LIBSECCOMP */ } static void cleanup(void) { destroy_managers(); if (ns_g_mapped != NULL) dns_acl_detach(&ns_g_mapped); ns_server_destroy(&ns_g_server); isc_entropy_detach(&ns_g_entropy); if (ns_g_fallbackentropy != NULL) isc_entropy_detach(&ns_g_fallbackentropy); ns_builtin_deinit(); /* * Add calls to unregister sdb drivers here. */ /* xxdb_clear(); */ #ifdef CONTRIB_DLZ /* * Unregister contributed DLZ drivers. */ dlz_drivers_clear(); #endif #ifdef ISC_DLZ_DLOPEN /* * Unregister "dlopen" DLZ driver. */ dlz_dlopen_clear(); #endif dns_name_destroy(); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, ISC_LOG_NOTICE, "exiting"); ns_log_shutdown(); } static char *memstats = NULL; void ns_main_setmemstats(const char *filename) { /* * Caller has to ensure locking. */ if (memstats != NULL) { free(memstats); memstats = NULL; } if (filename == NULL) return; memstats = strdup(filename); } #ifdef HAVE_LIBSCF /* * Get FMRI for the named process. */ isc_result_t ns_smf_get_instance(char **ins_name, int debug, isc_mem_t *mctx) { scf_handle_t *h = NULL; int namelen; char *instance; REQUIRE(ins_name != NULL && *ins_name == NULL); if ((h = scf_handle_create(SCF_VERSION)) == NULL) { if (debug) UNEXPECTED_ERROR(__FILE__, __LINE__, "scf_handle_create() failed: %s", scf_strerror(scf_error())); return (ISC_R_FAILURE); } if (scf_handle_bind(h) == -1) { if (debug) UNEXPECTED_ERROR(__FILE__, __LINE__, "scf_handle_bind() failed: %s", scf_strerror(scf_error())); scf_handle_destroy(h); return (ISC_R_FAILURE); } if ((namelen = scf_myname(h, NULL, 0)) == -1) { if (debug) UNEXPECTED_ERROR(__FILE__, __LINE__, "scf_myname() failed: %s", scf_strerror(scf_error())); scf_handle_destroy(h); return (ISC_R_FAILURE); } if ((instance = isc_mem_allocate(mctx, namelen + 1)) == NULL) { UNEXPECTED_ERROR(__FILE__, __LINE__, "ns_smf_get_instance memory " "allocation failed: %s", isc_result_totext(ISC_R_NOMEMORY)); scf_handle_destroy(h); return (ISC_R_FAILURE); } if (scf_myname(h, instance, namelen + 1) == -1) { if (debug) UNEXPECTED_ERROR(__FILE__, __LINE__, "scf_myname() failed: %s", scf_strerror(scf_error())); scf_handle_destroy(h); isc_mem_free(mctx, instance); return (ISC_R_FAILURE); } scf_handle_destroy(h); *ins_name = instance; return (ISC_R_SUCCESS); } #endif /* HAVE_LIBSCF */ /* main entry point, possibly hooked */ int main(int argc, char *argv[]) { isc_result_t result; #ifdef HAVE_LIBSCF char *instance = NULL; #endif #ifdef HAVE_GPERFTOOLS_PROFILER (void) ProfilerStart(NULL); #endif /* * Record version in core image. * strings named.core | grep "named version:" */ strlcat(version, #if defined(NO_VERSION_DATE) || !defined(__DATE__) "named version: BIND " VERSION " <" SRCID ">", #else "named version: BIND " VERSION " <" SRCID "> (" __DATE__ ")", #endif sizeof(version)); result = isc_file_progname(*argv, program_name, sizeof(program_name)); if (result != ISC_R_SUCCESS) ns_main_earlyfatal("program name too long"); if (strcmp(program_name, "lwresd") == 0) ns_g_lwresdonly = ISC_TRUE; if (result != ISC_R_SUCCESS) ns_main_earlyfatal("failed to build internal symbol table"); isc_assertion_setcallback(assertion_failed); isc_error_setfatal(library_fatal_error); isc_error_setunexpected(library_unexpected_error); ns_os_init(program_name); dns_result_register(); dst_result_register(); isccc_result_register(); #ifdef PKCS11CRYPTO pk11_result_register(); #endif parse_command_line(argc, argv); #ifdef ENABLE_AFL if (ns_g_fuzz_type != ns_fuzz_none) { named_fuzz_setup(); } if (ns_g_fuzz_type == ns_fuzz_resolver) { dns_resolver_setfuzzing(); } else if (ns_g_fuzz_type == ns_fuzz_http) { isc_httpd_setfinishhook(named_fuzz_notify); } #endif /* * Warn about common configuration error. */ if (ns_g_chrootdir != NULL) { int len = strlen(ns_g_chrootdir); if (strncmp(ns_g_chrootdir, ns_g_conffile, len) == 0 && (ns_g_conffile[len] == '/' || ns_g_conffile[len] == '\\')) ns_main_earlywarning("config filename (-c %s) contains " "chroot path (-t %s)", ns_g_conffile, ns_g_chrootdir); } result = isc_mem_create(0, 0, &ns_g_mctx); if (result != ISC_R_SUCCESS) ns_main_earlyfatal("isc_mem_create() failed: %s", isc_result_totext(result)); isc_mem_setname(ns_g_mctx, "main", NULL); setup(); /* * Start things running and then wait for a shutdown request * or reload. */ do { result = isc_app_run(); if (result == ISC_R_RELOAD) { ns_server_reloadwanted(ns_g_server); } else if (result != ISC_R_SUCCESS) { UNEXPECTED_ERROR(__FILE__, __LINE__, "isc_app_run(): %s", isc_result_totext(result)); /* * Force exit. */ result = ISC_R_SUCCESS; } } while (result != ISC_R_SUCCESS); #ifdef HAVE_LIBSCF if (ns_smf_want_disable == 1) { result = ns_smf_get_instance(&instance, 1, ns_g_mctx); if (result == ISC_R_SUCCESS && instance != NULL) { if (smf_disable_instance(instance, 0) != 0) UNEXPECTED_ERROR(__FILE__, __LINE__, "smf_disable_instance() " "failed for %s : %s", instance, scf_strerror(scf_error())); } if (instance != NULL) isc_mem_free(ns_g_mctx, instance); } #endif /* HAVE_LIBSCF */ cleanup(); if (want_stats) { isc_mem_stats(ns_g_mctx, stdout); isc_mutex_stats(stdout); } if (ns_g_memstatistics && memstats != NULL) { FILE *fp = NULL; result = isc_stdio_open(memstats, "w", &fp); if (result == ISC_R_SUCCESS) { isc_mem_stats(ns_g_mctx, fp); isc_mutex_stats(fp); (void) isc_stdio_close(fp); } } isc_mem_destroy(&ns_g_mctx); isc_mem_checkdestroyed(stderr); ns_main_setmemstats(NULL); isc_app_finish(); ns_os_closedevnull(); ns_os_shutdown(); #ifdef HAVE_GPERFTOOLS_PROFILER ProfilerStop(); #endif return (0); } bind9-9.11.3+dfsg/bin/named/named.8000066400000000000000000000242341325250447100165520ustar00rootroot00000000000000.\" Copyright (C) 2000, 2001, 2003-2009, 2011, 2013-2017 Internet Systems Consortium, Inc. ("ISC") .\" .\" This Source Code Form is subject to the terms of the Mozilla Public .\" License, v. 2.0. If a copy of the MPL was not distributed with this .\" file, You can obtain one at http://mozilla.org/MPL/2.0/. .\" .hy 0 .ad l '\" t .\" Title: named .\" Author: .\" Generator: DocBook XSL Stylesheets v1.78.1 .\" Date: 2014-02-19 .\" Manual: BIND9 .\" Source: ISC .\" Language: English .\" .TH "NAMED" "8" "2014\-02\-19" "ISC" "BIND9" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" named \- Internet domain name server .SH "SYNOPSIS" .HP \w'\fBnamed\fR\ 'u \fBnamed\fR [[\fB\-4\fR] | [\fB\-6\fR]] [\fB\-c\ \fR\fB\fIconfig\-file\fR\fR] [\fB\-d\ \fR\fB\fIdebug\-level\fR\fR] [\fB\-D\ \fR\fB\fIstring\fR\fR] [\fB\-E\ \fR\fB\fIengine\-name\fR\fR] [\fB\-f\fR] [\fB\-g\fR] [\fB\-L\ \fR\fB\fIlogfile\fR\fR] [\fB\-M\ \fR\fB\fIoption\fR\fR] [\fB\-m\ \fR\fB\fIflag\fR\fR] [\fB\-n\ \fR\fB\fI#cpus\fR\fR] [\fB\-p\ \fR\fB\fIport\fR\fR] [\fB\-s\fR] [\fB\-S\ \fR\fB\fI#max\-socks\fR\fR] [\fB\-t\ \fR\fB\fIdirectory\fR\fR] [\fB\-U\ \fR\fB\fI#listeners\fR\fR] [\fB\-u\ \fR\fB\fIuser\fR\fR] [\fB\-v\fR] [\fB\-V\fR] [\fB\-X\ \fR\fB\fIlock\-file\fR\fR] [\fB\-x\ \fR\fB\fIcache\-file\fR\fR] .SH "DESCRIPTION" .PP \fBnamed\fR is a Domain Name System (DNS) server, part of the BIND 9 distribution from ISC\&. For more information on the DNS, see RFCs 1033, 1034, and 1035\&. .PP When invoked without arguments, \fBnamed\fR will read the default configuration file /etc/named\&.conf, read any initial data, and listen for queries\&. .SH "OPTIONS" .PP \-4 .RS 4 Use IPv4 only even if the host machine is capable of IPv6\&. \fB\-4\fR and \fB\-6\fR are mutually exclusive\&. .RE .PP \-6 .RS 4 Use IPv6 only even if the host machine is capable of IPv4\&. \fB\-4\fR and \fB\-6\fR are mutually exclusive\&. .RE .PP \-c \fIconfig\-file\fR .RS 4 Use \fIconfig\-file\fR as the configuration file instead of the default, /etc/named\&.conf\&. To ensure that reloading the configuration file continues to work after the server has changed its working directory due to to a possible \fBdirectory\fR option in the configuration file, \fIconfig\-file\fR should be an absolute pathname\&. .RE .PP \-d \fIdebug\-level\fR .RS 4 Set the daemon\*(Aqs debug level to \fIdebug\-level\fR\&. Debugging traces from \fBnamed\fR become more verbose as the debug level increases\&. .RE .PP \-D \fIstring\fR .RS 4 Specifies a string that is used to identify a instance of \fBnamed\fR in a process listing\&. The contents of \fIstring\fR are not examined\&. .RE .PP \-E \fIengine\-name\fR .RS 4 When applicable, specifies the hardware to use for cryptographic operations, such as a secure key store used for signing\&. .sp When BIND is built with OpenSSL PKCS#11 support, this defaults to the string "pkcs11", which identifies an OpenSSL engine that can drive a cryptographic accelerator or hardware service module\&. When BIND is built with native PKCS#11 cryptography (\-\-enable\-native\-pkcs11), it defaults to the path of the PKCS#11 provider library specified via "\-\-with\-pkcs11"\&. .RE .PP \-f .RS 4 Run the server in the foreground (i\&.e\&. do not daemonize)\&. .RE .PP \-g .RS 4 Run the server in the foreground and force all logging to stderr\&. .RE .PP \-L \fIlogfile\fR .RS 4 Log to the file \fBlogfile\fR by default instead of the system log\&. .RE .PP \-M \fIoption\fR .RS 4 Sets the default memory context options\&. Currently the only supported option is \fIexternal\fR, which causes the internal memory manager to be bypassed in favor of system\-provided memory allocation functions\&. .RE .PP \-m \fIflag\fR .RS 4 Turn on memory usage debugging flags\&. Possible flags are \fIusage\fR, \fItrace\fR, \fIrecord\fR, \fIsize\fR, and \fImctx\fR\&. These correspond to the ISC_MEM_DEBUGXXXX flags described in \&. .RE .PP \-n \fI#cpus\fR .RS 4 Create \fI#cpus\fR worker threads to take advantage of multiple CPUs\&. If not specified, \fBnamed\fR will try to determine the number of CPUs present and create one thread per CPU\&. If it is unable to determine the number of CPUs, a single worker thread will be created\&. .RE .PP \-p \fIport\fR .RS 4 Listen for queries on port \fIport\fR\&. If not specified, the default is port 53\&. .RE .PP \-s .RS 4 Write memory usage statistics to stdout on exit\&. .if n \{\ .sp .\} .RS 4 .it 1 an-trap .nr an-no-space-flag 1 .nr an-break-flag 1 .br .ps +1 \fBNote\fR .ps -1 .br This option is mainly of interest to BIND 9 developers and may be removed or changed in a future release\&. .sp .5v .RE .RE .PP \-S \fI#max\-socks\fR .RS 4 Allow \fBnamed\fR to use up to \fI#max\-socks\fR sockets\&. The default value is 4096 on systems built with default configuration options, and 21000 on systems built with "configure \-\-with\-tuning=large"\&. .if n \{\ .sp .\} .RS 4 .it 1 an-trap .nr an-no-space-flag 1 .nr an-break-flag 1 .br .ps +1 \fBWarning\fR .ps -1 .br This option should be unnecessary for the vast majority of users\&. The use of this option could even be harmful because the specified value may exceed the limitation of the underlying system API\&. It is therefore set only when the default configuration causes exhaustion of file descriptors and the operational environment is known to support the specified number of sockets\&. Note also that the actual maximum number is normally a little fewer than the specified value because \fBnamed\fR reserves some file descriptors for its internal use\&. .sp .5v .RE .RE .PP \-t \fIdirectory\fR .RS 4 Chroot to \fIdirectory\fR after processing the command line arguments, but before reading the configuration file\&. .if n \{\ .sp .\} .RS 4 .it 1 an-trap .nr an-no-space-flag 1 .nr an-break-flag 1 .br .ps +1 \fBWarning\fR .ps -1 .br This option should be used in conjunction with the \fB\-u\fR option, as chrooting a process running as root doesn\*(Aqt enhance security on most systems; the way \fBchroot(2)\fR is defined allows a process with root privileges to escape a chroot jail\&. .sp .5v .RE .RE .PP \-U \fI#listeners\fR .RS 4 Use \fI#listeners\fR worker threads to listen for incoming UDP packets on each address\&. If not specified, \fBnamed\fR will calculate a default value based on the number of detected CPUs: 1 for 1 CPU, and the number of detected CPUs minus one for machines with more than 1 CPU\&. This cannot be increased to a value higher than the number of CPUs\&. If \fB\-n\fR has been set to a higher value than the number of detected CPUs, then \fB\-U\fR may be increased as high as that value, but no higher\&. On Windows, the number of UDP listeners is hardwired to 1 and this option has no effect\&. .RE .PP \-u \fIuser\fR .RS 4 Setuid to \fIuser\fR after completing privileged operations, such as creating sockets that listen on privileged ports\&. .if n \{\ .sp .\} .RS 4 .it 1 an-trap .nr an-no-space-flag 1 .nr an-break-flag 1 .br .ps +1 \fBNote\fR .ps -1 .br On Linux, \fBnamed\fR uses the kernel\*(Aqs capability mechanism to drop all root privileges except the ability to \fBbind(2)\fR to a privileged port and set process resource limits\&. Unfortunately, this means that the \fB\-u\fR option only works when \fBnamed\fR is run on kernel 2\&.2\&.18 or later, or kernel 2\&.3\&.99\-pre3 or later, since previous kernels did not allow privileges to be retained after \fBsetuid(2)\fR\&. .sp .5v .RE .RE .PP \-v .RS 4 Report the version number and exit\&. .RE .PP \-V .RS 4 Report the version number and build options, and exit\&. .RE .PP \-X \fIlock\-file\fR .RS 4 Acquire a lock on the specified file at runtime; this helps to prevent duplicate \fBnamed\fR instances from running simultaneously\&. Use of this option overrides the \fBlock\-file\fR option in named\&.conf\&. If set to none, the lock file check is disabled\&. .RE .PP \-x \fIcache\-file\fR .RS 4 Load data from \fIcache\-file\fR into the cache of the default view\&. .if n \{\ .sp .\} .RS 4 .it 1 an-trap .nr an-no-space-flag 1 .nr an-break-flag 1 .br .ps +1 \fBWarning\fR .ps -1 .br This option must not be used\&. It is only of interest to BIND 9 developers and may be removed or changed in a future release\&. .sp .5v .RE .RE .SH "SIGNALS" .PP In routine operation, signals should not be used to control the nameserver; \fBrndc\fR should be used instead\&. .PP SIGHUP .RS 4 Force a reload of the server\&. .RE .PP SIGINT, SIGTERM .RS 4 Shut down the server\&. .RE .PP The result of sending any other signals to the server is undefined\&. .SH "CONFIGURATION" .PP The \fBnamed\fR configuration file is too complex to describe in detail here\&. A complete description is provided in the BIND 9 Administrator Reference Manual\&. .PP \fBnamed\fR inherits the \fBumask\fR (file creation mode mask) from the parent process\&. If files created by \fBnamed\fR, such as journal files, need to have custom permissions, the \fBumask\fR should be set explicitly in the script used to start the \fBnamed\fR process\&. .SH "FILES" .PP /etc/named\&.conf .RS 4 The default configuration file\&. .RE .PP /var/run/named/named\&.pid .RS 4 The default process\-id file\&. .RE .SH "SEE ALSO" .PP RFC 1033, RFC 1034, RFC 1035, \fBnamed-checkconf\fR(8), \fBnamed-checkzone\fR(8), \fBrndc\fR(8), \fBlwresd\fR(8), \fBnamed.conf\fR(5), BIND 9 Administrator Reference Manual\&. .SH "AUTHOR" .PP \fBInternet Systems Consortium, Inc\&.\fR .SH "COPYRIGHT" .br Copyright \(co 2000, 2001, 2003-2009, 2011, 2013-2017 Internet Systems Consortium, Inc. ("ISC") .br bind9-9.11.3+dfsg/bin/named/named.conf.5000066400000000000000000001135261325250447100174760ustar00rootroot00000000000000.\" Copyright (C) 2004-2018 Internet Systems Consortium, Inc. ("ISC") .\" .\" This Source Code Form is subject to the terms of the Mozilla Public .\" License, v. 2.0. If a copy of the MPL was not distributed with this .\" file, You can obtain one at http://mozilla.org/MPL/2.0/. .\" .hy 0 .ad l '\" t .\" Title: named.conf .\" Author: .\" Generator: DocBook XSL Stylesheets v1.78.1 .\" Date: 2017-08-15 .\" Manual: BIND9 .\" Source: ISC .\" Language: English .\" .TH "NAMED\&.CONF" "5" "2017\-08\-15" "ISC" "BIND9" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" named.conf \- configuration file for \fBnamed\fR .SH "SYNOPSIS" .HP \w'\fBnamed\&.conf\fR\ 'u \fBnamed\&.conf\fR .SH "DESCRIPTION" .PP named\&.conf is the configuration file for \fBnamed\fR\&. Statements are enclosed in braces and terminated with a semi\-colon\&. Clauses in the statements are also semi\-colon terminated\&. The usual comment styles are supported: .PP C style: /* */ .PP C++ style: // to end of line .PP Unix style: # to end of line .SH "ACL" .sp .if n \{\ .RS 4 .\} .nf acl \fIstring\fR { \fIaddress_match_element\fR; \&.\&.\&. }; .fi .if n \{\ .RE .\} .SH "CONTROLS" .sp .if n \{\ .RS 4 .\} .nf controls { inet ( \fIipv4_address\fR | \fIipv6_address\fR | * ) [ port ( \fIinteger\fR | * ) ] allow { \fIaddress_match_element\fR; \&.\&.\&. } [ keys { \fIstring\fR; \&.\&.\&. } ] [ read\-only \fIboolean\fR ]; unix \fIquoted_string\fR perm \fIinteger\fR owner \fIinteger\fR group \fIinteger\fR [ keys { \fIstring\fR; \&.\&.\&. } ] [ read\-only \fIboolean\fR ]; }; .fi .if n \{\ .RE .\} .SH "DLZ" .sp .if n \{\ .RS 4 .\} .nf dlz \fIstring\fR { database \fIstring\fR; search \fIboolean\fR; }; .fi .if n \{\ .RE .\} .SH "DYNDB" .sp .if n \{\ .RS 4 .\} .nf dyndb \fIstring\fR \fIquoted_string\fR { \fIunspecified\-text\fR }; .fi .if n \{\ .RE .\} .SH "KEY" .sp .if n \{\ .RS 4 .\} .nf key \fIstring\fR { algorithm \fIstring\fR; secret \fIstring\fR; }; .fi .if n \{\ .RE .\} .SH "LOGGING" .sp .if n \{\ .RS 4 .\} .nf logging { category \fIstring\fR { \fIstring\fR; \&.\&.\&. }; channel \fIstring\fR { buffered \fIboolean\fR; file \fIquoted_string\fR [ versions ( "unlimited" | \fIinteger\fR ) ] [ size \fIsize\fR ]; null; print\-category \fIboolean\fR; print\-severity \fIboolean\fR; print\-time \fIboolean\fR; severity \fIlog_severity\fR; stderr; syslog [ \fIsyslog_facility\fR ]; }; }; .fi .if n \{\ .RE .\} .SH "LWRES" .sp .if n \{\ .RS 4 .\} .nf lwres { listen\-on [ port \fIinteger\fR ] [ dscp \fIinteger\fR ] { ( \fIipv4_address\fR | \fIipv6_address\fR ) [ port \fIinteger\fR ] [ dscp \fIinteger\fR ]; \&.\&.\&. }; lwres\-clients \fIinteger\fR; lwres\-tasks \fIinteger\fR; ndots \fIinteger\fR; search { \fIstring\fR; \&.\&.\&. }; view \fIstring\fR [ \fIclass\fR ]; }; .fi .if n \{\ .RE .\} .SH "MANAGED-KEYS" .sp .if n \{\ .RS 4 .\} .nf managed\-keys { \fIstring\fR \fIstring\fR \fIinteger\fR \fIinteger\fR \fIinteger\fR \fIquoted_string\fR; \&.\&.\&. }; .fi .if n \{\ .RE .\} .SH "MASTERS" .sp .if n \{\ .RS 4 .\} .nf masters \fIstring\fR [ port \fIinteger\fR ] [ dscp \fIinteger\fR ] { ( \fImasters\fR | \fIipv4_address\fR [ port \fIinteger\fR ] | \fIipv6_address\fR [ port \fIinteger\fR ] ) [ key \fIstring\fR ]; \&.\&.\&. }; .fi .if n \{\ .RE .\} .SH "OPTIONS" .sp .if n \{\ .RS 4 .\} .nf options { acache\-cleaning\-interval \fIinteger\fR; acache\-enable \fIboolean\fR; additional\-from\-auth \fIboolean\fR; additional\-from\-cache \fIboolean\fR; allow\-new\-zones \fIboolean\fR; allow\-notify { \fIaddress_match_element\fR; \&.\&.\&. }; allow\-query { \fIaddress_match_element\fR; \&.\&.\&. }; allow\-query\-cache { \fIaddress_match_element\fR; \&.\&.\&. }; allow\-query\-cache\-on { \fIaddress_match_element\fR; \&.\&.\&. }; allow\-query\-on { \fIaddress_match_element\fR; \&.\&.\&. }; allow\-recursion { \fIaddress_match_element\fR; \&.\&.\&. }; allow\-recursion\-on { \fIaddress_match_element\fR; \&.\&.\&. }; allow\-transfer { \fIaddress_match_element\fR; \&.\&.\&. }; allow\-update { \fIaddress_match_element\fR; \&.\&.\&. }; allow\-update\-forwarding { \fIaddress_match_element\fR; \&.\&.\&. }; also\-notify [ port \fIinteger\fR ] [ dscp \fIinteger\fR ] { ( \fImasters\fR | \fIipv4_address\fR [ port \fIinteger\fR ] | \fIipv6_address\fR [ port \fIinteger\fR ] ) [ key \fIstring\fR ]; \&.\&.\&. }; alt\-transfer\-source ( \fIipv4_address\fR | * ) [ port ( \fIinteger\fR | * ) ] [ dscp \fIinteger\fR ]; alt\-transfer\-source\-v6 ( \fIipv6_address\fR | * ) [ port ( \fIinteger\fR | * ) ] [ dscp \fIinteger\fR ]; attach\-cache \fIstring\fR; auth\-nxdomain \fIboolean\fR; // default changed auto\-dnssec ( allow | maintain | off ); automatic\-interface\-scan \fIboolean\fR; avoid\-v4\-udp\-ports { \fIportrange\fR; \&.\&.\&. }; avoid\-v6\-udp\-ports { \fIportrange\fR; \&.\&.\&. }; bindkeys\-file \fIquoted_string\fR; blackhole { \fIaddress_match_element\fR; \&.\&.\&. }; cache\-file \fIquoted_string\fR; catalog\-zones { zone \fIquoted_string\fR [ default\-masters [ port \fIinteger\fR ] [ dscp \fIinteger\fR ] { ( \fImasters\fR | \fIipv4_address\fR [ port \fIinteger\fR ] | \fIipv6_address\fR [ port \fIinteger\fR ] ) [ key \fIstring\fR ]; \&.\&.\&. } ] [ zone\-directory \fIquoted_string\fR ] [ in\-memory \fIboolean\fR ] [ min\-update\-interval \fIinteger\fR ]; \&.\&.\&. }; check\-dup\-records ( fail | warn | ignore ); check\-integrity \fIboolean\fR; check\-mx ( fail | warn | ignore ); check\-mx\-cname ( fail | warn | ignore ); check\-names ( master | slave | response ) ( fail | warn | ignore ); check\-sibling \fIboolean\fR; check\-spf ( warn | ignore ); check\-srv\-cname ( fail | warn | ignore ); check\-wildcard \fIboolean\fR; cleaning\-interval \fIinteger\fR; clients\-per\-query \fIinteger\fR; cookie\-algorithm ( aes | sha1 | sha256 ); cookie\-secret \fIstring\fR; coresize ( default | unlimited | \fIsizeval\fR ); datasize ( default | unlimited | \fIsizeval\fR ); deny\-answer\-addresses { \fIaddress_match_element\fR; \&.\&.\&. } [ except\-from { \fIquoted_string\fR; \&.\&.\&. } ]; deny\-answer\-aliases { \fIquoted_string\fR; \&.\&.\&. } [ except\-from { \fIquoted_string\fR; \&.\&.\&. } ]; dialup ( notify | notify\-passive | passive | refresh | \fIboolean\fR ); directory \fIquoted_string\fR; disable\-algorithms \fIstring\fR { \fIstring\fR; \&.\&.\&. }; disable\-ds\-digests \fIstring\fR { \fIstring\fR; \&.\&.\&. }; disable\-empty\-zone \fIstring\fR; dns64 \fInetprefix\fR { break\-dnssec \fIboolean\fR; clients { \fIaddress_match_element\fR; \&.\&.\&. }; exclude { \fIaddress_match_element\fR; \&.\&.\&. }; mapped { \fIaddress_match_element\fR; \&.\&.\&. }; recursive\-only \fIboolean\fR; suffix \fIipv6_address\fR; }; dns64\-contact \fIstring\fR; dns64\-server \fIstring\fR; dnssec\-accept\-expired \fIboolean\fR; dnssec\-dnskey\-kskonly \fIboolean\fR; dnssec\-enable \fIboolean\fR; dnssec\-loadkeys\-interval \fIinteger\fR; dnssec\-lookaside ( \fIstring\fR trust\-anchor \fIstring\fR | auto | no ); dnssec\-must\-be\-secure \fIstring\fR \fIboolean\fR; dnssec\-secure\-to\-insecure \fIboolean\fR; dnssec\-update\-mode ( maintain | no\-resign ); dnssec\-validation ( yes | no | auto ); dnstap { ( all | auth | client | forwarder | resolver ) [ ( query | response ) ]; \&.\&.\&. }; dnstap\-identity ( \fIquoted_string\fR | none | hostname ); dnstap\-output ( file | unix ) \fIquoted_string\fR; dnstap\-version ( \fIquoted_string\fR | none ); dscp \fIinteger\fR; dual\-stack\-servers [ port \fIinteger\fR ] { ( \fIquoted_string\fR [ port \fIinteger\fR ] [ dscp \fIinteger\fR ] | \fIipv4_address\fR [ port \fIinteger\fR ] [ dscp \fIinteger\fR ] | \fIipv6_address\fR [ port \fIinteger\fR ] [ dscp \fIinteger\fR ] ); \&.\&.\&. }; dump\-file \fIquoted_string\fR; edns\-udp\-size \fIinteger\fR; empty\-contact \fIstring\fR; empty\-server \fIstring\fR; empty\-zones\-enable \fIboolean\fR; fetch\-quota\-params \fIinteger\fR \fIfixedpoint\fR \fIfixedpoint\fR \fIfixedpoint\fR; fetches\-per\-server \fIinteger\fR [ ( drop | fail ) ]; fetches\-per\-zone \fIinteger\fR [ ( drop | fail ) ]; files ( default | unlimited | \fIsizeval\fR ); filter\-aaaa { \fIaddress_match_element\fR; \&.\&.\&. }; filter\-aaaa\-on\-v4 ( break\-dnssec | \fIboolean\fR ); filter\-aaaa\-on\-v6 ( break\-dnssec | \fIboolean\fR ); flush\-zones\-on\-shutdown \fIboolean\fR; forward ( first | only ); forwarders [ port \fIinteger\fR ] [ dscp \fIinteger\fR ] { ( \fIipv4_address\fR | \fIipv6_address\fR ) [ port \fIinteger\fR ] [ dscp \fIinteger\fR ]; \&.\&.\&. }; fstrm\-set\-buffer\-hint \fIinteger\fR; fstrm\-set\-flush\-timeout \fIinteger\fR; fstrm\-set\-input\-queue\-size \fIinteger\fR; fstrm\-set\-output\-notify\-threshold \fIinteger\fR; fstrm\-set\-output\-queue\-model ( mpsc | spsc ); fstrm\-set\-output\-queue\-size \fIinteger\fR; fstrm\-set\-reopen\-interval \fIinteger\fR; geoip\-directory ( \fIquoted_string\fR | none ); geoip\-use\-ecs \fIboolean\fR; heartbeat\-interval \fIinteger\fR; hostname ( \fIquoted_string\fR | none ); inline\-signing \fIboolean\fR; interface\-interval \fIinteger\fR; ixfr\-from\-differences ( master | slave | \fIboolean\fR ); keep\-response\-order { \fIaddress_match_element\fR; \&.\&.\&. }; key\-directory \fIquoted_string\fR; lame\-ttl \fIttlval\fR; listen\-on [ port \fIinteger\fR ] [ dscp \fIinteger\fR ] { \fIaddress_match_element\fR; \&.\&.\&. }; listen\-on\-v6 [ port \fIinteger\fR ] [ dscp \fIinteger\fR ] { \fIaddress_match_element\fR; \&.\&.\&. }; lmdb\-mapsize \fIsizeval\fR; lock\-file ( \fIquoted_string\fR | none ); managed\-keys\-directory \fIquoted_string\fR; masterfile\-format ( map | raw | text ); masterfile\-style ( full | relative ); match\-mapped\-addresses \fIboolean\fR; max\-acache\-size ( unlimited | \fIsizeval\fR ); max\-cache\-size ( default | unlimited | \fIsizeval\fR | \fIpercentage\fR ); max\-cache\-ttl \fIinteger\fR; max\-clients\-per\-query \fIinteger\fR; max\-journal\-size ( unlimited | \fIsizeval\fR ); max\-ncache\-ttl \fIinteger\fR; max\-records \fIinteger\fR; max\-recursion\-depth \fIinteger\fR; max\-recursion\-queries \fIinteger\fR; max\-refresh\-time \fIinteger\fR; max\-retry\-time \fIinteger\fR; max\-rsa\-exponent\-size \fIinteger\fR; max\-transfer\-idle\-in \fIinteger\fR; max\-transfer\-idle\-out \fIinteger\fR; max\-transfer\-time\-in \fIinteger\fR; max\-transfer\-time\-out \fIinteger\fR; max\-udp\-size \fIinteger\fR; max\-zone\-ttl ( unlimited | \fIttlval\fR ); memstatistics \fIboolean\fR; memstatistics\-file \fIquoted_string\fR; message\-compression \fIboolean\fR; min\-refresh\-time \fIinteger\fR; min\-retry\-time \fIinteger\fR; minimal\-any \fIboolean\fR; minimal\-responses ( no\-auth | no\-auth\-recursive | \fIboolean\fR ); multi\-master \fIboolean\fR; no\-case\-compress { \fIaddress_match_element\fR; \&.\&.\&. }; nocookie\-udp\-size \fIinteger\fR; notify ( explicit | master\-only | \fIboolean\fR ); notify\-delay \fIinteger\fR; notify\-rate \fIinteger\fR; notify\-source ( \fIipv4_address\fR | * ) [ port ( \fIinteger\fR | * ) ] [ dscp \fIinteger\fR ]; notify\-source\-v6 ( \fIipv6_address\fR | * ) [ port ( \fIinteger\fR | * ) ] [ dscp \fIinteger\fR ]; notify\-to\-soa \fIboolean\fR; nta\-lifetime \fIttlval\fR; nta\-recheck \fIttlval\fR; nxdomain\-redirect \fIstring\fR; pid\-file ( \fIquoted_string\fR | none ); port \fIinteger\fR; preferred\-glue \fIstring\fR; prefetch \fIinteger\fR [ \fIinteger\fR ]; provide\-ixfr \fIboolean\fR; query\-source ( ( [ address ] ( \fIipv4_address\fR | * ) [ port ( \fIinteger\fR | * ) ] ) | ( [ [ address ] ( \fIipv4_address\fR | * ) ] port ( \fIinteger\fR | * ) ) ) [ dscp \fIinteger\fR ]; query\-source\-v6 ( ( [ address ] ( \fIipv6_address\fR | * ) [ port ( \fIinteger\fR | * ) ] ) | ( [ [ address ] ( \fIipv6_address\fR | * ) ] port ( \fIinteger\fR | * ) ) ) [ dscp \fIinteger\fR ]; querylog \fIboolean\fR; random\-device \fIquoted_string\fR; rate\-limit { all\-per\-second \fIinteger\fR; errors\-per\-second \fIinteger\fR; exempt\-clients { \fIaddress_match_element\fR; \&.\&.\&. }; ipv4\-prefix\-length \fIinteger\fR; ipv6\-prefix\-length \fIinteger\fR; log\-only \fIboolean\fR; max\-table\-size \fIinteger\fR; min\-table\-size \fIinteger\fR; nodata\-per\-second \fIinteger\fR; nxdomains\-per\-second \fIinteger\fR; qps\-scale \fIinteger\fR; referrals\-per\-second \fIinteger\fR; responses\-per\-second \fIinteger\fR; slip \fIinteger\fR; window \fIinteger\fR; }; recursing\-file \fIquoted_string\fR; recursion \fIboolean\fR; recursive\-clients \fIinteger\fR; request\-expire \fIboolean\fR; request\-ixfr \fIboolean\fR; request\-nsid \fIboolean\fR; require\-server\-cookie \fIboolean\fR; reserved\-sockets \fIinteger\fR; resolver\-query\-timeout \fIinteger\fR; response\-policy { zone \fIquoted_string\fR [ log \fIboolean\fR ] [ max\-policy\-ttl \fIinteger\fR ] [ policy ( cname | disabled | drop | given | no\-op | nodata | nxdomain | passthru | tcp\-only \fIquoted_string\fR ) ] [ recursive\-only \fIboolean\fR ]; \&.\&.\&. } [ break\-dnssec \fIboolean\fR ] [ max\-policy\-ttl \fIinteger\fR ] [ min\-ns\-dots \fIinteger\fR ] [ nsip\-wait\-recurse \fIboolean\fR ] [ qname\-wait\-recurse \fIboolean\fR ] [ recursive\-only \fIboolean\fR ]; root\-delegation\-only [ exclude { \fIquoted_string\fR; \&.\&.\&. } ]; rrset\-order { [ class \fIstring\fR ] [ type \fIstring\fR ] [ name \fIquoted_string\fR ] \fIstring\fR \fIstring\fR; \&.\&.\&. }; secroots\-file \fIquoted_string\fR; send\-cookie \fIboolean\fR; serial\-query\-rate \fIinteger\fR; serial\-update\-method ( date | increment | unixtime ); server\-id ( \fIquoted_string\fR | none | hostname ); servfail\-ttl \fIttlval\fR; session\-keyalg \fIstring\fR; session\-keyfile ( \fIquoted_string\fR | none ); session\-keyname \fIstring\fR; sig\-signing\-nodes \fIinteger\fR; sig\-signing\-signatures \fIinteger\fR; sig\-signing\-type \fIinteger\fR; sig\-validity\-interval \fIinteger\fR [ \fIinteger\fR ]; sortlist { \fIaddress_match_element\fR; \&.\&.\&. }; stacksize ( default | unlimited | \fIsizeval\fR ); startup\-notify\-rate \fIinteger\fR; statistics\-file \fIquoted_string\fR; tcp\-clients \fIinteger\fR; tcp\-listen\-queue \fIinteger\fR; tkey\-dhkey \fIquoted_string\fR \fIinteger\fR; tkey\-domain \fIquoted_string\fR; tkey\-gssapi\-credential \fIquoted_string\fR; tkey\-gssapi\-keytab \fIquoted_string\fR; transfer\-format ( many\-answers | one\-answer ); transfer\-message\-size \fIinteger\fR; transfer\-source ( \fIipv4_address\fR | * ) [ port ( \fIinteger\fR | * ) ] [ dscp \fIinteger\fR ]; transfer\-source\-v6 ( \fIipv6_address\fR | * ) [ port ( \fIinteger\fR | * ) ] [ dscp \fIinteger\fR ]; transfers\-in \fIinteger\fR; transfers\-out \fIinteger\fR; transfers\-per\-ns \fIinteger\fR; trust\-anchor\-telemetry \fIboolean\fR; // experimental try\-tcp\-refresh \fIboolean\fR; update\-check\-ksk \fIboolean\fR; use\-alt\-transfer\-source \fIboolean\fR; use\-v4\-udp\-ports { \fIportrange\fR; \&.\&.\&. }; use\-v6\-udp\-ports { \fIportrange\fR; \&.\&.\&. }; v6\-bias \fIinteger\fR; version ( \fIquoted_string\fR | none ); zero\-no\-soa\-ttl \fIboolean\fR; zero\-no\-soa\-ttl\-cache \fIboolean\fR; zone\-statistics ( full | terse | none | \fIboolean\fR ); }; .fi .if n \{\ .RE .\} .SH "SERVER" .sp .if n \{\ .RS 4 .\} .nf server \fInetprefix\fR { bogus \fIboolean\fR; edns \fIboolean\fR; edns\-udp\-size \fIinteger\fR; edns\-version \fIinteger\fR; keys \fIserver_key\fR; max\-udp\-size \fIinteger\fR; notify\-source ( \fIipv4_address\fR | * ) [ port ( \fIinteger\fR | * ) ] [ dscp \fIinteger\fR ]; notify\-source\-v6 ( \fIipv6_address\fR | * ) [ port ( \fIinteger\fR | * ) ] [ dscp \fIinteger\fR ]; provide\-ixfr \fIboolean\fR; query\-source ( ( [ address ] ( \fIipv4_address\fR | * ) [ port ( \fIinteger\fR | * ) ] ) | ( [ [ address ] ( \fIipv4_address\fR | * ) ] port ( \fIinteger\fR | * ) ) ) [ dscp \fIinteger\fR ]; query\-source\-v6 ( ( [ address ] ( \fIipv6_address\fR | * ) [ port ( \fIinteger\fR | * ) ] ) | ( [ [ address ] ( \fIipv6_address\fR | * ) ] port ( \fIinteger\fR | * ) ) ) [ dscp \fIinteger\fR ]; request\-expire \fIboolean\fR; request\-ixfr \fIboolean\fR; request\-nsid \fIboolean\fR; send\-cookie \fIboolean\fR; tcp\-only \fIboolean\fR; transfer\-format ( many\-answers | one\-answer ); transfer\-source ( \fIipv4_address\fR | * ) [ port ( \fIinteger\fR | * ) ] [ dscp \fIinteger\fR ]; transfer\-source\-v6 ( \fIipv6_address\fR | * ) [ port ( \fIinteger\fR | * ) ] [ dscp \fIinteger\fR ]; transfers \fIinteger\fR; }; .fi .if n \{\ .RE .\} .SH "STATISTICS-CHANNELS" .sp .if n \{\ .RS 4 .\} .nf statistics\-channels { inet ( \fIipv4_address\fR | \fIipv6_address\fR | * ) [ port ( \fIinteger\fR | * ) ] [ allow { \fIaddress_match_element\fR; \&.\&.\&. } ]; }; .fi .if n \{\ .RE .\} .SH "TRUSTED-KEYS" .sp .if n \{\ .RS 4 .\} .nf trusted\-keys { \fIstring\fR \fIinteger\fR \fIinteger\fR \fIinteger\fR \fIquoted_string\fR; \&.\&.\&. }; .fi .if n \{\ .RE .\} .SH "VIEW" .sp .if n \{\ .RS 4 .\} .nf view \fIstring\fR [ \fIclass\fR ] { acache\-cleaning\-interval \fIinteger\fR; acache\-enable \fIboolean\fR; additional\-from\-auth \fIboolean\fR; additional\-from\-cache \fIboolean\fR; allow\-new\-zones \fIboolean\fR; allow\-notify { \fIaddress_match_element\fR; \&.\&.\&. }; allow\-query { \fIaddress_match_element\fR; \&.\&.\&. }; allow\-query\-cache { \fIaddress_match_element\fR; \&.\&.\&. }; allow\-query\-cache\-on { \fIaddress_match_element\fR; \&.\&.\&. }; allow\-query\-on { \fIaddress_match_element\fR; \&.\&.\&. }; allow\-recursion { \fIaddress_match_element\fR; \&.\&.\&. }; allow\-recursion\-on { \fIaddress_match_element\fR; \&.\&.\&. }; allow\-transfer { \fIaddress_match_element\fR; \&.\&.\&. }; allow\-update { \fIaddress_match_element\fR; \&.\&.\&. }; allow\-update\-forwarding { \fIaddress_match_element\fR; \&.\&.\&. }; also\-notify [ port \fIinteger\fR ] [ dscp \fIinteger\fR ] { ( \fImasters\fR | \fIipv4_address\fR [ port \fIinteger\fR ] | \fIipv6_address\fR [ port \fIinteger\fR ] ) [ key \fIstring\fR ]; \&.\&.\&. }; alt\-transfer\-source ( \fIipv4_address\fR | * ) [ port ( \fIinteger\fR | * ) ] [ dscp \fIinteger\fR ]; alt\-transfer\-source\-v6 ( \fIipv6_address\fR | * ) [ port ( \fIinteger\fR | * ) ] [ dscp \fIinteger\fR ]; attach\-cache \fIstring\fR; auth\-nxdomain \fIboolean\fR; // default changed auto\-dnssec ( allow | maintain | off ); cache\-file \fIquoted_string\fR; catalog\-zones { zone \fIquoted_string\fR [ default\-masters [ port \fIinteger\fR ] [ dscp \fIinteger\fR ] { ( \fImasters\fR | \fIipv4_address\fR [ port \fIinteger\fR ] | \fIipv6_address\fR [ port \fIinteger\fR ] ) [ key \fIstring\fR ]; \&.\&.\&. } ] [ zone\-directory \fIquoted_string\fR ] [ in\-memory \fIboolean\fR ] [ min\-update\-interval \fIinteger\fR ]; \&.\&.\&. }; check\-dup\-records ( fail | warn | ignore ); check\-integrity \fIboolean\fR; check\-mx ( fail | warn | ignore ); check\-mx\-cname ( fail | warn | ignore ); check\-names ( master | slave | response ) ( fail | warn | ignore ); check\-sibling \fIboolean\fR; check\-spf ( warn | ignore ); check\-srv\-cname ( fail | warn | ignore ); check\-wildcard \fIboolean\fR; cleaning\-interval \fIinteger\fR; clients\-per\-query \fIinteger\fR; deny\-answer\-addresses { \fIaddress_match_element\fR; \&.\&.\&. } [ except\-from { \fIquoted_string\fR; \&.\&.\&. } ]; deny\-answer\-aliases { \fIquoted_string\fR; \&.\&.\&. } [ except\-from { \fIquoted_string\fR; \&.\&.\&. } ]; dialup ( notify | notify\-passive | passive | refresh | \fIboolean\fR ); disable\-algorithms \fIstring\fR { \fIstring\fR; \&.\&.\&. }; disable\-ds\-digests \fIstring\fR { \fIstring\fR; \&.\&.\&. }; disable\-empty\-zone \fIstring\fR; dlz \fIstring\fR { database \fIstring\fR; search \fIboolean\fR; }; dns64 \fInetprefix\fR { break\-dnssec \fIboolean\fR; clients { \fIaddress_match_element\fR; \&.\&.\&. }; exclude { \fIaddress_match_element\fR; \&.\&.\&. }; mapped { \fIaddress_match_element\fR; \&.\&.\&. }; recursive\-only \fIboolean\fR; suffix \fIipv6_address\fR; }; dns64\-contact \fIstring\fR; dns64\-server \fIstring\fR; dnssec\-accept\-expired \fIboolean\fR; dnssec\-dnskey\-kskonly \fIboolean\fR; dnssec\-enable \fIboolean\fR; dnssec\-loadkeys\-interval \fIinteger\fR; dnssec\-lookaside ( \fIstring\fR trust\-anchor \fIstring\fR | auto | no ); dnssec\-must\-be\-secure \fIstring\fR \fIboolean\fR; dnssec\-secure\-to\-insecure \fIboolean\fR; dnssec\-update\-mode ( maintain | no\-resign ); dnssec\-validation ( yes | no | auto ); dnstap { ( all | auth | client | forwarder | resolver ) [ ( query | response ) ]; \&.\&.\&. }; dual\-stack\-servers [ port \fIinteger\fR ] { ( \fIquoted_string\fR [ port \fIinteger\fR ] [ dscp \fIinteger\fR ] | \fIipv4_address\fR [ port \fIinteger\fR ] [ dscp \fIinteger\fR ] | \fIipv6_address\fR [ port \fIinteger\fR ] [ dscp \fIinteger\fR ] ); \&.\&.\&. }; dyndb \fIstring\fR \fIquoted_string\fR { \fIunspecified\-text\fR }; edns\-udp\-size \fIinteger\fR; empty\-contact \fIstring\fR; empty\-server \fIstring\fR; empty\-zones\-enable \fIboolean\fR; fetch\-quota\-params \fIinteger\fR \fIfixedpoint\fR \fIfixedpoint\fR \fIfixedpoint\fR; fetches\-per\-server \fIinteger\fR [ ( drop | fail ) ]; fetches\-per\-zone \fIinteger\fR [ ( drop | fail ) ]; filter\-aaaa { \fIaddress_match_element\fR; \&.\&.\&. }; filter\-aaaa\-on\-v4 ( break\-dnssec | \fIboolean\fR ); filter\-aaaa\-on\-v6 ( break\-dnssec | \fIboolean\fR ); forward ( first | only ); forwarders [ port \fIinteger\fR ] [ dscp \fIinteger\fR ] { ( \fIipv4_address\fR | \fIipv6_address\fR ) [ port \fIinteger\fR ] [ dscp \fIinteger\fR ]; \&.\&.\&. }; inline\-signing \fIboolean\fR; ixfr\-from\-differences ( master | slave | \fIboolean\fR ); key \fIstring\fR { algorithm \fIstring\fR; secret \fIstring\fR; }; key\-directory \fIquoted_string\fR; lame\-ttl \fIttlval\fR; lmdb\-mapsize \fIsizeval\fR; managed\-keys { \fIstring\fR \fIstring\fR \fIinteger\fR \fIinteger\fR \fIinteger\fR \fIquoted_string\fR; \&.\&.\&. }; masterfile\-format ( map | raw | text ); masterfile\-style ( full | relative ); match\-clients { \fIaddress_match_element\fR; \&.\&.\&. }; match\-destinations { \fIaddress_match_element\fR; \&.\&.\&. }; match\-recursive\-only \fIboolean\fR; max\-acache\-size ( unlimited | \fIsizeval\fR ); max\-cache\-size ( default | unlimited | \fIsizeval\fR | \fIpercentage\fR ); max\-cache\-ttl \fIinteger\fR; max\-clients\-per\-query \fIinteger\fR; max\-journal\-size ( unlimited | \fIsizeval\fR ); max\-ncache\-ttl \fIinteger\fR; max\-records \fIinteger\fR; max\-recursion\-depth \fIinteger\fR; max\-recursion\-queries \fIinteger\fR; max\-refresh\-time \fIinteger\fR; max\-retry\-time \fIinteger\fR; max\-transfer\-idle\-in \fIinteger\fR; max\-transfer\-idle\-out \fIinteger\fR; max\-transfer\-time\-in \fIinteger\fR; max\-transfer\-time\-out \fIinteger\fR; max\-udp\-size \fIinteger\fR; max\-zone\-ttl ( unlimited | \fIttlval\fR ); message\-compression \fIboolean\fR; min\-refresh\-time \fIinteger\fR; min\-retry\-time \fIinteger\fR; minimal\-any \fIboolean\fR; minimal\-responses ( no\-auth | no\-auth\-recursive | \fIboolean\fR ); multi\-master \fIboolean\fR; no\-case\-compress { \fIaddress_match_element\fR; \&.\&.\&. }; nocookie\-udp\-size \fIinteger\fR; notify ( explicit | master\-only | \fIboolean\fR ); notify\-delay \fIinteger\fR; notify\-source ( \fIipv4_address\fR | * ) [ port ( \fIinteger\fR | * ) ] [ dscp \fIinteger\fR ]; notify\-source\-v6 ( \fIipv6_address\fR | * ) [ port ( \fIinteger\fR | * ) ] [ dscp \fIinteger\fR ]; notify\-to\-soa \fIboolean\fR; nta\-lifetime \fIttlval\fR; nta\-recheck \fIttlval\fR; nxdomain\-redirect \fIstring\fR; preferred\-glue \fIstring\fR; prefetch \fIinteger\fR [ \fIinteger\fR ]; provide\-ixfr \fIboolean\fR; query\-source ( ( [ address ] ( \fIipv4_address\fR | * ) [ port ( \fIinteger\fR | * ) ] ) | ( [ [ address ] ( \fIipv4_address\fR | * ) ] port ( \fIinteger\fR | * ) ) ) [ dscp \fIinteger\fR ]; query\-source\-v6 ( ( [ address ] ( \fIipv6_address\fR | * ) [ port ( \fIinteger\fR | * ) ] ) | ( [ [ address ] ( \fIipv6_address\fR | * ) ] port ( \fIinteger\fR | * ) ) ) [ dscp \fIinteger\fR ]; rate\-limit { all\-per\-second \fIinteger\fR; errors\-per\-second \fIinteger\fR; exempt\-clients { \fIaddress_match_element\fR; \&.\&.\&. }; ipv4\-prefix\-length \fIinteger\fR; ipv6\-prefix\-length \fIinteger\fR; log\-only \fIboolean\fR; max\-table\-size \fIinteger\fR; min\-table\-size \fIinteger\fR; nodata\-per\-second \fIinteger\fR; nxdomains\-per\-second \fIinteger\fR; qps\-scale \fIinteger\fR; referrals\-per\-second \fIinteger\fR; responses\-per\-second \fIinteger\fR; slip \fIinteger\fR; window \fIinteger\fR; }; recursion \fIboolean\fR; request\-expire \fIboolean\fR; request\-ixfr \fIboolean\fR; request\-nsid \fIboolean\fR; require\-server\-cookie \fIboolean\fR; resolver\-query\-timeout \fIinteger\fR; response\-policy { zone \fIquoted_string\fR [ log \fIboolean\fR ] [ max\-policy\-ttl \fIinteger\fR ] [ policy ( cname | disabled | drop | given | no\-op | nodata | nxdomain | passthru | tcp\-only \fIquoted_string\fR ) ] [ recursive\-only \fIboolean\fR ]; \&.\&.\&. } [ break\-dnssec \fIboolean\fR ] [ max\-policy\-ttl \fIinteger\fR ] [ min\-ns\-dots \fIinteger\fR ] [ nsip\-wait\-recurse \fIboolean\fR ] [ qname\-wait\-recurse \fIboolean\fR ] [ recursive\-only \fIboolean\fR ]; root\-delegation\-only [ exclude { \fIquoted_string\fR; \&.\&.\&. } ]; rrset\-order { [ class \fIstring\fR ] [ type \fIstring\fR ] [ name \fIquoted_string\fR ] \fIstring\fR \fIstring\fR; \&.\&.\&. }; send\-cookie \fIboolean\fR; serial\-update\-method ( date | increment | unixtime ); server \fInetprefix\fR { bogus \fIboolean\fR; edns \fIboolean\fR; edns\-udp\-size \fIinteger\fR; edns\-version \fIinteger\fR; keys \fIserver_key\fR; max\-udp\-size \fIinteger\fR; notify\-source ( \fIipv4_address\fR | * ) [ port ( \fIinteger\fR | * ) ] [ dscp \fIinteger\fR ]; notify\-source\-v6 ( \fIipv6_address\fR | * ) [ port ( \fIinteger\fR | * ) ] [ dscp \fIinteger\fR ]; provide\-ixfr \fIboolean\fR; query\-source ( ( [ address ] ( \fIipv4_address\fR | * ) [ port ( \fIinteger\fR | * ) ] ) | ( [ [ address ] ( \fIipv4_address\fR | * ) ] port ( \fIinteger\fR | * ) ) ) [ dscp \fIinteger\fR ]; query\-source\-v6 ( ( [ address ] ( \fIipv6_address\fR | * ) [ port ( \fIinteger\fR | * ) ] ) | ( [ [ address ] ( \fIipv6_address\fR | * ) ] port ( \fIinteger\fR | * ) ) ) [ dscp \fIinteger\fR ]; request\-expire \fIboolean\fR; request\-ixfr \fIboolean\fR; request\-nsid \fIboolean\fR; send\-cookie \fIboolean\fR; tcp\-only \fIboolean\fR; transfer\-format ( many\-answers | one\-answer ); transfer\-source ( \fIipv4_address\fR | * ) [ port ( \fIinteger\fR | * ) ] [ dscp \fIinteger\fR ]; transfer\-source\-v6 ( \fIipv6_address\fR | * ) [ port ( \fIinteger\fR | * ) ] [ dscp \fIinteger\fR ]; transfers \fIinteger\fR; }; servfail\-ttl \fIttlval\fR; sig\-signing\-nodes \fIinteger\fR; sig\-signing\-signatures \fIinteger\fR; sig\-signing\-type \fIinteger\fR; sig\-validity\-interval \fIinteger\fR [ \fIinteger\fR ]; sortlist { \fIaddress_match_element\fR; \&.\&.\&. }; transfer\-format ( many\-answers | one\-answer ); transfer\-source ( \fIipv4_address\fR | * ) [ port ( \fIinteger\fR | * ) ] [ dscp \fIinteger\fR ]; transfer\-source\-v6 ( \fIipv6_address\fR | * ) [ port ( \fIinteger\fR | * ) ] [ dscp \fIinteger\fR ]; trust\-anchor\-telemetry \fIboolean\fR; // experimental trusted\-keys { \fIstring\fR \fIinteger\fR \fIinteger\fR \fIinteger\fR \fIquoted_string\fR; \&.\&.\&. }; try\-tcp\-refresh \fIboolean\fR; update\-check\-ksk \fIboolean\fR; use\-alt\-transfer\-source \fIboolean\fR; v6\-bias \fIinteger\fR; zero\-no\-soa\-ttl \fIboolean\fR; zero\-no\-soa\-ttl\-cache \fIboolean\fR; zone \fIstring\fR [ \fIclass\fR ] { allow\-notify { \fIaddress_match_element\fR; \&.\&.\&. }; allow\-query { \fIaddress_match_element\fR; \&.\&.\&. }; allow\-query\-on { \fIaddress_match_element\fR; \&.\&.\&. }; allow\-transfer { \fIaddress_match_element\fR; \&.\&.\&. }; allow\-update { \fIaddress_match_element\fR; \&.\&.\&. }; allow\-update\-forwarding { \fIaddress_match_element\fR; \&.\&.\&. }; also\-notify [ port \fIinteger\fR ] [ dscp \fIinteger\fR ] { ( \fImasters\fR | \fIipv4_address\fR [ port \fIinteger\fR ] | \fIipv6_address\fR [ port \fIinteger\fR ] ) [ key \fIstring\fR ]; \&.\&.\&. }; alt\-transfer\-source ( \fIipv4_address\fR | * ) [ port ( \fIinteger\fR | * ) ] [ dscp \fIinteger\fR ]; alt\-transfer\-source\-v6 ( \fIipv6_address\fR | * ) [ port ( \fIinteger\fR | * ) ] [ dscp \fIinteger\fR ]; auto\-dnssec ( allow | maintain | off ); check\-dup\-records ( fail | warn | ignore ); check\-integrity \fIboolean\fR; check\-mx ( fail | warn | ignore ); check\-mx\-cname ( fail | warn | ignore ); check\-names ( fail | warn | ignore ); check\-sibling \fIboolean\fR; check\-spf ( warn | ignore ); check\-srv\-cname ( fail | warn | ignore ); check\-wildcard \fIboolean\fR; database \fIstring\fR; delegation\-only \fIboolean\fR; dialup ( notify | notify\-passive | passive | refresh | \fIboolean\fR ); dlz \fIstring\fR; dnssec\-dnskey\-kskonly \fIboolean\fR; dnssec\-loadkeys\-interval \fIinteger\fR; dnssec\-secure\-to\-insecure \fIboolean\fR; dnssec\-update\-mode ( maintain | no\-resign ); file \fIquoted_string\fR; forward ( first | only ); forwarders [ port \fIinteger\fR ] [ dscp \fIinteger\fR ] { ( \fIipv4_address\fR | \fIipv6_address\fR ) [ port \fIinteger\fR ] [ dscp \fIinteger\fR ]; \&.\&.\&. }; in\-view \fIstring\fR; inline\-signing \fIboolean\fR; ixfr\-from\-differences \fIboolean\fR; journal \fIquoted_string\fR; key\-directory \fIquoted_string\fR; masterfile\-format ( map | raw | text ); masterfile\-style ( full | relative ); masters [ port \fIinteger\fR ] [ dscp \fIinteger\fR ] { ( \fImasters\fR | \fIipv4_address\fR [ port \fIinteger\fR ] | \fIipv6_address\fR [ port \fIinteger\fR ] ) [ key \fIstring\fR ]; \&.\&.\&. }; max\-ixfr\-log\-size ( default | unlimited | max\-journal\-size ( unlimited | \fIsizeval\fR ); max\-records \fIinteger\fR; max\-refresh\-time \fIinteger\fR; max\-retry\-time \fIinteger\fR; max\-transfer\-idle\-in \fIinteger\fR; max\-transfer\-idle\-out \fIinteger\fR; max\-transfer\-time\-in \fIinteger\fR; max\-transfer\-time\-out \fIinteger\fR; max\-zone\-ttl ( unlimited | \fIttlval\fR ); min\-refresh\-time \fIinteger\fR; min\-retry\-time \fIinteger\fR; multi\-master \fIboolean\fR; notify ( explicit | master\-only | \fIboolean\fR ); notify\-delay \fIinteger\fR; notify\-source ( \fIipv4_address\fR | * ) [ port ( \fIinteger\fR | * ) ] [ dscp \fIinteger\fR ]; notify\-source\-v6 ( \fIipv6_address\fR | * ) [ port ( \fIinteger\fR | * ) ] [ dscp \fIinteger\fR ]; notify\-to\-soa \fIboolean\fR; pubkey \fIinteger\fR \fIinteger\fR \fIinteger\fR request\-expire \fIboolean\fR; request\-ixfr \fIboolean\fR; serial\-update\-method ( date | increment | unixtime ); server\-addresses { ( \fIipv4_address\fR | \fIipv6_address\fR ) [ port \fIinteger\fR ]; \&.\&.\&. }; server\-names { \fIquoted_string\fR; \&.\&.\&. }; sig\-signing\-nodes \fIinteger\fR; sig\-signing\-signatures \fIinteger\fR; sig\-signing\-type \fIinteger\fR; sig\-validity\-interval \fIinteger\fR [ \fIinteger\fR ]; transfer\-source ( \fIipv4_address\fR | * ) [ port ( \fIinteger\fR | * ) ] [ dscp \fIinteger\fR ]; transfer\-source\-v6 ( \fIipv6_address\fR | * ) [ port ( \fIinteger\fR | * ) ] [ dscp \fIinteger\fR ]; try\-tcp\-refresh \fIboolean\fR; type ( delegation\-only | forward | hint | master | redirect | slave | static\-stub | stub ); update\-check\-ksk \fIboolean\fR; update\-policy ( local | { ( deny | grant ) \fIstring\fR ( 6to4\-self | external | krb5\-self | krb5\-subdomain | ms\-self | ms\-subdomain | name | self | selfsub | selfwild | subdomain | tcp\-self | wildcard | zonesub ) [ \fIstring\fR ] \fIrrtypelist\fR; \&.\&.\&. }; use\-alt\-transfer\-source \fIboolean\fR; zero\-no\-soa\-ttl \fIboolean\fR; zone\-statistics ( full | terse | none | \fIboolean\fR ); }; zone\-statistics ( full | terse | none | \fIboolean\fR ); }; .fi .if n \{\ .RE .\} .SH "ZONE" .sp .if n \{\ .RS 4 .\} .nf zone \fIstring\fR [ \fIclass\fR ] { allow\-notify { \fIaddress_match_element\fR; \&.\&.\&. }; allow\-query { \fIaddress_match_element\fR; \&.\&.\&. }; allow\-query\-on { \fIaddress_match_element\fR; \&.\&.\&. }; allow\-transfer { \fIaddress_match_element\fR; \&.\&.\&. }; allow\-update { \fIaddress_match_element\fR; \&.\&.\&. }; allow\-update\-forwarding { \fIaddress_match_element\fR; \&.\&.\&. }; also\-notify [ port \fIinteger\fR ] [ dscp \fIinteger\fR ] { ( \fImasters\fR | \fIipv4_address\fR [ port \fIinteger\fR ] | \fIipv6_address\fR [ port \fIinteger\fR ] ) [ key \fIstring\fR ]; \&.\&.\&. }; alt\-transfer\-source ( \fIipv4_address\fR | * ) [ port ( \fIinteger\fR | * ) ] [ dscp \fIinteger\fR ]; alt\-transfer\-source\-v6 ( \fIipv6_address\fR | * ) [ port ( \fIinteger\fR | * ) ] [ dscp \fIinteger\fR ]; auto\-dnssec ( allow | maintain | off ); check\-dup\-records ( fail | warn | ignore ); check\-integrity \fIboolean\fR; check\-mx ( fail | warn | ignore ); check\-mx\-cname ( fail | warn | ignore ); check\-names ( fail | warn | ignore ); check\-sibling \fIboolean\fR; check\-spf ( warn | ignore ); check\-srv\-cname ( fail | warn | ignore ); check\-wildcard \fIboolean\fR; database \fIstring\fR; delegation\-only \fIboolean\fR; dialup ( notify | notify\-passive | passive | refresh | \fIboolean\fR ); dlz \fIstring\fR; dnssec\-dnskey\-kskonly \fIboolean\fR; dnssec\-loadkeys\-interval \fIinteger\fR; dnssec\-secure\-to\-insecure \fIboolean\fR; dnssec\-update\-mode ( maintain | no\-resign ); file \fIquoted_string\fR; forward ( first | only ); forwarders [ port \fIinteger\fR ] [ dscp \fIinteger\fR ] { ( \fIipv4_address\fR | \fIipv6_address\fR ) [ port \fIinteger\fR ] [ dscp \fIinteger\fR ]; \&.\&.\&. }; in\-view \fIstring\fR; inline\-signing \fIboolean\fR; ixfr\-from\-differences \fIboolean\fR; journal \fIquoted_string\fR; key\-directory \fIquoted_string\fR; masterfile\-format ( map | raw | text ); masterfile\-style ( full | relative ); masters [ port \fIinteger\fR ] [ dscp \fIinteger\fR ] { ( \fImasters\fR | \fIipv4_address\fR [ port \fIinteger\fR ] | \fIipv6_address\fR [ port \fIinteger\fR ] ) [ key \fIstring\fR ]; \&.\&.\&. }; max\-journal\-size ( unlimited | \fIsizeval\fR ); max\-records \fIinteger\fR; max\-refresh\-time \fIinteger\fR; max\-retry\-time \fIinteger\fR; max\-transfer\-idle\-in \fIinteger\fR; max\-transfer\-idle\-out \fIinteger\fR; max\-transfer\-time\-in \fIinteger\fR; max\-transfer\-time\-out \fIinteger\fR; max\-zone\-ttl ( unlimited | \fIttlval\fR ); min\-refresh\-time \fIinteger\fR; min\-retry\-time \fIinteger\fR; multi\-master \fIboolean\fR; notify ( explicit | master\-only | \fIboolean\fR ); notify\-delay \fIinteger\fR; notify\-source ( \fIipv4_address\fR | * ) [ port ( \fIinteger\fR | * ) ] [ dscp \fIinteger\fR ]; notify\-source\-v6 ( \fIipv6_address\fR | * ) [ port ( \fIinteger\fR | * ) ] [ dscp \fIinteger\fR ]; notify\-to\-soa \fIboolean\fR; pubkey \fIinteger\fR \fIinteger\fR request\-expire \fIboolean\fR; request\-ixfr \fIboolean\fR; serial\-update\-method ( date | increment | unixtime ); server\-addresses { ( \fIipv4_address\fR | \fIipv6_address\fR ) [ port \fIinteger\fR ]; \&.\&.\&. }; server\-names { \fIquoted_string\fR; \&.\&.\&. }; sig\-signing\-nodes \fIinteger\fR; sig\-signing\-signatures \fIinteger\fR; sig\-signing\-type \fIinteger\fR; sig\-validity\-interval \fIinteger\fR [ \fIinteger\fR ]; transfer\-source ( \fIipv4_address\fR | * ) [ port ( \fIinteger\fR | * ) ] [ dscp \fIinteger\fR ]; transfer\-source\-v6 ( \fIipv6_address\fR | * ) [ port ( \fIinteger\fR | * ) ] [ dscp \fIinteger\fR ]; try\-tcp\-refresh \fIboolean\fR; type ( delegation\-only | forward | hint | master | redirect | slave | static\-stub | stub ); update\-check\-ksk \fIboolean\fR; update\-policy ( local | { ( deny | grant ) \fIstring\fR ( 6to4\-self | external | krb5\-self | krb5\-subdomain | ms\-self | ms\-subdomain | name | self | selfsub | selfwild | subdomain | tcp\-self | wildcard | zonesub ) [ \fIstring\fR ] \fIrrtypelist\fR; \&.\&.\&. }; use\-alt\-transfer\-source \fIboolean\fR; zero\-no\-soa\-ttl \fIboolean\fR; zone\-statistics ( full | terse | none | \fIboolean\fR ); }; .fi .if n \{\ .RE .\} .SH "FILES" .PP /etc/named\&.conf .SH "SEE ALSO" .PP \fBddns-confgen\fR(8), \fBnamed\fR(8), \fBnamed-checkconf\fR(8), \fBrndc\fR(8), \fBrndc-confgen\fR(8), BIND 9 Administrator Reference Manual\&. .SH "AUTHOR" .PP \fBInternet Systems Consortium, Inc\&.\fR .SH "COPYRIGHT" .br Copyright \(co 2004-2018 Internet Systems Consortium, Inc. ("ISC") .br bind9-9.11.3+dfsg/bin/named/named.conf.docbook000066400000000000000000001576121325250447100207560ustar00rootroot00000000000000 2017-08-15 ISC Internet Systems Consortium, Inc. named.conf 5 BIND9 named.conf configuration file for named 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 Internet Systems Consortium, Inc. ("ISC") named.conf DESCRIPTION named.conf is the configuration file for named. Statements are enclosed in braces and terminated with a semi-colon. Clauses in the statements are also semi-colon terminated. The usual comment styles are supported: C style: /* */ C++ style: // to end of line Unix style: # to end of line ACL acl string { address_match_element; ... }; CONTROLS controls { inet ( ipv4_address | ipv6_address | * ) [ port ( integer | * ) ] allow { address_match_element; ... } [ keys { string; ... } ] [ read-only boolean ]; unix quoted_string perm integer owner integer group integer [ keys { string; ... } ] [ read-only boolean ]; }; DLZ dlz string { database string; search boolean; }; DYNDB dyndb string quoted_string { unspecified-text }; KEY key string { algorithm string; secret string; }; LOGGING logging { category string { string; ... }; channel string { buffered boolean; file quoted_string [ versions ( "unlimited" | integer ) ] [ size size ]; null; print-category boolean; print-severity boolean; print-time boolean; severity log_severity; stderr; syslog [ syslog_facility ]; }; }; LWRES lwres { listen-on [ port integer ] [ dscp integer ] { ( ipv4_address | ipv6_address ) [ port integer ] [ dscp integer ]; ... }; lwres-clients integer; lwres-tasks integer; ndots integer; search { string; ... }; view string [ class ]; }; MANAGED-KEYS managed-keys { string string integer integer integer quoted_string; ... }; MASTERS masters string [ port integer ] [ dscp integer ] { ( masters | ipv4_address [ port integer ] | ipv6_address [ port integer ] ) [ key string ]; ... }; OPTIONS options { acache-cleaning-interval integer; acache-enable boolean; additional-from-auth boolean; additional-from-cache boolean; allow-new-zones boolean; allow-notify { address_match_element; ... }; allow-query { address_match_element; ... }; allow-query-cache { address_match_element; ... }; allow-query-cache-on { address_match_element; ... }; allow-query-on { address_match_element; ... }; allow-recursion { address_match_element; ... }; allow-recursion-on { address_match_element; ... }; allow-transfer { address_match_element; ... }; allow-update { address_match_element; ... }; allow-update-forwarding { address_match_element; ... }; also-notify [ port integer ] [ dscp integer ] { ( masters | ipv4_address [ port integer ] | ipv6_address [ port integer ] ) [ key string ]; ... }; alt-transfer-source ( ipv4_address | * ) [ port ( integer | * ) ] [ dscp integer ]; alt-transfer-source-v6 ( ipv6_address | * ) [ port ( integer | * ) ] [ dscp integer ]; attach-cache string; auth-nxdomain boolean; // default changed auto-dnssec ( allow | maintain | off ); automatic-interface-scan boolean; avoid-v4-udp-ports { portrange; ... }; avoid-v6-udp-ports { portrange; ... }; bindkeys-file quoted_string; blackhole { address_match_element; ... }; cache-file quoted_string; catalog-zones { zone quoted_string [ default-masters [ port integer ] [ dscp integer ] { ( masters | ipv4_address [ port integer ] | ipv6_address [ port integer ] ) [ key string ]; ... } ] [ zone-directory quoted_string ] [ in-memory boolean ] [ min-update-interval integer ]; ... }; check-dup-records ( fail | warn | ignore ); check-integrity boolean; check-mx ( fail | warn | ignore ); check-mx-cname ( fail | warn | ignore ); check-names ( master | slave | response ) ( fail | warn | ignore ); check-sibling boolean; check-spf ( warn | ignore ); check-srv-cname ( fail | warn | ignore ); check-wildcard boolean; cleaning-interval integer; clients-per-query integer; cookie-algorithm ( aes | sha1 | sha256 ); cookie-secret string; coresize ( default | unlimited | sizeval ); datasize ( default | unlimited | sizeval ); deny-answer-addresses { address_match_element; ... } [ except-from { quoted_string; ... } ]; deny-answer-aliases { quoted_string; ... } [ except-from { quoted_string; ... } ]; dialup ( notify | notify-passive | passive | refresh | boolean ); directory quoted_string; disable-algorithms string { string; ... }; disable-ds-digests string { string; ... }; disable-empty-zone string; dns64 netprefix { break-dnssec boolean; clients { address_match_element; ... }; exclude { address_match_element; ... }; mapped { address_match_element; ... }; recursive-only boolean; suffix ipv6_address; }; dns64-contact string; dns64-server string; dnssec-accept-expired boolean; dnssec-dnskey-kskonly boolean; dnssec-enable boolean; dnssec-loadkeys-interval integer; dnssec-lookaside ( string trust-anchor string | auto | no ); dnssec-must-be-secure string boolean; dnssec-secure-to-insecure boolean; dnssec-update-mode ( maintain | no-resign ); dnssec-validation ( yes | no | auto ); dnstap { ( all | auth | client | forwarder | resolver ) [ ( query | response ) ]; ... }; dnstap-identity ( quoted_string | none | hostname ); dnstap-output ( file | unix ) quoted_string; dnstap-version ( quoted_string | none ); dscp integer; dual-stack-servers [ port integer ] { ( quoted_string [ port integer ] [ dscp integer ] | ipv4_address [ port integer ] [ dscp integer ] | ipv6_address [ port integer ] [ dscp integer ] ); ... }; dump-file quoted_string; edns-udp-size integer; empty-contact string; empty-server string; empty-zones-enable boolean; fetch-quota-params integer fixedpoint fixedpoint fixedpoint; fetches-per-server integer [ ( drop | fail ) ]; fetches-per-zone integer [ ( drop | fail ) ]; files ( default | unlimited | sizeval ); filter-aaaa { address_match_element; ... }; filter-aaaa-on-v4 ( break-dnssec | boolean ); filter-aaaa-on-v6 ( break-dnssec | boolean ); flush-zones-on-shutdown boolean; forward ( first | only ); forwarders [ port integer ] [ dscp integer ] { ( ipv4_address | ipv6_address ) [ port integer ] [ dscp integer ]; ... }; fstrm-set-buffer-hint integer; fstrm-set-flush-timeout integer; fstrm-set-input-queue-size integer; fstrm-set-output-notify-threshold integer; fstrm-set-output-queue-model ( mpsc | spsc ); fstrm-set-output-queue-size integer; fstrm-set-reopen-interval integer; geoip-directory ( quoted_string | none ); geoip-use-ecs boolean; heartbeat-interval integer; hostname ( quoted_string | none ); inline-signing boolean; interface-interval integer; ixfr-from-differences ( master | slave | boolean ); keep-response-order { address_match_element; ... }; key-directory quoted_string; lame-ttl ttlval; listen-on [ port integer ] [ dscp integer ] { address_match_element; ... }; listen-on-v6 [ port integer ] [ dscp integer ] { address_match_element; ... }; lmdb-mapsize sizeval; lock-file ( quoted_string | none ); managed-keys-directory quoted_string; masterfile-format ( map | raw | text ); masterfile-style ( full | relative ); match-mapped-addresses boolean; max-acache-size ( unlimited | sizeval ); max-cache-size ( default | unlimited | sizeval | percentage ); max-cache-ttl integer; max-clients-per-query integer; max-journal-size ( unlimited | sizeval ); max-ncache-ttl integer; max-records integer; max-recursion-depth integer; max-recursion-queries integer; max-refresh-time integer; max-retry-time integer; max-rsa-exponent-size integer; max-transfer-idle-in integer; max-transfer-idle-out integer; max-transfer-time-in integer; max-transfer-time-out integer; max-udp-size integer; max-zone-ttl ( unlimited | ttlval ); memstatistics boolean; memstatistics-file quoted_string; message-compression boolean; min-refresh-time integer; min-retry-time integer; minimal-any boolean; minimal-responses ( no-auth | no-auth-recursive | boolean ); multi-master boolean; no-case-compress { address_match_element; ... }; nocookie-udp-size integer; notify ( explicit | master-only | boolean ); notify-delay integer; notify-rate integer; notify-source ( ipv4_address | * ) [ port ( integer | * ) ] [ dscp integer ]; notify-source-v6 ( ipv6_address | * ) [ port ( integer | * ) ] [ dscp integer ]; notify-to-soa boolean; nta-lifetime ttlval; nta-recheck ttlval; nxdomain-redirect string; pid-file ( quoted_string | none ); port integer; preferred-glue string; prefetch integer [ integer ]; provide-ixfr boolean; query-source ( ( [ address ] ( ipv4_address | * ) [ port ( integer | * ) ] ) | ( [ [ address ] ( ipv4_address | * ) ] port ( integer | * ) ) ) [ dscp integer ]; query-source-v6 ( ( [ address ] ( ipv6_address | * ) [ port ( integer | * ) ] ) | ( [ [ address ] ( ipv6_address | * ) ] port ( integer | * ) ) ) [ dscp integer ]; querylog boolean; random-device quoted_string; rate-limit { all-per-second integer; errors-per-second integer; exempt-clients { address_match_element; ... }; ipv4-prefix-length integer; ipv6-prefix-length integer; log-only boolean; max-table-size integer; min-table-size integer; nodata-per-second integer; nxdomains-per-second integer; qps-scale integer; referrals-per-second integer; responses-per-second integer; slip integer; window integer; }; recursing-file quoted_string; recursion boolean; recursive-clients integer; request-expire boolean; request-ixfr boolean; request-nsid boolean; require-server-cookie boolean; reserved-sockets integer; resolver-query-timeout integer; response-policy { zone quoted_string [ log boolean ] [ max-policy-ttl integer ] [ policy ( cname | disabled | drop | given | no-op | nodata | nxdomain | passthru | tcp-only quoted_string ) ] [ recursive-only boolean ]; ... } [ break-dnssec boolean ] [ max-policy-ttl integer ] [ min-ns-dots integer ] [ nsip-wait-recurse boolean ] [ qname-wait-recurse boolean ] [ recursive-only boolean ]; root-delegation-only [ exclude { quoted_string; ... } ]; rrset-order { [ class string ] [ type string ] [ name quoted_string ] string string; ... }; secroots-file quoted_string; send-cookie boolean; serial-query-rate integer; serial-update-method ( date | increment | unixtime ); server-id ( quoted_string | none | hostname ); servfail-ttl ttlval; session-keyalg string; session-keyfile ( quoted_string | none ); session-keyname string; sig-signing-nodes integer; sig-signing-signatures integer; sig-signing-type integer; sig-validity-interval integer [ integer ]; sortlist { address_match_element; ... }; stacksize ( default | unlimited | sizeval ); startup-notify-rate integer; statistics-file quoted_string; tcp-clients integer; tcp-listen-queue integer; tkey-dhkey quoted_string integer; tkey-domain quoted_string; tkey-gssapi-credential quoted_string; tkey-gssapi-keytab quoted_string; transfer-format ( many-answers | one-answer ); transfer-message-size integer; transfer-source ( ipv4_address | * ) [ port ( integer | * ) ] [ dscp integer ]; transfer-source-v6 ( ipv6_address | * ) [ port ( integer | * ) ] [ dscp integer ]; transfers-in integer; transfers-out integer; transfers-per-ns integer; trust-anchor-telemetry boolean; // experimental try-tcp-refresh boolean; update-check-ksk boolean; use-alt-transfer-source boolean; use-v4-udp-ports { portrange; ... }; use-v6-udp-ports { portrange; ... }; v6-bias integer; version ( quoted_string | none ); zero-no-soa-ttl boolean; zero-no-soa-ttl-cache boolean; zone-statistics ( full | terse | none | boolean ); }; SERVER server netprefix { bogus boolean; edns boolean; edns-udp-size integer; edns-version integer; keys server_key; max-udp-size integer; notify-source ( ipv4_address | * ) [ port ( integer | * ) ] [ dscp integer ]; notify-source-v6 ( ipv6_address | * ) [ port ( integer | * ) ] [ dscp integer ]; provide-ixfr boolean; query-source ( ( [ address ] ( ipv4_address | * ) [ port ( integer | * ) ] ) | ( [ [ address ] ( ipv4_address | * ) ] port ( integer | * ) ) ) [ dscp integer ]; query-source-v6 ( ( [ address ] ( ipv6_address | * ) [ port ( integer | * ) ] ) | ( [ [ address ] ( ipv6_address | * ) ] port ( integer | * ) ) ) [ dscp integer ]; request-expire boolean; request-ixfr boolean; request-nsid boolean; send-cookie boolean; tcp-only boolean; transfer-format ( many-answers | one-answer ); transfer-source ( ipv4_address | * ) [ port ( integer | * ) ] [ dscp integer ]; transfer-source-v6 ( ipv6_address | * ) [ port ( integer | * ) ] [ dscp integer ]; transfers integer; }; STATISTICS-CHANNELS statistics-channels { inet ( ipv4_address | ipv6_address | * ) [ port ( integer | * ) ] [ allow { address_match_element; ... } ]; }; TRUSTED-KEYS trusted-keys { string integer integer integer quoted_string; ... }; VIEW view string [ class ] { acache-cleaning-interval integer; acache-enable boolean; additional-from-auth boolean; additional-from-cache boolean; allow-new-zones boolean; allow-notify { address_match_element; ... }; allow-query { address_match_element; ... }; allow-query-cache { address_match_element; ... }; allow-query-cache-on { address_match_element; ... }; allow-query-on { address_match_element; ... }; allow-recursion { address_match_element; ... }; allow-recursion-on { address_match_element; ... }; allow-transfer { address_match_element; ... }; allow-update { address_match_element; ... }; allow-update-forwarding { address_match_element; ... }; also-notify [ port integer ] [ dscp integer ] { ( masters | ipv4_address [ port integer ] | ipv6_address [ port integer ] ) [ key string ]; ... }; alt-transfer-source ( ipv4_address | * ) [ port ( integer | * ) ] [ dscp integer ]; alt-transfer-source-v6 ( ipv6_address | * ) [ port ( integer | * ) ] [ dscp integer ]; attach-cache string; auth-nxdomain boolean; // default changed auto-dnssec ( allow | maintain | off ); cache-file quoted_string; catalog-zones { zone quoted_string [ default-masters [ port integer ] [ dscp integer ] { ( masters | ipv4_address [ port integer ] | ipv6_address [ port integer ] ) [ key string ]; ... } ] [ zone-directory quoted_string ] [ in-memory boolean ] [ min-update-interval integer ]; ... }; check-dup-records ( fail | warn | ignore ); check-integrity boolean; check-mx ( fail | warn | ignore ); check-mx-cname ( fail | warn | ignore ); check-names ( master | slave | response ) ( fail | warn | ignore ); check-sibling boolean; check-spf ( warn | ignore ); check-srv-cname ( fail | warn | ignore ); check-wildcard boolean; cleaning-interval integer; clients-per-query integer; deny-answer-addresses { address_match_element; ... } [ except-from { quoted_string; ... } ]; deny-answer-aliases { quoted_string; ... } [ except-from { quoted_string; ... } ]; dialup ( notify | notify-passive | passive | refresh | boolean ); disable-algorithms string { string; ... }; disable-ds-digests string { string; ... }; disable-empty-zone string; dlz string { database string; search boolean; }; dns64 netprefix { break-dnssec boolean; clients { address_match_element; ... }; exclude { address_match_element; ... }; mapped { address_match_element; ... }; recursive-only boolean; suffix ipv6_address; }; dns64-contact string; dns64-server string; dnssec-accept-expired boolean; dnssec-dnskey-kskonly boolean; dnssec-enable boolean; dnssec-loadkeys-interval integer; dnssec-lookaside ( string trust-anchor string | auto | no ); dnssec-must-be-secure string boolean; dnssec-secure-to-insecure boolean; dnssec-update-mode ( maintain | no-resign ); dnssec-validation ( yes | no | auto ); dnstap { ( all | auth | client | forwarder | resolver ) [ ( query | response ) ]; ... }; dual-stack-servers [ port integer ] { ( quoted_string [ port integer ] [ dscp integer ] | ipv4_address [ port integer ] [ dscp integer ] | ipv6_address [ port integer ] [ dscp integer ] ); ... }; dyndb string quoted_string { unspecified-text }; edns-udp-size integer; empty-contact string; empty-server string; empty-zones-enable boolean; fetch-quota-params integer fixedpoint fixedpoint fixedpoint; fetches-per-server integer [ ( drop | fail ) ]; fetches-per-zone integer [ ( drop | fail ) ]; filter-aaaa { address_match_element; ... }; filter-aaaa-on-v4 ( break-dnssec | boolean ); filter-aaaa-on-v6 ( break-dnssec | boolean ); forward ( first | only ); forwarders [ port integer ] [ dscp integer ] { ( ipv4_address | ipv6_address ) [ port integer ] [ dscp integer ]; ... }; inline-signing boolean; ixfr-from-differences ( master | slave | boolean ); key string { algorithm string; secret string; }; key-directory quoted_string; lame-ttl ttlval; lmdb-mapsize sizeval; managed-keys { string string integer integer integer quoted_string; ... }; masterfile-format ( map | raw | text ); masterfile-style ( full | relative ); match-clients { address_match_element; ... }; match-destinations { address_match_element; ... }; match-recursive-only boolean; max-acache-size ( unlimited | sizeval ); max-cache-size ( default | unlimited | sizeval | percentage ); max-cache-ttl integer; max-clients-per-query integer; max-journal-size ( unlimited | sizeval ); max-ncache-ttl integer; max-records integer; max-recursion-depth integer; max-recursion-queries integer; max-refresh-time integer; max-retry-time integer; max-transfer-idle-in integer; max-transfer-idle-out integer; max-transfer-time-in integer; max-transfer-time-out integer; max-udp-size integer; max-zone-ttl ( unlimited | ttlval ); message-compression boolean; min-refresh-time integer; min-retry-time integer; minimal-any boolean; minimal-responses ( no-auth | no-auth-recursive | boolean ); multi-master boolean; no-case-compress { address_match_element; ... }; nocookie-udp-size integer; notify ( explicit | master-only | boolean ); notify-delay integer; notify-source ( ipv4_address | * ) [ port ( integer | * ) ] [ dscp integer ]; notify-source-v6 ( ipv6_address | * ) [ port ( integer | * ) ] [ dscp integer ]; notify-to-soa boolean; nta-lifetime ttlval; nta-recheck ttlval; nxdomain-redirect string; preferred-glue string; prefetch integer [ integer ]; provide-ixfr boolean; query-source ( ( [ address ] ( ipv4_address | * ) [ port ( integer | * ) ] ) | ( [ [ address ] ( ipv4_address | * ) ] port ( integer | * ) ) ) [ dscp integer ]; query-source-v6 ( ( [ address ] ( ipv6_address | * ) [ port ( integer | * ) ] ) | ( [ [ address ] ( ipv6_address | * ) ] port ( integer | * ) ) ) [ dscp integer ]; rate-limit { all-per-second integer; errors-per-second integer; exempt-clients { address_match_element; ... }; ipv4-prefix-length integer; ipv6-prefix-length integer; log-only boolean; max-table-size integer; min-table-size integer; nodata-per-second integer; nxdomains-per-second integer; qps-scale integer; referrals-per-second integer; responses-per-second integer; slip integer; window integer; }; recursion boolean; request-expire boolean; request-ixfr boolean; request-nsid boolean; require-server-cookie boolean; resolver-query-timeout integer; response-policy { zone quoted_string [ log boolean ] [ max-policy-ttl integer ] [ policy ( cname | disabled | drop | given | no-op | nodata | nxdomain | passthru | tcp-only quoted_string ) ] [ recursive-only boolean ]; ... } [ break-dnssec boolean ] [ max-policy-ttl integer ] [ min-ns-dots integer ] [ nsip-wait-recurse boolean ] [ qname-wait-recurse boolean ] [ recursive-only boolean ]; root-delegation-only [ exclude { quoted_string; ... } ]; rrset-order { [ class string ] [ type string ] [ name quoted_string ] string string; ... }; send-cookie boolean; serial-update-method ( date | increment | unixtime ); server netprefix { bogus boolean; edns boolean; edns-udp-size integer; edns-version integer; keys server_key; max-udp-size integer; notify-source ( ipv4_address | * ) [ port ( integer | * ) ] [ dscp integer ]; notify-source-v6 ( ipv6_address | * ) [ port ( integer | * ) ] [ dscp integer ]; provide-ixfr boolean; query-source ( ( [ address ] ( ipv4_address | * ) [ port ( integer | * ) ] ) | ( [ [ address ] ( ipv4_address | * ) ] port ( integer | * ) ) ) [ dscp integer ]; query-source-v6 ( ( [ address ] ( ipv6_address | * ) [ port ( integer | * ) ] ) | ( [ [ address ] ( ipv6_address | * ) ] port ( integer | * ) ) ) [ dscp integer ]; request-expire boolean; request-ixfr boolean; request-nsid boolean; send-cookie boolean; tcp-only boolean; transfer-format ( many-answers | one-answer ); transfer-source ( ipv4_address | * ) [ port ( integer | * ) ] [ dscp integer ]; transfer-source-v6 ( ipv6_address | * ) [ port ( integer | * ) ] [ dscp integer ]; transfers integer; }; servfail-ttl ttlval; sig-signing-nodes integer; sig-signing-signatures integer; sig-signing-type integer; sig-validity-interval integer [ integer ]; sortlist { address_match_element; ... }; transfer-format ( many-answers | one-answer ); transfer-source ( ipv4_address | * ) [ port ( integer | * ) ] [ dscp integer ]; transfer-source-v6 ( ipv6_address | * ) [ port ( integer | * ) ] [ dscp integer ]; trust-anchor-telemetry boolean; // experimental trusted-keys { string integer integer integer quoted_string; ... }; try-tcp-refresh boolean; update-check-ksk boolean; use-alt-transfer-source boolean; v6-bias integer; zero-no-soa-ttl boolean; zero-no-soa-ttl-cache boolean; zone string [ class ] { allow-notify { address_match_element; ... }; allow-query { address_match_element; ... }; allow-query-on { address_match_element; ... }; allow-transfer { address_match_element; ... }; allow-update { address_match_element; ... }; allow-update-forwarding { address_match_element; ... }; also-notify [ port integer ] [ dscp integer ] { ( masters | ipv4_address [ port integer ] | ipv6_address [ port integer ] ) [ key string ]; ... }; alt-transfer-source ( ipv4_address | * ) [ port ( integer | * ) ] [ dscp integer ]; alt-transfer-source-v6 ( ipv6_address | * ) [ port ( integer | * ) ] [ dscp integer ]; auto-dnssec ( allow | maintain | off ); check-dup-records ( fail | warn | ignore ); check-integrity boolean; check-mx ( fail | warn | ignore ); check-mx-cname ( fail | warn | ignore ); check-names ( fail | warn | ignore ); check-sibling boolean; check-spf ( warn | ignore ); check-srv-cname ( fail | warn | ignore ); check-wildcard boolean; database string; delegation-only boolean; dialup ( notify | notify-passive | passive | refresh | boolean ); dlz string; dnssec-dnskey-kskonly boolean; dnssec-loadkeys-interval integer; dnssec-secure-to-insecure boolean; dnssec-update-mode ( maintain | no-resign ); file quoted_string; forward ( first | only ); forwarders [ port integer ] [ dscp integer ] { ( ipv4_address | ipv6_address ) [ port integer ] [ dscp integer ]; ... }; in-view string; inline-signing boolean; ixfr-from-differences boolean; journal quoted_string; key-directory quoted_string; masterfile-format ( map | raw | text ); masterfile-style ( full | relative ); masters [ port integer ] [ dscp integer ] { ( masters | ipv4_address [ port integer ] | ipv6_address [ port integer ] ) [ key string ]; ... }; max-ixfr-log-size ( default | unlimited | max-journal-size ( unlimited | sizeval ); max-records integer; max-refresh-time integer; max-retry-time integer; max-transfer-idle-in integer; max-transfer-idle-out integer; max-transfer-time-in integer; max-transfer-time-out integer; max-zone-ttl ( unlimited | ttlval ); min-refresh-time integer; min-retry-time integer; multi-master boolean; notify ( explicit | master-only | boolean ); notify-delay integer; notify-source ( ipv4_address | * ) [ port ( integer | * ) ] [ dscp integer ]; notify-source-v6 ( ipv6_address | * ) [ port ( integer | * ) ] [ dscp integer ]; notify-to-soa boolean; pubkey integer integer integer request-expire boolean; request-ixfr boolean; serial-update-method ( date | increment | unixtime ); server-addresses { ( ipv4_address | ipv6_address ) [ port integer ]; ... }; server-names { quoted_string; ... }; sig-signing-nodes integer; sig-signing-signatures integer; sig-signing-type integer; sig-validity-interval integer [ integer ]; transfer-source ( ipv4_address | * ) [ port ( integer | * ) ] [ dscp integer ]; transfer-source-v6 ( ipv6_address | * ) [ port ( integer | * ) ] [ dscp integer ]; try-tcp-refresh boolean; type ( delegation-only | forward | hint | master | redirect | slave | static-stub | stub ); update-check-ksk boolean; update-policy ( local | { ( deny | grant ) string ( 6to4-self | external | krb5-self | krb5-subdomain | ms-self | ms-subdomain | name | self | selfsub | selfwild | subdomain | tcp-self | wildcard | zonesub ) [ string ] rrtypelist; ... }; use-alt-transfer-source boolean; zero-no-soa-ttl boolean; zone-statistics ( full | terse | none | boolean ); }; zone-statistics ( full | terse | none | boolean ); }; ZONE zone string [ class ] { allow-notify { address_match_element; ... }; allow-query { address_match_element; ... }; allow-query-on { address_match_element; ... }; allow-transfer { address_match_element; ... }; allow-update { address_match_element; ... }; allow-update-forwarding { address_match_element; ... }; also-notify [ port integer ] [ dscp integer ] { ( masters | ipv4_address [ port integer ] | ipv6_address [ port integer ] ) [ key string ]; ... }; alt-transfer-source ( ipv4_address | * ) [ port ( integer | * ) ] [ dscp integer ]; alt-transfer-source-v6 ( ipv6_address | * ) [ port ( integer | * ) ] [ dscp integer ]; auto-dnssec ( allow | maintain | off ); check-dup-records ( fail | warn | ignore ); check-integrity boolean; check-mx ( fail | warn | ignore ); check-mx-cname ( fail | warn | ignore ); check-names ( fail | warn | ignore ); check-sibling boolean; check-spf ( warn | ignore ); check-srv-cname ( fail | warn | ignore ); check-wildcard boolean; database string; delegation-only boolean; dialup ( notify | notify-passive | passive | refresh | boolean ); dlz string; dnssec-dnskey-kskonly boolean; dnssec-loadkeys-interval integer; dnssec-secure-to-insecure boolean; dnssec-update-mode ( maintain | no-resign ); file quoted_string; forward ( first | only ); forwarders [ port integer ] [ dscp integer ] { ( ipv4_address | ipv6_address ) [ port integer ] [ dscp integer ]; ... }; in-view string; inline-signing boolean; ixfr-from-differences boolean; journal quoted_string; key-directory quoted_string; masterfile-format ( map | raw | text ); masterfile-style ( full | relative ); masters [ port integer ] [ dscp integer ] { ( masters | ipv4_address [ port integer ] | ipv6_address [ port integer ] ) [ key string ]; ... }; max-journal-size ( unlimited | sizeval ); max-records integer; max-refresh-time integer; max-retry-time integer; max-transfer-idle-in integer; max-transfer-idle-out integer; max-transfer-time-in integer; max-transfer-time-out integer; max-zone-ttl ( unlimited | ttlval ); min-refresh-time integer; min-retry-time integer; multi-master boolean; notify ( explicit | master-only | boolean ); notify-delay integer; notify-source ( ipv4_address | * ) [ port ( integer | * ) ] [ dscp integer ]; notify-source-v6 ( ipv6_address | * ) [ port ( integer | * ) ] [ dscp integer ]; notify-to-soa boolean; pubkey integer integer request-expire boolean; request-ixfr boolean; serial-update-method ( date | increment | unixtime ); server-addresses { ( ipv4_address | ipv6_address ) [ port integer ]; ... }; server-names { quoted_string; ... }; sig-signing-nodes integer; sig-signing-signatures integer; sig-signing-type integer; sig-validity-interval integer [ integer ]; transfer-source ( ipv4_address | * ) [ port ( integer | * ) ] [ dscp integer ]; transfer-source-v6 ( ipv6_address | * ) [ port ( integer | * ) ] [ dscp integer ]; try-tcp-refresh boolean; type ( delegation-only | forward | hint | master | redirect | slave | static-stub | stub ); update-check-ksk boolean; update-policy ( local | { ( deny | grant ) string ( 6to4-self | external | krb5-self | krb5-subdomain | ms-self | ms-subdomain | name | self | selfsub | selfwild | subdomain | tcp-self | wildcard | zonesub ) [ string ] rrtypelist; ... }; use-alt-transfer-source boolean; zero-no-soa-ttl boolean; zone-statistics ( full | terse | none | boolean ); }; FILES /etc/named.conf SEE ALSO ddns-confgen8 , named8 , named-checkconf8 , rndc8 , rndc-confgen8 , BIND 9 Administrator Reference Manual. bind9-9.11.3+dfsg/bin/named/named.conf.html000066400000000000000000002172651325250447100203030ustar00rootroot00000000000000 named.conf

Name

named.conf — configuration file for named

Synopsis

named.conf

DESCRIPTION

named.conf is the configuration file for named. Statements are enclosed in braces and terminated with a semi-colon. Clauses in the statements are also semi-colon terminated. The usual comment styles are supported:

C style: /* */

C++ style: // to end of line

Unix style: # to end of line

ACL


acl string { address_match_element; ... };

CONTROLS


controls {
inet ( ipv4_address | ipv6_address |
    * ) [ port ( integer | * ) ] allow
    { address_match_element; ... } [
    keys { string; ... } ] [ read-only
    boolean ];
unix quoted_string perm integer
    owner integer group integer [
    keys { string; ... } ] [ read-only
    boolean ];
};

DLZ


dlz string {
database string;
search boolean;
};

DYNDB


dyndb string quoted_string {
    unspecified-text };

KEY


key string {
algorithm string;
secret string;
};

LOGGING


logging {
category string { string; ... };
channel string {
buffered boolean;
file quoted_string [ versions ( "unlimited" | integer )
    ] [ size size ];
null;
print-category boolean;
print-severity boolean;
print-time boolean;
severity log_severity;
stderr;
syslog [ syslog_facility ];
};
};

LWRES


lwres {
listen-on [ port integer ] [ dscp integer ] { ( ipv4_address
    | ipv6_address ) [ port integer ] [ dscp integer ]; ... };
lwres-clients integer;
lwres-tasks integer;
ndots integer;
search { string; ... };
view string [ class ];
};

MANAGED-KEYS


managed-keys { string string integer
    integer integer quoted_string; ... };

MASTERS


masters string [ port integer ] [ dscp
    integer ] { ( masters | ipv4_address [
    port integer ] | ipv6_address [ port
    integer ] ) [ key string ]; ... };

OPTIONS


options {
acache-cleaning-interval integer;
acache-enable boolean;
additional-from-auth boolean;
additional-from-cache boolean;
allow-new-zones boolean;
allow-notify { address_match_element; ... };
allow-query { address_match_element; ... };
allow-query-cache { address_match_element; ... };
allow-query-cache-on { address_match_element; ... };
allow-query-on { address_match_element; ... };
allow-recursion { address_match_element; ... };
allow-recursion-on { address_match_element; ... };
allow-transfer { address_match_element; ... };
allow-update { address_match_element; ... };
allow-update-forwarding { address_match_element; ... };
also-notify [ port integer ] [ dscp integer ] { ( masters |
    ipv4_address [ port integer ] | ipv6_address [ port
    integer ] ) [ key string ]; ... };
alt-transfer-source ( ipv4_address | * ) [ port ( integer | * )
    ] [ dscp integer ];
alt-transfer-source-v6 ( ipv6_address | * ) [ port ( integer |
    * ) ] [ dscp integer ];
attach-cache string;
auth-nxdomain boolean; // default changed
auto-dnssec ( allow | maintain | off );
automatic-interface-scan boolean;
avoid-v4-udp-ports { portrange; ... };
avoid-v6-udp-ports { portrange; ... };
bindkeys-file quoted_string;
blackhole { address_match_element; ... };
cache-file quoted_string;
catalog-zones { zone quoted_string [ default-masters [ port
    integer ] [ dscp integer ] { ( masters | ipv4_address [
    port integer ] | ipv6_address [ port integer ] ) [ key
    string ]; ... } ] [ zone-directory quoted_string ] [
    in-memory boolean ] [ min-update-interval integer ]; ... };
check-dup-records ( fail | warn | ignore );
check-integrity boolean;
check-mx ( fail | warn | ignore );
check-mx-cname ( fail | warn | ignore );
check-names ( master | slave | response
    ) ( fail | warn | ignore );
check-sibling boolean;
check-spf ( warn | ignore );
check-srv-cname ( fail | warn | ignore );
check-wildcard boolean;
cleaning-interval integer;
clients-per-query integer;
cookie-algorithm ( aes | sha1 | sha256 );
cookie-secret string;
coresize ( default | unlimited | sizeval );
datasize ( default | unlimited | sizeval );
deny-answer-addresses { address_match_element; ... } [
    except-from { quoted_string; ... } ];
deny-answer-aliases { quoted_string; ... } [ except-from {
    quoted_string; ... } ];
dialup ( notify | notify-passive | passive | refresh | boolean );
directory quoted_string;
disable-algorithms string { string;
    ... };
disable-ds-digests string { string;
    ... };
disable-empty-zone string;
dns64 netprefix {
break-dnssec boolean;
clients { address_match_element; ... };
exclude { address_match_element; ... };
mapped { address_match_element; ... };
recursive-only boolean;
suffix ipv6_address;
};
dns64-contact string;
dns64-server string;
dnssec-accept-expired boolean;
dnssec-dnskey-kskonly boolean;
dnssec-enable boolean;
dnssec-loadkeys-interval integer;
dnssec-lookaside ( string trust-anchor
    string | auto | no );
dnssec-must-be-secure string boolean;
dnssec-secure-to-insecure boolean;
dnssec-update-mode ( maintain | no-resign );
dnssec-validation ( yes | no | auto );
dnstap { ( all | auth | client | forwarder |
    resolver ) [ ( query | response ) ]; ... };
dnstap-identity ( quoted_string | none |
    hostname );
dnstap-output ( file | unix ) quoted_string;
dnstap-version ( quoted_string | none );
dscp integer;
dual-stack-servers [ port integer ] { ( quoted_string [ port
    integer ] [ dscp integer ] | ipv4_address [ port
    integer ] [ dscp integer ] | ipv6_address [ port
    integer ] [ dscp integer ] ); ... };
dump-file quoted_string;
edns-udp-size integer;
empty-contact string;
empty-server string;
empty-zones-enable boolean;
fetch-quota-params integer fixedpoint fixedpoint fixedpoint;
fetches-per-server integer [ ( drop | fail ) ];
fetches-per-zone integer [ ( drop | fail ) ];
files ( default | unlimited | sizeval );
filter-aaaa { address_match_element; ... };
filter-aaaa-on-v4 ( break-dnssec | boolean );
filter-aaaa-on-v6 ( break-dnssec | boolean );
flush-zones-on-shutdown boolean;
forward ( first | only );
forwarders [ port integer ] [ dscp integer ] { ( ipv4_address
    | ipv6_address ) [ port integer ] [ dscp integer ]; ... };
fstrm-set-buffer-hint integer;
fstrm-set-flush-timeout integer;
fstrm-set-input-queue-size integer;
fstrm-set-output-notify-threshold integer;
fstrm-set-output-queue-model ( mpsc | spsc );
fstrm-set-output-queue-size integer;
fstrm-set-reopen-interval integer;
geoip-directory ( quoted_string | none );
geoip-use-ecs boolean;
heartbeat-interval integer;
hostname ( quoted_string | none );
inline-signing boolean;
interface-interval integer;
ixfr-from-differences ( master | slave | boolean );
keep-response-order { address_match_element; ... };
key-directory quoted_string;
lame-ttl ttlval;
listen-on [ port integer ] [ dscp
    integer ] {
    address_match_element; ... };
listen-on-v6 [ port integer ] [ dscp
    integer ] {
    address_match_element; ... };
lmdb-mapsize sizeval;
lock-file ( quoted_string | none );
managed-keys-directory quoted_string;
masterfile-format ( map | raw | text );
masterfile-style ( full | relative );
match-mapped-addresses boolean;
max-acache-size ( unlimited | sizeval );
max-cache-size ( default | unlimited | sizeval | percentage );
max-cache-ttl integer;
max-clients-per-query integer;
max-journal-size ( unlimited | sizeval );
max-ncache-ttl integer;
max-records integer;
max-recursion-depth integer;
max-recursion-queries integer;
max-refresh-time integer;
max-retry-time integer;
max-rsa-exponent-size integer;
max-transfer-idle-in integer;
max-transfer-idle-out integer;
max-transfer-time-in integer;
max-transfer-time-out integer;
max-udp-size integer;
max-zone-ttl ( unlimited | ttlval );
memstatistics boolean;
memstatistics-file quoted_string;
message-compression boolean;
min-refresh-time integer;
min-retry-time integer;
minimal-any boolean;
minimal-responses ( no-auth | no-auth-recursive | boolean );
multi-master boolean;
no-case-compress { address_match_element; ... };
nocookie-udp-size integer;
notify ( explicit | master-only | boolean );
notify-delay integer;
notify-rate integer;
notify-source ( ipv4_address | * ) [ port ( integer | * ) ] [
    dscp integer ];
notify-source-v6 ( ipv6_address | * ) [ port ( integer | * ) ]
    [ dscp integer ];
notify-to-soa boolean;
nta-lifetime ttlval;
nta-recheck ttlval;
nxdomain-redirect string;
pid-file ( quoted_string | none );
port integer;
preferred-glue string;
prefetch integer [ integer ];
provide-ixfr boolean;
query-source ( ( [ address ] ( ipv4_address | * ) [ port (
    integer | * ) ] ) | ( [ [ address ] ( ipv4_address | * ) ]
    port ( integer | * ) ) ) [ dscp integer ];
query-source-v6 ( ( [ address ] ( ipv6_address | * ) [ port (
    integer | * ) ] ) | ( [ [ address ] ( ipv6_address | * ) ]
    port ( integer | * ) ) ) [ dscp integer ];
querylog boolean;
random-device quoted_string;
rate-limit {
all-per-second integer;
errors-per-second integer;
exempt-clients { address_match_element; ... };
ipv4-prefix-length integer;
ipv6-prefix-length integer;
log-only boolean;
max-table-size integer;
min-table-size integer;
nodata-per-second integer;
nxdomains-per-second integer;
qps-scale integer;
referrals-per-second integer;
responses-per-second integer;
slip integer;
window integer;
};
recursing-file quoted_string;
recursion boolean;
recursive-clients integer;
request-expire boolean;
request-ixfr boolean;
request-nsid boolean;
require-server-cookie boolean;
reserved-sockets integer;
resolver-query-timeout integer;
response-policy { zone quoted_string [ log boolean ] [
    max-policy-ttl integer ] [ policy ( cname | disabled | drop |
    given | no-op | nodata | nxdomain | passthru | tcp-only
    quoted_string ) ] [ recursive-only boolean ]; ... } [
    break-dnssec boolean ] [ max-policy-ttl integer ] [
    min-ns-dots integer ] [ nsip-wait-recurse boolean ] [
    qname-wait-recurse boolean ] [ recursive-only boolean ];
root-delegation-only [ exclude { quoted_string; ... } ];
rrset-order { [ class string ] [ type string ] [ name
    quoted_string ] string string; ... };
secroots-file quoted_string;
send-cookie boolean;
serial-query-rate integer;
serial-update-method ( date | increment | unixtime );
server-id ( quoted_string | none | hostname );
servfail-ttl ttlval;
session-keyalg string;
session-keyfile ( quoted_string | none );
session-keyname string;
sig-signing-nodes integer;
sig-signing-signatures integer;
sig-signing-type integer;
sig-validity-interval integer [ integer ];
sortlist { address_match_element; ... };
stacksize ( default | unlimited | sizeval );
startup-notify-rate integer;
statistics-file quoted_string;
tcp-clients integer;
tcp-listen-queue integer;
tkey-dhkey quoted_string integer;
tkey-domain quoted_string;
tkey-gssapi-credential quoted_string;
tkey-gssapi-keytab quoted_string;
transfer-format ( many-answers | one-answer );
transfer-message-size integer;
transfer-source ( ipv4_address | * ) [ port ( integer | * ) ] [
    dscp integer ];
transfer-source-v6 ( ipv6_address | * ) [ port ( integer | * )
    ] [ dscp integer ];
transfers-in integer;
transfers-out integer;
transfers-per-ns integer;
trust-anchor-telemetry boolean; // experimental
try-tcp-refresh boolean;
update-check-ksk boolean;
use-alt-transfer-source boolean;
use-v4-udp-ports { portrange; ... };
use-v6-udp-ports { portrange; ... };
v6-bias integer;
version ( quoted_string | none );
zero-no-soa-ttl boolean;
zero-no-soa-ttl-cache boolean;
zone-statistics ( full | terse | none | boolean );
};

SERVER


server netprefix {
bogus boolean;
edns boolean;
edns-udp-size integer;
edns-version integer;
keys server_key;
max-udp-size integer;
notify-source ( ipv4_address | * ) [ port ( integer | * ) ] [
    dscp integer ];
notify-source-v6 ( ipv6_address | * ) [ port ( integer | * ) ]
    [ dscp integer ];
provide-ixfr boolean;
query-source ( ( [ address ] ( ipv4_address | * ) [ port (
    integer | * ) ] ) | ( [ [ address ] ( ipv4_address | * ) ]
    port ( integer | * ) ) ) [ dscp integer ];
query-source-v6 ( ( [ address ] ( ipv6_address | * ) [ port (
    integer | * ) ] ) | ( [ [ address ] ( ipv6_address | * ) ]
    port ( integer | * ) ) ) [ dscp integer ];
request-expire boolean;
request-ixfr boolean;
request-nsid boolean;
send-cookie boolean;
tcp-only boolean;
transfer-format ( many-answers | one-answer );
transfer-source ( ipv4_address | * ) [ port ( integer | * ) ] [
    dscp integer ];
transfer-source-v6 ( ipv6_address | * ) [ port ( integer | * )
    ] [ dscp integer ];
transfers integer;
};

STATISTICS-CHANNELS


statistics-channels {
inet ( ipv4_address | ipv6_address |
    * ) [ port ( integer | * ) ] [
    allow { address_match_element; ...
    } ];
};

TRUSTED-KEYS


trusted-keys { string integer integer
    integer quoted_string; ... };

VIEW


view string [ class ] {
acache-cleaning-interval integer;
acache-enable boolean;
additional-from-auth boolean;
additional-from-cache boolean;
allow-new-zones boolean;
allow-notify { address_match_element; ... };
allow-query { address_match_element; ... };
allow-query-cache { address_match_element; ... };
allow-query-cache-on { address_match_element; ... };
allow-query-on { address_match_element; ... };
allow-recursion { address_match_element; ... };
allow-recursion-on { address_match_element; ... };
allow-transfer { address_match_element; ... };
allow-update { address_match_element; ... };
allow-update-forwarding { address_match_element; ... };
also-notify [ port integer ] [ dscp integer ] { ( masters |
    ipv4_address [ port integer ] | ipv6_address [ port
    integer ] ) [ key string ]; ... };
alt-transfer-source ( ipv4_address | * ) [ port ( integer | * )
    ] [ dscp integer ];
alt-transfer-source-v6 ( ipv6_address | * ) [ port ( integer |
    * ) ] [ dscp integer ];
attach-cache string;
auth-nxdomain boolean; // default changed
auto-dnssec ( allow | maintain | off );
cache-file quoted_string;
catalog-zones { zone quoted_string [ default-masters [ port
    integer ] [ dscp integer ] { ( masters | ipv4_address [
    port integer ] | ipv6_address [ port integer ] ) [ key
    string ]; ... } ] [ zone-directory quoted_string ] [
    in-memory boolean ] [ min-update-interval integer ]; ... };
check-dup-records ( fail | warn | ignore );
check-integrity boolean;
check-mx ( fail | warn | ignore );
check-mx-cname ( fail | warn | ignore );
check-names ( master | slave | response
    ) ( fail | warn | ignore );
check-sibling boolean;
check-spf ( warn | ignore );
check-srv-cname ( fail | warn | ignore );
check-wildcard boolean;
cleaning-interval integer;
clients-per-query integer;
deny-answer-addresses { address_match_element; ... } [
    except-from { quoted_string; ... } ];
deny-answer-aliases { quoted_string; ... } [ except-from {
    quoted_string; ... } ];
dialup ( notify | notify-passive | passive | refresh | boolean );
disable-algorithms string { string;
    ... };
disable-ds-digests string { string;
    ... };
disable-empty-zone string;
dlz string {
database string;
search boolean;
};
dns64 netprefix {
break-dnssec boolean;
clients { address_match_element; ... };
exclude { address_match_element; ... };
mapped { address_match_element; ... };
recursive-only boolean;
suffix ipv6_address;
};
dns64-contact string;
dns64-server string;
dnssec-accept-expired boolean;
dnssec-dnskey-kskonly boolean;
dnssec-enable boolean;
dnssec-loadkeys-interval integer;
dnssec-lookaside ( string trust-anchor
    string | auto | no );
dnssec-must-be-secure string boolean;
dnssec-secure-to-insecure boolean;
dnssec-update-mode ( maintain | no-resign );
dnssec-validation ( yes | no | auto );
dnstap { ( all | auth | client | forwarder |
    resolver ) [ ( query | response ) ]; ... };
dual-stack-servers [ port integer ] { ( quoted_string [ port
    integer ] [ dscp integer ] | ipv4_address [ port
    integer ] [ dscp integer ] | ipv6_address [ port
    integer ] [ dscp integer ] ); ... };
dyndb string quoted_string {
    unspecified-text };
edns-udp-size integer;
empty-contact string;
empty-server string;
empty-zones-enable boolean;
fetch-quota-params integer fixedpoint fixedpoint fixedpoint;
fetches-per-server integer [ ( drop | fail ) ];
fetches-per-zone integer [ ( drop | fail ) ];
filter-aaaa { address_match_element; ... };
filter-aaaa-on-v4 ( break-dnssec | boolean );
filter-aaaa-on-v6 ( break-dnssec | boolean );
forward ( first | only );
forwarders [ port integer ] [ dscp integer ] { ( ipv4_address
    | ipv6_address ) [ port integer ] [ dscp integer ]; ... };
inline-signing boolean;
ixfr-from-differences ( master | slave | boolean );
key string {
algorithm string;
secret string;
};
key-directory quoted_string;
lame-ttl ttlval;
lmdb-mapsize sizeval;
managed-keys { string string
    integer integer integer
    quoted_string; ... };
masterfile-format ( map | raw | text );
masterfile-style ( full | relative );
match-clients { address_match_element; ... };
match-destinations { address_match_element; ... };
match-recursive-only boolean;
max-acache-size ( unlimited | sizeval );
max-cache-size ( default | unlimited | sizeval | percentage );
max-cache-ttl integer;
max-clients-per-query integer;
max-journal-size ( unlimited | sizeval );
max-ncache-ttl integer;
max-records integer;
max-recursion-depth integer;
max-recursion-queries integer;
max-refresh-time integer;
max-retry-time integer;
max-transfer-idle-in integer;
max-transfer-idle-out integer;
max-transfer-time-in integer;
max-transfer-time-out integer;
max-udp-size integer;
max-zone-ttl ( unlimited | ttlval );
message-compression boolean;
min-refresh-time integer;
min-retry-time integer;
minimal-any boolean;
minimal-responses ( no-auth | no-auth-recursive | boolean );
multi-master boolean;
no-case-compress { address_match_element; ... };
nocookie-udp-size integer;
notify ( explicit | master-only | boolean );
notify-delay integer;
notify-source ( ipv4_address | * ) [ port ( integer | * ) ] [
    dscp integer ];
notify-source-v6 ( ipv6_address | * ) [ port ( integer | * ) ]
    [ dscp integer ];
notify-to-soa boolean;
nta-lifetime ttlval;
nta-recheck ttlval;
nxdomain-redirect string;
preferred-glue string;
prefetch integer [ integer ];
provide-ixfr boolean;
query-source ( ( [ address ] ( ipv4_address | * ) [ port (
    integer | * ) ] ) | ( [ [ address ] ( ipv4_address | * ) ]
    port ( integer | * ) ) ) [ dscp integer ];
query-source-v6 ( ( [ address ] ( ipv6_address | * ) [ port (
    integer | * ) ] ) | ( [ [ address ] ( ipv6_address | * ) ]
    port ( integer | * ) ) ) [ dscp integer ];
rate-limit {
all-per-second integer;
errors-per-second integer;
exempt-clients { address_match_element; ... };
ipv4-prefix-length integer;
ipv6-prefix-length integer;
log-only boolean;
max-table-size integer;
min-table-size integer;
nodata-per-second integer;
nxdomains-per-second integer;
qps-scale integer;
referrals-per-second integer;
responses-per-second integer;
slip integer;
window integer;
};
recursion boolean;
request-expire boolean;
request-ixfr boolean;
request-nsid boolean;
require-server-cookie boolean;
resolver-query-timeout integer;
response-policy { zone quoted_string [ log boolean ] [
    max-policy-ttl integer ] [ policy ( cname | disabled | drop |
    given | no-op | nodata | nxdomain | passthru | tcp-only
    quoted_string ) ] [ recursive-only boolean ]; ... } [
    break-dnssec boolean ] [ max-policy-ttl integer ] [
    min-ns-dots integer ] [ nsip-wait-recurse boolean ] [
    qname-wait-recurse boolean ] [ recursive-only boolean ];
root-delegation-only [ exclude { quoted_string; ... } ];
rrset-order { [ class string ] [ type string ] [ name
    quoted_string ] string string; ... };
send-cookie boolean;
serial-update-method ( date | increment | unixtime );
server netprefix {
bogus boolean;
edns boolean;
edns-udp-size integer;
edns-version integer;
keys server_key;
max-udp-size integer;
notify-source ( ipv4_address | * ) [ port ( integer | *
    ) ] [ dscp integer ];
notify-source-v6 ( ipv6_address | * ) [ port ( integer
    | * ) ] [ dscp integer ];
provide-ixfr boolean;
query-source ( ( [ address ] ( ipv4_address | * ) [ port
    ( integer | * ) ] ) | ( [ [ address ] (
    ipv4_address | * ) ] port ( integer | * ) ) ) [
    dscp integer ];
query-source-v6 ( ( [ address ] ( ipv6_address | * ) [
    port ( integer | * ) ] ) | ( [ [ address ] (
    ipv6_address | * ) ] port ( integer | * ) ) ) [
    dscp integer ];
request-expire boolean;
request-ixfr boolean;
request-nsid boolean;
send-cookie boolean;
tcp-only boolean;
transfer-format ( many-answers | one-answer );
transfer-source ( ipv4_address | * ) [ port ( integer |
    * ) ] [ dscp integer ];
transfer-source-v6 ( ipv6_address | * ) [ port (
    integer | * ) ] [ dscp integer ];
transfers integer;
};
servfail-ttl ttlval;
sig-signing-nodes integer;
sig-signing-signatures integer;
sig-signing-type integer;
sig-validity-interval integer [ integer ];
sortlist { address_match_element; ... };
transfer-format ( many-answers | one-answer );
transfer-source ( ipv4_address | * ) [ port ( integer | * ) ] [
    dscp integer ];
transfer-source-v6 ( ipv6_address | * ) [ port ( integer | * )
    ] [ dscp integer ];
trust-anchor-telemetry boolean; // experimental
trusted-keys { string integer
    integer integer quoted_string;
    ... };
try-tcp-refresh boolean;
update-check-ksk boolean;
use-alt-transfer-source boolean;
v6-bias integer;
zero-no-soa-ttl boolean;
zero-no-soa-ttl-cache boolean;
zone string [ class ] {
allow-notify { address_match_element; ... };
allow-query { address_match_element; ... };
allow-query-on { address_match_element; ... };
allow-transfer { address_match_element; ... };
allow-update { address_match_element; ... };
allow-update-forwarding { address_match_element; ... };
also-notify [ port integer ] [ dscp integer ] { (
    masters | ipv4_address [ port integer ] |
    ipv6_address [ port integer ] ) [ key string ];
    ... };
alt-transfer-source ( ipv4_address | * ) [ port (
    integer | * ) ] [ dscp integer ];
alt-transfer-source-v6 ( ipv6_address | * ) [ port (
    integer | * ) ] [ dscp integer ];
auto-dnssec ( allow | maintain | off );
check-dup-records ( fail | warn | ignore );
check-integrity boolean;
check-mx ( fail | warn | ignore );
check-mx-cname ( fail | warn | ignore );
check-names ( fail | warn | ignore );
check-sibling boolean;
check-spf ( warn | ignore );
check-srv-cname ( fail | warn | ignore );
check-wildcard boolean;
database string;
delegation-only boolean;
dialup ( notify | notify-passive | passive | refresh |
    boolean );
dlz string;
dnssec-dnskey-kskonly boolean;
dnssec-loadkeys-interval integer;
dnssec-secure-to-insecure boolean;
dnssec-update-mode ( maintain | no-resign );
file quoted_string;
forward ( first | only );
forwarders [ port integer ] [ dscp integer ] { (
    ipv4_address | ipv6_address ) [ port integer ] [
    dscp integer ]; ... };
in-view string;
inline-signing boolean;
ixfr-from-differences boolean;
journal quoted_string;
key-directory quoted_string;
masterfile-format ( map | raw | text );
masterfile-style ( full | relative );
masters [ port integer ] [ dscp integer ] { ( masters
    | ipv4_address [ port integer ] | ipv6_address [
    port integer ] ) [ key string ]; ... };
max-ixfr-log-size ( default | unlimited |
max-journal-size ( unlimited | sizeval );
max-records integer;
max-refresh-time integer;
max-retry-time integer;
max-transfer-idle-in integer;
max-transfer-idle-out integer;
max-transfer-time-in integer;
max-transfer-time-out integer;
max-zone-ttl ( unlimited | ttlval );
min-refresh-time integer;
min-retry-time integer;
multi-master boolean;
notify ( explicit | master-only | boolean );
notify-delay integer;
notify-source ( ipv4_address | * ) [ port ( integer | *
    ) ] [ dscp integer ];
notify-source-v6 ( ipv6_address | * ) [ port ( integer
    | * ) ] [ dscp integer ];
notify-to-soa boolean;
pubkey integer
    integer
    integer
request-expire boolean;
request-ixfr boolean;
serial-update-method ( date | increment | unixtime );
server-addresses { ( ipv4_address | ipv6_address ) [
    port integer ]; ... };
server-names { quoted_string; ... };
sig-signing-nodes integer;
sig-signing-signatures integer;
sig-signing-type integer;
sig-validity-interval integer [ integer ];
transfer-source ( ipv4_address | * ) [ port ( integer |
    * ) ] [ dscp integer ];
transfer-source-v6 ( ipv6_address | * ) [ port (
    integer | * ) ] [ dscp integer ];
try-tcp-refresh boolean;
type ( delegation-only | forward | hint | master | redirect
    | slave | static-stub | stub );
update-check-ksk boolean;
update-policy ( local | { ( deny | grant ) string (
    6to4-self | external | krb5-self | krb5-subdomain |
    ms-self | ms-subdomain | name | self | selfsub |
    selfwild | subdomain | tcp-self | wildcard | zonesub )
    [ string ] rrtypelist; ... };
use-alt-transfer-source boolean;
zero-no-soa-ttl boolean;
zone-statistics ( full | terse | none | boolean );
};
zone-statistics ( full | terse | none | boolean );
};

ZONE


zone string [ class ] {
allow-notify { address_match_element; ... };
allow-query { address_match_element; ... };
allow-query-on { address_match_element; ... };
allow-transfer { address_match_element; ... };
allow-update { address_match_element; ... };
allow-update-forwarding { address_match_element; ... };
also-notify [ port integer ] [ dscp integer ] { ( masters |
    ipv4_address [ port integer ] | ipv6_address [ port
    integer ] ) [ key string ]; ... };
alt-transfer-source ( ipv4_address | * ) [ port ( integer | * )
    ] [ dscp integer ];
alt-transfer-source-v6 ( ipv6_address | * ) [ port ( integer |
    * ) ] [ dscp integer ];
auto-dnssec ( allow | maintain | off );
check-dup-records ( fail | warn | ignore );
check-integrity boolean;
check-mx ( fail | warn | ignore );
check-mx-cname ( fail | warn | ignore );
check-names ( fail | warn | ignore );
check-sibling boolean;
check-spf ( warn | ignore );
check-srv-cname ( fail | warn | ignore );
check-wildcard boolean;
database string;
delegation-only boolean;
dialup ( notify | notify-passive | passive | refresh | boolean );
dlz string;
dnssec-dnskey-kskonly boolean;
dnssec-loadkeys-interval integer;
dnssec-secure-to-insecure boolean;
dnssec-update-mode ( maintain | no-resign );
file quoted_string;
forward ( first | only );
forwarders [ port integer ] [ dscp integer ] { ( ipv4_address
    | ipv6_address ) [ port integer ] [ dscp integer ]; ... };
in-view string;
inline-signing boolean;
ixfr-from-differences boolean;
journal quoted_string;
key-directory quoted_string;
masterfile-format ( map | raw | text );
masterfile-style ( full | relative );
masters [ port integer ] [ dscp integer ] { ( masters |
    ipv4_address [ port integer ] | ipv6_address [ port
    integer ] ) [ key string ]; ... };
max-journal-size ( unlimited | sizeval );
max-records integer;
max-refresh-time integer;
max-retry-time integer;
max-transfer-idle-in integer;
max-transfer-idle-out integer;
max-transfer-time-in integer;
max-transfer-time-out integer;
max-zone-ttl ( unlimited | ttlval );
min-refresh-time integer;
min-retry-time integer;
multi-master boolean;
notify ( explicit | master-only | boolean );
notify-delay integer;
notify-source ( ipv4_address | * ) [ port ( integer | * ) ] [
    dscp integer ];
notify-source-v6 ( ipv6_address | * ) [ port ( integer | * ) ]
    [ dscp integer ];
notify-to-soa boolean;
pubkey integer integer
request-expire boolean;
request-ixfr boolean;
serial-update-method ( date | increment | unixtime );
server-addresses { ( ipv4_address | ipv6_address ) [ port
    integer ]; ... };
server-names { quoted_string; ... };
sig-signing-nodes integer;
sig-signing-signatures integer;
sig-signing-type integer;
sig-validity-interval integer [ integer ];
transfer-source ( ipv4_address | * ) [ port ( integer | * ) ] [
    dscp integer ];
transfer-source-v6 ( ipv6_address | * ) [ port ( integer | * )
    ] [ dscp integer ];
try-tcp-refresh boolean;
type ( delegation-only | forward | hint | master | redirect | slave
    | static-stub | stub );
update-check-ksk boolean;
update-policy ( local | { ( deny | grant ) string ( 6to4-self |
    external | krb5-self | krb5-subdomain | ms-self | ms-subdomain
    | name | self | selfsub | selfwild | subdomain | tcp-self |
    wildcard | zonesub ) [ string ] rrtypelist; ... };
use-alt-transfer-source boolean;
zero-no-soa-ttl boolean;
zone-statistics ( full | terse | none | boolean );
};

FILES

/etc/named.conf

SEE ALSO

ddns-confgen(8) , named(8) , named-checkconf(8) , rndc(8) , rndc-confgen(8) , BIND 9 Administrator Reference Manual.

bind9-9.11.3+dfsg/bin/named/named.docbook000066400000000000000000000461551325250447100200310ustar00rootroot00000000000000 2014-02-19 ISC Internet Systems Consortium, Inc. named 8 BIND9 named Internet domain name server 2000 2001 2003 2004 2005 2006 2007 2008 2009 2011 2013 2014 2015 2016 2017 Internet Systems Consortium, Inc. ("ISC") named DESCRIPTION named is a Domain Name System (DNS) server, part of the BIND 9 distribution from ISC. For more information on the DNS, see RFCs 1033, 1034, and 1035. When invoked without arguments, named will read the default configuration file /etc/named.conf, read any initial data, and listen for queries. OPTIONS -4 Use IPv4 only even if the host machine is capable of IPv6. and are mutually exclusive. -6 Use IPv6 only even if the host machine is capable of IPv4. and are mutually exclusive. -c config-file Use config-file as the configuration file instead of the default, /etc/named.conf. To ensure that reloading the configuration file continues to work after the server has changed its working directory due to to a possible option in the configuration file, config-file should be an absolute pathname. -d debug-level Set the daemon's debug level to debug-level. Debugging traces from named become more verbose as the debug level increases. -D string Specifies a string that is used to identify a instance of named in a process listing. The contents of string are not examined. -E engine-name When applicable, specifies the hardware to use for cryptographic operations, such as a secure key store used for signing. When BIND is built with OpenSSL PKCS#11 support, this defaults to the string "pkcs11", which identifies an OpenSSL engine that can drive a cryptographic accelerator or hardware service module. When BIND is built with native PKCS#11 cryptography (--enable-native-pkcs11), it defaults to the path of the PKCS#11 provider library specified via "--with-pkcs11". -f Run the server in the foreground (i.e. do not daemonize). -g Run the server in the foreground and force all logging to stderr. -L logfile Log to the file by default instead of the system log. -M option Sets the default memory context options. Currently the only supported option is external, which causes the internal memory manager to be bypassed in favor of system-provided memory allocation functions. -m flag Turn on memory usage debugging flags. Possible flags are usage, trace, record, size, and mctx. These correspond to the ISC_MEM_DEBUGXXXX flags described in <isc/mem.h>. -n #cpus Create #cpus worker threads to take advantage of multiple CPUs. If not specified, named will try to determine the number of CPUs present and create one thread per CPU. If it is unable to determine the number of CPUs, a single worker thread will be created. -p port Listen for queries on port port. If not specified, the default is port 53. -s Write memory usage statistics to stdout on exit. This option is mainly of interest to BIND 9 developers and may be removed or changed in a future release. -S #max-socks Allow named to use up to #max-socks sockets. The default value is 4096 on systems built with default configuration options, and 21000 on systems built with "configure --with-tuning=large". This option should be unnecessary for the vast majority of users. The use of this option could even be harmful because the specified value may exceed the limitation of the underlying system API. It is therefore set only when the default configuration causes exhaustion of file descriptors and the operational environment is known to support the specified number of sockets. Note also that the actual maximum number is normally a little fewer than the specified value because named reserves some file descriptors for its internal use. -t directory Chroot to directory after processing the command line arguments, but before reading the configuration file. This option should be used in conjunction with the option, as chrooting a process running as root doesn't enhance security on most systems; the way chroot(2) is defined allows a process with root privileges to escape a chroot jail. -U #listeners Use #listeners worker threads to listen for incoming UDP packets on each address. If not specified, named will calculate a default value based on the number of detected CPUs: 1 for 1 CPU, and the number of detected CPUs minus one for machines with more than 1 CPU. This cannot be increased to a value higher than the number of CPUs. If has been set to a higher value than the number of detected CPUs, then may be increased as high as that value, but no higher. On Windows, the number of UDP listeners is hardwired to 1 and this option has no effect. -u user Setuid to user after completing privileged operations, such as creating sockets that listen on privileged ports. On Linux, named uses the kernel's capability mechanism to drop all root privileges except the ability to bind(2) to a privileged port and set process resource limits. Unfortunately, this means that the option only works when named is run on kernel 2.2.18 or later, or kernel 2.3.99-pre3 or later, since previous kernels did not allow privileges to be retained after setuid(2). -v Report the version number and exit. -V Report the version number and build options, and exit. -X lock-file Acquire a lock on the specified file at runtime; this helps to prevent duplicate named instances from running simultaneously. Use of this option overrides the lock-file option in named.conf. If set to none, the lock file check is disabled. -x cache-file Load data from cache-file into the cache of the default view. This option must not be used. It is only of interest to BIND 9 developers and may be removed or changed in a future release. SIGNALS In routine operation, signals should not be used to control the nameserver; rndc should be used instead. SIGHUP Force a reload of the server. SIGINT, SIGTERM Shut down the server. The result of sending any other signals to the server is undefined. CONFIGURATION The named configuration file is too complex to describe in detail here. A complete description is provided in the BIND 9 Administrator Reference Manual. named inherits the umask (file creation mode mask) from the parent process. If files created by named, such as journal files, need to have custom permissions, the umask should be set explicitly in the script used to start the named process. FILES /etc/named.conf The default configuration file. /var/run/named/named.pid The default process-id file. SEE ALSO RFC 1033, RFC 1034, RFC 1035, named-checkconf 8 , named-checkzone 8 , rndc 8 , lwresd 8 , named.conf 5 , BIND 9 Administrator Reference Manual. bind9-9.11.3+dfsg/bin/named/named.html000066400000000000000000000432521325250447100173500ustar00rootroot00000000000000 named

Name

named — Internet domain name server

Synopsis

named [ [-4] | [-6] ] [-c config-file] [-d debug-level] [-D string] [-E engine-name] [-f] [-g] [-L logfile] [-M option] [-m flag] [-n #cpus] [-p port] [-s] [-S #max-socks] [-t directory] [-U #listeners] [-u user] [-v] [-V] [-X lock-file] [-x cache-file]

DESCRIPTION

named is a Domain Name System (DNS) server, part of the BIND 9 distribution from ISC. For more information on the DNS, see RFCs 1033, 1034, and 1035.

When invoked without arguments, named will read the default configuration file /etc/named.conf, read any initial data, and listen for queries.

OPTIONS

-4

Use IPv4 only even if the host machine is capable of IPv6. -4 and -6 are mutually exclusive.

-6

Use IPv6 only even if the host machine is capable of IPv4. -4 and -6 are mutually exclusive.

-c config-file

Use config-file as the configuration file instead of the default, /etc/named.conf. To ensure that reloading the configuration file continues to work after the server has changed its working directory due to to a possible directory option in the configuration file, config-file should be an absolute pathname.

-d debug-level

Set the daemon's debug level to debug-level. Debugging traces from named become more verbose as the debug level increases.

-D string

Specifies a string that is used to identify a instance of named in a process listing. The contents of string are not examined.

-E engine-name

When applicable, specifies the hardware to use for cryptographic operations, such as a secure key store used for signing.

When BIND is built with OpenSSL PKCS#11 support, this defaults to the string "pkcs11", which identifies an OpenSSL engine that can drive a cryptographic accelerator or hardware service module. When BIND is built with native PKCS#11 cryptography (--enable-native-pkcs11), it defaults to the path of the PKCS#11 provider library specified via "--with-pkcs11".

-f

Run the server in the foreground (i.e. do not daemonize).

-g

Run the server in the foreground and force all logging to stderr.

-L logfile

Log to the file logfile by default instead of the system log.

-M option

Sets the default memory context options. Currently the only supported option is external, which causes the internal memory manager to be bypassed in favor of system-provided memory allocation functions.

-m flag

Turn on memory usage debugging flags. Possible flags are usage, trace, record, size, and mctx. These correspond to the ISC_MEM_DEBUGXXXX flags described in <isc/mem.h>.

-n #cpus

Create #cpus worker threads to take advantage of multiple CPUs. If not specified, named will try to determine the number of CPUs present and create one thread per CPU. If it is unable to determine the number of CPUs, a single worker thread will be created.

-p port

Listen for queries on port port. If not specified, the default is port 53.

-s

Write memory usage statistics to stdout on exit.

Note

This option is mainly of interest to BIND 9 developers and may be removed or changed in a future release.

-S #max-socks

Allow named to use up to #max-socks sockets. The default value is 4096 on systems built with default configuration options, and 21000 on systems built with "configure --with-tuning=large".

Warning

This option should be unnecessary for the vast majority of users. The use of this option could even be harmful because the specified value may exceed the limitation of the underlying system API. It is therefore set only when the default configuration causes exhaustion of file descriptors and the operational environment is known to support the specified number of sockets. Note also that the actual maximum number is normally a little fewer than the specified value because named reserves some file descriptors for its internal use.

-t directory

Chroot to directory after processing the command line arguments, but before reading the configuration file.

Warning

This option should be used in conjunction with the -u option, as chrooting a process running as root doesn't enhance security on most systems; the way chroot(2) is defined allows a process with root privileges to escape a chroot jail.

-U #listeners

Use #listeners worker threads to listen for incoming UDP packets on each address. If not specified, named will calculate a default value based on the number of detected CPUs: 1 for 1 CPU, and the number of detected CPUs minus one for machines with more than 1 CPU. This cannot be increased to a value higher than the number of CPUs. If -n has been set to a higher value than the number of detected CPUs, then -U may be increased as high as that value, but no higher. On Windows, the number of UDP listeners is hardwired to 1 and this option has no effect.

-u user

Setuid to user after completing privileged operations, such as creating sockets that listen on privileged ports.

Note

On Linux, named uses the kernel's capability mechanism to drop all root privileges except the ability to bind(2) to a privileged port and set process resource limits. Unfortunately, this means that the -u option only works when named is run on kernel 2.2.18 or later, or kernel 2.3.99-pre3 or later, since previous kernels did not allow privileges to be retained after setuid(2).

-v

Report the version number and exit.

-V

Report the version number and build options, and exit.

-X lock-file

Acquire a lock on the specified file at runtime; this helps to prevent duplicate named instances from running simultaneously. Use of this option overrides the lock-file option in named.conf. If set to none, the lock file check is disabled.

-x cache-file

Load data from cache-file into the cache of the default view.

Warning

This option must not be used. It is only of interest to BIND 9 developers and may be removed or changed in a future release.

SIGNALS

In routine operation, signals should not be used to control the nameserver; rndc should be used instead.

SIGHUP

Force a reload of the server.

SIGINT, SIGTERM

Shut down the server.

The result of sending any other signals to the server is undefined.

CONFIGURATION

The named configuration file is too complex to describe in detail here. A complete description is provided in the BIND 9 Administrator Reference Manual.

named inherits the umask (file creation mode mask) from the parent process. If files created by named, such as journal files, need to have custom permissions, the umask should be set explicitly in the script used to start the named process.

FILES

/etc/named.conf

The default configuration file.

/var/run/named/named.pid

The default process-id file.

SEE ALSO

RFC 1033, RFC 1034, RFC 1035, named-checkconf (8) , named-checkzone (8) , rndc (8) , lwresd (8) , named.conf (5) , BIND 9 Administrator Reference Manual.

bind9-9.11.3+dfsg/bin/named/notify.c000066400000000000000000000103331325250447100170440ustar00rootroot00000000000000/* * Copyright (C) 1999-2007, 2016, 2018 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* $Id: notify.c,v 1.37 2007/06/19 23:46:59 tbox Exp $ */ #include #include #include #include #include #include #include #include #include #include #include #include /*! \file * \brief * This module implements notify as in RFC1996. */ static void notify_log(ns_client_t *client, int level, const char *fmt, ...) { va_list ap; va_start(ap, fmt); ns_client_logv(client, DNS_LOGCATEGORY_NOTIFY, NS_LOGMODULE_NOTIFY, level, fmt, ap); va_end(ap); } static void respond(ns_client_t *client, isc_result_t result) { dns_rcode_t rcode; dns_message_t *message; isc_result_t msg_result; message = client->message; rcode = dns_result_torcode(result); msg_result = dns_message_reply(message, ISC_TRUE); if (msg_result != ISC_R_SUCCESS) msg_result = dns_message_reply(message, ISC_FALSE); if (msg_result != ISC_R_SUCCESS) { ns_client_next(client, msg_result); return; } message->rcode = rcode; if (rcode == dns_rcode_noerror) message->flags |= DNS_MESSAGEFLAG_AA; else message->flags &= ~DNS_MESSAGEFLAG_AA; ns_client_send(client); } void ns_notify_start(ns_client_t *client) { dns_message_t *request = client->message; isc_result_t result; dns_name_t *zonename; dns_rdataset_t *zone_rdataset; dns_zone_t *zone = NULL; char namebuf[DNS_NAME_FORMATSIZE]; char tsigbuf[DNS_NAME_FORMATSIZE + sizeof(": TSIG ''")]; dns_tsigkey_t *tsigkey; /* * Interpret the question section. */ result = dns_message_firstname(request, DNS_SECTION_QUESTION); if (result != ISC_R_SUCCESS) { notify_log(client, ISC_LOG_NOTICE, "notify question section empty"); result = DNS_R_FORMERR; goto done; } /* * The question section must contain exactly one question. */ zonename = NULL; dns_message_currentname(request, DNS_SECTION_QUESTION, &zonename); zone_rdataset = ISC_LIST_HEAD(zonename->list); if (ISC_LIST_NEXT(zone_rdataset, link) != NULL) { notify_log(client, ISC_LOG_NOTICE, "notify question section contains multiple RRs"); result = DNS_R_FORMERR; goto done; } /* The zone section must have exactly one name. */ result = dns_message_nextname(request, DNS_SECTION_ZONE); if (result != ISC_R_NOMORE) { notify_log(client, ISC_LOG_NOTICE, "notify question section contains multiple RRs"); result = DNS_R_FORMERR; goto done; } /* The one rdataset must be an SOA. */ if (zone_rdataset->type != dns_rdatatype_soa) { notify_log(client, ISC_LOG_NOTICE, "notify question section contains no SOA"); result = DNS_R_FORMERR; goto done; } tsigkey = dns_message_gettsigkey(request); if (tsigkey != NULL) { dns_name_format(&tsigkey->name, namebuf, sizeof(namebuf)); if (tsigkey->generated) { char cnamebuf[DNS_NAME_FORMATSIZE]; dns_name_format(tsigkey->creator, cnamebuf, sizeof(cnamebuf)); snprintf(tsigbuf, sizeof(tsigbuf), ": TSIG '%s' (%s)", namebuf, cnamebuf); } else { snprintf(tsigbuf, sizeof(tsigbuf), ": TSIG '%s'", namebuf); } } else tsigbuf[0] = '\0'; dns_name_format(zonename, namebuf, sizeof(namebuf)); result = dns_zt_find(client->view->zonetable, zonename, 0, NULL, &zone); if (result == ISC_R_SUCCESS) { dns_zonetype_t zonetype = dns_zone_gettype(zone); if ((zonetype == dns_zone_master) || (zonetype == dns_zone_slave) || (zonetype == dns_zone_stub)) { isc_sockaddr_t *from = ns_client_getsockaddr(client); isc_sockaddr_t *to = ns_client_getdestaddr(client); notify_log(client, ISC_LOG_INFO, "received notify for zone '%s'%s", namebuf, tsigbuf); result = dns_zone_notifyreceive2(zone, from, to, request); goto done; } } notify_log(client, ISC_LOG_NOTICE, "received notify for zone '%s'%s: not authoritative", namebuf, tsigbuf); result = DNS_R_NOTAUTH; done: if (zone != NULL) dns_zone_detach(&zone); respond(client, result); } bind9-9.11.3+dfsg/bin/named/query.c000066400000000000000000010161661325250447100167140ustar00rootroot00000000000000/* * Copyright (C) 1999-2018 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /*! \file */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if 0 /* * It has been recommended that DNS64 be changed to return excluded * AAAA addresses if DNS64 synthesis does not occur. This minimises * the impact on the lookup results. While most DNS AAAA lookups are * done to send IP packets to a host, not all of them are and filtering * excluded addresses has a negative impact on those uses. */ #define dns64_bis_return_excluded_addresses 1 #endif /*% Partial answer? */ #define PARTIALANSWER(c) (((c)->query.attributes & \ NS_QUERYATTR_PARTIALANSWER) != 0) /*% Use Cache? */ #define USECACHE(c) (((c)->query.attributes & \ NS_QUERYATTR_CACHEOK) != 0) /*% Recursion OK? */ #define RECURSIONOK(c) (((c)->query.attributes & \ NS_QUERYATTR_RECURSIONOK) != 0) /*% Recursing? */ #define RECURSING(c) (((c)->query.attributes & \ NS_QUERYATTR_RECURSING) != 0) /*% Cache glue ok? */ #define CACHEGLUEOK(c) (((c)->query.attributes & \ NS_QUERYATTR_CACHEGLUEOK) != 0) /*% Want Recursion? */ #define WANTRECURSION(c) (((c)->query.attributes & \ NS_QUERYATTR_WANTRECURSION) != 0) /*% Is TCP? */ #define TCP(c) (((c)->attributes & NS_CLIENTATTR_TCP) != 0) /*% Want DNSSEC? */ #define WANTDNSSEC(c) (((c)->attributes & \ NS_CLIENTATTR_WANTDNSSEC) != 0) /*% Want WANTAD? */ #define WANTAD(c) (((c)->attributes & \ NS_CLIENTATTR_WANTAD) != 0) /*% Client presented a valid COOKIE. */ #define HAVECOOKIE(c) (((c)->attributes & \ NS_CLIENTATTR_HAVECOOKIE) != 0) /*% Client presented a COOKIE. */ #define WANTCOOKIE(c) (((c)->attributes & \ NS_CLIENTATTR_WANTCOOKIE) != 0) /*% No authority? */ #define NOAUTHORITY(c) (((c)->query.attributes & \ NS_QUERYATTR_NOAUTHORITY) != 0) /*% No additional? */ #define NOADDITIONAL(c) (((c)->query.attributes & \ NS_QUERYATTR_NOADDITIONAL) != 0) /*% Secure? */ #define SECURE(c) (((c)->query.attributes & \ NS_QUERYATTR_SECURE) != 0) /*% DNS64 A lookup? */ #define DNS64(c) (((c)->query.attributes & \ NS_QUERYATTR_DNS64) != 0) #define DNS64EXCLUDE(c) (((c)->query.attributes & \ NS_QUERYATTR_DNS64EXCLUDE) != 0) #define REDIRECT(c) (((c)->query.attributes & \ NS_QUERYATTR_REDIRECT) != 0) /*% No QNAME Proof? */ #define NOQNAME(r) (((r)->attributes & \ DNS_RDATASETATTR_NOQNAME) != 0) #ifdef WANT_QUERYTRACE static inline void client_trace(ns_client_t *client, int level, const char *message) { if (client != NULL && client->query.qname != NULL) { if (isc_log_wouldlog(ns_g_lctx, level)) { char qbuf[DNS_NAME_FORMATSIZE]; char tbuf[DNS_RDATATYPE_FORMATSIZE]; dns_name_format(client->query.qname, qbuf, sizeof(qbuf)); dns_rdatatype_format(client->query.qtype, tbuf, sizeof(tbuf)); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_CLIENT, NS_LOGMODULE_QUERY, level, "query client=%p thread=0x%lx " "(%s/%s): %s", client, (unsigned long) isc_thread_self(), qbuf, tbuf, message); } } else { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_CLIENT, NS_LOGMODULE_QUERY, level, "query client=%p thread=0x%lx " "(): %s", client, (unsigned long) isc_thread_self(), message); } } #define CTRACE(l,m) client_trace(client, l, m) #else #define CTRACE(l,m) ((void)m) #endif /* WANT_QUERYTRACE */ #define DNS_GETDB_NOEXACT 0x01U #define DNS_GETDB_NOLOG 0x02U #define DNS_GETDB_PARTIAL 0x04U #define DNS_GETDB_IGNOREACL 0x08U #define PENDINGOK(x) (((x) & DNS_DBFIND_PENDINGOK) != 0) #define SFCACHE_CDFLAG 0x1 /* * These have the same semantics as: * * foo_attach(b, a); * foo_detach(&a); * * without the locking and magic testing. * * We use SAVE and RESTORE as that shows the operation being performed. */ #define SAVE(a, b) do { INSIST(a == NULL); a = b; b = NULL; } while (0) #define RESTORE(a, b) SAVE(a, b) typedef struct client_additionalctx { ns_client_t *client; dns_rdataset_t *rdataset; } client_additionalctx_t; static isc_result_t query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype); static isc_boolean_t validate(ns_client_t *client, dns_db_t *db, dns_name_t *name, dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset); static void query_findclosestnsec3(dns_name_t *qname, dns_db_t *db, dns_dbversion_t *version, ns_client_t *client, dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset, dns_name_t *fname, isc_boolean_t exact, dns_name_t *found); static inline void log_queryerror(ns_client_t *client, isc_result_t result, int line, int level); static void rpz_st_clear(ns_client_t *client); static isc_boolean_t rpz_ck_dnssec(ns_client_t *client, isc_result_t qresult, dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset); /*% * Increment query statistics counters. */ static inline void inc_stats(ns_client_t *client, isc_statscounter_t counter) { dns_zone_t *zone = client->query.authzone; dns_rdatatype_t qtype; dns_rdataset_t *rdataset; isc_stats_t *zonestats; dns_stats_t *querystats = NULL; isc_stats_increment(ns_g_server->nsstats, counter); if (zone == NULL) return; /* Do regular response type stats */ zonestats = dns_zone_getrequeststats(zone); if (zonestats != NULL) isc_stats_increment(zonestats, counter); /* Do query type statistics * * We only increment per-type if we're using the authoritative * answer counter, preventing double-counting. */ if (counter == dns_nsstatscounter_authans) { querystats = dns_zone_getrcvquerystats(zone); if (querystats != NULL) { rdataset = ISC_LIST_HEAD(client->query.qname->list); if (rdataset != NULL) { qtype = rdataset->type; dns_rdatatypestats_increment(querystats, qtype); } } } } static void query_send(ns_client_t *client) { isc_statscounter_t counter; if ((client->message->flags & DNS_MESSAGEFLAG_AA) == 0) inc_stats(client, dns_nsstatscounter_nonauthans); else inc_stats(client, dns_nsstatscounter_authans); if (client->message->rcode == dns_rcode_noerror) { dns_section_t answer = DNS_SECTION_ANSWER; if (ISC_LIST_EMPTY(client->message->sections[answer])) { if (client->query.isreferral) counter = dns_nsstatscounter_referral; else counter = dns_nsstatscounter_nxrrset; } else counter = dns_nsstatscounter_success; } else if (client->message->rcode == dns_rcode_nxdomain) counter = dns_nsstatscounter_nxdomain; else if (client->message->rcode == dns_rcode_badcookie) counter = dns_nsstatscounter_badcookie; else /* We end up here in case of YXDOMAIN, and maybe others */ counter = dns_nsstatscounter_failure; inc_stats(client, counter); ns_client_send(client); } static void query_error(ns_client_t *client, isc_result_t result, int line) { int loglevel = ISC_LOG_DEBUG(3); switch (result) { case DNS_R_SERVFAIL: loglevel = ISC_LOG_DEBUG(1); inc_stats(client, dns_nsstatscounter_servfail); break; case DNS_R_FORMERR: inc_stats(client, dns_nsstatscounter_formerr); break; default: inc_stats(client, dns_nsstatscounter_failure); break; } if (ns_g_server->log_queries) loglevel = ISC_LOG_INFO; log_queryerror(client, result, line, loglevel); ns_client_error(client, result); } static void query_next(ns_client_t *client, isc_result_t result) { if (result == DNS_R_DUPLICATE) inc_stats(client, dns_nsstatscounter_duplicate); else if (result == DNS_R_DROP) inc_stats(client, dns_nsstatscounter_dropped); else inc_stats(client, dns_nsstatscounter_failure); ns_client_next(client, result); } static inline void query_freefreeversions(ns_client_t *client, isc_boolean_t everything) { ns_dbversion_t *dbversion, *dbversion_next; unsigned int i; for (dbversion = ISC_LIST_HEAD(client->query.freeversions), i = 0; dbversion != NULL; dbversion = dbversion_next, i++) { dbversion_next = ISC_LIST_NEXT(dbversion, link); /* * If we're not freeing everything, we keep the first three * dbversions structures around. */ if (i > 3 || everything) { ISC_LIST_UNLINK(client->query.freeversions, dbversion, link); isc_mem_put(client->mctx, dbversion, sizeof(*dbversion)); } } } void ns_query_cancel(ns_client_t *client) { REQUIRE(NS_CLIENT_VALID(client)); LOCK(&client->query.fetchlock); if (client->query.fetch != NULL) { dns_resolver_cancelfetch(client->query.fetch); client->query.fetch = NULL; } UNLOCK(&client->query.fetchlock); } static inline void query_putrdataset(ns_client_t *client, dns_rdataset_t **rdatasetp) { dns_rdataset_t *rdataset = *rdatasetp; CTRACE(ISC_LOG_DEBUG(3), "query_putrdataset"); if (rdataset != NULL) { if (dns_rdataset_isassociated(rdataset)) dns_rdataset_disassociate(rdataset); dns_message_puttemprdataset(client->message, rdatasetp); } CTRACE(ISC_LOG_DEBUG(3), "query_putrdataset: done"); } static inline void query_reset(ns_client_t *client, isc_boolean_t everything) { isc_buffer_t *dbuf, *dbuf_next; ns_dbversion_t *dbversion, *dbversion_next; CTRACE(ISC_LOG_DEBUG(3), "query_reset"); /*% * Reset the query state of a client to its default state. */ /* * Cancel the fetch if it's running. */ ns_query_cancel(client); /* * Cleanup any active versions. */ for (dbversion = ISC_LIST_HEAD(client->query.activeversions); dbversion != NULL; dbversion = dbversion_next) { dbversion_next = ISC_LIST_NEXT(dbversion, link); dns_db_closeversion(dbversion->db, &dbversion->version, ISC_FALSE); dns_db_detach(&dbversion->db); ISC_LIST_INITANDAPPEND(client->query.freeversions, dbversion, link); } ISC_LIST_INIT(client->query.activeversions); if (client->query.authdb != NULL) dns_db_detach(&client->query.authdb); if (client->query.authzone != NULL) dns_zone_detach(&client->query.authzone); if (client->query.dns64_aaaa != NULL) query_putrdataset(client, &client->query.dns64_aaaa); if (client->query.dns64_sigaaaa != NULL) query_putrdataset(client, &client->query.dns64_sigaaaa); if (client->query.dns64_aaaaok != NULL) { isc_mem_put(client->mctx, client->query.dns64_aaaaok, client->query.dns64_aaaaoklen * sizeof(isc_boolean_t)); client->query.dns64_aaaaok = NULL; client->query.dns64_aaaaoklen = 0; } query_putrdataset(client, &client->query.redirect.rdataset); query_putrdataset(client, &client->query.redirect.sigrdataset); if (client->query.redirect.db != NULL) { if (client->query.redirect.node != NULL) dns_db_detachnode(client->query.redirect.db, &client->query.redirect.node); dns_db_detach(&client->query.redirect.db); } if (client->query.redirect.zone != NULL) dns_zone_detach(&client->query.redirect.zone); query_freefreeversions(client, everything); for (dbuf = ISC_LIST_HEAD(client->query.namebufs); dbuf != NULL; dbuf = dbuf_next) { dbuf_next = ISC_LIST_NEXT(dbuf, link); if (dbuf_next != NULL || everything) { ISC_LIST_UNLINK(client->query.namebufs, dbuf, link); isc_buffer_free(&dbuf); } } if (client->query.restarts > 0) { /* * client->query.qname was dynamically allocated. */ dns_message_puttempname(client->message, &client->query.qname); } client->query.qname = NULL; client->query.attributes = (NS_QUERYATTR_RECURSIONOK | NS_QUERYATTR_CACHEOK | NS_QUERYATTR_SECURE); client->query.restarts = 0; client->query.timerset = ISC_FALSE; if (client->query.rpz_st != NULL) { rpz_st_clear(client); if (everything) { isc_mem_put(client->mctx, client->query.rpz_st, sizeof(*client->query.rpz_st)); client->query.rpz_st = NULL; } } client->query.origqname = NULL; client->query.dboptions = 0; client->query.fetchoptions = 0; client->query.gluedb = NULL; client->query.authdbset = ISC_FALSE; client->query.isreferral = ISC_FALSE; client->query.dns64_options = 0; client->query.dns64_ttl = ISC_UINT32_MAX; } static void query_next_callback(ns_client_t *client) { query_reset(client, ISC_FALSE); } void ns_query_free(ns_client_t *client) { REQUIRE(NS_CLIENT_VALID(client)); query_reset(client, ISC_TRUE); } static inline isc_result_t query_newnamebuf(ns_client_t *client) { isc_buffer_t *dbuf; isc_result_t result; CTRACE(ISC_LOG_DEBUG(3), "query_newnamebuf"); /*% * Allocate a name buffer. */ dbuf = NULL; result = isc_buffer_allocate(client->mctx, &dbuf, 1024); if (result != ISC_R_SUCCESS) { CTRACE(ISC_LOG_DEBUG(3), "query_newnamebuf: isc_buffer_allocate failed: done"); return (result); } ISC_LIST_APPEND(client->query.namebufs, dbuf, link); CTRACE(ISC_LOG_DEBUG(3), "query_newnamebuf: done"); return (ISC_R_SUCCESS); } static inline isc_buffer_t * query_getnamebuf(ns_client_t *client) { isc_buffer_t *dbuf; isc_result_t result; isc_region_t r; CTRACE(ISC_LOG_DEBUG(3), "query_getnamebuf"); /*% * Return a name buffer with space for a maximal name, allocating * a new one if necessary. */ if (ISC_LIST_EMPTY(client->query.namebufs)) { result = query_newnamebuf(client); if (result != ISC_R_SUCCESS) { CTRACE(ISC_LOG_DEBUG(3), "query_getnamebuf: query_newnamebuf failed: done"); return (NULL); } } dbuf = ISC_LIST_TAIL(client->query.namebufs); INSIST(dbuf != NULL); isc_buffer_availableregion(dbuf, &r); if (r.length < DNS_NAME_MAXWIRE) { result = query_newnamebuf(client); if (result != ISC_R_SUCCESS) { CTRACE(ISC_LOG_DEBUG(3), "query_getnamebuf: query_newnamebuf failed: done"); return (NULL); } dbuf = ISC_LIST_TAIL(client->query.namebufs); isc_buffer_availableregion(dbuf, &r); INSIST(r.length >= 255); } CTRACE(ISC_LOG_DEBUG(3), "query_getnamebuf: done"); return (dbuf); } static inline void query_keepname(ns_client_t *client, dns_name_t *name, isc_buffer_t *dbuf) { isc_region_t r; CTRACE(ISC_LOG_DEBUG(3), "query_keepname"); /*% * 'name' is using space in 'dbuf', but 'dbuf' has not yet been * adjusted to take account of that. We do the adjustment. */ REQUIRE((client->query.attributes & NS_QUERYATTR_NAMEBUFUSED) != 0); dns_name_toregion(name, &r); isc_buffer_add(dbuf, r.length); dns_name_setbuffer(name, NULL); client->query.attributes &= ~NS_QUERYATTR_NAMEBUFUSED; } static inline void query_releasename(ns_client_t *client, dns_name_t **namep) { dns_name_t *name = *namep; /*% * 'name' is no longer needed. Return it to our pool of temporary * names. If it is using a name buffer, relinquish its exclusive * rights on the buffer. */ CTRACE(ISC_LOG_DEBUG(3), "query_releasename"); if (dns_name_hasbuffer(name)) { INSIST((client->query.attributes & NS_QUERYATTR_NAMEBUFUSED) != 0); client->query.attributes &= ~NS_QUERYATTR_NAMEBUFUSED; } dns_message_puttempname(client->message, namep); CTRACE(ISC_LOG_DEBUG(3), "query_releasename: done"); } static inline dns_name_t * query_newname(ns_client_t *client, isc_buffer_t *dbuf, isc_buffer_t *nbuf) { dns_name_t *name; isc_region_t r; isc_result_t result; REQUIRE((client->query.attributes & NS_QUERYATTR_NAMEBUFUSED) == 0); CTRACE(ISC_LOG_DEBUG(3), "query_newname"); name = NULL; result = dns_message_gettempname(client->message, &name); if (result != ISC_R_SUCCESS) { CTRACE(ISC_LOG_DEBUG(3), "query_newname: dns_message_gettempname failed: done"); return (NULL); } isc_buffer_availableregion(dbuf, &r); isc_buffer_init(nbuf, r.base, r.length); dns_name_init(name, NULL); dns_name_setbuffer(name, nbuf); client->query.attributes |= NS_QUERYATTR_NAMEBUFUSED; CTRACE(ISC_LOG_DEBUG(3), "query_newname: done"); return (name); } static inline dns_rdataset_t * query_newrdataset(ns_client_t *client) { dns_rdataset_t *rdataset; isc_result_t result; CTRACE(ISC_LOG_DEBUG(3), "query_newrdataset"); rdataset = NULL; result = dns_message_gettemprdataset(client->message, &rdataset); if (result != ISC_R_SUCCESS) { CTRACE(ISC_LOG_DEBUG(3), "query_newrdataset: " "dns_message_gettemprdataset failed: done"); return (NULL); } CTRACE(ISC_LOG_DEBUG(3), "query_newrdataset: done"); return (rdataset); } static inline isc_result_t query_newdbversion(ns_client_t *client, unsigned int n) { unsigned int i; ns_dbversion_t *dbversion; for (i = 0; i < n; i++) { dbversion = isc_mem_get(client->mctx, sizeof(*dbversion)); if (dbversion != NULL) { dbversion->db = NULL; dbversion->version = NULL; ISC_LIST_INITANDAPPEND(client->query.freeversions, dbversion, link); } else { /* * We only return ISC_R_NOMEMORY if we couldn't * allocate anything. */ if (i == 0) return (ISC_R_NOMEMORY); else return (ISC_R_SUCCESS); } } return (ISC_R_SUCCESS); } static inline ns_dbversion_t * query_getdbversion(ns_client_t *client) { isc_result_t result; ns_dbversion_t *dbversion; if (ISC_LIST_EMPTY(client->query.freeversions)) { result = query_newdbversion(client, 1); if (result != ISC_R_SUCCESS) return (NULL); } dbversion = ISC_LIST_HEAD(client->query.freeversions); INSIST(dbversion != NULL); ISC_LIST_UNLINK(client->query.freeversions, dbversion, link); return (dbversion); } isc_result_t ns_query_init(ns_client_t *client) { isc_result_t result; REQUIRE(NS_CLIENT_VALID(client)); ISC_LIST_INIT(client->query.namebufs); ISC_LIST_INIT(client->query.activeversions); ISC_LIST_INIT(client->query.freeversions); client->query.restarts = 0; client->query.timerset = ISC_FALSE; client->query.rpz_st = NULL; client->query.qname = NULL; /* * This mutex is destroyed when the client is destroyed in * exit_check(). */ result = isc_mutex_init(&client->query.fetchlock); if (result != ISC_R_SUCCESS) return (result); client->query.fetch = NULL; client->query.prefetch = NULL; client->query.authdb = NULL; client->query.authzone = NULL; client->query.authdbset = ISC_FALSE; client->query.isreferral = ISC_FALSE; client->query.dns64_aaaa = NULL; client->query.dns64_sigaaaa = NULL; client->query.dns64_aaaaok = NULL; client->query.dns64_aaaaoklen = 0; client->query.redirect.db = NULL; client->query.redirect.node = NULL; client->query.redirect.zone = NULL; client->query.redirect.qtype = dns_rdatatype_none; client->query.redirect.result = ISC_R_SUCCESS; client->query.redirect.rdataset = NULL; client->query.redirect.sigrdataset = NULL; client->query.redirect.authoritative = ISC_FALSE; client->query.redirect.is_zone = ISC_FALSE; dns_fixedname_init(&client->query.redirect.fixed); client->query.redirect.fname = dns_fixedname_name(&client->query.redirect.fixed); query_reset(client, ISC_FALSE); result = query_newdbversion(client, 3); if (result != ISC_R_SUCCESS) { DESTROYLOCK(&client->query.fetchlock); return (result); } result = query_newnamebuf(client); if (result != ISC_R_SUCCESS) { query_freefreeversions(client, ISC_TRUE); DESTROYLOCK(&client->query.fetchlock); } return (result); } static ns_dbversion_t * query_findversion(ns_client_t *client, dns_db_t *db) { ns_dbversion_t *dbversion; /*% * We may already have done a query related to this * database. If so, we must be sure to make subsequent * queries from the same version. */ for (dbversion = ISC_LIST_HEAD(client->query.activeversions); dbversion != NULL; dbversion = ISC_LIST_NEXT(dbversion, link)) { if (dbversion->db == db) break; } if (dbversion == NULL) { /* * This is a new zone for this query. Add it to * the active list. */ dbversion = query_getdbversion(client); if (dbversion == NULL) return (NULL); dns_db_attach(db, &dbversion->db); dns_db_currentversion(db, &dbversion->version); dbversion->acl_checked = ISC_FALSE; dbversion->queryok = ISC_FALSE; ISC_LIST_APPEND(client->query.activeversions, dbversion, link); } return (dbversion); } static inline isc_result_t query_validatezonedb(ns_client_t *client, dns_name_t *name, dns_rdatatype_t qtype, unsigned int options, dns_zone_t *zone, dns_db_t *db, dns_dbversion_t **versionp) { isc_result_t result; dns_acl_t *queryacl, *queryonacl; ns_dbversion_t *dbversion; REQUIRE(zone != NULL); REQUIRE(db != NULL); /* * This limits our searching to the zone where the first name * (the query target) was looked for. This prevents following * CNAMES or DNAMES into other zones and prevents returning * additional data from other zones. */ if (!client->view->additionalfromauth && client->query.authdbset && db != client->query.authdb) return (DNS_R_REFUSED); /* * Non recursive query to a static-stub zone is prohibited; its * zone content is not public data, but a part of local configuration * and should not be disclosed. */ if (dns_zone_gettype(zone) == dns_zone_staticstub && !RECURSIONOK(client)) { return (DNS_R_REFUSED); } /* * If the zone has an ACL, we'll check it, otherwise * we use the view's "allow-query" ACL. Each ACL is only checked * once per query. * * Also, get the database version to use. */ /* * Get the current version of this database. */ dbversion = query_findversion(client, db); if (dbversion == NULL) { CTRACE(ISC_LOG_ERROR, "unable to get db version"); return (DNS_R_SERVFAIL); } if ((options & DNS_GETDB_IGNOREACL) != 0) goto approved; if (dbversion->acl_checked) { if (!dbversion->queryok) return (DNS_R_REFUSED); goto approved; } queryacl = dns_zone_getqueryacl(zone); if (queryacl == NULL) { queryacl = client->view->queryacl; if ((client->query.attributes & NS_QUERYATTR_QUERYOKVALID) != 0) { /* * We've evaluated the view's queryacl already. If * NS_QUERYATTR_QUERYOK is set, then the client is * allowed to make queries, otherwise the query should * be refused. */ dbversion->acl_checked = ISC_TRUE; if ((client->query.attributes & NS_QUERYATTR_QUERYOK) == 0) { dbversion->queryok = ISC_FALSE; return (DNS_R_REFUSED); } dbversion->queryok = ISC_TRUE; goto approved; } } result = ns_client_checkaclsilent(client, NULL, queryacl, ISC_TRUE); if ((options & DNS_GETDB_NOLOG) == 0) { char msg[NS_CLIENT_ACLMSGSIZE("query")]; if (result == ISC_R_SUCCESS) { if (isc_log_wouldlog(ns_g_lctx, ISC_LOG_DEBUG(3))) { ns_client_aclmsg("query", name, qtype, client->view->rdclass, msg, sizeof(msg)); ns_client_log(client, DNS_LOGCATEGORY_SECURITY, NS_LOGMODULE_QUERY, ISC_LOG_DEBUG(3), "%s approved", msg); } } else { ns_client_aclmsg("query", name, qtype, client->view->rdclass, msg, sizeof(msg)); ns_client_log(client, DNS_LOGCATEGORY_SECURITY, NS_LOGMODULE_QUERY, ISC_LOG_INFO, "%s denied", msg); } } if (queryacl == client->view->queryacl) { if (result == ISC_R_SUCCESS) { /* * We were allowed by the default * "allow-query" ACL. Remember this so we * don't have to check again. */ client->query.attributes |= NS_QUERYATTR_QUERYOK; } /* * We've now evaluated the view's query ACL, and * the NS_QUERYATTR_QUERYOK attribute is now valid. */ client->query.attributes |= NS_QUERYATTR_QUERYOKVALID; } /* If and only if we've gotten this far, check allow-query-on too */ if (result == ISC_R_SUCCESS) { queryonacl = dns_zone_getqueryonacl(zone); if (queryonacl == NULL) queryonacl = client->view->queryonacl; result = ns_client_checkaclsilent(client, &client->destaddr, queryonacl, ISC_TRUE); if ((options & DNS_GETDB_NOLOG) == 0 && result != ISC_R_SUCCESS) ns_client_log(client, DNS_LOGCATEGORY_SECURITY, NS_LOGMODULE_QUERY, ISC_LOG_INFO, "query-on denied"); } dbversion->acl_checked = ISC_TRUE; if (result != ISC_R_SUCCESS) { dbversion->queryok = ISC_FALSE; return (DNS_R_REFUSED); } dbversion->queryok = ISC_TRUE; approved: /* Transfer ownership, if necessary. */ if (versionp != NULL) *versionp = dbversion->version; return (ISC_R_SUCCESS); } static inline isc_result_t query_getzonedb(ns_client_t *client, dns_name_t *name, dns_rdatatype_t qtype, unsigned int options, dns_zone_t **zonep, dns_db_t **dbp, dns_dbversion_t **versionp) { isc_result_t result; unsigned int ztoptions; dns_zone_t *zone = NULL; dns_db_t *db = NULL; isc_boolean_t partial = ISC_FALSE; REQUIRE(zonep != NULL && *zonep == NULL); REQUIRE(dbp != NULL && *dbp == NULL); /*% * Find a zone database to answer the query. */ ztoptions = ((options & DNS_GETDB_NOEXACT) != 0) ? DNS_ZTFIND_NOEXACT : 0; result = dns_zt_find(client->view->zonetable, name, ztoptions, NULL, &zone); if (result == DNS_R_PARTIALMATCH) partial = ISC_TRUE; if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) result = dns_zone_getdb(zone, &db); if (result != ISC_R_SUCCESS) goto fail; result = query_validatezonedb(client, name, qtype, options, zone, db, versionp); if (result != ISC_R_SUCCESS) goto fail; /* Transfer ownership. */ *zonep = zone; *dbp = db; if (partial && (options & DNS_GETDB_PARTIAL) != 0) return (DNS_R_PARTIALMATCH); return (ISC_R_SUCCESS); fail: if (zone != NULL) dns_zone_detach(&zone); if (db != NULL) dns_db_detach(&db); return (result); } static void rpz_log_rewrite(ns_client_t *client, isc_boolean_t disabled, dns_rpz_policy_t policy, dns_rpz_type_t type, dns_zone_t *p_zone, dns_name_t *p_name, dns_name_t *cname, dns_rpz_num_t rpz_num) { isc_stats_t *zonestats; char qname_buf[DNS_NAME_FORMATSIZE]; char p_name_buf[DNS_NAME_FORMATSIZE]; char cname_buf[DNS_NAME_FORMATSIZE] = { 0 }; const char *s1 = cname_buf, *s2 = cname_buf; dns_rpz_st_t *st; /* * Count enabled rewrites in the global counter. * Count both enabled and disabled rewrites for each zone. */ if (!disabled && policy != DNS_RPZ_POLICY_PASSTHRU) { isc_stats_increment(ns_g_server->nsstats, dns_nsstatscounter_rpz_rewrites); } if (p_zone != NULL) { zonestats = dns_zone_getrequeststats(p_zone); if (zonestats != NULL) isc_stats_increment(zonestats, dns_nsstatscounter_rpz_rewrites); } if (!isc_log_wouldlog(ns_g_lctx, DNS_RPZ_INFO_LEVEL)) return; st = client->query.rpz_st; if ((st->popt.no_log & DNS_RPZ_ZBIT(rpz_num)) != 0) return; dns_name_format(client->query.qname, qname_buf, sizeof(qname_buf)); dns_name_format(p_name, p_name_buf, sizeof(p_name_buf)); if (cname != NULL) { s1 = " (CNAME to: "; dns_name_format(cname, cname_buf, sizeof(cname_buf)); s2 = ")"; } ns_client_log(client, DNS_LOGCATEGORY_RPZ, NS_LOGMODULE_QUERY, DNS_RPZ_INFO_LEVEL, "%srpz %s %s rewrite %s via %s%s%s%s", disabled ? "disabled " : "", dns_rpz_type2str(type), dns_rpz_policy2str(policy), qname_buf, p_name_buf, s1, cname_buf, s2); } static void rpz_log_fail_helper(ns_client_t *client, int level, dns_name_t *p_name, dns_rpz_type_t rpz_type1, dns_rpz_type_t rpz_type2, const char *str, isc_result_t result) { char qnamebuf[DNS_NAME_FORMATSIZE]; char p_namebuf[DNS_NAME_FORMATSIZE]; const char *failed; const char *slash; const char *via; const char *str_blank; const char *rpztypestr1; const char *rpztypestr2; if (!isc_log_wouldlog(ns_g_lctx, level)) return; /* * bin/tests/system/rpz/tests.sh looks for "rpz.*failed" for problems. */ if (level <= DNS_RPZ_DEBUG_LEVEL1) failed = "failed: "; else failed = ": "; rpztypestr1 = dns_rpz_type2str(rpz_type1); if (rpz_type2 != DNS_RPZ_TYPE_BAD) { slash = "/"; rpztypestr2 = dns_rpz_type2str(rpz_type2); } else { slash = ""; rpztypestr2 = ""; } str_blank = (*str != ' ' && *str != '\0') ? " " : ""; dns_name_format(client->query.qname, qnamebuf, sizeof(qnamebuf)); if (p_name != NULL) { via = " via "; dns_name_format(p_name, p_namebuf, sizeof(p_namebuf)); } else { via = ""; p_namebuf[0] = '\0'; } ns_client_log(client, NS_LOGCATEGORY_QUERY_ERRORS, NS_LOGMODULE_QUERY, level, "rpz %s%s%s rewrite %s%s%s%s%s%s : %s", rpztypestr1, slash, rpztypestr2, qnamebuf, via, p_namebuf, str_blank, str, failed, isc_result_totext(result)); } static void rpz_log_fail(ns_client_t *client, int level, dns_name_t *p_name, dns_rpz_type_t rpz_type, const char *str, isc_result_t result) { rpz_log_fail_helper(client, level, p_name, rpz_type, DNS_RPZ_TYPE_BAD, str, result); } /* * Get a policy rewrite zone database. */ static isc_result_t rpz_getdb(ns_client_t *client, dns_name_t *p_name, dns_rpz_type_t rpz_type, dns_zone_t **zonep, dns_db_t **dbp, dns_dbversion_t **versionp) { char qnamebuf[DNS_NAME_FORMATSIZE]; char p_namebuf[DNS_NAME_FORMATSIZE]; dns_dbversion_t *rpz_version = NULL; isc_result_t result; CTRACE(ISC_LOG_DEBUG(3), "rpz_getdb"); result = query_getzonedb(client, p_name, dns_rdatatype_any, DNS_GETDB_IGNOREACL, zonep, dbp, &rpz_version); if (result == ISC_R_SUCCESS) { dns_rpz_st_t *st = client->query.rpz_st; /* * It isn't meaningful to log this message when * logging is disabled for some policy zones. */ if (st->popt.no_log == 0 && isc_log_wouldlog(ns_g_lctx, DNS_RPZ_DEBUG_LEVEL2)) { dns_name_format(client->query.qname, qnamebuf, sizeof(qnamebuf)); dns_name_format(p_name, p_namebuf, sizeof(p_namebuf)); ns_client_log(client, DNS_LOGCATEGORY_RPZ, NS_LOGMODULE_QUERY, DNS_RPZ_DEBUG_LEVEL2, "try rpz %s rewrite %s via %s", dns_rpz_type2str(rpz_type), qnamebuf, p_namebuf); } *versionp = rpz_version; return (ISC_R_SUCCESS); } rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, p_name, rpz_type, " query_getzonedb()", result); return (result); } static inline isc_result_t query_getcachedb(ns_client_t *client, dns_name_t *name, dns_rdatatype_t qtype, dns_db_t **dbp, unsigned int options) { isc_result_t result; isc_boolean_t check_acl; dns_db_t *db = NULL; REQUIRE(dbp != NULL && *dbp == NULL); /*% * Find a cache database to answer the query. * This may fail with DNS_R_REFUSED if the client * is not allowed to use the cache. */ if (!USECACHE(client)) return (DNS_R_REFUSED); dns_db_attach(client->view->cachedb, &db); if ((client->query.attributes & NS_QUERYATTR_CACHEACLOKVALID) != 0) { /* * We've evaluated the view's cacheacl already. If * NS_QUERYATTR_CACHEACLOK is set, then the client is * allowed to make queries, otherwise the query should * be refused. */ check_acl = ISC_FALSE; if ((client->query.attributes & NS_QUERYATTR_CACHEACLOK) == 0) goto refuse; } else { /* * We haven't evaluated the view's queryacl yet. */ check_acl = ISC_TRUE; } if (check_acl) { isc_boolean_t log = ISC_TF((options & DNS_GETDB_NOLOG) == 0); char msg[NS_CLIENT_ACLMSGSIZE("query (cache)")]; result = ns_client_checkaclsilent(client, NULL, client->view->cacheacl, ISC_TRUE); if (result == ISC_R_SUCCESS) { /* * We were allowed by the "allow-query-cache" ACL. * Remember this so we don't have to check again. */ client->query.attributes |= NS_QUERYATTR_CACHEACLOK; if (log && isc_log_wouldlog(ns_g_lctx, ISC_LOG_DEBUG(3))) { ns_client_aclmsg("query (cache)", name, qtype, client->view->rdclass, msg, sizeof(msg)); ns_client_log(client, DNS_LOGCATEGORY_SECURITY, NS_LOGMODULE_QUERY, ISC_LOG_DEBUG(3), "%s approved", msg); } } else if (log) { ns_client_aclmsg("query (cache)", name, qtype, client->view->rdclass, msg, sizeof(msg)); ns_client_log(client, DNS_LOGCATEGORY_SECURITY, NS_LOGMODULE_QUERY, ISC_LOG_INFO, "%s denied", msg); } /* * We've now evaluated the view's query ACL, and * the NS_QUERYATTR_CACHEACLOKVALID attribute is now valid. */ client->query.attributes |= NS_QUERYATTR_CACHEACLOKVALID; if (result != ISC_R_SUCCESS) goto refuse; } /* Approved. */ /* Transfer ownership. */ *dbp = db; return (ISC_R_SUCCESS); refuse: result = DNS_R_REFUSED; if (db != NULL) dns_db_detach(&db); return (result); } static inline isc_result_t query_getdb(ns_client_t *client, dns_name_t *name, dns_rdatatype_t qtype, unsigned int options, dns_zone_t **zonep, dns_db_t **dbp, dns_dbversion_t **versionp, isc_boolean_t *is_zonep) { isc_result_t result; isc_result_t tresult; unsigned int namelabels; unsigned int zonelabels; dns_zone_t *zone = NULL; REQUIRE(zonep != NULL && *zonep == NULL); /* Calculate how many labels are in name. */ namelabels = dns_name_countlabels(name); zonelabels = 0; /* Try to find name in bind's standard database. */ result = query_getzonedb(client, name, qtype, options, &zone, dbp, versionp); /* See how many labels are in the zone's name. */ if (result == ISC_R_SUCCESS && zone != NULL) zonelabels = dns_name_countlabels(dns_zone_getorigin(zone)); /* * If # zone labels < # name labels, try to find an even better match * Only try if DLZ drivers are loaded for this view */ if (ISC_UNLIKELY(zonelabels < namelabels && !ISC_LIST_EMPTY(client->view->dlz_searched))) { dns_clientinfomethods_t cm; dns_clientinfo_t ci; dns_db_t *tdbp; dns_clientinfomethods_init(&cm, ns_client_sourceip); dns_clientinfo_init(&ci, client, NULL); tdbp = NULL; tresult = dns_view_searchdlz(client->view, name, zonelabels, &cm, &ci, &tdbp); /* If we successful, we found a better match. */ if (tresult == ISC_R_SUCCESS) { ns_dbversion_t *dbversion; /* * If the previous search returned a zone, detach it. */ if (zone != NULL) dns_zone_detach(&zone); /* * If the previous search returned a database, * detach it. */ if (*dbp != NULL) dns_db_detach(dbp); /* * If the previous search returned a version, clear it. */ *versionp = NULL; dbversion = query_findversion(client, tdbp); if (dbversion == NULL) { tresult = ISC_R_NOMEMORY; } else { /* * Be sure to return our database. */ *dbp = tdbp; *versionp = dbversion->version; } /* * We return a null zone, No stats for DLZ zones. */ zone = NULL; result = tresult; } } /* If successful, Transfer ownership of zone. */ if (result == ISC_R_SUCCESS) { *zonep = zone; /* * If neither attempt above succeeded, return the cache instead */ *is_zonep = ISC_TRUE; } else if (result == ISC_R_NOTFOUND) { result = query_getcachedb(client, name, qtype, dbp, options); *is_zonep = ISC_FALSE; } return (result); } static inline isc_boolean_t query_isduplicate(ns_client_t *client, dns_name_t *name, dns_rdatatype_t type, dns_name_t **mnamep) { dns_section_t section; dns_name_t *mname = NULL; isc_result_t result; CTRACE(ISC_LOG_DEBUG(3), "query_isduplicate"); for (section = DNS_SECTION_ANSWER; section <= DNS_SECTION_ADDITIONAL; section++) { result = dns_message_findname(client->message, section, name, type, 0, &mname, NULL); if (result == ISC_R_SUCCESS) { /* * We've already got this RRset in the response. */ CTRACE(ISC_LOG_DEBUG(3), "query_isduplicate: true: done"); return (ISC_TRUE); } else if (result == DNS_R_NXRRSET) { /* * The name exists, but the rdataset does not. */ if (section == DNS_SECTION_ADDITIONAL) break; } else RUNTIME_CHECK(result == DNS_R_NXDOMAIN); mname = NULL; } if (mnamep != NULL) *mnamep = mname; CTRACE(ISC_LOG_DEBUG(3), "query_isduplicate: false: done"); return (ISC_FALSE); } static isc_result_t query_addadditional(void *arg, dns_name_t *name, dns_rdatatype_t qtype) { ns_client_t *client = arg; isc_result_t result, eresult; dns_dbnode_t *node; dns_db_t *db; dns_name_t *fname, *mname; dns_rdataset_t *rdataset, *sigrdataset, *trdataset; isc_buffer_t *dbuf; isc_buffer_t b; dns_dbversion_t *version; isc_boolean_t added_something, need_addname; dns_zone_t *zone; dns_rdatatype_t type; dns_clientinfomethods_t cm; dns_clientinfo_t ci; dns_rdatasetadditional_t additionaltype; REQUIRE(NS_CLIENT_VALID(client)); REQUIRE(qtype != dns_rdatatype_any); if (!WANTDNSSEC(client) && dns_rdatatype_isdnssec(qtype)) return (ISC_R_SUCCESS); CTRACE(ISC_LOG_DEBUG(3), "query_addadditional"); /* * Initialization. */ eresult = ISC_R_SUCCESS; fname = NULL; rdataset = NULL; sigrdataset = NULL; trdataset = NULL; db = NULL; version = NULL; node = NULL; added_something = ISC_FALSE; need_addname = ISC_FALSE; zone = NULL; additionaltype = dns_rdatasetadditional_fromauth; dns_clientinfomethods_init(&cm, ns_client_sourceip); dns_clientinfo_init(&ci, client, NULL); /* * We treat type A additional section processing as if it * were "any address type" additional section processing. * To avoid multiple lookups, we do an 'any' database * lookup and iterate over the node. */ if (qtype == dns_rdatatype_a) type = dns_rdatatype_any; else type = qtype; /* * Get some resources. */ dbuf = query_getnamebuf(client); if (dbuf == NULL) goto cleanup; fname = query_newname(client, dbuf, &b); rdataset = query_newrdataset(client); if (fname == NULL || rdataset == NULL) goto cleanup; if (WANTDNSSEC(client)) { sigrdataset = query_newrdataset(client); if (sigrdataset == NULL) goto cleanup; } /* * Look for a zone database that might contain authoritative * additional data. */ result = query_getzonedb(client, name, qtype, DNS_GETDB_NOLOG, &zone, &db, &version); if (result != ISC_R_SUCCESS) goto try_cache; CTRACE(ISC_LOG_DEBUG(3), "query_addadditional: db_find"); /* * Since we are looking for authoritative data, we do not set * the GLUEOK flag. Glue will be looked for later, but not * necessarily in the same database. */ result = dns_db_findext(db, name, version, type, client->query.dboptions, client->now, &node, fname, &cm, &ci, rdataset, sigrdataset); if (result == ISC_R_SUCCESS) { if (sigrdataset != NULL && !dns_db_issecure(db) && dns_rdataset_isassociated(sigrdataset)) dns_rdataset_disassociate(sigrdataset); goto found; } if (dns_rdataset_isassociated(rdataset)) dns_rdataset_disassociate(rdataset); if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset)) dns_rdataset_disassociate(sigrdataset); if (node != NULL) dns_db_detachnode(db, &node); version = NULL; dns_db_detach(&db); /* * No authoritative data was found. The cache is our next best bet. */ try_cache: additionaltype = dns_rdatasetadditional_fromcache; result = query_getcachedb(client, name, qtype, &db, DNS_GETDB_NOLOG); if (result != ISC_R_SUCCESS) /* * Most likely the client isn't allowed to query the cache. */ goto try_glue; /* * Attempt to validate glue. */ if (sigrdataset == NULL) { sigrdataset = query_newrdataset(client); if (sigrdataset == NULL) goto cleanup; } result = dns_db_findext(db, name, version, type, client->query.dboptions | DNS_DBFIND_GLUEOK | DNS_DBFIND_ADDITIONALOK, client->now, &node, fname, &cm, &ci, rdataset, sigrdataset); dns_cache_updatestats(client->view->cache, result); if (!WANTDNSSEC(client)) query_putrdataset(client, &sigrdataset); if (result == ISC_R_SUCCESS) goto found; if (dns_rdataset_isassociated(rdataset)) dns_rdataset_disassociate(rdataset); if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset)) dns_rdataset_disassociate(sigrdataset); if (node != NULL) dns_db_detachnode(db, &node); dns_db_detach(&db); try_glue: /* * No cached data was found. Glue is our last chance. * RFC1035 sayeth: * * NS records cause both the usual additional section * processing to locate a type A record, and, when used * in a referral, a special search of the zone in which * they reside for glue information. * * This is the "special search". Note that we must search * the zone where the NS record resides, not the zone it * points to, and that we only do the search in the delegation * case (identified by client->query.gluedb being set). */ if (client->query.gluedb == NULL) goto cleanup; /* * Don't poison caches using the bailiwick protection model. */ if (!dns_name_issubdomain(name, dns_db_origin(client->query.gluedb))) goto cleanup; dns_db_attach(client->query.gluedb, &db); additionaltype = dns_rdatasetadditional_fromglue; result = dns_db_findext(db, name, version, type, client->query.dboptions | DNS_DBFIND_GLUEOK, client->now, &node, fname, &cm, &ci, rdataset, sigrdataset); if (!(result == ISC_R_SUCCESS || result == DNS_R_ZONECUT || result == DNS_R_GLUE)) goto cleanup; found: /* * We have found a potential additional data rdataset, or * at least a node to iterate over. */ query_keepname(client, fname, dbuf); /* * If we have an rdataset, add it to the additional data * section. */ mname = NULL; if (dns_rdataset_isassociated(rdataset) && !query_isduplicate(client, fname, type, &mname)) { if (mname != NULL) { INSIST(mname != fname); query_releasename(client, &fname); fname = mname; } else need_addname = ISC_TRUE; ISC_LIST_APPEND(fname->list, rdataset, link); trdataset = rdataset; rdataset = NULL; added_something = ISC_TRUE; /* * Note: we only add SIGs if we've added the type they cover, * so we do not need to check if the SIG rdataset is already * in the response. */ if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset)) { ISC_LIST_APPEND(fname->list, sigrdataset, link); sigrdataset = NULL; } } if (qtype == dns_rdatatype_a) { #ifdef ALLOW_FILTER_AAAA isc_boolean_t have_a = ISC_FALSE; #endif /* * We now go looking for A and AAAA records, along with * their signatures. * * XXXRTH This code could be more efficient. */ if (rdataset != NULL) { if (dns_rdataset_isassociated(rdataset)) dns_rdataset_disassociate(rdataset); } else { rdataset = query_newrdataset(client); if (rdataset == NULL) goto addname; } if (sigrdataset != NULL) { if (dns_rdataset_isassociated(sigrdataset)) dns_rdataset_disassociate(sigrdataset); } else if (WANTDNSSEC(client)) { sigrdataset = query_newrdataset(client); if (sigrdataset == NULL) goto addname; } if (query_isduplicate(client, fname, dns_rdatatype_a, NULL)) goto aaaa_lookup; result = dns_db_findrdataset(db, node, version, dns_rdatatype_a, 0, client->now, rdataset, sigrdataset); if (result == DNS_R_NCACHENXDOMAIN) goto addname; if (result == DNS_R_NCACHENXRRSET) { dns_rdataset_disassociate(rdataset); if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset)) dns_rdataset_disassociate(sigrdataset); } if (result == ISC_R_SUCCESS) { mname = NULL; #ifdef ALLOW_FILTER_AAAA have_a = ISC_TRUE; #endif if (additionaltype == dns_rdatasetadditional_fromcache && (DNS_TRUST_PENDING(rdataset->trust) || DNS_TRUST_GLUE(rdataset->trust)) && !validate(client, db, fname, rdataset, sigrdataset)) { dns_rdataset_disassociate(rdataset); if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset)) dns_rdataset_disassociate(sigrdataset); /* treat as if not found */ } else if (!query_isduplicate(client, fname, dns_rdatatype_a, &mname)) { if (mname != fname) { if (mname != NULL) { query_releasename(client, &fname); fname = mname; } else need_addname = ISC_TRUE; } ISC_LIST_APPEND(fname->list, rdataset, link); added_something = ISC_TRUE; if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset)) { ISC_LIST_APPEND(fname->list, sigrdataset, link); sigrdataset = query_newrdataset(client); } rdataset = query_newrdataset(client); if (rdataset == NULL) goto addname; if (WANTDNSSEC(client) && sigrdataset == NULL) goto addname; } else { dns_rdataset_disassociate(rdataset); if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset)) dns_rdataset_disassociate(sigrdataset); } } aaaa_lookup: if (query_isduplicate(client, fname, dns_rdatatype_aaaa, NULL)) goto addname; result = dns_db_findrdataset(db, node, version, dns_rdatatype_aaaa, 0, client->now, rdataset, sigrdataset); if (result == DNS_R_NCACHENXDOMAIN) goto addname; if (result == DNS_R_NCACHENXRRSET) { dns_rdataset_disassociate(rdataset); if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset)) dns_rdataset_disassociate(sigrdataset); } if (result == ISC_R_SUCCESS) { mname = NULL; /* * There's an A; check whether we're filtering AAAA */ #ifdef ALLOW_FILTER_AAAA if (have_a && (client->filter_aaaa == dns_aaaa_break_dnssec || (client->filter_aaaa == dns_aaaa_filter && (!WANTDNSSEC(client) || sigrdataset == NULL || !dns_rdataset_isassociated(sigrdataset))))) goto addname; #endif if (additionaltype == dns_rdatasetadditional_fromcache && (DNS_TRUST_PENDING(rdataset->trust) || DNS_TRUST_GLUE(rdataset->trust)) && !validate(client, db, fname, rdataset, sigrdataset)) { dns_rdataset_disassociate(rdataset); if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset)) dns_rdataset_disassociate(sigrdataset); /* treat as if not found */ } else if (!query_isduplicate(client, fname, dns_rdatatype_aaaa, &mname)) { if (mname != fname) { if (mname != NULL) { query_releasename(client, &fname); fname = mname; } else need_addname = ISC_TRUE; } ISC_LIST_APPEND(fname->list, rdataset, link); added_something = ISC_TRUE; if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset)) { ISC_LIST_APPEND(fname->list, sigrdataset, link); sigrdataset = NULL; } rdataset = NULL; } } } addname: CTRACE(ISC_LOG_DEBUG(3), "query_addadditional: addname"); /* * If we haven't added anything, then we're done. */ if (!added_something) goto cleanup; /* * We may have added our rdatasets to an existing name, if so, then * need_addname will be ISC_FALSE. Whether we used an existing name * or a new one, we must set fname to NULL to prevent cleanup. */ if (need_addname) dns_message_addname(client->message, fname, DNS_SECTION_ADDITIONAL); fname = NULL; /* * In a few cases, we want to add additional data for additional * data. It's simpler to just deal with special cases here than * to try to create a general purpose mechanism and allow the * rdata implementations to do it themselves. * * This involves recursion, but the depth is limited. The * most complex case is adding a SRV rdataset, which involves * recursing to add address records, which in turn can cause * recursion to add KEYs. */ if (type == dns_rdatatype_srv && trdataset != NULL) { /* * If we're adding SRV records to the additional data * section, it's helpful if we add the SRV additional data * as well. */ eresult = dns_rdataset_additionaldata(trdataset, query_addadditional, client); } cleanup: CTRACE(ISC_LOG_DEBUG(3), "query_addadditional: cleanup"); query_putrdataset(client, &rdataset); if (sigrdataset != NULL) query_putrdataset(client, &sigrdataset); if (fname != NULL) query_releasename(client, &fname); if (node != NULL) dns_db_detachnode(db, &node); if (db != NULL) dns_db_detach(&db); if (zone != NULL) dns_zone_detach(&zone); CTRACE(ISC_LOG_DEBUG(3), "query_addadditional: done"); return (eresult); } static inline void query_discardcache(ns_client_t *client, dns_rdataset_t *rdataset_base, dns_rdatasetadditional_t additionaltype, dns_rdatatype_t type, dns_zone_t **zonep, dns_db_t **dbp, dns_dbversion_t **versionp, dns_dbnode_t **nodep, dns_name_t *fname) { dns_rdataset_t *rdataset; while ((rdataset = ISC_LIST_HEAD(fname->list)) != NULL) { ISC_LIST_UNLINK(fname->list, rdataset, link); query_putrdataset(client, &rdataset); } if (*versionp != NULL) dns_db_closeversion(*dbp, versionp, ISC_FALSE); if (*nodep != NULL) dns_db_detachnode(*dbp, nodep); if (*dbp != NULL) dns_db_detach(dbp); if (*zonep != NULL) dns_zone_detach(zonep); (void)dns_rdataset_putadditional(client->view->acache, rdataset_base, additionaltype, type); } static inline isc_result_t query_iscachevalid(dns_zone_t *zone, dns_db_t *db, dns_db_t *db0, dns_dbversion_t *version) { isc_result_t result = ISC_R_SUCCESS; dns_dbversion_t *version_current = NULL; dns_db_t *db_current = db0; if (db_current == NULL) { result = dns_zone_getdb(zone, &db_current); if (result != ISC_R_SUCCESS) return (result); } dns_db_currentversion(db_current, &version_current); if (db_current != db || version_current != version) { result = ISC_R_FAILURE; goto cleanup; } cleanup: dns_db_closeversion(db_current, &version_current, ISC_FALSE); if (db0 == NULL && db_current != NULL) dns_db_detach(&db_current); return (result); } static isc_result_t query_addadditional2(void *arg, dns_name_t *name, dns_rdatatype_t qtype) { client_additionalctx_t *additionalctx = arg; dns_rdataset_t *rdataset_base; ns_client_t *client; isc_result_t result, eresult; dns_dbnode_t *node, *cnode; dns_db_t *db, *cdb; dns_name_t *fname, *mname0, cfname; dns_rdataset_t *rdataset, *sigrdataset; dns_rdataset_t *crdataset, *crdataset_next; isc_buffer_t *dbuf; isc_buffer_t b; dns_dbversion_t *version, *cversion; isc_boolean_t added_something, need_addname, needadditionalcache; isc_boolean_t need_sigrrset; dns_zone_t *zone; dns_rdatatype_t type; dns_rdatasetadditional_t additionaltype; dns_clientinfomethods_t cm; dns_clientinfo_t ci; /* * If we don't have an additional cache call query_addadditional. */ client = additionalctx->client; REQUIRE(NS_CLIENT_VALID(client)); if (qtype != dns_rdatatype_a || client->view->acache == NULL) { /* * This function is optimized for "address" types. For other * types, use a generic routine. * XXX: ideally, this function should be generic enough. */ return (query_addadditional(additionalctx->client, name, qtype)); } /* * Initialization. */ rdataset_base = additionalctx->rdataset; eresult = ISC_R_SUCCESS; fname = NULL; rdataset = NULL; sigrdataset = NULL; db = NULL; cdb = NULL; version = NULL; cversion = NULL; node = NULL; cnode = NULL; added_something = ISC_FALSE; need_addname = ISC_FALSE; zone = NULL; needadditionalcache = ISC_FALSE; POST(needadditionalcache); additionaltype = dns_rdatasetadditional_fromauth; dns_name_init(&cfname, NULL); dns_clientinfomethods_init(&cm, ns_client_sourceip); dns_clientinfo_init(&ci, client, NULL); CTRACE(ISC_LOG_DEBUG(3), "query_addadditional2"); /* * We treat type A additional section processing as if it * were "any address type" additional section processing. * To avoid multiple lookups, we do an 'any' database * lookup and iterate over the node. * XXXJT: this approach can cause a suboptimal result when the cache * DB only has partial address types and the glue DB has remaining * ones. */ type = dns_rdatatype_any; /* * Get some resources. */ dbuf = query_getnamebuf(client); if (dbuf == NULL) goto cleanup; fname = query_newname(client, dbuf, &b); if (fname == NULL) goto cleanup; dns_name_setbuffer(&cfname, &b); /* share the buffer */ /* Check additional cache */ result = dns_rdataset_getadditional(rdataset_base, additionaltype, type, client->view->acache, &zone, &cdb, &cversion, &cnode, &cfname, client->message, client->now); if (result != ISC_R_SUCCESS) goto findauthdb; if (zone == NULL) { CTRACE(ISC_LOG_DEBUG(3), "query_addadditional2: auth zone not found"); goto try_cache; } /* Is the cached DB up-to-date? */ result = query_iscachevalid(zone, cdb, NULL, cversion); if (result != ISC_R_SUCCESS) { CTRACE(ISC_LOG_DEBUG(3), "query_addadditional2: old auth additional cache"); query_discardcache(client, rdataset_base, additionaltype, type, &zone, &cdb, &cversion, &cnode, &cfname); goto findauthdb; } if (cnode == NULL) { /* * We have a negative cache. We don't have to check the zone * ACL, since the result (not using this zone) would be same * regardless of the result. */ CTRACE(ISC_LOG_DEBUG(3), "query_addadditional2: negative auth additional cache"); dns_db_closeversion(cdb, &cversion, ISC_FALSE); dns_db_detach(&cdb); dns_zone_detach(&zone); goto try_cache; } result = query_validatezonedb(client, name, qtype, DNS_GETDB_NOLOG, zone, cdb, NULL); if (result != ISC_R_SUCCESS) { query_discardcache(client, rdataset_base, additionaltype, type, &zone, &cdb, &cversion, &cnode, &cfname); goto try_cache; } /* We've got an active cache. */ CTRACE(ISC_LOG_DEBUG(3), "query_addadditional2: auth additional cache"); dns_db_closeversion(cdb, &cversion, ISC_FALSE); db = cdb; node = cnode; dns_name_clone(&cfname, fname); query_keepname(client, fname, dbuf); goto foundcache; /* * Look for a zone database that might contain authoritative * additional data. */ findauthdb: result = query_getzonedb(client, name, qtype, DNS_GETDB_NOLOG, &zone, &db, &version); if (result != ISC_R_SUCCESS) { /* Cache the negative result */ (void)dns_rdataset_setadditional(rdataset_base, additionaltype, type, client->view->acache, NULL, NULL, NULL, NULL, NULL); goto try_cache; } CTRACE(ISC_LOG_DEBUG(3), "query_addadditional2: db_find"); /* * Since we are looking for authoritative data, we do not set * the GLUEOK flag. Glue will be looked for later, but not * necessarily in the same database. */ node = NULL; result = dns_db_findext(db, name, version, type, client->query.dboptions, client->now, &node, fname, &cm, &ci, NULL, NULL); if (result == ISC_R_SUCCESS) goto found; /* Cache the negative result */ (void)dns_rdataset_setadditional(rdataset_base, additionaltype, type, client->view->acache, zone, db, version, NULL, fname); if (node != NULL) dns_db_detachnode(db, &node); version = NULL; dns_db_detach(&db); /* * No authoritative data was found. The cache is our next best bet. */ try_cache: additionaltype = dns_rdatasetadditional_fromcache; result = query_getcachedb(client, name, qtype, &db, DNS_GETDB_NOLOG); if (result != ISC_R_SUCCESS) /* * Most likely the client isn't allowed to query the cache. */ goto try_glue; result = dns_db_findext(db, name, version, type, client->query.dboptions | DNS_DBFIND_GLUEOK | DNS_DBFIND_ADDITIONALOK, client->now, &node, fname, &cm, &ci, NULL, NULL); if (result == ISC_R_SUCCESS) goto found; if (node != NULL) dns_db_detachnode(db, &node); dns_db_detach(&db); try_glue: /* * No cached data was found. Glue is our last chance. * RFC1035 sayeth: * * NS records cause both the usual additional section * processing to locate a type A record, and, when used * in a referral, a special search of the zone in which * they reside for glue information. * * This is the "special search". Note that we must search * the zone where the NS record resides, not the zone it * points to, and that we only do the search in the delegation * case (identified by client->query.gluedb being set). */ if (client->query.gluedb == NULL) goto cleanup; /* * Don't poison caches using the bailiwick protection model. */ if (!dns_name_issubdomain(name, dns_db_origin(client->query.gluedb))) goto cleanup; /* Check additional cache */ additionaltype = dns_rdatasetadditional_fromglue; result = dns_rdataset_getadditional(rdataset_base, additionaltype, type, client->view->acache, NULL, &cdb, &cversion, &cnode, &cfname, client->message, client->now); if (result != ISC_R_SUCCESS) goto findglue; result = query_iscachevalid(zone, cdb, client->query.gluedb, cversion); if (result != ISC_R_SUCCESS) { CTRACE(ISC_LOG_DEBUG(3), "query_addadditional2: old glue additional cache"); query_discardcache(client, rdataset_base, additionaltype, type, &zone, &cdb, &cversion, &cnode, &cfname); goto findglue; } if (cnode == NULL) { /* We have a negative cache. */ CTRACE(ISC_LOG_DEBUG(3), "query_addadditional2: negative glue additional cache"); dns_db_closeversion(cdb, &cversion, ISC_FALSE); dns_db_detach(&cdb); goto cleanup; } /* Cache hit. */ CTRACE(ISC_LOG_DEBUG(3), "query_addadditional2: glue additional cache"); dns_db_closeversion(cdb, &cversion, ISC_FALSE); db = cdb; node = cnode; dns_name_clone(&cfname, fname); query_keepname(client, fname, dbuf); goto foundcache; findglue: dns_db_attach(client->query.gluedb, &db); result = dns_db_findext(db, name, version, type, client->query.dboptions | DNS_DBFIND_GLUEOK, client->now, &node, fname, &cm, &ci, NULL, NULL); if (!(result == ISC_R_SUCCESS || result == DNS_R_ZONECUT || result == DNS_R_GLUE)) { /* cache the negative result */ (void)dns_rdataset_setadditional(rdataset_base, additionaltype, type, client->view->acache, NULL, db, version, NULL, fname); goto cleanup; } found: /* * We have found a DB node to iterate over from a DB. * We are going to look for address RRsets (i.e., A and AAAA) in the DB * node we've just found. We'll then store the complete information * in the additional data cache. */ dns_name_clone(fname, &cfname); query_keepname(client, fname, dbuf); needadditionalcache = ISC_TRUE; rdataset = query_newrdataset(client); if (rdataset == NULL) goto cleanup; sigrdataset = query_newrdataset(client); if (sigrdataset == NULL) goto cleanup; if (additionaltype == dns_rdatasetadditional_fromcache && query_isduplicate(client, fname, dns_rdatatype_a, NULL)) goto aaaa_lookup; /* * Find A RRset with sig RRset. Even if we don't find a sig RRset * for a client using DNSSEC, we'll continue the process to make a * complete list to be cached. However, we need to cancel the * caching when something unexpected happens, in order to avoid * caching incomplete information. */ result = dns_db_findrdataset(db, node, version, dns_rdatatype_a, 0, client->now, rdataset, sigrdataset); /* * If we can't promote glue/pending from the cache to secure * then drop it. */ if (result == ISC_R_SUCCESS && additionaltype == dns_rdatasetadditional_fromcache && (DNS_TRUST_PENDING(rdataset->trust) || DNS_TRUST_GLUE(rdataset->trust)) && !validate(client, db, fname, rdataset, sigrdataset)) { dns_rdataset_disassociate(rdataset); if (dns_rdataset_isassociated(sigrdataset)) dns_rdataset_disassociate(sigrdataset); result = ISC_R_NOTFOUND; } if (result == DNS_R_NCACHENXDOMAIN) goto setcache; if (result == DNS_R_NCACHENXRRSET) { dns_rdataset_disassociate(rdataset); if (dns_rdataset_isassociated(sigrdataset)) dns_rdataset_disassociate(sigrdataset); } if (result == ISC_R_SUCCESS) { /* Remember the result as a cache */ ISC_LIST_APPEND(cfname.list, rdataset, link); if (dns_rdataset_isassociated(sigrdataset)) { ISC_LIST_APPEND(cfname.list, sigrdataset, link); sigrdataset = query_newrdataset(client); } rdataset = query_newrdataset(client); if (sigrdataset == NULL || rdataset == NULL) { /* do not cache incomplete information */ goto foundcache; } } aaaa_lookup: if (additionaltype == dns_rdatasetadditional_fromcache && query_isduplicate(client, fname, dns_rdatatype_aaaa, NULL)) goto foundcache; /* Find AAAA RRset with sig RRset */ result = dns_db_findrdataset(db, node, version, dns_rdatatype_aaaa, 0, client->now, rdataset, sigrdataset); /* * If we can't promote glue/pending from the cache to secure * then drop it. */ if (result == ISC_R_SUCCESS && additionaltype == dns_rdatasetadditional_fromcache && (DNS_TRUST_PENDING(rdataset->trust) || DNS_TRUST_GLUE(rdataset->trust)) && !validate(client, db, fname, rdataset, sigrdataset)) { dns_rdataset_disassociate(rdataset); if (dns_rdataset_isassociated(sigrdataset)) dns_rdataset_disassociate(sigrdataset); result = ISC_R_NOTFOUND; } if (result == ISC_R_SUCCESS) { ISC_LIST_APPEND(cfname.list, rdataset, link); rdataset = NULL; if (dns_rdataset_isassociated(sigrdataset)) { ISC_LIST_APPEND(cfname.list, sigrdataset, link); sigrdataset = NULL; } } setcache: /* * Set the new result in the cache if required. We do not support * caching additional data from a cache DB. */ if (needadditionalcache == ISC_TRUE && (additionaltype == dns_rdatasetadditional_fromauth || additionaltype == dns_rdatasetadditional_fromglue)) { (void)dns_rdataset_setadditional(rdataset_base, additionaltype, type, client->view->acache, zone, db, version, node, &cfname); } foundcache: need_sigrrset = ISC_FALSE; mname0 = NULL; for (crdataset = ISC_LIST_HEAD(cfname.list); crdataset != NULL; crdataset = crdataset_next) { dns_name_t *mname; crdataset_next = ISC_LIST_NEXT(crdataset, link); mname = NULL; if (crdataset->type == dns_rdatatype_a || crdataset->type == dns_rdatatype_aaaa) { if (!query_isduplicate(client, fname, crdataset->type, &mname)) { if (mname != fname) { if (mname != NULL) { /* * A different type of this name is * already stored in the additional * section. We'll reuse the name. * Note that this should happen at most * once. Otherwise, fname->link could * leak below. */ INSIST(mname0 == NULL); query_releasename(client, &fname); fname = mname; mname0 = mname; } else need_addname = ISC_TRUE; } ISC_LIST_UNLINK(cfname.list, crdataset, link); ISC_LIST_APPEND(fname->list, crdataset, link); added_something = ISC_TRUE; need_sigrrset = ISC_TRUE; } else need_sigrrset = ISC_FALSE; } else if (crdataset->type == dns_rdatatype_rrsig && need_sigrrset && WANTDNSSEC(client)) { ISC_LIST_UNLINK(cfname.list, crdataset, link); ISC_LIST_APPEND(fname->list, crdataset, link); added_something = ISC_TRUE; /* just in case */ need_sigrrset = ISC_FALSE; } } CTRACE(ISC_LOG_DEBUG(3), "query_addadditional2: addname"); /* * If we haven't added anything, then we're done. */ if (!added_something) goto cleanup; /* * We may have added our rdatasets to an existing name, if so, then * need_addname will be ISC_FALSE. Whether we used an existing name * or a new one, we must set fname to NULL to prevent cleanup. */ if (need_addname) dns_message_addname(client->message, fname, DNS_SECTION_ADDITIONAL); fname = NULL; cleanup: CTRACE(ISC_LOG_DEBUG(3), "query_addadditional2: cleanup"); if (rdataset != NULL) query_putrdataset(client, &rdataset); if (sigrdataset != NULL) query_putrdataset(client, &sigrdataset); while ((crdataset = ISC_LIST_HEAD(cfname.list)) != NULL) { ISC_LIST_UNLINK(cfname.list, crdataset, link); query_putrdataset(client, &crdataset); } if (fname != NULL) query_releasename(client, &fname); if (node != NULL) dns_db_detachnode(db, &node); if (db != NULL) dns_db_detach(&db); if (zone != NULL) dns_zone_detach(&zone); CTRACE(ISC_LOG_DEBUG(3), "query_addadditional2: done"); return (eresult); } static inline void query_addrdataset(ns_client_t *client, dns_name_t *fname, dns_rdataset_t *rdataset) { client_additionalctx_t additionalctx; /* * Add 'rdataset' and any pertinent additional data to * 'fname', a name in the response message for 'client'. */ CTRACE(ISC_LOG_DEBUG(3), "query_addrdataset"); ISC_LIST_APPEND(fname->list, rdataset, link); if (client->view->order != NULL) rdataset->attributes |= dns_order_find(client->view->order, fname, rdataset->type, rdataset->rdclass); rdataset->attributes |= DNS_RDATASETATTR_LOADORDER; if (NOADDITIONAL(client)) return; /* * Add additional data. * * We don't care if dns_rdataset_additionaldata() fails. */ additionalctx.client = client; additionalctx.rdataset = rdataset; (void)dns_rdataset_additionaldata(rdataset, query_addadditional2, &additionalctx); CTRACE(ISC_LOG_DEBUG(3), "query_addrdataset: done"); } static isc_result_t query_dns64(ns_client_t *client, dns_name_t **namep, dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset, isc_buffer_t *dbuf, dns_section_t section) { dns_name_t *name, *mname; dns_rdata_t *dns64_rdata; dns_rdata_t rdata = DNS_RDATA_INIT; dns_rdatalist_t *dns64_rdatalist; dns_rdataset_t *dns64_rdataset; dns_rdataset_t *mrdataset; isc_buffer_t *buffer; isc_region_t r; isc_result_t result; dns_view_t *view = client->view; isc_netaddr_t netaddr; dns_dns64_t *dns64; unsigned int flags = 0; /*% * To the current response for 'client', add the answer RRset * '*rdatasetp' and an optional signature set '*sigrdatasetp', with * owner name '*namep', to section 'section', unless they are * already there. Also add any pertinent additional data. * * If 'dbuf' is not NULL, then '*namep' is the name whose data is * stored in 'dbuf'. In this case, query_addrrset() guarantees that * when it returns the name will either have been kept or released. */ CTRACE(ISC_LOG_DEBUG(3), "query_dns64"); name = *namep; mname = NULL; mrdataset = NULL; buffer = NULL; dns64_rdata = NULL; dns64_rdataset = NULL; dns64_rdatalist = NULL; result = dns_message_findname(client->message, section, name, dns_rdatatype_aaaa, rdataset->covers, &mname, &mrdataset); if (result == ISC_R_SUCCESS) { /* * We've already got an RRset of the given name and type. * There's nothing else to do; */ CTRACE(ISC_LOG_DEBUG(3), "query_dns64: dns_message_findname succeeded: done"); if (dbuf != NULL) query_releasename(client, namep); return (ISC_R_SUCCESS); } else if (result == DNS_R_NXDOMAIN) { /* * The name doesn't exist. */ if (dbuf != NULL) query_keepname(client, name, dbuf); dns_message_addname(client->message, name, section); *namep = NULL; mname = name; } else { RUNTIME_CHECK(result == DNS_R_NXRRSET); if (dbuf != NULL) query_releasename(client, namep); } if (rdataset->trust != dns_trust_secure && (section == DNS_SECTION_ANSWER || section == DNS_SECTION_AUTHORITY)) client->query.attributes &= ~NS_QUERYATTR_SECURE; isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr); result = isc_buffer_allocate(client->mctx, &buffer, view->dns64cnt * 16 * dns_rdataset_count(rdataset)); if (result != ISC_R_SUCCESS) goto cleanup; result = dns_message_gettemprdataset(client->message, &dns64_rdataset); if (result != ISC_R_SUCCESS) goto cleanup; result = dns_message_gettemprdatalist(client->message, &dns64_rdatalist); if (result != ISC_R_SUCCESS) goto cleanup; dns_rdatalist_init(dns64_rdatalist); dns64_rdatalist->rdclass = dns_rdataclass_in; dns64_rdatalist->type = dns_rdatatype_aaaa; if (client->query.dns64_ttl != ISC_UINT32_MAX) dns64_rdatalist->ttl = ISC_MIN(rdataset->ttl, client->query.dns64_ttl); else dns64_rdatalist->ttl = ISC_MIN(rdataset->ttl, 600); if (RECURSIONOK(client)) flags |= DNS_DNS64_RECURSIVE; /* * We use the signatures from the A lookup to set DNS_DNS64_DNSSEC * as this provides a easy way to see if the answer was signed. */ if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset)) flags |= DNS_DNS64_DNSSEC; for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS; result = dns_rdataset_next(rdataset)) { for (dns64 = ISC_LIST_HEAD(client->view->dns64); dns64 != NULL; dns64 = dns_dns64_next(dns64)) { dns_rdataset_current(rdataset, &rdata); isc_buffer_availableregion(buffer, &r); INSIST(r.length >= 16); result = dns_dns64_aaaafroma(dns64, &netaddr, client->signer, &ns_g_server->aclenv, flags, rdata.data, r.base); if (result != ISC_R_SUCCESS) { dns_rdata_reset(&rdata); continue; } isc_buffer_add(buffer, 16); isc_buffer_remainingregion(buffer, &r); isc_buffer_forward(buffer, 16); result = dns_message_gettemprdata(client->message, &dns64_rdata); if (result != ISC_R_SUCCESS) goto cleanup; dns_rdata_init(dns64_rdata); dns_rdata_fromregion(dns64_rdata, dns_rdataclass_in, dns_rdatatype_aaaa, &r); ISC_LIST_APPEND(dns64_rdatalist->rdata, dns64_rdata, link); dns64_rdata = NULL; dns_rdata_reset(&rdata); } } if (result != ISC_R_NOMORE) goto cleanup; if (ISC_LIST_EMPTY(dns64_rdatalist->rdata)) goto cleanup; result = dns_rdatalist_tordataset(dns64_rdatalist, dns64_rdataset); if (result != ISC_R_SUCCESS) goto cleanup; dns_rdataset_setownercase(dns64_rdataset, mname); client->query.attributes |= NS_QUERYATTR_NOADDITIONAL; dns64_rdataset->trust = rdataset->trust; query_addrdataset(client, mname, dns64_rdataset); dns64_rdataset = NULL; dns64_rdatalist = NULL; dns_message_takebuffer(client->message, &buffer); inc_stats(client, dns_nsstatscounter_dns64); result = ISC_R_SUCCESS; cleanup: if (buffer != NULL) isc_buffer_free(&buffer); if (dns64_rdata != NULL) dns_message_puttemprdata(client->message, &dns64_rdata); if (dns64_rdataset != NULL) dns_message_puttemprdataset(client->message, &dns64_rdataset); if (dns64_rdatalist != NULL) { for (dns64_rdata = ISC_LIST_HEAD(dns64_rdatalist->rdata); dns64_rdata != NULL; dns64_rdata = ISC_LIST_HEAD(dns64_rdatalist->rdata)) { ISC_LIST_UNLINK(dns64_rdatalist->rdata, dns64_rdata, link); dns_message_puttemprdata(client->message, &dns64_rdata); } dns_message_puttemprdatalist(client->message, &dns64_rdatalist); } CTRACE(ISC_LOG_DEBUG(3), "query_dns64: done"); return (result); } static void query_filter64(ns_client_t *client, dns_name_t **namep, dns_rdataset_t *rdataset, isc_buffer_t *dbuf, dns_section_t section) { dns_name_t *name, *mname; dns_rdata_t *myrdata; dns_rdata_t rdata = DNS_RDATA_INIT; dns_rdatalist_t *myrdatalist; dns_rdataset_t *myrdataset; isc_buffer_t *buffer; isc_region_t r; isc_result_t result; unsigned int i; CTRACE(ISC_LOG_DEBUG(3), "query_filter64"); INSIST(client->query.dns64_aaaaok != NULL); INSIST(client->query.dns64_aaaaoklen == dns_rdataset_count(rdataset)); name = *namep; mname = NULL; buffer = NULL; myrdata = NULL; myrdataset = NULL; myrdatalist = NULL; result = dns_message_findname(client->message, section, name, dns_rdatatype_aaaa, rdataset->covers, &mname, &myrdataset); if (result == ISC_R_SUCCESS) { /* * We've already got an RRset of the given name and type. * There's nothing else to do; */ CTRACE(ISC_LOG_DEBUG(3), "query_filter64: dns_message_findname succeeded: done"); if (dbuf != NULL) query_releasename(client, namep); return; } else if (result == DNS_R_NXDOMAIN) { mname = name; *namep = NULL; } else { RUNTIME_CHECK(result == DNS_R_NXRRSET); if (dbuf != NULL) query_releasename(client, namep); dbuf = NULL; } if (rdataset->trust != dns_trust_secure && (section == DNS_SECTION_ANSWER || section == DNS_SECTION_AUTHORITY)) client->query.attributes &= ~NS_QUERYATTR_SECURE; result = isc_buffer_allocate(client->mctx, &buffer, 16 * dns_rdataset_count(rdataset)); if (result != ISC_R_SUCCESS) goto cleanup; result = dns_message_gettemprdataset(client->message, &myrdataset); if (result != ISC_R_SUCCESS) goto cleanup; result = dns_message_gettemprdatalist(client->message, &myrdatalist); if (result != ISC_R_SUCCESS) goto cleanup; dns_rdatalist_init(myrdatalist); myrdatalist->rdclass = dns_rdataclass_in; myrdatalist->type = dns_rdatatype_aaaa; myrdatalist->ttl = rdataset->ttl; i = 0; for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS; result = dns_rdataset_next(rdataset)) { if (!client->query.dns64_aaaaok[i++]) continue; dns_rdataset_current(rdataset, &rdata); INSIST(rdata.length == 16); isc_buffer_putmem(buffer, rdata.data, rdata.length); isc_buffer_remainingregion(buffer, &r); isc_buffer_forward(buffer, rdata.length); result = dns_message_gettemprdata(client->message, &myrdata); if (result != ISC_R_SUCCESS) goto cleanup; dns_rdata_init(myrdata); dns_rdata_fromregion(myrdata, dns_rdataclass_in, dns_rdatatype_aaaa, &r); ISC_LIST_APPEND(myrdatalist->rdata, myrdata, link); myrdata = NULL; dns_rdata_reset(&rdata); } if (result != ISC_R_NOMORE) goto cleanup; result = dns_rdatalist_tordataset(myrdatalist, myrdataset); if (result != ISC_R_SUCCESS) goto cleanup; dns_rdataset_setownercase(myrdataset, name); client->query.attributes |= NS_QUERYATTR_NOADDITIONAL; if (mname == name) { if (dbuf != NULL) query_keepname(client, name, dbuf); dns_message_addname(client->message, name, section); dbuf = NULL; } myrdataset->trust = rdataset->trust; query_addrdataset(client, mname, myrdataset); myrdataset = NULL; myrdatalist = NULL; dns_message_takebuffer(client->message, &buffer); cleanup: if (buffer != NULL) isc_buffer_free(&buffer); if (myrdata != NULL) dns_message_puttemprdata(client->message, &myrdata); if (myrdataset != NULL) dns_message_puttemprdataset(client->message, &myrdataset); if (myrdatalist != NULL) { for (myrdata = ISC_LIST_HEAD(myrdatalist->rdata); myrdata != NULL; myrdata = ISC_LIST_HEAD(myrdatalist->rdata)) { ISC_LIST_UNLINK(myrdatalist->rdata, myrdata, link); dns_message_puttemprdata(client->message, &myrdata); } dns_message_puttemprdatalist(client->message, &myrdatalist); } if (dbuf != NULL) query_releasename(client, &name); CTRACE(ISC_LOG_DEBUG(3), "query_filter64: done"); } static void query_addrrset(ns_client_t *client, dns_name_t **namep, dns_rdataset_t **rdatasetp, dns_rdataset_t **sigrdatasetp, isc_buffer_t *dbuf, dns_section_t section) { dns_name_t *name, *mname; dns_rdataset_t *rdataset, *mrdataset, *sigrdataset; isc_result_t result; /*% * To the current response for 'client', add the answer RRset * '*rdatasetp' and an optional signature set '*sigrdatasetp', with * owner name '*namep', to section 'section', unless they are * already there. Also add any pertinent additional data. * * If 'dbuf' is not NULL, then '*namep' is the name whose data is * stored in 'dbuf'. In this case, query_addrrset() guarantees that * when it returns the name will either have been kept or released. */ CTRACE(ISC_LOG_DEBUG(3), "query_addrrset"); name = *namep; rdataset = *rdatasetp; if (sigrdatasetp != NULL) sigrdataset = *sigrdatasetp; else sigrdataset = NULL; mname = NULL; mrdataset = NULL; result = dns_message_findname(client->message, section, name, rdataset->type, rdataset->covers, &mname, &mrdataset); if (result == ISC_R_SUCCESS) { /* * We've already got an RRset of the given name and type. */ CTRACE(ISC_LOG_DEBUG(3), "query_addrrset: dns_message_findname succeeded: done"); if (dbuf != NULL) query_releasename(client, namep); if ((rdataset->attributes & DNS_RDATASETATTR_REQUIRED) != 0) mrdataset->attributes |= DNS_RDATASETATTR_REQUIRED; return; } else if (result == DNS_R_NXDOMAIN) { /* * The name doesn't exist. */ if (dbuf != NULL) query_keepname(client, name, dbuf); dns_message_addname(client->message, name, section); *namep = NULL; mname = name; } else { RUNTIME_CHECK(result == DNS_R_NXRRSET); if (dbuf != NULL) query_releasename(client, namep); } if (rdataset->trust != dns_trust_secure && (section == DNS_SECTION_ANSWER || section == DNS_SECTION_AUTHORITY)) client->query.attributes &= ~NS_QUERYATTR_SECURE; /* * Note: we only add SIGs if we've added the type they cover, so * we do not need to check if the SIG rdataset is already in the * response. */ query_addrdataset(client, mname, rdataset); *rdatasetp = NULL; if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset)) { /* * We have a signature. Add it to the response. */ ISC_LIST_APPEND(mname->list, sigrdataset, link); *sigrdatasetp = NULL; } CTRACE(ISC_LOG_DEBUG(3), "query_addrrset: done"); } static inline isc_result_t query_addsoa(ns_client_t *client, dns_db_t *db, dns_dbversion_t *version, unsigned int override_ttl, isc_boolean_t isassociated, dns_section_t section) { dns_name_t *name; dns_dbnode_t *node; isc_result_t result, eresult; dns_rdataset_t *rdataset = NULL, *sigrdataset = NULL; dns_rdataset_t **sigrdatasetp = NULL; dns_clientinfomethods_t cm; dns_clientinfo_t ci; CTRACE(ISC_LOG_DEBUG(3), "query_addsoa"); /* * Initialization. */ eresult = ISC_R_SUCCESS; name = NULL; rdataset = NULL; node = NULL; dns_clientinfomethods_init(&cm, ns_client_sourceip); dns_clientinfo_init(&ci, client, NULL); /* * Don't add the SOA record for test which set "-T nosoa". */ if (ns_g_nosoa && (!WANTDNSSEC(client) || !isassociated)) return (ISC_R_SUCCESS); /* * Get resources and make 'name' be the database origin. */ result = dns_message_gettempname(client->message, &name); if (result != ISC_R_SUCCESS) return (result); dns_name_init(name, NULL); dns_name_clone(dns_db_origin(db), name); rdataset = query_newrdataset(client); if (rdataset == NULL) { CTRACE(ISC_LOG_ERROR, "unable to allocate rdataset"); eresult = DNS_R_SERVFAIL; goto cleanup; } if (WANTDNSSEC(client) && dns_db_issecure(db)) { sigrdataset = query_newrdataset(client); if (sigrdataset == NULL) { CTRACE(ISC_LOG_ERROR, "unable to allocate sigrdataset"); eresult = DNS_R_SERVFAIL; goto cleanup; } } /* * Find the SOA. */ result = dns_db_getoriginnode(db, &node); if (result == ISC_R_SUCCESS) { result = dns_db_findrdataset(db, node, version, dns_rdatatype_soa, 0, client->now, rdataset, sigrdataset); } else { dns_fixedname_t foundname; dns_name_t *fname; dns_fixedname_init(&foundname); fname = dns_fixedname_name(&foundname); result = dns_db_findext(db, name, version, dns_rdatatype_soa, client->query.dboptions, 0, &node, fname, &cm, &ci, rdataset, sigrdataset); } if (result != ISC_R_SUCCESS) { /* * This is bad. We tried to get the SOA RR at the zone top * and it didn't work! */ CTRACE(ISC_LOG_ERROR, "unable to find SOA RR at zone apex"); eresult = DNS_R_SERVFAIL; } else { /* * Extract the SOA MINIMUM. */ dns_rdata_soa_t soa; dns_rdata_t rdata = DNS_RDATA_INIT; result = dns_rdataset_first(rdataset); RUNTIME_CHECK(result == ISC_R_SUCCESS); dns_rdataset_current(rdataset, &rdata); result = dns_rdata_tostruct(&rdata, &soa, NULL); if (result != ISC_R_SUCCESS) goto cleanup; if (override_ttl != ISC_UINT32_MAX && override_ttl < rdataset->ttl) { rdataset->ttl = override_ttl; if (sigrdataset != NULL) sigrdataset->ttl = override_ttl; } /* * Add the SOA and its SIG to the response, with the * TTLs adjusted per RFC2308 section 3. */ if (rdataset->ttl > soa.minimum) rdataset->ttl = soa.minimum; if (sigrdataset != NULL && sigrdataset->ttl > soa.minimum) sigrdataset->ttl = soa.minimum; if (sigrdataset != NULL) sigrdatasetp = &sigrdataset; else sigrdatasetp = NULL; if (section == DNS_SECTION_ADDITIONAL) rdataset->attributes |= DNS_RDATASETATTR_REQUIRED; query_addrrset(client, &name, &rdataset, sigrdatasetp, NULL, section); } cleanup: query_putrdataset(client, &rdataset); if (sigrdataset != NULL) query_putrdataset(client, &sigrdataset); if (name != NULL) query_releasename(client, &name); if (node != NULL) dns_db_detachnode(db, &node); return (eresult); } static inline isc_result_t query_addns(ns_client_t *client, dns_db_t *db, dns_dbversion_t *version) { dns_name_t *name, *fname; dns_dbnode_t *node; isc_result_t result, eresult; dns_fixedname_t foundname; dns_rdataset_t *rdataset = NULL, *sigrdataset = NULL; dns_rdataset_t **sigrdatasetp = NULL; dns_clientinfomethods_t cm; dns_clientinfo_t ci; CTRACE(ISC_LOG_DEBUG(3), "query_addns"); /* * Initialization. */ eresult = ISC_R_SUCCESS; name = NULL; rdataset = NULL; node = NULL; dns_fixedname_init(&foundname); fname = dns_fixedname_name(&foundname); dns_clientinfomethods_init(&cm, ns_client_sourceip); dns_clientinfo_init(&ci, client, NULL); /* * Get resources and make 'name' be the database origin. */ result = dns_message_gettempname(client->message, &name); if (result != ISC_R_SUCCESS) { CTRACE(ISC_LOG_DEBUG(3), "query_addns: dns_message_gettempname failed: done"); return (result); } dns_name_init(name, NULL); dns_name_clone(dns_db_origin(db), name); rdataset = query_newrdataset(client); if (rdataset == NULL) { CTRACE(ISC_LOG_ERROR, "query_addns: query_newrdataset failed"); eresult = DNS_R_SERVFAIL; goto cleanup; } if (WANTDNSSEC(client) && dns_db_issecure(db)) { sigrdataset = query_newrdataset(client); if (sigrdataset == NULL) { CTRACE(ISC_LOG_ERROR, "query_addns: query_newrdataset failed"); eresult = DNS_R_SERVFAIL; goto cleanup; } } /* * Find the NS rdataset. */ result = dns_db_getoriginnode(db, &node); if (result == ISC_R_SUCCESS) { result = dns_db_findrdataset(db, node, version, dns_rdatatype_ns, 0, client->now, rdataset, sigrdataset); } else { CTRACE(ISC_LOG_DEBUG(3), "query_addns: calling dns_db_find"); result = dns_db_findext(db, name, NULL, dns_rdatatype_ns, client->query.dboptions, 0, &node, fname, &cm, &ci, rdataset, sigrdataset); CTRACE(ISC_LOG_DEBUG(3), "query_addns: dns_db_find complete"); } if (result != ISC_R_SUCCESS) { CTRACE(ISC_LOG_ERROR, "query_addns: " "dns_db_findrdataset or dns_db_find failed"); /* * This is bad. We tried to get the NS rdataset at the zone * top and it didn't work! */ eresult = DNS_R_SERVFAIL; } else { if (sigrdataset != NULL) sigrdatasetp = &sigrdataset; else sigrdatasetp = NULL; query_addrrset(client, &name, &rdataset, sigrdatasetp, NULL, DNS_SECTION_AUTHORITY); } cleanup: CTRACE(ISC_LOG_DEBUG(3), "query_addns: cleanup"); query_putrdataset(client, &rdataset); if (sigrdataset != NULL) query_putrdataset(client, &sigrdataset); if (name != NULL) query_releasename(client, &name); if (node != NULL) dns_db_detachnode(db, &node); CTRACE(ISC_LOG_DEBUG(3), "query_addns: done"); return (eresult); } static isc_result_t query_add_cname(ns_client_t *client, dns_name_t *qname, dns_name_t *tname, dns_trust_t trust, dns_ttl_t ttl) { dns_rdataset_t *rdataset; dns_rdatalist_t *rdatalist; dns_rdata_t *rdata; isc_region_t r; dns_name_t *aname; isc_result_t result; /* * We assume the name data referred to by tname won't go away. */ aname = NULL; result = dns_message_gettempname(client->message, &aname); if (result != ISC_R_SUCCESS) return (result); result = dns_name_dup(qname, client->mctx, aname); if (result != ISC_R_SUCCESS) { dns_message_puttempname(client->message, &aname); return (result); } rdatalist = NULL; result = dns_message_gettemprdatalist(client->message, &rdatalist); if (result != ISC_R_SUCCESS) { dns_message_puttempname(client->message, &aname); return (result); } rdata = NULL; result = dns_message_gettemprdata(client->message, &rdata); if (result != ISC_R_SUCCESS) { dns_message_puttempname(client->message, &aname); dns_message_puttemprdatalist(client->message, &rdatalist); return (result); } rdataset = NULL; result = dns_message_gettemprdataset(client->message, &rdataset); if (result != ISC_R_SUCCESS) { dns_message_puttempname(client->message, &aname); dns_message_puttemprdatalist(client->message, &rdatalist); dns_message_puttemprdata(client->message, &rdata); return (result); } rdatalist->type = dns_rdatatype_cname; rdatalist->rdclass = client->message->rdclass; rdatalist->ttl = ttl; dns_name_toregion(tname, &r); rdata->data = r.base; rdata->length = r.length; rdata->rdclass = client->message->rdclass; rdata->type = dns_rdatatype_cname; ISC_LIST_APPEND(rdatalist->rdata, rdata, link); RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset) == ISC_R_SUCCESS); rdataset->trust = trust; dns_rdataset_setownercase(rdataset, aname); query_addrrset(client, &aname, &rdataset, NULL, NULL, DNS_SECTION_ANSWER); if (rdataset != NULL) { if (dns_rdataset_isassociated(rdataset)) dns_rdataset_disassociate(rdataset); dns_message_puttemprdataset(client->message, &rdataset); } if (aname != NULL) dns_message_puttempname(client->message, &aname); return (ISC_R_SUCCESS); } /* * Mark the RRsets as secure. Update the cache (db) to reflect the * change in trust level. */ static void mark_secure(ns_client_t *client, dns_db_t *db, dns_name_t *name, dns_rdata_rrsig_t *rrsig, dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) { isc_result_t result; dns_dbnode_t *node = NULL; dns_clientinfomethods_t cm; dns_clientinfo_t ci; isc_stdtime_t now; rdataset->trust = dns_trust_secure; sigrdataset->trust = dns_trust_secure; dns_clientinfomethods_init(&cm, ns_client_sourceip); dns_clientinfo_init(&ci, client, NULL); /* * Save the updated secure state. Ignore failures. */ result = dns_db_findnodeext(db, name, ISC_TRUE, &cm, &ci, &node); if (result != ISC_R_SUCCESS) return; isc_stdtime_get(&now); dns_rdataset_trimttl(rdataset, sigrdataset, rrsig, now, client->view->acceptexpired); (void)dns_db_addrdataset(db, node, NULL, client->now, rdataset, 0, NULL); (void)dns_db_addrdataset(db, node, NULL, client->now, sigrdataset, 0, NULL); dns_db_detachnode(db, &node); } /* * Find the secure key that corresponds to rrsig. * Note: 'keyrdataset' maintains state between successive calls, * there may be multiple keys with the same keyid. * Return ISC_FALSE if we have exhausted all the possible keys. */ static isc_boolean_t get_key(ns_client_t *client, dns_db_t *db, dns_rdata_rrsig_t *rrsig, dns_rdataset_t *keyrdataset, dst_key_t **keyp) { isc_result_t result; dns_dbnode_t *node = NULL; isc_boolean_t secure = ISC_FALSE; dns_clientinfomethods_t cm; dns_clientinfo_t ci; dns_clientinfomethods_init(&cm, ns_client_sourceip); dns_clientinfo_init(&ci, client, NULL); if (!dns_rdataset_isassociated(keyrdataset)) { result = dns_db_findnodeext(db, &rrsig->signer, ISC_FALSE, &cm, &ci, &node); if (result != ISC_R_SUCCESS) return (ISC_FALSE); result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_dnskey, 0, client->now, keyrdataset, NULL); dns_db_detachnode(db, &node); if (result != ISC_R_SUCCESS) return (ISC_FALSE); if (keyrdataset->trust != dns_trust_secure) return (ISC_FALSE); result = dns_rdataset_first(keyrdataset); } else result = dns_rdataset_next(keyrdataset); for ( ; result == ISC_R_SUCCESS; result = dns_rdataset_next(keyrdataset)) { dns_rdata_t rdata = DNS_RDATA_INIT; isc_buffer_t b; dns_rdataset_current(keyrdataset, &rdata); isc_buffer_init(&b, rdata.data, rdata.length); isc_buffer_add(&b, rdata.length); result = dst_key_fromdns(&rrsig->signer, rdata.rdclass, &b, client->mctx, keyp); if (result != ISC_R_SUCCESS) continue; if (rrsig->algorithm == (dns_secalg_t)dst_key_alg(*keyp) && rrsig->keyid == (dns_keytag_t)dst_key_id(*keyp) && dst_key_iszonekey(*keyp)) { secure = ISC_TRUE; break; } dst_key_free(keyp); } return (secure); } static isc_boolean_t verify(dst_key_t *key, dns_name_t *name, dns_rdataset_t *rdataset, dns_rdata_t *rdata, ns_client_t *client) { isc_result_t result; dns_fixedname_t fixed; isc_boolean_t ignore = ISC_FALSE; dns_fixedname_init(&fixed); again: result = dns_dnssec_verify3(name, rdataset, key, ignore, client->view->maxbits, client->mctx, rdata, NULL); if (result == DNS_R_SIGEXPIRED && client->view->acceptexpired) { ignore = ISC_TRUE; goto again; } if (result == ISC_R_SUCCESS || result == DNS_R_FROMWILDCARD) return (ISC_TRUE); return (ISC_FALSE); } /* * Validate the rdataset if possible with available records. */ static isc_boolean_t validate(ns_client_t *client, dns_db_t *db, dns_name_t *name, dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) { isc_result_t result; dns_rdata_t rdata = DNS_RDATA_INIT; dns_rdata_rrsig_t rrsig; dst_key_t *key = NULL; dns_rdataset_t keyrdataset; if (sigrdataset == NULL || !dns_rdataset_isassociated(sigrdataset)) return (ISC_FALSE); for (result = dns_rdataset_first(sigrdataset); result == ISC_R_SUCCESS; result = dns_rdataset_next(sigrdataset)) { dns_rdata_reset(&rdata); dns_rdataset_current(sigrdataset, &rdata); result = dns_rdata_tostruct(&rdata, &rrsig, NULL); if (result != ISC_R_SUCCESS) return (ISC_FALSE); if (!dns_resolver_algorithm_supported(client->view->resolver, name, rrsig.algorithm)) continue; if (!dns_name_issubdomain(name, &rrsig.signer)) continue; dns_rdataset_init(&keyrdataset); do { if (!get_key(client, db, &rrsig, &keyrdataset, &key)) break; if (verify(key, name, rdataset, &rdata, client)) { dst_key_free(&key); dns_rdataset_disassociate(&keyrdataset); mark_secure(client, db, name, &rrsig, rdataset, sigrdataset); return (ISC_TRUE); } dst_key_free(&key); } while (1); if (dns_rdataset_isassociated(&keyrdataset)) dns_rdataset_disassociate(&keyrdataset); } return (ISC_FALSE); } static void query_addbestns(ns_client_t *client) { dns_db_t *db, *zdb; dns_dbnode_t *node; dns_name_t *fname, *zfname; dns_rdataset_t *rdataset, *sigrdataset, *zrdataset, *zsigrdataset; isc_boolean_t is_zone, use_zone; isc_buffer_t *dbuf; isc_result_t result; dns_dbversion_t *version; dns_zone_t *zone; isc_buffer_t b; dns_clientinfomethods_t cm; dns_clientinfo_t ci; CTRACE(ISC_LOG_DEBUG(3), "query_addbestns"); fname = NULL; zfname = NULL; rdataset = NULL; zrdataset = NULL; sigrdataset = NULL; zsigrdataset = NULL; node = NULL; db = NULL; zdb = NULL; version = NULL; zone = NULL; is_zone = ISC_FALSE; use_zone = ISC_FALSE; dns_clientinfomethods_init(&cm, ns_client_sourceip); dns_clientinfo_init(&ci, client, NULL); /* * Find the right database. */ result = query_getdb(client, client->query.qname, dns_rdatatype_ns, 0, &zone, &db, &version, &is_zone); if (result != ISC_R_SUCCESS) goto cleanup; db_find: /* * We'll need some resources... */ dbuf = query_getnamebuf(client); if (dbuf == NULL) goto cleanup; fname = query_newname(client, dbuf, &b); rdataset = query_newrdataset(client); if (fname == NULL || rdataset == NULL) goto cleanup; /* * Get the RRSIGs if the client requested them or if we may * need to validate answers from the cache. */ if (WANTDNSSEC(client) || !is_zone) { sigrdataset = query_newrdataset(client); if (sigrdataset == NULL) goto cleanup; } /* * Now look for the zonecut. */ if (is_zone) { result = dns_db_findext(db, client->query.qname, version, dns_rdatatype_ns, client->query.dboptions, client->now, &node, fname, &cm, &ci, rdataset, sigrdataset); if (result != DNS_R_DELEGATION) goto cleanup; if (USECACHE(client)) { query_keepname(client, fname, dbuf); dns_db_detachnode(db, &node); SAVE(zdb, db); SAVE(zfname, fname); SAVE(zrdataset, rdataset); SAVE(zsigrdataset, sigrdataset); version = NULL; dns_db_attach(client->view->cachedb, &db); is_zone = ISC_FALSE; goto db_find; } } else { result = dns_db_findzonecut(db, client->query.qname, client->query.dboptions, client->now, &node, fname, rdataset, sigrdataset); if (result == ISC_R_SUCCESS) { if (zfname != NULL && !dns_name_issubdomain(fname, zfname)) { /* * We found a zonecut in the cache, but our * zone delegation is better. */ use_zone = ISC_TRUE; } } else if (result == ISC_R_NOTFOUND && zfname != NULL) { /* * We didn't find anything in the cache, but we * have a zone delegation, so use it. */ use_zone = ISC_TRUE; } else goto cleanup; } if (use_zone) { query_releasename(client, &fname); /* * We've already done query_keepname() on * zfname, so we must set dbuf to NULL to * prevent query_addrrset() from trying to * call query_keepname() again. */ dbuf = NULL; query_putrdataset(client, &rdataset); if (sigrdataset != NULL) query_putrdataset(client, &sigrdataset); if (node != NULL) dns_db_detachnode(db, &node); dns_db_detach(&db); RESTORE(db, zdb); RESTORE(fname, zfname); RESTORE(rdataset, zrdataset); RESTORE(sigrdataset, zsigrdataset); } /* * Attempt to validate RRsets that are pending or that are glue. */ if ((DNS_TRUST_PENDING(rdataset->trust) || (sigrdataset != NULL && DNS_TRUST_PENDING(sigrdataset->trust))) && !validate(client, db, fname, rdataset, sigrdataset) && !PENDINGOK(client->query.dboptions)) goto cleanup; if ((DNS_TRUST_GLUE(rdataset->trust) || (sigrdataset != NULL && DNS_TRUST_GLUE(sigrdataset->trust))) && !validate(client, db, fname, rdataset, sigrdataset) && SECURE(client) && WANTDNSSEC(client)) goto cleanup; /* * If the answer is secure only add NS records if they are secure * when the client may be looking for AD in the response. */ if (SECURE(client) && (WANTDNSSEC(client) || WANTAD(client)) && ((rdataset->trust != dns_trust_secure) || (sigrdataset != NULL && sigrdataset->trust != dns_trust_secure))) goto cleanup; /* * If the client doesn't want DNSSEC we can discard the sigrdataset * now. */ if (!WANTDNSSEC(client)) query_putrdataset(client, &sigrdataset); query_addrrset(client, &fname, &rdataset, &sigrdataset, dbuf, DNS_SECTION_AUTHORITY); cleanup: if (rdataset != NULL) query_putrdataset(client, &rdataset); if (sigrdataset != NULL) query_putrdataset(client, &sigrdataset); if (fname != NULL) query_releasename(client, &fname); if (node != NULL) dns_db_detachnode(db, &node); if (db != NULL) dns_db_detach(&db); if (zone != NULL) dns_zone_detach(&zone); if (zdb != NULL) { query_putrdataset(client, &zrdataset); if (zsigrdataset != NULL) query_putrdataset(client, &zsigrdataset); if (zfname != NULL) query_releasename(client, &zfname); dns_db_detach(&zdb); } } static void fixrdataset(ns_client_t *client, dns_rdataset_t **rdataset) { if (*rdataset == NULL) *rdataset = query_newrdataset(client); else if (dns_rdataset_isassociated(*rdataset)) dns_rdataset_disassociate(*rdataset); } static void fixfname(ns_client_t *client, dns_name_t **fname, isc_buffer_t **dbuf, isc_buffer_t *nbuf) { if (*fname == NULL) { *dbuf = query_getnamebuf(client); if (*dbuf == NULL) return; *fname = query_newname(client, *dbuf, nbuf); } } static void query_addds(ns_client_t *client, dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, dns_name_t *name) { dns_fixedname_t fixed; dns_name_t *fname = NULL; dns_name_t *rname; dns_rdataset_t *rdataset, *sigrdataset; isc_buffer_t *dbuf, b; isc_result_t result; unsigned int count; CTRACE(ISC_LOG_DEBUG(3), "query_addds"); rname = NULL; rdataset = NULL; sigrdataset = NULL; /* * We'll need some resources... */ rdataset = query_newrdataset(client); sigrdataset = query_newrdataset(client); if (rdataset == NULL || sigrdataset == NULL) goto cleanup; /* * Look for the DS record, which may or may not be present. */ result = dns_db_findrdataset(db, node, version, dns_rdatatype_ds, 0, client->now, rdataset, sigrdataset); /* * If we didn't find it, look for an NSEC. */ if (result == ISC_R_NOTFOUND) result = dns_db_findrdataset(db, node, version, dns_rdatatype_nsec, 0, client->now, rdataset, sigrdataset); if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) goto addnsec3; if (!dns_rdataset_isassociated(rdataset) || !dns_rdataset_isassociated(sigrdataset)) goto addnsec3; /* * We've already added the NS record, so if the name's not there, * we have other problems. Use this name rather than calling * query_addrrset(). */ result = dns_message_firstname(client->message, DNS_SECTION_AUTHORITY); if (result != ISC_R_SUCCESS) goto cleanup; rname = NULL; dns_message_currentname(client->message, DNS_SECTION_AUTHORITY, &rname); result = dns_message_findtype(rname, dns_rdatatype_ns, 0, NULL); if (result != ISC_R_SUCCESS) goto cleanup; ISC_LIST_APPEND(rname->list, rdataset, link); ISC_LIST_APPEND(rname->list, sigrdataset, link); rdataset = NULL; sigrdataset = NULL; return; addnsec3: if (!dns_db_iszone(db)) goto cleanup; /* * Add the NSEC3 which proves the DS does not exist. */ dbuf = query_getnamebuf(client); if (dbuf == NULL) goto cleanup; fname = query_newname(client, dbuf, &b); dns_fixedname_init(&fixed); if (dns_rdataset_isassociated(rdataset)) dns_rdataset_disassociate(rdataset); if (dns_rdataset_isassociated(sigrdataset)) dns_rdataset_disassociate(sigrdataset); query_findclosestnsec3(name, db, version, client, rdataset, sigrdataset, fname, ISC_TRUE, dns_fixedname_name(&fixed)); if (!dns_rdataset_isassociated(rdataset)) goto cleanup; query_addrrset(client, &fname, &rdataset, &sigrdataset, dbuf, DNS_SECTION_AUTHORITY); /* * Did we find the closest provable encloser instead? * If so add the nearest to the closest provable encloser. */ if (!dns_name_equal(name, dns_fixedname_name(&fixed))) { count = dns_name_countlabels(dns_fixedname_name(&fixed)) + 1; dns_name_getlabelsequence(name, dns_name_countlabels(name) - count, count, dns_fixedname_name(&fixed)); fixfname(client, &fname, &dbuf, &b); fixrdataset(client, &rdataset); fixrdataset(client, &sigrdataset); if (fname == NULL || rdataset == NULL || sigrdataset == NULL) goto cleanup; query_findclosestnsec3(dns_fixedname_name(&fixed), db, version, client, rdataset, sigrdataset, fname, ISC_FALSE, NULL); if (!dns_rdataset_isassociated(rdataset)) goto cleanup; query_addrrset(client, &fname, &rdataset, &sigrdataset, dbuf, DNS_SECTION_AUTHORITY); } cleanup: if (rdataset != NULL) query_putrdataset(client, &rdataset); if (sigrdataset != NULL) query_putrdataset(client, &sigrdataset); if (fname != NULL) query_releasename(client, &fname); } static void query_addwildcardproof(ns_client_t *client, dns_db_t *db, dns_dbversion_t *version, dns_name_t *name, isc_boolean_t ispositive, isc_boolean_t nodata) { isc_buffer_t *dbuf, b; dns_name_t *fname; dns_rdataset_t *rdataset, *sigrdataset; dns_fixedname_t wfixed; dns_name_t *wname; dns_dbnode_t *node; unsigned int options; unsigned int olabels, nlabels, labels; isc_result_t result; dns_rdata_t rdata = DNS_RDATA_INIT; dns_rdata_nsec_t nsec; isc_boolean_t have_wname; int order; dns_fixedname_t cfixed; dns_name_t *cname; dns_clientinfomethods_t cm; dns_clientinfo_t ci; CTRACE(ISC_LOG_DEBUG(3), "query_addwildcardproof"); fname = NULL; rdataset = NULL; sigrdataset = NULL; node = NULL; dns_clientinfomethods_init(&cm, ns_client_sourceip); dns_clientinfo_init(&ci, client, NULL); /* * Get the NOQNAME proof then if !ispositive * get the NOWILDCARD proof. * * DNS_DBFIND_NOWILD finds the NSEC records that covers the * name ignoring any wildcard. From the owner and next names * of this record you can compute which wildcard (if it exists) * will match by finding the longest common suffix of the * owner name and next names with the qname and prefixing that * with the wildcard label. * * e.g. * Given: * example SOA * example NSEC b.example * b.example A * b.example NSEC a.d.example * a.d.example A * a.d.example NSEC g.f.example * g.f.example A * g.f.example NSEC z.i.example * z.i.example A * z.i.example NSEC example * * QNAME: * a.example -> example NSEC b.example * owner common example * next common example * wild *.example * d.b.example -> b.example NSEC a.d.example * owner common b.example * next common example * wild *.b.example * a.f.example -> a.d.example NSEC g.f.example * owner common example * next common f.example * wild *.f.example * j.example -> z.i.example NSEC example * owner common example * next common example * wild *.example */ options = client->query.dboptions | DNS_DBFIND_NOWILD; dns_fixedname_init(&wfixed); wname = dns_fixedname_name(&wfixed); again: have_wname = ISC_FALSE; /* * We'll need some resources... */ dbuf = query_getnamebuf(client); if (dbuf == NULL) goto cleanup; fname = query_newname(client, dbuf, &b); rdataset = query_newrdataset(client); sigrdataset = query_newrdataset(client); if (fname == NULL || rdataset == NULL || sigrdataset == NULL) goto cleanup; result = dns_db_findext(db, name, version, dns_rdatatype_nsec, options, 0, &node, fname, &cm, &ci, rdataset, sigrdataset); if (node != NULL) dns_db_detachnode(db, &node); if (!dns_rdataset_isassociated(rdataset)) { /* * No NSEC proof available, return NSEC3 proofs instead. */ dns_fixedname_init(&cfixed); cname = dns_fixedname_name(&cfixed); /* * Find the closest encloser. */ dns_name_copy(name, cname, NULL); while (result == DNS_R_NXDOMAIN) { labels = dns_name_countlabels(cname) - 1; /* * Sanity check. */ if (labels == 0U) goto cleanup; dns_name_split(cname, labels, NULL, cname); result = dns_db_findext(db, cname, version, dns_rdatatype_nsec, options, 0, NULL, fname, &cm, &ci, NULL, NULL); } /* * Add closest (provable) encloser NSEC3. */ query_findclosestnsec3(cname, db, version, client, rdataset, sigrdataset, fname, ISC_TRUE, cname); if (!dns_rdataset_isassociated(rdataset)) goto cleanup; if (!ispositive) query_addrrset(client, &fname, &rdataset, &sigrdataset, dbuf, DNS_SECTION_AUTHORITY); /* * Replace resources which were consumed by query_addrrset. */ if (fname == NULL) { dbuf = query_getnamebuf(client); if (dbuf == NULL) goto cleanup; fname = query_newname(client, dbuf, &b); } if (rdataset == NULL) rdataset = query_newrdataset(client); else if (dns_rdataset_isassociated(rdataset)) dns_rdataset_disassociate(rdataset); if (sigrdataset == NULL) sigrdataset = query_newrdataset(client); else if (dns_rdataset_isassociated(sigrdataset)) dns_rdataset_disassociate(sigrdataset); if (fname == NULL || rdataset == NULL || sigrdataset == NULL) goto cleanup; /* * Add no qname proof. */ labels = dns_name_countlabels(cname) + 1; if (dns_name_countlabels(name) == labels) dns_name_copy(name, wname, NULL); else dns_name_split(name, labels, NULL, wname); query_findclosestnsec3(wname, db, version, client, rdataset, sigrdataset, fname, ISC_FALSE, NULL); if (!dns_rdataset_isassociated(rdataset)) goto cleanup; query_addrrset(client, &fname, &rdataset, &sigrdataset, dbuf, DNS_SECTION_AUTHORITY); if (ispositive) goto cleanup; /* * Replace resources which were consumed by query_addrrset. */ if (fname == NULL) { dbuf = query_getnamebuf(client); if (dbuf == NULL) goto cleanup; fname = query_newname(client, dbuf, &b); } if (rdataset == NULL) rdataset = query_newrdataset(client); else if (dns_rdataset_isassociated(rdataset)) dns_rdataset_disassociate(rdataset); if (sigrdataset == NULL) sigrdataset = query_newrdataset(client); else if (dns_rdataset_isassociated(sigrdataset)) dns_rdataset_disassociate(sigrdataset); if (fname == NULL || rdataset == NULL || sigrdataset == NULL) goto cleanup; /* * Add the no wildcard proof. */ result = dns_name_concatenate(dns_wildcardname, cname, wname, NULL); if (result != ISC_R_SUCCESS) goto cleanup; query_findclosestnsec3(wname, db, version, client, rdataset, sigrdataset, fname, nodata, NULL); if (!dns_rdataset_isassociated(rdataset)) goto cleanup; query_addrrset(client, &fname, &rdataset, &sigrdataset, dbuf, DNS_SECTION_AUTHORITY); goto cleanup; } else if (result == DNS_R_NXDOMAIN) { if (!ispositive) result = dns_rdataset_first(rdataset); if (result == ISC_R_SUCCESS) { dns_rdataset_current(rdataset, &rdata); result = dns_rdata_tostruct(&rdata, &nsec, NULL); } if (result == ISC_R_SUCCESS) { (void)dns_name_fullcompare(name, fname, &order, &olabels); (void)dns_name_fullcompare(name, &nsec.next, &order, &nlabels); /* * Check for a pathological condition created when * serving some malformed signed zones and bail out. */ if (dns_name_countlabels(name) == nlabels) goto cleanup; if (olabels > nlabels) dns_name_split(name, olabels, NULL, wname); else dns_name_split(name, nlabels, NULL, wname); result = dns_name_concatenate(dns_wildcardname, wname, wname, NULL); if (result == ISC_R_SUCCESS) have_wname = ISC_TRUE; dns_rdata_freestruct(&nsec); } query_addrrset(client, &fname, &rdataset, &sigrdataset, dbuf, DNS_SECTION_AUTHORITY); } if (rdataset != NULL) query_putrdataset(client, &rdataset); if (sigrdataset != NULL) query_putrdataset(client, &sigrdataset); if (fname != NULL) query_releasename(client, &fname); if (have_wname) { ispositive = ISC_TRUE; /* prevent loop */ if (!dns_name_equal(name, wname)) { name = wname; goto again; } } cleanup: if (rdataset != NULL) query_putrdataset(client, &rdataset); if (sigrdataset != NULL) query_putrdataset(client, &sigrdataset); if (fname != NULL) query_releasename(client, &fname); } static void query_addnxrrsetnsec(ns_client_t *client, dns_db_t *db, dns_dbversion_t *version, dns_name_t **namep, dns_rdataset_t **rdatasetp, dns_rdataset_t **sigrdatasetp) { dns_name_t *name; dns_rdataset_t *sigrdataset; dns_rdata_t sigrdata; dns_rdata_rrsig_t sig; unsigned int labels; isc_buffer_t *dbuf, b; dns_name_t *fname; isc_result_t result; name = *namep; if ((name->attributes & DNS_NAMEATTR_WILDCARD) == 0) { query_addrrset(client, namep, rdatasetp, sigrdatasetp, NULL, DNS_SECTION_AUTHORITY); return; } if (sigrdatasetp == NULL) return; sigrdataset = *sigrdatasetp; if (sigrdataset == NULL || !dns_rdataset_isassociated(sigrdataset)) return; result = dns_rdataset_first(sigrdataset); if (result != ISC_R_SUCCESS) return; dns_rdata_init(&sigrdata); dns_rdataset_current(sigrdataset, &sigrdata); result = dns_rdata_tostruct(&sigrdata, &sig, NULL); if (result != ISC_R_SUCCESS) return; labels = dns_name_countlabels(name); if ((unsigned int)sig.labels + 1 >= labels) return; /* XXX */ query_addwildcardproof(client, db, version, client->query.qname, ISC_TRUE, ISC_FALSE); /* * We'll need some resources... */ dbuf = query_getnamebuf(client); if (dbuf == NULL) return; fname = query_newname(client, dbuf, &b); if (fname == NULL) return; dns_name_split(name, sig.labels + 1, NULL, fname); /* This will succeed, since we've stripped labels. */ RUNTIME_CHECK(dns_name_concatenate(dns_wildcardname, fname, fname, NULL) == ISC_R_SUCCESS); query_addrrset(client, &fname, rdatasetp, sigrdatasetp, dbuf, DNS_SECTION_AUTHORITY); } static void free_devent(ns_client_t *client, isc_event_t **eventp, dns_fetchevent_t **deventp) { dns_fetchevent_t *devent = *deventp; REQUIRE((void*)(*eventp) == (void *)(*deventp)); if (devent->fetch != NULL) dns_resolver_destroyfetch(&devent->fetch); if (devent->node != NULL) dns_db_detachnode(devent->db, &devent->node); if (devent->db != NULL) dns_db_detach(&devent->db); if (devent->rdataset != NULL) query_putrdataset(client, &devent->rdataset); if (devent->sigrdataset != NULL) query_putrdataset(client, &devent->sigrdataset); /* * If the two pointers are the same then leave the setting of * (*deventp) to NULL to isc_event_free. */ if ((void *)eventp != (void *)deventp) (*deventp) = NULL; isc_event_free(eventp); } static void query_resume(isc_task_t *task, isc_event_t *event) { dns_fetchevent_t *devent = (dns_fetchevent_t *)event; dns_fetch_t *fetch = NULL; ns_client_t *client; isc_boolean_t fetch_canceled, client_shuttingdown; isc_result_t result; isc_logcategory_t *logcategory = NS_LOGCATEGORY_QUERY_ERRORS; int errorloglevel; /* * Resume a query after recursion. */ UNUSED(task); REQUIRE(event->ev_type == DNS_EVENT_FETCHDONE); client = devent->ev_arg; REQUIRE(NS_CLIENT_VALID(client)); REQUIRE(task == client->task); REQUIRE(RECURSING(client)); LOCK(&client->query.fetchlock); if (client->query.fetch != NULL) { /* * This is the fetch we've been waiting for. */ INSIST(devent->fetch == client->query.fetch); client->query.fetch = NULL; fetch_canceled = ISC_FALSE; /* * Update client->now. */ isc_stdtime_get(&client->now); } else { /* * This is a fetch completion event for a canceled fetch. * Clean up and don't resume the find. */ fetch_canceled = ISC_TRUE; } UNLOCK(&client->query.fetchlock); INSIST(client->query.fetch == NULL); client->query.attributes &= ~NS_QUERYATTR_RECURSING; SAVE(fetch, devent->fetch); /* * If this client is shutting down, or this transaction * has timed out, do not resume the find. */ client_shuttingdown = ns_client_shuttingdown(client); if (fetch_canceled || client_shuttingdown) { free_devent(client, &event, &devent); if (fetch_canceled) { CTRACE(ISC_LOG_ERROR, "fetch cancelled"); query_error(client, DNS_R_SERVFAIL, __LINE__); } else query_next(client, ISC_R_CANCELED); /* * This may destroy the client. */ ns_client_detach(&client); } else { result = query_find(client, devent, 0); if (result != ISC_R_SUCCESS) { if (result == DNS_R_SERVFAIL) errorloglevel = ISC_LOG_DEBUG(2); else errorloglevel = ISC_LOG_DEBUG(4); if (isc_log_wouldlog(ns_g_lctx, errorloglevel)) { dns_resolver_logfetch(fetch, ns_g_lctx, logcategory, NS_LOGMODULE_QUERY, errorloglevel, ISC_FALSE); } } } dns_resolver_destroyfetch(&fetch); } static void prefetch_done(isc_task_t *task, isc_event_t *event) { dns_fetchevent_t *devent = (dns_fetchevent_t *)event; ns_client_t *client; UNUSED(task); REQUIRE(event->ev_type == DNS_EVENT_FETCHDONE); client = devent->ev_arg; REQUIRE(NS_CLIENT_VALID(client)); REQUIRE(task == client->task); LOCK(&client->query.fetchlock); if (client->query.prefetch != NULL) { INSIST(devent->fetch == client->query.prefetch); client->query.prefetch = NULL; } UNLOCK(&client->query.fetchlock); free_devent(client, &event, &devent); ns_client_detach(&client); } static void query_prefetch(ns_client_t *client, dns_name_t *qname, dns_rdataset_t *rdataset) { isc_result_t result; isc_sockaddr_t *peeraddr; dns_rdataset_t *tmprdataset; ns_client_t *dummy = NULL; unsigned int options; if (client->query.prefetch != NULL || client->view->prefetch_trigger == 0U || rdataset->ttl > client->view->prefetch_trigger || (rdataset->attributes & DNS_RDATASETATTR_PREFETCH) == 0) return; if (client->recursionquota == NULL) { result = isc_quota_attach(&ns_g_server->recursionquota, &client->recursionquota); if (result == ISC_R_SUCCESS && !client->mortal && !TCP(client)) result = ns_client_replace(client); if (result != ISC_R_SUCCESS) return; isc_stats_increment(ns_g_server->nsstats, dns_nsstatscounter_recursclients); } tmprdataset = query_newrdataset(client); if (tmprdataset == NULL) return; if (!TCP(client)) peeraddr = &client->peeraddr; else peeraddr = NULL; ns_client_attach(client, &dummy); options = client->query.fetchoptions | DNS_FETCHOPT_PREFETCH; result = dns_resolver_createfetch3(client->view->resolver, qname, rdataset->type, NULL, NULL, NULL, peeraddr, client->message->id, options, 0, NULL, client->task, prefetch_done, client, tmprdataset, NULL, &client->query.prefetch); if (result != ISC_R_SUCCESS) { query_putrdataset(client, &tmprdataset); ns_client_detach(&dummy); } dns_rdataset_clearprefetch(rdataset); } static isc_result_t query_recurse(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qname, dns_name_t *qdomain, dns_rdataset_t *nameservers, isc_boolean_t resuming) { isc_result_t result; dns_rdataset_t *rdataset, *sigrdataset; isc_sockaddr_t *peeraddr; if (!resuming) inc_stats(client, dns_nsstatscounter_recursion); /* * We are about to recurse, which means that this client will * be unavailable for serving new requests for an indeterminate * amount of time. If this client is currently responsible * for handling incoming queries, set up a new client * object to handle them while we are waiting for a * response. There is no need to replace TCP clients * because those have already been replaced when the * connection was accepted (if allowed by the TCP quota). */ if (client->recursionquota == NULL) { result = isc_quota_attach(&ns_g_server->recursionquota, &client->recursionquota); isc_stats_increment(ns_g_server->nsstats, dns_nsstatscounter_recursclients); if (result == ISC_R_SOFTQUOTA) { static isc_stdtime_t last = 0; isc_stdtime_t now; isc_stdtime_get(&now); if (now != last) { last = now; ns_client_log(client, NS_LOGCATEGORY_CLIENT, NS_LOGMODULE_QUERY, ISC_LOG_WARNING, "recursive-clients soft limit " "exceeded (%d/%d/%d), " "aborting oldest query", client->recursionquota->used, client->recursionquota->soft, client->recursionquota->max); } ns_client_killoldestquery(client); result = ISC_R_SUCCESS; } else if (result == ISC_R_QUOTA) { static isc_stdtime_t last = 0; isc_stdtime_t now; isc_stdtime_get(&now); if (now != last) { last = now; ns_client_log(client, NS_LOGCATEGORY_CLIENT, NS_LOGMODULE_QUERY, ISC_LOG_WARNING, "no more recursive clients " "(%d/%d/%d): %s", ns_g_server->recursionquota.used, ns_g_server->recursionquota.soft, ns_g_server->recursionquota.max, isc_result_totext(result)); } ns_client_killoldestquery(client); } if (result == ISC_R_SUCCESS && !client->mortal && !TCP(client)) { result = ns_client_replace(client); if (result != ISC_R_SUCCESS) { ns_client_log(client, NS_LOGCATEGORY_CLIENT, NS_LOGMODULE_QUERY, ISC_LOG_WARNING, "ns_client_replace() failed: %s", isc_result_totext(result)); isc_quota_detach(&client->recursionquota); isc_stats_decrement(ns_g_server->nsstats, dns_nsstatscounter_recursclients); } } if (result != ISC_R_SUCCESS) return (result); ns_client_recursing(client); } /* * Invoke the resolver. */ REQUIRE(nameservers == NULL || nameservers->type == dns_rdatatype_ns); REQUIRE(client->query.fetch == NULL); rdataset = query_newrdataset(client); if (rdataset == NULL) return (ISC_R_NOMEMORY); if (WANTDNSSEC(client)) { sigrdataset = query_newrdataset(client); if (sigrdataset == NULL) { query_putrdataset(client, &rdataset); return (ISC_R_NOMEMORY); } } else sigrdataset = NULL; if (client->query.timerset == ISC_FALSE) ns_client_settimeout(client, 60); if (!TCP(client)) peeraddr = &client->peeraddr; else peeraddr = NULL; result = dns_resolver_createfetch3(client->view->resolver, qname, qtype, qdomain, nameservers, NULL, peeraddr, client->message->id, client->query.fetchoptions, 0, NULL, client->task, query_resume, client, rdataset, sigrdataset, &client->query.fetch); if (result == ISC_R_SUCCESS) { /* * Record that we're waiting for an event. A client which * is shutting down will not be destroyed until all the * events have been received. */ } else { query_putrdataset(client, &rdataset); if (sigrdataset != NULL) query_putrdataset(client, &sigrdataset); } return (result); } static inline void rpz_clean(dns_zone_t **zonep, dns_db_t **dbp, dns_dbnode_t **nodep, dns_rdataset_t **rdatasetp) { if (nodep != NULL && *nodep != NULL) { REQUIRE(dbp != NULL && *dbp != NULL); dns_db_detachnode(*dbp, nodep); } if (dbp != NULL && *dbp != NULL) dns_db_detach(dbp); if (zonep != NULL && *zonep != NULL) dns_zone_detach(zonep); if (rdatasetp != NULL && *rdatasetp != NULL && dns_rdataset_isassociated(*rdatasetp)) dns_rdataset_disassociate(*rdatasetp); } static inline void rpz_match_clear(dns_rpz_st_t *st) { rpz_clean(&st->m.zone, &st->m.db, &st->m.node, &st->m.rdataset); st->m.version = NULL; } static inline isc_result_t rpz_ready(ns_client_t *client, dns_rdataset_t **rdatasetp) { REQUIRE(rdatasetp != NULL); CTRACE(ISC_LOG_DEBUG(3), "rpz_ready"); if (*rdatasetp == NULL) { *rdatasetp = query_newrdataset(client); if (*rdatasetp == NULL) { CTRACE(ISC_LOG_ERROR, "rpz_ready: query_newrdataset failed"); return (DNS_R_SERVFAIL); } } else if (dns_rdataset_isassociated(*rdatasetp)) { dns_rdataset_disassociate(*rdatasetp); } return (ISC_R_SUCCESS); } static void rpz_st_clear(ns_client_t *client) { dns_rpz_st_t *st = client->query.rpz_st; CTRACE(ISC_LOG_DEBUG(3), "rpz_st_clear"); if (st->m.rdataset != NULL) query_putrdataset(client, &st->m.rdataset); rpz_match_clear(st); rpz_clean(NULL, &st->r.db, NULL, NULL); if (st->r.ns_rdataset != NULL) query_putrdataset(client, &st->r.ns_rdataset); if (st->r.r_rdataset != NULL) query_putrdataset(client, &st->r.r_rdataset); rpz_clean(&st->q.zone, &st->q.db, &st->q.node, NULL); if (st->q.rdataset != NULL) query_putrdataset(client, &st->q.rdataset); if (st->q.sigrdataset != NULL) query_putrdataset(client, &st->q.sigrdataset); st->state = 0; st->m.type = DNS_RPZ_TYPE_BAD; st->m.policy = DNS_RPZ_POLICY_MISS; } static dns_rpz_zbits_t rpz_get_zbits(ns_client_t *client, dns_rdatatype_t ip_type, dns_rpz_type_t rpz_type) { dns_rpz_st_t *st; dns_rpz_zbits_t zbits; REQUIRE(client != NULL); REQUIRE(client->query.rpz_st != NULL); st = client->query.rpz_st; switch (rpz_type) { case DNS_RPZ_TYPE_CLIENT_IP: zbits = st->have.client_ip; break; case DNS_RPZ_TYPE_QNAME: zbits = st->have.qname; break; case DNS_RPZ_TYPE_IP: if (ip_type == dns_rdatatype_a) { zbits = st->have.ipv4; } else if (ip_type == dns_rdatatype_aaaa) { zbits = st->have.ipv6; } else { zbits = st->have.ip; } break; case DNS_RPZ_TYPE_NSDNAME: zbits = st->have.nsdname; break; case DNS_RPZ_TYPE_NSIP: if (ip_type == dns_rdatatype_a) { zbits = st->have.nsipv4; } else if (ip_type == dns_rdatatype_aaaa) { zbits = st->have.nsipv6; } else { zbits = st->have.nsip; } break; default: INSIST(0); break; } /* * Choose * the earliest configured policy zone (rpz->num) * QNAME over IP over NSDNAME over NSIP (rpz_type) * the smallest name, * the longest IP address prefix, * the lexically smallest address. */ if (st->m.policy != DNS_RPZ_POLICY_MISS) { if (st->m.type >= rpz_type) { zbits &= DNS_RPZ_ZMASK(st->m.rpz->num); } else{ zbits &= DNS_RPZ_ZMASK(st->m.rpz->num) >> 1; } } /* * If the client wants recursion, allow only compatible policies. */ if (!RECURSIONOK(client)) zbits &= st->popt.no_rd_ok; return (zbits); } static void query_rpzfetch(ns_client_t *client, dns_name_t *qname, dns_rdatatype_t type) { isc_result_t result; isc_sockaddr_t *peeraddr; dns_rdataset_t *tmprdataset; ns_client_t *dummy = NULL; unsigned int options; if (client->query.prefetch != NULL) return; if (client->recursionquota == NULL) { result = isc_quota_attach(&ns_g_server->recursionquota, &client->recursionquota); if (result == ISC_R_SUCCESS && !client->mortal && !TCP(client)) result = ns_client_replace(client); if (result != ISC_R_SUCCESS) return; isc_stats_increment(ns_g_server->nsstats, dns_nsstatscounter_recursclients); } tmprdataset = query_newrdataset(client); if (tmprdataset == NULL) return; if (!TCP(client)) peeraddr = &client->peeraddr; else peeraddr = NULL; ns_client_attach(client, &dummy); options = client->query.fetchoptions; result = dns_resolver_createfetch3(client->view->resolver, qname, type, NULL, NULL, NULL, peeraddr, client->message->id, options, 0, NULL, client->task, prefetch_done, client, tmprdataset, NULL, &client->query.prefetch); if (result != ISC_R_SUCCESS) { query_putrdataset(client, &tmprdataset); ns_client_detach(&dummy); } } /* * Get an NS, A, or AAAA rrset related to the response for the client * to check the contents of that rrset for hits by eligible policy zones. */ static isc_result_t rpz_rrset_find(ns_client_t *client, dns_name_t *name, dns_rdatatype_t type, dns_rpz_type_t rpz_type, dns_db_t **dbp, dns_dbversion_t *version, dns_rdataset_t **rdatasetp, isc_boolean_t resuming) { dns_rpz_st_t *st; isc_boolean_t is_zone; dns_dbnode_t *node; dns_fixedname_t fixed; dns_name_t *found; isc_result_t result; dns_clientinfomethods_t cm; dns_clientinfo_t ci; CTRACE(ISC_LOG_DEBUG(3), "rpz_rrset_find"); st = client->query.rpz_st; if ((st->state & DNS_RPZ_RECURSING) != 0) { INSIST(st->r.r_type == type); INSIST(dns_name_equal(name, st->r_name)); INSIST(*rdatasetp == NULL || !dns_rdataset_isassociated(*rdatasetp)); st->state &= ~DNS_RPZ_RECURSING; RESTORE(*dbp, st->r.db); if (*rdatasetp != NULL) query_putrdataset(client, rdatasetp); RESTORE(*rdatasetp, st->r.r_rdataset); result = st->r.r_result; if (result == DNS_R_DELEGATION) { CTRACE(ISC_LOG_ERROR, "RPZ recursing"); rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, name, rpz_type, " rpz_rrset_find(1)", result); st->m.policy = DNS_RPZ_POLICY_ERROR; result = DNS_R_SERVFAIL; } return (result); } result = rpz_ready(client, rdatasetp); if (result != ISC_R_SUCCESS) { st->m.policy = DNS_RPZ_POLICY_ERROR; return (result); } if (*dbp != NULL) { is_zone = ISC_FALSE; } else { dns_zone_t *zone; version = NULL; zone = NULL; result = query_getdb(client, name, type, 0, &zone, dbp, &version, &is_zone); if (result != ISC_R_SUCCESS) { rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, name, rpz_type, " rpz_rrset_find(2)", result); st->m.policy = DNS_RPZ_POLICY_ERROR; if (zone != NULL) dns_zone_detach(&zone); return (result); } if (zone != NULL) dns_zone_detach(&zone); } node = NULL; dns_fixedname_init(&fixed); found = dns_fixedname_name(&fixed); dns_clientinfomethods_init(&cm, ns_client_sourceip); dns_clientinfo_init(&ci, client, NULL); result = dns_db_findext(*dbp, name, version, type, DNS_DBFIND_GLUEOK, client->now, &node, found, &cm, &ci, *rdatasetp, NULL); if (result == DNS_R_DELEGATION && is_zone && USECACHE(client)) { /* * Try the cache if we're authoritative for an * ancestor but not the domain itself. */ rpz_clean(NULL, dbp, &node, rdatasetp); version = NULL; dns_db_attach(client->view->cachedb, dbp); result = dns_db_findext(*dbp, name, version, type, 0, client->now, &node, found, &cm, &ci, *rdatasetp, NULL); } rpz_clean(NULL, dbp, &node, NULL); if (result == DNS_R_DELEGATION) { rpz_clean(NULL, NULL, NULL, rdatasetp); /* * Recurse for NS rrset or A or AAAA rrset for an NS. * Do not recurse for addresses for the query name. */ if (rpz_type == DNS_RPZ_TYPE_IP) { result = DNS_R_NXRRSET; } else if (!client->view->rpzs->p.nsip_wait_recurse) { query_rpzfetch(client, name, type); result = DNS_R_NXRRSET; } else { dns_name_copy(name, st->r_name, NULL); result = query_recurse(client, type, st->r_name, NULL, NULL, resuming); if (result == ISC_R_SUCCESS) { st->state |= DNS_RPZ_RECURSING; result = DNS_R_DELEGATION; } } } return (result); } /* * Compute a policy owner name, p_name, in a policy zone given the needed * policy type and the trigger name. */ static isc_result_t rpz_get_p_name(ns_client_t *client, dns_name_t *p_name, dns_rpz_zone_t *rpz, dns_rpz_type_t rpz_type, dns_name_t *trig_name) { dns_offsets_t prefix_offsets; dns_name_t prefix, *suffix; unsigned int first, labels; isc_result_t result; CTRACE(ISC_LOG_DEBUG(3), "rpz_get_p_name"); /* * The policy owner name consists of a suffix depending on the type * and policy zone and a prefix that is the longest possible string * from the trigger name that keesp the resulting policy owner name * from being too long. */ switch (rpz_type) { case DNS_RPZ_TYPE_CLIENT_IP: suffix = &rpz->client_ip; break; case DNS_RPZ_TYPE_QNAME: suffix = &rpz->origin; break; case DNS_RPZ_TYPE_IP: suffix = &rpz->ip; break; case DNS_RPZ_TYPE_NSDNAME: suffix = &rpz->nsdname; break; case DNS_RPZ_TYPE_NSIP: suffix = &rpz->nsip; break; default: INSIST(0); } /* * Start with relative version of the full trigger name, * and trim enough allow the addition of the suffix. */ dns_name_init(&prefix, prefix_offsets); labels = dns_name_countlabels(trig_name); first = 0; for (;;) { dns_name_getlabelsequence(trig_name, first, labels-first-1, &prefix); result = dns_name_concatenate(&prefix, suffix, p_name, NULL); if (result == ISC_R_SUCCESS) break; INSIST(result == DNS_R_NAMETOOLONG); /* * Trim the trigger name until the combination is not too long. */ if (labels-first < 2) { rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, suffix, rpz_type, " concatentate()", result); return (ISC_R_FAILURE); } /* * Complain once about trimming the trigger name. */ if (first == 0) { rpz_log_fail(client, DNS_RPZ_DEBUG_LEVEL1, suffix, rpz_type, " concatentate()", result); } ++first; } return (ISC_R_SUCCESS); } /* * Look in policy zone rpz for a policy of rpz_type by p_name. * The self-name (usually the client qname or an NS name) is compared with * the target of a CNAME policy for the old style passthru encoding. * If found, the policy is recorded in *zonep, *dbp, *versionp, *nodep, * *rdatasetp, and *policyp. * The target DNS type, qtype, chooses the best rdataset for *rdatasetp. * The caller must decide if the found policy is most suitable, including * better than a previously found policy. * If it is best, the caller records it in client->query.rpz_st->m. */ static isc_result_t rpz_find_p(ns_client_t *client, dns_name_t *self_name, dns_rdatatype_t qtype, dns_name_t *p_name, dns_rpz_zone_t *rpz, dns_rpz_type_t rpz_type, dns_zone_t **zonep, dns_db_t **dbp, dns_dbversion_t **versionp, dns_dbnode_t **nodep, dns_rdataset_t **rdatasetp, dns_rpz_policy_t *policyp) { dns_fixedname_t foundf; dns_name_t *found; isc_result_t result; dns_clientinfomethods_t cm; dns_clientinfo_t ci; REQUIRE(nodep != NULL); CTRACE(ISC_LOG_DEBUG(3), "rpz_find_p"); dns_clientinfomethods_init(&cm, ns_client_sourceip); dns_clientinfo_init(&ci, client, NULL); /* * Try to find either a CNAME or the type of record demanded by the * request from the policy zone. */ rpz_clean(zonep, dbp, nodep, rdatasetp); result = rpz_ready(client, rdatasetp); if (result != ISC_R_SUCCESS) { CTRACE(ISC_LOG_ERROR, "rpz_ready() failed"); return (DNS_R_SERVFAIL); } *versionp = NULL; result = rpz_getdb(client, p_name, rpz_type, zonep, dbp, versionp); if (result != ISC_R_SUCCESS) return (DNS_R_NXDOMAIN); dns_fixedname_init(&foundf); found = dns_fixedname_name(&foundf); result = dns_db_findext(*dbp, p_name, *versionp, dns_rdatatype_any, 0, client->now, nodep, found, &cm, &ci, *rdatasetp, NULL); /* * Choose the best rdataset if we found something. */ if (result == ISC_R_SUCCESS) { dns_rdatasetiter_t *rdsiter; rdsiter = NULL; result = dns_db_allrdatasets(*dbp, *nodep, *versionp, 0, &rdsiter); if (result != ISC_R_SUCCESS) { rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, p_name, rpz_type, " allrdatasets()", result); CTRACE(ISC_LOG_ERROR, "rpz_find_p: allrdatasets failed"); return (DNS_R_SERVFAIL); } for (result = dns_rdatasetiter_first(rdsiter); result == ISC_R_SUCCESS; result = dns_rdatasetiter_next(rdsiter)) { dns_rdatasetiter_current(rdsiter, *rdatasetp); if ((*rdatasetp)->type == dns_rdatatype_cname || (*rdatasetp)->type == qtype) break; dns_rdataset_disassociate(*rdatasetp); } dns_rdatasetiter_destroy(&rdsiter); if (result != ISC_R_SUCCESS) { if (result != ISC_R_NOMORE) { rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, p_name, rpz_type, " rdatasetiter", result); CTRACE(ISC_LOG_ERROR, "rpz_find_p: rdatasetiter failed"); return (DNS_R_SERVFAIL); } /* * Ask again to get the right DNS_R_DNAME/NXRRSET/... * result if there is neither a CNAME nor target type. */ if (dns_rdataset_isassociated(*rdatasetp)) dns_rdataset_disassociate(*rdatasetp); dns_db_detachnode(*dbp, nodep); if (qtype == dns_rdatatype_rrsig || qtype == dns_rdatatype_sig) result = DNS_R_NXRRSET; else result = dns_db_findext(*dbp, p_name, *versionp, qtype, 0, client->now, nodep, found, &cm, &ci, *rdatasetp, NULL); } } switch (result) { case ISC_R_SUCCESS: if ((*rdatasetp)->type != dns_rdatatype_cname) { *policyp = DNS_RPZ_POLICY_RECORD; } else { *policyp = dns_rpz_decode_cname(rpz, *rdatasetp, self_name); if ((*policyp == DNS_RPZ_POLICY_RECORD || *policyp == DNS_RPZ_POLICY_WILDCNAME) && qtype != dns_rdatatype_cname && qtype != dns_rdatatype_any) return (DNS_R_CNAME); } return (ISC_R_SUCCESS); case DNS_R_NXRRSET: *policyp = DNS_RPZ_POLICY_NODATA; return (result); case DNS_R_DNAME: /* * DNAME policy RRs have very few if any uses that are not * better served with simple wildcards. Making them work would * require complications to get the number of labels matched * in the name or the found name to the main DNS_R_DNAME case * in query_find(). The domain also does not appear in the * summary database at the right level, so this happens only * with a single policy zone when we have no summary database. * Treat it as a miss. */ case DNS_R_NXDOMAIN: case DNS_R_EMPTYNAME: return (DNS_R_NXDOMAIN); default: rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, p_name, rpz_type, "", result); CTRACE(ISC_LOG_ERROR, "rpz_find_p: unexpected result"); return (DNS_R_SERVFAIL); } } static void rpz_save_p(dns_rpz_st_t *st, dns_rpz_zone_t *rpz, dns_rpz_type_t rpz_type, dns_rpz_policy_t policy, dns_name_t *p_name, dns_rpz_prefix_t prefix, isc_result_t result, dns_zone_t **zonep, dns_db_t **dbp, dns_dbnode_t **nodep, dns_rdataset_t **rdatasetp, dns_dbversion_t *version) { dns_rdataset_t *trdataset = NULL; rpz_match_clear(st); st->m.rpz = rpz; st->m.type = rpz_type; st->m.policy = policy; dns_name_copy(p_name, st->p_name, NULL); st->m.prefix = prefix; st->m.result = result; SAVE(st->m.zone, *zonep); SAVE(st->m.db, *dbp); SAVE(st->m.node, *nodep); if (*rdatasetp != NULL && dns_rdataset_isassociated(*rdatasetp)) { /* * Save the replacement rdataset from the policy * and make the previous replacement rdataset scratch. */ SAVE(trdataset, st->m.rdataset); SAVE(st->m.rdataset, *rdatasetp); SAVE(*rdatasetp, trdataset); st->m.ttl = ISC_MIN(st->m.rdataset->ttl, rpz->max_policy_ttl); } else { st->m.ttl = ISC_MIN(DNS_RPZ_TTL_DEFAULT, rpz->max_policy_ttl); } SAVE(st->m.version, version); } /* * Check this address in every eligible policy zone. */ static isc_result_t rpz_rewrite_ip(ns_client_t *client, const isc_netaddr_t *netaddr, dns_rdatatype_t qtype, dns_rpz_type_t rpz_type, dns_rpz_zbits_t zbits, dns_rdataset_t **p_rdatasetp) { dns_rpz_zones_t *rpzs; dns_rpz_st_t *st; dns_rpz_zone_t *rpz; dns_rpz_prefix_t prefix; dns_rpz_num_t rpz_num; dns_fixedname_t ip_namef, p_namef; dns_name_t *ip_name, *p_name; dns_zone_t *p_zone; dns_db_t *p_db; dns_dbversion_t *p_version; dns_dbnode_t *p_node; dns_rpz_policy_t policy; isc_result_t result; CTRACE(ISC_LOG_DEBUG(3), "rpz_rewrite_ip"); dns_fixedname_init(&ip_namef); ip_name = dns_fixedname_name(&ip_namef); p_zone = NULL; p_db = NULL; p_node = NULL; rpzs = client->view->rpzs; st = client->query.rpz_st; while (zbits != 0) { rpz_num = dns_rpz_find_ip(rpzs, rpz_type, zbits, netaddr, ip_name, &prefix); if (rpz_num == DNS_RPZ_INVALID_NUM) break; zbits &= (DNS_RPZ_ZMASK(rpz_num) >> 1); /* * Do not try applying policy zones that cannot replace a * previously found policy zone. * Stop looking if the next best choice cannot * replace what we already have. */ rpz = rpzs->zones[rpz_num]; if (st->m.policy != DNS_RPZ_POLICY_MISS) { if (st->m.rpz->num < rpz->num) break; if (st->m.rpz->num == rpz->num && (st->m.type < rpz_type || st->m.prefix > prefix)) break; } /* * Get the policy for a prefix at least as long * as the prefix of the entry we had before. */ dns_fixedname_init(&p_namef); p_name = dns_fixedname_name(&p_namef); result = rpz_get_p_name(client, p_name, rpz, rpz_type, ip_name); if (result != ISC_R_SUCCESS) continue; result = rpz_find_p(client, ip_name, qtype, p_name, rpz, rpz_type, &p_zone, &p_db, &p_version, &p_node, p_rdatasetp, &policy); switch (result) { case DNS_R_NXDOMAIN: /* * Continue after a policy record that is missing * contrary to the summary data. The summary * data can out of date during races with and among * policy zone updates. */ CTRACE(ISC_LOG_ERROR, "rpz_rewrite_ip: mismatched summary data; " "continuing"); continue; case DNS_R_SERVFAIL: rpz_clean(&p_zone, &p_db, &p_node, p_rdatasetp); st->m.policy = DNS_RPZ_POLICY_ERROR; return (DNS_R_SERVFAIL); default: /* * Forget this policy if it is not preferable * to the previously found policy. * If this policy is not good, then stop looking * because none of the later policy zones would work. * * With more than one applicable policy, prefer * the earliest configured policy, * client-IP over QNAME over IP over NSDNAME over NSIP, * the longest prefix * the lexically smallest address. * dns_rpz_find_ip() ensures st->m.rpz->num >= rpz->num. * We can compare new and current p_name because * both are of the same type and in the same zone. * The tests above eliminate other reasons to * reject this policy. If this policy can't work, * then neither can later zones. */ if (st->m.policy != DNS_RPZ_POLICY_MISS && rpz->num == st->m.rpz->num && (st->m.type == rpz_type && st->m.prefix == prefix && 0 > dns_name_rdatacompare(st->p_name, p_name))) break; /* * Stop checking after saving an enabled hit in this * policy zone. The radix tree in the policy zone * ensures that we found the longest match. */ if (rpz->policy != DNS_RPZ_POLICY_DISABLED) { CTRACE(ISC_LOG_DEBUG(3), "rpz_rewrite_ip: rpz_save_p"); rpz_save_p(st, rpz, rpz_type, policy, p_name, prefix, result, &p_zone, &p_db, &p_node, p_rdatasetp, p_version); break; } /* * Log DNS_RPZ_POLICY_DISABLED zones * and try the next eligible policy zone. */ rpz_log_rewrite(client, ISC_TRUE, policy, rpz_type, p_zone, p_name, NULL, rpz_num); } } rpz_clean(&p_zone, &p_db, &p_node, p_rdatasetp); return (ISC_R_SUCCESS); } /* * Check the IP addresses in the A or AAAA rrsets for name against * all eligible rpz_type (IP or NSIP) response policy rewrite rules. */ static isc_result_t rpz_rewrite_ip_rrset(ns_client_t *client, dns_name_t *name, dns_rdatatype_t qtype, dns_rpz_type_t rpz_type, dns_rdatatype_t ip_type, dns_db_t **ip_dbp, dns_dbversion_t *ip_version, dns_rdataset_t **ip_rdatasetp, dns_rdataset_t **p_rdatasetp, isc_boolean_t resuming) { dns_rpz_zbits_t zbits; isc_netaddr_t netaddr; struct in_addr ina; struct in6_addr in6a; isc_result_t result; CTRACE(ISC_LOG_DEBUG(3), "rpz_rewrite_ip_rrset"); zbits = rpz_get_zbits(client, ip_type, rpz_type); if (zbits == 0) return (ISC_R_SUCCESS); /* * Get the A or AAAA rdataset. */ result = rpz_rrset_find(client, name, ip_type, rpz_type, ip_dbp, ip_version, ip_rdatasetp, resuming); switch (result) { case ISC_R_SUCCESS: case DNS_R_GLUE: case DNS_R_ZONECUT: break; case DNS_R_EMPTYNAME: case DNS_R_EMPTYWILD: case DNS_R_NXDOMAIN: case DNS_R_NCACHENXDOMAIN: case DNS_R_NXRRSET: case DNS_R_NCACHENXRRSET: case ISC_R_NOTFOUND: return (ISC_R_SUCCESS); case DNS_R_DELEGATION: case DNS_R_DUPLICATE: case DNS_R_DROP: return (result); case DNS_R_CNAME: case DNS_R_DNAME: rpz_log_fail(client, DNS_RPZ_DEBUG_LEVEL1, name, rpz_type, " NS address rewrite rrset", result); return (ISC_R_SUCCESS); default: if (client->query.rpz_st->m.policy != DNS_RPZ_POLICY_ERROR) { client->query.rpz_st->m.policy = DNS_RPZ_POLICY_ERROR; rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, name, rpz_type, " NS address rewrite rrset", result); } CTRACE(ISC_LOG_ERROR, "rpz_rewrite_ip_rrset: unexpected result"); return (DNS_R_SERVFAIL); } /* * Check all of the IP addresses in the rdataset. */ for (result = dns_rdataset_first(*ip_rdatasetp); result == ISC_R_SUCCESS; result = dns_rdataset_next(*ip_rdatasetp)) { dns_rdata_t rdata = DNS_RDATA_INIT; dns_rdataset_current(*ip_rdatasetp, &rdata); switch (rdata.type) { case dns_rdatatype_a: INSIST(rdata.length == 4); memmove(&ina.s_addr, rdata.data, 4); isc_netaddr_fromin(&netaddr, &ina); break; case dns_rdatatype_aaaa: INSIST(rdata.length == 16); memmove(in6a.s6_addr, rdata.data, 16); isc_netaddr_fromin6(&netaddr, &in6a); break; default: continue; } result = rpz_rewrite_ip(client, &netaddr, qtype, rpz_type, zbits, p_rdatasetp); if (result != ISC_R_SUCCESS) return (result); } return (ISC_R_SUCCESS); } /* * Look for IP addresses in A and AAAA rdatasets * that trigger all eligible IP or NSIP policy rules. */ static isc_result_t rpz_rewrite_ip_rrsets(ns_client_t *client, dns_name_t *name, dns_rdatatype_t qtype, dns_rpz_type_t rpz_type, dns_rdataset_t **ip_rdatasetp, isc_boolean_t resuming) { dns_rpz_st_t *st; dns_dbversion_t *ip_version; dns_db_t *ip_db; dns_rdataset_t *p_rdataset; isc_result_t result; CTRACE(ISC_LOG_DEBUG(3), "rpz_rewrite_ip_rrsets"); st = client->query.rpz_st; ip_version = NULL; ip_db = NULL; p_rdataset = NULL; if ((st->state & DNS_RPZ_DONE_IPv4) == 0 && (qtype == dns_rdatatype_a || qtype == dns_rdatatype_any || rpz_type == DNS_RPZ_TYPE_NSIP)) { /* * Rewrite based on an IPv4 address that will appear * in the ANSWER section or if we are checking IP addresses. */ result = rpz_rewrite_ip_rrset(client, name, qtype, rpz_type, dns_rdatatype_a, &ip_db, ip_version, ip_rdatasetp, &p_rdataset, resuming); if (result == ISC_R_SUCCESS) st->state |= DNS_RPZ_DONE_IPv4; } else { result = ISC_R_SUCCESS; } if (result == ISC_R_SUCCESS && (qtype == dns_rdatatype_aaaa || qtype == dns_rdatatype_any || rpz_type == DNS_RPZ_TYPE_NSIP)) { /* * Rewrite based on IPv6 addresses that will appear * in the ANSWER section or if we are checking IP addresses. */ result = rpz_rewrite_ip_rrset(client, name, qtype, rpz_type, dns_rdatatype_aaaa, &ip_db, ip_version, ip_rdatasetp, &p_rdataset, resuming); } if (ip_db != NULL) dns_db_detach(&ip_db); query_putrdataset(client, &p_rdataset); return (result); } /* * Try to rewrite a request for a qtype rdataset based on the trigger name * trig_name and rpz_type (DNS_RPZ_TYPE_QNAME or DNS_RPZ_TYPE_NSDNAME). * Record the results including the replacement rdataset if any * in client->query.rpz_st. * *rdatasetp is a scratch rdataset. */ static isc_result_t rpz_rewrite_name(ns_client_t *client, dns_name_t *trig_name, dns_rdatatype_t qtype, dns_rpz_type_t rpz_type, dns_rpz_zbits_t allowed_zbits, dns_rdataset_t **rdatasetp) { dns_rpz_zones_t *rpzs; dns_rpz_zone_t *rpz; dns_rpz_st_t *st; dns_fixedname_t p_namef; dns_name_t *p_name; dns_rpz_zbits_t zbits; dns_rpz_num_t rpz_num; dns_zone_t *p_zone; dns_db_t *p_db; dns_dbversion_t *p_version; dns_dbnode_t *p_node; dns_rpz_policy_t policy; isc_result_t result; CTRACE(ISC_LOG_DEBUG(3), "rpz_rewrite_name"); zbits = rpz_get_zbits(client, qtype, rpz_type); zbits &= allowed_zbits; if (zbits == 0) return (ISC_R_SUCCESS); rpzs = client->view->rpzs; /* * Use the summary database to find the bit mask of policy zones * with policies for this trigger name. We do this even if there * is only one eligible policy zone so that wildcard triggers * are matched correctly, and not into their parent. */ zbits = dns_rpz_find_name(rpzs, rpz_type, zbits, trig_name); if (zbits == 0) return (ISC_R_SUCCESS); dns_fixedname_init(&p_namef); p_name = dns_fixedname_name(&p_namef); p_zone = NULL; p_db = NULL; p_node = NULL; st = client->query.rpz_st; /* * Check the trigger name in every policy zone that the summary data * says has a hit for the trigger name. * Most of the time there are no eligible zones and the summary data * keeps us from getting this far. * We check the most eligible zone first and so usually check only * one policy zone. */ for (rpz_num = 0; zbits != 0; ++rpz_num, zbits >>= 1) { if ((zbits & 1) == 0) continue; /* * Do not check policy zones that cannot replace a previously * found policy. */ rpz = rpzs->zones[rpz_num]; if (st->m.policy != DNS_RPZ_POLICY_MISS) { if (st->m.rpz->num < rpz->num) break; if (st->m.rpz->num == rpz->num && st->m.type < rpz_type) break; } /* * Get the next policy zone's record for this trigger name. */ result = rpz_get_p_name(client, p_name, rpz, rpz_type, trig_name); if (result != ISC_R_SUCCESS) continue; result = rpz_find_p(client, trig_name, qtype, p_name, rpz, rpz_type, &p_zone, &p_db, &p_version, &p_node, rdatasetp, &policy); switch (result) { case DNS_R_NXDOMAIN: /* * Continue after a missing policy record * contrary to the summary data. The summary * data can out of date during races with and among * policy zone updates. */ CTRACE(ISC_LOG_ERROR, "rpz_rewrite_name: mismatched summary data; " "continuing"); continue; case DNS_R_SERVFAIL: rpz_clean(&p_zone, &p_db, &p_node, rdatasetp); st->m.policy = DNS_RPZ_POLICY_ERROR; return (DNS_R_SERVFAIL); default: /* * With more than one applicable policy, prefer * the earliest configured policy, * client-IP over QNAME over IP over NSDNAME over NSIP, * and the smallest name. * We known st->m.rpz->num >= rpz->num and either * st->m.rpz->num > rpz->num or st->m.type >= rpz_type */ if (st->m.policy != DNS_RPZ_POLICY_MISS && rpz->num == st->m.rpz->num && (st->m.type < rpz_type || (st->m.type == rpz_type && 0 >= dns_name_compare(p_name, st->p_name)))) continue; #if 0 /* * This code would block a customer reported information * leak of rpz rules by rewriting requests in the * rpz-ip, rpz-nsip, rpz-nsdname,and rpz-passthru TLDs. * Without this code, a bad guy could request * 24.0.3.2.10.rpz-ip. to find the policy rule for * 10.2.3.0/14. It is an insignificant leak and this * code is not worth its cost, because the bad guy * could publish "evil.com A 10.2.3.4" and request * evil.com to get the same information. * Keep code with "#if 0" in case customer demand * is irresistible. * * We have the less frequent case of a triggered * policy. Check that we have not trigger on one * of the pretend RPZ TLDs. * This test would make it impossible to rewrite * names in TLDs that start with "rpz-" should * ICANN ever allow such TLDs. */ unsigned int labels; labels = dns_name_countlabels(trig_name); if (labels >= 2) { dns_label_t label; dns_name_getlabel(trig_name, labels-2, &label); if (label.length >= sizeof(DNS_RPZ_PREFIX)-1 && strncasecmp((const char *)label.base+1, DNS_RPZ_PREFIX, sizeof(DNS_RPZ_PREFIX)-1) == 0) continue; } #endif if (rpz->policy != DNS_RPZ_POLICY_DISABLED) { CTRACE(ISC_LOG_DEBUG(3), "rpz_rewrite_name: rpz_save_p"); rpz_save_p(st, rpz, rpz_type, policy, p_name, 0, result, &p_zone, &p_db, &p_node, rdatasetp, p_version); /* * After a hit, higher numbered policy zones * are irrelevant */ rpz_clean(&p_zone, &p_db, &p_node, rdatasetp); return (ISC_R_SUCCESS); } /* * Log DNS_RPZ_POLICY_DISABLED zones * and try the next eligible policy zone. */ rpz_log_rewrite(client, ISC_TRUE, policy, rpz_type, p_zone, p_name, NULL, rpz_num); break; } } rpz_clean(&p_zone, &p_db, &p_node, rdatasetp); return (ISC_R_SUCCESS); } static void rpz_rewrite_ns_skip(ns_client_t *client, dns_name_t *nsname, isc_result_t result, int level, const char *str) { dns_rpz_st_t *st; CTRACE(ISC_LOG_DEBUG(3), "rpz_rewrite_ns_skip"); st = client->query.rpz_st; if (str != NULL) rpz_log_fail_helper(client, level, nsname, DNS_RPZ_TYPE_NSIP, DNS_RPZ_TYPE_NSDNAME, str, result); if (st->r.ns_rdataset != NULL && dns_rdataset_isassociated(st->r.ns_rdataset)) dns_rdataset_disassociate(st->r.ns_rdataset); st->r.label--; } /* * RPZ query result types */ typedef enum { RPZ_QRESULT_TYPE_DONE, RPZ_QRESULT_TYPE_RESTART, RPZ_QRESULT_TYPE_RECURSE, } rpz_qresult_type_t; /* * Look for response policy zone QNAME, NSIP, and NSDNAME rewriting. */ static isc_result_t rpz_rewrite(ns_client_t *client, dns_rdatatype_t qtype, isc_result_t qresult, isc_boolean_t resuming, dns_rdataset_t *ordataset, dns_rdataset_t *osigset) { dns_rpz_zones_t *rpzs; dns_rpz_st_t *st; dns_rdataset_t *rdataset; dns_fixedname_t nsnamef; dns_name_t *nsname; rpz_qresult_type_t qresult_type; dns_rpz_zbits_t zbits; isc_result_t result = ISC_R_SUCCESS; dns_rpz_have_t have; dns_rpz_popt_t popt; int rpz_ver; CTRACE(ISC_LOG_DEBUG(3), "rpz_rewrite"); rpzs = client->view->rpzs; st = client->query.rpz_st; if (rpzs == NULL || (st != NULL && (st->state & DNS_RPZ_REWRITTEN) != 0)) return (DNS_R_DISALLOWED); RWLOCK(&rpzs->search_lock, isc_rwlocktype_read); if (rpzs->p.num_zones == 0 || (!RECURSIONOK(client) && rpzs->p.no_rd_ok == 0) || !rpz_ck_dnssec(client, qresult, ordataset, osigset)) { RWUNLOCK(&rpzs->search_lock, isc_rwlocktype_read); return (DNS_R_DISALLOWED); } have = rpzs->have; popt = rpzs->p; rpz_ver = rpzs->rpz_ver; RWUNLOCK(&rpzs->search_lock, isc_rwlocktype_read); if (st == NULL) { st = isc_mem_get(client->mctx, sizeof(*st)); if (st == NULL) return (ISC_R_NOMEMORY); st->state = 0; } if (st->state == 0) { st->state |= DNS_RPZ_ACTIVE; memset(&st->m, 0, sizeof(st->m)); st->m.type = DNS_RPZ_TYPE_BAD; st->m.policy = DNS_RPZ_POLICY_MISS; st->m.ttl = ~0; memset(&st->r, 0, sizeof(st->r)); memset(&st->q, 0, sizeof(st->q)); dns_fixedname_init(&st->_p_namef); dns_fixedname_init(&st->_r_namef); dns_fixedname_init(&st->_fnamef); st->p_name = dns_fixedname_name(&st->_p_namef); st->r_name = dns_fixedname_name(&st->_r_namef); st->fname = dns_fixedname_name(&st->_fnamef); st->have = have; st->popt = popt; st->rpz_ver = rpz_ver; client->query.rpz_st = st; } /* * There is nothing to rewrite if the main query failed. */ switch (qresult) { case ISC_R_SUCCESS: case DNS_R_GLUE: case DNS_R_ZONECUT: qresult_type = RPZ_QRESULT_TYPE_DONE; break; case DNS_R_EMPTYNAME: case DNS_R_NXRRSET: case DNS_R_NXDOMAIN: case DNS_R_EMPTYWILD: case DNS_R_NCACHENXDOMAIN: case DNS_R_NCACHENXRRSET: case DNS_R_CNAME: case DNS_R_DNAME: qresult_type = RPZ_QRESULT_TYPE_RESTART; break; case DNS_R_DELEGATION: case ISC_R_NOTFOUND: /* * If recursion is on, do only tentative rewriting. * If recursion is off, this the normal and only time we * can rewrite. */ if (RECURSIONOK(client)) qresult_type = RPZ_QRESULT_TYPE_RECURSE; else qresult_type = RPZ_QRESULT_TYPE_RESTART; break; case ISC_R_FAILURE: case ISC_R_TIMEDOUT: case DNS_R_BROKENCHAIN: rpz_log_fail(client, DNS_RPZ_DEBUG_LEVEL3, client->query.qname, DNS_RPZ_TYPE_QNAME, " stop on qresult in rpz_rewrite()", qresult); return (ISC_R_SUCCESS); default: rpz_log_fail(client, DNS_RPZ_DEBUG_LEVEL1, client->query.qname, DNS_RPZ_TYPE_QNAME, " stop on unrecognized qresult in rpz_rewrite()", qresult); return (ISC_R_SUCCESS); } rdataset = NULL; if ((st->state & (DNS_RPZ_DONE_CLIENT_IP | DNS_RPZ_DONE_QNAME)) != (DNS_RPZ_DONE_CLIENT_IP | DNS_RPZ_DONE_QNAME)) { isc_netaddr_t netaddr; dns_rpz_zbits_t allowed; if (qresult_type == RPZ_QRESULT_TYPE_RECURSE) { /* * This request needs recursion that has not been done. * Get bits for the policy zones that do not need * to wait for the results of recursion. */ allowed = st->have.qname_skip_recurse; if (allowed == 0) return (ISC_R_SUCCESS); } else { allowed = DNS_RPZ_ALL_ZBITS; } /* * Check once for triggers for the client IP address. */ if ((st->state & DNS_RPZ_DONE_CLIENT_IP) == 0) { zbits = rpz_get_zbits(client, dns_rdatatype_none, DNS_RPZ_TYPE_CLIENT_IP); zbits &= allowed; if (zbits != 0) { isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr); result = rpz_rewrite_ip(client, &netaddr, qtype, DNS_RPZ_TYPE_CLIENT_IP, zbits, &rdataset); if (result != ISC_R_SUCCESS) goto cleanup; } } /* * Check triggers for the query name if this is the first time * for the current qname. * There is a first time for each name in a CNAME chain */ if ((st->state & DNS_RPZ_DONE_QNAME) == 0) { result = rpz_rewrite_name(client, client->query.qname, qtype, DNS_RPZ_TYPE_QNAME, allowed, &rdataset); if (result != ISC_R_SUCCESS) goto cleanup; /* * Check IPv4 addresses in A RRs next. * Reset to the start of the NS names. */ st->r.label = dns_name_countlabels(client->query.qname); st->state &= ~(DNS_RPZ_DONE_QNAME_IP | DNS_RPZ_DONE_IPv4); } /* * Quit if this was an attempt to find a qname or * client-IP trigger before recursion. * We will be back if no pre-recursion triggers hit. * For example, consider 2 policy zones, both with qname and * IP address triggers. If the qname misses the 1st zone, * then we cannot know whether a hit for the qname in the * 2nd zone matters until after recursing to get the A RRs and * testing them in the first zone. * Do not bother saving the work from this attempt, * because recusion is so slow. */ if (qresult_type == RPZ_QRESULT_TYPE_RECURSE) goto cleanup; /* * DNS_RPZ_DONE_QNAME but not DNS_RPZ_DONE_CLIENT_IP * is reset at the end of dealing with each CNAME. */ st->state |= (DNS_RPZ_DONE_CLIENT_IP | DNS_RPZ_DONE_QNAME); } /* * Check known IP addresses for the query name if the database * lookup resulted in some addresses (qresult_type == * RPZ_QRESULT_TYPE_DONE) and if we have not already checked them. * Any recursion required for the query has already happened. * Do not check addresses that will not be in the ANSWER section. */ if ((st->state & DNS_RPZ_DONE_QNAME_IP) == 0 && qresult_type == RPZ_QRESULT_TYPE_DONE && rpz_get_zbits(client, qtype, DNS_RPZ_TYPE_IP) != 0) { result = rpz_rewrite_ip_rrsets(client, client->query.qname, qtype, DNS_RPZ_TYPE_IP, &rdataset, resuming); if (result != ISC_R_SUCCESS) goto cleanup; /* * We are finished checking the IP addresses for the qname. * Start with IPv4 if we will check NS IP addesses. */ st->state |= DNS_RPZ_DONE_QNAME_IP; st->state &= ~DNS_RPZ_DONE_IPv4; } /* * Stop looking for rules if there are none of the other kinds * that could override what we already have. */ if (rpz_get_zbits(client, dns_rdatatype_any, DNS_RPZ_TYPE_NSDNAME) == 0 && rpz_get_zbits(client, dns_rdatatype_any, DNS_RPZ_TYPE_NSIP) == 0) { result = ISC_R_SUCCESS; goto cleanup; } dns_fixedname_init(&nsnamef); dns_name_clone(client->query.qname, dns_fixedname_name(&nsnamef)); while (st->r.label > st->popt.min_ns_labels) { /* * Get NS rrset for each domain in the current qname. */ if (st->r.label == dns_name_countlabels(client->query.qname)) { nsname = client->query.qname; } else { nsname = dns_fixedname_name(&nsnamef); dns_name_split(client->query.qname, st->r.label, NULL, nsname); } if (st->r.ns_rdataset == NULL || !dns_rdataset_isassociated(st->r.ns_rdataset)) { dns_db_t *db = NULL; result = rpz_rrset_find(client, nsname, dns_rdatatype_ns, DNS_RPZ_TYPE_NSDNAME, &db, NULL, &st->r.ns_rdataset, resuming); if (db != NULL) dns_db_detach(&db); if (st->m.policy == DNS_RPZ_POLICY_ERROR) goto cleanup; switch (result) { case ISC_R_SUCCESS: result = dns_rdataset_first(st->r.ns_rdataset); if (result != ISC_R_SUCCESS) goto cleanup; st->state &= ~(DNS_RPZ_DONE_NSDNAME | DNS_RPZ_DONE_IPv4); break; case DNS_R_DELEGATION: case DNS_R_DUPLICATE: case DNS_R_DROP: goto cleanup; case DNS_R_EMPTYNAME: case DNS_R_NXRRSET: case DNS_R_EMPTYWILD: case DNS_R_NXDOMAIN: case DNS_R_NCACHENXDOMAIN: case DNS_R_NCACHENXRRSET: case ISC_R_NOTFOUND: case DNS_R_CNAME: case DNS_R_DNAME: rpz_rewrite_ns_skip(client, nsname, result, 0, NULL); continue; case ISC_R_TIMEDOUT: case DNS_R_BROKENCHAIN: case ISC_R_FAILURE: rpz_rewrite_ns_skip(client, nsname, result, DNS_RPZ_DEBUG_LEVEL3, " NS rpz_rrset_find()"); continue; default: rpz_rewrite_ns_skip(client, nsname, result, DNS_RPZ_INFO_LEVEL, " unrecognized NS" " rpz_rrset_find()"); continue; } } /* * Check all NS names. */ do { dns_rdata_ns_t ns; dns_rdata_t nsrdata = DNS_RDATA_INIT; dns_rdataset_current(st->r.ns_rdataset, &nsrdata); result = dns_rdata_tostruct(&nsrdata, &ns, NULL); dns_rdata_reset(&nsrdata); if (result != ISC_R_SUCCESS) { rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, nsname, DNS_RPZ_TYPE_NSIP, " rdata_tostruct()", result); st->m.policy = DNS_RPZ_POLICY_ERROR; goto cleanup; } /* * Do nothing about "NS ." */ if (dns_name_equal(&ns.name, dns_rootname)) { dns_rdata_freestruct(&ns); result = dns_rdataset_next(st->r.ns_rdataset); continue; } /* * Check this NS name if we did not handle it * during a previous recursion. */ if ((st->state & DNS_RPZ_DONE_NSDNAME) == 0) { result = rpz_rewrite_name(client, &ns.name, qtype, DNS_RPZ_TYPE_NSDNAME, DNS_RPZ_ALL_ZBITS, &rdataset); if (result != ISC_R_SUCCESS) { dns_rdata_freestruct(&ns); goto cleanup; } st->state |= DNS_RPZ_DONE_NSDNAME; } /* * Check all IP addresses for this NS name. */ result = rpz_rewrite_ip_rrsets(client, &ns.name, qtype, DNS_RPZ_TYPE_NSIP, &rdataset, resuming); dns_rdata_freestruct(&ns); if (result != ISC_R_SUCCESS) goto cleanup; st->state &= ~(DNS_RPZ_DONE_NSDNAME | DNS_RPZ_DONE_IPv4); result = dns_rdataset_next(st->r.ns_rdataset); } while (result == ISC_R_SUCCESS); dns_rdataset_disassociate(st->r.ns_rdataset); st->r.label--; if (rpz_get_zbits(client, dns_rdatatype_any, DNS_RPZ_TYPE_NSDNAME) == 0 && rpz_get_zbits(client, dns_rdatatype_any, DNS_RPZ_TYPE_NSIP) == 0) break; } /* * Use the best hit, if any. */ result = ISC_R_SUCCESS; cleanup: if (st->m.policy != DNS_RPZ_POLICY_MISS && st->m.policy != DNS_RPZ_POLICY_ERROR && st->m.rpz->policy != DNS_RPZ_POLICY_GIVEN) st->m.policy = st->m.rpz->policy; if (st->m.policy == DNS_RPZ_POLICY_MISS || st->m.policy == DNS_RPZ_POLICY_PASSTHRU || st->m.policy == DNS_RPZ_POLICY_ERROR) { if (st->m.policy == DNS_RPZ_POLICY_PASSTHRU && result != DNS_R_DELEGATION) rpz_log_rewrite(client, ISC_FALSE, st->m.policy, st->m.type, st->m.zone, st->p_name, NULL, st->m.rpz->num); rpz_match_clear(st); } if (st->m.policy == DNS_RPZ_POLICY_ERROR) { CTRACE(ISC_LOG_ERROR, "SERVFAIL due to RPZ policy"); st->m.type = DNS_RPZ_TYPE_BAD; result = DNS_R_SERVFAIL; } query_putrdataset(client, &rdataset); if ((st->state & DNS_RPZ_RECURSING) == 0) rpz_clean(NULL, &st->r.db, NULL, &st->r.ns_rdataset); return (result); } /* * See if response policy zone rewriting is allowed by a lack of interest * by the client in DNSSEC or a lack of signatures. */ static isc_boolean_t rpz_ck_dnssec(ns_client_t *client, isc_result_t qresult, dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) { dns_fixedname_t fixed; dns_name_t *found; dns_rdataset_t trdataset; dns_rdatatype_t type; isc_result_t result; CTRACE(ISC_LOG_DEBUG(3), "rpz_ck_dnssec"); if (client->view->rpzs->p.break_dnssec || !WANTDNSSEC(client)) return (ISC_TRUE); /* * We do not know if there are signatures if we have not recursed * for them. */ if (qresult == DNS_R_DELEGATION || qresult == ISC_R_NOTFOUND) return (ISC_FALSE); if (sigrdataset == NULL) return (ISC_TRUE); if (dns_rdataset_isassociated(sigrdataset)) return (ISC_FALSE); /* * We are happy to rewrite nothing. */ if (rdataset == NULL || !dns_rdataset_isassociated(rdataset)) return (ISC_TRUE); /* * Do not rewrite if there is any sign of signatures. */ if (rdataset->type == dns_rdatatype_nsec || rdataset->type == dns_rdatatype_nsec3 || rdataset->type == dns_rdatatype_rrsig) return (ISC_FALSE); /* * Look for a signature in a negative cache rdataset. */ if ((rdataset->attributes & DNS_RDATASETATTR_NEGATIVE) == 0) return (ISC_TRUE); dns_fixedname_init(&fixed); found = dns_fixedname_name(&fixed); dns_rdataset_init(&trdataset); for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS; result = dns_rdataset_next(rdataset)) { dns_ncache_current(rdataset, found, &trdataset); type = trdataset.type; dns_rdataset_disassociate(&trdataset); if (type == dns_rdatatype_nsec || type == dns_rdatatype_nsec3 || type == dns_rdatatype_rrsig) return (ISC_FALSE); } return (ISC_TRUE); } /* * Add a CNAME to the query response, including translating foo.evil.com and * *.evil.com CNAME *.example.com * to * foo.evil.com CNAME foo.evil.com.example.com */ static isc_result_t rpz_add_cname(ns_client_t *client, dns_rpz_st_t *st, dns_name_t *cname, dns_name_t *fname, isc_buffer_t *dbuf) { dns_fixedname_t prefix, suffix; unsigned int labels; isc_result_t result; CTRACE(ISC_LOG_DEBUG(3), "rpz_add_cname"); labels = dns_name_countlabels(cname); if (labels > 2 && dns_name_iswildcard(cname)) { dns_fixedname_init(&prefix); dns_name_split(client->query.qname, 1, dns_fixedname_name(&prefix), NULL); dns_fixedname_init(&suffix); dns_name_split(cname, labels-1, NULL, dns_fixedname_name(&suffix)); result = dns_name_concatenate(dns_fixedname_name(&prefix), dns_fixedname_name(&suffix), fname, NULL); if (result == DNS_R_NAMETOOLONG) client->message->rcode = dns_rcode_yxdomain; } else { result = dns_name_copy(cname, fname, NULL); RUNTIME_CHECK(result == ISC_R_SUCCESS); } if (result != ISC_R_SUCCESS) return (result); query_keepname(client, fname, dbuf); result = query_add_cname(client, client->query.qname, fname, dns_trust_authanswer, st->m.ttl); if (result != ISC_R_SUCCESS) return (result); rpz_log_rewrite(client, ISC_FALSE, st->m.policy, st->m.type, st->m.zone, st->p_name, fname, st->m.rpz->num); ns_client_qnamereplace(client, fname); /* * Turn off DNSSEC because the results of a * response policy zone cannot verify. */ client->attributes &= ~(NS_CLIENTATTR_WANTDNSSEC | NS_CLIENTATTR_WANTAD); return (ISC_R_SUCCESS); } #define MAX_RESTARTS 16 #define QUERY_ERROR(r) \ do { \ eresult = r; \ want_restart = ISC_FALSE; \ line = __LINE__; \ } while (0) #define RECURSE_ERROR(r) \ do { \ if ((r) == DNS_R_DUPLICATE || (r) == DNS_R_DROP) \ QUERY_ERROR(r); \ else \ QUERY_ERROR(DNS_R_SERVFAIL); \ } while (0) /* * Extract a network address from the RDATA of an A or AAAA * record. * * Returns: * ISC_R_SUCCESS * ISC_R_NOTIMPLEMENTED The rdata is not a known address type. */ static isc_result_t rdata_tonetaddr(const dns_rdata_t *rdata, isc_netaddr_t *netaddr) { struct in_addr ina; struct in6_addr in6a; switch (rdata->type) { case dns_rdatatype_a: INSIST(rdata->length == 4); memmove(&ina.s_addr, rdata->data, 4); isc_netaddr_fromin(netaddr, &ina); return (ISC_R_SUCCESS); case dns_rdatatype_aaaa: INSIST(rdata->length == 16); memmove(in6a.s6_addr, rdata->data, 16); isc_netaddr_fromin6(netaddr, &in6a); return (ISC_R_SUCCESS); default: return (ISC_R_NOTIMPLEMENTED); } } /* * Find the sort order of 'rdata' in the topology-like * ACL forming the second element in a 2-element top-level * sortlist statement. */ static int query_sortlist_order_2element(const dns_rdata_t *rdata, const void *arg) { isc_netaddr_t netaddr; if (rdata_tonetaddr(rdata, &netaddr) != ISC_R_SUCCESS) return (INT_MAX); return (ns_sortlist_addrorder2(&netaddr, arg)); } /* * Find the sort order of 'rdata' in the matching element * of a 1-element top-level sortlist statement. */ static int query_sortlist_order_1element(const dns_rdata_t *rdata, const void *arg) { isc_netaddr_t netaddr; if (rdata_tonetaddr(rdata, &netaddr) != ISC_R_SUCCESS) return (INT_MAX); return (ns_sortlist_addrorder1(&netaddr, arg)); } /* * Find the sortlist statement that applies to 'client' and set up * the sortlist info in in client->message appropriately. */ static void setup_query_sortlist(ns_client_t *client) { isc_netaddr_t netaddr; dns_rdatasetorderfunc_t order = NULL; const void *order_arg = NULL; isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr); switch (ns_sortlist_setup(client->view->sortlist, &netaddr, &order_arg)) { case NS_SORTLISTTYPE_1ELEMENT: order = query_sortlist_order_1element; break; case NS_SORTLISTTYPE_2ELEMENT: order = query_sortlist_order_2element; break; case NS_SORTLISTTYPE_NONE: order = NULL; break; default: INSIST(0); break; } dns_message_setsortorder(client->message, order, order_arg); } static void query_addnoqnameproof(ns_client_t *client, dns_rdataset_t *rdataset) { isc_buffer_t *dbuf, b; dns_name_t *fname; dns_rdataset_t *neg, *negsig; isc_result_t result = ISC_R_NOMEMORY; CTRACE(ISC_LOG_DEBUG(3), "query_addnoqnameproof"); fname = NULL; neg = NULL; negsig = NULL; dbuf = query_getnamebuf(client); if (dbuf == NULL) goto cleanup; fname = query_newname(client, dbuf, &b); neg = query_newrdataset(client); negsig = query_newrdataset(client); if (fname == NULL || neg == NULL || negsig == NULL) goto cleanup; result = dns_rdataset_getnoqname(rdataset, fname, neg, negsig); RUNTIME_CHECK(result == ISC_R_SUCCESS); query_addrrset(client, &fname, &neg, &negsig, dbuf, DNS_SECTION_AUTHORITY); if ((rdataset->attributes & DNS_RDATASETATTR_CLOSEST) == 0) goto cleanup; if (fname == NULL) { dbuf = query_getnamebuf(client); if (dbuf == NULL) goto cleanup; fname = query_newname(client, dbuf, &b); } if (neg == NULL) neg = query_newrdataset(client); else if (dns_rdataset_isassociated(neg)) dns_rdataset_disassociate(neg); if (negsig == NULL) negsig = query_newrdataset(client); else if (dns_rdataset_isassociated(negsig)) dns_rdataset_disassociate(negsig); if (fname == NULL || neg == NULL || negsig == NULL) goto cleanup; result = dns_rdataset_getclosest(rdataset, fname, neg, negsig); RUNTIME_CHECK(result == ISC_R_SUCCESS); query_addrrset(client, &fname, &neg, &negsig, dbuf, DNS_SECTION_AUTHORITY); cleanup: if (neg != NULL) query_putrdataset(client, &neg); if (negsig != NULL) query_putrdataset(client, &negsig); if (fname != NULL) query_releasename(client, &fname); } static inline void answer_in_glue(ns_client_t *client, dns_rdatatype_t qtype) { dns_name_t *name; dns_message_t *msg; dns_section_t section = DNS_SECTION_ADDITIONAL; dns_rdataset_t *rdataset = NULL; msg = client->message; for (name = ISC_LIST_HEAD(msg->sections[section]); name != NULL; name = ISC_LIST_NEXT(name, link)) if (dns_name_equal(name, client->query.qname)) { for (rdataset = ISC_LIST_HEAD(name->list); rdataset != NULL; rdataset = ISC_LIST_NEXT(rdataset, link)) if (rdataset->type == qtype) break; break; } if (rdataset != NULL) { ISC_LIST_UNLINK(msg->sections[section], name, link); ISC_LIST_PREPEND(msg->sections[section], name, link); ISC_LIST_UNLINK(name->list, rdataset, link); ISC_LIST_PREPEND(name->list, rdataset, link); rdataset->attributes |= DNS_RDATASETATTR_REQUIRED; } } static unsigned char inaddr10_offsets[] = { 0, 3, 11, 16 }; static unsigned char inaddr172_offsets[] = { 0, 3, 7, 15, 20 }; static unsigned char inaddr192_offsets[] = { 0, 4, 8, 16, 21 }; static unsigned char inaddr10[] = "\00210\007IN-ADDR\004ARPA"; static unsigned char inaddr16172[] = "\00216\003172\007IN-ADDR\004ARPA"; static unsigned char inaddr17172[] = "\00217\003172\007IN-ADDR\004ARPA"; static unsigned char inaddr18172[] = "\00218\003172\007IN-ADDR\004ARPA"; static unsigned char inaddr19172[] = "\00219\003172\007IN-ADDR\004ARPA"; static unsigned char inaddr20172[] = "\00220\003172\007IN-ADDR\004ARPA"; static unsigned char inaddr21172[] = "\00221\003172\007IN-ADDR\004ARPA"; static unsigned char inaddr22172[] = "\00222\003172\007IN-ADDR\004ARPA"; static unsigned char inaddr23172[] = "\00223\003172\007IN-ADDR\004ARPA"; static unsigned char inaddr24172[] = "\00224\003172\007IN-ADDR\004ARPA"; static unsigned char inaddr25172[] = "\00225\003172\007IN-ADDR\004ARPA"; static unsigned char inaddr26172[] = "\00226\003172\007IN-ADDR\004ARPA"; static unsigned char inaddr27172[] = "\00227\003172\007IN-ADDR\004ARPA"; static unsigned char inaddr28172[] = "\00228\003172\007IN-ADDR\004ARPA"; static unsigned char inaddr29172[] = "\00229\003172\007IN-ADDR\004ARPA"; static unsigned char inaddr30172[] = "\00230\003172\007IN-ADDR\004ARPA"; static unsigned char inaddr31172[] = "\00231\003172\007IN-ADDR\004ARPA"; static unsigned char inaddr168192[] = "\003168\003192\007IN-ADDR\004ARPA"; static dns_name_t rfc1918names[] = { DNS_NAME_INITABSOLUTE(inaddr10, inaddr10_offsets), DNS_NAME_INITABSOLUTE(inaddr16172, inaddr172_offsets), DNS_NAME_INITABSOLUTE(inaddr17172, inaddr172_offsets), DNS_NAME_INITABSOLUTE(inaddr18172, inaddr172_offsets), DNS_NAME_INITABSOLUTE(inaddr19172, inaddr172_offsets), DNS_NAME_INITABSOLUTE(inaddr20172, inaddr172_offsets), DNS_NAME_INITABSOLUTE(inaddr21172, inaddr172_offsets), DNS_NAME_INITABSOLUTE(inaddr22172, inaddr172_offsets), DNS_NAME_INITABSOLUTE(inaddr23172, inaddr172_offsets), DNS_NAME_INITABSOLUTE(inaddr24172, inaddr172_offsets), DNS_NAME_INITABSOLUTE(inaddr25172, inaddr172_offsets), DNS_NAME_INITABSOLUTE(inaddr26172, inaddr172_offsets), DNS_NAME_INITABSOLUTE(inaddr27172, inaddr172_offsets), DNS_NAME_INITABSOLUTE(inaddr28172, inaddr172_offsets), DNS_NAME_INITABSOLUTE(inaddr29172, inaddr172_offsets), DNS_NAME_INITABSOLUTE(inaddr30172, inaddr172_offsets), DNS_NAME_INITABSOLUTE(inaddr31172, inaddr172_offsets), DNS_NAME_INITABSOLUTE(inaddr168192, inaddr192_offsets) }; static unsigned char prisoner_data[] = "\010prisoner\004iana\003org"; static unsigned char hostmaster_data[] = "\012hostmaster\014root-servers\003org"; static unsigned char prisoner_offsets[] = { 0, 9, 14, 18 }; static unsigned char hostmaster_offsets[] = { 0, 11, 24, 28 }; static dns_name_t prisoner = DNS_NAME_INITABSOLUTE(prisoner_data, prisoner_offsets); static dns_name_t hostmaster = DNS_NAME_INITABSOLUTE(hostmaster_data, hostmaster_offsets); static void warn_rfc1918(ns_client_t *client, dns_name_t *fname, dns_rdataset_t *rdataset) { unsigned int i; dns_rdata_t rdata = DNS_RDATA_INIT; dns_rdata_soa_t soa; dns_rdataset_t found; isc_result_t result; for (i = 0; i < (sizeof(rfc1918names)/sizeof(*rfc1918names)); i++) { if (dns_name_issubdomain(fname, &rfc1918names[i])) { dns_rdataset_init(&found); result = dns_ncache_getrdataset(rdataset, &rfc1918names[i], dns_rdatatype_soa, &found); if (result != ISC_R_SUCCESS) return; result = dns_rdataset_first(&found); RUNTIME_CHECK(result == ISC_R_SUCCESS); dns_rdataset_current(&found, &rdata); result = dns_rdata_tostruct(&rdata, &soa, NULL); RUNTIME_CHECK(result == ISC_R_SUCCESS); if (dns_name_equal(&soa.origin, &prisoner) && dns_name_equal(&soa.contact, &hostmaster)) { char buf[DNS_NAME_FORMATSIZE]; dns_name_format(fname, buf, sizeof(buf)); ns_client_log(client, DNS_LOGCATEGORY_SECURITY, NS_LOGMODULE_QUERY, ISC_LOG_WARNING, "RFC 1918 response from " "Internet for %s", buf); } dns_rdataset_disassociate(&found); return; } } } static void query_findclosestnsec3(dns_name_t *qname, dns_db_t *db, dns_dbversion_t *version, ns_client_t *client, dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset, dns_name_t *fname, isc_boolean_t exact, dns_name_t *found) { unsigned char salt[256]; size_t salt_length; isc_uint16_t iterations; isc_result_t result; unsigned int dboptions; dns_fixedname_t fixed; dns_hash_t hash; dns_name_t name; unsigned int skip = 0, labels; dns_rdata_nsec3_t nsec3; dns_rdata_t rdata = DNS_RDATA_INIT; isc_boolean_t optout; dns_clientinfomethods_t cm; dns_clientinfo_t ci; salt_length = sizeof(salt); result = dns_db_getnsec3parameters(db, version, &hash, NULL, &iterations, salt, &salt_length); if (result != ISC_R_SUCCESS) return; dns_name_init(&name, NULL); dns_name_clone(qname, &name); labels = dns_name_countlabels(&name); dns_clientinfomethods_init(&cm, ns_client_sourceip); dns_clientinfo_init(&ci, client, NULL); /* * Map unknown algorithm to known value. */ if (hash == DNS_NSEC3_UNKNOWNALG) hash = 1; again: dns_fixedname_init(&fixed); result = dns_nsec3_hashname(&fixed, NULL, NULL, &name, dns_db_origin(db), hash, iterations, salt, salt_length); if (result != ISC_R_SUCCESS) return; dboptions = client->query.dboptions | DNS_DBFIND_FORCENSEC3; result = dns_db_findext(db, dns_fixedname_name(&fixed), version, dns_rdatatype_nsec3, dboptions, client->now, NULL, fname, &cm, &ci, rdataset, sigrdataset); if (result == DNS_R_NXDOMAIN) { if (!dns_rdataset_isassociated(rdataset)) { return; } result = dns_rdataset_first(rdataset); INSIST(result == ISC_R_SUCCESS); dns_rdataset_current(rdataset, &rdata); dns_rdata_tostruct(&rdata, &nsec3, NULL); dns_rdata_reset(&rdata); optout = ISC_TF((nsec3.flags & DNS_NSEC3FLAG_OPTOUT) != 0); if (found != NULL && optout && dns_name_issubdomain(&name, dns_db_origin(db))) { dns_rdataset_disassociate(rdataset); if (dns_rdataset_isassociated(sigrdataset)) dns_rdataset_disassociate(sigrdataset); skip++; dns_name_getlabelsequence(qname, skip, labels - skip, &name); ns_client_log(client, DNS_LOGCATEGORY_DNSSEC, NS_LOGMODULE_QUERY, ISC_LOG_DEBUG(3), "looking for closest provable encloser"); goto again; } if (exact) ns_client_log(client, DNS_LOGCATEGORY_DNSSEC, NS_LOGMODULE_QUERY, ISC_LOG_WARNING, "expected a exact match NSEC3, got " "a covering record"); } else if (result != ISC_R_SUCCESS) { return; } else if (!exact) ns_client_log(client, DNS_LOGCATEGORY_DNSSEC, NS_LOGMODULE_QUERY, ISC_LOG_WARNING, "expected covering NSEC3, got an exact match"); if (found == qname) { if (skip != 0U) dns_name_getlabelsequence(qname, skip, labels - skip, found); } else if (found != NULL) dns_name_copy(&name, found, NULL); return; } #ifdef ALLOW_FILTER_AAAA static isc_boolean_t is_v4_client(ns_client_t *client) { if (isc_sockaddr_pf(&client->peeraddr) == AF_INET) return (ISC_TRUE); if (isc_sockaddr_pf(&client->peeraddr) == AF_INET6 && IN6_IS_ADDR_V4MAPPED(&client->peeraddr.type.sin6.sin6_addr)) return (ISC_TRUE); return (ISC_FALSE); } static isc_boolean_t is_v6_client(ns_client_t *client) { if (isc_sockaddr_pf(&client->peeraddr) == AF_INET6 && !IN6_IS_ADDR_V4MAPPED(&client->peeraddr.type.sin6.sin6_addr)) return (ISC_TRUE); return (ISC_FALSE); } #endif static isc_uint32_t dns64_ttl(dns_db_t *db, dns_dbversion_t *version) { dns_dbnode_t *node = NULL; dns_rdata_soa_t soa; dns_rdata_t rdata = DNS_RDATA_INIT; dns_rdataset_t rdataset; isc_result_t result; isc_uint32_t ttl = ISC_UINT32_MAX; dns_rdataset_init(&rdataset); result = dns_db_getoriginnode(db, &node); if (result != ISC_R_SUCCESS) goto cleanup; result = dns_db_findrdataset(db, node, version, dns_rdatatype_soa, 0, 0, &rdataset, NULL); if (result != ISC_R_SUCCESS) goto cleanup; result = dns_rdataset_first(&rdataset); if (result != ISC_R_SUCCESS) goto cleanup; dns_rdataset_current(&rdataset, &rdata); result = dns_rdata_tostruct(&rdata, &soa, NULL); RUNTIME_CHECK(result == ISC_R_SUCCESS); ttl = ISC_MIN(rdataset.ttl, soa.minimum); cleanup: if (dns_rdataset_isassociated(&rdataset)) dns_rdataset_disassociate(&rdataset); if (node != NULL) dns_db_detachnode(db, &node); return (ttl); } static isc_boolean_t dns64_aaaaok(ns_client_t *client, dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) { isc_netaddr_t netaddr; dns_dns64_t *dns64 = ISC_LIST_HEAD(client->view->dns64); unsigned int flags = 0; unsigned int i, count; isc_boolean_t *aaaaok; INSIST(client->query.dns64_aaaaok == NULL); INSIST(client->query.dns64_aaaaoklen == 0); INSIST(client->query.dns64_aaaa == NULL); INSIST(client->query.dns64_sigaaaa == NULL); if (dns64 == NULL) return (ISC_TRUE); if (RECURSIONOK(client)) flags |= DNS_DNS64_RECURSIVE; if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset)) flags |= DNS_DNS64_DNSSEC; count = dns_rdataset_count(rdataset); aaaaok = isc_mem_get(client->mctx, sizeof(isc_boolean_t) * count); isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr); if (dns_dns64_aaaaok(dns64, &netaddr, client->signer, &ns_g_server->aclenv, flags, rdataset, aaaaok, count)) { for (i = 0; i < count; i++) { if (aaaaok != NULL && !aaaaok[i]) { SAVE(client->query.dns64_aaaaok, aaaaok); client->query.dns64_aaaaoklen = count; break; } } if (aaaaok != NULL) isc_mem_put(client->mctx, aaaaok, sizeof(isc_boolean_t) * count); return (ISC_TRUE); } if (aaaaok != NULL) isc_mem_put(client->mctx, aaaaok, sizeof(isc_boolean_t) * count); return (ISC_FALSE); } /* * Look for the name and type in the redirection zone. If found update * the arguments as appropriate. Return ISC_TRUE if a update was * performed. * * Only perform the update if the client is in the allow query acl and * returning the update would not cause a DNSSEC validation failure. */ static isc_result_t redirect(ns_client_t *client, dns_name_t *name, dns_rdataset_t *rdataset, dns_dbnode_t **nodep, dns_db_t **dbp, dns_dbversion_t **versionp, dns_rdatatype_t qtype) { dns_db_t *db = NULL; dns_dbnode_t *node = NULL; dns_fixedname_t fixed; dns_name_t *found; dns_rdataset_t trdataset; isc_result_t result; dns_rdatatype_t type; dns_clientinfomethods_t cm; dns_clientinfo_t ci; ns_dbversion_t *dbversion; CTRACE(ISC_LOG_DEBUG(3), "redirect"); if (client->view->redirect == NULL) return (ISC_R_NOTFOUND); dns_fixedname_init(&fixed); found = dns_fixedname_name(&fixed); dns_rdataset_init(&trdataset); dns_clientinfomethods_init(&cm, ns_client_sourceip); dns_clientinfo_init(&ci, client, NULL); if (WANTDNSSEC(client) && dns_db_iszone(*dbp) && dns_db_issecure(*dbp)) return (ISC_R_NOTFOUND); if (WANTDNSSEC(client) && dns_rdataset_isassociated(rdataset)) { if (rdataset->trust == dns_trust_secure) return (ISC_R_NOTFOUND); if (rdataset->trust == dns_trust_ultimate && (rdataset->type == dns_rdatatype_nsec || rdataset->type == dns_rdatatype_nsec3)) return (ISC_R_NOTFOUND); if ((rdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0) { for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS; result = dns_rdataset_next(rdataset)) { dns_ncache_current(rdataset, found, &trdataset); type = trdataset.type; dns_rdataset_disassociate(&trdataset); if (type == dns_rdatatype_nsec || type == dns_rdatatype_nsec3 || type == dns_rdatatype_rrsig) return (ISC_R_NOTFOUND); } } } result = ns_client_checkaclsilent(client, NULL, dns_zone_getqueryacl(client->view->redirect), ISC_TRUE); if (result != ISC_R_SUCCESS) return (ISC_R_NOTFOUND); result = dns_zone_getdb(client->view->redirect, &db); if (result != ISC_R_SUCCESS) return (ISC_R_NOTFOUND); dbversion = query_findversion(client, db); if (dbversion == NULL) { dns_db_detach(&db); return (ISC_R_NOTFOUND); } /* * Lookup the requested data in the redirect zone. */ result = dns_db_findext(db, client->query.qname, dbversion->version, qtype, DNS_DBFIND_NOZONECUT, client->now, &node, found, &cm, &ci, &trdataset, NULL); if (result == DNS_R_NXRRSET || result == DNS_R_NCACHENXRRSET) { if (dns_rdataset_isassociated(rdataset)) dns_rdataset_disassociate(rdataset); if (dns_rdataset_isassociated(&trdataset)) dns_rdataset_disassociate(&trdataset); goto nxrrset; } else if (result != ISC_R_SUCCESS) { if (dns_rdataset_isassociated(&trdataset)) dns_rdataset_disassociate(&trdataset); if (node != NULL) dns_db_detachnode(db, &node); dns_db_detach(&db); return (ISC_R_NOTFOUND); } CTRACE(ISC_LOG_DEBUG(3), "redirect: found data: done"); dns_name_copy(found, name, NULL); if (dns_rdataset_isassociated(rdataset)) dns_rdataset_disassociate(rdataset); if (dns_rdataset_isassociated(&trdataset)) { dns_rdataset_clone(&trdataset, rdataset); dns_rdataset_disassociate(&trdataset); } nxrrset: if (*nodep != NULL) dns_db_detachnode(*dbp, nodep); dns_db_detach(dbp); dns_db_attachnode(db, node, nodep); dns_db_attach(db, dbp); dns_db_detachnode(db, &node); dns_db_detach(&db); *versionp = dbversion->version; client->query.attributes |= (NS_QUERYATTR_NOAUTHORITY | NS_QUERYATTR_NOADDITIONAL); return (result); } static isc_result_t redirect2(ns_client_t *client, dns_name_t *name, dns_rdataset_t *rdataset, dns_dbnode_t **nodep, dns_db_t **dbp, dns_dbversion_t **versionp, dns_rdatatype_t qtype, isc_boolean_t *is_zonep) { dns_db_t *db = NULL; dns_dbnode_t *node = NULL; dns_fixedname_t fixed; dns_fixedname_t fixedredirect; dns_name_t *found, *redirectname; dns_rdataset_t trdataset; isc_result_t result; dns_rdatatype_t type; dns_clientinfomethods_t cm; dns_clientinfo_t ci; dns_dbversion_t *version = NULL; dns_zone_t *zone = NULL; isc_boolean_t is_zone; unsigned int options; CTRACE(ISC_LOG_DEBUG(3), "redirect2"); if (client->view->redirectzone == NULL) return (ISC_R_NOTFOUND); if (dns_name_issubdomain(name, client->view->redirectzone)) return (ISC_R_NOTFOUND); dns_fixedname_init(&fixed); found = dns_fixedname_name(&fixed); dns_rdataset_init(&trdataset); dns_clientinfomethods_init(&cm, ns_client_sourceip); dns_clientinfo_init(&ci, client, NULL); if (WANTDNSSEC(client) && dns_db_iszone(*dbp) && dns_db_issecure(*dbp)) return (ISC_R_NOTFOUND); if (WANTDNSSEC(client) && dns_rdataset_isassociated(rdataset)) { if (rdataset->trust == dns_trust_secure) return (ISC_R_NOTFOUND); if (rdataset->trust == dns_trust_ultimate && (rdataset->type == dns_rdatatype_nsec || rdataset->type == dns_rdatatype_nsec3)) return (ISC_R_NOTFOUND); if ((rdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0) { for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS; result = dns_rdataset_next(rdataset)) { dns_ncache_current(rdataset, found, &trdataset); type = trdataset.type; dns_rdataset_disassociate(&trdataset); if (type == dns_rdatatype_nsec || type == dns_rdatatype_nsec3 || type == dns_rdatatype_rrsig) return (ISC_R_NOTFOUND); } } } dns_fixedname_init(&fixedredirect); redirectname = dns_fixedname_name(&fixedredirect); if (dns_name_countlabels(name) > 1U) { dns_name_t prefix; unsigned int labels = dns_name_countlabels(name) - 1; dns_name_init(&prefix, NULL); dns_name_getlabelsequence(name, 0, labels, &prefix); result = dns_name_concatenate(&prefix, client->view->redirectzone, redirectname, NULL); if (result != ISC_R_SUCCESS) return (ISC_R_NOTFOUND); } else dns_name_copy(redirectname, client->view->redirectzone, NULL); options = 0; result = query_getdb(client, redirectname, qtype, options, &zone, &db, &version, &is_zone); if (result != ISC_R_SUCCESS) return (ISC_R_NOTFOUND); if (zone != NULL) dns_zone_detach(&zone); /* * Lookup the requested data in the redirect zone. */ result = dns_db_findext(db, redirectname, version, qtype, 0, client->now, &node, found, &cm, &ci, &trdataset, NULL); if (result == DNS_R_NXRRSET || result == DNS_R_NCACHENXRRSET) { if (dns_rdataset_isassociated(rdataset)) dns_rdataset_disassociate(rdataset); if (dns_rdataset_isassociated(&trdataset)) dns_rdataset_disassociate(&trdataset); goto nxrrset; } else if (result == ISC_R_NOTFOUND || result == DNS_R_DELEGATION) { /* * Cleanup. */ if (dns_rdataset_isassociated(&trdataset)) dns_rdataset_disassociate(&trdataset); if (node != NULL) dns_db_detachnode(db, &node); dns_db_detach(&db); /* * Don't loop forever if the lookup failed last time. */ if (!REDIRECT(client)) { result = query_recurse(client, qtype, redirectname, NULL, NULL, ISC_TRUE); if (result == ISC_R_SUCCESS) { client->query.attributes |= NS_QUERYATTR_RECURSING; client->query.attributes |= NS_QUERYATTR_REDIRECT; return (DNS_R_CONTINUE); } } return (ISC_R_NOTFOUND); } else if (result != ISC_R_SUCCESS) { if (dns_rdataset_isassociated(&trdataset)) dns_rdataset_disassociate(&trdataset); if (node != NULL) dns_db_detachnode(db, &node); dns_db_detach(&db); return (ISC_R_NOTFOUND); } CTRACE(ISC_LOG_DEBUG(3), "redirect2: found data: done"); /* * Adjust the found name to not include the redirectzone suffix. */ dns_name_split(found, dns_name_countlabels(client->view->redirectzone), found, NULL); /* * Make the name absolute. */ result = dns_name_concatenate(found, dns_rootname, found, NULL); RUNTIME_CHECK(result == ISC_R_SUCCESS); dns_name_copy(found, name, NULL); if (dns_rdataset_isassociated(rdataset)) dns_rdataset_disassociate(rdataset); if (dns_rdataset_isassociated(&trdataset)) { dns_rdataset_clone(&trdataset, rdataset); dns_rdataset_disassociate(&trdataset); } nxrrset: if (*nodep != NULL) dns_db_detachnode(*dbp, nodep); dns_db_detach(dbp); dns_db_attachnode(db, node, nodep); dns_db_attach(db, dbp); dns_db_detachnode(db, &node); dns_db_detach(&db); *is_zonep = is_zone; *versionp = version; client->query.attributes |= (NS_QUERYATTR_NOAUTHORITY | NS_QUERYATTR_NOADDITIONAL); return (result); } /* * Do the bulk of query processing for the current query of 'client'. * If 'event' is non-NULL, we are returning from recursion and 'qtype' * is ignored. Otherwise, 'qtype' is the query type. */ static isc_result_t query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) { dns_db_t *db, *zdb; dns_dbnode_t *node; dns_rdatatype_t type = qtype; dns_name_t *fname, *zfname, *tname, *prefix; dns_rdataset_t *rdataset, *trdataset; dns_rdataset_t *sigrdataset, *zrdataset, *zsigrdataset; dns_rdataset_t **sigrdatasetp; dns_rdata_t rdata = DNS_RDATA_INIT; dns_rdatasetiter_t *rdsiter; isc_boolean_t want_restart, is_zone, need_wildcardproof; isc_boolean_t is_staticstub_zone; isc_boolean_t authoritative = ISC_FALSE; isc_boolean_t answer_has_ns = ISC_FALSE; unsigned int n, nlabels; dns_namereln_t namereln; int order; isc_buffer_t *dbuf; isc_buffer_t b; isc_result_t result, eresult, tresult; dns_fixedname_t fixed; dns_fixedname_t wildcardname; dns_dbversion_t *version, *zversion; dns_zone_t *zone; dns_rdata_cname_t cname; dns_rdata_dname_t dname; unsigned int options; isc_boolean_t empty_wild; dns_rdataset_t *noqname; dns_rpz_st_t *rpz_st; isc_boolean_t resuming; int line = -1; isc_boolean_t dns64_exclude, dns64, rpz; isc_boolean_t nxrewrite = ISC_FALSE; isc_boolean_t redirected = ISC_FALSE; dns_clientinfomethods_t cm; dns_clientinfo_t ci; char errmsg[256]; isc_boolean_t associated; dns_section_t section; dns_ttl_t ttl; isc_boolean_t failcache; isc_uint32_t flags; #ifdef WANT_QUERYTRACE char mbuf[BUFSIZ]; char qbuf[DNS_NAME_FORMATSIZE]; char tbuf[DNS_RDATATYPE_FORMATSIZE]; #endif dns_name_t *rpzqname; CTRACE(ISC_LOG_DEBUG(3), "query_find"); /* * One-time initialization. * * It's especially important to initialize anything that the cleanup * code might cleanup. */ eresult = ISC_R_SUCCESS; fname = NULL; zfname = NULL; rdataset = NULL; zrdataset = NULL; sigrdataset = NULL; zsigrdataset = NULL; zversion = NULL; node = NULL; db = NULL; zdb = NULL; version = NULL; zone = NULL; need_wildcardproof = ISC_FALSE; empty_wild = ISC_FALSE; dns64_exclude = dns64 = rpz = ISC_FALSE; options = 0; resuming = ISC_FALSE; is_zone = ISC_FALSE; is_staticstub_zone = ISC_FALSE; dns_clientinfomethods_init(&cm, ns_client_sourceip); dns_clientinfo_init(&ci, client, NULL); #ifdef WANT_QUERYTRACE if (client->query.origqname != NULL) dns_name_format(client->query.origqname, qbuf, sizeof(qbuf)); else snprintf(qbuf, sizeof(qbuf), ""); snprintf(mbuf, sizeof(mbuf) - 1, "client attr:0x%x, query attr:0x%X, restarts:%d, " "origqname:%s, timer:%d, authdb:%d, referral:%d", client->attributes, client->query.attributes, client->query.restarts, qbuf, (int) client->query.timerset, (int) client->query.authdbset, (int) client->query.isreferral); CTRACE(ISC_LOG_DEBUG(3), mbuf); #endif if (event != NULL) { /* * We're returning from recursion. Restore the query context * and resume. */ want_restart = ISC_FALSE; rpz_st = client->query.rpz_st; if (rpz_st != NULL && (rpz_st->state & DNS_RPZ_RECURSING) != 0) { CTRACE(ISC_LOG_DEBUG(3), "resume from RPZ recursion"); #ifdef WANT_QUERYTRACE { char pbuf[DNS_NAME_FORMATSIZE] = ""; char fbuf[DNS_NAME_FORMATSIZE] = ""; if (rpz_st->r_name != NULL) dns_name_format(rpz_st->r_name, qbuf, sizeof(qbuf)); else snprintf(qbuf, sizeof(qbuf), ""); if (rpz_st->p_name != NULL) dns_name_format(rpz_st->p_name, pbuf, sizeof(pbuf)); if (rpz_st->fname != NULL) dns_name_format(rpz_st->fname, fbuf, sizeof(fbuf)); snprintf(mbuf, sizeof(mbuf) - 1, "rpz rname:%s, pname:%s, fname:%s", qbuf, pbuf, fbuf); CTRACE(ISC_LOG_DEBUG(3), mbuf); } #endif is_zone = rpz_st->q.is_zone; authoritative = rpz_st->q.authoritative; RESTORE(zone, rpz_st->q.zone); RESTORE(node, rpz_st->q.node); RESTORE(db, rpz_st->q.db); RESTORE(rdataset, rpz_st->q.rdataset); RESTORE(sigrdataset, rpz_st->q.sigrdataset); qtype = rpz_st->q.qtype; if (event->node != NULL) dns_db_detachnode(event->db, &event->node); SAVE(rpz_st->r.db, event->db); rpz_st->r.r_type = event->qtype; SAVE(rpz_st->r.r_rdataset, event->rdataset); query_putrdataset(client, &event->sigrdataset); } else if (REDIRECT(client)) { /* * Restore saved state. */ CTRACE(ISC_LOG_DEBUG(3), "resume from redirect recursion"); #ifdef WANT_QUERYTRACE dns_name_format(client->query.redirect.fname, qbuf, sizeof(qbuf)); dns_rdatatype_format(client->query.redirect.qtype, tbuf, sizeof(tbuf)); snprintf(mbuf, sizeof(mbuf) - 1, "redirect fname:%s, qtype:%s, auth:%d", qbuf, tbuf, client->query.redirect.authoritative); CTRACE(ISC_LOG_DEBUG(3), mbuf); #endif qtype = client->query.redirect.qtype; INSIST(client->query.redirect.rdataset != NULL); RESTORE(rdataset, client->query.redirect.rdataset); RESTORE(sigrdataset, client->query.redirect.sigrdataset); RESTORE(db, client->query.redirect.db); RESTORE(node, client->query.redirect.node); RESTORE(zone, client->query.redirect.zone); authoritative = client->query.redirect.authoritative; is_zone = client->query.redirect.is_zone; /* * Free resources used while recursing. */ query_putrdataset(client, &event->rdataset); query_putrdataset(client, &event->sigrdataset); if (event->node != NULL) dns_db_detachnode(event->db, &event->node); if (event->db != NULL) dns_db_detach(&event->db); } else { CTRACE(ISC_LOG_DEBUG(3), "resume from normal recursion"); authoritative = ISC_FALSE; qtype = event->qtype; SAVE(db, event->db); SAVE(node, event->node); SAVE(rdataset, event->rdataset); SAVE(sigrdataset, event->sigrdataset); } INSIST(rdataset != NULL); if (qtype == dns_rdatatype_rrsig || qtype == dns_rdatatype_sig) type = dns_rdatatype_any; else type = qtype; if (DNS64(client)) { client->query.attributes &= ~NS_QUERYATTR_DNS64; dns64 = ISC_TRUE; } if (DNS64EXCLUDE(client)) { client->query.attributes &= ~NS_QUERYATTR_DNS64EXCLUDE; dns64_exclude = ISC_TRUE; } if (rpz_st != NULL && (rpz_st->state & DNS_RPZ_RECURSING) != 0) { /* * Has response policy changed out from under us? */ if (rpz_st->rpz_ver != client->view->rpzs->rpz_ver) { ns_client_log(client, NS_LOGCATEGORY_CLIENT, NS_LOGMODULE_QUERY, DNS_RPZ_INFO_LEVEL, "query_find: RPZ settings " "out of date " "(rpz_ver %d, expected %d)", client->view->rpzs->rpz_ver, rpz_st->rpz_ver); QUERY_ERROR(DNS_R_SERVFAIL); goto cleanup; } } /* * We'll need some resources... */ dbuf = query_getnamebuf(client); if (dbuf == NULL) { CTRACE(ISC_LOG_ERROR, "query_find: query_getnamebuf failed (1)"); QUERY_ERROR(DNS_R_SERVFAIL); goto cleanup; } fname = query_newname(client, dbuf, &b); if (fname == NULL) { CTRACE(ISC_LOG_ERROR, "query_find: query_newname failed (1)"); QUERY_ERROR(DNS_R_SERVFAIL); goto cleanup; } if (rpz_st != NULL && (rpz_st->state & DNS_RPZ_RECURSING) != 0) { tname = rpz_st->fname; } else if (REDIRECT(client)) { tname = client->query.redirect.fname; } else { tname = dns_fixedname_name(&event->foundname); } result = dns_name_copy(tname, fname, NULL); if (result != ISC_R_SUCCESS) { CTRACE(ISC_LOG_ERROR, "query_find: dns_name_copy failed"); QUERY_ERROR(DNS_R_SERVFAIL); goto cleanup; } if (rpz_st != NULL && (rpz_st->state & DNS_RPZ_RECURSING) != 0) { rpz_st->r.r_result = event->result; result = rpz_st->q.result; free_devent(client, ISC_EVENT_PTR(&event), &event); } else if (REDIRECT(client)) { result = client->query.redirect.result; is_zone = client->query.redirect.is_zone; } else { result = event->result; } resuming = ISC_TRUE; goto resume; } /* * Not returning from recursion. * * First, check for a recent match in the view's SERVFAIL cache. * If we find one, and it was from a query with CD=1, *or* * if the current query has CD=0, then we can just return * SERVFAIL now. */ if (RECURSIONOK(client)) { flags = 0; #ifdef ENABLE_AFL if (ns_g_fuzz_type == ns_fuzz_resolver) { failcache = ISC_FALSE; } else { failcache = dns_badcache_find(client->view->failcache, client->query.qname, qtype, &flags, &client->tnow); } #else failcache = dns_badcache_find(client->view->failcache, client->query.qname, qtype, &flags, &client->tnow); #endif if (failcache && (((flags & NS_FAILCACHE_CD) != 0) || ((client->message->flags & DNS_MESSAGEFLAG_CD) == 0))) { if (isc_log_wouldlog(ns_g_lctx, ISC_LOG_DEBUG(1))) { char namebuf[DNS_NAME_FORMATSIZE]; char typename[DNS_RDATATYPE_FORMATSIZE]; dns_name_format(client->query.qname, namebuf, sizeof(namebuf)); dns_rdatatype_format(qtype, typename, sizeof(typename)); ns_client_log(client, NS_LOGCATEGORY_CLIENT, NS_LOGMODULE_QUERY, ISC_LOG_DEBUG(1), "servfail cache hit %s/%s (%s)", namebuf, typename, ((flags & NS_FAILCACHE_CD) != 0) ? "CD=1" : "CD=0"); } client->attributes |= NS_CLIENTATTR_NOSETFC; QUERY_ERROR(DNS_R_SERVFAIL); goto cleanup; } } /* * If it's a SIG query, we'll iterate the node. */ if (qtype == dns_rdatatype_rrsig || qtype == dns_rdatatype_sig) type = dns_rdatatype_any; else type = qtype; restart: CTRACE(ISC_LOG_DEBUG(3), "query_find: restart"); want_restart = ISC_FALSE; authoritative = ISC_FALSE; version = NULL; zversion = NULL; need_wildcardproof = ISC_FALSE; rpz = ISC_FALSE; if (client->view->checknames && !dns_rdata_checkowner(client->query.qname, client->message->rdclass, qtype, ISC_FALSE)) { char namebuf[DNS_NAME_FORMATSIZE]; char typename[DNS_RDATATYPE_FORMATSIZE]; char classname[DNS_RDATACLASS_FORMATSIZE]; dns_name_format(client->query.qname, namebuf, sizeof(namebuf)); dns_rdatatype_format(qtype, typename, sizeof(typename)); dns_rdataclass_format(client->message->rdclass, classname, sizeof(classname)); ns_client_log(client, DNS_LOGCATEGORY_SECURITY, NS_LOGMODULE_QUERY, ISC_LOG_ERROR, "check-names failure %s/%s/%s", namebuf, typename, classname); QUERY_ERROR(DNS_R_REFUSED); goto cleanup; } /* * First we must find the right database. */ options &= DNS_GETDB_NOLOG; /* Preserve DNS_GETDB_NOLOG. */ if (dns_rdatatype_atparent(qtype) && !dns_name_equal(client->query.qname, dns_rootname)) options |= DNS_GETDB_NOEXACT; result = query_getdb(client, client->query.qname, qtype, options, &zone, &db, &version, &is_zone); if (ISC_UNLIKELY((result != ISC_R_SUCCESS || !is_zone) && qtype == dns_rdatatype_ds && !RECURSIONOK(client) && (options & DNS_GETDB_NOEXACT) != 0)) { /* * If the query type is DS, look to see if we are * authoritative for the child zone. */ dns_db_t *tdb = NULL; dns_zone_t *tzone = NULL; dns_dbversion_t *tversion = NULL; tresult = query_getzonedb(client, client->query.qname, qtype, DNS_GETDB_PARTIAL, &tzone, &tdb, &tversion); if (tresult == ISC_R_SUCCESS) { options &= ~DNS_GETDB_NOEXACT; query_putrdataset(client, &rdataset); if (db != NULL) dns_db_detach(&db); if (zone != NULL) dns_zone_detach(&zone); version = NULL; RESTORE(version, tversion); RESTORE(db, tdb); RESTORE(zone, tzone); is_zone = ISC_TRUE; result = ISC_R_SUCCESS; } else { if (tdb != NULL) dns_db_detach(&tdb); if (tzone != NULL) dns_zone_detach(&tzone); } } if (result != ISC_R_SUCCESS) { if (result == DNS_R_REFUSED) { if (WANTRECURSION(client)) { inc_stats(client, dns_nsstatscounter_recurserej); } else inc_stats(client, dns_nsstatscounter_authrej); if (!PARTIALANSWER(client)) QUERY_ERROR(DNS_R_REFUSED); } else { CTRACE(ISC_LOG_ERROR, "query_find: query_getdb failed"); QUERY_ERROR(DNS_R_SERVFAIL); } goto cleanup; } is_staticstub_zone = ISC_FALSE; if (is_zone) { authoritative = ISC_TRUE; if (zone != NULL && dns_zone_gettype(zone) == dns_zone_staticstub) is_staticstub_zone = ISC_TRUE; } if (event == NULL && client->query.restarts == 0) { if (is_zone) { if (zone != NULL) { /* * if is_zone = true, zone = NULL then this is * a DLZ zone. Don't attempt to attach zone. */ dns_zone_attach(zone, &client->query.authzone); } dns_db_attach(db, &client->query.authdb); } client->query.authdbset = ISC_TRUE; /* Track TCP vs UDP stats per zone */ if (TCP(client)) inc_stats(client, dns_nsstatscounter_tcp); else inc_stats(client, dns_nsstatscounter_udp); } db_find: CTRACE(ISC_LOG_DEBUG(3), "query_find: db_find"); /* * We'll need some resources... */ dbuf = query_getnamebuf(client); if (ISC_UNLIKELY(dbuf == NULL)) { CTRACE(ISC_LOG_ERROR, "query_find: query_getnamebuf failed (2)"); QUERY_ERROR(DNS_R_SERVFAIL); goto cleanup; } fname = query_newname(client, dbuf, &b); rdataset = query_newrdataset(client); if (ISC_UNLIKELY(fname == NULL || rdataset == NULL)) { CTRACE(ISC_LOG_ERROR, "query_find: query_newname failed (2)"); QUERY_ERROR(DNS_R_SERVFAIL); goto cleanup; } if (WANTDNSSEC(client) && (!is_zone || dns_db_issecure(db))) { sigrdataset = query_newrdataset(client); if (sigrdataset == NULL) { CTRACE(ISC_LOG_ERROR, "query_find: query_newrdataset failed (2)"); QUERY_ERROR(DNS_R_SERVFAIL); goto cleanup; } } /* * Now look for an answer in the database. If this is a dns64 * AAAA lookup on a rpz database adjust the qname. */ if (dns64 && rpz) rpzqname = client->query.rpz_st->p_name; else rpzqname = client->query.qname; result = dns_db_findext(db, rpzqname, version, type, client->query.dboptions, client->now, &node, fname, &cm, &ci, rdataset, sigrdataset); /* * Fixup fname and sigrdataset. */ if (dns64 && rpz) { isc_result_t rresult; rresult = dns_name_copy(client->query.qname, fname, NULL); RUNTIME_CHECK(rresult == ISC_R_SUCCESS); if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset)) dns_rdataset_disassociate(sigrdataset); } if (!is_zone) dns_cache_updatestats(client->view->cache, result); resume: CTRACE(ISC_LOG_DEBUG(3), "query_find: resume"); /* * Rate limit these responses to this client. * Do not delay counting and handling obvious referrals, * since those won't come here again. * Delay handling delegations for which we are certain to recurse and * return here (DNS_R_DELEGATION, not a child of one of our * own zones, and recursion enabled) * Don't mess with responses rewritten by RPZ * Count each response at most once. */ if (client->view->rrl != NULL && !HAVECOOKIE(client) && ((fname != NULL && dns_name_isabsolute(fname)) || (result == ISC_R_NOTFOUND && !RECURSIONOK(client))) && !(result == DNS_R_DELEGATION && !is_zone && RECURSIONOK(client)) && (client->query.rpz_st == NULL || (client->query.rpz_st->state & DNS_RPZ_REWRITTEN) == 0)&& (client->query.attributes & NS_QUERYATTR_RRL_CHECKED) == 0) { dns_rdataset_t nc_rdataset; isc_boolean_t wouldlog; char log_buf[DNS_RRL_LOG_BUF_LEN]; isc_result_t nc_result, resp_result; dns_rrl_result_t rrl_result; client->query.attributes |= NS_QUERYATTR_RRL_CHECKED; wouldlog = isc_log_wouldlog(ns_g_lctx, DNS_RRL_LOG_DROP); tname = fname; if (result == DNS_R_NXDOMAIN) { /* * Use the database origin name to rate limit NXDOMAIN */ if (db != NULL) tname = dns_db_origin(db); resp_result = result; } else if (result == DNS_R_NCACHENXDOMAIN && rdataset != NULL && dns_rdataset_isassociated(rdataset) && (rdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0) { /* * Try to use owner name in the negative cache SOA. */ dns_fixedname_init(&fixed); dns_rdataset_init(&nc_rdataset); for (nc_result = dns_rdataset_first(rdataset); nc_result == ISC_R_SUCCESS; nc_result = dns_rdataset_next(rdataset)) { dns_ncache_current(rdataset, dns_fixedname_name(&fixed), &nc_rdataset); if (nc_rdataset.type == dns_rdatatype_soa) { dns_rdataset_disassociate(&nc_rdataset); tname = dns_fixedname_name(&fixed); break; } dns_rdataset_disassociate(&nc_rdataset); } resp_result = DNS_R_NXDOMAIN; } else if (result == DNS_R_NXRRSET || result == DNS_R_EMPTYNAME) { resp_result = DNS_R_NXRRSET; } else if (result == DNS_R_DELEGATION) { resp_result = result; } else if (result == ISC_R_NOTFOUND) { /* * Handle referral to ".", including when recursion * is off or not requested and the hints have not * been loaded or we have "additional-from-cache no". */ tname = dns_rootname; resp_result = DNS_R_DELEGATION; } else { resp_result = ISC_R_SUCCESS; } rrl_result = dns_rrl(client->view, &client->peeraddr, TCP(client), client->message->rdclass, qtype, tname, resp_result, client->now, wouldlog, log_buf, sizeof(log_buf)); if (rrl_result != DNS_RRL_RESULT_OK) { /* * Log dropped or slipped responses in the query * category so that requests are not silently lost. * Starts of rate-limited bursts are logged in * DNS_LOGCATEGORY_RRL. * * Dropped responses are counted with dropped queries * in QryDropped while slipped responses are counted * with other truncated responses in RespTruncated. */ if (wouldlog) { ns_client_log(client, DNS_LOGCATEGORY_RRL, NS_LOGMODULE_QUERY, DNS_RRL_LOG_DROP, "%s", log_buf); } if (!client->view->rrl->log_only) { if (rrl_result == DNS_RRL_RESULT_DROP) { /* * These will also be counted in * dns_nsstatscounter_dropped */ inc_stats(client, dns_nsstatscounter_ratedropped); QUERY_ERROR(DNS_R_DROP); } else { /* * These will also be counted in * dns_nsstatscounter_truncatedresp */ inc_stats(client, dns_nsstatscounter_rateslipped); if (WANTCOOKIE(client)) { client->message->flags &= ~DNS_MESSAGEFLAG_AA; client->message->flags &= ~DNS_MESSAGEFLAG_AD; client->message->rcode = dns_rcode_badcookie; } else { client->message->flags |= DNS_MESSAGEFLAG_TC; if (resp_result == DNS_R_NXDOMAIN) client->message->rcode = dns_rcode_nxdomain; } } goto cleanup; } } } else if (!TCP(client) && client->view->requireservercookie && WANTCOOKIE(client) && !HAVECOOKIE(client)) { client->message->flags &= ~DNS_MESSAGEFLAG_AA; client->message->flags &= ~DNS_MESSAGEFLAG_AD; client->message->rcode = dns_rcode_badcookie; goto cleanup; } if (!RECURSING(client) && !dns_name_equal(client->query.qname, dns_rootname)) { isc_result_t rresult; rresult = rpz_rewrite(client, qtype, result, resuming, rdataset, sigrdataset); rpz_st = client->query.rpz_st; switch (rresult) { case ISC_R_SUCCESS: break; case DNS_R_DISALLOWED: goto norpz; case DNS_R_DELEGATION: /* * recursing for NS names or addresses, * so save the main query state */ rpz_st->q.qtype = qtype; rpz_st->q.is_zone = is_zone; rpz_st->q.authoritative = authoritative; SAVE(rpz_st->q.zone, zone); SAVE(rpz_st->q.db, db); SAVE(rpz_st->q.node, node); SAVE(rpz_st->q.rdataset, rdataset); SAVE(rpz_st->q.sigrdataset, sigrdataset); dns_name_copy(fname, rpz_st->fname, NULL); rpz_st->q.result = result; client->query.attributes |= NS_QUERYATTR_RECURSING; goto cleanup; default: RECURSE_ERROR(rresult); goto cleanup; } if (rpz_st->m.policy != DNS_RPZ_POLICY_MISS) rpz_st->state |= DNS_RPZ_REWRITTEN; if (rpz_st->m.policy != DNS_RPZ_POLICY_MISS && rpz_st->m.policy != DNS_RPZ_POLICY_PASSTHRU && (rpz_st->m.policy != DNS_RPZ_POLICY_TCP_ONLY || !TCP(client)) && rpz_st->m.policy != DNS_RPZ_POLICY_ERROR) { /* * We got a hit and are going to answer with our * fiction. Ensure that we answer with the name * we looked up even if we were stopped short * in recursion or for a deferral. */ rresult = dns_name_copy(client->query.qname, fname, NULL); RUNTIME_CHECK(rresult == ISC_R_SUCCESS); rpz_clean(&zone, &db, &node, NULL); if (rpz_st->m.rdataset != NULL) { query_putrdataset(client, &rdataset); RESTORE(rdataset, rpz_st->m.rdataset); } else if (rdataset != NULL && dns_rdataset_isassociated(rdataset)) { dns_rdataset_disassociate(rdataset); } version = NULL; RESTORE(node, rpz_st->m.node); RESTORE(db, rpz_st->m.db); RESTORE(version, rpz_st->m.version); RESTORE(zone, rpz_st->m.zone); switch (rpz_st->m.policy) { case DNS_RPZ_POLICY_TCP_ONLY: client->message->flags |= DNS_MESSAGEFLAG_TC; if (result == DNS_R_NXDOMAIN || result == DNS_R_NCACHENXDOMAIN) client->message->rcode = dns_rcode_nxdomain; rpz_log_rewrite(client, ISC_FALSE, rpz_st->m.policy, rpz_st->m.type, zone, rpz_st->p_name, NULL, rpz_st->m.rpz->num); goto cleanup; case DNS_RPZ_POLICY_DROP: QUERY_ERROR(DNS_R_DROP); rpz_log_rewrite(client, ISC_FALSE, rpz_st->m.policy, rpz_st->m.type, zone, rpz_st->p_name, NULL, rpz_st->m.rpz->num); goto cleanup; case DNS_RPZ_POLICY_NXDOMAIN: result = DNS_R_NXDOMAIN; nxrewrite = ISC_TRUE; rpz = ISC_TRUE; break; case DNS_RPZ_POLICY_NODATA: result = DNS_R_NXRRSET; nxrewrite = ISC_TRUE; rpz = ISC_TRUE; break; case DNS_RPZ_POLICY_RECORD: result = rpz_st->m.result; if (qtype == dns_rdatatype_any && result != DNS_R_CNAME) { /* * We will add all of the rdatasets of * the node by iterating later, * and set the TTL then. */ if (dns_rdataset_isassociated(rdataset)) dns_rdataset_disassociate(rdataset); } else { /* * We will add this rdataset. */ rdataset->ttl = ISC_MIN(rdataset->ttl, rpz_st->m.ttl); } rpz = ISC_TRUE; break; case DNS_RPZ_POLICY_WILDCNAME: result = dns_rdataset_first(rdataset); RUNTIME_CHECK(result == ISC_R_SUCCESS); dns_rdataset_current(rdataset, &rdata); result = dns_rdata_tostruct(&rdata, &cname, NULL); RUNTIME_CHECK(result == ISC_R_SUCCESS); dns_rdata_reset(&rdata); result = rpz_add_cname(client, rpz_st, &cname.cname, fname, dbuf); if (result != ISC_R_SUCCESS) goto cleanup; fname = NULL; want_restart = ISC_TRUE; goto cleanup; case DNS_RPZ_POLICY_CNAME: /* * Add overridding CNAME from a named.conf * response-policy statement */ result = rpz_add_cname(client, rpz_st, &rpz_st->m.rpz->cname, fname, dbuf); if (result != ISC_R_SUCCESS) goto cleanup; fname = NULL; want_restart = ISC_TRUE; goto cleanup; default: INSIST(0); } /* * Turn off DNSSEC because the results of a * response policy zone cannot verify. */ client->attributes &= ~(NS_CLIENTATTR_WANTDNSSEC | NS_CLIENTATTR_WANTAD); client->message->flags &= ~DNS_MESSAGEFLAG_AD; query_putrdataset(client, &sigrdataset); is_zone = ISC_TRUE; rpz_log_rewrite(client, ISC_FALSE, rpz_st->m.policy, rpz_st->m.type, zone, rpz_st->p_name, NULL, rpz_st->m.rpz->num); } } norpz: switch (result) { case ISC_R_SUCCESS: /* * This case is handled in the main line below. */ break; case DNS_R_GLUE: case DNS_R_ZONECUT: /* * These cases are handled in the main line below. */ INSIST(is_zone); authoritative = ISC_FALSE; break; case ISC_R_NOTFOUND: /* * The cache doesn't even have the root NS. Get them from * the hints DB. */ INSIST(!is_zone); if (db != NULL) dns_db_detach(&db); if (client->view->hints == NULL) { /* We have no hints. */ result = ISC_R_FAILURE; } else { dns_db_attach(client->view->hints, &db); result = dns_db_findext(db, dns_rootname, NULL, dns_rdatatype_ns, 0, client->now, &node, fname, &cm, &ci, rdataset, sigrdataset); } if (result != ISC_R_SUCCESS) { /* * Nonsensical root hints may require cleanup. */ if (dns_rdataset_isassociated(rdataset)) dns_rdataset_disassociate(rdataset); if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset)) dns_rdataset_disassociate(sigrdataset); if (node != NULL) dns_db_detachnode(db, &node); /* * We don't have any root server hints, but * we may have working forwarders, so try to * recurse anyway. */ if (RECURSIONOK(client)) { INSIST(!REDIRECT(client)); result = query_recurse(client, qtype, client->query.qname, NULL, NULL, resuming); if (result == ISC_R_SUCCESS) { client->query.attributes |= NS_QUERYATTR_RECURSING; if (dns64) client->query.attributes |= NS_QUERYATTR_DNS64; if (dns64_exclude) client->query.attributes |= NS_QUERYATTR_DNS64EXCLUDE; } else RECURSE_ERROR(result); goto cleanup; } else { /* Unable to give root server referral. */ CTRACE(ISC_LOG_ERROR, "unable to give root server referral"); QUERY_ERROR(DNS_R_SERVFAIL); goto cleanup; } } /* * XXXRTH We should trigger root server priming here. */ /* FALLTHROUGH */ case DNS_R_DELEGATION: authoritative = ISC_FALSE; if (is_zone) { /* * Look to see if we are authoritative for the * child zone if the query type is DS. */ if (!RECURSIONOK(client) && (options & DNS_GETDB_NOEXACT) != 0 && qtype == dns_rdatatype_ds) { dns_db_t *tdb = NULL; dns_zone_t *tzone = NULL; dns_dbversion_t *tversion = NULL; result = query_getzonedb(client, client->query.qname, qtype, DNS_GETDB_PARTIAL, &tzone, &tdb, &tversion); if (result == ISC_R_SUCCESS) { options &= ~DNS_GETDB_NOEXACT; query_putrdataset(client, &rdataset); if (sigrdataset != NULL) query_putrdataset(client, &sigrdataset); if (fname != NULL) query_releasename(client, &fname); if (node != NULL) dns_db_detachnode(db, &node); if (db != NULL) dns_db_detach(&db); if (zone != NULL) dns_zone_detach(&zone); version = NULL; RESTORE(version, tversion); RESTORE(db, tdb); RESTORE(zone, tzone); authoritative = ISC_TRUE; goto db_find; } if (tdb != NULL) dns_db_detach(&tdb); if (tzone != NULL) dns_zone_detach(&tzone); } /* * We're authoritative for an ancestor of QNAME. */ if (!USECACHE(client) || !RECURSIONOK(client)) { isc_boolean_t detach = ISC_FALSE; dns_fixedname_init(&fixed); dns_name_copy(fname, dns_fixedname_name(&fixed), NULL); /* * If we don't have a cache, this is the best * answer. * * If the client is making a nonrecursive * query we always give out the authoritative * delegation. This way even if we get * junk in our cache, we won't fail in our * role as the delegating authority if another * nameserver asks us about a delegated * subzone. * * We enable the retrieval of glue for this * database by setting client->query.gluedb. */ if (db != NULL && client->query.gluedb == NULL) { dns_db_attach(db, &client->query.gluedb); detach = ISC_TRUE; } client->query.isreferral = ISC_TRUE; /* * We must ensure NOADDITIONAL is off, * because the generation of * additional data is required in * delegations. */ client->query.attributes &= ~NS_QUERYATTR_NOADDITIONAL; if (sigrdataset != NULL) sigrdatasetp = &sigrdataset; else sigrdatasetp = NULL; query_addrrset(client, &fname, &rdataset, sigrdatasetp, dbuf, DNS_SECTION_AUTHORITY); if (detach) { dns_db_detach(&client->query.gluedb); } if (WANTDNSSEC(client)) query_addds(client, db, node, version, dns_fixedname_name(&fixed)); } else { /* * We might have a better answer or delegation * in the cache. We'll remember the current * values of fname, rdataset, and sigrdataset. * We'll then go looking for QNAME in the * cache. If we find something better, we'll * use it instead. */ query_keepname(client, fname, dbuf); dns_db_detachnode(db, &node); SAVE(zdb, db); SAVE(zfname, fname); SAVE(zversion, version); SAVE(zrdataset, rdataset); SAVE(zsigrdataset, sigrdataset); dns_db_attach(client->view->cachedb, &db); is_zone = ISC_FALSE; goto db_find; } } else { if (zfname != NULL && (!dns_name_issubdomain(fname, zfname) || (is_staticstub_zone && dns_name_equal(fname, zfname)))) { /* * In the following cases use "authoritative" * data instead of the cache delegation: * 1. We've already got a delegation from * authoritative data, and it is better * than what we found in the cache. * 2. The query name matches the origin name * of a static-stub zone. This needs to be * considered for the case where the NS of * the static-stub zone and the cached NS * are different. We still need to contact * the nameservers configured in the * static-stub zone. */ query_releasename(client, &fname); /* * We've already done query_keepname() on * zfname, so we must set dbuf to NULL to * prevent query_addrrset() from trying to * call query_keepname() again. */ dbuf = NULL; query_putrdataset(client, &rdataset); if (sigrdataset != NULL) query_putrdataset(client, &sigrdataset); version = NULL; RESTORE(fname, zfname); RESTORE(version, zversion); RESTORE(rdataset, zrdataset); RESTORE(sigrdataset, zsigrdataset); /* * We don't clean up zdb here because we * may still need it. It will get cleaned * up by the main cleanup code. */ } if (RECURSIONOK(client)) { /* * Recurse! */ INSIST(!REDIRECT(client)); if (dns_rdatatype_atparent(type)) result = query_recurse(client, qtype, client->query.qname, NULL, NULL, resuming); else if (dns64) result = query_recurse(client, dns_rdatatype_a, client->query.qname, NULL, NULL, resuming); else result = query_recurse(client, qtype, client->query.qname, fname, rdataset, resuming); if (result == ISC_R_SUCCESS) { client->query.attributes |= NS_QUERYATTR_RECURSING; if (dns64) client->query.attributes |= NS_QUERYATTR_DNS64; if (dns64_exclude) client->query.attributes |= NS_QUERYATTR_DNS64EXCLUDE; } else if (result == DNS_R_DUPLICATE || result == DNS_R_DROP) QUERY_ERROR(result); else RECURSE_ERROR(result); } else { isc_boolean_t detach = ISC_FALSE; dns_fixedname_init(&fixed); dns_name_copy(fname, dns_fixedname_name(&fixed), NULL); /* * This is the best answer. */ client->query.attributes |= NS_QUERYATTR_CACHEGLUEOK; client->query.isreferral = ISC_TRUE; if (zdb != NULL && client->query.gluedb == NULL) { dns_db_attach(zdb, &client->query.gluedb); detach = ISC_TRUE; } /* * We must ensure NOADDITIONAL is off, * because the generation of * additional data is required in * delegations. */ client->query.attributes &= ~NS_QUERYATTR_NOADDITIONAL; if (sigrdataset != NULL) sigrdatasetp = &sigrdataset; else sigrdatasetp = NULL; query_addrrset(client, &fname, &rdataset, sigrdatasetp, dbuf, DNS_SECTION_AUTHORITY); client->query.attributes &= ~NS_QUERYATTR_CACHEGLUEOK; if (detach) { dns_db_detach(&client->query.gluedb); } if (WANTDNSSEC(client)) query_addds(client, db, node, version, dns_fixedname_name(&fixed)); } } goto cleanup; case DNS_R_EMPTYNAME: case DNS_R_NXRRSET: iszone_nxrrset: INSIST(is_zone); #ifdef dns64_bis_return_excluded_addresses if (dns64) #else if (dns64 && !dns64_exclude) #endif { /* * Restore the answers from the previous AAAA lookup. */ if (rdataset != NULL) query_putrdataset(client, &rdataset); if (sigrdataset != NULL) query_putrdataset(client, &sigrdataset); RESTORE(rdataset, client->query.dns64_aaaa); RESTORE(sigrdataset, client->query.dns64_sigaaaa); if (fname == NULL) { dbuf = query_getnamebuf(client); if (dbuf == NULL) { CTRACE(ISC_LOG_ERROR, "query_find: " "query_getnamebuf failed (3)"); QUERY_ERROR(DNS_R_SERVFAIL); goto cleanup; } fname = query_newname(client, dbuf, &b); if (fname == NULL) { CTRACE(ISC_LOG_ERROR, "query_find: " "query_newname failed (3)"); QUERY_ERROR(DNS_R_SERVFAIL); goto cleanup; } } dns_name_copy(client->query.qname, fname, NULL); dns64 = ISC_FALSE; #ifdef dns64_bis_return_excluded_addresses /* * Resume the diverted processing of the AAAA response? */ if (dns64_excluded) break; #endif } else if (result == DNS_R_NXRRSET && !ISC_LIST_EMPTY(client->view->dns64) && client->message->rdclass == dns_rdataclass_in && qtype == dns_rdatatype_aaaa) { /* * Look to see if there are A records for this * name. */ SAVE(client->query.dns64_aaaa, rdataset); SAVE(client->query.dns64_sigaaaa, sigrdataset); client->query.dns64_ttl = dns64_ttl(db, version); query_releasename(client, &fname); dns_db_detachnode(db, &node); type = qtype = dns_rdatatype_a; dns64 = ISC_TRUE; goto db_find; } /* * Look for a NSEC3 record if we don't have a NSEC record. */ nxrrset_rrsig: if (redirected) goto cleanup; if (!dns_rdataset_isassociated(rdataset) && WANTDNSSEC(client)) { if ((fname->attributes & DNS_NAMEATTR_WILDCARD) == 0) { dns_name_t *found; dns_name_t *qname; dns_fixedname_init(&fixed); found = dns_fixedname_name(&fixed); qname = client->query.qname; query_findclosestnsec3(qname, db, version, client, rdataset, sigrdataset, fname, ISC_TRUE, found); /* * Did we find the closest provable encloser * instead? If so add the nearest to the * closest provable encloser. */ if (dns_rdataset_isassociated(rdataset) && !dns_name_equal(qname, found) && !(ns_g_nonearest && qtype != dns_rdatatype_ds)) { unsigned int count; unsigned int skip; /* * Add the closest provable encloser. */ query_addrrset(client, &fname, &rdataset, &sigrdataset, dbuf, DNS_SECTION_AUTHORITY); count = dns_name_countlabels(found) + 1; skip = dns_name_countlabels(qname) - count; dns_name_getlabelsequence(qname, skip, count, found); fixfname(client, &fname, &dbuf, &b); fixrdataset(client, &rdataset); fixrdataset(client, &sigrdataset); if (fname == NULL || rdataset == NULL || sigrdataset == NULL) { CTRACE(ISC_LOG_ERROR, "query_find: " "failure getting " "closest encloser"); QUERY_ERROR(DNS_R_SERVFAIL); goto cleanup; } /* * 'nearest' doesn't exist so * 'exist' is set to ISC_FALSE. */ query_findclosestnsec3(found, db, version, client, rdataset, sigrdataset, fname, ISC_FALSE, NULL); } } else { query_releasename(client, &fname); query_addwildcardproof(client, db, version, client->query.qname, ISC_FALSE, ISC_TRUE); } } if (dns_rdataset_isassociated(rdataset)) { /* * If we've got a NSEC record, we need to save the * name now because we're going call query_addsoa() * below, and it needs to use the name buffer. */ query_keepname(client, fname, dbuf); } else if (fname != NULL) { /* * We're not going to use fname, and need to release * our hold on the name buffer so query_addsoa() * may use it. */ query_releasename(client, &fname); } /* * Add SOA to the additional section if generated by a RPZ * rewrite. */ associated = dns_rdataset_isassociated(rdataset); section = nxrewrite ? DNS_SECTION_ADDITIONAL : DNS_SECTION_AUTHORITY; result = query_addsoa(client, db, version, ISC_UINT32_MAX, associated, section); if (result != ISC_R_SUCCESS) { QUERY_ERROR(result); goto cleanup; } /* * Add NSEC record if we found one. */ if (WANTDNSSEC(client)) { if (dns_rdataset_isassociated(rdataset)) query_addnxrrsetnsec(client, db, version, &fname, &rdataset, &sigrdataset); } goto cleanup; case DNS_R_EMPTYWILD: empty_wild = ISC_TRUE; /* FALLTHROUGH */ case DNS_R_NXDOMAIN: INSIST(is_zone || REDIRECT(client)); if (!empty_wild) { tresult = redirect(client, fname, rdataset, &node, &db, &version, type); if (tresult == ISC_R_SUCCESS) { inc_stats(client, dns_nsstatscounter_nxdomainredirect); break; } if (tresult == DNS_R_NXRRSET) { redirected = ISC_TRUE; goto iszone_nxrrset; } if (tresult == DNS_R_NCACHENXRRSET) { redirected = ISC_TRUE; is_zone = ISC_FALSE; goto ncache_nxrrset; } tresult = redirect2(client, fname, rdataset, &node, &db, &version, type, &is_zone); if (tresult == DNS_R_CONTINUE) { inc_stats(client, dns_nsstatscounter_nxdomainredirect_rlookup); client->query.redirect.qtype = qtype; INSIST(rdataset != NULL); SAVE(client->query.redirect.rdataset, rdataset); SAVE(client->query.redirect.sigrdataset, sigrdataset); SAVE(client->query.redirect.db, db); SAVE(client->query.redirect.node, node); SAVE(client->query.redirect.zone, zone); client->query.redirect.result = DNS_R_NXDOMAIN; dns_name_copy(fname, client->query.redirect.fname, NULL); client->query.redirect.authoritative = authoritative; client->query.redirect.is_zone = is_zone; goto cleanup; } if (tresult == ISC_R_SUCCESS) { inc_stats(client, dns_nsstatscounter_nxdomainredirect); break; } if (tresult == DNS_R_NXRRSET) { redirected = ISC_TRUE; goto iszone_nxrrset; } if (tresult == DNS_R_NCACHENXRRSET) { redirected = ISC_TRUE; is_zone = ISC_FALSE; goto ncache_nxrrset; } } if (dns_rdataset_isassociated(rdataset)) { /* * If we've got a NSEC record, we need to save the * name now because we're going call query_addsoa() * below, and it needs to use the name buffer. */ query_keepname(client, fname, dbuf); } else if (fname != NULL) { /* * We're not going to use fname, and need to release * our hold on the name buffer so query_addsoa() * may use it. */ query_releasename(client, &fname); } /* * Add SOA to the additional section if generated by a * RPZ rewrite. * * If the query was for a SOA record force the * ttl to zero so that it is possible for clients to find * the containing zone of an arbitrary name with a stub * resolver and not have it cached. */ associated = dns_rdataset_isassociated(rdataset); section = nxrewrite ? DNS_SECTION_ADDITIONAL : DNS_SECTION_AUTHORITY; ttl = ISC_UINT32_MAX; if (!nxrewrite && qtype == dns_rdatatype_soa && zone != NULL && dns_zone_getzeronosoattl(zone)) ttl = 0; result = query_addsoa(client, db, version, ttl, associated, section); if (result != ISC_R_SUCCESS) { QUERY_ERROR(result); goto cleanup; } if (WANTDNSSEC(client)) { /* * Add NSEC record if we found one. */ if (dns_rdataset_isassociated(rdataset)) query_addrrset(client, &fname, &rdataset, &sigrdataset, NULL, DNS_SECTION_AUTHORITY); query_addwildcardproof(client, db, version, client->query.qname, ISC_FALSE, ISC_FALSE); } /* * Set message rcode. */ if (empty_wild) client->message->rcode = dns_rcode_noerror; else client->message->rcode = dns_rcode_nxdomain; goto cleanup; case DNS_R_NCACHENXDOMAIN: tresult = redirect(client, fname, rdataset, &node, &db, &version, type); if (tresult == ISC_R_SUCCESS) { inc_stats(client, dns_nsstatscounter_nxdomainredirect); break; } if (tresult == DNS_R_NXRRSET) { redirected = ISC_TRUE; is_zone = ISC_TRUE; goto iszone_nxrrset; } if (tresult == DNS_R_NCACHENXRRSET) { redirected = ISC_TRUE; result = tresult; goto ncache_nxrrset; } tresult = redirect2(client, fname, rdataset, &node, &db, &version, type, &is_zone); if (tresult == DNS_R_CONTINUE) { inc_stats(client, dns_nsstatscounter_nxdomainredirect_rlookup); SAVE(client->query.redirect.db, db); SAVE(client->query.redirect.node, node); SAVE(client->query.redirect.zone, zone); client->query.redirect.qtype = qtype; INSIST(rdataset != NULL); SAVE(client->query.redirect.rdataset, rdataset); SAVE(client->query.redirect.sigrdataset, sigrdataset); client->query.redirect.result = DNS_R_NCACHENXDOMAIN; dns_name_copy(fname, client->query.redirect.fname, NULL); client->query.redirect.authoritative = authoritative; client->query.redirect.is_zone = is_zone; goto cleanup; } if (tresult == ISC_R_SUCCESS) { inc_stats(client, dns_nsstatscounter_nxdomainredirect); break; } if (tresult == DNS_R_NXRRSET) { redirected = ISC_TRUE; is_zone = ISC_TRUE; goto iszone_nxrrset; } if (tresult == DNS_R_NCACHENXRRSET) { redirected = ISC_TRUE; result = tresult; goto ncache_nxrrset; } /* FALLTHROUGH */ case DNS_R_NCACHENXRRSET: ncache_nxrrset: INSIST(!is_zone); authoritative = ISC_FALSE; /* * Set message rcode, if required. */ if (result == DNS_R_NCACHENXDOMAIN) client->message->rcode = dns_rcode_nxdomain; /* * Look for RFC 1918 leakage from Internet. */ if (result == DNS_R_NCACHENXDOMAIN && qtype == dns_rdatatype_ptr && client->message->rdclass == dns_rdataclass_in && dns_name_countlabels(fname) == 7) warn_rfc1918(client, fname, rdataset); #ifdef dns64_bis_return_excluded_addresses if (dns64) #else if (dns64 && !dns64_exclude) #endif { /* * Restore the answers from the previous AAAA lookup. */ if (rdataset != NULL) query_putrdataset(client, &rdataset); if (sigrdataset != NULL) query_putrdataset(client, &sigrdataset); RESTORE(rdataset, client->query.dns64_aaaa); RESTORE(sigrdataset, client->query.dns64_sigaaaa); if (fname == NULL) { dbuf = query_getnamebuf(client); if (dbuf == NULL) { CTRACE(ISC_LOG_ERROR, "query_find: " "query_getnamebuf failed (4)"); QUERY_ERROR(DNS_R_SERVFAIL); goto cleanup; } fname = query_newname(client, dbuf, &b); if (fname == NULL) { CTRACE(ISC_LOG_ERROR, "query_find: " "query_newname failed (4)"); QUERY_ERROR(DNS_R_SERVFAIL); goto cleanup; } } dns_name_copy(client->query.qname, fname, NULL); dns64 = ISC_FALSE; #ifdef dns64_bis_return_excluded_addresses if (dns64_excluded) break; #endif } else if (result == DNS_R_NCACHENXRRSET && !ISC_LIST_EMPTY(client->view->dns64) && client->message->rdclass == dns_rdataclass_in && qtype == dns_rdatatype_aaaa) { /* * Look to see if there are A records for this * name. */ /* * If the ttl is zero we need to workout if we have just * decremented to zero or if there was no negative cache * ttl in the answer. */ if (rdataset->ttl != 0) client->query.dns64_ttl = rdataset->ttl; else if (dns_rdataset_first(rdataset) == ISC_R_SUCCESS) client->query.dns64_ttl = 0; SAVE(client->query.dns64_aaaa, rdataset); SAVE(client->query.dns64_sigaaaa, sigrdataset); query_releasename(client, &fname); dns_db_detachnode(db, &node); type = qtype = dns_rdatatype_a; dns64 = ISC_TRUE; goto db_find; } /* * We don't call query_addrrset() because we don't need any * of its extra features (and things would probably break!). */ if (dns_rdataset_isassociated(rdataset)) { query_keepname(client, fname, dbuf); dns_message_addname(client->message, fname, DNS_SECTION_AUTHORITY); ISC_LIST_APPEND(fname->list, rdataset, link); fname = NULL; rdataset = NULL; } goto cleanup; case DNS_R_CNAME: /* * If we have a zero ttl from the cache refetch it. */ if (!is_zone && !resuming && rdataset->ttl == 0 && RECURSIONOK(client)) { if (dns_rdataset_isassociated(rdataset)) dns_rdataset_disassociate(rdataset); if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset)) dns_rdataset_disassociate(sigrdataset); if (node != NULL) dns_db_detachnode(db, &node); INSIST(!REDIRECT(client)); result = query_recurse(client, qtype, client->query.qname, NULL, NULL, resuming); if (result == ISC_R_SUCCESS) { client->query.attributes |= NS_QUERYATTR_RECURSING; if (dns64) client->query.attributes |= NS_QUERYATTR_DNS64; if (dns64_exclude) client->query.attributes |= NS_QUERYATTR_DNS64EXCLUDE; } else RECURSE_ERROR(result); goto cleanup; } /* * Keep a copy of the rdataset. We have to do this because * query_addrrset may clear 'rdataset' (to prevent the * cleanup code from cleaning it up). */ trdataset = rdataset; /* * Add the CNAME to the answer section. */ if (sigrdataset != NULL) sigrdatasetp = &sigrdataset; else sigrdatasetp = NULL; if (WANTDNSSEC(client) && (fname->attributes & DNS_NAMEATTR_WILDCARD) != 0) { dns_fixedname_init(&wildcardname); dns_name_copy(fname, dns_fixedname_name(&wildcardname), NULL); need_wildcardproof = ISC_TRUE; } if (NOQNAME(rdataset) && WANTDNSSEC(client)) noqname = rdataset; else noqname = NULL; if (!is_zone && RECURSIONOK(client)) query_prefetch(client, fname, rdataset); query_addrrset(client, &fname, &rdataset, sigrdatasetp, dbuf, DNS_SECTION_ANSWER); if (noqname != NULL) query_addnoqnameproof(client, noqname); /* * We set the PARTIALANSWER attribute so that if anything goes * wrong later on, we'll return what we've got so far. */ client->query.attributes |= NS_QUERYATTR_PARTIALANSWER; /* * Reset qname to be the target name of the CNAME and restart * the query. */ tname = NULL; result = dns_message_gettempname(client->message, &tname); if (result != ISC_R_SUCCESS) goto cleanup; result = dns_rdataset_first(trdataset); if (result != ISC_R_SUCCESS) { dns_message_puttempname(client->message, &tname); goto cleanup; } dns_rdataset_current(trdataset, &rdata); result = dns_rdata_tostruct(&rdata, &cname, NULL); dns_rdata_reset(&rdata); if (result != ISC_R_SUCCESS) { dns_message_puttempname(client->message, &tname); goto cleanup; } dns_name_init(tname, NULL); result = dns_name_dup(&cname.cname, client->mctx, tname); if (result != ISC_R_SUCCESS) { dns_message_puttempname(client->message, &tname); dns_rdata_freestruct(&cname); goto cleanup; } dns_rdata_freestruct(&cname); ns_client_qnamereplace(client, tname); want_restart = ISC_TRUE; if (!WANTRECURSION(client)) options |= DNS_GETDB_NOLOG; goto addauth; case DNS_R_DNAME: /* * Compare the current qname to the found name. We need * to know how many labels and bits are in common because * we're going to have to split qname later on. */ namereln = dns_name_fullcompare(client->query.qname, fname, &order, &nlabels); INSIST(namereln == dns_namereln_subdomain); /* * Keep a copy of the rdataset. We have to do this because * query_addrrset may clear 'rdataset' (to prevent the * cleanup code from cleaning it up). */ trdataset = rdataset; /* * Add the DNAME to the answer section. */ if (sigrdataset != NULL) sigrdatasetp = &sigrdataset; else sigrdatasetp = NULL; if (WANTDNSSEC(client) && (fname->attributes & DNS_NAMEATTR_WILDCARD) != 0) { dns_fixedname_init(&wildcardname); dns_name_copy(fname, dns_fixedname_name(&wildcardname), NULL); need_wildcardproof = ISC_TRUE; } if (!is_zone && RECURSIONOK(client)) query_prefetch(client, fname, rdataset); query_addrrset(client, &fname, &rdataset, sigrdatasetp, dbuf, DNS_SECTION_ANSWER); /* * We set the PARTIALANSWER attribute so that if anything goes * wrong later on, we'll return what we've got so far. */ client->query.attributes |= NS_QUERYATTR_PARTIALANSWER; /* * Get the target name of the DNAME. */ tname = NULL; result = dns_message_gettempname(client->message, &tname); if (result != ISC_R_SUCCESS) goto cleanup; result = dns_rdataset_first(trdataset); if (result != ISC_R_SUCCESS) { dns_message_puttempname(client->message, &tname); goto cleanup; } dns_rdataset_current(trdataset, &rdata); result = dns_rdata_tostruct(&rdata, &dname, NULL); dns_rdata_reset(&rdata); if (result != ISC_R_SUCCESS) { dns_message_puttempname(client->message, &tname); goto cleanup; } dns_name_clone(&dname.dname, tname); dns_rdata_freestruct(&dname); /* * Construct the new qname consisting of * . */ dns_fixedname_init(&fixed); prefix = dns_fixedname_name(&fixed); dns_name_split(client->query.qname, nlabels, prefix, NULL); INSIST(fname == NULL); dbuf = query_getnamebuf(client); if (dbuf == NULL) { dns_message_puttempname(client->message, &tname); goto cleanup; } fname = query_newname(client, dbuf, &b); if (fname == NULL) { dns_message_puttempname(client->message, &tname); goto cleanup; } result = dns_name_concatenate(prefix, tname, fname, NULL); dns_message_puttempname(client->message, &tname); /* * RFC2672, section 4.1, subsection 3c says * we should return YXDOMAIN if the constructed * name would be too long. */ if (result == DNS_R_NAMETOOLONG) client->message->rcode = dns_rcode_yxdomain; if (result != ISC_R_SUCCESS) goto cleanup; query_keepname(client, fname, dbuf); /* * Synthesize a CNAME consisting of * CNAME * with * * Synthesize a CNAME so old old clients that don't understand * DNAME can chain. * * We do not try to synthesize a signature because we hope * that security aware servers will understand DNAME. Also, * even if we had an online key, making a signature * on-the-fly is costly, and not really legitimate anyway * since the synthesized CNAME is NOT in the zone. */ result = query_add_cname(client, client->query.qname, fname, trdataset->trust, trdataset->ttl); if (result != ISC_R_SUCCESS) goto cleanup; /* * Switch to the new qname and restart. */ ns_client_qnamereplace(client, fname); fname = NULL; want_restart = ISC_TRUE; if (!WANTRECURSION(client)) options |= DNS_GETDB_NOLOG; goto addauth; default: /* * Something has gone wrong. */ snprintf(errmsg, sizeof(errmsg) - 1, "query_find: unexpected error after resuming: %s", isc_result_totext(result)); CTRACE(ISC_LOG_ERROR, errmsg); QUERY_ERROR(DNS_R_SERVFAIL); goto cleanup; } if (WANTDNSSEC(client) && (fname->attributes & DNS_NAMEATTR_WILDCARD) != 0) { dns_fixedname_init(&wildcardname); dns_name_copy(fname, dns_fixedname_name(&wildcardname), NULL); need_wildcardproof = ISC_TRUE; } #ifdef ALLOW_FILTER_AAAA /* * The filter-aaaa-on-v4 option should suppress AAAAs for IPv4 * clients if there is an A; filter-aaaa-on-v6 option does the same * for IPv6 clients. */ client->filter_aaaa = dns_aaaa_ok; if (client->view->v4_aaaa != dns_aaaa_ok || client->view->v6_aaaa != dns_aaaa_ok) { result = ns_client_checkaclsilent(client, NULL, client->view->aaaa_acl, ISC_TRUE); if (result == ISC_R_SUCCESS && client->view->v4_aaaa != dns_aaaa_ok && is_v4_client(client)) client->filter_aaaa = client->view->v4_aaaa; else if (result == ISC_R_SUCCESS && client->view->v6_aaaa != dns_aaaa_ok && is_v6_client(client)) client->filter_aaaa = client->view->v6_aaaa; } #endif if (type == dns_rdatatype_any) { /* * For minimal-any, we only add records that * match this type or cover this type. */ dns_rdatatype_t onetype = 0; #ifdef ALLOW_FILTER_AAAA isc_boolean_t have_aaaa, have_a, have_sig; /* * If we are not authoritative, assume there is a A * even in if it is not in our cache. This assumption could * be wrong but it is a good bet. */ have_aaaa = ISC_FALSE; have_a = !authoritative; have_sig = ISC_FALSE; #endif /* * XXXRTH Need to handle zonecuts with special case * code. */ n = 0; rdsiter = NULL; result = dns_db_allrdatasets(db, node, version, 0, &rdsiter); if (result != ISC_R_SUCCESS) { CTRACE(ISC_LOG_ERROR, "query_find: type any; allrdatasets failed"); QUERY_ERROR(DNS_R_SERVFAIL); goto cleanup; } /* * Calling query_addrrset() with a non-NULL dbuf is going * to either keep or release the name. We don't want it to * release fname, since we may have to call query_addrrset() * more than once. That means we have to call query_keepname() * now, and pass a NULL dbuf to query_addrrset(). * * If we do a query_addrrset() below, we must set fname to * NULL before leaving this block, otherwise we might try to * cleanup fname even though we're using it! */ query_keepname(client, fname, dbuf); tname = fname; result = dns_rdatasetiter_first(rdsiter); while (result == ISC_R_SUCCESS) { dns_rdatasetiter_current(rdsiter, rdataset); #ifdef ALLOW_FILTER_AAAA /* * Notice the presence of A and AAAAs so * that AAAAs can be hidden from IPv4 clients. */ if (client->filter_aaaa != dns_aaaa_ok) { if (rdataset->type == dns_rdatatype_aaaa) have_aaaa = ISC_TRUE; else if (rdataset->type == dns_rdatatype_a) have_a = ISC_TRUE; } #endif /* * We found an NS RRset; no need to add one later. */ if (qtype == dns_rdatatype_any && rdataset->type == dns_rdatatype_ns) { answer_has_ns = ISC_TRUE; } if (is_zone && qtype == dns_rdatatype_any && !dns_db_issecure(db) && dns_rdatatype_isdnssec(rdataset->type)) { /* * The zone is transitioning from insecure * to secure. Hide the dnssec records from * ANY queries. */ dns_rdataset_disassociate(rdataset); } else if (client->view->minimal_any && !TCP(client) && !WANTDNSSEC(client) && qtype == dns_rdatatype_any && (rdataset->type == dns_rdatatype_sig || rdataset->type == dns_rdatatype_rrsig)) { CTRACE(ISC_LOG_DEBUG(5), "query_find: " "minimal-any skip signature"); dns_rdataset_disassociate(rdataset); } else if (client->view->minimal_any && !TCP(client) && onetype != 0 && rdataset->type != onetype && rdataset->covers != onetype) { CTRACE(ISC_LOG_DEBUG(5), "query_find: " "minimal-any skip rdataset"); dns_rdataset_disassociate(rdataset); } else if ((qtype == dns_rdatatype_any || rdataset->type == qtype) && rdataset->type != 0) { #ifdef ALLOW_FILTER_AAAA if (dns_rdatatype_isdnssec(rdataset->type)) have_sig = ISC_TRUE; #endif if (NOQNAME(rdataset) && WANTDNSSEC(client)) noqname = rdataset; else noqname = NULL; rpz_st = client->query.rpz_st; if (rpz_st != NULL) rdataset->ttl = ISC_MIN(rdataset->ttl, rpz_st->m.ttl); if (!is_zone && RECURSIONOK(client)) { dns_name_t *name; name = (fname != NULL) ? fname : tname; query_prefetch(client, name, rdataset); } /* * Remember the first RRtype we find so we * can skip others with minimal-any. */ if (rdataset->type == dns_rdatatype_sig || rdataset->type == dns_rdatatype_rrsig) onetype = rdataset->covers; else onetype = rdataset->type; query_addrrset(client, fname != NULL ? &fname : &tname, &rdataset, NULL, NULL, DNS_SECTION_ANSWER); if (noqname != NULL) query_addnoqnameproof(client, noqname); n++; INSIST(tname != NULL); /* * rdataset is non-NULL only in certain * pathological cases involving DNAMEs. */ if (rdataset != NULL) query_putrdataset(client, &rdataset); rdataset = query_newrdataset(client); if (rdataset == NULL) break; } else { /* * We're not interested in this rdataset. */ dns_rdataset_disassociate(rdataset); } result = dns_rdatasetiter_next(rdsiter); } #ifdef ALLOW_FILTER_AAAA /* * Filter AAAAs if there is an A and there is no signature * or we are supposed to break DNSSEC. */ if (client->filter_aaaa == dns_aaaa_break_dnssec) client->attributes |= NS_CLIENTATTR_FILTER_AAAA; else if (client->filter_aaaa != dns_aaaa_ok && have_aaaa && have_a && (!have_sig || !WANTDNSSEC(client))) client->attributes |= NS_CLIENTATTR_FILTER_AAAA; #endif if (fname != NULL) dns_message_puttempname(client->message, &fname); if (n == 0) { /* * No matching rdatasets found in cache. If we were * searching for RRSIG/SIG, that's probably okay; * otherwise this is an error condition. */ if ((qtype == dns_rdatatype_rrsig || qtype == dns_rdatatype_sig) && result == ISC_R_NOMORE) { if (!is_zone) { authoritative = ISC_FALSE; dns_rdatasetiter_destroy(&rdsiter); client->attributes &= ~NS_CLIENTATTR_RA; goto addauth; } if (qtype == dns_rdatatype_rrsig && dns_db_issecure(db)) { char namebuf[DNS_NAME_FORMATSIZE]; dns_name_format(client->query.qname, namebuf, sizeof(namebuf)); ns_client_log(client, DNS_LOGCATEGORY_DNSSEC, NS_LOGMODULE_QUERY, ISC_LOG_WARNING, "missing signature " "for %s", namebuf); } dns_rdatasetiter_destroy(&rdsiter); fname = query_newname(client, dbuf, &b); goto nxrrset_rrsig; } else { CTRACE(ISC_LOG_ERROR, "query_find: no matching rdatasets " "in cache"); result = DNS_R_SERVFAIL; } } dns_rdatasetiter_destroy(&rdsiter); if (result != ISC_R_NOMORE) { CTRACE(ISC_LOG_ERROR, "query_find: dns_rdatasetiter_destroy failed"); QUERY_ERROR(DNS_R_SERVFAIL); goto cleanup; } } else { /* * This is the "normal" case -- an ordinary question to which * we know the answer. */ /* * If we have a zero ttl from the cache refetch it. */ if (!is_zone && !resuming && rdataset->ttl == 0 && RECURSIONOK(client)) { if (dns_rdataset_isassociated(rdataset)) dns_rdataset_disassociate(rdataset); if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset)) dns_rdataset_disassociate(sigrdataset); if (node != NULL) dns_db_detachnode(db, &node); INSIST(!REDIRECT(client)); result = query_recurse(client, qtype, client->query.qname, NULL, NULL, resuming); if (result == ISC_R_SUCCESS) { client->query.attributes |= NS_QUERYATTR_RECURSING; if (dns64) client->query.attributes |= NS_QUERYATTR_DNS64; if (dns64_exclude) client->query.attributes |= NS_QUERYATTR_DNS64EXCLUDE; } else RECURSE_ERROR(result); goto cleanup; } #ifdef ALLOW_FILTER_AAAA /* * Optionally hide AAAAs from IPv4 clients if there is an A. * We add the AAAAs now, but might refuse to render them later * after DNSSEC is figured out. * This could be more efficient, but the whole idea is * so fundamentally wrong, unavoidably inaccurate, and * unneeded that it is best to keep it as short as possible. */ if (client->filter_aaaa == dns_aaaa_break_dnssec || (client->filter_aaaa == dns_aaaa_filter && (!WANTDNSSEC(client) || sigrdataset == NULL || !dns_rdataset_isassociated(sigrdataset)))) { if (qtype == dns_rdatatype_aaaa) { trdataset = query_newrdataset(client); result = dns_db_findrdataset(db, node, version, dns_rdatatype_a, 0, client->now, trdataset, NULL); if (dns_rdataset_isassociated(trdataset)) dns_rdataset_disassociate(trdataset); query_putrdataset(client, &trdataset); /* * We have an AAAA but the A is not in our cache. * Assume any result other than DNS_R_DELEGATION * or ISC_R_NOTFOUND means there is no A and * so AAAAs are ok. * Assume there is no A if we can't recurse * for this client, although that could be * the wrong answer. What else can we do? * Besides, that we have the AAAA and are using * this mechanism suggests that we care more * about As than AAAAs and would have cached * the A if it existed. */ if (result == ISC_R_SUCCESS) { client->attributes |= NS_CLIENTATTR_FILTER_AAAA; } else if (authoritative || !RECURSIONOK(client) || (result != DNS_R_DELEGATION && result != ISC_R_NOTFOUND)) { client->attributes &= ~NS_CLIENTATTR_FILTER_AAAA; } else { /* * This is an ugly kludge to recurse * for the A and discard the result. * * Continue to add the AAAA now. * We'll make a note to not render it * if the recursion for the A succeeds. */ INSIST(!REDIRECT(client)); result = query_recurse(client, dns_rdatatype_a, client->query.qname, NULL, NULL, resuming); if (result == ISC_R_SUCCESS) { client->attributes |= NS_CLIENTATTR_FILTER_AAAA_RC; client->query.attributes |= NS_QUERYATTR_RECURSING; } } } else if (qtype == dns_rdatatype_a && (client->attributes & NS_CLIENTATTR_FILTER_AAAA_RC) != 0) { client->attributes &= ~NS_CLIENTATTR_FILTER_AAAA_RC; client->attributes |= NS_CLIENTATTR_FILTER_AAAA; dns_rdataset_disassociate(rdataset); if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset)) dns_rdataset_disassociate(sigrdataset); goto cleanup; } } #endif /* * Check to see if the AAAA RRset has non-excluded addresses * in it. If not look for a A RRset. */ INSIST(client->query.dns64_aaaaok == NULL); if (qtype == dns_rdatatype_aaaa && !dns64_exclude && !ISC_LIST_EMPTY(client->view->dns64) && client->message->rdclass == dns_rdataclass_in && !dns64_aaaaok(client, rdataset, sigrdataset)) { /* * Look to see if there are A records for this * name. */ client->query.dns64_ttl = rdataset->ttl; SAVE(client->query.dns64_aaaa, rdataset); SAVE(client->query.dns64_sigaaaa, sigrdataset); query_releasename(client, &fname); dns_db_detachnode(db, &node); type = qtype = dns_rdatatype_a; dns64_exclude = dns64 = ISC_TRUE; goto db_find; } if (sigrdataset != NULL) sigrdatasetp = &sigrdataset; else sigrdatasetp = NULL; if (NOQNAME(rdataset) && WANTDNSSEC(client)) noqname = rdataset; else noqname = NULL; /* * Special case NS handling */ if (is_zone && qtype == dns_rdatatype_ns) { /* * We've already got an NS, no need to add one in * the authority section */ if (dns_name_equal(client->query.qname, dns_db_origin(db))) { answer_has_ns = ISC_TRUE; } /* * BIND 8 priming queries need the additional section. */ if (dns_name_equal(client->query.qname, dns_rootname)) { client->query.attributes &= ~NS_QUERYATTR_NOADDITIONAL; } } /* * Return the time to expire for slave and master zones. */ if (zone != NULL && is_zone && qtype == dns_rdatatype_soa && (client->attributes & NS_CLIENTATTR_WANTEXPIRE) != 0 && client->query.restarts == 0) { dns_zone_t *raw = NULL, *mayberaw; dns_zone_getraw(zone, &raw); mayberaw = (raw != NULL) ? raw : zone; if (dns_zone_gettype(mayberaw) == dns_zone_slave) { isc_time_t expiretime; isc_uint32_t secs; dns_zone_getexpiretime(zone, &expiretime); secs = isc_time_seconds(&expiretime); if (secs >= client->now && result == ISC_R_SUCCESS) { client->attributes |= NS_CLIENTATTR_HAVEEXPIRE; client->expire = secs - client->now; } } if (dns_zone_gettype(mayberaw) == dns_zone_master) { dns_rdata_soa_t soa; result = dns_rdataset_first(rdataset); RUNTIME_CHECK(result == ISC_R_SUCCESS); dns_rdataset_current(rdataset, &rdata); result = dns_rdata_tostruct(&rdata, &soa, NULL); RUNTIME_CHECK(result == ISC_R_SUCCESS); client->expire = soa.expire; client->attributes |= NS_CLIENTATTR_HAVEEXPIRE; } if (raw != NULL) dns_zone_detach(&raw); } if (dns64) { qtype = type = dns_rdatatype_aaaa; result = query_dns64(client, &fname, rdataset, sigrdataset, dbuf, DNS_SECTION_ANSWER); noqname = NULL; dns_rdataset_disassociate(rdataset); dns_message_puttemprdataset(client->message, &rdataset); if (result == ISC_R_NOMORE) { #ifndef dns64_bis_return_excluded_addresses if (dns64_exclude) { if (!is_zone) goto cleanup; /* * Add a fake SOA record. */ (void)query_addsoa(client, db, version, 600, ISC_FALSE, DNS_SECTION_AUTHORITY); goto cleanup; } #endif if (is_zone) goto iszone_nxrrset; else goto ncache_nxrrset; } else if (result != ISC_R_SUCCESS) { eresult = result; goto cleanup; } } else if (client->query.dns64_aaaaok != NULL) { query_filter64(client, &fname, rdataset, dbuf, DNS_SECTION_ANSWER); query_putrdataset(client, &rdataset); } else { if (!is_zone && RECURSIONOK(client)) query_prefetch(client, fname, rdataset); query_addrrset(client, &fname, &rdataset, sigrdatasetp, dbuf, DNS_SECTION_ANSWER); } if (noqname != NULL) query_addnoqnameproof(client, noqname); /* * We shouldn't ever fail to add 'rdataset' * because it's already in the answer. */ INSIST(rdataset == NULL); } addauth: CTRACE(ISC_LOG_DEBUG(3), "query_find: addauth"); /* * Add NS records to the authority section (if we haven't already * added them to the answer section). */ if (!want_restart && !NOAUTHORITY(client)) { if (is_zone) { if (!answer_has_ns) { (void)query_addns(client, db, version); } } else if (!answer_has_ns && qtype != dns_rdatatype_ns) { if (fname != NULL) { query_releasename(client, &fname); } query_addbestns(client); } } /* * Add NSEC records to the authority section if they're needed for * DNSSEC wildcard proofs. */ if (need_wildcardproof && dns_db_issecure(db)) query_addwildcardproof(client, db, version, dns_fixedname_name(&wildcardname), ISC_TRUE, ISC_FALSE); cleanup: CTRACE(ISC_LOG_DEBUG(3), "query_find: cleanup"); /* * General cleanup. */ rpz_st = client->query.rpz_st; if (rpz_st != NULL && (rpz_st->state & DNS_RPZ_RECURSING) == 0) { rpz_match_clear(rpz_st); rpz_st->state &= ~DNS_RPZ_DONE_QNAME; } if (rdataset != NULL) query_putrdataset(client, &rdataset); if (sigrdataset != NULL) query_putrdataset(client, &sigrdataset); if (fname != NULL) query_releasename(client, &fname); if (node != NULL) dns_db_detachnode(db, &node); if (db != NULL) dns_db_detach(&db); if (zone != NULL) dns_zone_detach(&zone); if (zdb != NULL) { query_putrdataset(client, &zrdataset); if (zsigrdataset != NULL) query_putrdataset(client, &zsigrdataset); if (zfname != NULL) query_releasename(client, &zfname); dns_db_detach(&zdb); } if (event != NULL) { free_devent(client, ISC_EVENT_PTR(&event), &event); } /* * AA bit. */ if (client->query.restarts == 0 && !authoritative) { /* * We're not authoritative, so we must ensure the AA bit * isn't set. */ client->message->flags &= ~DNS_MESSAGEFLAG_AA; } /* * Restart the query? */ if (want_restart && client->query.restarts < MAX_RESTARTS) { client->query.restarts++; goto restart; } if (eresult != ISC_R_SUCCESS && (!PARTIALANSWER(client) || WANTRECURSION(client) || eresult == DNS_R_DROP)) { if (eresult == DNS_R_DUPLICATE || eresult == DNS_R_DROP) { /* * This was a duplicate query that we are * recursing on or the result of rate limiting. * Don't send a response now for a duplicate query, * because the original will still cause a response. */ query_next(client, eresult); } else { /* * If we don't have any answer to give the client, * or if the client requested recursion and thus wanted * the complete answer, send an error response. */ INSIST(line >= 0); query_error(client, eresult, line); } ns_client_detach(&client); } else if (!RECURSING(client)) { /* * We are done. Set up sortlist data for the message * rendering code, make a final tweak to the AA bit if the * auth-nxdomain config option says so, then render and * send the response. */ setup_query_sortlist(client); /* * If this is a referral and the answer to the question * is in the glue sort it to the start of the additional * section. */ if (ISC_LIST_EMPTY(client->message->sections[DNS_SECTION_ANSWER]) && client->message->rcode == dns_rcode_noerror && (qtype == dns_rdatatype_a || qtype == dns_rdatatype_aaaa)) answer_in_glue(client, qtype); if (client->message->rcode == dns_rcode_nxdomain && client->view->auth_nxdomain == ISC_TRUE) client->message->flags |= DNS_MESSAGEFLAG_AA; /* * If the response is somehow unexpected for the client and this * is a result of recursion, return an error to the caller * to indicate it may need to be logged. */ if (resuming && (ISC_LIST_EMPTY(client->message->sections[DNS_SECTION_ANSWER]) || client->message->rcode != dns_rcode_noerror)) eresult = ISC_R_FAILURE; query_send(client); ns_client_detach(&client); } CTRACE(ISC_LOG_DEBUG(3), "query_find: done"); return (eresult); } static inline void log_tat(ns_client_t *client) { char namebuf[DNS_NAME_FORMATSIZE]; char clientbuf[ISC_NETADDR_FORMATSIZE]; char classname[DNS_RDATACLASS_FORMATSIZE]; isc_netaddr_t netaddr; char *tags = NULL; size_t taglen = 0; if (!isc_log_wouldlog(ns_g_lctx, ISC_LOG_INFO)) { return; } if ((client->query.qtype != dns_rdatatype_null || !dns_name_istat(client->query.qname)) && (client->keytag == NULL || client->query.qtype != dns_rdatatype_dnskey)) { return; } isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr); dns_name_format(client->query.qname, namebuf, sizeof(namebuf)); isc_netaddr_format(&client->destaddr, clientbuf, sizeof(clientbuf)); dns_rdataclass_format(client->view->rdclass, classname, sizeof(classname)); if (client->query.qtype == dns_rdatatype_dnskey) { isc_uint16_t keytags = client->keytag_len / 2; size_t len = taglen = sizeof("65000") * keytags + 1; char *cp = tags = isc_mem_get(client->mctx, taglen); int i = 0; INSIST(client->keytag != NULL); if (tags != NULL) { while (keytags-- > 0U) { int n; isc_uint16_t keytag; keytag = (client->keytag[i * 2] << 8) | client->keytag[i * 2 + 1]; n = snprintf(cp, len, " %u", keytag); if (n > 0 && (size_t)n <= len) { cp += n; len -= n; i++; } else { break; } } } } isc_log_write(ns_g_lctx, NS_LOGCATEGORY_TAT, NS_LOGMODULE_QUERY, ISC_LOG_INFO, "trust-anchor-telemetry '%s/%s' from %s%s", namebuf, classname, clientbuf, tags != NULL? tags : ""); if (tags != NULL) { isc_mem_put(client->mctx, tags, taglen); } } static inline void log_query(ns_client_t *client, unsigned int flags, unsigned int extflags) { char namebuf[DNS_NAME_FORMATSIZE]; char typename[DNS_RDATATYPE_FORMATSIZE]; char classname[DNS_RDATACLASS_FORMATSIZE]; char onbuf[ISC_NETADDR_FORMATSIZE]; char ednsbuf[sizeof("E(65535)")] = { 0 }; dns_rdataset_t *rdataset; int level = ISC_LOG_INFO; if (! isc_log_wouldlog(ns_g_lctx, level)) return; rdataset = ISC_LIST_HEAD(client->query.qname->list); INSIST(rdataset != NULL); dns_name_format(client->query.qname, namebuf, sizeof(namebuf)); dns_rdataclass_format(rdataset->rdclass, classname, sizeof(classname)); dns_rdatatype_format(rdataset->type, typename, sizeof(typename)); isc_netaddr_format(&client->destaddr, onbuf, sizeof(onbuf)); if (client->ednsversion >= 0) snprintf(ednsbuf, sizeof(ednsbuf), "E(%hd)", client->ednsversion); ns_client_log(client, NS_LOGCATEGORY_QUERIES, NS_LOGMODULE_QUERY, level, "query: %s %s %s %s%s%s%s%s%s%s (%s)", namebuf, classname, typename, WANTRECURSION(client) ? "+" : "-", (client->signer != NULL) ? "S" : "", ednsbuf, TCP(client) ? "T" : "", ((extflags & DNS_MESSAGEEXTFLAG_DO) != 0) ? "D" : "", ((flags & DNS_MESSAGEFLAG_CD) != 0) ? "C" : "", HAVECOOKIE(client) ? "V" : WANTCOOKIE(client) ? "K" : "", onbuf); } static inline void log_queryerror(ns_client_t *client, isc_result_t result, int line, int level) { char namebuf[DNS_NAME_FORMATSIZE]; char typename[DNS_RDATATYPE_FORMATSIZE]; char classname[DNS_RDATACLASS_FORMATSIZE]; const char *namep, *typep, *classp, *sep1, *sep2; dns_rdataset_t *rdataset; if (!isc_log_wouldlog(ns_g_lctx, level)) return; namep = typep = classp = sep1 = sep2 = ""; /* * Query errors can happen for various reasons. In some cases we cannot * even assume the query contains a valid question section, so we should * expect exceptional cases. */ if (client->query.origqname != NULL) { dns_name_format(client->query.origqname, namebuf, sizeof(namebuf)); namep = namebuf; sep1 = " for "; rdataset = ISC_LIST_HEAD(client->query.origqname->list); if (rdataset != NULL) { dns_rdataclass_format(rdataset->rdclass, classname, sizeof(classname)); classp = classname; dns_rdatatype_format(rdataset->type, typename, sizeof(typename)); typep = typename; sep2 = "/"; } } ns_client_log(client, NS_LOGCATEGORY_QUERY_ERRORS, NS_LOGMODULE_QUERY, level, "query failed (%s)%s%s%s%s%s%s at %s:%d", isc_result_totext(result), sep1, namep, sep2, classp, sep2, typep, __FILE__, line); } void ns_query_start(ns_client_t *client) { isc_result_t result; dns_message_t *message = client->message; dns_rdataset_t *rdataset; ns_client_t *qclient; dns_rdatatype_t qtype; unsigned int saved_extflags = client->extflags; unsigned int saved_flags = client->message->flags; REQUIRE(NS_CLIENT_VALID(client)); CTRACE(ISC_LOG_DEBUG(3), "ns_query_start"); /* * Test only. */ if (ns_g_clienttest && !TCP(client)) { result = ns_client_replace(client); if (result == ISC_R_SHUTTINGDOWN) { ns_client_next(client, result); return; } else if (result != ISC_R_SUCCESS) { query_error(client, result, __LINE__); return; } } /* * Ensure that appropriate cleanups occur. */ client->next = query_next_callback; /* * Behave as if we don't support DNSSEC if not enabled. */ if (!client->view->enablednssec) { message->flags &= ~DNS_MESSAGEFLAG_CD; client->extflags &= ~DNS_MESSAGEEXTFLAG_DO; } if ((message->flags & DNS_MESSAGEFLAG_RD) != 0) client->query.attributes |= NS_QUERYATTR_WANTRECURSION; if ((client->extflags & DNS_MESSAGEEXTFLAG_DO) != 0) client->attributes |= NS_CLIENTATTR_WANTDNSSEC; switch (client->view->minimalresponses) { case dns_minimal_no: break; case dns_minimal_yes: client->query.attributes |= (NS_QUERYATTR_NOAUTHORITY | NS_QUERYATTR_NOADDITIONAL); break; case dns_minimal_noauth: client->query.attributes |= NS_QUERYATTR_NOAUTHORITY; break; case dns_minimal_noauthrec: if ((message->flags & DNS_MESSAGEFLAG_RD) != 0) client->query.attributes |= NS_QUERYATTR_NOAUTHORITY; break; } if ((client->view->cachedb == NULL) || (!client->view->additionalfromcache)) { /* * We don't have a cache. Turn off cache support and * recursion. */ client->query.attributes &= ~(NS_QUERYATTR_RECURSIONOK|NS_QUERYATTR_CACHEOK); client->attributes |= NS_CLIENTATTR_NOSETFC; } else if ((client->attributes & NS_CLIENTATTR_RA) == 0 || (message->flags & DNS_MESSAGEFLAG_RD) == 0) { /* * If the client isn't allowed to recurse (due to * "recursion no", the allow-recursion ACL, or the * lack of a resolver in this view), or if it * doesn't want recursion, turn recursion off. */ client->query.attributes &= ~NS_QUERYATTR_RECURSIONOK; client->attributes |= NS_CLIENTATTR_NOSETFC; } /* * Check for multiple question queries, since edns1 is dead. */ if (message->counts[DNS_SECTION_QUESTION] > 1) { query_error(client, DNS_R_FORMERR, __LINE__); return; } /* * Get the question name. */ result = dns_message_firstname(message, DNS_SECTION_QUESTION); if (result != ISC_R_SUCCESS) { query_error(client, result, __LINE__); return; } dns_message_currentname(message, DNS_SECTION_QUESTION, &client->query.qname); client->query.origqname = client->query.qname; result = dns_message_nextname(message, DNS_SECTION_QUESTION); if (result != ISC_R_NOMORE) { if (result == ISC_R_SUCCESS) { /* * There's more than one QNAME in the question * section. */ query_error(client, DNS_R_FORMERR, __LINE__); } else query_error(client, result, __LINE__); return; } if (ns_g_server->log_queries) log_query(client, saved_flags, saved_extflags); /* * Check for meta-queries like IXFR and AXFR. */ rdataset = ISC_LIST_HEAD(client->query.qname->list); INSIST(rdataset != NULL); client->query.qtype = qtype = rdataset->type; dns_rdatatypestats_increment(ns_g_server->rcvquerystats, qtype); log_tat(client); if (dns_rdatatype_ismeta(qtype)) { switch (qtype) { case dns_rdatatype_any: break; /* Let query_find handle it. */ case dns_rdatatype_ixfr: case dns_rdatatype_axfr: ns_xfr_start(client, rdataset->type); return; case dns_rdatatype_maila: case dns_rdatatype_mailb: query_error(client, DNS_R_NOTIMP, __LINE__); return; case dns_rdatatype_tkey: result = dns_tkey_processquery(client->message, ns_g_server->tkeyctx, client->view->dynamickeys); if (result == ISC_R_SUCCESS) query_send(client); else query_error(client, result, __LINE__); return; default: /* TSIG, etc. */ query_error(client, DNS_R_FORMERR, __LINE__); return; } } /* * Turn on minimal response for (C)DNSKEY and (C)DS queries. */ if (qtype == dns_rdatatype_dnskey || qtype == dns_rdatatype_ds || qtype == dns_rdatatype_cdnskey || qtype == dns_rdatatype_cds) { client->query.attributes |= (NS_QUERYATTR_NOAUTHORITY | NS_QUERYATTR_NOADDITIONAL); } /* * Maybe turn on minimal responses for ANY queries. */ if (qtype == dns_rdatatype_any && client->view->minimal_any && !TCP(client)) client->query.attributes |= (NS_QUERYATTR_NOAUTHORITY | NS_QUERYATTR_NOADDITIONAL); /* * Turn on minimal responses for EDNS/UDP bufsize 512 queries. */ if (client->ednsversion >= 0 && client->udpsize <= 512U && !TCP(client)) client->query.attributes |= (NS_QUERYATTR_NOAUTHORITY | NS_QUERYATTR_NOADDITIONAL); /* * If the client has requested that DNSSEC checking be disabled, * allow lookups to return pending data and instruct the resolver * to return data before validation has completed. * * We don't need to set DNS_DBFIND_PENDINGOK when validation is * disabled as there will be no pending data. */ if (message->flags & DNS_MESSAGEFLAG_CD || qtype == dns_rdatatype_rrsig) { client->query.dboptions |= DNS_DBFIND_PENDINGOK; client->query.fetchoptions |= DNS_FETCHOPT_NOVALIDATE; } else if (!client->view->enablevalidation) client->query.fetchoptions |= DNS_FETCHOPT_NOVALIDATE; /* * Allow glue NS records to be added to the authority section * if the answer is secure. */ if (message->flags & DNS_MESSAGEFLAG_CD) client->query.attributes &= ~NS_QUERYATTR_SECURE; /* * Set NS_CLIENTATTR_WANTDNSSEC if the client has set AD in the query. * This allows AD to be returned on queries without DO set. */ if ((message->flags & DNS_MESSAGEFLAG_AD) != 0) client->attributes |= NS_CLIENTATTR_WANTAD; /* * This is an ordinary query. */ result = dns_message_reply(message, ISC_TRUE); if (result != ISC_R_SUCCESS) { query_next(client, result); return; } /* * Assume authoritative response until it is known to be * otherwise. * * If "-T noaa" has been set on the command line don't set * AA on authoritative answers. */ if (!ns_g_noaa) message->flags |= DNS_MESSAGEFLAG_AA; /* * Set AD. We must clear it if we add non-validated data to a * response. */ if (WANTDNSSEC(client) || WANTAD(client)) message->flags |= DNS_MESSAGEFLAG_AD; qclient = NULL; ns_client_attach(client, &qclient); (void)query_find(qclient, NULL, qtype); } bind9-9.11.3+dfsg/bin/named/server.c000066400000000000000000013473251325250447100170610ustar00rootroot00000000000000/* * Copyright (C) 1999-2018 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /*! \file */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_GEOIP #include #endif /* HAVE_GEOIP */ #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_LIBSCF #include #include #endif #ifdef HAVE_LMDB #include #define count_newzones count_newzones_db #define configure_newzones configure_newzones_db #define dumpzone dumpzone_db #else /* HAVE_LMDB */ #define count_newzones count_newzones_file #define configure_newzones configure_newzones_file #define dumpzone dumpzone_file #endif /* HAVE_LMDB */ #ifndef PATH_MAX #define PATH_MAX 1024 #endif #ifndef SIZE_MAX #define SIZE_MAX ((size_t)-1) #endif #ifndef SIZE_AS_PERCENT #define SIZE_AS_PERCENT ((size_t)-2) #endif #ifdef TUNE_LARGE #define RESOLVER_NTASKS 523 #define UDPBUFFERS 32768 #define EXCLBUFFERS 32768 #else #define RESOLVER_NTASKS 31 #define UDPBUFFERS 1000 #define EXCLBUFFERS 4096 #endif /* TUNE_LARGE */ /*% * Check an operation for failure. Assumes that the function * using it has a 'result' variable and a 'cleanup' label. */ #define CHECK(op) \ do { result = (op); \ if (result != ISC_R_SUCCESS) goto cleanup; \ } while (0) #define TCHECK(op) \ do { tresult = (op); \ if (tresult != ISC_R_SUCCESS) { \ isc_buffer_clear(*text); \ goto cleanup; \ } \ } while (0) #define CHECKM(op, msg) \ do { result = (op); \ if (result != ISC_R_SUCCESS) { \ isc_log_write(ns_g_lctx, \ NS_LOGCATEGORY_GENERAL, \ NS_LOGMODULE_SERVER, \ ISC_LOG_ERROR, \ "%s: %s", msg, \ isc_result_totext(result)); \ goto cleanup; \ } \ } while (0) \ #define CHECKMF(op, msg, file) \ do { result = (op); \ if (result != ISC_R_SUCCESS) { \ isc_log_write(ns_g_lctx, \ NS_LOGCATEGORY_GENERAL, \ NS_LOGMODULE_SERVER, \ ISC_LOG_ERROR, \ "%s '%s': %s", msg, file, \ isc_result_totext(result)); \ goto cleanup; \ } \ } while (0) \ #define CHECKFATAL(op, msg) \ do { result = (op); \ if (result != ISC_R_SUCCESS) \ fatal(msg, result); \ } while (0) \ /*% * Maximum ADB size for views that share a cache. Use this limit to suppress * the total of memory footprint, which should be the main reason for sharing * a cache. Only effective when a finite max-cache-size is specified. * This is currently defined to be 8MB. */ #define MAX_ADB_SIZE_FOR_CACHESHARE 8388608U struct ns_dispatch { isc_sockaddr_t addr; unsigned int dispatchgen; dns_dispatch_t *dispatch; ISC_LINK(struct ns_dispatch) link; }; struct ns_cache { dns_cache_t *cache; dns_view_t *primaryview; isc_boolean_t needflush; isc_boolean_t adbsizeadjusted; dns_rdataclass_t rdclass; ISC_LINK(ns_cache_t) link; }; struct dumpcontext { isc_mem_t *mctx; isc_boolean_t dumpcache; isc_boolean_t dumpzones; isc_boolean_t dumpadb; isc_boolean_t dumpbad; isc_boolean_t dumpfail; FILE *fp; ISC_LIST(struct viewlistentry) viewlist; struct viewlistentry *view; struct zonelistentry *zone; dns_dumpctx_t *mdctx; dns_db_t *db; dns_db_t *cache; isc_task_t *task; dns_dbversion_t *version; }; struct viewlistentry { dns_view_t *view; ISC_LINK(struct viewlistentry) link; ISC_LIST(struct zonelistentry) zonelist; }; struct zonelistentry { dns_zone_t *zone; ISC_LINK(struct zonelistentry) link; }; /*% * Configuration context to retain for each view that allows * new zones to be added at runtime. */ typedef struct ns_cfgctx { isc_mem_t * mctx; cfg_parser_t * conf_parser; cfg_parser_t * add_parser; cfg_obj_t * config; cfg_obj_t * vconfig; cfg_obj_t * nzf_config; cfg_aclconfctx_t * actx; } ns_cfgctx_t; /*% * A function to write out added-zone configuration to the new_zone_file * specified in 'view'. Maybe called by delete_zoneconf(). */ typedef isc_result_t (*nzfwriter_t)(const cfg_obj_t *config, dns_view_t *view); /*% * Holds state information for the initial zone loading process. * Uses the isc_refcount structure to count the number of views * with pending zone loads, dereferencing as each view finishes. */ typedef struct { ns_server_t *server; isc_boolean_t reconfig; isc_refcount_t refs; } ns_zoneload_t; typedef struct { ns_server_t *server; } catz_cb_data_t; typedef struct catz_chgzone_event { ISC_EVENT_COMMON(struct catz_chgzone_event); dns_catz_entry_t *entry; dns_catz_zone_t *origin; dns_view_t *view; catz_cb_data_t *cbd; isc_boolean_t mod; } catz_chgzone_event_t; /* * These zones should not leak onto the Internet. */ const char *empty_zones[] = { /* RFC 1918 */ "10.IN-ADDR.ARPA", "16.172.IN-ADDR.ARPA", "17.172.IN-ADDR.ARPA", "18.172.IN-ADDR.ARPA", "19.172.IN-ADDR.ARPA", "20.172.IN-ADDR.ARPA", "21.172.IN-ADDR.ARPA", "22.172.IN-ADDR.ARPA", "23.172.IN-ADDR.ARPA", "24.172.IN-ADDR.ARPA", "25.172.IN-ADDR.ARPA", "26.172.IN-ADDR.ARPA", "27.172.IN-ADDR.ARPA", "28.172.IN-ADDR.ARPA", "29.172.IN-ADDR.ARPA", "30.172.IN-ADDR.ARPA", "31.172.IN-ADDR.ARPA", "168.192.IN-ADDR.ARPA", /* RFC 6598 */ "64.100.IN-ADDR.ARPA", "65.100.IN-ADDR.ARPA", "66.100.IN-ADDR.ARPA", "67.100.IN-ADDR.ARPA", "68.100.IN-ADDR.ARPA", "69.100.IN-ADDR.ARPA", "70.100.IN-ADDR.ARPA", "71.100.IN-ADDR.ARPA", "72.100.IN-ADDR.ARPA", "73.100.IN-ADDR.ARPA", "74.100.IN-ADDR.ARPA", "75.100.IN-ADDR.ARPA", "76.100.IN-ADDR.ARPA", "77.100.IN-ADDR.ARPA", "78.100.IN-ADDR.ARPA", "79.100.IN-ADDR.ARPA", "80.100.IN-ADDR.ARPA", "81.100.IN-ADDR.ARPA", "82.100.IN-ADDR.ARPA", "83.100.IN-ADDR.ARPA", "84.100.IN-ADDR.ARPA", "85.100.IN-ADDR.ARPA", "86.100.IN-ADDR.ARPA", "87.100.IN-ADDR.ARPA", "88.100.IN-ADDR.ARPA", "89.100.IN-ADDR.ARPA", "90.100.IN-ADDR.ARPA", "91.100.IN-ADDR.ARPA", "92.100.IN-ADDR.ARPA", "93.100.IN-ADDR.ARPA", "94.100.IN-ADDR.ARPA", "95.100.IN-ADDR.ARPA", "96.100.IN-ADDR.ARPA", "97.100.IN-ADDR.ARPA", "98.100.IN-ADDR.ARPA", "99.100.IN-ADDR.ARPA", "100.100.IN-ADDR.ARPA", "101.100.IN-ADDR.ARPA", "102.100.IN-ADDR.ARPA", "103.100.IN-ADDR.ARPA", "104.100.IN-ADDR.ARPA", "105.100.IN-ADDR.ARPA", "106.100.IN-ADDR.ARPA", "107.100.IN-ADDR.ARPA", "108.100.IN-ADDR.ARPA", "109.100.IN-ADDR.ARPA", "110.100.IN-ADDR.ARPA", "111.100.IN-ADDR.ARPA", "112.100.IN-ADDR.ARPA", "113.100.IN-ADDR.ARPA", "114.100.IN-ADDR.ARPA", "115.100.IN-ADDR.ARPA", "116.100.IN-ADDR.ARPA", "117.100.IN-ADDR.ARPA", "118.100.IN-ADDR.ARPA", "119.100.IN-ADDR.ARPA", "120.100.IN-ADDR.ARPA", "121.100.IN-ADDR.ARPA", "122.100.IN-ADDR.ARPA", "123.100.IN-ADDR.ARPA", "124.100.IN-ADDR.ARPA", "125.100.IN-ADDR.ARPA", "126.100.IN-ADDR.ARPA", "127.100.IN-ADDR.ARPA", /* RFC 5735 and RFC 5737 */ "0.IN-ADDR.ARPA", /* THIS NETWORK */ "127.IN-ADDR.ARPA", /* LOOPBACK */ "254.169.IN-ADDR.ARPA", /* LINK LOCAL */ "2.0.192.IN-ADDR.ARPA", /* TEST NET */ "100.51.198.IN-ADDR.ARPA", /* TEST NET 2 */ "113.0.203.IN-ADDR.ARPA", /* TEST NET 3 */ "255.255.255.255.IN-ADDR.ARPA", /* BROADCAST */ /* Local IPv6 Unicast Addresses */ "0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.IP6.ARPA", "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.IP6.ARPA", /* LOCALLY ASSIGNED LOCAL ADDRESS SCOPE */ "D.F.IP6.ARPA", "8.E.F.IP6.ARPA", /* LINK LOCAL */ "9.E.F.IP6.ARPA", /* LINK LOCAL */ "A.E.F.IP6.ARPA", /* LINK LOCAL */ "B.E.F.IP6.ARPA", /* LINK LOCAL */ /* Example Prefix, RFC 3849. */ "8.B.D.0.1.0.0.2.IP6.ARPA", /* RFC 7534 */ "EMPTY.AS112.ARPA", NULL }; ISC_PLATFORM_NORETURN_PRE static void fatal(const char *msg, isc_result_t result) ISC_PLATFORM_NORETURN_POST; static void ns_server_reload(isc_task_t *task, isc_event_t *event); static isc_result_t ns_listenelt_fromconfig(const cfg_obj_t *listener, const cfg_obj_t *config, cfg_aclconfctx_t *actx, isc_mem_t *mctx, isc_uint16_t family, ns_listenelt_t **target); static isc_result_t ns_listenlist_fromconfig(const cfg_obj_t *listenlist, const cfg_obj_t *config, cfg_aclconfctx_t *actx, isc_mem_t *mctx, isc_uint16_t family, ns_listenlist_t **target); static isc_result_t configure_forward(const cfg_obj_t *config, dns_view_t *view, dns_name_t *origin, const cfg_obj_t *forwarders, const cfg_obj_t *forwardtype); static isc_result_t configure_alternates(const cfg_obj_t *config, dns_view_t *view, const cfg_obj_t *alternates); static isc_result_t configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig, const cfg_obj_t *vconfig, isc_mem_t *mctx, dns_view_t *view, dns_viewlist_t *viewlist, cfg_aclconfctx_t *aclconf, isc_boolean_t added, isc_boolean_t old_rpz_ok, isc_boolean_t modify); static isc_result_t configure_newzones(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig, isc_mem_t *mctx, cfg_aclconfctx_t *actx); static isc_result_t add_keydata_zone(dns_view_t *view, const char *directory, isc_mem_t *mctx); static void end_reserved_dispatches(ns_server_t *server, isc_boolean_t all); static void newzone_cfgctx_destroy(void **cfgp); static inline isc_result_t putstr(isc_buffer_t **b, const char *str); static isc_result_t putmem(isc_buffer_t **b, const char *str, size_t len); static isc_result_t putuint8(isc_buffer_t **b, isc_uint8_t val); static inline isc_result_t putnull(isc_buffer_t **b); static int count_zones(const cfg_obj_t *conf); #ifdef HAVE_LMDB static isc_result_t migrate_nzf(dns_view_t *view); static isc_result_t nzd_writable(dns_view_t *view); static isc_result_t nzd_open(dns_view_t *view, unsigned int flags, MDB_txn **txnp, MDB_dbi *dbi); static isc_result_t nzd_env_reopen(dns_view_t *view); static void nzd_env_close(dns_view_t *view); static isc_result_t nzd_close(MDB_txn **txnp, isc_boolean_t commit); static isc_result_t nzd_count(dns_view_t *view, int *countp); #else static isc_result_t nzf_append(dns_view_t *view, const cfg_obj_t *zconfig); #endif /*% * Configure a single view ACL at '*aclp'. Get its configuration from * 'vconfig' (for per-view configuration) and maybe from 'config' */ static isc_result_t configure_view_acl(const cfg_obj_t *vconfig, const cfg_obj_t *config, const cfg_obj_t *gconfig, const char *aclname, const char *acltuplename, cfg_aclconfctx_t *actx, isc_mem_t *mctx, dns_acl_t **aclp) { isc_result_t result; const cfg_obj_t *maps[4]; const cfg_obj_t *aclobj = NULL; int i = 0; if (*aclp != NULL) { dns_acl_detach(aclp); } if (vconfig != NULL) { maps[i++] = cfg_tuple_get(vconfig, "options"); } if (config != NULL) { const cfg_obj_t *options = NULL; (void)cfg_map_get(config, "options", &options); if (options != NULL) { maps[i++] = options; } } if (gconfig != NULL) { const cfg_obj_t *options = NULL; (void)cfg_map_get(gconfig, "options", &options); if (options != NULL) { maps[i++] = options; } } maps[i] = NULL; (void)ns_config_get(maps, aclname, &aclobj); if (aclobj == NULL) { /* * No value available. *aclp == NULL. */ return (ISC_R_SUCCESS); } if (acltuplename != NULL) { /* * If the ACL is given in an optional tuple, retrieve it. * The parser should have ensured that a valid object be * returned. */ aclobj = cfg_tuple_get(aclobj, acltuplename); } result = cfg_acl_fromconfig(aclobj, config, ns_g_lctx, actx, mctx, 0, aclp); return (result); } /*% * Configure a sortlist at '*aclp'. Essentially the same as * configure_view_acl() except it calls cfg_acl_fromconfig with a * nest_level value of 2. */ static isc_result_t configure_view_sortlist(const cfg_obj_t *vconfig, const cfg_obj_t *config, cfg_aclconfctx_t *actx, isc_mem_t *mctx, dns_acl_t **aclp) { isc_result_t result; const cfg_obj_t *maps[3]; const cfg_obj_t *aclobj = NULL; int i = 0; if (*aclp != NULL) dns_acl_detach(aclp); if (vconfig != NULL) maps[i++] = cfg_tuple_get(vconfig, "options"); if (config != NULL) { const cfg_obj_t *options = NULL; (void)cfg_map_get(config, "options", &options); if (options != NULL) maps[i++] = options; } maps[i] = NULL; (void)ns_config_get(maps, "sortlist", &aclobj); if (aclobj == NULL) return (ISC_R_SUCCESS); /* * Use a nest level of 3 for the "top level" of the sortlist; * this means each entry in the top three levels will be stored * as lists of separate, nested ACLs, rather than merged together * into IP tables as is usually done with ACLs. */ result = cfg_acl_fromconfig(aclobj, config, ns_g_lctx, actx, mctx, 3, aclp); return (result); } static isc_result_t configure_view_nametable(const cfg_obj_t *vconfig, const cfg_obj_t *config, const char *confname, const char *conftuplename, isc_mem_t *mctx, dns_rbt_t **rbtp) { isc_result_t result; const cfg_obj_t *maps[3]; const cfg_obj_t *obj = NULL; const cfg_listelt_t *element; int i = 0; dns_fixedname_t fixed; dns_name_t *name; isc_buffer_t b; const char *str; const cfg_obj_t *nameobj; if (*rbtp != NULL) dns_rbt_destroy(rbtp); if (vconfig != NULL) maps[i++] = cfg_tuple_get(vconfig, "options"); if (config != NULL) { const cfg_obj_t *options = NULL; (void)cfg_map_get(config, "options", &options); if (options != NULL) maps[i++] = options; } maps[i] = NULL; (void)ns_config_get(maps, confname, &obj); if (obj == NULL) /* * No value available. *rbtp == NULL. */ return (ISC_R_SUCCESS); if (conftuplename != NULL) { obj = cfg_tuple_get(obj, conftuplename); if (cfg_obj_isvoid(obj)) return (ISC_R_SUCCESS); } result = dns_rbt_create(mctx, NULL, NULL, rbtp); if (result != ISC_R_SUCCESS) return (result); dns_fixedname_init(&fixed); name = dns_fixedname_name(&fixed); for (element = cfg_list_first(obj); element != NULL; element = cfg_list_next(element)) { nameobj = cfg_listelt_value(element); str = cfg_obj_asstring(nameobj); isc_buffer_constinit(&b, str, strlen(str)); isc_buffer_add(&b, strlen(str)); CHECK(dns_name_fromtext(name, &b, dns_rootname, 0, NULL)); /* * We don't need the node data, but need to set dummy data to * avoid a partial match with an empty node. For example, if * we have foo.example.com and bar.example.com, we'd get a match * for baz.example.com, which is not the expected result. * We simply use (void *)1 as the dummy data. */ result = dns_rbt_addname(*rbtp, name, (void *)1); if (result != ISC_R_SUCCESS) { cfg_obj_log(nameobj, ns_g_lctx, ISC_LOG_ERROR, "failed to add %s for %s: %s", str, confname, isc_result_totext(result)); goto cleanup; } } return (result); cleanup: dns_rbt_destroy(rbtp); return (result); } static isc_result_t dstkey_fromconfig(const cfg_obj_t *vconfig, const cfg_obj_t *key, isc_boolean_t managed, dst_key_t **target, isc_mem_t *mctx) { dns_rdataclass_t viewclass; dns_rdata_dnskey_t keystruct; isc_uint32_t flags, proto, alg; const char *keystr, *keynamestr; unsigned char keydata[4096]; isc_buffer_t keydatabuf; unsigned char rrdata[4096]; isc_buffer_t rrdatabuf; isc_region_t r; dns_fixedname_t fkeyname; dns_name_t *keyname; isc_buffer_t namebuf; isc_result_t result; dst_key_t *dstkey = NULL; INSIST(target != NULL && *target == NULL); flags = cfg_obj_asuint32(cfg_tuple_get(key, "flags")); proto = cfg_obj_asuint32(cfg_tuple_get(key, "protocol")); alg = cfg_obj_asuint32(cfg_tuple_get(key, "algorithm")); keyname = dns_fixedname_name(&fkeyname); keynamestr = cfg_obj_asstring(cfg_tuple_get(key, "name")); if (managed) { const char *initmethod; initmethod = cfg_obj_asstring(cfg_tuple_get(key, "init")); if (strcasecmp(initmethod, "initial-key") != 0) { cfg_obj_log(key, ns_g_lctx, ISC_LOG_ERROR, "managed key '%s': " "invalid initialization method '%s'", keynamestr, initmethod); result = ISC_R_FAILURE; goto cleanup; } } if (vconfig == NULL) viewclass = dns_rdataclass_in; else { const cfg_obj_t *classobj = cfg_tuple_get(vconfig, "class"); CHECK(ns_config_getclass(classobj, dns_rdataclass_in, &viewclass)); } keystruct.common.rdclass = viewclass; keystruct.common.rdtype = dns_rdatatype_dnskey; /* * The key data in keystruct is not dynamically allocated. */ keystruct.mctx = NULL; ISC_LINK_INIT(&keystruct.common, link); if (flags > 0xffff) CHECKM(ISC_R_RANGE, "key flags"); if (proto > 0xff) CHECKM(ISC_R_RANGE, "key protocol"); if (alg > 0xff) CHECKM(ISC_R_RANGE, "key algorithm"); keystruct.flags = (isc_uint16_t)flags; keystruct.protocol = (isc_uint8_t)proto; keystruct.algorithm = (isc_uint8_t)alg; isc_buffer_init(&keydatabuf, keydata, sizeof(keydata)); isc_buffer_init(&rrdatabuf, rrdata, sizeof(rrdata)); keystr = cfg_obj_asstring(cfg_tuple_get(key, "key")); CHECK(isc_base64_decodestring(keystr, &keydatabuf)); isc_buffer_usedregion(&keydatabuf, &r); keystruct.datalen = r.length; keystruct.data = r.base; if ((keystruct.algorithm == DST_ALG_RSASHA1 || keystruct.algorithm == DST_ALG_RSAMD5) && r.length > 1 && r.base[0] == 1 && r.base[1] == 3) cfg_obj_log(key, ns_g_lctx, ISC_LOG_WARNING, "%s key '%s' has a weak exponent", managed ? "managed" : "trusted", keynamestr); CHECK(dns_rdata_fromstruct(NULL, keystruct.common.rdclass, keystruct.common.rdtype, &keystruct, &rrdatabuf)); dns_fixedname_init(&fkeyname); isc_buffer_constinit(&namebuf, keynamestr, strlen(keynamestr)); isc_buffer_add(&namebuf, strlen(keynamestr)); CHECK(dns_name_fromtext(keyname, &namebuf, dns_rootname, 0, NULL)); CHECK(dst_key_fromdns(keyname, viewclass, &rrdatabuf, mctx, &dstkey)); *target = dstkey; return (ISC_R_SUCCESS); cleanup: if (result == DST_R_NOCRYPTO) { cfg_obj_log(key, ns_g_lctx, ISC_LOG_ERROR, "ignoring %s key for '%s': no crypto support", managed ? "managed" : "trusted", keynamestr); } else if (result == DST_R_UNSUPPORTEDALG) { cfg_obj_log(key, ns_g_lctx, ISC_LOG_WARNING, "skipping %s key for '%s': %s", managed ? "managed" : "trusted", keynamestr, isc_result_totext(result)); } else { cfg_obj_log(key, ns_g_lctx, ISC_LOG_ERROR, "configuring %s key for '%s': %s", managed ? "managed" : "trusted", keynamestr, isc_result_totext(result)); result = ISC_R_FAILURE; } if (dstkey != NULL) dst_key_free(&dstkey); return (result); } static isc_result_t load_view_keys(const cfg_obj_t *keys, const cfg_obj_t *vconfig, dns_view_t *view, isc_boolean_t managed, dns_name_t *keyname, isc_mem_t *mctx) { const cfg_listelt_t *elt, *elt2; const cfg_obj_t *key, *keylist; dst_key_t *dstkey = NULL; isc_result_t result; dns_keytable_t *secroots = NULL; CHECK(dns_view_getsecroots(view, &secroots)); for (elt = cfg_list_first(keys); elt != NULL; elt = cfg_list_next(elt)) { keylist = cfg_listelt_value(elt); for (elt2 = cfg_list_first(keylist); elt2 != NULL; elt2 = cfg_list_next(elt2)) { key = cfg_listelt_value(elt2); result = dstkey_fromconfig(vconfig, key, managed, &dstkey, mctx); if (result == DST_R_UNSUPPORTEDALG) { result = ISC_R_SUCCESS; continue; } if (result != ISC_R_SUCCESS) goto cleanup; /* * If keyname was specified, we only add that key. */ if (keyname != NULL && !dns_name_equal(keyname, dst_key_name(dstkey))) { dst_key_free(&dstkey); continue; } CHECK(dns_keytable_add(secroots, managed, &dstkey)); } } cleanup: if (dstkey != NULL) dst_key_free(&dstkey); if (secroots != NULL) dns_keytable_detach(&secroots); if (result == DST_R_NOCRYPTO) result = ISC_R_SUCCESS; return (result); } /*% * Check whether a key has been successfully loaded. */ static isc_boolean_t keyloaded(dns_view_t *view, dns_name_t *name) { isc_result_t result; dns_keytable_t *secroots = NULL; dns_keynode_t *keynode = NULL; result = dns_view_getsecroots(view, &secroots); if (result != ISC_R_SUCCESS) return (ISC_FALSE); result = dns_keytable_find(secroots, name, &keynode); if (keynode != NULL) dns_keytable_detachkeynode(secroots, &keynode); if (secroots != NULL) dns_keytable_detach(&secroots); return (ISC_TF(result == ISC_R_SUCCESS)); } /*% * Configure DNSSEC keys for a view. * * The per-view configuration values and the server-global defaults are read * from 'vconfig' and 'config'. */ static isc_result_t configure_view_dnsseckeys(dns_view_t *view, const cfg_obj_t *vconfig, const cfg_obj_t *config, const cfg_obj_t *bindkeys, isc_boolean_t auto_root, isc_mem_t *mctx) { isc_result_t result = ISC_R_SUCCESS; const cfg_obj_t *view_keys = NULL; const cfg_obj_t *global_keys = NULL; const cfg_obj_t *view_managed_keys = NULL; const cfg_obj_t *global_managed_keys = NULL; const cfg_obj_t *maps[4]; const cfg_obj_t *voptions = NULL; const cfg_obj_t *options = NULL; const cfg_obj_t *obj = NULL; const char *directory; isc_boolean_t need_mkey_dir = ISC_FALSE; int i = 0; /* We don't need trust anchors for the _bind view */ if (strcmp(view->name, "_bind") == 0 && view->rdclass == dns_rdataclass_chaos) { return (ISC_R_SUCCESS); } if (vconfig != NULL) { voptions = cfg_tuple_get(vconfig, "options"); if (voptions != NULL) { (void) cfg_map_get(voptions, "trusted-keys", &view_keys); (void) cfg_map_get(voptions, "managed-keys", &view_managed_keys); maps[i++] = voptions; } } if (config != NULL) { (void)cfg_map_get(config, "trusted-keys", &global_keys); (void)cfg_map_get(config, "managed-keys", &global_managed_keys); (void)cfg_map_get(config, "options", &options); if (options != NULL) { maps[i++] = options; } } maps[i++] = ns_g_defaults; maps[i] = NULL; result = dns_view_initsecroots(view, mctx); if (result != ISC_R_SUCCESS) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, "couldn't create keytable"); return (ISC_R_UNEXPECTED); } result = dns_view_initntatable(view, ns_g_taskmgr, ns_g_timermgr); if (result != ISC_R_SUCCESS) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, "couldn't create NTA table"); return (ISC_R_UNEXPECTED); } if (auto_root && view->rdclass == dns_rdataclass_in) { const cfg_obj_t *builtin_keys = NULL; const cfg_obj_t *builtin_managed_keys = NULL; /* * If bind.keys exists and is populated, it overrides * the managed-keys clause hard-coded in ns_g_config. */ if (bindkeys != NULL) { isc_log_write(ns_g_lctx, DNS_LOGCATEGORY_SECURITY, NS_LOGMODULE_SERVER, ISC_LOG_INFO, "obtaining root key for view %s " "from '%s'", view->name, ns_g_server->bindkeysfile); (void)cfg_map_get(bindkeys, "trusted-keys", &builtin_keys); (void)cfg_map_get(bindkeys, "managed-keys", &builtin_managed_keys); if ((builtin_keys == NULL) && (builtin_managed_keys == NULL)) isc_log_write(ns_g_lctx, DNS_LOGCATEGORY_SECURITY, NS_LOGMODULE_SERVER, ISC_LOG_WARNING, "dnssec-validation auto: " "WARNING: root zone key " "not found"); } if ((builtin_keys == NULL) && (builtin_managed_keys == NULL)) { isc_log_write(ns_g_lctx, DNS_LOGCATEGORY_SECURITY, NS_LOGMODULE_SERVER, ISC_LOG_INFO, "using built-in root key for view %s", view->name); (void)cfg_map_get(ns_g_config, "trusted-keys", &builtin_keys); (void)cfg_map_get(ns_g_config, "managed-keys", &builtin_managed_keys); } if (builtin_keys != NULL) CHECK(load_view_keys(builtin_keys, vconfig, view, ISC_FALSE, dns_rootname, mctx)); if (builtin_managed_keys != NULL) CHECK(load_view_keys(builtin_managed_keys, vconfig, view, ISC_TRUE, dns_rootname, mctx)); if (!keyloaded(view, dns_rootname)) { isc_log_write(ns_g_lctx, DNS_LOGCATEGORY_SECURITY, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, "root key not loaded"); result = ISC_R_FAILURE; goto cleanup; } } CHECK(load_view_keys(view_keys, vconfig, view, ISC_FALSE, NULL, mctx)); CHECK(load_view_keys(view_managed_keys, vconfig, view, ISC_TRUE, NULL, mctx)); if (view->rdclass == dns_rdataclass_in) { CHECK(load_view_keys(global_keys, vconfig, view, ISC_FALSE, NULL, mctx)); CHECK(load_view_keys(global_managed_keys, vconfig, view, ISC_TRUE, NULL, mctx)); } /* * Add key zone for managed-keys. */ need_mkey_dir = ISC_TF(auto_root || view_managed_keys != NULL); obj = NULL; (void)ns_config_get(maps, "managed-keys-directory", &obj); directory = (obj != NULL ? cfg_obj_asstring(obj) : NULL); if (directory != NULL) { result = isc_file_isdirectory(directory); } if (result != ISC_R_SUCCESS) { isc_log_write(ns_g_lctx, DNS_LOGCATEGORY_SECURITY, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, "invalid managed-keys-directory %s: %s", directory, isc_result_totext(result)); goto cleanup; } else if (need_mkey_dir && directory != NULL) { if (!isc_file_isdirwritable(directory)) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, "managed-keys-directory '%s' " "is not writable", directory); result = ISC_R_NOPERM; goto cleanup; } } else if (need_mkey_dir) { char cwd[PATH_MAX]; if (getcwd(cwd, sizeof(cwd)) == NULL) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, "unable to retrieve " "current working directory"); result = ISC_R_FAILURE; goto cleanup; } if (!isc_file_isdirwritable(cwd)) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, "working directory '%s' " "is not writable", cwd); result = ISC_R_NOPERM; goto cleanup; } } CHECK(add_keydata_zone(view, directory, ns_g_mctx)); cleanup: return (result); } static isc_result_t mustbesecure(const cfg_obj_t *mbs, dns_resolver_t *resolver) { const cfg_listelt_t *element; const cfg_obj_t *obj; const char *str; dns_fixedname_t fixed; dns_name_t *name; isc_boolean_t value; isc_result_t result; isc_buffer_t b; dns_fixedname_init(&fixed); name = dns_fixedname_name(&fixed); for (element = cfg_list_first(mbs); element != NULL; element = cfg_list_next(element)) { obj = cfg_listelt_value(element); str = cfg_obj_asstring(cfg_tuple_get(obj, "name")); isc_buffer_constinit(&b, str, strlen(str)); isc_buffer_add(&b, strlen(str)); CHECK(dns_name_fromtext(name, &b, dns_rootname, 0, NULL)); value = cfg_obj_asboolean(cfg_tuple_get(obj, "value")); CHECK(dns_resolver_setmustbesecure(resolver, name, value)); } result = ISC_R_SUCCESS; cleanup: return (result); } /*% * Get a dispatch appropriate for the resolver of a given view. */ static isc_result_t get_view_querysource_dispatch(const cfg_obj_t **maps, int af, dns_dispatch_t **dispatchp, isc_dscp_t *dscpp, isc_boolean_t is_firstview) { isc_result_t result = ISC_R_FAILURE; dns_dispatch_t *disp; isc_sockaddr_t sa; unsigned int attrs, attrmask; const cfg_obj_t *obj = NULL; unsigned int maxdispatchbuffers = UDPBUFFERS; isc_dscp_t dscp = -1; switch (af) { case AF_INET: result = ns_config_get(maps, "query-source", &obj); INSIST(result == ISC_R_SUCCESS); break; case AF_INET6: result = ns_config_get(maps, "query-source-v6", &obj); INSIST(result == ISC_R_SUCCESS); break; default: INSIST(0); } sa = *(cfg_obj_assockaddr(obj)); INSIST(isc_sockaddr_pf(&sa) == af); dscp = cfg_obj_getdscp(obj); if (dscp != -1 && dscpp != NULL) *dscpp = dscp; /* * If we don't support this address family, we're done! */ switch (af) { case AF_INET: result = isc_net_probeipv4(); break; case AF_INET6: result = isc_net_probeipv6(); break; default: INSIST(0); } if (result != ISC_R_SUCCESS) return (ISC_R_SUCCESS); /* * Try to find a dispatcher that we can share. */ attrs = 0; attrs |= DNS_DISPATCHATTR_UDP; switch (af) { case AF_INET: attrs |= DNS_DISPATCHATTR_IPV4; break; case AF_INET6: attrs |= DNS_DISPATCHATTR_IPV6; break; } if (isc_sockaddr_getport(&sa) == 0) { attrs |= DNS_DISPATCHATTR_EXCLUSIVE; maxdispatchbuffers = EXCLBUFFERS; } else { INSIST(obj != NULL); if (is_firstview) { cfg_obj_log(obj, ns_g_lctx, ISC_LOG_INFO, "using specific query-source port " "suppresses port randomization and can be " "insecure."); } } attrmask = 0; attrmask |= DNS_DISPATCHATTR_UDP; attrmask |= DNS_DISPATCHATTR_TCP; attrmask |= DNS_DISPATCHATTR_IPV4; attrmask |= DNS_DISPATCHATTR_IPV6; disp = NULL; result = dns_dispatch_getudp(ns_g_dispatchmgr, ns_g_socketmgr, ns_g_taskmgr, &sa, 4096, maxdispatchbuffers, 32768, 16411, 16433, attrs, attrmask, &disp); if (result != ISC_R_SUCCESS) { isc_sockaddr_t any; char buf[ISC_SOCKADDR_FORMATSIZE]; switch (af) { case AF_INET: isc_sockaddr_any(&any); break; case AF_INET6: isc_sockaddr_any6(&any); break; } if (isc_sockaddr_equal(&sa, &any)) return (ISC_R_SUCCESS); isc_sockaddr_format(&sa, buf, sizeof(buf)); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, "could not get query source dispatcher (%s)", buf); return (result); } *dispatchp = disp; return (ISC_R_SUCCESS); } static isc_result_t configure_order(dns_order_t *order, const cfg_obj_t *ent) { dns_rdataclass_t rdclass; dns_rdatatype_t rdtype; const cfg_obj_t *obj; dns_fixedname_t fixed; unsigned int mode = 0; const char *str; isc_buffer_t b; isc_result_t result; isc_boolean_t addroot; result = ns_config_getclass(cfg_tuple_get(ent, "class"), dns_rdataclass_any, &rdclass); if (result != ISC_R_SUCCESS) return (result); result = ns_config_gettype(cfg_tuple_get(ent, "type"), dns_rdatatype_any, &rdtype); if (result != ISC_R_SUCCESS) return (result); obj = cfg_tuple_get(ent, "name"); if (cfg_obj_isstring(obj)) str = cfg_obj_asstring(obj); else str = "*"; addroot = ISC_TF(strcmp(str, "*") == 0); isc_buffer_constinit(&b, str, strlen(str)); isc_buffer_add(&b, strlen(str)); dns_fixedname_init(&fixed); result = dns_name_fromtext(dns_fixedname_name(&fixed), &b, dns_rootname, 0, NULL); if (result != ISC_R_SUCCESS) return (result); obj = cfg_tuple_get(ent, "ordering"); INSIST(cfg_obj_isstring(obj)); str = cfg_obj_asstring(obj); if (!strcasecmp(str, "fixed")) #if DNS_RDATASET_FIXED mode = DNS_RDATASETATTR_FIXEDORDER; #else mode = 0; #endif /* DNS_RDATASET_FIXED */ else if (!strcasecmp(str, "random")) mode = DNS_RDATASETATTR_RANDOMIZE; else if (!strcasecmp(str, "cyclic")) mode = 0; else INSIST(0); /* * "*" should match everything including the root (BIND 8 compat). * As dns_name_matcheswildcard(".", "*.") returns FALSE add a * explicit entry for "." when the name is "*". */ if (addroot) { result = dns_order_add(order, dns_rootname, rdtype, rdclass, mode); if (result != ISC_R_SUCCESS) return (result); } return (dns_order_add(order, dns_fixedname_name(&fixed), rdtype, rdclass, mode)); } static isc_result_t configure_peer(const cfg_obj_t *cpeer, isc_mem_t *mctx, dns_peer_t **peerp) { isc_netaddr_t na; dns_peer_t *peer; const cfg_obj_t *obj; const char *str; isc_result_t result; unsigned int prefixlen; cfg_obj_asnetprefix(cfg_map_getname(cpeer), &na, &prefixlen); peer = NULL; result = dns_peer_newprefix(mctx, &na, prefixlen, &peer); if (result != ISC_R_SUCCESS) return (result); obj = NULL; (void)cfg_map_get(cpeer, "bogus", &obj); if (obj != NULL) CHECK(dns_peer_setbogus(peer, cfg_obj_asboolean(obj))); obj = NULL; (void)cfg_map_get(cpeer, "provide-ixfr", &obj); if (obj != NULL) CHECK(dns_peer_setprovideixfr(peer, cfg_obj_asboolean(obj))); obj = NULL; (void)cfg_map_get(cpeer, "request-expire", &obj); if (obj != NULL) CHECK(dns_peer_setrequestexpire(peer, cfg_obj_asboolean(obj))); obj = NULL; (void)cfg_map_get(cpeer, "request-ixfr", &obj); if (obj != NULL) CHECK(dns_peer_setrequestixfr(peer, cfg_obj_asboolean(obj))); obj = NULL; (void)cfg_map_get(cpeer, "request-nsid", &obj); if (obj != NULL) CHECK(dns_peer_setrequestnsid(peer, cfg_obj_asboolean(obj))); obj = NULL; (void)cfg_map_get(cpeer, "send-cookie", &obj); if (obj != NULL) CHECK(dns_peer_setsendcookie(peer, cfg_obj_asboolean(obj))); obj = NULL; (void)cfg_map_get(cpeer, "edns", &obj); if (obj != NULL) CHECK(dns_peer_setsupportedns(peer, cfg_obj_asboolean(obj))); obj = NULL; (void)cfg_map_get(cpeer, "edns-udp-size", &obj); if (obj != NULL) { isc_uint32_t udpsize = cfg_obj_asuint32(obj); if (udpsize < 512) udpsize = 512; if (udpsize > 4096) udpsize = 4096; CHECK(dns_peer_setudpsize(peer, (isc_uint16_t)udpsize)); } obj = NULL; (void)cfg_map_get(cpeer, "edns-version", &obj); if (obj != NULL) { isc_uint32_t ednsversion = cfg_obj_asuint32(obj); if (ednsversion > 255) ednsversion = 255; CHECK(dns_peer_setednsversion(peer, (isc_uint8_t)ednsversion)); } obj = NULL; (void)cfg_map_get(cpeer, "max-udp-size", &obj); if (obj != NULL) { isc_uint32_t udpsize = cfg_obj_asuint32(obj); if (udpsize < 512) udpsize = 512; if (udpsize > 4096) udpsize = 4096; CHECK(dns_peer_setmaxudp(peer, (isc_uint16_t)udpsize)); } obj = NULL; (void)cfg_map_get(cpeer, "tcp-only", &obj); if (obj != NULL) CHECK(dns_peer_setforcetcp(peer, cfg_obj_asboolean(obj))); obj = NULL; (void)cfg_map_get(cpeer, "transfers", &obj); if (obj != NULL) CHECK(dns_peer_settransfers(peer, cfg_obj_asuint32(obj))); obj = NULL; (void)cfg_map_get(cpeer, "transfer-format", &obj); if (obj != NULL) { str = cfg_obj_asstring(obj); if (strcasecmp(str, "many-answers") == 0) CHECK(dns_peer_settransferformat(peer, dns_many_answers)); else if (strcasecmp(str, "one-answer") == 0) CHECK(dns_peer_settransferformat(peer, dns_one_answer)); else INSIST(0); } obj = NULL; (void)cfg_map_get(cpeer, "keys", &obj); if (obj != NULL) { result = dns_peer_setkeybycharp(peer, cfg_obj_asstring(obj)); if (result != ISC_R_SUCCESS) goto cleanup; } obj = NULL; if (na.family == AF_INET) (void)cfg_map_get(cpeer, "transfer-source", &obj); else (void)cfg_map_get(cpeer, "transfer-source-v6", &obj); if (obj != NULL) { result = dns_peer_settransfersource(peer, cfg_obj_assockaddr(obj)); if (result != ISC_R_SUCCESS) goto cleanup; result = dns_peer_settransferdscp(peer, cfg_obj_getdscp(obj)); if (result != ISC_R_SUCCESS) goto cleanup; ns_add_reserved_dispatch(ns_g_server, cfg_obj_assockaddr(obj)); } obj = NULL; if (na.family == AF_INET) (void)cfg_map_get(cpeer, "notify-source", &obj); else (void)cfg_map_get(cpeer, "notify-source-v6", &obj); if (obj != NULL) { result = dns_peer_setnotifysource(peer, cfg_obj_assockaddr(obj)); if (result != ISC_R_SUCCESS) goto cleanup; result = dns_peer_setnotifydscp(peer, cfg_obj_getdscp(obj)); if (result != ISC_R_SUCCESS) goto cleanup; ns_add_reserved_dispatch(ns_g_server, cfg_obj_assockaddr(obj)); } obj = NULL; if (na.family == AF_INET) (void)cfg_map_get(cpeer, "query-source", &obj); else (void)cfg_map_get(cpeer, "query-source-v6", &obj); if (obj != NULL) { result = dns_peer_setquerysource(peer, cfg_obj_assockaddr(obj)); if (result != ISC_R_SUCCESS) goto cleanup; result = dns_peer_setquerydscp(peer, cfg_obj_getdscp(obj)); if (result != ISC_R_SUCCESS) goto cleanup; ns_add_reserved_dispatch(ns_g_server, cfg_obj_assockaddr(obj)); } *peerp = peer; return (ISC_R_SUCCESS); cleanup: dns_peer_detach(&peer); return (result); } #ifdef HAVE_DLOPEN static isc_result_t configure_dyndb(const cfg_obj_t *dyndb, isc_mem_t *mctx, const dns_dyndbctx_t *dctx) { isc_result_t result = ISC_R_SUCCESS; const cfg_obj_t *obj; const char *name, *library; /* Get the name of the dyndb instance and the library path . */ name = cfg_obj_asstring(cfg_tuple_get(dyndb, "name")); library = cfg_obj_asstring(cfg_tuple_get(dyndb, "library")); obj = cfg_tuple_get(dyndb, "parameters"); if (obj != NULL) result = dns_dyndb_load(library, name, cfg_obj_asstring(obj), cfg_obj_file(obj), cfg_obj_line(obj), mctx, dctx); if (result != ISC_R_SUCCESS) isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, "dynamic database '%s' configuration failed: %s", name, isc_result_totext(result)); return (result); } #endif static isc_result_t disable_algorithms(const cfg_obj_t *disabled, dns_resolver_t *resolver) { isc_result_t result; const cfg_obj_t *algorithms; const cfg_listelt_t *element; const char *str; dns_fixedname_t fixed; dns_name_t *name; isc_buffer_t b; dns_fixedname_init(&fixed); name = dns_fixedname_name(&fixed); str = cfg_obj_asstring(cfg_tuple_get(disabled, "name")); isc_buffer_constinit(&b, str, strlen(str)); isc_buffer_add(&b, strlen(str)); CHECK(dns_name_fromtext(name, &b, dns_rootname, 0, NULL)); algorithms = cfg_tuple_get(disabled, "algorithms"); for (element = cfg_list_first(algorithms); element != NULL; element = cfg_list_next(element)) { isc_textregion_t r; dns_secalg_t alg; DE_CONST(cfg_obj_asstring(cfg_listelt_value(element)), r.base); r.length = strlen(r.base); result = dns_secalg_fromtext(&alg, &r); if (result != ISC_R_SUCCESS) { isc_uint8_t ui; result = isc_parse_uint8(&ui, r.base, 10); alg = ui; } if (result != ISC_R_SUCCESS) { cfg_obj_log(cfg_listelt_value(element), ns_g_lctx, ISC_LOG_ERROR, "invalid algorithm"); CHECK(result); } CHECK(dns_resolver_disable_algorithm(resolver, name, alg)); } cleanup: return (result); } static isc_result_t disable_ds_digests(const cfg_obj_t *disabled, dns_resolver_t *resolver) { isc_result_t result; const cfg_obj_t *digests; const cfg_listelt_t *element; const char *str; dns_fixedname_t fixed; dns_name_t *name; isc_buffer_t b; dns_fixedname_init(&fixed); name = dns_fixedname_name(&fixed); str = cfg_obj_asstring(cfg_tuple_get(disabled, "name")); isc_buffer_constinit(&b, str, strlen(str)); isc_buffer_add(&b, strlen(str)); CHECK(dns_name_fromtext(name, &b, dns_rootname, 0, NULL)); digests = cfg_tuple_get(disabled, "digests"); for (element = cfg_list_first(digests); element != NULL; element = cfg_list_next(element)) { isc_textregion_t r; dns_dsdigest_t digest; DE_CONST(cfg_obj_asstring(cfg_listelt_value(element)), r.base); r.length = strlen(r.base); /* disable_ds_digests handles numeric values. */ result = dns_dsdigest_fromtext(&digest, &r); if (result != ISC_R_SUCCESS) { cfg_obj_log(cfg_listelt_value(element), ns_g_lctx, ISC_LOG_ERROR, "invalid algorithm"); CHECK(result); } CHECK(dns_resolver_disable_ds_digest(resolver, name, digest)); } cleanup: return (result); } static isc_boolean_t on_disable_list(const cfg_obj_t *disablelist, dns_name_t *zonename) { const cfg_listelt_t *element; dns_fixedname_t fixed; dns_name_t *name; isc_result_t result; const cfg_obj_t *value; const char *str; isc_buffer_t b; dns_fixedname_init(&fixed); name = dns_fixedname_name(&fixed); for (element = cfg_list_first(disablelist); element != NULL; element = cfg_list_next(element)) { value = cfg_listelt_value(element); str = cfg_obj_asstring(value); isc_buffer_constinit(&b, str, strlen(str)); isc_buffer_add(&b, strlen(str)); result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL); RUNTIME_CHECK(result == ISC_R_SUCCESS); if (dns_name_equal(name, zonename)) return (ISC_TRUE); } return (ISC_FALSE); } static isc_result_t check_dbtype(dns_zone_t *zone, unsigned int dbtypec, const char **dbargv, isc_mem_t *mctx) { char **argv = NULL; unsigned int i; isc_result_t result = ISC_R_SUCCESS; CHECK(dns_zone_getdbtype(zone, &argv, mctx)); /* * Check that all the arguments match. */ for (i = 0; i < dbtypec; i++) if (argv[i] == NULL || strcmp(argv[i], dbargv[i]) != 0) CHECK(ISC_R_FAILURE); /* * Check that there are not extra arguments. */ if (i == dbtypec && argv[i] != NULL) result = ISC_R_FAILURE; cleanup: isc_mem_free(mctx, argv); return (result); } static isc_result_t setquerystats(dns_zone_t *zone, isc_mem_t *mctx, dns_zonestat_level_t level) { isc_result_t result; isc_stats_t *zoneqrystats; dns_zone_setstatlevel(zone, level); zoneqrystats = NULL; if (level == dns_zonestat_full) { result = isc_stats_create(mctx, &zoneqrystats, dns_nsstatscounter_max); if (result != ISC_R_SUCCESS) return (result); } dns_zone_setrequeststats(zone, zoneqrystats); if (zoneqrystats != NULL) isc_stats_detach(&zoneqrystats); return (ISC_R_SUCCESS); } static ns_cache_t * cachelist_find(ns_cachelist_t *cachelist, const char *cachename, dns_rdataclass_t rdclass) { ns_cache_t *nsc; for (nsc = ISC_LIST_HEAD(*cachelist); nsc != NULL; nsc = ISC_LIST_NEXT(nsc, link)) { if (nsc->rdclass == rdclass && strcmp(dns_cache_getname(nsc->cache), cachename) == 0) return (nsc); } return (NULL); } static isc_boolean_t cache_reusable(dns_view_t *originview, dns_view_t *view, isc_boolean_t new_zero_no_soattl) { if (originview->rdclass != view->rdclass || originview->checknames != view->checknames || dns_resolver_getzeronosoattl(originview->resolver) != new_zero_no_soattl || originview->acceptexpired != view->acceptexpired || originview->enablevalidation != view->enablevalidation || originview->maxcachettl != view->maxcachettl || originview->maxncachettl != view->maxncachettl) { return (ISC_FALSE); } return (ISC_TRUE); } static isc_boolean_t cache_sharable(dns_view_t *originview, dns_view_t *view, isc_boolean_t new_zero_no_soattl, unsigned int new_cleaning_interval, isc_uint64_t new_max_cache_size) { /* * If the cache cannot even reused for the same view, it cannot be * shared with other views. */ if (!cache_reusable(originview, view, new_zero_no_soattl)) return (ISC_FALSE); /* * Check other cache related parameters that must be consistent among * the sharing views. */ if (dns_cache_getcleaninginterval(originview->cache) != new_cleaning_interval || dns_cache_getcachesize(originview->cache) != new_max_cache_size) { return (ISC_FALSE); } return (ISC_TRUE); } /* * Callback from DLZ configure when the driver sets up a writeable zone */ static isc_result_t dlzconfigure_callback(dns_view_t *view, dns_dlzdb_t *dlzdb, dns_zone_t *zone) { dns_name_t *origin = dns_zone_getorigin(zone); dns_rdataclass_t zclass = view->rdclass; isc_result_t result; result = dns_zonemgr_managezone(ns_g_server->zonemgr, zone); if (result != ISC_R_SUCCESS) return (result); dns_zone_setstats(zone, ns_g_server->zonestats); return (ns_zone_configure_writeable_dlz(dlzdb, zone, zclass, origin)); } static isc_result_t dns64_reverse(dns_view_t *view, isc_mem_t *mctx, isc_netaddr_t *na, unsigned int prefixlen, const char *server, const char *contact) { char reverse[48+sizeof("ip6.arpa.")] = { 0 }; char buf[sizeof("x.x.")]; const char *dns64_dbtype[4] = { "_dns64", "dns64", ".", "." }; const char *sep = ": view "; const char *viewname = view->name; const unsigned char *s6; dns_fixedname_t fixed; dns_name_t *name; dns_zone_t *zone = NULL; int dns64_dbtypec = 4; isc_buffer_t b; isc_result_t result; REQUIRE(prefixlen == 32 || prefixlen == 40 || prefixlen == 48 || prefixlen == 56 || prefixlen == 64 || prefixlen == 96); if (!strcmp(viewname, "_default")) { sep = ""; viewname = ""; } /* * Construct the reverse name of the zone. */ s6 = na->type.in6.s6_addr; while (prefixlen > 0) { prefixlen -= 8; snprintf(buf, sizeof(buf), "%x.%x.", s6[prefixlen/8] & 0xf, (s6[prefixlen/8] >> 4) & 0xf); strlcat(reverse, buf, sizeof(reverse)); } strlcat(reverse, "ip6.arpa.", sizeof(reverse)); /* * Create the actual zone. */ if (server != NULL) dns64_dbtype[2] = server; if (contact != NULL) dns64_dbtype[3] = contact; dns_fixedname_init(&fixed); name = dns_fixedname_name(&fixed); isc_buffer_constinit(&b, reverse, strlen(reverse)); isc_buffer_add(&b, strlen(reverse)); CHECK(dns_name_fromtext(name, &b, dns_rootname, 0, NULL)); CHECK(dns_zone_create(&zone, mctx)); CHECK(dns_zone_setorigin(zone, name)); dns_zone_setview(zone, view); CHECK(dns_zonemgr_managezone(ns_g_server->zonemgr, zone)); dns_zone_setclass(zone, view->rdclass); dns_zone_settype(zone, dns_zone_master); dns_zone_setstats(zone, ns_g_server->zonestats); CHECK(dns_zone_setdbtype(zone, dns64_dbtypec, dns64_dbtype)); if (view->queryacl != NULL) dns_zone_setqueryacl(zone, view->queryacl); if (view->queryonacl != NULL) dns_zone_setqueryonacl(zone, view->queryonacl); dns_zone_setdialup(zone, dns_dialuptype_no); dns_zone_setnotifytype(zone, dns_notifytype_no); dns_zone_setoption(zone, DNS_ZONEOPT_NOCHECKNS, ISC_TRUE); CHECK(setquerystats(zone, mctx, dns_zonestat_none)); /* XXXMPA */ CHECK(dns_view_addzone(view, zone)); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_INFO, "dns64 reverse zone%s%s: %s", sep, viewname, reverse); cleanup: if (zone != NULL) dns_zone_detach(&zone); return (result); } static isc_result_t configure_rpz_name(dns_view_t *view, const cfg_obj_t *obj, dns_name_t *name, const char *str, const char *msg) { isc_result_t result; result = dns_name_fromstring(name, str, DNS_NAME_DOWNCASE, view->mctx); if (result != ISC_R_SUCCESS) cfg_obj_log(obj, ns_g_lctx, DNS_RPZ_ERROR_LEVEL, "invalid %s '%s'", msg, str); return (result); } static isc_result_t configure_rpz_name2(dns_view_t *view, const cfg_obj_t *obj, dns_name_t *name, const char *str, const dns_name_t *origin) { isc_result_t result; result = dns_name_fromstring2(name, str, origin, DNS_NAME_DOWNCASE, view->mctx); if (result != ISC_R_SUCCESS) cfg_obj_log(obj, ns_g_lctx, DNS_RPZ_ERROR_LEVEL, "invalid zone '%s'", str); return (result); } static isc_result_t configure_rpz_zone(dns_view_t *view, const cfg_listelt_t *element, isc_boolean_t recursive_only_def, dns_ttl_t ttl_def, const dns_rpz_zone_t *old, isc_boolean_t *old_rpz_okp) { const cfg_obj_t *rpz_obj, *obj; const char *str; dns_rpz_zone_t *new; isc_result_t result; dns_rpz_num_t rpz_num; REQUIRE(old != NULL || !*old_rpz_okp); rpz_obj = cfg_listelt_value(element); if (view->rpzs->p.num_zones >= DNS_RPZ_MAX_ZONES) { cfg_obj_log(rpz_obj, ns_g_lctx, DNS_RPZ_ERROR_LEVEL, "limit of %d response policy zones exceeded", DNS_RPZ_MAX_ZONES); return (ISC_R_FAILURE); } new = isc_mem_get(view->rpzs->mctx, sizeof(*new)); if (new == NULL) { cfg_obj_log(rpz_obj, ns_g_lctx, DNS_RPZ_ERROR_LEVEL, "no memory for response policy zones"); return (ISC_R_NOMEMORY); } memset(new, 0, sizeof(*new)); result = isc_refcount_init(&new->refs, 1); if (result != ISC_R_SUCCESS) { isc_mem_put(view->rpzs->mctx, new, sizeof(*new)); return (result); } dns_name_init(&new->origin, NULL); dns_name_init(&new->client_ip, NULL); dns_name_init(&new->ip, NULL); dns_name_init(&new->nsdname, NULL); dns_name_init(&new->nsip, NULL); dns_name_init(&new->passthru, NULL); dns_name_init(&new->drop, NULL); dns_name_init(&new->tcp_only, NULL); dns_name_init(&new->cname, NULL); new->num = view->rpzs->p.num_zones++; view->rpzs->zones[new->num] = new; obj = cfg_tuple_get(rpz_obj, "recursive-only"); if (cfg_obj_isvoid(obj) ? recursive_only_def : cfg_obj_asboolean(obj)) { view->rpzs->p.no_rd_ok &= ~DNS_RPZ_ZBIT(new->num); } else { view->rpzs->p.no_rd_ok |= DNS_RPZ_ZBIT(new->num); } obj = cfg_tuple_get(rpz_obj, "log"); if (!cfg_obj_isvoid(obj) && !cfg_obj_asboolean(obj)) { view->rpzs->p.no_log |= DNS_RPZ_ZBIT(new->num); } else { view->rpzs->p.no_log &= ~DNS_RPZ_ZBIT(new->num); } obj = cfg_tuple_get(rpz_obj, "max-policy-ttl"); if (cfg_obj_isuint32(obj)) { new->max_policy_ttl = cfg_obj_asuint32(obj); } else { new->max_policy_ttl = ttl_def; } if (*old_rpz_okp && new->max_policy_ttl != old->max_policy_ttl) *old_rpz_okp = ISC_FALSE; str = cfg_obj_asstring(cfg_tuple_get(rpz_obj, "zone name")); result = configure_rpz_name(view, rpz_obj, &new->origin, str, "zone"); if (result != ISC_R_SUCCESS) return (result); if (dns_name_equal(&new->origin, dns_rootname)) { cfg_obj_log(rpz_obj, ns_g_lctx, DNS_RPZ_ERROR_LEVEL, "invalid zone name '%s'", str); return (DNS_R_EMPTYLABEL); } for (rpz_num = 0; rpz_num < view->rpzs->p.num_zones-1; ++rpz_num) { if (dns_name_equal(&view->rpzs->zones[rpz_num]->origin, &new->origin)) { cfg_obj_log(rpz_obj, ns_g_lctx, DNS_RPZ_ERROR_LEVEL, "duplicate '%s'", str); result = DNS_R_DUPLICATE; return (result); } } if (*old_rpz_okp && !dns_name_equal(&old->origin, &new->origin)) *old_rpz_okp = ISC_FALSE; result = configure_rpz_name2(view, rpz_obj, &new->client_ip, DNS_RPZ_CLIENT_IP_ZONE, &new->origin); if (result != ISC_R_SUCCESS) return (result); result = configure_rpz_name2(view, rpz_obj, &new->ip, DNS_RPZ_IP_ZONE, &new->origin); if (result != ISC_R_SUCCESS) return (result); result = configure_rpz_name2(view, rpz_obj, &new->nsdname, DNS_RPZ_NSDNAME_ZONE, &new->origin); if (result != ISC_R_SUCCESS) return (result); result = configure_rpz_name2(view, rpz_obj, &new->nsip, DNS_RPZ_NSIP_ZONE, &new->origin); if (result != ISC_R_SUCCESS) return (result); result = configure_rpz_name(view, rpz_obj, &new->passthru, DNS_RPZ_PASSTHRU_NAME, "name"); if (result != ISC_R_SUCCESS) return (result); result = configure_rpz_name(view, rpz_obj, &new->drop, DNS_RPZ_DROP_NAME, "name"); if (result != ISC_R_SUCCESS) return (result); result = configure_rpz_name(view, rpz_obj, &new->tcp_only, DNS_RPZ_TCP_ONLY_NAME, "name"); if (result != ISC_R_SUCCESS) return (result); obj = cfg_tuple_get(rpz_obj, "policy"); if (cfg_obj_isvoid(obj)) { new->policy = DNS_RPZ_POLICY_GIVEN; } else { str = cfg_obj_asstring(cfg_tuple_get(obj, "policy name")); new->policy = dns_rpz_str2policy(str); INSIST(new->policy != DNS_RPZ_POLICY_ERROR); if (new->policy == DNS_RPZ_POLICY_CNAME) { str = cfg_obj_asstring(cfg_tuple_get(obj, "cname")); result = configure_rpz_name(view, rpz_obj, &new->cname, str, "cname"); if (result != ISC_R_SUCCESS) return (result); } } if (*old_rpz_okp && (new->policy != old->policy || !dns_name_equal(&old->cname, &new->cname))) *old_rpz_okp = ISC_FALSE; return (ISC_R_SUCCESS); } static isc_result_t configure_rpz(dns_view_t *view, const cfg_obj_t *rpz_obj, isc_boolean_t *old_rpz_okp) { const cfg_listelt_t *zone_element; const cfg_obj_t *sub_obj; isc_boolean_t recursive_only_def; dns_ttl_t ttl_def; dns_rpz_zones_t *new; const dns_rpz_zones_t *old; dns_view_t *pview; const dns_rpz_zone_t *old_zone; isc_result_t result; int i; *old_rpz_okp = ISC_FALSE; zone_element = cfg_list_first(cfg_tuple_get(rpz_obj, "zone list")); if (zone_element == NULL) return (ISC_R_SUCCESS); result = dns_rpz_new_zones(&view->rpzs, view->mctx); if (result != ISC_R_SUCCESS) return (result); new = view->rpzs; sub_obj = cfg_tuple_get(rpz_obj, "recursive-only"); if (!cfg_obj_isvoid(sub_obj) && !cfg_obj_asboolean(sub_obj)) recursive_only_def = ISC_FALSE; else recursive_only_def = ISC_TRUE; sub_obj = cfg_tuple_get(rpz_obj, "break-dnssec"); if (!cfg_obj_isvoid(sub_obj) && cfg_obj_asboolean(sub_obj)) new->p.break_dnssec = ISC_TRUE; else new->p.break_dnssec = ISC_FALSE; sub_obj = cfg_tuple_get(rpz_obj, "max-policy-ttl"); if (cfg_obj_isuint32(sub_obj)) ttl_def = cfg_obj_asuint32(sub_obj); else ttl_def = DNS_RPZ_MAX_TTL_DEFAULT; sub_obj = cfg_tuple_get(rpz_obj, "min-ns-dots"); if (cfg_obj_isuint32(sub_obj)) new->p.min_ns_labels = cfg_obj_asuint32(sub_obj) + 1; else new->p.min_ns_labels = 2; sub_obj = cfg_tuple_get(rpz_obj, "qname-wait-recurse"); if (cfg_obj_isvoid(sub_obj) || cfg_obj_asboolean(sub_obj)) new->p.qname_wait_recurse = ISC_TRUE; else new->p.qname_wait_recurse = ISC_FALSE; sub_obj = cfg_tuple_get(rpz_obj, "nsip-wait-recurse"); if (cfg_obj_isvoid(sub_obj) || cfg_obj_asboolean(sub_obj)) new->p.nsip_wait_recurse = ISC_TRUE; else new->p.nsip_wait_recurse = ISC_FALSE; pview = NULL; result = dns_viewlist_find(&ns_g_server->viewlist, view->name, view->rdclass, &pview); if (result == ISC_R_SUCCESS) { old = pview->rpzs; } else { old = NULL; } if (old == NULL) *old_rpz_okp = ISC_FALSE; else *old_rpz_okp = ISC_TRUE; for (i = 0; zone_element != NULL; ++i, zone_element = cfg_list_next(zone_element)) { INSIST(old != NULL || !*old_rpz_okp); if (*old_rpz_okp && i < old->p.num_zones) { old_zone = old->zones[i]; } else { *old_rpz_okp = ISC_FALSE; old_zone = NULL; } result = configure_rpz_zone(view, zone_element, recursive_only_def, ttl_def, old_zone, old_rpz_okp); if (result != ISC_R_SUCCESS) { if (pview != NULL) dns_view_detach(&pview); return (result); } } /* * If this is a reloading and the parameters and list of policy * zones are unchanged, then use the same policy data. * Data for individual zones that must be reloaded will be merged. */ if (old != NULL && memcmp(&old->p, &new->p, sizeof(new->p)) != 0) *old_rpz_okp = ISC_FALSE; if (*old_rpz_okp) { dns_rpz_detach_rpzs(&view->rpzs); dns_rpz_attach_rpzs(pview->rpzs, &view->rpzs); } else if (old != NULL && pview != NULL) { pview->rpzs->rpz_ver += 1; view->rpzs->rpz_ver = pview->rpzs->rpz_ver; cfg_obj_log(rpz_obj, ns_g_lctx, DNS_RPZ_DEBUG_LEVEL1, "updated RPZ policy: version %d", view->rpzs->rpz_ver); } if (pview != NULL) dns_view_detach(&pview); return (ISC_R_SUCCESS); } static void catz_addmodzone_taskaction(isc_task_t *task, isc_event_t *event0) { catz_chgzone_event_t *ev = (catz_chgzone_event_t *) event0; isc_result_t result; isc_buffer_t namebuf; isc_buffer_t *confbuf; char nameb[DNS_NAME_FORMATSIZE]; const cfg_obj_t *zlist = NULL; cfg_obj_t *zoneconf = NULL; cfg_obj_t *zoneobj = NULL; ns_cfgctx_t *cfg; dns_zone_t *zone = NULL; cfg = (ns_cfgctx_t *) ev->view->new_zone_config; if (cfg == NULL) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, "catz: allow-new-zones statement missing from " "config; cannot add zone from the catalog"); goto cleanup; } isc_buffer_init(&namebuf, nameb, DNS_NAME_FORMATSIZE); dns_name_totext(dns_catz_entry_getname(ev->entry), ISC_TRUE, &namebuf); isc_buffer_putuint8(&namebuf, 0); /* Zone shouldn't already exist */ result = dns_zt_find(ev->view->zonetable, dns_catz_entry_getname(ev->entry), 0, NULL, &zone); if (ev->mod == ISC_TRUE) { if (result != ISC_R_SUCCESS) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_WARNING, "catz: error \"%s\" while trying to " "modify zone \"%s\"", isc_result_totext(result), nameb); goto cleanup; } else { if (!dns_zone_getadded(zone)) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_WARNING, "catz: catz_addmodzone_taskaction: " "zone '%s' is not a dynamically " "added zone", nameb); goto cleanup; } if (dns_zone_get_parentcatz(zone) != ev->origin) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_WARNING, "catz: catz_delzone_taskaction: " "zone '%s' exists in multiple " "catalog zones", nameb); goto cleanup; } dns_zone_detach(&zone); } } else { if (result != ISC_R_NOTFOUND && result != DNS_R_PARTIALMATCH) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_WARNING, "catz: error \"%s\" while trying to " "add zone \"%s\"", isc_result_totext(result), nameb); goto cleanup; } else { /* this can happen in case of DNS_R_PARTIALMATCH */ if (zone != NULL) dns_zone_detach(&zone); } } RUNTIME_CHECK(zone == NULL); /* Create a config for new zone */ confbuf = NULL; result = dns_catz_generate_zonecfg(ev->origin, ev->entry, &confbuf); if (result == ISC_R_SUCCESS) { cfg_parser_reset(cfg->add_parser); result = cfg_parse_buffer3(cfg->add_parser, confbuf, "catz", 0, &cfg_type_addzoneconf, &zoneconf); isc_buffer_free(&confbuf); } /* * Fail if either dns_catz_generate_zonecfg() or cfg_parse_buffer3() * failed. */ if (result != ISC_R_SUCCESS) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, "catz: error \"%s\" while trying to generate " "config for zone \"%s\"", isc_result_totext(result), nameb); goto cleanup; } CHECK(cfg_map_get(zoneconf, "zone", &zlist)); if (!cfg_obj_islist(zlist)) CHECK(ISC_R_FAILURE); /* For now we only support adding one zone at a time */ zoneobj = cfg_listelt_value(cfg_list_first(zlist)); /* Mark view unfrozen so that zone can be added */ result = isc_task_beginexclusive(task); RUNTIME_CHECK(result == ISC_R_SUCCESS); dns_view_thaw(ev->view); result = configure_zone(cfg->config, zoneobj, cfg->vconfig, ev->cbd->server->mctx, ev->view, &ev->cbd->server->viewlist, cfg->actx, ISC_TRUE, ISC_FALSE, ev->mod); dns_view_freeze(ev->view); isc_task_endexclusive(task); if (result != ISC_R_SUCCESS) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_WARNING, "catz: failed to configure zone \"%s\" - %d", nameb, result); goto cleanup; } /* Is it there yet? */ CHECK(dns_zt_find(ev->view->zonetable, dns_catz_entry_getname(ev->entry), 0, NULL, &zone)); /* * Load the zone from the master file. If this fails, we'll * need to undo the configuration we've done already. */ result = dns_zone_loadnew(zone); if (result != ISC_R_SUCCESS) { dns_db_t *dbp = NULL; isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, "catz: dns_zone_loadnew() failed " "with %s; reverting.", isc_result_totext(result)); /* If the zone loaded partially, unload it */ if (dns_zone_getdb(zone, &dbp) == ISC_R_SUCCESS) { dns_db_detach(&dbp); dns_zone_unload(zone); } /* Remove the zone from the zone table */ dns_zt_unmount(ev->view->zonetable, zone); goto cleanup; } /* Flag the zone as having been added at runtime */ dns_zone_setadded(zone, ISC_TRUE); dns_zone_set_parentcatz(zone, ev->origin); cleanup: if (zone != NULL) dns_zone_detach(&zone); if (zoneconf != NULL) cfg_obj_destroy(cfg->add_parser, &zoneconf); dns_catz_entry_detach(ev->origin, &ev->entry); dns_catz_zone_detach(&ev->origin); dns_view_detach(&ev->view); isc_event_free(ISC_EVENT_PTR(&ev)); } static void catz_delzone_taskaction(isc_task_t *task, isc_event_t *event0) { catz_chgzone_event_t *ev = (catz_chgzone_event_t *) event0; isc_result_t result; dns_zone_t *zone = NULL; dns_db_t *dbp = NULL; char cname[DNS_NAME_FORMATSIZE]; const char * file; result = isc_task_beginexclusive(task); RUNTIME_CHECK(result == ISC_R_SUCCESS); dns_name_format(dns_catz_entry_getname(ev->entry), cname, DNS_NAME_FORMATSIZE); result = dns_zt_find(ev->view->zonetable, dns_catz_entry_getname(ev->entry), 0, NULL, &zone); if (result != ISC_R_SUCCESS) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_WARNING, "catz: catz_delzone_taskaction: " "zone '%s' not found", cname); goto cleanup; } if (!dns_zone_getadded(zone)) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_WARNING, "catz: catz_delzone_taskaction: " "zone '%s' is not a dynamically added zone", cname); goto cleanup; } if (dns_zone_get_parentcatz(zone) != ev->origin) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_WARNING, "catz: catz_delzone_taskaction: zone " "'%s' exists in multiple catalog zones", cname); goto cleanup; } /* Stop answering for this zone */ if (dns_zone_getdb(zone, &dbp) == ISC_R_SUCCESS) { dns_db_detach(&dbp); dns_zone_unload(zone); } CHECK(dns_zt_unmount(ev->view->zonetable, zone)); file = dns_zone_getfile(zone); if (file != NULL) isc_file_remove(file); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_WARNING, "catz: catz_delzone_taskaction: " "zone '%s' deleted", cname); cleanup: isc_task_endexclusive(task); if (zone != NULL) dns_zone_detach(&zone); dns_catz_entry_detach(ev->origin, &ev->entry); dns_catz_zone_detach(&ev->origin); dns_view_detach(&ev->view); isc_event_free(ISC_EVENT_PTR(&ev)); } static isc_result_t catz_create_chg_task(dns_catz_entry_t *entry, dns_catz_zone_t *origin, dns_view_t *view, isc_taskmgr_t *taskmgr, void *udata, isc_eventtype_t type) { catz_chgzone_event_t *event; isc_task_t *task; isc_result_t result; isc_taskaction_t action; switch (type) { case DNS_EVENT_CATZADDZONE: case DNS_EVENT_CATZMODZONE: action = catz_addmodzone_taskaction; break; case DNS_EVENT_CATZDELZONE: action = catz_delzone_taskaction; break; default: REQUIRE(0); } event = (catz_chgzone_event_t *) isc_event_allocate(view->mctx, origin, type, action, NULL, sizeof(*event)); if (event == NULL) return (ISC_R_NOMEMORY); event->cbd = (catz_cb_data_t *) udata; event->entry = NULL; event->origin = NULL; event->view = NULL; event->mod = ISC_TF(type == DNS_EVENT_CATZMODZONE); dns_catz_entry_attach(entry, &event->entry); dns_catz_zone_attach(origin, &event->origin); dns_view_attach(view, &event->view); task = NULL; result = isc_taskmgr_excltask(taskmgr, &task); REQUIRE(result == ISC_R_SUCCESS); isc_task_send(task, ISC_EVENT_PTR(&event)); isc_task_detach(&task); return (ISC_R_SUCCESS); } static isc_result_t catz_addzone(dns_catz_entry_t *entry, dns_catz_zone_t *origin, dns_view_t *view, isc_taskmgr_t *taskmgr, void *udata) { return (catz_create_chg_task(entry, origin, view, taskmgr, udata, DNS_EVENT_CATZADDZONE)); } static isc_result_t catz_delzone(dns_catz_entry_t *entry, dns_catz_zone_t *origin, dns_view_t *view, isc_taskmgr_t *taskmgr, void *udata) { return (catz_create_chg_task(entry, origin, view, taskmgr, udata, DNS_EVENT_CATZDELZONE)); } static isc_result_t catz_modzone(dns_catz_entry_t *entry, dns_catz_zone_t *origin, dns_view_t *view, isc_taskmgr_t *taskmgr, void *udata) { return (catz_create_chg_task(entry, origin, view, taskmgr, udata, DNS_EVENT_CATZMODZONE)); } static isc_result_t configure_catz_zone(dns_view_t *view, const cfg_obj_t *config, const cfg_listelt_t *element) { const cfg_obj_t *catz_obj, *obj; dns_catz_zone_t *zone = NULL; const char *str; isc_result_t result; dns_name_t origin; dns_catz_options_t *opts; dns_view_t *pview = NULL; dns_name_init(&origin, NULL); catz_obj = cfg_listelt_value(element); str = cfg_obj_asstring(cfg_tuple_get(catz_obj, "zone name")); result = dns_name_fromstring(&origin, str, DNS_NAME_DOWNCASE, view->mctx); if (result == ISC_R_SUCCESS && dns_name_equal(&origin, dns_rootname)) result = DNS_R_EMPTYLABEL; if (result != ISC_R_SUCCESS) { cfg_obj_log(catz_obj, ns_g_lctx, DNS_CATZ_ERROR_LEVEL, "catz: invalid zone name '%s'", str); goto cleanup; } result = dns_catz_add_zone(view->catzs, &origin, &zone); if (result != ISC_R_SUCCESS && result != ISC_R_EXISTS) { cfg_obj_log(catz_obj, ns_g_lctx, DNS_CATZ_ERROR_LEVEL, "catz: unable to create catalog zone '%s', " "error %s", str, isc_result_totext(result)); goto cleanup; } if (result == ISC_R_EXISTS) { isc_ht_iter_t *it = NULL; result = dns_viewlist_find(&ns_g_server->viewlist, view->name, view->rdclass, &pview); RUNTIME_CHECK(result == ISC_R_SUCCESS); /* * xxxwpk todo: reconfigure the zone!!!! */ cfg_obj_log(catz_obj, ns_g_lctx, DNS_CATZ_ERROR_LEVEL, "catz: catalog zone '%s' will not be reconfigured", str); /* * We have to walk through all the member zones and attach * them to current view */ result = dns_catz_get_iterator(zone, &it); if (result != ISC_R_SUCCESS) { cfg_obj_log(catz_obj, ns_g_lctx, DNS_CATZ_ERROR_LEVEL, "catz: unable to create iterator"); goto cleanup; } for (result = isc_ht_iter_first(it); result == ISC_R_SUCCESS; result = isc_ht_iter_next(it)) { dns_name_t *name = NULL; dns_zone_t *dnszone = NULL; dns_catz_entry_t *entry = NULL; isc_result_t tresult; isc_ht_iter_current(it, (void **) &entry); name = dns_catz_entry_getname(entry); tresult = dns_view_findzone(pview, name, &dnszone); RUNTIME_CHECK(tresult == ISC_R_SUCCESS); dns_zone_setview(dnszone, view); if (view->acache != NULL) dns_zone_setacache(dnszone, view->acache); dns_view_addzone(view, dnszone); /* * The dns_view_findzone() call above increments the * zone's reference count, which we need to decrement * back. However, as dns_zone_detach() sets the * supplied pointer to NULL, calling it is deferred * until the dnszone variable is no longer used. */ dns_zone_detach(&dnszone); } isc_ht_iter_destroy(&it); result = ISC_R_SUCCESS; } dns_catz_zone_resetdefoptions(zone); opts = dns_catz_zone_getdefoptions(zone); obj = cfg_tuple_get(catz_obj, "default-masters"); if (obj != NULL && cfg_obj_istuple(obj)) result = ns_config_getipandkeylist(config, obj, view->mctx, &opts->masters); obj = cfg_tuple_get(catz_obj, "in-memory"); if (obj != NULL && cfg_obj_isboolean(obj)) opts->in_memory = cfg_obj_asboolean(obj); obj = cfg_tuple_get(catz_obj, "zone-directory"); if (!opts->in_memory && obj != NULL && cfg_obj_isstring(obj)) { opts->zonedir = isc_mem_strdup(view->mctx, cfg_obj_asstring(obj)); if (isc_file_isdirectory(opts->zonedir) != ISC_R_SUCCESS) { cfg_obj_log(obj, ns_g_lctx, DNS_CATZ_ERROR_LEVEL, "catz: zone-directory '%s' " "not found; zone files will not be " "saved", opts->zonedir); opts->in_memory = ISC_TRUE; } } obj = cfg_tuple_get(catz_obj, "min-update-interval"); if (obj != NULL && cfg_obj_isuint32(obj)) opts->min_update_interval = cfg_obj_asuint32(obj); cleanup: if (pview != NULL) dns_view_detach(&pview); dns_name_free(&origin, view->mctx); return (result); } static catz_cb_data_t ns_catz_cbdata; static dns_catz_zonemodmethods_t ns_catz_zonemodmethods = { catz_addzone, catz_modzone, catz_delzone, &ns_catz_cbdata }; static isc_result_t configure_catz(dns_view_t *view, const cfg_obj_t *config, const cfg_obj_t *catz_obj) { const cfg_listelt_t *zone_element; const dns_catz_zones_t *old = NULL; dns_view_t *pview = NULL; isc_result_t result; /* xxxwpk TODO do it cleaner, once, somewhere */ ns_catz_cbdata.server = ns_g_server; zone_element = cfg_list_first(cfg_tuple_get(catz_obj, "zone list")); if (zone_element == NULL) return (ISC_R_SUCCESS); CHECK(dns_catz_new_zones(&view->catzs, &ns_catz_zonemodmethods, view->mctx, ns_g_taskmgr, ns_g_timermgr)); result = dns_viewlist_find(&ns_g_server->viewlist, view->name, view->rdclass, &pview); if (result == ISC_R_SUCCESS) old = pview->catzs; if (old != NULL) { dns_catz_catzs_detach(&view->catzs); dns_catz_catzs_attach(pview->catzs, &view->catzs); dns_catz_prereconfig(view->catzs); } while (zone_element != NULL) { CHECK(configure_catz_zone(view, config, zone_element)); zone_element = cfg_list_next(zone_element); } if (old != NULL) dns_catz_postreconfig(view->catzs); result = ISC_R_SUCCESS; cleanup: if (pview != NULL) dns_view_detach(&pview); return (result); } #define CHECK_RRL(cond, pat, val1, val2) \ do { \ if (!(cond)) { \ cfg_obj_log(obj, ns_g_lctx, ISC_LOG_ERROR, \ pat, val1, val2); \ result = ISC_R_RANGE; \ goto cleanup; \ } \ } while (0) #define CHECK_RRL_RATE(rate, def, max_rate, name) \ do { \ obj = NULL; \ rrl->rate.str = name; \ result = cfg_map_get(map, name, &obj); \ if (result == ISC_R_SUCCESS) { \ rrl->rate.r = cfg_obj_asuint32(obj); \ CHECK_RRL(rrl->rate.r <= max_rate, \ name" %d > %d", \ rrl->rate.r, max_rate); \ } else { \ rrl->rate.r = def; \ } \ rrl->rate.scaled = rrl->rate.r; \ } while (0) static isc_result_t configure_rrl(dns_view_t *view, const cfg_obj_t *config, const cfg_obj_t *map) { const cfg_obj_t *obj; dns_rrl_t *rrl; isc_result_t result; int min_entries, i, j; /* * Most DNS servers have few clients, but intentinally open * recursive and authoritative servers often have many. * So start with a small number of entries unless told otherwise * to reduce cold-start costs. */ min_entries = 500; obj = NULL; result = cfg_map_get(map, "min-table-size", &obj); if (result == ISC_R_SUCCESS) { min_entries = cfg_obj_asuint32(obj); if (min_entries < 1) min_entries = 1; } result = dns_rrl_init(&rrl, view, min_entries); if (result != ISC_R_SUCCESS) return (result); i = ISC_MAX(20000, min_entries); obj = NULL; result = cfg_map_get(map, "max-table-size", &obj); if (result == ISC_R_SUCCESS) { i = cfg_obj_asuint32(obj); CHECK_RRL(i >= min_entries, "max-table-size %d < min-table-size %d", i, min_entries); } rrl->max_entries = i; CHECK_RRL_RATE(responses_per_second, 0, DNS_RRL_MAX_RATE, "responses-per-second"); CHECK_RRL_RATE(referrals_per_second, rrl->responses_per_second.r, DNS_RRL_MAX_RATE, "referrals-per-second"); CHECK_RRL_RATE(nodata_per_second, rrl->responses_per_second.r, DNS_RRL_MAX_RATE, "nodata-per-second"); CHECK_RRL_RATE(nxdomains_per_second, rrl->responses_per_second.r, DNS_RRL_MAX_RATE, "nxdomains-per-second"); CHECK_RRL_RATE(errors_per_second, rrl->responses_per_second.r, DNS_RRL_MAX_RATE, "errors-per-second"); CHECK_RRL_RATE(all_per_second, 0, DNS_RRL_MAX_RATE, "all-per-second"); CHECK_RRL_RATE(slip, 2, DNS_RRL_MAX_SLIP, "slip"); i = 15; obj = NULL; result = cfg_map_get(map, "window", &obj); if (result == ISC_R_SUCCESS) { i = cfg_obj_asuint32(obj); CHECK_RRL(i >= 1 && i <= DNS_RRL_MAX_WINDOW, "window %d < 1 or > %d", i, DNS_RRL_MAX_WINDOW); } rrl->window = i; i = 0; obj = NULL; result = cfg_map_get(map, "qps-scale", &obj); if (result == ISC_R_SUCCESS) { i = cfg_obj_asuint32(obj); CHECK_RRL(i >= 1, "invalid 'qps-scale %d'%s", i, ""); } rrl->qps_scale = i; rrl->qps = 1.0; i = 24; obj = NULL; result = cfg_map_get(map, "ipv4-prefix-length", &obj); if (result == ISC_R_SUCCESS) { i = cfg_obj_asuint32(obj); CHECK_RRL(i >= 8 && i <= 32, "invalid 'ipv4-prefix-length %d'%s", i, ""); } rrl->ipv4_prefixlen = i; if (i == 32) rrl->ipv4_mask = 0xffffffff; else rrl->ipv4_mask = htonl(0xffffffff << (32-i)); i = 56; obj = NULL; result = cfg_map_get(map, "ipv6-prefix-length", &obj); if (result == ISC_R_SUCCESS) { i = cfg_obj_asuint32(obj); CHECK_RRL(i >= 16 && i <= DNS_RRL_MAX_PREFIX, "ipv6-prefix-length %d < 16 or > %d", i, DNS_RRL_MAX_PREFIX); } rrl->ipv6_prefixlen = i; for (j = 0; j < 4; ++j) { if (i <= 0) { rrl->ipv6_mask[j] = 0; } else if (i < 32) { rrl->ipv6_mask[j] = htonl(0xffffffff << (32-i)); } else { rrl->ipv6_mask[j] = 0xffffffff; } i -= 32; } obj = NULL; result = cfg_map_get(map, "exempt-clients", &obj); if (result == ISC_R_SUCCESS) { result = cfg_acl_fromconfig(obj, config, ns_g_lctx, ns_g_aclconfctx, ns_g_mctx, 0, &rrl->exempt); CHECK_RRL(result == ISC_R_SUCCESS, "invalid %s%s", "address match list", ""); } obj = NULL; result = cfg_map_get(map, "log-only", &obj); if (result == ISC_R_SUCCESS && cfg_obj_asboolean(obj)) rrl->log_only = ISC_TRUE; else rrl->log_only = ISC_FALSE; return (ISC_R_SUCCESS); cleanup: dns_rrl_view_destroy(view); return (result); } static isc_result_t add_soa(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name, dns_name_t *origin, dns_name_t *contact) { dns_dbnode_t *node = NULL; dns_rdata_t rdata = DNS_RDATA_INIT; dns_rdatalist_t rdatalist; dns_rdataset_t rdataset; isc_result_t result; unsigned char buf[DNS_SOA_BUFFERSIZE]; CHECK(dns_soa_buildrdata(origin, contact, dns_db_class(db), 0, 28800, 7200, 604800, 86400, buf, &rdata)); dns_rdatalist_init(&rdatalist); rdatalist.type = rdata.type; rdatalist.rdclass = rdata.rdclass; rdatalist.ttl = 86400; ISC_LIST_APPEND(rdatalist.rdata, &rdata, link); dns_rdataset_init(&rdataset); CHECK(dns_rdatalist_tordataset(&rdatalist, &rdataset)); CHECK(dns_db_findnode(db, name, ISC_TRUE, &node)); CHECK(dns_db_addrdataset(db, node, version, 0, &rdataset, 0, NULL)); cleanup: if (node != NULL) dns_db_detachnode(db, &node); return (result); } static isc_result_t add_ns(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name, dns_name_t *nsname) { dns_dbnode_t *node = NULL; dns_rdata_ns_t ns; dns_rdata_t rdata = DNS_RDATA_INIT; dns_rdatalist_t rdatalist; dns_rdataset_t rdataset; isc_result_t result; isc_buffer_t b; unsigned char buf[DNS_NAME_MAXWIRE]; isc_buffer_init(&b, buf, sizeof(buf)); ns.common.rdtype = dns_rdatatype_ns; ns.common.rdclass = dns_db_class(db); ns.mctx = NULL; dns_name_init(&ns.name, NULL); dns_name_clone(nsname, &ns.name); CHECK(dns_rdata_fromstruct(&rdata, dns_db_class(db), dns_rdatatype_ns, &ns, &b)); dns_rdatalist_init(&rdatalist); rdatalist.type = rdata.type; rdatalist.rdclass = rdata.rdclass; rdatalist.ttl = 86400; ISC_LIST_APPEND(rdatalist.rdata, &rdata, link); dns_rdataset_init(&rdataset); CHECK(dns_rdatalist_tordataset(&rdatalist, &rdataset)); CHECK(dns_db_findnode(db, name, ISC_TRUE, &node)); CHECK(dns_db_addrdataset(db, node, version, 0, &rdataset, 0, NULL)); cleanup: if (node != NULL) dns_db_detachnode(db, &node); return (result); } static isc_result_t create_empty_zone(dns_zone_t *zone, dns_name_t *name, dns_view_t *view, const cfg_obj_t *zonelist, const char **empty_dbtype, int empty_dbtypec, dns_zonestat_level_t statlevel) { char namebuf[DNS_NAME_FORMATSIZE]; const cfg_listelt_t *element; const cfg_obj_t *obj; const cfg_obj_t *zconfig; const cfg_obj_t *zoptions; const char *rbt_dbtype[4] = { "rbt" }; const char *sep = ": view "; const char *str; const char *viewname = view->name; dns_db_t *db = NULL; dns_dbversion_t *version = NULL; dns_fixedname_t cfixed; dns_fixedname_t fixed; dns_fixedname_t nsfixed; dns_name_t *contact; dns_name_t *ns; dns_name_t *zname; dns_zone_t *myzone = NULL; int rbt_dbtypec = 1; isc_result_t result; dns_namereln_t namereln; int order; unsigned int nlabels; dns_fixedname_init(&fixed); zname = dns_fixedname_name(&fixed); dns_fixedname_init(&nsfixed); ns = dns_fixedname_name(&nsfixed); dns_fixedname_init(&cfixed); contact = dns_fixedname_name(&cfixed); /* * Look for forward "zones" beneath this empty zone and if so * create a custom db for the empty zone. */ for (element = cfg_list_first(zonelist); element != NULL; element = cfg_list_next(element)) { zconfig = cfg_listelt_value(element); str = cfg_obj_asstring(cfg_tuple_get(zconfig, "name")); CHECK(dns_name_fromstring(zname, str, 0, NULL)); namereln = dns_name_fullcompare(zname, name, &order, &nlabels); if (namereln != dns_namereln_subdomain) continue; zoptions = cfg_tuple_get(zconfig, "options"); obj = NULL; (void)cfg_map_get(zoptions, "type", &obj); if (obj != NULL && strcasecmp(cfg_obj_asstring(obj), "forward") == 0) { obj = NULL; (void)cfg_map_get(zoptions, "forward", &obj); if (obj == NULL) continue; if (strcasecmp(cfg_obj_asstring(obj), "only") != 0) continue; } if (db == NULL) { CHECK(dns_db_create(view->mctx, "rbt", name, dns_dbtype_zone, view->rdclass, 0, NULL, &db)); CHECK(dns_db_newversion(db, &version)); if (strcmp(empty_dbtype[2], "@") == 0) dns_name_clone(name, ns); else CHECK(dns_name_fromstring(ns, empty_dbtype[2], 0, NULL)); CHECK(dns_name_fromstring(contact, empty_dbtype[3], 0, NULL)); CHECK(add_soa(db, version, name, ns, contact)); CHECK(add_ns(db, version, name, ns)); } CHECK(add_ns(db, version, zname, dns_rootname)); } /* * Is the existing zone the ok to use? */ if (zone != NULL) { unsigned int typec; const char **dbargv; if (db != NULL) { typec = rbt_dbtypec; dbargv = rbt_dbtype; } else { typec = empty_dbtypec; dbargv = empty_dbtype; } result = check_dbtype(zone, typec, dbargv, view->mctx); if (result != ISC_R_SUCCESS) zone = NULL; if (zone != NULL && dns_zone_gettype(zone) != dns_zone_master) zone = NULL; if (zone != NULL && dns_zone_getfile(zone) != NULL) zone = NULL; if (zone != NULL) { dns_zone_getraw(zone, &myzone); if (myzone != NULL) { dns_zone_detach(&myzone); zone = NULL; } } } if (zone == NULL) { CHECK(dns_zonemgr_createzone(ns_g_server->zonemgr, &myzone)); zone = myzone; CHECK(dns_zone_setorigin(zone, name)); CHECK(dns_zonemgr_managezone(ns_g_server->zonemgr, zone)); if (db == NULL) CHECK(dns_zone_setdbtype(zone, empty_dbtypec, empty_dbtype)); dns_zone_setclass(zone, view->rdclass); dns_zone_settype(zone, dns_zone_master); dns_zone_setstats(zone, ns_g_server->zonestats); } dns_zone_setoption(zone, ~DNS_ZONEOPT_NOCHECKNS, ISC_FALSE); dns_zone_setoption(zone, DNS_ZONEOPT_NOCHECKNS, ISC_TRUE); dns_zone_setnotifytype(zone, dns_notifytype_no); dns_zone_setdialup(zone, dns_dialuptype_no); dns_zone_setautomatic(zone, ISC_TRUE); if (view->queryacl != NULL) dns_zone_setqueryacl(zone, view->queryacl); else dns_zone_clearqueryacl(zone); if (view->queryonacl != NULL) dns_zone_setqueryonacl(zone, view->queryonacl); else dns_zone_clearqueryonacl(zone); dns_zone_clearupdateacl(zone); if (view->transferacl != NULL) dns_zone_setxfracl(zone, view->transferacl); else dns_zone_clearxfracl(zone); CHECK(setquerystats(zone, view->mctx, statlevel)); if (db != NULL) { dns_db_closeversion(db, &version, ISC_TRUE); CHECK(dns_zone_replacedb(zone, db, ISC_FALSE)); } dns_zone_setoption2(zone, DNS_ZONEOPT2_AUTOEMPTY, ISC_TRUE); dns_zone_setview(zone, view); CHECK(dns_view_addzone(view, zone)); if (!strcmp(viewname, "_default")) { sep = ""; viewname = ""; } dns_name_format(name, namebuf, sizeof(namebuf)); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_INFO, "automatic empty zone%s%s: %s", sep, viewname, namebuf); cleanup: if (myzone != NULL) dns_zone_detach(&myzone); if (version != NULL) dns_db_closeversion(db, &version, ISC_FALSE); if (db != NULL) dns_db_detach(&db); INSIST(version == NULL); return (result); } #ifdef HAVE_DNSTAP static isc_result_t configure_dnstap(const cfg_obj_t **maps, dns_view_t *view) { isc_result_t result; const cfg_obj_t *obj, *obj2; const cfg_listelt_t *element; const char *dpath = ns_g_defaultdnstap; const cfg_obj_t *dlist = NULL; dns_dtmsgtype_t dttypes = 0; dns_dtmode_t dmode; unsigned int i; struct fstrm_iothr_options *fopt = NULL; result = ns_config_get(maps, "dnstap", &dlist); if (result != ISC_R_SUCCESS) return (ISC_R_SUCCESS); for (element = cfg_list_first(dlist); element != NULL; element = cfg_list_next(element)) { const char *str; dns_dtmsgtype_t dt = 0; obj = cfg_listelt_value(element); obj2 = cfg_tuple_get(obj, "type"); str = cfg_obj_asstring(obj2); if (strcasecmp(str, "client") == 0) { dt |= DNS_DTTYPE_CQ|DNS_DTTYPE_CR; } else if (strcasecmp(str, "auth") == 0) { dt |= DNS_DTTYPE_AQ|DNS_DTTYPE_AR; } else if (strcasecmp(str, "resolver") == 0) { dt |= DNS_DTTYPE_RQ|DNS_DTTYPE_RR; } else if (strcasecmp(str, "forwarder") == 0) { dt |= DNS_DTTYPE_FQ|DNS_DTTYPE_FR; } else if (strcasecmp(str, "all") == 0) { dt |= DNS_DTTYPE_CQ|DNS_DTTYPE_CR| DNS_DTTYPE_AQ|DNS_DTTYPE_AR| DNS_DTTYPE_RQ|DNS_DTTYPE_RR| DNS_DTTYPE_FQ|DNS_DTTYPE_FR; } obj2 = cfg_tuple_get(obj, "mode"); if (obj2 == NULL || cfg_obj_isvoid(obj2)) { dttypes |= dt; continue; } str = cfg_obj_asstring(obj2); if (strcasecmp(str, "query") == 0) { dt &= ~DNS_DTTYPE_RESPONSE; } else if (strcasecmp(str, "response") == 0) { dt &= ~DNS_DTTYPE_QUERY; } dttypes |= dt; } if (ns_g_server->dtenv == NULL && dttypes != 0) { obj = NULL; CHECKM(ns_config_get(maps, "dnstap-output", &obj), "'dnstap-output' must be set if 'dnstap' is set"); obj2 = cfg_tuple_get(obj, "mode"); if (obj2 == NULL) CHECKM(ISC_R_FAILURE, "dnstap-output mode not found"); if (strcasecmp(cfg_obj_asstring(obj2), "file") == 0) dmode = dns_dtmode_file; else dmode = dns_dtmode_unix; obj2 = cfg_tuple_get(obj, "path"); if (obj2 == NULL) CHECKM(ISC_R_FAILURE, "dnstap-output path not found"); dpath = cfg_obj_asstring(obj2); fopt = fstrm_iothr_options_init(); fstrm_iothr_options_set_num_input_queues(fopt, ns_g_cpus); fstrm_iothr_options_set_queue_model(fopt, FSTRM_IOTHR_QUEUE_MODEL_MPSC); obj = NULL; result = ns_config_get(maps, "fstrm-set-buffer-hint", &obj); if (result == ISC_R_SUCCESS) { i = cfg_obj_asuint32(obj); fstrm_iothr_options_set_buffer_hint(fopt, i); } obj = NULL; result = ns_config_get(maps, "fstrm-set-flush-timeout", &obj); if (result == ISC_R_SUCCESS) { i = cfg_obj_asuint32(obj); fstrm_iothr_options_set_flush_timeout(fopt, i); } obj = NULL; result = ns_config_get(maps, "fstrm-set-input-queue-size", &obj); if (result == ISC_R_SUCCESS) { i = cfg_obj_asuint32(obj); fstrm_iothr_options_set_input_queue_size(fopt, i); } obj = NULL; result = ns_config_get(maps, "fstrm-set-output-notify-threshold", &obj); if (result == ISC_R_SUCCESS) { i = cfg_obj_asuint32(obj); fstrm_iothr_options_set_queue_notify_threshold(fopt, i); } obj = NULL; result = ns_config_get(maps, "fstrm-set-output-queue-model", &obj); if (result == ISC_R_SUCCESS) { if (strcasecmp(cfg_obj_asstring(obj), "spsc") == 0) i = FSTRM_IOTHR_QUEUE_MODEL_SPSC; else i = FSTRM_IOTHR_QUEUE_MODEL_MPSC; fstrm_iothr_options_set_queue_model(fopt, i); } obj = NULL; result = ns_config_get(maps, "fstrm-set-output-queue-size", &obj); if (result == ISC_R_SUCCESS) { i = cfg_obj_asuint32(obj); fstrm_iothr_options_set_output_queue_size(fopt, i); } obj = NULL; result = ns_config_get(maps, "fstrm-set-reopen-interval", &obj); if (result == ISC_R_SUCCESS) { i = cfg_obj_asuint32(obj); fstrm_iothr_options_set_reopen_interval(fopt, i); } CHECKM(dns_dt_create(ns_g_mctx, dmode, dpath, &fopt, &ns_g_server->dtenv), "unable to create dnstap environment"); } if (ns_g_server->dtenv == NULL) return (ISC_R_SUCCESS); obj = NULL; result = ns_config_get(maps, "dnstap-version", &obj); if (result != ISC_R_SUCCESS) { /* not specified; use the product and version */ dns_dt_setversion(ns_g_server->dtenv, PRODUCT " " VERSION); } else if (result == ISC_R_SUCCESS && !cfg_obj_isvoid(obj)) { /* Quoted string */ dns_dt_setversion(ns_g_server->dtenv, cfg_obj_asstring(obj)); } obj = NULL; result = ns_config_get(maps, "dnstap-identity", &obj); if (result == ISC_R_SUCCESS && cfg_obj_isboolean(obj)) { /* "hostname" is interpreted as boolean ISC_TRUE */ char buf[256]; result = ns_os_gethostname(buf, sizeof(buf)); if (result == ISC_R_SUCCESS) dns_dt_setidentity(ns_g_server->dtenv, buf); } else if (result == ISC_R_SUCCESS && !cfg_obj_isvoid(obj)) { /* Quoted string */ dns_dt_setidentity(ns_g_server->dtenv, cfg_obj_asstring(obj)); } dns_dt_attach(ns_g_server->dtenv, &view->dtenv); view->dttypes = dttypes; result = ISC_R_SUCCESS; cleanup: if (fopt != NULL) fstrm_iothr_options_destroy(&fopt); return (result); } #endif /* HAVE_DNSTAP */ static isc_result_t create_mapped_acl(void) { isc_result_t result; dns_acl_t *acl = NULL; struct in6_addr in6 = IN6ADDR_V4MAPPED_INIT; isc_netaddr_t addr; isc_netaddr_fromin6(&addr, &in6); result = dns_acl_create(ns_g_mctx, 1, &acl); if (result != ISC_R_SUCCESS) return (result); result = dns_iptable_addprefix2(acl->iptable, &addr, 96, ISC_TRUE, ISC_FALSE); if (result == ISC_R_SUCCESS) dns_acl_attach(acl, &ns_g_mapped); dns_acl_detach(&acl); return (result); } /* * Configure 'view' according to 'vconfig', taking defaults from 'config' * where values are missing in 'vconfig'. * * When configuring the default view, 'vconfig' will be NULL and the * global defaults in 'config' used exclusively. */ static isc_result_t configure_view(dns_view_t *view, dns_viewlist_t *viewlist, cfg_obj_t *config, cfg_obj_t *vconfig, ns_cachelist_t *cachelist, const cfg_obj_t *bindkeys, isc_mem_t *mctx, cfg_aclconfctx_t *actx, isc_boolean_t need_hints) { const cfg_obj_t *maps[4]; const cfg_obj_t *cfgmaps[3]; const cfg_obj_t *optionmaps[3]; const cfg_obj_t *options = NULL; const cfg_obj_t *voptions = NULL; const cfg_obj_t *forwardtype; const cfg_obj_t *forwarders; const cfg_obj_t *alternates; const cfg_obj_t *zonelist; const cfg_obj_t *dlzlist; const cfg_obj_t *dlz; const cfg_obj_t *dlvobj = NULL; unsigned int dlzargc; char **dlzargv; const cfg_obj_t *dyndb_list; const cfg_obj_t *disabled; const cfg_obj_t *obj, *obj2; const cfg_listelt_t *element; in_port_t port; dns_cache_t *cache = NULL; isc_result_t result; unsigned int cleaning_interval; size_t max_cache_size; isc_uint32_t max_cache_size_percent = 0; size_t max_acache_size; size_t max_adb_size; isc_uint32_t lame_ttl, fail_ttl; dns_tsig_keyring_t *ring = NULL; dns_view_t *pview = NULL; /* Production view */ isc_mem_t *cmctx = NULL, *hmctx = NULL; dns_dispatch_t *dispatch4 = NULL; dns_dispatch_t *dispatch6 = NULL; isc_boolean_t reused_cache = ISC_FALSE; isc_boolean_t shared_cache = ISC_FALSE; int i = 0, j = 0, k = 0; const char *str; const char *cachename = NULL; dns_order_t *order = NULL; isc_uint32_t udpsize; isc_uint32_t maxbits; unsigned int resopts = 0; dns_zone_t *zone = NULL; isc_uint32_t max_clients_per_query; isc_boolean_t empty_zones_enable; const cfg_obj_t *disablelist = NULL; isc_stats_t *resstats = NULL; dns_stats_t *resquerystats = NULL; isc_boolean_t auto_root = ISC_FALSE; ns_cache_t *nsc; isc_boolean_t zero_no_soattl; dns_acl_t *clients = NULL, *mapped = NULL, *excluded = NULL; unsigned int query_timeout, ndisp; isc_boolean_t old_rpz_ok = ISC_FALSE; isc_dscp_t dscp4 = -1, dscp6 = -1; dns_dyndbctx_t *dctx = NULL; REQUIRE(DNS_VIEW_VALID(view)); if (config != NULL) (void)cfg_map_get(config, "options", &options); /* * maps: view options, options, defaults * cfgmaps: view options, config * optionmaps: view options, options */ if (vconfig != NULL) { voptions = cfg_tuple_get(vconfig, "options"); maps[i++] = voptions; optionmaps[j++] = voptions; cfgmaps[k++] = voptions; } if (options != NULL) { maps[i++] = options; optionmaps[j++] = options; } maps[i++] = ns_g_defaults; maps[i] = NULL; optionmaps[j] = NULL; if (config != NULL) cfgmaps[k++] = config; cfgmaps[k] = NULL; /* * Set the view's port number for outgoing queries. */ CHECKM(ns_config_getport(config, &port), "port"); dns_view_setdstport(view, port); /* * Create additional cache for this view and zones under the view * if explicitly enabled. * XXX950 default to on. */ obj = NULL; (void)ns_config_get(maps, "acache-enable", &obj); if (obj != NULL && cfg_obj_asboolean(obj)) { cmctx = NULL; CHECK(isc_mem_create(0, 0, &cmctx)); CHECK(dns_acache_create(&view->acache, cmctx, ns_g_taskmgr, ns_g_timermgr)); isc_mem_setname(cmctx, "acache", NULL); isc_mem_detach(&cmctx); } if (view->acache != NULL) { obj = NULL; result = ns_config_get(maps, "acache-cleaning-interval", &obj); INSIST(result == ISC_R_SUCCESS); dns_acache_setcleaninginterval(view->acache, cfg_obj_asuint32(obj) * 60); obj = NULL; result = ns_config_get(maps, "max-acache-size", &obj); INSIST(result == ISC_R_SUCCESS); if (cfg_obj_isstring(obj)) { str = cfg_obj_asstring(obj); INSIST(strcasecmp(str, "unlimited") == 0); max_acache_size = 0; } else { isc_resourcevalue_t value; value = cfg_obj_asuint64(obj); if (value > SIZE_MAX) { cfg_obj_log(obj, ns_g_lctx, ISC_LOG_WARNING, "'max-acache-size " "%" ISC_PRINT_QUADFORMAT "u' " "is too large for this " "system; reducing to %lu", value, (unsigned long)SIZE_MAX); value = SIZE_MAX; } max_acache_size = (size_t) value; } dns_acache_setcachesize(view->acache, max_acache_size); } CHECK(configure_view_acl(vconfig, config, ns_g_config, "allow-query", NULL, actx, ns_g_mctx, &view->queryacl)); /* * Make the list of response policy zone names for a view that * is used for real lookups and so cares about hints. */ obj = NULL; if (view->rdclass == dns_rdataclass_in && need_hints && ns_config_get(maps, "response-policy", &obj) == ISC_R_SUCCESS) { CHECK(configure_rpz(view, obj, &old_rpz_ok)); } obj = NULL; if (view->rdclass == dns_rdataclass_in && need_hints && ns_config_get(maps, "catalog-zones", &obj) == ISC_R_SUCCESS) { CHECK(configure_catz(view, config, obj)); } /* * Configure the zones. */ zonelist = NULL; if (voptions != NULL) (void)cfg_map_get(voptions, "zone", &zonelist); else (void)cfg_map_get(config, "zone", &zonelist); /* * Load zone configuration */ for (element = cfg_list_first(zonelist); element != NULL; element = cfg_list_next(element)) { const cfg_obj_t *zconfig = cfg_listelt_value(element); CHECK(configure_zone(config, zconfig, vconfig, mctx, view, viewlist, actx, ISC_FALSE, old_rpz_ok, ISC_FALSE)); } /* * If we're allowing added zones, then load zone configuration * from the newzone file for zones that were added during previous * runs. */ CHECK(configure_newzones(view, config, vconfig, mctx, actx)); /* * Create Dynamically Loadable Zone driver. */ dlzlist = NULL; if (voptions != NULL) (void)cfg_map_get(voptions, "dlz", &dlzlist); else (void)cfg_map_get(config, "dlz", &dlzlist); for (element = cfg_list_first(dlzlist); element != NULL; element = cfg_list_next(element)) { dlz = cfg_listelt_value(element); obj = NULL; (void)cfg_map_get(dlz, "database", &obj); if (obj != NULL) { dns_dlzdb_t *dlzdb = NULL; const cfg_obj_t *name, *search = NULL; char *s = isc_mem_strdup(mctx, cfg_obj_asstring(obj)); if (s == NULL) { result = ISC_R_NOMEMORY; goto cleanup; } result = isc_commandline_strtoargv(mctx, s, &dlzargc, &dlzargv, 0); if (result != ISC_R_SUCCESS) { isc_mem_free(mctx, s); goto cleanup; } name = cfg_map_getname(dlz); result = dns_dlzcreate(mctx, cfg_obj_asstring(name), dlzargv[0], dlzargc, dlzargv, &dlzdb); isc_mem_free(mctx, s); isc_mem_put(mctx, dlzargv, dlzargc * sizeof(*dlzargv)); if (result != ISC_R_SUCCESS) goto cleanup; /* * If the DLZ backend supports configuration, * and is searchable, then call its configure * method now. If not searchable, we'll take * care of it when we process the zone statement. */ (void)cfg_map_get(dlz, "search", &search); if (search == NULL || cfg_obj_asboolean(search)) { dlzdb->search = ISC_TRUE; result = dns_dlzconfigure(view, dlzdb, dlzconfigure_callback); if (result != ISC_R_SUCCESS) goto cleanup; ISC_LIST_APPEND(view->dlz_searched, dlzdb, link); } else { dlzdb->search = ISC_FALSE; ISC_LIST_APPEND(view->dlz_unsearched, dlzdb, link); } } } /* * Obtain configuration parameters that affect the decision of whether * we can reuse/share an existing cache. */ obj = NULL; result = ns_config_get(maps, "cleaning-interval", &obj); INSIST(result == ISC_R_SUCCESS); cleaning_interval = cfg_obj_asuint32(obj) * 60; obj = NULL; result = ns_config_get(maps, "max-cache-size", &obj); INSIST(result == ISC_R_SUCCESS); if (cfg_obj_isstring(obj)) { str = cfg_obj_asstring(obj); INSIST(strcasecmp(str, "unlimited") == 0); max_cache_size = 0; } else if (cfg_obj_ispercentage(obj)) { max_cache_size = SIZE_AS_PERCENT; max_cache_size_percent = cfg_obj_aspercentage(obj); } else { isc_resourcevalue_t value; value = cfg_obj_asuint64(obj); if (value > SIZE_MAX) { cfg_obj_log(obj, ns_g_lctx, ISC_LOG_WARNING, "'max-cache-size " "%" ISC_PRINT_QUADFORMAT "u' " "is too large for this " "system; reducing to %lu", value, (unsigned long)SIZE_MAX); value = SIZE_MAX; } max_cache_size = (size_t) value; } if (max_cache_size == SIZE_AS_PERCENT) { isc_uint64_t totalphys = isc_meminfo_totalphys(); max_cache_size = (size_t) (totalphys * max_cache_size_percent/100); if (totalphys == 0) { cfg_obj_log(obj, ns_g_lctx, ISC_LOG_WARNING, "Unable to determine amount of physical " "memory, setting 'max-cache-size' to " "unlimited"); } else { cfg_obj_log(obj, ns_g_lctx, ISC_LOG_INFO, "'max-cache-size %d%%' " "- setting to %" ISC_PRINT_QUADFORMAT "uMB " "(out of %" ISC_PRINT_QUADFORMAT "uMB)", max_cache_size_percent, (isc_uint64_t)(max_cache_size / (1024*1024)), totalphys / (1024*1024)); } } /* Check-names. */ obj = NULL; result = ns_checknames_get(maps, "response", &obj); INSIST(result == ISC_R_SUCCESS); str = cfg_obj_asstring(obj); if (strcasecmp(str, "fail") == 0) { resopts |= DNS_RESOLVER_CHECKNAMES | DNS_RESOLVER_CHECKNAMESFAIL; view->checknames = ISC_TRUE; } else if (strcasecmp(str, "warn") == 0) { resopts |= DNS_RESOLVER_CHECKNAMES; view->checknames = ISC_FALSE; } else if (strcasecmp(str, "ignore") == 0) { view->checknames = ISC_FALSE; } else INSIST(0); obj = NULL; result = ns_config_get(maps, "zero-no-soa-ttl-cache", &obj); INSIST(result == ISC_R_SUCCESS); zero_no_soattl = cfg_obj_asboolean(obj); obj = NULL; result = ns_config_get(maps, "dns64", &obj); if (result == ISC_R_SUCCESS && strcmp(view->name, "_bind") && strcmp(view->name, "_meta")) { isc_netaddr_t na, suffix, *sp; unsigned int prefixlen; const char *server, *contact; const cfg_obj_t *myobj; myobj = NULL; result = ns_config_get(maps, "dns64-server", &myobj); if (result == ISC_R_SUCCESS) server = cfg_obj_asstring(myobj); else server = NULL; myobj = NULL; result = ns_config_get(maps, "dns64-contact", &myobj); if (result == ISC_R_SUCCESS) contact = cfg_obj_asstring(myobj); else contact = NULL; for (element = cfg_list_first(obj); element != NULL; element = cfg_list_next(element)) { const cfg_obj_t *map = cfg_listelt_value(element); dns_dns64_t *dns64 = NULL; unsigned int dns64options = 0; cfg_obj_asnetprefix(cfg_map_getname(map), &na, &prefixlen); obj = NULL; (void)cfg_map_get(map, "suffix", &obj); if (obj != NULL) { sp = &suffix; isc_netaddr_fromsockaddr(sp, cfg_obj_assockaddr(obj)); } else sp = NULL; clients = mapped = excluded = NULL; obj = NULL; (void)cfg_map_get(map, "clients", &obj); if (obj != NULL) { result = cfg_acl_fromconfig(obj, config, ns_g_lctx, actx, mctx, 0, &clients); if (result != ISC_R_SUCCESS) goto cleanup; } obj = NULL; (void)cfg_map_get(map, "mapped", &obj); if (obj != NULL) { result = cfg_acl_fromconfig(obj, config, ns_g_lctx, actx, mctx, 0, &mapped); if (result != ISC_R_SUCCESS) goto cleanup; } obj = NULL; (void)cfg_map_get(map, "exclude", &obj); if (obj != NULL) { result = cfg_acl_fromconfig(obj, config, ns_g_lctx, actx, mctx, 0, &excluded); if (result != ISC_R_SUCCESS) goto cleanup; } else { if (ns_g_mapped == NULL) { result = create_mapped_acl(); if (result != ISC_R_SUCCESS) goto cleanup; } dns_acl_attach(ns_g_mapped, &excluded); } obj = NULL; (void)cfg_map_get(map, "recursive-only", &obj); if (obj != NULL && cfg_obj_asboolean(obj)) dns64options |= DNS_DNS64_RECURSIVE_ONLY; obj = NULL; (void)cfg_map_get(map, "break-dnssec", &obj); if (obj != NULL && cfg_obj_asboolean(obj)) dns64options |= DNS_DNS64_BREAK_DNSSEC; result = dns_dns64_create(mctx, &na, prefixlen, sp, clients, mapped, excluded, dns64options, &dns64); if (result != ISC_R_SUCCESS) goto cleanup; dns_dns64_append(&view->dns64, dns64); view->dns64cnt++; result = dns64_reverse(view, mctx, &na, prefixlen, server, contact); if (result != ISC_R_SUCCESS) goto cleanup; if (clients != NULL) dns_acl_detach(&clients); if (mapped != NULL) dns_acl_detach(&mapped); if (excluded != NULL) dns_acl_detach(&excluded); } } obj = NULL; result = ns_config_get(maps, "dnssec-accept-expired", &obj); INSIST(result == ISC_R_SUCCESS); view->acceptexpired = cfg_obj_asboolean(obj); obj = NULL; result = ns_config_get(maps, "dnssec-validation", &obj); INSIST(result == ISC_R_SUCCESS); if (cfg_obj_isboolean(obj)) { view->enablevalidation = cfg_obj_asboolean(obj); } else { /* If dnssec-validation is not boolean, it must be "auto" */ view->enablevalidation = ISC_TRUE; auto_root = ISC_TRUE; } obj = NULL; result = ns_config_get(maps, "max-cache-ttl", &obj); INSIST(result == ISC_R_SUCCESS); view->maxcachettl = cfg_obj_asuint32(obj); obj = NULL; result = ns_config_get(maps, "max-ncache-ttl", &obj); INSIST(result == ISC_R_SUCCESS); view->maxncachettl = cfg_obj_asuint32(obj); if (view->maxncachettl > 7 * 24 * 3600) view->maxncachettl = 7 * 24 * 3600; /* * Configure the view's cache. * * First, check to see if there are any attach-cache options. If yes, * attempt to lookup an existing cache at attach it to the view. If * there is not one, then try to reuse an existing cache if possible; * otherwise create a new cache. * * Note that the ADB is not preserved or shared in either case. * * When a matching view is found, the associated statistics are also * retrieved and reused. * * XXX Determining when it is safe to reuse or share a cache is tricky. * When the view's configuration changes, the cached data may become * invalid because it reflects our old view of the world. We check * some of the configuration parameters that could invalidate the cache * or otherwise make it unsharable, but there are other configuration * options that should be checked. For example, if a view uses a * forwarder, changes in the forwarder configuration may invalidate * the cache. At the moment, it's the administrator's responsibility to * ensure these configuration options don't invalidate reusing/sharing. */ obj = NULL; result = ns_config_get(maps, "attach-cache", &obj); if (result == ISC_R_SUCCESS) cachename = cfg_obj_asstring(obj); else cachename = view->name; cache = NULL; nsc = cachelist_find(cachelist, cachename, view->rdclass); if (nsc != NULL) { if (!cache_sharable(nsc->primaryview, view, zero_no_soattl, cleaning_interval, max_cache_size)) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, "views %s and %s can't share the cache " "due to configuration parameter mismatch", nsc->primaryview->name, view->name); result = ISC_R_FAILURE; goto cleanup; } dns_cache_attach(nsc->cache, &cache); shared_cache = ISC_TRUE; } else { if (strcmp(cachename, view->name) == 0) { result = dns_viewlist_find(&ns_g_server->viewlist, cachename, view->rdclass, &pview); if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS) goto cleanup; if (pview != NULL) { if (!cache_reusable(pview, view, zero_no_soattl)) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_DEBUG(1), "cache cannot be reused " "for view %s due to " "configuration parameter " "mismatch", view->name); } else { INSIST(pview->cache != NULL); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_DEBUG(3), "reusing existing cache"); reused_cache = ISC_TRUE; dns_cache_attach(pview->cache, &cache); } dns_view_getresstats(pview, &resstats); dns_view_getresquerystats(pview, &resquerystats); dns_view_detach(&pview); } } if (cache == NULL) { /* * Create a cache with the desired name. This normally * equals the view name, but may also be a forward * reference to a view that share the cache with this * view but is not yet configured. If it is not the * view name but not a forward reference either, then it * is simply a named cache that is not shared. * * We use two separate memory contexts for the * cache, for the main cache memory and the heap * memory. */ CHECK(isc_mem_create(0, 0, &cmctx)); isc_mem_setname(cmctx, "cache", NULL); CHECK(isc_mem_create(0, 0, &hmctx)); isc_mem_setname(hmctx, "cache_heap", NULL); CHECK(dns_cache_create3(cmctx, hmctx, ns_g_taskmgr, ns_g_timermgr, view->rdclass, cachename, "rbt", 0, NULL, &cache)); isc_mem_detach(&cmctx); isc_mem_detach(&hmctx); } nsc = isc_mem_get(mctx, sizeof(*nsc)); if (nsc == NULL) { result = ISC_R_NOMEMORY; goto cleanup; } nsc->cache = NULL; dns_cache_attach(cache, &nsc->cache); nsc->primaryview = view; nsc->needflush = ISC_FALSE; nsc->adbsizeadjusted = ISC_FALSE; nsc->rdclass = view->rdclass; ISC_LINK_INIT(nsc, link); ISC_LIST_APPEND(*cachelist, nsc, link); } dns_view_setcache2(view, cache, shared_cache); /* * cache-file cannot be inherited if views are present, but this * should be caught by the configuration checking stage. */ obj = NULL; result = ns_config_get(maps, "cache-file", &obj); if (result == ISC_R_SUCCESS && strcmp(view->name, "_bind") != 0) { CHECK(dns_cache_setfilename(cache, cfg_obj_asstring(obj))); if (!reused_cache && !shared_cache) CHECK(dns_cache_load(cache)); } dns_cache_setcleaninginterval(cache, cleaning_interval); dns_cache_setcachesize(cache, max_cache_size); dns_cache_detach(&cache); /* * Resolver. * * XXXRTH Hardwired number of tasks. */ CHECK(get_view_querysource_dispatch(maps, AF_INET, &dispatch4, &dscp4, ISC_TF(ISC_LIST_PREV(view, link) == NULL))); CHECK(get_view_querysource_dispatch(maps, AF_INET6, &dispatch6, &dscp6, ISC_TF(ISC_LIST_PREV(view, link) == NULL))); if (dispatch4 == NULL && dispatch6 == NULL) { UNEXPECTED_ERROR(__FILE__, __LINE__, "unable to obtain neither an IPv4 nor" " an IPv6 dispatch"); result = ISC_R_UNEXPECTED; goto cleanup; } if (resstats == NULL) { CHECK(isc_stats_create(mctx, &resstats, dns_resstatscounter_max)); } dns_view_setresstats(view, resstats); if (resquerystats == NULL) CHECK(dns_rdatatypestats_create(mctx, &resquerystats)); dns_view_setresquerystats(view, resquerystats); ndisp = 4 * ISC_MIN(ns_g_udpdisp, MAX_UDP_DISPATCH); CHECK(dns_view_createresolver(view, ns_g_taskmgr, RESOLVER_NTASKS, ndisp, ns_g_socketmgr, ns_g_timermgr, resopts, ns_g_dispatchmgr, dispatch4, dispatch6)); if (dscp4 == -1) dscp4 = ns_g_dscp; if (dscp6 == -1) dscp6 = ns_g_dscp; if (dscp4 != -1) dns_resolver_setquerydscp4(view->resolver, dscp4); if (dscp6 != -1) dns_resolver_setquerydscp6(view->resolver, dscp6); /* * Set the ADB cache size to 1/8th of the max-cache-size or * MAX_ADB_SIZE_FOR_CACHESHARE when the cache is shared. */ max_adb_size = 0; if (max_cache_size != 0U) { max_adb_size = max_cache_size / 8; if (max_adb_size == 0U) max_adb_size = 1; /* Force minimum. */ if (view != nsc->primaryview && max_adb_size > MAX_ADB_SIZE_FOR_CACHESHARE) { max_adb_size = MAX_ADB_SIZE_FOR_CACHESHARE; if (!nsc->adbsizeadjusted) { dns_adb_setadbsize(nsc->primaryview->adb, MAX_ADB_SIZE_FOR_CACHESHARE); nsc->adbsizeadjusted = ISC_TRUE; } } } dns_adb_setadbsize(view->adb, max_adb_size); /* * Set up ADB quotas */ { isc_uint32_t fps, freq; double low, high, discount; obj = NULL; result = ns_config_get(maps, "fetches-per-server", &obj); INSIST(result == ISC_R_SUCCESS); obj2 = cfg_tuple_get(obj, "fetches"); fps = cfg_obj_asuint32(obj2); obj2 = cfg_tuple_get(obj, "response"); if (!cfg_obj_isvoid(obj2)) { const char *resp = cfg_obj_asstring(obj2); isc_result_t r; if (strcasecmp(resp, "drop") == 0) r = DNS_R_DROP; else if (strcasecmp(resp, "fail") == 0) r = DNS_R_SERVFAIL; else INSIST(0); dns_resolver_setquotaresponse(view->resolver, dns_quotatype_server, r); } obj = NULL; result = ns_config_get(maps, "fetch-quota-params", &obj); INSIST(result == ISC_R_SUCCESS); obj2 = cfg_tuple_get(obj, "frequency"); freq = cfg_obj_asuint32(obj2); obj2 = cfg_tuple_get(obj, "low"); low = (double) cfg_obj_asfixedpoint(obj2) / 100.0; obj2 = cfg_tuple_get(obj, "high"); high = (double) cfg_obj_asfixedpoint(obj2) / 100.0; obj2 = cfg_tuple_get(obj, "discount"); discount = (double) cfg_obj_asfixedpoint(obj2) / 100.0; dns_adb_setquota(view->adb, fps, freq, low, high, discount); } /* * Set resolver's lame-ttl. */ obj = NULL; result = ns_config_get(maps, "lame-ttl", &obj); INSIST(result == ISC_R_SUCCESS); lame_ttl = cfg_obj_asuint32(obj); if (lame_ttl > 1800) lame_ttl = 1800; dns_resolver_setlamettl(view->resolver, lame_ttl); /* * Set the resolver's query timeout. */ obj = NULL; result = ns_config_get(maps, "resolver-query-timeout", &obj); INSIST(result == ISC_R_SUCCESS); query_timeout = cfg_obj_asuint32(obj); dns_resolver_settimeout(view->resolver, query_timeout); /* Specify whether to use 0-TTL for negative response for SOA query */ dns_resolver_setzeronosoattl(view->resolver, zero_no_soattl); /* * Set the resolver's EDNS UDP size. */ obj = NULL; result = ns_config_get(maps, "edns-udp-size", &obj); INSIST(result == ISC_R_SUCCESS); udpsize = cfg_obj_asuint32(obj); if (udpsize < 512) udpsize = 512; if (udpsize > 4096) udpsize = 4096; dns_resolver_setudpsize(view->resolver, (isc_uint16_t)udpsize); /* * Set the maximum UDP response size. */ obj = NULL; result = ns_config_get(maps, "max-udp-size", &obj); INSIST(result == ISC_R_SUCCESS); udpsize = cfg_obj_asuint32(obj); if (udpsize < 512) udpsize = 512; if (udpsize > 4096) udpsize = 4096; view->maxudp = udpsize; /* * Set the maximum UDP when a COOKIE is not provided. */ obj = NULL; result = ns_config_get(maps, "nocookie-udp-size", &obj); INSIST(result == ISC_R_SUCCESS); udpsize = cfg_obj_asuint32(obj); if (udpsize < 128) udpsize = 128; if (udpsize > view->maxudp) udpsize = view->maxudp; view->nocookieudp = udpsize; /* * Set the maximum rsa exponent bits. */ obj = NULL; result = ns_config_get(maps, "max-rsa-exponent-size", &obj); INSIST(result == ISC_R_SUCCESS); maxbits = cfg_obj_asuint32(obj); if (maxbits != 0 && maxbits < 35) maxbits = 35; if (maxbits > 4096) maxbits = 4096; view->maxbits = maxbits; /* * Set supported DNSSEC algorithms. */ dns_resolver_reset_algorithms(view->resolver); disabled = NULL; (void)ns_config_get(maps, "disable-algorithms", &disabled); if (disabled != NULL) { for (element = cfg_list_first(disabled); element != NULL; element = cfg_list_next(element)) CHECK(disable_algorithms(cfg_listelt_value(element), view->resolver)); } /* * Set supported DS/DLV digest types. */ dns_resolver_reset_ds_digests(view->resolver); disabled = NULL; (void)ns_config_get(maps, "disable-ds-digests", &disabled); if (disabled != NULL) { for (element = cfg_list_first(disabled); element != NULL; element = cfg_list_next(element)) CHECK(disable_ds_digests(cfg_listelt_value(element), view->resolver)); } /* * A global or view "forwarders" option, if present, * creates an entry for "." in the forwarding table. */ forwardtype = NULL; forwarders = NULL; (void)ns_config_get(maps, "forward", &forwardtype); (void)ns_config_get(maps, "forwarders", &forwarders); if (forwarders != NULL) CHECK(configure_forward(config, view, dns_rootname, forwarders, forwardtype)); /* * Dual Stack Servers. */ alternates = NULL; (void)ns_config_get(maps, "dual-stack-servers", &alternates); if (alternates != NULL) CHECK(configure_alternates(config, view, alternates)); /* * We have default hints for class IN if we need them. */ if (view->rdclass == dns_rdataclass_in && view->hints == NULL) dns_view_sethints(view, ns_g_server->in_roothints); /* * If we still have no hints, this is a non-IN view with no * "hints zone" configured. Issue a warning, except if this * is a root server. Root servers never need to consult * their hints, so it's no point requiring users to configure * them. */ if (view->hints == NULL) { dns_zone_t *rootzone = NULL; (void)dns_view_findzone(view, dns_rootname, &rootzone); if (rootzone != NULL) { dns_zone_detach(&rootzone); need_hints = ISC_FALSE; } if (need_hints) isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_WARNING, "no root hints for view '%s'", view->name); } /* * Configure the view's TSIG keys. */ CHECK(ns_tsigkeyring_fromconfig(config, vconfig, view->mctx, &ring)); if (ns_g_server->sessionkey != NULL) { CHECK(dns_tsigkeyring_add(ring, ns_g_server->session_keyname, ns_g_server->sessionkey)); } dns_view_setkeyring(view, ring); dns_tsigkeyring_detach(&ring); /* * See if we can re-use a dynamic key ring. */ result = dns_viewlist_find(&ns_g_server->viewlist, view->name, view->rdclass, &pview); if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS) goto cleanup; if (pview != NULL) { dns_view_getdynamickeyring(pview, &ring); if (ring != NULL) dns_view_setdynamickeyring(view, ring); dns_tsigkeyring_detach(&ring); dns_view_detach(&pview); } else dns_view_restorekeyring(view); /* * Configure the view's peer list. */ { const cfg_obj_t *peers = NULL; dns_peerlist_t *newpeers = NULL; (void)ns_config_get(cfgmaps, "server", &peers); CHECK(dns_peerlist_new(mctx, &newpeers)); for (element = cfg_list_first(peers); element != NULL; element = cfg_list_next(element)) { const cfg_obj_t *cpeer = cfg_listelt_value(element); dns_peer_t *peer; CHECK(configure_peer(cpeer, mctx, &peer)); dns_peerlist_addpeer(newpeers, peer); dns_peer_detach(&peer); } dns_peerlist_detach(&view->peers); view->peers = newpeers; /* Transfer ownership. */ } /* * Configure the views rrset-order. */ { const cfg_obj_t *rrsetorder = NULL; (void)ns_config_get(maps, "rrset-order", &rrsetorder); CHECK(dns_order_create(mctx, &order)); for (element = cfg_list_first(rrsetorder); element != NULL; element = cfg_list_next(element)) { const cfg_obj_t *ent = cfg_listelt_value(element); CHECK(configure_order(order, ent)); } if (view->order != NULL) dns_order_detach(&view->order); dns_order_attach(order, &view->order); dns_order_detach(&order); } /* * Copy the aclenv object. */ dns_aclenv_copy(&view->aclenv, &ns_g_server->aclenv); /* * Configure the "match-clients" and "match-destinations" ACL. * (These are only meaningful at the view level, but 'config' * must be passed so that named ACLs defined at the global level * can be retrieved.) */ CHECK(configure_view_acl(vconfig, config, NULL, "match-clients", NULL, actx, ns_g_mctx, &view->matchclients)); CHECK(configure_view_acl(vconfig, config, NULL, "match-destinations", NULL, actx, ns_g_mctx, &view->matchdestinations)); /* * Configure the "match-recursive-only" option. */ obj = NULL; (void)ns_config_get(maps, "match-recursive-only", &obj); if (obj != NULL && cfg_obj_asboolean(obj)) view->matchrecursiveonly = ISC_TRUE; else view->matchrecursiveonly = ISC_FALSE; /* * Configure other configurable data. */ obj = NULL; result = ns_config_get(maps, "recursion", &obj); INSIST(result == ISC_R_SUCCESS); view->recursion = cfg_obj_asboolean(obj); obj = NULL; result = ns_config_get(maps, "auth-nxdomain", &obj); INSIST(result == ISC_R_SUCCESS); view->auth_nxdomain = cfg_obj_asboolean(obj); obj = NULL; result = ns_config_get(maps, "minimal-any", &obj); INSIST(result == ISC_R_SUCCESS); view->minimal_any = cfg_obj_asboolean(obj); obj = NULL; result = ns_config_get(maps, "minimal-responses", &obj); INSIST(result == ISC_R_SUCCESS); if (cfg_obj_isboolean(obj)) { if (cfg_obj_asboolean(obj)) view->minimalresponses = dns_minimal_yes; else view->minimalresponses = dns_minimal_no; } else { str = cfg_obj_asstring(obj); if (strcasecmp(str, "no-auth") == 0) { view->minimalresponses = dns_minimal_noauth; } else if (strcasecmp(str, "no-auth-recursive") == 0) { view->minimalresponses = dns_minimal_noauthrec; } else INSIST(0); } obj = NULL; result = ns_config_get(maps, "transfer-format", &obj); INSIST(result == ISC_R_SUCCESS); str = cfg_obj_asstring(obj); if (strcasecmp(str, "many-answers") == 0) view->transfer_format = dns_many_answers; else if (strcasecmp(str, "one-answer") == 0) view->transfer_format = dns_one_answer; else INSIST(0); obj = NULL; result = ns_config_get(maps, "trust-anchor-telemetry", &obj); INSIST(result == ISC_R_SUCCESS); view->trust_anchor_telemetry = cfg_obj_asboolean(obj); CHECK(configure_view_acl(vconfig, config, ns_g_config, "allow-query-cache-on", NULL, actx, ns_g_mctx, &view->cacheonacl)); /* * Set sources where additional data and CNAME/DNAME * targets for authoritative answers may be found. */ obj = NULL; result = ns_config_get(maps, "additional-from-auth", &obj); INSIST(result == ISC_R_SUCCESS); view->additionalfromauth = cfg_obj_asboolean(obj); if (view->recursion && ! view->additionalfromauth) { cfg_obj_log(obj, ns_g_lctx, ISC_LOG_WARNING, "'additional-from-auth no' is only supported " "with 'recursion no'"); view->additionalfromauth = ISC_TRUE; } obj = NULL; result = ns_config_get(maps, "additional-from-cache", &obj); INSIST(result == ISC_R_SUCCESS); view->additionalfromcache = cfg_obj_asboolean(obj); if (view->recursion && ! view->additionalfromcache) { cfg_obj_log(obj, ns_g_lctx, ISC_LOG_WARNING, "'additional-from-cache no' is only supported " "with 'recursion no'"); view->additionalfromcache = ISC_TRUE; } /* * Set "allow-query-cache", "allow-recursion", and * "allow-recursion-on" acls if configured in named.conf. * (Ignore the global defaults for now, because these ACLs * can inherit from each other when only some of them set at * the options/view level.) */ CHECK(configure_view_acl(vconfig, config, NULL, "allow-query-cache", NULL, actx, ns_g_mctx, &view->cacheacl)); if (strcmp(view->name, "_bind") != 0 && view->rdclass != dns_rdataclass_chaos) { CHECK(configure_view_acl(vconfig, config, NULL, "allow-recursion", NULL, actx, ns_g_mctx, &view->recursionacl)); CHECK(configure_view_acl(vconfig, config, NULL, "allow-recursion-on", NULL, actx, ns_g_mctx, &view->recursiononacl)); } if (view->recursion) { /* * "allow-query-cache" inherits from "allow-recursion" if set, * otherwise from "allow-query" if set. * "allow-recursion" inherits from "allow-query-cache" if set, * otherwise from "allow-query" if set. */ if (view->cacheacl == NULL) { if (view->recursionacl != NULL) { dns_acl_attach(view->recursionacl, &view->cacheacl); } else if (view->queryacl != NULL) { dns_acl_attach(view->queryacl, &view->cacheacl); } } if (view->recursionacl == NULL) { if (view->cacheacl != NULL) { dns_acl_attach(view->cacheacl, &view->recursionacl); } else if (view->queryacl != NULL) { dns_acl_attach(view->queryacl, &view->recursionacl); } } /* * If any are still unset, we now get default "allow-recursion", * "allow-recursion-on" and "allow-query-cache" ACLs from * the global config. */ if (view->recursionacl == NULL) { CHECK(configure_view_acl(NULL, NULL, ns_g_config, "allow-recursion", NULL, actx, ns_g_mctx, &view->recursionacl)); } if (view->recursiononacl == NULL) { CHECK(configure_view_acl(NULL, NULL, ns_g_config, "allow-recursion-on", NULL, actx, ns_g_mctx, &view->recursiononacl)); } if (view->cacheacl == NULL) { CHECK(configure_view_acl(NULL, NULL, ns_g_config, "allow-query-cache", NULL, actx, ns_g_mctx, &view->cacheacl)); } } else if (view->cacheacl == NULL) { /* * We're not recursive; if "allow-query-cache" hasn't been * set at the options/view level, set it to none. */ CHECK(dns_acl_none(mctx, &view->cacheacl)); } /* * Ignore case when compressing responses to the specified * clients. This causes case not always to be preserved, * and is needed by some broken clients. */ CHECK(configure_view_acl(vconfig, config, ns_g_config, "no-case-compress", NULL, actx, ns_g_mctx, &view->nocasecompress)); /* * Disable name compression completely, this is a tradeoff * between CPU and network usage. */ obj = NULL; result = ns_config_get(maps, "message-compression", &obj); INSIST(result == ISC_R_SUCCESS); view->msgcompression = cfg_obj_asboolean(obj); /* * Filter setting on addresses in the answer section. */ CHECK(configure_view_acl(vconfig, config, ns_g_config, "deny-answer-addresses", "acl", actx, ns_g_mctx, &view->denyansweracl)); CHECK(configure_view_nametable(vconfig, config, "deny-answer-addresses", "except-from", ns_g_mctx, &view->answeracl_exclude)); /* * Filter setting on names (CNAME/DNAME targets) in the answer section. */ CHECK(configure_view_nametable(vconfig, config, "deny-answer-aliases", "name", ns_g_mctx, &view->denyanswernames)); CHECK(configure_view_nametable(vconfig, config, "deny-answer-aliases", "except-from", ns_g_mctx, &view->answernames_exclude)); /* * Configure sortlist, if set */ CHECK(configure_view_sortlist(vconfig, config, actx, ns_g_mctx, &view->sortlist)); /* * Configure default allow-notify, allow-update * and allow-update-forwarding ACLs, so they can be * inherited by zones. (Note these cannot be set at * options/view level.) */ if (view->notifyacl == NULL) { CHECK(configure_view_acl(vconfig, config, ns_g_config, "allow-notify", NULL, actx, ns_g_mctx, &view->notifyacl)); } if (view->updateacl == NULL) { CHECK(configure_view_acl(NULL, NULL, ns_g_config, "allow-update", NULL, actx, ns_g_mctx, &view->updateacl)); } if (view->upfwdacl == NULL) { CHECK(configure_view_acl(NULL, NULL, ns_g_config, "allow-update-forwarding", NULL, actx, ns_g_mctx, &view->upfwdacl)); } /* * Configure default allow-transer ACL so it can be inherited * by zones. (Note this *can* be set at options or view level.) */ if (view->transferacl == NULL) { CHECK(configure_view_acl(vconfig, config, ns_g_config, "allow-transfer", NULL, actx, ns_g_mctx, &view->transferacl)); } obj = NULL; result = ns_config_get(maps, "provide-ixfr", &obj); INSIST(result == ISC_R_SUCCESS); view->provideixfr = cfg_obj_asboolean(obj); obj = NULL; result = ns_config_get(maps, "request-nsid", &obj); INSIST(result == ISC_R_SUCCESS); view->requestnsid = cfg_obj_asboolean(obj); obj = NULL; result = ns_config_get(maps, "send-cookie", &obj); INSIST(result == ISC_R_SUCCESS); view->sendcookie = cfg_obj_asboolean(obj); obj = NULL; result = ns_config_get(maps, "require-server-cookie", &obj); INSIST(result == ISC_R_SUCCESS); view->requireservercookie = cfg_obj_asboolean(obj); obj = NULL; result = ns_config_get(maps, "v6-bias", &obj); INSIST(result == ISC_R_SUCCESS); view->v6bias = cfg_obj_asuint32(obj) * 1000; obj = NULL; result = ns_config_get(maps, "max-clients-per-query", &obj); INSIST(result == ISC_R_SUCCESS); max_clients_per_query = cfg_obj_asuint32(obj); obj = NULL; result = ns_config_get(maps, "clients-per-query", &obj); INSIST(result == ISC_R_SUCCESS); dns_resolver_setclientsperquery(view->resolver, cfg_obj_asuint32(obj), max_clients_per_query); obj = NULL; result = ns_config_get(maps, "max-recursion-depth", &obj); INSIST(result == ISC_R_SUCCESS); dns_resolver_setmaxdepth(view->resolver, cfg_obj_asuint32(obj)); obj = NULL; result = ns_config_get(maps, "max-recursion-queries", &obj); INSIST(result == ISC_R_SUCCESS); dns_resolver_setmaxqueries(view->resolver, cfg_obj_asuint32(obj)); obj = NULL; result = ns_config_get(maps, "fetches-per-zone", &obj); INSIST(result == ISC_R_SUCCESS); obj2 = cfg_tuple_get(obj, "fetches"); dns_resolver_setfetchesperzone(view->resolver, cfg_obj_asuint32(obj2)); obj2 = cfg_tuple_get(obj, "response"); if (!cfg_obj_isvoid(obj2)) { const char *resp = cfg_obj_asstring(obj2); isc_result_t r; if (strcasecmp(resp, "drop") == 0) r = DNS_R_DROP; else if (strcasecmp(resp, "fail") == 0) r = DNS_R_SERVFAIL; else INSIST(0); dns_resolver_setquotaresponse(view->resolver, dns_quotatype_zone, r); } #ifdef ALLOW_FILTER_AAAA obj = NULL; result = ns_config_get(maps, "filter-aaaa-on-v4", &obj); INSIST(result == ISC_R_SUCCESS); if (cfg_obj_isboolean(obj)) { if (cfg_obj_asboolean(obj)) view->v4_aaaa = dns_aaaa_filter; else view->v4_aaaa = dns_aaaa_ok; } else { const char *v4_aaaastr = cfg_obj_asstring(obj); if (strcasecmp(v4_aaaastr, "break-dnssec") == 0) view->v4_aaaa = dns_aaaa_break_dnssec; else INSIST(0); } obj = NULL; result = ns_config_get(maps, "filter-aaaa-on-v6", &obj); INSIST(result == ISC_R_SUCCESS); if (cfg_obj_isboolean(obj)) { if (cfg_obj_asboolean(obj)) view->v6_aaaa = dns_aaaa_filter; else view->v6_aaaa = dns_aaaa_ok; } else { const char *v6_aaaastr = cfg_obj_asstring(obj); if (strcasecmp(v6_aaaastr, "break-dnssec") == 0) view->v6_aaaa = dns_aaaa_break_dnssec; else INSIST(0); } CHECK(configure_view_acl(vconfig, config, ns_g_config, "filter-aaaa", NULL, actx, ns_g_mctx, &view->aaaa_acl)); #endif obj = NULL; result = ns_config_get(maps, "prefetch", &obj); if (result == ISC_R_SUCCESS) { const cfg_obj_t *trigger, *eligible; trigger = cfg_tuple_get(obj, "trigger"); view->prefetch_trigger = cfg_obj_asuint32(trigger); if (view->prefetch_trigger > 10) view->prefetch_trigger = 10; eligible = cfg_tuple_get(obj, "eligible"); if (cfg_obj_isvoid(eligible)) { int m; for (m = 1; maps[m] != NULL; m++) { obj = NULL; result = ns_config_get(&maps[m], "prefetch", &obj); INSIST(result == ISC_R_SUCCESS); eligible = cfg_tuple_get(obj, "eligible"); if (cfg_obj_isuint32(eligible)) break; } INSIST(cfg_obj_isuint32(eligible)); } view->prefetch_eligible = cfg_obj_asuint32(eligible); if (view->prefetch_eligible < view->prefetch_trigger + 6) view->prefetch_eligible = view->prefetch_trigger + 6; } obj = NULL; result = ns_config_get(maps, "dnssec-enable", &obj); INSIST(result == ISC_R_SUCCESS); view->enablednssec = cfg_obj_asboolean(obj); obj = NULL; result = ns_config_get(optionmaps, "dnssec-lookaside", &obj); if (result == ISC_R_SUCCESS) { /* "auto" is deprecated, log a warning if seen */ const char *dom; dlvobj = cfg_listelt_value(cfg_list_first(obj)); dom = cfg_obj_asstring(cfg_tuple_get(dlvobj, "domain")); if (cfg_obj_isvoid(cfg_tuple_get(dlvobj, "trust-anchor"))) { /* If "no", skip; if "auto", log warning */ if (!strcasecmp(dom, "no")) { result = ISC_R_NOTFOUND; } else if (!strcasecmp(dom, "auto")) { /* * Warning logged by libbind9. */ result = ISC_R_NOTFOUND; } } } if (result == ISC_R_SUCCESS) { dns_name_t *dlv, *iscdlv; dns_fixedname_t f; dns_fixedname_init(&f); /* Also log a warning if manually configured to dlv.isc.org */ iscdlv = dns_fixedname_name(&f); CHECK(dns_name_fromstring(iscdlv, "dlv.isc.org", 0, NULL)); for (element = cfg_list_first(obj); element != NULL; element = cfg_list_next(element)) { obj = cfg_listelt_value(element); obj = cfg_tuple_get(obj, "trust-anchor"); dlv = dns_fixedname_name(&view->dlv_fixed); CHECK(dns_name_fromstring(dlv, cfg_obj_asstring(obj), DNS_NAME_DOWNCASE, NULL)); if (dns_name_equal(dlv, iscdlv)) { /* * Warning logged by libbind9. */ view->dlv = NULL; } else { view->dlv = dlv; } } } else { view->dlv = NULL; } /* * For now, there is only one kind of trusted keys, the * "security roots". */ CHECK(configure_view_dnsseckeys(view, vconfig, config, bindkeys, auto_root, mctx)); dns_resolver_resetmustbesecure(view->resolver); obj = NULL; result = ns_config_get(maps, "dnssec-must-be-secure", &obj); if (result == ISC_R_SUCCESS) CHECK(mustbesecure(obj, view->resolver)); obj = NULL; result = ns_config_get(maps, "nta-recheck", &obj); INSIST(result == ISC_R_SUCCESS); view->nta_recheck = cfg_obj_asuint32(obj); obj = NULL; result = ns_config_get(maps, "nta-lifetime", &obj); INSIST(result == ISC_R_SUCCESS); view->nta_lifetime = cfg_obj_asuint32(obj); obj = NULL; result = ns_config_get(maps, "preferred-glue", &obj); if (result == ISC_R_SUCCESS) { str = cfg_obj_asstring(obj); if (strcasecmp(str, "a") == 0) view->preferred_glue = dns_rdatatype_a; else if (strcasecmp(str, "aaaa") == 0) view->preferred_glue = dns_rdatatype_aaaa; else view->preferred_glue = 0; } else view->preferred_glue = 0; obj = NULL; result = ns_config_get(maps, "root-delegation-only", &obj); if (result == ISC_R_SUCCESS) dns_view_setrootdelonly(view, ISC_TRUE); if (result == ISC_R_SUCCESS && ! cfg_obj_isvoid(obj)) { const cfg_obj_t *exclude; dns_fixedname_t fixed; dns_name_t *name; dns_fixedname_init(&fixed); name = dns_fixedname_name(&fixed); for (element = cfg_list_first(obj); element != NULL; element = cfg_list_next(element)) { exclude = cfg_listelt_value(element); CHECK(dns_name_fromstring(name, cfg_obj_asstring(exclude), 0, NULL)); CHECK(dns_view_excludedelegationonly(view, name)); } } else dns_view_setrootdelonly(view, ISC_FALSE); /* * Load DynDB modules. */ dyndb_list = NULL; if (voptions != NULL) (void)cfg_map_get(voptions, "dyndb", &dyndb_list); else (void)cfg_map_get(config, "dyndb", &dyndb_list); #ifdef HAVE_DLOPEN for (element = cfg_list_first(dyndb_list); element != NULL; element = cfg_list_next(element)) { const cfg_obj_t *dyndb = cfg_listelt_value(element); if (dctx == NULL) { const void *hashinit = isc_hash_get_initializer(); CHECK(dns_dyndb_createctx(mctx, hashinit, ns_g_lctx, view, ns_g_server->zonemgr, ns_g_server->task, ns_g_timermgr, &dctx)); } CHECK(configure_dyndb(dyndb, mctx, dctx)); } #endif /* * Setup automatic empty zones. If recursion is off then * they are disabled by default. */ obj = NULL; (void)ns_config_get(maps, "empty-zones-enable", &obj); (void)ns_config_get(maps, "disable-empty-zone", &disablelist); if (obj == NULL && disablelist == NULL && view->rdclass == dns_rdataclass_in) { empty_zones_enable = view->recursion; } else if (view->rdclass == dns_rdataclass_in) { if (obj != NULL) empty_zones_enable = cfg_obj_asboolean(obj); else empty_zones_enable = view->recursion; } else { empty_zones_enable = ISC_FALSE; } if (empty_zones_enable && !lwresd_g_useresolvconf) { const char *empty; int empty_zone = 0; dns_fixedname_t fixed; dns_name_t *name; isc_buffer_t buffer; char server[DNS_NAME_FORMATSIZE + 1]; char contact[DNS_NAME_FORMATSIZE + 1]; const char *empty_dbtype[4] = { "_builtin", "empty", NULL, NULL }; int empty_dbtypec = 4; dns_zonestat_level_t statlevel; dns_fixedname_init(&fixed); name = dns_fixedname_name(&fixed); obj = NULL; result = ns_config_get(maps, "empty-server", &obj); if (result == ISC_R_SUCCESS) { CHECK(dns_name_fromstring(name, cfg_obj_asstring(obj), 0, NULL)); isc_buffer_init(&buffer, server, sizeof(server) - 1); CHECK(dns_name_totext(name, ISC_FALSE, &buffer)); server[isc_buffer_usedlength(&buffer)] = 0; empty_dbtype[2] = server; } else empty_dbtype[2] = "@"; obj = NULL; result = ns_config_get(maps, "empty-contact", &obj); if (result == ISC_R_SUCCESS) { CHECK(dns_name_fromstring(name, cfg_obj_asstring(obj), 0, NULL)); isc_buffer_init(&buffer, contact, sizeof(contact) - 1); CHECK(dns_name_totext(name, ISC_FALSE, &buffer)); contact[isc_buffer_usedlength(&buffer)] = 0; empty_dbtype[3] = contact; } else empty_dbtype[3] = "."; obj = NULL; result = ns_config_get(maps, "zone-statistics", &obj); INSIST(result == ISC_R_SUCCESS); if (cfg_obj_isboolean(obj)) { if (cfg_obj_asboolean(obj)) statlevel = dns_zonestat_full; else statlevel = dns_zonestat_none; } else { const char *levelstr = cfg_obj_asstring(obj); if (strcasecmp(levelstr, "full") == 0) statlevel = dns_zonestat_full; else if (strcasecmp(levelstr, "terse") == 0) statlevel = dns_zonestat_terse; else if (strcasecmp(levelstr, "none") == 0) statlevel = dns_zonestat_none; else INSIST(0); } for (empty = empty_zones[empty_zone]; empty != NULL; empty = empty_zones[++empty_zone]) { dns_forwarders_t *dnsforwarders = NULL; /* * Look for zone on drop list. */ CHECK(dns_name_fromstring(name, empty, 0, NULL)); if (disablelist != NULL && on_disable_list(disablelist, name)) continue; /* * This zone already exists. */ (void)dns_view_findzone(view, name, &zone); if (zone != NULL) { dns_zone_detach(&zone); continue; } /* * If we would forward this name don't add a * empty zone for it. */ result = dns_fwdtable_find(view->fwdtable, name, &dnsforwarders); if (result == ISC_R_SUCCESS && dnsforwarders->fwdpolicy == dns_fwdpolicy_only) continue; /* * See if we can re-use a existing zone. */ result = dns_viewlist_find(&ns_g_server->viewlist, view->name, view->rdclass, &pview); if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS) goto cleanup; if (pview != NULL) { (void)dns_view_findzone(pview, name, &zone); dns_view_detach(&pview); } CHECK(create_empty_zone(zone, name, view, zonelist, empty_dbtype, empty_dbtypec, statlevel)); if (zone != NULL) dns_zone_detach(&zone); } } obj = NULL; result = ns_config_get(maps, "rate-limit", &obj); if (result == ISC_R_SUCCESS) { result = configure_rrl(view, config, obj); if (result != ISC_R_SUCCESS) goto cleanup; } /* * Set the servfail-ttl. */ obj = NULL; result = ns_config_get(maps, "servfail-ttl", &obj); INSIST(result == ISC_R_SUCCESS); fail_ttl = cfg_obj_asuint32(obj); if (fail_ttl > 30) fail_ttl = 30; dns_view_setfailttl(view, fail_ttl); /* * Name space to look up redirect information in. */ obj = NULL; result = ns_config_get(maps, "nxdomain-redirect", &obj); if (result == ISC_R_SUCCESS) { dns_name_t *name = dns_fixedname_name(&view->redirectfixed); CHECK(dns_name_fromstring(name, cfg_obj_asstring(obj), 0, NULL)); view->redirectzone = name; } else view->redirectzone = NULL; #ifdef HAVE_DNSTAP /* * Set up the dnstap environment and configure message * types to log. */ CHECK(configure_dnstap(maps, view)); #endif /* HAVE_DNSTAP */ result = ISC_R_SUCCESS; cleanup: if (clients != NULL) dns_acl_detach(&clients); if (mapped != NULL) dns_acl_detach(&mapped); if (excluded != NULL) dns_acl_detach(&excluded); if (ring != NULL) dns_tsigkeyring_detach(&ring); if (zone != NULL) dns_zone_detach(&zone); if (dispatch4 != NULL) dns_dispatch_detach(&dispatch4); if (dispatch6 != NULL) dns_dispatch_detach(&dispatch6); if (resstats != NULL) isc_stats_detach(&resstats); if (resquerystats != NULL) dns_stats_detach(&resquerystats); if (order != NULL) dns_order_detach(&order); if (cmctx != NULL) isc_mem_detach(&cmctx); if (hmctx != NULL) isc_mem_detach(&hmctx); if (cache != NULL) dns_cache_detach(&cache); if (dctx != NULL) dns_dyndb_destroyctx(&dctx); return (result); } static isc_result_t configure_hints(dns_view_t *view, const char *filename) { isc_result_t result; dns_db_t *db; db = NULL; result = dns_rootns_create(view->mctx, view->rdclass, filename, &db); if (result == ISC_R_SUCCESS) { dns_view_sethints(view, db); dns_db_detach(&db); } return (result); } static isc_result_t configure_alternates(const cfg_obj_t *config, dns_view_t *view, const cfg_obj_t *alternates) { const cfg_obj_t *portobj; const cfg_obj_t *addresses; const cfg_listelt_t *element; isc_result_t result = ISC_R_SUCCESS; in_port_t port; /* * Determine which port to send requests to. */ if (ns_g_lwresdonly && ns_g_port != 0) port = ns_g_port; else CHECKM(ns_config_getport(config, &port), "port"); if (alternates != NULL) { portobj = cfg_tuple_get(alternates, "port"); if (cfg_obj_isuint32(portobj)) { isc_uint32_t val = cfg_obj_asuint32(portobj); if (val > ISC_UINT16_MAX) { cfg_obj_log(portobj, ns_g_lctx, ISC_LOG_ERROR, "port '%u' out of range", val); return (ISC_R_RANGE); } port = (in_port_t) val; } } addresses = NULL; if (alternates != NULL) addresses = cfg_tuple_get(alternates, "addresses"); for (element = cfg_list_first(addresses); element != NULL; element = cfg_list_next(element)) { const cfg_obj_t *alternate = cfg_listelt_value(element); isc_sockaddr_t sa; if (!cfg_obj_issockaddr(alternate)) { dns_fixedname_t fixed; dns_name_t *name; const char *str = cfg_obj_asstring(cfg_tuple_get( alternate, "name")); isc_buffer_t buffer; in_port_t myport = port; isc_buffer_constinit(&buffer, str, strlen(str)); isc_buffer_add(&buffer, strlen(str)); dns_fixedname_init(&fixed); name = dns_fixedname_name(&fixed); CHECK(dns_name_fromtext(name, &buffer, dns_rootname, 0, NULL)); portobj = cfg_tuple_get(alternate, "port"); if (cfg_obj_isuint32(portobj)) { isc_uint32_t val = cfg_obj_asuint32(portobj); if (val > ISC_UINT16_MAX) { cfg_obj_log(portobj, ns_g_lctx, ISC_LOG_ERROR, "port '%u' out of range", val); return (ISC_R_RANGE); } myport = (in_port_t) val; } CHECK(dns_resolver_addalternate(view->resolver, NULL, name, myport)); continue; } sa = *cfg_obj_assockaddr(alternate); if (isc_sockaddr_getport(&sa) == 0) isc_sockaddr_setport(&sa, port); CHECK(dns_resolver_addalternate(view->resolver, &sa, NULL, 0)); } cleanup: return (result); } static isc_result_t configure_forward(const cfg_obj_t *config, dns_view_t *view, dns_name_t *origin, const cfg_obj_t *forwarders, const cfg_obj_t *forwardtype) { const cfg_obj_t *portobj, *dscpobj; const cfg_obj_t *faddresses; const cfg_listelt_t *element; dns_fwdpolicy_t fwdpolicy = dns_fwdpolicy_none; dns_forwarderlist_t fwdlist; dns_forwarder_t *fwd; isc_result_t result; in_port_t port; isc_dscp_t dscp = -1; ISC_LIST_INIT(fwdlist); /* * Determine which port to send forwarded requests to. */ if (ns_g_lwresdonly && ns_g_port != 0) port = ns_g_port; else CHECKM(ns_config_getport(config, &port), "port"); if (forwarders != NULL) { portobj = cfg_tuple_get(forwarders, "port"); if (cfg_obj_isuint32(portobj)) { isc_uint32_t val = cfg_obj_asuint32(portobj); if (val > ISC_UINT16_MAX) { cfg_obj_log(portobj, ns_g_lctx, ISC_LOG_ERROR, "port '%u' out of range", val); return (ISC_R_RANGE); } port = (in_port_t) val; } } /* * DSCP value for forwarded requests. */ dscp = ns_g_dscp; if (forwarders != NULL) { dscpobj = cfg_tuple_get(forwarders, "dscp"); if (cfg_obj_isuint32(dscpobj)) { if (cfg_obj_asuint32(dscpobj) > 63) { cfg_obj_log(dscpobj, ns_g_lctx, ISC_LOG_ERROR, "dscp value '%u' is out of range", cfg_obj_asuint32(dscpobj)); return (ISC_R_RANGE); } dscp = (isc_dscp_t)cfg_obj_asuint32(dscpobj); } } faddresses = NULL; if (forwarders != NULL) faddresses = cfg_tuple_get(forwarders, "addresses"); for (element = cfg_list_first(faddresses); element != NULL; element = cfg_list_next(element)) { const cfg_obj_t *forwarder = cfg_listelt_value(element); fwd = isc_mem_get(view->mctx, sizeof(dns_forwarder_t)); if (fwd == NULL) { result = ISC_R_NOMEMORY; goto cleanup; } fwd->addr = *cfg_obj_assockaddr(forwarder); if (isc_sockaddr_getport(&fwd->addr) == 0) isc_sockaddr_setport(&fwd->addr, port); fwd->dscp = cfg_obj_getdscp(forwarder); if (fwd->dscp == -1) fwd->dscp = dscp; ISC_LINK_INIT(fwd, link); ISC_LIST_APPEND(fwdlist, fwd, link); } if (ISC_LIST_EMPTY(fwdlist)) { if (forwardtype != NULL) cfg_obj_log(forwardtype, ns_g_lctx, ISC_LOG_WARNING, "no forwarders seen; disabling " "forwarding"); fwdpolicy = dns_fwdpolicy_none; } else { if (forwardtype == NULL) fwdpolicy = dns_fwdpolicy_first; else { const char *forwardstr = cfg_obj_asstring(forwardtype); if (strcasecmp(forwardstr, "first") == 0) fwdpolicy = dns_fwdpolicy_first; else if (strcasecmp(forwardstr, "only") == 0) fwdpolicy = dns_fwdpolicy_only; else INSIST(0); } } result = dns_fwdtable_addfwd(view->fwdtable, origin, &fwdlist, fwdpolicy); if (result != ISC_R_SUCCESS) { char namebuf[DNS_NAME_FORMATSIZE]; dns_name_format(origin, namebuf, sizeof(namebuf)); cfg_obj_log(forwarders, ns_g_lctx, ISC_LOG_WARNING, "could not set up forwarding for domain '%s': %s", namebuf, isc_result_totext(result)); goto cleanup; } result = ISC_R_SUCCESS; cleanup: while (!ISC_LIST_EMPTY(fwdlist)) { fwd = ISC_LIST_HEAD(fwdlist); ISC_LIST_UNLINK(fwdlist, fwd, link); isc_mem_put(view->mctx, fwd, sizeof(dns_forwarder_t)); } return (result); } static isc_result_t get_viewinfo(const cfg_obj_t *vconfig, const char **namep, dns_rdataclass_t *classp) { isc_result_t result = ISC_R_SUCCESS; const char *viewname; dns_rdataclass_t viewclass; REQUIRE(namep != NULL && *namep == NULL); REQUIRE(classp != NULL); if (vconfig != NULL) { const cfg_obj_t *classobj = NULL; viewname = cfg_obj_asstring(cfg_tuple_get(vconfig, "name")); classobj = cfg_tuple_get(vconfig, "class"); CHECK(ns_config_getclass(classobj, dns_rdataclass_in, &viewclass)); if (dns_rdataclass_ismeta(viewclass)) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, "view '%s': class must not be meta", viewname); CHECK(ISC_R_FAILURE); } } else { viewname = "_default"; viewclass = dns_rdataclass_in; } *namep = viewname; *classp = viewclass; cleanup: return (result); } /* * Find a view based on its configuration info and attach to it. * * If 'vconfig' is NULL, attach to the default view. */ static isc_result_t find_view(const cfg_obj_t *vconfig, dns_viewlist_t *viewlist, dns_view_t **viewp) { isc_result_t result; const char *viewname = NULL; dns_rdataclass_t viewclass; dns_view_t *view = NULL; result = get_viewinfo(vconfig, &viewname, &viewclass); if (result != ISC_R_SUCCESS) return (result); result = dns_viewlist_find(viewlist, viewname, viewclass, &view); if (result != ISC_R_SUCCESS) return (result); *viewp = view; return (ISC_R_SUCCESS); } /* * Create a new view and add it to the list. * * If 'vconfig' is NULL, create the default view. * * The view created is attached to '*viewp'. */ static isc_result_t create_view(const cfg_obj_t *vconfig, dns_viewlist_t *viewlist, dns_view_t **viewp) { isc_result_t result; const char *viewname = NULL; dns_rdataclass_t viewclass; dns_view_t *view = NULL; result = get_viewinfo(vconfig, &viewname, &viewclass); if (result != ISC_R_SUCCESS) return (result); result = dns_viewlist_find(viewlist, viewname, viewclass, &view); if (result == ISC_R_SUCCESS) return (ISC_R_EXISTS); if (result != ISC_R_NOTFOUND) return (result); INSIST(view == NULL); result = dns_view_create(ns_g_mctx, viewclass, viewname, &view); if (result != ISC_R_SUCCESS) return (result); result = isc_entropy_getdata(ns_g_entropy, view->secret, sizeof(view->secret), NULL, 0); if (result != ISC_R_SUCCESS) { dns_view_detach(&view); return (result); } #ifdef HAVE_GEOIP view->aclenv.geoip = ns_g_geoip; #endif ISC_LIST_APPEND(*viewlist, view, link); dns_view_attach(view, viewp); return (ISC_R_SUCCESS); } /* * Configure or reconfigure a zone. */ static isc_result_t configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig, const cfg_obj_t *vconfig, isc_mem_t *mctx, dns_view_t *view, dns_viewlist_t *viewlist, cfg_aclconfctx_t *aclconf, isc_boolean_t added, isc_boolean_t old_rpz_ok, isc_boolean_t modify) { dns_view_t *pview = NULL; /* Production view */ dns_zone_t *zone = NULL; /* New or reused zone */ dns_zone_t *raw = NULL; /* New or reused raw zone */ dns_zone_t *dupzone = NULL; const cfg_obj_t *options = NULL; const cfg_obj_t *zoptions = NULL; const cfg_obj_t *typeobj = NULL; const cfg_obj_t *forwarders = NULL; const cfg_obj_t *forwardtype = NULL; const cfg_obj_t *only = NULL; const cfg_obj_t *signing = NULL; const cfg_obj_t *viewobj = NULL; isc_result_t result; isc_result_t tresult; isc_buffer_t buffer; dns_fixedname_t fixorigin; dns_name_t *origin; const char *zname; dns_rdataclass_t zclass; const char *ztypestr; dns_rpz_num_t rpz_num; isc_boolean_t zone_is_catz = ISC_FALSE; options = NULL; (void)cfg_map_get(config, "options", &options); zoptions = cfg_tuple_get(zconfig, "options"); /* * Get the zone origin as a dns_name_t. */ zname = cfg_obj_asstring(cfg_tuple_get(zconfig, "name")); isc_buffer_constinit(&buffer, zname, strlen(zname)); isc_buffer_add(&buffer, strlen(zname)); dns_fixedname_init(&fixorigin); CHECK(dns_name_fromtext(dns_fixedname_name(&fixorigin), &buffer, dns_rootname, 0, NULL)); origin = dns_fixedname_name(&fixorigin); CHECK(ns_config_getclass(cfg_tuple_get(zconfig, "class"), view->rdclass, &zclass)); if (zclass != view->rdclass) { const char *vname = NULL; if (vconfig != NULL) vname = cfg_obj_asstring(cfg_tuple_get(vconfig, "name")); else vname = ""; isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, "zone '%s': wrong class for view '%s'", zname, vname); result = ISC_R_FAILURE; goto cleanup; } (void)cfg_map_get(zoptions, "in-view", &viewobj); if (viewobj != NULL) { const char *inview = cfg_obj_asstring(viewobj); dns_view_t *otherview = NULL; if (viewlist == NULL) { cfg_obj_log(zconfig, ns_g_lctx, ISC_LOG_ERROR, "'in-view' option is not permitted in " "dynamically added zones"); result = ISC_R_FAILURE; goto cleanup; } result = dns_viewlist_find(viewlist, inview, view->rdclass, &otherview); if (result != ISC_R_SUCCESS) { cfg_obj_log(zconfig, ns_g_lctx, ISC_LOG_ERROR, "view '%s' is not yet defined.", inview); result = ISC_R_FAILURE; goto cleanup; } result = dns_view_findzone(otherview, origin, &zone); dns_view_detach(&otherview); if (result != ISC_R_SUCCESS) { cfg_obj_log(zconfig, ns_g_lctx, ISC_LOG_ERROR, "zone '%s' not defined in view '%s'", zname, inview); result = ISC_R_FAILURE; goto cleanup; } CHECK(dns_view_addzone(view, zone)); dns_zone_detach(&zone); /* * If the zone contains a 'forwarders' statement, configure * selective forwarding. Note: this is not inherited from the * other view. */ forwarders = NULL; result = cfg_map_get(zoptions, "forwarders", &forwarders); if (result == ISC_R_SUCCESS) { forwardtype = NULL; (void)cfg_map_get(zoptions, "forward", &forwardtype); CHECK(configure_forward(config, view, origin, forwarders, forwardtype)); } result = ISC_R_SUCCESS; goto cleanup; } (void)cfg_map_get(zoptions, "type", &typeobj); if (typeobj == NULL) { cfg_obj_log(zconfig, ns_g_lctx, ISC_LOG_ERROR, "zone '%s' 'type' not specified", zname); result = ISC_R_FAILURE; goto cleanup; } ztypestr = cfg_obj_asstring(typeobj); /* * "hints zones" aren't zones. If we've got one, * configure it and return. */ if (strcasecmp(ztypestr, "hint") == 0) { const cfg_obj_t *fileobj = NULL; if (cfg_map_get(zoptions, "file", &fileobj) != ISC_R_SUCCESS) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, "zone '%s': 'file' not specified", zname); result = ISC_R_FAILURE; goto cleanup; } if (dns_name_equal(origin, dns_rootname)) { const char *hintsfile = cfg_obj_asstring(fileobj); CHECK(configure_hints(view, hintsfile)); /* * Hint zones may also refer to delegation only points. */ only = NULL; tresult = cfg_map_get(zoptions, "delegation-only", &only); if (tresult == ISC_R_SUCCESS && cfg_obj_asboolean(only)) CHECK(dns_view_adddelegationonly(view, origin)); } else { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_WARNING, "ignoring non-root hint zone '%s'", zname); result = ISC_R_SUCCESS; } /* Skip ordinary zone processing. */ goto cleanup; } /* * "forward zones" aren't zones either. Translate this syntax into * the appropriate selective forwarding configuration and return. */ if (strcasecmp(ztypestr, "forward") == 0) { forwardtype = NULL; forwarders = NULL; (void)cfg_map_get(zoptions, "forward", &forwardtype); (void)cfg_map_get(zoptions, "forwarders", &forwarders); CHECK(configure_forward(config, view, origin, forwarders, forwardtype)); /* * Forward zones may also set delegation only. */ only = NULL; tresult = cfg_map_get(zoptions, "delegation-only", &only); if (tresult == ISC_R_SUCCESS && cfg_obj_asboolean(only)) CHECK(dns_view_adddelegationonly(view, origin)); goto cleanup; } /* * "delegation-only zones" aren't zones either. */ if (strcasecmp(ztypestr, "delegation-only") == 0) { result = dns_view_adddelegationonly(view, origin); goto cleanup; } /* * Redirect zones only require minimal configuration. */ if (strcasecmp(ztypestr, "redirect") == 0) { if (view->redirect != NULL) { cfg_obj_log(zconfig, ns_g_lctx, ISC_LOG_ERROR, "redirect zone already exists"); result = ISC_R_EXISTS; goto cleanup; } result = dns_viewlist_find(viewlist, view->name, view->rdclass, &pview); if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS) goto cleanup; if (pview != NULL && pview->redirect != NULL) { dns_zone_attach(pview->redirect, &zone); dns_zone_setview(zone, view); } else { CHECK(dns_zonemgr_createzone(ns_g_server->zonemgr, &zone)); CHECK(dns_zone_setorigin(zone, origin)); dns_zone_setview(zone, view); CHECK(dns_zonemgr_managezone(ns_g_server->zonemgr, zone)); dns_zone_setstats(zone, ns_g_server->zonestats); } CHECK(ns_zone_configure(config, vconfig, zconfig, aclconf, zone, NULL)); dns_zone_attach(zone, &view->redirect); goto cleanup; } if (!modify) { /* * Check for duplicates in the new zone table. */ result = dns_view_findzone(view, origin, &dupzone); if (result == ISC_R_SUCCESS) { /* * We already have this zone! */ cfg_obj_log(zconfig, ns_g_lctx, ISC_LOG_ERROR, "zone '%s' already exists", zname); dns_zone_detach(&dupzone); result = ISC_R_EXISTS; goto cleanup; } INSIST(dupzone == NULL); } /* * Note whether this is a response policy zone and which one if so. */ for (rpz_num = 0; ; ++rpz_num) { if (view->rpzs == NULL || rpz_num >= view->rpzs->p.num_zones) { rpz_num = DNS_RPZ_INVALID_NUM; break; } if (dns_name_equal(&view->rpzs->zones[rpz_num]->origin, origin)) break; } if (view->catzs != NULL && dns_catz_get_zone(view->catzs, origin) != NULL) zone_is_catz = ISC_TRUE; /* * See if we can reuse an existing zone. This is * only possible if all of these are true: * - The zone's view exists * - A zone with the right name exists in the view * - The zone is compatible with the config * options (e.g., an existing master zone cannot * be reused if the options specify a slave zone) * - The zone was not and is still not a response policy zone * or the zone is a policy zone with an unchanged number * and we are using the old policy zone summary data. */ result = dns_viewlist_find(&ns_g_server->viewlist, view->name, view->rdclass, &pview); if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS) goto cleanup; if (pview != NULL) result = dns_view_findzone(pview, origin, &zone); if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS) goto cleanup; if (zone != NULL && !ns_zone_reusable(zone, zconfig)) dns_zone_detach(&zone); if (zone != NULL && (rpz_num != dns_zone_get_rpz_num(zone) || (rpz_num != DNS_RPZ_INVALID_NUM && !old_rpz_ok))) dns_zone_detach(&zone); if (zone != NULL) { /* * We found a reusable zone. Make it use the * new view. */ dns_zone_setview(zone, view); if (view->acache != NULL) dns_zone_setacache(zone, view->acache); } else { /* * We cannot reuse an existing zone, we have * to create a new one. */ CHECK(dns_zonemgr_createzone(ns_g_server->zonemgr, &zone)); CHECK(dns_zone_setorigin(zone, origin)); dns_zone_setview(zone, view); if (view->acache != NULL) dns_zone_setacache(zone, view->acache); CHECK(dns_zonemgr_managezone(ns_g_server->zonemgr, zone)); dns_zone_setstats(zone, ns_g_server->zonestats); } if (rpz_num != DNS_RPZ_INVALID_NUM) { result = dns_zone_rpz_enable(zone, view->rpzs, rpz_num); if (result != ISC_R_SUCCESS) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, "zone '%s': incompatible" " masterfile-format or database" " for a response policy zone", zname); goto cleanup; } } if (zone_is_catz) dns_zone_catz_enable(zone, view->catzs); /* * If the zone contains a 'forwarders' statement, configure * selective forwarding. */ forwarders = NULL; if (cfg_map_get(zoptions, "forwarders", &forwarders) == ISC_R_SUCCESS) { forwardtype = NULL; (void)cfg_map_get(zoptions, "forward", &forwardtype); CHECK(configure_forward(config, view, origin, forwarders, forwardtype)); } /* * Stub and forward zones may also refer to delegation only points. */ only = NULL; if (cfg_map_get(zoptions, "delegation-only", &only) == ISC_R_SUCCESS) { if (cfg_obj_asboolean(only)) CHECK(dns_view_adddelegationonly(view, origin)); } /* * Mark whether the zone was originally added at runtime or not */ dns_zone_setadded(zone, added); signing = NULL; if ((strcasecmp(ztypestr, "master") == 0 || strcasecmp(ztypestr, "slave") == 0) && cfg_map_get(zoptions, "inline-signing", &signing) == ISC_R_SUCCESS && cfg_obj_asboolean(signing)) { dns_zone_getraw(zone, &raw); if (raw == NULL) { CHECK(dns_zone_create(&raw, mctx)); CHECK(dns_zone_setorigin(raw, origin)); dns_zone_setview(raw, view); if (view->acache != NULL) dns_zone_setacache(raw, view->acache); dns_zone_setstats(raw, ns_g_server->zonestats); CHECK(dns_zone_link(zone, raw)); } } /* * Configure the zone. */ CHECK(ns_zone_configure(config, vconfig, zconfig, aclconf, zone, raw)); /* * Add the zone to its view in the new view list. */ if (!modify) CHECK(dns_view_addzone(view, zone)); if (zone_is_catz) { /* * force catz reload if the zone is loaded; * if it's not it'll get reloaded on zone load */ dns_db_t *db = NULL; tresult = dns_zone_getdb(zone, &db); if (tresult == ISC_R_SUCCESS) { dns_catz_dbupdate_callback(db, view->catzs); dns_db_detach(&db); } } /* * Ensure that zone keys are reloaded on reconfig */ if ((dns_zone_getkeyopts(zone) & DNS_ZONEKEY_MAINTAIN) != 0) dns_zone_rekey(zone, ISC_FALSE); cleanup: if (zone != NULL) dns_zone_detach(&zone); if (raw != NULL) dns_zone_detach(&raw); if (pview != NULL) dns_view_detach(&pview); return (result); } /* * Configure built-in zone for storing managed-key data. */ static isc_result_t add_keydata_zone(dns_view_t *view, const char *directory, isc_mem_t *mctx) { isc_result_t result; dns_view_t *pview = NULL; dns_zone_t *zone = NULL; dns_acl_t *none = NULL; char filename[PATH_MAX]; isc_boolean_t defaultview; REQUIRE(view != NULL); /* See if we can re-use an existing keydata zone. */ result = dns_viewlist_find(&ns_g_server->viewlist, view->name, view->rdclass, &pview); if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS) return (result); if (pview != NULL && pview->managed_keys != NULL) { dns_zone_attach(pview->managed_keys, &view->managed_keys); dns_zone_setview(pview->managed_keys, view); dns_view_detach(&pview); dns_zone_synckeyzone(view->managed_keys); return (ISC_R_SUCCESS); } /* No existing keydata zone was found; create one */ CHECK(dns_zonemgr_createzone(ns_g_server->zonemgr, &zone)); CHECK(dns_zone_setorigin(zone, dns_rootname)); defaultview = ISC_TF(strcmp(view->name, "_default") == 0); CHECK(isc_file_sanitize(directory, defaultview ? "managed-keys" : view->name, defaultview ? "bind" : "mkeys", filename, sizeof(filename))); CHECK(dns_zone_setfile(zone, filename)); dns_zone_setview(zone, view); dns_zone_settype(zone, dns_zone_key); dns_zone_setclass(zone, view->rdclass); CHECK(dns_zonemgr_managezone(ns_g_server->zonemgr, zone)); if (view->acache != NULL) dns_zone_setacache(zone, view->acache); CHECK(dns_acl_none(mctx, &none)); dns_zone_setqueryacl(zone, none); dns_zone_setqueryonacl(zone, none); dns_acl_detach(&none); dns_zone_setdialup(zone, dns_dialuptype_no); dns_zone_setnotifytype(zone, dns_notifytype_no); dns_zone_setoption(zone, DNS_ZONEOPT_NOCHECKNS, ISC_TRUE); dns_zone_setjournalsize(zone, 0); dns_zone_setstats(zone, ns_g_server->zonestats); CHECK(setquerystats(zone, mctx, dns_zonestat_none)); if (view->managed_keys != NULL) dns_zone_detach(&view->managed_keys); dns_zone_attach(zone, &view->managed_keys); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_INFO, "set up managed keys zone for view %s, file '%s'", view->name, filename); cleanup: if (zone != NULL) dns_zone_detach(&zone); if (none != NULL) dns_acl_detach(&none); return (result); } /* * Configure a single server quota. */ static void configure_server_quota(const cfg_obj_t **maps, const char *name, isc_quota_t *quota) { const cfg_obj_t *obj = NULL; isc_result_t result; result = ns_config_get(maps, name, &obj); INSIST(result == ISC_R_SUCCESS); isc_quota_max(quota, cfg_obj_asuint32(obj)); } /* * This function is called as soon as the 'directory' statement has been * parsed. This can be extended to support other options if necessary. */ static isc_result_t directory_callback(const char *clausename, const cfg_obj_t *obj, void *arg) { isc_result_t result; const char *directory; REQUIRE(strcasecmp("directory", clausename) == 0); UNUSED(arg); UNUSED(clausename); /* * Change directory. */ directory = cfg_obj_asstring(obj); if (! isc_file_ischdiridempotent(directory)) cfg_obj_log(obj, ns_g_lctx, ISC_LOG_WARNING, "option 'directory' contains relative path '%s'", directory); result = isc_dir_chdir(directory); if (result != ISC_R_SUCCESS) { cfg_obj_log(obj, ns_g_lctx, ISC_LOG_ERROR, "change directory to '%s' failed: %s", directory, isc_result_totext(result)); return (result); } return (ISC_R_SUCCESS); } static isc_result_t scan_interfaces(ns_server_t *server, isc_boolean_t verbose) { isc_result_t result; isc_boolean_t match_mapped = server->aclenv.match_mapped; #ifdef HAVE_GEOIP isc_boolean_t use_ecs = server->aclenv.geoip_use_ecs; #endif result = ns_interfacemgr_scan(server->interfacemgr, verbose); /* * Update the "localhost" and "localnets" ACLs to match the * current set of network interfaces. */ dns_aclenv_copy(&server->aclenv, ns_interfacemgr_getaclenv(server->interfacemgr)); server->aclenv.match_mapped = match_mapped; #ifdef HAVE_GEOIP server->aclenv.geoip_use_ecs = use_ecs; #endif return (result); } static isc_result_t add_listenelt(isc_mem_t *mctx, ns_listenlist_t *list, isc_sockaddr_t *addr, isc_dscp_t dscp, isc_boolean_t wcardport_ok) { ns_listenelt_t *lelt = NULL; dns_acl_t *src_acl = NULL; isc_result_t result; isc_sockaddr_t any_sa6; isc_netaddr_t netaddr; REQUIRE(isc_sockaddr_pf(addr) == AF_INET6); isc_sockaddr_any6(&any_sa6); if (!isc_sockaddr_equal(&any_sa6, addr) && (wcardport_ok || isc_sockaddr_getport(addr) != 0)) { isc_netaddr_fromin6(&netaddr, &addr->type.sin6.sin6_addr); result = dns_acl_create(mctx, 0, &src_acl); if (result != ISC_R_SUCCESS) return (result); result = dns_iptable_addprefix(src_acl->iptable, &netaddr, 128, ISC_TRUE); if (result != ISC_R_SUCCESS) goto clean; result = ns_listenelt_create(mctx, isc_sockaddr_getport(addr), dscp, src_acl, &lelt); if (result != ISC_R_SUCCESS) goto clean; ISC_LIST_APPEND(list->elts, lelt, link); } return (ISC_R_SUCCESS); clean: INSIST(lelt == NULL); dns_acl_detach(&src_acl); return (result); } /* * Make a list of xxx-source addresses and call ns_interfacemgr_adjust() * to update the listening interfaces accordingly. * We currently only consider IPv6, because this only affects IPv6 wildcard * sockets. */ static void adjust_interfaces(ns_server_t *server, isc_mem_t *mctx) { isc_result_t result; ns_listenlist_t *list = NULL; dns_view_t *view; dns_zone_t *zone, *next; isc_sockaddr_t addr, *addrp; isc_dscp_t dscp = -1; result = ns_listenlist_create(mctx, &list); if (result != ISC_R_SUCCESS) return; for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; view = ISC_LIST_NEXT(view, link)) { dns_dispatch_t *dispatch6; dispatch6 = dns_resolver_dispatchv6(view->resolver); if (dispatch6 == NULL) continue; result = dns_dispatch_getlocaladdress(dispatch6, &addr); if (result != ISC_R_SUCCESS) goto fail; /* * We always add non-wildcard address regardless of whether * the port is 'any' (the fourth arg is TRUE): if the port is * specific, we need to add it since it may conflict with a * listening interface; if it's zero, we'll dynamically open * query ports, and some of them may override an existing * wildcard IPv6 port. */ /* XXXMPA fix dscp */ result = add_listenelt(mctx, list, &addr, dscp, ISC_TRUE); if (result != ISC_R_SUCCESS) goto fail; } zone = NULL; for (result = dns_zone_first(server->zonemgr, &zone); result == ISC_R_SUCCESS; next = NULL, result = dns_zone_next(zone, &next), zone = next) { dns_view_t *zoneview; /* * At this point the zone list may contain a stale zone * just removed from the configuration. To see the validity, * check if the corresponding view is in our current view list. * There may also be old zones that are still in the process * of shutting down and have detached from their old view * (zoneview == NULL). */ zoneview = dns_zone_getview(zone); if (zoneview == NULL) continue; for (view = ISC_LIST_HEAD(server->viewlist); view != NULL && view != zoneview; view = ISC_LIST_NEXT(view, link)) ; if (view == NULL) continue; addrp = dns_zone_getnotifysrc6(zone); dscp = dns_zone_getnotifysrc6dscp(zone); result = add_listenelt(mctx, list, addrp, dscp, ISC_FALSE); if (result != ISC_R_SUCCESS) goto fail; addrp = dns_zone_getxfrsource6(zone); dscp = dns_zone_getxfrsource6dscp(zone); result = add_listenelt(mctx, list, addrp, dscp, ISC_FALSE); if (result != ISC_R_SUCCESS) goto fail; } ns_interfacemgr_adjust(server->interfacemgr, list, ISC_TRUE); clean: ns_listenlist_detach(&list); return; fail: /* * Even when we failed the procedure, most of other interfaces * should work correctly. We therefore just warn it. */ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_WARNING, "could not adjust the listen-on list; " "some interfaces may not work"); goto clean; } /* * This event callback is invoked to do periodic network interface * scanning. It is also called by ns_server_scan_interfaces(), * invoked by "rndc scan" */ static void interface_timer_tick(isc_task_t *task, isc_event_t *event) { isc_result_t result; ns_server_t *server = (ns_server_t *) event->ev_arg; INSIST(task == server->task); UNUSED(task); isc_event_free(&event); /* * XXX should scan interfaces unlocked and get exclusive access * only to replace ACLs. */ result = isc_task_beginexclusive(server->task); RUNTIME_CHECK(result == ISC_R_SUCCESS); scan_interfaces(server, ISC_FALSE); isc_task_endexclusive(server->task); } static void heartbeat_timer_tick(isc_task_t *task, isc_event_t *event) { ns_server_t *server = (ns_server_t *) event->ev_arg; dns_view_t *view; UNUSED(task); isc_event_free(&event); view = ISC_LIST_HEAD(server->viewlist); while (view != NULL) { dns_view_dialup(view); view = ISC_LIST_NEXT(view, link); } } typedef struct { isc_mem_t *mctx; isc_task_t *task; dns_rdataset_t rdataset; dns_rdataset_t sigrdataset; dns_fetch_t *fetch; } ns_tat_t; static int cid(const void *a, const void *b) { const isc_uint16_t ida = *(const isc_uint16_t *)a; const isc_uint16_t idb = *(const isc_uint16_t *)b; if (ida < idb) return (-1); else if (ida > idb) return (1); else return (0); } static void tat_done(isc_task_t *task, isc_event_t *event) { dns_fetchevent_t *devent; ns_tat_t *tat; UNUSED(task); INSIST(event != NULL && event->ev_type == DNS_EVENT_FETCHDONE); INSIST(event->ev_arg != NULL); tat = event->ev_arg; devent = (dns_fetchevent_t *) event; /* Free resources which are not of interest */ if (devent->node != NULL) dns_db_detachnode(devent->db, &devent->node); if (devent->db != NULL) dns_db_detach(&devent->db); isc_event_free(&event); dns_resolver_destroyfetch(&tat->fetch); if (dns_rdataset_isassociated(&tat->rdataset)) dns_rdataset_disassociate(&tat->rdataset); if (dns_rdataset_isassociated(&tat->sigrdataset)) dns_rdataset_disassociate(&tat->sigrdataset); isc_task_detach(&tat->task); isc_mem_putanddetach(&tat->mctx, tat, sizeof(*tat)); } struct dotat_arg { dns_view_t *view; isc_task_t *task; }; static void dotat(dns_keytable_t *keytable, dns_keynode_t *keynode, void *arg) { isc_result_t result; dns_keynode_t *firstnode = keynode; dns_keynode_t *nextnode; unsigned int i, n = 0; char label[64], namebuf[DNS_NAME_FORMATSIZE]; dns_fixedname_t fixed; dns_name_t *tatname; isc_uint16_t ids[12]; /* Only 12 id's will fit in a label. */ int m; ns_tat_t *tat; dns_name_t *name = NULL; struct dotat_arg *dotat_arg = arg; dns_view_t *view; isc_task_t *task; isc_textregion_t r; REQUIRE(keytable != NULL); REQUIRE(keynode != NULL); REQUIRE(arg != NULL); view = dotat_arg->view; task = dotat_arg->task; do { dst_key_t *key = dns_keynode_key(keynode); if (key != NULL) { name = dst_key_name(key); if (n < (sizeof(ids)/sizeof(ids[0]))) { ids[n] = dst_key_id(key); n++; } } nextnode = NULL; (void)dns_keytable_nextkeynode(keytable, keynode, &nextnode); if (keynode != firstnode) dns_keytable_detachkeynode(keytable, &keynode); keynode = nextnode; } while (keynode != NULL); if (n == 0) return; if (n > 1) qsort(ids, n, sizeof(ids[0]), cid); /* * Encoded as "_ta-xxxx\(-xxxx\)*" where xxxx is the hex version of * of the keyid. */ label[0] = 0; r.base = label; r.length = sizeof(label);; m = snprintf(r.base, r.length, "_ta"); if (m < 0 || (unsigned)m > r.length) return; isc_textregion_consume(&r, m); for (i = 0; i < n; i++) { m = snprintf(r.base, r.length, "-%04x", ids[i]); if (m < 0 || (unsigned)m > r.length) return; isc_textregion_consume(&r, m); } dns_fixedname_init(&fixed); tatname = dns_fixedname_name(&fixed); result = dns_name_fromstring2(tatname, label, name, 0, NULL); if (result != ISC_R_SUCCESS) return; dns_name_format(tatname, namebuf, sizeof(namebuf)); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_INFO, "%s: sending trust-anchor-telemetry query '%s/NULL'", view->name, namebuf); tat = isc_mem_get(dotat_arg->view->mctx, sizeof(*tat)); if (tat == NULL) return; tat->mctx = NULL; tat->task = NULL; tat->fetch = NULL; dns_rdataset_init(&tat->rdataset); dns_rdataset_init(&tat->sigrdataset); isc_mem_attach(dotat_arg->view->mctx, &tat->mctx); isc_task_attach(task, &tat->task); result = dns_resolver_createfetch(view->resolver, tatname, dns_rdatatype_null, NULL, NULL, NULL, 0, tat->task, tat_done, tat, &tat->rdataset, &tat->sigrdataset, &tat->fetch); if (result != ISC_R_SUCCESS) { isc_task_detach(&tat->task); isc_mem_putanddetach(&tat->mctx, tat, sizeof(*tat)); } } static void tat_timer_tick(isc_task_t *task, isc_event_t *event) { isc_result_t result; ns_server_t *server = (ns_server_t *) event->ev_arg; struct dotat_arg arg; dns_view_t *view; dns_keytable_t *secroots = NULL; isc_event_free(&event); for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; view = ISC_LIST_NEXT(view, link)) { if (!view->trust_anchor_telemetry || !view->enablevalidation) { continue; } result = dns_view_getsecroots(view, &secroots); if (result != ISC_R_SUCCESS) { continue; } arg.view = view; arg.task = task; (void)dns_keytable_forall(secroots, dotat, &arg); dns_keytable_detach(&secroots); } } static void pps_timer_tick(isc_task_t *task, isc_event_t *event) { static unsigned int oldrequests = 0; unsigned int requests = ns_client_requests; UNUSED(task); isc_event_free(&event); /* * Don't worry about wrapping as the overflow result will be right. */ dns_pps = (requests - oldrequests) / 1200; oldrequests = requests; } /* * Replace the current value of '*field', a dynamically allocated * string or NULL, with a dynamically allocated copy of the * null-terminated string pointed to by 'value', or NULL. */ static isc_result_t setstring(ns_server_t *server, char **field, const char *value) { char *copy; if (value != NULL) { copy = isc_mem_strdup(server->mctx, value); if (copy == NULL) return (ISC_R_NOMEMORY); } else { copy = NULL; } if (*field != NULL) isc_mem_free(server->mctx, *field); *field = copy; return (ISC_R_SUCCESS); } /* * Replace the current value of '*field', a dynamically allocated * string or NULL, with another dynamically allocated string * or NULL if whether 'obj' is a string or void value, respectively. */ static isc_result_t setoptstring(ns_server_t *server, char **field, const cfg_obj_t *obj) { if (cfg_obj_isvoid(obj)) return (setstring(server, field, NULL)); else return (setstring(server, field, cfg_obj_asstring(obj))); } static void set_limit(const cfg_obj_t **maps, const char *configname, const char *description, isc_resource_t resourceid, isc_resourcevalue_t defaultvalue) { const cfg_obj_t *obj = NULL; const char *resource; isc_resourcevalue_t value; isc_result_t result; if (ns_config_get(maps, configname, &obj) != ISC_R_SUCCESS) return; if (cfg_obj_isstring(obj)) { resource = cfg_obj_asstring(obj); if (strcasecmp(resource, "unlimited") == 0) value = ISC_RESOURCE_UNLIMITED; else { INSIST(strcasecmp(resource, "default") == 0); value = defaultvalue; } } else value = cfg_obj_asuint64(obj); result = isc_resource_setlimit(resourceid, value); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, result == ISC_R_SUCCESS ? ISC_LOG_DEBUG(3) : ISC_LOG_WARNING, "set maximum %s to %" ISC_PRINT_QUADFORMAT "u: %s", description, value, isc_result_totext(result)); } #define SETLIMIT(cfgvar, resource, description) \ set_limit(maps, cfgvar, description, isc_resource_ ## resource, \ ns_g_init ## resource) static void set_limits(const cfg_obj_t **maps) { SETLIMIT("stacksize", stacksize, "stack size"); SETLIMIT("datasize", datasize, "data size"); SETLIMIT("coresize", coresize, "core size"); SETLIMIT("files", openfiles, "open files"); } static void portset_fromconf(isc_portset_t *portset, const cfg_obj_t *ports, isc_boolean_t positive) { const cfg_listelt_t *element; for (element = cfg_list_first(ports); element != NULL; element = cfg_list_next(element)) { const cfg_obj_t *obj = cfg_listelt_value(element); if (cfg_obj_isuint32(obj)) { in_port_t port = (in_port_t)cfg_obj_asuint32(obj); if (positive) isc_portset_add(portset, port); else isc_portset_remove(portset, port); } else { const cfg_obj_t *obj_loport, *obj_hiport; in_port_t loport, hiport; obj_loport = cfg_tuple_get(obj, "loport"); loport = (in_port_t)cfg_obj_asuint32(obj_loport); obj_hiport = cfg_tuple_get(obj, "hiport"); hiport = (in_port_t)cfg_obj_asuint32(obj_hiport); if (positive) isc_portset_addrange(portset, loport, hiport); else { isc_portset_removerange(portset, loport, hiport); } } } } static isc_result_t removed(dns_zone_t *zone, void *uap) { const char *type; if (dns_zone_getview(zone) != uap) return (ISC_R_SUCCESS); switch (dns_zone_gettype(zone)) { case dns_zone_master: type = "master"; break; case dns_zone_slave: type = "slave"; break; case dns_zone_stub: type = "stub"; break; case dns_zone_staticstub: type = "static-stub"; break; case dns_zone_redirect: type = "redirect"; break; default: type = "other"; break; } dns_zone_log(zone, ISC_LOG_INFO, "(%s) removed", type); return (ISC_R_SUCCESS); } static void cleanup_session_key(ns_server_t *server, isc_mem_t *mctx) { if (server->session_keyfile != NULL) { isc_file_remove(server->session_keyfile); isc_mem_free(mctx, server->session_keyfile); server->session_keyfile = NULL; } if (server->session_keyname != NULL) { if (dns_name_dynamic(server->session_keyname)) dns_name_free(server->session_keyname, mctx); isc_mem_put(mctx, server->session_keyname, sizeof(dns_name_t)); server->session_keyname = NULL; } if (server->sessionkey != NULL) dns_tsigkey_detach(&server->sessionkey); server->session_keyalg = DST_ALG_UNKNOWN; server->session_keybits = 0; } static isc_result_t generate_session_key(const char *filename, const char *keynamestr, dns_name_t *keyname, const char *algstr, dns_name_t *algname, unsigned int algtype, isc_uint16_t bits, isc_mem_t *mctx, dns_tsigkey_t **tsigkeyp) { isc_result_t result = ISC_R_SUCCESS; dst_key_t *key = NULL; isc_buffer_t key_txtbuffer; isc_buffer_t key_rawbuffer; char key_txtsecret[256]; char key_rawsecret[64]; isc_region_t key_rawregion; isc_stdtime_t now; dns_tsigkey_t *tsigkey = NULL; FILE *fp = NULL; isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_INFO, "generating session key for dynamic DNS"); /* generate key */ result = dst_key_generate(keyname, algtype, bits, 1, 0, DNS_KEYPROTO_ANY, dns_rdataclass_in, mctx, &key); if (result != ISC_R_SUCCESS) return (result); /* * Dump the key to the buffer for later use. Should be done before * we transfer the ownership of key to tsigkey. */ isc_buffer_init(&key_rawbuffer, &key_rawsecret, sizeof(key_rawsecret)); CHECK(dst_key_tobuffer(key, &key_rawbuffer)); isc_buffer_usedregion(&key_rawbuffer, &key_rawregion); isc_buffer_init(&key_txtbuffer, &key_txtsecret, sizeof(key_txtsecret)); CHECK(isc_base64_totext(&key_rawregion, -1, "", &key_txtbuffer)); /* Store the key in tsigkey. */ isc_stdtime_get(&now); CHECK(dns_tsigkey_createfromkey(dst_key_name(key), algname, key, ISC_FALSE, NULL, now, now, mctx, NULL, &tsigkey)); /* Dump the key to the key file. */ fp = ns_os_openfile(filename, S_IRUSR|S_IWUSR, ISC_TRUE); if (fp == NULL) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, "could not create %s", filename); result = ISC_R_NOPERM; goto cleanup; } fprintf(fp, "key \"%s\" {\n" "\talgorithm %s;\n" "\tsecret \"%.*s\";\n};\n", keynamestr, algstr, (int) isc_buffer_usedlength(&key_txtbuffer), (char*) isc_buffer_base(&key_txtbuffer)); CHECK(isc_stdio_flush(fp)); result = isc_stdio_close(fp); fp = NULL; if (result != ISC_R_SUCCESS) goto cleanup; dst_key_free(&key); *tsigkeyp = tsigkey; return (ISC_R_SUCCESS); cleanup: isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, "failed to generate session key " "for dynamic DNS: %s", isc_result_totext(result)); if (fp != NULL) { (void)isc_stdio_close(fp); (void)isc_file_remove(filename); } if (tsigkey != NULL) dns_tsigkey_detach(&tsigkey); if (key != NULL) dst_key_free(&key); return (result); } static isc_result_t configure_session_key(const cfg_obj_t **maps, ns_server_t *server, isc_mem_t *mctx) { const char *keyfile, *keynamestr, *algstr; unsigned int algtype; dns_fixedname_t fname; dns_name_t *keyname, *algname; isc_buffer_t buffer; isc_uint16_t bits; const cfg_obj_t *obj; isc_boolean_t need_deleteold = ISC_FALSE; isc_boolean_t need_createnew = ISC_FALSE; isc_result_t result; obj = NULL; result = ns_config_get(maps, "session-keyfile", &obj); if (result == ISC_R_SUCCESS) { if (cfg_obj_isvoid(obj)) keyfile = NULL; /* disable it */ else keyfile = cfg_obj_asstring(obj); } else keyfile = ns_g_defaultsessionkeyfile; obj = NULL; result = ns_config_get(maps, "session-keyname", &obj); INSIST(result == ISC_R_SUCCESS); keynamestr = cfg_obj_asstring(obj); dns_fixedname_init(&fname); isc_buffer_constinit(&buffer, keynamestr, strlen(keynamestr)); isc_buffer_add(&buffer, strlen(keynamestr)); keyname = dns_fixedname_name(&fname); result = dns_name_fromtext(keyname, &buffer, dns_rootname, 0, NULL); if (result != ISC_R_SUCCESS) return (result); obj = NULL; result = ns_config_get(maps, "session-keyalg", &obj); INSIST(result == ISC_R_SUCCESS); algstr = cfg_obj_asstring(obj); algname = NULL; result = ns_config_getkeyalgorithm2(algstr, &algname, &algtype, &bits); if (result != ISC_R_SUCCESS) { const char *s = " (keeping current key)"; cfg_obj_log(obj, ns_g_lctx, ISC_LOG_ERROR, "session-keyalg: " "unsupported or unknown algorithm '%s'%s", algstr, server->session_keyfile != NULL ? s : ""); return (result); } /* See if we need to (re)generate a new key. */ if (keyfile == NULL) { if (server->session_keyfile != NULL) need_deleteold = ISC_TRUE; } else if (server->session_keyfile == NULL) need_createnew = ISC_TRUE; else if (strcmp(keyfile, server->session_keyfile) != 0 || !dns_name_equal(server->session_keyname, keyname) || server->session_keyalg != algtype || server->session_keybits != bits) { need_deleteold = ISC_TRUE; need_createnew = ISC_TRUE; } if (need_deleteold) { INSIST(server->session_keyfile != NULL); INSIST(server->session_keyname != NULL); INSIST(server->sessionkey != NULL); cleanup_session_key(server, mctx); } if (need_createnew) { INSIST(server->sessionkey == NULL); INSIST(server->session_keyfile == NULL); INSIST(server->session_keyname == NULL); INSIST(server->session_keyalg == DST_ALG_UNKNOWN); INSIST(server->session_keybits == 0); server->session_keyname = isc_mem_get(mctx, sizeof(dns_name_t)); if (server->session_keyname == NULL) goto cleanup; dns_name_init(server->session_keyname, NULL); CHECK(dns_name_dup(keyname, mctx, server->session_keyname)); server->session_keyfile = isc_mem_strdup(mctx, keyfile); if (server->session_keyfile == NULL) goto cleanup; server->session_keyalg = algtype; server->session_keybits = bits; CHECK(generate_session_key(keyfile, keynamestr, keyname, algstr, algname, algtype, bits, mctx, &server->sessionkey)); } return (result); cleanup: cleanup_session_key(server, mctx); return (result); } #ifndef HAVE_LMDB static isc_result_t count_newzones(dns_view_t *view, ns_cfgctx_t *nzcfg, int *num_zonesp) { isc_result_t result; /* The new zone file may not exist. That is OK. */ if (!isc_file_exists(view->new_zone_file)) { *num_zonesp = 0; return (ISC_R_SUCCESS); } /* * In the case of NZF files, we also parse the configuration in * the file at this stage. * * This may be called in multiple views, so we reset * the parser each time. */ cfg_parser_reset(ns_g_addparser); result = cfg_parse_file(ns_g_addparser, view->new_zone_file, &cfg_type_addzoneconf, &nzcfg->nzf_config); if (result == ISC_R_SUCCESS) { int num_zones; num_zones = count_zones(nzcfg->nzf_config); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_INFO, "NZF file '%s' contains %d zones", view->new_zone_file, num_zones); if (num_zonesp != NULL) *num_zonesp = num_zones; } else { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, "Error parsing NZF file '%s': %s", view->new_zone_file, isc_result_totext(result)); } return (result); } #else /* HAVE_LMDB */ static isc_result_t count_newzones(dns_view_t *view, ns_cfgctx_t *nzcfg, int *num_zonesp) { isc_result_t result; int n; UNUSED(nzcfg); REQUIRE(num_zonesp != NULL); CHECK(migrate_nzf(view)); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_INFO, "loading NZD zone count from '%s' " "for view '%s'", view->new_zone_db, view->name); CHECK(nzd_count(view, &n)); *num_zonesp = n; isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_INFO, "NZD database '%s' contains %d zones", view->new_zone_db, n); cleanup: if (result != ISC_R_SUCCESS) *num_zonesp = 0; return (ISC_R_SUCCESS); } #endif /* HAVE_LMDB */ static isc_result_t setup_newzones(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig, cfg_parser_t *conf_parser, cfg_aclconfctx_t *actx, int *num_zones) { isc_result_t result = ISC_R_SUCCESS; isc_boolean_t allow = ISC_FALSE; ns_cfgctx_t *nzcfg = NULL; const cfg_obj_t *maps[4]; const cfg_obj_t *options = NULL, *voptions = NULL; const cfg_obj_t *nz = NULL; const cfg_obj_t *obj = NULL; int i = 0; isc_uint64_t mapsize = 0ULL; REQUIRE(config != NULL); if (vconfig != NULL) voptions = cfg_tuple_get(vconfig, "options"); if (voptions != NULL) maps[i++] = voptions; result = cfg_map_get(config, "options", &options); if (result == ISC_R_SUCCESS) maps[i++] = options; maps[i++] = ns_g_defaults; maps[i] = NULL; result = ns_config_get(maps, "allow-new-zones", &nz); if (result == ISC_R_SUCCESS) allow = cfg_obj_asboolean(nz); #ifdef HAVE_LMDB result = ns_config_get(maps, "lmdb-mapsize", &obj); if (result == ISC_R_SUCCESS && obj != NULL) { mapsize = cfg_obj_asuint64(obj); if (mapsize < (1ULL << 20)) { /* 1 megabyte */ cfg_obj_log(obj, ns_g_lctx, ISC_LOG_ERROR, "'lmdb-mapsize " "%" ISC_PRINT_QUADFORMAT "d' " "is too small", mapsize); return (ISC_R_FAILURE); } else if (mapsize > (1ULL << 40)) { /* 1 terabyte */ cfg_obj_log(obj, ns_g_lctx, ISC_LOG_ERROR, "'lmdb-mapsize " "%" ISC_PRINT_QUADFORMAT "d' " "is too large", mapsize); return (ISC_R_FAILURE); } } #else UNUSED(obj); #endif /* HAVE_LMDB */ /* * A non-empty catalog-zones statement implies allow-new-zones */ if (!allow) { const cfg_obj_t *cz = NULL; result = ns_config_get(maps, "catalog-zones", &cz); if (result == ISC_R_SUCCESS) { const cfg_listelt_t *e = cfg_list_first(cfg_tuple_get(cz, "zone list")); if (e != NULL) allow = ISC_TRUE; } } if (!allow) { dns_view_setnewzones(view, ISC_FALSE, NULL, NULL, 0ULL); if (num_zones != NULL) *num_zones = 0; return (ISC_R_SUCCESS); } nzcfg = isc_mem_get(view->mctx, sizeof(*nzcfg)); if (nzcfg == NULL) { dns_view_setnewzones(view, ISC_FALSE, NULL, NULL, 0ULL); return (ISC_R_NOMEMORY); } /* * We attach the parser that was used for config as well * as the one that will be used for added zones, to avoid * a shutdown race later. */ memset(nzcfg, 0, sizeof(*nzcfg)); cfg_parser_attach(conf_parser, &nzcfg->conf_parser); cfg_parser_attach(ns_g_addparser, &nzcfg->add_parser); isc_mem_attach(view->mctx, &nzcfg->mctx); cfg_aclconfctx_attach(actx, &nzcfg->actx); result = dns_view_setnewzones(view, allow, nzcfg, newzone_cfgctx_destroy, mapsize); if (result != ISC_R_SUCCESS) { dns_view_setnewzones(view, ISC_FALSE, NULL, NULL, 0ULL); return (result); } cfg_obj_attach(config, &nzcfg->config); if (vconfig != NULL) cfg_obj_attach(vconfig, &nzcfg->vconfig); result = count_newzones(view, nzcfg, num_zones); return (result); } static void configure_zone_setviewcommit(isc_result_t result, const cfg_obj_t *zconfig, dns_view_t *view) { const char *zname; dns_fixedname_t fixorigin; dns_name_t *origin; isc_result_t result2; dns_view_t *pview = NULL; dns_zone_t *zone = NULL; dns_zone_t *raw = NULL; zname = cfg_obj_asstring(cfg_tuple_get(zconfig, "name")); dns_fixedname_init(&fixorigin); origin = dns_fixedname_name(&fixorigin); result2 = dns_name_fromstring(origin, zname, 0, NULL); if (result2 != ISC_R_SUCCESS) { return; } result2 = dns_viewlist_find(&ns_g_server->viewlist, view->name, view->rdclass, &pview); if (result2 != ISC_R_SUCCESS) { return; } result2 = dns_view_findzone(pview, origin, &zone); if (result2 != ISC_R_SUCCESS) { dns_view_detach(&pview); return; } dns_zone_getraw(zone, &raw); if (result == ISC_R_SUCCESS) { dns_zone_setviewcommit(zone); if (raw != NULL) dns_zone_setviewcommit(raw); } else { dns_zone_setviewrevert(zone); if (raw != NULL) dns_zone_setviewrevert(raw); } if (raw != NULL) { dns_zone_detach(&raw); } dns_zone_detach(&zone); dns_view_detach(&pview); } #ifndef HAVE_LMDB static isc_result_t configure_newzones(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig, isc_mem_t *mctx, cfg_aclconfctx_t *actx) { isc_result_t result; ns_cfgctx_t *nzctx; const cfg_obj_t *zonelist; const cfg_listelt_t *element; nzctx = view->new_zone_config; if (nzctx == NULL || nzctx->nzf_config == NULL) { return (ISC_R_SUCCESS); } isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_INFO, "loading additional zones for view '%s'", view->name); zonelist = NULL; cfg_map_get(nzctx->nzf_config, "zone", &zonelist); for (element = cfg_list_first(zonelist); element != NULL; element = cfg_list_next(element)) { const cfg_obj_t *zconfig = cfg_listelt_value(element); CHECK(configure_zone(config, zconfig, vconfig, mctx, view, &ns_g_server->viewlist, actx, ISC_TRUE, ISC_FALSE, ISC_FALSE)); } result = ISC_R_SUCCESS; cleanup: for (element = cfg_list_first(zonelist); element != NULL; element = cfg_list_next(element)) { const cfg_obj_t *zconfig = cfg_listelt_value(element); configure_zone_setviewcommit(result, zconfig, view); } return (result); } #else /* HAVE_LMDB */ static isc_result_t data_to_cfg(dns_view_t *view, MDB_val *key, MDB_val *data, isc_buffer_t **text, cfg_obj_t **zoneconfig) { isc_result_t result; const char *zone_name; size_t zone_name_len; const char *zone_config; size_t zone_config_len; cfg_obj_t *zoneconf = NULL; REQUIRE(view != NULL); REQUIRE(key != NULL); REQUIRE(data != NULL); REQUIRE(text != NULL); REQUIRE(zoneconfig != NULL && *zoneconfig == NULL); if (*text == NULL) { result = isc_buffer_allocate(view->mctx, text, 256); if (result != ISC_R_SUCCESS) goto cleanup; } else { isc_buffer_clear(*text); } zone_name = (const char *) key->mv_data; zone_name_len = key->mv_size; INSIST(zone_name != NULL && zone_name_len > 0); zone_config = (const char *) data->mv_data; zone_config_len = data->mv_size; INSIST(zone_config != NULL && zone_config_len > 0); /* zone zonename { config; }; */ result = isc_buffer_reserve(text, 5 + zone_name_len + 1 + zone_config_len + 2); if (result != ISC_R_SUCCESS) { goto cleanup; } putstr(text, "zone "); putmem(text, (const void *) zone_name, zone_name_len); putstr(text, " "); putmem(text, (const void *) zone_config, zone_config_len); putstr(text, ";\n"); cfg_parser_reset(ns_g_addparser); result = cfg_parse_buffer3(ns_g_addparser, *text, zone_name, 0, &cfg_type_addzoneconf, &zoneconf); if (result != ISC_R_SUCCESS) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, "parsing config for zone '%.*s' in " "NZD database '%s' failed", (int) zone_name_len, zone_name, view->new_zone_db); goto cleanup; } *zoneconfig = zoneconf; zoneconf = NULL; result = ISC_R_SUCCESS; cleanup: if (zoneconf != NULL) { cfg_obj_destroy(ns_g_addparser, &zoneconf); } return (result); } /*% * Prototype for a callback which can be used with for_all_newzone_cfgs(). */ typedef isc_result_t (*newzone_cfg_cb_t)(const cfg_obj_t *zconfig, cfg_obj_t *config, cfg_obj_t *vconfig, isc_mem_t *mctx, dns_view_t *view, cfg_aclconfctx_t *actx); /*% * For each zone found in a NZD opened by the caller, create an object * representing its configuration and invoke "callback" with the created * object, "config", "vconfig", "mctx", "view" and "actx" as arguments (all * these are non-global variables required to invoke configure_zone()). * Immediately interrupt processing if an error is encountered while * transforming NZD data into a zone configuration object or if "callback" * returns an error. */ static isc_result_t for_all_newzone_cfgs(newzone_cfg_cb_t callback, cfg_obj_t *config, cfg_obj_t *vconfig, isc_mem_t *mctx, dns_view_t *view, cfg_aclconfctx_t *actx, MDB_txn *txn, MDB_dbi dbi) { const cfg_obj_t *zconfig, *zlist; isc_result_t result = ISC_R_SUCCESS; cfg_obj_t *zconfigobj = NULL; isc_buffer_t *text = NULL; MDB_cursor *cursor = NULL; MDB_val data, key; int status; status = mdb_cursor_open(txn, dbi, &cursor); if (status != MDB_SUCCESS) { return (ISC_R_FAILURE); } for (status = mdb_cursor_get(cursor, &key, &data, MDB_FIRST); status == MDB_SUCCESS; status = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) { /* * Create a configuration object from data fetched from NZD. */ result = data_to_cfg(view, &key, &data, &text, &zconfigobj); if (result != ISC_R_SUCCESS) { break; } /* * Extract zone configuration from configuration object. */ zlist = NULL; result = cfg_map_get(zconfigobj, "zone", &zlist); if (result != ISC_R_SUCCESS) { break; } else if (!cfg_obj_islist(zlist)) { result = ISC_R_FAILURE; break; } zconfig = cfg_listelt_value(cfg_list_first(zlist)); /* * Invoke callback. */ result = callback(zconfig, config, vconfig, mctx, view, actx); if (result != ISC_R_SUCCESS) { break; } /* * Destroy the configuration object created in this iteration. */ cfg_obj_destroy(ns_g_addparser, &zconfigobj); } if (text != NULL) { isc_buffer_free(&text); } if (zconfigobj != NULL) { cfg_obj_destroy(ns_g_addparser, &zconfigobj); } mdb_cursor_close(cursor); return (result); } /*% * Attempt to configure a zone found in NZD and return the result. */ static isc_result_t configure_newzone(const cfg_obj_t *zconfig, cfg_obj_t *config, cfg_obj_t *vconfig, isc_mem_t *mctx, dns_view_t *view, cfg_aclconfctx_t *actx) { return (configure_zone(config, zconfig, vconfig, mctx, view, &ns_g_server->viewlist, actx, ISC_TRUE, ISC_FALSE, ISC_FALSE)); } /*% * Revert new view assignment for a zone found in NZD. */ static isc_result_t configure_newzone_revert(const cfg_obj_t *zconfig, cfg_obj_t *config, cfg_obj_t *vconfig, isc_mem_t *mctx, dns_view_t *view, cfg_aclconfctx_t *actx) { UNUSED(config); UNUSED(vconfig); UNUSED(mctx); UNUSED(actx); configure_zone_setviewcommit(ISC_R_FAILURE, zconfig, view); return (ISC_R_SUCCESS); } static isc_result_t configure_newzones(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig, isc_mem_t *mctx, cfg_aclconfctx_t *actx) { isc_result_t result; MDB_txn *txn = NULL; MDB_dbi dbi; if (view->new_zone_config == NULL) { return (ISC_R_SUCCESS); } result = nzd_open(view, MDB_RDONLY, &txn, &dbi); if (result != ISC_R_SUCCESS) { return (ISC_R_SUCCESS); } isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_INFO, "loading NZD configs from '%s' " "for view '%s'", view->new_zone_db, view->name); result = for_all_newzone_cfgs(configure_newzone, config, vconfig, mctx, view, actx, txn, dbi); if (result != ISC_R_SUCCESS) { /* * An error was encountered while attempting to configure zones * found in NZD. As this error may have been caused by a * configure_zone() failure, try restoring a sane configuration * by reattaching all zones found in NZD to the old view. If * this also fails, too bad, there is nothing more we can do in * terms of trying to make things right. */ (void) for_all_newzone_cfgs(configure_newzone_revert, config, vconfig, mctx, view, actx, txn, dbi); } (void) nzd_close(&txn, ISC_FALSE); return (result); } static isc_result_t get_newzone_config(dns_view_t *view, const char *zonename, cfg_obj_t **zoneconfig) { isc_result_t result; int status; cfg_obj_t *zoneconf = NULL; isc_buffer_t *text = NULL; MDB_txn *txn = NULL; MDB_dbi dbi; MDB_val key, data; char zname[DNS_NAME_FORMATSIZE]; dns_fixedname_t fname; dns_name_t *name; isc_buffer_t b; INSIST(zoneconfig != NULL && *zoneconfig == NULL); CHECK(nzd_open(view, MDB_RDONLY, &txn, &dbi)); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_INFO, "loading NZD config from '%s' " "for zone '%s'", view->new_zone_db, zonename); /* Normalize zone name */ isc_buffer_constinit(&b, zonename, strlen(zonename)); isc_buffer_add(&b, strlen(zonename)); dns_fixedname_init(&fname); name = dns_fixedname_name(&fname); CHECK(dns_name_fromtext(name, &b, dns_rootname, DNS_NAME_DOWNCASE, NULL)); dns_name_format(name, zname, sizeof(zname)); key.mv_data = zname; key.mv_size = strlen(zname); status = mdb_get(txn, dbi, &key, &data); if (status != MDB_SUCCESS) { CHECK(ISC_R_FAILURE); } CHECK(data_to_cfg(view, &key, &data, &text, &zoneconf)); *zoneconfig = zoneconf; zoneconf = NULL; result = ISC_R_SUCCESS; cleanup: (void) nzd_close(&txn, ISC_FALSE); if (zoneconf != NULL) { cfg_obj_destroy(ns_g_addparser, &zoneconf); } if (text != NULL) { isc_buffer_free(&text); } return (result); } #endif /* HAVE_LMDB */ static int count_zones(const cfg_obj_t *conf) { const cfg_obj_t *zonelist = NULL; const cfg_listelt_t *element; int n = 0; REQUIRE(conf != NULL); cfg_map_get(conf, "zone", &zonelist); for (element = cfg_list_first(zonelist); element != NULL; element = cfg_list_next(element)) n++; return (n); } static isc_result_t check_lockfile(ns_server_t *server, const cfg_obj_t *config, isc_boolean_t first_time) { isc_result_t result; const char *filename = NULL; const cfg_obj_t *maps[3]; const cfg_obj_t *options; const cfg_obj_t *obj; int i; i = 0; options = NULL; result = cfg_map_get(config, "options", &options); if (result == ISC_R_SUCCESS) maps[i++] = options; maps[i++] = ns_g_defaults; maps[i] = NULL; obj = NULL; (void) ns_config_get(maps, "lock-file", &obj); if (!first_time) { if (obj != NULL && !cfg_obj_isstring(obj) && server->lockfile != NULL && strcmp(cfg_obj_asstring(obj), server->lockfile) != 0) isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_WARNING, "changing 'lock-file' " "has no effect until the " "server is restarted"); return (ISC_R_SUCCESS); } if (obj != NULL) { if (cfg_obj_isvoid(obj)) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_DEBUG(1), "skipping lock-file check "); return (ISC_R_SUCCESS); } else if (ns_g_forcelock) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_WARNING, "'lock-file' has no effect " "because the server was run with -X"); server->lockfile = isc_mem_strdup(server->mctx, ns_g_defaultlockfile); } else { filename = cfg_obj_asstring(obj); server->lockfile = isc_mem_strdup(server->mctx, filename); } if (server->lockfile == NULL) return (ISC_R_NOMEMORY); } if (ns_g_forcelock && ns_g_defaultlockfile != NULL) { INSIST(server->lockfile == NULL); server->lockfile = isc_mem_strdup(server->mctx, ns_g_defaultlockfile); } if (server->lockfile == NULL) return (ISC_R_SUCCESS); if (ns_os_issingleton(server->lockfile)) return (ISC_R_SUCCESS); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, "could not lock %s; another named " "process may be running", server->lockfile); return (ISC_R_FAILURE); } static isc_result_t load_configuration(const char *filename, ns_server_t *server, isc_boolean_t first_time) { cfg_obj_t *config = NULL, *bindkeys = NULL; cfg_parser_t *conf_parser = NULL, *bindkeys_parser = NULL; const cfg_listelt_t *element; const cfg_obj_t *builtin_views; const cfg_obj_t *maps[3]; const cfg_obj_t *obj; const cfg_obj_t *options; const cfg_obj_t *usev4ports, *avoidv4ports, *usev6ports, *avoidv6ports; const cfg_obj_t *views; dns_view_t *view = NULL; dns_view_t *view_next; dns_viewlist_t tmpviewlist; dns_viewlist_t viewlist, builtin_viewlist; in_port_t listen_port, udpport_low, udpport_high; int i; int num_zones = 0; isc_boolean_t exclusive = ISC_FALSE; isc_interval_t interval; isc_logconfig_t *logc = NULL; isc_portset_t *v4portset = NULL; isc_portset_t *v6portset = NULL; isc_resourcevalue_t nfiles; isc_result_t result, tresult; isc_uint32_t heartbeat_interval; isc_uint32_t interface_interval; isc_uint32_t reserved; isc_uint32_t udpsize; isc_uint32_t transfer_message_size; ns_cache_t *nsc; ns_cachelist_t cachelist, tmpcachelist; unsigned int maxsocks; isc_uint32_t softquota = 0; ISC_LIST_INIT(viewlist); ISC_LIST_INIT(builtin_viewlist); ISC_LIST_INIT(cachelist); /* Create the ACL configuration context */ if (ns_g_aclconfctx != NULL) { cfg_aclconfctx_detach(&ns_g_aclconfctx); } CHECK(cfg_aclconfctx_create(ns_g_mctx, &ns_g_aclconfctx)); /* * Shut down all dyndb instances. */ dns_dyndb_cleanup(ISC_FALSE); /* * Parse the global default pseudo-config file. */ if (first_time) { result = ns_config_parsedefaults(ns_g_parser, &ns_g_config); if (result != ISC_R_SUCCESS) { ns_main_earlyfatal("unable to load " "internal defaults: %s", isc_result_totext(result)); } RUNTIME_CHECK(cfg_map_get(ns_g_config, "options", &ns_g_defaults) == ISC_R_SUCCESS); } /* * Parse the configuration file using the new config code. */ config = NULL; /* * Unless this is lwresd with the -C option, parse the config file. */ if (!(ns_g_lwresdonly && lwresd_g_useresolvconf)) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_INFO, "loading configuration from '%s'", filename); CHECK(cfg_parser_create(ns_g_mctx, ns_g_lctx, &conf_parser)); cfg_parser_setcallback(conf_parser, directory_callback, NULL); result = cfg_parse_file(conf_parser, filename, &cfg_type_namedconf, &config); } /* * If this is lwresd with the -C option, or lwresd with no -C or -c * option where the above parsing failed, parse resolv.conf. */ if (ns_g_lwresdonly && (lwresd_g_useresolvconf || (!ns_g_conffileset && result == ISC_R_FILENOTFOUND))) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_INFO, "loading configuration from '%s'", lwresd_g_resolvconffile); if (conf_parser != NULL) { cfg_parser_destroy(&conf_parser); } CHECK(cfg_parser_create(ns_g_mctx, ns_g_lctx, &conf_parser)); result = ns_lwresd_parseeresolvconf(ns_g_mctx, conf_parser, &config); } CHECK(result); /* * Check the validity of the configuration. */ CHECK(bind9_check_namedconf(config, ns_g_lctx, ns_g_mctx)); /* * Fill in the maps array, used for resolving defaults. */ i = 0; options = NULL; result = cfg_map_get(config, "options", &options); if (result == ISC_R_SUCCESS) { maps[i++] = options; } maps[i++] = ns_g_defaults; maps[i] = NULL; /* * If bind.keys exists, load it. If "dnssec-validation auto" * is turned on, the root key found there will be used as a * default trust anchor. */ obj = NULL; result = ns_config_get(maps, "bindkeys-file", &obj); INSIST(result == ISC_R_SUCCESS); CHECKM(setstring(server, &server->bindkeysfile, cfg_obj_asstring(obj)), "strdup"); if (access(server->bindkeysfile, R_OK) == 0) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_INFO, "reading built-in trust anchors " "from file '%s'", server->bindkeysfile); CHECK(cfg_parser_create(ns_g_mctx, ns_g_lctx, &bindkeys_parser)); result = cfg_parse_file(bindkeys_parser, server->bindkeysfile, &cfg_type_bindkeys, &bindkeys); CHECK(result); } else { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_INFO, "unable to open '%s'; using built-in keys " "instead", server->bindkeysfile); } /* Ensure exclusive access to configuration data. */ if (!exclusive) { result = isc_task_beginexclusive(server->task); RUNTIME_CHECK(result == ISC_R_SUCCESS); exclusive = ISC_TRUE; } /* * Set process limits, which (usually) needs to be done as root. */ set_limits(maps); /* * Check the process lockfile. */ CHECK(check_lockfile(server, config, first_time)); /* * Check if max number of open sockets that the system allows is * sufficiently large. Failing this condition is not necessarily fatal, * but may cause subsequent runtime failures for a busy recursive * server. */ result = isc_socketmgr_getmaxsockets(ns_g_socketmgr, &maxsocks); if (result != ISC_R_SUCCESS) { maxsocks = 0; } result = isc_resource_getcurlimit(isc_resource_openfiles, &nfiles); if (result == ISC_R_SUCCESS && (isc_resourcevalue_t)maxsocks > nfiles) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_WARNING, "max open files (%" ISC_PRINT_QUADFORMAT "u)" " is smaller than max sockets (%u)", nfiles, maxsocks); } /* * Set the number of socket reserved for TCP, stdio etc. */ obj = NULL; result = ns_config_get(maps, "reserved-sockets", &obj); INSIST(result == ISC_R_SUCCESS); reserved = cfg_obj_asuint32(obj); if (maxsocks != 0) { if (maxsocks < 128U) { /* Prevent underflow. */ reserved = 0; } else if (reserved > maxsocks - 128U) { /* Minimum UDP space. */ reserved = maxsocks - 128; } } /* Minimum TCP/stdio space. */ if (reserved < 128U) { reserved = 128; } if (reserved + 128U > maxsocks && maxsocks != 0) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_WARNING, "less than 128 UDP sockets available after " "applying 'reserved-sockets' and 'maxsockets'"); } isc__socketmgr_setreserved(ns_g_socketmgr, reserved); #ifdef HAVE_GEOIP /* * Initialize GeoIP databases from the configured location. * This should happen before configuring any ACLs, so that we * know what databases are available and can reject any GeoIP * ACLs that can't work. */ obj = NULL; result = ns_config_get(maps, "geoip-directory", &obj); if (result == ISC_R_SUCCESS && cfg_obj_isstring(obj)) { char *dir; DE_CONST(cfg_obj_asstring(obj), dir); ns_geoip_load(dir); } else { ns_geoip_load(NULL); } ns_g_aclconfctx->geoip = ns_g_geoip; obj = NULL; result = ns_config_get(maps, "geoip-use-ecs", &obj); INSIST(result == ISC_R_SUCCESS); ns_g_server->aclenv.geoip_use_ecs = cfg_obj_asboolean(obj); #endif /* HAVE_GEOIP */ /* * Configure various server options. */ configure_server_quota(maps, "transfers-out", &server->xfroutquota); configure_server_quota(maps, "tcp-clients", &server->tcpquota); configure_server_quota(maps, "recursive-clients", &server->recursionquota); if (server->recursionquota.max > 1000) { int margin = ISC_MAX(100, ns_g_cpus + 1); if (margin > server->recursionquota.max - 100) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, "'recursive-clients %d' too low when " "running with %d worker threads", server->recursionquota.max, ns_g_cpus); CHECK(ISC_R_RANGE); } softquota = server->recursionquota.max - margin; } else { softquota = (server->recursionquota.max * 90) / 100; } isc_quota_soft(&server->recursionquota, softquota); /* * Set "blackhole". Only legal at options level; there is * no default. */ CHECK(configure_view_acl(NULL, config, NULL, "blackhole", NULL, ns_g_aclconfctx, ns_g_mctx, &server->blackholeacl)); if (server->blackholeacl != NULL) { dns_dispatchmgr_setblackhole(ns_g_dispatchmgr, server->blackholeacl); } /* * Set "keep-response-order". Only legal at options or * global defaults level. */ CHECK(configure_view_acl(NULL, config, ns_g_config, "keep-response-order", NULL, ns_g_aclconfctx, ns_g_mctx, &server->keepresporder)); obj = NULL; result = ns_config_get(maps, "match-mapped-addresses", &obj); INSIST(result == ISC_R_SUCCESS); server->aclenv.match_mapped = cfg_obj_asboolean(obj); CHECKM(ns_statschannels_configure(ns_g_server, config, ns_g_aclconfctx), "configuring statistics server(s)"); /* * Configure sets of UDP query source ports. */ CHECKM(isc_portset_create(ns_g_mctx, &v4portset), "creating UDP port set"); CHECKM(isc_portset_create(ns_g_mctx, &v6portset), "creating UDP port set"); usev4ports = NULL; usev6ports = NULL; avoidv4ports = NULL; avoidv6ports = NULL; (void)ns_config_get(maps, "use-v4-udp-ports", &usev4ports); if (usev4ports != NULL) { portset_fromconf(v4portset, usev4ports, ISC_TRUE); } else { CHECKM(isc_net_getudpportrange(AF_INET, &udpport_low, &udpport_high), "get the default UDP/IPv4 port range"); if (udpport_low == udpport_high) { isc_portset_add(v4portset, udpport_low); } else { isc_portset_addrange(v4portset, udpport_low, udpport_high); } if (!ns_g_disable4) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_INFO, "using default UDP/IPv4 port range: " "[%d, %d]", udpport_low, udpport_high); } } (void)ns_config_get(maps, "avoid-v4-udp-ports", &avoidv4ports); if (avoidv4ports != NULL) { portset_fromconf(v4portset, avoidv4ports, ISC_FALSE); } (void)ns_config_get(maps, "use-v6-udp-ports", &usev6ports); if (usev6ports != NULL) { portset_fromconf(v6portset, usev6ports, ISC_TRUE); } else { CHECKM(isc_net_getudpportrange(AF_INET6, &udpport_low, &udpport_high), "get the default UDP/IPv6 port range"); if (udpport_low == udpport_high) { isc_portset_add(v6portset, udpport_low); } else { isc_portset_addrange(v6portset, udpport_low, udpport_high); } if (!ns_g_disable6) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_INFO, "using default UDP/IPv6 port range: " "[%d, %d]", udpport_low, udpport_high); } } (void)ns_config_get(maps, "avoid-v6-udp-ports", &avoidv6ports); if (avoidv6ports != NULL) { portset_fromconf(v6portset, avoidv6ports, ISC_FALSE); } dns_dispatchmgr_setavailports(ns_g_dispatchmgr, v4portset, v6portset); /* * Set the EDNS UDP size when we don't match a view. */ obj = NULL; result = ns_config_get(maps, "edns-udp-size", &obj); INSIST(result == ISC_R_SUCCESS); udpsize = cfg_obj_asuint32(obj); if (udpsize < 512) { udpsize = 512; } if (udpsize > 4096) { udpsize = 4096; } ns_g_udpsize = (isc_uint16_t)udpsize; /* Set the transfer message size for TCP */ obj = NULL; result = ns_config_get(maps, "transfer-message-size", &obj); INSIST(result == ISC_R_SUCCESS); transfer_message_size = cfg_obj_asuint32(obj); if (transfer_message_size < 512) { transfer_message_size = 512; } else if (transfer_message_size > 65535) { transfer_message_size = 65535; } server->transfer_tcp_message_size = (isc_uint16_t) transfer_message_size; /* * Configure the zone manager. */ obj = NULL; result = ns_config_get(maps, "transfers-in", &obj); INSIST(result == ISC_R_SUCCESS); dns_zonemgr_settransfersin(server->zonemgr, cfg_obj_asuint32(obj)); obj = NULL; result = ns_config_get(maps, "transfers-per-ns", &obj); INSIST(result == ISC_R_SUCCESS); dns_zonemgr_settransfersperns(server->zonemgr, cfg_obj_asuint32(obj)); obj = NULL; result = ns_config_get(maps, "notify-rate", &obj); INSIST(result == ISC_R_SUCCESS); dns_zonemgr_setnotifyrate(server->zonemgr, cfg_obj_asuint32(obj)); obj = NULL; result = ns_config_get(maps, "startup-notify-rate", &obj); INSIST(result == ISC_R_SUCCESS); dns_zonemgr_setstartupnotifyrate(server->zonemgr, cfg_obj_asuint32(obj)); obj = NULL; result = ns_config_get(maps, "serial-query-rate", &obj); INSIST(result == ISC_R_SUCCESS); dns_zonemgr_setserialqueryrate(server->zonemgr, cfg_obj_asuint32(obj)); /* * Determine which port to use for listening for incoming connections. */ if (ns_g_port != 0) { listen_port = ns_g_port; } else { CHECKM(ns_config_getport(config, &listen_port), "port"); } /* * Determing the default DSCP code point. */ CHECKM(ns_config_getdscp(config, &ns_g_dscp), "dscp"); /* * Find the listen queue depth. */ obj = NULL; result = ns_config_get(maps, "tcp-listen-queue", &obj); INSIST(result == ISC_R_SUCCESS); ns_g_listen = cfg_obj_asuint32(obj); if ((ns_g_listen > 0) && (ns_g_listen < 10)) { ns_g_listen = 10; } /* * Configure the interface manager according to the "listen-on" * statement. */ { const cfg_obj_t *clistenon = NULL; ns_listenlist_t *listenon = NULL; clistenon = NULL; /* * Even though listen-on is present in the default * configuration, we can't use it here, since it isn't * used if we're in lwresd mode. This way is easier. */ if (options != NULL) { (void)cfg_map_get(options, "listen-on", &clistenon); } if (clistenon != NULL) { /* check return code? */ (void)ns_listenlist_fromconfig(clistenon, config, ns_g_aclconfctx, ns_g_mctx, AF_INET, &listenon); } else if (!ns_g_lwresdonly) { /* * Not specified, use default. */ CHECK(ns_listenlist_default(ns_g_mctx, listen_port, -1, ISC_TRUE, &listenon)); } if (listenon != NULL) { ns_interfacemgr_setlistenon4(server->interfacemgr, listenon); ns_listenlist_detach(&listenon); } } /* * Ditto for IPv6. */ { const cfg_obj_t *clistenon = NULL; ns_listenlist_t *listenon = NULL; if (options != NULL) { (void)cfg_map_get(options, "listen-on-v6", &clistenon); } if (clistenon != NULL) { /* check return code? */ (void)ns_listenlist_fromconfig(clistenon, config, ns_g_aclconfctx, ns_g_mctx, AF_INET6, &listenon); } else if (!ns_g_lwresdonly) { /* * Not specified, use default. */ CHECK(ns_listenlist_default(ns_g_mctx, listen_port, -1, ISC_TRUE, &listenon)); } if (listenon != NULL) { ns_interfacemgr_setlistenon6(server->interfacemgr, listenon); ns_listenlist_detach(&listenon); } } /* * Rescan the interface list to pick up changes in the * listen-on option. It's important that we do this before we try * to configure the query source, since the dispatcher we use might * be shared with an interface. */ result = scan_interfaces(server, ISC_TRUE); /* * Check that named is able to TCP listen on at least one * interface. Otherwise, another named process could be running * and we should fail. */ if (first_time && (result == ISC_R_ADDRINUSE)) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, "unable to listen on any configured interfaces"); result = ISC_R_FAILURE; goto cleanup; } /* * Arrange for further interface scanning to occur periodically * as specified by the "interface-interval" option. */ obj = NULL; result = ns_config_get(maps, "interface-interval", &obj); INSIST(result == ISC_R_SUCCESS); interface_interval = cfg_obj_asuint32(obj) * 60; if (interface_interval == 0) { CHECK(isc_timer_reset(server->interface_timer, isc_timertype_inactive, NULL, NULL, ISC_TRUE)); } else if (server->interface_interval != interface_interval) { isc_interval_set(&interval, interface_interval, 0); CHECK(isc_timer_reset(server->interface_timer, isc_timertype_ticker, NULL, &interval, ISC_FALSE)); } server->interface_interval = interface_interval; /* * Enable automatic interface scans. */ obj = NULL; result = ns_config_get(maps, "automatic-interface-scan", &obj); INSIST(result == ISC_R_SUCCESS); server->interface_auto = cfg_obj_asboolean(obj); /* * Configure the dialup heartbeat timer. */ obj = NULL; result = ns_config_get(maps, "heartbeat-interval", &obj); INSIST(result == ISC_R_SUCCESS); heartbeat_interval = cfg_obj_asuint32(obj) * 60; if (heartbeat_interval == 0) { CHECK(isc_timer_reset(server->heartbeat_timer, isc_timertype_inactive, NULL, NULL, ISC_TRUE)); } else if (server->heartbeat_interval != heartbeat_interval) { isc_interval_set(&interval, heartbeat_interval, 0); CHECK(isc_timer_reset(server->heartbeat_timer, isc_timertype_ticker, NULL, &interval, ISC_FALSE)); } server->heartbeat_interval = heartbeat_interval; isc_interval_set(&interval, 1200, 0); CHECK(isc_timer_reset(server->pps_timer, isc_timertype_ticker, NULL, &interval, ISC_FALSE)); isc_interval_set(&interval, ns_g_tat_interval, 0); CHECK(isc_timer_reset(server->tat_timer, isc_timertype_ticker, NULL, &interval, ISC_FALSE)); /* * Write the PID file. */ obj = NULL; if (ns_config_get(maps, "pid-file", &obj) == ISC_R_SUCCESS) { if (cfg_obj_isvoid(obj)) { ns_os_writepidfile(NULL, first_time); } else { ns_os_writepidfile(cfg_obj_asstring(obj), first_time); } } else if (ns_g_lwresdonly) { ns_os_writepidfile(lwresd_g_defaultpidfile, first_time); } else { ns_os_writepidfile(ns_g_defaultpidfile, first_time); } /* * Configure the server-wide session key. This must be done before * configure views because zone configuration may need to know * session-keyname. * * Failure of session key generation isn't fatal at this time; if it * turns out that a session key is really needed but doesn't exist, * we'll treat it as a fatal error then. */ (void)configure_session_key(maps, server, ns_g_mctx); views = NULL; (void)cfg_map_get(config, "view", &views); /* * Create the views and count all the configured zones in * order to correctly size the zone manager's task table. * (We only count zones for configured views; the built-in * "bind" view can be ignored as it only adds a negligible * number of zones.) * * If we're allowing new zones, we need to be able to find the * new zone file and count those as well. So we setup the new * zone configuration context, but otherwise view configuration * waits until after the zone manager's task list has been sized. */ for (element = cfg_list_first(views); element != NULL; element = cfg_list_next(element)) { cfg_obj_t *vconfig = cfg_listelt_value(element); const cfg_obj_t *voptions = cfg_tuple_get(vconfig, "options"); int nzf_num_zones; view = NULL; CHECK(create_view(vconfig, &viewlist, &view)); INSIST(view != NULL); num_zones += count_zones(voptions); CHECK(setup_newzones(view, config, vconfig, conf_parser, ns_g_aclconfctx, &nzf_num_zones)); num_zones += nzf_num_zones; dns_view_detach(&view); } /* * If there were no explicit views then we do the default * view here. */ if (views == NULL) { int nzf_num_zones; CHECK(create_view(NULL, &viewlist, &view)); INSIST(view != NULL); num_zones = count_zones(config); CHECK(setup_newzones(view, config, NULL, conf_parser, ns_g_aclconfctx, &nzf_num_zones)); num_zones += nzf_num_zones; dns_view_detach(&view); } /* * Zones have been counted; set the zone manager task pool size. */ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_INFO, "sizing zone task pool based on %d zones", num_zones); CHECK(dns_zonemgr_setsize(ns_g_server->zonemgr, num_zones)); /* * Configure and freeze all explicit views. Explicit * views that have zones were already created at parsing * time, but views with no zones must be created here. */ for (element = cfg_list_first(views); element != NULL; element = cfg_list_next(element)) { cfg_obj_t *vconfig = cfg_listelt_value(element); view = NULL; CHECK(find_view(vconfig, &viewlist, &view)); CHECK(configure_view(view, &viewlist, config, vconfig, &cachelist, bindkeys, ns_g_mctx, ns_g_aclconfctx, ISC_TRUE)); dns_view_freeze(view); dns_view_detach(&view); } /* * Make sure we have a default view if and only if there * were no explicit views. */ if (views == NULL) { view = NULL; CHECK(find_view(NULL, &viewlist, &view)); CHECK(configure_view(view, &viewlist, config, NULL, &cachelist, bindkeys, ns_g_mctx, ns_g_aclconfctx, ISC_TRUE)); dns_view_freeze(view); dns_view_detach(&view); } /* * Create (or recreate) the built-in views. */ builtin_views = NULL; RUNTIME_CHECK(cfg_map_get(ns_g_config, "view", &builtin_views) == ISC_R_SUCCESS); for (element = cfg_list_first(builtin_views); element != NULL; element = cfg_list_next(element)) { cfg_obj_t *vconfig = cfg_listelt_value(element); CHECK(create_view(vconfig, &builtin_viewlist, &view)); CHECK(configure_view(view, &viewlist, config, vconfig, &cachelist, bindkeys, ns_g_mctx, ns_g_aclconfctx, ISC_FALSE)); dns_view_freeze(view); dns_view_detach(&view); view = NULL; } /* Now combine the two viewlists into one */ ISC_LIST_APPENDLIST(viewlist, builtin_viewlist, link); /* * Commit any dns_zone_setview() calls on all zones in the new * view. */ for (view = ISC_LIST_HEAD(viewlist); view != NULL; view = ISC_LIST_NEXT(view, link)) { dns_view_setviewcommit(view); } /* Swap our new view list with the production one. */ tmpviewlist = server->viewlist; server->viewlist = viewlist; viewlist = tmpviewlist; /* Make the view list available to each of the views */ view = ISC_LIST_HEAD(server->viewlist); while (view != NULL) { view->viewlist = &server->viewlist; view = ISC_LIST_NEXT(view, link); } /* Swap our new cache list with the production one. */ tmpcachelist = server->cachelist; server->cachelist = cachelist; cachelist = tmpcachelist; /* Load the TKEY information from the configuration. */ if (options != NULL) { dns_tkeyctx_t *t = NULL; CHECKM(ns_tkeyctx_fromconfig(options, ns_g_mctx, ns_g_entropy, &t), "configuring TKEY"); if (server->tkeyctx != NULL) { dns_tkeyctx_destroy(&server->tkeyctx); } server->tkeyctx = t; } /* * Bind the control port(s). */ CHECKM(ns_controls_configure(ns_g_server->controls, config, ns_g_aclconfctx), "binding control channel(s)"); /* * Bind the lwresd port(s). */ CHECKM(ns_lwresd_configure(ns_g_mctx, config), "binding lightweight resolver ports"); /* * Open the source of entropy. */ if (first_time) { obj = NULL; result = ns_config_get(maps, "random-device", &obj); if (result != ISC_R_SUCCESS) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_INFO, "no source of entropy found"); } else { const char *randomdev = cfg_obj_asstring(obj); int level = ISC_LOG_ERROR; result = isc_entropy_createfilesource(ns_g_entropy, randomdev); #ifdef PATH_RANDOMDEV if (ns_g_fallbackentropy != NULL) { level = ISC_LOG_INFO; } #endif if (result != ISC_R_SUCCESS) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, level, "could not open entropy source " "%s: %s", randomdev, isc_result_totext(result)); } #ifdef PATH_RANDOMDEV if (ns_g_fallbackentropy != NULL) { if (result != ISC_R_SUCCESS) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_INFO, "using pre-chroot entropy source " "%s", PATH_RANDOMDEV); isc_entropy_detach(&ns_g_entropy); isc_entropy_attach(ns_g_fallbackentropy, &ns_g_entropy); } isc_entropy_detach(&ns_g_fallbackentropy); } #endif } } #ifdef HAVE_LMDB /* * If we're using LMDB, we may have created newzones databases * as root, making it impossible to reopen them later after * switching to a new userid. We close them now, and reopen * after relinquishing privileges them. */ if (first_time) { for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; view = ISC_LIST_NEXT(view, link)) { nzd_env_close(view); } } #endif /* HAVE_LMDB */ /* * Relinquish root privileges. */ if (first_time) { ns_os_changeuser(); } /* * Check that the working directory is writable. */ if (!isc_file_isdirwritable(".")) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, "the working directory is not writable"); } #ifdef HAVE_LMDB /* * Reopen NZD databases. */ if (first_time) { for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; view = ISC_LIST_NEXT(view, link)) { nzd_env_reopen(view); } } #endif /* HAVE_LMDB */ /* * Configure the logging system. * * Do this after changing UID to make sure that any log * files specified in named.conf get created by the * unprivileged user, not root. */ if (ns_g_logstderr) { const cfg_obj_t *logobj = NULL; isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_INFO, "not using config file logging " "statement for logging due to " "-g option"); (void)cfg_map_get(config, "logging", &logobj); if (logobj != NULL) { result = ns_log_configure(NULL, logobj); if (result != ISC_R_SUCCESS) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, "checking logging configuration " "failed: %s", isc_result_totext(result)); goto cleanup; } } } else { const cfg_obj_t *logobj = NULL; CHECKM(isc_logconfig_create(ns_g_lctx, &logc), "creating new logging configuration"); logobj = NULL; (void)cfg_map_get(config, "logging", &logobj); if (logobj != NULL) { CHECKM(ns_log_configure(logc, logobj), "configuring logging"); } else { CHECKM(ns_log_setdefaultchannels(logc), "setting up default logging channels"); CHECKM(ns_log_setunmatchedcategory(logc), "setting up default 'category unmatched'"); CHECKM(ns_log_setdefaultcategory(logc), "setting up default 'category default'"); } CHECKM(isc_logconfig_use(ns_g_lctx, logc), "installing logging configuration"); logc = NULL; isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_DEBUG(1), "now using logging configuration from " "config file"); } /* * Set the default value of the query logging flag depending * whether a "queries" category has been defined. This is * a disgusting hack, but we need to do this for BIND 8 * compatibility. */ if (first_time) { const cfg_obj_t *logobj = NULL; const cfg_obj_t *categories = NULL; obj = NULL; if (ns_config_get(maps, "querylog", &obj) == ISC_R_SUCCESS) { server->log_queries = cfg_obj_asboolean(obj); } else { (void)cfg_map_get(config, "logging", &logobj); if (logobj != NULL) (void)cfg_map_get(logobj, "category", &categories); if (categories != NULL) { for (element = cfg_list_first(categories); element != NULL; element = cfg_list_next(element)) { const cfg_obj_t *catobj; const char *str; obj = cfg_listelt_value(element); catobj = cfg_tuple_get(obj, "name"); str = cfg_obj_asstring(catobj); if (strcasecmp(str, "queries") == 0) server->log_queries = ISC_TRUE; } } } } obj = NULL; if (options != NULL && cfg_map_get(options, "memstatistics", &obj) == ISC_R_SUCCESS) { ns_g_memstatistics = cfg_obj_asboolean(obj); } else { ns_g_memstatistics = ISC_TF((isc_mem_debugging & ISC_MEM_DEBUGRECORD) != 0); } obj = NULL; if (ns_config_get(maps, "memstatistics-file", &obj) == ISC_R_SUCCESS) { ns_main_setmemstats(cfg_obj_asstring(obj)); } else if (ns_g_memstatistics) { ns_main_setmemstats("named.memstats"); } else { ns_main_setmemstats(NULL); } obj = NULL; result = ns_config_get(maps, "statistics-file", &obj); INSIST(result == ISC_R_SUCCESS); CHECKM(setstring(server, &server->statsfile, cfg_obj_asstring(obj)), "strdup"); obj = NULL; result = ns_config_get(maps, "dump-file", &obj); INSIST(result == ISC_R_SUCCESS); CHECKM(setstring(server, &server->dumpfile, cfg_obj_asstring(obj)), "strdup"); obj = NULL; result = ns_config_get(maps, "secroots-file", &obj); INSIST(result == ISC_R_SUCCESS); CHECKM(setstring(server, &server->secrootsfile, cfg_obj_asstring(obj)), "strdup"); obj = NULL; result = ns_config_get(maps, "recursing-file", &obj); INSIST(result == ISC_R_SUCCESS); CHECKM(setstring(server, &server->recfile, cfg_obj_asstring(obj)), "strdup"); obj = NULL; result = ns_config_get(maps, "version", &obj); if (result == ISC_R_SUCCESS) { CHECKM(setoptstring(server, &server->version, obj), "strdup"); server->version_set = ISC_TRUE; } else { server->version_set = ISC_FALSE; } obj = NULL; result = ns_config_get(maps, "hostname", &obj); if (result == ISC_R_SUCCESS) { CHECKM(setoptstring(server, &server->hostname, obj), "strdup"); server->hostname_set = ISC_TRUE; } else { server->hostname_set = ISC_FALSE; } obj = NULL; result = ns_config_get(maps, "server-id", &obj); server->server_usehostname = ISC_FALSE; if (result == ISC_R_SUCCESS && cfg_obj_isboolean(obj)) { /* The parser translates "hostname" to ISC_TRUE */ server->server_usehostname = cfg_obj_asboolean(obj); result = setstring(server, &server->server_id, NULL); RUNTIME_CHECK(result == ISC_R_SUCCESS); } else if (result == ISC_R_SUCCESS) { /* Found a quoted string */ CHECKM(setoptstring(server, &server->server_id, obj), "strdup"); } else { result = setstring(server, &server->server_id, NULL); RUNTIME_CHECK(result == ISC_R_SUCCESS); } obj = NULL; result = ns_config_get(maps, "flush-zones-on-shutdown", &obj); if (result == ISC_R_SUCCESS) { server->flushonshutdown = cfg_obj_asboolean(obj); } else { server->flushonshutdown = ISC_FALSE; } obj = NULL; result = ns_config_get(maps, "cookie-algorithm", &obj); INSIST(result == ISC_R_SUCCESS); if (strcasecmp(cfg_obj_asstring(obj), "aes") == 0) { #if defined(HAVE_OPENSSL_AES) || defined(HAVE_OPENSSL_EVP_AES) server->cookiealg = ns_cookiealg_aes; #else INSIST(0); #endif } else if (strcasecmp(cfg_obj_asstring(obj), "sha1") == 0) { server->cookiealg = ns_cookiealg_sha1; } else if (strcasecmp(cfg_obj_asstring(obj), "sha256") == 0) { server->cookiealg = ns_cookiealg_sha256; } else { INSIST(0); } obj = NULL; result = ns_config_get(maps, "cookie-secret", &obj); if (result == ISC_R_SUCCESS) { isc_buffer_t b; unsigned int usedlength; memset(server->secret, 0, sizeof(server->secret)); isc_buffer_init(&b, server->secret, sizeof(server->secret)); result = isc_hex_decodestring(cfg_obj_asstring(obj), &b); if (result != ISC_R_SUCCESS && result != ISC_R_NOSPACE) { goto cleanup; } usedlength = isc_buffer_usedlength(&b); switch (server->cookiealg) { case ns_cookiealg_aes: if (usedlength != ISC_AES128_KEYLENGTH) { CHECKM(ISC_R_RANGE, "AES cookie-secret must be 128 bits"); } break; case ns_cookiealg_sha1: if (usedlength != ISC_SHA1_DIGESTLENGTH) { CHECKM(ISC_R_RANGE, "SHA1 cookie-secret must be 160 bits"); } break; case ns_cookiealg_sha256: if (usedlength != ISC_SHA256_DIGESTLENGTH) { CHECKM(ISC_R_RANGE, "SHA256 cookie-secret must be 256 bits"); } break; } } else { result = isc_entropy_getdata(ns_g_entropy, server->secret, sizeof(server->secret), NULL, 0); if (result != ISC_R_SUCCESS) { goto cleanup; } } (void) ns_server_loadnta(server); result = ISC_R_SUCCESS; cleanup: if (logc != NULL) { isc_logconfig_destroy(&logc); } if (v4portset != NULL) { isc_portset_destroy(ns_g_mctx, &v4portset); } if (v6portset != NULL) { isc_portset_destroy(ns_g_mctx, &v6portset); } if (conf_parser != NULL) { if (config != NULL) { cfg_obj_destroy(conf_parser, &config); } cfg_parser_destroy(&conf_parser); } if (bindkeys_parser != NULL) { if (bindkeys != NULL) { cfg_obj_destroy(bindkeys_parser, &bindkeys); } cfg_parser_destroy(&bindkeys_parser); } if (view != NULL) { dns_view_detach(&view); } ISC_LIST_APPENDLIST(viewlist, builtin_viewlist, link); /* * This cleans up either the old production view list * or our temporary list depending on whether they * were swapped above or not. */ for (view = ISC_LIST_HEAD(viewlist); view != NULL; view = view_next) { view_next = ISC_LIST_NEXT(view, link); ISC_LIST_UNLINK(viewlist, view, link); if (result == ISC_R_SUCCESS && strcmp(view->name, "_bind") != 0) { dns_view_setviewrevert(view); (void)dns_zt_apply(view->zonetable, ISC_FALSE, removed, view); } dns_view_detach(&view); } /* Same cleanup for cache list. */ while ((nsc = ISC_LIST_HEAD(cachelist)) != NULL) { ISC_LIST_UNLINK(cachelist, nsc, link); dns_cache_detach(&nsc->cache); isc_mem_put(server->mctx, nsc, sizeof(*nsc)); } /* * Adjust the listening interfaces in accordance with the source * addresses specified in views and zones. */ if (isc_net_probeipv6() == ISC_R_SUCCESS) { adjust_interfaces(server, ns_g_mctx); } /* * Record the time of most recent configuration */ tresult = isc_time_now(&ns_g_configtime); if (tresult != ISC_R_SUCCESS) { ns_main_earlyfatal("isc_time_now() failed: %s", isc_result_totext(result)); } /* Relinquish exclusive access to configuration data. */ if (exclusive) { isc_task_endexclusive(server->task); } isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_DEBUG(1), "load_configuration: %s", isc_result_totext(result)); return (result); } static isc_result_t view_loaded(void *arg) { isc_result_t result; ns_zoneload_t *zl = (ns_zoneload_t *) arg; ns_server_t *server = zl->server; isc_boolean_t reconfig = zl->reconfig; unsigned int refs; /* * Force zone maintenance. Do this after loading * so that we know when we need to force AXFR of * slave zones whose master files are missing. * * We use the zoneload reference counter to let us * know when all views are finished. */ isc_refcount_decrement(&zl->refs, &refs); if (refs != 0) return (ISC_R_SUCCESS); isc_refcount_destroy(&zl->refs); isc_mem_put(server->mctx, zl, sizeof (*zl)); /* * To maintain compatibility with log parsing tools that might * be looking for this string after "rndc reconfig", we keep it * as it is */ if (reconfig) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_INFO, "any newly configured zones are now loaded"); } else { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_NOTICE, "all zones loaded"); } CHECKFATAL(dns_zonemgr_forcemaint(server->zonemgr), "forcing zone maintenance"); ns_os_started(); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_NOTICE, "running"); return (ISC_R_SUCCESS); } static isc_result_t load_zones(ns_server_t *server, isc_boolean_t init, isc_boolean_t reconfig) { isc_result_t result; dns_view_t *view; ns_zoneload_t *zl; unsigned int refs = 0; zl = isc_mem_get(server->mctx, sizeof (*zl)); if (zl == NULL) return (ISC_R_NOMEMORY); zl->server = server; zl->reconfig = reconfig; result = isc_task_beginexclusive(server->task); RUNTIME_CHECK(result == ISC_R_SUCCESS); isc_refcount_init(&zl->refs, 1); /* * Schedule zones to be loaded from disk. */ for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; view = ISC_LIST_NEXT(view, link)) { if (view->managed_keys != NULL) { result = dns_zone_load(view->managed_keys); if (result != ISC_R_SUCCESS && result != DNS_R_UPTODATE && result != DNS_R_CONTINUE) goto cleanup; } if (view->redirect != NULL) { result = dns_zone_load(view->redirect); if (result != ISC_R_SUCCESS && result != DNS_R_UPTODATE && result != DNS_R_CONTINUE) goto cleanup; } /* * 'dns_view_asyncload' calls view_loaded if there are no * zones. */ isc_refcount_increment(&zl->refs, NULL); CHECK(dns_view_asyncload(view, view_loaded, zl)); } cleanup: isc_refcount_decrement(&zl->refs, &refs); if (refs == 0) { isc_refcount_destroy(&zl->refs); isc_mem_put(server->mctx, zl, sizeof (*zl)); } else if (init) { /* * Place the task manager into privileged mode. This * ensures that after we leave task-exclusive mode, no * other tasks will be able to run except for the ones * that are loading zones. (This should only be done during * the initial server setup; it isn't necessary during * a reload.) */ isc_taskmgr_setmode(ns_g_taskmgr, isc_taskmgrmode_privileged); } isc_task_endexclusive(server->task); return (result); } static void run_server(isc_task_t *task, isc_event_t *event) { isc_result_t result; ns_server_t *server = (ns_server_t *)event->ev_arg; INSIST(task == server->task); isc_event_free(&event); CHECKFATAL(dns_dispatchmgr_create(ns_g_mctx, ns_g_entropy, &ns_g_dispatchmgr), "creating dispatch manager"); dns_dispatchmgr_setstats(ns_g_dispatchmgr, server->resolverstats); CHECKFATAL(ns_interfacemgr_create(ns_g_mctx, ns_g_taskmgr, ns_g_socketmgr, ns_g_dispatchmgr, server->task, &server->interfacemgr), "creating interface manager"); CHECKFATAL(isc_timer_create(ns_g_timermgr, isc_timertype_inactive, NULL, NULL, server->task, interface_timer_tick, server, &server->interface_timer), "creating interface timer"); CHECKFATAL(isc_timer_create(ns_g_timermgr, isc_timertype_inactive, NULL, NULL, server->task, heartbeat_timer_tick, server, &server->heartbeat_timer), "creating heartbeat timer"); CHECKFATAL(isc_timer_create(ns_g_timermgr, isc_timertype_inactive, NULL, NULL, server->task, tat_timer_tick, server, &server->tat_timer), "creating trust anchor telemetry timer"); CHECKFATAL(isc_timer_create(ns_g_timermgr, isc_timertype_inactive, NULL, NULL, server->task, pps_timer_tick, server, &server->pps_timer), "creating pps timer"); CHECKFATAL(cfg_parser_create(ns_g_mctx, ns_g_lctx, &ns_g_parser), "creating default configuration parser"); CHECKFATAL(cfg_parser_create(ns_g_mctx, ns_g_lctx, &ns_g_addparser), "creating additional configuration parser"); if (ns_g_lwresdonly) CHECKFATAL(load_configuration(lwresd_g_conffile, server, ISC_TRUE), "loading configuration"); else CHECKFATAL(load_configuration(ns_g_conffile, server, ISC_TRUE), "loading configuration"); isc_hash_init(); CHECKFATAL(load_zones(server, ISC_TRUE, ISC_FALSE), "loading zones"); #ifdef ENABLE_AFL ns_g_run_done = ISC_TRUE; #endif } void ns_server_flushonshutdown(ns_server_t *server, isc_boolean_t flush) { REQUIRE(NS_SERVER_VALID(server)); server->flushonshutdown = flush; } static void shutdown_server(isc_task_t *task, isc_event_t *event) { isc_result_t result; dns_view_t *view, *view_next; ns_server_t *server = (ns_server_t *)event->ev_arg; isc_boolean_t flush = server->flushonshutdown; ns_cache_t *nsc; UNUSED(task); INSIST(task == server->task); result = isc_task_beginexclusive(server->task); RUNTIME_CHECK(result == ISC_R_SUCCESS); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_INFO, "shutting down%s", flush ? ": flushing changes" : ""); ns_statschannels_shutdown(server); ns_controls_shutdown(server->controls); end_reserved_dispatches(server, ISC_TRUE); cleanup_session_key(server, server->mctx); if (ns_g_aclconfctx != NULL) cfg_aclconfctx_detach(&ns_g_aclconfctx); cfg_obj_destroy(ns_g_parser, &ns_g_config); cfg_parser_destroy(&ns_g_parser); cfg_parser_destroy(&ns_g_addparser); (void) ns_server_saventa(server); for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; view = view_next) { view_next = ISC_LIST_NEXT(view, link); ISC_LIST_UNLINK(server->viewlist, view, link); if (flush) dns_view_flushanddetach(&view); else dns_view_detach(&view); } dns_dyndb_cleanup(ISC_TRUE); while ((nsc = ISC_LIST_HEAD(server->cachelist)) != NULL) { ISC_LIST_UNLINK(server->cachelist, nsc, link); dns_cache_detach(&nsc->cache); isc_mem_put(server->mctx, nsc, sizeof(*nsc)); } isc_timer_detach(&server->interface_timer); isc_timer_detach(&server->heartbeat_timer); isc_timer_detach(&server->pps_timer); isc_timer_detach(&server->tat_timer); ns_interfacemgr_shutdown(server->interfacemgr); ns_interfacemgr_detach(&server->interfacemgr); dns_dispatchmgr_destroy(&ns_g_dispatchmgr); dns_zonemgr_shutdown(server->zonemgr); if (ns_g_sessionkey != NULL) { dns_tsigkey_detach(&ns_g_sessionkey); dns_name_free(&ns_g_sessionkeyname, server->mctx); } if (server->keepresporder != NULL) dns_acl_detach(&server->keepresporder); if (server->blackholeacl != NULL) dns_acl_detach(&server->blackholeacl); #ifdef HAVE_DNSTAP dns_dt_shutdown(); #endif #ifdef HAVE_GEOIP dns_geoip_shutdown(); #endif dns_db_detach(&server->in_roothints); isc_task_endexclusive(server->task); isc_task_detach(&server->task); isc_event_free(&event); } void ns_server_create(isc_mem_t *mctx, ns_server_t **serverp) { isc_result_t result; ns_server_t *server = isc_mem_get(mctx, sizeof(*server)); if (server == NULL) fatal("allocating server object", ISC_R_NOMEMORY); server->mctx = mctx; server->task = NULL; /* Initialize configuration data with default values. */ result = isc_quota_init(&server->xfroutquota, 10); RUNTIME_CHECK(result == ISC_R_SUCCESS); result = isc_quota_init(&server->tcpquota, 10); RUNTIME_CHECK(result == ISC_R_SUCCESS); result = isc_quota_init(&server->recursionquota, 100); RUNTIME_CHECK(result == ISC_R_SUCCESS); result = dns_aclenv_init(mctx, &server->aclenv); RUNTIME_CHECK(result == ISC_R_SUCCESS); #ifdef HAVE_GEOIP /* Initialize GeoIP before using ACL environment */ ns_geoip_init(); server->aclenv.geoip = ns_g_geoip; #endif /* Initialize server data structures. */ server->zonemgr = NULL; server->interfacemgr = NULL; ISC_LIST_INIT(server->viewlist); server->in_roothints = NULL; server->blackholeacl = NULL; server->keepresporder = NULL; /* Must be first. */ CHECKFATAL(dst_lib_init2(ns_g_mctx, ns_g_entropy, ns_g_engine, ISC_ENTROPY_GOODONLY), "initializing DST"); CHECKFATAL(dns_rootns_create(mctx, dns_rdataclass_in, NULL, &server->in_roothints), "setting up root hints"); CHECKFATAL(isc_mutex_init(&server->reload_event_lock), "initializing reload event lock"); server->reload_event = isc_event_allocate(ns_g_mctx, server, NS_EVENT_RELOAD, ns_server_reload, server, sizeof(isc_event_t)); CHECKFATAL(server->reload_event == NULL ? ISC_R_NOMEMORY : ISC_R_SUCCESS, "allocating reload event"); server->tkeyctx = NULL; CHECKFATAL(dns_tkeyctx_create(ns_g_mctx, ns_g_entropy, &server->tkeyctx), "creating TKEY context"); /* * Setup the server task, which is responsible for coordinating * startup and shutdown of the server, as well as all exclusive * tasks. */ CHECKFATAL(isc_task_create(ns_g_taskmgr, 0, &server->task), "creating server task"); isc_task_setname(server->task, "server", server); isc_taskmgr_setexcltask(ns_g_taskmgr, server->task); CHECKFATAL(isc_task_onshutdown(server->task, shutdown_server, server), "isc_task_onshutdown"); CHECKFATAL(isc_app_onrun(ns_g_mctx, server->task, run_server, server), "isc_app_onrun"); server->interface_timer = NULL; server->heartbeat_timer = NULL; server->pps_timer = NULL; server->tat_timer = NULL; server->interface_interval = 0; server->heartbeat_interval = 0; CHECKFATAL(dns_zonemgr_create(ns_g_mctx, ns_g_taskmgr, ns_g_timermgr, ns_g_socketmgr, &server->zonemgr), "dns_zonemgr_create"); CHECKFATAL(dns_zonemgr_setsize(server->zonemgr, 1000), "dns_zonemgr_setsize"); server->statsfile = isc_mem_strdup(server->mctx, "named.stats"); CHECKFATAL(server->statsfile == NULL ? ISC_R_NOMEMORY : ISC_R_SUCCESS, "isc_mem_strdup"); server->nsstats = NULL; server->rcvquerystats = NULL; server->opcodestats = NULL; server->rcodestats = NULL; server->zonestats = NULL; server->resolverstats = NULL; server->sockstats = NULL; server->udpinstats4 = NULL; server->udpoutstats4 = NULL; server->udpinstats6 = NULL; server->udpoutstats6 = NULL; server->tcpinstats4 = NULL; server->tcpoutstats4 = NULL; server->tcpinstats6 = NULL; server->tcpoutstats6 = NULL; CHECKFATAL(isc_stats_create(server->mctx, &server->sockstats, isc_sockstatscounter_max), "isc_stats_create"); isc_socketmgr_setstats(ns_g_socketmgr, server->sockstats); server->bindkeysfile = isc_mem_strdup(server->mctx, "bind.keys"); CHECKFATAL(server->bindkeysfile == NULL ? ISC_R_NOMEMORY : ISC_R_SUCCESS, "isc_mem_strdup"); server->dumpfile = isc_mem_strdup(server->mctx, "named_dump.db"); CHECKFATAL(server->dumpfile == NULL ? ISC_R_NOMEMORY : ISC_R_SUCCESS, "isc_mem_strdup"); server->secrootsfile = isc_mem_strdup(server->mctx, "named.secroots"); CHECKFATAL(server->secrootsfile == NULL ? ISC_R_NOMEMORY : ISC_R_SUCCESS, "isc_mem_strdup"); server->recfile = isc_mem_strdup(server->mctx, "named.recursing"); CHECKFATAL(server->recfile == NULL ? ISC_R_NOMEMORY : ISC_R_SUCCESS, "isc_mem_strdup"); server->hostname_set = ISC_FALSE; server->hostname = NULL; server->version_set = ISC_FALSE; server->version = NULL; server->server_usehostname = ISC_FALSE; server->server_id = NULL; CHECKFATAL(isc_stats_create(ns_g_mctx, &server->nsstats, dns_nsstatscounter_max), "dns_stats_create (server)"); CHECKFATAL(dns_rdatatypestats_create(ns_g_mctx, &server->rcvquerystats), "dns_stats_create (rcvquery)"); CHECKFATAL(dns_opcodestats_create(ns_g_mctx, &server->opcodestats), "dns_stats_create (opcode)"); CHECKFATAL(dns_rcodestats_create(ns_g_mctx, &server->rcodestats), "dns_stats_create (rcode)"); CHECKFATAL(isc_stats_create(ns_g_mctx, &server->zonestats, dns_zonestatscounter_max), "dns_stats_create (zone)"); CHECKFATAL(isc_stats_create(ns_g_mctx, &server->resolverstats, dns_resstatscounter_max), "dns_stats_create (resolver)"); CHECKFATAL(isc_stats_create(ns_g_mctx, &server->udpinstats4, dns_sizecounter_in_max), "dns_stats_create (inbound UDP IPv4 traffic size)"); CHECKFATAL(isc_stats_create(ns_g_mctx, &server->udpoutstats4, dns_sizecounter_out_max), "dns_stats_create (outbound UDP IPv4 traffic size)"); CHECKFATAL(isc_stats_create(ns_g_mctx, &server->udpinstats6, dns_sizecounter_in_max), "dns_stats_create (inbound UDP IPv6 traffic size)"); CHECKFATAL(isc_stats_create(ns_g_mctx, &server->udpoutstats6, dns_sizecounter_out_max), "dns_stats_create (outbound UDP IPv6 traffic size)"); CHECKFATAL(isc_stats_create(ns_g_mctx, &server->tcpinstats4, dns_sizecounter_in_max), "dns_stats_create (inbound TCP IPv4 traffic size)"); CHECKFATAL(isc_stats_create(ns_g_mctx, &server->tcpoutstats4, dns_sizecounter_out_max), "dns_stats_create (outbound TCP IPv4 traffic size)"); CHECKFATAL(isc_stats_create(ns_g_mctx, &server->tcpinstats6, dns_sizecounter_in_max), "dns_stats_create (inbound TCP IPv6 traffic size)"); CHECKFATAL(isc_stats_create(ns_g_mctx, &server->tcpoutstats6, dns_sizecounter_out_max), "dns_stats_create (outbound TCP IPv6 traffic size)"); server->flushonshutdown = ISC_FALSE; server->log_queries = ISC_FALSE; server->controls = NULL; CHECKFATAL(ns_controls_create(server, &server->controls), "ns_controls_create"); server->dispatchgen = 0; ISC_LIST_INIT(server->dispatches); ISC_LIST_INIT(server->statschannels); ISC_LIST_INIT(server->cachelist); server->sessionkey = NULL; server->session_keyfile = NULL; server->session_keyname = NULL; server->session_keyalg = DST_ALG_UNKNOWN; server->session_keybits = 0; server->lockfile = NULL; server->dtenv = NULL; server->magic = NS_SERVER_MAGIC; *serverp = server; } void ns_server_destroy(ns_server_t **serverp) { ns_server_t *server = *serverp; REQUIRE(NS_SERVER_VALID(server)); #ifdef HAVE_DNSTAP if (server->dtenv != NULL) dns_dt_detach(&server->dtenv); #endif /* HAVE_DNSTAP */ ns_controls_destroy(&server->controls); isc_stats_detach(&server->nsstats); dns_stats_detach(&server->rcvquerystats); dns_stats_detach(&server->opcodestats); dns_stats_detach(&server->rcodestats); isc_stats_detach(&server->zonestats); isc_stats_detach(&server->resolverstats); isc_stats_detach(&server->sockstats); isc_stats_detach(&server->udpinstats4); isc_stats_detach(&server->udpoutstats4); isc_stats_detach(&server->udpinstats6); isc_stats_detach(&server->udpoutstats6); isc_stats_detach(&server->tcpinstats4); isc_stats_detach(&server->tcpoutstats4); isc_stats_detach(&server->tcpinstats6); isc_stats_detach(&server->tcpoutstats6); isc_mem_free(server->mctx, server->statsfile); isc_mem_free(server->mctx, server->bindkeysfile); isc_mem_free(server->mctx, server->dumpfile); isc_mem_free(server->mctx, server->secrootsfile); isc_mem_free(server->mctx, server->recfile); if (server->version != NULL) isc_mem_free(server->mctx, server->version); if (server->hostname != NULL) isc_mem_free(server->mctx, server->hostname); if (server->server_id != NULL) isc_mem_free(server->mctx, server->server_id); if (server->lockfile != NULL) isc_mem_free(server->mctx, server->lockfile); if (server->zonemgr != NULL) dns_zonemgr_detach(&server->zonemgr); if (server->tkeyctx != NULL) dns_tkeyctx_destroy(&server->tkeyctx); dst_lib_destroy(); isc_event_free(&server->reload_event); INSIST(ISC_LIST_EMPTY(server->viewlist)); INSIST(ISC_LIST_EMPTY(server->cachelist)); dns_aclenv_destroy(&server->aclenv); isc_quota_destroy(&server->recursionquota); isc_quota_destroy(&server->tcpquota); isc_quota_destroy(&server->xfroutquota); server->magic = 0; isc_mem_put(server->mctx, server, sizeof(*server)); *serverp = NULL; } static void fatal(const char *msg, isc_result_t result) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_CRITICAL, "%s: %s", msg, isc_result_totext(result)); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_CRITICAL, "exiting (due to fatal error)"); ns_os_shutdown(); exit(1); } static void start_reserved_dispatches(ns_server_t *server) { REQUIRE(NS_SERVER_VALID(server)); server->dispatchgen++; } static void end_reserved_dispatches(ns_server_t *server, isc_boolean_t all) { ns_dispatch_t *dispatch, *nextdispatch; REQUIRE(NS_SERVER_VALID(server)); for (dispatch = ISC_LIST_HEAD(server->dispatches); dispatch != NULL; dispatch = nextdispatch) { nextdispatch = ISC_LIST_NEXT(dispatch, link); if (!all && server->dispatchgen == dispatch-> dispatchgen) continue; ISC_LIST_UNLINK(server->dispatches, dispatch, link); dns_dispatch_detach(&dispatch->dispatch); isc_mem_put(server->mctx, dispatch, sizeof(*dispatch)); } } void ns_add_reserved_dispatch(ns_server_t *server, const isc_sockaddr_t *addr) { ns_dispatch_t *dispatch; in_port_t port; char addrbuf[ISC_SOCKADDR_FORMATSIZE]; isc_result_t result; unsigned int attrs, attrmask; REQUIRE(NS_SERVER_VALID(server)); port = isc_sockaddr_getport(addr); if (port == 0 || port >= 1024) return; for (dispatch = ISC_LIST_HEAD(server->dispatches); dispatch != NULL; dispatch = ISC_LIST_NEXT(dispatch, link)) { if (isc_sockaddr_equal(&dispatch->addr, addr)) break; } if (dispatch != NULL) { dispatch->dispatchgen = server->dispatchgen; return; } dispatch = isc_mem_get(server->mctx, sizeof(*dispatch)); if (dispatch == NULL) { result = ISC_R_NOMEMORY; goto cleanup; } dispatch->addr = *addr; dispatch->dispatchgen = server->dispatchgen; dispatch->dispatch = NULL; attrs = 0; attrs |= DNS_DISPATCHATTR_UDP; switch (isc_sockaddr_pf(addr)) { case AF_INET: attrs |= DNS_DISPATCHATTR_IPV4; break; case AF_INET6: attrs |= DNS_DISPATCHATTR_IPV6; break; default: result = ISC_R_NOTIMPLEMENTED; goto cleanup; } attrmask = 0; attrmask |= DNS_DISPATCHATTR_UDP; attrmask |= DNS_DISPATCHATTR_TCP; attrmask |= DNS_DISPATCHATTR_IPV4; attrmask |= DNS_DISPATCHATTR_IPV6; result = dns_dispatch_getudp(ns_g_dispatchmgr, ns_g_socketmgr, ns_g_taskmgr, &dispatch->addr, 4096, UDPBUFFERS, 32768, 16411, 16433, attrs, attrmask, &dispatch->dispatch); if (result != ISC_R_SUCCESS) goto cleanup; ISC_LIST_INITANDPREPEND(server->dispatches, dispatch, link); return; cleanup: if (dispatch != NULL) isc_mem_put(server->mctx, dispatch, sizeof(*dispatch)); isc_sockaddr_format(addr, addrbuf, sizeof(addrbuf)); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_WARNING, "unable to create dispatch for reserved port %s: %s", addrbuf, isc_result_totext(result)); } static isc_result_t loadconfig(ns_server_t *server) { isc_result_t result; start_reserved_dispatches(server); result = load_configuration(ns_g_lwresdonly ? lwresd_g_conffile : ns_g_conffile, server, ISC_FALSE); if (result == ISC_R_SUCCESS) { end_reserved_dispatches(server, ISC_FALSE); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_INFO, "reloading configuration succeeded"); } else { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, "reloading configuration failed: %s", isc_result_totext(result)); } return (result); } static isc_result_t reload(ns_server_t *server) { isc_result_t result; CHECK(loadconfig(server)); result = load_zones(server, ISC_FALSE, ISC_FALSE); if (result == ISC_R_SUCCESS) isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_INFO, "reloading zones succeeded"); else isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, "reloading zones failed: %s", isc_result_totext(result)); cleanup: return (result); } /* * Handle a reload event (from SIGHUP). */ static void ns_server_reload(isc_task_t *task, isc_event_t *event) { ns_server_t *server = (ns_server_t *)event->ev_arg; INSIST(task = server->task); UNUSED(task); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_INFO, "received SIGHUP signal to reload zones"); (void)reload(server); LOCK(&server->reload_event_lock); INSIST(server->reload_event == NULL); server->reload_event = event; UNLOCK(&server->reload_event_lock); } void ns_server_reloadwanted(ns_server_t *server) { LOCK(&server->reload_event_lock); if (server->reload_event != NULL) isc_task_send(server->task, &server->reload_event); UNLOCK(&server->reload_event_lock); } void ns_server_scan_interfaces(ns_server_t *server) { isc_result_t result; isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_DEBUG(1), "automatic interface rescan"); result = isc_task_beginexclusive(server->task); RUNTIME_CHECK(result == ISC_R_SUCCESS); scan_interfaces(server, ISC_TRUE); isc_task_endexclusive(server->task); } /* * Get the next token from lexer 'lex'. * * NOTE: the token value for string tokens always uses the same pointer * value. Multiple calls to this function on the same lexer will always * return either that value (lex->data) or NULL. It is necessary to copy * the token into local storage if it needs to be referenced after the next * call to next_token(). */ static char * next_token(isc_lex_t *lex, isc_buffer_t **text) { isc_result_t result; isc_token_t token; token.type = isc_tokentype_unknown; result = isc_lex_gettoken(lex, ISC_LEXOPT_EOF|ISC_LEXOPT_QSTRING, &token); switch (result) { case ISC_R_NOMORE: (void) isc_lex_close(lex); break; case ISC_R_SUCCESS: if (token.type == isc_tokentype_eof) (void) isc_lex_close(lex); break; case ISC_R_NOSPACE: if (text != NULL) { (void) putstr(text, "token too large"); (void) putnull(text); } return (NULL); default: if (text != NULL) { (void) putstr(text, isc_result_totext(result)); (void) putnull(text); } return (NULL); } if (token.type == isc_tokentype_string || token.type == isc_tokentype_qstring) return (token.value.as_textregion.base); return (NULL); } /* * Find the zone specified in the control channel command, if any. * If a zone is specified, point '*zonep' at it, otherwise * set '*zonep' to NULL, and f 'zonename' is not NULL, copy * the zone name into it (N.B. 'zonename' must have space to hold * a full DNS name). * * If 'zonetxt' is set, the caller has already pulled a token * off the command line that is to be used as the zone name. (This * is sometimes done when it's necessary to check for an optional * argument before the zone name, as in "rndc sync [-clean] zone".) */ static isc_result_t zone_from_args(ns_server_t *server, isc_lex_t *lex, const char *zonetxt, dns_zone_t **zonep, char *zonename, isc_buffer_t **text, isc_boolean_t skip) { char *ptr; char *classtxt; const char *viewtxt = NULL; dns_fixedname_t fname; dns_name_t *name; isc_result_t result; dns_view_t *view = NULL; dns_rdataclass_t rdclass; char problem[DNS_NAME_FORMATSIZE + 500] = ""; char zonebuf[DNS_NAME_FORMATSIZE]; REQUIRE(zonep != NULL && *zonep == NULL); if (skip) { /* Skip the command name. */ ptr = next_token(lex, text); if (ptr == NULL) return (ISC_R_UNEXPECTEDEND); } /* Look for the zone name. */ if (zonetxt == NULL) zonetxt = next_token(lex, text); if (zonetxt == NULL) return (ISC_R_SUCCESS); /* Copy zonetxt because it'll be overwritten by next_token() */ strlcpy(zonebuf, zonetxt, DNS_NAME_FORMATSIZE); if (zonename != NULL) strlcpy(zonename, zonetxt, DNS_NAME_FORMATSIZE); dns_fixedname_init(&fname); name = dns_fixedname_name(&fname); CHECK(dns_name_fromstring(name, zonebuf, 0, NULL)); /* Look for the optional class name. */ classtxt = next_token(lex, text); if (classtxt != NULL) { isc_textregion_t r; r.base = classtxt; r.length = strlen(classtxt); CHECK(dns_rdataclass_fromtext(&rdclass, &r)); /* Look for the optional view name. */ viewtxt = next_token(lex, text); } else rdclass = dns_rdataclass_in; if (viewtxt == NULL) { result = dns_viewlist_findzone(&server->viewlist, name, ISC_TF(classtxt == NULL), rdclass, zonep); if (result == ISC_R_NOTFOUND) snprintf(problem, sizeof(problem), "no matching zone '%s' in any view", zonebuf); else if (result == ISC_R_MULTIPLE) snprintf(problem, sizeof(problem), "zone '%s' was found in multiple views", zonebuf); } else { result = dns_viewlist_find(&server->viewlist, viewtxt, rdclass, &view); if (result != ISC_R_SUCCESS) { snprintf(problem, sizeof(problem), "no matching view '%s'", viewtxt); goto report; } result = dns_zt_find(view->zonetable, name, 0, NULL, zonep); if (result != ISC_R_SUCCESS) snprintf(problem, sizeof(problem), "no matching zone '%s' in view '%s'", zonebuf, viewtxt); } /* Partial match? */ if (result != ISC_R_SUCCESS && *zonep != NULL) dns_zone_detach(zonep); if (result == DNS_R_PARTIALMATCH) result = ISC_R_NOTFOUND; report: if (result != ISC_R_SUCCESS) { isc_result_t tresult; tresult = putstr(text, problem); if (tresult == ISC_R_SUCCESS) (void) putnull(text); } cleanup: if (view != NULL) dns_view_detach(&view); return (result); } /* * Act on a "retransfer" command from the command channel. */ isc_result_t ns_server_retransfercommand(ns_server_t *server, isc_lex_t *lex, isc_buffer_t **text) { isc_result_t result; dns_zone_t *zone = NULL; dns_zone_t *raw = NULL; dns_zonetype_t type; result = zone_from_args(server, lex, NULL, &zone, NULL, text, ISC_TRUE); if (result != ISC_R_SUCCESS) return (result); if (zone == NULL) return (ISC_R_UNEXPECTEDEND); dns_zone_getraw(zone, &raw); if (raw != NULL) { dns_zone_detach(&zone); dns_zone_attach(raw, &zone); dns_zone_detach(&raw); } type = dns_zone_gettype(zone); if (type == dns_zone_slave || type == dns_zone_stub) dns_zone_forcereload(zone); else result = ISC_R_NOTFOUND; dns_zone_detach(&zone); return (result); } /* * Act on a "reload" command from the command channel. */ isc_result_t ns_server_reloadcommand(ns_server_t *server, isc_lex_t *lex, isc_buffer_t **text) { isc_result_t result; dns_zone_t *zone = NULL; dns_zonetype_t type; const char *msg = NULL; result = zone_from_args(server, lex, NULL, &zone, NULL, text, ISC_TRUE); if (result != ISC_R_SUCCESS) return (result); if (zone == NULL) { result = reload(server); if (result == ISC_R_SUCCESS) msg = "server reload successful"; } else { type = dns_zone_gettype(zone); if (type == dns_zone_slave || type == dns_zone_stub) { dns_zone_refresh(zone); dns_zone_detach(&zone); msg = "zone refresh queued"; } else { result = dns_zone_load(zone); dns_zone_detach(&zone); switch (result) { case ISC_R_SUCCESS: msg = "zone reload successful"; break; case DNS_R_CONTINUE: msg = "zone reload queued"; result = ISC_R_SUCCESS; break; case DNS_R_UPTODATE: msg = "zone reload up-to-date"; result = ISC_R_SUCCESS; break; default: /* failure message will be generated by rndc */ break; } } } if (msg != NULL) { (void) putstr(text, msg); (void) putnull(text); } return (result); } /* * Act on a "reconfig" command from the command channel. */ isc_result_t ns_server_reconfigcommand(ns_server_t *server) { isc_result_t result; CHECK(loadconfig(server)); result = load_zones(server, ISC_FALSE, ISC_TRUE); if (result == ISC_R_SUCCESS) isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_INFO, "scheduled loading new zones"); else isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, "loading new zones failed: %s", isc_result_totext(result)); cleanup: return (result); } /* * Act on a "notify" command from the command channel. */ isc_result_t ns_server_notifycommand(ns_server_t *server, isc_lex_t *lex, isc_buffer_t **text) { isc_result_t result; dns_zone_t *zone = NULL; const char msg[] = "zone notify queued"; result = zone_from_args(server, lex, NULL, &zone, NULL, text, ISC_TRUE); if (result != ISC_R_SUCCESS) return (result); if (zone == NULL) return (ISC_R_UNEXPECTEDEND); dns_zone_notify(zone); dns_zone_detach(&zone); (void) putstr(text, msg); (void) putnull(text); return (ISC_R_SUCCESS); } /* * Act on a "refresh" command from the command channel. */ isc_result_t ns_server_refreshcommand(ns_server_t *server, isc_lex_t *lex, isc_buffer_t **text) { isc_result_t result; dns_zone_t *zone = NULL, *raw = NULL; const char msg1[] = "zone refresh queued"; const char msg2[] = "not a slave or stub zone"; dns_zonetype_t type; result = zone_from_args(server, lex, NULL, &zone, NULL, text, ISC_TRUE); if (result != ISC_R_SUCCESS) return (result); if (zone == NULL) return (ISC_R_UNEXPECTEDEND); dns_zone_getraw(zone, &raw); if (raw != NULL) { dns_zone_detach(&zone); dns_zone_attach(raw, &zone); dns_zone_detach(&raw); } type = dns_zone_gettype(zone); if (type == dns_zone_slave || type == dns_zone_stub) { dns_zone_refresh(zone); dns_zone_detach(&zone); (void) putstr(text, msg1); (void) putnull(text); return (ISC_R_SUCCESS); } dns_zone_detach(&zone); (void) putstr(text, msg2); (void) putnull(text); return (ISC_R_FAILURE); } isc_result_t ns_server_togglequerylog(ns_server_t *server, isc_lex_t *lex) { isc_boolean_t value; char *ptr; /* Skip the command name. */ ptr = next_token(lex, NULL); if (ptr == NULL) return (ISC_R_UNEXPECTEDEND); ptr = next_token(lex, NULL); if (ptr == NULL) { value = server->log_queries ? ISC_FALSE : ISC_TRUE; } else if (!strcasecmp(ptr, "on") || !strcasecmp(ptr, "yes") || !strcasecmp(ptr, "enable") || !strcasecmp(ptr, "true")) { value = ISC_TRUE; } else if (!strcasecmp(ptr, "off") || !strcasecmp(ptr, "no") || !strcasecmp(ptr, "disable") || !strcasecmp(ptr, "false")) { value = ISC_FALSE; } else { return (DNS_R_SYNTAX); } if (server->log_queries == value) return (ISC_R_SUCCESS); server->log_queries = value; isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_INFO, "query logging is now %s", server->log_queries ? "on" : "off"); return (ISC_R_SUCCESS); } static isc_result_t ns_listenlist_fromconfig(const cfg_obj_t *listenlist, const cfg_obj_t *config, cfg_aclconfctx_t *actx, isc_mem_t *mctx, isc_uint16_t family, ns_listenlist_t **target) { isc_result_t result; const cfg_listelt_t *element; ns_listenlist_t *dlist = NULL; REQUIRE(target != NULL && *target == NULL); result = ns_listenlist_create(mctx, &dlist); if (result != ISC_R_SUCCESS) return (result); for (element = cfg_list_first(listenlist); element != NULL; element = cfg_list_next(element)) { ns_listenelt_t *delt = NULL; const cfg_obj_t *listener = cfg_listelt_value(element); result = ns_listenelt_fromconfig(listener, config, actx, mctx, family, &delt); if (result != ISC_R_SUCCESS) goto cleanup; ISC_LIST_APPEND(dlist->elts, delt, link); } *target = dlist; return (ISC_R_SUCCESS); cleanup: ns_listenlist_detach(&dlist); return (result); } /* * Create a listen list from the corresponding configuration * data structure. */ static isc_result_t ns_listenelt_fromconfig(const cfg_obj_t *listener, const cfg_obj_t *config, cfg_aclconfctx_t *actx, isc_mem_t *mctx, isc_uint16_t family, ns_listenelt_t **target) { isc_result_t result; const cfg_obj_t *portobj, *dscpobj; in_port_t port; isc_dscp_t dscp = -1; ns_listenelt_t *delt = NULL; REQUIRE(target != NULL && *target == NULL); portobj = cfg_tuple_get(listener, "port"); if (!cfg_obj_isuint32(portobj)) { if (ns_g_port != 0) { port = ns_g_port; } else { result = ns_config_getport(config, &port); if (result != ISC_R_SUCCESS) return (result); } } else { if (cfg_obj_asuint32(portobj) >= ISC_UINT16_MAX) { cfg_obj_log(portobj, ns_g_lctx, ISC_LOG_ERROR, "port value '%u' is out of range", cfg_obj_asuint32(portobj)); return (ISC_R_RANGE); } port = (in_port_t)cfg_obj_asuint32(portobj); } dscpobj = cfg_tuple_get(listener, "dscp"); if (!cfg_obj_isuint32(dscpobj)) dscp = ns_g_dscp; else { if (cfg_obj_asuint32(dscpobj) > 63) { cfg_obj_log(dscpobj, ns_g_lctx, ISC_LOG_ERROR, "dscp value '%u' is out of range", cfg_obj_asuint32(dscpobj)); return (ISC_R_RANGE); } dscp = (isc_dscp_t)cfg_obj_asuint32(dscpobj); } result = ns_listenelt_create(mctx, port, dscp, NULL, &delt); if (result != ISC_R_SUCCESS) return (result); result = cfg_acl_fromconfig2(cfg_tuple_get(listener, "acl"), config, ns_g_lctx, actx, mctx, 0, family, &delt->acl); if (result != ISC_R_SUCCESS) { ns_listenelt_destroy(delt); return (result); } *target = delt; return (ISC_R_SUCCESS); } isc_result_t ns_server_dumpstats(ns_server_t *server) { isc_result_t result; FILE *fp = NULL; CHECKMF(isc_stdio_open(server->statsfile, "a", &fp), "could not open statistics dump file", server->statsfile); result = ns_stats_dump(server, fp); cleanup: if (fp != NULL) (void)isc_stdio_close(fp); if (result == ISC_R_SUCCESS) isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_INFO, "dumpstats complete"); else isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, "dumpstats failed: %s", dns_result_totext(result)); return (result); } static isc_result_t add_zone_tolist(dns_zone_t *zone, void *uap) { struct dumpcontext *dctx = uap; struct zonelistentry *zle; zle = isc_mem_get(dctx->mctx, sizeof *zle); if (zle == NULL) return (ISC_R_NOMEMORY); zle->zone = NULL; dns_zone_attach(zone, &zle->zone); ISC_LINK_INIT(zle, link); ISC_LIST_APPEND(ISC_LIST_TAIL(dctx->viewlist)->zonelist, zle, link); return (ISC_R_SUCCESS); } static isc_result_t add_view_tolist(struct dumpcontext *dctx, dns_view_t *view) { struct viewlistentry *vle; isc_result_t result = ISC_R_SUCCESS; /* * Prevent duplicate views. */ for (vle = ISC_LIST_HEAD(dctx->viewlist); vle != NULL; vle = ISC_LIST_NEXT(vle, link)) if (vle->view == view) return (ISC_R_SUCCESS); vle = isc_mem_get(dctx->mctx, sizeof *vle); if (vle == NULL) return (ISC_R_NOMEMORY); vle->view = NULL; dns_view_attach(view, &vle->view); ISC_LINK_INIT(vle, link); ISC_LIST_INIT(vle->zonelist); ISC_LIST_APPEND(dctx->viewlist, vle, link); if (dctx->dumpzones) result = dns_zt_apply(view->zonetable, ISC_TRUE, add_zone_tolist, dctx); return (result); } static void dumpcontext_destroy(struct dumpcontext *dctx) { struct viewlistentry *vle; struct zonelistentry *zle; vle = ISC_LIST_HEAD(dctx->viewlist); while (vle != NULL) { ISC_LIST_UNLINK(dctx->viewlist, vle, link); zle = ISC_LIST_HEAD(vle->zonelist); while (zle != NULL) { ISC_LIST_UNLINK(vle->zonelist, zle, link); dns_zone_detach(&zle->zone); isc_mem_put(dctx->mctx, zle, sizeof *zle); zle = ISC_LIST_HEAD(vle->zonelist); } dns_view_detach(&vle->view); isc_mem_put(dctx->mctx, vle, sizeof *vle); vle = ISC_LIST_HEAD(dctx->viewlist); } if (dctx->version != NULL) dns_db_closeversion(dctx->db, &dctx->version, ISC_FALSE); if (dctx->db != NULL) dns_db_detach(&dctx->db); if (dctx->cache != NULL) dns_db_detach(&dctx->cache); if (dctx->task != NULL) isc_task_detach(&dctx->task); if (dctx->fp != NULL) (void)isc_stdio_close(dctx->fp); if (dctx->mdctx != NULL) dns_dumpctx_detach(&dctx->mdctx); isc_mem_put(dctx->mctx, dctx, sizeof *dctx); } static void dumpdone(void *arg, isc_result_t result) { struct dumpcontext *dctx = arg; char buf[1024+32]; const dns_master_style_t *style; if (result != ISC_R_SUCCESS) goto cleanup; if (dctx->mdctx != NULL) dns_dumpctx_detach(&dctx->mdctx); if (dctx->view == NULL) { dctx->view = ISC_LIST_HEAD(dctx->viewlist); if (dctx->view == NULL) goto done; INSIST(dctx->zone == NULL); } else goto resume; nextview: fprintf(dctx->fp, ";\n; Start view %s\n;\n", dctx->view->view->name); resume: if (dctx->dumpcache && dns_view_iscacheshared(dctx->view->view)) { fprintf(dctx->fp, ";\n; Cache of view '%s' is shared as '%s'\n", dctx->view->view->name, dns_cache_getname(dctx->view->view->cache)); } else if (dctx->zone == NULL && dctx->cache == NULL && dctx->dumpcache) { style = &dns_master_style_cache; /* start cache dump */ if (dctx->view->view->cachedb != NULL) dns_db_attach(dctx->view->view->cachedb, &dctx->cache); if (dctx->cache != NULL) { fprintf(dctx->fp, ";\n; Cache dump of view '%s' (cache %s)\n;\n", dctx->view->view->name, dns_cache_getname(dctx->view->view->cache)); result = dns_master_dumptostreaminc(dctx->mctx, dctx->cache, NULL, style, dctx->fp, dctx->task, dumpdone, dctx, &dctx->mdctx); if (result == DNS_R_CONTINUE) return; if (result == ISC_R_NOTIMPLEMENTED) fprintf(dctx->fp, "; %s\n", dns_result_totext(result)); else if (result != ISC_R_SUCCESS) goto cleanup; } } if ((dctx->dumpadb || dctx->dumpbad || dctx->dumpfail) && dctx->cache == NULL && dctx->view->view->cachedb != NULL) dns_db_attach(dctx->view->view->cachedb, &dctx->cache); if (dctx->cache != NULL) { if (dctx->dumpadb) dns_adb_dump(dctx->view->view->adb, dctx->fp); if (dctx->dumpbad) dns_resolver_printbadcache(dctx->view->view->resolver, dctx->fp); if (dctx->dumpfail) dns_badcache_print(dctx->view->view->failcache, "SERVFAIL cache", dctx->fp); dns_db_detach(&dctx->cache); } if (dctx->dumpzones) { style = &dns_master_style_full; nextzone: if (dctx->version != NULL) dns_db_closeversion(dctx->db, &dctx->version, ISC_FALSE); if (dctx->db != NULL) dns_db_detach(&dctx->db); if (dctx->zone == NULL) dctx->zone = ISC_LIST_HEAD(dctx->view->zonelist); else dctx->zone = ISC_LIST_NEXT(dctx->zone, link); if (dctx->zone != NULL) { /* start zone dump */ dns_zone_name(dctx->zone->zone, buf, sizeof(buf)); fprintf(dctx->fp, ";\n; Zone dump of '%s'\n;\n", buf); result = dns_zone_getdb(dctx->zone->zone, &dctx->db); if (result != ISC_R_SUCCESS) { fprintf(dctx->fp, "; %s\n", dns_result_totext(result)); goto nextzone; } dns_db_currentversion(dctx->db, &dctx->version); result = dns_master_dumptostreaminc(dctx->mctx, dctx->db, dctx->version, style, dctx->fp, dctx->task, dumpdone, dctx, &dctx->mdctx); if (result == DNS_R_CONTINUE) return; if (result == ISC_R_NOTIMPLEMENTED) { fprintf(dctx->fp, "; %s\n", dns_result_totext(result)); result = ISC_R_SUCCESS; POST(result); goto nextzone; } if (result != ISC_R_SUCCESS) goto cleanup; } } if (dctx->view != NULL) dctx->view = ISC_LIST_NEXT(dctx->view, link); if (dctx->view != NULL) goto nextview; done: fprintf(dctx->fp, "; Dump complete\n"); result = isc_stdio_flush(dctx->fp); if (result == ISC_R_SUCCESS) isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_INFO, "dumpdb complete"); cleanup: if (result != ISC_R_SUCCESS) isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, "dumpdb failed: %s", dns_result_totext(result)); dumpcontext_destroy(dctx); } isc_result_t ns_server_dumpdb(ns_server_t *server, isc_lex_t *lex, isc_buffer_t **text) { struct dumpcontext *dctx = NULL; dns_view_t *view; isc_result_t result; char *ptr; const char *sep; isc_boolean_t found; /* Skip the command name. */ ptr = next_token(lex, NULL); if (ptr == NULL) return (ISC_R_UNEXPECTEDEND); dctx = isc_mem_get(server->mctx, sizeof(*dctx)); if (dctx == NULL) return (ISC_R_NOMEMORY); dctx->mctx = server->mctx; dctx->dumpcache = ISC_TRUE; dctx->dumpadb = ISC_TRUE; dctx->dumpbad = ISC_TRUE; dctx->dumpfail = ISC_TRUE; dctx->dumpzones = ISC_FALSE; dctx->fp = NULL; ISC_LIST_INIT(dctx->viewlist); dctx->view = NULL; dctx->zone = NULL; dctx->cache = NULL; dctx->mdctx = NULL; dctx->db = NULL; dctx->cache = NULL; dctx->task = NULL; dctx->version = NULL; isc_task_attach(server->task, &dctx->task); CHECKMF(isc_stdio_open(server->dumpfile, "w", &dctx->fp), "could not open dump file", server->dumpfile); ptr = next_token(lex, NULL); sep = (ptr == NULL) ? "" : ": "; isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_INFO, "dumpdb started%s%s", sep, (ptr != NULL) ? ptr : ""); if (ptr != NULL && strcmp(ptr, "-all") == 0) { /* also dump zones */ dctx->dumpzones = ISC_TRUE; ptr = next_token(lex, NULL); } else if (ptr != NULL && strcmp(ptr, "-cache") == 0) { /* this is the default */ ptr = next_token(lex, NULL); } else if (ptr != NULL && strcmp(ptr, "-zones") == 0) { /* only dump zones, suppress caches */ dctx->dumpadb = ISC_FALSE; dctx->dumpbad = ISC_FALSE; dctx->dumpcache = ISC_FALSE; dctx->dumpfail = ISC_FALSE; dctx->dumpzones = ISC_TRUE; ptr = next_token(lex, NULL); } else if (ptr != NULL && strcmp(ptr, "-adb") == 0) { /* only dump adb, suppress other caches */ dctx->dumpbad = ISC_FALSE; dctx->dumpcache = ISC_FALSE; dctx->dumpfail = ISC_FALSE; ptr = next_token(lex, NULL); } else if (ptr != NULL && strcmp(ptr, "-bad") == 0) { /* only dump badcache, suppress other caches */ dctx->dumpadb = ISC_FALSE; dctx->dumpcache = ISC_FALSE; dctx->dumpfail = ISC_FALSE; ptr = next_token(lex, NULL); } else if (ptr != NULL && strcmp(ptr, "-fail") == 0) { /* only dump servfail cache, suppress other caches */ dctx->dumpadb = ISC_FALSE; dctx->dumpbad = ISC_FALSE; dctx->dumpcache = ISC_FALSE; ptr = next_token(lex, NULL); } nextview: found = ISC_FALSE; for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; view = ISC_LIST_NEXT(view, link)) { if (ptr != NULL && strcmp(view->name, ptr) != 0) continue; found = ISC_TRUE; CHECK(add_view_tolist(dctx, view)); } if (ptr != NULL) { if (!found) { putstr(text, "view '"); putstr(text, ptr); putstr(text, "' not found"); putnull(text); result = ISC_R_NOTFOUND; dumpdone(dctx, result); return (result); } ptr = next_token(lex, NULL); if (ptr != NULL) goto nextview; } dumpdone(dctx, ISC_R_SUCCESS); return (ISC_R_SUCCESS); cleanup: if (dctx != NULL) dumpcontext_destroy(dctx); return (result); } isc_result_t ns_server_dumpsecroots(ns_server_t *server, isc_lex_t *lex, isc_buffer_t **text) { dns_view_t *view; dns_keytable_t *secroots = NULL; dns_ntatable_t *ntatable = NULL; isc_result_t result; char *ptr; FILE *fp = NULL; isc_time_t now; char tbuf[64]; /* Skip the command name. */ ptr = next_token(lex, text); if (ptr == NULL) return (ISC_R_UNEXPECTEDEND); /* "-" here means print the output instead of dumping to file */ ptr = next_token(lex, text); if (ptr != NULL && strcmp(ptr, "-") == 0) ptr = next_token(lex, text); else { result = isc_stdio_open(server->secrootsfile, "w", &fp); if (result != ISC_R_SUCCESS) { (void) putstr(text, "could not open "); (void) putstr(text, server->secrootsfile); CHECKMF(result, "could not open secroots dump file", server->secrootsfile); } } TIME_NOW(&now); isc_time_formattimestamp(&now, tbuf, sizeof(tbuf)); CHECK(putstr(text, "secure roots as of ")); CHECK(putstr(text, tbuf)); CHECK(putstr(text, ":\n")); do { for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; view = ISC_LIST_NEXT(view, link)) { if (ptr != NULL && strcmp(view->name, ptr) != 0) continue; if (secroots != NULL) dns_keytable_detach(&secroots); result = dns_view_getsecroots(view, &secroots); if (result == ISC_R_NOTFOUND) { result = ISC_R_SUCCESS; continue; } CHECK(putstr(text, "\n Start view ")); CHECK(putstr(text, view->name)); CHECK(putstr(text, "\n Secure roots:\n\n")); CHECK(dns_keytable_totext(secroots, text)); if (ntatable != NULL) dns_ntatable_detach(&ntatable); result = dns_view_getntatable(view, &ntatable); if (result == ISC_R_NOTFOUND) { result = ISC_R_SUCCESS; continue; } CHECK(putstr(text, "\n Negative trust anchors:\n\n")); CHECK(dns_ntatable_totext(ntatable, text)); } if (ptr != NULL) ptr = next_token(lex, text); } while (ptr != NULL); cleanup: if (isc_buffer_usedlength(*text) > 0) { if (fp != NULL) (void)putstr(text, "\n"); else (void)putnull(text); } if (secroots != NULL) dns_keytable_detach(&secroots); if (ntatable != NULL) dns_ntatable_detach(&ntatable); if (fp != NULL) { fprintf(fp, "%.*s", (int) isc_buffer_usedlength(*text), (char *) isc_buffer_base(*text)); isc_buffer_clear(*text); (void)isc_stdio_close(fp); } if (result == ISC_R_SUCCESS) isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_INFO, "dumpsecroots complete"); else isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, "dumpsecroots failed: %s", dns_result_totext(result)); return (result); } isc_result_t ns_server_dumprecursing(ns_server_t *server) { FILE *fp = NULL; dns_view_t *view; isc_result_t result; CHECKMF(isc_stdio_open(server->recfile, "w", &fp), "could not open dump file", server->recfile); fprintf(fp, ";\n; Recursing Queries\n;\n"); ns_interfacemgr_dumprecursing(fp, server->interfacemgr); for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; view = ISC_LIST_NEXT(view, link)) { fprintf(fp, ";\n; Active fetch domains [view: %s]\n;\n", view->name); dns_resolver_dumpfetches(view->resolver, isc_statsformat_file, fp); } fprintf(fp, "; Dump complete\n"); cleanup: if (fp != NULL) result = isc_stdio_close(fp); if (result == ISC_R_SUCCESS) isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_INFO, "dumprecursing complete"); else isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, "dumprecursing failed: %s", dns_result_totext(result)); return (result); } isc_result_t ns_server_setdebuglevel(ns_server_t *server, isc_lex_t *lex) { char *ptr; char *endp; long newlevel; UNUSED(server); /* Skip the command name. */ ptr = next_token(lex, NULL); if (ptr == NULL) return (ISC_R_UNEXPECTEDEND); /* Look for the new level name. */ ptr = next_token(lex, NULL); if (ptr == NULL) { if (ns_g_debuglevel < 99) ns_g_debuglevel++; } else { newlevel = strtol(ptr, &endp, 10); if (*endp != '\0' || newlevel < 0 || newlevel > 99) return (ISC_R_RANGE); ns_g_debuglevel = (unsigned int)newlevel; } isc_log_setdebuglevel(ns_g_lctx, ns_g_debuglevel); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_INFO, "debug level is now %d", ns_g_debuglevel); return (ISC_R_SUCCESS); } isc_result_t ns_server_validation(ns_server_t *server, isc_lex_t *lex, isc_buffer_t **text) { char *ptr; dns_view_t *view; isc_boolean_t changed = ISC_FALSE; isc_result_t result; isc_boolean_t enable = ISC_TRUE, set = ISC_TRUE, first = ISC_TRUE; /* Skip the command name. */ ptr = next_token(lex, text); if (ptr == NULL) return (ISC_R_UNEXPECTEDEND); /* Find out what we are to do. */ ptr = next_token(lex, text); if (ptr == NULL) return (ISC_R_UNEXPECTEDEND); if (!strcasecmp(ptr, "on") || !strcasecmp(ptr, "yes") || !strcasecmp(ptr, "enable") || !strcasecmp(ptr, "true")) { enable = ISC_TRUE; } else if (!strcasecmp(ptr, "off") || !strcasecmp(ptr, "no") || !strcasecmp(ptr, "disable") || !strcasecmp(ptr, "false")) { enable = ISC_FALSE; } else if (!strcasecmp(ptr, "check") || !strcasecmp(ptr, "status")) { set = ISC_FALSE; } else { return (DNS_R_SYNTAX); } /* Look for the view name. */ ptr = next_token(lex, text); result = isc_task_beginexclusive(server->task); RUNTIME_CHECK(result == ISC_R_SUCCESS); for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; view = ISC_LIST_NEXT(view, link)) { if (ptr != NULL && strcasecmp(ptr, view->name) != 0) continue; CHECK(dns_view_flushcache(view)); if (set) { view->enablevalidation = enable; changed = ISC_TRUE; } else { if (!first) CHECK(putstr(text, "\n")); CHECK(putstr(text, "DNSSEC validation is ")); CHECK(putstr(text, view->enablevalidation ? "enabled" : "disabled")); CHECK(putstr(text, " (view ")); CHECK(putstr(text, view->name)); CHECK(putstr(text, ")")); CHECK(putnull(text)); first = ISC_FALSE; } } if (!set) result = ISC_R_SUCCESS; else if (changed) result = ISC_R_SUCCESS; else result = ISC_R_FAILURE; cleanup: isc_task_endexclusive(server->task); return (result); } isc_result_t ns_server_flushcache(ns_server_t *server, isc_lex_t *lex) { char *ptr; dns_view_t *view; isc_boolean_t flushed; isc_boolean_t found; isc_result_t result; ns_cache_t *nsc; /* Skip the command name. */ ptr = next_token(lex, NULL); if (ptr == NULL) return (ISC_R_UNEXPECTEDEND); /* Look for the view name. */ ptr = next_token(lex, NULL); result = isc_task_beginexclusive(server->task); RUNTIME_CHECK(result == ISC_R_SUCCESS); flushed = ISC_TRUE; found = ISC_FALSE; /* * Flushing a cache is tricky when caches are shared by multiple views. * We first identify which caches should be flushed in the local cache * list, flush these caches, and then update other views that refer to * the flushed cache DB. */ if (ptr != NULL) { /* * Mark caches that need to be flushed. This is an O(#view^2) * operation in the very worst case, but should be normally * much more lightweight because only a few (most typically just * one) views will match. */ for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; view = ISC_LIST_NEXT(view, link)) { if (strcasecmp(ptr, view->name) != 0) continue; found = ISC_TRUE; for (nsc = ISC_LIST_HEAD(server->cachelist); nsc != NULL; nsc = ISC_LIST_NEXT(nsc, link)) { if (nsc->cache == view->cache) break; } INSIST(nsc != NULL); nsc->needflush = ISC_TRUE; } } else found = ISC_TRUE; /* Perform flush */ for (nsc = ISC_LIST_HEAD(server->cachelist); nsc != NULL; nsc = ISC_LIST_NEXT(nsc, link)) { if (ptr != NULL && !nsc->needflush) continue; nsc->needflush = ISC_TRUE; result = dns_view_flushcache2(nsc->primaryview, ISC_FALSE); if (result != ISC_R_SUCCESS) { flushed = ISC_FALSE; isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, "flushing cache in view '%s' failed: %s", nsc->primaryview->name, isc_result_totext(result)); } } /* * Fix up views that share a flushed cache: let the views update the * cache DB they're referring to. This could also be an expensive * operation, but should typically be marginal: the inner loop is only * necessary for views that share a cache, and if there are many such * views the number of shared cache should normally be small. * A worst case is that we have n views and n/2 caches, each shared by * two views. Then this will be a O(n^2/4) operation. */ for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; view = ISC_LIST_NEXT(view, link)) { if (!dns_view_iscacheshared(view)) continue; for (nsc = ISC_LIST_HEAD(server->cachelist); nsc != NULL; nsc = ISC_LIST_NEXT(nsc, link)) { if (!nsc->needflush || nsc->cache != view->cache) continue; result = dns_view_flushcache2(view, ISC_TRUE); if (result != ISC_R_SUCCESS) { flushed = ISC_FALSE; isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, "fixing cache in view '%s' " "failed: %s", view->name, isc_result_totext(result)); } } } /* Cleanup the cache list. */ for (nsc = ISC_LIST_HEAD(server->cachelist); nsc != NULL; nsc = ISC_LIST_NEXT(nsc, link)) { nsc->needflush = ISC_FALSE; } if (flushed && found) { if (ptr != NULL) isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_INFO, "flushing cache in view '%s' succeeded", ptr); else isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_INFO, "flushing caches in all views succeeded"); result = ISC_R_SUCCESS; } else { if (!found) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, "flushing cache in view '%s' failed: " "view not found", ptr); result = ISC_R_NOTFOUND; } else result = ISC_R_FAILURE; } isc_task_endexclusive(server->task); return (result); } isc_result_t ns_server_flushnode(ns_server_t *server, isc_lex_t *lex, isc_boolean_t tree) { char *ptr, *viewname; char target[DNS_NAME_FORMATSIZE]; dns_view_t *view; isc_boolean_t flushed; isc_boolean_t found; isc_result_t result; isc_buffer_t b; dns_fixedname_t fixed; dns_name_t *name; /* Skip the command name. */ ptr = next_token(lex, NULL); if (ptr == NULL) return (ISC_R_UNEXPECTEDEND); /* Find the domain name to flush. */ ptr = next_token(lex, NULL); if (ptr == NULL) return (ISC_R_UNEXPECTEDEND); strlcpy(target, ptr, DNS_NAME_FORMATSIZE); isc_buffer_constinit(&b, target, strlen(target)); isc_buffer_add(&b, strlen(target)); dns_fixedname_init(&fixed); name = dns_fixedname_name(&fixed); result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL); if (result != ISC_R_SUCCESS) return (result); /* Look for the view name. */ viewname = next_token(lex, NULL); result = isc_task_beginexclusive(server->task); RUNTIME_CHECK(result == ISC_R_SUCCESS); flushed = ISC_TRUE; found = ISC_FALSE; for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; view = ISC_LIST_NEXT(view, link)) { if (viewname != NULL && strcasecmp(viewname, view->name) != 0) continue; found = ISC_TRUE; /* * It's a little inefficient to try flushing name for all views * if some of the views share a single cache. But since the * operation is lightweight we prefer simplicity here. */ result = dns_view_flushnode(view, name, tree); if (result != ISC_R_SUCCESS) { flushed = ISC_FALSE; isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, "flushing %s '%s' in cache view '%s' " "failed: %s", tree ? "tree" : "name", target, view->name, isc_result_totext(result)); } } if (flushed && found) { if (viewname != NULL) isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_INFO, "flushing %s '%s' in cache view '%s' " "succeeded", tree ? "tree" : "name", target, viewname); else isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_INFO, "flushing %s '%s' in all cache views " "succeeded", tree ? "tree" : "name", target); result = ISC_R_SUCCESS; } else { if (!found) isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, "flushing %s '%s' in cache view '%s' " "failed: view not found", tree ? "tree" : "name", target, viewname); result = ISC_R_FAILURE; } isc_task_endexclusive(server->task); return (result); } isc_result_t ns_server_status(ns_server_t *server, isc_buffer_t **text) { isc_result_t result; unsigned int zonecount, xferrunning, xferdeferred, soaqueries; unsigned int automatic; const char *ob = "", *cb = "", *alt = ""; char boottime[ISC_FORMATHTTPTIMESTAMP_SIZE]; char configtime[ISC_FORMATHTTPTIMESTAMP_SIZE]; char line[1024], hostname[256]; if (ns_g_server->version_set) { ob = " ("; cb = ")"; if (ns_g_server->version == NULL) alt = "version.bind/txt/ch disabled"; else alt = ns_g_server->version; } zonecount = dns_zonemgr_getcount(server->zonemgr, DNS_ZONESTATE_ANY); xferrunning = dns_zonemgr_getcount(server->zonemgr, DNS_ZONESTATE_XFERRUNNING); xferdeferred = dns_zonemgr_getcount(server->zonemgr, DNS_ZONESTATE_XFERDEFERRED); soaqueries = dns_zonemgr_getcount(server->zonemgr, DNS_ZONESTATE_SOAQUERY); automatic = dns_zonemgr_getcount(server->zonemgr, DNS_ZONESTATE_AUTOMATIC); isc_time_formathttptimestamp(&ns_g_boottime, boottime, sizeof(boottime)); isc_time_formathttptimestamp(&ns_g_configtime, configtime, sizeof(configtime)); snprintf(line, sizeof(line), "version: %s %s%s%s %s%s%s\n", ns_g_product, ns_g_version, (*ns_g_description != '\0') ? " " : "", ns_g_description, ns_g_srcid, ob, alt, cb); CHECK(putstr(text, line)); result = ns_os_gethostname(hostname, sizeof(hostname)); if (result != ISC_R_SUCCESS) strlcpy(hostname, "localhost", sizeof(hostname)); snprintf(line, sizeof(line), "running on %s: %s\n", hostname, ns_os_uname()); CHECK(putstr(text, line)); snprintf(line, sizeof(line), "boot time: %s\n", boottime); CHECK(putstr(text, line)); snprintf(line, sizeof(line), "last configured: %s\n", configtime); CHECK(putstr(text, line)); if (ns_g_chrootdir != NULL) { snprintf(line, sizeof(line), "configuration file: %s (%s%s)\n", ns_g_conffile, ns_g_chrootdir, ns_g_conffile); } else { snprintf(line, sizeof(line), "configuration file: %s\n", ns_g_conffile); } CHECK(putstr(text, line)); #ifdef ISC_PLATFORM_USETHREADS snprintf(line, sizeof(line), "CPUs found: %u\n", ns_g_cpus_detected); CHECK(putstr(text, line)); snprintf(line, sizeof(line), "worker threads: %u\n", ns_g_cpus); CHECK(putstr(text, line)); snprintf(line, sizeof(line), "UDP listeners per interface: %u\n", ns_g_udpdisp); CHECK(putstr(text, line)); #else snprintf(line, sizeof(line), "CPUs found: N/A (threads disabled)\n"); CHECK(putstr(text, line)); #endif snprintf(line, sizeof(line), "number of zones: %u (%u automatic)\n", zonecount, automatic); CHECK(putstr(text, line)); snprintf(line, sizeof(line), "debug level: %d\n", ns_g_debuglevel); CHECK(putstr(text, line)); snprintf(line, sizeof(line), "xfers running: %u\n", xferrunning); CHECK(putstr(text, line)); snprintf(line, sizeof(line), "xfers deferred: %u\n", xferdeferred); CHECK(putstr(text, line)); snprintf(line, sizeof(line), "soa queries in progress: %u\n", soaqueries); CHECK(putstr(text, line)); snprintf(line, sizeof(line), "query logging is %s\n", server->log_queries ? "ON" : "OFF"); CHECK(putstr(text, line)); snprintf(line, sizeof(line), "recursive clients: %d/%d/%d\n", server->recursionquota.used, server->recursionquota.soft, server->recursionquota.max); CHECK(putstr(text, line)); snprintf(line, sizeof(line), "tcp clients: %d/%d\n", server->tcpquota.used, server->tcpquota.max); CHECK(putstr(text, line)); CHECK(putstr(text, "server is up and running")); CHECK(putnull(text)); return (ISC_R_SUCCESS); cleanup: return (result); } isc_result_t ns_server_testgen(isc_lex_t *lex, isc_buffer_t **text) { isc_result_t result; char *ptr; unsigned long count; unsigned long i; const unsigned char chars[] = "abcdefghijklmnopqrstuvwxyz0123456789"; /* Skip the command name. */ ptr = next_token(lex, text); if (ptr == NULL) return (ISC_R_UNEXPECTEDEND); ptr = next_token(lex, text); if (ptr == NULL) count = 26; else count = strtoul(ptr, NULL, 10); CHECK(isc_buffer_reserve(text, count)); for (i = 0; i < count; i++) CHECK(putuint8(text, chars[i % (sizeof(chars) - 1)])); CHECK(putnull(text)); cleanup: return (result); } static isc_result_t delete_keynames(dns_tsig_keyring_t *ring, char *target, unsigned int *foundkeys) { char namestr[DNS_NAME_FORMATSIZE]; isc_result_t result; dns_rbtnodechain_t chain; dns_name_t foundname; dns_fixedname_t fixedorigin; dns_name_t *origin; dns_rbtnode_t *node; dns_tsigkey_t *tkey; dns_name_init(&foundname, NULL); dns_fixedname_init(&fixedorigin); origin = dns_fixedname_name(&fixedorigin); again: dns_rbtnodechain_init(&chain, ring->mctx); result = dns_rbtnodechain_first(&chain, ring->keys, &foundname, origin); if (result == ISC_R_NOTFOUND) { dns_rbtnodechain_invalidate(&chain); return (ISC_R_SUCCESS); } if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) { dns_rbtnodechain_invalidate(&chain); return (result); } for (;;) { node = NULL; dns_rbtnodechain_current(&chain, &foundname, origin, &node); tkey = node->data; if (tkey != NULL) { if (!tkey->generated) goto nextkey; dns_name_format(&tkey->name, namestr, sizeof(namestr)); if (strcmp(namestr, target) == 0) { (*foundkeys)++; dns_rbtnodechain_invalidate(&chain); (void)dns_rbt_deletename(ring->keys, &tkey->name, ISC_FALSE); goto again; } } nextkey: result = dns_rbtnodechain_next(&chain, &foundname, origin); if (result == ISC_R_NOMORE) break; if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) { dns_rbtnodechain_invalidate(&chain); return (result); } } return (ISC_R_SUCCESS); } isc_result_t ns_server_tsigdelete(ns_server_t *server, isc_lex_t *lex, isc_buffer_t **text) { isc_result_t result; dns_view_t *view; unsigned int foundkeys = 0; char *ptr, *viewname; char target[DNS_NAME_FORMATSIZE]; char fbuf[16]; (void)next_token(lex, text); /* skip command name */ ptr = next_token(lex, text); if (ptr == NULL) return (ISC_R_UNEXPECTEDEND); strlcpy(target, ptr, DNS_NAME_FORMATSIZE); viewname = next_token(lex, text); result = isc_task_beginexclusive(server->task); RUNTIME_CHECK(result == ISC_R_SUCCESS); for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; view = ISC_LIST_NEXT(view, link)) { if (viewname == NULL || strcmp(view->name, viewname) == 0) { RWLOCK(&view->dynamickeys->lock, isc_rwlocktype_write); result = delete_keynames(view->dynamickeys, target, &foundkeys); RWUNLOCK(&view->dynamickeys->lock, isc_rwlocktype_write); if (result != ISC_R_SUCCESS) { isc_task_endexclusive(server->task); return (result); } } } isc_task_endexclusive(server->task); snprintf(fbuf, sizeof(fbuf), "%d", foundkeys); CHECK(putstr(text, fbuf)); CHECK(putstr(text, " tsig keys deleted.")); CHECK(putnull(text)); cleanup: return (result); } static isc_result_t list_keynames(dns_view_t *view, dns_tsig_keyring_t *ring, isc_buffer_t **text, unsigned int *foundkeys) { char namestr[DNS_NAME_FORMATSIZE]; char creatorstr[DNS_NAME_FORMATSIZE]; isc_result_t result; dns_rbtnodechain_t chain; dns_name_t foundname; dns_fixedname_t fixedorigin; dns_name_t *origin; dns_rbtnode_t *node; dns_tsigkey_t *tkey; const char *viewname; if (view != NULL) viewname = view->name; else viewname = "(global)"; dns_name_init(&foundname, NULL); dns_fixedname_init(&fixedorigin); origin = dns_fixedname_name(&fixedorigin); dns_rbtnodechain_init(&chain, ring->mctx); result = dns_rbtnodechain_first(&chain, ring->keys, &foundname, origin); if (result == ISC_R_NOTFOUND) { dns_rbtnodechain_invalidate(&chain); return (ISC_R_SUCCESS); } if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) { dns_rbtnodechain_invalidate(&chain); return (result); } for (;;) { node = NULL; dns_rbtnodechain_current(&chain, &foundname, origin, &node); tkey = node->data; if (tkey != NULL) { dns_name_format(&tkey->name, namestr, sizeof(namestr)); if (tkey->generated) { dns_name_format(tkey->creator, creatorstr, sizeof(creatorstr)); if (*foundkeys != 0) CHECK(putstr(text, "\n")); CHECK(putstr(text, "view \"")); CHECK(putstr(text, viewname)); CHECK(putstr(text, "\"; type \"dynamic\"; key \"")); CHECK(putstr(text, namestr)); CHECK(putstr(text, "\"; creator \"")); CHECK(putstr(text, creatorstr)); CHECK(putstr(text, "\";")); } else { if (*foundkeys != 0) CHECK(putstr(text, "\n")); CHECK(putstr(text, "view \"")); CHECK(putstr(text, viewname)); CHECK(putstr(text, "\"; type \"static\"; key \"")); CHECK(putstr(text, namestr)); CHECK(putstr(text, "\";")); } (*foundkeys)++; } result = dns_rbtnodechain_next(&chain, &foundname, origin); if (result == ISC_R_NOMORE || result == DNS_R_NEWORIGIN) break; } return (ISC_R_SUCCESS); cleanup: dns_rbtnodechain_invalidate(&chain); return (result); } isc_result_t ns_server_tsiglist(ns_server_t *server, isc_buffer_t **text) { isc_result_t result; dns_view_t *view; unsigned int foundkeys = 0; result = isc_task_beginexclusive(server->task); RUNTIME_CHECK(result == ISC_R_SUCCESS); for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; view = ISC_LIST_NEXT(view, link)) { RWLOCK(&view->statickeys->lock, isc_rwlocktype_read); result = list_keynames(view, view->statickeys, text, &foundkeys); RWUNLOCK(&view->statickeys->lock, isc_rwlocktype_read); if (result != ISC_R_SUCCESS) { isc_task_endexclusive(server->task); return (result); } RWLOCK(&view->dynamickeys->lock, isc_rwlocktype_read); result = list_keynames(view, view->dynamickeys, text, &foundkeys); RWUNLOCK(&view->dynamickeys->lock, isc_rwlocktype_read); if (result != ISC_R_SUCCESS) { isc_task_endexclusive(server->task); return (result); } } isc_task_endexclusive(server->task); if (foundkeys == 0) CHECK(putstr(text, "no tsig keys found.")); if (isc_buffer_usedlength(*text) > 0) CHECK(putnull(text)); cleanup: return (result); } /* * Act on a "sign" or "loadkeys" command from the command channel. */ isc_result_t ns_server_rekey(ns_server_t *server, isc_lex_t *lex, isc_buffer_t **text) { isc_result_t result; dns_zone_t *zone = NULL; dns_zonetype_t type; isc_uint16_t keyopts; isc_boolean_t fullsign = ISC_FALSE; char *ptr; ptr = next_token(lex, text); if (ptr == NULL) return (ISC_R_UNEXPECTEDEND); if (strcasecmp(ptr, NS_COMMAND_SIGN) == 0) fullsign = ISC_TRUE; result = zone_from_args(server, lex, NULL, &zone, NULL, text, ISC_FALSE); if (result != ISC_R_SUCCESS) return (result); if (zone == NULL) return (ISC_R_UNEXPECTEDEND); /* XXX: or do all zones? */ type = dns_zone_gettype(zone); if (type != dns_zone_master) { dns_zone_detach(&zone); return (DNS_R_NOTMASTER); } keyopts = dns_zone_getkeyopts(zone); /* "rndc loadkeys" requires "auto-dnssec maintain". */ if ((keyopts & DNS_ZONEKEY_ALLOW) == 0) result = ISC_R_NOPERM; else if ((keyopts & DNS_ZONEKEY_MAINTAIN) == 0 && !fullsign) result = ISC_R_NOPERM; else dns_zone_rekey(zone, fullsign); dns_zone_detach(&zone); return (result); } /* * Act on a "sync" command from the command channel. */ static isc_result_t synczone(dns_zone_t *zone, void *uap) { isc_boolean_t cleanup = *(isc_boolean_t *)uap; isc_result_t result; dns_zone_t *raw = NULL; char *journal; dns_zone_getraw(zone, &raw); if (raw != NULL) { synczone(raw, uap); dns_zone_detach(&raw); } result = dns_zone_flush(zone); if (result != ISC_R_SUCCESS) cleanup = ISC_FALSE; if (cleanup) { journal = dns_zone_getjournal(zone); if (journal != NULL) (void)isc_file_remove(journal); } return (result); } isc_result_t ns_server_sync(ns_server_t *server, isc_lex_t *lex, isc_buffer_t **text) { isc_result_t result, tresult; dns_view_t *view; dns_zone_t *zone = NULL; char classstr[DNS_RDATACLASS_FORMATSIZE]; char zonename[DNS_NAME_FORMATSIZE]; const char *vname, *sep, *arg; isc_boolean_t cleanup = ISC_FALSE; (void) next_token(lex, text); arg = next_token(lex, text); if (arg != NULL && (strcmp(arg, "-clean") == 0 || strcmp(arg, "-clear") == 0)) { cleanup = ISC_TRUE; arg = next_token(lex, text); } result = zone_from_args(server, lex, arg, &zone, NULL, text, ISC_FALSE); if (result != ISC_R_SUCCESS) return (result); if (zone == NULL) { result = isc_task_beginexclusive(server->task); RUNTIME_CHECK(result == ISC_R_SUCCESS); tresult = ISC_R_SUCCESS; for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; view = ISC_LIST_NEXT(view, link)) { result = dns_zt_apply(view->zonetable, ISC_FALSE, synczone, &cleanup); if (result != ISC_R_SUCCESS && tresult == ISC_R_SUCCESS) tresult = result; } isc_task_endexclusive(server->task); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_INFO, "dumping all zones%s: %s", cleanup ? ", removing journal files" : "", isc_result_totext(result)); return (tresult); } result = isc_task_beginexclusive(server->task); RUNTIME_CHECK(result == ISC_R_SUCCESS); result = synczone(zone, &cleanup); isc_task_endexclusive(server->task); view = dns_zone_getview(zone); if (strcmp(view->name, "_default") == 0 || strcmp(view->name, "_bind") == 0) { vname = ""; sep = ""; } else { vname = view->name; sep = " "; } dns_rdataclass_format(dns_zone_getclass(zone), classstr, sizeof(classstr)); dns_name_format(dns_zone_getorigin(zone), zonename, sizeof(zonename)); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_INFO, "sync: dumping zone '%s/%s'%s%s%s: %s", zonename, classstr, sep, vname, cleanup ? ", removing journal file" : "", isc_result_totext(result)); dns_zone_detach(&zone); return (result); } /* * Act on a "freeze" or "thaw" command from the command channel. */ isc_result_t ns_server_freeze(ns_server_t *server, isc_boolean_t freeze, isc_lex_t *lex, isc_buffer_t **text) { isc_result_t result, tresult; dns_zone_t *zone = NULL, *raw = NULL; dns_zonetype_t type; char classstr[DNS_RDATACLASS_FORMATSIZE]; char zonename[DNS_NAME_FORMATSIZE]; dns_view_t *view; const char *vname, *sep; isc_boolean_t frozen; const char *msg = NULL; result = zone_from_args(server, lex, NULL, &zone, NULL, text, ISC_TRUE); if (result != ISC_R_SUCCESS) return (result); if (zone == NULL) { result = isc_task_beginexclusive(server->task); RUNTIME_CHECK(result == ISC_R_SUCCESS); tresult = ISC_R_SUCCESS; for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; view = ISC_LIST_NEXT(view, link)) { result = dns_view_freezezones(view, freeze); if (result != ISC_R_SUCCESS && tresult == ISC_R_SUCCESS) tresult = result; } isc_task_endexclusive(server->task); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_INFO, "%s all zones: %s", freeze ? "freezing" : "thawing", isc_result_totext(tresult)); return (tresult); } dns_zone_getraw(zone, &raw); if (raw != NULL) { dns_zone_detach(&zone); dns_zone_attach(raw, &zone); dns_zone_detach(&raw); } type = dns_zone_gettype(zone); if (type != dns_zone_master) { dns_zone_detach(&zone); return (DNS_R_NOTMASTER); } if (freeze && !dns_zone_isdynamic(zone, ISC_TRUE)) { dns_zone_detach(&zone); return (DNS_R_NOTDYNAMIC); } result = isc_task_beginexclusive(server->task); RUNTIME_CHECK(result == ISC_R_SUCCESS); frozen = dns_zone_getupdatedisabled(zone); if (freeze) { if (frozen) { msg = "WARNING: The zone was already frozen.\n" "Someone else may be editing it or " "it may still be re-loading."; result = DNS_R_FROZEN; } if (result == ISC_R_SUCCESS) { result = dns_zone_flush(zone); if (result != ISC_R_SUCCESS) msg = "Flushing the zone updates to " "disk failed."; } if (result == ISC_R_SUCCESS) dns_zone_setupdatedisabled(zone, freeze); } else { if (frozen) { result = dns_zone_loadandthaw(zone); switch (result) { case ISC_R_SUCCESS: case DNS_R_UPTODATE: msg = "The zone reload and thaw was " "successful."; result = ISC_R_SUCCESS; break; case DNS_R_CONTINUE: msg = "A zone reload and thaw was started.\n" "Check the logs to see the result."; result = ISC_R_SUCCESS; break; } } } isc_task_endexclusive(server->task); if (msg != NULL) { (void) putstr(text, msg); (void) putnull(text); } view = dns_zone_getview(zone); if (strcmp(view->name, "_default") == 0 || strcmp(view->name, "_bind") == 0) { vname = ""; sep = ""; } else { vname = view->name; sep = " "; } dns_rdataclass_format(dns_zone_getclass(zone), classstr, sizeof(classstr)); dns_name_format(dns_zone_getorigin(zone), zonename, sizeof(zonename)); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_INFO, "%s zone '%s/%s'%s%s: %s", freeze ? "freezing" : "thawing", zonename, classstr, sep, vname, isc_result_totext(result)); dns_zone_detach(&zone); return (result); } #ifdef HAVE_LIBSCF /* * This function adds a message for rndc to echo if named * is managed by smf and is also running chroot. */ isc_result_t ns_smf_add_message(isc_buffer_t **text) { return (putstr(text, "use svcadm(1M) to manage named")); } #endif /* HAVE_LIBSCF */ #ifndef HAVE_LMDB /* * Emit a comment at the top of the nzf file containing the viewname * Expects the fp to already be open for writing */ #define HEADER1 "# New zone file for view: " #define HEADER2 "\n# This file contains configuration for zones added by\n" \ "# the 'rndc addzone' command. DO NOT EDIT BY HAND.\n" static isc_result_t add_comment(FILE *fp, const char *viewname) { isc_result_t result; CHECK(isc_stdio_write(HEADER1, sizeof(HEADER1) - 1, 1, fp, NULL)); CHECK(isc_stdio_write(viewname, strlen(viewname), 1, fp, NULL)); CHECK(isc_stdio_write(HEADER2, sizeof(HEADER2) - 1, 1, fp, NULL)); cleanup: return (result); } static void dumpzone(void *arg, const char *buf, int len) { FILE *fp = arg; (void) isc_stdio_write(buf, len, 1, fp, NULL); } static isc_result_t nzf_append(dns_view_t *view, const cfg_obj_t *zconfig) { isc_result_t result; off_t offset; FILE *fp = NULL; isc_boolean_t offsetok = ISC_FALSE; LOCK(&view->new_zone_lock); CHECK(isc_stdio_open(view->new_zone_file, "a", &fp)); CHECK(isc_stdio_seek(fp, 0, SEEK_END)); CHECK(isc_stdio_tell(fp, &offset)); offsetok = ISC_TRUE; if (offset == 0) CHECK(add_comment(fp, view->name)); CHECK(isc_stdio_write("zone ", 5, 1, fp, NULL)); cfg_printx(zconfig, CFG_PRINTER_ONELINE, dumpzone, fp); CHECK(isc_stdio_write(";\n", 2, 1, fp, NULL)); CHECK(isc_stdio_flush(fp)); result = isc_stdio_close(fp); fp = NULL; cleanup: if (fp != NULL) { (void)isc_stdio_close(fp); if (offsetok) { isc_result_t result2; result2 = isc_file_truncate(view->new_zone_file, offset); if (result2 != ISC_R_SUCCESS) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, "Error truncating NZF file '%s' " "during rollback from append: " "%s", view->new_zone_file, isc_result_totext(result2)); } } } UNLOCK(&view->new_zone_lock); return (result); } static isc_result_t nzf_writeconf(const cfg_obj_t *config, dns_view_t *view) { const cfg_obj_t *zl = NULL; cfg_list_t *list; const cfg_listelt_t *elt; FILE *fp = NULL; char tmp[1024]; isc_result_t result; result = isc_file_template("", "nzf-XXXXXXXX", tmp, sizeof(tmp)); if (result == ISC_R_SUCCESS) result = isc_file_openunique(tmp, &fp); if (result != ISC_R_SUCCESS) return (result); cfg_map_get(config, "zone", &zl); if (!cfg_obj_islist(zl)) CHECK(ISC_R_FAILURE); DE_CONST(&zl->value.list, list); CHECK(add_comment(fp, view->name)); /* force a comment */ for (elt = ISC_LIST_HEAD(*list); elt != NULL; elt = ISC_LIST_NEXT(elt, link)) { const cfg_obj_t *zconfig = cfg_listelt_value(elt); CHECK(isc_stdio_write("zone ", 5, 1, fp, NULL)); cfg_printx(zconfig, CFG_PRINTER_ONELINE, dumpzone, fp); CHECK(isc_stdio_write(";\n", 2, 1, fp, NULL)); } CHECK(isc_stdio_flush(fp)); result = isc_stdio_close(fp); fp = NULL; if (result != ISC_R_SUCCESS) goto cleanup; CHECK(isc_file_rename(tmp, view->new_zone_file)); return (result); cleanup: if (fp != NULL) (void)isc_stdio_close(fp); (void)isc_file_remove(tmp); return (result); } #else /* HAVE_LMDB */ static void nzd_setkey(MDB_val *key, dns_name_t *name, char *namebuf, size_t buflen) { dns_fixedname_t fixed; dns_fixedname_init(&fixed); dns_name_downcase(name, dns_fixedname_name(&fixed), NULL); dns_name_format(dns_fixedname_name(&fixed), namebuf, buflen); key->mv_data = namebuf; key->mv_size = strlen(namebuf); } static void dumpzone(void *arg, const char *buf, int len) { isc_buffer_t **text = arg; putmem(text, buf, len); } static isc_result_t nzd_save(MDB_txn **txnp, MDB_dbi dbi, dns_zone_t *zone, const cfg_obj_t *zconfig) { isc_result_t result; int status; dns_view_t *view; isc_boolean_t commit = ISC_FALSE; isc_buffer_t *text = NULL; char namebuf[1024]; MDB_val key, data; view = dns_zone_getview(zone); nzd_setkey(&key, dns_zone_getorigin(zone), namebuf, sizeof(namebuf)); LOCK(&view->new_zone_lock); if (zconfig == NULL) { /* We're deleting the zone from the database */ status = mdb_del(*txnp, dbi, &key, NULL); if (status != MDB_SUCCESS && status != MDB_NOTFOUND) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, "Error deleting zone %s " "from NZD database: %s", namebuf, mdb_strerror(status)); result = ISC_R_FAILURE; goto cleanup; } else if (status != MDB_NOTFOUND) { commit = ISC_TRUE; } } else { /* We're creating or overwriting the zone */ const cfg_obj_t *zoptions; result = isc_buffer_allocate(view->mctx, &text, 256); if (result != ISC_R_SUCCESS) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, "Unable to allocate buffer in " "nzd_save(): %s", isc_result_totext(result)); goto cleanup; } zoptions = cfg_tuple_get(zconfig, "options"); if (zoptions == NULL) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, "Unable to get options from config in " "nzd_save()"); result = ISC_R_FAILURE; goto cleanup; } cfg_printx(zoptions, CFG_PRINTER_ONELINE, dumpzone, &text); data.mv_data = isc_buffer_base(text); data.mv_size = isc_buffer_usedlength(text); status = mdb_put(*txnp, dbi, &key, &data, 0); if (status != MDB_SUCCESS) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, "Error inserting zone in " "NZD database: %s", mdb_strerror(status)); result = ISC_R_FAILURE; goto cleanup; } commit = ISC_TRUE; } result = ISC_R_SUCCESS; cleanup: if (!commit || result != ISC_R_SUCCESS) { (void) mdb_txn_abort(*txnp); } else { status = mdb_txn_commit(*txnp); if (status != MDB_SUCCESS) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, "Error committing " "NZD database: %s", mdb_strerror(status)); result = ISC_R_FAILURE; } } *txnp = NULL; UNLOCK(&view->new_zone_lock); if (text != NULL) { isc_buffer_free(&text); } return (result); } static isc_result_t nzd_writable(dns_view_t *view) { isc_result_t result = ISC_R_SUCCESS; int status; MDB_dbi dbi; MDB_txn *txn = NULL; REQUIRE(view != NULL); status = mdb_txn_begin((MDB_env *) view->new_zone_dbenv, 0, 0, &txn); if (status != MDB_SUCCESS) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_WARNING, "mdb_txn_begin: %s", mdb_strerror(status)); return (ISC_R_FAILURE); } status = mdb_dbi_open(txn, NULL, 0, &dbi); if (status != MDB_SUCCESS) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_WARNING, "mdb_dbi_open: %s", mdb_strerror(status)); result = ISC_R_FAILURE; } mdb_txn_abort(txn); return (result); } static isc_result_t nzd_open(dns_view_t *view, unsigned int flags, MDB_txn **txnp, MDB_dbi *dbi) { int status; MDB_txn *txn = NULL; REQUIRE(view != NULL); REQUIRE(txnp != NULL && *txnp == NULL); REQUIRE(dbi != NULL); status = mdb_txn_begin((MDB_env *) view->new_zone_dbenv, 0, flags, &txn); if (status != MDB_SUCCESS) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_WARNING, "mdb_txn_begin: %s", mdb_strerror(status)); goto cleanup; } status = mdb_dbi_open(txn, NULL, 0, dbi); if (status != MDB_SUCCESS) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_WARNING, "mdb_dbi_open: %s", mdb_strerror(status)); goto cleanup; } *txnp = txn; cleanup: if (status != MDB_SUCCESS) { if (txn != NULL) { mdb_txn_abort(txn); } return (ISC_R_FAILURE); } return (ISC_R_SUCCESS); } /* * nzd_env_close() and nzd_env_reopen are a kluge to address the * problem of an NZD file possibly being created before we drop * root privileges. */ static void nzd_env_close(dns_view_t *view) { const char *dbpath = NULL; char dbpath_copy[PATH_MAX]; char lockpath[PATH_MAX]; int status, ret; if (view->new_zone_dbenv == NULL) { return; } status = mdb_env_get_path(view->new_zone_dbenv, &dbpath); INSIST(status == MDB_SUCCESS); snprintf(lockpath, sizeof(lockpath), "%s-lock", dbpath); strlcpy(dbpath_copy, dbpath, sizeof(dbpath_copy)); mdb_env_close((MDB_env *) view->new_zone_dbenv); /* * Database files must be owned by the eventual user, not by root. */ ret = chown(dbpath_copy, ns_os_uid(), -1); UNUSED(ret); /* * Some platforms need the lockfile not to exist when we reopen the * environment. */ (void) isc_file_remove(lockpath); view->new_zone_dbenv = NULL; } static isc_result_t nzd_env_reopen(dns_view_t *view) { isc_result_t result; MDB_env *env = NULL; int status; if (view->new_zone_db == NULL) { return (ISC_R_SUCCESS); } nzd_env_close(view); status = mdb_env_create(&env); if (status != MDB_SUCCESS) { isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, ISC_LOGMODULE_OTHER, ISC_LOG_ERROR, "mdb_env_create failed: %s", mdb_strerror(status)); CHECK(ISC_R_FAILURE); } if (view->new_zone_mapsize != 0ULL) { status = mdb_env_set_mapsize(env, view->new_zone_mapsize); if (status != MDB_SUCCESS) { isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, ISC_LOGMODULE_OTHER, ISC_LOG_ERROR, "mdb_env_set_mapsize failed: %s", mdb_strerror(status)); CHECK(ISC_R_FAILURE); } } status = mdb_env_open(env, view->new_zone_db, DNS_LMDB_FLAGS, 0600); if (status != MDB_SUCCESS) { isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, ISC_LOGMODULE_OTHER, ISC_LOG_ERROR, "mdb_env_open of '%s' failed: %s", view->new_zone_db, mdb_strerror(status)); CHECK(ISC_R_FAILURE); } view->new_zone_dbenv = env; env = NULL; result = ISC_R_SUCCESS; cleanup: if (env != NULL) { mdb_env_close(env); } return (result); } static isc_result_t nzd_close(MDB_txn **txnp, isc_boolean_t commit) { isc_result_t result = ISC_R_SUCCESS; int status; REQUIRE(txnp != NULL); if (*txnp != NULL) { if (commit) { status = mdb_txn_commit(*txnp); if (status != MDB_SUCCESS) { result = ISC_R_FAILURE; } } else { mdb_txn_abort(*txnp); } *txnp = NULL; } return (result); } static isc_result_t nzd_count(dns_view_t *view, int *countp) { isc_result_t result; int status; MDB_txn *txn = NULL; MDB_dbi dbi; MDB_stat statbuf; REQUIRE(countp != NULL); result = nzd_open(view, MDB_RDONLY, &txn, &dbi); if (result != ISC_R_SUCCESS) { goto cleanup; } status = mdb_stat(txn, dbi, &statbuf); if (status != MDB_SUCCESS) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_WARNING, "mdb_stat: %s", mdb_strerror(status)); result = ISC_R_FAILURE; goto cleanup; } *countp = statbuf.ms_entries; cleanup: (void) nzd_close(&txn, ISC_FALSE); return (result); } static isc_result_t migrate_nzf(dns_view_t *view) { isc_result_t result; cfg_obj_t *nzf_config = NULL; int status, n; isc_buffer_t *text = NULL; isc_boolean_t commit = ISC_FALSE; const cfg_obj_t *zonelist; const cfg_listelt_t *element; char tempname[PATH_MAX]; MDB_txn *txn = NULL; MDB_dbi dbi; MDB_val key, data; /* * If NZF file doesn't exist, or NZD DB exists and already * has data, return without attempting migration. */ if (!isc_file_exists(view->new_zone_file)) { result = ISC_R_SUCCESS; goto cleanup; } result = nzd_count(view, &n); if (result == ISC_R_SUCCESS && n > 0) { result = ISC_R_SUCCESS; goto cleanup; } isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_INFO, "Migrating zones from NZF file '%s' to " "NZD database '%s'", view->new_zone_file, view->new_zone_db); /* * Instead of blindly copying lines, we parse the NZF file using * the configuration parser, because it validates it against the * config type, giving us a guarantee that valid configuration * will be written to DB. */ cfg_parser_reset(ns_g_addparser); result = cfg_parse_file(ns_g_addparser, view->new_zone_file, &cfg_type_addzoneconf, &nzf_config); if (result != ISC_R_SUCCESS) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, "Error parsing NZF file '%s': %s", view->new_zone_file, isc_result_totext(result)); goto cleanup; } zonelist = NULL; CHECK(cfg_map_get(nzf_config, "zone", &zonelist)); if (!cfg_obj_islist(zonelist)) { CHECK(ISC_R_FAILURE); } CHECK(nzd_open(view, 0, &txn, &dbi)); CHECK(isc_buffer_allocate(view->mctx, &text, 256)); for (element = cfg_list_first(zonelist); element != NULL; element = cfg_list_next(element)) { const cfg_obj_t *zconfig; const cfg_obj_t *zoptions; char zname[DNS_NAME_FORMATSIZE]; dns_fixedname_t fname; dns_name_t *name; const char *origin; isc_buffer_t b; zconfig = cfg_listelt_value(element); origin = cfg_obj_asstring(cfg_tuple_get(zconfig, "name")); if (origin == NULL) { result = ISC_R_FAILURE; goto cleanup; } /* Normalize zone name */ isc_buffer_constinit(&b, origin, strlen(origin)); isc_buffer_add(&b, strlen(origin)); dns_fixedname_init(&fname); name = dns_fixedname_name(&fname); CHECK(dns_name_fromtext(name, &b, dns_rootname, DNS_NAME_DOWNCASE, NULL)); dns_name_format(name, zname, sizeof(zname)); key.mv_data = zname; key.mv_size = strlen(zname); zoptions = cfg_tuple_get(zconfig, "options"); if (zoptions == NULL) { result = ISC_R_FAILURE; goto cleanup; } isc_buffer_clear(text); cfg_printx(zoptions, CFG_PRINTER_ONELINE, dumpzone, &text); data.mv_data = isc_buffer_base(text); data.mv_size = isc_buffer_usedlength(text); status = mdb_put(txn, dbi, &key, &data, MDB_NOOVERWRITE); if (status != MDB_SUCCESS) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, "Error inserting zone in " "NZD database: %s", mdb_strerror(status)); result = ISC_R_FAILURE; goto cleanup; } commit = ISC_TRUE; } result = ISC_R_SUCCESS; /* * Leaving the NZF file in place is harmless as we won't use it * if an NZD database is found for the view. But we rename NZF file * to a backup name here. */ strlcpy(tempname, view->new_zone_file, sizeof(tempname)); if (strlen(tempname) < sizeof(tempname) - 1) { strlcat(tempname, "~", sizeof(tempname)); isc_file_rename(view->new_zone_file, tempname); } cleanup: if (result != ISC_R_SUCCESS) { (void) nzd_close(&txn, ISC_FALSE); } else { result = nzd_close(&txn, commit); } if (text != NULL) { isc_buffer_free(&text); } if (nzf_config != NULL) { cfg_obj_destroy(ns_g_addparser, &nzf_config); } return (result); } #endif /* HAVE_LMDB */ static isc_result_t newzone_parse(ns_server_t *server, char *command, dns_view_t **viewp, cfg_obj_t **zoneconfp, const cfg_obj_t **zoneobjp, isc_buffer_t **text) { isc_result_t result; isc_buffer_t argbuf; cfg_obj_t *zoneconf = NULL; const cfg_obj_t *zlist = NULL; const cfg_obj_t *zoneobj = NULL; const cfg_obj_t *zoptions = NULL; const cfg_obj_t *obj = NULL; const char *viewname = NULL; dns_rdataclass_t rdclass; dns_view_t *view = NULL; const char *bn; REQUIRE(viewp != NULL && *viewp == NULL); REQUIRE(zoneobjp != NULL && *zoneobjp == NULL); REQUIRE(zoneconfp != NULL && *zoneconfp == NULL); /* Try to parse the argument string */ isc_buffer_init(&argbuf, command, (unsigned int) strlen(command)); isc_buffer_add(&argbuf, strlen(command)); if (strncasecmp(command, "add", 3) == 0) bn = "addzone"; else if (strncasecmp(command, "mod", 3) == 0) bn = "modzone"; else INSIST(0); /* * Convert the "addzone" or "modzone" to just "zone", for * the benefit of the parser */ isc_buffer_forward(&argbuf, 3); cfg_parser_reset(ns_g_addparser); CHECK(cfg_parse_buffer3(ns_g_addparser, &argbuf, bn, 0, &cfg_type_addzoneconf, &zoneconf)); CHECK(cfg_map_get(zoneconf, "zone", &zlist)); if (!cfg_obj_islist(zlist)) CHECK(ISC_R_FAILURE); /* For now we only support adding one zone at a time */ zoneobj = cfg_listelt_value(cfg_list_first(zlist)); /* Check the zone type for ones that are not supported by addzone. */ zoptions = cfg_tuple_get(zoneobj, "options"); obj = NULL; (void)cfg_map_get(zoptions, "type", &obj); if (obj == NULL) { (void) cfg_map_get(zoptions, "in-view", &obj); if (obj != NULL) { (void) putstr(text, "'in-view' zones not supported by "); (void) putstr(text, bn); } else (void) putstr(text, "zone type not specified"); CHECK(ISC_R_FAILURE); } if (strcasecmp(cfg_obj_asstring(obj), "hint") == 0 || strcasecmp(cfg_obj_asstring(obj), "forward") == 0 || strcasecmp(cfg_obj_asstring(obj), "redirect") == 0 || strcasecmp(cfg_obj_asstring(obj), "delegation-only") == 0) { (void) putstr(text, "'"); (void) putstr(text, cfg_obj_asstring(obj)); (void) putstr(text, "' zones not supported by "); (void) putstr(text, bn); CHECK(ISC_R_FAILURE); } /* Make sense of optional class argument */ obj = cfg_tuple_get(zoneobj, "class"); CHECK(ns_config_getclass(obj, dns_rdataclass_in, &rdclass)); /* Make sense of optional view argument */ obj = cfg_tuple_get(zoneobj, "view"); if (obj && cfg_obj_isstring(obj)) viewname = cfg_obj_asstring(obj); if (viewname == NULL || *viewname == '\0') viewname = "_default"; result = dns_viewlist_find(&server->viewlist, viewname, rdclass, &view); if (result == ISC_R_NOTFOUND) { (void) putstr(text, "no matching view found for '"); (void) putstr(text, viewname); (void) putstr(text, "'"); goto cleanup; } else if (result != ISC_R_SUCCESS) { goto cleanup; } *viewp = view; *zoneobjp = zoneobj; *zoneconfp = zoneconf; return (ISC_R_SUCCESS); cleanup: if (zoneconf != NULL) cfg_obj_destroy(ns_g_addparser, &zoneconf); if (view != NULL) dns_view_detach(&view); return (result); } static isc_result_t delete_zoneconf(dns_view_t *view, cfg_parser_t *pctx, const cfg_obj_t *config, const dns_name_t *zname, nzfwriter_t nzfwriter) { isc_result_t result = ISC_R_NOTFOUND; const cfg_listelt_t *elt = NULL; const cfg_obj_t *zl = NULL; cfg_list_t *list; dns_fixedname_t myfixed; dns_name_t *myname; REQUIRE(view != NULL); REQUIRE(pctx != NULL); REQUIRE(config != NULL); REQUIRE(zname != NULL); LOCK(&view->new_zone_lock); cfg_map_get(config, "zone", &zl); if (!cfg_obj_islist(zl)) CHECK(ISC_R_FAILURE); DE_CONST(&zl->value.list, list); dns_fixedname_init(&myfixed); myname = dns_fixedname_name(&myfixed); for (elt = ISC_LIST_HEAD(*list); elt != NULL; elt = ISC_LIST_NEXT(elt, link)) { const cfg_obj_t *zconf = cfg_listelt_value(elt); const char *zn; cfg_listelt_t *e; zn = cfg_obj_asstring(cfg_tuple_get(zconf, "name")); result = dns_name_fromstring(myname, zn, 0, NULL); if (result != ISC_R_SUCCESS || !dns_name_equal(zname, myname)) continue; DE_CONST(elt, e); ISC_LIST_UNLINK(*list, e, link); cfg_obj_destroy(pctx, &e->obj); isc_mem_put(pctx->mctx, e, sizeof(*e)); result = ISC_R_SUCCESS; break; } /* * Write config to NZF file if appropriate */ if (nzfwriter != NULL && view->new_zone_file != NULL) result = nzfwriter(config, view); cleanup: UNLOCK(&view->new_zone_lock); return (result); } static isc_result_t do_addzone(ns_server_t *server, ns_cfgctx_t *cfg, dns_view_t *view, dns_name_t *name, cfg_obj_t *zoneconf, const cfg_obj_t *zoneobj, isc_buffer_t **text) { isc_result_t result, tresult; dns_zone_t *zone = NULL; #ifndef HAVE_LMDB FILE *fp = NULL; isc_boolean_t cleanup_config = ISC_FALSE; #else /* HAVE_LMDB */ MDB_txn *txn = NULL; MDB_dbi dbi; UNUSED(zoneconf); #endif /* HAVE_LMDB */ /* Zone shouldn't already exist */ result = dns_zt_find(view->zonetable, name, 0, NULL, &zone); if (result == ISC_R_SUCCESS) { result = ISC_R_EXISTS; goto cleanup; } else if (result == DNS_R_PARTIALMATCH) { /* Create our sub-zone anyway */ dns_zone_detach(&zone); zone = NULL; } else if (result != ISC_R_NOTFOUND) goto cleanup; #ifndef HAVE_LMDB /* * Make sure we can open the configuration save file */ result = isc_stdio_open(view->new_zone_file, "a", &fp); if (result != ISC_R_SUCCESS) { TCHECK(putstr(text, "unable to create '")); TCHECK(putstr(text, view->new_zone_file)); TCHECK(putstr(text, "': ")); TCHECK(putstr(text, isc_result_totext(result))); goto cleanup; } (void)isc_stdio_close(fp); fp = NULL; #else /* HAVE_LMDB */ /* Make sure we can open the NZD database */ result = nzd_writable(view); if (result != ISC_R_SUCCESS) { TCHECK(putstr(text, "unable to open NZD database for '")); TCHECK(putstr(text, view->new_zone_db)); TCHECK(putstr(text, "'")); result = ISC_R_FAILURE; goto cleanup; } #endif /* HAVE_LMDB */ result = isc_task_beginexclusive(server->task); RUNTIME_CHECK(result == ISC_R_SUCCESS); /* Mark view unfrozen and configure zone */ dns_view_thaw(view); result = configure_zone(cfg->config, zoneobj, cfg->vconfig, server->mctx, view, &server->viewlist, cfg->actx, ISC_TRUE, ISC_FALSE, ISC_FALSE); dns_view_freeze(view); isc_task_endexclusive(server->task); if (result != ISC_R_SUCCESS) { TCHECK(putstr(text, "configure_zone failed: ")); TCHECK(putstr(text, isc_result_totext(result))); goto cleanup; } /* Is it there yet? */ result = dns_zt_find(view->zonetable, name, 0, NULL, &zone); if (result != ISC_R_SUCCESS) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, "added new zone was not found: %s", isc_result_totext(result)); goto cleanup; } #ifndef HAVE_LMDB /* * If there wasn't a previous newzone config, just save the one * we've created. If there was a previous one, merge the new * zone into it. */ if (cfg->nzf_config == NULL) { cfg_obj_attach(zoneconf, &cfg->nzf_config); } else { cfg_obj_t *z; DE_CONST(zoneobj, z); CHECK(cfg_parser_mapadd(cfg->add_parser, cfg->nzf_config, z, "zone")); } cleanup_config = ISC_TRUE; #endif /* HAVE_LMDB */ /* * Load the zone from the master file. If this fails, we'll * need to undo the configuration we've done already. */ result = dns_zone_loadnew(zone); if (result != ISC_R_SUCCESS) { dns_db_t *dbp = NULL; TCHECK(putstr(text, "dns_zone_loadnew failed: ")); TCHECK(putstr(text, isc_result_totext(result))); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_INFO, "addzone failed; reverting."); /* If the zone loaded partially, unload it */ if (dns_zone_getdb(zone, &dbp) == ISC_R_SUCCESS) { dns_db_detach(&dbp); dns_zone_unload(zone); } /* Remove the zone from the zone table */ dns_zt_unmount(view->zonetable, zone); goto cleanup; } /* Flag the zone as having been added at runtime */ dns_zone_setadded(zone, ISC_TRUE); #ifdef HAVE_LMDB /* Save the new zone configuration into the NZD */ CHECK(nzd_open(view, 0, &txn, &dbi)); CHECK(nzd_save(&txn, dbi, zone, zoneobj)); #else /* Append the zone configuration to the NZF */ result = nzf_append(view, zoneobj); #endif /* HAVE_LMDB */ cleanup: #ifndef HAVE_LMDB if (fp != NULL) (void)isc_stdio_close(fp); if (result != ISC_R_SUCCESS && cleanup_config) { tresult = delete_zoneconf(view, cfg->add_parser, cfg->nzf_config, name, NULL); RUNTIME_CHECK(tresult == ISC_R_SUCCESS); } #else /* HAVE_LMDB */ if (txn != NULL) (void) nzd_close(&txn, ISC_FALSE); #endif /* HAVE_LMDB */ if (zone != NULL) dns_zone_detach(&zone); return (result); } static isc_result_t do_modzone(ns_server_t *server, ns_cfgctx_t *cfg, dns_view_t *view, dns_name_t *name, const char *zname, const cfg_obj_t *zoneobj, isc_buffer_t **text) { isc_result_t result, tresult; dns_zone_t *zone = NULL; isc_boolean_t added; isc_boolean_t exclusive = ISC_FALSE; #ifndef HAVE_LMDB FILE *fp = NULL; cfg_obj_t *z; #else /* HAVE_LMDB */ MDB_txn *txn = NULL; MDB_dbi dbi; #endif /* HAVE_LMDB */ /* Zone must already exist */ result = dns_zt_find(view->zonetable, name, 0, NULL, &zone); if (result != ISC_R_SUCCESS) goto cleanup; added = dns_zone_getadded(zone); dns_zone_detach(&zone); #ifndef HAVE_LMDB cfg = (ns_cfgctx_t *) view->new_zone_config; if (cfg == NULL) { TCHECK(putstr(text, "new zone config is not set")); CHECK(ISC_R_FAILURE); } #endif result = isc_task_beginexclusive(server->task); RUNTIME_CHECK(result == ISC_R_SUCCESS); exclusive = ISC_TRUE; #ifndef HAVE_LMDB /* Make sure we can open the configuration save file */ result = isc_stdio_open(view->new_zone_file, "a", &fp); if (result != ISC_R_SUCCESS) { TCHECK(putstr(text, "unable to open '")); TCHECK(putstr(text, view->new_zone_file)); TCHECK(putstr(text, "': ")); TCHECK(putstr(text, isc_result_totext(result))); goto cleanup; } (void)isc_stdio_close(fp); fp = NULL; #else /* HAVE_LMDB */ /* Make sure we can open the NZD database */ result = nzd_writable(view); if (result != ISC_R_SUCCESS) { TCHECK(putstr(text, "unable to open NZD database for '")); TCHECK(putstr(text, view->new_zone_db)); TCHECK(putstr(text, "'")); result = ISC_R_FAILURE; goto cleanup; } #endif /* HAVE_LMDB */ /* Reconfigure the zone */ dns_view_thaw(view); result = configure_zone(cfg->config, zoneobj, cfg->vconfig, server->mctx, view, &server->viewlist, cfg->actx, ISC_TRUE, ISC_FALSE, ISC_TRUE); dns_view_freeze(view); exclusive = ISC_FALSE; isc_task_endexclusive(server->task); if (result != ISC_R_SUCCESS) { TCHECK(putstr(text, "configure_zone failed: ")); TCHECK(putstr(text, isc_result_totext(result))); goto cleanup; } /* Is it there yet? */ CHECK(dns_zt_find(view->zonetable, name, 0, NULL, &zone)); #ifndef HAVE_LMDB /* Remove old zone from configuration (and NZF file if applicable) */ if (added) { result = delete_zoneconf(view, cfg->add_parser, cfg->nzf_config, dns_zone_getorigin(zone), nzf_writeconf); if (result != ISC_R_SUCCESS) { TCHECK(putstr(text, "former zone configuration " "not deleted: ")); TCHECK(putstr(text, isc_result_totext(result))); goto cleanup; } } #endif /* HAVE_LMDB */ if (!added) { if (cfg->vconfig == NULL) { result = delete_zoneconf(view, cfg->conf_parser, cfg->config, dns_zone_getorigin(zone), NULL); } else { const cfg_obj_t *voptions = cfg_tuple_get(cfg->vconfig, "options"); result = delete_zoneconf(view, cfg->conf_parser, voptions, dns_zone_getorigin(zone), NULL); } if (result != ISC_R_SUCCESS) { TCHECK(putstr(text, "former zone configuration " "not deleted: ")); TCHECK(putstr(text, isc_result_totext(result))); goto cleanup; } } /* Load the zone from the master file if it needs reloading. */ result = dns_zone_loadnew(zone); /* * Dynamic zones need no reloading, so we can pass this result. */ if (result == DNS_R_DYNAMIC) result = ISC_R_SUCCESS; if (result != ISC_R_SUCCESS) { dns_db_t *dbp = NULL; TCHECK(putstr(text, "failed to load zone '")); TCHECK(putstr(text, zname)); TCHECK(putstr(text, "': ")); TCHECK(putstr(text, isc_result_totext(result))); TCHECK(putstr(text, "\nThe zone is no longer being served. ")); TCHECK(putstr(text, "Use 'rndc addzone' to correct\n")); TCHECK(putstr(text, "the problem and restore service.")); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_INFO, "modzone failed; removing zone."); /* If the zone loaded partially, unload it */ if (dns_zone_getdb(zone, &dbp) == ISC_R_SUCCESS) { dns_db_detach(&dbp); dns_zone_unload(zone); } /* Remove the zone from the zone table */ dns_zt_unmount(view->zonetable, zone); goto cleanup; } #ifndef HAVE_LMDB /* Store the new zone configuration; also in NZF if applicable */ DE_CONST(zoneobj, z); CHECK(cfg_parser_mapadd(cfg->add_parser, cfg->nzf_config, z, "zone")); #endif /* HAVE_LMDB */ if (added) { #ifdef HAVE_LMDB CHECK(nzd_open(view, 0, &txn, &dbi)); CHECK(nzd_save(&txn, dbi, zone, zoneobj)); #else result = nzf_append(view, zoneobj); if (result != ISC_R_SUCCESS) { TCHECK(putstr(text, "\nNew zone config not saved: ")); TCHECK(putstr(text, isc_result_totext(result))); goto cleanup; } #endif /* HAVE_LMDB */ TCHECK(putstr(text, "zone '")); TCHECK(putstr(text, zname)); TCHECK(putstr(text, "' reconfigured.")); } else { TCHECK(putstr(text, "zone '")); TCHECK(putstr(text, zname)); TCHECK(putstr(text, "' must also be reconfigured in\n")); TCHECK(putstr(text, "named.conf to make changes permanent.")); } cleanup: if (exclusive) isc_task_endexclusive(server->task); #ifndef HAVE_LMDB if (fp != NULL) (void)isc_stdio_close(fp); #else /* HAVE_LMDB */ if (txn != NULL) (void) nzd_close(&txn, ISC_FALSE); #endif /* HAVE_LMDB */ if (zone != NULL) dns_zone_detach(&zone); return (result); } /* * Act on an "addzone" or "modzone" command from the command channel. */ isc_result_t ns_server_changezone(ns_server_t *server, char *command, isc_buffer_t **text) { isc_result_t result; isc_boolean_t addzone; ns_cfgctx_t *cfg = NULL; cfg_obj_t *zoneconf = NULL; const cfg_obj_t *zoneobj = NULL; const char *zonename; dns_view_t *view = NULL; isc_buffer_t buf; dns_fixedname_t fname; dns_name_t *dnsname; if (strncasecmp(command, "add", 3) == 0) addzone = ISC_TRUE; else { INSIST(strncasecmp(command, "mod", 3) == 0); addzone = ISC_FALSE; } CHECK(newzone_parse(server, command, &view, &zoneconf, &zoneobj, text)); /* Are we accepting new zones in this view? */ #ifdef HAVE_LMDB if (view->new_zone_db == NULL) #else if (view->new_zone_file == NULL) #endif /* HAVE_LMDB */ { (void) putstr(text, "Not allowing new zones in view '"); (void) putstr(text, view->name); (void) putstr(text, "'"); result = ISC_R_NOPERM; goto cleanup; } cfg = (ns_cfgctx_t *) view->new_zone_config; if (cfg == NULL) { result = ISC_R_FAILURE; goto cleanup; } zonename = cfg_obj_asstring(cfg_tuple_get(zoneobj, "name")); isc_buffer_constinit(&buf, zonename, strlen(zonename)); isc_buffer_add(&buf, strlen(zonename)); dns_fixedname_init(&fname); dnsname = dns_fixedname_name(&fname); CHECK(dns_name_fromtext(dnsname, &buf, dns_rootname, 0, NULL)); if (addzone) CHECK(do_addzone(server, cfg, view, dnsname, zoneconf, zoneobj, text)); else CHECK(do_modzone(server, cfg, view, dnsname, zonename, zoneobj, text)); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_INFO, "%s zone %s in view %s via %s", addzone ? "added" : "updated", zonename, view->name, addzone ? NS_COMMAND_ADDZONE : NS_COMMAND_MODZONE); /* Changing a zone counts as reconfiguration */ CHECK(isc_time_now(&ns_g_configtime)); cleanup: if (isc_buffer_usedlength(*text) > 0) (void) putnull(text); if (zoneconf != NULL) cfg_obj_destroy(ns_g_addparser, &zoneconf); if (view != NULL) dns_view_detach(&view); return (result); } static isc_boolean_t inuse(const char* file, isc_boolean_t first, isc_buffer_t **text) { if (file != NULL && isc_file_exists(file)) { if (first) (void) putstr(text, "The following files were in use " "and may now be removed:\n"); else (void) putstr(text, "\n"); (void) putstr(text, file); (void) putnull(text); return (ISC_FALSE); } return (first); } typedef struct { dns_zone_t *zone; isc_boolean_t cleanup; } ns_dzctx_t; /* * Carry out a zone deletion scheduled by ns_server_delzone(). */ static void rmzone(isc_task_t *task, isc_event_t *event) { ns_dzctx_t *dz = (ns_dzctx_t *)event->ev_arg; dns_zone_t *zone, *raw = NULL, *mayberaw; char zonename[DNS_NAME_FORMATSIZE]; dns_view_t *view; ns_cfgctx_t *cfg; dns_db_t *dbp = NULL; isc_boolean_t added; isc_result_t result; #ifdef HAVE_LMDB MDB_txn *txn = NULL; MDB_dbi dbi; #endif REQUIRE(dz != NULL); isc_event_free(&event); /* Dig out configuration for this zone */ zone = dz->zone; view = dns_zone_getview(zone); cfg = (ns_cfgctx_t *) view->new_zone_config; dns_name_format(dns_zone_getorigin(zone), zonename, sizeof(zonename)); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_INFO, "deleting zone %s in view %s via delzone", zonename, view->name); /* Remove the zone from configuration (and NZF file if applicable) */ added = dns_zone_getadded(zone); if (added && cfg != NULL) { #ifdef HAVE_LMDB /* Make sure we can open the NZD database */ result = nzd_open(view, 0, &txn, &dbi); if (result != ISC_R_SUCCESS) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, "unable to open NZD database for '%s'", view->new_zone_db); } else { result = nzd_save(&txn, dbi, zone, NULL); } if (result != ISC_R_SUCCESS) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, "unable to " "delete zone configuration: %s", isc_result_totext(result)); } #else result = delete_zoneconf(view, cfg->add_parser, cfg->nzf_config, dns_zone_getorigin(zone), nzf_writeconf); if (result != ISC_R_SUCCESS) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, "unable to " "delete zone configuration: %s", isc_result_totext(result)); } #endif /* HAVE_LMDB */ } if (!added && cfg != NULL) { if (cfg->vconfig != NULL) { const cfg_obj_t *voptions = cfg_tuple_get(cfg->vconfig, "options"); result = delete_zoneconf(view, cfg->conf_parser, voptions, dns_zone_getorigin(zone), NULL); } else { result = delete_zoneconf(view, cfg->conf_parser, cfg->config, dns_zone_getorigin(zone), NULL); } if (result != ISC_R_SUCCESS){ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, "unable to " "delete zone configuration: %s", isc_result_totext(result)); } } /* Unload zone database */ if (dns_zone_getdb(zone, &dbp) == ISC_R_SUCCESS) { dns_db_detach(&dbp); dns_zone_unload(zone); } /* Clean up stub/slave zone files if requested to do so */ dns_zone_getraw(zone, &raw); mayberaw = (raw != NULL) ? raw : zone; if (added && dz->cleanup) { const char *file; file = dns_zone_getfile(mayberaw); result = isc_file_remove(file); if (result != ISC_R_SUCCESS) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_WARNING, "file %s not removed: %s", file, isc_result_totext(result)); } file = dns_zone_getjournal(mayberaw); result = isc_file_remove(file); if (result != ISC_R_SUCCESS) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_WARNING, "file %s not removed: %s", file, isc_result_totext(result)); } if (zone != mayberaw) { file = dns_zone_getfile(zone); result = isc_file_remove(file); if (result != ISC_R_SUCCESS) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_WARNING, "file %s not removed: %s", file, isc_result_totext(result)); } file = dns_zone_getjournal(zone); result = isc_file_remove(file); if (result != ISC_R_SUCCESS) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_WARNING, "file %s not removed: %s", file, isc_result_totext(result)); } } } #ifdef HAVE_LMDB if (txn != NULL) (void) nzd_close(&txn, ISC_FALSE); #endif if (raw != NULL) dns_zone_detach(&raw); dns_zone_detach(&zone); isc_mem_put(ns_g_mctx, dz, sizeof(*dz)); isc_task_detach(&task); } /* * Act on a "delzone" command from the command channel. */ isc_result_t ns_server_delzone(ns_server_t *server, isc_lex_t *lex, isc_buffer_t **text) { isc_result_t result, tresult; dns_zone_t *zone = NULL; dns_zone_t *raw = NULL; dns_zone_t *mayberaw; dns_view_t *view = NULL; char zonename[DNS_NAME_FORMATSIZE]; isc_boolean_t cleanup = ISC_FALSE; const char *ptr; isc_boolean_t added; ns_dzctx_t *dz = NULL; isc_event_t *dzevent = NULL; isc_task_t *task = NULL; /* Skip the command name. */ ptr = next_token(lex, text); if (ptr == NULL) return (ISC_R_UNEXPECTEDEND); /* Find out what we are to do. */ ptr = next_token(lex, text); if (ptr == NULL) return (ISC_R_UNEXPECTEDEND); if (strcmp(ptr, "-clean") == 0 || strcmp(ptr, "-clear") == 0) { cleanup = ISC_TRUE; ptr = next_token(lex, text); } CHECK(zone_from_args(server, lex, ptr, &zone, zonename, text, ISC_FALSE)); if (zone == NULL) { result = ISC_R_UNEXPECTEDEND; goto cleanup; } INSIST(zonename != NULL); /* Is this a policy zone? */ if (dns_zone_get_rpz_num(zone) != DNS_RPZ_INVALID_NUM) { TCHECK(putstr(text, "zone '")); TCHECK(putstr(text, zonename)); TCHECK(putstr(text, "' cannot be deleted: response-policy zone.")); result = ISC_R_FAILURE; goto cleanup; } view = dns_zone_getview(zone); CHECK(dns_zt_unmount(view->zonetable, zone)); /* Send cleanup event */ dz = isc_mem_get(ns_g_mctx, sizeof(*dz)); if (dz == NULL) CHECK(ISC_R_NOMEMORY); dz->cleanup = cleanup; dz->zone = NULL; dns_zone_attach(zone, &dz->zone); dzevent = isc_event_allocate(ns_g_mctx, server, NS_EVENT_DELZONE, rmzone, dz, sizeof(isc_event_t)); if (dzevent == NULL) CHECK(ISC_R_NOMEMORY); dns_zone_gettask(zone, &task); isc_task_send(task, &dzevent); dz = NULL; /* Inform user about cleaning up stub/slave zone files */ dns_zone_getraw(zone, &raw); mayberaw = (raw != NULL) ? raw : zone; added = dns_zone_getadded(zone); if (!added) { TCHECK(putstr(text, "zone '")); TCHECK(putstr(text, zonename)); TCHECK(putstr(text, "' is no longer active and will be deleted.\n")); TCHECK(putstr(text, "To keep it from returning ")); TCHECK(putstr(text, "when the server is restarted, it\n")); TCHECK(putstr(text, "must also be removed from named.conf.")); } else if (cleanup) { TCHECK(putstr(text, "zone '")); TCHECK(putstr(text, zonename)); TCHECK(putstr(text, "' and associated files will be deleted.")); } else if (dns_zone_gettype(mayberaw) == dns_zone_slave || dns_zone_gettype(mayberaw) == dns_zone_stub) { isc_boolean_t first; const char *file; TCHECK(putstr(text, "zone '")); TCHECK(putstr(text, zonename)); TCHECK(putstr(text, "' will be deleted.")); file = dns_zone_getfile(mayberaw); first = inuse(file, ISC_TRUE, text); file = dns_zone_getjournal(mayberaw); first = inuse(file, first, text); if (zone != mayberaw) { file = dns_zone_getfile(zone); first = inuse(file, first, text); file = dns_zone_getjournal(zone); (void) inuse(file, first, text); } } isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_INFO, "zone %s scheduled for removal via delzone", zonename); /* Removing a zone counts as reconfiguration */ CHECK(isc_time_now(&ns_g_configtime)); result = ISC_R_SUCCESS; cleanup: if (isc_buffer_usedlength(*text) > 0) (void) putnull(text); if (raw != NULL) dns_zone_detach(&raw); if (zone != NULL) dns_zone_detach(&zone); if (dz != NULL) { dns_zone_detach(&dz->zone); isc_mem_put(ns_g_mctx, dz, sizeof(*dz)); } return (result); } static const cfg_obj_t * find_name_in_list_from_map(const cfg_obj_t *config, const char *map_key_for_list, const char *name) { const cfg_obj_t *list = NULL; const cfg_listelt_t *element; const cfg_obj_t *obj = NULL; dns_fixedname_t fixed1, fixed2; dns_name_t *name1 = NULL, *name2 = NULL; isc_result_t result; if (strcmp(map_key_for_list, "zone") == 0) { dns_fixedname_init(&fixed1); dns_fixedname_init(&fixed2); name1 = dns_fixedname_name(&fixed1); name2 = dns_fixedname_name(&fixed2); result = dns_name_fromstring(name1, name, 0, NULL); RUNTIME_CHECK(result == ISC_R_SUCCESS); } cfg_map_get(config, map_key_for_list, &list); for (element = cfg_list_first(list); element != NULL; element = cfg_list_next(element)) { const char *vname; obj = cfg_listelt_value(element); INSIST(obj != NULL); vname = cfg_obj_asstring(cfg_tuple_get(obj, "name")); if (vname == NULL) { obj = NULL; continue; } if (name1 != NULL) { result = dns_name_fromstring(name2, vname, 0, NULL); if (result == ISC_R_SUCCESS && dns_name_equal(name1, name2)) break; } else if (strcasecmp(vname, name) == 0) break; obj = NULL; } return (obj); } static void emitzone(void *arg, const char *buf, int len) { isc_buffer_t **tpp = arg; putmem(tpp, buf, len); } /* * Act on a "showzone" command from the command channel. */ isc_result_t ns_server_showzone(ns_server_t *server, isc_lex_t *lex, isc_buffer_t **text) { isc_result_t result; const cfg_obj_t *vconfig = NULL, *zconfig = NULL; char zonename[DNS_NAME_FORMATSIZE]; const cfg_obj_t *map; dns_view_t *view = NULL; dns_zone_t *zone = NULL; ns_cfgctx_t *cfg = NULL; isc_boolean_t exclusive = ISC_FALSE; #ifdef HAVE_LMDB cfg_obj_t *nzconfig = NULL; #endif /* HAVE_LMDB */ /* Parse parameters */ CHECK(zone_from_args(server, lex, NULL, &zone, zonename, text, ISC_TRUE)); if (zone == NULL) { result = ISC_R_UNEXPECTEDEND; goto cleanup; } view = dns_zone_getview(zone); dns_zone_detach(&zone); cfg = (ns_cfgctx_t *) view->new_zone_config; if (cfg == NULL) { result = ISC_R_FAILURE; goto cleanup; } result = isc_task_beginexclusive(server->task); RUNTIME_CHECK(result == ISC_R_SUCCESS); exclusive = ISC_TRUE; /* Find the view statement */ vconfig = find_name_in_list_from_map(cfg->config, "view", view->name); /* Find the zone statement */ if (vconfig != NULL) map = cfg_tuple_get(vconfig, "options"); else map = cfg->config; zconfig = find_name_in_list_from_map(map, "zone", zonename); #ifndef HAVE_LMDB if (zconfig == NULL && cfg->nzf_config != NULL) zconfig = find_name_in_list_from_map(cfg->nzf_config, "zone", zonename); #else /* HAVE_LMDB */ if (zconfig == NULL) { const cfg_obj_t *zlist = NULL; CHECK(get_newzone_config(view, zonename, &nzconfig)); CHECK(cfg_map_get(nzconfig, "zone", &zlist)); if (!cfg_obj_islist(zlist)) CHECK(ISC_R_FAILURE); zconfig = cfg_listelt_value(cfg_list_first(zlist)); } #endif /* HAVE_LMDB */ if (zconfig == NULL) CHECK(ISC_R_NOTFOUND); putstr(text, "zone "); cfg_printx(zconfig, CFG_PRINTER_ONELINE, emitzone, text); putstr(text, ";"); result = ISC_R_SUCCESS; cleanup: #ifdef HAVE_LMDB if (nzconfig != NULL) cfg_obj_destroy(ns_g_addparser, &nzconfig); #endif /* HAVE_LMDB */ if (isc_buffer_usedlength(*text) > 0) (void) putnull(text); if (exclusive) isc_task_endexclusive(server->task); return (result); } static void newzone_cfgctx_destroy(void **cfgp) { ns_cfgctx_t *cfg; REQUIRE(cfgp != NULL && *cfgp != NULL); cfg = *cfgp; if (cfg->conf_parser != NULL) { if (cfg->config != NULL) cfg_obj_destroy(cfg->conf_parser, &cfg->config); if (cfg->vconfig != NULL) cfg_obj_destroy(cfg->conf_parser, &cfg->vconfig); cfg_parser_destroy(&cfg->conf_parser); } if (cfg->add_parser != NULL) { if (cfg->nzf_config != NULL) cfg_obj_destroy(cfg->add_parser, &cfg->nzf_config); cfg_parser_destroy(&cfg->add_parser); } if (cfg->actx != NULL) cfg_aclconfctx_detach(&cfg->actx); isc_mem_putanddetach(&cfg->mctx, cfg, sizeof(*cfg)); *cfgp = NULL; } static isc_result_t generate_salt(unsigned char *salt, size_t saltlen) { int i, n; union { unsigned char rnd[256]; isc_uint32_t rnd32[64]; } rnd; unsigned char text[512 + 1]; isc_region_t r; isc_buffer_t buf; isc_result_t result; if (saltlen > 256U) return (ISC_R_RANGE); n = (int) (saltlen + sizeof(isc_uint32_t) - 1) / sizeof(isc_uint32_t); for (i = 0; i < n; i++) isc_random_get(&rnd.rnd32[i]); memmove(salt, rnd.rnd, saltlen); r.base = rnd.rnd; r.length = (unsigned int) saltlen; isc_buffer_init(&buf, text, sizeof(text)); result = isc_hex_totext(&r, 2, "", &buf); RUNTIME_CHECK(result == ISC_R_SUCCESS); text[saltlen * 2] = 0; isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_INFO, "generated salt: %s", text); return (ISC_R_SUCCESS); } isc_result_t ns_server_signing(ns_server_t *server, isc_lex_t *lex, isc_buffer_t **text) { isc_result_t result = ISC_R_SUCCESS; dns_zone_t *zone = NULL; dns_name_t *origin; dns_db_t *db = NULL; dns_dbnode_t *node = NULL; dns_dbversion_t *version = NULL; dns_rdatatype_t privatetype; dns_rdataset_t privset; isc_boolean_t first = ISC_TRUE; isc_boolean_t list = ISC_FALSE, clear = ISC_FALSE; isc_boolean_t chain = ISC_FALSE; isc_boolean_t setserial = ISC_FALSE; isc_uint32_t serial = 0; char keystr[DNS_SECALG_FORMATSIZE + 7]; /* <5-digit keyid>/ */ unsigned short hash = 0, flags = 0, iter = 0, saltlen = 0; unsigned char salt[255]; const char *ptr; size_t n; dns_rdataset_init(&privset); /* Skip the command name. */ ptr = next_token(lex, text); if (ptr == NULL) return (ISC_R_UNEXPECTEDEND); /* Find out what we are to do. */ ptr = next_token(lex, text); if (ptr == NULL) return (ISC_R_UNEXPECTEDEND); if (strcasecmp(ptr, "-list") == 0) list = ISC_TRUE; else if ((strcasecmp(ptr, "-clear") == 0) || (strcasecmp(ptr, "-clean") == 0)) { clear = ISC_TRUE; ptr = next_token(lex, text); if (ptr == NULL) return (ISC_R_UNEXPECTEDEND); strlcpy(keystr, ptr, sizeof(keystr)); } else if (strcasecmp(ptr, "-nsec3param") == 0) { char hashbuf[64], flagbuf[64], iterbuf[64]; char nbuf[256]; chain = ISC_TRUE; ptr = next_token(lex, text); if (ptr == NULL) return (ISC_R_UNEXPECTEDEND); if (strcasecmp(ptr, "none") == 0) hash = 0; else { strlcpy(hashbuf, ptr, sizeof(hashbuf)); ptr = next_token(lex, text); if (ptr == NULL) return (ISC_R_UNEXPECTEDEND); strlcpy(flagbuf, ptr, sizeof(flagbuf)); ptr = next_token(lex, text); if (ptr == NULL) return (ISC_R_UNEXPECTEDEND); strlcpy(iterbuf, ptr, sizeof(iterbuf)); n = snprintf(nbuf, sizeof(nbuf), "%s %s %s", hashbuf, flagbuf, iterbuf); if (n == sizeof(nbuf)) return (ISC_R_NOSPACE); n = sscanf(nbuf, "%hu %hu %hu", &hash, &flags, &iter); if (n != 3U) return (ISC_R_BADNUMBER); if (hash > 0xffU || flags > 0xffU) return (ISC_R_RANGE); ptr = next_token(lex, text); if (ptr == NULL) { return (ISC_R_UNEXPECTEDEND); } else if (strcasecmp(ptr, "auto") == 0) { /* Auto-generate a random salt. * XXXMUKS: This currently uses the * minimum recommended length by RFC * 5155 (64 bits). It should be made * configurable. */ saltlen = 8; CHECK(generate_salt(salt, saltlen)); } else if (strcmp(ptr, "-") != 0) { isc_buffer_t buf; isc_buffer_init(&buf, salt, sizeof(salt)); CHECK(isc_hex_decodestring(ptr, &buf)); saltlen = isc_buffer_usedlength(&buf); } } } else if (strcasecmp(ptr, "-serial") == 0) { ptr = next_token(lex, text); if (ptr == NULL) return (ISC_R_UNEXPECTEDEND); CHECK(isc_parse_uint32(&serial, ptr, 10)); setserial = ISC_TRUE; } else CHECK(DNS_R_SYNTAX); CHECK(zone_from_args(server, lex, NULL, &zone, NULL, text, ISC_FALSE)); if (zone == NULL) CHECK(ISC_R_UNEXPECTEDEND); if (clear) { CHECK(dns_zone_keydone(zone, keystr)); (void) putstr(text, "request queued"); (void) putnull(text); } else if (chain) { CHECK(dns_zone_setnsec3param(zone, (isc_uint8_t)hash, (isc_uint8_t)flags, iter, (isc_uint8_t)saltlen, salt, ISC_TRUE)); (void) putstr(text, "nsec3param request queued"); (void) putnull(text); } else if (setserial) { CHECK(dns_zone_setserial(zone, serial)); (void) putstr(text, "serial request queued"); (void) putnull(text); } else if (list) { privatetype = dns_zone_getprivatetype(zone); origin = dns_zone_getorigin(zone); CHECK(dns_zone_getdb(zone, &db)); CHECK(dns_db_findnode(db, origin, ISC_FALSE, &node)); dns_db_currentversion(db, &version); result = dns_db_findrdataset(db, node, version, privatetype, dns_rdatatype_none, 0, &privset, NULL); if (result == ISC_R_NOTFOUND) { (void) putstr(text, "No signing records found"); (void) putnull(text); result = ISC_R_SUCCESS; goto cleanup; } for (result = dns_rdataset_first(&privset); result == ISC_R_SUCCESS; result = dns_rdataset_next(&privset)) { dns_rdata_t priv = DNS_RDATA_INIT; char output[BUFSIZ]; isc_buffer_t buf; dns_rdataset_current(&privset, &priv); isc_buffer_init(&buf, output, sizeof(output)); CHECK(dns_private_totext(&priv, &buf)); if (!first) CHECK(putstr(text, "\n")); CHECK(putstr(text, output)); first = ISC_FALSE; } if (!first) CHECK(putnull(text)); if (result == ISC_R_NOMORE) result = ISC_R_SUCCESS; } cleanup: if (dns_rdataset_isassociated(&privset)) dns_rdataset_disassociate(&privset); if (node != NULL) dns_db_detachnode(db, &node); if (version != NULL) dns_db_closeversion(db, &version, ISC_FALSE); if (db != NULL) dns_db_detach(&db); if (zone != NULL) dns_zone_detach(&zone); return (result); } static isc_result_t putmem(isc_buffer_t **b, const char *str, size_t len) { isc_result_t result; result = isc_buffer_reserve(b, (unsigned int)len); if (result != ISC_R_SUCCESS) return (ISC_R_NOSPACE); isc_buffer_putmem(*b, (const unsigned char *)str, (unsigned int)len); return (ISC_R_SUCCESS); } static inline isc_result_t putstr(isc_buffer_t **b, const char *str) { return (putmem(b, str, strlen(str))); } static isc_result_t putuint8(isc_buffer_t **b, isc_uint8_t val) { isc_result_t result; result = isc_buffer_reserve(b, 1); if (result != ISC_R_SUCCESS) return (ISC_R_NOSPACE); isc_buffer_putuint8(*b, val); return (ISC_R_SUCCESS); } static inline isc_result_t putnull(isc_buffer_t **b) { return (putuint8(b, 0)); } isc_result_t ns_server_zonestatus(ns_server_t *server, isc_lex_t *lex, isc_buffer_t **text) { isc_result_t result = ISC_R_SUCCESS; dns_zone_t *zone = NULL, *raw = NULL, *mayberaw = NULL; const char *type, *file; char zonename[DNS_NAME_FORMATSIZE]; isc_uint32_t serial, signed_serial, nodes; char serbuf[16], sserbuf[16], nodebuf[16], resignbuf[512]; char lbuf[ISC_FORMATHTTPTIMESTAMP_SIZE]; char xbuf[ISC_FORMATHTTPTIMESTAMP_SIZE]; char rbuf[ISC_FORMATHTTPTIMESTAMP_SIZE]; char kbuf[ISC_FORMATHTTPTIMESTAMP_SIZE]; char rtbuf[ISC_FORMATHTTPTIMESTAMP_SIZE]; isc_time_t loadtime, expiretime, refreshtime; isc_time_t refreshkeytime, resigntime; dns_zonetype_t zonetype; isc_boolean_t dynamic = ISC_FALSE, frozen = ISC_FALSE; isc_boolean_t hasraw = ISC_FALSE; isc_boolean_t secure, maintain, allow; dns_db_t *db = NULL, *rawdb = NULL; char **incfiles = NULL; int nfiles = 0; isc_time_settoepoch(&loadtime); isc_time_settoepoch(&refreshtime); isc_time_settoepoch(&expiretime); isc_time_settoepoch(&refreshkeytime); isc_time_settoepoch(&resigntime); CHECK(zone_from_args(server, lex, NULL, &zone, zonename, text, ISC_TRUE)); if (zone == NULL) { result = ISC_R_UNEXPECTEDEND; goto cleanup; } /* Inline signing? */ CHECK(dns_zone_getdb(zone, &db)); dns_zone_getraw(zone, &raw); hasraw = ISC_TF(raw != NULL); if (hasraw) { mayberaw = raw; zonetype = dns_zone_gettype(raw); CHECK(dns_zone_getdb(raw, &rawdb)); } else { mayberaw = zone; zonetype = dns_zone_gettype(zone); } switch (zonetype) { case dns_zone_master: type = "master"; break; case dns_zone_slave: type = "slave"; break; case dns_zone_stub: type = "stub"; break; case dns_zone_staticstub: type = "staticstub"; break; case dns_zone_redirect: type = "redirect"; break; case dns_zone_key: type = "key"; break; case dns_zone_dlz: type = "dlz"; break; default: type = "unknown"; } /* Serial number */ serial = dns_zone_getserial(mayberaw); snprintf(serbuf, sizeof(serbuf), "%u", serial); if (hasraw) { signed_serial = dns_zone_getserial(zone); snprintf(sserbuf, sizeof(sserbuf), "%u", signed_serial); } /* Database node count */ nodes = dns_db_nodecount(hasraw ? rawdb : db); snprintf(nodebuf, sizeof(nodebuf), "%u", nodes); /* Security */ secure = dns_db_issecure(db); allow = ISC_TF((dns_zone_getkeyopts(zone) & DNS_ZONEKEY_ALLOW) != 0); maintain = ISC_TF((dns_zone_getkeyopts(zone) & DNS_ZONEKEY_MAINTAIN) != 0); /* Master files */ file = dns_zone_getfile(mayberaw); nfiles = dns_zone_getincludes(mayberaw, &incfiles); /* Load time */ dns_zone_getloadtime(zone, &loadtime); isc_time_formathttptimestamp(&loadtime, lbuf, sizeof(lbuf)); /* Refresh/expire times */ if (zonetype == dns_zone_slave || zonetype == dns_zone_stub || zonetype == dns_zone_redirect) { dns_zone_getexpiretime(mayberaw, &expiretime); isc_time_formathttptimestamp(&expiretime, xbuf, sizeof(xbuf)); dns_zone_getrefreshtime(mayberaw, &refreshtime); isc_time_formathttptimestamp(&refreshtime, rbuf, sizeof(rbuf)); } /* Key refresh time */ if (zonetype == dns_zone_master || (zonetype == dns_zone_slave && hasraw)) { dns_zone_getrefreshkeytime(zone, &refreshkeytime); isc_time_formathttptimestamp(&refreshkeytime, kbuf, sizeof(kbuf)); } /* Dynamic? */ if (zonetype == dns_zone_master) { dynamic = dns_zone_isdynamic(mayberaw, ISC_TRUE); frozen = dynamic && !dns_zone_isdynamic(mayberaw, ISC_FALSE); } /* Next resign event */ if (secure && (zonetype == dns_zone_master || (zonetype == dns_zone_slave && hasraw)) && ((dns_zone_getkeyopts(zone) & DNS_ZONEKEY_NORESIGN) == 0)) { dns_name_t *name; dns_fixedname_t fixed; dns_rdataset_t next; dns_rdataset_init(&next); dns_fixedname_init(&fixed); name = dns_fixedname_name(&fixed); result = dns_db_getsigningtime(db, &next, name); if (result == ISC_R_SUCCESS) { isc_stdtime_t timenow; char namebuf[DNS_NAME_FORMATSIZE]; char typebuf[DNS_RDATATYPE_FORMATSIZE]; isc_stdtime_get(&timenow); dns_name_format(name, namebuf, sizeof(namebuf)); dns_rdatatype_format(next.covers, typebuf, sizeof(typebuf)); snprintf(resignbuf, sizeof(resignbuf), "%s/%s", namebuf, typebuf); isc_time_set(&resigntime, next.resign - dns_zone_getsigresigninginterval(zone), 0); isc_time_formathttptimestamp(&resigntime, rtbuf, sizeof(rtbuf)); dns_rdataset_disassociate(&next); } } /* Create text */ CHECK(putstr(text, "name: ")); CHECK(putstr(text, zonename)); CHECK(putstr(text, "\ntype: ")); CHECK(putstr(text, type)); if (file != NULL) { int i; CHECK(putstr(text, "\nfiles: ")); CHECK(putstr(text, file)); for (i = 0; i < nfiles; i++) { CHECK(putstr(text, ", ")); if (incfiles[i] != NULL) { CHECK(putstr(text, incfiles[i])); } } } CHECK(putstr(text, "\nserial: ")); CHECK(putstr(text, serbuf)); if (hasraw) { CHECK(putstr(text, "\nsigned serial: ")); CHECK(putstr(text, sserbuf)); } CHECK(putstr(text, "\nnodes: ")); CHECK(putstr(text, nodebuf)); if (! isc_time_isepoch(&loadtime)) { CHECK(putstr(text, "\nlast loaded: ")); CHECK(putstr(text, lbuf)); } if (! isc_time_isepoch(&refreshtime)) { CHECK(putstr(text, "\nnext refresh: ")); CHECK(putstr(text, rbuf)); } if (! isc_time_isepoch(&expiretime)) { CHECK(putstr(text, "\nexpires: ")); CHECK(putstr(text, xbuf)); } if (secure) { CHECK(putstr(text, "\nsecure: yes")); if (hasraw) { CHECK(putstr(text, "\ninline signing: yes")); } else { CHECK(putstr(text, "\ninline signing: no")); } } else { CHECK(putstr(text, "\nsecure: no")); } if (maintain) { CHECK(putstr(text, "\nkey maintenance: automatic")); if (! isc_time_isepoch(&refreshkeytime)) { CHECK(putstr(text, "\nnext key event: ")); CHECK(putstr(text, kbuf)); } } else if (allow) { CHECK(putstr(text, "\nkey maintenance: on command")); } else if (secure || hasraw) { CHECK(putstr(text, "\nkey maintenance: none")); } if (!isc_time_isepoch(&resigntime)) { CHECK(putstr(text, "\nnext resign node: ")); CHECK(putstr(text, resignbuf)); CHECK(putstr(text, "\nnext resign time: ")); CHECK(putstr(text, rtbuf)); } if (dynamic) { CHECK(putstr(text, "\ndynamic: yes")); if (frozen) { CHECK(putstr(text, "\nfrozen: yes")); } else { CHECK(putstr(text, "\nfrozen: no")); } } else { CHECK(putstr(text, "\ndynamic: no")); } CHECK(putstr(text, "\nreconfigurable via modzone: ")); CHECK(putstr(text, dns_zone_getadded(zone) ? "yes" : "no")); cleanup: /* Indicate truncated output if possible. */ if (result == ISC_R_NOSPACE) { (void) putstr(text, "\n..."); } if ((result == ISC_R_SUCCESS || result == ISC_R_NOSPACE)) { (void) putnull(text); } if (db != NULL) { dns_db_detach(&db); } if (rawdb != NULL) { dns_db_detach(&rawdb); } if (incfiles != NULL && mayberaw != NULL) { int i; isc_mem_t *mctx = dns_zone_getmctx(mayberaw); for (i = 0; i < nfiles; i++) { if (incfiles[i] != NULL) { isc_mem_free(mctx, incfiles[i]); } } isc_mem_free(mctx, incfiles); } if (raw != NULL) { dns_zone_detach(&raw); } if (zone != NULL) { dns_zone_detach(&zone); } return (result); } static inline isc_boolean_t argcheck(char *cmd, const char *full) { size_t l; if (cmd == NULL || cmd[0] != '-') return (ISC_FALSE); cmd++; l = strlen(cmd); if (l > strlen(full) || strncasecmp(cmd, full, l) != 0) return (ISC_FALSE); return (ISC_TRUE); } isc_result_t ns_server_nta(ns_server_t *server, isc_lex_t *lex, isc_boolean_t readonly, isc_buffer_t **text) { dns_view_t *view; dns_ntatable_t *ntatable = NULL; isc_result_t result = ISC_R_SUCCESS; char *ptr, *nametext = NULL, *viewname; char namebuf[DNS_NAME_FORMATSIZE]; isc_stdtime_t now, when; isc_time_t t; char tbuf[64]; const char *msg = NULL; isc_boolean_t dump = ISC_FALSE, force = ISC_FALSE; dns_fixedname_t fn; dns_name_t *ntaname; dns_ttl_t ntattl; isc_boolean_t ttlset = ISC_FALSE, excl = ISC_FALSE; UNUSED(force); dns_fixedname_init(&fn); ntaname = dns_fixedname_name(&fn); /* Skip the command name. */ ptr = next_token(lex, text); if (ptr == NULL) return (ISC_R_UNEXPECTEDEND); for (;;) { /* Check for options */ ptr = next_token(lex, text); if (ptr == NULL) return (ISC_R_UNEXPECTEDEND); if (argcheck(ptr, "dump")) dump = ISC_TRUE; else if (argcheck(ptr, "remove")) { ntattl = 0; ttlset = ISC_TRUE; } else if (argcheck(ptr, "force")) { force = ISC_TRUE; continue; } else if (argcheck(ptr, "lifetime")) { isc_textregion_t tr; ptr = next_token(lex, text); if (ptr == NULL) { msg = "No lifetime specified"; CHECK(ISC_R_UNEXPECTEDEND); } tr.base = ptr; tr.length = strlen(ptr); result = dns_ttl_fromtext(&tr, &ntattl); if (result != ISC_R_SUCCESS) { msg = "could not parse NTA lifetime"; CHECK(result); } if (ntattl > 604800) { msg = "NTA lifetime cannot exceed one week"; CHECK(ISC_R_RANGE); } ttlset = ISC_TRUE; continue; } else nametext = ptr; break; } /* * If -dump was specified, list NTA's and return */ if (dump) { for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; view = ISC_LIST_NEXT(view, link)) { if (ntatable != NULL) dns_ntatable_detach(&ntatable); result = dns_view_getntatable(view, &ntatable); if (result == ISC_R_NOTFOUND) continue; CHECK(dns_ntatable_totext(ntatable, text)); } CHECK(putnull(text)); goto cleanup; } if (readonly) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_CONTROL, ISC_LOG_INFO, "rejecting restricted control channel " "NTA command"); CHECK(ISC_R_FAILURE); } /* Get the NTA name. */ if (nametext == NULL) nametext = next_token(lex, text); if (nametext == NULL) return (ISC_R_UNEXPECTEDEND); /* Copy nametext as it'll be overwritten by next_token() */ strlcpy(namebuf, nametext, DNS_NAME_FORMATSIZE); if (strcmp(namebuf, ".") == 0) ntaname = dns_rootname; else { isc_buffer_t b; isc_buffer_init(&b, namebuf, strlen(namebuf)); isc_buffer_add(&b, strlen(namebuf)); CHECK(dns_name_fromtext(ntaname, &b, dns_rootname, 0, NULL)); } /* Look for the view name. */ viewname = next_token(lex, text); isc_stdtime_get(&now); result = isc_task_beginexclusive(server->task); RUNTIME_CHECK(result == ISC_R_SUCCESS); excl = ISC_TRUE; for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; view = ISC_LIST_NEXT(view, link)) { if (viewname != NULL && strcmp(view->name, viewname) != 0) continue; if (view->nta_lifetime == 0) continue; if (!ttlset) ntattl = view->nta_lifetime; if (ntatable != NULL) dns_ntatable_detach(&ntatable); result = dns_view_getntatable(view, &ntatable); if (result == ISC_R_NOTFOUND) { result = ISC_R_SUCCESS; continue; } result = dns_view_flushnode(view, ntaname, ISC_TRUE); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_INFO, "flush tree '%s' in cache view '%s': %s", namebuf, view->name, isc_result_totext(result)); if (ntattl != 0) { CHECK(dns_ntatable_add(ntatable, ntaname, force, now, ntattl)); when = now + ntattl; isc_time_set(&t, when, 0); isc_time_formattimestamp(&t, tbuf, sizeof(tbuf)); CHECK(putstr(text, "Negative trust anchor added: ")); CHECK(putstr(text, namebuf)); CHECK(putstr(text, "/")); CHECK(putstr(text, view->name)); CHECK(putstr(text, ", expires ")); CHECK(putstr(text, tbuf)); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_INFO, "added NTA '%s' (%d sec) in view '%s'", namebuf, ntattl, view->name); } else { CHECK(dns_ntatable_delete(ntatable, ntaname)); CHECK(putstr(text, "Negative trust anchor removed: ")); CHECK(putstr(text, namebuf)); CHECK(putstr(text, "/")); CHECK(putstr(text, view->name)); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_INFO, "removed NTA '%s' in view %s", namebuf, view->name); } result = dns_view_saventa(view); if (result != ISC_R_SUCCESS) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, "error writing NTA file " "for view '%s': %s", view->name, isc_result_totext(result)); } CHECK(putnull(text)); } cleanup: if (msg != NULL) { (void) putstr(text, msg); (void) putnull(text); } if (excl) isc_task_endexclusive(server->task); if (ntatable != NULL) dns_ntatable_detach(&ntatable); return (result); } isc_result_t ns_server_saventa(ns_server_t *server) { dns_view_t *view; for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; view = ISC_LIST_NEXT(view, link)) { isc_result_t result = dns_view_saventa(view); if (result != ISC_R_SUCCESS) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, "error writing NTA file " "for view '%s': %s", view->name, isc_result_totext(result)); } } return (ISC_R_SUCCESS); } isc_result_t ns_server_loadnta(ns_server_t *server) { dns_view_t *view; for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; view = ISC_LIST_NEXT(view, link)) { isc_result_t result = dns_view_loadnta(view); if ((result != ISC_R_SUCCESS) && (result != ISC_R_FILENOTFOUND) && (result != ISC_R_NOTFOUND)) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, "error loading NTA file " "for view '%s': %s", view->name, isc_result_totext(result)); } } return (ISC_R_SUCCESS); } static isc_result_t mkey_refresh(dns_view_t *view, isc_buffer_t **text) { isc_result_t result; char msg[DNS_NAME_FORMATSIZE + 500] = ""; snprintf(msg, sizeof(msg), "refreshing managed keys for '%s'", view->name); CHECK(putstr(text, msg)); CHECK(dns_zone_synckeyzone(view->managed_keys)); cleanup: return (result); } static isc_result_t mkey_dumpzone(dns_view_t *view, isc_buffer_t **text) { isc_result_t result; dns_db_t *db = NULL; dns_dbversion_t *ver = NULL; dns_rriterator_t rrit; isc_stdtime_t now; dns_name_t *prevname = NULL; isc_stdtime_get(&now); CHECK(dns_zone_getdb(view->managed_keys, &db)); dns_db_currentversion(db, &ver); dns_rriterator_init(&rrit, db, ver, 0); for (result = dns_rriterator_first(&rrit); result == ISC_R_SUCCESS; result = dns_rriterator_nextrrset(&rrit)) { char buf[DNS_NAME_FORMATSIZE + 500]; dns_name_t *name = NULL; dns_rdataset_t *kdset = NULL; dns_rdata_t rdata = DNS_RDATA_INIT; dns_rdata_keydata_t kd; isc_uint32_t ttl; dns_rriterator_current(&rrit, &name, &ttl, &kdset, NULL); if (kdset == NULL || kdset->type != dns_rdatatype_keydata || !dns_rdataset_isassociated(kdset)) continue; if (name != prevname) { char nbuf[DNS_NAME_FORMATSIZE]; dns_name_format(name, nbuf, sizeof(nbuf)); snprintf(buf, sizeof(buf), "\n\n name: %s", nbuf); CHECK(putstr(text, buf)); } for (result = dns_rdataset_first(kdset); result == ISC_R_SUCCESS; result = dns_rdataset_next(kdset)) { char alg[DNS_SECALG_FORMATSIZE]; char tbuf[ISC_FORMATHTTPTIMESTAMP_SIZE]; dns_keytag_t keyid; isc_region_t r; isc_time_t t; isc_boolean_t revoked; dns_rdata_reset(&rdata); dns_rdataset_current(kdset, &rdata); result = dns_rdata_tostruct(&rdata, &kd, NULL); RUNTIME_CHECK(result == ISC_R_SUCCESS); dns_rdata_toregion(&rdata, &r); isc_region_consume(&r, 12); keyid = dst_region_computeid(&r, kd.algorithm); snprintf(buf, sizeof(buf), "\n keyid: %u", keyid); CHECK(putstr(text, buf)); dns_secalg_format(kd.algorithm, alg, sizeof(alg)); snprintf(buf, sizeof(buf), "\n\talgorithm: %s", alg); CHECK(putstr(text, buf)); revoked = ISC_TF((kd.flags & DNS_KEYFLAG_REVOKE) != 0); snprintf(buf, sizeof(buf), "\n\tflags:%s%s%s", revoked ? " REVOKE" : "", ((kd.flags & DNS_KEYFLAG_KSK) != 0) ? " SEP" : "", (kd.flags == 0) ? " (none)" : ""); CHECK(putstr(text, buf)); isc_time_set(&t, kd.refresh, 0); isc_time_formathttptimestamp(&t, tbuf, sizeof(tbuf)); snprintf(buf, sizeof(buf), "\n\tnext refresh: %s", tbuf); CHECK(putstr(text, buf)); if (kd.removehd != 0) { isc_time_set(&t, kd.removehd, 0); isc_time_formathttptimestamp(&t, tbuf, sizeof(tbuf)); snprintf(buf, sizeof(buf), "\n\tremove at: %s", tbuf); CHECK(putstr(text, buf)); } isc_time_set(&t, kd.addhd, 0); isc_time_formathttptimestamp(&t, tbuf, sizeof(tbuf)); if (kd.addhd == 0) snprintf(buf, sizeof(buf), "\n\tno trust"); else if (revoked) snprintf(buf, sizeof(buf), "\n\ttrust revoked"); else if (kd.addhd <= now) snprintf(buf, sizeof(buf), "\n\ttrusted since: %s", tbuf); else if (kd.addhd > now) snprintf(buf, sizeof(buf), "\n\ttrust pending: %s", tbuf); CHECK(putstr(text, buf)); } } if (result == ISC_R_NOMORE) result = ISC_R_SUCCESS; cleanup: if (ver != NULL) { dns_rriterator_destroy(&rrit); dns_db_closeversion(db, &ver, ISC_FALSE); } if (db != NULL) dns_db_detach(&db); return (result); } static isc_result_t mkey_status(dns_view_t *view, isc_buffer_t **text) { isc_result_t result; char msg[ISC_FORMATHTTPTIMESTAMP_SIZE]; isc_time_t t; CHECK(putstr(text, "view: ")); CHECK(putstr(text, view->name)); CHECK(putstr(text, "\nnext scheduled event: ")); dns_zone_getrefreshkeytime(view->managed_keys, &t); if (isc_time_isepoch(&t)) { CHECK(putstr(text, "never")); } else { isc_time_formathttptimestamp(&t, msg, sizeof(msg)); CHECK(putstr(text, msg)); } CHECK(mkey_dumpzone(view, text)); cleanup: return (result); } isc_result_t ns_server_mkeys(ns_server_t *server, isc_lex_t *lex, isc_buffer_t **text) { char *cmd, *classtxt, *viewtxt = NULL; isc_result_t result = ISC_R_SUCCESS; dns_view_t *view = NULL; dns_rdataclass_t rdclass; char msg[DNS_NAME_FORMATSIZE + 500] = ""; enum { NONE, STATUS, REFRESH, SYNC } opt = NONE; isc_boolean_t found = ISC_FALSE; isc_boolean_t first = ISC_TRUE; /* Skip rndc command name */ cmd = next_token(lex, text); if (cmd == NULL) return (ISC_R_UNEXPECTEDEND); /* Get managed-keys subcommand */ cmd = next_token(lex, text); if (cmd == NULL) return (ISC_R_UNEXPECTEDEND); if (strcasecmp(cmd, "status") == 0) opt = STATUS; else if (strcasecmp(cmd, "refresh") == 0) opt = REFRESH; else if (strcasecmp(cmd, "sync") == 0) opt = SYNC; else { snprintf(msg, sizeof(msg), "unknown command '%s'", cmd); (void) putstr(text, msg); result = ISC_R_UNEXPECTED; goto cleanup; } /* Look for the optional class name. */ classtxt = next_token(lex, text); if (classtxt != NULL) { /* Look for the optional view name. */ viewtxt = next_token(lex, text); } if (classtxt == NULL) { rdclass = dns_rdataclass_in; } else { isc_textregion_t r; r.base = classtxt; r.length = strlen(classtxt); result = dns_rdataclass_fromtext(&rdclass, &r); if (result != ISC_R_SUCCESS) { if (viewtxt == NULL) { rdclass = dns_rdataclass_in; viewtxt = classtxt; result = ISC_R_SUCCESS; } else { snprintf(msg, sizeof(msg), "unknown class '%s'", classtxt); (void) putstr(text, msg); goto cleanup; } } } for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; view = ISC_LIST_NEXT(view, link)) { if (viewtxt != NULL && (rdclass != view->rdclass || strcmp(view->name, viewtxt) != 0)) continue; if (view->managed_keys == NULL) { if (viewtxt != NULL) { snprintf(msg, sizeof(msg), "view '%s': no managed keys", viewtxt); CHECK(putstr(text, msg)); goto cleanup; } else continue; } found = ISC_TRUE; switch (opt) { case REFRESH: CHECK(mkey_refresh(view, text)); break; case STATUS: if (!first) CHECK(putstr(text, "\n\n")); CHECK(mkey_status(view, text)); first = ISC_FALSE; break; case SYNC: CHECK(dns_zone_flush(view->managed_keys)); break; default: INSIST(0); } if (viewtxt != NULL) break; } if (!found) CHECK(putstr(text, "no views with managed keys")); cleanup: if (isc_buffer_usedlength(*text) > 0) (void) putnull(text); return (result); } isc_result_t ns_server_dnstap(ns_server_t *server, isc_lex_t *lex, isc_buffer_t **text) { #if HAVE_DNSTAP char *ptr; isc_result_t result; isc_boolean_t reopen = ISC_FALSE; int backups = 0; if (server->dtenv == NULL) return (ISC_R_NOTFOUND); /* Check the command name. */ ptr = next_token(lex, text); if (ptr == NULL) return (ISC_R_UNEXPECTEDEND); /* "dnstap-reopen" was used in 9.11.0b1 */ if (strcasecmp(ptr, "dnstap-reopen") == 0) { reopen = ISC_TRUE; } else { ptr = next_token(lex, text); if (ptr == NULL) return (ISC_R_UNEXPECTEDEND); } if (reopen || strcasecmp(ptr, "-reopen") == 0) { backups = -1; } else if ((strcasecmp(ptr, "-roll") == 0)) { unsigned int n; ptr = next_token(lex, text); if (ptr != NULL) { n = sscanf(ptr, "%u", &backups); if (n != 1U) return (ISC_R_BADNUMBER); } } else return (DNS_R_SYNTAX); result = isc_task_beginexclusive(server->task); RUNTIME_CHECK(result == ISC_R_SUCCESS); result = dns_dt_reopen(server->dtenv, backups); isc_task_endexclusive(server->task); return (result); #else UNUSED(server); UNUSED(lex); UNUSED(text); return (ISC_R_NOTIMPLEMENTED); #endif } bind9-9.11.3+dfsg/bin/named/sortlist.c000066400000000000000000000074511325250447100174260ustar00rootroot00000000000000/* * Copyright (C) 2000, 2001, 2004-2007, 2016 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* $Id: sortlist.c,v 1.17 2007/09/14 01:46:05 marka Exp $ */ /*! \file */ #include #include #include #include #include #include #include #include ns_sortlisttype_t ns_sortlist_setup(dns_acl_t *acl, isc_netaddr_t *clientaddr, const void **argp) { unsigned int i; if (acl == NULL) goto dont_sort; for (i = 0; i < acl->length; i++) { /* * 'e' refers to the current 'top level statement' * in the sortlist (see ARM). */ dns_aclelement_t *e = &acl->elements[i]; dns_aclelement_t *try_elt; dns_aclelement_t *order_elt = NULL; const dns_aclelement_t *matched_elt = NULL; if (e->type == dns_aclelementtype_nestedacl) { dns_acl_t *inner = e->nestedacl; if (inner->length == 0) try_elt = e; else if (inner->length > 2) goto dont_sort; else if (inner->elements[0].negative) goto dont_sort; else { try_elt = &inner->elements[0]; if (inner->length == 2) order_elt = &inner->elements[1]; } } else { /* * BIND 8 allows bare elements at the top level * as an undocumented feature. */ try_elt = e; } if (dns_aclelement_match(clientaddr, NULL, try_elt, &ns_g_server->aclenv, &matched_elt)) { if (order_elt != NULL) { if (order_elt->type == dns_aclelementtype_nestedacl) { *argp = order_elt->nestedacl; return (NS_SORTLISTTYPE_2ELEMENT); } else if (order_elt->type == dns_aclelementtype_localhost && ns_g_server->aclenv.localhost != NULL) { *argp = ns_g_server->aclenv.localhost; return (NS_SORTLISTTYPE_2ELEMENT); } else if (order_elt->type == dns_aclelementtype_localnets && ns_g_server->aclenv.localnets != NULL) { *argp = ns_g_server->aclenv.localnets; return (NS_SORTLISTTYPE_2ELEMENT); } else { /* * BIND 8 allows a bare IP prefix as * the 2nd element of a 2-element * sortlist statement. */ *argp = order_elt; return (NS_SORTLISTTYPE_1ELEMENT); } } else { INSIST(matched_elt != NULL); *argp = matched_elt; return (NS_SORTLISTTYPE_1ELEMENT); } } } /* No match; don't sort. */ dont_sort: *argp = NULL; return (NS_SORTLISTTYPE_NONE); } int ns_sortlist_addrorder2(const isc_netaddr_t *addr, const void *arg) { const dns_acl_t *sortacl = (const dns_acl_t *) arg; int match; (void)dns_acl_match(addr, NULL, sortacl, &ns_g_server->aclenv, &match, NULL); if (match > 0) return (match); else if (match < 0) return (INT_MAX - (-match)); else return (INT_MAX / 2); } int ns_sortlist_addrorder1(const isc_netaddr_t *addr, const void *arg) { const dns_aclelement_t *matchelt = (const dns_aclelement_t *) arg; if (dns_aclelement_match(addr, NULL, matchelt, &ns_g_server->aclenv, NULL)) { return (0); } else { return (INT_MAX); } } void ns_sortlist_byaddrsetup(dns_acl_t *sortlist_acl, isc_netaddr_t *client_addr, dns_addressorderfunc_t *orderp, const void **argp) { ns_sortlisttype_t sortlisttype; sortlisttype = ns_sortlist_setup(sortlist_acl, client_addr, argp); switch (sortlisttype) { case NS_SORTLISTTYPE_1ELEMENT: *orderp = ns_sortlist_addrorder1; break; case NS_SORTLISTTYPE_2ELEMENT: *orderp = ns_sortlist_addrorder2; break; case NS_SORTLISTTYPE_NONE: *orderp = NULL; break; default: UNEXPECTED_ERROR(__FILE__, __LINE__, "unexpected return from ns_sortlist_setup(): " "%d", sortlisttype); break; } } bind9-9.11.3+dfsg/bin/named/statschannel.c000066400000000000000000003637721325250447100202450ustar00rootroot00000000000000/* * Copyright (C) 2008-2017 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /*! \file */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "bind9.xsl.h" struct ns_statschannel { /* Unlocked */ isc_httpdmgr_t *httpdmgr; isc_sockaddr_t address; isc_mem_t *mctx; /* * Locked by channel lock: can be referenced and modified by both * the server task and the channel task. */ isc_mutex_t lock; dns_acl_t *acl; /* Locked by server task */ ISC_LINK(struct ns_statschannel) link; }; typedef struct stats_dumparg { isc_statsformat_t type; void *arg; /* type dependent argument */ int ncounters; /* for general statistics */ int *counterindices; /* for general statistics */ isc_uint64_t *countervalues; /* for general statistics */ isc_result_t result; } stats_dumparg_t; static isc_once_t once = ISC_ONCE_INIT; #if defined(HAVE_LIBXML2) || defined(HAVE_JSON) #define EXTENDED_STATS #else #undef EXTENDED_STATS #endif #ifdef EXTENDED_STATS static const char * user_zonetype( dns_zone_t *zone ) { dns_zonetype_t ztype; dns_view_t *view; static const struct zt { const dns_zonetype_t type; const char *const string; } typemap[] = { { dns_zone_none, "none" }, { dns_zone_master, "master" }, { dns_zone_slave, "slave" }, { dns_zone_stub, "stub" }, { dns_zone_staticstub, "static-stub" }, { dns_zone_key, "key" }, { dns_zone_dlz, "dlz" }, { dns_zone_redirect, "redirect" }, { 0, NULL } }; const struct zt *tp; if ((dns_zone_getoptions2(zone) & DNS_ZONEOPT2_AUTOEMPTY) != 0) return ("builtin"); view = dns_zone_getview(zone); if (view != NULL && strcmp(view->name, "_bind") == 0) return ("builtin"); ztype = dns_zone_gettype(zone); for (tp = typemap; tp->string != NULL && tp->type != ztype; tp++) /* empty */; return (tp->string); } #endif /*% * Statistics descriptions. These could be statistically initialized at * compile time, but we configure them run time in the init_desc() function * below so that they'll be less susceptible to counter name changes. */ static const char *nsstats_desc[dns_nsstatscounter_max]; static const char *resstats_desc[dns_resstatscounter_max]; static const char *adbstats_desc[dns_adbstats_max]; static const char *zonestats_desc[dns_zonestatscounter_max]; static const char *sockstats_desc[isc_sockstatscounter_max]; static const char *dnssecstats_desc[dns_dnssecstats_max]; static const char *udpinsizestats_desc[dns_sizecounter_in_max]; static const char *udpoutsizestats_desc[dns_sizecounter_out_max]; static const char *tcpinsizestats_desc[dns_sizecounter_in_max]; static const char *tcpoutsizestats_desc[dns_sizecounter_out_max]; static const char *dnstapstats_desc[dns_dnstapcounter_max]; #if defined(EXTENDED_STATS) static const char *nsstats_xmldesc[dns_nsstatscounter_max]; static const char *resstats_xmldesc[dns_resstatscounter_max]; static const char *adbstats_xmldesc[dns_adbstats_max]; static const char *zonestats_xmldesc[dns_zonestatscounter_max]; static const char *sockstats_xmldesc[isc_sockstatscounter_max]; static const char *dnssecstats_xmldesc[dns_dnssecstats_max]; static const char *udpinsizestats_xmldesc[dns_sizecounter_in_max]; static const char *udpoutsizestats_xmldesc[dns_sizecounter_out_max]; static const char *tcpinsizestats_xmldesc[dns_sizecounter_in_max]; static const char *tcpoutsizestats_xmldesc[dns_sizecounter_out_max]; static const char *dnstapstats_xmldesc[dns_dnstapcounter_max]; #else #define nsstats_xmldesc NULL #define resstats_xmldesc NULL #define adbstats_xmldesc NULL #define zonestats_xmldesc NULL #define sockstats_xmldesc NULL #define dnssecstats_xmldesc NULL #define udpinsizestats_xmldesc NULL #define udpoutsizestats_xmldesc NULL #define tcpinsizestats_xmldesc NULL #define tcpoutsizestats_xmldesc NULL #define dnstapstats_xmldesc NULL #endif /* EXTENDED_STATS */ #define TRY0(a) do { xmlrc = (a); if (xmlrc < 0) goto error; } while(0) /*% * Mapping arrays to represent statistics counters in the order of our * preference, regardless of the order of counter indices. For example, * nsstats_desc[nsstats_index[0]] will be the description that is shown first. */ static int nsstats_index[dns_nsstatscounter_max]; static int resstats_index[dns_resstatscounter_max]; static int adbstats_index[dns_adbstats_max]; static int zonestats_index[dns_zonestatscounter_max]; static int sockstats_index[isc_sockstatscounter_max]; static int dnssecstats_index[dns_dnssecstats_max]; static int udpinsizestats_index[dns_sizecounter_in_max]; static int udpoutsizestats_index[dns_sizecounter_out_max]; static int tcpinsizestats_index[dns_sizecounter_in_max]; static int tcpoutsizestats_index[dns_sizecounter_out_max]; static int dnstapstats_index[dns_dnstapcounter_max]; static inline void set_desc(int counter, int maxcounter, const char *fdesc, const char **fdescs, const char *xdesc, const char **xdescs) { REQUIRE(counter < maxcounter); REQUIRE(fdescs != NULL && fdescs[counter] == NULL); #if defined(EXTENDED_STATS) REQUIRE(xdescs != NULL && xdescs[counter] == NULL); #endif fdescs[counter] = fdesc; #if defined(EXTENDED_STATS) xdescs[counter] = xdesc; #else UNUSED(xdesc); UNUSED(xdescs); #endif } static void init_desc(void) { int i; /* Initialize name server statistics */ for (i = 0; i < dns_nsstatscounter_max; i++) nsstats_desc[i] = NULL; #if defined(EXTENDED_STATS) for (i = 0; i < dns_nsstatscounter_max; i++) nsstats_xmldesc[i] = NULL; #endif #define SET_NSSTATDESC(counterid, desc, xmldesc) \ do { \ set_desc(dns_nsstatscounter_ ## counterid, \ dns_nsstatscounter_max, \ desc, nsstats_desc, xmldesc, nsstats_xmldesc); \ nsstats_index[i++] = dns_nsstatscounter_ ## counterid; \ } while (0) i = 0; SET_NSSTATDESC(requestv4, "IPv4 requests received", "Requestv4"); SET_NSSTATDESC(requestv6, "IPv6 requests received", "Requestv6"); SET_NSSTATDESC(edns0in, "requests with EDNS(0) received", "ReqEdns0"); SET_NSSTATDESC(badednsver, "requests with unsupported EDNS version received", "ReqBadEDNSVer"); SET_NSSTATDESC(tsigin, "requests with TSIG received", "ReqTSIG"); SET_NSSTATDESC(sig0in, "requests with SIG(0) received", "ReqSIG0"); SET_NSSTATDESC(invalidsig, "requests with invalid signature", "ReqBadSIG"); SET_NSSTATDESC(requesttcp, "TCP requests received", "ReqTCP"); SET_NSSTATDESC(authrej, "auth queries rejected", "AuthQryRej"); SET_NSSTATDESC(recurserej, "recursive queries rejected", "RecQryRej"); SET_NSSTATDESC(xfrrej, "transfer requests rejected", "XfrRej"); SET_NSSTATDESC(updaterej, "update requests rejected", "UpdateRej"); SET_NSSTATDESC(response, "responses sent", "Response"); SET_NSSTATDESC(truncatedresp, "truncated responses sent", "TruncatedResp"); SET_NSSTATDESC(edns0out, "responses with EDNS(0) sent", "RespEDNS0"); SET_NSSTATDESC(tsigout, "responses with TSIG sent", "RespTSIG"); SET_NSSTATDESC(sig0out, "responses with SIG(0) sent", "RespSIG0"); SET_NSSTATDESC(success, "queries resulted in successful answer", "QrySuccess"); SET_NSSTATDESC(authans, "queries resulted in authoritative answer", "QryAuthAns"); SET_NSSTATDESC(nonauthans, "queries resulted in non authoritative answer", "QryNoauthAns"); SET_NSSTATDESC(referral, "queries resulted in referral answer", "QryReferral"); SET_NSSTATDESC(nxrrset, "queries resulted in nxrrset", "QryNxrrset"); SET_NSSTATDESC(servfail, "queries resulted in SERVFAIL", "QrySERVFAIL"); SET_NSSTATDESC(formerr, "queries resulted in FORMERR", "QryFORMERR"); SET_NSSTATDESC(nxdomain, "queries resulted in NXDOMAIN", "QryNXDOMAIN"); SET_NSSTATDESC(recursion, "queries caused recursion", "QryRecursion"); SET_NSSTATDESC(duplicate, "duplicate queries received", "QryDuplicate"); SET_NSSTATDESC(dropped, "queries dropped", "QryDropped"); SET_NSSTATDESC(failure, "other query failures", "QryFailure"); SET_NSSTATDESC(xfrdone, "requested transfers completed", "XfrReqDone"); SET_NSSTATDESC(updatereqfwd, "update requests forwarded", "UpdateReqFwd"); SET_NSSTATDESC(updaterespfwd, "update responses forwarded", "UpdateRespFwd"); SET_NSSTATDESC(updatefwdfail, "update forward failed", "UpdateFwdFail"); SET_NSSTATDESC(updatedone, "updates completed", "UpdateDone"); SET_NSSTATDESC(updatefail, "updates failed", "UpdateFail"); SET_NSSTATDESC(updatebadprereq, "updates rejected due to prerequisite failure", "UpdateBadPrereq"); SET_NSSTATDESC(recursclients, "recursing clients", "RecursClients"); SET_NSSTATDESC(dns64, "queries answered by DNS64", "DNS64"); SET_NSSTATDESC(ratedropped, "responses dropped for rate limits", "RateDropped"); SET_NSSTATDESC(rateslipped, "responses truncated for rate limits", "RateSlipped"); SET_NSSTATDESC(rpz_rewrites, "response policy zone rewrites", "RPZRewrites"); SET_NSSTATDESC(udp, "UDP queries received", "QryUDP"); SET_NSSTATDESC(tcp, "TCP queries received", "QryTCP"); SET_NSSTATDESC(nsidopt, "NSID option received", "NSIDOpt"); SET_NSSTATDESC(expireopt, "Expire option received", "ExpireOpt"); SET_NSSTATDESC(otheropt, "Other EDNS option received", "OtherOpt"); SET_NSSTATDESC(cookiein, "COOKIE option received", "CookieIn"); SET_NSSTATDESC(cookienew, "COOKIE - client only", "CookieNew"); SET_NSSTATDESC(cookiebadsize, "COOKIE - bad size", "CookieBadSize"); SET_NSSTATDESC(cookiebadtime, "COOKIE - bad time", "CookieBadTime"); SET_NSSTATDESC(cookienomatch, "COOKIE - no match", "CookieNoMatch"); SET_NSSTATDESC(cookiematch, "COOKIE - match", "CookieMatch"); SET_NSSTATDESC(ecsopt, "EDNS client subnet option received", "ECSOpt"); SET_NSSTATDESC(nxdomainredirect, "queries resulted in NXDOMAIN that were redirected", "QryNXRedir"); SET_NSSTATDESC(nxdomainredirect_rlookup, "queries resulted in NXDOMAIN that were redirected and " "resulted in a successful remote lookup", "QryNXRedirRLookup"); SET_NSSTATDESC(badcookie, "sent badcookie response", "QryBADCOOKIE"); SET_NSSTATDESC(keytagopt, "Keytag option received", "KeyTagOpt"); INSIST(i == dns_nsstatscounter_max); /* Initialize resolver statistics */ for (i = 0; i < dns_resstatscounter_max; i++) resstats_desc[i] = NULL; #if defined(EXTENDED_STATS) for (i = 0; i < dns_resstatscounter_max; i++) resstats_xmldesc[i] = NULL; #endif #define SET_RESSTATDESC(counterid, desc, xmldesc) \ do { \ set_desc(dns_resstatscounter_ ## counterid, \ dns_resstatscounter_max, \ desc, resstats_desc, xmldesc, resstats_xmldesc); \ resstats_index[i++] = dns_resstatscounter_ ## counterid; \ } while (0) i = 0; SET_RESSTATDESC(queryv4, "IPv4 queries sent", "Queryv4"); SET_RESSTATDESC(queryv6, "IPv6 queries sent", "Queryv6"); SET_RESSTATDESC(responsev4, "IPv4 responses received", "Responsev4"); SET_RESSTATDESC(responsev6, "IPv6 responses received", "Responsev6"); SET_RESSTATDESC(nxdomain, "NXDOMAIN received", "NXDOMAIN"); SET_RESSTATDESC(servfail, "SERVFAIL received", "SERVFAIL"); SET_RESSTATDESC(formerr, "FORMERR received", "FORMERR"); SET_RESSTATDESC(othererror, "other errors received", "OtherError"); SET_RESSTATDESC(edns0fail, "EDNS(0) query failures", "EDNS0Fail"); SET_RESSTATDESC(mismatch, "mismatch responses received", "Mismatch"); SET_RESSTATDESC(truncated, "truncated responses received", "Truncated"); SET_RESSTATDESC(lame, "lame delegations received", "Lame"); SET_RESSTATDESC(retry, "query retries", "Retry"); SET_RESSTATDESC(dispabort, "queries aborted due to quota", "QueryAbort"); SET_RESSTATDESC(dispsockfail, "failures in opening query sockets", "QuerySockFail"); SET_RESSTATDESC(disprequdp, "UDP queries in progress", "QueryCurUDP"); SET_RESSTATDESC(dispreqtcp, "TCP queries in progress", "QueryCurTCP"); SET_RESSTATDESC(querytimeout, "query timeouts", "QueryTimeout"); SET_RESSTATDESC(gluefetchv4, "IPv4 NS address fetches", "GlueFetchv4"); SET_RESSTATDESC(gluefetchv6, "IPv6 NS address fetches", "GlueFetchv6"); SET_RESSTATDESC(gluefetchv4fail, "IPv4 NS address fetch failed", "GlueFetchv4Fail"); SET_RESSTATDESC(gluefetchv6fail, "IPv6 NS address fetch failed", "GlueFetchv6Fail"); SET_RESSTATDESC(val, "DNSSEC validation attempted", "ValAttempt"); SET_RESSTATDESC(valsuccess, "DNSSEC validation succeeded", "ValOk"); SET_RESSTATDESC(valnegsuccess, "DNSSEC NX validation succeeded", "ValNegOk"); SET_RESSTATDESC(valfail, "DNSSEC validation failed", "ValFail"); SET_RESSTATDESC(queryrtt0, "queries with RTT < " DNS_RESOLVER_QRYRTTCLASS0STR "ms", "QryRTT" DNS_RESOLVER_QRYRTTCLASS0STR); SET_RESSTATDESC(queryrtt1, "queries with RTT " DNS_RESOLVER_QRYRTTCLASS0STR "-" DNS_RESOLVER_QRYRTTCLASS1STR "ms", "QryRTT" DNS_RESOLVER_QRYRTTCLASS1STR); SET_RESSTATDESC(queryrtt2, "queries with RTT " DNS_RESOLVER_QRYRTTCLASS1STR "-" DNS_RESOLVER_QRYRTTCLASS2STR "ms", "QryRTT" DNS_RESOLVER_QRYRTTCLASS2STR); SET_RESSTATDESC(queryrtt3, "queries with RTT " DNS_RESOLVER_QRYRTTCLASS2STR "-" DNS_RESOLVER_QRYRTTCLASS3STR "ms", "QryRTT" DNS_RESOLVER_QRYRTTCLASS3STR); SET_RESSTATDESC(queryrtt4, "queries with RTT " DNS_RESOLVER_QRYRTTCLASS3STR "-" DNS_RESOLVER_QRYRTTCLASS4STR "ms", "QryRTT" DNS_RESOLVER_QRYRTTCLASS4STR); SET_RESSTATDESC(queryrtt5, "queries with RTT > " DNS_RESOLVER_QRYRTTCLASS4STR "ms", "QryRTT" DNS_RESOLVER_QRYRTTCLASS4STR "+"); SET_RESSTATDESC(nfetch, "active fetches", "NumFetch"); SET_RESSTATDESC(buckets, "bucket size", "BucketSize"); SET_RESSTATDESC(refused, "REFUSED received", "REFUSED"); SET_RESSTATDESC(cookienew, "COOKIE send with client cookie only", "ClientCookieOut"); SET_RESSTATDESC(cookieout, "COOKIE sent with client and server cookie", "ServerCookieOut"); SET_RESSTATDESC(cookiein, "COOKIE replies received", "CookieIn"); SET_RESSTATDESC(cookieok, "COOKIE client ok", "CookieClientOk"); SET_RESSTATDESC(badvers, "bad EDNS version", "BadEDNSVersion"); SET_RESSTATDESC(badcookie, "bad cookie rcode", "BadCookieRcode"); SET_RESSTATDESC(zonequota, "spilled due to zone quota", "ZoneQuota"); SET_RESSTATDESC(serverquota, "spilled due to server quota", "ServerQuota"); SET_RESSTATDESC(nextitem, "waited for next item", "NextItem"); INSIST(i == dns_resstatscounter_max); /* Initialize adb statistics */ for (i = 0; i < dns_adbstats_max; i++) adbstats_desc[i] = NULL; #if defined(EXTENDED_STATS) for (i = 0; i < dns_adbstats_max; i++) adbstats_xmldesc[i] = NULL; #endif #define SET_ADBSTATDESC(id, desc, xmldesc) \ do { \ set_desc(dns_adbstats_ ## id, dns_adbstats_max, \ desc, adbstats_desc, xmldesc, adbstats_xmldesc); \ adbstats_index[i++] = dns_adbstats_ ## id; \ } while (0) i = 0; SET_ADBSTATDESC(nentries, "Address hash table size", "nentries"); SET_ADBSTATDESC(entriescnt, "Addresses in hash table", "entriescnt"); SET_ADBSTATDESC(nnames, "Name hash table size", "nnames"); SET_ADBSTATDESC(namescnt, "Names in hash table", "namescnt"); INSIST(i == dns_adbstats_max); /* Initialize zone statistics */ for (i = 0; i < dns_zonestatscounter_max; i++) zonestats_desc[i] = NULL; #if defined(EXTENDED_STATS) for (i = 0; i < dns_zonestatscounter_max; i++) zonestats_xmldesc[i] = NULL; #endif #define SET_ZONESTATDESC(counterid, desc, xmldesc) \ do { \ set_desc(dns_zonestatscounter_ ## counterid, \ dns_zonestatscounter_max, \ desc, zonestats_desc, xmldesc, zonestats_xmldesc); \ zonestats_index[i++] = dns_zonestatscounter_ ## counterid; \ } while (0) i = 0; SET_ZONESTATDESC(notifyoutv4, "IPv4 notifies sent", "NotifyOutv4"); SET_ZONESTATDESC(notifyoutv6, "IPv6 notifies sent", "NotifyOutv6"); SET_ZONESTATDESC(notifyinv4, "IPv4 notifies received", "NotifyInv4"); SET_ZONESTATDESC(notifyinv6, "IPv6 notifies received", "NotifyInv6"); SET_ZONESTATDESC(notifyrej, "notifies rejected", "NotifyRej"); SET_ZONESTATDESC(soaoutv4, "IPv4 SOA queries sent", "SOAOutv4"); SET_ZONESTATDESC(soaoutv6, "IPv6 SOA queries sent", "SOAOutv6"); SET_ZONESTATDESC(axfrreqv4, "IPv4 AXFR requested", "AXFRReqv4"); SET_ZONESTATDESC(axfrreqv6, "IPv6 AXFR requested", "AXFRReqv6"); SET_ZONESTATDESC(ixfrreqv4, "IPv4 IXFR requested", "IXFRReqv4"); SET_ZONESTATDESC(ixfrreqv6, "IPv6 IXFR requested", "IXFRReqv6"); SET_ZONESTATDESC(xfrsuccess, "transfer requests succeeded", "XfrSuccess"); SET_ZONESTATDESC(xfrfail, "transfer requests failed", "XfrFail"); INSIST(i == dns_zonestatscounter_max); /* Initialize socket statistics */ for (i = 0; i < isc_sockstatscounter_max; i++) sockstats_desc[i] = NULL; #if defined(EXTENDED_STATS) for (i = 0; i < isc_sockstatscounter_max; i++) sockstats_xmldesc[i] = NULL; #endif #define SET_SOCKSTATDESC(counterid, desc, xmldesc) \ do { \ set_desc(isc_sockstatscounter_ ## counterid, \ isc_sockstatscounter_max, \ desc, sockstats_desc, xmldesc, sockstats_xmldesc); \ sockstats_index[i++] = isc_sockstatscounter_ ## counterid; \ } while (0) i = 0; SET_SOCKSTATDESC(udp4open, "UDP/IPv4 sockets opened", "UDP4Open"); SET_SOCKSTATDESC(udp6open, "UDP/IPv6 sockets opened", "UDP6Open"); SET_SOCKSTATDESC(tcp4open, "TCP/IPv4 sockets opened", "TCP4Open"); SET_SOCKSTATDESC(tcp6open, "TCP/IPv6 sockets opened", "TCP6Open"); SET_SOCKSTATDESC(unixopen, "Unix domain sockets opened", "UnixOpen"); SET_SOCKSTATDESC(rawopen, "Raw sockets opened", "RawOpen"); SET_SOCKSTATDESC(udp4openfail, "UDP/IPv4 socket open failures", "UDP4OpenFail"); SET_SOCKSTATDESC(udp6openfail, "UDP/IPv6 socket open failures", "UDP6OpenFail"); SET_SOCKSTATDESC(tcp4openfail, "TCP/IPv4 socket open failures", "TCP4OpenFail"); SET_SOCKSTATDESC(tcp6openfail, "TCP/IPv6 socket open failures", "TCP6OpenFail"); SET_SOCKSTATDESC(unixopenfail, "Unix domain socket open failures", "UnixOpenFail"); SET_SOCKSTATDESC(rawopenfail, "Raw socket open failures", "RawOpenFail"); SET_SOCKSTATDESC(udp4close, "UDP/IPv4 sockets closed", "UDP4Close"); SET_SOCKSTATDESC(udp6close, "UDP/IPv6 sockets closed", "UDP6Close"); SET_SOCKSTATDESC(tcp4close, "TCP/IPv4 sockets closed", "TCP4Close"); SET_SOCKSTATDESC(tcp6close, "TCP/IPv6 sockets closed", "TCP6Close"); SET_SOCKSTATDESC(unixclose, "Unix domain sockets closed", "UnixClose"); SET_SOCKSTATDESC(fdwatchclose, "FDwatch sockets closed", "FDWatchClose"); SET_SOCKSTATDESC(rawclose, "Raw sockets closed", "RawClose"); SET_SOCKSTATDESC(udp4bindfail, "UDP/IPv4 socket bind failures", "UDP4BindFail"); SET_SOCKSTATDESC(udp6bindfail, "UDP/IPv6 socket bind failures", "UDP6BindFail"); SET_SOCKSTATDESC(tcp4bindfail, "TCP/IPv4 socket bind failures", "TCP4BindFail"); SET_SOCKSTATDESC(tcp6bindfail, "TCP/IPv6 socket bind failures", "TCP6BindFail"); SET_SOCKSTATDESC(unixbindfail, "Unix domain socket bind failures", "UnixBindFail"); SET_SOCKSTATDESC(fdwatchbindfail, "FDwatch socket bind failures", "FdwatchBindFail"); SET_SOCKSTATDESC(udp4connectfail, "UDP/IPv4 socket connect failures", "UDP4ConnFail"); SET_SOCKSTATDESC(udp6connectfail, "UDP/IPv6 socket connect failures", "UDP6ConnFail"); SET_SOCKSTATDESC(tcp4connectfail, "TCP/IPv4 socket connect failures", "TCP4ConnFail"); SET_SOCKSTATDESC(tcp6connectfail, "TCP/IPv6 socket connect failures", "TCP6ConnFail"); SET_SOCKSTATDESC(unixconnectfail, "Unix domain socket connect failures", "UnixConnFail"); SET_SOCKSTATDESC(fdwatchconnectfail, "FDwatch socket connect failures", "FDwatchConnFail"); SET_SOCKSTATDESC(udp4connect, "UDP/IPv4 connections established", "UDP4Conn"); SET_SOCKSTATDESC(udp6connect, "UDP/IPv6 connections established", "UDP6Conn"); SET_SOCKSTATDESC(tcp4connect, "TCP/IPv4 connections established", "TCP4Conn"); SET_SOCKSTATDESC(tcp6connect, "TCP/IPv6 connections established", "TCP6Conn"); SET_SOCKSTATDESC(unixconnect, "Unix domain connections established", "UnixConn"); SET_SOCKSTATDESC(fdwatchconnect, "FDwatch domain connections established", "FDwatchConn"); SET_SOCKSTATDESC(tcp4acceptfail, "TCP/IPv4 connection accept failures", "TCP4AcceptFail"); SET_SOCKSTATDESC(tcp6acceptfail, "TCP/IPv6 connection accept failures", "TCP6AcceptFail"); SET_SOCKSTATDESC(unixacceptfail, "Unix domain connection accept failures", "UnixAcceptFail"); SET_SOCKSTATDESC(tcp4accept, "TCP/IPv4 connections accepted", "TCP4Accept"); SET_SOCKSTATDESC(tcp6accept, "TCP/IPv6 connections accepted", "TCP6Accept"); SET_SOCKSTATDESC(unixaccept, "Unix domain connections accepted", "UnixAccept"); SET_SOCKSTATDESC(udp4sendfail, "UDP/IPv4 send errors", "UDP4SendErr"); SET_SOCKSTATDESC(udp6sendfail, "UDP/IPv6 send errors", "UDP6SendErr"); SET_SOCKSTATDESC(tcp4sendfail, "TCP/IPv4 send errors", "TCP4SendErr"); SET_SOCKSTATDESC(tcp6sendfail, "TCP/IPv6 send errors", "TCP6SendErr"); SET_SOCKSTATDESC(unixsendfail, "Unix domain send errors", "UnixSendErr"); SET_SOCKSTATDESC(fdwatchsendfail, "FDwatch send errors", "FDwatchSendErr"); SET_SOCKSTATDESC(udp4recvfail, "UDP/IPv4 recv errors", "UDP4RecvErr"); SET_SOCKSTATDESC(udp6recvfail, "UDP/IPv6 recv errors", "UDP6RecvErr"); SET_SOCKSTATDESC(tcp4recvfail, "TCP/IPv4 recv errors", "TCP4RecvErr"); SET_SOCKSTATDESC(tcp6recvfail, "TCP/IPv6 recv errors", "TCP6RecvErr"); SET_SOCKSTATDESC(unixrecvfail, "Unix domain recv errors", "UnixRecvErr"); SET_SOCKSTATDESC(fdwatchrecvfail, "FDwatch recv errors", "FDwatchRecvErr"); SET_SOCKSTATDESC(rawrecvfail, "Raw recv errors", "RawRecvErr"); SET_SOCKSTATDESC(udp4active, "UDP/IPv4 sockets active", "UDP4Active"); SET_SOCKSTATDESC(udp6active, "UDP/IPv6 sockets active", "UDP6Active"); SET_SOCKSTATDESC(tcp4active, "TCP/IPv4 sockets active", "TCP4Active"); SET_SOCKSTATDESC(tcp6active, "TCP/IPv6 sockets active", "TCP6Active"); SET_SOCKSTATDESC(unixactive, "Unix domain sockets active", "UnixActive"); SET_SOCKSTATDESC(rawactive, "Raw sockets active", "RawActive"); INSIST(i == isc_sockstatscounter_max); /* Initialize DNSSEC statistics */ for (i = 0; i < dns_dnssecstats_max; i++) dnssecstats_desc[i] = NULL; #if defined(EXTENDED_STATS) for (i = 0; i < dns_dnssecstats_max; i++) dnssecstats_xmldesc[i] = NULL; #endif #define SET_DNSSECSTATDESC(counterid, desc, xmldesc) \ do { \ set_desc(dns_dnssecstats_ ## counterid, \ dns_dnssecstats_max, \ desc, dnssecstats_desc, \ xmldesc, dnssecstats_xmldesc); \ dnssecstats_index[i++] = dns_dnssecstats_ ## counterid; \ } while (0) i = 0; SET_DNSSECSTATDESC(asis, "dnssec validation success with signer " "\"as is\"", "DNSSECasis"); SET_DNSSECSTATDESC(downcase, "dnssec validation success with signer " "lower cased", "DNSSECdowncase"); SET_DNSSECSTATDESC(wildcard, "dnssec validation of wildcard signature", "DNSSECwild"); SET_DNSSECSTATDESC(fail, "dnssec validation failures", "DNSSECfail"); INSIST(i == dns_dnssecstats_max); /* Initialize dnstap statistics */ for (i = 0; i < dns_dnstapcounter_max; i++) dnstapstats_desc[i] = NULL; #if defined(EXTENDED_STATS) for (i = 0; i < dns_dnstapcounter_max; i++) dnstapstats_xmldesc[i] = NULL; #endif #define SET_DNSTAPSTATDESC(counterid, desc, xmldesc) \ do { \ set_desc(dns_dnstapcounter_ ## counterid, \ dns_dnstapcounter_max, \ desc, dnstapstats_desc, \ xmldesc, dnstapstats_xmldesc); \ dnstapstats_index[i++] = dns_dnstapcounter_ ## counterid; \ } while (0) i = 0; SET_DNSTAPSTATDESC(success, "dnstap messges written", "DNSTAPsuccess"); SET_DNSTAPSTATDESC(drop, "dnstap messages dropped", "DNSTAPdropped"); INSIST(i == dns_dnstapcounter_max); /* Sanity check */ for (i = 0; i < dns_nsstatscounter_max; i++) INSIST(nsstats_desc[i] != NULL); for (i = 0; i < dns_resstatscounter_max; i++) INSIST(resstats_desc[i] != NULL); for (i = 0; i < dns_adbstats_max; i++) INSIST(adbstats_desc[i] != NULL); for (i = 0; i < dns_zonestatscounter_max; i++) INSIST(zonestats_desc[i] != NULL); for (i = 0; i < isc_sockstatscounter_max; i++) INSIST(sockstats_desc[i] != NULL); for (i = 0; i < dns_dnssecstats_max; i++) INSIST(dnssecstats_desc[i] != NULL); for (i = 0; i < dns_dnstapcounter_max; i++) INSIST(dnstapstats_desc[i] != NULL); #if defined(EXTENDED_STATS) for (i = 0; i < dns_nsstatscounter_max; i++) INSIST(nsstats_xmldesc[i] != NULL); for (i = 0; i < dns_resstatscounter_max; i++) INSIST(resstats_xmldesc[i] != NULL); for (i = 0; i < dns_adbstats_max; i++) INSIST(adbstats_xmldesc[i] != NULL); for (i = 0; i < dns_zonestatscounter_max; i++) INSIST(zonestats_xmldesc[i] != NULL); for (i = 0; i < isc_sockstatscounter_max; i++) INSIST(sockstats_xmldesc[i] != NULL); for (i = 0; i < dns_dnssecstats_max; i++) INSIST(dnssecstats_xmldesc[i] != NULL); for (i = 0; i < dns_dnstapcounter_max; i++) INSIST(dnstapstats_xmldesc[i] != NULL); #endif /* Initialize traffic size statistics */ for (i = 0; i < dns_sizecounter_in_max; i++) { udpinsizestats_desc[i] = NULL; tcpinsizestats_desc[i] = NULL; #if defined(EXTENDED_STATS) udpinsizestats_xmldesc[i] = NULL; tcpinsizestats_xmldesc[i] = NULL; #endif } for (i = 0; i < dns_sizecounter_out_max; i++) { udpoutsizestats_desc[i] = NULL; tcpoutsizestats_desc[i] = NULL; #if defined(EXTENDED_STATS) udpoutsizestats_xmldesc[i] = NULL; tcpoutsizestats_xmldesc[i] = NULL; #endif } #define SET_SIZESTATDESC(counterid, desc, xmldesc, inout) \ do { \ set_desc(dns_sizecounter_ ## inout ## _ ## counterid, \ dns_sizecounter_ ## inout ## _max, \ desc, udp ## inout ## sizestats_desc, \ xmldesc, udp ## inout ## sizestats_xmldesc); \ set_desc(dns_sizecounter_ ## inout ## _ ## counterid, \ dns_sizecounter_ ## inout ## _max, \ desc, tcp ## inout ## sizestats_desc, \ xmldesc, tcp ## inout ## sizestats_xmldesc); \ udp ## inout ## sizestats_index[i] = dns_sizecounter_ ## inout ## _ ## counterid; \ tcp ## inout ## sizestats_index[i] = dns_sizecounter_ ## inout ## _ ## counterid; \ i++; \ } while (0) i = 0; SET_SIZESTATDESC(0, "requests received 0-15 bytes", "0-15", in); SET_SIZESTATDESC(16, "requests received 16-31 bytes", "16-31", in); SET_SIZESTATDESC(32, "requests received 32-47 bytes", "32-47", in); SET_SIZESTATDESC(48, "requests received 48-63 bytes", "48-63", in); SET_SIZESTATDESC(64, "requests received 64-79 bytes", "64-79", in); SET_SIZESTATDESC(80, "requests received 80-95 bytes", "80-95", in); SET_SIZESTATDESC(96, "requests received 96-111 bytes", "96-111", in); SET_SIZESTATDESC(112, "requests received 112-127 bytes", "112-127", in); SET_SIZESTATDESC(128, "requests received 128-143 bytes", "128-143", in); SET_SIZESTATDESC(144, "requests received 144-159 bytes", "144-159", in); SET_SIZESTATDESC(160, "requests received 160-175 bytes", "160-175", in); SET_SIZESTATDESC(176, "requests received 176-191 bytes", "176-191", in); SET_SIZESTATDESC(192, "requests received 192-207 bytes", "192-207", in); SET_SIZESTATDESC(208, "requests received 208-223 bytes", "208-223", in); SET_SIZESTATDESC(224, "requests received 224-239 bytes", "224-239", in); SET_SIZESTATDESC(240, "requests received 240-255 bytes", "240-255", in); SET_SIZESTATDESC(256, "requests received 256-271 bytes", "256-271", in); SET_SIZESTATDESC(272, "requests received 272-287 bytes", "272-287", in); SET_SIZESTATDESC(288, "requests received 288+ bytes", "288+", in); INSIST(i == dns_sizecounter_in_max); i = 0; SET_SIZESTATDESC(0, "responses sent 0-15 bytes", "0-15", out); SET_SIZESTATDESC(16, "responses sent 16-31 bytes", "16-31", out); SET_SIZESTATDESC(32, "responses sent 32-47 bytes", "32-47", out); SET_SIZESTATDESC(48, "responses sent 48-63 bytes", "48-63", out); SET_SIZESTATDESC(64, "responses sent 64-79 bytes", "64-79", out); SET_SIZESTATDESC(80, "responses sent 80-95 bytes", "80-95", out); SET_SIZESTATDESC(96, "responses sent 96-111 bytes", "96-111", out); SET_SIZESTATDESC(112, "responses sent 112-127 bytes", "112-127", out); SET_SIZESTATDESC(128, "responses sent 128-143 bytes", "128-143", out); SET_SIZESTATDESC(144, "responses sent 144-159 bytes", "144-159", out); SET_SIZESTATDESC(160, "responses sent 160-175 bytes", "160-175", out); SET_SIZESTATDESC(176, "responses sent 176-191 bytes", "176-191", out); SET_SIZESTATDESC(192, "responses sent 192-207 bytes", "192-207", out); SET_SIZESTATDESC(208, "responses sent 208-223 bytes", "208-223", out); SET_SIZESTATDESC(224, "responses sent 224-239 bytes", "224-239", out); SET_SIZESTATDESC(240, "responses sent 240-255 bytes", "240-255", out); SET_SIZESTATDESC(256, "responses sent 256-271 bytes", "256-271", out); SET_SIZESTATDESC(272, "responses sent 272-287 bytes", "272-287", out); SET_SIZESTATDESC(288, "responses sent 288-303 bytes", "288-303", out); SET_SIZESTATDESC(304, "responses sent 304-319 bytes", "304-319", out); SET_SIZESTATDESC(320, "responses sent 320-335 bytes", "320-335", out); SET_SIZESTATDESC(336, "responses sent 336-351 bytes", "336-351", out); SET_SIZESTATDESC(352, "responses sent 352-367 bytes", "352-367", out); SET_SIZESTATDESC(368, "responses sent 368-383 bytes", "368-383", out); SET_SIZESTATDESC(384, "responses sent 384-399 bytes", "384-399", out); SET_SIZESTATDESC(400, "responses sent 400-415 bytes", "400-415", out); SET_SIZESTATDESC(416, "responses sent 416-431 bytes", "416-431", out); SET_SIZESTATDESC(432, "responses sent 432-447 bytes", "432-447", out); SET_SIZESTATDESC(448, "responses sent 448-463 bytes", "448-463", out); SET_SIZESTATDESC(464, "responses sent 464-479 bytes", "464-479", out); SET_SIZESTATDESC(480, "responses sent 480-495 bytes", "480-495", out); SET_SIZESTATDESC(496, "responses sent 496-511 bytes", "496-511", out); SET_SIZESTATDESC(512, "responses sent 512-527 bytes", "512-527", out); SET_SIZESTATDESC(528, "responses sent 528-543 bytes", "528-543", out); SET_SIZESTATDESC(544, "responses sent 544-559 bytes", "544-559", out); SET_SIZESTATDESC(560, "responses sent 560-575 bytes", "560-575", out); SET_SIZESTATDESC(576, "responses sent 576-591 bytes", "576-591", out); SET_SIZESTATDESC(592, "responses sent 592-607 bytes", "592-607", out); SET_SIZESTATDESC(608, "responses sent 608-623 bytes", "608-623", out); SET_SIZESTATDESC(624, "responses sent 624-639 bytes", "624-639", out); SET_SIZESTATDESC(640, "responses sent 640-655 bytes", "640-655", out); SET_SIZESTATDESC(656, "responses sent 656-671 bytes", "656-671", out); SET_SIZESTATDESC(672, "responses sent 672-687 bytes", "672-687", out); SET_SIZESTATDESC(688, "responses sent 688-703 bytes", "688-703", out); SET_SIZESTATDESC(704, "responses sent 704-719 bytes", "704-719", out); SET_SIZESTATDESC(720, "responses sent 720-735 bytes", "720-735", out); SET_SIZESTATDESC(736, "responses sent 736-751 bytes", "736-751", out); SET_SIZESTATDESC(752, "responses sent 752-767 bytes", "752-767", out); SET_SIZESTATDESC(768, "responses sent 768-783 bytes", "768-783", out); SET_SIZESTATDESC(784, "responses sent 784-799 bytes", "784-799", out); SET_SIZESTATDESC(800, "responses sent 800-815 bytes", "800-815", out); SET_SIZESTATDESC(816, "responses sent 816-831 bytes", "816-831", out); SET_SIZESTATDESC(832, "responses sent 832-847 bytes", "832-847", out); SET_SIZESTATDESC(848, "responses sent 848-863 bytes", "848-863", out); SET_SIZESTATDESC(864, "responses sent 864-879 bytes", "864-879", out); SET_SIZESTATDESC(880, "responses sent 880-895 bytes", "880-895", out); SET_SIZESTATDESC(896, "responses sent 896-911 bytes", "896-911", out); SET_SIZESTATDESC(912, "responses sent 912-927 bytes", "912-927", out); SET_SIZESTATDESC(928, "responses sent 928-943 bytes", "928-943", out); SET_SIZESTATDESC(944, "responses sent 944-959 bytes", "944-959", out); SET_SIZESTATDESC(960, "responses sent 960-975 bytes", "960-975", out); SET_SIZESTATDESC(976, "responses sent 976-991 bytes", "976-991", out); SET_SIZESTATDESC(992, "responses sent 992-1007 bytes", "992-1007", out); SET_SIZESTATDESC(1008, "responses sent 1008-1023 bytes", "1008-1023", out); SET_SIZESTATDESC(1024, "responses sent 1024-1039 bytes", "1024-1039", out); SET_SIZESTATDESC(1040, "responses sent 1040-1055 bytes", "1040-1055", out); SET_SIZESTATDESC(1056, "responses sent 1056-1071 bytes", "1056-1071", out); SET_SIZESTATDESC(1072, "responses sent 1072-1087 bytes", "1072-1087", out); SET_SIZESTATDESC(1088, "responses sent 1088-1103 bytes", "1088-1103", out); SET_SIZESTATDESC(1104, "responses sent 1104-1119 bytes", "1104-1119", out); SET_SIZESTATDESC(1120, "responses sent 1120-1135 bytes", "1120-1135", out); SET_SIZESTATDESC(1136, "responses sent 1136-1151 bytes", "1136-1151", out); SET_SIZESTATDESC(1152, "responses sent 1152-1167 bytes", "1152-1167", out); SET_SIZESTATDESC(1168, "responses sent 1168-1183 bytes", "1168-1183", out); SET_SIZESTATDESC(1184, "responses sent 1184-1199 bytes", "1184-1199", out); SET_SIZESTATDESC(1200, "responses sent 1200-1215 bytes", "1200-1215", out); SET_SIZESTATDESC(1216, "responses sent 1216-1231 bytes", "1216-1231", out); SET_SIZESTATDESC(1232, "responses sent 1232-1247 bytes", "1232-1247", out); SET_SIZESTATDESC(1248, "responses sent 1248-1263 bytes", "1248-1263", out); SET_SIZESTATDESC(1264, "responses sent 1264-1279 bytes", "1264-1279", out); SET_SIZESTATDESC(1280, "responses sent 1280-1295 bytes", "1280-1295", out); SET_SIZESTATDESC(1296, "responses sent 1296-1311 bytes", "1296-1311", out); SET_SIZESTATDESC(1312, "responses sent 1312-1327 bytes", "1312-1327", out); SET_SIZESTATDESC(1328, "responses sent 1328-1343 bytes", "1328-1343", out); SET_SIZESTATDESC(1344, "responses sent 1344-1359 bytes", "1344-1359", out); SET_SIZESTATDESC(1360, "responses sent 1360-1375 bytes", "1360-1375", out); SET_SIZESTATDESC(1376, "responses sent 1376-1391 bytes", "1376-1391", out); SET_SIZESTATDESC(1392, "responses sent 1392-1407 bytes", "1392-1407", out); SET_SIZESTATDESC(1408, "responses sent 1408-1423 bytes", "1408-1423", out); SET_SIZESTATDESC(1424, "responses sent 1424-1439 bytes", "1424-1439", out); SET_SIZESTATDESC(1440, "responses sent 1440-1455 bytes", "1440-1455", out); SET_SIZESTATDESC(1456, "responses sent 1456-1471 bytes", "1456-1471", out); SET_SIZESTATDESC(1472, "responses sent 1472-1487 bytes", "1472-1487", out); SET_SIZESTATDESC(1488, "responses sent 1488-1503 bytes", "1488-1503", out); SET_SIZESTATDESC(1504, "responses sent 1504-1519 bytes", "1504-1519", out); SET_SIZESTATDESC(1520, "responses sent 1520-1535 bytes", "1520-1535", out); SET_SIZESTATDESC(1536, "responses sent 1536-1551 bytes", "1536-1551", out); SET_SIZESTATDESC(1552, "responses sent 1552-1567 bytes", "1552-1567", out); SET_SIZESTATDESC(1568, "responses sent 1568-1583 bytes", "1568-1583", out); SET_SIZESTATDESC(1584, "responses sent 1584-1599 bytes", "1584-1599", out); SET_SIZESTATDESC(1600, "responses sent 1600-1615 bytes", "1600-1615", out); SET_SIZESTATDESC(1616, "responses sent 1616-1631 bytes", "1616-1631", out); SET_SIZESTATDESC(1632, "responses sent 1632-1647 bytes", "1632-1647", out); SET_SIZESTATDESC(1648, "responses sent 1648-1663 bytes", "1648-1663", out); SET_SIZESTATDESC(1664, "responses sent 1664-1679 bytes", "1664-1679", out); SET_SIZESTATDESC(1680, "responses sent 1680-1695 bytes", "1680-1695", out); SET_SIZESTATDESC(1696, "responses sent 1696-1711 bytes", "1696-1711", out); SET_SIZESTATDESC(1712, "responses sent 1712-1727 bytes", "1712-1727", out); SET_SIZESTATDESC(1728, "responses sent 1728-1743 bytes", "1728-1743", out); SET_SIZESTATDESC(1744, "responses sent 1744-1759 bytes", "1744-1759", out); SET_SIZESTATDESC(1760, "responses sent 1760-1775 bytes", "1760-1775", out); SET_SIZESTATDESC(1776, "responses sent 1776-1791 bytes", "1776-1791", out); SET_SIZESTATDESC(1792, "responses sent 1792-1807 bytes", "1792-1807", out); SET_SIZESTATDESC(1808, "responses sent 1808-1823 bytes", "1808-1823", out); SET_SIZESTATDESC(1824, "responses sent 1824-1839 bytes", "1824-1839", out); SET_SIZESTATDESC(1840, "responses sent 1840-1855 bytes", "1840-1855", out); SET_SIZESTATDESC(1856, "responses sent 1856-1871 bytes", "1856-1871", out); SET_SIZESTATDESC(1872, "responses sent 1872-1887 bytes", "1872-1887", out); SET_SIZESTATDESC(1888, "responses sent 1888-1903 bytes", "1888-1903", out); SET_SIZESTATDESC(1904, "responses sent 1904-1919 bytes", "1904-1919", out); SET_SIZESTATDESC(1920, "responses sent 1920-1935 bytes", "1920-1935", out); SET_SIZESTATDESC(1936, "responses sent 1936-1951 bytes", "1936-1951", out); SET_SIZESTATDESC(1952, "responses sent 1952-1967 bytes", "1952-1967", out); SET_SIZESTATDESC(1968, "responses sent 1968-1983 bytes", "1968-1983", out); SET_SIZESTATDESC(1984, "responses sent 1984-1999 bytes", "1984-1999", out); SET_SIZESTATDESC(2000, "responses sent 2000-2015 bytes", "2000-2015", out); SET_SIZESTATDESC(2016, "responses sent 2016-2031 bytes", "2016-2031", out); SET_SIZESTATDESC(2032, "responses sent 2032-2047 bytes", "2032-2047", out); SET_SIZESTATDESC(2048, "responses sent 2048-2063 bytes", "2048-2063", out); SET_SIZESTATDESC(2064, "responses sent 2064-2079 bytes", "2064-2079", out); SET_SIZESTATDESC(2080, "responses sent 2080-2095 bytes", "2080-2095", out); SET_SIZESTATDESC(2096, "responses sent 2096-2111 bytes", "2096-2111", out); SET_SIZESTATDESC(2112, "responses sent 2112-2127 bytes", "2112-2127", out); SET_SIZESTATDESC(2128, "responses sent 2128-2143 bytes", "2128-2143", out); SET_SIZESTATDESC(2144, "responses sent 2144-2159 bytes", "2144-2159", out); SET_SIZESTATDESC(2160, "responses sent 2160-2175 bytes", "2160-2175", out); SET_SIZESTATDESC(2176, "responses sent 2176-2191 bytes", "2176-2191", out); SET_SIZESTATDESC(2192, "responses sent 2192-2207 bytes", "2192-2207", out); SET_SIZESTATDESC(2208, "responses sent 2208-2223 bytes", "2208-2223", out); SET_SIZESTATDESC(2224, "responses sent 2224-2239 bytes", "2224-2239", out); SET_SIZESTATDESC(2240, "responses sent 2240-2255 bytes", "2240-2255", out); SET_SIZESTATDESC(2256, "responses sent 2256-2271 bytes", "2256-2271", out); SET_SIZESTATDESC(2272, "responses sent 2272-2287 bytes", "2272-2287", out); SET_SIZESTATDESC(2288, "responses sent 2288-2303 bytes", "2288-2303", out); SET_SIZESTATDESC(2304, "responses sent 2304-2319 bytes", "2304-2319", out); SET_SIZESTATDESC(2320, "responses sent 2320-2335 bytes", "2320-2335", out); SET_SIZESTATDESC(2336, "responses sent 2336-2351 bytes", "2336-2351", out); SET_SIZESTATDESC(2352, "responses sent 2352-2367 bytes", "2352-2367", out); SET_SIZESTATDESC(2368, "responses sent 2368-2383 bytes", "2368-2383", out); SET_SIZESTATDESC(2384, "responses sent 2384-2399 bytes", "2384-2399", out); SET_SIZESTATDESC(2400, "responses sent 2400-2415 bytes", "2400-2415", out); SET_SIZESTATDESC(2416, "responses sent 2416-2431 bytes", "2416-2431", out); SET_SIZESTATDESC(2432, "responses sent 2432-2447 bytes", "2432-2447", out); SET_SIZESTATDESC(2448, "responses sent 2448-2463 bytes", "2448-2463", out); SET_SIZESTATDESC(2464, "responses sent 2464-2479 bytes", "2464-2479", out); SET_SIZESTATDESC(2480, "responses sent 2480-2495 bytes", "2480-2495", out); SET_SIZESTATDESC(2496, "responses sent 2496-2511 bytes", "2496-2511", out); SET_SIZESTATDESC(2512, "responses sent 2512-2527 bytes", "2512-2527", out); SET_SIZESTATDESC(2528, "responses sent 2528-2543 bytes", "2528-2543", out); SET_SIZESTATDESC(2544, "responses sent 2544-2559 bytes", "2544-2559", out); SET_SIZESTATDESC(2560, "responses sent 2560-2575 bytes", "2560-2575", out); SET_SIZESTATDESC(2576, "responses sent 2576-2591 bytes", "2576-2591", out); SET_SIZESTATDESC(2592, "responses sent 2592-2607 bytes", "2592-2607", out); SET_SIZESTATDESC(2608, "responses sent 2608-2623 bytes", "2608-2623", out); SET_SIZESTATDESC(2624, "responses sent 2624-2639 bytes", "2624-2639", out); SET_SIZESTATDESC(2640, "responses sent 2640-2655 bytes", "2640-2655", out); SET_SIZESTATDESC(2656, "responses sent 2656-2671 bytes", "2656-2671", out); SET_SIZESTATDESC(2672, "responses sent 2672-2687 bytes", "2672-2687", out); SET_SIZESTATDESC(2688, "responses sent 2688-2703 bytes", "2688-2703", out); SET_SIZESTATDESC(2704, "responses sent 2704-2719 bytes", "2704-2719", out); SET_SIZESTATDESC(2720, "responses sent 2720-2735 bytes", "2720-2735", out); SET_SIZESTATDESC(2736, "responses sent 2736-2751 bytes", "2736-2751", out); SET_SIZESTATDESC(2752, "responses sent 2752-2767 bytes", "2752-2767", out); SET_SIZESTATDESC(2768, "responses sent 2768-2783 bytes", "2768-2783", out); SET_SIZESTATDESC(2784, "responses sent 2784-2799 bytes", "2784-2799", out); SET_SIZESTATDESC(2800, "responses sent 2800-2815 bytes", "2800-2815", out); SET_SIZESTATDESC(2816, "responses sent 2816-2831 bytes", "2816-2831", out); SET_SIZESTATDESC(2832, "responses sent 2832-2847 bytes", "2832-2847", out); SET_SIZESTATDESC(2848, "responses sent 2848-2863 bytes", "2848-2863", out); SET_SIZESTATDESC(2864, "responses sent 2864-2879 bytes", "2864-2879", out); SET_SIZESTATDESC(2880, "responses sent 2880-2895 bytes", "2880-2895", out); SET_SIZESTATDESC(2896, "responses sent 2896-2911 bytes", "2896-2911", out); SET_SIZESTATDESC(2912, "responses sent 2912-2927 bytes", "2912-2927", out); SET_SIZESTATDESC(2928, "responses sent 2928-2943 bytes", "2928-2943", out); SET_SIZESTATDESC(2944, "responses sent 2944-2959 bytes", "2944-2959", out); SET_SIZESTATDESC(2960, "responses sent 2960-2975 bytes", "2960-2975", out); SET_SIZESTATDESC(2976, "responses sent 2976-2991 bytes", "2976-2991", out); SET_SIZESTATDESC(2992, "responses sent 2992-3007 bytes", "2992-3007", out); SET_SIZESTATDESC(3008, "responses sent 3008-3023 bytes", "3008-3023", out); SET_SIZESTATDESC(3024, "responses sent 3024-3039 bytes", "3024-3039", out); SET_SIZESTATDESC(3040, "responses sent 3040-3055 bytes", "3040-3055", out); SET_SIZESTATDESC(3056, "responses sent 3056-3071 bytes", "3056-3071", out); SET_SIZESTATDESC(3072, "responses sent 3072-3087 bytes", "3072-3087", out); SET_SIZESTATDESC(3088, "responses sent 3088-3103 bytes", "3088-3103", out); SET_SIZESTATDESC(3104, "responses sent 3104-3119 bytes", "3104-3119", out); SET_SIZESTATDESC(3120, "responses sent 3120-3135 bytes", "3120-3135", out); SET_SIZESTATDESC(3136, "responses sent 3136-3151 bytes", "3136-3151", out); SET_SIZESTATDESC(3152, "responses sent 3152-3167 bytes", "3152-3167", out); SET_SIZESTATDESC(3168, "responses sent 3168-3183 bytes", "3168-3183", out); SET_SIZESTATDESC(3184, "responses sent 3184-3199 bytes", "3184-3199", out); SET_SIZESTATDESC(3200, "responses sent 3200-3215 bytes", "3200-3215", out); SET_SIZESTATDESC(3216, "responses sent 3216-3231 bytes", "3216-3231", out); SET_SIZESTATDESC(3232, "responses sent 3232-3247 bytes", "3232-3247", out); SET_SIZESTATDESC(3248, "responses sent 3248-3263 bytes", "3248-3263", out); SET_SIZESTATDESC(3264, "responses sent 3264-3279 bytes", "3264-3279", out); SET_SIZESTATDESC(3280, "responses sent 3280-3295 bytes", "3280-3295", out); SET_SIZESTATDESC(3296, "responses sent 3296-3311 bytes", "3296-3311", out); SET_SIZESTATDESC(3312, "responses sent 3312-3327 bytes", "3312-3327", out); SET_SIZESTATDESC(3328, "responses sent 3328-3343 bytes", "3328-3343", out); SET_SIZESTATDESC(3344, "responses sent 3344-3359 bytes", "3344-3359", out); SET_SIZESTATDESC(3360, "responses sent 3360-3375 bytes", "3360-3375", out); SET_SIZESTATDESC(3376, "responses sent 3376-3391 bytes", "3376-3391", out); SET_SIZESTATDESC(3392, "responses sent 3392-3407 bytes", "3392-3407", out); SET_SIZESTATDESC(3408, "responses sent 3408-3423 bytes", "3408-3423", out); SET_SIZESTATDESC(3424, "responses sent 3424-3439 bytes", "3424-3439", out); SET_SIZESTATDESC(3440, "responses sent 3440-3455 bytes", "3440-3455", out); SET_SIZESTATDESC(3456, "responses sent 3456-3471 bytes", "3456-3471", out); SET_SIZESTATDESC(3472, "responses sent 3472-3487 bytes", "3472-3487", out); SET_SIZESTATDESC(3488, "responses sent 3488-3503 bytes", "3488-3503", out); SET_SIZESTATDESC(3504, "responses sent 3504-3519 bytes", "3504-3519", out); SET_SIZESTATDESC(3520, "responses sent 3520-3535 bytes", "3520-3535", out); SET_SIZESTATDESC(3536, "responses sent 3536-3551 bytes", "3536-3551", out); SET_SIZESTATDESC(3552, "responses sent 3552-3567 bytes", "3552-3567", out); SET_SIZESTATDESC(3568, "responses sent 3568-3583 bytes", "3568-3583", out); SET_SIZESTATDESC(3584, "responses sent 3584-3599 bytes", "3584-3599", out); SET_SIZESTATDESC(3600, "responses sent 3600-3615 bytes", "3600-3615", out); SET_SIZESTATDESC(3616, "responses sent 3616-3631 bytes", "3616-3631", out); SET_SIZESTATDESC(3632, "responses sent 3632-3647 bytes", "3632-3647", out); SET_SIZESTATDESC(3648, "responses sent 3648-3663 bytes", "3648-3663", out); SET_SIZESTATDESC(3664, "responses sent 3664-3679 bytes", "3664-3679", out); SET_SIZESTATDESC(3680, "responses sent 3680-3695 bytes", "3680-3695", out); SET_SIZESTATDESC(3696, "responses sent 3696-3711 bytes", "3696-3711", out); SET_SIZESTATDESC(3712, "responses sent 3712-3727 bytes", "3712-3727", out); SET_SIZESTATDESC(3728, "responses sent 3728-3743 bytes", "3728-3743", out); SET_SIZESTATDESC(3744, "responses sent 3744-3759 bytes", "3744-3759", out); SET_SIZESTATDESC(3760, "responses sent 3760-3775 bytes", "3760-3775", out); SET_SIZESTATDESC(3776, "responses sent 3776-3791 bytes", "3776-3791", out); SET_SIZESTATDESC(3792, "responses sent 3792-3807 bytes", "3792-3807", out); SET_SIZESTATDESC(3808, "responses sent 3808-3823 bytes", "3808-3823", out); SET_SIZESTATDESC(3824, "responses sent 3824-3839 bytes", "3824-3839", out); SET_SIZESTATDESC(3840, "responses sent 3840-3855 bytes", "3840-3855", out); SET_SIZESTATDESC(3856, "responses sent 3856-3871 bytes", "3856-3871", out); SET_SIZESTATDESC(3872, "responses sent 3872-3887 bytes", "3872-3887", out); SET_SIZESTATDESC(3888, "responses sent 3888-3903 bytes", "3888-3903", out); SET_SIZESTATDESC(3904, "responses sent 3904-3919 bytes", "3904-3919", out); SET_SIZESTATDESC(3920, "responses sent 3920-3935 bytes", "3920-3935", out); SET_SIZESTATDESC(3936, "responses sent 3936-3951 bytes", "3936-3951", out); SET_SIZESTATDESC(3952, "responses sent 3952-3967 bytes", "3952-3967", out); SET_SIZESTATDESC(3968, "responses sent 3968-3983 bytes", "3968-3983", out); SET_SIZESTATDESC(3984, "responses sent 3984-3999 bytes", "3984-3999", out); SET_SIZESTATDESC(4000, "responses sent 4000-4015 bytes", "4000-4015", out); SET_SIZESTATDESC(4016, "responses sent 4016-4031 bytes", "4016-4031", out); SET_SIZESTATDESC(4032, "responses sent 4032-4047 bytes", "4032-4047", out); SET_SIZESTATDESC(4048, "responses sent 4048-4063 bytes", "4048-4063", out); SET_SIZESTATDESC(4064, "responses sent 4064-4079 bytes", "4064-4079", out); SET_SIZESTATDESC(4080, "responses sent 4080-4095 bytes", "4080-4095", out); SET_SIZESTATDESC(4096, "responses sent 4096+ bytes", "4096+", out); INSIST(i == dns_sizecounter_out_max); /* Sanity check */ for (i = 0; i < dns_nsstatscounter_max; i++) INSIST(nsstats_desc[i] != NULL); for (i = 0; i < dns_resstatscounter_max; i++) INSIST(resstats_desc[i] != NULL); for (i = 0; i < dns_adbstats_max; i++) INSIST(adbstats_desc[i] != NULL); for (i = 0; i < dns_zonestatscounter_max; i++) INSIST(zonestats_desc[i] != NULL); for (i = 0; i < isc_sockstatscounter_max; i++) INSIST(sockstats_desc[i] != NULL); for (i = 0; i < dns_dnssecstats_max; i++) INSIST(dnssecstats_desc[i] != NULL); for (i = 0; i < dns_sizecounter_in_max; i++) { INSIST(udpinsizestats_desc[i] != NULL); INSIST(tcpinsizestats_desc[i] != NULL); } for (i = 0; i < dns_sizecounter_out_max; i++) { INSIST(udpoutsizestats_desc[i] != NULL); INSIST(tcpoutsizestats_desc[i] != NULL); } #if defined(EXTENDED_STATS) for (i = 0; i < dns_nsstatscounter_max; i++) INSIST(nsstats_xmldesc[i] != NULL); for (i = 0; i < dns_resstatscounter_max; i++) INSIST(resstats_xmldesc[i] != NULL); for (i = 0; i < dns_adbstats_max; i++) INSIST(adbstats_xmldesc[i] != NULL); for (i = 0; i < dns_zonestatscounter_max; i++) INSIST(zonestats_xmldesc[i] != NULL); for (i = 0; i < isc_sockstatscounter_max; i++) INSIST(sockstats_xmldesc[i] != NULL); for (i = 0; i < dns_dnssecstats_max; i++) INSIST(dnssecstats_xmldesc[i] != NULL); for (i = 0; i < dns_sizecounter_in_max; i++) { INSIST(udpinsizestats_xmldesc[i] != NULL); INSIST(tcpinsizestats_xmldesc[i] != NULL); } for (i = 0; i < dns_sizecounter_out_max; i++) { INSIST(udpoutsizestats_xmldesc[i] != NULL); INSIST(tcpoutsizestats_xmldesc[i] != NULL); } #endif } /*% * Dump callback functions. */ static void generalstat_dump(isc_statscounter_t counter, isc_uint64_t val, void *arg) { stats_dumparg_t *dumparg = arg; REQUIRE(counter < dumparg->ncounters); dumparg->countervalues[counter] = val; } static isc_result_t dump_counters(isc_stats_t *stats, isc_statsformat_t type, void *arg, const char *category, const char **desc, int ncounters, int *indices, isc_uint64_t *values, int options) { int i, idx; isc_uint64_t value; stats_dumparg_t dumparg; FILE *fp; #ifdef HAVE_LIBXML2 xmlTextWriterPtr writer; int xmlrc; #endif #ifdef HAVE_JSON json_object *job, *cat, *counter; #endif #if !defined(EXTENDED_STATS) UNUSED(category); #endif dumparg.type = type; dumparg.ncounters = ncounters; dumparg.counterindices = indices; dumparg.countervalues = values; memset(values, 0, sizeof(values[0]) * ncounters); isc_stats_dump(stats, generalstat_dump, &dumparg, options); #ifdef HAVE_JSON cat = job = (json_object *) arg; if (ncounters > 0 && type == isc_statsformat_json) { if (category != NULL) { cat = json_object_new_object(); if (cat == NULL) return (ISC_R_NOMEMORY); json_object_object_add(job, category, cat); } } #endif for (i = 0; i < ncounters; i++) { idx = indices[i]; value = values[idx]; if (value == 0 && (options & ISC_STATSDUMP_VERBOSE) == 0) continue; switch (dumparg.type) { case isc_statsformat_file: fp = arg; fprintf(fp, "%20" ISC_PRINT_QUADFORMAT "u %s\n", value, desc[idx]); break; case isc_statsformat_xml: #ifdef HAVE_LIBXML2 writer = (xmlTextWriterPtr) arg; if (category != NULL) { /* */ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR category)); /* inside category */ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "name")); TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR desc[idx])); TRY0(xmlTextWriterEndElement(writer)); /* */ /* */ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counter")); TRY0(xmlTextWriterWriteFormatString(writer, "%" ISC_PRINT_QUADFORMAT "u", value)); TRY0(xmlTextWriterEndElement(writer)); /* */ TRY0(xmlTextWriterEndElement(writer)); /* */ } else { TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counter")); TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "name", ISC_XMLCHAR desc[idx])); TRY0(xmlTextWriterWriteFormatString(writer, "%" ISC_PRINT_QUADFORMAT "u", value)); TRY0(xmlTextWriterEndElement(writer)); /* counter */ } #endif break; case isc_statsformat_json: #ifdef HAVE_JSON counter = json_object_new_int64(value); if (counter == NULL) return (ISC_R_NOMEMORY); json_object_object_add(cat, desc[idx], counter); #endif break; } } return (ISC_R_SUCCESS); #ifdef HAVE_LIBXML2 error: isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, "failed at dump_counters()"); return (ISC_R_FAILURE); #endif } static void rdtypestat_dump(dns_rdatastatstype_t type, isc_uint64_t val, void *arg) { char typebuf[64]; const char *typestr; stats_dumparg_t *dumparg = arg; FILE *fp; #ifdef HAVE_LIBXML2 xmlTextWriterPtr writer; int xmlrc; #endif #ifdef HAVE_JSON json_object *zoneobj, *obj; #endif if ((DNS_RDATASTATSTYPE_ATTR(type) & DNS_RDATASTATSTYPE_ATTR_OTHERTYPE) == 0) { dns_rdatatype_format(DNS_RDATASTATSTYPE_BASE(type), typebuf, sizeof(typebuf)); typestr = typebuf; } else typestr = "Others"; switch (dumparg->type) { case isc_statsformat_file: fp = dumparg->arg; fprintf(fp, "%20" ISC_PRINT_QUADFORMAT "u %s\n", val, typestr); break; case isc_statsformat_xml: #ifdef HAVE_LIBXML2 writer = dumparg->arg; TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counter")); TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "name", ISC_XMLCHAR typestr)); TRY0(xmlTextWriterWriteFormatString(writer, "%" ISC_PRINT_QUADFORMAT "u", val)); TRY0(xmlTextWriterEndElement(writer)); /* type */ #endif break; case isc_statsformat_json: #ifdef HAVE_JSON zoneobj = (json_object *) dumparg->arg; obj = json_object_new_int64(val); if (obj == NULL) return; json_object_object_add(zoneobj, typestr, obj); #endif break; } return; #ifdef HAVE_LIBXML2 error: isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, "failed at rdtypestat_dump()"); dumparg->result = ISC_R_FAILURE; return; #endif } static void rdatasetstats_dump(dns_rdatastatstype_t type, isc_uint64_t val, void *arg) { stats_dumparg_t *dumparg = arg; FILE *fp; char typebuf[64]; const char *typestr; isc_boolean_t nxrrset = ISC_FALSE; isc_boolean_t stale = ISC_FALSE; #ifdef HAVE_LIBXML2 xmlTextWriterPtr writer; int xmlrc; #endif #ifdef HAVE_JSON json_object *zoneobj, *obj; char buf[1024]; #endif if ((DNS_RDATASTATSTYPE_ATTR(type) & DNS_RDATASTATSTYPE_ATTR_NXDOMAIN) != 0) { typestr = "NXDOMAIN"; } else if ((DNS_RDATASTATSTYPE_ATTR(type) & DNS_RDATASTATSTYPE_ATTR_OTHERTYPE) != 0) { typestr = "Others"; } else { dns_rdatatype_format(DNS_RDATASTATSTYPE_BASE(type), typebuf, sizeof(typebuf)); typestr = typebuf; } if ((DNS_RDATASTATSTYPE_ATTR(type) & DNS_RDATASTATSTYPE_ATTR_NXRRSET) != 0) nxrrset = ISC_TRUE; if ((DNS_RDATASTATSTYPE_ATTR(type) & DNS_RDATASTATSTYPE_ATTR_STALE) != 0) stale = ISC_TRUE; switch (dumparg->type) { case isc_statsformat_file: fp = dumparg->arg; fprintf(fp, "%20" ISC_PRINT_QUADFORMAT "u %s%s%s\n", val, stale ? "#" : "", nxrrset ? "!" : "", typestr); break; case isc_statsformat_xml: #ifdef HAVE_LIBXML2 writer = dumparg->arg; TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "rrset")); TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "name")); TRY0(xmlTextWriterWriteFormatString(writer, "%s%s%s", stale ? "#" : "", nxrrset ? "!" : "", typestr)); TRY0(xmlTextWriterEndElement(writer)); /* name */ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counter")); TRY0(xmlTextWriterWriteFormatString(writer, "%" ISC_PRINT_QUADFORMAT "u", val)); TRY0(xmlTextWriterEndElement(writer)); /* counter */ TRY0(xmlTextWriterEndElement(writer)); /* rrset */ #endif break; case isc_statsformat_json: #ifdef HAVE_JSON zoneobj = (json_object *) dumparg->arg; snprintf(buf, sizeof(buf), "%s%s%s", stale ? "#" : "", nxrrset ? "!" : "", typestr); obj = json_object_new_int64(val); if (obj == NULL) return; json_object_object_add(zoneobj, buf, obj); #endif break; } return; #ifdef HAVE_LIBXML2 error: isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, "failed at rdatasetstats_dump()"); dumparg->result = ISC_R_FAILURE; #endif } static void opcodestat_dump(dns_opcode_t code, isc_uint64_t val, void *arg) { FILE *fp; isc_buffer_t b; char codebuf[64]; stats_dumparg_t *dumparg = arg; #ifdef HAVE_LIBXML2 xmlTextWriterPtr writer; int xmlrc; #endif #ifdef HAVE_JSON json_object *zoneobj, *obj; #endif isc_buffer_init(&b, codebuf, sizeof(codebuf) - 1); dns_opcode_totext(code, &b); codebuf[isc_buffer_usedlength(&b)] = '\0'; switch (dumparg->type) { case isc_statsformat_file: fp = dumparg->arg; fprintf(fp, "%20" ISC_PRINT_QUADFORMAT "u %s\n", val, codebuf); break; case isc_statsformat_xml: #ifdef HAVE_LIBXML2 writer = dumparg->arg; TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counter")); TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "name", ISC_XMLCHAR codebuf )); TRY0(xmlTextWriterWriteFormatString(writer, "%" ISC_PRINT_QUADFORMAT "u", val)); TRY0(xmlTextWriterEndElement(writer)); /* counter */ #endif break; case isc_statsformat_json: #ifdef HAVE_JSON zoneobj = (json_object *) dumparg->arg; obj = json_object_new_int64(val); if (obj == NULL) return; json_object_object_add(zoneobj, codebuf, obj); #endif break; } return; #ifdef HAVE_LIBXML2 error: isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, "failed at opcodestat_dump()"); dumparg->result = ISC_R_FAILURE; return; #endif } static void rcodestat_dump(dns_rcode_t code, isc_uint64_t val, void *arg) { FILE *fp; isc_buffer_t b; char codebuf[64]; stats_dumparg_t *dumparg = arg; #ifdef HAVE_LIBXML2 xmlTextWriterPtr writer; int xmlrc; #endif #ifdef HAVE_JSON json_object *zoneobj, *obj; #endif isc_buffer_init(&b, codebuf, sizeof(codebuf) - 1); dns_rcode_totext(code, &b); codebuf[isc_buffer_usedlength(&b)] = '\0'; switch (dumparg->type) { case isc_statsformat_file: fp = dumparg->arg; fprintf(fp, "%20" ISC_PRINT_QUADFORMAT "u %s\n", val, codebuf); break; case isc_statsformat_xml: #ifdef HAVE_LIBXML2 writer = dumparg->arg; TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counter")); TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "name", ISC_XMLCHAR codebuf )); TRY0(xmlTextWriterWriteFormatString(writer, "%" ISC_PRINT_QUADFORMAT "u", val)); TRY0(xmlTextWriterEndElement(writer)); /* counter */ #endif break; case isc_statsformat_json: #ifdef HAVE_JSON zoneobj = (json_object *) dumparg->arg; obj = json_object_new_int64(val); if (obj == NULL) return; json_object_object_add(zoneobj, codebuf, obj); #endif break; } return; #ifdef HAVE_LIBXML2 error: isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, "failed at rcodestat_dump()"); dumparg->result = ISC_R_FAILURE; return; #endif } #ifdef HAVE_LIBXML2 /* * Which statistics to include when rendering to XML */ #define STATS_XML_STATUS 0x00 /* display only common statistics */ #define STATS_XML_SERVER 0x01 #define STATS_XML_ZONES 0x02 #define STATS_XML_TASKS 0x04 #define STATS_XML_NET 0x08 #define STATS_XML_MEM 0x10 #define STATS_XML_TRAFFIC 0x20 #define STATS_XML_ALL 0xff static isc_result_t zone_xmlrender(dns_zone_t *zone, void *arg) { isc_result_t result; char buf[1024 + 32]; /* sufficiently large for zone name and class */ dns_rdataclass_t rdclass; isc_uint32_t serial; xmlTextWriterPtr writer = arg; isc_stats_t *zonestats; dns_stats_t *rcvquerystats; dns_zonestat_level_t statlevel; isc_uint64_t nsstat_values[dns_nsstatscounter_max]; int xmlrc; stats_dumparg_t dumparg; const char *ztype; statlevel = dns_zone_getstatlevel(zone); if (statlevel == dns_zonestat_none) return (ISC_R_SUCCESS); dumparg.type = isc_statsformat_xml; dumparg.arg = writer; TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "zone")); dns_zone_nameonly(zone, buf, sizeof(buf)); TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "name", ISC_XMLCHAR buf)); rdclass = dns_zone_getclass(zone); dns_rdataclass_format(rdclass, buf, sizeof(buf)); TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "rdataclass", ISC_XMLCHAR buf)); TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "type")); ztype = user_zonetype(zone); if (ztype != NULL) TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR ztype)); else TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR "unknown")); TRY0(xmlTextWriterEndElement(writer)); /* type */ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "serial")); if (dns_zone_getserial2(zone, &serial) == ISC_R_SUCCESS) TRY0(xmlTextWriterWriteFormatString(writer, "%u", serial)); else TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR "-")); TRY0(xmlTextWriterEndElement(writer)); /* serial */ zonestats = dns_zone_getrequeststats(zone); rcvquerystats = dns_zone_getrcvquerystats(zone); if (statlevel == dns_zonestat_full && zonestats != NULL) { TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters")); TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type", ISC_XMLCHAR "rcode")); result = dump_counters(zonestats, isc_statsformat_xml, writer, NULL, nsstats_xmldesc, dns_nsstatscounter_max, nsstats_index, nsstat_values, ISC_STATSDUMP_VERBOSE); if (result != ISC_R_SUCCESS) goto error; /* counters type="rcode"*/ TRY0(xmlTextWriterEndElement(writer)); } if (statlevel == dns_zonestat_full && rcvquerystats != NULL) { TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters")); TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type", ISC_XMLCHAR "qtype")); dumparg.result = ISC_R_SUCCESS; dns_rdatatypestats_dump(rcvquerystats, rdtypestat_dump, &dumparg, 0); if(dumparg.result != ISC_R_SUCCESS) goto error; /* counters type="qtype"*/ TRY0(xmlTextWriterEndElement(writer)); } TRY0(xmlTextWriterEndElement(writer)); /* zone */ return (ISC_R_SUCCESS); error: isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, "Failed at zone_xmlrender()"); return (ISC_R_FAILURE); } static isc_result_t generatexml(ns_server_t *server, isc_uint32_t flags, int *buflen, xmlChar **buf) { char boottime[sizeof "yyyy-mm-ddThh:mm:ss.sssZ"]; char configtime[sizeof "yyyy-mm-ddThh:mm:ss.sssZ"]; char nowstr[sizeof "yyyy-mm-ddThh:mm:ss.sssZ"]; isc_time_t now; xmlTextWriterPtr writer = NULL; xmlDocPtr doc = NULL; int xmlrc; dns_view_t *view; stats_dumparg_t dumparg; dns_stats_t *cacherrstats; isc_uint64_t nsstat_values[dns_nsstatscounter_max]; isc_uint64_t resstat_values[dns_resstatscounter_max]; isc_uint64_t adbstat_values[dns_adbstats_max]; isc_uint64_t zonestat_values[dns_zonestatscounter_max]; isc_uint64_t sockstat_values[isc_sockstatscounter_max]; isc_uint64_t udpinsizestat_values[dns_sizecounter_in_max]; isc_uint64_t udpoutsizestat_values[dns_sizecounter_out_max]; isc_uint64_t tcpinsizestat_values[dns_sizecounter_in_max]; isc_uint64_t tcpoutsizestat_values[dns_sizecounter_out_max]; #if HAVE_DNSTAP isc_uint64_t dnstapstat_values[dns_dnstapcounter_max]; #endif isc_result_t result; isc_time_now(&now); isc_time_formatISO8601ms(&ns_g_boottime, boottime, sizeof boottime); isc_time_formatISO8601ms(&ns_g_configtime, configtime, sizeof configtime); isc_time_formatISO8601ms(&now, nowstr, sizeof nowstr); writer = xmlNewTextWriterDoc(&doc, 0); if (writer == NULL) goto error; TRY0(xmlTextWriterStartDocument(writer, NULL, "UTF-8", NULL)); TRY0(xmlTextWriterWritePI(writer, ISC_XMLCHAR "xml-stylesheet", ISC_XMLCHAR "type=\"text/xsl\" href=\"/bind9.xsl\"")); TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "statistics")); TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "version", ISC_XMLCHAR "3.8")); /* Set common fields for statistics dump */ dumparg.type = isc_statsformat_xml; dumparg.arg = writer; /* Render server information */ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "server")); TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "boot-time")); TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR boottime)); TRY0(xmlTextWriterEndElement(writer)); /* boot-time */ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "config-time")); TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR configtime)); TRY0(xmlTextWriterEndElement(writer)); /* config-time */ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "current-time")); TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR nowstr)); TRY0(xmlTextWriterEndElement(writer)); /* current-time */ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "version")); TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR ns_g_version)); TRY0(xmlTextWriterEndElement(writer)); /* version */ if ((flags & STATS_XML_SERVER) != 0) { dumparg.result = ISC_R_SUCCESS; TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters")); TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type", ISC_XMLCHAR "opcode")); dns_opcodestats_dump(server->opcodestats, opcodestat_dump, &dumparg, ISC_STATSDUMP_VERBOSE); if (dumparg.result != ISC_R_SUCCESS) goto error; TRY0(xmlTextWriterEndElement(writer)); TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters")); TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type", ISC_XMLCHAR "rcode")); dns_rcodestats_dump(server->rcodestats, rcodestat_dump, &dumparg, ISC_STATSDUMP_VERBOSE); if (dumparg.result != ISC_R_SUCCESS) goto error; TRY0(xmlTextWriterEndElement(writer)); TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters")); TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type", ISC_XMLCHAR "qtype")); dumparg.result = ISC_R_SUCCESS; dns_rdatatypestats_dump(server->rcvquerystats, rdtypestat_dump, &dumparg, 0); if (dumparg.result != ISC_R_SUCCESS) goto error; TRY0(xmlTextWriterEndElement(writer)); /* counters */ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters")); TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type", ISC_XMLCHAR "nsstat")); result = dump_counters(server->nsstats, isc_statsformat_xml, writer, NULL, nsstats_xmldesc, dns_nsstatscounter_max, nsstats_index, nsstat_values, ISC_STATSDUMP_VERBOSE); if (result != ISC_R_SUCCESS) goto error; TRY0(xmlTextWriterEndElement(writer)); /* /nsstat */ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters")); TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type", ISC_XMLCHAR "zonestat")); result = dump_counters(server->zonestats, isc_statsformat_xml, writer, NULL, zonestats_xmldesc, dns_zonestatscounter_max, zonestats_index, zonestat_values, ISC_STATSDUMP_VERBOSE); if (result != ISC_R_SUCCESS) goto error; TRY0(xmlTextWriterEndElement(writer)); /* /zonestat */ /* * Most of the common resolver statistics entries are 0, so * we don't use the verbose dump here. */ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters")); TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type", ISC_XMLCHAR "resstat")); result = dump_counters(server->resolverstats, isc_statsformat_xml, writer, NULL, resstats_xmldesc, dns_resstatscounter_max, resstats_index, resstat_values, 0); if (result != ISC_R_SUCCESS) goto error; TRY0(xmlTextWriterEndElement(writer)); /* resstat */ #if HAVE_DNSTAP if (server->dtenv != NULL) { isc_stats_t *dnstapstats = NULL; TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters")); TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type", ISC_XMLCHAR "dnstap")); dns_dt_getstats(ns_g_server->dtenv, &dnstapstats); result = dump_counters(dnstapstats, isc_statsformat_xml, writer, NULL, dnstapstats_xmldesc, dns_dnstapcounter_max, dnstapstats_index, dnstapstat_values, 0); isc_stats_detach(&dnstapstats); if (result != ISC_R_SUCCESS) goto error; TRY0(xmlTextWriterEndElement(writer)); /* dnstap */ } #endif } if ((flags & STATS_XML_NET) != 0) { TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters")); TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type", ISC_XMLCHAR "sockstat")); result = dump_counters(server->sockstats, isc_statsformat_xml, writer, NULL, sockstats_xmldesc, isc_sockstatscounter_max, sockstats_index, sockstat_values, ISC_STATSDUMP_VERBOSE); if (result != ISC_R_SUCCESS) goto error; TRY0(xmlTextWriterEndElement(writer)); /* /sockstat */ } TRY0(xmlTextWriterEndElement(writer)); /* /server */ if ((flags & STATS_XML_TRAFFIC) != 0) { TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "traffic")); TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "ipv4")); TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "udp")); TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters")); TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type", ISC_XMLCHAR "request-size")); result = dump_counters(server->udpinstats4, isc_statsformat_xml, writer, NULL, udpinsizestats_xmldesc, dns_sizecounter_in_max, udpinsizestats_index, udpinsizestat_values, 0); if (result != ISC_R_SUCCESS) goto error; TRY0(xmlTextWriterEndElement(writer)); /* */ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters")); TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type", ISC_XMLCHAR "response-size")); result = dump_counters(server->udpoutstats4, isc_statsformat_xml, writer, NULL, udpoutsizestats_xmldesc, dns_sizecounter_out_max, udpoutsizestats_index, udpoutsizestat_values, 0); if (result != ISC_R_SUCCESS) goto error; TRY0(xmlTextWriterEndElement(writer)); /* */ TRY0(xmlTextWriterEndElement(writer)); /* */ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "tcp")); TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters")); TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type", ISC_XMLCHAR "request-size")); result = dump_counters(server->tcpinstats4, isc_statsformat_xml, writer, NULL, tcpinsizestats_xmldesc, dns_sizecounter_in_max, tcpinsizestats_index, tcpinsizestat_values, 0); if (result != ISC_R_SUCCESS) goto error; TRY0(xmlTextWriterEndElement(writer)); /* */ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters")); TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type", ISC_XMLCHAR "response-size")); result = dump_counters(server->tcpoutstats4, isc_statsformat_xml, writer, NULL, tcpoutsizestats_xmldesc, dns_sizecounter_out_max, tcpoutsizestats_index, tcpoutsizestat_values, 0); if (result != ISC_R_SUCCESS) goto error; TRY0(xmlTextWriterEndElement(writer)); /* */ TRY0(xmlTextWriterEndElement(writer)); /* */ TRY0(xmlTextWriterEndElement(writer)); /* */ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "ipv6")); TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "udp")); TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters")); TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type", ISC_XMLCHAR "request-size")); result = dump_counters(server->udpinstats6, isc_statsformat_xml, writer, NULL, udpinsizestats_xmldesc, dns_sizecounter_in_max, udpinsizestats_index, udpinsizestat_values, 0); if (result != ISC_R_SUCCESS) goto error; TRY0(xmlTextWriterEndElement(writer)); /* */ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters")); TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type", ISC_XMLCHAR "response-size")); result = dump_counters(server->udpoutstats6, isc_statsformat_xml, writer, NULL, udpoutsizestats_xmldesc, dns_sizecounter_out_max, udpoutsizestats_index, udpoutsizestat_values, 0); if (result != ISC_R_SUCCESS) goto error; TRY0(xmlTextWriterEndElement(writer)); /* */ TRY0(xmlTextWriterEndElement(writer)); /* */ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "tcp")); TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters")); TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type", ISC_XMLCHAR "request-size")); result = dump_counters(server->tcpinstats6, isc_statsformat_xml, writer, NULL, tcpinsizestats_xmldesc, dns_sizecounter_in_max, tcpinsizestats_index, tcpinsizestat_values, 0); if (result != ISC_R_SUCCESS) goto error; TRY0(xmlTextWriterEndElement(writer)); /* */ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters")); TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type", ISC_XMLCHAR "response-size")); result = dump_counters(server->tcpoutstats6, isc_statsformat_xml, writer, NULL, tcpoutsizestats_xmldesc, dns_sizecounter_out_max, tcpoutsizestats_index, tcpoutsizestat_values, 0); if (result != ISC_R_SUCCESS) goto error; TRY0(xmlTextWriterEndElement(writer)); /* */ TRY0(xmlTextWriterEndElement(writer)); /* */ TRY0(xmlTextWriterEndElement(writer)); /* */ TRY0(xmlTextWriterEndElement(writer)); /* */ } /* * Render views. For each view we know of, call its * rendering function. */ view = ISC_LIST_HEAD(server->viewlist); TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "views")); while (view != NULL && ((flags & (STATS_XML_SERVER | STATS_XML_ZONES)) != 0)) { TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "view")); TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "name", ISC_XMLCHAR view->name)); if ((flags & STATS_XML_ZONES) != 0) { TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "zones")); result = dns_zt_apply(view->zonetable, ISC_TRUE, zone_xmlrender, writer); if (result != ISC_R_SUCCESS) goto error; TRY0(xmlTextWriterEndElement(writer)); /* /zones */ } if ((flags & STATS_XML_SERVER) == 0) { TRY0(xmlTextWriterEndElement(writer)); /* /view */ view = ISC_LIST_NEXT(view, link); continue; } TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters")); TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type", ISC_XMLCHAR "resqtype")); if (view->resquerystats != NULL) { dumparg.result = ISC_R_SUCCESS; dns_rdatatypestats_dump(view->resquerystats, rdtypestat_dump, &dumparg, 0); if (dumparg.result != ISC_R_SUCCESS) goto error; } TRY0(xmlTextWriterEndElement(writer)); /* */ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters")); TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type", ISC_XMLCHAR "resstats")); if (view->resstats != NULL) { result = dump_counters(view->resstats, isc_statsformat_xml, writer, NULL, resstats_xmldesc, dns_resstatscounter_max, resstats_index, resstat_values, ISC_STATSDUMP_VERBOSE); if (result != ISC_R_SUCCESS) goto error; } TRY0(xmlTextWriterEndElement(writer)); /* */ cacherrstats = dns_db_getrrsetstats(view->cachedb); if (cacherrstats != NULL) { TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "cache")); TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "name", ISC_XMLCHAR dns_cache_getname(view->cache))); dumparg.result = ISC_R_SUCCESS; dns_rdatasetstats_dump(cacherrstats, rdatasetstats_dump, &dumparg, 0); if (dumparg.result != ISC_R_SUCCESS) goto error; TRY0(xmlTextWriterEndElement(writer)); /* cache */ } /* */ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters")); TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type", ISC_XMLCHAR "adbstat")); if (view->adbstats != NULL) { result = dump_counters(view->adbstats, isc_statsformat_xml, writer, NULL, adbstats_xmldesc, dns_adbstats_max, adbstats_index, adbstat_values, ISC_STATSDUMP_VERBOSE); if (result != ISC_R_SUCCESS) goto error; } TRY0(xmlTextWriterEndElement(writer)); /* */ /* */ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters")); TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type", ISC_XMLCHAR "cachestats")); TRY0(dns_cache_renderxml(view->cache, writer)); TRY0(xmlTextWriterEndElement(writer)); /* */ TRY0(xmlTextWriterEndElement(writer)); /* view */ view = ISC_LIST_NEXT(view, link); } TRY0(xmlTextWriterEndElement(writer)); /* /views */ if ((flags & STATS_XML_NET) != 0) { TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "socketmgr")); TRY0(isc_socketmgr_renderxml(ns_g_socketmgr, writer)); TRY0(xmlTextWriterEndElement(writer)); /* /socketmgr */ } if ((flags & STATS_XML_TASKS) != 0) { TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "taskmgr")); TRY0(isc_taskmgr_renderxml(ns_g_taskmgr, writer)); TRY0(xmlTextWriterEndElement(writer)); /* /taskmgr */ } if ((flags & STATS_XML_MEM) != 0) { TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "memory")); TRY0(isc_mem_renderxml(writer)); TRY0(xmlTextWriterEndElement(writer)); /* /memory */ } TRY0(xmlTextWriterEndElement(writer)); /* /statistics */ TRY0(xmlTextWriterEndDocument(writer)); xmlFreeTextWriter(writer); xmlDocDumpFormatMemoryEnc(doc, buf, buflen, "UTF-8", 0); if (*buf == NULL) goto error; xmlFreeDoc(doc); return (ISC_R_SUCCESS); error: isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, "failed generating XML response"); if (writer != NULL) xmlFreeTextWriter(writer); if (doc != NULL) xmlFreeDoc(doc); return (ISC_R_FAILURE); } static void wrap_xmlfree(isc_buffer_t *buffer, void *arg) { UNUSED(arg); xmlFree(isc_buffer_base(buffer)); } static isc_result_t render_xml(isc_uint32_t flags, const char *url, isc_httpdurl_t *urlinfo, const char *querystring, const char *headers, void *arg, unsigned int *retcode, const char **retmsg, const char **mimetype, isc_buffer_t *b, isc_httpdfree_t **freecb, void **freecb_args) { unsigned char *msg = NULL; int msglen; ns_server_t *server = arg; isc_result_t result; UNUSED(url); UNUSED(urlinfo); UNUSED(headers); UNUSED(querystring); result = generatexml(server, flags, &msglen, &msg); if (result == ISC_R_SUCCESS) { *retcode = 200; *retmsg = "OK"; *mimetype = "text/xml"; isc_buffer_reinit(b, msg, msglen); isc_buffer_add(b, msglen); *freecb = wrap_xmlfree; *freecb_args = NULL; } else isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, "failed at rendering XML()"); return (result); } static isc_result_t render_xml_all(const char *url, isc_httpdurl_t *urlinfo, const char *querystring, const char *headers, void *arg, unsigned int *retcode, const char **retmsg, const char **mimetype, isc_buffer_t *b, isc_httpdfree_t **freecb, void **freecb_args) { return (render_xml(STATS_XML_ALL, url, urlinfo, querystring, headers, arg, retcode, retmsg, mimetype, b, freecb, freecb_args)); } static isc_result_t render_xml_status(const char *url, isc_httpdurl_t *urlinfo, const char *querystring, const char *headers, void *arg, unsigned int *retcode, const char **retmsg, const char **mimetype, isc_buffer_t *b, isc_httpdfree_t **freecb, void **freecb_args) { return (render_xml(STATS_XML_STATUS, url, urlinfo, querystring, headers, arg, retcode, retmsg, mimetype, b, freecb, freecb_args)); } static isc_result_t render_xml_server(const char *url, isc_httpdurl_t *urlinfo, const char *querystring, const char *headers, void *arg, unsigned int *retcode, const char **retmsg, const char **mimetype, isc_buffer_t *b, isc_httpdfree_t **freecb, void **freecb_args) { return (render_xml(STATS_XML_SERVER, url, urlinfo, querystring, headers, arg, retcode, retmsg, mimetype, b, freecb, freecb_args)); } static isc_result_t render_xml_zones(const char *url, isc_httpdurl_t *urlinfo, const char *querystring, const char *headers, void *arg, unsigned int *retcode, const char **retmsg, const char **mimetype, isc_buffer_t *b, isc_httpdfree_t **freecb, void **freecb_args) { return (render_xml(STATS_XML_ZONES, url, urlinfo, querystring, headers, arg, retcode, retmsg, mimetype, b, freecb, freecb_args)); } static isc_result_t render_xml_net(const char *url, isc_httpdurl_t *urlinfo, const char *querystring, const char *headers, void *arg, unsigned int *retcode, const char **retmsg, const char **mimetype, isc_buffer_t *b, isc_httpdfree_t **freecb, void **freecb_args) { return (render_xml(STATS_XML_NET, url, urlinfo, querystring, headers, arg, retcode, retmsg, mimetype, b, freecb, freecb_args)); } static isc_result_t render_xml_tasks(const char *url, isc_httpdurl_t *urlinfo, const char *querystring, const char *headers, void *arg, unsigned int *retcode, const char **retmsg, const char **mimetype, isc_buffer_t *b, isc_httpdfree_t **freecb, void **freecb_args) { return (render_xml(STATS_XML_TASKS, url, urlinfo, querystring, headers, arg, retcode, retmsg, mimetype, b, freecb, freecb_args)); } static isc_result_t render_xml_mem(const char *url, isc_httpdurl_t *urlinfo, const char *querystring, const char *headers, void *arg, unsigned int *retcode, const char **retmsg, const char **mimetype, isc_buffer_t *b, isc_httpdfree_t **freecb, void **freecb_args) { return (render_xml(STATS_XML_MEM, url, urlinfo, querystring, headers, arg, retcode, retmsg, mimetype, b, freecb, freecb_args)); } static isc_result_t render_xml_traffic(const char *url, isc_httpdurl_t *urlinfo, const char *querystring, const char *headers, void *arg, unsigned int *retcode, const char **retmsg, const char **mimetype, isc_buffer_t *b, isc_httpdfree_t **freecb, void **freecb_args) { return (render_xml(STATS_XML_TRAFFIC, url, urlinfo, querystring, headers, arg, retcode, retmsg, mimetype, b, freecb, freecb_args)); } #endif /* HAVE_LIBXML2 */ #ifdef HAVE_JSON /* * Which statistics to include when rendering to JSON */ #define STATS_JSON_STATUS 0x00 /* display only common statistics */ #define STATS_JSON_SERVER 0x01 #define STATS_JSON_ZONES 0x02 #define STATS_JSON_TASKS 0x04 #define STATS_JSON_NET 0x08 #define STATS_JSON_MEM 0x10 #define STATS_JSON_TRAFFIC 0x20 #define STATS_JSON_ALL 0xff #define CHECK(m) do { \ result = (m); \ if (result != ISC_R_SUCCESS) \ goto error; \ } while (0) #define CHECKMEM(m) do { \ if (m == NULL) { \ result = ISC_R_NOMEMORY;\ goto error;\ } \ } while(0) static void wrap_jsonfree(isc_buffer_t *buffer, void *arg) { json_object_put(isc_buffer_base(buffer)); if (arg != NULL) json_object_put((json_object *) arg); } static json_object * addzone(char *name, char *classname, const char *ztype, isc_uint32_t serial, isc_boolean_t add_serial) { json_object *node = json_object_new_object(); if (node == NULL) return (NULL); json_object_object_add(node, "name", json_object_new_string(name)); json_object_object_add(node, "class", json_object_new_string(classname)); if (add_serial) json_object_object_add(node, "serial", json_object_new_int64(serial)); if (ztype != NULL) json_object_object_add(node, "type", json_object_new_string(ztype)); return (node); } static isc_result_t zone_jsonrender(dns_zone_t *zone, void *arg) { isc_result_t result = ISC_R_SUCCESS; char buf[1024 + 32]; /* sufficiently large for zone name and class */ char classbuf[64]; /* sufficiently large for class */ char *zone_name_only = NULL; char *class_only = NULL; dns_rdataclass_t rdclass; isc_uint32_t serial; isc_uint64_t nsstat_values[dns_nsstatscounter_max]; isc_stats_t *zonestats; dns_stats_t *rcvquerystats; json_object *zonearray = (json_object *) arg; json_object *zoneobj = NULL; dns_zonestat_level_t statlevel; statlevel = dns_zone_getstatlevel(zone); if (statlevel == dns_zonestat_none) return (ISC_R_SUCCESS); dns_zone_nameonly(zone, buf, sizeof(buf)); zone_name_only = buf; rdclass = dns_zone_getclass(zone); dns_rdataclass_format(rdclass, classbuf, sizeof(classbuf)); class_only = classbuf; if (dns_zone_getserial2(zone, &serial) != ISC_R_SUCCESS) zoneobj = addzone(zone_name_only, class_only, user_zonetype(zone), 0, ISC_FALSE); else zoneobj = addzone(zone_name_only, class_only, user_zonetype(zone), serial, ISC_TRUE); if (zoneobj == NULL) return (ISC_R_NOMEMORY); zonestats = dns_zone_getrequeststats(zone); rcvquerystats = dns_zone_getrcvquerystats(zone); if (statlevel == dns_zonestat_full && zonestats != NULL) { json_object *counters = json_object_new_object(); if (counters == NULL) { result = ISC_R_NOMEMORY; goto error; } result = dump_counters(zonestats, isc_statsformat_json, counters, NULL, nsstats_xmldesc, dns_nsstatscounter_max, nsstats_index, nsstat_values, 0); if (result != ISC_R_SUCCESS) { json_object_put(counters); goto error; } if (json_object_get_object(counters)->count != 0) json_object_object_add(zoneobj, "rcodes", counters); else json_object_put(counters); } if (statlevel == dns_zonestat_full && rcvquerystats != NULL) { stats_dumparg_t dumparg; json_object *counters = json_object_new_object(); CHECKMEM(counters); dumparg.type = isc_statsformat_json; dumparg.arg = counters; dumparg.result = ISC_R_SUCCESS; dns_rdatatypestats_dump(rcvquerystats, rdtypestat_dump, &dumparg, 0); if (dumparg.result != ISC_R_SUCCESS) { json_object_put(counters); goto error; } if (json_object_get_object(counters)->count != 0) json_object_object_add(zoneobj, "qtypes", counters); else json_object_put(counters); } json_object_array_add(zonearray, zoneobj); zoneobj = NULL; result = ISC_R_SUCCESS; error: if (zoneobj != NULL) json_object_put(zoneobj); return (result); } static isc_result_t generatejson(ns_server_t *server, size_t *msglen, const char **msg, json_object **rootp, isc_uint32_t flags) { dns_view_t *view; isc_result_t result = ISC_R_SUCCESS; json_object *bindstats, *viewlist, *counters, *obj; json_object *traffic = NULL; json_object *udpreq4 = NULL, *udpresp4 = NULL; json_object *tcpreq4 = NULL, *tcpresp4 = NULL; json_object *udpreq6 = NULL, *udpresp6 = NULL; json_object *tcpreq6 = NULL, *tcpresp6 = NULL; isc_uint64_t nsstat_values[dns_nsstatscounter_max]; isc_uint64_t resstat_values[dns_resstatscounter_max]; isc_uint64_t adbstat_values[dns_adbstats_max]; isc_uint64_t zonestat_values[dns_zonestatscounter_max]; isc_uint64_t sockstat_values[isc_sockstatscounter_max]; isc_uint64_t udpinsizestat_values[dns_sizecounter_in_max]; isc_uint64_t udpoutsizestat_values[dns_sizecounter_out_max]; isc_uint64_t tcpinsizestat_values[dns_sizecounter_in_max]; isc_uint64_t tcpoutsizestat_values[dns_sizecounter_out_max]; #if HAVE_DNSTAP isc_uint64_t dnstapstat_values[dns_dnstapcounter_max]; #endif stats_dumparg_t dumparg; char boottime[sizeof "yyyy-mm-ddThh:mm:ss.sssZ"]; char configtime[sizeof "yyyy-mm-ddThh:mm:ss.sssZ"]; char nowstr[sizeof "yyyy-mm-ddThh:mm:ss.sssZ"]; isc_time_t now; REQUIRE(msglen != NULL); REQUIRE(msg != NULL && *msg == NULL); REQUIRE(rootp == NULL || *rootp == NULL); bindstats = json_object_new_object(); if (bindstats == NULL) return (ISC_R_NOMEMORY); /* * These statistics are included no matter which URL we use. */ obj = json_object_new_string("1.2"); CHECKMEM(obj); json_object_object_add(bindstats, "json-stats-version", obj); isc_time_now(&now); isc_time_formatISO8601ms(&ns_g_boottime, boottime, sizeof(boottime)); isc_time_formatISO8601ms(&ns_g_configtime, configtime, sizeof configtime); isc_time_formatISO8601ms(&now, nowstr, sizeof(nowstr)); obj = json_object_new_string(boottime); CHECKMEM(obj); json_object_object_add(bindstats, "boot-time", obj); obj = json_object_new_string(configtime); CHECKMEM(obj); json_object_object_add(bindstats, "config-time", obj); obj = json_object_new_string(nowstr); CHECKMEM(obj); json_object_object_add(bindstats, "current-time", obj); obj = json_object_new_string(ns_g_version); CHECKMEM(obj); json_object_object_add(bindstats, "version", obj); if ((flags & STATS_JSON_SERVER) != 0) { /* OPCODE counters */ counters = json_object_new_object(); dumparg.result = ISC_R_SUCCESS; dumparg.type = isc_statsformat_json; dumparg.arg = counters; dns_opcodestats_dump(server->opcodestats, opcodestat_dump, &dumparg, ISC_STATSDUMP_VERBOSE); if (dumparg.result != ISC_R_SUCCESS) { json_object_put(counters); goto error; } if (json_object_get_object(counters)->count != 0) json_object_object_add(bindstats, "opcodes", counters); else json_object_put(counters); /* OPCODE counters */ counters = json_object_new_object(); dumparg.type = isc_statsformat_json; dumparg.arg = counters; dns_rcodestats_dump(server->rcodestats, rcodestat_dump, &dumparg, ISC_STATSDUMP_VERBOSE); if (dumparg.result != ISC_R_SUCCESS) { json_object_put(counters); goto error; } if (json_object_get_object(counters)->count != 0) json_object_object_add(bindstats, "rcodes", counters); else json_object_put(counters); /* QTYPE counters */ counters = json_object_new_object(); dumparg.result = ISC_R_SUCCESS; dumparg.arg = counters; dns_rdatatypestats_dump(server->rcvquerystats, rdtypestat_dump, &dumparg, 0); if (dumparg.result != ISC_R_SUCCESS) { json_object_put(counters); goto error; } if (json_object_get_object(counters)->count != 0) json_object_object_add(bindstats, "qtypes", counters); else json_object_put(counters); /* server stat counters */ counters = json_object_new_object(); dumparg.result = ISC_R_SUCCESS; dumparg.arg = counters; result = dump_counters(server->nsstats, isc_statsformat_json, counters, NULL, nsstats_xmldesc, dns_nsstatscounter_max, nsstats_index, nsstat_values, 0); if (result != ISC_R_SUCCESS) { json_object_put(counters); goto error; } if (json_object_get_object(counters)->count != 0) json_object_object_add(bindstats, "nsstats", counters); else json_object_put(counters); /* zone stat counters */ counters = json_object_new_object(); dumparg.result = ISC_R_SUCCESS; dumparg.arg = counters; result = dump_counters(server->zonestats, isc_statsformat_json, counters, NULL, zonestats_xmldesc, dns_zonestatscounter_max, zonestats_index, zonestat_values, 0); if (result != ISC_R_SUCCESS) { json_object_put(counters); goto error; } if (json_object_get_object(counters)->count != 0) json_object_object_add(bindstats, "zonestats", counters); else json_object_put(counters); /* resolver stat counters */ counters = json_object_new_object(); dumparg.result = ISC_R_SUCCESS; dumparg.arg = counters; result = dump_counters(server->resolverstats, isc_statsformat_json, counters, NULL, resstats_xmldesc, dns_resstatscounter_max, resstats_index, resstat_values, 0); if (result != ISC_R_SUCCESS) { json_object_put(counters); goto error; } if (json_object_get_object(counters)->count != 0) json_object_object_add(bindstats, "resstats", counters); else json_object_put(counters); #if HAVE_DNSTAP /* dnstap stat counters */ if (ns_g_server->dtenv != NULL) { isc_stats_t *dnstapstats = NULL; dns_dt_getstats(ns_g_server->dtenv, &dnstapstats); counters = json_object_new_object(); dumparg.result = ISC_R_SUCCESS; dumparg.arg = counters; result = dump_counters(dnstapstats, isc_statsformat_json, counters, NULL, dnstapstats_xmldesc, dns_dnstapcounter_max, dnstapstats_index, dnstapstat_values, 0); isc_stats_detach(&dnstapstats); if (result != ISC_R_SUCCESS) { json_object_put(counters); goto error; } if (json_object_get_object(counters)->count != 0) json_object_object_add(bindstats, "dnstapstats", counters); else json_object_put(counters); } #endif } if ((flags & (STATS_JSON_ZONES | STATS_JSON_SERVER)) != 0) { viewlist = json_object_new_object(); CHECKMEM(viewlist); json_object_object_add(bindstats, "views", viewlist); view = ISC_LIST_HEAD(server->viewlist); while (view != NULL) { json_object *za, *v = json_object_new_object(); CHECKMEM(v); json_object_object_add(viewlist, view->name, v); za = json_object_new_array(); CHECKMEM(za); if ((flags & STATS_JSON_ZONES) != 0) { result = dns_zt_apply(view->zonetable, ISC_TRUE, zone_jsonrender, za); if (result != ISC_R_SUCCESS) { goto error; } } if (json_object_array_length(za) != 0) json_object_object_add(v, "zones", za); else json_object_put(za); if ((flags & STATS_JSON_SERVER) != 0) { json_object *res; dns_stats_t *dstats; isc_stats_t *istats; res = json_object_new_object(); CHECKMEM(res); json_object_object_add(v, "resolver", res); istats = view->resstats; if (istats != NULL) { counters = json_object_new_object(); CHECKMEM(counters); result = dump_counters(istats, isc_statsformat_json, counters, NULL, resstats_xmldesc, dns_resstatscounter_max, resstats_index, resstat_values, 0); if (result != ISC_R_SUCCESS) { json_object_put(counters); result = dumparg.result; goto error; } json_object_object_add(res, "stats", counters); } dstats = view->resquerystats; if (dstats != NULL) { counters = json_object_new_object(); CHECKMEM(counters); dumparg.arg = counters; dumparg.result = ISC_R_SUCCESS; dns_rdatatypestats_dump(dstats, rdtypestat_dump, &dumparg, 0); if (dumparg.result != ISC_R_SUCCESS) { json_object_put(counters); result = dumparg.result; goto error; } json_object_object_add(res, "qtypes", counters); } dstats = dns_db_getrrsetstats(view->cachedb); if (dstats != NULL) { counters = json_object_new_object(); CHECKMEM(counters); dumparg.arg = counters; dumparg.result = ISC_R_SUCCESS; dns_rdatasetstats_dump(dstats, rdatasetstats_dump, &dumparg, 0); if (dumparg.result != ISC_R_SUCCESS) { json_object_put(counters); result = dumparg.result; goto error; } json_object_object_add(res, "cache", counters); } counters = json_object_new_object(); CHECKMEM(counters); result = dns_cache_renderjson(view->cache, counters); if (result != ISC_R_SUCCESS) { json_object_put(counters); goto error; } json_object_object_add(res, "cachestats", counters); istats = view->adbstats; if (istats != NULL) { counters = json_object_new_object(); CHECKMEM(counters); result = dump_counters(istats, isc_statsformat_json, counters, NULL, adbstats_xmldesc, dns_adbstats_max, adbstats_index, adbstat_values, 0); if (result != ISC_R_SUCCESS) { json_object_put(counters); result = dumparg.result; goto error; } json_object_object_add(res, "adb", counters); } } view = ISC_LIST_NEXT(view, link); } } if ((flags & STATS_JSON_NET) != 0) { /* socket stat counters */ json_object *sockets; counters = json_object_new_object(); dumparg.result = ISC_R_SUCCESS; dumparg.arg = counters; result = dump_counters(server->sockstats, isc_statsformat_json, counters, NULL, sockstats_xmldesc, isc_sockstatscounter_max, sockstats_index, sockstat_values, 0); if (result != ISC_R_SUCCESS) { json_object_put(counters); goto error; } if (json_object_get_object(counters)->count != 0) json_object_object_add(bindstats, "sockstats", counters); else json_object_put(counters); sockets = json_object_new_object(); CHECKMEM(sockets); result = isc_socketmgr_renderjson(ns_g_socketmgr, sockets); if (result != ISC_R_SUCCESS) { json_object_put(sockets); goto error; } json_object_object_add(bindstats, "socketmgr", sockets); } if ((flags & STATS_JSON_TASKS) != 0) { json_object *tasks = json_object_new_object(); CHECKMEM(tasks); result = isc_taskmgr_renderjson(ns_g_taskmgr, tasks); if (result != ISC_R_SUCCESS) { json_object_put(tasks); goto error; } json_object_object_add(bindstats, "taskmgr", tasks); } if ((flags & STATS_JSON_MEM) != 0) { json_object *memory = json_object_new_object(); CHECKMEM(memory); result = isc_mem_renderjson(memory); if (result != ISC_R_SUCCESS) { json_object_put(memory); goto error; } json_object_object_add(bindstats, "memory", memory); } if ((flags & STATS_JSON_TRAFFIC) != 0) { traffic = json_object_new_object(); CHECKMEM(traffic); udpreq4 = json_object_new_object(); CHECKMEM(udpreq4); udpresp4 = json_object_new_object(); CHECKMEM(udpresp4); tcpreq4 = json_object_new_object(); CHECKMEM(tcpreq4); tcpresp4 = json_object_new_object(); CHECKMEM(tcpresp4); udpreq6 = json_object_new_object(); CHECKMEM(udpreq6); udpresp6 = json_object_new_object(); CHECKMEM(udpresp6); tcpreq6 = json_object_new_object(); CHECKMEM(tcpreq6); tcpresp6 = json_object_new_object(); CHECKMEM(tcpresp6); CHECK(dump_counters(server->udpinstats4, isc_statsformat_json, udpreq4, NULL, udpinsizestats_xmldesc, dns_sizecounter_in_max, udpinsizestats_index, udpinsizestat_values, 0)); CHECK(dump_counters(server->udpoutstats4, isc_statsformat_json, udpresp4, NULL, udpoutsizestats_xmldesc, dns_sizecounter_out_max, udpoutsizestats_index, udpoutsizestat_values, 0)); CHECK(dump_counters(server->tcpinstats4, isc_statsformat_json, tcpreq4, NULL, tcpinsizestats_xmldesc, dns_sizecounter_in_max, tcpinsizestats_index, tcpinsizestat_values, 0)); CHECK(dump_counters(server->tcpoutstats4, isc_statsformat_json, tcpresp4, NULL, tcpoutsizestats_xmldesc, dns_sizecounter_out_max, tcpoutsizestats_index, tcpoutsizestat_values, 0)); CHECK(dump_counters(server->udpinstats6, isc_statsformat_json, udpreq6, NULL, udpinsizestats_xmldesc, dns_sizecounter_in_max, udpinsizestats_index, udpinsizestat_values, 0)); CHECK(dump_counters(server->udpoutstats6, isc_statsformat_json, udpresp6, NULL, udpoutsizestats_xmldesc, dns_sizecounter_out_max, udpoutsizestats_index, udpoutsizestat_values, 0)); CHECK(dump_counters(server->tcpinstats6, isc_statsformat_json, tcpreq6, NULL, tcpinsizestats_xmldesc, dns_sizecounter_in_max, tcpinsizestats_index, tcpinsizestat_values, 0)); CHECK(dump_counters(server->tcpoutstats6, isc_statsformat_json, tcpresp6, NULL, tcpoutsizestats_xmldesc, dns_sizecounter_out_max, tcpoutsizestats_index, tcpoutsizestat_values, 0)); json_object_object_add(traffic, "dns-udp-requests-sizes-received-ipv4", udpreq4); json_object_object_add(traffic, "dns-udp-responses-sizes-sent-ipv4", udpresp4); json_object_object_add(traffic, "dns-tcp-requests-sizes-received-ipv4", tcpreq4); json_object_object_add(traffic, "dns-tcp-responses-sizes-sent-ipv4", tcpresp4); json_object_object_add(traffic, "dns-udp-requests-sizes-received-ipv6", udpreq6); json_object_object_add(traffic, "dns-udp-responses-sizes-sent-ipv6", udpresp6); json_object_object_add(traffic, "dns-tcp-requests-sizes-received-ipv6", tcpreq6); json_object_object_add(traffic, "dns-tcp-responses-sizes-sent-ipv6", tcpresp6); json_object_object_add(bindstats, "traffic", traffic); udpreq4 = NULL; udpresp4 = NULL; tcpreq4 = NULL; tcpresp4 = NULL; udpreq6 = NULL; udpresp6 = NULL; tcpreq6 = NULL; tcpresp6 = NULL; traffic = NULL; } *msg = json_object_to_json_string_ext(bindstats, JSON_C_TO_STRING_PRETTY); *msglen = strlen(*msg); if (rootp != NULL) { *rootp = bindstats; bindstats = NULL; } result = ISC_R_SUCCESS; error: if (udpreq4 != NULL) json_object_put(udpreq4); if (udpresp4 != NULL) json_object_put(udpresp4); if (tcpreq4 != NULL) json_object_put(tcpreq4); if (tcpresp4 != NULL) json_object_put(tcpresp4); if (udpreq6 != NULL) json_object_put(udpreq6); if (udpresp6 != NULL) json_object_put(udpresp6); if (tcpreq6 != NULL) json_object_put(tcpreq6); if (tcpresp6 != NULL) json_object_put(tcpresp6); if (traffic != NULL) json_object_put(traffic); if (bindstats != NULL) json_object_put(bindstats); return (result); } static isc_result_t render_json(isc_uint32_t flags, const char *url, isc_httpdurl_t *urlinfo, const char *querystring, const char *headers, void *arg, unsigned int *retcode, const char **retmsg, const char **mimetype, isc_buffer_t *b, isc_httpdfree_t **freecb, void **freecb_args) { isc_result_t result; json_object *bindstats = NULL; ns_server_t *server = arg; const char *msg = NULL; size_t msglen = 0; char *p; UNUSED(url); UNUSED(urlinfo); UNUSED(headers); UNUSED(querystring); result = generatejson(server, &msglen, &msg, &bindstats, flags); if (result == ISC_R_SUCCESS) { *retcode = 200; *retmsg = "OK"; *mimetype = "application/json"; DE_CONST(msg, p); isc_buffer_reinit(b, p, msglen); isc_buffer_add(b, msglen); *freecb = wrap_jsonfree; *freecb_args = bindstats; } else isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, "failed at rendering JSON()"); return (result); } static isc_result_t render_json_all(const char *url, isc_httpdurl_t *urlinfo, const char *querystring, const char *headers, void *arg, unsigned int *retcode, const char **retmsg, const char **mimetype, isc_buffer_t *b, isc_httpdfree_t **freecb, void **freecb_args) { return (render_json(STATS_JSON_ALL, url, urlinfo, querystring, headers, arg, retcode, retmsg, mimetype, b, freecb, freecb_args)); } static isc_result_t render_json_status(const char *url, isc_httpdurl_t *urlinfo, const char *querystring, const char *headers, void *arg, unsigned int *retcode, const char **retmsg, const char **mimetype, isc_buffer_t *b, isc_httpdfree_t **freecb, void **freecb_args) { return (render_json(STATS_JSON_STATUS, url, urlinfo, querystring, headers, arg, retcode, retmsg, mimetype, b, freecb, freecb_args)); } static isc_result_t render_json_server(const char *url, isc_httpdurl_t *urlinfo, const char *querystring, const char *headers, void *arg, unsigned int *retcode, const char **retmsg, const char **mimetype, isc_buffer_t *b, isc_httpdfree_t **freecb, void **freecb_args) { return (render_json(STATS_JSON_SERVER, url, urlinfo, querystring, headers, arg, retcode, retmsg, mimetype, b, freecb, freecb_args)); } static isc_result_t render_json_zones(const char *url, isc_httpdurl_t *urlinfo, const char *querystring, const char *headers, void *arg, unsigned int *retcode, const char **retmsg, const char **mimetype, isc_buffer_t *b, isc_httpdfree_t **freecb, void **freecb_args) { return (render_json(STATS_JSON_ZONES, url, urlinfo, querystring, headers, arg, retcode, retmsg, mimetype, b, freecb, freecb_args)); } static isc_result_t render_json_mem(const char *url, isc_httpdurl_t *urlinfo, const char *querystring, const char *headers, void *arg, unsigned int *retcode, const char **retmsg, const char **mimetype, isc_buffer_t *b, isc_httpdfree_t **freecb, void **freecb_args) { return (render_json(STATS_JSON_MEM, url, urlinfo, querystring, headers, arg, retcode, retmsg, mimetype, b, freecb, freecb_args)); } static isc_result_t render_json_tasks(const char *url, isc_httpdurl_t *urlinfo, const char *querystring, const char *headers, void *arg, unsigned int *retcode, const char **retmsg, const char **mimetype, isc_buffer_t *b, isc_httpdfree_t **freecb, void **freecb_args) { return (render_json(STATS_JSON_TASKS, url, urlinfo, querystring, headers, arg, retcode, retmsg, mimetype, b, freecb, freecb_args)); } static isc_result_t render_json_net(const char *url, isc_httpdurl_t *urlinfo, const char *querystring, const char *headers, void *arg, unsigned int *retcode, const char **retmsg, const char **mimetype, isc_buffer_t *b, isc_httpdfree_t **freecb, void **freecb_args) { return (render_json(STATS_JSON_NET, url, urlinfo, querystring, headers, arg, retcode, retmsg, mimetype, b, freecb, freecb_args)); } static isc_result_t render_json_traffic(const char *url, isc_httpdurl_t *urlinfo, const char *querystring, const char *headers, void *arg, unsigned int *retcode, const char **retmsg, const char **mimetype, isc_buffer_t *b, isc_httpdfree_t **freecb, void **freecb_args) { return (render_json(STATS_JSON_TRAFFIC, url, urlinfo, querystring, headers, arg, retcode, retmsg, mimetype, b, freecb, freecb_args)); } #endif /* HAVE_JSON */ static isc_result_t render_xsl(const char *url, isc_httpdurl_t *urlinfo, const char *querystring, const char *headers, void *args, unsigned int *retcode, const char **retmsg, const char **mimetype, isc_buffer_t *b, isc_httpdfree_t **freecb, void **freecb_args) { isc_result_t result; UNUSED(url); UNUSED(querystring); UNUSED(args); *freecb = NULL; *freecb_args = NULL; *mimetype = "text/xslt+xml"; if (urlinfo->isstatic) { isc_time_t when; char *p = strcasestr(headers, "If-Modified-Since: "); if (p != NULL) { time_t t1, t2; p += strlen("If-Modified-Since: "); result = isc_time_parsehttptimestamp(p, &when); if (result != ISC_R_SUCCESS) goto send; result = isc_time_secondsastimet(&when, &t1); if (result != ISC_R_SUCCESS) goto send; result = isc_time_secondsastimet(&urlinfo->loadtime, &t2); if (result != ISC_R_SUCCESS) goto send; if (t1 < t2) goto send; *retcode = 304; *retmsg = "Not modified"; return (ISC_R_SUCCESS); } } send: *retcode = 200; *retmsg = "OK"; isc_buffer_reinit(b, xslmsg, strlen(xslmsg)); isc_buffer_add(b, strlen(xslmsg)); return (ISC_R_SUCCESS); } static void shutdown_listener(ns_statschannel_t *listener) { char socktext[ISC_SOCKADDR_FORMATSIZE]; isc_sockaddr_format(&listener->address, socktext, sizeof(socktext)); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_NOTICE, "stopping statistics channel on %s", socktext); isc_httpdmgr_shutdown(&listener->httpdmgr); } static isc_boolean_t client_ok(const isc_sockaddr_t *fromaddr, void *arg) { ns_statschannel_t *listener = arg; isc_netaddr_t netaddr; char socktext[ISC_SOCKADDR_FORMATSIZE]; int match; REQUIRE(listener != NULL); isc_netaddr_fromsockaddr(&netaddr, fromaddr); LOCK(&listener->lock); if (dns_acl_match(&netaddr, NULL, listener->acl, &ns_g_server->aclenv, &match, NULL) == ISC_R_SUCCESS && match > 0) { UNLOCK(&listener->lock); return (ISC_TRUE); } UNLOCK(&listener->lock); isc_sockaddr_format(fromaddr, socktext, sizeof(socktext)); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_WARNING, "rejected statistics connection from %s", socktext); return (ISC_FALSE); } static void destroy_listener(void *arg) { ns_statschannel_t *listener = arg; REQUIRE(listener != NULL); REQUIRE(!ISC_LINK_LINKED(listener, link)); /* We don't have to acquire the lock here since it's already unlinked */ dns_acl_detach(&listener->acl); DESTROYLOCK(&listener->lock); isc_mem_putanddetach(&listener->mctx, listener, sizeof(*listener)); } static isc_result_t add_listener(ns_server_t *server, ns_statschannel_t **listenerp, const cfg_obj_t *listen_params, const cfg_obj_t *config, isc_sockaddr_t *addr, cfg_aclconfctx_t *aclconfctx, const char *socktext) { isc_result_t result; ns_statschannel_t *listener; isc_task_t *task = NULL; isc_socket_t *sock = NULL; const cfg_obj_t *allow; dns_acl_t *new_acl = NULL; listener = isc_mem_get(server->mctx, sizeof(*listener)); if (listener == NULL) return (ISC_R_NOMEMORY); listener->httpdmgr = NULL; listener->address = *addr; listener->acl = NULL; listener->mctx = NULL; ISC_LINK_INIT(listener, link); result = isc_mutex_init(&listener->lock); if (result != ISC_R_SUCCESS) { isc_mem_put(server->mctx, listener, sizeof(*listener)); return (ISC_R_FAILURE); } isc_mem_attach(server->mctx, &listener->mctx); allow = cfg_tuple_get(listen_params, "allow"); if (allow != NULL && cfg_obj_islist(allow)) { result = cfg_acl_fromconfig(allow, config, ns_g_lctx, aclconfctx, listener->mctx, 0, &new_acl); } else result = dns_acl_any(listener->mctx, &new_acl); if (result != ISC_R_SUCCESS) goto cleanup; dns_acl_attach(new_acl, &listener->acl); dns_acl_detach(&new_acl); result = isc_task_create(ns_g_taskmgr, 0, &task); if (result != ISC_R_SUCCESS) goto cleanup; isc_task_setname(task, "statchannel", NULL); result = isc_socket_create(ns_g_socketmgr, isc_sockaddr_pf(addr), isc_sockettype_tcp, &sock); if (result != ISC_R_SUCCESS) goto cleanup; isc_socket_setname(sock, "statchannel", NULL); #ifndef ISC_ALLOW_MAPPED isc_socket_ipv6only(sock, ISC_TRUE); #endif result = isc_socket_bind(sock, addr, ISC_SOCKET_REUSEADDRESS); if (result != ISC_R_SUCCESS) goto cleanup; result = isc_httpdmgr_create(server->mctx, sock, task, client_ok, destroy_listener, listener, ns_g_timermgr, &listener->httpdmgr); if (result != ISC_R_SUCCESS) goto cleanup; #ifdef HAVE_LIBXML2 isc_httpdmgr_addurl(listener->httpdmgr, "/", render_xml_all, server); isc_httpdmgr_addurl(listener->httpdmgr, "/xml", render_xml_all, server); isc_httpdmgr_addurl(listener->httpdmgr, "/xml/v3", render_xml_all, server); isc_httpdmgr_addurl(listener->httpdmgr, "/xml/v3/status", render_xml_status, server); isc_httpdmgr_addurl(listener->httpdmgr, "/xml/v3/server", render_xml_server, server); isc_httpdmgr_addurl(listener->httpdmgr, "/xml/v3/zones", render_xml_zones, server); isc_httpdmgr_addurl(listener->httpdmgr, "/xml/v3/net", render_xml_net, server); isc_httpdmgr_addurl(listener->httpdmgr, "/xml/v3/tasks", render_xml_tasks, server); isc_httpdmgr_addurl(listener->httpdmgr, "/xml/v3/mem", render_xml_mem, server); isc_httpdmgr_addurl(listener->httpdmgr, "/xml/v3/traffic", render_xml_traffic, server); #endif #ifdef HAVE_JSON isc_httpdmgr_addurl(listener->httpdmgr, "/json", render_json_all, server); isc_httpdmgr_addurl(listener->httpdmgr, "/json/v1", render_json_all, server); isc_httpdmgr_addurl(listener->httpdmgr, "/json/v1/status", render_json_status, server); isc_httpdmgr_addurl(listener->httpdmgr, "/json/v1/server", render_json_server, server); isc_httpdmgr_addurl(listener->httpdmgr, "/json/v1/zones", render_json_zones, server); isc_httpdmgr_addurl(listener->httpdmgr, "/json/v1/tasks", render_json_tasks, server); isc_httpdmgr_addurl(listener->httpdmgr, "/json/v1/net", render_json_net, server); isc_httpdmgr_addurl(listener->httpdmgr, "/json/v1/mem", render_json_mem, server); isc_httpdmgr_addurl(listener->httpdmgr, "/json/v1/traffic", render_json_traffic, server); #endif isc_httpdmgr_addurl2(listener->httpdmgr, "/bind9.xsl", ISC_TRUE, render_xsl, server); *listenerp = listener; isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_NOTICE, "statistics channel listening on %s", socktext); cleanup: if (result != ISC_R_SUCCESS) { if (listener->acl != NULL) dns_acl_detach(&listener->acl); DESTROYLOCK(&listener->lock); isc_mem_putanddetach(&listener->mctx, listener, sizeof(*listener)); } if (task != NULL) isc_task_detach(&task); if (sock != NULL) isc_socket_detach(&sock); return (result); } static void update_listener(ns_server_t *server, ns_statschannel_t **listenerp, const cfg_obj_t *listen_params, const cfg_obj_t *config, isc_sockaddr_t *addr, cfg_aclconfctx_t *aclconfctx, const char *socktext) { ns_statschannel_t *listener; const cfg_obj_t *allow = NULL; dns_acl_t *new_acl = NULL; isc_result_t result = ISC_R_SUCCESS; for (listener = ISC_LIST_HEAD(server->statschannels); listener != NULL; listener = ISC_LIST_NEXT(listener, link)) if (isc_sockaddr_equal(addr, &listener->address)) break; if (listener == NULL) { *listenerp = NULL; return; } /* * Now, keep the old access list unless a new one can be made. */ allow = cfg_tuple_get(listen_params, "allow"); if (allow != NULL && cfg_obj_islist(allow)) { result = cfg_acl_fromconfig(allow, config, ns_g_lctx, aclconfctx, listener->mctx, 0, &new_acl); } else result = dns_acl_any(listener->mctx, &new_acl); if (result == ISC_R_SUCCESS) { LOCK(&listener->lock); dns_acl_detach(&listener->acl); dns_acl_attach(new_acl, &listener->acl); dns_acl_detach(&new_acl); UNLOCK(&listener->lock); } else { cfg_obj_log(listen_params, ns_g_lctx, ISC_LOG_WARNING, "couldn't install new acl for " "statistics channel %s: %s", socktext, isc_result_totext(result)); } *listenerp = listener; } isc_result_t ns_statschannels_configure(ns_server_t *server, const cfg_obj_t *config, cfg_aclconfctx_t *aclconfctx) { ns_statschannel_t *listener, *listener_next; ns_statschannellist_t new_listeners; const cfg_obj_t *statschannellist = NULL; const cfg_listelt_t *element, *element2; char socktext[ISC_SOCKADDR_FORMATSIZE]; RUNTIME_CHECK(isc_once_do(&once, init_desc) == ISC_R_SUCCESS); ISC_LIST_INIT(new_listeners); /* * Get the list of named.conf 'statistics-channels' statements. */ (void)cfg_map_get(config, "statistics-channels", &statschannellist); /* * Run through the new address/port list, noting sockets that are * already being listened on and moving them to the new list. * * Identifying duplicate addr/port combinations is left to either * the underlying config code, or to the bind attempt getting an * address-in-use error. */ if (statschannellist != NULL) { #ifndef EXTENDED_STATS isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_WARNING, "statistics-channels specified but not effective " "due to missing XML and/or JSON library"); #else /* EXTENDED_STATS */ #ifndef HAVE_LIBXML2 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_WARNING, "statistics-channels: XML library missing, " "only JSON stats will be available"); #endif /* !HAVE_LIBXML2 */ #ifndef HAVE_JSON isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_WARNING, "statistics-channels: JSON library missing, " "only XML stats will be available"); #endif /* !HAVE_JSON */ #endif /* EXTENDED_STATS */ for (element = cfg_list_first(statschannellist); element != NULL; element = cfg_list_next(element)) { const cfg_obj_t *statschannel; const cfg_obj_t *listenercfg = NULL; statschannel = cfg_listelt_value(element); (void)cfg_map_get(statschannel, "inet", &listenercfg); if (listenercfg == NULL) continue; for (element2 = cfg_list_first(listenercfg); element2 != NULL; element2 = cfg_list_next(element2)) { const cfg_obj_t *listen_params; const cfg_obj_t *obj; isc_sockaddr_t addr; listen_params = cfg_listelt_value(element2); obj = cfg_tuple_get(listen_params, "address"); addr = *cfg_obj_assockaddr(obj); if (isc_sockaddr_getport(&addr) == 0) isc_sockaddr_setport(&addr, NS_STATSCHANNEL_HTTPPORT); isc_sockaddr_format(&addr, socktext, sizeof(socktext)); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_DEBUG(9), "processing statistics " "channel %s", socktext); update_listener(server, &listener, listen_params, config, &addr, aclconfctx, socktext); if (listener != NULL) { /* * Remove the listener from the old * list, so it won't be shut down. */ ISC_LIST_UNLINK(server->statschannels, listener, link); } else { /* * This is a new listener. */ isc_result_t r; r = add_listener(server, &listener, listen_params, config, &addr, aclconfctx, socktext); if (r != ISC_R_SUCCESS) { cfg_obj_log(listen_params, ns_g_lctx, ISC_LOG_WARNING, "couldn't allocate " "statistics channel" " %s: %s", socktext, isc_result_totext(r)); } } if (listener != NULL) ISC_LIST_APPEND(new_listeners, listener, link); } } } for (listener = ISC_LIST_HEAD(server->statschannels); listener != NULL; listener = listener_next) { listener_next = ISC_LIST_NEXT(listener, link); ISC_LIST_UNLINK(server->statschannels, listener, link); shutdown_listener(listener); } ISC_LIST_APPENDLIST(server->statschannels, new_listeners, link); return (ISC_R_SUCCESS); } void ns_statschannels_shutdown(ns_server_t *server) { ns_statschannel_t *listener; while ((listener = ISC_LIST_HEAD(server->statschannels)) != NULL) { ISC_LIST_UNLINK(server->statschannels, listener, link); shutdown_listener(listener); } } isc_result_t ns_stats_dump(ns_server_t *server, FILE *fp) { isc_stdtime_t now; isc_result_t result; dns_view_t *view; dns_zone_t *zone, *next; stats_dumparg_t dumparg; isc_uint64_t nsstat_values[dns_nsstatscounter_max]; isc_uint64_t resstat_values[dns_resstatscounter_max]; isc_uint64_t adbstat_values[dns_adbstats_max]; isc_uint64_t zonestat_values[dns_zonestatscounter_max]; isc_uint64_t sockstat_values[isc_sockstatscounter_max]; RUNTIME_CHECK(isc_once_do(&once, init_desc) == ISC_R_SUCCESS); /* Set common fields */ dumparg.type = isc_statsformat_file; dumparg.arg = fp; isc_stdtime_get(&now); fprintf(fp, "+++ Statistics Dump +++ (%lu)\n", (unsigned long)now); fprintf(fp, "++ Incoming Requests ++\n"); dns_opcodestats_dump(server->opcodestats, opcodestat_dump, &dumparg, 0); fprintf(fp, "++ Incoming Queries ++\n"); dns_rdatatypestats_dump(server->rcvquerystats, rdtypestat_dump, &dumparg, 0); fprintf(fp, "++ Outgoing Rcodes ++\n"); dns_rcodestats_dump(server->rcodestats, rcodestat_dump, &dumparg, 0); fprintf(fp, "++ Outgoing Queries ++\n"); for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; view = ISC_LIST_NEXT(view, link)) { if (view->resquerystats == NULL) continue; if (strcmp(view->name, "_default") == 0) fprintf(fp, "[View: default]\n"); else fprintf(fp, "[View: %s]\n", view->name); dns_rdatatypestats_dump(view->resquerystats, rdtypestat_dump, &dumparg, 0); } fprintf(fp, "++ Name Server Statistics ++\n"); (void) dump_counters(server->nsstats, isc_statsformat_file, fp, NULL, nsstats_desc, dns_nsstatscounter_max, nsstats_index, nsstat_values, 0); fprintf(fp, "++ Zone Maintenance Statistics ++\n"); (void) dump_counters(server->zonestats, isc_statsformat_file, fp, NULL, zonestats_desc, dns_zonestatscounter_max, zonestats_index, zonestat_values, 0); fprintf(fp, "++ Resolver Statistics ++\n"); fprintf(fp, "[Common]\n"); (void) dump_counters(server->resolverstats, isc_statsformat_file, fp, NULL, resstats_desc, dns_resstatscounter_max, resstats_index, resstat_values, 0); for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; view = ISC_LIST_NEXT(view, link)) { if (view->resstats == NULL) continue; if (strcmp(view->name, "_default") == 0) fprintf(fp, "[View: default]\n"); else fprintf(fp, "[View: %s]\n", view->name); (void) dump_counters(view->resstats, isc_statsformat_file, fp, NULL, resstats_desc, dns_resstatscounter_max, resstats_index, resstat_values, 0); } fprintf(fp, "++ Cache Statistics ++\n"); for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; view = ISC_LIST_NEXT(view, link)) { if (strcmp(view->name, "_default") == 0) fprintf(fp, "[View: default]\n"); else fprintf(fp, "[View: %s (Cache: %s)]\n", view->name, dns_cache_getname(view->cache)); /* * Avoid dumping redundant statistics when the cache is shared. */ if (dns_view_iscacheshared(view)) continue; dns_cache_dumpstats(view->cache, fp); } fprintf(fp, "++ Cache DB RRsets ++\n"); for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; view = ISC_LIST_NEXT(view, link)) { dns_stats_t *cacherrstats; cacherrstats = dns_db_getrrsetstats(view->cachedb); if (cacherrstats == NULL) continue; if (strcmp(view->name, "_default") == 0) fprintf(fp, "[View: default]\n"); else fprintf(fp, "[View: %s (Cache: %s)]\n", view->name, dns_cache_getname(view->cache)); if (dns_view_iscacheshared(view)) { /* * Avoid dumping redundant statistics when the cache is * shared. */ continue; } dns_rdatasetstats_dump(cacherrstats, rdatasetstats_dump, &dumparg, 0); } fprintf(fp, "++ ADB stats ++\n"); for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; view = ISC_LIST_NEXT(view, link)) { if (view->adbstats == NULL) continue; if (strcmp(view->name, "_default") == 0) fprintf(fp, "[View: default]\n"); else fprintf(fp, "[View: %s]\n", view->name); (void) dump_counters(view->adbstats, isc_statsformat_file, fp, NULL, adbstats_desc, dns_adbstats_max, adbstats_index, adbstat_values, 0); } fprintf(fp, "++ Socket I/O Statistics ++\n"); (void) dump_counters(server->sockstats, isc_statsformat_file, fp, NULL, sockstats_desc, isc_sockstatscounter_max, sockstats_index, sockstat_values, 0); fprintf(fp, "++ Per Zone Query Statistics ++\n"); zone = NULL; for (result = dns_zone_first(server->zonemgr, &zone); result == ISC_R_SUCCESS; next = NULL, result = dns_zone_next(zone, &next), zone = next) { isc_stats_t *zonestats = dns_zone_getrequeststats(zone); if (zonestats != NULL) { char zonename[DNS_NAME_FORMATSIZE]; view = dns_zone_getview(zone); if (view == NULL) continue; dns_name_format(dns_zone_getorigin(zone), zonename, sizeof(zonename)); fprintf(fp, "[%s", zonename); if (strcmp(view->name, "_default") != 0) fprintf(fp, " (view: %s)", view->name); fprintf(fp, "]\n"); (void) dump_counters(zonestats, isc_statsformat_file, fp, NULL, nsstats_desc, dns_nsstatscounter_max, nsstats_index, nsstat_values, 0); } } fprintf(fp, "--- Statistics Dump --- (%lu)\n", (unsigned long)now); return (ISC_R_SUCCESS); /* this function currently always succeeds */ } bind9-9.11.3+dfsg/bin/named/tkeyconf.c000066400000000000000000000063331325250447100173630ustar00rootroot00000000000000/* * Copyright (C) 1999-2001, 2004-2007, 2009, 2010, 2012, 2014, 2016 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* $Id: tkeyconf.c,v 1.33 2010/12/20 23:47:20 tbox Exp $ */ /*! \file */ #include #include #include /* Required for HP/UX (and others?) */ #include #include #include #include #include #include #include #include #define RETERR(x) do { \ result = (x); \ if (result != ISC_R_SUCCESS) \ goto failure; \ } while (0) #include #define LOG(msg) \ isc_log_write(ns_g_lctx, \ NS_LOGCATEGORY_GENERAL, \ NS_LOGMODULE_SERVER, \ ISC_LOG_ERROR, \ "%s", msg) isc_result_t ns_tkeyctx_fromconfig(const cfg_obj_t *options, isc_mem_t *mctx, isc_entropy_t *ectx, dns_tkeyctx_t **tctxp) { isc_result_t result; dns_tkeyctx_t *tctx = NULL; const char *s; isc_uint32_t n; dns_fixedname_t fname; dns_name_t *name; isc_buffer_t b; const cfg_obj_t *obj; int type; result = dns_tkeyctx_create(mctx, ectx, &tctx); if (result != ISC_R_SUCCESS) return (result); obj = NULL; result = cfg_map_get(options, "tkey-dhkey", &obj); if (result == ISC_R_SUCCESS) { s = cfg_obj_asstring(cfg_tuple_get(obj, "name")); n = cfg_obj_asuint32(cfg_tuple_get(obj, "keyid")); isc_buffer_constinit(&b, s, strlen(s)); isc_buffer_add(&b, strlen(s)); dns_fixedname_init(&fname); name = dns_fixedname_name(&fname); RETERR(dns_name_fromtext(name, &b, dns_rootname, 0, NULL)); type = DST_TYPE_PUBLIC|DST_TYPE_PRIVATE|DST_TYPE_KEY; RETERR(dst_key_fromfile(name, (dns_keytag_t) n, DNS_KEYALG_DH, type, NULL, mctx, &tctx->dhkey)); } obj = NULL; result = cfg_map_get(options, "tkey-domain", &obj); if (result == ISC_R_SUCCESS) { s = cfg_obj_asstring(obj); isc_buffer_constinit(&b, s, strlen(s)); isc_buffer_add(&b, strlen(s)); dns_fixedname_init(&fname); name = dns_fixedname_name(&fname); RETERR(dns_name_fromtext(name, &b, dns_rootname, 0, NULL)); tctx->domain = isc_mem_get(mctx, sizeof(dns_name_t)); if (tctx->domain == NULL) { result = ISC_R_NOMEMORY; goto failure; } dns_name_init(tctx->domain, NULL); RETERR(dns_name_dup(name, mctx, tctx->domain)); } obj = NULL; result = cfg_map_get(options, "tkey-gssapi-credential", &obj); if (result == ISC_R_SUCCESS) { s = cfg_obj_asstring(obj); isc_buffer_constinit(&b, s, strlen(s)); isc_buffer_add(&b, strlen(s)); dns_fixedname_init(&fname); name = dns_fixedname_name(&fname); RETERR(dns_name_fromtext(name, &b, dns_rootname, 0, NULL)); RETERR(dst_gssapi_acquirecred(name, ISC_FALSE, &tctx->gsscred)); } obj = NULL; result = cfg_map_get(options, "tkey-gssapi-keytab", &obj); if (result == ISC_R_SUCCESS) { s = cfg_obj_asstring(obj); tctx->gssapi_keytab = isc_mem_strdup(mctx, s); if (tctx->gssapi_keytab == NULL) { result = ISC_R_NOMEMORY; goto failure; } } *tctxp = tctx; return (ISC_R_SUCCESS); failure: dns_tkeyctx_destroy(&tctx); return (result); } bind9-9.11.3+dfsg/bin/named/tsigconf.c000066400000000000000000000103201325250447100173440ustar00rootroot00000000000000/* * Copyright (C) 1999-2001, 2004-2007, 2009, 2011, 2012, 2016, 2017 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* $Id: tsigconf.c,v 1.35 2011/01/11 23:47:12 tbox Exp $ */ /*! \file */ #include #include #include #include #include #include #include #include #include #include #include #include static isc_result_t add_initial_keys(const cfg_obj_t *list, dns_tsig_keyring_t *ring, isc_mem_t *mctx) { dns_tsigkey_t *tsigkey = NULL; const cfg_listelt_t *element; const cfg_obj_t *key = NULL; const char *keyid = NULL; unsigned char *secret = NULL; int secretalloc = 0; int secretlen = 0; isc_result_t ret; isc_stdtime_t now; isc_uint16_t bits; for (element = cfg_list_first(list); element != NULL; element = cfg_list_next(element)) { const cfg_obj_t *algobj = NULL; const cfg_obj_t *secretobj = NULL; dns_name_t keyname; dns_name_t *alg; const char *algstr; char keynamedata[1024]; isc_buffer_t keynamesrc, keynamebuf; const char *secretstr; isc_buffer_t secretbuf; key = cfg_listelt_value(element); keyid = cfg_obj_asstring(cfg_map_getname(key)); algobj = NULL; secretobj = NULL; (void)cfg_map_get(key, "algorithm", &algobj); (void)cfg_map_get(key, "secret", &secretobj); INSIST(algobj != NULL && secretobj != NULL); /* * Create the key name. */ dns_name_init(&keyname, NULL); isc_buffer_constinit(&keynamesrc, keyid, strlen(keyid)); isc_buffer_add(&keynamesrc, strlen(keyid)); isc_buffer_init(&keynamebuf, keynamedata, sizeof(keynamedata)); ret = dns_name_fromtext(&keyname, &keynamesrc, dns_rootname, DNS_NAME_DOWNCASE, &keynamebuf); if (ret != ISC_R_SUCCESS) goto failure; /* * Create the algorithm. */ algstr = cfg_obj_asstring(algobj); if (ns_config_getkeyalgorithm(algstr, &alg, &bits) != ISC_R_SUCCESS) { cfg_obj_log(algobj, ns_g_lctx, ISC_LOG_ERROR, "key '%s': has a unsupported algorithm '%s'", keyid, algstr); ret = DNS_R_BADALG; goto failure; } secretstr = cfg_obj_asstring(secretobj); secretalloc = secretlen = strlen(secretstr) * 3 / 4; secret = isc_mem_get(mctx, secretlen); if (secret == NULL) { ret = ISC_R_NOMEMORY; goto failure; } isc_buffer_init(&secretbuf, secret, secretlen); ret = isc_base64_decodestring(secretstr, &secretbuf); if (ret != ISC_R_SUCCESS) goto failure; secretlen = isc_buffer_usedlength(&secretbuf); isc_stdtime_get(&now); ret = dns_tsigkey_create(&keyname, alg, secret, secretlen, ISC_FALSE, NULL, now, now, mctx, ring, &tsigkey); isc_mem_put(mctx, secret, secretalloc); secret = NULL; if (ret != ISC_R_SUCCESS) goto failure; /* * Set digest bits. */ dst_key_setbits(tsigkey->key, bits); dns_tsigkey_detach(&tsigkey); } return (ISC_R_SUCCESS); failure: cfg_obj_log(key, ns_g_lctx, ISC_LOG_ERROR, "configuring key '%s': %s", keyid, isc_result_totext(ret)); if (secret != NULL) isc_mem_put(mctx, secret, secretalloc); return (ret); } isc_result_t ns_tsigkeyring_fromconfig(const cfg_obj_t *config, const cfg_obj_t *vconfig, isc_mem_t *mctx, dns_tsig_keyring_t **ringp) { const cfg_obj_t *maps[3]; const cfg_obj_t *keylist; dns_tsig_keyring_t *ring = NULL; isc_result_t result; int i; REQUIRE(ringp != NULL && *ringp == NULL); i = 0; if (config != NULL) maps[i++] = config; if (vconfig != NULL) maps[i++] = cfg_tuple_get(vconfig, "options"); maps[i] = NULL; result = dns_tsigkeyring_create(mctx, &ring); if (result != ISC_R_SUCCESS) return (result); for (i = 0; ; i++) { if (maps[i] == NULL) break; keylist = NULL; result = cfg_map_get(maps[i], "key", &keylist); if (result != ISC_R_SUCCESS) continue; result = add_initial_keys(keylist, ring, mctx); if (result != ISC_R_SUCCESS) goto failure; } *ringp = ring; return (ISC_R_SUCCESS); failure: dns_tsigkeyring_detach(&ring); return (result); } bind9-9.11.3+dfsg/bin/named/unix/000077500000000000000000000000001325250447100163535ustar00rootroot00000000000000bind9-9.11.3+dfsg/bin/named/unix/Makefile.in000066400000000000000000000013511325250447100204200ustar00rootroot00000000000000# Copyright (C) 1999-2001, 2004, 2007, 2009, 2011, 2012, 2016 Internet Systems Consortium, Inc. ("ISC") # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. # $Id: Makefile.in,v 1.15 2011/03/10 23:47:49 tbox Exp $ srcdir = @srcdir@ VPATH = @srcdir@ top_srcdir = @top_srcdir@ @BIND9_MAKE_INCLUDES@ CINCLUDES = -I${srcdir}/include -I${srcdir}/../include \ ${ISCCFG_INCLUDES} ${ISCCC_INCLUDES} \ ${DNS_INCLUDES} ${ISC_INCLUDES} @DST_OPENSSL_INC@ CDEFINES = @CRYPTO@ CWARNINGS = OBJS = os.@O@ dlz_dlopen_driver.@O@ SRCS = os.c dlz_dlopen_driver.c TARGETS = ${OBJS} @BIND9_MAKE_RULES@ bind9-9.11.3+dfsg/bin/named/unix/dlz_dlopen_driver.c000066400000000000000000000346561325250447100222420ustar00rootroot00000000000000/* * Copyright (C) 2011-2014, 2016, 2017 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* $Id$ */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef ISC_DLZ_DLOPEN static dns_sdlzimplementation_t *dlz_dlopen = NULL; typedef struct dlopen_data { isc_mem_t *mctx; char *dl_path; char *dlzname; void *dl_handle; void *dbdata; unsigned int flags; isc_mutex_t lock; int version; isc_boolean_t in_configure; dlz_dlopen_version_t *dlz_version; dlz_dlopen_create_t *dlz_create; dlz_dlopen_findzonedb_t *dlz_findzonedb; dlz_dlopen_lookup_t *dlz_lookup; dlz_dlopen_authority_t *dlz_authority; dlz_dlopen_allnodes_t *dlz_allnodes; dlz_dlopen_allowzonexfr_t *dlz_allowzonexfr; dlz_dlopen_newversion_t *dlz_newversion; dlz_dlopen_closeversion_t *dlz_closeversion; dlz_dlopen_configure_t *dlz_configure; dlz_dlopen_ssumatch_t *dlz_ssumatch; dlz_dlopen_addrdataset_t *dlz_addrdataset; dlz_dlopen_subrdataset_t *dlz_subrdataset; dlz_dlopen_delrdataset_t *dlz_delrdataset; dlz_dlopen_destroy_t *dlz_destroy; } dlopen_data_t; /* Modules can choose whether they are lock-safe or not. */ #define MAYBE_LOCK(cd) \ do { \ if ((cd->flags & DNS_SDLZFLAG_THREADSAFE) == 0 && \ cd->in_configure == ISC_FALSE) \ LOCK(&cd->lock); \ } while (0) #define MAYBE_UNLOCK(cd) \ do { \ if ((cd->flags & DNS_SDLZFLAG_THREADSAFE) == 0 && \ cd->in_configure == ISC_FALSE) \ UNLOCK(&cd->lock); \ } while (0) /* * Log a message at the given level. */ static void dlopen_log(int level, const char *fmt, ...) { va_list ap; va_start(ap, fmt); isc_log_vwrite(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(level), fmt, ap); va_end(ap); } /* * SDLZ methods */ static isc_result_t dlopen_dlz_allnodes(const char *zone, void *driverarg, void *dbdata, dns_sdlzallnodes_t *allnodes) { dlopen_data_t *cd = (dlopen_data_t *) dbdata; isc_result_t result; UNUSED(driverarg); if (cd->dlz_allnodes == NULL) { return (ISC_R_NOPERM); } MAYBE_LOCK(cd); result = cd->dlz_allnodes(zone, cd->dbdata, allnodes); MAYBE_UNLOCK(cd); return (result); } static isc_result_t dlopen_dlz_allowzonexfr(void *driverarg, void *dbdata, const char *name, const char *client) { dlopen_data_t *cd = (dlopen_data_t *) dbdata; isc_result_t result; UNUSED(driverarg); if (cd->dlz_allowzonexfr == NULL) { return (ISC_R_NOPERM); } MAYBE_LOCK(cd); result = cd->dlz_allowzonexfr(cd->dbdata, name, client); MAYBE_UNLOCK(cd); return (result); } static isc_result_t dlopen_dlz_authority(const char *zone, void *driverarg, void *dbdata, dns_sdlzlookup_t *lookup) { dlopen_data_t *cd = (dlopen_data_t *) dbdata; isc_result_t result; UNUSED(driverarg); if (cd->dlz_authority == NULL) { return (ISC_R_NOTIMPLEMENTED); } MAYBE_LOCK(cd); result = cd->dlz_authority(zone, cd->dbdata, lookup); MAYBE_UNLOCK(cd); return (result); } static isc_result_t dlopen_dlz_findzonedb(void *driverarg, void *dbdata, const char *name, dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo) { dlopen_data_t *cd = (dlopen_data_t *) dbdata; isc_result_t result; UNUSED(driverarg); MAYBE_LOCK(cd); result = cd->dlz_findzonedb(cd->dbdata, name, methods, clientinfo); MAYBE_UNLOCK(cd); return (result); } static isc_result_t dlopen_dlz_lookup(const char *zone, const char *name, void *driverarg, void *dbdata, dns_sdlzlookup_t *lookup, dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo) { dlopen_data_t *cd = (dlopen_data_t *) dbdata; isc_result_t result; UNUSED(driverarg); MAYBE_LOCK(cd); result = cd->dlz_lookup(zone, name, cd->dbdata, lookup, methods, clientinfo); MAYBE_UNLOCK(cd); return (result); } /* * Load a symbol from the library */ static void * dl_load_symbol(dlopen_data_t *cd, const char *symbol, isc_boolean_t mandatory) { void *ptr = dlsym(cd->dl_handle, symbol); if (ptr == NULL && mandatory) { dlopen_log(ISC_LOG_ERROR, "dlz_dlopen: library '%s' is missing " "required symbol '%s'", cd->dl_path, symbol); } return (ptr); } /* * Called at startup for each dlopen zone in named.conf */ static isc_result_t dlopen_dlz_create(const char *dlzname, unsigned int argc, char *argv[], void *driverarg, void **dbdata) { dlopen_data_t *cd; isc_mem_t *mctx = NULL; isc_result_t result = ISC_R_FAILURE; int dlopen_flags = 0; UNUSED(driverarg); if (argc < 2) { dlopen_log(ISC_LOG_ERROR, "dlz_dlopen driver for '%s' needs a path to " "the shared library", dlzname); return (ISC_R_FAILURE); } result = isc_mem_create(0, 0, &mctx); if (result != ISC_R_SUCCESS) return (result); cd = isc_mem_get(mctx, sizeof(*cd)); if (cd == NULL) { isc_mem_destroy(&mctx); return (ISC_R_NOMEMORY); } memset(cd, 0, sizeof(*cd)); cd->mctx = mctx; cd->dl_path = isc_mem_strdup(cd->mctx, argv[1]); if (cd->dl_path == NULL) { result = ISC_R_NOMEMORY; goto failed; } cd->dlzname = isc_mem_strdup(cd->mctx, dlzname); if (cd->dlzname == NULL) { result = ISC_R_NOMEMORY; goto failed; } /* Initialize the lock */ result = isc_mutex_init(&cd->lock); if (result != ISC_R_SUCCESS) goto failed; /* Open the library */ dlopen_flags = RTLD_NOW|RTLD_GLOBAL; #ifdef RTLD_DEEPBIND /* * If RTLD_DEEPBIND is available then use it. This can avoid * issues with a module using a different version of a system * library than one that bind9 uses. For example, bind9 may link * to MIT kerberos, but the module may use Heimdal. If we don't * use RTLD_DEEPBIND then we could end up with Heimdal functions * calling MIT functions, which leads to bizarre results (usually * a segfault). */ dlopen_flags |= RTLD_DEEPBIND; #endif cd->dl_handle = dlopen(cd->dl_path, dlopen_flags); if (cd->dl_handle == NULL) { dlopen_log(ISC_LOG_ERROR, "dlz_dlopen failed to open library '%s' - %s", cd->dl_path, dlerror()); result = ISC_R_FAILURE; goto failed; } /* Find the symbols */ cd->dlz_version = (dlz_dlopen_version_t *) dl_load_symbol(cd, "dlz_version", ISC_TRUE); cd->dlz_create = (dlz_dlopen_create_t *) dl_load_symbol(cd, "dlz_create", ISC_TRUE); cd->dlz_lookup = (dlz_dlopen_lookup_t *) dl_load_symbol(cd, "dlz_lookup", ISC_TRUE); cd->dlz_findzonedb = (dlz_dlopen_findzonedb_t *) dl_load_symbol(cd, "dlz_findzonedb", ISC_TRUE); if (cd->dlz_create == NULL || cd->dlz_version == NULL || cd->dlz_lookup == NULL || cd->dlz_findzonedb == NULL) { /* We're missing a required symbol */ result = ISC_R_FAILURE; goto failed; } cd->dlz_allowzonexfr = (dlz_dlopen_allowzonexfr_t *) dl_load_symbol(cd, "dlz_allowzonexfr", ISC_FALSE); cd->dlz_allnodes = (dlz_dlopen_allnodes_t *) dl_load_symbol(cd, "dlz_allnodes", ISC_TF(cd->dlz_allowzonexfr != NULL)); cd->dlz_authority = (dlz_dlopen_authority_t *) dl_load_symbol(cd, "dlz_authority", ISC_FALSE); cd->dlz_newversion = (dlz_dlopen_newversion_t *) dl_load_symbol(cd, "dlz_newversion", ISC_FALSE); cd->dlz_closeversion = (dlz_dlopen_closeversion_t *) dl_load_symbol(cd, "dlz_closeversion", ISC_TF(cd->dlz_newversion != NULL)); cd->dlz_configure = (dlz_dlopen_configure_t *) dl_load_symbol(cd, "dlz_configure", ISC_FALSE); cd->dlz_ssumatch = (dlz_dlopen_ssumatch_t *) dl_load_symbol(cd, "dlz_ssumatch", ISC_FALSE); cd->dlz_addrdataset = (dlz_dlopen_addrdataset_t *) dl_load_symbol(cd, "dlz_addrdataset", ISC_FALSE); cd->dlz_subrdataset = (dlz_dlopen_subrdataset_t *) dl_load_symbol(cd, "dlz_subrdataset", ISC_FALSE); cd->dlz_delrdataset = (dlz_dlopen_delrdataset_t *) dl_load_symbol(cd, "dlz_delrdataset", ISC_FALSE); cd->dlz_destroy = (dlz_dlopen_destroy_t *) dl_load_symbol(cd, "dlz_destroy", ISC_FALSE); /* Check the version of the API is the same */ cd->version = cd->dlz_version(&cd->flags); if (cd->version < (DLZ_DLOPEN_VERSION - DLZ_DLOPEN_AGE) || cd->version > DLZ_DLOPEN_VERSION) { dlopen_log(ISC_LOG_ERROR, "dlz_dlopen: %s: incorrect driver API version %d, " "requires %d", cd->dl_path, cd->version, DLZ_DLOPEN_VERSION); result = ISC_R_FAILURE; goto failed; } /* * Call the library's create function. Note that this is an * extended version of dlz create, with the addition of * named function pointers for helper functions that the * driver will need. This avoids the need for the backend to * link the BIND9 libraries */ MAYBE_LOCK(cd); result = cd->dlz_create(dlzname, argc-1, argv+1, &cd->dbdata, "log", dlopen_log, "putrr", dns_sdlz_putrr, "putnamedrr", dns_sdlz_putnamedrr, "writeable_zone", dns_dlz_writeablezone, NULL); MAYBE_UNLOCK(cd); if (result != ISC_R_SUCCESS) goto failed; *dbdata = cd; return (ISC_R_SUCCESS); failed: dlopen_log(ISC_LOG_ERROR, "dlz_dlopen of '%s' failed", dlzname); if (cd->dl_path != NULL) isc_mem_free(mctx, cd->dl_path); if (cd->dlzname != NULL) isc_mem_free(mctx, cd->dlzname); if (dlopen_flags != 0) (void) isc_mutex_destroy(&cd->lock); #ifdef HAVE_DLCLOSE if (cd->dl_handle) dlclose(cd->dl_handle); #endif isc_mem_put(mctx, cd, sizeof(*cd)); isc_mem_destroy(&mctx); return (result); } /* * Called when bind is shutting down */ static void dlopen_dlz_destroy(void *driverarg, void *dbdata) { dlopen_data_t *cd = (dlopen_data_t *) dbdata; isc_mem_t *mctx; UNUSED(driverarg); if (cd->dlz_destroy) { MAYBE_LOCK(cd); cd->dlz_destroy(cd->dbdata); MAYBE_UNLOCK(cd); } if (cd->dl_path) isc_mem_free(cd->mctx, cd->dl_path); if (cd->dlzname) isc_mem_free(cd->mctx, cd->dlzname); #ifdef HAVE_DLCLOSE if (cd->dl_handle) dlclose(cd->dl_handle); #endif (void) isc_mutex_destroy(&cd->lock); mctx = cd->mctx; isc_mem_put(mctx, cd, sizeof(*cd)); isc_mem_destroy(&mctx); } /* * Called to start a transaction */ static isc_result_t dlopen_dlz_newversion(const char *zone, void *driverarg, void *dbdata, void **versionp) { dlopen_data_t *cd = (dlopen_data_t *) dbdata; isc_result_t result; UNUSED(driverarg); if (cd->dlz_newversion == NULL) return (ISC_R_NOTIMPLEMENTED); MAYBE_LOCK(cd); result = cd->dlz_newversion(zone, cd->dbdata, versionp); MAYBE_UNLOCK(cd); return (result); } /* * Called to end a transaction */ static void dlopen_dlz_closeversion(const char *zone, isc_boolean_t commit, void *driverarg, void *dbdata, void **versionp) { dlopen_data_t *cd = (dlopen_data_t *) dbdata; UNUSED(driverarg); if (cd->dlz_newversion == NULL) { *versionp = NULL; return; } MAYBE_LOCK(cd); cd->dlz_closeversion(zone, commit, cd->dbdata, versionp); MAYBE_UNLOCK(cd); } /* * Called on startup to configure any writeable zones */ static isc_result_t dlopen_dlz_configure(dns_view_t *view, dns_dlzdb_t *dlzdb, void *driverarg, void *dbdata) { dlopen_data_t *cd = (dlopen_data_t *) dbdata; isc_result_t result; UNUSED(driverarg); if (cd->dlz_configure == NULL) return (ISC_R_SUCCESS); MAYBE_LOCK(cd); cd->in_configure = ISC_TRUE; result = cd->dlz_configure(view, dlzdb, cd->dbdata); cd->in_configure = ISC_FALSE; MAYBE_UNLOCK(cd); return (result); } /* * Check for authority to change a name. */ static isc_boolean_t dlopen_dlz_ssumatch(const char *signer, const char *name, const char *tcpaddr, const char *type, const char *key, isc_uint32_t keydatalen, unsigned char *keydata, void *driverarg, void *dbdata) { dlopen_data_t *cd = (dlopen_data_t *) dbdata; isc_boolean_t ret; UNUSED(driverarg); if (cd->dlz_ssumatch == NULL) return (ISC_FALSE); MAYBE_LOCK(cd); ret = cd->dlz_ssumatch(signer, name, tcpaddr, type, key, keydatalen, keydata, cd->dbdata); MAYBE_UNLOCK(cd); return (ret); } /* * Add an rdataset. */ static isc_result_t dlopen_dlz_addrdataset(const char *name, const char *rdatastr, void *driverarg, void *dbdata, void *version) { dlopen_data_t *cd = (dlopen_data_t *) dbdata; isc_result_t result; UNUSED(driverarg); if (cd->dlz_addrdataset == NULL) return (ISC_R_NOTIMPLEMENTED); MAYBE_LOCK(cd); result = cd->dlz_addrdataset(name, rdatastr, cd->dbdata, version); MAYBE_UNLOCK(cd); return (result); } /* * Subtract an rdataset. */ static isc_result_t dlopen_dlz_subrdataset(const char *name, const char *rdatastr, void *driverarg, void *dbdata, void *version) { dlopen_data_t *cd = (dlopen_data_t *) dbdata; isc_result_t result; UNUSED(driverarg); if (cd->dlz_subrdataset == NULL) return (ISC_R_NOTIMPLEMENTED); MAYBE_LOCK(cd); result = cd->dlz_subrdataset(name, rdatastr, cd->dbdata, version); MAYBE_UNLOCK(cd); return (result); } /* * Delete a rdataset. */ static isc_result_t dlopen_dlz_delrdataset(const char *name, const char *type, void *driverarg, void *dbdata, void *version) { dlopen_data_t *cd = (dlopen_data_t *) dbdata; isc_result_t result; UNUSED(driverarg); if (cd->dlz_delrdataset == NULL) return (ISC_R_NOTIMPLEMENTED); MAYBE_LOCK(cd); result = cd->dlz_delrdataset(name, type, cd->dbdata, version); MAYBE_UNLOCK(cd); return (result); } static dns_sdlzmethods_t dlz_dlopen_methods = { dlopen_dlz_create, dlopen_dlz_destroy, dlopen_dlz_findzonedb, dlopen_dlz_lookup, dlopen_dlz_authority, dlopen_dlz_allnodes, dlopen_dlz_allowzonexfr, dlopen_dlz_newversion, dlopen_dlz_closeversion, dlopen_dlz_configure, dlopen_dlz_ssumatch, dlopen_dlz_addrdataset, dlopen_dlz_subrdataset, dlopen_dlz_delrdataset }; #endif /* * Register driver with BIND */ isc_result_t dlz_dlopen_init(isc_mem_t *mctx) { #ifndef ISC_DLZ_DLOPEN UNUSED(mctx); return (ISC_R_NOTIMPLEMENTED); #else isc_result_t result; dlopen_log(2, "Registering DLZ_dlopen driver"); result = dns_sdlzregister("dlopen", &dlz_dlopen_methods, NULL, DNS_SDLZFLAG_RELATIVEOWNER | DNS_SDLZFLAG_RELATIVERDATA | DNS_SDLZFLAG_THREADSAFE, mctx, &dlz_dlopen); if (result != ISC_R_SUCCESS) { UNEXPECTED_ERROR(__FILE__, __LINE__, "dns_sdlzregister() failed: %s", isc_result_totext(result)); result = ISC_R_UNEXPECTED; } return (result); #endif } /* * Unregister the driver */ void dlz_dlopen_clear(void) { #ifdef ISC_DLZ_DLOPEN dlopen_log(2, "Unregistering DLZ_dlopen driver"); if (dlz_dlopen != NULL) dns_sdlzunregister(&dlz_dlopen); #endif } bind9-9.11.3+dfsg/bin/named/unix/include/000077500000000000000000000000001325250447100177765ustar00rootroot00000000000000bind9-9.11.3+dfsg/bin/named/unix/include/named/000077500000000000000000000000001325250447100210625ustar00rootroot00000000000000bind9-9.11.3+dfsg/bin/named/unix/include/named/os.h000066400000000000000000000022671325250447100216630ustar00rootroot00000000000000/* * Copyright (C) 1999-2002, 2004, 2005, 2007-2009, 2014, 2016, 2017 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef NS_OS_H #define NS_OS_H 1 /*! \file */ #include #include void ns_os_init(const char *progname); void ns_os_daemonize(void); void ns_os_opendevnull(void); void ns_os_closedevnull(void); void ns_os_chroot(const char *root); void ns_os_inituserinfo(const char *username); void ns_os_changeuser(void); uid_t ns_os_uid(void); void ns_os_adjustnofile(void); void ns_os_minprivs(void); FILE * ns_os_openfile(const char *filename, mode_t mode, isc_boolean_t switch_user); void ns_os_writepidfile(const char *filename, isc_boolean_t first_time); isc_boolean_t ns_os_issingleton(const char *filename); void ns_os_shutdown(void); isc_result_t ns_os_gethostname(char *buf, size_t len); void ns_os_shutdownmsg(char *command, isc_buffer_t *text); void ns_os_tzset(void); void ns_os_started(void); char * ns_os_uname(void); #endif /* NS_OS_H */ bind9-9.11.3+dfsg/bin/named/unix/os.c000066400000000000000000000577241325250447100171570ustar00rootroot00000000000000/* * Copyright (C) 1999-2002, 2004-2011, 2013-2017 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /*! \file */ #include #include #include /* dev_t FreeBSD 2.1 */ #include #ifdef HAVE_UNAME #include #endif #include #include #include #include /* Required for initgroups() on IRIX. */ #include #include #include #include #include #ifdef HAVE_TZSET #include #endif #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_LIBSCF #include #endif static char *pidfile = NULL; static char *lockfile = NULL; static int devnullfd = -1; static int singletonfd = -1; #ifndef ISC_FACILITY #define ISC_FACILITY LOG_DAEMON #endif /* * If there's no , we don't care about */ #ifndef HAVE_LINUX_CAPABILITY_H #undef HAVE_SYS_PRCTL_H #endif /* * Linux defines: * (T) HAVE_LINUXTHREADS * (C) HAVE_SYS_CAPABILITY_H (or HAVE_LINUX_CAPABILITY_H) * (P) HAVE_SYS_PRCTL_H * The possible cases are: * none: setuid() normally * T: no setuid() * C: setuid() normally, drop caps (keep CAP_SETUID) * T+C: no setuid(), drop caps (don't keep CAP_SETUID) * T+C+P: setuid() early, drop caps (keep CAP_SETUID) * C+P: setuid() normally, drop caps (keep CAP_SETUID) * P: not possible * T+P: not possible * * if (C) * caps = BIND_SERVICE + CHROOT + SETGID * if ((T && C && P) || !T) * caps += SETUID * endif * capset(caps) * endif * if (T && C && P && -u) * setuid() * else if (T && -u) * fail * --> start threads * if (!T && -u) * setuid() * if (C && (P || !-u)) * caps = BIND_SERVICE * capset(caps) * endif * * It will be nice when Linux threads work properly with setuid(). */ #ifdef HAVE_LINUXTHREADS static pid_t mainpid = 0; #endif static struct passwd *runas_pw = NULL; static isc_boolean_t done_setuid = ISC_FALSE; static int dfd[2] = { -1, -1 }; #ifdef HAVE_LINUX_CAPABILITY_H static isc_boolean_t non_root = ISC_FALSE; static isc_boolean_t non_root_caps = ISC_FALSE; #ifdef HAVE_SYS_CAPABILITY_H #include #else #ifdef HAVE_LINUX_TYPES_H #include #endif /*% * We define _LINUX_FS_H to prevent it from being included. We don't need * anything from it, and the files it includes cause warnings with 2.2 * kernels, and compilation failures (due to conflicts between * and ) on 2.3 kernels. */ #define _LINUX_FS_H #include #include #ifndef SYS_capset #ifndef __NR_capset #include /* Slackware 4.0 needs this. */ #endif /* __NR_capset */ #define SYS_capset __NR_capset #endif /* SYS_capset */ #endif /* HAVE_SYS_CAPABILITY_H */ #ifdef HAVE_SYS_PRCTL_H #include /* Required for prctl(). */ /* * If the value of PR_SET_KEEPCAPS is not in , define it * here. This allows setuid() to work on systems running a new enough * kernel but with /usr/include/linux pointing to "standard" kernel * headers. */ #ifndef PR_SET_KEEPCAPS #define PR_SET_KEEPCAPS 8 #endif #endif /* HAVE_SYS_PRCTL_H */ #ifdef HAVE_LIBCAP #define SETCAPS_FUNC "cap_set_proc " #else typedef unsigned int cap_t; #define SETCAPS_FUNC "syscall(capset) " #endif /* HAVE_LIBCAP */ static void linux_setcaps(cap_t caps) { #ifndef HAVE_LIBCAP struct __user_cap_header_struct caphead; struct __user_cap_data_struct cap; #endif char strbuf[ISC_STRERRORSIZE]; if ((getuid() != 0 && !non_root_caps) || non_root) return; #ifndef HAVE_LIBCAP memset(&caphead, 0, sizeof(caphead)); caphead.version = _LINUX_CAPABILITY_VERSION; caphead.pid = 0; memset(&cap, 0, sizeof(cap)); cap.effective = caps; cap.permitted = caps; cap.inheritable = 0; #endif #ifdef HAVE_LIBCAP if (cap_set_proc(caps) < 0) { #else if (syscall(SYS_capset, &caphead, &cap) < 0) { #endif isc__strerror(errno, strbuf, sizeof(strbuf)); ns_main_earlyfatal(SETCAPS_FUNC "failed: %s:" " please ensure that the capset kernel" " module is loaded. see insmod(8)", strbuf); } } #ifdef HAVE_LIBCAP #define SET_CAP(flag) \ do { \ cap_flag_value_t curval; \ capval = (flag); \ err = cap_get_flag(curcaps, capval, CAP_PERMITTED, &curval); \ if (err != -1 && curval) { \ err = cap_set_flag(caps, CAP_EFFECTIVE, 1, &capval, CAP_SET); \ if (err == -1) { \ isc__strerror(errno, strbuf, sizeof(strbuf)); \ ns_main_earlyfatal("cap_set_proc failed: %s", strbuf); \ } \ \ err = cap_set_flag(caps, CAP_PERMITTED, 1, &capval, CAP_SET); \ if (err == -1) { \ isc__strerror(errno, strbuf, sizeof(strbuf)); \ ns_main_earlyfatal("cap_set_proc failed: %s", strbuf); \ } \ } \ } while (0) #define INIT_CAP \ do { \ caps = cap_init(); \ if (caps == NULL) { \ isc__strerror(errno, strbuf, sizeof(strbuf)); \ ns_main_earlyfatal("cap_init failed: %s", strbuf); \ } \ curcaps = cap_get_proc(); \ if (curcaps == NULL) { \ isc__strerror(errno, strbuf, sizeof(strbuf)); \ ns_main_earlyfatal("cap_get_proc failed: %s", strbuf); \ } \ } while (0) #define FREE_CAP \ { \ cap_free(caps); \ cap_free(curcaps); \ } while (0) #else #define SET_CAP(flag) do { caps |= (1 << (flag)); } while (0) #define INIT_CAP do { caps = 0; } while (0) #endif /* HAVE_LIBCAP */ static void linux_initialprivs(void) { cap_t caps; #ifdef HAVE_LIBCAP cap_t curcaps; cap_value_t capval; char strbuf[ISC_STRERRORSIZE]; int err; #endif /*% * We don't need most privileges, so we drop them right away. * Later on linux_minprivs() will be called, which will drop our * capabilities to the minimum needed to run the server. */ INIT_CAP; /* * We need to be able to bind() to privileged ports, notably port 53! */ SET_CAP(CAP_NET_BIND_SERVICE); /* * We need chroot() initially too. */ SET_CAP(CAP_SYS_CHROOT); #if defined(HAVE_SYS_PRCTL_H) || !defined(HAVE_LINUXTHREADS) /* * We can setuid() only if either the kernel supports keeping * capabilities after setuid() (which we don't know until we've * tried) or we're not using threads. If either of these is * true, we want the setuid capability. */ SET_CAP(CAP_SETUID); #endif /* * Since we call initgroups, we need this. */ SET_CAP(CAP_SETGID); /* * Without this, we run into problems reading a configuration file * owned by a non-root user and non-world-readable on startup. */ SET_CAP(CAP_DAC_READ_SEARCH); /* * XXX We might want to add CAP_SYS_RESOURCE, though it's not * clear it would work right given the way linuxthreads work. * XXXDCL But since we need to be able to set the maximum number * of files, the stack size, data size, and core dump size to * support named.conf options, this is now being added to test. */ SET_CAP(CAP_SYS_RESOURCE); /* * We need to be able to set the ownership of the containing * directory of the pid file when we create it. */ SET_CAP(CAP_CHOWN); linux_setcaps(caps); #ifdef HAVE_LIBCAP FREE_CAP; #endif } static void linux_minprivs(void) { cap_t caps; #ifdef HAVE_LIBCAP cap_t curcaps; cap_value_t capval; char strbuf[ISC_STRERRORSIZE]; int err; #endif INIT_CAP; /*% * Drop all privileges except the ability to bind() to privileged * ports. * * It's important that we drop CAP_SYS_CHROOT. If we didn't, it * chroot() could be used to escape from the chrooted area. */ SET_CAP(CAP_NET_BIND_SERVICE); /* * XXX We might want to add CAP_SYS_RESOURCE, though it's not * clear it would work right given the way linuxthreads work. * XXXDCL But since we need to be able to set the maximum number * of files, the stack size, data size, and core dump size to * support named.conf options, this is now being added to test. */ SET_CAP(CAP_SYS_RESOURCE); linux_setcaps(caps); #ifdef HAVE_LIBCAP FREE_CAP; #endif } #ifdef HAVE_SYS_PRCTL_H static void linux_keepcaps(void) { char strbuf[ISC_STRERRORSIZE]; /*% * Ask the kernel to allow us to keep our capabilities after we * setuid(). */ if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) < 0) { if (errno != EINVAL) { isc__strerror(errno, strbuf, sizeof(strbuf)); ns_main_earlyfatal("prctl() failed: %s", strbuf); } } else { non_root_caps = ISC_TRUE; if (getuid() != 0) non_root = ISC_TRUE; } } #endif #endif /* HAVE_LINUX_CAPABILITY_H */ static void setup_syslog(const char *progname) { int options; options = LOG_PID; #ifdef LOG_NDELAY options |= LOG_NDELAY; #endif openlog(isc_file_basename(progname), options, ISC_FACILITY); } void ns_os_init(const char *progname) { setup_syslog(progname); #ifdef HAVE_LINUX_CAPABILITY_H linux_initialprivs(); #endif #ifdef HAVE_LINUXTHREADS mainpid = getpid(); #endif #ifdef SIGXFSZ signal(SIGXFSZ, SIG_IGN); #endif } void ns_os_daemonize(void) { pid_t pid; char strbuf[ISC_STRERRORSIZE]; if (pipe(dfd) == -1) { isc__strerror(errno, strbuf, sizeof(strbuf)); ns_main_earlyfatal("pipe(): %s", strbuf); } pid = fork(); if (pid == -1) { isc__strerror(errno, strbuf, sizeof(strbuf)); ns_main_earlyfatal("fork(): %s", strbuf); } if (pid != 0) { int n; /* * Wait for the child to finish loading for the first time. * This would be so much simpler if fork() worked once we * were multi-threaded. */ (void)close(dfd[1]); do { char buf; n = read(dfd[0], &buf, 1); if (n == 1) _exit(0); } while (n == -1 && errno == EINTR); _exit(1); } (void)close(dfd[0]); /* * We're the child. */ #ifdef HAVE_LINUXTHREADS mainpid = getpid(); #endif if (setsid() == -1) { isc__strerror(errno, strbuf, sizeof(strbuf)); ns_main_earlyfatal("setsid(): %s", strbuf); } /* * Try to set stdin, stdout, and stderr to /dev/null, but press * on even if it fails. * * XXXMLG The close() calls here are unneeded on all but NetBSD, but * are harmless to include everywhere. dup2() is supposed to close * the FD if it is in use, but unproven-pthreads-0.16 is broken * and will end up closing the wrong FD. This will be fixed eventually, * and these calls will be removed. */ if (devnullfd != -1) { if (devnullfd != STDIN_FILENO) { (void)close(STDIN_FILENO); (void)dup2(devnullfd, STDIN_FILENO); } if (devnullfd != STDOUT_FILENO) { (void)close(STDOUT_FILENO); (void)dup2(devnullfd, STDOUT_FILENO); } if (devnullfd != STDERR_FILENO && !ns_g_keepstderr) { (void)close(STDERR_FILENO); (void)dup2(devnullfd, STDERR_FILENO); } } } void ns_os_started(void) { char buf = 0; /* * Signal to the parent that we started successfully. */ if (dfd[0] != -1 && dfd[1] != -1) { if (write(dfd[1], &buf, 1) != 1) ns_main_earlyfatal("unable to signal parent that we " "otherwise started successfully."); close(dfd[1]); dfd[0] = dfd[1] = -1; } } void ns_os_opendevnull(void) { devnullfd = open("/dev/null", O_RDWR, 0); } void ns_os_closedevnull(void) { if (devnullfd != STDIN_FILENO && devnullfd != STDOUT_FILENO && devnullfd != STDERR_FILENO) { close(devnullfd); devnullfd = -1; } } static isc_boolean_t all_digits(const char *s) { if (*s == '\0') return (ISC_FALSE); while (*s != '\0') { if (!isdigit((*s)&0xff)) return (ISC_FALSE); s++; } return (ISC_TRUE); } void ns_os_chroot(const char *root) { char strbuf[ISC_STRERRORSIZE]; #ifdef HAVE_LIBSCF ns_smf_chroot = 0; #endif if (root != NULL) { #ifdef HAVE_CHROOT if (chroot(root) < 0) { isc__strerror(errno, strbuf, sizeof(strbuf)); ns_main_earlyfatal("chroot(): %s", strbuf); } #else ns_main_earlyfatal("chroot(): disabled"); #endif if (chdir("/") < 0) { isc__strerror(errno, strbuf, sizeof(strbuf)); ns_main_earlyfatal("chdir(/): %s", strbuf); } #ifdef HAVE_LIBSCF /* Set ns_smf_chroot flag on successful chroot. */ ns_smf_chroot = 1; #endif } } void ns_os_inituserinfo(const char *username) { char strbuf[ISC_STRERRORSIZE]; if (username == NULL) return; if (all_digits(username)) runas_pw = getpwuid((uid_t)atoi(username)); else runas_pw = getpwnam(username); endpwent(); if (runas_pw == NULL) ns_main_earlyfatal("user '%s' unknown", username); if (getuid() == 0) { if (initgroups(runas_pw->pw_name, runas_pw->pw_gid) < 0) { isc__strerror(errno, strbuf, sizeof(strbuf)); ns_main_earlyfatal("initgroups(): %s", strbuf); } } } void ns_os_changeuser(void) { char strbuf[ISC_STRERRORSIZE]; if (runas_pw == NULL || done_setuid) return; done_setuid = ISC_TRUE; #ifdef HAVE_LINUXTHREADS #ifdef HAVE_LINUX_CAPABILITY_H if (!non_root_caps) ns_main_earlyfatal("-u with Linux threads not supported: " "requires kernel support for " "prctl(PR_SET_KEEPCAPS)"); #else ns_main_earlyfatal("-u with Linux threads not supported: " "no capabilities support or capabilities " "disabled at build time"); #endif #endif if (setgid(runas_pw->pw_gid) < 0) { isc__strerror(errno, strbuf, sizeof(strbuf)); ns_main_earlyfatal("setgid(): %s", strbuf); } if (setuid(runas_pw->pw_uid) < 0) { isc__strerror(errno, strbuf, sizeof(strbuf)); ns_main_earlyfatal("setuid(): %s", strbuf); } #if defined(HAVE_SYS_PRCTL_H) && defined(PR_SET_DUMPABLE) /* * Restore the ability of named to drop core after the setuid() * call has disabled it. */ if (prctl(PR_SET_DUMPABLE,1,0,0,0) < 0) { isc__strerror(errno, strbuf, sizeof(strbuf)); ns_main_earlywarning("prctl(PR_SET_DUMPABLE) failed: %s", strbuf); } #endif #if defined(HAVE_LINUX_CAPABILITY_H) && !defined(HAVE_LINUXTHREADS) linux_minprivs(); #endif } uid_t ns_os_uid(void) { if (runas_pw == NULL) return (0); return (runas_pw->pw_uid); } void ns_os_adjustnofile(void) { #ifdef HAVE_LINUXTHREADS isc_result_t result; isc_resourcevalue_t newvalue; /* * Linux: max number of open files specified by one thread doesn't seem * to apply to other threads on Linux. */ newvalue = ISC_RESOURCE_UNLIMITED; result = isc_resource_setlimit(isc_resource_openfiles, newvalue); if (result != ISC_R_SUCCESS) ns_main_earlywarning("couldn't adjust limit on open files"); #endif } void ns_os_minprivs(void) { #ifdef HAVE_SYS_PRCTL_H linux_keepcaps(); #endif #ifdef HAVE_LINUXTHREADS ns_os_changeuser(); /* Call setuid() before threads are started */ #endif #if defined(HAVE_LINUX_CAPABILITY_H) && defined(HAVE_LINUXTHREADS) linux_minprivs(); #endif } static int safe_open(const char *filename, mode_t mode, isc_boolean_t append) { int fd; struct stat sb; if (stat(filename, &sb) == -1) { if (errno != ENOENT) return (-1); } else if ((sb.st_mode & S_IFREG) == 0) { errno = EOPNOTSUPP; return (-1); } if (append) fd = open(filename, O_WRONLY|O_CREAT|O_APPEND, mode); else { if (unlink(filename) < 0 && errno != ENOENT) return (-1); fd = open(filename, O_WRONLY|O_CREAT|O_EXCL, mode); } return (fd); } static void cleanup_pidfile(void) { int n; if (pidfile != NULL) { n = unlink(pidfile); if (n == -1 && errno != ENOENT) ns_main_earlywarning("unlink '%s': failed", pidfile); free(pidfile); } pidfile = NULL; } static void cleanup_lockfile(void) { if (singletonfd != -1) { close(singletonfd); singletonfd = -1; } if (lockfile != NULL) { int n = unlink(lockfile); if (n == -1 && errno != ENOENT) ns_main_earlywarning("unlink '%s': failed", lockfile); free(lockfile); lockfile = NULL; } } /* * Ensure that a directory exists. * NOTE: This function overwrites the '/' characters in 'filename' with * nulls. The caller should copy the filename to a fresh buffer first. */ static int mkdirpath(char *filename, void (*report)(const char *, ...)) { char *slash = strrchr(filename, '/'); char strbuf[ISC_STRERRORSIZE]; unsigned int mode; if (slash != NULL && slash != filename) { struct stat sb; *slash = '\0'; if (stat(filename, &sb) == -1) { if (errno != ENOENT) { isc__strerror(errno, strbuf, sizeof(strbuf)); (*report)("couldn't stat '%s': %s", filename, strbuf); goto error; } if (mkdirpath(filename, report) == -1) goto error; /* * Handle "//", "/./" and "/../" in path. */ if (!strcmp(slash + 1, "") || !strcmp(slash + 1, ".") || !strcmp(slash + 1, "..")) { *slash = '/'; return (0); } mode = S_IRUSR | S_IWUSR | S_IXUSR; /* u=rwx */ mode |= S_IRGRP | S_IXGRP; /* g=rx */ mode |= S_IROTH | S_IXOTH; /* o=rx */ if (mkdir(filename, mode) == -1) { isc__strerror(errno, strbuf, sizeof(strbuf)); (*report)("couldn't mkdir '%s': %s", filename, strbuf); goto error; } if (runas_pw != NULL && chown(filename, runas_pw->pw_uid, runas_pw->pw_gid) == -1) { isc__strerror(errno, strbuf, sizeof(strbuf)); (*report)("couldn't chown '%s': %s", filename, strbuf); } } *slash = '/'; } return (0); error: *slash = '/'; return (-1); } static void setperms(uid_t uid, gid_t gid) { char strbuf[ISC_STRERRORSIZE]; #if !defined(HAVE_SETEGID) && defined(HAVE_SETRESGID) gid_t oldgid, tmpg; #endif #if !defined(HAVE_SETEUID) && defined(HAVE_SETRESUID) uid_t olduid, tmpu; #endif #if defined(HAVE_SETEGID) if (getegid() != gid && setegid(gid) == -1) { isc__strerror(errno, strbuf, sizeof(strbuf)); ns_main_earlywarning("unable to set effective gid to %ld: %s", (long)gid, strbuf); } #elif defined(HAVE_SETRESGID) if (getresgid(&tmpg, &oldgid, &tmpg) == -1 || oldgid != gid) { if (setresgid(-1, gid, -1) == -1) { isc__strerror(errno, strbuf, sizeof(strbuf)); ns_main_earlywarning("unable to set effective " "gid to %d: %s", gid, strbuf); } } #endif #if defined(HAVE_SETEUID) if (geteuid() != uid && seteuid(uid) == -1) { isc__strerror(errno, strbuf, sizeof(strbuf)); ns_main_earlywarning("unable to set effective uid to %ld: %s", (long)uid, strbuf); } #elif defined(HAVE_SETRESUID) if (getresuid(&tmpu, &olduid, &tmpu) == -1 || olduid != uid) { if (setresuid(-1, uid, -1) == -1) { isc__strerror(errno, strbuf, sizeof(strbuf)); ns_main_earlywarning("unable to set effective " "uid to %d: %s", uid, strbuf); } } #endif } FILE * ns_os_openfile(const char *filename, mode_t mode, isc_boolean_t switch_user) { char strbuf[ISC_STRERRORSIZE], *f; FILE *fp; int fd; /* * Make the containing directory if it doesn't exist. */ f = strdup(filename); if (f == NULL) { isc__strerror(errno, strbuf, sizeof(strbuf)); ns_main_earlywarning("couldn't strdup() '%s': %s", filename, strbuf); return (NULL); } if (mkdirpath(f, ns_main_earlywarning) == -1) { free(f); return (NULL); } free(f); if (switch_user && runas_pw != NULL) { #ifndef HAVE_LINUXTHREADS gid_t oldgid = getgid(); #endif /* Set UID/GID to the one we'll be running with eventually */ setperms(runas_pw->pw_uid, runas_pw->pw_gid); fd = safe_open(filename, mode, ISC_FALSE); #ifndef HAVE_LINUXTHREADS /* Restore UID/GID to root */ setperms(0, oldgid); #endif /* HAVE_LINUXTHREADS */ if (fd == -1) { #ifndef HAVE_LINUXTHREADS fd = safe_open(filename, mode, ISC_FALSE); if (fd != -1) { ns_main_earlywarning("Required root " "permissions to open " "'%s'.", filename); } else { ns_main_earlywarning("Could not open " "'%s'.", filename); } ns_main_earlywarning("Please check file and " "directory permissions " "or reconfigure the filename."); #else /* HAVE_LINUXTHREADS */ ns_main_earlywarning("Could not open " "'%s'.", filename); ns_main_earlywarning("Please check file and " "directory permissions " "or reconfigure the filename."); #endif /* HAVE_LINUXTHREADS */ } } else { fd = safe_open(filename, mode, ISC_FALSE); } if (fd < 0) { isc__strerror(errno, strbuf, sizeof(strbuf)); ns_main_earlywarning("could not open file '%s': %s", filename, strbuf); return (NULL); } fp = fdopen(fd, "w"); if (fp == NULL) { isc__strerror(errno, strbuf, sizeof(strbuf)); ns_main_earlywarning("could not fdopen() file '%s': %s", filename, strbuf); } return (fp); } void ns_os_writepidfile(const char *filename, isc_boolean_t first_time) { FILE *fh; pid_t pid; char strbuf[ISC_STRERRORSIZE]; void (*report)(const char *, ...); /* * The caller must ensure any required synchronization. */ report = first_time ? ns_main_earlyfatal : ns_main_earlywarning; cleanup_pidfile(); if (filename == NULL) return; pidfile = strdup(filename); if (pidfile == NULL) { isc__strerror(errno, strbuf, sizeof(strbuf)); (*report)("couldn't strdup() '%s': %s", filename, strbuf); return; } fh = ns_os_openfile(filename, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH, first_time); if (fh == NULL) { cleanup_pidfile(); return; } #ifdef HAVE_LINUXTHREADS pid = mainpid; #else pid = getpid(); #endif if (fprintf(fh, "%ld\n", (long)pid) < 0) { (*report)("fprintf() to pid file '%s' failed", filename); (void)fclose(fh); cleanup_pidfile(); return; } if (fflush(fh) == EOF) { (*report)("fflush() to pid file '%s' failed", filename); (void)fclose(fh); cleanup_pidfile(); return; } (void)fclose(fh); } isc_boolean_t ns_os_issingleton(const char *filename) { char strbuf[ISC_STRERRORSIZE]; struct flock lock; if (singletonfd != -1) return (ISC_TRUE); if (strcasecmp(filename, "none") == 0) return (ISC_TRUE); /* * Make the containing directory if it doesn't exist. */ lockfile = strdup(filename); if (lockfile == NULL) { isc__strerror(errno, strbuf, sizeof(strbuf)); ns_main_earlyfatal("couldn't allocate memory for '%s': %s", filename, strbuf); } else { int ret = mkdirpath(lockfile, ns_main_earlywarning); if (ret == -1) { ns_main_earlywarning("couldn't create '%s'", filename); cleanup_lockfile(); return (ISC_FALSE); } } /* * ns_os_openfile() uses safeopen() which removes any existing * files. We can't use that here. */ singletonfd = open(filename, O_WRONLY | O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); if (singletonfd == -1) { cleanup_lockfile(); return (ISC_FALSE); } memset(&lock, 0, sizeof(lock)); lock.l_type = F_WRLCK; lock.l_whence = SEEK_SET; lock.l_start = 0; lock.l_len = 1; /* Non-blocking (does not wait for lock) */ if (fcntl(singletonfd, F_SETLK, &lock) == -1) { close(singletonfd); singletonfd = -1; return (ISC_FALSE); } return (ISC_TRUE); } void ns_os_shutdown(void) { closelog(); cleanup_pidfile(); cleanup_lockfile(); } isc_result_t ns_os_gethostname(char *buf, size_t len) { int n; n = gethostname(buf, len); return ((n == 0) ? ISC_R_SUCCESS : ISC_R_FAILURE); } static char * next_token(char **stringp, const char *delim) { char *res; do { res = strsep(stringp, delim); if (res == NULL) break; } while (*res == '\0'); return (res); } void ns_os_shutdownmsg(char *command, isc_buffer_t *text) { char *input, *ptr; unsigned int n; pid_t pid; input = command; /* Skip the command name. */ ptr = next_token(&input, " \t"); if (ptr == NULL) return; ptr = next_token(&input, " \t"); if (ptr == NULL) return; if (strcmp(ptr, "-p") != 0) return; #ifdef HAVE_LINUXTHREADS pid = mainpid; #else pid = getpid(); #endif n = snprintf((char *)isc_buffer_used(text), isc_buffer_availablelength(text), "pid: %ld", (long)pid); /* Only send a message if it is complete. */ if (n > 0 && n < isc_buffer_availablelength(text)) isc_buffer_add(text, n); } void ns_os_tzset(void) { #ifdef HAVE_TZSET tzset(); #endif } static char unamebuf[BUFSIZ]; static char *unamep = NULL; static void getuname(void) { #ifdef HAVE_UNAME struct utsname uts; memset(&uts, 0, sizeof(uts)); if (uname(&uts) < 0) { snprintf(unamebuf, sizeof(unamebuf), "unknown architecture"); return; } snprintf(unamebuf, sizeof(unamebuf), "%s %s %s %s", uts.sysname, uts.machine, uts.release, uts.version); #else snprintf(unamebuf, sizeof(unamebuf), "unknown architecture"); #endif unamep = unamebuf; } char * ns_os_uname(void) { if (unamep == NULL) getuname(); return (unamep); } bind9-9.11.3+dfsg/bin/named/update.c000066400000000000000000002757651325250447100170440ustar00rootroot00000000000000/* * Copyright (C) 1999-2018 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* $Id: update.c,v 1.199 2011/12/22 07:32:40 each Exp $ */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /*! \file * \brief * This module implements dynamic update as in RFC2136. */ /* * XXX TODO: * - document strict minimality */ /**************************************************************************/ /*% * Log level for tracing dynamic update protocol requests. */ #define LOGLEVEL_PROTOCOL ISC_LOG_INFO /*% * Log level for low-level debug tracing. */ #define LOGLEVEL_DEBUG ISC_LOG_DEBUG(8) /*% * Check an operation for failure. These macros all assume that * the function using them has a 'result' variable and a 'failure' * label. */ #define CHECK(op) \ do { result = (op); \ if (result != ISC_R_SUCCESS) goto failure; \ } while (0) /*% * Fail unconditionally with result 'code', which must not * be ISC_R_SUCCESS. The reason for failure presumably has * been logged already. * * The test against ISC_R_SUCCESS is there to keep the Solaris compiler * from complaining about "end-of-loop code not reached". */ #define FAIL(code) \ do { \ result = (code); \ if (result != ISC_R_SUCCESS) goto failure; \ } while (0) /*% * Fail unconditionally and log as a client error. * The test against ISC_R_SUCCESS is there to keep the Solaris compiler * from complaining about "end-of-loop code not reached". */ #define FAILC(code, msg) \ do { \ const char *_what = "failed"; \ result = (code); \ switch (result) { \ case DNS_R_NXDOMAIN: \ case DNS_R_YXDOMAIN: \ case DNS_R_YXRRSET: \ case DNS_R_NXRRSET: \ _what = "unsuccessful"; \ } \ update_log(client, zone, LOGLEVEL_PROTOCOL, \ "update %s: %s (%s)", _what, \ msg, isc_result_totext(result)); \ if (result != ISC_R_SUCCESS) goto failure; \ } while (0) #define PREREQFAILC(code, msg) \ do { \ inc_stats(zone, dns_nsstatscounter_updatebadprereq); \ FAILC(code, msg); \ } while (0) #define FAILN(code, name, msg) \ do { \ const char *_what = "failed"; \ result = (code); \ switch (result) { \ case DNS_R_NXDOMAIN: \ case DNS_R_YXDOMAIN: \ case DNS_R_YXRRSET: \ case DNS_R_NXRRSET: \ _what = "unsuccessful"; \ } \ if (isc_log_wouldlog(ns_g_lctx, LOGLEVEL_PROTOCOL)) { \ char _nbuf[DNS_NAME_FORMATSIZE]; \ dns_name_format(name, _nbuf, sizeof(_nbuf)); \ update_log(client, zone, LOGLEVEL_PROTOCOL, \ "update %s: %s: %s (%s)", _what, _nbuf, \ msg, isc_result_totext(result)); \ } \ if (result != ISC_R_SUCCESS) goto failure; \ } while (0) #define PREREQFAILN(code, name, msg) \ do { \ inc_stats(zone, dns_nsstatscounter_updatebadprereq); \ FAILN(code, name, msg); \ } while (0) #define FAILNT(code, name, type, msg) \ do { \ const char *_what = "failed"; \ result = (code); \ switch (result) { \ case DNS_R_NXDOMAIN: \ case DNS_R_YXDOMAIN: \ case DNS_R_YXRRSET: \ case DNS_R_NXRRSET: \ _what = "unsuccessful"; \ } \ if (isc_log_wouldlog(ns_g_lctx, LOGLEVEL_PROTOCOL)) { \ char _nbuf[DNS_NAME_FORMATSIZE]; \ char _tbuf[DNS_RDATATYPE_FORMATSIZE]; \ dns_name_format(name, _nbuf, sizeof(_nbuf)); \ dns_rdatatype_format(type, _tbuf, sizeof(_tbuf)); \ update_log(client, zone, LOGLEVEL_PROTOCOL, \ "update %s: %s/%s: %s (%s)", \ _what, _nbuf, _tbuf, msg, \ isc_result_totext(result)); \ } \ if (result != ISC_R_SUCCESS) goto failure; \ } while (0) #define PREREQFAILNT(code, name, type, msg) \ do { \ inc_stats(zone, dns_nsstatscounter_updatebadprereq); \ FAILNT(code, name, type, msg); \ } while (0) /*% * Fail unconditionally and log as a server error. * The test against ISC_R_SUCCESS is there to keep the Solaris compiler * from complaining about "end-of-loop code not reached". */ #define FAILS(code, msg) \ do { \ result = (code); \ update_log(client, zone, LOGLEVEL_PROTOCOL, \ "error: %s: %s", \ msg, isc_result_totext(result)); \ if (result != ISC_R_SUCCESS) goto failure; \ } while (0) /* * Return TRUE if NS_CLIENTATTR_TCP is set in the attributes other FALSE. */ #define TCPCLIENT(client) (((client)->attributes & NS_CLIENTATTR_TCP) != 0) /**************************************************************************/ typedef struct rr rr_t; struct rr { /* dns_name_t name; */ isc_uint32_t ttl; dns_rdata_t rdata; }; typedef struct update_event update_event_t; struct update_event { ISC_EVENT_COMMON(update_event_t); dns_zone_t *zone; isc_result_t result; dns_message_t *answer; }; /*% * Prepare an RR for the addition of the new RR 'ctx->update_rr', * with TTL 'ctx->update_rr_ttl', to its rdataset, by deleting * the RRs if it is replaced by the new RR or has a conflicting TTL. * The necessary changes are appended to ctx->del_diff and ctx->add_diff; * we need to do all deletions before any additions so that we don't run * into transient states with conflicting TTLs. */ typedef struct { dns_db_t *db; dns_dbversion_t *ver; dns_diff_t *diff; dns_name_t *name; dns_name_t *oldname; dns_rdata_t *update_rr; dns_ttl_t update_rr_ttl; isc_boolean_t ignore_add; dns_diff_t del_diff; dns_diff_t add_diff; } add_rr_prepare_ctx_t; /**************************************************************************/ /* * Forward declarations. */ static void update_action(isc_task_t *task, isc_event_t *event); static void updatedone_action(isc_task_t *task, isc_event_t *event); static isc_result_t send_forward_event(ns_client_t *client, dns_zone_t *zone); static void forward_done(isc_task_t *task, isc_event_t *event); static isc_result_t add_rr_prepare_action(void *data, rr_t *rr); /**************************************************************************/ static void update_log(ns_client_t *client, dns_zone_t *zone, int level, const char *fmt, ...) ISC_FORMAT_PRINTF(4, 5); static void update_log(ns_client_t *client, dns_zone_t *zone, int level, const char *fmt, ...) { va_list ap; char message[4096]; char namebuf[DNS_NAME_FORMATSIZE]; char classbuf[DNS_RDATACLASS_FORMATSIZE]; if (client == NULL || zone == NULL) return; if (isc_log_wouldlog(ns_g_lctx, level) == ISC_FALSE) return; dns_name_format(dns_zone_getorigin(zone), namebuf, sizeof(namebuf)); dns_rdataclass_format(dns_zone_getclass(zone), classbuf, sizeof(classbuf)); va_start(ap, fmt); vsnprintf(message, sizeof(message), fmt, ap); va_end(ap); ns_client_log(client, NS_LOGCATEGORY_UPDATE, NS_LOGMODULE_UPDATE, level, "updating zone '%s/%s': %s", namebuf, classbuf, message); } static void update_log_cb(void *arg, dns_zone_t *zone, int level, const char *message) { update_log(arg, zone, level, "%s", message); } /*% * Increment updated-related statistics counters. */ static inline void inc_stats(dns_zone_t *zone, isc_statscounter_t counter) { isc_stats_increment(ns_g_server->nsstats, counter); if (zone != NULL) { isc_stats_t *zonestats = dns_zone_getrequeststats(zone); if (zonestats != NULL) isc_stats_increment(zonestats, counter); } } /*% * Check if we could have queried for the contents of this zone or * if the zone is potentially updateable. * If the zone can potentially be updated and the check failed then * log a error otherwise we log a informational message. */ static isc_result_t checkqueryacl(ns_client_t *client, dns_acl_t *queryacl, dns_name_t *zonename, dns_acl_t *updateacl, dns_ssutable_t *ssutable) { char namebuf[DNS_NAME_FORMATSIZE]; char classbuf[DNS_RDATACLASS_FORMATSIZE]; int level; isc_result_t result; result = ns_client_checkaclsilent(client, NULL, queryacl, ISC_TRUE); if (result != ISC_R_SUCCESS) { dns_name_format(zonename, namebuf, sizeof(namebuf)); dns_rdataclass_format(client->view->rdclass, classbuf, sizeof(classbuf)); level = (updateacl == NULL && ssutable == NULL) ? ISC_LOG_INFO : ISC_LOG_ERROR; ns_client_log(client, NS_LOGCATEGORY_UPDATE_SECURITY, NS_LOGMODULE_UPDATE, level, "update '%s/%s' denied due to allow-query", namebuf, classbuf); } else if (updateacl == NULL && ssutable == NULL) { dns_name_format(zonename, namebuf, sizeof(namebuf)); dns_rdataclass_format(client->view->rdclass, classbuf, sizeof(classbuf)); result = DNS_R_REFUSED; ns_client_log(client, NS_LOGCATEGORY_UPDATE_SECURITY, NS_LOGMODULE_UPDATE, ISC_LOG_INFO, "update '%s/%s' denied", namebuf, classbuf); } return (result); } /*% * Override the default acl logging when checking whether a client * can update the zone or whether we can forward the request to the * master based on IP address. * * 'message' contains the type of operation that is being attempted. * 'slave' indicates if this is a slave zone. If 'acl' is NULL then * log at debug=3. * If the zone has no access controls configured ('acl' == NULL && * 'has_ssutable == ISC_FALS) log the attempt at info, otherwise * at error. * * If the request was signed log that we received it. */ static isc_result_t checkupdateacl(ns_client_t *client, dns_acl_t *acl, const char *message, dns_name_t *zonename, isc_boolean_t slave, isc_boolean_t has_ssutable) { char namebuf[DNS_NAME_FORMATSIZE]; char classbuf[DNS_RDATACLASS_FORMATSIZE]; int level = ISC_LOG_ERROR; const char *msg = "denied"; isc_result_t result; if (slave && acl == NULL) { result = DNS_R_NOTIMP; level = ISC_LOG_DEBUG(3); msg = "disabled"; } else { result = ns_client_checkaclsilent(client, NULL, acl, ISC_FALSE); if (result == ISC_R_SUCCESS) { level = ISC_LOG_DEBUG(3); msg = "approved"; } else if (acl == NULL && !has_ssutable) { level = ISC_LOG_INFO; } } if (client->signer != NULL) { dns_name_format(client->signer, namebuf, sizeof(namebuf)); ns_client_log(client, NS_LOGCATEGORY_UPDATE_SECURITY, NS_LOGMODULE_UPDATE, ISC_LOG_INFO, "signer \"%s\" %s", namebuf, msg); } dns_name_format(zonename, namebuf, sizeof(namebuf)); dns_rdataclass_format(client->view->rdclass, classbuf, sizeof(classbuf)); ns_client_log(client, NS_LOGCATEGORY_UPDATE_SECURITY, NS_LOGMODULE_UPDATE, level, "%s '%s/%s' %s", message, namebuf, classbuf, msg); return (result); } /*% * Update a single RR in version 'ver' of 'db' and log the * update in 'diff'. * * Ensures: * \li '*tuple' == NULL. Either the tuple is freed, or its * ownership has been transferred to the diff. */ static isc_result_t do_one_tuple(dns_difftuple_t **tuple, dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff) { dns_diff_t temp_diff; isc_result_t result; /* * Create a singleton diff. */ dns_diff_init(diff->mctx, &temp_diff); ISC_LIST_APPEND(temp_diff.tuples, *tuple, link); /* * Apply it to the database. */ result = dns_diff_apply(&temp_diff, db, ver); ISC_LIST_UNLINK(temp_diff.tuples, *tuple, link); if (result != ISC_R_SUCCESS) { dns_difftuple_free(tuple); return (result); } /* * Merge it into the current pending journal entry. */ dns_diff_appendminimal(diff, tuple); /* * Do not clear temp_diff. */ return (ISC_R_SUCCESS); } /*% * Perform the updates in 'updates' in version 'ver' of 'db' and log the * update in 'diff'. * * Ensures: * \li 'updates' is empty. */ static isc_result_t do_diff(dns_diff_t *updates, dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff) { isc_result_t result; while (! ISC_LIST_EMPTY(updates->tuples)) { dns_difftuple_t *t = ISC_LIST_HEAD(updates->tuples); ISC_LIST_UNLINK(updates->tuples, t, link); CHECK(do_one_tuple(&t, db, ver, diff)); } return (ISC_R_SUCCESS); failure: dns_diff_clear(diff); return (result); } static isc_result_t update_one_rr(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff, dns_diffop_t op, dns_name_t *name, dns_ttl_t ttl, dns_rdata_t *rdata) { dns_difftuple_t *tuple = NULL; isc_result_t result; result = dns_difftuple_create(diff->mctx, op, name, ttl, rdata, &tuple); if (result != ISC_R_SUCCESS) return (result); return (do_one_tuple(&tuple, db, ver, diff)); } /**************************************************************************/ /* * Callback-style iteration over rdatasets and rdatas. * * foreach_rrset() can be used to iterate over the RRsets * of a name and call a callback function with each * one. Similarly, foreach_rr() can be used to iterate * over the individual RRs at name, optionally restricted * to RRs of a given type. * * The callback functions are called "actions" and take * two arguments: a void pointer for passing arbitrary * context information, and a pointer to the current RRset * or RR. By convention, their names end in "_action". */ /* * XXXRTH We might want to make this public somewhere in libdns. */ /*% * Function type for foreach_rrset() iterator actions. */ typedef isc_result_t rrset_func(void *data, dns_rdataset_t *rrset); /*% * Function type for foreach_rr() iterator actions. */ typedef isc_result_t rr_func(void *data, rr_t *rr); /*% * Internal context struct for foreach_node_rr(). */ typedef struct { rr_func * rr_action; void * rr_action_data; } foreach_node_rr_ctx_t; /*% * Internal helper function for foreach_node_rr(). */ static isc_result_t foreach_node_rr_action(void *data, dns_rdataset_t *rdataset) { isc_result_t result; foreach_node_rr_ctx_t *ctx = data; for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS; result = dns_rdataset_next(rdataset)) { rr_t rr = { 0, DNS_RDATA_INIT }; dns_rdataset_current(rdataset, &rr.rdata); rr.ttl = rdataset->ttl; result = (*ctx->rr_action)(ctx->rr_action_data, &rr); if (result != ISC_R_SUCCESS) return (result); } if (result != ISC_R_NOMORE) return (result); return (ISC_R_SUCCESS); } /*% * For each rdataset of 'name' in 'ver' of 'db', call 'action' * with the rdataset and 'action_data' as arguments. If the name * does not exist, do nothing. * * If 'action' returns an error, abort iteration and return the error. */ static isc_result_t foreach_rrset(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, rrset_func *action, void *action_data) { isc_result_t result; dns_dbnode_t *node; dns_rdatasetiter_t *iter; dns_clientinfomethods_t cm; dns_clientinfo_t ci; dns_dbversion_t *oldver = NULL; dns_clientinfomethods_init(&cm, ns_client_sourceip); /* * Only set the clientinfo 'versionp' if the new version is * different from the current version */ dns_db_currentversion(db, &oldver); dns_clientinfo_init(&ci, NULL, (ver != oldver) ? ver : NULL); dns_db_closeversion(db, &oldver, ISC_FALSE); node = NULL; result = dns_db_findnodeext(db, name, ISC_FALSE, &cm, &ci, &node); if (result == ISC_R_NOTFOUND) return (ISC_R_SUCCESS); if (result != ISC_R_SUCCESS) return (result); iter = NULL; result = dns_db_allrdatasets(db, node, ver, (isc_stdtime_t) 0, &iter); if (result != ISC_R_SUCCESS) goto cleanup_node; for (result = dns_rdatasetiter_first(iter); result == ISC_R_SUCCESS; result = dns_rdatasetiter_next(iter)) { dns_rdataset_t rdataset; dns_rdataset_init(&rdataset); dns_rdatasetiter_current(iter, &rdataset); result = (*action)(action_data, &rdataset); dns_rdataset_disassociate(&rdataset); if (result != ISC_R_SUCCESS) goto cleanup_iterator; } if (result == ISC_R_NOMORE) result = ISC_R_SUCCESS; cleanup_iterator: dns_rdatasetiter_destroy(&iter); cleanup_node: dns_db_detachnode(db, &node); return (result); } /*% * For each RR of 'name' in 'ver' of 'db', call 'action' * with the RR and 'action_data' as arguments. If the name * does not exist, do nothing. * * If 'action' returns an error, abort iteration * and return the error. */ static isc_result_t foreach_node_rr(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, rr_func *rr_action, void *rr_action_data) { foreach_node_rr_ctx_t ctx; ctx.rr_action = rr_action; ctx.rr_action_data = rr_action_data; return (foreach_rrset(db, ver, name, foreach_node_rr_action, &ctx)); } /*% * For each of the RRs specified by 'db', 'ver', 'name', 'type', * (which can be dns_rdatatype_any to match any type), and 'covers', call * 'action' with the RR and 'action_data' as arguments. If the name * does not exist, or if no RRset of the given type exists at the name, * do nothing. * * If 'action' returns an error, abort iteration and return the error. */ static isc_result_t foreach_rr(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, dns_rdatatype_t type, dns_rdatatype_t covers, rr_func *rr_action, void *rr_action_data) { isc_result_t result; dns_dbnode_t *node; dns_rdataset_t rdataset; dns_clientinfomethods_t cm; dns_clientinfo_t ci; dns_dbversion_t *oldver = NULL; dns_fixedname_t fixed; dns_clientinfomethods_init(&cm, ns_client_sourceip); /* * Only set the clientinfo 'versionp' if the new version is * different from the current version */ dns_db_currentversion(db, &oldver); dns_clientinfo_init(&ci, NULL, (ver != oldver) ? ver : NULL); dns_db_closeversion(db, &oldver, ISC_FALSE); if (type == dns_rdatatype_any) return (foreach_node_rr(db, ver, name, rr_action, rr_action_data)); node = NULL; if (type == dns_rdatatype_nsec3 || (type == dns_rdatatype_rrsig && covers == dns_rdatatype_nsec3)) result = dns_db_findnsec3node(db, name, ISC_FALSE, &node); else result = dns_db_findnodeext(db, name, ISC_FALSE, &cm, &ci, &node); if (result == ISC_R_NOTFOUND) return (ISC_R_SUCCESS); if (result != ISC_R_SUCCESS) return (result); dns_rdataset_init(&rdataset); result = dns_db_findrdataset(db, node, ver, type, covers, (isc_stdtime_t) 0, &rdataset, NULL); if (result == ISC_R_NOTFOUND) { result = ISC_R_SUCCESS; goto cleanup_node; } if (result != ISC_R_SUCCESS) goto cleanup_node; if (rr_action == add_rr_prepare_action) { add_rr_prepare_ctx_t *ctx = rr_action_data; dns_fixedname_init(&fixed); ctx->oldname = dns_fixedname_name(&fixed); dns_name_copy(name, ctx->oldname, NULL); dns_rdataset_getownercase(&rdataset, ctx->oldname); } for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS; result = dns_rdataset_next(&rdataset)) { rr_t rr = { 0, DNS_RDATA_INIT }; dns_rdataset_current(&rdataset, &rr.rdata); rr.ttl = rdataset.ttl; result = (*rr_action)(rr_action_data, &rr); if (result != ISC_R_SUCCESS) goto cleanup_rdataset; } if (result != ISC_R_NOMORE) goto cleanup_rdataset; result = ISC_R_SUCCESS; cleanup_rdataset: dns_rdataset_disassociate(&rdataset); cleanup_node: dns_db_detachnode(db, &node); return (result); } /**************************************************************************/ /* * Various tests on the database contents (for prerequisites, etc). */ /*% * Function type for predicate functions that compare a database RR 'db_rr' * against an update RR 'update_rr'. */ typedef isc_boolean_t rr_predicate(dns_rdata_t *update_rr, dns_rdata_t *db_rr); /*% * Helper function for rrset_exists(). */ static isc_result_t rrset_exists_action(void *data, rr_t *rr) { UNUSED(data); UNUSED(rr); return (ISC_R_EXISTS); } /*% * Utility macro for RR existence checking functions. * * If the variable 'result' has the value ISC_R_EXISTS or * ISC_R_SUCCESS, set *exists to ISC_TRUE or ISC_FALSE, * respectively, and return success. * * If 'result' has any other value, there was a failure. * Return the failure result code and do not set *exists. * * This would be more readable as "do { if ... } while(0)", * but that form generates tons of warnings on Solaris 2.6. */ #define RETURN_EXISTENCE_FLAG \ return ((result == ISC_R_EXISTS) ? \ (*exists = ISC_TRUE, ISC_R_SUCCESS) : \ ((result == ISC_R_SUCCESS) ? \ (*exists = ISC_FALSE, ISC_R_SUCCESS) : \ result)) /*% * Set '*exists' to true iff an rrset of the given type exists, * to false otherwise. */ static isc_result_t rrset_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, dns_rdatatype_t type, dns_rdatatype_t covers, isc_boolean_t *exists) { isc_result_t result; result = foreach_rr(db, ver, name, type, covers, rrset_exists_action, NULL); RETURN_EXISTENCE_FLAG; } /*% * Helper function for cname_incompatible_rrset_exists. */ static isc_result_t cname_compatibility_action(void *data, dns_rdataset_t *rrset) { UNUSED(data); if (rrset->type != dns_rdatatype_cname && ! dns_rdatatype_isdnssec(rrset->type)) return (ISC_R_EXISTS); return (ISC_R_SUCCESS); } /*% * Check whether there is an rrset incompatible with adding a CNAME RR, * i.e., anything but another CNAME (which can be replaced) or a * DNSSEC RR (which can coexist). * * If such an incompatible rrset exists, set '*exists' to ISC_TRUE. * Otherwise, set it to ISC_FALSE. */ static isc_result_t cname_incompatible_rrset_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, isc_boolean_t *exists) { isc_result_t result; result = foreach_rrset(db, ver, name, cname_compatibility_action, NULL); RETURN_EXISTENCE_FLAG; } /*% * Helper function for rr_count(). */ static isc_result_t count_rr_action(void *data, rr_t *rr) { int *countp = data; UNUSED(rr); (*countp)++; return (ISC_R_SUCCESS); } /*% * Count the number of RRs of 'type' belonging to 'name' in 'ver' of 'db'. */ static isc_result_t rr_count(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, dns_rdatatype_t type, dns_rdatatype_t covers, int *countp) { *countp = 0; return (foreach_rr(db, ver, name, type, covers, count_rr_action, countp)); } /*% * Context struct and helper function for name_exists(). */ static isc_result_t name_exists_action(void *data, dns_rdataset_t *rrset) { UNUSED(data); UNUSED(rrset); return (ISC_R_EXISTS); } /*% * Set '*exists' to true iff the given name exists, to false otherwise. */ static isc_result_t name_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, isc_boolean_t *exists) { isc_result_t result; result = foreach_rrset(db, ver, name, name_exists_action, NULL); RETURN_EXISTENCE_FLAG; } /* * 'ssu_check_t' is used to pass the arguments to * dns_ssutable_checkrules() to the callback function * ssu_checkrule(). */ typedef struct { /* The ownername of the record to be updated. */ dns_name_t *name; /* The signature's name if the request was signed. */ dns_name_t *signer; /* The address of the client. */ isc_netaddr_t *addr; /* Whether the request was sent via TCP. */ isc_boolean_t tcp; /* The ssu table to check against. */ dns_ssutable_t *table; /* the key used for TKEY requests */ dst_key_t *key; } ssu_check_t; static isc_result_t ssu_checkrule(void *data, dns_rdataset_t *rrset) { ssu_check_t *ssuinfo = data; isc_boolean_t result; /* * If we're deleting all records, it's ok to delete RRSIG and NSEC even * if we're normally not allowed to. */ if (rrset->type == dns_rdatatype_rrsig || rrset->type == dns_rdatatype_nsec) return (ISC_R_SUCCESS); result = dns_ssutable_checkrules2(ssuinfo->table, ssuinfo->signer, ssuinfo->name, ssuinfo->addr, ssuinfo->tcp, &ns_g_server->aclenv, rrset->type, ssuinfo->key); return (result == ISC_TRUE ? ISC_R_SUCCESS : ISC_R_FAILURE); } static isc_boolean_t ssu_checkall(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, dns_ssutable_t *ssutable, dns_name_t *signer, isc_netaddr_t *addr, isc_boolean_t tcp, dst_key_t *key) { isc_result_t result; ssu_check_t ssuinfo; ssuinfo.name = name; ssuinfo.table = ssutable; ssuinfo.signer = signer; ssuinfo.addr = addr; ssuinfo.tcp = tcp; ssuinfo.key = key; result = foreach_rrset(db, ver, name, ssu_checkrule, &ssuinfo); return (ISC_TF(result == ISC_R_SUCCESS)); } /**************************************************************************/ /* * Checking of "RRset exists (value dependent)" prerequisites. * * In the RFC2136 section 3.2.5, this is the pseudocode involving * a variable called "temp", a mapping of tuples to rrsets. * * Here, we represent the "temp" data structure as (non-minimal) "dns_diff_t" * where each tuple has op==DNS_DIFFOP_EXISTS. */ /*% * Append a tuple asserting the existence of the RR with * 'name' and 'rdata' to 'diff'. */ static isc_result_t temp_append(dns_diff_t *diff, dns_name_t *name, dns_rdata_t *rdata) { isc_result_t result; dns_difftuple_t *tuple = NULL; REQUIRE(DNS_DIFF_VALID(diff)); CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_EXISTS, name, 0, rdata, &tuple)); ISC_LIST_APPEND(diff->tuples, tuple, link); failure: return (result); } /*% * Compare two rdatasets represented as sorted lists of tuples. * All list elements must have the same owner name and type. * Return ISC_R_SUCCESS if the rdatasets are equal, rcode(dns_rcode_nxrrset) * if not. */ static isc_result_t temp_check_rrset(dns_difftuple_t *a, dns_difftuple_t *b) { for (;;) { if (a == NULL || b == NULL) break; INSIST(a->op == DNS_DIFFOP_EXISTS && b->op == DNS_DIFFOP_EXISTS); INSIST(a->rdata.type == b->rdata.type); INSIST(dns_name_equal(&a->name, &b->name)); if (dns_rdata_casecompare(&a->rdata, &b->rdata) != 0) return (DNS_R_NXRRSET); a = ISC_LIST_NEXT(a, link); b = ISC_LIST_NEXT(b, link); } if (a != NULL || b != NULL) return (DNS_R_NXRRSET); return (ISC_R_SUCCESS); } /*% * A comparison function defining the sorting order for the entries * in the "temp" data structure. The major sort key is the owner name, * followed by the type and rdata. */ static int temp_order(const void *av, const void *bv) { dns_difftuple_t const * const *ap = av; dns_difftuple_t const * const *bp = bv; dns_difftuple_t const *a = *ap; dns_difftuple_t const *b = *bp; int r; r = dns_name_compare(&a->name, &b->name); if (r != 0) return (r); r = (b->rdata.type - a->rdata.type); if (r != 0) return (r); r = dns_rdata_casecompare(&a->rdata, &b->rdata); return (r); } /*% * Check the "RRset exists (value dependent)" prerequisite information * in 'temp' against the contents of the database 'db'. * * Return ISC_R_SUCCESS if the prerequisites are satisfied, * rcode(dns_rcode_nxrrset) if not. * * 'temp' must be pre-sorted. */ static isc_result_t temp_check(isc_mem_t *mctx, dns_diff_t *temp, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *tmpname, dns_rdatatype_t *typep) { isc_result_t result; dns_name_t *name; dns_dbnode_t *node; dns_difftuple_t *t; dns_diff_t trash; dns_diff_init(mctx, &trash); /* * For each name and type in the prerequisites, * construct a sorted rdata list of the corresponding * database contents, and compare the lists. */ t = ISC_LIST_HEAD(temp->tuples); while (t != NULL) { name = &t->name; (void)dns_name_copy(name, tmpname, NULL); *typep = t->rdata.type; /* A new unique name begins here. */ node = NULL; result = dns_db_findnode(db, name, ISC_FALSE, &node); if (result == ISC_R_NOTFOUND) { dns_diff_clear(&trash); return (DNS_R_NXRRSET); } if (result != ISC_R_SUCCESS) { dns_diff_clear(&trash); return (result); } /* A new unique type begins here. */ while (t != NULL && dns_name_equal(&t->name, name)) { dns_rdatatype_t type, covers; dns_rdataset_t rdataset; dns_diff_t d_rrs; /* Database RRs with this name and type */ dns_diff_t u_rrs; /* Update RRs with this name and type */ *typep = type = t->rdata.type; if (type == dns_rdatatype_rrsig || type == dns_rdatatype_sig) covers = dns_rdata_covers(&t->rdata); else if (type == dns_rdatatype_any) { dns_db_detachnode(db, &node); dns_diff_clear(&trash); return (DNS_R_NXRRSET); } else covers = 0; /* * Collect all database RRs for this name and type * onto d_rrs and sort them. */ dns_rdataset_init(&rdataset); result = dns_db_findrdataset(db, node, ver, type, covers, (isc_stdtime_t) 0, &rdataset, NULL); if (result != ISC_R_SUCCESS) { dns_db_detachnode(db, &node); dns_diff_clear(&trash); return (DNS_R_NXRRSET); } dns_diff_init(mctx, &d_rrs); dns_diff_init(mctx, &u_rrs); for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS; result = dns_rdataset_next(&rdataset)) { dns_rdata_t rdata = DNS_RDATA_INIT; dns_rdataset_current(&rdataset, &rdata); result = temp_append(&d_rrs, name, &rdata); if (result != ISC_R_SUCCESS) goto failure; } if (result != ISC_R_NOMORE) goto failure; result = dns_diff_sort(&d_rrs, temp_order); if (result != ISC_R_SUCCESS) goto failure; /* * Collect all update RRs for this name and type * onto u_rrs. No need to sort them here - * they are already sorted. */ while (t != NULL && dns_name_equal(&t->name, name) && t->rdata.type == type) { dns_difftuple_t *next = ISC_LIST_NEXT(t, link); ISC_LIST_UNLINK(temp->tuples, t, link); ISC_LIST_APPEND(u_rrs.tuples, t, link); t = next; } /* Compare the two sorted lists. */ result = temp_check_rrset(ISC_LIST_HEAD(u_rrs.tuples), ISC_LIST_HEAD(d_rrs.tuples)); if (result != ISC_R_SUCCESS) goto failure; /* * We are done with the tuples, but we can't free * them yet because "name" still points into one * of them. Move them on a temporary list. */ ISC_LIST_APPENDLIST(trash.tuples, u_rrs.tuples, link); ISC_LIST_APPENDLIST(trash.tuples, d_rrs.tuples, link); dns_rdataset_disassociate(&rdataset); continue; failure: dns_diff_clear(&d_rrs); dns_diff_clear(&u_rrs); dns_diff_clear(&trash); dns_rdataset_disassociate(&rdataset); dns_db_detachnode(db, &node); return (result); } dns_db_detachnode(db, &node); } dns_diff_clear(&trash); return (ISC_R_SUCCESS); } /**************************************************************************/ /* * Conditional deletion of RRs. */ /*% * Context structure for delete_if(). */ typedef struct { rr_predicate *predicate; dns_db_t *db; dns_dbversion_t *ver; dns_diff_t *diff; dns_name_t *name; dns_rdata_t *update_rr; } conditional_delete_ctx_t; /*% * Predicate functions for delete_if(). */ /*% * Return true iff 'db_rr' is neither a SOA nor an NS RR nor * an RRSIG nor an NSEC3PARAM nor a NSEC. */ static isc_boolean_t type_not_soa_nor_ns_p(dns_rdata_t *update_rr, dns_rdata_t *db_rr) { UNUSED(update_rr); return ((db_rr->type != dns_rdatatype_soa && db_rr->type != dns_rdatatype_ns && db_rr->type != dns_rdatatype_nsec3param && db_rr->type != dns_rdatatype_rrsig && db_rr->type != dns_rdatatype_nsec) ? ISC_TRUE : ISC_FALSE); } /*% * Return true iff 'db_rr' is neither a RRSIG nor a NSEC. */ static isc_boolean_t type_not_dnssec(dns_rdata_t *update_rr, dns_rdata_t *db_rr) { UNUSED(update_rr); return ((db_rr->type != dns_rdatatype_rrsig && db_rr->type != dns_rdatatype_nsec) ? ISC_TRUE : ISC_FALSE); } /*% * Return true always. */ static isc_boolean_t true_p(dns_rdata_t *update_rr, dns_rdata_t *db_rr) { UNUSED(update_rr); UNUSED(db_rr); return (ISC_TRUE); } /*% * Return true iff the two RRs have identical rdata. */ static isc_boolean_t rr_equal_p(dns_rdata_t *update_rr, dns_rdata_t *db_rr) { /* * XXXRTH This is not a problem, but we should consider creating * dns_rdata_equal() (that used dns_name_equal()), since it * would be faster. Not a priority. */ return (dns_rdata_casecompare(update_rr, db_rr) == 0 ? ISC_TRUE : ISC_FALSE); } /*% * Return true iff 'update_rr' should replace 'db_rr' according * to the special RFC2136 rules for CNAME, SOA, and WKS records. * * RFC2136 does not mention NSEC or DNAME, but multiple NSECs or DNAMEs * make little sense, so we replace those, too. * * Additionally replace RRSIG that have been generated by the same key * for the same type. This simplifies refreshing a offline KSK by not * requiring that the old RRSIG be deleted. It also simplifies key * rollover by only requiring that the new RRSIG be added. */ static isc_boolean_t replaces_p(dns_rdata_t *update_rr, dns_rdata_t *db_rr) { dns_rdata_rrsig_t updatesig, dbsig; isc_result_t result; if (db_rr->type != update_rr->type) return (ISC_FALSE); if (db_rr->type == dns_rdatatype_cname) return (ISC_TRUE); if (db_rr->type == dns_rdatatype_dname) return (ISC_TRUE); if (db_rr->type == dns_rdatatype_soa) return (ISC_TRUE); if (db_rr->type == dns_rdatatype_nsec) return (ISC_TRUE); if (db_rr->type == dns_rdatatype_rrsig) { /* * Replace existing RRSIG with the same keyid, * covered and algorithm. */ result = dns_rdata_tostruct(db_rr, &dbsig, NULL); RUNTIME_CHECK(result == ISC_R_SUCCESS); result = dns_rdata_tostruct(update_rr, &updatesig, NULL); RUNTIME_CHECK(result == ISC_R_SUCCESS); if (dbsig.keyid == updatesig.keyid && dbsig.covered == updatesig.covered && dbsig.algorithm == updatesig.algorithm) return (ISC_TRUE); } if (db_rr->type == dns_rdatatype_wks) { /* * Compare the address and protocol fields only. These * form the first five bytes of the RR data. Do a * raw binary comparison; unpacking the WKS RRs using * dns_rdata_tostruct() might be cleaner in some ways. */ INSIST(db_rr->length >= 5 && update_rr->length >= 5); return (memcmp(db_rr->data, update_rr->data, 5) == 0 ? ISC_TRUE : ISC_FALSE); } if (db_rr->type == dns_rdatatype_nsec3param) { if (db_rr->length != update_rr->length) return (ISC_FALSE); INSIST(db_rr->length >= 4 && update_rr->length >= 4); /* * Replace NSEC3PARAM records that only differ by the * flags field. */ if (db_rr->data[0] == update_rr->data[0] && memcmp(db_rr->data+2, update_rr->data+2, update_rr->length - 2) == 0) return (ISC_TRUE); } return (ISC_FALSE); } /*% * Internal helper function for delete_if(). */ static isc_result_t delete_if_action(void *data, rr_t *rr) { conditional_delete_ctx_t *ctx = data; if ((*ctx->predicate)(ctx->update_rr, &rr->rdata)) { isc_result_t result; result = update_one_rr(ctx->db, ctx->ver, ctx->diff, DNS_DIFFOP_DEL, ctx->name, rr->ttl, &rr->rdata); return (result); } else { return (ISC_R_SUCCESS); } } /*% * Conditionally delete RRs. Apply 'predicate' to the RRs * specified by 'db', 'ver', 'name', and 'type' (which can * be dns_rdatatype_any to match any type). Delete those * RRs for which the predicate returns true, and log the * deletions in 'diff'. */ static isc_result_t delete_if(rr_predicate *predicate, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, dns_rdatatype_t type, dns_rdatatype_t covers, dns_rdata_t *update_rr, dns_diff_t *diff) { conditional_delete_ctx_t ctx; ctx.predicate = predicate; ctx.db = db; ctx.ver = ver; ctx.diff = diff; ctx.name = name; ctx.update_rr = update_rr; return (foreach_rr(db, ver, name, type, covers, delete_if_action, &ctx)); } /**************************************************************************/ static isc_result_t add_rr_prepare_action(void *data, rr_t *rr) { isc_result_t result = ISC_R_SUCCESS; add_rr_prepare_ctx_t *ctx = data; dns_difftuple_t *tuple = NULL; isc_boolean_t equal, case_equal, ttl_equal; /* * Are the new and old cases equal? */ case_equal = dns_name_caseequal(ctx->name, ctx->oldname); /* * Are the ttl's equal? */ ttl_equal = rr->ttl == ctx->update_rr_ttl; /* * If the update RR is a "duplicate" of a existing RR, * the update should be silently ignored. */ equal = ISC_TF(dns_rdata_casecompare(&rr->rdata, ctx->update_rr) == 0); if (equal && case_equal && ttl_equal) { ctx->ignore_add = ISC_TRUE; return (ISC_R_SUCCESS); } /* * If this RR is "equal" to the update RR, it should * be deleted before the update RR is added. */ if (replaces_p(ctx->update_rr, &rr->rdata)) { CHECK(dns_difftuple_create(ctx->del_diff.mctx, DNS_DIFFOP_DEL, ctx->oldname, rr->ttl, &rr->rdata, &tuple)); dns_diff_append(&ctx->del_diff, &tuple); return (ISC_R_SUCCESS); } /* * If this RR differs in TTL or case from the update RR, * its TTL and case must be adjusted. */ if (!ttl_equal || !case_equal) { CHECK(dns_difftuple_create(ctx->del_diff.mctx, DNS_DIFFOP_DEL, ctx->oldname, rr->ttl, &rr->rdata, &tuple)); dns_diff_append(&ctx->del_diff, &tuple); if (!equal) { CHECK(dns_difftuple_create(ctx->add_diff.mctx, DNS_DIFFOP_ADD, ctx->name, ctx->update_rr_ttl, &rr->rdata, &tuple)); dns_diff_append(&ctx->add_diff, &tuple); } } failure: return (result); } /**************************************************************************/ /* * Miscellaneous subroutines. */ /*% * Extract a single update RR from 'section' of dynamic update message * 'msg', with consistency checking. * * Stores the owner name, rdata, and TTL of the update RR at 'name', * 'rdata', and 'ttl', respectively. */ static void get_current_rr(dns_message_t *msg, dns_section_t section, dns_rdataclass_t zoneclass, dns_name_t **name, dns_rdata_t *rdata, dns_rdatatype_t *covers, dns_ttl_t *ttl, dns_rdataclass_t *update_class) { dns_rdataset_t *rdataset; isc_result_t result; dns_message_currentname(msg, section, name); rdataset = ISC_LIST_HEAD((*name)->list); INSIST(rdataset != NULL); INSIST(ISC_LIST_NEXT(rdataset, link) == NULL); *covers = rdataset->covers; *ttl = rdataset->ttl; result = dns_rdataset_first(rdataset); INSIST(result == ISC_R_SUCCESS); dns_rdataset_current(rdataset, rdata); INSIST(dns_rdataset_next(rdataset) == ISC_R_NOMORE); *update_class = rdata->rdclass; rdata->rdclass = zoneclass; } /*% * Increment the SOA serial number of database 'db', version 'ver'. * Replace the SOA record in the database, and log the * change in 'diff'. */ /* * XXXRTH Failures in this routine will be worth logging, when * we have a logging system. Failure to find the zonename * or the SOA rdataset warrant at least an UNEXPECTED_ERROR(). */ static isc_result_t update_soa_serial(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff, isc_mem_t *mctx, dns_updatemethod_t method) { dns_difftuple_t *deltuple = NULL; dns_difftuple_t *addtuple = NULL; isc_uint32_t serial; isc_result_t result; CHECK(dns_db_createsoatuple(db, ver, mctx, DNS_DIFFOP_DEL, &deltuple)); CHECK(dns_difftuple_copy(deltuple, &addtuple)); addtuple->op = DNS_DIFFOP_ADD; serial = dns_soa_getserial(&addtuple->rdata); serial = dns_update_soaserial(serial, method); dns_soa_setserial(serial, &addtuple->rdata); CHECK(do_one_tuple(&deltuple, db, ver, diff)); CHECK(do_one_tuple(&addtuple, db, ver, diff)); result = ISC_R_SUCCESS; failure: if (addtuple != NULL) dns_difftuple_free(&addtuple); if (deltuple != NULL) dns_difftuple_free(&deltuple); return (result); } /*% * Check that the new SOA record at 'update_rdata' does not * illegally cause the SOA serial number to decrease or stay * unchanged relative to the existing SOA in 'db'. * * Sets '*ok' to ISC_TRUE if the update is legal, ISC_FALSE if not. * * William King points out that RFC2136 is inconsistent about * the case where the serial number stays unchanged: * * section 3.4.2.2 requires a server to ignore a SOA update request * if the serial number on the update SOA is less_than_or_equal to * the zone SOA serial. * * section 3.6 requires a server to ignore a SOA update request if * the serial is less_than the zone SOA serial. * * Paul says 3.4.2.2 is correct. * */ static isc_result_t check_soa_increment(dns_db_t *db, dns_dbversion_t *ver, dns_rdata_t *update_rdata, isc_boolean_t *ok) { isc_uint32_t db_serial; isc_uint32_t update_serial; isc_result_t result; update_serial = dns_soa_getserial(update_rdata); result = dns_db_getsoaserial(db, ver, &db_serial); if (result != ISC_R_SUCCESS) return (result); if (DNS_SERIAL_GE(db_serial, update_serial)) { *ok = ISC_FALSE; } else { *ok = ISC_TRUE; } return (ISC_R_SUCCESS); } /**************************************************************************/ /*% * The actual update code in all its glory. We try to follow * the RFC2136 pseudocode as closely as possible. */ static isc_result_t send_update_event(ns_client_t *client, dns_zone_t *zone) { isc_result_t result = ISC_R_SUCCESS; update_event_t *event = NULL; isc_task_t *zonetask = NULL; ns_client_t *evclient; event = (update_event_t *) isc_event_allocate(client->mctx, client, DNS_EVENT_UPDATE, update_action, NULL, sizeof(*event)); if (event == NULL) FAIL(ISC_R_NOMEMORY); event->zone = zone; event->result = ISC_R_SUCCESS; evclient = NULL; ns_client_attach(client, &evclient); INSIST(client->nupdates == 0); client->nupdates++; event->ev_arg = evclient; dns_zone_gettask(zone, &zonetask); isc_task_send(zonetask, ISC_EVENT_PTR(&event)); failure: if (event != NULL) isc_event_free(ISC_EVENT_PTR(&event)); return (result); } static void respond(ns_client_t *client, isc_result_t result) { isc_result_t msg_result; msg_result = dns_message_reply(client->message, ISC_TRUE); if (msg_result != ISC_R_SUCCESS) goto msg_failure; client->message->rcode = dns_result_torcode(result); ns_client_send(client); return; msg_failure: isc_log_write(ns_g_lctx, NS_LOGCATEGORY_UPDATE, NS_LOGMODULE_UPDATE, ISC_LOG_ERROR, "could not create update response message: %s", isc_result_totext(msg_result)); ns_client_next(client, msg_result); } void ns_update_start(ns_client_t *client, isc_result_t sigresult) { dns_message_t *request = client->message; isc_result_t result; dns_name_t *zonename; dns_rdataset_t *zone_rdataset; dns_zone_t *zone = NULL, *raw = NULL; /* * Interpret the zone section. */ result = dns_message_firstname(request, DNS_SECTION_ZONE); if (result != ISC_R_SUCCESS) FAILC(DNS_R_FORMERR, "update zone section empty"); /* * The zone section must contain exactly one "question", and * it must be of type SOA. */ zonename = NULL; dns_message_currentname(request, DNS_SECTION_ZONE, &zonename); zone_rdataset = ISC_LIST_HEAD(zonename->list); if (zone_rdataset->type != dns_rdatatype_soa) FAILC(DNS_R_FORMERR, "update zone section contains non-SOA"); if (ISC_LIST_NEXT(zone_rdataset, link) != NULL) FAILC(DNS_R_FORMERR, "update zone section contains multiple RRs"); /* The zone section must have exactly one name. */ result = dns_message_nextname(request, DNS_SECTION_ZONE); if (result != ISC_R_NOMORE) FAILC(DNS_R_FORMERR, "update zone section contains multiple RRs"); result = dns_zt_find(client->view->zonetable, zonename, 0, NULL, &zone); if (result != ISC_R_SUCCESS) FAILC(DNS_R_NOTAUTH, "not authoritative for update zone"); /* * If there is a raw (unsigned) zone associated with this * zone then it processes the UPDATE request. */ dns_zone_getraw(zone, &raw); if (raw != NULL) { dns_zone_detach(&zone); dns_zone_attach(raw, &zone); dns_zone_detach(&raw); } switch(dns_zone_gettype(zone)) { case dns_zone_master: case dns_zone_dlz: /* * We can now fail due to a bad signature as we now know * that we are the master. */ if (sigresult != ISC_R_SUCCESS) FAIL(sigresult); CHECK(send_update_event(client, zone)); break; case dns_zone_slave: CHECK(checkupdateacl(client, dns_zone_getforwardacl(zone), "update forwarding", zonename, ISC_TRUE, ISC_FALSE)); CHECK(send_forward_event(client, zone)); break; default: FAILC(DNS_R_NOTAUTH, "not authoritative for update zone"); } return; failure: if (result == DNS_R_REFUSED) { INSIST(dns_zone_gettype(zone) == dns_zone_slave); inc_stats(zone, dns_nsstatscounter_updaterej); } /* * We failed without having sent an update event to the zone. * We are still in the client task context, so we can * simply give an error response without switching tasks. */ respond(client, result); if (zone != NULL) dns_zone_detach(&zone); } /*% * DS records are not allowed to exist without corresponding NS records, * RFC 3658, 2.2 Protocol Change, * "DS RRsets MUST NOT appear at non-delegation points or at a zone's apex". */ static isc_result_t remove_orphaned_ds(dns_db_t *db, dns_dbversion_t *newver, dns_diff_t *diff) { isc_result_t result; isc_boolean_t ns_exists; dns_difftuple_t *tupple; dns_diff_t temp_diff; dns_diff_init(diff->mctx, &temp_diff); for (tupple = ISC_LIST_HEAD(diff->tuples); tupple != NULL; tupple = ISC_LIST_NEXT(tupple, link)) { if (!((tupple->op == DNS_DIFFOP_DEL && tupple->rdata.type == dns_rdatatype_ns) || (tupple->op == DNS_DIFFOP_ADD && tupple->rdata.type == dns_rdatatype_ds))) continue; CHECK(rrset_exists(db, newver, &tupple->name, dns_rdatatype_ns, 0, &ns_exists)); if (ns_exists && !dns_name_equal(&tupple->name, dns_db_origin(db))) continue; CHECK(delete_if(true_p, db, newver, &tupple->name, dns_rdatatype_ds, 0, NULL, &temp_diff)); } result = ISC_R_SUCCESS; failure: for (tupple = ISC_LIST_HEAD(temp_diff.tuples); tupple != NULL; tupple = ISC_LIST_HEAD(temp_diff.tuples)) { ISC_LIST_UNLINK(temp_diff.tuples, tupple, link); dns_diff_appendminimal(diff, &tupple); } return (result); } /* * This implements the post load integrity checks for mx records. */ static isc_result_t check_mx(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *newver, dns_diff_t *diff) { char tmp[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:123.123.123.123.")]; char ownerbuf[DNS_NAME_FORMATSIZE]; char namebuf[DNS_NAME_FORMATSIZE]; char altbuf[DNS_NAME_FORMATSIZE]; dns_difftuple_t *t; dns_fixedname_t fixed; dns_name_t *foundname; dns_rdata_mx_t mx; dns_rdata_t rdata; isc_boolean_t ok = ISC_TRUE; isc_boolean_t isaddress; isc_result_t result; struct in6_addr addr6; struct in_addr addr; unsigned int options; dns_fixedname_init(&fixed); foundname = dns_fixedname_name(&fixed); dns_rdata_init(&rdata); options = dns_zone_getoptions(zone); for (t = ISC_LIST_HEAD(diff->tuples); t != NULL; t = ISC_LIST_NEXT(t, link)) { if (t->op != DNS_DIFFOP_ADD || t->rdata.type != dns_rdatatype_mx) continue; result = dns_rdata_tostruct(&t->rdata, &mx, NULL); RUNTIME_CHECK(result == ISC_R_SUCCESS); /* * Check if we will error out if we attempt to reload the * zone. */ dns_name_format(&mx.mx, namebuf, sizeof(namebuf)); dns_name_format(&t->name, ownerbuf, sizeof(ownerbuf)); isaddress = ISC_FALSE; if ((options & DNS_RDATA_CHECKMX) != 0 && strlcpy(tmp, namebuf, sizeof(tmp)) < sizeof(tmp)) { if (tmp[strlen(tmp) - 1] == '.') tmp[strlen(tmp) - 1] = '\0'; if (inet_aton(tmp, &addr) == 1 || inet_pton(AF_INET6, tmp, &addr6) == 1) isaddress = ISC_TRUE; } if (isaddress && (options & DNS_RDATA_CHECKMXFAIL) != 0) { update_log(client, zone, ISC_LOG_ERROR, "%s/MX: '%s': %s", ownerbuf, namebuf, dns_result_totext(DNS_R_MXISADDRESS)); ok = ISC_FALSE; } else if (isaddress) { update_log(client, zone, ISC_LOG_WARNING, "%s/MX: warning: '%s': %s", ownerbuf, namebuf, dns_result_totext(DNS_R_MXISADDRESS)); } /* * Check zone integrity checks. */ if ((options & DNS_ZONEOPT_CHECKINTEGRITY) == 0) continue; result = dns_db_find(db, &mx.mx, newver, dns_rdatatype_a, 0, 0, NULL, foundname, NULL, NULL); if (result == ISC_R_SUCCESS) continue; if (result == DNS_R_NXRRSET) { result = dns_db_find(db, &mx.mx, newver, dns_rdatatype_aaaa, 0, 0, NULL, foundname, NULL, NULL); if (result == ISC_R_SUCCESS) continue; } if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN) { update_log(client, zone, ISC_LOG_ERROR, "%s/MX '%s' has no address records " "(A or AAAA)", ownerbuf, namebuf); ok = ISC_FALSE; } else if (result == DNS_R_CNAME) { update_log(client, zone, ISC_LOG_ERROR, "%s/MX '%s' is a CNAME (illegal)", ownerbuf, namebuf); ok = ISC_FALSE; } else if (result == DNS_R_DNAME) { dns_name_format(foundname, altbuf, sizeof altbuf); update_log(client, zone, ISC_LOG_ERROR, "%s/MX '%s' is below a DNAME '%s' (illegal)", ownerbuf, namebuf, altbuf); ok = ISC_FALSE; } } return (ok ? ISC_R_SUCCESS : DNS_R_REFUSED); } static isc_result_t rr_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, const dns_rdata_t *rdata, isc_boolean_t *flag) { dns_rdataset_t rdataset; dns_dbnode_t *node = NULL; isc_result_t result; dns_rdataset_init(&rdataset); if (rdata->type == dns_rdatatype_nsec3) CHECK(dns_db_findnsec3node(db, name, ISC_FALSE, &node)); else CHECK(dns_db_findnode(db, name, ISC_FALSE, &node)); result = dns_db_findrdataset(db, node, ver, rdata->type, 0, (isc_stdtime_t) 0, &rdataset, NULL); if (result == ISC_R_NOTFOUND) { *flag = ISC_FALSE; result = ISC_R_SUCCESS; goto failure; } for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS; result = dns_rdataset_next(&rdataset)) { dns_rdata_t myrdata = DNS_RDATA_INIT; dns_rdataset_current(&rdataset, &myrdata); if (!dns_rdata_casecompare(&myrdata, rdata)) break; } dns_rdataset_disassociate(&rdataset); if (result == ISC_R_SUCCESS) { *flag = ISC_TRUE; } else if (result == ISC_R_NOMORE) { *flag = ISC_FALSE; result = ISC_R_SUCCESS; } failure: if (node != NULL) dns_db_detachnode(db, &node); return (result); } static isc_result_t get_iterations(dns_db_t *db, dns_dbversion_t *ver, dns_rdatatype_t privatetype, unsigned int *iterationsp) { dns_dbnode_t *node = NULL; dns_rdata_nsec3param_t nsec3param; dns_rdataset_t rdataset; isc_result_t result; unsigned int iterations = 0; dns_rdataset_init(&rdataset); result = dns_db_getoriginnode(db, &node); if (result != ISC_R_SUCCESS) return (result); result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param, 0, (isc_stdtime_t) 0, &rdataset, NULL); if (result == ISC_R_NOTFOUND) goto try_private; if (result != ISC_R_SUCCESS) goto failure; for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS; result = dns_rdataset_next(&rdataset)) { dns_rdata_t rdata = DNS_RDATA_INIT; dns_rdataset_current(&rdataset, &rdata); CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL)); if ((nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0) continue; if (nsec3param.iterations > iterations) iterations = nsec3param.iterations; } if (result != ISC_R_NOMORE) goto failure; dns_rdataset_disassociate(&rdataset); try_private: if (privatetype == 0) goto success; result = dns_db_findrdataset(db, node, ver, privatetype, 0, (isc_stdtime_t) 0, &rdataset, NULL); if (result == ISC_R_NOTFOUND) goto success; if (result != ISC_R_SUCCESS) goto failure; for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS; result = dns_rdataset_next(&rdataset)) { unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE]; dns_rdata_t private = DNS_RDATA_INIT; dns_rdata_t rdata = DNS_RDATA_INIT; dns_rdataset_current(&rdataset, &rdata); if (!dns_nsec3param_fromprivate(&private, &rdata, buf, sizeof(buf))) continue; CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL)); if ((nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0) continue; if (nsec3param.iterations > iterations) iterations = nsec3param.iterations; } if (result != ISC_R_NOMORE) goto failure; success: *iterationsp = iterations; result = ISC_R_SUCCESS; failure: if (node != NULL) dns_db_detachnode(db, &node); if (dns_rdataset_isassociated(&rdataset)) dns_rdataset_disassociate(&rdataset); return (result); } /* * Prevent the zone entering a inconsistent state where * NSEC only DNSKEYs are present with NSEC3 chains. */ static isc_result_t check_dnssec(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff) { dns_difftuple_t *tuple; isc_boolean_t nseconly = ISC_FALSE, nsec3 = ISC_FALSE; isc_result_t result; unsigned int iterations = 0, max; dns_rdatatype_t privatetype = dns_zone_getprivatetype(zone); /* Scan the tuples for an NSEC-only DNSKEY or an NSEC3PARAM */ for (tuple = ISC_LIST_HEAD(diff->tuples); tuple != NULL; tuple = ISC_LIST_NEXT(tuple, link)) { if (tuple->op != DNS_DIFFOP_ADD) continue; if (tuple->rdata.type == dns_rdatatype_dnskey) { isc_uint8_t alg; alg = tuple->rdata.data[3]; if (alg == DST_ALG_RSAMD5 || alg == DST_ALG_RSASHA1 || alg == DST_ALG_DSA || alg == DST_ALG_ECC) { nseconly = ISC_TRUE; break; } } else if (tuple->rdata.type == dns_rdatatype_nsec3param) { nsec3 = ISC_TRUE; break; } } /* Check existing DB for NSEC-only DNSKEY */ if (!nseconly) { result = dns_nsec_nseconly(db, ver, &nseconly); /* * An NSEC3PARAM update can proceed without a DNSKEY (it * will trigger a delayed change), so we can ignore * ISC_R_NOTFOUND here. */ if (result == ISC_R_NOTFOUND) result = ISC_R_SUCCESS; CHECK(result); } /* Check existing DB for NSEC3 */ if (!nsec3) CHECK(dns_nsec3_activex(db, ver, ISC_FALSE, privatetype, &nsec3)); /* Refuse to allow NSEC3 with NSEC-only keys */ if (nseconly && nsec3) { update_log(client, zone, ISC_LOG_ERROR, "NSEC only DNSKEYs and NSEC3 chains not allowed"); result = DNS_R_REFUSED; goto failure; } /* Verify NSEC3 params */ CHECK(get_iterations(db, ver, privatetype, &iterations)); CHECK(dns_nsec3_maxiterations(db, ver, client->mctx, &max)); if (max != 0 && iterations > max) { update_log(client, zone, ISC_LOG_ERROR, "too many NSEC3 iterations (%u) for " "weakest DNSKEY (%u)", iterations, max); result = DNS_R_REFUSED; goto failure; } failure: return (result); } /* * Delay NSEC3PARAM changes as they need to be applied to the whole zone. */ static isc_result_t add_nsec3param_records(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff) { isc_result_t result = ISC_R_SUCCESS; dns_difftuple_t *tuple, *newtuple = NULL, *next; dns_rdata_t rdata = DNS_RDATA_INIT; unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE + 1]; dns_diff_t temp_diff; dns_diffop_t op; isc_boolean_t flag; dns_name_t *name = dns_zone_getorigin(zone); dns_rdatatype_t privatetype = dns_zone_getprivatetype(zone); isc_uint32_t ttl = 0; isc_boolean_t ttl_good = ISC_FALSE; update_log(client, zone, ISC_LOG_DEBUG(3), "checking for NSEC3PARAM changes"); dns_diff_init(diff->mctx, &temp_diff); /* * Extract NSEC3PARAM tuples from list. */ for (tuple = ISC_LIST_HEAD(diff->tuples); tuple != NULL; tuple = next) { next = ISC_LIST_NEXT(tuple, link); if (tuple->rdata.type != dns_rdatatype_nsec3param || !dns_name_equal(name, &tuple->name)) continue; ISC_LIST_UNLINK(diff->tuples, tuple, link); ISC_LIST_APPEND(temp_diff.tuples, tuple, link); } /* * Extract TTL changes pairs, we don't need to convert these to * delayed changes. */ for (tuple = ISC_LIST_HEAD(temp_diff.tuples); tuple != NULL; tuple = next) { if (tuple->op == DNS_DIFFOP_ADD) { if (!ttl_good) { /* * Any adds here will contain the final * NSEC3PARAM RRset TTL. */ ttl = tuple->ttl; ttl_good = ISC_TRUE; } /* * Walk the temp_diff list looking for the * corresponding delete. */ next = ISC_LIST_HEAD(temp_diff.tuples); while (next != NULL) { unsigned char *next_data = next->rdata.data; unsigned char *tuple_data = tuple->rdata.data; if (next->op == DNS_DIFFOP_DEL && next->rdata.length == tuple->rdata.length && !memcmp(next_data, tuple_data, next->rdata.length)) { ISC_LIST_UNLINK(temp_diff.tuples, next, link); ISC_LIST_APPEND(diff->tuples, next, link); break; } next = ISC_LIST_NEXT(next, link); } /* * If we have not found a pair move onto the next * tuple. */ if (next == NULL) { next = ISC_LIST_NEXT(tuple, link); continue; } /* * Find the next tuple to be processed before * unlinking then complete moving the pair to 'diff'. */ next = ISC_LIST_NEXT(tuple, link); ISC_LIST_UNLINK(temp_diff.tuples, tuple, link); ISC_LIST_APPEND(diff->tuples, tuple, link); } else next = ISC_LIST_NEXT(tuple, link); } /* * Preserve any ongoing changes from a BIND 9.6.x upgrade. * * Any NSEC3PARAM records with flags other than OPTOUT named * in managing and should not be touched so revert such changes * taking into account any TTL change of the NSEC3PARAM RRset. */ for (tuple = ISC_LIST_HEAD(temp_diff.tuples); tuple != NULL; tuple = next) { next = ISC_LIST_NEXT(tuple, link); if ((tuple->rdata.data[1] & ~DNS_NSEC3FLAG_OPTOUT) != 0) { /* * If we havn't had any adds then the tuple->ttl must * be the original ttl and should be used for any * future changes. */ if (!ttl_good) { ttl = tuple->ttl; ttl_good = ISC_TRUE; } op = (tuple->op == DNS_DIFFOP_DEL) ? DNS_DIFFOP_ADD : DNS_DIFFOP_DEL; CHECK(dns_difftuple_create(diff->mctx, op, name, ttl, &tuple->rdata, &newtuple)); CHECK(do_one_tuple(&newtuple, db, ver, diff)); ISC_LIST_UNLINK(temp_diff.tuples, tuple, link); dns_diff_appendminimal(diff, &tuple); } } /* * We now have just the actual changes to the NSEC3PARAM RRset. * Convert the adds to delayed adds and the deletions into delayed * deletions. */ for (tuple = ISC_LIST_HEAD(temp_diff.tuples); tuple != NULL; tuple = next) { /* * If we havn't had any adds then the tuple->ttl must be the * original ttl and should be used for any future changes. */ if (!ttl_good) { ttl = tuple->ttl; ttl_good = ISC_TRUE; } if (tuple->op == DNS_DIFFOP_ADD) { isc_boolean_t nseconly = ISC_FALSE; /* * Look for any deletes which match this ADD ignoring * flags. We don't need to explictly remove them as * they will be removed a side effect of processing * the add. */ next = ISC_LIST_HEAD(temp_diff.tuples); while (next != NULL) { unsigned char *next_data = next->rdata.data; unsigned char *tuple_data = tuple->rdata.data; if (next->op != DNS_DIFFOP_DEL || next->rdata.length != tuple->rdata.length || next_data[0] != tuple_data[0] || next_data[2] != tuple_data[2] || next_data[3] != tuple_data[3] || memcmp(next_data + 4, tuple_data + 4, tuple->rdata.length - 4)) { next = ISC_LIST_NEXT(next, link); continue; } ISC_LIST_UNLINK(temp_diff.tuples, next, link); ISC_LIST_APPEND(diff->tuples, next, link); next = ISC_LIST_HEAD(temp_diff.tuples); } /* * Create a private-type record to signal that * we want a delayed NSEC3 chain add/delete */ dns_nsec3param_toprivate(&tuple->rdata, &rdata, privatetype, buf, sizeof(buf)); buf[2] |= DNS_NSEC3FLAG_CREATE; /* * If the zone is not currently capable of * supporting an NSEC3 chain, then we set the * INITIAL flag to indicate that these parameters * are to be used later. */ result = dns_nsec_nseconly(db, ver, &nseconly); if (result == ISC_R_NOTFOUND || nseconly) buf[2] |= DNS_NSEC3FLAG_INITIAL; /* * See if this CREATE request already exists. */ CHECK(rr_exists(db, ver, name, &rdata, &flag)); if (!flag) { CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD, name, 0, &rdata, &newtuple)); CHECK(do_one_tuple(&newtuple, db, ver, diff)); } /* * Remove any existing CREATE request to add an * otherwise indentical chain with a reversed * OPTOUT state. */ buf[2] ^= DNS_NSEC3FLAG_OPTOUT; CHECK(rr_exists(db, ver, name, &rdata, &flag)); if (flag) { CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_DEL, name, 0, &rdata, &newtuple)); CHECK(do_one_tuple(&newtuple, db, ver, diff)); } /* * Find the next tuple to be processed and remove the * temporary add record. */ next = ISC_LIST_NEXT(tuple, link); CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_DEL, name, ttl, &tuple->rdata, &newtuple)); CHECK(do_one_tuple(&newtuple, db, ver, diff)); ISC_LIST_UNLINK(temp_diff.tuples, tuple, link); dns_diff_appendminimal(diff, &tuple); dns_rdata_reset(&rdata); } else next = ISC_LIST_NEXT(tuple, link); } for (tuple = ISC_LIST_HEAD(temp_diff.tuples); tuple != NULL; tuple = next) { INSIST(ttl_good); next = ISC_LIST_NEXT(tuple, link); /* * See if we already have a REMOVE request in progress. */ dns_nsec3param_toprivate(&tuple->rdata, &rdata, privatetype, buf, sizeof(buf)); buf[2] |= DNS_NSEC3FLAG_REMOVE | DNS_NSEC3FLAG_NONSEC; CHECK(rr_exists(db, ver, name, &rdata, &flag)); if (!flag) { buf[2] &= ~DNS_NSEC3FLAG_NONSEC; CHECK(rr_exists(db, ver, name, &rdata, &flag)); } if (!flag) { CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD, name, 0, &rdata, &newtuple)); CHECK(do_one_tuple(&newtuple, db, ver, diff)); } CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD, name, ttl, &tuple->rdata, &newtuple)); CHECK(do_one_tuple(&newtuple, db, ver, diff)); ISC_LIST_UNLINK(temp_diff.tuples, tuple, link); dns_diff_appendminimal(diff, &tuple); dns_rdata_reset(&rdata); } result = ISC_R_SUCCESS; failure: dns_diff_clear(&temp_diff); return (result); } static isc_result_t rollback_private(dns_db_t *db, dns_rdatatype_t privatetype, dns_dbversion_t *ver, dns_diff_t *diff) { dns_diff_t temp_diff; dns_diffop_t op; dns_difftuple_t *tuple, *newtuple = NULL, *next; dns_name_t *name = dns_db_origin(db); isc_mem_t *mctx = diff->mctx; isc_result_t result; if (privatetype == 0) return (ISC_R_SUCCESS); dns_diff_init(mctx, &temp_diff); /* * Extract the changes to be rolled back. */ for (tuple = ISC_LIST_HEAD(diff->tuples); tuple != NULL; tuple = next) { next = ISC_LIST_NEXT(tuple, link); if (tuple->rdata.type != privatetype || !dns_name_equal(name, &tuple->name)) continue; /* * Allow records which indicate that a zone has been * signed with a DNSKEY to be removed. */ if (tuple->op == DNS_DIFFOP_DEL && tuple->rdata.length == 5 && tuple->rdata.data[0] != 0 && tuple->rdata.data[4] != 0) continue; ISC_LIST_UNLINK(diff->tuples, tuple, link); ISC_LIST_PREPEND(temp_diff.tuples, tuple, link); } /* * Rollback the changes. */ while ((tuple = ISC_LIST_HEAD(temp_diff.tuples)) != NULL) { op = (tuple->op == DNS_DIFFOP_DEL) ? DNS_DIFFOP_ADD : DNS_DIFFOP_DEL; CHECK(dns_difftuple_create(mctx, op, name, tuple->ttl, &tuple->rdata, &newtuple)); CHECK(do_one_tuple(&newtuple, db, ver, &temp_diff)); } result = ISC_R_SUCCESS; failure: dns_diff_clear(&temp_diff); return (result); } /* * Add records to cause the delayed signing of the zone by added DNSKEY * to remove the RRSIG records generated by a deleted DNSKEY. */ static isc_result_t add_signing_records(dns_db_t *db, dns_rdatatype_t privatetype, dns_dbversion_t *ver, dns_diff_t *diff) { dns_difftuple_t *tuple, *newtuple = NULL, *next; dns_rdata_dnskey_t dnskey; dns_rdata_t rdata = DNS_RDATA_INIT; isc_boolean_t flag; isc_region_t r; isc_result_t result = ISC_R_SUCCESS; isc_uint16_t keyid; unsigned char buf[5]; dns_name_t *name = dns_db_origin(db); dns_diff_t temp_diff; dns_diff_init(diff->mctx, &temp_diff); /* * Extract the DNSKEY tuples from the list. */ for (tuple = ISC_LIST_HEAD(diff->tuples); tuple != NULL; tuple = next) { next = ISC_LIST_NEXT(tuple, link); if (tuple->rdata.type != dns_rdatatype_dnskey) continue; ISC_LIST_UNLINK(diff->tuples, tuple, link); ISC_LIST_APPEND(temp_diff.tuples, tuple, link); } /* * Extract TTL changes pairs, we don't need signing records for these. */ for (tuple = ISC_LIST_HEAD(temp_diff.tuples); tuple != NULL; tuple = next) { if (tuple->op == DNS_DIFFOP_ADD) { /* * Walk the temp_diff list looking for the * corresponding delete. */ next = ISC_LIST_HEAD(temp_diff.tuples); while (next != NULL) { unsigned char *next_data = next->rdata.data; unsigned char *tuple_data = tuple->rdata.data; if (next->op == DNS_DIFFOP_DEL && dns_name_equal(&tuple->name, &next->name) && next->rdata.length == tuple->rdata.length && !memcmp(next_data, tuple_data, next->rdata.length)) { ISC_LIST_UNLINK(temp_diff.tuples, next, link); ISC_LIST_APPEND(diff->tuples, next, link); break; } next = ISC_LIST_NEXT(next, link); } /* * If we have not found a pair move onto the next * tuple. */ if (next == NULL) { next = ISC_LIST_NEXT(tuple, link); continue; } /* * Find the next tuple to be processed before * unlinking then complete moving the pair to 'diff'. */ next = ISC_LIST_NEXT(tuple, link); ISC_LIST_UNLINK(temp_diff.tuples, tuple, link); ISC_LIST_APPEND(diff->tuples, tuple, link); } else next = ISC_LIST_NEXT(tuple, link); } /* * Process the remaining DNSKEY entries. */ for (tuple = ISC_LIST_HEAD(temp_diff.tuples); tuple != NULL; tuple = ISC_LIST_HEAD(temp_diff.tuples)) { ISC_LIST_UNLINK(temp_diff.tuples, tuple, link); ISC_LIST_APPEND(diff->tuples, tuple, link); result = dns_rdata_tostruct(&tuple->rdata, &dnskey, NULL); RUNTIME_CHECK(result == ISC_R_SUCCESS); if ((dnskey.flags & (DNS_KEYFLAG_OWNERMASK|DNS_KEYTYPE_NOAUTH)) != DNS_KEYOWNER_ZONE) continue; dns_rdata_toregion(&tuple->rdata, &r); keyid = dst_region_computeid(&r, dnskey.algorithm); buf[0] = dnskey.algorithm; buf[1] = (keyid & 0xff00) >> 8; buf[2] = (keyid & 0xff); buf[3] = (tuple->op == DNS_DIFFOP_ADD) ? 0 : 1; buf[4] = 0; rdata.data = buf; rdata.length = sizeof(buf); rdata.type = privatetype; rdata.rdclass = tuple->rdata.rdclass; CHECK(rr_exists(db, ver, name, &rdata, &flag)); if (flag) continue; CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD, name, 0, &rdata, &newtuple)); CHECK(do_one_tuple(&newtuple, db, ver, diff)); INSIST(newtuple == NULL); /* * Remove any record which says this operation has already * completed. */ buf[4] = 1; CHECK(rr_exists(db, ver, name, &rdata, &flag)); if (flag) { CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_DEL, name, 0, &rdata, &newtuple)); CHECK(do_one_tuple(&newtuple, db, ver, diff)); INSIST(newtuple == NULL); } } failure: dns_diff_clear(&temp_diff); return (result); } static isc_boolean_t isdnssec(dns_db_t *db, dns_dbversion_t *ver, dns_rdatatype_t privatetype) { isc_result_t result; isc_boolean_t build_nsec, build_nsec3; if (dns_db_issecure(db)) return (ISC_TRUE); result = dns_private_chains(db, ver, privatetype, &build_nsec, &build_nsec3); RUNTIME_CHECK(result == ISC_R_SUCCESS); return (build_nsec || build_nsec3); } static void update_action(isc_task_t *task, isc_event_t *event) { update_event_t *uev = (update_event_t *) event; dns_zone_t *zone = uev->zone; ns_client_t *client = (ns_client_t *)event->ev_arg; isc_result_t result; dns_db_t *db = NULL; dns_dbversion_t *oldver = NULL; dns_dbversion_t *ver = NULL; dns_diff_t diff; /* Pending updates. */ dns_diff_t temp; /* Pending RR existence assertions. */ isc_boolean_t soa_serial_changed = ISC_FALSE; isc_mem_t *mctx = client->mctx; dns_rdatatype_t covers; dns_message_t *request = client->message; dns_rdataclass_t zoneclass; dns_name_t *zonename; dns_ssutable_t *ssutable = NULL; dns_fixedname_t tmpnamefixed; dns_name_t *tmpname = NULL; unsigned int options, options2; dns_difftuple_t *tuple; dns_rdata_dnskey_t dnskey; isc_boolean_t had_dnskey; dns_rdatatype_t privatetype = dns_zone_getprivatetype(zone); dns_ttl_t maxttl = 0; isc_uint32_t maxrecords; isc_uint64_t records; INSIST(event->ev_type == DNS_EVENT_UPDATE); dns_diff_init(mctx, &diff); dns_diff_init(mctx, &temp); CHECK(dns_zone_getdb(zone, &db)); zonename = dns_db_origin(db); zoneclass = dns_db_class(db); dns_zone_getssutable(zone, &ssutable); /* * Update message processing can leak record existance information * so check that we are allowed to query this zone. Additionally * if we would refuse all updates for this zone we bail out here. */ CHECK(checkqueryacl(client, dns_zone_getqueryacl(zone), zonename, dns_zone_getupdateacl(zone), ssutable)); /* * Get old and new versions now that queryacl has been checked. */ dns_db_currentversion(db, &oldver); CHECK(dns_db_newversion(db, &ver)); /* * Check prerequisites. */ for (result = dns_message_firstname(request, DNS_SECTION_PREREQUISITE); result == ISC_R_SUCCESS; result = dns_message_nextname(request, DNS_SECTION_PREREQUISITE)) { dns_name_t *name = NULL; dns_rdata_t rdata = DNS_RDATA_INIT; dns_ttl_t ttl; dns_rdataclass_t update_class; isc_boolean_t flag; get_current_rr(request, DNS_SECTION_PREREQUISITE, zoneclass, &name, &rdata, &covers, &ttl, &update_class); if (ttl != 0) PREREQFAILC(DNS_R_FORMERR, "prerequisite TTL is not zero"); if (! dns_name_issubdomain(name, zonename)) PREREQFAILN(DNS_R_NOTZONE, name, "prerequisite name is out of zone"); if (update_class == dns_rdataclass_any) { if (rdata.length != 0) PREREQFAILC(DNS_R_FORMERR, "class ANY prerequisite " "RDATA is not empty"); if (rdata.type == dns_rdatatype_any) { CHECK(name_exists(db, ver, name, &flag)); if (! flag) { PREREQFAILN(DNS_R_NXDOMAIN, name, "'name in use' " "prerequisite not " "satisfied"); } } else { CHECK(rrset_exists(db, ver, name, rdata.type, covers, &flag)); if (! flag) { /* RRset does not exist. */ PREREQFAILNT(DNS_R_NXRRSET, name, rdata.type, "'rrset exists (value independent)' " "prerequisite not satisfied"); } } } else if (update_class == dns_rdataclass_none) { if (rdata.length != 0) PREREQFAILC(DNS_R_FORMERR, "class NONE prerequisite " "RDATA is not empty"); if (rdata.type == dns_rdatatype_any) { CHECK(name_exists(db, ver, name, &flag)); if (flag) { PREREQFAILN(DNS_R_YXDOMAIN, name, "'name not in use' " "prerequisite not " "satisfied"); } } else { CHECK(rrset_exists(db, ver, name, rdata.type, covers, &flag)); if (flag) { /* RRset exists. */ PREREQFAILNT(DNS_R_YXRRSET, name, rdata.type, "'rrset does not exist' " "prerequisite not " "satisfied"); } } } else if (update_class == zoneclass) { /* "temp += rr;" */ result = temp_append(&temp, name, &rdata); if (result != ISC_R_SUCCESS) { UNEXPECTED_ERROR(__FILE__, __LINE__, "temp entry creation failed: %s", dns_result_totext(result)); FAIL(ISC_R_UNEXPECTED); } } else { PREREQFAILC(DNS_R_FORMERR, "malformed prerequisite"); } } if (result != ISC_R_NOMORE) FAIL(result); /* * Perform the final check of the "rrset exists (value dependent)" * prerequisites. */ if (ISC_LIST_HEAD(temp.tuples) != NULL) { dns_rdatatype_t type; /* * Sort the prerequisite records by owner name, * type, and rdata. */ result = dns_diff_sort(&temp, temp_order); if (result != ISC_R_SUCCESS) FAILC(result, "'RRset exists (value dependent)' " "prerequisite not satisfied"); dns_fixedname_init(&tmpnamefixed); tmpname = dns_fixedname_name(&tmpnamefixed); result = temp_check(mctx, &temp, db, ver, tmpname, &type); if (result != ISC_R_SUCCESS) FAILNT(result, tmpname, type, "'RRset exists (value dependent)' " "prerequisite not satisfied"); } update_log(client, zone, LOGLEVEL_DEBUG, "prerequisites are OK"); /* * Check Requestor's Permissions. It seems a bit silly to do this * only after prerequisite testing, but that is what RFC2136 says. */ if (ssutable == NULL) CHECK(checkupdateacl(client, dns_zone_getupdateacl(zone), "update", zonename, ISC_FALSE, ISC_FALSE)); else if (client->signer == NULL && !TCPCLIENT(client)) CHECK(checkupdateacl(client, NULL, "update", zonename, ISC_FALSE, ISC_TRUE)); if (dns_zone_getupdatedisabled(zone)) FAILC(DNS_R_REFUSED, "dynamic update temporarily disabled " "because the zone is frozen. Use " "'rndc thaw' to re-enable updates."); /* * Perform the Update Section Prescan. */ for (result = dns_message_firstname(request, DNS_SECTION_UPDATE); result == ISC_R_SUCCESS; result = dns_message_nextname(request, DNS_SECTION_UPDATE)) { dns_name_t *name = NULL; dns_rdata_t rdata = DNS_RDATA_INIT; dns_ttl_t ttl; dns_rdataclass_t update_class; get_current_rr(request, DNS_SECTION_UPDATE, zoneclass, &name, &rdata, &covers, &ttl, &update_class); if (! dns_name_issubdomain(name, zonename)) FAILC(DNS_R_NOTZONE, "update RR is outside zone"); if (update_class == zoneclass) { /* * Check for meta-RRs. The RFC2136 pseudocode says * check for ANY|AXFR|MAILA|MAILB, but the text adds * "or any other QUERY metatype" */ if (dns_rdatatype_ismeta(rdata.type)) { FAILC(DNS_R_FORMERR, "meta-RR in update"); } result = dns_zone_checknames(zone, name, &rdata); if (result != ISC_R_SUCCESS) FAIL(DNS_R_REFUSED); } else if (update_class == dns_rdataclass_any) { if (ttl != 0 || rdata.length != 0 || (dns_rdatatype_ismeta(rdata.type) && rdata.type != dns_rdatatype_any)) FAILC(DNS_R_FORMERR, "meta-RR in update"); } else if (update_class == dns_rdataclass_none) { if (ttl != 0 || dns_rdatatype_ismeta(rdata.type)) FAILC(DNS_R_FORMERR, "meta-RR in update"); } else { update_log(client, zone, ISC_LOG_WARNING, "update RR has incorrect class %d", update_class); FAIL(DNS_R_FORMERR); } /* * draft-ietf-dnsind-simple-secure-update-01 says * "Unlike traditional dynamic update, the client * is forbidden from updating NSEC records." */ if (rdata.type == dns_rdatatype_nsec3) { FAILC(DNS_R_REFUSED, "explicit NSEC3 updates are not allowed " "in secure zones"); } else if (rdata.type == dns_rdatatype_nsec) { FAILC(DNS_R_REFUSED, "explicit NSEC updates are not allowed " "in secure zones"); } else if (rdata.type == dns_rdatatype_rrsig && !dns_name_equal(name, zonename)) { FAILC(DNS_R_REFUSED, "explicit RRSIG updates are currently " "not supported in secure zones except " "at the apex"); } if (ssutable != NULL) { isc_netaddr_t netaddr; dst_key_t *tsigkey = NULL; isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr); if (client->message->tsigkey != NULL) tsigkey = client->message->tsigkey->key; if (rdata.type != dns_rdatatype_any) { if (!dns_ssutable_checkrules2 (ssutable, client->signer, name, &netaddr, ISC_TF(TCPCLIENT(client)), &ns_g_server->aclenv, rdata.type, tsigkey)) { FAILC(DNS_R_REFUSED, "rejected by secure update"); } } else { if (!ssu_checkall(db, ver, name, ssutable, client->signer, &netaddr, ISC_TF(TCPCLIENT(client)), tsigkey)) { FAILC(DNS_R_REFUSED, "rejected by secure update"); } } } } if (result != ISC_R_NOMORE) FAIL(result); update_log(client, zone, LOGLEVEL_DEBUG, "update section prescan OK"); /* * Process the Update Section. */ options = dns_zone_getoptions(zone); options2 = dns_zone_getoptions2(zone); for (result = dns_message_firstname(request, DNS_SECTION_UPDATE); result == ISC_R_SUCCESS; result = dns_message_nextname(request, DNS_SECTION_UPDATE)) { dns_name_t *name = NULL; dns_rdata_t rdata = DNS_RDATA_INIT; dns_ttl_t ttl; dns_rdataclass_t update_class; isc_boolean_t flag; get_current_rr(request, DNS_SECTION_UPDATE, zoneclass, &name, &rdata, &covers, &ttl, &update_class); if (update_class == zoneclass) { /* * RFC1123 doesn't allow MF and MD in master zones. */ if (rdata.type == dns_rdatatype_md || rdata.type == dns_rdatatype_mf) { char typebuf[DNS_RDATATYPE_FORMATSIZE]; dns_rdatatype_format(rdata.type, typebuf, sizeof(typebuf)); update_log(client, zone, LOGLEVEL_PROTOCOL, "attempt to add %s ignored", typebuf); continue; } if ((rdata.type == dns_rdatatype_ns || rdata.type == dns_rdatatype_dname) && dns_name_iswildcard(name)) { char typebuf[DNS_RDATATYPE_FORMATSIZE]; dns_rdatatype_format(rdata.type, typebuf, sizeof(typebuf)); update_log(client, zone, LOGLEVEL_PROTOCOL, "attempt to add wildcard %s record " "ignored", typebuf); continue; } if (rdata.type == dns_rdatatype_cname) { CHECK(cname_incompatible_rrset_exists(db, ver, name, &flag)); if (flag) { update_log(client, zone, LOGLEVEL_PROTOCOL, "attempt to add CNAME " "alongside non-CNAME " "ignored"); continue; } } else { CHECK(rrset_exists(db, ver, name, dns_rdatatype_cname, 0, &flag)); if (flag && ! dns_rdatatype_isdnssec(rdata.type)) { update_log(client, zone, LOGLEVEL_PROTOCOL, "attempt to add non-CNAME " "alongside CNAME ignored"); continue; } } if (rdata.type == dns_rdatatype_soa) { isc_boolean_t ok; CHECK(rrset_exists(db, ver, name, dns_rdatatype_soa, 0, &flag)); if (! flag) { update_log(client, zone, LOGLEVEL_PROTOCOL, "attempt to create 2nd " "SOA ignored"); continue; } CHECK(check_soa_increment(db, ver, &rdata, &ok)); if (! ok) { update_log(client, zone, LOGLEVEL_PROTOCOL, "SOA update failed to " "increment serial, " "ignoring it"); continue; } soa_serial_changed = ISC_TRUE; } if (rdata.type == privatetype) { update_log(client, zone, LOGLEVEL_PROTOCOL, "attempt to add a private type " "(%u) record rejected internal " "use only", privatetype); continue; } if (rdata.type == dns_rdatatype_nsec3param) { /* * Ignore attempts to add NSEC3PARAM records * with any flags other than OPTOUT. */ if ((rdata.data[1] & ~DNS_NSEC3FLAG_OPTOUT) != 0) { update_log(client, zone, LOGLEVEL_PROTOCOL, "attempt to add NSEC3PARAM " "record with non OPTOUT " "flag"); continue; } } if ((options & DNS_ZONEOPT_CHECKWILDCARD) != 0 && dns_name_internalwildcard(name)) { char namestr[DNS_NAME_FORMATSIZE]; dns_name_format(name, namestr, sizeof(namestr)); update_log(client, zone, LOGLEVEL_PROTOCOL, "warning: ownername '%s' contains " "a non-terminal wildcard", namestr); } if ((options2 & DNS_ZONEOPT2_CHECKTTL) != 0) { maxttl = dns_zone_getmaxttl(zone); if (ttl > maxttl) { ttl = maxttl; update_log(client, zone, LOGLEVEL_PROTOCOL, "reducing TTL to the " "configured max-zone-ttl %d", maxttl); } } if (isc_log_wouldlog(ns_g_lctx, LOGLEVEL_PROTOCOL)) { char namestr[DNS_NAME_FORMATSIZE]; char typestr[DNS_RDATATYPE_FORMATSIZE]; char rdstr[2048]; isc_buffer_t buf; int len = 0; const char *truncated = ""; dns_name_format(name, namestr, sizeof(namestr)); dns_rdatatype_format(rdata.type, typestr, sizeof(typestr)); isc_buffer_init(&buf, rdstr, sizeof(rdstr)); result = dns_rdata_totext(&rdata, NULL, &buf); if (result == ISC_R_NOSPACE) { len = (int)isc_buffer_usedlength(&buf); truncated = " [TRUNCATED]"; } else if (result != ISC_R_SUCCESS) { snprintf(rdstr, sizeof(rdstr), "[dns_" "rdata_totext failed: %s]", dns_result_totext(result)); len = strlen(rdstr); } else len = (int)isc_buffer_usedlength(&buf); update_log(client, zone, LOGLEVEL_PROTOCOL, "adding an RR at '%s' %s %.*s%s", namestr, typestr, len, rdstr, truncated); } /* Prepare the affected RRset for the addition. */ { add_rr_prepare_ctx_t ctx; ctx.db = db; ctx.ver = ver; ctx.diff = &diff; ctx.name = name; ctx.oldname = name; ctx.update_rr = &rdata; ctx.update_rr_ttl = ttl; ctx.ignore_add = ISC_FALSE; dns_diff_init(mctx, &ctx.del_diff); dns_diff_init(mctx, &ctx.add_diff); CHECK(foreach_rr(db, ver, name, rdata.type, covers, add_rr_prepare_action, &ctx)); if (ctx.ignore_add) { dns_diff_clear(&ctx.del_diff); dns_diff_clear(&ctx.add_diff); } else { result = do_diff(&ctx.del_diff, db, ver, &diff); if (result == ISC_R_SUCCESS) { result = do_diff(&ctx.add_diff, db, ver, &diff); } if (result != ISC_R_SUCCESS) { dns_diff_clear(&ctx.del_diff); dns_diff_clear(&ctx.add_diff); goto failure; } CHECK(update_one_rr(db, ver, &diff, DNS_DIFFOP_ADD, name, ttl, &rdata)); } } } else if (update_class == dns_rdataclass_any) { if (rdata.type == dns_rdatatype_any) { if (isc_log_wouldlog(ns_g_lctx, LOGLEVEL_PROTOCOL)) { char namestr[DNS_NAME_FORMATSIZE]; dns_name_format(name, namestr, sizeof(namestr)); update_log(client, zone, LOGLEVEL_PROTOCOL, "delete all rrsets from " "name '%s'", namestr); } if (dns_name_equal(name, zonename)) { CHECK(delete_if(type_not_soa_nor_ns_p, db, ver, name, dns_rdatatype_any, 0, &rdata, &diff)); } else { CHECK(delete_if(type_not_dnssec, db, ver, name, dns_rdatatype_any, 0, &rdata, &diff)); } } else if (dns_name_equal(name, zonename) && (rdata.type == dns_rdatatype_soa || rdata.type == dns_rdatatype_ns)) { update_log(client, zone, LOGLEVEL_PROTOCOL, "attempt to delete all SOA " "or NS records ignored"); continue; } else { if (isc_log_wouldlog(ns_g_lctx, LOGLEVEL_PROTOCOL)) { char namestr[DNS_NAME_FORMATSIZE]; char typestr[DNS_RDATATYPE_FORMATSIZE]; dns_name_format(name, namestr, sizeof(namestr)); dns_rdatatype_format(rdata.type, typestr, sizeof(typestr)); update_log(client, zone, LOGLEVEL_PROTOCOL, "deleting rrset at '%s' %s", namestr, typestr); } CHECK(delete_if(true_p, db, ver, name, rdata.type, covers, &rdata, &diff)); } } else if (update_class == dns_rdataclass_none) { char namestr[DNS_NAME_FORMATSIZE]; char typestr[DNS_RDATATYPE_FORMATSIZE]; /* * The (name == zonename) condition appears in * RFC2136 3.4.2.4 but is missing from the pseudocode. */ if (dns_name_equal(name, zonename)) { if (rdata.type == dns_rdatatype_soa) { update_log(client, zone, LOGLEVEL_PROTOCOL, "attempt to delete SOA " "ignored"); continue; } if (rdata.type == dns_rdatatype_ns) { int count; CHECK(rr_count(db, ver, name, dns_rdatatype_ns, 0, &count)); if (count == 1) { update_log(client, zone, LOGLEVEL_PROTOCOL, "attempt to " "delete last " "NS ignored"); continue; } } } dns_name_format(name, namestr, sizeof(namestr)); dns_rdatatype_format(rdata.type, typestr, sizeof(typestr)); update_log(client, zone, LOGLEVEL_PROTOCOL, "deleting an RR at %s %s", namestr, typestr); CHECK(delete_if(rr_equal_p, db, ver, name, rdata.type, covers, &rdata, &diff)); } } if (result != ISC_R_NOMORE) FAIL(result); /* * Check that any changes to DNSKEY/NSEC3PARAM records make sense. * If they don't then back out all changes to DNSKEY/NSEC3PARAM * records. */ if (! ISC_LIST_EMPTY(diff.tuples)) CHECK(check_dnssec(client, zone, db, ver, &diff)); if (! ISC_LIST_EMPTY(diff.tuples)) { unsigned int errors = 0; CHECK(dns_zone_nscheck(zone, db, ver, &errors)); if (errors != 0) { update_log(client, zone, LOGLEVEL_PROTOCOL, "update rejected: post update name server " "sanity check failed"); result = DNS_R_REFUSED; goto failure; } } if (! ISC_LIST_EMPTY(diff.tuples)) { result = dns_zone_cdscheck(zone, db, ver); if (result == DNS_R_BADCDS || result == DNS_R_BADCDNSKEY) { update_log(client, zone, LOGLEVEL_PROTOCOL, "update rejected: bad %s RRset", result == DNS_R_BADCDS ? "CDS" : "CDNSKEY"); result = DNS_R_REFUSED; goto failure; } if (result != ISC_R_SUCCESS) goto failure; } /* * If any changes were made, increment the SOA serial number, * update RRSIGs and NSECs (if zone is secure), and write the update * to the journal. */ if (! ISC_LIST_EMPTY(diff.tuples)) { char *journalfile; dns_journal_t *journal; isc_boolean_t has_dnskey; /* * Increment the SOA serial, but only if it was not * changed as a result of an update operation. */ if (! soa_serial_changed) { CHECK(update_soa_serial(db, ver, &diff, mctx, dns_zone_getserialupdatemethod(zone))); } CHECK(check_mx(client, zone, db, ver, &diff)); CHECK(remove_orphaned_ds(db, ver, &diff)); CHECK(rrset_exists(db, ver, zonename, dns_rdatatype_dnskey, 0, &has_dnskey)); #define ALLOW_SECURE_TO_INSECURE(zone) \ ((dns_zone_getoptions(zone) & DNS_ZONEOPT_SECURETOINSECURE) != 0) CHECK(rrset_exists(db, oldver, zonename, dns_rdatatype_dnskey, 0, &had_dnskey)); if (!ALLOW_SECURE_TO_INSECURE(zone)) { if (had_dnskey && !has_dnskey) { update_log(client, zone, LOGLEVEL_PROTOCOL, "update rejected: all DNSKEY " "records removed and " "'dnssec-secure-to-insecure' " "not set"); result = DNS_R_REFUSED; goto failure; } } CHECK(rollback_private(db, privatetype, ver, &diff)); CHECK(add_signing_records(db, privatetype, ver, &diff)); CHECK(add_nsec3param_records(client, zone, db, ver, &diff)); if (had_dnskey && !has_dnskey) { /* * We are transitioning from secure to insecure. * Cause all NSEC3 chains to be deleted. When the * the last signature for the DNSKEY records are * remove any NSEC chain present will also be removed. */ CHECK(dns_nsec3param_deletechains(db, ver, zone, ISC_TRUE, &diff)); } else if (has_dnskey && isdnssec(db, ver, privatetype)) { isc_uint32_t interval; dns_update_log_t log; interval = dns_zone_getsigvalidityinterval(zone); log.func = update_log_cb; log.arg = client; result = dns_update_signatures(&log, zone, db, oldver, ver, &diff, interval); if (result != ISC_R_SUCCESS) { update_log(client, zone, ISC_LOG_ERROR, "RRSIG/NSEC/NSEC3 update failed: %s", isc_result_totext(result)); goto failure; } } maxrecords = dns_zone_getmaxrecords(zone); if (maxrecords != 0U) { result = dns_db_getsize(db, ver, &records, NULL); if (result == ISC_R_SUCCESS && records > maxrecords) { update_log(client, zone, ISC_LOG_ERROR, "records in zone (%" ISC_PRINT_QUADFORMAT "u) exceeds max-records (%u)", records, maxrecords); result = DNS_R_TOOMANYRECORDS; goto failure; } } journalfile = dns_zone_getjournal(zone); if (journalfile != NULL) { update_log(client, zone, LOGLEVEL_DEBUG, "writing journal %s", journalfile); journal = NULL; result = dns_journal_open(mctx, journalfile, DNS_JOURNAL_CREATE, &journal); if (result != ISC_R_SUCCESS) FAILS(result, "journal open failed"); result = dns_journal_write_transaction(journal, &diff); if (result != ISC_R_SUCCESS) { dns_journal_destroy(&journal); FAILS(result, "journal write failed"); } dns_journal_destroy(&journal); } /* * XXXRTH Just a note that this committing code will have * to change to handle databases that need two-phase * commit, but this isn't a priority. */ update_log(client, zone, LOGLEVEL_DEBUG, "committing update transaction"); dns_db_closeversion(db, &ver, ISC_TRUE); /* * Mark the zone as dirty so that it will be written to disk. */ dns_zone_markdirty(zone); /* * Notify slaves of the change we just made. */ dns_zone_notify(zone); /* * Cause the zone to be signed with the key that we * have just added or have the corresponding signatures * deleted. * * Note: we are already committed to this course of action. */ for (tuple = ISC_LIST_HEAD(diff.tuples); tuple != NULL; tuple = ISC_LIST_NEXT(tuple, link)) { isc_region_t r; dns_secalg_t algorithm; isc_uint16_t keyid; if (tuple->rdata.type != dns_rdatatype_dnskey) continue; dns_rdata_tostruct(&tuple->rdata, &dnskey, NULL); if ((dnskey.flags & (DNS_KEYFLAG_OWNERMASK|DNS_KEYTYPE_NOAUTH)) != DNS_KEYOWNER_ZONE) continue; dns_rdata_toregion(&tuple->rdata, &r); algorithm = dnskey.algorithm; keyid = dst_region_computeid(&r, algorithm); result = dns_zone_signwithkey(zone, algorithm, keyid, ISC_TF(tuple->op == DNS_DIFFOP_DEL)); if (result != ISC_R_SUCCESS) { update_log(client, zone, ISC_LOG_ERROR, "dns_zone_signwithkey failed: %s", dns_result_totext(result)); } } /* * Cause the zone to add/delete NSEC3 chains for the * deferred NSEC3PARAM changes. * * Note: we are already committed to this course of action. */ for (tuple = ISC_LIST_HEAD(diff.tuples); tuple != NULL; tuple = ISC_LIST_NEXT(tuple, link)) { unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE]; dns_rdata_t rdata = DNS_RDATA_INIT; dns_rdata_nsec3param_t nsec3param; if (tuple->rdata.type != privatetype || tuple->op != DNS_DIFFOP_ADD) continue; if (!dns_nsec3param_fromprivate(&tuple->rdata, &rdata, buf, sizeof(buf))) continue; dns_rdata_tostruct(&rdata, &nsec3param, NULL); if (nsec3param.flags == 0) continue; result = dns_zone_addnsec3chain(zone, &nsec3param); if (result != ISC_R_SUCCESS) { update_log(client, zone, ISC_LOG_ERROR, "dns_zone_addnsec3chain failed: %s", dns_result_totext(result)); } } } else { update_log(client, zone, LOGLEVEL_DEBUG, "redundant request"); dns_db_closeversion(db, &ver, ISC_TRUE); } result = ISC_R_SUCCESS; goto common; failure: /* * The reason for failure should have been logged at this point. */ if (ver != NULL) { update_log(client, zone, LOGLEVEL_DEBUG, "rolling back"); dns_db_closeversion(db, &ver, ISC_FALSE); } common: dns_diff_clear(&temp); dns_diff_clear(&diff); if (oldver != NULL) dns_db_closeversion(db, &oldver, ISC_FALSE); if (db != NULL) dns_db_detach(&db); if (ssutable != NULL) dns_ssutable_detach(&ssutable); isc_task_detach(&task); uev->result = result; if (zone != NULL) INSIST(uev->zone == zone); /* we use this later */ uev->ev_type = DNS_EVENT_UPDATEDONE; uev->ev_action = updatedone_action; isc_task_send(client->task, &event); INSIST(ver == NULL); INSIST(event == NULL); } static void updatedone_action(isc_task_t *task, isc_event_t *event) { update_event_t *uev = (update_event_t *) event; ns_client_t *client = (ns_client_t *) event->ev_arg; UNUSED(task); INSIST(event->ev_type == DNS_EVENT_UPDATEDONE); INSIST(task == client->task); INSIST(client->nupdates > 0); switch (uev->result) { case ISC_R_SUCCESS: inc_stats(uev->zone, dns_nsstatscounter_updatedone); break; case DNS_R_REFUSED: inc_stats(uev->zone, dns_nsstatscounter_updaterej); break; default: inc_stats(uev->zone, dns_nsstatscounter_updatefail); break; } if (uev->zone != NULL) dns_zone_detach(&uev->zone); client->nupdates--; respond(client, uev->result); isc_event_free(&event); ns_client_detach(&client); } /*% * Update forwarding support. */ static void forward_fail(isc_task_t *task, isc_event_t *event) { ns_client_t *client = (ns_client_t *)event->ev_arg; UNUSED(task); INSIST(client->nupdates > 0); client->nupdates--; respond(client, DNS_R_SERVFAIL); isc_event_free(&event); ns_client_detach(&client); } static void forward_callback(void *arg, isc_result_t result, dns_message_t *answer) { update_event_t *uev = arg; ns_client_t *client = uev->ev_arg; dns_zone_t *zone = uev->zone; if (result != ISC_R_SUCCESS) { INSIST(answer == NULL); uev->ev_type = DNS_EVENT_UPDATEDONE; uev->ev_action = forward_fail; inc_stats(zone, dns_nsstatscounter_updatefwdfail); } else { uev->ev_type = DNS_EVENT_UPDATEDONE; uev->ev_action = forward_done; uev->answer = answer; inc_stats(zone, dns_nsstatscounter_updaterespfwd); } isc_task_send(client->task, ISC_EVENT_PTR(&uev)); dns_zone_detach(&zone); } static void forward_done(isc_task_t *task, isc_event_t *event) { update_event_t *uev = (update_event_t *) event; ns_client_t *client = (ns_client_t *)event->ev_arg; UNUSED(task); INSIST(client->nupdates > 0); client->nupdates--; ns_client_sendraw(client, uev->answer); dns_message_destroy(&uev->answer); isc_event_free(&event); ns_client_detach(&client); } static void forward_action(isc_task_t *task, isc_event_t *event) { update_event_t *uev = (update_event_t *) event; dns_zone_t *zone = uev->zone; ns_client_t *client = (ns_client_t *)event->ev_arg; isc_result_t result; result = dns_zone_forwardupdate(zone, client->message, forward_callback, event); if (result != ISC_R_SUCCESS) { uev->ev_type = DNS_EVENT_UPDATEDONE; uev->ev_action = forward_fail; isc_task_send(client->task, &event); inc_stats(zone, dns_nsstatscounter_updatefwdfail); dns_zone_detach(&zone); } else inc_stats(zone, dns_nsstatscounter_updatereqfwd); isc_task_detach(&task); } static isc_result_t send_forward_event(ns_client_t *client, dns_zone_t *zone) { char namebuf[DNS_NAME_FORMATSIZE]; char classbuf[DNS_RDATACLASS_FORMATSIZE]; isc_result_t result = ISC_R_SUCCESS; update_event_t *event = NULL; isc_task_t *zonetask = NULL; ns_client_t *evclient; /* * This may take some time so replace this client. */ if (!client->mortal && (client->attributes & NS_CLIENTATTR_TCP) == 0) CHECK(ns_client_replace(client)); event = (update_event_t *) isc_event_allocate(client->mctx, client, DNS_EVENT_UPDATE, forward_action, NULL, sizeof(*event)); if (event == NULL) FAIL(ISC_R_NOMEMORY); event->zone = zone; event->result = ISC_R_SUCCESS; evclient = NULL; ns_client_attach(client, &evclient); INSIST(client->nupdates == 0); client->nupdates++; event->ev_arg = evclient; dns_name_format(dns_zone_getorigin(zone), namebuf, sizeof(namebuf)); dns_rdataclass_format(dns_zone_getclass(zone), classbuf, sizeof(classbuf)); ns_client_log(client, NS_LOGCATEGORY_UPDATE, NS_LOGMODULE_UPDATE, LOGLEVEL_PROTOCOL, "forwarding update for zone '%s/%s'", namebuf, classbuf); dns_zone_gettask(zone, &zonetask); isc_task_send(zonetask, ISC_EVENT_PTR(&event)); failure: if (event != NULL) isc_event_free(ISC_EVENT_PTR(&event)); return (result); } bind9-9.11.3+dfsg/bin/named/win32/000077500000000000000000000000001325250447100163325ustar00rootroot00000000000000bind9-9.11.3+dfsg/bin/named/win32/dlz_dlopen_driver.c000066400000000000000000000336001325250447100222050ustar00rootroot00000000000000/* * Copyright (C) 2011-2014, 2016 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* $Id: dlz_dlopen_driver.c,v 1.5 2011/10/14 00:52:32 marka Exp $ */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef ISC_DLZ_DLOPEN static dns_sdlzimplementation_t *dlz_dlopen = NULL; typedef struct dlopen_data { isc_mem_t *mctx; char *dl_path; char *dlzname; HMODULE dl_handle; void *dbdata; unsigned int flags; isc_mutex_t lock; int version; isc_boolean_t in_configure; dlz_dlopen_version_t *dlz_version; dlz_dlopen_create_t *dlz_create; dlz_dlopen_findzonedb_t *dlz_findzonedb; dlz_dlopen_lookup_t *dlz_lookup; dlz_dlopen_authority_t *dlz_authority; dlz_dlopen_allnodes_t *dlz_allnodes; dlz_dlopen_allowzonexfr_t *dlz_allowzonexfr; dlz_dlopen_newversion_t *dlz_newversion; dlz_dlopen_closeversion_t *dlz_closeversion; dlz_dlopen_configure_t *dlz_configure; dlz_dlopen_ssumatch_t *dlz_ssumatch; dlz_dlopen_addrdataset_t *dlz_addrdataset; dlz_dlopen_subrdataset_t *dlz_subrdataset; dlz_dlopen_delrdataset_t *dlz_delrdataset; dlz_dlopen_destroy_t *dlz_destroy; } dlopen_data_t; /* Modules can choose whether they are lock-safe or not. */ #define MAYBE_LOCK(cd) \ do { \ if ((cd->flags & DNS_SDLZFLAG_THREADSAFE) == 0 && \ cd->in_configure == ISC_FALSE) \ LOCK(&cd->lock); \ } while (0) #define MAYBE_UNLOCK(cd) \ do { \ if ((cd->flags & DNS_SDLZFLAG_THREADSAFE) == 0 && \ cd->in_configure == ISC_FALSE) \ UNLOCK(&cd->lock); \ } while (0) /* * Log a message at the given level. */ static void dlopen_log(int level, const char *fmt, ...) { va_list ap; va_start(ap, fmt); isc_log_vwrite(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(level), fmt, ap); va_end(ap); } /* * SDLZ methods */ static isc_result_t dlopen_dlz_allnodes(const char *zone, void *driverarg, void *dbdata, dns_sdlzallnodes_t *allnodes) { dlopen_data_t *cd = (dlopen_data_t *) dbdata; isc_result_t result; UNUSED(driverarg); if (cd->dlz_allnodes == NULL) { return (ISC_R_NOPERM); } MAYBE_LOCK(cd); result = cd->dlz_allnodes(zone, cd->dbdata, allnodes); MAYBE_UNLOCK(cd); return (result); } static isc_result_t dlopen_dlz_allowzonexfr(void *driverarg, void *dbdata, const char *name, const char *client) { dlopen_data_t *cd = (dlopen_data_t *) dbdata; isc_result_t result; UNUSED(driverarg); if (cd->dlz_allowzonexfr == NULL) { return (ISC_R_NOPERM); } MAYBE_LOCK(cd); result = cd->dlz_allowzonexfr(cd->dbdata, name, client); MAYBE_UNLOCK(cd); return (result); } static isc_result_t dlopen_dlz_authority(const char *zone, void *driverarg, void *dbdata, dns_sdlzlookup_t *lookup) { dlopen_data_t *cd = (dlopen_data_t *) dbdata; isc_result_t result; UNUSED(driverarg); if (cd->dlz_authority == NULL) { return (ISC_R_NOTIMPLEMENTED); } MAYBE_LOCK(cd); result = cd->dlz_authority(zone, cd->dbdata, lookup); MAYBE_UNLOCK(cd); return (result); } static isc_result_t dlopen_dlz_findzonedb(void *driverarg, void *dbdata, const char *name, dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo) { dlopen_data_t *cd = (dlopen_data_t *) dbdata; isc_result_t result; UNUSED(driverarg); MAYBE_LOCK(cd); result = cd->dlz_findzonedb(cd->dbdata, name, methods, clientinfo); MAYBE_UNLOCK(cd); return (result); } static isc_result_t dlopen_dlz_lookup(const char *zone, const char *name, void *driverarg, void *dbdata, dns_sdlzlookup_t *lookup, dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo) { dlopen_data_t *cd = (dlopen_data_t *) dbdata; isc_result_t result; UNUSED(driverarg); MAYBE_LOCK(cd); result = cd->dlz_lookup(zone, name, cd->dbdata, lookup, methods, clientinfo); MAYBE_UNLOCK(cd); return (result); } /* * Load a symbol from the library */ static void * dl_load_symbol(dlopen_data_t *cd, const char *symbol, isc_boolean_t mandatory) { void *ptr = GetProcAddress(cd->dl_handle, symbol); if (ptr == NULL && mandatory) { dlopen_log(ISC_LOG_ERROR, "dlz_dlopen: library '%s' is missing " "required symbol '%s'", cd->dl_path, symbol); } return (ptr); } /* * Called at startup for each dlopen zone in named.conf */ static isc_result_t dlopen_dlz_create(const char *dlzname, unsigned int argc, char *argv[], void *driverarg, void **dbdata) { dlopen_data_t *cd; isc_mem_t *mctx = NULL; isc_result_t result = ISC_R_FAILURE; isc_boolean_t triedload = ISC_FALSE; UNUSED(driverarg); if (argc < 2) { dlopen_log(ISC_LOG_ERROR, "dlz_dlopen driver for '%s' needs a path to " "the shared library", dlzname); return (ISC_R_FAILURE); } isc_mem_create(0, 0, &mctx); cd = isc_mem_get(mctx, sizeof(*cd)); if (cd == NULL) { isc_mem_destroy(&mctx); return (ISC_R_NOMEMORY); } memset(cd, 0, sizeof(*cd)); cd->mctx = mctx; cd->dl_path = isc_mem_strdup(cd->mctx, argv[1]); if (cd->dl_path == NULL) { result = ISC_R_NOMEMORY; goto failed; } cd->dlzname = isc_mem_strdup(cd->mctx, dlzname); if (cd->dlzname == NULL) { result = ISC_R_NOMEMORY; goto failed; } triedload = ISC_TRUE; /* Initialize the lock */ result = isc_mutex_init(&cd->lock); if (result != ISC_R_SUCCESS) goto failed; /* Open the library */ cd->dl_handle = LoadLibraryA(cd->dl_path); if (cd->dl_handle == NULL) { unsigned int error = GetLastError(); dlopen_log(ISC_LOG_ERROR, "dlz_dlopen failed to open library '%s' - %u", cd->dl_path, error); result = ISC_R_FAILURE; goto cleanup_lock; } /* Find the symbols */ cd->dlz_version = (dlz_dlopen_version_t *) dl_load_symbol(cd, "dlz_version", ISC_TRUE); cd->dlz_create = (dlz_dlopen_create_t *) dl_load_symbol(cd, "dlz_create", ISC_TRUE); cd->dlz_lookup = (dlz_dlopen_lookup_t *) dl_load_symbol(cd, "dlz_lookup", ISC_TRUE); cd->dlz_findzonedb = (dlz_dlopen_findzonedb_t *) dl_load_symbol(cd, "dlz_findzonedb", ISC_TRUE); if (cd->dlz_create == NULL || cd->dlz_version == NULL || cd->dlz_lookup == NULL || cd->dlz_findzonedb == NULL) { /* We're missing a required symbol */ result = ISC_R_FAILURE; goto cleanup_lock; } cd->dlz_allowzonexfr = (dlz_dlopen_allowzonexfr_t *) dl_load_symbol(cd, "dlz_allowzonexfr", ISC_FALSE); cd->dlz_allnodes = (dlz_dlopen_allnodes_t *) dl_load_symbol(cd, "dlz_allnodes", ISC_TF(cd->dlz_allowzonexfr != NULL)); cd->dlz_authority = (dlz_dlopen_authority_t *) dl_load_symbol(cd, "dlz_authority", ISC_FALSE); cd->dlz_newversion = (dlz_dlopen_newversion_t *) dl_load_symbol(cd, "dlz_newversion", ISC_FALSE); cd->dlz_closeversion = (dlz_dlopen_closeversion_t *) dl_load_symbol(cd, "dlz_closeversion", ISC_TF(cd->dlz_newversion != NULL)); cd->dlz_configure = (dlz_dlopen_configure_t *) dl_load_symbol(cd, "dlz_configure", ISC_FALSE); cd->dlz_ssumatch = (dlz_dlopen_ssumatch_t *) dl_load_symbol(cd, "dlz_ssumatch", ISC_FALSE); cd->dlz_addrdataset = (dlz_dlopen_addrdataset_t *) dl_load_symbol(cd, "dlz_addrdataset", ISC_FALSE); cd->dlz_subrdataset = (dlz_dlopen_subrdataset_t *) dl_load_symbol(cd, "dlz_subrdataset", ISC_FALSE); cd->dlz_delrdataset = (dlz_dlopen_delrdataset_t *) dl_load_symbol(cd, "dlz_delrdataset", ISC_FALSE); /* Check the version of the API is the same */ cd->version = cd->dlz_version(&cd->flags); if (cd->version < (DLZ_DLOPEN_VERSION - DLZ_DLOPEN_AGE) || cd->version > DLZ_DLOPEN_VERSION) { dlopen_log(ISC_LOG_ERROR, "dlz_dlopen: %s: incorrect driver API version %d, " "requires %d", cd->dl_path, cd->version, DLZ_DLOPEN_VERSION); result = ISC_R_FAILURE; goto cleanup_lock; } /* * Call the library's create function. Note that this is an * extended version of dlz create, with the addition of * named function pointers for helper functions that the * driver will need. This avoids the need for the backend to * link the BIND9 libraries */ MAYBE_LOCK(cd); result = cd->dlz_create(dlzname, argc-1, argv+1, &cd->dbdata, "log", dlopen_log, "putrr", dns_sdlz_putrr, "putnamedrr", dns_sdlz_putnamedrr, "writeable_zone", dns_dlz_writeablezone, NULL); MAYBE_UNLOCK(cd); if (result != ISC_R_SUCCESS) goto cleanup_lock; *dbdata = cd; return (ISC_R_SUCCESS); cleanup_lock: DESTROYLOCK(&cd->lock); failed: dlopen_log(ISC_LOG_ERROR, "dlz_dlopen of '%s' failed", dlzname); if (cd->dl_path) isc_mem_free(mctx, cd->dl_path); if (cd->dlzname) isc_mem_free(mctx, cd->dlzname); if (triedload) (void) isc_mutex_destroy(&cd->lock); if (cd->dl_handle) FreeLibrary(cd->dl_handle); isc_mem_put(mctx, cd, sizeof(*cd)); isc_mem_destroy(&mctx); return (result); } /* * Called when bind is shutting down */ static void dlopen_dlz_destroy(void *driverarg, void *dbdata) { dlopen_data_t *cd = (dlopen_data_t *) dbdata; isc_mem_t *mctx; UNUSED(driverarg); if (cd->dlz_destroy) { MAYBE_LOCK(cd); cd->dlz_destroy(cd->dbdata); MAYBE_UNLOCK(cd); } if (cd->dl_path) isc_mem_free(cd->mctx, cd->dl_path); if (cd->dlzname) isc_mem_free(cd->mctx, cd->dlzname); if (cd->dl_handle) FreeLibrary(cd->dl_handle); DESTROYLOCK(&cd->lock); mctx = cd->mctx; isc_mem_put(mctx, cd, sizeof(*cd)); isc_mem_destroy(&mctx); } /* * Called to start a transaction */ static isc_result_t dlopen_dlz_newversion(const char *zone, void *driverarg, void *dbdata, void **versionp) { dlopen_data_t *cd = (dlopen_data_t *) dbdata; isc_result_t result; UNUSED(driverarg); if (cd->dlz_newversion == NULL) return (ISC_R_NOTIMPLEMENTED); MAYBE_LOCK(cd); result = cd->dlz_newversion(zone, cd->dbdata, versionp); MAYBE_UNLOCK(cd); return (result); } /* * Called to end a transaction */ static void dlopen_dlz_closeversion(const char *zone, isc_boolean_t commit, void *driverarg, void *dbdata, void **versionp) { dlopen_data_t *cd = (dlopen_data_t *) dbdata; UNUSED(driverarg); if (cd->dlz_newversion == NULL) { *versionp = NULL; return; } MAYBE_LOCK(cd); cd->dlz_closeversion(zone, commit, cd->dbdata, versionp); MAYBE_UNLOCK(cd); } /* * Called on startup to configure any writeable zones */ static isc_result_t dlopen_dlz_configure(dns_view_t *view, dns_dlzdb_t *dlzdb, void *driverarg, void *dbdata) { dlopen_data_t *cd = (dlopen_data_t *) dbdata; isc_result_t result; UNUSED(driverarg); if (cd->dlz_configure == NULL) return (ISC_R_SUCCESS); MAYBE_LOCK(cd); cd->in_configure = ISC_TRUE; result = cd->dlz_configure(view, dlzdb, cd->dbdata); cd->in_configure = ISC_FALSE; MAYBE_UNLOCK(cd); return (result); } /* * Check for authority to change a name */ static isc_boolean_t dlopen_dlz_ssumatch(const char *signer, const char *name, const char *tcpaddr, const char *type, const char *key, isc_uint32_t keydatalen, unsigned char *keydata, void *driverarg, void *dbdata) { dlopen_data_t *cd = (dlopen_data_t *) dbdata; isc_boolean_t ret; UNUSED(driverarg); if (cd->dlz_ssumatch == NULL) return (ISC_FALSE); MAYBE_LOCK(cd); ret = cd->dlz_ssumatch(signer, name, tcpaddr, type, key, keydatalen, keydata, cd->dbdata); MAYBE_UNLOCK(cd); return (ret); } /* * Add an rdataset */ static isc_result_t dlopen_dlz_addrdataset(const char *name, const char *rdatastr, void *driverarg, void *dbdata, void *version) { dlopen_data_t *cd = (dlopen_data_t *) dbdata; isc_result_t result; UNUSED(driverarg); if (cd->dlz_addrdataset == NULL) return (ISC_R_NOTIMPLEMENTED); MAYBE_LOCK(cd); result = cd->dlz_addrdataset(name, rdatastr, cd->dbdata, version); MAYBE_UNLOCK(cd); return (result); } /* * Subtract an rdataset */ static isc_result_t dlopen_dlz_subrdataset(const char *name, const char *rdatastr, void *driverarg, void *dbdata, void *version) { dlopen_data_t *cd = (dlopen_data_t *) dbdata; isc_result_t result; UNUSED(driverarg); if (cd->dlz_subrdataset == NULL) return (ISC_R_NOTIMPLEMENTED); MAYBE_LOCK(cd); result = cd->dlz_subrdataset(name, rdatastr, cd->dbdata, version); MAYBE_UNLOCK(cd); return (result); } /* delete a rdataset */ static isc_result_t dlopen_dlz_delrdataset(const char *name, const char *type, void *driverarg, void *dbdata, void *version) { dlopen_data_t *cd = (dlopen_data_t *) dbdata; isc_result_t result; UNUSED(driverarg); if (cd->dlz_delrdataset == NULL) return (ISC_R_NOTIMPLEMENTED); MAYBE_LOCK(cd); result = cd->dlz_delrdataset(name, type, cd->dbdata, version); MAYBE_UNLOCK(cd); return (result); } static dns_sdlzmethods_t dlz_dlopen_methods = { dlopen_dlz_create, dlopen_dlz_destroy, dlopen_dlz_findzonedb, dlopen_dlz_lookup, dlopen_dlz_authority, dlopen_dlz_allnodes, dlopen_dlz_allowzonexfr, dlopen_dlz_newversion, dlopen_dlz_closeversion, dlopen_dlz_configure, dlopen_dlz_ssumatch, dlopen_dlz_addrdataset, dlopen_dlz_subrdataset, dlopen_dlz_delrdataset }; #endif /* * Register driver with BIND */ isc_result_t dlz_dlopen_init(isc_mem_t *mctx) { #ifndef ISC_DLZ_DLOPEN UNUSED(mctx); return (ISC_R_NOTIMPLEMENTED); #else isc_result_t result; dlopen_log(2, "Registering DLZ_dlopen driver"); result = dns_sdlzregister("dlopen", &dlz_dlopen_methods, NULL, DNS_SDLZFLAG_RELATIVEOWNER | DNS_SDLZFLAG_RELATIVERDATA | DNS_SDLZFLAG_THREADSAFE, mctx, &dlz_dlopen); if (result != ISC_R_SUCCESS) { UNEXPECTED_ERROR(__FILE__, __LINE__, "dns_sdlzregister() failed: %s", isc_result_totext(result)); result = ISC_R_UNEXPECTED; } return (result); #endif } /* * Unregister the driver */ void dlz_dlopen_clear(void) { #ifdef ISC_DLZ_DLOPEN dlopen_log(2, "Unregistering DLZ_dlopen driver"); if (dlz_dlopen != NULL) dns_sdlzunregister(&dlz_dlopen); #endif } bind9-9.11.3+dfsg/bin/named/win32/include/000077500000000000000000000000001325250447100177555ustar00rootroot00000000000000bind9-9.11.3+dfsg/bin/named/win32/include/named/000077500000000000000000000000001325250447100210415ustar00rootroot00000000000000bind9-9.11.3+dfsg/bin/named/win32/include/named/ntservice.h000066400000000000000000000011751325250447100232200ustar00rootroot00000000000000/* * Copyright (C) 1999-2004, 2007, 2016 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* $Id: ntservice.h,v 1.6 2007/06/19 23:46:59 tbox Exp $ */ #ifndef NTSERVICE_H #define NTSERVICE_H #include #define BIND_DISPLAY_NAME "ISC BIND" #define BIND_SERVICE_NAME "named" void ntservice_init(); void UpdateSCM(DWORD); void ServiceControl(DWORD dwCtrlCode); void ntservice_shutdown(); BOOL ntservice_isservice(); #endif bind9-9.11.3+dfsg/bin/named/win32/include/named/os.h000066400000000000000000000022251325250447100216340ustar00rootroot00000000000000/* * Copyright (C) 1999-2002, 2004, 2007-2009, 2014, 2016, 2017 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef NS_OS_H #define NS_OS_H 1 #include void ns_os_init(const char *progname); void ns_os_daemonize(void); void ns_os_opendevnull(void); void ns_os_closedevnull(void); void ns_os_chroot(const char *root); void ns_os_inituserinfo(const char *username); void ns_os_changeuser(void); unsigned int ns_os_uid(void); void ns_os_adjustnofile(void); void ns_os_minprivs(void); FILE * ns_os_openfile(const char *filename, int mode, isc_boolean_t switch_user); void ns_os_writepidfile(const char *filename, isc_boolean_t first_time); isc_boolean_t ns_os_issingleton(const char *filename); void ns_os_shutdown(void); isc_result_t ns_os_gethostname(char *buf, size_t len); void ns_os_shutdownmsg(char *command, isc_buffer_t *text); void ns_os_tzset(void); void ns_os_started(void); char * ns_os_uname(void); #endif /* NS_OS_H */ bind9-9.11.3+dfsg/bin/named/win32/named.dsp.in000066400000000000000000000224741325250447100205440ustar00rootroot00000000000000# Microsoft Developer Studio Project File - Name="named" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "@PLATFORM@ (x86) Console Application" 0x0103 CFG=named - @PLATFORM@ Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "named.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "named.mak" CFG="named - @PLATFORM@ Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "named - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE "named - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "named - @PLATFORM@ Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 @COPTX@ @COPTI@ /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c # ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 @OPENSSL_INC@ @GSSAPI_INC@ @GEOIP_INC@ /I "./" /I "../../../" @LIBXML2_INC@ /I "../win32/include" /I "../include" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/win32/include" /I "../../../lib/dns/include" /I "../../../lib/isccc/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" /I "../../../lib/isccfg/include" /I "../../../lib/bind9/include" @CRYPTO@ @USE_GSSAPI@ /D "BUILDER=\"old Visual Studio\"" /D "WIN32" /D "NDEBUG" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console @MACHINE@ # ADD LINK32 @LIBXML2_LIB@ @OPENSSL_LIB@ @GSSAPI_LIB@ @GEOIP_LIB@ user32.lib advapi32.lib kernel32.lib version.lib ws2_32.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib ../../../lib/isccc/win32/Release/libisccc.lib ../../../lib/lwres/win32/Release/liblwres.lib ../../../lib/isccfg/win32/Release/libisccfg.lib ../../../lib/bind9/win32/Release/libbind9.lib /nologo /subsystem:console @MACHINE@ /out:"../../../Build/Release/named.exe" !ELSEIF "$(CFG)" == "named - @PLATFORM@ Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /GZ /c # ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od @OPENSSL_INC@ @GSSAPI_INC@ @GEOIP_INC@ /I "./" /I "../../../" @LIBXML2_INC@ /I "../win32/include" /I "../include" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/win32/include" /I "../../../lib/dns/include" /I "../../../lib/isccc/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" /I "../../../lib/isccfg/include" /I "../../../lib/bind9/include" @CRYPTO@ @USE_GSSAPI@ /D "BUILDER=\"old Visual Studio\"" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "i386" /FR /FD /GZ /c # SUBTRACT CPP /X @COPTY@ # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug @MACHINE@ /pdbtype:sept # ADD LINK32 @LIBXML2_LIB@ @OPENSSL_LIB@ @GSSAPI_LIB@ @GEOIP_LIB@ user32.lib advapi32.lib kernel32.lib version.lib ws2_32.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib ../../../lib/isccc/win32/Debug/libisccc.lib ../../../lib/lwres/win32/Debug/liblwres.lib ../../../lib/isccfg/win32/Debug/libisccfg.lib ../../../lib/bind9/win32/Debug/libbind9.lib /nologo /subsystem:console /map /debug @MACHINE@ /out:"../../../Build/Debug/named.exe" /pdbtype:sept !ENDIF # Begin Target # Name "named - @PLATFORM@ Release" # Name "named - @PLATFORM@ Debug" # Begin Group "Source Files" # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" # Begin Source File SOURCE=..\builtin.c # End Source File # Begin Source File SOURCE=..\client.c # End Source File # Begin Source File SOURCE=..\config.c # End Source File # Begin Source File SOURCE=..\control.c # End Source File # Begin Source File SOURCE=..\controlconf.c # End Source File # Begin Source File SOURCE=.\dlz_dlopen_driver.c # End Source File @IF GEOIP # Begin Source File SOURCE=..\geoip.c # End Source File @END GEOIP # Begin Source File SOURCE=..\interfacemgr.c # End Source File # Begin Source File SOURCE=..\listenlist.c # End Source File # Begin Source File SOURCE=..\log.c # End Source File # Begin Source File SOURCE=..\logconf.c # End Source File # Begin Source File SOURCE=..\lwaddr.c # End Source File # Begin Source File SOURCE=..\lwdclient.c # End Source File # Begin Source File SOURCE=..\lwderror.c # End Source File # Begin Source File SOURCE=..\lwdgabn.c # End Source File # Begin Source File SOURCE=..\lwdgnba.c # End Source File # Begin Source File SOURCE=..\lwdgrbn.c # End Source File # Begin Source File SOURCE=..\lwdnoop.c # End Source File # Begin Source File SOURCE=..\lwresd.c # End Source File # Begin Source File SOURCE=..\lwsearch.c # End Source File # Begin Source File SOURCE=..\main.c # End Source File # Begin Source File SOURCE=..\notify.c # End Source File # Begin Source File SOURCE=.\ntservice.c # End Source File # Begin Source File SOURCE=.\os.c # End Source File # Begin Source File SOURCE=..\query.c # End Source File # Begin Source File SOURCE=..\server.c # End Source File # Begin Source File SOURCE=..\sortlist.c # End Source File # Begin Source File SOURCE=..\statschannel.c # End Source File # Begin Source File SOURCE=..\tkeyconf.c # End Source File # Begin Source File SOURCE=..\tsigconf.c # End Source File # Begin Source File SOURCE=..\update.c # End Source File # Begin Source File SOURCE=..\xfrout.c # End Source File # Begin Source File SOURCE=..\zoneconf.c # End Source File # End Group # Begin Group "Header Files" # PROP Default_Filter "h;hpp;hxx;hm;inl" # Begin Source File SOURCE=..\include\named\client.h # End Source File # Begin Source File SOURCE=..\include\named\config.h # End Source File # Begin Source File SOURCE=..\include\named\globals.h # End Source File # Begin Source File SOURCE=..\include\named\interfacemgr.h # End Source File # Begin Source File SOURCE=..\include\named\listenlist.h # End Source File # Begin Source File SOURCE=..\include\named\log.h # End Source File # Begin Source File SOURCE=..\include\named\logconf.h # End Source File # Begin Source File SOURCE=..\include\named\lwaddr.h # End Source File # Begin Source File SOURCE=..\include\named\lwdclient.h # End Source File # Begin Source File SOURCE=..\include\named\lwresd.h # End Source File # Begin Source File SOURCE=..\include\named\lwsearch.h # End Source File # Begin Source File SOURCE=..\include\named\main.h # End Source File # Begin Source File SOURCE=..\include\named\notify.h # End Source File # Begin Source File SOURCE=.\include\named\ntservice.h # End Source File # Begin Source File SOURCE=..\include\named\omapi.h # End Source File # Begin Source File SOURCE=.\include\named\os.h # End Source File # Begin Source File SOURCE=..\include\named\query.h # End Source File # Begin Source File SOURCE=..\include\named\seccomp.h # End Source File # Begin Source File SOURCE=..\include\named\server.h # End Source File # Begin Source File SOURCE=..\include\named\sortlist.h # End Source File # Begin Source File SOURCE=..\include\named\statschannel.h # End Source File # Begin Source File SOURCE=..\include\named\tkeyconf.h # End Source File # Begin Source File SOURCE=..\include\named\tsigconf.h # End Source File # Begin Source File SOURCE=..\include\named\types.h # End Source File # Begin Source File SOURCE=..\include\named\update.h # End Source File # Begin Source File SOURCE=..\include\named\xfrout.h # End Source File # Begin Source File SOURCE=..\include\named\zoneconf.h # End Source File # End Group # Begin Group "Resource Files" # PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" # End Group # End Target # End Project bind9-9.11.3+dfsg/bin/named/win32/named.dsw000066400000000000000000000010271325250447100201350ustar00rootroot00000000000000Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "named"=".\named.dsp" - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### bind9-9.11.3+dfsg/bin/named/win32/named.mak.in000066400000000000000000000750051325250447100205240ustar00rootroot00000000000000# Microsoft Developer Studio Generated NMAKE File, Based on named.dsp !IF "$(CFG)" == "" CFG=named - @PLATFORM@ Debug !MESSAGE No configuration specified. Defaulting to named - @PLATFORM@ Debug. !ENDIF !IF "$(CFG)" != "named - @PLATFORM@ Release" && "$(CFG)" != "named - @PLATFORM@ Debug" !MESSAGE Invalid configuration "$(CFG)" specified. !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "named.mak" CFG="named - @PLATFORM@ Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "named - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE "named - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE !ERROR An invalid configuration is specified. !ENDIF !IF "$(OS)" == "Windows_NT" NULL= !ELSE NULL=nul !ENDIF CPP=cl.exe RSC=rc.exe LIBXML=@LIBXML2_LIB@ !IF "$(CFG)" == "named - @PLATFORM@ Release" _VC_MANIFEST_INC=0 _VC_MANIFEST_BASENAME=__VC80 !ELSE _VC_MANIFEST_INC=1 _VC_MANIFEST_BASENAME=__VC80.Debug !ENDIF #################################################### # Specifying name of temporary resource file used only in incremental builds: !if "$(_VC_MANIFEST_INC)" == "1" _VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res !else _VC_MANIFEST_AUTO_RES= !endif #################################################### # _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE: !if "$(_VC_MANIFEST_INC)" == "1" #MT_SPECIAL_RETURN=1090650113 #MT_SPECIAL_SWITCH=-notify_resource_update MT_SPECIAL_RETURN=0 MT_SPECIAL_SWITCH= _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \ if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \ rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \ link $** /out:$@ $(LFLAGS) !else _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1 !endif #################################################### # _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL: !if "$(_VC_MANIFEST_INC)" == "1" #MT_SPECIAL_RETURN=1090650113 #MT_SPECIAL_SWITCH=-notify_resource_update MT_SPECIAL_RETURN=0 MT_SPECIAL_SWITCH= _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \ if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \ rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \ link $** /out:$@ $(LFLAGS) !else _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2 !endif #################################################### # _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily: !if "$(_VC_MANIFEST_INC)" == "1" _VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \ $(_VC_MANIFEST_BASENAME).auto.rc \ $(_VC_MANIFEST_BASENAME).auto.manifest !else _VC_MANIFEST_CLEAN= !endif !IF "$(CFG)" == "named - @PLATFORM@ Release" OUTDIR=.\Release INTDIR=.\Release !IF "$(RECURSE)" == "0" ALL : "..\..\..\Build\Release\named.exe" !ELSE ALL : "libisccfg - @PLATFORM@ Release" "libisccc - @PLATFORM@ Release" "liblwres - @PLATFORM@ Release" "libbind9 - @PLATFORM@ Release" "libisc - @PLATFORM@ Release" "libdns - @PLATFORM@ Release" "..\..\..\Build\Release\named.exe" !ENDIF !IF "$(RECURSE)" == "1" CLEAN :"libdns - @PLATFORM@ ReleaseCLEAN" "libisc - @PLATFORM@ ReleaseCLEAN" "libbind9 - @PLATFORM@ ReleaseCLEAN" "liblwres - @PLATFORM@ ReleaseCLEAN" "libisccc - @PLATFORM@ ReleaseCLEAN" "libisccfg - @PLATFORM@ ReleaseCLEAN" !ELSE CLEAN : !ENDIF -@erase "$(INTDIR)\builtin.obj" -@erase "$(INTDIR)\client.obj" -@erase "$(INTDIR)\config.obj" -@erase "$(INTDIR)\control.obj" -@erase "$(INTDIR)\controlconf.obj" -@erase "$(INTDIR)\dlz_dlopen_driver.obj" @IF GEOIP -@erase "$(INTDIR)\geoip.obj" @END GEOIP -@erase "$(INTDIR)\interfacemgr.obj" -@erase "$(INTDIR)\listenlist.obj" -@erase "$(INTDIR)\log.obj" -@erase "$(INTDIR)\logconf.obj" -@erase "$(INTDIR)\lwaddr.obj" -@erase "$(INTDIR)\lwdclient.obj" -@erase "$(INTDIR)\lwderror.obj" -@erase "$(INTDIR)\lwdgabn.obj" -@erase "$(INTDIR)\lwdgnba.obj" -@erase "$(INTDIR)\lwdgrbn.obj" -@erase "$(INTDIR)\lwdnoop.obj" -@erase "$(INTDIR)\lwresd.obj" -@erase "$(INTDIR)\lwsearch.obj" -@erase "$(INTDIR)\main.obj" -@erase "$(INTDIR)\notify.obj" -@erase "$(INTDIR)\ntservice.obj" -@erase "$(INTDIR)\os.obj" -@erase "$(INTDIR)\query.obj" -@erase "$(INTDIR)\server.obj" -@erase "$(INTDIR)\sortlist.obj" -@erase "$(INTDIR)\statschannel.obj" -@erase "$(INTDIR)\tkeyconf.obj" -@erase "$(INTDIR)\tsigconf.obj" -@erase "$(INTDIR)\update.obj" -@erase "$(INTDIR)\vc60.idb" -@erase "$(INTDIR)\xfrout.obj" -@erase "$(INTDIR)\zoneconf.obj" -@erase "..\..\..\Build\Release\named.exe" -@$(_VC_MANIFEST_CLEAN) "$(OUTDIR)" : if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" CPP_PROJ=/nologo /MD /W3 @COPTX@ @COPTI@ /O2 @OPENSSL_INC@ @GSSAPI_INC@ /I "./" /I "../../../" @LIBXML2_INC@ /I "../win32/include" /I "../include" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/win32/include" /I "../../../lib/dns/include" /I "../../../lib/isccc/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" /I "../../../lib/isccfg/include" /I "../../../lib/bind9/include" @CRYPTO@ @USE_GSSAPI@ /D "BUILDER=\"nmake\"" /D "WIN32" /D "NDEBUG" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\named.pch" @COPTY@ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c BSC32=bscmake.exe BSC32_FLAGS=/nologo /o"$(OUTDIR)\named.bsc" BSC32_SBRS= \ LINK32=link.exe LINK32_FLAGS=user32.lib advapi32.lib kernel32.lib version.lib ws2_32.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib ../../../lib/isccc/win32/Release/libisccc.lib ../../../lib/lwres/win32/Release/liblwres.lib ../../../lib/isccfg/win32/Release/libisccfg.lib ../../../lib/bind9/win32/Release/libbind9.lib $(LIBXML) @OPENSSL_LIB@ @GSSAPI_LIB@ @GEOIP_LIB@ /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\named.pdb" @MACHINE@ /out:"../../../Build/Release/named.exe" LINK32_OBJS= \ "$(INTDIR)\client.obj" \ "$(INTDIR)\config.obj" \ "$(INTDIR)\control.obj" \ "$(INTDIR)\controlconf.obj" \ "$(INTDIR)\dlz_dlopen_driver.obj" \ @IF GEOIP "$(INTDIR)\geoip.obj" \ @END GEOIP "$(INTDIR)\interfacemgr.obj" \ "$(INTDIR)\listenlist.obj" \ "$(INTDIR)\log.obj" \ "$(INTDIR)\logconf.obj" \ "$(INTDIR)\lwaddr.obj" \ "$(INTDIR)\lwdclient.obj" \ "$(INTDIR)\lwderror.obj" \ "$(INTDIR)\lwdgabn.obj" \ "$(INTDIR)\lwdgnba.obj" \ "$(INTDIR)\lwdgrbn.obj" \ "$(INTDIR)\lwdnoop.obj" \ "$(INTDIR)\lwresd.obj" \ "$(INTDIR)\lwsearch.obj" \ "$(INTDIR)\main.obj" \ "$(INTDIR)\notify.obj" \ "$(INTDIR)\ntservice.obj" \ "$(INTDIR)\os.obj" \ "$(INTDIR)\query.obj" \ "$(INTDIR)\server.obj" \ "$(INTDIR)\sortlist.obj" \ "$(INTDIR)\statschannel.obj" \ "$(INTDIR)\tkeyconf.obj" \ "$(INTDIR)\tsigconf.obj" \ "$(INTDIR)\update.obj" \ "$(INTDIR)\xfrout.obj" \ "$(INTDIR)\zoneconf.obj" \ "$(INTDIR)\builtin.obj" \ "..\..\..\lib\dns\win32\Release\libdns.lib" \ "..\..\..\lib\isc\win32\Release\libisc.lib" \ "..\..\..\lib\bind9\win32\Release\libbind9.lib" \ "..\..\..\lib\lwres\win32\Release\liblwres.lib" \ "..\..\..\lib\isccc\win32\Release\libisccc.lib" \ "..\..\..\lib\isccfg\win32\Release\libisccfg.lib" "..\..\..\Build\Release\named.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) $(LINK32) @<< $(LINK32_FLAGS) $(LINK32_OBJS) << $(_VC_MANIFEST_EMBED_EXE) !ELSEIF "$(CFG)" == "named - @PLATFORM@ Debug" OUTDIR=.\Debug INTDIR=.\Debug # Begin Custom Macros OutDir=.\Debug # End Custom Macros !IF "$(RECURSE)" == "0" ALL : "..\..\..\Build\Debug\named.exe" "$(OUTDIR)\named.bsc" !ELSE ALL : "libisccfg - @PLATFORM@ Debug" "libisccc - @PLATFORM@ Debug" "liblwres - @PLATFORM@ Debug" "libbind9 - @PLATFORM@ Debug" "libisc - @PLATFORM@ Debug" "libdns - @PLATFORM@ Debug" "..\..\..\Build\Debug\named.exe" "$(OUTDIR)\named.bsc" !ENDIF !IF "$(RECURSE)" == "1" CLEAN :"libdns - @PLATFORM@ DebugCLEAN" "libisc - @PLATFORM@ DebugCLEAN" "libbind9 - @PLATFORM@ DebugCLEAN" "liblwres - @PLATFORM@ DebugCLEAN" "libisccc - @PLATFORM@ DebugCLEAN" "libisccfg - @PLATFORM@ DebugCLEAN" !ELSE CLEAN : !ENDIF -@erase "$(INTDIR)\builtin.obj" -@erase "$(INTDIR)\builtin.sbr" -@erase "$(INTDIR)\client.obj" -@erase "$(INTDIR)\client.sbr" -@erase "$(INTDIR)\config.obj" -@erase "$(INTDIR)\config.sbr" -@erase "$(INTDIR)\control.obj" -@erase "$(INTDIR)\control.sbr" -@erase "$(INTDIR)\controlconf.obj" -@erase "$(INTDIR)\controlconf.sbr" -@erase "$(INTDIR)\dlz_dlopen_driver.obj" -@erase "$(INTDIR)\dlz_dlopen_driver.sbr" @IF GEOIP -@erase "$(INTDIR)\geoip.obj" -@erase "$(INTDIR)\geoip.sbr" @END GEOIP -@erase "$(INTDIR)\interfacemgr.obj" -@erase "$(INTDIR)\interfacemgr.sbr" -@erase "$(INTDIR)\listenlist.obj" -@erase "$(INTDIR)\listenlist.sbr" -@erase "$(INTDIR)\log.obj" -@erase "$(INTDIR)\log.sbr" -@erase "$(INTDIR)\logconf.obj" -@erase "$(INTDIR)\logconf.sbr" -@erase "$(INTDIR)\lwaddr.obj" -@erase "$(INTDIR)\lwaddr.sbr" -@erase "$(INTDIR)\lwdclient.obj" -@erase "$(INTDIR)\lwdclient.sbr" -@erase "$(INTDIR)\lwderror.obj" -@erase "$(INTDIR)\lwderror.sbr" -@erase "$(INTDIR)\lwdgabn.obj" -@erase "$(INTDIR)\lwdgabn.sbr" -@erase "$(INTDIR)\lwdgnba.obj" -@erase "$(INTDIR)\lwdgnba.sbr" -@erase "$(INTDIR)\lwdgrbn.obj" -@erase "$(INTDIR)\lwdgrbn.sbr" -@erase "$(INTDIR)\lwdnoop.obj" -@erase "$(INTDIR)\lwdnoop.sbr" -@erase "$(INTDIR)\lwresd.obj" -@erase "$(INTDIR)\lwresd.sbr" -@erase "$(INTDIR)\lwsearch.obj" -@erase "$(INTDIR)\lwsearch.sbr" -@erase "$(INTDIR)\main.obj" -@erase "$(INTDIR)\main.sbr" -@erase "$(INTDIR)\notify.obj" -@erase "$(INTDIR)\notify.sbr" -@erase "$(INTDIR)\ntservice.obj" -@erase "$(INTDIR)\ntservice.sbr" -@erase "$(INTDIR)\os.obj" -@erase "$(INTDIR)\os.sbr" -@erase "$(INTDIR)\query.obj" -@erase "$(INTDIR)\query.sbr" -@erase "$(INTDIR)\server.obj" -@erase "$(INTDIR)\server.sbr" -@erase "$(INTDIR)\sortlist.obj" -@erase "$(INTDIR)\sortlist.sbr" -@erase "$(INTDIR)\statschannel.obj" -@erase "$(INTDIR)\statschannel.sbr" -@erase "$(INTDIR)\tkeyconf.obj" -@erase "$(INTDIR)\tkeyconf.sbr" -@erase "$(INTDIR)\tsigconf.obj" -@erase "$(INTDIR)\tsigconf.sbr" -@erase "$(INTDIR)\update.obj" -@erase "$(INTDIR)\update.sbr" -@erase "$(INTDIR)\vc60.idb" -@erase "$(INTDIR)\vc60.pdb" -@erase "$(INTDIR)\xfrout.obj" -@erase "$(INTDIR)\xfrout.sbr" -@erase "$(INTDIR)\zoneconf.obj" -@erase "$(INTDIR)\zoneconf.sbr" -@erase "$(OUTDIR)\named.bsc" -@erase "$(OUTDIR)\named.map" -@erase "$(OUTDIR)\named.pdb" -@erase "..\..\..\Build\Debug\named.exe" -@erase "..\..\..\Build\Debug\named.ilk" -@$(_VC_MANIFEST_CLEAN) "$(OUTDIR)" : if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" CPP_PROJ=/nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od @OPENSSL_INC@ @GSSAPI_INC@ /I "./" /I "../../../" @LIBXML2_INC@ /I "../win32/include" /I "../include" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/win32/include" /I "../../../lib/dns/include" /I "../../../lib/isccc/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" /I "../../../lib/isccfg/include" /I "../../../lib/bind9/include" @CRYPTO@ @USE_GSSAPI@ /D "BUILDER=\"nmake\"" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "i386" /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c BSC32=bscmake.exe BSC32_FLAGS=/nologo /o"$(OUTDIR)\named.bsc" BSC32_SBRS= \ "$(INTDIR)\client.sbr" \ "$(INTDIR)\config.sbr" \ "$(INTDIR)\control.sbr" \ "$(INTDIR)\controlconf.sbr" \ "$(INTDIR)\dlz_dlopen_driver.sbr" \ @IF GEOIP "$(INTDIR)\geoip.sbr" \ @END GEOIP "$(INTDIR)\interfacemgr.sbr" \ "$(INTDIR)\listenlist.sbr" \ "$(INTDIR)\log.sbr" \ "$(INTDIR)\logconf.sbr" \ "$(INTDIR)\lwaddr.sbr" \ "$(INTDIR)\lwdclient.sbr" \ "$(INTDIR)\lwderror.sbr" \ "$(INTDIR)\lwdgabn.sbr" \ "$(INTDIR)\lwdgnba.sbr" \ "$(INTDIR)\lwdgrbn.sbr" \ "$(INTDIR)\lwdnoop.sbr" \ "$(INTDIR)\lwresd.sbr" \ "$(INTDIR)\lwsearch.sbr" \ "$(INTDIR)\main.sbr" \ "$(INTDIR)\notify.sbr" \ "$(INTDIR)\ntservice.sbr" \ "$(INTDIR)\os.sbr" \ "$(INTDIR)\query.sbr" \ "$(INTDIR)\server.sbr" \ "$(INTDIR)\sortlist.sbr" \ "$(INTDIR)\statschannel.sbr" \ "$(INTDIR)\tkeyconf.sbr" \ "$(INTDIR)\tsigconf.sbr" \ "$(INTDIR)\update.sbr" \ "$(INTDIR)\xfrout.sbr" \ "$(INTDIR)\zoneconf.sbr" \ "$(INTDIR)\builtin.sbr" "$(OUTDIR)\named.bsc" : "$(OUTDIR)" $(BSC32_SBRS) $(BSC32) @<< $(BSC32_FLAGS) $(BSC32_SBRS) << LINK32=link.exe LINK32_FLAGS=user32.lib advapi32.lib kernel32.lib version.lib ws2_32.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib ../../../lib/isccc/win32/Debug/libisccc.lib ../../../lib/lwres/win32/Debug/liblwres.lib ../../../lib/isccfg/win32/Debug/libisccfg.lib ../../../lib/bind9/win32/Debug/libbind9.lib $(LIBXML) @OPENSSL_LIB@ @GSSAPI_LIB@ @GEOIP_LIB@ /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\named.pdb" /map:"$(INTDIR)\named.map" /debug @MACHINE@ /out:"../../../Build/Debug/named.exe" /pdbtype:sept LINK32_OBJS= \ "$(INTDIR)\client.obj" \ "$(INTDIR)\config.obj" \ "$(INTDIR)\control.obj" \ "$(INTDIR)\controlconf.obj" \ "$(INTDIR)\dlz_dlopen_driver.obj" \ @IF GEOIP "$(INTDIR)\geoip.obj" \ @END GEOIP "$(INTDIR)\interfacemgr.obj" \ "$(INTDIR)\listenlist.obj" \ "$(INTDIR)\log.obj" \ "$(INTDIR)\logconf.obj" \ "$(INTDIR)\lwaddr.obj" \ "$(INTDIR)\lwdclient.obj" \ "$(INTDIR)\lwderror.obj" \ "$(INTDIR)\lwdgabn.obj" \ "$(INTDIR)\lwdgnba.obj" \ "$(INTDIR)\lwdgrbn.obj" \ "$(INTDIR)\lwdnoop.obj" \ "$(INTDIR)\lwresd.obj" \ "$(INTDIR)\lwsearch.obj" \ "$(INTDIR)\main.obj" \ "$(INTDIR)\notify.obj" \ "$(INTDIR)\ntservice.obj" \ "$(INTDIR)\os.obj" \ "$(INTDIR)\query.obj" \ "$(INTDIR)\server.obj" \ "$(INTDIR)\sortlist.obj" \ "$(INTDIR)\statschannel.obj" \ "$(INTDIR)\tkeyconf.obj" \ "$(INTDIR)\tsigconf.obj" \ "$(INTDIR)\update.obj" \ "$(INTDIR)\xfrout.obj" \ "$(INTDIR)\zoneconf.obj" \ "$(INTDIR)\builtin.obj" \ "..\..\..\lib\dns\win32\Debug\libdns.lib" \ "..\..\..\lib\isc\win32\Debug\libisc.lib" \ "..\..\..\lib\bind9\win32\Debug\libbind9.lib" \ "..\..\..\lib\lwres\win32\Debug\liblwres.lib" \ "..\..\..\lib\isccc\win32\Debug\libisccc.lib" \ "..\..\..\lib\isccfg\win32\Debug\libisccfg.lib" "..\..\..\Build\Debug\named.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) $(LINK32) @<< $(LINK32_FLAGS) $(LINK32_OBJS) << $(_VC_MANIFEST_EMBED_EXE) !ENDIF .c{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .c{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << !IF "$(NO_EXTERNAL_DEPS)" != "1" !IF EXISTS("named.dep") !INCLUDE "named.dep" !ELSE !MESSAGE Warning: cannot find "named.dep" !ENDIF !ENDIF !IF "$(CFG)" == "named - @PLATFORM@ Release" || "$(CFG)" == "named - @PLATFORM@ Debug" SOURCE=..\builtin.c !IF "$(CFG)" == "named - @PLATFORM@ Release" "$(INTDIR)\builtin.obj" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ELSEIF "$(CFG)" == "named - @PLATFORM@ Debug" "$(INTDIR)\builtin.obj" "$(INTDIR)\builtin.sbr" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ENDIF SOURCE=..\client.c !IF "$(CFG)" == "named - @PLATFORM@ Release" "$(INTDIR)\client.obj" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ELSEIF "$(CFG)" == "named - @PLATFORM@ Debug" "$(INTDIR)\client.obj" "$(INTDIR)\client.sbr" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ENDIF SOURCE=..\config.c !IF "$(CFG)" == "named - @PLATFORM@ Release" "$(INTDIR)\config.obj" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ELSEIF "$(CFG)" == "named - @PLATFORM@ Debug" "$(INTDIR)\config.obj" "$(INTDIR)\config.sbr" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ENDIF SOURCE=..\control.c !IF "$(CFG)" == "named - @PLATFORM@ Release" "$(INTDIR)\control.obj" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ELSEIF "$(CFG)" == "named - @PLATFORM@ Debug" "$(INTDIR)\control.obj" "$(INTDIR)\control.sbr" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ENDIF SOURCE=..\controlconf.c !IF "$(CFG)" == "named - @PLATFORM@ Release" "$(INTDIR)\controlconf.obj" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ELSEIF "$(CFG)" == "named - @PLATFORM@ Debug" "$(INTDIR)\controlconf.obj" "$(INTDIR)\controlconf.sbr" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ENDIF SOURCE=.\dlz_dlopen_driver.c !IF "$(CFG)" == "named - @PLATFORM@ Release" "$(INTDIR)\dlz_dlopen_driver.obj" : $(SOURCE) "$(INTDIR)" !ELSEIF "$(CFG)" == "named - @PLATFORM@ Debug" "$(INTDIR)\dlz_dlopen_driver.obj" "$(INTDIR)\dlz_dlopen_driver.sbr" : $(SOURCE) "$(INTDIR)" !ENDIF @IF GEOIP SOURCE=..\geoip.c !IF "$(CFG)" == "named - @PLATFORM@ Release" "$(INTDIR)\geoip.obj" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ELSEIF "$(CFG)" == "named - @PLATFORM@ Debug" "$(INTDIR)\geoip.obj" "$(INTDIR)\geoip.sbr" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ENDIF @END GEOIP SOURCE=..\interfacemgr.c !IF "$(CFG)" == "named - @PLATFORM@ Release" "$(INTDIR)\interfacemgr.obj" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ELSEIF "$(CFG)" == "named - @PLATFORM@ Debug" "$(INTDIR)\interfacemgr.obj" "$(INTDIR)\interfacemgr.sbr" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ENDIF SOURCE=..\listenlist.c !IF "$(CFG)" == "named - @PLATFORM@ Release" "$(INTDIR)\listenlist.obj" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ELSEIF "$(CFG)" == "named - @PLATFORM@ Debug" "$(INTDIR)\listenlist.obj" "$(INTDIR)\listenlist.sbr" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ENDIF SOURCE=..\log.c !IF "$(CFG)" == "named - @PLATFORM@ Release" "$(INTDIR)\log.obj" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ELSEIF "$(CFG)" == "named - @PLATFORM@ Debug" "$(INTDIR)\log.obj" "$(INTDIR)\log.sbr" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ENDIF SOURCE=..\logconf.c !IF "$(CFG)" == "named - @PLATFORM@ Release" "$(INTDIR)\logconf.obj" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ELSEIF "$(CFG)" == "named - @PLATFORM@ Debug" "$(INTDIR)\logconf.obj" "$(INTDIR)\logconf.sbr" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ENDIF SOURCE=..\lwaddr.c !IF "$(CFG)" == "named - @PLATFORM@ Release" "$(INTDIR)\lwaddr.obj" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ELSEIF "$(CFG)" == "named - @PLATFORM@ Debug" "$(INTDIR)\lwaddr.obj" "$(INTDIR)\lwaddr.sbr" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ENDIF SOURCE=..\lwdclient.c !IF "$(CFG)" == "named - @PLATFORM@ Release" "$(INTDIR)\lwdclient.obj" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ELSEIF "$(CFG)" == "named - @PLATFORM@ Debug" "$(INTDIR)\lwdclient.obj" "$(INTDIR)\lwdclient.sbr" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ENDIF SOURCE=..\lwderror.c !IF "$(CFG)" == "named - @PLATFORM@ Release" "$(INTDIR)\lwderror.obj" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ELSEIF "$(CFG)" == "named - @PLATFORM@ Debug" "$(INTDIR)\lwderror.obj" "$(INTDIR)\lwderror.sbr" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ENDIF SOURCE=..\lwdgabn.c !IF "$(CFG)" == "named - @PLATFORM@ Release" "$(INTDIR)\lwdgabn.obj" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ELSEIF "$(CFG)" == "named - @PLATFORM@ Debug" "$(INTDIR)\lwdgabn.obj" "$(INTDIR)\lwdgabn.sbr" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ENDIF SOURCE=..\lwdgnba.c !IF "$(CFG)" == "named - @PLATFORM@ Release" "$(INTDIR)\lwdgnba.obj" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ELSEIF "$(CFG)" == "named - @PLATFORM@ Debug" "$(INTDIR)\lwdgnba.obj" "$(INTDIR)\lwdgnba.sbr" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ENDIF SOURCE=..\lwdgrbn.c !IF "$(CFG)" == "named - @PLATFORM@ Release" "$(INTDIR)\lwdgrbn.obj" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ELSEIF "$(CFG)" == "named - @PLATFORM@ Debug" "$(INTDIR)\lwdgrbn.obj" "$(INTDIR)\lwdgrbn.sbr" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ENDIF SOURCE=..\lwdnoop.c !IF "$(CFG)" == "named - @PLATFORM@ Release" "$(INTDIR)\lwdnoop.obj" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ELSEIF "$(CFG)" == "named - @PLATFORM@ Debug" "$(INTDIR)\lwdnoop.obj" "$(INTDIR)\lwdnoop.sbr" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ENDIF SOURCE=..\lwresd.c !IF "$(CFG)" == "named - @PLATFORM@ Release" "$(INTDIR)\lwresd.obj" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ELSEIF "$(CFG)" == "named - @PLATFORM@ Debug" "$(INTDIR)\lwresd.obj" "$(INTDIR)\lwresd.sbr" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ENDIF SOURCE=..\lwsearch.c !IF "$(CFG)" == "named - @PLATFORM@ Release" "$(INTDIR)\lwsearch.obj" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ELSEIF "$(CFG)" == "named - @PLATFORM@ Debug" "$(INTDIR)\lwsearch.obj" "$(INTDIR)\lwsearch.sbr" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ENDIF SOURCE=..\main.c !IF "$(CFG)" == "named - @PLATFORM@ Release" "$(INTDIR)\main.obj" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ELSEIF "$(CFG)" == "named - @PLATFORM@ Debug" "$(INTDIR)\main.obj" "$(INTDIR)\main.sbr" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ENDIF SOURCE=..\notify.c !IF "$(CFG)" == "named - @PLATFORM@ Release" "$(INTDIR)\notify.obj" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ELSEIF "$(CFG)" == "named - @PLATFORM@ Debug" "$(INTDIR)\notify.obj" "$(INTDIR)\notify.sbr" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ENDIF SOURCE=.\ntservice.c !IF "$(CFG)" == "named - @PLATFORM@ Release" "$(INTDIR)\ntservice.obj" : $(SOURCE) "$(INTDIR)" !ELSEIF "$(CFG)" == "named - @PLATFORM@ Debug" "$(INTDIR)\ntservice.obj" "$(INTDIR)\ntservice.sbr" : $(SOURCE) "$(INTDIR)" !ENDIF SOURCE=.\os.c !IF "$(CFG)" == "named - @PLATFORM@ Release" "$(INTDIR)\os.obj" : $(SOURCE) "$(INTDIR)" !ELSEIF "$(CFG)" == "named - @PLATFORM@ Debug" "$(INTDIR)\os.obj" "$(INTDIR)\os.sbr" : $(SOURCE) "$(INTDIR)" !ENDIF SOURCE=..\query.c !IF "$(CFG)" == "named - @PLATFORM@ Release" "$(INTDIR)\query.obj" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ELSEIF "$(CFG)" == "named - @PLATFORM@ Debug" "$(INTDIR)\query.obj" "$(INTDIR)\query.sbr" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ENDIF SOURCE=..\server.c !IF "$(CFG)" == "named - @PLATFORM@ Release" "$(INTDIR)\server.obj" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ELSEIF "$(CFG)" == "named - @PLATFORM@ Debug" "$(INTDIR)\server.obj" "$(INTDIR)\server.sbr" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ENDIF SOURCE=..\sortlist.c !IF "$(CFG)" == "named - @PLATFORM@ Release" "$(INTDIR)\sortlist.obj" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ELSEIF "$(CFG)" == "named - @PLATFORM@ Debug" "$(INTDIR)\sortlist.obj" "$(INTDIR)\sortlist.sbr" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ENDIF SOURCE=..\statschannel.c !IF "$(CFG)" == "named - @PLATFORM@ Release" "$(INTDIR)\statschannel.obj" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ELSEIF "$(CFG)" == "named - @PLATFORM@ Debug" "$(INTDIR)\statschannel.obj" "$(INTDIR)\statschannel.sbr" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ENDIF SOURCE=..\tkeyconf.c !IF "$(CFG)" == "named - @PLATFORM@ Release" "$(INTDIR)\tkeyconf.obj" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ELSEIF "$(CFG)" == "named - @PLATFORM@ Debug" "$(INTDIR)\tkeyconf.obj" "$(INTDIR)\tkeyconf.sbr" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ENDIF SOURCE=..\tsigconf.c !IF "$(CFG)" == "named - @PLATFORM@ Release" "$(INTDIR)\tsigconf.obj" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ELSEIF "$(CFG)" == "named - @PLATFORM@ Debug" "$(INTDIR)\tsigconf.obj" "$(INTDIR)\tsigconf.sbr" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ENDIF SOURCE=..\update.c !IF "$(CFG)" == "named - @PLATFORM@ Release" "$(INTDIR)\update.obj" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ELSEIF "$(CFG)" == "named - @PLATFORM@ Debug" "$(INTDIR)\update.obj" "$(INTDIR)\update.sbr" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ENDIF SOURCE=..\xfrout.c !IF "$(CFG)" == "named - @PLATFORM@ Release" "$(INTDIR)\xfrout.obj" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ELSEIF "$(CFG)" == "named - @PLATFORM@ Debug" "$(INTDIR)\xfrout.obj" "$(INTDIR)\xfrout.sbr" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ENDIF SOURCE=..\zoneconf.c !IF "$(CFG)" == "named - @PLATFORM@ Release" "$(INTDIR)\zoneconf.obj" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ELSEIF "$(CFG)" == "named - @PLATFORM@ Debug" "$(INTDIR)\zoneconf.obj" "$(INTDIR)\zoneconf.sbr" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ENDIF !IF "$(CFG)" == "named - @PLATFORM@ Release" "libdns - @PLATFORM@ Release" : cd "..\..\..\lib\dns\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Release" cd "..\..\..\bin\named\win32" "libdns - @PLATFORM@ ReleaseCLEAN" : cd "..\..\..\lib\dns\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Release" RECURSE=1 CLEAN cd "..\..\..\bin\named\win32" !ELSEIF "$(CFG)" == "named - @PLATFORM@ Debug" "libdns - @PLATFORM@ Debug" : cd "..\..\..\lib\dns\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Debug" cd "..\..\..\bin\named\win32" "libdns - @PLATFORM@ DebugCLEAN" : cd "..\..\..\lib\dns\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Debug" RECURSE=1 CLEAN cd "..\..\..\bin\named\win32" !ENDIF !IF "$(CFG)" == "named - @PLATFORM@ Release" "libisc - @PLATFORM@ Release" : cd "..\..\..\lib\isc\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Release" cd "..\..\..\bin\named\win32" "libisc - @PLATFORM@ ReleaseCLEAN" : cd "..\..\..\lib\isc\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Release" RECURSE=1 CLEAN cd "..\..\..\bin\named\win32" !ELSEIF "$(CFG)" == "named - @PLATFORM@ Debug" "libisc - @PLATFORM@ Debug" : cd "..\..\..\lib\isc\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Debug" cd "..\..\..\bin\named\win32" "libisc - @PLATFORM@ DebugCLEAN" : cd "..\..\..\lib\isc\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Debug" RECURSE=1 CLEAN cd "..\..\..\bin\named\win32" !ENDIF !IF "$(CFG)" == "named - @PLATFORM@ Release" "libbind9 - @PLATFORM@ Release" : cd "..\..\..\lib\bind9\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - @PLATFORM@ Release" cd "..\..\..\bin\named\win32" "libbind9 - @PLATFORM@ ReleaseCLEAN" : cd "..\..\..\lib\bind9\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - @PLATFORM@ Release" RECURSE=1 CLEAN cd "..\..\..\bin\named\win32" !ELSEIF "$(CFG)" == "named - @PLATFORM@ Debug" "libbind9 - @PLATFORM@ Debug" : cd "..\..\..\lib\bind9\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - @PLATFORM@ Debug" cd "..\..\..\bin\named\win32" "libbind9 - @PLATFORM@ DebugCLEAN" : cd "..\..\..\lib\bind9\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - @PLATFORM@ Debug" RECURSE=1 CLEAN cd "..\..\..\bin\named\win32" !ENDIF !IF "$(CFG)" == "named - @PLATFORM@ Release" "liblwres - @PLATFORM@ Release" : cd "..\..\..\lib\lwres\win32" $(MAKE) /$(MAKEFLAGS) /F ".\liblwres.mak" CFG="liblwres - @PLATFORM@ Release" cd "..\..\..\bin\named\win32" "liblwres - @PLATFORM@ ReleaseCLEAN" : cd "..\..\..\lib\lwres\win32" $(MAKE) /$(MAKEFLAGS) /F ".\liblwres.mak" CFG="liblwres - @PLATFORM@ Release" RECURSE=1 CLEAN cd "..\..\..\bin\named\win32" !ELSEIF "$(CFG)" == "named - @PLATFORM@ Debug" "liblwres - @PLATFORM@ Debug" : cd "..\..\..\lib\lwres\win32" $(MAKE) /$(MAKEFLAGS) /F ".\liblwres.mak" CFG="liblwres - @PLATFORM@ Debug" cd "..\..\..\bin\named\win32" "liblwres - @PLATFORM@ DebugCLEAN" : cd "..\..\..\lib\lwres\win32" $(MAKE) /$(MAKEFLAGS) /F ".\liblwres.mak" CFG="liblwres - @PLATFORM@ Debug" RECURSE=1 CLEAN cd "..\..\..\bin\named\win32" !ENDIF !IF "$(CFG)" == "named - @PLATFORM@ Release" "libisccc - @PLATFORM@ Release" : cd "..\..\..\lib\isccc\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libisccc.mak" CFG="libisccc - @PLATFORM@ Release" cd "..\..\..\bin\named\win32" "libisccc - @PLATFORM@ ReleaseCLEAN" : cd "..\..\..\lib\isccc\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libisccc.mak" CFG="libisccc - @PLATFORM@ Release" RECURSE=1 CLEAN cd "..\..\..\bin\named\win32" !ELSEIF "$(CFG)" == "named - @PLATFORM@ Debug" "libisccc - @PLATFORM@ Debug" : cd "..\..\..\lib\isccc\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libisccc.mak" CFG="libisccc - @PLATFORM@ Debug" cd "..\..\..\bin\named\win32" "libisccc - @PLATFORM@ DebugCLEAN" : cd "..\..\..\lib\isccc\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libisccc.mak" CFG="libisccc - @PLATFORM@ Debug" RECURSE=1 CLEAN cd "..\..\..\bin\named\win32" !ENDIF !IF "$(CFG)" == "named - @PLATFORM@ Release" "libisccfg - @PLATFORM@ Release" : cd "..\..\..\lib\isccfg\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libisccfg.mak" CFG="libisccfg - @PLATFORM@ Release" cd "..\..\..\bin\named\win32" "libisccfg - @PLATFORM@ ReleaseCLEAN" : cd "..\..\..\lib\isccfg\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libisccfg.mak" CFG="libisccfg - @PLATFORM@ Release" RECURSE=1 CLEAN cd "..\..\..\bin\named\win32" !ELSEIF "$(CFG)" == "named - @PLATFORM@ Debug" "libisccfg - @PLATFORM@ Debug" : cd "..\..\..\lib\isccfg\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libisccfg.mak" CFG="libisccfg - @PLATFORM@ Debug" cd "..\..\..\bin\named\win32" "libisccfg - @PLATFORM@ DebugCLEAN" : cd "..\..\..\lib\isccfg\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libisccfg.mak" CFG="libisccfg - @PLATFORM@ Debug" RECURSE=1 CLEAN cd "..\..\..\bin\named\win32" !ENDIF !ENDIF #################################################### # Commands to generate initial empty manifest file and the RC file # that references it, and for generating the .res file: $(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc $(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest type <<$@ #include 1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest" << KEEP $(_VC_MANIFEST_BASENAME).auto.manifest : type <<$@ << KEEP bind9-9.11.3+dfsg/bin/named/win32/named.vcxproj.filters.in000066400000000000000000000160751325250447100231200ustar00rootroot00000000000000 {4FC737F1-C7A5-4376-A066-2A32D752A2FF} cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx {93995380-89BD-4b04-88EB-625FBE52EBFB} h;hpp;hxx;hm;inl;inc;xsd {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files @IF GEOIP Source Files @END GEOIP Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Header Files Header Files Header Files Header Files Header Files Header Files @IF GEOIP Header Files @END GEOIP Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files bind9-9.11.3+dfsg/bin/named/win32/named.vcxproj.in000066400000000000000000000245721325250447100214520ustar00rootroot00000000000000 Debug @PLATFORM@ Release @PLATFORM@ {723C65DA-A96C-4BA3-A34E-44F11CA346F9} Win32Proj named Application true MultiByte Application false true MultiByte true ..\..\..\Build\$(Configuration)\ .\$(Configuration)\ false ..\..\..\Build\$(Configuration)\ .\$(Configuration)\ Level3 Disabled WIN32;@CRYPTO@@USE_GSSAPI@BUILDER="Visual Studio";_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true .\$(Configuration)\$(TargetName).pch .\$(Configuration)\ .\$(Configuration)\ $(OutDir)$(TargetName).pdb true @OPENSSL_INC@@GSSAPI_INC@@GEOIP_INC@.\;..\..\..\;@LIBXML2_INC@..\win32\include;..\include;..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;..\..\..\lib\isccc\include;..\..\..\lib\lwres\win32\include;..\..\..\lib\lwres\include;..\..\..\lib\isccfg\include;..\..\..\lib\bind9\include;%(AdditionalIncludeDirectories) CompileAsC Console true ..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt) ..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);..\..\..\lib\isccc\win32\$(Configuration);..\..\..\lib\lwres\win32\$(Configuration);..\..\..\lib\isccfg\win32\$(Configuration);..\..\..\lib\bind9\win32\$(Configuration);%(AdditionalLibraryDirectories) @LIBXML2_LIB@@OPENSSL_LIB@@GSSAPI_LIB@@GEOIP_LIB@libisc.lib;libdns.lib;libisccc.lib;liblwres.lib;libisccfg.lib;libbind9.lib;version.lib;ws2_32.lib;%(AdditionalDependencies) Level3 MaxSpeed true @INTRINSIC@ WIN32;@CRYPTO@@USE_GSSAPI@BUILDER="Visual Studio";NDEBUG;_CONSOLE;%(PreprocessorDefinitions) OnlyExplicitInline false true .\$(Configuration)\$(TargetName).pch .\$(Configuration)\ .\$(Configuration)\ $(OutDir)$(TargetName).pdb @OPENSSL_INC@@GSSAPI_INC@@GEOIP_INC@.\;..\..\..\;@LIBXML2_INC@..\win32\include;..\include;..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;..\..\..\lib\isccc\include;..\..\..\lib\lwres\win32\include;..\..\..\lib\lwres\include;..\..\..\lib\isccfg\include;..\..\..\lib\bind9\include;%(AdditionalIncludeDirectories) CompileAsC Console false true true ..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt) Default ..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);..\..\..\lib\isccc\win32\$(Configuration);..\..\..\lib\lwres\win32\$(Configuration);..\..\..\lib\isccfg\win32\$(Configuration);..\..\..\lib\bind9\win32\$(Configuration);%(AdditionalLibraryDirectories) @LIBXML2_LIB@@OPENSSL_LIB@@GSSAPI_LIB@@GEOIP_LIB@libisc.lib;libdns.lib;libisccc.lib;liblwres.lib;libisccfg.lib;libbind9.lib;version.lib;ws2_32.lib;%(AdditionalDependencies) @IF GEOIP @END GEOIP @IF GEOIP @END GEOIP bind9-9.11.3+dfsg/bin/named/win32/named.vcxproj.user000066400000000000000000000002171325250447100220100ustar00rootroot00000000000000 bind9-9.11.3+dfsg/bin/named/win32/ntservice.c000066400000000000000000000075651325250447100205150ustar00rootroot00000000000000/* * Copyright (C) 1999-2002, 2004, 2006, 2007, 2009, 2011, 2013-2017 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* $Id: ntservice.c,v 1.16 2011/01/13 08:50:29 tbox Exp $ */ #include #include #include #include #include #include #include #include #include #include #include /* Handle to SCM for updating service status */ static SERVICE_STATUS_HANDLE hServiceStatus = 0; static BOOL foreground = FALSE; static char ConsoleTitle[128]; /* * Forward declarations */ void ServiceControl(DWORD dwCtrlCode); int bindmain(int, char *[]); /* From main.c */ /* * Initialize the Service by registering it. */ void ntservice_init(void) { if (!foreground) { /* Register handler with the SCM */ hServiceStatus = RegisterServiceCtrlHandler(BIND_SERVICE_NAME, (LPHANDLER_FUNCTION)ServiceControl); if (!hServiceStatus) { ns_main_earlyfatal( "could not register service control handler"); UpdateSCM(SERVICE_STOPPED); exit(1); } UpdateSCM(SERVICE_RUNNING); } else { strlcpy(ConsoleTitle, "BIND Version ", sizeof(ConsoleTitle)); strlcat(ConsoleTitle, VERSION, sizeof(ConsoleTitle)); SetConsoleTitle(ConsoleTitle); } } void ntservice_shutdown(void) { UpdateSCM(SERVICE_STOPPED); } /* * Routine to check if this is a service or a foreground program */ BOOL ntservice_isservice(void) { return(!foreground); } /* * ServiceControl(): Handles requests from the SCM and passes them on * to named. */ void ServiceControl(DWORD dwCtrlCode) { /* Handle the requested control code */ switch(dwCtrlCode) { case SERVICE_CONTROL_INTERROGATE: UpdateSCM(0); break; case SERVICE_CONTROL_SHUTDOWN: case SERVICE_CONTROL_STOP: ns_server_flushonshutdown(ns_g_server, ISC_TRUE); isc_app_shutdown(); UpdateSCM(SERVICE_STOPPED); break; default: break; } } /* * Tell the Service Control Manager the state of the service. */ void UpdateSCM(DWORD state) { SERVICE_STATUS ss; static DWORD dwState = SERVICE_STOPPED; if (hServiceStatus) { if (state) dwState = state; memset(&ss, 0, sizeof(SERVICE_STATUS)); ss.dwServiceType |= SERVICE_WIN32_OWN_PROCESS; ss.dwCurrentState = dwState; ss.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN; ss.dwCheckPoint = 0; ss.dwServiceSpecificExitCode = 0; ss.dwWin32ExitCode = NO_ERROR; ss.dwWaitHint = dwState == SERVICE_STOP_PENDING ? 10000 : 1000; if (!SetServiceStatus(hServiceStatus, &ss)) { ss.dwCurrentState = SERVICE_STOPPED; SetServiceStatus(hServiceStatus, &ss); } } } /* unhook main */ #undef main /* * This is the entry point for the executable * We can now call bindmain() explicitly or via StartServiceCtrlDispatcher() * as we need to. */ int main(int argc, char *argv[]) { int rc, ch; /* Command line users should put -f in the options. */ isc_commandline_errprint = ISC_FALSE; while ((ch = isc_commandline_parse(argc, argv, NS_MAIN_ARGS)) != -1) { switch (ch) { case 'f': case 'g': case 'v': case 'V': foreground = TRUE; break; default: break; } } isc_commandline_reset = ISC_TRUE; if (foreground) { /* run in console window */ exit(bindmain(argc, argv)); } else { /* Start up as service */ char *SERVICE_NAME = BIND_SERVICE_NAME; SERVICE_TABLE_ENTRY dispatchTable[] = { { TEXT(SERVICE_NAME), (LPSERVICE_MAIN_FUNCTION)bindmain }, { NULL, NULL } }; rc = StartServiceCtrlDispatcher(dispatchTable); if (!rc) { fprintf(stderr, "Use -f to run from the command line.\n"); /* will be 1063 when launched as a console app */ exit(GetLastError()); } } exit(0); } bind9-9.11.3+dfsg/bin/named/win32/os.c000066400000000000000000000225411325250447100171230ustar00rootroot00000000000000/* * Copyright (C) 1999-2002, 2004, 2005, 2007-2009, 2012-2017 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static char *lockfile = NULL; static char *pidfile = NULL; static int devnullfd = -1; static int lockfilefd = -1; static BOOL Initialized = FALSE; static char *version_error = "named requires Windows 2000 Service Pack 2 or later to run correctly"; void ns_paths_init(void) { if (!Initialized) isc_ntpaths_init(); ns_g_conffile = isc_ntpaths_get(NAMED_CONF_PATH); lwresd_g_conffile = isc_ntpaths_get(LWRES_CONF_PATH); lwresd_g_resolvconffile = isc_ntpaths_get(RESOLV_CONF_PATH); ns_g_conffile = isc_ntpaths_get(NAMED_CONF_PATH); ns_g_defaultpidfile = isc_ntpaths_get(NAMED_PID_PATH); lwresd_g_defaultpidfile = isc_ntpaths_get(LWRESD_PID_PATH); ns_g_defaultlockfile = isc_ntpaths_get(NAMED_LOCK_PATH); ns_g_keyfile = isc_ntpaths_get(RNDC_KEY_PATH); ns_g_defaultsessionkeyfile = isc_ntpaths_get(SESSION_KEY_PATH); ns_g_defaultdnstap = NULL; Initialized = TRUE; } /* * Due to Knowledge base article Q263823 we need to make sure that * Windows 2000 systems have Service Pack 2 or later installed and * warn when it isn't. */ static void version_check(const char *progname) { if ((isc_win32os_versioncheck(4, 0, 0, 0) >= 0) && (isc_win32os_versioncheck(5, 0, 0, 0) < 0)) return; /* No problem with Version 4.0 */ if (isc_win32os_versioncheck(5, 0, 2, 0) < 0) if (ntservice_isservice()) NTReportError(progname, version_error); else fprintf(stderr, "%s\n", version_error); } static void setup_syslog(const char *progname) { int options; options = LOG_PID; #ifdef LOG_NDELAY options |= LOG_NDELAY; #endif openlog(progname, options, LOG_DAEMON); } void ns_os_init(const char *progname) { ns_paths_init(); setup_syslog(progname); /* * XXXMPA. We may need to split ntservice_init() in two and * just mark as running in ns_os_started(). If we do that * this is where the first part of ntservice_init() should be * called from. * * XXX970 Remove comment if no problems by 9.7.0. * * ntservice_init(); */ version_check(progname); } void ns_os_daemonize(void) { /* * Try to set stdin, stdout, and stderr to /dev/null, but press * on even if it fails. */ if (devnullfd != -1) { if (devnullfd != _fileno(stdin)) { close(_fileno(stdin)); (void)_dup2(devnullfd, _fileno(stdin)); } if (devnullfd != _fileno(stdout)) { close(_fileno(stdout)); (void)_dup2(devnullfd, _fileno(stdout)); } if (devnullfd != _fileno(stderr)) { close(_fileno(stderr)); (void)_dup2(devnullfd, _fileno(stderr)); } } } void ns_os_opendevnull(void) { devnullfd = open("NUL", O_RDWR, 0); } void ns_os_closedevnull(void) { if (devnullfd != _fileno(stdin) && devnullfd != _fileno(stdout) && devnullfd != _fileno(stderr)) { close(devnullfd); devnullfd = -1; } } void ns_os_chroot(const char *root) { if (root != NULL) ns_main_earlyfatal("chroot(): isn't supported by Win32 API"); } void ns_os_inituserinfo(const char *username) { } void ns_os_changeuser(void) { } unsigned int ns_os_uid(void) { return (0); } void ns_os_adjustnofile(void) { } void ns_os_minprivs(void) { } static int safe_open(const char *filename, int mode, isc_boolean_t append) { int fd; struct stat sb; if (stat(filename, &sb) == -1) { if (errno != ENOENT) return (-1); } else if ((sb.st_mode & S_IFREG) == 0) return (-1); if (append) fd = open(filename, O_WRONLY|O_CREAT|O_APPEND, mode); else { (void)unlink(filename); fd = open(filename, O_WRONLY|O_CREAT|O_EXCL, mode); } return (fd); } static void cleanup_pidfile(void) { if (pidfile != NULL) { (void)unlink(pidfile); free(pidfile); } pidfile = NULL; } static void cleanup_lockfile(void) { if (lockfilefd != -1) { close(lockfilefd); lockfilefd = -1; } if (lockfile != NULL) { int n = unlink(lockfile); if (n == -1 && errno != ENOENT) ns_main_earlywarning("unlink '%s': failed", lockfile); free(lockfile); lockfile = NULL; } } FILE * ns_os_openfile(const char *filename, int mode, isc_boolean_t switch_user) { char strbuf[ISC_STRERRORSIZE]; FILE *fp; int fd; UNUSED(switch_user); fd = safe_open(filename, mode, ISC_FALSE); if (fd < 0) { isc__strerror(errno, strbuf, sizeof(strbuf)); ns_main_earlywarning("could not open file '%s': %s", filename, strbuf); return (NULL); } fp = fdopen(fd, "w"); if (fp == NULL) { isc__strerror(errno, strbuf, sizeof(strbuf)); ns_main_earlywarning("could not fdopen() file '%s': %s", filename, strbuf); close(fd); } return (fp); } void ns_os_writepidfile(const char *filename, isc_boolean_t first_time) { FILE *pidlockfile; pid_t pid; char strbuf[ISC_STRERRORSIZE]; void (*report)(const char *, ...); /* * The caller must ensure any required synchronization. */ report = first_time ? ns_main_earlyfatal : ns_main_earlywarning; cleanup_pidfile(); if (filename == NULL) return; pidfile = strdup(filename); if (pidfile == NULL) { isc__strerror(errno, strbuf, sizeof(strbuf)); (*report)("couldn't strdup() '%s': %s", filename, strbuf); return; } pidlockfile = ns_os_openfile(filename, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH, ISC_FALSE); if (pidlockfile == NULL) { free(pidfile); pidfile = NULL; return; } pid = getpid(); if (fprintf(pidlockfile, "%ld\n", (long)pid) < 0) { (*report)("fprintf() to pid file '%s' failed", filename); (void)fclose(pidlockfile); cleanup_pidfile(); return; } if (fflush(pidlockfile) == EOF) { (*report)("fflush() to pid file '%s' failed", filename); (void)fclose(pidlockfile); cleanup_pidfile(); return; } (void)fclose(pidlockfile); } isc_boolean_t ns_os_issingleton(const char *filename) { char strbuf[ISC_STRERRORSIZE]; OVERLAPPED o; if (lockfilefd != -1) return (ISC_TRUE); if (strcasecmp(filename, "none") == 0) return (ISC_TRUE); lockfile = strdup(filename); if (lockfile == NULL) { isc__strerror(errno, strbuf, sizeof(strbuf)); ns_main_earlyfatal("couldn't allocate memory for '%s': %s", filename, strbuf); } /* * ns_os_openfile() uses safeopen() which removes any existing * files. We can't use that here. */ lockfilefd = open(filename, O_WRONLY | O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); if (lockfilefd == -1) { cleanup_lockfile(); return (ISC_FALSE); } memset(&o, 0, sizeof(o)); /* Expect ERROR_LOCK_VIOLATION if already locked */ if (!LockFileEx((HANDLE) _get_osfhandle(lockfilefd), LOCKFILE_EXCLUSIVE_LOCK | LOCKFILE_FAIL_IMMEDIATELY, 0, 0, 1, &o)) { cleanup_lockfile(); return (ISC_FALSE); } return (ISC_TRUE); } void ns_os_shutdown(void) { closelog(); cleanup_pidfile(); if (lockfilefd != -1) { (void) UnlockFile((HANDLE) _get_osfhandle(lockfilefd), 0, 0, 0, 1); close(lockfilefd); lockfilefd = -1; } ntservice_shutdown(); /* This MUST be the last thing done */ } isc_result_t ns_os_gethostname(char *buf, size_t len) { int n; n = gethostname(buf, (int)len); return ((n == 0) ? ISC_R_SUCCESS : ISC_R_FAILURE); } void ns_os_shutdownmsg(char *command, isc_buffer_t *text) { UNUSED(command); UNUSED(text); } void ns_os_tzset(void) { #ifdef HAVE_TZSET tzset(); #endif } void ns_os_started(void) { ntservice_init(); } static char unamebuf[BUFSIZ]; static char *unamep = NULL; static void getuname(void) { DWORD fvilen; char *fvi; VS_FIXEDFILEINFO *ffi; UINT ffilen; SYSTEM_INFO sysinfo; char *arch; fvi = NULL; fvilen = GetFileVersionInfoSize("kernel32.dll", 0); if (fvilen == 0) { goto err; } fvi = (char *)malloc(fvilen); if (fvi == NULL) { goto err; } memset(fvi, 0, fvilen); if (GetFileVersionInfo("kernel32.dll", 0, fvilen, fvi) == 0) { goto err; } ffi = NULL; ffilen = 0; if ((VerQueryValue(fvi, "\\", &ffi, &ffilen) == 0) || (ffi == NULL) || (ffilen == 0)) { goto err; } memset(&sysinfo, 0, sizeof(sysinfo)); GetSystemInfo(&sysinfo); switch (sysinfo.wProcessorArchitecture) { case PROCESSOR_ARCHITECTURE_INTEL: arch = "x86"; break; case PROCESSOR_ARCHITECTURE_ARM: arch = "arm"; break; case PROCESSOR_ARCHITECTURE_IA64: arch = "ia64"; break; case PROCESSOR_ARCHITECTURE_AMD64: arch = "x64"; break; default: arch = "unknown architecture"; break; } snprintf(unamebuf, sizeof(unamebuf), "Windows %d %d build %d %d for %s\n", (ffi->dwProductVersionMS >> 16) & 0xffff, ffi->dwProductVersionMS & 0xffff, (ffi->dwProductVersionLS >> 16) & 0xffff, ffi->dwProductVersionLS & 0xffff, arch); err: if (fvi != NULL) { free(fvi); } unamep = unamebuf; } /* * GetVersionEx() returns 6.2 (aka Windows 8.1) since it was obsoleted * so we had to switch to the recommended way to get the Windows version. */ char * ns_os_uname(void) { if (unamep == NULL) getuname(); return (unamep); } bind9-9.11.3+dfsg/bin/named/xfrout.c000066400000000000000000001330141325250447100170650ustar00rootroot00000000000000/* * Copyright (C) 1999-2017 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* $Id$ */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /*! \file * \brief * Outgoing AXFR and IXFR. */ /* * TODO: * - IXFR over UDP */ #define XFROUT_COMMON_LOGARGS \ ns_g_lctx, DNS_LOGCATEGORY_XFER_OUT, NS_LOGMODULE_XFER_OUT #define XFROUT_PROTOCOL_LOGARGS \ XFROUT_COMMON_LOGARGS, ISC_LOG_INFO #define XFROUT_DEBUG_LOGARGS(n) \ XFROUT_COMMON_LOGARGS, ISC_LOG_DEBUG(n) #define XFROUT_RR_LOGARGS \ XFROUT_COMMON_LOGARGS, XFROUT_RR_LOGLEVEL #define XFROUT_RR_LOGLEVEL ISC_LOG_DEBUG(8) /*% * Fail unconditionally and log as a client error. * The test against ISC_R_SUCCESS is there to keep the Solaris compiler * from complaining about "end-of-loop code not reached". */ #define FAILC(code, msg) \ do { \ result = (code); \ ns_client_log(client, DNS_LOGCATEGORY_XFER_OUT, \ NS_LOGMODULE_XFER_OUT, ISC_LOG_INFO, \ "bad zone transfer request: %s (%s)", \ msg, isc_result_totext(code)); \ if (result != ISC_R_SUCCESS) goto failure; \ } while (0) #define FAILQ(code, msg, question, rdclass) \ do { \ char _buf1[DNS_NAME_FORMATSIZE]; \ char _buf2[DNS_RDATACLASS_FORMATSIZE]; \ result = (code); \ dns_name_format(question, _buf1, sizeof(_buf1)); \ dns_rdataclass_format(rdclass, _buf2, sizeof(_buf2)); \ ns_client_log(client, DNS_LOGCATEGORY_XFER_OUT, \ NS_LOGMODULE_XFER_OUT, ISC_LOG_INFO, \ "bad zone transfer request: '%s/%s': %s (%s)", \ _buf1, _buf2, msg, isc_result_totext(code)); \ if (result != ISC_R_SUCCESS) goto failure; \ } while (0) #define CHECK(op) \ do { result = (op); \ if (result != ISC_R_SUCCESS) goto failure; \ } while (0) /**************************************************************************/ static inline void inc_stats(dns_zone_t *zone, isc_statscounter_t counter) { isc_stats_increment(ns_g_server->nsstats, counter); if (zone != NULL) { isc_stats_t *zonestats = dns_zone_getrequeststats(zone); if (zonestats != NULL) isc_stats_increment(zonestats, counter); } } /**************************************************************************/ /*% Log an RR (for debugging) */ static void log_rr(dns_name_t *name, dns_rdata_t *rdata, isc_uint32_t ttl) { isc_result_t result; isc_buffer_t buf; char mem[2000]; dns_rdatalist_t rdl; dns_rdataset_t rds; dns_rdata_t rd = DNS_RDATA_INIT; dns_rdatalist_init(&rdl); rdl.type = rdata->type; rdl.rdclass = rdata->rdclass; rdl.ttl = ttl; if (rdata->type == dns_rdatatype_sig || rdata->type == dns_rdatatype_rrsig) rdl.covers = dns_rdata_covers(rdata); else rdl.covers = dns_rdatatype_none; dns_rdataset_init(&rds); dns_rdata_init(&rd); dns_rdata_clone(rdata, &rd); ISC_LIST_APPEND(rdl.rdata, &rd, link); RUNTIME_CHECK(dns_rdatalist_tordataset(&rdl, &rds) == ISC_R_SUCCESS); isc_buffer_init(&buf, mem, sizeof(mem)); result = dns_rdataset_totext(&rds, name, ISC_FALSE, ISC_FALSE, &buf); /* * We could use xfrout_log(), but that would produce * very long lines with a repetitive prefix. */ if (result == ISC_R_SUCCESS) { /* * Get rid of final newline. */ INSIST(buf.used >= 1 && ((char *) buf.base)[buf.used - 1] == '\n'); buf.used--; isc_log_write(XFROUT_RR_LOGARGS, "%.*s", (int)isc_buffer_usedlength(&buf), (char *)isc_buffer_base(&buf)); } else { isc_log_write(XFROUT_RR_LOGARGS, ""); } } /**************************************************************************/ /* * An 'rrstream_t' is a polymorphic iterator that returns * a stream of resource records. There are multiple implementations, * e.g. for generating AXFR and IXFR records streams. */ typedef struct rrstream_methods rrstream_methods_t; typedef struct rrstream { isc_mem_t *mctx; rrstream_methods_t *methods; } rrstream_t; struct rrstream_methods { isc_result_t (*first)(rrstream_t *); isc_result_t (*next)(rrstream_t *); void (*current)(rrstream_t *, dns_name_t **, isc_uint32_t *, dns_rdata_t **); void (*pause)(rrstream_t *); void (*destroy)(rrstream_t **); }; static void rrstream_noop_pause(rrstream_t *rs) { UNUSED(rs); } /**************************************************************************/ /* * An 'ixfr_rrstream_t' is an 'rrstream_t' that returns * an IXFR-like RR stream from a journal file. * * The SOA at the beginning of each sequence of additions * or deletions are included in the stream, but the extra * SOAs at the beginning and end of the entire transfer are * not included. */ typedef struct ixfr_rrstream { rrstream_t common; dns_journal_t *journal; } ixfr_rrstream_t; /* Forward declarations. */ static void ixfr_rrstream_destroy(rrstream_t **sp); static rrstream_methods_t ixfr_rrstream_methods; /* * Returns: anything dns_journal_open() or dns_journal_iter_init() * may return. */ static isc_result_t ixfr_rrstream_create(isc_mem_t *mctx, const char *journal_filename, isc_uint32_t begin_serial, isc_uint32_t end_serial, rrstream_t **sp) { ixfr_rrstream_t *s; isc_result_t result; INSIST(sp != NULL && *sp == NULL); s = isc_mem_get(mctx, sizeof(*s)); if (s == NULL) return (ISC_R_NOMEMORY); s->common.mctx = NULL; isc_mem_attach(mctx, &s->common.mctx); s->common.methods = &ixfr_rrstream_methods; s->journal = NULL; CHECK(dns_journal_open(mctx, journal_filename, DNS_JOURNAL_READ, &s->journal)); CHECK(dns_journal_iter_init(s->journal, begin_serial, end_serial)); *sp = (rrstream_t *) s; return (ISC_R_SUCCESS); failure: ixfr_rrstream_destroy((rrstream_t **) (void *)&s); return (result); } static isc_result_t ixfr_rrstream_first(rrstream_t *rs) { ixfr_rrstream_t *s = (ixfr_rrstream_t *) rs; return (dns_journal_first_rr(s->journal)); } static isc_result_t ixfr_rrstream_next(rrstream_t *rs) { ixfr_rrstream_t *s = (ixfr_rrstream_t *) rs; return (dns_journal_next_rr(s->journal)); } static void ixfr_rrstream_current(rrstream_t *rs, dns_name_t **name, isc_uint32_t *ttl, dns_rdata_t **rdata) { ixfr_rrstream_t *s = (ixfr_rrstream_t *) rs; dns_journal_current_rr(s->journal, name, ttl, rdata); } static void ixfr_rrstream_destroy(rrstream_t **rsp) { ixfr_rrstream_t *s = (ixfr_rrstream_t *) *rsp; if (s->journal != 0) dns_journal_destroy(&s->journal); isc_mem_putanddetach(&s->common.mctx, s, sizeof(*s)); } static rrstream_methods_t ixfr_rrstream_methods = { ixfr_rrstream_first, ixfr_rrstream_next, ixfr_rrstream_current, rrstream_noop_pause, ixfr_rrstream_destroy }; /**************************************************************************/ /* * An 'axfr_rrstream_t' is an 'rrstream_t' that returns * an AXFR-like RR stream from a database. * * The SOAs at the beginning and end of the transfer are * not included in the stream. */ typedef struct axfr_rrstream { rrstream_t common; dns_rriterator_t it; isc_boolean_t it_valid; } axfr_rrstream_t; /* * Forward declarations. */ static void axfr_rrstream_destroy(rrstream_t **rsp); static rrstream_methods_t axfr_rrstream_methods; static isc_result_t axfr_rrstream_create(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *ver, rrstream_t **sp) { axfr_rrstream_t *s; isc_result_t result; INSIST(sp != NULL && *sp == NULL); s = isc_mem_get(mctx, sizeof(*s)); if (s == NULL) return (ISC_R_NOMEMORY); s->common.mctx = NULL; isc_mem_attach(mctx, &s->common.mctx); s->common.methods = &axfr_rrstream_methods; s->it_valid = ISC_FALSE; CHECK(dns_rriterator_init(&s->it, db, ver, 0)); s->it_valid = ISC_TRUE; *sp = (rrstream_t *) s; return (ISC_R_SUCCESS); failure: axfr_rrstream_destroy((rrstream_t **) (void *)&s); return (result); } static isc_result_t axfr_rrstream_first(rrstream_t *rs) { axfr_rrstream_t *s = (axfr_rrstream_t *) rs; isc_result_t result; result = dns_rriterator_first(&s->it); if (result != ISC_R_SUCCESS) return (result); /* Skip SOA records. */ for (;;) { dns_name_t *name_dummy = NULL; isc_uint32_t ttl_dummy; dns_rdata_t *rdata = NULL; dns_rriterator_current(&s->it, &name_dummy, &ttl_dummy, NULL, &rdata); if (rdata->type != dns_rdatatype_soa) break; result = dns_rriterator_next(&s->it); if (result != ISC_R_SUCCESS) break; } return (result); } static isc_result_t axfr_rrstream_next(rrstream_t *rs) { axfr_rrstream_t *s = (axfr_rrstream_t *) rs; isc_result_t result; /* Skip SOA records. */ for (;;) { dns_name_t *name_dummy = NULL; isc_uint32_t ttl_dummy; dns_rdata_t *rdata = NULL; result = dns_rriterator_next(&s->it); if (result != ISC_R_SUCCESS) break; dns_rriterator_current(&s->it, &name_dummy, &ttl_dummy, NULL, &rdata); if (rdata->type != dns_rdatatype_soa) break; } return (result); } static void axfr_rrstream_current(rrstream_t *rs, dns_name_t **name, isc_uint32_t *ttl, dns_rdata_t **rdata) { axfr_rrstream_t *s = (axfr_rrstream_t *) rs; dns_rriterator_current(&s->it, name, ttl, NULL, rdata); } static void axfr_rrstream_pause(rrstream_t *rs) { axfr_rrstream_t *s = (axfr_rrstream_t *) rs; dns_rriterator_pause(&s->it); } static void axfr_rrstream_destroy(rrstream_t **rsp) { axfr_rrstream_t *s = (axfr_rrstream_t *) *rsp; if (s->it_valid) dns_rriterator_destroy(&s->it); isc_mem_putanddetach(&s->common.mctx, s, sizeof(*s)); } static rrstream_methods_t axfr_rrstream_methods = { axfr_rrstream_first, axfr_rrstream_next, axfr_rrstream_current, axfr_rrstream_pause, axfr_rrstream_destroy }; /**************************************************************************/ /* * An 'soa_rrstream_t' is a degenerate 'rrstream_t' that returns * a single SOA record. */ typedef struct soa_rrstream { rrstream_t common; dns_difftuple_t *soa_tuple; } soa_rrstream_t; /* * Forward declarations. */ static void soa_rrstream_destroy(rrstream_t **rsp); static rrstream_methods_t soa_rrstream_methods; static isc_result_t soa_rrstream_create(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *ver, rrstream_t **sp) { soa_rrstream_t *s; isc_result_t result; INSIST(sp != NULL && *sp == NULL); s = isc_mem_get(mctx, sizeof(*s)); if (s == NULL) return (ISC_R_NOMEMORY); s->common.mctx = NULL; isc_mem_attach(mctx, &s->common.mctx); s->common.methods = &soa_rrstream_methods; s->soa_tuple = NULL; CHECK(dns_db_createsoatuple(db, ver, mctx, DNS_DIFFOP_EXISTS, &s->soa_tuple)); *sp = (rrstream_t *) s; return (ISC_R_SUCCESS); failure: soa_rrstream_destroy((rrstream_t **) (void *)&s); return (result); } static isc_result_t soa_rrstream_first(rrstream_t *rs) { UNUSED(rs); return (ISC_R_SUCCESS); } static isc_result_t soa_rrstream_next(rrstream_t *rs) { UNUSED(rs); return (ISC_R_NOMORE); } static void soa_rrstream_current(rrstream_t *rs, dns_name_t **name, isc_uint32_t *ttl, dns_rdata_t **rdata) { soa_rrstream_t *s = (soa_rrstream_t *) rs; *name = &s->soa_tuple->name; *ttl = s->soa_tuple->ttl; *rdata = &s->soa_tuple->rdata; } static void soa_rrstream_destroy(rrstream_t **rsp) { soa_rrstream_t *s = (soa_rrstream_t *) *rsp; if (s->soa_tuple != NULL) dns_difftuple_free(&s->soa_tuple); isc_mem_putanddetach(&s->common.mctx, s, sizeof(*s)); } static rrstream_methods_t soa_rrstream_methods = { soa_rrstream_first, soa_rrstream_next, soa_rrstream_current, rrstream_noop_pause, soa_rrstream_destroy }; /**************************************************************************/ /* * A 'compound_rrstream_t' objects owns a soa_rrstream * and another rrstream, the "data stream". It returns * a concatenated stream consisting of the soa_rrstream, then * the data stream, then the soa_rrstream again. * * The component streams are owned by the compound_rrstream_t * and are destroyed with it. */ typedef struct compound_rrstream { rrstream_t common; rrstream_t *components[3]; int state; isc_result_t result; } compound_rrstream_t; /* * Forward declarations. */ static void compound_rrstream_destroy(rrstream_t **rsp); static isc_result_t compound_rrstream_next(rrstream_t *rs); static rrstream_methods_t compound_rrstream_methods; /* * Requires: * soa_stream != NULL && *soa_stream != NULL * data_stream != NULL && *data_stream != NULL * sp != NULL && *sp == NULL * * Ensures: * *soa_stream == NULL * *data_stream == NULL * *sp points to a valid compound_rrstream_t * The soa and data streams will be destroyed * when the compound_rrstream_t is destroyed. */ static isc_result_t compound_rrstream_create(isc_mem_t *mctx, rrstream_t **soa_stream, rrstream_t **data_stream, rrstream_t **sp) { compound_rrstream_t *s; INSIST(sp != NULL && *sp == NULL); s = isc_mem_get(mctx, sizeof(*s)); if (s == NULL) return (ISC_R_NOMEMORY); s->common.mctx = NULL; isc_mem_attach(mctx, &s->common.mctx); s->common.methods = &compound_rrstream_methods; s->components[0] = *soa_stream; s->components[1] = *data_stream; s->components[2] = *soa_stream; s->state = -1; s->result = ISC_R_FAILURE; *soa_stream = NULL; *data_stream = NULL; *sp = (rrstream_t *) s; return (ISC_R_SUCCESS); } static isc_result_t compound_rrstream_first(rrstream_t *rs) { compound_rrstream_t *s = (compound_rrstream_t *) rs; s->state = 0; do { rrstream_t *curstream = s->components[s->state]; s->result = curstream->methods->first(curstream); } while (s->result == ISC_R_NOMORE && s->state < 2); return (s->result); } static isc_result_t compound_rrstream_next(rrstream_t *rs) { compound_rrstream_t *s = (compound_rrstream_t *) rs; rrstream_t *curstream = s->components[s->state]; s->result = curstream->methods->next(curstream); while (s->result == ISC_R_NOMORE) { /* * Make sure locks held by the current stream * are released before we switch streams. */ curstream->methods->pause(curstream); if (s->state == 2) return (ISC_R_NOMORE); s->state++; curstream = s->components[s->state]; s->result = curstream->methods->first(curstream); } return (s->result); } static void compound_rrstream_current(rrstream_t *rs, dns_name_t **name, isc_uint32_t *ttl, dns_rdata_t **rdata) { compound_rrstream_t *s = (compound_rrstream_t *) rs; rrstream_t *curstream; INSIST(0 <= s->state && s->state < 3); INSIST(s->result == ISC_R_SUCCESS); curstream = s->components[s->state]; curstream->methods->current(curstream, name, ttl, rdata); } static void compound_rrstream_pause(rrstream_t *rs) { compound_rrstream_t *s = (compound_rrstream_t *) rs; rrstream_t *curstream; INSIST(0 <= s->state && s->state < 3); curstream = s->components[s->state]; curstream->methods->pause(curstream); } static void compound_rrstream_destroy(rrstream_t **rsp) { compound_rrstream_t *s = (compound_rrstream_t *) *rsp; s->components[0]->methods->destroy(&s->components[0]); s->components[1]->methods->destroy(&s->components[1]); s->components[2] = NULL; /* Copy of components[0]. */ isc_mem_putanddetach(&s->common.mctx, s, sizeof(*s)); } static rrstream_methods_t compound_rrstream_methods = { compound_rrstream_first, compound_rrstream_next, compound_rrstream_current, compound_rrstream_pause, compound_rrstream_destroy }; /**************************************************************************/ /* * An 'xfrout_ctx_t' contains the state of an outgoing AXFR or IXFR * in progress. */ typedef struct { isc_mem_t *mctx; ns_client_t *client; unsigned int id; /* ID of request */ dns_name_t *qname; /* Question name of request */ dns_rdatatype_t qtype; /* dns_rdatatype_{a,i}xfr */ dns_rdataclass_t qclass; dns_zone_t *zone; /* (necessary for stats) */ dns_db_t *db; dns_dbversion_t *ver; isc_quota_t *quota; rrstream_t *stream; /* The XFR RR stream */ isc_boolean_t end_of_stream; /* EOS has been reached */ isc_buffer_t buf; /* Buffer for message owner names and rdatas */ isc_buffer_t txlenbuf; /* Transmit length buffer */ isc_buffer_t txbuf; /* Transmit message buffer */ void *txmem; unsigned int txmemlen; unsigned int nmsg; /* Number of messages sent */ dns_tsigkey_t *tsigkey; /* Key used to create TSIG */ isc_buffer_t *lasttsig; /* the last TSIG */ isc_boolean_t verified_tsig; /* verified request MAC */ isc_boolean_t many_answers; int sends; /* Send in progress */ isc_boolean_t shuttingdown; const char *mnemonic; /* Style of transfer */ } xfrout_ctx_t; static isc_result_t xfrout_ctx_create(isc_mem_t *mctx, ns_client_t *client, unsigned int id, dns_name_t *qname, dns_rdatatype_t qtype, dns_rdataclass_t qclass, dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, isc_quota_t *quota, rrstream_t *stream, dns_tsigkey_t *tsigkey, isc_buffer_t *lasttsig, isc_boolean_t verified_tsig, unsigned int maxtime, unsigned int idletime, isc_boolean_t many_answers, xfrout_ctx_t **xfrp); static void sendstream(xfrout_ctx_t *xfr); static void xfrout_senddone(isc_task_t *task, isc_event_t *event); static void xfrout_fail(xfrout_ctx_t *xfr, isc_result_t result, const char *msg); static void xfrout_maybe_destroy(xfrout_ctx_t *xfr); static void xfrout_ctx_destroy(xfrout_ctx_t **xfrp); static void xfrout_client_shutdown(void *arg, isc_result_t result); static void xfrout_log1(ns_client_t *client, dns_name_t *zonename, dns_rdataclass_t rdclass, int level, const char *fmt, ...) ISC_FORMAT_PRINTF(5, 6); static void xfrout_log(xfrout_ctx_t *xfr, int level, const char *fmt, ...) ISC_FORMAT_PRINTF(3, 4); /**************************************************************************/ void ns_xfr_start(ns_client_t *client, dns_rdatatype_t reqtype) { isc_result_t result; dns_name_t *question_name; dns_rdataset_t *question_rdataset; dns_zone_t *zone = NULL, *raw = NULL, *mayberaw; dns_db_t *db = NULL; dns_dbversion_t *ver = NULL; dns_rdataclass_t question_class; rrstream_t *soa_stream = NULL; rrstream_t *data_stream = NULL; rrstream_t *stream = NULL; dns_difftuple_t *current_soa_tuple = NULL; dns_name_t *soa_name; dns_rdataset_t *soa_rdataset; dns_rdata_t soa_rdata = DNS_RDATA_INIT; isc_boolean_t have_soa = ISC_FALSE; const char *mnemonic = NULL; isc_mem_t *mctx = client->mctx; dns_message_t *request = client->message; xfrout_ctx_t *xfr = NULL; isc_quota_t *quota = NULL; dns_transfer_format_t format = client->view->transfer_format; isc_netaddr_t na; dns_peer_t *peer = NULL; isc_buffer_t *tsigbuf = NULL; char *journalfile; char msg[NS_CLIENT_ACLMSGSIZE("zone transfer")]; char keyname[DNS_NAME_FORMATSIZE]; isc_boolean_t is_poll = ISC_FALSE; isc_boolean_t is_dlz = ISC_FALSE; isc_boolean_t is_ixfr = ISC_FALSE; isc_uint32_t begin_serial = 0, current_serial; switch (reqtype) { case dns_rdatatype_axfr: mnemonic = "AXFR"; break; case dns_rdatatype_ixfr: mnemonic = "IXFR"; break; default: INSIST(0); break; } ns_client_log(client, DNS_LOGCATEGORY_XFER_OUT, NS_LOGMODULE_XFER_OUT, ISC_LOG_DEBUG(6), "%s request", mnemonic); /* * Apply quota. */ result = isc_quota_attach(&ns_g_server->xfroutquota, "a); if (result != ISC_R_SUCCESS) { isc_log_write(XFROUT_COMMON_LOGARGS, ISC_LOG_WARNING, "%s request denied: %s", mnemonic, isc_result_totext(result)); goto failure; } /* * Interpret the question section. */ result = dns_message_firstname(request, DNS_SECTION_QUESTION); INSIST(result == ISC_R_SUCCESS); /* * The question section must contain exactly one question, and * it must be for AXFR/IXFR as appropriate. */ question_name = NULL; dns_message_currentname(request, DNS_SECTION_QUESTION, &question_name); question_rdataset = ISC_LIST_HEAD(question_name->list); question_class = question_rdataset->rdclass; INSIST(question_rdataset->type == reqtype); if (ISC_LIST_NEXT(question_rdataset, link) != NULL) FAILC(DNS_R_FORMERR, "multiple questions"); result = dns_message_nextname(request, DNS_SECTION_QUESTION); if (result != ISC_R_NOMORE) FAILC(DNS_R_FORMERR, "multiple questions"); result = dns_zt_find(client->view->zonetable, question_name, 0, NULL, &zone); if (result != ISC_R_SUCCESS) { /* * Normal zone table does not have a match. * Try the DLZ database */ // Temporary: only searching the first DLZ database if (! ISC_LIST_EMPTY(client->view->dlz_searched)) { result = dns_dlzallowzonexfr(client->view, question_name, &client->peeraddr, &db); if (result == ISC_R_NOPERM) { char _buf1[DNS_NAME_FORMATSIZE]; char _buf2[DNS_RDATACLASS_FORMATSIZE]; result = DNS_R_REFUSED; dns_name_format(question_name, _buf1, sizeof(_buf1)); dns_rdataclass_format(question_class, _buf2, sizeof(_buf2)); ns_client_log(client, DNS_LOGCATEGORY_SECURITY, NS_LOGMODULE_XFER_OUT, ISC_LOG_ERROR, "zone transfer '%s/%s' denied", _buf1, _buf2); goto failure; } if (result != ISC_R_SUCCESS) FAILQ(DNS_R_NOTAUTH, "non-authoritative zone", question_name, question_class); is_dlz = ISC_TRUE; } else { /* * not DLZ and not in normal zone table, we are * not authoritative */ FAILQ(DNS_R_NOTAUTH, "non-authoritative zone", question_name, question_class); } } else { /* zone table has a match */ switch(dns_zone_gettype(zone)) { /* Master and slave zones are OK for transfer. */ case dns_zone_master: case dns_zone_slave: case dns_zone_dlz: break; default: FAILQ(DNS_R_NOTAUTH, "non-authoritative zone", question_name, question_class); } CHECK(dns_zone_getdb(zone, &db)); dns_db_currentversion(db, &ver); } xfrout_log1(client, question_name, question_class, ISC_LOG_DEBUG(6), "%s question section OK", mnemonic); /* * Check the authority section. Look for a SOA record with * the same name and class as the question. */ for (result = dns_message_firstname(request, DNS_SECTION_AUTHORITY); result == ISC_R_SUCCESS; result = dns_message_nextname(request, DNS_SECTION_AUTHORITY)) { soa_name = NULL; dns_message_currentname(request, DNS_SECTION_AUTHORITY, &soa_name); /* * Ignore data whose owner name is not the zone apex. */ if (! dns_name_equal(soa_name, question_name)) continue; for (soa_rdataset = ISC_LIST_HEAD(soa_name->list); soa_rdataset != NULL; soa_rdataset = ISC_LIST_NEXT(soa_rdataset, link)) { /* * Ignore non-SOA data. */ if (soa_rdataset->type != dns_rdatatype_soa) continue; if (soa_rdataset->rdclass != question_class) continue; CHECK(dns_rdataset_first(soa_rdataset)); dns_rdataset_current(soa_rdataset, &soa_rdata); result = dns_rdataset_next(soa_rdataset); if (result == ISC_R_SUCCESS) FAILC(DNS_R_FORMERR, "IXFR authority section " "has multiple SOAs"); have_soa = ISC_TRUE; goto got_soa; } } got_soa: if (result != ISC_R_NOMORE) CHECK(result); xfrout_log1(client, question_name, question_class, ISC_LOG_DEBUG(6), "%s authority section OK", mnemonic); /* * If not a DLZ zone, decide whether to allow this transfer. */ if (!is_dlz) { ns_client_aclmsg("zone transfer", question_name, reqtype, client->view->rdclass, msg, sizeof(msg)); CHECK(ns_client_checkacl(client, NULL, msg, dns_zone_getxfracl(zone), ISC_TRUE, ISC_LOG_ERROR)); } /* * AXFR over UDP is not possible. */ if (reqtype == dns_rdatatype_axfr && (client->attributes & NS_CLIENTATTR_TCP) == 0) FAILC(DNS_R_FORMERR, "attempted AXFR over UDP"); /* * Look up the requesting server in the peer table. */ isc_netaddr_fromsockaddr(&na, &client->peeraddr); (void)dns_peerlist_peerbyaddr(client->view->peers, &na, &peer); /* * Decide on the transfer format (one-answer or many-answers). */ if (peer != NULL) (void)dns_peer_gettransferformat(peer, &format); /* * Get a dynamically allocated copy of the current SOA. */ if (is_dlz) dns_db_currentversion(db, &ver); CHECK(dns_db_createsoatuple(db, ver, mctx, DNS_DIFFOP_EXISTS, ¤t_soa_tuple)); current_serial = dns_soa_getserial(¤t_soa_tuple->rdata); if (reqtype == dns_rdatatype_ixfr) { isc_boolean_t provide_ixfr; /* * Outgoing IXFR may have been disabled for this peer * or globally. */ provide_ixfr = client->view->provideixfr; if (peer != NULL) (void) dns_peer_getprovideixfr(peer, &provide_ixfr); if (provide_ixfr == ISC_FALSE) goto axfr_fallback; if (! have_soa) FAILC(DNS_R_FORMERR, "IXFR request missing SOA"); begin_serial = dns_soa_getserial(&soa_rdata); /* * RFC1995 says "If an IXFR query with the same or * newer version number than that of the server * is received, it is replied to with a single SOA * record of the server's current version, just as * in AXFR". The claim about AXFR is incorrect, * but other than that, we do as the RFC says. * * Sending a single SOA record is also how we refuse * IXFR over UDP (currently, we always do). */ if (DNS_SERIAL_GE(begin_serial, current_serial) || (client->attributes & NS_CLIENTATTR_TCP) == 0) { CHECK(soa_rrstream_create(mctx, db, ver, &stream)); is_poll = ISC_TRUE; goto have_stream; } journalfile = is_dlz ? NULL : dns_zone_getjournal(zone); if (journalfile != NULL) result = ixfr_rrstream_create(mctx, journalfile, begin_serial, current_serial, &data_stream); else result = ISC_R_NOTFOUND; if (result == ISC_R_NOTFOUND || result == ISC_R_RANGE) { xfrout_log1(client, question_name, question_class, ISC_LOG_DEBUG(4), "IXFR version not in journal, " "falling back to AXFR"); mnemonic = "AXFR-style IXFR"; goto axfr_fallback; } CHECK(result); is_ixfr = ISC_TRUE; } else { axfr_fallback: CHECK(axfr_rrstream_create(mctx, db, ver, &data_stream)); } /* * Bracket the data stream with SOAs. */ CHECK(soa_rrstream_create(mctx, db, ver, &soa_stream)); CHECK(compound_rrstream_create(mctx, &soa_stream, &data_stream, &stream)); soa_stream = NULL; data_stream = NULL; have_stream: CHECK(dns_message_getquerytsig(request, mctx, &tsigbuf)); /* * Create the xfrout context object. This transfers the ownership * of "stream", "db", "ver", and "quota" to the xfrout context object. */ if (is_dlz) CHECK(xfrout_ctx_create(mctx, client, request->id, question_name, reqtype, question_class, zone, db, ver, quota, stream, dns_message_gettsigkey(request), tsigbuf, request->verified_sig, 3600, 3600, (format == dns_many_answers) ? ISC_TRUE : ISC_FALSE, &xfr)); else CHECK(xfrout_ctx_create(mctx, client, request->id, question_name, reqtype, question_class, zone, db, ver, quota, stream, dns_message_gettsigkey(request), tsigbuf, request->verified_sig, dns_zone_getmaxxfrout(zone), dns_zone_getidleout(zone), (format == dns_many_answers) ? ISC_TRUE : ISC_FALSE, &xfr)); xfr->mnemonic = mnemonic; stream = NULL; quota = NULL; CHECK(xfr->stream->methods->first(xfr->stream)); if (xfr->tsigkey != NULL) dns_name_format(&xfr->tsigkey->name, keyname, sizeof(keyname)); else keyname[0] = '\0'; if (is_poll) xfrout_log1(client, question_name, question_class, ISC_LOG_DEBUG(1), "IXFR poll up to date%s%s", (xfr->tsigkey != NULL) ? ": TSIG " : "", keyname); else if (is_ixfr) xfrout_log1(client, question_name, question_class, ISC_LOG_INFO, "%s started%s%s (serial %u -> %u)", mnemonic, (xfr->tsigkey != NULL) ? ": TSIG " : "", keyname, begin_serial, current_serial); else xfrout_log1(client, question_name, question_class, ISC_LOG_INFO, "%s started%s%s (serial %u)", mnemonic, (xfr->tsigkey != NULL) ? ": TSIG " : "", keyname, current_serial); if (zone != NULL) { dns_zone_getraw(zone, &raw); mayberaw = (raw != NULL) ? raw : zone; if ((client->attributes & NS_CLIENTATTR_WANTEXPIRE) != 0 && dns_zone_gettype(mayberaw) == dns_zone_slave) { isc_time_t expiretime; isc_uint32_t secs; dns_zone_getexpiretime(zone, &expiretime); secs = isc_time_seconds(&expiretime); if (secs >= client->now && result == ISC_R_SUCCESS) { client->attributes |= NS_CLIENTATTR_HAVEEXPIRE; client->expire = secs - client->now; } } if (raw != NULL) dns_zone_detach(&raw); } /* * Hand the context over to sendstream(). Set xfr to NULL; * sendstream() is responsible for either passing the * context on to a later event handler or destroying it. */ sendstream(xfr); xfr = NULL; result = ISC_R_SUCCESS; failure: if (result == DNS_R_REFUSED) inc_stats(zone, dns_nsstatscounter_xfrrej); if (quota != NULL) isc_quota_detach("a); if (current_soa_tuple != NULL) dns_difftuple_free(¤t_soa_tuple); if (stream != NULL) stream->methods->destroy(&stream); if (soa_stream != NULL) soa_stream->methods->destroy(&soa_stream); if (data_stream != NULL) data_stream->methods->destroy(&data_stream); if (ver != NULL) dns_db_closeversion(db, &ver, ISC_FALSE); if (db != NULL) dns_db_detach(&db); if (zone != NULL) dns_zone_detach(&zone); /* XXX kludge */ if (xfr != NULL) { xfrout_fail(xfr, result, "setting up zone transfer"); } else if (result != ISC_R_SUCCESS) { ns_client_log(client, DNS_LOGCATEGORY_XFER_OUT, NS_LOGMODULE_XFER_OUT, ISC_LOG_DEBUG(3), "zone transfer setup failed"); ns_client_error(client, result); } } static isc_result_t xfrout_ctx_create(isc_mem_t *mctx, ns_client_t *client, unsigned int id, dns_name_t *qname, dns_rdatatype_t qtype, dns_rdataclass_t qclass, dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, isc_quota_t *quota, rrstream_t *stream, dns_tsigkey_t *tsigkey, isc_buffer_t *lasttsig, isc_boolean_t verified_tsig, unsigned int maxtime, unsigned int idletime, isc_boolean_t many_answers, xfrout_ctx_t **xfrp) { xfrout_ctx_t *xfr; isc_result_t result; unsigned int len; void *mem; INSIST(xfrp != NULL && *xfrp == NULL); xfr = isc_mem_get(mctx, sizeof(*xfr)); if (xfr == NULL) return (ISC_R_NOMEMORY); xfr->mctx = NULL; isc_mem_attach(mctx, &xfr->mctx); xfr->client = NULL; ns_client_attach(client, &xfr->client); xfr->id = id; xfr->qname = qname; xfr->qtype = qtype; xfr->qclass = qclass; xfr->zone = NULL; xfr->db = NULL; xfr->ver = NULL; if (zone != NULL) /* zone will be NULL if it's DLZ */ dns_zone_attach(zone, &xfr->zone); dns_db_attach(db, &xfr->db); dns_db_attachversion(db, ver, &xfr->ver); xfr->end_of_stream = ISC_FALSE; xfr->tsigkey = tsigkey; xfr->lasttsig = lasttsig; xfr->verified_tsig = verified_tsig; xfr->nmsg = 0; xfr->many_answers = many_answers; xfr->sends = 0; xfr->shuttingdown = ISC_FALSE; xfr->mnemonic = NULL; xfr->buf.base = NULL; xfr->buf.length = 0; xfr->txmem = NULL; xfr->txmemlen = 0; xfr->stream = NULL; xfr->quota = NULL; /* * Allocate a temporary buffer for the uncompressed response * message data. The size should be no more than 65535 bytes * so that the compressed data will fit in a TCP message, * and no less than 65535 bytes so that an almost maximum-sized * RR will fit. Note that although 65535-byte RRs are allowed * in principle, they cannot be zone-transferred (at least not * if uncompressible), because the message and RR headers would * push the size of the TCP message over the 65536 byte limit. */ len = 65535; mem = isc_mem_get(mctx, len); if (mem == NULL) { result = ISC_R_NOMEMORY; goto failure; } isc_buffer_init(&xfr->buf, mem, len); /* * Allocate another temporary buffer for the compressed * response message and its TCP length prefix. */ len = 2 + 65535; mem = isc_mem_get(mctx, len); if (mem == NULL) { result = ISC_R_NOMEMORY; goto failure; } isc_buffer_init(&xfr->txlenbuf, mem, 2); isc_buffer_init(&xfr->txbuf, (char *) mem + 2, len - 2); xfr->txmem = mem; xfr->txmemlen = len; CHECK(dns_timer_setidle(xfr->client->timer, maxtime, idletime, ISC_FALSE)); /* * Register a shutdown callback with the client, so that we * can stop the transfer immediately when the client task * gets a shutdown event. */ xfr->client->shutdown = xfrout_client_shutdown; xfr->client->shutdown_arg = xfr; /* * These MUST be after the last "goto failure;" / CHECK to * prevent a double free by the caller. */ xfr->quota = quota; xfr->stream = stream; *xfrp = xfr; return (ISC_R_SUCCESS); failure: xfrout_ctx_destroy(&xfr); return (result); } /* * Arrange to send as much as we can of "stream" without blocking. * * Requires: * The stream iterator is initialized and points at an RR, * or possibly at the end of the stream (that is, the * _first method of the iterator has been called). */ static void sendstream(xfrout_ctx_t *xfr) { dns_message_t *tcpmsg = NULL; dns_message_t *msg = NULL; /* Client message if UDP, tcpmsg if TCP */ isc_result_t result; isc_region_t used; isc_region_t region; dns_rdataset_t *qrdataset; dns_name_t *msgname = NULL; dns_rdata_t *msgrdata = NULL; dns_rdatalist_t *msgrdl = NULL; dns_rdataset_t *msgrds = NULL; dns_compress_t cctx; isc_boolean_t cleanup_cctx = ISC_FALSE; isc_boolean_t is_tcp; int n_rrs; isc_buffer_clear(&xfr->buf); isc_buffer_clear(&xfr->txlenbuf); isc_buffer_clear(&xfr->txbuf); is_tcp = ISC_TF((xfr->client->attributes & NS_CLIENTATTR_TCP) != 0); if (!is_tcp) { /* * In the UDP case, we put the response data directly into * the client message. */ msg = xfr->client->message; CHECK(dns_message_reply(msg, ISC_TRUE)); } else { /* * TCP. Build a response dns_message_t, temporarily storing * the raw, uncompressed owner names and RR data contiguously * in xfr->buf. We know that if the uncompressed data fits * in xfr->buf, the compressed data will surely fit in a TCP * message. */ CHECK(dns_message_create(xfr->mctx, DNS_MESSAGE_INTENTRENDER, &tcpmsg)); msg = tcpmsg; msg->id = xfr->id; msg->rcode = dns_rcode_noerror; msg->flags = DNS_MESSAGEFLAG_QR | DNS_MESSAGEFLAG_AA; if ((xfr->client->attributes & NS_CLIENTATTR_RA) != 0) msg->flags |= DNS_MESSAGEFLAG_RA; CHECK(dns_message_settsigkey(msg, xfr->tsigkey)); CHECK(dns_message_setquerytsig(msg, xfr->lasttsig)); if (xfr->lasttsig != NULL) isc_buffer_free(&xfr->lasttsig); msg->verified_sig = xfr->verified_tsig; /* * Add a EDNS option to the message? */ if ((xfr->client->attributes & NS_CLIENTATTR_WANTOPT) != 0) { dns_rdataset_t *opt = NULL; CHECK(ns_client_addopt(xfr->client, msg, &opt)); CHECK(dns_message_setopt(msg, opt)); /* * Add to first message only. */ xfr->client->attributes &= ~NS_CLIENTATTR_WANTNSID; xfr->client->attributes &= ~NS_CLIENTATTR_HAVEEXPIRE; } /* * Account for reserved space. */ if (xfr->tsigkey != NULL) INSIST(msg->reserved != 0U); isc_buffer_add(&xfr->buf, msg->reserved); /* * Include a question section in the first message only. * BIND 8.2.1 will not recognize an IXFR if it does not * have a question section. */ if (xfr->nmsg == 0) { dns_name_t *qname = NULL; isc_region_t r; /* * Reserve space for the 12-byte message header * and 4 bytes of question. */ isc_buffer_add(&xfr->buf, 12 + 4); qrdataset = NULL; result = dns_message_gettemprdataset(msg, &qrdataset); if (result != ISC_R_SUCCESS) goto failure; dns_rdataset_makequestion(qrdataset, xfr->client->message->rdclass, xfr->qtype); result = dns_message_gettempname(msg, &qname); if (result != ISC_R_SUCCESS) goto failure; dns_name_init(qname, NULL); isc_buffer_availableregion(&xfr->buf, &r); INSIST(r.length >= xfr->qname->length); r.length = xfr->qname->length; isc_buffer_putmem(&xfr->buf, xfr->qname->ndata, xfr->qname->length); dns_name_fromregion(qname, &r); ISC_LIST_INIT(qname->list); ISC_LIST_APPEND(qname->list, qrdataset, link); dns_message_addname(msg, qname, DNS_SECTION_QUESTION); } else { /* * Reserve space for the 12-byte message header */ isc_buffer_add(&xfr->buf, 12); msg->tcp_continuation = 1; } } /* * Try to fit in as many RRs as possible, unless "one-answer" * format has been requested. */ for (n_rrs = 0; ; n_rrs++) { dns_name_t *name = NULL; isc_uint32_t ttl; dns_rdata_t *rdata = NULL; unsigned int size; isc_region_t r; msgname = NULL; msgrdata = NULL; msgrdl = NULL; msgrds = NULL; xfr->stream->methods->current(xfr->stream, &name, &ttl, &rdata); size = name->length + 10 + rdata->length; isc_buffer_availableregion(&xfr->buf, &r); if (size >= r.length) { /* * RR would not fit. If there are other RRs in the * buffer, send them now and leave this RR to the * next message. If this RR overflows the buffer * all by itself, fail. * * In theory some RRs might fit in a TCP message * when compressed even if they do not fit when * uncompressed, but surely we don't want * to send such monstrosities to an unsuspecting * slave. */ if (n_rrs == 0) { xfrout_log(xfr, ISC_LOG_WARNING, "RR too large for zone transfer " "(%d bytes)", size); /* XXX DNS_R_RRTOOLARGE? */ result = ISC_R_NOSPACE; goto failure; } break; } if (isc_log_wouldlog(ns_g_lctx, XFROUT_RR_LOGLEVEL)) log_rr(name, rdata, ttl); /* XXX */ result = dns_message_gettempname(msg, &msgname); if (result != ISC_R_SUCCESS) goto failure; dns_name_init(msgname, NULL); isc_buffer_availableregion(&xfr->buf, &r); INSIST(r.length >= name->length); r.length = name->length; isc_buffer_putmem(&xfr->buf, name->ndata, name->length); dns_name_fromregion(msgname, &r); /* Reserve space for RR header. */ isc_buffer_add(&xfr->buf, 10); result = dns_message_gettemprdata(msg, &msgrdata); if (result != ISC_R_SUCCESS) goto failure; isc_buffer_availableregion(&xfr->buf, &r); r.length = rdata->length; isc_buffer_putmem(&xfr->buf, rdata->data, rdata->length); dns_rdata_init(msgrdata); dns_rdata_fromregion(msgrdata, rdata->rdclass, rdata->type, &r); result = dns_message_gettemprdatalist(msg, &msgrdl); if (result != ISC_R_SUCCESS) goto failure; msgrdl->type = rdata->type; msgrdl->rdclass = rdata->rdclass; msgrdl->ttl = ttl; if (rdata->type == dns_rdatatype_sig || rdata->type == dns_rdatatype_rrsig) msgrdl->covers = dns_rdata_covers(rdata); else msgrdl->covers = dns_rdatatype_none; ISC_LIST_APPEND(msgrdl->rdata, msgrdata, link); result = dns_message_gettemprdataset(msg, &msgrds); if (result != ISC_R_SUCCESS) goto failure; result = dns_rdatalist_tordataset(msgrdl, msgrds); INSIST(result == ISC_R_SUCCESS); ISC_LIST_APPEND(msgname->list, msgrds, link); dns_message_addname(msg, msgname, DNS_SECTION_ANSWER); msgname = NULL; result = xfr->stream->methods->next(xfr->stream); if (result == ISC_R_NOMORE) { xfr->end_of_stream = ISC_TRUE; break; } CHECK(result); if (! xfr->many_answers) break; /* * At this stage, at least 1 RR has been rendered into * the message. Check if we want to clamp this message * here (TCP only). */ if ((isc_buffer_usedlength(&xfr->buf) >= ns_g_server->transfer_tcp_message_size) && is_tcp) break; } if (is_tcp) { CHECK(dns_compress_init(&cctx, -1, xfr->mctx)); dns_compress_setsensitive(&cctx, ISC_TRUE); cleanup_cctx = ISC_TRUE; CHECK(dns_message_renderbegin(msg, &cctx, &xfr->txbuf)); CHECK(dns_message_rendersection(msg, DNS_SECTION_QUESTION, 0)); CHECK(dns_message_rendersection(msg, DNS_SECTION_ANSWER, 0)); CHECK(dns_message_renderend(msg)); dns_compress_invalidate(&cctx); cleanup_cctx = ISC_FALSE; isc_buffer_usedregion(&xfr->txbuf, &used); isc_buffer_putuint16(&xfr->txlenbuf, (isc_uint16_t)used.length); region.base = xfr->txlenbuf.base; region.length = 2 + used.length; xfrout_log(xfr, ISC_LOG_DEBUG(8), "sending TCP message of %d bytes", used.length); CHECK(isc_socket_send(xfr->client->tcpsocket, /* XXX */ ®ion, xfr->client->task, xfrout_senddone, xfr)); xfr->sends++; } else { xfrout_log(xfr, ISC_LOG_DEBUG(8), "sending IXFR UDP response"); ns_client_send(xfr->client); xfr->stream->methods->pause(xfr->stream); xfrout_ctx_destroy(&xfr); return; } /* Advance lasttsig to be the last TSIG generated */ CHECK(dns_message_getquerytsig(msg, xfr->mctx, &xfr->lasttsig)); xfr->nmsg++; failure: if (msgname != NULL) { if (msgrds != NULL) { if (dns_rdataset_isassociated(msgrds)) dns_rdataset_disassociate(msgrds); dns_message_puttemprdataset(msg, &msgrds); } if (msgrdl != NULL) { ISC_LIST_UNLINK(msgrdl->rdata, msgrdata, link); dns_message_puttemprdatalist(msg, &msgrdl); } if (msgrdata != NULL) dns_message_puttemprdata(msg, &msgrdata); dns_message_puttempname(msg, &msgname); } if (tcpmsg != NULL) dns_message_destroy(&tcpmsg); if (cleanup_cctx) dns_compress_invalidate(&cctx); /* * Make sure to release any locks held by database * iterators before returning from the event handler. */ xfr->stream->methods->pause(xfr->stream); if (result == ISC_R_SUCCESS) return; xfrout_fail(xfr, result, "sending zone data"); } static void xfrout_ctx_destroy(xfrout_ctx_t **xfrp) { xfrout_ctx_t *xfr = *xfrp; ns_client_t *client = NULL; INSIST(xfr->sends == 0); xfr->client->shutdown = NULL; xfr->client->shutdown_arg = NULL; if (xfr->stream != NULL) xfr->stream->methods->destroy(&xfr->stream); if (xfr->buf.base != NULL) isc_mem_put(xfr->mctx, xfr->buf.base, xfr->buf.length); if (xfr->txmem != NULL) isc_mem_put(xfr->mctx, xfr->txmem, xfr->txmemlen); if (xfr->lasttsig != NULL) isc_buffer_free(&xfr->lasttsig); if (xfr->quota != NULL) isc_quota_detach(&xfr->quota); if (xfr->ver != NULL) dns_db_closeversion(xfr->db, &xfr->ver, ISC_FALSE); if (xfr->zone != NULL) dns_zone_detach(&xfr->zone); if (xfr->db != NULL) dns_db_detach(&xfr->db); /* * We want to detch the client after we have released the memory * context as ns_client_detach checks the memory reference count. */ ns_client_attach(xfr->client, &client); ns_client_detach(&xfr->client); isc_mem_putanddetach(&xfr->mctx, xfr, sizeof(*xfr)); ns_client_detach(&client); *xfrp = NULL; } static void xfrout_senddone(isc_task_t *task, isc_event_t *event) { isc_socketevent_t *sev = (isc_socketevent_t *)event; xfrout_ctx_t *xfr = (xfrout_ctx_t *)event->ev_arg; isc_result_t evresult = sev->result; UNUSED(task); INSIST(event->ev_type == ISC_SOCKEVENT_SENDDONE); isc_event_free(&event); xfr->sends--; INSIST(xfr->sends == 0); (void)isc_timer_touch(xfr->client->timer); if (xfr->shuttingdown == ISC_TRUE) { xfrout_maybe_destroy(xfr); } else if (evresult != ISC_R_SUCCESS) { xfrout_fail(xfr, evresult, "send"); } else if (xfr->end_of_stream == ISC_FALSE) { sendstream(xfr); } else { /* End of zone transfer stream. */ inc_stats(xfr->zone, dns_nsstatscounter_xfrdone); xfrout_log(xfr, ISC_LOG_INFO, "%s ended", xfr->mnemonic); ns_client_next(xfr->client, ISC_R_SUCCESS); xfrout_ctx_destroy(&xfr); } } static void xfrout_fail(xfrout_ctx_t *xfr, isc_result_t result, const char *msg) { xfr->shuttingdown = ISC_TRUE; xfrout_log(xfr, ISC_LOG_ERROR, "%s: %s", msg, isc_result_totext(result)); xfrout_maybe_destroy(xfr); } static void xfrout_maybe_destroy(xfrout_ctx_t *xfr) { INSIST(xfr->shuttingdown == ISC_TRUE); if (xfr->sends > 0) { /* * If we are currently sending, cancel it and wait for * cancel event before destroying the context. */ isc_socket_cancel(xfr->client->tcpsocket, xfr->client->task, ISC_SOCKCANCEL_SEND); } else { ns_client_next(xfr->client, ISC_R_CANCELED); xfrout_ctx_destroy(&xfr); } } static void xfrout_client_shutdown(void *arg, isc_result_t result) { xfrout_ctx_t *xfr = (xfrout_ctx_t *) arg; xfrout_fail(xfr, result, "aborted"); } /* * Log outgoing zone transfer messages in a format like * : transfer of : */ static void xfrout_logv(ns_client_t *client, dns_name_t *zonename, dns_rdataclass_t rdclass, int level, const char *fmt, va_list ap) ISC_FORMAT_PRINTF(5, 0); static void xfrout_logv(ns_client_t *client, dns_name_t *zonename, dns_rdataclass_t rdclass, int level, const char *fmt, va_list ap) { char msgbuf[2048]; char namebuf[DNS_NAME_FORMATSIZE]; char classbuf[DNS_RDATACLASS_FORMATSIZE]; dns_name_format(zonename, namebuf, sizeof(namebuf)); dns_rdataclass_format(rdclass, classbuf, sizeof(classbuf)); vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap); ns_client_log(client, DNS_LOGCATEGORY_XFER_OUT, NS_LOGMODULE_XFER_OUT, level, "transfer of '%s/%s': %s", namebuf, classbuf, msgbuf); } /* * Logging function for use when a xfrout_ctx_t has not yet been created. */ static void xfrout_log1(ns_client_t *client, dns_name_t *zonename, dns_rdataclass_t rdclass, int level, const char *fmt, ...) { va_list ap; va_start(ap, fmt); xfrout_logv(client, zonename, rdclass, level, fmt, ap); va_end(ap); } /* * Logging function for use when there is a xfrout_ctx_t. */ static void xfrout_log(xfrout_ctx_t *xfr, int level, const char *fmt, ...) { va_list ap; va_start(ap, fmt); xfrout_logv(xfr->client, xfr->qname, xfr->qclass, level, fmt, ap); va_end(ap); } bind9-9.11.3+dfsg/bin/named/zoneconf.c000066400000000000000000001463221325250447100173650ustar00rootroot00000000000000/* * Copyright (C) 1999-2018 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include #include #include #include #include #include #include /* Required for HP/UX (and others?) */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* ACLs associated with zone */ typedef enum { allow_notify, allow_query, allow_query_on, allow_transfer, allow_update, allow_update_forwarding } acl_type_t; #define RETERR(x) do { \ isc_result_t _r = (x); \ if (_r != ISC_R_SUCCESS) \ return (_r); \ } while (0) #define CHECK(x) do { \ result = (x); \ if (result != ISC_R_SUCCESS) \ goto cleanup; \ } while (0) /*% * Convenience function for configuring a single zone ACL. */ static isc_result_t configure_zone_acl(const cfg_obj_t *zconfig, const cfg_obj_t *vconfig, const cfg_obj_t *config, acl_type_t acltype, cfg_aclconfctx_t *actx, dns_zone_t *zone, void (*setzacl)(dns_zone_t *, dns_acl_t *), void (*clearzacl)(dns_zone_t *)) { isc_result_t result; const cfg_obj_t *maps[5] = {NULL, NULL, NULL, NULL, NULL}; const cfg_obj_t *aclobj = NULL; int i = 0; dns_acl_t **aclp = NULL, *acl = NULL; const char *aclname; dns_view_t *view; view = dns_zone_getview(zone); switch (acltype) { case allow_notify: if (view != NULL) aclp = &view->notifyacl; aclname = "allow-notify"; break; case allow_query: if (view != NULL) aclp = &view->queryacl; aclname = "allow-query"; break; case allow_query_on: if (view != NULL) aclp = &view->queryonacl; aclname = "allow-query-on"; break; case allow_transfer: if (view != NULL) aclp = &view->transferacl; aclname = "allow-transfer"; break; case allow_update: if (view != NULL) aclp = &view->updateacl; aclname = "allow-update"; break; case allow_update_forwarding: if (view != NULL) aclp = &view->upfwdacl; aclname = "allow-update-forwarding"; break; default: INSIST(0); return (ISC_R_FAILURE); } /* First check to see if ACL is defined within the zone */ if (zconfig != NULL) { maps[0] = cfg_tuple_get(zconfig, "options"); (void)ns_config_get(maps, aclname, &aclobj); if (aclobj != NULL) { aclp = NULL; goto parse_acl; } } /* Failing that, see if there's a default ACL already in the view */ if (aclp != NULL && *aclp != NULL) { (*setzacl)(zone, *aclp); return (ISC_R_SUCCESS); } /* Check for default ACLs that haven't been parsed yet */ if (vconfig != NULL) { const cfg_obj_t *options = cfg_tuple_get(vconfig, "options"); if (options != NULL) maps[i++] = options; } if (config != NULL) { const cfg_obj_t *options = NULL; (void)cfg_map_get(config, "options", &options); if (options != NULL) maps[i++] = options; } maps[i++] = ns_g_defaults; maps[i] = NULL; (void)ns_config_get(maps, aclname, &aclobj); if (aclobj == NULL) { (*clearzacl)(zone); return (ISC_R_SUCCESS); } parse_acl: result = cfg_acl_fromconfig(aclobj, config, ns_g_lctx, actx, dns_zone_getmctx(zone), 0, &acl); if (result != ISC_R_SUCCESS) return (result); (*setzacl)(zone, acl); /* Set the view default now */ if (aclp != NULL) dns_acl_attach(acl, aclp); dns_acl_detach(&acl); return (ISC_R_SUCCESS); } /*% * Parse the zone update-policy statement. */ static isc_result_t configure_zone_ssutable(const cfg_obj_t *zconfig, dns_zone_t *zone, const char *zname) { const cfg_obj_t *updatepolicy = NULL; const cfg_listelt_t *element, *element2; dns_ssutable_t *table = NULL; isc_mem_t *mctx = dns_zone_getmctx(zone); isc_boolean_t autoddns = ISC_FALSE; isc_result_t result; (void)cfg_map_get(zconfig, "update-policy", &updatepolicy); if (updatepolicy == NULL) { dns_zone_setssutable(zone, NULL); return (ISC_R_SUCCESS); } if (cfg_obj_isstring(updatepolicy) && strcmp("local", cfg_obj_asstring(updatepolicy)) == 0) { autoddns = ISC_TRUE; updatepolicy = NULL; } result = dns_ssutable_create(mctx, &table); if (result != ISC_R_SUCCESS) return (result); for (element = cfg_list_first(updatepolicy); element != NULL; element = cfg_list_next(element)) { const cfg_obj_t *stmt = cfg_listelt_value(element); const cfg_obj_t *mode = cfg_tuple_get(stmt, "mode"); const cfg_obj_t *identity = cfg_tuple_get(stmt, "identity"); const cfg_obj_t *matchtype = cfg_tuple_get(stmt, "matchtype"); const cfg_obj_t *dname = cfg_tuple_get(stmt, "name"); const cfg_obj_t *typelist = cfg_tuple_get(stmt, "types"); const char *str; isc_boolean_t grant = ISC_FALSE; isc_boolean_t usezone = ISC_FALSE; dns_ssumatchtype_t mtype = DNS_SSUMATCHTYPE_NAME; dns_fixedname_t fname, fident; isc_buffer_t b; dns_rdatatype_t *types; unsigned int i, n; str = cfg_obj_asstring(mode); if (strcasecmp(str, "grant") == 0) grant = ISC_TRUE; else if (strcasecmp(str, "deny") == 0) grant = ISC_FALSE; else INSIST(0); str = cfg_obj_asstring(matchtype); CHECK(dns_ssu_mtypefromstring(str, &mtype)); if (mtype == dns_ssumatchtype_subdomain) { usezone = ISC_TRUE; } dns_fixedname_init(&fident); str = cfg_obj_asstring(identity); isc_buffer_constinit(&b, str, strlen(str)); isc_buffer_add(&b, strlen(str)); result = dns_name_fromtext(dns_fixedname_name(&fident), &b, dns_rootname, 0, NULL); if (result != ISC_R_SUCCESS) { cfg_obj_log(identity, ns_g_lctx, ISC_LOG_ERROR, "'%s' is not a valid name", str); goto cleanup; } dns_fixedname_init(&fname); if (usezone) { result = dns_name_copy(dns_zone_getorigin(zone), dns_fixedname_name(&fname), NULL); if (result != ISC_R_SUCCESS) { cfg_obj_log(identity, ns_g_lctx, ISC_LOG_ERROR, "error copying origin: %s", isc_result_totext(result)); goto cleanup; } } else { str = cfg_obj_asstring(dname); isc_buffer_constinit(&b, str, strlen(str)); isc_buffer_add(&b, strlen(str)); result = dns_name_fromtext(dns_fixedname_name(&fname), &b, dns_rootname, 0, NULL); if (result != ISC_R_SUCCESS) { cfg_obj_log(identity, ns_g_lctx, ISC_LOG_ERROR, "'%s' is not a valid name", str); goto cleanup; } } n = ns_config_listcount(typelist); if (n == 0) types = NULL; else { types = isc_mem_get(mctx, n * sizeof(dns_rdatatype_t)); if (types == NULL) { result = ISC_R_NOMEMORY; goto cleanup; } } i = 0; for (element2 = cfg_list_first(typelist); element2 != NULL; element2 = cfg_list_next(element2)) { const cfg_obj_t *typeobj; isc_textregion_t r; INSIST(i < n); typeobj = cfg_listelt_value(element2); str = cfg_obj_asstring(typeobj); DE_CONST(str, r.base); r.length = strlen(str); result = dns_rdatatype_fromtext(&types[i++], &r); if (result != ISC_R_SUCCESS) { cfg_obj_log(identity, ns_g_lctx, ISC_LOG_ERROR, "'%s' is not a valid type", str); isc_mem_put(mctx, types, n * sizeof(dns_rdatatype_t)); goto cleanup; } } INSIST(i == n); result = dns_ssutable_addrule(table, grant, dns_fixedname_name(&fident), mtype, dns_fixedname_name(&fname), n, types); if (types != NULL) isc_mem_put(mctx, types, n * sizeof(dns_rdatatype_t)); if (result != ISC_R_SUCCESS) { goto cleanup; } } /* * If "update-policy local;" and a session key exists, * then use the default policy, which is equivalent to: * update-policy { grant zonesub any; }; */ if (autoddns) { dns_rdatatype_t any = dns_rdatatype_any; if (ns_g_server->session_keyname == NULL) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, "failed to enable auto DDNS policy " "for zone %s: session key not found", zname); result = ISC_R_NOTFOUND; goto cleanup; } result = dns_ssutable_addrule(table, ISC_TRUE, ns_g_server->session_keyname, DNS_SSUMATCHTYPE_LOCAL, dns_zone_getorigin(zone), 1, &any); if (result != ISC_R_SUCCESS) goto cleanup; } result = ISC_R_SUCCESS; dns_zone_setssutable(zone, table); cleanup: dns_ssutable_detach(&table); return (result); } /* * This is the TTL used for internally generated RRsets for static-stub zones. * The value doesn't matter because the mapping is static, but needs to be * defined for the sake of implementation. */ #define STATICSTUB_SERVER_TTL 86400 /*% * Configure an apex NS with glues for a static-stub zone. * For example, for the zone named "example.com", the following RRs will be * added to the zone DB: * example.com. NS example.com. * example.com. A 192.0.2.1 * example.com. AAAA 2001:db8::1 */ static isc_result_t configure_staticstub_serveraddrs(const cfg_obj_t *zconfig, dns_zone_t *zone, dns_rdatalist_t *rdatalist_ns, dns_rdatalist_t *rdatalist_a, dns_rdatalist_t *rdatalist_aaaa) { const cfg_listelt_t *element; isc_mem_t *mctx = dns_zone_getmctx(zone); isc_region_t region, sregion; dns_rdata_t *rdata; isc_result_t result = ISC_R_SUCCESS; for (element = cfg_list_first(zconfig); element != NULL; element = cfg_list_next(element)) { const isc_sockaddr_t* sa; isc_netaddr_t na; const cfg_obj_t *address = cfg_listelt_value(element); dns_rdatalist_t *rdatalist; sa = cfg_obj_assockaddr(address); if (isc_sockaddr_getport(sa) != 0) { cfg_obj_log(zconfig, ns_g_lctx, ISC_LOG_ERROR, "port is not configurable for " "static stub server-addresses"); return (ISC_R_FAILURE); } isc_netaddr_fromsockaddr(&na, sa); if (isc_netaddr_getzone(&na) != 0) { cfg_obj_log(zconfig, ns_g_lctx, ISC_LOG_ERROR, "scoped address is not allowed " "for static stub " "server-addresses"); return (ISC_R_FAILURE); } switch (na.family) { case AF_INET: region.length = sizeof(na.type.in); rdatalist = rdatalist_a; break; default: INSIST(na.family == AF_INET6); region.length = sizeof(na.type.in6); rdatalist = rdatalist_aaaa; break; } rdata = isc_mem_get(mctx, sizeof(*rdata) + region.length); if (rdata == NULL) return (ISC_R_NOMEMORY); region.base = (unsigned char *)(rdata + 1); memmove(region.base, &na.type, region.length); dns_rdata_init(rdata); dns_rdata_fromregion(rdata, dns_zone_getclass(zone), rdatalist->type, ®ion); ISC_LIST_APPEND(rdatalist->rdata, rdata, link); } /* * If no address is specified (unlikely in this context, but possible), * there's nothing to do anymore. */ if (ISC_LIST_EMPTY(rdatalist_a->rdata) && ISC_LIST_EMPTY(rdatalist_aaaa->rdata)) { return (ISC_R_SUCCESS); } /* Add to the list an apex NS with the ns name being the origin name */ dns_name_toregion(dns_zone_getorigin(zone), &sregion); rdata = isc_mem_get(mctx, sizeof(*rdata) + sregion.length); if (rdata == NULL) { /* * Already allocated data will be freed in the caller, so * we can simply return here. */ return (ISC_R_NOMEMORY); } region.length = sregion.length; region.base = (unsigned char *)(rdata + 1); memmove(region.base, sregion.base, region.length); dns_rdata_init(rdata); dns_rdata_fromregion(rdata, dns_zone_getclass(zone), dns_rdatatype_ns, ®ion); ISC_LIST_APPEND(rdatalist_ns->rdata, rdata, link); return (result); } /*% * Configure an apex NS with an out-of-zone NS names for a static-stub zone. * For example, for the zone named "example.com", something like the following * RRs will be added to the zone DB: * example.com. NS ns.example.net. */ static isc_result_t configure_staticstub_servernames(const cfg_obj_t *zconfig, dns_zone_t *zone, dns_rdatalist_t *rdatalist, const char *zname) { const cfg_listelt_t *element; isc_mem_t *mctx = dns_zone_getmctx(zone); dns_rdata_t *rdata; isc_region_t sregion, region; isc_result_t result = ISC_R_SUCCESS; for (element = cfg_list_first(zconfig); element != NULL; element = cfg_list_next(element)) { const cfg_obj_t *obj; const char *str; dns_fixedname_t fixed_name; dns_name_t *nsname; isc_buffer_t b; obj = cfg_listelt_value(element); str = cfg_obj_asstring(obj); dns_fixedname_init(&fixed_name); nsname = dns_fixedname_name(&fixed_name); isc_buffer_constinit(&b, str, strlen(str)); isc_buffer_add(&b, strlen(str)); result = dns_name_fromtext(nsname, &b, dns_rootname, 0, NULL); if (result != ISC_R_SUCCESS) { cfg_obj_log(zconfig, ns_g_lctx, ISC_LOG_ERROR, "server-name '%s' is not a valid " "name", str); return (result); } if (dns_name_issubdomain(nsname, dns_zone_getorigin(zone))) { cfg_obj_log(zconfig, ns_g_lctx, ISC_LOG_ERROR, "server-name '%s' must not be a " "subdomain of zone name '%s'", str, zname); return (ISC_R_FAILURE); } dns_name_toregion(nsname, &sregion); rdata = isc_mem_get(mctx, sizeof(*rdata) + sregion.length); if (rdata == NULL) return (ISC_R_NOMEMORY); region.length = sregion.length; region.base = (unsigned char *)(rdata + 1); memmove(region.base, sregion.base, region.length); dns_rdata_init(rdata); dns_rdata_fromregion(rdata, dns_zone_getclass(zone), dns_rdatatype_ns, ®ion); ISC_LIST_APPEND(rdatalist->rdata, rdata, link); } return (result); } /*% * Configure static-stub zone. */ static isc_result_t configure_staticstub(const cfg_obj_t *zconfig, dns_zone_t *zone, const char *zname, const char *dbtype) { int i = 0; const cfg_obj_t *obj; isc_mem_t *mctx = dns_zone_getmctx(zone); dns_db_t *db = NULL; dns_dbversion_t *dbversion = NULL; dns_dbnode_t *apexnode = NULL; dns_name_t apexname; isc_result_t result; dns_rdataset_t rdataset; dns_rdatalist_t rdatalist_ns, rdatalist_a, rdatalist_aaaa; dns_rdatalist_t* rdatalists[] = { &rdatalist_ns, &rdatalist_a, &rdatalist_aaaa, NULL }; dns_rdata_t *rdata; isc_region_t region; /* Create the DB beforehand */ RETERR(dns_db_create(mctx, dbtype, dns_zone_getorigin(zone), dns_dbtype_stub, dns_zone_getclass(zone), 0, NULL, &db)); dns_zone_setdb(zone, db); dns_rdatalist_init(&rdatalist_ns); rdatalist_ns.rdclass = dns_zone_getclass(zone); rdatalist_ns.type = dns_rdatatype_ns; rdatalist_ns.ttl = STATICSTUB_SERVER_TTL; dns_rdatalist_init(&rdatalist_a); rdatalist_a.rdclass = dns_zone_getclass(zone); rdatalist_a.type = dns_rdatatype_a; rdatalist_a.ttl = STATICSTUB_SERVER_TTL; dns_rdatalist_init(&rdatalist_aaaa); rdatalist_aaaa.rdclass = dns_zone_getclass(zone); rdatalist_aaaa.type = dns_rdatatype_aaaa; rdatalist_aaaa.ttl = STATICSTUB_SERVER_TTL; /* Prepare zone RRs from the configuration */ obj = NULL; result = cfg_map_get(zconfig, "server-addresses", &obj); if (result == ISC_R_SUCCESS) { INSIST(obj != NULL); result = configure_staticstub_serveraddrs(obj, zone, &rdatalist_ns, &rdatalist_a, &rdatalist_aaaa); if (result != ISC_R_SUCCESS) goto cleanup; } obj = NULL; result = cfg_map_get(zconfig, "server-names", &obj); if (result == ISC_R_SUCCESS) { INSIST(obj != NULL); result = configure_staticstub_servernames(obj, zone, &rdatalist_ns, zname); if (result != ISC_R_SUCCESS) goto cleanup; } /* * Sanity check: there should be at least one NS RR at the zone apex * to trigger delegation. */ if (ISC_LIST_EMPTY(rdatalist_ns.rdata)) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, "No NS record is configured for a " "static-stub zone '%s'", zname); result = ISC_R_FAILURE; goto cleanup; } /* * Now add NS and glue A/AAAA RRsets to the zone DB. * First open a new version for the add operation and get a pointer * to the apex node (all RRs are of the apex name). */ result = dns_db_newversion(db, &dbversion); if (result != ISC_R_SUCCESS) goto cleanup; dns_name_init(&apexname, NULL); dns_name_clone(dns_zone_getorigin(zone), &apexname); result = dns_db_findnode(db, &apexname, ISC_FALSE, &apexnode); if (result != ISC_R_SUCCESS) goto cleanup; /* Add NS RRset */ dns_rdataset_init(&rdataset); RUNTIME_CHECK(dns_rdatalist_tordataset(&rdatalist_ns, &rdataset) == ISC_R_SUCCESS); result = dns_db_addrdataset(db, apexnode, dbversion, 0, &rdataset, 0, NULL); dns_rdataset_disassociate(&rdataset); if (result != ISC_R_SUCCESS) goto cleanup; /* Add glue A RRset, if any */ if (!ISC_LIST_EMPTY(rdatalist_a.rdata)) { RUNTIME_CHECK(dns_rdatalist_tordataset(&rdatalist_a, &rdataset) == ISC_R_SUCCESS); result = dns_db_addrdataset(db, apexnode, dbversion, 0, &rdataset, 0, NULL); dns_rdataset_disassociate(&rdataset); if (result != ISC_R_SUCCESS) goto cleanup; } /* Add glue AAAA RRset, if any */ if (!ISC_LIST_EMPTY(rdatalist_aaaa.rdata)) { RUNTIME_CHECK(dns_rdatalist_tordataset(&rdatalist_aaaa, &rdataset) == ISC_R_SUCCESS); result = dns_db_addrdataset(db, apexnode, dbversion, 0, &rdataset, 0, NULL); dns_rdataset_disassociate(&rdataset); if (result != ISC_R_SUCCESS) goto cleanup; } result = ISC_R_SUCCESS; cleanup: if (apexnode != NULL) dns_db_detachnode(db, &apexnode); if (dbversion != NULL) dns_db_closeversion(db, &dbversion, ISC_TRUE); if (db != NULL) dns_db_detach(&db); for (i = 0; rdatalists[i] != NULL; i++) { while ((rdata = ISC_LIST_HEAD(rdatalists[i]->rdata)) != NULL) { ISC_LIST_UNLINK(rdatalists[i]->rdata, rdata, link); dns_rdata_toregion(rdata, ®ion); isc_mem_put(mctx, rdata, sizeof(*rdata) + region.length); } } INSIST(dbversion == NULL); return (result); } /*% * Convert a config file zone type into a server zone type. */ static inline dns_zonetype_t zonetype_fromconfig(const cfg_obj_t *map) { const cfg_obj_t *obj = NULL; isc_result_t result; result = cfg_map_get(map, "type", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); return (ns_config_getzonetype(obj)); } /*% * Helper function for strtoargv(). Pardon the gratuitous recursion. */ static isc_result_t strtoargvsub(isc_mem_t *mctx, char *s, unsigned int *argcp, char ***argvp, unsigned int n) { isc_result_t result; /* Discard leading whitespace. */ while (*s == ' ' || *s == '\t') s++; if (*s == '\0') { /* We have reached the end of the string. */ *argcp = n; *argvp = isc_mem_get(mctx, n * sizeof(char *)); if (*argvp == NULL) return (ISC_R_NOMEMORY); } else { char *p = s; while (*p != ' ' && *p != '\t' && *p != '\0') p++; if (*p != '\0') *p++ = '\0'; result = strtoargvsub(mctx, p, argcp, argvp, n + 1); if (result != ISC_R_SUCCESS) return (result); (*argvp)[n] = s; } return (ISC_R_SUCCESS); } /*% * Tokenize the string "s" into whitespace-separated words, * return the number of words in '*argcp' and an array * of pointers to the words in '*argvp'. The caller * must free the array using isc_mem_put(). The string * is modified in-place. */ static isc_result_t strtoargv(isc_mem_t *mctx, char *s, unsigned int *argcp, char ***argvp) { return (strtoargvsub(mctx, s, argcp, argvp, 0)); } static void checknames(dns_zonetype_t ztype, const cfg_obj_t **maps, const cfg_obj_t **objp) { const char *zone = NULL; isc_result_t result; switch (ztype) { case dns_zone_slave: zone = "slave"; break; case dns_zone_master: zone = "master"; break; default: INSIST(0); } result = ns_checknames_get(maps, zone, objp); INSIST(result == ISC_R_SUCCESS && objp != NULL && *objp != NULL); } isc_result_t ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, const cfg_obj_t *zconfig, cfg_aclconfctx_t *ac, dns_zone_t *zone, dns_zone_t *raw) { isc_result_t result; const char *zname; dns_rdataclass_t zclass; dns_rdataclass_t vclass; const cfg_obj_t *maps[5]; const cfg_obj_t *nodefault[4]; const cfg_obj_t *zoptions = NULL; const cfg_obj_t *options = NULL; const cfg_obj_t *obj; const char *filename = NULL; const char *dupcheck; dns_notifytype_t notifytype = dns_notifytype_yes; isc_uint32_t count; unsigned int dbargc; char **dbargv; static char default_dbtype[] = "rbt"; static char dlz_dbtype[] = "dlz"; char *cpval = default_dbtype; isc_mem_t *mctx = dns_zone_getmctx(zone); dns_dialuptype_t dialup = dns_dialuptype_no; dns_zonetype_t ztype; int i; isc_int32_t journal_size; isc_boolean_t multi; isc_boolean_t alt; dns_view_t *view; isc_boolean_t check = ISC_FALSE, fail = ISC_FALSE; isc_boolean_t warn = ISC_FALSE, ignore = ISC_FALSE; isc_boolean_t ixfrdiff; dns_masterformat_t masterformat; const dns_master_style_t *masterstyle = &dns_master_style_default; isc_stats_t *zoneqrystats; dns_stats_t *rcvquerystats; dns_zonestat_level_t statlevel; int seconds; dns_zone_t *mayberaw = (raw != NULL) ? raw : zone; isc_dscp_t dscp; i = 0; if (zconfig != NULL) { zoptions = cfg_tuple_get(zconfig, "options"); nodefault[i] = maps[i] = zoptions; i++; } if (vconfig != NULL) { nodefault[i] = maps[i] = cfg_tuple_get(vconfig, "options"); i++; } if (config != NULL) { (void)cfg_map_get(config, "options", &options); if (options != NULL) { nodefault[i] = maps[i] = options; i++; } } nodefault[i] = NULL; maps[i++] = ns_g_defaults; maps[i] = NULL; if (vconfig != NULL) RETERR(ns_config_getclass(cfg_tuple_get(vconfig, "class"), dns_rdataclass_in, &vclass)); else vclass = dns_rdataclass_in; /* * Configure values common to all zone types. */ zname = cfg_obj_asstring(cfg_tuple_get(zconfig, "name")); RETERR(ns_config_getclass(cfg_tuple_get(zconfig, "class"), vclass, &zclass)); dns_zone_setclass(zone, zclass); if (raw != NULL) dns_zone_setclass(raw, zclass); ztype = zonetype_fromconfig(zoptions); if (raw != NULL) { dns_zone_settype(raw, ztype); dns_zone_settype(zone, dns_zone_master); } else dns_zone_settype(zone, ztype); obj = NULL; result = cfg_map_get(zoptions, "database", &obj); if (result == ISC_R_SUCCESS) cpval = isc_mem_strdup(mctx, cfg_obj_asstring(obj)); if (cpval == NULL) return(ISC_R_NOMEMORY); obj = NULL; result = cfg_map_get(zoptions, "dlz", &obj); if (result == ISC_R_SUCCESS) { const char *dlzname = cfg_obj_asstring(obj); size_t len; if (cpval != default_dbtype) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, "zone '%s': both 'database' and 'dlz' " "specified", zname); return (ISC_R_FAILURE); } len = strlen(dlzname) + 5; cpval = isc_mem_allocate(mctx, len); if (cpval == NULL) return (ISC_R_NOMEMORY); snprintf(cpval, len, "dlz %s", dlzname); } result = strtoargv(mctx, cpval, &dbargc, &dbargv); if (result != ISC_R_SUCCESS && cpval != default_dbtype) { isc_mem_free(mctx, cpval); return (result); } /* * ANSI C is strange here. There is no logical reason why (char **) * cannot be promoted automatically to (const char * const *) by the * compiler w/o generating a warning. */ result = dns_zone_setdbtype(zone, dbargc, (const char * const *)dbargv); isc_mem_put(mctx, dbargv, dbargc * sizeof(*dbargv)); if (cpval != default_dbtype && cpval != dlz_dbtype) isc_mem_free(mctx, cpval); if (result != ISC_R_SUCCESS) return (result); obj = NULL; result = cfg_map_get(zoptions, "file", &obj); if (result == ISC_R_SUCCESS) filename = cfg_obj_asstring(obj); /* * Unless we're using some alternative database, a master zone * will be needing a master file. */ if (ztype == dns_zone_master && cpval == default_dbtype && filename == NULL) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, "zone '%s': 'file' not specified", zname); return (ISC_R_FAILURE); } if (ztype == dns_zone_slave) masterformat = dns_masterformat_raw; else masterformat = dns_masterformat_text; obj = NULL; result = ns_config_get(maps, "masterfile-format", &obj); if (result == ISC_R_SUCCESS) { const char *masterformatstr = cfg_obj_asstring(obj); if (strcasecmp(masterformatstr, "text") == 0) masterformat = dns_masterformat_text; else if (strcasecmp(masterformatstr, "raw") == 0) masterformat = dns_masterformat_raw; else if (strcasecmp(masterformatstr, "map") == 0) masterformat = dns_masterformat_map; else INSIST(0); } obj = NULL; result = ns_config_get(maps, "masterfile-style", &obj); if (result == ISC_R_SUCCESS) { const char *masterstylestr = cfg_obj_asstring(obj); if (masterformat != dns_masterformat_text) { cfg_obj_log(obj, ns_g_lctx, ISC_LOG_ERROR, "zone '%s': 'masterfile-style' " "can only be used with " "'masterfile-format text'", zname); return (ISC_R_FAILURE); } if (strcasecmp(masterstylestr, "full") == 0) masterstyle = &dns_master_style_full; else if (strcasecmp(masterstylestr, "relative") == 0) masterstyle = &dns_master_style_default; else INSIST(0); } obj = NULL; result = ns_config_get(maps, "max-zone-ttl", &obj); if (result == ISC_R_SUCCESS && masterformat == dns_masterformat_map) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, "zone '%s': 'max-zone-ttl' is not compatible " "with 'masterfile-format map'", zname); return (ISC_R_FAILURE); } else if (result == ISC_R_SUCCESS) { dns_ttl_t maxttl = 0; /* unlimited */ if (cfg_obj_isuint32(obj)) maxttl = cfg_obj_asuint32(obj); dns_zone_setmaxttl(zone, maxttl); if (raw != NULL) dns_zone_setmaxttl(raw, maxttl); } obj = NULL; result = ns_config_get(maps, "max-records", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); dns_zone_setmaxrecords(mayberaw, cfg_obj_asuint32(obj)); if (zone != mayberaw) dns_zone_setmaxrecords(zone, 0); if (raw != NULL && filename != NULL) { #define SIGNED ".signed" size_t signedlen = strlen(filename) + sizeof(SIGNED); char *signedname; RETERR(dns_zone_setfile3(raw, filename, masterformat, masterstyle)); signedname = isc_mem_get(mctx, signedlen); if (signedname == NULL) return (ISC_R_NOMEMORY); (void)snprintf(signedname, signedlen, "%s" SIGNED, filename); result = dns_zone_setfile3(zone, signedname, dns_masterformat_raw, NULL); isc_mem_put(mctx, signedname, signedlen); if (result != ISC_R_SUCCESS) return (result); } else RETERR(dns_zone_setfile3(zone, filename, masterformat, masterstyle)); obj = NULL; result = cfg_map_get(zoptions, "journal", &obj); if (result == ISC_R_SUCCESS) RETERR(dns_zone_setjournal(mayberaw, cfg_obj_asstring(obj))); /* * Notify messages are processed by the raw zone if it exists. */ if (ztype == dns_zone_slave) RETERR(configure_zone_acl(zconfig, vconfig, config, allow_notify, ac, mayberaw, dns_zone_setnotifyacl, dns_zone_clearnotifyacl)); /* * XXXAG This probably does not make sense for stubs. */ RETERR(configure_zone_acl(zconfig, vconfig, config, allow_query, ac, zone, dns_zone_setqueryacl, dns_zone_clearqueryacl)); RETERR(configure_zone_acl(zconfig, vconfig, config, allow_query_on, ac, zone, dns_zone_setqueryonacl, dns_zone_clearqueryonacl)); obj = NULL; result = ns_config_get(maps, "dialup", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); if (cfg_obj_isboolean(obj)) { if (cfg_obj_asboolean(obj)) dialup = dns_dialuptype_yes; else dialup = dns_dialuptype_no; } else { const char *dialupstr = cfg_obj_asstring(obj); if (strcasecmp(dialupstr, "notify") == 0) dialup = dns_dialuptype_notify; else if (strcasecmp(dialupstr, "notify-passive") == 0) dialup = dns_dialuptype_notifypassive; else if (strcasecmp(dialupstr, "refresh") == 0) dialup = dns_dialuptype_refresh; else if (strcasecmp(dialupstr, "passive") == 0) dialup = dns_dialuptype_passive; else INSIST(0); } if (raw != NULL) dns_zone_setdialup(raw, dialup); dns_zone_setdialup(zone, dialup); obj = NULL; result = ns_config_get(maps, "zone-statistics", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); if (cfg_obj_isboolean(obj)) { if (cfg_obj_asboolean(obj)) statlevel = dns_zonestat_full; else statlevel = dns_zonestat_none; } else { const char *levelstr = cfg_obj_asstring(obj); if (strcasecmp(levelstr, "full") == 0) statlevel = dns_zonestat_full; else if (strcasecmp(levelstr, "terse") == 0) statlevel = dns_zonestat_terse; else if (strcasecmp(levelstr, "none") == 0) statlevel = dns_zonestat_none; else INSIST(0); } dns_zone_setstatlevel(zone, statlevel); zoneqrystats = NULL; rcvquerystats = NULL; if (statlevel == dns_zonestat_full) { RETERR(isc_stats_create(mctx, &zoneqrystats, dns_nsstatscounter_max)); RETERR(dns_rdatatypestats_create(mctx, &rcvquerystats)); } dns_zone_setrequeststats(zone, zoneqrystats); dns_zone_setrcvquerystats(zone, rcvquerystats); if (zoneqrystats != NULL) isc_stats_detach(&zoneqrystats); if(rcvquerystats != NULL) dns_stats_detach(&rcvquerystats); /* * Configure master functionality. This applies * to primary masters (type "master") and slaves * acting as masters (type "slave"), but not to stubs. */ if (ztype != dns_zone_stub && ztype != dns_zone_staticstub && ztype != dns_zone_redirect) { obj = NULL; result = ns_config_get(maps, "notify", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); if (cfg_obj_isboolean(obj)) { if (cfg_obj_asboolean(obj)) notifytype = dns_notifytype_yes; else notifytype = dns_notifytype_no; } else { const char *notifystr = cfg_obj_asstring(obj); if (strcasecmp(notifystr, "explicit") == 0) notifytype = dns_notifytype_explicit; else if (strcasecmp(notifystr, "master-only") == 0) notifytype = dns_notifytype_masteronly; else INSIST(0); } if (raw != NULL) dns_zone_setnotifytype(raw, dns_notifytype_no); dns_zone_setnotifytype(zone, notifytype); obj = NULL; result = ns_config_get(maps, "also-notify", &obj); if (result == ISC_R_SUCCESS && (notifytype == dns_notifytype_yes || notifytype == dns_notifytype_explicit || (notifytype == dns_notifytype_masteronly && ztype == dns_zone_master))) { dns_ipkeylist_t ipkl; dns_ipkeylist_init(&ipkl); RETERR(ns_config_getipandkeylist(config, obj, mctx, &ipkl)); result = dns_zone_setalsonotifydscpkeys(zone, ipkl.addrs, ipkl.dscps, ipkl.keys, ipkl.count); dns_ipkeylist_clear(mctx, &ipkl); RETERR(result); } else RETERR(dns_zone_setalsonotify(zone, NULL, 0)); obj = NULL; result = ns_config_get(maps, "notify-source", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); RETERR(dns_zone_setnotifysrc4(zone, cfg_obj_assockaddr(obj))); dscp = cfg_obj_getdscp(obj); if (dscp == -1) dscp = ns_g_dscp; RETERR(dns_zone_setnotifysrc4dscp(zone, dscp)); ns_add_reserved_dispatch(ns_g_server, cfg_obj_assockaddr(obj)); obj = NULL; result = ns_config_get(maps, "notify-source-v6", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); RETERR(dns_zone_setnotifysrc6(zone, cfg_obj_assockaddr(obj))); dscp = cfg_obj_getdscp(obj); if (dscp == -1) dscp = ns_g_dscp; RETERR(dns_zone_setnotifysrc6dscp(zone, dscp)); ns_add_reserved_dispatch(ns_g_server, cfg_obj_assockaddr(obj)); obj = NULL; result = ns_config_get(maps, "notify-to-soa", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); dns_zone_setoption(zone, DNS_ZONEOPT_NOTIFYTOSOA, cfg_obj_asboolean(obj)); dns_zone_setisself(zone, ns_client_isself, NULL); RETERR(configure_zone_acl(zconfig, vconfig, config, allow_transfer, ac, zone, dns_zone_setxfracl, dns_zone_clearxfracl)); obj = NULL; result = ns_config_get(maps, "max-transfer-time-out", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); dns_zone_setmaxxfrout(zone, cfg_obj_asuint32(obj) * 60); obj = NULL; result = ns_config_get(maps, "max-transfer-idle-out", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); dns_zone_setidleout(zone, cfg_obj_asuint32(obj) * 60); obj = NULL; result = ns_config_get(maps, "max-journal-size", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); if (raw != NULL) dns_zone_setjournalsize(raw, -1); dns_zone_setjournalsize(zone, -1); if (cfg_obj_isstring(obj)) { const char *str = cfg_obj_asstring(obj); INSIST(strcasecmp(str, "unlimited") == 0); journal_size = ISC_UINT32_MAX / 2; } else { isc_resourcevalue_t value; value = cfg_obj_asuint64(obj); if (value > ISC_UINT32_MAX / 2) { cfg_obj_log(obj, ns_g_lctx, ISC_LOG_ERROR, "'max-journal-size " "%" ISC_PRINT_QUADFORMAT "d' " "is too large", value); RETERR(ISC_R_RANGE); } journal_size = (isc_uint32_t)value; } if (raw != NULL) dns_zone_setjournalsize(raw, journal_size); dns_zone_setjournalsize(zone, journal_size); obj = NULL; result = ns_config_get(maps, "ixfr-from-differences", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); if (cfg_obj_isboolean(obj)) ixfrdiff = cfg_obj_asboolean(obj); else if (!strcasecmp(cfg_obj_asstring(obj), "master") && ztype == dns_zone_master) ixfrdiff = ISC_TRUE; else if (!strcasecmp(cfg_obj_asstring(obj), "slave") && ztype == dns_zone_slave) ixfrdiff = ISC_TRUE; else ixfrdiff = ISC_FALSE; if (raw != NULL) { dns_zone_setoption(raw, DNS_ZONEOPT_IXFRFROMDIFFS, ISC_TRUE); dns_zone_setoption(zone, DNS_ZONEOPT_IXFRFROMDIFFS, ISC_TRUE); } else dns_zone_setoption(zone, DNS_ZONEOPT_IXFRFROMDIFFS, ixfrdiff); obj = NULL; result = ns_config_get(maps, "request-expire", &obj); INSIST(result == ISC_R_SUCCESS); dns_zone_setrequestexpire(zone, cfg_obj_asboolean(obj)); obj = NULL; result = ns_config_get(maps, "request-ixfr", &obj); INSIST(result == ISC_R_SUCCESS); dns_zone_setrequestixfr(zone, cfg_obj_asboolean(obj)); checknames(ztype, maps, &obj); INSIST(obj != NULL); if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) { fail = ISC_FALSE; check = ISC_TRUE; } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) { fail = check = ISC_TRUE; } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) { fail = check = ISC_FALSE; } else INSIST(0); if (raw != NULL) { dns_zone_setoption(raw, DNS_ZONEOPT_CHECKNAMES, check); dns_zone_setoption(raw, DNS_ZONEOPT_CHECKNAMESFAIL, fail); dns_zone_setoption(zone, DNS_ZONEOPT_CHECKNAMES, ISC_FALSE); dns_zone_setoption(zone, DNS_ZONEOPT_CHECKNAMESFAIL, ISC_FALSE); } else { dns_zone_setoption(zone, DNS_ZONEOPT_CHECKNAMES, check); dns_zone_setoption(zone, DNS_ZONEOPT_CHECKNAMESFAIL, fail); } obj = NULL; result = ns_config_get(maps, "notify-delay", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); dns_zone_setnotifydelay(zone, cfg_obj_asuint32(obj)); obj = NULL; result = ns_config_get(maps, "check-sibling", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); dns_zone_setoption(zone, DNS_ZONEOPT_CHECKSIBLING, cfg_obj_asboolean(obj)); obj = NULL; result = ns_config_get(maps, "check-spf", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) { check = ISC_TRUE; } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) { check = ISC_FALSE; } else INSIST(0); dns_zone_setoption(zone, DNS_ZONEOPT_CHECKSPF, check); obj = NULL; result = ns_config_get(maps, "zero-no-soa-ttl", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); dns_zone_setzeronosoattl(zone, cfg_obj_asboolean(obj)); obj = NULL; result = ns_config_get(maps, "nsec3-test-zone", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); dns_zone_setoption(zone, DNS_ZONEOPT_NSEC3TESTZONE, cfg_obj_asboolean(obj)); } else if (ztype == dns_zone_redirect) { dns_zone_setnotifytype(zone, dns_notifytype_no); obj = NULL; result = ns_config_get(maps, "max-journal-size", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); dns_zone_setjournalsize(zone, -1); if (cfg_obj_isstring(obj)) { const char *str = cfg_obj_asstring(obj); INSIST(strcasecmp(str, "unlimited") == 0); journal_size = ISC_UINT32_MAX / 2; } else { isc_resourcevalue_t value; value = cfg_obj_asuint64(obj); if (value > ISC_UINT32_MAX / 2) { cfg_obj_log(obj, ns_g_lctx, ISC_LOG_ERROR, "'max-journal-size " "%" ISC_PRINT_QUADFORMAT "d' " "is too large", value); RETERR(ISC_R_RANGE); } journal_size = (isc_uint32_t)value; } dns_zone_setjournalsize(zone, journal_size); } /* * Configure update-related options. These apply to * primary masters only. */ if (ztype == dns_zone_master) { dns_acl_t *updateacl; RETERR(configure_zone_acl(zconfig, vconfig, config, allow_update, ac, mayberaw, dns_zone_setupdateacl, dns_zone_clearupdateacl)); updateacl = dns_zone_getupdateacl(mayberaw); if (updateacl != NULL && dns_acl_isinsecure(updateacl)) isc_log_write(ns_g_lctx, DNS_LOGCATEGORY_SECURITY, NS_LOGMODULE_SERVER, ISC_LOG_WARNING, "zone '%s' allows unsigned updates " "from remote hosts, which is insecure", zname); RETERR(configure_zone_ssutable(zoptions, mayberaw, zname)); } if (ztype == dns_zone_master || raw != NULL) { isc_boolean_t allow = ISC_FALSE, maint = ISC_FALSE; obj = NULL; result = ns_config_get(maps, "sig-validity-interval", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); { const cfg_obj_t *validity, *resign; validity = cfg_tuple_get(obj, "validity"); seconds = cfg_obj_asuint32(validity) * 86400; dns_zone_setsigvalidityinterval(zone, seconds); resign = cfg_tuple_get(obj, "re-sign"); if (cfg_obj_isvoid(resign)) { seconds /= 4; } else { if (seconds > 7 * 86400) seconds = cfg_obj_asuint32(resign) * 86400; else seconds = cfg_obj_asuint32(resign) * 3600; } dns_zone_setsigresigninginterval(zone, seconds); } obj = NULL; result = ns_config_get(maps, "key-directory", &obj); if (result == ISC_R_SUCCESS) { filename = cfg_obj_asstring(obj); RETERR(dns_zone_setkeydirectory(zone, filename)); } obj = NULL; result = ns_config_get(maps, "sig-signing-signatures", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); dns_zone_setsignatures(zone, cfg_obj_asuint32(obj)); obj = NULL; result = ns_config_get(maps, "sig-signing-nodes", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); dns_zone_setnodes(zone, cfg_obj_asuint32(obj)); obj = NULL; result = ns_config_get(maps, "sig-signing-type", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); dns_zone_setprivatetype(zone, cfg_obj_asuint32(obj)); obj = NULL; result = ns_config_get(maps, "update-check-ksk", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); dns_zone_setoption(zone, DNS_ZONEOPT_UPDATECHECKKSK, cfg_obj_asboolean(obj)); obj = NULL; result = ns_config_get(maps, "dnssec-dnskey-kskonly", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); dns_zone_setoption(zone, DNS_ZONEOPT_DNSKEYKSKONLY, cfg_obj_asboolean(obj)); obj = NULL; result = ns_config_get(maps, "dnssec-loadkeys-interval", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); RETERR(dns_zone_setrefreshkeyinterval(zone, cfg_obj_asuint32(obj))); obj = NULL; result = cfg_map_get(zoptions, "auto-dnssec", &obj); if (result == ISC_R_SUCCESS) { const char *arg = cfg_obj_asstring(obj); if (strcasecmp(arg, "allow") == 0) allow = ISC_TRUE; else if (strcasecmp(arg, "maintain") == 0) allow = maint = ISC_TRUE; else if (strcasecmp(arg, "off") == 0) ; else INSIST(0); dns_zone_setkeyopt(zone, DNS_ZONEKEY_ALLOW, allow); dns_zone_setkeyopt(zone, DNS_ZONEKEY_MAINTAIN, maint); } } if (ztype == dns_zone_slave) { RETERR(configure_zone_acl(zconfig, vconfig, config, allow_update_forwarding, ac, mayberaw, dns_zone_setforwardacl, dns_zone_clearforwardacl)); } /*% * Primary master functionality. */ if (ztype == dns_zone_master) { obj = NULL; result = ns_config_get(maps, "check-wildcard", &obj); if (result == ISC_R_SUCCESS) check = cfg_obj_asboolean(obj); else check = ISC_FALSE; dns_zone_setoption(mayberaw, DNS_ZONEOPT_CHECKWILDCARD, check); /* * With map files, the default is ignore duplicate * records. With other master formats, the default is * taken from the global configuration. */ obj = NULL; if (masterformat != dns_masterformat_map) { result = ns_config_get(maps, "check-dup-records", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); dupcheck = cfg_obj_asstring(obj); } else { result = ns_config_get(nodefault, "check-dup-records", &obj); if (result == ISC_R_SUCCESS) dupcheck = cfg_obj_asstring(obj); else dupcheck = "ignore"; } if (strcasecmp(dupcheck, "warn") == 0) { fail = ISC_FALSE; check = ISC_TRUE; } else if (strcasecmp(dupcheck, "fail") == 0) { fail = check = ISC_TRUE; } else if (strcasecmp(dupcheck, "ignore") == 0) { fail = check = ISC_FALSE; } else INSIST(0); dns_zone_setoption(mayberaw, DNS_ZONEOPT_CHECKDUPRR, check); dns_zone_setoption(mayberaw, DNS_ZONEOPT_CHECKDUPRRFAIL, fail); obj = NULL; result = ns_config_get(maps, "check-mx", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) { fail = ISC_FALSE; check = ISC_TRUE; } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) { fail = check = ISC_TRUE; } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) { fail = check = ISC_FALSE; } else INSIST(0); dns_zone_setoption(mayberaw, DNS_ZONEOPT_CHECKMX, check); dns_zone_setoption(mayberaw, DNS_ZONEOPT_CHECKMXFAIL, fail); /* * With map files, the default is *not* to check * integrity. With other master formats, the default is * taken from the global configuration. */ obj = NULL; if (masterformat != dns_masterformat_map) { result = ns_config_get(maps, "check-integrity", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); dns_zone_setoption(mayberaw, DNS_ZONEOPT_CHECKINTEGRITY, cfg_obj_asboolean(obj)); } else { check = ISC_FALSE; result = ns_config_get(nodefault, "check-integrity", &obj); if (result == ISC_R_SUCCESS) check = cfg_obj_asboolean(obj); dns_zone_setoption(mayberaw, DNS_ZONEOPT_CHECKINTEGRITY, check); } obj = NULL; result = ns_config_get(maps, "check-mx-cname", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) { warn = ISC_TRUE; ignore = ISC_FALSE; } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) { warn = ignore = ISC_FALSE; } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) { warn = ignore = ISC_TRUE; } else INSIST(0); dns_zone_setoption(mayberaw, DNS_ZONEOPT_WARNMXCNAME, warn); dns_zone_setoption(mayberaw, DNS_ZONEOPT_IGNOREMXCNAME, ignore); obj = NULL; result = ns_config_get(maps, "check-srv-cname", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) { warn = ISC_TRUE; ignore = ISC_FALSE; } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) { warn = ignore = ISC_FALSE; } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) { warn = ignore = ISC_TRUE; } else INSIST(0); dns_zone_setoption(mayberaw, DNS_ZONEOPT_WARNSRVCNAME, warn); dns_zone_setoption(mayberaw, DNS_ZONEOPT_IGNORESRVCNAME, ignore); obj = NULL; result = ns_config_get(maps, "dnssec-secure-to-insecure", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); dns_zone_setoption(mayberaw, DNS_ZONEOPT_SECURETOINSECURE, cfg_obj_asboolean(obj)); obj = NULL; result = cfg_map_get(zoptions, "dnssec-update-mode", &obj); if (result == ISC_R_SUCCESS) { const char *arg = cfg_obj_asstring(obj); if (strcasecmp(arg, "no-resign") == 0) dns_zone_setkeyopt(zone, DNS_ZONEKEY_NORESIGN, ISC_TRUE); else if (strcasecmp(arg, "maintain") == 0) ; else INSIST(0); } obj = NULL; result = ns_config_get(maps, "serial-update-method", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); if (strcasecmp(cfg_obj_asstring(obj), "unixtime") == 0) dns_zone_setserialupdatemethod(zone, dns_updatemethod_unixtime); else if (strcasecmp(cfg_obj_asstring(obj), "date") == 0) dns_zone_setserialupdatemethod(zone, dns_updatemethod_date); else dns_zone_setserialupdatemethod(zone, dns_updatemethod_increment); } /* * Configure slave functionality. */ switch (ztype) { case dns_zone_slave: case dns_zone_stub: case dns_zone_redirect: count = 0; obj = NULL; (void)cfg_map_get(zoptions, "masters", &obj); if (obj != NULL) { dns_ipkeylist_t ipkl; dns_ipkeylist_init(&ipkl); RETERR(ns_config_getipandkeylist(config, obj, mctx, &ipkl)); result = dns_zone_setmasterswithkeys(mayberaw, ipkl.addrs, ipkl.keys, ipkl.count); dns_ipkeylist_clear(mctx, &ipkl); RETERR(result); } else result = dns_zone_setmasters(mayberaw, NULL, 0); RETERR(result); multi = ISC_FALSE; if (count > 1) { obj = NULL; result = ns_config_get(maps, "multi-master", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); multi = cfg_obj_asboolean(obj); } dns_zone_setoption(mayberaw, DNS_ZONEOPT_MULTIMASTER, multi); obj = NULL; result = ns_config_get(maps, "max-transfer-time-in", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); dns_zone_setmaxxfrin(mayberaw, cfg_obj_asuint32(obj) * 60); obj = NULL; result = ns_config_get(maps, "max-transfer-idle-in", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); dns_zone_setidlein(mayberaw, cfg_obj_asuint32(obj) * 60); obj = NULL; result = ns_config_get(maps, "max-refresh-time", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); dns_zone_setmaxrefreshtime(mayberaw, cfg_obj_asuint32(obj)); obj = NULL; result = ns_config_get(maps, "min-refresh-time", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); dns_zone_setminrefreshtime(mayberaw, cfg_obj_asuint32(obj)); obj = NULL; result = ns_config_get(maps, "max-retry-time", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); dns_zone_setmaxretrytime(mayberaw, cfg_obj_asuint32(obj)); obj = NULL; result = ns_config_get(maps, "min-retry-time", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); dns_zone_setminretrytime(mayberaw, cfg_obj_asuint32(obj)); obj = NULL; result = ns_config_get(maps, "transfer-source", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); RETERR(dns_zone_setxfrsource4(mayberaw, cfg_obj_assockaddr(obj))); dscp = cfg_obj_getdscp(obj); if (dscp == -1) dscp = ns_g_dscp; RETERR(dns_zone_setxfrsource4dscp(mayberaw, dscp)); ns_add_reserved_dispatch(ns_g_server, cfg_obj_assockaddr(obj)); obj = NULL; result = ns_config_get(maps, "transfer-source-v6", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); RETERR(dns_zone_setxfrsource6(mayberaw, cfg_obj_assockaddr(obj))); dscp = cfg_obj_getdscp(obj); if (dscp == -1) dscp = ns_g_dscp; RETERR(dns_zone_setxfrsource6dscp(mayberaw, dscp)); ns_add_reserved_dispatch(ns_g_server, cfg_obj_assockaddr(obj)); obj = NULL; result = ns_config_get(maps, "alt-transfer-source", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); RETERR(dns_zone_setaltxfrsource4(mayberaw, cfg_obj_assockaddr(obj))); dscp = cfg_obj_getdscp(obj); if (dscp == -1) dscp = ns_g_dscp; RETERR(dns_zone_setaltxfrsource4dscp(mayberaw, dscp)); obj = NULL; result = ns_config_get(maps, "alt-transfer-source-v6", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); RETERR(dns_zone_setaltxfrsource6(mayberaw, cfg_obj_assockaddr(obj))); dscp = cfg_obj_getdscp(obj); if (dscp == -1) dscp = ns_g_dscp; RETERR(dns_zone_setaltxfrsource6dscp(mayberaw, dscp)); obj = NULL; (void)ns_config_get(maps, "use-alt-transfer-source", &obj); if (obj == NULL) { /* * Default off when views are in use otherwise * on for BIND 8 compatibility. */ view = dns_zone_getview(zone); if (view != NULL && strcmp(view->name, "_default") == 0) alt = ISC_TRUE; else alt = ISC_FALSE; } else alt = cfg_obj_asboolean(obj); dns_zone_setoption(mayberaw, DNS_ZONEOPT_USEALTXFRSRC, alt); obj = NULL; (void)ns_config_get(maps, "try-tcp-refresh", &obj); dns_zone_setoption(mayberaw, DNS_ZONEOPT_TRYTCPREFRESH, cfg_obj_asboolean(obj)); break; case dns_zone_staticstub: RETERR(configure_staticstub(zoptions, zone, zname, default_dbtype)); break; default: break; } return (ISC_R_SUCCESS); } /* * Set up a DLZ zone as writeable */ isc_result_t ns_zone_configure_writeable_dlz(dns_dlzdb_t *dlzdatabase, dns_zone_t *zone, dns_rdataclass_t rdclass, dns_name_t *name) { dns_db_t *db = NULL; isc_time_t now; isc_result_t result; TIME_NOW(&now); dns_zone_settype(zone, dns_zone_dlz); result = dns_sdlz_setdb(dlzdatabase, rdclass, name, &db); if (result != ISC_R_SUCCESS) return (result); result = dns_zone_dlzpostload(zone, db); dns_db_detach(&db); return (result); } isc_boolean_t ns_zone_reusable(dns_zone_t *zone, const cfg_obj_t *zconfig) { const cfg_obj_t *zoptions = NULL; const cfg_obj_t *obj = NULL; const char *cfilename; const char *zfilename; dns_zone_t *raw = NULL; isc_boolean_t has_raw; dns_zonetype_t ztype; zoptions = cfg_tuple_get(zconfig, "options"); /* * We always reconfigure a static-stub zone for simplicity, assuming * the amount of data to be loaded is small. */ if (zonetype_fromconfig(zoptions) == dns_zone_staticstub) { dns_zone_log(zone, ISC_LOG_DEBUG(1), "not reusable: staticstub"); return (ISC_FALSE); } /* If there's a raw zone, use that for filename and type comparison */ dns_zone_getraw(zone, &raw); if (raw != NULL) { zfilename = dns_zone_getfile(raw); ztype = dns_zone_gettype(raw); dns_zone_detach(&raw); has_raw = ISC_TRUE; } else { zfilename = dns_zone_getfile(zone); ztype = dns_zone_gettype(zone); has_raw = ISC_FALSE; } obj = NULL; (void)cfg_map_get(zoptions, "inline-signing", &obj); if ((obj == NULL || !cfg_obj_asboolean(obj)) && has_raw) { dns_zone_log(zone, ISC_LOG_DEBUG(1), "not reusable: old zone was inline-signing"); return (ISC_FALSE); } else if ((obj != NULL && cfg_obj_asboolean(obj)) && !has_raw) { dns_zone_log(zone, ISC_LOG_DEBUG(1), "not reusable: old zone was not inline-signing"); return (ISC_FALSE); } if (zonetype_fromconfig(zoptions) != ztype) { dns_zone_log(zone, ISC_LOG_DEBUG(1), "not reusable: type mismatch"); return (ISC_FALSE); } obj = NULL; (void)cfg_map_get(zoptions, "file", &obj); if (obj != NULL) cfilename = cfg_obj_asstring(obj); else cfilename = NULL; if (!((cfilename == NULL && zfilename == NULL) || (cfilename != NULL && zfilename != NULL && strcmp(cfilename, zfilename) == 0))) { dns_zone_log(zone, ISC_LOG_DEBUG(1), "not reusable: filename mismatch"); return (ISC_FALSE); } return (ISC_TRUE); } bind9-9.11.3+dfsg/bin/nsupdate/000077500000000000000000000000001325250447100161275ustar00rootroot00000000000000bind9-9.11.3+dfsg/bin/nsupdate/Makefile.in000066400000000000000000000047171325250447100202050ustar00rootroot00000000000000# Copyright (C) 2000-2002, 2004, 2006-2009, 2012-2017 Internet Systems Consortium, Inc. ("ISC") # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. # $Id: Makefile.in,v 1.36 2009/12/05 23:31:40 each Exp $ srcdir = @srcdir@ VPATH = @srcdir@ top_srcdir = @top_srcdir@ VERSION=@BIND9_VERSION@ @BIND9_MAKE_INCLUDES@ READLINE_LIB = @READLINE_LIB@ DST_GSSAPI_INC = @DST_GSSAPI_INC@ CINCLUDES = ${LWRES_INCLUDES} ${DNS_INCLUDES} \ ${BIND9_INCLUDES} ${ISC_INCLUDES} \ ${ISCCFG_INCLUDES} ${DST_GSSAPI_INC} @DST_OPENSSL_INC@ CDEFINES = -DVERSION=\"${VERSION}\" @CRYPTO@ @USE_GSSAPI@ CWARNINGS = LWRESLIBS = ../../lib/lwres/liblwres.@A@ DNSLIBS = ../../lib/dns/libdns.@A@ @DNS_CRYPTO_LIBS@ BIND9LIBS = ../../lib/bind9/libbind9.@A@ ISCLIBS = ../../lib/isc/libisc.@A@ ISCNOSYMLIBS = ../../lib/isc/libisc-nosymtbl.@A@ ISCCFGLIBS = ../../lib/isccfg/libisccfg.@A@ LWRESDEPLIBS = ../../lib/lwres/liblwres.@A@ DNSDEPLIBS = ../../lib/dns/libdns.@A@ BIND9DEPLIBS = ../../lib/bind9/libbind9.@A@ ISCDEPLIBS = ../../lib/isc/libisc.@A@ ISCCFGDEPLIBS = ../../lib/isccfg/libisccfg.@A@ DEPLIBS = ${DNSDEPLIBS} ${BIND9DEPLIBS} ${ISCDEPLIBS} ${ISCCFGDEPLIBS} LIBS = ${LWRESLIBS} ${DNSLIBS} ${BIND9LIBS} ${ISCCFGLIBS} ${ISCLIBS} @LIBS@ NOSYMLIBS = ${LWRESLIBS} ${DNSLIBS} ${BIND9LIBS} ${ISCCFGLIBS} ${ISCNOSYMLIBS} @LIBS@ SUBDIRS = TARGETS = nsupdate@EXEEXT@ OBJS = nsupdate.@O@ UOBJS = SRCS = nsupdate.c MANPAGES = nsupdate.1 HTMLPAGES = nsupdate.html MANOBJS = ${MANPAGES} ${HTMLPAGES} @BIND9_MAKE_RULES@ nsupdate.@O@: nsupdate.c ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} \ -DSESSION_KEYFILE=\"${localstatedir}/run/named/session.key\" \ -c ${srcdir}/nsupdate.c nsupdate@EXEEXT@: nsupdate.@O@ ${UOBJS} ${DEPLIBS} export BASEOBJS="nsupdate.@O@ ${READLINE_LIB} ${UOBJS}"; \ ${FINALBUILDCMD} doc man:: ${MANOBJS} docclean manclean maintainer-clean:: rm -f ${MANOBJS} clean distclean:: rm -f ${TARGETS} installdirs: $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${bindir} $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${mandir}/man1 install:: nsupdate@EXEEXT@ installdirs ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} nsupdate@EXEEXT@ ${DESTDIR}${bindir} ${INSTALL_DATA} ${srcdir}/nsupdate.1 ${DESTDIR}${mandir}/man1 uninstall:: rm -f ${DESTDIR}${mandir}/man1/nsupdate.1 ${LIBTOOL_MODE_UNINSTALL} rm -f ${DESTDIR}${bindir}/nsupdate@EXEEXT@ bind9-9.11.3+dfsg/bin/nsupdate/nsupdate.1000066400000000000000000000377201325250447100200450ustar00rootroot00000000000000.\" Copyright (C) 2000-2012, 2014-2017 Internet Systems Consortium, Inc. ("ISC") .\" .\" This Source Code Form is subject to the terms of the Mozilla Public .\" License, v. 2.0. If a copy of the MPL was not distributed with this .\" file, You can obtain one at http://mozilla.org/MPL/2.0/. .\" .hy 0 .ad l '\" t .\" Title: nsupdate .\" Author: .\" Generator: DocBook XSL Stylesheets v1.78.1 .\" Date: 2014-04-18 .\" Manual: BIND9 .\" Source: ISC .\" Language: English .\" .TH "NSUPDATE" "1" "2014\-04\-18" "ISC" "BIND9" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" nsupdate \- Dynamic DNS update utility .SH "SYNOPSIS" .HP \w'\fBnsupdate\fR\ 'u \fBnsupdate\fR [\fB\-d\fR] [\fB\-D\fR] [\fB\-i\fR] [\fB\-L\ \fR\fB\fIlevel\fR\fR] [[\fB\-g\fR] | [\fB\-o\fR] | [\fB\-l\fR] | [\fB\-y\ \fR\fB\fI[hmac:]\fR\fIkeyname:secret\fR\fR] | [\fB\-k\ \fR\fB\fIkeyfile\fR\fR]] [\fB\-t\ \fR\fB\fItimeout\fR\fR] [\fB\-u\ \fR\fB\fIudptimeout\fR\fR] [\fB\-r\ \fR\fB\fIudpretries\fR\fR] [\fB\-R\ \fR\fB\fIrandomdev\fR\fR] [\fB\-v\fR] [\fB\-T\fR] [\fB\-P\fR] [\fB\-V\fR] [filename] .SH "DESCRIPTION" .PP \fBnsupdate\fR is used to submit Dynamic DNS Update requests as defined in RFC 2136 to a name server\&. This allows resource records to be added or removed from a zone without manually editing the zone file\&. A single update request can contain requests to add or remove more than one resource record\&. .PP Zones that are under dynamic control via \fBnsupdate\fR or a DHCP server should not be edited by hand\&. Manual edits could conflict with dynamic updates and cause data to be lost\&. .PP The resource records that are dynamically added or removed with \fBnsupdate\fR have to be in the same zone\&. Requests are sent to the zone\*(Aqs master server\&. This is identified by the MNAME field of the zone\*(Aqs SOA record\&. .PP Transaction signatures can be used to authenticate the Dynamic DNS updates\&. These use the TSIG resource record type described in RFC 2845 or the SIG(0) record described in RFC 2535 and RFC 2931 or GSS\-TSIG as described in RFC 3645\&. .PP TSIG relies on a shared secret that should only be known to \fBnsupdate\fR and the name server\&. For instance, suitable \fBkey\fR and \fBserver\fR statements would be added to /etc/named\&.conf so that the name server can associate the appropriate secret key and algorithm with the IP address of the client application that will be using TSIG authentication\&. You can use \fBddns\-confgen\fR to generate suitable configuration fragments\&. \fBnsupdate\fR uses the \fB\-y\fR or \fB\-k\fR options to provide the TSIG shared secret\&. These options are mutually exclusive\&. .PP SIG(0) uses public key cryptography\&. To use a SIG(0) key, the public key must be stored in a KEY record in a zone served by the name server\&. .PP GSS\-TSIG uses Kerberos credentials\&. Standard GSS\-TSIG mode is switched on with the \fB\-g\fR flag\&. A non\-standards\-compliant variant of GSS\-TSIG used by Windows 2000 can be switched on with the \fB\-o\fR flag\&. .SH "OPTIONS" .PP \-d .RS 4 Debug mode\&. This provides tracing information about the update requests that are made and the replies received from the name server\&. .RE .PP \-D .RS 4 Extra debug mode\&. .RE .PP \-i .RS 4 Force interactive mode, even when standard input is not a terminal\&. .RE .PP \-k \fIkeyfile\fR .RS 4 The file containing the TSIG authentication key\&. Keyfiles may be in two formats: a single file containing a named\&.conf\-format \fBkey\fR statement, which may be generated automatically by \fBddns\-confgen\fR, or a pair of files whose names are of the format K{name}\&.+157\&.+{random}\&.key and K{name}\&.+157\&.+{random}\&.private, which can be generated by \fBdnssec\-keygen\fR\&. The \fB\-k\fR may also be used to specify a SIG(0) key used to authenticate Dynamic DNS update requests\&. In this case, the key specified is not an HMAC\-MD5 key\&. .RE .PP \-l .RS 4 Local\-host only mode\&. This sets the server address to localhost (disabling the \fBserver\fR so that the server address cannot be overridden)\&. Connections to the local server will use a TSIG key found in /var/run/named/session\&.key, which is automatically generated by \fBnamed\fR if any local master zone has set \fBupdate\-policy\fR to \fBlocal\fR\&. The location of this key file can be overridden with the \fB\-k\fR option\&. .RE .PP \-L \fIlevel\fR .RS 4 Set the logging debug level\&. If zero, logging is disabled\&. .RE .PP \-p \fIport\fR .RS 4 Set the port to use for connections to a name server\&. The default is 53\&. .RE .PP \-P .RS 4 Print the list of private BIND\-specific resource record types whose format is understood by \fBnsupdate\fR\&. See also the \fB\-T\fR option\&. .RE .PP \-r \fIudpretries\fR .RS 4 The number of UDP retries\&. The default is 3\&. If zero, only one update request will be made\&. .RE .PP \-R \fIrandomdev\fR .RS 4 Where to obtain randomness\&. If the operating system does not provide a /dev/random or equivalent device, the default source of randomness is keyboard input\&. randomdev specifies the name of a character device or file containing random data to be used instead of the default\&. The special value keyboard indicates that keyboard input should be used\&. This option may be specified multiple times\&. .RE .PP \-t \fItimeout\fR .RS 4 The maximum time an update request can take before it is aborted\&. The default is 300 seconds\&. Zero can be used to disable the timeout\&. .RE .PP \-T .RS 4 Print the list of IANA standard resource record types whose format is understood by \fBnsupdate\fR\&. \fBnsupdate\fR will exit after the lists are printed\&. The \fB\-T\fR option can be combined with the \fB\-P\fR option\&. .sp Other types can be entered using "TYPEXXXXX" where "XXXXX" is the decimal value of the type with no leading zeros\&. The rdata, if present, will be parsed using the UNKNOWN rdata format, ( )\&. .RE .PP \-u \fIudptimeout\fR .RS 4 The UDP retry interval\&. The default is 3 seconds\&. If zero, the interval will be computed from the timeout interval and number of UDP retries\&. .RE .PP \-v .RS 4 Use TCP even for small update requests\&. By default, \fBnsupdate\fR uses UDP to send update requests to the name server unless they are too large to fit in a UDP request in which case TCP will be used\&. TCP may be preferable when a batch of update requests is made\&. .RE .PP \-V .RS 4 Print the version number and exit\&. .RE .PP \-y \fI[hmac:]\fR\fIkeyname:secret\fR .RS 4 Literal TSIG authentication key\&. \fIkeyname\fR is the name of the key, and \fIsecret\fR is the base64 encoded shared secret\&. \fIhmac\fR is the name of the key algorithm; valid choices are hmac\-md5, hmac\-sha1, hmac\-sha224, hmac\-sha256, hmac\-sha384, or hmac\-sha512\&. If \fIhmac\fR is not specified, the default is hmac\-md5 or if MD5 was disabled hmac\-sha256\&. .sp NOTE: Use of the \fB\-y\fR option is discouraged because the shared secret is supplied as a command line argument in clear text\&. This may be visible in the output from \fBps\fR(1) or in a history file maintained by the user\*(Aqs shell\&. .RE .SH "INPUT FORMAT" .PP \fBnsupdate\fR reads input from \fIfilename\fR or standard input\&. Each command is supplied on exactly one line of input\&. Some commands are for administrative purposes\&. The others are either update instructions or prerequisite checks on the contents of the zone\&. These checks set conditions that some name or set of resource records (RRset) either exists or is absent from the zone\&. These conditions must be met if the entire update request is to succeed\&. Updates will be rejected if the tests for the prerequisite conditions fail\&. .PP Every update request consists of zero or more prerequisites and zero or more updates\&. This allows a suitably authenticated update request to proceed if some specified resource records are present or missing from the zone\&. A blank input line (or the \fBsend\fR command) causes the accumulated commands to be sent as one Dynamic DNS update request to the name server\&. .PP The command formats and their meaning are as follows: .PP \fBserver\fR {servername} [port] .RS 4 Sends all dynamic update requests to the name server \fIservername\fR\&. When no server statement is provided, \fBnsupdate\fR will send updates to the master server of the correct zone\&. The MNAME field of that zone\*(Aqs SOA record will identify the master server for that zone\&. \fIport\fR is the port number on \fIservername\fR where the dynamic update requests get sent\&. If no port number is specified, the default DNS port number of 53 is used\&. .RE .PP \fBlocal\fR {address} [port] .RS 4 Sends all dynamic update requests using the local \fIaddress\fR\&. When no local statement is provided, \fBnsupdate\fR will send updates using an address and port chosen by the system\&. \fIport\fR can additionally be used to make requests come from a specific port\&. If no port number is specified, the system will assign one\&. .RE .PP \fBzone\fR {zonename} .RS 4 Specifies that all updates are to be made to the zone \fIzonename\fR\&. If no \fIzone\fR statement is provided, \fBnsupdate\fR will attempt determine the correct zone to update based on the rest of the input\&. .RE .PP \fBclass\fR {classname} .RS 4 Specify the default class\&. If no \fIclass\fR is specified, the default class is \fIIN\fR\&. .RE .PP \fBttl\fR {seconds} .RS 4 Specify the default time to live for records to be added\&. The value \fInone\fR will clear the default ttl\&. .RE .PP \fBkey\fR [hmac:] {keyname} {secret} .RS 4 Specifies that all updates are to be TSIG\-signed using the \fIkeyname\fR\fIsecret\fR pair\&. If \fIhmac\fR is specified, then it sets the signing algorithm in use; the default is hmac\-md5 or if MD5 was disabled hmac\-sha256\&. The \fBkey\fR command overrides any key specified on the command line via \fB\-y\fR or \fB\-k\fR\&. .RE .PP \fBgsstsig\fR .RS 4 Use GSS\-TSIG to sign the updated\&. This is equivalent to specifying \fB\-g\fR on the command line\&. .RE .PP \fBoldgsstsig\fR .RS 4 Use the Windows 2000 version of GSS\-TSIG to sign the updated\&. This is equivalent to specifying \fB\-o\fR on the command line\&. .RE .PP \fBrealm\fR {[realm_name]} .RS 4 When using GSS\-TSIG use \fIrealm_name\fR rather than the default realm in krb5\&.conf\&. If no realm is specified the saved realm is cleared\&. .RE .PP \fBcheck\-names\fR {[yes_or_no]} .RS 4 Turn on or off check\-names processing on records to be added\&. Check\-names has no effect on prerequisites or records to be deleted\&. By default check\-names processing is on\&. If check\-names processing fails the record will not be added to the UPDATE message\&. .RE .PP \fB[prereq]\fR\fB nxdomain\fR {domain\-name} .RS 4 Requires that no resource record of any type exists with name \fIdomain\-name\fR\&. .RE .PP \fB[prereq]\fR\fB yxdomain\fR {domain\-name} .RS 4 Requires that \fIdomain\-name\fR exists (has as at least one resource record, of any type)\&. .RE .PP \fB[prereq]\fR\fB nxrrset\fR {domain\-name} [class] {type} .RS 4 Requires that no resource record exists of the specified \fItype\fR, \fIclass\fR and \fIdomain\-name\fR\&. If \fIclass\fR is omitted, IN (internet) is assumed\&. .RE .PP \fB[prereq]\fR\fB yxrrset\fR {domain\-name} [class] {type} .RS 4 This requires that a resource record of the specified \fItype\fR, \fIclass\fR and \fIdomain\-name\fR must exist\&. If \fIclass\fR is omitted, IN (internet) is assumed\&. .RE .PP \fB[prereq]\fR\fB yxrrset\fR {domain\-name} [class] {type} {data...} .RS 4 The \fIdata\fR from each set of prerequisites of this form sharing a common \fItype\fR, \fIclass\fR, and \fIdomain\-name\fR are combined to form a set of RRs\&. This set of RRs must exactly match the set of RRs existing in the zone at the given \fItype\fR, \fIclass\fR, and \fIdomain\-name\fR\&. The \fIdata\fR are written in the standard text representation of the resource record\*(Aqs RDATA\&. .RE .PP \fB[update]\fR\fB del\fR\fB[ete]\fR {domain\-name} [ttl] [class] [type\ [data...]] .RS 4 Deletes any resource records named \fIdomain\-name\fR\&. If \fItype\fR and \fIdata\fR is provided, only matching resource records will be removed\&. The internet class is assumed if \fIclass\fR is not supplied\&. The \fIttl\fR is ignored, and is only allowed for compatibility\&. .RE .PP \fB[update]\fR\fB add\fR {domain\-name} {ttl} [class] {type} {data...} .RS 4 Adds a new resource record with the specified \fIttl\fR, \fIclass\fR and \fIdata\fR\&. .RE .PP \fBshow\fR .RS 4 Displays the current message, containing all of the prerequisites and updates specified since the last send\&. .RE .PP \fBsend\fR .RS 4 Sends the current message\&. This is equivalent to entering a blank line\&. .RE .PP \fBanswer\fR .RS 4 Displays the answer\&. .RE .PP \fBdebug\fR .RS 4 Turn on debugging\&. .RE .PP \fBversion\fR .RS 4 Print version number\&. .RE .PP \fBhelp\fR .RS 4 Print a list of commands\&. .RE .PP Lines beginning with a semicolon are comments and are ignored\&. .SH "EXAMPLES" .PP The examples below show how \fBnsupdate\fR could be used to insert and delete resource records from the \fBexample\&.com\fR zone\&. Notice that the input in each example contains a trailing blank line so that a group of commands are sent as one dynamic update request to the master name server for \fBexample\&.com\fR\&. .sp .if n \{\ .RS 4 .\} .nf # nsupdate > update delete oldhost\&.example\&.com A > update add newhost\&.example\&.com 86400 A 172\&.16\&.1\&.1 > send .fi .if n \{\ .RE .\} .PP Any A records for \fBoldhost\&.example\&.com\fR are deleted\&. And an A record for \fBnewhost\&.example\&.com\fR with IP address 172\&.16\&.1\&.1 is added\&. The newly\-added record has a 1 day TTL (86400 seconds)\&. .sp .if n \{\ .RS 4 .\} .nf # nsupdate > prereq nxdomain nickname\&.example\&.com > update add nickname\&.example\&.com 86400 CNAME somehost\&.example\&.com > send .fi .if n \{\ .RE .\} .PP The prerequisite condition gets the name server to check that there are no resource records of any type for \fBnickname\&.example\&.com\fR\&. If there are, the update request fails\&. If this name does not exist, a CNAME for it is added\&. This ensures that when the CNAME is added, it cannot conflict with the long\-standing rule in RFC 1034 that a name must not exist as any other record type if it exists as a CNAME\&. (The rule has been updated for DNSSEC in RFC 2535 to allow CNAMEs to have RRSIG, DNSKEY and NSEC records\&.) .SH "FILES" .PP \fB/etc/resolv\&.conf\fR .RS 4 used to identify default name server .RE .PP \fB/var/run/named/session\&.key\fR .RS 4 sets the default TSIG key for use in local\-only mode .RE .PP \fBK{name}\&.+157\&.+{random}\&.key\fR .RS 4 base\-64 encoding of HMAC\-MD5 key created by \fBdnssec-keygen\fR(8)\&. .RE .PP \fBK{name}\&.+157\&.+{random}\&.private\fR .RS 4 base\-64 encoding of HMAC\-MD5 key created by \fBdnssec-keygen\fR(8)\&. .RE .SH "SEE ALSO" .PP RFC 2136, RFC 3007, RFC 2104, RFC 2845, RFC 1034, RFC 2535, RFC 2931, \fBnamed\fR(8), \fBddns-confgen\fR(8), \fBdnssec-keygen\fR(8)\&. .SH "BUGS" .PP The TSIG key is redundantly stored in two separate files\&. This is a consequence of nsupdate using the DST library for its cryptographic operations, and may change in future releases\&. .SH "AUTHOR" .PP \fBInternet Systems Consortium, Inc\&.\fR .SH "COPYRIGHT" .br Copyright \(co 2000-2012, 2014-2017 Internet Systems Consortium, Inc. ("ISC") .br bind9-9.11.3+dfsg/bin/nsupdate/nsupdate.c000066400000000000000000002504511325250447100201250ustar00rootroot00000000000000/* * Copyright (C) 2000-2018 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /*! \file */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef GSSAPI #include #ifdef WIN32 #include #else #include ISC_PLATFORM_KRB5HEADER #endif #endif #include #if defined(HAVE_READLINE) #if defined(HAVE_EDIT_READLINE_READLINE_H) #include #if defined(HAVE_EDIT_READLINE_HISTORY_H) #include #endif #elif defined(HAVE_EDITLINE_READLINE_H) #include #else #include #include #endif #endif #ifdef HAVE_ADDRINFO #ifdef HAVE_GETADDRINFO #ifdef HAVE_GAISTRERROR #define USE_GETADDRINFO #endif #endif #endif #ifndef USE_GETADDRINFO #ifndef ISC_PLATFORM_NONSTDHERRNO extern int h_errno; #endif #endif #define MAXCMD (128 * 1024) #define MAXWIRE (64 * 1024) #define PACKETSIZE ((64 * 1024) - 1) #define INITTEXT (2 * 1024) #define MAXTEXT (128 * 1024) #define FIND_TIMEOUT 5 #define TTL_MAX 2147483647U /* Maximum signed 32 bit integer. */ #define DNSDEFAULTPORT 53 /* Number of addresses to request from bind9_getaddresses() */ #define MAX_SERVERADDRS 4 static isc_uint16_t dnsport = DNSDEFAULTPORT; #ifndef RESOLV_CONF #define RESOLV_CONF "/etc/resolv.conf" #endif static isc_boolean_t debugging = ISC_FALSE, ddebugging = ISC_FALSE; static isc_boolean_t memdebugging = ISC_FALSE; static isc_boolean_t have_ipv4 = ISC_FALSE; static isc_boolean_t have_ipv6 = ISC_FALSE; static isc_boolean_t is_dst_up = ISC_FALSE; static isc_boolean_t usevc = ISC_FALSE; static isc_boolean_t usegsstsig = ISC_FALSE; static isc_boolean_t use_win2k_gsstsig = ISC_FALSE; static isc_boolean_t tried_other_gsstsig = ISC_FALSE; static isc_boolean_t local_only = ISC_FALSE; static isc_taskmgr_t *taskmgr = NULL; static isc_task_t *global_task = NULL; static isc_event_t *global_event = NULL; static isc_log_t *glctx = NULL; static isc_mem_t *gmctx = NULL; static dns_dispatchmgr_t *dispatchmgr = NULL; static dns_requestmgr_t *requestmgr = NULL; static isc_socketmgr_t *socketmgr = NULL; static isc_timermgr_t *timermgr = NULL; static dns_dispatch_t *dispatchv4 = NULL; static dns_dispatch_t *dispatchv6 = NULL; static dns_message_t *updatemsg = NULL; static dns_fixedname_t fuserzone; static dns_fixedname_t fzname; static dns_name_t *userzone = NULL; static dns_name_t *zname = NULL; static dns_name_t tmpzonename; static dns_name_t restart_master; static dns_tsig_keyring_t *gssring = NULL; static dns_tsigkey_t *tsigkey = NULL; static dst_key_t *sig0key = NULL; static lwres_context_t *lwctx = NULL; static lwres_conf_t *lwconf; static isc_sockaddr_t *servers = NULL; static isc_sockaddr_t *master_servers = NULL; static isc_boolean_t default_servers = ISC_TRUE; static int ns_inuse = 0; static int master_inuse = 0; static int ns_total = 0; static int ns_alloc = 0; static int master_total = 0; static int master_alloc = 0; static isc_sockaddr_t *localaddr4 = NULL; static isc_sockaddr_t *localaddr6 = NULL; static const char *keyfile = NULL; static char *keystr = NULL; static isc_entropy_t *entropy = NULL; static isc_boolean_t shuttingdown = ISC_FALSE; static FILE *input; static isc_boolean_t interactive = ISC_TRUE; static isc_boolean_t seenerror = ISC_FALSE; static const dns_master_style_t *style; static int requests = 0; static unsigned int logdebuglevel = 0; static unsigned int timeout = 300; static unsigned int udp_timeout = 3; static unsigned int udp_retries = 3; static dns_rdataclass_t defaultclass = dns_rdataclass_in; static dns_rdataclass_t zoneclass = dns_rdataclass_none; static dns_message_t *answer = NULL; static isc_uint32_t default_ttl = 0; static isc_boolean_t default_ttl_set = ISC_FALSE; static isc_boolean_t checknames = ISC_TRUE; typedef struct nsu_requestinfo { dns_message_t *msg; isc_sockaddr_t *addr; } nsu_requestinfo_t; static void sendrequest(isc_sockaddr_t *destaddr, dns_message_t *msg, dns_request_t **request); static void send_update(dns_name_t *zonename, isc_sockaddr_t *master); ISC_PLATFORM_NORETURN_PRE static void fatal(const char *format, ...) ISC_FORMAT_PRINTF(1, 2) ISC_PLATFORM_NORETURN_POST; static void debug(const char *format, ...) ISC_FORMAT_PRINTF(1, 2); static void ddebug(const char *format, ...) ISC_FORMAT_PRINTF(1, 2); #ifdef GSSAPI static dns_fixedname_t fkname; static isc_sockaddr_t *kserver = NULL; static char *realm = NULL; static char servicename[DNS_NAME_FORMATSIZE]; static dns_name_t *keyname; typedef struct nsu_gssinfo { dns_message_t *msg; isc_sockaddr_t *addr; gss_ctx_id_t context; } nsu_gssinfo_t; static void failed_gssrequest(); static void start_gssrequest(dns_name_t *master); static void send_gssrequest(isc_sockaddr_t *destaddr, dns_message_t *msg, dns_request_t **request, gss_ctx_id_t context); static void recvgss(isc_task_t *task, isc_event_t *event); #endif /* GSSAPI */ static void error(const char *format, ...) ISC_FORMAT_PRINTF(1, 2); #define STATUS_MORE (isc_uint16_t)0 #define STATUS_SEND (isc_uint16_t)1 #define STATUS_QUIT (isc_uint16_t)2 #define STATUS_SYNTAX (isc_uint16_t)3 typedef struct entropysource entropysource_t; struct entropysource { isc_entropysource_t *source; isc_mem_t *mctx; ISC_LINK(entropysource_t) link; }; static ISC_LIST(entropysource_t) sources; static void setup_entropy(isc_mem_t *mctx, const char *randomfile, isc_entropy_t **ectx) { isc_result_t result; isc_entropysource_t *source = NULL; entropysource_t *elt; int usekeyboard = ISC_ENTROPY_KEYBOARDMAYBE; REQUIRE(ectx != NULL); if (*ectx == NULL) { result = isc_entropy_create(mctx, ectx); if (result != ISC_R_SUCCESS) fatal("could not create entropy object"); ISC_LIST_INIT(sources); } if (randomfile != NULL && strcmp(randomfile, "keyboard") == 0) { usekeyboard = ISC_ENTROPY_KEYBOARDYES; randomfile = NULL; } result = isc_entropy_usebestsource(*ectx, &source, randomfile, usekeyboard); if (result != ISC_R_SUCCESS) fatal("could not initialize entropy source: %s", isc_result_totext(result)); if (source != NULL) { elt = isc_mem_get(mctx, sizeof(*elt)); if (elt == NULL) fatal("out of memory"); elt->source = source; elt->mctx = mctx; ISC_LINK_INIT(elt, link); ISC_LIST_APPEND(sources, elt, link); } } static void cleanup_entropy(isc_entropy_t **ectx) { entropysource_t *source; while (!ISC_LIST_EMPTY(sources)) { source = ISC_LIST_HEAD(sources); ISC_LIST_UNLINK(sources, source, link); isc_entropy_destroysource(&source->source); isc_mem_put(source->mctx, source, sizeof(*source)); } isc_entropy_detach(ectx); } static void master_from_servers(void) { if (master_servers != NULL && master_servers != servers) isc_mem_put(gmctx, master_servers, master_alloc * sizeof(isc_sockaddr_t)); master_servers = servers; master_total = ns_total; master_alloc = ns_alloc; master_inuse = ns_inuse; } static dns_rdataclass_t getzoneclass(void) { if (zoneclass == dns_rdataclass_none) zoneclass = defaultclass; return (zoneclass); } static isc_boolean_t setzoneclass(dns_rdataclass_t rdclass) { if (zoneclass == dns_rdataclass_none || rdclass == dns_rdataclass_none) zoneclass = rdclass; if (zoneclass != rdclass) return (ISC_FALSE); return (ISC_TRUE); } static void fatal(const char *format, ...) { va_list args; va_start(args, format); vfprintf(stderr, format, args); va_end(args); fprintf(stderr, "\n"); exit(1); } static void error(const char *format, ...) { va_list args; va_start(args, format); vfprintf(stderr, format, args); va_end(args); fprintf(stderr, "\n"); } static void debug(const char *format, ...) { va_list args; if (debugging) { va_start(args, format); vfprintf(stderr, format, args); va_end(args); fprintf(stderr, "\n"); } } static void ddebug(const char *format, ...) { va_list args; if (ddebugging) { va_start(args, format); vfprintf(stderr, format, args); va_end(args); fprintf(stderr, "\n"); } } static inline void check_result(isc_result_t result, const char *msg) { if (result != ISC_R_SUCCESS) fatal("%s: %s", msg, isc_result_totext(result)); } static void * mem_alloc(void *arg, size_t size) { return (isc_mem_get(arg, size)); } static void mem_free(void *arg, void *mem, size_t size) { isc_mem_put(arg, mem, size); } static char * nsu_strsep(char **stringp, const char *delim) { char *string = *stringp; char *s; const char *d; char sc, dc; if (string == NULL) return (NULL); for (; *string != '\0'; string++) { sc = *string; for (d = delim; (dc = *d) != '\0'; d++) { if (sc == dc) break; } if (dc == 0) break; } for (s = string; *s != '\0'; s++) { sc = *s; for (d = delim; (dc = *d) != '\0'; d++) { if (sc == dc) { *s++ = '\0'; *stringp = s; return (string); } } } *stringp = NULL; return (string); } static void reset_system(void) { isc_result_t result; ddebug("reset_system()"); /* If the update message is still around, destroy it */ if (updatemsg != NULL) dns_message_reset(updatemsg, DNS_MESSAGE_INTENTRENDER); else { result = dns_message_create(gmctx, DNS_MESSAGE_INTENTRENDER, &updatemsg); check_result(result, "dns_message_create"); } updatemsg->opcode = dns_opcode_update; if (usegsstsig) { if (tsigkey != NULL) dns_tsigkey_detach(&tsigkey); if (gssring != NULL) dns_tsigkeyring_detach(&gssring); tried_other_gsstsig = ISC_FALSE; } } static isc_boolean_t parse_hmac(dns_name_t **hmac, const char *hmacstr, size_t len, isc_uint16_t *digestbitsp) { isc_uint16_t digestbits = 0; isc_result_t result; char buf[20]; REQUIRE(hmac != NULL && *hmac == NULL); REQUIRE(hmacstr != NULL); if (len >= sizeof(buf)) { error("unknown key type '%.*s'", (int)(len), hmacstr); return (ISC_FALSE); } /* Copy len bytes and NUL terminate. */ strlcpy(buf, hmacstr, ISC_MIN(len + 1, sizeof(buf))); #ifndef PK11_MD5_DISABLE if (strcasecmp(buf, "hmac-md5") == 0) { *hmac = DNS_TSIG_HMACMD5_NAME; } else if (strncasecmp(buf, "hmac-md5-", 9) == 0) { *hmac = DNS_TSIG_HMACMD5_NAME; result = isc_parse_uint16(&digestbits, &buf[9], 10); if (result != ISC_R_SUCCESS || digestbits > 128) { error("digest-bits out of range [0..128]"); return (ISC_FALSE); } *digestbitsp = (digestbits + 7) & ~0x7U; } else #endif if (strcasecmp(buf, "hmac-sha1") == 0) { *hmac = DNS_TSIG_HMACSHA1_NAME; } else if (strncasecmp(buf, "hmac-sha1-", 10) == 0) { *hmac = DNS_TSIG_HMACSHA1_NAME; result = isc_parse_uint16(&digestbits, &buf[10], 10); if (result != ISC_R_SUCCESS || digestbits > 160) { error("digest-bits out of range [0..160]"); return (ISC_FALSE); } *digestbitsp = (digestbits + 7) & ~0x7U; } else if (strcasecmp(buf, "hmac-sha224") == 0) { *hmac = DNS_TSIG_HMACSHA224_NAME; } else if (strncasecmp(buf, "hmac-sha224-", 12) == 0) { *hmac = DNS_TSIG_HMACSHA224_NAME; result = isc_parse_uint16(&digestbits, &buf[12], 10); if (result != ISC_R_SUCCESS || digestbits > 224) { error("digest-bits out of range [0..224]"); return (ISC_FALSE); } *digestbitsp = (digestbits + 7) & ~0x7U; } else if (strcasecmp(buf, "hmac-sha256") == 0) { *hmac = DNS_TSIG_HMACSHA256_NAME; } else if (strncasecmp(buf, "hmac-sha256-", 12) == 0) { *hmac = DNS_TSIG_HMACSHA256_NAME; result = isc_parse_uint16(&digestbits, &buf[12], 10); if (result != ISC_R_SUCCESS || digestbits > 256) { error("digest-bits out of range [0..256]"); return (ISC_FALSE); } *digestbitsp = (digestbits + 7) & ~0x7U; } else if (strcasecmp(buf, "hmac-sha384") == 0) { *hmac = DNS_TSIG_HMACSHA384_NAME; } else if (strncasecmp(buf, "hmac-sha384-", 12) == 0) { *hmac = DNS_TSIG_HMACSHA384_NAME; result = isc_parse_uint16(&digestbits, &buf[12], 10); if (result != ISC_R_SUCCESS || digestbits > 384) { error("digest-bits out of range [0..384]"); return (ISC_FALSE); } *digestbitsp = (digestbits + 7) & ~0x7U; } else if (strcasecmp(buf, "hmac-sha512") == 0) { *hmac = DNS_TSIG_HMACSHA512_NAME; } else if (strncasecmp(buf, "hmac-sha512-", 12) == 0) { *hmac = DNS_TSIG_HMACSHA512_NAME; result = isc_parse_uint16(&digestbits, &buf[12], 10); if (result != ISC_R_SUCCESS || digestbits > 512) { error("digest-bits out of range [0..512]"); return (ISC_FALSE); } *digestbitsp = (digestbits + 7) & ~0x7U; } else { error("unknown key type '%s'", buf); return (ISC_FALSE); } return (ISC_TRUE); } static int basenamelen(const char *file) { int len = strlen(file); if (len > 1 && file[len - 1] == '.') len -= 1; else if (len > 8 && strcmp(file + len - 8, ".private") == 0) len -= 8; else if (len > 4 && strcmp(file + len - 4, ".key") == 0) len -= 4; return (len); } static void setup_keystr(void) { unsigned char *secret = NULL; int secretlen; isc_buffer_t secretbuf; isc_result_t result; isc_buffer_t keynamesrc; char *secretstr; char *s, *n; dns_fixedname_t fkeyname; dns_name_t *mykeyname; char *name; dns_name_t *hmacname = NULL; isc_uint16_t digestbits = 0; dns_fixedname_init(&fkeyname); mykeyname = dns_fixedname_name(&fkeyname); debug("Creating key..."); s = strchr(keystr, ':'); if (s == NULL || s == keystr || s[1] == 0) fatal("key option must specify [hmac:]keyname:secret"); secretstr = s + 1; n = strchr(secretstr, ':'); if (n != NULL) { if (n == secretstr || n[1] == 0) fatal("key option must specify [hmac:]keyname:secret"); name = secretstr; secretstr = n + 1; if (!parse_hmac(&hmacname, keystr, s - keystr, &digestbits)) { exit(1); } } else { #ifndef PK11_MD5_DISABLE hmacname = DNS_TSIG_HMACMD5_NAME; #else hmacname = DNS_TSIG_HMACSHA256_NAME; #endif name = keystr; n = s; } isc_buffer_init(&keynamesrc, name, (unsigned int)(n - name)); isc_buffer_add(&keynamesrc, (unsigned int)(n - name)); debug("namefromtext"); result = dns_name_fromtext(mykeyname, &keynamesrc, dns_rootname, 0, NULL); check_result(result, "dns_name_fromtext"); secretlen = strlen(secretstr) * 3 / 4; secret = isc_mem_allocate(gmctx, secretlen); if (secret == NULL) fatal("out of memory"); isc_buffer_init(&secretbuf, secret, secretlen); result = isc_base64_decodestring(secretstr, &secretbuf); if (result != ISC_R_SUCCESS) { fprintf(stderr, "could not create key from %s: %s\n", keystr, isc_result_totext(result)); goto failure; } secretlen = isc_buffer_usedlength(&secretbuf); debug("keycreate"); result = dns_tsigkey_create(mykeyname, hmacname, secret, secretlen, ISC_FALSE, NULL, 0, 0, gmctx, NULL, &tsigkey); if (result != ISC_R_SUCCESS) fprintf(stderr, "could not create key from %s: %s\n", keystr, dns_result_totext(result)); else dst_key_setbits(tsigkey->key, digestbits); failure: if (secret != NULL) isc_mem_free(gmctx, secret); } /* * Get a key from a named.conf format keyfile */ static isc_result_t read_sessionkey(isc_mem_t *mctx, isc_log_t *lctx) { cfg_parser_t *pctx = NULL; cfg_obj_t *sessionkey = NULL; const cfg_obj_t *key = NULL; const cfg_obj_t *secretobj = NULL; const cfg_obj_t *algorithmobj = NULL; const char *mykeyname; const char *secretstr; const char *algorithm; isc_result_t result; int len; if (! isc_file_exists(keyfile)) return (ISC_R_FILENOTFOUND); result = cfg_parser_create(mctx, lctx, &pctx); if (result != ISC_R_SUCCESS) goto cleanup; result = cfg_parse_file(pctx, keyfile, &cfg_type_sessionkey, &sessionkey); if (result != ISC_R_SUCCESS) goto cleanup; result = cfg_map_get(sessionkey, "key", &key); if (result != ISC_R_SUCCESS) goto cleanup; (void) cfg_map_get(key, "secret", &secretobj); (void) cfg_map_get(key, "algorithm", &algorithmobj); if (secretobj == NULL || algorithmobj == NULL) fatal("key must have algorithm and secret"); mykeyname = cfg_obj_asstring(cfg_map_getname(key)); secretstr = cfg_obj_asstring(secretobj); algorithm = cfg_obj_asstring(algorithmobj); len = strlen(algorithm) + strlen(mykeyname) + strlen(secretstr) + 3; keystr = isc_mem_allocate(mctx, len); if (keystr == NULL) fatal("out of memory"); snprintf(keystr, len, "%s:%s:%s", algorithm, mykeyname, secretstr); setup_keystr(); cleanup: if (pctx != NULL) { if (sessionkey != NULL) cfg_obj_destroy(pctx, &sessionkey); cfg_parser_destroy(&pctx); } if (keystr != NULL) isc_mem_free(mctx, keystr); return (result); } static void setup_keyfile(isc_mem_t *mctx, isc_log_t *lctx) { dst_key_t *dstkey = NULL; isc_result_t result; dns_name_t *hmacname = NULL; debug("Creating key..."); if (sig0key != NULL) dst_key_free(&sig0key); /* Try reading the key from a K* pair */ result = dst_key_fromnamedfile(keyfile, NULL, DST_TYPE_PRIVATE | DST_TYPE_KEY, mctx, &dstkey); /* If that didn't work, try reading it as a session.key keyfile */ if (result != ISC_R_SUCCESS) { result = read_sessionkey(mctx, lctx); if (result == ISC_R_SUCCESS) return; } if (result != ISC_R_SUCCESS) { fprintf(stderr, "could not read key from %.*s.{private,key}: " "%s\n", basenamelen(keyfile), keyfile, isc_result_totext(result)); return; } switch (dst_key_alg(dstkey)) { #ifndef PK11_MD5_DISABLE case DST_ALG_HMACMD5: hmacname = DNS_TSIG_HMACMD5_NAME; break; #endif case DST_ALG_HMACSHA1: hmacname = DNS_TSIG_HMACSHA1_NAME; break; case DST_ALG_HMACSHA224: hmacname = DNS_TSIG_HMACSHA224_NAME; break; case DST_ALG_HMACSHA256: hmacname = DNS_TSIG_HMACSHA256_NAME; break; case DST_ALG_HMACSHA384: hmacname = DNS_TSIG_HMACSHA384_NAME; break; case DST_ALG_HMACSHA512: hmacname = DNS_TSIG_HMACSHA512_NAME; break; } if (hmacname != NULL) { result = dns_tsigkey_createfromkey(dst_key_name(dstkey), hmacname, dstkey, ISC_FALSE, NULL, 0, 0, mctx, NULL, &tsigkey); dst_key_free(&dstkey); if (result != ISC_R_SUCCESS) { fprintf(stderr, "could not create key from %s: %s\n", keyfile, isc_result_totext(result)); return; } } else { dst_key_attach(dstkey, &sig0key); dst_key_free(&dstkey); } } static void doshutdown(void) { isc_task_detach(&global_task); /* * The isc_mem_put of master_servers must be before the * isc_mem_put of servers as it sets the servers pointer * to NULL. */ if (master_servers != NULL && master_servers != servers) isc_mem_put(gmctx, master_servers, master_alloc * sizeof(isc_sockaddr_t)); if (servers != NULL) isc_mem_put(gmctx, servers, ns_alloc * sizeof(isc_sockaddr_t)); if (localaddr4 != NULL) isc_mem_put(gmctx, localaddr4, sizeof(isc_sockaddr_t)); if (localaddr6 != NULL) isc_mem_put(gmctx, localaddr6, sizeof(isc_sockaddr_t)); if (tsigkey != NULL) { ddebug("Freeing TSIG key"); dns_tsigkey_detach(&tsigkey); } if (sig0key != NULL) { ddebug("Freeing SIG(0) key"); dst_key_free(&sig0key); } if (updatemsg != NULL) dns_message_destroy(&updatemsg); if (is_dst_up) { ddebug("Destroy DST lib"); dst_lib_destroy(); is_dst_up = ISC_FALSE; } cleanup_entropy(&entropy); lwres_conf_clear(lwctx); lwres_context_destroy(&lwctx); ddebug("Destroying request manager"); dns_requestmgr_detach(&requestmgr); ddebug("Freeing the dispatchers"); if (have_ipv4) dns_dispatch_detach(&dispatchv4); if (have_ipv6) dns_dispatch_detach(&dispatchv6); ddebug("Shutting down dispatch manager"); dns_dispatchmgr_destroy(&dispatchmgr); } static void maybeshutdown(void) { ddebug("Shutting down request manager"); dns_requestmgr_shutdown(requestmgr); if (requests != 0) return; doshutdown(); } static void shutdown_program(isc_task_t *task, isc_event_t *event) { REQUIRE(task == global_task); UNUSED(task); ddebug("shutdown_program()"); isc_event_free(&event); shuttingdown = ISC_TRUE; maybeshutdown(); } static void setup_system(void) { isc_result_t result; isc_sockaddr_t bind_any, bind_any6; lwres_result_t lwresult; unsigned int attrs, attrmask; int i; isc_logconfig_t *logconfig = NULL; ddebug("setup_system()"); dns_result_register(); result = isc_net_probeipv4(); if (result == ISC_R_SUCCESS) have_ipv4 = ISC_TRUE; result = isc_net_probeipv6(); if (result == ISC_R_SUCCESS) have_ipv6 = ISC_TRUE; if (!have_ipv4 && !have_ipv6) fatal("could not find either IPv4 or IPv6"); result = isc_log_create(gmctx, &glctx, &logconfig); check_result(result, "isc_log_create"); isc_log_setcontext(glctx); dns_log_init(glctx); dns_log_setcontext(glctx); result = isc_log_usechannel(logconfig, "default_debug", NULL, NULL); check_result(result, "isc_log_usechannel"); isc_log_setdebuglevel(glctx, logdebuglevel); lwresult = lwres_context_create(&lwctx, gmctx, mem_alloc, mem_free, 1); if (lwresult != LWRES_R_SUCCESS) fatal("lwres_context_create failed"); (void)lwres_conf_parse(lwctx, RESOLV_CONF); lwconf = lwres_conf_get(lwctx); if (servers != NULL) { if (master_servers == servers) master_servers = NULL; isc_mem_put(gmctx, servers, ns_alloc * sizeof(isc_sockaddr_t)); } ns_inuse = 0; if (local_only || lwconf->nsnext <= 0) { struct in_addr in; struct in6_addr in6; if (local_only && keyfile == NULL) keyfile = SESSION_KEYFILE; default_servers = !local_only; ns_total = ns_alloc = (have_ipv4 ? 1 : 0) + (have_ipv6 ? 1 : 0); servers = isc_mem_get(gmctx, ns_alloc * sizeof(isc_sockaddr_t)); if (servers == NULL) fatal("out of memory"); if (have_ipv4) { in.s_addr = htonl(INADDR_LOOPBACK); isc_sockaddr_fromin(&servers[0], &in, dnsport); } if (have_ipv6) { memset(&in6, 0, sizeof(in6)); in6.s6_addr[15] = 1; isc_sockaddr_fromin6(&servers[(have_ipv4 ? 1 : 0)], &in6, dnsport); } } else { ns_total = ns_alloc = lwconf->nsnext; servers = isc_mem_get(gmctx, ns_alloc * sizeof(isc_sockaddr_t)); if (servers == NULL) fatal("out of memory"); for (i = 0; i < ns_total; i++) { if (lwconf->nameservers[i].family == LWRES_ADDRTYPE_V4) { struct in_addr in4; memmove(&in4, lwconf->nameservers[i].address, 4); isc_sockaddr_fromin(&servers[i], &in4, dnsport); } else { struct in6_addr in6; memmove(&in6, lwconf->nameservers[i].address, 16); isc_sockaddr_fromin6(&servers[i], &in6, dnsport); } } } setup_entropy(gmctx, NULL, &entropy); result = isc_hash_create(gmctx, entropy, DNS_NAME_MAXWIRE); check_result(result, "isc_hash_create"); isc_hash_init(); result = dns_dispatchmgr_create(gmctx, entropy, &dispatchmgr); check_result(result, "dns_dispatchmgr_create"); result = isc_socketmgr_create(gmctx, &socketmgr); check_result(result, "dns_socketmgr_create"); result = isc_timermgr_create(gmctx, &timermgr); check_result(result, "dns_timermgr_create"); result = isc_taskmgr_create(gmctx, 1, 0, &taskmgr); check_result(result, "isc_taskmgr_create"); result = isc_task_create(taskmgr, 0, &global_task); check_result(result, "isc_task_create"); result = isc_task_onshutdown(global_task, shutdown_program, NULL); check_result(result, "isc_task_onshutdown"); result = dst_lib_init(gmctx, entropy, 0); check_result(result, "dst_lib_init"); is_dst_up = ISC_TRUE; attrmask = DNS_DISPATCHATTR_UDP | DNS_DISPATCHATTR_TCP; attrmask |= DNS_DISPATCHATTR_IPV4 | DNS_DISPATCHATTR_IPV6; if (have_ipv6) { attrs = DNS_DISPATCHATTR_UDP; attrs |= DNS_DISPATCHATTR_MAKEQUERY; attrs |= DNS_DISPATCHATTR_IPV6; isc_sockaddr_any6(&bind_any6); result = dns_dispatch_getudp(dispatchmgr, socketmgr, taskmgr, &bind_any6, PACKETSIZE, 4, 2, 3, 5, attrs, attrmask, &dispatchv6); check_result(result, "dns_dispatch_getudp (v6)"); } if (have_ipv4) { attrs = DNS_DISPATCHATTR_UDP; attrs |= DNS_DISPATCHATTR_MAKEQUERY; attrs |= DNS_DISPATCHATTR_IPV4; isc_sockaddr_any(&bind_any); result = dns_dispatch_getudp(dispatchmgr, socketmgr, taskmgr, &bind_any, PACKETSIZE, 4, 2, 3, 5, attrs, attrmask, &dispatchv4); check_result(result, "dns_dispatch_getudp (v4)"); } result = dns_requestmgr_create(gmctx, timermgr, socketmgr, taskmgr, dispatchmgr, dispatchv4, dispatchv6, &requestmgr); check_result(result, "dns_requestmgr_create"); if (keystr != NULL) setup_keystr(); else if (local_only) { result = read_sessionkey(gmctx, glctx); if (result != ISC_R_SUCCESS) fatal("can't read key from %s: %s\n", keyfile, isc_result_totext(result)); } else if (keyfile != NULL) setup_keyfile(gmctx, glctx); } static int get_addresses(char *host, in_port_t port, isc_sockaddr_t *sockaddr, int naddrs) { int count = 0; isc_result_t result; isc_app_block(); result = bind9_getaddresses(host, port, sockaddr, naddrs, &count); isc_app_unblock(); if (result != ISC_R_SUCCESS) error("couldn't get address for '%s': %s", host, isc_result_totext(result)); return (count); } static void version(void) { fputs("nsupdate " VERSION "\n", stderr); } #define PARSE_ARGS_FMT "dDML:y:ghilovk:p:Pr:R::t:Tu:V" static void pre_parse_args(int argc, char **argv) { dns_rdatatype_t t; int ch; char buf[100]; isc_boolean_t doexit = ISC_FALSE; while ((ch = isc_commandline_parse(argc, argv, PARSE_ARGS_FMT)) != -1) { switch (ch) { case 'M': /* was -dm */ debugging = ISC_TRUE; ddebugging = ISC_TRUE; memdebugging = ISC_TRUE; isc_mem_debugging = ISC_MEM_DEBUGTRACE | ISC_MEM_DEBUGRECORD; break; case '?': case 'h': if (isc_commandline_option != '?') fprintf(stderr, "%s: invalid argument -%c\n", argv[0], isc_commandline_option); fprintf(stderr, "usage: nsupdate [-dDi] [-L level] [-l]" "[-g | -o | -y keyname:secret | -k keyfile] " "[-v] [-V] [-P] [-T] [filename]\n"); exit(1); case 'P': for (t = 0xff00; t <= 0xfffe; t++) { if (dns_rdatatype_ismeta(t)) continue; dns_rdatatype_format(t, buf, sizeof(buf)); if (strncmp(buf, "TYPE", 4) != 0) fprintf(stdout, "%s\n", buf); } doexit = ISC_TRUE; break; case 'T': for (t = 1; t <= 0xfeff; t++) { if (dns_rdatatype_ismeta(t)) continue; dns_rdatatype_format(t, buf, sizeof(buf)); if (strncmp(buf, "TYPE", 4) != 0) fprintf(stdout, "%s\n", buf); } doexit = ISC_TRUE; break; case 'V': version(); doexit = ISC_TRUE; break; default: break; } } if (doexit) exit(0); isc_commandline_reset = ISC_TRUE; isc_commandline_index = 1; } static void parse_args(int argc, char **argv, isc_mem_t *mctx, isc_entropy_t **ectx) { int ch; isc_uint32_t i; isc_result_t result; isc_boolean_t force_interactive = ISC_FALSE; debug("parse_args"); while ((ch = isc_commandline_parse(argc, argv, PARSE_ARGS_FMT)) != -1) { switch (ch) { case 'd': debugging = ISC_TRUE; break; case 'D': /* was -dd */ debugging = ISC_TRUE; ddebugging = ISC_TRUE; break; case 'M': break; case 'i': force_interactive = ISC_TRUE; interactive = ISC_TRUE; break; case 'l': local_only = ISC_TRUE; break; case 'L': result = isc_parse_uint32(&i, isc_commandline_argument, 10); if (result != ISC_R_SUCCESS) { fprintf(stderr, "bad library debug value " "'%s'\n", isc_commandline_argument); exit(1); } logdebuglevel = i; break; case 'y': keystr = isc_commandline_argument; break; case 'v': usevc = ISC_TRUE; break; case 'k': keyfile = isc_commandline_argument; break; case 'g': usegsstsig = ISC_TRUE; use_win2k_gsstsig = ISC_FALSE; break; case 'o': usegsstsig = ISC_TRUE; use_win2k_gsstsig = ISC_TRUE; break; case 'p': result = isc_parse_uint16(&dnsport, isc_commandline_argument, 10); if (result != ISC_R_SUCCESS) { fprintf(stderr, "bad port number " "'%s'\n", isc_commandline_argument); exit(1); } break; case 't': result = isc_parse_uint32(&timeout, isc_commandline_argument, 10); if (result != ISC_R_SUCCESS) { fprintf(stderr, "bad timeout '%s'\n", isc_commandline_argument); exit(1); } if (timeout == 0) timeout = UINT_MAX; break; case 'u': result = isc_parse_uint32(&udp_timeout, isc_commandline_argument, 10); if (result != ISC_R_SUCCESS) { fprintf(stderr, "bad udp timeout '%s'\n", isc_commandline_argument); exit(1); } if (udp_timeout == 0) udp_timeout = UINT_MAX; break; case 'r': result = isc_parse_uint32(&udp_retries, isc_commandline_argument, 10); if (result != ISC_R_SUCCESS) { fprintf(stderr, "bad udp retries '%s'\n", isc_commandline_argument); exit(1); } break; case 'R': setup_entropy(mctx, isc_commandline_argument, ectx); break; default: fprintf(stderr, "%s: unhandled option: %c\n", argv[0], isc_commandline_option); exit(1); } } if (keyfile != NULL && keystr != NULL) { fprintf(stderr, "%s: cannot specify both -k and -y\n", argv[0]); exit(1); } #ifdef GSSAPI if (usegsstsig && (keyfile != NULL || keystr != NULL)) { fprintf(stderr, "%s: cannot specify -g with -k or -y\n", argv[0]); exit(1); } #else if (usegsstsig) { fprintf(stderr, "%s: cannot specify -g or -o, " \ "program not linked with GSS API Library\n", argv[0]); exit(1); } #endif if (argv[isc_commandline_index] != NULL) { if (strcmp(argv[isc_commandline_index], "-") == 0) { input = stdin; } else { result = isc_stdio_open(argv[isc_commandline_index], "r", &input); if (result != ISC_R_SUCCESS) { fprintf(stderr, "could not open '%s': %s\n", argv[isc_commandline_index], isc_result_totext(result)); exit(1); } } if (!force_interactive) { interactive = ISC_FALSE; } } } static isc_uint16_t parse_name(char **cmdlinep, dns_message_t *msg, dns_name_t **namep) { isc_result_t result; char *word; isc_buffer_t *namebuf = NULL; isc_buffer_t source; word = nsu_strsep(cmdlinep, " \t\r\n"); if (word == NULL || *word == 0) { fprintf(stderr, "could not read owner name\n"); return (STATUS_SYNTAX); } result = dns_message_gettempname(msg, namep); check_result(result, "dns_message_gettempname"); result = isc_buffer_allocate(gmctx, &namebuf, DNS_NAME_MAXWIRE); check_result(result, "isc_buffer_allocate"); dns_name_init(*namep, NULL); dns_name_setbuffer(*namep, namebuf); dns_message_takebuffer(msg, &namebuf); isc_buffer_init(&source, word, strlen(word)); isc_buffer_add(&source, strlen(word)); result = dns_name_fromtext(*namep, &source, dns_rootname, 0, NULL); if (result != ISC_R_SUCCESS) { error("invalid owner name: %s", isc_result_totext(result)); isc_buffer_invalidate(&source); dns_message_puttempname(msg, namep); return (STATUS_SYNTAX); } isc_buffer_invalidate(&source); return (STATUS_MORE); } static isc_uint16_t parse_rdata(char **cmdlinep, dns_rdataclass_t rdataclass, dns_rdatatype_t rdatatype, dns_message_t *msg, dns_rdata_t *rdata) { char *cmdline = *cmdlinep; isc_buffer_t source, *buf = NULL, *newbuf = NULL; isc_region_t r; isc_lex_t *lex = NULL; dns_rdatacallbacks_t callbacks; isc_result_t result; if (cmdline == NULL) { rdata->flags = DNS_RDATA_UPDATE; return (STATUS_MORE); } while (*cmdline != 0 && isspace((unsigned char)*cmdline)) cmdline++; if (*cmdline != 0) { dns_rdatacallbacks_init(&callbacks); result = isc_lex_create(gmctx, strlen(cmdline), &lex); check_result(result, "isc_lex_create"); isc_buffer_init(&source, cmdline, strlen(cmdline)); isc_buffer_add(&source, strlen(cmdline)); result = isc_lex_openbuffer(lex, &source); check_result(result, "isc_lex_openbuffer"); result = isc_buffer_allocate(gmctx, &buf, MAXWIRE); check_result(result, "isc_buffer_allocate"); result = dns_rdata_fromtext(NULL, rdataclass, rdatatype, lex, dns_rootname, 0, gmctx, buf, &callbacks); isc_lex_destroy(&lex); if (result == ISC_R_SUCCESS) { isc_buffer_usedregion(buf, &r); result = isc_buffer_allocate(gmctx, &newbuf, r.length); check_result(result, "isc_buffer_allocate"); isc_buffer_putmem(newbuf, r.base, r.length); isc_buffer_usedregion(newbuf, &r); dns_rdata_fromregion(rdata, rdataclass, rdatatype, &r); isc_buffer_free(&buf); dns_message_takebuffer(msg, &newbuf); } else { fprintf(stderr, "invalid rdata format: %s\n", isc_result_totext(result)); isc_buffer_free(&buf); return (STATUS_SYNTAX); } } else { rdata->flags = DNS_RDATA_UPDATE; } *cmdlinep = cmdline; return (STATUS_MORE); } static isc_uint16_t make_prereq(char *cmdline, isc_boolean_t ispositive, isc_boolean_t isrrset) { isc_result_t result; char *word; dns_name_t *name = NULL; isc_textregion_t region; dns_rdataset_t *rdataset = NULL; dns_rdatalist_t *rdatalist = NULL; dns_rdataclass_t rdataclass; dns_rdatatype_t rdatatype; dns_rdata_t *rdata = NULL; isc_uint16_t retval; ddebug("make_prereq()"); /* * Read the owner name */ retval = parse_name(&cmdline, updatemsg, &name); if (retval != STATUS_MORE) return (retval); /* * If this is an rrset prereq, read the class or type. */ if (isrrset) { word = nsu_strsep(&cmdline, " \t\r\n"); if (word == NULL || *word == 0) { fprintf(stderr, "could not read class or type\n"); goto failure; } region.base = word; region.length = strlen(word); result = dns_rdataclass_fromtext(&rdataclass, ®ion); if (result == ISC_R_SUCCESS) { if (!setzoneclass(rdataclass)) { fprintf(stderr, "class mismatch: %s\n", word); goto failure; } /* * Now read the type. */ word = nsu_strsep(&cmdline, " \t\r\n"); if (word == NULL || *word == 0) { fprintf(stderr, "could not read type\n"); goto failure; } region.base = word; region.length = strlen(word); result = dns_rdatatype_fromtext(&rdatatype, ®ion); if (result != ISC_R_SUCCESS) { fprintf(stderr, "invalid type: %s\n", word); goto failure; } } else { rdataclass = getzoneclass(); result = dns_rdatatype_fromtext(&rdatatype, ®ion); if (result != ISC_R_SUCCESS) { fprintf(stderr, "invalid type: %s\n", word); goto failure; } } } else rdatatype = dns_rdatatype_any; result = dns_message_gettemprdata(updatemsg, &rdata); check_result(result, "dns_message_gettemprdata"); dns_rdata_init(rdata); if (isrrset && ispositive) { retval = parse_rdata(&cmdline, rdataclass, rdatatype, updatemsg, rdata); if (retval != STATUS_MORE) goto failure; } else rdata->flags = DNS_RDATA_UPDATE; result = dns_message_gettemprdatalist(updatemsg, &rdatalist); check_result(result, "dns_message_gettemprdatalist"); result = dns_message_gettemprdataset(updatemsg, &rdataset); check_result(result, "dns_message_gettemprdataset"); rdatalist->type = rdatatype; if (ispositive) { if (isrrset && rdata->data != NULL) rdatalist->rdclass = rdataclass; else rdatalist->rdclass = dns_rdataclass_any; } else rdatalist->rdclass = dns_rdataclass_none; rdata->rdclass = rdatalist->rdclass; rdata->type = rdatatype; ISC_LIST_APPEND(rdatalist->rdata, rdata, link); dns_rdatalist_tordataset(rdatalist, rdataset); ISC_LIST_INIT(name->list); ISC_LIST_APPEND(name->list, rdataset, link); dns_message_addname(updatemsg, name, DNS_SECTION_PREREQUISITE); return (STATUS_MORE); failure: if (name != NULL) dns_message_puttempname(updatemsg, &name); return (STATUS_SYNTAX); } static isc_uint16_t evaluate_prereq(char *cmdline) { char *word; isc_boolean_t ispositive, isrrset; ddebug("evaluate_prereq()"); word = nsu_strsep(&cmdline, " \t\r\n"); if (word == NULL || *word == 0) { fprintf(stderr, "could not read operation code\n"); return (STATUS_SYNTAX); } if (strcasecmp(word, "nxdomain") == 0) { ispositive = ISC_FALSE; isrrset = ISC_FALSE; } else if (strcasecmp(word, "yxdomain") == 0) { ispositive = ISC_TRUE; isrrset = ISC_FALSE; } else if (strcasecmp(word, "nxrrset") == 0) { ispositive = ISC_FALSE; isrrset = ISC_TRUE; } else if (strcasecmp(word, "yxrrset") == 0) { ispositive = ISC_TRUE; isrrset = ISC_TRUE; } else { fprintf(stderr, "incorrect operation code: %s\n", word); return (STATUS_SYNTAX); } return (make_prereq(cmdline, ispositive, isrrset)); } static isc_uint16_t evaluate_server(char *cmdline) { char *word, *server; long port; if (local_only) { fprintf(stderr, "cannot reset server in localhost-only mode\n"); return (STATUS_SYNTAX); } word = nsu_strsep(&cmdline, " \t\r\n"); if (word == NULL || *word == 0) { fprintf(stderr, "could not read server name\n"); return (STATUS_SYNTAX); } server = word; word = nsu_strsep(&cmdline, " \t\r\n"); if (word == NULL || *word == 0) port = dnsport; else { char *endp; port = strtol(word, &endp, 10); if (*endp != 0) { fprintf(stderr, "port '%s' is not numeric\n", word); return (STATUS_SYNTAX); } else if (port < 1 || port > 65535) { fprintf(stderr, "port '%s' is out of range " "(1 to 65535)\n", word); return (STATUS_SYNTAX); } } if (servers != NULL) { if (master_servers == servers) master_servers = NULL; isc_mem_put(gmctx, servers, ns_alloc * sizeof(isc_sockaddr_t)); } default_servers = ISC_FALSE; ns_alloc = MAX_SERVERADDRS; ns_inuse = 0; servers = isc_mem_get(gmctx, ns_alloc * sizeof(isc_sockaddr_t)); if (servers == NULL) fatal("out of memory"); memset(servers, 0, ns_alloc * sizeof(isc_sockaddr_t)); ns_total = get_addresses(server, (in_port_t)port, servers, ns_alloc); if (ns_total == 0) { return (STATUS_SYNTAX); } return (STATUS_MORE); } static isc_uint16_t evaluate_local(char *cmdline) { char *word, *local; long port; struct in_addr in4; struct in6_addr in6; word = nsu_strsep(&cmdline, " \t\r\n"); if (word == NULL || *word == 0) { fprintf(stderr, "could not read server name\n"); return (STATUS_SYNTAX); } local = word; word = nsu_strsep(&cmdline, " \t\r\n"); if (word == NULL || *word == 0) port = 0; else { char *endp; port = strtol(word, &endp, 10); if (*endp != 0) { fprintf(stderr, "port '%s' is not numeric\n", word); return (STATUS_SYNTAX); } else if (port < 1 || port > 65535) { fprintf(stderr, "port '%s' is out of range " "(1 to 65535)\n", word); return (STATUS_SYNTAX); } } if (have_ipv6 && inet_pton(AF_INET6, local, &in6) == 1) { if (localaddr6 == NULL) localaddr6 = isc_mem_get(gmctx, sizeof(isc_sockaddr_t)); if (localaddr6 == NULL) fatal("out of memory"); isc_sockaddr_fromin6(localaddr6, &in6, (in_port_t)port); } else if (have_ipv4 && inet_pton(AF_INET, local, &in4) == 1) { if (localaddr4 == NULL) localaddr4 = isc_mem_get(gmctx, sizeof(isc_sockaddr_t)); if (localaddr4 == NULL) fatal("out of memory"); isc_sockaddr_fromin(localaddr4, &in4, (in_port_t)port); } else { fprintf(stderr, "invalid address %s", local); return (STATUS_SYNTAX); } return (STATUS_MORE); } static isc_uint16_t evaluate_key(char *cmdline) { char *namestr; char *secretstr; isc_buffer_t b; isc_result_t result; dns_fixedname_t fkeyname; dns_name_t *mykeyname; int secretlen; unsigned char *secret = NULL; isc_buffer_t secretbuf; dns_name_t *hmacname = NULL; isc_uint16_t digestbits = 0; char *n; namestr = nsu_strsep(&cmdline, " \t\r\n"); if (namestr == NULL || *namestr == 0) { fprintf(stderr, "could not read key name\n"); return (STATUS_SYNTAX); } dns_fixedname_init(&fkeyname); mykeyname = dns_fixedname_name(&fkeyname); n = strchr(namestr, ':'); if (n != NULL) { if (!parse_hmac(&hmacname, namestr, n - namestr, &digestbits)) { return (STATUS_SYNTAX); } namestr = n + 1; } else #ifndef PK11_MD5_DISABLE hmacname = DNS_TSIG_HMACMD5_NAME; #else hmacname = DNS_TSIG_HMACSHA256_NAME; #endif isc_buffer_init(&b, namestr, strlen(namestr)); isc_buffer_add(&b, strlen(namestr)); result = dns_name_fromtext(mykeyname, &b, dns_rootname, 0, NULL); if (result != ISC_R_SUCCESS) { fprintf(stderr, "could not parse key name\n"); return (STATUS_SYNTAX); } secretstr = nsu_strsep(&cmdline, "\r\n"); if (secretstr == NULL || *secretstr == 0) { fprintf(stderr, "could not read key secret\n"); return (STATUS_SYNTAX); } secretlen = strlen(secretstr) * 3 / 4; secret = isc_mem_allocate(gmctx, secretlen); if (secret == NULL) fatal("out of memory"); isc_buffer_init(&secretbuf, secret, secretlen); result = isc_base64_decodestring(secretstr, &secretbuf); if (result != ISC_R_SUCCESS) { fprintf(stderr, "could not create key from %s: %s\n", secretstr, isc_result_totext(result)); isc_mem_free(gmctx, secret); return (STATUS_SYNTAX); } secretlen = isc_buffer_usedlength(&secretbuf); if (tsigkey != NULL) dns_tsigkey_detach(&tsigkey); result = dns_tsigkey_create(mykeyname, hmacname, secret, secretlen, ISC_FALSE, NULL, 0, 0, gmctx, NULL, &tsigkey); isc_mem_free(gmctx, secret); if (result != ISC_R_SUCCESS) { fprintf(stderr, "could not create key from %s %s: %s\n", namestr, secretstr, dns_result_totext(result)); return (STATUS_SYNTAX); } dst_key_setbits(tsigkey->key, digestbits); return (STATUS_MORE); } static isc_uint16_t evaluate_zone(char *cmdline) { char *word; isc_buffer_t b; isc_result_t result; word = nsu_strsep(&cmdline, " \t\r\n"); if (word == NULL || *word == 0) { fprintf(stderr, "could not read zone name\n"); return (STATUS_SYNTAX); } dns_fixedname_init(&fuserzone); userzone = dns_fixedname_name(&fuserzone); isc_buffer_init(&b, word, strlen(word)); isc_buffer_add(&b, strlen(word)); result = dns_name_fromtext(userzone, &b, dns_rootname, 0, NULL); if (result != ISC_R_SUCCESS) { userzone = NULL; /* Lest it point to an invalid name */ fprintf(stderr, "could not parse zone name\n"); return (STATUS_SYNTAX); } return (STATUS_MORE); } static isc_uint16_t evaluate_realm(char *cmdline) { #ifdef GSSAPI char *word; char buf[1024]; int n; if (realm != NULL) { isc_mem_free(gmctx, realm); realm = NULL; } word = nsu_strsep(&cmdline, " \t\r\n"); if (word == NULL || *word == 0) return (STATUS_MORE); n = snprintf(buf, sizeof(buf), "@%s", word); if (n < 0 || (size_t)n >= sizeof(buf)) { error("realm is too long"); return (STATUS_SYNTAX); } realm = isc_mem_strdup(gmctx, buf); if (realm == NULL) fatal("out of memory"); return (STATUS_MORE); #else UNUSED(cmdline); return (STATUS_SYNTAX); #endif } static isc_uint16_t evaluate_ttl(char *cmdline) { char *word; isc_result_t result; isc_uint32_t ttl; word = nsu_strsep(&cmdline, " \t\r\n"); if (word == NULL || *word == 0) { fprintf(stderr, "could not read ttl\n"); return (STATUS_SYNTAX); } if (!strcasecmp(word, "none")) { default_ttl = 0; default_ttl_set = ISC_FALSE; return (STATUS_MORE); } result = isc_parse_uint32(&ttl, word, 10); if (result != ISC_R_SUCCESS) return (STATUS_SYNTAX); if (ttl > TTL_MAX) { fprintf(stderr, "ttl '%s' is out of range (0 to %u)\n", word, TTL_MAX); return (STATUS_SYNTAX); } default_ttl = ttl; default_ttl_set = ISC_TRUE; return (STATUS_MORE); } static isc_uint16_t evaluate_class(char *cmdline) { char *word; isc_textregion_t r; isc_result_t result; dns_rdataclass_t rdclass; word = nsu_strsep(&cmdline, " \t\r\n"); if (word == NULL || *word == 0) { fprintf(stderr, "could not read class name\n"); return (STATUS_SYNTAX); } r.base = word; r.length = strlen(word); result = dns_rdataclass_fromtext(&rdclass, &r); if (result != ISC_R_SUCCESS) { fprintf(stderr, "could not parse class name: %s\n", word); return (STATUS_SYNTAX); } switch (rdclass) { case dns_rdataclass_none: case dns_rdataclass_any: case dns_rdataclass_reserved0: fprintf(stderr, "bad default class: %s\n", word); return (STATUS_SYNTAX); default: defaultclass = rdclass; } return (STATUS_MORE); } static isc_uint16_t update_addordelete(char *cmdline, isc_boolean_t isdelete) { isc_result_t result; dns_name_t *name = NULL; isc_uint32_t ttl; char *word; dns_rdataclass_t rdataclass; dns_rdatatype_t rdatatype; dns_rdata_t *rdata = NULL; dns_rdatalist_t *rdatalist = NULL; dns_rdataset_t *rdataset = NULL; isc_textregion_t region; isc_uint16_t retval; ddebug("update_addordelete()"); /* * Read the owner name. */ retval = parse_name(&cmdline, updatemsg, &name); if (retval != STATUS_MORE) return (retval); result = dns_message_gettemprdata(updatemsg, &rdata); check_result(result, "dns_message_gettemprdata"); dns_rdata_init(rdata); /* * If this is an add, read the TTL and verify that it's in range. * If it's a delete, ignore a TTL if present (for compatibility). */ word = nsu_strsep(&cmdline, " \t\r\n"); if (word == NULL || *word == 0) { if (!isdelete) { fprintf(stderr, "could not read owner ttl\n"); goto failure; } else { ttl = 0; rdataclass = dns_rdataclass_any; rdatatype = dns_rdatatype_any; rdata->flags = DNS_RDATA_UPDATE; goto doneparsing; } } result = isc_parse_uint32(&ttl, word, 10); if (result != ISC_R_SUCCESS) { if (isdelete) { ttl = 0; goto parseclass; } else if (default_ttl_set) { ttl = default_ttl; goto parseclass; } else { fprintf(stderr, "ttl '%s': %s\n", word, isc_result_totext(result)); goto failure; } } if (isdelete) ttl = 0; else if (ttl > TTL_MAX) { fprintf(stderr, "ttl '%s' is out of range (0 to %u)\n", word, TTL_MAX); goto failure; } /* * Read the class or type. */ word = nsu_strsep(&cmdline, " \t\r\n"); parseclass: if (word == NULL || *word == 0) { if (isdelete) { rdataclass = dns_rdataclass_any; rdatatype = dns_rdatatype_any; rdata->flags = DNS_RDATA_UPDATE; goto doneparsing; } else { fprintf(stderr, "could not read class or type\n"); goto failure; } } region.base = word; region.length = strlen(word); rdataclass = dns_rdataclass_any; result = dns_rdataclass_fromtext(&rdataclass, ®ion); if (result == ISC_R_SUCCESS && rdataclass != dns_rdataclass_any) { if (!setzoneclass(rdataclass)) { fprintf(stderr, "class mismatch: %s\n", word); goto failure; } /* * Now read the type. */ word = nsu_strsep(&cmdline, " \t\r\n"); if (word == NULL || *word == 0) { if (isdelete) { rdataclass = dns_rdataclass_any; rdatatype = dns_rdatatype_any; rdata->flags = DNS_RDATA_UPDATE; goto doneparsing; } else { fprintf(stderr, "could not read type\n"); goto failure; } } region.base = word; region.length = strlen(word); result = dns_rdatatype_fromtext(&rdatatype, ®ion); if (result != ISC_R_SUCCESS) { fprintf(stderr, "'%s' is not a valid type: %s\n", word, isc_result_totext(result)); goto failure; } } else { rdataclass = getzoneclass(); result = dns_rdatatype_fromtext(&rdatatype, ®ion); if (result != ISC_R_SUCCESS) { fprintf(stderr, "'%s' is not a valid class or type: " "%s\n", word, isc_result_totext(result)); goto failure; } } retval = parse_rdata(&cmdline, rdataclass, rdatatype, updatemsg, rdata); if (retval != STATUS_MORE) goto failure; if (isdelete) { if ((rdata->flags & DNS_RDATA_UPDATE) != 0) rdataclass = dns_rdataclass_any; else rdataclass = dns_rdataclass_none; } else { if ((rdata->flags & DNS_RDATA_UPDATE) != 0) { fprintf(stderr, "could not read rdata\n"); goto failure; } } if (!isdelete && checknames) { dns_fixedname_t fixed; dns_name_t *bad; if (!dns_rdata_checkowner(name, rdata->rdclass, rdata->type, ISC_TRUE)) { char namebuf[DNS_NAME_FORMATSIZE]; dns_name_format(name, namebuf, sizeof(namebuf)); fprintf(stderr, "check-names failed: bad owner '%s'\n", namebuf); goto failure; } dns_fixedname_init(&fixed); bad = dns_fixedname_name(&fixed); if (!dns_rdata_checknames(rdata, name, bad)) { char namebuf[DNS_NAME_FORMATSIZE]; dns_name_format(bad, namebuf, sizeof(namebuf)); fprintf(stderr, "check-names failed: bad name '%s'\n", namebuf); goto failure; } } doneparsing: result = dns_message_gettemprdatalist(updatemsg, &rdatalist); check_result(result, "dns_message_gettemprdatalist"); result = dns_message_gettemprdataset(updatemsg, &rdataset); check_result(result, "dns_message_gettemprdataset"); rdatalist->type = rdatatype; rdatalist->rdclass = rdataclass; rdatalist->covers = rdatatype; rdatalist->ttl = (dns_ttl_t)ttl; ISC_LIST_APPEND(rdatalist->rdata, rdata, link); dns_rdatalist_tordataset(rdatalist, rdataset); ISC_LIST_INIT(name->list); ISC_LIST_APPEND(name->list, rdataset, link); dns_message_addname(updatemsg, name, DNS_SECTION_UPDATE); return (STATUS_MORE); failure: if (name != NULL) dns_message_puttempname(updatemsg, &name); dns_message_puttemprdata(updatemsg, &rdata); return (STATUS_SYNTAX); } static isc_uint16_t evaluate_update(char *cmdline) { char *word; isc_boolean_t isdelete; ddebug("evaluate_update()"); word = nsu_strsep(&cmdline, " \t\r\n"); if (word == NULL || *word == 0) { fprintf(stderr, "could not read operation code\n"); return (STATUS_SYNTAX); } if (strcasecmp(word, "delete") == 0) isdelete = ISC_TRUE; else if (strcasecmp(word, "del") == 0) isdelete = ISC_TRUE; else if (strcasecmp(word, "add") == 0) isdelete = ISC_FALSE; else { fprintf(stderr, "incorrect operation code: %s\n", word); return (STATUS_SYNTAX); } return (update_addordelete(cmdline, isdelete)); } static isc_uint16_t evaluate_checknames(char *cmdline) { char *word; ddebug("evaluate_checknames()"); word = nsu_strsep(&cmdline, " \t\r\n"); if (word == NULL || *word == 0) { fprintf(stderr, "could not read check-names directive\n"); return (STATUS_SYNTAX); } if (strcasecmp(word, "yes") == 0 || strcasecmp(word, "true") == 0 || strcasecmp(word, "on") == 0) { checknames = ISC_TRUE; } else if (strcasecmp(word, "no") == 0 || strcasecmp(word, "false") == 0 || strcasecmp(word, "off") == 0) { checknames = ISC_FALSE; } else { fprintf(stderr, "incorrect check-names directive: %s\n", word); return (STATUS_SYNTAX); } return (STATUS_MORE); } static void setzone(dns_name_t *zonename) { isc_result_t result; dns_name_t *name = NULL; dns_rdataset_t *rdataset = NULL; result = dns_message_firstname(updatemsg, DNS_SECTION_ZONE); if (result == ISC_R_SUCCESS) { dns_message_currentname(updatemsg, DNS_SECTION_ZONE, &name); dns_message_removename(updatemsg, name, DNS_SECTION_ZONE); for (rdataset = ISC_LIST_HEAD(name->list); rdataset != NULL; rdataset = ISC_LIST_HEAD(name->list)) { ISC_LIST_UNLINK(name->list, rdataset, link); dns_rdataset_disassociate(rdataset); dns_message_puttemprdataset(updatemsg, &rdataset); } dns_message_puttempname(updatemsg, &name); } if (zonename != NULL) { result = dns_message_gettempname(updatemsg, &name); check_result(result, "dns_message_gettempname"); dns_name_init(name, NULL); dns_name_clone(zonename, name); result = dns_message_gettemprdataset(updatemsg, &rdataset); check_result(result, "dns_message_gettemprdataset"); dns_rdataset_makequestion(rdataset, getzoneclass(), dns_rdatatype_soa); ISC_LIST_INIT(name->list); ISC_LIST_APPEND(name->list, rdataset, link); dns_message_addname(updatemsg, name, DNS_SECTION_ZONE); } } static void show_message(FILE *stream, dns_message_t *msg, const char *description) { isc_result_t result; isc_buffer_t *buf = NULL; int bufsz; ddebug("show_message()"); setzone(userzone); bufsz = INITTEXT; do { if (bufsz > MAXTEXT) { fprintf(stderr, "could not allocate large enough " "buffer to display message\n"); exit(1); } if (buf != NULL) isc_buffer_free(&buf); result = isc_buffer_allocate(gmctx, &buf, bufsz); check_result(result, "isc_buffer_allocate"); result = dns_message_totext(msg, style, 0, buf); bufsz *= 2; } while (result == ISC_R_NOSPACE); if (result != ISC_R_SUCCESS) { fprintf(stderr, "could not convert message to text format.\n"); isc_buffer_free(&buf); return; } fprintf(stream, "%s\n%.*s", description, (int)isc_buffer_usedlength(buf), (char*)isc_buffer_base(buf)); fflush(stream); isc_buffer_free(&buf); } static isc_uint16_t do_next_command(char *cmdline) { char *word; ddebug("do_next_command()"); word = nsu_strsep(&cmdline, " \t\r\n"); if (word == NULL || *word == 0) return (STATUS_SEND); if (word[0] == ';') return (STATUS_MORE); if (strcasecmp(word, "quit") == 0) return (STATUS_QUIT); if (strcasecmp(word, "prereq") == 0) return (evaluate_prereq(cmdline)); if (strcasecmp(word, "nxdomain") == 0) return (make_prereq(cmdline, ISC_FALSE, ISC_FALSE)); if (strcasecmp(word, "yxdomain") == 0) return (make_prereq(cmdline, ISC_TRUE, ISC_FALSE)); if (strcasecmp(word, "nxrrset") == 0) return (make_prereq(cmdline, ISC_FALSE, ISC_TRUE)); if (strcasecmp(word, "yxrrset") == 0) return (make_prereq(cmdline, ISC_TRUE, ISC_TRUE)); if (strcasecmp(word, "update") == 0) return (evaluate_update(cmdline)); if (strcasecmp(word, "delete") == 0) return (update_addordelete(cmdline, ISC_TRUE)); if (strcasecmp(word, "del") == 0) return (update_addordelete(cmdline, ISC_TRUE)); if (strcasecmp(word, "add") == 0) return (update_addordelete(cmdline, ISC_FALSE)); if (strcasecmp(word, "server") == 0) return (evaluate_server(cmdline)); if (strcasecmp(word, "local") == 0) return (evaluate_local(cmdline)); if (strcasecmp(word, "zone") == 0) return (evaluate_zone(cmdline)); if (strcasecmp(word, "class") == 0) return (evaluate_class(cmdline)); if (strcasecmp(word, "send") == 0) return (STATUS_SEND); if (strcasecmp(word, "debug") == 0) { if (debugging) ddebugging = ISC_TRUE; else debugging = ISC_TRUE; return (STATUS_MORE); } if (strcasecmp(word, "ttl") == 0) return (evaluate_ttl(cmdline)); if (strcasecmp(word, "show") == 0) { show_message(stdout, updatemsg, "Outgoing update query:"); return (STATUS_MORE); } if (strcasecmp(word, "answer") == 0) { if (answer != NULL) show_message(stdout, answer, "Answer:"); return (STATUS_MORE); } if (strcasecmp(word, "key") == 0) { usegsstsig = ISC_FALSE; return (evaluate_key(cmdline)); } if (strcasecmp(word, "realm") == 0) return (evaluate_realm(cmdline)); if (strcasecmp(word, "check-names") == 0 || strcasecmp(word, "checknames") == 0) return (evaluate_checknames(cmdline)); if (strcasecmp(word, "gsstsig") == 0) { #ifdef GSSAPI usegsstsig = ISC_TRUE; use_win2k_gsstsig = ISC_FALSE; #else fprintf(stderr, "gsstsig not supported\n"); #endif return (STATUS_MORE); } if (strcasecmp(word, "oldgsstsig") == 0) { #ifdef GSSAPI usegsstsig = ISC_TRUE; use_win2k_gsstsig = ISC_TRUE; #else fprintf(stderr, "gsstsig not supported\n"); #endif return (STATUS_MORE); } if (strcasecmp(word, "help") == 0) { fprintf(stdout, "nsupdate " VERSION ":\n" "local address [port] (set local resolver)\n" "server address [port] (set master server for zone)\n" "send (send the update request)\n" "show (show the update request)\n" "answer (show the answer to the last request)\n" "quit (quit, any pending update is not sent\n" "help (display this message_\n" "key [hmac:]keyname secret (use TSIG to sign the request)\n" "gsstsig (use GSS_TSIG to sign the request)\n" "oldgsstsig (use Microsoft's GSS_TSIG to sign the request)\n" "zone name (set the zone to be updated)\n" "class CLASS (set the zone's DNS class, e.g. IN (default), CH)\n" "check-names { on | off } (enable / disable check-names)\n" "[prereq] nxdomain name (require that this name does not exist)\n" "[prereq] yxdomain name (require that this name exists)\n" "[prereq] nxrrset .... (require that this RRset does not exist)\n" "[prereq] yxrrset .... (require that this RRset exists)\n" "[update] add .... (add the given record to the zone)\n" "[update] del[ete] .... (remove the given record(s) from the zone)\n"); return (STATUS_MORE); } if (strcasecmp(word, "version") == 0) { fprintf(stdout, "nsupdate " VERSION "\n"); return (STATUS_MORE); } fprintf(stderr, "incorrect section name: %s\n", word); return (STATUS_SYNTAX); } static isc_uint16_t get_next_command(void) { isc_uint16_t result = STATUS_QUIT; char cmdlinebuf[MAXCMD]; char *cmdline; isc_app_block(); if (interactive) { #ifdef HAVE_READLINE cmdline = readline("> "); if (cmdline != NULL) add_history(cmdline); #else fprintf(stdout, "> "); fflush(stdout); cmdline = fgets(cmdlinebuf, MAXCMD, input); #endif } else cmdline = fgets(cmdlinebuf, MAXCMD, input); isc_app_unblock(); if (cmdline != NULL) { char *tmp = cmdline; /* * Normalize input by removing any eol as readline() * removes eol but fgets doesn't. */ (void)nsu_strsep(&tmp, "\r\n"); result = do_next_command(cmdline); } #ifdef HAVE_READLINE if (interactive) free(cmdline); #endif return (result); } static isc_boolean_t user_interaction(void) { isc_uint16_t result = STATUS_MORE; ddebug("user_interaction()"); while ((result == STATUS_MORE) || (result == STATUS_SYNTAX)) { result = get_next_command(); if (!interactive && result == STATUS_SYNTAX) fatal("syntax error"); } if (result == STATUS_SEND) return (ISC_TRUE); return (ISC_FALSE); } static void done_update(void) { isc_event_t *event = global_event; ddebug("done_update()"); isc_task_send(global_task, &event); } static void check_tsig_error(dns_rdataset_t *rdataset, isc_buffer_t *b) { isc_result_t result; dns_rdata_t rdata = DNS_RDATA_INIT; dns_rdata_any_tsig_t tsig; result = dns_rdataset_first(rdataset); check_result(result, "dns_rdataset_first"); dns_rdataset_current(rdataset, &rdata); result = dns_rdata_tostruct(&rdata, &tsig, NULL); check_result(result, "dns_rdata_tostruct"); if (tsig.error != 0) { if (isc_buffer_remaininglength(b) < 1) check_result(ISC_R_NOSPACE, "isc_buffer_remaininglength"); isc_buffer_putstr(b, "(" /*)*/); result = dns_tsigrcode_totext(tsig.error, b); check_result(result, "dns_tsigrcode_totext"); if (isc_buffer_remaininglength(b) < 1) check_result(ISC_R_NOSPACE, "isc_buffer_remaininglength"); isc_buffer_putstr(b, /*(*/ ")"); } } static isc_boolean_t next_master(const char *caller, isc_sockaddr_t *addr, isc_result_t eresult) { char addrbuf[ISC_SOCKADDR_FORMATSIZE]; isc_sockaddr_format(addr, addrbuf, sizeof(addrbuf)); fprintf(stderr, "; Communication with %s failed: %s\n", addrbuf, isc_result_totext(eresult)); if (++master_inuse >= master_total) return (ISC_FALSE); ddebug("%s: trying next server", caller); return (ISC_TRUE); } static void update_completed(isc_task_t *task, isc_event_t *event) { dns_requestevent_t *reqev = NULL; isc_result_t result; dns_request_t *request; UNUSED(task); ddebug("update_completed()"); requests--; REQUIRE(event->ev_type == DNS_EVENT_REQUESTDONE); reqev = (dns_requestevent_t *)event; request = reqev->request; if (shuttingdown) { dns_request_destroy(&request); isc_event_free(&event); maybeshutdown(); return; } if (reqev->result != ISC_R_SUCCESS) { if (!next_master("update_completed", &master_servers[master_inuse], reqev->result)) { seenerror = ISC_TRUE; goto done; } ddebug("Destroying request [%p]", request); dns_request_destroy(&request); dns_message_renderreset(updatemsg); dns_message_settsigkey(updatemsg, NULL); send_update(zname, &master_servers[master_inuse]); isc_event_free(&event); return; } result = dns_message_create(gmctx, DNS_MESSAGE_INTENTPARSE, &answer); check_result(result, "dns_message_create"); result = dns_request_getresponse(request, answer, DNS_MESSAGEPARSE_PRESERVEORDER); switch (result) { case ISC_R_SUCCESS: if (answer->verify_attempted) ddebug("tsig verification successful"); break; case DNS_R_CLOCKSKEW: case DNS_R_EXPECTEDTSIG: case DNS_R_TSIGERRORSET: case DNS_R_TSIGVERIFYFAILURE: case DNS_R_UNEXPECTEDTSIG: case ISC_R_FAILURE: #if 0 if (usegsstsig && answer->rcode == dns_rcode_noerror) { /* * For MS DNS that violates RFC 2845, section 4.2 */ break; } #endif fprintf(stderr, "; TSIG error with server: %s\n", isc_result_totext(result)); seenerror = ISC_TRUE; break; default: check_result(result, "dns_request_getresponse"); } if (answer->rcode != dns_rcode_noerror) { seenerror = ISC_TRUE; if (!debugging) { char buf[64]; isc_buffer_t b; dns_rdataset_t *rds; isc_buffer_init(&b, buf, sizeof(buf) - 1); result = dns_rcode_totext(answer->rcode, &b); check_result(result, "dns_rcode_totext"); rds = dns_message_gettsig(answer, NULL); if (rds != NULL) check_tsig_error(rds, &b); fprintf(stderr, "update failed: %.*s\n", (int)isc_buffer_usedlength(&b), buf); } } if (debugging) show_message(stderr, answer, "\nReply from update query:"); done: dns_request_destroy(&request); if (usegsstsig) { dns_name_free(&tmpzonename, gmctx); dns_name_free(&restart_master, gmctx); } isc_event_free(&event); done_update(); } static void send_update(dns_name_t *zone, isc_sockaddr_t *master) { isc_result_t result; dns_request_t *request = NULL; unsigned int options = DNS_REQUESTOPT_CASE; isc_sockaddr_t *srcaddr; ddebug("send_update()"); setzone(zone); if (usevc) options |= DNS_REQUESTOPT_TCP; if (tsigkey == NULL && sig0key != NULL) { result = dns_message_setsig0key(updatemsg, sig0key); check_result(result, "dns_message_setsig0key"); } if (debugging) { char addrbuf[ISC_SOCKADDR_FORMATSIZE]; isc_sockaddr_format(master, addrbuf, sizeof(addrbuf)); fprintf(stderr, "Sending update to %s\n", addrbuf); } if (isc_sockaddr_pf(master) == AF_INET6) srcaddr = localaddr6; else srcaddr = localaddr4; /* Windows doesn't like the tsig name to be compressed. */ if (updatemsg->tsigname) updatemsg->tsigname->attributes |= DNS_NAMEATTR_NOCOMPRESS; result = dns_request_createvia3(requestmgr, updatemsg, srcaddr, master, options, tsigkey, timeout, udp_timeout, udp_retries, global_task, update_completed, NULL, &request); check_result(result, "dns_request_createvia3"); if (debugging) show_message(stdout, updatemsg, "Outgoing update query:"); requests++; } static void next_server(const char *caller, isc_sockaddr_t *addr, isc_result_t eresult) { char addrbuf[ISC_SOCKADDR_FORMATSIZE]; isc_sockaddr_format(addr, addrbuf, sizeof(addrbuf)); fprintf(stderr, "; Communication with %s failed: %s\n", addrbuf, isc_result_totext(eresult)); if (++ns_inuse >= ns_total) fatal("could not reach any name server"); else ddebug("%s: trying next server", caller); } static void recvsoa(isc_task_t *task, isc_event_t *event) { dns_requestevent_t *reqev = NULL; dns_request_t *request = NULL; isc_result_t result, eresult; dns_message_t *rcvmsg = NULL; dns_section_t section; dns_name_t *name = NULL; dns_rdataset_t *soaset = NULL; dns_rdata_soa_t soa; dns_rdata_t soarr = DNS_RDATA_INIT; int pass = 0; dns_name_t master; nsu_requestinfo_t *reqinfo; dns_message_t *soaquery = NULL; isc_sockaddr_t *addr; isc_sockaddr_t *srcaddr; isc_boolean_t seencname = ISC_FALSE; dns_name_t tname; unsigned int nlabels; UNUSED(task); ddebug("recvsoa()"); requests--; REQUIRE(event->ev_type == DNS_EVENT_REQUESTDONE); reqev = (dns_requestevent_t *)event; request = reqev->request; eresult = reqev->result; reqinfo = reqev->ev_arg; soaquery = reqinfo->msg; addr = reqinfo->addr; if (shuttingdown) { dns_request_destroy(&request); dns_message_destroy(&soaquery); isc_mem_put(gmctx, reqinfo, sizeof(nsu_requestinfo_t)); isc_event_free(&event); maybeshutdown(); return; } if (eresult != ISC_R_SUCCESS) { next_server("recvsoa", addr, eresult); ddebug("Destroying request [%p]", request); dns_request_destroy(&request); dns_message_renderreset(soaquery); dns_message_settsigkey(soaquery, NULL); sendrequest(&servers[ns_inuse], soaquery, &request); isc_mem_put(gmctx, reqinfo, sizeof(nsu_requestinfo_t)); isc_event_free(&event); setzoneclass(dns_rdataclass_none); return; } isc_mem_put(gmctx, reqinfo, sizeof(nsu_requestinfo_t)); reqinfo = NULL; isc_event_free(&event); reqev = NULL; ddebug("About to create rcvmsg"); result = dns_message_create(gmctx, DNS_MESSAGE_INTENTPARSE, &rcvmsg); check_result(result, "dns_message_create"); result = dns_request_getresponse(request, rcvmsg, DNS_MESSAGEPARSE_PRESERVEORDER); if (result == DNS_R_TSIGERRORSET && servers != NULL) { dns_message_destroy(&rcvmsg); ddebug("Destroying request [%p]", request); dns_request_destroy(&request); reqinfo = isc_mem_get(gmctx, sizeof(nsu_requestinfo_t)); if (reqinfo == NULL) fatal("out of memory"); reqinfo->msg = soaquery; reqinfo->addr = addr; dns_message_renderreset(soaquery); ddebug("retrying soa request without TSIG"); if (isc_sockaddr_pf(addr) == AF_INET6) srcaddr = localaddr6; else srcaddr = localaddr4; result = dns_request_createvia3(requestmgr, soaquery, srcaddr, addr, 0, NULL, FIND_TIMEOUT * 20, FIND_TIMEOUT, 3, global_task, recvsoa, reqinfo, &request); check_result(result, "dns_request_createvia3"); requests++; return; } check_result(result, "dns_request_getresponse"); section = DNS_SECTION_ANSWER; POST(section); if (debugging) show_message(stderr, rcvmsg, "Reply from SOA query:"); if (rcvmsg->rcode != dns_rcode_noerror && rcvmsg->rcode != dns_rcode_nxdomain) fatal("response to SOA query was unsuccessful"); if (userzone != NULL && rcvmsg->rcode == dns_rcode_nxdomain) { char namebuf[DNS_NAME_FORMATSIZE]; dns_name_format(userzone, namebuf, sizeof(namebuf)); error("specified zone '%s' does not exist (NXDOMAIN)", namebuf); dns_message_destroy(&rcvmsg); dns_request_destroy(&request); dns_message_destroy(&soaquery); ddebug("Out of recvsoa"); done_update(); seenerror = ISC_TRUE; return; } lookforsoa: if (pass == 0) section = DNS_SECTION_ANSWER; else if (pass == 1) section = DNS_SECTION_AUTHORITY; else goto droplabel; result = dns_message_firstname(rcvmsg, section); if (result != ISC_R_SUCCESS) { pass++; goto lookforsoa; } while (result == ISC_R_SUCCESS) { name = NULL; dns_message_currentname(rcvmsg, section, &name); soaset = NULL; result = dns_message_findtype(name, dns_rdatatype_soa, 0, &soaset); if (result == ISC_R_SUCCESS) break; if (section == DNS_SECTION_ANSWER) { dns_rdataset_t *tset = NULL; if (dns_message_findtype(name, dns_rdatatype_cname, 0, &tset) == ISC_R_SUCCESS || dns_message_findtype(name, dns_rdatatype_dname, 0, &tset) == ISC_R_SUCCESS ) { seencname = ISC_TRUE; break; } } result = dns_message_nextname(rcvmsg, section); } if (soaset == NULL && !seencname) { pass++; goto lookforsoa; } if (seencname) goto droplabel; if (debugging) { char namestr[DNS_NAME_FORMATSIZE]; dns_name_format(name, namestr, sizeof(namestr)); fprintf(stderr, "Found zone name: %s\n", namestr); } result = dns_rdataset_first(soaset); check_result(result, "dns_rdataset_first"); dns_rdata_init(&soarr); dns_rdataset_current(soaset, &soarr); result = dns_rdata_tostruct(&soarr, &soa, NULL); check_result(result, "dns_rdata_tostruct"); dns_name_init(&master, NULL); dns_name_clone(&soa.origin, &master); if (userzone != NULL) { zname = userzone; } else { /* * Save the zone name in case we need to try a second * address. */ dns_fixedname_init(&fzname); zname = dns_fixedname_name(&fzname); dns_name_copy(name, zname, NULL); } if (debugging) { char namestr[DNS_NAME_FORMATSIZE]; dns_name_format(&master, namestr, sizeof(namestr)); fprintf(stderr, "The master is: %s\n", namestr); } if (default_servers) { char serverstr[DNS_NAME_MAXTEXT+1]; isc_buffer_t buf; size_t size; isc_buffer_init(&buf, serverstr, sizeof(serverstr)); result = dns_name_totext(&master, ISC_TRUE, &buf); check_result(result, "dns_name_totext"); serverstr[isc_buffer_usedlength(&buf)] = 0; if (master_servers != NULL && master_servers != servers) isc_mem_put(gmctx, master_servers, master_alloc * sizeof(isc_sockaddr_t)); master_alloc = MAX_SERVERADDRS; size = master_alloc * sizeof(isc_sockaddr_t); master_servers = isc_mem_get(gmctx, size); if (master_servers == NULL) fatal("out of memory"); memset(master_servers, 0, size); master_total = get_addresses(serverstr, dnsport, master_servers, master_alloc); if (master_total == 0) { exit(1); } master_inuse = 0; } else master_from_servers(); dns_rdata_freestruct(&soa); #ifdef GSSAPI if (usegsstsig) { dns_name_init(&tmpzonename, NULL); dns_name_dup(zname, gmctx, &tmpzonename); dns_name_init(&restart_master, NULL); dns_name_dup(&master, gmctx, &restart_master); start_gssrequest(&master); } else { send_update(zname, &master_servers[master_inuse]); setzoneclass(dns_rdataclass_none); } #else send_update(zname, &master_servers[master_inuse]); setzoneclass(dns_rdataclass_none); #endif dns_message_destroy(&soaquery); dns_request_destroy(&request); out: dns_message_destroy(&rcvmsg); ddebug("Out of recvsoa"); return; droplabel: result = dns_message_firstname(soaquery, DNS_SECTION_QUESTION); INSIST(result == ISC_R_SUCCESS); name = NULL; dns_message_currentname(soaquery, DNS_SECTION_QUESTION, &name); nlabels = dns_name_countlabels(name); if (nlabels == 1) fatal("could not find enclosing zone"); dns_name_init(&tname, NULL); dns_name_getlabelsequence(name, 1, nlabels - 1, &tname); dns_name_clone(&tname, name); dns_request_destroy(&request); dns_message_renderreset(soaquery); dns_message_settsigkey(soaquery, NULL); sendrequest(&servers[ns_inuse], soaquery, &request); goto out; } static void sendrequest(isc_sockaddr_t *destaddr, dns_message_t *msg, dns_request_t **request) { isc_result_t result; nsu_requestinfo_t *reqinfo; isc_sockaddr_t *srcaddr; reqinfo = isc_mem_get(gmctx, sizeof(nsu_requestinfo_t)); if (reqinfo == NULL) fatal("out of memory"); reqinfo->msg = msg; reqinfo->addr = destaddr; if (isc_sockaddr_pf(destaddr) == AF_INET6) srcaddr = localaddr6; else srcaddr = localaddr4; result = dns_request_createvia3(requestmgr, msg, srcaddr, destaddr, 0, default_servers ? NULL : tsigkey, FIND_TIMEOUT * 20, FIND_TIMEOUT, 3, global_task, recvsoa, reqinfo, request); check_result(result, "dns_request_createvia3"); requests++; } #ifdef GSSAPI /* * Get the realm from the users kerberos ticket if possible */ static void get_ticket_realm(isc_mem_t *mctx) { krb5_context ctx; krb5_error_code rc; krb5_ccache ccache; krb5_principal princ; char *name; const char * ticket_realm; rc = krb5_init_context(&ctx); if (rc != 0) return; rc = krb5_cc_default(ctx, &ccache); if (rc != 0) { krb5_free_context(ctx); return; } rc = krb5_cc_get_principal(ctx, ccache, &princ); if (rc != 0) { krb5_cc_close(ctx, ccache); krb5_free_context(ctx); return; } rc = krb5_unparse_name(ctx, princ, &name); if (rc != 0) { krb5_free_principal(ctx, princ); krb5_cc_close(ctx, ccache); krb5_free_context(ctx); return; } ticket_realm = strrchr(name, '@'); if (ticket_realm != NULL) { realm = isc_mem_strdup(mctx, ticket_realm); } free(name); krb5_free_principal(ctx, princ); krb5_cc_close(ctx, ccache); krb5_free_context(ctx); if (realm != NULL && debugging) fprintf(stderr, "Found realm from ticket: %s\n", realm+1); } static void failed_gssrequest() { seenerror = ISC_TRUE; dns_name_free(&tmpzonename, gmctx); dns_name_free(&restart_master, gmctx); done_update(); } static void start_gssrequest(dns_name_t *master) { gss_ctx_id_t context; isc_buffer_t buf; isc_result_t result; isc_uint32_t val = 0; dns_message_t *rmsg = NULL; dns_request_t *request = NULL; dns_name_t *servname; dns_fixedname_t fname; char namestr[DNS_NAME_FORMATSIZE]; char mykeystr[DNS_NAME_FORMATSIZE]; char *err_message = NULL; debug("start_gssrequest"); usevc = ISC_TRUE; if (gssring != NULL) dns_tsigkeyring_detach(&gssring); gssring = NULL; result = dns_tsigkeyring_create(gmctx, &gssring); if (result != ISC_R_SUCCESS) fatal("dns_tsigkeyring_create failed: %s", isc_result_totext(result)); dns_name_format(master, namestr, sizeof(namestr)); if (kserver == NULL) { kserver = isc_mem_get(gmctx, sizeof(isc_sockaddr_t)); if (kserver == NULL) fatal("out of memory"); } memmove(kserver, &master_servers[master_inuse], sizeof(isc_sockaddr_t)); dns_fixedname_init(&fname); servname = dns_fixedname_name(&fname); if (realm == NULL) get_ticket_realm(gmctx); result = isc_string_printf(servicename, sizeof(servicename), "DNS/%s%s", namestr, realm ? realm : ""); if (result != ISC_R_SUCCESS) fatal("isc_string_printf(servicename) failed: %s", isc_result_totext(result)); isc_buffer_init(&buf, servicename, strlen(servicename)); isc_buffer_add(&buf, strlen(servicename)); result = dns_name_fromtext(servname, &buf, dns_rootname, 0, NULL); if (result != ISC_R_SUCCESS) fatal("dns_name_fromtext(servname) failed: %s", isc_result_totext(result)); dns_fixedname_init(&fkname); keyname = dns_fixedname_name(&fkname); isc_random_get(&val); result = isc_string_printf(mykeystr, sizeof(mykeystr), "%u.sig-%s", val, namestr); if (result != ISC_R_SUCCESS) fatal("isc_string_printf(mykeystr) failed: %s", isc_result_totext(result)); isc_buffer_init(&buf, mykeystr, strlen(mykeystr)); isc_buffer_add(&buf, strlen(mykeystr)); result = dns_name_fromtext(keyname, &buf, dns_rootname, 0, NULL); if (result != ISC_R_SUCCESS) fatal("dns_name_fromtext(keyname) failed: %s", isc_result_totext(result)); /* Windows doesn't recognize name compression in the key name. */ keyname->attributes |= DNS_NAMEATTR_NOCOMPRESS; rmsg = NULL; result = dns_message_create(gmctx, DNS_MESSAGE_INTENTRENDER, &rmsg); if (result != ISC_R_SUCCESS) fatal("dns_message_create failed: %s", isc_result_totext(result)); /* Build first request. */ context = GSS_C_NO_CONTEXT; result = dns_tkey_buildgssquery(rmsg, keyname, servname, NULL, 0, &context, use_win2k_gsstsig, gmctx, &err_message); if (result == ISC_R_FAILURE) { fprintf(stderr, "tkey query failed: %s\n", err_message != NULL ? err_message : "unknown error"); goto failure; } if (result != ISC_R_SUCCESS) fatal("dns_tkey_buildgssquery failed: %s", isc_result_totext(result)); send_gssrequest(kserver, rmsg, &request, context); return; failure: if (rmsg != NULL) dns_message_destroy(&rmsg); if (err_message != NULL) isc_mem_free(gmctx, err_message); failed_gssrequest(); } static void send_gssrequest(isc_sockaddr_t *destaddr, dns_message_t *msg, dns_request_t **request, gss_ctx_id_t context) { isc_result_t result; nsu_gssinfo_t *reqinfo; unsigned int options = 0; isc_sockaddr_t *srcaddr; debug("send_gssrequest"); reqinfo = isc_mem_get(gmctx, sizeof(nsu_gssinfo_t)); if (reqinfo == NULL) fatal("out of memory"); reqinfo->msg = msg; reqinfo->addr = destaddr; reqinfo->context = context; options |= DNS_REQUESTOPT_TCP; if (isc_sockaddr_pf(destaddr) == AF_INET6) srcaddr = localaddr6; else srcaddr = localaddr4; result = dns_request_createvia3(requestmgr, msg, srcaddr, destaddr, options, tsigkey, FIND_TIMEOUT * 20, FIND_TIMEOUT, 3, global_task, recvgss, reqinfo, request); check_result(result, "dns_request_createvia3"); if (debugging) show_message(stdout, msg, "Outgoing update query:"); requests++; } static void recvgss(isc_task_t *task, isc_event_t *event) { dns_requestevent_t *reqev = NULL; dns_request_t *request = NULL; isc_result_t result, eresult; dns_message_t *rcvmsg = NULL; nsu_gssinfo_t *reqinfo; dns_message_t *tsigquery = NULL; isc_sockaddr_t *addr; gss_ctx_id_t context; isc_buffer_t buf; dns_name_t *servname; dns_fixedname_t fname; char *err_message = NULL; UNUSED(task); ddebug("recvgss()"); requests--; REQUIRE(event->ev_type == DNS_EVENT_REQUESTDONE); reqev = (dns_requestevent_t *)event; request = reqev->request; eresult = reqev->result; reqinfo = reqev->ev_arg; tsigquery = reqinfo->msg; context = reqinfo->context; addr = reqinfo->addr; if (shuttingdown) { dns_request_destroy(&request); dns_message_destroy(&tsigquery); isc_mem_put(gmctx, reqinfo, sizeof(nsu_gssinfo_t)); isc_event_free(&event); maybeshutdown(); return; } if (eresult != ISC_R_SUCCESS) { ddebug("Destroying request [%p]", request); dns_request_destroy(&request); if (!next_master("recvgss", addr, eresult)) { dns_message_destroy(&tsigquery); failed_gssrequest(); } else { dns_message_renderreset(tsigquery); memmove(kserver, &master_servers[master_inuse], sizeof(isc_sockaddr_t)); send_gssrequest(kserver, tsigquery, &request, context); } isc_mem_put(gmctx, reqinfo, sizeof(nsu_gssinfo_t)); isc_event_free(&event); return; } isc_mem_put(gmctx, reqinfo, sizeof(nsu_gssinfo_t)); isc_event_free(&event); reqev = NULL; ddebug("recvgss creating rcvmsg"); result = dns_message_create(gmctx, DNS_MESSAGE_INTENTPARSE, &rcvmsg); check_result(result, "dns_message_create"); result = dns_request_getresponse(request, rcvmsg, DNS_MESSAGEPARSE_PRESERVEORDER); check_result(result, "dns_request_getresponse"); if (debugging) show_message(stderr, rcvmsg, "recvmsg reply from GSS-TSIG query"); if (rcvmsg->rcode == dns_rcode_formerr && !tried_other_gsstsig) { ddebug("recvgss trying %s GSS-TSIG", use_win2k_gsstsig ? "Standard" : "Win2k"); if (use_win2k_gsstsig) use_win2k_gsstsig = ISC_FALSE; else use_win2k_gsstsig = ISC_TRUE; tried_other_gsstsig = ISC_TRUE; start_gssrequest(&restart_master); goto done; } if (rcvmsg->rcode != dns_rcode_noerror && rcvmsg->rcode != dns_rcode_nxdomain) fatal("response to GSS-TSIG query was unsuccessful"); dns_fixedname_init(&fname); servname = dns_fixedname_name(&fname); isc_buffer_init(&buf, servicename, strlen(servicename)); isc_buffer_add(&buf, strlen(servicename)); result = dns_name_fromtext(servname, &buf, dns_rootname, 0, NULL); check_result(result, "dns_name_fromtext"); tsigkey = NULL; result = dns_tkey_gssnegotiate(tsigquery, rcvmsg, servname, &context, &tsigkey, gssring, use_win2k_gsstsig, &err_message); switch (result) { case DNS_R_CONTINUE: dns_message_destroy(&rcvmsg); dns_request_destroy(&request); send_gssrequest(kserver, tsigquery, &request, context); ddebug("Out of recvgss"); return; case ISC_R_SUCCESS: /* * XXXSRA Waaay too much fun here. There's no good * reason why we need a TSIG here (the people who put * it into the spec admitted at the time that it was * not a security issue), and Windows clients don't * seem to work if named complies with the spec and * includes the gratuitous TSIG. So we're in the * bizarre situation of having to choose between * complying with a useless requirement in the spec * and interoperating. This is nuts. If we can * confirm this behavior, we should ask the WG to * consider removing the requirement for the * gratuitous TSIG here. For the moment, we ignore * the TSIG -- this too is a spec violation, but it's * the least insane thing to do. */ #if 0 /* * Verify the signature. */ rcvmsg->state = DNS_SECTION_ANY; dns_message_setquerytsig(rcvmsg, NULL); result = dns_message_settsigkey(rcvmsg, tsigkey); check_result(result, "dns_message_settsigkey"); result = dns_message_checksig(rcvmsg, NULL); ddebug("tsig verification: %s", dns_result_totext(result)); check_result(result, "dns_message_checksig"); #endif /* 0 */ send_update(&tmpzonename, &master_servers[master_inuse]); setzoneclass(dns_rdataclass_none); break; default: fatal("dns_tkey_gssnegotiate: %s %s", isc_result_totext(result), err_message != NULL ? err_message : ""); } done: dns_request_destroy(&request); dns_message_destroy(&tsigquery); dns_message_destroy(&rcvmsg); ddebug("Out of recvgss"); } #endif static void start_update(void) { isc_result_t result; dns_rdataset_t *rdataset = NULL; dns_name_t *name = NULL; dns_request_t *request = NULL; dns_message_t *soaquery = NULL; dns_name_t *firstname; dns_section_t section = DNS_SECTION_UPDATE; ddebug("start_update()"); if (answer != NULL) dns_message_destroy(&answer); /* * If we have both the zone and the servers we have enough information * to send the update straight away otherwise we need to discover * the zone and / or the master server. */ if (userzone != NULL && !default_servers && !usegsstsig) { master_from_servers(); send_update(userzone, &master_servers[master_inuse]); setzoneclass(dns_rdataclass_none); return; } result = dns_message_create(gmctx, DNS_MESSAGE_INTENTRENDER, &soaquery); check_result(result, "dns_message_create"); if (default_servers) soaquery->flags |= DNS_MESSAGEFLAG_RD; result = dns_message_gettempname(soaquery, &name); check_result(result, "dns_message_gettempname"); result = dns_message_gettemprdataset(soaquery, &rdataset); check_result(result, "dns_message_gettemprdataset"); dns_rdataset_makequestion(rdataset, getzoneclass(), dns_rdatatype_soa); if (userzone != NULL) { dns_name_init(name, NULL); dns_name_clone(userzone, name); } else { dns_rdataset_t *tmprdataset; result = dns_message_firstname(updatemsg, section); if (result == ISC_R_NOMORE) { section = DNS_SECTION_PREREQUISITE; result = dns_message_firstname(updatemsg, section); } if (result != ISC_R_SUCCESS) { dns_message_puttempname(soaquery, &name); dns_rdataset_disassociate(rdataset); dns_message_puttemprdataset(soaquery, &rdataset); dns_message_destroy(&soaquery); done_update(); return; } firstname = NULL; dns_message_currentname(updatemsg, section, &firstname); dns_name_init(name, NULL); dns_name_clone(firstname, name); /* * Looks to see if the first name references a DS record * and if that name is not the root remove a label as DS * records live in the parent zone so we need to start our * search one label up. */ tmprdataset = ISC_LIST_HEAD(firstname->list); if (section == DNS_SECTION_UPDATE && !dns_name_equal(firstname, dns_rootname) && tmprdataset->type == dns_rdatatype_ds) { unsigned int labels = dns_name_countlabels(name); dns_name_getlabelsequence(name, 1, labels - 1, name); } } ISC_LIST_INIT(name->list); ISC_LIST_APPEND(name->list, rdataset, link); dns_message_addname(soaquery, name, DNS_SECTION_QUESTION); ns_inuse = 0; sendrequest(&servers[ns_inuse], soaquery, &request); } static void cleanup(void) { ddebug("cleanup()"); if (answer != NULL) dns_message_destroy(&answer); #ifdef GSSAPI if (tsigkey != NULL) { ddebug("detach tsigkey x%p", tsigkey); dns_tsigkey_detach(&tsigkey); } if (gssring != NULL) { ddebug("Detaching GSS-TSIG keyring"); dns_tsigkeyring_detach(&gssring); } if (kserver != NULL) { isc_mem_put(gmctx, kserver, sizeof(isc_sockaddr_t)); kserver = NULL; } if (realm != NULL) { isc_mem_free(gmctx, realm); realm = NULL; } #endif if (sig0key != NULL) dst_key_free(&sig0key); ddebug("Shutting down task manager"); isc_taskmgr_destroy(&taskmgr); ddebug("Destroying event"); isc_event_free(&global_event); ddebug("Shutting down socket manager"); isc_socketmgr_destroy(&socketmgr); ddebug("Shutting down timer manager"); isc_timermgr_destroy(&timermgr); ddebug("Destroying hash context"); isc_hash_destroy(); ddebug("Destroying name state"); dns_name_destroy(); ddebug("Removing log context"); isc_log_destroy(&glctx); ddebug("Destroying memory context"); if (memdebugging) isc_mem_stats(gmctx, stderr); isc_mem_destroy(&gmctx); } static void getinput(isc_task_t *task, isc_event_t *event) { isc_boolean_t more; UNUSED(task); if (shuttingdown) { maybeshutdown(); return; } if (global_event == NULL) global_event = event; reset_system(); more = user_interaction(); if (!more) { isc_app_shutdown(); return; } start_update(); return; } int main(int argc, char **argv) { isc_result_t result; style = &dns_master_style_debug; input = stdin; interactive = ISC_TF(isatty(0)); isc_app_start(); pre_parse_args(argc, argv); result = isc_mem_create(0, 0, &gmctx); check_result(result, "isc_mem_create"); parse_args(argc, argv, gmctx, &entropy); setup_system(); result = isc_app_onrun(gmctx, global_task, getinput, NULL); check_result(result, "isc_app_onrun"); (void)isc_app_run(); cleanup(); isc_app_finish(); if (seenerror) return (2); else return (0); } bind9-9.11.3+dfsg/bin/nsupdate/nsupdate.docbook000066400000000000000000000676131325250447100213310ustar00rootroot00000000000000 2014-04-18 ISC Internet Systems Consortium, Inc. nsupdate 1 BIND9 nsupdate Dynamic DNS update utility 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2014 2015 2016 2017 Internet Systems Consortium, Inc. ("ISC") nsupdate filename DESCRIPTION nsupdate is used to submit Dynamic DNS Update requests as defined in RFC 2136 to a name server. This allows resource records to be added or removed from a zone without manually editing the zone file. A single update request can contain requests to add or remove more than one resource record. Zones that are under dynamic control via nsupdate or a DHCP server should not be edited by hand. Manual edits could conflict with dynamic updates and cause data to be lost. The resource records that are dynamically added or removed with nsupdate have to be in the same zone. Requests are sent to the zone's master server. This is identified by the MNAME field of the zone's SOA record. Transaction signatures can be used to authenticate the Dynamic DNS updates. These use the TSIG resource record type described in RFC 2845 or the SIG(0) record described in RFC 2535 and RFC 2931 or GSS-TSIG as described in RFC 3645. TSIG relies on a shared secret that should only be known to nsupdate and the name server. For instance, suitable key and server statements would be added to /etc/named.conf so that the name server can associate the appropriate secret key and algorithm with the IP address of the client application that will be using TSIG authentication. You can use ddns-confgen to generate suitable configuration fragments. nsupdate uses the or options to provide the TSIG shared secret. These options are mutually exclusive. SIG(0) uses public key cryptography. To use a SIG(0) key, the public key must be stored in a KEY record in a zone served by the name server. GSS-TSIG uses Kerberos credentials. Standard GSS-TSIG mode is switched on with the flag. A non-standards-compliant variant of GSS-TSIG used by Windows 2000 can be switched on with the flag. OPTIONS -d Debug mode. This provides tracing information about the update requests that are made and the replies received from the name server. -D Extra debug mode. -i Force interactive mode, even when standard input is not a terminal. -k keyfile The file containing the TSIG authentication key. Keyfiles may be in two formats: a single file containing a named.conf-format key statement, which may be generated automatically by ddns-confgen, or a pair of files whose names are of the format K{name}.+157.+{random}.key and K{name}.+157.+{random}.private, which can be generated by dnssec-keygen. The may also be used to specify a SIG(0) key used to authenticate Dynamic DNS update requests. In this case, the key specified is not an HMAC-MD5 key. -l Local-host only mode. This sets the server address to localhost (disabling the server so that the server address cannot be overridden). Connections to the local server will use a TSIG key found in /var/run/named/session.key, which is automatically generated by named if any local master zone has set update-policy to local. The location of this key file can be overridden with the option. -L level Set the logging debug level. If zero, logging is disabled. -p port Set the port to use for connections to a name server. The default is 53. -P Print the list of private BIND-specific resource record types whose format is understood by nsupdate. See also the option. -r udpretries The number of UDP retries. The default is 3. If zero, only one update request will be made. -R randomdev Where to obtain randomness. If the operating system does not provide a /dev/random or equivalent device, the default source of randomness is keyboard input. randomdev specifies the name of a character device or file containing random data to be used instead of the default. The special value keyboard indicates that keyboard input should be used. This option may be specified multiple times. -t timeout The maximum time an update request can take before it is aborted. The default is 300 seconds. Zero can be used to disable the timeout. -T Print the list of IANA standard resource record types whose format is understood by nsupdate. nsupdate will exit after the lists are printed. The option can be combined with the option. Other types can be entered using "TYPEXXXXX" where "XXXXX" is the decimal value of the type with no leading zeros. The rdata, if present, will be parsed using the UNKNOWN rdata format, (<backslash> <hash> <space> <length> <space> <hexstring>). -u udptimeout The UDP retry interval. The default is 3 seconds. If zero, the interval will be computed from the timeout interval and number of UDP retries. -v Use TCP even for small update requests. By default, nsupdate uses UDP to send update requests to the name server unless they are too large to fit in a UDP request in which case TCP will be used. TCP may be preferable when a batch of update requests is made. -V Print the version number and exit. -y hmac:keyname:secret Literal TSIG authentication key. keyname is the name of the key, and secret is the base64 encoded shared secret. hmac is the name of the key algorithm; valid choices are hmac-md5, hmac-sha1, hmac-sha224, hmac-sha256, hmac-sha384, or hmac-sha512. If hmac is not specified, the default is hmac-md5 or if MD5 was disabled hmac-sha256. NOTE: Use of the option is discouraged because the shared secret is supplied as a command line argument in clear text. This may be visible in the output from ps1 or in a history file maintained by the user's shell. INPUT FORMAT nsupdate reads input from filename or standard input. Each command is supplied on exactly one line of input. Some commands are for administrative purposes. The others are either update instructions or prerequisite checks on the contents of the zone. These checks set conditions that some name or set of resource records (RRset) either exists or is absent from the zone. These conditions must be met if the entire update request is to succeed. Updates will be rejected if the tests for the prerequisite conditions fail. Every update request consists of zero or more prerequisites and zero or more updates. This allows a suitably authenticated update request to proceed if some specified resource records are present or missing from the zone. A blank input line (or the send command) causes the accumulated commands to be sent as one Dynamic DNS update request to the name server. The command formats and their meaning are as follows: server servername port Sends all dynamic update requests to the name server servername. When no server statement is provided, nsupdate will send updates to the master server of the correct zone. The MNAME field of that zone's SOA record will identify the master server for that zone. port is the port number on servername where the dynamic update requests get sent. If no port number is specified, the default DNS port number of 53 is used. local address port Sends all dynamic update requests using the local address. When no local statement is provided, nsupdate will send updates using an address and port chosen by the system. port can additionally be used to make requests come from a specific port. If no port number is specified, the system will assign one. zone zonename Specifies that all updates are to be made to the zone zonename. If no zone statement is provided, nsupdate will attempt determine the correct zone to update based on the rest of the input. class classname Specify the default class. If no class is specified, the default class is IN. ttl seconds Specify the default time to live for records to be added. The value none will clear the default ttl. key hmac:keyname secret Specifies that all updates are to be TSIG-signed using the keyname secret pair. If hmac is specified, then it sets the signing algorithm in use; the default is hmac-md5 or if MD5 was disabled hmac-sha256. The key command overrides any key specified on the command line via or . gsstsig Use GSS-TSIG to sign the updated. This is equivalent to specifying on the command line. oldgsstsig Use the Windows 2000 version of GSS-TSIG to sign the updated. This is equivalent to specifying on the command line. realm realm_name When using GSS-TSIG use realm_name rather than the default realm in krb5.conf. If no realm is specified the saved realm is cleared. check-names yes_or_no Turn on or off check-names processing on records to be added. Check-names has no effect on prerequisites or records to be deleted. By default check-names processing is on. If check-names processing fails the record will not be added to the UPDATE message. prereq nxdomain domain-name Requires that no resource record of any type exists with name domain-name. prereq yxdomain domain-name Requires that domain-name exists (has as at least one resource record, of any type). prereq nxrrset domain-name class type Requires that no resource record exists of the specified type, class and domain-name. If class is omitted, IN (internet) is assumed. prereq yxrrset domain-name class type This requires that a resource record of the specified type, class and domain-name must exist. If class is omitted, IN (internet) is assumed. prereq yxrrset domain-name class type data The data from each set of prerequisites of this form sharing a common type, class, and domain-name are combined to form a set of RRs. This set of RRs must exactly match the set of RRs existing in the zone at the given type, class, and domain-name. The data are written in the standard text representation of the resource record's RDATA. update delete domain-name ttl class type data Deletes any resource records named domain-name. If type and data is provided, only matching resource records will be removed. The internet class is assumed if class is not supplied. The ttl is ignored, and is only allowed for compatibility. update add domain-name ttl class type data Adds a new resource record with the specified ttl, class and data. show Displays the current message, containing all of the prerequisites and updates specified since the last send. send Sends the current message. This is equivalent to entering a blank line. answer Displays the answer. debug Turn on debugging. version Print version number. help Print a list of commands. Lines beginning with a semicolon are comments and are ignored. EXAMPLES The examples below show how nsupdate could be used to insert and delete resource records from the example.com zone. Notice that the input in each example contains a trailing blank line so that a group of commands are sent as one dynamic update request to the master name server for example.com. # nsupdate > update delete oldhost.example.com A > update add newhost.example.com 86400 A 172.16.1.1 > send Any A records for oldhost.example.com are deleted. And an A record for newhost.example.com with IP address 172.16.1.1 is added. The newly-added record has a 1 day TTL (86400 seconds). # nsupdate > prereq nxdomain nickname.example.com > update add nickname.example.com 86400 CNAME somehost.example.com > send The prerequisite condition gets the name server to check that there are no resource records of any type for nickname.example.com. If there are, the update request fails. If this name does not exist, a CNAME for it is added. This ensures that when the CNAME is added, it cannot conflict with the long-standing rule in RFC 1034 that a name must not exist as any other record type if it exists as a CNAME. (The rule has been updated for DNSSEC in RFC 2535 to allow CNAMEs to have RRSIG, DNSKEY and NSEC records.) FILES /etc/resolv.conf used to identify default name server /var/run/named/session.key sets the default TSIG key for use in local-only mode K{name}.+157.+{random}.key base-64 encoding of HMAC-MD5 key created by dnssec-keygen8 . K{name}.+157.+{random}.private base-64 encoding of HMAC-MD5 key created by dnssec-keygen8 . SEE ALSO RFC 2136, RFC 3007, RFC 2104, RFC 2845, RFC 1034, RFC 2535, RFC 2931, named8 , ddns-confgen8 , dnssec-keygen8 . BUGS The TSIG key is redundantly stored in two separate files. This is a consequence of nsupdate using the DST library for its cryptographic operations, and may change in future releases. bind9-9.11.3+dfsg/bin/nsupdate/nsupdate.html000066400000000000000000000652411325250447100206500ustar00rootroot00000000000000 nsupdate

Name

nsupdate — Dynamic DNS update utility

Synopsis

nsupdate [-d] [-D] [-i] [-L level] [ [-g] | [-o] | [-l] | [-y [hmac:]keyname:secret] | [-k keyfile] ] [-t timeout] [-u udptimeout] [-r udpretries] [-R randomdev] [-v] [-T] [-P] [-V] [filename]

DESCRIPTION

nsupdate is used to submit Dynamic DNS Update requests as defined in RFC 2136 to a name server. This allows resource records to be added or removed from a zone without manually editing the zone file. A single update request can contain requests to add or remove more than one resource record.

Zones that are under dynamic control via nsupdate or a DHCP server should not be edited by hand. Manual edits could conflict with dynamic updates and cause data to be lost.

The resource records that are dynamically added or removed with nsupdate have to be in the same zone. Requests are sent to the zone's master server. This is identified by the MNAME field of the zone's SOA record.

Transaction signatures can be used to authenticate the Dynamic DNS updates. These use the TSIG resource record type described in RFC 2845 or the SIG(0) record described in RFC 2535 and RFC 2931 or GSS-TSIG as described in RFC 3645.

TSIG relies on a shared secret that should only be known to nsupdate and the name server. For instance, suitable key and server statements would be added to /etc/named.conf so that the name server can associate the appropriate secret key and algorithm with the IP address of the client application that will be using TSIG authentication. You can use ddns-confgen to generate suitable configuration fragments. nsupdate uses the -y or -k options to provide the TSIG shared secret. These options are mutually exclusive.

SIG(0) uses public key cryptography. To use a SIG(0) key, the public key must be stored in a KEY record in a zone served by the name server.

GSS-TSIG uses Kerberos credentials. Standard GSS-TSIG mode is switched on with the -g flag. A non-standards-compliant variant of GSS-TSIG used by Windows 2000 can be switched on with the -o flag.

OPTIONS

-d

Debug mode. This provides tracing information about the update requests that are made and the replies received from the name server.

-D

Extra debug mode.

-i

Force interactive mode, even when standard input is not a terminal.

-k keyfile

The file containing the TSIG authentication key. Keyfiles may be in two formats: a single file containing a named.conf-format key statement, which may be generated automatically by ddns-confgen, or a pair of files whose names are of the format K{name}.+157.+{random}.key and K{name}.+157.+{random}.private, which can be generated by dnssec-keygen. The -k may also be used to specify a SIG(0) key used to authenticate Dynamic DNS update requests. In this case, the key specified is not an HMAC-MD5 key.

-l

Local-host only mode. This sets the server address to localhost (disabling the server so that the server address cannot be overridden). Connections to the local server will use a TSIG key found in /var/run/named/session.key, which is automatically generated by named if any local master zone has set update-policy to local. The location of this key file can be overridden with the -k option.

-L level

Set the logging debug level. If zero, logging is disabled.

-p port

Set the port to use for connections to a name server. The default is 53.

-P

Print the list of private BIND-specific resource record types whose format is understood by nsupdate. See also the -T option.

-r udpretries

The number of UDP retries. The default is 3. If zero, only one update request will be made.

-R randomdev

Where to obtain randomness. If the operating system does not provide a /dev/random or equivalent device, the default source of randomness is keyboard input. randomdev specifies the name of a character device or file containing random data to be used instead of the default. The special value keyboard indicates that keyboard input should be used. This option may be specified multiple times.

-t timeout

The maximum time an update request can take before it is aborted. The default is 300 seconds. Zero can be used to disable the timeout.

-T

Print the list of IANA standard resource record types whose format is understood by nsupdate. nsupdate will exit after the lists are printed. The -T option can be combined with the -P option.

Other types can be entered using "TYPEXXXXX" where "XXXXX" is the decimal value of the type with no leading zeros. The rdata, if present, will be parsed using the UNKNOWN rdata format, (<backslash> <hash> <space> <length> <space> <hexstring>).

-u udptimeout

The UDP retry interval. The default is 3 seconds. If zero, the interval will be computed from the timeout interval and number of UDP retries.

-v

Use TCP even for small update requests. By default, nsupdate uses UDP to send update requests to the name server unless they are too large to fit in a UDP request in which case TCP will be used. TCP may be preferable when a batch of update requests is made.

-V

Print the version number and exit.

-y [hmac:]keyname:secret

Literal TSIG authentication key. keyname is the name of the key, and secret is the base64 encoded shared secret. hmac is the name of the key algorithm; valid choices are hmac-md5, hmac-sha1, hmac-sha224, hmac-sha256, hmac-sha384, or hmac-sha512. If hmac is not specified, the default is hmac-md5 or if MD5 was disabled hmac-sha256.

NOTE: Use of the -y option is discouraged because the shared secret is supplied as a command line argument in clear text. This may be visible in the output from ps(1) or in a history file maintained by the user's shell.

INPUT FORMAT

nsupdate reads input from filename or standard input. Each command is supplied on exactly one line of input. Some commands are for administrative purposes. The others are either update instructions or prerequisite checks on the contents of the zone. These checks set conditions that some name or set of resource records (RRset) either exists or is absent from the zone. These conditions must be met if the entire update request is to succeed. Updates will be rejected if the tests for the prerequisite conditions fail.

Every update request consists of zero or more prerequisites and zero or more updates. This allows a suitably authenticated update request to proceed if some specified resource records are present or missing from the zone. A blank input line (or the send command) causes the accumulated commands to be sent as one Dynamic DNS update request to the name server.

The command formats and their meaning are as follows:

server {servername} [port]

Sends all dynamic update requests to the name server servername. When no server statement is provided, nsupdate will send updates to the master server of the correct zone. The MNAME field of that zone's SOA record will identify the master server for that zone. port is the port number on servername where the dynamic update requests get sent. If no port number is specified, the default DNS port number of 53 is used.

local {address} [port]

Sends all dynamic update requests using the local address. When no local statement is provided, nsupdate will send updates using an address and port chosen by the system. port can additionally be used to make requests come from a specific port. If no port number is specified, the system will assign one.

zone {zonename}

Specifies that all updates are to be made to the zone zonename. If no zone statement is provided, nsupdate will attempt determine the correct zone to update based on the rest of the input.

class {classname}

Specify the default class. If no class is specified, the default class is IN.

ttl {seconds}

Specify the default time to live for records to be added. The value none will clear the default ttl.

key [hmac:] {keyname} {secret}

Specifies that all updates are to be TSIG-signed using the keyname secret pair. If hmac is specified, then it sets the signing algorithm in use; the default is hmac-md5 or if MD5 was disabled hmac-sha256. The key command overrides any key specified on the command line via -y or -k.

gsstsig

Use GSS-TSIG to sign the updated. This is equivalent to specifying -g on the command line.

oldgsstsig

Use the Windows 2000 version of GSS-TSIG to sign the updated. This is equivalent to specifying -o on the command line.

realm {[realm_name]}

When using GSS-TSIG use realm_name rather than the default realm in krb5.conf. If no realm is specified the saved realm is cleared.

check-names {[yes_or_no]}

Turn on or off check-names processing on records to be added. Check-names has no effect on prerequisites or records to be deleted. By default check-names processing is on. If check-names processing fails the record will not be added to the UPDATE message.

[prereq] nxdomain {domain-name}

Requires that no resource record of any type exists with name domain-name.

[prereq] yxdomain {domain-name}

Requires that domain-name exists (has as at least one resource record, of any type).

[prereq] nxrrset {domain-name} [class] {type}

Requires that no resource record exists of the specified type, class and domain-name. If class is omitted, IN (internet) is assumed.

[prereq] yxrrset {domain-name} [class] {type}

This requires that a resource record of the specified type, class and domain-name must exist. If class is omitted, IN (internet) is assumed.

[prereq] yxrrset {domain-name} [class] {type} {data...}

The data from each set of prerequisites of this form sharing a common type, class, and domain-name are combined to form a set of RRs. This set of RRs must exactly match the set of RRs existing in the zone at the given type, class, and domain-name. The data are written in the standard text representation of the resource record's RDATA.

[update] del[ete] {domain-name} [ttl] [class] [type [data...]]

Deletes any resource records named domain-name. If type and data is provided, only matching resource records will be removed. The internet class is assumed if class is not supplied. The ttl is ignored, and is only allowed for compatibility.

[update] add {domain-name} {ttl} [class] {type} {data...}

Adds a new resource record with the specified ttl, class and data.

show

Displays the current message, containing all of the prerequisites and updates specified since the last send.

send

Sends the current message. This is equivalent to entering a blank line.

answer

Displays the answer.

debug

Turn on debugging.

version

Print version number.

help

Print a list of commands.

Lines beginning with a semicolon are comments and are ignored.

EXAMPLES

The examples below show how nsupdate could be used to insert and delete resource records from the example.com zone. Notice that the input in each example contains a trailing blank line so that a group of commands are sent as one dynamic update request to the master name server for example.com.

# nsupdate
> update delete oldhost.example.com A
> update add newhost.example.com 86400 A 172.16.1.1
> send

Any A records for oldhost.example.com are deleted. And an A record for newhost.example.com with IP address 172.16.1.1 is added. The newly-added record has a 1 day TTL (86400 seconds).

# nsupdate
> prereq nxdomain nickname.example.com
> update add nickname.example.com 86400 CNAME somehost.example.com
> send

The prerequisite condition gets the name server to check that there are no resource records of any type for nickname.example.com. If there are, the update request fails. If this name does not exist, a CNAME for it is added. This ensures that when the CNAME is added, it cannot conflict with the long-standing rule in RFC 1034 that a name must not exist as any other record type if it exists as a CNAME. (The rule has been updated for DNSSEC in RFC 2535 to allow CNAMEs to have RRSIG, DNSKEY and NSEC records.)

FILES

/etc/resolv.conf

used to identify default name server

/var/run/named/session.key

sets the default TSIG key for use in local-only mode

K{name}.+157.+{random}.key

base-64 encoding of HMAC-MD5 key created by dnssec-keygen(8) .

K{name}.+157.+{random}.private

base-64 encoding of HMAC-MD5 key created by dnssec-keygen(8) .

SEE ALSO

RFC 2136, RFC 3007, RFC 2104, RFC 2845, RFC 1034, RFC 2535, RFC 2931, named(8) , ddns-confgen(8) , dnssec-keygen(8) .

BUGS

The TSIG key is redundantly stored in two separate files. This is a consequence of nsupdate using the DST library for its cryptographic operations, and may change in future releases.

bind9-9.11.3+dfsg/bin/nsupdate/win32/000077500000000000000000000000001325250447100170715ustar00rootroot00000000000000bind9-9.11.3+dfsg/bin/nsupdate/win32/nsupdate.dsp.in000066400000000000000000000124331325250447100220340ustar00rootroot00000000000000# Microsoft Developer Studio Project File - Name="nsupdate" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "@PLATFORM@ (x86) Console Application" 0x0103 CFG=nsupdate - @PLATFORM@ Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "nsupdate.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "nsupdate.mak" CFG="nsupdate - @PLATFORM@ Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "nsupdate - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE "nsupdate - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "nsupdate - @PLATFORM@ Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 @COPTX@ @COPTI@ /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c # ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../include" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ @GSSAPI_INC@ @READLINE_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" /I "../../../lib/lwres/win32/include/lwres" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /I "../../../lib/isccfg/include" /D "WIN32" @CRYPTO@ @USE_GSSAPI@ /D "USE_READLINE_STATIC" /D "__STDC__" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console @MACHINE@ # ADD LINK32 @GSSAPI_LIB@ @KRB5_LIB@ @READLINE_LIB@ ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib ../../../lib/lwres/win32/Release/liblwres.lib user32.lib advapi32.lib ws2_32.lib ../../../lib/bind9/win32/Release/libbind9.lib ../../../lib/isccfg/win32/Release/libisccfg.lib /nologo /subsystem:console @MACHINE@ /out:"../../../Build/Release/nsupdate.exe" !ELSEIF "$(CFG)" == "nsupdate - @PLATFORM@ Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /GZ /c # ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../include" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ @GSSAPI_INC@ @READLINE_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" /I "../../../lib/lwres/win32/include/lwres" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /I "../../../lib/isccfg/include" /D "WIN32" @CRYPTO@ @USE_GSSAPI@ /D "USE_READLINE_STATIC" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c # SUBTRACT CPP /X /u @COPTY@ # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug @MACHINE@ /pdbtype:sept # ADD LINK32 @GSSAPI_LIB@ @KRB5_LIB@ @READLINE_LIBD@ ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib ../../../lib/lwres/win32/Debug/liblwres.lib user32.lib advapi32.lib ws2_32.lib ../../../lib/bind9/win32/Debug/libbind9.lib ../../../lib/isccfg/win32/Debug/libisccfg.lib /nologo /subsystem:console /debug @MACHINE@ /out:"../../../Build/Debug/nsupdate.exe" /pdbtype:sept !ENDIF # Begin Target # Name "nsupdate - @PLATFORM@ Release" # Name "nsupdate - @PLATFORM@ Debug" # Begin Group "Source Files" # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" # Begin Source File SOURCE=..\nsupdate.c # End Source File # End Group # Begin Group "Header Files" # PROP Default_Filter "h;hpp;hxx;hm;inl" # End Group # Begin Group "Resource Files" # PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" # End Group # End Target # End Project bind9-9.11.3+dfsg/bin/nsupdate/win32/nsupdate.dsw000066400000000000000000000010351325250447100214320ustar00rootroot00000000000000Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "nsupdate"=".\nsupdate.dsp" - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### bind9-9.11.3+dfsg/bin/nsupdate/win32/nsupdate.mak.in000066400000000000000000000274271325250447100220270ustar00rootroot00000000000000# Microsoft Developer Studio Generated NMAKE File, Based on nsupdate.dsp !IF "$(CFG)" == "" CFG=nsupdate - @PLATFORM@ Debug !MESSAGE No configuration specified. Defaulting to nsupdate - @PLATFORM@ Debug. !ENDIF !IF "$(CFG)" != "nsupdate - @PLATFORM@ Release" && "$(CFG)" != "nsupdate - @PLATFORM@ Debug" !MESSAGE Invalid configuration "$(CFG)" specified. !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "nsupdate.mak" CFG="nsupdate - @PLATFORM@ Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "nsupdate - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE "nsupdate - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE !ERROR An invalid configuration is specified. !ENDIF !IF "$(OS)" == "Windows_NT" NULL= !ELSE NULL=nul !ENDIF CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "nsupdate - @PLATFORM@ Release" _VC_MANIFEST_INC=0 _VC_MANIFEST_BASENAME=__VC80 !ELSE _VC_MANIFEST_INC=1 _VC_MANIFEST_BASENAME=__VC80.Debug !ENDIF #################################################### # Specifying name of temporary resource file used only in incremental builds: !if "$(_VC_MANIFEST_INC)" == "1" _VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res !else _VC_MANIFEST_AUTO_RES= !endif #################################################### # _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE: !if "$(_VC_MANIFEST_INC)" == "1" #MT_SPECIAL_RETURN=1090650113 #MT_SPECIAL_SWITCH=-notify_resource_update MT_SPECIAL_RETURN=0 MT_SPECIAL_SWITCH= _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \ if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \ rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \ link $** /out:$@ $(LFLAGS) !else _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1 !endif #################################################### # _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL: !if "$(_VC_MANIFEST_INC)" == "1" #MT_SPECIAL_RETURN=1090650113 #MT_SPECIAL_SWITCH=-notify_resource_update MT_SPECIAL_RETURN=0 MT_SPECIAL_SWITCH= _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \ if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \ rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \ link $** /out:$@ $(LFLAGS) !else _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2 !endif #################################################### # _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily: !if "$(_VC_MANIFEST_INC)" == "1" _VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \ $(_VC_MANIFEST_BASENAME).auto.rc \ $(_VC_MANIFEST_BASENAME).auto.manifest !else _VC_MANIFEST_CLEAN= !endif !IF "$(CFG)" == "nsupdate - @PLATFORM@ Release" OUTDIR=.\Release INTDIR=.\Release !IF "$(RECURSE)" == "0" ALL : "..\..\..\Build\Release\nsupdate.exe" !ELSE ALL : "libbind9 - @PLATFORM@ Release" "libisc - @PLATFORM@ Release" "libdns - @PLATFORM@ Release" "..\..\..\Build\Release\nsupdate.exe" !ENDIF !IF "$(RECURSE)" == "1" CLEAN :"libdns - @PLATFORM@ ReleaseCLEAN" "libisc - @PLATFORM@ ReleaseCLEAN" "libbind9 - @PLATFORM@ ReleaseCLEAN" !ELSE CLEAN : !ENDIF -@erase "$(INTDIR)\nsupdate.obj" -@erase "$(INTDIR)\vc60.idb" -@erase "..\..\..\Build\Release\nsupdate.exe" -@$(_VC_MANIFEST_CLEAN) "$(OUTDIR)" : if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" CPP_PROJ=/nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../include" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ @GSSAPI_INC@ @READLINE_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" /I "../../../lib/lwres/win32/include/lwres" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /I "../../../lib/isccfg/include" /D "WIN32" @CRYPTO@ @USE_GSSAPI@ /D "USE_READLINE_STATIC" /D "__STDC__" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\nsupdate.pch" @COPTY@ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c BSC32=bscmake.exe BSC32_FLAGS=/nologo /o"$(OUTDIR)\nsupdate.bsc" BSC32_SBRS= \ LINK32=link.exe LINK32_FLAGS=../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib ../../../lib/lwres/win32/Release/liblwres.lib user32.lib advapi32.lib ws2_32.lib ../../../lib/bind9/win32/Release/libbind9.lib ../../../lib/isccfg/win32/Release/libisccfg.lib @GSSAPI_LIB@ @KRB5_LIB@ @READLINE_LIB@ /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\nsupdate.pdb" @MACHINE@ /out:"../../../Build/Release/nsupdate.exe" LINK32_OBJS= \ "$(INTDIR)\nsupdate.obj" \ "..\..\..\lib\dns\win32\Release\libdns.lib" \ "..\..\..\lib\isc\win32\Release\libisc.lib" \ "..\..\..\lib\bind9\win32\Release\libbind9.lib" \ "..\..\..\lib\isccfg\win32\Release\libisccfg.lib" "..\..\..\Build\Release\nsupdate.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) $(LINK32) @<< $(LINK32_FLAGS) $(LINK32_OBJS) << $(_VC_MANIFEST_EMBED_EXE) !ELSEIF "$(CFG)" == "nsupdate - @PLATFORM@ Debug" OUTDIR=.\Debug INTDIR=.\Debug # Begin Custom Macros OutDir=.\Debug # End Custom Macros !IF "$(RECURSE)" == "0" ALL : "..\..\..\Build\Debug\nsupdate.exe" "$(OUTDIR)\nsupdate.bsc" !ELSE ALL : "libbind9 - @PLATFORM@ Debug" "libisc - @PLATFORM@ Debug" "libdns - @PLATFORM@ Debug" "..\..\..\Build\Debug\nsupdate.exe" "$(OUTDIR)\nsupdate.bsc" !ENDIF !IF "$(RECURSE)" == "1" CLEAN :"libdns - @PLATFORM@ DebugCLEAN" "libisc - @PLATFORM@ DebugCLEAN" "libbind9 - @PLATFORM@ DebugCLEAN" !ELSE CLEAN : !ENDIF -@erase "$(INTDIR)\nsupdate.obj" -@erase "$(INTDIR)\nsupdate.sbr" -@erase "$(INTDIR)\vc60.idb" -@erase "$(INTDIR)\vc60.pdb" -@erase "$(OUTDIR)\nsupdate.bsc" -@erase "$(OUTDIR)\nsupdate.pdb" -@erase "..\..\..\Build\Debug\nsupdate.exe" -@erase "..\..\..\Build\Debug\nsupdate.ilk" -@$(_VC_MANIFEST_CLEAN) "$(OUTDIR)" : if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" CPP_PROJ=/nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../include" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ @GSSAPI_INC@ @READLINE_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" /I "../../../lib/lwres/win32/include/lwres" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /I "../../../lib/isccfg/include" /D "WIN32" @CRYPTO@ @USE_GSSAPI@ /D "USE_READLINE_STATIC" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c BSC32=bscmake.exe BSC32_FLAGS=/nologo /o"$(OUTDIR)\nsupdate.bsc" BSC32_SBRS= \ "$(INTDIR)\nsupdate.sbr" "$(OUTDIR)\nsupdate.bsc" : "$(OUTDIR)" $(BSC32_SBRS) $(BSC32) @<< $(BSC32_FLAGS) $(BSC32_SBRS) << LINK32=link.exe LINK32_FLAGS=../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib ../../../lib/lwres/win32/Debug/liblwres.lib user32.lib advapi32.lib ws2_32.lib ../../../lib/bind9/win32/Debug/libbind9.lib ../../../lib/isccfg/win32/Debug/libisccfg.lib @GSSAPI_LIB@ @KRB5_LIB@ @READLINE_LIBD@ /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\nsupdate.pdb" /debug @MACHINE@ /out:"../../../Build/Debug/nsupdate.exe" /pdbtype:sept LINK32_OBJS= \ "$(INTDIR)\nsupdate.obj" \ "..\..\..\lib\dns\win32\Debug\libdns.lib" \ "..\..\..\lib\isc\win32\Debug\libisc.lib" \ "..\..\..\lib\bind9\win32\Debug\libbind9.lib" \ "..\..\..\lib\isccfg\win32\Release\libisccfg.lib" "..\..\..\Build\Debug\nsupdate.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) $(LINK32) @<< $(LINK32_FLAGS) $(LINK32_OBJS) << $(_VC_MANIFEST_EMBED_EXE) !ENDIF .c{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .c{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << !IF "$(NO_EXTERNAL_DEPS)" != "1" !IF EXISTS("nsupdate.dep") !INCLUDE "nsupdate.dep" !ELSE !MESSAGE Warning: cannot find "nsupdate.dep" !ENDIF !ENDIF !IF "$(CFG)" == "nsupdate - @PLATFORM@ Release" || "$(CFG)" == "nsupdate - @PLATFORM@ Debug" SOURCE=..\nsupdate.c !IF "$(CFG)" == "nsupdate - @PLATFORM@ Release" "$(INTDIR)\nsupdate.obj" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ELSEIF "$(CFG)" == "nsupdate - @PLATFORM@ Debug" "$(INTDIR)\nsupdate.obj" "$(INTDIR)\nsupdate.sbr" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ENDIF !IF "$(CFG)" == "nsupdate - @PLATFORM@ Release" "libdns - @PLATFORM@ Release" : cd "..\..\..\lib\dns\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Release" cd "..\..\..\bin\nsupdate\win32" "libdns - @PLATFORM@ ReleaseCLEAN" : cd "..\..\..\lib\dns\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Release" RECURSE=1 CLEAN cd "..\..\..\bin\nsupdate\win32" !ELSEIF "$(CFG)" == "nsupdate - @PLATFORM@ Debug" "libdns - @PLATFORM@ Debug" : cd "..\..\..\lib\dns\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Debug" cd "..\..\..\bin\nsupdate\win32" "libdns - @PLATFORM@ DebugCLEAN" : cd "..\..\..\lib\dns\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Debug" RECURSE=1 CLEAN cd "..\..\..\bin\nsupdate\win32" !ENDIF !IF "$(CFG)" == "nsupdate - @PLATFORM@ Release" "libisc - @PLATFORM@ Release" : cd "..\..\..\lib\isc\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Release" cd "..\..\..\bin\nsupdate\win32" "libisc - @PLATFORM@ ReleaseCLEAN" : cd "..\..\..\lib\isc\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Release" RECURSE=1 CLEAN cd "..\..\..\bin\nsupdate\win32" !ELSEIF "$(CFG)" == "nsupdate - @PLATFORM@ Debug" "libisc - @PLATFORM@ Debug" : cd "..\..\..\lib\isc\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Debug" cd "..\..\..\bin\nsupdate\win32" "libisc - @PLATFORM@ DebugCLEAN" : cd "..\..\..\lib\isc\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Debug" RECURSE=1 CLEAN cd "..\..\..\bin\nsupdate\win32" !ENDIF !IF "$(CFG)" == "nsupdate - @PLATFORM@ Release" "libbind9 - @PLATFORM@ Release" : cd "..\..\..\lib\bind9\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - @PLATFORM@ Release" cd "..\..\..\bin\nsupdate\win32" "libbind9 - @PLATFORM@ ReleaseCLEAN" : cd "..\..\..\lib\bind9\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - @PLATFORM@ Release" RECURSE=1 CLEAN cd "..\..\..\bin\nsupdate\win32" !ELSEIF "$(CFG)" == "nsupdate - @PLATFORM@ Debug" "libbind9 - @PLATFORM@ Debug" : cd "..\..\..\lib\bind9\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - @PLATFORM@ Debug" cd "..\..\..\bin\nsupdate\win32" "libbind9 - @PLATFORM@ DebugCLEAN" : cd "..\..\..\lib\bind9\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - @PLATFORM@ Debug" RECURSE=1 CLEAN cd "..\..\..\bin\nsupdate\win32" !ENDIF !ENDIF #################################################### # Commands to generate initial empty manifest file and the RC file # that references it, and for generating the .res file: $(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc $(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest type <<$@ #include 1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest" << KEEP $(_VC_MANIFEST_BASENAME).auto.manifest : type <<$@ << KEEP bind9-9.11.3+dfsg/bin/nsupdate/win32/nsupdate.vcxproj.filters.in000066400000000000000000000013761325250447100244140ustar00rootroot00000000000000 {4FC737F1-C7A5-4376-A066-2A32D752A2FF} cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms Source Files bind9-9.11.3+dfsg/bin/nsupdate/win32/nsupdate.vcxproj.in000066400000000000000000000163641325250447100227500ustar00rootroot00000000000000 Debug @PLATFORM@ Release @PLATFORM@ {C41266C7-E27E-4D60-9815-82D3B32BF82F} Win32Proj nsupdate Application true MultiByte Application false true MultiByte true ..\..\..\Build\$(Configuration)\ .\$(Configuration)\ false ..\..\..\Build\$(Configuration)\ .\$(Configuration)\ Level3 Disabled WIN32;@CRYPTO@@USE_GSSAPI@USE_READLINE_STATIC;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true .\$(Configuration)\$(TargetName).pch .\$(Configuration)\ .\$(Configuration)\ $(OutDir)$(TargetName).pdb true .\;..\include;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@@GSSAPI_INC@@READLINE_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\lwres\win32\include;..\..\..\lib\lwres\include;..\..\..\lib\lwres\win32\include\lwres;..\..\..\lib\dns\include;..\..\..\lib\bind9\include;..\..\..\lib\isccfg\include;%(AdditionalIncludeDirectories) CompileAsC Console true ..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt) ..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);..\..\..\lib\lwres\win32\$(Configuration);..\..\..\lib\bind9\win32\$(Configuration);..\..\..\lib\isccfg\win32\$(Configuration);%(AdditionalLibraryDirectories) @READLINE_LIBD@@GSSAPI_LIB@@KRB5_LIB@libisc.lib;libdns.lib;liblwres.lib;libbind9.lib;libisccfg.lib;ws2_32.lib;%(AdditionalDependencies) Level3 MaxSpeed true @INTRINSIC@ WIN32;@CRYPTO@@USE_GSSAPI@USE_READLINE_STATIC;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) OnlyExplicitInline false true .\$(Configuration)\$(TargetName).pch .\$(Configuration)\ .\$(Configuration)\ $(OutDir)$(TargetName).pdb .\;..\include;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@@GSSAPI_INC@@READLINE_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\lwres\win32\include;..\..\..\lib\lwres\include;..\..\..\lib\lwres\win32\include\lwres;..\..\..\lib\dns\include;..\..\..\lib\bind9\include;..\..\..\lib\isccfg\include;%(AdditionalIncludeDirectories) CompileAsC Console false true true ..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt) Default ..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);..\..\..\lib\lwres\win32\$(Configuration);..\..\..\lib\bind9\win32\$(Configuration);..\..\..\lib\isccfg\win32\$(Configuration);%(AdditionalLibraryDirectories) @READLINE_LIB@@GSSAPI_LIB@@KRB5_LIB@libisc.lib;libdns.lib;liblwres.lib;libbind9.lib;libisccfg.lib;ws2_32.lib;%(AdditionalDependencies) bind9-9.11.3+dfsg/bin/nsupdate/win32/nsupdate.vcxproj.user000066400000000000000000000002171325250447100233060ustar00rootroot00000000000000 bind9-9.11.3+dfsg/bin/pkcs11/000077500000000000000000000000001325250447100154065ustar00rootroot00000000000000bind9-9.11.3+dfsg/bin/pkcs11/Makefile.in000066400000000000000000000062321325250447100174560ustar00rootroot00000000000000# Copyright (C) 2009, 2012, 2014-2016 Internet Systems Consortium, Inc. ("ISC") # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. # $Id: Makefile.in,v 1.2 2009/10/05 12:07:08 fdupont Exp $ srcdir = @srcdir@ VPATH = @srcdir@ top_srcdir = @top_srcdir@ @BIND9_MAKE_INCLUDES@ CINCLUDES = ${ISC_INCLUDES} CDEFINES = ISCLIBS = ../../lib/isc/libisc.@A@ @ISC_OPENSSL_LIBS@ ISCDEPLIBS = ../../lib/isc/libisc.@A@ DEPLIBS = ${ISCDEPLIBS} # if FORCE_STATIC_PROVIDER: LIBS += ${PROVIDER} LIBS = ${ISCLIBS} @LIBS@ SUBDIRS = benchmarks TARGETS = pkcs11-list@EXEEXT@ pkcs11-destroy@EXEEXT@ \ pkcs11-keygen@EXEEXT@ pkcs11-tokens@EXEEXT@ SRCS = pkcs11-list.c pkcs11-destroy.c \ pkcs11-keygen.c pkcs11-tokens.c OBJS = pkcs11-list.@O@ pkcs11-destroy.@O@ \ pkcs11-keygen.@O@ pkcs11-tokens.@O@ MANPAGES = pkcs11-list.8 pkcs11-destroy.8 \ pkcs11-keygen.8 pkcs11-tokens.8 HTMLPAGES = pkcs11-list.html pkcs11-destroy.html \ pkcs11-keygen.html pkcs11-tokens.html MANOBJS = ${MANPAGES} ${HTMLPAGES} @BIND9_MAKE_RULES@ pkcs11-list@EXEEXT@: pkcs11-list.@O@ ${DEPLIBS} ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${ALL_CFLAGS} ${LDFLAGS} \ -o $@ pkcs11-list.@O@ ${LIBS} pkcs11-destroy@EXEEXT@: pkcs11-destroy.@O@ ${DEPLIBS} ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${ALL_CFLAGS} ${LDFLAGS} \ -o $@ pkcs11-destroy.@O@ ${LIBS} pkcs11-keygen@EXEEXT@: pkcs11-keygen.@O@ ${DEPLIBS} ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${ALL_CFLAGS} ${LDFLAGS} \ -o $@ pkcs11-keygen.@O@ ${LIBS} pkcs11-tokens@EXEEXT@: pkcs11-tokens.@O@ ${DEPLIBS} ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${ALL_CFLAGS} ${LDFLAGS} \ -o $@ pkcs11-tokens.@O@ ${LIBS} doc man:: ${MANOBJS} docclean manclean maintainer-clean:: rm -f ${MANOBJS} installdirs: $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${sbindir} $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${mandir}/man8 install:: ${TARGETS} installdirs ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} pkcs11-list@EXEEXT@ \ ${DESTDIR}${sbindir} ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} pkcs11-destroy@EXEEXT@ \ ${DESTDIR}${sbindir} ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} pkcs11-keygen@EXEEXT@ \ ${DESTDIR}${sbindir} ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} pkcs11-tokens@EXEEXT@ \ ${DESTDIR}${sbindir} ${INSTALL_DATA} ${srcdir}/pkcs11-list.8 ${DESTDIR}${mandir}/man8 ${INSTALL_DATA} ${srcdir}/pkcs11-destroy.8 ${DESTDIR}${mandir}/man8 ${INSTALL_DATA} ${srcdir}/pkcs11-keygen.8 ${DESTDIR}${mandir}/man8 ${INSTALL_DATA} ${srcdir}/pkcs11-tokens.8 ${DESTDIR}${mandir}/man8 uninstall:: rm -f ${DESTDIR}${mandir}/man8/pkcs11-tokens.8 rm -f ${DESTDIR}${mandir}/man8/pkcs11-keygen.8 rm -f ${DESTDIR}${mandir}/man8/pkcs11-destroy.8 rm -f ${DESTDIR}${mandir}/man8/pkcs11-list.8 ${LIBTOOL_MODE_UNINSTALL} rm -f / ${DESTDIR}${sbindir}/pkcs11-tokens@EXEEXT@ ${LIBTOOL_MODE_UNINSTALL} rm -f / ${DESTDIR}${sbindir}/pkcs11-keygen@EXEEXT@ ${LIBTOOL_MODE_UNINSTALL} rm -f / ${DESTDIR}${sbindir}/pkcs11-destroy@EXEEXT@ ${LIBTOOL_MODE_UNINSTALL} rm -f / ${DESTDIR}${sbindir}/pkcs11-list@EXEEXT@ clean distclean:: rm -f ${OBJS} ${TARGETS} bind9-9.11.3+dfsg/bin/pkcs11/OLD-PKCS11-NOTES000066400000000000000000000063301325250447100175370ustar00rootroot00000000000000 BIND-9 PKCS#11 support Prerequisite The PKCS#11 support needs a PKCS#11 OpenSSL engine based on the Solaris one, released the 2008-12-02 for OpenSSL 0.9.8i, with back port of key by reference and some improvements, including user friendly PIN management. You may also use the original engine code. Compilation "configure --with-pkcs11 ..." PKCS#11 Libraries Tested with Solaris one with a SCA board and with openCryptoki with the software token. Known to work on Linux and Windows 2003 server so should work on most operating systems. For AEP Keyper or any device used only for its protected key store, please switch to the sign-only engine. OpenSSL Engines With PKCS#11 support the PKCS#11 engine is statically loaded but at its initialization it dynamically loads the PKCS#11 objects. Even the pre commands are therefore unused they are defined with: SO_PATH: define: PKCS11_SO_PATH default: /usr/local/lib/engines/engine_pkcs11.so MODULE_PATH: define: PKCS11_MODULE_PATH default: /usr/lib/libpkcs11.so Without PKCS#11 support, a specific OpenSSL engine can be still used by defining ENGINE_ID at compile time. PKCS#11 tools The contrib/pkcs11-keygen directory contains a set of experimental tools to handle keys stored in a Hardware Security Module at the benefit of BIND. The patch for OpenSSL 0.9.8i is in this directory. Read its README.pkcs11 for the way to use it (these are the original notes so with the original path, etc. Define HAVE_GETPASSPHRASE if you have getpassphrase() on a operating system which is not Solaris.) Not all tools are supported on AEP Keyper but genkey and dnssec-keyfromlabel are functional. PIN management With the just fixed PKCS#11 OpenSSL engine, the PIN should be entered each time it is required. With the improved engine, the PIN should be entered the first time it is required or can be configured in the OpenSSL configuration file (aka. openssl.cnf) by adding in it: - at the beginning: openssl_conf = openssl_def - at any place these sections: [ openssl_def ] engines = engine_section [ engine_section ] pkcs11 = pkcs11_section [ pkcs11_section ] PIN = put__your__pin__value__here Slot management The engine tries to use the first best slot but it is recommended to simply use the slot 0 (usual default, meta-slot on Solaris). Sign-only engine openssl.../crypto/engine/hw_pk11-kp.c and hw_pk11_pub-kp.c contain a stripped down version of hw_pk11.c and hw_pk11_pub.c files which has only the useful functions (i.e., signature with a RSA private key in the device protected key store and key loading). This engine should be used with a device which provides mainly a protected store and no acceleration. AEP Keyper is an example of such a device (BTW with the fully capable engine, key export must be enabled on this device and this configuration is not yet supported). Original engine If you are using the original engine and getpassphrase() is not defined, add: #define getpassphrase(x) getpass(x) in openssl.../crypto/engine/hw_pk11_pub.c Notes Some names here are registered trademarks, at least Solaris is a trademark of Sun Microsystems Inc... Include files are from RSA Labs., PKCS#11 version is 2.20 amendment 3. The PKCS#11 support is compatible with the forthcoming FIPS 140-2 support. bind9-9.11.3+dfsg/bin/pkcs11/openssl-0.9.8zh-patch000066400000000000000000016376641325250447100211540ustar00rootroot00000000000000Index: openssl/Configure diff -u openssl/Configure:1.8.6.1.4.1.2.1 openssl/Configure:1.8.2.2 --- openssl/Configure:1.8.6.1.4.1.2.1 Thu Jul 3 12:12:31 2014 +++ openssl/Configure Thu Jul 3 12:31:57 2014 @@ -12,7 +12,7 @@ # see INSTALL for instructions. -my $usage="Usage: Configure [no- ...] [enable- ...] [experimental- ...] [-Dxxx] [-lxxx] [-Lxxx] [-fxxx] [-Kxxx] [no-hw-xxx|no-hw] [[no-]threads] [[no-]shared] [[no-]zlib|zlib-dynamic] [enable-montasm] [no-asm] [no-dso] [no-krb5] [386] [--prefix=DIR] [--openssldir=OPENSSLDIR] [--with-xxx[=vvv]] [--test-sanity] os/compiler[:flags]\n"; +my $usage="Usage: Configure --pk11-libname=PK11_LIB_LOCATION --pk11-flavor=FLAVOR [no- ...] [enable- ...] [experimental- ...] [-Dxxx] [-lxxx] [-Lxxx] [-fxxx] [-Kxxx] [no-hw-xxx|no-hw] [[no-]threads] [[no-]shared] [[no-]zlib|zlib-dynamic] [enable-montasm] [no-asm] [no-dso] [no-krb5] [386] [--prefix=DIR] [--openssldir=OPENSSLDIR] [--with-xxx[=vvv]] [--test-sanity] os/compiler[:flags]\n"; # Options: # @@ -25,6 +25,12 @@ # default). This needn't be set in advance, you can # just as well use "make INSTALL_PREFIX=/whatever install". # +# --pk11-libname PKCS#11 library name. +# (No default) +# +# --pk11-flavor either crypto-accelerator or sign-only +# (No default) +# # --with-krb5-dir Declare where Kerberos 5 lives. The libraries are expected # to live in the subdirectory lib/ and the header files in # include/. A value is required. @@ -336,7 +342,7 @@ "linux-ppc", "gcc:-DB_ENDIAN -DTERMIO -O3 -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_RISC1 DES_UNROLL::linux_ppc32.o::::::::::dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", #### IA-32 targets... "linux-ia32-icc", "icc:-DL_ENDIAN -DTERMIO -O2 -no_cpprt::-D_REENTRANT::-ldl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_elf_asm}:dlfcn:linux-shared:-KPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", -"linux-elf", "gcc:-DL_ENDIAN -DTERMIO -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_elf_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", +"linux-elf", "gcc:-DL_ENDIAN -DTERMIO -O3 -fomit-frame-pointer -Wall::-D_REENTRANT -pthread::-ldl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_elf_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", "linux-aout", "gcc:-DL_ENDIAN -DTERMIO -O3 -fomit-frame-pointer -march=i486 -Wall::(unknown):::BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_out_asm}", #### "linux-generic64","gcc:-DTERMIO -O3 -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${no_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", @@ -344,7 +350,7 @@ "linux-ia64", "gcc:-DL_ENDIAN -DTERMIO -O3 -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHUNK:${ia64_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", "linux-ia64-ecc","ecc:-DL_ENDIAN -DTERMIO -O2 -Wall -no_cpprt::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHUNK:${ia64_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", "linux-ia64-icc","icc:-DL_ENDIAN -DTERMIO -O2 -Wall -no_cpprt::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHUNK:${ia64_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", -"linux-x86_64", "gcc:-m64 -DL_ENDIAN -DTERMIO -O3 -Wall -DMD32_REG_T=int::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_INT DES_UNROLL:${x86_64_asm}:dlfcn:linux-shared:-fPIC:-m64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", +"linux-x86_64", "gcc:-m64 -DL_ENDIAN -DTERMIO -O3 -Wall -DMD32_REG_T=int::-D_REENTRANT -pthread::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_INT DES_UNROLL:${x86_64_asm}:dlfcn:linux-shared:-fPIC:-m64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", #### SPARC Linux setups # Ray Miller has patiently # assisted with debugging of following two configs. @@ -591,6 +597,10 @@ my $idx_ranlib = $idx++; my $idx_arflags = $idx++; +# PKCS#11 engine patch +my $pk11_libname=""; +my $pk11_flavor=""; + my $prefix=""; my $libdir=""; my $openssldir=""; @@ -829,6 +839,14 @@ { $flags.=$_." "; } + elsif (/^--pk11-libname=(.*)$/) + { + $pk11_libname=$1; + } + elsif (/^--pk11-flavor=(.*)$/) + { + $pk11_flavor=$1; + } elsif (/^--prefix=(.*)$/) { $prefix=$1; @@ -964,6 +982,22 @@ exit 0; } +if (! $pk11_libname) + { + print STDERR "You must set --pk11-libname for PKCS#11 library.\n"; + print STDERR "See README.pkcs11 for more information.\n"; + exit 1; + } + +if (! $pk11_flavor + || !($pk11_flavor eq "crypto-accelerator" || $pk11_flavor eq "sign-only")) + { + print STDERR "You must set --pk11-flavor.\n"; + print STDERR "Choices are crypto-accelerator and sign-only.\n"; + print STDERR "See README.pkcs11 for more information.\n"; + exit 1; + } + if ($target =~ m/^CygWin32(-.*)$/) { $target = "Cygwin".$1; } @@ -1079,6 +1113,25 @@ print "\n"; } +if ($pk11_flavor eq "crypto-accelerator") + { + $openssl_other_defines .= "#define OPENSSL_NO_HW_PKCS11SO\n"; + $default_depflags .= " -DOPENSSL_NO_HW_PKCS11SO"; + $depflags .= " -DOPENSSL_NO_HW_PKCS11SO"; + $options .= " no-hw-pkcs11so"; + print " no-hw-pkcs11so [pk11-flavor]"; + print " OPENSSL_NO_HW_PKCS11SO\n"; + } +else + { + $openssl_other_defines .= "#define OPENSSL_NO_HW_PKCS11CA\n"; + $default_depflags .= " -DOPENSSL_NO_HW_PKCS11CA"; + $depflags .= " -DOPENSSL_NO_HW_PKCS11CA"; + $options .= " no-hw-pkcs11ca"; + print " no-hw-pkcs11ca [pk11-flavor]"; + print " OPENSSL_NO_HW_PKCS11CA\n"; +} + my $IsMK1MF=scalar grep /^$target$/,@MK1MF_Builds; $IsMK1MF=1 if ($target eq "mingw" && $^O ne "cygwin" && !is_msys()); @@ -1130,6 +1183,8 @@ if ($flags ne "") { $cflags="$flags$cflags"; } else { $no_user_cflags=1; } +$cflags="-DPK11_LIB_LOCATION=\"$pk11_libname\" $cflags"; + # Kerberos settings. The flavor must be provided from outside, either through # the script "config" or manually. if (!$no_krb5) @@ -1493,6 +1548,7 @@ s/^VERSION=.*/VERSION=$version/; s/^MAJOR=.*/MAJOR=$major/; s/^MINOR=.*/MINOR=$minor/; + s/^PK11_LIB_LOCATION=.*/PK11_LIB_LOCATION=$pk11_libname/; s/^SHLIB_VERSION_NUMBER=.*/SHLIB_VERSION_NUMBER=$shlib_version_number/; s/^SHLIB_VERSION_HISTORY=.*/SHLIB_VERSION_HISTORY=$shlib_version_history/; s/^SHLIB_MAJOR=.*/SHLIB_MAJOR=$shlib_major/; Index: openssl/Makefile.org diff -u openssl/Makefile.org:1.4.6.1.6.1.6.1 openssl/Makefile.org:1.4.2.2 --- openssl/Makefile.org:1.4.6.1.6.1.6.1 Wed Dec 23 16:02:57 2015 +++ openssl/Makefile.org Wed Dec 23 16:44:50 2015 @@ -26,6 +26,9 @@ INSTALL_PREFIX= INSTALLTOP=/usr/local/ssl +# You must set this through --pk11-libname configure option. +PK11_LIB_LOCATION= + # Do not edit this manually. Use Configure --openssldir=DIR do change this! OPENSSLDIR=/usr/local/ssl Index: openssl/README.pkcs11 diff -u /dev/null openssl/README.pkcs11:1.6.4.2 --- /dev/null Wed Dec 23 16:49:05 2015 +++ openssl/README.pkcs11 Fri Oct 4 14:45:25 2013 @@ -0,0 +1,266 @@ +ISC modified +============ + +The previous key naming scheme was kept for backward compatibility. + +The PKCS#11 engine exists in two flavors, crypto-accelerator and +sign-only. The first one is from the Solaris patch and uses the +PKCS#11 device for all crypto operations it supports. The second +is a stripped down version which provides only the useful +function (i.e., signature with a RSA private key in the device +protected key store and key loading). + +As a hint PKCS#11 boards should use the crypto-accelerator flavor, +external PKCS#11 devices the sign-only. SCA 6000 is an example +of the first, AEP Keyper of the second. + +Note it is mandatory to set a pk11-flavor (and only one) in +config/Configure. + +It is highly recommended to compile in (vs. as a DSO) the engine. +The way to configure this is system dependent, on Unixes it is no-shared +(and is in general the default), on WIN32 it is enable-static-engine +(and still enable to build the OpenSSL libraries as DLLs). + +PKCS#11 engine support for OpenSSL 0.9.8l +========================================= + +[Nov 19, 2009] + +Contents: + +Overview +Revisions of the patch for 0.9.8 branch +FAQs +Feedback + +Overview +======== + +This patch containing code available in OpenSolaris adds support for PKCS#11 +engine into OpenSSL and implements PKCS#11 v2.20. It is to be applied against +OpenSSL 0.9.8l source code distribution as shipped by OpenSSL.Org. Your system +must provide PKCS#11 backend otherwise the patch is useless. You provide the +PKCS#11 library name during the build configuration phase, see below. + +Patch can be applied like this: + + # NOTE: use gtar if on Solaris + tar xfzv openssl-0.9.8l.tar.gz + # now download the patch to the current directory + # ... + cd openssl-0.9.8l + # NOTE: must use gpatch if on Solaris (is part of the system) + patch -p1 < path-to/pkcs11_engine-0.9.8l.patch.2009-11-19 + +It is designed to support pure acceleration for RSA, DSA, DH and all the +symetric ciphers and message digest algorithms that PKCS#11 and OpenSSL share +except for missing support for patented algorithms MDC2, RC3, RC5 and IDEA. + +According to the PKCS#11 providers installed on your machine, it can support +following mechanisms: + + RSA, DSA, DH, RAND, DES-CBC, DES-EDE3-CBC, DES-ECB, DES-EDE3, RC4, + AES-128-CBC, AES-192-CBC, AES-256-CBC, AES-128-ECB, AES-192-ECB, + AES-256-ECB, AES-128-CTR, AES-192-CTR, AES-256-CTR, MD5, SHA1, SHA224, + SHA256, SHA384, SHA512 + +Note that for AES counter mode the application must provide their own EVP +functions since OpenSSL doesn't support counter mode through EVP yet. You may +see OpenSSH source code (cipher.c) to get the idea how to do that. SunSSH is an +example of code that uses the PKCS#11 engine and deals with the fork-safety +problem (see engine.c and packet.c files if interested). + +You must provide the location of PKCS#11 library in your system to the +configure script. You will be instructed to do that when you try to run the +config script: + + $ ./config + Operating system: i86pc-whatever-solaris2 + Configuring for solaris-x86-cc + You must set --pk11-libname for PKCS#11 library. + See README.pkcs11 for more information. + +Taking openCryptoki project on Linux AMD64 box as an example, you would run +configure script like this: + + ./config --pk11-libname=/usr/lib64/pkcs11/PKCS11_API.so + +To check whether newly built openssl really supports PKCS#11 it's enough to run +"apps/openssl engine" and look for "(pkcs11) PKCS #11 engine support" in the +output. If you see no PKCS#11 engine support check that the built openssl binary +and the PKCS#11 library from --pk11-libname don't conflict on 32/64 bits. + +The patch, during various phases of development, was tested on Solaris against +PKCS#11 engine available from Solaris Cryptographic Framework (Solaris 10 and +OpenSolaris) and also on Linux using PKCS#11 libraries from openCryptoki project +(see openCryptoki website http://sourceforge.net/projects/opencryptoki for more +information). Some Linux distributions even ship those libraries with the +system. The patch should work on any system that is supported by OpenSSL itself +and has functional PKCS#11 library. + +The patch contains "RSA Security Inc. PKCS #11 Cryptographic Token Interface +(Cryptoki)" - files cryptoki.h, pkcs11.h, pkcs11f.h and pkcs11t.h which are +copyrighted by RSA Security Inc., see pkcs11.h for more information. + +Other added/modified code in this patch is copyrighted by Sun Microsystems, +Inc. and is released under the OpenSSL license (see LICENSE file for more +information). + +Revisions of the patch for 0.9.8 branch +======================================= + +2009-11-19 +- adjusted for OpenSSL version 0.9.8l + +- bugs and RFEs: + + 6479874 OpenSSL should support RSA key by reference/hardware keystores + 6896677 PKCS#11 engine's hw_pk11_err.h needs to be split + 6732677 make check to trigger Solaris specific code automatic in the + PKCS#11 engine + +2009-03-11 +- adjusted for OpenSSL version 0.9.8j + +- README.pkcs11 moved out of the patch, and is shipped together with it in a + tarball instead so that it can be read before the patch is applied. + +- fixed bugs: + + 6804216 pkcs#11 engine should support a key length range for RC4 + 6734038 Apache SSL web server using the pkcs11 engine fails to start if + meta slot is disabled + +2008-12-02 +- fixed bugs and RFEs (most of the work done by Vladimir Kotal) + + 6723504 more granular locking in PKCS#11 engine + 6667128 CRYPTO_LOCK_PK11_ENGINE assumption does not hold true + 6710420 PKCS#11 engine source should be lint clean + 6747327 PKCS#11 engine atfork handlers need to be aware of guys who take + it seriously + 6746712 PKCS#11 engine source code should be cstyle clean + 6731380 return codes of several functions are not checked in the PKCS#11 + engine code + 6746735 PKCS#11 engine should use extended FILE space API + 6734038 Apache SSL web server using the pkcs11 engine fails to start if + meta slot is disabled + +2008-08-01 +- fixed bug + + 6731839 OpenSSL PKCS#11 engine no longer uses n2cp for symmetric ciphers + and digests + +- Solaris specific code for slot selection made automatic + +2008-07-29 +- update the patch to OpenSSL 0.9.8h version +- pkcs11t.h updated to the latest version: + + 6545665 make CKM_AES_CTR available to non-kernel users + +- fixed bugs in the engine code: + + 6602801 PK11_SESSION cache has to employ reference counting scheme for + asymmetric key operations + 6605538 pkcs11 functions C_FindObjects[{Init,Final}]() not called + atomically + 6607307 pkcs#11 engine can't read RSA private keys + 6652362 pk11_RSA_finish() is cutting corners + 6662112 pk11_destroy_{rsa,dsa,dh}_key_objects() use locking in + suboptimal way + 6666625 pk11_destroy_{rsa,dsa,dh}_key_objects() should be more + resilient to destroy failures + 6667273 OpenSSL engine should not use free() but OPENSSL_free() + 6670363 PKCS#11 engine fails to reuse existing symmetric keys + 6678135 memory corruption in pk11_DH_generate_key() in pkcs#11 engine + 6678503 DSA signature conversion in pk11_dsa_do_verify() ignores size + of big numbers leading to failures + 6706562 pk11_DH_compute_key() returns 0 in case of failure instead of + -1 + 6706622 pk11_load_{pub,priv}key create corrupted RSA key references + 6707129 return values from BN_new() in pk11_DH_generate_key() are not + checked + 6707274 DSA/RSA/DH PKCS#11 engine operations need to be resistant to + structure reuse + 6707782 OpenSSL PKCS#11 engine pretends to be aware of + OPENSSL_NO_{RSA,DSA,DH} + defines but fails miserably + 6709966 make check_new_*() to return values to indicate cache hit/miss + 6705200 pk11_dh struct initialization in PKCS#11 engine is missing + generate_params parameter + 6709513 PKCS#11 engine sets IV length even for ECB modes + 6728296 buffer length not initialized for C_(En|De)crypt_Final() in the + PKCS#11 engine + 6728871 PKCS#11 engine must reset global_session in pk11_finish() + +- new features and enhancements: + + 6562155 OpenSSL pkcs#11 engine needs support for SHA224/256/384/512 + 6685012 OpenSSL pkcs#11 engine needs support for new cipher modes + 6725903 OpenSSL PKCS#11 engine shouldn't use soft token for symmetric + ciphers and digests + +2007-10-15 +- update for 0.9.8f version +- update for "6607670 teach pkcs#11 engine how to use keys be reference" + +2007-10-02 +- draft for "6607670 teach pkcs#11 engine how to use keys be reference" +- draft for "6607307 pkcs#11 engine can't read RSA private keys" + +2007-09-26 +- 6375348 Using pkcs11 as the SSLCryptoDevice with Apache/OpenSSL causes + significant performance drop +- 6573196 memory is leaked when OpenSSL is used with PKCS#11 engine + +2007-05-25 +- 6558630 race in OpenSSL pkcs11 engine when using symetric block ciphers + +2007-05-19 +- initial patch for 0.9.8e using latest OpenSolaris code + +FAQs +==== + +(1) my build failed on Linux distro with this error: + +../libcrypto.a(hw_pk11.o): In function `pk11_library_init': +hw_pk11.c:(.text+0x20f5): undefined reference to `pthread_atfork' + +Answer: + + - don't use "no-threads" when configuring + - if you didn't then OpenSSL failed to create a threaded library by + default. You may manually edit Configure and try again. Look for the + architecture that Configure printed, for example: + +Configured for linux-elf. + + - then edit Configure, find string "linux-elf" (inluding the quotes), + and add flags to support threads to the 4th column of the 2nd string. + If you build with GCC then adding "-pthread" should be enough. With + "linux-elf" as an example, you would add " -pthread" right after + "-D_REENTRANT", like this: + +....-O3 -fomit-frame-pointer -Wall::-D_REENTRANT -pthread::-ldl:..... + +(2) I'm using MinGW/MSYS environment and get undeclared reference error for +pthread_atfork() function when trying to build OpenSSL with the patch. + +Answer: + + Sorry, pthread_atfork() is not implemented in the current pthread-win32 + (as of Nov 2009). You can not use the patch there. + + +Feedback +======== + +Please send feedback to security-discuss@opensolaris.org. The patch was +created by Jan.Pechanec@Sun.COM from code available in OpenSolaris. + +Latest version should be always available on http://blogs.sun.com/janp. + Index: openssl/crypto/opensslconf.h diff -u openssl/crypto/opensslconf.h:1.5.10.1 openssl/crypto/opensslconf.h:1.5 --- openssl/crypto/opensslconf.h:1.5.10.1 Sun Jan 15 15:45:34 2012 +++ openssl/crypto/opensslconf.h Fri Sep 4 10:43:21 2009 @@ -38,6 +38,9 @@ #endif /* OPENSSL_DOING_MAKEDEPEND */ +#ifndef OPENSSL_THREADS +# define OPENSSL_THREADS +#endif #ifndef OPENSSL_NO_DYNAMIC_ENGINE # define OPENSSL_NO_DYNAMIC_ENGINE #endif @@ -79,6 +82,8 @@ # endif #endif +#define OPENSSL_CPUID_OBJ + /* crypto/opensslconf.h.in */ #ifdef OPENSSL_DOING_MAKEDEPEND @@ -140,7 +145,7 @@ * This enables code handling data aligned at natural CPU word * boundary. See crypto/rc4/rc4_enc.c for further details. */ -#undef RC4_CHUNK +#define RC4_CHUNK unsigned long #endif #endif @@ -148,7 +153,7 @@ /* If this is set to 'unsigned int' on a DEC Alpha, this gives about a * %20 speed up (longs are 8 bytes, int's are 4). */ #ifndef DES_LONG -#define DES_LONG unsigned long +#define DES_LONG unsigned int #endif #endif @@ -162,9 +167,9 @@ /* The prime number generation stuff may not work when * EIGHT_BIT but I don't care since I've only used this mode * for debuging the bignum libraries */ -#undef SIXTY_FOUR_BIT_LONG +#define SIXTY_FOUR_BIT_LONG #undef SIXTY_FOUR_BIT -#define THIRTY_TWO_BIT +#undef THIRTY_TWO_BIT #undef SIXTEEN_BIT #undef EIGHT_BIT #endif @@ -178,7 +183,7 @@ #if defined(HEADER_BF_LOCL_H) && !defined(CONFIG_HEADER_BF_LOCL_H) #define CONFIG_HEADER_BF_LOCL_H -#undef BF_PTR +#define BF_PTR2 #endif /* HEADER_BF_LOCL_H */ #if defined(HEADER_DES_LOCL_H) && !defined(CONFIG_HEADER_DES_LOCL_H) @@ -208,7 +213,7 @@ /* Unroll the inner loop, this sometimes helps, sometimes hinders. * Very mucy CPU dependant */ #ifndef DES_UNROLL -#undef DES_UNROLL +#define DES_UNROLL #endif /* These default values were supplied by Index: openssl/crypto/bio/bss_file.c diff -u openssl/crypto/bio/bss_file.c:1.5.6.1.12.1 openssl/crypto/bio/bss_file.c:1.5.2.1 --- openssl/crypto/bio/bss_file.c:1.5.6.1.12.1 Wed Dec 23 16:03:19 2015 +++ openssl/crypto/bio/bss_file.c Wed Dec 23 16:45:10 2015 @@ -123,7 +123,7 @@ if ((file = fopen(filename, mode)) == NULL) { SYSerr(SYS_F_FOPEN, get_last_sys_error()); ERR_add_error_data(5, "fopen('", filename, "','", mode, "')"); - if (errno == ENOENT) + if ((errno == ENOENT) || ((*mode == 'r') && (errno == EACCES))) BIOerr(BIO_F_BIO_NEW_FILE, BIO_R_NO_SUCH_FILE); else BIOerr(BIO_F_BIO_NEW_FILE, ERR_R_SYS_LIB); Index: openssl/crypto/engine/Makefile diff -u openssl/crypto/engine/Makefile:1.6.6.1 openssl/crypto/engine/Makefile:1.6 --- openssl/crypto/engine/Makefile:1.6.6.1 Sun Jan 15 15:45:35 2012 +++ openssl/crypto/engine/Makefile Mon Jun 13 14:25:19 2011 @@ -21,12 +21,14 @@ eng_table.c eng_pkey.c eng_fat.c eng_all.c \ tb_rsa.c tb_dsa.c tb_ecdsa.c tb_dh.c tb_ecdh.c tb_rand.c tb_store.c \ tb_cipher.c tb_digest.c \ - eng_openssl.c eng_cnf.c eng_dyn.c eng_cryptodev.c eng_padlock.c + eng_openssl.c eng_cnf.c eng_dyn.c eng_cryptodev.c eng_padlock.c \ + hw_pk11.c hw_pk11_pub.c hw_pk11so.c hw_pk11so_pub.c LIBOBJ= eng_err.o eng_lib.o eng_list.o eng_init.o eng_ctrl.o \ eng_table.o eng_pkey.o eng_fat.o eng_all.o \ tb_rsa.o tb_dsa.o tb_ecdsa.o tb_dh.o tb_ecdh.o tb_rand.o tb_store.o \ tb_cipher.o tb_digest.o \ - eng_openssl.o eng_cnf.o eng_dyn.o eng_cryptodev.o eng_padlock.o + eng_openssl.o eng_cnf.o eng_dyn.o eng_cryptodev.o eng_padlock.o \ + hw_pk11.o hw_pk11_pub.o hw_pk11so.o hw_pk11so_pub.o SRC= $(LIBSRC) @@ -288,6 +290,102 @@ eng_table.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h eng_table.o: ../../include/openssl/x509_vfy.h ../cryptlib.h eng_int.h eng_table.o: eng_table.c +hw_pk11.o: ../../include/openssl/e_os2.h ../../include/openssl/opensslconf.h +hw_pk11.o: ../../include/openssl/engine.h ../../include/openssl/ossl_typ.h +hw_pk11.o: ../../include/openssl/bn.h ../../include/openssl/rsa.h +hw_pk11.o: ../../include/openssl/asn1.h ../../include/openssl/bio.h +hw_pk11.o: ../../include/openssl/crypto.h ../../include/openssl/stack.h +hw_pk11.o: ../../include/openssl/safestack.h ../../include/openssl/opensslv.h +hw_pk11.o: ../../include/openssl/symhacks.h ../../include/openssl/dsa.h +hw_pk11.o: ../../include/openssl/dh.h ../../include/openssl/rand.h +hw_pk11.o: ../../include/openssl/ui.h ../../include/openssl/err.h +hw_pk11.o: ../../include/openssl/lhash.h ../../include/openssl/dso.h +hw_pk11.o: ../../include/openssl/pem.h ../../include/openssl/evp.h +hw_pk11.o: ../../include/openssl/md2.h ../../include/openssl/md4.h +hw_pk11.o: ../../include/openssl/md5.h ../../include/openssl/sha.h +hw_pk11.o: ../../include/openssl/ripemd.h ../../include/openssl/des.h +hw_pk11.o: ../../include/openssl/des_old.h ../../include/openssl/ui_compat.h +hw_pk11.o: ../../include/openssl/rc4.h ../../include/openssl/rc2.h +hw_pk11.o: ../../crypto/rc5/rc5.h ../../include/openssl/blowfish.h +hw_pk11.o: ../../include/openssl/cast.h ../../include/openssl/idea.h +hw_pk11.o: ../../crypto/mdc2/mdc2.h ../../include/openssl/aes.h +hw_pk11.o: ../../include/openssl/objects.h ../../include/openssl/obj_mac.h +hw_pk11.o: ../../include/openssl/x509.h ../../include/openssl/buffer.h +hw_pk11.o: ../../include/openssl/x509_vfy.h ../../include/openssl/pkcs7.h +hw_pk11.o: ../../include/openssl/pem2.h ../cryptlib.h +hw_pk11.o: ../../e_os.h hw_pk11_err.c hw_pk11_err.h hw_pk11.c +hw_pk11_pub.o: ../../include/openssl/e_os2.h ../../include/openssl/opensslconf.h +hw_pk11_pub.o: ../../include/openssl/engine.h ../../include/openssl/ossl_typ.h +hw_pk11_pub.o: ../../include/openssl/bn.h ../../include/openssl/rsa.h +hw_pk11_pub.o: ../../include/openssl/asn1.h ../../include/openssl/bio.h +hw_pk11_pub.o: ../../include/openssl/crypto.h ../../include/openssl/stack.h +hw_pk11_pub.o: ../../include/openssl/safestack.h ../../include/openssl/opensslv.h +hw_pk11_pub.o: ../../include/openssl/symhacks.h ../../include/openssl/dsa.h +hw_pk11_pub.o: ../../include/openssl/dh.h ../../include/openssl/rand.h +hw_pk11_pub.o: ../../include/openssl/ui.h ../../include/openssl/err.h +hw_pk11_pub.o: ../../include/openssl/lhash.h ../../include/openssl/dso.h +hw_pk11_pub.o: ../../include/openssl/pem.h ../../include/openssl/evp.h +hw_pk11_pub.o: ../../include/openssl/md2.h ../../include/openssl/md4.h +hw_pk11_pub.o: ../../include/openssl/md5.h ../../include/openssl/sha.h +hw_pk11_pub.o: ../../include/openssl/ripemd.h ../../include/openssl/des.h +hw_pk11_pub.o: ../../include/openssl/des_old.h ../../include/openssl/ui_compat.h +hw_pk11_pub.o: ../../include/openssl/rc4.h ../../include/openssl/rc2.h +hw_pk11_pub.o: ../../crypto/rc5/rc5.h ../../include/openssl/blowfish.h +hw_pk11_pub.o: ../../include/openssl/cast.h ../../include/openssl/idea.h +hw_pk11_pub.o: ../../crypto/mdc2/mdc2.h ../../include/openssl/aes.h +hw_pk11_pub.o: ../../include/openssl/objects.h ../../include/openssl/obj_mac.h +hw_pk11_pub.o: ../../include/openssl/x509.h ../../include/openssl/buffer.h +hw_pk11_pub.o: ../../include/openssl/x509_vfy.h ../../include/openssl/pkcs7.h +hw_pk11_pub.o: ../../include/openssl/pem2.h ../cryptlib.h +hw_pk11_pub.o: ../../e_os.h hw_pk11_err.c hw_pk11_err.h hw_pk11_pub.c +hw_pk11so.o: ../../include/openssl/e_os2.h ../../include/openssl/opensslconf.h +hw_pk11so.o: ../../include/openssl/engine.h ../../include/openssl/ossl_typ.h +hw_pk11so.o: ../../include/openssl/bn.h ../../include/openssl/rsa.h +hw_pk11so.o: ../../include/openssl/asn1.h ../../include/openssl/bio.h +hw_pk11so.o: ../../include/openssl/crypto.h ../../include/openssl/stack.h +hw_pk11so.o: ../../include/openssl/safestack.h ../../include/openssl/opensslv.h +hw_pk11so.o: ../../include/openssl/symhacks.h ../../include/openssl/dsa.h +hw_pk11so.o: ../../include/openssl/dh.h ../../include/openssl/rand.h +hw_pk11so.o: ../../include/openssl/ui.h ../../include/openssl/err.h +hw_pk11so.o: ../../include/openssl/lhash.h ../../include/openssl/dso.h +hw_pk11so.o: ../../include/openssl/pem.h ../../include/openssl/evp.h +hw_pk11so.o: ../../include/openssl/md2.h ../../include/openssl/md4.h +hw_pk11so.o: ../../include/openssl/md5.h ../../include/openssl/sha.h +hw_pk11so.o: ../../include/openssl/ripemd.h ../../include/openssl/des.h +hw_pk11so.o: ../../include/openssl/des_old.h ../../include/openssl/ui_compat.h +hw_pk11so.o: ../../include/openssl/rc4.h ../../include/openssl/rc2.h +hw_pk11so.o: ../../crypto/rc5/rc5.h ../../include/openssl/blowfish.h +hw_pk11so.o: ../../include/openssl/cast.h ../../include/openssl/idea.h +hw_pk11so.o: ../../crypto/mdc2/mdc2.h ../../include/openssl/aes.h +hw_pk11so.o: ../../include/openssl/objects.h ../../include/openssl/obj_mac.h +hw_pk11so.o: ../../include/openssl/x509.h ../../include/openssl/buffer.h +hw_pk11so.o: ../../include/openssl/x509_vfy.h ../../include/openssl/pkcs7.h +hw_pk11so.o: ../../include/openssl/pem2.h ../cryptlib.h +hw_pk11so.o: ../../e_os.h hw_pk11_err.c hw_pk11_err.h hw_pk11so.c +hw_pk11so_pub.o: ../../include/openssl/e_os2.h ../../include/openssl/opensslconf.h +hw_pk11so_pub.o: ../../include/openssl/engine.h ../../include/openssl/ossl_typ.h +hw_pk11so_pub.o: ../../include/openssl/bn.h ../../include/openssl/rsa.h +hw_pk11so_pub.o: ../../include/openssl/asn1.h ../../include/openssl/bio.h +hw_pk11so_pub.o: ../../include/openssl/crypto.h ../../include/openssl/stack.h +hw_pk11so_pub.o: ../../include/openssl/safestack.h ../../include/openssl/opensslv.h +hw_pk11so_pub.o: ../../include/openssl/symhacks.h ../../include/openssl/dsa.h +hw_pk11so_pub.o: ../../include/openssl/dh.h ../../include/openssl/rand.h +hw_pk11so_pub.o: ../../include/openssl/ui.h ../../include/openssl/err.h +hw_pk11so_pub.o: ../../include/openssl/lhash.h ../../include/openssl/dso.h +hw_pk11so_pub.o: ../../include/openssl/pem.h ../../include/openssl/evp.h +hw_pk11so_pub.o: ../../include/openssl/md2.h ../../include/openssl/md4.h +hw_pk11so_pub.o: ../../include/openssl/md5.h ../../include/openssl/sha.h +hw_pk11so_pub.o: ../../include/openssl/ripemd.h ../../include/openssl/des.h +hw_pk11so_pub.o: ../../include/openssl/des_old.h ../../include/openssl/ui_compat.h +hw_pk11so_pub.o: ../../include/openssl/rc4.h ../../include/openssl/rc2.h +hw_pk11so_pub.o: ../../crypto/rc5/rc5.h ../../include/openssl/blowfish.h +hw_pk11so_pub.o: ../../include/openssl/cast.h ../../include/openssl/idea.h +hw_pk11so_pub.o: ../../crypto/mdc2/mdc2.h ../../include/openssl/aes.h +hw_pk11so_pub.o: ../../include/openssl/objects.h ../../include/openssl/obj_mac.h +hw_pk11so_pub.o: ../../include/openssl/x509.h ../../include/openssl/buffer.h +hw_pk11so_pub.o: ../../include/openssl/x509_vfy.h ../../include/openssl/pkcs7.h +hw_pk11so_pub.o: ../../include/openssl/pem2.h ../cryptlib.h +hw_pk11so_pub.o: ../../e_os.h hw_pk11_err.c hw_pk11_err.h hw_pk11so_pub.c tb_cipher.o: ../../e_os.h ../../include/openssl/asn1.h tb_cipher.o: ../../include/openssl/bio.h ../../include/openssl/buffer.h tb_cipher.o: ../../include/openssl/crypto.h ../../include/openssl/e_os2.h Index: openssl/crypto/engine/cryptoki.h diff -u /dev/null openssl/crypto/engine/cryptoki.h:1.4 --- /dev/null Wed Dec 23 16:49:05 2015 +++ openssl/crypto/engine/cryptoki.h Thu Dec 18 00:14:12 2008 @@ -0,0 +1,103 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _CRYPTOKI_H +#define _CRYPTOKI_H + +/* ident "@(#)cryptoki.h 1.2 05/06/08 SMI" */ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef CK_PTR +#define CK_PTR * +#endif + +#ifndef CK_DEFINE_FUNCTION +#define CK_DEFINE_FUNCTION(returnType, name) returnType name +#endif + +#ifndef CK_DECLARE_FUNCTION +#define CK_DECLARE_FUNCTION(returnType, name) returnType name +#endif + +#ifndef CK_DECLARE_FUNCTION_POINTER +#define CK_DECLARE_FUNCTION_POINTER(returnType, name) returnType (* name) +#endif + +#ifndef CK_CALLBACK_FUNCTION +#define CK_CALLBACK_FUNCTION(returnType, name) returnType (* name) +#endif + +#ifndef NULL_PTR +#include /* For NULL */ +#define NULL_PTR NULL +#endif + +/* + * pkcs11t.h defines TRUE and FALSE in a way that upsets lint + */ +#ifndef CK_DISABLE_TRUE_FALSE +#define CK_DISABLE_TRUE_FALSE +#ifndef TRUE +#define TRUE 1 +#endif /* TRUE */ +#ifndef FALSE +#define FALSE 0 +#endif /* FALSE */ +#endif /* CK_DISABLE_TRUE_FALSE */ + +#undef CK_PKCS11_FUNCTION_INFO + +#include "pkcs11.h" + +/* Solaris specific functions */ + +#include + +/* + * SUNW_C_GetMechSession will initialize the framework and do all + * the necessary PKCS#11 calls to create a session capable of + * providing operations on the requested mechanism + */ +CK_RV SUNW_C_GetMechSession(CK_MECHANISM_TYPE mech, + CK_SESSION_HANDLE_PTR hSession); + +/* + * SUNW_C_KeyToObject will create a secret key object for the given + * mechanism from the rawkey data. + */ +CK_RV SUNW_C_KeyToObject(CK_SESSION_HANDLE hSession, + CK_MECHANISM_TYPE mech, const void *rawkey, size_t rawkey_len, + CK_OBJECT_HANDLE_PTR obj); + + +#ifdef __cplusplus +} +#endif + +#endif /* _CRYPTOKI_H */ Index: openssl/crypto/engine/eng_all.c diff -u openssl/crypto/engine/eng_all.c:1.4.6.1.6.1.6.1 openssl/crypto/engine/eng_all.c:1.4.2.2 --- openssl/crypto/engine/eng_all.c:1.4.6.1.6.1.6.1 Wed Dec 23 16:03:42 2015 +++ openssl/crypto/engine/eng_all.c Wed Dec 23 16:45:32 2015 @@ -113,6 +113,14 @@ # if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(HAVE_CRYPTODEV) ENGINE_load_cryptodev(); # endif +# ifndef OPENSSL_NO_HW_PKCS11 +# ifndef OPENSSL_NO_HW_PKCS11CA + ENGINE_load_pk11ca(); +# endif +# ifndef OPENSSL_NO_HW_PKCS11SO + ENGINE_load_pk11so(); +# endif +# endif #endif } Index: openssl/crypto/engine/engine.h diff -u openssl/crypto/engine/engine.h:1.4.6.1.6.1.6.1 openssl/crypto/engine/engine.h:1.4.2.2 --- openssl/crypto/engine/engine.h:1.4.6.1.6.1.6.1 Wed Dec 23 16:03:44 2015 +++ openssl/crypto/engine/engine.h Wed Dec 23 16:45:34 2015 @@ -403,6 +403,12 @@ void ENGINE_load_cryptodev(void); void ENGINE_load_padlock(void); void ENGINE_load_builtin_engines(void); +# ifndef OPENSSL_NO_HW_PKCS11CA +void ENGINE_load_pk11ca(void); +# endif +# ifndef OPENSSL_NO_HW_PKCS11SO +void ENGINE_load_pk11so(void); +# endif /* * Get and set global flags (ENGINE_TABLE_FLAG_***) for the implementation Index: openssl/crypto/engine/hw_pk11.c diff -u /dev/null openssl/crypto/engine/hw_pk11.c:1.26.4.4 --- /dev/null Wed Dec 23 16:49:05 2015 +++ openssl/crypto/engine/hw_pk11.c Fri Oct 4 14:45:25 2013 @@ -0,0 +1,4116 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* crypto/engine/hw_pk11.c */ +/* + * This product includes software developed by the OpenSSL Project for + * use in the OpenSSL Toolkit (http://www.openssl.org/). + * + * This project also referenced hw_pkcs11-0.9.7b.patch written by + * Afchine Madjlessi. + */ +/* + * ==================================================================== + * Copyright (c) 2000-2001 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifndef OPENSSL_NO_RSA +#include +#endif +#ifndef OPENSSL_NO_DSA +#include +#endif +#ifndef OPENSSL_NO_DH +#include +#endif +#include +#include +#include +#include +#include + +#ifdef OPENSSL_SYS_WIN32 +typedef int pid_t; +#define getpid() GetCurrentProcessId() +#define NOPTHREADS +#ifndef NULL_PTR +#define NULL_PTR NULL +#endif +#define CK_DEFINE_FUNCTION(returnType, name) \ + returnType __declspec(dllexport) name +#define CK_DECLARE_FUNCTION(returnType, name) \ + returnType __declspec(dllimport) name +#define CK_DECLARE_FUNCTION_POINTER(returnType, name) \ + returnType __declspec(dllimport) (* name) +#else +#include +#include +#include +#endif + +/* Debug mutexes */ +/*#undef DEBUG_MUTEX */ +#define DEBUG_MUTEX + +#ifndef NOPTHREADS +/* for pthread error check on Linuxes */ +#ifdef DEBUG_MUTEX +#define __USE_UNIX98 +#endif +#include +#endif + +#ifndef OPENSSL_NO_HW +#ifndef OPENSSL_NO_HW_PK11 +#ifndef OPENSSL_NO_HW_PK11CA + +/* label for debug messages printed on stderr */ +#define PK11_DBG "PKCS#11 ENGINE DEBUG" +/* prints a lot of debug messages on stderr about slot selection process */ +/* #undef DEBUG_SLOT_SELECTION */ +/* + * Solaris specific code. See comment at check_hw_mechanisms() for more + * information. + */ +#if defined(__SVR4) && defined(__sun) +#undef SOLARIS_HW_SLOT_SELECTION +#endif + +/* + * AES counter mode is not supported in the OpenSSL EVP API yet and neither + * there are official OIDs for mechanisms based on this mode. With our changes, + * an application can define its own EVP calls for AES counter mode and then + * it can make use of hardware acceleration through this engine. However, it's + * better if we keep AES CTR support code under ifdef's. + */ +#define SOLARIS_AES_CTR + +#ifdef OPENSSL_SYS_WIN32 +#pragma pack(push, cryptoki, 1) +#include "cryptoki.h" +#include "pkcs11.h" +#pragma pack(pop, cryptoki) +#else +#include "cryptoki.h" +#include "pkcs11.h" +#endif +#include "hw_pk11ca.h" +#include "hw_pk11_err.c" + +#ifdef SOLARIS_AES_CTR +/* + * NIDs for AES counter mode that will be defined during the engine + * initialization. + */ +static int NID_aes_128_ctr = NID_undef; +static int NID_aes_192_ctr = NID_undef; +static int NID_aes_256_ctr = NID_undef; +#endif /* SOLARIS_AES_CTR */ + +/* + * We use this lock to prevent multiple C_Login()s, guard getpassphrase(), + * uri_struct manipulation, and static token info. All of that is used by the + * RSA keys by reference feature. + */ +#ifndef NOPTHREADS +pthread_mutex_t *token_lock; +#endif + +#ifdef SOLARIS_HW_SLOT_SELECTION +/* + * Tables for symmetric ciphers and digest mechs found in the pkcs11_kernel + * library. See comment at check_hw_mechanisms() for more information. + */ +static int *hw_cnids; +static int *hw_dnids; +#endif /* SOLARIS_HW_SLOT_SELECTION */ + +/* PKCS#11 session caches and their locks for all operation types */ +static PK11_CACHE session_cache[OP_MAX]; + +/* + * We cache the flags so that we do not have to run C_GetTokenInfo() again when + * logging into the token. + */ +CK_FLAGS pubkey_token_flags; + +/* + * As stated in v2.20, 11.7 Object Management Function, in section for + * C_FindObjectsInit(), at most one search operation may be active at a given + * time in a given session. Therefore, C_Find{,Init,Final}Objects() should be + * grouped together to form one atomic search operation. This is already + * ensured by the property of unique PKCS#11 session handle used for each + * PK11_SESSION object. + * + * This is however not the biggest concern - maintaining consistency of the + * underlying object store is more important. The same section of the spec also + * says that one thread can be in the middle of a search operation while another + * thread destroys the object matching the search template which would result in + * invalid handle returned from the search operation. + * + * Hence, the following locks are used for both protection of the object stores. + * They are also used for active list protection. + */ +#ifndef NOPTHREADS +pthread_mutex_t *find_lock[OP_MAX] = { NULL }; +#endif + +/* + * lists of asymmetric key handles which are active (referenced by at least one + * PK11_SESSION structure, either held by a thread or present in free_session + * list) for given algorithm type + */ +PK11_active *active_list[OP_MAX] = { NULL }; + +/* + * Create all secret key objects in a global session so that they are available + * to use for other sessions. These other sessions may be opened or closed + * without losing the secret key objects. + */ +static CK_SESSION_HANDLE global_session = CK_INVALID_HANDLE; + +/* ENGINE level stuff */ +static int pk11_init(ENGINE *e); +static int pk11_library_init(ENGINE *e); +static int pk11_finish(ENGINE *e); +static int pk11_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void)); +static int pk11_destroy(ENGINE *e); + +/* RAND stuff */ +static void pk11_rand_seed(const void *buf, int num); +static void pk11_rand_add(const void *buf, int num, double add_entropy); +static void pk11_rand_cleanup(void); +static int pk11_rand_bytes(unsigned char *buf, int num); +static int pk11_rand_status(void); + +/* These functions are also used in other files */ +PK11_SESSION *pk11_get_session(PK11_OPTYPE optype); +void pk11_return_session(PK11_SESSION *sp, PK11_OPTYPE optype); + +/* active list manipulation functions used in this file */ +extern int pk11_active_delete(CK_OBJECT_HANDLE h, PK11_OPTYPE type); +extern void pk11_free_active_list(PK11_OPTYPE type); + +#ifndef OPENSSL_NO_RSA +int pk11_destroy_rsa_key_objects(PK11_SESSION *session); +int pk11_destroy_rsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock); +int pk11_destroy_rsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock); +#endif +#ifndef OPENSSL_NO_DSA +int pk11_destroy_dsa_key_objects(PK11_SESSION *session); +int pk11_destroy_dsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock); +int pk11_destroy_dsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock); +#endif +#ifndef OPENSSL_NO_DH +int pk11_destroy_dh_key_objects(PK11_SESSION *session); +int pk11_destroy_dh_object(PK11_SESSION *session, CK_BBOOL uselock); +#endif + +/* Local helper functions */ +static int pk11_free_all_sessions(void); +static int pk11_free_session_list(PK11_OPTYPE optype); +static int pk11_setup_session(PK11_SESSION *sp, PK11_OPTYPE optype); +static int pk11_destroy_cipher_key_objects(PK11_SESSION *session); +static int pk11_destroy_object(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE oh, + CK_BBOOL persistent); +static const char *get_PK11_LIBNAME(void); +static void free_PK11_LIBNAME(void); +static long set_PK11_LIBNAME(const char *name); + +/* Symmetric cipher and digest support functions */ +static int cipher_nid_to_pk11(int nid); +#ifdef SOLARIS_AES_CTR +static int pk11_add_NID(char *sn, char *ln); +static int pk11_add_aes_ctr_NIDs(void); +#endif /* SOLARIS_AES_CTR */ +static int pk11_usable_ciphers(const int **nids); +static int pk11_usable_digests(const int **nids); +static int pk11_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc); +static int pk11_cipher_final(PK11_SESSION *sp); +#if OPENSSL_VERSION_NUMBER < 0x10000000L +static int pk11_cipher_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, unsigned int inl); +#else +static int pk11_cipher_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t inl); +#endif +static int pk11_cipher_cleanup(EVP_CIPHER_CTX *ctx); +static int pk11_engine_ciphers(ENGINE *e, const EVP_CIPHER **cipher, + const int **nids, int nid); +static int pk11_engine_digests(ENGINE *e, const EVP_MD **digest, + const int **nids, int nid); +static CK_OBJECT_HANDLE pk11_get_cipher_key(EVP_CIPHER_CTX *ctx, + const unsigned char *key, CK_KEY_TYPE key_type, PK11_SESSION *sp); +static int check_new_cipher_key(PK11_SESSION *sp, const unsigned char *key, + int key_len); +static int md_nid_to_pk11(int nid); +static int pk11_digest_init(EVP_MD_CTX *ctx); +static int pk11_digest_update(EVP_MD_CTX *ctx, const void *data, + size_t count); +static int pk11_digest_final(EVP_MD_CTX *ctx, unsigned char *md); +static int pk11_digest_copy(EVP_MD_CTX *to, const EVP_MD_CTX *from); +static int pk11_digest_cleanup(EVP_MD_CTX *ctx); + +static int pk11_choose_slots(int *any_slot_found); +static void pk11_find_symmetric_ciphers(CK_FUNCTION_LIST_PTR pflist, + CK_SLOT_ID current_slot, int *current_slot_n_cipher, + int *local_cipher_nids); +static void pk11_find_digests(CK_FUNCTION_LIST_PTR pflist, + CK_SLOT_ID current_slot, int *current_slot_n_digest, + int *local_digest_nids); +static void pk11_get_symmetric_cipher(CK_FUNCTION_LIST_PTR, int slot_id, + CK_MECHANISM_TYPE mech, int *current_slot_n_cipher, int *local_cipher_nids, + int id); +static void pk11_get_digest(CK_FUNCTION_LIST_PTR pflist, int slot_id, + CK_MECHANISM_TYPE mech, int *current_slot_n_digest, int *local_digest_nids, + int id); + +static int pk11_init_all_locks(void); +static void pk11_free_all_locks(void); + +#ifdef SOLARIS_HW_SLOT_SELECTION +static int check_hw_mechanisms(void); +static int nid_in_table(int nid, int *nid_table); +#endif /* SOLARIS_HW_SLOT_SELECTION */ + +/* Index for the supported ciphers */ +enum pk11_cipher_id { + PK11_DES_CBC, + PK11_DES3_CBC, + PK11_DES_ECB, + PK11_DES3_ECB, + PK11_RC4, + PK11_AES_128_CBC, + PK11_AES_192_CBC, + PK11_AES_256_CBC, + PK11_AES_128_ECB, + PK11_AES_192_ECB, + PK11_AES_256_ECB, + PK11_BLOWFISH_CBC, +#ifdef SOLARIS_AES_CTR + PK11_AES_128_CTR, + PK11_AES_192_CTR, + PK11_AES_256_CTR, +#endif /* SOLARIS_AES_CTR */ + PK11_CIPHER_MAX +}; + +/* Index for the supported digests */ +enum pk11_digest_id { + PK11_MD5, + PK11_SHA1, + PK11_SHA224, + PK11_SHA256, + PK11_SHA384, + PK11_SHA512, + PK11_DIGEST_MAX +}; + +#define TRY_OBJ_DESTROY(sp, obj_hdl, retval, uselock, alg_type, priv) \ + { \ + if (uselock) \ + LOCK_OBJSTORE(alg_type); \ + if (pk11_active_delete(obj_hdl, alg_type) == 1) \ + { \ + retval = pk11_destroy_object(sp->session, obj_hdl, \ + priv ? sp->priv_persistent : sp->pub_persistent); \ + } \ + if (uselock) \ + UNLOCK_OBJSTORE(alg_type); \ + } + +static int cipher_nids[PK11_CIPHER_MAX]; +static int digest_nids[PK11_DIGEST_MAX]; +static int cipher_count = 0; +static int digest_count = 0; +static CK_BBOOL pk11_have_rsa = CK_FALSE; +static CK_BBOOL pk11_have_recover = CK_FALSE; +static CK_BBOOL pk11_have_dsa = CK_FALSE; +static CK_BBOOL pk11_have_dh = CK_FALSE; +static CK_BBOOL pk11_have_random = CK_FALSE; + +typedef struct PK11_CIPHER_st + { + enum pk11_cipher_id id; + int nid; + int iv_len; + int min_key_len; + int max_key_len; + CK_KEY_TYPE key_type; + CK_MECHANISM_TYPE mech_type; + } PK11_CIPHER; + +static PK11_CIPHER ciphers[] = + { + { PK11_DES_CBC, NID_des_cbc, 8, 8, 8, + CKK_DES, CKM_DES_CBC, }, + { PK11_DES3_CBC, NID_des_ede3_cbc, 8, 24, 24, + CKK_DES3, CKM_DES3_CBC, }, + { PK11_DES_ECB, NID_des_ecb, 0, 8, 8, + CKK_DES, CKM_DES_ECB, }, + { PK11_DES3_ECB, NID_des_ede3_ecb, 0, 24, 24, + CKK_DES3, CKM_DES3_ECB, }, + { PK11_RC4, NID_rc4, 0, 16, 256, + CKK_RC4, CKM_RC4, }, + { PK11_AES_128_CBC, NID_aes_128_cbc, 16, 16, 16, + CKK_AES, CKM_AES_CBC, }, + { PK11_AES_192_CBC, NID_aes_192_cbc, 16, 24, 24, + CKK_AES, CKM_AES_CBC, }, + { PK11_AES_256_CBC, NID_aes_256_cbc, 16, 32, 32, + CKK_AES, CKM_AES_CBC, }, + { PK11_AES_128_ECB, NID_aes_128_ecb, 0, 16, 16, + CKK_AES, CKM_AES_ECB, }, + { PK11_AES_192_ECB, NID_aes_192_ecb, 0, 24, 24, + CKK_AES, CKM_AES_ECB, }, + { PK11_AES_256_ECB, NID_aes_256_ecb, 0, 32, 32, + CKK_AES, CKM_AES_ECB, }, + { PK11_BLOWFISH_CBC, NID_bf_cbc, 8, 16, 16, + CKK_BLOWFISH, CKM_BLOWFISH_CBC, }, +#ifdef SOLARIS_AES_CTR + /* we don't know the correct NIDs until the engine is initialized */ + { PK11_AES_128_CTR, NID_undef, 16, 16, 16, + CKK_AES, CKM_AES_CTR, }, + { PK11_AES_192_CTR, NID_undef, 16, 24, 24, + CKK_AES, CKM_AES_CTR, }, + { PK11_AES_256_CTR, NID_undef, 16, 32, 32, + CKK_AES, CKM_AES_CTR, }, +#endif /* SOLARIS_AES_CTR */ + }; + +typedef struct PK11_DIGEST_st + { + enum pk11_digest_id id; + int nid; + CK_MECHANISM_TYPE mech_type; + } PK11_DIGEST; + +static PK11_DIGEST digests[] = + { + {PK11_MD5, NID_md5, CKM_MD5, }, + {PK11_SHA1, NID_sha1, CKM_SHA_1, }, + {PK11_SHA224, NID_sha224, CKM_SHA224, }, + {PK11_SHA256, NID_sha256, CKM_SHA256, }, + {PK11_SHA384, NID_sha384, CKM_SHA384, }, + {PK11_SHA512, NID_sha512, CKM_SHA512, }, + {0, NID_undef, 0xFFFF, }, + }; + +/* + * Structure to be used for the cipher_data/md_data in + * EVP_CIPHER_CTX/EVP_MD_CTX structures in order to use the same pk11 + * session in multiple cipher_update calls + */ +typedef struct PK11_CIPHER_STATE_st + { + PK11_SESSION *sp; + } PK11_CIPHER_STATE; + + +/* + * libcrypto EVP stuff - this is how we get wired to EVP so the engine gets + * called when libcrypto requests a cipher NID. + * + * Note how the PK11_CIPHER_STATE is used here. + */ + +/* DES CBC EVP */ +static const EVP_CIPHER pk11_des_cbc = + { + NID_des_cbc, + 8, 8, 8, + EVP_CIPH_CBC_MODE, + pk11_cipher_init, + pk11_cipher_do_cipher, + pk11_cipher_cleanup, + sizeof (PK11_CIPHER_STATE), + EVP_CIPHER_set_asn1_iv, + EVP_CIPHER_get_asn1_iv, + NULL + }; + +/* 3DES CBC EVP */ +static const EVP_CIPHER pk11_3des_cbc = + { + NID_des_ede3_cbc, + 8, 24, 8, + EVP_CIPH_CBC_MODE, + pk11_cipher_init, + pk11_cipher_do_cipher, + pk11_cipher_cleanup, + sizeof (PK11_CIPHER_STATE), + EVP_CIPHER_set_asn1_iv, + EVP_CIPHER_get_asn1_iv, + NULL + }; + +/* + * ECB modes don't use an Initial Vector so that's why set_asn1_parameters and + * get_asn1_parameters fields are set to NULL. + */ +static const EVP_CIPHER pk11_des_ecb = + { + NID_des_ecb, + 8, 8, 8, + EVP_CIPH_ECB_MODE, + pk11_cipher_init, + pk11_cipher_do_cipher, + pk11_cipher_cleanup, + sizeof (PK11_CIPHER_STATE), + NULL, + NULL, + NULL + }; + +static const EVP_CIPHER pk11_3des_ecb = + { + NID_des_ede3_ecb, + 8, 24, 8, + EVP_CIPH_ECB_MODE, + pk11_cipher_init, + pk11_cipher_do_cipher, + pk11_cipher_cleanup, + sizeof (PK11_CIPHER_STATE), + NULL, + NULL, + NULL + }; + + +static const EVP_CIPHER pk11_aes_128_cbc = + { + NID_aes_128_cbc, + 16, 16, 16, + EVP_CIPH_CBC_MODE, + pk11_cipher_init, + pk11_cipher_do_cipher, + pk11_cipher_cleanup, + sizeof (PK11_CIPHER_STATE), + EVP_CIPHER_set_asn1_iv, + EVP_CIPHER_get_asn1_iv, + NULL + }; + +static const EVP_CIPHER pk11_aes_192_cbc = + { + NID_aes_192_cbc, + 16, 24, 16, + EVP_CIPH_CBC_MODE, + pk11_cipher_init, + pk11_cipher_do_cipher, + pk11_cipher_cleanup, + sizeof (PK11_CIPHER_STATE), + EVP_CIPHER_set_asn1_iv, + EVP_CIPHER_get_asn1_iv, + NULL + }; + +static const EVP_CIPHER pk11_aes_256_cbc = + { + NID_aes_256_cbc, + 16, 32, 16, + EVP_CIPH_CBC_MODE, + pk11_cipher_init, + pk11_cipher_do_cipher, + pk11_cipher_cleanup, + sizeof (PK11_CIPHER_STATE), + EVP_CIPHER_set_asn1_iv, + EVP_CIPHER_get_asn1_iv, + NULL + }; + +/* + * ECB modes don't use IV so that's why set_asn1_parameters and + * get_asn1_parameters are set to NULL. + */ +static const EVP_CIPHER pk11_aes_128_ecb = + { + NID_aes_128_ecb, + 16, 16, 0, + EVP_CIPH_ECB_MODE, + pk11_cipher_init, + pk11_cipher_do_cipher, + pk11_cipher_cleanup, + sizeof (PK11_CIPHER_STATE), + NULL, + NULL, + NULL + }; + +static const EVP_CIPHER pk11_aes_192_ecb = + { + NID_aes_192_ecb, + 16, 24, 0, + EVP_CIPH_ECB_MODE, + pk11_cipher_init, + pk11_cipher_do_cipher, + pk11_cipher_cleanup, + sizeof (PK11_CIPHER_STATE), + NULL, + NULL, + NULL + }; + +static const EVP_CIPHER pk11_aes_256_ecb = + { + NID_aes_256_ecb, + 16, 32, 0, + EVP_CIPH_ECB_MODE, + pk11_cipher_init, + pk11_cipher_do_cipher, + pk11_cipher_cleanup, + sizeof (PK11_CIPHER_STATE), + NULL, + NULL, + NULL + }; + +#ifdef SOLARIS_AES_CTR +/* + * NID_undef's will be changed to the AES counter mode NIDs as soon they are + * created in pk11_library_init(). Note that the need to change these structures + * is the reason why we don't define them with the const keyword. + */ +static EVP_CIPHER pk11_aes_128_ctr = + { + NID_undef, + 16, 16, 16, + EVP_CIPH_CBC_MODE, + pk11_cipher_init, + pk11_cipher_do_cipher, + pk11_cipher_cleanup, + sizeof (PK11_CIPHER_STATE), + EVP_CIPHER_set_asn1_iv, + EVP_CIPHER_get_asn1_iv, + NULL + }; + +static EVP_CIPHER pk11_aes_192_ctr = + { + NID_undef, + 16, 24, 16, + EVP_CIPH_CBC_MODE, + pk11_cipher_init, + pk11_cipher_do_cipher, + pk11_cipher_cleanup, + sizeof (PK11_CIPHER_STATE), + EVP_CIPHER_set_asn1_iv, + EVP_CIPHER_get_asn1_iv, + NULL + }; + +static EVP_CIPHER pk11_aes_256_ctr = + { + NID_undef, + 16, 32, 16, + EVP_CIPH_CBC_MODE, + pk11_cipher_init, + pk11_cipher_do_cipher, + pk11_cipher_cleanup, + sizeof (PK11_CIPHER_STATE), + EVP_CIPHER_set_asn1_iv, + EVP_CIPHER_get_asn1_iv, + NULL + }; +#endif /* SOLARIS_AES_CTR */ + +static const EVP_CIPHER pk11_bf_cbc = + { + NID_bf_cbc, + 8, 16, 8, + EVP_CIPH_VARIABLE_LENGTH, + pk11_cipher_init, + pk11_cipher_do_cipher, + pk11_cipher_cleanup, + sizeof (PK11_CIPHER_STATE), + EVP_CIPHER_set_asn1_iv, + EVP_CIPHER_get_asn1_iv, + NULL + }; + +static const EVP_CIPHER pk11_rc4 = + { + NID_rc4, + 1, 16, 0, + EVP_CIPH_VARIABLE_LENGTH, + pk11_cipher_init, + pk11_cipher_do_cipher, + pk11_cipher_cleanup, + sizeof (PK11_CIPHER_STATE), + NULL, + NULL, + NULL + }; + +static const EVP_MD pk11_md5 = + { + NID_md5, + NID_md5WithRSAEncryption, + MD5_DIGEST_LENGTH, + 0, + pk11_digest_init, + pk11_digest_update, + pk11_digest_final, + pk11_digest_copy, + pk11_digest_cleanup, + EVP_PKEY_RSA_method, + MD5_CBLOCK, + sizeof (PK11_CIPHER_STATE), + }; + +static const EVP_MD pk11_sha1 = + { + NID_sha1, + NID_sha1WithRSAEncryption, + SHA_DIGEST_LENGTH, + 0, + pk11_digest_init, + pk11_digest_update, + pk11_digest_final, + pk11_digest_copy, + pk11_digest_cleanup, + EVP_PKEY_RSA_method, + SHA_CBLOCK, + sizeof (PK11_CIPHER_STATE), + }; + +static const EVP_MD pk11_sha224 = + { + NID_sha224, + NID_sha224WithRSAEncryption, + SHA224_DIGEST_LENGTH, + 0, + pk11_digest_init, + pk11_digest_update, + pk11_digest_final, + pk11_digest_copy, + pk11_digest_cleanup, + EVP_PKEY_RSA_method, + /* SHA-224 uses the same cblock size as SHA-256 */ + SHA256_CBLOCK, + sizeof (PK11_CIPHER_STATE), + }; + +static const EVP_MD pk11_sha256 = + { + NID_sha256, + NID_sha256WithRSAEncryption, + SHA256_DIGEST_LENGTH, + 0, + pk11_digest_init, + pk11_digest_update, + pk11_digest_final, + pk11_digest_copy, + pk11_digest_cleanup, + EVP_PKEY_RSA_method, + SHA256_CBLOCK, + sizeof (PK11_CIPHER_STATE), + }; + +static const EVP_MD pk11_sha384 = + { + NID_sha384, + NID_sha384WithRSAEncryption, + SHA384_DIGEST_LENGTH, + 0, + pk11_digest_init, + pk11_digest_update, + pk11_digest_final, + pk11_digest_copy, + pk11_digest_cleanup, + EVP_PKEY_RSA_method, + /* SHA-384 uses the same cblock size as SHA-512 */ + SHA512_CBLOCK, + sizeof (PK11_CIPHER_STATE), + }; + +static const EVP_MD pk11_sha512 = + { + NID_sha512, + NID_sha512WithRSAEncryption, + SHA512_DIGEST_LENGTH, + 0, + pk11_digest_init, + pk11_digest_update, + pk11_digest_final, + pk11_digest_copy, + pk11_digest_cleanup, + EVP_PKEY_RSA_method, + SHA512_CBLOCK, + sizeof (PK11_CIPHER_STATE), + }; + +/* + * Initialization function. Sets up various PKCS#11 library components. + * The definitions for control commands specific to this engine + */ +#define PK11_CMD_SO_PATH ENGINE_CMD_BASE +#define PK11_CMD_PIN (ENGINE_CMD_BASE+1) +#define PK11_CMD_SLOT (ENGINE_CMD_BASE+2) +static const ENGINE_CMD_DEFN pk11_cmd_defns[] = + { + { + PK11_CMD_SO_PATH, + "SO_PATH", + "Specifies the path to the 'pkcs#11' shared library", + ENGINE_CMD_FLAG_STRING + }, + { + PK11_CMD_PIN, + "PIN", + "Specifies the pin code", + ENGINE_CMD_FLAG_STRING + }, + { + PK11_CMD_SLOT, + "SLOT", + "Specifies the slot (default is auto select)", + ENGINE_CMD_FLAG_NUMERIC, + }, + {0, NULL, NULL, 0} + }; + + +static RAND_METHOD pk11_random = + { + pk11_rand_seed, + pk11_rand_bytes, + pk11_rand_cleanup, + pk11_rand_add, + pk11_rand_bytes, + pk11_rand_status + }; + + +/* Constants used when creating the ENGINE */ +#ifdef OPENSSL_NO_HW_PK11SO +#error "can't load both crypto-accelerator and sign-only PKCS#11 engines" +#endif +static const char *engine_pk11_id = "pkcs11"; +static const char *engine_pk11_name = + "PKCS #11 engine support (crypto accelerator)"; + +CK_FUNCTION_LIST_PTR pFuncList = NULL; +static const char PK11_GET_FUNCTION_LIST[] = "C_GetFunctionList"; + +/* + * This is a static string constant for the DSO file name and the function + * symbol names to bind to. We set it in the Configure script based on whether + * this is 32 or 64 bit build. + */ +static const char def_PK11_LIBNAME[] = PK11_LIB_LOCATION; + +static CK_BBOOL mytrue = TRUE; +static CK_BBOOL myfalse = FALSE; +/* Needed in hw_pk11_pub.c as well so that's why it is not static. */ +CK_SLOT_ID pubkey_SLOTID = 0; +static CK_SLOT_ID rand_SLOTID = 0; +static CK_SLOT_ID SLOTID = 0; +char *pk11_pin = NULL; +static CK_BBOOL pk11_library_initialized = FALSE; +static CK_BBOOL pk11_atfork_initialized = FALSE; +static int pk11_pid = 0; + +static DSO *pk11_dso = NULL; + +/* allocate and initialize all locks used by the engine itself */ +static int pk11_init_all_locks(void) + { +#ifndef NOPTHREADS + int type; + pthread_mutexattr_t attr; + + if (pthread_mutexattr_init(&attr) != 0) + { + PK11err(PK11_F_INIT_ALL_LOCKS, 100); + return (0); + } + +#ifdef DEBUG_MUTEX + if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK) != 0) + { + PK11err(PK11_F_INIT_ALL_LOCKS, 101); + return (0); + } +#endif + + if ((token_lock = OPENSSL_malloc(sizeof (pthread_mutex_t))) == NULL) + goto malloc_err; + (void) pthread_mutex_init(token_lock, &attr); + +#ifndef OPENSSL_NO_RSA + find_lock[OP_RSA] = OPENSSL_malloc(sizeof (pthread_mutex_t)); + if (find_lock[OP_RSA] == NULL) + goto malloc_err; + (void) pthread_mutex_init(find_lock[OP_RSA], &attr); +#endif /* OPENSSL_NO_RSA */ + +#ifndef OPENSSL_NO_DSA + find_lock[OP_DSA] = OPENSSL_malloc(sizeof (pthread_mutex_t)); + if (find_lock[OP_DSA] == NULL) + goto malloc_err; + (void) pthread_mutex_init(find_lock[OP_DSA], &attr); +#endif /* OPENSSL_NO_DSA */ + +#ifndef OPENSSL_NO_DH + find_lock[OP_DH] = OPENSSL_malloc(sizeof (pthread_mutex_t)); + if (find_lock[OP_DH] == NULL) + goto malloc_err; + (void) pthread_mutex_init(find_lock[OP_DH], &attr); +#endif /* OPENSSL_NO_DH */ + + for (type = 0; type < OP_MAX; type++) + { + session_cache[type].lock = + OPENSSL_malloc(sizeof (pthread_mutex_t)); + if (session_cache[type].lock == NULL) + goto malloc_err; + (void) pthread_mutex_init(session_cache[type].lock, &attr); + } + + return (1); + +malloc_err: + pk11_free_all_locks(); + PK11err(PK11_F_INIT_ALL_LOCKS, PK11_R_MALLOC_FAILURE); + return (0); +#else + return (1); +#endif + } + +static void pk11_free_all_locks(void) + { +#ifndef NOPTHREADS + int type; + + if (token_lock != NULL) + { + (void) pthread_mutex_destroy(token_lock); + OPENSSL_free(token_lock); + token_lock = NULL; + } + +#ifndef OPENSSL_NO_RSA + if (find_lock[OP_RSA] != NULL) + { + (void) pthread_mutex_destroy(find_lock[OP_RSA]); + OPENSSL_free(find_lock[OP_RSA]); + find_lock[OP_RSA] = NULL; + } +#endif /* OPENSSL_NO_RSA */ +#ifndef OPENSSL_NO_DSA + if (find_lock[OP_DSA] != NULL) + { + (void) pthread_mutex_destroy(find_lock[OP_DSA]); + OPENSSL_free(find_lock[OP_DSA]); + find_lock[OP_DSA] = NULL; + } +#endif /* OPENSSL_NO_DSA */ +#ifndef OPENSSL_NO_DH + if (find_lock[OP_DH] != NULL) + { + (void) pthread_mutex_destroy(find_lock[OP_DH]); + OPENSSL_free(find_lock[OP_DH]); + find_lock[OP_DH] = NULL; + } +#endif /* OPENSSL_NO_DH */ + + for (type = 0; type < OP_MAX; type++) + { + if (session_cache[type].lock != NULL) + { + (void) pthread_mutex_destroy(session_cache[type].lock); + OPENSSL_free(session_cache[type].lock); + session_cache[type].lock = NULL; + } + } +#endif + } + +/* + * This internal function is used by ENGINE_pk11() and "dynamic" ENGINE support. + */ +static int bind_pk11(ENGINE *e) + { +#ifndef OPENSSL_NO_RSA + const RSA_METHOD *rsa = NULL; + RSA_METHOD *pk11_rsa = PK11_RSA(); +#endif /* OPENSSL_NO_RSA */ + if (!pk11_library_initialized) + if (!pk11_library_init(e)) + return (0); + + if (!ENGINE_set_id(e, engine_pk11_id) || + !ENGINE_set_name(e, engine_pk11_name) || + !ENGINE_set_ciphers(e, pk11_engine_ciphers) || + !ENGINE_set_digests(e, pk11_engine_digests)) + return (0); +#ifndef OPENSSL_NO_RSA + if (pk11_have_rsa == CK_TRUE) + { + if (!ENGINE_set_RSA(e, PK11_RSA()) || + !ENGINE_set_load_privkey_function(e, pk11_load_privkey) || + !ENGINE_set_load_pubkey_function(e, pk11_load_pubkey)) + return (0); +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: registered RSA\n", PK11_DBG); +#endif /* DEBUG_SLOT_SELECTION */ + } +#endif /* OPENSSL_NO_RSA */ +#ifndef OPENSSL_NO_DSA + if (pk11_have_dsa == CK_TRUE) + { + if (!ENGINE_set_DSA(e, PK11_DSA())) + return (0); +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: registered DSA\n", PK11_DBG); +#endif /* DEBUG_SLOT_SELECTION */ + } +#endif /* OPENSSL_NO_DSA */ +#ifndef OPENSSL_NO_DH + if (pk11_have_dh == CK_TRUE) + { + if (!ENGINE_set_DH(e, PK11_DH())) + return (0); +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: registered DH\n", PK11_DBG); +#endif /* DEBUG_SLOT_SELECTION */ + } +#endif /* OPENSSL_NO_DH */ + if (pk11_have_random) + { + if (!ENGINE_set_RAND(e, &pk11_random)) + return (0); +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: registered random\n", PK11_DBG); +#endif /* DEBUG_SLOT_SELECTION */ + } + if (!ENGINE_set_init_function(e, pk11_init) || + !ENGINE_set_destroy_function(e, pk11_destroy) || + !ENGINE_set_finish_function(e, pk11_finish) || + !ENGINE_set_ctrl_function(e, pk11_ctrl) || + !ENGINE_set_cmd_defns(e, pk11_cmd_defns)) + return (0); + +/* + * Apache calls OpenSSL function RSA_blinding_on() once during startup + * which in turn calls bn_mod_exp. Since we do not implement bn_mod_exp + * here, we wire it back to the OpenSSL software implementation. + * Since it is used only once, performance is not a concern. + */ +#ifndef OPENSSL_NO_RSA + rsa = RSA_PKCS1_SSLeay(); + pk11_rsa->rsa_mod_exp = rsa->rsa_mod_exp; + pk11_rsa->bn_mod_exp = rsa->bn_mod_exp; + if (pk11_have_recover != CK_TRUE) + pk11_rsa->rsa_pub_dec = rsa->rsa_pub_dec; +#endif /* OPENSSL_NO_RSA */ + + /* Ensure the pk11 error handling is set up */ + ERR_load_pk11_strings(); + + return (1); + } + +/* Dynamic engine support is disabled at a higher level for Solaris */ +#ifdef ENGINE_DYNAMIC_SUPPORT +#error "dynamic engine not supported" +static int bind_helper(ENGINE *e, const char *id) + { + if (id && (strcmp(id, engine_pk11_id) != 0)) + return (0); + + if (!bind_pk11(e)) + return (0); + + return (1); + } + +IMPLEMENT_DYNAMIC_CHECK_FN() +IMPLEMENT_DYNAMIC_BIND_FN(bind_helper) + +#else +static ENGINE *engine_pk11(void) + { + ENGINE *ret = ENGINE_new(); + + if (!ret) + return (NULL); + + if (!bind_pk11(ret)) + { + ENGINE_free(ret); + return (NULL); + } + + return (ret); + } + +void +ENGINE_load_pk11(void) + { + ENGINE *e_pk11 = NULL; + + /* + * Do not use dynamic PKCS#11 library on Solaris due to + * security reasons. We will link it in statically. + */ + /* Attempt to load PKCS#11 library */ + if (!pk11_dso) + pk11_dso = DSO_load(NULL, get_PK11_LIBNAME(), NULL, 0); + + if (pk11_dso == NULL) + { + PK11err(PK11_F_LOAD, PK11_R_DSO_FAILURE); + return; + } + + e_pk11 = engine_pk11(); + if (!e_pk11) + { + DSO_free(pk11_dso); + pk11_dso = NULL; + return; + } + + /* + * At this point, the pk11 shared library is either dynamically + * loaded or statically linked in. So, initialize the pk11 + * library before calling ENGINE_set_default since the latter + * needs cipher and digest algorithm information + */ + if (!pk11_library_init(e_pk11)) + { + DSO_free(pk11_dso); + pk11_dso = NULL; + ENGINE_free(e_pk11); + return; + } + + ENGINE_add(e_pk11); + + ENGINE_free(e_pk11); + ERR_clear_error(); + } +#endif /* ENGINE_DYNAMIC_SUPPORT */ + +/* + * These are the static string constants for the DSO file name and + * the function symbol names to bind to. + */ +static const char *PK11_LIBNAME = NULL; + +static const char *get_PK11_LIBNAME(void) + { + if (PK11_LIBNAME) + return (PK11_LIBNAME); + + return (def_PK11_LIBNAME); + } + +static void free_PK11_LIBNAME(void) + { + if (PK11_LIBNAME) + OPENSSL_free((void*)PK11_LIBNAME); + + PK11_LIBNAME = NULL; + } + +static long set_PK11_LIBNAME(const char *name) + { + free_PK11_LIBNAME(); + + return ((PK11_LIBNAME = BUF_strdup(name)) != NULL ? 1 : 0); + } + +/* acquire all engine specific mutexes before fork */ +static void pk11_fork_prepare(void) + { +#ifndef NOPTHREADS + int i; + + if (!pk11_library_initialized) + return; + + LOCK_OBJSTORE(OP_RSA); + LOCK_OBJSTORE(OP_DSA); + LOCK_OBJSTORE(OP_DH); + OPENSSL_assert(pthread_mutex_lock(token_lock) == 0); + for (i = 0; i < OP_MAX; i++) + { + OPENSSL_assert(pthread_mutex_lock(session_cache[i].lock) == 0); + } +#endif + } + +/* release all engine specific mutexes */ +static void pk11_fork_parent(void) + { +#ifndef NOPTHREADS + int i; + + if (!pk11_library_initialized) + return; + + for (i = OP_MAX - 1; i >= 0; i--) + { + OPENSSL_assert(pthread_mutex_unlock(session_cache[i].lock) == 0); + } + UNLOCK_OBJSTORE(OP_DH); + UNLOCK_OBJSTORE(OP_DSA); + UNLOCK_OBJSTORE(OP_RSA); + OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0); +#endif + } + +/* + * same situation as in parent - we need to unlock all locks to make them + * accessible to all threads. + */ +static void pk11_fork_child(void) + { +#ifndef NOPTHREADS + int i; + + if (!pk11_library_initialized) + return; + + for (i = OP_MAX - 1; i >= 0; i--) + { + OPENSSL_assert(pthread_mutex_unlock(session_cache[i].lock) == 0); + } + UNLOCK_OBJSTORE(OP_DH); + UNLOCK_OBJSTORE(OP_DSA); + UNLOCK_OBJSTORE(OP_RSA); + OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0); +#endif + } + +/* Initialization function for the pk11 engine */ +static int pk11_init(ENGINE *e) +{ + return (pk11_library_init(e)); +} + +static CK_C_INITIALIZE_ARGS pk11_init_args = + { + NULL_PTR, /* CreateMutex */ + NULL_PTR, /* DestroyMutex */ + NULL_PTR, /* LockMutex */ + NULL_PTR, /* UnlockMutex */ + CKF_OS_LOCKING_OK, /* flags */ + NULL_PTR, /* pReserved */ + }; + +/* + * Initialization function. Sets up various PKCS#11 library components. + * It selects a slot based on predefined critiera. In the process, it also + * count how many ciphers and digests to support. Since the cipher and + * digest information is needed when setting default engine, this function + * needs to be called before calling ENGINE_set_default. + */ +/* ARGSUSED */ +static int pk11_library_init(ENGINE *e) + { + CK_C_GetFunctionList p; + CK_RV rv = CKR_OK; + CK_INFO info; + CK_ULONG ul_state_len; + int any_slot_found; + int i; +#ifndef OPENSSL_SYS_WIN32 + struct sigaction sigint_act, sigterm_act, sighup_act; +#endif + + /* + * pk11_library_initialized is set to 0 in pk11_finish() which + * is called from ENGINE_finish(). However, if there is still + * at least one existing functional reference to the engine + * (see engine(3) for more information), pk11_finish() is + * skipped. For example, this can happen if an application + * forgets to clear one cipher context. In case of a fork() + * when the application is finishing the engine so that it can + * be reinitialized in the child, forgotten functional + * reference causes pk11_library_initialized to stay 1. In + * that case we need the PID check so that we properly + * initialize the engine again. + */ + if (pk11_library_initialized) + { + if (pk11_pid == getpid()) + { + return (1); + } + else + { + global_session = CK_INVALID_HANDLE; + /* + * free the locks first to prevent memory leak in case + * the application calls fork() without finishing the + * engine first. + */ + pk11_free_all_locks(); + } + } + + if (pk11_dso == NULL) + { + PK11err(PK11_F_LIBRARY_INIT, PK11_R_DSO_FAILURE); + goto err; + } + +#ifdef SOLARIS_AES_CTR + /* + * We must do this before we start working with slots since we need all + * NIDs there. + */ + if (pk11_add_aes_ctr_NIDs() == 0) + goto err; +#endif /* SOLARIS_AES_CTR */ + +#ifdef SOLARIS_HW_SLOT_SELECTION + if (check_hw_mechanisms() == 0) + goto err; +#endif /* SOLARIS_HW_SLOT_SELECTION */ + + /* get the C_GetFunctionList function from the loaded library */ + p = (CK_C_GetFunctionList)DSO_bind_func(pk11_dso, + PK11_GET_FUNCTION_LIST); + if (!p) + { + PK11err(PK11_F_LIBRARY_INIT, PK11_R_DSO_FAILURE); + goto err; + } + + /* get the full function list from the loaded library */ + rv = p(&pFuncList); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_LIBRARY_INIT, PK11_R_DSO_FAILURE, rv); + goto err; + } + +#ifndef OPENSSL_SYS_WIN32 + /* Not all PKCS#11 library are signal safe! */ + + (void) memset(&sigint_act, 0, sizeof(sigint_act)); + (void) memset(&sigterm_act, 0, sizeof(sigterm_act)); + (void) memset(&sighup_act, 0, sizeof(sighup_act)); + (void) sigaction(SIGINT, NULL, &sigint_act); + (void) sigaction(SIGTERM, NULL, &sigterm_act); + (void) sigaction(SIGHUP, NULL, &sighup_act); +#endif + rv = pFuncList->C_Initialize((CK_VOID_PTR)&pk11_init_args); +#ifndef OPENSSL_SYS_WIN32 + (void) sigaction(SIGINT, &sigint_act, NULL); + (void) sigaction(SIGTERM, &sigterm_act, NULL); + (void) sigaction(SIGHUP, &sighup_act, NULL); +#endif + if ((rv != CKR_OK) && (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)) + { + PK11err_add_data(PK11_F_LIBRARY_INIT, PK11_R_INITIALIZE, rv); + goto err; + } + + rv = pFuncList->C_GetInfo(&info); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_LIBRARY_INIT, PK11_R_GETINFO, rv); + goto err; + } + + if (pk11_choose_slots(&any_slot_found) == 0) + goto err; + + /* + * The library we use, set in def_PK11_LIBNAME, may not offer any + * slot(s). In that case, we must not proceed but we must not return an + * error. The reason is that applications that try to set up the PKCS#11 + * engine don't exit on error during the engine initialization just + * because no slot was present. + */ + if (any_slot_found == 0) + return (1); + + if (global_session == CK_INVALID_HANDLE) + { + /* Open the global_session for the new process */ + rv = pFuncList->C_OpenSession(SLOTID, CKF_SERIAL_SESSION, + NULL_PTR, NULL_PTR, &global_session); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_LIBRARY_INIT, + PK11_R_OPENSESSION, rv); + goto err; + } + } + + /* + * Disable digest if C_GetOperationState is not supported since + * this function is required by OpenSSL digest copy function + */ + /* Keyper fails to return CKR_FUNCTION_NOT_SUPPORTED */ + if (pFuncList->C_GetOperationState(global_session, NULL, &ul_state_len) + != CKR_OK) { +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: C_GetOperationState() not supported, " + "setting digest_count to 0\n", PK11_DBG); +#endif /* DEBUG_SLOT_SELECTION */ + digest_count = 0; + } + + pk11_library_initialized = TRUE; + pk11_pid = getpid(); + /* + * if initialization of the locks fails pk11_init_all_locks() + * will do the cleanup. + */ + if (!pk11_init_all_locks()) + goto err; + for (i = 0; i < OP_MAX; i++) + session_cache[i].head = NULL; + /* + * initialize active lists. We only use active lists + * for asymmetric ciphers. + */ + for (i = 0; i < OP_MAX; i++) + active_list[i] = NULL; + +#ifndef NOPTHREADS + if (!pk11_atfork_initialized) + { + if (pthread_atfork(pk11_fork_prepare, pk11_fork_parent, + pk11_fork_child) != 0) + { + PK11err(PK11_F_LIBRARY_INIT, PK11_R_ATFORK_FAILED); + goto err; + } + pk11_atfork_initialized = TRUE; + } +#endif + + return (1); + +err: + return (0); + } + +/* Destructor (complements the "ENGINE_pk11()" constructor) */ +/* ARGSUSED */ +static int pk11_destroy(ENGINE *e) + { + free_PK11_LIBNAME(); + ERR_unload_pk11_strings(); + if (pk11_pin) { + memset(pk11_pin, 0, strlen(pk11_pin)); + OPENSSL_free((void*)pk11_pin); + } + pk11_pin = NULL; + return (1); + } + +/* + * Termination function to clean up the session, the token, and the pk11 + * library. + */ +/* ARGSUSED */ +static int pk11_finish(ENGINE *e) + { + int i; + + if (pk11_pin) { + memset(pk11_pin, 0, strlen(pk11_pin)); + OPENSSL_free((void*)pk11_pin); + } + pk11_pin = NULL; + + if (pk11_dso == NULL) + { + PK11err(PK11_F_FINISH, PK11_R_NOT_LOADED); + goto err; + } + + OPENSSL_assert(pFuncList != NULL); + + if (pk11_free_all_sessions() == 0) + goto err; + + /* free all active lists */ + for (i = 0; i < OP_MAX; i++) + pk11_free_active_list(i); + + pFuncList->C_CloseSession(global_session); + global_session = CK_INVALID_HANDLE; + + /* + * Since we are part of a library (libcrypto.so), calling this function + * may have side-effects. + */ +#if 0 + pFuncList->C_Finalize(NULL); +#endif + + if (!DSO_free(pk11_dso)) + { + PK11err(PK11_F_FINISH, PK11_R_DSO_FAILURE); + goto err; + } + pk11_dso = NULL; + pFuncList = NULL; + pk11_library_initialized = FALSE; + pk11_pid = 0; + /* + * There is no way how to unregister atfork handlers (other than + * unloading the library) so we just free the locks. For this reason + * the atfork handlers check if the engine is initialized and bail out + * immediately if not. This is necessary in case a process finishes + * the engine before calling fork(). + */ + pk11_free_all_locks(); + + return (1); + +err: + return (0); + } + +/* Standard engine interface function to set the dynamic library path */ +/* ARGSUSED */ +static int pk11_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void)) + { + int initialized = ((pk11_dso == NULL) ? 0 : 1); + + switch (cmd) + { + case PK11_CMD_SO_PATH: + if (p == NULL) + { + PK11err(PK11_F_CTRL, ERR_R_PASSED_NULL_PARAMETER); + return (0); + } + + if (initialized) + { + PK11err(PK11_F_CTRL, PK11_R_ALREADY_LOADED); + return (0); + } + + return (set_PK11_LIBNAME((const char *)p)); + case PK11_CMD_PIN: + if (pk11_pin) { + memset(pk11_pin, 0, strlen(pk11_pin)); + OPENSSL_free((void*)pk11_pin); + } + pk11_pin = NULL; + + if (p == NULL) + { + PK11err(PK11_F_CTRL, ERR_R_PASSED_NULL_PARAMETER); + return (0); + } + + pk11_pin = BUF_strdup(p); + if (pk11_pin == NULL) + { + PK11err(PK11_F_GET_SESSION, PK11_R_MALLOC_FAILURE); + return (0); + } + return (1); + case PK11_CMD_SLOT: + SLOTID = (CK_SLOT_ID)i; +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: slot set\n", PK11_DBG); +#endif + return (1); + default: + break; + } + + PK11err(PK11_F_CTRL, PK11_R_CTRL_COMMAND_NOT_IMPLEMENTED); + + return (0); + } + + +/* Required function by the engine random interface. It does nothing here */ +static void pk11_rand_cleanup(void) + { + return; + } + +/* ARGSUSED */ +static void pk11_rand_add(const void *buf, int num, double add) + { + PK11_SESSION *sp; + + if ((sp = pk11_get_session(OP_RAND)) == NULL) + return; + + /* + * Ignore any errors (e.g. CKR_RANDOM_SEED_NOT_SUPPORTED) since + * the calling functions do not care anyway + */ + pFuncList->C_SeedRandom(sp->session, (unsigned char *) buf, num); + pk11_return_session(sp, OP_RAND); + + return; + } + +static void pk11_rand_seed(const void *buf, int num) + { + pk11_rand_add(buf, num, 0); + } + +static int pk11_rand_bytes(unsigned char *buf, int num) + { + CK_RV rv; + PK11_SESSION *sp; + + if ((sp = pk11_get_session(OP_RAND)) == NULL) + return (0); + + rv = pFuncList->C_GenerateRandom(sp->session, buf, num); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_RAND_BYTES, PK11_R_GENERATERANDOM, rv); + pk11_return_session(sp, OP_RAND); + return (0); + } + + pk11_return_session(sp, OP_RAND); + return (1); + } + +/* Required function by the engine random interface. It does nothing here */ +static int pk11_rand_status(void) + { + return (1); + } + +/* Free all BIGNUM structures from PK11_SESSION. */ +static void pk11_free_nums(PK11_SESSION *sp, PK11_OPTYPE optype) + { + switch (optype) + { +#ifndef OPENSSL_NO_RSA + case OP_RSA: + if (sp->opdata_rsa_n_num != NULL) + { + BN_free(sp->opdata_rsa_n_num); + sp->opdata_rsa_n_num = NULL; + } + if (sp->opdata_rsa_e_num != NULL) + { + BN_free(sp->opdata_rsa_e_num); + sp->opdata_rsa_e_num = NULL; + } + if (sp->opdata_rsa_pn_num != NULL) + { + BN_free(sp->opdata_rsa_pn_num); + sp->opdata_rsa_pn_num = NULL; + } + if (sp->opdata_rsa_pe_num != NULL) + { + BN_free(sp->opdata_rsa_pe_num); + sp->opdata_rsa_pe_num = NULL; + } + if (sp->opdata_rsa_d_num != NULL) + { + BN_free(sp->opdata_rsa_d_num); + sp->opdata_rsa_d_num = NULL; + } + break; +#endif +#ifndef OPENSSL_NO_DSA + case OP_DSA: + if (sp->opdata_dsa_pub_num != NULL) + { + BN_free(sp->opdata_dsa_pub_num); + sp->opdata_dsa_pub_num = NULL; + } + if (sp->opdata_dsa_priv_num != NULL) + { + BN_free(sp->opdata_dsa_priv_num); + sp->opdata_dsa_priv_num = NULL; + } + break; +#endif +#ifndef OPENSSL_NO_DH + case OP_DH: + if (sp->opdata_dh_priv_num != NULL) + { + BN_free(sp->opdata_dh_priv_num); + sp->opdata_dh_priv_num = NULL; + } + break; +#endif + default: + break; + } + } + +/* + * Get new PK11_SESSION structure ready for use. Every process must have + * its own freelist of PK11_SESSION structures so handle fork() here + * by destroying the old and creating new freelist. + * The returned PK11_SESSION structure is disconnected from the freelist. + */ +PK11_SESSION * +pk11_get_session(PK11_OPTYPE optype) + { + PK11_SESSION *sp = NULL, *sp1, *freelist; +#ifndef NOPTHREADS + pthread_mutex_t *freelist_lock = NULL; +#endif + static pid_t pid = 0; + pid_t new_pid; + CK_RV rv; + + switch (optype) + { + case OP_RSA: + case OP_DSA: + case OP_DH: + case OP_RAND: + case OP_DIGEST: + case OP_CIPHER: +#ifndef NOPTHREADS + freelist_lock = session_cache[optype].lock; +#endif + break; + default: + PK11err(PK11_F_GET_SESSION, + PK11_R_INVALID_OPERATION_TYPE); + return (NULL); + } +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_lock(freelist_lock) == 0); +#else + CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); +#endif + + /* + * Will use it to find out if we forked. We cannot use the PID field in + * the session structure because we could get a newly allocated session + * here, with no PID information. + */ + if (pid == 0) + pid = getpid(); + + freelist = session_cache[optype].head; + sp = freelist; + + /* + * If the free list is empty, allocate new unitialized (filled + * with zeroes) PK11_SESSION structure otherwise return first + * structure from the freelist. + */ + if (sp == NULL) + { + if ((sp = OPENSSL_malloc(sizeof (PK11_SESSION))) == NULL) + { + PK11err(PK11_F_GET_SESSION, + PK11_R_MALLOC_FAILURE); + goto err; + } + (void) memset(sp, 0, sizeof (PK11_SESSION)); + + /* + * It is a new session so it will look like a cache miss to the + * code below. So, we must not try to to destroy its members so + * mark them as unused. + */ + sp->opdata_rsa_priv_key = CK_INVALID_HANDLE; + sp->opdata_rsa_pub_key = CK_INVALID_HANDLE; + } + else + { + freelist = sp->next; + } + + /* + * Check whether we have forked. In that case, we must get rid of all + * inherited sessions and start allocating new ones. + */ + if (pid != (new_pid = getpid())) + { + pid = new_pid; + + /* + * We are a new process and thus need to free any inherited + * PK11_SESSION objects aside from the first session (sp) which + * is the only PK11_SESSION structure we will reuse (for the + * head of the list). + */ + while ((sp1 = freelist) != NULL) + { + freelist = sp1->next; + /* + * NOTE: we do not want to call pk11_free_all_sessions() + * here because it would close underlying PKCS#11 + * sessions and destroy all objects. + */ + pk11_free_nums(sp1, optype); + OPENSSL_free(sp1); + } + + /* we have to free the active list as well. */ + pk11_free_active_list(optype); + + /* Initialize the process */ + rv = pFuncList->C_Initialize((CK_VOID_PTR)&pk11_init_args); + if ((rv != CKR_OK) && (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)) + { + PK11err_add_data(PK11_F_GET_SESSION, PK11_R_INITIALIZE, + rv); + OPENSSL_free(sp); + sp = NULL; + goto err; + } + + /* + * Choose slot here since the slot table is different on this + * process. If we are here then we must have found at least one + * usable slot before so we don't need to check any_slot_found. + * See pk11_library_init()'s usage of this function for more + * information. + */ +#ifdef SOLARIS_HW_SLOT_SELECTION + if (check_hw_mechanisms() == 0) + goto err; +#endif /* SOLARIS_HW_SLOT_SELECTION */ + if (pk11_choose_slots(NULL) == 0) + goto err; + + /* Open the global_session for the new process */ + rv = pFuncList->C_OpenSession(SLOTID, CKF_SERIAL_SESSION, + NULL_PTR, NULL_PTR, &global_session); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_SESSION, PK11_R_OPENSESSION, + rv); + OPENSSL_free(sp); + sp = NULL; + goto err; + } + + /* + * It is an inherited session from our parent so it needs + * re-initialization. + */ + if (pk11_setup_session(sp, optype) == 0) + { + OPENSSL_free(sp); + sp = NULL; + goto err; + } + if (pk11_token_relogin(sp->session) == 0) + { + /* + * We will keep the session in the cache list and let + * the caller cope with the situation. + */ + freelist = sp; + sp = NULL; + goto err; + } + } + + if (sp->pid == 0) + { + /* It is a new session and needs initialization. */ + if (pk11_setup_session(sp, optype) == 0) + { + OPENSSL_free(sp); + sp = NULL; + } + } + + /* set new head for the list of PK11_SESSION objects */ + session_cache[optype].head = freelist; + +err: + if (sp != NULL) + sp->next = NULL; + +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_unlock(freelist_lock) == 0); +#else + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + + return (sp); + } + + +void +pk11_return_session(PK11_SESSION *sp, PK11_OPTYPE optype) + { +#ifndef NOPTHREADS + pthread_mutex_t *freelist_lock; +#endif + PK11_SESSION *freelist; + + /* + * If this is a session from the parent it will be taken care of and + * freed in pk11_get_session() as part of the post-fork clean up the + * next time we will ask for a new session. + */ + if (sp == NULL || sp->pid != getpid()) + return; + + switch (optype) + { + case OP_RSA: + case OP_DSA: + case OP_DH: + case OP_RAND: + case OP_DIGEST: + case OP_CIPHER: +#ifndef NOPTHREADS + freelist_lock = session_cache[optype].lock; +#endif + break; + default: + PK11err(PK11_F_RETURN_SESSION, + PK11_R_INVALID_OPERATION_TYPE); + return; + } + +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_lock(freelist_lock) == 0); +#else + CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); +#endif + freelist = session_cache[optype].head; + sp->next = freelist; + session_cache[optype].head = sp; +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_unlock(freelist_lock) == 0); +#else + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + } + + +/* Destroy all objects. This function is called when the engine is finished */ +static int pk11_free_all_sessions() + { + int ret = 1; + int type; + +#ifndef OPENSSL_NO_RSA + (void) pk11_destroy_rsa_key_objects(NULL); +#endif /* OPENSSL_NO_RSA */ +#ifndef OPENSSL_NO_DSA + (void) pk11_destroy_dsa_key_objects(NULL); +#endif /* OPENSSL_NO_DSA */ +#ifndef OPENSSL_NO_DH + (void) pk11_destroy_dh_key_objects(NULL); +#endif /* OPENSSL_NO_DH */ + (void) pk11_destroy_cipher_key_objects(NULL); + + /* + * We try to release as much as we can but any error means that we will + * return 0 on exit. + */ + for (type = 0; type < OP_MAX; type++) + { + if (pk11_free_session_list(type) == 0) + ret = 0; + } + + return (ret); + } + +/* + * Destroy session structures from the linked list specified. Free as many + * sessions as possible but any failure in C_CloseSession() means that we + * return an error on return. + */ +static int pk11_free_session_list(PK11_OPTYPE optype) + { + CK_RV rv; + PK11_SESSION *sp = NULL; + PK11_SESSION *freelist = NULL; + pid_t mypid = getpid(); +#ifndef NOPTHREADS + pthread_mutex_t *freelist_lock; +#endif + int ret = 1; + + switch (optype) + { + case OP_RSA: + case OP_DSA: + case OP_DH: + case OP_RAND: + case OP_DIGEST: + case OP_CIPHER: +#ifndef NOPTHREADS + freelist_lock = session_cache[optype].lock; +#endif + break; + default: + PK11err(PK11_F_FREE_ALL_SESSIONS, + PK11_R_INVALID_OPERATION_TYPE); + return (0); + } + +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_lock(freelist_lock) == 0); +#else + CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); +#endif + freelist = session_cache[optype].head; + while ((sp = freelist) != NULL) + { + if (sp->session != CK_INVALID_HANDLE && sp->pid == mypid) + { + rv = pFuncList->C_CloseSession(sp->session); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_FREE_ALL_SESSIONS, + PK11_R_CLOSESESSION, rv); + ret = 0; + } + } + freelist = sp->next; + pk11_free_nums(sp, optype); + OPENSSL_free(sp); + } + +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_unlock(freelist_lock) == 0); +#else + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + return (ret); + } + + +static int +pk11_setup_session(PK11_SESSION *sp, PK11_OPTYPE optype) + { + CK_RV rv; + CK_SLOT_ID myslot; + + switch (optype) + { + case OP_RSA: + case OP_DSA: + case OP_DH: + myslot = pubkey_SLOTID; + break; + case OP_RAND: + myslot = rand_SLOTID; + break; + case OP_DIGEST: + case OP_CIPHER: + myslot = SLOTID; + break; + default: + PK11err(PK11_F_SETUP_SESSION, + PK11_R_INVALID_OPERATION_TYPE); + return (0); + } + + sp->session = CK_INVALID_HANDLE; +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: myslot=%d optype=%d\n", PK11_DBG, myslot, optype); +#endif /* DEBUG_SLOT_SELECTION */ + rv = pFuncList->C_OpenSession(myslot, CKF_SERIAL_SESSION, + NULL_PTR, NULL_PTR, &sp->session); + if (rv == CKR_CRYPTOKI_NOT_INITIALIZED) + { + /* + * We are probably a child process so force the + * reinitialize of the session + */ + pk11_library_initialized = FALSE; + if (!pk11_library_init(NULL)) + return (0); + rv = pFuncList->C_OpenSession(myslot, CKF_SERIAL_SESSION, + NULL_PTR, NULL_PTR, &sp->session); + } + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_SETUP_SESSION, PK11_R_OPENSESSION, rv); + return (0); + } + + sp->pid = getpid(); + + switch (optype) + { +#ifndef OPENSSL_NO_RSA + case OP_RSA: + sp->opdata_rsa_pub_key = CK_INVALID_HANDLE; + sp->opdata_rsa_priv_key = CK_INVALID_HANDLE; + sp->opdata_rsa_pub = NULL; + sp->opdata_rsa_n_num = NULL; + sp->opdata_rsa_e_num = NULL; + sp->opdata_rsa_priv = NULL; + sp->opdata_rsa_pn_num = NULL; + sp->opdata_rsa_pe_num = NULL; + sp->opdata_rsa_d_num = NULL; + break; +#endif /* OPENSSL_NO_RSA */ +#ifndef OPENSSL_NO_DSA + case OP_DSA: + sp->opdata_dsa_pub_key = CK_INVALID_HANDLE; + sp->opdata_dsa_priv_key = CK_INVALID_HANDLE; + sp->opdata_dsa_pub = NULL; + sp->opdata_dsa_pub_num = NULL; + sp->opdata_dsa_priv = NULL; + sp->opdata_dsa_priv_num = NULL; + break; +#endif /* OPENSSL_NO_DSA */ +#ifndef OPENSSL_NO_DH + case OP_DH: + sp->opdata_dh_key = CK_INVALID_HANDLE; + sp->opdata_dh = NULL; + sp->opdata_dh_priv_num = NULL; + break; +#endif /* OPENSSL_NO_DH */ + case OP_CIPHER: + sp->opdata_cipher_key = CK_INVALID_HANDLE; + sp->opdata_encrypt = -1; + break; + default: + break; + } + + /* + * We always initialize the session as containing a non-persistent + * object. The key load functions set it to persistent if that is so. + */ + sp->pub_persistent = CK_FALSE; + sp->priv_persistent = CK_FALSE; + return (1); + } + +#ifndef OPENSSL_NO_RSA +/* Destroy RSA public key from single session. */ +int +pk11_destroy_rsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock) + { + int ret = 0; + + if (sp->opdata_rsa_pub_key != CK_INVALID_HANDLE) + { + TRY_OBJ_DESTROY(sp, sp->opdata_rsa_pub_key, + ret, uselock, OP_RSA, CK_FALSE); + sp->opdata_rsa_pub_key = CK_INVALID_HANDLE; + sp->opdata_rsa_pub = NULL; + if (sp->opdata_rsa_n_num != NULL) + { + BN_free(sp->opdata_rsa_n_num); + sp->opdata_rsa_n_num = NULL; + } + if (sp->opdata_rsa_e_num != NULL) + { + BN_free(sp->opdata_rsa_e_num); + sp->opdata_rsa_e_num = NULL; + } + } + + return (ret); + } + +/* Destroy RSA private key from single session. */ +int +pk11_destroy_rsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock) + { + int ret = 0; + + if (sp->opdata_rsa_priv_key != CK_INVALID_HANDLE) + { + TRY_OBJ_DESTROY(sp, sp->opdata_rsa_priv_key, + ret, uselock, OP_RSA, CK_TRUE); + sp->opdata_rsa_priv_key = CK_INVALID_HANDLE; + sp->opdata_rsa_priv = NULL; + if (sp->opdata_rsa_d_num != NULL) + { + BN_free(sp->opdata_rsa_d_num); + sp->opdata_rsa_d_num = NULL; + } + + /* + * For the RSA key by reference code, public components 'n'/'e' + * are the key components we use to check for the cache hit. We + * must free those as well. + */ + if (sp->opdata_rsa_pn_num != NULL) + { + BN_free(sp->opdata_rsa_pn_num); + sp->opdata_rsa_pn_num = NULL; + } + if (sp->opdata_rsa_pe_num != NULL) + { + BN_free(sp->opdata_rsa_pe_num); + sp->opdata_rsa_pe_num = NULL; + } + } + + return (ret); + } + +/* + * Destroy RSA key object wrapper. If session is NULL, try to destroy all + * objects in the free list. + */ +int +pk11_destroy_rsa_key_objects(PK11_SESSION *session) + { + int ret = 1; + PK11_SESSION *sp = NULL; + PK11_SESSION *local_free_session; + CK_BBOOL uselock = TRUE; + + if (session != NULL) + local_free_session = session; + else + { +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_lock(session_cache[OP_RSA].lock) == 0); +#else + CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); +#endif + local_free_session = session_cache[OP_RSA].head; + uselock = FALSE; + } + + /* + * go through the list of sessions and delete key objects + */ + while ((sp = local_free_session) != NULL) + { + local_free_session = sp->next; + + /* + * Do not terminate list traversal if one of the + * destroy operations fails. + */ + if (pk11_destroy_rsa_object_pub(sp, uselock) == 0) + { + ret = 0; + continue; + } + if (pk11_destroy_rsa_object_priv(sp, uselock) == 0) + { + ret = 0; + continue; + } + } + +#ifndef NOPTHREADS + if (session == NULL) + OPENSSL_assert(pthread_mutex_unlock(session_cache[OP_RSA].lock) == 0); +#else + if (session == NULL) + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + + return (ret); + } +#endif /* OPENSSL_NO_RSA */ + +#ifndef OPENSSL_NO_DSA +/* Destroy DSA public key from single session. */ +int +pk11_destroy_dsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock) + { + int ret = 0; + + if (sp->opdata_dsa_pub_key != CK_INVALID_HANDLE) + { + TRY_OBJ_DESTROY(sp, sp->opdata_dsa_pub_key, + ret, uselock, OP_DSA, CK_FALSE); + sp->opdata_dsa_pub_key = CK_INVALID_HANDLE; + sp->opdata_dsa_pub = NULL; + if (sp->opdata_dsa_pub_num != NULL) + { + BN_free(sp->opdata_dsa_pub_num); + sp->opdata_dsa_pub_num = NULL; + } + } + + return (ret); + } + +/* Destroy DSA private key from single session. */ +int +pk11_destroy_dsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock) + { + int ret = 0; + + if (sp->opdata_dsa_priv_key != CK_INVALID_HANDLE) + { + TRY_OBJ_DESTROY(sp, sp->opdata_dsa_priv_key, + ret, uselock, OP_DSA, CK_TRUE); + sp->opdata_dsa_priv_key = CK_INVALID_HANDLE; + sp->opdata_dsa_priv = NULL; + if (sp->opdata_dsa_priv_num != NULL) + { + BN_free(sp->opdata_dsa_priv_num); + sp->opdata_dsa_priv_num = NULL; + } + } + + return (ret); + } + +/* + * Destroy DSA key object wrapper. If session is NULL, try to destroy all + * objects in the free list. + */ +int +pk11_destroy_dsa_key_objects(PK11_SESSION *session) + { + int ret = 1; + PK11_SESSION *sp = NULL; + PK11_SESSION *local_free_session; + CK_BBOOL uselock = TRUE; + + if (session != NULL) + local_free_session = session; + else + { +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_lock(session_cache[OP_DSA].lock) == 0); +#else + CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); +#endif + local_free_session = session_cache[OP_DSA].head; + uselock = FALSE; + } + + /* + * go through the list of sessions and delete key objects + */ + while ((sp = local_free_session) != NULL) + { + local_free_session = sp->next; + + /* + * Do not terminate list traversal if one of the + * destroy operations fails. + */ + if (pk11_destroy_dsa_object_pub(sp, uselock) == 0) + { + ret = 0; + continue; + } + if (pk11_destroy_dsa_object_priv(sp, uselock) == 0) + { + ret = 0; + continue; + } + } + +#ifndef NOPTHREADS + if (session == NULL) + OPENSSL_assert(pthread_mutex_unlock(session_cache[OP_DSA].lock) == 0); +#else + if (session == NULL) + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + + return (ret); + } +#endif /* OPENSSL_NO_DSA */ + +#ifndef OPENSSL_NO_DH +/* Destroy DH key from single session. */ +int +pk11_destroy_dh_object(PK11_SESSION *sp, CK_BBOOL uselock) + { + int ret = 0; + + if (sp->opdata_dh_key != CK_INVALID_HANDLE) + { + TRY_OBJ_DESTROY(sp, sp->opdata_dh_key, + ret, uselock, OP_DH, CK_TRUE); + sp->opdata_dh_key = CK_INVALID_HANDLE; + sp->opdata_dh = NULL; + if (sp->opdata_dh_priv_num != NULL) + { + BN_free(sp->opdata_dh_priv_num); + sp->opdata_dh_priv_num = NULL; + } + } + + return (ret); + } + +/* + * Destroy DH key object wrapper. + * + * arg0: pointer to PKCS#11 engine session structure + * if session is NULL, try to destroy all objects in the free list + */ +int +pk11_destroy_dh_key_objects(PK11_SESSION *session) + { + int ret = 1; + PK11_SESSION *sp = NULL; + PK11_SESSION *local_free_session; + CK_BBOOL uselock = TRUE; + + if (session != NULL) + local_free_session = session; + else + { +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_lock(session_cache[OP_DH].lock) == 0); +#else + CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); +#endif + local_free_session = session_cache[OP_DH].head; + uselock = FALSE; + } + + while ((sp = local_free_session) != NULL) + { + local_free_session = sp->next; + + /* + * Do not terminate list traversal if one of the + * destroy operations fails. + */ + if (pk11_destroy_dh_object(sp, uselock) == 0) + { + ret = 0; + continue; + } + } + +#ifndef NOPTHREADS + if (session == NULL) + OPENSSL_assert(pthread_mutex_unlock(session_cache[OP_DH].lock) == 0); +#else + if (session == NULL) + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + + return (ret); + } +#endif /* OPENSSL_NO_DH */ + +static int +pk11_destroy_object(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE oh, + CK_BBOOL persistent) + { + CK_RV rv; + + /* + * We never try to destroy persistent objects which are the objects + * stored in the keystore. Also, we always use read-only sessions so + * C_DestroyObject() would be returning CKR_SESSION_READ_ONLY here. + */ + if (persistent == CK_TRUE) + return (1); + + rv = pFuncList->C_DestroyObject(session, oh); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DESTROY_OBJECT, PK11_R_DESTROYOBJECT, + rv); + return (0); + } + + return (1); + } + + +/* Symmetric ciphers and digests support functions */ + +static int +cipher_nid_to_pk11(int nid) + { + int i; + + for (i = 0; i < PK11_CIPHER_MAX; i++) + if (ciphers[i].nid == nid) + return (ciphers[i].id); + return (-1); + } + +static int +pk11_usable_ciphers(const int **nids) + { + if (cipher_count > 0) + *nids = cipher_nids; + else + *nids = NULL; + return (cipher_count); + } + +static int +pk11_usable_digests(const int **nids) + { + if (digest_count > 0) + *nids = digest_nids; + else + *nids = NULL; + return (digest_count); + } + +/* + * Init context for encryption or decryption using a symmetric key. + */ +static int pk11_init_symmetric(EVP_CIPHER_CTX *ctx, PK11_CIPHER *pcipher, + PK11_SESSION *sp, CK_MECHANISM_PTR pmech) + { + CK_RV rv; +#ifdef SOLARIS_AES_CTR + CK_AES_CTR_PARAMS ctr_params; +#endif /* SOLARIS_AES_CTR */ + + /* + * We expect pmech->mechanism to be already set and + * pParameter/ulParameterLen initialized to NULL/0 before + * pk11_init_symetric() is called. + */ + OPENSSL_assert(pmech->mechanism != 0); + OPENSSL_assert(pmech->pParameter == NULL); + OPENSSL_assert(pmech->ulParameterLen == 0); + +#ifdef SOLARIS_AES_CTR + if (ctx->cipher->nid == NID_aes_128_ctr || + ctx->cipher->nid == NID_aes_192_ctr || + ctx->cipher->nid == NID_aes_256_ctr) + { + pmech->pParameter = (void *)(&ctr_params); + pmech->ulParameterLen = sizeof (ctr_params); + /* + * For now, we are limited to the fixed length of the counter, + * it covers the whole counter block. That's what RFC 4344 + * needs. For more information on internal structure of the + * counter block, see RFC 3686. If needed in the future, we can + * add code so that the counter length can be set via + * ENGINE_ctrl() function. + */ + ctr_params.ulCounterBits = AES_BLOCK_SIZE * 8; + OPENSSL_assert(pcipher->iv_len == AES_BLOCK_SIZE); + (void) memcpy(ctr_params.cb, ctx->iv, AES_BLOCK_SIZE); + } + else +#endif /* SOLARIS_AES_CTR */ + { + if (pcipher->iv_len > 0) + { + pmech->pParameter = (void *)ctx->iv; + pmech->ulParameterLen = pcipher->iv_len; + } + } + + /* if we get here, the encryption needs to be reinitialized */ + if (ctx->encrypt) + rv = pFuncList->C_EncryptInit(sp->session, pmech, + sp->opdata_cipher_key); + else + rv = pFuncList->C_DecryptInit(sp->session, pmech, + sp->opdata_cipher_key); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_CIPHER_INIT, ctx->encrypt ? + PK11_R_ENCRYPTINIT : PK11_R_DECRYPTINIT, rv); + pk11_return_session(sp, OP_CIPHER); + return (0); + } + + return (1); + } + +/* ARGSUSED */ +static int +pk11_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc) + { + CK_MECHANISM mech; + int index; + PK11_CIPHER_STATE *state = (PK11_CIPHER_STATE *) ctx->cipher_data; + PK11_SESSION *sp; + PK11_CIPHER *p_ciph_table_row; + + state->sp = NULL; + + index = cipher_nid_to_pk11(ctx->cipher->nid); + if (index < 0 || index >= PK11_CIPHER_MAX) + return (0); + + p_ciph_table_row = &ciphers[index]; + /* + * iv_len in the ctx->cipher structure is the maximum IV length for the + * current cipher and it must be less or equal to the IV length in our + * ciphers table. The key length must be in the allowed interval. From + * all cipher modes that the PKCS#11 engine supports only RC4 allows a + * key length to be in some range, all other NIDs have a precise key + * length. Every application can define its own EVP functions so this + * code serves as a sanity check. + * + * Note that the reason why the IV length in ctx->cipher might be + * greater than the actual length is that OpenSSL uses BLOCK_CIPHER_defs + * macro to define functions that return EVP structures for all DES + * modes. So, even ECB modes get 8 byte IV. + */ + if (ctx->cipher->iv_len < p_ciph_table_row->iv_len || + ctx->key_len < p_ciph_table_row->min_key_len || + ctx->key_len > p_ciph_table_row->max_key_len) { + PK11err(PK11_F_CIPHER_INIT, PK11_R_KEY_OR_IV_LEN_PROBLEM); + return (0); + } + + if ((sp = pk11_get_session(OP_CIPHER)) == NULL) + return (0); + + /* if applicable, the mechanism parameter is used for IV */ + mech.mechanism = p_ciph_table_row->mech_type; + mech.pParameter = NULL; + mech.ulParameterLen = 0; + + /* The key object is destroyed here if it is not the current key. */ + (void) check_new_cipher_key(sp, key, ctx->key_len); + + /* + * If the key is the same and the encryption is also the same, then + * just reuse it. However, we must not forget to reinitialize the + * context that was finalized in pk11_cipher_cleanup(). + */ + if (sp->opdata_cipher_key != CK_INVALID_HANDLE && + sp->opdata_encrypt == ctx->encrypt) + { + state->sp = sp; + if (pk11_init_symmetric(ctx, p_ciph_table_row, sp, &mech) == 0) + return (0); + + return (1); + } + + /* + * Check if the key has been invalidated. If so, a new key object + * needs to be created. + */ + if (sp->opdata_cipher_key == CK_INVALID_HANDLE) + { + sp->opdata_cipher_key = pk11_get_cipher_key( + ctx, key, p_ciph_table_row->key_type, sp); + } + + if (sp->opdata_encrypt != ctx->encrypt && sp->opdata_encrypt != -1) + { + /* + * The previous encryption/decryption is different. Need to + * terminate the previous * active encryption/decryption here. + */ + if (!pk11_cipher_final(sp)) + { + pk11_return_session(sp, OP_CIPHER); + return (0); + } + } + + if (sp->opdata_cipher_key == CK_INVALID_HANDLE) + { + pk11_return_session(sp, OP_CIPHER); + return (0); + } + + /* now initialize the context with a new key */ + if (pk11_init_symmetric(ctx, p_ciph_table_row, sp, &mech) == 0) + return (0); + + sp->opdata_encrypt = ctx->encrypt; + state->sp = sp; + + return (1); + } + +/* + * When reusing the same key in an encryption/decryption session for a + * decryption/encryption session, we need to close the active session + * and recreate a new one. Note that the key is in the global session so + * that it needs not be recreated. + * + * It is more appropriate to use C_En/DecryptFinish here. At the time of this + * development, these two functions in the PKCS#11 libraries used return + * unexpected errors when passing in 0 length output. It may be a good + * idea to try them again if performance is a problem here and fix + * C_En/DecryptFinial if there are bugs there causing the problem. + */ +static int +pk11_cipher_final(PK11_SESSION *sp) + { + CK_RV rv; + + rv = pFuncList->C_CloseSession(sp->session); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_CIPHER_FINAL, PK11_R_CLOSESESSION, rv); + return (0); + } + + rv = pFuncList->C_OpenSession(SLOTID, CKF_SERIAL_SESSION, + NULL_PTR, NULL_PTR, &sp->session); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_CIPHER_FINAL, PK11_R_OPENSESSION, rv); + return (0); + } + + return (1); + } + +/* + * An engine interface function. The calling function allocates sufficient + * memory for the output buffer "out" to hold the results. + */ +#if OPENSSL_VERSION_NUMBER < 0x10000000L +static int +pk11_cipher_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, unsigned int inl) +#else +static int +pk11_cipher_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t inl) +#endif + { + PK11_CIPHER_STATE *state = (PK11_CIPHER_STATE *) ctx->cipher_data; + PK11_SESSION *sp; + CK_RV rv; + unsigned long outl = inl; + + if (state == NULL || state->sp == NULL) + return (0); + + sp = (PK11_SESSION *) state->sp; + + if (!inl) + return (1); + + /* RC4 is the only stream cipher we support */ + if (ctx->cipher->nid != NID_rc4 && (inl % ctx->cipher->block_size) != 0) + return (0); + + if (ctx->encrypt) + { + rv = pFuncList->C_EncryptUpdate(sp->session, + (unsigned char *)in, inl, out, &outl); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_CIPHER_DO_CIPHER, + PK11_R_ENCRYPTUPDATE, rv); + return (0); + } + } + else + { + rv = pFuncList->C_DecryptUpdate(sp->session, + (unsigned char *)in, inl, out, &outl); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_CIPHER_DO_CIPHER, + PK11_R_DECRYPTUPDATE, rv); + return (0); + } + } + + /* + * For DES_CBC, DES3_CBC, AES_CBC, and RC4, the output size is always + * the same size of input. + * The application has guaranteed to call the block ciphers with + * correctly aligned buffers. + */ + if (inl != outl) + return (0); + + return (1); + } + +/* + * Return the session to the pool. Calling C_EncryptFinal() and C_DecryptFinal() + * here is the right thing because in EVP_DecryptFinal_ex(), engine's + * do_cipher() is not even called, and in EVP_EncryptFinal_ex() it is called but + * the engine can't find out that it's the finalizing call. We wouldn't + * necessarily have to finalize the context here since reinitializing it with + * C_(Encrypt|Decrypt)Init() should be fine but for the sake of correctness, + * let's do it. Some implementations might leak memory if the previously used + * context is initialized without finalizing it first. + */ +static int +pk11_cipher_cleanup(EVP_CIPHER_CTX *ctx) + { + CK_RV rv; + CK_ULONG len = EVP_MAX_BLOCK_LENGTH; + CK_BYTE buf[EVP_MAX_BLOCK_LENGTH]; + PK11_CIPHER_STATE *state = ctx->cipher_data; + + if (state != NULL && state->sp != NULL) + { + /* + * We are not interested in the data here, we just need to get + * rid of the context. + */ + if (ctx->encrypt) + rv = pFuncList->C_EncryptFinal( + state->sp->session, buf, &len); + else + rv = pFuncList->C_DecryptFinal( + state->sp->session, buf, &len); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_CIPHER_CLEANUP, ctx->encrypt ? + PK11_R_ENCRYPTFINAL : PK11_R_DECRYPTFINAL, rv); + pk11_return_session(state->sp, OP_CIPHER); + return (0); + } + + pk11_return_session(state->sp, OP_CIPHER); + state->sp = NULL; + } + + return (1); + } + +/* + * Registered by the ENGINE when used to find out how to deal with + * a particular NID in the ENGINE. This says what we'll do at the + * top level - note, that list is restricted by what we answer with + */ +/* ARGSUSED */ +static int +pk11_engine_ciphers(ENGINE *e, const EVP_CIPHER **cipher, + const int **nids, int nid) + { + if (!cipher) + return (pk11_usable_ciphers(nids)); + + switch (nid) + { + case NID_des_ede3_cbc: + *cipher = &pk11_3des_cbc; + break; + case NID_des_cbc: + *cipher = &pk11_des_cbc; + break; + case NID_des_ede3_ecb: + *cipher = &pk11_3des_ecb; + break; + case NID_des_ecb: + *cipher = &pk11_des_ecb; + break; + case NID_aes_128_cbc: + *cipher = &pk11_aes_128_cbc; + break; + case NID_aes_192_cbc: + *cipher = &pk11_aes_192_cbc; + break; + case NID_aes_256_cbc: + *cipher = &pk11_aes_256_cbc; + break; + case NID_aes_128_ecb: + *cipher = &pk11_aes_128_ecb; + break; + case NID_aes_192_ecb: + *cipher = &pk11_aes_192_ecb; + break; + case NID_aes_256_ecb: + *cipher = &pk11_aes_256_ecb; + break; + case NID_bf_cbc: + *cipher = &pk11_bf_cbc; + break; + case NID_rc4: + *cipher = &pk11_rc4; + break; + default: +#ifdef SOLARIS_AES_CTR + /* + * These can't be in separated cases because the NIDs + * here are not constants. + */ + if (nid == NID_aes_128_ctr) + *cipher = &pk11_aes_128_ctr; + else if (nid == NID_aes_192_ctr) + *cipher = &pk11_aes_192_ctr; + else if (nid == NID_aes_256_ctr) + *cipher = &pk11_aes_256_ctr; + else +#endif /* SOLARIS_AES_CTR */ + *cipher = NULL; + break; + } + return (*cipher != NULL); + } + +/* ARGSUSED */ +static int +pk11_engine_digests(ENGINE *e, const EVP_MD **digest, + const int **nids, int nid) + { + if (!digest) + return (pk11_usable_digests(nids)); + + switch (nid) + { + case NID_md5: + *digest = &pk11_md5; + break; + case NID_sha1: + *digest = &pk11_sha1; + break; + case NID_sha224: + *digest = &pk11_sha224; + break; + case NID_sha256: + *digest = &pk11_sha256; + break; + case NID_sha384: + *digest = &pk11_sha384; + break; + case NID_sha512: + *digest = &pk11_sha512; + break; + default: + *digest = NULL; + break; + } + return (*digest != NULL); + } + + +/* Create a secret key object in a PKCS#11 session */ +static CK_OBJECT_HANDLE pk11_get_cipher_key(EVP_CIPHER_CTX *ctx, + const unsigned char *key, CK_KEY_TYPE key_type, PK11_SESSION *sp) + { + CK_RV rv; + CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE; + CK_OBJECT_CLASS obj_key = CKO_SECRET_KEY; + CK_ULONG ul_key_attr_count = 6; + unsigned char key_buf[PK11_KEY_LEN_MAX]; + + CK_ATTRIBUTE a_key_template[] = + { + {CKA_CLASS, (void*) NULL, sizeof (CK_OBJECT_CLASS)}, + {CKA_KEY_TYPE, (void*) NULL, sizeof (CK_KEY_TYPE)}, + {CKA_TOKEN, &myfalse, sizeof (myfalse)}, + {CKA_ENCRYPT, &mytrue, sizeof (mytrue)}, + {CKA_DECRYPT, &mytrue, sizeof (mytrue)}, + {CKA_VALUE, (void*) NULL, 0}, + }; + + /* + * Create secret key object in global_session. All other sessions + * can use the key handles. Here is why: + * OpenSSL will call EncryptInit and EncryptUpdate using a secret key. + * It may then call DecryptInit and DecryptUpdate using the same key. + * To use the same key object, we need to call EncryptFinal with + * a 0 length message. Currently, this does not work for 3DES + * mechanism. To get around this problem, we close the session and + * then create a new session to use the same key object. When a session + * is closed, all the object handles will be invalid. Thus, create key + * objects in a global session, an individual session may be closed to + * terminate the active operation. + */ + CK_SESSION_HANDLE session = global_session; + a_key_template[0].pValue = &obj_key; + a_key_template[1].pValue = &key_type; + if (ctx->key_len > PK11_KEY_LEN_MAX) + { + a_key_template[5].pValue = (void *) key; + } + else + { + memset(key_buf, 0, PK11_KEY_LEN_MAX); + memcpy(key_buf, key, ctx->key_len); + if ((key_type == CKK_DES) || + (key_type == CKK_DES2) || + (key_type == CKK_DES3)) + DES_fixup_key_parity((DES_cblock *) &key_buf[0]); + if ((key_type == CKK_DES2) || + (key_type == CKK_DES3)) + DES_fixup_key_parity((DES_cblock *) &key_buf[8]); + if (key_type == CKK_DES3) + DES_fixup_key_parity((DES_cblock *) &key_buf[16]); + a_key_template[5].pValue = (void *) key_buf; + } + a_key_template[5].ulValueLen = (unsigned long) ctx->key_len; + + rv = pFuncList->C_CreateObject(session, + a_key_template, ul_key_attr_count, &h_key); + if (rv != CKR_OK) + { + memset(key_buf, 0, PK11_KEY_LEN_MAX); + PK11err_add_data(PK11_F_GET_CIPHER_KEY, PK11_R_CREATEOBJECT, + rv); + goto err; + } + + /* + * Save the key information used in this session. + * The max can be saved is PK11_KEY_LEN_MAX. + */ + if (ctx->key_len > PK11_KEY_LEN_MAX) + { + sp->opdata_key_len = PK11_KEY_LEN_MAX; + (void) memcpy(sp->opdata_key, key, sp->opdata_key_len); + } + else + { + sp->opdata_key_len = ctx->key_len; + (void) memcpy(sp->opdata_key, key_buf, sp->opdata_key_len); + } + memset(key_buf, 0, PK11_KEY_LEN_MAX); +err: + + return (h_key); + } + +static int +md_nid_to_pk11(int nid) + { + int i; + + for (i = 0; i < PK11_DIGEST_MAX; i++) + if (digests[i].nid == nid) + return (digests[i].id); + return (-1); + } + +static int +pk11_digest_init(EVP_MD_CTX *ctx) + { + CK_RV rv; + CK_MECHANISM mech; + int index; + PK11_SESSION *sp; + PK11_DIGEST *pdp; + PK11_CIPHER_STATE *state = (PK11_CIPHER_STATE *) ctx->md_data; + + state->sp = NULL; + + index = md_nid_to_pk11(ctx->digest->type); + if (index < 0 || index >= PK11_DIGEST_MAX) + return (0); + + pdp = &digests[index]; + if ((sp = pk11_get_session(OP_DIGEST)) == NULL) + return (0); + + /* at present, no parameter is needed for supported digests */ + mech.mechanism = pdp->mech_type; + mech.pParameter = NULL; + mech.ulParameterLen = 0; + + rv = pFuncList->C_DigestInit(sp->session, &mech); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DIGEST_INIT, PK11_R_DIGESTINIT, rv); + pk11_return_session(sp, OP_DIGEST); + return (0); + } + + state->sp = sp; + + return (1); + } + +static int +pk11_digest_update(EVP_MD_CTX *ctx, const void *data, size_t count) + { + CK_RV rv; + PK11_CIPHER_STATE *state = (PK11_CIPHER_STATE *) ctx->md_data; + + /* 0 length message will cause a failure in C_DigestFinal */ + if (count == 0) + return (1); + + if (state == NULL || state->sp == NULL) + return (0); + + rv = pFuncList->C_DigestUpdate(state->sp->session, (CK_BYTE *) data, + count); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DIGEST_UPDATE, PK11_R_DIGESTUPDATE, rv); + pk11_return_session(state->sp, OP_DIGEST); + state->sp = NULL; + return (0); + } + + return (1); + } + +static int +pk11_digest_final(EVP_MD_CTX *ctx, unsigned char *md) + { + CK_RV rv; + unsigned long len; + PK11_CIPHER_STATE *state = (PK11_CIPHER_STATE *) ctx->md_data; + len = ctx->digest->md_size; + + if (state == NULL || state->sp == NULL) + return (0); + + rv = pFuncList->C_DigestFinal(state->sp->session, md, &len); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DIGEST_FINAL, PK11_R_DIGESTFINAL, rv); + pk11_return_session(state->sp, OP_DIGEST); + state->sp = NULL; + return (0); + } + + if (ctx->digest->md_size != len) + return (0); + + /* + * Final is called and digest is returned, so return the session + * to the pool + */ + pk11_return_session(state->sp, OP_DIGEST); + state->sp = NULL; + + return (1); + } + +static int +pk11_digest_copy(EVP_MD_CTX *to, const EVP_MD_CTX *from) + { + CK_RV rv; + int ret = 0; + PK11_CIPHER_STATE *state, *state_to; + CK_BYTE_PTR pstate = NULL; + CK_ULONG ul_state_len; + + /* The copy-from state */ + state = (PK11_CIPHER_STATE *) from->md_data; + if (state == NULL || state->sp == NULL) + goto err; + + /* Initialize the copy-to state */ + if (!pk11_digest_init(to)) + goto err; + state_to = (PK11_CIPHER_STATE *) to->md_data; + + /* Get the size of the operation state of the copy-from session */ + rv = pFuncList->C_GetOperationState(state->sp->session, NULL, + &ul_state_len); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DIGEST_COPY, PK11_R_GET_OPERATION_STATE, + rv); + goto err; + } + if (ul_state_len == 0) + { + goto err; + } + + pstate = OPENSSL_malloc(ul_state_len); + if (pstate == NULL) + { + PK11err(PK11_F_DIGEST_COPY, PK11_R_MALLOC_FAILURE); + goto err; + } + + /* Get the operation state of the copy-from session */ + rv = pFuncList->C_GetOperationState(state->sp->session, pstate, + &ul_state_len); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DIGEST_COPY, PK11_R_GET_OPERATION_STATE, + rv); + goto err; + } + + /* Set the operation state of the copy-to session */ + rv = pFuncList->C_SetOperationState(state_to->sp->session, pstate, + ul_state_len, 0, 0); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DIGEST_COPY, + PK11_R_SET_OPERATION_STATE, rv); + goto err; + } + + ret = 1; +err: + if (pstate != NULL) + OPENSSL_free(pstate); + + return (ret); + } + +/* Return any pending session state to the pool */ +static int +pk11_digest_cleanup(EVP_MD_CTX *ctx) + { + PK11_CIPHER_STATE *state = ctx->md_data; + unsigned char buf[EVP_MAX_MD_SIZE]; + + if (state != NULL && state->sp != NULL) + { + /* + * If state->sp is not NULL then pk11_digest_final() has not + * been called yet. We must call it now to free any memory + * that might have been allocated in the token when + * pk11_digest_init() was called. pk11_digest_final() + * will return the session to the cache. + */ + if (!pk11_digest_final(ctx, buf)) + return (0); + } + + return (1); + } + +/* + * Check if the new key is the same as the key object in the session. If the key + * is the same, no need to create a new key object. Otherwise, the old key + * object needs to be destroyed and a new one will be created. Return 1 for + * cache hit, 0 for cache miss. Note that we must check the key length first + * otherwise we could end up reusing a different, longer key with the same + * prefix. + */ +static int check_new_cipher_key(PK11_SESSION *sp, const unsigned char *key, + int key_len) + { + if (sp->opdata_key_len != key_len || + memcmp(sp->opdata_key, key, key_len) != 0) + { + (void) pk11_destroy_cipher_key_objects(sp); + return (0); + } + return (1); + } + +/* Destroy one or more secret key objects. */ +static int pk11_destroy_cipher_key_objects(PK11_SESSION *session) + { + int ret = 0; + PK11_SESSION *sp = NULL; + PK11_SESSION *local_free_session; + + if (session != NULL) + local_free_session = session; + else + { +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_lock(session_cache[OP_CIPHER].lock) == 0); +#else + CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); +#endif + local_free_session = session_cache[OP_CIPHER].head; + } + + while ((sp = local_free_session) != NULL) + { + local_free_session = sp->next; + + if (sp->opdata_cipher_key != CK_INVALID_HANDLE) + { + /* + * The secret key object is created in the + * global_session. See pk11_get_cipher_key(). + */ + if (pk11_destroy_object(global_session, + sp->opdata_cipher_key, CK_FALSE) == 0) + goto err; + sp->opdata_cipher_key = CK_INVALID_HANDLE; + } + } + ret = 1; +err: + +#ifndef NOPTHREADS + if (session == NULL) + OPENSSL_assert(pthread_mutex_unlock(session_cache[OP_CIPHER].lock) == 0); +#else + if (session == NULL) + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + + return (ret); + } + + +/* + * Public key mechanisms optionally supported + * + * CKM_RSA_X_509 + * CKM_RSA_PKCS + * CKM_DSA + * + * The first slot that supports at least one of those mechanisms is chosen as a + * public key slot. + * + * Symmetric ciphers optionally supported + * + * CKM_DES3_CBC + * CKM_DES_CBC + * CKM_AES_CBC + * CKM_DES3_ECB + * CKM_DES_ECB + * CKM_AES_ECB + * CKM_AES_CTR + * CKM_RC4 + * CKM_BLOWFISH_CBC + * + * Digests optionally supported + * + * CKM_MD5 + * CKM_SHA_1 + * CKM_SHA224 + * CKM_SHA256 + * CKM_SHA384 + * CKM_SHA512 + * + * The output of this function is a set of global variables indicating which + * mechanisms from RSA, DSA, DH and RAND are present, and also two arrays of + * mechanisms, one for symmetric ciphers and one for digests. Also, 3 global + * variables carry information about which slot was chosen for (a) public key + * mechanisms, (b) random operations, and (c) symmetric ciphers and digests. + */ +static int +pk11_choose_slots(int *any_slot_found) + { + CK_SLOT_ID_PTR pSlotList = NULL_PTR; + CK_ULONG ulSlotCount = 0; + CK_MECHANISM_INFO mech_info; + CK_TOKEN_INFO token_info; + unsigned int i; + CK_RV rv; + CK_SLOT_ID best_slot_sofar = 0; + CK_BBOOL found_candidate_slot = CK_FALSE; + int slot_n_cipher = 0; + int slot_n_digest = 0; + CK_SLOT_ID current_slot = 0; + int current_slot_n_cipher = 0; + int current_slot_n_digest = 0; + + int local_cipher_nids[PK11_CIPHER_MAX]; + int local_digest_nids[PK11_DIGEST_MAX]; + + /* let's initialize the output parameter */ + if (any_slot_found != NULL) + *any_slot_found = 0; + + /* Get slot list for memory allocation */ + rv = pFuncList->C_GetSlotList(CK_FALSE, NULL_PTR, &ulSlotCount); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_CHOOSE_SLOT, PK11_R_GETSLOTLIST, rv); + return (0); + } + + /* it's not an error if we didn't find any providers */ + if (ulSlotCount == 0) + { +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: no crypto providers found\n", PK11_DBG); +#endif /* DEBUG_SLOT_SELECTION */ + return (1); + } + + pSlotList = OPENSSL_malloc(ulSlotCount * sizeof (CK_SLOT_ID)); + + if (pSlotList == NULL) + { + PK11err(PK11_F_CHOOSE_SLOT, PK11_R_MALLOC_FAILURE); + return (0); + } + + /* Get the slot list for processing */ + rv = pFuncList->C_GetSlotList(CK_FALSE, pSlotList, &ulSlotCount); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_CHOOSE_SLOT, PK11_R_GETSLOTLIST, rv); + OPENSSL_free(pSlotList); + return (0); + } + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: provider: %s\n", PK11_DBG, def_PK11_LIBNAME); + fprintf(stderr, "%s: number of slots: %d\n", PK11_DBG, ulSlotCount); + + fprintf(stderr, "%s: == checking rand slots ==\n", PK11_DBG); +#endif /* DEBUG_SLOT_SELECTION */ + for (i = 0; i < ulSlotCount; i++) + { + current_slot = pSlotList[i]; + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: checking slot: %d\n", PK11_DBG, i); +#endif /* DEBUG_SLOT_SELECTION */ + /* Check if slot has random support. */ + rv = pFuncList->C_GetTokenInfo(current_slot, &token_info); + if (rv != CKR_OK) + continue; + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: token label: %.32s\n", PK11_DBG, token_info.label); +#endif /* DEBUG_SLOT_SELECTION */ + + if (token_info.flags & CKF_RNG) + { +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: this token has CKF_RNG flag\n", PK11_DBG); +#endif /* DEBUG_SLOT_SELECTION */ + pk11_have_random = CK_TRUE; + rand_SLOTID = current_slot; + break; + } + } + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: == checking pubkey slots ==\n", PK11_DBG); +#endif /* DEBUG_SLOT_SELECTION */ + + pubkey_SLOTID = pSlotList[0]; + for (i = 0; i < ulSlotCount; i++) + { + CK_BBOOL slot_has_rsa = CK_FALSE; + CK_BBOOL slot_has_recover = CK_FALSE; + CK_BBOOL slot_has_dsa = CK_FALSE; + CK_BBOOL slot_has_dh = CK_FALSE; + current_slot = pSlotList[i]; + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: checking slot: %d\n", PK11_DBG, i); +#endif /* DEBUG_SLOT_SELECTION */ + rv = pFuncList->C_GetTokenInfo(current_slot, &token_info); + if (rv != CKR_OK) + continue; + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: token label: %.32s\n", PK11_DBG, token_info.label); +#endif /* DEBUG_SLOT_SELECTION */ + +#ifndef OPENSSL_NO_RSA + /* + * Check if this slot is capable of signing and + * verifying with CKM_RSA_PKCS. + */ + rv = pFuncList->C_GetMechanismInfo(current_slot, CKM_RSA_PKCS, + &mech_info); + + if (rv == CKR_OK && ((mech_info.flags & CKF_SIGN) && + (mech_info.flags & CKF_VERIFY))) + { + /* + * Check if this slot is capable of encryption, + * decryption, sign, and verify with CKM_RSA_X_509. + */ + rv = pFuncList->C_GetMechanismInfo(current_slot, + CKM_RSA_X_509, &mech_info); + + if (rv == CKR_OK && ((mech_info.flags & CKF_SIGN) && + (mech_info.flags & CKF_VERIFY) && + (mech_info.flags & CKF_ENCRYPT) && + (mech_info.flags & CKF_DECRYPT))) + { + slot_has_rsa = CK_TRUE; + if (mech_info.flags & CKF_VERIFY_RECOVER) + { + slot_has_recover = CK_TRUE; + } + } + } +#endif /* OPENSSL_NO_RSA */ + +#ifndef OPENSSL_NO_DSA + /* + * Check if this slot is capable of signing and + * verifying with CKM_DSA. + */ + rv = pFuncList->C_GetMechanismInfo(current_slot, CKM_DSA, + &mech_info); + if (rv == CKR_OK && ((mech_info.flags & CKF_SIGN) && + (mech_info.flags & CKF_VERIFY))) + { + slot_has_dsa = CK_TRUE; + } + +#endif /* OPENSSL_NO_DSA */ + +#ifndef OPENSSL_NO_DH + /* + * Check if this slot is capable of DH key generataion and + * derivation. + */ + rv = pFuncList->C_GetMechanismInfo(current_slot, + CKM_DH_PKCS_KEY_PAIR_GEN, &mech_info); + + if (rv == CKR_OK && (mech_info.flags & CKF_GENERATE_KEY_PAIR)) + { + rv = pFuncList->C_GetMechanismInfo(current_slot, + CKM_DH_PKCS_DERIVE, &mech_info); + if (rv == CKR_OK && (mech_info.flags & CKF_DERIVE)) + { + slot_has_dh = CK_TRUE; + } + } +#endif /* OPENSSL_NO_DH */ + + if (!found_candidate_slot && + (slot_has_rsa || slot_has_dsa || slot_has_dh)) + { +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, + "%s: potential slot: %d\n", PK11_DBG, current_slot); +#endif /* DEBUG_SLOT_SELECTION */ + best_slot_sofar = current_slot; + pk11_have_rsa = slot_has_rsa; + pk11_have_recover = slot_has_recover; + pk11_have_dsa = slot_has_dsa; + pk11_have_dh = slot_has_dh; + found_candidate_slot = CK_TRUE; + /* + * Cache the flags for later use. We might + * need those if RSA keys by reference feature + * is used. + */ + pubkey_token_flags = token_info.flags; +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, + "%s: setting found_candidate_slot to CK_TRUE\n", + PK11_DBG); + fprintf(stderr, + "%s: best so far slot: %d\n", PK11_DBG, + best_slot_sofar); + fprintf(stderr, "%s: pubkey flags changed to " + "%lu.\n", PK11_DBG, pubkey_token_flags); + } + else + { + fprintf(stderr, + "%s: no rsa/dsa/dh\n", PK11_DBG); + } +#else + } /* if */ +#endif /* DEBUG_SLOT_SELECTION */ + } /* for */ + + if (found_candidate_slot == CK_TRUE) + { + pubkey_SLOTID = best_slot_sofar; + } + + found_candidate_slot = CK_FALSE; + best_slot_sofar = 0; + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: == checking cipher/digest ==\n", PK11_DBG); +#endif /* DEBUG_SLOT_SELECTION */ + + SLOTID = pSlotList[0]; + for (i = 0; i < ulSlotCount; i++) + { +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: checking slot: %d\n", PK11_DBG, i); +#endif /* DEBUG_SLOT_SELECTION */ + + current_slot = pSlotList[i]; + current_slot_n_cipher = 0; + current_slot_n_digest = 0; + (void) memset(local_cipher_nids, 0, sizeof (local_cipher_nids)); + (void) memset(local_digest_nids, 0, sizeof (local_digest_nids)); + + pk11_find_symmetric_ciphers(pFuncList, current_slot, + ¤t_slot_n_cipher, local_cipher_nids); + + pk11_find_digests(pFuncList, current_slot, + ¤t_slot_n_digest, local_digest_nids); + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: current_slot_n_cipher %d\n", PK11_DBG, + current_slot_n_cipher); + fprintf(stderr, "%s: current_slot_n_digest %d\n", PK11_DBG, + current_slot_n_digest); + fprintf(stderr, "%s: best so far cipher/digest slot: %d\n", + PK11_DBG, best_slot_sofar); +#endif /* DEBUG_SLOT_SELECTION */ + + /* + * If the current slot supports more ciphers/digests than + * the previous best one we change the current best to this one, + * otherwise leave it where it is. + */ + if ((current_slot_n_cipher + current_slot_n_digest) > + (slot_n_cipher + slot_n_digest)) + { +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, + "%s: changing best so far slot to %d\n", + PK11_DBG, current_slot); +#endif /* DEBUG_SLOT_SELECTION */ + best_slot_sofar = SLOTID = current_slot; + cipher_count = slot_n_cipher = current_slot_n_cipher; + digest_count = slot_n_digest = current_slot_n_digest; + (void) memcpy(cipher_nids, local_cipher_nids, + sizeof (local_cipher_nids)); + (void) memcpy(digest_nids, local_digest_nids, + sizeof (local_digest_nids)); + } + } + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, + "%s: chosen pubkey slot: %d\n", PK11_DBG, pubkey_SLOTID); + fprintf(stderr, + "%s: chosen rand slot: %d\n", PK11_DBG, rand_SLOTID); + fprintf(stderr, + "%s: chosen cipher/digest slot: %d\n", PK11_DBG, SLOTID); + fprintf(stderr, + "%s: pk11_have_rsa %d\n", PK11_DBG, pk11_have_rsa); + fprintf(stderr, + "%s: pk11_have_recover %d\n", PK11_DBG, pk11_have_recover); + fprintf(stderr, + "%s: pk11_have_dsa %d\n", PK11_DBG, pk11_have_dsa); + fprintf(stderr, + "%s: pk11_have_dh %d\n", PK11_DBG, pk11_have_dh); + fprintf(stderr, + "%s: pk11_have_random %d\n", PK11_DBG, pk11_have_random); + fprintf(stderr, + "%s: cipher_count %d\n", PK11_DBG, cipher_count); + fprintf(stderr, + "%s: digest_count %d\n", PK11_DBG, digest_count); +#endif /* DEBUG_SLOT_SELECTION */ + + if (pSlotList != NULL) + OPENSSL_free(pSlotList); + +#ifdef SOLARIS_HW_SLOT_SELECTION + OPENSSL_free(hw_cnids); + OPENSSL_free(hw_dnids); +#endif /* SOLARIS_HW_SLOT_SELECTION */ + + if (any_slot_found != NULL) + *any_slot_found = 1; + return (1); + } + +static void pk11_get_symmetric_cipher(CK_FUNCTION_LIST_PTR pflist, + int slot_id, CK_MECHANISM_TYPE mech, int *current_slot_n_cipher, + int *local_cipher_nids, int id) + { + CK_MECHANISM_INFO mech_info; + CK_RV rv; + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: checking mech: %x", PK11_DBG, mech); +#endif /* DEBUG_SLOT_SELECTION */ + rv = pflist->C_GetMechanismInfo(slot_id, mech, &mech_info); + + if (rv != CKR_OK) + { +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, " not found\n"); +#endif /* DEBUG_SLOT_SELECTION */ + return; + } + + if ((mech_info.flags & CKF_ENCRYPT) && + (mech_info.flags & CKF_DECRYPT)) + { +#ifdef SOLARIS_HW_SLOT_SELECTION + if (nid_in_table(ciphers[id].nid, hw_cnids)) +#endif /* SOLARIS_HW_SLOT_SELECTION */ + { +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, " usable\n"); +#endif /* DEBUG_SLOT_SELECTION */ + local_cipher_nids[(*current_slot_n_cipher)++] = + ciphers[id].nid; + } +#ifdef SOLARIS_HW_SLOT_SELECTION +#ifdef DEBUG_SLOT_SELECTION + else + { + fprintf(stderr, " rejected, software implementation only\n"); + } +#endif /* DEBUG_SLOT_SELECTION */ +#endif /* SOLARIS_HW_SLOT_SELECTION */ + } +#ifdef DEBUG_SLOT_SELECTION + else + { + fprintf(stderr, " unusable\n"); + } +#endif /* DEBUG_SLOT_SELECTION */ + + return; + } + +static void pk11_get_digest(CK_FUNCTION_LIST_PTR pflist, int slot_id, + CK_MECHANISM_TYPE mech, int *current_slot_n_digest, int *local_digest_nids, + int id) + { + CK_MECHANISM_INFO mech_info; + CK_RV rv; + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: checking mech: %x", PK11_DBG, mech); +#endif /* DEBUG_SLOT_SELECTION */ + rv = pflist->C_GetMechanismInfo(slot_id, mech, &mech_info); + + if (rv != CKR_OK) + { +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, " not found\n"); +#endif /* DEBUG_SLOT_SELECTION */ + return; + } + + if (mech_info.flags & CKF_DIGEST) + { +#ifdef SOLARIS_HW_SLOT_SELECTION + if (nid_in_table(digests[id].nid, hw_dnids)) +#endif /* SOLARIS_HW_SLOT_SELECTION */ + { +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, " usable\n"); +#endif /* DEBUG_SLOT_SELECTION */ + local_digest_nids[(*current_slot_n_digest)++] = + digests[id].nid; + } +#ifdef SOLARIS_HW_SLOT_SELECTION +#ifdef DEBUG_SLOT_SELECTION + else + { + fprintf(stderr, " rejected, software implementation only\n"); + } +#endif /* DEBUG_SLOT_SELECTION */ +#endif /* SOLARIS_HW_SLOT_SELECTION */ + } +#ifdef DEBUG_SLOT_SELECTION + else + { + fprintf(stderr, " unusable\n"); + } +#endif /* DEBUG_SLOT_SELECTION */ + + return; + } + +#ifdef SOLARIS_AES_CTR +/* create a new NID when we have no OID for that mechanism */ +static int pk11_add_NID(char *sn, char *ln) + { + ASN1_OBJECT *o; + int nid; + + if ((o = ASN1_OBJECT_create(OBJ_new_nid(1), (unsigned char *)"", + 1, sn, ln)) == NULL) + { + return (0); + } + + /* will return NID_undef on error */ + nid = OBJ_add_object(o); + ASN1_OBJECT_free(o); + + return (nid); + } + +/* + * Create new NIDs for AES counter mode. OpenSSL doesn't support them now so we + * have to help ourselves here. + */ +static int pk11_add_aes_ctr_NIDs(void) + { + /* are we already set? */ + if (NID_aes_256_ctr != NID_undef) + return (1); + + /* + * There are no official names for AES counter modes yet so we just + * follow the format of those that exist. + */ + if ((NID_aes_128_ctr = pk11_add_NID("AES-128-CTR", "aes-128-ctr")) == + NID_undef) + goto err; + ciphers[PK11_AES_128_CTR].nid = pk11_aes_128_ctr.nid = NID_aes_128_ctr; + if ((NID_aes_192_ctr = pk11_add_NID("AES-192-CTR", "aes-192-ctr")) == + NID_undef) + goto err; + ciphers[PK11_AES_192_CTR].nid = pk11_aes_192_ctr.nid = NID_aes_192_ctr; + if ((NID_aes_256_ctr = pk11_add_NID("AES-256-CTR", "aes-256-ctr")) == + NID_undef) + goto err; + ciphers[PK11_AES_256_CTR].nid = pk11_aes_256_ctr.nid = NID_aes_256_ctr; + return (1); + +err: + PK11err(PK11_F_ADD_AES_CTR_NIDS, PK11_R_ADD_NID_FAILED); + return (0); + } +#endif /* SOLARIS_AES_CTR */ + +/* Find what symmetric ciphers this slot supports. */ +static void pk11_find_symmetric_ciphers(CK_FUNCTION_LIST_PTR pflist, + CK_SLOT_ID current_slot, int *current_slot_n_cipher, int *local_cipher_nids) + { + int i; + + for (i = 0; i < PK11_CIPHER_MAX; ++i) + { + pk11_get_symmetric_cipher(pflist, current_slot, + ciphers[i].mech_type, current_slot_n_cipher, + local_cipher_nids, ciphers[i].id); + } + } + +/* Find what digest algorithms this slot supports. */ +static void pk11_find_digests(CK_FUNCTION_LIST_PTR pflist, + CK_SLOT_ID current_slot, int *current_slot_n_digest, int *local_digest_nids) + { + int i; + + for (i = 0; i < PK11_DIGEST_MAX; ++i) + { + pk11_get_digest(pflist, current_slot, digests[i].mech_type, + current_slot_n_digest, local_digest_nids, digests[i].id); + } + } + +#ifdef SOLARIS_HW_SLOT_SELECTION +/* + * It would be great if we could use pkcs11_kernel directly since this library + * offers hardware slots only. That's the easiest way to achieve the situation + * where we use the hardware accelerators when present and OpenSSL native code + * otherwise. That presumes the fact that OpenSSL native code is faster than the + * code in the soft token. It's a logical assumption - Crypto Framework has some + * inherent overhead so going there for the software implementation of a + * mechanism should be logically slower in contrast to the OpenSSL native code, + * presuming that both implementations are of similar speed. For example, the + * soft token for AES is roughly three times slower than OpenSSL for 64 byte + * blocks and still 20% slower for 8KB blocks. So, if we want to ship products + * that use the PKCS#11 engine by default, we must somehow avoid that regression + * on machines without hardware acceleration. That's why switching to the + * pkcs11_kernel library seems like a very good idea. + * + * The problem is that OpenSSL built with SunStudio is roughly 2x slower for + * asymmetric operations (RSA/DSA/DH) than the soft token built with the same + * compiler. That means that if we switched to pkcs11_kernel from the libpkcs11 + * library, we would have had a performance regression on machines without + * hardware acceleration for asymmetric operations for all applications that use + * the PKCS#11 engine. There is one such application - Apache web server since + * it's shipped configured to use the PKCS#11 engine by default. Having said + * that, we can't switch to the pkcs11_kernel library now and have to come with + * a solution that, on non-accelerated machines, uses the OpenSSL native code + * for all symmetric ciphers and digests while it uses the soft token for + * asymmetric operations. + * + * This is the idea: dlopen() pkcs11_kernel directly and find out what + * mechanisms are there. We don't care about duplications (more slots can + * support the same mechanism), we just want to know what mechanisms can be + * possibly supported in hardware on that particular machine. As said before, + * pkcs11_kernel will show you hardware providers only. + * + * Then, we rely on the fact that since we use libpkcs11 library we will find + * the metaslot. When we go through the metaslot's mechanisms for symmetric + * ciphers and digests, we check that any found mechanism is in the table + * created using the pkcs11_kernel library. So, as a result we have two arrays + * of mechanisms that were advertised as supported in hardware which was the + * goal of that whole excercise. Thus, we can use libpkcs11 but avoid soft token + * code for symmetric ciphers and digests. See pk11_choose_slots() for more + * information. + * + * This is Solaris specific code, if SOLARIS_HW_SLOT_SELECTION is not defined + * the code won't be used. + */ +#if defined(__sparcv9) || defined(__x86_64) || defined(__amd64) +static const char pkcs11_kernel[] = "/usr/lib/security/64/pkcs11_kernel.so.1"; +#else +static const char pkcs11_kernel[] = "/usr/lib/security/pkcs11_kernel.so.1"; +#endif + +/* + * Check hardware capabilities of the machines. The output are two lists, + * hw_cnids and hw_dnids, that contain hardware mechanisms found in all hardware + * providers together. They are not sorted and may contain duplicate mechanisms. + */ +static int check_hw_mechanisms(void) + { + int i; + CK_RV rv; + void *handle; + CK_C_GetFunctionList p; + CK_TOKEN_INFO token_info; + CK_ULONG ulSlotCount = 0; + int n_cipher = 0, n_digest = 0; + CK_FUNCTION_LIST_PTR pflist = NULL; + CK_SLOT_ID_PTR pSlotList = NULL_PTR; + int *tmp_hw_cnids = NULL, *tmp_hw_dnids = NULL; + int hw_ctable_size, hw_dtable_size; + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: SOLARIS_HW_SLOT_SELECTION code running\n", + PK11_DBG); +#endif + if ((handle = dlopen(pkcs11_kernel, RTLD_LAZY)) == NULL) + { + PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_DSO_FAILURE); + goto err; + } + + if ((p = (CK_C_GetFunctionList)dlsym(handle, + PK11_GET_FUNCTION_LIST)) == NULL) + { + PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_DSO_FAILURE); + goto err; + } + + /* get the full function list from the loaded library */ + if (p(&pflist) != CKR_OK) + { + PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_DSO_FAILURE); + goto err; + } + + rv = pflist->C_Initialize((CK_VOID_PTR)&pk11_init_args); + if ((rv != CKR_OK) && (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)) + { + PK11err_add_data(PK11_F_CHECK_HW_MECHANISMS, + PK11_R_INITIALIZE, rv); + goto err; + } + + if (pflist->C_GetSlotList(0, NULL_PTR, &ulSlotCount) != CKR_OK) + { + PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_GETSLOTLIST); + goto err; + } + + /* no slots, set the hw mechanism tables as empty */ + if (ulSlotCount == 0) + { +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: no hardware mechanisms found\n", PK11_DBG); +#endif + hw_cnids = OPENSSL_malloc(sizeof (int)); + hw_dnids = OPENSSL_malloc(sizeof (int)); + if (hw_cnids == NULL || hw_dnids == NULL) + { + PK11err(PK11_F_CHECK_HW_MECHANISMS, + PK11_R_MALLOC_FAILURE); + return (0); + } + /* this means empty tables */ + hw_cnids[0] = NID_undef; + hw_dnids[0] = NID_undef; + return (1); + } + + pSlotList = OPENSSL_malloc(ulSlotCount * sizeof (CK_SLOT_ID)); + if (pSlotList == NULL) + { + PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_MALLOC_FAILURE); + goto err; + } + + /* Get the slot list for processing */ + if (pflist->C_GetSlotList(0, pSlotList, &ulSlotCount) != CKR_OK) + { + PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_GETSLOTLIST); + goto err; + } + + /* + * We don't care about duplicit mechanisms in multiple slots and also + * reserve one slot for the terminal NID_undef which we use to stop the + * search. + */ + hw_ctable_size = ulSlotCount * PK11_CIPHER_MAX + 1; + hw_dtable_size = ulSlotCount * PK11_DIGEST_MAX + 1; + tmp_hw_cnids = OPENSSL_malloc(hw_ctable_size * sizeof (int)); + tmp_hw_dnids = OPENSSL_malloc(hw_dtable_size * sizeof (int)); + if (tmp_hw_cnids == NULL || tmp_hw_dnids == NULL) + { + PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_MALLOC_FAILURE); + goto err; + } + + /* + * Do not use memset since we should not rely on the fact that NID_undef + * is zero now. + */ + for (i = 0; i < hw_ctable_size; ++i) + tmp_hw_cnids[i] = NID_undef; + for (i = 0; i < hw_dtable_size; ++i) + tmp_hw_dnids[i] = NID_undef; + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: provider: %s\n", PK11_DBG, pkcs11_kernel); + fprintf(stderr, "%s: found %d hardware slots\n", PK11_DBG, ulSlotCount); + fprintf(stderr, "%s: now looking for mechs supported in hw\n", + PK11_DBG); +#endif /* DEBUG_SLOT_SELECTION */ + + for (i = 0; i < ulSlotCount; i++) + { + if (pflist->C_GetTokenInfo(pSlotList[i], &token_info) != CKR_OK) + continue; + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: token label: %.32s\n", PK11_DBG, token_info.label); +#endif /* DEBUG_SLOT_SELECTION */ + + /* + * We are filling the hw mech tables here. Global tables are + * still NULL so all mechanisms are put into tmp tables. + */ + pk11_find_symmetric_ciphers(pflist, pSlotList[i], + &n_cipher, tmp_hw_cnids); + pk11_find_digests(pflist, pSlotList[i], + &n_digest, tmp_hw_dnids); + } + + /* + * Since we are part of a library (libcrypto.so), calling this function + * may have side-effects. Also, C_Finalize() is triggered by + * dlclose(3C). + */ +#if 0 + pflist->C_Finalize(NULL); +#endif + OPENSSL_free(pSlotList); + (void) dlclose(handle); + hw_cnids = tmp_hw_cnids; + hw_dnids = tmp_hw_dnids; + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: hw mechs check complete\n", PK11_DBG); +#endif /* DEBUG_SLOT_SELECTION */ + return (1); + +err: + if (pSlotList != NULL) + OPENSSL_free(pSlotList); + if (tmp_hw_cnids != NULL) + OPENSSL_free(tmp_hw_cnids); + if (tmp_hw_dnids != NULL) + OPENSSL_free(tmp_hw_dnids); + + return (0); + } + +/* + * Check presence of a NID in the table of NIDs. The table may be NULL (i.e., + * non-existent). + */ +static int nid_in_table(int nid, int *nid_table) + { + int i = 0; + + /* + * a special case. NULL means that we are initializing a new + * table. + */ + if (nid_table == NULL) + return (1); + + /* + * the table is never full, there is always at least one + * NID_undef. + */ + while (nid_table[i] != NID_undef) + { + if (nid_table[i++] == nid) + { +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, " (NID %d in hw table, idx %d)", nid, i); +#endif /* DEBUG_SLOT_SELECTION */ + return (1); + } + } + + return (0); + } +#endif /* SOLARIS_HW_SLOT_SELECTION */ + +#endif /* OPENSSL_NO_HW_PK11CA */ +#endif /* OPENSSL_NO_HW_PK11 */ +#endif /* OPENSSL_NO_HW */ Index: openssl/crypto/engine/hw_pk11_err.c diff -u /dev/null openssl/crypto/engine/hw_pk11_err.c:1.4.10.1 --- /dev/null Wed Dec 23 16:49:05 2015 +++ openssl/crypto/engine/hw_pk11_err.c Tue Jun 14 21:52:40 2011 @@ -0,0 +1,288 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* crypto/engine/hw_pk11_err.c */ +/* + * This product includes software developed by the OpenSSL Project for + * use in the OpenSSL Toolkit (http://www.openssl.org/). + * + * This project also referenced hw_pkcs11-0.9.7b.patch written by + * Afchine Madjlessi. + */ +/* + * ==================================================================== + * Copyright (c) 2000-2001 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include +#include +#include "hw_pk11_err.h" + +/* BEGIN ERROR CODES */ +#ifndef OPENSSL_NO_ERR +static ERR_STRING_DATA pk11_str_functs[]= +{ +{ ERR_PACK(0, PK11_F_INIT, 0), "PK11_INIT"}, +{ ERR_PACK(0, PK11_F_FINISH, 0), "PK11_FINISH"}, +{ ERR_PACK(0, PK11_F_DESTROY, 0), "PK11_DESTROY"}, +{ ERR_PACK(0, PK11_F_CTRL, 0), "PK11_CTRL"}, +{ ERR_PACK(0, PK11_F_RSA_INIT, 0), "PK11_RSA_INIT"}, +{ ERR_PACK(0, PK11_F_RSA_FINISH, 0), "PK11_RSA_FINISH"}, +{ ERR_PACK(0, PK11_F_GET_PUB_RSA_KEY, 0), "PK11_GET_PUB_RSA_KEY"}, +{ ERR_PACK(0, PK11_F_GET_PRIV_RSA_KEY, 0), "PK11_GET_PRIV_RSA_KEY"}, +{ ERR_PACK(0, PK11_F_RSA_GEN_KEY, 0), "PK11_RSA_GEN_KEY"}, +{ ERR_PACK(0, PK11_F_RSA_PUB_ENC, 0), "PK11_RSA_PUB_ENC"}, +{ ERR_PACK(0, PK11_F_RSA_PRIV_ENC, 0), "PK11_RSA_PRIV_ENC"}, +{ ERR_PACK(0, PK11_F_RSA_PUB_DEC, 0), "PK11_RSA_PUB_DEC"}, +{ ERR_PACK(0, PK11_F_RSA_PRIV_DEC, 0), "PK11_RSA_PRIV_DEC"}, +{ ERR_PACK(0, PK11_F_RSA_SIGN, 0), "PK11_RSA_SIGN"}, +{ ERR_PACK(0, PK11_F_RSA_VERIFY, 0), "PK11_RSA_VERIFY"}, +{ ERR_PACK(0, PK11_F_RAND_ADD, 0), "PK11_RAND_ADD"}, +{ ERR_PACK(0, PK11_F_RAND_BYTES, 0), "PK11_RAND_BYTES"}, +{ ERR_PACK(0, PK11_F_GET_SESSION, 0), "PK11_GET_SESSION"}, +{ ERR_PACK(0, PK11_F_FREE_SESSION, 0), "PK11_FREE_SESSION"}, +{ ERR_PACK(0, PK11_F_LOAD_PUBKEY, 0), "PK11_LOAD_PUBKEY"}, +{ ERR_PACK(0, PK11_F_LOAD_PRIVKEY, 0), "PK11_LOAD_PRIV_KEY"}, +{ ERR_PACK(0, PK11_F_RSA_PUB_ENC_LOW, 0), "PK11_RSA_PUB_ENC_LOW"}, +{ ERR_PACK(0, PK11_F_RSA_PRIV_ENC_LOW, 0), "PK11_RSA_PRIV_ENC_LOW"}, +{ ERR_PACK(0, PK11_F_RSA_PUB_DEC_LOW, 0), "PK11_RSA_PUB_DEC_LOW"}, +{ ERR_PACK(0, PK11_F_RSA_PRIV_DEC_LOW, 0), "PK11_RSA_PRIV_DEC_LOW"}, +{ ERR_PACK(0, PK11_F_DSA_SIGN, 0), "PK11_DSA_SIGN"}, +{ ERR_PACK(0, PK11_F_DSA_VERIFY, 0), "PK11_DSA_VERIFY"}, +{ ERR_PACK(0, PK11_F_DSA_INIT, 0), "PK11_DSA_INIT"}, +{ ERR_PACK(0, PK11_F_DSA_FINISH, 0), "PK11_DSA_FINISH"}, +{ ERR_PACK(0, PK11_F_GET_PUB_DSA_KEY, 0), "PK11_GET_PUB_DSA_KEY"}, +{ ERR_PACK(0, PK11_F_GET_PRIV_DSA_KEY, 0), "PK11_GET_PRIV_DSA_KEY"}, +{ ERR_PACK(0, PK11_F_DH_INIT, 0), "PK11_DH_INIT"}, +{ ERR_PACK(0, PK11_F_DH_FINISH, 0), "PK11_DH_FINISH"}, +{ ERR_PACK(0, PK11_F_MOD_EXP_DH, 0), "PK11_MOD_EXP_DH"}, +{ ERR_PACK(0, PK11_F_GET_DH_KEY, 0), "PK11_GET_DH_KEY"}, +{ ERR_PACK(0, PK11_F_FREE_ALL_SESSIONS, 0), "PK11_FREE_ALL_SESSIONS"}, +{ ERR_PACK(0, PK11_F_SETUP_SESSION, 0), "PK11_SETUP_SESSION"}, +{ ERR_PACK(0, PK11_F_DESTROY_OBJECT, 0), "PK11_DESTROY_OBJECT"}, +{ ERR_PACK(0, PK11_F_CIPHER_INIT, 0), "PK11_CIPHER_INIT"}, +{ ERR_PACK(0, PK11_F_CIPHER_DO_CIPHER, 0), "PK11_CIPHER_DO_CIPHER"}, +{ ERR_PACK(0, PK11_F_GET_CIPHER_KEY, 0), "PK11_GET_CIPHER_KEY"}, +{ ERR_PACK(0, PK11_F_DIGEST_INIT, 0), "PK11_DIGEST_INIT"}, +{ ERR_PACK(0, PK11_F_DIGEST_UPDATE, 0), "PK11_DIGEST_UPDATE"}, +{ ERR_PACK(0, PK11_F_DIGEST_FINAL, 0), "PK11_DIGEST_FINAL"}, +{ ERR_PACK(0, PK11_F_CHOOSE_SLOT, 0), "PK11_CHOOSE_SLOT"}, +{ ERR_PACK(0, PK11_F_CIPHER_FINAL, 0), "PK11_CIPHER_FINAL"}, +{ ERR_PACK(0, PK11_F_LIBRARY_INIT, 0), "PK11_LIBRARY_INIT"}, +{ ERR_PACK(0, PK11_F_LOAD, 0), "ENGINE_LOAD_PK11"}, +{ ERR_PACK(0, PK11_F_DH_GEN_KEY, 0), "PK11_DH_GEN_KEY"}, +{ ERR_PACK(0, PK11_F_DH_COMP_KEY, 0), "PK11_DH_COMP_KEY"}, +{ ERR_PACK(0, PK11_F_DIGEST_COPY, 0), "PK11_DIGEST_COPY"}, +{ ERR_PACK(0, PK11_F_CIPHER_CLEANUP, 0), "PK11_CIPHER_CLEANUP"}, +{ ERR_PACK(0, PK11_F_ACTIVE_ADD, 0), "PK11_ACTIVE_ADD"}, +{ ERR_PACK(0, PK11_F_ACTIVE_DELETE, 0), "PK11_ACTIVE_DELETE"}, +{ ERR_PACK(0, PK11_F_CHECK_HW_MECHANISMS, 0), "PK11_CHECK_HW_MECHANISMS"}, +{ ERR_PACK(0, PK11_F_INIT_SYMMETRIC, 0), "PK11_INIT_SYMMETRIC"}, +{ ERR_PACK(0, PK11_F_ADD_AES_CTR_NIDS, 0), "PK11_ADD_AES_CTR_NIDS"}, +{ ERR_PACK(0, PK11_F_INIT_ALL_LOCKS, 0), "PK11_INIT_ALL_LOCKS"}, +{ ERR_PACK(0, PK11_F_RETURN_SESSION, 0), "PK11_RETURN_SESSION"}, +{ ERR_PACK(0, PK11_F_GET_PIN, 0), "PK11_GET_PIN"}, +{ ERR_PACK(0, PK11_F_FIND_ONE_OBJECT, 0), "PK11_FIND_ONE_OBJECT"}, +{ ERR_PACK(0, PK11_F_CHECK_TOKEN_ATTRS, 0), "PK11_CHECK_TOKEN_ATTRS"}, +{ ERR_PACK(0, PK11_F_CACHE_PIN, 0), "PK11_CACHE_PIN"}, +{ ERR_PACK(0, PK11_F_MLOCK_PIN_IN_MEMORY, 0), "PK11_MLOCK_PIN_IN_MEMORY"}, +{ ERR_PACK(0, PK11_F_TOKEN_LOGIN, 0), "PK11_TOKEN_LOGIN"}, +{ ERR_PACK(0, PK11_F_TOKEN_RELOGIN, 0), "PK11_TOKEN_RELOGIN"}, +{ ERR_PACK(0, PK11_F_RUN_ASKPASS, 0), "PK11_F_RUN_ASKPASS"}, +{ 0, NULL} +}; + +static ERR_STRING_DATA pk11_str_reasons[]= +{ +{ PK11_R_ALREADY_LOADED, "PKCS#11 DSO already loaded"}, +{ PK11_R_DSO_FAILURE, "unable to load PKCS#11 DSO"}, +{ PK11_R_NOT_LOADED, "PKCS#11 DSO not loaded"}, +{ PK11_R_PASSED_NULL_PARAMETER, "null parameter passed"}, +{ PK11_R_COMMAND_NOT_IMPLEMENTED, "command not implemented"}, +{ PK11_R_INITIALIZE, "C_Initialize failed"}, +{ PK11_R_FINALIZE, "C_Finalize failed"}, +{ PK11_R_GETINFO, "C_GetInfo faile"}, +{ PK11_R_GETSLOTLIST, "C_GetSlotList failed"}, +{ PK11_R_NO_MODULUS_OR_NO_EXPONENT, "no modulus or no exponent"}, +{ PK11_R_ATTRIBUT_SENSITIVE_OR_INVALID, "attr sensitive or invalid"}, +{ PK11_R_GETATTRIBUTVALUE, "C_GetAttributeValue failed"}, +{ PK11_R_NO_MODULUS, "no modulus"}, +{ PK11_R_NO_EXPONENT, "no exponent"}, +{ PK11_R_FINDOBJECTSINIT, "C_FindObjectsInit failed"}, +{ PK11_R_FINDOBJECTS, "C_FindObjects failed"}, +{ PK11_R_FINDOBJECTSFINAL, "C_FindObjectsFinal failed"}, +{ PK11_R_CREATEOBJECT, "C_CreateObject failed"}, +{ PK11_R_DESTROYOBJECT, "C_DestroyObject failed"}, +{ PK11_R_OPENSESSION, "C_OpenSession failed"}, +{ PK11_R_CLOSESESSION, "C_CloseSession failed"}, +{ PK11_R_ENCRYPTINIT, "C_EncryptInit failed"}, +{ PK11_R_ENCRYPT, "C_Encrypt failed"}, +{ PK11_R_SIGNINIT, "C_SignInit failed"}, +{ PK11_R_SIGN, "C_Sign failed"}, +{ PK11_R_DECRYPTINIT, "C_DecryptInit failed"}, +{ PK11_R_DECRYPT, "C_Decrypt failed"}, +{ PK11_R_VERIFYINIT, "C_VerifyRecover failed"}, +{ PK11_R_VERIFY, "C_Verify failed"}, +{ PK11_R_VERIFYRECOVERINIT, "C_VerifyRecoverInit failed"}, +{ PK11_R_VERIFYRECOVER, "C_VerifyRecover failed"}, +{ PK11_R_GEN_KEY, "C_GenerateKeyPair failed"}, +{ PK11_R_SEEDRANDOM, "C_SeedRandom failed"}, +{ PK11_R_GENERATERANDOM, "C_GenerateRandom failed"}, +{ PK11_R_INVALID_MESSAGE_LENGTH, "invalid message length"}, +{ PK11_R_UNKNOWN_ALGORITHM_TYPE, "unknown algorithm type"}, +{ PK11_R_UNKNOWN_ASN1_OBJECT_ID, "unknown asn1 onject id"}, +{ PK11_R_UNKNOWN_PADDING_TYPE, "unknown padding type"}, +{ PK11_R_PADDING_CHECK_FAILED, "padding check failed"}, +{ PK11_R_DIGEST_TOO_BIG, "digest too big"}, +{ PK11_R_MALLOC_FAILURE, "malloc failure"}, +{ PK11_R_CTRL_COMMAND_NOT_IMPLEMENTED, "ctl command not implemented"}, +{ PK11_R_DATA_GREATER_THAN_MOD_LEN, "data is bigger than mod"}, +{ PK11_R_DATA_TOO_LARGE_FOR_MODULUS, "data is too larger for mod"}, +{ PK11_R_MISSING_KEY_COMPONENT, "a dsa component is missing"}, +{ PK11_R_INVALID_SIGNATURE_LENGTH, "invalid signature length"}, +{ PK11_R_INVALID_DSA_SIGNATURE_R, "missing r in dsa verify"}, +{ PK11_R_INVALID_DSA_SIGNATURE_S, "missing s in dsa verify"}, +{ PK11_R_INCONSISTENT_KEY, "inconsistent key type"}, +{ PK11_R_ENCRYPTUPDATE, "C_EncryptUpdate failed"}, +{ PK11_R_DECRYPTUPDATE, "C_DecryptUpdate failed"}, +{ PK11_R_DIGESTINIT, "C_DigestInit failed"}, +{ PK11_R_DIGESTUPDATE, "C_DigestUpdate failed"}, +{ PK11_R_DIGESTFINAL, "C_DigestFinal failed"}, +{ PK11_R_ENCRYPTFINAL, "C_EncryptFinal failed"}, +{ PK11_R_DECRYPTFINAL, "C_DecryptFinal failed"}, +{ PK11_R_NO_PRNG_SUPPORT, "Slot does not support PRNG"}, +{ PK11_R_GETTOKENINFO, "C_GetTokenInfo failed"}, +{ PK11_R_DERIVEKEY, "C_DeriveKey failed"}, +{ PK11_R_GET_OPERATION_STATE, "C_GetOperationState failed"}, +{ PK11_R_SET_OPERATION_STATE, "C_SetOperationState failed"}, +{ PK11_R_INVALID_HANDLE, "invalid PKCS#11 object handle"}, +{ PK11_R_KEY_OR_IV_LEN_PROBLEM, "IV or key length incorrect"}, +{ PK11_R_INVALID_OPERATION_TYPE, "invalid operation type"}, +{ PK11_R_ADD_NID_FAILED, "failed to add NID" }, +{ PK11_R_ATFORK_FAILED, "atfork() failed" }, +{ PK11_R_TOKEN_LOGIN_FAILED, "C_Login() failed on token" }, +{ PK11_R_MORE_THAN_ONE_OBJECT_FOUND, "more than one object found" }, +{ PK11_R_INVALID_PKCS11_URI, "pkcs11 URI provided is invalid" }, +{ PK11_R_COULD_NOT_READ_PIN, "could not read PIN from terminal" }, +{ PK11_R_PIN_NOT_READ_FROM_COMMAND, "PIN not read from external command" }, +{ PK11_R_COULD_NOT_OPEN_COMMAND, "could not popen() dialog command" }, +{ PK11_R_PIPE_FAILED, "pipe() failed" }, +{ PK11_R_BAD_PASSPHRASE_SPEC, "bad passphrasedialog specification" }, +{ PK11_R_TOKEN_NOT_INITIALIZED, "token not initialized" }, +{ PK11_R_TOKEN_PIN_NOT_SET, "token PIN required but not set" }, +{ PK11_R_TOKEN_PIN_NOT_PROVIDED, "token PIN required but not provided" }, +{ PK11_R_MISSING_OBJECT_LABEL, "missing mandatory 'object' keyword" }, +{ PK11_R_TOKEN_ATTRS_DO_NOT_MATCH, "token attrs provided do not match" }, +{ PK11_R_PRIV_KEY_NOT_FOUND, "private key not found in keystore" }, +{ PK11_R_NO_OBJECT_FOUND, "specified object not found" }, +{ PK11_R_PIN_CACHING_POLICY_INVALID, "PIN set but caching policy invalid" }, +{ PK11_R_SYSCONF_FAILED, "sysconf() failed" }, +{ PK11_R_MMAP_FAILED, "mmap() failed" }, +{ PK11_R_PRIV_PROC_LOCK_MEMORY_MISSING, "PROC_LOCK_MEMORY privilege missing" }, +{ PK11_R_MLOCK_FAILED, "mlock() failed" }, +{ PK11_R_FORK_FAILED, "fork() failed" }, +{ 0, NULL} +}; +#endif /* OPENSSL_NO_ERR */ + +static int pk11_lib_error_code = 0; +static int pk11_error_init = 1; + +static void +ERR_load_pk11_strings(void) + { + if (pk11_lib_error_code == 0) + pk11_lib_error_code = ERR_get_next_error_library(); + + if (pk11_error_init) + { + pk11_error_init = 0; +#ifndef OPENSSL_NO_ERR + ERR_load_strings(pk11_lib_error_code, pk11_str_functs); + ERR_load_strings(pk11_lib_error_code, pk11_str_reasons); +#endif + } +} + +static void +ERR_unload_pk11_strings(void) + { + if (pk11_error_init == 0) + { +#ifndef OPENSSL_NO_ERR + ERR_unload_strings(pk11_lib_error_code, pk11_str_functs); + ERR_unload_strings(pk11_lib_error_code, pk11_str_reasons); +#endif + pk11_error_init = 1; + } +} + +void +ERR_pk11_error(int function, int reason, char *file, int line) +{ + if (pk11_lib_error_code == 0) + pk11_lib_error_code = ERR_get_next_error_library(); + ERR_PUT_error(pk11_lib_error_code, function, reason, file, line); +} + +void +PK11err_add_data(int function, int reason, CK_RV rv) +{ + char tmp_buf[20]; + + PK11err(function, reason); + (void) BIO_snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); + ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); +} Index: openssl/crypto/engine/hw_pk11_err.h diff -u /dev/null openssl/crypto/engine/hw_pk11_err.h:1.9.10.2 --- /dev/null Wed Dec 23 16:49:05 2015 +++ openssl/crypto/engine/hw_pk11_err.h Fri Oct 4 14:45:25 2013 @@ -0,0 +1,440 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * This product includes software developed by the OpenSSL Project for + * use in the OpenSSL Toolkit (http://www.openssl.org/). + * + * This project also referenced hw_pkcs11-0.9.7b.patch written by + * Afchine Madjlessi. + */ +/* + * ==================================================================== + * Copyright (c) 2000-2001 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#ifndef HW_PK11_ERR_H +#define HW_PK11_ERR_H + +void ERR_pk11_error(int function, int reason, char *file, int line); +void PK11err_add_data(int function, int reason, CK_RV rv); +#define PK11err(f, r) ERR_pk11_error((f), (r), __FILE__, __LINE__) + +/* Error codes for the PK11 functions. */ + +/* Function codes. */ + +#define PK11_F_INIT 100 +#define PK11_F_FINISH 101 +#define PK11_F_DESTROY 102 +#define PK11_F_CTRL 103 +#define PK11_F_RSA_INIT 104 +#define PK11_F_RSA_FINISH 105 +#define PK11_F_GET_PUB_RSA_KEY 106 +#define PK11_F_GET_PRIV_RSA_KEY 107 +#define PK11_F_RSA_GEN_KEY 108 +#define PK11_F_RSA_PUB_ENC 109 +#define PK11_F_RSA_PRIV_ENC 110 +#define PK11_F_RSA_PUB_DEC 111 +#define PK11_F_RSA_PRIV_DEC 112 +#define PK11_F_RSA_SIGN 113 +#define PK11_F_RSA_VERIFY 114 +#define PK11_F_RAND_ADD 115 +#define PK11_F_RAND_BYTES 116 +#define PK11_F_GET_SESSION 117 +#define PK11_F_FREE_SESSION 118 +#define PK11_F_LOAD_PUBKEY 119 +#define PK11_F_LOAD_PRIVKEY 120 +#define PK11_F_RSA_PUB_ENC_LOW 121 +#define PK11_F_RSA_PRIV_ENC_LOW 122 +#define PK11_F_RSA_PUB_DEC_LOW 123 +#define PK11_F_RSA_PRIV_DEC_LOW 124 +#define PK11_F_DSA_SIGN 125 +#define PK11_F_DSA_VERIFY 126 +#define PK11_F_DSA_INIT 127 +#define PK11_F_DSA_FINISH 128 +#define PK11_F_GET_PUB_DSA_KEY 129 +#define PK11_F_GET_PRIV_DSA_KEY 130 +#define PK11_F_DH_INIT 131 +#define PK11_F_DH_FINISH 132 +#define PK11_F_MOD_EXP_DH 133 +#define PK11_F_GET_DH_KEY 134 +#define PK11_F_FREE_ALL_SESSIONS 135 +#define PK11_F_SETUP_SESSION 136 +#define PK11_F_DESTROY_OBJECT 137 +#define PK11_F_CIPHER_INIT 138 +#define PK11_F_CIPHER_DO_CIPHER 139 +#define PK11_F_GET_CIPHER_KEY 140 +#define PK11_F_DIGEST_INIT 141 +#define PK11_F_DIGEST_UPDATE 142 +#define PK11_F_DIGEST_FINAL 143 +#define PK11_F_CHOOSE_SLOT 144 +#define PK11_F_CIPHER_FINAL 145 +#define PK11_F_LIBRARY_INIT 146 +#define PK11_F_LOAD 147 +#define PK11_F_DH_GEN_KEY 148 +#define PK11_F_DH_COMP_KEY 149 +#define PK11_F_DIGEST_COPY 150 +#define PK11_F_CIPHER_CLEANUP 151 +#define PK11_F_ACTIVE_ADD 152 +#define PK11_F_ACTIVE_DELETE 153 +#define PK11_F_CHECK_HW_MECHANISMS 154 +#define PK11_F_INIT_SYMMETRIC 155 +#define PK11_F_ADD_AES_CTR_NIDS 156 +#define PK11_F_INIT_ALL_LOCKS 157 +#define PK11_F_RETURN_SESSION 158 +#define PK11_F_GET_PIN 159 +#define PK11_F_FIND_ONE_OBJECT 160 +#define PK11_F_CHECK_TOKEN_ATTRS 161 +#define PK11_F_CACHE_PIN 162 +#define PK11_F_MLOCK_PIN_IN_MEMORY 163 +#define PK11_F_TOKEN_LOGIN 164 +#define PK11_F_TOKEN_RELOGIN 165 +#define PK11_F_RUN_ASKPASS 166 + +/* Reason codes. */ +#define PK11_R_ALREADY_LOADED 100 +#define PK11_R_DSO_FAILURE 101 +#define PK11_R_NOT_LOADED 102 +#define PK11_R_PASSED_NULL_PARAMETER 103 +#define PK11_R_COMMAND_NOT_IMPLEMENTED 104 +#define PK11_R_INITIALIZE 105 +#define PK11_R_FINALIZE 106 +#define PK11_R_GETINFO 107 +#define PK11_R_GETSLOTLIST 108 +#define PK11_R_NO_MODULUS_OR_NO_EXPONENT 109 +#define PK11_R_ATTRIBUT_SENSITIVE_OR_INVALID 110 +#define PK11_R_GETATTRIBUTVALUE 111 +#define PK11_R_NO_MODULUS 112 +#define PK11_R_NO_EXPONENT 113 +#define PK11_R_FINDOBJECTSINIT 114 +#define PK11_R_FINDOBJECTS 115 +#define PK11_R_FINDOBJECTSFINAL 116 +#define PK11_R_CREATEOBJECT 118 +#define PK11_R_DESTROYOBJECT 119 +#define PK11_R_OPENSESSION 120 +#define PK11_R_CLOSESESSION 121 +#define PK11_R_ENCRYPTINIT 122 +#define PK11_R_ENCRYPT 123 +#define PK11_R_SIGNINIT 124 +#define PK11_R_SIGN 125 +#define PK11_R_DECRYPTINIT 126 +#define PK11_R_DECRYPT 127 +#define PK11_R_VERIFYINIT 128 +#define PK11_R_VERIFY 129 +#define PK11_R_VERIFYRECOVERINIT 130 +#define PK11_R_VERIFYRECOVER 131 +#define PK11_R_GEN_KEY 132 +#define PK11_R_SEEDRANDOM 133 +#define PK11_R_GENERATERANDOM 134 +#define PK11_R_INVALID_MESSAGE_LENGTH 135 +#define PK11_R_UNKNOWN_ALGORITHM_TYPE 136 +#define PK11_R_UNKNOWN_ASN1_OBJECT_ID 137 +#define PK11_R_UNKNOWN_PADDING_TYPE 138 +#define PK11_R_PADDING_CHECK_FAILED 139 +#define PK11_R_DIGEST_TOO_BIG 140 +#define PK11_R_MALLOC_FAILURE 141 +#define PK11_R_CTRL_COMMAND_NOT_IMPLEMENTED 142 +#define PK11_R_DATA_GREATER_THAN_MOD_LEN 143 +#define PK11_R_DATA_TOO_LARGE_FOR_MODULUS 144 +#define PK11_R_MISSING_KEY_COMPONENT 145 +#define PK11_R_INVALID_SIGNATURE_LENGTH 146 +#define PK11_R_INVALID_DSA_SIGNATURE_R 147 +#define PK11_R_INVALID_DSA_SIGNATURE_S 148 +#define PK11_R_INCONSISTENT_KEY 149 +#define PK11_R_ENCRYPTUPDATE 150 +#define PK11_R_DECRYPTUPDATE 151 +#define PK11_R_DIGESTINIT 152 +#define PK11_R_DIGESTUPDATE 153 +#define PK11_R_DIGESTFINAL 154 +#define PK11_R_ENCRYPTFINAL 155 +#define PK11_R_DECRYPTFINAL 156 +#define PK11_R_NO_PRNG_SUPPORT 157 +#define PK11_R_GETTOKENINFO 158 +#define PK11_R_DERIVEKEY 159 +#define PK11_R_GET_OPERATION_STATE 160 +#define PK11_R_SET_OPERATION_STATE 161 +#define PK11_R_INVALID_HANDLE 162 +#define PK11_R_KEY_OR_IV_LEN_PROBLEM 163 +#define PK11_R_INVALID_OPERATION_TYPE 164 +#define PK11_R_ADD_NID_FAILED 165 +#define PK11_R_ATFORK_FAILED 166 + +#define PK11_R_TOKEN_LOGIN_FAILED 167 +#define PK11_R_MORE_THAN_ONE_OBJECT_FOUND 168 +#define PK11_R_INVALID_PKCS11_URI 169 +#define PK11_R_COULD_NOT_READ_PIN 170 +#define PK11_R_COULD_NOT_OPEN_COMMAND 171 +#define PK11_R_PIPE_FAILED 172 +#define PK11_R_PIN_NOT_READ_FROM_COMMAND 173 +#define PK11_R_BAD_PASSPHRASE_SPEC 174 +#define PK11_R_TOKEN_NOT_INITIALIZED 175 +#define PK11_R_TOKEN_PIN_NOT_SET 176 +#define PK11_R_TOKEN_PIN_NOT_PROVIDED 177 +#define PK11_R_MISSING_OBJECT_LABEL 178 +#define PK11_R_TOKEN_ATTRS_DO_NOT_MATCH 179 +#define PK11_R_PRIV_KEY_NOT_FOUND 180 +#define PK11_R_NO_OBJECT_FOUND 181 +#define PK11_R_PIN_CACHING_POLICY_INVALID 182 +#define PK11_R_SYSCONF_FAILED 183 +#define PK11_R_MMAP_FAILED 183 +#define PK11_R_PRIV_PROC_LOCK_MEMORY_MISSING 184 +#define PK11_R_MLOCK_FAILED 185 +#define PK11_R_FORK_FAILED 186 + +/* max byte length of a symetric key we support */ +#define PK11_KEY_LEN_MAX 32 + +#ifdef NOPTHREADS +/* + * CRYPTO_LOCK_PK11_ENGINE lock is primarily used for the protection of the + * free_session list and active_list but generally serves as a global + * per-process lock for the whole engine. + * + * We reuse CRYPTO_LOCK_EC lock (which is defined in OpenSSL for EC method) as + * the global engine lock. This is not optimal w.r.t. performance but + * it's safe. + */ +#define CRYPTO_LOCK_PK11_ENGINE CRYPTO_LOCK_EC +#endif + +/* + * This structure encapsulates all reusable information for a PKCS#11 + * session. A list of these objects is created on behalf of the + * calling application using an on-demand method. Each operation + * type (see PK11_OPTYPE below) has its own per-process list. + * Each of the lists is basically a cache for faster PKCS#11 object + * access to avoid expensive C_Find{,Init,Final}Object() calls. + * + * When a new request comes in, an object will be taken from the list + * (if there is one) or a new one is created to handle the request + * (if the list is empty). See pk11_get_session() on how it is done. + */ +typedef struct PK11_st_SESSION + { + struct PK11_st_SESSION *next; + CK_SESSION_HANDLE session; /* PK11 session handle */ + pid_t pid; /* Current process ID */ + CK_BBOOL pub_persistent; /* is pub key in keystore? */ + CK_BBOOL priv_persistent;/* is priv key in keystore? */ + union + { +#ifndef OPENSSL_NO_RSA + struct + { + CK_OBJECT_HANDLE rsa_pub_key; /* pub handle */ + CK_OBJECT_HANDLE rsa_priv_key; /* priv handle */ + RSA *rsa_pub; /* pub key addr */ + BIGNUM *rsa_n_num; /* pub modulus */ + BIGNUM *rsa_e_num; /* pub exponent */ + RSA *rsa_priv; /* priv key addr */ + BIGNUM *rsa_pn_num; /* pub modulus */ + BIGNUM *rsa_pe_num; /* pub exponent */ + BIGNUM *rsa_d_num; /* priv exponent */ + } u_RSA; +#endif /* OPENSSL_NO_RSA */ +#ifndef OPENSSL_NO_DSA + struct + { + CK_OBJECT_HANDLE dsa_pub_key; /* pub handle */ + CK_OBJECT_HANDLE dsa_priv_key; /* priv handle */ + DSA *dsa_pub; /* pub key addr */ + BIGNUM *dsa_pub_num; /* pub key */ + DSA *dsa_priv; /* priv key addr */ + BIGNUM *dsa_priv_num; /* priv key */ + } u_DSA; +#endif /* OPENSSL_NO_DSA */ +#ifndef OPENSSL_NO_DH + struct + { + CK_OBJECT_HANDLE dh_key; /* key handle */ + DH *dh; /* dh key addr */ + BIGNUM *dh_priv_num; /* priv dh key */ + } u_DH; +#endif /* OPENSSL_NO_DH */ + struct + { + CK_OBJECT_HANDLE cipher_key; /* key handle */ + unsigned char key[PK11_KEY_LEN_MAX]; + int key_len; /* priv key len */ + int encrypt; /* 1/0 enc/decr */ + } u_cipher; + } opdata_u; + } PK11_SESSION; + +#define opdata_rsa_pub_key opdata_u.u_RSA.rsa_pub_key +#define opdata_rsa_priv_key opdata_u.u_RSA.rsa_priv_key +#define opdata_rsa_pub opdata_u.u_RSA.rsa_pub +#define opdata_rsa_priv opdata_u.u_RSA.rsa_priv +#define opdata_rsa_n_num opdata_u.u_RSA.rsa_n_num +#define opdata_rsa_e_num opdata_u.u_RSA.rsa_e_num +#define opdata_rsa_pn_num opdata_u.u_RSA.rsa_pn_num +#define opdata_rsa_pe_num opdata_u.u_RSA.rsa_pe_num +#define opdata_rsa_d_num opdata_u.u_RSA.rsa_d_num +#define opdata_dsa_pub_key opdata_u.u_DSA.dsa_pub_key +#define opdata_dsa_priv_key opdata_u.u_DSA.dsa_priv_key +#define opdata_dsa_pub opdata_u.u_DSA.dsa_pub +#define opdata_dsa_pub_num opdata_u.u_DSA.dsa_pub_num +#define opdata_dsa_priv opdata_u.u_DSA.dsa_priv +#define opdata_dsa_priv_num opdata_u.u_DSA.dsa_priv_num +#define opdata_dh_key opdata_u.u_DH.dh_key +#define opdata_dh opdata_u.u_DH.dh +#define opdata_dh_priv_num opdata_u.u_DH.dh_priv_num +#define opdata_cipher_key opdata_u.u_cipher.cipher_key +#define opdata_key opdata_u.u_cipher.key +#define opdata_key_len opdata_u.u_cipher.key_len +#define opdata_encrypt opdata_u.u_cipher.encrypt + +/* + * We have 3 different groups of operation types: + * 1) asymmetric operations + * 2) random operations + * 3) symmetric and digest operations + * + * This division into groups stems from the fact that it's common that hardware + * providers may support operations from one group only. For example, hardware + * providers on UltraSPARC T2, n2rng(7d), ncp(7d), and n2cp(7d), each support + * only a single group of operations. + * + * For every group a different slot can be chosen. That means that we must have + * at least 3 different lists of cached PKCS#11 sessions since sessions from + * different groups may be initialized in different slots. + * + * To provide locking granularity in multithreaded environment, the groups are + * further splitted into types with each type having a separate session cache. + */ +typedef enum PK11_OPTYPE_ENUM + { + OP_RAND, + OP_RSA, + OP_DSA, + OP_DH, + OP_CIPHER, + OP_DIGEST, + OP_MAX + } PK11_OPTYPE; + +/* + * This structure contains the heads of the lists forming the object caches + * and locks associated with the lists. + */ +typedef struct PK11_st_CACHE + { + PK11_SESSION *head; +#ifndef NOPTHREADS + pthread_mutex_t *lock; +#endif + } PK11_CACHE; + +/* structure for tracking handles of asymmetric key objects */ +typedef struct PK11_active_st + { + CK_OBJECT_HANDLE h; + unsigned int refcnt; + struct PK11_active_st *prev; + struct PK11_active_st *next; + } PK11_active; + +#ifndef NOPTHREADS +extern pthread_mutex_t *find_lock[]; +#endif +extern PK11_active *active_list[]; +/* + * These variables are specific for the RSA keys by reference code. See + * hw_pk11_pub.c for explanation. + */ +extern CK_FLAGS pubkey_token_flags; + +#ifndef NOPTHREADS +#define LOCK_OBJSTORE(alg_type) \ + OPENSSL_assert(pthread_mutex_lock(find_lock[alg_type]) == 0) +#define UNLOCK_OBJSTORE(alg_type) \ + OPENSSL_assert(pthread_mutex_unlock(find_lock[alg_type]) == 0) +#else +#define LOCK_OBJSTORE(alg_type) \ + CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE) +#define UNLOCK_OBJSTORE(alg_type) \ + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE) +#endif + +extern PK11_SESSION *pk11_get_session(PK11_OPTYPE optype); +extern void pk11_return_session(PK11_SESSION *sp, PK11_OPTYPE optype); +extern int pk11_token_relogin(CK_SESSION_HANDLE session); + +#ifndef OPENSSL_NO_RSA +extern int pk11_destroy_rsa_key_objects(PK11_SESSION *session); +extern int pk11_destroy_rsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock); +extern int pk11_destroy_rsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock); +extern EVP_PKEY *pk11_load_privkey(ENGINE *e, const char *pubkey_file, + UI_METHOD *ui_method, void *callback_data); +extern EVP_PKEY *pk11_load_pubkey(ENGINE *e, const char *pubkey_file, + UI_METHOD *ui_method, void *callback_data); +extern RSA_METHOD *PK11_RSA(void); +#endif /* OPENSSL_NO_RSA */ +#ifndef OPENSSL_NO_DSA +extern int pk11_destroy_dsa_key_objects(PK11_SESSION *session); +extern int pk11_destroy_dsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock); +extern int pk11_destroy_dsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock); +extern DSA_METHOD *PK11_DSA(void); +#endif /* OPENSSL_NO_DSA */ +#ifndef OPENSSL_NO_DH +extern int pk11_destroy_dh_key_objects(PK11_SESSION *session); +extern int pk11_destroy_dh_object(PK11_SESSION *sp, CK_BBOOL uselock); +extern DH_METHOD *PK11_DH(void); +#endif /* OPENSSL_NO_DH */ + +extern CK_FUNCTION_LIST_PTR pFuncList; + +#endif /* HW_PK11_ERR_H */ Index: openssl/crypto/engine/hw_pk11_pub.c diff -u /dev/null openssl/crypto/engine/hw_pk11_pub.c:1.32.4.7 --- /dev/null Wed Dec 23 16:49:06 2015 +++ openssl/crypto/engine/hw_pk11_pub.c Fri Oct 4 14:45:25 2013 @@ -0,0 +1,3556 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* crypto/engine/hw_pk11_pub.c */ +/* + * This product includes software developed by the OpenSSL Project for + * use in the OpenSSL Toolkit (http://www.openssl.org/). + * + * This project also referenced hw_pkcs11-0.9.7b.patch written by + * Afchine Madjlessi. + */ +/* + * ==================================================================== + * Copyright (c) 2000-2001 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#ifndef OPENSSL_NO_RSA +#include +#endif /* OPENSSL_NO_RSA */ +#ifndef OPENSSL_NO_DSA +#include +#endif /* OPENSSL_NO_DSA */ +#ifndef OPENSSL_NO_DH +#include +#endif /* OPENSSL_NO_DH */ +#include +#include +#include + +#ifdef OPENSSL_SYS_WIN32 +#define NOPTHREADS +typedef int pid_t; +#define HAVE_GETPASSPHRASE +static char *getpassphrase(const char *prompt); +#ifndef NULL_PTR +#define NULL_PTR NULL +#endif +#define CK_DEFINE_FUNCTION(returnType, name) \ + returnType __declspec(dllexport) name +#define CK_DECLARE_FUNCTION(returnType, name) \ + returnType __declspec(dllimport) name +#define CK_DECLARE_FUNCTION_POINTER(returnType, name) \ + returnType __declspec(dllimport) (* name) +#else +#include +#endif + +#ifndef NOPTHREADS +#include +#endif + +#ifndef OPENSSL_NO_HW +#ifndef OPENSSL_NO_HW_PK11 +#ifndef OPENSSL_NO_HW_PK11CA + +#ifdef OPENSSL_SYS_WIN32 +#pragma pack(push, cryptoki, 1) +#include "cryptoki.h" +#include "pkcs11.h" +#pragma pack(pop, cryptoki) +#else +#include "cryptoki.h" +#include "pkcs11.h" +#endif +#include "hw_pk11ca.h" +#include "hw_pk11_err.h" + +static CK_BBOOL pk11_login_done = CK_FALSE; +extern CK_SLOT_ID pubkey_SLOTID; +#ifndef NOPTHREADS +extern pthread_mutex_t *token_lock; +#endif + +#if !(defined(HAVE_GETPASSPHRASE) || (defined (__SVR4) && defined (__sun))) +#define getpassphrase(x) getpass(x) +#endif + +#ifndef OPENSSL_NO_RSA +/* RSA stuff */ +static int pk11_RSA_public_encrypt(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding); +static int pk11_RSA_private_encrypt(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding); +static int pk11_RSA_public_decrypt(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding); +static int pk11_RSA_private_decrypt(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding); +static int pk11_RSA_init(RSA *rsa); +static int pk11_RSA_finish(RSA *rsa); +static int pk11_RSA_sign(int type, const unsigned char *m, unsigned int m_len, + unsigned char *sigret, unsigned int *siglen, const RSA *rsa); +#if OPENSSL_VERSION_NUMBER < 0x10000000L +static int pk11_RSA_verify(int dtype, const unsigned char *m, + unsigned int m_len, unsigned char *sigbuf, unsigned int siglen, + const RSA *rsa); +#else +static int pk11_RSA_verify(int dtype, const unsigned char *m, + unsigned int m_len, const unsigned char *sigbuf, unsigned int siglen, + const RSA *rsa); +#endif +EVP_PKEY *pk11_load_privkey(ENGINE*, const char *privkey_file, + UI_METHOD *ui_method, void *callback_data); +EVP_PKEY *pk11_load_pubkey(ENGINE*, const char *pubkey_file, + UI_METHOD *ui_method, void *callback_data); + +static int pk11_RSA_public_encrypt_low(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa); +static int pk11_RSA_private_encrypt_low(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa); +static int pk11_RSA_public_decrypt_low(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa); +static int pk11_RSA_private_decrypt_low(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa); + +static CK_OBJECT_HANDLE pk11_get_public_rsa_key(RSA* rsa, RSA** key_ptr, + BIGNUM **rsa_n_num, BIGNUM **rsa_e_num, CK_SESSION_HANDLE session); +static CK_OBJECT_HANDLE pk11_get_private_rsa_key(RSA* rsa, RSA** key_ptr, + BIGNUM **rsa_d_num, BIGNUM **rsa_n_num, BIGNUM **rsa_e_num, + CK_SESSION_HANDLE session); + +static int check_new_rsa_key_pub(PK11_SESSION *sp, const RSA *rsa); +static int check_new_rsa_key_priv(PK11_SESSION *sp, const RSA *rsa); +#endif + +/* DSA stuff */ +#ifndef OPENSSL_NO_DSA +static int pk11_DSA_init(DSA *dsa); +static int pk11_DSA_finish(DSA *dsa); +static DSA_SIG *pk11_dsa_do_sign(const unsigned char *dgst, int dlen, + DSA *dsa); +static int pk11_dsa_do_verify(const unsigned char *dgst, int dgst_len, + DSA_SIG *sig, DSA *dsa); + +static CK_OBJECT_HANDLE pk11_get_public_dsa_key(DSA* dsa, DSA **key_ptr, + BIGNUM **dsa_pub_num, CK_SESSION_HANDLE session); +static CK_OBJECT_HANDLE pk11_get_private_dsa_key(DSA* dsa, DSA **key_ptr, + BIGNUM **dsa_priv_num, CK_SESSION_HANDLE session); + +static int check_new_dsa_key_pub(PK11_SESSION *sp, DSA *dsa); +static int check_new_dsa_key_priv(PK11_SESSION *sp, DSA *dsa); +#endif + +/* DH stuff */ +#ifndef OPENSSL_NO_DH +static int pk11_DH_init(DH *dh); +static int pk11_DH_finish(DH *dh); +static int pk11_DH_generate_key(DH *dh); +static int pk11_DH_compute_key(unsigned char *key, + const BIGNUM *pub_key, DH *dh); + +static CK_OBJECT_HANDLE pk11_get_dh_key(DH* dh, DH **key_ptr, + BIGNUM **priv_key, CK_SESSION_HANDLE session); + +static int check_new_dh_key(PK11_SESSION *sp, DH *dh); +#endif + +static int find_one_object(PK11_OPTYPE op, CK_SESSION_HANDLE s, + CK_ATTRIBUTE_PTR ptempl, CK_ULONG nattr, CK_OBJECT_HANDLE_PTR pkey); +static int init_template_value(BIGNUM *bn, CK_VOID_PTR *pValue, + CK_ULONG *ulValueLen); +static void attr_to_BN(CK_ATTRIBUTE_PTR attr, CK_BYTE attr_data[], BIGNUM **bn); + +static int pk11_token_login(CK_SESSION_HANDLE session, CK_BBOOL *login_done, + CK_BBOOL is_private); + +/* Read mode string to be used for fopen() */ +#if SOLARIS_OPENSSL +static char *read_mode_flags = "rF"; +#else +static char *read_mode_flags = "r"; +#endif + +/* + * increment/create reference for an asymmetric key handle via active list + * manipulation. If active list operation fails, unlock (if locked), set error + * variable and jump to the specified label. + */ +#define KEY_HANDLE_REFHOLD(key_handle, alg_type, unlock, var, label) \ + { \ + if (pk11_active_add(key_handle, alg_type) < 0) \ + { \ + var = TRUE; \ + if (unlock) \ + UNLOCK_OBJSTORE(alg_type); \ + goto label; \ + } \ + } + +/* + * Find active list entry according to object handle and return pointer to the + * entry otherwise return NULL. + * + * This function presumes it is called with lock protecting the active list + * held. + */ +static PK11_active *pk11_active_find(CK_OBJECT_HANDLE h, PK11_OPTYPE type) + { + PK11_active *entry; + + for (entry = active_list[type]; entry != NULL; entry = entry->next) + if (entry->h == h) + return (entry); + + return (NULL); + } + +/* + * Search for an entry in the active list using PKCS#11 object handle as a + * search key and return refcnt of the found/created entry or -1 in case of + * failure. + * + * This function presumes it is called with lock protecting the active list + * held. + */ +int +pk11_active_add(CK_OBJECT_HANDLE h, PK11_OPTYPE type) + { + PK11_active *entry = NULL; + + if (h == CK_INVALID_HANDLE) + { + PK11err(PK11_F_ACTIVE_ADD, PK11_R_INVALID_HANDLE); + return (-1); + } + + /* search for entry in the active list */ + if ((entry = pk11_active_find(h, type)) != NULL) + entry->refcnt++; + else + { + /* not found, create new entry and add it to the list */ + entry = OPENSSL_malloc(sizeof (PK11_active)); + if (entry == NULL) + { + PK11err(PK11_F_ACTIVE_ADD, PK11_R_MALLOC_FAILURE); + return (-1); + } + entry->h = h; + entry->refcnt = 1; + entry->prev = NULL; + entry->next = NULL; + /* connect the newly created entry to the list */ + if (active_list[type] == NULL) + active_list[type] = entry; + else /* make the entry first in the list */ + { + entry->next = active_list[type]; + active_list[type]->prev = entry; + active_list[type] = entry; + } + } + + return (entry->refcnt); + } + +/* + * Remove active list entry from the list and free it. + * + * This function presumes it is called with lock protecting the active list + * held. + */ +void +pk11_active_remove(PK11_active *entry, PK11_OPTYPE type) + { + PK11_active *prev_entry; + + /* remove the entry from the list and free it */ + if ((prev_entry = entry->prev) != NULL) + { + prev_entry->next = entry->next; + if (entry->next != NULL) + entry->next->prev = prev_entry; + } + else + { + active_list[type] = entry->next; + /* we were the first but not the only one */ + if (entry->next != NULL) + entry->next->prev = NULL; + } + + /* sanitization */ + entry->h = CK_INVALID_HANDLE; + entry->prev = NULL; + entry->next = NULL; + OPENSSL_free(entry); + } + +/* Free all entries from the active list. */ +void +pk11_free_active_list(PK11_OPTYPE type) + { + PK11_active *entry; + + /* only for asymmetric types since only they have C_Find* locks. */ + switch (type) + { + case OP_RSA: + case OP_DSA: + case OP_DH: + break; + default: + return; + } + + /* see find_lock array definition for more info on object locking */ + LOCK_OBJSTORE(type); + while ((entry = active_list[type]) != NULL) + pk11_active_remove(entry, type); + UNLOCK_OBJSTORE(type); + } + +/* + * Search for active list entry associated with given PKCS#11 object handle, + * decrement its refcnt and if it drops to 0, disconnect the entry and free it. + * + * Return 1 if the PKCS#11 object associated with the entry has no references, + * return 0 if there is at least one reference, -1 on error. + * + * This function presumes it is called with lock protecting the active list + * held. + */ +int +pk11_active_delete(CK_OBJECT_HANDLE h, PK11_OPTYPE type) + { + PK11_active *entry = NULL; + + if ((entry = pk11_active_find(h, type)) == NULL) + { + PK11err(PK11_F_ACTIVE_DELETE, PK11_R_INVALID_HANDLE); + return (-1); + } + + OPENSSL_assert(entry->refcnt > 0); + entry->refcnt--; + if (entry->refcnt == 0) + { + pk11_active_remove(entry, type); + return (1); + } + + return (0); + } + +#ifndef OPENSSL_NO_RSA +/* Our internal RSA_METHOD that we provide pointers to */ +static RSA_METHOD pk11_rsa = + { + "PKCS#11 RSA method", + pk11_RSA_public_encrypt, /* rsa_pub_encrypt */ + pk11_RSA_public_decrypt, /* rsa_pub_decrypt */ + pk11_RSA_private_encrypt, /* rsa_priv_encrypt */ + pk11_RSA_private_decrypt, /* rsa_priv_decrypt */ + NULL, /* rsa_mod_exp */ + NULL, /* bn_mod_exp */ + pk11_RSA_init, /* init */ + pk11_RSA_finish, /* finish */ + RSA_FLAG_SIGN_VER, /* flags */ + NULL, /* app_data */ + pk11_RSA_sign, /* rsa_sign */ + pk11_RSA_verify /* rsa_verify */ + }; + +RSA_METHOD * +PK11_RSA(void) + { + return (&pk11_rsa); + } +#endif + +#ifndef OPENSSL_NO_DSA +/* Our internal DSA_METHOD that we provide pointers to */ +static DSA_METHOD pk11_dsa = + { + "PKCS#11 DSA method", + pk11_dsa_do_sign, /* dsa_do_sign */ + NULL, /* dsa_sign_setup */ + pk11_dsa_do_verify, /* dsa_do_verify */ + NULL, /* dsa_mod_exp */ + NULL, /* bn_mod_exp */ + pk11_DSA_init, /* init */ + pk11_DSA_finish, /* finish */ + 0, /* flags */ + NULL /* app_data */ + }; + +DSA_METHOD * +PK11_DSA(void) + { + return (&pk11_dsa); + } +#endif + +#ifndef OPENSSL_NO_DH +/* + * PKCS #11 V2.20, section 11.2 specifies that the number of bytes needed for + * output buffer may somewhat exceed the precise number of bytes needed, but + * should not exceed it by a large amount. That may be caused, for example, by + * rounding it up to multiple of X in the underlying bignum library. 8 should be + * enough. + */ +#define DH_BUF_RESERVE 8 + +/* Our internal DH_METHOD that we provide pointers to */ +static DH_METHOD pk11_dh = + { + "PKCS#11 DH method", + pk11_DH_generate_key, /* generate_key */ + pk11_DH_compute_key, /* compute_key */ + NULL, /* bn_mod_exp */ + pk11_DH_init, /* init */ + pk11_DH_finish, /* finish */ + 0, /* flags */ + NULL, /* app_data */ + NULL /* generate_params */ + }; + +DH_METHOD * +PK11_DH(void) + { + return (&pk11_dh); + } +#endif + +/* Size of an SSL signature: MD5+SHA1 */ +#define SSL_SIG_LENGTH 36 + +/* Lengths of DSA data and signature */ +#define DSA_DATA_LEN 20 +#define DSA_SIGNATURE_LEN 40 + +static CK_BBOOL mytrue = TRUE; +static CK_BBOOL myfalse = FALSE; + +#ifndef OPENSSL_NO_RSA +/* + * Similiar to OpenSSL to take advantage of the paddings. The goal is to + * support all paddings in this engine although PK11 library does not + * support all the paddings used in OpenSSL. + * The input errors should have been checked in the padding functions. + */ +static int pk11_RSA_public_encrypt(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding) + { + int i, num = 0, r = -1; + unsigned char *buf = NULL; + + num = BN_num_bytes(rsa->n); + if ((buf = (unsigned char *)OPENSSL_malloc(num)) == NULL) + { + RSAerr(PK11_F_RSA_PUB_ENC, PK11_R_MALLOC_FAILURE); + goto err; + } + + switch (padding) + { + case RSA_PKCS1_PADDING: + i = RSA_padding_add_PKCS1_type_2(buf, num, from, flen); + break; +#ifndef OPENSSL_NO_SHA + case RSA_PKCS1_OAEP_PADDING: + i = RSA_padding_add_PKCS1_OAEP(buf, num, from, flen, NULL, 0); + break; +#endif + case RSA_SSLV23_PADDING: + i = RSA_padding_add_SSLv23(buf, num, from, flen); + break; + case RSA_NO_PADDING: + i = RSA_padding_add_none(buf, num, from, flen); + break; + default: + RSAerr(PK11_F_RSA_PUB_ENC, PK11_R_UNKNOWN_PADDING_TYPE); + goto err; + } + if (i <= 0) goto err; + + /* PK11 functions are called here */ + r = pk11_RSA_public_encrypt_low(num, buf, to, rsa); +err: + if (buf != NULL) + { + OPENSSL_cleanse(buf, num); + OPENSSL_free(buf); + } + return (r); + } + + +/* + * Similar to Openssl to take advantage of the paddings. The input errors + * should be catched in the padding functions + */ +static int pk11_RSA_private_encrypt(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding) + { + int i, num = 0, r = -1; + unsigned char *buf = NULL; + + num = BN_num_bytes(rsa->n); + if ((buf = (unsigned char *)OPENSSL_malloc(num)) == NULL) + { + RSAerr(PK11_F_RSA_PRIV_ENC, PK11_R_MALLOC_FAILURE); + goto err; + } + + switch (padding) + { + case RSA_PKCS1_PADDING: + i = RSA_padding_add_PKCS1_type_1(buf, num, from, flen); + break; + case RSA_NO_PADDING: + i = RSA_padding_add_none(buf, num, from, flen); + break; + case RSA_SSLV23_PADDING: + default: + RSAerr(PK11_F_RSA_PRIV_ENC, PK11_R_UNKNOWN_PADDING_TYPE); + goto err; + } + if (i <= 0) goto err; + + /* PK11 functions are called here */ + r = pk11_RSA_private_encrypt_low(num, buf, to, rsa); +err: + if (buf != NULL) + { + OPENSSL_cleanse(buf, num); + OPENSSL_free(buf); + } + return (r); + } + +/* Similar to OpenSSL code. Input errors are also checked here */ +static int pk11_RSA_private_decrypt(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding) + { + BIGNUM f; + int j, num = 0, r = -1; + unsigned char *p; + unsigned char *buf = NULL; + + BN_init(&f); + + num = BN_num_bytes(rsa->n); + + if ((buf = (unsigned char *)OPENSSL_malloc(num)) == NULL) + { + RSAerr(PK11_F_RSA_PRIV_DEC, PK11_R_MALLOC_FAILURE); + goto err; + } + + /* + * This check was for equality but PGP does evil things + * and chops off the top '0' bytes + */ + if (flen > num) + { + RSAerr(PK11_F_RSA_PRIV_DEC, + PK11_R_DATA_GREATER_THAN_MOD_LEN); + goto err; + } + + /* make data into a big number */ + if (BN_bin2bn(from, (int)flen, &f) == NULL) + goto err; + + if (BN_ucmp(&f, rsa->n) >= 0) + { + RSAerr(PK11_F_RSA_PRIV_DEC, + PK11_R_DATA_TOO_LARGE_FOR_MODULUS); + goto err; + } + + /* PK11 functions are called here */ + r = pk11_RSA_private_decrypt_low(flen, from, buf, rsa); + + /* + * PK11 CKM_RSA_X_509 mechanism pads 0's at the beginning. + * Needs to skip these 0's paddings here. + */ + for (j = 0; j < r; j++) + if (buf[j] != 0) + break; + + p = buf + j; + j = r - j; /* j is only used with no-padding mode */ + + switch (padding) + { + case RSA_PKCS1_PADDING: + r = RSA_padding_check_PKCS1_type_2(to, num, p, j, num); + break; +#ifndef OPENSSL_NO_SHA + case RSA_PKCS1_OAEP_PADDING: + r = RSA_padding_check_PKCS1_OAEP(to, num, p, j, num, NULL, 0); + break; +#endif + case RSA_SSLV23_PADDING: + r = RSA_padding_check_SSLv23(to, num, p, j, num); + break; + case RSA_NO_PADDING: + r = RSA_padding_check_none(to, num, p, j, num); + break; + default: + RSAerr(PK11_F_RSA_PRIV_DEC, PK11_R_UNKNOWN_PADDING_TYPE); + goto err; + } + if (r < 0) + RSAerr(PK11_F_RSA_PRIV_DEC, PK11_R_PADDING_CHECK_FAILED); + +err: + BN_clear_free(&f); + if (buf != NULL) + { + OPENSSL_cleanse(buf, num); + OPENSSL_free(buf); + } + return (r); + } + +/* Similar to OpenSSL code. Input errors are also checked here */ +static int pk11_RSA_public_decrypt(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding) + { + BIGNUM f; + int i, num = 0, r = -1; + unsigned char *p; + unsigned char *buf = NULL; + + BN_init(&f); + num = BN_num_bytes(rsa->n); + buf = (unsigned char *)OPENSSL_malloc(num); + if (buf == NULL) + { + RSAerr(PK11_F_RSA_PUB_DEC, PK11_R_MALLOC_FAILURE); + goto err; + } + + /* + * This check was for equality but PGP does evil things + * and chops off the top '0' bytes + */ + if (flen > num) + { + RSAerr(PK11_F_RSA_PUB_DEC, PK11_R_DATA_GREATER_THAN_MOD_LEN); + goto err; + } + + if (BN_bin2bn(from, flen, &f) == NULL) + goto err; + + if (BN_ucmp(&f, rsa->n) >= 0) + { + RSAerr(PK11_F_RSA_PUB_DEC, + PK11_R_DATA_TOO_LARGE_FOR_MODULUS); + goto err; + } + + /* PK11 functions are called here */ + r = pk11_RSA_public_decrypt_low(flen, from, buf, rsa); + + /* + * PK11 CKM_RSA_X_509 mechanism pads 0's at the beginning. + * Needs to skip these 0's here + */ + for (i = 0; i < r; i++) + if (buf[i] != 0) + break; + + p = buf + i; + i = r - i; /* i is only used with no-padding mode */ + + switch (padding) + { + case RSA_PKCS1_PADDING: + r = RSA_padding_check_PKCS1_type_1(to, num, p, i, num); + break; + case RSA_NO_PADDING: + r = RSA_padding_check_none(to, num, p, i, num); + break; + default: + RSAerr(PK11_F_RSA_PUB_DEC, PK11_R_UNKNOWN_PADDING_TYPE); + goto err; + } + if (r < 0) + RSAerr(PK11_F_RSA_PUB_DEC, PK11_R_PADDING_CHECK_FAILED); + +err: + BN_clear_free(&f); + if (buf != NULL) + { + OPENSSL_cleanse(buf, num); + OPENSSL_free(buf); + } + return (r); + } + +/* + * This function implements RSA public encryption using C_EncryptInit and + * C_Encrypt pk11 interfaces. Note that the CKM_RSA_X_509 is used here. + * The calling function allocated sufficient memory in "to" to store results. + */ +static int pk11_RSA_public_encrypt_low(int flen, + const unsigned char *from, unsigned char *to, RSA *rsa) + { + CK_ULONG bytes_encrypted = flen; + int retval = -1; + CK_RV rv; + CK_MECHANISM mech_rsa = {CKM_RSA_X_509, NULL, 0}; + CK_MECHANISM *p_mech = &mech_rsa; + CK_OBJECT_HANDLE h_pub_key = CK_INVALID_HANDLE; + PK11_SESSION *sp; + + if ((sp = pk11_get_session(OP_RSA)) == NULL) + return (-1); + + (void) check_new_rsa_key_pub(sp, rsa); + + h_pub_key = sp->opdata_rsa_pub_key; + if (h_pub_key == CK_INVALID_HANDLE) + h_pub_key = sp->opdata_rsa_pub_key = + pk11_get_public_rsa_key(rsa, &sp->opdata_rsa_pub, + &sp->opdata_rsa_n_num, &sp->opdata_rsa_e_num, + sp->session); + + if (h_pub_key != CK_INVALID_HANDLE) + { + rv = pFuncList->C_EncryptInit(sp->session, p_mech, + h_pub_key); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_RSA_PUB_ENC_LOW, + PK11_R_ENCRYPTINIT, rv); + pk11_return_session(sp, OP_RSA); + return (-1); + } + + rv = pFuncList->C_Encrypt(sp->session, + (unsigned char *)from, flen, to, &bytes_encrypted); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_RSA_PUB_ENC_LOW, + PK11_R_ENCRYPT, rv); + pk11_return_session(sp, OP_RSA); + return (-1); + } + retval = bytes_encrypted; + } + + pk11_return_session(sp, OP_RSA); + return (retval); + } + + +/* + * This function implements RSA private encryption using C_SignInit and + * C_Sign pk11 APIs. Note that CKM_RSA_X_509 is used here. + * The calling function allocated sufficient memory in "to" to store results. + */ +static int pk11_RSA_private_encrypt_low(int flen, + const unsigned char *from, unsigned char *to, RSA *rsa) + { + CK_ULONG ul_sig_len = flen; + int retval = -1; + CK_RV rv; + CK_MECHANISM mech_rsa = {CKM_RSA_X_509, NULL, 0}; + CK_MECHANISM *p_mech = &mech_rsa; + CK_OBJECT_HANDLE h_priv_key = CK_INVALID_HANDLE; + PK11_SESSION *sp; + + if ((sp = pk11_get_session(OP_RSA)) == NULL) + return (-1); + + (void) check_new_rsa_key_priv(sp, rsa); + + h_priv_key = sp->opdata_rsa_priv_key; + if (h_priv_key == CK_INVALID_HANDLE) + { + h_priv_key = sp->opdata_rsa_priv_key = + pk11_get_private_rsa_key(rsa, &sp->opdata_rsa_priv, + &sp->opdata_rsa_d_num, &sp->opdata_rsa_pn_num, + &sp->opdata_rsa_pe_num, sp->session); + } + + if (h_priv_key != CK_INVALID_HANDLE) + { + rv = pFuncList->C_SignInit(sp->session, p_mech, + h_priv_key); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_RSA_PRIV_ENC_LOW, + PK11_R_SIGNINIT, rv); + pk11_return_session(sp, OP_RSA); + return (-1); + } + + rv = pFuncList->C_Sign(sp->session, + (unsigned char *)from, flen, to, &ul_sig_len); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_RSA_PRIV_ENC_LOW, PK11_R_SIGN, + rv); + pk11_return_session(sp, OP_RSA); + return (-1); + } + + retval = ul_sig_len; + } + + pk11_return_session(sp, OP_RSA); + return (retval); + } + + +/* + * This function implements RSA private decryption using C_DecryptInit and + * C_Decrypt pk11 APIs. Note that CKM_RSA_X_509 mechanism is used here. + * The calling function allocated sufficient memory in "to" to store results. + */ +static int pk11_RSA_private_decrypt_low(int flen, + const unsigned char *from, unsigned char *to, RSA *rsa) + { + CK_ULONG bytes_decrypted = flen; + int retval = -1; + CK_RV rv; + CK_MECHANISM mech_rsa = {CKM_RSA_X_509, NULL, 0}; + CK_MECHANISM *p_mech = &mech_rsa; + CK_OBJECT_HANDLE h_priv_key; + PK11_SESSION *sp; + + if ((sp = pk11_get_session(OP_RSA)) == NULL) + return (-1); + + (void) check_new_rsa_key_priv(sp, rsa); + + h_priv_key = sp->opdata_rsa_priv_key; + if (h_priv_key == CK_INVALID_HANDLE) + h_priv_key = sp->opdata_rsa_priv_key = + pk11_get_private_rsa_key(rsa, &sp->opdata_rsa_priv, + &sp->opdata_rsa_d_num, &sp->opdata_rsa_pn_num, + &sp->opdata_rsa_pe_num, sp->session); + + if (h_priv_key != CK_INVALID_HANDLE) + { + rv = pFuncList->C_DecryptInit(sp->session, p_mech, + h_priv_key); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_RSA_PRIV_DEC_LOW, + PK11_R_DECRYPTINIT, rv); + pk11_return_session(sp, OP_RSA); + return (-1); + } + + rv = pFuncList->C_Decrypt(sp->session, + (unsigned char *)from, flen, to, &bytes_decrypted); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_RSA_PRIV_DEC_LOW, + PK11_R_DECRYPT, rv); + pk11_return_session(sp, OP_RSA); + return (-1); + } + retval = bytes_decrypted; + } + + pk11_return_session(sp, OP_RSA); + return (retval); + } + + +/* + * This function implements RSA public decryption using C_VerifyRecoverInit + * and C_VerifyRecover pk11 APIs. Note that CKM_RSA_X_509 is used here. + * The calling function allocated sufficient memory in "to" to store results. + */ +static int pk11_RSA_public_decrypt_low(int flen, + const unsigned char *from, unsigned char *to, RSA *rsa) + { + CK_ULONG bytes_decrypted = flen; + int retval = -1; + CK_RV rv; + CK_MECHANISM mech_rsa = {CKM_RSA_X_509, NULL, 0}; + CK_MECHANISM *p_mech = &mech_rsa; + CK_OBJECT_HANDLE h_pub_key = CK_INVALID_HANDLE; + PK11_SESSION *sp; + + if ((sp = pk11_get_session(OP_RSA)) == NULL) + return (-1); + + (void) check_new_rsa_key_pub(sp, rsa); + + h_pub_key = sp->opdata_rsa_pub_key; + if (h_pub_key == CK_INVALID_HANDLE) + h_pub_key = sp->opdata_rsa_pub_key = + pk11_get_public_rsa_key(rsa, &sp->opdata_rsa_pub, + &sp->opdata_rsa_n_num, &sp->opdata_rsa_e_num, + sp->session); + + if (h_pub_key != CK_INVALID_HANDLE) + { + rv = pFuncList->C_VerifyRecoverInit(sp->session, + p_mech, h_pub_key); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_RSA_PUB_DEC_LOW, + PK11_R_VERIFYRECOVERINIT, rv); + pk11_return_session(sp, OP_RSA); + return (-1); + } + + rv = pFuncList->C_VerifyRecover(sp->session, + (unsigned char *)from, flen, to, &bytes_decrypted); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_RSA_PUB_DEC_LOW, + PK11_R_VERIFYRECOVER, rv); + pk11_return_session(sp, OP_RSA); + return (-1); + } + retval = bytes_decrypted; + } + + pk11_return_session(sp, OP_RSA); + return (retval); + } + +static int pk11_RSA_init(RSA *rsa) + { + /* + * This flag in the RSA_METHOD enables the new rsa_sign, + * rsa_verify functions. See rsa.h for details. + */ + rsa->flags |= RSA_FLAG_SIGN_VER; + + return (1); + } + +static int pk11_RSA_finish(RSA *rsa) + { + /* + * Since we are overloading OpenSSL's native RSA_eay_finish() we need + * to do the same as in the original function, i.e. to free bignum + * structures. + */ + if (rsa->_method_mod_n != NULL) + BN_MONT_CTX_free(rsa->_method_mod_n); + if (rsa->_method_mod_p != NULL) + BN_MONT_CTX_free(rsa->_method_mod_p); + if (rsa->_method_mod_q != NULL) + BN_MONT_CTX_free(rsa->_method_mod_q); + + return (1); + } + +/* + * Standard engine interface function. Majority codes here are from + * rsa/rsa_sign.c. We replaced the decrypt function call by C_Sign of PKCS#11. + * See more details in rsa/rsa_sign.c + */ +static int pk11_RSA_sign(int type, const unsigned char *m, unsigned int m_len, + unsigned char *sigret, unsigned int *siglen, const RSA *rsa) + { + X509_SIG sig; + ASN1_TYPE parameter; + int i, j = 0; + unsigned char *p, *s = NULL; + X509_ALGOR algor; + ASN1_OCTET_STRING digest; + CK_RV rv; + CK_MECHANISM mech_rsa = {CKM_RSA_PKCS, NULL, 0}; + CK_MECHANISM *p_mech = &mech_rsa; + CK_OBJECT_HANDLE h_priv_key; + PK11_SESSION *sp = NULL; + int ret = 0; + unsigned long ulsiglen; + + /* Encode the digest */ + /* Special case: SSL signature, just check the length */ + if (type == NID_md5_sha1) + { + if (m_len != SSL_SIG_LENGTH) + { + PK11err(PK11_F_RSA_SIGN, + PK11_R_INVALID_MESSAGE_LENGTH); + goto err; + } + i = SSL_SIG_LENGTH; + s = (unsigned char *)m; + } + else + { + sig.algor = &algor; + sig.algor->algorithm = OBJ_nid2obj(type); + if (sig.algor->algorithm == NULL) + { + PK11err(PK11_F_RSA_SIGN, + PK11_R_UNKNOWN_ALGORITHM_TYPE); + goto err; + } + if (sig.algor->algorithm->length == 0) + { + PK11err(PK11_F_RSA_SIGN, + PK11_R_UNKNOWN_ASN1_OBJECT_ID); + goto err; + } + parameter.type = V_ASN1_NULL; + parameter.value.ptr = NULL; + sig.algor->parameter = ¶meter; + + sig.digest = &digest; + sig.digest->data = (unsigned char *)m; + sig.digest->length = m_len; + + i = i2d_X509_SIG(&sig, NULL); + } + + j = RSA_size(rsa); + if ((i - RSA_PKCS1_PADDING) > j) + { + PK11err(PK11_F_RSA_SIGN, PK11_R_DIGEST_TOO_BIG); + goto err; + } + + if (type != NID_md5_sha1) + { + s = (unsigned char *)OPENSSL_malloc((unsigned int)(j + 1)); + if (s == NULL) + { + PK11err(PK11_F_RSA_SIGN, PK11_R_MALLOC_FAILURE); + goto err; + } + p = s; + (void) i2d_X509_SIG(&sig, &p); + } + + if ((sp = pk11_get_session(OP_RSA)) == NULL) + goto err; + + (void) check_new_rsa_key_priv(sp, rsa); + + h_priv_key = sp->opdata_rsa_priv_key; + if (h_priv_key == CK_INVALID_HANDLE) + h_priv_key = sp->opdata_rsa_priv_key = + pk11_get_private_rsa_key((RSA *)rsa, + &sp->opdata_rsa_priv, &sp->opdata_rsa_d_num, + &sp->opdata_rsa_pn_num, &sp->opdata_rsa_pe_num, + sp->session); + + if (h_priv_key != CK_INVALID_HANDLE) + { + rv = pFuncList->C_SignInit(sp->session, p_mech, h_priv_key); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_RSA_SIGN, PK11_R_SIGNINIT, rv); + goto err; + } + + ulsiglen = j; + rv = pFuncList->C_Sign(sp->session, s, i, sigret, + (CK_ULONG_PTR) &ulsiglen); + *siglen = ulsiglen; + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_RSA_SIGN, PK11_R_SIGN, rv); + goto err; + } + ret = 1; + } + +err: + if ((type != NID_md5_sha1) && (s != NULL)) + { + (void) memset(s, 0, (unsigned int)(j + 1)); + OPENSSL_free(s); + } + + pk11_return_session(sp, OP_RSA); + return (ret); + } + +#if OPENSSL_VERSION_NUMBER < 0x10000000L +static int pk11_RSA_verify(int type, const unsigned char *m, + unsigned int m_len, unsigned char *sigbuf, unsigned int siglen, + const RSA *rsa) +#else +static int pk11_RSA_verify(int type, const unsigned char *m, + unsigned int m_len, const unsigned char *sigbuf, unsigned int siglen, + const RSA *rsa) +#endif + { + X509_SIG sig; + ASN1_TYPE parameter; + int i, j = 0; + unsigned char *p, *s = NULL; + X509_ALGOR algor; + ASN1_OCTET_STRING digest; + CK_RV rv; + CK_MECHANISM mech_rsa = {CKM_RSA_PKCS, NULL, 0}; + CK_MECHANISM *p_mech = &mech_rsa; + CK_OBJECT_HANDLE h_pub_key; + PK11_SESSION *sp = NULL; + int ret = 0; + + /* Encode the digest */ + /* Special case: SSL signature, just check the length */ + if (type == NID_md5_sha1) + { + if (m_len != SSL_SIG_LENGTH) + { + PK11err(PK11_F_RSA_VERIFY, + PK11_R_INVALID_MESSAGE_LENGTH); + goto err; + } + i = SSL_SIG_LENGTH; + s = (unsigned char *)m; + } + else + { + sig.algor = &algor; + sig.algor->algorithm = OBJ_nid2obj(type); + if (sig.algor->algorithm == NULL) + { + PK11err(PK11_F_RSA_VERIFY, + PK11_R_UNKNOWN_ALGORITHM_TYPE); + goto err; + } + if (sig.algor->algorithm->length == 0) + { + PK11err(PK11_F_RSA_VERIFY, + PK11_R_UNKNOWN_ASN1_OBJECT_ID); + goto err; + } + parameter.type = V_ASN1_NULL; + parameter.value.ptr = NULL; + sig.algor->parameter = ¶meter; + sig.digest = &digest; + sig.digest->data = (unsigned char *)m; + sig.digest->length = m_len; + i = i2d_X509_SIG(&sig, NULL); + } + + j = RSA_size(rsa); + if ((i - RSA_PKCS1_PADDING) > j) + { + PK11err(PK11_F_RSA_VERIFY, PK11_R_DIGEST_TOO_BIG); + goto err; + } + + if (type != NID_md5_sha1) + { + s = (unsigned char *)OPENSSL_malloc((unsigned int)(j + 1)); + if (s == NULL) + { + PK11err(PK11_F_RSA_VERIFY, PK11_R_MALLOC_FAILURE); + goto err; + } + p = s; + (void) i2d_X509_SIG(&sig, &p); + } + + if ((sp = pk11_get_session(OP_RSA)) == NULL) + goto err; + + (void) check_new_rsa_key_pub(sp, rsa); + + h_pub_key = sp->opdata_rsa_pub_key; + if (h_pub_key == CK_INVALID_HANDLE) + h_pub_key = sp->opdata_rsa_pub_key = + pk11_get_public_rsa_key((RSA *)rsa, &sp->opdata_rsa_pub, + &sp->opdata_rsa_n_num, &sp->opdata_rsa_e_num, + sp->session); + + if (h_pub_key != CK_INVALID_HANDLE) + { + rv = pFuncList->C_VerifyInit(sp->session, p_mech, + h_pub_key); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_RSA_VERIFY, PK11_R_VERIFYINIT, + rv); + goto err; + } + rv = pFuncList->C_Verify(sp->session, s, i, + (CK_BYTE_PTR)sigbuf, (CK_ULONG)siglen); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_RSA_VERIFY, PK11_R_VERIFY, rv); + goto err; + } + ret = 1; + } + +err: + if ((type != NID_md5_sha1) && (s != NULL)) + { + (void) memset(s, 0, (unsigned int)(j + 1)); + OPENSSL_free(s); + } + + pk11_return_session(sp, OP_RSA); + return (ret); + } + +static int hndidx_rsa = -1; + +#define MAXATTR 1024 + +/* + * Load RSA private key from a file or get its PKCS#11 handle if stored in the + * PKCS#11 token. + */ +/* ARGSUSED */ +EVP_PKEY *pk11_load_privkey(ENGINE *e, const char *privkey_file, + UI_METHOD *ui_method, void *callback_data) + { + EVP_PKEY *pkey = NULL; + FILE *privkey; + CK_OBJECT_HANDLE h_priv_key = CK_INVALID_HANDLE; + RSA *rsa = NULL; + PK11_SESSION *sp; + /* Anything else below is needed for the key by reference extension. */ + CK_RV rv; + CK_BBOOL is_token = TRUE; + CK_BBOOL rollback = FALSE; + CK_BYTE attr_data[2][MAXATTR]; + CK_OBJECT_CLASS key_class = CKO_PRIVATE_KEY; + CK_OBJECT_HANDLE ks_key = CK_INVALID_HANDLE; /* key in keystore */ + + /* we look for private keys only */ + CK_ATTRIBUTE search_templ[] = + { + {CKA_TOKEN, &is_token, sizeof(is_token)}, + {CKA_CLASS, &key_class, sizeof(key_class)}, + {CKA_LABEL, NULL, 0} + }; + + /* + * These public attributes are needed to initialize the OpenSSL RSA + * structure with something we can use to look up the key. Note that we + * never ask for private components. + */ + CK_ATTRIBUTE get_templ[] = + { + {CKA_MODULUS, (void *)attr_data[0], MAXATTR}, /* n */ + {CKA_PUBLIC_EXPONENT, (void *)attr_data[1], MAXATTR}, /* e */ + }; + + if ((sp = pk11_get_session(OP_RSA)) == NULL) + return (NULL); + + /* + * Use simple scheme "pkcs11:" for now. + */ + if (strstr(privkey_file, "pkcs11:") == privkey_file) + { + search_templ[2].pValue = strstr(privkey_file, ":") + 1; + search_templ[2].ulValueLen = strlen(search_templ[2].pValue); + + if (pk11_token_login(sp->session, &pk11_login_done, + CK_TRUE) == 0) + goto err; + + /* see find_lock array definition + for more info on object locking */ + LOCK_OBJSTORE(OP_RSA); + + /* + * Now let's try to find the key in the token. It is a failure + * if we can't find it. + */ + if (find_one_object(OP_RSA, sp->session, search_templ, 3, + &ks_key) == 0) + { + UNLOCK_OBJSTORE(OP_RSA); + goto err; + } + + if (hndidx_rsa == -1) + hndidx_rsa = RSA_get_ex_new_index(0, + "pkcs11 RSA HSM key handle", + NULL, NULL, NULL); + + /* + * We might have a cache hit which we could confirm + * according to the 'n'/'e' params, RSA public pointer + * as NULL, and non-NULL RSA private pointer. However, + * it is easier just to recreate everything. We expect + * the keys to be loaded once and used many times. We + * do not check the return value because even in case + * of failure the sp structure will have both key + * pointer and object handle cleaned and + * pk11_destroy_object() reports the failure to the + * OpenSSL error message buffer. + */ + (void) pk11_destroy_rsa_object_priv(sp, FALSE); + + sp->opdata_rsa_priv_key = ks_key; + /* This object shall not be deleted on a cache miss. */ + sp->priv_persistent = CK_TRUE; + + /* + * Cache the RSA private structure pointer. We do not + * use it now for key-by-ref keys but let's do it for + * consistency reasons. + */ + if ((rsa = sp->opdata_rsa_priv = RSA_new_method(e)) == NULL) + { + UNLOCK_OBJSTORE(OP_RSA); + goto err; + } + + /* + * Now we have to initialize an OpenSSL RSA structure, + * everything else is 0 or NULL. + */ + rsa->flags = RSA_FLAG_SIGN_VER | RSA_FLAG_EXT_PKEY; + RSA_set_ex_data(rsa, hndidx_rsa, (void *) ks_key); + + if ((rv = pFuncList->C_GetAttributeValue(sp->session, ks_key, + get_templ, 2)) != CKR_OK) + { + UNLOCK_OBJSTORE(OP_RSA); + PK11err_add_data(PK11_F_LOAD_PRIVKEY, + PK11_R_GETATTRIBUTVALUE, rv); + goto err; + } + + /* + * We do not use pk11_get_private_rsa_key() here so we + * must take care of handle management ourselves. + */ + KEY_HANDLE_REFHOLD(ks_key, OP_RSA, TRUE, rollback, err); + + /* + * Those are the sensitive components we do not want to export + * from the token at all: rsa->(d|p|q|dmp1|dmq1|iqmp). + */ + attr_to_BN(&get_templ[0], attr_data[0], &rsa->n); + attr_to_BN(&get_templ[1], attr_data[1], &rsa->e); + /* + * Must have 'n'/'e' components in the session structure as + * well. They serve as a public look-up key for the private key + * in the keystore. + */ + attr_to_BN(&get_templ[0], attr_data[0], + &sp->opdata_rsa_pn_num); + attr_to_BN(&get_templ[1], attr_data[1], + &sp->opdata_rsa_pe_num); + + UNLOCK_OBJSTORE(OP_RSA); + + if ((pkey = EVP_PKEY_new()) == NULL) + goto err; + + if (EVP_PKEY_assign_RSA(pkey, rsa) == 0) + goto err; + } + else if ((privkey = fopen(privkey_file, read_mode_flags)) != NULL) + { + pkey = PEM_read_PrivateKey(privkey, NULL, NULL, NULL); + (void) fclose(privkey); + if (pkey != NULL) + { + rsa = EVP_PKEY_get1_RSA(pkey); + if (rsa != NULL) + { + /* + * This will always destroy the RSA + * object since we have a new RSA + * structure here. + */ + (void) check_new_rsa_key_priv(sp, rsa); + sp->priv_persistent = CK_FALSE; + + h_priv_key = sp->opdata_rsa_priv_key = + pk11_get_private_rsa_key(rsa, + &sp->opdata_rsa_priv, + &sp->opdata_rsa_d_num, + &sp->opdata_rsa_pn_num, + &sp->opdata_rsa_pe_num, sp->session); + if (h_priv_key == CK_INVALID_HANDLE) + goto err; + } + else + goto err; + } + } + + pk11_return_session(sp, OP_RSA); + return (pkey); +err: + pk11_return_session(sp, OP_RSA); + if (rsa != NULL) + RSA_free(rsa); + if (pkey != NULL) + { + EVP_PKEY_free(pkey); + pkey = NULL; + } + rollback = rollback; + return (pkey); + } + +/* + * Load RSA public key from a file or get its PKCS#11 handle if stored in the + * PKCS#11 token. + */ +/* ARGSUSED */ +EVP_PKEY *pk11_load_pubkey(ENGINE *e, const char *pubkey_file, + UI_METHOD *ui_method, void *callback_data) + { + EVP_PKEY *pkey = NULL; + FILE *pubkey; + CK_OBJECT_HANDLE h_pub_key = CK_INVALID_HANDLE; + RSA *rsa = NULL; + PK11_SESSION *sp; + /* Anything else below is needed for the key by reference extension. */ + CK_RV rv; + CK_BBOOL is_token = TRUE; + CK_BYTE attr_data[2][MAXATTR]; + CK_OBJECT_CLASS key_class = CKO_PUBLIC_KEY; + CK_OBJECT_HANDLE ks_key = CK_INVALID_HANDLE; /* key in keystore */ + + /* we look for public keys only */ + CK_ATTRIBUTE search_templ[] = + { + {CKA_TOKEN, &is_token, sizeof(is_token)}, + {CKA_CLASS, &key_class, sizeof(key_class)}, + {CKA_LABEL, NULL, 0} + }; + + /* + * These public attributes are needed to initialize OpenSSL RSA + * structure with something we can use to look up the key. + */ + CK_ATTRIBUTE get_templ[] = + { + {CKA_MODULUS, (void *)attr_data[0], MAXATTR}, /* n */ + {CKA_PUBLIC_EXPONENT, (void *)attr_data[1], MAXATTR}, /* e */ + }; + + if ((sp = pk11_get_session(OP_RSA)) == NULL) + return (NULL); + + /* + * Use simple scheme "pkcs11:" for now. + */ + if (strstr(pubkey_file, "pkcs11:") == pubkey_file) + { + search_templ[2].pValue = strstr(pubkey_file, ":") + 1; + search_templ[2].ulValueLen = strlen(search_templ[2].pValue); + + if (pk11_token_login(sp->session, &pk11_login_done, + CK_FALSE) == 0) + goto err; + + /* see find_lock array definition + for more info on object locking */ + LOCK_OBJSTORE(OP_RSA); + + /* + * Now let's try to find the key in the token. It is a failure + * if we can't find it. + */ + if (find_one_object(OP_RSA, sp->session, search_templ, 3, + &ks_key) == 0) + { + UNLOCK_OBJSTORE(OP_RSA); + goto err; + } + + /* + * We load a new public key so we will create a new RSA + * structure. No cache hit is possible. + */ + (void) pk11_destroy_rsa_object_pub(sp, FALSE); + + sp->opdata_rsa_pub_key = ks_key; + /* This object shall not be deleted on a cache miss. */ + sp->pub_persistent = CK_TRUE; + + /* + * Cache the RSA public structure pointer. + */ + if ((rsa = sp->opdata_rsa_pub = RSA_new_method(e)) == NULL) + { + UNLOCK_OBJSTORE(OP_RSA); + goto err; + } + + /* + * Now we have to initialize an OpenSSL RSA structure, + * everything else is 0 or NULL. + */ + rsa->flags = RSA_FLAG_SIGN_VER; + + if ((rv = pFuncList->C_GetAttributeValue(sp->session, ks_key, + get_templ, 2)) != CKR_OK) + { + UNLOCK_OBJSTORE(OP_RSA); + PK11err_add_data(PK11_F_LOAD_PUBKEY, + PK11_R_GETATTRIBUTVALUE, rv); + goto err; + } + + attr_to_BN(&get_templ[0], attr_data[0], &rsa->n); + attr_to_BN(&get_templ[1], attr_data[1], &rsa->e); + + UNLOCK_OBJSTORE(OP_RSA); + + if ((pkey = EVP_PKEY_new()) == NULL) + goto err; + + if (EVP_PKEY_assign_RSA(pkey, rsa) == 0) + goto err; + + /* + * Create a session object from it so that when calling + * pk11_get_public_rsa_key() the next time, we can find it. The + * reason why we do that is that we cannot tell from the RSA + * structure (OpenSSL RSA structure does not have any room for + * additional data used by the engine, for example) if it bears + * a public key stored in the keystore or not so it's better if + * we always have a session key. Note that this is different + * from what we do for the private keystore objects but in that + * case, we can tell from the RSA structure that the keystore + * object is in play - the 'd' component is NULL in that case. + */ + h_pub_key = sp->opdata_rsa_pub_key = + pk11_get_public_rsa_key(rsa, + &sp->opdata_rsa_pub, &sp->opdata_rsa_n_num, + &sp->opdata_rsa_e_num, sp->session); + if (h_pub_key == CK_INVALID_HANDLE) + goto err; + } + else if ((pubkey = fopen(pubkey_file, read_mode_flags)) != NULL) + { + pkey = PEM_read_PUBKEY(pubkey, NULL, NULL, NULL); + (void) fclose(pubkey); + if (pkey != NULL) + { + rsa = EVP_PKEY_get1_RSA(pkey); + if (rsa != NULL) + { + /* + * This will always destroy the RSA + * object since we have a new RSA + * structure here. + */ + (void) check_new_rsa_key_pub(sp, rsa); + sp->pub_persistent = CK_FALSE; + + h_pub_key = sp->opdata_rsa_pub_key = + pk11_get_public_rsa_key(rsa, + &sp->opdata_rsa_pub, &sp->opdata_rsa_n_num, + &sp->opdata_rsa_e_num, sp->session); + if (h_pub_key == CK_INVALID_HANDLE) + goto err; + } + else + goto err; + } + } + + pk11_return_session(sp, OP_RSA); + return (pkey); +err: + pk11_return_session(sp, OP_RSA); + if (rsa != NULL) + RSA_free(rsa); + if (pkey != NULL) + { + EVP_PKEY_free(pkey); + pkey = NULL; + } + return (pkey); + } + +/* + * Create a public key object in a session from a given rsa structure. + * The *rsa_n_num and *rsa_e_num pointers are non-NULL for RSA public keys. + */ +static CK_OBJECT_HANDLE pk11_get_public_rsa_key(RSA *rsa, + RSA **key_ptr, BIGNUM **rsa_n_num, BIGNUM **rsa_e_num, + CK_SESSION_HANDLE session) + { + CK_RV rv; + CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE; + CK_ULONG found; + CK_OBJECT_CLASS o_key = CKO_PUBLIC_KEY; + CK_KEY_TYPE k_type = CKK_RSA; + CK_ULONG ul_key_attr_count = 8; + CK_BBOOL rollback = FALSE; + + CK_ATTRIBUTE a_key_template[] = + { + {CKA_CLASS, (void *) NULL, sizeof (CK_OBJECT_CLASS)}, + {CKA_KEY_TYPE, (void *) NULL, sizeof (CK_KEY_TYPE)}, + {CKA_TOKEN, &myfalse, sizeof (myfalse)}, + {CKA_ENCRYPT, &mytrue, sizeof (mytrue)}, + {CKA_VERIFY, &mytrue, sizeof (mytrue)}, + {CKA_VERIFY_RECOVER, &mytrue, sizeof (mytrue)}, + {CKA_MODULUS, (void *)NULL, 0}, + {CKA_PUBLIC_EXPONENT, (void *)NULL, 0} + }; + + int i; + + a_key_template[0].pValue = &o_key; + a_key_template[1].pValue = &k_type; + + a_key_template[6].ulValueLen = BN_num_bytes(rsa->n); + a_key_template[6].pValue = (CK_VOID_PTR)OPENSSL_malloc( + (size_t)a_key_template[6].ulValueLen); + if (a_key_template[6].pValue == NULL) + { + PK11err(PK11_F_GET_PUB_RSA_KEY, PK11_R_MALLOC_FAILURE); + goto malloc_err; + } + + BN_bn2bin(rsa->n, a_key_template[6].pValue); + + a_key_template[7].ulValueLen = BN_num_bytes(rsa->e); + a_key_template[7].pValue = (CK_VOID_PTR)OPENSSL_malloc( + (size_t)a_key_template[7].ulValueLen); + if (a_key_template[7].pValue == NULL) + { + PK11err(PK11_F_GET_PUB_RSA_KEY, PK11_R_MALLOC_FAILURE); + goto malloc_err; + } + + BN_bn2bin(rsa->e, a_key_template[7].pValue); + + /* see find_lock array definition for more info on object locking */ + LOCK_OBJSTORE(OP_RSA); + + rv = pFuncList->C_FindObjectsInit(session, a_key_template, + ul_key_attr_count); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PUB_RSA_KEY, + PK11_R_FINDOBJECTSINIT, rv); + goto err; + } + + rv = pFuncList->C_FindObjects(session, &h_key, 1, &found); + + if (rv != CKR_OK) + { + (void) pFuncList->C_FindObjectsFinal(session); + PK11err_add_data(PK11_F_GET_PUB_RSA_KEY, + PK11_R_FINDOBJECTS, rv); + goto err; + } + + rv = pFuncList->C_FindObjectsFinal(session); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PUB_RSA_KEY, + PK11_R_FINDOBJECTSFINAL, rv); + goto err; + } + + if (found == 0) + { + rv = pFuncList->C_CreateObject(session, + a_key_template, ul_key_attr_count, &h_key); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PUB_RSA_KEY, + PK11_R_CREATEOBJECT, rv); + goto err; + } + } + + if (rsa_n_num != NULL) + if ((*rsa_n_num = BN_dup(rsa->n)) == NULL) + { + PK11err(PK11_F_GET_PUB_RSA_KEY, PK11_R_MALLOC_FAILURE); + rollback = TRUE; + goto err; + } + if (rsa_e_num != NULL) + if ((*rsa_e_num = BN_dup(rsa->e)) == NULL) + { + PK11err(PK11_F_GET_PUB_RSA_KEY, PK11_R_MALLOC_FAILURE); + BN_free(*rsa_n_num); + *rsa_n_num = NULL; + rollback = TRUE; + goto err; + } + + /* LINTED: E_CONSTANT_CONDITION */ + KEY_HANDLE_REFHOLD(h_key, OP_RSA, FALSE, rollback, err); + if (key_ptr != NULL) + *key_ptr = rsa; + +err: + if (rollback) + { + /* + * We do not care about the return value from C_DestroyObject() + * since we are doing rollback. + */ + if (found == 0) + (void) pFuncList->C_DestroyObject(session, h_key); + h_key = CK_INVALID_HANDLE; + } + + UNLOCK_OBJSTORE(OP_RSA); + +malloc_err: + for (i = 6; i <= 7; i++) + { + if (a_key_template[i].pValue != NULL) + { + OPENSSL_free(a_key_template[i].pValue); + a_key_template[i].pValue = NULL; + } + } + + return (h_key); + } + +/* + * Create a private key object in the session from a given rsa structure. + * The *rsa_d_num pointer is non-NULL for RSA private keys. + */ +static CK_OBJECT_HANDLE +pk11_get_private_rsa_key(RSA *rsa, RSA **key_ptr, BIGNUM **rsa_d_num, + BIGNUM **rsa_n_num, BIGNUM **rsa_e_num, CK_SESSION_HANDLE session) + { + CK_RV rv; + CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE; + int i; + CK_ULONG found; + CK_OBJECT_CLASS o_key = CKO_PRIVATE_KEY; + CK_KEY_TYPE k_type = CKK_RSA; + CK_ULONG ul_key_attr_count = 14; + CK_BBOOL rollback = FALSE; + + /* Both CKA_TOKEN and CKA_SENSITIVE have to be FALSE for session keys */ + CK_ATTRIBUTE a_key_template[] = + { + {CKA_CLASS, (void *) NULL, sizeof (CK_OBJECT_CLASS)}, + {CKA_KEY_TYPE, (void *) NULL, sizeof (CK_KEY_TYPE)}, + {CKA_TOKEN, &myfalse, sizeof (myfalse)}, + {CKA_SENSITIVE, &myfalse, sizeof (myfalse)}, + {CKA_DECRYPT, &mytrue, sizeof (mytrue)}, + {CKA_SIGN, &mytrue, sizeof (mytrue)}, + {CKA_MODULUS, (void *)NULL, 0}, + {CKA_PUBLIC_EXPONENT, (void *)NULL, 0}, + {CKA_PRIVATE_EXPONENT, (void *)NULL, 0}, + {CKA_PRIME_1, (void *)NULL, 0}, + {CKA_PRIME_2, (void *)NULL, 0}, + {CKA_EXPONENT_1, (void *)NULL, 0}, + {CKA_EXPONENT_2, (void *)NULL, 0}, + {CKA_COEFFICIENT, (void *)NULL, 0}, + }; + + if ((rsa->flags & RSA_FLAG_EXT_PKEY) != 0) { + h_key = (CK_OBJECT_HANDLE)RSA_get_ex_data(rsa, hndidx_rsa); + LOCK_OBJSTORE(OP_RSA); + goto set; + } + + a_key_template[0].pValue = &o_key; + a_key_template[1].pValue = &k_type; + + /* Put the private key components into the template */ + if (init_template_value(rsa->n, &a_key_template[6].pValue, + &a_key_template[6].ulValueLen) == 0 || + init_template_value(rsa->e, &a_key_template[7].pValue, + &a_key_template[7].ulValueLen) == 0 || + init_template_value(rsa->d, &a_key_template[8].pValue, + &a_key_template[8].ulValueLen) == 0 || + init_template_value(rsa->p, &a_key_template[9].pValue, + &a_key_template[9].ulValueLen) == 0 || + init_template_value(rsa->q, &a_key_template[10].pValue, + &a_key_template[10].ulValueLen) == 0 || + init_template_value(rsa->dmp1, &a_key_template[11].pValue, + &a_key_template[11].ulValueLen) == 0 || + init_template_value(rsa->dmq1, &a_key_template[12].pValue, + &a_key_template[12].ulValueLen) == 0 || + init_template_value(rsa->iqmp, &a_key_template[13].pValue, + &a_key_template[13].ulValueLen) == 0) + { + PK11err(PK11_F_GET_PRIV_RSA_KEY, PK11_R_MALLOC_FAILURE); + goto malloc_err; + } + + /* see find_lock array definition for more info on object locking */ + LOCK_OBJSTORE(OP_RSA); + + /* + * We are getting the private key but the private 'd' + * component is NULL. That means this is key by reference RSA + * key. In that case, we can use only public components for + * searching for the private key handle. + */ + if (rsa->d == NULL) + { + ul_key_attr_count = 8; + /* + * We will perform the search in the token, not in the existing + * session keys. + */ + a_key_template[2].pValue = &mytrue; + } + + rv = pFuncList->C_FindObjectsInit(session, a_key_template, + ul_key_attr_count); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PRIV_RSA_KEY, + PK11_R_FINDOBJECTSINIT, rv); + goto err; + } + + rv = pFuncList->C_FindObjects(session, &h_key, 1, &found); + + if (rv != CKR_OK) + { + (void) pFuncList->C_FindObjectsFinal(session); + PK11err_add_data(PK11_F_GET_PRIV_RSA_KEY, + PK11_R_FINDOBJECTS, rv); + goto err; + } + + rv = pFuncList->C_FindObjectsFinal(session); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PRIV_RSA_KEY, + PK11_R_FINDOBJECTSFINAL, rv); + goto err; + } + + if (found == 0) + { + /* + * We have an RSA structure with 'n'/'e' components + * only so we tried to find the private key in the + * keystore. If it was really a token key we have a + * problem. Note that for other key types we just + * create a new session key using the private + * components from the RSA structure. + */ + if (rsa->d == NULL) + { + PK11err(PK11_F_GET_PRIV_RSA_KEY, + PK11_R_PRIV_KEY_NOT_FOUND); + goto err; + } + + rv = pFuncList->C_CreateObject(session, + a_key_template, ul_key_attr_count, &h_key); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PRIV_RSA_KEY, + PK11_R_CREATEOBJECT, rv); + goto err; + } + } + +set: + if (rsa_d_num != NULL) + { + /* + * When RSA keys by reference code is used, we never + * extract private components from the keystore. In + * that case 'd' was set to NULL and we expect the + * application to properly cope with that. It is + * documented in openssl(5). In general, if keys by + * reference are used we expect it to be used + * exclusively using the high level API and then there + * is no problem. If the application expects the + * private components to be read from the keystore + * then that is not a supported way of usage. + */ + if (rsa->d != NULL && (*rsa_d_num = BN_dup(rsa->d)) == NULL) + { + PK11err(PK11_F_GET_PRIV_RSA_KEY, PK11_R_MALLOC_FAILURE); + rollback = TRUE; + goto err; + } + else + *rsa_d_num = NULL; + } + + /* + * For the key by reference code, we need public components as well + * since 'd' component is always NULL. For that reason, we always cache + * 'n'/'e' components as well. + */ + *rsa_n_num = BN_dup(rsa->n); + *rsa_e_num = BN_dup(rsa->e); + + /* LINTED: E_CONSTANT_CONDITION */ + KEY_HANDLE_REFHOLD(h_key, OP_RSA, FALSE, rollback, err); + if (key_ptr != NULL) + *key_ptr = rsa; + +err: + if (rollback) + { + /* + * We do not care about the return value from C_DestroyObject() + * since we are doing rollback. + */ + if (found == 0 && + (rsa->flags & RSA_FLAG_EXT_PKEY) == 0) + (void) pFuncList->C_DestroyObject(session, h_key); + h_key = CK_INVALID_HANDLE; + } + + UNLOCK_OBJSTORE(OP_RSA); + +malloc_err: + /* + * 6 to 13 entries in the key template are key components. + * They need to be freed upon exit or error. + */ + for (i = 6; i <= 13; i++) + { + if (a_key_template[i].pValue != NULL) + { + (void) memset(a_key_template[i].pValue, 0, + a_key_template[i].ulValueLen); + OPENSSL_free(a_key_template[i].pValue); + a_key_template[i].pValue = NULL; + } + } + + return (h_key); + } + +/* + * Check for cache miss and clean the object pointer and handle + * in such case. Return 1 for cache hit, 0 for cache miss. + */ +static int check_new_rsa_key_pub(PK11_SESSION *sp, const RSA *rsa) + { + /* + * Provide protection against RSA structure reuse by making the + * check for cache hit stronger. Only public components of RSA + * key matter here so it is sufficient to compare them with values + * cached in PK11_SESSION structure. + * + * We must check the handle as well since with key by reference, public + * components 'n'/'e' are cached in private keys as well. That means we + * could have a cache hit in a private key when looking for a public + * key. That would not work, you cannot have one PKCS#11 object for + * both data signing and verifying. + */ + if ((sp->opdata_rsa_pub != rsa) || + (BN_cmp(sp->opdata_rsa_n_num, rsa->n) != 0) || + (BN_cmp(sp->opdata_rsa_e_num, rsa->e) != 0) || + (sp->opdata_rsa_priv_key != CK_INVALID_HANDLE)) + { + /* + * We do not check the return value because even in case of + * failure the sp structure will have both key pointer + * and object handle cleaned and pk11_destroy_object() + * reports the failure to the OpenSSL error message buffer. + */ + (void) pk11_destroy_rsa_object_pub(sp, TRUE); + return (0); + } + return (1); + } + +/* + * Check for cache miss and clean the object pointer and handle + * in such case. Return 1 for cache hit, 0 for cache miss. + */ +static int check_new_rsa_key_priv(PK11_SESSION *sp, const RSA *rsa) + { + /* + * Provide protection against RSA structure reuse by making + * the check for cache hit stronger. Comparing public exponent + * of RSA key with value cached in PK11_SESSION structure + * should be sufficient. Note that we want to compare the + * public component since with the keys by reference + * mechanism, private components are not in the RSA + * structure. Also, see check_new_rsa_key_pub() about why we + * compare the handle as well. + */ + if ((sp->opdata_rsa_priv != rsa) || + (BN_cmp(sp->opdata_rsa_pn_num, rsa->n) != 0) || + (BN_cmp(sp->opdata_rsa_pe_num, rsa->e) != 0) || + (sp->opdata_rsa_pn_num == NULL) || + (sp->opdata_rsa_pe_num == NULL) || + (sp->opdata_rsa_pub_key != CK_INVALID_HANDLE)) + { + /* + * We do not check the return value because even in case of + * failure the sp structure will have both key pointer + * and object handle cleaned and pk11_destroy_object() + * reports the failure to the OpenSSL error message buffer. + */ + (void) pk11_destroy_rsa_object_priv(sp, TRUE); + return (0); + } + return (1); + } +#endif + +#ifndef OPENSSL_NO_DSA +/* The DSA function implementation */ +/* ARGSUSED */ +static int pk11_DSA_init(DSA *dsa) + { + return (1); + } + +/* ARGSUSED */ +static int pk11_DSA_finish(DSA *dsa) + { + return (1); + } + + +static DSA_SIG * +pk11_dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa) + { + BIGNUM *r = NULL, *s = NULL; + int i; + DSA_SIG *dsa_sig = NULL; + + CK_RV rv; + CK_MECHANISM Mechanism_dsa = {CKM_DSA, NULL, 0}; + CK_MECHANISM *p_mech = &Mechanism_dsa; + CK_OBJECT_HANDLE h_priv_key; + + /* + * The signature is the concatenation of r and s, + * each is 20 bytes long + */ + unsigned char sigret[DSA_SIGNATURE_LEN]; + unsigned long siglen = DSA_SIGNATURE_LEN; + unsigned int siglen2 = DSA_SIGNATURE_LEN / 2; + + PK11_SESSION *sp = NULL; + + if ((dsa->p == NULL) || (dsa->q == NULL) || (dsa->g == NULL)) + { + PK11err(PK11_F_DSA_SIGN, PK11_R_MISSING_KEY_COMPONENT); + goto ret; + } + + i = BN_num_bytes(dsa->q); /* should be 20 */ + if (dlen > i) + { + PK11err(PK11_F_DSA_SIGN, PK11_R_INVALID_SIGNATURE_LENGTH); + goto ret; + } + + if ((sp = pk11_get_session(OP_DSA)) == NULL) + goto ret; + + (void) check_new_dsa_key_priv(sp, dsa); + + h_priv_key = sp->opdata_dsa_priv_key; + if (h_priv_key == CK_INVALID_HANDLE) + h_priv_key = sp->opdata_dsa_priv_key = + pk11_get_private_dsa_key((DSA *)dsa, + &sp->opdata_dsa_priv, + &sp->opdata_dsa_priv_num, sp->session); + + if (h_priv_key != CK_INVALID_HANDLE) + { + rv = pFuncList->C_SignInit(sp->session, p_mech, h_priv_key); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DSA_SIGN, PK11_R_SIGNINIT, rv); + goto ret; + } + + (void) memset(sigret, 0, siglen); + rv = pFuncList->C_Sign(sp->session, + (unsigned char*) dgst, dlen, sigret, + (CK_ULONG_PTR) &siglen); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DSA_SIGN, PK11_R_SIGN, rv); + goto ret; + } + } + + + if ((s = BN_new()) == NULL) + { + PK11err(PK11_F_DSA_SIGN, PK11_R_MALLOC_FAILURE); + goto ret; + } + + if ((r = BN_new()) == NULL) + { + PK11err(PK11_F_DSA_SIGN, PK11_R_MALLOC_FAILURE); + goto ret; + } + + if ((dsa_sig = DSA_SIG_new()) == NULL) + { + PK11err(PK11_F_DSA_SIGN, PK11_R_MALLOC_FAILURE); + goto ret; + } + + if (BN_bin2bn(sigret, siglen2, r) == NULL || + BN_bin2bn(&sigret[siglen2], siglen2, s) == NULL) + { + PK11err(PK11_F_DSA_SIGN, PK11_R_MALLOC_FAILURE); + goto ret; + } + + dsa_sig->r = r; + dsa_sig->s = s; + +ret: + if (dsa_sig == NULL) + { + if (r != NULL) + BN_free(r); + if (s != NULL) + BN_free(s); + } + + pk11_return_session(sp, OP_DSA); + return (dsa_sig); + } + +static int +pk11_dsa_do_verify(const unsigned char *dgst, int dlen, DSA_SIG *sig, + DSA *dsa) + { + int i; + CK_RV rv; + int retval = 0; + CK_MECHANISM Mechanism_dsa = {CKM_DSA, NULL, 0}; + CK_MECHANISM *p_mech = &Mechanism_dsa; + CK_OBJECT_HANDLE h_pub_key; + + unsigned char sigbuf[DSA_SIGNATURE_LEN]; + unsigned long siglen = DSA_SIGNATURE_LEN; + unsigned long siglen2 = DSA_SIGNATURE_LEN/2; + + PK11_SESSION *sp = NULL; + + if (BN_is_zero(sig->r) || sig->r->neg || BN_ucmp(sig->r, dsa->q) >= 0) + { + PK11err(PK11_F_DSA_VERIFY, + PK11_R_INVALID_DSA_SIGNATURE_R); + goto ret; + } + + if (BN_is_zero(sig->s) || sig->s->neg || BN_ucmp(sig->s, dsa->q) >= 0) + { + PK11err(PK11_F_DSA_VERIFY, + PK11_R_INVALID_DSA_SIGNATURE_S); + goto ret; + } + + i = BN_num_bytes(dsa->q); /* should be 20 */ + + if (dlen > i) + { + PK11err(PK11_F_DSA_VERIFY, + PK11_R_INVALID_SIGNATURE_LENGTH); + goto ret; + } + + if ((sp = pk11_get_session(OP_DSA)) == NULL) + goto ret; + + (void) check_new_dsa_key_pub(sp, dsa); + + h_pub_key = sp->opdata_dsa_pub_key; + if (h_pub_key == CK_INVALID_HANDLE) + h_pub_key = sp->opdata_dsa_pub_key = + pk11_get_public_dsa_key((DSA *)dsa, &sp->opdata_dsa_pub, + &sp->opdata_dsa_pub_num, sp->session); + + if (h_pub_key != CK_INVALID_HANDLE) + { + rv = pFuncList->C_VerifyInit(sp->session, p_mech, + h_pub_key); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DSA_VERIFY, PK11_R_VERIFYINIT, + rv); + goto ret; + } + + /* + * The representation of each of the two big numbers could + * be shorter than DSA_SIGNATURE_LEN/2 bytes so we need + * to act accordingly and shift if necessary. + */ + (void) memset(sigbuf, 0, siglen); + BN_bn2bin(sig->r, sigbuf + siglen2 - BN_num_bytes(sig->r)); + BN_bn2bin(sig->s, &sigbuf[siglen2] + siglen2 - + BN_num_bytes(sig->s)); + + rv = pFuncList->C_Verify(sp->session, + (unsigned char *) dgst, dlen, sigbuf, (CK_ULONG)siglen); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DSA_VERIFY, PK11_R_VERIFY, rv); + goto ret; + } + } + + retval = 1; +ret: + + pk11_return_session(sp, OP_DSA); + return (retval); + } + + +/* + * Create a public key object in a session from a given dsa structure. + * The *dsa_pub_num pointer is non-NULL for DSA public keys. + */ +static CK_OBJECT_HANDLE pk11_get_public_dsa_key(DSA* dsa, + DSA **key_ptr, BIGNUM **dsa_pub_num, CK_SESSION_HANDLE session) + { + CK_RV rv; + CK_OBJECT_CLASS o_key = CKO_PUBLIC_KEY; + CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE; + CK_ULONG found; + CK_KEY_TYPE k_type = CKK_DSA; + CK_ULONG ul_key_attr_count = 8; + CK_BBOOL rollback = FALSE; + int i; + + CK_ATTRIBUTE a_key_template[] = + { + {CKA_CLASS, (void *) NULL, sizeof (CK_OBJECT_CLASS)}, + {CKA_KEY_TYPE, (void *) NULL, sizeof (CK_KEY_TYPE)}, + {CKA_TOKEN, &myfalse, sizeof (myfalse)}, + {CKA_VERIFY, &mytrue, sizeof (mytrue)}, + {CKA_PRIME, (void *)NULL, 0}, /* p */ + {CKA_SUBPRIME, (void *)NULL, 0}, /* q */ + {CKA_BASE, (void *)NULL, 0}, /* g */ + {CKA_VALUE, (void *)NULL, 0} /* pub_key - y */ + }; + + a_key_template[0].pValue = &o_key; + a_key_template[1].pValue = &k_type; + + if (init_template_value(dsa->p, &a_key_template[4].pValue, + &a_key_template[4].ulValueLen) == 0 || + init_template_value(dsa->q, &a_key_template[5].pValue, + &a_key_template[5].ulValueLen) == 0 || + init_template_value(dsa->g, &a_key_template[6].pValue, + &a_key_template[6].ulValueLen) == 0 || + init_template_value(dsa->pub_key, &a_key_template[7].pValue, + &a_key_template[7].ulValueLen) == 0) + { + PK11err(PK11_F_GET_PUB_DSA_KEY, PK11_R_MALLOC_FAILURE); + goto malloc_err; + } + + /* see find_lock array definition for more info on object locking */ + LOCK_OBJSTORE(OP_DSA); + rv = pFuncList->C_FindObjectsInit(session, a_key_template, + ul_key_attr_count); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PUB_DSA_KEY, + PK11_R_FINDOBJECTSINIT, rv); + goto err; + } + + rv = pFuncList->C_FindObjects(session, &h_key, 1, &found); + + if (rv != CKR_OK) + { + (void) pFuncList->C_FindObjectsFinal(session); + PK11err_add_data(PK11_F_GET_PUB_DSA_KEY, + PK11_R_FINDOBJECTS, rv); + goto err; + } + + rv = pFuncList->C_FindObjectsFinal(session); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PUB_DSA_KEY, + PK11_R_FINDOBJECTSFINAL, rv); + goto err; + } + + if (found == 0) + { + rv = pFuncList->C_CreateObject(session, + a_key_template, ul_key_attr_count, &h_key); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PUB_DSA_KEY, + PK11_R_CREATEOBJECT, rv); + goto err; + } + } + + if (dsa_pub_num != NULL) + if ((*dsa_pub_num = BN_dup(dsa->pub_key)) == NULL) + { + PK11err(PK11_F_GET_PUB_DSA_KEY, PK11_R_MALLOC_FAILURE); + rollback = TRUE; + goto err; + } + + /* LINTED: E_CONSTANT_CONDITION */ + KEY_HANDLE_REFHOLD(h_key, OP_DSA, FALSE, rollback, err); + if (key_ptr != NULL) + *key_ptr = dsa; + +err: + if (rollback) + { + /* + * We do not care about the return value from C_DestroyObject() + * since we are doing rollback. + */ + if (found == 0) + (void) pFuncList->C_DestroyObject(session, h_key); + h_key = CK_INVALID_HANDLE; + } + + UNLOCK_OBJSTORE(OP_DSA); + +malloc_err: + for (i = 4; i <= 7; i++) + { + if (a_key_template[i].pValue != NULL) + { + OPENSSL_free(a_key_template[i].pValue); + a_key_template[i].pValue = NULL; + } + } + + return (h_key); + } + +/* + * Create a private key object in the session from a given dsa structure + * The *dsa_priv_num pointer is non-NULL for DSA private keys. + */ +static CK_OBJECT_HANDLE pk11_get_private_dsa_key(DSA* dsa, + DSA **key_ptr, BIGNUM **dsa_priv_num, CK_SESSION_HANDLE session) + { + CK_RV rv; + CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE; + CK_OBJECT_CLASS o_key = CKO_PRIVATE_KEY; + int i; + CK_ULONG found; + CK_KEY_TYPE k_type = CKK_DSA; + CK_ULONG ul_key_attr_count = 9; + CK_BBOOL rollback = FALSE; + + /* Both CKA_TOKEN and CKA_SENSITIVE have to be FALSE for session keys */ + CK_ATTRIBUTE a_key_template[] = + { + {CKA_CLASS, (void *) NULL, sizeof (CK_OBJECT_CLASS)}, + {CKA_KEY_TYPE, (void *) NULL, sizeof (CK_KEY_TYPE)}, + {CKA_TOKEN, &myfalse, sizeof (myfalse)}, + {CKA_SENSITIVE, &myfalse, sizeof (myfalse)}, + {CKA_SIGN, &mytrue, sizeof (mytrue)}, + {CKA_PRIME, (void *)NULL, 0}, /* p */ + {CKA_SUBPRIME, (void *)NULL, 0}, /* q */ + {CKA_BASE, (void *)NULL, 0}, /* g */ + {CKA_VALUE, (void *)NULL, 0} /* priv_key - x */ + }; + + a_key_template[0].pValue = &o_key; + a_key_template[1].pValue = &k_type; + + /* Put the private key components into the template */ + if (init_template_value(dsa->p, &a_key_template[5].pValue, + &a_key_template[5].ulValueLen) == 0 || + init_template_value(dsa->q, &a_key_template[6].pValue, + &a_key_template[6].ulValueLen) == 0 || + init_template_value(dsa->g, &a_key_template[7].pValue, + &a_key_template[7].ulValueLen) == 0 || + init_template_value(dsa->priv_key, &a_key_template[8].pValue, + &a_key_template[8].ulValueLen) == 0) + { + PK11err(PK11_F_GET_PRIV_DSA_KEY, PK11_R_MALLOC_FAILURE); + goto malloc_err; + } + + /* see find_lock array definition for more info on object locking */ + LOCK_OBJSTORE(OP_DSA); + rv = pFuncList->C_FindObjectsInit(session, a_key_template, + ul_key_attr_count); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PRIV_DSA_KEY, + PK11_R_FINDOBJECTSINIT, rv); + goto err; + } + + rv = pFuncList->C_FindObjects(session, &h_key, 1, &found); + + if (rv != CKR_OK) + { + (void) pFuncList->C_FindObjectsFinal(session); + PK11err_add_data(PK11_F_GET_PRIV_DSA_KEY, + PK11_R_FINDOBJECTS, rv); + goto err; + } + + rv = pFuncList->C_FindObjectsFinal(session); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PRIV_DSA_KEY, + PK11_R_FINDOBJECTSFINAL, rv); + goto err; + } + + if (found == 0) + { + rv = pFuncList->C_CreateObject(session, + a_key_template, ul_key_attr_count, &h_key); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PRIV_DSA_KEY, + PK11_R_CREATEOBJECT, rv); + goto err; + } + } + + if (dsa_priv_num != NULL) + if ((*dsa_priv_num = BN_dup(dsa->priv_key)) == NULL) + { + PK11err(PK11_F_GET_PRIV_DSA_KEY, PK11_R_MALLOC_FAILURE); + rollback = TRUE; + goto err; + } + + /* LINTED: E_CONSTANT_CONDITION */ + KEY_HANDLE_REFHOLD(h_key, OP_DSA, FALSE, rollback, err); + if (key_ptr != NULL) + *key_ptr = dsa; + +err: + if (rollback) + { + /* + * We do not care about the return value from C_DestroyObject() + * since we are doing rollback. + */ + if (found == 0) + (void) pFuncList->C_DestroyObject(session, h_key); + h_key = CK_INVALID_HANDLE; + } + + UNLOCK_OBJSTORE(OP_DSA); + +malloc_err: + /* + * 5 to 8 entries in the key template are key components. + * They need to be freed apon exit or error. + */ + for (i = 5; i <= 8; i++) + { + if (a_key_template[i].pValue != NULL) + { + (void) memset(a_key_template[i].pValue, 0, + a_key_template[i].ulValueLen); + OPENSSL_free(a_key_template[i].pValue); + a_key_template[i].pValue = NULL; + } + } + + return (h_key); + } + +/* + * Check for cache miss and clean the object pointer and handle + * in such case. Return 1 for cache hit, 0 for cache miss. + */ +static int check_new_dsa_key_pub(PK11_SESSION *sp, DSA *dsa) + { + /* + * Provide protection against DSA structure reuse by making the + * check for cache hit stronger. Only public key component of DSA + * key matters here so it is sufficient to compare it with value + * cached in PK11_SESSION structure. + */ + if ((sp->opdata_dsa_pub != dsa) || + (BN_cmp(sp->opdata_dsa_pub_num, dsa->pub_key) != 0)) + { + /* + * We do not check the return value because even in case of + * failure the sp structure will have both key pointer + * and object handle cleaned and pk11_destroy_object() + * reports the failure to the OpenSSL error message buffer. + */ + (void) pk11_destroy_dsa_object_pub(sp, TRUE); + return (0); + } + return (1); + } + +/* + * Check for cache miss and clean the object pointer and handle + * in such case. Return 1 for cache hit, 0 for cache miss. + */ +static int check_new_dsa_key_priv(PK11_SESSION *sp, DSA *dsa) + { + /* + * Provide protection against DSA structure reuse by making the + * check for cache hit stronger. Only private key component of DSA + * key matters here so it is sufficient to compare it with value + * cached in PK11_SESSION structure. + */ + if ((sp->opdata_dsa_priv != dsa) || + (BN_cmp(sp->opdata_dsa_priv_num, dsa->priv_key) != 0)) + { + /* + * We do not check the return value because even in case of + * failure the sp structure will have both key pointer + * and object handle cleaned and pk11_destroy_object() + * reports the failure to the OpenSSL error message buffer. + */ + (void) pk11_destroy_dsa_object_priv(sp, TRUE); + return (0); + } + return (1); + } +#endif + + +#ifndef OPENSSL_NO_DH +/* The DH function implementation */ +/* ARGSUSED */ +static int pk11_DH_init(DH *dh) + { + return (1); + } + +/* ARGSUSED */ +static int pk11_DH_finish(DH *dh) + { + return (1); + } + +/* + * Generate DH key-pair. + * + * Warning: Unlike OpenSSL's DH_generate_key(3) we ignore dh->priv_key + * and override it even if it is set. OpenSSL does not touch dh->priv_key + * if set and just computes dh->pub_key. It looks like PKCS#11 standard + * is not capable of providing this functionality. This could be a problem + * for applications relying on OpenSSL's semantics. + */ +static int pk11_DH_generate_key(DH *dh) + { + CK_ULONG i; + CK_RV rv, rv1; + int reuse_mem_len = 0, ret = 0; + PK11_SESSION *sp = NULL; + CK_BYTE_PTR reuse_mem; + + CK_MECHANISM mechanism = {CKM_DH_PKCS_KEY_PAIR_GEN, NULL_PTR, 0}; + CK_OBJECT_HANDLE h_pub_key = CK_INVALID_HANDLE; + CK_OBJECT_HANDLE h_priv_key = CK_INVALID_HANDLE; + + CK_ULONG ul_pub_key_attr_count = 3; + CK_ATTRIBUTE pub_key_template[] = + { + {CKA_PRIVATE, &myfalse, sizeof (myfalse)}, + {CKA_PRIME, (void *)NULL, 0}, + {CKA_BASE, (void *)NULL, 0} + }; + + CK_ULONG ul_priv_key_attr_count = 3; + CK_ATTRIBUTE priv_key_template[] = + { + {CKA_PRIVATE, &myfalse, sizeof (myfalse)}, + {CKA_SENSITIVE, &myfalse, sizeof (myfalse)}, + {CKA_DERIVE, &mytrue, sizeof (mytrue)} + }; + + CK_ULONG pub_key_attr_result_count = 1; + CK_ATTRIBUTE pub_key_result[] = + { + {CKA_VALUE, (void *)NULL, 0} + }; + + CK_ULONG priv_key_attr_result_count = 1; + CK_ATTRIBUTE priv_key_result[] = + { + {CKA_VALUE, (void *)NULL, 0} + }; + + pub_key_template[1].ulValueLen = BN_num_bytes(dh->p); + if (pub_key_template[1].ulValueLen > 0) + { + /* + * We must not increase ulValueLen by DH_BUF_RESERVE since that + * could cause the same rounding problem. See definition of + * DH_BUF_RESERVE above. + */ + pub_key_template[1].pValue = + OPENSSL_malloc(pub_key_template[1].ulValueLen + + DH_BUF_RESERVE); + if (pub_key_template[1].pValue == NULL) + { + PK11err(PK11_F_DH_GEN_KEY, PK11_R_MALLOC_FAILURE); + goto err; + } + + i = BN_bn2bin(dh->p, pub_key_template[1].pValue); + } + else + goto err; + + pub_key_template[2].ulValueLen = BN_num_bytes(dh->g); + if (pub_key_template[2].ulValueLen > 0) + { + pub_key_template[2].pValue = + OPENSSL_malloc(pub_key_template[2].ulValueLen + + DH_BUF_RESERVE); + if (pub_key_template[2].pValue == NULL) + { + PK11err(PK11_F_DH_GEN_KEY, PK11_R_MALLOC_FAILURE); + goto err; + } + + i = BN_bn2bin(dh->g, pub_key_template[2].pValue); + } + else + goto err; + + /* + * Note: we are only using PK11_SESSION structure for getting + * a session handle. The objects created in this function are + * destroyed before return and thus not cached. + */ + if ((sp = pk11_get_session(OP_DH)) == NULL) + goto err; + + rv = pFuncList->C_GenerateKeyPair(sp->session, + &mechanism, + pub_key_template, + ul_pub_key_attr_count, + priv_key_template, + ul_priv_key_attr_count, + &h_pub_key, + &h_priv_key); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DH_GEN_KEY, PK11_R_GEN_KEY, rv); + goto err; + } + + /* + * Reuse the larger memory allocated. We know the larger memory + * should be sufficient for reuse. + */ + if (pub_key_template[1].ulValueLen > pub_key_template[2].ulValueLen) + { + reuse_mem = pub_key_template[1].pValue; + reuse_mem_len = pub_key_template[1].ulValueLen + DH_BUF_RESERVE; + } + else + { + reuse_mem = pub_key_template[2].pValue; + reuse_mem_len = pub_key_template[2].ulValueLen + DH_BUF_RESERVE; + } + + rv = pFuncList->C_GetAttributeValue(sp->session, h_pub_key, + pub_key_result, pub_key_attr_result_count); + rv1 = pFuncList->C_GetAttributeValue(sp->session, h_priv_key, + priv_key_result, priv_key_attr_result_count); + + if (rv != CKR_OK || rv1 != CKR_OK) + { + rv = (rv != CKR_OK) ? rv : rv1; + PK11err_add_data(PK11_F_DH_GEN_KEY, + PK11_R_GETATTRIBUTVALUE, rv); + goto err; + } + + if (((CK_LONG) pub_key_result[0].ulValueLen) <= 0 || + ((CK_LONG) priv_key_result[0].ulValueLen) <= 0) + { + PK11err(PK11_F_DH_GEN_KEY, PK11_R_GETATTRIBUTVALUE); + goto err; + } + + /* Reuse the memory allocated */ + pub_key_result[0].pValue = reuse_mem; + pub_key_result[0].ulValueLen = reuse_mem_len; + + rv = pFuncList->C_GetAttributeValue(sp->session, h_pub_key, + pub_key_result, pub_key_attr_result_count); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DH_GEN_KEY, + PK11_R_GETATTRIBUTVALUE, rv); + goto err; + } + + if (pub_key_result[0].type == CKA_VALUE) + { + if (dh->pub_key == NULL) + if ((dh->pub_key = BN_new()) == NULL) + { + PK11err(PK11_F_DH_GEN_KEY, + PK11_R_MALLOC_FAILURE); + goto err; + } + dh->pub_key = BN_bin2bn(pub_key_result[0].pValue, + pub_key_result[0].ulValueLen, dh->pub_key); + if (dh->pub_key == NULL) + { + PK11err(PK11_F_DH_GEN_KEY, PK11_R_MALLOC_FAILURE); + goto err; + } + } + + /* Reuse the memory allocated */ + priv_key_result[0].pValue = reuse_mem; + priv_key_result[0].ulValueLen = reuse_mem_len; + + rv = pFuncList->C_GetAttributeValue(sp->session, h_priv_key, + priv_key_result, priv_key_attr_result_count); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DH_GEN_KEY, + PK11_R_GETATTRIBUTVALUE, rv); + goto err; + } + + if (priv_key_result[0].type == CKA_VALUE) + { + if (dh->priv_key == NULL) + if ((dh->priv_key = BN_new()) == NULL) + { + PK11err(PK11_F_DH_GEN_KEY, + PK11_R_MALLOC_FAILURE); + goto err; + } + dh->priv_key = BN_bin2bn(priv_key_result[0].pValue, + priv_key_result[0].ulValueLen, dh->priv_key); + if (dh->priv_key == NULL) + { + PK11err(PK11_F_DH_GEN_KEY, PK11_R_MALLOC_FAILURE); + goto err; + } + } + + ret = 1; + +err: + + if (h_pub_key != CK_INVALID_HANDLE) + { + rv = pFuncList->C_DestroyObject(sp->session, h_pub_key); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DH_GEN_KEY, + PK11_R_DESTROYOBJECT, rv); + } + } + + if (h_priv_key != CK_INVALID_HANDLE) + { + rv = pFuncList->C_DestroyObject(sp->session, h_priv_key); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DH_GEN_KEY, + PK11_R_DESTROYOBJECT, rv); + } + } + + for (i = 1; i <= 2; i++) + { + if (pub_key_template[i].pValue != NULL) + { + OPENSSL_free(pub_key_template[i].pValue); + pub_key_template[i].pValue = NULL; + } + } + + pk11_return_session(sp, OP_DH); + return (ret); + } + +static int pk11_DH_compute_key(unsigned char *key, const BIGNUM *pub_key, + DH *dh) + { + unsigned int i; + CK_MECHANISM mechanism = {CKM_DH_PKCS_DERIVE, NULL_PTR, 0}; + CK_OBJECT_CLASS key_class = CKO_SECRET_KEY; + CK_KEY_TYPE key_type = CKK_GENERIC_SECRET; + CK_OBJECT_HANDLE h_derived_key = CK_INVALID_HANDLE; + CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE; + + CK_ULONG seclen; + CK_ULONG ul_priv_key_attr_count = 3; + CK_ATTRIBUTE priv_key_template[] = + { + {CKA_CLASS, (void*) NULL, sizeof (key_class)}, + {CKA_KEY_TYPE, (void*) NULL, sizeof (key_type)}, + {CKA_VALUE_LEN, &seclen, sizeof (seclen)}, + }; + + CK_ULONG priv_key_attr_result_count = 1; + CK_ATTRIBUTE priv_key_result[] = + { + {CKA_VALUE, (void *)NULL, 0} + }; + + CK_RV rv; + int ret = -1; + PK11_SESSION *sp = NULL; + + if (dh->priv_key == NULL) + goto err; + + priv_key_template[0].pValue = &key_class; + priv_key_template[1].pValue = &key_type; + seclen = BN_num_bytes(dh->p); + + if ((sp = pk11_get_session(OP_DH)) == NULL) + goto err; + + mechanism.ulParameterLen = BN_num_bytes(pub_key); + mechanism.pParameter = OPENSSL_malloc(mechanism.ulParameterLen); + if (mechanism.pParameter == NULL) + { + PK11err(PK11_F_DH_COMP_KEY, PK11_R_MALLOC_FAILURE); + goto err; + } + BN_bn2bin(pub_key, mechanism.pParameter); + + (void) check_new_dh_key(sp, dh); + + h_key = sp->opdata_dh_key; + if (h_key == CK_INVALID_HANDLE) + h_key = sp->opdata_dh_key = + pk11_get_dh_key((DH*) dh, &sp->opdata_dh, + &sp->opdata_dh_priv_num, sp->session); + + if (h_key == CK_INVALID_HANDLE) + { + PK11err(PK11_F_DH_COMP_KEY, PK11_R_CREATEOBJECT); + goto err; + } + + rv = pFuncList->C_DeriveKey(sp->session, + &mechanism, + h_key, + priv_key_template, + ul_priv_key_attr_count, + &h_derived_key); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DH_COMP_KEY, PK11_R_DERIVEKEY, rv); + goto err; + } + + rv = pFuncList->C_GetAttributeValue(sp->session, h_derived_key, + priv_key_result, priv_key_attr_result_count); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DH_COMP_KEY, PK11_R_GETATTRIBUTVALUE, + rv); + goto err; + } + + if (((CK_LONG) priv_key_result[0].ulValueLen) <= 0) + { + PK11err(PK11_F_DH_COMP_KEY, PK11_R_GETATTRIBUTVALUE); + goto err; + } + priv_key_result[0].pValue = + OPENSSL_malloc(priv_key_result[0].ulValueLen); + if (!priv_key_result[0].pValue) + { + PK11err(PK11_F_DH_COMP_KEY, PK11_R_MALLOC_FAILURE); + goto err; + } + + rv = pFuncList->C_GetAttributeValue(sp->session, h_derived_key, + priv_key_result, priv_key_attr_result_count); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DH_COMP_KEY, PK11_R_GETATTRIBUTVALUE, + rv); + goto err; + } + + /* + * OpenSSL allocates the output buffer 'key' which is the same + * length of the public key. It is long enough for the derived key + */ + if (priv_key_result[0].type == CKA_VALUE) + { + /* + * CKM_DH_PKCS_DERIVE mechanism is not supposed to strip + * leading zeros from a computed shared secret. However, + * OpenSSL always did it so we must do the same here. The + * vagueness of the spec regarding leading zero bytes was + * finally cleared with TLS 1.1 (RFC 4346) saying that leading + * zeros are stripped before the computed data is used as the + * pre-master secret. + */ + for (i = 0; i < priv_key_result[0].ulValueLen; ++i) + { + if (((char *)priv_key_result[0].pValue)[i] != 0) + break; + } + + (void) memcpy(key, ((char *)priv_key_result[0].pValue) + i, + priv_key_result[0].ulValueLen - i); + ret = priv_key_result[0].ulValueLen - i; + } + +err: + + if (h_derived_key != CK_INVALID_HANDLE) + { + rv = pFuncList->C_DestroyObject(sp->session, h_derived_key); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DH_COMP_KEY, + PK11_R_DESTROYOBJECT, rv); + } + } + if (priv_key_result[0].pValue) + { + OPENSSL_free(priv_key_result[0].pValue); + priv_key_result[0].pValue = NULL; + } + + if (mechanism.pParameter) + { + OPENSSL_free(mechanism.pParameter); + mechanism.pParameter = NULL; + } + + pk11_return_session(sp, OP_DH); + return (ret); + } + + +static CK_OBJECT_HANDLE pk11_get_dh_key(DH* dh, + DH **key_ptr, BIGNUM **dh_priv_num, CK_SESSION_HANDLE session) + { + CK_RV rv; + CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE; + CK_OBJECT_CLASS class = CKO_PRIVATE_KEY; + CK_KEY_TYPE key_type = CKK_DH; + CK_ULONG found; + CK_BBOOL rollback = FALSE; + int i; + + CK_ULONG ul_key_attr_count = 7; + CK_ATTRIBUTE key_template[] = + { + {CKA_CLASS, (void*) NULL, sizeof (class)}, + {CKA_KEY_TYPE, (void*) NULL, sizeof (key_type)}, + {CKA_DERIVE, &mytrue, sizeof (mytrue)}, + {CKA_PRIVATE, &myfalse, sizeof (myfalse)}, + {CKA_PRIME, (void *) NULL, 0}, + {CKA_BASE, (void *) NULL, 0}, + {CKA_VALUE, (void *) NULL, 0}, + }; + + key_template[0].pValue = &class; + key_template[1].pValue = &key_type; + + key_template[4].ulValueLen = BN_num_bytes(dh->p); + key_template[4].pValue = (CK_VOID_PTR)OPENSSL_malloc( + (size_t)key_template[4].ulValueLen); + if (key_template[4].pValue == NULL) + { + PK11err(PK11_F_GET_DH_KEY, PK11_R_MALLOC_FAILURE); + goto malloc_err; + } + + BN_bn2bin(dh->p, key_template[4].pValue); + + key_template[5].ulValueLen = BN_num_bytes(dh->g); + key_template[5].pValue = (CK_VOID_PTR)OPENSSL_malloc( + (size_t)key_template[5].ulValueLen); + if (key_template[5].pValue == NULL) + { + PK11err(PK11_F_GET_DH_KEY, PK11_R_MALLOC_FAILURE); + goto malloc_err; + } + + BN_bn2bin(dh->g, key_template[5].pValue); + + key_template[6].ulValueLen = BN_num_bytes(dh->priv_key); + key_template[6].pValue = (CK_VOID_PTR)OPENSSL_malloc( + (size_t)key_template[6].ulValueLen); + if (key_template[6].pValue == NULL) + { + PK11err(PK11_F_GET_DH_KEY, PK11_R_MALLOC_FAILURE); + goto malloc_err; + } + + BN_bn2bin(dh->priv_key, key_template[6].pValue); + + /* see find_lock array definition for more info on object locking */ + LOCK_OBJSTORE(OP_DH); + rv = pFuncList->C_FindObjectsInit(session, key_template, + ul_key_attr_count); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_DH_KEY, PK11_R_FINDOBJECTSINIT, rv); + goto err; + } + + rv = pFuncList->C_FindObjects(session, &h_key, 1, &found); + + if (rv != CKR_OK) + { + (void) pFuncList->C_FindObjectsFinal(session); + PK11err_add_data(PK11_F_GET_DH_KEY, PK11_R_FINDOBJECTS, rv); + goto err; + } + + rv = pFuncList->C_FindObjectsFinal(session); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_DH_KEY, PK11_R_FINDOBJECTSFINAL, + rv); + goto err; + } + + if (found == 0) + { + rv = pFuncList->C_CreateObject(session, + key_template, ul_key_attr_count, &h_key); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_DH_KEY, PK11_R_CREATEOBJECT, + rv); + goto err; + } + } + + if (dh_priv_num != NULL) + if ((*dh_priv_num = BN_dup(dh->priv_key)) == NULL) + { + PK11err(PK11_F_GET_DH_KEY, PK11_R_MALLOC_FAILURE); + rollback = TRUE; + goto err; + } + + /* LINTED: E_CONSTANT_CONDITION */ + KEY_HANDLE_REFHOLD(h_key, OP_DH, FALSE, rollback, err); + if (key_ptr != NULL) + *key_ptr = dh; + +err: + if (rollback) + { + /* + * We do not care about the return value from C_DestroyObject() + * since we are doing rollback. + */ + if (found == 0) + (void) pFuncList->C_DestroyObject(session, h_key); + h_key = CK_INVALID_HANDLE; + } + + UNLOCK_OBJSTORE(OP_DH); + +malloc_err: + for (i = 4; i <= 6; i++) + { + if (key_template[i].pValue != NULL) + { + OPENSSL_free(key_template[i].pValue); + key_template[i].pValue = NULL; + } + } + + return (h_key); + } + +/* + * Check for cache miss and clean the object pointer and handle + * in such case. Return 1 for cache hit, 0 for cache miss. + * + * Note: we rely on pk11_destroy_dh_key_objects() to set sp->opdata_dh + * to CK_INVALID_HANDLE even when it fails to destroy the object. + */ +static int check_new_dh_key(PK11_SESSION *sp, DH *dh) + { + /* + * Provide protection against DH structure reuse by making the + * check for cache hit stronger. Private key component of DH key + * is unique so it is sufficient to compare it with value cached + * in PK11_SESSION structure. + */ + if ((sp->opdata_dh != dh) || + (BN_cmp(sp->opdata_dh_priv_num, dh->priv_key) != 0)) + { + /* + * We do not check the return value because even in case of + * failure the sp structure will have both key pointer + * and object handle cleaned and pk11_destroy_object() + * reports the failure to the OpenSSL error message buffer. + */ + (void) pk11_destroy_dh_object(sp, TRUE); + return (0); + } + return (1); + } +#endif + +/* + * Local function to simplify key template population + * Return 0 -- error, 1 -- no error + */ +static int +init_template_value(BIGNUM *bn, CK_VOID_PTR *p_value, + CK_ULONG *ul_value_len) + { + CK_ULONG len = 0; + + /* + * This function can be used on non-initialized BIGNUMs. It is + * easier to check that here than individually in the callers. + */ + if (bn != NULL) + len = BN_num_bytes(bn); + + if (bn == NULL || len == 0) + return (1); + + *ul_value_len = len; + *p_value = (CK_VOID_PTR)OPENSSL_malloc((size_t)*ul_value_len); + if (*p_value == NULL) + return (0); + + BN_bn2bin(bn, *p_value); + + return (1); + } + +static void +attr_to_BN(CK_ATTRIBUTE_PTR attr, CK_BYTE attr_data[], BIGNUM **bn) + { + if (attr->ulValueLen > 0) + *bn = BN_bin2bn(attr_data, attr->ulValueLen, NULL); + } + +/* + * Find one object in the token. It is an error if we can not find the + * object or if we find more objects based on the template we got. + * Assume object store locked. + * + * Returns: + * 1 OK + * 0 no object or more than 1 object found + */ +static int +find_one_object(PK11_OPTYPE op, CK_SESSION_HANDLE s, + CK_ATTRIBUTE_PTR ptempl, CK_ULONG nattr, CK_OBJECT_HANDLE_PTR pkey) + { + CK_RV rv; + CK_ULONG objcnt; + + if ((rv = pFuncList->C_FindObjectsInit(s, ptempl, nattr)) != CKR_OK) + { + PK11err_add_data(PK11_F_FIND_ONE_OBJECT, + PK11_R_FINDOBJECTSINIT, rv); + return (0); + } + + rv = pFuncList->C_FindObjects(s, pkey, 1, &objcnt); + if (rv != CKR_OK) + { + (void) pFuncList->C_FindObjectsFinal(s); + PK11err_add_data(PK11_F_FIND_ONE_OBJECT, PK11_R_FINDOBJECTS, + rv); + return (0); + } + + (void) pFuncList->C_FindObjectsFinal(s); + + if (objcnt > 1) + { + PK11err(PK11_F_FIND_ONE_OBJECT, + PK11_R_MORE_THAN_ONE_OBJECT_FOUND); + return (0); + } + else if (objcnt == 0) + { + PK11err(PK11_F_FIND_ONE_OBJECT, PK11_R_NO_OBJECT_FOUND); + return (0); + } + return (1); + } + +/* from uri stuff */ + +extern char *pk11_pin; + +static int pk11_get_pin(void); + +static int +pk11_get_pin(void) +{ + char *pin; + + /* The getpassphrase() function is not MT safe. */ +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_lock(token_lock) == 0); +#else + CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); +#endif + pin = getpassphrase("Enter PIN: "); + if (pin == NULL) + { + PK11err(PK11_F_GET_PIN, PK11_R_COULD_NOT_READ_PIN); +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0); +#else + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + return (0); + } + pk11_pin = BUF_strdup(pin); + if (pk11_pin == NULL) + { + PK11err(PK11_F_LOAD_PRIVKEY, PK11_R_MALLOC_FAILURE); +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0); +#else + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + return (0); + } + memset(pin, 0, strlen(pin)); +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0); +#else + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + return (1); + } + +/* + * Log in to the keystore if we are supposed to do that at all. Take care of + * reading and caching the PIN etc. Log in only once even when called from + * multiple threads. + * + * Returns: + * 1 on success + * 0 on failure + */ +static int +pk11_token_login(CK_SESSION_HANDLE session, CK_BBOOL *login_done, + CK_BBOOL is_private) + { + CK_RV rv; + +#if 0 + /* doesn't work on the AEP Keyper??? */ + if ((pubkey_token_flags & CKF_TOKEN_INITIALIZED) == 0) + { + PK11err(PK11_F_TOKEN_LOGIN, + PK11_R_TOKEN_NOT_INITIALIZED); + return (0); + } +#endif + + /* + * If login is required or needed but the PIN has not been + * even initialized we can bail out right now. Note that we + * are supposed to always log in if we are going to access + * private keys. However, we may need to log in even for + * accessing public keys in case that the CKF_LOGIN_REQUIRED + * flag is set. + */ + if (((pubkey_token_flags & CKF_LOGIN_REQUIRED) || + (is_private == CK_TRUE)) && + (~pubkey_token_flags & CKF_USER_PIN_INITIALIZED)) + { + PK11err(PK11_F_TOKEN_LOGIN, PK11_R_TOKEN_PIN_NOT_SET); + return (0); + } + + /* + * Note on locking: it is possible that more than one thread + * gets into pk11_get_pin() so we must deal with that. We + * cannot avoid it since we cannot guard fork() in there with + * a lock because we could end up in a dead lock in the + * child. Why? Remember we are in a multithreaded environment + * so we must lock all mutexes in the prefork function to + * avoid a situation in which a thread that did not call + * fork() held a lock, making future unlocking impossible. We + * lock right before C_Login(). + */ + if ((pubkey_token_flags & CKF_LOGIN_REQUIRED) || + (is_private == CK_TRUE)) + { + if (*login_done == CK_FALSE) + { + if ((pk11_pin == NULL) && (pk11_get_pin() == 0)) + { + PK11err(PK11_F_TOKEN_LOGIN, + PK11_R_TOKEN_PIN_NOT_PROVIDED); + return (0); + } + } + + /* + * Note that what we are logging into is the keystore from + * pubkey_SLOTID because we work with OP_RSA session type here. + * That also means that we can work with only one keystore in + * the engine. + * + * We must make sure we do not try to login more than once. + * Also, see the comment above on locking strategy. + */ + +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_lock(token_lock) == 0); +#else + CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); +#endif + if (*login_done == CK_FALSE) + { + if ((rv = pFuncList->C_Login(session, + CKU_USER, (CK_UTF8CHAR*)pk11_pin, + strlen(pk11_pin))) != CKR_OK) + { + PK11err_add_data(PK11_F_TOKEN_LOGIN, + PK11_R_TOKEN_LOGIN_FAILED, rv); + goto err_locked; + } + + *login_done = CK_TRUE; + + } +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0); +#else + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + } + else + { + /* + * If token does not require login we take it as the + * login was done. + */ + *login_done = CK_TRUE; + } + + return (1); + +err_locked: + if (pk11_pin) { + memset(pk11_pin, 0, strlen(pk11_pin)); + OPENSSL_free((void*)pk11_pin); + } + pk11_pin = NULL; +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0); +#else + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + return (0); + } + +/* + * Log in to the keystore in the child if we were logged in in the + * parent. There are similarities in the code with pk11_token_login() + * but still it is quite different so we need a separate function for + * this. + * + * Note that this function is called under the locked session mutex when fork is + * detected. That means that C_Login() will be called from the child just once. + * + * Returns: + * 1 on success + * 0 on failure + */ +int +pk11_token_relogin(CK_SESSION_HANDLE session) + { + CK_RV rv; + + if ((pk11_pin == NULL) && (pk11_get_pin() == 0)) + return (0); + +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_lock(token_lock) == 0); +#else + CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); +#endif + if ((rv = pFuncList->C_Login(session, CKU_USER, + (CK_UTF8CHAR_PTR)pk11_pin, strlen(pk11_pin))) != CKR_OK) + { + PK11err_add_data(PK11_F_TOKEN_RELOGIN, + PK11_R_TOKEN_LOGIN_FAILED, rv); +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0); +#else + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + return (0); + } +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0); +#else + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + + return (1); + } + +#ifdef OPENSSL_SYS_WIN32 +char *getpassphrase(const char *prompt) + { + static char buf[128]; + HANDLE h; + DWORD cc, mode; + int cnt; + + h = GetStdHandle(STD_INPUT_HANDLE); + fputs(prompt, stderr); + fflush(stderr); + fflush(stdout); + FlushConsoleInputBuffer(h); + GetConsoleMode(h, &mode); + SetConsoleMode(h, ENABLE_PROCESSED_INPUT); + + for (cnt = 0; cnt < sizeof(buf) - 1; cnt++) + { + ReadFile(h, buf + cnt, 1, &cc, NULL); + if (buf[cnt] == '\r') + break; + fputc('*', stdout); + fflush(stderr); + fflush(stdout); + } + + SetConsoleMode(h, mode); + buf[cnt] = '\0'; + fputs("\n", stderr); + return buf; + } +#endif /* OPENSSL_SYS_WIN32 */ +#endif /* OPENSSL_NO_HW_PK11CA */ +#endif /* OPENSSL_NO_HW_PK11 */ +#endif /* OPENSSL_NO_HW */ Index: openssl/crypto/engine/hw_pk11ca.h diff -u /dev/null openssl/crypto/engine/hw_pk11ca.h:1.2.4.2 --- /dev/null Wed Dec 23 16:49:06 2015 +++ openssl/crypto/engine/hw_pk11ca.h Wed Jun 15 21:12:32 2011 @@ -0,0 +1,32 @@ +/* Redefine all pk11/PK11 external symbols to pk11ca/PK11CA */ + +#define token_lock pk11ca_token_lock +#define find_lock pk11ca_find_lock +#define active_list pk11ca_active_list +#define pubkey_token_flags pk11ca_pubkey_token_flags +#define pubkey_SLOTID pk11ca_pubkey_SLOTID +#define ERR_pk11_error ERR_pk11ca_error +#define PK11err_add_data PK11CAerr_add_data +#define pk11_get_session pk11ca_get_session +#define pk11_return_session pk11ca_return_session +#define pk11_active_add pk11ca_active_add +#define pk11_active_delete pk11ca_active_delete +#define pk11_active_remove pk11ca_active_remove +#define pk11_free_active_list pk11ca_free_active_list +#define pk11_destroy_rsa_key_objects pk11ca_destroy_rsa_key_objects +#define pk11_destroy_rsa_object_pub pk11ca_destroy_rsa_object_pub +#define pk11_destroy_rsa_object_priv pk11ca_destroy_rsa_object_priv +#define pk11_load_privkey pk11ca_load_privkey +#define pk11_load_pubkey pk11ca_load_pubkey +#define PK11_RSA PK11CA_RSA +#define pk11_destroy_dsa_key_objects pk11ca_destroy_dsa_key_objects +#define pk11_destroy_dsa_object_pub pk11ca_destroy_dsa_object_pub +#define pk11_destroy_dsa_object_priv pk11ca_destroy_dsa_object_priv +#define PK11_DSA PK11CA_DSA +#define pk11_destroy_dh_key_objects pk11ca_destroy_dh_key_objects +#define pk11_destroy_dh_object pk11ca_destroy_dh_object +#define PK11_DH PK11CA_DH +#define pk11_token_relogin pk11ca_token_relogin +#define pFuncList pk11ca_pFuncList +#define pk11_pin pk11ca_pin +#define ENGINE_load_pk11 ENGINE_load_pk11ca Index: openssl/crypto/engine/hw_pk11so.c diff -u /dev/null openssl/crypto/engine/hw_pk11so.c:1.3.4.3 --- /dev/null Wed Dec 23 16:49:06 2015 +++ openssl/crypto/engine/hw_pk11so.c Fri Oct 4 14:45:25 2013 @@ -0,0 +1,1775 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* crypto/engine/hw_pk11.c */ +/* + * This product includes software developed by the OpenSSL Project for + * use in the OpenSSL Toolkit (http://www.openssl.org/). + * + * This project also referenced hw_pkcs11-0.9.7b.patch written by + * Afchine Madjlessi. + */ +/* + * ==================================================================== + * Copyright (c) 2000-2001 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +/* Modified to keep only RNG and RSA Sign */ + +#ifdef OPENSSL_NO_RSA +#error RSA is disabled +#endif + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef OPENSSL_SYS_WIN32 +typedef int pid_t; +#define getpid() GetCurrentProcessId() +#define NOPTHREADS +#ifndef NULL_PTR +#define NULL_PTR NULL +#endif +#define CK_DEFINE_FUNCTION(returnType, name) \ + returnType __declspec(dllexport) name +#define CK_DECLARE_FUNCTION(returnType, name) \ + returnType __declspec(dllimport) name +#define CK_DECLARE_FUNCTION_POINTER(returnType, name) \ + returnType __declspec(dllimport) (* name) +#else +#include +#include +#include +#endif + +/* Debug mutexes */ +/*#undef DEBUG_MUTEX */ +#define DEBUG_MUTEX + +#ifndef NOPTHREADS +/* for pthread error check on Linuxes */ +#ifdef DEBUG_MUTEX +#define __USE_UNIX98 +#endif +#include +#endif + +#ifndef OPENSSL_NO_HW +#ifndef OPENSSL_NO_HW_PK11 +#ifndef OPENSSL_NO_HW_PK11SO + +/* label for debug messages printed on stderr */ +#define PK11_DBG "PKCS#11 ENGINE DEBUG" +/* prints a lot of debug messages on stderr about slot selection process */ +/*#undef DEBUG_SLOT_SELECTION */ + +#ifndef OPENSSL_NO_DSA +#define OPENSSL_NO_DSA +#endif +#ifndef OPENSSL_NO_DH +#define OPENSSL_NO_DH +#endif + +#ifdef OPENSSL_SYS_WIN32 +#pragma pack(push, cryptoki, 1) +#include "cryptoki.h" +#include "pkcs11.h" +#pragma pack(pop, cryptoki) +#else +#include "cryptoki.h" +#include "pkcs11.h" +#endif +#include "hw_pk11so.h" +#include "hw_pk11_err.c" + +/* + * We use this lock to prevent multiple C_Login()s, guard getpassphrase(), + * uri_struct manipulation, and static token info. All of that is used by the + * RSA keys by reference feature. + */ +#ifndef NOPTHREADS +pthread_mutex_t *token_lock; +#endif + +/* PKCS#11 session caches and their locks for all operation types */ +static PK11_CACHE session_cache[OP_MAX]; + +/* + * We cache the flags so that we do not have to run C_GetTokenInfo() again when + * logging into the token. + */ +CK_FLAGS pubkey_token_flags; + +/* + * As stated in v2.20, 11.7 Object Management Function, in section for + * C_FindObjectsInit(), at most one search operation may be active at a given + * time in a given session. Therefore, C_Find{,Init,Final}Objects() should be + * grouped together to form one atomic search operation. This is already + * ensured by the property of unique PKCS#11 session handle used for each + * PK11_SESSION object. + * + * This is however not the biggest concern - maintaining consistency of the + * underlying object store is more important. The same section of the spec also + * says that one thread can be in the middle of a search operation while another + * thread destroys the object matching the search template which would result in + * invalid handle returned from the search operation. + * + * Hence, the following locks are used for both protection of the object stores. + * They are also used for active list protection. + */ +#ifndef NOPTHREADS +pthread_mutex_t *find_lock[OP_MAX] = { NULL }; +#endif + +/* + * lists of asymmetric key handles which are active (referenced by at least one + * PK11_SESSION structure, either held by a thread or present in free_session + * list) for given algorithm type + */ +PK11_active *active_list[OP_MAX] = { NULL }; + +/* + * Create all secret key objects in a global session so that they are available + * to use for other sessions. These other sessions may be opened or closed + * without losing the secret key objects. + */ +static CK_SESSION_HANDLE global_session = CK_INVALID_HANDLE; + +/* ENGINE level stuff */ +static int pk11_init(ENGINE *e); +static int pk11_library_init(ENGINE *e); +static int pk11_finish(ENGINE *e); +static int pk11_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void)); +static int pk11_destroy(ENGINE *e); + +/* RAND stuff */ +static void pk11_rand_seed(const void *buf, int num); +static void pk11_rand_add(const void *buf, int num, double add_entropy); +static void pk11_rand_cleanup(void); +static int pk11_rand_bytes(unsigned char *buf, int num); +static int pk11_rand_status(void); + +/* These functions are also used in other files */ +PK11_SESSION *pk11_get_session(PK11_OPTYPE optype); +void pk11_return_session(PK11_SESSION *sp, PK11_OPTYPE optype); + +/* active list manipulation functions used in this file */ +extern int pk11_active_delete(CK_OBJECT_HANDLE h, PK11_OPTYPE type); +extern void pk11_free_active_list(PK11_OPTYPE type); + +int pk11_destroy_rsa_key_objects(PK11_SESSION *session); +int pk11_destroy_rsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock); +int pk11_destroy_rsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock); + +/* Local helper functions */ +static int pk11_free_all_sessions(void); +static int pk11_free_session_list(PK11_OPTYPE optype); +static int pk11_setup_session(PK11_SESSION *sp, PK11_OPTYPE optype); +static int pk11_destroy_object(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE oh, + CK_BBOOL persistent); +static const char *get_PK11_LIBNAME(void); +static void free_PK11_LIBNAME(void); +static long set_PK11_LIBNAME(const char *name); + +static int pk11_choose_slots(int *any_slot_found); + +static int pk11_init_all_locks(void); +static void pk11_free_all_locks(void); + +#define TRY_OBJ_DESTROY(sp, obj_hdl, retval, uselock, alg_type, priv) \ + { \ + if (uselock) \ + LOCK_OBJSTORE(alg_type); \ + if (pk11_active_delete(obj_hdl, alg_type) == 1) \ + { \ + retval = pk11_destroy_object(sp->session, obj_hdl, \ + priv ? sp->priv_persistent : sp->pub_persistent); \ + } \ + if (uselock) \ + UNLOCK_OBJSTORE(alg_type); \ + } + +static CK_BBOOL pk11_have_rsa = CK_FALSE; +static CK_BBOOL pk11_have_random = CK_FALSE; + +/* + * Initialization function. Sets up various PKCS#11 library components. + * The definitions for control commands specific to this engine + */ +#define PK11_CMD_SO_PATH ENGINE_CMD_BASE +#define PK11_CMD_PIN (ENGINE_CMD_BASE+1) +#define PK11_CMD_SLOT (ENGINE_CMD_BASE+2) +static const ENGINE_CMD_DEFN pk11_cmd_defns[] = + { + { + PK11_CMD_SO_PATH, + "SO_PATH", + "Specifies the path to the 'pkcs#11' shared library", + ENGINE_CMD_FLAG_STRING + }, + { + PK11_CMD_PIN, + "PIN", + "Specifies the pin code", + ENGINE_CMD_FLAG_STRING + }, + { + PK11_CMD_SLOT, + "SLOT", + "Specifies the slot (default is auto select)", + ENGINE_CMD_FLAG_NUMERIC, + }, + {0, NULL, NULL, 0} + }; + + +static RAND_METHOD pk11_random = + { + pk11_rand_seed, + pk11_rand_bytes, + pk11_rand_cleanup, + pk11_rand_add, + pk11_rand_bytes, + pk11_rand_status + }; + + +/* Constants used when creating the ENGINE */ +#ifdef OPENSSL_NO_HW_PK11CA +#error "can't load both crypto-accelerator and sign-only PKCS#11 engines" +#endif +static const char *engine_pk11_id = "pkcs11"; +static const char *engine_pk11_name = "PKCS #11 engine support (sign only)"; + +CK_FUNCTION_LIST_PTR pFuncList = NULL; +static const char PK11_GET_FUNCTION_LIST[] = "C_GetFunctionList"; + +/* + * This is a static string constant for the DSO file name and the function + * symbol names to bind to. We set it in the Configure script based on whether + * this is 32 or 64 bit build. + */ +static const char def_PK11_LIBNAME[] = PK11_LIB_LOCATION; + +/* Needed in hw_pk11_pub.c as well so that's why it is not static. */ +CK_SLOT_ID pubkey_SLOTID = 0; +static CK_SLOT_ID rand_SLOTID = 0; +static CK_SLOT_ID SLOTID = 0; +char *pk11_pin = NULL; +static CK_BBOOL pk11_library_initialized = FALSE; +static CK_BBOOL pk11_atfork_initialized = FALSE; +static int pk11_pid = 0; + +static DSO *pk11_dso = NULL; + +/* allocate and initialize all locks used by the engine itself */ +static int pk11_init_all_locks(void) + { +#ifndef NOPTHREADS + int type; + pthread_mutexattr_t attr; + + if (pthread_mutexattr_init(&attr) != 0) + { + PK11err(PK11_F_INIT_ALL_LOCKS, 100); + return (0); + } + +#ifdef DEBUG_MUTEX + if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK) != 0) + { + PK11err(PK11_F_INIT_ALL_LOCKS, 101); + return (0); + } +#endif + + if ((token_lock = OPENSSL_malloc(sizeof (pthread_mutex_t))) == NULL) + goto malloc_err; + (void) pthread_mutex_init(token_lock, &attr); + + find_lock[OP_RSA] = OPENSSL_malloc(sizeof (pthread_mutex_t)); + if (find_lock[OP_RSA] == NULL) + goto malloc_err; + (void) pthread_mutex_init(find_lock[OP_RSA], &attr); + + for (type = 0; type < OP_MAX; type++) + { + session_cache[type].lock = + OPENSSL_malloc(sizeof (pthread_mutex_t)); + if (session_cache[type].lock == NULL) + goto malloc_err; + (void) pthread_mutex_init(session_cache[type].lock, &attr); + } + + return (1); + +malloc_err: + pk11_free_all_locks(); + PK11err(PK11_F_INIT_ALL_LOCKS, PK11_R_MALLOC_FAILURE); + return (0); +#else + return (1); +#endif + } + +static void pk11_free_all_locks(void) + { +#ifndef NOPTHREADS + int type; + + if (token_lock != NULL) + { + (void) pthread_mutex_destroy(token_lock); + OPENSSL_free(token_lock); + token_lock = NULL; + } + + if (find_lock[OP_RSA] != NULL) + { + (void) pthread_mutex_destroy(find_lock[OP_RSA]); + OPENSSL_free(find_lock[OP_RSA]); + find_lock[OP_RSA] = NULL; + } + + for (type = 0; type < OP_MAX; type++) + { + if (session_cache[type].lock != NULL) + { + (void) pthread_mutex_destroy(session_cache[type].lock); + OPENSSL_free(session_cache[type].lock); + session_cache[type].lock = NULL; + } + } +#endif + } + +/* + * This internal function is used by ENGINE_pk11() and "dynamic" ENGINE support. + */ +static int bind_pk11(ENGINE *e) + { + if (!pk11_library_initialized) + if (!pk11_library_init(e)) + return (0); + + if (!ENGINE_set_id(e, engine_pk11_id) || + !ENGINE_set_name(e, engine_pk11_name)) + return (0); + + if (pk11_have_rsa == CK_TRUE) + { + if (!ENGINE_set_RSA(e, PK11_RSA()) || + !ENGINE_set_load_privkey_function(e, pk11_load_privkey) || + !ENGINE_set_load_pubkey_function(e, pk11_load_pubkey)) + return (0); +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: registered RSA\n", PK11_DBG); +#endif /* DEBUG_SLOT_SELECTION */ + } + + if (pk11_have_random) + { + if (!ENGINE_set_RAND(e, &pk11_random)) + return (0); +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: registered random\n", PK11_DBG); +#endif /* DEBUG_SLOT_SELECTION */ + } + if (!ENGINE_set_init_function(e, pk11_init) || + !ENGINE_set_destroy_function(e, pk11_destroy) || + !ENGINE_set_finish_function(e, pk11_finish) || + !ENGINE_set_ctrl_function(e, pk11_ctrl) || + !ENGINE_set_cmd_defns(e, pk11_cmd_defns)) + return (0); + + /* Ensure the pk11 error handling is set up */ + ERR_load_pk11_strings(); + + return (1); + } + +/* Dynamic engine support is disabled at a higher level for Solaris */ +#ifdef ENGINE_DYNAMIC_SUPPORT +#error "dynamic engine not supported" +static int bind_helper(ENGINE *e, const char *id) + { + if (id && (strcmp(id, engine_pk11_id) != 0)) + return (0); + + if (!bind_pk11(e)) + return (0); + + return (1); + } + +IMPLEMENT_DYNAMIC_CHECK_FN() +IMPLEMENT_DYNAMIC_BIND_FN(bind_helper) + +#else +static ENGINE *engine_pk11(void) + { + ENGINE *ret = ENGINE_new(); + + if (!ret) + return (NULL); + + if (!bind_pk11(ret)) + { + ENGINE_free(ret); + return (NULL); + } + + return (ret); + } + +void +ENGINE_load_pk11(void) + { + ENGINE *e_pk11 = NULL; + + /* + * Do not use dynamic PKCS#11 library on Solaris due to + * security reasons. We will link it in statically. + */ + /* Attempt to load PKCS#11 library */ + if (!pk11_dso) + pk11_dso = DSO_load(NULL, get_PK11_LIBNAME(), NULL, 0); + + if (pk11_dso == NULL) + { + PK11err(PK11_F_LOAD, PK11_R_DSO_FAILURE); + return; + } + + e_pk11 = engine_pk11(); + if (!e_pk11) + { + DSO_free(pk11_dso); + pk11_dso = NULL; + return; + } + + /* + * At this point, the pk11 shared library is either dynamically + * loaded or statically linked in. So, initialize the pk11 + * library before calling ENGINE_set_default since the latter + * needs cipher and digest algorithm information + */ + if (!pk11_library_init(e_pk11)) + { + DSO_free(pk11_dso); + pk11_dso = NULL; + ENGINE_free(e_pk11); + return; + } + + ENGINE_add(e_pk11); + + ENGINE_free(e_pk11); + ERR_clear_error(); + } +#endif /* ENGINE_DYNAMIC_SUPPORT */ + +/* + * These are the static string constants for the DSO file name and + * the function symbol names to bind to. + */ +static const char *PK11_LIBNAME = NULL; + +static const char *get_PK11_LIBNAME(void) + { + if (PK11_LIBNAME) + return (PK11_LIBNAME); + + return (def_PK11_LIBNAME); + } + +static void free_PK11_LIBNAME(void) + { + if (PK11_LIBNAME) + OPENSSL_free((void*)PK11_LIBNAME); + + PK11_LIBNAME = NULL; + } + +static long set_PK11_LIBNAME(const char *name) + { + free_PK11_LIBNAME(); + + return ((PK11_LIBNAME = BUF_strdup(name)) != NULL ? 1 : 0); + } + +/* acquire all engine specific mutexes before fork */ +static void pk11_fork_prepare(void) + { +#ifndef NOPTHREADS + int i; + + if (!pk11_library_initialized) + return; + + LOCK_OBJSTORE(OP_RSA); + OPENSSL_assert(pthread_mutex_lock(token_lock) == 0); + for (i = 0; i < OP_MAX; i++) + { + OPENSSL_assert(pthread_mutex_lock(session_cache[i].lock) == 0); + } +#endif + } + +/* release all engine specific mutexes */ +static void pk11_fork_parent(void) + { +#ifndef NOPTHREADS + int i; + + if (!pk11_library_initialized) + return; + + for (i = OP_MAX - 1; i >= 0; i--) + { + OPENSSL_assert(pthread_mutex_unlock(session_cache[i].lock) == 0); + } + UNLOCK_OBJSTORE(OP_RSA); + OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0); +#endif + } + +/* + * same situation as in parent - we need to unlock all locks to make them + * accessible to all threads. + */ +static void pk11_fork_child(void) + { +#ifndef NOPTHREADS + int i; + + if (!pk11_library_initialized) + return; + + for (i = OP_MAX - 1; i >= 0; i--) + { + OPENSSL_assert(pthread_mutex_unlock(session_cache[i].lock) == 0); + } + UNLOCK_OBJSTORE(OP_RSA); + OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0); +#endif + } + +/* Initialization function for the pk11 engine */ +static int pk11_init(ENGINE *e) +{ + return (pk11_library_init(e)); +} + +static CK_C_INITIALIZE_ARGS pk11_init_args = + { + NULL_PTR, /* CreateMutex */ + NULL_PTR, /* DestroyMutex */ + NULL_PTR, /* LockMutex */ + NULL_PTR, /* UnlockMutex */ + CKF_OS_LOCKING_OK, /* flags */ + NULL_PTR, /* pReserved */ + }; + +/* + * Initialization function. Sets up various PKCS#11 library components. + * It selects a slot based on predefined critiera. In the process, it also + * count how many ciphers and digests to support. Since the cipher and + * digest information is needed when setting default engine, this function + * needs to be called before calling ENGINE_set_default. + */ +/* ARGSUSED */ +static int pk11_library_init(ENGINE *e) + { + CK_C_GetFunctionList p; + CK_RV rv = CKR_OK; + CK_INFO info; + int any_slot_found; + int i; +#ifndef OPENSSL_SYS_WIN32 + struct sigaction sigint_act, sigterm_act, sighup_act; +#endif + + /* + * pk11_library_initialized is set to 0 in pk11_finish() which + * is called from ENGINE_finish(). However, if there is still + * at least one existing functional reference to the engine + * (see engine(3) for more information), pk11_finish() is + * skipped. For example, this can happen if an application + * forgets to clear one cipher context. In case of a fork() + * when the application is finishing the engine so that it can + * be reinitialized in the child, forgotten functional + * reference causes pk11_library_initialized to stay 1. In + * that case we need the PID check so that we properly + * initialize the engine again. + */ + if (pk11_library_initialized) + { + if (pk11_pid == getpid()) + { + return (1); + } + else + { + global_session = CK_INVALID_HANDLE; + /* + * free the locks first to prevent memory leak in case + * the application calls fork() without finishing the + * engine first. + */ + pk11_free_all_locks(); + } + } + + if (pk11_dso == NULL) + { + PK11err(PK11_F_LIBRARY_INIT, PK11_R_DSO_FAILURE); + goto err; + } + + /* get the C_GetFunctionList function from the loaded library */ + p = (CK_C_GetFunctionList)DSO_bind_func(pk11_dso, + PK11_GET_FUNCTION_LIST); + if (!p) + { + PK11err(PK11_F_LIBRARY_INIT, PK11_R_DSO_FAILURE); + goto err; + } + + /* get the full function list from the loaded library */ + rv = p(&pFuncList); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_LIBRARY_INIT, PK11_R_DSO_FAILURE, rv); + goto err; + } + +#ifndef OPENSSL_SYS_WIN32 + /* Not all PKCS#11 library are signal safe! */ + + (void) memset(&sigint_act, 0, sizeof(sigint_act)); + (void) memset(&sigterm_act, 0, sizeof(sigterm_act)); + (void) memset(&sighup_act, 0, sizeof(sighup_act)); + (void) sigaction(SIGINT, NULL, &sigint_act); + (void) sigaction(SIGTERM, NULL, &sigterm_act); + (void) sigaction(SIGHUP, NULL, &sighup_act); +#endif + rv = pFuncList->C_Initialize((CK_VOID_PTR)&pk11_init_args); +#ifndef OPENSSL_SYS_WIN32 + (void) sigaction(SIGINT, &sigint_act, NULL); + (void) sigaction(SIGTERM, &sigterm_act, NULL); + (void) sigaction(SIGHUP, &sighup_act, NULL); +#endif + if ((rv != CKR_OK) && (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)) + { + PK11err_add_data(PK11_F_LIBRARY_INIT, PK11_R_INITIALIZE, rv); + goto err; + } + + rv = pFuncList->C_GetInfo(&info); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_LIBRARY_INIT, PK11_R_GETINFO, rv); + goto err; + } + + if (pk11_choose_slots(&any_slot_found) == 0) + goto err; + + /* + * The library we use, set in def_PK11_LIBNAME, may not offer any + * slot(s). In that case, we must not proceed but we must not return an + * error. The reason is that applications that try to set up the PKCS#11 + * engine don't exit on error during the engine initialization just + * because no slot was present. + */ + if (any_slot_found == 0) + return (1); + + if (global_session == CK_INVALID_HANDLE) + { + /* Open the global_session for the new process */ + rv = pFuncList->C_OpenSession(SLOTID, CKF_SERIAL_SESSION, + NULL_PTR, NULL_PTR, &global_session); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_LIBRARY_INIT, + PK11_R_OPENSESSION, rv); + goto err; + } + } + + pk11_library_initialized = TRUE; + pk11_pid = getpid(); + /* + * if initialization of the locks fails pk11_init_all_locks() + * will do the cleanup. + */ + if (!pk11_init_all_locks()) + goto err; + for (i = 0; i < OP_MAX; i++) + session_cache[i].head = NULL; + /* + * initialize active lists. We only use active lists + * for asymmetric ciphers. + */ + for (i = 0; i < OP_MAX; i++) + active_list[i] = NULL; + +#ifndef NOPTHREADS + if (!pk11_atfork_initialized) + { + if (pthread_atfork(pk11_fork_prepare, pk11_fork_parent, + pk11_fork_child) != 0) + { + PK11err(PK11_F_LIBRARY_INIT, PK11_R_ATFORK_FAILED); + goto err; + } + pk11_atfork_initialized = TRUE; + } +#endif + + return (1); + +err: + return (0); + } + +/* Destructor (complements the "ENGINE_pk11()" constructor) */ +/* ARGSUSED */ +static int pk11_destroy(ENGINE *e) + { + free_PK11_LIBNAME(); + ERR_unload_pk11_strings(); + if (pk11_pin) { + memset(pk11_pin, 0, strlen(pk11_pin)); + OPENSSL_free((void*)pk11_pin); + } + pk11_pin = NULL; + return (1); + } + +/* + * Termination function to clean up the session, the token, and the pk11 + * library. + */ +/* ARGSUSED */ +static int pk11_finish(ENGINE *e) + { + int i; + + if (pk11_pin) { + memset(pk11_pin, 0, strlen(pk11_pin)); + OPENSSL_free((void*)pk11_pin); + } + pk11_pin = NULL; + + if (pk11_dso == NULL) + { + PK11err(PK11_F_FINISH, PK11_R_NOT_LOADED); + goto err; + } + + OPENSSL_assert(pFuncList != NULL); + + if (pk11_free_all_sessions() == 0) + goto err; + + /* free all active lists */ + for (i = 0; i < OP_MAX; i++) + pk11_free_active_list(i); + + pFuncList->C_CloseSession(global_session); + global_session = CK_INVALID_HANDLE; + + /* + * Since we are part of a library (libcrypto.so), calling this function + * may have side-effects. + */ +#if 0 + pFuncList->C_Finalize(NULL); +#endif + + if (!DSO_free(pk11_dso)) + { + PK11err(PK11_F_FINISH, PK11_R_DSO_FAILURE); + goto err; + } + pk11_dso = NULL; + pFuncList = NULL; + pk11_library_initialized = FALSE; + pk11_pid = 0; + /* + * There is no way how to unregister atfork handlers (other than + * unloading the library) so we just free the locks. For this reason + * the atfork handlers check if the engine is initialized and bail out + * immediately if not. This is necessary in case a process finishes + * the engine before calling fork(). + */ + pk11_free_all_locks(); + + return (1); + +err: + return (0); + } + +/* Standard engine interface function to set the dynamic library path */ +/* ARGSUSED */ +static int pk11_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void)) + { + int initialized = ((pk11_dso == NULL) ? 0 : 1); + + switch (cmd) + { + case PK11_CMD_SO_PATH: + if (p == NULL) + { + PK11err(PK11_F_CTRL, ERR_R_PASSED_NULL_PARAMETER); + return (0); + } + + if (initialized) + { + PK11err(PK11_F_CTRL, PK11_R_ALREADY_LOADED); + return (0); + } + + return (set_PK11_LIBNAME((const char *)p)); + case PK11_CMD_PIN: + if (pk11_pin) { + memset(pk11_pin, 0, strlen(pk11_pin)); + OPENSSL_free((void*)pk11_pin); + } + pk11_pin = NULL; + + if (p == NULL) + { + PK11err(PK11_F_CTRL, ERR_R_PASSED_NULL_PARAMETER); + return (0); + } + + pk11_pin = BUF_strdup(p); + if (pk11_pin == NULL) + { + PK11err(PK11_F_GET_SESSION, PK11_R_MALLOC_FAILURE); + return (0); + } + return (1); + case PK11_CMD_SLOT: + SLOTID = (CK_SLOT_ID)i; +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: slot set\n", PK11_DBG); +#endif + return (1); + default: + break; + } + + PK11err(PK11_F_CTRL, PK11_R_CTRL_COMMAND_NOT_IMPLEMENTED); + + return (0); + } + + +/* Required function by the engine random interface. It does nothing here */ +static void pk11_rand_cleanup(void) + { + return; + } + +/* ARGSUSED */ +static void pk11_rand_add(const void *buf, int num, double add) + { + PK11_SESSION *sp; + + if ((sp = pk11_get_session(OP_RAND)) == NULL) + return; + + /* + * Ignore any errors (e.g. CKR_RANDOM_SEED_NOT_SUPPORTED) since + * the calling functions do not care anyway + */ + pFuncList->C_SeedRandom(sp->session, (unsigned char *) buf, num); + pk11_return_session(sp, OP_RAND); + + return; + } + +static void pk11_rand_seed(const void *buf, int num) + { + pk11_rand_add(buf, num, 0); + } + +static int pk11_rand_bytes(unsigned char *buf, int num) + { + CK_RV rv; + PK11_SESSION *sp; + + if ((sp = pk11_get_session(OP_RAND)) == NULL) + return (0); + + rv = pFuncList->C_GenerateRandom(sp->session, buf, num); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_RAND_BYTES, PK11_R_GENERATERANDOM, rv); + pk11_return_session(sp, OP_RAND); + return (0); + } + + pk11_return_session(sp, OP_RAND); + return (1); + } + +/* Required function by the engine random interface. It does nothing here */ +static int pk11_rand_status(void) + { + return (1); + } + +/* Free all BIGNUM structures from PK11_SESSION. */ +static void pk11_free_nums(PK11_SESSION *sp, PK11_OPTYPE optype) + { + switch (optype) + { + case OP_RSA: + if (sp->opdata_rsa_n_num != NULL) + { + BN_free(sp->opdata_rsa_n_num); + sp->opdata_rsa_n_num = NULL; + } + if (sp->opdata_rsa_e_num != NULL) + { + BN_free(sp->opdata_rsa_e_num); + sp->opdata_rsa_e_num = NULL; + } + if (sp->opdata_rsa_pn_num != NULL) + { + BN_free(sp->opdata_rsa_pn_num); + sp->opdata_rsa_pn_num = NULL; + } + if (sp->opdata_rsa_pe_num != NULL) + { + BN_free(sp->opdata_rsa_pe_num); + sp->opdata_rsa_pe_num = NULL; + } + if (sp->opdata_rsa_d_num != NULL) + { + BN_free(sp->opdata_rsa_d_num); + sp->opdata_rsa_d_num = NULL; + } + break; + default: + break; + } + } + +/* + * Get new PK11_SESSION structure ready for use. Every process must have + * its own freelist of PK11_SESSION structures so handle fork() here + * by destroying the old and creating new freelist. + * The returned PK11_SESSION structure is disconnected from the freelist. + */ +PK11_SESSION * +pk11_get_session(PK11_OPTYPE optype) + { + PK11_SESSION *sp = NULL, *sp1, *freelist; +#ifndef NOPTHREADS + pthread_mutex_t *freelist_lock = NULL; +#endif + static pid_t pid = 0; + pid_t new_pid; + CK_RV rv; + + switch (optype) + { + case OP_RSA: + case OP_DSA: + case OP_DH: + case OP_RAND: + case OP_DIGEST: + case OP_CIPHER: +#ifndef NOPTHREADS + freelist_lock = session_cache[optype].lock; +#endif + break; + default: + PK11err(PK11_F_GET_SESSION, + PK11_R_INVALID_OPERATION_TYPE); + return (NULL); + } +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_lock(freelist_lock) == 0); +#else + CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); +#endif + + /* + * Will use it to find out if we forked. We cannot use the PID field in + * the session structure because we could get a newly allocated session + * here, with no PID information. + */ + if (pid == 0) + pid = getpid(); + + freelist = session_cache[optype].head; + sp = freelist; + + /* + * If the free list is empty, allocate new unitialized (filled + * with zeroes) PK11_SESSION structure otherwise return first + * structure from the freelist. + */ + if (sp == NULL) + { + if ((sp = OPENSSL_malloc(sizeof (PK11_SESSION))) == NULL) + { + PK11err(PK11_F_GET_SESSION, + PK11_R_MALLOC_FAILURE); + goto err; + } + (void) memset(sp, 0, sizeof (PK11_SESSION)); + + /* + * It is a new session so it will look like a cache miss to the + * code below. So, we must not try to to destroy its members so + * mark them as unused. + */ + sp->opdata_rsa_priv_key = CK_INVALID_HANDLE; + sp->opdata_rsa_pub_key = CK_INVALID_HANDLE; + } + else + { + freelist = sp->next; + } + + /* + * Check whether we have forked. In that case, we must get rid of all + * inherited sessions and start allocating new ones. + */ + if (pid != (new_pid = getpid())) + { + pid = new_pid; + + /* + * We are a new process and thus need to free any inherited + * PK11_SESSION objects aside from the first session (sp) which + * is the only PK11_SESSION structure we will reuse (for the + * head of the list). + */ + while ((sp1 = freelist) != NULL) + { + freelist = sp1->next; + /* + * NOTE: we do not want to call pk11_free_all_sessions() + * here because it would close underlying PKCS#11 + * sessions and destroy all objects. + */ + pk11_free_nums(sp1, optype); + OPENSSL_free(sp1); + } + + /* we have to free the active list as well. */ + pk11_free_active_list(optype); + + /* Initialize the process */ + rv = pFuncList->C_Initialize((CK_VOID_PTR)&pk11_init_args); + if ((rv != CKR_OK) && (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)) + { + PK11err_add_data(PK11_F_GET_SESSION, PK11_R_INITIALIZE, + rv); + OPENSSL_free(sp); + sp = NULL; + goto err; + } + + /* + * Choose slot here since the slot table is different on this + * process. If we are here then we must have found at least one + * usable slot before so we don't need to check any_slot_found. + * See pk11_library_init()'s usage of this function for more + * information. + */ + if (pk11_choose_slots(NULL) == 0) + goto err; + + /* Open the global_session for the new process */ + rv = pFuncList->C_OpenSession(SLOTID, CKF_SERIAL_SESSION, + NULL_PTR, NULL_PTR, &global_session); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_SESSION, PK11_R_OPENSESSION, + rv); + OPENSSL_free(sp); + sp = NULL; + goto err; + } + + /* + * It is an inherited session from our parent so it needs + * re-initialization. + */ + if (pk11_setup_session(sp, optype) == 0) + { + OPENSSL_free(sp); + sp = NULL; + goto err; + } + if (pk11_token_relogin(sp->session) == 0) + { + /* + * We will keep the session in the cache list and let + * the caller cope with the situation. + */ + freelist = sp; + sp = NULL; + goto err; + } + } + + if (sp->pid == 0) + { + /* It is a new session and needs initialization. */ + if (pk11_setup_session(sp, optype) == 0) + { + OPENSSL_free(sp); + sp = NULL; + } + } + + /* set new head for the list of PK11_SESSION objects */ + session_cache[optype].head = freelist; + +err: + if (sp != NULL) + sp->next = NULL; + +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_unlock(freelist_lock) == 0); +#else + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + + return (sp); + } + + +void +pk11_return_session(PK11_SESSION *sp, PK11_OPTYPE optype) + { +#ifndef NOPTHREADS + pthread_mutex_t *freelist_lock; +#endif + PK11_SESSION *freelist; + + /* + * If this is a session from the parent it will be taken care of and + * freed in pk11_get_session() as part of the post-fork clean up the + * next time we will ask for a new session. + */ + if (sp == NULL || sp->pid != getpid()) + return; + + switch (optype) + { + case OP_RSA: + case OP_DSA: + case OP_DH: + case OP_RAND: + case OP_DIGEST: + case OP_CIPHER: +#ifndef NOPTHREADS + freelist_lock = session_cache[optype].lock; +#endif + break; + default: + PK11err(PK11_F_RETURN_SESSION, + PK11_R_INVALID_OPERATION_TYPE); + return; + } + +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_lock(freelist_lock) == 0); +#else + CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); +#endif + freelist = session_cache[optype].head; + sp->next = freelist; + session_cache[optype].head = sp; +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_unlock(freelist_lock) == 0); +#else + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + } + + +/* Destroy all objects. This function is called when the engine is finished */ +static int pk11_free_all_sessions() + { + int ret = 1; + int type; + + (void) pk11_destroy_rsa_key_objects(NULL); + + /* + * We try to release as much as we can but any error means that we will + * return 0 on exit. + */ + for (type = 0; type < OP_MAX; type++) + { + if (pk11_free_session_list(type) == 0) + ret = 0; + } + + return (ret); + } + +/* + * Destroy session structures from the linked list specified. Free as many + * sessions as possible but any failure in C_CloseSession() means that we + * return an error on return. + */ +static int pk11_free_session_list(PK11_OPTYPE optype) + { + CK_RV rv; + PK11_SESSION *sp = NULL; + PK11_SESSION *freelist = NULL; + pid_t mypid = getpid(); +#ifndef NOPTHREADS + pthread_mutex_t *freelist_lock; +#endif + int ret = 1; + + switch (optype) + { + case OP_RSA: + case OP_DSA: + case OP_DH: + case OP_RAND: + case OP_DIGEST: + case OP_CIPHER: +#ifndef NOPTHREADS + freelist_lock = session_cache[optype].lock; +#endif + break; + default: + PK11err(PK11_F_FREE_ALL_SESSIONS, + PK11_R_INVALID_OPERATION_TYPE); + return (0); + } + +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_lock(freelist_lock) == 0); +#else + CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); +#endif + freelist = session_cache[optype].head; + while ((sp = freelist) != NULL) + { + if (sp->session != CK_INVALID_HANDLE && sp->pid == mypid) + { + rv = pFuncList->C_CloseSession(sp->session); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_FREE_ALL_SESSIONS, + PK11_R_CLOSESESSION, rv); + ret = 0; + } + } + freelist = sp->next; + pk11_free_nums(sp, optype); + OPENSSL_free(sp); + } + +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_unlock(freelist_lock) == 0); +#else + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + return (ret); + } + + +static int +pk11_setup_session(PK11_SESSION *sp, PK11_OPTYPE optype) + { + CK_RV rv; + CK_SLOT_ID myslot; + + switch (optype) + { + case OP_RSA: + myslot = pubkey_SLOTID; + break; + case OP_RAND: + myslot = rand_SLOTID; + break; + default: + PK11err(PK11_F_SETUP_SESSION, + PK11_R_INVALID_OPERATION_TYPE); + return (0); + } + + sp->session = CK_INVALID_HANDLE; +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: myslot=%d optype=%d\n", PK11_DBG, myslot, optype); +#endif /* DEBUG_SLOT_SELECTION */ + rv = pFuncList->C_OpenSession(myslot, CKF_SERIAL_SESSION, + NULL_PTR, NULL_PTR, &sp->session); + if (rv == CKR_CRYPTOKI_NOT_INITIALIZED) + { + /* + * We are probably a child process so force the + * reinitialize of the session + */ + pk11_library_initialized = FALSE; + if (!pk11_library_init(NULL)) + return (0); + rv = pFuncList->C_OpenSession(myslot, CKF_SERIAL_SESSION, + NULL_PTR, NULL_PTR, &sp->session); + } + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_SETUP_SESSION, PK11_R_OPENSESSION, rv); + return (0); + } + + sp->pid = getpid(); + + if (optype == OP_RSA) + { + sp->opdata_rsa_pub_key = CK_INVALID_HANDLE; + sp->opdata_rsa_priv_key = CK_INVALID_HANDLE; + sp->opdata_rsa_pub = NULL; + sp->opdata_rsa_n_num = NULL; + sp->opdata_rsa_e_num = NULL; + sp->opdata_rsa_priv = NULL; + sp->opdata_rsa_pn_num = NULL; + sp->opdata_rsa_pe_num = NULL; + sp->opdata_rsa_d_num = NULL; + } + + /* + * We always initialize the session as containing a non-persistent + * object. The key load functions set it to persistent if that is so. + */ + sp->pub_persistent = CK_FALSE; + sp->priv_persistent = CK_FALSE; + return (1); + } + +/* Destroy RSA public key from single session. */ +int +pk11_destroy_rsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock) + { + int ret = 0; + + if (sp->opdata_rsa_pub_key != CK_INVALID_HANDLE) + { + TRY_OBJ_DESTROY(sp, sp->opdata_rsa_pub_key, + ret, uselock, OP_RSA, CK_FALSE); + sp->opdata_rsa_pub_key = CK_INVALID_HANDLE; + sp->opdata_rsa_pub = NULL; + if (sp->opdata_rsa_n_num != NULL) + { + BN_free(sp->opdata_rsa_n_num); + sp->opdata_rsa_n_num = NULL; + } + if (sp->opdata_rsa_e_num != NULL) + { + BN_free(sp->opdata_rsa_e_num); + sp->opdata_rsa_e_num = NULL; + } + } + + return (ret); + } + +/* Destroy RSA private key from single session. */ +int +pk11_destroy_rsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock) + { + int ret = 0; + + if (sp->opdata_rsa_priv_key != CK_INVALID_HANDLE) + { + TRY_OBJ_DESTROY(sp, sp->opdata_rsa_priv_key, + ret, uselock, OP_RSA, CK_TRUE); + sp->opdata_rsa_priv_key = CK_INVALID_HANDLE; + sp->opdata_rsa_priv = NULL; + if (sp->opdata_rsa_d_num != NULL) + { + BN_free(sp->opdata_rsa_d_num); + sp->opdata_rsa_d_num = NULL; + } + + /* + * For the RSA key by reference code, public components 'n'/'e' + * are the key components we use to check for the cache hit. We + * must free those as well. + */ + if (sp->opdata_rsa_pn_num != NULL) + { + BN_free(sp->opdata_rsa_pn_num); + sp->opdata_rsa_pn_num = NULL; + } + if (sp->opdata_rsa_pe_num != NULL) + { + BN_free(sp->opdata_rsa_pe_num); + sp->opdata_rsa_pe_num = NULL; + } + } + + return (ret); + } + +/* + * Destroy RSA key object wrapper. If session is NULL, try to destroy all + * objects in the free list. + */ +int +pk11_destroy_rsa_key_objects(PK11_SESSION *session) + { + int ret = 1; + PK11_SESSION *sp = NULL; + PK11_SESSION *local_free_session; + CK_BBOOL uselock = TRUE; + + if (session != NULL) + local_free_session = session; + else + { +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_lock(session_cache[OP_RSA].lock) == 0); +#else + CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); +#endif + local_free_session = session_cache[OP_RSA].head; + uselock = FALSE; + } + + /* + * go through the list of sessions and delete key objects + */ + while ((sp = local_free_session) != NULL) + { + local_free_session = sp->next; + + /* + * Do not terminate list traversal if one of the + * destroy operations fails. + */ + if (pk11_destroy_rsa_object_pub(sp, uselock) == 0) + { + ret = 0; + continue; + } + if (pk11_destroy_rsa_object_priv(sp, uselock) == 0) + { + ret = 0; + continue; + } + } + +#ifndef NOPTHREADS + if (session == NULL) + OPENSSL_assert(pthread_mutex_unlock(session_cache[OP_RSA].lock) == 0); +#else + if (session == NULL) + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + + return (ret); + } + +static int +pk11_destroy_object(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE oh, + CK_BBOOL persistent) + { + CK_RV rv; + + /* + * We never try to destroy persistent objects which are the objects + * stored in the keystore. Also, we always use read-only sessions so + * C_DestroyObject() would be returning CKR_SESSION_READ_ONLY here. + */ + if (persistent == CK_TRUE) + return (1); + + rv = pFuncList->C_DestroyObject(session, oh); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DESTROY_OBJECT, PK11_R_DESTROYOBJECT, + rv); + return (0); + } + + return (1); + } + + +/* + * Public key mechanisms optionally supported + * + * CKM_RSA_PKCS + * + * The first slot that supports at least one of those mechanisms is chosen as a + * public key slot. + * + * The output of this function is a set of global variables indicating which + * mechanisms from RSA, DSA, DH and RAND are present, and also two arrays of + * mechanisms, one for symmetric ciphers and one for digests. Also, 3 global + * variables carry information about which slot was chosen for (a) public key + * mechanisms, (b) random operations, and (c) symmetric ciphers and digests. + */ +static int +pk11_choose_slots(int *any_slot_found) + { + CK_SLOT_ID_PTR pSlotList = NULL_PTR; + CK_ULONG ulSlotCount = 0; + CK_MECHANISM_INFO mech_info; + CK_TOKEN_INFO token_info; + unsigned int i; + CK_RV rv; + CK_SLOT_ID best_slot_sofar = 0; + CK_BBOOL found_candidate_slot = CK_FALSE; + CK_SLOT_ID current_slot = 0; + + /* let's initialize the output parameter */ + if (any_slot_found != NULL) + *any_slot_found = 0; + + /* Get slot list for memory allocation */ + rv = pFuncList->C_GetSlotList(CK_FALSE, NULL_PTR, &ulSlotCount); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_CHOOSE_SLOT, PK11_R_GETSLOTLIST, rv); + return (0); + } + + /* it's not an error if we didn't find any providers */ + if (ulSlotCount == 0) + { +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: no crypto providers found\n", PK11_DBG); +#endif /* DEBUG_SLOT_SELECTION */ + return (1); + } + + pSlotList = OPENSSL_malloc(ulSlotCount * sizeof (CK_SLOT_ID)); + + if (pSlotList == NULL) + { + PK11err(PK11_F_CHOOSE_SLOT, PK11_R_MALLOC_FAILURE); + return (0); + } + + /* Get the slot list for processing */ + rv = pFuncList->C_GetSlotList(CK_FALSE, pSlotList, &ulSlotCount); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_CHOOSE_SLOT, PK11_R_GETSLOTLIST, rv); + OPENSSL_free(pSlotList); + return (0); + } + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: provider: %s\n", PK11_DBG, def_PK11_LIBNAME); + fprintf(stderr, "%s: number of slots: %d\n", PK11_DBG, ulSlotCount); + + fprintf(stderr, "%s: == checking rand slots ==\n", PK11_DBG); +#endif /* DEBUG_SLOT_SELECTION */ + for (i = 0; i < ulSlotCount; i++) + { + current_slot = pSlotList[i]; + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: checking slot: %d\n", PK11_DBG, i); +#endif /* DEBUG_SLOT_SELECTION */ + /* Check if slot has random support. */ + rv = pFuncList->C_GetTokenInfo(current_slot, &token_info); + if (rv != CKR_OK) + continue; + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: token label: %.32s\n", PK11_DBG, token_info.label); +#endif /* DEBUG_SLOT_SELECTION */ + + if (token_info.flags & CKF_RNG) + { +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: this token has CKF_RNG flag\n", PK11_DBG); +#endif /* DEBUG_SLOT_SELECTION */ + pk11_have_random = CK_TRUE; + rand_SLOTID = current_slot; + break; + } + } + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: == checking pubkey slots ==\n", PK11_DBG); +#endif /* DEBUG_SLOT_SELECTION */ + + pubkey_SLOTID = pSlotList[0]; + for (i = 0; i < ulSlotCount; i++) + { + CK_BBOOL slot_has_rsa = CK_FALSE; + current_slot = pSlotList[i]; + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: checking slot: %d\n", PK11_DBG, i); +#endif /* DEBUG_SLOT_SELECTION */ + rv = pFuncList->C_GetTokenInfo(current_slot, &token_info); + if (rv != CKR_OK) + continue; + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: token label: %.32s\n", PK11_DBG, token_info.label); +#endif /* DEBUG_SLOT_SELECTION */ + + /* + * Check if this slot is capable of signing with CKM_RSA_PKCS. + */ + rv = pFuncList->C_GetMechanismInfo(current_slot, CKM_RSA_PKCS, + &mech_info); + + if (rv == CKR_OK && ((mech_info.flags & CKF_SIGN))) + { + slot_has_rsa = CK_TRUE; + } + + if (!found_candidate_slot && slot_has_rsa) + { +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, + "%s: potential slot: %d\n", PK11_DBG, current_slot); +#endif /* DEBUG_SLOT_SELECTION */ + best_slot_sofar = current_slot; + pk11_have_rsa = slot_has_rsa; + found_candidate_slot = CK_TRUE; + /* + * Cache the flags for later use. We might + * need those if RSA keys by reference feature + * is used. + */ + pubkey_token_flags = token_info.flags; +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, + "%s: setting found_candidate_slot to CK_TRUE\n", + PK11_DBG); + fprintf(stderr, + "%s: best so far slot: %d\n", PK11_DBG, + best_slot_sofar); + fprintf(stderr, "%s: pubkey flags changed to " + "%lu.\n", PK11_DBG, pubkey_token_flags); + } + else + { + fprintf(stderr, + "%s: no rsa\n", PK11_DBG); + } +#else + } /* if */ +#endif /* DEBUG_SLOT_SELECTION */ + } /* for */ + + if (found_candidate_slot == CK_TRUE) + { + pubkey_SLOTID = best_slot_sofar; + } + + /*SLOTID = pSlotList[0];*/ + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, + "%s: chosen pubkey slot: %d\n", PK11_DBG, pubkey_SLOTID); + fprintf(stderr, + "%s: chosen rand slot: %d\n", PK11_DBG, rand_SLOTID); + fprintf(stderr, + "%s: pk11_have_rsa %d\n", PK11_DBG, pk11_have_rsa); + fprintf(stderr, + "%s: pk11_have_random %d\n", PK11_DBG, pk11_have_random); +#endif /* DEBUG_SLOT_SELECTION */ + + if (pSlotList != NULL) + OPENSSL_free(pSlotList); + + if (any_slot_found != NULL) + *any_slot_found = 1; + return (1); + } + +#endif /* OPENSSL_NO_HW_PK11SO */ +#endif /* OPENSSL_NO_HW_PK11 */ +#endif /* OPENSSL_NO_HW */ Index: openssl/crypto/engine/hw_pk11so.h diff -u /dev/null openssl/crypto/engine/hw_pk11so.h:1.2.4.2 --- /dev/null Wed Dec 23 16:49:06 2015 +++ openssl/crypto/engine/hw_pk11so.h Wed Jun 15 21:12:32 2011 @@ -0,0 +1,32 @@ +/* Redefine all pk11/PK11 external symbols to pk11so/PK11SO */ + +#define token_lock pk11so_token_lock +#define find_lock pk11so_find_lock +#define active_list pk11so_active_list +#define pubkey_token_flags pk11so_pubkey_token_flags +#define pubkey_SLOTID pk11so_pubkey_SLOTID +#define ERR_pk11_error ERR_pk11so_error +#define PK11err_add_data PK11SOerr_add_data +#define pk11_get_session pk11so_get_session +#define pk11_return_session pk11so_return_session +#define pk11_active_add pk11so_active_add +#define pk11_active_delete pk11so_active_delete +#define pk11_active_remove pk11so_active_remove +#define pk11_free_active_list pk11so_free_active_list +#define pk11_destroy_rsa_key_objects pk11so_destroy_rsa_key_objects +#define pk11_destroy_rsa_object_pub pk11so_destroy_rsa_object_pub +#define pk11_destroy_rsa_object_priv pk11so_destroy_rsa_object_priv +#define pk11_load_privkey pk11so_load_privkey +#define pk11_load_pubkey pk11so_load_pubkey +#define PK11_RSA PK11SO_RSA +#define pk11_destroy_dsa_key_objects pk11so_destroy_dsa_key_objects +#define pk11_destroy_dsa_object_pub pk11so_destroy_dsa_object_pub +#define pk11_destroy_dsa_object_priv pk11so_destroy_dsa_object_priv +#define PK11_DSA PK11SO_DSA +#define pk11_destroy_dh_key_objects pk11so_destroy_dh_key_objects +#define pk11_destroy_dh_object pk11so_destroy_dh_object +#define PK11_DH PK11SO_DH +#define pk11_token_relogin pk11so_token_relogin +#define pFuncList pk11so_pFuncList +#define pk11_pin pk11so_pin +#define ENGINE_load_pk11 ENGINE_load_pk11so Index: openssl/crypto/engine/hw_pk11so_pub.c diff -u /dev/null openssl/crypto/engine/hw_pk11so_pub.c:1.2.4.6 --- /dev/null Wed Dec 23 16:49:06 2015 +++ openssl/crypto/engine/hw_pk11so_pub.c Fri Oct 4 14:45:25 2013 @@ -0,0 +1,1642 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* crypto/engine/hw_pk11_pub.c */ +/* + * This product includes software developed by the OpenSSL Project for + * use in the OpenSSL Toolkit (http://www.openssl.org/). + * + * This project also referenced hw_pkcs11-0.9.7b.patch written by + * Afchine Madjlessi. + */ +/* + * ==================================================================== + * Copyright (c) 2000-2001 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +/* Modified to keep only RNG and RSA Sign */ + +#ifdef OPENSSL_NO_RSA +#error RSA is disabled +#endif + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef OPENSSL_SYS_WIN32 +#define NOPTHREADS +typedef int pid_t; +#define HAVE_GETPASSPHRASE +static char *getpassphrase(const char *prompt); +#ifndef NULL_PTR +#define NULL_PTR NULL +#endif +#define CK_DEFINE_FUNCTION(returnType, name) \ + returnType __declspec(dllexport) name +#define CK_DECLARE_FUNCTION(returnType, name) \ + returnType __declspec(dllimport) name +#define CK_DECLARE_FUNCTION_POINTER(returnType, name) \ + returnType __declspec(dllimport) (* name) +#else +#include +#endif + +#ifndef NOPTHREADS +#include +#endif + +#ifndef OPENSSL_NO_HW +#ifndef OPENSSL_NO_HW_PK11 +#ifndef OPENSSL_NO_HW_PK11SO + +#ifdef OPENSSL_SYS_WIN32 +#pragma pack(push, cryptoki, 1) +#include "cryptoki.h" +#include "pkcs11.h" +#pragma pack(pop, cryptoki) +#else +#include "cryptoki.h" +#include "pkcs11.h" +#endif +#include "hw_pk11so.h" +#include "hw_pk11_err.h" + +static CK_BBOOL pk11_login_done = CK_FALSE; +extern CK_SLOT_ID pubkey_SLOTID; +#ifndef NOPTHREADS +extern pthread_mutex_t *token_lock; +#endif + +#if !(defined(HAVE_GETPASSPHRASE) || (defined (__SVR4) && defined (__sun))) +#define getpassphrase(x) getpass(x) +#endif + +/* RSA stuff */ +static int pk11_RSA_sign(int type, const unsigned char *m, unsigned int m_len, + unsigned char *sigret, unsigned int *siglen, const RSA *rsa); +EVP_PKEY *pk11_load_privkey(ENGINE*, const char *privkey_file, + UI_METHOD *ui_method, void *callback_data); +EVP_PKEY *pk11_load_pubkey(ENGINE*, const char *pubkey_file, + UI_METHOD *ui_method, void *callback_data); + +static CK_OBJECT_HANDLE pk11_get_public_rsa_key(RSA* rsa, RSA** key_ptr, + BIGNUM **rsa_n_num, BIGNUM **rsa_e_num, CK_SESSION_HANDLE session); +static CK_OBJECT_HANDLE pk11_get_private_rsa_key(RSA* rsa, RSA** key_ptr, + BIGNUM **rsa_d_num, BIGNUM **rsa_n_num, BIGNUM **rsa_e_num, + CK_SESSION_HANDLE session); + +static int check_new_rsa_key_pub(PK11_SESSION *sp, const RSA *rsa); +static int check_new_rsa_key_priv(PK11_SESSION *sp, const RSA *rsa); + +static int find_one_object(PK11_OPTYPE op, CK_SESSION_HANDLE s, + CK_ATTRIBUTE_PTR ptempl, CK_ULONG nattr, CK_OBJECT_HANDLE_PTR pkey); +static int init_template_value(BIGNUM *bn, CK_VOID_PTR *pValue, + CK_ULONG *ulValueLen); +static void attr_to_BN(CK_ATTRIBUTE_PTR attr, CK_BYTE attr_data[], BIGNUM **bn); + +static int pk11_token_login(CK_SESSION_HANDLE session, CK_BBOOL *login_done, + CK_BBOOL is_private); + +/* Read mode string to be used for fopen() */ +#if SOLARIS_OPENSSL +static char *read_mode_flags = "rF"; +#else +static char *read_mode_flags = "r"; +#endif + +/* + * increment/create reference for an asymmetric key handle via active list + * manipulation. If active list operation fails, unlock (if locked), set error + * variable and jump to the specified label. + */ +#define KEY_HANDLE_REFHOLD(key_handle, alg_type, unlock, var, label) \ + { \ + if (pk11_active_add(key_handle, alg_type) < 0) \ + { \ + var = TRUE; \ + if (unlock) \ + UNLOCK_OBJSTORE(alg_type); \ + goto label; \ + } \ + } + +/* + * Find active list entry according to object handle and return pointer to the + * entry otherwise return NULL. + * + * This function presumes it is called with lock protecting the active list + * held. + */ +static PK11_active *pk11_active_find(CK_OBJECT_HANDLE h, PK11_OPTYPE type) + { + PK11_active *entry; + + for (entry = active_list[type]; entry != NULL; entry = entry->next) + if (entry->h == h) + return (entry); + + return (NULL); + } + +/* + * Search for an entry in the active list using PKCS#11 object handle as a + * search key and return refcnt of the found/created entry or -1 in case of + * failure. + * + * This function presumes it is called with lock protecting the active list + * held. + */ +int +pk11_active_add(CK_OBJECT_HANDLE h, PK11_OPTYPE type) + { + PK11_active *entry = NULL; + + if (h == CK_INVALID_HANDLE) + { + PK11err(PK11_F_ACTIVE_ADD, PK11_R_INVALID_HANDLE); + return (-1); + } + + /* search for entry in the active list */ + if ((entry = pk11_active_find(h, type)) != NULL) + entry->refcnt++; + else + { + /* not found, create new entry and add it to the list */ + entry = OPENSSL_malloc(sizeof (PK11_active)); + if (entry == NULL) + { + PK11err(PK11_F_ACTIVE_ADD, PK11_R_MALLOC_FAILURE); + return (-1); + } + entry->h = h; + entry->refcnt = 1; + entry->prev = NULL; + entry->next = NULL; + /* connect the newly created entry to the list */ + if (active_list[type] == NULL) + active_list[type] = entry; + else /* make the entry first in the list */ + { + entry->next = active_list[type]; + active_list[type]->prev = entry; + active_list[type] = entry; + } + } + + return (entry->refcnt); + } + +/* + * Remove active list entry from the list and free it. + * + * This function presumes it is called with lock protecting the active list + * held. + */ +void +pk11_active_remove(PK11_active *entry, PK11_OPTYPE type) + { + PK11_active *prev_entry; + + /* remove the entry from the list and free it */ + if ((prev_entry = entry->prev) != NULL) + { + prev_entry->next = entry->next; + if (entry->next != NULL) + entry->next->prev = prev_entry; + } + else + { + active_list[type] = entry->next; + /* we were the first but not the only one */ + if (entry->next != NULL) + entry->next->prev = NULL; + } + + /* sanitization */ + entry->h = CK_INVALID_HANDLE; + entry->prev = NULL; + entry->next = NULL; + OPENSSL_free(entry); + } + +/* Free all entries from the active list. */ +void +pk11_free_active_list(PK11_OPTYPE type) + { + PK11_active *entry; + + /* only for asymmetric types since only they have C_Find* locks. */ + switch (type) + { + case OP_RSA: + break; + default: + return; + } + + /* see find_lock array definition for more info on object locking */ + LOCK_OBJSTORE(type); + while ((entry = active_list[type]) != NULL) + pk11_active_remove(entry, type); + UNLOCK_OBJSTORE(type); + } + +/* + * Search for active list entry associated with given PKCS#11 object handle, + * decrement its refcnt and if it drops to 0, disconnect the entry and free it. + * + * Return 1 if the PKCS#11 object associated with the entry has no references, + * return 0 if there is at least one reference, -1 on error. + * + * This function presumes it is called with lock protecting the active list + * held. + */ +int +pk11_active_delete(CK_OBJECT_HANDLE h, PK11_OPTYPE type) + { + PK11_active *entry = NULL; + + if ((entry = pk11_active_find(h, type)) == NULL) + { + PK11err(PK11_F_ACTIVE_DELETE, PK11_R_INVALID_HANDLE); + return (-1); + } + + OPENSSL_assert(entry->refcnt > 0); + entry->refcnt--; + if (entry->refcnt == 0) + { + pk11_active_remove(entry, type); + return (1); + } + + return (0); + } + +/* Our internal RSA_METHOD that we provide pointers to */ +static RSA_METHOD pk11_rsa; + +RSA_METHOD * +PK11_RSA(void) + { + const RSA_METHOD *rsa; + + if (pk11_rsa.name == NULL) + { + rsa = RSA_PKCS1_SSLeay(); + memcpy(&pk11_rsa, rsa, sizeof(*rsa)); + pk11_rsa.name = "PKCS#11 RSA method"; + pk11_rsa.rsa_sign = pk11_RSA_sign; + } + return (&pk11_rsa); + } + +/* Size of an SSL signature: MD5+SHA1 */ +#define SSL_SIG_LENGTH 36 + +static CK_BBOOL mytrue = TRUE; +static CK_BBOOL myfalse = FALSE; + +/* + * Standard engine interface function. Majority codes here are from + * rsa/rsa_sign.c. We replaced the decrypt function call by C_Sign of PKCS#11. + * See more details in rsa/rsa_sign.c + */ +static int pk11_RSA_sign(int type, const unsigned char *m, unsigned int m_len, + unsigned char *sigret, unsigned int *siglen, const RSA *rsa) + { + X509_SIG sig; + ASN1_TYPE parameter; + int i, j = 0; + unsigned char *p, *s = NULL; + X509_ALGOR algor; + ASN1_OCTET_STRING digest; + CK_RV rv; + CK_MECHANISM mech_rsa = {CKM_RSA_PKCS, NULL, 0}; + CK_MECHANISM *p_mech = &mech_rsa; + CK_OBJECT_HANDLE h_priv_key; + PK11_SESSION *sp = NULL; + int ret = 0; + unsigned long ulsiglen; + + /* Encode the digest */ + /* Special case: SSL signature, just check the length */ + if (type == NID_md5_sha1) + { + if (m_len != SSL_SIG_LENGTH) + { + PK11err(PK11_F_RSA_SIGN, + PK11_R_INVALID_MESSAGE_LENGTH); + goto err; + } + i = SSL_SIG_LENGTH; + s = (unsigned char *)m; + } + else + { + sig.algor = &algor; + sig.algor->algorithm = OBJ_nid2obj(type); + if (sig.algor->algorithm == NULL) + { + PK11err(PK11_F_RSA_SIGN, + PK11_R_UNKNOWN_ALGORITHM_TYPE); + goto err; + } + if (sig.algor->algorithm->length == 0) + { + PK11err(PK11_F_RSA_SIGN, + PK11_R_UNKNOWN_ASN1_OBJECT_ID); + goto err; + } + parameter.type = V_ASN1_NULL; + parameter.value.ptr = NULL; + sig.algor->parameter = ¶meter; + + sig.digest = &digest; + sig.digest->data = (unsigned char *)m; + sig.digest->length = m_len; + + i = i2d_X509_SIG(&sig, NULL); + } + + j = RSA_size(rsa); + if ((i - RSA_PKCS1_PADDING) > j) + { + PK11err(PK11_F_RSA_SIGN, PK11_R_DIGEST_TOO_BIG); + goto err; + } + + if (type != NID_md5_sha1) + { + s = (unsigned char *)OPENSSL_malloc((unsigned int)(j + 1)); + if (s == NULL) + { + PK11err(PK11_F_RSA_SIGN, PK11_R_MALLOC_FAILURE); + goto err; + } + p = s; + (void) i2d_X509_SIG(&sig, &p); + } + + if ((sp = pk11_get_session(OP_RSA)) == NULL) + goto err; + + (void) check_new_rsa_key_priv(sp, rsa); + + h_priv_key = sp->opdata_rsa_priv_key; + if (h_priv_key == CK_INVALID_HANDLE) + h_priv_key = sp->opdata_rsa_priv_key = + pk11_get_private_rsa_key((RSA *)rsa, + &sp->opdata_rsa_priv, &sp->opdata_rsa_d_num, + &sp->opdata_rsa_pn_num, &sp->opdata_rsa_pe_num, + sp->session); + + if (h_priv_key != CK_INVALID_HANDLE) + { + rv = pFuncList->C_SignInit(sp->session, p_mech, h_priv_key); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_RSA_SIGN, PK11_R_SIGNINIT, rv); + goto err; + } + + ulsiglen = j; + rv = pFuncList->C_Sign(sp->session, s, i, sigret, + (CK_ULONG_PTR) &ulsiglen); + *siglen = ulsiglen; + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_RSA_SIGN, PK11_R_SIGN, rv); + goto err; + } + ret = 1; + } + +err: + if ((type != NID_md5_sha1) && (s != NULL)) + { + (void) memset(s, 0, (unsigned int)(j + 1)); + OPENSSL_free(s); + } + + pk11_return_session(sp, OP_RSA); + return (ret); + } + +static int hndidx_rsa = -1; + +#define MAXATTR 1024 + +/* + * Load RSA private key from a file or get its PKCS#11 handle if stored in the + * PKCS#11 token. + */ +/* ARGSUSED */ +EVP_PKEY *pk11_load_privkey(ENGINE *e, const char *privkey_file, + UI_METHOD *ui_method, void *callback_data) + { + EVP_PKEY *pkey = NULL; + FILE *privkey; + CK_OBJECT_HANDLE h_priv_key = CK_INVALID_HANDLE; + RSA *rsa = NULL; + PK11_SESSION *sp; + /* Anything else below is needed for the key by reference extension. */ + CK_RV rv; + CK_BBOOL is_token = TRUE; + CK_BBOOL rollback = FALSE; + CK_BYTE attr_data[2][MAXATTR]; + CK_OBJECT_CLASS key_class = CKO_PRIVATE_KEY; + CK_OBJECT_HANDLE ks_key = CK_INVALID_HANDLE; /* key in keystore */ + + /* we look for private keys only */ + CK_ATTRIBUTE search_templ[] = + { + {CKA_TOKEN, &is_token, sizeof(is_token)}, + {CKA_CLASS, &key_class, sizeof(key_class)}, + {CKA_LABEL, NULL, 0} + }; + + /* + * These public attributes are needed to initialize the OpenSSL RSA + * structure with something we can use to look up the key. Note that we + * never ask for private components. + */ + CK_ATTRIBUTE get_templ[] = + { + {CKA_MODULUS, (void *)attr_data[0], MAXATTR}, /* n */ + {CKA_PUBLIC_EXPONENT, (void *)attr_data[1], MAXATTR}, /* e */ + }; + + if ((sp = pk11_get_session(OP_RSA)) == NULL) + return (NULL); + + /* + * Use simple scheme "pkcs11:" for now. + */ + if (strstr(privkey_file, "pkcs11:") == privkey_file) + { + search_templ[2].pValue = strstr(privkey_file, ":") + 1; + search_templ[2].ulValueLen = strlen(search_templ[2].pValue); + + if (pk11_token_login(sp->session, &pk11_login_done, + CK_TRUE) == 0) + goto err; + + /* see find_lock array definition + for more info on object locking */ + LOCK_OBJSTORE(OP_RSA); + + /* + * Now let's try to find the key in the token. It is a failure + * if we can't find it. + */ + if (find_one_object(OP_RSA, sp->session, search_templ, 3, + &ks_key) == 0) + { + UNLOCK_OBJSTORE(OP_RSA); + goto err; + } + + if (hndidx_rsa == -1) + hndidx_rsa = RSA_get_ex_new_index(0, + "pkcs11 RSA HSM key handle", + NULL, NULL, NULL); + + /* + * We might have a cache hit which we could confirm + * according to the 'n'/'e' params, RSA public pointer + * as NULL, and non-NULL RSA private pointer. However, + * it is easier just to recreate everything. We expect + * the keys to be loaded once and used many times. We + * do not check the return value because even in case + * of failure the sp structure will have both key + * pointer and object handle cleaned and + * pk11_destroy_object() reports the failure to the + * OpenSSL error message buffer. + */ + (void) pk11_destroy_rsa_object_priv(sp, FALSE); + + sp->opdata_rsa_priv_key = ks_key; + /* This object shall not be deleted on a cache miss. */ + sp->priv_persistent = CK_TRUE; + + /* + * Cache the RSA private structure pointer. We do not + * use it now for key-by-ref keys but let's do it for + * consistency reasons. + */ + if ((rsa = sp->opdata_rsa_priv = RSA_new_method(e)) == NULL) + { + UNLOCK_OBJSTORE(OP_RSA); + goto err; + } + + /* + * Now we have to initialize an OpenSSL RSA structure, + * everything else is 0 or NULL. + */ + rsa->flags = RSA_FLAG_SIGN_VER | RSA_FLAG_EXT_PKEY; + RSA_set_ex_data(rsa, hndidx_rsa, (void *) ks_key); + + if ((rv = pFuncList->C_GetAttributeValue(sp->session, ks_key, + get_templ, 2)) != CKR_OK) + { + UNLOCK_OBJSTORE(OP_RSA); + PK11err_add_data(PK11_F_LOAD_PRIVKEY, + PK11_R_GETATTRIBUTVALUE, rv); + goto err; + } + + /* + * We do not use pk11_get_private_rsa_key() here so we + * must take care of handle management ourselves. + */ + KEY_HANDLE_REFHOLD(ks_key, OP_RSA, TRUE, rollback, err); + + /* + * Those are the sensitive components we do not want to export + * from the token at all: rsa->(d|p|q|dmp1|dmq1|iqmp). + */ + attr_to_BN(&get_templ[0], attr_data[0], &rsa->n); + attr_to_BN(&get_templ[1], attr_data[1], &rsa->e); + /* + * Must have 'n'/'e' components in the session structure as + * well. They serve as a public look-up key for the private key + * in the keystore. + */ + attr_to_BN(&get_templ[0], attr_data[0], + &sp->opdata_rsa_pn_num); + attr_to_BN(&get_templ[1], attr_data[1], + &sp->opdata_rsa_pe_num); + + UNLOCK_OBJSTORE(OP_RSA); + + if ((pkey = EVP_PKEY_new()) == NULL) + goto err; + + if (EVP_PKEY_assign_RSA(pkey, rsa) == 0) + goto err; + } + else if ((privkey = fopen(privkey_file, read_mode_flags)) != NULL) + { + pkey = PEM_read_PrivateKey(privkey, NULL, NULL, NULL); + (void) fclose(privkey); + if (pkey != NULL) + { + rsa = EVP_PKEY_get1_RSA(pkey); + if (rsa != NULL) + { + /* + * This will always destroy the RSA + * object since we have a new RSA + * structure here. + */ + (void) check_new_rsa_key_priv(sp, rsa); + sp->priv_persistent = CK_FALSE; + + h_priv_key = sp->opdata_rsa_priv_key = + pk11_get_private_rsa_key(rsa, + &sp->opdata_rsa_priv, + &sp->opdata_rsa_d_num, + &sp->opdata_rsa_pn_num, + &sp->opdata_rsa_pe_num, sp->session); + if (h_priv_key == CK_INVALID_HANDLE) + goto err; + } + else + goto err; + } + } + + pk11_return_session(sp, OP_RSA); + return (pkey); +err: + pk11_return_session(sp, OP_RSA); + if (rsa != NULL) + RSA_free(rsa); + if (pkey != NULL) + { + EVP_PKEY_free(pkey); + pkey = NULL; + } + rollback = rollback; + return (pkey); + } + +/* + * Load RSA public key from a file or get its PKCS#11 handle if stored in the + * PKCS#11 token. + */ +/* ARGSUSED */ +EVP_PKEY *pk11_load_pubkey(ENGINE *e, const char *pubkey_file, + UI_METHOD *ui_method, void *callback_data) + { + EVP_PKEY *pkey = NULL; + FILE *pubkey; + CK_OBJECT_HANDLE h_pub_key = CK_INVALID_HANDLE; + RSA *rsa = NULL; + PK11_SESSION *sp; + /* Anything else below is needed for the key by reference extension. */ + CK_RV rv; + CK_BBOOL is_token = TRUE; + CK_BYTE attr_data[2][MAXATTR]; + CK_OBJECT_CLASS key_class = CKO_PUBLIC_KEY; + CK_OBJECT_HANDLE ks_key = CK_INVALID_HANDLE; /* key in keystore */ + + /* we look for public keys only */ + CK_ATTRIBUTE search_templ[] = + { + {CKA_TOKEN, &is_token, sizeof(is_token)}, + {CKA_CLASS, &key_class, sizeof(key_class)}, + {CKA_LABEL, NULL, 0} + }; + + /* + * These public attributes are needed to initialize OpenSSL RSA + * structure with something we can use to look up the key. + */ + CK_ATTRIBUTE get_templ[] = + { + {CKA_MODULUS, (void *)attr_data[0], MAXATTR}, /* n */ + {CKA_PUBLIC_EXPONENT, (void *)attr_data[1], MAXATTR}, /* e */ + }; + + if ((sp = pk11_get_session(OP_RSA)) == NULL) + return (NULL); + + /* + * Use simple scheme "pkcs11:" for now. + */ + if (strstr(pubkey_file, "pkcs11:") == pubkey_file) + { + search_templ[2].pValue = strstr(pubkey_file, ":") + 1; + search_templ[2].ulValueLen = strlen(search_templ[2].pValue); + + if (pk11_token_login(sp->session, &pk11_login_done, + CK_FALSE) == 0) + goto err; + + /* see find_lock array definition + for more info on object locking */ + LOCK_OBJSTORE(OP_RSA); + + /* + * Now let's try to find the key in the token. It is a failure + * if we can't find it. + */ + if (find_one_object(OP_RSA, sp->session, search_templ, 3, + &ks_key) == 0) + { + UNLOCK_OBJSTORE(OP_RSA); + goto err; + } + + /* + * We load a new public key so we will create a new RSA + * structure. No cache hit is possible. + */ + (void) pk11_destroy_rsa_object_pub(sp, FALSE); + + sp->opdata_rsa_pub_key = ks_key; + /* This object shall not be deleted on a cache miss. */ + sp->pub_persistent = CK_TRUE; + + /* + * Cache the RSA public structure pointer. + */ + if ((rsa = sp->opdata_rsa_pub = RSA_new_method(e)) == NULL) + { + UNLOCK_OBJSTORE(OP_RSA); + goto err; + } + + /* + * Now we have to initialize an OpenSSL RSA structure, + * everything else is 0 or NULL. + */ + rsa->flags = RSA_FLAG_SIGN_VER; + + if ((rv = pFuncList->C_GetAttributeValue(sp->session, ks_key, + get_templ, 2)) != CKR_OK) + { + UNLOCK_OBJSTORE(OP_RSA); + PK11err_add_data(PK11_F_LOAD_PUBKEY, + PK11_R_GETATTRIBUTVALUE, rv); + goto err; + } + + attr_to_BN(&get_templ[0], attr_data[0], &rsa->n); + attr_to_BN(&get_templ[1], attr_data[1], &rsa->e); + + UNLOCK_OBJSTORE(OP_RSA); + + if ((pkey = EVP_PKEY_new()) == NULL) + goto err; + + if (EVP_PKEY_assign_RSA(pkey, rsa) == 0) + goto err; + + /* + * Create a session object from it so that when calling + * pk11_get_public_rsa_key() the next time, we can find it. The + * reason why we do that is that we cannot tell from the RSA + * structure (OpenSSL RSA structure does not have any room for + * additional data used by the engine, for example) if it bears + * a public key stored in the keystore or not so it's better if + * we always have a session key. Note that this is different + * from what we do for the private keystore objects but in that + * case, we can tell from the RSA structure that the keystore + * object is in play - the 'd' component is NULL in that case. + */ + h_pub_key = sp->opdata_rsa_pub_key = + pk11_get_public_rsa_key(rsa, + &sp->opdata_rsa_pub, &sp->opdata_rsa_n_num, + &sp->opdata_rsa_e_num, sp->session); + if (h_pub_key == CK_INVALID_HANDLE) + goto err; + } + else if ((pubkey = fopen(pubkey_file, read_mode_flags)) != NULL) + { + pkey = PEM_read_PUBKEY(pubkey, NULL, NULL, NULL); + (void) fclose(pubkey); + if (pkey != NULL) + { + rsa = EVP_PKEY_get1_RSA(pkey); + if (rsa != NULL) + { + /* + * This will always destroy the RSA + * object since we have a new RSA + * structure here. + */ + (void) check_new_rsa_key_pub(sp, rsa); + sp->pub_persistent = CK_FALSE; + + h_pub_key = sp->opdata_rsa_pub_key = + pk11_get_public_rsa_key(rsa, + &sp->opdata_rsa_pub, &sp->opdata_rsa_n_num, + &sp->opdata_rsa_e_num, sp->session); + if (h_pub_key == CK_INVALID_HANDLE) + goto err; + } + else + goto err; + } + } + + pk11_return_session(sp, OP_RSA); + return (pkey); +err: + pk11_return_session(sp, OP_RSA); + if (rsa != NULL) + RSA_free(rsa); + if (pkey != NULL) + { + EVP_PKEY_free(pkey); + pkey = NULL; + } + return (pkey); + } + +/* + * Create a public key object in a session from a given rsa structure. + * The *rsa_n_num and *rsa_e_num pointers are non-NULL for RSA public keys. + */ +static CK_OBJECT_HANDLE pk11_get_public_rsa_key(RSA *rsa, + RSA **key_ptr, BIGNUM **rsa_n_num, BIGNUM **rsa_e_num, + CK_SESSION_HANDLE session) + { + CK_RV rv; + CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE; + CK_ULONG found; + CK_OBJECT_CLASS o_key = CKO_PUBLIC_KEY; + CK_KEY_TYPE k_type = CKK_RSA; + CK_ULONG ul_key_attr_count = 8; + CK_BBOOL rollback = FALSE; + + CK_ATTRIBUTE a_key_template[] = + { + {CKA_CLASS, (void *) NULL, sizeof (CK_OBJECT_CLASS)}, + {CKA_KEY_TYPE, (void *) NULL, sizeof (CK_KEY_TYPE)}, + {CKA_TOKEN, &myfalse, sizeof (myfalse)}, + {CKA_ENCRYPT, &mytrue, sizeof (mytrue)}, + {CKA_VERIFY, &mytrue, sizeof (mytrue)}, + {CKA_VERIFY_RECOVER, &mytrue, sizeof (mytrue)}, + {CKA_MODULUS, (void *)NULL, 0}, + {CKA_PUBLIC_EXPONENT, (void *)NULL, 0} + }; + + int i; + + a_key_template[0].pValue = &o_key; + a_key_template[1].pValue = &k_type; + + a_key_template[6].ulValueLen = BN_num_bytes(rsa->n); + a_key_template[6].pValue = (CK_VOID_PTR)OPENSSL_malloc( + (size_t)a_key_template[6].ulValueLen); + if (a_key_template[6].pValue == NULL) + { + PK11err(PK11_F_GET_PUB_RSA_KEY, PK11_R_MALLOC_FAILURE); + goto malloc_err; + } + + BN_bn2bin(rsa->n, a_key_template[6].pValue); + + a_key_template[7].ulValueLen = BN_num_bytes(rsa->e); + a_key_template[7].pValue = (CK_VOID_PTR)OPENSSL_malloc( + (size_t)a_key_template[7].ulValueLen); + if (a_key_template[7].pValue == NULL) + { + PK11err(PK11_F_GET_PUB_RSA_KEY, PK11_R_MALLOC_FAILURE); + goto malloc_err; + } + + BN_bn2bin(rsa->e, a_key_template[7].pValue); + + /* see find_lock array definition for more info on object locking */ + LOCK_OBJSTORE(OP_RSA); + + rv = pFuncList->C_FindObjectsInit(session, a_key_template, + ul_key_attr_count); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PUB_RSA_KEY, + PK11_R_FINDOBJECTSINIT, rv); + goto err; + } + + rv = pFuncList->C_FindObjects(session, &h_key, 1, &found); + + if (rv != CKR_OK) + { + (void) pFuncList->C_FindObjectsFinal(session); + PK11err_add_data(PK11_F_GET_PUB_RSA_KEY, + PK11_R_FINDOBJECTS, rv); + goto err; + } + + rv = pFuncList->C_FindObjectsFinal(session); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PUB_RSA_KEY, + PK11_R_FINDOBJECTSFINAL, rv); + goto err; + } + + if (found == 0) + { + rv = pFuncList->C_CreateObject(session, + a_key_template, ul_key_attr_count, &h_key); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PUB_RSA_KEY, + PK11_R_CREATEOBJECT, rv); + goto err; + } + } + + if (rsa_n_num != NULL) + if ((*rsa_n_num = BN_dup(rsa->n)) == NULL) + { + PK11err(PK11_F_GET_PUB_RSA_KEY, PK11_R_MALLOC_FAILURE); + rollback = TRUE; + goto err; + } + if (rsa_e_num != NULL) + if ((*rsa_e_num = BN_dup(rsa->e)) == NULL) + { + PK11err(PK11_F_GET_PUB_RSA_KEY, PK11_R_MALLOC_FAILURE); + BN_free(*rsa_n_num); + *rsa_n_num = NULL; + rollback = TRUE; + goto err; + } + + /* LINTED: E_CONSTANT_CONDITION */ + KEY_HANDLE_REFHOLD(h_key, OP_RSA, FALSE, rollback, err); + if (key_ptr != NULL) + *key_ptr = rsa; + +err: + if (rollback) + { + /* + * We do not care about the return value from C_DestroyObject() + * since we are doing rollback. + */ + if (found == 0) + (void) pFuncList->C_DestroyObject(session, h_key); + h_key = CK_INVALID_HANDLE; + } + + UNLOCK_OBJSTORE(OP_RSA); + +malloc_err: + for (i = 6; i <= 7; i++) + { + if (a_key_template[i].pValue != NULL) + { + OPENSSL_free(a_key_template[i].pValue); + a_key_template[i].pValue = NULL; + } + } + + return (h_key); + } + +/* + * Create a private key object in the session from a given rsa structure. + * The *rsa_d_num pointer is non-NULL for RSA private keys. + */ +static CK_OBJECT_HANDLE +pk11_get_private_rsa_key(RSA *rsa, RSA **key_ptr, BIGNUM **rsa_d_num, + BIGNUM **rsa_n_num, BIGNUM **rsa_e_num, CK_SESSION_HANDLE session) + { + CK_RV rv; + CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE; + int i; + CK_ULONG found; + CK_OBJECT_CLASS o_key = CKO_PRIVATE_KEY; + CK_KEY_TYPE k_type = CKK_RSA; + CK_ULONG ul_key_attr_count = 14; + CK_BBOOL rollback = FALSE; + + /* Both CKA_TOKEN and CKA_SENSITIVE have to be FALSE for session keys */ + CK_ATTRIBUTE a_key_template[] = + { + {CKA_CLASS, (void *) NULL, sizeof (CK_OBJECT_CLASS)}, + {CKA_KEY_TYPE, (void *) NULL, sizeof (CK_KEY_TYPE)}, + {CKA_TOKEN, &myfalse, sizeof (myfalse)}, + {CKA_SENSITIVE, &myfalse, sizeof (myfalse)}, + {CKA_DECRYPT, &mytrue, sizeof (mytrue)}, + {CKA_SIGN, &mytrue, sizeof (mytrue)}, + {CKA_MODULUS, (void *)NULL, 0}, + {CKA_PUBLIC_EXPONENT, (void *)NULL, 0}, + {CKA_PRIVATE_EXPONENT, (void *)NULL, 0}, + {CKA_PRIME_1, (void *)NULL, 0}, + {CKA_PRIME_2, (void *)NULL, 0}, + {CKA_EXPONENT_1, (void *)NULL, 0}, + {CKA_EXPONENT_2, (void *)NULL, 0}, + {CKA_COEFFICIENT, (void *)NULL, 0}, + }; + + if ((rsa->flags & RSA_FLAG_EXT_PKEY) != 0) { + h_key = (CK_OBJECT_HANDLE)RSA_get_ex_data(rsa, hndidx_rsa); + LOCK_OBJSTORE(OP_RSA); + goto set; + } + + a_key_template[0].pValue = &o_key; + a_key_template[1].pValue = &k_type; + + /* Put the private key components into the template */ + if (init_template_value(rsa->n, &a_key_template[6].pValue, + &a_key_template[6].ulValueLen) == 0 || + init_template_value(rsa->e, &a_key_template[7].pValue, + &a_key_template[7].ulValueLen) == 0 || + init_template_value(rsa->d, &a_key_template[8].pValue, + &a_key_template[8].ulValueLen) == 0 || + init_template_value(rsa->p, &a_key_template[9].pValue, + &a_key_template[9].ulValueLen) == 0 || + init_template_value(rsa->q, &a_key_template[10].pValue, + &a_key_template[10].ulValueLen) == 0 || + init_template_value(rsa->dmp1, &a_key_template[11].pValue, + &a_key_template[11].ulValueLen) == 0 || + init_template_value(rsa->dmq1, &a_key_template[12].pValue, + &a_key_template[12].ulValueLen) == 0 || + init_template_value(rsa->iqmp, &a_key_template[13].pValue, + &a_key_template[13].ulValueLen) == 0) + { + PK11err(PK11_F_GET_PRIV_RSA_KEY, PK11_R_MALLOC_FAILURE); + goto malloc_err; + } + + /* see find_lock array definition for more info on object locking */ + LOCK_OBJSTORE(OP_RSA); + + /* + * We are getting the private key but the private 'd' + * component is NULL. That means this is key by reference RSA + * key. In that case, we can use only public components for + * searching for the private key handle. + */ + if (rsa->d == NULL) + { + ul_key_attr_count = 8; + /* + * We will perform the search in the token, not in the existing + * session keys. + */ + a_key_template[2].pValue = &mytrue; + } + + rv = pFuncList->C_FindObjectsInit(session, a_key_template, + ul_key_attr_count); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PRIV_RSA_KEY, + PK11_R_FINDOBJECTSINIT, rv); + goto err; + } + + rv = pFuncList->C_FindObjects(session, &h_key, 1, &found); + + if (rv != CKR_OK) + { + (void) pFuncList->C_FindObjectsFinal(session); + PK11err_add_data(PK11_F_GET_PRIV_RSA_KEY, + PK11_R_FINDOBJECTS, rv); + goto err; + } + + rv = pFuncList->C_FindObjectsFinal(session); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PRIV_RSA_KEY, + PK11_R_FINDOBJECTSFINAL, rv); + goto err; + } + + if (found == 0) + { + /* + * We have an RSA structure with 'n'/'e' components + * only so we tried to find the private key in the + * keystore. If it was really a token key we have a + * problem. Note that for other key types we just + * create a new session key using the private + * components from the RSA structure. + */ + if (rsa->d == NULL) + { + PK11err(PK11_F_GET_PRIV_RSA_KEY, + PK11_R_PRIV_KEY_NOT_FOUND); + goto err; + } + + rv = pFuncList->C_CreateObject(session, + a_key_template, ul_key_attr_count, &h_key); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PRIV_RSA_KEY, + PK11_R_CREATEOBJECT, rv); + goto err; + } + } + +set: + if (rsa_d_num != NULL) + { + /* + * When RSA keys by reference code is used, we never + * extract private components from the keystore. In + * that case 'd' was set to NULL and we expect the + * application to properly cope with that. It is + * documented in openssl(5). In general, if keys by + * reference are used we expect it to be used + * exclusively using the high level API and then there + * is no problem. If the application expects the + * private components to be read from the keystore + * then that is not a supported way of usage. + */ + if (rsa->d != NULL && (*rsa_d_num = BN_dup(rsa->d)) == NULL) + { + PK11err(PK11_F_GET_PRIV_RSA_KEY, PK11_R_MALLOC_FAILURE); + rollback = TRUE; + goto err; + } + else + *rsa_d_num = NULL; + } + + /* + * For the key by reference code, we need public components as well + * since 'd' component is always NULL. For that reason, we always cache + * 'n'/'e' components as well. + */ + *rsa_n_num = BN_dup(rsa->n); + *rsa_e_num = BN_dup(rsa->e); + + /* LINTED: E_CONSTANT_CONDITION */ + KEY_HANDLE_REFHOLD(h_key, OP_RSA, FALSE, rollback, err); + if (key_ptr != NULL) + *key_ptr = rsa; + +err: + if (rollback) + { + /* + * We do not care about the return value from C_DestroyObject() + * since we are doing rollback. + */ + if (found == 0 && + (rsa->flags & RSA_FLAG_EXT_PKEY) == 0) + (void) pFuncList->C_DestroyObject(session, h_key); + h_key = CK_INVALID_HANDLE; + } + + UNLOCK_OBJSTORE(OP_RSA); + +malloc_err: + /* + * 6 to 13 entries in the key template are key components. + * They need to be freed upon exit or error. + */ + for (i = 6; i <= 13; i++) + { + if (a_key_template[i].pValue != NULL) + { + (void) memset(a_key_template[i].pValue, 0, + a_key_template[i].ulValueLen); + OPENSSL_free(a_key_template[i].pValue); + a_key_template[i].pValue = NULL; + } + } + + return (h_key); + } + +/* + * Check for cache miss and clean the object pointer and handle + * in such case. Return 1 for cache hit, 0 for cache miss. + */ +static int check_new_rsa_key_pub(PK11_SESSION *sp, const RSA *rsa) + { + /* + * Provide protection against RSA structure reuse by making the + * check for cache hit stronger. Only public components of RSA + * key matter here so it is sufficient to compare them with values + * cached in PK11_SESSION structure. + * + * We must check the handle as well since with key by reference, public + * components 'n'/'e' are cached in private keys as well. That means we + * could have a cache hit in a private key when looking for a public + * key. That would not work, you cannot have one PKCS#11 object for + * both data signing and verifying. + */ + if ((sp->opdata_rsa_pub != rsa) || + (BN_cmp(sp->opdata_rsa_n_num, rsa->n) != 0) || + (BN_cmp(sp->opdata_rsa_e_num, rsa->e) != 0) || + (sp->opdata_rsa_priv_key != CK_INVALID_HANDLE)) + { + /* + * We do not check the return value because even in case of + * failure the sp structure will have both key pointer + * and object handle cleaned and pk11_destroy_object() + * reports the failure to the OpenSSL error message buffer. + */ + (void) pk11_destroy_rsa_object_pub(sp, TRUE); + return (0); + } + return (1); + } + +/* + * Check for cache miss and clean the object pointer and handle + * in such case. Return 1 for cache hit, 0 for cache miss. + */ +static int check_new_rsa_key_priv(PK11_SESSION *sp, const RSA *rsa) + { + /* + * Provide protection against RSA structure reuse by making + * the check for cache hit stronger. Comparing public exponent + * of RSA key with value cached in PK11_SESSION structure + * should be sufficient. Note that we want to compare the + * public component since with the keys by reference + * mechanism, private components are not in the RSA + * structure. Also, see check_new_rsa_key_pub() about why we + * compare the handle as well. + */ + if ((sp->opdata_rsa_priv != rsa) || + (BN_cmp(sp->opdata_rsa_pn_num, rsa->n) != 0) || + (BN_cmp(sp->opdata_rsa_pe_num, rsa->e) != 0) || + (sp->opdata_rsa_pn_num == NULL) || + (sp->opdata_rsa_pe_num == NULL) || + (sp->opdata_rsa_pub_key != CK_INVALID_HANDLE)) + { + /* + * We do not check the return value because even in case of + * failure the sp structure will have both key pointer + * and object handle cleaned and pk11_destroy_object() + * reports the failure to the OpenSSL error message buffer. + */ + (void) pk11_destroy_rsa_object_priv(sp, TRUE); + return (0); + } + return (1); + } + +/* + * Local function to simplify key template population + * Return 0 -- error, 1 -- no error + */ +static int +init_template_value(BIGNUM *bn, CK_VOID_PTR *p_value, + CK_ULONG *ul_value_len) + { + CK_ULONG len = 0; + + /* + * This function can be used on non-initialized BIGNUMs. It is + * easier to check that here than individually in the callers. + */ + if (bn != NULL) + len = BN_num_bytes(bn); + + if (bn == NULL || len == 0) + return (1); + + *ul_value_len = len; + *p_value = (CK_VOID_PTR)OPENSSL_malloc((size_t)*ul_value_len); + if (*p_value == NULL) + return (0); + + BN_bn2bin(bn, *p_value); + + return (1); + } + +static void +attr_to_BN(CK_ATTRIBUTE_PTR attr, CK_BYTE attr_data[], BIGNUM **bn) + { + if (attr->ulValueLen > 0) + *bn = BN_bin2bn(attr_data, attr->ulValueLen, NULL); + } + +/* + * Find one object in the token. It is an error if we can not find the + * object or if we find more objects based on the template we got. + * Assume object store locked. + * + * Returns: + * 1 OK + * 0 no object or more than 1 object found + */ +static int +find_one_object(PK11_OPTYPE op, CK_SESSION_HANDLE s, + CK_ATTRIBUTE_PTR ptempl, CK_ULONG nattr, CK_OBJECT_HANDLE_PTR pkey) + { + CK_RV rv; + CK_ULONG objcnt; + + if ((rv = pFuncList->C_FindObjectsInit(s, ptempl, nattr)) != CKR_OK) + { + PK11err_add_data(PK11_F_FIND_ONE_OBJECT, + PK11_R_FINDOBJECTSINIT, rv); + return (0); + } + + rv = pFuncList->C_FindObjects(s, pkey, 1, &objcnt); + if (rv != CKR_OK) + { + (void) pFuncList->C_FindObjectsFinal(s); + PK11err_add_data(PK11_F_FIND_ONE_OBJECT, PK11_R_FINDOBJECTS, + rv); + return (0); + } + + (void) pFuncList->C_FindObjectsFinal(s); + + if (objcnt > 1) + { + PK11err(PK11_F_FIND_ONE_OBJECT, + PK11_R_MORE_THAN_ONE_OBJECT_FOUND); + return (0); + } + else if (objcnt == 0) + { + PK11err(PK11_F_FIND_ONE_OBJECT, PK11_R_NO_OBJECT_FOUND); + return (0); + } + return (1); + } + +/* from uri stuff */ + +extern char *pk11_pin; + +static int pk11_get_pin(void); + +static int +pk11_get_pin(void) +{ + char *pin; + + /* The getpassphrase() function is not MT safe. */ +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_lock(token_lock) == 0); +#else + CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); +#endif + pin = getpassphrase("Enter PIN: "); + if (pin == NULL) + { + PK11err(PK11_F_GET_PIN, PK11_R_COULD_NOT_READ_PIN); +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0); +#else + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + return (0); + } + pk11_pin = BUF_strdup(pin); + if (pk11_pin == NULL) + { + PK11err(PK11_F_LOAD_PRIVKEY, PK11_R_MALLOC_FAILURE); +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0); +#else + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + return (0); + } + memset(pin, 0, strlen(pin)); +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0); +#else + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + return (1); + } + +/* + * Log in to the keystore if we are supposed to do that at all. Take care of + * reading and caching the PIN etc. Log in only once even when called from + * multiple threads. + * + * Returns: + * 1 on success + * 0 on failure + */ +static int +pk11_token_login(CK_SESSION_HANDLE session, CK_BBOOL *login_done, + CK_BBOOL is_private) + { + CK_RV rv; + +#if 0 + /* doesn't work on the AEP Keyper??? */ + if ((pubkey_token_flags & CKF_TOKEN_INITIALIZED) == 0) + { + PK11err(PK11_F_TOKEN_LOGIN, + PK11_R_TOKEN_NOT_INITIALIZED); + return (0); + } +#endif + + /* + * If login is required or needed but the PIN has not been + * even initialized we can bail out right now. Note that we + * are supposed to always log in if we are going to access + * private keys. However, we may need to log in even for + * accessing public keys in case that the CKF_LOGIN_REQUIRED + * flag is set. + */ + if (((pubkey_token_flags & CKF_LOGIN_REQUIRED) || + (is_private == CK_TRUE)) && + (~pubkey_token_flags & CKF_USER_PIN_INITIALIZED)) + { + PK11err(PK11_F_TOKEN_LOGIN, PK11_R_TOKEN_PIN_NOT_SET); + return (0); + } + + /* + * Note on locking: it is possible that more than one thread + * gets into pk11_get_pin() so we must deal with that. We + * cannot avoid it since we cannot guard fork() in there with + * a lock because we could end up in a dead lock in the + * child. Why? Remember we are in a multithreaded environment + * so we must lock all mutexes in the prefork function to + * avoid a situation in which a thread that did not call + * fork() held a lock, making future unlocking impossible. We + * lock right before C_Login(). + */ + if ((pubkey_token_flags & CKF_LOGIN_REQUIRED) || + (is_private == CK_TRUE)) + { + if (*login_done == CK_FALSE) + { + if ((pk11_pin == NULL) && (pk11_get_pin() == 0)) + { + PK11err(PK11_F_TOKEN_LOGIN, + PK11_R_TOKEN_PIN_NOT_PROVIDED); + return (0); + } + } + + /* + * Note that what we are logging into is the keystore from + * pubkey_SLOTID because we work with OP_RSA session type here. + * That also means that we can work with only one keystore in + * the engine. + * + * We must make sure we do not try to login more than once. + * Also, see the comment above on locking strategy. + */ + +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_lock(token_lock) == 0); +#else + CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); +#endif + if (*login_done == CK_FALSE) + { + if ((rv = pFuncList->C_Login(session, + CKU_USER, (CK_UTF8CHAR*)pk11_pin, + strlen(pk11_pin))) != CKR_OK) + { + PK11err_add_data(PK11_F_TOKEN_LOGIN, + PK11_R_TOKEN_LOGIN_FAILED, rv); + goto err_locked; + } + + *login_done = CK_TRUE; + + } +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0); +#else + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + } + else + { + /* + * If token does not require login we take it as the + * login was done. + */ + *login_done = CK_TRUE; + } + + return (1); + +err_locked: + if (pk11_pin) { + memset(pk11_pin, 0, strlen(pk11_pin)); + OPENSSL_free((void*)pk11_pin); + } + pk11_pin = NULL; +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0); +#else + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + return (0); + } + +/* + * Log in to the keystore in the child if we were logged in in the + * parent. There are similarities in the code with pk11_token_login() + * but still it is quite different so we need a separate function for + * this. + * + * Note that this function is called under the locked session mutex when fork is + * detected. That means that C_Login() will be called from the child just once. + * + * Returns: + * 1 on success + * 0 on failure + */ +int +pk11_token_relogin(CK_SESSION_HANDLE session) + { + CK_RV rv; + + if ((pk11_pin == NULL) && (pk11_get_pin() == 0)) + return (0); + +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_lock(token_lock) == 0); +#else + CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); +#endif + if ((rv = pFuncList->C_Login(session, CKU_USER, + (CK_UTF8CHAR_PTR)pk11_pin, strlen(pk11_pin))) != CKR_OK) + { + PK11err_add_data(PK11_F_TOKEN_RELOGIN, + PK11_R_TOKEN_LOGIN_FAILED, rv); +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0); +#else + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + return (0); + } +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0); +#else + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + + return (1); + } + +#ifdef OPENSSL_SYS_WIN32 +char *getpassphrase(const char *prompt) + { + static char buf[128]; + HANDLE h; + DWORD cc, mode; + int cnt; + + h = GetStdHandle(STD_INPUT_HANDLE); + fputs(prompt, stderr); + fflush(stderr); + fflush(stdout); + FlushConsoleInputBuffer(h); + GetConsoleMode(h, &mode); + SetConsoleMode(h, ENABLE_PROCESSED_INPUT); + + for (cnt = 0; cnt < sizeof(buf) - 1; cnt++) + { + ReadFile(h, buf + cnt, 1, &cc, NULL); + if (buf[cnt] == '\r') + break; + fputc('*', stdout); + fflush(stderr); + fflush(stdout); + } + + SetConsoleMode(h, mode); + buf[cnt] = '\0'; + fputs("\n", stderr); + return buf; + } +#endif /* OPENSSL_SYS_WIN32 */ +#endif /* OPENSSL_NO_HW_PK11SO */ +#endif /* OPENSSL_NO_HW_PK11 */ +#endif /* OPENSSL_NO_HW */ Index: openssl/crypto/engine/pkcs11.h diff -u /dev/null openssl/crypto/engine/pkcs11.h:1.1.1.1 --- /dev/null Wed Dec 23 16:49:06 2015 +++ openssl/crypto/engine/pkcs11.h Wed Oct 24 23:27:09 2007 @@ -0,0 +1,299 @@ +/* pkcs11.h include file for PKCS #11. */ +/* $Revision: 1.1.1.1 $ */ + +/* License to copy and use this software is granted provided that it is + * identified as "RSA Security Inc. PKCS #11 Cryptographic Token Interface + * (Cryptoki)" in all material mentioning or referencing this software. + + * License is also granted to make and use derivative works provided that + * such works are identified as "derived from the RSA Security Inc. PKCS #11 + * Cryptographic Token Interface (Cryptoki)" in all material mentioning or + * referencing the derived work. + + * RSA Security Inc. makes no representations concerning either the + * merchantability of this software or the suitability of this software for + * any particular purpose. It is provided "as is" without express or implied + * warranty of any kind. + */ + +#ifndef _PKCS11_H_ +#define _PKCS11_H_ 1 + +#ifdef __cplusplus +extern "C" { +#endif + +/* Before including this file (pkcs11.h) (or pkcs11t.h by + * itself), 6 platform-specific macros must be defined. These + * macros are described below, and typical definitions for them + * are also given. Be advised that these definitions can depend + * on both the platform and the compiler used (and possibly also + * on whether a Cryptoki library is linked statically or + * dynamically). + * + * In addition to defining these 6 macros, the packing convention + * for Cryptoki structures should be set. The Cryptoki + * convention on packing is that structures should be 1-byte + * aligned. + * + * If you're using Microsoft Developer Studio 5.0 to produce + * Win32 stuff, this might be done by using the following + * preprocessor directive before including pkcs11.h or pkcs11t.h: + * + * #pragma pack(push, cryptoki, 1) + * + * and using the following preprocessor directive after including + * pkcs11.h or pkcs11t.h: + * + * #pragma pack(pop, cryptoki) + * + * If you're using an earlier version of Microsoft Developer + * Studio to produce Win16 stuff, this might be done by using + * the following preprocessor directive before including + * pkcs11.h or pkcs11t.h: + * + * #pragma pack(1) + * + * In a UNIX environment, you're on your own for this. You might + * not need to do (or be able to do!) anything. + * + * + * Now for the macros: + * + * + * 1. CK_PTR: The indirection string for making a pointer to an + * object. It can be used like this: + * + * typedef CK_BYTE CK_PTR CK_BYTE_PTR; + * + * If you're using Microsoft Developer Studio 5.0 to produce + * Win32 stuff, it might be defined by: + * + * #define CK_PTR * + * + * If you're using an earlier version of Microsoft Developer + * Studio to produce Win16 stuff, it might be defined by: + * + * #define CK_PTR far * + * + * In a typical UNIX environment, it might be defined by: + * + * #define CK_PTR * + * + * + * 2. CK_DEFINE_FUNCTION(returnType, name): A macro which makes + * an exportable Cryptoki library function definition out of a + * return type and a function name. It should be used in the + * following fashion to define the exposed Cryptoki functions in + * a Cryptoki library: + * + * CK_DEFINE_FUNCTION(CK_RV, C_Initialize)( + * CK_VOID_PTR pReserved + * ) + * { + * ... + * } + * + * If you're using Microsoft Developer Studio 5.0 to define a + * function in a Win32 Cryptoki .dll, it might be defined by: + * + * #define CK_DEFINE_FUNCTION(returnType, name) \ + * returnType __declspec(dllexport) name + * + * If you're using an earlier version of Microsoft Developer + * Studio to define a function in a Win16 Cryptoki .dll, it + * might be defined by: + * + * #define CK_DEFINE_FUNCTION(returnType, name) \ + * returnType __export _far _pascal name + * + * In a UNIX environment, it might be defined by: + * + * #define CK_DEFINE_FUNCTION(returnType, name) \ + * returnType name + * + * + * 3. CK_DECLARE_FUNCTION(returnType, name): A macro which makes + * an importable Cryptoki library function declaration out of a + * return type and a function name. It should be used in the + * following fashion: + * + * extern CK_DECLARE_FUNCTION(CK_RV, C_Initialize)( + * CK_VOID_PTR pReserved + * ); + * + * If you're using Microsoft Developer Studio 5.0 to declare a + * function in a Win32 Cryptoki .dll, it might be defined by: + * + * #define CK_DECLARE_FUNCTION(returnType, name) \ + * returnType __declspec(dllimport) name + * + * If you're using an earlier version of Microsoft Developer + * Studio to declare a function in a Win16 Cryptoki .dll, it + * might be defined by: + * + * #define CK_DECLARE_FUNCTION(returnType, name) \ + * returnType __export _far _pascal name + * + * In a UNIX environment, it might be defined by: + * + * #define CK_DECLARE_FUNCTION(returnType, name) \ + * returnType name + * + * + * 4. CK_DECLARE_FUNCTION_POINTER(returnType, name): A macro + * which makes a Cryptoki API function pointer declaration or + * function pointer type declaration out of a return type and a + * function name. It should be used in the following fashion: + * + * // Define funcPtr to be a pointer to a Cryptoki API function + * // taking arguments args and returning CK_RV. + * CK_DECLARE_FUNCTION_POINTER(CK_RV, funcPtr)(args); + * + * or + * + * // Define funcPtrType to be the type of a pointer to a + * // Cryptoki API function taking arguments args and returning + * // CK_RV, and then define funcPtr to be a variable of type + * // funcPtrType. + * typedef CK_DECLARE_FUNCTION_POINTER(CK_RV, funcPtrType)(args); + * funcPtrType funcPtr; + * + * If you're using Microsoft Developer Studio 5.0 to access + * functions in a Win32 Cryptoki .dll, in might be defined by: + * + * #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \ + * returnType __declspec(dllimport) (* name) + * + * If you're using an earlier version of Microsoft Developer + * Studio to access functions in a Win16 Cryptoki .dll, it might + * be defined by: + * + * #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \ + * returnType __export _far _pascal (* name) + * + * In a UNIX environment, it might be defined by: + * + * #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \ + * returnType (* name) + * + * + * 5. CK_CALLBACK_FUNCTION(returnType, name): A macro which makes + * a function pointer type for an application callback out of + * a return type for the callback and a name for the callback. + * It should be used in the following fashion: + * + * CK_CALLBACK_FUNCTION(CK_RV, myCallback)(args); + * + * to declare a function pointer, myCallback, to a callback + * which takes arguments args and returns a CK_RV. It can also + * be used like this: + * + * typedef CK_CALLBACK_FUNCTION(CK_RV, myCallbackType)(args); + * myCallbackType myCallback; + * + * If you're using Microsoft Developer Studio 5.0 to do Win32 + * Cryptoki development, it might be defined by: + * + * #define CK_CALLBACK_FUNCTION(returnType, name) \ + * returnType (* name) + * + * If you're using an earlier version of Microsoft Developer + * Studio to do Win16 development, it might be defined by: + * + * #define CK_CALLBACK_FUNCTION(returnType, name) \ + * returnType _far _pascal (* name) + * + * In a UNIX environment, it might be defined by: + * + * #define CK_CALLBACK_FUNCTION(returnType, name) \ + * returnType (* name) + * + * + * 6. NULL_PTR: This macro is the value of a NULL pointer. + * + * In any ANSI/ISO C environment (and in many others as well), + * this should best be defined by + * + * #ifndef NULL_PTR + * #define NULL_PTR 0 + * #endif + */ + + +/* All the various Cryptoki types and #define'd values are in the + * file pkcs11t.h. */ +#include "pkcs11t.h" + +#define __PASTE(x,y) x##y + + +/* ============================================================== + * Define the "extern" form of all the entry points. + * ============================================================== + */ + +#define CK_NEED_ARG_LIST 1 +#define CK_PKCS11_FUNCTION_INFO(name) \ + extern CK_DECLARE_FUNCTION(CK_RV, name) + +/* pkcs11f.h has all the information about the Cryptoki + * function prototypes. */ +#include "pkcs11f.h" + +#undef CK_NEED_ARG_LIST +#undef CK_PKCS11_FUNCTION_INFO + + +/* ============================================================== + * Define the typedef form of all the entry points. That is, for + * each Cryptoki function C_XXX, define a type CK_C_XXX which is + * a pointer to that kind of function. + * ============================================================== + */ + +#define CK_NEED_ARG_LIST 1 +#define CK_PKCS11_FUNCTION_INFO(name) \ + typedef CK_DECLARE_FUNCTION_POINTER(CK_RV, __PASTE(CK_,name)) + +/* pkcs11f.h has all the information about the Cryptoki + * function prototypes. */ +#include "pkcs11f.h" + +#undef CK_NEED_ARG_LIST +#undef CK_PKCS11_FUNCTION_INFO + + +/* ============================================================== + * Define structed vector of entry points. A CK_FUNCTION_LIST + * contains a CK_VERSION indicating a library's Cryptoki version + * and then a whole slew of function pointers to the routines in + * the library. This type was declared, but not defined, in + * pkcs11t.h. + * ============================================================== + */ + +#define CK_PKCS11_FUNCTION_INFO(name) \ + __PASTE(CK_,name) name; + +struct CK_FUNCTION_LIST { + + CK_VERSION version; /* Cryptoki version */ + +/* Pile all the function pointers into the CK_FUNCTION_LIST. */ +/* pkcs11f.h has all the information about the Cryptoki + * function prototypes. */ +#include "pkcs11f.h" + +}; + +#undef CK_PKCS11_FUNCTION_INFO + + +#undef __PASTE + +#ifdef __cplusplus +} +#endif + +#endif Index: openssl/crypto/engine/pkcs11f.h diff -u /dev/null openssl/crypto/engine/pkcs11f.h:1.1.1.1 --- /dev/null Wed Dec 23 16:49:06 2015 +++ openssl/crypto/engine/pkcs11f.h Wed Oct 24 23:27:09 2007 @@ -0,0 +1,912 @@ +/* pkcs11f.h include file for PKCS #11. */ +/* $Revision: 1.1.1.1 $ */ + +/* License to copy and use this software is granted provided that it is + * identified as "RSA Security Inc. PKCS #11 Cryptographic Token Interface + * (Cryptoki)" in all material mentioning or referencing this software. + + * License is also granted to make and use derivative works provided that + * such works are identified as "derived from the RSA Security Inc. PKCS #11 + * Cryptographic Token Interface (Cryptoki)" in all material mentioning or + * referencing the derived work. + + * RSA Security Inc. makes no representations concerning either the + * merchantability of this software or the suitability of this software for + * any particular purpose. It is provided "as is" without express or implied + * warranty of any kind. + */ + +/* This header file contains pretty much everything about all the */ +/* Cryptoki function prototypes. Because this information is */ +/* used for more than just declaring function prototypes, the */ +/* order of the functions appearing herein is important, and */ +/* should not be altered. */ + +/* General-purpose */ + +/* C_Initialize initializes the Cryptoki library. */ +CK_PKCS11_FUNCTION_INFO(C_Initialize) +#ifdef CK_NEED_ARG_LIST +( + CK_VOID_PTR pInitArgs /* if this is not NULL_PTR, it gets + * cast to CK_C_INITIALIZE_ARGS_PTR + * and dereferenced */ +); +#endif + + +/* C_Finalize indicates that an application is done with the + * Cryptoki library. */ +CK_PKCS11_FUNCTION_INFO(C_Finalize) +#ifdef CK_NEED_ARG_LIST +( + CK_VOID_PTR pReserved /* reserved. Should be NULL_PTR */ +); +#endif + + +/* C_GetInfo returns general information about Cryptoki. */ +CK_PKCS11_FUNCTION_INFO(C_GetInfo) +#ifdef CK_NEED_ARG_LIST +( + CK_INFO_PTR pInfo /* location that receives information */ +); +#endif + + +/* C_GetFunctionList returns the function list. */ +CK_PKCS11_FUNCTION_INFO(C_GetFunctionList) +#ifdef CK_NEED_ARG_LIST +( + CK_FUNCTION_LIST_PTR_PTR ppFunctionList /* receives pointer to + * function list */ +); +#endif + + + +/* Slot and token management */ + +/* C_GetSlotList obtains a list of slots in the system. */ +CK_PKCS11_FUNCTION_INFO(C_GetSlotList) +#ifdef CK_NEED_ARG_LIST +( + CK_BBOOL tokenPresent, /* only slots with tokens? */ + CK_SLOT_ID_PTR pSlotList, /* receives array of slot IDs */ + CK_ULONG_PTR pulCount /* receives number of slots */ +); +#endif + + +/* C_GetSlotInfo obtains information about a particular slot in + * the system. */ +CK_PKCS11_FUNCTION_INFO(C_GetSlotInfo) +#ifdef CK_NEED_ARG_LIST +( + CK_SLOT_ID slotID, /* the ID of the slot */ + CK_SLOT_INFO_PTR pInfo /* receives the slot information */ +); +#endif + + +/* C_GetTokenInfo obtains information about a particular token + * in the system. */ +CK_PKCS11_FUNCTION_INFO(C_GetTokenInfo) +#ifdef CK_NEED_ARG_LIST +( + CK_SLOT_ID slotID, /* ID of the token's slot */ + CK_TOKEN_INFO_PTR pInfo /* receives the token information */ +); +#endif + + +/* C_GetMechanismList obtains a list of mechanism types + * supported by a token. */ +CK_PKCS11_FUNCTION_INFO(C_GetMechanismList) +#ifdef CK_NEED_ARG_LIST +( + CK_SLOT_ID slotID, /* ID of token's slot */ + CK_MECHANISM_TYPE_PTR pMechanismList, /* gets mech. array */ + CK_ULONG_PTR pulCount /* gets # of mechs. */ +); +#endif + + +/* C_GetMechanismInfo obtains information about a particular + * mechanism possibly supported by a token. */ +CK_PKCS11_FUNCTION_INFO(C_GetMechanismInfo) +#ifdef CK_NEED_ARG_LIST +( + CK_SLOT_ID slotID, /* ID of the token's slot */ + CK_MECHANISM_TYPE type, /* type of mechanism */ + CK_MECHANISM_INFO_PTR pInfo /* receives mechanism info */ +); +#endif + + +/* C_InitToken initializes a token. */ +CK_PKCS11_FUNCTION_INFO(C_InitToken) +#ifdef CK_NEED_ARG_LIST +/* pLabel changed from CK_CHAR_PTR to CK_UTF8CHAR_PTR for v2.10 */ +( + CK_SLOT_ID slotID, /* ID of the token's slot */ + CK_UTF8CHAR_PTR pPin, /* the SO's initial PIN */ + CK_ULONG ulPinLen, /* length in bytes of the PIN */ + CK_UTF8CHAR_PTR pLabel /* 32-byte token label (blank padded) */ +); +#endif + + +/* C_InitPIN initializes the normal user's PIN. */ +CK_PKCS11_FUNCTION_INFO(C_InitPIN) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_UTF8CHAR_PTR pPin, /* the normal user's PIN */ + CK_ULONG ulPinLen /* length in bytes of the PIN */ +); +#endif + + +/* C_SetPIN modifies the PIN of the user who is logged in. */ +CK_PKCS11_FUNCTION_INFO(C_SetPIN) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_UTF8CHAR_PTR pOldPin, /* the old PIN */ + CK_ULONG ulOldLen, /* length of the old PIN */ + CK_UTF8CHAR_PTR pNewPin, /* the new PIN */ + CK_ULONG ulNewLen /* length of the new PIN */ +); +#endif + + + +/* Session management */ + +/* C_OpenSession opens a session between an application and a + * token. */ +CK_PKCS11_FUNCTION_INFO(C_OpenSession) +#ifdef CK_NEED_ARG_LIST +( + CK_SLOT_ID slotID, /* the slot's ID */ + CK_FLAGS flags, /* from CK_SESSION_INFO */ + CK_VOID_PTR pApplication, /* passed to callback */ + CK_NOTIFY Notify, /* callback function */ + CK_SESSION_HANDLE_PTR phSession /* gets session handle */ +); +#endif + + +/* C_CloseSession closes a session between an application and a + * token. */ +CK_PKCS11_FUNCTION_INFO(C_CloseSession) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession /* the session's handle */ +); +#endif + + +/* C_CloseAllSessions closes all sessions with a token. */ +CK_PKCS11_FUNCTION_INFO(C_CloseAllSessions) +#ifdef CK_NEED_ARG_LIST +( + CK_SLOT_ID slotID /* the token's slot */ +); +#endif + + +/* C_GetSessionInfo obtains information about the session. */ +CK_PKCS11_FUNCTION_INFO(C_GetSessionInfo) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_SESSION_INFO_PTR pInfo /* receives session info */ +); +#endif + + +/* C_GetOperationState obtains the state of the cryptographic operation + * in a session. */ +CK_PKCS11_FUNCTION_INFO(C_GetOperationState) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* session's handle */ + CK_BYTE_PTR pOperationState, /* gets state */ + CK_ULONG_PTR pulOperationStateLen /* gets state length */ +); +#endif + + +/* C_SetOperationState restores the state of the cryptographic + * operation in a session. */ +CK_PKCS11_FUNCTION_INFO(C_SetOperationState) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* session's handle */ + CK_BYTE_PTR pOperationState, /* holds state */ + CK_ULONG ulOperationStateLen, /* holds state length */ + CK_OBJECT_HANDLE hEncryptionKey, /* en/decryption key */ + CK_OBJECT_HANDLE hAuthenticationKey /* sign/verify key */ +); +#endif + + +/* C_Login logs a user into a token. */ +CK_PKCS11_FUNCTION_INFO(C_Login) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_USER_TYPE userType, /* the user type */ + CK_UTF8CHAR_PTR pPin, /* the user's PIN */ + CK_ULONG ulPinLen /* the length of the PIN */ +); +#endif + + +/* C_Logout logs a user out from a token. */ +CK_PKCS11_FUNCTION_INFO(C_Logout) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession /* the session's handle */ +); +#endif + + + +/* Object management */ + +/* C_CreateObject creates a new object. */ +CK_PKCS11_FUNCTION_INFO(C_CreateObject) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_ATTRIBUTE_PTR pTemplate, /* the object's template */ + CK_ULONG ulCount, /* attributes in template */ + CK_OBJECT_HANDLE_PTR phObject /* gets new object's handle. */ +); +#endif + + +/* C_CopyObject copies an object, creating a new object for the + * copy. */ +CK_PKCS11_FUNCTION_INFO(C_CopyObject) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_OBJECT_HANDLE hObject, /* the object's handle */ + CK_ATTRIBUTE_PTR pTemplate, /* template for new object */ + CK_ULONG ulCount, /* attributes in template */ + CK_OBJECT_HANDLE_PTR phNewObject /* receives handle of copy */ +); +#endif + + +/* C_DestroyObject destroys an object. */ +CK_PKCS11_FUNCTION_INFO(C_DestroyObject) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_OBJECT_HANDLE hObject /* the object's handle */ +); +#endif + + +/* C_GetObjectSize gets the size of an object in bytes. */ +CK_PKCS11_FUNCTION_INFO(C_GetObjectSize) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_OBJECT_HANDLE hObject, /* the object's handle */ + CK_ULONG_PTR pulSize /* receives size of object */ +); +#endif + + +/* C_GetAttributeValue obtains the value of one or more object + * attributes. */ +CK_PKCS11_FUNCTION_INFO(C_GetAttributeValue) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_OBJECT_HANDLE hObject, /* the object's handle */ + CK_ATTRIBUTE_PTR pTemplate, /* specifies attrs; gets vals */ + CK_ULONG ulCount /* attributes in template */ +); +#endif + + +/* C_SetAttributeValue modifies the value of one or more object + * attributes */ +CK_PKCS11_FUNCTION_INFO(C_SetAttributeValue) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_OBJECT_HANDLE hObject, /* the object's handle */ + CK_ATTRIBUTE_PTR pTemplate, /* specifies attrs and values */ + CK_ULONG ulCount /* attributes in template */ +); +#endif + + +/* C_FindObjectsInit initializes a search for token and session + * objects that match a template. */ +CK_PKCS11_FUNCTION_INFO(C_FindObjectsInit) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_ATTRIBUTE_PTR pTemplate, /* attribute values to match */ + CK_ULONG ulCount /* attrs in search template */ +); +#endif + + +/* C_FindObjects continues a search for token and session + * objects that match a template, obtaining additional object + * handles. */ +CK_PKCS11_FUNCTION_INFO(C_FindObjects) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* session's handle */ + CK_OBJECT_HANDLE_PTR phObject, /* gets obj. handles */ + CK_ULONG ulMaxObjectCount, /* max handles to get */ + CK_ULONG_PTR pulObjectCount /* actual # returned */ +); +#endif + + +/* C_FindObjectsFinal finishes a search for token and session + * objects. */ +CK_PKCS11_FUNCTION_INFO(C_FindObjectsFinal) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession /* the session's handle */ +); +#endif + + + +/* Encryption and decryption */ + +/* C_EncryptInit initializes an encryption operation. */ +CK_PKCS11_FUNCTION_INFO(C_EncryptInit) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_MECHANISM_PTR pMechanism, /* the encryption mechanism */ + CK_OBJECT_HANDLE hKey /* handle of encryption key */ +); +#endif + + +/* C_Encrypt encrypts single-part data. */ +CK_PKCS11_FUNCTION_INFO(C_Encrypt) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* session's handle */ + CK_BYTE_PTR pData, /* the plaintext data */ + CK_ULONG ulDataLen, /* bytes of plaintext */ + CK_BYTE_PTR pEncryptedData, /* gets ciphertext */ + CK_ULONG_PTR pulEncryptedDataLen /* gets c-text size */ +); +#endif + + +/* C_EncryptUpdate continues a multiple-part encryption + * operation. */ +CK_PKCS11_FUNCTION_INFO(C_EncryptUpdate) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* session's handle */ + CK_BYTE_PTR pPart, /* the plaintext data */ + CK_ULONG ulPartLen, /* plaintext data len */ + CK_BYTE_PTR pEncryptedPart, /* gets ciphertext */ + CK_ULONG_PTR pulEncryptedPartLen /* gets c-text size */ +); +#endif + + +/* C_EncryptFinal finishes a multiple-part encryption + * operation. */ +CK_PKCS11_FUNCTION_INFO(C_EncryptFinal) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* session handle */ + CK_BYTE_PTR pLastEncryptedPart, /* last c-text */ + CK_ULONG_PTR pulLastEncryptedPartLen /* gets last size */ +); +#endif + + +/* C_DecryptInit initializes a decryption operation. */ +CK_PKCS11_FUNCTION_INFO(C_DecryptInit) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_MECHANISM_PTR pMechanism, /* the decryption mechanism */ + CK_OBJECT_HANDLE hKey /* handle of decryption key */ +); +#endif + + +/* C_Decrypt decrypts encrypted data in a single part. */ +CK_PKCS11_FUNCTION_INFO(C_Decrypt) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* session's handle */ + CK_BYTE_PTR pEncryptedData, /* ciphertext */ + CK_ULONG ulEncryptedDataLen, /* ciphertext length */ + CK_BYTE_PTR pData, /* gets plaintext */ + CK_ULONG_PTR pulDataLen /* gets p-text size */ +); +#endif + + +/* C_DecryptUpdate continues a multiple-part decryption + * operation. */ +CK_PKCS11_FUNCTION_INFO(C_DecryptUpdate) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* session's handle */ + CK_BYTE_PTR pEncryptedPart, /* encrypted data */ + CK_ULONG ulEncryptedPartLen, /* input length */ + CK_BYTE_PTR pPart, /* gets plaintext */ + CK_ULONG_PTR pulPartLen /* p-text size */ +); +#endif + + +/* C_DecryptFinal finishes a multiple-part decryption + * operation. */ +CK_PKCS11_FUNCTION_INFO(C_DecryptFinal) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_BYTE_PTR pLastPart, /* gets plaintext */ + CK_ULONG_PTR pulLastPartLen /* p-text size */ +); +#endif + + + +/* Message digesting */ + +/* C_DigestInit initializes a message-digesting operation. */ +CK_PKCS11_FUNCTION_INFO(C_DigestInit) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_MECHANISM_PTR pMechanism /* the digesting mechanism */ +); +#endif + + +/* C_Digest digests data in a single part. */ +CK_PKCS11_FUNCTION_INFO(C_Digest) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_BYTE_PTR pData, /* data to be digested */ + CK_ULONG ulDataLen, /* bytes of data to digest */ + CK_BYTE_PTR pDigest, /* gets the message digest */ + CK_ULONG_PTR pulDigestLen /* gets digest length */ +); +#endif + + +/* C_DigestUpdate continues a multiple-part message-digesting + * operation. */ +CK_PKCS11_FUNCTION_INFO(C_DigestUpdate) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_BYTE_PTR pPart, /* data to be digested */ + CK_ULONG ulPartLen /* bytes of data to be digested */ +); +#endif + + +/* C_DigestKey continues a multi-part message-digesting + * operation, by digesting the value of a secret key as part of + * the data already digested. */ +CK_PKCS11_FUNCTION_INFO(C_DigestKey) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_OBJECT_HANDLE hKey /* secret key to digest */ +); +#endif + + +/* C_DigestFinal finishes a multiple-part message-digesting + * operation. */ +CK_PKCS11_FUNCTION_INFO(C_DigestFinal) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_BYTE_PTR pDigest, /* gets the message digest */ + CK_ULONG_PTR pulDigestLen /* gets byte count of digest */ +); +#endif + + + +/* Signing and MACing */ + +/* C_SignInit initializes a signature (private key encryption) + * operation, where the signature is (will be) an appendix to + * the data, and plaintext cannot be recovered from the + *signature. */ +CK_PKCS11_FUNCTION_INFO(C_SignInit) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_MECHANISM_PTR pMechanism, /* the signature mechanism */ + CK_OBJECT_HANDLE hKey /* handle of signature key */ +); +#endif + + +/* C_Sign signs (encrypts with private key) data in a single + * part, where the signature is (will be) an appendix to the + * data, and plaintext cannot be recovered from the signature. */ +CK_PKCS11_FUNCTION_INFO(C_Sign) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_BYTE_PTR pData, /* the data to sign */ + CK_ULONG ulDataLen, /* count of bytes to sign */ + CK_BYTE_PTR pSignature, /* gets the signature */ + CK_ULONG_PTR pulSignatureLen /* gets signature length */ +); +#endif + + +/* C_SignUpdate continues a multiple-part signature operation, + * where the signature is (will be) an appendix to the data, + * and plaintext cannot be recovered from the signature. */ +CK_PKCS11_FUNCTION_INFO(C_SignUpdate) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_BYTE_PTR pPart, /* the data to sign */ + CK_ULONG ulPartLen /* count of bytes to sign */ +); +#endif + + +/* C_SignFinal finishes a multiple-part signature operation, + * returning the signature. */ +CK_PKCS11_FUNCTION_INFO(C_SignFinal) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_BYTE_PTR pSignature, /* gets the signature */ + CK_ULONG_PTR pulSignatureLen /* gets signature length */ +); +#endif + + +/* C_SignRecoverInit initializes a signature operation, where + * the data can be recovered from the signature. */ +CK_PKCS11_FUNCTION_INFO(C_SignRecoverInit) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_MECHANISM_PTR pMechanism, /* the signature mechanism */ + CK_OBJECT_HANDLE hKey /* handle of the signature key */ +); +#endif + + +/* C_SignRecover signs data in a single operation, where the + * data can be recovered from the signature. */ +CK_PKCS11_FUNCTION_INFO(C_SignRecover) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_BYTE_PTR pData, /* the data to sign */ + CK_ULONG ulDataLen, /* count of bytes to sign */ + CK_BYTE_PTR pSignature, /* gets the signature */ + CK_ULONG_PTR pulSignatureLen /* gets signature length */ +); +#endif + + + +/* Verifying signatures and MACs */ + +/* C_VerifyInit initializes a verification operation, where the + * signature is an appendix to the data, and plaintext cannot + * cannot be recovered from the signature (e.g. DSA). */ +CK_PKCS11_FUNCTION_INFO(C_VerifyInit) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_MECHANISM_PTR pMechanism, /* the verification mechanism */ + CK_OBJECT_HANDLE hKey /* verification key */ +); +#endif + + +/* C_Verify verifies a signature in a single-part operation, + * where the signature is an appendix to the data, and plaintext + * cannot be recovered from the signature. */ +CK_PKCS11_FUNCTION_INFO(C_Verify) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_BYTE_PTR pData, /* signed data */ + CK_ULONG ulDataLen, /* length of signed data */ + CK_BYTE_PTR pSignature, /* signature */ + CK_ULONG ulSignatureLen /* signature length*/ +); +#endif + + +/* C_VerifyUpdate continues a multiple-part verification + * operation, where the signature is an appendix to the data, + * and plaintext cannot be recovered from the signature. */ +CK_PKCS11_FUNCTION_INFO(C_VerifyUpdate) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_BYTE_PTR pPart, /* signed data */ + CK_ULONG ulPartLen /* length of signed data */ +); +#endif + + +/* C_VerifyFinal finishes a multiple-part verification + * operation, checking the signature. */ +CK_PKCS11_FUNCTION_INFO(C_VerifyFinal) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_BYTE_PTR pSignature, /* signature to verify */ + CK_ULONG ulSignatureLen /* signature length */ +); +#endif + + +/* C_VerifyRecoverInit initializes a signature verification + * operation, where the data is recovered from the signature. */ +CK_PKCS11_FUNCTION_INFO(C_VerifyRecoverInit) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_MECHANISM_PTR pMechanism, /* the verification mechanism */ + CK_OBJECT_HANDLE hKey /* verification key */ +); +#endif + + +/* C_VerifyRecover verifies a signature in a single-part + * operation, where the data is recovered from the signature. */ +CK_PKCS11_FUNCTION_INFO(C_VerifyRecover) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_BYTE_PTR pSignature, /* signature to verify */ + CK_ULONG ulSignatureLen, /* signature length */ + CK_BYTE_PTR pData, /* gets signed data */ + CK_ULONG_PTR pulDataLen /* gets signed data len */ +); +#endif + + + +/* Dual-function cryptographic operations */ + +/* C_DigestEncryptUpdate continues a multiple-part digesting + * and encryption operation. */ +CK_PKCS11_FUNCTION_INFO(C_DigestEncryptUpdate) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* session's handle */ + CK_BYTE_PTR pPart, /* the plaintext data */ + CK_ULONG ulPartLen, /* plaintext length */ + CK_BYTE_PTR pEncryptedPart, /* gets ciphertext */ + CK_ULONG_PTR pulEncryptedPartLen /* gets c-text length */ +); +#endif + + +/* C_DecryptDigestUpdate continues a multiple-part decryption and + * digesting operation. */ +CK_PKCS11_FUNCTION_INFO(C_DecryptDigestUpdate) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* session's handle */ + CK_BYTE_PTR pEncryptedPart, /* ciphertext */ + CK_ULONG ulEncryptedPartLen, /* ciphertext length */ + CK_BYTE_PTR pPart, /* gets plaintext */ + CK_ULONG_PTR pulPartLen /* gets plaintext len */ +); +#endif + + +/* C_SignEncryptUpdate continues a multiple-part signing and + * encryption operation. */ +CK_PKCS11_FUNCTION_INFO(C_SignEncryptUpdate) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* session's handle */ + CK_BYTE_PTR pPart, /* the plaintext data */ + CK_ULONG ulPartLen, /* plaintext length */ + CK_BYTE_PTR pEncryptedPart, /* gets ciphertext */ + CK_ULONG_PTR pulEncryptedPartLen /* gets c-text length */ +); +#endif + + +/* C_DecryptVerifyUpdate continues a multiple-part decryption and + * verify operation. */ +CK_PKCS11_FUNCTION_INFO(C_DecryptVerifyUpdate) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* session's handle */ + CK_BYTE_PTR pEncryptedPart, /* ciphertext */ + CK_ULONG ulEncryptedPartLen, /* ciphertext length */ + CK_BYTE_PTR pPart, /* gets plaintext */ + CK_ULONG_PTR pulPartLen /* gets p-text length */ +); +#endif + + + +/* Key management */ + +/* C_GenerateKey generates a secret key, creating a new key + * object. */ +CK_PKCS11_FUNCTION_INFO(C_GenerateKey) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_MECHANISM_PTR pMechanism, /* key generation mech. */ + CK_ATTRIBUTE_PTR pTemplate, /* template for new key */ + CK_ULONG ulCount, /* # of attrs in template */ + CK_OBJECT_HANDLE_PTR phKey /* gets handle of new key */ +); +#endif + + +/* C_GenerateKeyPair generates a public-key/private-key pair, + * creating new key objects. */ +CK_PKCS11_FUNCTION_INFO(C_GenerateKeyPair) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* session + * handle */ + CK_MECHANISM_PTR pMechanism, /* key-gen + * mech. */ + CK_ATTRIBUTE_PTR pPublicKeyTemplate, /* template + * for pub. + * key */ + CK_ULONG ulPublicKeyAttributeCount, /* # pub. + * attrs. */ + CK_ATTRIBUTE_PTR pPrivateKeyTemplate, /* template + * for priv. + * key */ + CK_ULONG ulPrivateKeyAttributeCount, /* # priv. + * attrs. */ + CK_OBJECT_HANDLE_PTR phPublicKey, /* gets pub. + * key + * handle */ + CK_OBJECT_HANDLE_PTR phPrivateKey /* gets + * priv. key + * handle */ +); +#endif + + +/* C_WrapKey wraps (i.e., encrypts) a key. */ +CK_PKCS11_FUNCTION_INFO(C_WrapKey) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_MECHANISM_PTR pMechanism, /* the wrapping mechanism */ + CK_OBJECT_HANDLE hWrappingKey, /* wrapping key */ + CK_OBJECT_HANDLE hKey, /* key to be wrapped */ + CK_BYTE_PTR pWrappedKey, /* gets wrapped key */ + CK_ULONG_PTR pulWrappedKeyLen /* gets wrapped key size */ +); +#endif + + +/* C_UnwrapKey unwraps (decrypts) a wrapped key, creating a new + * key object. */ +CK_PKCS11_FUNCTION_INFO(C_UnwrapKey) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* session's handle */ + CK_MECHANISM_PTR pMechanism, /* unwrapping mech. */ + CK_OBJECT_HANDLE hUnwrappingKey, /* unwrapping key */ + CK_BYTE_PTR pWrappedKey, /* the wrapped key */ + CK_ULONG ulWrappedKeyLen, /* wrapped key len */ + CK_ATTRIBUTE_PTR pTemplate, /* new key template */ + CK_ULONG ulAttributeCount, /* template length */ + CK_OBJECT_HANDLE_PTR phKey /* gets new handle */ +); +#endif + + +/* C_DeriveKey derives a key from a base key, creating a new key + * object. */ +CK_PKCS11_FUNCTION_INFO(C_DeriveKey) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* session's handle */ + CK_MECHANISM_PTR pMechanism, /* key deriv. mech. */ + CK_OBJECT_HANDLE hBaseKey, /* base key */ + CK_ATTRIBUTE_PTR pTemplate, /* new key template */ + CK_ULONG ulAttributeCount, /* template length */ + CK_OBJECT_HANDLE_PTR phKey /* gets new handle */ +); +#endif + + + +/* Random number generation */ + +/* C_SeedRandom mixes additional seed material into the token's + * random number generator. */ +CK_PKCS11_FUNCTION_INFO(C_SeedRandom) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_BYTE_PTR pSeed, /* the seed material */ + CK_ULONG ulSeedLen /* length of seed material */ +); +#endif + + +/* C_GenerateRandom generates random data. */ +CK_PKCS11_FUNCTION_INFO(C_GenerateRandom) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_BYTE_PTR RandomData, /* receives the random data */ + CK_ULONG ulRandomLen /* # of bytes to generate */ +); +#endif + + + +/* Parallel function management */ + +/* C_GetFunctionStatus is a legacy function; it obtains an + * updated status of a function running in parallel with an + * application. */ +CK_PKCS11_FUNCTION_INFO(C_GetFunctionStatus) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession /* the session's handle */ +); +#endif + + +/* C_CancelFunction is a legacy function; it cancels a function + * running in parallel. */ +CK_PKCS11_FUNCTION_INFO(C_CancelFunction) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession /* the session's handle */ +); +#endif + + + +/* Functions added in for Cryptoki Version 2.01 or later */ + +/* C_WaitForSlotEvent waits for a slot event (token insertion, + * removal, etc.) to occur. */ +CK_PKCS11_FUNCTION_INFO(C_WaitForSlotEvent) +#ifdef CK_NEED_ARG_LIST +( + CK_FLAGS flags, /* blocking/nonblocking flag */ + CK_SLOT_ID_PTR pSlot, /* location that receives the slot ID */ + CK_VOID_PTR pRserved /* reserved. Should be NULL_PTR */ +); +#endif Index: openssl/crypto/engine/pkcs11t.h diff -u /dev/null openssl/crypto/engine/pkcs11t.h:1.2 --- /dev/null Wed Dec 23 16:49:06 2015 +++ openssl/crypto/engine/pkcs11t.h Sat Aug 30 11:58:07 2008 @@ -0,0 +1,1885 @@ +/* pkcs11t.h include file for PKCS #11. */ +/* $Revision: 1.2 $ */ + +/* License to copy and use this software is granted provided that it is + * identified as "RSA Security Inc. PKCS #11 Cryptographic Token Interface + * (Cryptoki)" in all material mentioning or referencing this software. + + * License is also granted to make and use derivative works provided that + * such works are identified as "derived from the RSA Security Inc. PKCS #11 + * Cryptographic Token Interface (Cryptoki)" in all material mentioning or + * referencing the derived work. + + * RSA Security Inc. makes no representations concerning either the + * merchantability of this software or the suitability of this software for + * any particular purpose. It is provided "as is" without express or implied + * warranty of any kind. + */ + +/* See top of pkcs11.h for information about the macros that + * must be defined and the structure-packing conventions that + * must be set before including this file. */ + +#ifndef _PKCS11T_H_ +#define _PKCS11T_H_ 1 + +#define CRYPTOKI_VERSION_MAJOR 2 +#define CRYPTOKI_VERSION_MINOR 20 +#define CRYPTOKI_VERSION_AMENDMENT 3 + +#define CK_TRUE 1 +#define CK_FALSE 0 + +#ifndef CK_DISABLE_TRUE_FALSE +#ifndef FALSE +#define FALSE CK_FALSE +#endif + +#ifndef TRUE +#define TRUE CK_TRUE +#endif +#endif + +/* an unsigned 8-bit value */ +typedef unsigned char CK_BYTE; + +/* an unsigned 8-bit character */ +typedef CK_BYTE CK_CHAR; + +/* an 8-bit UTF-8 character */ +typedef CK_BYTE CK_UTF8CHAR; + +/* a BYTE-sized Boolean flag */ +typedef CK_BYTE CK_BBOOL; + +/* an unsigned value, at least 32 bits long */ +typedef unsigned long int CK_ULONG; + +/* a signed value, the same size as a CK_ULONG */ +/* CK_LONG is new for v2.0 */ +typedef long int CK_LONG; + +/* at least 32 bits; each bit is a Boolean flag */ +typedef CK_ULONG CK_FLAGS; + + +/* some special values for certain CK_ULONG variables */ +#define CK_UNAVAILABLE_INFORMATION (~0UL) +#define CK_EFFECTIVELY_INFINITE 0 + + +typedef CK_BYTE CK_PTR CK_BYTE_PTR; +typedef CK_CHAR CK_PTR CK_CHAR_PTR; +typedef CK_UTF8CHAR CK_PTR CK_UTF8CHAR_PTR; +typedef CK_ULONG CK_PTR CK_ULONG_PTR; +typedef void CK_PTR CK_VOID_PTR; + +/* Pointer to a CK_VOID_PTR-- i.e., pointer to pointer to void */ +typedef CK_VOID_PTR CK_PTR CK_VOID_PTR_PTR; + + +/* The following value is always invalid if used as a session */ +/* handle or object handle */ +#define CK_INVALID_HANDLE 0 + + +typedef struct CK_VERSION { + CK_BYTE major; /* integer portion of version number */ + CK_BYTE minor; /* 1/100ths portion of version number */ +} CK_VERSION; + +typedef CK_VERSION CK_PTR CK_VERSION_PTR; + + +typedef struct CK_INFO { + /* manufacturerID and libraryDecription have been changed from + * CK_CHAR to CK_UTF8CHAR for v2.10 */ + CK_VERSION cryptokiVersion; /* Cryptoki interface ver */ + CK_UTF8CHAR manufacturerID[32]; /* blank padded */ + CK_FLAGS flags; /* must be zero */ + + /* libraryDescription and libraryVersion are new for v2.0 */ + CK_UTF8CHAR libraryDescription[32]; /* blank padded */ + CK_VERSION libraryVersion; /* version of library */ +} CK_INFO; + +typedef CK_INFO CK_PTR CK_INFO_PTR; + + +/* CK_NOTIFICATION enumerates the types of notifications that + * Cryptoki provides to an application */ +/* CK_NOTIFICATION has been changed from an enum to a CK_ULONG + * for v2.0 */ +typedef CK_ULONG CK_NOTIFICATION; +#define CKN_SURRENDER 0 + +/* The following notification is new for PKCS #11 v2.20 amendment 3 */ +#define CKN_OTP_CHANGED 1 + + +typedef CK_ULONG CK_SLOT_ID; + +typedef CK_SLOT_ID CK_PTR CK_SLOT_ID_PTR; + + +/* CK_SLOT_INFO provides information about a slot */ +typedef struct CK_SLOT_INFO { + /* slotDescription and manufacturerID have been changed from + * CK_CHAR to CK_UTF8CHAR for v2.10 */ + CK_UTF8CHAR slotDescription[64]; /* blank padded */ + CK_UTF8CHAR manufacturerID[32]; /* blank padded */ + CK_FLAGS flags; + + /* hardwareVersion and firmwareVersion are new for v2.0 */ + CK_VERSION hardwareVersion; /* version of hardware */ + CK_VERSION firmwareVersion; /* version of firmware */ +} CK_SLOT_INFO; + +/* flags: bit flags that provide capabilities of the slot + * Bit Flag Mask Meaning + */ +#define CKF_TOKEN_PRESENT 0x00000001 /* a token is there */ +#define CKF_REMOVABLE_DEVICE 0x00000002 /* removable devices*/ +#define CKF_HW_SLOT 0x00000004 /* hardware slot */ + +typedef CK_SLOT_INFO CK_PTR CK_SLOT_INFO_PTR; + + +/* CK_TOKEN_INFO provides information about a token */ +typedef struct CK_TOKEN_INFO { + /* label, manufacturerID, and model have been changed from + * CK_CHAR to CK_UTF8CHAR for v2.10 */ + CK_UTF8CHAR label[32]; /* blank padded */ + CK_UTF8CHAR manufacturerID[32]; /* blank padded */ + CK_UTF8CHAR model[16]; /* blank padded */ + CK_CHAR serialNumber[16]; /* blank padded */ + CK_FLAGS flags; /* see below */ + + /* ulMaxSessionCount, ulSessionCount, ulMaxRwSessionCount, + * ulRwSessionCount, ulMaxPinLen, and ulMinPinLen have all been + * changed from CK_USHORT to CK_ULONG for v2.0 */ + CK_ULONG ulMaxSessionCount; /* max open sessions */ + CK_ULONG ulSessionCount; /* sess. now open */ + CK_ULONG ulMaxRwSessionCount; /* max R/W sessions */ + CK_ULONG ulRwSessionCount; /* R/W sess. now open */ + CK_ULONG ulMaxPinLen; /* in bytes */ + CK_ULONG ulMinPinLen; /* in bytes */ + CK_ULONG ulTotalPublicMemory; /* in bytes */ + CK_ULONG ulFreePublicMemory; /* in bytes */ + CK_ULONG ulTotalPrivateMemory; /* in bytes */ + CK_ULONG ulFreePrivateMemory; /* in bytes */ + + /* hardwareVersion, firmwareVersion, and time are new for + * v2.0 */ + CK_VERSION hardwareVersion; /* version of hardware */ + CK_VERSION firmwareVersion; /* version of firmware */ + CK_CHAR utcTime[16]; /* time */ +} CK_TOKEN_INFO; + +/* The flags parameter is defined as follows: + * Bit Flag Mask Meaning + */ +#define CKF_RNG 0x00000001 /* has random # + * generator */ +#define CKF_WRITE_PROTECTED 0x00000002 /* token is + * write- + * protected */ +#define CKF_LOGIN_REQUIRED 0x00000004 /* user must + * login */ +#define CKF_USER_PIN_INITIALIZED 0x00000008 /* normal user's + * PIN is set */ + +/* CKF_RESTORE_KEY_NOT_NEEDED is new for v2.0. If it is set, + * that means that *every* time the state of cryptographic + * operations of a session is successfully saved, all keys + * needed to continue those operations are stored in the state */ +#define CKF_RESTORE_KEY_NOT_NEEDED 0x00000020 + +/* CKF_CLOCK_ON_TOKEN is new for v2.0. If it is set, that means + * that the token has some sort of clock. The time on that + * clock is returned in the token info structure */ +#define CKF_CLOCK_ON_TOKEN 0x00000040 + +/* CKF_PROTECTED_AUTHENTICATION_PATH is new for v2.0. If it is + * set, that means that there is some way for the user to login + * without sending a PIN through the Cryptoki library itself */ +#define CKF_PROTECTED_AUTHENTICATION_PATH 0x00000100 + +/* CKF_DUAL_CRYPTO_OPERATIONS is new for v2.0. If it is true, + * that means that a single session with the token can perform + * dual simultaneous cryptographic operations (digest and + * encrypt; decrypt and digest; sign and encrypt; and decrypt + * and sign) */ +#define CKF_DUAL_CRYPTO_OPERATIONS 0x00000200 + +/* CKF_TOKEN_INITIALIZED if new for v2.10. If it is true, the + * token has been initialized using C_InitializeToken or an + * equivalent mechanism outside the scope of PKCS #11. + * Calling C_InitializeToken when this flag is set will cause + * the token to be reinitialized. */ +#define CKF_TOKEN_INITIALIZED 0x00000400 + +/* CKF_SECONDARY_AUTHENTICATION if new for v2.10. If it is + * true, the token supports secondary authentication for + * private key objects. This flag is deprecated in v2.11 and + onwards. */ +#define CKF_SECONDARY_AUTHENTICATION 0x00000800 + +/* CKF_USER_PIN_COUNT_LOW if new for v2.10. If it is true, an + * incorrect user login PIN has been entered at least once + * since the last successful authentication. */ +#define CKF_USER_PIN_COUNT_LOW 0x00010000 + +/* CKF_USER_PIN_FINAL_TRY if new for v2.10. If it is true, + * supplying an incorrect user PIN will it to become locked. */ +#define CKF_USER_PIN_FINAL_TRY 0x00020000 + +/* CKF_USER_PIN_LOCKED if new for v2.10. If it is true, the + * user PIN has been locked. User login to the token is not + * possible. */ +#define CKF_USER_PIN_LOCKED 0x00040000 + +/* CKF_USER_PIN_TO_BE_CHANGED if new for v2.10. If it is true, + * the user PIN value is the default value set by token + * initialization or manufacturing, or the PIN has been + * expired by the card. */ +#define CKF_USER_PIN_TO_BE_CHANGED 0x00080000 + +/* CKF_SO_PIN_COUNT_LOW if new for v2.10. If it is true, an + * incorrect SO login PIN has been entered at least once since + * the last successful authentication. */ +#define CKF_SO_PIN_COUNT_LOW 0x00100000 + +/* CKF_SO_PIN_FINAL_TRY if new for v2.10. If it is true, + * supplying an incorrect SO PIN will it to become locked. */ +#define CKF_SO_PIN_FINAL_TRY 0x00200000 + +/* CKF_SO_PIN_LOCKED if new for v2.10. If it is true, the SO + * PIN has been locked. SO login to the token is not possible. + */ +#define CKF_SO_PIN_LOCKED 0x00400000 + +/* CKF_SO_PIN_TO_BE_CHANGED if new for v2.10. If it is true, + * the SO PIN value is the default value set by token + * initialization or manufacturing, or the PIN has been + * expired by the card. */ +#define CKF_SO_PIN_TO_BE_CHANGED 0x00800000 + +typedef CK_TOKEN_INFO CK_PTR CK_TOKEN_INFO_PTR; + + +/* CK_SESSION_HANDLE is a Cryptoki-assigned value that + * identifies a session */ +typedef CK_ULONG CK_SESSION_HANDLE; + +typedef CK_SESSION_HANDLE CK_PTR CK_SESSION_HANDLE_PTR; + + +/* CK_USER_TYPE enumerates the types of Cryptoki users */ +/* CK_USER_TYPE has been changed from an enum to a CK_ULONG for + * v2.0 */ +typedef CK_ULONG CK_USER_TYPE; +/* Security Officer */ +#define CKU_SO 0 +/* Normal user */ +#define CKU_USER 1 +/* Context specific (added in v2.20) */ +#define CKU_CONTEXT_SPECIFIC 2 + +/* CK_STATE enumerates the session states */ +/* CK_STATE has been changed from an enum to a CK_ULONG for + * v2.0 */ +typedef CK_ULONG CK_STATE; +#define CKS_RO_PUBLIC_SESSION 0 +#define CKS_RO_USER_FUNCTIONS 1 +#define CKS_RW_PUBLIC_SESSION 2 +#define CKS_RW_USER_FUNCTIONS 3 +#define CKS_RW_SO_FUNCTIONS 4 + + +/* CK_SESSION_INFO provides information about a session */ +typedef struct CK_SESSION_INFO { + CK_SLOT_ID slotID; + CK_STATE state; + CK_FLAGS flags; /* see below */ + + /* ulDeviceError was changed from CK_USHORT to CK_ULONG for + * v2.0 */ + CK_ULONG ulDeviceError; /* device-dependent error code */ +} CK_SESSION_INFO; + +/* The flags are defined in the following table: + * Bit Flag Mask Meaning + */ +#define CKF_RW_SESSION 0x00000002 /* session is r/w */ +#define CKF_SERIAL_SESSION 0x00000004 /* no parallel */ + +typedef CK_SESSION_INFO CK_PTR CK_SESSION_INFO_PTR; + + +/* CK_OBJECT_HANDLE is a token-specific identifier for an + * object */ +typedef CK_ULONG CK_OBJECT_HANDLE; + +typedef CK_OBJECT_HANDLE CK_PTR CK_OBJECT_HANDLE_PTR; + + +/* CK_OBJECT_CLASS is a value that identifies the classes (or + * types) of objects that Cryptoki recognizes. It is defined + * as follows: */ +/* CK_OBJECT_CLASS was changed from CK_USHORT to CK_ULONG for + * v2.0 */ +typedef CK_ULONG CK_OBJECT_CLASS; + +/* The following classes of objects are defined: */ +/* CKO_HW_FEATURE is new for v2.10 */ +/* CKO_DOMAIN_PARAMETERS is new for v2.11 */ +/* CKO_MECHANISM is new for v2.20 */ +#define CKO_DATA 0x00000000 +#define CKO_CERTIFICATE 0x00000001 +#define CKO_PUBLIC_KEY 0x00000002 +#define CKO_PRIVATE_KEY 0x00000003 +#define CKO_SECRET_KEY 0x00000004 +#define CKO_HW_FEATURE 0x00000005 +#define CKO_DOMAIN_PARAMETERS 0x00000006 +#define CKO_MECHANISM 0x00000007 + +/* CKO_OTP_KEY is new for PKCS #11 v2.20 amendment 1 */ +#define CKO_OTP_KEY 0x00000008 + +#define CKO_VENDOR_DEFINED 0x80000000 + +typedef CK_OBJECT_CLASS CK_PTR CK_OBJECT_CLASS_PTR; + +/* CK_HW_FEATURE_TYPE is new for v2.10. CK_HW_FEATURE_TYPE is a + * value that identifies the hardware feature type of an object + * with CK_OBJECT_CLASS equal to CKO_HW_FEATURE. */ +typedef CK_ULONG CK_HW_FEATURE_TYPE; + +/* The following hardware feature types are defined */ +/* CKH_USER_INTERFACE is new for v2.20 */ +#define CKH_MONOTONIC_COUNTER 0x00000001 +#define CKH_CLOCK 0x00000002 +#define CKH_USER_INTERFACE 0x00000003 +#define CKH_VENDOR_DEFINED 0x80000000 + +/* CK_KEY_TYPE is a value that identifies a key type */ +/* CK_KEY_TYPE was changed from CK_USHORT to CK_ULONG for v2.0 */ +typedef CK_ULONG CK_KEY_TYPE; + +/* the following key types are defined: */ +#define CKK_RSA 0x00000000 +#define CKK_DSA 0x00000001 +#define CKK_DH 0x00000002 + +/* CKK_ECDSA and CKK_KEA are new for v2.0 */ +/* CKK_ECDSA is deprecated in v2.11, CKK_EC is preferred. */ +#define CKK_ECDSA 0x00000003 +#define CKK_EC 0x00000003 +#define CKK_X9_42_DH 0x00000004 +#define CKK_KEA 0x00000005 + +#define CKK_GENERIC_SECRET 0x00000010 +#define CKK_RC2 0x00000011 +#define CKK_RC4 0x00000012 +#define CKK_DES 0x00000013 +#define CKK_DES2 0x00000014 +#define CKK_DES3 0x00000015 + +/* all these key types are new for v2.0 */ +#define CKK_CAST 0x00000016 +#define CKK_CAST3 0x00000017 +/* CKK_CAST5 is deprecated in v2.11, CKK_CAST128 is preferred. */ +#define CKK_CAST5 0x00000018 +#define CKK_CAST128 0x00000018 +#define CKK_RC5 0x00000019 +#define CKK_IDEA 0x0000001A +#define CKK_SKIPJACK 0x0000001B +#define CKK_BATON 0x0000001C +#define CKK_JUNIPER 0x0000001D +#define CKK_CDMF 0x0000001E +#define CKK_AES 0x0000001F + +/* BlowFish and TwoFish are new for v2.20 */ +#define CKK_BLOWFISH 0x00000020 +#define CKK_TWOFISH 0x00000021 + +/* SecurID, HOTP, and ACTI are new for PKCS #11 v2.20 amendment 1 */ +#define CKK_SECURID 0x00000022 +#define CKK_HOTP 0x00000023 +#define CKK_ACTI 0x00000024 + +/* Camellia is new for PKCS #11 v2.20 amendment 3 */ +#define CKK_CAMELLIA 0x00000025 +/* ARIA is new for PKCS #11 v2.20 amendment 3 */ +#define CKK_ARIA 0x00000026 + + +#define CKK_VENDOR_DEFINED 0x80000000 + + +/* CK_CERTIFICATE_TYPE is a value that identifies a certificate + * type */ +/* CK_CERTIFICATE_TYPE was changed from CK_USHORT to CK_ULONG + * for v2.0 */ +typedef CK_ULONG CK_CERTIFICATE_TYPE; + +/* The following certificate types are defined: */ +/* CKC_X_509_ATTR_CERT is new for v2.10 */ +/* CKC_WTLS is new for v2.20 */ +#define CKC_X_509 0x00000000 +#define CKC_X_509_ATTR_CERT 0x00000001 +#define CKC_WTLS 0x00000002 +#define CKC_VENDOR_DEFINED 0x80000000 + + +/* CK_ATTRIBUTE_TYPE is a value that identifies an attribute + * type */ +/* CK_ATTRIBUTE_TYPE was changed from CK_USHORT to CK_ULONG for + * v2.0 */ +typedef CK_ULONG CK_ATTRIBUTE_TYPE; + +/* The CKF_ARRAY_ATTRIBUTE flag identifies an attribute which + consists of an array of values. */ +#define CKF_ARRAY_ATTRIBUTE 0x40000000 + +/* The following OTP-related defines are new for PKCS #11 v2.20 amendment 1 + and relates to the CKA_OTP_FORMAT attribute */ +#define CK_OTP_FORMAT_DECIMAL 0 +#define CK_OTP_FORMAT_HEXADECIMAL 1 +#define CK_OTP_FORMAT_ALPHANUMERIC 2 +#define CK_OTP_FORMAT_BINARY 3 + +/* The following OTP-related defines are new for PKCS #11 v2.20 amendment 1 + and relates to the CKA_OTP_..._REQUIREMENT attributes */ +#define CK_OTP_PARAM_IGNORED 0 +#define CK_OTP_PARAM_OPTIONAL 1 +#define CK_OTP_PARAM_MANDATORY 2 + +/* The following attribute types are defined: */ +#define CKA_CLASS 0x00000000 +#define CKA_TOKEN 0x00000001 +#define CKA_PRIVATE 0x00000002 +#define CKA_LABEL 0x00000003 +#define CKA_APPLICATION 0x00000010 +#define CKA_VALUE 0x00000011 + +/* CKA_OBJECT_ID is new for v2.10 */ +#define CKA_OBJECT_ID 0x00000012 + +#define CKA_CERTIFICATE_TYPE 0x00000080 +#define CKA_ISSUER 0x00000081 +#define CKA_SERIAL_NUMBER 0x00000082 + +/* CKA_AC_ISSUER, CKA_OWNER, and CKA_ATTR_TYPES are new + * for v2.10 */ +#define CKA_AC_ISSUER 0x00000083 +#define CKA_OWNER 0x00000084 +#define CKA_ATTR_TYPES 0x00000085 + +/* CKA_TRUSTED is new for v2.11 */ +#define CKA_TRUSTED 0x00000086 + +/* CKA_CERTIFICATE_CATEGORY ... + * CKA_CHECK_VALUE are new for v2.20 */ +#define CKA_CERTIFICATE_CATEGORY 0x00000087 +#define CKA_JAVA_MIDP_SECURITY_DOMAIN 0x00000088 +#define CKA_URL 0x00000089 +#define CKA_HASH_OF_SUBJECT_PUBLIC_KEY 0x0000008A +#define CKA_HASH_OF_ISSUER_PUBLIC_KEY 0x0000008B +#define CKA_CHECK_VALUE 0x00000090 + +#define CKA_KEY_TYPE 0x00000100 +#define CKA_SUBJECT 0x00000101 +#define CKA_ID 0x00000102 +#define CKA_SENSITIVE 0x00000103 +#define CKA_ENCRYPT 0x00000104 +#define CKA_DECRYPT 0x00000105 +#define CKA_WRAP 0x00000106 +#define CKA_UNWRAP 0x00000107 +#define CKA_SIGN 0x00000108 +#define CKA_SIGN_RECOVER 0x00000109 +#define CKA_VERIFY 0x0000010A +#define CKA_VERIFY_RECOVER 0x0000010B +#define CKA_DERIVE 0x0000010C +#define CKA_START_DATE 0x00000110 +#define CKA_END_DATE 0x00000111 +#define CKA_MODULUS 0x00000120 +#define CKA_MODULUS_BITS 0x00000121 +#define CKA_PUBLIC_EXPONENT 0x00000122 +#define CKA_PRIVATE_EXPONENT 0x00000123 +#define CKA_PRIME_1 0x00000124 +#define CKA_PRIME_2 0x00000125 +#define CKA_EXPONENT_1 0x00000126 +#define CKA_EXPONENT_2 0x00000127 +#define CKA_COEFFICIENT 0x00000128 +#define CKA_PRIME 0x00000130 +#define CKA_SUBPRIME 0x00000131 +#define CKA_BASE 0x00000132 + +/* CKA_PRIME_BITS and CKA_SUB_PRIME_BITS are new for v2.11 */ +#define CKA_PRIME_BITS 0x00000133 +#define CKA_SUBPRIME_BITS 0x00000134 +#define CKA_SUB_PRIME_BITS CKA_SUBPRIME_BITS +/* (To retain backwards-compatibility) */ + +#define CKA_VALUE_BITS 0x00000160 +#define CKA_VALUE_LEN 0x00000161 + +/* CKA_EXTRACTABLE, CKA_LOCAL, CKA_NEVER_EXTRACTABLE, + * CKA_ALWAYS_SENSITIVE, CKA_MODIFIABLE, CKA_ECDSA_PARAMS, + * and CKA_EC_POINT are new for v2.0 */ +#define CKA_EXTRACTABLE 0x00000162 +#define CKA_LOCAL 0x00000163 +#define CKA_NEVER_EXTRACTABLE 0x00000164 +#define CKA_ALWAYS_SENSITIVE 0x00000165 + +/* CKA_KEY_GEN_MECHANISM is new for v2.11 */ +#define CKA_KEY_GEN_MECHANISM 0x00000166 + +#define CKA_MODIFIABLE 0x00000170 + +/* CKA_ECDSA_PARAMS is deprecated in v2.11, + * CKA_EC_PARAMS is preferred. */ +#define CKA_ECDSA_PARAMS 0x00000180 +#define CKA_EC_PARAMS 0x00000180 + +#define CKA_EC_POINT 0x00000181 + +/* CKA_SECONDARY_AUTH, CKA_AUTH_PIN_FLAGS, + * are new for v2.10. Deprecated in v2.11 and onwards. */ +#define CKA_SECONDARY_AUTH 0x00000200 +#define CKA_AUTH_PIN_FLAGS 0x00000201 + +/* CKA_ALWAYS_AUTHENTICATE ... + * CKA_UNWRAP_TEMPLATE are new for v2.20 */ +#define CKA_ALWAYS_AUTHENTICATE 0x00000202 + +#define CKA_WRAP_WITH_TRUSTED 0x00000210 +#define CKA_WRAP_TEMPLATE (CKF_ARRAY_ATTRIBUTE|0x00000211) +#define CKA_UNWRAP_TEMPLATE (CKF_ARRAY_ATTRIBUTE|0x00000212) + +/* CKA_OTP... atttributes are new for PKCS #11 v2.20 amendment 3. */ +#define CKA_OTP_FORMAT 0x00000220 +#define CKA_OTP_LENGTH 0x00000221 +#define CKA_OTP_TIME_INTERVAL 0x00000222 +#define CKA_OTP_USER_FRIENDLY_MODE 0x00000223 +#define CKA_OTP_CHALLENGE_REQUIREMENT 0x00000224 +#define CKA_OTP_TIME_REQUIREMENT 0x00000225 +#define CKA_OTP_COUNTER_REQUIREMENT 0x00000226 +#define CKA_OTP_PIN_REQUIREMENT 0x00000227 +#define CKA_OTP_COUNTER 0x0000022E +#define CKA_OTP_TIME 0x0000022F +#define CKA_OTP_USER_IDENTIFIER 0x0000022A +#define CKA_OTP_SERVICE_IDENTIFIER 0x0000022B +#define CKA_OTP_SERVICE_LOGO 0x0000022C +#define CKA_OTP_SERVICE_LOGO_TYPE 0x0000022D + + +/* CKA_HW_FEATURE_TYPE, CKA_RESET_ON_INIT, and CKA_HAS_RESET + * are new for v2.10 */ +#define CKA_HW_FEATURE_TYPE 0x00000300 +#define CKA_RESET_ON_INIT 0x00000301 +#define CKA_HAS_RESET 0x00000302 + +/* The following attributes are new for v2.20 */ +#define CKA_PIXEL_X 0x00000400 +#define CKA_PIXEL_Y 0x00000401 +#define CKA_RESOLUTION 0x00000402 +#define CKA_CHAR_ROWS 0x00000403 +#define CKA_CHAR_COLUMNS 0x00000404 +#define CKA_COLOR 0x00000405 +#define CKA_BITS_PER_PIXEL 0x00000406 +#define CKA_CHAR_SETS 0x00000480 +#define CKA_ENCODING_METHODS 0x00000481 +#define CKA_MIME_TYPES 0x00000482 +#define CKA_MECHANISM_TYPE 0x00000500 +#define CKA_REQUIRED_CMS_ATTRIBUTES 0x00000501 +#define CKA_DEFAULT_CMS_ATTRIBUTES 0x00000502 +#define CKA_SUPPORTED_CMS_ATTRIBUTES 0x00000503 +#define CKA_ALLOWED_MECHANISMS (CKF_ARRAY_ATTRIBUTE|0x00000600) + +#define CKA_VENDOR_DEFINED 0x80000000 + +/* CK_ATTRIBUTE is a structure that includes the type, length + * and value of an attribute */ +typedef struct CK_ATTRIBUTE { + CK_ATTRIBUTE_TYPE type; + CK_VOID_PTR pValue; + + /* ulValueLen went from CK_USHORT to CK_ULONG for v2.0 */ + CK_ULONG ulValueLen; /* in bytes */ +} CK_ATTRIBUTE; + +typedef CK_ATTRIBUTE CK_PTR CK_ATTRIBUTE_PTR; + + +/* CK_DATE is a structure that defines a date */ +typedef struct CK_DATE{ + CK_CHAR year[4]; /* the year ("1900" - "9999") */ + CK_CHAR month[2]; /* the month ("01" - "12") */ + CK_CHAR day[2]; /* the day ("01" - "31") */ +} CK_DATE; + + +/* CK_MECHANISM_TYPE is a value that identifies a mechanism + * type */ +/* CK_MECHANISM_TYPE was changed from CK_USHORT to CK_ULONG for + * v2.0 */ +typedef CK_ULONG CK_MECHANISM_TYPE; + +/* the following mechanism types are defined: */ +#define CKM_RSA_PKCS_KEY_PAIR_GEN 0x00000000 +#define CKM_RSA_PKCS 0x00000001 +#define CKM_RSA_9796 0x00000002 +#define CKM_RSA_X_509 0x00000003 + +/* CKM_MD2_RSA_PKCS, CKM_MD5_RSA_PKCS, and CKM_SHA1_RSA_PKCS + * are new for v2.0. They are mechanisms which hash and sign */ +#define CKM_MD2_RSA_PKCS 0x00000004 +#define CKM_MD5_RSA_PKCS 0x00000005 +#define CKM_SHA1_RSA_PKCS 0x00000006 + +/* CKM_RIPEMD128_RSA_PKCS, CKM_RIPEMD160_RSA_PKCS, and + * CKM_RSA_PKCS_OAEP are new for v2.10 */ +#define CKM_RIPEMD128_RSA_PKCS 0x00000007 +#define CKM_RIPEMD160_RSA_PKCS 0x00000008 +#define CKM_RSA_PKCS_OAEP 0x00000009 + +/* CKM_RSA_X9_31_KEY_PAIR_GEN, CKM_RSA_X9_31, CKM_SHA1_RSA_X9_31, + * CKM_RSA_PKCS_PSS, and CKM_SHA1_RSA_PKCS_PSS are new for v2.11 */ +#define CKM_RSA_X9_31_KEY_PAIR_GEN 0x0000000A +#define CKM_RSA_X9_31 0x0000000B +#define CKM_SHA1_RSA_X9_31 0x0000000C +#define CKM_RSA_PKCS_PSS 0x0000000D +#define CKM_SHA1_RSA_PKCS_PSS 0x0000000E + +#define CKM_DSA_KEY_PAIR_GEN 0x00000010 +#define CKM_DSA 0x00000011 +#define CKM_DSA_SHA1 0x00000012 +#define CKM_DH_PKCS_KEY_PAIR_GEN 0x00000020 +#define CKM_DH_PKCS_DERIVE 0x00000021 + +/* CKM_X9_42_DH_KEY_PAIR_GEN, CKM_X9_42_DH_DERIVE, + * CKM_X9_42_DH_HYBRID_DERIVE, and CKM_X9_42_MQV_DERIVE are new for + * v2.11 */ +#define CKM_X9_42_DH_KEY_PAIR_GEN 0x00000030 +#define CKM_X9_42_DH_DERIVE 0x00000031 +#define CKM_X9_42_DH_HYBRID_DERIVE 0x00000032 +#define CKM_X9_42_MQV_DERIVE 0x00000033 + +/* CKM_SHA256/384/512 are new for v2.20 */ +#define CKM_SHA256_RSA_PKCS 0x00000040 +#define CKM_SHA384_RSA_PKCS 0x00000041 +#define CKM_SHA512_RSA_PKCS 0x00000042 +#define CKM_SHA256_RSA_PKCS_PSS 0x00000043 +#define CKM_SHA384_RSA_PKCS_PSS 0x00000044 +#define CKM_SHA512_RSA_PKCS_PSS 0x00000045 + +/* SHA-224 RSA mechanisms are new for PKCS #11 v2.20 amendment 3 */ +#define CKM_SHA224_RSA_PKCS 0x00000046 +#define CKM_SHA224_RSA_PKCS_PSS 0x00000047 + +#define CKM_RC2_KEY_GEN 0x00000100 +#define CKM_RC2_ECB 0x00000101 +#define CKM_RC2_CBC 0x00000102 +#define CKM_RC2_MAC 0x00000103 + +/* CKM_RC2_MAC_GENERAL and CKM_RC2_CBC_PAD are new for v2.0 */ +#define CKM_RC2_MAC_GENERAL 0x00000104 +#define CKM_RC2_CBC_PAD 0x00000105 + +#define CKM_RC4_KEY_GEN 0x00000110 +#define CKM_RC4 0x00000111 +#define CKM_DES_KEY_GEN 0x00000120 +#define CKM_DES_ECB 0x00000121 +#define CKM_DES_CBC 0x00000122 +#define CKM_DES_MAC 0x00000123 + +/* CKM_DES_MAC_GENERAL and CKM_DES_CBC_PAD are new for v2.0 */ +#define CKM_DES_MAC_GENERAL 0x00000124 +#define CKM_DES_CBC_PAD 0x00000125 + +#define CKM_DES2_KEY_GEN 0x00000130 +#define CKM_DES3_KEY_GEN 0x00000131 +#define CKM_DES3_ECB 0x00000132 +#define CKM_DES3_CBC 0x00000133 +#define CKM_DES3_MAC 0x00000134 + +/* CKM_DES3_MAC_GENERAL, CKM_DES3_CBC_PAD, CKM_CDMF_KEY_GEN, + * CKM_CDMF_ECB, CKM_CDMF_CBC, CKM_CDMF_MAC, + * CKM_CDMF_MAC_GENERAL, and CKM_CDMF_CBC_PAD are new for v2.0 */ +#define CKM_DES3_MAC_GENERAL 0x00000135 +#define CKM_DES3_CBC_PAD 0x00000136 +#define CKM_CDMF_KEY_GEN 0x00000140 +#define CKM_CDMF_ECB 0x00000141 +#define CKM_CDMF_CBC 0x00000142 +#define CKM_CDMF_MAC 0x00000143 +#define CKM_CDMF_MAC_GENERAL 0x00000144 +#define CKM_CDMF_CBC_PAD 0x00000145 + +/* the following four DES mechanisms are new for v2.20 */ +#define CKM_DES_OFB64 0x00000150 +#define CKM_DES_OFB8 0x00000151 +#define CKM_DES_CFB64 0x00000152 +#define CKM_DES_CFB8 0x00000153 + +#define CKM_MD2 0x00000200 + +/* CKM_MD2_HMAC and CKM_MD2_HMAC_GENERAL are new for v2.0 */ +#define CKM_MD2_HMAC 0x00000201 +#define CKM_MD2_HMAC_GENERAL 0x00000202 + +#define CKM_MD5 0x00000210 + +/* CKM_MD5_HMAC and CKM_MD5_HMAC_GENERAL are new for v2.0 */ +#define CKM_MD5_HMAC 0x00000211 +#define CKM_MD5_HMAC_GENERAL 0x00000212 + +#define CKM_SHA_1 0x00000220 + +/* CKM_SHA_1_HMAC and CKM_SHA_1_HMAC_GENERAL are new for v2.0 */ +#define CKM_SHA_1_HMAC 0x00000221 +#define CKM_SHA_1_HMAC_GENERAL 0x00000222 + +/* CKM_RIPEMD128, CKM_RIPEMD128_HMAC, + * CKM_RIPEMD128_HMAC_GENERAL, CKM_RIPEMD160, CKM_RIPEMD160_HMAC, + * and CKM_RIPEMD160_HMAC_GENERAL are new for v2.10 */ +#define CKM_RIPEMD128 0x00000230 +#define CKM_RIPEMD128_HMAC 0x00000231 +#define CKM_RIPEMD128_HMAC_GENERAL 0x00000232 +#define CKM_RIPEMD160 0x00000240 +#define CKM_RIPEMD160_HMAC 0x00000241 +#define CKM_RIPEMD160_HMAC_GENERAL 0x00000242 + +/* CKM_SHA256/384/512 are new for v2.20 */ +#define CKM_SHA256 0x00000250 +#define CKM_SHA256_HMAC 0x00000251 +#define CKM_SHA256_HMAC_GENERAL 0x00000252 + +/* SHA-224 is new for PKCS #11 v2.20 amendment 3 */ +#define CKM_SHA224 0x00000255 +#define CKM_SHA224_HMAC 0x00000256 +#define CKM_SHA224_HMAC_GENERAL 0x00000257 + +#define CKM_SHA384 0x00000260 +#define CKM_SHA384_HMAC 0x00000261 +#define CKM_SHA384_HMAC_GENERAL 0x00000262 +#define CKM_SHA512 0x00000270 +#define CKM_SHA512_HMAC 0x00000271 +#define CKM_SHA512_HMAC_GENERAL 0x00000272 + +/* SecurID is new for PKCS #11 v2.20 amendment 1 */ +#define CKM_SECURID_KEY_GEN 0x00000280 +#define CKM_SECURID 0x00000282 + +/* HOTP is new for PKCS #11 v2.20 amendment 1 */ +#define CKM_HOTP_KEY_GEN 0x00000290 +#define CKM_HOTP 0x00000291 + +/* ACTI is new for PKCS #11 v2.20 amendment 1 */ +#define CKM_ACTI 0x000002A0 +#define CKM_ACTI_KEY_GEN 0x000002A1 + +/* All of the following mechanisms are new for v2.0 */ +/* Note that CAST128 and CAST5 are the same algorithm */ +#define CKM_CAST_KEY_GEN 0x00000300 +#define CKM_CAST_ECB 0x00000301 +#define CKM_CAST_CBC 0x00000302 +#define CKM_CAST_MAC 0x00000303 +#define CKM_CAST_MAC_GENERAL 0x00000304 +#define CKM_CAST_CBC_PAD 0x00000305 +#define CKM_CAST3_KEY_GEN 0x00000310 +#define CKM_CAST3_ECB 0x00000311 +#define CKM_CAST3_CBC 0x00000312 +#define CKM_CAST3_MAC 0x00000313 +#define CKM_CAST3_MAC_GENERAL 0x00000314 +#define CKM_CAST3_CBC_PAD 0x00000315 +#define CKM_CAST5_KEY_GEN 0x00000320 +#define CKM_CAST128_KEY_GEN 0x00000320 +#define CKM_CAST5_ECB 0x00000321 +#define CKM_CAST128_ECB 0x00000321 +#define CKM_CAST5_CBC 0x00000322 +#define CKM_CAST128_CBC 0x00000322 +#define CKM_CAST5_MAC 0x00000323 +#define CKM_CAST128_MAC 0x00000323 +#define CKM_CAST5_MAC_GENERAL 0x00000324 +#define CKM_CAST128_MAC_GENERAL 0x00000324 +#define CKM_CAST5_CBC_PAD 0x00000325 +#define CKM_CAST128_CBC_PAD 0x00000325 +#define CKM_RC5_KEY_GEN 0x00000330 +#define CKM_RC5_ECB 0x00000331 +#define CKM_RC5_CBC 0x00000332 +#define CKM_RC5_MAC 0x00000333 +#define CKM_RC5_MAC_GENERAL 0x00000334 +#define CKM_RC5_CBC_PAD 0x00000335 +#define CKM_IDEA_KEY_GEN 0x00000340 +#define CKM_IDEA_ECB 0x00000341 +#define CKM_IDEA_CBC 0x00000342 +#define CKM_IDEA_MAC 0x00000343 +#define CKM_IDEA_MAC_GENERAL 0x00000344 +#define CKM_IDEA_CBC_PAD 0x00000345 +#define CKM_GENERIC_SECRET_KEY_GEN 0x00000350 +#define CKM_CONCATENATE_BASE_AND_KEY 0x00000360 +#define CKM_CONCATENATE_BASE_AND_DATA 0x00000362 +#define CKM_CONCATENATE_DATA_AND_BASE 0x00000363 +#define CKM_XOR_BASE_AND_DATA 0x00000364 +#define CKM_EXTRACT_KEY_FROM_KEY 0x00000365 +#define CKM_SSL3_PRE_MASTER_KEY_GEN 0x00000370 +#define CKM_SSL3_MASTER_KEY_DERIVE 0x00000371 +#define CKM_SSL3_KEY_AND_MAC_DERIVE 0x00000372 + +/* CKM_SSL3_MASTER_KEY_DERIVE_DH, CKM_TLS_PRE_MASTER_KEY_GEN, + * CKM_TLS_MASTER_KEY_DERIVE, CKM_TLS_KEY_AND_MAC_DERIVE, and + * CKM_TLS_MASTER_KEY_DERIVE_DH are new for v2.11 */ +#define CKM_SSL3_MASTER_KEY_DERIVE_DH 0x00000373 +#define CKM_TLS_PRE_MASTER_KEY_GEN 0x00000374 +#define CKM_TLS_MASTER_KEY_DERIVE 0x00000375 +#define CKM_TLS_KEY_AND_MAC_DERIVE 0x00000376 +#define CKM_TLS_MASTER_KEY_DERIVE_DH 0x00000377 + +/* CKM_TLS_PRF is new for v2.20 */ +#define CKM_TLS_PRF 0x00000378 + +#define CKM_SSL3_MD5_MAC 0x00000380 +#define CKM_SSL3_SHA1_MAC 0x00000381 +#define CKM_MD5_KEY_DERIVATION 0x00000390 +#define CKM_MD2_KEY_DERIVATION 0x00000391 +#define CKM_SHA1_KEY_DERIVATION 0x00000392 + +/* CKM_SHA256/384/512 are new for v2.20 */ +#define CKM_SHA256_KEY_DERIVATION 0x00000393 +#define CKM_SHA384_KEY_DERIVATION 0x00000394 +#define CKM_SHA512_KEY_DERIVATION 0x00000395 + +/* SHA-224 key derivation is new for PKCS #11 v2.20 amendment 3 */ +#define CKM_SHA224_KEY_DERIVATION 0x00000396 + +#define CKM_PBE_MD2_DES_CBC 0x000003A0 +#define CKM_PBE_MD5_DES_CBC 0x000003A1 +#define CKM_PBE_MD5_CAST_CBC 0x000003A2 +#define CKM_PBE_MD5_CAST3_CBC 0x000003A3 +#define CKM_PBE_MD5_CAST5_CBC 0x000003A4 +#define CKM_PBE_MD5_CAST128_CBC 0x000003A4 +#define CKM_PBE_SHA1_CAST5_CBC 0x000003A5 +#define CKM_PBE_SHA1_CAST128_CBC 0x000003A5 +#define CKM_PBE_SHA1_RC4_128 0x000003A6 +#define CKM_PBE_SHA1_RC4_40 0x000003A7 +#define CKM_PBE_SHA1_DES3_EDE_CBC 0x000003A8 +#define CKM_PBE_SHA1_DES2_EDE_CBC 0x000003A9 +#define CKM_PBE_SHA1_RC2_128_CBC 0x000003AA +#define CKM_PBE_SHA1_RC2_40_CBC 0x000003AB + +/* CKM_PKCS5_PBKD2 is new for v2.10 */ +#define CKM_PKCS5_PBKD2 0x000003B0 + +#define CKM_PBA_SHA1_WITH_SHA1_HMAC 0x000003C0 + +/* WTLS mechanisms are new for v2.20 */ +#define CKM_WTLS_PRE_MASTER_KEY_GEN 0x000003D0 +#define CKM_WTLS_MASTER_KEY_DERIVE 0x000003D1 +#define CKM_WTLS_MASTER_KEY_DERIVE_DH_ECC 0x000003D2 +#define CKM_WTLS_PRF 0x000003D3 +#define CKM_WTLS_SERVER_KEY_AND_MAC_DERIVE 0x000003D4 +#define CKM_WTLS_CLIENT_KEY_AND_MAC_DERIVE 0x000003D5 + +#define CKM_KEY_WRAP_LYNKS 0x00000400 +#define CKM_KEY_WRAP_SET_OAEP 0x00000401 + +/* CKM_CMS_SIG is new for v2.20 */ +#define CKM_CMS_SIG 0x00000500 + +/* CKM_KIP mechanisms are new for PKCS #11 v2.20 amendment 2 */ +#define CKM_KIP_DERIVE 0x00000510 +#define CKM_KIP_WRAP 0x00000511 +#define CKM_KIP_MAC 0x00000512 + +/* Camellia is new for PKCS #11 v2.20 amendment 3 */ +#define CKM_CAMELLIA_KEY_GEN 0x00000550 +#define CKM_CAMELLIA_ECB 0x00000551 +#define CKM_CAMELLIA_CBC 0x00000552 +#define CKM_CAMELLIA_MAC 0x00000553 +#define CKM_CAMELLIA_MAC_GENERAL 0x00000554 +#define CKM_CAMELLIA_CBC_PAD 0x00000555 +#define CKM_CAMELLIA_ECB_ENCRYPT_DATA 0x00000556 +#define CKM_CAMELLIA_CBC_ENCRYPT_DATA 0x00000557 +#define CKM_CAMELLIA_CTR 0x00000558 + +/* ARIA is new for PKCS #11 v2.20 amendment 3 */ +#define CKM_ARIA_KEY_GEN 0x00000560 +#define CKM_ARIA_ECB 0x00000561 +#define CKM_ARIA_CBC 0x00000562 +#define CKM_ARIA_MAC 0x00000563 +#define CKM_ARIA_MAC_GENERAL 0x00000564 +#define CKM_ARIA_CBC_PAD 0x00000565 +#define CKM_ARIA_ECB_ENCRYPT_DATA 0x00000566 +#define CKM_ARIA_CBC_ENCRYPT_DATA 0x00000567 + +/* Fortezza mechanisms */ +#define CKM_SKIPJACK_KEY_GEN 0x00001000 +#define CKM_SKIPJACK_ECB64 0x00001001 +#define CKM_SKIPJACK_CBC64 0x00001002 +#define CKM_SKIPJACK_OFB64 0x00001003 +#define CKM_SKIPJACK_CFB64 0x00001004 +#define CKM_SKIPJACK_CFB32 0x00001005 +#define CKM_SKIPJACK_CFB16 0x00001006 +#define CKM_SKIPJACK_CFB8 0x00001007 +#define CKM_SKIPJACK_WRAP 0x00001008 +#define CKM_SKIPJACK_PRIVATE_WRAP 0x00001009 +#define CKM_SKIPJACK_RELAYX 0x0000100a +#define CKM_KEA_KEY_PAIR_GEN 0x00001010 +#define CKM_KEA_KEY_DERIVE 0x00001011 +#define CKM_FORTEZZA_TIMESTAMP 0x00001020 +#define CKM_BATON_KEY_GEN 0x00001030 +#define CKM_BATON_ECB128 0x00001031 +#define CKM_BATON_ECB96 0x00001032 +#define CKM_BATON_CBC128 0x00001033 +#define CKM_BATON_COUNTER 0x00001034 +#define CKM_BATON_SHUFFLE 0x00001035 +#define CKM_BATON_WRAP 0x00001036 + +/* CKM_ECDSA_KEY_PAIR_GEN is deprecated in v2.11, + * CKM_EC_KEY_PAIR_GEN is preferred */ +#define CKM_ECDSA_KEY_PAIR_GEN 0x00001040 +#define CKM_EC_KEY_PAIR_GEN 0x00001040 + +#define CKM_ECDSA 0x00001041 +#define CKM_ECDSA_SHA1 0x00001042 + +/* CKM_ECDH1_DERIVE, CKM_ECDH1_COFACTOR_DERIVE, and CKM_ECMQV_DERIVE + * are new for v2.11 */ +#define CKM_ECDH1_DERIVE 0x00001050 +#define CKM_ECDH1_COFACTOR_DERIVE 0x00001051 +#define CKM_ECMQV_DERIVE 0x00001052 + +#define CKM_JUNIPER_KEY_GEN 0x00001060 +#define CKM_JUNIPER_ECB128 0x00001061 +#define CKM_JUNIPER_CBC128 0x00001062 +#define CKM_JUNIPER_COUNTER 0x00001063 +#define CKM_JUNIPER_SHUFFLE 0x00001064 +#define CKM_JUNIPER_WRAP 0x00001065 +#define CKM_FASTHASH 0x00001070 + +/* CKM_AES_KEY_GEN, CKM_AES_ECB, CKM_AES_CBC, CKM_AES_MAC, + * CKM_AES_MAC_GENERAL, CKM_AES_CBC_PAD, CKM_DSA_PARAMETER_GEN, + * CKM_DH_PKCS_PARAMETER_GEN, and CKM_X9_42_DH_PARAMETER_GEN are + * new for v2.11 */ +#define CKM_AES_KEY_GEN 0x00001080 +#define CKM_AES_ECB 0x00001081 +#define CKM_AES_CBC 0x00001082 +#define CKM_AES_MAC 0x00001083 +#define CKM_AES_MAC_GENERAL 0x00001084 +#define CKM_AES_CBC_PAD 0x00001085 + +/* AES counter mode is new for PKCS #11 v2.20 amendment 3 */ +#define CKM_AES_CTR 0x00001086 + +/* BlowFish and TwoFish are new for v2.20 */ +#define CKM_BLOWFISH_KEY_GEN 0x00001090 +#define CKM_BLOWFISH_CBC 0x00001091 +#define CKM_TWOFISH_KEY_GEN 0x00001092 +#define CKM_TWOFISH_CBC 0x00001093 + + +/* CKM_xxx_ENCRYPT_DATA mechanisms are new for v2.20 */ +#define CKM_DES_ECB_ENCRYPT_DATA 0x00001100 +#define CKM_DES_CBC_ENCRYPT_DATA 0x00001101 +#define CKM_DES3_ECB_ENCRYPT_DATA 0x00001102 +#define CKM_DES3_CBC_ENCRYPT_DATA 0x00001103 +#define CKM_AES_ECB_ENCRYPT_DATA 0x00001104 +#define CKM_AES_CBC_ENCRYPT_DATA 0x00001105 + +#define CKM_DSA_PARAMETER_GEN 0x00002000 +#define CKM_DH_PKCS_PARAMETER_GEN 0x00002001 +#define CKM_X9_42_DH_PARAMETER_GEN 0x00002002 + +#define CKM_VENDOR_DEFINED 0x80000000 + +typedef CK_MECHANISM_TYPE CK_PTR CK_MECHANISM_TYPE_PTR; + + +/* CK_MECHANISM is a structure that specifies a particular + * mechanism */ +typedef struct CK_MECHANISM { + CK_MECHANISM_TYPE mechanism; + CK_VOID_PTR pParameter; + + /* ulParameterLen was changed from CK_USHORT to CK_ULONG for + * v2.0 */ + CK_ULONG ulParameterLen; /* in bytes */ +} CK_MECHANISM; + +typedef CK_MECHANISM CK_PTR CK_MECHANISM_PTR; + + +/* CK_MECHANISM_INFO provides information about a particular + * mechanism */ +typedef struct CK_MECHANISM_INFO { + CK_ULONG ulMinKeySize; + CK_ULONG ulMaxKeySize; + CK_FLAGS flags; +} CK_MECHANISM_INFO; + +/* The flags are defined as follows: + * Bit Flag Mask Meaning */ +#define CKF_HW 0x00000001 /* performed by HW */ + +/* The flags CKF_ENCRYPT, CKF_DECRYPT, CKF_DIGEST, CKF_SIGN, + * CKG_SIGN_RECOVER, CKF_VERIFY, CKF_VERIFY_RECOVER, + * CKF_GENERATE, CKF_GENERATE_KEY_PAIR, CKF_WRAP, CKF_UNWRAP, + * and CKF_DERIVE are new for v2.0. They specify whether or not + * a mechanism can be used for a particular task */ +#define CKF_ENCRYPT 0x00000100 +#define CKF_DECRYPT 0x00000200 +#define CKF_DIGEST 0x00000400 +#define CKF_SIGN 0x00000800 +#define CKF_SIGN_RECOVER 0x00001000 +#define CKF_VERIFY 0x00002000 +#define CKF_VERIFY_RECOVER 0x00004000 +#define CKF_GENERATE 0x00008000 +#define CKF_GENERATE_KEY_PAIR 0x00010000 +#define CKF_WRAP 0x00020000 +#define CKF_UNWRAP 0x00040000 +#define CKF_DERIVE 0x00080000 + +/* CKF_EC_F_P, CKF_EC_F_2M, CKF_EC_ECPARAMETERS, CKF_EC_NAMEDCURVE, + * CKF_EC_UNCOMPRESS, and CKF_EC_COMPRESS are new for v2.11. They + * describe a token's EC capabilities not available in mechanism + * information. */ +#define CKF_EC_F_P 0x00100000 +#define CKF_EC_F_2M 0x00200000 +#define CKF_EC_ECPARAMETERS 0x00400000 +#define CKF_EC_NAMEDCURVE 0x00800000 +#define CKF_EC_UNCOMPRESS 0x01000000 +#define CKF_EC_COMPRESS 0x02000000 + +#define CKF_EXTENSION 0x80000000 /* FALSE for this version */ + +typedef CK_MECHANISM_INFO CK_PTR CK_MECHANISM_INFO_PTR; + + +/* CK_RV is a value that identifies the return value of a + * Cryptoki function */ +/* CK_RV was changed from CK_USHORT to CK_ULONG for v2.0 */ +typedef CK_ULONG CK_RV; + +#define CKR_OK 0x00000000 +#define CKR_CANCEL 0x00000001 +#define CKR_HOST_MEMORY 0x00000002 +#define CKR_SLOT_ID_INVALID 0x00000003 + +/* CKR_FLAGS_INVALID was removed for v2.0 */ + +/* CKR_GENERAL_ERROR and CKR_FUNCTION_FAILED are new for v2.0 */ +#define CKR_GENERAL_ERROR 0x00000005 +#define CKR_FUNCTION_FAILED 0x00000006 + +/* CKR_ARGUMENTS_BAD, CKR_NO_EVENT, CKR_NEED_TO_CREATE_THREADS, + * and CKR_CANT_LOCK are new for v2.01 */ +#define CKR_ARGUMENTS_BAD 0x00000007 +#define CKR_NO_EVENT 0x00000008 +#define CKR_NEED_TO_CREATE_THREADS 0x00000009 +#define CKR_CANT_LOCK 0x0000000A + +#define CKR_ATTRIBUTE_READ_ONLY 0x00000010 +#define CKR_ATTRIBUTE_SENSITIVE 0x00000011 +#define CKR_ATTRIBUTE_TYPE_INVALID 0x00000012 +#define CKR_ATTRIBUTE_VALUE_INVALID 0x00000013 +#define CKR_DATA_INVALID 0x00000020 +#define CKR_DATA_LEN_RANGE 0x00000021 +#define CKR_DEVICE_ERROR 0x00000030 +#define CKR_DEVICE_MEMORY 0x00000031 +#define CKR_DEVICE_REMOVED 0x00000032 +#define CKR_ENCRYPTED_DATA_INVALID 0x00000040 +#define CKR_ENCRYPTED_DATA_LEN_RANGE 0x00000041 +#define CKR_FUNCTION_CANCELED 0x00000050 +#define CKR_FUNCTION_NOT_PARALLEL 0x00000051 + +/* CKR_FUNCTION_NOT_SUPPORTED is new for v2.0 */ +#define CKR_FUNCTION_NOT_SUPPORTED 0x00000054 + +#define CKR_KEY_HANDLE_INVALID 0x00000060 + +/* CKR_KEY_SENSITIVE was removed for v2.0 */ + +#define CKR_KEY_SIZE_RANGE 0x00000062 +#define CKR_KEY_TYPE_INCONSISTENT 0x00000063 + +/* CKR_KEY_NOT_NEEDED, CKR_KEY_CHANGED, CKR_KEY_NEEDED, + * CKR_KEY_INDIGESTIBLE, CKR_KEY_FUNCTION_NOT_PERMITTED, + * CKR_KEY_NOT_WRAPPABLE, and CKR_KEY_UNEXTRACTABLE are new for + * v2.0 */ +#define CKR_KEY_NOT_NEEDED 0x00000064 +#define CKR_KEY_CHANGED 0x00000065 +#define CKR_KEY_NEEDED 0x00000066 +#define CKR_KEY_INDIGESTIBLE 0x00000067 +#define CKR_KEY_FUNCTION_NOT_PERMITTED 0x00000068 +#define CKR_KEY_NOT_WRAPPABLE 0x00000069 +#define CKR_KEY_UNEXTRACTABLE 0x0000006A + +#define CKR_MECHANISM_INVALID 0x00000070 +#define CKR_MECHANISM_PARAM_INVALID 0x00000071 + +/* CKR_OBJECT_CLASS_INCONSISTENT and CKR_OBJECT_CLASS_INVALID + * were removed for v2.0 */ +#define CKR_OBJECT_HANDLE_INVALID 0x00000082 +#define CKR_OPERATION_ACTIVE 0x00000090 +#define CKR_OPERATION_NOT_INITIALIZED 0x00000091 +#define CKR_PIN_INCORRECT 0x000000A0 +#define CKR_PIN_INVALID 0x000000A1 +#define CKR_PIN_LEN_RANGE 0x000000A2 + +/* CKR_PIN_EXPIRED and CKR_PIN_LOCKED are new for v2.0 */ +#define CKR_PIN_EXPIRED 0x000000A3 +#define CKR_PIN_LOCKED 0x000000A4 + +#define CKR_SESSION_CLOSED 0x000000B0 +#define CKR_SESSION_COUNT 0x000000B1 +#define CKR_SESSION_HANDLE_INVALID 0x000000B3 +#define CKR_SESSION_PARALLEL_NOT_SUPPORTED 0x000000B4 +#define CKR_SESSION_READ_ONLY 0x000000B5 +#define CKR_SESSION_EXISTS 0x000000B6 + +/* CKR_SESSION_READ_ONLY_EXISTS and + * CKR_SESSION_READ_WRITE_SO_EXISTS are new for v2.0 */ +#define CKR_SESSION_READ_ONLY_EXISTS 0x000000B7 +#define CKR_SESSION_READ_WRITE_SO_EXISTS 0x000000B8 + +#define CKR_SIGNATURE_INVALID 0x000000C0 +#define CKR_SIGNATURE_LEN_RANGE 0x000000C1 +#define CKR_TEMPLATE_INCOMPLETE 0x000000D0 +#define CKR_TEMPLATE_INCONSISTENT 0x000000D1 +#define CKR_TOKEN_NOT_PRESENT 0x000000E0 +#define CKR_TOKEN_NOT_RECOGNIZED 0x000000E1 +#define CKR_TOKEN_WRITE_PROTECTED 0x000000E2 +#define CKR_UNWRAPPING_KEY_HANDLE_INVALID 0x000000F0 +#define CKR_UNWRAPPING_KEY_SIZE_RANGE 0x000000F1 +#define CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT 0x000000F2 +#define CKR_USER_ALREADY_LOGGED_IN 0x00000100 +#define CKR_USER_NOT_LOGGED_IN 0x00000101 +#define CKR_USER_PIN_NOT_INITIALIZED 0x00000102 +#define CKR_USER_TYPE_INVALID 0x00000103 + +/* CKR_USER_ANOTHER_ALREADY_LOGGED_IN and CKR_USER_TOO_MANY_TYPES + * are new to v2.01 */ +#define CKR_USER_ANOTHER_ALREADY_LOGGED_IN 0x00000104 +#define CKR_USER_TOO_MANY_TYPES 0x00000105 + +#define CKR_WRAPPED_KEY_INVALID 0x00000110 +#define CKR_WRAPPED_KEY_LEN_RANGE 0x00000112 +#define CKR_WRAPPING_KEY_HANDLE_INVALID 0x00000113 +#define CKR_WRAPPING_KEY_SIZE_RANGE 0x00000114 +#define CKR_WRAPPING_KEY_TYPE_INCONSISTENT 0x00000115 +#define CKR_RANDOM_SEED_NOT_SUPPORTED 0x00000120 + +/* These are new to v2.0 */ +#define CKR_RANDOM_NO_RNG 0x00000121 + +/* These are new to v2.11 */ +#define CKR_DOMAIN_PARAMS_INVALID 0x00000130 + +/* These are new to v2.0 */ +#define CKR_BUFFER_TOO_SMALL 0x00000150 +#define CKR_SAVED_STATE_INVALID 0x00000160 +#define CKR_INFORMATION_SENSITIVE 0x00000170 +#define CKR_STATE_UNSAVEABLE 0x00000180 + +/* These are new to v2.01 */ +#define CKR_CRYPTOKI_NOT_INITIALIZED 0x00000190 +#define CKR_CRYPTOKI_ALREADY_INITIALIZED 0x00000191 +#define CKR_MUTEX_BAD 0x000001A0 +#define CKR_MUTEX_NOT_LOCKED 0x000001A1 + +/* The following return values are new for PKCS #11 v2.20 amendment 3 */ +#define CKR_NEW_PIN_MODE 0x000001B0 +#define CKR_NEXT_OTP 0x000001B1 + +/* This is new to v2.20 */ +#define CKR_FUNCTION_REJECTED 0x00000200 + +#define CKR_VENDOR_DEFINED 0x80000000 + + +/* CK_NOTIFY is an application callback that processes events */ +typedef CK_CALLBACK_FUNCTION(CK_RV, CK_NOTIFY)( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_NOTIFICATION event, + CK_VOID_PTR pApplication /* passed to C_OpenSession */ +); + + +/* CK_FUNCTION_LIST is a structure holding a Cryptoki spec + * version and pointers of appropriate types to all the + * Cryptoki functions */ +/* CK_FUNCTION_LIST is new for v2.0 */ +typedef struct CK_FUNCTION_LIST CK_FUNCTION_LIST; + +typedef CK_FUNCTION_LIST CK_PTR CK_FUNCTION_LIST_PTR; + +typedef CK_FUNCTION_LIST_PTR CK_PTR CK_FUNCTION_LIST_PTR_PTR; + + +/* CK_CREATEMUTEX is an application callback for creating a + * mutex object */ +typedef CK_CALLBACK_FUNCTION(CK_RV, CK_CREATEMUTEX)( + CK_VOID_PTR_PTR ppMutex /* location to receive ptr to mutex */ +); + + +/* CK_DESTROYMUTEX is an application callback for destroying a + * mutex object */ +typedef CK_CALLBACK_FUNCTION(CK_RV, CK_DESTROYMUTEX)( + CK_VOID_PTR pMutex /* pointer to mutex */ +); + + +/* CK_LOCKMUTEX is an application callback for locking a mutex */ +typedef CK_CALLBACK_FUNCTION(CK_RV, CK_LOCKMUTEX)( + CK_VOID_PTR pMutex /* pointer to mutex */ +); + + +/* CK_UNLOCKMUTEX is an application callback for unlocking a + * mutex */ +typedef CK_CALLBACK_FUNCTION(CK_RV, CK_UNLOCKMUTEX)( + CK_VOID_PTR pMutex /* pointer to mutex */ +); + + +/* CK_C_INITIALIZE_ARGS provides the optional arguments to + * C_Initialize */ +typedef struct CK_C_INITIALIZE_ARGS { + CK_CREATEMUTEX CreateMutex; + CK_DESTROYMUTEX DestroyMutex; + CK_LOCKMUTEX LockMutex; + CK_UNLOCKMUTEX UnlockMutex; + CK_FLAGS flags; + CK_VOID_PTR pReserved; +} CK_C_INITIALIZE_ARGS; + +/* flags: bit flags that provide capabilities of the slot + * Bit Flag Mask Meaning + */ +#define CKF_LIBRARY_CANT_CREATE_OS_THREADS 0x00000001 +#define CKF_OS_LOCKING_OK 0x00000002 + +typedef CK_C_INITIALIZE_ARGS CK_PTR CK_C_INITIALIZE_ARGS_PTR; + + +/* additional flags for parameters to functions */ + +/* CKF_DONT_BLOCK is for the function C_WaitForSlotEvent */ +#define CKF_DONT_BLOCK 1 + +/* CK_RSA_PKCS_OAEP_MGF_TYPE is new for v2.10. + * CK_RSA_PKCS_OAEP_MGF_TYPE is used to indicate the Message + * Generation Function (MGF) applied to a message block when + * formatting a message block for the PKCS #1 OAEP encryption + * scheme. */ +typedef CK_ULONG CK_RSA_PKCS_MGF_TYPE; + +typedef CK_RSA_PKCS_MGF_TYPE CK_PTR CK_RSA_PKCS_MGF_TYPE_PTR; + +/* The following MGFs are defined */ +/* CKG_MGF1_SHA256, CKG_MGF1_SHA384, and CKG_MGF1_SHA512 + * are new for v2.20 */ +#define CKG_MGF1_SHA1 0x00000001 +#define CKG_MGF1_SHA256 0x00000002 +#define CKG_MGF1_SHA384 0x00000003 +#define CKG_MGF1_SHA512 0x00000004 +/* SHA-224 is new for PKCS #11 v2.20 amendment 3 */ +#define CKG_MGF1_SHA224 0x00000005 + +/* CK_RSA_PKCS_OAEP_SOURCE_TYPE is new for v2.10. + * CK_RSA_PKCS_OAEP_SOURCE_TYPE is used to indicate the source + * of the encoding parameter when formatting a message block + * for the PKCS #1 OAEP encryption scheme. */ +typedef CK_ULONG CK_RSA_PKCS_OAEP_SOURCE_TYPE; + +typedef CK_RSA_PKCS_OAEP_SOURCE_TYPE CK_PTR CK_RSA_PKCS_OAEP_SOURCE_TYPE_PTR; + +/* The following encoding parameter sources are defined */ +#define CKZ_DATA_SPECIFIED 0x00000001 + +/* CK_RSA_PKCS_OAEP_PARAMS is new for v2.10. + * CK_RSA_PKCS_OAEP_PARAMS provides the parameters to the + * CKM_RSA_PKCS_OAEP mechanism. */ +typedef struct CK_RSA_PKCS_OAEP_PARAMS { + CK_MECHANISM_TYPE hashAlg; + CK_RSA_PKCS_MGF_TYPE mgf; + CK_RSA_PKCS_OAEP_SOURCE_TYPE source; + CK_VOID_PTR pSourceData; + CK_ULONG ulSourceDataLen; +} CK_RSA_PKCS_OAEP_PARAMS; + +typedef CK_RSA_PKCS_OAEP_PARAMS CK_PTR CK_RSA_PKCS_OAEP_PARAMS_PTR; + +/* CK_RSA_PKCS_PSS_PARAMS is new for v2.11. + * CK_RSA_PKCS_PSS_PARAMS provides the parameters to the + * CKM_RSA_PKCS_PSS mechanism(s). */ +typedef struct CK_RSA_PKCS_PSS_PARAMS { + CK_MECHANISM_TYPE hashAlg; + CK_RSA_PKCS_MGF_TYPE mgf; + CK_ULONG sLen; +} CK_RSA_PKCS_PSS_PARAMS; + +typedef CK_RSA_PKCS_PSS_PARAMS CK_PTR CK_RSA_PKCS_PSS_PARAMS_PTR; + +/* CK_EC_KDF_TYPE is new for v2.11. */ +typedef CK_ULONG CK_EC_KDF_TYPE; + +/* The following EC Key Derivation Functions are defined */ +#define CKD_NULL 0x00000001 +#define CKD_SHA1_KDF 0x00000002 + +/* CK_ECDH1_DERIVE_PARAMS is new for v2.11. + * CK_ECDH1_DERIVE_PARAMS provides the parameters to the + * CKM_ECDH1_DERIVE and CKM_ECDH1_COFACTOR_DERIVE mechanisms, + * where each party contributes one key pair. + */ +typedef struct CK_ECDH1_DERIVE_PARAMS { + CK_EC_KDF_TYPE kdf; + CK_ULONG ulSharedDataLen; + CK_BYTE_PTR pSharedData; + CK_ULONG ulPublicDataLen; + CK_BYTE_PTR pPublicData; +} CK_ECDH1_DERIVE_PARAMS; + +typedef CK_ECDH1_DERIVE_PARAMS CK_PTR CK_ECDH1_DERIVE_PARAMS_PTR; + + +/* CK_ECDH2_DERIVE_PARAMS is new for v2.11. + * CK_ECDH2_DERIVE_PARAMS provides the parameters to the + * CKM_ECMQV_DERIVE mechanism, where each party contributes two key pairs. */ +typedef struct CK_ECDH2_DERIVE_PARAMS { + CK_EC_KDF_TYPE kdf; + CK_ULONG ulSharedDataLen; + CK_BYTE_PTR pSharedData; + CK_ULONG ulPublicDataLen; + CK_BYTE_PTR pPublicData; + CK_ULONG ulPrivateDataLen; + CK_OBJECT_HANDLE hPrivateData; + CK_ULONG ulPublicDataLen2; + CK_BYTE_PTR pPublicData2; +} CK_ECDH2_DERIVE_PARAMS; + +typedef CK_ECDH2_DERIVE_PARAMS CK_PTR CK_ECDH2_DERIVE_PARAMS_PTR; + +typedef struct CK_ECMQV_DERIVE_PARAMS { + CK_EC_KDF_TYPE kdf; + CK_ULONG ulSharedDataLen; + CK_BYTE_PTR pSharedData; + CK_ULONG ulPublicDataLen; + CK_BYTE_PTR pPublicData; + CK_ULONG ulPrivateDataLen; + CK_OBJECT_HANDLE hPrivateData; + CK_ULONG ulPublicDataLen2; + CK_BYTE_PTR pPublicData2; + CK_OBJECT_HANDLE publicKey; +} CK_ECMQV_DERIVE_PARAMS; + +typedef CK_ECMQV_DERIVE_PARAMS CK_PTR CK_ECMQV_DERIVE_PARAMS_PTR; + +/* Typedefs and defines for the CKM_X9_42_DH_KEY_PAIR_GEN and the + * CKM_X9_42_DH_PARAMETER_GEN mechanisms (new for PKCS #11 v2.11) */ +typedef CK_ULONG CK_X9_42_DH_KDF_TYPE; +typedef CK_X9_42_DH_KDF_TYPE CK_PTR CK_X9_42_DH_KDF_TYPE_PTR; + +/* The following X9.42 DH key derivation functions are defined + (besides CKD_NULL already defined : */ +#define CKD_SHA1_KDF_ASN1 0x00000003 +#define CKD_SHA1_KDF_CONCATENATE 0x00000004 + +/* CK_X9_42_DH1_DERIVE_PARAMS is new for v2.11. + * CK_X9_42_DH1_DERIVE_PARAMS provides the parameters to the + * CKM_X9_42_DH_DERIVE key derivation mechanism, where each party + * contributes one key pair */ +typedef struct CK_X9_42_DH1_DERIVE_PARAMS { + CK_X9_42_DH_KDF_TYPE kdf; + CK_ULONG ulOtherInfoLen; + CK_BYTE_PTR pOtherInfo; + CK_ULONG ulPublicDataLen; + CK_BYTE_PTR pPublicData; +} CK_X9_42_DH1_DERIVE_PARAMS; + +typedef struct CK_X9_42_DH1_DERIVE_PARAMS CK_PTR CK_X9_42_DH1_DERIVE_PARAMS_PTR; + +/* CK_X9_42_DH2_DERIVE_PARAMS is new for v2.11. + * CK_X9_42_DH2_DERIVE_PARAMS provides the parameters to the + * CKM_X9_42_DH_HYBRID_DERIVE and CKM_X9_42_MQV_DERIVE key derivation + * mechanisms, where each party contributes two key pairs */ +typedef struct CK_X9_42_DH2_DERIVE_PARAMS { + CK_X9_42_DH_KDF_TYPE kdf; + CK_ULONG ulOtherInfoLen; + CK_BYTE_PTR pOtherInfo; + CK_ULONG ulPublicDataLen; + CK_BYTE_PTR pPublicData; + CK_ULONG ulPrivateDataLen; + CK_OBJECT_HANDLE hPrivateData; + CK_ULONG ulPublicDataLen2; + CK_BYTE_PTR pPublicData2; +} CK_X9_42_DH2_DERIVE_PARAMS; + +typedef CK_X9_42_DH2_DERIVE_PARAMS CK_PTR CK_X9_42_DH2_DERIVE_PARAMS_PTR; + +typedef struct CK_X9_42_MQV_DERIVE_PARAMS { + CK_X9_42_DH_KDF_TYPE kdf; + CK_ULONG ulOtherInfoLen; + CK_BYTE_PTR pOtherInfo; + CK_ULONG ulPublicDataLen; + CK_BYTE_PTR pPublicData; + CK_ULONG ulPrivateDataLen; + CK_OBJECT_HANDLE hPrivateData; + CK_ULONG ulPublicDataLen2; + CK_BYTE_PTR pPublicData2; + CK_OBJECT_HANDLE publicKey; +} CK_X9_42_MQV_DERIVE_PARAMS; + +typedef CK_X9_42_MQV_DERIVE_PARAMS CK_PTR CK_X9_42_MQV_DERIVE_PARAMS_PTR; + +/* CK_KEA_DERIVE_PARAMS provides the parameters to the + * CKM_KEA_DERIVE mechanism */ +/* CK_KEA_DERIVE_PARAMS is new for v2.0 */ +typedef struct CK_KEA_DERIVE_PARAMS { + CK_BBOOL isSender; + CK_ULONG ulRandomLen; + CK_BYTE_PTR pRandomA; + CK_BYTE_PTR pRandomB; + CK_ULONG ulPublicDataLen; + CK_BYTE_PTR pPublicData; +} CK_KEA_DERIVE_PARAMS; + +typedef CK_KEA_DERIVE_PARAMS CK_PTR CK_KEA_DERIVE_PARAMS_PTR; + + +/* CK_RC2_PARAMS provides the parameters to the CKM_RC2_ECB and + * CKM_RC2_MAC mechanisms. An instance of CK_RC2_PARAMS just + * holds the effective keysize */ +typedef CK_ULONG CK_RC2_PARAMS; + +typedef CK_RC2_PARAMS CK_PTR CK_RC2_PARAMS_PTR; + + +/* CK_RC2_CBC_PARAMS provides the parameters to the CKM_RC2_CBC + * mechanism */ +typedef struct CK_RC2_CBC_PARAMS { + /* ulEffectiveBits was changed from CK_USHORT to CK_ULONG for + * v2.0 */ + CK_ULONG ulEffectiveBits; /* effective bits (1-1024) */ + + CK_BYTE iv[8]; /* IV for CBC mode */ +} CK_RC2_CBC_PARAMS; + +typedef CK_RC2_CBC_PARAMS CK_PTR CK_RC2_CBC_PARAMS_PTR; + + +/* CK_RC2_MAC_GENERAL_PARAMS provides the parameters for the + * CKM_RC2_MAC_GENERAL mechanism */ +/* CK_RC2_MAC_GENERAL_PARAMS is new for v2.0 */ +typedef struct CK_RC2_MAC_GENERAL_PARAMS { + CK_ULONG ulEffectiveBits; /* effective bits (1-1024) */ + CK_ULONG ulMacLength; /* Length of MAC in bytes */ +} CK_RC2_MAC_GENERAL_PARAMS; + +typedef CK_RC2_MAC_GENERAL_PARAMS CK_PTR \ + CK_RC2_MAC_GENERAL_PARAMS_PTR; + + +/* CK_RC5_PARAMS provides the parameters to the CKM_RC5_ECB and + * CKM_RC5_MAC mechanisms */ +/* CK_RC5_PARAMS is new for v2.0 */ +typedef struct CK_RC5_PARAMS { + CK_ULONG ulWordsize; /* wordsize in bits */ + CK_ULONG ulRounds; /* number of rounds */ +} CK_RC5_PARAMS; + +typedef CK_RC5_PARAMS CK_PTR CK_RC5_PARAMS_PTR; + + +/* CK_RC5_CBC_PARAMS provides the parameters to the CKM_RC5_CBC + * mechanism */ +/* CK_RC5_CBC_PARAMS is new for v2.0 */ +typedef struct CK_RC5_CBC_PARAMS { + CK_ULONG ulWordsize; /* wordsize in bits */ + CK_ULONG ulRounds; /* number of rounds */ + CK_BYTE_PTR pIv; /* pointer to IV */ + CK_ULONG ulIvLen; /* length of IV in bytes */ +} CK_RC5_CBC_PARAMS; + +typedef CK_RC5_CBC_PARAMS CK_PTR CK_RC5_CBC_PARAMS_PTR; + + +/* CK_RC5_MAC_GENERAL_PARAMS provides the parameters for the + * CKM_RC5_MAC_GENERAL mechanism */ +/* CK_RC5_MAC_GENERAL_PARAMS is new for v2.0 */ +typedef struct CK_RC5_MAC_GENERAL_PARAMS { + CK_ULONG ulWordsize; /* wordsize in bits */ + CK_ULONG ulRounds; /* number of rounds */ + CK_ULONG ulMacLength; /* Length of MAC in bytes */ +} CK_RC5_MAC_GENERAL_PARAMS; + +typedef CK_RC5_MAC_GENERAL_PARAMS CK_PTR \ + CK_RC5_MAC_GENERAL_PARAMS_PTR; + + +/* CK_MAC_GENERAL_PARAMS provides the parameters to most block + * ciphers' MAC_GENERAL mechanisms. Its value is the length of + * the MAC */ +/* CK_MAC_GENERAL_PARAMS is new for v2.0 */ +typedef CK_ULONG CK_MAC_GENERAL_PARAMS; + +typedef CK_MAC_GENERAL_PARAMS CK_PTR CK_MAC_GENERAL_PARAMS_PTR; + +/* CK_DES/AES_ECB/CBC_ENCRYPT_DATA_PARAMS are new for v2.20 */ +typedef struct CK_DES_CBC_ENCRYPT_DATA_PARAMS { + CK_BYTE iv[8]; + CK_BYTE_PTR pData; + CK_ULONG length; +} CK_DES_CBC_ENCRYPT_DATA_PARAMS; + +typedef CK_DES_CBC_ENCRYPT_DATA_PARAMS CK_PTR CK_DES_CBC_ENCRYPT_DATA_PARAMS_PTR; + +typedef struct CK_AES_CBC_ENCRYPT_DATA_PARAMS { + CK_BYTE iv[16]; + CK_BYTE_PTR pData; + CK_ULONG length; +} CK_AES_CBC_ENCRYPT_DATA_PARAMS; + +typedef CK_AES_CBC_ENCRYPT_DATA_PARAMS CK_PTR CK_AES_CBC_ENCRYPT_DATA_PARAMS_PTR; + +/* CK_SKIPJACK_PRIVATE_WRAP_PARAMS provides the parameters to the + * CKM_SKIPJACK_PRIVATE_WRAP mechanism */ +/* CK_SKIPJACK_PRIVATE_WRAP_PARAMS is new for v2.0 */ +typedef struct CK_SKIPJACK_PRIVATE_WRAP_PARAMS { + CK_ULONG ulPasswordLen; + CK_BYTE_PTR pPassword; + CK_ULONG ulPublicDataLen; + CK_BYTE_PTR pPublicData; + CK_ULONG ulPAndGLen; + CK_ULONG ulQLen; + CK_ULONG ulRandomLen; + CK_BYTE_PTR pRandomA; + CK_BYTE_PTR pPrimeP; + CK_BYTE_PTR pBaseG; + CK_BYTE_PTR pSubprimeQ; +} CK_SKIPJACK_PRIVATE_WRAP_PARAMS; + +typedef CK_SKIPJACK_PRIVATE_WRAP_PARAMS CK_PTR \ + CK_SKIPJACK_PRIVATE_WRAP_PTR; + + +/* CK_SKIPJACK_RELAYX_PARAMS provides the parameters to the + * CKM_SKIPJACK_RELAYX mechanism */ +/* CK_SKIPJACK_RELAYX_PARAMS is new for v2.0 */ +typedef struct CK_SKIPJACK_RELAYX_PARAMS { + CK_ULONG ulOldWrappedXLen; + CK_BYTE_PTR pOldWrappedX; + CK_ULONG ulOldPasswordLen; + CK_BYTE_PTR pOldPassword; + CK_ULONG ulOldPublicDataLen; + CK_BYTE_PTR pOldPublicData; + CK_ULONG ulOldRandomLen; + CK_BYTE_PTR pOldRandomA; + CK_ULONG ulNewPasswordLen; + CK_BYTE_PTR pNewPassword; + CK_ULONG ulNewPublicDataLen; + CK_BYTE_PTR pNewPublicData; + CK_ULONG ulNewRandomLen; + CK_BYTE_PTR pNewRandomA; +} CK_SKIPJACK_RELAYX_PARAMS; + +typedef CK_SKIPJACK_RELAYX_PARAMS CK_PTR \ + CK_SKIPJACK_RELAYX_PARAMS_PTR; + + +typedef struct CK_PBE_PARAMS { + CK_BYTE_PTR pInitVector; + CK_UTF8CHAR_PTR pPassword; + CK_ULONG ulPasswordLen; + CK_BYTE_PTR pSalt; + CK_ULONG ulSaltLen; + CK_ULONG ulIteration; +} CK_PBE_PARAMS; + +typedef CK_PBE_PARAMS CK_PTR CK_PBE_PARAMS_PTR; + + +/* CK_KEY_WRAP_SET_OAEP_PARAMS provides the parameters to the + * CKM_KEY_WRAP_SET_OAEP mechanism */ +/* CK_KEY_WRAP_SET_OAEP_PARAMS is new for v2.0 */ +typedef struct CK_KEY_WRAP_SET_OAEP_PARAMS { + CK_BYTE bBC; /* block contents byte */ + CK_BYTE_PTR pX; /* extra data */ + CK_ULONG ulXLen; /* length of extra data in bytes */ +} CK_KEY_WRAP_SET_OAEP_PARAMS; + +typedef CK_KEY_WRAP_SET_OAEP_PARAMS CK_PTR \ + CK_KEY_WRAP_SET_OAEP_PARAMS_PTR; + + +typedef struct CK_SSL3_RANDOM_DATA { + CK_BYTE_PTR pClientRandom; + CK_ULONG ulClientRandomLen; + CK_BYTE_PTR pServerRandom; + CK_ULONG ulServerRandomLen; +} CK_SSL3_RANDOM_DATA; + + +typedef struct CK_SSL3_MASTER_KEY_DERIVE_PARAMS { + CK_SSL3_RANDOM_DATA RandomInfo; + CK_VERSION_PTR pVersion; +} CK_SSL3_MASTER_KEY_DERIVE_PARAMS; + +typedef struct CK_SSL3_MASTER_KEY_DERIVE_PARAMS CK_PTR \ + CK_SSL3_MASTER_KEY_DERIVE_PARAMS_PTR; + + +typedef struct CK_SSL3_KEY_MAT_OUT { + CK_OBJECT_HANDLE hClientMacSecret; + CK_OBJECT_HANDLE hServerMacSecret; + CK_OBJECT_HANDLE hClientKey; + CK_OBJECT_HANDLE hServerKey; + CK_BYTE_PTR pIVClient; + CK_BYTE_PTR pIVServer; +} CK_SSL3_KEY_MAT_OUT; + +typedef CK_SSL3_KEY_MAT_OUT CK_PTR CK_SSL3_KEY_MAT_OUT_PTR; + + +typedef struct CK_SSL3_KEY_MAT_PARAMS { + CK_ULONG ulMacSizeInBits; + CK_ULONG ulKeySizeInBits; + CK_ULONG ulIVSizeInBits; + CK_BBOOL bIsExport; + CK_SSL3_RANDOM_DATA RandomInfo; + CK_SSL3_KEY_MAT_OUT_PTR pReturnedKeyMaterial; +} CK_SSL3_KEY_MAT_PARAMS; + +typedef CK_SSL3_KEY_MAT_PARAMS CK_PTR CK_SSL3_KEY_MAT_PARAMS_PTR; + +/* CK_TLS_PRF_PARAMS is new for version 2.20 */ +typedef struct CK_TLS_PRF_PARAMS { + CK_BYTE_PTR pSeed; + CK_ULONG ulSeedLen; + CK_BYTE_PTR pLabel; + CK_ULONG ulLabelLen; + CK_BYTE_PTR pOutput; + CK_ULONG_PTR pulOutputLen; +} CK_TLS_PRF_PARAMS; + +typedef CK_TLS_PRF_PARAMS CK_PTR CK_TLS_PRF_PARAMS_PTR; + +/* WTLS is new for version 2.20 */ +typedef struct CK_WTLS_RANDOM_DATA { + CK_BYTE_PTR pClientRandom; + CK_ULONG ulClientRandomLen; + CK_BYTE_PTR pServerRandom; + CK_ULONG ulServerRandomLen; +} CK_WTLS_RANDOM_DATA; + +typedef CK_WTLS_RANDOM_DATA CK_PTR CK_WTLS_RANDOM_DATA_PTR; + +typedef struct CK_WTLS_MASTER_KEY_DERIVE_PARAMS { + CK_MECHANISM_TYPE DigestMechanism; + CK_WTLS_RANDOM_DATA RandomInfo; + CK_BYTE_PTR pVersion; +} CK_WTLS_MASTER_KEY_DERIVE_PARAMS; + +typedef CK_WTLS_MASTER_KEY_DERIVE_PARAMS CK_PTR \ + CK_WTLS_MASTER_KEY_DERIVE_PARAMS_PTR; + +typedef struct CK_WTLS_PRF_PARAMS { + CK_MECHANISM_TYPE DigestMechanism; + CK_BYTE_PTR pSeed; + CK_ULONG ulSeedLen; + CK_BYTE_PTR pLabel; + CK_ULONG ulLabelLen; + CK_BYTE_PTR pOutput; + CK_ULONG_PTR pulOutputLen; +} CK_WTLS_PRF_PARAMS; + +typedef CK_WTLS_PRF_PARAMS CK_PTR CK_WTLS_PRF_PARAMS_PTR; + +typedef struct CK_WTLS_KEY_MAT_OUT { + CK_OBJECT_HANDLE hMacSecret; + CK_OBJECT_HANDLE hKey; + CK_BYTE_PTR pIV; +} CK_WTLS_KEY_MAT_OUT; + +typedef CK_WTLS_KEY_MAT_OUT CK_PTR CK_WTLS_KEY_MAT_OUT_PTR; + +typedef struct CK_WTLS_KEY_MAT_PARAMS { + CK_MECHANISM_TYPE DigestMechanism; + CK_ULONG ulMacSizeInBits; + CK_ULONG ulKeySizeInBits; + CK_ULONG ulIVSizeInBits; + CK_ULONG ulSequenceNumber; + CK_BBOOL bIsExport; + CK_WTLS_RANDOM_DATA RandomInfo; + CK_WTLS_KEY_MAT_OUT_PTR pReturnedKeyMaterial; +} CK_WTLS_KEY_MAT_PARAMS; + +typedef CK_WTLS_KEY_MAT_PARAMS CK_PTR CK_WTLS_KEY_MAT_PARAMS_PTR; + +/* CMS is new for version 2.20 */ +typedef struct CK_CMS_SIG_PARAMS { + CK_OBJECT_HANDLE certificateHandle; + CK_MECHANISM_PTR pSigningMechanism; + CK_MECHANISM_PTR pDigestMechanism; + CK_UTF8CHAR_PTR pContentType; + CK_BYTE_PTR pRequestedAttributes; + CK_ULONG ulRequestedAttributesLen; + CK_BYTE_PTR pRequiredAttributes; + CK_ULONG ulRequiredAttributesLen; +} CK_CMS_SIG_PARAMS; + +typedef CK_CMS_SIG_PARAMS CK_PTR CK_CMS_SIG_PARAMS_PTR; + +typedef struct CK_KEY_DERIVATION_STRING_DATA { + CK_BYTE_PTR pData; + CK_ULONG ulLen; +} CK_KEY_DERIVATION_STRING_DATA; + +typedef CK_KEY_DERIVATION_STRING_DATA CK_PTR \ + CK_KEY_DERIVATION_STRING_DATA_PTR; + + +/* The CK_EXTRACT_PARAMS is used for the + * CKM_EXTRACT_KEY_FROM_KEY mechanism. It specifies which bit + * of the base key should be used as the first bit of the + * derived key */ +/* CK_EXTRACT_PARAMS is new for v2.0 */ +typedef CK_ULONG CK_EXTRACT_PARAMS; + +typedef CK_EXTRACT_PARAMS CK_PTR CK_EXTRACT_PARAMS_PTR; + +/* CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE is new for v2.10. + * CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE is used to + * indicate the Pseudo-Random Function (PRF) used to generate + * key bits using PKCS #5 PBKDF2. */ +typedef CK_ULONG CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE; + +typedef CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE CK_PTR CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE_PTR; + +/* The following PRFs are defined in PKCS #5 v2.0. */ +#define CKP_PKCS5_PBKD2_HMAC_SHA1 0x00000001 + + +/* CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE is new for v2.10. + * CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE is used to indicate the + * source of the salt value when deriving a key using PKCS #5 + * PBKDF2. */ +typedef CK_ULONG CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE; + +typedef CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE CK_PTR CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE_PTR; + +/* The following salt value sources are defined in PKCS #5 v2.0. */ +#define CKZ_SALT_SPECIFIED 0x00000001 + +/* CK_PKCS5_PBKD2_PARAMS is new for v2.10. + * CK_PKCS5_PBKD2_PARAMS is a structure that provides the + * parameters to the CKM_PKCS5_PBKD2 mechanism. */ +typedef struct CK_PKCS5_PBKD2_PARAMS { + CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE saltSource; + CK_VOID_PTR pSaltSourceData; + CK_ULONG ulSaltSourceDataLen; + CK_ULONG iterations; + CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE prf; + CK_VOID_PTR pPrfData; + CK_ULONG ulPrfDataLen; + CK_UTF8CHAR_PTR pPassword; + CK_ULONG_PTR ulPasswordLen; +} CK_PKCS5_PBKD2_PARAMS; + +typedef CK_PKCS5_PBKD2_PARAMS CK_PTR CK_PKCS5_PBKD2_PARAMS_PTR; + +/* All CK_OTP structs are new for PKCS #11 v2.20 amendment 3 */ + +typedef CK_ULONG CK_OTP_PARAM_TYPE; +typedef CK_OTP_PARAM_TYPE CK_PARAM_TYPE; /* B/w compatibility */ + +typedef struct CK_OTP_PARAM { + CK_OTP_PARAM_TYPE type; + CK_VOID_PTR pValue; + CK_ULONG ulValueLen; +} CK_OTP_PARAM; + +typedef CK_OTP_PARAM CK_PTR CK_OTP_PARAM_PTR; + +typedef struct CK_OTP_PARAMS { + CK_OTP_PARAM_PTR pParams; + CK_ULONG ulCount; +} CK_OTP_PARAMS; + +typedef CK_OTP_PARAMS CK_PTR CK_OTP_PARAMS_PTR; + +typedef struct CK_OTP_SIGNATURE_INFO { + CK_OTP_PARAM_PTR pParams; + CK_ULONG ulCount; +} CK_OTP_SIGNATURE_INFO; + +typedef CK_OTP_SIGNATURE_INFO CK_PTR CK_OTP_SIGNATURE_INFO_PTR; + +/* The following OTP-related defines are new for PKCS #11 v2.20 amendment 1 */ +#define CK_OTP_VALUE 0 +#define CK_OTP_PIN 1 +#define CK_OTP_CHALLENGE 2 +#define CK_OTP_TIME 3 +#define CK_OTP_COUNTER 4 +#define CK_OTP_FLAGS 5 +#define CK_OTP_OUTPUT_LENGTH 6 +#define CK_OTP_OUTPUT_FORMAT 7 + +/* The following OTP-related defines are new for PKCS #11 v2.20 amendment 1 */ +#define CKF_NEXT_OTP 0x00000001 +#define CKF_EXCLUDE_TIME 0x00000002 +#define CKF_EXCLUDE_COUNTER 0x00000004 +#define CKF_EXCLUDE_CHALLENGE 0x00000008 +#define CKF_EXCLUDE_PIN 0x00000010 +#define CKF_USER_FRIENDLY_OTP 0x00000020 + +/* CK_KIP_PARAMS is new for PKCS #11 v2.20 amendment 2 */ +typedef struct CK_KIP_PARAMS { + CK_MECHANISM_PTR pMechanism; + CK_OBJECT_HANDLE hKey; + CK_BYTE_PTR pSeed; + CK_ULONG ulSeedLen; +} CK_KIP_PARAMS; + +typedef CK_KIP_PARAMS CK_PTR CK_KIP_PARAMS_PTR; + +/* CK_AES_CTR_PARAMS is new for PKCS #11 v2.20 amendment 3 */ +typedef struct CK_AES_CTR_PARAMS { + CK_ULONG ulCounterBits; + CK_BYTE cb[16]; +} CK_AES_CTR_PARAMS; + +typedef CK_AES_CTR_PARAMS CK_PTR CK_AES_CTR_PARAMS_PTR; + +/* CK_CAMELLIA_CTR_PARAMS is new for PKCS #11 v2.20 amendment 3 */ +typedef struct CK_CAMELLIA_CTR_PARAMS { + CK_ULONG ulCounterBits; + CK_BYTE cb[16]; +} CK_CAMELLIA_CTR_PARAMS; + +typedef CK_CAMELLIA_CTR_PARAMS CK_PTR CK_CAMELLIA_CTR_PARAMS_PTR; + +/* CK_CAMELLIA_CBC_ENCRYPT_DATA_PARAMS is new for PKCS #11 v2.20 amendment 3 */ +typedef struct CK_CAMELLIA_CBC_ENCRYPT_DATA_PARAMS { + CK_BYTE iv[16]; + CK_BYTE_PTR pData; + CK_ULONG length; +} CK_CAMELLIA_CBC_ENCRYPT_DATA_PARAMS; + +typedef CK_CAMELLIA_CBC_ENCRYPT_DATA_PARAMS CK_PTR CK_CAMELLIA_CBC_ENCRYPT_DATA_PARAMS_PTR; + +/* CK_ARIA_CBC_ENCRYPT_DATA_PARAMS is new for PKCS #11 v2.20 amendment 3 */ +typedef struct CK_ARIA_CBC_ENCRYPT_DATA_PARAMS { + CK_BYTE iv[16]; + CK_BYTE_PTR pData; + CK_ULONG length; +} CK_ARIA_CBC_ENCRYPT_DATA_PARAMS; + +typedef CK_ARIA_CBC_ENCRYPT_DATA_PARAMS CK_PTR CK_ARIA_CBC_ENCRYPT_DATA_PARAMS_PTR; + +#endif Index: openssl/util/libeay.num diff -u openssl/util/libeay.num:1.7.6.1.4.1.2.1.4.1 openssl/util/libeay.num:1.7.2.3 --- openssl/util/libeay.num:1.7.6.1.4.1.2.1.4.1 Wed Mar 4 13:46:38 2015 +++ openssl/util/libeay.num Wed Mar 4 13:57:56 2015 @@ -3731,4 +3731,6 @@ pqueue_size 4114 EXIST::FUNCTION: OPENSSL_uni2asc 4115 EXIST:NETWARE:FUNCTION: OPENSSL_asc2uni 4116 EXIST:NETWARE:FUNCTION: +ENGINE_load_pk11ca 4117 EXIST::FUNCTION:HW_PKCS11CA,ENGINE +ENGINE_load_pk11so 4117 EXIST::FUNCTION:HW_PKCS11SO,ENGINE ASN1_TYPE_cmp 4428 EXIST::FUNCTION: Index: openssl/util/mk1mf.pl diff -u openssl/util/mk1mf.pl:1.8.6.1.10.1 openssl/util/mk1mf.pl:1.8.2.1 --- openssl/util/mk1mf.pl:1.8.6.1.10.1 Wed Mar 4 13:46:38 2015 +++ openssl/util/mk1mf.pl Wed Mar 4 13:57:57 2015 @@ -87,6 +87,8 @@ no-ecdh - No ECDH no-engine - No engine no-hw - No hw + no-hw-pkcs11ca - No hw PKCS#11 CA flavor + no-hw-pkcs11so - No hw PKCS#11 SO flavor nasm - Use NASM for x86 asm nw-nasm - Use NASM x86 asm for NetWare nw-mwasm - Use Metrowerks x86 asm for NetWare @@ -242,6 +244,8 @@ $cflags.=" -DOPENSSL_NO_ECDH" if $no_ecdh; $cflags.=" -DOPENSSL_NO_ENGINE" if $no_engine; $cflags.=" -DOPENSSL_NO_HW" if $no_hw; +$cflags.=" -DOPENSSL_NO_HW_PKCS11CA" if $no_hw_pkcs11ca; +$cflags.=" -DOPENSSL_NO_HW_PKCS11SO" if $no_hw_pkcs11so; $cflags.=" -DOPENSSL_FIPS" if $fips; $cflags.= " -DZLIB" if $zlib_opt; $cflags.= " -DZLIB_SHARED" if $zlib_opt == 2; @@ -316,6 +320,9 @@ $dir=$val; } + if ($key eq "PK11_LIB_LOCATION") + { $cflags .= " -D$key=\\\"$val\\\"" if $val ne "";} + if ($key eq "KRB5_INCLUDES") { $cflags .= " $val";} @@ -1295,6 +1302,8 @@ "no-ecdh" => \$no_ecdh, "no-engine" => \$no_engine, "no-hw" => \$no_hw, + "no-hw-pkcs11ca" => \$no_hw_pkcs11ca, + "no-hw-pkcs11so" => \$no_hw_pkcs11so, "just-ssl" => [\$no_rc2, \$no_idea, \$no_des, \$no_bf, \$no_cast, \$no_md2, \$no_sha, \$no_mdc2, \$no_dsa, \$no_dh, Index: openssl/util/mkdef.pl diff -u openssl/util/mkdef.pl:1.6.6.1 openssl/util/mkdef.pl:1.6 --- openssl/util/mkdef.pl:1.6.6.1 Sun Jan 15 15:45:40 2012 +++ openssl/util/mkdef.pl Mon Jun 13 14:25:25 2011 @@ -93,7 +93,7 @@ # External "algorithms" "FP_API", "STDIO", "SOCK", "KRB5", "DGRAM", # Engines - "STATIC_ENGINE", "ENGINE", "HW", "GMP", + "STATIC_ENGINE", "ENGINE", "HW", "GMP", "HW_PKCS11CA", "HW_PKCS11SO", # RFC3779 support "RFC3779", # TLS extension support @@ -122,6 +122,7 @@ my $no_md2; my $no_md4; my $no_md5; my $no_sha; my $no_ripemd; my $no_mdc2; my $no_rsa; my $no_dsa; my $no_dh; my $no_hmac=0; my $no_aes; my $no_krb5; my $no_ec; my $no_ecdsa; my $no_ecdh; my $no_engine; my $no_hw; my $no_camellia; +my $no_pkcs11ca; my $no_pkcs11so; my $no_seed; my $no_fp_api; my $no_static_engine; my $no_gmp; my $no_deprecated; my $no_rfc3779; my $no_tlsext; my $no_cms; my $no_capieng; my $no_jpake; @@ -214,6 +215,8 @@ elsif (/^no-cms$/) { $no_cms=1; } elsif (/^no-capieng$/) { $no_capieng=1; } elsif (/^no-jpake$/) { $no_jpake=1; } + elsif (/^no-hw-pkcs11ca$/) { $no_pkcs11ca=1; } + elsif (/^no-hw-pkcs11so$/) { $no_pkcs11so=1; } } @@ -1155,6 +1158,8 @@ if ($keyword eq "KRB5" && $no_krb5) { return 0; } if ($keyword eq "ENGINE" && $no_engine) { return 0; } if ($keyword eq "HW" && $no_hw) { return 0; } + if ($keyword eq "HW_PKCS11CA" && $no_pkcs11ca) { return 0; } + if ($keyword eq "HW_PKCS11SO" && $no_pkcs11so) { return 0; } if ($keyword eq "FP_API" && $no_fp_api) { return 0; } if ($keyword eq "STATIC_ENGINE" && $no_static_engine) { return 0; } if ($keyword eq "GMP" && $no_gmp) { return 0; } Index: openssl/util/pl/VC-32.pl diff -u openssl/util/pl/VC-32.pl:1.6.6.1.2.1.4.1 openssl/util/pl/VC-32.pl:1.6.2.2 --- openssl/util/pl/VC-32.pl:1.6.6.1.2.1.4.1 Thu Jul 3 12:12:38 2014 +++ openssl/util/pl/VC-32.pl Thu Jul 3 12:32:04 2014 @@ -52,7 +52,7 @@ my $f = $shlib || $fips ?' /MD':' /MT'; $lib_cflag='/Zl' if (!$shlib); # remove /DEFAULTLIBs from static lib $opt_cflags=$f.' /Ox'; - $dbg_cflags=$f.'d /Od -DDEBUG -D_DEBUG'; + $dbg_cflags=$f.'d /Od /Zi -DDEBUG -D_DEBUG'; $lflags="/nologo /subsystem:console /opt:ref"; } elsif ($FLAVOR =~ /CE/) bind9-9.11.3+dfsg/bin/pkcs11/openssl-1.0.0t-patch000066400000000000000000016352651325250447100207510ustar00rootroot00000000000000Index: openssl/Configure diff -u openssl/Configure:1.9.2.1.2.1.4.1.2.1 openssl/Configure:1.11.2.2 --- openssl/Configure:1.9.2.1.2.1.4.1.2.1 Tue Jan 7 09:25:41 2014 +++ openssl/Configure Tue Jan 7 09:28:47 2014 @@ -10,7 +10,7 @@ # see INSTALL for instructions. -my $usage="Usage: Configure [no- ...] [enable- ...] [experimental- ...] [-Dxxx] [-lxxx] [-Lxxx] [-fxxx] [-Kxxx] [no-hw-xxx|no-hw] [[no-]threads] [[no-]shared] [[no-]zlib|zlib-dynamic] [no-asm] [no-dso] [no-krb5] [386] [--prefix=DIR] [--openssldir=OPENSSLDIR] [--with-xxx[=vvv]] [--test-sanity] os/compiler[:flags]\n"; +my $usage="Usage: Configure --pk11-libname=PK11_LIB_LOCATION --pk11-flavor=FLAVOR [no- ...] [enable- ...] [experimental- ...] [-Dxxx] [-lxxx] [-Lxxx] [-fxxx] [-Kxxx] [no-hw-xxx|no-hw] [[no-]threads] [[no-]shared] [[no-]zlib|zlib-dynamic] [no-asm] [no-dso] [no-krb5] [386] [--prefix=DIR] [--openssldir=OPENSSLDIR] [--with-xxx[=vvv]] [--test-sanity] os/compiler[:flags]\n"; # Options: # @@ -23,6 +23,12 @@ # default). This needn't be set in advance, you can # just as well use "make INSTALL_PREFIX=/whatever install". # +# --pk11-libname PKCS#11 library name. +# (No default) +# +# --pk11-flavor either crypto-accelerator or sign-only +# (No default) +# # --with-krb5-dir Declare where Kerberos 5 lives. The libraries are expected # to live in the subdirectory lib/ and the header files in # include/. A value is required. @@ -344,7 +350,7 @@ "linux-armv4", "gcc:-DTERMIO -O3 -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${armv4_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", #### IA-32 targets... "linux-ia32-icc", "icc:-DL_ENDIAN -DTERMIO -O2 -no_cpprt::-D_REENTRANT::-ldl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_elf_asm}:dlfcn:linux-shared:-KPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", -"linux-elf", "gcc:-DL_ENDIAN -DTERMIO -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_elf_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", +"linux-elf", "gcc:-DL_ENDIAN -DTERMIO -O3 -fomit-frame-pointer -Wall::-D_REENTRANT -pthread::-ldl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_elf_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", "linux-aout", "gcc:-DL_ENDIAN -DTERMIO -O3 -fomit-frame-pointer -march=i486 -Wall::(unknown):::BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_asm}:a.out", #### "linux-generic64","gcc:-DTERMIO -O3 -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${no_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", @@ -352,7 +358,7 @@ "linux-ia64", "gcc:-DL_ENDIAN -DTERMIO -O3 -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_UNROLL DES_INT:${ia64_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", "linux-ia64-ecc","ecc:-DL_ENDIAN -DTERMIO -O2 -Wall -no_cpprt::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_INT:${ia64_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", "linux-ia64-icc","icc:-DL_ENDIAN -DTERMIO -O2 -Wall -no_cpprt::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_RISC1 DES_INT:${ia64_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", -"linux-x86_64", "gcc:-m64 -DL_ENDIAN -DTERMIO -O3 -Wall -DMD32_REG_T=int::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_INT DES_UNROLL:${x86_64_asm}:elf:dlfcn:linux-shared:-fPIC:-m64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):::64", +"linux-x86_64", "gcc:-m64 -DL_ENDIAN -DTERMIO -O3 -Wall -DMD32_REG_T=int::-D_REENTRANT -pthread::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_INT DES_UNROLL:${x86_64_asm}:elf:dlfcn:linux-shared:-fPIC:-m64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):::64", "linux-s390x", "gcc:-m64 -DB_ENDIAN -DTERMIO -O3 -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL:${s390x_asm}:dlfcn:linux-shared:-fPIC:-m64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):::64", #### SPARC Linux setups # Ray Miller has patiently @@ -623,6 +629,10 @@ my $idx_arflags = $idx++; my $idx_multilib = $idx++; +# PKCS#11 engine patch +my $pk11_libname=""; +my $pk11_flavor=""; + my $prefix=""; my $libdir=""; my $openssldir=""; @@ -825,6 +835,14 @@ { $flags.=$_." "; } + elsif (/^--pk11-libname=(.*)$/) + { + $pk11_libname=$1; + } + elsif (/^--pk11-flavor=(.*)$/) + { + $pk11_flavor=$1; + } elsif (/^--prefix=(.*)$/) { $prefix=$1; @@ -962,6 +980,22 @@ exit 0; } +if (! $pk11_libname) + { + print STDERR "You must set --pk11-libname for PKCS#11 library.\n"; + print STDERR "See README.pkcs11 for more information.\n"; + exit 1; + } + +if (! $pk11_flavor + || !($pk11_flavor eq "crypto-accelerator" || $pk11_flavor eq "sign-only")) + { + print STDERR "You must set --pk11-flavor.\n"; + print STDERR "Choices are crypto-accelerator and sign-only.\n"; + print STDERR "See README.pkcs11 for more information.\n"; + exit 1; + } + if ($target =~ m/^CygWin32(-.*)$/) { $target = "Cygwin".$1; } @@ -1039,6 +1073,25 @@ $exp_cflags .= " -DOPENSSL_EXPERIMENTAL_$ALGO"; } +if ($pk11_flavor eq "crypto-accelerator") + { + $openssl_other_defines .= "#define OPENSSL_NO_HW_PKCS11SO\n"; + $default_depflags .= " -DOPENSSL_NO_HW_PKCS11SO"; + $depflags .= " -DOPENSSL_NO_HW_PKCS11SO"; + $options .= " no-hw-pkcs11so"; + print " no-hw-pkcs11so [pk11-flavor]"; + print " OPENSSL_NO_HW_PKCS11SO\n"; + } +else + { + $openssl_other_defines .= "#define OPENSSL_NO_HW_PKCS11CA\n"; + $default_depflags .= " -DOPENSSL_NO_HW_PKCS11CA"; + $depflags .= " -DOPENSSL_NO_HW_PKCS11CA"; + $options .= " no-hw-pkcs11ca"; + print " no-hw-pkcs11ca [pk11-flavor]"; + print " OPENSSL_NO_HW_PKCS11CA\n"; +} + my $IsMK1MF=scalar grep /^$target$/,@MK1MF_Builds; $exe_ext=".exe" if ($target eq "Cygwin" || $target eq "DJGPP" || $target =~ /^mingw/); @@ -1126,6 +1179,8 @@ if ($flags ne "") { $cflags="$flags$cflags"; } else { $no_user_cflags=1; } +$cflags="-DPK11_LIB_LOCATION=\"$pk11_libname\" $cflags"; + # Kerberos settings. The flavor must be provided from outside, either through # the script "config" or manually. if (!$no_krb5) @@ -1495,6 +1550,7 @@ s/^VERSION=.*/VERSION=$version/; s/^MAJOR=.*/MAJOR=$major/; s/^MINOR=.*/MINOR=$minor/; + s/^PK11_LIB_LOCATION=.*/PK11_LIB_LOCATION=$pk11_libname/; s/^SHLIB_VERSION_NUMBER=.*/SHLIB_VERSION_NUMBER=$shlib_version_number/; s/^SHLIB_VERSION_HISTORY=.*/SHLIB_VERSION_HISTORY=$shlib_version_history/; s/^SHLIB_MAJOR=.*/SHLIB_MAJOR=$shlib_major/; Index: openssl/Makefile.org diff -u openssl/Makefile.org:1.5.2.1.2.1.14.1 openssl/Makefile.org:1.6.2.1 --- openssl/Makefile.org:1.5.2.1.2.1.14.1 Wed Dec 23 17:25:07 2015 +++ openssl/Makefile.org Wed Dec 23 17:43:50 2015 @@ -26,6 +26,9 @@ INSTALL_PREFIX= INSTALLTOP=/usr/local/ssl +# You must set this through --pk11-libname configure option. +PK11_LIB_LOCATION= + # Do not edit this manually. Use Configure --openssldir=DIR do change this! OPENSSLDIR=/usr/local/ssl Index: openssl/README.pkcs11 diff -u /dev/null openssl/README.pkcs11:1.7.4.1 --- /dev/null Wed Dec 23 17:47:10 2015 +++ openssl/README.pkcs11 Fri Oct 4 14:33:56 2013 @@ -0,0 +1,266 @@ +ISC modified +============ + +The previous key naming scheme was kept for backward compatibility. + +The PKCS#11 engine exists in two flavors, crypto-accelerator and +sign-only. The first one is from the Solaris patch and uses the +PKCS#11 device for all crypto operations it supports. The second +is a stripped down version which provides only the useful +function (i.e., signature with a RSA private key in the device +protected key store and key loading). + +As a hint PKCS#11 boards should use the crypto-accelerator flavor, +external PKCS#11 devices the sign-only. SCA 6000 is an example +of the first, AEP Keyper of the second. + +Note it is mandatory to set a pk11-flavor (and only one) in +config/Configure. + +It is highly recommended to compile in (vs. as a DSO) the engine. +The way to configure this is system dependent, on Unixes it is no-shared +(and is in general the default), on WIN32 it is enable-static-engine +(and still enable to build the OpenSSL libraries as DLLs). + +PKCS#11 engine support for OpenSSL 0.9.8l +========================================= + +[Nov 19, 2009] + +Contents: + +Overview +Revisions of the patch for 0.9.8 branch +FAQs +Feedback + +Overview +======== + +This patch containing code available in OpenSolaris adds support for PKCS#11 +engine into OpenSSL and implements PKCS#11 v2.20. It is to be applied against +OpenSSL 0.9.8l source code distribution as shipped by OpenSSL.Org. Your system +must provide PKCS#11 backend otherwise the patch is useless. You provide the +PKCS#11 library name during the build configuration phase, see below. + +Patch can be applied like this: + + # NOTE: use gtar if on Solaris + tar xfzv openssl-0.9.8l.tar.gz + # now download the patch to the current directory + # ... + cd openssl-0.9.8l + # NOTE: must use gpatch if on Solaris (is part of the system) + patch -p1 < path-to/pkcs11_engine-0.9.8l.patch.2009-11-19 + +It is designed to support pure acceleration for RSA, DSA, DH and all the +symetric ciphers and message digest algorithms that PKCS#11 and OpenSSL share +except for missing support for patented algorithms MDC2, RC3, RC5 and IDEA. + +According to the PKCS#11 providers installed on your machine, it can support +following mechanisms: + + RSA, DSA, DH, RAND, DES-CBC, DES-EDE3-CBC, DES-ECB, DES-EDE3, RC4, + AES-128-CBC, AES-192-CBC, AES-256-CBC, AES-128-ECB, AES-192-ECB, + AES-256-ECB, AES-128-CTR, AES-192-CTR, AES-256-CTR, MD5, SHA1, SHA224, + SHA256, SHA384, SHA512 + +Note that for AES counter mode the application must provide their own EVP +functions since OpenSSL doesn't support counter mode through EVP yet. You may +see OpenSSH source code (cipher.c) to get the idea how to do that. SunSSH is an +example of code that uses the PKCS#11 engine and deals with the fork-safety +problem (see engine.c and packet.c files if interested). + +You must provide the location of PKCS#11 library in your system to the +configure script. You will be instructed to do that when you try to run the +config script: + + $ ./config + Operating system: i86pc-whatever-solaris2 + Configuring for solaris-x86-cc + You must set --pk11-libname for PKCS#11 library. + See README.pkcs11 for more information. + +Taking openCryptoki project on Linux AMD64 box as an example, you would run +configure script like this: + + ./config --pk11-libname=/usr/lib64/pkcs11/PKCS11_API.so + +To check whether newly built openssl really supports PKCS#11 it's enough to run +"apps/openssl engine" and look for "(pkcs11) PKCS #11 engine support" in the +output. If you see no PKCS#11 engine support check that the built openssl binary +and the PKCS#11 library from --pk11-libname don't conflict on 32/64 bits. + +The patch, during various phases of development, was tested on Solaris against +PKCS#11 engine available from Solaris Cryptographic Framework (Solaris 10 and +OpenSolaris) and also on Linux using PKCS#11 libraries from openCryptoki project +(see openCryptoki website http://sourceforge.net/projects/opencryptoki for more +information). Some Linux distributions even ship those libraries with the +system. The patch should work on any system that is supported by OpenSSL itself +and has functional PKCS#11 library. + +The patch contains "RSA Security Inc. PKCS #11 Cryptographic Token Interface +(Cryptoki)" - files cryptoki.h, pkcs11.h, pkcs11f.h and pkcs11t.h which are +copyrighted by RSA Security Inc., see pkcs11.h for more information. + +Other added/modified code in this patch is copyrighted by Sun Microsystems, +Inc. and is released under the OpenSSL license (see LICENSE file for more +information). + +Revisions of the patch for 0.9.8 branch +======================================= + +2009-11-19 +- adjusted for OpenSSL version 0.9.8l + +- bugs and RFEs: + + 6479874 OpenSSL should support RSA key by reference/hardware keystores + 6896677 PKCS#11 engine's hw_pk11_err.h needs to be split + 6732677 make check to trigger Solaris specific code automatic in the + PKCS#11 engine + +2009-03-11 +- adjusted for OpenSSL version 0.9.8j + +- README.pkcs11 moved out of the patch, and is shipped together with it in a + tarball instead so that it can be read before the patch is applied. + +- fixed bugs: + + 6804216 pkcs#11 engine should support a key length range for RC4 + 6734038 Apache SSL web server using the pkcs11 engine fails to start if + meta slot is disabled + +2008-12-02 +- fixed bugs and RFEs (most of the work done by Vladimir Kotal) + + 6723504 more granular locking in PKCS#11 engine + 6667128 CRYPTO_LOCK_PK11_ENGINE assumption does not hold true + 6710420 PKCS#11 engine source should be lint clean + 6747327 PKCS#11 engine atfork handlers need to be aware of guys who take + it seriously + 6746712 PKCS#11 engine source code should be cstyle clean + 6731380 return codes of several functions are not checked in the PKCS#11 + engine code + 6746735 PKCS#11 engine should use extended FILE space API + 6734038 Apache SSL web server using the pkcs11 engine fails to start if + meta slot is disabled + +2008-08-01 +- fixed bug + + 6731839 OpenSSL PKCS#11 engine no longer uses n2cp for symmetric ciphers + and digests + +- Solaris specific code for slot selection made automatic + +2008-07-29 +- update the patch to OpenSSL 0.9.8h version +- pkcs11t.h updated to the latest version: + + 6545665 make CKM_AES_CTR available to non-kernel users + +- fixed bugs in the engine code: + + 6602801 PK11_SESSION cache has to employ reference counting scheme for + asymmetric key operations + 6605538 pkcs11 functions C_FindObjects[{Init,Final}]() not called + atomically + 6607307 pkcs#11 engine can't read RSA private keys + 6652362 pk11_RSA_finish() is cutting corners + 6662112 pk11_destroy_{rsa,dsa,dh}_key_objects() use locking in + suboptimal way + 6666625 pk11_destroy_{rsa,dsa,dh}_key_objects() should be more + resilient to destroy failures + 6667273 OpenSSL engine should not use free() but OPENSSL_free() + 6670363 PKCS#11 engine fails to reuse existing symmetric keys + 6678135 memory corruption in pk11_DH_generate_key() in pkcs#11 engine + 6678503 DSA signature conversion in pk11_dsa_do_verify() ignores size + of big numbers leading to failures + 6706562 pk11_DH_compute_key() returns 0 in case of failure instead of + -1 + 6706622 pk11_load_{pub,priv}key create corrupted RSA key references + 6707129 return values from BN_new() in pk11_DH_generate_key() are not + checked + 6707274 DSA/RSA/DH PKCS#11 engine operations need to be resistant to + structure reuse + 6707782 OpenSSL PKCS#11 engine pretends to be aware of + OPENSSL_NO_{RSA,DSA,DH} + defines but fails miserably + 6709966 make check_new_*() to return values to indicate cache hit/miss + 6705200 pk11_dh struct initialization in PKCS#11 engine is missing + generate_params parameter + 6709513 PKCS#11 engine sets IV length even for ECB modes + 6728296 buffer length not initialized for C_(En|De)crypt_Final() in the + PKCS#11 engine + 6728871 PKCS#11 engine must reset global_session in pk11_finish() + +- new features and enhancements: + + 6562155 OpenSSL pkcs#11 engine needs support for SHA224/256/384/512 + 6685012 OpenSSL pkcs#11 engine needs support for new cipher modes + 6725903 OpenSSL PKCS#11 engine shouldn't use soft token for symmetric + ciphers and digests + +2007-10-15 +- update for 0.9.8f version +- update for "6607670 teach pkcs#11 engine how to use keys be reference" + +2007-10-02 +- draft for "6607670 teach pkcs#11 engine how to use keys be reference" +- draft for "6607307 pkcs#11 engine can't read RSA private keys" + +2007-09-26 +- 6375348 Using pkcs11 as the SSLCryptoDevice with Apache/OpenSSL causes + significant performance drop +- 6573196 memory is leaked when OpenSSL is used with PKCS#11 engine + +2007-05-25 +- 6558630 race in OpenSSL pkcs11 engine when using symetric block ciphers + +2007-05-19 +- initial patch for 0.9.8e using latest OpenSolaris code + +FAQs +==== + +(1) my build failed on Linux distro with this error: + +../libcrypto.a(hw_pk11.o): In function `pk11_library_init': +hw_pk11.c:(.text+0x20f5): undefined reference to `pthread_atfork' + +Answer: + + - don't use "no-threads" when configuring + - if you didn't then OpenSSL failed to create a threaded library by + default. You may manually edit Configure and try again. Look for the + architecture that Configure printed, for example: + +Configured for linux-elf. + + - then edit Configure, find string "linux-elf" (inluding the quotes), + and add flags to support threads to the 4th column of the 2nd string. + If you build with GCC then adding "-pthread" should be enough. With + "linux-elf" as an example, you would add " -pthread" right after + "-D_REENTRANT", like this: + +....-O3 -fomit-frame-pointer -Wall::-D_REENTRANT -pthread::-ldl:..... + +(2) I'm using MinGW/MSYS environment and get undeclared reference error for +pthread_atfork() function when trying to build OpenSSL with the patch. + +Answer: + + Sorry, pthread_atfork() is not implemented in the current pthread-win32 + (as of Nov 2009). You can not use the patch there. + + +Feedback +======== + +Please send feedback to security-discuss@opensolaris.org. The patch was +created by Jan.Pechanec@Sun.COM from code available in OpenSolaris. + +Latest version should be always available on http://blogs.sun.com/janp. + Index: openssl/crypto/opensslconf.h diff -u openssl/crypto/opensslconf.h:1.6.2.1.16.1 openssl/crypto/opensslconf.h:1.6.4.1 --- openssl/crypto/opensslconf.h:1.6.2.1.16.1 Wed Dec 23 17:25:17 2015 +++ openssl/crypto/opensslconf.h Wed Dec 23 17:44:01 2015 @@ -29,6 +29,9 @@ #endif /* OPENSSL_DOING_MAKEDEPEND */ +#ifndef OPENSSL_THREADS +# define OPENSSL_THREADS +#endif #ifndef OPENSSL_NO_DYNAMIC_ENGINE # define OPENSSL_NO_DYNAMIC_ENGINE #endif @@ -61,6 +64,8 @@ # endif #endif +#define OPENSSL_CPUID_OBJ + /* crypto/opensslconf.h.in */ /* Generate 80386 code? */ @@ -107,7 +112,7 @@ * This enables code handling data aligned at natural CPU word * boundary. See crypto/rc4/rc4_enc.c for further details. */ -#undef RC4_CHUNK +#define RC4_CHUNK unsigned long #endif #endif @@ -115,7 +120,7 @@ /* If this is set to 'unsigned int' on a DEC Alpha, this gives about a * %20 speed up (longs are 8 bytes, int's are 4). */ #ifndef DES_LONG -#define DES_LONG unsigned long +#define DES_LONG unsigned int #endif #endif @@ -126,9 +131,9 @@ /* Should we define BN_DIV2W here? */ /* Only one for the following should be defined */ -#undef SIXTY_FOUR_BIT_LONG +#define SIXTY_FOUR_BIT_LONG #undef SIXTY_FOUR_BIT -#define THIRTY_TWO_BIT +#undef THIRTY_TWO_BIT #endif #if defined(HEADER_RC4_LOCL_H) && !defined(CONFIG_HEADER_RC4_LOCL_H) @@ -140,7 +145,7 @@ #if defined(HEADER_BF_LOCL_H) && !defined(CONFIG_HEADER_BF_LOCL_H) #define CONFIG_HEADER_BF_LOCL_H -#undef BF_PTR +#define BF_PTR2 #endif /* HEADER_BF_LOCL_H */ #if defined(HEADER_DES_LOCL_H) && !defined(CONFIG_HEADER_DES_LOCL_H) @@ -170,7 +175,7 @@ /* Unroll the inner loop, this sometimes helps, sometimes hinders. * Very mucy CPU dependant */ #ifndef DES_UNROLL -#undef DES_UNROLL +#define DES_UNROLL #endif /* These default values were supplied by Index: openssl/crypto/bio/bss_file.c diff -u openssl/crypto/bio/bss_file.c:1.6.2.1.30.1 openssl/crypto/bio/bss_file.c:1.6.4.1 --- openssl/crypto/bio/bss_file.c:1.6.2.1.30.1 Wed Dec 23 17:25:30 2015 +++ openssl/crypto/bio/bss_file.c Wed Dec 23 17:44:14 2015 @@ -167,7 +167,7 @@ if (file == NULL) { SYSerr(SYS_F_FOPEN, get_last_sys_error()); ERR_add_error_data(5, "fopen('", filename, "','", mode, "')"); - if (errno == ENOENT) + if ((errno == ENOENT) || ((*mode == 'r') && (errno == EACCES))) BIOerr(BIO_F_BIO_NEW_FILE, BIO_R_NO_SUCH_FILE); else BIOerr(BIO_F_BIO_NEW_FILE, ERR_R_SYS_LIB); Index: openssl/crypto/engine/Makefile diff -u openssl/crypto/engine/Makefile:1.8.2.1.16.1 openssl/crypto/engine/Makefile:1.8.4.1 --- openssl/crypto/engine/Makefile:1.8.2.1.16.1 Wed Dec 23 17:25:54 2015 +++ openssl/crypto/engine/Makefile Wed Dec 23 17:44:39 2015 @@ -21,12 +21,14 @@ eng_table.c eng_pkey.c eng_fat.c eng_all.c \ tb_rsa.c tb_dsa.c tb_ecdsa.c tb_dh.c tb_ecdh.c tb_rand.c tb_store.c \ tb_cipher.c tb_digest.c tb_pkmeth.c tb_asnmth.c \ - eng_openssl.c eng_cnf.c eng_dyn.c eng_cryptodev.c + eng_openssl.c eng_cnf.c eng_dyn.c eng_cryptodev.c \ + hw_pk11.c hw_pk11_pub.c hw_pk11so.c hw_pk11so_pub.c LIBOBJ= eng_err.o eng_lib.o eng_list.o eng_init.o eng_ctrl.o \ eng_table.o eng_pkey.o eng_fat.o eng_all.o \ tb_rsa.o tb_dsa.o tb_ecdsa.o tb_dh.o tb_ecdh.o tb_rand.o tb_store.o \ tb_cipher.o tb_digest.o tb_pkmeth.o tb_asnmth.o \ - eng_openssl.o eng_cnf.o eng_dyn.o eng_cryptodev.o + eng_openssl.o eng_cnf.o eng_dyn.o eng_cryptodev.o \ + hw_pk11.o hw_pk11_pub.o hw_pk11so.o hw_pk11so_pub.o SRC= $(LIBSRC) @@ -266,6 +268,83 @@ eng_table.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h eng_table.o: ../../include/openssl/x509_vfy.h ../cryptlib.h eng_int.h eng_table.o: eng_table.c +hw_pk11.o: ../../e_os.h ../../include/openssl/aes.h +hw_pk11.o: ../../include/openssl/asn1.h ../../include/openssl/bio.h +hw_pk11.o: ../../include/openssl/bn.h ../../include/openssl/buffer.h +hw_pk11.o: ../../include/openssl/crypto.h ../../include/openssl/dh.h +hw_pk11.o: ../../include/openssl/dsa.h ../../include/openssl/dso.h +hw_pk11.o: ../../include/openssl/e_os2.h ../../include/openssl/ec.h +hw_pk11.o: ../../include/openssl/ecdh.h ../../include/openssl/ecdsa.h +hw_pk11.o: ../../include/openssl/engine.h ../../include/openssl/err.h +hw_pk11.o: ../../include/openssl/evp.h ../../include/openssl/lhash.h +hw_pk11.o: ../../include/openssl/md5.h ../../include/openssl/obj_mac.h +hw_pk11.o: ../../include/openssl/objects.h ../../include/openssl/opensslconf.h +hw_pk11.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h +hw_pk11.o: ../../include/openssl/pem.h ../../include/openssl/pem2.h +hw_pk11.o: ../../include/openssl/pkcs7.h ../../include/openssl/rand.h +hw_pk11.o: ../../include/openssl/rsa.h ../../include/openssl/safestack.h +hw_pk11.o: ../../include/openssl/sha.h ../../include/openssl/stack.h +hw_pk11.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h +hw_pk11.o: ../../include/openssl/x509_vfy.h ../cryptlib.h cryptoki.h hw_pk11.c +hw_pk11.o: hw_pk11_err.c hw_pk11_err.h hw_pk11ca.h pkcs11.h pkcs11f.h pkcs11t.h +hw_pk11_pub.o: ../../e_os.h ../../include/openssl/asn1.h +hw_pk11_pub.o: ../../include/openssl/bio.h ../../include/openssl/bn.h +hw_pk11_pub.o: ../../include/openssl/buffer.h ../../include/openssl/crypto.h +hw_pk11_pub.o: ../../include/openssl/dh.h ../../include/openssl/dsa.h +hw_pk11_pub.o: ../../include/openssl/dso.h ../../include/openssl/e_os2.h +hw_pk11_pub.o: ../../include/openssl/ec.h ../../include/openssl/ecdh.h +hw_pk11_pub.o: ../../include/openssl/ecdsa.h ../../include/openssl/engine.h +hw_pk11_pub.o: ../../include/openssl/err.h ../../include/openssl/evp.h +hw_pk11_pub.o: ../../include/openssl/lhash.h ../../include/openssl/obj_mac.h +hw_pk11_pub.o: ../../include/openssl/objects.h +hw_pk11_pub.o: ../../include/openssl/opensslconf.h +hw_pk11_pub.o: ../../include/openssl/opensslv.h +hw_pk11_pub.o: ../../include/openssl/ossl_typ.h ../../include/openssl/pem.h +hw_pk11_pub.o: ../../include/openssl/pem2.h ../../include/openssl/pkcs7.h +hw_pk11_pub.o: ../../include/openssl/rand.h ../../include/openssl/rsa.h +hw_pk11_pub.o: ../../include/openssl/safestack.h ../../include/openssl/sha.h +hw_pk11_pub.o: ../../include/openssl/stack.h ../../include/openssl/symhacks.h +hw_pk11_pub.o: ../../include/openssl/x509.h ../../include/openssl/x509_vfy.h +hw_pk11_pub.o: ../cryptlib.h cryptoki.h hw_pk11_err.h hw_pk11_pub.c hw_pk11ca.h +hw_pk11_pub.o: pkcs11.h pkcs11f.h pkcs11t.h +hw_pk11so.o: ../../e_os.h ../../include/openssl/asn1.h +hw_pk11so.o: ../../include/openssl/bio.h ../../include/openssl/bn.h +hw_pk11so.o: ../../include/openssl/buffer.h ../../include/openssl/crypto.h +hw_pk11so.o: ../../include/openssl/dso.h ../../include/openssl/e_os2.h +hw_pk11so.o: ../../include/openssl/ec.h ../../include/openssl/ecdh.h +hw_pk11so.o: ../../include/openssl/ecdsa.h ../../include/openssl/engine.h +hw_pk11so.o: ../../include/openssl/err.h ../../include/openssl/evp.h +hw_pk11so.o: ../../include/openssl/lhash.h ../../include/openssl/md5.h +hw_pk11so.o: ../../include/openssl/obj_mac.h ../../include/openssl/objects.h +hw_pk11so.o: ../../include/openssl/opensslconf.h +hw_pk11so.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h +hw_pk11so.o: ../../include/openssl/pem.h ../../include/openssl/pem2.h +hw_pk11so.o: ../../include/openssl/pkcs7.h ../../include/openssl/rand.h +hw_pk11so.o: ../../include/openssl/rsa.h ../../include/openssl/safestack.h +hw_pk11so.o: ../../include/openssl/sha.h ../../include/openssl/stack.h +hw_pk11so.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h +hw_pk11so.o: ../../include/openssl/x509_vfy.h ../cryptlib.h cryptoki.h +hw_pk11so.o: hw_pk11_err.c hw_pk11_err.h hw_pk11so.c hw_pk11so.h pkcs11.h +hw_pk11so.o: pkcs11f.h pkcs11t.h +hw_pk11so_pub.o: ../../e_os.h ../../include/openssl/asn1.h +hw_pk11so_pub.o: ../../include/openssl/bio.h ../../include/openssl/bn.h +hw_pk11so_pub.o: ../../include/openssl/buffer.h ../../include/openssl/crypto.h +hw_pk11so_pub.o: ../../include/openssl/dso.h ../../include/openssl/e_os2.h +hw_pk11so_pub.o: ../../include/openssl/ec.h ../../include/openssl/ecdh.h +hw_pk11so_pub.o: ../../include/openssl/ecdsa.h ../../include/openssl/engine.h +hw_pk11so_pub.o: ../../include/openssl/err.h ../../include/openssl/evp.h +hw_pk11so_pub.o: ../../include/openssl/lhash.h ../../include/openssl/obj_mac.h +hw_pk11so_pub.o: ../../include/openssl/objects.h +hw_pk11so_pub.o: ../../include/openssl/opensslconf.h +hw_pk11so_pub.o: ../../include/openssl/opensslv.h +hw_pk11so_pub.o: ../../include/openssl/ossl_typ.h ../../include/openssl/pem.h +hw_pk11so_pub.o: ../../include/openssl/pem2.h ../../include/openssl/pkcs7.h +hw_pk11so_pub.o: ../../include/openssl/rand.h ../../include/openssl/rsa.h +hw_pk11so_pub.o: ../../include/openssl/safestack.h ../../include/openssl/sha.h +hw_pk11so_pub.o: ../../include/openssl/stack.h ../../include/openssl/symhacks.h +hw_pk11so_pub.o: ../../include/openssl/x509.h ../../include/openssl/x509_vfy.h +hw_pk11so_pub.o: ../cryptlib.h cryptoki.h hw_pk11_err.h hw_pk11so.h +hw_pk11so_pub.o: hw_pk11so_pub.c pkcs11.h pkcs11f.h pkcs11t.h tb_asnmth.o: ../../e_os.h ../../include/openssl/asn1.h tb_asnmth.o: ../../include/openssl/bio.h ../../include/openssl/buffer.h tb_asnmth.o: ../../include/openssl/crypto.h ../../include/openssl/e_os2.h Index: openssl/crypto/engine/cryptoki.h diff -u /dev/null openssl/crypto/engine/cryptoki.h:1.4 --- /dev/null Wed Dec 23 17:47:11 2015 +++ openssl/crypto/engine/cryptoki.h Thu Dec 18 00:14:12 2008 @@ -0,0 +1,103 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _CRYPTOKI_H +#define _CRYPTOKI_H + +/* ident "@(#)cryptoki.h 1.2 05/06/08 SMI" */ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef CK_PTR +#define CK_PTR * +#endif + +#ifndef CK_DEFINE_FUNCTION +#define CK_DEFINE_FUNCTION(returnType, name) returnType name +#endif + +#ifndef CK_DECLARE_FUNCTION +#define CK_DECLARE_FUNCTION(returnType, name) returnType name +#endif + +#ifndef CK_DECLARE_FUNCTION_POINTER +#define CK_DECLARE_FUNCTION_POINTER(returnType, name) returnType (* name) +#endif + +#ifndef CK_CALLBACK_FUNCTION +#define CK_CALLBACK_FUNCTION(returnType, name) returnType (* name) +#endif + +#ifndef NULL_PTR +#include /* For NULL */ +#define NULL_PTR NULL +#endif + +/* + * pkcs11t.h defines TRUE and FALSE in a way that upsets lint + */ +#ifndef CK_DISABLE_TRUE_FALSE +#define CK_DISABLE_TRUE_FALSE +#ifndef TRUE +#define TRUE 1 +#endif /* TRUE */ +#ifndef FALSE +#define FALSE 0 +#endif /* FALSE */ +#endif /* CK_DISABLE_TRUE_FALSE */ + +#undef CK_PKCS11_FUNCTION_INFO + +#include "pkcs11.h" + +/* Solaris specific functions */ + +#include + +/* + * SUNW_C_GetMechSession will initialize the framework and do all + * the necessary PKCS#11 calls to create a session capable of + * providing operations on the requested mechanism + */ +CK_RV SUNW_C_GetMechSession(CK_MECHANISM_TYPE mech, + CK_SESSION_HANDLE_PTR hSession); + +/* + * SUNW_C_KeyToObject will create a secret key object for the given + * mechanism from the rawkey data. + */ +CK_RV SUNW_C_KeyToObject(CK_SESSION_HANDLE hSession, + CK_MECHANISM_TYPE mech, const void *rawkey, size_t rawkey_len, + CK_OBJECT_HANDLE_PTR obj); + + +#ifdef __cplusplus +} +#endif + +#endif /* _CRYPTOKI_H */ Index: openssl/crypto/engine/eng_all.c diff -u openssl/crypto/engine/eng_all.c:1.5.2.1.16.1 openssl/crypto/engine/eng_all.c:1.5.4.1 --- openssl/crypto/engine/eng_all.c:1.5.2.1.16.1 Wed Dec 23 17:25:54 2015 +++ openssl/crypto/engine/eng_all.c Wed Dec 23 17:44:39 2015 @@ -114,6 +114,14 @@ # if defined(OPENSSL_SYS_WIN32) && !defined(OPENSSL_NO_CAPIENG) ENGINE_load_capi(); # endif +# ifndef OPENSSL_NO_HW_PKCS11 +# ifndef OPENSSL_NO_HW_PKCS11CA + ENGINE_load_pk11ca(); +# endif +# ifndef OPENSSL_NO_HW_PKCS11SO + ENGINE_load_pk11so(); +# endif +# endif #endif } Index: openssl/crypto/engine/engine.h diff -u openssl/crypto/engine/engine.h:1.5.2.1.16.1 openssl/crypto/engine/engine.h:1.5.4.1 --- openssl/crypto/engine/engine.h:1.5.2.1.16.1 Wed Dec 23 17:25:55 2015 +++ openssl/crypto/engine/engine.h Wed Dec 23 17:44:40 2015 @@ -406,6 +406,12 @@ # endif void ENGINE_load_cryptodev(void); void ENGINE_load_builtin_engines(void); +# ifndef OPENSSL_NO_HW_PKCS11CA +void ENGINE_load_pk11ca(void); +# endif +# ifndef OPENSSL_NO_HW_PKCS11SO +void ENGINE_load_pk11so(void); +# endif /* * Get and set global flags (ENGINE_TABLE_FLAG_***) for the implementation Index: openssl/crypto/engine/hw_pk11.c diff -u /dev/null openssl/crypto/engine/hw_pk11.c:1.30.4.2 --- /dev/null Wed Dec 23 17:47:11 2015 +++ openssl/crypto/engine/hw_pk11.c Fri Oct 4 14:33:56 2013 @@ -0,0 +1,4116 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* crypto/engine/hw_pk11.c */ +/* + * This product includes software developed by the OpenSSL Project for + * use in the OpenSSL Toolkit (http://www.openssl.org/). + * + * This project also referenced hw_pkcs11-0.9.7b.patch written by + * Afchine Madjlessi. + */ +/* + * ==================================================================== + * Copyright (c) 2000-2001 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifndef OPENSSL_NO_RSA +#include +#endif +#ifndef OPENSSL_NO_DSA +#include +#endif +#ifndef OPENSSL_NO_DH +#include +#endif +#include +#include +#include +#include +#include + +#ifdef OPENSSL_SYS_WIN32 +typedef int pid_t; +#define getpid() GetCurrentProcessId() +#define NOPTHREADS +#ifndef NULL_PTR +#define NULL_PTR NULL +#endif +#define CK_DEFINE_FUNCTION(returnType, name) \ + returnType __declspec(dllexport) name +#define CK_DECLARE_FUNCTION(returnType, name) \ + returnType __declspec(dllimport) name +#define CK_DECLARE_FUNCTION_POINTER(returnType, name) \ + returnType __declspec(dllimport) (* name) +#else +#include +#include +#include +#endif + +/* Debug mutexes */ +/*#undef DEBUG_MUTEX */ +#define DEBUG_MUTEX + +#ifndef NOPTHREADS +/* for pthread error check on Linuxes */ +#ifdef DEBUG_MUTEX +#define __USE_UNIX98 +#endif +#include +#endif + +#ifndef OPENSSL_NO_HW +#ifndef OPENSSL_NO_HW_PK11 +#ifndef OPENSSL_NO_HW_PK11CA + +/* label for debug messages printed on stderr */ +#define PK11_DBG "PKCS#11 ENGINE DEBUG" +/* prints a lot of debug messages on stderr about slot selection process */ +/* #undef DEBUG_SLOT_SELECTION */ +/* + * Solaris specific code. See comment at check_hw_mechanisms() for more + * information. + */ +#if defined(__SVR4) && defined(__sun) +#undef SOLARIS_HW_SLOT_SELECTION +#endif + +/* + * AES counter mode is not supported in the OpenSSL EVP API yet and neither + * there are official OIDs for mechanisms based on this mode. With our changes, + * an application can define its own EVP calls for AES counter mode and then + * it can make use of hardware acceleration through this engine. However, it's + * better if we keep AES CTR support code under ifdef's. + */ +#define SOLARIS_AES_CTR + +#ifdef OPENSSL_SYS_WIN32 +#pragma pack(push, cryptoki, 1) +#include "cryptoki.h" +#include "pkcs11.h" +#pragma pack(pop, cryptoki) +#else +#include "cryptoki.h" +#include "pkcs11.h" +#endif +#include "hw_pk11ca.h" +#include "hw_pk11_err.c" + +#ifdef SOLARIS_AES_CTR +/* + * NIDs for AES counter mode that will be defined during the engine + * initialization. + */ +static int NID_aes_128_ctr = NID_undef; +static int NID_aes_192_ctr = NID_undef; +static int NID_aes_256_ctr = NID_undef; +#endif /* SOLARIS_AES_CTR */ + +/* + * We use this lock to prevent multiple C_Login()s, guard getpassphrase(), + * uri_struct manipulation, and static token info. All of that is used by the + * RSA keys by reference feature. + */ +#ifndef NOPTHREADS +pthread_mutex_t *token_lock; +#endif + +#ifdef SOLARIS_HW_SLOT_SELECTION +/* + * Tables for symmetric ciphers and digest mechs found in the pkcs11_kernel + * library. See comment at check_hw_mechanisms() for more information. + */ +static int *hw_cnids; +static int *hw_dnids; +#endif /* SOLARIS_HW_SLOT_SELECTION */ + +/* PKCS#11 session caches and their locks for all operation types */ +static PK11_CACHE session_cache[OP_MAX]; + +/* + * We cache the flags so that we do not have to run C_GetTokenInfo() again when + * logging into the token. + */ +CK_FLAGS pubkey_token_flags; + +/* + * As stated in v2.20, 11.7 Object Management Function, in section for + * C_FindObjectsInit(), at most one search operation may be active at a given + * time in a given session. Therefore, C_Find{,Init,Final}Objects() should be + * grouped together to form one atomic search operation. This is already + * ensured by the property of unique PKCS#11 session handle used for each + * PK11_SESSION object. + * + * This is however not the biggest concern - maintaining consistency of the + * underlying object store is more important. The same section of the spec also + * says that one thread can be in the middle of a search operation while another + * thread destroys the object matching the search template which would result in + * invalid handle returned from the search operation. + * + * Hence, the following locks are used for both protection of the object stores. + * They are also used for active list protection. + */ +#ifndef NOPTHREADS +pthread_mutex_t *find_lock[OP_MAX] = { NULL }; +#endif + +/* + * lists of asymmetric key handles which are active (referenced by at least one + * PK11_SESSION structure, either held by a thread or present in free_session + * list) for given algorithm type + */ +PK11_active *active_list[OP_MAX] = { NULL }; + +/* + * Create all secret key objects in a global session so that they are available + * to use for other sessions. These other sessions may be opened or closed + * without losing the secret key objects. + */ +static CK_SESSION_HANDLE global_session = CK_INVALID_HANDLE; + +/* ENGINE level stuff */ +static int pk11_init(ENGINE *e); +static int pk11_library_init(ENGINE *e); +static int pk11_finish(ENGINE *e); +static int pk11_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void)); +static int pk11_destroy(ENGINE *e); + +/* RAND stuff */ +static void pk11_rand_seed(const void *buf, int num); +static void pk11_rand_add(const void *buf, int num, double add_entropy); +static void pk11_rand_cleanup(void); +static int pk11_rand_bytes(unsigned char *buf, int num); +static int pk11_rand_status(void); + +/* These functions are also used in other files */ +PK11_SESSION *pk11_get_session(PK11_OPTYPE optype); +void pk11_return_session(PK11_SESSION *sp, PK11_OPTYPE optype); + +/* active list manipulation functions used in this file */ +extern int pk11_active_delete(CK_OBJECT_HANDLE h, PK11_OPTYPE type); +extern void pk11_free_active_list(PK11_OPTYPE type); + +#ifndef OPENSSL_NO_RSA +int pk11_destroy_rsa_key_objects(PK11_SESSION *session); +int pk11_destroy_rsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock); +int pk11_destroy_rsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock); +#endif +#ifndef OPENSSL_NO_DSA +int pk11_destroy_dsa_key_objects(PK11_SESSION *session); +int pk11_destroy_dsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock); +int pk11_destroy_dsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock); +#endif +#ifndef OPENSSL_NO_DH +int pk11_destroy_dh_key_objects(PK11_SESSION *session); +int pk11_destroy_dh_object(PK11_SESSION *session, CK_BBOOL uselock); +#endif + +/* Local helper functions */ +static int pk11_free_all_sessions(void); +static int pk11_free_session_list(PK11_OPTYPE optype); +static int pk11_setup_session(PK11_SESSION *sp, PK11_OPTYPE optype); +static int pk11_destroy_cipher_key_objects(PK11_SESSION *session); +static int pk11_destroy_object(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE oh, + CK_BBOOL persistent); +static const char *get_PK11_LIBNAME(void); +static void free_PK11_LIBNAME(void); +static long set_PK11_LIBNAME(const char *name); + +/* Symmetric cipher and digest support functions */ +static int cipher_nid_to_pk11(int nid); +#ifdef SOLARIS_AES_CTR +static int pk11_add_NID(char *sn, char *ln); +static int pk11_add_aes_ctr_NIDs(void); +#endif /* SOLARIS_AES_CTR */ +static int pk11_usable_ciphers(const int **nids); +static int pk11_usable_digests(const int **nids); +static int pk11_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc); +static int pk11_cipher_final(PK11_SESSION *sp); +#if OPENSSL_VERSION_NUMBER < 0x10000000L +static int pk11_cipher_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, unsigned int inl); +#else +static int pk11_cipher_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t inl); +#endif +static int pk11_cipher_cleanup(EVP_CIPHER_CTX *ctx); +static int pk11_engine_ciphers(ENGINE *e, const EVP_CIPHER **cipher, + const int **nids, int nid); +static int pk11_engine_digests(ENGINE *e, const EVP_MD **digest, + const int **nids, int nid); +static CK_OBJECT_HANDLE pk11_get_cipher_key(EVP_CIPHER_CTX *ctx, + const unsigned char *key, CK_KEY_TYPE key_type, PK11_SESSION *sp); +static int check_new_cipher_key(PK11_SESSION *sp, const unsigned char *key, + int key_len); +static int md_nid_to_pk11(int nid); +static int pk11_digest_init(EVP_MD_CTX *ctx); +static int pk11_digest_update(EVP_MD_CTX *ctx, const void *data, + size_t count); +static int pk11_digest_final(EVP_MD_CTX *ctx, unsigned char *md); +static int pk11_digest_copy(EVP_MD_CTX *to, const EVP_MD_CTX *from); +static int pk11_digest_cleanup(EVP_MD_CTX *ctx); + +static int pk11_choose_slots(int *any_slot_found); +static void pk11_find_symmetric_ciphers(CK_FUNCTION_LIST_PTR pflist, + CK_SLOT_ID current_slot, int *current_slot_n_cipher, + int *local_cipher_nids); +static void pk11_find_digests(CK_FUNCTION_LIST_PTR pflist, + CK_SLOT_ID current_slot, int *current_slot_n_digest, + int *local_digest_nids); +static void pk11_get_symmetric_cipher(CK_FUNCTION_LIST_PTR, int slot_id, + CK_MECHANISM_TYPE mech, int *current_slot_n_cipher, int *local_cipher_nids, + int id); +static void pk11_get_digest(CK_FUNCTION_LIST_PTR pflist, int slot_id, + CK_MECHANISM_TYPE mech, int *current_slot_n_digest, int *local_digest_nids, + int id); + +static int pk11_init_all_locks(void); +static void pk11_free_all_locks(void); + +#ifdef SOLARIS_HW_SLOT_SELECTION +static int check_hw_mechanisms(void); +static int nid_in_table(int nid, int *nid_table); +#endif /* SOLARIS_HW_SLOT_SELECTION */ + +/* Index for the supported ciphers */ +enum pk11_cipher_id { + PK11_DES_CBC, + PK11_DES3_CBC, + PK11_DES_ECB, + PK11_DES3_ECB, + PK11_RC4, + PK11_AES_128_CBC, + PK11_AES_192_CBC, + PK11_AES_256_CBC, + PK11_AES_128_ECB, + PK11_AES_192_ECB, + PK11_AES_256_ECB, + PK11_BLOWFISH_CBC, +#ifdef SOLARIS_AES_CTR + PK11_AES_128_CTR, + PK11_AES_192_CTR, + PK11_AES_256_CTR, +#endif /* SOLARIS_AES_CTR */ + PK11_CIPHER_MAX +}; + +/* Index for the supported digests */ +enum pk11_digest_id { + PK11_MD5, + PK11_SHA1, + PK11_SHA224, + PK11_SHA256, + PK11_SHA384, + PK11_SHA512, + PK11_DIGEST_MAX +}; + +#define TRY_OBJ_DESTROY(sp, obj_hdl, retval, uselock, alg_type, priv) \ + { \ + if (uselock) \ + LOCK_OBJSTORE(alg_type); \ + if (pk11_active_delete(obj_hdl, alg_type) == 1) \ + { \ + retval = pk11_destroy_object(sp->session, obj_hdl, \ + priv ? sp->priv_persistent : sp->pub_persistent); \ + } \ + if (uselock) \ + UNLOCK_OBJSTORE(alg_type); \ + } + +static int cipher_nids[PK11_CIPHER_MAX]; +static int digest_nids[PK11_DIGEST_MAX]; +static int cipher_count = 0; +static int digest_count = 0; +static CK_BBOOL pk11_have_rsa = CK_FALSE; +static CK_BBOOL pk11_have_recover = CK_FALSE; +static CK_BBOOL pk11_have_dsa = CK_FALSE; +static CK_BBOOL pk11_have_dh = CK_FALSE; +static CK_BBOOL pk11_have_random = CK_FALSE; + +typedef struct PK11_CIPHER_st + { + enum pk11_cipher_id id; + int nid; + int iv_len; + int min_key_len; + int max_key_len; + CK_KEY_TYPE key_type; + CK_MECHANISM_TYPE mech_type; + } PK11_CIPHER; + +static PK11_CIPHER ciphers[] = + { + { PK11_DES_CBC, NID_des_cbc, 8, 8, 8, + CKK_DES, CKM_DES_CBC, }, + { PK11_DES3_CBC, NID_des_ede3_cbc, 8, 24, 24, + CKK_DES3, CKM_DES3_CBC, }, + { PK11_DES_ECB, NID_des_ecb, 0, 8, 8, + CKK_DES, CKM_DES_ECB, }, + { PK11_DES3_ECB, NID_des_ede3_ecb, 0, 24, 24, + CKK_DES3, CKM_DES3_ECB, }, + { PK11_RC4, NID_rc4, 0, 16, 256, + CKK_RC4, CKM_RC4, }, + { PK11_AES_128_CBC, NID_aes_128_cbc, 16, 16, 16, + CKK_AES, CKM_AES_CBC, }, + { PK11_AES_192_CBC, NID_aes_192_cbc, 16, 24, 24, + CKK_AES, CKM_AES_CBC, }, + { PK11_AES_256_CBC, NID_aes_256_cbc, 16, 32, 32, + CKK_AES, CKM_AES_CBC, }, + { PK11_AES_128_ECB, NID_aes_128_ecb, 0, 16, 16, + CKK_AES, CKM_AES_ECB, }, + { PK11_AES_192_ECB, NID_aes_192_ecb, 0, 24, 24, + CKK_AES, CKM_AES_ECB, }, + { PK11_AES_256_ECB, NID_aes_256_ecb, 0, 32, 32, + CKK_AES, CKM_AES_ECB, }, + { PK11_BLOWFISH_CBC, NID_bf_cbc, 8, 16, 16, + CKK_BLOWFISH, CKM_BLOWFISH_CBC, }, +#ifdef SOLARIS_AES_CTR + /* we don't know the correct NIDs until the engine is initialized */ + { PK11_AES_128_CTR, NID_undef, 16, 16, 16, + CKK_AES, CKM_AES_CTR, }, + { PK11_AES_192_CTR, NID_undef, 16, 24, 24, + CKK_AES, CKM_AES_CTR, }, + { PK11_AES_256_CTR, NID_undef, 16, 32, 32, + CKK_AES, CKM_AES_CTR, }, +#endif /* SOLARIS_AES_CTR */ + }; + +typedef struct PK11_DIGEST_st + { + enum pk11_digest_id id; + int nid; + CK_MECHANISM_TYPE mech_type; + } PK11_DIGEST; + +static PK11_DIGEST digests[] = + { + {PK11_MD5, NID_md5, CKM_MD5, }, + {PK11_SHA1, NID_sha1, CKM_SHA_1, }, + {PK11_SHA224, NID_sha224, CKM_SHA224, }, + {PK11_SHA256, NID_sha256, CKM_SHA256, }, + {PK11_SHA384, NID_sha384, CKM_SHA384, }, + {PK11_SHA512, NID_sha512, CKM_SHA512, }, + {0, NID_undef, 0xFFFF, }, + }; + +/* + * Structure to be used for the cipher_data/md_data in + * EVP_CIPHER_CTX/EVP_MD_CTX structures in order to use the same pk11 + * session in multiple cipher_update calls + */ +typedef struct PK11_CIPHER_STATE_st + { + PK11_SESSION *sp; + } PK11_CIPHER_STATE; + + +/* + * libcrypto EVP stuff - this is how we get wired to EVP so the engine gets + * called when libcrypto requests a cipher NID. + * + * Note how the PK11_CIPHER_STATE is used here. + */ + +/* DES CBC EVP */ +static const EVP_CIPHER pk11_des_cbc = + { + NID_des_cbc, + 8, 8, 8, + EVP_CIPH_CBC_MODE, + pk11_cipher_init, + pk11_cipher_do_cipher, + pk11_cipher_cleanup, + sizeof (PK11_CIPHER_STATE), + EVP_CIPHER_set_asn1_iv, + EVP_CIPHER_get_asn1_iv, + NULL + }; + +/* 3DES CBC EVP */ +static const EVP_CIPHER pk11_3des_cbc = + { + NID_des_ede3_cbc, + 8, 24, 8, + EVP_CIPH_CBC_MODE, + pk11_cipher_init, + pk11_cipher_do_cipher, + pk11_cipher_cleanup, + sizeof (PK11_CIPHER_STATE), + EVP_CIPHER_set_asn1_iv, + EVP_CIPHER_get_asn1_iv, + NULL + }; + +/* + * ECB modes don't use an Initial Vector so that's why set_asn1_parameters and + * get_asn1_parameters fields are set to NULL. + */ +static const EVP_CIPHER pk11_des_ecb = + { + NID_des_ecb, + 8, 8, 8, + EVP_CIPH_ECB_MODE, + pk11_cipher_init, + pk11_cipher_do_cipher, + pk11_cipher_cleanup, + sizeof (PK11_CIPHER_STATE), + NULL, + NULL, + NULL + }; + +static const EVP_CIPHER pk11_3des_ecb = + { + NID_des_ede3_ecb, + 8, 24, 8, + EVP_CIPH_ECB_MODE, + pk11_cipher_init, + pk11_cipher_do_cipher, + pk11_cipher_cleanup, + sizeof (PK11_CIPHER_STATE), + NULL, + NULL, + NULL + }; + + +static const EVP_CIPHER pk11_aes_128_cbc = + { + NID_aes_128_cbc, + 16, 16, 16, + EVP_CIPH_CBC_MODE, + pk11_cipher_init, + pk11_cipher_do_cipher, + pk11_cipher_cleanup, + sizeof (PK11_CIPHER_STATE), + EVP_CIPHER_set_asn1_iv, + EVP_CIPHER_get_asn1_iv, + NULL + }; + +static const EVP_CIPHER pk11_aes_192_cbc = + { + NID_aes_192_cbc, + 16, 24, 16, + EVP_CIPH_CBC_MODE, + pk11_cipher_init, + pk11_cipher_do_cipher, + pk11_cipher_cleanup, + sizeof (PK11_CIPHER_STATE), + EVP_CIPHER_set_asn1_iv, + EVP_CIPHER_get_asn1_iv, + NULL + }; + +static const EVP_CIPHER pk11_aes_256_cbc = + { + NID_aes_256_cbc, + 16, 32, 16, + EVP_CIPH_CBC_MODE, + pk11_cipher_init, + pk11_cipher_do_cipher, + pk11_cipher_cleanup, + sizeof (PK11_CIPHER_STATE), + EVP_CIPHER_set_asn1_iv, + EVP_CIPHER_get_asn1_iv, + NULL + }; + +/* + * ECB modes don't use IV so that's why set_asn1_parameters and + * get_asn1_parameters are set to NULL. + */ +static const EVP_CIPHER pk11_aes_128_ecb = + { + NID_aes_128_ecb, + 16, 16, 0, + EVP_CIPH_ECB_MODE, + pk11_cipher_init, + pk11_cipher_do_cipher, + pk11_cipher_cleanup, + sizeof (PK11_CIPHER_STATE), + NULL, + NULL, + NULL + }; + +static const EVP_CIPHER pk11_aes_192_ecb = + { + NID_aes_192_ecb, + 16, 24, 0, + EVP_CIPH_ECB_MODE, + pk11_cipher_init, + pk11_cipher_do_cipher, + pk11_cipher_cleanup, + sizeof (PK11_CIPHER_STATE), + NULL, + NULL, + NULL + }; + +static const EVP_CIPHER pk11_aes_256_ecb = + { + NID_aes_256_ecb, + 16, 32, 0, + EVP_CIPH_ECB_MODE, + pk11_cipher_init, + pk11_cipher_do_cipher, + pk11_cipher_cleanup, + sizeof (PK11_CIPHER_STATE), + NULL, + NULL, + NULL + }; + +#ifdef SOLARIS_AES_CTR +/* + * NID_undef's will be changed to the AES counter mode NIDs as soon they are + * created in pk11_library_init(). Note that the need to change these structures + * is the reason why we don't define them with the const keyword. + */ +static EVP_CIPHER pk11_aes_128_ctr = + { + NID_undef, + 16, 16, 16, + EVP_CIPH_CBC_MODE, + pk11_cipher_init, + pk11_cipher_do_cipher, + pk11_cipher_cleanup, + sizeof (PK11_CIPHER_STATE), + EVP_CIPHER_set_asn1_iv, + EVP_CIPHER_get_asn1_iv, + NULL + }; + +static EVP_CIPHER pk11_aes_192_ctr = + { + NID_undef, + 16, 24, 16, + EVP_CIPH_CBC_MODE, + pk11_cipher_init, + pk11_cipher_do_cipher, + pk11_cipher_cleanup, + sizeof (PK11_CIPHER_STATE), + EVP_CIPHER_set_asn1_iv, + EVP_CIPHER_get_asn1_iv, + NULL + }; + +static EVP_CIPHER pk11_aes_256_ctr = + { + NID_undef, + 16, 32, 16, + EVP_CIPH_CBC_MODE, + pk11_cipher_init, + pk11_cipher_do_cipher, + pk11_cipher_cleanup, + sizeof (PK11_CIPHER_STATE), + EVP_CIPHER_set_asn1_iv, + EVP_CIPHER_get_asn1_iv, + NULL + }; +#endif /* SOLARIS_AES_CTR */ + +static const EVP_CIPHER pk11_bf_cbc = + { + NID_bf_cbc, + 8, 16, 8, + EVP_CIPH_VARIABLE_LENGTH, + pk11_cipher_init, + pk11_cipher_do_cipher, + pk11_cipher_cleanup, + sizeof (PK11_CIPHER_STATE), + EVP_CIPHER_set_asn1_iv, + EVP_CIPHER_get_asn1_iv, + NULL + }; + +static const EVP_CIPHER pk11_rc4 = + { + NID_rc4, + 1, 16, 0, + EVP_CIPH_VARIABLE_LENGTH, + pk11_cipher_init, + pk11_cipher_do_cipher, + pk11_cipher_cleanup, + sizeof (PK11_CIPHER_STATE), + NULL, + NULL, + NULL + }; + +static const EVP_MD pk11_md5 = + { + NID_md5, + NID_md5WithRSAEncryption, + MD5_DIGEST_LENGTH, + 0, + pk11_digest_init, + pk11_digest_update, + pk11_digest_final, + pk11_digest_copy, + pk11_digest_cleanup, + EVP_PKEY_RSA_method, + MD5_CBLOCK, + sizeof (PK11_CIPHER_STATE), + }; + +static const EVP_MD pk11_sha1 = + { + NID_sha1, + NID_sha1WithRSAEncryption, + SHA_DIGEST_LENGTH, + EVP_MD_FLAG_PKEY_METHOD_SIGNATURE|EVP_MD_FLAG_DIGALGID_ABSENT, + pk11_digest_init, + pk11_digest_update, + pk11_digest_final, + pk11_digest_copy, + pk11_digest_cleanup, + EVP_PKEY_RSA_method, + SHA_CBLOCK, + sizeof (PK11_CIPHER_STATE), + }; + +static const EVP_MD pk11_sha224 = + { + NID_sha224, + NID_sha224WithRSAEncryption, + SHA224_DIGEST_LENGTH, + EVP_MD_FLAG_PKEY_METHOD_SIGNATURE|EVP_MD_FLAG_DIGALGID_ABSENT, + pk11_digest_init, + pk11_digest_update, + pk11_digest_final, + pk11_digest_copy, + pk11_digest_cleanup, + EVP_PKEY_RSA_method, + /* SHA-224 uses the same cblock size as SHA-256 */ + SHA256_CBLOCK, + sizeof (PK11_CIPHER_STATE), + }; + +static const EVP_MD pk11_sha256 = + { + NID_sha256, + NID_sha256WithRSAEncryption, + SHA256_DIGEST_LENGTH, + EVP_MD_FLAG_PKEY_METHOD_SIGNATURE|EVP_MD_FLAG_DIGALGID_ABSENT, + pk11_digest_init, + pk11_digest_update, + pk11_digest_final, + pk11_digest_copy, + pk11_digest_cleanup, + EVP_PKEY_RSA_method, + SHA256_CBLOCK, + sizeof (PK11_CIPHER_STATE), + }; + +static const EVP_MD pk11_sha384 = + { + NID_sha384, + NID_sha384WithRSAEncryption, + SHA384_DIGEST_LENGTH, + EVP_MD_FLAG_PKEY_METHOD_SIGNATURE|EVP_MD_FLAG_DIGALGID_ABSENT, + pk11_digest_init, + pk11_digest_update, + pk11_digest_final, + pk11_digest_copy, + pk11_digest_cleanup, + EVP_PKEY_RSA_method, + /* SHA-384 uses the same cblock size as SHA-512 */ + SHA512_CBLOCK, + sizeof (PK11_CIPHER_STATE), + }; + +static const EVP_MD pk11_sha512 = + { + NID_sha512, + NID_sha512WithRSAEncryption, + SHA512_DIGEST_LENGTH, + EVP_MD_FLAG_PKEY_METHOD_SIGNATURE|EVP_MD_FLAG_DIGALGID_ABSENT, + pk11_digest_init, + pk11_digest_update, + pk11_digest_final, + pk11_digest_copy, + pk11_digest_cleanup, + EVP_PKEY_RSA_method, + SHA512_CBLOCK, + sizeof (PK11_CIPHER_STATE), + }; + +/* + * Initialization function. Sets up various PKCS#11 library components. + * The definitions for control commands specific to this engine + */ +#define PK11_CMD_SO_PATH ENGINE_CMD_BASE +#define PK11_CMD_PIN (ENGINE_CMD_BASE+1) +#define PK11_CMD_SLOT (ENGINE_CMD_BASE+2) +static const ENGINE_CMD_DEFN pk11_cmd_defns[] = + { + { + PK11_CMD_SO_PATH, + "SO_PATH", + "Specifies the path to the 'pkcs#11' shared library", + ENGINE_CMD_FLAG_STRING + }, + { + PK11_CMD_PIN, + "PIN", + "Specifies the pin code", + ENGINE_CMD_FLAG_STRING + }, + { + PK11_CMD_SLOT, + "SLOT", + "Specifies the slot (default is auto select)", + ENGINE_CMD_FLAG_NUMERIC, + }, + {0, NULL, NULL, 0} + }; + + +static RAND_METHOD pk11_random = + { + pk11_rand_seed, + pk11_rand_bytes, + pk11_rand_cleanup, + pk11_rand_add, + pk11_rand_bytes, + pk11_rand_status + }; + + +/* Constants used when creating the ENGINE */ +#ifdef OPENSSL_NO_HW_PK11SO +#error "can't load both crypto-accelerator and sign-only PKCS#11 engines" +#endif +static const char *engine_pk11_id = "pkcs11"; +static const char *engine_pk11_name = + "PKCS #11 engine support (crypto accelerator)"; + +CK_FUNCTION_LIST_PTR pFuncList = NULL; +static const char PK11_GET_FUNCTION_LIST[] = "C_GetFunctionList"; + +/* + * This is a static string constant for the DSO file name and the function + * symbol names to bind to. We set it in the Configure script based on whether + * this is 32 or 64 bit build. + */ +static const char def_PK11_LIBNAME[] = PK11_LIB_LOCATION; + +static CK_BBOOL mytrue = TRUE; +static CK_BBOOL myfalse = FALSE; +/* Needed in hw_pk11_pub.c as well so that's why it is not static. */ +CK_SLOT_ID pubkey_SLOTID = 0; +static CK_SLOT_ID rand_SLOTID = 0; +static CK_SLOT_ID SLOTID = 0; +char *pk11_pin = NULL; +static CK_BBOOL pk11_library_initialized = FALSE; +static CK_BBOOL pk11_atfork_initialized = FALSE; +static int pk11_pid = 0; + +static DSO *pk11_dso = NULL; + +/* allocate and initialize all locks used by the engine itself */ +static int pk11_init_all_locks(void) + { +#ifndef NOPTHREADS + int type; + pthread_mutexattr_t attr; + + if (pthread_mutexattr_init(&attr) != 0) + { + PK11err(PK11_F_INIT_ALL_LOCKS, 100); + return (0); + } + +#ifdef DEBUG_MUTEX + if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK) != 0) + { + PK11err(PK11_F_INIT_ALL_LOCKS, 101); + return (0); + } +#endif + + if ((token_lock = OPENSSL_malloc(sizeof (pthread_mutex_t))) == NULL) + goto malloc_err; + (void) pthread_mutex_init(token_lock, &attr); + +#ifndef OPENSSL_NO_RSA + find_lock[OP_RSA] = OPENSSL_malloc(sizeof (pthread_mutex_t)); + if (find_lock[OP_RSA] == NULL) + goto malloc_err; + (void) pthread_mutex_init(find_lock[OP_RSA], &attr); +#endif /* OPENSSL_NO_RSA */ + +#ifndef OPENSSL_NO_DSA + find_lock[OP_DSA] = OPENSSL_malloc(sizeof (pthread_mutex_t)); + if (find_lock[OP_DSA] == NULL) + goto malloc_err; + (void) pthread_mutex_init(find_lock[OP_DSA], &attr); +#endif /* OPENSSL_NO_DSA */ + +#ifndef OPENSSL_NO_DH + find_lock[OP_DH] = OPENSSL_malloc(sizeof (pthread_mutex_t)); + if (find_lock[OP_DH] == NULL) + goto malloc_err; + (void) pthread_mutex_init(find_lock[OP_DH], &attr); +#endif /* OPENSSL_NO_DH */ + + for (type = 0; type < OP_MAX; type++) + { + session_cache[type].lock = + OPENSSL_malloc(sizeof (pthread_mutex_t)); + if (session_cache[type].lock == NULL) + goto malloc_err; + (void) pthread_mutex_init(session_cache[type].lock, &attr); + } + + return (1); + +malloc_err: + pk11_free_all_locks(); + PK11err(PK11_F_INIT_ALL_LOCKS, PK11_R_MALLOC_FAILURE); + return (0); +#else + return (1); +#endif + } + +static void pk11_free_all_locks(void) + { +#ifndef NOPTHREADS + int type; + + if (token_lock != NULL) + { + (void) pthread_mutex_destroy(token_lock); + OPENSSL_free(token_lock); + token_lock = NULL; + } + +#ifndef OPENSSL_NO_RSA + if (find_lock[OP_RSA] != NULL) + { + (void) pthread_mutex_destroy(find_lock[OP_RSA]); + OPENSSL_free(find_lock[OP_RSA]); + find_lock[OP_RSA] = NULL; + } +#endif /* OPENSSL_NO_RSA */ +#ifndef OPENSSL_NO_DSA + if (find_lock[OP_DSA] != NULL) + { + (void) pthread_mutex_destroy(find_lock[OP_DSA]); + OPENSSL_free(find_lock[OP_DSA]); + find_lock[OP_DSA] = NULL; + } +#endif /* OPENSSL_NO_DSA */ +#ifndef OPENSSL_NO_DH + if (find_lock[OP_DH] != NULL) + { + (void) pthread_mutex_destroy(find_lock[OP_DH]); + OPENSSL_free(find_lock[OP_DH]); + find_lock[OP_DH] = NULL; + } +#endif /* OPENSSL_NO_DH */ + + for (type = 0; type < OP_MAX; type++) + { + if (session_cache[type].lock != NULL) + { + (void) pthread_mutex_destroy(session_cache[type].lock); + OPENSSL_free(session_cache[type].lock); + session_cache[type].lock = NULL; + } + } +#endif + } + +/* + * This internal function is used by ENGINE_pk11() and "dynamic" ENGINE support. + */ +static int bind_pk11(ENGINE *e) + { +#ifndef OPENSSL_NO_RSA + const RSA_METHOD *rsa = NULL; + RSA_METHOD *pk11_rsa = PK11_RSA(); +#endif /* OPENSSL_NO_RSA */ + if (!pk11_library_initialized) + if (!pk11_library_init(e)) + return (0); + + if (!ENGINE_set_id(e, engine_pk11_id) || + !ENGINE_set_name(e, engine_pk11_name) || + !ENGINE_set_ciphers(e, pk11_engine_ciphers) || + !ENGINE_set_digests(e, pk11_engine_digests)) + return (0); +#ifndef OPENSSL_NO_RSA + if (pk11_have_rsa == CK_TRUE) + { + if (!ENGINE_set_RSA(e, PK11_RSA()) || + !ENGINE_set_load_privkey_function(e, pk11_load_privkey) || + !ENGINE_set_load_pubkey_function(e, pk11_load_pubkey)) + return (0); +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: registered RSA\n", PK11_DBG); +#endif /* DEBUG_SLOT_SELECTION */ + } +#endif /* OPENSSL_NO_RSA */ +#ifndef OPENSSL_NO_DSA + if (pk11_have_dsa == CK_TRUE) + { + if (!ENGINE_set_DSA(e, PK11_DSA())) + return (0); +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: registered DSA\n", PK11_DBG); +#endif /* DEBUG_SLOT_SELECTION */ + } +#endif /* OPENSSL_NO_DSA */ +#ifndef OPENSSL_NO_DH + if (pk11_have_dh == CK_TRUE) + { + if (!ENGINE_set_DH(e, PK11_DH())) + return (0); +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: registered DH\n", PK11_DBG); +#endif /* DEBUG_SLOT_SELECTION */ + } +#endif /* OPENSSL_NO_DH */ + if (pk11_have_random) + { + if (!ENGINE_set_RAND(e, &pk11_random)) + return (0); +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: registered random\n", PK11_DBG); +#endif /* DEBUG_SLOT_SELECTION */ + } + if (!ENGINE_set_init_function(e, pk11_init) || + !ENGINE_set_destroy_function(e, pk11_destroy) || + !ENGINE_set_finish_function(e, pk11_finish) || + !ENGINE_set_ctrl_function(e, pk11_ctrl) || + !ENGINE_set_cmd_defns(e, pk11_cmd_defns)) + return (0); + +/* + * Apache calls OpenSSL function RSA_blinding_on() once during startup + * which in turn calls bn_mod_exp. Since we do not implement bn_mod_exp + * here, we wire it back to the OpenSSL software implementation. + * Since it is used only once, performance is not a concern. + */ +#ifndef OPENSSL_NO_RSA + rsa = RSA_PKCS1_SSLeay(); + pk11_rsa->rsa_mod_exp = rsa->rsa_mod_exp; + pk11_rsa->bn_mod_exp = rsa->bn_mod_exp; + if (pk11_have_recover != CK_TRUE) + pk11_rsa->rsa_pub_dec = rsa->rsa_pub_dec; +#endif /* OPENSSL_NO_RSA */ + + /* Ensure the pk11 error handling is set up */ + ERR_load_pk11_strings(); + + return (1); + } + +/* Dynamic engine support is disabled at a higher level for Solaris */ +#ifdef ENGINE_DYNAMIC_SUPPORT +#error "dynamic engine not supported" +static int bind_helper(ENGINE *e, const char *id) + { + if (id && (strcmp(id, engine_pk11_id) != 0)) + return (0); + + if (!bind_pk11(e)) + return (0); + + return (1); + } + +IMPLEMENT_DYNAMIC_CHECK_FN() +IMPLEMENT_DYNAMIC_BIND_FN(bind_helper) + +#else +static ENGINE *engine_pk11(void) + { + ENGINE *ret = ENGINE_new(); + + if (!ret) + return (NULL); + + if (!bind_pk11(ret)) + { + ENGINE_free(ret); + return (NULL); + } + + return (ret); + } + +void +ENGINE_load_pk11(void) + { + ENGINE *e_pk11 = NULL; + + /* + * Do not use dynamic PKCS#11 library on Solaris due to + * security reasons. We will link it in statically. + */ + /* Attempt to load PKCS#11 library */ + if (!pk11_dso) + pk11_dso = DSO_load(NULL, get_PK11_LIBNAME(), NULL, 0); + + if (pk11_dso == NULL) + { + PK11err(PK11_F_LOAD, PK11_R_DSO_FAILURE); + return; + } + + e_pk11 = engine_pk11(); + if (!e_pk11) + { + DSO_free(pk11_dso); + pk11_dso = NULL; + return; + } + + /* + * At this point, the pk11 shared library is either dynamically + * loaded or statically linked in. So, initialize the pk11 + * library before calling ENGINE_set_default since the latter + * needs cipher and digest algorithm information + */ + if (!pk11_library_init(e_pk11)) + { + DSO_free(pk11_dso); + pk11_dso = NULL; + ENGINE_free(e_pk11); + return; + } + + ENGINE_add(e_pk11); + + ENGINE_free(e_pk11); + ERR_clear_error(); + } +#endif /* ENGINE_DYNAMIC_SUPPORT */ + +/* + * These are the static string constants for the DSO file name and + * the function symbol names to bind to. + */ +static const char *PK11_LIBNAME = NULL; + +static const char *get_PK11_LIBNAME(void) + { + if (PK11_LIBNAME) + return (PK11_LIBNAME); + + return (def_PK11_LIBNAME); + } + +static void free_PK11_LIBNAME(void) + { + if (PK11_LIBNAME) + OPENSSL_free((void*)PK11_LIBNAME); + + PK11_LIBNAME = NULL; + } + +static long set_PK11_LIBNAME(const char *name) + { + free_PK11_LIBNAME(); + + return ((PK11_LIBNAME = BUF_strdup(name)) != NULL ? 1 : 0); + } + +/* acquire all engine specific mutexes before fork */ +static void pk11_fork_prepare(void) + { +#ifndef NOPTHREADS + int i; + + if (!pk11_library_initialized) + return; + + LOCK_OBJSTORE(OP_RSA); + LOCK_OBJSTORE(OP_DSA); + LOCK_OBJSTORE(OP_DH); + OPENSSL_assert(pthread_mutex_lock(token_lock) == 0); + for (i = 0; i < OP_MAX; i++) + { + OPENSSL_assert(pthread_mutex_lock(session_cache[i].lock) == 0); + } +#endif + } + +/* release all engine specific mutexes */ +static void pk11_fork_parent(void) + { +#ifndef NOPTHREADS + int i; + + if (!pk11_library_initialized) + return; + + for (i = OP_MAX - 1; i >= 0; i--) + { + OPENSSL_assert(pthread_mutex_unlock(session_cache[i].lock) == 0); + } + UNLOCK_OBJSTORE(OP_DH); + UNLOCK_OBJSTORE(OP_DSA); + UNLOCK_OBJSTORE(OP_RSA); + OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0); +#endif + } + +/* + * same situation as in parent - we need to unlock all locks to make them + * accessible to all threads. + */ +static void pk11_fork_child(void) + { +#ifndef NOPTHREADS + int i; + + if (!pk11_library_initialized) + return; + + for (i = OP_MAX - 1; i >= 0; i--) + { + OPENSSL_assert(pthread_mutex_unlock(session_cache[i].lock) == 0); + } + UNLOCK_OBJSTORE(OP_DH); + UNLOCK_OBJSTORE(OP_DSA); + UNLOCK_OBJSTORE(OP_RSA); + OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0); +#endif + } + +/* Initialization function for the pk11 engine */ +static int pk11_init(ENGINE *e) +{ + return (pk11_library_init(e)); +} + +static CK_C_INITIALIZE_ARGS pk11_init_args = + { + NULL_PTR, /* CreateMutex */ + NULL_PTR, /* DestroyMutex */ + NULL_PTR, /* LockMutex */ + NULL_PTR, /* UnlockMutex */ + CKF_OS_LOCKING_OK, /* flags */ + NULL_PTR, /* pReserved */ + }; + +/* + * Initialization function. Sets up various PKCS#11 library components. + * It selects a slot based on predefined critiera. In the process, it also + * count how many ciphers and digests to support. Since the cipher and + * digest information is needed when setting default engine, this function + * needs to be called before calling ENGINE_set_default. + */ +/* ARGSUSED */ +static int pk11_library_init(ENGINE *e) + { + CK_C_GetFunctionList p; + CK_RV rv = CKR_OK; + CK_INFO info; + CK_ULONG ul_state_len; + int any_slot_found; + int i; +#ifndef OPENSSL_SYS_WIN32 + struct sigaction sigint_act, sigterm_act, sighup_act; +#endif + + /* + * pk11_library_initialized is set to 0 in pk11_finish() which + * is called from ENGINE_finish(). However, if there is still + * at least one existing functional reference to the engine + * (see engine(3) for more information), pk11_finish() is + * skipped. For example, this can happen if an application + * forgets to clear one cipher context. In case of a fork() + * when the application is finishing the engine so that it can + * be reinitialized in the child, forgotten functional + * reference causes pk11_library_initialized to stay 1. In + * that case we need the PID check so that we properly + * initialize the engine again. + */ + if (pk11_library_initialized) + { + if (pk11_pid == getpid()) + { + return (1); + } + else + { + global_session = CK_INVALID_HANDLE; + /* + * free the locks first to prevent memory leak in case + * the application calls fork() without finishing the + * engine first. + */ + pk11_free_all_locks(); + } + } + + if (pk11_dso == NULL) + { + PK11err(PK11_F_LIBRARY_INIT, PK11_R_DSO_FAILURE); + goto err; + } + +#ifdef SOLARIS_AES_CTR + /* + * We must do this before we start working with slots since we need all + * NIDs there. + */ + if (pk11_add_aes_ctr_NIDs() == 0) + goto err; +#endif /* SOLARIS_AES_CTR */ + +#ifdef SOLARIS_HW_SLOT_SELECTION + if (check_hw_mechanisms() == 0) + goto err; +#endif /* SOLARIS_HW_SLOT_SELECTION */ + + /* get the C_GetFunctionList function from the loaded library */ + p = (CK_C_GetFunctionList)DSO_bind_func(pk11_dso, + PK11_GET_FUNCTION_LIST); + if (!p) + { + PK11err(PK11_F_LIBRARY_INIT, PK11_R_DSO_FAILURE); + goto err; + } + + /* get the full function list from the loaded library */ + rv = p(&pFuncList); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_LIBRARY_INIT, PK11_R_DSO_FAILURE, rv); + goto err; + } + +#ifndef OPENSSL_SYS_WIN32 + /* Not all PKCS#11 library are signal safe! */ + + (void) memset(&sigint_act, 0, sizeof(sigint_act)); + (void) memset(&sigterm_act, 0, sizeof(sigterm_act)); + (void) memset(&sighup_act, 0, sizeof(sighup_act)); + (void) sigaction(SIGINT, NULL, &sigint_act); + (void) sigaction(SIGTERM, NULL, &sigterm_act); + (void) sigaction(SIGHUP, NULL, &sighup_act); +#endif + rv = pFuncList->C_Initialize((CK_VOID_PTR)&pk11_init_args); +#ifndef OPENSSL_SYS_WIN32 + (void) sigaction(SIGINT, &sigint_act, NULL); + (void) sigaction(SIGTERM, &sigterm_act, NULL); + (void) sigaction(SIGHUP, &sighup_act, NULL); +#endif + if ((rv != CKR_OK) && (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)) + { + PK11err_add_data(PK11_F_LIBRARY_INIT, PK11_R_INITIALIZE, rv); + goto err; + } + + rv = pFuncList->C_GetInfo(&info); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_LIBRARY_INIT, PK11_R_GETINFO, rv); + goto err; + } + + if (pk11_choose_slots(&any_slot_found) == 0) + goto err; + + /* + * The library we use, set in def_PK11_LIBNAME, may not offer any + * slot(s). In that case, we must not proceed but we must not return an + * error. The reason is that applications that try to set up the PKCS#11 + * engine don't exit on error during the engine initialization just + * because no slot was present. + */ + if (any_slot_found == 0) + return (1); + + if (global_session == CK_INVALID_HANDLE) + { + /* Open the global_session for the new process */ + rv = pFuncList->C_OpenSession(SLOTID, CKF_SERIAL_SESSION, + NULL_PTR, NULL_PTR, &global_session); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_LIBRARY_INIT, + PK11_R_OPENSESSION, rv); + goto err; + } + } + + /* + * Disable digest if C_GetOperationState is not supported since + * this function is required by OpenSSL digest copy function + */ + /* Keyper fails to return CKR_FUNCTION_NOT_SUPPORTED */ + if (pFuncList->C_GetOperationState(global_session, NULL, &ul_state_len) + != CKR_OK) { +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: C_GetOperationState() not supported, " + "setting digest_count to 0\n", PK11_DBG); +#endif /* DEBUG_SLOT_SELECTION */ + digest_count = 0; + } + + pk11_library_initialized = TRUE; + pk11_pid = getpid(); + /* + * if initialization of the locks fails pk11_init_all_locks() + * will do the cleanup. + */ + if (!pk11_init_all_locks()) + goto err; + for (i = 0; i < OP_MAX; i++) + session_cache[i].head = NULL; + /* + * initialize active lists. We only use active lists + * for asymmetric ciphers. + */ + for (i = 0; i < OP_MAX; i++) + active_list[i] = NULL; + +#ifndef NOPTHREADS + if (!pk11_atfork_initialized) + { + if (pthread_atfork(pk11_fork_prepare, pk11_fork_parent, + pk11_fork_child) != 0) + { + PK11err(PK11_F_LIBRARY_INIT, PK11_R_ATFORK_FAILED); + goto err; + } + pk11_atfork_initialized = TRUE; + } +#endif + + return (1); + +err: + return (0); + } + +/* Destructor (complements the "ENGINE_pk11()" constructor) */ +/* ARGSUSED */ +static int pk11_destroy(ENGINE *e) + { + free_PK11_LIBNAME(); + ERR_unload_pk11_strings(); + if (pk11_pin) { + memset(pk11_pin, 0, strlen(pk11_pin)); + OPENSSL_free((void*)pk11_pin); + } + pk11_pin = NULL; + return (1); + } + +/* + * Termination function to clean up the session, the token, and the pk11 + * library. + */ +/* ARGSUSED */ +static int pk11_finish(ENGINE *e) + { + int i; + + if (pk11_pin) { + memset(pk11_pin, 0, strlen(pk11_pin)); + OPENSSL_free((void*)pk11_pin); + } + pk11_pin = NULL; + + if (pk11_dso == NULL) + { + PK11err(PK11_F_FINISH, PK11_R_NOT_LOADED); + goto err; + } + + OPENSSL_assert(pFuncList != NULL); + + if (pk11_free_all_sessions() == 0) + goto err; + + /* free all active lists */ + for (i = 0; i < OP_MAX; i++) + pk11_free_active_list(i); + + pFuncList->C_CloseSession(global_session); + global_session = CK_INVALID_HANDLE; + + /* + * Since we are part of a library (libcrypto.so), calling this function + * may have side-effects. + */ +#if 0 + pFuncList->C_Finalize(NULL); +#endif + + if (!DSO_free(pk11_dso)) + { + PK11err(PK11_F_FINISH, PK11_R_DSO_FAILURE); + goto err; + } + pk11_dso = NULL; + pFuncList = NULL; + pk11_library_initialized = FALSE; + pk11_pid = 0; + /* + * There is no way how to unregister atfork handlers (other than + * unloading the library) so we just free the locks. For this reason + * the atfork handlers check if the engine is initialized and bail out + * immediately if not. This is necessary in case a process finishes + * the engine before calling fork(). + */ + pk11_free_all_locks(); + + return (1); + +err: + return (0); + } + +/* Standard engine interface function to set the dynamic library path */ +/* ARGSUSED */ +static int pk11_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void)) + { + int initialized = ((pk11_dso == NULL) ? 0 : 1); + + switch (cmd) + { + case PK11_CMD_SO_PATH: + if (p == NULL) + { + PK11err(PK11_F_CTRL, ERR_R_PASSED_NULL_PARAMETER); + return (0); + } + + if (initialized) + { + PK11err(PK11_F_CTRL, PK11_R_ALREADY_LOADED); + return (0); + } + + return (set_PK11_LIBNAME((const char *)p)); + case PK11_CMD_PIN: + if (pk11_pin) { + memset(pk11_pin, 0, strlen(pk11_pin)); + OPENSSL_free((void*)pk11_pin); + } + pk11_pin = NULL; + + if (p == NULL) + { + PK11err(PK11_F_CTRL, ERR_R_PASSED_NULL_PARAMETER); + return (0); + } + + pk11_pin = BUF_strdup(p); + if (pk11_pin == NULL) + { + PK11err(PK11_F_GET_SESSION, PK11_R_MALLOC_FAILURE); + return (0); + } + return (1); + case PK11_CMD_SLOT: + SLOTID = (CK_SLOT_ID)i; +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: slot set\n", PK11_DBG); +#endif + return (1); + default: + break; + } + + PK11err(PK11_F_CTRL, PK11_R_CTRL_COMMAND_NOT_IMPLEMENTED); + + return (0); + } + + +/* Required function by the engine random interface. It does nothing here */ +static void pk11_rand_cleanup(void) + { + return; + } + +/* ARGSUSED */ +static void pk11_rand_add(const void *buf, int num, double add) + { + PK11_SESSION *sp; + + if ((sp = pk11_get_session(OP_RAND)) == NULL) + return; + + /* + * Ignore any errors (e.g. CKR_RANDOM_SEED_NOT_SUPPORTED) since + * the calling functions do not care anyway + */ + pFuncList->C_SeedRandom(sp->session, (unsigned char *) buf, num); + pk11_return_session(sp, OP_RAND); + + return; + } + +static void pk11_rand_seed(const void *buf, int num) + { + pk11_rand_add(buf, num, 0); + } + +static int pk11_rand_bytes(unsigned char *buf, int num) + { + CK_RV rv; + PK11_SESSION *sp; + + if ((sp = pk11_get_session(OP_RAND)) == NULL) + return (0); + + rv = pFuncList->C_GenerateRandom(sp->session, buf, num); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_RAND_BYTES, PK11_R_GENERATERANDOM, rv); + pk11_return_session(sp, OP_RAND); + return (0); + } + + pk11_return_session(sp, OP_RAND); + return (1); + } + +/* Required function by the engine random interface. It does nothing here */ +static int pk11_rand_status(void) + { + return (1); + } + +/* Free all BIGNUM structures from PK11_SESSION. */ +static void pk11_free_nums(PK11_SESSION *sp, PK11_OPTYPE optype) + { + switch (optype) + { +#ifndef OPENSSL_NO_RSA + case OP_RSA: + if (sp->opdata_rsa_n_num != NULL) + { + BN_free(sp->opdata_rsa_n_num); + sp->opdata_rsa_n_num = NULL; + } + if (sp->opdata_rsa_e_num != NULL) + { + BN_free(sp->opdata_rsa_e_num); + sp->opdata_rsa_e_num = NULL; + } + if (sp->opdata_rsa_pn_num != NULL) + { + BN_free(sp->opdata_rsa_pn_num); + sp->opdata_rsa_pn_num = NULL; + } + if (sp->opdata_rsa_pe_num != NULL) + { + BN_free(sp->opdata_rsa_pe_num); + sp->opdata_rsa_pe_num = NULL; + } + if (sp->opdata_rsa_d_num != NULL) + { + BN_free(sp->opdata_rsa_d_num); + sp->opdata_rsa_d_num = NULL; + } + break; +#endif +#ifndef OPENSSL_NO_DSA + case OP_DSA: + if (sp->opdata_dsa_pub_num != NULL) + { + BN_free(sp->opdata_dsa_pub_num); + sp->opdata_dsa_pub_num = NULL; + } + if (sp->opdata_dsa_priv_num != NULL) + { + BN_free(sp->opdata_dsa_priv_num); + sp->opdata_dsa_priv_num = NULL; + } + break; +#endif +#ifndef OPENSSL_NO_DH + case OP_DH: + if (sp->opdata_dh_priv_num != NULL) + { + BN_free(sp->opdata_dh_priv_num); + sp->opdata_dh_priv_num = NULL; + } + break; +#endif + default: + break; + } + } + +/* + * Get new PK11_SESSION structure ready for use. Every process must have + * its own freelist of PK11_SESSION structures so handle fork() here + * by destroying the old and creating new freelist. + * The returned PK11_SESSION structure is disconnected from the freelist. + */ +PK11_SESSION * +pk11_get_session(PK11_OPTYPE optype) + { + PK11_SESSION *sp = NULL, *sp1, *freelist; +#ifndef NOPTHREADS + pthread_mutex_t *freelist_lock = NULL; +#endif + static pid_t pid = 0; + pid_t new_pid; + CK_RV rv; + + switch (optype) + { + case OP_RSA: + case OP_DSA: + case OP_DH: + case OP_RAND: + case OP_DIGEST: + case OP_CIPHER: +#ifndef NOPTHREADS + freelist_lock = session_cache[optype].lock; +#endif + break; + default: + PK11err(PK11_F_GET_SESSION, + PK11_R_INVALID_OPERATION_TYPE); + return (NULL); + } +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_lock(freelist_lock) == 0); +#else + CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); +#endif + + /* + * Will use it to find out if we forked. We cannot use the PID field in + * the session structure because we could get a newly allocated session + * here, with no PID information. + */ + if (pid == 0) + pid = getpid(); + + freelist = session_cache[optype].head; + sp = freelist; + + /* + * If the free list is empty, allocate new unitialized (filled + * with zeroes) PK11_SESSION structure otherwise return first + * structure from the freelist. + */ + if (sp == NULL) + { + if ((sp = OPENSSL_malloc(sizeof (PK11_SESSION))) == NULL) + { + PK11err(PK11_F_GET_SESSION, + PK11_R_MALLOC_FAILURE); + goto err; + } + (void) memset(sp, 0, sizeof (PK11_SESSION)); + + /* + * It is a new session so it will look like a cache miss to the + * code below. So, we must not try to to destroy its members so + * mark them as unused. + */ + sp->opdata_rsa_priv_key = CK_INVALID_HANDLE; + sp->opdata_rsa_pub_key = CK_INVALID_HANDLE; + } + else + { + freelist = sp->next; + } + + /* + * Check whether we have forked. In that case, we must get rid of all + * inherited sessions and start allocating new ones. + */ + if (pid != (new_pid = getpid())) + { + pid = new_pid; + + /* + * We are a new process and thus need to free any inherited + * PK11_SESSION objects aside from the first session (sp) which + * is the only PK11_SESSION structure we will reuse (for the + * head of the list). + */ + while ((sp1 = freelist) != NULL) + { + freelist = sp1->next; + /* + * NOTE: we do not want to call pk11_free_all_sessions() + * here because it would close underlying PKCS#11 + * sessions and destroy all objects. + */ + pk11_free_nums(sp1, optype); + OPENSSL_free(sp1); + } + + /* we have to free the active list as well. */ + pk11_free_active_list(optype); + + /* Initialize the process */ + rv = pFuncList->C_Initialize((CK_VOID_PTR)&pk11_init_args); + if ((rv != CKR_OK) && (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)) + { + PK11err_add_data(PK11_F_GET_SESSION, PK11_R_INITIALIZE, + rv); + OPENSSL_free(sp); + sp = NULL; + goto err; + } + + /* + * Choose slot here since the slot table is different on this + * process. If we are here then we must have found at least one + * usable slot before so we don't need to check any_slot_found. + * See pk11_library_init()'s usage of this function for more + * information. + */ +#ifdef SOLARIS_HW_SLOT_SELECTION + if (check_hw_mechanisms() == 0) + goto err; +#endif /* SOLARIS_HW_SLOT_SELECTION */ + if (pk11_choose_slots(NULL) == 0) + goto err; + + /* Open the global_session for the new process */ + rv = pFuncList->C_OpenSession(SLOTID, CKF_SERIAL_SESSION, + NULL_PTR, NULL_PTR, &global_session); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_SESSION, PK11_R_OPENSESSION, + rv); + OPENSSL_free(sp); + sp = NULL; + goto err; + } + + /* + * It is an inherited session from our parent so it needs + * re-initialization. + */ + if (pk11_setup_session(sp, optype) == 0) + { + OPENSSL_free(sp); + sp = NULL; + goto err; + } + if (pk11_token_relogin(sp->session) == 0) + { + /* + * We will keep the session in the cache list and let + * the caller cope with the situation. + */ + freelist = sp; + sp = NULL; + goto err; + } + } + + if (sp->pid == 0) + { + /* It is a new session and needs initialization. */ + if (pk11_setup_session(sp, optype) == 0) + { + OPENSSL_free(sp); + sp = NULL; + } + } + + /* set new head for the list of PK11_SESSION objects */ + session_cache[optype].head = freelist; + +err: + if (sp != NULL) + sp->next = NULL; + +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_unlock(freelist_lock) == 0); +#else + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + + return (sp); + } + + +void +pk11_return_session(PK11_SESSION *sp, PK11_OPTYPE optype) + { +#ifndef NOPTHREADS + pthread_mutex_t *freelist_lock; +#endif + PK11_SESSION *freelist; + + /* + * If this is a session from the parent it will be taken care of and + * freed in pk11_get_session() as part of the post-fork clean up the + * next time we will ask for a new session. + */ + if (sp == NULL || sp->pid != getpid()) + return; + + switch (optype) + { + case OP_RSA: + case OP_DSA: + case OP_DH: + case OP_RAND: + case OP_DIGEST: + case OP_CIPHER: +#ifndef NOPTHREADS + freelist_lock = session_cache[optype].lock; +#endif + break; + default: + PK11err(PK11_F_RETURN_SESSION, + PK11_R_INVALID_OPERATION_TYPE); + return; + } + +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_lock(freelist_lock) == 0); +#else + CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); +#endif + freelist = session_cache[optype].head; + sp->next = freelist; + session_cache[optype].head = sp; +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_unlock(freelist_lock) == 0); +#else + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + } + + +/* Destroy all objects. This function is called when the engine is finished */ +static int pk11_free_all_sessions() + { + int ret = 1; + int type; + +#ifndef OPENSSL_NO_RSA + (void) pk11_destroy_rsa_key_objects(NULL); +#endif /* OPENSSL_NO_RSA */ +#ifndef OPENSSL_NO_DSA + (void) pk11_destroy_dsa_key_objects(NULL); +#endif /* OPENSSL_NO_DSA */ +#ifndef OPENSSL_NO_DH + (void) pk11_destroy_dh_key_objects(NULL); +#endif /* OPENSSL_NO_DH */ + (void) pk11_destroy_cipher_key_objects(NULL); + + /* + * We try to release as much as we can but any error means that we will + * return 0 on exit. + */ + for (type = 0; type < OP_MAX; type++) + { + if (pk11_free_session_list(type) == 0) + ret = 0; + } + + return (ret); + } + +/* + * Destroy session structures from the linked list specified. Free as many + * sessions as possible but any failure in C_CloseSession() means that we + * return an error on return. + */ +static int pk11_free_session_list(PK11_OPTYPE optype) + { + CK_RV rv; + PK11_SESSION *sp = NULL; + PK11_SESSION *freelist = NULL; + pid_t mypid = getpid(); +#ifndef NOPTHREADS + pthread_mutex_t *freelist_lock; +#endif + int ret = 1; + + switch (optype) + { + case OP_RSA: + case OP_DSA: + case OP_DH: + case OP_RAND: + case OP_DIGEST: + case OP_CIPHER: +#ifndef NOPTHREADS + freelist_lock = session_cache[optype].lock; +#endif + break; + default: + PK11err(PK11_F_FREE_ALL_SESSIONS, + PK11_R_INVALID_OPERATION_TYPE); + return (0); + } + +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_lock(freelist_lock) == 0); +#else + CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); +#endif + freelist = session_cache[optype].head; + while ((sp = freelist) != NULL) + { + if (sp->session != CK_INVALID_HANDLE && sp->pid == mypid) + { + rv = pFuncList->C_CloseSession(sp->session); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_FREE_ALL_SESSIONS, + PK11_R_CLOSESESSION, rv); + ret = 0; + } + } + freelist = sp->next; + pk11_free_nums(sp, optype); + OPENSSL_free(sp); + } + +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_unlock(freelist_lock) == 0); +#else + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + return (ret); + } + + +static int +pk11_setup_session(PK11_SESSION *sp, PK11_OPTYPE optype) + { + CK_RV rv; + CK_SLOT_ID myslot; + + switch (optype) + { + case OP_RSA: + case OP_DSA: + case OP_DH: + myslot = pubkey_SLOTID; + break; + case OP_RAND: + myslot = rand_SLOTID; + break; + case OP_DIGEST: + case OP_CIPHER: + myslot = SLOTID; + break; + default: + PK11err(PK11_F_SETUP_SESSION, + PK11_R_INVALID_OPERATION_TYPE); + return (0); + } + + sp->session = CK_INVALID_HANDLE; +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: myslot=%d optype=%d\n", PK11_DBG, myslot, optype); +#endif /* DEBUG_SLOT_SELECTION */ + rv = pFuncList->C_OpenSession(myslot, CKF_SERIAL_SESSION, + NULL_PTR, NULL_PTR, &sp->session); + if (rv == CKR_CRYPTOKI_NOT_INITIALIZED) + { + /* + * We are probably a child process so force the + * reinitialize of the session + */ + pk11_library_initialized = FALSE; + if (!pk11_library_init(NULL)) + return (0); + rv = pFuncList->C_OpenSession(myslot, CKF_SERIAL_SESSION, + NULL_PTR, NULL_PTR, &sp->session); + } + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_SETUP_SESSION, PK11_R_OPENSESSION, rv); + return (0); + } + + sp->pid = getpid(); + + switch (optype) + { +#ifndef OPENSSL_NO_RSA + case OP_RSA: + sp->opdata_rsa_pub_key = CK_INVALID_HANDLE; + sp->opdata_rsa_priv_key = CK_INVALID_HANDLE; + sp->opdata_rsa_pub = NULL; + sp->opdata_rsa_n_num = NULL; + sp->opdata_rsa_e_num = NULL; + sp->opdata_rsa_priv = NULL; + sp->opdata_rsa_pn_num = NULL; + sp->opdata_rsa_pe_num = NULL; + sp->opdata_rsa_d_num = NULL; + break; +#endif /* OPENSSL_NO_RSA */ +#ifndef OPENSSL_NO_DSA + case OP_DSA: + sp->opdata_dsa_pub_key = CK_INVALID_HANDLE; + sp->opdata_dsa_priv_key = CK_INVALID_HANDLE; + sp->opdata_dsa_pub = NULL; + sp->opdata_dsa_pub_num = NULL; + sp->opdata_dsa_priv = NULL; + sp->opdata_dsa_priv_num = NULL; + break; +#endif /* OPENSSL_NO_DSA */ +#ifndef OPENSSL_NO_DH + case OP_DH: + sp->opdata_dh_key = CK_INVALID_HANDLE; + sp->opdata_dh = NULL; + sp->opdata_dh_priv_num = NULL; + break; +#endif /* OPENSSL_NO_DH */ + case OP_CIPHER: + sp->opdata_cipher_key = CK_INVALID_HANDLE; + sp->opdata_encrypt = -1; + break; + default: + break; + } + + /* + * We always initialize the session as containing a non-persistent + * object. The key load functions set it to persistent if that is so. + */ + sp->pub_persistent = CK_FALSE; + sp->priv_persistent = CK_FALSE; + return (1); + } + +#ifndef OPENSSL_NO_RSA +/* Destroy RSA public key from single session. */ +int +pk11_destroy_rsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock) + { + int ret = 0; + + if (sp->opdata_rsa_pub_key != CK_INVALID_HANDLE) + { + TRY_OBJ_DESTROY(sp, sp->opdata_rsa_pub_key, + ret, uselock, OP_RSA, CK_FALSE); + sp->opdata_rsa_pub_key = CK_INVALID_HANDLE; + sp->opdata_rsa_pub = NULL; + if (sp->opdata_rsa_n_num != NULL) + { + BN_free(sp->opdata_rsa_n_num); + sp->opdata_rsa_n_num = NULL; + } + if (sp->opdata_rsa_e_num != NULL) + { + BN_free(sp->opdata_rsa_e_num); + sp->opdata_rsa_e_num = NULL; + } + } + + return (ret); + } + +/* Destroy RSA private key from single session. */ +int +pk11_destroy_rsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock) + { + int ret = 0; + + if (sp->opdata_rsa_priv_key != CK_INVALID_HANDLE) + { + TRY_OBJ_DESTROY(sp, sp->opdata_rsa_priv_key, + ret, uselock, OP_RSA, CK_TRUE); + sp->opdata_rsa_priv_key = CK_INVALID_HANDLE; + sp->opdata_rsa_priv = NULL; + if (sp->opdata_rsa_d_num != NULL) + { + BN_free(sp->opdata_rsa_d_num); + sp->opdata_rsa_d_num = NULL; + } + + /* + * For the RSA key by reference code, public components 'n'/'e' + * are the key components we use to check for the cache hit. We + * must free those as well. + */ + if (sp->opdata_rsa_pn_num != NULL) + { + BN_free(sp->opdata_rsa_pn_num); + sp->opdata_rsa_pn_num = NULL; + } + if (sp->opdata_rsa_pe_num != NULL) + { + BN_free(sp->opdata_rsa_pe_num); + sp->opdata_rsa_pe_num = NULL; + } + } + + return (ret); + } + +/* + * Destroy RSA key object wrapper. If session is NULL, try to destroy all + * objects in the free list. + */ +int +pk11_destroy_rsa_key_objects(PK11_SESSION *session) + { + int ret = 1; + PK11_SESSION *sp = NULL; + PK11_SESSION *local_free_session; + CK_BBOOL uselock = TRUE; + + if (session != NULL) + local_free_session = session; + else + { +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_lock(session_cache[OP_RSA].lock) == 0); +#else + CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); +#endif + local_free_session = session_cache[OP_RSA].head; + uselock = FALSE; + } + + /* + * go through the list of sessions and delete key objects + */ + while ((sp = local_free_session) != NULL) + { + local_free_session = sp->next; + + /* + * Do not terminate list traversal if one of the + * destroy operations fails. + */ + if (pk11_destroy_rsa_object_pub(sp, uselock) == 0) + { + ret = 0; + continue; + } + if (pk11_destroy_rsa_object_priv(sp, uselock) == 0) + { + ret = 0; + continue; + } + } + +#ifndef NOPTHREADS + if (session == NULL) + OPENSSL_assert(pthread_mutex_unlock(session_cache[OP_RSA].lock) == 0); +#else + if (session == NULL) + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + + return (ret); + } +#endif /* OPENSSL_NO_RSA */ + +#ifndef OPENSSL_NO_DSA +/* Destroy DSA public key from single session. */ +int +pk11_destroy_dsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock) + { + int ret = 0; + + if (sp->opdata_dsa_pub_key != CK_INVALID_HANDLE) + { + TRY_OBJ_DESTROY(sp, sp->opdata_dsa_pub_key, + ret, uselock, OP_DSA, CK_FALSE); + sp->opdata_dsa_pub_key = CK_INVALID_HANDLE; + sp->opdata_dsa_pub = NULL; + if (sp->opdata_dsa_pub_num != NULL) + { + BN_free(sp->opdata_dsa_pub_num); + sp->opdata_dsa_pub_num = NULL; + } + } + + return (ret); + } + +/* Destroy DSA private key from single session. */ +int +pk11_destroy_dsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock) + { + int ret = 0; + + if (sp->opdata_dsa_priv_key != CK_INVALID_HANDLE) + { + TRY_OBJ_DESTROY(sp, sp->opdata_dsa_priv_key, + ret, uselock, OP_DSA, CK_TRUE); + sp->opdata_dsa_priv_key = CK_INVALID_HANDLE; + sp->opdata_dsa_priv = NULL; + if (sp->opdata_dsa_priv_num != NULL) + { + BN_free(sp->opdata_dsa_priv_num); + sp->opdata_dsa_priv_num = NULL; + } + } + + return (ret); + } + +/* + * Destroy DSA key object wrapper. If session is NULL, try to destroy all + * objects in the free list. + */ +int +pk11_destroy_dsa_key_objects(PK11_SESSION *session) + { + int ret = 1; + PK11_SESSION *sp = NULL; + PK11_SESSION *local_free_session; + CK_BBOOL uselock = TRUE; + + if (session != NULL) + local_free_session = session; + else + { +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_lock(session_cache[OP_DSA].lock) == 0); +#else + CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); +#endif + local_free_session = session_cache[OP_DSA].head; + uselock = FALSE; + } + + /* + * go through the list of sessions and delete key objects + */ + while ((sp = local_free_session) != NULL) + { + local_free_session = sp->next; + + /* + * Do not terminate list traversal if one of the + * destroy operations fails. + */ + if (pk11_destroy_dsa_object_pub(sp, uselock) == 0) + { + ret = 0; + continue; + } + if (pk11_destroy_dsa_object_priv(sp, uselock) == 0) + { + ret = 0; + continue; + } + } + +#ifndef NOPTHREADS + if (session == NULL) + OPENSSL_assert(pthread_mutex_unlock(session_cache[OP_DSA].lock) == 0); +#else + if (session == NULL) + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + + return (ret); + } +#endif /* OPENSSL_NO_DSA */ + +#ifndef OPENSSL_NO_DH +/* Destroy DH key from single session. */ +int +pk11_destroy_dh_object(PK11_SESSION *sp, CK_BBOOL uselock) + { + int ret = 0; + + if (sp->opdata_dh_key != CK_INVALID_HANDLE) + { + TRY_OBJ_DESTROY(sp, sp->opdata_dh_key, + ret, uselock, OP_DH, CK_TRUE); + sp->opdata_dh_key = CK_INVALID_HANDLE; + sp->opdata_dh = NULL; + if (sp->opdata_dh_priv_num != NULL) + { + BN_free(sp->opdata_dh_priv_num); + sp->opdata_dh_priv_num = NULL; + } + } + + return (ret); + } + +/* + * Destroy DH key object wrapper. + * + * arg0: pointer to PKCS#11 engine session structure + * if session is NULL, try to destroy all objects in the free list + */ +int +pk11_destroy_dh_key_objects(PK11_SESSION *session) + { + int ret = 1; + PK11_SESSION *sp = NULL; + PK11_SESSION *local_free_session; + CK_BBOOL uselock = TRUE; + + if (session != NULL) + local_free_session = session; + else + { +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_lock(session_cache[OP_DH].lock) == 0); +#else + CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); +#endif + local_free_session = session_cache[OP_DH].head; + uselock = FALSE; + } + + while ((sp = local_free_session) != NULL) + { + local_free_session = sp->next; + + /* + * Do not terminate list traversal if one of the + * destroy operations fails. + */ + if (pk11_destroy_dh_object(sp, uselock) == 0) + { + ret = 0; + continue; + } + } + +#ifndef NOPTHREADS + if (session == NULL) + OPENSSL_assert(pthread_mutex_unlock(session_cache[OP_DH].lock) == 0); +#else + if (session == NULL) + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + + return (ret); + } +#endif /* OPENSSL_NO_DH */ + +static int +pk11_destroy_object(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE oh, + CK_BBOOL persistent) + { + CK_RV rv; + + /* + * We never try to destroy persistent objects which are the objects + * stored in the keystore. Also, we always use read-only sessions so + * C_DestroyObject() would be returning CKR_SESSION_READ_ONLY here. + */ + if (persistent == CK_TRUE) + return (1); + + rv = pFuncList->C_DestroyObject(session, oh); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DESTROY_OBJECT, PK11_R_DESTROYOBJECT, + rv); + return (0); + } + + return (1); + } + + +/* Symmetric ciphers and digests support functions */ + +static int +cipher_nid_to_pk11(int nid) + { + int i; + + for (i = 0; i < PK11_CIPHER_MAX; i++) + if (ciphers[i].nid == nid) + return (ciphers[i].id); + return (-1); + } + +static int +pk11_usable_ciphers(const int **nids) + { + if (cipher_count > 0) + *nids = cipher_nids; + else + *nids = NULL; + return (cipher_count); + } + +static int +pk11_usable_digests(const int **nids) + { + if (digest_count > 0) + *nids = digest_nids; + else + *nids = NULL; + return (digest_count); + } + +/* + * Init context for encryption or decryption using a symmetric key. + */ +static int pk11_init_symmetric(EVP_CIPHER_CTX *ctx, PK11_CIPHER *pcipher, + PK11_SESSION *sp, CK_MECHANISM_PTR pmech) + { + CK_RV rv; +#ifdef SOLARIS_AES_CTR + CK_AES_CTR_PARAMS ctr_params; +#endif /* SOLARIS_AES_CTR */ + + /* + * We expect pmech->mechanism to be already set and + * pParameter/ulParameterLen initialized to NULL/0 before + * pk11_init_symetric() is called. + */ + OPENSSL_assert(pmech->mechanism != 0); + OPENSSL_assert(pmech->pParameter == NULL); + OPENSSL_assert(pmech->ulParameterLen == 0); + +#ifdef SOLARIS_AES_CTR + if (ctx->cipher->nid == NID_aes_128_ctr || + ctx->cipher->nid == NID_aes_192_ctr || + ctx->cipher->nid == NID_aes_256_ctr) + { + pmech->pParameter = (void *)(&ctr_params); + pmech->ulParameterLen = sizeof (ctr_params); + /* + * For now, we are limited to the fixed length of the counter, + * it covers the whole counter block. That's what RFC 4344 + * needs. For more information on internal structure of the + * counter block, see RFC 3686. If needed in the future, we can + * add code so that the counter length can be set via + * ENGINE_ctrl() function. + */ + ctr_params.ulCounterBits = AES_BLOCK_SIZE * 8; + OPENSSL_assert(pcipher->iv_len == AES_BLOCK_SIZE); + (void) memcpy(ctr_params.cb, ctx->iv, AES_BLOCK_SIZE); + } + else +#endif /* SOLARIS_AES_CTR */ + { + if (pcipher->iv_len > 0) + { + pmech->pParameter = (void *)ctx->iv; + pmech->ulParameterLen = pcipher->iv_len; + } + } + + /* if we get here, the encryption needs to be reinitialized */ + if (ctx->encrypt) + rv = pFuncList->C_EncryptInit(sp->session, pmech, + sp->opdata_cipher_key); + else + rv = pFuncList->C_DecryptInit(sp->session, pmech, + sp->opdata_cipher_key); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_CIPHER_INIT, ctx->encrypt ? + PK11_R_ENCRYPTINIT : PK11_R_DECRYPTINIT, rv); + pk11_return_session(sp, OP_CIPHER); + return (0); + } + + return (1); + } + +/* ARGSUSED */ +static int +pk11_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc) + { + CK_MECHANISM mech; + int index; + PK11_CIPHER_STATE *state = (PK11_CIPHER_STATE *) ctx->cipher_data; + PK11_SESSION *sp; + PK11_CIPHER *p_ciph_table_row; + + state->sp = NULL; + + index = cipher_nid_to_pk11(ctx->cipher->nid); + if (index < 0 || index >= PK11_CIPHER_MAX) + return (0); + + p_ciph_table_row = &ciphers[index]; + /* + * iv_len in the ctx->cipher structure is the maximum IV length for the + * current cipher and it must be less or equal to the IV length in our + * ciphers table. The key length must be in the allowed interval. From + * all cipher modes that the PKCS#11 engine supports only RC4 allows a + * key length to be in some range, all other NIDs have a precise key + * length. Every application can define its own EVP functions so this + * code serves as a sanity check. + * + * Note that the reason why the IV length in ctx->cipher might be + * greater than the actual length is that OpenSSL uses BLOCK_CIPHER_defs + * macro to define functions that return EVP structures for all DES + * modes. So, even ECB modes get 8 byte IV. + */ + if (ctx->cipher->iv_len < p_ciph_table_row->iv_len || + ctx->key_len < p_ciph_table_row->min_key_len || + ctx->key_len > p_ciph_table_row->max_key_len) { + PK11err(PK11_F_CIPHER_INIT, PK11_R_KEY_OR_IV_LEN_PROBLEM); + return (0); + } + + if ((sp = pk11_get_session(OP_CIPHER)) == NULL) + return (0); + + /* if applicable, the mechanism parameter is used for IV */ + mech.mechanism = p_ciph_table_row->mech_type; + mech.pParameter = NULL; + mech.ulParameterLen = 0; + + /* The key object is destroyed here if it is not the current key. */ + (void) check_new_cipher_key(sp, key, ctx->key_len); + + /* + * If the key is the same and the encryption is also the same, then + * just reuse it. However, we must not forget to reinitialize the + * context that was finalized in pk11_cipher_cleanup(). + */ + if (sp->opdata_cipher_key != CK_INVALID_HANDLE && + sp->opdata_encrypt == ctx->encrypt) + { + state->sp = sp; + if (pk11_init_symmetric(ctx, p_ciph_table_row, sp, &mech) == 0) + return (0); + + return (1); + } + + /* + * Check if the key has been invalidated. If so, a new key object + * needs to be created. + */ + if (sp->opdata_cipher_key == CK_INVALID_HANDLE) + { + sp->opdata_cipher_key = pk11_get_cipher_key( + ctx, key, p_ciph_table_row->key_type, sp); + } + + if (sp->opdata_encrypt != ctx->encrypt && sp->opdata_encrypt != -1) + { + /* + * The previous encryption/decryption is different. Need to + * terminate the previous * active encryption/decryption here. + */ + if (!pk11_cipher_final(sp)) + { + pk11_return_session(sp, OP_CIPHER); + return (0); + } + } + + if (sp->opdata_cipher_key == CK_INVALID_HANDLE) + { + pk11_return_session(sp, OP_CIPHER); + return (0); + } + + /* now initialize the context with a new key */ + if (pk11_init_symmetric(ctx, p_ciph_table_row, sp, &mech) == 0) + return (0); + + sp->opdata_encrypt = ctx->encrypt; + state->sp = sp; + + return (1); + } + +/* + * When reusing the same key in an encryption/decryption session for a + * decryption/encryption session, we need to close the active session + * and recreate a new one. Note that the key is in the global session so + * that it needs not be recreated. + * + * It is more appropriate to use C_En/DecryptFinish here. At the time of this + * development, these two functions in the PKCS#11 libraries used return + * unexpected errors when passing in 0 length output. It may be a good + * idea to try them again if performance is a problem here and fix + * C_En/DecryptFinial if there are bugs there causing the problem. + */ +static int +pk11_cipher_final(PK11_SESSION *sp) + { + CK_RV rv; + + rv = pFuncList->C_CloseSession(sp->session); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_CIPHER_FINAL, PK11_R_CLOSESESSION, rv); + return (0); + } + + rv = pFuncList->C_OpenSession(SLOTID, CKF_SERIAL_SESSION, + NULL_PTR, NULL_PTR, &sp->session); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_CIPHER_FINAL, PK11_R_OPENSESSION, rv); + return (0); + } + + return (1); + } + +/* + * An engine interface function. The calling function allocates sufficient + * memory for the output buffer "out" to hold the results. + */ +#if OPENSSL_VERSION_NUMBER < 0x10000000L +static int +pk11_cipher_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, unsigned int inl) +#else +static int +pk11_cipher_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t inl) +#endif + { + PK11_CIPHER_STATE *state = (PK11_CIPHER_STATE *) ctx->cipher_data; + PK11_SESSION *sp; + CK_RV rv; + unsigned long outl = inl; + + if (state == NULL || state->sp == NULL) + return (0); + + sp = (PK11_SESSION *) state->sp; + + if (!inl) + return (1); + + /* RC4 is the only stream cipher we support */ + if (ctx->cipher->nid != NID_rc4 && (inl % ctx->cipher->block_size) != 0) + return (0); + + if (ctx->encrypt) + { + rv = pFuncList->C_EncryptUpdate(sp->session, + (unsigned char *)in, inl, out, &outl); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_CIPHER_DO_CIPHER, + PK11_R_ENCRYPTUPDATE, rv); + return (0); + } + } + else + { + rv = pFuncList->C_DecryptUpdate(sp->session, + (unsigned char *)in, inl, out, &outl); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_CIPHER_DO_CIPHER, + PK11_R_DECRYPTUPDATE, rv); + return (0); + } + } + + /* + * For DES_CBC, DES3_CBC, AES_CBC, and RC4, the output size is always + * the same size of input. + * The application has guaranteed to call the block ciphers with + * correctly aligned buffers. + */ + if (inl != outl) + return (0); + + return (1); + } + +/* + * Return the session to the pool. Calling C_EncryptFinal() and C_DecryptFinal() + * here is the right thing because in EVP_DecryptFinal_ex(), engine's + * do_cipher() is not even called, and in EVP_EncryptFinal_ex() it is called but + * the engine can't find out that it's the finalizing call. We wouldn't + * necessarily have to finalize the context here since reinitializing it with + * C_(Encrypt|Decrypt)Init() should be fine but for the sake of correctness, + * let's do it. Some implementations might leak memory if the previously used + * context is initialized without finalizing it first. + */ +static int +pk11_cipher_cleanup(EVP_CIPHER_CTX *ctx) + { + CK_RV rv; + CK_ULONG len = EVP_MAX_BLOCK_LENGTH; + CK_BYTE buf[EVP_MAX_BLOCK_LENGTH]; + PK11_CIPHER_STATE *state = ctx->cipher_data; + + if (state != NULL && state->sp != NULL) + { + /* + * We are not interested in the data here, we just need to get + * rid of the context. + */ + if (ctx->encrypt) + rv = pFuncList->C_EncryptFinal( + state->sp->session, buf, &len); + else + rv = pFuncList->C_DecryptFinal( + state->sp->session, buf, &len); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_CIPHER_CLEANUP, ctx->encrypt ? + PK11_R_ENCRYPTFINAL : PK11_R_DECRYPTFINAL, rv); + pk11_return_session(state->sp, OP_CIPHER); + return (0); + } + + pk11_return_session(state->sp, OP_CIPHER); + state->sp = NULL; + } + + return (1); + } + +/* + * Registered by the ENGINE when used to find out how to deal with + * a particular NID in the ENGINE. This says what we'll do at the + * top level - note, that list is restricted by what we answer with + */ +/* ARGSUSED */ +static int +pk11_engine_ciphers(ENGINE *e, const EVP_CIPHER **cipher, + const int **nids, int nid) + { + if (!cipher) + return (pk11_usable_ciphers(nids)); + + switch (nid) + { + case NID_des_ede3_cbc: + *cipher = &pk11_3des_cbc; + break; + case NID_des_cbc: + *cipher = &pk11_des_cbc; + break; + case NID_des_ede3_ecb: + *cipher = &pk11_3des_ecb; + break; + case NID_des_ecb: + *cipher = &pk11_des_ecb; + break; + case NID_aes_128_cbc: + *cipher = &pk11_aes_128_cbc; + break; + case NID_aes_192_cbc: + *cipher = &pk11_aes_192_cbc; + break; + case NID_aes_256_cbc: + *cipher = &pk11_aes_256_cbc; + break; + case NID_aes_128_ecb: + *cipher = &pk11_aes_128_ecb; + break; + case NID_aes_192_ecb: + *cipher = &pk11_aes_192_ecb; + break; + case NID_aes_256_ecb: + *cipher = &pk11_aes_256_ecb; + break; + case NID_bf_cbc: + *cipher = &pk11_bf_cbc; + break; + case NID_rc4: + *cipher = &pk11_rc4; + break; + default: +#ifdef SOLARIS_AES_CTR + /* + * These can't be in separated cases because the NIDs + * here are not constants. + */ + if (nid == NID_aes_128_ctr) + *cipher = &pk11_aes_128_ctr; + else if (nid == NID_aes_192_ctr) + *cipher = &pk11_aes_192_ctr; + else if (nid == NID_aes_256_ctr) + *cipher = &pk11_aes_256_ctr; + else +#endif /* SOLARIS_AES_CTR */ + *cipher = NULL; + break; + } + return (*cipher != NULL); + } + +/* ARGSUSED */ +static int +pk11_engine_digests(ENGINE *e, const EVP_MD **digest, + const int **nids, int nid) + { + if (!digest) + return (pk11_usable_digests(nids)); + + switch (nid) + { + case NID_md5: + *digest = &pk11_md5; + break; + case NID_sha1: + *digest = &pk11_sha1; + break; + case NID_sha224: + *digest = &pk11_sha224; + break; + case NID_sha256: + *digest = &pk11_sha256; + break; + case NID_sha384: + *digest = &pk11_sha384; + break; + case NID_sha512: + *digest = &pk11_sha512; + break; + default: + *digest = NULL; + break; + } + return (*digest != NULL); + } + + +/* Create a secret key object in a PKCS#11 session */ +static CK_OBJECT_HANDLE pk11_get_cipher_key(EVP_CIPHER_CTX *ctx, + const unsigned char *key, CK_KEY_TYPE key_type, PK11_SESSION *sp) + { + CK_RV rv; + CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE; + CK_OBJECT_CLASS obj_key = CKO_SECRET_KEY; + CK_ULONG ul_key_attr_count = 6; + unsigned char key_buf[PK11_KEY_LEN_MAX]; + + CK_ATTRIBUTE a_key_template[] = + { + {CKA_CLASS, (void*) NULL, sizeof (CK_OBJECT_CLASS)}, + {CKA_KEY_TYPE, (void*) NULL, sizeof (CK_KEY_TYPE)}, + {CKA_TOKEN, &myfalse, sizeof (myfalse)}, + {CKA_ENCRYPT, &mytrue, sizeof (mytrue)}, + {CKA_DECRYPT, &mytrue, sizeof (mytrue)}, + {CKA_VALUE, (void*) NULL, 0}, + }; + + /* + * Create secret key object in global_session. All other sessions + * can use the key handles. Here is why: + * OpenSSL will call EncryptInit and EncryptUpdate using a secret key. + * It may then call DecryptInit and DecryptUpdate using the same key. + * To use the same key object, we need to call EncryptFinal with + * a 0 length message. Currently, this does not work for 3DES + * mechanism. To get around this problem, we close the session and + * then create a new session to use the same key object. When a session + * is closed, all the object handles will be invalid. Thus, create key + * objects in a global session, an individual session may be closed to + * terminate the active operation. + */ + CK_SESSION_HANDLE session = global_session; + a_key_template[0].pValue = &obj_key; + a_key_template[1].pValue = &key_type; + if (ctx->key_len > PK11_KEY_LEN_MAX) + { + a_key_template[5].pValue = (void *) key; + } + else + { + memset(key_buf, 0, PK11_KEY_LEN_MAX); + memcpy(key_buf, key, ctx->key_len); + if ((key_type == CKK_DES) || + (key_type == CKK_DES2) || + (key_type == CKK_DES3)) + DES_fixup_key_parity((DES_cblock *) &key_buf[0]); + if ((key_type == CKK_DES2) || + (key_type == CKK_DES3)) + DES_fixup_key_parity((DES_cblock *) &key_buf[8]); + if (key_type == CKK_DES3) + DES_fixup_key_parity((DES_cblock *) &key_buf[16]); + a_key_template[5].pValue = (void *) key_buf; + } + a_key_template[5].ulValueLen = (unsigned long) ctx->key_len; + + rv = pFuncList->C_CreateObject(session, + a_key_template, ul_key_attr_count, &h_key); + if (rv != CKR_OK) + { + memset(key_buf, 0, PK11_KEY_LEN_MAX); + PK11err_add_data(PK11_F_GET_CIPHER_KEY, PK11_R_CREATEOBJECT, + rv); + goto err; + } + + /* + * Save the key information used in this session. + * The max can be saved is PK11_KEY_LEN_MAX. + */ + if (ctx->key_len > PK11_KEY_LEN_MAX) + { + sp->opdata_key_len = PK11_KEY_LEN_MAX; + (void) memcpy(sp->opdata_key, key, sp->opdata_key_len); + } + else + { + sp->opdata_key_len = ctx->key_len; + (void) memcpy(sp->opdata_key, key_buf, sp->opdata_key_len); + } + memset(key_buf, 0, PK11_KEY_LEN_MAX); +err: + + return (h_key); + } + +static int +md_nid_to_pk11(int nid) + { + int i; + + for (i = 0; i < PK11_DIGEST_MAX; i++) + if (digests[i].nid == nid) + return (digests[i].id); + return (-1); + } + +static int +pk11_digest_init(EVP_MD_CTX *ctx) + { + CK_RV rv; + CK_MECHANISM mech; + int index; + PK11_SESSION *sp; + PK11_DIGEST *pdp; + PK11_CIPHER_STATE *state = (PK11_CIPHER_STATE *) ctx->md_data; + + state->sp = NULL; + + index = md_nid_to_pk11(ctx->digest->type); + if (index < 0 || index >= PK11_DIGEST_MAX) + return (0); + + pdp = &digests[index]; + if ((sp = pk11_get_session(OP_DIGEST)) == NULL) + return (0); + + /* at present, no parameter is needed for supported digests */ + mech.mechanism = pdp->mech_type; + mech.pParameter = NULL; + mech.ulParameterLen = 0; + + rv = pFuncList->C_DigestInit(sp->session, &mech); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DIGEST_INIT, PK11_R_DIGESTINIT, rv); + pk11_return_session(sp, OP_DIGEST); + return (0); + } + + state->sp = sp; + + return (1); + } + +static int +pk11_digest_update(EVP_MD_CTX *ctx, const void *data, size_t count) + { + CK_RV rv; + PK11_CIPHER_STATE *state = (PK11_CIPHER_STATE *) ctx->md_data; + + /* 0 length message will cause a failure in C_DigestFinal */ + if (count == 0) + return (1); + + if (state == NULL || state->sp == NULL) + return (0); + + rv = pFuncList->C_DigestUpdate(state->sp->session, (CK_BYTE *) data, + count); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DIGEST_UPDATE, PK11_R_DIGESTUPDATE, rv); + pk11_return_session(state->sp, OP_DIGEST); + state->sp = NULL; + return (0); + } + + return (1); + } + +static int +pk11_digest_final(EVP_MD_CTX *ctx, unsigned char *md) + { + CK_RV rv; + unsigned long len; + PK11_CIPHER_STATE *state = (PK11_CIPHER_STATE *) ctx->md_data; + len = ctx->digest->md_size; + + if (state == NULL || state->sp == NULL) + return (0); + + rv = pFuncList->C_DigestFinal(state->sp->session, md, &len); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DIGEST_FINAL, PK11_R_DIGESTFINAL, rv); + pk11_return_session(state->sp, OP_DIGEST); + state->sp = NULL; + return (0); + } + + if (ctx->digest->md_size != len) + return (0); + + /* + * Final is called and digest is returned, so return the session + * to the pool + */ + pk11_return_session(state->sp, OP_DIGEST); + state->sp = NULL; + + return (1); + } + +static int +pk11_digest_copy(EVP_MD_CTX *to, const EVP_MD_CTX *from) + { + CK_RV rv; + int ret = 0; + PK11_CIPHER_STATE *state, *state_to; + CK_BYTE_PTR pstate = NULL; + CK_ULONG ul_state_len; + + /* The copy-from state */ + state = (PK11_CIPHER_STATE *) from->md_data; + if (state == NULL || state->sp == NULL) + goto err; + + /* Initialize the copy-to state */ + if (!pk11_digest_init(to)) + goto err; + state_to = (PK11_CIPHER_STATE *) to->md_data; + + /* Get the size of the operation state of the copy-from session */ + rv = pFuncList->C_GetOperationState(state->sp->session, NULL, + &ul_state_len); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DIGEST_COPY, PK11_R_GET_OPERATION_STATE, + rv); + goto err; + } + if (ul_state_len == 0) + { + goto err; + } + + pstate = OPENSSL_malloc(ul_state_len); + if (pstate == NULL) + { + PK11err(PK11_F_DIGEST_COPY, PK11_R_MALLOC_FAILURE); + goto err; + } + + /* Get the operation state of the copy-from session */ + rv = pFuncList->C_GetOperationState(state->sp->session, pstate, + &ul_state_len); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DIGEST_COPY, PK11_R_GET_OPERATION_STATE, + rv); + goto err; + } + + /* Set the operation state of the copy-to session */ + rv = pFuncList->C_SetOperationState(state_to->sp->session, pstate, + ul_state_len, 0, 0); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DIGEST_COPY, + PK11_R_SET_OPERATION_STATE, rv); + goto err; + } + + ret = 1; +err: + if (pstate != NULL) + OPENSSL_free(pstate); + + return (ret); + } + +/* Return any pending session state to the pool */ +static int +pk11_digest_cleanup(EVP_MD_CTX *ctx) + { + PK11_CIPHER_STATE *state = ctx->md_data; + unsigned char buf[EVP_MAX_MD_SIZE]; + + if (state != NULL && state->sp != NULL) + { + /* + * If state->sp is not NULL then pk11_digest_final() has not + * been called yet. We must call it now to free any memory + * that might have been allocated in the token when + * pk11_digest_init() was called. pk11_digest_final() + * will return the session to the cache. + */ + if (!pk11_digest_final(ctx, buf)) + return (0); + } + + return (1); + } + +/* + * Check if the new key is the same as the key object in the session. If the key + * is the same, no need to create a new key object. Otherwise, the old key + * object needs to be destroyed and a new one will be created. Return 1 for + * cache hit, 0 for cache miss. Note that we must check the key length first + * otherwise we could end up reusing a different, longer key with the same + * prefix. + */ +static int check_new_cipher_key(PK11_SESSION *sp, const unsigned char *key, + int key_len) + { + if (sp->opdata_key_len != key_len || + memcmp(sp->opdata_key, key, key_len) != 0) + { + (void) pk11_destroy_cipher_key_objects(sp); + return (0); + } + return (1); + } + +/* Destroy one or more secret key objects. */ +static int pk11_destroy_cipher_key_objects(PK11_SESSION *session) + { + int ret = 0; + PK11_SESSION *sp = NULL; + PK11_SESSION *local_free_session; + + if (session != NULL) + local_free_session = session; + else + { +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_lock(session_cache[OP_CIPHER].lock) == 0); +#else + CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); +#endif + local_free_session = session_cache[OP_CIPHER].head; + } + + while ((sp = local_free_session) != NULL) + { + local_free_session = sp->next; + + if (sp->opdata_cipher_key != CK_INVALID_HANDLE) + { + /* + * The secret key object is created in the + * global_session. See pk11_get_cipher_key(). + */ + if (pk11_destroy_object(global_session, + sp->opdata_cipher_key, CK_FALSE) == 0) + goto err; + sp->opdata_cipher_key = CK_INVALID_HANDLE; + } + } + ret = 1; +err: + +#ifndef NOPTHREADS + if (session == NULL) + OPENSSL_assert(pthread_mutex_unlock(session_cache[OP_CIPHER].lock) == 0); +#else + if (session == NULL) + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + + return (ret); + } + + +/* + * Public key mechanisms optionally supported + * + * CKM_RSA_X_509 + * CKM_RSA_PKCS + * CKM_DSA + * + * The first slot that supports at least one of those mechanisms is chosen as a + * public key slot. + * + * Symmetric ciphers optionally supported + * + * CKM_DES3_CBC + * CKM_DES_CBC + * CKM_AES_CBC + * CKM_DES3_ECB + * CKM_DES_ECB + * CKM_AES_ECB + * CKM_AES_CTR + * CKM_RC4 + * CKM_BLOWFISH_CBC + * + * Digests optionally supported + * + * CKM_MD5 + * CKM_SHA_1 + * CKM_SHA224 + * CKM_SHA256 + * CKM_SHA384 + * CKM_SHA512 + * + * The output of this function is a set of global variables indicating which + * mechanisms from RSA, DSA, DH and RAND are present, and also two arrays of + * mechanisms, one for symmetric ciphers and one for digests. Also, 3 global + * variables carry information about which slot was chosen for (a) public key + * mechanisms, (b) random operations, and (c) symmetric ciphers and digests. + */ +static int +pk11_choose_slots(int *any_slot_found) + { + CK_SLOT_ID_PTR pSlotList = NULL_PTR; + CK_ULONG ulSlotCount = 0; + CK_MECHANISM_INFO mech_info; + CK_TOKEN_INFO token_info; + unsigned int i; + CK_RV rv; + CK_SLOT_ID best_slot_sofar = 0; + CK_BBOOL found_candidate_slot = CK_FALSE; + int slot_n_cipher = 0; + int slot_n_digest = 0; + CK_SLOT_ID current_slot = 0; + int current_slot_n_cipher = 0; + int current_slot_n_digest = 0; + + int local_cipher_nids[PK11_CIPHER_MAX]; + int local_digest_nids[PK11_DIGEST_MAX]; + + /* let's initialize the output parameter */ + if (any_slot_found != NULL) + *any_slot_found = 0; + + /* Get slot list for memory allocation */ + rv = pFuncList->C_GetSlotList(CK_FALSE, NULL_PTR, &ulSlotCount); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_CHOOSE_SLOT, PK11_R_GETSLOTLIST, rv); + return (0); + } + + /* it's not an error if we didn't find any providers */ + if (ulSlotCount == 0) + { +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: no crypto providers found\n", PK11_DBG); +#endif /* DEBUG_SLOT_SELECTION */ + return (1); + } + + pSlotList = OPENSSL_malloc(ulSlotCount * sizeof (CK_SLOT_ID)); + + if (pSlotList == NULL) + { + PK11err(PK11_F_CHOOSE_SLOT, PK11_R_MALLOC_FAILURE); + return (0); + } + + /* Get the slot list for processing */ + rv = pFuncList->C_GetSlotList(CK_FALSE, pSlotList, &ulSlotCount); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_CHOOSE_SLOT, PK11_R_GETSLOTLIST, rv); + OPENSSL_free(pSlotList); + return (0); + } + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: provider: %s\n", PK11_DBG, def_PK11_LIBNAME); + fprintf(stderr, "%s: number of slots: %d\n", PK11_DBG, ulSlotCount); + + fprintf(stderr, "%s: == checking rand slots ==\n", PK11_DBG); +#endif /* DEBUG_SLOT_SELECTION */ + for (i = 0; i < ulSlotCount; i++) + { + current_slot = pSlotList[i]; + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: checking slot: %d\n", PK11_DBG, i); +#endif /* DEBUG_SLOT_SELECTION */ + /* Check if slot has random support. */ + rv = pFuncList->C_GetTokenInfo(current_slot, &token_info); + if (rv != CKR_OK) + continue; + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: token label: %.32s\n", PK11_DBG, token_info.label); +#endif /* DEBUG_SLOT_SELECTION */ + + if (token_info.flags & CKF_RNG) + { +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: this token has CKF_RNG flag\n", PK11_DBG); +#endif /* DEBUG_SLOT_SELECTION */ + pk11_have_random = CK_TRUE; + rand_SLOTID = current_slot; + break; + } + } + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: == checking pubkey slots ==\n", PK11_DBG); +#endif /* DEBUG_SLOT_SELECTION */ + + pubkey_SLOTID = pSlotList[0]; + for (i = 0; i < ulSlotCount; i++) + { + CK_BBOOL slot_has_rsa = CK_FALSE; + CK_BBOOL slot_has_recover = CK_FALSE; + CK_BBOOL slot_has_dsa = CK_FALSE; + CK_BBOOL slot_has_dh = CK_FALSE; + current_slot = pSlotList[i]; + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: checking slot: %d\n", PK11_DBG, i); +#endif /* DEBUG_SLOT_SELECTION */ + rv = pFuncList->C_GetTokenInfo(current_slot, &token_info); + if (rv != CKR_OK) + continue; + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: token label: %.32s\n", PK11_DBG, token_info.label); +#endif /* DEBUG_SLOT_SELECTION */ + +#ifndef OPENSSL_NO_RSA + /* + * Check if this slot is capable of signing and + * verifying with CKM_RSA_PKCS. + */ + rv = pFuncList->C_GetMechanismInfo(current_slot, CKM_RSA_PKCS, + &mech_info); + + if (rv == CKR_OK && ((mech_info.flags & CKF_SIGN) && + (mech_info.flags & CKF_VERIFY))) + { + /* + * Check if this slot is capable of encryption, + * decryption, sign, and verify with CKM_RSA_X_509. + */ + rv = pFuncList->C_GetMechanismInfo(current_slot, + CKM_RSA_X_509, &mech_info); + + if (rv == CKR_OK && ((mech_info.flags & CKF_SIGN) && + (mech_info.flags & CKF_VERIFY) && + (mech_info.flags & CKF_ENCRYPT) && + (mech_info.flags & CKF_DECRYPT))) + { + slot_has_rsa = CK_TRUE; + if (mech_info.flags & CKF_VERIFY_RECOVER) + { + slot_has_recover = CK_TRUE; + } + } + } +#endif /* OPENSSL_NO_RSA */ + +#ifndef OPENSSL_NO_DSA + /* + * Check if this slot is capable of signing and + * verifying with CKM_DSA. + */ + rv = pFuncList->C_GetMechanismInfo(current_slot, CKM_DSA, + &mech_info); + if (rv == CKR_OK && ((mech_info.flags & CKF_SIGN) && + (mech_info.flags & CKF_VERIFY))) + { + slot_has_dsa = CK_TRUE; + } + +#endif /* OPENSSL_NO_DSA */ + +#ifndef OPENSSL_NO_DH + /* + * Check if this slot is capable of DH key generataion and + * derivation. + */ + rv = pFuncList->C_GetMechanismInfo(current_slot, + CKM_DH_PKCS_KEY_PAIR_GEN, &mech_info); + + if (rv == CKR_OK && (mech_info.flags & CKF_GENERATE_KEY_PAIR)) + { + rv = pFuncList->C_GetMechanismInfo(current_slot, + CKM_DH_PKCS_DERIVE, &mech_info); + if (rv == CKR_OK && (mech_info.flags & CKF_DERIVE)) + { + slot_has_dh = CK_TRUE; + } + } +#endif /* OPENSSL_NO_DH */ + + if (!found_candidate_slot && + (slot_has_rsa || slot_has_dsa || slot_has_dh)) + { +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, + "%s: potential slot: %d\n", PK11_DBG, current_slot); +#endif /* DEBUG_SLOT_SELECTION */ + best_slot_sofar = current_slot; + pk11_have_rsa = slot_has_rsa; + pk11_have_recover = slot_has_recover; + pk11_have_dsa = slot_has_dsa; + pk11_have_dh = slot_has_dh; + found_candidate_slot = CK_TRUE; + /* + * Cache the flags for later use. We might + * need those if RSA keys by reference feature + * is used. + */ + pubkey_token_flags = token_info.flags; +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, + "%s: setting found_candidate_slot to CK_TRUE\n", + PK11_DBG); + fprintf(stderr, + "%s: best so far slot: %d\n", PK11_DBG, + best_slot_sofar); + fprintf(stderr, "%s: pubkey flags changed to " + "%lu.\n", PK11_DBG, pubkey_token_flags); + } + else + { + fprintf(stderr, + "%s: no rsa/dsa/dh\n", PK11_DBG); + } +#else + } /* if */ +#endif /* DEBUG_SLOT_SELECTION */ + } /* for */ + + if (found_candidate_slot == CK_TRUE) + { + pubkey_SLOTID = best_slot_sofar; + } + + found_candidate_slot = CK_FALSE; + best_slot_sofar = 0; + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: == checking cipher/digest ==\n", PK11_DBG); +#endif /* DEBUG_SLOT_SELECTION */ + + SLOTID = pSlotList[0]; + for (i = 0; i < ulSlotCount; i++) + { +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: checking slot: %d\n", PK11_DBG, i); +#endif /* DEBUG_SLOT_SELECTION */ + + current_slot = pSlotList[i]; + current_slot_n_cipher = 0; + current_slot_n_digest = 0; + (void) memset(local_cipher_nids, 0, sizeof (local_cipher_nids)); + (void) memset(local_digest_nids, 0, sizeof (local_digest_nids)); + + pk11_find_symmetric_ciphers(pFuncList, current_slot, + ¤t_slot_n_cipher, local_cipher_nids); + + pk11_find_digests(pFuncList, current_slot, + ¤t_slot_n_digest, local_digest_nids); + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: current_slot_n_cipher %d\n", PK11_DBG, + current_slot_n_cipher); + fprintf(stderr, "%s: current_slot_n_digest %d\n", PK11_DBG, + current_slot_n_digest); + fprintf(stderr, "%s: best so far cipher/digest slot: %d\n", + PK11_DBG, best_slot_sofar); +#endif /* DEBUG_SLOT_SELECTION */ + + /* + * If the current slot supports more ciphers/digests than + * the previous best one we change the current best to this one, + * otherwise leave it where it is. + */ + if ((current_slot_n_cipher + current_slot_n_digest) > + (slot_n_cipher + slot_n_digest)) + { +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, + "%s: changing best so far slot to %d\n", + PK11_DBG, current_slot); +#endif /* DEBUG_SLOT_SELECTION */ + best_slot_sofar = SLOTID = current_slot; + cipher_count = slot_n_cipher = current_slot_n_cipher; + digest_count = slot_n_digest = current_slot_n_digest; + (void) memcpy(cipher_nids, local_cipher_nids, + sizeof (local_cipher_nids)); + (void) memcpy(digest_nids, local_digest_nids, + sizeof (local_digest_nids)); + } + } + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, + "%s: chosen pubkey slot: %d\n", PK11_DBG, pubkey_SLOTID); + fprintf(stderr, + "%s: chosen rand slot: %d\n", PK11_DBG, rand_SLOTID); + fprintf(stderr, + "%s: chosen cipher/digest slot: %d\n", PK11_DBG, SLOTID); + fprintf(stderr, + "%s: pk11_have_rsa %d\n", PK11_DBG, pk11_have_rsa); + fprintf(stderr, + "%s: pk11_have_recover %d\n", PK11_DBG, pk11_have_recover); + fprintf(stderr, + "%s: pk11_have_dsa %d\n", PK11_DBG, pk11_have_dsa); + fprintf(stderr, + "%s: pk11_have_dh %d\n", PK11_DBG, pk11_have_dh); + fprintf(stderr, + "%s: pk11_have_random %d\n", PK11_DBG, pk11_have_random); + fprintf(stderr, + "%s: cipher_count %d\n", PK11_DBG, cipher_count); + fprintf(stderr, + "%s: digest_count %d\n", PK11_DBG, digest_count); +#endif /* DEBUG_SLOT_SELECTION */ + + if (pSlotList != NULL) + OPENSSL_free(pSlotList); + +#ifdef SOLARIS_HW_SLOT_SELECTION + OPENSSL_free(hw_cnids); + OPENSSL_free(hw_dnids); +#endif /* SOLARIS_HW_SLOT_SELECTION */ + + if (any_slot_found != NULL) + *any_slot_found = 1; + return (1); + } + +static void pk11_get_symmetric_cipher(CK_FUNCTION_LIST_PTR pflist, + int slot_id, CK_MECHANISM_TYPE mech, int *current_slot_n_cipher, + int *local_cipher_nids, int id) + { + CK_MECHANISM_INFO mech_info; + CK_RV rv; + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: checking mech: %x", PK11_DBG, mech); +#endif /* DEBUG_SLOT_SELECTION */ + rv = pflist->C_GetMechanismInfo(slot_id, mech, &mech_info); + + if (rv != CKR_OK) + { +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, " not found\n"); +#endif /* DEBUG_SLOT_SELECTION */ + return; + } + + if ((mech_info.flags & CKF_ENCRYPT) && + (mech_info.flags & CKF_DECRYPT)) + { +#ifdef SOLARIS_HW_SLOT_SELECTION + if (nid_in_table(ciphers[id].nid, hw_cnids)) +#endif /* SOLARIS_HW_SLOT_SELECTION */ + { +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, " usable\n"); +#endif /* DEBUG_SLOT_SELECTION */ + local_cipher_nids[(*current_slot_n_cipher)++] = + ciphers[id].nid; + } +#ifdef SOLARIS_HW_SLOT_SELECTION +#ifdef DEBUG_SLOT_SELECTION + else + { + fprintf(stderr, " rejected, software implementation only\n"); + } +#endif /* DEBUG_SLOT_SELECTION */ +#endif /* SOLARIS_HW_SLOT_SELECTION */ + } +#ifdef DEBUG_SLOT_SELECTION + else + { + fprintf(stderr, " unusable\n"); + } +#endif /* DEBUG_SLOT_SELECTION */ + + return; + } + +static void pk11_get_digest(CK_FUNCTION_LIST_PTR pflist, int slot_id, + CK_MECHANISM_TYPE mech, int *current_slot_n_digest, int *local_digest_nids, + int id) + { + CK_MECHANISM_INFO mech_info; + CK_RV rv; + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: checking mech: %x", PK11_DBG, mech); +#endif /* DEBUG_SLOT_SELECTION */ + rv = pflist->C_GetMechanismInfo(slot_id, mech, &mech_info); + + if (rv != CKR_OK) + { +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, " not found\n"); +#endif /* DEBUG_SLOT_SELECTION */ + return; + } + + if (mech_info.flags & CKF_DIGEST) + { +#ifdef SOLARIS_HW_SLOT_SELECTION + if (nid_in_table(digests[id].nid, hw_dnids)) +#endif /* SOLARIS_HW_SLOT_SELECTION */ + { +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, " usable\n"); +#endif /* DEBUG_SLOT_SELECTION */ + local_digest_nids[(*current_slot_n_digest)++] = + digests[id].nid; + } +#ifdef SOLARIS_HW_SLOT_SELECTION +#ifdef DEBUG_SLOT_SELECTION + else + { + fprintf(stderr, " rejected, software implementation only\n"); + } +#endif /* DEBUG_SLOT_SELECTION */ +#endif /* SOLARIS_HW_SLOT_SELECTION */ + } +#ifdef DEBUG_SLOT_SELECTION + else + { + fprintf(stderr, " unusable\n"); + } +#endif /* DEBUG_SLOT_SELECTION */ + + return; + } + +#ifdef SOLARIS_AES_CTR +/* create a new NID when we have no OID for that mechanism */ +static int pk11_add_NID(char *sn, char *ln) + { + ASN1_OBJECT *o; + int nid; + + if ((o = ASN1_OBJECT_create(OBJ_new_nid(1), (unsigned char *)"", + 1, sn, ln)) == NULL) + { + return (0); + } + + /* will return NID_undef on error */ + nid = OBJ_add_object(o); + ASN1_OBJECT_free(o); + + return (nid); + } + +/* + * Create new NIDs for AES counter mode. OpenSSL doesn't support them now so we + * have to help ourselves here. + */ +static int pk11_add_aes_ctr_NIDs(void) + { + /* are we already set? */ + if (NID_aes_256_ctr != NID_undef) + return (1); + + /* + * There are no official names for AES counter modes yet so we just + * follow the format of those that exist. + */ + if ((NID_aes_128_ctr = pk11_add_NID("AES-128-CTR", "aes-128-ctr")) == + NID_undef) + goto err; + ciphers[PK11_AES_128_CTR].nid = pk11_aes_128_ctr.nid = NID_aes_128_ctr; + if ((NID_aes_192_ctr = pk11_add_NID("AES-192-CTR", "aes-192-ctr")) == + NID_undef) + goto err; + ciphers[PK11_AES_192_CTR].nid = pk11_aes_192_ctr.nid = NID_aes_192_ctr; + if ((NID_aes_256_ctr = pk11_add_NID("AES-256-CTR", "aes-256-ctr")) == + NID_undef) + goto err; + ciphers[PK11_AES_256_CTR].nid = pk11_aes_256_ctr.nid = NID_aes_256_ctr; + return (1); + +err: + PK11err(PK11_F_ADD_AES_CTR_NIDS, PK11_R_ADD_NID_FAILED); + return (0); + } +#endif /* SOLARIS_AES_CTR */ + +/* Find what symmetric ciphers this slot supports. */ +static void pk11_find_symmetric_ciphers(CK_FUNCTION_LIST_PTR pflist, + CK_SLOT_ID current_slot, int *current_slot_n_cipher, int *local_cipher_nids) + { + int i; + + for (i = 0; i < PK11_CIPHER_MAX; ++i) + { + pk11_get_symmetric_cipher(pflist, current_slot, + ciphers[i].mech_type, current_slot_n_cipher, + local_cipher_nids, ciphers[i].id); + } + } + +/* Find what digest algorithms this slot supports. */ +static void pk11_find_digests(CK_FUNCTION_LIST_PTR pflist, + CK_SLOT_ID current_slot, int *current_slot_n_digest, int *local_digest_nids) + { + int i; + + for (i = 0; i < PK11_DIGEST_MAX; ++i) + { + pk11_get_digest(pflist, current_slot, digests[i].mech_type, + current_slot_n_digest, local_digest_nids, digests[i].id); + } + } + +#ifdef SOLARIS_HW_SLOT_SELECTION +/* + * It would be great if we could use pkcs11_kernel directly since this library + * offers hardware slots only. That's the easiest way to achieve the situation + * where we use the hardware accelerators when present and OpenSSL native code + * otherwise. That presumes the fact that OpenSSL native code is faster than the + * code in the soft token. It's a logical assumption - Crypto Framework has some + * inherent overhead so going there for the software implementation of a + * mechanism should be logically slower in contrast to the OpenSSL native code, + * presuming that both implementations are of similar speed. For example, the + * soft token for AES is roughly three times slower than OpenSSL for 64 byte + * blocks and still 20% slower for 8KB blocks. So, if we want to ship products + * that use the PKCS#11 engine by default, we must somehow avoid that regression + * on machines without hardware acceleration. That's why switching to the + * pkcs11_kernel library seems like a very good idea. + * + * The problem is that OpenSSL built with SunStudio is roughly 2x slower for + * asymmetric operations (RSA/DSA/DH) than the soft token built with the same + * compiler. That means that if we switched to pkcs11_kernel from the libpkcs11 + * library, we would have had a performance regression on machines without + * hardware acceleration for asymmetric operations for all applications that use + * the PKCS#11 engine. There is one such application - Apache web server since + * it's shipped configured to use the PKCS#11 engine by default. Having said + * that, we can't switch to the pkcs11_kernel library now and have to come with + * a solution that, on non-accelerated machines, uses the OpenSSL native code + * for all symmetric ciphers and digests while it uses the soft token for + * asymmetric operations. + * + * This is the idea: dlopen() pkcs11_kernel directly and find out what + * mechanisms are there. We don't care about duplications (more slots can + * support the same mechanism), we just want to know what mechanisms can be + * possibly supported in hardware on that particular machine. As said before, + * pkcs11_kernel will show you hardware providers only. + * + * Then, we rely on the fact that since we use libpkcs11 library we will find + * the metaslot. When we go through the metaslot's mechanisms for symmetric + * ciphers and digests, we check that any found mechanism is in the table + * created using the pkcs11_kernel library. So, as a result we have two arrays + * of mechanisms that were advertised as supported in hardware which was the + * goal of that whole excercise. Thus, we can use libpkcs11 but avoid soft token + * code for symmetric ciphers and digests. See pk11_choose_slots() for more + * information. + * + * This is Solaris specific code, if SOLARIS_HW_SLOT_SELECTION is not defined + * the code won't be used. + */ +#if defined(__sparcv9) || defined(__x86_64) || defined(__amd64) +static const char pkcs11_kernel[] = "/usr/lib/security/64/pkcs11_kernel.so.1"; +#else +static const char pkcs11_kernel[] = "/usr/lib/security/pkcs11_kernel.so.1"; +#endif + +/* + * Check hardware capabilities of the machines. The output are two lists, + * hw_cnids and hw_dnids, that contain hardware mechanisms found in all hardware + * providers together. They are not sorted and may contain duplicate mechanisms. + */ +static int check_hw_mechanisms(void) + { + int i; + CK_RV rv; + void *handle; + CK_C_GetFunctionList p; + CK_TOKEN_INFO token_info; + CK_ULONG ulSlotCount = 0; + int n_cipher = 0, n_digest = 0; + CK_FUNCTION_LIST_PTR pflist = NULL; + CK_SLOT_ID_PTR pSlotList = NULL_PTR; + int *tmp_hw_cnids = NULL, *tmp_hw_dnids = NULL; + int hw_ctable_size, hw_dtable_size; + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: SOLARIS_HW_SLOT_SELECTION code running\n", + PK11_DBG); +#endif + if ((handle = dlopen(pkcs11_kernel, RTLD_LAZY)) == NULL) + { + PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_DSO_FAILURE); + goto err; + } + + if ((p = (CK_C_GetFunctionList)dlsym(handle, + PK11_GET_FUNCTION_LIST)) == NULL) + { + PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_DSO_FAILURE); + goto err; + } + + /* get the full function list from the loaded library */ + if (p(&pflist) != CKR_OK) + { + PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_DSO_FAILURE); + goto err; + } + + rv = pflist->C_Initialize((CK_VOID_PTR)&pk11_init_args); + if ((rv != CKR_OK) && (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)) + { + PK11err_add_data(PK11_F_CHECK_HW_MECHANISMS, + PK11_R_INITIALIZE, rv); + goto err; + } + + if (pflist->C_GetSlotList(0, NULL_PTR, &ulSlotCount) != CKR_OK) + { + PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_GETSLOTLIST); + goto err; + } + + /* no slots, set the hw mechanism tables as empty */ + if (ulSlotCount == 0) + { +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: no hardware mechanisms found\n", PK11_DBG); +#endif + hw_cnids = OPENSSL_malloc(sizeof (int)); + hw_dnids = OPENSSL_malloc(sizeof (int)); + if (hw_cnids == NULL || hw_dnids == NULL) + { + PK11err(PK11_F_CHECK_HW_MECHANISMS, + PK11_R_MALLOC_FAILURE); + return (0); + } + /* this means empty tables */ + hw_cnids[0] = NID_undef; + hw_dnids[0] = NID_undef; + return (1); + } + + pSlotList = OPENSSL_malloc(ulSlotCount * sizeof (CK_SLOT_ID)); + if (pSlotList == NULL) + { + PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_MALLOC_FAILURE); + goto err; + } + + /* Get the slot list for processing */ + if (pflist->C_GetSlotList(0, pSlotList, &ulSlotCount) != CKR_OK) + { + PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_GETSLOTLIST); + goto err; + } + + /* + * We don't care about duplicit mechanisms in multiple slots and also + * reserve one slot for the terminal NID_undef which we use to stop the + * search. + */ + hw_ctable_size = ulSlotCount * PK11_CIPHER_MAX + 1; + hw_dtable_size = ulSlotCount * PK11_DIGEST_MAX + 1; + tmp_hw_cnids = OPENSSL_malloc(hw_ctable_size * sizeof (int)); + tmp_hw_dnids = OPENSSL_malloc(hw_dtable_size * sizeof (int)); + if (tmp_hw_cnids == NULL || tmp_hw_dnids == NULL) + { + PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_MALLOC_FAILURE); + goto err; + } + + /* + * Do not use memset since we should not rely on the fact that NID_undef + * is zero now. + */ + for (i = 0; i < hw_ctable_size; ++i) + tmp_hw_cnids[i] = NID_undef; + for (i = 0; i < hw_dtable_size; ++i) + tmp_hw_dnids[i] = NID_undef; + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: provider: %s\n", PK11_DBG, pkcs11_kernel); + fprintf(stderr, "%s: found %d hardware slots\n", PK11_DBG, ulSlotCount); + fprintf(stderr, "%s: now looking for mechs supported in hw\n", + PK11_DBG); +#endif /* DEBUG_SLOT_SELECTION */ + + for (i = 0; i < ulSlotCount; i++) + { + if (pflist->C_GetTokenInfo(pSlotList[i], &token_info) != CKR_OK) + continue; + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: token label: %.32s\n", PK11_DBG, token_info.label); +#endif /* DEBUG_SLOT_SELECTION */ + + /* + * We are filling the hw mech tables here. Global tables are + * still NULL so all mechanisms are put into tmp tables. + */ + pk11_find_symmetric_ciphers(pflist, pSlotList[i], + &n_cipher, tmp_hw_cnids); + pk11_find_digests(pflist, pSlotList[i], + &n_digest, tmp_hw_dnids); + } + + /* + * Since we are part of a library (libcrypto.so), calling this function + * may have side-effects. Also, C_Finalize() is triggered by + * dlclose(3C). + */ +#if 0 + pflist->C_Finalize(NULL); +#endif + OPENSSL_free(pSlotList); + (void) dlclose(handle); + hw_cnids = tmp_hw_cnids; + hw_dnids = tmp_hw_dnids; + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: hw mechs check complete\n", PK11_DBG); +#endif /* DEBUG_SLOT_SELECTION */ + return (1); + +err: + if (pSlotList != NULL) + OPENSSL_free(pSlotList); + if (tmp_hw_cnids != NULL) + OPENSSL_free(tmp_hw_cnids); + if (tmp_hw_dnids != NULL) + OPENSSL_free(tmp_hw_dnids); + + return (0); + } + +/* + * Check presence of a NID in the table of NIDs. The table may be NULL (i.e., + * non-existent). + */ +static int nid_in_table(int nid, int *nid_table) + { + int i = 0; + + /* + * a special case. NULL means that we are initializing a new + * table. + */ + if (nid_table == NULL) + return (1); + + /* + * the table is never full, there is always at least one + * NID_undef. + */ + while (nid_table[i] != NID_undef) + { + if (nid_table[i++] == nid) + { +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, " (NID %d in hw table, idx %d)", nid, i); +#endif /* DEBUG_SLOT_SELECTION */ + return (1); + } + } + + return (0); + } +#endif /* SOLARIS_HW_SLOT_SELECTION */ + +#endif /* OPENSSL_NO_HW_PK11CA */ +#endif /* OPENSSL_NO_HW_PK11 */ +#endif /* OPENSSL_NO_HW */ Index: openssl/crypto/engine/hw_pk11_err.c diff -u /dev/null openssl/crypto/engine/hw_pk11_err.c:1.5 --- /dev/null Wed Dec 23 17:47:11 2015 +++ openssl/crypto/engine/hw_pk11_err.c Tue Jun 14 00:43:26 2011 @@ -0,0 +1,288 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* crypto/engine/hw_pk11_err.c */ +/* + * This product includes software developed by the OpenSSL Project for + * use in the OpenSSL Toolkit (http://www.openssl.org/). + * + * This project also referenced hw_pkcs11-0.9.7b.patch written by + * Afchine Madjlessi. + */ +/* + * ==================================================================== + * Copyright (c) 2000-2001 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include +#include +#include "hw_pk11_err.h" + +/* BEGIN ERROR CODES */ +#ifndef OPENSSL_NO_ERR +static ERR_STRING_DATA pk11_str_functs[]= +{ +{ ERR_PACK(0, PK11_F_INIT, 0), "PK11_INIT"}, +{ ERR_PACK(0, PK11_F_FINISH, 0), "PK11_FINISH"}, +{ ERR_PACK(0, PK11_F_DESTROY, 0), "PK11_DESTROY"}, +{ ERR_PACK(0, PK11_F_CTRL, 0), "PK11_CTRL"}, +{ ERR_PACK(0, PK11_F_RSA_INIT, 0), "PK11_RSA_INIT"}, +{ ERR_PACK(0, PK11_F_RSA_FINISH, 0), "PK11_RSA_FINISH"}, +{ ERR_PACK(0, PK11_F_GET_PUB_RSA_KEY, 0), "PK11_GET_PUB_RSA_KEY"}, +{ ERR_PACK(0, PK11_F_GET_PRIV_RSA_KEY, 0), "PK11_GET_PRIV_RSA_KEY"}, +{ ERR_PACK(0, PK11_F_RSA_GEN_KEY, 0), "PK11_RSA_GEN_KEY"}, +{ ERR_PACK(0, PK11_F_RSA_PUB_ENC, 0), "PK11_RSA_PUB_ENC"}, +{ ERR_PACK(0, PK11_F_RSA_PRIV_ENC, 0), "PK11_RSA_PRIV_ENC"}, +{ ERR_PACK(0, PK11_F_RSA_PUB_DEC, 0), "PK11_RSA_PUB_DEC"}, +{ ERR_PACK(0, PK11_F_RSA_PRIV_DEC, 0), "PK11_RSA_PRIV_DEC"}, +{ ERR_PACK(0, PK11_F_RSA_SIGN, 0), "PK11_RSA_SIGN"}, +{ ERR_PACK(0, PK11_F_RSA_VERIFY, 0), "PK11_RSA_VERIFY"}, +{ ERR_PACK(0, PK11_F_RAND_ADD, 0), "PK11_RAND_ADD"}, +{ ERR_PACK(0, PK11_F_RAND_BYTES, 0), "PK11_RAND_BYTES"}, +{ ERR_PACK(0, PK11_F_GET_SESSION, 0), "PK11_GET_SESSION"}, +{ ERR_PACK(0, PK11_F_FREE_SESSION, 0), "PK11_FREE_SESSION"}, +{ ERR_PACK(0, PK11_F_LOAD_PUBKEY, 0), "PK11_LOAD_PUBKEY"}, +{ ERR_PACK(0, PK11_F_LOAD_PRIVKEY, 0), "PK11_LOAD_PRIV_KEY"}, +{ ERR_PACK(0, PK11_F_RSA_PUB_ENC_LOW, 0), "PK11_RSA_PUB_ENC_LOW"}, +{ ERR_PACK(0, PK11_F_RSA_PRIV_ENC_LOW, 0), "PK11_RSA_PRIV_ENC_LOW"}, +{ ERR_PACK(0, PK11_F_RSA_PUB_DEC_LOW, 0), "PK11_RSA_PUB_DEC_LOW"}, +{ ERR_PACK(0, PK11_F_RSA_PRIV_DEC_LOW, 0), "PK11_RSA_PRIV_DEC_LOW"}, +{ ERR_PACK(0, PK11_F_DSA_SIGN, 0), "PK11_DSA_SIGN"}, +{ ERR_PACK(0, PK11_F_DSA_VERIFY, 0), "PK11_DSA_VERIFY"}, +{ ERR_PACK(0, PK11_F_DSA_INIT, 0), "PK11_DSA_INIT"}, +{ ERR_PACK(0, PK11_F_DSA_FINISH, 0), "PK11_DSA_FINISH"}, +{ ERR_PACK(0, PK11_F_GET_PUB_DSA_KEY, 0), "PK11_GET_PUB_DSA_KEY"}, +{ ERR_PACK(0, PK11_F_GET_PRIV_DSA_KEY, 0), "PK11_GET_PRIV_DSA_KEY"}, +{ ERR_PACK(0, PK11_F_DH_INIT, 0), "PK11_DH_INIT"}, +{ ERR_PACK(0, PK11_F_DH_FINISH, 0), "PK11_DH_FINISH"}, +{ ERR_PACK(0, PK11_F_MOD_EXP_DH, 0), "PK11_MOD_EXP_DH"}, +{ ERR_PACK(0, PK11_F_GET_DH_KEY, 0), "PK11_GET_DH_KEY"}, +{ ERR_PACK(0, PK11_F_FREE_ALL_SESSIONS, 0), "PK11_FREE_ALL_SESSIONS"}, +{ ERR_PACK(0, PK11_F_SETUP_SESSION, 0), "PK11_SETUP_SESSION"}, +{ ERR_PACK(0, PK11_F_DESTROY_OBJECT, 0), "PK11_DESTROY_OBJECT"}, +{ ERR_PACK(0, PK11_F_CIPHER_INIT, 0), "PK11_CIPHER_INIT"}, +{ ERR_PACK(0, PK11_F_CIPHER_DO_CIPHER, 0), "PK11_CIPHER_DO_CIPHER"}, +{ ERR_PACK(0, PK11_F_GET_CIPHER_KEY, 0), "PK11_GET_CIPHER_KEY"}, +{ ERR_PACK(0, PK11_F_DIGEST_INIT, 0), "PK11_DIGEST_INIT"}, +{ ERR_PACK(0, PK11_F_DIGEST_UPDATE, 0), "PK11_DIGEST_UPDATE"}, +{ ERR_PACK(0, PK11_F_DIGEST_FINAL, 0), "PK11_DIGEST_FINAL"}, +{ ERR_PACK(0, PK11_F_CHOOSE_SLOT, 0), "PK11_CHOOSE_SLOT"}, +{ ERR_PACK(0, PK11_F_CIPHER_FINAL, 0), "PK11_CIPHER_FINAL"}, +{ ERR_PACK(0, PK11_F_LIBRARY_INIT, 0), "PK11_LIBRARY_INIT"}, +{ ERR_PACK(0, PK11_F_LOAD, 0), "ENGINE_LOAD_PK11"}, +{ ERR_PACK(0, PK11_F_DH_GEN_KEY, 0), "PK11_DH_GEN_KEY"}, +{ ERR_PACK(0, PK11_F_DH_COMP_KEY, 0), "PK11_DH_COMP_KEY"}, +{ ERR_PACK(0, PK11_F_DIGEST_COPY, 0), "PK11_DIGEST_COPY"}, +{ ERR_PACK(0, PK11_F_CIPHER_CLEANUP, 0), "PK11_CIPHER_CLEANUP"}, +{ ERR_PACK(0, PK11_F_ACTIVE_ADD, 0), "PK11_ACTIVE_ADD"}, +{ ERR_PACK(0, PK11_F_ACTIVE_DELETE, 0), "PK11_ACTIVE_DELETE"}, +{ ERR_PACK(0, PK11_F_CHECK_HW_MECHANISMS, 0), "PK11_CHECK_HW_MECHANISMS"}, +{ ERR_PACK(0, PK11_F_INIT_SYMMETRIC, 0), "PK11_INIT_SYMMETRIC"}, +{ ERR_PACK(0, PK11_F_ADD_AES_CTR_NIDS, 0), "PK11_ADD_AES_CTR_NIDS"}, +{ ERR_PACK(0, PK11_F_INIT_ALL_LOCKS, 0), "PK11_INIT_ALL_LOCKS"}, +{ ERR_PACK(0, PK11_F_RETURN_SESSION, 0), "PK11_RETURN_SESSION"}, +{ ERR_PACK(0, PK11_F_GET_PIN, 0), "PK11_GET_PIN"}, +{ ERR_PACK(0, PK11_F_FIND_ONE_OBJECT, 0), "PK11_FIND_ONE_OBJECT"}, +{ ERR_PACK(0, PK11_F_CHECK_TOKEN_ATTRS, 0), "PK11_CHECK_TOKEN_ATTRS"}, +{ ERR_PACK(0, PK11_F_CACHE_PIN, 0), "PK11_CACHE_PIN"}, +{ ERR_PACK(0, PK11_F_MLOCK_PIN_IN_MEMORY, 0), "PK11_MLOCK_PIN_IN_MEMORY"}, +{ ERR_PACK(0, PK11_F_TOKEN_LOGIN, 0), "PK11_TOKEN_LOGIN"}, +{ ERR_PACK(0, PK11_F_TOKEN_RELOGIN, 0), "PK11_TOKEN_RELOGIN"}, +{ ERR_PACK(0, PK11_F_RUN_ASKPASS, 0), "PK11_F_RUN_ASKPASS"}, +{ 0, NULL} +}; + +static ERR_STRING_DATA pk11_str_reasons[]= +{ +{ PK11_R_ALREADY_LOADED, "PKCS#11 DSO already loaded"}, +{ PK11_R_DSO_FAILURE, "unable to load PKCS#11 DSO"}, +{ PK11_R_NOT_LOADED, "PKCS#11 DSO not loaded"}, +{ PK11_R_PASSED_NULL_PARAMETER, "null parameter passed"}, +{ PK11_R_COMMAND_NOT_IMPLEMENTED, "command not implemented"}, +{ PK11_R_INITIALIZE, "C_Initialize failed"}, +{ PK11_R_FINALIZE, "C_Finalize failed"}, +{ PK11_R_GETINFO, "C_GetInfo faile"}, +{ PK11_R_GETSLOTLIST, "C_GetSlotList failed"}, +{ PK11_R_NO_MODULUS_OR_NO_EXPONENT, "no modulus or no exponent"}, +{ PK11_R_ATTRIBUT_SENSITIVE_OR_INVALID, "attr sensitive or invalid"}, +{ PK11_R_GETATTRIBUTVALUE, "C_GetAttributeValue failed"}, +{ PK11_R_NO_MODULUS, "no modulus"}, +{ PK11_R_NO_EXPONENT, "no exponent"}, +{ PK11_R_FINDOBJECTSINIT, "C_FindObjectsInit failed"}, +{ PK11_R_FINDOBJECTS, "C_FindObjects failed"}, +{ PK11_R_FINDOBJECTSFINAL, "C_FindObjectsFinal failed"}, +{ PK11_R_CREATEOBJECT, "C_CreateObject failed"}, +{ PK11_R_DESTROYOBJECT, "C_DestroyObject failed"}, +{ PK11_R_OPENSESSION, "C_OpenSession failed"}, +{ PK11_R_CLOSESESSION, "C_CloseSession failed"}, +{ PK11_R_ENCRYPTINIT, "C_EncryptInit failed"}, +{ PK11_R_ENCRYPT, "C_Encrypt failed"}, +{ PK11_R_SIGNINIT, "C_SignInit failed"}, +{ PK11_R_SIGN, "C_Sign failed"}, +{ PK11_R_DECRYPTINIT, "C_DecryptInit failed"}, +{ PK11_R_DECRYPT, "C_Decrypt failed"}, +{ PK11_R_VERIFYINIT, "C_VerifyRecover failed"}, +{ PK11_R_VERIFY, "C_Verify failed"}, +{ PK11_R_VERIFYRECOVERINIT, "C_VerifyRecoverInit failed"}, +{ PK11_R_VERIFYRECOVER, "C_VerifyRecover failed"}, +{ PK11_R_GEN_KEY, "C_GenerateKeyPair failed"}, +{ PK11_R_SEEDRANDOM, "C_SeedRandom failed"}, +{ PK11_R_GENERATERANDOM, "C_GenerateRandom failed"}, +{ PK11_R_INVALID_MESSAGE_LENGTH, "invalid message length"}, +{ PK11_R_UNKNOWN_ALGORITHM_TYPE, "unknown algorithm type"}, +{ PK11_R_UNKNOWN_ASN1_OBJECT_ID, "unknown asn1 onject id"}, +{ PK11_R_UNKNOWN_PADDING_TYPE, "unknown padding type"}, +{ PK11_R_PADDING_CHECK_FAILED, "padding check failed"}, +{ PK11_R_DIGEST_TOO_BIG, "digest too big"}, +{ PK11_R_MALLOC_FAILURE, "malloc failure"}, +{ PK11_R_CTRL_COMMAND_NOT_IMPLEMENTED, "ctl command not implemented"}, +{ PK11_R_DATA_GREATER_THAN_MOD_LEN, "data is bigger than mod"}, +{ PK11_R_DATA_TOO_LARGE_FOR_MODULUS, "data is too larger for mod"}, +{ PK11_R_MISSING_KEY_COMPONENT, "a dsa component is missing"}, +{ PK11_R_INVALID_SIGNATURE_LENGTH, "invalid signature length"}, +{ PK11_R_INVALID_DSA_SIGNATURE_R, "missing r in dsa verify"}, +{ PK11_R_INVALID_DSA_SIGNATURE_S, "missing s in dsa verify"}, +{ PK11_R_INCONSISTENT_KEY, "inconsistent key type"}, +{ PK11_R_ENCRYPTUPDATE, "C_EncryptUpdate failed"}, +{ PK11_R_DECRYPTUPDATE, "C_DecryptUpdate failed"}, +{ PK11_R_DIGESTINIT, "C_DigestInit failed"}, +{ PK11_R_DIGESTUPDATE, "C_DigestUpdate failed"}, +{ PK11_R_DIGESTFINAL, "C_DigestFinal failed"}, +{ PK11_R_ENCRYPTFINAL, "C_EncryptFinal failed"}, +{ PK11_R_DECRYPTFINAL, "C_DecryptFinal failed"}, +{ PK11_R_NO_PRNG_SUPPORT, "Slot does not support PRNG"}, +{ PK11_R_GETTOKENINFO, "C_GetTokenInfo failed"}, +{ PK11_R_DERIVEKEY, "C_DeriveKey failed"}, +{ PK11_R_GET_OPERATION_STATE, "C_GetOperationState failed"}, +{ PK11_R_SET_OPERATION_STATE, "C_SetOperationState failed"}, +{ PK11_R_INVALID_HANDLE, "invalid PKCS#11 object handle"}, +{ PK11_R_KEY_OR_IV_LEN_PROBLEM, "IV or key length incorrect"}, +{ PK11_R_INVALID_OPERATION_TYPE, "invalid operation type"}, +{ PK11_R_ADD_NID_FAILED, "failed to add NID" }, +{ PK11_R_ATFORK_FAILED, "atfork() failed" }, +{ PK11_R_TOKEN_LOGIN_FAILED, "C_Login() failed on token" }, +{ PK11_R_MORE_THAN_ONE_OBJECT_FOUND, "more than one object found" }, +{ PK11_R_INVALID_PKCS11_URI, "pkcs11 URI provided is invalid" }, +{ PK11_R_COULD_NOT_READ_PIN, "could not read PIN from terminal" }, +{ PK11_R_PIN_NOT_READ_FROM_COMMAND, "PIN not read from external command" }, +{ PK11_R_COULD_NOT_OPEN_COMMAND, "could not popen() dialog command" }, +{ PK11_R_PIPE_FAILED, "pipe() failed" }, +{ PK11_R_BAD_PASSPHRASE_SPEC, "bad passphrasedialog specification" }, +{ PK11_R_TOKEN_NOT_INITIALIZED, "token not initialized" }, +{ PK11_R_TOKEN_PIN_NOT_SET, "token PIN required but not set" }, +{ PK11_R_TOKEN_PIN_NOT_PROVIDED, "token PIN required but not provided" }, +{ PK11_R_MISSING_OBJECT_LABEL, "missing mandatory 'object' keyword" }, +{ PK11_R_TOKEN_ATTRS_DO_NOT_MATCH, "token attrs provided do not match" }, +{ PK11_R_PRIV_KEY_NOT_FOUND, "private key not found in keystore" }, +{ PK11_R_NO_OBJECT_FOUND, "specified object not found" }, +{ PK11_R_PIN_CACHING_POLICY_INVALID, "PIN set but caching policy invalid" }, +{ PK11_R_SYSCONF_FAILED, "sysconf() failed" }, +{ PK11_R_MMAP_FAILED, "mmap() failed" }, +{ PK11_R_PRIV_PROC_LOCK_MEMORY_MISSING, "PROC_LOCK_MEMORY privilege missing" }, +{ PK11_R_MLOCK_FAILED, "mlock() failed" }, +{ PK11_R_FORK_FAILED, "fork() failed" }, +{ 0, NULL} +}; +#endif /* OPENSSL_NO_ERR */ + +static int pk11_lib_error_code = 0; +static int pk11_error_init = 1; + +static void +ERR_load_pk11_strings(void) + { + if (pk11_lib_error_code == 0) + pk11_lib_error_code = ERR_get_next_error_library(); + + if (pk11_error_init) + { + pk11_error_init = 0; +#ifndef OPENSSL_NO_ERR + ERR_load_strings(pk11_lib_error_code, pk11_str_functs); + ERR_load_strings(pk11_lib_error_code, pk11_str_reasons); +#endif + } +} + +static void +ERR_unload_pk11_strings(void) + { + if (pk11_error_init == 0) + { +#ifndef OPENSSL_NO_ERR + ERR_unload_strings(pk11_lib_error_code, pk11_str_functs); + ERR_unload_strings(pk11_lib_error_code, pk11_str_reasons); +#endif + pk11_error_init = 1; + } +} + +void +ERR_pk11_error(int function, int reason, char *file, int line) +{ + if (pk11_lib_error_code == 0) + pk11_lib_error_code = ERR_get_next_error_library(); + ERR_PUT_error(pk11_lib_error_code, function, reason, file, line); +} + +void +PK11err_add_data(int function, int reason, CK_RV rv) +{ + char tmp_buf[20]; + + PK11err(function, reason); + (void) BIO_snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); + ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); +} Index: openssl/crypto/engine/hw_pk11_err.h diff -u /dev/null openssl/crypto/engine/hw_pk11_err.h:1.12.4.1 --- /dev/null Wed Dec 23 17:47:11 2015 +++ openssl/crypto/engine/hw_pk11_err.h Fri Oct 4 14:33:56 2013 @@ -0,0 +1,440 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * This product includes software developed by the OpenSSL Project for + * use in the OpenSSL Toolkit (http://www.openssl.org/). + * + * This project also referenced hw_pkcs11-0.9.7b.patch written by + * Afchine Madjlessi. + */ +/* + * ==================================================================== + * Copyright (c) 2000-2001 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#ifndef HW_PK11_ERR_H +#define HW_PK11_ERR_H + +void ERR_pk11_error(int function, int reason, char *file, int line); +void PK11err_add_data(int function, int reason, CK_RV rv); +#define PK11err(f, r) ERR_pk11_error((f), (r), __FILE__, __LINE__) + +/* Error codes for the PK11 functions. */ + +/* Function codes. */ + +#define PK11_F_INIT 100 +#define PK11_F_FINISH 101 +#define PK11_F_DESTROY 102 +#define PK11_F_CTRL 103 +#define PK11_F_RSA_INIT 104 +#define PK11_F_RSA_FINISH 105 +#define PK11_F_GET_PUB_RSA_KEY 106 +#define PK11_F_GET_PRIV_RSA_KEY 107 +#define PK11_F_RSA_GEN_KEY 108 +#define PK11_F_RSA_PUB_ENC 109 +#define PK11_F_RSA_PRIV_ENC 110 +#define PK11_F_RSA_PUB_DEC 111 +#define PK11_F_RSA_PRIV_DEC 112 +#define PK11_F_RSA_SIGN 113 +#define PK11_F_RSA_VERIFY 114 +#define PK11_F_RAND_ADD 115 +#define PK11_F_RAND_BYTES 116 +#define PK11_F_GET_SESSION 117 +#define PK11_F_FREE_SESSION 118 +#define PK11_F_LOAD_PUBKEY 119 +#define PK11_F_LOAD_PRIVKEY 120 +#define PK11_F_RSA_PUB_ENC_LOW 121 +#define PK11_F_RSA_PRIV_ENC_LOW 122 +#define PK11_F_RSA_PUB_DEC_LOW 123 +#define PK11_F_RSA_PRIV_DEC_LOW 124 +#define PK11_F_DSA_SIGN 125 +#define PK11_F_DSA_VERIFY 126 +#define PK11_F_DSA_INIT 127 +#define PK11_F_DSA_FINISH 128 +#define PK11_F_GET_PUB_DSA_KEY 129 +#define PK11_F_GET_PRIV_DSA_KEY 130 +#define PK11_F_DH_INIT 131 +#define PK11_F_DH_FINISH 132 +#define PK11_F_MOD_EXP_DH 133 +#define PK11_F_GET_DH_KEY 134 +#define PK11_F_FREE_ALL_SESSIONS 135 +#define PK11_F_SETUP_SESSION 136 +#define PK11_F_DESTROY_OBJECT 137 +#define PK11_F_CIPHER_INIT 138 +#define PK11_F_CIPHER_DO_CIPHER 139 +#define PK11_F_GET_CIPHER_KEY 140 +#define PK11_F_DIGEST_INIT 141 +#define PK11_F_DIGEST_UPDATE 142 +#define PK11_F_DIGEST_FINAL 143 +#define PK11_F_CHOOSE_SLOT 144 +#define PK11_F_CIPHER_FINAL 145 +#define PK11_F_LIBRARY_INIT 146 +#define PK11_F_LOAD 147 +#define PK11_F_DH_GEN_KEY 148 +#define PK11_F_DH_COMP_KEY 149 +#define PK11_F_DIGEST_COPY 150 +#define PK11_F_CIPHER_CLEANUP 151 +#define PK11_F_ACTIVE_ADD 152 +#define PK11_F_ACTIVE_DELETE 153 +#define PK11_F_CHECK_HW_MECHANISMS 154 +#define PK11_F_INIT_SYMMETRIC 155 +#define PK11_F_ADD_AES_CTR_NIDS 156 +#define PK11_F_INIT_ALL_LOCKS 157 +#define PK11_F_RETURN_SESSION 158 +#define PK11_F_GET_PIN 159 +#define PK11_F_FIND_ONE_OBJECT 160 +#define PK11_F_CHECK_TOKEN_ATTRS 161 +#define PK11_F_CACHE_PIN 162 +#define PK11_F_MLOCK_PIN_IN_MEMORY 163 +#define PK11_F_TOKEN_LOGIN 164 +#define PK11_F_TOKEN_RELOGIN 165 +#define PK11_F_RUN_ASKPASS 166 + +/* Reason codes. */ +#define PK11_R_ALREADY_LOADED 100 +#define PK11_R_DSO_FAILURE 101 +#define PK11_R_NOT_LOADED 102 +#define PK11_R_PASSED_NULL_PARAMETER 103 +#define PK11_R_COMMAND_NOT_IMPLEMENTED 104 +#define PK11_R_INITIALIZE 105 +#define PK11_R_FINALIZE 106 +#define PK11_R_GETINFO 107 +#define PK11_R_GETSLOTLIST 108 +#define PK11_R_NO_MODULUS_OR_NO_EXPONENT 109 +#define PK11_R_ATTRIBUT_SENSITIVE_OR_INVALID 110 +#define PK11_R_GETATTRIBUTVALUE 111 +#define PK11_R_NO_MODULUS 112 +#define PK11_R_NO_EXPONENT 113 +#define PK11_R_FINDOBJECTSINIT 114 +#define PK11_R_FINDOBJECTS 115 +#define PK11_R_FINDOBJECTSFINAL 116 +#define PK11_R_CREATEOBJECT 118 +#define PK11_R_DESTROYOBJECT 119 +#define PK11_R_OPENSESSION 120 +#define PK11_R_CLOSESESSION 121 +#define PK11_R_ENCRYPTINIT 122 +#define PK11_R_ENCRYPT 123 +#define PK11_R_SIGNINIT 124 +#define PK11_R_SIGN 125 +#define PK11_R_DECRYPTINIT 126 +#define PK11_R_DECRYPT 127 +#define PK11_R_VERIFYINIT 128 +#define PK11_R_VERIFY 129 +#define PK11_R_VERIFYRECOVERINIT 130 +#define PK11_R_VERIFYRECOVER 131 +#define PK11_R_GEN_KEY 132 +#define PK11_R_SEEDRANDOM 133 +#define PK11_R_GENERATERANDOM 134 +#define PK11_R_INVALID_MESSAGE_LENGTH 135 +#define PK11_R_UNKNOWN_ALGORITHM_TYPE 136 +#define PK11_R_UNKNOWN_ASN1_OBJECT_ID 137 +#define PK11_R_UNKNOWN_PADDING_TYPE 138 +#define PK11_R_PADDING_CHECK_FAILED 139 +#define PK11_R_DIGEST_TOO_BIG 140 +#define PK11_R_MALLOC_FAILURE 141 +#define PK11_R_CTRL_COMMAND_NOT_IMPLEMENTED 142 +#define PK11_R_DATA_GREATER_THAN_MOD_LEN 143 +#define PK11_R_DATA_TOO_LARGE_FOR_MODULUS 144 +#define PK11_R_MISSING_KEY_COMPONENT 145 +#define PK11_R_INVALID_SIGNATURE_LENGTH 146 +#define PK11_R_INVALID_DSA_SIGNATURE_R 147 +#define PK11_R_INVALID_DSA_SIGNATURE_S 148 +#define PK11_R_INCONSISTENT_KEY 149 +#define PK11_R_ENCRYPTUPDATE 150 +#define PK11_R_DECRYPTUPDATE 151 +#define PK11_R_DIGESTINIT 152 +#define PK11_R_DIGESTUPDATE 153 +#define PK11_R_DIGESTFINAL 154 +#define PK11_R_ENCRYPTFINAL 155 +#define PK11_R_DECRYPTFINAL 156 +#define PK11_R_NO_PRNG_SUPPORT 157 +#define PK11_R_GETTOKENINFO 158 +#define PK11_R_DERIVEKEY 159 +#define PK11_R_GET_OPERATION_STATE 160 +#define PK11_R_SET_OPERATION_STATE 161 +#define PK11_R_INVALID_HANDLE 162 +#define PK11_R_KEY_OR_IV_LEN_PROBLEM 163 +#define PK11_R_INVALID_OPERATION_TYPE 164 +#define PK11_R_ADD_NID_FAILED 165 +#define PK11_R_ATFORK_FAILED 166 + +#define PK11_R_TOKEN_LOGIN_FAILED 167 +#define PK11_R_MORE_THAN_ONE_OBJECT_FOUND 168 +#define PK11_R_INVALID_PKCS11_URI 169 +#define PK11_R_COULD_NOT_READ_PIN 170 +#define PK11_R_COULD_NOT_OPEN_COMMAND 171 +#define PK11_R_PIPE_FAILED 172 +#define PK11_R_PIN_NOT_READ_FROM_COMMAND 173 +#define PK11_R_BAD_PASSPHRASE_SPEC 174 +#define PK11_R_TOKEN_NOT_INITIALIZED 175 +#define PK11_R_TOKEN_PIN_NOT_SET 176 +#define PK11_R_TOKEN_PIN_NOT_PROVIDED 177 +#define PK11_R_MISSING_OBJECT_LABEL 178 +#define PK11_R_TOKEN_ATTRS_DO_NOT_MATCH 179 +#define PK11_R_PRIV_KEY_NOT_FOUND 180 +#define PK11_R_NO_OBJECT_FOUND 181 +#define PK11_R_PIN_CACHING_POLICY_INVALID 182 +#define PK11_R_SYSCONF_FAILED 183 +#define PK11_R_MMAP_FAILED 183 +#define PK11_R_PRIV_PROC_LOCK_MEMORY_MISSING 184 +#define PK11_R_MLOCK_FAILED 185 +#define PK11_R_FORK_FAILED 186 + +/* max byte length of a symetric key we support */ +#define PK11_KEY_LEN_MAX 32 + +#ifdef NOPTHREADS +/* + * CRYPTO_LOCK_PK11_ENGINE lock is primarily used for the protection of the + * free_session list and active_list but generally serves as a global + * per-process lock for the whole engine. + * + * We reuse CRYPTO_LOCK_EC lock (which is defined in OpenSSL for EC method) as + * the global engine lock. This is not optimal w.r.t. performance but + * it's safe. + */ +#define CRYPTO_LOCK_PK11_ENGINE CRYPTO_LOCK_EC +#endif + +/* + * This structure encapsulates all reusable information for a PKCS#11 + * session. A list of these objects is created on behalf of the + * calling application using an on-demand method. Each operation + * type (see PK11_OPTYPE below) has its own per-process list. + * Each of the lists is basically a cache for faster PKCS#11 object + * access to avoid expensive C_Find{,Init,Final}Object() calls. + * + * When a new request comes in, an object will be taken from the list + * (if there is one) or a new one is created to handle the request + * (if the list is empty). See pk11_get_session() on how it is done. + */ +typedef struct PK11_st_SESSION + { + struct PK11_st_SESSION *next; + CK_SESSION_HANDLE session; /* PK11 session handle */ + pid_t pid; /* Current process ID */ + CK_BBOOL pub_persistent; /* is pub key in keystore? */ + CK_BBOOL priv_persistent;/* is priv key in keystore? */ + union + { +#ifndef OPENSSL_NO_RSA + struct + { + CK_OBJECT_HANDLE rsa_pub_key; /* pub handle */ + CK_OBJECT_HANDLE rsa_priv_key; /* priv handle */ + RSA *rsa_pub; /* pub key addr */ + BIGNUM *rsa_n_num; /* pub modulus */ + BIGNUM *rsa_e_num; /* pub exponent */ + RSA *rsa_priv; /* priv key addr */ + BIGNUM *rsa_pn_num; /* pub modulus */ + BIGNUM *rsa_pe_num; /* pub exponent */ + BIGNUM *rsa_d_num; /* priv exponent */ + } u_RSA; +#endif /* OPENSSL_NO_RSA */ +#ifndef OPENSSL_NO_DSA + struct + { + CK_OBJECT_HANDLE dsa_pub_key; /* pub handle */ + CK_OBJECT_HANDLE dsa_priv_key; /* priv handle */ + DSA *dsa_pub; /* pub key addr */ + BIGNUM *dsa_pub_num; /* pub key */ + DSA *dsa_priv; /* priv key addr */ + BIGNUM *dsa_priv_num; /* priv key */ + } u_DSA; +#endif /* OPENSSL_NO_DSA */ +#ifndef OPENSSL_NO_DH + struct + { + CK_OBJECT_HANDLE dh_key; /* key handle */ + DH *dh; /* dh key addr */ + BIGNUM *dh_priv_num; /* priv dh key */ + } u_DH; +#endif /* OPENSSL_NO_DH */ + struct + { + CK_OBJECT_HANDLE cipher_key; /* key handle */ + unsigned char key[PK11_KEY_LEN_MAX]; + int key_len; /* priv key len */ + int encrypt; /* 1/0 enc/decr */ + } u_cipher; + } opdata_u; + } PK11_SESSION; + +#define opdata_rsa_pub_key opdata_u.u_RSA.rsa_pub_key +#define opdata_rsa_priv_key opdata_u.u_RSA.rsa_priv_key +#define opdata_rsa_pub opdata_u.u_RSA.rsa_pub +#define opdata_rsa_priv opdata_u.u_RSA.rsa_priv +#define opdata_rsa_n_num opdata_u.u_RSA.rsa_n_num +#define opdata_rsa_e_num opdata_u.u_RSA.rsa_e_num +#define opdata_rsa_pn_num opdata_u.u_RSA.rsa_pn_num +#define opdata_rsa_pe_num opdata_u.u_RSA.rsa_pe_num +#define opdata_rsa_d_num opdata_u.u_RSA.rsa_d_num +#define opdata_dsa_pub_key opdata_u.u_DSA.dsa_pub_key +#define opdata_dsa_priv_key opdata_u.u_DSA.dsa_priv_key +#define opdata_dsa_pub opdata_u.u_DSA.dsa_pub +#define opdata_dsa_pub_num opdata_u.u_DSA.dsa_pub_num +#define opdata_dsa_priv opdata_u.u_DSA.dsa_priv +#define opdata_dsa_priv_num opdata_u.u_DSA.dsa_priv_num +#define opdata_dh_key opdata_u.u_DH.dh_key +#define opdata_dh opdata_u.u_DH.dh +#define opdata_dh_priv_num opdata_u.u_DH.dh_priv_num +#define opdata_cipher_key opdata_u.u_cipher.cipher_key +#define opdata_key opdata_u.u_cipher.key +#define opdata_key_len opdata_u.u_cipher.key_len +#define opdata_encrypt opdata_u.u_cipher.encrypt + +/* + * We have 3 different groups of operation types: + * 1) asymmetric operations + * 2) random operations + * 3) symmetric and digest operations + * + * This division into groups stems from the fact that it's common that hardware + * providers may support operations from one group only. For example, hardware + * providers on UltraSPARC T2, n2rng(7d), ncp(7d), and n2cp(7d), each support + * only a single group of operations. + * + * For every group a different slot can be chosen. That means that we must have + * at least 3 different lists of cached PKCS#11 sessions since sessions from + * different groups may be initialized in different slots. + * + * To provide locking granularity in multithreaded environment, the groups are + * further splitted into types with each type having a separate session cache. + */ +typedef enum PK11_OPTYPE_ENUM + { + OP_RAND, + OP_RSA, + OP_DSA, + OP_DH, + OP_CIPHER, + OP_DIGEST, + OP_MAX + } PK11_OPTYPE; + +/* + * This structure contains the heads of the lists forming the object caches + * and locks associated with the lists. + */ +typedef struct PK11_st_CACHE + { + PK11_SESSION *head; +#ifndef NOPTHREADS + pthread_mutex_t *lock; +#endif + } PK11_CACHE; + +/* structure for tracking handles of asymmetric key objects */ +typedef struct PK11_active_st + { + CK_OBJECT_HANDLE h; + unsigned int refcnt; + struct PK11_active_st *prev; + struct PK11_active_st *next; + } PK11_active; + +#ifndef NOPTHREADS +extern pthread_mutex_t *find_lock[]; +#endif +extern PK11_active *active_list[]; +/* + * These variables are specific for the RSA keys by reference code. See + * hw_pk11_pub.c for explanation. + */ +extern CK_FLAGS pubkey_token_flags; + +#ifndef NOPTHREADS +#define LOCK_OBJSTORE(alg_type) \ + OPENSSL_assert(pthread_mutex_lock(find_lock[alg_type]) == 0) +#define UNLOCK_OBJSTORE(alg_type) \ + OPENSSL_assert(pthread_mutex_unlock(find_lock[alg_type]) == 0) +#else +#define LOCK_OBJSTORE(alg_type) \ + CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE) +#define UNLOCK_OBJSTORE(alg_type) \ + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE) +#endif + +extern PK11_SESSION *pk11_get_session(PK11_OPTYPE optype); +extern void pk11_return_session(PK11_SESSION *sp, PK11_OPTYPE optype); +extern int pk11_token_relogin(CK_SESSION_HANDLE session); + +#ifndef OPENSSL_NO_RSA +extern int pk11_destroy_rsa_key_objects(PK11_SESSION *session); +extern int pk11_destroy_rsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock); +extern int pk11_destroy_rsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock); +extern EVP_PKEY *pk11_load_privkey(ENGINE *e, const char *pubkey_file, + UI_METHOD *ui_method, void *callback_data); +extern EVP_PKEY *pk11_load_pubkey(ENGINE *e, const char *pubkey_file, + UI_METHOD *ui_method, void *callback_data); +extern RSA_METHOD *PK11_RSA(void); +#endif /* OPENSSL_NO_RSA */ +#ifndef OPENSSL_NO_DSA +extern int pk11_destroy_dsa_key_objects(PK11_SESSION *session); +extern int pk11_destroy_dsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock); +extern int pk11_destroy_dsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock); +extern DSA_METHOD *PK11_DSA(void); +#endif /* OPENSSL_NO_DSA */ +#ifndef OPENSSL_NO_DH +extern int pk11_destroy_dh_key_objects(PK11_SESSION *session); +extern int pk11_destroy_dh_object(PK11_SESSION *sp, CK_BBOOL uselock); +extern DH_METHOD *PK11_DH(void); +#endif /* OPENSSL_NO_DH */ + +extern CK_FUNCTION_LIST_PTR pFuncList; + +#endif /* HW_PK11_ERR_H */ Index: openssl/crypto/engine/hw_pk11_pub.c diff -u /dev/null openssl/crypto/engine/hw_pk11_pub.c:1.38.2.3 --- /dev/null Wed Dec 23 17:47:11 2015 +++ openssl/crypto/engine/hw_pk11_pub.c Fri Oct 4 14:33:56 2013 @@ -0,0 +1,3556 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* crypto/engine/hw_pk11_pub.c */ +/* + * This product includes software developed by the OpenSSL Project for + * use in the OpenSSL Toolkit (http://www.openssl.org/). + * + * This project also referenced hw_pkcs11-0.9.7b.patch written by + * Afchine Madjlessi. + */ +/* + * ==================================================================== + * Copyright (c) 2000-2001 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#ifndef OPENSSL_NO_RSA +#include +#endif /* OPENSSL_NO_RSA */ +#ifndef OPENSSL_NO_DSA +#include +#endif /* OPENSSL_NO_DSA */ +#ifndef OPENSSL_NO_DH +#include +#endif /* OPENSSL_NO_DH */ +#include +#include +#include + +#ifdef OPENSSL_SYS_WIN32 +#define NOPTHREADS +typedef int pid_t; +#define HAVE_GETPASSPHRASE +static char *getpassphrase(const char *prompt); +#ifndef NULL_PTR +#define NULL_PTR NULL +#endif +#define CK_DEFINE_FUNCTION(returnType, name) \ + returnType __declspec(dllexport) name +#define CK_DECLARE_FUNCTION(returnType, name) \ + returnType __declspec(dllimport) name +#define CK_DECLARE_FUNCTION_POINTER(returnType, name) \ + returnType __declspec(dllimport) (* name) +#else +#include +#endif + +#ifndef NOPTHREADS +#include +#endif + +#ifndef OPENSSL_NO_HW +#ifndef OPENSSL_NO_HW_PK11 +#ifndef OPENSSL_NO_HW_PK11CA + +#ifdef OPENSSL_SYS_WIN32 +#pragma pack(push, cryptoki, 1) +#include "cryptoki.h" +#include "pkcs11.h" +#pragma pack(pop, cryptoki) +#else +#include "cryptoki.h" +#include "pkcs11.h" +#endif +#include "hw_pk11ca.h" +#include "hw_pk11_err.h" + +static CK_BBOOL pk11_login_done = CK_FALSE; +extern CK_SLOT_ID pubkey_SLOTID; +#ifndef NOPTHREADS +extern pthread_mutex_t *token_lock; +#endif + +#if !(defined(HAVE_GETPASSPHRASE) || (defined (__SVR4) && defined (__sun))) +#define getpassphrase(x) getpass(x) +#endif + +#ifndef OPENSSL_NO_RSA +/* RSA stuff */ +static int pk11_RSA_public_encrypt(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding); +static int pk11_RSA_private_encrypt(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding); +static int pk11_RSA_public_decrypt(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding); +static int pk11_RSA_private_decrypt(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding); +static int pk11_RSA_init(RSA *rsa); +static int pk11_RSA_finish(RSA *rsa); +static int pk11_RSA_sign(int type, const unsigned char *m, unsigned int m_len, + unsigned char *sigret, unsigned int *siglen, const RSA *rsa); +#if OPENSSL_VERSION_NUMBER < 0x10000000L +static int pk11_RSA_verify(int dtype, const unsigned char *m, + unsigned int m_len, unsigned char *sigbuf, unsigned int siglen, + const RSA *rsa); +#else +static int pk11_RSA_verify(int dtype, const unsigned char *m, + unsigned int m_len, const unsigned char *sigbuf, unsigned int siglen, + const RSA *rsa); +#endif +EVP_PKEY *pk11_load_privkey(ENGINE*, const char *privkey_file, + UI_METHOD *ui_method, void *callback_data); +EVP_PKEY *pk11_load_pubkey(ENGINE*, const char *pubkey_file, + UI_METHOD *ui_method, void *callback_data); + +static int pk11_RSA_public_encrypt_low(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa); +static int pk11_RSA_private_encrypt_low(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa); +static int pk11_RSA_public_decrypt_low(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa); +static int pk11_RSA_private_decrypt_low(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa); + +static CK_OBJECT_HANDLE pk11_get_public_rsa_key(RSA* rsa, RSA** key_ptr, + BIGNUM **rsa_n_num, BIGNUM **rsa_e_num, CK_SESSION_HANDLE session); +static CK_OBJECT_HANDLE pk11_get_private_rsa_key(RSA* rsa, RSA** key_ptr, + BIGNUM **rsa_d_num, BIGNUM **rsa_n_num, BIGNUM **rsa_e_num, + CK_SESSION_HANDLE session); + +static int check_new_rsa_key_pub(PK11_SESSION *sp, const RSA *rsa); +static int check_new_rsa_key_priv(PK11_SESSION *sp, const RSA *rsa); +#endif + +/* DSA stuff */ +#ifndef OPENSSL_NO_DSA +static int pk11_DSA_init(DSA *dsa); +static int pk11_DSA_finish(DSA *dsa); +static DSA_SIG *pk11_dsa_do_sign(const unsigned char *dgst, int dlen, + DSA *dsa); +static int pk11_dsa_do_verify(const unsigned char *dgst, int dgst_len, + DSA_SIG *sig, DSA *dsa); + +static CK_OBJECT_HANDLE pk11_get_public_dsa_key(DSA* dsa, DSA **key_ptr, + BIGNUM **dsa_pub_num, CK_SESSION_HANDLE session); +static CK_OBJECT_HANDLE pk11_get_private_dsa_key(DSA* dsa, DSA **key_ptr, + BIGNUM **dsa_priv_num, CK_SESSION_HANDLE session); + +static int check_new_dsa_key_pub(PK11_SESSION *sp, DSA *dsa); +static int check_new_dsa_key_priv(PK11_SESSION *sp, DSA *dsa); +#endif + +/* DH stuff */ +#ifndef OPENSSL_NO_DH +static int pk11_DH_init(DH *dh); +static int pk11_DH_finish(DH *dh); +static int pk11_DH_generate_key(DH *dh); +static int pk11_DH_compute_key(unsigned char *key, + const BIGNUM *pub_key, DH *dh); + +static CK_OBJECT_HANDLE pk11_get_dh_key(DH* dh, DH **key_ptr, + BIGNUM **priv_key, CK_SESSION_HANDLE session); + +static int check_new_dh_key(PK11_SESSION *sp, DH *dh); +#endif + +static int find_one_object(PK11_OPTYPE op, CK_SESSION_HANDLE s, + CK_ATTRIBUTE_PTR ptempl, CK_ULONG nattr, CK_OBJECT_HANDLE_PTR pkey); +static int init_template_value(BIGNUM *bn, CK_VOID_PTR *pValue, + CK_ULONG *ulValueLen); +static void attr_to_BN(CK_ATTRIBUTE_PTR attr, CK_BYTE attr_data[], BIGNUM **bn); + +static int pk11_token_login(CK_SESSION_HANDLE session, CK_BBOOL *login_done, + CK_BBOOL is_private); + +/* Read mode string to be used for fopen() */ +#if SOLARIS_OPENSSL +static char *read_mode_flags = "rF"; +#else +static char *read_mode_flags = "r"; +#endif + +/* + * increment/create reference for an asymmetric key handle via active list + * manipulation. If active list operation fails, unlock (if locked), set error + * variable and jump to the specified label. + */ +#define KEY_HANDLE_REFHOLD(key_handle, alg_type, unlock, var, label) \ + { \ + if (pk11_active_add(key_handle, alg_type) < 0) \ + { \ + var = TRUE; \ + if (unlock) \ + UNLOCK_OBJSTORE(alg_type); \ + goto label; \ + } \ + } + +/* + * Find active list entry according to object handle and return pointer to the + * entry otherwise return NULL. + * + * This function presumes it is called with lock protecting the active list + * held. + */ +static PK11_active *pk11_active_find(CK_OBJECT_HANDLE h, PK11_OPTYPE type) + { + PK11_active *entry; + + for (entry = active_list[type]; entry != NULL; entry = entry->next) + if (entry->h == h) + return (entry); + + return (NULL); + } + +/* + * Search for an entry in the active list using PKCS#11 object handle as a + * search key and return refcnt of the found/created entry or -1 in case of + * failure. + * + * This function presumes it is called with lock protecting the active list + * held. + */ +int +pk11_active_add(CK_OBJECT_HANDLE h, PK11_OPTYPE type) + { + PK11_active *entry = NULL; + + if (h == CK_INVALID_HANDLE) + { + PK11err(PK11_F_ACTIVE_ADD, PK11_R_INVALID_HANDLE); + return (-1); + } + + /* search for entry in the active list */ + if ((entry = pk11_active_find(h, type)) != NULL) + entry->refcnt++; + else + { + /* not found, create new entry and add it to the list */ + entry = OPENSSL_malloc(sizeof (PK11_active)); + if (entry == NULL) + { + PK11err(PK11_F_ACTIVE_ADD, PK11_R_MALLOC_FAILURE); + return (-1); + } + entry->h = h; + entry->refcnt = 1; + entry->prev = NULL; + entry->next = NULL; + /* connect the newly created entry to the list */ + if (active_list[type] == NULL) + active_list[type] = entry; + else /* make the entry first in the list */ + { + entry->next = active_list[type]; + active_list[type]->prev = entry; + active_list[type] = entry; + } + } + + return (entry->refcnt); + } + +/* + * Remove active list entry from the list and free it. + * + * This function presumes it is called with lock protecting the active list + * held. + */ +void +pk11_active_remove(PK11_active *entry, PK11_OPTYPE type) + { + PK11_active *prev_entry; + + /* remove the entry from the list and free it */ + if ((prev_entry = entry->prev) != NULL) + { + prev_entry->next = entry->next; + if (entry->next != NULL) + entry->next->prev = prev_entry; + } + else + { + active_list[type] = entry->next; + /* we were the first but not the only one */ + if (entry->next != NULL) + entry->next->prev = NULL; + } + + /* sanitization */ + entry->h = CK_INVALID_HANDLE; + entry->prev = NULL; + entry->next = NULL; + OPENSSL_free(entry); + } + +/* Free all entries from the active list. */ +void +pk11_free_active_list(PK11_OPTYPE type) + { + PK11_active *entry; + + /* only for asymmetric types since only they have C_Find* locks. */ + switch (type) + { + case OP_RSA: + case OP_DSA: + case OP_DH: + break; + default: + return; + } + + /* see find_lock array definition for more info on object locking */ + LOCK_OBJSTORE(type); + while ((entry = active_list[type]) != NULL) + pk11_active_remove(entry, type); + UNLOCK_OBJSTORE(type); + } + +/* + * Search for active list entry associated with given PKCS#11 object handle, + * decrement its refcnt and if it drops to 0, disconnect the entry and free it. + * + * Return 1 if the PKCS#11 object associated with the entry has no references, + * return 0 if there is at least one reference, -1 on error. + * + * This function presumes it is called with lock protecting the active list + * held. + */ +int +pk11_active_delete(CK_OBJECT_HANDLE h, PK11_OPTYPE type) + { + PK11_active *entry = NULL; + + if ((entry = pk11_active_find(h, type)) == NULL) + { + PK11err(PK11_F_ACTIVE_DELETE, PK11_R_INVALID_HANDLE); + return (-1); + } + + OPENSSL_assert(entry->refcnt > 0); + entry->refcnt--; + if (entry->refcnt == 0) + { + pk11_active_remove(entry, type); + return (1); + } + + return (0); + } + +#ifndef OPENSSL_NO_RSA +/* Our internal RSA_METHOD that we provide pointers to */ +static RSA_METHOD pk11_rsa = + { + "PKCS#11 RSA method", + pk11_RSA_public_encrypt, /* rsa_pub_encrypt */ + pk11_RSA_public_decrypt, /* rsa_pub_decrypt */ + pk11_RSA_private_encrypt, /* rsa_priv_encrypt */ + pk11_RSA_private_decrypt, /* rsa_priv_decrypt */ + NULL, /* rsa_mod_exp */ + NULL, /* bn_mod_exp */ + pk11_RSA_init, /* init */ + pk11_RSA_finish, /* finish */ + RSA_FLAG_SIGN_VER, /* flags */ + NULL, /* app_data */ + pk11_RSA_sign, /* rsa_sign */ + pk11_RSA_verify /* rsa_verify */ + }; + +RSA_METHOD * +PK11_RSA(void) + { + return (&pk11_rsa); + } +#endif + +#ifndef OPENSSL_NO_DSA +/* Our internal DSA_METHOD that we provide pointers to */ +static DSA_METHOD pk11_dsa = + { + "PKCS#11 DSA method", + pk11_dsa_do_sign, /* dsa_do_sign */ + NULL, /* dsa_sign_setup */ + pk11_dsa_do_verify, /* dsa_do_verify */ + NULL, /* dsa_mod_exp */ + NULL, /* bn_mod_exp */ + pk11_DSA_init, /* init */ + pk11_DSA_finish, /* finish */ + 0, /* flags */ + NULL /* app_data */ + }; + +DSA_METHOD * +PK11_DSA(void) + { + return (&pk11_dsa); + } +#endif + +#ifndef OPENSSL_NO_DH +/* + * PKCS #11 V2.20, section 11.2 specifies that the number of bytes needed for + * output buffer may somewhat exceed the precise number of bytes needed, but + * should not exceed it by a large amount. That may be caused, for example, by + * rounding it up to multiple of X in the underlying bignum library. 8 should be + * enough. + */ +#define DH_BUF_RESERVE 8 + +/* Our internal DH_METHOD that we provide pointers to */ +static DH_METHOD pk11_dh = + { + "PKCS#11 DH method", + pk11_DH_generate_key, /* generate_key */ + pk11_DH_compute_key, /* compute_key */ + NULL, /* bn_mod_exp */ + pk11_DH_init, /* init */ + pk11_DH_finish, /* finish */ + 0, /* flags */ + NULL, /* app_data */ + NULL /* generate_params */ + }; + +DH_METHOD * +PK11_DH(void) + { + return (&pk11_dh); + } +#endif + +/* Size of an SSL signature: MD5+SHA1 */ +#define SSL_SIG_LENGTH 36 + +/* Lengths of DSA data and signature */ +#define DSA_DATA_LEN 20 +#define DSA_SIGNATURE_LEN 40 + +static CK_BBOOL mytrue = TRUE; +static CK_BBOOL myfalse = FALSE; + +#ifndef OPENSSL_NO_RSA +/* + * Similiar to OpenSSL to take advantage of the paddings. The goal is to + * support all paddings in this engine although PK11 library does not + * support all the paddings used in OpenSSL. + * The input errors should have been checked in the padding functions. + */ +static int pk11_RSA_public_encrypt(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding) + { + int i, num = 0, r = -1; + unsigned char *buf = NULL; + + num = BN_num_bytes(rsa->n); + if ((buf = (unsigned char *)OPENSSL_malloc(num)) == NULL) + { + RSAerr(PK11_F_RSA_PUB_ENC, PK11_R_MALLOC_FAILURE); + goto err; + } + + switch (padding) + { + case RSA_PKCS1_PADDING: + i = RSA_padding_add_PKCS1_type_2(buf, num, from, flen); + break; +#ifndef OPENSSL_NO_SHA + case RSA_PKCS1_OAEP_PADDING: + i = RSA_padding_add_PKCS1_OAEP(buf, num, from, flen, NULL, 0); + break; +#endif + case RSA_SSLV23_PADDING: + i = RSA_padding_add_SSLv23(buf, num, from, flen); + break; + case RSA_NO_PADDING: + i = RSA_padding_add_none(buf, num, from, flen); + break; + default: + RSAerr(PK11_F_RSA_PUB_ENC, PK11_R_UNKNOWN_PADDING_TYPE); + goto err; + } + if (i <= 0) goto err; + + /* PK11 functions are called here */ + r = pk11_RSA_public_encrypt_low(num, buf, to, rsa); +err: + if (buf != NULL) + { + OPENSSL_cleanse(buf, num); + OPENSSL_free(buf); + } + return (r); + } + + +/* + * Similar to Openssl to take advantage of the paddings. The input errors + * should be catched in the padding functions + */ +static int pk11_RSA_private_encrypt(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding) + { + int i, num = 0, r = -1; + unsigned char *buf = NULL; + + num = BN_num_bytes(rsa->n); + if ((buf = (unsigned char *)OPENSSL_malloc(num)) == NULL) + { + RSAerr(PK11_F_RSA_PRIV_ENC, PK11_R_MALLOC_FAILURE); + goto err; + } + + switch (padding) + { + case RSA_PKCS1_PADDING: + i = RSA_padding_add_PKCS1_type_1(buf, num, from, flen); + break; + case RSA_NO_PADDING: + i = RSA_padding_add_none(buf, num, from, flen); + break; + case RSA_SSLV23_PADDING: + default: + RSAerr(PK11_F_RSA_PRIV_ENC, PK11_R_UNKNOWN_PADDING_TYPE); + goto err; + } + if (i <= 0) goto err; + + /* PK11 functions are called here */ + r = pk11_RSA_private_encrypt_low(num, buf, to, rsa); +err: + if (buf != NULL) + { + OPENSSL_cleanse(buf, num); + OPENSSL_free(buf); + } + return (r); + } + +/* Similar to OpenSSL code. Input errors are also checked here */ +static int pk11_RSA_private_decrypt(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding) + { + BIGNUM f; + int j, num = 0, r = -1; + unsigned char *p; + unsigned char *buf = NULL; + + BN_init(&f); + + num = BN_num_bytes(rsa->n); + + if ((buf = (unsigned char *)OPENSSL_malloc(num)) == NULL) + { + RSAerr(PK11_F_RSA_PRIV_DEC, PK11_R_MALLOC_FAILURE); + goto err; + } + + /* + * This check was for equality but PGP does evil things + * and chops off the top '0' bytes + */ + if (flen > num) + { + RSAerr(PK11_F_RSA_PRIV_DEC, + PK11_R_DATA_GREATER_THAN_MOD_LEN); + goto err; + } + + /* make data into a big number */ + if (BN_bin2bn(from, (int)flen, &f) == NULL) + goto err; + + if (BN_ucmp(&f, rsa->n) >= 0) + { + RSAerr(PK11_F_RSA_PRIV_DEC, + PK11_R_DATA_TOO_LARGE_FOR_MODULUS); + goto err; + } + + /* PK11 functions are called here */ + r = pk11_RSA_private_decrypt_low(flen, from, buf, rsa); + + /* + * PK11 CKM_RSA_X_509 mechanism pads 0's at the beginning. + * Needs to skip these 0's paddings here. + */ + for (j = 0; j < r; j++) + if (buf[j] != 0) + break; + + p = buf + j; + j = r - j; /* j is only used with no-padding mode */ + + switch (padding) + { + case RSA_PKCS1_PADDING: + r = RSA_padding_check_PKCS1_type_2(to, num, p, j, num); + break; +#ifndef OPENSSL_NO_SHA + case RSA_PKCS1_OAEP_PADDING: + r = RSA_padding_check_PKCS1_OAEP(to, num, p, j, num, NULL, 0); + break; +#endif + case RSA_SSLV23_PADDING: + r = RSA_padding_check_SSLv23(to, num, p, j, num); + break; + case RSA_NO_PADDING: + r = RSA_padding_check_none(to, num, p, j, num); + break; + default: + RSAerr(PK11_F_RSA_PRIV_DEC, PK11_R_UNKNOWN_PADDING_TYPE); + goto err; + } + if (r < 0) + RSAerr(PK11_F_RSA_PRIV_DEC, PK11_R_PADDING_CHECK_FAILED); + +err: + BN_clear_free(&f); + if (buf != NULL) + { + OPENSSL_cleanse(buf, num); + OPENSSL_free(buf); + } + return (r); + } + +/* Similar to OpenSSL code. Input errors are also checked here */ +static int pk11_RSA_public_decrypt(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding) + { + BIGNUM f; + int i, num = 0, r = -1; + unsigned char *p; + unsigned char *buf = NULL; + + BN_init(&f); + num = BN_num_bytes(rsa->n); + buf = (unsigned char *)OPENSSL_malloc(num); + if (buf == NULL) + { + RSAerr(PK11_F_RSA_PUB_DEC, PK11_R_MALLOC_FAILURE); + goto err; + } + + /* + * This check was for equality but PGP does evil things + * and chops off the top '0' bytes + */ + if (flen > num) + { + RSAerr(PK11_F_RSA_PUB_DEC, PK11_R_DATA_GREATER_THAN_MOD_LEN); + goto err; + } + + if (BN_bin2bn(from, flen, &f) == NULL) + goto err; + + if (BN_ucmp(&f, rsa->n) >= 0) + { + RSAerr(PK11_F_RSA_PUB_DEC, + PK11_R_DATA_TOO_LARGE_FOR_MODULUS); + goto err; + } + + /* PK11 functions are called here */ + r = pk11_RSA_public_decrypt_low(flen, from, buf, rsa); + + /* + * PK11 CKM_RSA_X_509 mechanism pads 0's at the beginning. + * Needs to skip these 0's here + */ + for (i = 0; i < r; i++) + if (buf[i] != 0) + break; + + p = buf + i; + i = r - i; /* i is only used with no-padding mode */ + + switch (padding) + { + case RSA_PKCS1_PADDING: + r = RSA_padding_check_PKCS1_type_1(to, num, p, i, num); + break; + case RSA_NO_PADDING: + r = RSA_padding_check_none(to, num, p, i, num); + break; + default: + RSAerr(PK11_F_RSA_PUB_DEC, PK11_R_UNKNOWN_PADDING_TYPE); + goto err; + } + if (r < 0) + RSAerr(PK11_F_RSA_PUB_DEC, PK11_R_PADDING_CHECK_FAILED); + +err: + BN_clear_free(&f); + if (buf != NULL) + { + OPENSSL_cleanse(buf, num); + OPENSSL_free(buf); + } + return (r); + } + +/* + * This function implements RSA public encryption using C_EncryptInit and + * C_Encrypt pk11 interfaces. Note that the CKM_RSA_X_509 is used here. + * The calling function allocated sufficient memory in "to" to store results. + */ +static int pk11_RSA_public_encrypt_low(int flen, + const unsigned char *from, unsigned char *to, RSA *rsa) + { + CK_ULONG bytes_encrypted = flen; + int retval = -1; + CK_RV rv; + CK_MECHANISM mech_rsa = {CKM_RSA_X_509, NULL, 0}; + CK_MECHANISM *p_mech = &mech_rsa; + CK_OBJECT_HANDLE h_pub_key = CK_INVALID_HANDLE; + PK11_SESSION *sp; + + if ((sp = pk11_get_session(OP_RSA)) == NULL) + return (-1); + + (void) check_new_rsa_key_pub(sp, rsa); + + h_pub_key = sp->opdata_rsa_pub_key; + if (h_pub_key == CK_INVALID_HANDLE) + h_pub_key = sp->opdata_rsa_pub_key = + pk11_get_public_rsa_key(rsa, &sp->opdata_rsa_pub, + &sp->opdata_rsa_n_num, &sp->opdata_rsa_e_num, + sp->session); + + if (h_pub_key != CK_INVALID_HANDLE) + { + rv = pFuncList->C_EncryptInit(sp->session, p_mech, + h_pub_key); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_RSA_PUB_ENC_LOW, + PK11_R_ENCRYPTINIT, rv); + pk11_return_session(sp, OP_RSA); + return (-1); + } + + rv = pFuncList->C_Encrypt(sp->session, + (unsigned char *)from, flen, to, &bytes_encrypted); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_RSA_PUB_ENC_LOW, + PK11_R_ENCRYPT, rv); + pk11_return_session(sp, OP_RSA); + return (-1); + } + retval = bytes_encrypted; + } + + pk11_return_session(sp, OP_RSA); + return (retval); + } + + +/* + * This function implements RSA private encryption using C_SignInit and + * C_Sign pk11 APIs. Note that CKM_RSA_X_509 is used here. + * The calling function allocated sufficient memory in "to" to store results. + */ +static int pk11_RSA_private_encrypt_low(int flen, + const unsigned char *from, unsigned char *to, RSA *rsa) + { + CK_ULONG ul_sig_len = flen; + int retval = -1; + CK_RV rv; + CK_MECHANISM mech_rsa = {CKM_RSA_X_509, NULL, 0}; + CK_MECHANISM *p_mech = &mech_rsa; + CK_OBJECT_HANDLE h_priv_key = CK_INVALID_HANDLE; + PK11_SESSION *sp; + + if ((sp = pk11_get_session(OP_RSA)) == NULL) + return (-1); + + (void) check_new_rsa_key_priv(sp, rsa); + + h_priv_key = sp->opdata_rsa_priv_key; + if (h_priv_key == CK_INVALID_HANDLE) + { + h_priv_key = sp->opdata_rsa_priv_key = + pk11_get_private_rsa_key(rsa, &sp->opdata_rsa_priv, + &sp->opdata_rsa_d_num, &sp->opdata_rsa_pn_num, + &sp->opdata_rsa_pe_num, sp->session); + } + + if (h_priv_key != CK_INVALID_HANDLE) + { + rv = pFuncList->C_SignInit(sp->session, p_mech, + h_priv_key); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_RSA_PRIV_ENC_LOW, + PK11_R_SIGNINIT, rv); + pk11_return_session(sp, OP_RSA); + return (-1); + } + + rv = pFuncList->C_Sign(sp->session, + (unsigned char *)from, flen, to, &ul_sig_len); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_RSA_PRIV_ENC_LOW, PK11_R_SIGN, + rv); + pk11_return_session(sp, OP_RSA); + return (-1); + } + + retval = ul_sig_len; + } + + pk11_return_session(sp, OP_RSA); + return (retval); + } + + +/* + * This function implements RSA private decryption using C_DecryptInit and + * C_Decrypt pk11 APIs. Note that CKM_RSA_X_509 mechanism is used here. + * The calling function allocated sufficient memory in "to" to store results. + */ +static int pk11_RSA_private_decrypt_low(int flen, + const unsigned char *from, unsigned char *to, RSA *rsa) + { + CK_ULONG bytes_decrypted = flen; + int retval = -1; + CK_RV rv; + CK_MECHANISM mech_rsa = {CKM_RSA_X_509, NULL, 0}; + CK_MECHANISM *p_mech = &mech_rsa; + CK_OBJECT_HANDLE h_priv_key; + PK11_SESSION *sp; + + if ((sp = pk11_get_session(OP_RSA)) == NULL) + return (-1); + + (void) check_new_rsa_key_priv(sp, rsa); + + h_priv_key = sp->opdata_rsa_priv_key; + if (h_priv_key == CK_INVALID_HANDLE) + h_priv_key = sp->opdata_rsa_priv_key = + pk11_get_private_rsa_key(rsa, &sp->opdata_rsa_priv, + &sp->opdata_rsa_d_num, &sp->opdata_rsa_pn_num, + &sp->opdata_rsa_pe_num, sp->session); + + if (h_priv_key != CK_INVALID_HANDLE) + { + rv = pFuncList->C_DecryptInit(sp->session, p_mech, + h_priv_key); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_RSA_PRIV_DEC_LOW, + PK11_R_DECRYPTINIT, rv); + pk11_return_session(sp, OP_RSA); + return (-1); + } + + rv = pFuncList->C_Decrypt(sp->session, + (unsigned char *)from, flen, to, &bytes_decrypted); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_RSA_PRIV_DEC_LOW, + PK11_R_DECRYPT, rv); + pk11_return_session(sp, OP_RSA); + return (-1); + } + retval = bytes_decrypted; + } + + pk11_return_session(sp, OP_RSA); + return (retval); + } + + +/* + * This function implements RSA public decryption using C_VerifyRecoverInit + * and C_VerifyRecover pk11 APIs. Note that CKM_RSA_X_509 is used here. + * The calling function allocated sufficient memory in "to" to store results. + */ +static int pk11_RSA_public_decrypt_low(int flen, + const unsigned char *from, unsigned char *to, RSA *rsa) + { + CK_ULONG bytes_decrypted = flen; + int retval = -1; + CK_RV rv; + CK_MECHANISM mech_rsa = {CKM_RSA_X_509, NULL, 0}; + CK_MECHANISM *p_mech = &mech_rsa; + CK_OBJECT_HANDLE h_pub_key = CK_INVALID_HANDLE; + PK11_SESSION *sp; + + if ((sp = pk11_get_session(OP_RSA)) == NULL) + return (-1); + + (void) check_new_rsa_key_pub(sp, rsa); + + h_pub_key = sp->opdata_rsa_pub_key; + if (h_pub_key == CK_INVALID_HANDLE) + h_pub_key = sp->opdata_rsa_pub_key = + pk11_get_public_rsa_key(rsa, &sp->opdata_rsa_pub, + &sp->opdata_rsa_n_num, &sp->opdata_rsa_e_num, + sp->session); + + if (h_pub_key != CK_INVALID_HANDLE) + { + rv = pFuncList->C_VerifyRecoverInit(sp->session, + p_mech, h_pub_key); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_RSA_PUB_DEC_LOW, + PK11_R_VERIFYRECOVERINIT, rv); + pk11_return_session(sp, OP_RSA); + return (-1); + } + + rv = pFuncList->C_VerifyRecover(sp->session, + (unsigned char *)from, flen, to, &bytes_decrypted); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_RSA_PUB_DEC_LOW, + PK11_R_VERIFYRECOVER, rv); + pk11_return_session(sp, OP_RSA); + return (-1); + } + retval = bytes_decrypted; + } + + pk11_return_session(sp, OP_RSA); + return (retval); + } + +static int pk11_RSA_init(RSA *rsa) + { + /* + * This flag in the RSA_METHOD enables the new rsa_sign, + * rsa_verify functions. See rsa.h for details. + */ + rsa->flags |= RSA_FLAG_SIGN_VER; + + return (1); + } + +static int pk11_RSA_finish(RSA *rsa) + { + /* + * Since we are overloading OpenSSL's native RSA_eay_finish() we need + * to do the same as in the original function, i.e. to free bignum + * structures. + */ + if (rsa->_method_mod_n != NULL) + BN_MONT_CTX_free(rsa->_method_mod_n); + if (rsa->_method_mod_p != NULL) + BN_MONT_CTX_free(rsa->_method_mod_p); + if (rsa->_method_mod_q != NULL) + BN_MONT_CTX_free(rsa->_method_mod_q); + + return (1); + } + +/* + * Standard engine interface function. Majority codes here are from + * rsa/rsa_sign.c. We replaced the decrypt function call by C_Sign of PKCS#11. + * See more details in rsa/rsa_sign.c + */ +static int pk11_RSA_sign(int type, const unsigned char *m, unsigned int m_len, + unsigned char *sigret, unsigned int *siglen, const RSA *rsa) + { + X509_SIG sig; + ASN1_TYPE parameter; + int i, j = 0; + unsigned char *p, *s = NULL; + X509_ALGOR algor; + ASN1_OCTET_STRING digest; + CK_RV rv; + CK_MECHANISM mech_rsa = {CKM_RSA_PKCS, NULL, 0}; + CK_MECHANISM *p_mech = &mech_rsa; + CK_OBJECT_HANDLE h_priv_key; + PK11_SESSION *sp = NULL; + int ret = 0; + unsigned long ulsiglen; + + /* Encode the digest */ + /* Special case: SSL signature, just check the length */ + if (type == NID_md5_sha1) + { + if (m_len != SSL_SIG_LENGTH) + { + PK11err(PK11_F_RSA_SIGN, + PK11_R_INVALID_MESSAGE_LENGTH); + goto err; + } + i = SSL_SIG_LENGTH; + s = (unsigned char *)m; + } + else + { + sig.algor = &algor; + sig.algor->algorithm = OBJ_nid2obj(type); + if (sig.algor->algorithm == NULL) + { + PK11err(PK11_F_RSA_SIGN, + PK11_R_UNKNOWN_ALGORITHM_TYPE); + goto err; + } + if (sig.algor->algorithm->length == 0) + { + PK11err(PK11_F_RSA_SIGN, + PK11_R_UNKNOWN_ASN1_OBJECT_ID); + goto err; + } + parameter.type = V_ASN1_NULL; + parameter.value.ptr = NULL; + sig.algor->parameter = ¶meter; + + sig.digest = &digest; + sig.digest->data = (unsigned char *)m; + sig.digest->length = m_len; + + i = i2d_X509_SIG(&sig, NULL); + } + + j = RSA_size(rsa); + if ((i - RSA_PKCS1_PADDING) > j) + { + PK11err(PK11_F_RSA_SIGN, PK11_R_DIGEST_TOO_BIG); + goto err; + } + + if (type != NID_md5_sha1) + { + s = (unsigned char *)OPENSSL_malloc((unsigned int)(j + 1)); + if (s == NULL) + { + PK11err(PK11_F_RSA_SIGN, PK11_R_MALLOC_FAILURE); + goto err; + } + p = s; + (void) i2d_X509_SIG(&sig, &p); + } + + if ((sp = pk11_get_session(OP_RSA)) == NULL) + goto err; + + (void) check_new_rsa_key_priv(sp, rsa); + + h_priv_key = sp->opdata_rsa_priv_key; + if (h_priv_key == CK_INVALID_HANDLE) + h_priv_key = sp->opdata_rsa_priv_key = + pk11_get_private_rsa_key((RSA *)rsa, + &sp->opdata_rsa_priv, &sp->opdata_rsa_d_num, + &sp->opdata_rsa_pn_num, &sp->opdata_rsa_pe_num, + sp->session); + + if (h_priv_key != CK_INVALID_HANDLE) + { + rv = pFuncList->C_SignInit(sp->session, p_mech, h_priv_key); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_RSA_SIGN, PK11_R_SIGNINIT, rv); + goto err; + } + + ulsiglen = j; + rv = pFuncList->C_Sign(sp->session, s, i, sigret, + (CK_ULONG_PTR) &ulsiglen); + *siglen = ulsiglen; + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_RSA_SIGN, PK11_R_SIGN, rv); + goto err; + } + ret = 1; + } + +err: + if ((type != NID_md5_sha1) && (s != NULL)) + { + (void) memset(s, 0, (unsigned int)(j + 1)); + OPENSSL_free(s); + } + + pk11_return_session(sp, OP_RSA); + return (ret); + } + +#if OPENSSL_VERSION_NUMBER < 0x10000000L +static int pk11_RSA_verify(int type, const unsigned char *m, + unsigned int m_len, unsigned char *sigbuf, unsigned int siglen, + const RSA *rsa) +#else +static int pk11_RSA_verify(int type, const unsigned char *m, + unsigned int m_len, const unsigned char *sigbuf, unsigned int siglen, + const RSA *rsa) +#endif + { + X509_SIG sig; + ASN1_TYPE parameter; + int i, j = 0; + unsigned char *p, *s = NULL; + X509_ALGOR algor; + ASN1_OCTET_STRING digest; + CK_RV rv; + CK_MECHANISM mech_rsa = {CKM_RSA_PKCS, NULL, 0}; + CK_MECHANISM *p_mech = &mech_rsa; + CK_OBJECT_HANDLE h_pub_key; + PK11_SESSION *sp = NULL; + int ret = 0; + + /* Encode the digest */ + /* Special case: SSL signature, just check the length */ + if (type == NID_md5_sha1) + { + if (m_len != SSL_SIG_LENGTH) + { + PK11err(PK11_F_RSA_VERIFY, + PK11_R_INVALID_MESSAGE_LENGTH); + goto err; + } + i = SSL_SIG_LENGTH; + s = (unsigned char *)m; + } + else + { + sig.algor = &algor; + sig.algor->algorithm = OBJ_nid2obj(type); + if (sig.algor->algorithm == NULL) + { + PK11err(PK11_F_RSA_VERIFY, + PK11_R_UNKNOWN_ALGORITHM_TYPE); + goto err; + } + if (sig.algor->algorithm->length == 0) + { + PK11err(PK11_F_RSA_VERIFY, + PK11_R_UNKNOWN_ASN1_OBJECT_ID); + goto err; + } + parameter.type = V_ASN1_NULL; + parameter.value.ptr = NULL; + sig.algor->parameter = ¶meter; + sig.digest = &digest; + sig.digest->data = (unsigned char *)m; + sig.digest->length = m_len; + i = i2d_X509_SIG(&sig, NULL); + } + + j = RSA_size(rsa); + if ((i - RSA_PKCS1_PADDING) > j) + { + PK11err(PK11_F_RSA_VERIFY, PK11_R_DIGEST_TOO_BIG); + goto err; + } + + if (type != NID_md5_sha1) + { + s = (unsigned char *)OPENSSL_malloc((unsigned int)(j + 1)); + if (s == NULL) + { + PK11err(PK11_F_RSA_VERIFY, PK11_R_MALLOC_FAILURE); + goto err; + } + p = s; + (void) i2d_X509_SIG(&sig, &p); + } + + if ((sp = pk11_get_session(OP_RSA)) == NULL) + goto err; + + (void) check_new_rsa_key_pub(sp, rsa); + + h_pub_key = sp->opdata_rsa_pub_key; + if (h_pub_key == CK_INVALID_HANDLE) + h_pub_key = sp->opdata_rsa_pub_key = + pk11_get_public_rsa_key((RSA *)rsa, &sp->opdata_rsa_pub, + &sp->opdata_rsa_n_num, &sp->opdata_rsa_e_num, + sp->session); + + if (h_pub_key != CK_INVALID_HANDLE) + { + rv = pFuncList->C_VerifyInit(sp->session, p_mech, + h_pub_key); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_RSA_VERIFY, PK11_R_VERIFYINIT, + rv); + goto err; + } + rv = pFuncList->C_Verify(sp->session, s, i, + (CK_BYTE_PTR)sigbuf, (CK_ULONG)siglen); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_RSA_VERIFY, PK11_R_VERIFY, rv); + goto err; + } + ret = 1; + } + +err: + if ((type != NID_md5_sha1) && (s != NULL)) + { + (void) memset(s, 0, (unsigned int)(j + 1)); + OPENSSL_free(s); + } + + pk11_return_session(sp, OP_RSA); + return (ret); + } + +static int hndidx_rsa = -1; + +#define MAXATTR 1024 + +/* + * Load RSA private key from a file or get its PKCS#11 handle if stored in the + * PKCS#11 token. + */ +/* ARGSUSED */ +EVP_PKEY *pk11_load_privkey(ENGINE *e, const char *privkey_file, + UI_METHOD *ui_method, void *callback_data) + { + EVP_PKEY *pkey = NULL; + FILE *privkey; + CK_OBJECT_HANDLE h_priv_key = CK_INVALID_HANDLE; + RSA *rsa = NULL; + PK11_SESSION *sp; + /* Anything else below is needed for the key by reference extension. */ + CK_RV rv; + CK_BBOOL is_token = TRUE; + CK_BBOOL rollback = FALSE; + CK_BYTE attr_data[2][MAXATTR]; + CK_OBJECT_CLASS key_class = CKO_PRIVATE_KEY; + CK_OBJECT_HANDLE ks_key = CK_INVALID_HANDLE; /* key in keystore */ + + /* we look for private keys only */ + CK_ATTRIBUTE search_templ[] = + { + {CKA_TOKEN, &is_token, sizeof(is_token)}, + {CKA_CLASS, &key_class, sizeof(key_class)}, + {CKA_LABEL, NULL, 0} + }; + + /* + * These public attributes are needed to initialize the OpenSSL RSA + * structure with something we can use to look up the key. Note that we + * never ask for private components. + */ + CK_ATTRIBUTE get_templ[] = + { + {CKA_MODULUS, (void *)attr_data[0], MAXATTR}, /* n */ + {CKA_PUBLIC_EXPONENT, (void *)attr_data[1], MAXATTR}, /* e */ + }; + + if ((sp = pk11_get_session(OP_RSA)) == NULL) + return (NULL); + + /* + * Use simple scheme "pkcs11:" for now. + */ + if (strstr(privkey_file, "pkcs11:") == privkey_file) + { + search_templ[2].pValue = strstr(privkey_file, ":") + 1; + search_templ[2].ulValueLen = strlen(search_templ[2].pValue); + + if (pk11_token_login(sp->session, &pk11_login_done, + CK_TRUE) == 0) + goto err; + + /* see find_lock array definition + for more info on object locking */ + LOCK_OBJSTORE(OP_RSA); + + /* + * Now let's try to find the key in the token. It is a failure + * if we can't find it. + */ + if (find_one_object(OP_RSA, sp->session, search_templ, 3, + &ks_key) == 0) + { + UNLOCK_OBJSTORE(OP_RSA); + goto err; + } + + if (hndidx_rsa == -1) + hndidx_rsa = RSA_get_ex_new_index(0, + "pkcs11 RSA HSM key handle", + NULL, NULL, NULL); + + /* + * We might have a cache hit which we could confirm + * according to the 'n'/'e' params, RSA public pointer + * as NULL, and non-NULL RSA private pointer. However, + * it is easier just to recreate everything. We expect + * the keys to be loaded once and used many times. We + * do not check the return value because even in case + * of failure the sp structure will have both key + * pointer and object handle cleaned and + * pk11_destroy_object() reports the failure to the + * OpenSSL error message buffer. + */ + (void) pk11_destroy_rsa_object_priv(sp, FALSE); + + sp->opdata_rsa_priv_key = ks_key; + /* This object shall not be deleted on a cache miss. */ + sp->priv_persistent = CK_TRUE; + + /* + * Cache the RSA private structure pointer. We do not + * use it now for key-by-ref keys but let's do it for + * consistency reasons. + */ + if ((rsa = sp->opdata_rsa_priv = RSA_new_method(e)) == NULL) + { + UNLOCK_OBJSTORE(OP_RSA); + goto err; + } + + /* + * Now we have to initialize an OpenSSL RSA structure, + * everything else is 0 or NULL. + */ + rsa->flags = RSA_FLAG_SIGN_VER | RSA_FLAG_EXT_PKEY; + RSA_set_ex_data(rsa, hndidx_rsa, (void *) ks_key); + + if ((rv = pFuncList->C_GetAttributeValue(sp->session, ks_key, + get_templ, 2)) != CKR_OK) + { + UNLOCK_OBJSTORE(OP_RSA); + PK11err_add_data(PK11_F_LOAD_PRIVKEY, + PK11_R_GETATTRIBUTVALUE, rv); + goto err; + } + + /* + * We do not use pk11_get_private_rsa_key() here so we + * must take care of handle management ourselves. + */ + KEY_HANDLE_REFHOLD(ks_key, OP_RSA, TRUE, rollback, err); + + /* + * Those are the sensitive components we do not want to export + * from the token at all: rsa->(d|p|q|dmp1|dmq1|iqmp). + */ + attr_to_BN(&get_templ[0], attr_data[0], &rsa->n); + attr_to_BN(&get_templ[1], attr_data[1], &rsa->e); + /* + * Must have 'n'/'e' components in the session structure as + * well. They serve as a public look-up key for the private key + * in the keystore. + */ + attr_to_BN(&get_templ[0], attr_data[0], + &sp->opdata_rsa_pn_num); + attr_to_BN(&get_templ[1], attr_data[1], + &sp->opdata_rsa_pe_num); + + UNLOCK_OBJSTORE(OP_RSA); + + if ((pkey = EVP_PKEY_new()) == NULL) + goto err; + + if (EVP_PKEY_assign_RSA(pkey, rsa) == 0) + goto err; + } + else if ((privkey = fopen(privkey_file, read_mode_flags)) != NULL) + { + pkey = PEM_read_PrivateKey(privkey, NULL, NULL, NULL); + (void) fclose(privkey); + if (pkey != NULL) + { + rsa = EVP_PKEY_get1_RSA(pkey); + if (rsa != NULL) + { + /* + * This will always destroy the RSA + * object since we have a new RSA + * structure here. + */ + (void) check_new_rsa_key_priv(sp, rsa); + sp->priv_persistent = CK_FALSE; + + h_priv_key = sp->opdata_rsa_priv_key = + pk11_get_private_rsa_key(rsa, + &sp->opdata_rsa_priv, + &sp->opdata_rsa_d_num, + &sp->opdata_rsa_pn_num, + &sp->opdata_rsa_pe_num, sp->session); + if (h_priv_key == CK_INVALID_HANDLE) + goto err; + } + else + goto err; + } + } + + pk11_return_session(sp, OP_RSA); + return (pkey); +err: + pk11_return_session(sp, OP_RSA); + if (rsa != NULL) + RSA_free(rsa); + if (pkey != NULL) + { + EVP_PKEY_free(pkey); + pkey = NULL; + } + rollback = rollback; + return (pkey); + } + +/* + * Load RSA public key from a file or get its PKCS#11 handle if stored in the + * PKCS#11 token. + */ +/* ARGSUSED */ +EVP_PKEY *pk11_load_pubkey(ENGINE *e, const char *pubkey_file, + UI_METHOD *ui_method, void *callback_data) + { + EVP_PKEY *pkey = NULL; + FILE *pubkey; + CK_OBJECT_HANDLE h_pub_key = CK_INVALID_HANDLE; + RSA *rsa = NULL; + PK11_SESSION *sp; + /* Anything else below is needed for the key by reference extension. */ + CK_RV rv; + CK_BBOOL is_token = TRUE; + CK_BYTE attr_data[2][MAXATTR]; + CK_OBJECT_CLASS key_class = CKO_PUBLIC_KEY; + CK_OBJECT_HANDLE ks_key = CK_INVALID_HANDLE; /* key in keystore */ + + /* we look for public keys only */ + CK_ATTRIBUTE search_templ[] = + { + {CKA_TOKEN, &is_token, sizeof(is_token)}, + {CKA_CLASS, &key_class, sizeof(key_class)}, + {CKA_LABEL, NULL, 0} + }; + + /* + * These public attributes are needed to initialize OpenSSL RSA + * structure with something we can use to look up the key. + */ + CK_ATTRIBUTE get_templ[] = + { + {CKA_MODULUS, (void *)attr_data[0], MAXATTR}, /* n */ + {CKA_PUBLIC_EXPONENT, (void *)attr_data[1], MAXATTR}, /* e */ + }; + + if ((sp = pk11_get_session(OP_RSA)) == NULL) + return (NULL); + + /* + * Use simple scheme "pkcs11:" for now. + */ + if (strstr(pubkey_file, "pkcs11:") == pubkey_file) + { + search_templ[2].pValue = strstr(pubkey_file, ":") + 1; + search_templ[2].ulValueLen = strlen(search_templ[2].pValue); + + if (pk11_token_login(sp->session, &pk11_login_done, + CK_FALSE) == 0) + goto err; + + /* see find_lock array definition + for more info on object locking */ + LOCK_OBJSTORE(OP_RSA); + + /* + * Now let's try to find the key in the token. It is a failure + * if we can't find it. + */ + if (find_one_object(OP_RSA, sp->session, search_templ, 3, + &ks_key) == 0) + { + UNLOCK_OBJSTORE(OP_RSA); + goto err; + } + + /* + * We load a new public key so we will create a new RSA + * structure. No cache hit is possible. + */ + (void) pk11_destroy_rsa_object_pub(sp, FALSE); + + sp->opdata_rsa_pub_key = ks_key; + /* This object shall not be deleted on a cache miss. */ + sp->pub_persistent = CK_TRUE; + + /* + * Cache the RSA public structure pointer. + */ + if ((rsa = sp->opdata_rsa_pub = RSA_new_method(e)) == NULL) + { + UNLOCK_OBJSTORE(OP_RSA); + goto err; + } + + /* + * Now we have to initialize an OpenSSL RSA structure, + * everything else is 0 or NULL. + */ + rsa->flags = RSA_FLAG_SIGN_VER; + + if ((rv = pFuncList->C_GetAttributeValue(sp->session, ks_key, + get_templ, 2)) != CKR_OK) + { + UNLOCK_OBJSTORE(OP_RSA); + PK11err_add_data(PK11_F_LOAD_PUBKEY, + PK11_R_GETATTRIBUTVALUE, rv); + goto err; + } + + attr_to_BN(&get_templ[0], attr_data[0], &rsa->n); + attr_to_BN(&get_templ[1], attr_data[1], &rsa->e); + + UNLOCK_OBJSTORE(OP_RSA); + + if ((pkey = EVP_PKEY_new()) == NULL) + goto err; + + if (EVP_PKEY_assign_RSA(pkey, rsa) == 0) + goto err; + + /* + * Create a session object from it so that when calling + * pk11_get_public_rsa_key() the next time, we can find it. The + * reason why we do that is that we cannot tell from the RSA + * structure (OpenSSL RSA structure does not have any room for + * additional data used by the engine, for example) if it bears + * a public key stored in the keystore or not so it's better if + * we always have a session key. Note that this is different + * from what we do for the private keystore objects but in that + * case, we can tell from the RSA structure that the keystore + * object is in play - the 'd' component is NULL in that case. + */ + h_pub_key = sp->opdata_rsa_pub_key = + pk11_get_public_rsa_key(rsa, + &sp->opdata_rsa_pub, &sp->opdata_rsa_n_num, + &sp->opdata_rsa_e_num, sp->session); + if (h_pub_key == CK_INVALID_HANDLE) + goto err; + } + else if ((pubkey = fopen(pubkey_file, read_mode_flags)) != NULL) + { + pkey = PEM_read_PUBKEY(pubkey, NULL, NULL, NULL); + (void) fclose(pubkey); + if (pkey != NULL) + { + rsa = EVP_PKEY_get1_RSA(pkey); + if (rsa != NULL) + { + /* + * This will always destroy the RSA + * object since we have a new RSA + * structure here. + */ + (void) check_new_rsa_key_pub(sp, rsa); + sp->pub_persistent = CK_FALSE; + + h_pub_key = sp->opdata_rsa_pub_key = + pk11_get_public_rsa_key(rsa, + &sp->opdata_rsa_pub, &sp->opdata_rsa_n_num, + &sp->opdata_rsa_e_num, sp->session); + if (h_pub_key == CK_INVALID_HANDLE) + goto err; + } + else + goto err; + } + } + + pk11_return_session(sp, OP_RSA); + return (pkey); +err: + pk11_return_session(sp, OP_RSA); + if (rsa != NULL) + RSA_free(rsa); + if (pkey != NULL) + { + EVP_PKEY_free(pkey); + pkey = NULL; + } + return (pkey); + } + +/* + * Create a public key object in a session from a given rsa structure. + * The *rsa_n_num and *rsa_e_num pointers are non-NULL for RSA public keys. + */ +static CK_OBJECT_HANDLE pk11_get_public_rsa_key(RSA *rsa, + RSA **key_ptr, BIGNUM **rsa_n_num, BIGNUM **rsa_e_num, + CK_SESSION_HANDLE session) + { + CK_RV rv; + CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE; + CK_ULONG found; + CK_OBJECT_CLASS o_key = CKO_PUBLIC_KEY; + CK_KEY_TYPE k_type = CKK_RSA; + CK_ULONG ul_key_attr_count = 8; + CK_BBOOL rollback = FALSE; + + CK_ATTRIBUTE a_key_template[] = + { + {CKA_CLASS, (void *) NULL, sizeof (CK_OBJECT_CLASS)}, + {CKA_KEY_TYPE, (void *) NULL, sizeof (CK_KEY_TYPE)}, + {CKA_TOKEN, &myfalse, sizeof (myfalse)}, + {CKA_ENCRYPT, &mytrue, sizeof (mytrue)}, + {CKA_VERIFY, &mytrue, sizeof (mytrue)}, + {CKA_VERIFY_RECOVER, &mytrue, sizeof (mytrue)}, + {CKA_MODULUS, (void *)NULL, 0}, + {CKA_PUBLIC_EXPONENT, (void *)NULL, 0} + }; + + int i; + + a_key_template[0].pValue = &o_key; + a_key_template[1].pValue = &k_type; + + a_key_template[6].ulValueLen = BN_num_bytes(rsa->n); + a_key_template[6].pValue = (CK_VOID_PTR)OPENSSL_malloc( + (size_t)a_key_template[6].ulValueLen); + if (a_key_template[6].pValue == NULL) + { + PK11err(PK11_F_GET_PUB_RSA_KEY, PK11_R_MALLOC_FAILURE); + goto malloc_err; + } + + BN_bn2bin(rsa->n, a_key_template[6].pValue); + + a_key_template[7].ulValueLen = BN_num_bytes(rsa->e); + a_key_template[7].pValue = (CK_VOID_PTR)OPENSSL_malloc( + (size_t)a_key_template[7].ulValueLen); + if (a_key_template[7].pValue == NULL) + { + PK11err(PK11_F_GET_PUB_RSA_KEY, PK11_R_MALLOC_FAILURE); + goto malloc_err; + } + + BN_bn2bin(rsa->e, a_key_template[7].pValue); + + /* see find_lock array definition for more info on object locking */ + LOCK_OBJSTORE(OP_RSA); + + rv = pFuncList->C_FindObjectsInit(session, a_key_template, + ul_key_attr_count); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PUB_RSA_KEY, + PK11_R_FINDOBJECTSINIT, rv); + goto err; + } + + rv = pFuncList->C_FindObjects(session, &h_key, 1, &found); + + if (rv != CKR_OK) + { + (void) pFuncList->C_FindObjectsFinal(session); + PK11err_add_data(PK11_F_GET_PUB_RSA_KEY, + PK11_R_FINDOBJECTS, rv); + goto err; + } + + rv = pFuncList->C_FindObjectsFinal(session); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PUB_RSA_KEY, + PK11_R_FINDOBJECTSFINAL, rv); + goto err; + } + + if (found == 0) + { + rv = pFuncList->C_CreateObject(session, + a_key_template, ul_key_attr_count, &h_key); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PUB_RSA_KEY, + PK11_R_CREATEOBJECT, rv); + goto err; + } + } + + if (rsa_n_num != NULL) + if ((*rsa_n_num = BN_dup(rsa->n)) == NULL) + { + PK11err(PK11_F_GET_PUB_RSA_KEY, PK11_R_MALLOC_FAILURE); + rollback = TRUE; + goto err; + } + if (rsa_e_num != NULL) + if ((*rsa_e_num = BN_dup(rsa->e)) == NULL) + { + PK11err(PK11_F_GET_PUB_RSA_KEY, PK11_R_MALLOC_FAILURE); + BN_free(*rsa_n_num); + *rsa_n_num = NULL; + rollback = TRUE; + goto err; + } + + /* LINTED: E_CONSTANT_CONDITION */ + KEY_HANDLE_REFHOLD(h_key, OP_RSA, FALSE, rollback, err); + if (key_ptr != NULL) + *key_ptr = rsa; + +err: + if (rollback) + { + /* + * We do not care about the return value from C_DestroyObject() + * since we are doing rollback. + */ + if (found == 0) + (void) pFuncList->C_DestroyObject(session, h_key); + h_key = CK_INVALID_HANDLE; + } + + UNLOCK_OBJSTORE(OP_RSA); + +malloc_err: + for (i = 6; i <= 7; i++) + { + if (a_key_template[i].pValue != NULL) + { + OPENSSL_free(a_key_template[i].pValue); + a_key_template[i].pValue = NULL; + } + } + + return (h_key); + } + +/* + * Create a private key object in the session from a given rsa structure. + * The *rsa_d_num pointer is non-NULL for RSA private keys. + */ +static CK_OBJECT_HANDLE +pk11_get_private_rsa_key(RSA *rsa, RSA **key_ptr, BIGNUM **rsa_d_num, + BIGNUM **rsa_n_num, BIGNUM **rsa_e_num, CK_SESSION_HANDLE session) + { + CK_RV rv; + CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE; + int i; + CK_ULONG found; + CK_OBJECT_CLASS o_key = CKO_PRIVATE_KEY; + CK_KEY_TYPE k_type = CKK_RSA; + CK_ULONG ul_key_attr_count = 14; + CK_BBOOL rollback = FALSE; + + /* Both CKA_TOKEN and CKA_SENSITIVE have to be FALSE for session keys */ + CK_ATTRIBUTE a_key_template[] = + { + {CKA_CLASS, (void *) NULL, sizeof (CK_OBJECT_CLASS)}, + {CKA_KEY_TYPE, (void *) NULL, sizeof (CK_KEY_TYPE)}, + {CKA_TOKEN, &myfalse, sizeof (myfalse)}, + {CKA_SENSITIVE, &myfalse, sizeof (myfalse)}, + {CKA_DECRYPT, &mytrue, sizeof (mytrue)}, + {CKA_SIGN, &mytrue, sizeof (mytrue)}, + {CKA_MODULUS, (void *)NULL, 0}, + {CKA_PUBLIC_EXPONENT, (void *)NULL, 0}, + {CKA_PRIVATE_EXPONENT, (void *)NULL, 0}, + {CKA_PRIME_1, (void *)NULL, 0}, + {CKA_PRIME_2, (void *)NULL, 0}, + {CKA_EXPONENT_1, (void *)NULL, 0}, + {CKA_EXPONENT_2, (void *)NULL, 0}, + {CKA_COEFFICIENT, (void *)NULL, 0}, + }; + + if ((rsa->flags & RSA_FLAG_EXT_PKEY) != 0) { + h_key = (CK_OBJECT_HANDLE)RSA_get_ex_data(rsa, hndidx_rsa); + LOCK_OBJSTORE(OP_RSA); + goto set; + } + + a_key_template[0].pValue = &o_key; + a_key_template[1].pValue = &k_type; + + /* Put the private key components into the template */ + if (init_template_value(rsa->n, &a_key_template[6].pValue, + &a_key_template[6].ulValueLen) == 0 || + init_template_value(rsa->e, &a_key_template[7].pValue, + &a_key_template[7].ulValueLen) == 0 || + init_template_value(rsa->d, &a_key_template[8].pValue, + &a_key_template[8].ulValueLen) == 0 || + init_template_value(rsa->p, &a_key_template[9].pValue, + &a_key_template[9].ulValueLen) == 0 || + init_template_value(rsa->q, &a_key_template[10].pValue, + &a_key_template[10].ulValueLen) == 0 || + init_template_value(rsa->dmp1, &a_key_template[11].pValue, + &a_key_template[11].ulValueLen) == 0 || + init_template_value(rsa->dmq1, &a_key_template[12].pValue, + &a_key_template[12].ulValueLen) == 0 || + init_template_value(rsa->iqmp, &a_key_template[13].pValue, + &a_key_template[13].ulValueLen) == 0) + { + PK11err(PK11_F_GET_PRIV_RSA_KEY, PK11_R_MALLOC_FAILURE); + goto malloc_err; + } + + /* see find_lock array definition for more info on object locking */ + LOCK_OBJSTORE(OP_RSA); + + /* + * We are getting the private key but the private 'd' + * component is NULL. That means this is key by reference RSA + * key. In that case, we can use only public components for + * searching for the private key handle. + */ + if (rsa->d == NULL) + { + ul_key_attr_count = 8; + /* + * We will perform the search in the token, not in the existing + * session keys. + */ + a_key_template[2].pValue = &mytrue; + } + + rv = pFuncList->C_FindObjectsInit(session, a_key_template, + ul_key_attr_count); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PRIV_RSA_KEY, + PK11_R_FINDOBJECTSINIT, rv); + goto err; + } + + rv = pFuncList->C_FindObjects(session, &h_key, 1, &found); + + if (rv != CKR_OK) + { + (void) pFuncList->C_FindObjectsFinal(session); + PK11err_add_data(PK11_F_GET_PRIV_RSA_KEY, + PK11_R_FINDOBJECTS, rv); + goto err; + } + + rv = pFuncList->C_FindObjectsFinal(session); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PRIV_RSA_KEY, + PK11_R_FINDOBJECTSFINAL, rv); + goto err; + } + + if (found == 0) + { + /* + * We have an RSA structure with 'n'/'e' components + * only so we tried to find the private key in the + * keystore. If it was really a token key we have a + * problem. Note that for other key types we just + * create a new session key using the private + * components from the RSA structure. + */ + if (rsa->d == NULL) + { + PK11err(PK11_F_GET_PRIV_RSA_KEY, + PK11_R_PRIV_KEY_NOT_FOUND); + goto err; + } + + rv = pFuncList->C_CreateObject(session, + a_key_template, ul_key_attr_count, &h_key); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PRIV_RSA_KEY, + PK11_R_CREATEOBJECT, rv); + goto err; + } + } + +set: + if (rsa_d_num != NULL) + { + /* + * When RSA keys by reference code is used, we never + * extract private components from the keystore. In + * that case 'd' was set to NULL and we expect the + * application to properly cope with that. It is + * documented in openssl(5). In general, if keys by + * reference are used we expect it to be used + * exclusively using the high level API and then there + * is no problem. If the application expects the + * private components to be read from the keystore + * then that is not a supported way of usage. + */ + if (rsa->d != NULL && (*rsa_d_num = BN_dup(rsa->d)) == NULL) + { + PK11err(PK11_F_GET_PRIV_RSA_KEY, PK11_R_MALLOC_FAILURE); + rollback = TRUE; + goto err; + } + else + *rsa_d_num = NULL; + } + + /* + * For the key by reference code, we need public components as well + * since 'd' component is always NULL. For that reason, we always cache + * 'n'/'e' components as well. + */ + *rsa_n_num = BN_dup(rsa->n); + *rsa_e_num = BN_dup(rsa->e); + + /* LINTED: E_CONSTANT_CONDITION */ + KEY_HANDLE_REFHOLD(h_key, OP_RSA, FALSE, rollback, err); + if (key_ptr != NULL) + *key_ptr = rsa; + +err: + if (rollback) + { + /* + * We do not care about the return value from C_DestroyObject() + * since we are doing rollback. + */ + if (found == 0 && + (rsa->flags & RSA_FLAG_EXT_PKEY) == 0) + (void) pFuncList->C_DestroyObject(session, h_key); + h_key = CK_INVALID_HANDLE; + } + + UNLOCK_OBJSTORE(OP_RSA); + +malloc_err: + /* + * 6 to 13 entries in the key template are key components. + * They need to be freed upon exit or error. + */ + for (i = 6; i <= 13; i++) + { + if (a_key_template[i].pValue != NULL) + { + (void) memset(a_key_template[i].pValue, 0, + a_key_template[i].ulValueLen); + OPENSSL_free(a_key_template[i].pValue); + a_key_template[i].pValue = NULL; + } + } + + return (h_key); + } + +/* + * Check for cache miss and clean the object pointer and handle + * in such case. Return 1 for cache hit, 0 for cache miss. + */ +static int check_new_rsa_key_pub(PK11_SESSION *sp, const RSA *rsa) + { + /* + * Provide protection against RSA structure reuse by making the + * check for cache hit stronger. Only public components of RSA + * key matter here so it is sufficient to compare them with values + * cached in PK11_SESSION structure. + * + * We must check the handle as well since with key by reference, public + * components 'n'/'e' are cached in private keys as well. That means we + * could have a cache hit in a private key when looking for a public + * key. That would not work, you cannot have one PKCS#11 object for + * both data signing and verifying. + */ + if ((sp->opdata_rsa_pub != rsa) || + (BN_cmp(sp->opdata_rsa_n_num, rsa->n) != 0) || + (BN_cmp(sp->opdata_rsa_e_num, rsa->e) != 0) || + (sp->opdata_rsa_priv_key != CK_INVALID_HANDLE)) + { + /* + * We do not check the return value because even in case of + * failure the sp structure will have both key pointer + * and object handle cleaned and pk11_destroy_object() + * reports the failure to the OpenSSL error message buffer. + */ + (void) pk11_destroy_rsa_object_pub(sp, TRUE); + return (0); + } + return (1); + } + +/* + * Check for cache miss and clean the object pointer and handle + * in such case. Return 1 for cache hit, 0 for cache miss. + */ +static int check_new_rsa_key_priv(PK11_SESSION *sp, const RSA *rsa) + { + /* + * Provide protection against RSA structure reuse by making + * the check for cache hit stronger. Comparing public exponent + * of RSA key with value cached in PK11_SESSION structure + * should be sufficient. Note that we want to compare the + * public component since with the keys by reference + * mechanism, private components are not in the RSA + * structure. Also, see check_new_rsa_key_pub() about why we + * compare the handle as well. + */ + if ((sp->opdata_rsa_priv != rsa) || + (BN_cmp(sp->opdata_rsa_pn_num, rsa->n) != 0) || + (BN_cmp(sp->opdata_rsa_pe_num, rsa->e) != 0) || + (sp->opdata_rsa_pn_num == NULL) || + (sp->opdata_rsa_pe_num == NULL) || + (sp->opdata_rsa_pub_key != CK_INVALID_HANDLE)) + { + /* + * We do not check the return value because even in case of + * failure the sp structure will have both key pointer + * and object handle cleaned and pk11_destroy_object() + * reports the failure to the OpenSSL error message buffer. + */ + (void) pk11_destroy_rsa_object_priv(sp, TRUE); + return (0); + } + return (1); + } +#endif + +#ifndef OPENSSL_NO_DSA +/* The DSA function implementation */ +/* ARGSUSED */ +static int pk11_DSA_init(DSA *dsa) + { + return (1); + } + +/* ARGSUSED */ +static int pk11_DSA_finish(DSA *dsa) + { + return (1); + } + + +static DSA_SIG * +pk11_dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa) + { + BIGNUM *r = NULL, *s = NULL; + int i; + DSA_SIG *dsa_sig = NULL; + + CK_RV rv; + CK_MECHANISM Mechanism_dsa = {CKM_DSA, NULL, 0}; + CK_MECHANISM *p_mech = &Mechanism_dsa; + CK_OBJECT_HANDLE h_priv_key; + + /* + * The signature is the concatenation of r and s, + * each is 20 bytes long + */ + unsigned char sigret[DSA_SIGNATURE_LEN]; + unsigned long siglen = DSA_SIGNATURE_LEN; + unsigned int siglen2 = DSA_SIGNATURE_LEN / 2; + + PK11_SESSION *sp = NULL; + + if ((dsa->p == NULL) || (dsa->q == NULL) || (dsa->g == NULL)) + { + PK11err(PK11_F_DSA_SIGN, PK11_R_MISSING_KEY_COMPONENT); + goto ret; + } + + i = BN_num_bytes(dsa->q); /* should be 20 */ + if (dlen > i) + { + PK11err(PK11_F_DSA_SIGN, PK11_R_INVALID_SIGNATURE_LENGTH); + goto ret; + } + + if ((sp = pk11_get_session(OP_DSA)) == NULL) + goto ret; + + (void) check_new_dsa_key_priv(sp, dsa); + + h_priv_key = sp->opdata_dsa_priv_key; + if (h_priv_key == CK_INVALID_HANDLE) + h_priv_key = sp->opdata_dsa_priv_key = + pk11_get_private_dsa_key((DSA *)dsa, + &sp->opdata_dsa_priv, + &sp->opdata_dsa_priv_num, sp->session); + + if (h_priv_key != CK_INVALID_HANDLE) + { + rv = pFuncList->C_SignInit(sp->session, p_mech, h_priv_key); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DSA_SIGN, PK11_R_SIGNINIT, rv); + goto ret; + } + + (void) memset(sigret, 0, siglen); + rv = pFuncList->C_Sign(sp->session, + (unsigned char*) dgst, dlen, sigret, + (CK_ULONG_PTR) &siglen); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DSA_SIGN, PK11_R_SIGN, rv); + goto ret; + } + } + + + if ((s = BN_new()) == NULL) + { + PK11err(PK11_F_DSA_SIGN, PK11_R_MALLOC_FAILURE); + goto ret; + } + + if ((r = BN_new()) == NULL) + { + PK11err(PK11_F_DSA_SIGN, PK11_R_MALLOC_FAILURE); + goto ret; + } + + if ((dsa_sig = DSA_SIG_new()) == NULL) + { + PK11err(PK11_F_DSA_SIGN, PK11_R_MALLOC_FAILURE); + goto ret; + } + + if (BN_bin2bn(sigret, siglen2, r) == NULL || + BN_bin2bn(&sigret[siglen2], siglen2, s) == NULL) + { + PK11err(PK11_F_DSA_SIGN, PK11_R_MALLOC_FAILURE); + goto ret; + } + + dsa_sig->r = r; + dsa_sig->s = s; + +ret: + if (dsa_sig == NULL) + { + if (r != NULL) + BN_free(r); + if (s != NULL) + BN_free(s); + } + + pk11_return_session(sp, OP_DSA); + return (dsa_sig); + } + +static int +pk11_dsa_do_verify(const unsigned char *dgst, int dlen, DSA_SIG *sig, + DSA *dsa) + { + int i; + CK_RV rv; + int retval = 0; + CK_MECHANISM Mechanism_dsa = {CKM_DSA, NULL, 0}; + CK_MECHANISM *p_mech = &Mechanism_dsa; + CK_OBJECT_HANDLE h_pub_key; + + unsigned char sigbuf[DSA_SIGNATURE_LEN]; + unsigned long siglen = DSA_SIGNATURE_LEN; + unsigned long siglen2 = DSA_SIGNATURE_LEN/2; + + PK11_SESSION *sp = NULL; + + if (BN_is_zero(sig->r) || sig->r->neg || BN_ucmp(sig->r, dsa->q) >= 0) + { + PK11err(PK11_F_DSA_VERIFY, + PK11_R_INVALID_DSA_SIGNATURE_R); + goto ret; + } + + if (BN_is_zero(sig->s) || sig->s->neg || BN_ucmp(sig->s, dsa->q) >= 0) + { + PK11err(PK11_F_DSA_VERIFY, + PK11_R_INVALID_DSA_SIGNATURE_S); + goto ret; + } + + i = BN_num_bytes(dsa->q); /* should be 20 */ + + if (dlen > i) + { + PK11err(PK11_F_DSA_VERIFY, + PK11_R_INVALID_SIGNATURE_LENGTH); + goto ret; + } + + if ((sp = pk11_get_session(OP_DSA)) == NULL) + goto ret; + + (void) check_new_dsa_key_pub(sp, dsa); + + h_pub_key = sp->opdata_dsa_pub_key; + if (h_pub_key == CK_INVALID_HANDLE) + h_pub_key = sp->opdata_dsa_pub_key = + pk11_get_public_dsa_key((DSA *)dsa, &sp->opdata_dsa_pub, + &sp->opdata_dsa_pub_num, sp->session); + + if (h_pub_key != CK_INVALID_HANDLE) + { + rv = pFuncList->C_VerifyInit(sp->session, p_mech, + h_pub_key); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DSA_VERIFY, PK11_R_VERIFYINIT, + rv); + goto ret; + } + + /* + * The representation of each of the two big numbers could + * be shorter than DSA_SIGNATURE_LEN/2 bytes so we need + * to act accordingly and shift if necessary. + */ + (void) memset(sigbuf, 0, siglen); + BN_bn2bin(sig->r, sigbuf + siglen2 - BN_num_bytes(sig->r)); + BN_bn2bin(sig->s, &sigbuf[siglen2] + siglen2 - + BN_num_bytes(sig->s)); + + rv = pFuncList->C_Verify(sp->session, + (unsigned char *) dgst, dlen, sigbuf, (CK_ULONG)siglen); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DSA_VERIFY, PK11_R_VERIFY, rv); + goto ret; + } + } + + retval = 1; +ret: + + pk11_return_session(sp, OP_DSA); + return (retval); + } + + +/* + * Create a public key object in a session from a given dsa structure. + * The *dsa_pub_num pointer is non-NULL for DSA public keys. + */ +static CK_OBJECT_HANDLE pk11_get_public_dsa_key(DSA* dsa, + DSA **key_ptr, BIGNUM **dsa_pub_num, CK_SESSION_HANDLE session) + { + CK_RV rv; + CK_OBJECT_CLASS o_key = CKO_PUBLIC_KEY; + CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE; + CK_ULONG found; + CK_KEY_TYPE k_type = CKK_DSA; + CK_ULONG ul_key_attr_count = 8; + CK_BBOOL rollback = FALSE; + int i; + + CK_ATTRIBUTE a_key_template[] = + { + {CKA_CLASS, (void *) NULL, sizeof (CK_OBJECT_CLASS)}, + {CKA_KEY_TYPE, (void *) NULL, sizeof (CK_KEY_TYPE)}, + {CKA_TOKEN, &myfalse, sizeof (myfalse)}, + {CKA_VERIFY, &mytrue, sizeof (mytrue)}, + {CKA_PRIME, (void *)NULL, 0}, /* p */ + {CKA_SUBPRIME, (void *)NULL, 0}, /* q */ + {CKA_BASE, (void *)NULL, 0}, /* g */ + {CKA_VALUE, (void *)NULL, 0} /* pub_key - y */ + }; + + a_key_template[0].pValue = &o_key; + a_key_template[1].pValue = &k_type; + + if (init_template_value(dsa->p, &a_key_template[4].pValue, + &a_key_template[4].ulValueLen) == 0 || + init_template_value(dsa->q, &a_key_template[5].pValue, + &a_key_template[5].ulValueLen) == 0 || + init_template_value(dsa->g, &a_key_template[6].pValue, + &a_key_template[6].ulValueLen) == 0 || + init_template_value(dsa->pub_key, &a_key_template[7].pValue, + &a_key_template[7].ulValueLen) == 0) + { + PK11err(PK11_F_GET_PUB_DSA_KEY, PK11_R_MALLOC_FAILURE); + goto malloc_err; + } + + /* see find_lock array definition for more info on object locking */ + LOCK_OBJSTORE(OP_DSA); + rv = pFuncList->C_FindObjectsInit(session, a_key_template, + ul_key_attr_count); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PUB_DSA_KEY, + PK11_R_FINDOBJECTSINIT, rv); + goto err; + } + + rv = pFuncList->C_FindObjects(session, &h_key, 1, &found); + + if (rv != CKR_OK) + { + (void) pFuncList->C_FindObjectsFinal(session); + PK11err_add_data(PK11_F_GET_PUB_DSA_KEY, + PK11_R_FINDOBJECTS, rv); + goto err; + } + + rv = pFuncList->C_FindObjectsFinal(session); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PUB_DSA_KEY, + PK11_R_FINDOBJECTSFINAL, rv); + goto err; + } + + if (found == 0) + { + rv = pFuncList->C_CreateObject(session, + a_key_template, ul_key_attr_count, &h_key); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PUB_DSA_KEY, + PK11_R_CREATEOBJECT, rv); + goto err; + } + } + + if (dsa_pub_num != NULL) + if ((*dsa_pub_num = BN_dup(dsa->pub_key)) == NULL) + { + PK11err(PK11_F_GET_PUB_DSA_KEY, PK11_R_MALLOC_FAILURE); + rollback = TRUE; + goto err; + } + + /* LINTED: E_CONSTANT_CONDITION */ + KEY_HANDLE_REFHOLD(h_key, OP_DSA, FALSE, rollback, err); + if (key_ptr != NULL) + *key_ptr = dsa; + +err: + if (rollback) + { + /* + * We do not care about the return value from C_DestroyObject() + * since we are doing rollback. + */ + if (found == 0) + (void) pFuncList->C_DestroyObject(session, h_key); + h_key = CK_INVALID_HANDLE; + } + + UNLOCK_OBJSTORE(OP_DSA); + +malloc_err: + for (i = 4; i <= 7; i++) + { + if (a_key_template[i].pValue != NULL) + { + OPENSSL_free(a_key_template[i].pValue); + a_key_template[i].pValue = NULL; + } + } + + return (h_key); + } + +/* + * Create a private key object in the session from a given dsa structure + * The *dsa_priv_num pointer is non-NULL for DSA private keys. + */ +static CK_OBJECT_HANDLE pk11_get_private_dsa_key(DSA* dsa, + DSA **key_ptr, BIGNUM **dsa_priv_num, CK_SESSION_HANDLE session) + { + CK_RV rv; + CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE; + CK_OBJECT_CLASS o_key = CKO_PRIVATE_KEY; + int i; + CK_ULONG found; + CK_KEY_TYPE k_type = CKK_DSA; + CK_ULONG ul_key_attr_count = 9; + CK_BBOOL rollback = FALSE; + + /* Both CKA_TOKEN and CKA_SENSITIVE have to be FALSE for session keys */ + CK_ATTRIBUTE a_key_template[] = + { + {CKA_CLASS, (void *) NULL, sizeof (CK_OBJECT_CLASS)}, + {CKA_KEY_TYPE, (void *) NULL, sizeof (CK_KEY_TYPE)}, + {CKA_TOKEN, &myfalse, sizeof (myfalse)}, + {CKA_SENSITIVE, &myfalse, sizeof (myfalse)}, + {CKA_SIGN, &mytrue, sizeof (mytrue)}, + {CKA_PRIME, (void *)NULL, 0}, /* p */ + {CKA_SUBPRIME, (void *)NULL, 0}, /* q */ + {CKA_BASE, (void *)NULL, 0}, /* g */ + {CKA_VALUE, (void *)NULL, 0} /* priv_key - x */ + }; + + a_key_template[0].pValue = &o_key; + a_key_template[1].pValue = &k_type; + + /* Put the private key components into the template */ + if (init_template_value(dsa->p, &a_key_template[5].pValue, + &a_key_template[5].ulValueLen) == 0 || + init_template_value(dsa->q, &a_key_template[6].pValue, + &a_key_template[6].ulValueLen) == 0 || + init_template_value(dsa->g, &a_key_template[7].pValue, + &a_key_template[7].ulValueLen) == 0 || + init_template_value(dsa->priv_key, &a_key_template[8].pValue, + &a_key_template[8].ulValueLen) == 0) + { + PK11err(PK11_F_GET_PRIV_DSA_KEY, PK11_R_MALLOC_FAILURE); + goto malloc_err; + } + + /* see find_lock array definition for more info on object locking */ + LOCK_OBJSTORE(OP_DSA); + rv = pFuncList->C_FindObjectsInit(session, a_key_template, + ul_key_attr_count); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PRIV_DSA_KEY, + PK11_R_FINDOBJECTSINIT, rv); + goto err; + } + + rv = pFuncList->C_FindObjects(session, &h_key, 1, &found); + + if (rv != CKR_OK) + { + (void) pFuncList->C_FindObjectsFinal(session); + PK11err_add_data(PK11_F_GET_PRIV_DSA_KEY, + PK11_R_FINDOBJECTS, rv); + goto err; + } + + rv = pFuncList->C_FindObjectsFinal(session); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PRIV_DSA_KEY, + PK11_R_FINDOBJECTSFINAL, rv); + goto err; + } + + if (found == 0) + { + rv = pFuncList->C_CreateObject(session, + a_key_template, ul_key_attr_count, &h_key); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PRIV_DSA_KEY, + PK11_R_CREATEOBJECT, rv); + goto err; + } + } + + if (dsa_priv_num != NULL) + if ((*dsa_priv_num = BN_dup(dsa->priv_key)) == NULL) + { + PK11err(PK11_F_GET_PRIV_DSA_KEY, PK11_R_MALLOC_FAILURE); + rollback = TRUE; + goto err; + } + + /* LINTED: E_CONSTANT_CONDITION */ + KEY_HANDLE_REFHOLD(h_key, OP_DSA, FALSE, rollback, err); + if (key_ptr != NULL) + *key_ptr = dsa; + +err: + if (rollback) + { + /* + * We do not care about the return value from C_DestroyObject() + * since we are doing rollback. + */ + if (found == 0) + (void) pFuncList->C_DestroyObject(session, h_key); + h_key = CK_INVALID_HANDLE; + } + + UNLOCK_OBJSTORE(OP_DSA); + +malloc_err: + /* + * 5 to 8 entries in the key template are key components. + * They need to be freed apon exit or error. + */ + for (i = 5; i <= 8; i++) + { + if (a_key_template[i].pValue != NULL) + { + (void) memset(a_key_template[i].pValue, 0, + a_key_template[i].ulValueLen); + OPENSSL_free(a_key_template[i].pValue); + a_key_template[i].pValue = NULL; + } + } + + return (h_key); + } + +/* + * Check for cache miss and clean the object pointer and handle + * in such case. Return 1 for cache hit, 0 for cache miss. + */ +static int check_new_dsa_key_pub(PK11_SESSION *sp, DSA *dsa) + { + /* + * Provide protection against DSA structure reuse by making the + * check for cache hit stronger. Only public key component of DSA + * key matters here so it is sufficient to compare it with value + * cached in PK11_SESSION structure. + */ + if ((sp->opdata_dsa_pub != dsa) || + (BN_cmp(sp->opdata_dsa_pub_num, dsa->pub_key) != 0)) + { + /* + * We do not check the return value because even in case of + * failure the sp structure will have both key pointer + * and object handle cleaned and pk11_destroy_object() + * reports the failure to the OpenSSL error message buffer. + */ + (void) pk11_destroy_dsa_object_pub(sp, TRUE); + return (0); + } + return (1); + } + +/* + * Check for cache miss and clean the object pointer and handle + * in such case. Return 1 for cache hit, 0 for cache miss. + */ +static int check_new_dsa_key_priv(PK11_SESSION *sp, DSA *dsa) + { + /* + * Provide protection against DSA structure reuse by making the + * check for cache hit stronger. Only private key component of DSA + * key matters here so it is sufficient to compare it with value + * cached in PK11_SESSION structure. + */ + if ((sp->opdata_dsa_priv != dsa) || + (BN_cmp(sp->opdata_dsa_priv_num, dsa->priv_key) != 0)) + { + /* + * We do not check the return value because even in case of + * failure the sp structure will have both key pointer + * and object handle cleaned and pk11_destroy_object() + * reports the failure to the OpenSSL error message buffer. + */ + (void) pk11_destroy_dsa_object_priv(sp, TRUE); + return (0); + } + return (1); + } +#endif + + +#ifndef OPENSSL_NO_DH +/* The DH function implementation */ +/* ARGSUSED */ +static int pk11_DH_init(DH *dh) + { + return (1); + } + +/* ARGSUSED */ +static int pk11_DH_finish(DH *dh) + { + return (1); + } + +/* + * Generate DH key-pair. + * + * Warning: Unlike OpenSSL's DH_generate_key(3) we ignore dh->priv_key + * and override it even if it is set. OpenSSL does not touch dh->priv_key + * if set and just computes dh->pub_key. It looks like PKCS#11 standard + * is not capable of providing this functionality. This could be a problem + * for applications relying on OpenSSL's semantics. + */ +static int pk11_DH_generate_key(DH *dh) + { + CK_ULONG i; + CK_RV rv, rv1; + int reuse_mem_len = 0, ret = 0; + PK11_SESSION *sp = NULL; + CK_BYTE_PTR reuse_mem; + + CK_MECHANISM mechanism = {CKM_DH_PKCS_KEY_PAIR_GEN, NULL_PTR, 0}; + CK_OBJECT_HANDLE h_pub_key = CK_INVALID_HANDLE; + CK_OBJECT_HANDLE h_priv_key = CK_INVALID_HANDLE; + + CK_ULONG ul_pub_key_attr_count = 3; + CK_ATTRIBUTE pub_key_template[] = + { + {CKA_PRIVATE, &myfalse, sizeof (myfalse)}, + {CKA_PRIME, (void *)NULL, 0}, + {CKA_BASE, (void *)NULL, 0} + }; + + CK_ULONG ul_priv_key_attr_count = 3; + CK_ATTRIBUTE priv_key_template[] = + { + {CKA_PRIVATE, &myfalse, sizeof (myfalse)}, + {CKA_SENSITIVE, &myfalse, sizeof (myfalse)}, + {CKA_DERIVE, &mytrue, sizeof (mytrue)} + }; + + CK_ULONG pub_key_attr_result_count = 1; + CK_ATTRIBUTE pub_key_result[] = + { + {CKA_VALUE, (void *)NULL, 0} + }; + + CK_ULONG priv_key_attr_result_count = 1; + CK_ATTRIBUTE priv_key_result[] = + { + {CKA_VALUE, (void *)NULL, 0} + }; + + pub_key_template[1].ulValueLen = BN_num_bytes(dh->p); + if (pub_key_template[1].ulValueLen > 0) + { + /* + * We must not increase ulValueLen by DH_BUF_RESERVE since that + * could cause the same rounding problem. See definition of + * DH_BUF_RESERVE above. + */ + pub_key_template[1].pValue = + OPENSSL_malloc(pub_key_template[1].ulValueLen + + DH_BUF_RESERVE); + if (pub_key_template[1].pValue == NULL) + { + PK11err(PK11_F_DH_GEN_KEY, PK11_R_MALLOC_FAILURE); + goto err; + } + + i = BN_bn2bin(dh->p, pub_key_template[1].pValue); + } + else + goto err; + + pub_key_template[2].ulValueLen = BN_num_bytes(dh->g); + if (pub_key_template[2].ulValueLen > 0) + { + pub_key_template[2].pValue = + OPENSSL_malloc(pub_key_template[2].ulValueLen + + DH_BUF_RESERVE); + if (pub_key_template[2].pValue == NULL) + { + PK11err(PK11_F_DH_GEN_KEY, PK11_R_MALLOC_FAILURE); + goto err; + } + + i = BN_bn2bin(dh->g, pub_key_template[2].pValue); + } + else + goto err; + + /* + * Note: we are only using PK11_SESSION structure for getting + * a session handle. The objects created in this function are + * destroyed before return and thus not cached. + */ + if ((sp = pk11_get_session(OP_DH)) == NULL) + goto err; + + rv = pFuncList->C_GenerateKeyPair(sp->session, + &mechanism, + pub_key_template, + ul_pub_key_attr_count, + priv_key_template, + ul_priv_key_attr_count, + &h_pub_key, + &h_priv_key); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DH_GEN_KEY, PK11_R_GEN_KEY, rv); + goto err; + } + + /* + * Reuse the larger memory allocated. We know the larger memory + * should be sufficient for reuse. + */ + if (pub_key_template[1].ulValueLen > pub_key_template[2].ulValueLen) + { + reuse_mem = pub_key_template[1].pValue; + reuse_mem_len = pub_key_template[1].ulValueLen + DH_BUF_RESERVE; + } + else + { + reuse_mem = pub_key_template[2].pValue; + reuse_mem_len = pub_key_template[2].ulValueLen + DH_BUF_RESERVE; + } + + rv = pFuncList->C_GetAttributeValue(sp->session, h_pub_key, + pub_key_result, pub_key_attr_result_count); + rv1 = pFuncList->C_GetAttributeValue(sp->session, h_priv_key, + priv_key_result, priv_key_attr_result_count); + + if (rv != CKR_OK || rv1 != CKR_OK) + { + rv = (rv != CKR_OK) ? rv : rv1; + PK11err_add_data(PK11_F_DH_GEN_KEY, + PK11_R_GETATTRIBUTVALUE, rv); + goto err; + } + + if (((CK_LONG) pub_key_result[0].ulValueLen) <= 0 || + ((CK_LONG) priv_key_result[0].ulValueLen) <= 0) + { + PK11err(PK11_F_DH_GEN_KEY, PK11_R_GETATTRIBUTVALUE); + goto err; + } + + /* Reuse the memory allocated */ + pub_key_result[0].pValue = reuse_mem; + pub_key_result[0].ulValueLen = reuse_mem_len; + + rv = pFuncList->C_GetAttributeValue(sp->session, h_pub_key, + pub_key_result, pub_key_attr_result_count); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DH_GEN_KEY, + PK11_R_GETATTRIBUTVALUE, rv); + goto err; + } + + if (pub_key_result[0].type == CKA_VALUE) + { + if (dh->pub_key == NULL) + if ((dh->pub_key = BN_new()) == NULL) + { + PK11err(PK11_F_DH_GEN_KEY, + PK11_R_MALLOC_FAILURE); + goto err; + } + dh->pub_key = BN_bin2bn(pub_key_result[0].pValue, + pub_key_result[0].ulValueLen, dh->pub_key); + if (dh->pub_key == NULL) + { + PK11err(PK11_F_DH_GEN_KEY, PK11_R_MALLOC_FAILURE); + goto err; + } + } + + /* Reuse the memory allocated */ + priv_key_result[0].pValue = reuse_mem; + priv_key_result[0].ulValueLen = reuse_mem_len; + + rv = pFuncList->C_GetAttributeValue(sp->session, h_priv_key, + priv_key_result, priv_key_attr_result_count); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DH_GEN_KEY, + PK11_R_GETATTRIBUTVALUE, rv); + goto err; + } + + if (priv_key_result[0].type == CKA_VALUE) + { + if (dh->priv_key == NULL) + if ((dh->priv_key = BN_new()) == NULL) + { + PK11err(PK11_F_DH_GEN_KEY, + PK11_R_MALLOC_FAILURE); + goto err; + } + dh->priv_key = BN_bin2bn(priv_key_result[0].pValue, + priv_key_result[0].ulValueLen, dh->priv_key); + if (dh->priv_key == NULL) + { + PK11err(PK11_F_DH_GEN_KEY, PK11_R_MALLOC_FAILURE); + goto err; + } + } + + ret = 1; + +err: + + if (h_pub_key != CK_INVALID_HANDLE) + { + rv = pFuncList->C_DestroyObject(sp->session, h_pub_key); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DH_GEN_KEY, + PK11_R_DESTROYOBJECT, rv); + } + } + + if (h_priv_key != CK_INVALID_HANDLE) + { + rv = pFuncList->C_DestroyObject(sp->session, h_priv_key); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DH_GEN_KEY, + PK11_R_DESTROYOBJECT, rv); + } + } + + for (i = 1; i <= 2; i++) + { + if (pub_key_template[i].pValue != NULL) + { + OPENSSL_free(pub_key_template[i].pValue); + pub_key_template[i].pValue = NULL; + } + } + + pk11_return_session(sp, OP_DH); + return (ret); + } + +static int pk11_DH_compute_key(unsigned char *key, const BIGNUM *pub_key, + DH *dh) + { + unsigned int i; + CK_MECHANISM mechanism = {CKM_DH_PKCS_DERIVE, NULL_PTR, 0}; + CK_OBJECT_CLASS key_class = CKO_SECRET_KEY; + CK_KEY_TYPE key_type = CKK_GENERIC_SECRET; + CK_OBJECT_HANDLE h_derived_key = CK_INVALID_HANDLE; + CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE; + + CK_ULONG seclen; + CK_ULONG ul_priv_key_attr_count = 3; + CK_ATTRIBUTE priv_key_template[] = + { + {CKA_CLASS, (void*) NULL, sizeof (key_class)}, + {CKA_KEY_TYPE, (void*) NULL, sizeof (key_type)}, + {CKA_VALUE_LEN, &seclen, sizeof (seclen)}, + }; + + CK_ULONG priv_key_attr_result_count = 1; + CK_ATTRIBUTE priv_key_result[] = + { + {CKA_VALUE, (void *)NULL, 0} + }; + + CK_RV rv; + int ret = -1; + PK11_SESSION *sp = NULL; + + if (dh->priv_key == NULL) + goto err; + + priv_key_template[0].pValue = &key_class; + priv_key_template[1].pValue = &key_type; + seclen = BN_num_bytes(dh->p); + + if ((sp = pk11_get_session(OP_DH)) == NULL) + goto err; + + mechanism.ulParameterLen = BN_num_bytes(pub_key); + mechanism.pParameter = OPENSSL_malloc(mechanism.ulParameterLen); + if (mechanism.pParameter == NULL) + { + PK11err(PK11_F_DH_COMP_KEY, PK11_R_MALLOC_FAILURE); + goto err; + } + BN_bn2bin(pub_key, mechanism.pParameter); + + (void) check_new_dh_key(sp, dh); + + h_key = sp->opdata_dh_key; + if (h_key == CK_INVALID_HANDLE) + h_key = sp->opdata_dh_key = + pk11_get_dh_key((DH*) dh, &sp->opdata_dh, + &sp->opdata_dh_priv_num, sp->session); + + if (h_key == CK_INVALID_HANDLE) + { + PK11err(PK11_F_DH_COMP_KEY, PK11_R_CREATEOBJECT); + goto err; + } + + rv = pFuncList->C_DeriveKey(sp->session, + &mechanism, + h_key, + priv_key_template, + ul_priv_key_attr_count, + &h_derived_key); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DH_COMP_KEY, PK11_R_DERIVEKEY, rv); + goto err; + } + + rv = pFuncList->C_GetAttributeValue(sp->session, h_derived_key, + priv_key_result, priv_key_attr_result_count); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DH_COMP_KEY, PK11_R_GETATTRIBUTVALUE, + rv); + goto err; + } + + if (((CK_LONG) priv_key_result[0].ulValueLen) <= 0) + { + PK11err(PK11_F_DH_COMP_KEY, PK11_R_GETATTRIBUTVALUE); + goto err; + } + priv_key_result[0].pValue = + OPENSSL_malloc(priv_key_result[0].ulValueLen); + if (!priv_key_result[0].pValue) + { + PK11err(PK11_F_DH_COMP_KEY, PK11_R_MALLOC_FAILURE); + goto err; + } + + rv = pFuncList->C_GetAttributeValue(sp->session, h_derived_key, + priv_key_result, priv_key_attr_result_count); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DH_COMP_KEY, PK11_R_GETATTRIBUTVALUE, + rv); + goto err; + } + + /* + * OpenSSL allocates the output buffer 'key' which is the same + * length of the public key. It is long enough for the derived key + */ + if (priv_key_result[0].type == CKA_VALUE) + { + /* + * CKM_DH_PKCS_DERIVE mechanism is not supposed to strip + * leading zeros from a computed shared secret. However, + * OpenSSL always did it so we must do the same here. The + * vagueness of the spec regarding leading zero bytes was + * finally cleared with TLS 1.1 (RFC 4346) saying that leading + * zeros are stripped before the computed data is used as the + * pre-master secret. + */ + for (i = 0; i < priv_key_result[0].ulValueLen; ++i) + { + if (((char *)priv_key_result[0].pValue)[i] != 0) + break; + } + + (void) memcpy(key, ((char *)priv_key_result[0].pValue) + i, + priv_key_result[0].ulValueLen - i); + ret = priv_key_result[0].ulValueLen - i; + } + +err: + + if (h_derived_key != CK_INVALID_HANDLE) + { + rv = pFuncList->C_DestroyObject(sp->session, h_derived_key); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DH_COMP_KEY, + PK11_R_DESTROYOBJECT, rv); + } + } + if (priv_key_result[0].pValue) + { + OPENSSL_free(priv_key_result[0].pValue); + priv_key_result[0].pValue = NULL; + } + + if (mechanism.pParameter) + { + OPENSSL_free(mechanism.pParameter); + mechanism.pParameter = NULL; + } + + pk11_return_session(sp, OP_DH); + return (ret); + } + + +static CK_OBJECT_HANDLE pk11_get_dh_key(DH* dh, + DH **key_ptr, BIGNUM **dh_priv_num, CK_SESSION_HANDLE session) + { + CK_RV rv; + CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE; + CK_OBJECT_CLASS class = CKO_PRIVATE_KEY; + CK_KEY_TYPE key_type = CKK_DH; + CK_ULONG found; + CK_BBOOL rollback = FALSE; + int i; + + CK_ULONG ul_key_attr_count = 7; + CK_ATTRIBUTE key_template[] = + { + {CKA_CLASS, (void*) NULL, sizeof (class)}, + {CKA_KEY_TYPE, (void*) NULL, sizeof (key_type)}, + {CKA_DERIVE, &mytrue, sizeof (mytrue)}, + {CKA_PRIVATE, &myfalse, sizeof (myfalse)}, + {CKA_PRIME, (void *) NULL, 0}, + {CKA_BASE, (void *) NULL, 0}, + {CKA_VALUE, (void *) NULL, 0}, + }; + + key_template[0].pValue = &class; + key_template[1].pValue = &key_type; + + key_template[4].ulValueLen = BN_num_bytes(dh->p); + key_template[4].pValue = (CK_VOID_PTR)OPENSSL_malloc( + (size_t)key_template[4].ulValueLen); + if (key_template[4].pValue == NULL) + { + PK11err(PK11_F_GET_DH_KEY, PK11_R_MALLOC_FAILURE); + goto malloc_err; + } + + BN_bn2bin(dh->p, key_template[4].pValue); + + key_template[5].ulValueLen = BN_num_bytes(dh->g); + key_template[5].pValue = (CK_VOID_PTR)OPENSSL_malloc( + (size_t)key_template[5].ulValueLen); + if (key_template[5].pValue == NULL) + { + PK11err(PK11_F_GET_DH_KEY, PK11_R_MALLOC_FAILURE); + goto malloc_err; + } + + BN_bn2bin(dh->g, key_template[5].pValue); + + key_template[6].ulValueLen = BN_num_bytes(dh->priv_key); + key_template[6].pValue = (CK_VOID_PTR)OPENSSL_malloc( + (size_t)key_template[6].ulValueLen); + if (key_template[6].pValue == NULL) + { + PK11err(PK11_F_GET_DH_KEY, PK11_R_MALLOC_FAILURE); + goto malloc_err; + } + + BN_bn2bin(dh->priv_key, key_template[6].pValue); + + /* see find_lock array definition for more info on object locking */ + LOCK_OBJSTORE(OP_DH); + rv = pFuncList->C_FindObjectsInit(session, key_template, + ul_key_attr_count); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_DH_KEY, PK11_R_FINDOBJECTSINIT, rv); + goto err; + } + + rv = pFuncList->C_FindObjects(session, &h_key, 1, &found); + + if (rv != CKR_OK) + { + (void) pFuncList->C_FindObjectsFinal(session); + PK11err_add_data(PK11_F_GET_DH_KEY, PK11_R_FINDOBJECTS, rv); + goto err; + } + + rv = pFuncList->C_FindObjectsFinal(session); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_DH_KEY, PK11_R_FINDOBJECTSFINAL, + rv); + goto err; + } + + if (found == 0) + { + rv = pFuncList->C_CreateObject(session, + key_template, ul_key_attr_count, &h_key); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_DH_KEY, PK11_R_CREATEOBJECT, + rv); + goto err; + } + } + + if (dh_priv_num != NULL) + if ((*dh_priv_num = BN_dup(dh->priv_key)) == NULL) + { + PK11err(PK11_F_GET_DH_KEY, PK11_R_MALLOC_FAILURE); + rollback = TRUE; + goto err; + } + + /* LINTED: E_CONSTANT_CONDITION */ + KEY_HANDLE_REFHOLD(h_key, OP_DH, FALSE, rollback, err); + if (key_ptr != NULL) + *key_ptr = dh; + +err: + if (rollback) + { + /* + * We do not care about the return value from C_DestroyObject() + * since we are doing rollback. + */ + if (found == 0) + (void) pFuncList->C_DestroyObject(session, h_key); + h_key = CK_INVALID_HANDLE; + } + + UNLOCK_OBJSTORE(OP_DH); + +malloc_err: + for (i = 4; i <= 6; i++) + { + if (key_template[i].pValue != NULL) + { + OPENSSL_free(key_template[i].pValue); + key_template[i].pValue = NULL; + } + } + + return (h_key); + } + +/* + * Check for cache miss and clean the object pointer and handle + * in such case. Return 1 for cache hit, 0 for cache miss. + * + * Note: we rely on pk11_destroy_dh_key_objects() to set sp->opdata_dh + * to CK_INVALID_HANDLE even when it fails to destroy the object. + */ +static int check_new_dh_key(PK11_SESSION *sp, DH *dh) + { + /* + * Provide protection against DH structure reuse by making the + * check for cache hit stronger. Private key component of DH key + * is unique so it is sufficient to compare it with value cached + * in PK11_SESSION structure. + */ + if ((sp->opdata_dh != dh) || + (BN_cmp(sp->opdata_dh_priv_num, dh->priv_key) != 0)) + { + /* + * We do not check the return value because even in case of + * failure the sp structure will have both key pointer + * and object handle cleaned and pk11_destroy_object() + * reports the failure to the OpenSSL error message buffer. + */ + (void) pk11_destroy_dh_object(sp, TRUE); + return (0); + } + return (1); + } +#endif + +/* + * Local function to simplify key template population + * Return 0 -- error, 1 -- no error + */ +static int +init_template_value(BIGNUM *bn, CK_VOID_PTR *p_value, + CK_ULONG *ul_value_len) + { + CK_ULONG len = 0; + + /* + * This function can be used on non-initialized BIGNUMs. It is + * easier to check that here than individually in the callers. + */ + if (bn != NULL) + len = BN_num_bytes(bn); + + if (bn == NULL || len == 0) + return (1); + + *ul_value_len = len; + *p_value = (CK_VOID_PTR)OPENSSL_malloc((size_t)*ul_value_len); + if (*p_value == NULL) + return (0); + + BN_bn2bin(bn, *p_value); + + return (1); + } + +static void +attr_to_BN(CK_ATTRIBUTE_PTR attr, CK_BYTE attr_data[], BIGNUM **bn) + { + if (attr->ulValueLen > 0) + *bn = BN_bin2bn(attr_data, attr->ulValueLen, NULL); + } + +/* + * Find one object in the token. It is an error if we can not find the + * object or if we find more objects based on the template we got. + * Assume object store locked. + * + * Returns: + * 1 OK + * 0 no object or more than 1 object found + */ +static int +find_one_object(PK11_OPTYPE op, CK_SESSION_HANDLE s, + CK_ATTRIBUTE_PTR ptempl, CK_ULONG nattr, CK_OBJECT_HANDLE_PTR pkey) + { + CK_RV rv; + CK_ULONG objcnt; + + if ((rv = pFuncList->C_FindObjectsInit(s, ptempl, nattr)) != CKR_OK) + { + PK11err_add_data(PK11_F_FIND_ONE_OBJECT, + PK11_R_FINDOBJECTSINIT, rv); + return (0); + } + + rv = pFuncList->C_FindObjects(s, pkey, 1, &objcnt); + if (rv != CKR_OK) + { + (void) pFuncList->C_FindObjectsFinal(s); + PK11err_add_data(PK11_F_FIND_ONE_OBJECT, PK11_R_FINDOBJECTS, + rv); + return (0); + } + + (void) pFuncList->C_FindObjectsFinal(s); + + if (objcnt > 1) + { + PK11err(PK11_F_FIND_ONE_OBJECT, + PK11_R_MORE_THAN_ONE_OBJECT_FOUND); + return (0); + } + else if (objcnt == 0) + { + PK11err(PK11_F_FIND_ONE_OBJECT, PK11_R_NO_OBJECT_FOUND); + return (0); + } + return (1); + } + +/* from uri stuff */ + +extern char *pk11_pin; + +static int pk11_get_pin(void); + +static int +pk11_get_pin(void) +{ + char *pin; + + /* The getpassphrase() function is not MT safe. */ +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_lock(token_lock) == 0); +#else + CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); +#endif + pin = getpassphrase("Enter PIN: "); + if (pin == NULL) + { + PK11err(PK11_F_GET_PIN, PK11_R_COULD_NOT_READ_PIN); +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0); +#else + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + return (0); + } + pk11_pin = BUF_strdup(pin); + if (pk11_pin == NULL) + { + PK11err(PK11_F_LOAD_PRIVKEY, PK11_R_MALLOC_FAILURE); +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0); +#else + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + return (0); + } + memset(pin, 0, strlen(pin)); +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0); +#else + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + return (1); + } + +/* + * Log in to the keystore if we are supposed to do that at all. Take care of + * reading and caching the PIN etc. Log in only once even when called from + * multiple threads. + * + * Returns: + * 1 on success + * 0 on failure + */ +static int +pk11_token_login(CK_SESSION_HANDLE session, CK_BBOOL *login_done, + CK_BBOOL is_private) + { + CK_RV rv; + +#if 0 + /* doesn't work on the AEP Keyper??? */ + if ((pubkey_token_flags & CKF_TOKEN_INITIALIZED) == 0) + { + PK11err(PK11_F_TOKEN_LOGIN, + PK11_R_TOKEN_NOT_INITIALIZED); + return (0); + } +#endif + + /* + * If login is required or needed but the PIN has not been + * even initialized we can bail out right now. Note that we + * are supposed to always log in if we are going to access + * private keys. However, we may need to log in even for + * accessing public keys in case that the CKF_LOGIN_REQUIRED + * flag is set. + */ + if (((pubkey_token_flags & CKF_LOGIN_REQUIRED) || + (is_private == CK_TRUE)) && + (~pubkey_token_flags & CKF_USER_PIN_INITIALIZED)) + { + PK11err(PK11_F_TOKEN_LOGIN, PK11_R_TOKEN_PIN_NOT_SET); + return (0); + } + + /* + * Note on locking: it is possible that more than one thread + * gets into pk11_get_pin() so we must deal with that. We + * cannot avoid it since we cannot guard fork() in there with + * a lock because we could end up in a dead lock in the + * child. Why? Remember we are in a multithreaded environment + * so we must lock all mutexes in the prefork function to + * avoid a situation in which a thread that did not call + * fork() held a lock, making future unlocking impossible. We + * lock right before C_Login(). + */ + if ((pubkey_token_flags & CKF_LOGIN_REQUIRED) || + (is_private == CK_TRUE)) + { + if (*login_done == CK_FALSE) + { + if ((pk11_pin == NULL) && (pk11_get_pin() == 0)) + { + PK11err(PK11_F_TOKEN_LOGIN, + PK11_R_TOKEN_PIN_NOT_PROVIDED); + return (0); + } + } + + /* + * Note that what we are logging into is the keystore from + * pubkey_SLOTID because we work with OP_RSA session type here. + * That also means that we can work with only one keystore in + * the engine. + * + * We must make sure we do not try to login more than once. + * Also, see the comment above on locking strategy. + */ + +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_lock(token_lock) == 0); +#else + CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); +#endif + if (*login_done == CK_FALSE) + { + if ((rv = pFuncList->C_Login(session, + CKU_USER, (CK_UTF8CHAR*)pk11_pin, + strlen(pk11_pin))) != CKR_OK) + { + PK11err_add_data(PK11_F_TOKEN_LOGIN, + PK11_R_TOKEN_LOGIN_FAILED, rv); + goto err_locked; + } + + *login_done = CK_TRUE; + + } +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0); +#else + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + } + else + { + /* + * If token does not require login we take it as the + * login was done. + */ + *login_done = CK_TRUE; + } + + return (1); + +err_locked: + if (pk11_pin) { + memset(pk11_pin, 0, strlen(pk11_pin)); + OPENSSL_free((void*)pk11_pin); + } + pk11_pin = NULL; +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0); +#else + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + return (0); + } + +/* + * Log in to the keystore in the child if we were logged in in the + * parent. There are similarities in the code with pk11_token_login() + * but still it is quite different so we need a separate function for + * this. + * + * Note that this function is called under the locked session mutex when fork is + * detected. That means that C_Login() will be called from the child just once. + * + * Returns: + * 1 on success + * 0 on failure + */ +int +pk11_token_relogin(CK_SESSION_HANDLE session) + { + CK_RV rv; + + if ((pk11_pin == NULL) && (pk11_get_pin() == 0)) + return (0); + +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_lock(token_lock) == 0); +#else + CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); +#endif + if ((rv = pFuncList->C_Login(session, CKU_USER, + (CK_UTF8CHAR_PTR)pk11_pin, strlen(pk11_pin))) != CKR_OK) + { + PK11err_add_data(PK11_F_TOKEN_RELOGIN, + PK11_R_TOKEN_LOGIN_FAILED, rv); +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0); +#else + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + return (0); + } +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0); +#else + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + + return (1); + } + +#ifdef OPENSSL_SYS_WIN32 +char *getpassphrase(const char *prompt) + { + static char buf[128]; + HANDLE h; + DWORD cc, mode; + int cnt; + + h = GetStdHandle(STD_INPUT_HANDLE); + fputs(prompt, stderr); + fflush(stderr); + fflush(stdout); + FlushConsoleInputBuffer(h); + GetConsoleMode(h, &mode); + SetConsoleMode(h, ENABLE_PROCESSED_INPUT); + + for (cnt = 0; cnt < sizeof(buf) - 1; cnt++) + { + ReadFile(h, buf + cnt, 1, &cc, NULL); + if (buf[cnt] == '\r') + break; + fputc('*', stdout); + fflush(stderr); + fflush(stdout); + } + + SetConsoleMode(h, mode); + buf[cnt] = '\0'; + fputs("\n", stderr); + return buf; + } +#endif /* OPENSSL_SYS_WIN32 */ +#endif /* OPENSSL_NO_HW_PK11CA */ +#endif /* OPENSSL_NO_HW_PK11 */ +#endif /* OPENSSL_NO_HW */ Index: openssl/crypto/engine/hw_pk11ca.h diff -u /dev/null openssl/crypto/engine/hw_pk11ca.h:1.4 --- /dev/null Wed Dec 23 17:47:11 2015 +++ openssl/crypto/engine/hw_pk11ca.h Wed Jun 15 21:12:20 2011 @@ -0,0 +1,32 @@ +/* Redefine all pk11/PK11 external symbols to pk11ca/PK11CA */ + +#define token_lock pk11ca_token_lock +#define find_lock pk11ca_find_lock +#define active_list pk11ca_active_list +#define pubkey_token_flags pk11ca_pubkey_token_flags +#define pubkey_SLOTID pk11ca_pubkey_SLOTID +#define ERR_pk11_error ERR_pk11ca_error +#define PK11err_add_data PK11CAerr_add_data +#define pk11_get_session pk11ca_get_session +#define pk11_return_session pk11ca_return_session +#define pk11_active_add pk11ca_active_add +#define pk11_active_delete pk11ca_active_delete +#define pk11_active_remove pk11ca_active_remove +#define pk11_free_active_list pk11ca_free_active_list +#define pk11_destroy_rsa_key_objects pk11ca_destroy_rsa_key_objects +#define pk11_destroy_rsa_object_pub pk11ca_destroy_rsa_object_pub +#define pk11_destroy_rsa_object_priv pk11ca_destroy_rsa_object_priv +#define pk11_load_privkey pk11ca_load_privkey +#define pk11_load_pubkey pk11ca_load_pubkey +#define PK11_RSA PK11CA_RSA +#define pk11_destroy_dsa_key_objects pk11ca_destroy_dsa_key_objects +#define pk11_destroy_dsa_object_pub pk11ca_destroy_dsa_object_pub +#define pk11_destroy_dsa_object_priv pk11ca_destroy_dsa_object_priv +#define PK11_DSA PK11CA_DSA +#define pk11_destroy_dh_key_objects pk11ca_destroy_dh_key_objects +#define pk11_destroy_dh_object pk11ca_destroy_dh_object +#define PK11_DH PK11CA_DH +#define pk11_token_relogin pk11ca_token_relogin +#define pFuncList pk11ca_pFuncList +#define pk11_pin pk11ca_pin +#define ENGINE_load_pk11 ENGINE_load_pk11ca Index: openssl/crypto/engine/hw_pk11so.c diff -u /dev/null openssl/crypto/engine/hw_pk11so.c:1.7.4.1 --- /dev/null Wed Dec 23 17:47:11 2015 +++ openssl/crypto/engine/hw_pk11so.c Fri Oct 4 14:33:56 2013 @@ -0,0 +1,1775 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* crypto/engine/hw_pk11.c */ +/* + * This product includes software developed by the OpenSSL Project for + * use in the OpenSSL Toolkit (http://www.openssl.org/). + * + * This project also referenced hw_pkcs11-0.9.7b.patch written by + * Afchine Madjlessi. + */ +/* + * ==================================================================== + * Copyright (c) 2000-2001 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +/* Modified to keep only RNG and RSA Sign */ + +#ifdef OPENSSL_NO_RSA +#error RSA is disabled +#endif + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef OPENSSL_SYS_WIN32 +typedef int pid_t; +#define getpid() GetCurrentProcessId() +#define NOPTHREADS +#ifndef NULL_PTR +#define NULL_PTR NULL +#endif +#define CK_DEFINE_FUNCTION(returnType, name) \ + returnType __declspec(dllexport) name +#define CK_DECLARE_FUNCTION(returnType, name) \ + returnType __declspec(dllimport) name +#define CK_DECLARE_FUNCTION_POINTER(returnType, name) \ + returnType __declspec(dllimport) (* name) +#else +#include +#include +#include +#endif + +/* Debug mutexes */ +/*#undef DEBUG_MUTEX */ +#define DEBUG_MUTEX + +#ifndef NOPTHREADS +/* for pthread error check on Linuxes */ +#ifdef DEBUG_MUTEX +#define __USE_UNIX98 +#endif +#include +#endif + +#ifndef OPENSSL_NO_HW +#ifndef OPENSSL_NO_HW_PK11 +#ifndef OPENSSL_NO_HW_PK11SO + +/* label for debug messages printed on stderr */ +#define PK11_DBG "PKCS#11 ENGINE DEBUG" +/* prints a lot of debug messages on stderr about slot selection process */ +/*#undef DEBUG_SLOT_SELECTION */ + +#ifndef OPENSSL_NO_DSA +#define OPENSSL_NO_DSA +#endif +#ifndef OPENSSL_NO_DH +#define OPENSSL_NO_DH +#endif + +#ifdef OPENSSL_SYS_WIN32 +#pragma pack(push, cryptoki, 1) +#include "cryptoki.h" +#include "pkcs11.h" +#pragma pack(pop, cryptoki) +#else +#include "cryptoki.h" +#include "pkcs11.h" +#endif +#include "hw_pk11so.h" +#include "hw_pk11_err.c" + +/* + * We use this lock to prevent multiple C_Login()s, guard getpassphrase(), + * uri_struct manipulation, and static token info. All of that is used by the + * RSA keys by reference feature. + */ +#ifndef NOPTHREADS +pthread_mutex_t *token_lock; +#endif + +/* PKCS#11 session caches and their locks for all operation types */ +static PK11_CACHE session_cache[OP_MAX]; + +/* + * We cache the flags so that we do not have to run C_GetTokenInfo() again when + * logging into the token. + */ +CK_FLAGS pubkey_token_flags; + +/* + * As stated in v2.20, 11.7 Object Management Function, in section for + * C_FindObjectsInit(), at most one search operation may be active at a given + * time in a given session. Therefore, C_Find{,Init,Final}Objects() should be + * grouped together to form one atomic search operation. This is already + * ensured by the property of unique PKCS#11 session handle used for each + * PK11_SESSION object. + * + * This is however not the biggest concern - maintaining consistency of the + * underlying object store is more important. The same section of the spec also + * says that one thread can be in the middle of a search operation while another + * thread destroys the object matching the search template which would result in + * invalid handle returned from the search operation. + * + * Hence, the following locks are used for both protection of the object stores. + * They are also used for active list protection. + */ +#ifndef NOPTHREADS +pthread_mutex_t *find_lock[OP_MAX] = { NULL }; +#endif + +/* + * lists of asymmetric key handles which are active (referenced by at least one + * PK11_SESSION structure, either held by a thread or present in free_session + * list) for given algorithm type + */ +PK11_active *active_list[OP_MAX] = { NULL }; + +/* + * Create all secret key objects in a global session so that they are available + * to use for other sessions. These other sessions may be opened or closed + * without losing the secret key objects. + */ +static CK_SESSION_HANDLE global_session = CK_INVALID_HANDLE; + +/* ENGINE level stuff */ +static int pk11_init(ENGINE *e); +static int pk11_library_init(ENGINE *e); +static int pk11_finish(ENGINE *e); +static int pk11_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void)); +static int pk11_destroy(ENGINE *e); + +/* RAND stuff */ +static void pk11_rand_seed(const void *buf, int num); +static void pk11_rand_add(const void *buf, int num, double add_entropy); +static void pk11_rand_cleanup(void); +static int pk11_rand_bytes(unsigned char *buf, int num); +static int pk11_rand_status(void); + +/* These functions are also used in other files */ +PK11_SESSION *pk11_get_session(PK11_OPTYPE optype); +void pk11_return_session(PK11_SESSION *sp, PK11_OPTYPE optype); + +/* active list manipulation functions used in this file */ +extern int pk11_active_delete(CK_OBJECT_HANDLE h, PK11_OPTYPE type); +extern void pk11_free_active_list(PK11_OPTYPE type); + +int pk11_destroy_rsa_key_objects(PK11_SESSION *session); +int pk11_destroy_rsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock); +int pk11_destroy_rsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock); + +/* Local helper functions */ +static int pk11_free_all_sessions(void); +static int pk11_free_session_list(PK11_OPTYPE optype); +static int pk11_setup_session(PK11_SESSION *sp, PK11_OPTYPE optype); +static int pk11_destroy_object(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE oh, + CK_BBOOL persistent); +static const char *get_PK11_LIBNAME(void); +static void free_PK11_LIBNAME(void); +static long set_PK11_LIBNAME(const char *name); + +static int pk11_choose_slots(int *any_slot_found); + +static int pk11_init_all_locks(void); +static void pk11_free_all_locks(void); + +#define TRY_OBJ_DESTROY(sp, obj_hdl, retval, uselock, alg_type, priv) \ + { \ + if (uselock) \ + LOCK_OBJSTORE(alg_type); \ + if (pk11_active_delete(obj_hdl, alg_type) == 1) \ + { \ + retval = pk11_destroy_object(sp->session, obj_hdl, \ + priv ? sp->priv_persistent : sp->pub_persistent); \ + } \ + if (uselock) \ + UNLOCK_OBJSTORE(alg_type); \ + } + +static CK_BBOOL pk11_have_rsa = CK_FALSE; +static CK_BBOOL pk11_have_random = CK_FALSE; + +/* + * Initialization function. Sets up various PKCS#11 library components. + * The definitions for control commands specific to this engine + */ +#define PK11_CMD_SO_PATH ENGINE_CMD_BASE +#define PK11_CMD_PIN (ENGINE_CMD_BASE+1) +#define PK11_CMD_SLOT (ENGINE_CMD_BASE+2) +static const ENGINE_CMD_DEFN pk11_cmd_defns[] = + { + { + PK11_CMD_SO_PATH, + "SO_PATH", + "Specifies the path to the 'pkcs#11' shared library", + ENGINE_CMD_FLAG_STRING + }, + { + PK11_CMD_PIN, + "PIN", + "Specifies the pin code", + ENGINE_CMD_FLAG_STRING + }, + { + PK11_CMD_SLOT, + "SLOT", + "Specifies the slot (default is auto select)", + ENGINE_CMD_FLAG_NUMERIC, + }, + {0, NULL, NULL, 0} + }; + + +static RAND_METHOD pk11_random = + { + pk11_rand_seed, + pk11_rand_bytes, + pk11_rand_cleanup, + pk11_rand_add, + pk11_rand_bytes, + pk11_rand_status + }; + + +/* Constants used when creating the ENGINE */ +#ifdef OPENSSL_NO_HW_PK11CA +#error "can't load both crypto-accelerator and sign-only PKCS#11 engines" +#endif +static const char *engine_pk11_id = "pkcs11"; +static const char *engine_pk11_name = "PKCS #11 engine support (sign only)"; + +CK_FUNCTION_LIST_PTR pFuncList = NULL; +static const char PK11_GET_FUNCTION_LIST[] = "C_GetFunctionList"; + +/* + * This is a static string constant for the DSO file name and the function + * symbol names to bind to. We set it in the Configure script based on whether + * this is 32 or 64 bit build. + */ +static const char def_PK11_LIBNAME[] = PK11_LIB_LOCATION; + +/* Needed in hw_pk11_pub.c as well so that's why it is not static. */ +CK_SLOT_ID pubkey_SLOTID = 0; +static CK_SLOT_ID rand_SLOTID = 0; +static CK_SLOT_ID SLOTID = 0; +char *pk11_pin = NULL; +static CK_BBOOL pk11_library_initialized = FALSE; +static CK_BBOOL pk11_atfork_initialized = FALSE; +static int pk11_pid = 0; + +static DSO *pk11_dso = NULL; + +/* allocate and initialize all locks used by the engine itself */ +static int pk11_init_all_locks(void) + { +#ifndef NOPTHREADS + int type; + pthread_mutexattr_t attr; + + if (pthread_mutexattr_init(&attr) != 0) + { + PK11err(PK11_F_INIT_ALL_LOCKS, 100); + return (0); + } + +#ifdef DEBUG_MUTEX + if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK) != 0) + { + PK11err(PK11_F_INIT_ALL_LOCKS, 101); + return (0); + } +#endif + + if ((token_lock = OPENSSL_malloc(sizeof (pthread_mutex_t))) == NULL) + goto malloc_err; + (void) pthread_mutex_init(token_lock, &attr); + + find_lock[OP_RSA] = OPENSSL_malloc(sizeof (pthread_mutex_t)); + if (find_lock[OP_RSA] == NULL) + goto malloc_err; + (void) pthread_mutex_init(find_lock[OP_RSA], &attr); + + for (type = 0; type < OP_MAX; type++) + { + session_cache[type].lock = + OPENSSL_malloc(sizeof (pthread_mutex_t)); + if (session_cache[type].lock == NULL) + goto malloc_err; + (void) pthread_mutex_init(session_cache[type].lock, &attr); + } + + return (1); + +malloc_err: + pk11_free_all_locks(); + PK11err(PK11_F_INIT_ALL_LOCKS, PK11_R_MALLOC_FAILURE); + return (0); +#else + return (1); +#endif + } + +static void pk11_free_all_locks(void) + { +#ifndef NOPTHREADS + int type; + + if (token_lock != NULL) + { + (void) pthread_mutex_destroy(token_lock); + OPENSSL_free(token_lock); + token_lock = NULL; + } + + if (find_lock[OP_RSA] != NULL) + { + (void) pthread_mutex_destroy(find_lock[OP_RSA]); + OPENSSL_free(find_lock[OP_RSA]); + find_lock[OP_RSA] = NULL; + } + + for (type = 0; type < OP_MAX; type++) + { + if (session_cache[type].lock != NULL) + { + (void) pthread_mutex_destroy(session_cache[type].lock); + OPENSSL_free(session_cache[type].lock); + session_cache[type].lock = NULL; + } + } +#endif + } + +/* + * This internal function is used by ENGINE_pk11() and "dynamic" ENGINE support. + */ +static int bind_pk11(ENGINE *e) + { + if (!pk11_library_initialized) + if (!pk11_library_init(e)) + return (0); + + if (!ENGINE_set_id(e, engine_pk11_id) || + !ENGINE_set_name(e, engine_pk11_name)) + return (0); + + if (pk11_have_rsa == CK_TRUE) + { + if (!ENGINE_set_RSA(e, PK11_RSA()) || + !ENGINE_set_load_privkey_function(e, pk11_load_privkey) || + !ENGINE_set_load_pubkey_function(e, pk11_load_pubkey)) + return (0); +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: registered RSA\n", PK11_DBG); +#endif /* DEBUG_SLOT_SELECTION */ + } + + if (pk11_have_random) + { + if (!ENGINE_set_RAND(e, &pk11_random)) + return (0); +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: registered random\n", PK11_DBG); +#endif /* DEBUG_SLOT_SELECTION */ + } + if (!ENGINE_set_init_function(e, pk11_init) || + !ENGINE_set_destroy_function(e, pk11_destroy) || + !ENGINE_set_finish_function(e, pk11_finish) || + !ENGINE_set_ctrl_function(e, pk11_ctrl) || + !ENGINE_set_cmd_defns(e, pk11_cmd_defns)) + return (0); + + /* Ensure the pk11 error handling is set up */ + ERR_load_pk11_strings(); + + return (1); + } + +/* Dynamic engine support is disabled at a higher level for Solaris */ +#ifdef ENGINE_DYNAMIC_SUPPORT +#error "dynamic engine not supported" +static int bind_helper(ENGINE *e, const char *id) + { + if (id && (strcmp(id, engine_pk11_id) != 0)) + return (0); + + if (!bind_pk11(e)) + return (0); + + return (1); + } + +IMPLEMENT_DYNAMIC_CHECK_FN() +IMPLEMENT_DYNAMIC_BIND_FN(bind_helper) + +#else +static ENGINE *engine_pk11(void) + { + ENGINE *ret = ENGINE_new(); + + if (!ret) + return (NULL); + + if (!bind_pk11(ret)) + { + ENGINE_free(ret); + return (NULL); + } + + return (ret); + } + +void +ENGINE_load_pk11(void) + { + ENGINE *e_pk11 = NULL; + + /* + * Do not use dynamic PKCS#11 library on Solaris due to + * security reasons. We will link it in statically. + */ + /* Attempt to load PKCS#11 library */ + if (!pk11_dso) + pk11_dso = DSO_load(NULL, get_PK11_LIBNAME(), NULL, 0); + + if (pk11_dso == NULL) + { + PK11err(PK11_F_LOAD, PK11_R_DSO_FAILURE); + return; + } + + e_pk11 = engine_pk11(); + if (!e_pk11) + { + DSO_free(pk11_dso); + pk11_dso = NULL; + return; + } + + /* + * At this point, the pk11 shared library is either dynamically + * loaded or statically linked in. So, initialize the pk11 + * library before calling ENGINE_set_default since the latter + * needs cipher and digest algorithm information + */ + if (!pk11_library_init(e_pk11)) + { + DSO_free(pk11_dso); + pk11_dso = NULL; + ENGINE_free(e_pk11); + return; + } + + ENGINE_add(e_pk11); + + ENGINE_free(e_pk11); + ERR_clear_error(); + } +#endif /* ENGINE_DYNAMIC_SUPPORT */ + +/* + * These are the static string constants for the DSO file name and + * the function symbol names to bind to. + */ +static const char *PK11_LIBNAME = NULL; + +static const char *get_PK11_LIBNAME(void) + { + if (PK11_LIBNAME) + return (PK11_LIBNAME); + + return (def_PK11_LIBNAME); + } + +static void free_PK11_LIBNAME(void) + { + if (PK11_LIBNAME) + OPENSSL_free((void*)PK11_LIBNAME); + + PK11_LIBNAME = NULL; + } + +static long set_PK11_LIBNAME(const char *name) + { + free_PK11_LIBNAME(); + + return ((PK11_LIBNAME = BUF_strdup(name)) != NULL ? 1 : 0); + } + +/* acquire all engine specific mutexes before fork */ +static void pk11_fork_prepare(void) + { +#ifndef NOPTHREADS + int i; + + if (!pk11_library_initialized) + return; + + LOCK_OBJSTORE(OP_RSA); + OPENSSL_assert(pthread_mutex_lock(token_lock) == 0); + for (i = 0; i < OP_MAX; i++) + { + OPENSSL_assert(pthread_mutex_lock(session_cache[i].lock) == 0); + } +#endif + } + +/* release all engine specific mutexes */ +static void pk11_fork_parent(void) + { +#ifndef NOPTHREADS + int i; + + if (!pk11_library_initialized) + return; + + for (i = OP_MAX - 1; i >= 0; i--) + { + OPENSSL_assert(pthread_mutex_unlock(session_cache[i].lock) == 0); + } + UNLOCK_OBJSTORE(OP_RSA); + OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0); +#endif + } + +/* + * same situation as in parent - we need to unlock all locks to make them + * accessible to all threads. + */ +static void pk11_fork_child(void) + { +#ifndef NOPTHREADS + int i; + + if (!pk11_library_initialized) + return; + + for (i = OP_MAX - 1; i >= 0; i--) + { + OPENSSL_assert(pthread_mutex_unlock(session_cache[i].lock) == 0); + } + UNLOCK_OBJSTORE(OP_RSA); + OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0); +#endif + } + +/* Initialization function for the pk11 engine */ +static int pk11_init(ENGINE *e) +{ + return (pk11_library_init(e)); +} + +static CK_C_INITIALIZE_ARGS pk11_init_args = + { + NULL_PTR, /* CreateMutex */ + NULL_PTR, /* DestroyMutex */ + NULL_PTR, /* LockMutex */ + NULL_PTR, /* UnlockMutex */ + CKF_OS_LOCKING_OK, /* flags */ + NULL_PTR, /* pReserved */ + }; + +/* + * Initialization function. Sets up various PKCS#11 library components. + * It selects a slot based on predefined critiera. In the process, it also + * count how many ciphers and digests to support. Since the cipher and + * digest information is needed when setting default engine, this function + * needs to be called before calling ENGINE_set_default. + */ +/* ARGSUSED */ +static int pk11_library_init(ENGINE *e) + { + CK_C_GetFunctionList p; + CK_RV rv = CKR_OK; + CK_INFO info; + int any_slot_found; + int i; +#ifndef OPENSSL_SYS_WIN32 + struct sigaction sigint_act, sigterm_act, sighup_act; +#endif + + /* + * pk11_library_initialized is set to 0 in pk11_finish() which + * is called from ENGINE_finish(). However, if there is still + * at least one existing functional reference to the engine + * (see engine(3) for more information), pk11_finish() is + * skipped. For example, this can happen if an application + * forgets to clear one cipher context. In case of a fork() + * when the application is finishing the engine so that it can + * be reinitialized in the child, forgotten functional + * reference causes pk11_library_initialized to stay 1. In + * that case we need the PID check so that we properly + * initialize the engine again. + */ + if (pk11_library_initialized) + { + if (pk11_pid == getpid()) + { + return (1); + } + else + { + global_session = CK_INVALID_HANDLE; + /* + * free the locks first to prevent memory leak in case + * the application calls fork() without finishing the + * engine first. + */ + pk11_free_all_locks(); + } + } + + if (pk11_dso == NULL) + { + PK11err(PK11_F_LIBRARY_INIT, PK11_R_DSO_FAILURE); + goto err; + } + + /* get the C_GetFunctionList function from the loaded library */ + p = (CK_C_GetFunctionList)DSO_bind_func(pk11_dso, + PK11_GET_FUNCTION_LIST); + if (!p) + { + PK11err(PK11_F_LIBRARY_INIT, PK11_R_DSO_FAILURE); + goto err; + } + + /* get the full function list from the loaded library */ + rv = p(&pFuncList); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_LIBRARY_INIT, PK11_R_DSO_FAILURE, rv); + goto err; + } + +#ifndef OPENSSL_SYS_WIN32 + /* Not all PKCS#11 library are signal safe! */ + + (void) memset(&sigint_act, 0, sizeof(sigint_act)); + (void) memset(&sigterm_act, 0, sizeof(sigterm_act)); + (void) memset(&sighup_act, 0, sizeof(sighup_act)); + (void) sigaction(SIGINT, NULL, &sigint_act); + (void) sigaction(SIGTERM, NULL, &sigterm_act); + (void) sigaction(SIGHUP, NULL, &sighup_act); +#endif + rv = pFuncList->C_Initialize((CK_VOID_PTR)&pk11_init_args); +#ifndef OPENSSL_SYS_WIN32 + (void) sigaction(SIGINT, &sigint_act, NULL); + (void) sigaction(SIGTERM, &sigterm_act, NULL); + (void) sigaction(SIGHUP, &sighup_act, NULL); +#endif + if ((rv != CKR_OK) && (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)) + { + PK11err_add_data(PK11_F_LIBRARY_INIT, PK11_R_INITIALIZE, rv); + goto err; + } + + rv = pFuncList->C_GetInfo(&info); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_LIBRARY_INIT, PK11_R_GETINFO, rv); + goto err; + } + + if (pk11_choose_slots(&any_slot_found) == 0) + goto err; + + /* + * The library we use, set in def_PK11_LIBNAME, may not offer any + * slot(s). In that case, we must not proceed but we must not return an + * error. The reason is that applications that try to set up the PKCS#11 + * engine don't exit on error during the engine initialization just + * because no slot was present. + */ + if (any_slot_found == 0) + return (1); + + if (global_session == CK_INVALID_HANDLE) + { + /* Open the global_session for the new process */ + rv = pFuncList->C_OpenSession(SLOTID, CKF_SERIAL_SESSION, + NULL_PTR, NULL_PTR, &global_session); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_LIBRARY_INIT, + PK11_R_OPENSESSION, rv); + goto err; + } + } + + pk11_library_initialized = TRUE; + pk11_pid = getpid(); + /* + * if initialization of the locks fails pk11_init_all_locks() + * will do the cleanup. + */ + if (!pk11_init_all_locks()) + goto err; + for (i = 0; i < OP_MAX; i++) + session_cache[i].head = NULL; + /* + * initialize active lists. We only use active lists + * for asymmetric ciphers. + */ + for (i = 0; i < OP_MAX; i++) + active_list[i] = NULL; + +#ifndef NOPTHREADS + if (!pk11_atfork_initialized) + { + if (pthread_atfork(pk11_fork_prepare, pk11_fork_parent, + pk11_fork_child) != 0) + { + PK11err(PK11_F_LIBRARY_INIT, PK11_R_ATFORK_FAILED); + goto err; + } + pk11_atfork_initialized = TRUE; + } +#endif + + return (1); + +err: + return (0); + } + +/* Destructor (complements the "ENGINE_pk11()" constructor) */ +/* ARGSUSED */ +static int pk11_destroy(ENGINE *e) + { + free_PK11_LIBNAME(); + ERR_unload_pk11_strings(); + if (pk11_pin) { + memset(pk11_pin, 0, strlen(pk11_pin)); + OPENSSL_free((void*)pk11_pin); + } + pk11_pin = NULL; + return (1); + } + +/* + * Termination function to clean up the session, the token, and the pk11 + * library. + */ +/* ARGSUSED */ +static int pk11_finish(ENGINE *e) + { + int i; + + if (pk11_pin) { + memset(pk11_pin, 0, strlen(pk11_pin)); + OPENSSL_free((void*)pk11_pin); + } + pk11_pin = NULL; + + if (pk11_dso == NULL) + { + PK11err(PK11_F_FINISH, PK11_R_NOT_LOADED); + goto err; + } + + OPENSSL_assert(pFuncList != NULL); + + if (pk11_free_all_sessions() == 0) + goto err; + + /* free all active lists */ + for (i = 0; i < OP_MAX; i++) + pk11_free_active_list(i); + + pFuncList->C_CloseSession(global_session); + global_session = CK_INVALID_HANDLE; + + /* + * Since we are part of a library (libcrypto.so), calling this function + * may have side-effects. + */ +#if 0 + pFuncList->C_Finalize(NULL); +#endif + + if (!DSO_free(pk11_dso)) + { + PK11err(PK11_F_FINISH, PK11_R_DSO_FAILURE); + goto err; + } + pk11_dso = NULL; + pFuncList = NULL; + pk11_library_initialized = FALSE; + pk11_pid = 0; + /* + * There is no way how to unregister atfork handlers (other than + * unloading the library) so we just free the locks. For this reason + * the atfork handlers check if the engine is initialized and bail out + * immediately if not. This is necessary in case a process finishes + * the engine before calling fork(). + */ + pk11_free_all_locks(); + + return (1); + +err: + return (0); + } + +/* Standard engine interface function to set the dynamic library path */ +/* ARGSUSED */ +static int pk11_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void)) + { + int initialized = ((pk11_dso == NULL) ? 0 : 1); + + switch (cmd) + { + case PK11_CMD_SO_PATH: + if (p == NULL) + { + PK11err(PK11_F_CTRL, ERR_R_PASSED_NULL_PARAMETER); + return (0); + } + + if (initialized) + { + PK11err(PK11_F_CTRL, PK11_R_ALREADY_LOADED); + return (0); + } + + return (set_PK11_LIBNAME((const char *)p)); + case PK11_CMD_PIN: + if (pk11_pin) { + memset(pk11_pin, 0, strlen(pk11_pin)); + OPENSSL_free((void*)pk11_pin); + } + pk11_pin = NULL; + + if (p == NULL) + { + PK11err(PK11_F_CTRL, ERR_R_PASSED_NULL_PARAMETER); + return (0); + } + + pk11_pin = BUF_strdup(p); + if (pk11_pin == NULL) + { + PK11err(PK11_F_GET_SESSION, PK11_R_MALLOC_FAILURE); + return (0); + } + return (1); + case PK11_CMD_SLOT: + SLOTID = (CK_SLOT_ID)i; +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: slot set\n", PK11_DBG); +#endif + return (1); + default: + break; + } + + PK11err(PK11_F_CTRL, PK11_R_CTRL_COMMAND_NOT_IMPLEMENTED); + + return (0); + } + + +/* Required function by the engine random interface. It does nothing here */ +static void pk11_rand_cleanup(void) + { + return; + } + +/* ARGSUSED */ +static void pk11_rand_add(const void *buf, int num, double add) + { + PK11_SESSION *sp; + + if ((sp = pk11_get_session(OP_RAND)) == NULL) + return; + + /* + * Ignore any errors (e.g. CKR_RANDOM_SEED_NOT_SUPPORTED) since + * the calling functions do not care anyway + */ + pFuncList->C_SeedRandom(sp->session, (unsigned char *) buf, num); + pk11_return_session(sp, OP_RAND); + + return; + } + +static void pk11_rand_seed(const void *buf, int num) + { + pk11_rand_add(buf, num, 0); + } + +static int pk11_rand_bytes(unsigned char *buf, int num) + { + CK_RV rv; + PK11_SESSION *sp; + + if ((sp = pk11_get_session(OP_RAND)) == NULL) + return (0); + + rv = pFuncList->C_GenerateRandom(sp->session, buf, num); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_RAND_BYTES, PK11_R_GENERATERANDOM, rv); + pk11_return_session(sp, OP_RAND); + return (0); + } + + pk11_return_session(sp, OP_RAND); + return (1); + } + +/* Required function by the engine random interface. It does nothing here */ +static int pk11_rand_status(void) + { + return (1); + } + +/* Free all BIGNUM structures from PK11_SESSION. */ +static void pk11_free_nums(PK11_SESSION *sp, PK11_OPTYPE optype) + { + switch (optype) + { + case OP_RSA: + if (sp->opdata_rsa_n_num != NULL) + { + BN_free(sp->opdata_rsa_n_num); + sp->opdata_rsa_n_num = NULL; + } + if (sp->opdata_rsa_e_num != NULL) + { + BN_free(sp->opdata_rsa_e_num); + sp->opdata_rsa_e_num = NULL; + } + if (sp->opdata_rsa_pn_num != NULL) + { + BN_free(sp->opdata_rsa_pn_num); + sp->opdata_rsa_pn_num = NULL; + } + if (sp->opdata_rsa_pe_num != NULL) + { + BN_free(sp->opdata_rsa_pe_num); + sp->opdata_rsa_pe_num = NULL; + } + if (sp->opdata_rsa_d_num != NULL) + { + BN_free(sp->opdata_rsa_d_num); + sp->opdata_rsa_d_num = NULL; + } + break; + default: + break; + } + } + +/* + * Get new PK11_SESSION structure ready for use. Every process must have + * its own freelist of PK11_SESSION structures so handle fork() here + * by destroying the old and creating new freelist. + * The returned PK11_SESSION structure is disconnected from the freelist. + */ +PK11_SESSION * +pk11_get_session(PK11_OPTYPE optype) + { + PK11_SESSION *sp = NULL, *sp1, *freelist; +#ifndef NOPTHREADS + pthread_mutex_t *freelist_lock = NULL; +#endif + static pid_t pid = 0; + pid_t new_pid; + CK_RV rv; + + switch (optype) + { + case OP_RSA: + case OP_DSA: + case OP_DH: + case OP_RAND: + case OP_DIGEST: + case OP_CIPHER: +#ifndef NOPTHREADS + freelist_lock = session_cache[optype].lock; +#endif + break; + default: + PK11err(PK11_F_GET_SESSION, + PK11_R_INVALID_OPERATION_TYPE); + return (NULL); + } +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_lock(freelist_lock) == 0); +#else + CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); +#endif + + /* + * Will use it to find out if we forked. We cannot use the PID field in + * the session structure because we could get a newly allocated session + * here, with no PID information. + */ + if (pid == 0) + pid = getpid(); + + freelist = session_cache[optype].head; + sp = freelist; + + /* + * If the free list is empty, allocate new unitialized (filled + * with zeroes) PK11_SESSION structure otherwise return first + * structure from the freelist. + */ + if (sp == NULL) + { + if ((sp = OPENSSL_malloc(sizeof (PK11_SESSION))) == NULL) + { + PK11err(PK11_F_GET_SESSION, + PK11_R_MALLOC_FAILURE); + goto err; + } + (void) memset(sp, 0, sizeof (PK11_SESSION)); + + /* + * It is a new session so it will look like a cache miss to the + * code below. So, we must not try to to destroy its members so + * mark them as unused. + */ + sp->opdata_rsa_priv_key = CK_INVALID_HANDLE; + sp->opdata_rsa_pub_key = CK_INVALID_HANDLE; + } + else + { + freelist = sp->next; + } + + /* + * Check whether we have forked. In that case, we must get rid of all + * inherited sessions and start allocating new ones. + */ + if (pid != (new_pid = getpid())) + { + pid = new_pid; + + /* + * We are a new process and thus need to free any inherited + * PK11_SESSION objects aside from the first session (sp) which + * is the only PK11_SESSION structure we will reuse (for the + * head of the list). + */ + while ((sp1 = freelist) != NULL) + { + freelist = sp1->next; + /* + * NOTE: we do not want to call pk11_free_all_sessions() + * here because it would close underlying PKCS#11 + * sessions and destroy all objects. + */ + pk11_free_nums(sp1, optype); + OPENSSL_free(sp1); + } + + /* we have to free the active list as well. */ + pk11_free_active_list(optype); + + /* Initialize the process */ + rv = pFuncList->C_Initialize((CK_VOID_PTR)&pk11_init_args); + if ((rv != CKR_OK) && (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)) + { + PK11err_add_data(PK11_F_GET_SESSION, PK11_R_INITIALIZE, + rv); + OPENSSL_free(sp); + sp = NULL; + goto err; + } + + /* + * Choose slot here since the slot table is different on this + * process. If we are here then we must have found at least one + * usable slot before so we don't need to check any_slot_found. + * See pk11_library_init()'s usage of this function for more + * information. + */ + if (pk11_choose_slots(NULL) == 0) + goto err; + + /* Open the global_session for the new process */ + rv = pFuncList->C_OpenSession(SLOTID, CKF_SERIAL_SESSION, + NULL_PTR, NULL_PTR, &global_session); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_SESSION, PK11_R_OPENSESSION, + rv); + OPENSSL_free(sp); + sp = NULL; + goto err; + } + + /* + * It is an inherited session from our parent so it needs + * re-initialization. + */ + if (pk11_setup_session(sp, optype) == 0) + { + OPENSSL_free(sp); + sp = NULL; + goto err; + } + if (pk11_token_relogin(sp->session) == 0) + { + /* + * We will keep the session in the cache list and let + * the caller cope with the situation. + */ + freelist = sp; + sp = NULL; + goto err; + } + } + + if (sp->pid == 0) + { + /* It is a new session and needs initialization. */ + if (pk11_setup_session(sp, optype) == 0) + { + OPENSSL_free(sp); + sp = NULL; + } + } + + /* set new head for the list of PK11_SESSION objects */ + session_cache[optype].head = freelist; + +err: + if (sp != NULL) + sp->next = NULL; + +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_unlock(freelist_lock) == 0); +#else + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + + return (sp); + } + + +void +pk11_return_session(PK11_SESSION *sp, PK11_OPTYPE optype) + { +#ifndef NOPTHREADS + pthread_mutex_t *freelist_lock; +#endif + PK11_SESSION *freelist; + + /* + * If this is a session from the parent it will be taken care of and + * freed in pk11_get_session() as part of the post-fork clean up the + * next time we will ask for a new session. + */ + if (sp == NULL || sp->pid != getpid()) + return; + + switch (optype) + { + case OP_RSA: + case OP_DSA: + case OP_DH: + case OP_RAND: + case OP_DIGEST: + case OP_CIPHER: +#ifndef NOPTHREADS + freelist_lock = session_cache[optype].lock; +#endif + break; + default: + PK11err(PK11_F_RETURN_SESSION, + PK11_R_INVALID_OPERATION_TYPE); + return; + } + +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_lock(freelist_lock) == 0); +#else + CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); +#endif + freelist = session_cache[optype].head; + sp->next = freelist; + session_cache[optype].head = sp; +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_unlock(freelist_lock) == 0); +#else + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + } + + +/* Destroy all objects. This function is called when the engine is finished */ +static int pk11_free_all_sessions() + { + int ret = 1; + int type; + + (void) pk11_destroy_rsa_key_objects(NULL); + + /* + * We try to release as much as we can but any error means that we will + * return 0 on exit. + */ + for (type = 0; type < OP_MAX; type++) + { + if (pk11_free_session_list(type) == 0) + ret = 0; + } + + return (ret); + } + +/* + * Destroy session structures from the linked list specified. Free as many + * sessions as possible but any failure in C_CloseSession() means that we + * return an error on return. + */ +static int pk11_free_session_list(PK11_OPTYPE optype) + { + CK_RV rv; + PK11_SESSION *sp = NULL; + PK11_SESSION *freelist = NULL; + pid_t mypid = getpid(); +#ifndef NOPTHREADS + pthread_mutex_t *freelist_lock; +#endif + int ret = 1; + + switch (optype) + { + case OP_RSA: + case OP_DSA: + case OP_DH: + case OP_RAND: + case OP_DIGEST: + case OP_CIPHER: +#ifndef NOPTHREADS + freelist_lock = session_cache[optype].lock; +#endif + break; + default: + PK11err(PK11_F_FREE_ALL_SESSIONS, + PK11_R_INVALID_OPERATION_TYPE); + return (0); + } + +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_lock(freelist_lock) == 0); +#else + CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); +#endif + freelist = session_cache[optype].head; + while ((sp = freelist) != NULL) + { + if (sp->session != CK_INVALID_HANDLE && sp->pid == mypid) + { + rv = pFuncList->C_CloseSession(sp->session); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_FREE_ALL_SESSIONS, + PK11_R_CLOSESESSION, rv); + ret = 0; + } + } + freelist = sp->next; + pk11_free_nums(sp, optype); + OPENSSL_free(sp); + } + +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_unlock(freelist_lock) == 0); +#else + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + return (ret); + } + + +static int +pk11_setup_session(PK11_SESSION *sp, PK11_OPTYPE optype) + { + CK_RV rv; + CK_SLOT_ID myslot; + + switch (optype) + { + case OP_RSA: + myslot = pubkey_SLOTID; + break; + case OP_RAND: + myslot = rand_SLOTID; + break; + default: + PK11err(PK11_F_SETUP_SESSION, + PK11_R_INVALID_OPERATION_TYPE); + return (0); + } + + sp->session = CK_INVALID_HANDLE; +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: myslot=%d optype=%d\n", PK11_DBG, myslot, optype); +#endif /* DEBUG_SLOT_SELECTION */ + rv = pFuncList->C_OpenSession(myslot, CKF_SERIAL_SESSION, + NULL_PTR, NULL_PTR, &sp->session); + if (rv == CKR_CRYPTOKI_NOT_INITIALIZED) + { + /* + * We are probably a child process so force the + * reinitialize of the session + */ + pk11_library_initialized = FALSE; + if (!pk11_library_init(NULL)) + return (0); + rv = pFuncList->C_OpenSession(myslot, CKF_SERIAL_SESSION, + NULL_PTR, NULL_PTR, &sp->session); + } + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_SETUP_SESSION, PK11_R_OPENSESSION, rv); + return (0); + } + + sp->pid = getpid(); + + if (optype == OP_RSA) + { + sp->opdata_rsa_pub_key = CK_INVALID_HANDLE; + sp->opdata_rsa_priv_key = CK_INVALID_HANDLE; + sp->opdata_rsa_pub = NULL; + sp->opdata_rsa_n_num = NULL; + sp->opdata_rsa_e_num = NULL; + sp->opdata_rsa_priv = NULL; + sp->opdata_rsa_pn_num = NULL; + sp->opdata_rsa_pe_num = NULL; + sp->opdata_rsa_d_num = NULL; + } + + /* + * We always initialize the session as containing a non-persistent + * object. The key load functions set it to persistent if that is so. + */ + sp->pub_persistent = CK_FALSE; + sp->priv_persistent = CK_FALSE; + return (1); + } + +/* Destroy RSA public key from single session. */ +int +pk11_destroy_rsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock) + { + int ret = 0; + + if (sp->opdata_rsa_pub_key != CK_INVALID_HANDLE) + { + TRY_OBJ_DESTROY(sp, sp->opdata_rsa_pub_key, + ret, uselock, OP_RSA, CK_FALSE); + sp->opdata_rsa_pub_key = CK_INVALID_HANDLE; + sp->opdata_rsa_pub = NULL; + if (sp->opdata_rsa_n_num != NULL) + { + BN_free(sp->opdata_rsa_n_num); + sp->opdata_rsa_n_num = NULL; + } + if (sp->opdata_rsa_e_num != NULL) + { + BN_free(sp->opdata_rsa_e_num); + sp->opdata_rsa_e_num = NULL; + } + } + + return (ret); + } + +/* Destroy RSA private key from single session. */ +int +pk11_destroy_rsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock) + { + int ret = 0; + + if (sp->opdata_rsa_priv_key != CK_INVALID_HANDLE) + { + TRY_OBJ_DESTROY(sp, sp->opdata_rsa_priv_key, + ret, uselock, OP_RSA, CK_TRUE); + sp->opdata_rsa_priv_key = CK_INVALID_HANDLE; + sp->opdata_rsa_priv = NULL; + if (sp->opdata_rsa_d_num != NULL) + { + BN_free(sp->opdata_rsa_d_num); + sp->opdata_rsa_d_num = NULL; + } + + /* + * For the RSA key by reference code, public components 'n'/'e' + * are the key components we use to check for the cache hit. We + * must free those as well. + */ + if (sp->opdata_rsa_pn_num != NULL) + { + BN_free(sp->opdata_rsa_pn_num); + sp->opdata_rsa_pn_num = NULL; + } + if (sp->opdata_rsa_pe_num != NULL) + { + BN_free(sp->opdata_rsa_pe_num); + sp->opdata_rsa_pe_num = NULL; + } + } + + return (ret); + } + +/* + * Destroy RSA key object wrapper. If session is NULL, try to destroy all + * objects in the free list. + */ +int +pk11_destroy_rsa_key_objects(PK11_SESSION *session) + { + int ret = 1; + PK11_SESSION *sp = NULL; + PK11_SESSION *local_free_session; + CK_BBOOL uselock = TRUE; + + if (session != NULL) + local_free_session = session; + else + { +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_lock(session_cache[OP_RSA].lock) == 0); +#else + CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); +#endif + local_free_session = session_cache[OP_RSA].head; + uselock = FALSE; + } + + /* + * go through the list of sessions and delete key objects + */ + while ((sp = local_free_session) != NULL) + { + local_free_session = sp->next; + + /* + * Do not terminate list traversal if one of the + * destroy operations fails. + */ + if (pk11_destroy_rsa_object_pub(sp, uselock) == 0) + { + ret = 0; + continue; + } + if (pk11_destroy_rsa_object_priv(sp, uselock) == 0) + { + ret = 0; + continue; + } + } + +#ifndef NOPTHREADS + if (session == NULL) + OPENSSL_assert(pthread_mutex_unlock(session_cache[OP_RSA].lock) == 0); +#else + if (session == NULL) + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + + return (ret); + } + +static int +pk11_destroy_object(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE oh, + CK_BBOOL persistent) + { + CK_RV rv; + + /* + * We never try to destroy persistent objects which are the objects + * stored in the keystore. Also, we always use read-only sessions so + * C_DestroyObject() would be returning CKR_SESSION_READ_ONLY here. + */ + if (persistent == CK_TRUE) + return (1); + + rv = pFuncList->C_DestroyObject(session, oh); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DESTROY_OBJECT, PK11_R_DESTROYOBJECT, + rv); + return (0); + } + + return (1); + } + + +/* + * Public key mechanisms optionally supported + * + * CKM_RSA_PKCS + * + * The first slot that supports at least one of those mechanisms is chosen as a + * public key slot. + * + * The output of this function is a set of global variables indicating which + * mechanisms from RSA, DSA, DH and RAND are present, and also two arrays of + * mechanisms, one for symmetric ciphers and one for digests. Also, 3 global + * variables carry information about which slot was chosen for (a) public key + * mechanisms, (b) random operations, and (c) symmetric ciphers and digests. + */ +static int +pk11_choose_slots(int *any_slot_found) + { + CK_SLOT_ID_PTR pSlotList = NULL_PTR; + CK_ULONG ulSlotCount = 0; + CK_MECHANISM_INFO mech_info; + CK_TOKEN_INFO token_info; + unsigned int i; + CK_RV rv; + CK_SLOT_ID best_slot_sofar = 0; + CK_BBOOL found_candidate_slot = CK_FALSE; + CK_SLOT_ID current_slot = 0; + + /* let's initialize the output parameter */ + if (any_slot_found != NULL) + *any_slot_found = 0; + + /* Get slot list for memory allocation */ + rv = pFuncList->C_GetSlotList(CK_FALSE, NULL_PTR, &ulSlotCount); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_CHOOSE_SLOT, PK11_R_GETSLOTLIST, rv); + return (0); + } + + /* it's not an error if we didn't find any providers */ + if (ulSlotCount == 0) + { +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: no crypto providers found\n", PK11_DBG); +#endif /* DEBUG_SLOT_SELECTION */ + return (1); + } + + pSlotList = OPENSSL_malloc(ulSlotCount * sizeof (CK_SLOT_ID)); + + if (pSlotList == NULL) + { + PK11err(PK11_F_CHOOSE_SLOT, PK11_R_MALLOC_FAILURE); + return (0); + } + + /* Get the slot list for processing */ + rv = pFuncList->C_GetSlotList(CK_FALSE, pSlotList, &ulSlotCount); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_CHOOSE_SLOT, PK11_R_GETSLOTLIST, rv); + OPENSSL_free(pSlotList); + return (0); + } + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: provider: %s\n", PK11_DBG, def_PK11_LIBNAME); + fprintf(stderr, "%s: number of slots: %d\n", PK11_DBG, ulSlotCount); + + fprintf(stderr, "%s: == checking rand slots ==\n", PK11_DBG); +#endif /* DEBUG_SLOT_SELECTION */ + for (i = 0; i < ulSlotCount; i++) + { + current_slot = pSlotList[i]; + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: checking slot: %d\n", PK11_DBG, i); +#endif /* DEBUG_SLOT_SELECTION */ + /* Check if slot has random support. */ + rv = pFuncList->C_GetTokenInfo(current_slot, &token_info); + if (rv != CKR_OK) + continue; + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: token label: %.32s\n", PK11_DBG, token_info.label); +#endif /* DEBUG_SLOT_SELECTION */ + + if (token_info.flags & CKF_RNG) + { +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: this token has CKF_RNG flag\n", PK11_DBG); +#endif /* DEBUG_SLOT_SELECTION */ + pk11_have_random = CK_TRUE; + rand_SLOTID = current_slot; + break; + } + } + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: == checking pubkey slots ==\n", PK11_DBG); +#endif /* DEBUG_SLOT_SELECTION */ + + pubkey_SLOTID = pSlotList[0]; + for (i = 0; i < ulSlotCount; i++) + { + CK_BBOOL slot_has_rsa = CK_FALSE; + current_slot = pSlotList[i]; + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: checking slot: %d\n", PK11_DBG, i); +#endif /* DEBUG_SLOT_SELECTION */ + rv = pFuncList->C_GetTokenInfo(current_slot, &token_info); + if (rv != CKR_OK) + continue; + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: token label: %.32s\n", PK11_DBG, token_info.label); +#endif /* DEBUG_SLOT_SELECTION */ + + /* + * Check if this slot is capable of signing with CKM_RSA_PKCS. + */ + rv = pFuncList->C_GetMechanismInfo(current_slot, CKM_RSA_PKCS, + &mech_info); + + if (rv == CKR_OK && ((mech_info.flags & CKF_SIGN))) + { + slot_has_rsa = CK_TRUE; + } + + if (!found_candidate_slot && slot_has_rsa) + { +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, + "%s: potential slot: %d\n", PK11_DBG, current_slot); +#endif /* DEBUG_SLOT_SELECTION */ + best_slot_sofar = current_slot; + pk11_have_rsa = slot_has_rsa; + found_candidate_slot = CK_TRUE; + /* + * Cache the flags for later use. We might + * need those if RSA keys by reference feature + * is used. + */ + pubkey_token_flags = token_info.flags; +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, + "%s: setting found_candidate_slot to CK_TRUE\n", + PK11_DBG); + fprintf(stderr, + "%s: best so far slot: %d\n", PK11_DBG, + best_slot_sofar); + fprintf(stderr, "%s: pubkey flags changed to " + "%lu.\n", PK11_DBG, pubkey_token_flags); + } + else + { + fprintf(stderr, + "%s: no rsa\n", PK11_DBG); + } +#else + } /* if */ +#endif /* DEBUG_SLOT_SELECTION */ + } /* for */ + + if (found_candidate_slot == CK_TRUE) + { + pubkey_SLOTID = best_slot_sofar; + } + + /*SLOTID = pSlotList[0];*/ + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, + "%s: chosen pubkey slot: %d\n", PK11_DBG, pubkey_SLOTID); + fprintf(stderr, + "%s: chosen rand slot: %d\n", PK11_DBG, rand_SLOTID); + fprintf(stderr, + "%s: pk11_have_rsa %d\n", PK11_DBG, pk11_have_rsa); + fprintf(stderr, + "%s: pk11_have_random %d\n", PK11_DBG, pk11_have_random); +#endif /* DEBUG_SLOT_SELECTION */ + + if (pSlotList != NULL) + OPENSSL_free(pSlotList); + + if (any_slot_found != NULL) + *any_slot_found = 1; + return (1); + } + +#endif /* OPENSSL_NO_HW_PK11SO */ +#endif /* OPENSSL_NO_HW_PK11 */ +#endif /* OPENSSL_NO_HW */ Index: openssl/crypto/engine/hw_pk11so.h diff -u /dev/null openssl/crypto/engine/hw_pk11so.h:1.4 --- /dev/null Wed Dec 23 17:47:11 2015 +++ openssl/crypto/engine/hw_pk11so.h Wed Jun 15 21:12:20 2011 @@ -0,0 +1,32 @@ +/* Redefine all pk11/PK11 external symbols to pk11so/PK11SO */ + +#define token_lock pk11so_token_lock +#define find_lock pk11so_find_lock +#define active_list pk11so_active_list +#define pubkey_token_flags pk11so_pubkey_token_flags +#define pubkey_SLOTID pk11so_pubkey_SLOTID +#define ERR_pk11_error ERR_pk11so_error +#define PK11err_add_data PK11SOerr_add_data +#define pk11_get_session pk11so_get_session +#define pk11_return_session pk11so_return_session +#define pk11_active_add pk11so_active_add +#define pk11_active_delete pk11so_active_delete +#define pk11_active_remove pk11so_active_remove +#define pk11_free_active_list pk11so_free_active_list +#define pk11_destroy_rsa_key_objects pk11so_destroy_rsa_key_objects +#define pk11_destroy_rsa_object_pub pk11so_destroy_rsa_object_pub +#define pk11_destroy_rsa_object_priv pk11so_destroy_rsa_object_priv +#define pk11_load_privkey pk11so_load_privkey +#define pk11_load_pubkey pk11so_load_pubkey +#define PK11_RSA PK11SO_RSA +#define pk11_destroy_dsa_key_objects pk11so_destroy_dsa_key_objects +#define pk11_destroy_dsa_object_pub pk11so_destroy_dsa_object_pub +#define pk11_destroy_dsa_object_priv pk11so_destroy_dsa_object_priv +#define PK11_DSA PK11SO_DSA +#define pk11_destroy_dh_key_objects pk11so_destroy_dh_key_objects +#define pk11_destroy_dh_object pk11so_destroy_dh_object +#define PK11_DH PK11SO_DH +#define pk11_token_relogin pk11so_token_relogin +#define pFuncList pk11so_pFuncList +#define pk11_pin pk11so_pin +#define ENGINE_load_pk11 ENGINE_load_pk11so Index: openssl/crypto/engine/hw_pk11so_pub.c diff -u /dev/null openssl/crypto/engine/hw_pk11so_pub.c:1.8.2.2 --- /dev/null Wed Dec 23 17:47:11 2015 +++ openssl/crypto/engine/hw_pk11so_pub.c Fri Oct 4 14:33:56 2013 @@ -0,0 +1,1642 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* crypto/engine/hw_pk11_pub.c */ +/* + * This product includes software developed by the OpenSSL Project for + * use in the OpenSSL Toolkit (http://www.openssl.org/). + * + * This project also referenced hw_pkcs11-0.9.7b.patch written by + * Afchine Madjlessi. + */ +/* + * ==================================================================== + * Copyright (c) 2000-2001 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +/* Modified to keep only RNG and RSA Sign */ + +#ifdef OPENSSL_NO_RSA +#error RSA is disabled +#endif + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef OPENSSL_SYS_WIN32 +#define NOPTHREADS +typedef int pid_t; +#define HAVE_GETPASSPHRASE +static char *getpassphrase(const char *prompt); +#ifndef NULL_PTR +#define NULL_PTR NULL +#endif +#define CK_DEFINE_FUNCTION(returnType, name) \ + returnType __declspec(dllexport) name +#define CK_DECLARE_FUNCTION(returnType, name) \ + returnType __declspec(dllimport) name +#define CK_DECLARE_FUNCTION_POINTER(returnType, name) \ + returnType __declspec(dllimport) (* name) +#else +#include +#endif + +#ifndef NOPTHREADS +#include +#endif + +#ifndef OPENSSL_NO_HW +#ifndef OPENSSL_NO_HW_PK11 +#ifndef OPENSSL_NO_HW_PK11SO + +#ifdef OPENSSL_SYS_WIN32 +#pragma pack(push, cryptoki, 1) +#include "cryptoki.h" +#include "pkcs11.h" +#pragma pack(pop, cryptoki) +#else +#include "cryptoki.h" +#include "pkcs11.h" +#endif +#include "hw_pk11so.h" +#include "hw_pk11_err.h" + +static CK_BBOOL pk11_login_done = CK_FALSE; +extern CK_SLOT_ID pubkey_SLOTID; +#ifndef NOPTHREADS +extern pthread_mutex_t *token_lock; +#endif + +#if !(defined(HAVE_GETPASSPHRASE) || (defined (__SVR4) && defined (__sun))) +#define getpassphrase(x) getpass(x) +#endif + +/* RSA stuff */ +static int pk11_RSA_sign(int type, const unsigned char *m, unsigned int m_len, + unsigned char *sigret, unsigned int *siglen, const RSA *rsa); +EVP_PKEY *pk11_load_privkey(ENGINE*, const char *privkey_file, + UI_METHOD *ui_method, void *callback_data); +EVP_PKEY *pk11_load_pubkey(ENGINE*, const char *pubkey_file, + UI_METHOD *ui_method, void *callback_data); + +static CK_OBJECT_HANDLE pk11_get_public_rsa_key(RSA* rsa, RSA** key_ptr, + BIGNUM **rsa_n_num, BIGNUM **rsa_e_num, CK_SESSION_HANDLE session); +static CK_OBJECT_HANDLE pk11_get_private_rsa_key(RSA* rsa, RSA** key_ptr, + BIGNUM **rsa_d_num, BIGNUM **rsa_n_num, BIGNUM **rsa_e_num, + CK_SESSION_HANDLE session); + +static int check_new_rsa_key_pub(PK11_SESSION *sp, const RSA *rsa); +static int check_new_rsa_key_priv(PK11_SESSION *sp, const RSA *rsa); + +static int find_one_object(PK11_OPTYPE op, CK_SESSION_HANDLE s, + CK_ATTRIBUTE_PTR ptempl, CK_ULONG nattr, CK_OBJECT_HANDLE_PTR pkey); +static int init_template_value(BIGNUM *bn, CK_VOID_PTR *pValue, + CK_ULONG *ulValueLen); +static void attr_to_BN(CK_ATTRIBUTE_PTR attr, CK_BYTE attr_data[], BIGNUM **bn); + +static int pk11_token_login(CK_SESSION_HANDLE session, CK_BBOOL *login_done, + CK_BBOOL is_private); + +/* Read mode string to be used for fopen() */ +#if SOLARIS_OPENSSL +static char *read_mode_flags = "rF"; +#else +static char *read_mode_flags = "r"; +#endif + +/* + * increment/create reference for an asymmetric key handle via active list + * manipulation. If active list operation fails, unlock (if locked), set error + * variable and jump to the specified label. + */ +#define KEY_HANDLE_REFHOLD(key_handle, alg_type, unlock, var, label) \ + { \ + if (pk11_active_add(key_handle, alg_type) < 0) \ + { \ + var = TRUE; \ + if (unlock) \ + UNLOCK_OBJSTORE(alg_type); \ + goto label; \ + } \ + } + +/* + * Find active list entry according to object handle and return pointer to the + * entry otherwise return NULL. + * + * This function presumes it is called with lock protecting the active list + * held. + */ +static PK11_active *pk11_active_find(CK_OBJECT_HANDLE h, PK11_OPTYPE type) + { + PK11_active *entry; + + for (entry = active_list[type]; entry != NULL; entry = entry->next) + if (entry->h == h) + return (entry); + + return (NULL); + } + +/* + * Search for an entry in the active list using PKCS#11 object handle as a + * search key and return refcnt of the found/created entry or -1 in case of + * failure. + * + * This function presumes it is called with lock protecting the active list + * held. + */ +int +pk11_active_add(CK_OBJECT_HANDLE h, PK11_OPTYPE type) + { + PK11_active *entry = NULL; + + if (h == CK_INVALID_HANDLE) + { + PK11err(PK11_F_ACTIVE_ADD, PK11_R_INVALID_HANDLE); + return (-1); + } + + /* search for entry in the active list */ + if ((entry = pk11_active_find(h, type)) != NULL) + entry->refcnt++; + else + { + /* not found, create new entry and add it to the list */ + entry = OPENSSL_malloc(sizeof (PK11_active)); + if (entry == NULL) + { + PK11err(PK11_F_ACTIVE_ADD, PK11_R_MALLOC_FAILURE); + return (-1); + } + entry->h = h; + entry->refcnt = 1; + entry->prev = NULL; + entry->next = NULL; + /* connect the newly created entry to the list */ + if (active_list[type] == NULL) + active_list[type] = entry; + else /* make the entry first in the list */ + { + entry->next = active_list[type]; + active_list[type]->prev = entry; + active_list[type] = entry; + } + } + + return (entry->refcnt); + } + +/* + * Remove active list entry from the list and free it. + * + * This function presumes it is called with lock protecting the active list + * held. + */ +void +pk11_active_remove(PK11_active *entry, PK11_OPTYPE type) + { + PK11_active *prev_entry; + + /* remove the entry from the list and free it */ + if ((prev_entry = entry->prev) != NULL) + { + prev_entry->next = entry->next; + if (entry->next != NULL) + entry->next->prev = prev_entry; + } + else + { + active_list[type] = entry->next; + /* we were the first but not the only one */ + if (entry->next != NULL) + entry->next->prev = NULL; + } + + /* sanitization */ + entry->h = CK_INVALID_HANDLE; + entry->prev = NULL; + entry->next = NULL; + OPENSSL_free(entry); + } + +/* Free all entries from the active list. */ +void +pk11_free_active_list(PK11_OPTYPE type) + { + PK11_active *entry; + + /* only for asymmetric types since only they have C_Find* locks. */ + switch (type) + { + case OP_RSA: + break; + default: + return; + } + + /* see find_lock array definition for more info on object locking */ + LOCK_OBJSTORE(type); + while ((entry = active_list[type]) != NULL) + pk11_active_remove(entry, type); + UNLOCK_OBJSTORE(type); + } + +/* + * Search for active list entry associated with given PKCS#11 object handle, + * decrement its refcnt and if it drops to 0, disconnect the entry and free it. + * + * Return 1 if the PKCS#11 object associated with the entry has no references, + * return 0 if there is at least one reference, -1 on error. + * + * This function presumes it is called with lock protecting the active list + * held. + */ +int +pk11_active_delete(CK_OBJECT_HANDLE h, PK11_OPTYPE type) + { + PK11_active *entry = NULL; + + if ((entry = pk11_active_find(h, type)) == NULL) + { + PK11err(PK11_F_ACTIVE_DELETE, PK11_R_INVALID_HANDLE); + return (-1); + } + + OPENSSL_assert(entry->refcnt > 0); + entry->refcnt--; + if (entry->refcnt == 0) + { + pk11_active_remove(entry, type); + return (1); + } + + return (0); + } + +/* Our internal RSA_METHOD that we provide pointers to */ +static RSA_METHOD pk11_rsa; + +RSA_METHOD * +PK11_RSA(void) + { + const RSA_METHOD *rsa; + + if (pk11_rsa.name == NULL) + { + rsa = RSA_PKCS1_SSLeay(); + memcpy(&pk11_rsa, rsa, sizeof(*rsa)); + pk11_rsa.name = "PKCS#11 RSA method"; + pk11_rsa.rsa_sign = pk11_RSA_sign; + } + return (&pk11_rsa); + } + +/* Size of an SSL signature: MD5+SHA1 */ +#define SSL_SIG_LENGTH 36 + +static CK_BBOOL mytrue = TRUE; +static CK_BBOOL myfalse = FALSE; + +/* + * Standard engine interface function. Majority codes here are from + * rsa/rsa_sign.c. We replaced the decrypt function call by C_Sign of PKCS#11. + * See more details in rsa/rsa_sign.c + */ +static int pk11_RSA_sign(int type, const unsigned char *m, unsigned int m_len, + unsigned char *sigret, unsigned int *siglen, const RSA *rsa) + { + X509_SIG sig; + ASN1_TYPE parameter; + int i, j = 0; + unsigned char *p, *s = NULL; + X509_ALGOR algor; + ASN1_OCTET_STRING digest; + CK_RV rv; + CK_MECHANISM mech_rsa = {CKM_RSA_PKCS, NULL, 0}; + CK_MECHANISM *p_mech = &mech_rsa; + CK_OBJECT_HANDLE h_priv_key; + PK11_SESSION *sp = NULL; + int ret = 0; + unsigned long ulsiglen; + + /* Encode the digest */ + /* Special case: SSL signature, just check the length */ + if (type == NID_md5_sha1) + { + if (m_len != SSL_SIG_LENGTH) + { + PK11err(PK11_F_RSA_SIGN, + PK11_R_INVALID_MESSAGE_LENGTH); + goto err; + } + i = SSL_SIG_LENGTH; + s = (unsigned char *)m; + } + else + { + sig.algor = &algor; + sig.algor->algorithm = OBJ_nid2obj(type); + if (sig.algor->algorithm == NULL) + { + PK11err(PK11_F_RSA_SIGN, + PK11_R_UNKNOWN_ALGORITHM_TYPE); + goto err; + } + if (sig.algor->algorithm->length == 0) + { + PK11err(PK11_F_RSA_SIGN, + PK11_R_UNKNOWN_ASN1_OBJECT_ID); + goto err; + } + parameter.type = V_ASN1_NULL; + parameter.value.ptr = NULL; + sig.algor->parameter = ¶meter; + + sig.digest = &digest; + sig.digest->data = (unsigned char *)m; + sig.digest->length = m_len; + + i = i2d_X509_SIG(&sig, NULL); + } + + j = RSA_size(rsa); + if ((i - RSA_PKCS1_PADDING) > j) + { + PK11err(PK11_F_RSA_SIGN, PK11_R_DIGEST_TOO_BIG); + goto err; + } + + if (type != NID_md5_sha1) + { + s = (unsigned char *)OPENSSL_malloc((unsigned int)(j + 1)); + if (s == NULL) + { + PK11err(PK11_F_RSA_SIGN, PK11_R_MALLOC_FAILURE); + goto err; + } + p = s; + (void) i2d_X509_SIG(&sig, &p); + } + + if ((sp = pk11_get_session(OP_RSA)) == NULL) + goto err; + + (void) check_new_rsa_key_priv(sp, rsa); + + h_priv_key = sp->opdata_rsa_priv_key; + if (h_priv_key == CK_INVALID_HANDLE) + h_priv_key = sp->opdata_rsa_priv_key = + pk11_get_private_rsa_key((RSA *)rsa, + &sp->opdata_rsa_priv, &sp->opdata_rsa_d_num, + &sp->opdata_rsa_pn_num, &sp->opdata_rsa_pe_num, + sp->session); + + if (h_priv_key != CK_INVALID_HANDLE) + { + rv = pFuncList->C_SignInit(sp->session, p_mech, h_priv_key); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_RSA_SIGN, PK11_R_SIGNINIT, rv); + goto err; + } + + ulsiglen = j; + rv = pFuncList->C_Sign(sp->session, s, i, sigret, + (CK_ULONG_PTR) &ulsiglen); + *siglen = ulsiglen; + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_RSA_SIGN, PK11_R_SIGN, rv); + goto err; + } + ret = 1; + } + +err: + if ((type != NID_md5_sha1) && (s != NULL)) + { + (void) memset(s, 0, (unsigned int)(j + 1)); + OPENSSL_free(s); + } + + pk11_return_session(sp, OP_RSA); + return (ret); + } + +static int hndidx_rsa = -1; + +#define MAXATTR 1024 + +/* + * Load RSA private key from a file or get its PKCS#11 handle if stored in the + * PKCS#11 token. + */ +/* ARGSUSED */ +EVP_PKEY *pk11_load_privkey(ENGINE *e, const char *privkey_file, + UI_METHOD *ui_method, void *callback_data) + { + EVP_PKEY *pkey = NULL; + FILE *privkey; + CK_OBJECT_HANDLE h_priv_key = CK_INVALID_HANDLE; + RSA *rsa = NULL; + PK11_SESSION *sp; + /* Anything else below is needed for the key by reference extension. */ + CK_RV rv; + CK_BBOOL is_token = TRUE; + CK_BBOOL rollback = FALSE; + CK_BYTE attr_data[2][MAXATTR]; + CK_OBJECT_CLASS key_class = CKO_PRIVATE_KEY; + CK_OBJECT_HANDLE ks_key = CK_INVALID_HANDLE; /* key in keystore */ + + /* we look for private keys only */ + CK_ATTRIBUTE search_templ[] = + { + {CKA_TOKEN, &is_token, sizeof(is_token)}, + {CKA_CLASS, &key_class, sizeof(key_class)}, + {CKA_LABEL, NULL, 0} + }; + + /* + * These public attributes are needed to initialize the OpenSSL RSA + * structure with something we can use to look up the key. Note that we + * never ask for private components. + */ + CK_ATTRIBUTE get_templ[] = + { + {CKA_MODULUS, (void *)attr_data[0], MAXATTR}, /* n */ + {CKA_PUBLIC_EXPONENT, (void *)attr_data[1], MAXATTR}, /* e */ + }; + + if ((sp = pk11_get_session(OP_RSA)) == NULL) + return (NULL); + + /* + * Use simple scheme "pkcs11:" for now. + */ + if (strstr(privkey_file, "pkcs11:") == privkey_file) + { + search_templ[2].pValue = strstr(privkey_file, ":") + 1; + search_templ[2].ulValueLen = strlen(search_templ[2].pValue); + + if (pk11_token_login(sp->session, &pk11_login_done, + CK_TRUE) == 0) + goto err; + + /* see find_lock array definition + for more info on object locking */ + LOCK_OBJSTORE(OP_RSA); + + /* + * Now let's try to find the key in the token. It is a failure + * if we can't find it. + */ + if (find_one_object(OP_RSA, sp->session, search_templ, 3, + &ks_key) == 0) + { + UNLOCK_OBJSTORE(OP_RSA); + goto err; + } + + if (hndidx_rsa == -1) + hndidx_rsa = RSA_get_ex_new_index(0, + "pkcs11 RSA HSM key handle", + NULL, NULL, NULL); + + /* + * We might have a cache hit which we could confirm + * according to the 'n'/'e' params, RSA public pointer + * as NULL, and non-NULL RSA private pointer. However, + * it is easier just to recreate everything. We expect + * the keys to be loaded once and used many times. We + * do not check the return value because even in case + * of failure the sp structure will have both key + * pointer and object handle cleaned and + * pk11_destroy_object() reports the failure to the + * OpenSSL error message buffer. + */ + (void) pk11_destroy_rsa_object_priv(sp, FALSE); + + sp->opdata_rsa_priv_key = ks_key; + /* This object shall not be deleted on a cache miss. */ + sp->priv_persistent = CK_TRUE; + + /* + * Cache the RSA private structure pointer. We do not + * use it now for key-by-ref keys but let's do it for + * consistency reasons. + */ + if ((rsa = sp->opdata_rsa_priv = RSA_new_method(e)) == NULL) + { + UNLOCK_OBJSTORE(OP_RSA); + goto err; + } + + /* + * Now we have to initialize an OpenSSL RSA structure, + * everything else is 0 or NULL. + */ + rsa->flags = RSA_FLAG_SIGN_VER | RSA_FLAG_EXT_PKEY; + RSA_set_ex_data(rsa, hndidx_rsa, (void *) ks_key); + + if ((rv = pFuncList->C_GetAttributeValue(sp->session, ks_key, + get_templ, 2)) != CKR_OK) + { + UNLOCK_OBJSTORE(OP_RSA); + PK11err_add_data(PK11_F_LOAD_PRIVKEY, + PK11_R_GETATTRIBUTVALUE, rv); + goto err; + } + + /* + * We do not use pk11_get_private_rsa_key() here so we + * must take care of handle management ourselves. + */ + KEY_HANDLE_REFHOLD(ks_key, OP_RSA, TRUE, rollback, err); + + /* + * Those are the sensitive components we do not want to export + * from the token at all: rsa->(d|p|q|dmp1|dmq1|iqmp). + */ + attr_to_BN(&get_templ[0], attr_data[0], &rsa->n); + attr_to_BN(&get_templ[1], attr_data[1], &rsa->e); + /* + * Must have 'n'/'e' components in the session structure as + * well. They serve as a public look-up key for the private key + * in the keystore. + */ + attr_to_BN(&get_templ[0], attr_data[0], + &sp->opdata_rsa_pn_num); + attr_to_BN(&get_templ[1], attr_data[1], + &sp->opdata_rsa_pe_num); + + UNLOCK_OBJSTORE(OP_RSA); + + if ((pkey = EVP_PKEY_new()) == NULL) + goto err; + + if (EVP_PKEY_assign_RSA(pkey, rsa) == 0) + goto err; + } + else if ((privkey = fopen(privkey_file, read_mode_flags)) != NULL) + { + pkey = PEM_read_PrivateKey(privkey, NULL, NULL, NULL); + (void) fclose(privkey); + if (pkey != NULL) + { + rsa = EVP_PKEY_get1_RSA(pkey); + if (rsa != NULL) + { + /* + * This will always destroy the RSA + * object since we have a new RSA + * structure here. + */ + (void) check_new_rsa_key_priv(sp, rsa); + sp->priv_persistent = CK_FALSE; + + h_priv_key = sp->opdata_rsa_priv_key = + pk11_get_private_rsa_key(rsa, + &sp->opdata_rsa_priv, + &sp->opdata_rsa_d_num, + &sp->opdata_rsa_pn_num, + &sp->opdata_rsa_pe_num, sp->session); + if (h_priv_key == CK_INVALID_HANDLE) + goto err; + } + else + goto err; + } + } + + pk11_return_session(sp, OP_RSA); + return (pkey); +err: + pk11_return_session(sp, OP_RSA); + if (rsa != NULL) + RSA_free(rsa); + if (pkey != NULL) + { + EVP_PKEY_free(pkey); + pkey = NULL; + } + rollback = rollback; + return (pkey); + } + +/* + * Load RSA public key from a file or get its PKCS#11 handle if stored in the + * PKCS#11 token. + */ +/* ARGSUSED */ +EVP_PKEY *pk11_load_pubkey(ENGINE *e, const char *pubkey_file, + UI_METHOD *ui_method, void *callback_data) + { + EVP_PKEY *pkey = NULL; + FILE *pubkey; + CK_OBJECT_HANDLE h_pub_key = CK_INVALID_HANDLE; + RSA *rsa = NULL; + PK11_SESSION *sp; + /* Anything else below is needed for the key by reference extension. */ + CK_RV rv; + CK_BBOOL is_token = TRUE; + CK_BYTE attr_data[2][MAXATTR]; + CK_OBJECT_CLASS key_class = CKO_PUBLIC_KEY; + CK_OBJECT_HANDLE ks_key = CK_INVALID_HANDLE; /* key in keystore */ + + /* we look for public keys only */ + CK_ATTRIBUTE search_templ[] = + { + {CKA_TOKEN, &is_token, sizeof(is_token)}, + {CKA_CLASS, &key_class, sizeof(key_class)}, + {CKA_LABEL, NULL, 0} + }; + + /* + * These public attributes are needed to initialize OpenSSL RSA + * structure with something we can use to look up the key. + */ + CK_ATTRIBUTE get_templ[] = + { + {CKA_MODULUS, (void *)attr_data[0], MAXATTR}, /* n */ + {CKA_PUBLIC_EXPONENT, (void *)attr_data[1], MAXATTR}, /* e */ + }; + + if ((sp = pk11_get_session(OP_RSA)) == NULL) + return (NULL); + + /* + * Use simple scheme "pkcs11:" for now. + */ + if (strstr(pubkey_file, "pkcs11:") == pubkey_file) + { + search_templ[2].pValue = strstr(pubkey_file, ":") + 1; + search_templ[2].ulValueLen = strlen(search_templ[2].pValue); + + if (pk11_token_login(sp->session, &pk11_login_done, + CK_FALSE) == 0) + goto err; + + /* see find_lock array definition + for more info on object locking */ + LOCK_OBJSTORE(OP_RSA); + + /* + * Now let's try to find the key in the token. It is a failure + * if we can't find it. + */ + if (find_one_object(OP_RSA, sp->session, search_templ, 3, + &ks_key) == 0) + { + UNLOCK_OBJSTORE(OP_RSA); + goto err; + } + + /* + * We load a new public key so we will create a new RSA + * structure. No cache hit is possible. + */ + (void) pk11_destroy_rsa_object_pub(sp, FALSE); + + sp->opdata_rsa_pub_key = ks_key; + /* This object shall not be deleted on a cache miss. */ + sp->pub_persistent = CK_TRUE; + + /* + * Cache the RSA public structure pointer. + */ + if ((rsa = sp->opdata_rsa_pub = RSA_new_method(e)) == NULL) + { + UNLOCK_OBJSTORE(OP_RSA); + goto err; + } + + /* + * Now we have to initialize an OpenSSL RSA structure, + * everything else is 0 or NULL. + */ + rsa->flags = RSA_FLAG_SIGN_VER; + + if ((rv = pFuncList->C_GetAttributeValue(sp->session, ks_key, + get_templ, 2)) != CKR_OK) + { + UNLOCK_OBJSTORE(OP_RSA); + PK11err_add_data(PK11_F_LOAD_PUBKEY, + PK11_R_GETATTRIBUTVALUE, rv); + goto err; + } + + attr_to_BN(&get_templ[0], attr_data[0], &rsa->n); + attr_to_BN(&get_templ[1], attr_data[1], &rsa->e); + + UNLOCK_OBJSTORE(OP_RSA); + + if ((pkey = EVP_PKEY_new()) == NULL) + goto err; + + if (EVP_PKEY_assign_RSA(pkey, rsa) == 0) + goto err; + + /* + * Create a session object from it so that when calling + * pk11_get_public_rsa_key() the next time, we can find it. The + * reason why we do that is that we cannot tell from the RSA + * structure (OpenSSL RSA structure does not have any room for + * additional data used by the engine, for example) if it bears + * a public key stored in the keystore or not so it's better if + * we always have a session key. Note that this is different + * from what we do for the private keystore objects but in that + * case, we can tell from the RSA structure that the keystore + * object is in play - the 'd' component is NULL in that case. + */ + h_pub_key = sp->opdata_rsa_pub_key = + pk11_get_public_rsa_key(rsa, + &sp->opdata_rsa_pub, &sp->opdata_rsa_n_num, + &sp->opdata_rsa_e_num, sp->session); + if (h_pub_key == CK_INVALID_HANDLE) + goto err; + } + else if ((pubkey = fopen(pubkey_file, read_mode_flags)) != NULL) + { + pkey = PEM_read_PUBKEY(pubkey, NULL, NULL, NULL); + (void) fclose(pubkey); + if (pkey != NULL) + { + rsa = EVP_PKEY_get1_RSA(pkey); + if (rsa != NULL) + { + /* + * This will always destroy the RSA + * object since we have a new RSA + * structure here. + */ + (void) check_new_rsa_key_pub(sp, rsa); + sp->pub_persistent = CK_FALSE; + + h_pub_key = sp->opdata_rsa_pub_key = + pk11_get_public_rsa_key(rsa, + &sp->opdata_rsa_pub, &sp->opdata_rsa_n_num, + &sp->opdata_rsa_e_num, sp->session); + if (h_pub_key == CK_INVALID_HANDLE) + goto err; + } + else + goto err; + } + } + + pk11_return_session(sp, OP_RSA); + return (pkey); +err: + pk11_return_session(sp, OP_RSA); + if (rsa != NULL) + RSA_free(rsa); + if (pkey != NULL) + { + EVP_PKEY_free(pkey); + pkey = NULL; + } + return (pkey); + } + +/* + * Create a public key object in a session from a given rsa structure. + * The *rsa_n_num and *rsa_e_num pointers are non-NULL for RSA public keys. + */ +static CK_OBJECT_HANDLE pk11_get_public_rsa_key(RSA *rsa, + RSA **key_ptr, BIGNUM **rsa_n_num, BIGNUM **rsa_e_num, + CK_SESSION_HANDLE session) + { + CK_RV rv; + CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE; + CK_ULONG found; + CK_OBJECT_CLASS o_key = CKO_PUBLIC_KEY; + CK_KEY_TYPE k_type = CKK_RSA; + CK_ULONG ul_key_attr_count = 8; + CK_BBOOL rollback = FALSE; + + CK_ATTRIBUTE a_key_template[] = + { + {CKA_CLASS, (void *) NULL, sizeof (CK_OBJECT_CLASS)}, + {CKA_KEY_TYPE, (void *) NULL, sizeof (CK_KEY_TYPE)}, + {CKA_TOKEN, &myfalse, sizeof (myfalse)}, + {CKA_ENCRYPT, &mytrue, sizeof (mytrue)}, + {CKA_VERIFY, &mytrue, sizeof (mytrue)}, + {CKA_VERIFY_RECOVER, &mytrue, sizeof (mytrue)}, + {CKA_MODULUS, (void *)NULL, 0}, + {CKA_PUBLIC_EXPONENT, (void *)NULL, 0} + }; + + int i; + + a_key_template[0].pValue = &o_key; + a_key_template[1].pValue = &k_type; + + a_key_template[6].ulValueLen = BN_num_bytes(rsa->n); + a_key_template[6].pValue = (CK_VOID_PTR)OPENSSL_malloc( + (size_t)a_key_template[6].ulValueLen); + if (a_key_template[6].pValue == NULL) + { + PK11err(PK11_F_GET_PUB_RSA_KEY, PK11_R_MALLOC_FAILURE); + goto malloc_err; + } + + BN_bn2bin(rsa->n, a_key_template[6].pValue); + + a_key_template[7].ulValueLen = BN_num_bytes(rsa->e); + a_key_template[7].pValue = (CK_VOID_PTR)OPENSSL_malloc( + (size_t)a_key_template[7].ulValueLen); + if (a_key_template[7].pValue == NULL) + { + PK11err(PK11_F_GET_PUB_RSA_KEY, PK11_R_MALLOC_FAILURE); + goto malloc_err; + } + + BN_bn2bin(rsa->e, a_key_template[7].pValue); + + /* see find_lock array definition for more info on object locking */ + LOCK_OBJSTORE(OP_RSA); + + rv = pFuncList->C_FindObjectsInit(session, a_key_template, + ul_key_attr_count); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PUB_RSA_KEY, + PK11_R_FINDOBJECTSINIT, rv); + goto err; + } + + rv = pFuncList->C_FindObjects(session, &h_key, 1, &found); + + if (rv != CKR_OK) + { + (void) pFuncList->C_FindObjectsFinal(session); + PK11err_add_data(PK11_F_GET_PUB_RSA_KEY, + PK11_R_FINDOBJECTS, rv); + goto err; + } + + rv = pFuncList->C_FindObjectsFinal(session); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PUB_RSA_KEY, + PK11_R_FINDOBJECTSFINAL, rv); + goto err; + } + + if (found == 0) + { + rv = pFuncList->C_CreateObject(session, + a_key_template, ul_key_attr_count, &h_key); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PUB_RSA_KEY, + PK11_R_CREATEOBJECT, rv); + goto err; + } + } + + if (rsa_n_num != NULL) + if ((*rsa_n_num = BN_dup(rsa->n)) == NULL) + { + PK11err(PK11_F_GET_PUB_RSA_KEY, PK11_R_MALLOC_FAILURE); + rollback = TRUE; + goto err; + } + if (rsa_e_num != NULL) + if ((*rsa_e_num = BN_dup(rsa->e)) == NULL) + { + PK11err(PK11_F_GET_PUB_RSA_KEY, PK11_R_MALLOC_FAILURE); + BN_free(*rsa_n_num); + *rsa_n_num = NULL; + rollback = TRUE; + goto err; + } + + /* LINTED: E_CONSTANT_CONDITION */ + KEY_HANDLE_REFHOLD(h_key, OP_RSA, FALSE, rollback, err); + if (key_ptr != NULL) + *key_ptr = rsa; + +err: + if (rollback) + { + /* + * We do not care about the return value from C_DestroyObject() + * since we are doing rollback. + */ + if (found == 0) + (void) pFuncList->C_DestroyObject(session, h_key); + h_key = CK_INVALID_HANDLE; + } + + UNLOCK_OBJSTORE(OP_RSA); + +malloc_err: + for (i = 6; i <= 7; i++) + { + if (a_key_template[i].pValue != NULL) + { + OPENSSL_free(a_key_template[i].pValue); + a_key_template[i].pValue = NULL; + } + } + + return (h_key); + } + +/* + * Create a private key object in the session from a given rsa structure. + * The *rsa_d_num pointer is non-NULL for RSA private keys. + */ +static CK_OBJECT_HANDLE +pk11_get_private_rsa_key(RSA *rsa, RSA **key_ptr, BIGNUM **rsa_d_num, + BIGNUM **rsa_n_num, BIGNUM **rsa_e_num, CK_SESSION_HANDLE session) + { + CK_RV rv; + CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE; + int i; + CK_ULONG found; + CK_OBJECT_CLASS o_key = CKO_PRIVATE_KEY; + CK_KEY_TYPE k_type = CKK_RSA; + CK_ULONG ul_key_attr_count = 14; + CK_BBOOL rollback = FALSE; + + /* Both CKA_TOKEN and CKA_SENSITIVE have to be FALSE for session keys */ + CK_ATTRIBUTE a_key_template[] = + { + {CKA_CLASS, (void *) NULL, sizeof (CK_OBJECT_CLASS)}, + {CKA_KEY_TYPE, (void *) NULL, sizeof (CK_KEY_TYPE)}, + {CKA_TOKEN, &myfalse, sizeof (myfalse)}, + {CKA_SENSITIVE, &myfalse, sizeof (myfalse)}, + {CKA_DECRYPT, &mytrue, sizeof (mytrue)}, + {CKA_SIGN, &mytrue, sizeof (mytrue)}, + {CKA_MODULUS, (void *)NULL, 0}, + {CKA_PUBLIC_EXPONENT, (void *)NULL, 0}, + {CKA_PRIVATE_EXPONENT, (void *)NULL, 0}, + {CKA_PRIME_1, (void *)NULL, 0}, + {CKA_PRIME_2, (void *)NULL, 0}, + {CKA_EXPONENT_1, (void *)NULL, 0}, + {CKA_EXPONENT_2, (void *)NULL, 0}, + {CKA_COEFFICIENT, (void *)NULL, 0}, + }; + + if ((rsa->flags & RSA_FLAG_EXT_PKEY) != 0) { + h_key = (CK_OBJECT_HANDLE)RSA_get_ex_data(rsa, hndidx_rsa); + LOCK_OBJSTORE(OP_RSA); + goto set; + } + + a_key_template[0].pValue = &o_key; + a_key_template[1].pValue = &k_type; + + /* Put the private key components into the template */ + if (init_template_value(rsa->n, &a_key_template[6].pValue, + &a_key_template[6].ulValueLen) == 0 || + init_template_value(rsa->e, &a_key_template[7].pValue, + &a_key_template[7].ulValueLen) == 0 || + init_template_value(rsa->d, &a_key_template[8].pValue, + &a_key_template[8].ulValueLen) == 0 || + init_template_value(rsa->p, &a_key_template[9].pValue, + &a_key_template[9].ulValueLen) == 0 || + init_template_value(rsa->q, &a_key_template[10].pValue, + &a_key_template[10].ulValueLen) == 0 || + init_template_value(rsa->dmp1, &a_key_template[11].pValue, + &a_key_template[11].ulValueLen) == 0 || + init_template_value(rsa->dmq1, &a_key_template[12].pValue, + &a_key_template[12].ulValueLen) == 0 || + init_template_value(rsa->iqmp, &a_key_template[13].pValue, + &a_key_template[13].ulValueLen) == 0) + { + PK11err(PK11_F_GET_PRIV_RSA_KEY, PK11_R_MALLOC_FAILURE); + goto malloc_err; + } + + /* see find_lock array definition for more info on object locking */ + LOCK_OBJSTORE(OP_RSA); + + /* + * We are getting the private key but the private 'd' + * component is NULL. That means this is key by reference RSA + * key. In that case, we can use only public components for + * searching for the private key handle. + */ + if (rsa->d == NULL) + { + ul_key_attr_count = 8; + /* + * We will perform the search in the token, not in the existing + * session keys. + */ + a_key_template[2].pValue = &mytrue; + } + + rv = pFuncList->C_FindObjectsInit(session, a_key_template, + ul_key_attr_count); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PRIV_RSA_KEY, + PK11_R_FINDOBJECTSINIT, rv); + goto err; + } + + rv = pFuncList->C_FindObjects(session, &h_key, 1, &found); + + if (rv != CKR_OK) + { + (void) pFuncList->C_FindObjectsFinal(session); + PK11err_add_data(PK11_F_GET_PRIV_RSA_KEY, + PK11_R_FINDOBJECTS, rv); + goto err; + } + + rv = pFuncList->C_FindObjectsFinal(session); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PRIV_RSA_KEY, + PK11_R_FINDOBJECTSFINAL, rv); + goto err; + } + + if (found == 0) + { + /* + * We have an RSA structure with 'n'/'e' components + * only so we tried to find the private key in the + * keystore. If it was really a token key we have a + * problem. Note that for other key types we just + * create a new session key using the private + * components from the RSA structure. + */ + if (rsa->d == NULL) + { + PK11err(PK11_F_GET_PRIV_RSA_KEY, + PK11_R_PRIV_KEY_NOT_FOUND); + goto err; + } + + rv = pFuncList->C_CreateObject(session, + a_key_template, ul_key_attr_count, &h_key); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PRIV_RSA_KEY, + PK11_R_CREATEOBJECT, rv); + goto err; + } + } + +set: + if (rsa_d_num != NULL) + { + /* + * When RSA keys by reference code is used, we never + * extract private components from the keystore. In + * that case 'd' was set to NULL and we expect the + * application to properly cope with that. It is + * documented in openssl(5). In general, if keys by + * reference are used we expect it to be used + * exclusively using the high level API and then there + * is no problem. If the application expects the + * private components to be read from the keystore + * then that is not a supported way of usage. + */ + if (rsa->d != NULL && (*rsa_d_num = BN_dup(rsa->d)) == NULL) + { + PK11err(PK11_F_GET_PRIV_RSA_KEY, PK11_R_MALLOC_FAILURE); + rollback = TRUE; + goto err; + } + else + *rsa_d_num = NULL; + } + + /* + * For the key by reference code, we need public components as well + * since 'd' component is always NULL. For that reason, we always cache + * 'n'/'e' components as well. + */ + *rsa_n_num = BN_dup(rsa->n); + *rsa_e_num = BN_dup(rsa->e); + + /* LINTED: E_CONSTANT_CONDITION */ + KEY_HANDLE_REFHOLD(h_key, OP_RSA, FALSE, rollback, err); + if (key_ptr != NULL) + *key_ptr = rsa; + +err: + if (rollback) + { + /* + * We do not care about the return value from C_DestroyObject() + * since we are doing rollback. + */ + if (found == 0 && + (rsa->flags & RSA_FLAG_EXT_PKEY) == 0) + (void) pFuncList->C_DestroyObject(session, h_key); + h_key = CK_INVALID_HANDLE; + } + + UNLOCK_OBJSTORE(OP_RSA); + +malloc_err: + /* + * 6 to 13 entries in the key template are key components. + * They need to be freed upon exit or error. + */ + for (i = 6; i <= 13; i++) + { + if (a_key_template[i].pValue != NULL) + { + (void) memset(a_key_template[i].pValue, 0, + a_key_template[i].ulValueLen); + OPENSSL_free(a_key_template[i].pValue); + a_key_template[i].pValue = NULL; + } + } + + return (h_key); + } + +/* + * Check for cache miss and clean the object pointer and handle + * in such case. Return 1 for cache hit, 0 for cache miss. + */ +static int check_new_rsa_key_pub(PK11_SESSION *sp, const RSA *rsa) + { + /* + * Provide protection against RSA structure reuse by making the + * check for cache hit stronger. Only public components of RSA + * key matter here so it is sufficient to compare them with values + * cached in PK11_SESSION structure. + * + * We must check the handle as well since with key by reference, public + * components 'n'/'e' are cached in private keys as well. That means we + * could have a cache hit in a private key when looking for a public + * key. That would not work, you cannot have one PKCS#11 object for + * both data signing and verifying. + */ + if ((sp->opdata_rsa_pub != rsa) || + (BN_cmp(sp->opdata_rsa_n_num, rsa->n) != 0) || + (BN_cmp(sp->opdata_rsa_e_num, rsa->e) != 0) || + (sp->opdata_rsa_priv_key != CK_INVALID_HANDLE)) + { + /* + * We do not check the return value because even in case of + * failure the sp structure will have both key pointer + * and object handle cleaned and pk11_destroy_object() + * reports the failure to the OpenSSL error message buffer. + */ + (void) pk11_destroy_rsa_object_pub(sp, TRUE); + return (0); + } + return (1); + } + +/* + * Check for cache miss and clean the object pointer and handle + * in such case. Return 1 for cache hit, 0 for cache miss. + */ +static int check_new_rsa_key_priv(PK11_SESSION *sp, const RSA *rsa) + { + /* + * Provide protection against RSA structure reuse by making + * the check for cache hit stronger. Comparing public exponent + * of RSA key with value cached in PK11_SESSION structure + * should be sufficient. Note that we want to compare the + * public component since with the keys by reference + * mechanism, private components are not in the RSA + * structure. Also, see check_new_rsa_key_pub() about why we + * compare the handle as well. + */ + if ((sp->opdata_rsa_priv != rsa) || + (BN_cmp(sp->opdata_rsa_pn_num, rsa->n) != 0) || + (BN_cmp(sp->opdata_rsa_pe_num, rsa->e) != 0) || + (sp->opdata_rsa_pn_num == NULL) || + (sp->opdata_rsa_pe_num == NULL) || + (sp->opdata_rsa_pub_key != CK_INVALID_HANDLE)) + { + /* + * We do not check the return value because even in case of + * failure the sp structure will have both key pointer + * and object handle cleaned and pk11_destroy_object() + * reports the failure to the OpenSSL error message buffer. + */ + (void) pk11_destroy_rsa_object_priv(sp, TRUE); + return (0); + } + return (1); + } + +/* + * Local function to simplify key template population + * Return 0 -- error, 1 -- no error + */ +static int +init_template_value(BIGNUM *bn, CK_VOID_PTR *p_value, + CK_ULONG *ul_value_len) + { + CK_ULONG len = 0; + + /* + * This function can be used on non-initialized BIGNUMs. It is + * easier to check that here than individually in the callers. + */ + if (bn != NULL) + len = BN_num_bytes(bn); + + if (bn == NULL || len == 0) + return (1); + + *ul_value_len = len; + *p_value = (CK_VOID_PTR)OPENSSL_malloc((size_t)*ul_value_len); + if (*p_value == NULL) + return (0); + + BN_bn2bin(bn, *p_value); + + return (1); + } + +static void +attr_to_BN(CK_ATTRIBUTE_PTR attr, CK_BYTE attr_data[], BIGNUM **bn) + { + if (attr->ulValueLen > 0) + *bn = BN_bin2bn(attr_data, attr->ulValueLen, NULL); + } + +/* + * Find one object in the token. It is an error if we can not find the + * object or if we find more objects based on the template we got. + * Assume object store locked. + * + * Returns: + * 1 OK + * 0 no object or more than 1 object found + */ +static int +find_one_object(PK11_OPTYPE op, CK_SESSION_HANDLE s, + CK_ATTRIBUTE_PTR ptempl, CK_ULONG nattr, CK_OBJECT_HANDLE_PTR pkey) + { + CK_RV rv; + CK_ULONG objcnt; + + if ((rv = pFuncList->C_FindObjectsInit(s, ptempl, nattr)) != CKR_OK) + { + PK11err_add_data(PK11_F_FIND_ONE_OBJECT, + PK11_R_FINDOBJECTSINIT, rv); + return (0); + } + + rv = pFuncList->C_FindObjects(s, pkey, 1, &objcnt); + if (rv != CKR_OK) + { + (void) pFuncList->C_FindObjectsFinal(s); + PK11err_add_data(PK11_F_FIND_ONE_OBJECT, PK11_R_FINDOBJECTS, + rv); + return (0); + } + + (void) pFuncList->C_FindObjectsFinal(s); + + if (objcnt > 1) + { + PK11err(PK11_F_FIND_ONE_OBJECT, + PK11_R_MORE_THAN_ONE_OBJECT_FOUND); + return (0); + } + else if (objcnt == 0) + { + PK11err(PK11_F_FIND_ONE_OBJECT, PK11_R_NO_OBJECT_FOUND); + return (0); + } + return (1); + } + +/* from uri stuff */ + +extern char *pk11_pin; + +static int pk11_get_pin(void); + +static int +pk11_get_pin(void) +{ + char *pin; + + /* The getpassphrase() function is not MT safe. */ +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_lock(token_lock) == 0); +#else + CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); +#endif + pin = getpassphrase("Enter PIN: "); + if (pin == NULL) + { + PK11err(PK11_F_GET_PIN, PK11_R_COULD_NOT_READ_PIN); +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0); +#else + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + return (0); + } + pk11_pin = BUF_strdup(pin); + if (pk11_pin == NULL) + { + PK11err(PK11_F_LOAD_PRIVKEY, PK11_R_MALLOC_FAILURE); +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0); +#else + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + return (0); + } + memset(pin, 0, strlen(pin)); +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0); +#else + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + return (1); + } + +/* + * Log in to the keystore if we are supposed to do that at all. Take care of + * reading and caching the PIN etc. Log in only once even when called from + * multiple threads. + * + * Returns: + * 1 on success + * 0 on failure + */ +static int +pk11_token_login(CK_SESSION_HANDLE session, CK_BBOOL *login_done, + CK_BBOOL is_private) + { + CK_RV rv; + +#if 0 + /* doesn't work on the AEP Keyper??? */ + if ((pubkey_token_flags & CKF_TOKEN_INITIALIZED) == 0) + { + PK11err(PK11_F_TOKEN_LOGIN, + PK11_R_TOKEN_NOT_INITIALIZED); + return (0); + } +#endif + + /* + * If login is required or needed but the PIN has not been + * even initialized we can bail out right now. Note that we + * are supposed to always log in if we are going to access + * private keys. However, we may need to log in even for + * accessing public keys in case that the CKF_LOGIN_REQUIRED + * flag is set. + */ + if (((pubkey_token_flags & CKF_LOGIN_REQUIRED) || + (is_private == CK_TRUE)) && + (~pubkey_token_flags & CKF_USER_PIN_INITIALIZED)) + { + PK11err(PK11_F_TOKEN_LOGIN, PK11_R_TOKEN_PIN_NOT_SET); + return (0); + } + + /* + * Note on locking: it is possible that more than one thread + * gets into pk11_get_pin() so we must deal with that. We + * cannot avoid it since we cannot guard fork() in there with + * a lock because we could end up in a dead lock in the + * child. Why? Remember we are in a multithreaded environment + * so we must lock all mutexes in the prefork function to + * avoid a situation in which a thread that did not call + * fork() held a lock, making future unlocking impossible. We + * lock right before C_Login(). + */ + if ((pubkey_token_flags & CKF_LOGIN_REQUIRED) || + (is_private == CK_TRUE)) + { + if (*login_done == CK_FALSE) + { + if ((pk11_pin == NULL) && (pk11_get_pin() == 0)) + { + PK11err(PK11_F_TOKEN_LOGIN, + PK11_R_TOKEN_PIN_NOT_PROVIDED); + return (0); + } + } + + /* + * Note that what we are logging into is the keystore from + * pubkey_SLOTID because we work with OP_RSA session type here. + * That also means that we can work with only one keystore in + * the engine. + * + * We must make sure we do not try to login more than once. + * Also, see the comment above on locking strategy. + */ + +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_lock(token_lock) == 0); +#else + CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); +#endif + if (*login_done == CK_FALSE) + { + if ((rv = pFuncList->C_Login(session, + CKU_USER, (CK_UTF8CHAR*)pk11_pin, + strlen(pk11_pin))) != CKR_OK) + { + PK11err_add_data(PK11_F_TOKEN_LOGIN, + PK11_R_TOKEN_LOGIN_FAILED, rv); + goto err_locked; + } + + *login_done = CK_TRUE; + + } +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0); +#else + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + } + else + { + /* + * If token does not require login we take it as the + * login was done. + */ + *login_done = CK_TRUE; + } + + return (1); + +err_locked: + if (pk11_pin) { + memset(pk11_pin, 0, strlen(pk11_pin)); + OPENSSL_free((void*)pk11_pin); + } + pk11_pin = NULL; +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0); +#else + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + return (0); + } + +/* + * Log in to the keystore in the child if we were logged in in the + * parent. There are similarities in the code with pk11_token_login() + * but still it is quite different so we need a separate function for + * this. + * + * Note that this function is called under the locked session mutex when fork is + * detected. That means that C_Login() will be called from the child just once. + * + * Returns: + * 1 on success + * 0 on failure + */ +int +pk11_token_relogin(CK_SESSION_HANDLE session) + { + CK_RV rv; + + if ((pk11_pin == NULL) && (pk11_get_pin() == 0)) + return (0); + +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_lock(token_lock) == 0); +#else + CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); +#endif + if ((rv = pFuncList->C_Login(session, CKU_USER, + (CK_UTF8CHAR_PTR)pk11_pin, strlen(pk11_pin))) != CKR_OK) + { + PK11err_add_data(PK11_F_TOKEN_RELOGIN, + PK11_R_TOKEN_LOGIN_FAILED, rv); +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0); +#else + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + return (0); + } +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0); +#else + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + + return (1); + } + +#ifdef OPENSSL_SYS_WIN32 +char *getpassphrase(const char *prompt) + { + static char buf[128]; + HANDLE h; + DWORD cc, mode; + int cnt; + + h = GetStdHandle(STD_INPUT_HANDLE); + fputs(prompt, stderr); + fflush(stderr); + fflush(stdout); + FlushConsoleInputBuffer(h); + GetConsoleMode(h, &mode); + SetConsoleMode(h, ENABLE_PROCESSED_INPUT); + + for (cnt = 0; cnt < sizeof(buf) - 1; cnt++) + { + ReadFile(h, buf + cnt, 1, &cc, NULL); + if (buf[cnt] == '\r') + break; + fputc('*', stdout); + fflush(stderr); + fflush(stdout); + } + + SetConsoleMode(h, mode); + buf[cnt] = '\0'; + fputs("\n", stderr); + return buf; + } +#endif /* OPENSSL_SYS_WIN32 */ +#endif /* OPENSSL_NO_HW_PK11SO */ +#endif /* OPENSSL_NO_HW_PK11 */ +#endif /* OPENSSL_NO_HW */ Index: openssl/crypto/engine/pkcs11.h diff -u /dev/null openssl/crypto/engine/pkcs11.h:1.1.1.1 --- /dev/null Wed Dec 23 17:47:11 2015 +++ openssl/crypto/engine/pkcs11.h Wed Oct 24 23:27:09 2007 @@ -0,0 +1,299 @@ +/* pkcs11.h include file for PKCS #11. */ +/* $Revision: 1.1.1.1 $ */ + +/* License to copy and use this software is granted provided that it is + * identified as "RSA Security Inc. PKCS #11 Cryptographic Token Interface + * (Cryptoki)" in all material mentioning or referencing this software. + + * License is also granted to make and use derivative works provided that + * such works are identified as "derived from the RSA Security Inc. PKCS #11 + * Cryptographic Token Interface (Cryptoki)" in all material mentioning or + * referencing the derived work. + + * RSA Security Inc. makes no representations concerning either the + * merchantability of this software or the suitability of this software for + * any particular purpose. It is provided "as is" without express or implied + * warranty of any kind. + */ + +#ifndef _PKCS11_H_ +#define _PKCS11_H_ 1 + +#ifdef __cplusplus +extern "C" { +#endif + +/* Before including this file (pkcs11.h) (or pkcs11t.h by + * itself), 6 platform-specific macros must be defined. These + * macros are described below, and typical definitions for them + * are also given. Be advised that these definitions can depend + * on both the platform and the compiler used (and possibly also + * on whether a Cryptoki library is linked statically or + * dynamically). + * + * In addition to defining these 6 macros, the packing convention + * for Cryptoki structures should be set. The Cryptoki + * convention on packing is that structures should be 1-byte + * aligned. + * + * If you're using Microsoft Developer Studio 5.0 to produce + * Win32 stuff, this might be done by using the following + * preprocessor directive before including pkcs11.h or pkcs11t.h: + * + * #pragma pack(push, cryptoki, 1) + * + * and using the following preprocessor directive after including + * pkcs11.h or pkcs11t.h: + * + * #pragma pack(pop, cryptoki) + * + * If you're using an earlier version of Microsoft Developer + * Studio to produce Win16 stuff, this might be done by using + * the following preprocessor directive before including + * pkcs11.h or pkcs11t.h: + * + * #pragma pack(1) + * + * In a UNIX environment, you're on your own for this. You might + * not need to do (or be able to do!) anything. + * + * + * Now for the macros: + * + * + * 1. CK_PTR: The indirection string for making a pointer to an + * object. It can be used like this: + * + * typedef CK_BYTE CK_PTR CK_BYTE_PTR; + * + * If you're using Microsoft Developer Studio 5.0 to produce + * Win32 stuff, it might be defined by: + * + * #define CK_PTR * + * + * If you're using an earlier version of Microsoft Developer + * Studio to produce Win16 stuff, it might be defined by: + * + * #define CK_PTR far * + * + * In a typical UNIX environment, it might be defined by: + * + * #define CK_PTR * + * + * + * 2. CK_DEFINE_FUNCTION(returnType, name): A macro which makes + * an exportable Cryptoki library function definition out of a + * return type and a function name. It should be used in the + * following fashion to define the exposed Cryptoki functions in + * a Cryptoki library: + * + * CK_DEFINE_FUNCTION(CK_RV, C_Initialize)( + * CK_VOID_PTR pReserved + * ) + * { + * ... + * } + * + * If you're using Microsoft Developer Studio 5.0 to define a + * function in a Win32 Cryptoki .dll, it might be defined by: + * + * #define CK_DEFINE_FUNCTION(returnType, name) \ + * returnType __declspec(dllexport) name + * + * If you're using an earlier version of Microsoft Developer + * Studio to define a function in a Win16 Cryptoki .dll, it + * might be defined by: + * + * #define CK_DEFINE_FUNCTION(returnType, name) \ + * returnType __export _far _pascal name + * + * In a UNIX environment, it might be defined by: + * + * #define CK_DEFINE_FUNCTION(returnType, name) \ + * returnType name + * + * + * 3. CK_DECLARE_FUNCTION(returnType, name): A macro which makes + * an importable Cryptoki library function declaration out of a + * return type and a function name. It should be used in the + * following fashion: + * + * extern CK_DECLARE_FUNCTION(CK_RV, C_Initialize)( + * CK_VOID_PTR pReserved + * ); + * + * If you're using Microsoft Developer Studio 5.0 to declare a + * function in a Win32 Cryptoki .dll, it might be defined by: + * + * #define CK_DECLARE_FUNCTION(returnType, name) \ + * returnType __declspec(dllimport) name + * + * If you're using an earlier version of Microsoft Developer + * Studio to declare a function in a Win16 Cryptoki .dll, it + * might be defined by: + * + * #define CK_DECLARE_FUNCTION(returnType, name) \ + * returnType __export _far _pascal name + * + * In a UNIX environment, it might be defined by: + * + * #define CK_DECLARE_FUNCTION(returnType, name) \ + * returnType name + * + * + * 4. CK_DECLARE_FUNCTION_POINTER(returnType, name): A macro + * which makes a Cryptoki API function pointer declaration or + * function pointer type declaration out of a return type and a + * function name. It should be used in the following fashion: + * + * // Define funcPtr to be a pointer to a Cryptoki API function + * // taking arguments args and returning CK_RV. + * CK_DECLARE_FUNCTION_POINTER(CK_RV, funcPtr)(args); + * + * or + * + * // Define funcPtrType to be the type of a pointer to a + * // Cryptoki API function taking arguments args and returning + * // CK_RV, and then define funcPtr to be a variable of type + * // funcPtrType. + * typedef CK_DECLARE_FUNCTION_POINTER(CK_RV, funcPtrType)(args); + * funcPtrType funcPtr; + * + * If you're using Microsoft Developer Studio 5.0 to access + * functions in a Win32 Cryptoki .dll, in might be defined by: + * + * #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \ + * returnType __declspec(dllimport) (* name) + * + * If you're using an earlier version of Microsoft Developer + * Studio to access functions in a Win16 Cryptoki .dll, it might + * be defined by: + * + * #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \ + * returnType __export _far _pascal (* name) + * + * In a UNIX environment, it might be defined by: + * + * #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \ + * returnType (* name) + * + * + * 5. CK_CALLBACK_FUNCTION(returnType, name): A macro which makes + * a function pointer type for an application callback out of + * a return type for the callback and a name for the callback. + * It should be used in the following fashion: + * + * CK_CALLBACK_FUNCTION(CK_RV, myCallback)(args); + * + * to declare a function pointer, myCallback, to a callback + * which takes arguments args and returns a CK_RV. It can also + * be used like this: + * + * typedef CK_CALLBACK_FUNCTION(CK_RV, myCallbackType)(args); + * myCallbackType myCallback; + * + * If you're using Microsoft Developer Studio 5.0 to do Win32 + * Cryptoki development, it might be defined by: + * + * #define CK_CALLBACK_FUNCTION(returnType, name) \ + * returnType (* name) + * + * If you're using an earlier version of Microsoft Developer + * Studio to do Win16 development, it might be defined by: + * + * #define CK_CALLBACK_FUNCTION(returnType, name) \ + * returnType _far _pascal (* name) + * + * In a UNIX environment, it might be defined by: + * + * #define CK_CALLBACK_FUNCTION(returnType, name) \ + * returnType (* name) + * + * + * 6. NULL_PTR: This macro is the value of a NULL pointer. + * + * In any ANSI/ISO C environment (and in many others as well), + * this should best be defined by + * + * #ifndef NULL_PTR + * #define NULL_PTR 0 + * #endif + */ + + +/* All the various Cryptoki types and #define'd values are in the + * file pkcs11t.h. */ +#include "pkcs11t.h" + +#define __PASTE(x,y) x##y + + +/* ============================================================== + * Define the "extern" form of all the entry points. + * ============================================================== + */ + +#define CK_NEED_ARG_LIST 1 +#define CK_PKCS11_FUNCTION_INFO(name) \ + extern CK_DECLARE_FUNCTION(CK_RV, name) + +/* pkcs11f.h has all the information about the Cryptoki + * function prototypes. */ +#include "pkcs11f.h" + +#undef CK_NEED_ARG_LIST +#undef CK_PKCS11_FUNCTION_INFO + + +/* ============================================================== + * Define the typedef form of all the entry points. That is, for + * each Cryptoki function C_XXX, define a type CK_C_XXX which is + * a pointer to that kind of function. + * ============================================================== + */ + +#define CK_NEED_ARG_LIST 1 +#define CK_PKCS11_FUNCTION_INFO(name) \ + typedef CK_DECLARE_FUNCTION_POINTER(CK_RV, __PASTE(CK_,name)) + +/* pkcs11f.h has all the information about the Cryptoki + * function prototypes. */ +#include "pkcs11f.h" + +#undef CK_NEED_ARG_LIST +#undef CK_PKCS11_FUNCTION_INFO + + +/* ============================================================== + * Define structed vector of entry points. A CK_FUNCTION_LIST + * contains a CK_VERSION indicating a library's Cryptoki version + * and then a whole slew of function pointers to the routines in + * the library. This type was declared, but not defined, in + * pkcs11t.h. + * ============================================================== + */ + +#define CK_PKCS11_FUNCTION_INFO(name) \ + __PASTE(CK_,name) name; + +struct CK_FUNCTION_LIST { + + CK_VERSION version; /* Cryptoki version */ + +/* Pile all the function pointers into the CK_FUNCTION_LIST. */ +/* pkcs11f.h has all the information about the Cryptoki + * function prototypes. */ +#include "pkcs11f.h" + +}; + +#undef CK_PKCS11_FUNCTION_INFO + + +#undef __PASTE + +#ifdef __cplusplus +} +#endif + +#endif Index: openssl/crypto/engine/pkcs11f.h diff -u /dev/null openssl/crypto/engine/pkcs11f.h:1.1.1.1 --- /dev/null Wed Dec 23 17:47:11 2015 +++ openssl/crypto/engine/pkcs11f.h Wed Oct 24 23:27:09 2007 @@ -0,0 +1,912 @@ +/* pkcs11f.h include file for PKCS #11. */ +/* $Revision: 1.1.1.1 $ */ + +/* License to copy and use this software is granted provided that it is + * identified as "RSA Security Inc. PKCS #11 Cryptographic Token Interface + * (Cryptoki)" in all material mentioning or referencing this software. + + * License is also granted to make and use derivative works provided that + * such works are identified as "derived from the RSA Security Inc. PKCS #11 + * Cryptographic Token Interface (Cryptoki)" in all material mentioning or + * referencing the derived work. + + * RSA Security Inc. makes no representations concerning either the + * merchantability of this software or the suitability of this software for + * any particular purpose. It is provided "as is" without express or implied + * warranty of any kind. + */ + +/* This header file contains pretty much everything about all the */ +/* Cryptoki function prototypes. Because this information is */ +/* used for more than just declaring function prototypes, the */ +/* order of the functions appearing herein is important, and */ +/* should not be altered. */ + +/* General-purpose */ + +/* C_Initialize initializes the Cryptoki library. */ +CK_PKCS11_FUNCTION_INFO(C_Initialize) +#ifdef CK_NEED_ARG_LIST +( + CK_VOID_PTR pInitArgs /* if this is not NULL_PTR, it gets + * cast to CK_C_INITIALIZE_ARGS_PTR + * and dereferenced */ +); +#endif + + +/* C_Finalize indicates that an application is done with the + * Cryptoki library. */ +CK_PKCS11_FUNCTION_INFO(C_Finalize) +#ifdef CK_NEED_ARG_LIST +( + CK_VOID_PTR pReserved /* reserved. Should be NULL_PTR */ +); +#endif + + +/* C_GetInfo returns general information about Cryptoki. */ +CK_PKCS11_FUNCTION_INFO(C_GetInfo) +#ifdef CK_NEED_ARG_LIST +( + CK_INFO_PTR pInfo /* location that receives information */ +); +#endif + + +/* C_GetFunctionList returns the function list. */ +CK_PKCS11_FUNCTION_INFO(C_GetFunctionList) +#ifdef CK_NEED_ARG_LIST +( + CK_FUNCTION_LIST_PTR_PTR ppFunctionList /* receives pointer to + * function list */ +); +#endif + + + +/* Slot and token management */ + +/* C_GetSlotList obtains a list of slots in the system. */ +CK_PKCS11_FUNCTION_INFO(C_GetSlotList) +#ifdef CK_NEED_ARG_LIST +( + CK_BBOOL tokenPresent, /* only slots with tokens? */ + CK_SLOT_ID_PTR pSlotList, /* receives array of slot IDs */ + CK_ULONG_PTR pulCount /* receives number of slots */ +); +#endif + + +/* C_GetSlotInfo obtains information about a particular slot in + * the system. */ +CK_PKCS11_FUNCTION_INFO(C_GetSlotInfo) +#ifdef CK_NEED_ARG_LIST +( + CK_SLOT_ID slotID, /* the ID of the slot */ + CK_SLOT_INFO_PTR pInfo /* receives the slot information */ +); +#endif + + +/* C_GetTokenInfo obtains information about a particular token + * in the system. */ +CK_PKCS11_FUNCTION_INFO(C_GetTokenInfo) +#ifdef CK_NEED_ARG_LIST +( + CK_SLOT_ID slotID, /* ID of the token's slot */ + CK_TOKEN_INFO_PTR pInfo /* receives the token information */ +); +#endif + + +/* C_GetMechanismList obtains a list of mechanism types + * supported by a token. */ +CK_PKCS11_FUNCTION_INFO(C_GetMechanismList) +#ifdef CK_NEED_ARG_LIST +( + CK_SLOT_ID slotID, /* ID of token's slot */ + CK_MECHANISM_TYPE_PTR pMechanismList, /* gets mech. array */ + CK_ULONG_PTR pulCount /* gets # of mechs. */ +); +#endif + + +/* C_GetMechanismInfo obtains information about a particular + * mechanism possibly supported by a token. */ +CK_PKCS11_FUNCTION_INFO(C_GetMechanismInfo) +#ifdef CK_NEED_ARG_LIST +( + CK_SLOT_ID slotID, /* ID of the token's slot */ + CK_MECHANISM_TYPE type, /* type of mechanism */ + CK_MECHANISM_INFO_PTR pInfo /* receives mechanism info */ +); +#endif + + +/* C_InitToken initializes a token. */ +CK_PKCS11_FUNCTION_INFO(C_InitToken) +#ifdef CK_NEED_ARG_LIST +/* pLabel changed from CK_CHAR_PTR to CK_UTF8CHAR_PTR for v2.10 */ +( + CK_SLOT_ID slotID, /* ID of the token's slot */ + CK_UTF8CHAR_PTR pPin, /* the SO's initial PIN */ + CK_ULONG ulPinLen, /* length in bytes of the PIN */ + CK_UTF8CHAR_PTR pLabel /* 32-byte token label (blank padded) */ +); +#endif + + +/* C_InitPIN initializes the normal user's PIN. */ +CK_PKCS11_FUNCTION_INFO(C_InitPIN) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_UTF8CHAR_PTR pPin, /* the normal user's PIN */ + CK_ULONG ulPinLen /* length in bytes of the PIN */ +); +#endif + + +/* C_SetPIN modifies the PIN of the user who is logged in. */ +CK_PKCS11_FUNCTION_INFO(C_SetPIN) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_UTF8CHAR_PTR pOldPin, /* the old PIN */ + CK_ULONG ulOldLen, /* length of the old PIN */ + CK_UTF8CHAR_PTR pNewPin, /* the new PIN */ + CK_ULONG ulNewLen /* length of the new PIN */ +); +#endif + + + +/* Session management */ + +/* C_OpenSession opens a session between an application and a + * token. */ +CK_PKCS11_FUNCTION_INFO(C_OpenSession) +#ifdef CK_NEED_ARG_LIST +( + CK_SLOT_ID slotID, /* the slot's ID */ + CK_FLAGS flags, /* from CK_SESSION_INFO */ + CK_VOID_PTR pApplication, /* passed to callback */ + CK_NOTIFY Notify, /* callback function */ + CK_SESSION_HANDLE_PTR phSession /* gets session handle */ +); +#endif + + +/* C_CloseSession closes a session between an application and a + * token. */ +CK_PKCS11_FUNCTION_INFO(C_CloseSession) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession /* the session's handle */ +); +#endif + + +/* C_CloseAllSessions closes all sessions with a token. */ +CK_PKCS11_FUNCTION_INFO(C_CloseAllSessions) +#ifdef CK_NEED_ARG_LIST +( + CK_SLOT_ID slotID /* the token's slot */ +); +#endif + + +/* C_GetSessionInfo obtains information about the session. */ +CK_PKCS11_FUNCTION_INFO(C_GetSessionInfo) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_SESSION_INFO_PTR pInfo /* receives session info */ +); +#endif + + +/* C_GetOperationState obtains the state of the cryptographic operation + * in a session. */ +CK_PKCS11_FUNCTION_INFO(C_GetOperationState) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* session's handle */ + CK_BYTE_PTR pOperationState, /* gets state */ + CK_ULONG_PTR pulOperationStateLen /* gets state length */ +); +#endif + + +/* C_SetOperationState restores the state of the cryptographic + * operation in a session. */ +CK_PKCS11_FUNCTION_INFO(C_SetOperationState) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* session's handle */ + CK_BYTE_PTR pOperationState, /* holds state */ + CK_ULONG ulOperationStateLen, /* holds state length */ + CK_OBJECT_HANDLE hEncryptionKey, /* en/decryption key */ + CK_OBJECT_HANDLE hAuthenticationKey /* sign/verify key */ +); +#endif + + +/* C_Login logs a user into a token. */ +CK_PKCS11_FUNCTION_INFO(C_Login) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_USER_TYPE userType, /* the user type */ + CK_UTF8CHAR_PTR pPin, /* the user's PIN */ + CK_ULONG ulPinLen /* the length of the PIN */ +); +#endif + + +/* C_Logout logs a user out from a token. */ +CK_PKCS11_FUNCTION_INFO(C_Logout) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession /* the session's handle */ +); +#endif + + + +/* Object management */ + +/* C_CreateObject creates a new object. */ +CK_PKCS11_FUNCTION_INFO(C_CreateObject) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_ATTRIBUTE_PTR pTemplate, /* the object's template */ + CK_ULONG ulCount, /* attributes in template */ + CK_OBJECT_HANDLE_PTR phObject /* gets new object's handle. */ +); +#endif + + +/* C_CopyObject copies an object, creating a new object for the + * copy. */ +CK_PKCS11_FUNCTION_INFO(C_CopyObject) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_OBJECT_HANDLE hObject, /* the object's handle */ + CK_ATTRIBUTE_PTR pTemplate, /* template for new object */ + CK_ULONG ulCount, /* attributes in template */ + CK_OBJECT_HANDLE_PTR phNewObject /* receives handle of copy */ +); +#endif + + +/* C_DestroyObject destroys an object. */ +CK_PKCS11_FUNCTION_INFO(C_DestroyObject) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_OBJECT_HANDLE hObject /* the object's handle */ +); +#endif + + +/* C_GetObjectSize gets the size of an object in bytes. */ +CK_PKCS11_FUNCTION_INFO(C_GetObjectSize) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_OBJECT_HANDLE hObject, /* the object's handle */ + CK_ULONG_PTR pulSize /* receives size of object */ +); +#endif + + +/* C_GetAttributeValue obtains the value of one or more object + * attributes. */ +CK_PKCS11_FUNCTION_INFO(C_GetAttributeValue) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_OBJECT_HANDLE hObject, /* the object's handle */ + CK_ATTRIBUTE_PTR pTemplate, /* specifies attrs; gets vals */ + CK_ULONG ulCount /* attributes in template */ +); +#endif + + +/* C_SetAttributeValue modifies the value of one or more object + * attributes */ +CK_PKCS11_FUNCTION_INFO(C_SetAttributeValue) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_OBJECT_HANDLE hObject, /* the object's handle */ + CK_ATTRIBUTE_PTR pTemplate, /* specifies attrs and values */ + CK_ULONG ulCount /* attributes in template */ +); +#endif + + +/* C_FindObjectsInit initializes a search for token and session + * objects that match a template. */ +CK_PKCS11_FUNCTION_INFO(C_FindObjectsInit) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_ATTRIBUTE_PTR pTemplate, /* attribute values to match */ + CK_ULONG ulCount /* attrs in search template */ +); +#endif + + +/* C_FindObjects continues a search for token and session + * objects that match a template, obtaining additional object + * handles. */ +CK_PKCS11_FUNCTION_INFO(C_FindObjects) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* session's handle */ + CK_OBJECT_HANDLE_PTR phObject, /* gets obj. handles */ + CK_ULONG ulMaxObjectCount, /* max handles to get */ + CK_ULONG_PTR pulObjectCount /* actual # returned */ +); +#endif + + +/* C_FindObjectsFinal finishes a search for token and session + * objects. */ +CK_PKCS11_FUNCTION_INFO(C_FindObjectsFinal) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession /* the session's handle */ +); +#endif + + + +/* Encryption and decryption */ + +/* C_EncryptInit initializes an encryption operation. */ +CK_PKCS11_FUNCTION_INFO(C_EncryptInit) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_MECHANISM_PTR pMechanism, /* the encryption mechanism */ + CK_OBJECT_HANDLE hKey /* handle of encryption key */ +); +#endif + + +/* C_Encrypt encrypts single-part data. */ +CK_PKCS11_FUNCTION_INFO(C_Encrypt) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* session's handle */ + CK_BYTE_PTR pData, /* the plaintext data */ + CK_ULONG ulDataLen, /* bytes of plaintext */ + CK_BYTE_PTR pEncryptedData, /* gets ciphertext */ + CK_ULONG_PTR pulEncryptedDataLen /* gets c-text size */ +); +#endif + + +/* C_EncryptUpdate continues a multiple-part encryption + * operation. */ +CK_PKCS11_FUNCTION_INFO(C_EncryptUpdate) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* session's handle */ + CK_BYTE_PTR pPart, /* the plaintext data */ + CK_ULONG ulPartLen, /* plaintext data len */ + CK_BYTE_PTR pEncryptedPart, /* gets ciphertext */ + CK_ULONG_PTR pulEncryptedPartLen /* gets c-text size */ +); +#endif + + +/* C_EncryptFinal finishes a multiple-part encryption + * operation. */ +CK_PKCS11_FUNCTION_INFO(C_EncryptFinal) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* session handle */ + CK_BYTE_PTR pLastEncryptedPart, /* last c-text */ + CK_ULONG_PTR pulLastEncryptedPartLen /* gets last size */ +); +#endif + + +/* C_DecryptInit initializes a decryption operation. */ +CK_PKCS11_FUNCTION_INFO(C_DecryptInit) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_MECHANISM_PTR pMechanism, /* the decryption mechanism */ + CK_OBJECT_HANDLE hKey /* handle of decryption key */ +); +#endif + + +/* C_Decrypt decrypts encrypted data in a single part. */ +CK_PKCS11_FUNCTION_INFO(C_Decrypt) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* session's handle */ + CK_BYTE_PTR pEncryptedData, /* ciphertext */ + CK_ULONG ulEncryptedDataLen, /* ciphertext length */ + CK_BYTE_PTR pData, /* gets plaintext */ + CK_ULONG_PTR pulDataLen /* gets p-text size */ +); +#endif + + +/* C_DecryptUpdate continues a multiple-part decryption + * operation. */ +CK_PKCS11_FUNCTION_INFO(C_DecryptUpdate) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* session's handle */ + CK_BYTE_PTR pEncryptedPart, /* encrypted data */ + CK_ULONG ulEncryptedPartLen, /* input length */ + CK_BYTE_PTR pPart, /* gets plaintext */ + CK_ULONG_PTR pulPartLen /* p-text size */ +); +#endif + + +/* C_DecryptFinal finishes a multiple-part decryption + * operation. */ +CK_PKCS11_FUNCTION_INFO(C_DecryptFinal) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_BYTE_PTR pLastPart, /* gets plaintext */ + CK_ULONG_PTR pulLastPartLen /* p-text size */ +); +#endif + + + +/* Message digesting */ + +/* C_DigestInit initializes a message-digesting operation. */ +CK_PKCS11_FUNCTION_INFO(C_DigestInit) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_MECHANISM_PTR pMechanism /* the digesting mechanism */ +); +#endif + + +/* C_Digest digests data in a single part. */ +CK_PKCS11_FUNCTION_INFO(C_Digest) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_BYTE_PTR pData, /* data to be digested */ + CK_ULONG ulDataLen, /* bytes of data to digest */ + CK_BYTE_PTR pDigest, /* gets the message digest */ + CK_ULONG_PTR pulDigestLen /* gets digest length */ +); +#endif + + +/* C_DigestUpdate continues a multiple-part message-digesting + * operation. */ +CK_PKCS11_FUNCTION_INFO(C_DigestUpdate) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_BYTE_PTR pPart, /* data to be digested */ + CK_ULONG ulPartLen /* bytes of data to be digested */ +); +#endif + + +/* C_DigestKey continues a multi-part message-digesting + * operation, by digesting the value of a secret key as part of + * the data already digested. */ +CK_PKCS11_FUNCTION_INFO(C_DigestKey) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_OBJECT_HANDLE hKey /* secret key to digest */ +); +#endif + + +/* C_DigestFinal finishes a multiple-part message-digesting + * operation. */ +CK_PKCS11_FUNCTION_INFO(C_DigestFinal) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_BYTE_PTR pDigest, /* gets the message digest */ + CK_ULONG_PTR pulDigestLen /* gets byte count of digest */ +); +#endif + + + +/* Signing and MACing */ + +/* C_SignInit initializes a signature (private key encryption) + * operation, where the signature is (will be) an appendix to + * the data, and plaintext cannot be recovered from the + *signature. */ +CK_PKCS11_FUNCTION_INFO(C_SignInit) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_MECHANISM_PTR pMechanism, /* the signature mechanism */ + CK_OBJECT_HANDLE hKey /* handle of signature key */ +); +#endif + + +/* C_Sign signs (encrypts with private key) data in a single + * part, where the signature is (will be) an appendix to the + * data, and plaintext cannot be recovered from the signature. */ +CK_PKCS11_FUNCTION_INFO(C_Sign) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_BYTE_PTR pData, /* the data to sign */ + CK_ULONG ulDataLen, /* count of bytes to sign */ + CK_BYTE_PTR pSignature, /* gets the signature */ + CK_ULONG_PTR pulSignatureLen /* gets signature length */ +); +#endif + + +/* C_SignUpdate continues a multiple-part signature operation, + * where the signature is (will be) an appendix to the data, + * and plaintext cannot be recovered from the signature. */ +CK_PKCS11_FUNCTION_INFO(C_SignUpdate) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_BYTE_PTR pPart, /* the data to sign */ + CK_ULONG ulPartLen /* count of bytes to sign */ +); +#endif + + +/* C_SignFinal finishes a multiple-part signature operation, + * returning the signature. */ +CK_PKCS11_FUNCTION_INFO(C_SignFinal) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_BYTE_PTR pSignature, /* gets the signature */ + CK_ULONG_PTR pulSignatureLen /* gets signature length */ +); +#endif + + +/* C_SignRecoverInit initializes a signature operation, where + * the data can be recovered from the signature. */ +CK_PKCS11_FUNCTION_INFO(C_SignRecoverInit) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_MECHANISM_PTR pMechanism, /* the signature mechanism */ + CK_OBJECT_HANDLE hKey /* handle of the signature key */ +); +#endif + + +/* C_SignRecover signs data in a single operation, where the + * data can be recovered from the signature. */ +CK_PKCS11_FUNCTION_INFO(C_SignRecover) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_BYTE_PTR pData, /* the data to sign */ + CK_ULONG ulDataLen, /* count of bytes to sign */ + CK_BYTE_PTR pSignature, /* gets the signature */ + CK_ULONG_PTR pulSignatureLen /* gets signature length */ +); +#endif + + + +/* Verifying signatures and MACs */ + +/* C_VerifyInit initializes a verification operation, where the + * signature is an appendix to the data, and plaintext cannot + * cannot be recovered from the signature (e.g. DSA). */ +CK_PKCS11_FUNCTION_INFO(C_VerifyInit) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_MECHANISM_PTR pMechanism, /* the verification mechanism */ + CK_OBJECT_HANDLE hKey /* verification key */ +); +#endif + + +/* C_Verify verifies a signature in a single-part operation, + * where the signature is an appendix to the data, and plaintext + * cannot be recovered from the signature. */ +CK_PKCS11_FUNCTION_INFO(C_Verify) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_BYTE_PTR pData, /* signed data */ + CK_ULONG ulDataLen, /* length of signed data */ + CK_BYTE_PTR pSignature, /* signature */ + CK_ULONG ulSignatureLen /* signature length*/ +); +#endif + + +/* C_VerifyUpdate continues a multiple-part verification + * operation, where the signature is an appendix to the data, + * and plaintext cannot be recovered from the signature. */ +CK_PKCS11_FUNCTION_INFO(C_VerifyUpdate) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_BYTE_PTR pPart, /* signed data */ + CK_ULONG ulPartLen /* length of signed data */ +); +#endif + + +/* C_VerifyFinal finishes a multiple-part verification + * operation, checking the signature. */ +CK_PKCS11_FUNCTION_INFO(C_VerifyFinal) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_BYTE_PTR pSignature, /* signature to verify */ + CK_ULONG ulSignatureLen /* signature length */ +); +#endif + + +/* C_VerifyRecoverInit initializes a signature verification + * operation, where the data is recovered from the signature. */ +CK_PKCS11_FUNCTION_INFO(C_VerifyRecoverInit) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_MECHANISM_PTR pMechanism, /* the verification mechanism */ + CK_OBJECT_HANDLE hKey /* verification key */ +); +#endif + + +/* C_VerifyRecover verifies a signature in a single-part + * operation, where the data is recovered from the signature. */ +CK_PKCS11_FUNCTION_INFO(C_VerifyRecover) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_BYTE_PTR pSignature, /* signature to verify */ + CK_ULONG ulSignatureLen, /* signature length */ + CK_BYTE_PTR pData, /* gets signed data */ + CK_ULONG_PTR pulDataLen /* gets signed data len */ +); +#endif + + + +/* Dual-function cryptographic operations */ + +/* C_DigestEncryptUpdate continues a multiple-part digesting + * and encryption operation. */ +CK_PKCS11_FUNCTION_INFO(C_DigestEncryptUpdate) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* session's handle */ + CK_BYTE_PTR pPart, /* the plaintext data */ + CK_ULONG ulPartLen, /* plaintext length */ + CK_BYTE_PTR pEncryptedPart, /* gets ciphertext */ + CK_ULONG_PTR pulEncryptedPartLen /* gets c-text length */ +); +#endif + + +/* C_DecryptDigestUpdate continues a multiple-part decryption and + * digesting operation. */ +CK_PKCS11_FUNCTION_INFO(C_DecryptDigestUpdate) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* session's handle */ + CK_BYTE_PTR pEncryptedPart, /* ciphertext */ + CK_ULONG ulEncryptedPartLen, /* ciphertext length */ + CK_BYTE_PTR pPart, /* gets plaintext */ + CK_ULONG_PTR pulPartLen /* gets plaintext len */ +); +#endif + + +/* C_SignEncryptUpdate continues a multiple-part signing and + * encryption operation. */ +CK_PKCS11_FUNCTION_INFO(C_SignEncryptUpdate) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* session's handle */ + CK_BYTE_PTR pPart, /* the plaintext data */ + CK_ULONG ulPartLen, /* plaintext length */ + CK_BYTE_PTR pEncryptedPart, /* gets ciphertext */ + CK_ULONG_PTR pulEncryptedPartLen /* gets c-text length */ +); +#endif + + +/* C_DecryptVerifyUpdate continues a multiple-part decryption and + * verify operation. */ +CK_PKCS11_FUNCTION_INFO(C_DecryptVerifyUpdate) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* session's handle */ + CK_BYTE_PTR pEncryptedPart, /* ciphertext */ + CK_ULONG ulEncryptedPartLen, /* ciphertext length */ + CK_BYTE_PTR pPart, /* gets plaintext */ + CK_ULONG_PTR pulPartLen /* gets p-text length */ +); +#endif + + + +/* Key management */ + +/* C_GenerateKey generates a secret key, creating a new key + * object. */ +CK_PKCS11_FUNCTION_INFO(C_GenerateKey) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_MECHANISM_PTR pMechanism, /* key generation mech. */ + CK_ATTRIBUTE_PTR pTemplate, /* template for new key */ + CK_ULONG ulCount, /* # of attrs in template */ + CK_OBJECT_HANDLE_PTR phKey /* gets handle of new key */ +); +#endif + + +/* C_GenerateKeyPair generates a public-key/private-key pair, + * creating new key objects. */ +CK_PKCS11_FUNCTION_INFO(C_GenerateKeyPair) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* session + * handle */ + CK_MECHANISM_PTR pMechanism, /* key-gen + * mech. */ + CK_ATTRIBUTE_PTR pPublicKeyTemplate, /* template + * for pub. + * key */ + CK_ULONG ulPublicKeyAttributeCount, /* # pub. + * attrs. */ + CK_ATTRIBUTE_PTR pPrivateKeyTemplate, /* template + * for priv. + * key */ + CK_ULONG ulPrivateKeyAttributeCount, /* # priv. + * attrs. */ + CK_OBJECT_HANDLE_PTR phPublicKey, /* gets pub. + * key + * handle */ + CK_OBJECT_HANDLE_PTR phPrivateKey /* gets + * priv. key + * handle */ +); +#endif + + +/* C_WrapKey wraps (i.e., encrypts) a key. */ +CK_PKCS11_FUNCTION_INFO(C_WrapKey) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_MECHANISM_PTR pMechanism, /* the wrapping mechanism */ + CK_OBJECT_HANDLE hWrappingKey, /* wrapping key */ + CK_OBJECT_HANDLE hKey, /* key to be wrapped */ + CK_BYTE_PTR pWrappedKey, /* gets wrapped key */ + CK_ULONG_PTR pulWrappedKeyLen /* gets wrapped key size */ +); +#endif + + +/* C_UnwrapKey unwraps (decrypts) a wrapped key, creating a new + * key object. */ +CK_PKCS11_FUNCTION_INFO(C_UnwrapKey) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* session's handle */ + CK_MECHANISM_PTR pMechanism, /* unwrapping mech. */ + CK_OBJECT_HANDLE hUnwrappingKey, /* unwrapping key */ + CK_BYTE_PTR pWrappedKey, /* the wrapped key */ + CK_ULONG ulWrappedKeyLen, /* wrapped key len */ + CK_ATTRIBUTE_PTR pTemplate, /* new key template */ + CK_ULONG ulAttributeCount, /* template length */ + CK_OBJECT_HANDLE_PTR phKey /* gets new handle */ +); +#endif + + +/* C_DeriveKey derives a key from a base key, creating a new key + * object. */ +CK_PKCS11_FUNCTION_INFO(C_DeriveKey) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* session's handle */ + CK_MECHANISM_PTR pMechanism, /* key deriv. mech. */ + CK_OBJECT_HANDLE hBaseKey, /* base key */ + CK_ATTRIBUTE_PTR pTemplate, /* new key template */ + CK_ULONG ulAttributeCount, /* template length */ + CK_OBJECT_HANDLE_PTR phKey /* gets new handle */ +); +#endif + + + +/* Random number generation */ + +/* C_SeedRandom mixes additional seed material into the token's + * random number generator. */ +CK_PKCS11_FUNCTION_INFO(C_SeedRandom) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_BYTE_PTR pSeed, /* the seed material */ + CK_ULONG ulSeedLen /* length of seed material */ +); +#endif + + +/* C_GenerateRandom generates random data. */ +CK_PKCS11_FUNCTION_INFO(C_GenerateRandom) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_BYTE_PTR RandomData, /* receives the random data */ + CK_ULONG ulRandomLen /* # of bytes to generate */ +); +#endif + + + +/* Parallel function management */ + +/* C_GetFunctionStatus is a legacy function; it obtains an + * updated status of a function running in parallel with an + * application. */ +CK_PKCS11_FUNCTION_INFO(C_GetFunctionStatus) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession /* the session's handle */ +); +#endif + + +/* C_CancelFunction is a legacy function; it cancels a function + * running in parallel. */ +CK_PKCS11_FUNCTION_INFO(C_CancelFunction) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession /* the session's handle */ +); +#endif + + + +/* Functions added in for Cryptoki Version 2.01 or later */ + +/* C_WaitForSlotEvent waits for a slot event (token insertion, + * removal, etc.) to occur. */ +CK_PKCS11_FUNCTION_INFO(C_WaitForSlotEvent) +#ifdef CK_NEED_ARG_LIST +( + CK_FLAGS flags, /* blocking/nonblocking flag */ + CK_SLOT_ID_PTR pSlot, /* location that receives the slot ID */ + CK_VOID_PTR pRserved /* reserved. Should be NULL_PTR */ +); +#endif Index: openssl/crypto/engine/pkcs11t.h diff -u /dev/null openssl/crypto/engine/pkcs11t.h:1.2 --- /dev/null Wed Dec 23 17:47:11 2015 +++ openssl/crypto/engine/pkcs11t.h Sat Aug 30 11:58:07 2008 @@ -0,0 +1,1885 @@ +/* pkcs11t.h include file for PKCS #11. */ +/* $Revision: 1.2 $ */ + +/* License to copy and use this software is granted provided that it is + * identified as "RSA Security Inc. PKCS #11 Cryptographic Token Interface + * (Cryptoki)" in all material mentioning or referencing this software. + + * License is also granted to make and use derivative works provided that + * such works are identified as "derived from the RSA Security Inc. PKCS #11 + * Cryptographic Token Interface (Cryptoki)" in all material mentioning or + * referencing the derived work. + + * RSA Security Inc. makes no representations concerning either the + * merchantability of this software or the suitability of this software for + * any particular purpose. It is provided "as is" without express or implied + * warranty of any kind. + */ + +/* See top of pkcs11.h for information about the macros that + * must be defined and the structure-packing conventions that + * must be set before including this file. */ + +#ifndef _PKCS11T_H_ +#define _PKCS11T_H_ 1 + +#define CRYPTOKI_VERSION_MAJOR 2 +#define CRYPTOKI_VERSION_MINOR 20 +#define CRYPTOKI_VERSION_AMENDMENT 3 + +#define CK_TRUE 1 +#define CK_FALSE 0 + +#ifndef CK_DISABLE_TRUE_FALSE +#ifndef FALSE +#define FALSE CK_FALSE +#endif + +#ifndef TRUE +#define TRUE CK_TRUE +#endif +#endif + +/* an unsigned 8-bit value */ +typedef unsigned char CK_BYTE; + +/* an unsigned 8-bit character */ +typedef CK_BYTE CK_CHAR; + +/* an 8-bit UTF-8 character */ +typedef CK_BYTE CK_UTF8CHAR; + +/* a BYTE-sized Boolean flag */ +typedef CK_BYTE CK_BBOOL; + +/* an unsigned value, at least 32 bits long */ +typedef unsigned long int CK_ULONG; + +/* a signed value, the same size as a CK_ULONG */ +/* CK_LONG is new for v2.0 */ +typedef long int CK_LONG; + +/* at least 32 bits; each bit is a Boolean flag */ +typedef CK_ULONG CK_FLAGS; + + +/* some special values for certain CK_ULONG variables */ +#define CK_UNAVAILABLE_INFORMATION (~0UL) +#define CK_EFFECTIVELY_INFINITE 0 + + +typedef CK_BYTE CK_PTR CK_BYTE_PTR; +typedef CK_CHAR CK_PTR CK_CHAR_PTR; +typedef CK_UTF8CHAR CK_PTR CK_UTF8CHAR_PTR; +typedef CK_ULONG CK_PTR CK_ULONG_PTR; +typedef void CK_PTR CK_VOID_PTR; + +/* Pointer to a CK_VOID_PTR-- i.e., pointer to pointer to void */ +typedef CK_VOID_PTR CK_PTR CK_VOID_PTR_PTR; + + +/* The following value is always invalid if used as a session */ +/* handle or object handle */ +#define CK_INVALID_HANDLE 0 + + +typedef struct CK_VERSION { + CK_BYTE major; /* integer portion of version number */ + CK_BYTE minor; /* 1/100ths portion of version number */ +} CK_VERSION; + +typedef CK_VERSION CK_PTR CK_VERSION_PTR; + + +typedef struct CK_INFO { + /* manufacturerID and libraryDecription have been changed from + * CK_CHAR to CK_UTF8CHAR for v2.10 */ + CK_VERSION cryptokiVersion; /* Cryptoki interface ver */ + CK_UTF8CHAR manufacturerID[32]; /* blank padded */ + CK_FLAGS flags; /* must be zero */ + + /* libraryDescription and libraryVersion are new for v2.0 */ + CK_UTF8CHAR libraryDescription[32]; /* blank padded */ + CK_VERSION libraryVersion; /* version of library */ +} CK_INFO; + +typedef CK_INFO CK_PTR CK_INFO_PTR; + + +/* CK_NOTIFICATION enumerates the types of notifications that + * Cryptoki provides to an application */ +/* CK_NOTIFICATION has been changed from an enum to a CK_ULONG + * for v2.0 */ +typedef CK_ULONG CK_NOTIFICATION; +#define CKN_SURRENDER 0 + +/* The following notification is new for PKCS #11 v2.20 amendment 3 */ +#define CKN_OTP_CHANGED 1 + + +typedef CK_ULONG CK_SLOT_ID; + +typedef CK_SLOT_ID CK_PTR CK_SLOT_ID_PTR; + + +/* CK_SLOT_INFO provides information about a slot */ +typedef struct CK_SLOT_INFO { + /* slotDescription and manufacturerID have been changed from + * CK_CHAR to CK_UTF8CHAR for v2.10 */ + CK_UTF8CHAR slotDescription[64]; /* blank padded */ + CK_UTF8CHAR manufacturerID[32]; /* blank padded */ + CK_FLAGS flags; + + /* hardwareVersion and firmwareVersion are new for v2.0 */ + CK_VERSION hardwareVersion; /* version of hardware */ + CK_VERSION firmwareVersion; /* version of firmware */ +} CK_SLOT_INFO; + +/* flags: bit flags that provide capabilities of the slot + * Bit Flag Mask Meaning + */ +#define CKF_TOKEN_PRESENT 0x00000001 /* a token is there */ +#define CKF_REMOVABLE_DEVICE 0x00000002 /* removable devices*/ +#define CKF_HW_SLOT 0x00000004 /* hardware slot */ + +typedef CK_SLOT_INFO CK_PTR CK_SLOT_INFO_PTR; + + +/* CK_TOKEN_INFO provides information about a token */ +typedef struct CK_TOKEN_INFO { + /* label, manufacturerID, and model have been changed from + * CK_CHAR to CK_UTF8CHAR for v2.10 */ + CK_UTF8CHAR label[32]; /* blank padded */ + CK_UTF8CHAR manufacturerID[32]; /* blank padded */ + CK_UTF8CHAR model[16]; /* blank padded */ + CK_CHAR serialNumber[16]; /* blank padded */ + CK_FLAGS flags; /* see below */ + + /* ulMaxSessionCount, ulSessionCount, ulMaxRwSessionCount, + * ulRwSessionCount, ulMaxPinLen, and ulMinPinLen have all been + * changed from CK_USHORT to CK_ULONG for v2.0 */ + CK_ULONG ulMaxSessionCount; /* max open sessions */ + CK_ULONG ulSessionCount; /* sess. now open */ + CK_ULONG ulMaxRwSessionCount; /* max R/W sessions */ + CK_ULONG ulRwSessionCount; /* R/W sess. now open */ + CK_ULONG ulMaxPinLen; /* in bytes */ + CK_ULONG ulMinPinLen; /* in bytes */ + CK_ULONG ulTotalPublicMemory; /* in bytes */ + CK_ULONG ulFreePublicMemory; /* in bytes */ + CK_ULONG ulTotalPrivateMemory; /* in bytes */ + CK_ULONG ulFreePrivateMemory; /* in bytes */ + + /* hardwareVersion, firmwareVersion, and time are new for + * v2.0 */ + CK_VERSION hardwareVersion; /* version of hardware */ + CK_VERSION firmwareVersion; /* version of firmware */ + CK_CHAR utcTime[16]; /* time */ +} CK_TOKEN_INFO; + +/* The flags parameter is defined as follows: + * Bit Flag Mask Meaning + */ +#define CKF_RNG 0x00000001 /* has random # + * generator */ +#define CKF_WRITE_PROTECTED 0x00000002 /* token is + * write- + * protected */ +#define CKF_LOGIN_REQUIRED 0x00000004 /* user must + * login */ +#define CKF_USER_PIN_INITIALIZED 0x00000008 /* normal user's + * PIN is set */ + +/* CKF_RESTORE_KEY_NOT_NEEDED is new for v2.0. If it is set, + * that means that *every* time the state of cryptographic + * operations of a session is successfully saved, all keys + * needed to continue those operations are stored in the state */ +#define CKF_RESTORE_KEY_NOT_NEEDED 0x00000020 + +/* CKF_CLOCK_ON_TOKEN is new for v2.0. If it is set, that means + * that the token has some sort of clock. The time on that + * clock is returned in the token info structure */ +#define CKF_CLOCK_ON_TOKEN 0x00000040 + +/* CKF_PROTECTED_AUTHENTICATION_PATH is new for v2.0. If it is + * set, that means that there is some way for the user to login + * without sending a PIN through the Cryptoki library itself */ +#define CKF_PROTECTED_AUTHENTICATION_PATH 0x00000100 + +/* CKF_DUAL_CRYPTO_OPERATIONS is new for v2.0. If it is true, + * that means that a single session with the token can perform + * dual simultaneous cryptographic operations (digest and + * encrypt; decrypt and digest; sign and encrypt; and decrypt + * and sign) */ +#define CKF_DUAL_CRYPTO_OPERATIONS 0x00000200 + +/* CKF_TOKEN_INITIALIZED if new for v2.10. If it is true, the + * token has been initialized using C_InitializeToken or an + * equivalent mechanism outside the scope of PKCS #11. + * Calling C_InitializeToken when this flag is set will cause + * the token to be reinitialized. */ +#define CKF_TOKEN_INITIALIZED 0x00000400 + +/* CKF_SECONDARY_AUTHENTICATION if new for v2.10. If it is + * true, the token supports secondary authentication for + * private key objects. This flag is deprecated in v2.11 and + onwards. */ +#define CKF_SECONDARY_AUTHENTICATION 0x00000800 + +/* CKF_USER_PIN_COUNT_LOW if new for v2.10. If it is true, an + * incorrect user login PIN has been entered at least once + * since the last successful authentication. */ +#define CKF_USER_PIN_COUNT_LOW 0x00010000 + +/* CKF_USER_PIN_FINAL_TRY if new for v2.10. If it is true, + * supplying an incorrect user PIN will it to become locked. */ +#define CKF_USER_PIN_FINAL_TRY 0x00020000 + +/* CKF_USER_PIN_LOCKED if new for v2.10. If it is true, the + * user PIN has been locked. User login to the token is not + * possible. */ +#define CKF_USER_PIN_LOCKED 0x00040000 + +/* CKF_USER_PIN_TO_BE_CHANGED if new for v2.10. If it is true, + * the user PIN value is the default value set by token + * initialization or manufacturing, or the PIN has been + * expired by the card. */ +#define CKF_USER_PIN_TO_BE_CHANGED 0x00080000 + +/* CKF_SO_PIN_COUNT_LOW if new for v2.10. If it is true, an + * incorrect SO login PIN has been entered at least once since + * the last successful authentication. */ +#define CKF_SO_PIN_COUNT_LOW 0x00100000 + +/* CKF_SO_PIN_FINAL_TRY if new for v2.10. If it is true, + * supplying an incorrect SO PIN will it to become locked. */ +#define CKF_SO_PIN_FINAL_TRY 0x00200000 + +/* CKF_SO_PIN_LOCKED if new for v2.10. If it is true, the SO + * PIN has been locked. SO login to the token is not possible. + */ +#define CKF_SO_PIN_LOCKED 0x00400000 + +/* CKF_SO_PIN_TO_BE_CHANGED if new for v2.10. If it is true, + * the SO PIN value is the default value set by token + * initialization or manufacturing, or the PIN has been + * expired by the card. */ +#define CKF_SO_PIN_TO_BE_CHANGED 0x00800000 + +typedef CK_TOKEN_INFO CK_PTR CK_TOKEN_INFO_PTR; + + +/* CK_SESSION_HANDLE is a Cryptoki-assigned value that + * identifies a session */ +typedef CK_ULONG CK_SESSION_HANDLE; + +typedef CK_SESSION_HANDLE CK_PTR CK_SESSION_HANDLE_PTR; + + +/* CK_USER_TYPE enumerates the types of Cryptoki users */ +/* CK_USER_TYPE has been changed from an enum to a CK_ULONG for + * v2.0 */ +typedef CK_ULONG CK_USER_TYPE; +/* Security Officer */ +#define CKU_SO 0 +/* Normal user */ +#define CKU_USER 1 +/* Context specific (added in v2.20) */ +#define CKU_CONTEXT_SPECIFIC 2 + +/* CK_STATE enumerates the session states */ +/* CK_STATE has been changed from an enum to a CK_ULONG for + * v2.0 */ +typedef CK_ULONG CK_STATE; +#define CKS_RO_PUBLIC_SESSION 0 +#define CKS_RO_USER_FUNCTIONS 1 +#define CKS_RW_PUBLIC_SESSION 2 +#define CKS_RW_USER_FUNCTIONS 3 +#define CKS_RW_SO_FUNCTIONS 4 + + +/* CK_SESSION_INFO provides information about a session */ +typedef struct CK_SESSION_INFO { + CK_SLOT_ID slotID; + CK_STATE state; + CK_FLAGS flags; /* see below */ + + /* ulDeviceError was changed from CK_USHORT to CK_ULONG for + * v2.0 */ + CK_ULONG ulDeviceError; /* device-dependent error code */ +} CK_SESSION_INFO; + +/* The flags are defined in the following table: + * Bit Flag Mask Meaning + */ +#define CKF_RW_SESSION 0x00000002 /* session is r/w */ +#define CKF_SERIAL_SESSION 0x00000004 /* no parallel */ + +typedef CK_SESSION_INFO CK_PTR CK_SESSION_INFO_PTR; + + +/* CK_OBJECT_HANDLE is a token-specific identifier for an + * object */ +typedef CK_ULONG CK_OBJECT_HANDLE; + +typedef CK_OBJECT_HANDLE CK_PTR CK_OBJECT_HANDLE_PTR; + + +/* CK_OBJECT_CLASS is a value that identifies the classes (or + * types) of objects that Cryptoki recognizes. It is defined + * as follows: */ +/* CK_OBJECT_CLASS was changed from CK_USHORT to CK_ULONG for + * v2.0 */ +typedef CK_ULONG CK_OBJECT_CLASS; + +/* The following classes of objects are defined: */ +/* CKO_HW_FEATURE is new for v2.10 */ +/* CKO_DOMAIN_PARAMETERS is new for v2.11 */ +/* CKO_MECHANISM is new for v2.20 */ +#define CKO_DATA 0x00000000 +#define CKO_CERTIFICATE 0x00000001 +#define CKO_PUBLIC_KEY 0x00000002 +#define CKO_PRIVATE_KEY 0x00000003 +#define CKO_SECRET_KEY 0x00000004 +#define CKO_HW_FEATURE 0x00000005 +#define CKO_DOMAIN_PARAMETERS 0x00000006 +#define CKO_MECHANISM 0x00000007 + +/* CKO_OTP_KEY is new for PKCS #11 v2.20 amendment 1 */ +#define CKO_OTP_KEY 0x00000008 + +#define CKO_VENDOR_DEFINED 0x80000000 + +typedef CK_OBJECT_CLASS CK_PTR CK_OBJECT_CLASS_PTR; + +/* CK_HW_FEATURE_TYPE is new for v2.10. CK_HW_FEATURE_TYPE is a + * value that identifies the hardware feature type of an object + * with CK_OBJECT_CLASS equal to CKO_HW_FEATURE. */ +typedef CK_ULONG CK_HW_FEATURE_TYPE; + +/* The following hardware feature types are defined */ +/* CKH_USER_INTERFACE is new for v2.20 */ +#define CKH_MONOTONIC_COUNTER 0x00000001 +#define CKH_CLOCK 0x00000002 +#define CKH_USER_INTERFACE 0x00000003 +#define CKH_VENDOR_DEFINED 0x80000000 + +/* CK_KEY_TYPE is a value that identifies a key type */ +/* CK_KEY_TYPE was changed from CK_USHORT to CK_ULONG for v2.0 */ +typedef CK_ULONG CK_KEY_TYPE; + +/* the following key types are defined: */ +#define CKK_RSA 0x00000000 +#define CKK_DSA 0x00000001 +#define CKK_DH 0x00000002 + +/* CKK_ECDSA and CKK_KEA are new for v2.0 */ +/* CKK_ECDSA is deprecated in v2.11, CKK_EC is preferred. */ +#define CKK_ECDSA 0x00000003 +#define CKK_EC 0x00000003 +#define CKK_X9_42_DH 0x00000004 +#define CKK_KEA 0x00000005 + +#define CKK_GENERIC_SECRET 0x00000010 +#define CKK_RC2 0x00000011 +#define CKK_RC4 0x00000012 +#define CKK_DES 0x00000013 +#define CKK_DES2 0x00000014 +#define CKK_DES3 0x00000015 + +/* all these key types are new for v2.0 */ +#define CKK_CAST 0x00000016 +#define CKK_CAST3 0x00000017 +/* CKK_CAST5 is deprecated in v2.11, CKK_CAST128 is preferred. */ +#define CKK_CAST5 0x00000018 +#define CKK_CAST128 0x00000018 +#define CKK_RC5 0x00000019 +#define CKK_IDEA 0x0000001A +#define CKK_SKIPJACK 0x0000001B +#define CKK_BATON 0x0000001C +#define CKK_JUNIPER 0x0000001D +#define CKK_CDMF 0x0000001E +#define CKK_AES 0x0000001F + +/* BlowFish and TwoFish are new for v2.20 */ +#define CKK_BLOWFISH 0x00000020 +#define CKK_TWOFISH 0x00000021 + +/* SecurID, HOTP, and ACTI are new for PKCS #11 v2.20 amendment 1 */ +#define CKK_SECURID 0x00000022 +#define CKK_HOTP 0x00000023 +#define CKK_ACTI 0x00000024 + +/* Camellia is new for PKCS #11 v2.20 amendment 3 */ +#define CKK_CAMELLIA 0x00000025 +/* ARIA is new for PKCS #11 v2.20 amendment 3 */ +#define CKK_ARIA 0x00000026 + + +#define CKK_VENDOR_DEFINED 0x80000000 + + +/* CK_CERTIFICATE_TYPE is a value that identifies a certificate + * type */ +/* CK_CERTIFICATE_TYPE was changed from CK_USHORT to CK_ULONG + * for v2.0 */ +typedef CK_ULONG CK_CERTIFICATE_TYPE; + +/* The following certificate types are defined: */ +/* CKC_X_509_ATTR_CERT is new for v2.10 */ +/* CKC_WTLS is new for v2.20 */ +#define CKC_X_509 0x00000000 +#define CKC_X_509_ATTR_CERT 0x00000001 +#define CKC_WTLS 0x00000002 +#define CKC_VENDOR_DEFINED 0x80000000 + + +/* CK_ATTRIBUTE_TYPE is a value that identifies an attribute + * type */ +/* CK_ATTRIBUTE_TYPE was changed from CK_USHORT to CK_ULONG for + * v2.0 */ +typedef CK_ULONG CK_ATTRIBUTE_TYPE; + +/* The CKF_ARRAY_ATTRIBUTE flag identifies an attribute which + consists of an array of values. */ +#define CKF_ARRAY_ATTRIBUTE 0x40000000 + +/* The following OTP-related defines are new for PKCS #11 v2.20 amendment 1 + and relates to the CKA_OTP_FORMAT attribute */ +#define CK_OTP_FORMAT_DECIMAL 0 +#define CK_OTP_FORMAT_HEXADECIMAL 1 +#define CK_OTP_FORMAT_ALPHANUMERIC 2 +#define CK_OTP_FORMAT_BINARY 3 + +/* The following OTP-related defines are new for PKCS #11 v2.20 amendment 1 + and relates to the CKA_OTP_..._REQUIREMENT attributes */ +#define CK_OTP_PARAM_IGNORED 0 +#define CK_OTP_PARAM_OPTIONAL 1 +#define CK_OTP_PARAM_MANDATORY 2 + +/* The following attribute types are defined: */ +#define CKA_CLASS 0x00000000 +#define CKA_TOKEN 0x00000001 +#define CKA_PRIVATE 0x00000002 +#define CKA_LABEL 0x00000003 +#define CKA_APPLICATION 0x00000010 +#define CKA_VALUE 0x00000011 + +/* CKA_OBJECT_ID is new for v2.10 */ +#define CKA_OBJECT_ID 0x00000012 + +#define CKA_CERTIFICATE_TYPE 0x00000080 +#define CKA_ISSUER 0x00000081 +#define CKA_SERIAL_NUMBER 0x00000082 + +/* CKA_AC_ISSUER, CKA_OWNER, and CKA_ATTR_TYPES are new + * for v2.10 */ +#define CKA_AC_ISSUER 0x00000083 +#define CKA_OWNER 0x00000084 +#define CKA_ATTR_TYPES 0x00000085 + +/* CKA_TRUSTED is new for v2.11 */ +#define CKA_TRUSTED 0x00000086 + +/* CKA_CERTIFICATE_CATEGORY ... + * CKA_CHECK_VALUE are new for v2.20 */ +#define CKA_CERTIFICATE_CATEGORY 0x00000087 +#define CKA_JAVA_MIDP_SECURITY_DOMAIN 0x00000088 +#define CKA_URL 0x00000089 +#define CKA_HASH_OF_SUBJECT_PUBLIC_KEY 0x0000008A +#define CKA_HASH_OF_ISSUER_PUBLIC_KEY 0x0000008B +#define CKA_CHECK_VALUE 0x00000090 + +#define CKA_KEY_TYPE 0x00000100 +#define CKA_SUBJECT 0x00000101 +#define CKA_ID 0x00000102 +#define CKA_SENSITIVE 0x00000103 +#define CKA_ENCRYPT 0x00000104 +#define CKA_DECRYPT 0x00000105 +#define CKA_WRAP 0x00000106 +#define CKA_UNWRAP 0x00000107 +#define CKA_SIGN 0x00000108 +#define CKA_SIGN_RECOVER 0x00000109 +#define CKA_VERIFY 0x0000010A +#define CKA_VERIFY_RECOVER 0x0000010B +#define CKA_DERIVE 0x0000010C +#define CKA_START_DATE 0x00000110 +#define CKA_END_DATE 0x00000111 +#define CKA_MODULUS 0x00000120 +#define CKA_MODULUS_BITS 0x00000121 +#define CKA_PUBLIC_EXPONENT 0x00000122 +#define CKA_PRIVATE_EXPONENT 0x00000123 +#define CKA_PRIME_1 0x00000124 +#define CKA_PRIME_2 0x00000125 +#define CKA_EXPONENT_1 0x00000126 +#define CKA_EXPONENT_2 0x00000127 +#define CKA_COEFFICIENT 0x00000128 +#define CKA_PRIME 0x00000130 +#define CKA_SUBPRIME 0x00000131 +#define CKA_BASE 0x00000132 + +/* CKA_PRIME_BITS and CKA_SUB_PRIME_BITS are new for v2.11 */ +#define CKA_PRIME_BITS 0x00000133 +#define CKA_SUBPRIME_BITS 0x00000134 +#define CKA_SUB_PRIME_BITS CKA_SUBPRIME_BITS +/* (To retain backwards-compatibility) */ + +#define CKA_VALUE_BITS 0x00000160 +#define CKA_VALUE_LEN 0x00000161 + +/* CKA_EXTRACTABLE, CKA_LOCAL, CKA_NEVER_EXTRACTABLE, + * CKA_ALWAYS_SENSITIVE, CKA_MODIFIABLE, CKA_ECDSA_PARAMS, + * and CKA_EC_POINT are new for v2.0 */ +#define CKA_EXTRACTABLE 0x00000162 +#define CKA_LOCAL 0x00000163 +#define CKA_NEVER_EXTRACTABLE 0x00000164 +#define CKA_ALWAYS_SENSITIVE 0x00000165 + +/* CKA_KEY_GEN_MECHANISM is new for v2.11 */ +#define CKA_KEY_GEN_MECHANISM 0x00000166 + +#define CKA_MODIFIABLE 0x00000170 + +/* CKA_ECDSA_PARAMS is deprecated in v2.11, + * CKA_EC_PARAMS is preferred. */ +#define CKA_ECDSA_PARAMS 0x00000180 +#define CKA_EC_PARAMS 0x00000180 + +#define CKA_EC_POINT 0x00000181 + +/* CKA_SECONDARY_AUTH, CKA_AUTH_PIN_FLAGS, + * are new for v2.10. Deprecated in v2.11 and onwards. */ +#define CKA_SECONDARY_AUTH 0x00000200 +#define CKA_AUTH_PIN_FLAGS 0x00000201 + +/* CKA_ALWAYS_AUTHENTICATE ... + * CKA_UNWRAP_TEMPLATE are new for v2.20 */ +#define CKA_ALWAYS_AUTHENTICATE 0x00000202 + +#define CKA_WRAP_WITH_TRUSTED 0x00000210 +#define CKA_WRAP_TEMPLATE (CKF_ARRAY_ATTRIBUTE|0x00000211) +#define CKA_UNWRAP_TEMPLATE (CKF_ARRAY_ATTRIBUTE|0x00000212) + +/* CKA_OTP... atttributes are new for PKCS #11 v2.20 amendment 3. */ +#define CKA_OTP_FORMAT 0x00000220 +#define CKA_OTP_LENGTH 0x00000221 +#define CKA_OTP_TIME_INTERVAL 0x00000222 +#define CKA_OTP_USER_FRIENDLY_MODE 0x00000223 +#define CKA_OTP_CHALLENGE_REQUIREMENT 0x00000224 +#define CKA_OTP_TIME_REQUIREMENT 0x00000225 +#define CKA_OTP_COUNTER_REQUIREMENT 0x00000226 +#define CKA_OTP_PIN_REQUIREMENT 0x00000227 +#define CKA_OTP_COUNTER 0x0000022E +#define CKA_OTP_TIME 0x0000022F +#define CKA_OTP_USER_IDENTIFIER 0x0000022A +#define CKA_OTP_SERVICE_IDENTIFIER 0x0000022B +#define CKA_OTP_SERVICE_LOGO 0x0000022C +#define CKA_OTP_SERVICE_LOGO_TYPE 0x0000022D + + +/* CKA_HW_FEATURE_TYPE, CKA_RESET_ON_INIT, and CKA_HAS_RESET + * are new for v2.10 */ +#define CKA_HW_FEATURE_TYPE 0x00000300 +#define CKA_RESET_ON_INIT 0x00000301 +#define CKA_HAS_RESET 0x00000302 + +/* The following attributes are new for v2.20 */ +#define CKA_PIXEL_X 0x00000400 +#define CKA_PIXEL_Y 0x00000401 +#define CKA_RESOLUTION 0x00000402 +#define CKA_CHAR_ROWS 0x00000403 +#define CKA_CHAR_COLUMNS 0x00000404 +#define CKA_COLOR 0x00000405 +#define CKA_BITS_PER_PIXEL 0x00000406 +#define CKA_CHAR_SETS 0x00000480 +#define CKA_ENCODING_METHODS 0x00000481 +#define CKA_MIME_TYPES 0x00000482 +#define CKA_MECHANISM_TYPE 0x00000500 +#define CKA_REQUIRED_CMS_ATTRIBUTES 0x00000501 +#define CKA_DEFAULT_CMS_ATTRIBUTES 0x00000502 +#define CKA_SUPPORTED_CMS_ATTRIBUTES 0x00000503 +#define CKA_ALLOWED_MECHANISMS (CKF_ARRAY_ATTRIBUTE|0x00000600) + +#define CKA_VENDOR_DEFINED 0x80000000 + +/* CK_ATTRIBUTE is a structure that includes the type, length + * and value of an attribute */ +typedef struct CK_ATTRIBUTE { + CK_ATTRIBUTE_TYPE type; + CK_VOID_PTR pValue; + + /* ulValueLen went from CK_USHORT to CK_ULONG for v2.0 */ + CK_ULONG ulValueLen; /* in bytes */ +} CK_ATTRIBUTE; + +typedef CK_ATTRIBUTE CK_PTR CK_ATTRIBUTE_PTR; + + +/* CK_DATE is a structure that defines a date */ +typedef struct CK_DATE{ + CK_CHAR year[4]; /* the year ("1900" - "9999") */ + CK_CHAR month[2]; /* the month ("01" - "12") */ + CK_CHAR day[2]; /* the day ("01" - "31") */ +} CK_DATE; + + +/* CK_MECHANISM_TYPE is a value that identifies a mechanism + * type */ +/* CK_MECHANISM_TYPE was changed from CK_USHORT to CK_ULONG for + * v2.0 */ +typedef CK_ULONG CK_MECHANISM_TYPE; + +/* the following mechanism types are defined: */ +#define CKM_RSA_PKCS_KEY_PAIR_GEN 0x00000000 +#define CKM_RSA_PKCS 0x00000001 +#define CKM_RSA_9796 0x00000002 +#define CKM_RSA_X_509 0x00000003 + +/* CKM_MD2_RSA_PKCS, CKM_MD5_RSA_PKCS, and CKM_SHA1_RSA_PKCS + * are new for v2.0. They are mechanisms which hash and sign */ +#define CKM_MD2_RSA_PKCS 0x00000004 +#define CKM_MD5_RSA_PKCS 0x00000005 +#define CKM_SHA1_RSA_PKCS 0x00000006 + +/* CKM_RIPEMD128_RSA_PKCS, CKM_RIPEMD160_RSA_PKCS, and + * CKM_RSA_PKCS_OAEP are new for v2.10 */ +#define CKM_RIPEMD128_RSA_PKCS 0x00000007 +#define CKM_RIPEMD160_RSA_PKCS 0x00000008 +#define CKM_RSA_PKCS_OAEP 0x00000009 + +/* CKM_RSA_X9_31_KEY_PAIR_GEN, CKM_RSA_X9_31, CKM_SHA1_RSA_X9_31, + * CKM_RSA_PKCS_PSS, and CKM_SHA1_RSA_PKCS_PSS are new for v2.11 */ +#define CKM_RSA_X9_31_KEY_PAIR_GEN 0x0000000A +#define CKM_RSA_X9_31 0x0000000B +#define CKM_SHA1_RSA_X9_31 0x0000000C +#define CKM_RSA_PKCS_PSS 0x0000000D +#define CKM_SHA1_RSA_PKCS_PSS 0x0000000E + +#define CKM_DSA_KEY_PAIR_GEN 0x00000010 +#define CKM_DSA 0x00000011 +#define CKM_DSA_SHA1 0x00000012 +#define CKM_DH_PKCS_KEY_PAIR_GEN 0x00000020 +#define CKM_DH_PKCS_DERIVE 0x00000021 + +/* CKM_X9_42_DH_KEY_PAIR_GEN, CKM_X9_42_DH_DERIVE, + * CKM_X9_42_DH_HYBRID_DERIVE, and CKM_X9_42_MQV_DERIVE are new for + * v2.11 */ +#define CKM_X9_42_DH_KEY_PAIR_GEN 0x00000030 +#define CKM_X9_42_DH_DERIVE 0x00000031 +#define CKM_X9_42_DH_HYBRID_DERIVE 0x00000032 +#define CKM_X9_42_MQV_DERIVE 0x00000033 + +/* CKM_SHA256/384/512 are new for v2.20 */ +#define CKM_SHA256_RSA_PKCS 0x00000040 +#define CKM_SHA384_RSA_PKCS 0x00000041 +#define CKM_SHA512_RSA_PKCS 0x00000042 +#define CKM_SHA256_RSA_PKCS_PSS 0x00000043 +#define CKM_SHA384_RSA_PKCS_PSS 0x00000044 +#define CKM_SHA512_RSA_PKCS_PSS 0x00000045 + +/* SHA-224 RSA mechanisms are new for PKCS #11 v2.20 amendment 3 */ +#define CKM_SHA224_RSA_PKCS 0x00000046 +#define CKM_SHA224_RSA_PKCS_PSS 0x00000047 + +#define CKM_RC2_KEY_GEN 0x00000100 +#define CKM_RC2_ECB 0x00000101 +#define CKM_RC2_CBC 0x00000102 +#define CKM_RC2_MAC 0x00000103 + +/* CKM_RC2_MAC_GENERAL and CKM_RC2_CBC_PAD are new for v2.0 */ +#define CKM_RC2_MAC_GENERAL 0x00000104 +#define CKM_RC2_CBC_PAD 0x00000105 + +#define CKM_RC4_KEY_GEN 0x00000110 +#define CKM_RC4 0x00000111 +#define CKM_DES_KEY_GEN 0x00000120 +#define CKM_DES_ECB 0x00000121 +#define CKM_DES_CBC 0x00000122 +#define CKM_DES_MAC 0x00000123 + +/* CKM_DES_MAC_GENERAL and CKM_DES_CBC_PAD are new for v2.0 */ +#define CKM_DES_MAC_GENERAL 0x00000124 +#define CKM_DES_CBC_PAD 0x00000125 + +#define CKM_DES2_KEY_GEN 0x00000130 +#define CKM_DES3_KEY_GEN 0x00000131 +#define CKM_DES3_ECB 0x00000132 +#define CKM_DES3_CBC 0x00000133 +#define CKM_DES3_MAC 0x00000134 + +/* CKM_DES3_MAC_GENERAL, CKM_DES3_CBC_PAD, CKM_CDMF_KEY_GEN, + * CKM_CDMF_ECB, CKM_CDMF_CBC, CKM_CDMF_MAC, + * CKM_CDMF_MAC_GENERAL, and CKM_CDMF_CBC_PAD are new for v2.0 */ +#define CKM_DES3_MAC_GENERAL 0x00000135 +#define CKM_DES3_CBC_PAD 0x00000136 +#define CKM_CDMF_KEY_GEN 0x00000140 +#define CKM_CDMF_ECB 0x00000141 +#define CKM_CDMF_CBC 0x00000142 +#define CKM_CDMF_MAC 0x00000143 +#define CKM_CDMF_MAC_GENERAL 0x00000144 +#define CKM_CDMF_CBC_PAD 0x00000145 + +/* the following four DES mechanisms are new for v2.20 */ +#define CKM_DES_OFB64 0x00000150 +#define CKM_DES_OFB8 0x00000151 +#define CKM_DES_CFB64 0x00000152 +#define CKM_DES_CFB8 0x00000153 + +#define CKM_MD2 0x00000200 + +/* CKM_MD2_HMAC and CKM_MD2_HMAC_GENERAL are new for v2.0 */ +#define CKM_MD2_HMAC 0x00000201 +#define CKM_MD2_HMAC_GENERAL 0x00000202 + +#define CKM_MD5 0x00000210 + +/* CKM_MD5_HMAC and CKM_MD5_HMAC_GENERAL are new for v2.0 */ +#define CKM_MD5_HMAC 0x00000211 +#define CKM_MD5_HMAC_GENERAL 0x00000212 + +#define CKM_SHA_1 0x00000220 + +/* CKM_SHA_1_HMAC and CKM_SHA_1_HMAC_GENERAL are new for v2.0 */ +#define CKM_SHA_1_HMAC 0x00000221 +#define CKM_SHA_1_HMAC_GENERAL 0x00000222 + +/* CKM_RIPEMD128, CKM_RIPEMD128_HMAC, + * CKM_RIPEMD128_HMAC_GENERAL, CKM_RIPEMD160, CKM_RIPEMD160_HMAC, + * and CKM_RIPEMD160_HMAC_GENERAL are new for v2.10 */ +#define CKM_RIPEMD128 0x00000230 +#define CKM_RIPEMD128_HMAC 0x00000231 +#define CKM_RIPEMD128_HMAC_GENERAL 0x00000232 +#define CKM_RIPEMD160 0x00000240 +#define CKM_RIPEMD160_HMAC 0x00000241 +#define CKM_RIPEMD160_HMAC_GENERAL 0x00000242 + +/* CKM_SHA256/384/512 are new for v2.20 */ +#define CKM_SHA256 0x00000250 +#define CKM_SHA256_HMAC 0x00000251 +#define CKM_SHA256_HMAC_GENERAL 0x00000252 + +/* SHA-224 is new for PKCS #11 v2.20 amendment 3 */ +#define CKM_SHA224 0x00000255 +#define CKM_SHA224_HMAC 0x00000256 +#define CKM_SHA224_HMAC_GENERAL 0x00000257 + +#define CKM_SHA384 0x00000260 +#define CKM_SHA384_HMAC 0x00000261 +#define CKM_SHA384_HMAC_GENERAL 0x00000262 +#define CKM_SHA512 0x00000270 +#define CKM_SHA512_HMAC 0x00000271 +#define CKM_SHA512_HMAC_GENERAL 0x00000272 + +/* SecurID is new for PKCS #11 v2.20 amendment 1 */ +#define CKM_SECURID_KEY_GEN 0x00000280 +#define CKM_SECURID 0x00000282 + +/* HOTP is new for PKCS #11 v2.20 amendment 1 */ +#define CKM_HOTP_KEY_GEN 0x00000290 +#define CKM_HOTP 0x00000291 + +/* ACTI is new for PKCS #11 v2.20 amendment 1 */ +#define CKM_ACTI 0x000002A0 +#define CKM_ACTI_KEY_GEN 0x000002A1 + +/* All of the following mechanisms are new for v2.0 */ +/* Note that CAST128 and CAST5 are the same algorithm */ +#define CKM_CAST_KEY_GEN 0x00000300 +#define CKM_CAST_ECB 0x00000301 +#define CKM_CAST_CBC 0x00000302 +#define CKM_CAST_MAC 0x00000303 +#define CKM_CAST_MAC_GENERAL 0x00000304 +#define CKM_CAST_CBC_PAD 0x00000305 +#define CKM_CAST3_KEY_GEN 0x00000310 +#define CKM_CAST3_ECB 0x00000311 +#define CKM_CAST3_CBC 0x00000312 +#define CKM_CAST3_MAC 0x00000313 +#define CKM_CAST3_MAC_GENERAL 0x00000314 +#define CKM_CAST3_CBC_PAD 0x00000315 +#define CKM_CAST5_KEY_GEN 0x00000320 +#define CKM_CAST128_KEY_GEN 0x00000320 +#define CKM_CAST5_ECB 0x00000321 +#define CKM_CAST128_ECB 0x00000321 +#define CKM_CAST5_CBC 0x00000322 +#define CKM_CAST128_CBC 0x00000322 +#define CKM_CAST5_MAC 0x00000323 +#define CKM_CAST128_MAC 0x00000323 +#define CKM_CAST5_MAC_GENERAL 0x00000324 +#define CKM_CAST128_MAC_GENERAL 0x00000324 +#define CKM_CAST5_CBC_PAD 0x00000325 +#define CKM_CAST128_CBC_PAD 0x00000325 +#define CKM_RC5_KEY_GEN 0x00000330 +#define CKM_RC5_ECB 0x00000331 +#define CKM_RC5_CBC 0x00000332 +#define CKM_RC5_MAC 0x00000333 +#define CKM_RC5_MAC_GENERAL 0x00000334 +#define CKM_RC5_CBC_PAD 0x00000335 +#define CKM_IDEA_KEY_GEN 0x00000340 +#define CKM_IDEA_ECB 0x00000341 +#define CKM_IDEA_CBC 0x00000342 +#define CKM_IDEA_MAC 0x00000343 +#define CKM_IDEA_MAC_GENERAL 0x00000344 +#define CKM_IDEA_CBC_PAD 0x00000345 +#define CKM_GENERIC_SECRET_KEY_GEN 0x00000350 +#define CKM_CONCATENATE_BASE_AND_KEY 0x00000360 +#define CKM_CONCATENATE_BASE_AND_DATA 0x00000362 +#define CKM_CONCATENATE_DATA_AND_BASE 0x00000363 +#define CKM_XOR_BASE_AND_DATA 0x00000364 +#define CKM_EXTRACT_KEY_FROM_KEY 0x00000365 +#define CKM_SSL3_PRE_MASTER_KEY_GEN 0x00000370 +#define CKM_SSL3_MASTER_KEY_DERIVE 0x00000371 +#define CKM_SSL3_KEY_AND_MAC_DERIVE 0x00000372 + +/* CKM_SSL3_MASTER_KEY_DERIVE_DH, CKM_TLS_PRE_MASTER_KEY_GEN, + * CKM_TLS_MASTER_KEY_DERIVE, CKM_TLS_KEY_AND_MAC_DERIVE, and + * CKM_TLS_MASTER_KEY_DERIVE_DH are new for v2.11 */ +#define CKM_SSL3_MASTER_KEY_DERIVE_DH 0x00000373 +#define CKM_TLS_PRE_MASTER_KEY_GEN 0x00000374 +#define CKM_TLS_MASTER_KEY_DERIVE 0x00000375 +#define CKM_TLS_KEY_AND_MAC_DERIVE 0x00000376 +#define CKM_TLS_MASTER_KEY_DERIVE_DH 0x00000377 + +/* CKM_TLS_PRF is new for v2.20 */ +#define CKM_TLS_PRF 0x00000378 + +#define CKM_SSL3_MD5_MAC 0x00000380 +#define CKM_SSL3_SHA1_MAC 0x00000381 +#define CKM_MD5_KEY_DERIVATION 0x00000390 +#define CKM_MD2_KEY_DERIVATION 0x00000391 +#define CKM_SHA1_KEY_DERIVATION 0x00000392 + +/* CKM_SHA256/384/512 are new for v2.20 */ +#define CKM_SHA256_KEY_DERIVATION 0x00000393 +#define CKM_SHA384_KEY_DERIVATION 0x00000394 +#define CKM_SHA512_KEY_DERIVATION 0x00000395 + +/* SHA-224 key derivation is new for PKCS #11 v2.20 amendment 3 */ +#define CKM_SHA224_KEY_DERIVATION 0x00000396 + +#define CKM_PBE_MD2_DES_CBC 0x000003A0 +#define CKM_PBE_MD5_DES_CBC 0x000003A1 +#define CKM_PBE_MD5_CAST_CBC 0x000003A2 +#define CKM_PBE_MD5_CAST3_CBC 0x000003A3 +#define CKM_PBE_MD5_CAST5_CBC 0x000003A4 +#define CKM_PBE_MD5_CAST128_CBC 0x000003A4 +#define CKM_PBE_SHA1_CAST5_CBC 0x000003A5 +#define CKM_PBE_SHA1_CAST128_CBC 0x000003A5 +#define CKM_PBE_SHA1_RC4_128 0x000003A6 +#define CKM_PBE_SHA1_RC4_40 0x000003A7 +#define CKM_PBE_SHA1_DES3_EDE_CBC 0x000003A8 +#define CKM_PBE_SHA1_DES2_EDE_CBC 0x000003A9 +#define CKM_PBE_SHA1_RC2_128_CBC 0x000003AA +#define CKM_PBE_SHA1_RC2_40_CBC 0x000003AB + +/* CKM_PKCS5_PBKD2 is new for v2.10 */ +#define CKM_PKCS5_PBKD2 0x000003B0 + +#define CKM_PBA_SHA1_WITH_SHA1_HMAC 0x000003C0 + +/* WTLS mechanisms are new for v2.20 */ +#define CKM_WTLS_PRE_MASTER_KEY_GEN 0x000003D0 +#define CKM_WTLS_MASTER_KEY_DERIVE 0x000003D1 +#define CKM_WTLS_MASTER_KEY_DERIVE_DH_ECC 0x000003D2 +#define CKM_WTLS_PRF 0x000003D3 +#define CKM_WTLS_SERVER_KEY_AND_MAC_DERIVE 0x000003D4 +#define CKM_WTLS_CLIENT_KEY_AND_MAC_DERIVE 0x000003D5 + +#define CKM_KEY_WRAP_LYNKS 0x00000400 +#define CKM_KEY_WRAP_SET_OAEP 0x00000401 + +/* CKM_CMS_SIG is new for v2.20 */ +#define CKM_CMS_SIG 0x00000500 + +/* CKM_KIP mechanisms are new for PKCS #11 v2.20 amendment 2 */ +#define CKM_KIP_DERIVE 0x00000510 +#define CKM_KIP_WRAP 0x00000511 +#define CKM_KIP_MAC 0x00000512 + +/* Camellia is new for PKCS #11 v2.20 amendment 3 */ +#define CKM_CAMELLIA_KEY_GEN 0x00000550 +#define CKM_CAMELLIA_ECB 0x00000551 +#define CKM_CAMELLIA_CBC 0x00000552 +#define CKM_CAMELLIA_MAC 0x00000553 +#define CKM_CAMELLIA_MAC_GENERAL 0x00000554 +#define CKM_CAMELLIA_CBC_PAD 0x00000555 +#define CKM_CAMELLIA_ECB_ENCRYPT_DATA 0x00000556 +#define CKM_CAMELLIA_CBC_ENCRYPT_DATA 0x00000557 +#define CKM_CAMELLIA_CTR 0x00000558 + +/* ARIA is new for PKCS #11 v2.20 amendment 3 */ +#define CKM_ARIA_KEY_GEN 0x00000560 +#define CKM_ARIA_ECB 0x00000561 +#define CKM_ARIA_CBC 0x00000562 +#define CKM_ARIA_MAC 0x00000563 +#define CKM_ARIA_MAC_GENERAL 0x00000564 +#define CKM_ARIA_CBC_PAD 0x00000565 +#define CKM_ARIA_ECB_ENCRYPT_DATA 0x00000566 +#define CKM_ARIA_CBC_ENCRYPT_DATA 0x00000567 + +/* Fortezza mechanisms */ +#define CKM_SKIPJACK_KEY_GEN 0x00001000 +#define CKM_SKIPJACK_ECB64 0x00001001 +#define CKM_SKIPJACK_CBC64 0x00001002 +#define CKM_SKIPJACK_OFB64 0x00001003 +#define CKM_SKIPJACK_CFB64 0x00001004 +#define CKM_SKIPJACK_CFB32 0x00001005 +#define CKM_SKIPJACK_CFB16 0x00001006 +#define CKM_SKIPJACK_CFB8 0x00001007 +#define CKM_SKIPJACK_WRAP 0x00001008 +#define CKM_SKIPJACK_PRIVATE_WRAP 0x00001009 +#define CKM_SKIPJACK_RELAYX 0x0000100a +#define CKM_KEA_KEY_PAIR_GEN 0x00001010 +#define CKM_KEA_KEY_DERIVE 0x00001011 +#define CKM_FORTEZZA_TIMESTAMP 0x00001020 +#define CKM_BATON_KEY_GEN 0x00001030 +#define CKM_BATON_ECB128 0x00001031 +#define CKM_BATON_ECB96 0x00001032 +#define CKM_BATON_CBC128 0x00001033 +#define CKM_BATON_COUNTER 0x00001034 +#define CKM_BATON_SHUFFLE 0x00001035 +#define CKM_BATON_WRAP 0x00001036 + +/* CKM_ECDSA_KEY_PAIR_GEN is deprecated in v2.11, + * CKM_EC_KEY_PAIR_GEN is preferred */ +#define CKM_ECDSA_KEY_PAIR_GEN 0x00001040 +#define CKM_EC_KEY_PAIR_GEN 0x00001040 + +#define CKM_ECDSA 0x00001041 +#define CKM_ECDSA_SHA1 0x00001042 + +/* CKM_ECDH1_DERIVE, CKM_ECDH1_COFACTOR_DERIVE, and CKM_ECMQV_DERIVE + * are new for v2.11 */ +#define CKM_ECDH1_DERIVE 0x00001050 +#define CKM_ECDH1_COFACTOR_DERIVE 0x00001051 +#define CKM_ECMQV_DERIVE 0x00001052 + +#define CKM_JUNIPER_KEY_GEN 0x00001060 +#define CKM_JUNIPER_ECB128 0x00001061 +#define CKM_JUNIPER_CBC128 0x00001062 +#define CKM_JUNIPER_COUNTER 0x00001063 +#define CKM_JUNIPER_SHUFFLE 0x00001064 +#define CKM_JUNIPER_WRAP 0x00001065 +#define CKM_FASTHASH 0x00001070 + +/* CKM_AES_KEY_GEN, CKM_AES_ECB, CKM_AES_CBC, CKM_AES_MAC, + * CKM_AES_MAC_GENERAL, CKM_AES_CBC_PAD, CKM_DSA_PARAMETER_GEN, + * CKM_DH_PKCS_PARAMETER_GEN, and CKM_X9_42_DH_PARAMETER_GEN are + * new for v2.11 */ +#define CKM_AES_KEY_GEN 0x00001080 +#define CKM_AES_ECB 0x00001081 +#define CKM_AES_CBC 0x00001082 +#define CKM_AES_MAC 0x00001083 +#define CKM_AES_MAC_GENERAL 0x00001084 +#define CKM_AES_CBC_PAD 0x00001085 + +/* AES counter mode is new for PKCS #11 v2.20 amendment 3 */ +#define CKM_AES_CTR 0x00001086 + +/* BlowFish and TwoFish are new for v2.20 */ +#define CKM_BLOWFISH_KEY_GEN 0x00001090 +#define CKM_BLOWFISH_CBC 0x00001091 +#define CKM_TWOFISH_KEY_GEN 0x00001092 +#define CKM_TWOFISH_CBC 0x00001093 + + +/* CKM_xxx_ENCRYPT_DATA mechanisms are new for v2.20 */ +#define CKM_DES_ECB_ENCRYPT_DATA 0x00001100 +#define CKM_DES_CBC_ENCRYPT_DATA 0x00001101 +#define CKM_DES3_ECB_ENCRYPT_DATA 0x00001102 +#define CKM_DES3_CBC_ENCRYPT_DATA 0x00001103 +#define CKM_AES_ECB_ENCRYPT_DATA 0x00001104 +#define CKM_AES_CBC_ENCRYPT_DATA 0x00001105 + +#define CKM_DSA_PARAMETER_GEN 0x00002000 +#define CKM_DH_PKCS_PARAMETER_GEN 0x00002001 +#define CKM_X9_42_DH_PARAMETER_GEN 0x00002002 + +#define CKM_VENDOR_DEFINED 0x80000000 + +typedef CK_MECHANISM_TYPE CK_PTR CK_MECHANISM_TYPE_PTR; + + +/* CK_MECHANISM is a structure that specifies a particular + * mechanism */ +typedef struct CK_MECHANISM { + CK_MECHANISM_TYPE mechanism; + CK_VOID_PTR pParameter; + + /* ulParameterLen was changed from CK_USHORT to CK_ULONG for + * v2.0 */ + CK_ULONG ulParameterLen; /* in bytes */ +} CK_MECHANISM; + +typedef CK_MECHANISM CK_PTR CK_MECHANISM_PTR; + + +/* CK_MECHANISM_INFO provides information about a particular + * mechanism */ +typedef struct CK_MECHANISM_INFO { + CK_ULONG ulMinKeySize; + CK_ULONG ulMaxKeySize; + CK_FLAGS flags; +} CK_MECHANISM_INFO; + +/* The flags are defined as follows: + * Bit Flag Mask Meaning */ +#define CKF_HW 0x00000001 /* performed by HW */ + +/* The flags CKF_ENCRYPT, CKF_DECRYPT, CKF_DIGEST, CKF_SIGN, + * CKG_SIGN_RECOVER, CKF_VERIFY, CKF_VERIFY_RECOVER, + * CKF_GENERATE, CKF_GENERATE_KEY_PAIR, CKF_WRAP, CKF_UNWRAP, + * and CKF_DERIVE are new for v2.0. They specify whether or not + * a mechanism can be used for a particular task */ +#define CKF_ENCRYPT 0x00000100 +#define CKF_DECRYPT 0x00000200 +#define CKF_DIGEST 0x00000400 +#define CKF_SIGN 0x00000800 +#define CKF_SIGN_RECOVER 0x00001000 +#define CKF_VERIFY 0x00002000 +#define CKF_VERIFY_RECOVER 0x00004000 +#define CKF_GENERATE 0x00008000 +#define CKF_GENERATE_KEY_PAIR 0x00010000 +#define CKF_WRAP 0x00020000 +#define CKF_UNWRAP 0x00040000 +#define CKF_DERIVE 0x00080000 + +/* CKF_EC_F_P, CKF_EC_F_2M, CKF_EC_ECPARAMETERS, CKF_EC_NAMEDCURVE, + * CKF_EC_UNCOMPRESS, and CKF_EC_COMPRESS are new for v2.11. They + * describe a token's EC capabilities not available in mechanism + * information. */ +#define CKF_EC_F_P 0x00100000 +#define CKF_EC_F_2M 0x00200000 +#define CKF_EC_ECPARAMETERS 0x00400000 +#define CKF_EC_NAMEDCURVE 0x00800000 +#define CKF_EC_UNCOMPRESS 0x01000000 +#define CKF_EC_COMPRESS 0x02000000 + +#define CKF_EXTENSION 0x80000000 /* FALSE for this version */ + +typedef CK_MECHANISM_INFO CK_PTR CK_MECHANISM_INFO_PTR; + + +/* CK_RV is a value that identifies the return value of a + * Cryptoki function */ +/* CK_RV was changed from CK_USHORT to CK_ULONG for v2.0 */ +typedef CK_ULONG CK_RV; + +#define CKR_OK 0x00000000 +#define CKR_CANCEL 0x00000001 +#define CKR_HOST_MEMORY 0x00000002 +#define CKR_SLOT_ID_INVALID 0x00000003 + +/* CKR_FLAGS_INVALID was removed for v2.0 */ + +/* CKR_GENERAL_ERROR and CKR_FUNCTION_FAILED are new for v2.0 */ +#define CKR_GENERAL_ERROR 0x00000005 +#define CKR_FUNCTION_FAILED 0x00000006 + +/* CKR_ARGUMENTS_BAD, CKR_NO_EVENT, CKR_NEED_TO_CREATE_THREADS, + * and CKR_CANT_LOCK are new for v2.01 */ +#define CKR_ARGUMENTS_BAD 0x00000007 +#define CKR_NO_EVENT 0x00000008 +#define CKR_NEED_TO_CREATE_THREADS 0x00000009 +#define CKR_CANT_LOCK 0x0000000A + +#define CKR_ATTRIBUTE_READ_ONLY 0x00000010 +#define CKR_ATTRIBUTE_SENSITIVE 0x00000011 +#define CKR_ATTRIBUTE_TYPE_INVALID 0x00000012 +#define CKR_ATTRIBUTE_VALUE_INVALID 0x00000013 +#define CKR_DATA_INVALID 0x00000020 +#define CKR_DATA_LEN_RANGE 0x00000021 +#define CKR_DEVICE_ERROR 0x00000030 +#define CKR_DEVICE_MEMORY 0x00000031 +#define CKR_DEVICE_REMOVED 0x00000032 +#define CKR_ENCRYPTED_DATA_INVALID 0x00000040 +#define CKR_ENCRYPTED_DATA_LEN_RANGE 0x00000041 +#define CKR_FUNCTION_CANCELED 0x00000050 +#define CKR_FUNCTION_NOT_PARALLEL 0x00000051 + +/* CKR_FUNCTION_NOT_SUPPORTED is new for v2.0 */ +#define CKR_FUNCTION_NOT_SUPPORTED 0x00000054 + +#define CKR_KEY_HANDLE_INVALID 0x00000060 + +/* CKR_KEY_SENSITIVE was removed for v2.0 */ + +#define CKR_KEY_SIZE_RANGE 0x00000062 +#define CKR_KEY_TYPE_INCONSISTENT 0x00000063 + +/* CKR_KEY_NOT_NEEDED, CKR_KEY_CHANGED, CKR_KEY_NEEDED, + * CKR_KEY_INDIGESTIBLE, CKR_KEY_FUNCTION_NOT_PERMITTED, + * CKR_KEY_NOT_WRAPPABLE, and CKR_KEY_UNEXTRACTABLE are new for + * v2.0 */ +#define CKR_KEY_NOT_NEEDED 0x00000064 +#define CKR_KEY_CHANGED 0x00000065 +#define CKR_KEY_NEEDED 0x00000066 +#define CKR_KEY_INDIGESTIBLE 0x00000067 +#define CKR_KEY_FUNCTION_NOT_PERMITTED 0x00000068 +#define CKR_KEY_NOT_WRAPPABLE 0x00000069 +#define CKR_KEY_UNEXTRACTABLE 0x0000006A + +#define CKR_MECHANISM_INVALID 0x00000070 +#define CKR_MECHANISM_PARAM_INVALID 0x00000071 + +/* CKR_OBJECT_CLASS_INCONSISTENT and CKR_OBJECT_CLASS_INVALID + * were removed for v2.0 */ +#define CKR_OBJECT_HANDLE_INVALID 0x00000082 +#define CKR_OPERATION_ACTIVE 0x00000090 +#define CKR_OPERATION_NOT_INITIALIZED 0x00000091 +#define CKR_PIN_INCORRECT 0x000000A0 +#define CKR_PIN_INVALID 0x000000A1 +#define CKR_PIN_LEN_RANGE 0x000000A2 + +/* CKR_PIN_EXPIRED and CKR_PIN_LOCKED are new for v2.0 */ +#define CKR_PIN_EXPIRED 0x000000A3 +#define CKR_PIN_LOCKED 0x000000A4 + +#define CKR_SESSION_CLOSED 0x000000B0 +#define CKR_SESSION_COUNT 0x000000B1 +#define CKR_SESSION_HANDLE_INVALID 0x000000B3 +#define CKR_SESSION_PARALLEL_NOT_SUPPORTED 0x000000B4 +#define CKR_SESSION_READ_ONLY 0x000000B5 +#define CKR_SESSION_EXISTS 0x000000B6 + +/* CKR_SESSION_READ_ONLY_EXISTS and + * CKR_SESSION_READ_WRITE_SO_EXISTS are new for v2.0 */ +#define CKR_SESSION_READ_ONLY_EXISTS 0x000000B7 +#define CKR_SESSION_READ_WRITE_SO_EXISTS 0x000000B8 + +#define CKR_SIGNATURE_INVALID 0x000000C0 +#define CKR_SIGNATURE_LEN_RANGE 0x000000C1 +#define CKR_TEMPLATE_INCOMPLETE 0x000000D0 +#define CKR_TEMPLATE_INCONSISTENT 0x000000D1 +#define CKR_TOKEN_NOT_PRESENT 0x000000E0 +#define CKR_TOKEN_NOT_RECOGNIZED 0x000000E1 +#define CKR_TOKEN_WRITE_PROTECTED 0x000000E2 +#define CKR_UNWRAPPING_KEY_HANDLE_INVALID 0x000000F0 +#define CKR_UNWRAPPING_KEY_SIZE_RANGE 0x000000F1 +#define CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT 0x000000F2 +#define CKR_USER_ALREADY_LOGGED_IN 0x00000100 +#define CKR_USER_NOT_LOGGED_IN 0x00000101 +#define CKR_USER_PIN_NOT_INITIALIZED 0x00000102 +#define CKR_USER_TYPE_INVALID 0x00000103 + +/* CKR_USER_ANOTHER_ALREADY_LOGGED_IN and CKR_USER_TOO_MANY_TYPES + * are new to v2.01 */ +#define CKR_USER_ANOTHER_ALREADY_LOGGED_IN 0x00000104 +#define CKR_USER_TOO_MANY_TYPES 0x00000105 + +#define CKR_WRAPPED_KEY_INVALID 0x00000110 +#define CKR_WRAPPED_KEY_LEN_RANGE 0x00000112 +#define CKR_WRAPPING_KEY_HANDLE_INVALID 0x00000113 +#define CKR_WRAPPING_KEY_SIZE_RANGE 0x00000114 +#define CKR_WRAPPING_KEY_TYPE_INCONSISTENT 0x00000115 +#define CKR_RANDOM_SEED_NOT_SUPPORTED 0x00000120 + +/* These are new to v2.0 */ +#define CKR_RANDOM_NO_RNG 0x00000121 + +/* These are new to v2.11 */ +#define CKR_DOMAIN_PARAMS_INVALID 0x00000130 + +/* These are new to v2.0 */ +#define CKR_BUFFER_TOO_SMALL 0x00000150 +#define CKR_SAVED_STATE_INVALID 0x00000160 +#define CKR_INFORMATION_SENSITIVE 0x00000170 +#define CKR_STATE_UNSAVEABLE 0x00000180 + +/* These are new to v2.01 */ +#define CKR_CRYPTOKI_NOT_INITIALIZED 0x00000190 +#define CKR_CRYPTOKI_ALREADY_INITIALIZED 0x00000191 +#define CKR_MUTEX_BAD 0x000001A0 +#define CKR_MUTEX_NOT_LOCKED 0x000001A1 + +/* The following return values are new for PKCS #11 v2.20 amendment 3 */ +#define CKR_NEW_PIN_MODE 0x000001B0 +#define CKR_NEXT_OTP 0x000001B1 + +/* This is new to v2.20 */ +#define CKR_FUNCTION_REJECTED 0x00000200 + +#define CKR_VENDOR_DEFINED 0x80000000 + + +/* CK_NOTIFY is an application callback that processes events */ +typedef CK_CALLBACK_FUNCTION(CK_RV, CK_NOTIFY)( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_NOTIFICATION event, + CK_VOID_PTR pApplication /* passed to C_OpenSession */ +); + + +/* CK_FUNCTION_LIST is a structure holding a Cryptoki spec + * version and pointers of appropriate types to all the + * Cryptoki functions */ +/* CK_FUNCTION_LIST is new for v2.0 */ +typedef struct CK_FUNCTION_LIST CK_FUNCTION_LIST; + +typedef CK_FUNCTION_LIST CK_PTR CK_FUNCTION_LIST_PTR; + +typedef CK_FUNCTION_LIST_PTR CK_PTR CK_FUNCTION_LIST_PTR_PTR; + + +/* CK_CREATEMUTEX is an application callback for creating a + * mutex object */ +typedef CK_CALLBACK_FUNCTION(CK_RV, CK_CREATEMUTEX)( + CK_VOID_PTR_PTR ppMutex /* location to receive ptr to mutex */ +); + + +/* CK_DESTROYMUTEX is an application callback for destroying a + * mutex object */ +typedef CK_CALLBACK_FUNCTION(CK_RV, CK_DESTROYMUTEX)( + CK_VOID_PTR pMutex /* pointer to mutex */ +); + + +/* CK_LOCKMUTEX is an application callback for locking a mutex */ +typedef CK_CALLBACK_FUNCTION(CK_RV, CK_LOCKMUTEX)( + CK_VOID_PTR pMutex /* pointer to mutex */ +); + + +/* CK_UNLOCKMUTEX is an application callback for unlocking a + * mutex */ +typedef CK_CALLBACK_FUNCTION(CK_RV, CK_UNLOCKMUTEX)( + CK_VOID_PTR pMutex /* pointer to mutex */ +); + + +/* CK_C_INITIALIZE_ARGS provides the optional arguments to + * C_Initialize */ +typedef struct CK_C_INITIALIZE_ARGS { + CK_CREATEMUTEX CreateMutex; + CK_DESTROYMUTEX DestroyMutex; + CK_LOCKMUTEX LockMutex; + CK_UNLOCKMUTEX UnlockMutex; + CK_FLAGS flags; + CK_VOID_PTR pReserved; +} CK_C_INITIALIZE_ARGS; + +/* flags: bit flags that provide capabilities of the slot + * Bit Flag Mask Meaning + */ +#define CKF_LIBRARY_CANT_CREATE_OS_THREADS 0x00000001 +#define CKF_OS_LOCKING_OK 0x00000002 + +typedef CK_C_INITIALIZE_ARGS CK_PTR CK_C_INITIALIZE_ARGS_PTR; + + +/* additional flags for parameters to functions */ + +/* CKF_DONT_BLOCK is for the function C_WaitForSlotEvent */ +#define CKF_DONT_BLOCK 1 + +/* CK_RSA_PKCS_OAEP_MGF_TYPE is new for v2.10. + * CK_RSA_PKCS_OAEP_MGF_TYPE is used to indicate the Message + * Generation Function (MGF) applied to a message block when + * formatting a message block for the PKCS #1 OAEP encryption + * scheme. */ +typedef CK_ULONG CK_RSA_PKCS_MGF_TYPE; + +typedef CK_RSA_PKCS_MGF_TYPE CK_PTR CK_RSA_PKCS_MGF_TYPE_PTR; + +/* The following MGFs are defined */ +/* CKG_MGF1_SHA256, CKG_MGF1_SHA384, and CKG_MGF1_SHA512 + * are new for v2.20 */ +#define CKG_MGF1_SHA1 0x00000001 +#define CKG_MGF1_SHA256 0x00000002 +#define CKG_MGF1_SHA384 0x00000003 +#define CKG_MGF1_SHA512 0x00000004 +/* SHA-224 is new for PKCS #11 v2.20 amendment 3 */ +#define CKG_MGF1_SHA224 0x00000005 + +/* CK_RSA_PKCS_OAEP_SOURCE_TYPE is new for v2.10. + * CK_RSA_PKCS_OAEP_SOURCE_TYPE is used to indicate the source + * of the encoding parameter when formatting a message block + * for the PKCS #1 OAEP encryption scheme. */ +typedef CK_ULONG CK_RSA_PKCS_OAEP_SOURCE_TYPE; + +typedef CK_RSA_PKCS_OAEP_SOURCE_TYPE CK_PTR CK_RSA_PKCS_OAEP_SOURCE_TYPE_PTR; + +/* The following encoding parameter sources are defined */ +#define CKZ_DATA_SPECIFIED 0x00000001 + +/* CK_RSA_PKCS_OAEP_PARAMS is new for v2.10. + * CK_RSA_PKCS_OAEP_PARAMS provides the parameters to the + * CKM_RSA_PKCS_OAEP mechanism. */ +typedef struct CK_RSA_PKCS_OAEP_PARAMS { + CK_MECHANISM_TYPE hashAlg; + CK_RSA_PKCS_MGF_TYPE mgf; + CK_RSA_PKCS_OAEP_SOURCE_TYPE source; + CK_VOID_PTR pSourceData; + CK_ULONG ulSourceDataLen; +} CK_RSA_PKCS_OAEP_PARAMS; + +typedef CK_RSA_PKCS_OAEP_PARAMS CK_PTR CK_RSA_PKCS_OAEP_PARAMS_PTR; + +/* CK_RSA_PKCS_PSS_PARAMS is new for v2.11. + * CK_RSA_PKCS_PSS_PARAMS provides the parameters to the + * CKM_RSA_PKCS_PSS mechanism(s). */ +typedef struct CK_RSA_PKCS_PSS_PARAMS { + CK_MECHANISM_TYPE hashAlg; + CK_RSA_PKCS_MGF_TYPE mgf; + CK_ULONG sLen; +} CK_RSA_PKCS_PSS_PARAMS; + +typedef CK_RSA_PKCS_PSS_PARAMS CK_PTR CK_RSA_PKCS_PSS_PARAMS_PTR; + +/* CK_EC_KDF_TYPE is new for v2.11. */ +typedef CK_ULONG CK_EC_KDF_TYPE; + +/* The following EC Key Derivation Functions are defined */ +#define CKD_NULL 0x00000001 +#define CKD_SHA1_KDF 0x00000002 + +/* CK_ECDH1_DERIVE_PARAMS is new for v2.11. + * CK_ECDH1_DERIVE_PARAMS provides the parameters to the + * CKM_ECDH1_DERIVE and CKM_ECDH1_COFACTOR_DERIVE mechanisms, + * where each party contributes one key pair. + */ +typedef struct CK_ECDH1_DERIVE_PARAMS { + CK_EC_KDF_TYPE kdf; + CK_ULONG ulSharedDataLen; + CK_BYTE_PTR pSharedData; + CK_ULONG ulPublicDataLen; + CK_BYTE_PTR pPublicData; +} CK_ECDH1_DERIVE_PARAMS; + +typedef CK_ECDH1_DERIVE_PARAMS CK_PTR CK_ECDH1_DERIVE_PARAMS_PTR; + + +/* CK_ECDH2_DERIVE_PARAMS is new for v2.11. + * CK_ECDH2_DERIVE_PARAMS provides the parameters to the + * CKM_ECMQV_DERIVE mechanism, where each party contributes two key pairs. */ +typedef struct CK_ECDH2_DERIVE_PARAMS { + CK_EC_KDF_TYPE kdf; + CK_ULONG ulSharedDataLen; + CK_BYTE_PTR pSharedData; + CK_ULONG ulPublicDataLen; + CK_BYTE_PTR pPublicData; + CK_ULONG ulPrivateDataLen; + CK_OBJECT_HANDLE hPrivateData; + CK_ULONG ulPublicDataLen2; + CK_BYTE_PTR pPublicData2; +} CK_ECDH2_DERIVE_PARAMS; + +typedef CK_ECDH2_DERIVE_PARAMS CK_PTR CK_ECDH2_DERIVE_PARAMS_PTR; + +typedef struct CK_ECMQV_DERIVE_PARAMS { + CK_EC_KDF_TYPE kdf; + CK_ULONG ulSharedDataLen; + CK_BYTE_PTR pSharedData; + CK_ULONG ulPublicDataLen; + CK_BYTE_PTR pPublicData; + CK_ULONG ulPrivateDataLen; + CK_OBJECT_HANDLE hPrivateData; + CK_ULONG ulPublicDataLen2; + CK_BYTE_PTR pPublicData2; + CK_OBJECT_HANDLE publicKey; +} CK_ECMQV_DERIVE_PARAMS; + +typedef CK_ECMQV_DERIVE_PARAMS CK_PTR CK_ECMQV_DERIVE_PARAMS_PTR; + +/* Typedefs and defines for the CKM_X9_42_DH_KEY_PAIR_GEN and the + * CKM_X9_42_DH_PARAMETER_GEN mechanisms (new for PKCS #11 v2.11) */ +typedef CK_ULONG CK_X9_42_DH_KDF_TYPE; +typedef CK_X9_42_DH_KDF_TYPE CK_PTR CK_X9_42_DH_KDF_TYPE_PTR; + +/* The following X9.42 DH key derivation functions are defined + (besides CKD_NULL already defined : */ +#define CKD_SHA1_KDF_ASN1 0x00000003 +#define CKD_SHA1_KDF_CONCATENATE 0x00000004 + +/* CK_X9_42_DH1_DERIVE_PARAMS is new for v2.11. + * CK_X9_42_DH1_DERIVE_PARAMS provides the parameters to the + * CKM_X9_42_DH_DERIVE key derivation mechanism, where each party + * contributes one key pair */ +typedef struct CK_X9_42_DH1_DERIVE_PARAMS { + CK_X9_42_DH_KDF_TYPE kdf; + CK_ULONG ulOtherInfoLen; + CK_BYTE_PTR pOtherInfo; + CK_ULONG ulPublicDataLen; + CK_BYTE_PTR pPublicData; +} CK_X9_42_DH1_DERIVE_PARAMS; + +typedef struct CK_X9_42_DH1_DERIVE_PARAMS CK_PTR CK_X9_42_DH1_DERIVE_PARAMS_PTR; + +/* CK_X9_42_DH2_DERIVE_PARAMS is new for v2.11. + * CK_X9_42_DH2_DERIVE_PARAMS provides the parameters to the + * CKM_X9_42_DH_HYBRID_DERIVE and CKM_X9_42_MQV_DERIVE key derivation + * mechanisms, where each party contributes two key pairs */ +typedef struct CK_X9_42_DH2_DERIVE_PARAMS { + CK_X9_42_DH_KDF_TYPE kdf; + CK_ULONG ulOtherInfoLen; + CK_BYTE_PTR pOtherInfo; + CK_ULONG ulPublicDataLen; + CK_BYTE_PTR pPublicData; + CK_ULONG ulPrivateDataLen; + CK_OBJECT_HANDLE hPrivateData; + CK_ULONG ulPublicDataLen2; + CK_BYTE_PTR pPublicData2; +} CK_X9_42_DH2_DERIVE_PARAMS; + +typedef CK_X9_42_DH2_DERIVE_PARAMS CK_PTR CK_X9_42_DH2_DERIVE_PARAMS_PTR; + +typedef struct CK_X9_42_MQV_DERIVE_PARAMS { + CK_X9_42_DH_KDF_TYPE kdf; + CK_ULONG ulOtherInfoLen; + CK_BYTE_PTR pOtherInfo; + CK_ULONG ulPublicDataLen; + CK_BYTE_PTR pPublicData; + CK_ULONG ulPrivateDataLen; + CK_OBJECT_HANDLE hPrivateData; + CK_ULONG ulPublicDataLen2; + CK_BYTE_PTR pPublicData2; + CK_OBJECT_HANDLE publicKey; +} CK_X9_42_MQV_DERIVE_PARAMS; + +typedef CK_X9_42_MQV_DERIVE_PARAMS CK_PTR CK_X9_42_MQV_DERIVE_PARAMS_PTR; + +/* CK_KEA_DERIVE_PARAMS provides the parameters to the + * CKM_KEA_DERIVE mechanism */ +/* CK_KEA_DERIVE_PARAMS is new for v2.0 */ +typedef struct CK_KEA_DERIVE_PARAMS { + CK_BBOOL isSender; + CK_ULONG ulRandomLen; + CK_BYTE_PTR pRandomA; + CK_BYTE_PTR pRandomB; + CK_ULONG ulPublicDataLen; + CK_BYTE_PTR pPublicData; +} CK_KEA_DERIVE_PARAMS; + +typedef CK_KEA_DERIVE_PARAMS CK_PTR CK_KEA_DERIVE_PARAMS_PTR; + + +/* CK_RC2_PARAMS provides the parameters to the CKM_RC2_ECB and + * CKM_RC2_MAC mechanisms. An instance of CK_RC2_PARAMS just + * holds the effective keysize */ +typedef CK_ULONG CK_RC2_PARAMS; + +typedef CK_RC2_PARAMS CK_PTR CK_RC2_PARAMS_PTR; + + +/* CK_RC2_CBC_PARAMS provides the parameters to the CKM_RC2_CBC + * mechanism */ +typedef struct CK_RC2_CBC_PARAMS { + /* ulEffectiveBits was changed from CK_USHORT to CK_ULONG for + * v2.0 */ + CK_ULONG ulEffectiveBits; /* effective bits (1-1024) */ + + CK_BYTE iv[8]; /* IV for CBC mode */ +} CK_RC2_CBC_PARAMS; + +typedef CK_RC2_CBC_PARAMS CK_PTR CK_RC2_CBC_PARAMS_PTR; + + +/* CK_RC2_MAC_GENERAL_PARAMS provides the parameters for the + * CKM_RC2_MAC_GENERAL mechanism */ +/* CK_RC2_MAC_GENERAL_PARAMS is new for v2.0 */ +typedef struct CK_RC2_MAC_GENERAL_PARAMS { + CK_ULONG ulEffectiveBits; /* effective bits (1-1024) */ + CK_ULONG ulMacLength; /* Length of MAC in bytes */ +} CK_RC2_MAC_GENERAL_PARAMS; + +typedef CK_RC2_MAC_GENERAL_PARAMS CK_PTR \ + CK_RC2_MAC_GENERAL_PARAMS_PTR; + + +/* CK_RC5_PARAMS provides the parameters to the CKM_RC5_ECB and + * CKM_RC5_MAC mechanisms */ +/* CK_RC5_PARAMS is new for v2.0 */ +typedef struct CK_RC5_PARAMS { + CK_ULONG ulWordsize; /* wordsize in bits */ + CK_ULONG ulRounds; /* number of rounds */ +} CK_RC5_PARAMS; + +typedef CK_RC5_PARAMS CK_PTR CK_RC5_PARAMS_PTR; + + +/* CK_RC5_CBC_PARAMS provides the parameters to the CKM_RC5_CBC + * mechanism */ +/* CK_RC5_CBC_PARAMS is new for v2.0 */ +typedef struct CK_RC5_CBC_PARAMS { + CK_ULONG ulWordsize; /* wordsize in bits */ + CK_ULONG ulRounds; /* number of rounds */ + CK_BYTE_PTR pIv; /* pointer to IV */ + CK_ULONG ulIvLen; /* length of IV in bytes */ +} CK_RC5_CBC_PARAMS; + +typedef CK_RC5_CBC_PARAMS CK_PTR CK_RC5_CBC_PARAMS_PTR; + + +/* CK_RC5_MAC_GENERAL_PARAMS provides the parameters for the + * CKM_RC5_MAC_GENERAL mechanism */ +/* CK_RC5_MAC_GENERAL_PARAMS is new for v2.0 */ +typedef struct CK_RC5_MAC_GENERAL_PARAMS { + CK_ULONG ulWordsize; /* wordsize in bits */ + CK_ULONG ulRounds; /* number of rounds */ + CK_ULONG ulMacLength; /* Length of MAC in bytes */ +} CK_RC5_MAC_GENERAL_PARAMS; + +typedef CK_RC5_MAC_GENERAL_PARAMS CK_PTR \ + CK_RC5_MAC_GENERAL_PARAMS_PTR; + + +/* CK_MAC_GENERAL_PARAMS provides the parameters to most block + * ciphers' MAC_GENERAL mechanisms. Its value is the length of + * the MAC */ +/* CK_MAC_GENERAL_PARAMS is new for v2.0 */ +typedef CK_ULONG CK_MAC_GENERAL_PARAMS; + +typedef CK_MAC_GENERAL_PARAMS CK_PTR CK_MAC_GENERAL_PARAMS_PTR; + +/* CK_DES/AES_ECB/CBC_ENCRYPT_DATA_PARAMS are new for v2.20 */ +typedef struct CK_DES_CBC_ENCRYPT_DATA_PARAMS { + CK_BYTE iv[8]; + CK_BYTE_PTR pData; + CK_ULONG length; +} CK_DES_CBC_ENCRYPT_DATA_PARAMS; + +typedef CK_DES_CBC_ENCRYPT_DATA_PARAMS CK_PTR CK_DES_CBC_ENCRYPT_DATA_PARAMS_PTR; + +typedef struct CK_AES_CBC_ENCRYPT_DATA_PARAMS { + CK_BYTE iv[16]; + CK_BYTE_PTR pData; + CK_ULONG length; +} CK_AES_CBC_ENCRYPT_DATA_PARAMS; + +typedef CK_AES_CBC_ENCRYPT_DATA_PARAMS CK_PTR CK_AES_CBC_ENCRYPT_DATA_PARAMS_PTR; + +/* CK_SKIPJACK_PRIVATE_WRAP_PARAMS provides the parameters to the + * CKM_SKIPJACK_PRIVATE_WRAP mechanism */ +/* CK_SKIPJACK_PRIVATE_WRAP_PARAMS is new for v2.0 */ +typedef struct CK_SKIPJACK_PRIVATE_WRAP_PARAMS { + CK_ULONG ulPasswordLen; + CK_BYTE_PTR pPassword; + CK_ULONG ulPublicDataLen; + CK_BYTE_PTR pPublicData; + CK_ULONG ulPAndGLen; + CK_ULONG ulQLen; + CK_ULONG ulRandomLen; + CK_BYTE_PTR pRandomA; + CK_BYTE_PTR pPrimeP; + CK_BYTE_PTR pBaseG; + CK_BYTE_PTR pSubprimeQ; +} CK_SKIPJACK_PRIVATE_WRAP_PARAMS; + +typedef CK_SKIPJACK_PRIVATE_WRAP_PARAMS CK_PTR \ + CK_SKIPJACK_PRIVATE_WRAP_PTR; + + +/* CK_SKIPJACK_RELAYX_PARAMS provides the parameters to the + * CKM_SKIPJACK_RELAYX mechanism */ +/* CK_SKIPJACK_RELAYX_PARAMS is new for v2.0 */ +typedef struct CK_SKIPJACK_RELAYX_PARAMS { + CK_ULONG ulOldWrappedXLen; + CK_BYTE_PTR pOldWrappedX; + CK_ULONG ulOldPasswordLen; + CK_BYTE_PTR pOldPassword; + CK_ULONG ulOldPublicDataLen; + CK_BYTE_PTR pOldPublicData; + CK_ULONG ulOldRandomLen; + CK_BYTE_PTR pOldRandomA; + CK_ULONG ulNewPasswordLen; + CK_BYTE_PTR pNewPassword; + CK_ULONG ulNewPublicDataLen; + CK_BYTE_PTR pNewPublicData; + CK_ULONG ulNewRandomLen; + CK_BYTE_PTR pNewRandomA; +} CK_SKIPJACK_RELAYX_PARAMS; + +typedef CK_SKIPJACK_RELAYX_PARAMS CK_PTR \ + CK_SKIPJACK_RELAYX_PARAMS_PTR; + + +typedef struct CK_PBE_PARAMS { + CK_BYTE_PTR pInitVector; + CK_UTF8CHAR_PTR pPassword; + CK_ULONG ulPasswordLen; + CK_BYTE_PTR pSalt; + CK_ULONG ulSaltLen; + CK_ULONG ulIteration; +} CK_PBE_PARAMS; + +typedef CK_PBE_PARAMS CK_PTR CK_PBE_PARAMS_PTR; + + +/* CK_KEY_WRAP_SET_OAEP_PARAMS provides the parameters to the + * CKM_KEY_WRAP_SET_OAEP mechanism */ +/* CK_KEY_WRAP_SET_OAEP_PARAMS is new for v2.0 */ +typedef struct CK_KEY_WRAP_SET_OAEP_PARAMS { + CK_BYTE bBC; /* block contents byte */ + CK_BYTE_PTR pX; /* extra data */ + CK_ULONG ulXLen; /* length of extra data in bytes */ +} CK_KEY_WRAP_SET_OAEP_PARAMS; + +typedef CK_KEY_WRAP_SET_OAEP_PARAMS CK_PTR \ + CK_KEY_WRAP_SET_OAEP_PARAMS_PTR; + + +typedef struct CK_SSL3_RANDOM_DATA { + CK_BYTE_PTR pClientRandom; + CK_ULONG ulClientRandomLen; + CK_BYTE_PTR pServerRandom; + CK_ULONG ulServerRandomLen; +} CK_SSL3_RANDOM_DATA; + + +typedef struct CK_SSL3_MASTER_KEY_DERIVE_PARAMS { + CK_SSL3_RANDOM_DATA RandomInfo; + CK_VERSION_PTR pVersion; +} CK_SSL3_MASTER_KEY_DERIVE_PARAMS; + +typedef struct CK_SSL3_MASTER_KEY_DERIVE_PARAMS CK_PTR \ + CK_SSL3_MASTER_KEY_DERIVE_PARAMS_PTR; + + +typedef struct CK_SSL3_KEY_MAT_OUT { + CK_OBJECT_HANDLE hClientMacSecret; + CK_OBJECT_HANDLE hServerMacSecret; + CK_OBJECT_HANDLE hClientKey; + CK_OBJECT_HANDLE hServerKey; + CK_BYTE_PTR pIVClient; + CK_BYTE_PTR pIVServer; +} CK_SSL3_KEY_MAT_OUT; + +typedef CK_SSL3_KEY_MAT_OUT CK_PTR CK_SSL3_KEY_MAT_OUT_PTR; + + +typedef struct CK_SSL3_KEY_MAT_PARAMS { + CK_ULONG ulMacSizeInBits; + CK_ULONG ulKeySizeInBits; + CK_ULONG ulIVSizeInBits; + CK_BBOOL bIsExport; + CK_SSL3_RANDOM_DATA RandomInfo; + CK_SSL3_KEY_MAT_OUT_PTR pReturnedKeyMaterial; +} CK_SSL3_KEY_MAT_PARAMS; + +typedef CK_SSL3_KEY_MAT_PARAMS CK_PTR CK_SSL3_KEY_MAT_PARAMS_PTR; + +/* CK_TLS_PRF_PARAMS is new for version 2.20 */ +typedef struct CK_TLS_PRF_PARAMS { + CK_BYTE_PTR pSeed; + CK_ULONG ulSeedLen; + CK_BYTE_PTR pLabel; + CK_ULONG ulLabelLen; + CK_BYTE_PTR pOutput; + CK_ULONG_PTR pulOutputLen; +} CK_TLS_PRF_PARAMS; + +typedef CK_TLS_PRF_PARAMS CK_PTR CK_TLS_PRF_PARAMS_PTR; + +/* WTLS is new for version 2.20 */ +typedef struct CK_WTLS_RANDOM_DATA { + CK_BYTE_PTR pClientRandom; + CK_ULONG ulClientRandomLen; + CK_BYTE_PTR pServerRandom; + CK_ULONG ulServerRandomLen; +} CK_WTLS_RANDOM_DATA; + +typedef CK_WTLS_RANDOM_DATA CK_PTR CK_WTLS_RANDOM_DATA_PTR; + +typedef struct CK_WTLS_MASTER_KEY_DERIVE_PARAMS { + CK_MECHANISM_TYPE DigestMechanism; + CK_WTLS_RANDOM_DATA RandomInfo; + CK_BYTE_PTR pVersion; +} CK_WTLS_MASTER_KEY_DERIVE_PARAMS; + +typedef CK_WTLS_MASTER_KEY_DERIVE_PARAMS CK_PTR \ + CK_WTLS_MASTER_KEY_DERIVE_PARAMS_PTR; + +typedef struct CK_WTLS_PRF_PARAMS { + CK_MECHANISM_TYPE DigestMechanism; + CK_BYTE_PTR pSeed; + CK_ULONG ulSeedLen; + CK_BYTE_PTR pLabel; + CK_ULONG ulLabelLen; + CK_BYTE_PTR pOutput; + CK_ULONG_PTR pulOutputLen; +} CK_WTLS_PRF_PARAMS; + +typedef CK_WTLS_PRF_PARAMS CK_PTR CK_WTLS_PRF_PARAMS_PTR; + +typedef struct CK_WTLS_KEY_MAT_OUT { + CK_OBJECT_HANDLE hMacSecret; + CK_OBJECT_HANDLE hKey; + CK_BYTE_PTR pIV; +} CK_WTLS_KEY_MAT_OUT; + +typedef CK_WTLS_KEY_MAT_OUT CK_PTR CK_WTLS_KEY_MAT_OUT_PTR; + +typedef struct CK_WTLS_KEY_MAT_PARAMS { + CK_MECHANISM_TYPE DigestMechanism; + CK_ULONG ulMacSizeInBits; + CK_ULONG ulKeySizeInBits; + CK_ULONG ulIVSizeInBits; + CK_ULONG ulSequenceNumber; + CK_BBOOL bIsExport; + CK_WTLS_RANDOM_DATA RandomInfo; + CK_WTLS_KEY_MAT_OUT_PTR pReturnedKeyMaterial; +} CK_WTLS_KEY_MAT_PARAMS; + +typedef CK_WTLS_KEY_MAT_PARAMS CK_PTR CK_WTLS_KEY_MAT_PARAMS_PTR; + +/* CMS is new for version 2.20 */ +typedef struct CK_CMS_SIG_PARAMS { + CK_OBJECT_HANDLE certificateHandle; + CK_MECHANISM_PTR pSigningMechanism; + CK_MECHANISM_PTR pDigestMechanism; + CK_UTF8CHAR_PTR pContentType; + CK_BYTE_PTR pRequestedAttributes; + CK_ULONG ulRequestedAttributesLen; + CK_BYTE_PTR pRequiredAttributes; + CK_ULONG ulRequiredAttributesLen; +} CK_CMS_SIG_PARAMS; + +typedef CK_CMS_SIG_PARAMS CK_PTR CK_CMS_SIG_PARAMS_PTR; + +typedef struct CK_KEY_DERIVATION_STRING_DATA { + CK_BYTE_PTR pData; + CK_ULONG ulLen; +} CK_KEY_DERIVATION_STRING_DATA; + +typedef CK_KEY_DERIVATION_STRING_DATA CK_PTR \ + CK_KEY_DERIVATION_STRING_DATA_PTR; + + +/* The CK_EXTRACT_PARAMS is used for the + * CKM_EXTRACT_KEY_FROM_KEY mechanism. It specifies which bit + * of the base key should be used as the first bit of the + * derived key */ +/* CK_EXTRACT_PARAMS is new for v2.0 */ +typedef CK_ULONG CK_EXTRACT_PARAMS; + +typedef CK_EXTRACT_PARAMS CK_PTR CK_EXTRACT_PARAMS_PTR; + +/* CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE is new for v2.10. + * CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE is used to + * indicate the Pseudo-Random Function (PRF) used to generate + * key bits using PKCS #5 PBKDF2. */ +typedef CK_ULONG CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE; + +typedef CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE CK_PTR CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE_PTR; + +/* The following PRFs are defined in PKCS #5 v2.0. */ +#define CKP_PKCS5_PBKD2_HMAC_SHA1 0x00000001 + + +/* CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE is new for v2.10. + * CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE is used to indicate the + * source of the salt value when deriving a key using PKCS #5 + * PBKDF2. */ +typedef CK_ULONG CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE; + +typedef CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE CK_PTR CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE_PTR; + +/* The following salt value sources are defined in PKCS #5 v2.0. */ +#define CKZ_SALT_SPECIFIED 0x00000001 + +/* CK_PKCS5_PBKD2_PARAMS is new for v2.10. + * CK_PKCS5_PBKD2_PARAMS is a structure that provides the + * parameters to the CKM_PKCS5_PBKD2 mechanism. */ +typedef struct CK_PKCS5_PBKD2_PARAMS { + CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE saltSource; + CK_VOID_PTR pSaltSourceData; + CK_ULONG ulSaltSourceDataLen; + CK_ULONG iterations; + CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE prf; + CK_VOID_PTR pPrfData; + CK_ULONG ulPrfDataLen; + CK_UTF8CHAR_PTR pPassword; + CK_ULONG_PTR ulPasswordLen; +} CK_PKCS5_PBKD2_PARAMS; + +typedef CK_PKCS5_PBKD2_PARAMS CK_PTR CK_PKCS5_PBKD2_PARAMS_PTR; + +/* All CK_OTP structs are new for PKCS #11 v2.20 amendment 3 */ + +typedef CK_ULONG CK_OTP_PARAM_TYPE; +typedef CK_OTP_PARAM_TYPE CK_PARAM_TYPE; /* B/w compatibility */ + +typedef struct CK_OTP_PARAM { + CK_OTP_PARAM_TYPE type; + CK_VOID_PTR pValue; + CK_ULONG ulValueLen; +} CK_OTP_PARAM; + +typedef CK_OTP_PARAM CK_PTR CK_OTP_PARAM_PTR; + +typedef struct CK_OTP_PARAMS { + CK_OTP_PARAM_PTR pParams; + CK_ULONG ulCount; +} CK_OTP_PARAMS; + +typedef CK_OTP_PARAMS CK_PTR CK_OTP_PARAMS_PTR; + +typedef struct CK_OTP_SIGNATURE_INFO { + CK_OTP_PARAM_PTR pParams; + CK_ULONG ulCount; +} CK_OTP_SIGNATURE_INFO; + +typedef CK_OTP_SIGNATURE_INFO CK_PTR CK_OTP_SIGNATURE_INFO_PTR; + +/* The following OTP-related defines are new for PKCS #11 v2.20 amendment 1 */ +#define CK_OTP_VALUE 0 +#define CK_OTP_PIN 1 +#define CK_OTP_CHALLENGE 2 +#define CK_OTP_TIME 3 +#define CK_OTP_COUNTER 4 +#define CK_OTP_FLAGS 5 +#define CK_OTP_OUTPUT_LENGTH 6 +#define CK_OTP_OUTPUT_FORMAT 7 + +/* The following OTP-related defines are new for PKCS #11 v2.20 amendment 1 */ +#define CKF_NEXT_OTP 0x00000001 +#define CKF_EXCLUDE_TIME 0x00000002 +#define CKF_EXCLUDE_COUNTER 0x00000004 +#define CKF_EXCLUDE_CHALLENGE 0x00000008 +#define CKF_EXCLUDE_PIN 0x00000010 +#define CKF_USER_FRIENDLY_OTP 0x00000020 + +/* CK_KIP_PARAMS is new for PKCS #11 v2.20 amendment 2 */ +typedef struct CK_KIP_PARAMS { + CK_MECHANISM_PTR pMechanism; + CK_OBJECT_HANDLE hKey; + CK_BYTE_PTR pSeed; + CK_ULONG ulSeedLen; +} CK_KIP_PARAMS; + +typedef CK_KIP_PARAMS CK_PTR CK_KIP_PARAMS_PTR; + +/* CK_AES_CTR_PARAMS is new for PKCS #11 v2.20 amendment 3 */ +typedef struct CK_AES_CTR_PARAMS { + CK_ULONG ulCounterBits; + CK_BYTE cb[16]; +} CK_AES_CTR_PARAMS; + +typedef CK_AES_CTR_PARAMS CK_PTR CK_AES_CTR_PARAMS_PTR; + +/* CK_CAMELLIA_CTR_PARAMS is new for PKCS #11 v2.20 amendment 3 */ +typedef struct CK_CAMELLIA_CTR_PARAMS { + CK_ULONG ulCounterBits; + CK_BYTE cb[16]; +} CK_CAMELLIA_CTR_PARAMS; + +typedef CK_CAMELLIA_CTR_PARAMS CK_PTR CK_CAMELLIA_CTR_PARAMS_PTR; + +/* CK_CAMELLIA_CBC_ENCRYPT_DATA_PARAMS is new for PKCS #11 v2.20 amendment 3 */ +typedef struct CK_CAMELLIA_CBC_ENCRYPT_DATA_PARAMS { + CK_BYTE iv[16]; + CK_BYTE_PTR pData; + CK_ULONG length; +} CK_CAMELLIA_CBC_ENCRYPT_DATA_PARAMS; + +typedef CK_CAMELLIA_CBC_ENCRYPT_DATA_PARAMS CK_PTR CK_CAMELLIA_CBC_ENCRYPT_DATA_PARAMS_PTR; + +/* CK_ARIA_CBC_ENCRYPT_DATA_PARAMS is new for PKCS #11 v2.20 amendment 3 */ +typedef struct CK_ARIA_CBC_ENCRYPT_DATA_PARAMS { + CK_BYTE iv[16]; + CK_BYTE_PTR pData; + CK_ULONG length; +} CK_ARIA_CBC_ENCRYPT_DATA_PARAMS; + +typedef CK_ARIA_CBC_ENCRYPT_DATA_PARAMS CK_PTR CK_ARIA_CBC_ENCRYPT_DATA_PARAMS_PTR; + +#endif Index: openssl/util/libeay.num diff -u openssl/util/libeay.num:1.8.2.1.6.1.4.1.4.1.2.1 openssl/util/libeay.num:1.9.2.4 --- openssl/util/libeay.num:1.8.2.1.6.1.4.1.4.1.2.1 Wed Dec 23 17:27:04 2015 +++ openssl/util/libeay.num Wed Dec 23 17:45:51 2015 @@ -4198,3 +4198,5 @@ OPENSSL_strncasecmp 4566 EXIST::FUNCTION: OPENSSL_gmtime 4567 EXIST::FUNCTION: OPENSSL_gmtime_adj 4568 EXIST::FUNCTION: +ENGINE_load_pk11ca 4569 EXIST::FUNCTION:HW_PKCS11CA,ENGINE +ENGINE_load_pk11so 4569 EXIST::FUNCTION:HW_PKCS11SO,ENGINE Index: openssl/util/mk1mf.pl diff -u openssl/util/mk1mf.pl:1.9.2.1.14.1 openssl/util/mk1mf.pl:1.9.4.1 --- openssl/util/mk1mf.pl:1.9.2.1.14.1 Wed Mar 4 14:03:25 2015 +++ openssl/util/mk1mf.pl Wed Mar 4 14:04:40 2015 @@ -109,6 +109,8 @@ no-ecdh - No ECDH no-engine - No engine no-hw - No hw + no-hw-pkcs11ca - No hw PKCS#11 CA flavor + no-hw-pkcs11so - No hw PKCS#11 SO flavor nasm - Use NASM for x86 asm nw-nasm - Use NASM x86 asm for NetWare nw-mwasm - Use Metrowerks x86 asm for NetWare @@ -270,6 +272,8 @@ $cflags.=" -DOPENSSL_NO_GOST" if $no_gost; $cflags.=" -DOPENSSL_NO_ENGINE" if $no_engine; $cflags.=" -DOPENSSL_NO_HW" if $no_hw; +$cflags.=" -DOPENSSL_NO_HW_PKCS11CA" if $no_hw_pkcs11ca; +$cflags.=" -DOPENSSL_NO_HW_PKCS11SO" if $no_hw_pkcs11so; $cflags.=" -DOPENSSL_NO_JPAKE" if $no_jpake; $cflags.= " -DZLIB" if $zlib_opt; $cflags.= " -DZLIB_SHARED" if $zlib_opt == 2; @@ -335,6 +339,9 @@ $dir=$val; } + if ($key eq "PK11_LIB_LOCATION") + { $cflags .= " -D$key=\\\"$val\\\"" if $val ne "";} + if ($key eq "KRB5_INCLUDES") { $cflags .= " $val";} @@ -1061,6 +1068,8 @@ "no-gost" => \$no_gost, "no-engine" => \$no_engine, "no-hw" => \$no_hw, + "no-hw-pkcs11ca" => \$no_hw_pkcs11ca, + "no-hw-pkcs11so" => \$no_hw_pkcs11so, "just-ssl" => [\$no_rc2, \$no_idea, \$no_des, \$no_bf, \$no_cast, \$no_md2, \$no_sha, \$no_mdc2, \$no_dsa, \$no_dh, Index: openssl/util/mkdef.pl diff -u openssl/util/mkdef.pl:1.7.2.1 openssl/util/mkdef.pl:1.8 --- openssl/util/mkdef.pl:1.7.2.1 Sun Jan 15 16:09:52 2012 +++ openssl/util/mkdef.pl Sun Jan 15 16:30:10 2012 @@ -94,7 +94,7 @@ # External "algorithms" "FP_API", "STDIO", "SOCK", "KRB5", "DGRAM", # Engines - "STATIC_ENGINE", "ENGINE", "HW", "GMP", + "STATIC_ENGINE", "ENGINE", "HW", "GMP", "HW_PKCS11CA", "HW_PKCS11SO", # RFC3779 "RFC3779", # TLS @@ -125,6 +125,7 @@ my $no_md2; my $no_md4; my $no_md5; my $no_sha; my $no_ripemd; my $no_mdc2; my $no_rsa; my $no_dsa; my $no_dh; my $no_hmac=0; my $no_aes; my $no_krb5; my $no_ec; my $no_ecdsa; my $no_ecdh; my $no_engine; my $no_hw; +my $no_pkcs11ca; my $no_pkcs11so; my $no_fp_api; my $no_static_engine=1; my $no_gmp; my $no_deprecated; my $no_rfc3779; my $no_psk; my $no_tlsext; my $no_cms; my $no_capieng; my $no_jpake; my $no_ssl2; @@ -218,6 +219,8 @@ elsif (/^no-ssl2$/) { $no_ssl2=1; } elsif (/^no-capieng$/) { $no_capieng=1; } elsif (/^no-jpake$/) { $no_jpake=1; } + elsif (/^no-hw-pkcs11ca$/) { $no_pkcs11ca=1; } + elsif (/^no-hw-pkcs11so$/) { $no_pkcs11so=1; } } @@ -1165,6 +1168,8 @@ if ($keyword eq "KRB5" && $no_krb5) { return 0; } if ($keyword eq "ENGINE" && $no_engine) { return 0; } if ($keyword eq "HW" && $no_hw) { return 0; } + if ($keyword eq "HW_PKCS11CA" && $no_pkcs11ca) { return 0; } + if ($keyword eq "HW_PKCS11SO" && $no_pkcs11so) { return 0; } if ($keyword eq "FP_API" && $no_fp_api) { return 0; } if ($keyword eq "STATIC_ENGINE" && $no_static_engine) { return 0; } if ($keyword eq "GMP" && $no_gmp) { return 0; } Index: openssl/util/pl/VC-32.pl diff -u openssl/util/pl/VC-32.pl:1.7.2.1.16.1 openssl/util/pl/VC-32.pl:1.7.4.1 --- openssl/util/pl/VC-32.pl:1.7.2.1.16.1 Wed Dec 23 17:27:05 2015 +++ openssl/util/pl/VC-32.pl Wed Dec 23 17:45:51 2015 @@ -36,7 +36,7 @@ my $f = $shlib?' /MD':' /MT'; $lib_cflag='/Zl' if (!$shlib); # remove /DEFAULTLIBs from static lib $opt_cflags=$f.' /Ox'; - $dbg_cflags=$f.'d /Od -DDEBUG -D_DEBUG'; + $dbg_cflags=$f.'d /Od /Zi -DDEBUG -D_DEBUG'; $lflags="/nologo /subsystem:console /opt:ref"; *::perlasm_compile_target = sub { bind9-9.11.3+dfsg/bin/pkcs11/openssl-1.0.1t-patch000066400000000000000000016347501325250447100207500ustar00rootroot00000000000000Index: openssl/Configure diff -u openssl/Configure:1.9.2.1.2.1.2.1.2.1.2.1.2.1.4.1.2.1.4.1.2.1 openssl/Configure:1.19 --- openssl/Configure:1.9.2.1.2.1.2.1.2.1.2.1.2.1.4.1.2.1.4.1.2.1 Mon Jun 13 15:10:46 2016 +++ openssl/Configure Mon Jun 13 15:20:23 2016 @@ -10,7 +10,7 @@ # see INSTALL for instructions. -my $usage="Usage: Configure [no- ...] [enable- ...] [experimental- ...] [-Dxxx] [-lxxx] [-Lxxx] [-fxxx] [-Kxxx] [no-hw-xxx|no-hw] [[no-]threads] [[no-]shared] [[no-]zlib|zlib-dynamic] [no-asm] [no-dso] [no-krb5] [sctp] [386] [--prefix=DIR] [--openssldir=OPENSSLDIR] [--with-xxx[=vvv]] [--test-sanity] os/compiler[:flags]\n"; +my $usage="Usage: Configure --pk11-libname=PK11_LIB_LOCATION --pk11-flavor=FLAVOR [no- ...] [enable- ...] [experimental- ...] [-Dxxx] [-lxxx] [-Lxxx] [-fxxx] [-Kxxx] [no-hw-xxx|no-hw] [[no-]threads] [[no-]shared] [[no-]zlib|zlib-dynamic] [no-asm] [no-dso] [no-krb5] [sctp] [386] [--prefix=DIR] [--openssldir=OPENSSLDIR] [--with-xxx[=vvv]] [--test-sanity] os/compiler[:flags]\n"; # Options: # @@ -23,6 +23,12 @@ # default). This needn't be set in advance, you can # just as well use "make INSTALL_PREFIX=/whatever install". # +# --pk11-libname PKCS#11 library name. +# (No default) +# +# --pk11-flavor either crypto-accelerator or sign-only +# (No default) +# # --with-krb5-dir Declare where Kerberos 5 lives. The libraries are expected # to live in the subdirectory lib/ and the header files in # include/. A value is required. @@ -355,24 +361,23 @@ #### # *-generic* is endian-neutral target, but ./config is free to # throw in -D[BL]_ENDIAN, whichever appropriate... -"linux-generic32","gcc:-O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${no_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", -"linux-ppc", "gcc:-DB_ENDIAN -O3 -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_RISC1 DES_UNROLL:${ppc32_asm}:linux32:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", +"linux-generic32","gcc:-DTERMIO -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${no_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", +"linux-ppc", "gcc:-DB_ENDIAN -DTERMIO -O3 -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_RISC1 DES_UNROLL:${ppc32_asm}:linux32:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", # It's believed that majority of ARM toolchains predefine appropriate -march. # If you compiler does not, do complement config command line with one! -"linux-armv4", "gcc:-O3 -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${armv4_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", +"linux-armv4", "gcc:-DTERMIO -O3 -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${armv4_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", #### IA-32 targets... -"linux-ia32-icc", "icc:-DL_ENDIAN -O2 -no_cpprt::-D_REENTRANT::-ldl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_elf_asm}:dlfcn:linux-shared:-KPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", -"linux-elf", "gcc:-DL_ENDIAN -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_elf_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", -"linux-aout", "gcc:-DL_ENDIAN -O3 -fomit-frame-pointer -march=i486 -Wall::(unknown):::BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_asm}:a.out", +"linux-ia32-icc", "icc:-DL_ENDIAN -DTERMIO -O2 -no_cpprt::-D_REENTRANT::-ldl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_elf_asm}:dlfcn:linux-shared:-KPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", +"linux-elf", "gcc:-DL_ENDIAN -DTERMIO -O3 -fomit-frame-pointer -Wall::-D_REENTRANT -pthread::-ldl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_elf_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", +"linux-aout", "gcc:-DL_ENDIAN -DTERMIO -O3 -fomit-frame-pointer -march=i486 -Wall::(unknown):::BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_asm}:a.out", #### -"linux-generic64","gcc:-O3 -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${no_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", -"linux-ppc64", "gcc:-m64 -DB_ENDIAN -O3 -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_RISC1 DES_UNROLL:${ppc64_asm}:linux64:dlfcn:linux-shared:-fPIC:-m64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):::64", -"linux-ia64", "gcc:-DL_ENDIAN -O3 -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_UNROLL DES_INT:${ia64_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", -"linux-ia64-ecc","ecc:-DL_ENDIAN -O2 -Wall -no_cpprt::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_INT:${ia64_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", -"linux-ia64-icc","icc:-DL_ENDIAN -O2 -Wall -no_cpprt::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_RISC1 DES_INT:${ia64_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", -"linux-x86_64", "gcc:-m64 -DL_ENDIAN -O3 -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_INT DES_UNROLL:${x86_64_asm}:elf:dlfcn:linux-shared:-fPIC:-m64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):::64", -"linux-x86_64-clang","clang: -m64 -DL_ENDIAN -O3 -Wall -Qunused-arguments::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_INT DES_UNROLL:${x86_64_asm}:elf:dlfcn:linux-shared:-fPIC:-m64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):::64", -"linux64-s390x", "gcc:-m64 -DB_ENDIAN -O3 -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL:${s390x_asm}:64:dlfcn:linux-shared:-fPIC:-m64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):::64", +"linux-generic64","gcc:-DTERMIO -O3 -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${no_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", +"linux-ppc64", "gcc:-m64 -DB_ENDIAN -DTERMIO -O3 -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_RISC1 DES_UNROLL:${ppc64_asm}:linux64:dlfcn:linux-shared:-fPIC:-m64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):::64", +"linux-ia64", "gcc:-DL_ENDIAN -DTERMIO -O3 -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_UNROLL DES_INT:${ia64_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", +"linux-ia64-ecc","ecc:-DL_ENDIAN -DTERMIO -O2 -Wall -no_cpprt::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_INT:${ia64_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", +"linux-ia64-icc","icc:-DL_ENDIAN -DTERMIO -O2 -Wall -no_cpprt::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_RISC1 DES_INT:${ia64_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", +"linux-x86_64", "gcc:-m64 -DL_ENDIAN -DTERMIO -O3 -Wall::-D_REENTRANT -pthread::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_INT DES_UNROLL:${x86_64_asm}:elf:dlfcn:linux-shared:-fPIC:-m64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):::64", +"linux64-s390x", "gcc:-m64 -DB_ENDIAN -DTERMIO -O3 -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL:${s390x_asm}:64:dlfcn:linux-shared:-fPIC:-m64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):::64", #### So called "highgprs" target for z/Architecture CPUs # "Highgprs" is kernel feature first implemented in Linux 2.6.32, see # /proc/cpuinfo. The idea is to preserve most significant bits of @@ -668,6 +673,10 @@ my $idx_arflags = $idx++; my $idx_multilib = $idx++; +# PKCS#11 engine patch +my $pk11_libname=""; +my $pk11_flavor=""; + my $prefix=""; my $libdir=""; my $openssldir=""; @@ -895,6 +904,14 @@ $_ =~ s/%([0-9a-f]{1,2})/chr(hex($1))/gei; $flags.=$_." "; } + elsif (/^--pk11-libname=(.*)$/) + { + $pk11_libname=$1; + } + elsif (/^--pk11-flavor=(.*)$/) + { + $pk11_flavor=$1; + } elsif (/^--prefix=(.*)$/) { $prefix=$1; @@ -1062,6 +1079,22 @@ exit 0; } +if (! $pk11_libname) + { + print STDERR "You must set --pk11-libname for PKCS#11 library.\n"; + print STDERR "See README.pkcs11 for more information.\n"; + exit 1; + } + +if (! $pk11_flavor + || !($pk11_flavor eq "crypto-accelerator" || $pk11_flavor eq "sign-only")) + { + print STDERR "You must set --pk11-flavor.\n"; + print STDERR "Choices are crypto-accelerator and sign-only.\n"; + print STDERR "See README.pkcs11 for more information.\n"; + exit 1; + } + if ($target =~ m/^CygWin32(-.*)$/) { $target = "Cygwin".$1; } @@ -1139,6 +1172,25 @@ $exp_cflags .= " -DOPENSSL_EXPERIMENTAL_$ALGO"; } +if ($pk11_flavor eq "crypto-accelerator") + { + $openssl_other_defines .= "#define OPENSSL_NO_HW_PKCS11SO\n"; + $default_depflags .= " -DOPENSSL_NO_HW_PKCS11SO"; + $depflags .= " -DOPENSSL_NO_HW_PKCS11SO"; + $options .= " no-hw-pkcs11so"; + print " no-hw-pkcs11so [pk11-flavor]"; + print " OPENSSL_NO_HW_PKCS11SO\n"; + } +else + { + $openssl_other_defines .= "#define OPENSSL_NO_HW_PKCS11CA\n"; + $default_depflags .= " -DOPENSSL_NO_HW_PKCS11CA"; + $depflags .= " -DOPENSSL_NO_HW_PKCS11CA"; + $options .= " no-hw-pkcs11ca"; + print " no-hw-pkcs11ca [pk11-flavor]"; + print " OPENSSL_NO_HW_PKCS11CA\n"; +} + my $IsMK1MF=scalar grep /^$target$/,@MK1MF_Builds; $exe_ext=".exe" if ($target eq "Cygwin" || $target eq "DJGPP" || $target =~ /^mingw/); @@ -1228,6 +1280,8 @@ if ($flags ne "") { $cflags="$flags$cflags"; } else { $no_user_cflags=1; } +$cflags="-DPK11_LIB_LOCATION=\"$pk11_libname\" $cflags"; + # Kerberos settings. The flavor must be provided from outside, either through # the script "config" or manually. if (!$no_krb5) @@ -1626,6 +1680,7 @@ s/^VERSION=.*/VERSION=$version/; s/^MAJOR=.*/MAJOR=$major/; s/^MINOR=.*/MINOR=$minor/; + s/^PK11_LIB_LOCATION=.*/PK11_LIB_LOCATION=$pk11_libname/; s/^SHLIB_VERSION_NUMBER=.*/SHLIB_VERSION_NUMBER=$shlib_version_number/; s/^SHLIB_VERSION_HISTORY=.*/SHLIB_VERSION_HISTORY=$shlib_version_history/; s/^SHLIB_MAJOR=.*/SHLIB_MAJOR=$shlib_major/; Index: openssl/Makefile.org diff -u openssl/Makefile.org:1.5.2.1.2.1.2.1.2.1.2.1.2.1.10.1.2.1 openssl/Makefile.org:1.12 --- openssl/Makefile.org:1.5.2.1.2.1.2.1.2.1.2.1.2.1.10.1.2.1 Mon Jun 13 15:10:47 2016 +++ openssl/Makefile.org Mon Jun 13 15:20:23 2016 @@ -26,6 +26,9 @@ INSTALL_PREFIX= INSTALLTOP=/usr/local/ssl +# You must set this through --pk11-libname configure option. +PK11_LIB_LOCATION= + # Do not edit this manually. Use Configure --openssldir=DIR do change this! OPENSSLDIR=/usr/local/ssl Index: openssl/README.pkcs11 diff -u /dev/null openssl/README.pkcs11:1.8 --- /dev/null Mon Jun 13 15:26:28 2016 +++ openssl/README.pkcs11 Fri Oct 4 14:16:43 2013 @@ -0,0 +1,266 @@ +ISC modified +============ + +The previous key naming scheme was kept for backward compatibility. + +The PKCS#11 engine exists in two flavors, crypto-accelerator and +sign-only. The first one is from the Solaris patch and uses the +PKCS#11 device for all crypto operations it supports. The second +is a stripped down version which provides only the useful +function (i.e., signature with a RSA private key in the device +protected key store and key loading). + +As a hint PKCS#11 boards should use the crypto-accelerator flavor, +external PKCS#11 devices the sign-only. SCA 6000 is an example +of the first, AEP Keyper of the second. + +Note it is mandatory to set a pk11-flavor (and only one) in +config/Configure. + +It is highly recommended to compile in (vs. as a DSO) the engine. +The way to configure this is system dependent, on Unixes it is no-shared +(and is in general the default), on WIN32 it is enable-static-engine +(and still enable to build the OpenSSL libraries as DLLs). + +PKCS#11 engine support for OpenSSL 0.9.8l +========================================= + +[Nov 19, 2009] + +Contents: + +Overview +Revisions of the patch for 0.9.8 branch +FAQs +Feedback + +Overview +======== + +This patch containing code available in OpenSolaris adds support for PKCS#11 +engine into OpenSSL and implements PKCS#11 v2.20. It is to be applied against +OpenSSL 0.9.8l source code distribution as shipped by OpenSSL.Org. Your system +must provide PKCS#11 backend otherwise the patch is useless. You provide the +PKCS#11 library name during the build configuration phase, see below. + +Patch can be applied like this: + + # NOTE: use gtar if on Solaris + tar xfzv openssl-0.9.8l.tar.gz + # now download the patch to the current directory + # ... + cd openssl-0.9.8l + # NOTE: must use gpatch if on Solaris (is part of the system) + patch -p1 < path-to/pkcs11_engine-0.9.8l.patch.2009-11-19 + +It is designed to support pure acceleration for RSA, DSA, DH and all the +symetric ciphers and message digest algorithms that PKCS#11 and OpenSSL share +except for missing support for patented algorithms MDC2, RC3, RC5 and IDEA. + +According to the PKCS#11 providers installed on your machine, it can support +following mechanisms: + + RSA, DSA, DH, RAND, DES-CBC, DES-EDE3-CBC, DES-ECB, DES-EDE3, RC4, + AES-128-CBC, AES-192-CBC, AES-256-CBC, AES-128-ECB, AES-192-ECB, + AES-256-ECB, AES-128-CTR, AES-192-CTR, AES-256-CTR, MD5, SHA1, SHA224, + SHA256, SHA384, SHA512 + +Note that for AES counter mode the application must provide their own EVP +functions since OpenSSL doesn't support counter mode through EVP yet. You may +see OpenSSH source code (cipher.c) to get the idea how to do that. SunSSH is an +example of code that uses the PKCS#11 engine and deals with the fork-safety +problem (see engine.c and packet.c files if interested). + +You must provide the location of PKCS#11 library in your system to the +configure script. You will be instructed to do that when you try to run the +config script: + + $ ./config + Operating system: i86pc-whatever-solaris2 + Configuring for solaris-x86-cc + You must set --pk11-libname for PKCS#11 library. + See README.pkcs11 for more information. + +Taking openCryptoki project on Linux AMD64 box as an example, you would run +configure script like this: + + ./config --pk11-libname=/usr/lib64/pkcs11/PKCS11_API.so + +To check whether newly built openssl really supports PKCS#11 it's enough to run +"apps/openssl engine" and look for "(pkcs11) PKCS #11 engine support" in the +output. If you see no PKCS#11 engine support check that the built openssl binary +and the PKCS#11 library from --pk11-libname don't conflict on 32/64 bits. + +The patch, during various phases of development, was tested on Solaris against +PKCS#11 engine available from Solaris Cryptographic Framework (Solaris 10 and +OpenSolaris) and also on Linux using PKCS#11 libraries from openCryptoki project +(see openCryptoki website http://sourceforge.net/projects/opencryptoki for more +information). Some Linux distributions even ship those libraries with the +system. The patch should work on any system that is supported by OpenSSL itself +and has functional PKCS#11 library. + +The patch contains "RSA Security Inc. PKCS #11 Cryptographic Token Interface +(Cryptoki)" - files cryptoki.h, pkcs11.h, pkcs11f.h and pkcs11t.h which are +copyrighted by RSA Security Inc., see pkcs11.h for more information. + +Other added/modified code in this patch is copyrighted by Sun Microsystems, +Inc. and is released under the OpenSSL license (see LICENSE file for more +information). + +Revisions of the patch for 0.9.8 branch +======================================= + +2009-11-19 +- adjusted for OpenSSL version 0.9.8l + +- bugs and RFEs: + + 6479874 OpenSSL should support RSA key by reference/hardware keystores + 6896677 PKCS#11 engine's hw_pk11_err.h needs to be split + 6732677 make check to trigger Solaris specific code automatic in the + PKCS#11 engine + +2009-03-11 +- adjusted for OpenSSL version 0.9.8j + +- README.pkcs11 moved out of the patch, and is shipped together with it in a + tarball instead so that it can be read before the patch is applied. + +- fixed bugs: + + 6804216 pkcs#11 engine should support a key length range for RC4 + 6734038 Apache SSL web server using the pkcs11 engine fails to start if + meta slot is disabled + +2008-12-02 +- fixed bugs and RFEs (most of the work done by Vladimir Kotal) + + 6723504 more granular locking in PKCS#11 engine + 6667128 CRYPTO_LOCK_PK11_ENGINE assumption does not hold true + 6710420 PKCS#11 engine source should be lint clean + 6747327 PKCS#11 engine atfork handlers need to be aware of guys who take + it seriously + 6746712 PKCS#11 engine source code should be cstyle clean + 6731380 return codes of several functions are not checked in the PKCS#11 + engine code + 6746735 PKCS#11 engine should use extended FILE space API + 6734038 Apache SSL web server using the pkcs11 engine fails to start if + meta slot is disabled + +2008-08-01 +- fixed bug + + 6731839 OpenSSL PKCS#11 engine no longer uses n2cp for symmetric ciphers + and digests + +- Solaris specific code for slot selection made automatic + +2008-07-29 +- update the patch to OpenSSL 0.9.8h version +- pkcs11t.h updated to the latest version: + + 6545665 make CKM_AES_CTR available to non-kernel users + +- fixed bugs in the engine code: + + 6602801 PK11_SESSION cache has to employ reference counting scheme for + asymmetric key operations + 6605538 pkcs11 functions C_FindObjects[{Init,Final}]() not called + atomically + 6607307 pkcs#11 engine can't read RSA private keys + 6652362 pk11_RSA_finish() is cutting corners + 6662112 pk11_destroy_{rsa,dsa,dh}_key_objects() use locking in + suboptimal way + 6666625 pk11_destroy_{rsa,dsa,dh}_key_objects() should be more + resilient to destroy failures + 6667273 OpenSSL engine should not use free() but OPENSSL_free() + 6670363 PKCS#11 engine fails to reuse existing symmetric keys + 6678135 memory corruption in pk11_DH_generate_key() in pkcs#11 engine + 6678503 DSA signature conversion in pk11_dsa_do_verify() ignores size + of big numbers leading to failures + 6706562 pk11_DH_compute_key() returns 0 in case of failure instead of + -1 + 6706622 pk11_load_{pub,priv}key create corrupted RSA key references + 6707129 return values from BN_new() in pk11_DH_generate_key() are not + checked + 6707274 DSA/RSA/DH PKCS#11 engine operations need to be resistant to + structure reuse + 6707782 OpenSSL PKCS#11 engine pretends to be aware of + OPENSSL_NO_{RSA,DSA,DH} + defines but fails miserably + 6709966 make check_new_*() to return values to indicate cache hit/miss + 6705200 pk11_dh struct initialization in PKCS#11 engine is missing + generate_params parameter + 6709513 PKCS#11 engine sets IV length even for ECB modes + 6728296 buffer length not initialized for C_(En|De)crypt_Final() in the + PKCS#11 engine + 6728871 PKCS#11 engine must reset global_session in pk11_finish() + +- new features and enhancements: + + 6562155 OpenSSL pkcs#11 engine needs support for SHA224/256/384/512 + 6685012 OpenSSL pkcs#11 engine needs support for new cipher modes + 6725903 OpenSSL PKCS#11 engine shouldn't use soft token for symmetric + ciphers and digests + +2007-10-15 +- update for 0.9.8f version +- update for "6607670 teach pkcs#11 engine how to use keys be reference" + +2007-10-02 +- draft for "6607670 teach pkcs#11 engine how to use keys be reference" +- draft for "6607307 pkcs#11 engine can't read RSA private keys" + +2007-09-26 +- 6375348 Using pkcs11 as the SSLCryptoDevice with Apache/OpenSSL causes + significant performance drop +- 6573196 memory is leaked when OpenSSL is used with PKCS#11 engine + +2007-05-25 +- 6558630 race in OpenSSL pkcs11 engine when using symetric block ciphers + +2007-05-19 +- initial patch for 0.9.8e using latest OpenSolaris code + +FAQs +==== + +(1) my build failed on Linux distro with this error: + +../libcrypto.a(hw_pk11.o): In function `pk11_library_init': +hw_pk11.c:(.text+0x20f5): undefined reference to `pthread_atfork' + +Answer: + + - don't use "no-threads" when configuring + - if you didn't then OpenSSL failed to create a threaded library by + default. You may manually edit Configure and try again. Look for the + architecture that Configure printed, for example: + +Configured for linux-elf. + + - then edit Configure, find string "linux-elf" (inluding the quotes), + and add flags to support threads to the 4th column of the 2nd string. + If you build with GCC then adding "-pthread" should be enough. With + "linux-elf" as an example, you would add " -pthread" right after + "-D_REENTRANT", like this: + +....-O3 -fomit-frame-pointer -Wall::-D_REENTRANT -pthread::-ldl:..... + +(2) I'm using MinGW/MSYS environment and get undeclared reference error for +pthread_atfork() function when trying to build OpenSSL with the patch. + +Answer: + + Sorry, pthread_atfork() is not implemented in the current pthread-win32 + (as of Nov 2009). You can not use the patch there. + + +Feedback +======== + +Please send feedback to security-discuss@opensolaris.org. The patch was +created by Jan.Pechanec@Sun.COM from code available in OpenSolaris. + +Latest version should be always available on http://blogs.sun.com/janp. + Index: openssl/crypto/opensslconf.h diff -u openssl/crypto/opensslconf.h:1.6.2.1.4.1.10.1.6.1.2.1 openssl/crypto/opensslconf.h:1.10 --- openssl/crypto/opensslconf.h:1.6.2.1.4.1.10.1.6.1.2.1 Mon Jun 13 15:10:49 2016 +++ openssl/crypto/opensslconf.h Mon Jun 13 15:20:26 2016 @@ -47,6 +47,9 @@ #endif /* OPENSSL_DOING_MAKEDEPEND */ +#ifndef OPENSSL_THREADS +# define OPENSSL_THREADS +#endif #ifndef OPENSSL_NO_DYNAMIC_ENGINE # define OPENSSL_NO_DYNAMIC_ENGINE #endif @@ -94,6 +97,8 @@ # endif #endif +#define OPENSSL_CPUID_OBJ + /* crypto/opensslconf.h.in */ /* Generate 80386 code? */ @@ -140,7 +145,7 @@ * This enables code handling data aligned at natural CPU word * boundary. See crypto/rc4/rc4_enc.c for further details. */ -#undef RC4_CHUNK +#define RC4_CHUNK unsigned long #endif #endif @@ -148,7 +153,7 @@ /* If this is set to 'unsigned int' on a DEC Alpha, this gives about a * %20 speed up (longs are 8 bytes, int's are 4). */ #ifndef DES_LONG -#define DES_LONG unsigned long +#define DES_LONG unsigned int #endif #endif @@ -159,9 +164,9 @@ /* Should we define BN_DIV2W here? */ /* Only one for the following should be defined */ -#undef SIXTY_FOUR_BIT_LONG +#define SIXTY_FOUR_BIT_LONG #undef SIXTY_FOUR_BIT -#define THIRTY_TWO_BIT +#undef THIRTY_TWO_BIT #endif #if defined(HEADER_RC4_LOCL_H) && !defined(CONFIG_HEADER_RC4_LOCL_H) @@ -173,7 +178,7 @@ #if defined(HEADER_BF_LOCL_H) && !defined(CONFIG_HEADER_BF_LOCL_H) #define CONFIG_HEADER_BF_LOCL_H -#undef BF_PTR +#define BF_PTR2 #endif /* HEADER_BF_LOCL_H */ #if defined(HEADER_DES_LOCL_H) && !defined(CONFIG_HEADER_DES_LOCL_H) @@ -203,7 +208,7 @@ /* Unroll the inner loop, this sometimes helps, sometimes hinders. * Very mucy CPU dependant */ #ifndef DES_UNROLL -#undef DES_UNROLL +#define DES_UNROLL #endif /* These default values were supplied by Index: openssl/crypto/engine/Makefile diff -u openssl/crypto/engine/Makefile:1.8.2.1.4.1.16.1 openssl/crypto/engine/Makefile:1.10 --- openssl/crypto/engine/Makefile:1.8.2.1.4.1.16.1 Wed Dec 23 18:09:29 2015 +++ openssl/crypto/engine/Makefile Wed Dec 23 18:27:10 2015 @@ -22,13 +22,15 @@ tb_rsa.c tb_dsa.c tb_ecdsa.c tb_dh.c tb_ecdh.c tb_rand.c tb_store.c \ tb_cipher.c tb_digest.c tb_pkmeth.c tb_asnmth.c \ eng_openssl.c eng_cnf.c eng_dyn.c eng_cryptodev.c \ - eng_rsax.c eng_rdrand.c + eng_rsax.c eng_rdrand.c \ + hw_pk11.c hw_pk11_pub.c hw_pk11so.c hw_pk11so_pub.c LIBOBJ= eng_err.o eng_lib.o eng_list.o eng_init.o eng_ctrl.o \ eng_table.o eng_pkey.o eng_fat.o eng_all.o \ tb_rsa.o tb_dsa.o tb_ecdsa.o tb_dh.o tb_ecdh.o tb_rand.o tb_store.o \ tb_cipher.o tb_digest.o tb_pkmeth.o tb_asnmth.o \ eng_openssl.o eng_cnf.o eng_dyn.o eng_cryptodev.o \ - eng_rsax.o eng_rdrand.o + eng_rsax.o eng_rdrand.o \ + hw_pk11.o hw_pk11_pub.o hw_pk11so.o hw_pk11so_pub.o SRC= $(LIBSRC) @@ -296,6 +298,83 @@ eng_table.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h eng_table.o: ../../include/openssl/x509_vfy.h ../cryptlib.h eng_int.h eng_table.o: eng_table.c +hw_pk11.o: ../../e_os.h ../../include/openssl/aes.h +hw_pk11.o: ../../include/openssl/asn1.h ../../include/openssl/bio.h +hw_pk11.o: ../../include/openssl/bn.h ../../include/openssl/buffer.h +hw_pk11.o: ../../include/openssl/crypto.h ../../include/openssl/dh.h +hw_pk11.o: ../../include/openssl/dsa.h ../../include/openssl/dso.h +hw_pk11.o: ../../include/openssl/e_os2.h ../../include/openssl/ec.h +hw_pk11.o: ../../include/openssl/ecdh.h ../../include/openssl/ecdsa.h +hw_pk11.o: ../../include/openssl/engine.h ../../include/openssl/err.h +hw_pk11.o: ../../include/openssl/evp.h ../../include/openssl/lhash.h +hw_pk11.o: ../../include/openssl/md5.h ../../include/openssl/obj_mac.h +hw_pk11.o: ../../include/openssl/objects.h ../../include/openssl/opensslconf.h +hw_pk11.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h +hw_pk11.o: ../../include/openssl/pem.h ../../include/openssl/pem2.h +hw_pk11.o: ../../include/openssl/pkcs7.h ../../include/openssl/rand.h +hw_pk11.o: ../../include/openssl/rsa.h ../../include/openssl/safestack.h +hw_pk11.o: ../../include/openssl/sha.h ../../include/openssl/stack.h +hw_pk11.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h +hw_pk11.o: ../../include/openssl/x509_vfy.h ../cryptlib.h cryptoki.h hw_pk11.c +hw_pk11.o: hw_pk11_err.c hw_pk11_err.h hw_pk11ca.h pkcs11.h pkcs11f.h pkcs11t.h +hw_pk11_pub.o: ../../e_os.h ../../include/openssl/asn1.h +hw_pk11_pub.o: ../../include/openssl/bio.h ../../include/openssl/bn.h +hw_pk11_pub.o: ../../include/openssl/buffer.h ../../include/openssl/crypto.h +hw_pk11_pub.o: ../../include/openssl/dh.h ../../include/openssl/dsa.h +hw_pk11_pub.o: ../../include/openssl/dso.h ../../include/openssl/e_os2.h +hw_pk11_pub.o: ../../include/openssl/ec.h ../../include/openssl/ecdh.h +hw_pk11_pub.o: ../../include/openssl/ecdsa.h ../../include/openssl/engine.h +hw_pk11_pub.o: ../../include/openssl/err.h ../../include/openssl/evp.h +hw_pk11_pub.o: ../../include/openssl/lhash.h ../../include/openssl/obj_mac.h +hw_pk11_pub.o: ../../include/openssl/objects.h +hw_pk11_pub.o: ../../include/openssl/opensslconf.h +hw_pk11_pub.o: ../../include/openssl/opensslv.h +hw_pk11_pub.o: ../../include/openssl/ossl_typ.h ../../include/openssl/pem.h +hw_pk11_pub.o: ../../include/openssl/pem2.h ../../include/openssl/pkcs7.h +hw_pk11_pub.o: ../../include/openssl/rand.h ../../include/openssl/rsa.h +hw_pk11_pub.o: ../../include/openssl/safestack.h ../../include/openssl/sha.h +hw_pk11_pub.o: ../../include/openssl/stack.h ../../include/openssl/symhacks.h +hw_pk11_pub.o: ../../include/openssl/x509.h ../../include/openssl/x509_vfy.h +hw_pk11_pub.o: ../cryptlib.h cryptoki.h hw_pk11_err.h hw_pk11_pub.c hw_pk11ca.h +hw_pk11_pub.o: pkcs11.h pkcs11f.h pkcs11t.h +hw_pk11so.o: ../../e_os.h ../../include/openssl/asn1.h +hw_pk11so.o: ../../include/openssl/bio.h ../../include/openssl/bn.h +hw_pk11so.o: ../../include/openssl/buffer.h ../../include/openssl/crypto.h +hw_pk11so.o: ../../include/openssl/dso.h ../../include/openssl/e_os2.h +hw_pk11so.o: ../../include/openssl/ec.h ../../include/openssl/ecdh.h +hw_pk11so.o: ../../include/openssl/ecdsa.h ../../include/openssl/engine.h +hw_pk11so.o: ../../include/openssl/err.h ../../include/openssl/evp.h +hw_pk11so.o: ../../include/openssl/lhash.h ../../include/openssl/md5.h +hw_pk11so.o: ../../include/openssl/obj_mac.h ../../include/openssl/objects.h +hw_pk11so.o: ../../include/openssl/opensslconf.h +hw_pk11so.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h +hw_pk11so.o: ../../include/openssl/pem.h ../../include/openssl/pem2.h +hw_pk11so.o: ../../include/openssl/pkcs7.h ../../include/openssl/rand.h +hw_pk11so.o: ../../include/openssl/rsa.h ../../include/openssl/safestack.h +hw_pk11so.o: ../../include/openssl/sha.h ../../include/openssl/stack.h +hw_pk11so.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h +hw_pk11so.o: ../../include/openssl/x509_vfy.h ../cryptlib.h cryptoki.h +hw_pk11so.o: hw_pk11_err.c hw_pk11_err.h hw_pk11so.c hw_pk11so.h pkcs11.h +hw_pk11so.o: pkcs11f.h pkcs11t.h +hw_pk11so_pub.o: ../../e_os.h ../../include/openssl/asn1.h +hw_pk11so_pub.o: ../../include/openssl/bio.h ../../include/openssl/bn.h +hw_pk11so_pub.o: ../../include/openssl/buffer.h ../../include/openssl/crypto.h +hw_pk11so_pub.o: ../../include/openssl/dso.h ../../include/openssl/e_os2.h +hw_pk11so_pub.o: ../../include/openssl/ec.h ../../include/openssl/ecdh.h +hw_pk11so_pub.o: ../../include/openssl/ecdsa.h ../../include/openssl/engine.h +hw_pk11so_pub.o: ../../include/openssl/err.h ../../include/openssl/evp.h +hw_pk11so_pub.o: ../../include/openssl/lhash.h ../../include/openssl/obj_mac.h +hw_pk11so_pub.o: ../../include/openssl/objects.h +hw_pk11so_pub.o: ../../include/openssl/opensslconf.h +hw_pk11so_pub.o: ../../include/openssl/opensslv.h +hw_pk11so_pub.o: ../../include/openssl/ossl_typ.h ../../include/openssl/pem.h +hw_pk11so_pub.o: ../../include/openssl/pem2.h ../../include/openssl/pkcs7.h +hw_pk11so_pub.o: ../../include/openssl/rand.h ../../include/openssl/rsa.h +hw_pk11so_pub.o: ../../include/openssl/safestack.h ../../include/openssl/sha.h +hw_pk11so_pub.o: ../../include/openssl/stack.h ../../include/openssl/symhacks.h +hw_pk11so_pub.o: ../../include/openssl/x509.h ../../include/openssl/x509_vfy.h +hw_pk11so_pub.o: ../cryptlib.h cryptoki.h hw_pk11_err.h hw_pk11so.h +hw_pk11so_pub.o: hw_pk11so_pub.c pkcs11.h pkcs11f.h pkcs11t.h tb_asnmth.o: ../../e_os.h ../../include/openssl/asn1.h tb_asnmth.o: ../../include/openssl/bio.h ../../include/openssl/buffer.h tb_asnmth.o: ../../include/openssl/crypto.h ../../include/openssl/e_os2.h Index: openssl/crypto/engine/cryptoki.h diff -u /dev/null openssl/crypto/engine/cryptoki.h:1.4 --- /dev/null Mon Jun 13 15:26:29 2016 +++ openssl/crypto/engine/cryptoki.h Thu Dec 18 00:14:12 2008 @@ -0,0 +1,103 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _CRYPTOKI_H +#define _CRYPTOKI_H + +/* ident "@(#)cryptoki.h 1.2 05/06/08 SMI" */ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef CK_PTR +#define CK_PTR * +#endif + +#ifndef CK_DEFINE_FUNCTION +#define CK_DEFINE_FUNCTION(returnType, name) returnType name +#endif + +#ifndef CK_DECLARE_FUNCTION +#define CK_DECLARE_FUNCTION(returnType, name) returnType name +#endif + +#ifndef CK_DECLARE_FUNCTION_POINTER +#define CK_DECLARE_FUNCTION_POINTER(returnType, name) returnType (* name) +#endif + +#ifndef CK_CALLBACK_FUNCTION +#define CK_CALLBACK_FUNCTION(returnType, name) returnType (* name) +#endif + +#ifndef NULL_PTR +#include /* For NULL */ +#define NULL_PTR NULL +#endif + +/* + * pkcs11t.h defines TRUE and FALSE in a way that upsets lint + */ +#ifndef CK_DISABLE_TRUE_FALSE +#define CK_DISABLE_TRUE_FALSE +#ifndef TRUE +#define TRUE 1 +#endif /* TRUE */ +#ifndef FALSE +#define FALSE 0 +#endif /* FALSE */ +#endif /* CK_DISABLE_TRUE_FALSE */ + +#undef CK_PKCS11_FUNCTION_INFO + +#include "pkcs11.h" + +/* Solaris specific functions */ + +#include + +/* + * SUNW_C_GetMechSession will initialize the framework and do all + * the necessary PKCS#11 calls to create a session capable of + * providing operations on the requested mechanism + */ +CK_RV SUNW_C_GetMechSession(CK_MECHANISM_TYPE mech, + CK_SESSION_HANDLE_PTR hSession); + +/* + * SUNW_C_KeyToObject will create a secret key object for the given + * mechanism from the rawkey data. + */ +CK_RV SUNW_C_KeyToObject(CK_SESSION_HANDLE hSession, + CK_MECHANISM_TYPE mech, const void *rawkey, size_t rawkey_len, + CK_OBJECT_HANDLE_PTR obj); + + +#ifdef __cplusplus +} +#endif + +#endif /* _CRYPTOKI_H */ Index: openssl/crypto/engine/eng_all.c diff -u openssl/crypto/engine/eng_all.c:1.5.2.1.4.1.16.1.2.1 openssl/crypto/engine/eng_all.c:1.8 --- openssl/crypto/engine/eng_all.c:1.5.2.1.4.1.16.1.2.1 Mon Jun 13 15:10:52 2016 +++ openssl/crypto/engine/eng_all.c Mon Jun 13 15:20:31 2016 @@ -122,6 +122,14 @@ # if defined(OPENSSL_SYS_WIN32) && !defined(OPENSSL_NO_CAPIENG) ENGINE_load_capi(); # endif +# ifndef OPENSSL_NO_HW_PKCS11 +# ifndef OPENSSL_NO_HW_PKCS11CA + ENGINE_load_pk11ca(); +# endif +# ifndef OPENSSL_NO_HW_PKCS11SO + ENGINE_load_pk11so(); +# endif +# endif #endif ENGINE_register_all_complete(); } Index: openssl/crypto/engine/engine.h diff -u openssl/crypto/engine/engine.h:1.5.2.1.4.1.16.1 openssl/crypto/engine/engine.h:1.7 --- openssl/crypto/engine/engine.h:1.5.2.1.4.1.16.1 Wed Dec 23 18:09:30 2015 +++ openssl/crypto/engine/engine.h Wed Dec 23 18:27:11 2015 @@ -416,6 +416,12 @@ void ENGINE_load_rsax(void); void ENGINE_load_rdrand(void); void ENGINE_load_builtin_engines(void); +# ifndef OPENSSL_NO_HW_PKCS11CA +void ENGINE_load_pk11ca(void); +# endif +# ifndef OPENSSL_NO_HW_PKCS11SO +void ENGINE_load_pk11so(void); +# endif /* * Get and set global flags (ENGINE_TABLE_FLAG_***) for the implementation Index: openssl/crypto/engine/hw_pk11.c diff -u /dev/null openssl/crypto/engine/hw_pk11.c:1.33 --- /dev/null Mon Jun 13 15:26:29 2016 +++ openssl/crypto/engine/hw_pk11.c Fri Oct 4 14:07:41 2013 @@ -0,0 +1,4010 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* crypto/engine/hw_pk11.c */ +/* + * This product includes software developed by the OpenSSL Project for + * use in the OpenSSL Toolkit (http://www.openssl.org/). + * + * This project also referenced hw_pkcs11-0.9.7b.patch written by + * Afchine Madjlessi. + */ +/* + * ==================================================================== + * Copyright (c) 2000-2001 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifndef OPENSSL_NO_RSA +#include +#endif +#ifndef OPENSSL_NO_DSA +#include +#endif +#ifndef OPENSSL_NO_DH +#include +#endif +#include +#include +#include +#include +#include + +#ifdef OPENSSL_SYS_WIN32 +typedef int pid_t; +#define getpid() GetCurrentProcessId() +#define NOPTHREADS +#ifndef NULL_PTR +#define NULL_PTR NULL +#endif +#define CK_DEFINE_FUNCTION(returnType, name) \ + returnType __declspec(dllexport) name +#define CK_DECLARE_FUNCTION(returnType, name) \ + returnType __declspec(dllimport) name +#define CK_DECLARE_FUNCTION_POINTER(returnType, name) \ + returnType __declspec(dllimport) (* name) +#else +#include +#include +#include +#endif + +/* Debug mutexes */ +/*#undef DEBUG_MUTEX */ +#define DEBUG_MUTEX + +#ifndef NOPTHREADS +/* for pthread error check on Linuxes */ +#ifdef DEBUG_MUTEX +#define __USE_UNIX98 +#endif +#include +#endif + +#ifndef OPENSSL_NO_HW +#ifndef OPENSSL_NO_HW_PK11 +#ifndef OPENSSL_NO_HW_PK11CA + +/* label for debug messages printed on stderr */ +#define PK11_DBG "PKCS#11 ENGINE DEBUG" +/* prints a lot of debug messages on stderr about slot selection process */ +/* #undef DEBUG_SLOT_SELECTION */ +/* + * Solaris specific code. See comment at check_hw_mechanisms() for more + * information. + */ +#if defined(__SVR4) && defined(__sun) +#undef SOLARIS_HW_SLOT_SELECTION +#endif + +#ifdef OPENSSL_SYS_WIN32 +#pragma pack(push, cryptoki, 1) +#include "cryptoki.h" +#include "pkcs11.h" +#pragma pack(pop, cryptoki) +#else +#include "cryptoki.h" +#include "pkcs11.h" +#endif +#include "hw_pk11ca.h" +#include "hw_pk11_err.c" + +/* + * We use this lock to prevent multiple C_Login()s, guard getpassphrase(), + * uri_struct manipulation, and static token info. All of that is used by the + * RSA keys by reference feature. + */ +#ifndef NOPTHREADS +pthread_mutex_t *token_lock; +#endif + +#ifdef SOLARIS_HW_SLOT_SELECTION +/* + * Tables for symmetric ciphers and digest mechs found in the pkcs11_kernel + * library. See comment at check_hw_mechanisms() for more information. + */ +static int *hw_cnids; +static int *hw_dnids; +#endif /* SOLARIS_HW_SLOT_SELECTION */ + +/* PKCS#11 session caches and their locks for all operation types */ +static PK11_CACHE session_cache[OP_MAX]; + +/* + * We cache the flags so that we do not have to run C_GetTokenInfo() again when + * logging into the token. + */ +CK_FLAGS pubkey_token_flags; + +/* + * As stated in v2.20, 11.7 Object Management Function, in section for + * C_FindObjectsInit(), at most one search operation may be active at a given + * time in a given session. Therefore, C_Find{,Init,Final}Objects() should be + * grouped together to form one atomic search operation. This is already + * ensured by the property of unique PKCS#11 session handle used for each + * PK11_SESSION object. + * + * This is however not the biggest concern - maintaining consistency of the + * underlying object store is more important. The same section of the spec also + * says that one thread can be in the middle of a search operation while another + * thread destroys the object matching the search template which would result in + * invalid handle returned from the search operation. + * + * Hence, the following locks are used for both protection of the object stores. + * They are also used for active list protection. + */ +#ifndef NOPTHREADS +pthread_mutex_t *find_lock[OP_MAX] = { NULL }; +#endif + +/* + * lists of asymmetric key handles which are active (referenced by at least one + * PK11_SESSION structure, either held by a thread or present in free_session + * list) for given algorithm type + */ +PK11_active *active_list[OP_MAX] = { NULL }; + +/* + * Create all secret key objects in a global session so that they are available + * to use for other sessions. These other sessions may be opened or closed + * without losing the secret key objects. + */ +static CK_SESSION_HANDLE global_session = CK_INVALID_HANDLE; + +/* ENGINE level stuff */ +static int pk11_init(ENGINE *e); +static int pk11_library_init(ENGINE *e); +static int pk11_finish(ENGINE *e); +static int pk11_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void)); +static int pk11_destroy(ENGINE *e); + +/* RAND stuff */ +static void pk11_rand_seed(const void *buf, int num); +static void pk11_rand_add(const void *buf, int num, double add_entropy); +static void pk11_rand_cleanup(void); +static int pk11_rand_bytes(unsigned char *buf, int num); +static int pk11_rand_status(void); + +/* These functions are also used in other files */ +PK11_SESSION *pk11_get_session(PK11_OPTYPE optype); +void pk11_return_session(PK11_SESSION *sp, PK11_OPTYPE optype); + +/* active list manipulation functions used in this file */ +extern int pk11_active_delete(CK_OBJECT_HANDLE h, PK11_OPTYPE type); +extern void pk11_free_active_list(PK11_OPTYPE type); + +#ifndef OPENSSL_NO_RSA +int pk11_destroy_rsa_key_objects(PK11_SESSION *session); +int pk11_destroy_rsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock); +int pk11_destroy_rsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock); +#endif +#ifndef OPENSSL_NO_DSA +int pk11_destroy_dsa_key_objects(PK11_SESSION *session); +int pk11_destroy_dsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock); +int pk11_destroy_dsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock); +#endif +#ifndef OPENSSL_NO_DH +int pk11_destroy_dh_key_objects(PK11_SESSION *session); +int pk11_destroy_dh_object(PK11_SESSION *session, CK_BBOOL uselock); +#endif + +/* Local helper functions */ +static int pk11_free_all_sessions(void); +static int pk11_free_session_list(PK11_OPTYPE optype); +static int pk11_setup_session(PK11_SESSION *sp, PK11_OPTYPE optype); +static int pk11_destroy_cipher_key_objects(PK11_SESSION *session); +static int pk11_destroy_object(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE oh, + CK_BBOOL persistent); +static const char *get_PK11_LIBNAME(void); +static void free_PK11_LIBNAME(void); +static long set_PK11_LIBNAME(const char *name); + +/* Symmetric cipher and digest support functions */ +static int cipher_nid_to_pk11(int nid); +static int pk11_usable_ciphers(const int **nids); +static int pk11_usable_digests(const int **nids); +static int pk11_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc); +static int pk11_cipher_final(PK11_SESSION *sp); +#if OPENSSL_VERSION_NUMBER < 0x10000000L +static int pk11_cipher_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, unsigned int inl); +#else +static int pk11_cipher_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t inl); +#endif +static int pk11_cipher_cleanup(EVP_CIPHER_CTX *ctx); +static int pk11_engine_ciphers(ENGINE *e, const EVP_CIPHER **cipher, + const int **nids, int nid); +static int pk11_engine_digests(ENGINE *e, const EVP_MD **digest, + const int **nids, int nid); +static CK_OBJECT_HANDLE pk11_get_cipher_key(EVP_CIPHER_CTX *ctx, + const unsigned char *key, CK_KEY_TYPE key_type, PK11_SESSION *sp); +static int check_new_cipher_key(PK11_SESSION *sp, const unsigned char *key, + int key_len); +static int md_nid_to_pk11(int nid); +static int pk11_digest_init(EVP_MD_CTX *ctx); +static int pk11_digest_update(EVP_MD_CTX *ctx, const void *data, + size_t count); +static int pk11_digest_final(EVP_MD_CTX *ctx, unsigned char *md); +static int pk11_digest_copy(EVP_MD_CTX *to, const EVP_MD_CTX *from); +static int pk11_digest_cleanup(EVP_MD_CTX *ctx); + +static int pk11_choose_slots(int *any_slot_found); +static void pk11_find_symmetric_ciphers(CK_FUNCTION_LIST_PTR pflist, + CK_SLOT_ID current_slot, int *current_slot_n_cipher, + int *local_cipher_nids); +static void pk11_find_digests(CK_FUNCTION_LIST_PTR pflist, + CK_SLOT_ID current_slot, int *current_slot_n_digest, + int *local_digest_nids); +static void pk11_get_symmetric_cipher(CK_FUNCTION_LIST_PTR, int slot_id, + CK_MECHANISM_TYPE mech, int *current_slot_n_cipher, int *local_cipher_nids, + int id); +static void pk11_get_digest(CK_FUNCTION_LIST_PTR pflist, int slot_id, + CK_MECHANISM_TYPE mech, int *current_slot_n_digest, int *local_digest_nids, + int id); + +static int pk11_init_all_locks(void); +static void pk11_free_all_locks(void); + +#ifdef SOLARIS_HW_SLOT_SELECTION +static int check_hw_mechanisms(void); +static int nid_in_table(int nid, int *nid_table); +#endif /* SOLARIS_HW_SLOT_SELECTION */ + +/* Index for the supported ciphers */ +enum pk11_cipher_id { + PK11_DES_CBC, + PK11_DES3_CBC, + PK11_DES_ECB, + PK11_DES3_ECB, + PK11_RC4, + PK11_AES_128_CBC, + PK11_AES_192_CBC, + PK11_AES_256_CBC, + PK11_AES_128_ECB, + PK11_AES_192_ECB, + PK11_AES_256_ECB, + PK11_AES_128_CTR, + PK11_AES_192_CTR, + PK11_AES_256_CTR, + PK11_BLOWFISH_CBC, + PK11_CIPHER_MAX +}; + +/* Index for the supported digests */ +enum pk11_digest_id { + PK11_MD5, + PK11_SHA1, + PK11_SHA224, + PK11_SHA256, + PK11_SHA384, + PK11_SHA512, + PK11_DIGEST_MAX +}; + +#define TRY_OBJ_DESTROY(sp, obj_hdl, retval, uselock, alg_type, priv) \ + { \ + if (uselock) \ + LOCK_OBJSTORE(alg_type); \ + if (pk11_active_delete(obj_hdl, alg_type) == 1) \ + { \ + retval = pk11_destroy_object(sp->session, obj_hdl, \ + priv ? sp->priv_persistent : sp->pub_persistent); \ + } \ + if (uselock) \ + UNLOCK_OBJSTORE(alg_type); \ + } + +static int cipher_nids[PK11_CIPHER_MAX]; +static int digest_nids[PK11_DIGEST_MAX]; +static int cipher_count = 0; +static int digest_count = 0; +static CK_BBOOL pk11_have_rsa = CK_FALSE; +static CK_BBOOL pk11_have_recover = CK_FALSE; +static CK_BBOOL pk11_have_dsa = CK_FALSE; +static CK_BBOOL pk11_have_dh = CK_FALSE; +static CK_BBOOL pk11_have_random = CK_FALSE; + +typedef struct PK11_CIPHER_st + { + enum pk11_cipher_id id; + int nid; + int iv_len; + int min_key_len; + int max_key_len; + CK_KEY_TYPE key_type; + CK_MECHANISM_TYPE mech_type; + } PK11_CIPHER; + +static PK11_CIPHER ciphers[] = + { + { PK11_DES_CBC, NID_des_cbc, 8, 8, 8, + CKK_DES, CKM_DES_CBC, }, + { PK11_DES3_CBC, NID_des_ede3_cbc, 8, 24, 24, + CKK_DES3, CKM_DES3_CBC, }, + { PK11_DES_ECB, NID_des_ecb, 0, 8, 8, + CKK_DES, CKM_DES_ECB, }, + { PK11_DES3_ECB, NID_des_ede3_ecb, 0, 24, 24, + CKK_DES3, CKM_DES3_ECB, }, + { PK11_RC4, NID_rc4, 0, 16, 256, + CKK_RC4, CKM_RC4, }, + { PK11_AES_128_CBC, NID_aes_128_cbc, 16, 16, 16, + CKK_AES, CKM_AES_CBC, }, + { PK11_AES_192_CBC, NID_aes_192_cbc, 16, 24, 24, + CKK_AES, CKM_AES_CBC, }, + { PK11_AES_256_CBC, NID_aes_256_cbc, 16, 32, 32, + CKK_AES, CKM_AES_CBC, }, + { PK11_AES_128_ECB, NID_aes_128_ecb, 0, 16, 16, + CKK_AES, CKM_AES_ECB, }, + { PK11_AES_192_ECB, NID_aes_192_ecb, 0, 24, 24, + CKK_AES, CKM_AES_ECB, }, + { PK11_AES_256_ECB, NID_aes_256_ecb, 0, 32, 32, + CKK_AES, CKM_AES_ECB, }, + { PK11_AES_128_CTR, NID_aes_128_ctr, 16, 16, 16, + CKK_AES, CKM_AES_CTR, }, + { PK11_AES_192_CTR, NID_aes_192_ctr, 16, 24, 24, + CKK_AES, CKM_AES_CTR, }, + { PK11_AES_256_CTR, NID_aes_256_ctr, 16, 32, 32, + CKK_AES, CKM_AES_CTR, }, + { PK11_BLOWFISH_CBC, NID_bf_cbc, 8, 16, 16, + CKK_BLOWFISH, CKM_BLOWFISH_CBC, }, + }; + +typedef struct PK11_DIGEST_st + { + enum pk11_digest_id id; + int nid; + CK_MECHANISM_TYPE mech_type; + } PK11_DIGEST; + +static PK11_DIGEST digests[] = + { + {PK11_MD5, NID_md5, CKM_MD5, }, + {PK11_SHA1, NID_sha1, CKM_SHA_1, }, + {PK11_SHA224, NID_sha224, CKM_SHA224, }, + {PK11_SHA256, NID_sha256, CKM_SHA256, }, + {PK11_SHA384, NID_sha384, CKM_SHA384, }, + {PK11_SHA512, NID_sha512, CKM_SHA512, }, + {0, NID_undef, 0xFFFF, }, + }; + +/* + * Structure to be used for the cipher_data/md_data in + * EVP_CIPHER_CTX/EVP_MD_CTX structures in order to use the same pk11 + * session in multiple cipher_update calls + */ +typedef struct PK11_CIPHER_STATE_st + { + PK11_SESSION *sp; + } PK11_CIPHER_STATE; + + +/* + * libcrypto EVP stuff - this is how we get wired to EVP so the engine gets + * called when libcrypto requests a cipher NID. + * + * Note how the PK11_CIPHER_STATE is used here. + */ + +/* DES CBC EVP */ +static const EVP_CIPHER pk11_des_cbc = + { + NID_des_cbc, + 8, 8, 8, + EVP_CIPH_CBC_MODE, + pk11_cipher_init, + pk11_cipher_do_cipher, + pk11_cipher_cleanup, + sizeof (PK11_CIPHER_STATE), + EVP_CIPHER_set_asn1_iv, + EVP_CIPHER_get_asn1_iv, + NULL + }; + +/* 3DES CBC EVP */ +static const EVP_CIPHER pk11_3des_cbc = + { + NID_des_ede3_cbc, + 8, 24, 8, + EVP_CIPH_CBC_MODE, + pk11_cipher_init, + pk11_cipher_do_cipher, + pk11_cipher_cleanup, + sizeof (PK11_CIPHER_STATE), + EVP_CIPHER_set_asn1_iv, + EVP_CIPHER_get_asn1_iv, + NULL + }; + +/* + * ECB modes don't use an Initial Vector so that's why set_asn1_parameters and + * get_asn1_parameters fields are set to NULL. + */ +static const EVP_CIPHER pk11_des_ecb = + { + NID_des_ecb, + 8, 8, 8, + EVP_CIPH_ECB_MODE, + pk11_cipher_init, + pk11_cipher_do_cipher, + pk11_cipher_cleanup, + sizeof (PK11_CIPHER_STATE), + NULL, + NULL, + NULL + }; + +static const EVP_CIPHER pk11_3des_ecb = + { + NID_des_ede3_ecb, + 8, 24, 8, + EVP_CIPH_ECB_MODE, + pk11_cipher_init, + pk11_cipher_do_cipher, + pk11_cipher_cleanup, + sizeof (PK11_CIPHER_STATE), + NULL, + NULL, + NULL + }; + + +static const EVP_CIPHER pk11_aes_128_cbc = + { + NID_aes_128_cbc, + 16, 16, 16, + EVP_CIPH_CBC_MODE, + pk11_cipher_init, + pk11_cipher_do_cipher, + pk11_cipher_cleanup, + sizeof (PK11_CIPHER_STATE), + EVP_CIPHER_set_asn1_iv, + EVP_CIPHER_get_asn1_iv, + NULL + }; + +static const EVP_CIPHER pk11_aes_192_cbc = + { + NID_aes_192_cbc, + 16, 24, 16, + EVP_CIPH_CBC_MODE, + pk11_cipher_init, + pk11_cipher_do_cipher, + pk11_cipher_cleanup, + sizeof (PK11_CIPHER_STATE), + EVP_CIPHER_set_asn1_iv, + EVP_CIPHER_get_asn1_iv, + NULL + }; + +static const EVP_CIPHER pk11_aes_256_cbc = + { + NID_aes_256_cbc, + 16, 32, 16, + EVP_CIPH_CBC_MODE, + pk11_cipher_init, + pk11_cipher_do_cipher, + pk11_cipher_cleanup, + sizeof (PK11_CIPHER_STATE), + EVP_CIPHER_set_asn1_iv, + EVP_CIPHER_get_asn1_iv, + NULL + }; + +/* + * ECB modes don't use IV so that's why set_asn1_parameters and + * get_asn1_parameters are set to NULL. + */ +static const EVP_CIPHER pk11_aes_128_ecb = + { + NID_aes_128_ecb, + 16, 16, 0, + EVP_CIPH_ECB_MODE, + pk11_cipher_init, + pk11_cipher_do_cipher, + pk11_cipher_cleanup, + sizeof (PK11_CIPHER_STATE), + NULL, + NULL, + NULL + }; + +static const EVP_CIPHER pk11_aes_192_ecb = + { + NID_aes_192_ecb, + 16, 24, 0, + EVP_CIPH_ECB_MODE, + pk11_cipher_init, + pk11_cipher_do_cipher, + pk11_cipher_cleanup, + sizeof (PK11_CIPHER_STATE), + NULL, + NULL, + NULL + }; + +static const EVP_CIPHER pk11_aes_256_ecb = + { + NID_aes_256_ecb, + 16, 32, 0, + EVP_CIPH_ECB_MODE, + pk11_cipher_init, + pk11_cipher_do_cipher, + pk11_cipher_cleanup, + sizeof (PK11_CIPHER_STATE), + NULL, + NULL, + NULL + }; + +static const EVP_CIPHER pk11_aes_128_ctr = + { + NID_aes_128_ctr, + 16, 16, 16, + EVP_CIPH_CBC_MODE, + pk11_cipher_init, + pk11_cipher_do_cipher, + pk11_cipher_cleanup, + sizeof (PK11_CIPHER_STATE), + EVP_CIPHER_set_asn1_iv, + EVP_CIPHER_get_asn1_iv, + NULL + }; + +static const EVP_CIPHER pk11_aes_192_ctr = + { + NID_aes_192_ctr, + 16, 24, 16, + EVP_CIPH_CBC_MODE, + pk11_cipher_init, + pk11_cipher_do_cipher, + pk11_cipher_cleanup, + sizeof (PK11_CIPHER_STATE), + EVP_CIPHER_set_asn1_iv, + EVP_CIPHER_get_asn1_iv, + NULL + }; + +static const EVP_CIPHER pk11_aes_256_ctr = + { + NID_aes_256_ctr, + 16, 32, 16, + EVP_CIPH_CBC_MODE, + pk11_cipher_init, + pk11_cipher_do_cipher, + pk11_cipher_cleanup, + sizeof (PK11_CIPHER_STATE), + EVP_CIPHER_set_asn1_iv, + EVP_CIPHER_get_asn1_iv, + NULL + }; + +static const EVP_CIPHER pk11_bf_cbc = + { + NID_bf_cbc, + 8, 16, 8, + EVP_CIPH_VARIABLE_LENGTH, + pk11_cipher_init, + pk11_cipher_do_cipher, + pk11_cipher_cleanup, + sizeof (PK11_CIPHER_STATE), + EVP_CIPHER_set_asn1_iv, + EVP_CIPHER_get_asn1_iv, + NULL + }; + +static const EVP_CIPHER pk11_rc4 = + { + NID_rc4, + 1, 16, 0, + EVP_CIPH_VARIABLE_LENGTH, + pk11_cipher_init, + pk11_cipher_do_cipher, + pk11_cipher_cleanup, + sizeof (PK11_CIPHER_STATE), + NULL, + NULL, + NULL + }; + +static const EVP_MD pk11_md5 = + { + NID_md5, + NID_md5WithRSAEncryption, + MD5_DIGEST_LENGTH, + 0, + pk11_digest_init, + pk11_digest_update, + pk11_digest_final, + pk11_digest_copy, + pk11_digest_cleanup, + EVP_PKEY_RSA_method, + MD5_CBLOCK, + sizeof (PK11_CIPHER_STATE), + }; + +static const EVP_MD pk11_sha1 = + { + NID_sha1, + NID_sha1WithRSAEncryption, + SHA_DIGEST_LENGTH, + EVP_MD_FLAG_PKEY_METHOD_SIGNATURE|EVP_MD_FLAG_DIGALGID_ABSENT, + pk11_digest_init, + pk11_digest_update, + pk11_digest_final, + pk11_digest_copy, + pk11_digest_cleanup, + EVP_PKEY_RSA_method, + SHA_CBLOCK, + sizeof (PK11_CIPHER_STATE), + }; + +static const EVP_MD pk11_sha224 = + { + NID_sha224, + NID_sha224WithRSAEncryption, + SHA224_DIGEST_LENGTH, + EVP_MD_FLAG_PKEY_METHOD_SIGNATURE|EVP_MD_FLAG_DIGALGID_ABSENT, + pk11_digest_init, + pk11_digest_update, + pk11_digest_final, + pk11_digest_copy, + pk11_digest_cleanup, + EVP_PKEY_RSA_method, + /* SHA-224 uses the same cblock size as SHA-256 */ + SHA256_CBLOCK, + sizeof (PK11_CIPHER_STATE), + }; + +static const EVP_MD pk11_sha256 = + { + NID_sha256, + NID_sha256WithRSAEncryption, + SHA256_DIGEST_LENGTH, + EVP_MD_FLAG_PKEY_METHOD_SIGNATURE|EVP_MD_FLAG_DIGALGID_ABSENT, + pk11_digest_init, + pk11_digest_update, + pk11_digest_final, + pk11_digest_copy, + pk11_digest_cleanup, + EVP_PKEY_RSA_method, + SHA256_CBLOCK, + sizeof (PK11_CIPHER_STATE), + }; + +static const EVP_MD pk11_sha384 = + { + NID_sha384, + NID_sha384WithRSAEncryption, + SHA384_DIGEST_LENGTH, + EVP_MD_FLAG_PKEY_METHOD_SIGNATURE|EVP_MD_FLAG_DIGALGID_ABSENT, + pk11_digest_init, + pk11_digest_update, + pk11_digest_final, + pk11_digest_copy, + pk11_digest_cleanup, + EVP_PKEY_RSA_method, + /* SHA-384 uses the same cblock size as SHA-512 */ + SHA512_CBLOCK, + sizeof (PK11_CIPHER_STATE), + }; + +static const EVP_MD pk11_sha512 = + { + NID_sha512, + NID_sha512WithRSAEncryption, + SHA512_DIGEST_LENGTH, + EVP_MD_FLAG_PKEY_METHOD_SIGNATURE|EVP_MD_FLAG_DIGALGID_ABSENT, + pk11_digest_init, + pk11_digest_update, + pk11_digest_final, + pk11_digest_copy, + pk11_digest_cleanup, + EVP_PKEY_RSA_method, + SHA512_CBLOCK, + sizeof (PK11_CIPHER_STATE), + }; + +/* + * Initialization function. Sets up various PKCS#11 library components. + * The definitions for control commands specific to this engine + */ +#define PK11_CMD_SO_PATH ENGINE_CMD_BASE +#define PK11_CMD_PIN (ENGINE_CMD_BASE+1) +#define PK11_CMD_SLOT (ENGINE_CMD_BASE+2) +static const ENGINE_CMD_DEFN pk11_cmd_defns[] = + { + { + PK11_CMD_SO_PATH, + "SO_PATH", + "Specifies the path to the 'pkcs#11' shared library", + ENGINE_CMD_FLAG_STRING + }, + { + PK11_CMD_PIN, + "PIN", + "Specifies the pin code", + ENGINE_CMD_FLAG_STRING + }, + { + PK11_CMD_SLOT, + "SLOT", + "Specifies the slot (default is auto select)", + ENGINE_CMD_FLAG_NUMERIC, + }, + {0, NULL, NULL, 0} + }; + + +static RAND_METHOD pk11_random = + { + pk11_rand_seed, + pk11_rand_bytes, + pk11_rand_cleanup, + pk11_rand_add, + pk11_rand_bytes, + pk11_rand_status + }; + + +/* Constants used when creating the ENGINE */ +#ifdef OPENSSL_NO_HW_PK11SO +#error "can't load both crypto-accelerator and sign-only PKCS#11 engines" +#endif +static const char *engine_pk11_id = "pkcs11"; +static const char *engine_pk11_name = + "PKCS #11 engine support (crypto accelerator)"; + +CK_FUNCTION_LIST_PTR pFuncList = NULL; +static const char PK11_GET_FUNCTION_LIST[] = "C_GetFunctionList"; + +/* + * This is a static string constant for the DSO file name and the function + * symbol names to bind to. We set it in the Configure script based on whether + * this is 32 or 64 bit build. + */ +static const char def_PK11_LIBNAME[] = PK11_LIB_LOCATION; + +static CK_BBOOL mytrue = TRUE; +static CK_BBOOL myfalse = FALSE; +/* Needed in hw_pk11_pub.c as well so that's why it is not static. */ +CK_SLOT_ID pubkey_SLOTID = 0; +static CK_SLOT_ID rand_SLOTID = 0; +static CK_SLOT_ID SLOTID = 0; +char *pk11_pin = NULL; +static CK_BBOOL pk11_library_initialized = FALSE; +static CK_BBOOL pk11_atfork_initialized = FALSE; +static int pk11_pid = 0; + +static DSO *pk11_dso = NULL; + +/* allocate and initialize all locks used by the engine itself */ +static int pk11_init_all_locks(void) + { +#ifndef NOPTHREADS + int type; + pthread_mutexattr_t attr; + + if (pthread_mutexattr_init(&attr) != 0) + { + PK11err(PK11_F_INIT_ALL_LOCKS, 100); + return (0); + } + +#ifdef DEBUG_MUTEX + if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK) != 0) + { + PK11err(PK11_F_INIT_ALL_LOCKS, 101); + return (0); + } +#endif + + if ((token_lock = OPENSSL_malloc(sizeof (pthread_mutex_t))) == NULL) + goto malloc_err; + (void) pthread_mutex_init(token_lock, &attr); + +#ifndef OPENSSL_NO_RSA + find_lock[OP_RSA] = OPENSSL_malloc(sizeof (pthread_mutex_t)); + if (find_lock[OP_RSA] == NULL) + goto malloc_err; + (void) pthread_mutex_init(find_lock[OP_RSA], &attr); +#endif /* OPENSSL_NO_RSA */ + +#ifndef OPENSSL_NO_DSA + find_lock[OP_DSA] = OPENSSL_malloc(sizeof (pthread_mutex_t)); + if (find_lock[OP_DSA] == NULL) + goto malloc_err; + (void) pthread_mutex_init(find_lock[OP_DSA], &attr); +#endif /* OPENSSL_NO_DSA */ + +#ifndef OPENSSL_NO_DH + find_lock[OP_DH] = OPENSSL_malloc(sizeof (pthread_mutex_t)); + if (find_lock[OP_DH] == NULL) + goto malloc_err; + (void) pthread_mutex_init(find_lock[OP_DH], &attr); +#endif /* OPENSSL_NO_DH */ + + for (type = 0; type < OP_MAX; type++) + { + session_cache[type].lock = + OPENSSL_malloc(sizeof (pthread_mutex_t)); + if (session_cache[type].lock == NULL) + goto malloc_err; + (void) pthread_mutex_init(session_cache[type].lock, &attr); + } + + return (1); + +malloc_err: + pk11_free_all_locks(); + PK11err(PK11_F_INIT_ALL_LOCKS, PK11_R_MALLOC_FAILURE); + return (0); +#else + return (1); +#endif + } + +static void pk11_free_all_locks(void) + { +#ifndef NOPTHREADS + int type; + + if (token_lock != NULL) + { + (void) pthread_mutex_destroy(token_lock); + OPENSSL_free(token_lock); + token_lock = NULL; + } + +#ifndef OPENSSL_NO_RSA + if (find_lock[OP_RSA] != NULL) + { + (void) pthread_mutex_destroy(find_lock[OP_RSA]); + OPENSSL_free(find_lock[OP_RSA]); + find_lock[OP_RSA] = NULL; + } +#endif /* OPENSSL_NO_RSA */ +#ifndef OPENSSL_NO_DSA + if (find_lock[OP_DSA] != NULL) + { + (void) pthread_mutex_destroy(find_lock[OP_DSA]); + OPENSSL_free(find_lock[OP_DSA]); + find_lock[OP_DSA] = NULL; + } +#endif /* OPENSSL_NO_DSA */ +#ifndef OPENSSL_NO_DH + if (find_lock[OP_DH] != NULL) + { + (void) pthread_mutex_destroy(find_lock[OP_DH]); + OPENSSL_free(find_lock[OP_DH]); + find_lock[OP_DH] = NULL; + } +#endif /* OPENSSL_NO_DH */ + + for (type = 0; type < OP_MAX; type++) + { + if (session_cache[type].lock != NULL) + { + (void) pthread_mutex_destroy(session_cache[type].lock); + OPENSSL_free(session_cache[type].lock); + session_cache[type].lock = NULL; + } + } +#endif + } + +/* + * This internal function is used by ENGINE_pk11() and "dynamic" ENGINE support. + */ +static int bind_pk11(ENGINE *e) + { +#ifndef OPENSSL_NO_RSA + const RSA_METHOD *rsa = NULL; + RSA_METHOD *pk11_rsa = PK11_RSA(); +#endif /* OPENSSL_NO_RSA */ + if (!pk11_library_initialized) + if (!pk11_library_init(e)) + return (0); + + if (!ENGINE_set_id(e, engine_pk11_id) || + !ENGINE_set_name(e, engine_pk11_name) || + !ENGINE_set_ciphers(e, pk11_engine_ciphers) || + !ENGINE_set_digests(e, pk11_engine_digests)) + return (0); +#ifndef OPENSSL_NO_RSA + if (pk11_have_rsa == CK_TRUE) + { + if (!ENGINE_set_RSA(e, PK11_RSA()) || + !ENGINE_set_load_privkey_function(e, pk11_load_privkey) || + !ENGINE_set_load_pubkey_function(e, pk11_load_pubkey)) + return (0); +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: registered RSA\n", PK11_DBG); +#endif /* DEBUG_SLOT_SELECTION */ + } +#endif /* OPENSSL_NO_RSA */ +#ifndef OPENSSL_NO_DSA + if (pk11_have_dsa == CK_TRUE) + { + if (!ENGINE_set_DSA(e, PK11_DSA())) + return (0); +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: registered DSA\n", PK11_DBG); +#endif /* DEBUG_SLOT_SELECTION */ + } +#endif /* OPENSSL_NO_DSA */ +#ifndef OPENSSL_NO_DH + if (pk11_have_dh == CK_TRUE) + { + if (!ENGINE_set_DH(e, PK11_DH())) + return (0); +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: registered DH\n", PK11_DBG); +#endif /* DEBUG_SLOT_SELECTION */ + } +#endif /* OPENSSL_NO_DH */ + if (pk11_have_random) + { + if (!ENGINE_set_RAND(e, &pk11_random)) + return (0); +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: registered random\n", PK11_DBG); +#endif /* DEBUG_SLOT_SELECTION */ + } + if (!ENGINE_set_init_function(e, pk11_init) || + !ENGINE_set_destroy_function(e, pk11_destroy) || + !ENGINE_set_finish_function(e, pk11_finish) || + !ENGINE_set_ctrl_function(e, pk11_ctrl) || + !ENGINE_set_cmd_defns(e, pk11_cmd_defns)) + return (0); + +/* + * Apache calls OpenSSL function RSA_blinding_on() once during startup + * which in turn calls bn_mod_exp. Since we do not implement bn_mod_exp + * here, we wire it back to the OpenSSL software implementation. + * Since it is used only once, performance is not a concern. + */ +#ifndef OPENSSL_NO_RSA + rsa = RSA_PKCS1_SSLeay(); + pk11_rsa->rsa_mod_exp = rsa->rsa_mod_exp; + pk11_rsa->bn_mod_exp = rsa->bn_mod_exp; + if (pk11_have_recover != CK_TRUE) + pk11_rsa->rsa_pub_dec = rsa->rsa_pub_dec; +#endif /* OPENSSL_NO_RSA */ + + /* Ensure the pk11 error handling is set up */ + ERR_load_pk11_strings(); + + return (1); + } + +/* Dynamic engine support is disabled at a higher level for Solaris */ +#ifdef ENGINE_DYNAMIC_SUPPORT +#error "dynamic engine not supported" +static int bind_helper(ENGINE *e, const char *id) + { + if (id && (strcmp(id, engine_pk11_id) != 0)) + return (0); + + if (!bind_pk11(e)) + return (0); + + return (1); + } + +IMPLEMENT_DYNAMIC_CHECK_FN() +IMPLEMENT_DYNAMIC_BIND_FN(bind_helper) + +#else +static ENGINE *engine_pk11(void) + { + ENGINE *ret = ENGINE_new(); + + if (!ret) + return (NULL); + + if (!bind_pk11(ret)) + { + ENGINE_free(ret); + return (NULL); + } + + return (ret); + } + +void +ENGINE_load_pk11(void) + { + ENGINE *e_pk11 = NULL; + + /* + * Do not use dynamic PKCS#11 library on Solaris due to + * security reasons. We will link it in statically. + */ + /* Attempt to load PKCS#11 library */ + if (!pk11_dso) + pk11_dso = DSO_load(NULL, get_PK11_LIBNAME(), NULL, 0); + + if (pk11_dso == NULL) + { + PK11err(PK11_F_LOAD, PK11_R_DSO_FAILURE); + return; + } + + e_pk11 = engine_pk11(); + if (!e_pk11) + { + DSO_free(pk11_dso); + pk11_dso = NULL; + return; + } + + /* + * At this point, the pk11 shared library is either dynamically + * loaded or statically linked in. So, initialize the pk11 + * library before calling ENGINE_set_default since the latter + * needs cipher and digest algorithm information + */ + if (!pk11_library_init(e_pk11)) + { + DSO_free(pk11_dso); + pk11_dso = NULL; + ENGINE_free(e_pk11); + return; + } + + ENGINE_add(e_pk11); + + ENGINE_free(e_pk11); + ERR_clear_error(); + } +#endif /* ENGINE_DYNAMIC_SUPPORT */ + +/* + * These are the static string constants for the DSO file name and + * the function symbol names to bind to. + */ +static const char *PK11_LIBNAME = NULL; + +static const char *get_PK11_LIBNAME(void) + { + if (PK11_LIBNAME) + return (PK11_LIBNAME); + + return (def_PK11_LIBNAME); + } + +static void free_PK11_LIBNAME(void) + { + if (PK11_LIBNAME) + OPENSSL_free((void*)PK11_LIBNAME); + + PK11_LIBNAME = NULL; + } + +static long set_PK11_LIBNAME(const char *name) + { + free_PK11_LIBNAME(); + + return ((PK11_LIBNAME = BUF_strdup(name)) != NULL ? 1 : 0); + } + +/* acquire all engine specific mutexes before fork */ +static void pk11_fork_prepare(void) + { +#ifndef NOPTHREADS + int i; + + if (!pk11_library_initialized) + return; + + LOCK_OBJSTORE(OP_RSA); + LOCK_OBJSTORE(OP_DSA); + LOCK_OBJSTORE(OP_DH); + OPENSSL_assert(pthread_mutex_lock(token_lock) == 0); + for (i = 0; i < OP_MAX; i++) + { + OPENSSL_assert(pthread_mutex_lock(session_cache[i].lock) == 0); + } +#endif + } + +/* release all engine specific mutexes */ +static void pk11_fork_parent(void) + { +#ifndef NOPTHREADS + int i; + + if (!pk11_library_initialized) + return; + + for (i = OP_MAX - 1; i >= 0; i--) + { + OPENSSL_assert(pthread_mutex_unlock(session_cache[i].lock) == 0); + } + UNLOCK_OBJSTORE(OP_DH); + UNLOCK_OBJSTORE(OP_DSA); + UNLOCK_OBJSTORE(OP_RSA); + OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0); +#endif + } + +/* + * same situation as in parent - we need to unlock all locks to make them + * accessible to all threads. + */ +static void pk11_fork_child(void) + { +#ifndef NOPTHREADS + int i; + + if (!pk11_library_initialized) + return; + + for (i = OP_MAX - 1; i >= 0; i--) + { + OPENSSL_assert(pthread_mutex_unlock(session_cache[i].lock) == 0); + } + UNLOCK_OBJSTORE(OP_DH); + UNLOCK_OBJSTORE(OP_DSA); + UNLOCK_OBJSTORE(OP_RSA); + OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0); +#endif + } + +/* Initialization function for the pk11 engine */ +static int pk11_init(ENGINE *e) +{ + return (pk11_library_init(e)); +} + +static CK_C_INITIALIZE_ARGS pk11_init_args = + { + NULL_PTR, /* CreateMutex */ + NULL_PTR, /* DestroyMutex */ + NULL_PTR, /* LockMutex */ + NULL_PTR, /* UnlockMutex */ + CKF_OS_LOCKING_OK, /* flags */ + NULL_PTR, /* pReserved */ + }; + +/* + * Initialization function. Sets up various PKCS#11 library components. + * It selects a slot based on predefined critiera. In the process, it also + * count how many ciphers and digests to support. Since the cipher and + * digest information is needed when setting default engine, this function + * needs to be called before calling ENGINE_set_default. + */ +/* ARGSUSED */ +static int pk11_library_init(ENGINE *e) + { + CK_C_GetFunctionList p; + CK_RV rv = CKR_OK; + CK_INFO info; + CK_ULONG ul_state_len; + int any_slot_found; + int i; +#ifndef OPENSSL_SYS_WIN32 + struct sigaction sigint_act, sigterm_act, sighup_act; +#endif + + /* + * pk11_library_initialized is set to 0 in pk11_finish() which + * is called from ENGINE_finish(). However, if there is still + * at least one existing functional reference to the engine + * (see engine(3) for more information), pk11_finish() is + * skipped. For example, this can happen if an application + * forgets to clear one cipher context. In case of a fork() + * when the application is finishing the engine so that it can + * be reinitialized in the child, forgotten functional + * reference causes pk11_library_initialized to stay 1. In + * that case we need the PID check so that we properly + * initialize the engine again. + */ + if (pk11_library_initialized) + { + if (pk11_pid == getpid()) + { + return (1); + } + else + { + global_session = CK_INVALID_HANDLE; + /* + * free the locks first to prevent memory leak in case + * the application calls fork() without finishing the + * engine first. + */ + pk11_free_all_locks(); + } + } + + if (pk11_dso == NULL) + { + PK11err(PK11_F_LIBRARY_INIT, PK11_R_DSO_FAILURE); + goto err; + } + +#ifdef SOLARIS_HW_SLOT_SELECTION + if (check_hw_mechanisms() == 0) + goto err; +#endif /* SOLARIS_HW_SLOT_SELECTION */ + + /* get the C_GetFunctionList function from the loaded library */ + p = (CK_C_GetFunctionList)DSO_bind_func(pk11_dso, + PK11_GET_FUNCTION_LIST); + if (!p) + { + PK11err(PK11_F_LIBRARY_INIT, PK11_R_DSO_FAILURE); + goto err; + } + + /* get the full function list from the loaded library */ + rv = p(&pFuncList); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_LIBRARY_INIT, PK11_R_DSO_FAILURE, rv); + goto err; + } + +#ifndef OPENSSL_SYS_WIN32 + /* Not all PKCS#11 library are signal safe! */ + + (void) memset(&sigint_act, 0, sizeof(sigint_act)); + (void) memset(&sigterm_act, 0, sizeof(sigterm_act)); + (void) memset(&sighup_act, 0, sizeof(sighup_act)); + (void) sigaction(SIGINT, NULL, &sigint_act); + (void) sigaction(SIGTERM, NULL, &sigterm_act); + (void) sigaction(SIGHUP, NULL, &sighup_act); +#endif + rv = pFuncList->C_Initialize((CK_VOID_PTR)&pk11_init_args); +#ifndef OPENSSL_SYS_WIN32 + (void) sigaction(SIGINT, &sigint_act, NULL); + (void) sigaction(SIGTERM, &sigterm_act, NULL); + (void) sigaction(SIGHUP, &sighup_act, NULL); +#endif + if ((rv != CKR_OK) && (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)) + { + PK11err_add_data(PK11_F_LIBRARY_INIT, PK11_R_INITIALIZE, rv); + goto err; + } + + rv = pFuncList->C_GetInfo(&info); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_LIBRARY_INIT, PK11_R_GETINFO, rv); + goto err; + } + + if (pk11_choose_slots(&any_slot_found) == 0) + goto err; + + /* + * The library we use, set in def_PK11_LIBNAME, may not offer any + * slot(s). In that case, we must not proceed but we must not return an + * error. The reason is that applications that try to set up the PKCS#11 + * engine don't exit on error during the engine initialization just + * because no slot was present. + */ + if (any_slot_found == 0) + return (1); + + if (global_session == CK_INVALID_HANDLE) + { + /* Open the global_session for the new process */ + rv = pFuncList->C_OpenSession(SLOTID, CKF_SERIAL_SESSION, + NULL_PTR, NULL_PTR, &global_session); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_LIBRARY_INIT, + PK11_R_OPENSESSION, rv); + goto err; + } + } + + /* + * Disable digest if C_GetOperationState is not supported since + * this function is required by OpenSSL digest copy function + */ + /* Keyper fails to return CKR_FUNCTION_NOT_SUPPORTED */ + if (pFuncList->C_GetOperationState(global_session, NULL, &ul_state_len) + != CKR_OK) { +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: C_GetOperationState() not supported, " + "setting digest_count to 0\n", PK11_DBG); +#endif /* DEBUG_SLOT_SELECTION */ + digest_count = 0; + } + + pk11_library_initialized = TRUE; + pk11_pid = getpid(); + /* + * if initialization of the locks fails pk11_init_all_locks() + * will do the cleanup. + */ + if (!pk11_init_all_locks()) + goto err; + for (i = 0; i < OP_MAX; i++) + session_cache[i].head = NULL; + /* + * initialize active lists. We only use active lists + * for asymmetric ciphers. + */ + for (i = 0; i < OP_MAX; i++) + active_list[i] = NULL; + +#ifndef NOPTHREADS + if (!pk11_atfork_initialized) + { + if (pthread_atfork(pk11_fork_prepare, pk11_fork_parent, + pk11_fork_child) != 0) + { + PK11err(PK11_F_LIBRARY_INIT, PK11_R_ATFORK_FAILED); + goto err; + } + pk11_atfork_initialized = TRUE; + } +#endif + + return (1); + +err: + return (0); + } + +/* Destructor (complements the "ENGINE_pk11()" constructor) */ +/* ARGSUSED */ +static int pk11_destroy(ENGINE *e) + { + free_PK11_LIBNAME(); + ERR_unload_pk11_strings(); + if (pk11_pin) { + memset(pk11_pin, 0, strlen(pk11_pin)); + OPENSSL_free((void*)pk11_pin); + } + pk11_pin = NULL; + return (1); + } + +/* + * Termination function to clean up the session, the token, and the pk11 + * library. + */ +/* ARGSUSED */ +static int pk11_finish(ENGINE *e) + { + int i; + + if (pk11_pin) { + memset(pk11_pin, 0, strlen(pk11_pin)); + OPENSSL_free((void*)pk11_pin); + } + pk11_pin = NULL; + + if (pk11_dso == NULL) + { + PK11err(PK11_F_FINISH, PK11_R_NOT_LOADED); + goto err; + } + + OPENSSL_assert(pFuncList != NULL); + + if (pk11_free_all_sessions() == 0) + goto err; + + /* free all active lists */ + for (i = 0; i < OP_MAX; i++) + pk11_free_active_list(i); + + pFuncList->C_CloseSession(global_session); + global_session = CK_INVALID_HANDLE; + + /* + * Since we are part of a library (libcrypto.so), calling this function + * may have side-effects. + */ +#if 0 + pFuncList->C_Finalize(NULL); +#endif + + if (!DSO_free(pk11_dso)) + { + PK11err(PK11_F_FINISH, PK11_R_DSO_FAILURE); + goto err; + } + pk11_dso = NULL; + pFuncList = NULL; + pk11_library_initialized = FALSE; + pk11_pid = 0; + /* + * There is no way how to unregister atfork handlers (other than + * unloading the library) so we just free the locks. For this reason + * the atfork handlers check if the engine is initialized and bail out + * immediately if not. This is necessary in case a process finishes + * the engine before calling fork(). + */ + pk11_free_all_locks(); + + return (1); + +err: + return (0); + } + +/* Standard engine interface function to set the dynamic library path */ +/* ARGSUSED */ +static int pk11_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void)) + { + int initialized = ((pk11_dso == NULL) ? 0 : 1); + + switch (cmd) + { + case PK11_CMD_SO_PATH: + if (p == NULL) + { + PK11err(PK11_F_CTRL, ERR_R_PASSED_NULL_PARAMETER); + return (0); + } + + if (initialized) + { + PK11err(PK11_F_CTRL, PK11_R_ALREADY_LOADED); + return (0); + } + + return (set_PK11_LIBNAME((const char *)p)); + case PK11_CMD_PIN: + if (pk11_pin) { + memset(pk11_pin, 0, strlen(pk11_pin)); + OPENSSL_free((void*)pk11_pin); + } + pk11_pin = NULL; + + if (p == NULL) + { + PK11err(PK11_F_CTRL, ERR_R_PASSED_NULL_PARAMETER); + return (0); + } + + pk11_pin = BUF_strdup(p); + if (pk11_pin == NULL) + { + PK11err(PK11_F_GET_SESSION, PK11_R_MALLOC_FAILURE); + return (0); + } + return (1); + case PK11_CMD_SLOT: + SLOTID = (CK_SLOT_ID)i; +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: slot set\n", PK11_DBG); +#endif + return (1); + default: + break; + } + + PK11err(PK11_F_CTRL, PK11_R_CTRL_COMMAND_NOT_IMPLEMENTED); + + return (0); + } + + +/* Required function by the engine random interface. It does nothing here */ +static void pk11_rand_cleanup(void) + { + return; + } + +/* ARGSUSED */ +static void pk11_rand_add(const void *buf, int num, double add) + { + PK11_SESSION *sp; + + if ((sp = pk11_get_session(OP_RAND)) == NULL) + return; + + /* + * Ignore any errors (e.g. CKR_RANDOM_SEED_NOT_SUPPORTED) since + * the calling functions do not care anyway + */ + pFuncList->C_SeedRandom(sp->session, (unsigned char *) buf, num); + pk11_return_session(sp, OP_RAND); + + return; + } + +static void pk11_rand_seed(const void *buf, int num) + { + pk11_rand_add(buf, num, 0); + } + +static int pk11_rand_bytes(unsigned char *buf, int num) + { + CK_RV rv; + PK11_SESSION *sp; + + if ((sp = pk11_get_session(OP_RAND)) == NULL) + return (0); + + rv = pFuncList->C_GenerateRandom(sp->session, buf, num); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_RAND_BYTES, PK11_R_GENERATERANDOM, rv); + pk11_return_session(sp, OP_RAND); + return (0); + } + + pk11_return_session(sp, OP_RAND); + return (1); + } + +/* Required function by the engine random interface. It does nothing here */ +static int pk11_rand_status(void) + { + return (1); + } + +/* Free all BIGNUM structures from PK11_SESSION. */ +static void pk11_free_nums(PK11_SESSION *sp, PK11_OPTYPE optype) + { + switch (optype) + { +#ifndef OPENSSL_NO_RSA + case OP_RSA: + if (sp->opdata_rsa_n_num != NULL) + { + BN_free(sp->opdata_rsa_n_num); + sp->opdata_rsa_n_num = NULL; + } + if (sp->opdata_rsa_e_num != NULL) + { + BN_free(sp->opdata_rsa_e_num); + sp->opdata_rsa_e_num = NULL; + } + if (sp->opdata_rsa_pn_num != NULL) + { + BN_free(sp->opdata_rsa_pn_num); + sp->opdata_rsa_pn_num = NULL; + } + if (sp->opdata_rsa_pe_num != NULL) + { + BN_free(sp->opdata_rsa_pe_num); + sp->opdata_rsa_pe_num = NULL; + } + if (sp->opdata_rsa_d_num != NULL) + { + BN_free(sp->opdata_rsa_d_num); + sp->opdata_rsa_d_num = NULL; + } + break; +#endif +#ifndef OPENSSL_NO_DSA + case OP_DSA: + if (sp->opdata_dsa_pub_num != NULL) + { + BN_free(sp->opdata_dsa_pub_num); + sp->opdata_dsa_pub_num = NULL; + } + if (sp->opdata_dsa_priv_num != NULL) + { + BN_free(sp->opdata_dsa_priv_num); + sp->opdata_dsa_priv_num = NULL; + } + break; +#endif +#ifndef OPENSSL_NO_DH + case OP_DH: + if (sp->opdata_dh_priv_num != NULL) + { + BN_free(sp->opdata_dh_priv_num); + sp->opdata_dh_priv_num = NULL; + } + break; +#endif + default: + break; + } + } + +/* + * Get new PK11_SESSION structure ready for use. Every process must have + * its own freelist of PK11_SESSION structures so handle fork() here + * by destroying the old and creating new freelist. + * The returned PK11_SESSION structure is disconnected from the freelist. + */ +PK11_SESSION * +pk11_get_session(PK11_OPTYPE optype) + { + PK11_SESSION *sp = NULL, *sp1, *freelist; +#ifndef NOPTHREADS + pthread_mutex_t *freelist_lock = NULL; +#endif + static pid_t pid = 0; + pid_t new_pid; + CK_RV rv; + + switch (optype) + { + case OP_RSA: + case OP_DSA: + case OP_DH: + case OP_RAND: + case OP_DIGEST: + case OP_CIPHER: +#ifndef NOPTHREADS + freelist_lock = session_cache[optype].lock; +#endif + break; + default: + PK11err(PK11_F_GET_SESSION, + PK11_R_INVALID_OPERATION_TYPE); + return (NULL); + } +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_lock(freelist_lock) == 0); +#else + CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); +#endif + + /* + * Will use it to find out if we forked. We cannot use the PID field in + * the session structure because we could get a newly allocated session + * here, with no PID information. + */ + if (pid == 0) + pid = getpid(); + + freelist = session_cache[optype].head; + sp = freelist; + + /* + * If the free list is empty, allocate new unitialized (filled + * with zeroes) PK11_SESSION structure otherwise return first + * structure from the freelist. + */ + if (sp == NULL) + { + if ((sp = OPENSSL_malloc(sizeof (PK11_SESSION))) == NULL) + { + PK11err(PK11_F_GET_SESSION, + PK11_R_MALLOC_FAILURE); + goto err; + } + (void) memset(sp, 0, sizeof (PK11_SESSION)); + + /* + * It is a new session so it will look like a cache miss to the + * code below. So, we must not try to to destroy its members so + * mark them as unused. + */ + sp->opdata_rsa_priv_key = CK_INVALID_HANDLE; + sp->opdata_rsa_pub_key = CK_INVALID_HANDLE; + } + else + { + freelist = sp->next; + } + + /* + * Check whether we have forked. In that case, we must get rid of all + * inherited sessions and start allocating new ones. + */ + if (pid != (new_pid = getpid())) + { + pid = new_pid; + + /* + * We are a new process and thus need to free any inherited + * PK11_SESSION objects aside from the first session (sp) which + * is the only PK11_SESSION structure we will reuse (for the + * head of the list). + */ + while ((sp1 = freelist) != NULL) + { + freelist = sp1->next; + /* + * NOTE: we do not want to call pk11_free_all_sessions() + * here because it would close underlying PKCS#11 + * sessions and destroy all objects. + */ + pk11_free_nums(sp1, optype); + OPENSSL_free(sp1); + } + + /* we have to free the active list as well. */ + pk11_free_active_list(optype); + + /* Initialize the process */ + rv = pFuncList->C_Initialize((CK_VOID_PTR)&pk11_init_args); + if ((rv != CKR_OK) && (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)) + { + PK11err_add_data(PK11_F_GET_SESSION, PK11_R_INITIALIZE, + rv); + OPENSSL_free(sp); + sp = NULL; + goto err; + } + + /* + * Choose slot here since the slot table is different on this + * process. If we are here then we must have found at least one + * usable slot before so we don't need to check any_slot_found. + * See pk11_library_init()'s usage of this function for more + * information. + */ +#ifdef SOLARIS_HW_SLOT_SELECTION + if (check_hw_mechanisms() == 0) + goto err; +#endif /* SOLARIS_HW_SLOT_SELECTION */ + if (pk11_choose_slots(NULL) == 0) + goto err; + + /* Open the global_session for the new process */ + rv = pFuncList->C_OpenSession(SLOTID, CKF_SERIAL_SESSION, + NULL_PTR, NULL_PTR, &global_session); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_SESSION, PK11_R_OPENSESSION, + rv); + OPENSSL_free(sp); + sp = NULL; + goto err; + } + + /* + * It is an inherited session from our parent so it needs + * re-initialization. + */ + if (pk11_setup_session(sp, optype) == 0) + { + OPENSSL_free(sp); + sp = NULL; + goto err; + } + if (pk11_token_relogin(sp->session) == 0) + { + /* + * We will keep the session in the cache list and let + * the caller cope with the situation. + */ + freelist = sp; + sp = NULL; + goto err; + } + } + + if (sp->pid == 0) + { + /* It is a new session and needs initialization. */ + if (pk11_setup_session(sp, optype) == 0) + { + OPENSSL_free(sp); + sp = NULL; + } + } + + /* set new head for the list of PK11_SESSION objects */ + session_cache[optype].head = freelist; + +err: + if (sp != NULL) + sp->next = NULL; + +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_unlock(freelist_lock) == 0); +#else + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + + return (sp); + } + + +void +pk11_return_session(PK11_SESSION *sp, PK11_OPTYPE optype) + { +#ifndef NOPTHREADS + pthread_mutex_t *freelist_lock; +#endif + PK11_SESSION *freelist; + + /* + * If this is a session from the parent it will be taken care of and + * freed in pk11_get_session() as part of the post-fork clean up the + * next time we will ask for a new session. + */ + if (sp == NULL || sp->pid != getpid()) + return; + + switch (optype) + { + case OP_RSA: + case OP_DSA: + case OP_DH: + case OP_RAND: + case OP_DIGEST: + case OP_CIPHER: +#ifndef NOPTHREADS + freelist_lock = session_cache[optype].lock; +#endif + break; + default: + PK11err(PK11_F_RETURN_SESSION, + PK11_R_INVALID_OPERATION_TYPE); + return; + } + +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_lock(freelist_lock) == 0); +#else + CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); +#endif + freelist = session_cache[optype].head; + sp->next = freelist; + session_cache[optype].head = sp; +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_unlock(freelist_lock) == 0); +#else + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + } + + +/* Destroy all objects. This function is called when the engine is finished */ +static int pk11_free_all_sessions() + { + int ret = 1; + int type; + +#ifndef OPENSSL_NO_RSA + (void) pk11_destroy_rsa_key_objects(NULL); +#endif /* OPENSSL_NO_RSA */ +#ifndef OPENSSL_NO_DSA + (void) pk11_destroy_dsa_key_objects(NULL); +#endif /* OPENSSL_NO_DSA */ +#ifndef OPENSSL_NO_DH + (void) pk11_destroy_dh_key_objects(NULL); +#endif /* OPENSSL_NO_DH */ + (void) pk11_destroy_cipher_key_objects(NULL); + + /* + * We try to release as much as we can but any error means that we will + * return 0 on exit. + */ + for (type = 0; type < OP_MAX; type++) + { + if (pk11_free_session_list(type) == 0) + ret = 0; + } + + return (ret); + } + +/* + * Destroy session structures from the linked list specified. Free as many + * sessions as possible but any failure in C_CloseSession() means that we + * return an error on return. + */ +static int pk11_free_session_list(PK11_OPTYPE optype) + { + CK_RV rv; + PK11_SESSION *sp = NULL; + PK11_SESSION *freelist = NULL; + pid_t mypid = getpid(); +#ifndef NOPTHREADS + pthread_mutex_t *freelist_lock; +#endif + int ret = 1; + + switch (optype) + { + case OP_RSA: + case OP_DSA: + case OP_DH: + case OP_RAND: + case OP_DIGEST: + case OP_CIPHER: +#ifndef NOPTHREADS + freelist_lock = session_cache[optype].lock; +#endif + break; + default: + PK11err(PK11_F_FREE_ALL_SESSIONS, + PK11_R_INVALID_OPERATION_TYPE); + return (0); + } + +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_lock(freelist_lock) == 0); +#else + CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); +#endif + freelist = session_cache[optype].head; + while ((sp = freelist) != NULL) + { + if (sp->session != CK_INVALID_HANDLE && sp->pid == mypid) + { + rv = pFuncList->C_CloseSession(sp->session); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_FREE_ALL_SESSIONS, + PK11_R_CLOSESESSION, rv); + ret = 0; + } + } + freelist = sp->next; + pk11_free_nums(sp, optype); + OPENSSL_free(sp); + } + +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_unlock(freelist_lock) == 0); +#else + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + return (ret); + } + + +static int +pk11_setup_session(PK11_SESSION *sp, PK11_OPTYPE optype) + { + CK_RV rv; + CK_SLOT_ID myslot; + + switch (optype) + { + case OP_RSA: + case OP_DSA: + case OP_DH: + myslot = pubkey_SLOTID; + break; + case OP_RAND: + myslot = rand_SLOTID; + break; + case OP_DIGEST: + case OP_CIPHER: + myslot = SLOTID; + break; + default: + PK11err(PK11_F_SETUP_SESSION, + PK11_R_INVALID_OPERATION_TYPE); + return (0); + } + + sp->session = CK_INVALID_HANDLE; +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: myslot=%d optype=%d\n", PK11_DBG, myslot, optype); +#endif /* DEBUG_SLOT_SELECTION */ + rv = pFuncList->C_OpenSession(myslot, CKF_SERIAL_SESSION, + NULL_PTR, NULL_PTR, &sp->session); + if (rv == CKR_CRYPTOKI_NOT_INITIALIZED) + { + /* + * We are probably a child process so force the + * reinitialize of the session + */ + pk11_library_initialized = FALSE; + if (!pk11_library_init(NULL)) + return (0); + rv = pFuncList->C_OpenSession(myslot, CKF_SERIAL_SESSION, + NULL_PTR, NULL_PTR, &sp->session); + } + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_SETUP_SESSION, PK11_R_OPENSESSION, rv); + return (0); + } + + sp->pid = getpid(); + + switch (optype) + { +#ifndef OPENSSL_NO_RSA + case OP_RSA: + sp->opdata_rsa_pub_key = CK_INVALID_HANDLE; + sp->opdata_rsa_priv_key = CK_INVALID_HANDLE; + sp->opdata_rsa_pub = NULL; + sp->opdata_rsa_n_num = NULL; + sp->opdata_rsa_e_num = NULL; + sp->opdata_rsa_priv = NULL; + sp->opdata_rsa_pn_num = NULL; + sp->opdata_rsa_pe_num = NULL; + sp->opdata_rsa_d_num = NULL; + break; +#endif /* OPENSSL_NO_RSA */ +#ifndef OPENSSL_NO_DSA + case OP_DSA: + sp->opdata_dsa_pub_key = CK_INVALID_HANDLE; + sp->opdata_dsa_priv_key = CK_INVALID_HANDLE; + sp->opdata_dsa_pub = NULL; + sp->opdata_dsa_pub_num = NULL; + sp->opdata_dsa_priv = NULL; + sp->opdata_dsa_priv_num = NULL; + break; +#endif /* OPENSSL_NO_DSA */ +#ifndef OPENSSL_NO_DH + case OP_DH: + sp->opdata_dh_key = CK_INVALID_HANDLE; + sp->opdata_dh = NULL; + sp->opdata_dh_priv_num = NULL; + break; +#endif /* OPENSSL_NO_DH */ + case OP_CIPHER: + sp->opdata_cipher_key = CK_INVALID_HANDLE; + sp->opdata_encrypt = -1; + break; + default: + break; + } + + /* + * We always initialize the session as containing a non-persistent + * object. The key load functions set it to persistent if that is so. + */ + sp->pub_persistent = CK_FALSE; + sp->priv_persistent = CK_FALSE; + return (1); + } + +#ifndef OPENSSL_NO_RSA +/* Destroy RSA public key from single session. */ +int +pk11_destroy_rsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock) + { + int ret = 0; + + if (sp->opdata_rsa_pub_key != CK_INVALID_HANDLE) + { + TRY_OBJ_DESTROY(sp, sp->opdata_rsa_pub_key, + ret, uselock, OP_RSA, CK_FALSE); + sp->opdata_rsa_pub_key = CK_INVALID_HANDLE; + sp->opdata_rsa_pub = NULL; + if (sp->opdata_rsa_n_num != NULL) + { + BN_free(sp->opdata_rsa_n_num); + sp->opdata_rsa_n_num = NULL; + } + if (sp->opdata_rsa_e_num != NULL) + { + BN_free(sp->opdata_rsa_e_num); + sp->opdata_rsa_e_num = NULL; + } + } + + return (ret); + } + +/* Destroy RSA private key from single session. */ +int +pk11_destroy_rsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock) + { + int ret = 0; + + if (sp->opdata_rsa_priv_key != CK_INVALID_HANDLE) + { + TRY_OBJ_DESTROY(sp, sp->opdata_rsa_priv_key, + ret, uselock, OP_RSA, CK_TRUE); + sp->opdata_rsa_priv_key = CK_INVALID_HANDLE; + sp->opdata_rsa_priv = NULL; + if (sp->opdata_rsa_d_num != NULL) + { + BN_free(sp->opdata_rsa_d_num); + sp->opdata_rsa_d_num = NULL; + } + + /* + * For the RSA key by reference code, public components 'n'/'e' + * are the key components we use to check for the cache hit. We + * must free those as well. + */ + if (sp->opdata_rsa_pn_num != NULL) + { + BN_free(sp->opdata_rsa_pn_num); + sp->opdata_rsa_pn_num = NULL; + } + if (sp->opdata_rsa_pe_num != NULL) + { + BN_free(sp->opdata_rsa_pe_num); + sp->opdata_rsa_pe_num = NULL; + } + } + + return (ret); + } + +/* + * Destroy RSA key object wrapper. If session is NULL, try to destroy all + * objects in the free list. + */ +int +pk11_destroy_rsa_key_objects(PK11_SESSION *session) + { + int ret = 1; + PK11_SESSION *sp = NULL; + PK11_SESSION *local_free_session; + CK_BBOOL uselock = TRUE; + + if (session != NULL) + local_free_session = session; + else + { +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_lock(session_cache[OP_RSA].lock) == 0); +#else + CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); +#endif + local_free_session = session_cache[OP_RSA].head; + uselock = FALSE; + } + + /* + * go through the list of sessions and delete key objects + */ + while ((sp = local_free_session) != NULL) + { + local_free_session = sp->next; + + /* + * Do not terminate list traversal if one of the + * destroy operations fails. + */ + if (pk11_destroy_rsa_object_pub(sp, uselock) == 0) + { + ret = 0; + continue; + } + if (pk11_destroy_rsa_object_priv(sp, uselock) == 0) + { + ret = 0; + continue; + } + } + +#ifndef NOPTHREADS + if (session == NULL) + OPENSSL_assert(pthread_mutex_unlock(session_cache[OP_RSA].lock) == 0); +#else + if (session == NULL) + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + + return (ret); + } +#endif /* OPENSSL_NO_RSA */ + +#ifndef OPENSSL_NO_DSA +/* Destroy DSA public key from single session. */ +int +pk11_destroy_dsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock) + { + int ret = 0; + + if (sp->opdata_dsa_pub_key != CK_INVALID_HANDLE) + { + TRY_OBJ_DESTROY(sp, sp->opdata_dsa_pub_key, + ret, uselock, OP_DSA, CK_FALSE); + sp->opdata_dsa_pub_key = CK_INVALID_HANDLE; + sp->opdata_dsa_pub = NULL; + if (sp->opdata_dsa_pub_num != NULL) + { + BN_free(sp->opdata_dsa_pub_num); + sp->opdata_dsa_pub_num = NULL; + } + } + + return (ret); + } + +/* Destroy DSA private key from single session. */ +int +pk11_destroy_dsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock) + { + int ret = 0; + + if (sp->opdata_dsa_priv_key != CK_INVALID_HANDLE) + { + TRY_OBJ_DESTROY(sp, sp->opdata_dsa_priv_key, + ret, uselock, OP_DSA, CK_TRUE); + sp->opdata_dsa_priv_key = CK_INVALID_HANDLE; + sp->opdata_dsa_priv = NULL; + if (sp->opdata_dsa_priv_num != NULL) + { + BN_free(sp->opdata_dsa_priv_num); + sp->opdata_dsa_priv_num = NULL; + } + } + + return (ret); + } + +/* + * Destroy DSA key object wrapper. If session is NULL, try to destroy all + * objects in the free list. + */ +int +pk11_destroy_dsa_key_objects(PK11_SESSION *session) + { + int ret = 1; + PK11_SESSION *sp = NULL; + PK11_SESSION *local_free_session; + CK_BBOOL uselock = TRUE; + + if (session != NULL) + local_free_session = session; + else + { +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_lock(session_cache[OP_DSA].lock) == 0); +#else + CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); +#endif + local_free_session = session_cache[OP_DSA].head; + uselock = FALSE; + } + + /* + * go through the list of sessions and delete key objects + */ + while ((sp = local_free_session) != NULL) + { + local_free_session = sp->next; + + /* + * Do not terminate list traversal if one of the + * destroy operations fails. + */ + if (pk11_destroy_dsa_object_pub(sp, uselock) == 0) + { + ret = 0; + continue; + } + if (pk11_destroy_dsa_object_priv(sp, uselock) == 0) + { + ret = 0; + continue; + } + } + +#ifndef NOPTHREADS + if (session == NULL) + OPENSSL_assert(pthread_mutex_unlock(session_cache[OP_DSA].lock) == 0); +#else + if (session == NULL) + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + + return (ret); + } +#endif /* OPENSSL_NO_DSA */ + +#ifndef OPENSSL_NO_DH +/* Destroy DH key from single session. */ +int +pk11_destroy_dh_object(PK11_SESSION *sp, CK_BBOOL uselock) + { + int ret = 0; + + if (sp->opdata_dh_key != CK_INVALID_HANDLE) + { + TRY_OBJ_DESTROY(sp, sp->opdata_dh_key, + ret, uselock, OP_DH, CK_TRUE); + sp->opdata_dh_key = CK_INVALID_HANDLE; + sp->opdata_dh = NULL; + if (sp->opdata_dh_priv_num != NULL) + { + BN_free(sp->opdata_dh_priv_num); + sp->opdata_dh_priv_num = NULL; + } + } + + return (ret); + } + +/* + * Destroy DH key object wrapper. + * + * arg0: pointer to PKCS#11 engine session structure + * if session is NULL, try to destroy all objects in the free list + */ +int +pk11_destroy_dh_key_objects(PK11_SESSION *session) + { + int ret = 1; + PK11_SESSION *sp = NULL; + PK11_SESSION *local_free_session; + CK_BBOOL uselock = TRUE; + + if (session != NULL) + local_free_session = session; + else + { +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_lock(session_cache[OP_DH].lock) == 0); +#else + CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); +#endif + local_free_session = session_cache[OP_DH].head; + uselock = FALSE; + } + + while ((sp = local_free_session) != NULL) + { + local_free_session = sp->next; + + /* + * Do not terminate list traversal if one of the + * destroy operations fails. + */ + if (pk11_destroy_dh_object(sp, uselock) == 0) + { + ret = 0; + continue; + } + } + +#ifndef NOPTHREADS + if (session == NULL) + OPENSSL_assert(pthread_mutex_unlock(session_cache[OP_DH].lock) == 0); +#else + if (session == NULL) + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + + return (ret); + } +#endif /* OPENSSL_NO_DH */ + +static int +pk11_destroy_object(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE oh, + CK_BBOOL persistent) + { + CK_RV rv; + + /* + * We never try to destroy persistent objects which are the objects + * stored in the keystore. Also, we always use read-only sessions so + * C_DestroyObject() would be returning CKR_SESSION_READ_ONLY here. + */ + if (persistent == CK_TRUE) + return (1); + + rv = pFuncList->C_DestroyObject(session, oh); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DESTROY_OBJECT, PK11_R_DESTROYOBJECT, + rv); + return (0); + } + + return (1); + } + + +/* Symmetric ciphers and digests support functions */ + +static int +cipher_nid_to_pk11(int nid) + { + int i; + + for (i = 0; i < PK11_CIPHER_MAX; i++) + if (ciphers[i].nid == nid) + return (ciphers[i].id); + return (-1); + } + +static int +pk11_usable_ciphers(const int **nids) + { + if (cipher_count > 0) + *nids = cipher_nids; + else + *nids = NULL; + return (cipher_count); + } + +static int +pk11_usable_digests(const int **nids) + { + if (digest_count > 0) + *nids = digest_nids; + else + *nids = NULL; + return (digest_count); + } + +/* + * Init context for encryption or decryption using a symmetric key. + */ +static int pk11_init_symmetric(EVP_CIPHER_CTX *ctx, PK11_CIPHER *pcipher, + PK11_SESSION *sp, CK_MECHANISM_PTR pmech) + { + CK_RV rv; + CK_AES_CTR_PARAMS ctr_params; + + /* + * We expect pmech->mechanism to be already set and + * pParameter/ulParameterLen initialized to NULL/0 before + * pk11_init_symetric() is called. + */ + OPENSSL_assert(pmech->mechanism != 0); + OPENSSL_assert(pmech->pParameter == NULL); + OPENSSL_assert(pmech->ulParameterLen == 0); + + if (ctx->cipher->nid == NID_aes_128_ctr || + ctx->cipher->nid == NID_aes_192_ctr || + ctx->cipher->nid == NID_aes_256_ctr) + { + pmech->pParameter = (void *)(&ctr_params); + pmech->ulParameterLen = sizeof (ctr_params); + /* + * For now, we are limited to the fixed length of the counter, + * it covers the whole counter block. That's what RFC 4344 + * needs. For more information on internal structure of the + * counter block, see RFC 3686. If needed in the future, we can + * add code so that the counter length can be set via + * ENGINE_ctrl() function. + */ + ctr_params.ulCounterBits = AES_BLOCK_SIZE * 8; + OPENSSL_assert(pcipher->iv_len == AES_BLOCK_SIZE); + (void) memcpy(ctr_params.cb, ctx->iv, AES_BLOCK_SIZE); + } + else + { + if (pcipher->iv_len > 0) + { + pmech->pParameter = (void *)ctx->iv; + pmech->ulParameterLen = pcipher->iv_len; + } + } + + /* if we get here, the encryption needs to be reinitialized */ + if (ctx->encrypt) + rv = pFuncList->C_EncryptInit(sp->session, pmech, + sp->opdata_cipher_key); + else + rv = pFuncList->C_DecryptInit(sp->session, pmech, + sp->opdata_cipher_key); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_CIPHER_INIT, ctx->encrypt ? + PK11_R_ENCRYPTINIT : PK11_R_DECRYPTINIT, rv); + pk11_return_session(sp, OP_CIPHER); + return (0); + } + + return (1); + } + +/* ARGSUSED */ +static int +pk11_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc) + { + CK_MECHANISM mech; + int index; + PK11_CIPHER_STATE *state = (PK11_CIPHER_STATE *) ctx->cipher_data; + PK11_SESSION *sp; + PK11_CIPHER *p_ciph_table_row; + + state->sp = NULL; + + index = cipher_nid_to_pk11(ctx->cipher->nid); + if (index < 0 || index >= PK11_CIPHER_MAX) + return (0); + + p_ciph_table_row = &ciphers[index]; + /* + * iv_len in the ctx->cipher structure is the maximum IV length for the + * current cipher and it must be less or equal to the IV length in our + * ciphers table. The key length must be in the allowed interval. From + * all cipher modes that the PKCS#11 engine supports only RC4 allows a + * key length to be in some range, all other NIDs have a precise key + * length. Every application can define its own EVP functions so this + * code serves as a sanity check. + * + * Note that the reason why the IV length in ctx->cipher might be + * greater than the actual length is that OpenSSL uses BLOCK_CIPHER_defs + * macro to define functions that return EVP structures for all DES + * modes. So, even ECB modes get 8 byte IV. + */ + if (ctx->cipher->iv_len < p_ciph_table_row->iv_len || + ctx->key_len < p_ciph_table_row->min_key_len || + ctx->key_len > p_ciph_table_row->max_key_len) { + PK11err(PK11_F_CIPHER_INIT, PK11_R_KEY_OR_IV_LEN_PROBLEM); + return (0); + } + + if ((sp = pk11_get_session(OP_CIPHER)) == NULL) + return (0); + + /* if applicable, the mechanism parameter is used for IV */ + mech.mechanism = p_ciph_table_row->mech_type; + mech.pParameter = NULL; + mech.ulParameterLen = 0; + + /* The key object is destroyed here if it is not the current key. */ + (void) check_new_cipher_key(sp, key, ctx->key_len); + + /* + * If the key is the same and the encryption is also the same, then + * just reuse it. However, we must not forget to reinitialize the + * context that was finalized in pk11_cipher_cleanup(). + */ + if (sp->opdata_cipher_key != CK_INVALID_HANDLE && + sp->opdata_encrypt == ctx->encrypt) + { + state->sp = sp; + if (pk11_init_symmetric(ctx, p_ciph_table_row, sp, &mech) == 0) + return (0); + + return (1); + } + + /* + * Check if the key has been invalidated. If so, a new key object + * needs to be created. + */ + if (sp->opdata_cipher_key == CK_INVALID_HANDLE) + { + sp->opdata_cipher_key = pk11_get_cipher_key( + ctx, key, p_ciph_table_row->key_type, sp); + } + + if (sp->opdata_encrypt != ctx->encrypt && sp->opdata_encrypt != -1) + { + /* + * The previous encryption/decryption is different. Need to + * terminate the previous * active encryption/decryption here. + */ + if (!pk11_cipher_final(sp)) + { + pk11_return_session(sp, OP_CIPHER); + return (0); + } + } + + if (sp->opdata_cipher_key == CK_INVALID_HANDLE) + { + pk11_return_session(sp, OP_CIPHER); + return (0); + } + + /* now initialize the context with a new key */ + if (pk11_init_symmetric(ctx, p_ciph_table_row, sp, &mech) == 0) + return (0); + + sp->opdata_encrypt = ctx->encrypt; + state->sp = sp; + + return (1); + } + +/* + * When reusing the same key in an encryption/decryption session for a + * decryption/encryption session, we need to close the active session + * and recreate a new one. Note that the key is in the global session so + * that it needs not be recreated. + * + * It is more appropriate to use C_En/DecryptFinish here. At the time of this + * development, these two functions in the PKCS#11 libraries used return + * unexpected errors when passing in 0 length output. It may be a good + * idea to try them again if performance is a problem here and fix + * C_En/DecryptFinial if there are bugs there causing the problem. + */ +static int +pk11_cipher_final(PK11_SESSION *sp) + { + CK_RV rv; + + rv = pFuncList->C_CloseSession(sp->session); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_CIPHER_FINAL, PK11_R_CLOSESESSION, rv); + return (0); + } + + rv = pFuncList->C_OpenSession(SLOTID, CKF_SERIAL_SESSION, + NULL_PTR, NULL_PTR, &sp->session); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_CIPHER_FINAL, PK11_R_OPENSESSION, rv); + return (0); + } + + return (1); + } + +/* + * An engine interface function. The calling function allocates sufficient + * memory for the output buffer "out" to hold the results. + */ +#if OPENSSL_VERSION_NUMBER < 0x10000000L +static int +pk11_cipher_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, unsigned int inl) +#else +static int +pk11_cipher_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t inl) +#endif + { + PK11_CIPHER_STATE *state = (PK11_CIPHER_STATE *) ctx->cipher_data; + PK11_SESSION *sp; + CK_RV rv; + unsigned long outl = inl; + + if (state == NULL || state->sp == NULL) + return (0); + + sp = (PK11_SESSION *) state->sp; + + if (!inl) + return (1); + + /* RC4 is the only stream cipher we support */ + if (ctx->cipher->nid != NID_rc4 && (inl % ctx->cipher->block_size) != 0) + return (0); + + if (ctx->encrypt) + { + rv = pFuncList->C_EncryptUpdate(sp->session, + (unsigned char *)in, inl, out, &outl); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_CIPHER_DO_CIPHER, + PK11_R_ENCRYPTUPDATE, rv); + return (0); + } + } + else + { + rv = pFuncList->C_DecryptUpdate(sp->session, + (unsigned char *)in, inl, out, &outl); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_CIPHER_DO_CIPHER, + PK11_R_DECRYPTUPDATE, rv); + return (0); + } + } + + /* + * For DES_CBC, DES3_CBC, AES_CBC, and RC4, the output size is always + * the same size of input. + * The application has guaranteed to call the block ciphers with + * correctly aligned buffers. + */ + if (inl != outl) + return (0); + + return (1); + } + +/* + * Return the session to the pool. Calling C_EncryptFinal() and C_DecryptFinal() + * here is the right thing because in EVP_DecryptFinal_ex(), engine's + * do_cipher() is not even called, and in EVP_EncryptFinal_ex() it is called but + * the engine can't find out that it's the finalizing call. We wouldn't + * necessarily have to finalize the context here since reinitializing it with + * C_(Encrypt|Decrypt)Init() should be fine but for the sake of correctness, + * let's do it. Some implementations might leak memory if the previously used + * context is initialized without finalizing it first. + */ +static int +pk11_cipher_cleanup(EVP_CIPHER_CTX *ctx) + { + CK_RV rv; + CK_ULONG len = EVP_MAX_BLOCK_LENGTH; + CK_BYTE buf[EVP_MAX_BLOCK_LENGTH]; + PK11_CIPHER_STATE *state = ctx->cipher_data; + + if (state != NULL && state->sp != NULL) + { + /* + * We are not interested in the data here, we just need to get + * rid of the context. + */ + if (ctx->encrypt) + rv = pFuncList->C_EncryptFinal( + state->sp->session, buf, &len); + else + rv = pFuncList->C_DecryptFinal( + state->sp->session, buf, &len); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_CIPHER_CLEANUP, ctx->encrypt ? + PK11_R_ENCRYPTFINAL : PK11_R_DECRYPTFINAL, rv); + pk11_return_session(state->sp, OP_CIPHER); + return (0); + } + + pk11_return_session(state->sp, OP_CIPHER); + state->sp = NULL; + } + + return (1); + } + +/* + * Registered by the ENGINE when used to find out how to deal with + * a particular NID in the ENGINE. This says what we'll do at the + * top level - note, that list is restricted by what we answer with + */ +/* ARGSUSED */ +static int +pk11_engine_ciphers(ENGINE *e, const EVP_CIPHER **cipher, + const int **nids, int nid) + { + if (!cipher) + return (pk11_usable_ciphers(nids)); + + switch (nid) + { + case NID_des_ede3_cbc: + *cipher = &pk11_3des_cbc; + break; + case NID_des_cbc: + *cipher = &pk11_des_cbc; + break; + case NID_des_ede3_ecb: + *cipher = &pk11_3des_ecb; + break; + case NID_des_ecb: + *cipher = &pk11_des_ecb; + break; + case NID_aes_128_cbc: + *cipher = &pk11_aes_128_cbc; + break; + case NID_aes_192_cbc: + *cipher = &pk11_aes_192_cbc; + break; + case NID_aes_256_cbc: + *cipher = &pk11_aes_256_cbc; + break; + case NID_aes_128_ecb: + *cipher = &pk11_aes_128_ecb; + break; + case NID_aes_192_ecb: + *cipher = &pk11_aes_192_ecb; + break; + case NID_aes_256_ecb: + *cipher = &pk11_aes_256_ecb; + break; + case NID_bf_cbc: + *cipher = &pk11_bf_cbc; + break; + case NID_rc4: + *cipher = &pk11_rc4; + break; + case NID_aes_128_ctr: + *cipher = &pk11_aes_128_ctr; + break; + case NID_aes_192_ctr: + *cipher = &pk11_aes_192_ctr; + break; + case NID_aes_256_ctr: + *cipher = &pk11_aes_256_ctr; + break; + default: + *cipher = NULL; + break; + } + return (*cipher != NULL); + } + +/* ARGSUSED */ +static int +pk11_engine_digests(ENGINE *e, const EVP_MD **digest, + const int **nids, int nid) + { + if (!digest) + return (pk11_usable_digests(nids)); + + switch (nid) + { + case NID_md5: + *digest = &pk11_md5; + break; + case NID_sha1: + *digest = &pk11_sha1; + break; + case NID_sha224: + *digest = &pk11_sha224; + break; + case NID_sha256: + *digest = &pk11_sha256; + break; + case NID_sha384: + *digest = &pk11_sha384; + break; + case NID_sha512: + *digest = &pk11_sha512; + break; + default: + *digest = NULL; + break; + } + return (*digest != NULL); + } + + +/* Create a secret key object in a PKCS#11 session */ +static CK_OBJECT_HANDLE pk11_get_cipher_key(EVP_CIPHER_CTX *ctx, + const unsigned char *key, CK_KEY_TYPE key_type, PK11_SESSION *sp) + { + CK_RV rv; + CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE; + CK_OBJECT_CLASS obj_key = CKO_SECRET_KEY; + CK_ULONG ul_key_attr_count = 6; + unsigned char key_buf[PK11_KEY_LEN_MAX]; + + CK_ATTRIBUTE a_key_template[] = + { + {CKA_CLASS, (void*) NULL, sizeof (CK_OBJECT_CLASS)}, + {CKA_KEY_TYPE, (void*) NULL, sizeof (CK_KEY_TYPE)}, + {CKA_TOKEN, &myfalse, sizeof (myfalse)}, + {CKA_ENCRYPT, &mytrue, sizeof (mytrue)}, + {CKA_DECRYPT, &mytrue, sizeof (mytrue)}, + {CKA_VALUE, (void*) NULL, 0}, + }; + + /* + * Create secret key object in global_session. All other sessions + * can use the key handles. Here is why: + * OpenSSL will call EncryptInit and EncryptUpdate using a secret key. + * It may then call DecryptInit and DecryptUpdate using the same key. + * To use the same key object, we need to call EncryptFinal with + * a 0 length message. Currently, this does not work for 3DES + * mechanism. To get around this problem, we close the session and + * then create a new session to use the same key object. When a session + * is closed, all the object handles will be invalid. Thus, create key + * objects in a global session, an individual session may be closed to + * terminate the active operation. + */ + CK_SESSION_HANDLE session = global_session; + a_key_template[0].pValue = &obj_key; + a_key_template[1].pValue = &key_type; + if (ctx->key_len > PK11_KEY_LEN_MAX) + { + a_key_template[5].pValue = (void *) key; + } + else + { + memset(key_buf, 0, PK11_KEY_LEN_MAX); + memcpy(key_buf, key, ctx->key_len); + if ((key_type == CKK_DES) || + (key_type == CKK_DES2) || + (key_type == CKK_DES3)) + DES_fixup_key_parity((DES_cblock *) &key_buf[0]); + if ((key_type == CKK_DES2) || + (key_type == CKK_DES3)) + DES_fixup_key_parity((DES_cblock *) &key_buf[8]); + if (key_type == CKK_DES3) + DES_fixup_key_parity((DES_cblock *) &key_buf[16]); + a_key_template[5].pValue = (void *) key_buf; + } + a_key_template[5].ulValueLen = (unsigned long) ctx->key_len; + + rv = pFuncList->C_CreateObject(session, + a_key_template, ul_key_attr_count, &h_key); + if (rv != CKR_OK) + { + memset(key_buf, 0, PK11_KEY_LEN_MAX); + PK11err_add_data(PK11_F_GET_CIPHER_KEY, PK11_R_CREATEOBJECT, + rv); + goto err; + } + + /* + * Save the key information used in this session. + * The max can be saved is PK11_KEY_LEN_MAX. + */ + if (ctx->key_len > PK11_KEY_LEN_MAX) + { + sp->opdata_key_len = PK11_KEY_LEN_MAX; + (void) memcpy(sp->opdata_key, key, sp->opdata_key_len); + } + else + { + sp->opdata_key_len = ctx->key_len; + (void) memcpy(sp->opdata_key, key_buf, sp->opdata_key_len); + } + memset(key_buf, 0, PK11_KEY_LEN_MAX); +err: + + return (h_key); + } + +static int +md_nid_to_pk11(int nid) + { + int i; + + for (i = 0; i < PK11_DIGEST_MAX; i++) + if (digests[i].nid == nid) + return (digests[i].id); + return (-1); + } + +static int +pk11_digest_init(EVP_MD_CTX *ctx) + { + CK_RV rv; + CK_MECHANISM mech; + int index; + PK11_SESSION *sp; + PK11_DIGEST *pdp; + PK11_CIPHER_STATE *state = (PK11_CIPHER_STATE *) ctx->md_data; + + state->sp = NULL; + + index = md_nid_to_pk11(ctx->digest->type); + if (index < 0 || index >= PK11_DIGEST_MAX) + return (0); + + pdp = &digests[index]; + if ((sp = pk11_get_session(OP_DIGEST)) == NULL) + return (0); + + /* at present, no parameter is needed for supported digests */ + mech.mechanism = pdp->mech_type; + mech.pParameter = NULL; + mech.ulParameterLen = 0; + + rv = pFuncList->C_DigestInit(sp->session, &mech); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DIGEST_INIT, PK11_R_DIGESTINIT, rv); + pk11_return_session(sp, OP_DIGEST); + return (0); + } + + state->sp = sp; + + return (1); + } + +static int +pk11_digest_update(EVP_MD_CTX *ctx, const void *data, size_t count) + { + CK_RV rv; + PK11_CIPHER_STATE *state = (PK11_CIPHER_STATE *) ctx->md_data; + + /* 0 length message will cause a failure in C_DigestFinal */ + if (count == 0) + return (1); + + if (state == NULL || state->sp == NULL) + return (0); + + rv = pFuncList->C_DigestUpdate(state->sp->session, (CK_BYTE *) data, + count); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DIGEST_UPDATE, PK11_R_DIGESTUPDATE, rv); + pk11_return_session(state->sp, OP_DIGEST); + state->sp = NULL; + return (0); + } + + return (1); + } + +static int +pk11_digest_final(EVP_MD_CTX *ctx, unsigned char *md) + { + CK_RV rv; + unsigned long len; + PK11_CIPHER_STATE *state = (PK11_CIPHER_STATE *) ctx->md_data; + len = ctx->digest->md_size; + + if (state == NULL || state->sp == NULL) + return (0); + + rv = pFuncList->C_DigestFinal(state->sp->session, md, &len); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DIGEST_FINAL, PK11_R_DIGESTFINAL, rv); + pk11_return_session(state->sp, OP_DIGEST); + state->sp = NULL; + return (0); + } + + if (ctx->digest->md_size != len) + return (0); + + /* + * Final is called and digest is returned, so return the session + * to the pool + */ + pk11_return_session(state->sp, OP_DIGEST); + state->sp = NULL; + + return (1); + } + +static int +pk11_digest_copy(EVP_MD_CTX *to, const EVP_MD_CTX *from) + { + CK_RV rv; + int ret = 0; + PK11_CIPHER_STATE *state, *state_to; + CK_BYTE_PTR pstate = NULL; + CK_ULONG ul_state_len; + + /* The copy-from state */ + state = (PK11_CIPHER_STATE *) from->md_data; + if (state == NULL || state->sp == NULL) + goto err; + + /* Initialize the copy-to state */ + if (!pk11_digest_init(to)) + goto err; + state_to = (PK11_CIPHER_STATE *) to->md_data; + + /* Get the size of the operation state of the copy-from session */ + rv = pFuncList->C_GetOperationState(state->sp->session, NULL, + &ul_state_len); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DIGEST_COPY, PK11_R_GET_OPERATION_STATE, + rv); + goto err; + } + if (ul_state_len == 0) + { + goto err; + } + + pstate = OPENSSL_malloc(ul_state_len); + if (pstate == NULL) + { + PK11err(PK11_F_DIGEST_COPY, PK11_R_MALLOC_FAILURE); + goto err; + } + + /* Get the operation state of the copy-from session */ + rv = pFuncList->C_GetOperationState(state->sp->session, pstate, + &ul_state_len); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DIGEST_COPY, PK11_R_GET_OPERATION_STATE, + rv); + goto err; + } + + /* Set the operation state of the copy-to session */ + rv = pFuncList->C_SetOperationState(state_to->sp->session, pstate, + ul_state_len, 0, 0); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DIGEST_COPY, + PK11_R_SET_OPERATION_STATE, rv); + goto err; + } + + ret = 1; +err: + if (pstate != NULL) + OPENSSL_free(pstate); + + return (ret); + } + +/* Return any pending session state to the pool */ +static int +pk11_digest_cleanup(EVP_MD_CTX *ctx) + { + PK11_CIPHER_STATE *state = ctx->md_data; + unsigned char buf[EVP_MAX_MD_SIZE]; + + if (state != NULL && state->sp != NULL) + { + /* + * If state->sp is not NULL then pk11_digest_final() has not + * been called yet. We must call it now to free any memory + * that might have been allocated in the token when + * pk11_digest_init() was called. pk11_digest_final() + * will return the session to the cache. + */ + if (!pk11_digest_final(ctx, buf)) + return (0); + } + + return (1); + } + +/* + * Check if the new key is the same as the key object in the session. If the key + * is the same, no need to create a new key object. Otherwise, the old key + * object needs to be destroyed and a new one will be created. Return 1 for + * cache hit, 0 for cache miss. Note that we must check the key length first + * otherwise we could end up reusing a different, longer key with the same + * prefix. + */ +static int check_new_cipher_key(PK11_SESSION *sp, const unsigned char *key, + int key_len) + { + if (sp->opdata_key_len != key_len || + memcmp(sp->opdata_key, key, key_len) != 0) + { + (void) pk11_destroy_cipher_key_objects(sp); + return (0); + } + return (1); + } + +/* Destroy one or more secret key objects. */ +static int pk11_destroy_cipher_key_objects(PK11_SESSION *session) + { + int ret = 0; + PK11_SESSION *sp = NULL; + PK11_SESSION *local_free_session; + + if (session != NULL) + local_free_session = session; + else + { +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_lock(session_cache[OP_CIPHER].lock) == 0); +#else + CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); +#endif + local_free_session = session_cache[OP_CIPHER].head; + } + + while ((sp = local_free_session) != NULL) + { + local_free_session = sp->next; + + if (sp->opdata_cipher_key != CK_INVALID_HANDLE) + { + /* + * The secret key object is created in the + * global_session. See pk11_get_cipher_key(). + */ + if (pk11_destroy_object(global_session, + sp->opdata_cipher_key, CK_FALSE) == 0) + goto err; + sp->opdata_cipher_key = CK_INVALID_HANDLE; + } + } + ret = 1; +err: + +#ifndef NOPTHREADS + if (session == NULL) + OPENSSL_assert(pthread_mutex_unlock(session_cache[OP_CIPHER].lock) == 0); +#else + if (session == NULL) + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + + return (ret); + } + + +/* + * Public key mechanisms optionally supported + * + * CKM_RSA_X_509 + * CKM_RSA_PKCS + * CKM_DSA + * + * The first slot that supports at least one of those mechanisms is chosen as a + * public key slot. + * + * Symmetric ciphers optionally supported + * + * CKM_DES3_CBC + * CKM_DES_CBC + * CKM_AES_CBC + * CKM_DES3_ECB + * CKM_DES_ECB + * CKM_AES_ECB + * CKM_AES_CTR + * CKM_RC4 + * CKM_BLOWFISH_CBC + * + * Digests optionally supported + * + * CKM_MD5 + * CKM_SHA_1 + * CKM_SHA224 + * CKM_SHA256 + * CKM_SHA384 + * CKM_SHA512 + * + * The output of this function is a set of global variables indicating which + * mechanisms from RSA, DSA, DH and RAND are present, and also two arrays of + * mechanisms, one for symmetric ciphers and one for digests. Also, 3 global + * variables carry information about which slot was chosen for (a) public key + * mechanisms, (b) random operations, and (c) symmetric ciphers and digests. + */ +static int +pk11_choose_slots(int *any_slot_found) + { + CK_SLOT_ID_PTR pSlotList = NULL_PTR; + CK_ULONG ulSlotCount = 0; + CK_MECHANISM_INFO mech_info; + CK_TOKEN_INFO token_info; + unsigned int i; + CK_RV rv; + CK_SLOT_ID best_slot_sofar = 0; + CK_BBOOL found_candidate_slot = CK_FALSE; + int slot_n_cipher = 0; + int slot_n_digest = 0; + CK_SLOT_ID current_slot = 0; + int current_slot_n_cipher = 0; + int current_slot_n_digest = 0; + + int local_cipher_nids[PK11_CIPHER_MAX]; + int local_digest_nids[PK11_DIGEST_MAX]; + + /* let's initialize the output parameter */ + if (any_slot_found != NULL) + *any_slot_found = 0; + + /* Get slot list for memory allocation */ + rv = pFuncList->C_GetSlotList(CK_FALSE, NULL_PTR, &ulSlotCount); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_CHOOSE_SLOT, PK11_R_GETSLOTLIST, rv); + return (0); + } + + /* it's not an error if we didn't find any providers */ + if (ulSlotCount == 0) + { +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: no crypto providers found\n", PK11_DBG); +#endif /* DEBUG_SLOT_SELECTION */ + return (1); + } + + pSlotList = OPENSSL_malloc(ulSlotCount * sizeof (CK_SLOT_ID)); + + if (pSlotList == NULL) + { + PK11err(PK11_F_CHOOSE_SLOT, PK11_R_MALLOC_FAILURE); + return (0); + } + + /* Get the slot list for processing */ + rv = pFuncList->C_GetSlotList(CK_FALSE, pSlotList, &ulSlotCount); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_CHOOSE_SLOT, PK11_R_GETSLOTLIST, rv); + OPENSSL_free(pSlotList); + return (0); + } + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: provider: %s\n", PK11_DBG, def_PK11_LIBNAME); + fprintf(stderr, "%s: number of slots: %d\n", PK11_DBG, ulSlotCount); + + fprintf(stderr, "%s: == checking rand slots ==\n", PK11_DBG); +#endif /* DEBUG_SLOT_SELECTION */ + for (i = 0; i < ulSlotCount; i++) + { + current_slot = pSlotList[i]; + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: checking slot: %d\n", PK11_DBG, i); +#endif /* DEBUG_SLOT_SELECTION */ + /* Check if slot has random support. */ + rv = pFuncList->C_GetTokenInfo(current_slot, &token_info); + if (rv != CKR_OK) + continue; + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: token label: %.32s\n", PK11_DBG, token_info.label); +#endif /* DEBUG_SLOT_SELECTION */ + + if (token_info.flags & CKF_RNG) + { +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: this token has CKF_RNG flag\n", PK11_DBG); +#endif /* DEBUG_SLOT_SELECTION */ + pk11_have_random = CK_TRUE; + rand_SLOTID = current_slot; + break; + } + } + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: == checking pubkey slots ==\n", PK11_DBG); +#endif /* DEBUG_SLOT_SELECTION */ + + pubkey_SLOTID = pSlotList[0]; + for (i = 0; i < ulSlotCount; i++) + { + CK_BBOOL slot_has_rsa = CK_FALSE; + CK_BBOOL slot_has_recover = CK_FALSE; + CK_BBOOL slot_has_dsa = CK_FALSE; + CK_BBOOL slot_has_dh = CK_FALSE; + current_slot = pSlotList[i]; + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: checking slot: %d\n", PK11_DBG, i); +#endif /* DEBUG_SLOT_SELECTION */ + rv = pFuncList->C_GetTokenInfo(current_slot, &token_info); + if (rv != CKR_OK) + continue; + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: token label: %.32s\n", PK11_DBG, token_info.label); +#endif /* DEBUG_SLOT_SELECTION */ + +#ifndef OPENSSL_NO_RSA + /* + * Check if this slot is capable of signing and + * verifying with CKM_RSA_PKCS. + */ + rv = pFuncList->C_GetMechanismInfo(current_slot, CKM_RSA_PKCS, + &mech_info); + + if (rv == CKR_OK && ((mech_info.flags & CKF_SIGN) && + (mech_info.flags & CKF_VERIFY))) + { + /* + * Check if this slot is capable of encryption, + * decryption, sign, and verify with CKM_RSA_X_509. + */ + rv = pFuncList->C_GetMechanismInfo(current_slot, + CKM_RSA_X_509, &mech_info); + + if (rv == CKR_OK && ((mech_info.flags & CKF_SIGN) && + (mech_info.flags & CKF_VERIFY) && + (mech_info.flags & CKF_ENCRYPT) && + (mech_info.flags & CKF_DECRYPT))) + { + slot_has_rsa = CK_TRUE; + if (mech_info.flags & CKF_VERIFY_RECOVER) + { + slot_has_recover = CK_TRUE; + } + } + } +#endif /* OPENSSL_NO_RSA */ + +#ifndef OPENSSL_NO_DSA + /* + * Check if this slot is capable of signing and + * verifying with CKM_DSA. + */ + rv = pFuncList->C_GetMechanismInfo(current_slot, CKM_DSA, + &mech_info); + if (rv == CKR_OK && ((mech_info.flags & CKF_SIGN) && + (mech_info.flags & CKF_VERIFY))) + { + slot_has_dsa = CK_TRUE; + } + +#endif /* OPENSSL_NO_DSA */ + +#ifndef OPENSSL_NO_DH + /* + * Check if this slot is capable of DH key generataion and + * derivation. + */ + rv = pFuncList->C_GetMechanismInfo(current_slot, + CKM_DH_PKCS_KEY_PAIR_GEN, &mech_info); + + if (rv == CKR_OK && (mech_info.flags & CKF_GENERATE_KEY_PAIR)) + { + rv = pFuncList->C_GetMechanismInfo(current_slot, + CKM_DH_PKCS_DERIVE, &mech_info); + if (rv == CKR_OK && (mech_info.flags & CKF_DERIVE)) + { + slot_has_dh = CK_TRUE; + } + } +#endif /* OPENSSL_NO_DH */ + + if (!found_candidate_slot && + (slot_has_rsa || slot_has_dsa || slot_has_dh)) + { +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, + "%s: potential slot: %d\n", PK11_DBG, current_slot); +#endif /* DEBUG_SLOT_SELECTION */ + best_slot_sofar = current_slot; + pk11_have_rsa = slot_has_rsa; + pk11_have_recover = slot_has_recover; + pk11_have_dsa = slot_has_dsa; + pk11_have_dh = slot_has_dh; + found_candidate_slot = CK_TRUE; + /* + * Cache the flags for later use. We might + * need those if RSA keys by reference feature + * is used. + */ + pubkey_token_flags = token_info.flags; +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, + "%s: setting found_candidate_slot to CK_TRUE\n", + PK11_DBG); + fprintf(stderr, + "%s: best so far slot: %d\n", PK11_DBG, + best_slot_sofar); + fprintf(stderr, "%s: pubkey flags changed to " + "%lu.\n", PK11_DBG, pubkey_token_flags); + } + else + { + fprintf(stderr, + "%s: no rsa/dsa/dh\n", PK11_DBG); + } +#else + } /* if */ +#endif /* DEBUG_SLOT_SELECTION */ + } /* for */ + + if (found_candidate_slot == CK_TRUE) + { + pubkey_SLOTID = best_slot_sofar; + } + + found_candidate_slot = CK_FALSE; + best_slot_sofar = 0; + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: == checking cipher/digest ==\n", PK11_DBG); +#endif /* DEBUG_SLOT_SELECTION */ + + SLOTID = pSlotList[0]; + for (i = 0; i < ulSlotCount; i++) + { +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: checking slot: %d\n", PK11_DBG, i); +#endif /* DEBUG_SLOT_SELECTION */ + + current_slot = pSlotList[i]; + current_slot_n_cipher = 0; + current_slot_n_digest = 0; + (void) memset(local_cipher_nids, 0, sizeof (local_cipher_nids)); + (void) memset(local_digest_nids, 0, sizeof (local_digest_nids)); + + pk11_find_symmetric_ciphers(pFuncList, current_slot, + ¤t_slot_n_cipher, local_cipher_nids); + + pk11_find_digests(pFuncList, current_slot, + ¤t_slot_n_digest, local_digest_nids); + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: current_slot_n_cipher %d\n", PK11_DBG, + current_slot_n_cipher); + fprintf(stderr, "%s: current_slot_n_digest %d\n", PK11_DBG, + current_slot_n_digest); + fprintf(stderr, "%s: best so far cipher/digest slot: %d\n", + PK11_DBG, best_slot_sofar); +#endif /* DEBUG_SLOT_SELECTION */ + + /* + * If the current slot supports more ciphers/digests than + * the previous best one we change the current best to this one, + * otherwise leave it where it is. + */ + if ((current_slot_n_cipher + current_slot_n_digest) > + (slot_n_cipher + slot_n_digest)) + { +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, + "%s: changing best so far slot to %d\n", + PK11_DBG, current_slot); +#endif /* DEBUG_SLOT_SELECTION */ + best_slot_sofar = SLOTID = current_slot; + cipher_count = slot_n_cipher = current_slot_n_cipher; + digest_count = slot_n_digest = current_slot_n_digest; + (void) memcpy(cipher_nids, local_cipher_nids, + sizeof (local_cipher_nids)); + (void) memcpy(digest_nids, local_digest_nids, + sizeof (local_digest_nids)); + } + } + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, + "%s: chosen pubkey slot: %d\n", PK11_DBG, pubkey_SLOTID); + fprintf(stderr, + "%s: chosen rand slot: %d\n", PK11_DBG, rand_SLOTID); + fprintf(stderr, + "%s: chosen cipher/digest slot: %d\n", PK11_DBG, SLOTID); + fprintf(stderr, + "%s: pk11_have_rsa %d\n", PK11_DBG, pk11_have_rsa); + fprintf(stderr, + "%s: pk11_have_recover %d\n", PK11_DBG, pk11_have_recover); + fprintf(stderr, + "%s: pk11_have_dsa %d\n", PK11_DBG, pk11_have_dsa); + fprintf(stderr, + "%s: pk11_have_dh %d\n", PK11_DBG, pk11_have_dh); + fprintf(stderr, + "%s: pk11_have_random %d\n", PK11_DBG, pk11_have_random); + fprintf(stderr, + "%s: cipher_count %d\n", PK11_DBG, cipher_count); + fprintf(stderr, + "%s: digest_count %d\n", PK11_DBG, digest_count); +#endif /* DEBUG_SLOT_SELECTION */ + + if (pSlotList != NULL) + OPENSSL_free(pSlotList); + +#ifdef SOLARIS_HW_SLOT_SELECTION + OPENSSL_free(hw_cnids); + OPENSSL_free(hw_dnids); +#endif /* SOLARIS_HW_SLOT_SELECTION */ + + if (any_slot_found != NULL) + *any_slot_found = 1; + return (1); + } + +static void pk11_get_symmetric_cipher(CK_FUNCTION_LIST_PTR pflist, + int slot_id, CK_MECHANISM_TYPE mech, int *current_slot_n_cipher, + int *local_cipher_nids, int id) + { + CK_MECHANISM_INFO mech_info; + CK_RV rv; + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: checking mech: %x", PK11_DBG, mech); +#endif /* DEBUG_SLOT_SELECTION */ + rv = pflist->C_GetMechanismInfo(slot_id, mech, &mech_info); + + if (rv != CKR_OK) + { +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, " not found\n"); +#endif /* DEBUG_SLOT_SELECTION */ + return; + } + + if ((mech_info.flags & CKF_ENCRYPT) && + (mech_info.flags & CKF_DECRYPT)) + { +#ifdef SOLARIS_HW_SLOT_SELECTION + if (nid_in_table(ciphers[id].nid, hw_cnids)) +#endif /* SOLARIS_HW_SLOT_SELECTION */ + { +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, " usable\n"); +#endif /* DEBUG_SLOT_SELECTION */ + local_cipher_nids[(*current_slot_n_cipher)++] = + ciphers[id].nid; + } +#ifdef SOLARIS_HW_SLOT_SELECTION +#ifdef DEBUG_SLOT_SELECTION + else + { + fprintf(stderr, " rejected, software implementation only\n"); + } +#endif /* DEBUG_SLOT_SELECTION */ +#endif /* SOLARIS_HW_SLOT_SELECTION */ + } +#ifdef DEBUG_SLOT_SELECTION + else + { + fprintf(stderr, " unusable\n"); + } +#endif /* DEBUG_SLOT_SELECTION */ + + return; + } + +static void pk11_get_digest(CK_FUNCTION_LIST_PTR pflist, int slot_id, + CK_MECHANISM_TYPE mech, int *current_slot_n_digest, int *local_digest_nids, + int id) + { + CK_MECHANISM_INFO mech_info; + CK_RV rv; + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: checking mech: %x", PK11_DBG, mech); +#endif /* DEBUG_SLOT_SELECTION */ + rv = pflist->C_GetMechanismInfo(slot_id, mech, &mech_info); + + if (rv != CKR_OK) + { +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, " not found\n"); +#endif /* DEBUG_SLOT_SELECTION */ + return; + } + + if (mech_info.flags & CKF_DIGEST) + { +#ifdef SOLARIS_HW_SLOT_SELECTION + if (nid_in_table(digests[id].nid, hw_dnids)) +#endif /* SOLARIS_HW_SLOT_SELECTION */ + { +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, " usable\n"); +#endif /* DEBUG_SLOT_SELECTION */ + local_digest_nids[(*current_slot_n_digest)++] = + digests[id].nid; + } +#ifdef SOLARIS_HW_SLOT_SELECTION +#ifdef DEBUG_SLOT_SELECTION + else + { + fprintf(stderr, " rejected, software implementation only\n"); + } +#endif /* DEBUG_SLOT_SELECTION */ +#endif /* SOLARIS_HW_SLOT_SELECTION */ + } +#ifdef DEBUG_SLOT_SELECTION + else + { + fprintf(stderr, " unusable\n"); + } +#endif /* DEBUG_SLOT_SELECTION */ + + return; + } + +/* Find what symmetric ciphers this slot supports. */ +static void pk11_find_symmetric_ciphers(CK_FUNCTION_LIST_PTR pflist, + CK_SLOT_ID current_slot, int *current_slot_n_cipher, int *local_cipher_nids) + { + int i; + + for (i = 0; i < PK11_CIPHER_MAX; ++i) + { + pk11_get_symmetric_cipher(pflist, current_slot, + ciphers[i].mech_type, current_slot_n_cipher, + local_cipher_nids, ciphers[i].id); + } + } + +/* Find what digest algorithms this slot supports. */ +static void pk11_find_digests(CK_FUNCTION_LIST_PTR pflist, + CK_SLOT_ID current_slot, int *current_slot_n_digest, int *local_digest_nids) + { + int i; + + for (i = 0; i < PK11_DIGEST_MAX; ++i) + { + pk11_get_digest(pflist, current_slot, digests[i].mech_type, + current_slot_n_digest, local_digest_nids, digests[i].id); + } + } + +#ifdef SOLARIS_HW_SLOT_SELECTION +/* + * It would be great if we could use pkcs11_kernel directly since this library + * offers hardware slots only. That's the easiest way to achieve the situation + * where we use the hardware accelerators when present and OpenSSL native code + * otherwise. That presumes the fact that OpenSSL native code is faster than the + * code in the soft token. It's a logical assumption - Crypto Framework has some + * inherent overhead so going there for the software implementation of a + * mechanism should be logically slower in contrast to the OpenSSL native code, + * presuming that both implementations are of similar speed. For example, the + * soft token for AES is roughly three times slower than OpenSSL for 64 byte + * blocks and still 20% slower for 8KB blocks. So, if we want to ship products + * that use the PKCS#11 engine by default, we must somehow avoid that regression + * on machines without hardware acceleration. That's why switching to the + * pkcs11_kernel library seems like a very good idea. + * + * The problem is that OpenSSL built with SunStudio is roughly 2x slower for + * asymmetric operations (RSA/DSA/DH) than the soft token built with the same + * compiler. That means that if we switched to pkcs11_kernel from the libpkcs11 + * library, we would have had a performance regression on machines without + * hardware acceleration for asymmetric operations for all applications that use + * the PKCS#11 engine. There is one such application - Apache web server since + * it's shipped configured to use the PKCS#11 engine by default. Having said + * that, we can't switch to the pkcs11_kernel library now and have to come with + * a solution that, on non-accelerated machines, uses the OpenSSL native code + * for all symmetric ciphers and digests while it uses the soft token for + * asymmetric operations. + * + * This is the idea: dlopen() pkcs11_kernel directly and find out what + * mechanisms are there. We don't care about duplications (more slots can + * support the same mechanism), we just want to know what mechanisms can be + * possibly supported in hardware on that particular machine. As said before, + * pkcs11_kernel will show you hardware providers only. + * + * Then, we rely on the fact that since we use libpkcs11 library we will find + * the metaslot. When we go through the metaslot's mechanisms for symmetric + * ciphers and digests, we check that any found mechanism is in the table + * created using the pkcs11_kernel library. So, as a result we have two arrays + * of mechanisms that were advertised as supported in hardware which was the + * goal of that whole excercise. Thus, we can use libpkcs11 but avoid soft token + * code for symmetric ciphers and digests. See pk11_choose_slots() for more + * information. + * + * This is Solaris specific code, if SOLARIS_HW_SLOT_SELECTION is not defined + * the code won't be used. + */ +#if defined(__sparcv9) || defined(__x86_64) || defined(__amd64) +static const char pkcs11_kernel[] = "/usr/lib/security/64/pkcs11_kernel.so.1"; +#else +static const char pkcs11_kernel[] = "/usr/lib/security/pkcs11_kernel.so.1"; +#endif + +/* + * Check hardware capabilities of the machines. The output are two lists, + * hw_cnids and hw_dnids, that contain hardware mechanisms found in all hardware + * providers together. They are not sorted and may contain duplicate mechanisms. + */ +static int check_hw_mechanisms(void) + { + int i; + CK_RV rv; + void *handle; + CK_C_GetFunctionList p; + CK_TOKEN_INFO token_info; + CK_ULONG ulSlotCount = 0; + int n_cipher = 0, n_digest = 0; + CK_FUNCTION_LIST_PTR pflist = NULL; + CK_SLOT_ID_PTR pSlotList = NULL_PTR; + int *tmp_hw_cnids = NULL, *tmp_hw_dnids = NULL; + int hw_ctable_size, hw_dtable_size; + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: SOLARIS_HW_SLOT_SELECTION code running\n", + PK11_DBG); +#endif + if ((handle = dlopen(pkcs11_kernel, RTLD_LAZY)) == NULL) + { + PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_DSO_FAILURE); + goto err; + } + + if ((p = (CK_C_GetFunctionList)dlsym(handle, + PK11_GET_FUNCTION_LIST)) == NULL) + { + PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_DSO_FAILURE); + goto err; + } + + /* get the full function list from the loaded library */ + if (p(&pflist) != CKR_OK) + { + PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_DSO_FAILURE); + goto err; + } + + rv = pflist->C_Initialize((CK_VOID_PTR)&pk11_init_args); + if ((rv != CKR_OK) && (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)) + { + PK11err_add_data(PK11_F_CHECK_HW_MECHANISMS, + PK11_R_INITIALIZE, rv); + goto err; + } + + if (pflist->C_GetSlotList(0, NULL_PTR, &ulSlotCount) != CKR_OK) + { + PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_GETSLOTLIST); + goto err; + } + + /* no slots, set the hw mechanism tables as empty */ + if (ulSlotCount == 0) + { +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: no hardware mechanisms found\n", PK11_DBG); +#endif + hw_cnids = OPENSSL_malloc(sizeof (int)); + hw_dnids = OPENSSL_malloc(sizeof (int)); + if (hw_cnids == NULL || hw_dnids == NULL) + { + PK11err(PK11_F_CHECK_HW_MECHANISMS, + PK11_R_MALLOC_FAILURE); + return (0); + } + /* this means empty tables */ + hw_cnids[0] = NID_undef; + hw_dnids[0] = NID_undef; + return (1); + } + + pSlotList = OPENSSL_malloc(ulSlotCount * sizeof (CK_SLOT_ID)); + if (pSlotList == NULL) + { + PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_MALLOC_FAILURE); + goto err; + } + + /* Get the slot list for processing */ + if (pflist->C_GetSlotList(0, pSlotList, &ulSlotCount) != CKR_OK) + { + PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_GETSLOTLIST); + goto err; + } + + /* + * We don't care about duplicit mechanisms in multiple slots and also + * reserve one slot for the terminal NID_undef which we use to stop the + * search. + */ + hw_ctable_size = ulSlotCount * PK11_CIPHER_MAX + 1; + hw_dtable_size = ulSlotCount * PK11_DIGEST_MAX + 1; + tmp_hw_cnids = OPENSSL_malloc(hw_ctable_size * sizeof (int)); + tmp_hw_dnids = OPENSSL_malloc(hw_dtable_size * sizeof (int)); + if (tmp_hw_cnids == NULL || tmp_hw_dnids == NULL) + { + PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_MALLOC_FAILURE); + goto err; + } + + /* + * Do not use memset since we should not rely on the fact that NID_undef + * is zero now. + */ + for (i = 0; i < hw_ctable_size; ++i) + tmp_hw_cnids[i] = NID_undef; + for (i = 0; i < hw_dtable_size; ++i) + tmp_hw_dnids[i] = NID_undef; + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: provider: %s\n", PK11_DBG, pkcs11_kernel); + fprintf(stderr, "%s: found %d hardware slots\n", PK11_DBG, ulSlotCount); + fprintf(stderr, "%s: now looking for mechs supported in hw\n", + PK11_DBG); +#endif /* DEBUG_SLOT_SELECTION */ + + for (i = 0; i < ulSlotCount; i++) + { + if (pflist->C_GetTokenInfo(pSlotList[i], &token_info) != CKR_OK) + continue; + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: token label: %.32s\n", PK11_DBG, token_info.label); +#endif /* DEBUG_SLOT_SELECTION */ + + /* + * We are filling the hw mech tables here. Global tables are + * still NULL so all mechanisms are put into tmp tables. + */ + pk11_find_symmetric_ciphers(pflist, pSlotList[i], + &n_cipher, tmp_hw_cnids); + pk11_find_digests(pflist, pSlotList[i], + &n_digest, tmp_hw_dnids); + } + + /* + * Since we are part of a library (libcrypto.so), calling this function + * may have side-effects. Also, C_Finalize() is triggered by + * dlclose(3C). + */ +#if 0 + pflist->C_Finalize(NULL); +#endif + OPENSSL_free(pSlotList); + (void) dlclose(handle); + hw_cnids = tmp_hw_cnids; + hw_dnids = tmp_hw_dnids; + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: hw mechs check complete\n", PK11_DBG); +#endif /* DEBUG_SLOT_SELECTION */ + return (1); + +err: + if (pSlotList != NULL) + OPENSSL_free(pSlotList); + if (tmp_hw_cnids != NULL) + OPENSSL_free(tmp_hw_cnids); + if (tmp_hw_dnids != NULL) + OPENSSL_free(tmp_hw_dnids); + + return (0); + } + +/* + * Check presence of a NID in the table of NIDs. The table may be NULL (i.e., + * non-existent). + */ +static int nid_in_table(int nid, int *nid_table) + { + int i = 0; + + /* + * a special case. NULL means that we are initializing a new + * table. + */ + if (nid_table == NULL) + return (1); + + /* + * the table is never full, there is always at least one + * NID_undef. + */ + while (nid_table[i] != NID_undef) + { + if (nid_table[i++] == nid) + { +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, " (NID %d in hw table, idx %d)", nid, i); +#endif /* DEBUG_SLOT_SELECTION */ + return (1); + } + } + + return (0); + } +#endif /* SOLARIS_HW_SLOT_SELECTION */ + +#endif /* OPENSSL_NO_HW_PK11CA */ +#endif /* OPENSSL_NO_HW_PK11 */ +#endif /* OPENSSL_NO_HW */ Index: openssl/crypto/engine/hw_pk11_err.c diff -u /dev/null openssl/crypto/engine/hw_pk11_err.c:1.5 --- /dev/null Mon Jun 13 15:26:29 2016 +++ openssl/crypto/engine/hw_pk11_err.c Tue Jun 14 00:43:26 2011 @@ -0,0 +1,288 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* crypto/engine/hw_pk11_err.c */ +/* + * This product includes software developed by the OpenSSL Project for + * use in the OpenSSL Toolkit (http://www.openssl.org/). + * + * This project also referenced hw_pkcs11-0.9.7b.patch written by + * Afchine Madjlessi. + */ +/* + * ==================================================================== + * Copyright (c) 2000-2001 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include +#include +#include "hw_pk11_err.h" + +/* BEGIN ERROR CODES */ +#ifndef OPENSSL_NO_ERR +static ERR_STRING_DATA pk11_str_functs[]= +{ +{ ERR_PACK(0, PK11_F_INIT, 0), "PK11_INIT"}, +{ ERR_PACK(0, PK11_F_FINISH, 0), "PK11_FINISH"}, +{ ERR_PACK(0, PK11_F_DESTROY, 0), "PK11_DESTROY"}, +{ ERR_PACK(0, PK11_F_CTRL, 0), "PK11_CTRL"}, +{ ERR_PACK(0, PK11_F_RSA_INIT, 0), "PK11_RSA_INIT"}, +{ ERR_PACK(0, PK11_F_RSA_FINISH, 0), "PK11_RSA_FINISH"}, +{ ERR_PACK(0, PK11_F_GET_PUB_RSA_KEY, 0), "PK11_GET_PUB_RSA_KEY"}, +{ ERR_PACK(0, PK11_F_GET_PRIV_RSA_KEY, 0), "PK11_GET_PRIV_RSA_KEY"}, +{ ERR_PACK(0, PK11_F_RSA_GEN_KEY, 0), "PK11_RSA_GEN_KEY"}, +{ ERR_PACK(0, PK11_F_RSA_PUB_ENC, 0), "PK11_RSA_PUB_ENC"}, +{ ERR_PACK(0, PK11_F_RSA_PRIV_ENC, 0), "PK11_RSA_PRIV_ENC"}, +{ ERR_PACK(0, PK11_F_RSA_PUB_DEC, 0), "PK11_RSA_PUB_DEC"}, +{ ERR_PACK(0, PK11_F_RSA_PRIV_DEC, 0), "PK11_RSA_PRIV_DEC"}, +{ ERR_PACK(0, PK11_F_RSA_SIGN, 0), "PK11_RSA_SIGN"}, +{ ERR_PACK(0, PK11_F_RSA_VERIFY, 0), "PK11_RSA_VERIFY"}, +{ ERR_PACK(0, PK11_F_RAND_ADD, 0), "PK11_RAND_ADD"}, +{ ERR_PACK(0, PK11_F_RAND_BYTES, 0), "PK11_RAND_BYTES"}, +{ ERR_PACK(0, PK11_F_GET_SESSION, 0), "PK11_GET_SESSION"}, +{ ERR_PACK(0, PK11_F_FREE_SESSION, 0), "PK11_FREE_SESSION"}, +{ ERR_PACK(0, PK11_F_LOAD_PUBKEY, 0), "PK11_LOAD_PUBKEY"}, +{ ERR_PACK(0, PK11_F_LOAD_PRIVKEY, 0), "PK11_LOAD_PRIV_KEY"}, +{ ERR_PACK(0, PK11_F_RSA_PUB_ENC_LOW, 0), "PK11_RSA_PUB_ENC_LOW"}, +{ ERR_PACK(0, PK11_F_RSA_PRIV_ENC_LOW, 0), "PK11_RSA_PRIV_ENC_LOW"}, +{ ERR_PACK(0, PK11_F_RSA_PUB_DEC_LOW, 0), "PK11_RSA_PUB_DEC_LOW"}, +{ ERR_PACK(0, PK11_F_RSA_PRIV_DEC_LOW, 0), "PK11_RSA_PRIV_DEC_LOW"}, +{ ERR_PACK(0, PK11_F_DSA_SIGN, 0), "PK11_DSA_SIGN"}, +{ ERR_PACK(0, PK11_F_DSA_VERIFY, 0), "PK11_DSA_VERIFY"}, +{ ERR_PACK(0, PK11_F_DSA_INIT, 0), "PK11_DSA_INIT"}, +{ ERR_PACK(0, PK11_F_DSA_FINISH, 0), "PK11_DSA_FINISH"}, +{ ERR_PACK(0, PK11_F_GET_PUB_DSA_KEY, 0), "PK11_GET_PUB_DSA_KEY"}, +{ ERR_PACK(0, PK11_F_GET_PRIV_DSA_KEY, 0), "PK11_GET_PRIV_DSA_KEY"}, +{ ERR_PACK(0, PK11_F_DH_INIT, 0), "PK11_DH_INIT"}, +{ ERR_PACK(0, PK11_F_DH_FINISH, 0), "PK11_DH_FINISH"}, +{ ERR_PACK(0, PK11_F_MOD_EXP_DH, 0), "PK11_MOD_EXP_DH"}, +{ ERR_PACK(0, PK11_F_GET_DH_KEY, 0), "PK11_GET_DH_KEY"}, +{ ERR_PACK(0, PK11_F_FREE_ALL_SESSIONS, 0), "PK11_FREE_ALL_SESSIONS"}, +{ ERR_PACK(0, PK11_F_SETUP_SESSION, 0), "PK11_SETUP_SESSION"}, +{ ERR_PACK(0, PK11_F_DESTROY_OBJECT, 0), "PK11_DESTROY_OBJECT"}, +{ ERR_PACK(0, PK11_F_CIPHER_INIT, 0), "PK11_CIPHER_INIT"}, +{ ERR_PACK(0, PK11_F_CIPHER_DO_CIPHER, 0), "PK11_CIPHER_DO_CIPHER"}, +{ ERR_PACK(0, PK11_F_GET_CIPHER_KEY, 0), "PK11_GET_CIPHER_KEY"}, +{ ERR_PACK(0, PK11_F_DIGEST_INIT, 0), "PK11_DIGEST_INIT"}, +{ ERR_PACK(0, PK11_F_DIGEST_UPDATE, 0), "PK11_DIGEST_UPDATE"}, +{ ERR_PACK(0, PK11_F_DIGEST_FINAL, 0), "PK11_DIGEST_FINAL"}, +{ ERR_PACK(0, PK11_F_CHOOSE_SLOT, 0), "PK11_CHOOSE_SLOT"}, +{ ERR_PACK(0, PK11_F_CIPHER_FINAL, 0), "PK11_CIPHER_FINAL"}, +{ ERR_PACK(0, PK11_F_LIBRARY_INIT, 0), "PK11_LIBRARY_INIT"}, +{ ERR_PACK(0, PK11_F_LOAD, 0), "ENGINE_LOAD_PK11"}, +{ ERR_PACK(0, PK11_F_DH_GEN_KEY, 0), "PK11_DH_GEN_KEY"}, +{ ERR_PACK(0, PK11_F_DH_COMP_KEY, 0), "PK11_DH_COMP_KEY"}, +{ ERR_PACK(0, PK11_F_DIGEST_COPY, 0), "PK11_DIGEST_COPY"}, +{ ERR_PACK(0, PK11_F_CIPHER_CLEANUP, 0), "PK11_CIPHER_CLEANUP"}, +{ ERR_PACK(0, PK11_F_ACTIVE_ADD, 0), "PK11_ACTIVE_ADD"}, +{ ERR_PACK(0, PK11_F_ACTIVE_DELETE, 0), "PK11_ACTIVE_DELETE"}, +{ ERR_PACK(0, PK11_F_CHECK_HW_MECHANISMS, 0), "PK11_CHECK_HW_MECHANISMS"}, +{ ERR_PACK(0, PK11_F_INIT_SYMMETRIC, 0), "PK11_INIT_SYMMETRIC"}, +{ ERR_PACK(0, PK11_F_ADD_AES_CTR_NIDS, 0), "PK11_ADD_AES_CTR_NIDS"}, +{ ERR_PACK(0, PK11_F_INIT_ALL_LOCKS, 0), "PK11_INIT_ALL_LOCKS"}, +{ ERR_PACK(0, PK11_F_RETURN_SESSION, 0), "PK11_RETURN_SESSION"}, +{ ERR_PACK(0, PK11_F_GET_PIN, 0), "PK11_GET_PIN"}, +{ ERR_PACK(0, PK11_F_FIND_ONE_OBJECT, 0), "PK11_FIND_ONE_OBJECT"}, +{ ERR_PACK(0, PK11_F_CHECK_TOKEN_ATTRS, 0), "PK11_CHECK_TOKEN_ATTRS"}, +{ ERR_PACK(0, PK11_F_CACHE_PIN, 0), "PK11_CACHE_PIN"}, +{ ERR_PACK(0, PK11_F_MLOCK_PIN_IN_MEMORY, 0), "PK11_MLOCK_PIN_IN_MEMORY"}, +{ ERR_PACK(0, PK11_F_TOKEN_LOGIN, 0), "PK11_TOKEN_LOGIN"}, +{ ERR_PACK(0, PK11_F_TOKEN_RELOGIN, 0), "PK11_TOKEN_RELOGIN"}, +{ ERR_PACK(0, PK11_F_RUN_ASKPASS, 0), "PK11_F_RUN_ASKPASS"}, +{ 0, NULL} +}; + +static ERR_STRING_DATA pk11_str_reasons[]= +{ +{ PK11_R_ALREADY_LOADED, "PKCS#11 DSO already loaded"}, +{ PK11_R_DSO_FAILURE, "unable to load PKCS#11 DSO"}, +{ PK11_R_NOT_LOADED, "PKCS#11 DSO not loaded"}, +{ PK11_R_PASSED_NULL_PARAMETER, "null parameter passed"}, +{ PK11_R_COMMAND_NOT_IMPLEMENTED, "command not implemented"}, +{ PK11_R_INITIALIZE, "C_Initialize failed"}, +{ PK11_R_FINALIZE, "C_Finalize failed"}, +{ PK11_R_GETINFO, "C_GetInfo faile"}, +{ PK11_R_GETSLOTLIST, "C_GetSlotList failed"}, +{ PK11_R_NO_MODULUS_OR_NO_EXPONENT, "no modulus or no exponent"}, +{ PK11_R_ATTRIBUT_SENSITIVE_OR_INVALID, "attr sensitive or invalid"}, +{ PK11_R_GETATTRIBUTVALUE, "C_GetAttributeValue failed"}, +{ PK11_R_NO_MODULUS, "no modulus"}, +{ PK11_R_NO_EXPONENT, "no exponent"}, +{ PK11_R_FINDOBJECTSINIT, "C_FindObjectsInit failed"}, +{ PK11_R_FINDOBJECTS, "C_FindObjects failed"}, +{ PK11_R_FINDOBJECTSFINAL, "C_FindObjectsFinal failed"}, +{ PK11_R_CREATEOBJECT, "C_CreateObject failed"}, +{ PK11_R_DESTROYOBJECT, "C_DestroyObject failed"}, +{ PK11_R_OPENSESSION, "C_OpenSession failed"}, +{ PK11_R_CLOSESESSION, "C_CloseSession failed"}, +{ PK11_R_ENCRYPTINIT, "C_EncryptInit failed"}, +{ PK11_R_ENCRYPT, "C_Encrypt failed"}, +{ PK11_R_SIGNINIT, "C_SignInit failed"}, +{ PK11_R_SIGN, "C_Sign failed"}, +{ PK11_R_DECRYPTINIT, "C_DecryptInit failed"}, +{ PK11_R_DECRYPT, "C_Decrypt failed"}, +{ PK11_R_VERIFYINIT, "C_VerifyRecover failed"}, +{ PK11_R_VERIFY, "C_Verify failed"}, +{ PK11_R_VERIFYRECOVERINIT, "C_VerifyRecoverInit failed"}, +{ PK11_R_VERIFYRECOVER, "C_VerifyRecover failed"}, +{ PK11_R_GEN_KEY, "C_GenerateKeyPair failed"}, +{ PK11_R_SEEDRANDOM, "C_SeedRandom failed"}, +{ PK11_R_GENERATERANDOM, "C_GenerateRandom failed"}, +{ PK11_R_INVALID_MESSAGE_LENGTH, "invalid message length"}, +{ PK11_R_UNKNOWN_ALGORITHM_TYPE, "unknown algorithm type"}, +{ PK11_R_UNKNOWN_ASN1_OBJECT_ID, "unknown asn1 onject id"}, +{ PK11_R_UNKNOWN_PADDING_TYPE, "unknown padding type"}, +{ PK11_R_PADDING_CHECK_FAILED, "padding check failed"}, +{ PK11_R_DIGEST_TOO_BIG, "digest too big"}, +{ PK11_R_MALLOC_FAILURE, "malloc failure"}, +{ PK11_R_CTRL_COMMAND_NOT_IMPLEMENTED, "ctl command not implemented"}, +{ PK11_R_DATA_GREATER_THAN_MOD_LEN, "data is bigger than mod"}, +{ PK11_R_DATA_TOO_LARGE_FOR_MODULUS, "data is too larger for mod"}, +{ PK11_R_MISSING_KEY_COMPONENT, "a dsa component is missing"}, +{ PK11_R_INVALID_SIGNATURE_LENGTH, "invalid signature length"}, +{ PK11_R_INVALID_DSA_SIGNATURE_R, "missing r in dsa verify"}, +{ PK11_R_INVALID_DSA_SIGNATURE_S, "missing s in dsa verify"}, +{ PK11_R_INCONSISTENT_KEY, "inconsistent key type"}, +{ PK11_R_ENCRYPTUPDATE, "C_EncryptUpdate failed"}, +{ PK11_R_DECRYPTUPDATE, "C_DecryptUpdate failed"}, +{ PK11_R_DIGESTINIT, "C_DigestInit failed"}, +{ PK11_R_DIGESTUPDATE, "C_DigestUpdate failed"}, +{ PK11_R_DIGESTFINAL, "C_DigestFinal failed"}, +{ PK11_R_ENCRYPTFINAL, "C_EncryptFinal failed"}, +{ PK11_R_DECRYPTFINAL, "C_DecryptFinal failed"}, +{ PK11_R_NO_PRNG_SUPPORT, "Slot does not support PRNG"}, +{ PK11_R_GETTOKENINFO, "C_GetTokenInfo failed"}, +{ PK11_R_DERIVEKEY, "C_DeriveKey failed"}, +{ PK11_R_GET_OPERATION_STATE, "C_GetOperationState failed"}, +{ PK11_R_SET_OPERATION_STATE, "C_SetOperationState failed"}, +{ PK11_R_INVALID_HANDLE, "invalid PKCS#11 object handle"}, +{ PK11_R_KEY_OR_IV_LEN_PROBLEM, "IV or key length incorrect"}, +{ PK11_R_INVALID_OPERATION_TYPE, "invalid operation type"}, +{ PK11_R_ADD_NID_FAILED, "failed to add NID" }, +{ PK11_R_ATFORK_FAILED, "atfork() failed" }, +{ PK11_R_TOKEN_LOGIN_FAILED, "C_Login() failed on token" }, +{ PK11_R_MORE_THAN_ONE_OBJECT_FOUND, "more than one object found" }, +{ PK11_R_INVALID_PKCS11_URI, "pkcs11 URI provided is invalid" }, +{ PK11_R_COULD_NOT_READ_PIN, "could not read PIN from terminal" }, +{ PK11_R_PIN_NOT_READ_FROM_COMMAND, "PIN not read from external command" }, +{ PK11_R_COULD_NOT_OPEN_COMMAND, "could not popen() dialog command" }, +{ PK11_R_PIPE_FAILED, "pipe() failed" }, +{ PK11_R_BAD_PASSPHRASE_SPEC, "bad passphrasedialog specification" }, +{ PK11_R_TOKEN_NOT_INITIALIZED, "token not initialized" }, +{ PK11_R_TOKEN_PIN_NOT_SET, "token PIN required but not set" }, +{ PK11_R_TOKEN_PIN_NOT_PROVIDED, "token PIN required but not provided" }, +{ PK11_R_MISSING_OBJECT_LABEL, "missing mandatory 'object' keyword" }, +{ PK11_R_TOKEN_ATTRS_DO_NOT_MATCH, "token attrs provided do not match" }, +{ PK11_R_PRIV_KEY_NOT_FOUND, "private key not found in keystore" }, +{ PK11_R_NO_OBJECT_FOUND, "specified object not found" }, +{ PK11_R_PIN_CACHING_POLICY_INVALID, "PIN set but caching policy invalid" }, +{ PK11_R_SYSCONF_FAILED, "sysconf() failed" }, +{ PK11_R_MMAP_FAILED, "mmap() failed" }, +{ PK11_R_PRIV_PROC_LOCK_MEMORY_MISSING, "PROC_LOCK_MEMORY privilege missing" }, +{ PK11_R_MLOCK_FAILED, "mlock() failed" }, +{ PK11_R_FORK_FAILED, "fork() failed" }, +{ 0, NULL} +}; +#endif /* OPENSSL_NO_ERR */ + +static int pk11_lib_error_code = 0; +static int pk11_error_init = 1; + +static void +ERR_load_pk11_strings(void) + { + if (pk11_lib_error_code == 0) + pk11_lib_error_code = ERR_get_next_error_library(); + + if (pk11_error_init) + { + pk11_error_init = 0; +#ifndef OPENSSL_NO_ERR + ERR_load_strings(pk11_lib_error_code, pk11_str_functs); + ERR_load_strings(pk11_lib_error_code, pk11_str_reasons); +#endif + } +} + +static void +ERR_unload_pk11_strings(void) + { + if (pk11_error_init == 0) + { +#ifndef OPENSSL_NO_ERR + ERR_unload_strings(pk11_lib_error_code, pk11_str_functs); + ERR_unload_strings(pk11_lib_error_code, pk11_str_reasons); +#endif + pk11_error_init = 1; + } +} + +void +ERR_pk11_error(int function, int reason, char *file, int line) +{ + if (pk11_lib_error_code == 0) + pk11_lib_error_code = ERR_get_next_error_library(); + ERR_PUT_error(pk11_lib_error_code, function, reason, file, line); +} + +void +PK11err_add_data(int function, int reason, CK_RV rv) +{ + char tmp_buf[20]; + + PK11err(function, reason); + (void) BIO_snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); + ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); +} Index: openssl/crypto/engine/hw_pk11_err.h diff -u /dev/null openssl/crypto/engine/hw_pk11_err.h:1.13 --- /dev/null Mon Jun 13 15:26:29 2016 +++ openssl/crypto/engine/hw_pk11_err.h Fri Oct 4 14:04:20 2013 @@ -0,0 +1,440 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * This product includes software developed by the OpenSSL Project for + * use in the OpenSSL Toolkit (http://www.openssl.org/). + * + * This project also referenced hw_pkcs11-0.9.7b.patch written by + * Afchine Madjlessi. + */ +/* + * ==================================================================== + * Copyright (c) 2000-2001 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#ifndef HW_PK11_ERR_H +#define HW_PK11_ERR_H + +void ERR_pk11_error(int function, int reason, char *file, int line); +void PK11err_add_data(int function, int reason, CK_RV rv); +#define PK11err(f, r) ERR_pk11_error((f), (r), __FILE__, __LINE__) + +/* Error codes for the PK11 functions. */ + +/* Function codes. */ + +#define PK11_F_INIT 100 +#define PK11_F_FINISH 101 +#define PK11_F_DESTROY 102 +#define PK11_F_CTRL 103 +#define PK11_F_RSA_INIT 104 +#define PK11_F_RSA_FINISH 105 +#define PK11_F_GET_PUB_RSA_KEY 106 +#define PK11_F_GET_PRIV_RSA_KEY 107 +#define PK11_F_RSA_GEN_KEY 108 +#define PK11_F_RSA_PUB_ENC 109 +#define PK11_F_RSA_PRIV_ENC 110 +#define PK11_F_RSA_PUB_DEC 111 +#define PK11_F_RSA_PRIV_DEC 112 +#define PK11_F_RSA_SIGN 113 +#define PK11_F_RSA_VERIFY 114 +#define PK11_F_RAND_ADD 115 +#define PK11_F_RAND_BYTES 116 +#define PK11_F_GET_SESSION 117 +#define PK11_F_FREE_SESSION 118 +#define PK11_F_LOAD_PUBKEY 119 +#define PK11_F_LOAD_PRIVKEY 120 +#define PK11_F_RSA_PUB_ENC_LOW 121 +#define PK11_F_RSA_PRIV_ENC_LOW 122 +#define PK11_F_RSA_PUB_DEC_LOW 123 +#define PK11_F_RSA_PRIV_DEC_LOW 124 +#define PK11_F_DSA_SIGN 125 +#define PK11_F_DSA_VERIFY 126 +#define PK11_F_DSA_INIT 127 +#define PK11_F_DSA_FINISH 128 +#define PK11_F_GET_PUB_DSA_KEY 129 +#define PK11_F_GET_PRIV_DSA_KEY 130 +#define PK11_F_DH_INIT 131 +#define PK11_F_DH_FINISH 132 +#define PK11_F_MOD_EXP_DH 133 +#define PK11_F_GET_DH_KEY 134 +#define PK11_F_FREE_ALL_SESSIONS 135 +#define PK11_F_SETUP_SESSION 136 +#define PK11_F_DESTROY_OBJECT 137 +#define PK11_F_CIPHER_INIT 138 +#define PK11_F_CIPHER_DO_CIPHER 139 +#define PK11_F_GET_CIPHER_KEY 140 +#define PK11_F_DIGEST_INIT 141 +#define PK11_F_DIGEST_UPDATE 142 +#define PK11_F_DIGEST_FINAL 143 +#define PK11_F_CHOOSE_SLOT 144 +#define PK11_F_CIPHER_FINAL 145 +#define PK11_F_LIBRARY_INIT 146 +#define PK11_F_LOAD 147 +#define PK11_F_DH_GEN_KEY 148 +#define PK11_F_DH_COMP_KEY 149 +#define PK11_F_DIGEST_COPY 150 +#define PK11_F_CIPHER_CLEANUP 151 +#define PK11_F_ACTIVE_ADD 152 +#define PK11_F_ACTIVE_DELETE 153 +#define PK11_F_CHECK_HW_MECHANISMS 154 +#define PK11_F_INIT_SYMMETRIC 155 +#define PK11_F_ADD_AES_CTR_NIDS 156 +#define PK11_F_INIT_ALL_LOCKS 157 +#define PK11_F_RETURN_SESSION 158 +#define PK11_F_GET_PIN 159 +#define PK11_F_FIND_ONE_OBJECT 160 +#define PK11_F_CHECK_TOKEN_ATTRS 161 +#define PK11_F_CACHE_PIN 162 +#define PK11_F_MLOCK_PIN_IN_MEMORY 163 +#define PK11_F_TOKEN_LOGIN 164 +#define PK11_F_TOKEN_RELOGIN 165 +#define PK11_F_RUN_ASKPASS 166 + +/* Reason codes. */ +#define PK11_R_ALREADY_LOADED 100 +#define PK11_R_DSO_FAILURE 101 +#define PK11_R_NOT_LOADED 102 +#define PK11_R_PASSED_NULL_PARAMETER 103 +#define PK11_R_COMMAND_NOT_IMPLEMENTED 104 +#define PK11_R_INITIALIZE 105 +#define PK11_R_FINALIZE 106 +#define PK11_R_GETINFO 107 +#define PK11_R_GETSLOTLIST 108 +#define PK11_R_NO_MODULUS_OR_NO_EXPONENT 109 +#define PK11_R_ATTRIBUT_SENSITIVE_OR_INVALID 110 +#define PK11_R_GETATTRIBUTVALUE 111 +#define PK11_R_NO_MODULUS 112 +#define PK11_R_NO_EXPONENT 113 +#define PK11_R_FINDOBJECTSINIT 114 +#define PK11_R_FINDOBJECTS 115 +#define PK11_R_FINDOBJECTSFINAL 116 +#define PK11_R_CREATEOBJECT 118 +#define PK11_R_DESTROYOBJECT 119 +#define PK11_R_OPENSESSION 120 +#define PK11_R_CLOSESESSION 121 +#define PK11_R_ENCRYPTINIT 122 +#define PK11_R_ENCRYPT 123 +#define PK11_R_SIGNINIT 124 +#define PK11_R_SIGN 125 +#define PK11_R_DECRYPTINIT 126 +#define PK11_R_DECRYPT 127 +#define PK11_R_VERIFYINIT 128 +#define PK11_R_VERIFY 129 +#define PK11_R_VERIFYRECOVERINIT 130 +#define PK11_R_VERIFYRECOVER 131 +#define PK11_R_GEN_KEY 132 +#define PK11_R_SEEDRANDOM 133 +#define PK11_R_GENERATERANDOM 134 +#define PK11_R_INVALID_MESSAGE_LENGTH 135 +#define PK11_R_UNKNOWN_ALGORITHM_TYPE 136 +#define PK11_R_UNKNOWN_ASN1_OBJECT_ID 137 +#define PK11_R_UNKNOWN_PADDING_TYPE 138 +#define PK11_R_PADDING_CHECK_FAILED 139 +#define PK11_R_DIGEST_TOO_BIG 140 +#define PK11_R_MALLOC_FAILURE 141 +#define PK11_R_CTRL_COMMAND_NOT_IMPLEMENTED 142 +#define PK11_R_DATA_GREATER_THAN_MOD_LEN 143 +#define PK11_R_DATA_TOO_LARGE_FOR_MODULUS 144 +#define PK11_R_MISSING_KEY_COMPONENT 145 +#define PK11_R_INVALID_SIGNATURE_LENGTH 146 +#define PK11_R_INVALID_DSA_SIGNATURE_R 147 +#define PK11_R_INVALID_DSA_SIGNATURE_S 148 +#define PK11_R_INCONSISTENT_KEY 149 +#define PK11_R_ENCRYPTUPDATE 150 +#define PK11_R_DECRYPTUPDATE 151 +#define PK11_R_DIGESTINIT 152 +#define PK11_R_DIGESTUPDATE 153 +#define PK11_R_DIGESTFINAL 154 +#define PK11_R_ENCRYPTFINAL 155 +#define PK11_R_DECRYPTFINAL 156 +#define PK11_R_NO_PRNG_SUPPORT 157 +#define PK11_R_GETTOKENINFO 158 +#define PK11_R_DERIVEKEY 159 +#define PK11_R_GET_OPERATION_STATE 160 +#define PK11_R_SET_OPERATION_STATE 161 +#define PK11_R_INVALID_HANDLE 162 +#define PK11_R_KEY_OR_IV_LEN_PROBLEM 163 +#define PK11_R_INVALID_OPERATION_TYPE 164 +#define PK11_R_ADD_NID_FAILED 165 +#define PK11_R_ATFORK_FAILED 166 + +#define PK11_R_TOKEN_LOGIN_FAILED 167 +#define PK11_R_MORE_THAN_ONE_OBJECT_FOUND 168 +#define PK11_R_INVALID_PKCS11_URI 169 +#define PK11_R_COULD_NOT_READ_PIN 170 +#define PK11_R_COULD_NOT_OPEN_COMMAND 171 +#define PK11_R_PIPE_FAILED 172 +#define PK11_R_PIN_NOT_READ_FROM_COMMAND 173 +#define PK11_R_BAD_PASSPHRASE_SPEC 174 +#define PK11_R_TOKEN_NOT_INITIALIZED 175 +#define PK11_R_TOKEN_PIN_NOT_SET 176 +#define PK11_R_TOKEN_PIN_NOT_PROVIDED 177 +#define PK11_R_MISSING_OBJECT_LABEL 178 +#define PK11_R_TOKEN_ATTRS_DO_NOT_MATCH 179 +#define PK11_R_PRIV_KEY_NOT_FOUND 180 +#define PK11_R_NO_OBJECT_FOUND 181 +#define PK11_R_PIN_CACHING_POLICY_INVALID 182 +#define PK11_R_SYSCONF_FAILED 183 +#define PK11_R_MMAP_FAILED 183 +#define PK11_R_PRIV_PROC_LOCK_MEMORY_MISSING 184 +#define PK11_R_MLOCK_FAILED 185 +#define PK11_R_FORK_FAILED 186 + +/* max byte length of a symetric key we support */ +#define PK11_KEY_LEN_MAX 32 + +#ifdef NOPTHREADS +/* + * CRYPTO_LOCK_PK11_ENGINE lock is primarily used for the protection of the + * free_session list and active_list but generally serves as a global + * per-process lock for the whole engine. + * + * We reuse CRYPTO_LOCK_EC lock (which is defined in OpenSSL for EC method) as + * the global engine lock. This is not optimal w.r.t. performance but + * it's safe. + */ +#define CRYPTO_LOCK_PK11_ENGINE CRYPTO_LOCK_EC +#endif + +/* + * This structure encapsulates all reusable information for a PKCS#11 + * session. A list of these objects is created on behalf of the + * calling application using an on-demand method. Each operation + * type (see PK11_OPTYPE below) has its own per-process list. + * Each of the lists is basically a cache for faster PKCS#11 object + * access to avoid expensive C_Find{,Init,Final}Object() calls. + * + * When a new request comes in, an object will be taken from the list + * (if there is one) or a new one is created to handle the request + * (if the list is empty). See pk11_get_session() on how it is done. + */ +typedef struct PK11_st_SESSION + { + struct PK11_st_SESSION *next; + CK_SESSION_HANDLE session; /* PK11 session handle */ + pid_t pid; /* Current process ID */ + CK_BBOOL pub_persistent; /* is pub key in keystore? */ + CK_BBOOL priv_persistent;/* is priv key in keystore? */ + union + { +#ifndef OPENSSL_NO_RSA + struct + { + CK_OBJECT_HANDLE rsa_pub_key; /* pub handle */ + CK_OBJECT_HANDLE rsa_priv_key; /* priv handle */ + RSA *rsa_pub; /* pub key addr */ + BIGNUM *rsa_n_num; /* pub modulus */ + BIGNUM *rsa_e_num; /* pub exponent */ + RSA *rsa_priv; /* priv key addr */ + BIGNUM *rsa_pn_num; /* pub modulus */ + BIGNUM *rsa_pe_num; /* pub exponent */ + BIGNUM *rsa_d_num; /* priv exponent */ + } u_RSA; +#endif /* OPENSSL_NO_RSA */ +#ifndef OPENSSL_NO_DSA + struct + { + CK_OBJECT_HANDLE dsa_pub_key; /* pub handle */ + CK_OBJECT_HANDLE dsa_priv_key; /* priv handle */ + DSA *dsa_pub; /* pub key addr */ + BIGNUM *dsa_pub_num; /* pub key */ + DSA *dsa_priv; /* priv key addr */ + BIGNUM *dsa_priv_num; /* priv key */ + } u_DSA; +#endif /* OPENSSL_NO_DSA */ +#ifndef OPENSSL_NO_DH + struct + { + CK_OBJECT_HANDLE dh_key; /* key handle */ + DH *dh; /* dh key addr */ + BIGNUM *dh_priv_num; /* priv dh key */ + } u_DH; +#endif /* OPENSSL_NO_DH */ + struct + { + CK_OBJECT_HANDLE cipher_key; /* key handle */ + unsigned char key[PK11_KEY_LEN_MAX]; + int key_len; /* priv key len */ + int encrypt; /* 1/0 enc/decr */ + } u_cipher; + } opdata_u; + } PK11_SESSION; + +#define opdata_rsa_pub_key opdata_u.u_RSA.rsa_pub_key +#define opdata_rsa_priv_key opdata_u.u_RSA.rsa_priv_key +#define opdata_rsa_pub opdata_u.u_RSA.rsa_pub +#define opdata_rsa_priv opdata_u.u_RSA.rsa_priv +#define opdata_rsa_n_num opdata_u.u_RSA.rsa_n_num +#define opdata_rsa_e_num opdata_u.u_RSA.rsa_e_num +#define opdata_rsa_pn_num opdata_u.u_RSA.rsa_pn_num +#define opdata_rsa_pe_num opdata_u.u_RSA.rsa_pe_num +#define opdata_rsa_d_num opdata_u.u_RSA.rsa_d_num +#define opdata_dsa_pub_key opdata_u.u_DSA.dsa_pub_key +#define opdata_dsa_priv_key opdata_u.u_DSA.dsa_priv_key +#define opdata_dsa_pub opdata_u.u_DSA.dsa_pub +#define opdata_dsa_pub_num opdata_u.u_DSA.dsa_pub_num +#define opdata_dsa_priv opdata_u.u_DSA.dsa_priv +#define opdata_dsa_priv_num opdata_u.u_DSA.dsa_priv_num +#define opdata_dh_key opdata_u.u_DH.dh_key +#define opdata_dh opdata_u.u_DH.dh +#define opdata_dh_priv_num opdata_u.u_DH.dh_priv_num +#define opdata_cipher_key opdata_u.u_cipher.cipher_key +#define opdata_key opdata_u.u_cipher.key +#define opdata_key_len opdata_u.u_cipher.key_len +#define opdata_encrypt opdata_u.u_cipher.encrypt + +/* + * We have 3 different groups of operation types: + * 1) asymmetric operations + * 2) random operations + * 3) symmetric and digest operations + * + * This division into groups stems from the fact that it's common that hardware + * providers may support operations from one group only. For example, hardware + * providers on UltraSPARC T2, n2rng(7d), ncp(7d), and n2cp(7d), each support + * only a single group of operations. + * + * For every group a different slot can be chosen. That means that we must have + * at least 3 different lists of cached PKCS#11 sessions since sessions from + * different groups may be initialized in different slots. + * + * To provide locking granularity in multithreaded environment, the groups are + * further splitted into types with each type having a separate session cache. + */ +typedef enum PK11_OPTYPE_ENUM + { + OP_RAND, + OP_RSA, + OP_DSA, + OP_DH, + OP_CIPHER, + OP_DIGEST, + OP_MAX + } PK11_OPTYPE; + +/* + * This structure contains the heads of the lists forming the object caches + * and locks associated with the lists. + */ +typedef struct PK11_st_CACHE + { + PK11_SESSION *head; +#ifndef NOPTHREADS + pthread_mutex_t *lock; +#endif + } PK11_CACHE; + +/* structure for tracking handles of asymmetric key objects */ +typedef struct PK11_active_st + { + CK_OBJECT_HANDLE h; + unsigned int refcnt; + struct PK11_active_st *prev; + struct PK11_active_st *next; + } PK11_active; + +#ifndef NOPTHREADS +extern pthread_mutex_t *find_lock[]; +#endif +extern PK11_active *active_list[]; +/* + * These variables are specific for the RSA keys by reference code. See + * hw_pk11_pub.c for explanation. + */ +extern CK_FLAGS pubkey_token_flags; + +#ifndef NOPTHREADS +#define LOCK_OBJSTORE(alg_type) \ + OPENSSL_assert(pthread_mutex_lock(find_lock[alg_type]) == 0) +#define UNLOCK_OBJSTORE(alg_type) \ + OPENSSL_assert(pthread_mutex_unlock(find_lock[alg_type]) == 0) +#else +#define LOCK_OBJSTORE(alg_type) \ + CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE) +#define UNLOCK_OBJSTORE(alg_type) \ + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE) +#endif + +extern PK11_SESSION *pk11_get_session(PK11_OPTYPE optype); +extern void pk11_return_session(PK11_SESSION *sp, PK11_OPTYPE optype); +extern int pk11_token_relogin(CK_SESSION_HANDLE session); + +#ifndef OPENSSL_NO_RSA +extern int pk11_destroy_rsa_key_objects(PK11_SESSION *session); +extern int pk11_destroy_rsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock); +extern int pk11_destroy_rsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock); +extern EVP_PKEY *pk11_load_privkey(ENGINE *e, const char *pubkey_file, + UI_METHOD *ui_method, void *callback_data); +extern EVP_PKEY *pk11_load_pubkey(ENGINE *e, const char *pubkey_file, + UI_METHOD *ui_method, void *callback_data); +extern RSA_METHOD *PK11_RSA(void); +#endif /* OPENSSL_NO_RSA */ +#ifndef OPENSSL_NO_DSA +extern int pk11_destroy_dsa_key_objects(PK11_SESSION *session); +extern int pk11_destroy_dsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock); +extern int pk11_destroy_dsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock); +extern DSA_METHOD *PK11_DSA(void); +#endif /* OPENSSL_NO_DSA */ +#ifndef OPENSSL_NO_DH +extern int pk11_destroy_dh_key_objects(PK11_SESSION *session); +extern int pk11_destroy_dh_object(PK11_SESSION *sp, CK_BBOOL uselock); +extern DH_METHOD *PK11_DH(void); +#endif /* OPENSSL_NO_DH */ + +extern CK_FUNCTION_LIST_PTR pFuncList; + +#endif /* HW_PK11_ERR_H */ Index: openssl/crypto/engine/hw_pk11_pub.c diff -u /dev/null openssl/crypto/engine/hw_pk11_pub.c:1.42 --- /dev/null Mon Jun 13 15:26:30 2016 +++ openssl/crypto/engine/hw_pk11_pub.c Fri Oct 4 14:27:06 2013 @@ -0,0 +1,3556 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* crypto/engine/hw_pk11_pub.c */ +/* + * This product includes software developed by the OpenSSL Project for + * use in the OpenSSL Toolkit (http://www.openssl.org/). + * + * This project also referenced hw_pkcs11-0.9.7b.patch written by + * Afchine Madjlessi. + */ +/* + * ==================================================================== + * Copyright (c) 2000-2001 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#ifndef OPENSSL_NO_RSA +#include +#endif /* OPENSSL_NO_RSA */ +#ifndef OPENSSL_NO_DSA +#include +#endif /* OPENSSL_NO_DSA */ +#ifndef OPENSSL_NO_DH +#include +#endif /* OPENSSL_NO_DH */ +#include +#include +#include + +#ifdef OPENSSL_SYS_WIN32 +#define NOPTHREADS +typedef int pid_t; +#define HAVE_GETPASSPHRASE +static char *getpassphrase(const char *prompt); +#ifndef NULL_PTR +#define NULL_PTR NULL +#endif +#define CK_DEFINE_FUNCTION(returnType, name) \ + returnType __declspec(dllexport) name +#define CK_DECLARE_FUNCTION(returnType, name) \ + returnType __declspec(dllimport) name +#define CK_DECLARE_FUNCTION_POINTER(returnType, name) \ + returnType __declspec(dllimport) (* name) +#else +#include +#endif + +#ifndef NOPTHREADS +#include +#endif + +#ifndef OPENSSL_NO_HW +#ifndef OPENSSL_NO_HW_PK11 +#ifndef OPENSSL_NO_HW_PK11CA + +#ifdef OPENSSL_SYS_WIN32 +#pragma pack(push, cryptoki, 1) +#include "cryptoki.h" +#include "pkcs11.h" +#pragma pack(pop, cryptoki) +#else +#include "cryptoki.h" +#include "pkcs11.h" +#endif +#include "hw_pk11ca.h" +#include "hw_pk11_err.h" + +static CK_BBOOL pk11_login_done = CK_FALSE; +extern CK_SLOT_ID pubkey_SLOTID; +#ifndef NOPTHREADS +extern pthread_mutex_t *token_lock; +#endif + +#if !(defined(HAVE_GETPASSPHRASE) || (defined (__SVR4) && defined (__sun))) +#define getpassphrase(x) getpass(x) +#endif + +#ifndef OPENSSL_NO_RSA +/* RSA stuff */ +static int pk11_RSA_public_encrypt(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding); +static int pk11_RSA_private_encrypt(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding); +static int pk11_RSA_public_decrypt(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding); +static int pk11_RSA_private_decrypt(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding); +static int pk11_RSA_init(RSA *rsa); +static int pk11_RSA_finish(RSA *rsa); +static int pk11_RSA_sign(int type, const unsigned char *m, unsigned int m_len, + unsigned char *sigret, unsigned int *siglen, const RSA *rsa); +#if OPENSSL_VERSION_NUMBER < 0x10000000L +static int pk11_RSA_verify(int dtype, const unsigned char *m, + unsigned int m_len, unsigned char *sigbuf, unsigned int siglen, + const RSA *rsa); +#else +static int pk11_RSA_verify(int dtype, const unsigned char *m, + unsigned int m_len, const unsigned char *sigbuf, unsigned int siglen, + const RSA *rsa); +#endif +EVP_PKEY *pk11_load_privkey(ENGINE*, const char *privkey_file, + UI_METHOD *ui_method, void *callback_data); +EVP_PKEY *pk11_load_pubkey(ENGINE*, const char *pubkey_file, + UI_METHOD *ui_method, void *callback_data); + +static int pk11_RSA_public_encrypt_low(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa); +static int pk11_RSA_private_encrypt_low(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa); +static int pk11_RSA_public_decrypt_low(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa); +static int pk11_RSA_private_decrypt_low(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa); + +static CK_OBJECT_HANDLE pk11_get_public_rsa_key(RSA* rsa, RSA** key_ptr, + BIGNUM **rsa_n_num, BIGNUM **rsa_e_num, CK_SESSION_HANDLE session); +static CK_OBJECT_HANDLE pk11_get_private_rsa_key(RSA* rsa, RSA** key_ptr, + BIGNUM **rsa_d_num, BIGNUM **rsa_n_num, BIGNUM **rsa_e_num, + CK_SESSION_HANDLE session); + +static int check_new_rsa_key_pub(PK11_SESSION *sp, const RSA *rsa); +static int check_new_rsa_key_priv(PK11_SESSION *sp, const RSA *rsa); +#endif + +/* DSA stuff */ +#ifndef OPENSSL_NO_DSA +static int pk11_DSA_init(DSA *dsa); +static int pk11_DSA_finish(DSA *dsa); +static DSA_SIG *pk11_dsa_do_sign(const unsigned char *dgst, int dlen, + DSA *dsa); +static int pk11_dsa_do_verify(const unsigned char *dgst, int dgst_len, + DSA_SIG *sig, DSA *dsa); + +static CK_OBJECT_HANDLE pk11_get_public_dsa_key(DSA* dsa, DSA **key_ptr, + BIGNUM **dsa_pub_num, CK_SESSION_HANDLE session); +static CK_OBJECT_HANDLE pk11_get_private_dsa_key(DSA* dsa, DSA **key_ptr, + BIGNUM **dsa_priv_num, CK_SESSION_HANDLE session); + +static int check_new_dsa_key_pub(PK11_SESSION *sp, DSA *dsa); +static int check_new_dsa_key_priv(PK11_SESSION *sp, DSA *dsa); +#endif + +/* DH stuff */ +#ifndef OPENSSL_NO_DH +static int pk11_DH_init(DH *dh); +static int pk11_DH_finish(DH *dh); +static int pk11_DH_generate_key(DH *dh); +static int pk11_DH_compute_key(unsigned char *key, + const BIGNUM *pub_key, DH *dh); + +static CK_OBJECT_HANDLE pk11_get_dh_key(DH* dh, DH **key_ptr, + BIGNUM **priv_key, CK_SESSION_HANDLE session); + +static int check_new_dh_key(PK11_SESSION *sp, DH *dh); +#endif + +static int find_one_object(PK11_OPTYPE op, CK_SESSION_HANDLE s, + CK_ATTRIBUTE_PTR ptempl, CK_ULONG nattr, CK_OBJECT_HANDLE_PTR pkey); +static int init_template_value(BIGNUM *bn, CK_VOID_PTR *pValue, + CK_ULONG *ulValueLen); +static void attr_to_BN(CK_ATTRIBUTE_PTR attr, CK_BYTE attr_data[], BIGNUM **bn); + +static int pk11_token_login(CK_SESSION_HANDLE session, CK_BBOOL *login_done, + CK_BBOOL is_private); + +/* Read mode string to be used for fopen() */ +#if SOLARIS_OPENSSL +static char *read_mode_flags = "rF"; +#else +static char *read_mode_flags = "r"; +#endif + +/* + * increment/create reference for an asymmetric key handle via active list + * manipulation. If active list operation fails, unlock (if locked), set error + * variable and jump to the specified label. + */ +#define KEY_HANDLE_REFHOLD(key_handle, alg_type, unlock, var, label) \ + { \ + if (pk11_active_add(key_handle, alg_type) < 0) \ + { \ + var = TRUE; \ + if (unlock) \ + UNLOCK_OBJSTORE(alg_type); \ + goto label; \ + } \ + } + +/* + * Find active list entry according to object handle and return pointer to the + * entry otherwise return NULL. + * + * This function presumes it is called with lock protecting the active list + * held. + */ +static PK11_active *pk11_active_find(CK_OBJECT_HANDLE h, PK11_OPTYPE type) + { + PK11_active *entry; + + for (entry = active_list[type]; entry != NULL; entry = entry->next) + if (entry->h == h) + return (entry); + + return (NULL); + } + +/* + * Search for an entry in the active list using PKCS#11 object handle as a + * search key and return refcnt of the found/created entry or -1 in case of + * failure. + * + * This function presumes it is called with lock protecting the active list + * held. + */ +int +pk11_active_add(CK_OBJECT_HANDLE h, PK11_OPTYPE type) + { + PK11_active *entry = NULL; + + if (h == CK_INVALID_HANDLE) + { + PK11err(PK11_F_ACTIVE_ADD, PK11_R_INVALID_HANDLE); + return (-1); + } + + /* search for entry in the active list */ + if ((entry = pk11_active_find(h, type)) != NULL) + entry->refcnt++; + else + { + /* not found, create new entry and add it to the list */ + entry = OPENSSL_malloc(sizeof (PK11_active)); + if (entry == NULL) + { + PK11err(PK11_F_ACTIVE_ADD, PK11_R_MALLOC_FAILURE); + return (-1); + } + entry->h = h; + entry->refcnt = 1; + entry->prev = NULL; + entry->next = NULL; + /* connect the newly created entry to the list */ + if (active_list[type] == NULL) + active_list[type] = entry; + else /* make the entry first in the list */ + { + entry->next = active_list[type]; + active_list[type]->prev = entry; + active_list[type] = entry; + } + } + + return (entry->refcnt); + } + +/* + * Remove active list entry from the list and free it. + * + * This function presumes it is called with lock protecting the active list + * held. + */ +void +pk11_active_remove(PK11_active *entry, PK11_OPTYPE type) + { + PK11_active *prev_entry; + + /* remove the entry from the list and free it */ + if ((prev_entry = entry->prev) != NULL) + { + prev_entry->next = entry->next; + if (entry->next != NULL) + entry->next->prev = prev_entry; + } + else + { + active_list[type] = entry->next; + /* we were the first but not the only one */ + if (entry->next != NULL) + entry->next->prev = NULL; + } + + /* sanitization */ + entry->h = CK_INVALID_HANDLE; + entry->prev = NULL; + entry->next = NULL; + OPENSSL_free(entry); + } + +/* Free all entries from the active list. */ +void +pk11_free_active_list(PK11_OPTYPE type) + { + PK11_active *entry; + + /* only for asymmetric types since only they have C_Find* locks. */ + switch (type) + { + case OP_RSA: + case OP_DSA: + case OP_DH: + break; + default: + return; + } + + /* see find_lock array definition for more info on object locking */ + LOCK_OBJSTORE(type); + while ((entry = active_list[type]) != NULL) + pk11_active_remove(entry, type); + UNLOCK_OBJSTORE(type); + } + +/* + * Search for active list entry associated with given PKCS#11 object handle, + * decrement its refcnt and if it drops to 0, disconnect the entry and free it. + * + * Return 1 if the PKCS#11 object associated with the entry has no references, + * return 0 if there is at least one reference, -1 on error. + * + * This function presumes it is called with lock protecting the active list + * held. + */ +int +pk11_active_delete(CK_OBJECT_HANDLE h, PK11_OPTYPE type) + { + PK11_active *entry = NULL; + + if ((entry = pk11_active_find(h, type)) == NULL) + { + PK11err(PK11_F_ACTIVE_DELETE, PK11_R_INVALID_HANDLE); + return (-1); + } + + OPENSSL_assert(entry->refcnt > 0); + entry->refcnt--; + if (entry->refcnt == 0) + { + pk11_active_remove(entry, type); + return (1); + } + + return (0); + } + +#ifndef OPENSSL_NO_RSA +/* Our internal RSA_METHOD that we provide pointers to */ +static RSA_METHOD pk11_rsa = + { + "PKCS#11 RSA method", + pk11_RSA_public_encrypt, /* rsa_pub_encrypt */ + pk11_RSA_public_decrypt, /* rsa_pub_decrypt */ + pk11_RSA_private_encrypt, /* rsa_priv_encrypt */ + pk11_RSA_private_decrypt, /* rsa_priv_decrypt */ + NULL, /* rsa_mod_exp */ + NULL, /* bn_mod_exp */ + pk11_RSA_init, /* init */ + pk11_RSA_finish, /* finish */ + RSA_FLAG_SIGN_VER, /* flags */ + NULL, /* app_data */ + pk11_RSA_sign, /* rsa_sign */ + pk11_RSA_verify /* rsa_verify */ + }; + +RSA_METHOD * +PK11_RSA(void) + { + return (&pk11_rsa); + } +#endif + +#ifndef OPENSSL_NO_DSA +/* Our internal DSA_METHOD that we provide pointers to */ +static DSA_METHOD pk11_dsa = + { + "PKCS#11 DSA method", + pk11_dsa_do_sign, /* dsa_do_sign */ + NULL, /* dsa_sign_setup */ + pk11_dsa_do_verify, /* dsa_do_verify */ + NULL, /* dsa_mod_exp */ + NULL, /* bn_mod_exp */ + pk11_DSA_init, /* init */ + pk11_DSA_finish, /* finish */ + 0, /* flags */ + NULL /* app_data */ + }; + +DSA_METHOD * +PK11_DSA(void) + { + return (&pk11_dsa); + } +#endif + +#ifndef OPENSSL_NO_DH +/* + * PKCS #11 V2.20, section 11.2 specifies that the number of bytes needed for + * output buffer may somewhat exceed the precise number of bytes needed, but + * should not exceed it by a large amount. That may be caused, for example, by + * rounding it up to multiple of X in the underlying bignum library. 8 should be + * enough. + */ +#define DH_BUF_RESERVE 8 + +/* Our internal DH_METHOD that we provide pointers to */ +static DH_METHOD pk11_dh = + { + "PKCS#11 DH method", + pk11_DH_generate_key, /* generate_key */ + pk11_DH_compute_key, /* compute_key */ + NULL, /* bn_mod_exp */ + pk11_DH_init, /* init */ + pk11_DH_finish, /* finish */ + 0, /* flags */ + NULL, /* app_data */ + NULL /* generate_params */ + }; + +DH_METHOD * +PK11_DH(void) + { + return (&pk11_dh); + } +#endif + +/* Size of an SSL signature: MD5+SHA1 */ +#define SSL_SIG_LENGTH 36 + +/* Lengths of DSA data and signature */ +#define DSA_DATA_LEN 20 +#define DSA_SIGNATURE_LEN 40 + +static CK_BBOOL mytrue = TRUE; +static CK_BBOOL myfalse = FALSE; + +#ifndef OPENSSL_NO_RSA +/* + * Similiar to OpenSSL to take advantage of the paddings. The goal is to + * support all paddings in this engine although PK11 library does not + * support all the paddings used in OpenSSL. + * The input errors should have been checked in the padding functions. + */ +static int pk11_RSA_public_encrypt(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding) + { + int i, num = 0, r = -1; + unsigned char *buf = NULL; + + num = BN_num_bytes(rsa->n); + if ((buf = (unsigned char *)OPENSSL_malloc(num)) == NULL) + { + RSAerr(PK11_F_RSA_PUB_ENC, PK11_R_MALLOC_FAILURE); + goto err; + } + + switch (padding) + { + case RSA_PKCS1_PADDING: + i = RSA_padding_add_PKCS1_type_2(buf, num, from, flen); + break; +#ifndef OPENSSL_NO_SHA + case RSA_PKCS1_OAEP_PADDING: + i = RSA_padding_add_PKCS1_OAEP(buf, num, from, flen, NULL, 0); + break; +#endif + case RSA_SSLV23_PADDING: + i = RSA_padding_add_SSLv23(buf, num, from, flen); + break; + case RSA_NO_PADDING: + i = RSA_padding_add_none(buf, num, from, flen); + break; + default: + RSAerr(PK11_F_RSA_PUB_ENC, PK11_R_UNKNOWN_PADDING_TYPE); + goto err; + } + if (i <= 0) goto err; + + /* PK11 functions are called here */ + r = pk11_RSA_public_encrypt_low(num, buf, to, rsa); +err: + if (buf != NULL) + { + OPENSSL_cleanse(buf, num); + OPENSSL_free(buf); + } + return (r); + } + + +/* + * Similar to Openssl to take advantage of the paddings. The input errors + * should be catched in the padding functions + */ +static int pk11_RSA_private_encrypt(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding) + { + int i, num = 0, r = -1; + unsigned char *buf = NULL; + + num = BN_num_bytes(rsa->n); + if ((buf = (unsigned char *)OPENSSL_malloc(num)) == NULL) + { + RSAerr(PK11_F_RSA_PRIV_ENC, PK11_R_MALLOC_FAILURE); + goto err; + } + + switch (padding) + { + case RSA_PKCS1_PADDING: + i = RSA_padding_add_PKCS1_type_1(buf, num, from, flen); + break; + case RSA_NO_PADDING: + i = RSA_padding_add_none(buf, num, from, flen); + break; + case RSA_SSLV23_PADDING: + default: + RSAerr(PK11_F_RSA_PRIV_ENC, PK11_R_UNKNOWN_PADDING_TYPE); + goto err; + } + if (i <= 0) goto err; + + /* PK11 functions are called here */ + r = pk11_RSA_private_encrypt_low(num, buf, to, rsa); +err: + if (buf != NULL) + { + OPENSSL_cleanse(buf, num); + OPENSSL_free(buf); + } + return (r); + } + +/* Similar to OpenSSL code. Input errors are also checked here */ +static int pk11_RSA_private_decrypt(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding) + { + BIGNUM f; + int j, num = 0, r = -1; + unsigned char *p; + unsigned char *buf = NULL; + + BN_init(&f); + + num = BN_num_bytes(rsa->n); + + if ((buf = (unsigned char *)OPENSSL_malloc(num)) == NULL) + { + RSAerr(PK11_F_RSA_PRIV_DEC, PK11_R_MALLOC_FAILURE); + goto err; + } + + /* + * This check was for equality but PGP does evil things + * and chops off the top '0' bytes + */ + if (flen > num) + { + RSAerr(PK11_F_RSA_PRIV_DEC, + PK11_R_DATA_GREATER_THAN_MOD_LEN); + goto err; + } + + /* make data into a big number */ + if (BN_bin2bn(from, (int)flen, &f) == NULL) + goto err; + + if (BN_ucmp(&f, rsa->n) >= 0) + { + RSAerr(PK11_F_RSA_PRIV_DEC, + PK11_R_DATA_TOO_LARGE_FOR_MODULUS); + goto err; + } + + /* PK11 functions are called here */ + r = pk11_RSA_private_decrypt_low(flen, from, buf, rsa); + + /* + * PK11 CKM_RSA_X_509 mechanism pads 0's at the beginning. + * Needs to skip these 0's paddings here. + */ + for (j = 0; j < r; j++) + if (buf[j] != 0) + break; + + p = buf + j; + j = r - j; /* j is only used with no-padding mode */ + + switch (padding) + { + case RSA_PKCS1_PADDING: + r = RSA_padding_check_PKCS1_type_2(to, num, p, j, num); + break; +#ifndef OPENSSL_NO_SHA + case RSA_PKCS1_OAEP_PADDING: + r = RSA_padding_check_PKCS1_OAEP(to, num, p, j, num, NULL, 0); + break; +#endif + case RSA_SSLV23_PADDING: + r = RSA_padding_check_SSLv23(to, num, p, j, num); + break; + case RSA_NO_PADDING: + r = RSA_padding_check_none(to, num, p, j, num); + break; + default: + RSAerr(PK11_F_RSA_PRIV_DEC, PK11_R_UNKNOWN_PADDING_TYPE); + goto err; + } + if (r < 0) + RSAerr(PK11_F_RSA_PRIV_DEC, PK11_R_PADDING_CHECK_FAILED); + +err: + BN_clear_free(&f); + if (buf != NULL) + { + OPENSSL_cleanse(buf, num); + OPENSSL_free(buf); + } + return (r); + } + +/* Similar to OpenSSL code. Input errors are also checked here */ +static int pk11_RSA_public_decrypt(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding) + { + BIGNUM f; + int i, num = 0, r = -1; + unsigned char *p; + unsigned char *buf = NULL; + + BN_init(&f); + num = BN_num_bytes(rsa->n); + buf = (unsigned char *)OPENSSL_malloc(num); + if (buf == NULL) + { + RSAerr(PK11_F_RSA_PUB_DEC, PK11_R_MALLOC_FAILURE); + goto err; + } + + /* + * This check was for equality but PGP does evil things + * and chops off the top '0' bytes + */ + if (flen > num) + { + RSAerr(PK11_F_RSA_PUB_DEC, PK11_R_DATA_GREATER_THAN_MOD_LEN); + goto err; + } + + if (BN_bin2bn(from, flen, &f) == NULL) + goto err; + + if (BN_ucmp(&f, rsa->n) >= 0) + { + RSAerr(PK11_F_RSA_PUB_DEC, + PK11_R_DATA_TOO_LARGE_FOR_MODULUS); + goto err; + } + + /* PK11 functions are called here */ + r = pk11_RSA_public_decrypt_low(flen, from, buf, rsa); + + /* + * PK11 CKM_RSA_X_509 mechanism pads 0's at the beginning. + * Needs to skip these 0's here + */ + for (i = 0; i < r; i++) + if (buf[i] != 0) + break; + + p = buf + i; + i = r - i; /* i is only used with no-padding mode */ + + switch (padding) + { + case RSA_PKCS1_PADDING: + r = RSA_padding_check_PKCS1_type_1(to, num, p, i, num); + break; + case RSA_NO_PADDING: + r = RSA_padding_check_none(to, num, p, i, num); + break; + default: + RSAerr(PK11_F_RSA_PUB_DEC, PK11_R_UNKNOWN_PADDING_TYPE); + goto err; + } + if (r < 0) + RSAerr(PK11_F_RSA_PUB_DEC, PK11_R_PADDING_CHECK_FAILED); + +err: + BN_clear_free(&f); + if (buf != NULL) + { + OPENSSL_cleanse(buf, num); + OPENSSL_free(buf); + } + return (r); + } + +/* + * This function implements RSA public encryption using C_EncryptInit and + * C_Encrypt pk11 interfaces. Note that the CKM_RSA_X_509 is used here. + * The calling function allocated sufficient memory in "to" to store results. + */ +static int pk11_RSA_public_encrypt_low(int flen, + const unsigned char *from, unsigned char *to, RSA *rsa) + { + CK_ULONG bytes_encrypted = flen; + int retval = -1; + CK_RV rv; + CK_MECHANISM mech_rsa = {CKM_RSA_X_509, NULL, 0}; + CK_MECHANISM *p_mech = &mech_rsa; + CK_OBJECT_HANDLE h_pub_key = CK_INVALID_HANDLE; + PK11_SESSION *sp; + + if ((sp = pk11_get_session(OP_RSA)) == NULL) + return (-1); + + (void) check_new_rsa_key_pub(sp, rsa); + + h_pub_key = sp->opdata_rsa_pub_key; + if (h_pub_key == CK_INVALID_HANDLE) + h_pub_key = sp->opdata_rsa_pub_key = + pk11_get_public_rsa_key(rsa, &sp->opdata_rsa_pub, + &sp->opdata_rsa_n_num, &sp->opdata_rsa_e_num, + sp->session); + + if (h_pub_key != CK_INVALID_HANDLE) + { + rv = pFuncList->C_EncryptInit(sp->session, p_mech, + h_pub_key); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_RSA_PUB_ENC_LOW, + PK11_R_ENCRYPTINIT, rv); + pk11_return_session(sp, OP_RSA); + return (-1); + } + + rv = pFuncList->C_Encrypt(sp->session, + (unsigned char *)from, flen, to, &bytes_encrypted); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_RSA_PUB_ENC_LOW, + PK11_R_ENCRYPT, rv); + pk11_return_session(sp, OP_RSA); + return (-1); + } + retval = bytes_encrypted; + } + + pk11_return_session(sp, OP_RSA); + return (retval); + } + + +/* + * This function implements RSA private encryption using C_SignInit and + * C_Sign pk11 APIs. Note that CKM_RSA_X_509 is used here. + * The calling function allocated sufficient memory in "to" to store results. + */ +static int pk11_RSA_private_encrypt_low(int flen, + const unsigned char *from, unsigned char *to, RSA *rsa) + { + CK_ULONG ul_sig_len = flen; + int retval = -1; + CK_RV rv; + CK_MECHANISM mech_rsa = {CKM_RSA_X_509, NULL, 0}; + CK_MECHANISM *p_mech = &mech_rsa; + CK_OBJECT_HANDLE h_priv_key = CK_INVALID_HANDLE; + PK11_SESSION *sp; + + if ((sp = pk11_get_session(OP_RSA)) == NULL) + return (-1); + + (void) check_new_rsa_key_priv(sp, rsa); + + h_priv_key = sp->opdata_rsa_priv_key; + if (h_priv_key == CK_INVALID_HANDLE) + { + h_priv_key = sp->opdata_rsa_priv_key = + pk11_get_private_rsa_key(rsa, &sp->opdata_rsa_priv, + &sp->opdata_rsa_d_num, &sp->opdata_rsa_pn_num, + &sp->opdata_rsa_pe_num, sp->session); + } + + if (h_priv_key != CK_INVALID_HANDLE) + { + rv = pFuncList->C_SignInit(sp->session, p_mech, + h_priv_key); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_RSA_PRIV_ENC_LOW, + PK11_R_SIGNINIT, rv); + pk11_return_session(sp, OP_RSA); + return (-1); + } + + rv = pFuncList->C_Sign(sp->session, + (unsigned char *)from, flen, to, &ul_sig_len); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_RSA_PRIV_ENC_LOW, PK11_R_SIGN, + rv); + pk11_return_session(sp, OP_RSA); + return (-1); + } + + retval = ul_sig_len; + } + + pk11_return_session(sp, OP_RSA); + return (retval); + } + + +/* + * This function implements RSA private decryption using C_DecryptInit and + * C_Decrypt pk11 APIs. Note that CKM_RSA_X_509 mechanism is used here. + * The calling function allocated sufficient memory in "to" to store results. + */ +static int pk11_RSA_private_decrypt_low(int flen, + const unsigned char *from, unsigned char *to, RSA *rsa) + { + CK_ULONG bytes_decrypted = flen; + int retval = -1; + CK_RV rv; + CK_MECHANISM mech_rsa = {CKM_RSA_X_509, NULL, 0}; + CK_MECHANISM *p_mech = &mech_rsa; + CK_OBJECT_HANDLE h_priv_key; + PK11_SESSION *sp; + + if ((sp = pk11_get_session(OP_RSA)) == NULL) + return (-1); + + (void) check_new_rsa_key_priv(sp, rsa); + + h_priv_key = sp->opdata_rsa_priv_key; + if (h_priv_key == CK_INVALID_HANDLE) + h_priv_key = sp->opdata_rsa_priv_key = + pk11_get_private_rsa_key(rsa, &sp->opdata_rsa_priv, + &sp->opdata_rsa_d_num, &sp->opdata_rsa_pn_num, + &sp->opdata_rsa_pe_num, sp->session); + + if (h_priv_key != CK_INVALID_HANDLE) + { + rv = pFuncList->C_DecryptInit(sp->session, p_mech, + h_priv_key); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_RSA_PRIV_DEC_LOW, + PK11_R_DECRYPTINIT, rv); + pk11_return_session(sp, OP_RSA); + return (-1); + } + + rv = pFuncList->C_Decrypt(sp->session, + (unsigned char *)from, flen, to, &bytes_decrypted); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_RSA_PRIV_DEC_LOW, + PK11_R_DECRYPT, rv); + pk11_return_session(sp, OP_RSA); + return (-1); + } + retval = bytes_decrypted; + } + + pk11_return_session(sp, OP_RSA); + return (retval); + } + + +/* + * This function implements RSA public decryption using C_VerifyRecoverInit + * and C_VerifyRecover pk11 APIs. Note that CKM_RSA_X_509 is used here. + * The calling function allocated sufficient memory in "to" to store results. + */ +static int pk11_RSA_public_decrypt_low(int flen, + const unsigned char *from, unsigned char *to, RSA *rsa) + { + CK_ULONG bytes_decrypted = flen; + int retval = -1; + CK_RV rv; + CK_MECHANISM mech_rsa = {CKM_RSA_X_509, NULL, 0}; + CK_MECHANISM *p_mech = &mech_rsa; + CK_OBJECT_HANDLE h_pub_key = CK_INVALID_HANDLE; + PK11_SESSION *sp; + + if ((sp = pk11_get_session(OP_RSA)) == NULL) + return (-1); + + (void) check_new_rsa_key_pub(sp, rsa); + + h_pub_key = sp->opdata_rsa_pub_key; + if (h_pub_key == CK_INVALID_HANDLE) + h_pub_key = sp->opdata_rsa_pub_key = + pk11_get_public_rsa_key(rsa, &sp->opdata_rsa_pub, + &sp->opdata_rsa_n_num, &sp->opdata_rsa_e_num, + sp->session); + + if (h_pub_key != CK_INVALID_HANDLE) + { + rv = pFuncList->C_VerifyRecoverInit(sp->session, + p_mech, h_pub_key); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_RSA_PUB_DEC_LOW, + PK11_R_VERIFYRECOVERINIT, rv); + pk11_return_session(sp, OP_RSA); + return (-1); + } + + rv = pFuncList->C_VerifyRecover(sp->session, + (unsigned char *)from, flen, to, &bytes_decrypted); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_RSA_PUB_DEC_LOW, + PK11_R_VERIFYRECOVER, rv); + pk11_return_session(sp, OP_RSA); + return (-1); + } + retval = bytes_decrypted; + } + + pk11_return_session(sp, OP_RSA); + return (retval); + } + +static int pk11_RSA_init(RSA *rsa) + { + /* + * This flag in the RSA_METHOD enables the new rsa_sign, + * rsa_verify functions. See rsa.h for details. + */ + rsa->flags |= RSA_FLAG_SIGN_VER; + + return (1); + } + +static int pk11_RSA_finish(RSA *rsa) + { + /* + * Since we are overloading OpenSSL's native RSA_eay_finish() we need + * to do the same as in the original function, i.e. to free bignum + * structures. + */ + if (rsa->_method_mod_n != NULL) + BN_MONT_CTX_free(rsa->_method_mod_n); + if (rsa->_method_mod_p != NULL) + BN_MONT_CTX_free(rsa->_method_mod_p); + if (rsa->_method_mod_q != NULL) + BN_MONT_CTX_free(rsa->_method_mod_q); + + return (1); + } + +/* + * Standard engine interface function. Majority codes here are from + * rsa/rsa_sign.c. We replaced the decrypt function call by C_Sign of PKCS#11. + * See more details in rsa/rsa_sign.c + */ +static int pk11_RSA_sign(int type, const unsigned char *m, unsigned int m_len, + unsigned char *sigret, unsigned int *siglen, const RSA *rsa) + { + X509_SIG sig; + ASN1_TYPE parameter; + int i, j = 0; + unsigned char *p, *s = NULL; + X509_ALGOR algor; + ASN1_OCTET_STRING digest; + CK_RV rv; + CK_MECHANISM mech_rsa = {CKM_RSA_PKCS, NULL, 0}; + CK_MECHANISM *p_mech = &mech_rsa; + CK_OBJECT_HANDLE h_priv_key; + PK11_SESSION *sp = NULL; + int ret = 0; + unsigned long ulsiglen; + + /* Encode the digest */ + /* Special case: SSL signature, just check the length */ + if (type == NID_md5_sha1) + { + if (m_len != SSL_SIG_LENGTH) + { + PK11err(PK11_F_RSA_SIGN, + PK11_R_INVALID_MESSAGE_LENGTH); + goto err; + } + i = SSL_SIG_LENGTH; + s = (unsigned char *)m; + } + else + { + sig.algor = &algor; + sig.algor->algorithm = OBJ_nid2obj(type); + if (sig.algor->algorithm == NULL) + { + PK11err(PK11_F_RSA_SIGN, + PK11_R_UNKNOWN_ALGORITHM_TYPE); + goto err; + } + if (sig.algor->algorithm->length == 0) + { + PK11err(PK11_F_RSA_SIGN, + PK11_R_UNKNOWN_ASN1_OBJECT_ID); + goto err; + } + parameter.type = V_ASN1_NULL; + parameter.value.ptr = NULL; + sig.algor->parameter = ¶meter; + + sig.digest = &digest; + sig.digest->data = (unsigned char *)m; + sig.digest->length = m_len; + + i = i2d_X509_SIG(&sig, NULL); + } + + j = RSA_size(rsa); + if ((i - RSA_PKCS1_PADDING) > j) + { + PK11err(PK11_F_RSA_SIGN, PK11_R_DIGEST_TOO_BIG); + goto err; + } + + if (type != NID_md5_sha1) + { + s = (unsigned char *)OPENSSL_malloc((unsigned int)(j + 1)); + if (s == NULL) + { + PK11err(PK11_F_RSA_SIGN, PK11_R_MALLOC_FAILURE); + goto err; + } + p = s; + (void) i2d_X509_SIG(&sig, &p); + } + + if ((sp = pk11_get_session(OP_RSA)) == NULL) + goto err; + + (void) check_new_rsa_key_priv(sp, rsa); + + h_priv_key = sp->opdata_rsa_priv_key; + if (h_priv_key == CK_INVALID_HANDLE) + h_priv_key = sp->opdata_rsa_priv_key = + pk11_get_private_rsa_key((RSA *)rsa, + &sp->opdata_rsa_priv, &sp->opdata_rsa_d_num, + &sp->opdata_rsa_pn_num, &sp->opdata_rsa_pe_num, + sp->session); + + if (h_priv_key != CK_INVALID_HANDLE) + { + rv = pFuncList->C_SignInit(sp->session, p_mech, h_priv_key); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_RSA_SIGN, PK11_R_SIGNINIT, rv); + goto err; + } + + ulsiglen = j; + rv = pFuncList->C_Sign(sp->session, s, i, sigret, + (CK_ULONG_PTR) &ulsiglen); + *siglen = ulsiglen; + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_RSA_SIGN, PK11_R_SIGN, rv); + goto err; + } + ret = 1; + } + +err: + if ((type != NID_md5_sha1) && (s != NULL)) + { + (void) memset(s, 0, (unsigned int)(j + 1)); + OPENSSL_free(s); + } + + pk11_return_session(sp, OP_RSA); + return (ret); + } + +#if OPENSSL_VERSION_NUMBER < 0x10000000L +static int pk11_RSA_verify(int type, const unsigned char *m, + unsigned int m_len, unsigned char *sigbuf, unsigned int siglen, + const RSA *rsa) +#else +static int pk11_RSA_verify(int type, const unsigned char *m, + unsigned int m_len, const unsigned char *sigbuf, unsigned int siglen, + const RSA *rsa) +#endif + { + X509_SIG sig; + ASN1_TYPE parameter; + int i, j = 0; + unsigned char *p, *s = NULL; + X509_ALGOR algor; + ASN1_OCTET_STRING digest; + CK_RV rv; + CK_MECHANISM mech_rsa = {CKM_RSA_PKCS, NULL, 0}; + CK_MECHANISM *p_mech = &mech_rsa; + CK_OBJECT_HANDLE h_pub_key; + PK11_SESSION *sp = NULL; + int ret = 0; + + /* Encode the digest */ + /* Special case: SSL signature, just check the length */ + if (type == NID_md5_sha1) + { + if (m_len != SSL_SIG_LENGTH) + { + PK11err(PK11_F_RSA_VERIFY, + PK11_R_INVALID_MESSAGE_LENGTH); + goto err; + } + i = SSL_SIG_LENGTH; + s = (unsigned char *)m; + } + else + { + sig.algor = &algor; + sig.algor->algorithm = OBJ_nid2obj(type); + if (sig.algor->algorithm == NULL) + { + PK11err(PK11_F_RSA_VERIFY, + PK11_R_UNKNOWN_ALGORITHM_TYPE); + goto err; + } + if (sig.algor->algorithm->length == 0) + { + PK11err(PK11_F_RSA_VERIFY, + PK11_R_UNKNOWN_ASN1_OBJECT_ID); + goto err; + } + parameter.type = V_ASN1_NULL; + parameter.value.ptr = NULL; + sig.algor->parameter = ¶meter; + sig.digest = &digest; + sig.digest->data = (unsigned char *)m; + sig.digest->length = m_len; + i = i2d_X509_SIG(&sig, NULL); + } + + j = RSA_size(rsa); + if ((i - RSA_PKCS1_PADDING) > j) + { + PK11err(PK11_F_RSA_VERIFY, PK11_R_DIGEST_TOO_BIG); + goto err; + } + + if (type != NID_md5_sha1) + { + s = (unsigned char *)OPENSSL_malloc((unsigned int)(j + 1)); + if (s == NULL) + { + PK11err(PK11_F_RSA_VERIFY, PK11_R_MALLOC_FAILURE); + goto err; + } + p = s; + (void) i2d_X509_SIG(&sig, &p); + } + + if ((sp = pk11_get_session(OP_RSA)) == NULL) + goto err; + + (void) check_new_rsa_key_pub(sp, rsa); + + h_pub_key = sp->opdata_rsa_pub_key; + if (h_pub_key == CK_INVALID_HANDLE) + h_pub_key = sp->opdata_rsa_pub_key = + pk11_get_public_rsa_key((RSA *)rsa, &sp->opdata_rsa_pub, + &sp->opdata_rsa_n_num, &sp->opdata_rsa_e_num, + sp->session); + + if (h_pub_key != CK_INVALID_HANDLE) + { + rv = pFuncList->C_VerifyInit(sp->session, p_mech, + h_pub_key); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_RSA_VERIFY, PK11_R_VERIFYINIT, + rv); + goto err; + } + rv = pFuncList->C_Verify(sp->session, s, i, + (CK_BYTE_PTR)sigbuf, (CK_ULONG)siglen); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_RSA_VERIFY, PK11_R_VERIFY, rv); + goto err; + } + ret = 1; + } + +err: + if ((type != NID_md5_sha1) && (s != NULL)) + { + (void) memset(s, 0, (unsigned int)(j + 1)); + OPENSSL_free(s); + } + + pk11_return_session(sp, OP_RSA); + return (ret); + } + +static int hndidx_rsa = -1; + +#define MAXATTR 1024 + +/* + * Load RSA private key from a file or get its PKCS#11 handle if stored in the + * PKCS#11 token. + */ +/* ARGSUSED */ +EVP_PKEY *pk11_load_privkey(ENGINE *e, const char *privkey_file, + UI_METHOD *ui_method, void *callback_data) + { + EVP_PKEY *pkey = NULL; + FILE *privkey; + CK_OBJECT_HANDLE h_priv_key = CK_INVALID_HANDLE; + RSA *rsa = NULL; + PK11_SESSION *sp; + /* Anything else below is needed for the key by reference extension. */ + CK_RV rv; + CK_BBOOL is_token = TRUE; + CK_BBOOL rollback = FALSE; + CK_BYTE attr_data[2][MAXATTR]; + CK_OBJECT_CLASS key_class = CKO_PRIVATE_KEY; + CK_OBJECT_HANDLE ks_key = CK_INVALID_HANDLE; /* key in keystore */ + + /* we look for private keys only */ + CK_ATTRIBUTE search_templ[] = + { + {CKA_TOKEN, &is_token, sizeof(is_token)}, + {CKA_CLASS, &key_class, sizeof(key_class)}, + {CKA_LABEL, NULL, 0} + }; + + /* + * These public attributes are needed to initialize the OpenSSL RSA + * structure with something we can use to look up the key. Note that we + * never ask for private components. + */ + CK_ATTRIBUTE get_templ[] = + { + {CKA_MODULUS, (void *)attr_data[0], MAXATTR}, /* n */ + {CKA_PUBLIC_EXPONENT, (void *)attr_data[1], MAXATTR}, /* e */ + }; + + if ((sp = pk11_get_session(OP_RSA)) == NULL) + return (NULL); + + /* + * Use simple scheme "pkcs11:" for now. + */ + if (strstr(privkey_file, "pkcs11:") == privkey_file) + { + search_templ[2].pValue = strstr(privkey_file, ":") + 1; + search_templ[2].ulValueLen = strlen(search_templ[2].pValue); + + if (pk11_token_login(sp->session, &pk11_login_done, + CK_TRUE) == 0) + goto err; + + /* see find_lock array definition + for more info on object locking */ + LOCK_OBJSTORE(OP_RSA); + + /* + * Now let's try to find the key in the token. It is a failure + * if we can't find it. + */ + if (find_one_object(OP_RSA, sp->session, search_templ, 3, + &ks_key) == 0) + { + UNLOCK_OBJSTORE(OP_RSA); + goto err; + } + + if (hndidx_rsa == -1) + hndidx_rsa = RSA_get_ex_new_index(0, + "pkcs11 RSA HSM key handle", + NULL, NULL, NULL); + + /* + * We might have a cache hit which we could confirm + * according to the 'n'/'e' params, RSA public pointer + * as NULL, and non-NULL RSA private pointer. However, + * it is easier just to recreate everything. We expect + * the keys to be loaded once and used many times. We + * do not check the return value because even in case + * of failure the sp structure will have both key + * pointer and object handle cleaned and + * pk11_destroy_object() reports the failure to the + * OpenSSL error message buffer. + */ + (void) pk11_destroy_rsa_object_priv(sp, FALSE); + + sp->opdata_rsa_priv_key = ks_key; + /* This object shall not be deleted on a cache miss. */ + sp->priv_persistent = CK_TRUE; + + /* + * Cache the RSA private structure pointer. We do not + * use it now for key-by-ref keys but let's do it for + * consistency reasons. + */ + if ((rsa = sp->opdata_rsa_priv = RSA_new_method(e)) == NULL) + { + UNLOCK_OBJSTORE(OP_RSA); + goto err; + } + + /* + * Now we have to initialize an OpenSSL RSA structure, + * everything else is 0 or NULL. + */ + rsa->flags = RSA_FLAG_SIGN_VER | RSA_FLAG_EXT_PKEY; + RSA_set_ex_data(rsa, hndidx_rsa, (void *) ks_key); + + if ((rv = pFuncList->C_GetAttributeValue(sp->session, ks_key, + get_templ, 2)) != CKR_OK) + { + UNLOCK_OBJSTORE(OP_RSA); + PK11err_add_data(PK11_F_LOAD_PRIVKEY, + PK11_R_GETATTRIBUTVALUE, rv); + goto err; + } + + /* + * We do not use pk11_get_private_rsa_key() here so we + * must take care of handle management ourselves. + */ + KEY_HANDLE_REFHOLD(ks_key, OP_RSA, TRUE, rollback, err); + + /* + * Those are the sensitive components we do not want to export + * from the token at all: rsa->(d|p|q|dmp1|dmq1|iqmp). + */ + attr_to_BN(&get_templ[0], attr_data[0], &rsa->n); + attr_to_BN(&get_templ[1], attr_data[1], &rsa->e); + /* + * Must have 'n'/'e' components in the session structure as + * well. They serve as a public look-up key for the private key + * in the keystore. + */ + attr_to_BN(&get_templ[0], attr_data[0], + &sp->opdata_rsa_pn_num); + attr_to_BN(&get_templ[1], attr_data[1], + &sp->opdata_rsa_pe_num); + + UNLOCK_OBJSTORE(OP_RSA); + + if ((pkey = EVP_PKEY_new()) == NULL) + goto err; + + if (EVP_PKEY_assign_RSA(pkey, rsa) == 0) + goto err; + } + else if ((privkey = fopen(privkey_file, read_mode_flags)) != NULL) + { + pkey = PEM_read_PrivateKey(privkey, NULL, NULL, NULL); + (void) fclose(privkey); + if (pkey != NULL) + { + rsa = EVP_PKEY_get1_RSA(pkey); + if (rsa != NULL) + { + /* + * This will always destroy the RSA + * object since we have a new RSA + * structure here. + */ + (void) check_new_rsa_key_priv(sp, rsa); + sp->priv_persistent = CK_FALSE; + + h_priv_key = sp->opdata_rsa_priv_key = + pk11_get_private_rsa_key(rsa, + &sp->opdata_rsa_priv, + &sp->opdata_rsa_d_num, + &sp->opdata_rsa_pn_num, + &sp->opdata_rsa_pe_num, sp->session); + if (h_priv_key == CK_INVALID_HANDLE) + goto err; + } + else + goto err; + } + } + + pk11_return_session(sp, OP_RSA); + return (pkey); +err: + pk11_return_session(sp, OP_RSA); + if (rsa != NULL) + RSA_free(rsa); + if (pkey != NULL) + { + EVP_PKEY_free(pkey); + pkey = NULL; + } + rollback = rollback; + return (pkey); + } + +/* + * Load RSA public key from a file or get its PKCS#11 handle if stored in the + * PKCS#11 token. + */ +/* ARGSUSED */ +EVP_PKEY *pk11_load_pubkey(ENGINE *e, const char *pubkey_file, + UI_METHOD *ui_method, void *callback_data) + { + EVP_PKEY *pkey = NULL; + FILE *pubkey; + CK_OBJECT_HANDLE h_pub_key = CK_INVALID_HANDLE; + RSA *rsa = NULL; + PK11_SESSION *sp; + /* Anything else below is needed for the key by reference extension. */ + CK_RV rv; + CK_BBOOL is_token = TRUE; + CK_BYTE attr_data[2][MAXATTR]; + CK_OBJECT_CLASS key_class = CKO_PUBLIC_KEY; + CK_OBJECT_HANDLE ks_key = CK_INVALID_HANDLE; /* key in keystore */ + + /* we look for public keys only */ + CK_ATTRIBUTE search_templ[] = + { + {CKA_TOKEN, &is_token, sizeof(is_token)}, + {CKA_CLASS, &key_class, sizeof(key_class)}, + {CKA_LABEL, NULL, 0} + }; + + /* + * These public attributes are needed to initialize OpenSSL RSA + * structure with something we can use to look up the key. + */ + CK_ATTRIBUTE get_templ[] = + { + {CKA_MODULUS, (void *)attr_data[0], MAXATTR}, /* n */ + {CKA_PUBLIC_EXPONENT, (void *)attr_data[1], MAXATTR}, /* e */ + }; + + if ((sp = pk11_get_session(OP_RSA)) == NULL) + return (NULL); + + /* + * Use simple scheme "pkcs11:" for now. + */ + if (strstr(pubkey_file, "pkcs11:") == pubkey_file) + { + search_templ[2].pValue = strstr(pubkey_file, ":") + 1; + search_templ[2].ulValueLen = strlen(search_templ[2].pValue); + + if (pk11_token_login(sp->session, &pk11_login_done, + CK_FALSE) == 0) + goto err; + + /* see find_lock array definition + for more info on object locking */ + LOCK_OBJSTORE(OP_RSA); + + /* + * Now let's try to find the key in the token. It is a failure + * if we can't find it. + */ + if (find_one_object(OP_RSA, sp->session, search_templ, 3, + &ks_key) == 0) + { + UNLOCK_OBJSTORE(OP_RSA); + goto err; + } + + /* + * We load a new public key so we will create a new RSA + * structure. No cache hit is possible. + */ + (void) pk11_destroy_rsa_object_pub(sp, FALSE); + + sp->opdata_rsa_pub_key = ks_key; + /* This object shall not be deleted on a cache miss. */ + sp->pub_persistent = CK_TRUE; + + /* + * Cache the RSA public structure pointer. + */ + if ((rsa = sp->opdata_rsa_pub = RSA_new_method(e)) == NULL) + { + UNLOCK_OBJSTORE(OP_RSA); + goto err; + } + + /* + * Now we have to initialize an OpenSSL RSA structure, + * everything else is 0 or NULL. + */ + rsa->flags = RSA_FLAG_SIGN_VER; + + if ((rv = pFuncList->C_GetAttributeValue(sp->session, ks_key, + get_templ, 2)) != CKR_OK) + { + UNLOCK_OBJSTORE(OP_RSA); + PK11err_add_data(PK11_F_LOAD_PUBKEY, + PK11_R_GETATTRIBUTVALUE, rv); + goto err; + } + + attr_to_BN(&get_templ[0], attr_data[0], &rsa->n); + attr_to_BN(&get_templ[1], attr_data[1], &rsa->e); + + UNLOCK_OBJSTORE(OP_RSA); + + if ((pkey = EVP_PKEY_new()) == NULL) + goto err; + + if (EVP_PKEY_assign_RSA(pkey, rsa) == 0) + goto err; + + /* + * Create a session object from it so that when calling + * pk11_get_public_rsa_key() the next time, we can find it. The + * reason why we do that is that we cannot tell from the RSA + * structure (OpenSSL RSA structure does not have any room for + * additional data used by the engine, for example) if it bears + * a public key stored in the keystore or not so it's better if + * we always have a session key. Note that this is different + * from what we do for the private keystore objects but in that + * case, we can tell from the RSA structure that the keystore + * object is in play - the 'd' component is NULL in that case. + */ + h_pub_key = sp->opdata_rsa_pub_key = + pk11_get_public_rsa_key(rsa, + &sp->opdata_rsa_pub, &sp->opdata_rsa_n_num, + &sp->opdata_rsa_e_num, sp->session); + if (h_pub_key == CK_INVALID_HANDLE) + goto err; + } + else if ((pubkey = fopen(pubkey_file, read_mode_flags)) != NULL) + { + pkey = PEM_read_PUBKEY(pubkey, NULL, NULL, NULL); + (void) fclose(pubkey); + if (pkey != NULL) + { + rsa = EVP_PKEY_get1_RSA(pkey); + if (rsa != NULL) + { + /* + * This will always destroy the RSA + * object since we have a new RSA + * structure here. + */ + (void) check_new_rsa_key_pub(sp, rsa); + sp->pub_persistent = CK_FALSE; + + h_pub_key = sp->opdata_rsa_pub_key = + pk11_get_public_rsa_key(rsa, + &sp->opdata_rsa_pub, &sp->opdata_rsa_n_num, + &sp->opdata_rsa_e_num, sp->session); + if (h_pub_key == CK_INVALID_HANDLE) + goto err; + } + else + goto err; + } + } + + pk11_return_session(sp, OP_RSA); + return (pkey); +err: + pk11_return_session(sp, OP_RSA); + if (rsa != NULL) + RSA_free(rsa); + if (pkey != NULL) + { + EVP_PKEY_free(pkey); + pkey = NULL; + } + return (pkey); + } + +/* + * Create a public key object in a session from a given rsa structure. + * The *rsa_n_num and *rsa_e_num pointers are non-NULL for RSA public keys. + */ +static CK_OBJECT_HANDLE pk11_get_public_rsa_key(RSA *rsa, + RSA **key_ptr, BIGNUM **rsa_n_num, BIGNUM **rsa_e_num, + CK_SESSION_HANDLE session) + { + CK_RV rv; + CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE; + CK_ULONG found; + CK_OBJECT_CLASS o_key = CKO_PUBLIC_KEY; + CK_KEY_TYPE k_type = CKK_RSA; + CK_ULONG ul_key_attr_count = 8; + CK_BBOOL rollback = FALSE; + + CK_ATTRIBUTE a_key_template[] = + { + {CKA_CLASS, (void *) NULL, sizeof (CK_OBJECT_CLASS)}, + {CKA_KEY_TYPE, (void *) NULL, sizeof (CK_KEY_TYPE)}, + {CKA_TOKEN, &myfalse, sizeof (myfalse)}, + {CKA_ENCRYPT, &mytrue, sizeof (mytrue)}, + {CKA_VERIFY, &mytrue, sizeof (mytrue)}, + {CKA_VERIFY_RECOVER, &mytrue, sizeof (mytrue)}, + {CKA_MODULUS, (void *)NULL, 0}, + {CKA_PUBLIC_EXPONENT, (void *)NULL, 0} + }; + + int i; + + a_key_template[0].pValue = &o_key; + a_key_template[1].pValue = &k_type; + + a_key_template[6].ulValueLen = BN_num_bytes(rsa->n); + a_key_template[6].pValue = (CK_VOID_PTR)OPENSSL_malloc( + (size_t)a_key_template[6].ulValueLen); + if (a_key_template[6].pValue == NULL) + { + PK11err(PK11_F_GET_PUB_RSA_KEY, PK11_R_MALLOC_FAILURE); + goto malloc_err; + } + + BN_bn2bin(rsa->n, a_key_template[6].pValue); + + a_key_template[7].ulValueLen = BN_num_bytes(rsa->e); + a_key_template[7].pValue = (CK_VOID_PTR)OPENSSL_malloc( + (size_t)a_key_template[7].ulValueLen); + if (a_key_template[7].pValue == NULL) + { + PK11err(PK11_F_GET_PUB_RSA_KEY, PK11_R_MALLOC_FAILURE); + goto malloc_err; + } + + BN_bn2bin(rsa->e, a_key_template[7].pValue); + + /* see find_lock array definition for more info on object locking */ + LOCK_OBJSTORE(OP_RSA); + + rv = pFuncList->C_FindObjectsInit(session, a_key_template, + ul_key_attr_count); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PUB_RSA_KEY, + PK11_R_FINDOBJECTSINIT, rv); + goto err; + } + + rv = pFuncList->C_FindObjects(session, &h_key, 1, &found); + + if (rv != CKR_OK) + { + (void) pFuncList->C_FindObjectsFinal(session); + PK11err_add_data(PK11_F_GET_PUB_RSA_KEY, + PK11_R_FINDOBJECTS, rv); + goto err; + } + + rv = pFuncList->C_FindObjectsFinal(session); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PUB_RSA_KEY, + PK11_R_FINDOBJECTSFINAL, rv); + goto err; + } + + if (found == 0) + { + rv = pFuncList->C_CreateObject(session, + a_key_template, ul_key_attr_count, &h_key); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PUB_RSA_KEY, + PK11_R_CREATEOBJECT, rv); + goto err; + } + } + + if (rsa_n_num != NULL) + if ((*rsa_n_num = BN_dup(rsa->n)) == NULL) + { + PK11err(PK11_F_GET_PUB_RSA_KEY, PK11_R_MALLOC_FAILURE); + rollback = TRUE; + goto err; + } + if (rsa_e_num != NULL) + if ((*rsa_e_num = BN_dup(rsa->e)) == NULL) + { + PK11err(PK11_F_GET_PUB_RSA_KEY, PK11_R_MALLOC_FAILURE); + BN_free(*rsa_n_num); + *rsa_n_num = NULL; + rollback = TRUE; + goto err; + } + + /* LINTED: E_CONSTANT_CONDITION */ + KEY_HANDLE_REFHOLD(h_key, OP_RSA, FALSE, rollback, err); + if (key_ptr != NULL) + *key_ptr = rsa; + +err: + if (rollback) + { + /* + * We do not care about the return value from C_DestroyObject() + * since we are doing rollback. + */ + if (found == 0) + (void) pFuncList->C_DestroyObject(session, h_key); + h_key = CK_INVALID_HANDLE; + } + + UNLOCK_OBJSTORE(OP_RSA); + +malloc_err: + for (i = 6; i <= 7; i++) + { + if (a_key_template[i].pValue != NULL) + { + OPENSSL_free(a_key_template[i].pValue); + a_key_template[i].pValue = NULL; + } + } + + return (h_key); + } + +/* + * Create a private key object in the session from a given rsa structure. + * The *rsa_d_num pointer is non-NULL for RSA private keys. + */ +static CK_OBJECT_HANDLE +pk11_get_private_rsa_key(RSA *rsa, RSA **key_ptr, BIGNUM **rsa_d_num, + BIGNUM **rsa_n_num, BIGNUM **rsa_e_num, CK_SESSION_HANDLE session) + { + CK_RV rv; + CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE; + int i; + CK_ULONG found; + CK_OBJECT_CLASS o_key = CKO_PRIVATE_KEY; + CK_KEY_TYPE k_type = CKK_RSA; + CK_ULONG ul_key_attr_count = 14; + CK_BBOOL rollback = FALSE; + + /* Both CKA_TOKEN and CKA_SENSITIVE have to be FALSE for session keys */ + CK_ATTRIBUTE a_key_template[] = + { + {CKA_CLASS, (void *) NULL, sizeof (CK_OBJECT_CLASS)}, + {CKA_KEY_TYPE, (void *) NULL, sizeof (CK_KEY_TYPE)}, + {CKA_TOKEN, &myfalse, sizeof (myfalse)}, + {CKA_SENSITIVE, &myfalse, sizeof (myfalse)}, + {CKA_DECRYPT, &mytrue, sizeof (mytrue)}, + {CKA_SIGN, &mytrue, sizeof (mytrue)}, + {CKA_MODULUS, (void *)NULL, 0}, + {CKA_PUBLIC_EXPONENT, (void *)NULL, 0}, + {CKA_PRIVATE_EXPONENT, (void *)NULL, 0}, + {CKA_PRIME_1, (void *)NULL, 0}, + {CKA_PRIME_2, (void *)NULL, 0}, + {CKA_EXPONENT_1, (void *)NULL, 0}, + {CKA_EXPONENT_2, (void *)NULL, 0}, + {CKA_COEFFICIENT, (void *)NULL, 0}, + }; + + if ((rsa->flags & RSA_FLAG_EXT_PKEY) != 0) { + h_key = (CK_OBJECT_HANDLE)RSA_get_ex_data(rsa, hndidx_rsa); + LOCK_OBJSTORE(OP_RSA); + goto set; + } + + a_key_template[0].pValue = &o_key; + a_key_template[1].pValue = &k_type; + + /* Put the private key components into the template */ + if (init_template_value(rsa->n, &a_key_template[6].pValue, + &a_key_template[6].ulValueLen) == 0 || + init_template_value(rsa->e, &a_key_template[7].pValue, + &a_key_template[7].ulValueLen) == 0 || + init_template_value(rsa->d, &a_key_template[8].pValue, + &a_key_template[8].ulValueLen) == 0 || + init_template_value(rsa->p, &a_key_template[9].pValue, + &a_key_template[9].ulValueLen) == 0 || + init_template_value(rsa->q, &a_key_template[10].pValue, + &a_key_template[10].ulValueLen) == 0 || + init_template_value(rsa->dmp1, &a_key_template[11].pValue, + &a_key_template[11].ulValueLen) == 0 || + init_template_value(rsa->dmq1, &a_key_template[12].pValue, + &a_key_template[12].ulValueLen) == 0 || + init_template_value(rsa->iqmp, &a_key_template[13].pValue, + &a_key_template[13].ulValueLen) == 0) + { + PK11err(PK11_F_GET_PRIV_RSA_KEY, PK11_R_MALLOC_FAILURE); + goto malloc_err; + } + + /* see find_lock array definition for more info on object locking */ + LOCK_OBJSTORE(OP_RSA); + + /* + * We are getting the private key but the private 'd' + * component is NULL. That means this is key by reference RSA + * key. In that case, we can use only public components for + * searching for the private key handle. + */ + if (rsa->d == NULL) + { + ul_key_attr_count = 8; + /* + * We will perform the search in the token, not in the existing + * session keys. + */ + a_key_template[2].pValue = &mytrue; + } + + rv = pFuncList->C_FindObjectsInit(session, a_key_template, + ul_key_attr_count); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PRIV_RSA_KEY, + PK11_R_FINDOBJECTSINIT, rv); + goto err; + } + + rv = pFuncList->C_FindObjects(session, &h_key, 1, &found); + + if (rv != CKR_OK) + { + (void) pFuncList->C_FindObjectsFinal(session); + PK11err_add_data(PK11_F_GET_PRIV_RSA_KEY, + PK11_R_FINDOBJECTS, rv); + goto err; + } + + rv = pFuncList->C_FindObjectsFinal(session); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PRIV_RSA_KEY, + PK11_R_FINDOBJECTSFINAL, rv); + goto err; + } + + if (found == 0) + { + /* + * We have an RSA structure with 'n'/'e' components + * only so we tried to find the private key in the + * keystore. If it was really a token key we have a + * problem. Note that for other key types we just + * create a new session key using the private + * components from the RSA structure. + */ + if (rsa->d == NULL) + { + PK11err(PK11_F_GET_PRIV_RSA_KEY, + PK11_R_PRIV_KEY_NOT_FOUND); + goto err; + } + + rv = pFuncList->C_CreateObject(session, + a_key_template, ul_key_attr_count, &h_key); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PRIV_RSA_KEY, + PK11_R_CREATEOBJECT, rv); + goto err; + } + } + +set: + if (rsa_d_num != NULL) + { + /* + * When RSA keys by reference code is used, we never + * extract private components from the keystore. In + * that case 'd' was set to NULL and we expect the + * application to properly cope with that. It is + * documented in openssl(5). In general, if keys by + * reference are used we expect it to be used + * exclusively using the high level API and then there + * is no problem. If the application expects the + * private components to be read from the keystore + * then that is not a supported way of usage. + */ + if (rsa->d != NULL && (*rsa_d_num = BN_dup(rsa->d)) == NULL) + { + PK11err(PK11_F_GET_PRIV_RSA_KEY, PK11_R_MALLOC_FAILURE); + rollback = TRUE; + goto err; + } + else + *rsa_d_num = NULL; + } + + /* + * For the key by reference code, we need public components as well + * since 'd' component is always NULL. For that reason, we always cache + * 'n'/'e' components as well. + */ + *rsa_n_num = BN_dup(rsa->n); + *rsa_e_num = BN_dup(rsa->e); + + /* LINTED: E_CONSTANT_CONDITION */ + KEY_HANDLE_REFHOLD(h_key, OP_RSA, FALSE, rollback, err); + if (key_ptr != NULL) + *key_ptr = rsa; + +err: + if (rollback) + { + /* + * We do not care about the return value from C_DestroyObject() + * since we are doing rollback. + */ + if (found == 0 && + (rsa->flags & RSA_FLAG_EXT_PKEY) == 0) + (void) pFuncList->C_DestroyObject(session, h_key); + h_key = CK_INVALID_HANDLE; + } + + UNLOCK_OBJSTORE(OP_RSA); + +malloc_err: + /* + * 6 to 13 entries in the key template are key components. + * They need to be freed upon exit or error. + */ + for (i = 6; i <= 13; i++) + { + if (a_key_template[i].pValue != NULL) + { + (void) memset(a_key_template[i].pValue, 0, + a_key_template[i].ulValueLen); + OPENSSL_free(a_key_template[i].pValue); + a_key_template[i].pValue = NULL; + } + } + + return (h_key); + } + +/* + * Check for cache miss and clean the object pointer and handle + * in such case. Return 1 for cache hit, 0 for cache miss. + */ +static int check_new_rsa_key_pub(PK11_SESSION *sp, const RSA *rsa) + { + /* + * Provide protection against RSA structure reuse by making the + * check for cache hit stronger. Only public components of RSA + * key matter here so it is sufficient to compare them with values + * cached in PK11_SESSION structure. + * + * We must check the handle as well since with key by reference, public + * components 'n'/'e' are cached in private keys as well. That means we + * could have a cache hit in a private key when looking for a public + * key. That would not work, you cannot have one PKCS#11 object for + * both data signing and verifying. + */ + if ((sp->opdata_rsa_pub != rsa) || + (BN_cmp(sp->opdata_rsa_n_num, rsa->n) != 0) || + (BN_cmp(sp->opdata_rsa_e_num, rsa->e) != 0) || + (sp->opdata_rsa_priv_key != CK_INVALID_HANDLE)) + { + /* + * We do not check the return value because even in case of + * failure the sp structure will have both key pointer + * and object handle cleaned and pk11_destroy_object() + * reports the failure to the OpenSSL error message buffer. + */ + (void) pk11_destroy_rsa_object_pub(sp, TRUE); + return (0); + } + return (1); + } + +/* + * Check for cache miss and clean the object pointer and handle + * in such case. Return 1 for cache hit, 0 for cache miss. + */ +static int check_new_rsa_key_priv(PK11_SESSION *sp, const RSA *rsa) + { + /* + * Provide protection against RSA structure reuse by making + * the check for cache hit stronger. Comparing public exponent + * of RSA key with value cached in PK11_SESSION structure + * should be sufficient. Note that we want to compare the + * public component since with the keys by reference + * mechanism, private components are not in the RSA + * structure. Also, see check_new_rsa_key_pub() about why we + * compare the handle as well. + */ + if ((sp->opdata_rsa_priv != rsa) || + (BN_cmp(sp->opdata_rsa_pn_num, rsa->n) != 0) || + (BN_cmp(sp->opdata_rsa_pe_num, rsa->e) != 0) || + (sp->opdata_rsa_pn_num == NULL) || + (sp->opdata_rsa_pe_num == NULL) || + (sp->opdata_rsa_pub_key != CK_INVALID_HANDLE)) + { + /* + * We do not check the return value because even in case of + * failure the sp structure will have both key pointer + * and object handle cleaned and pk11_destroy_object() + * reports the failure to the OpenSSL error message buffer. + */ + (void) pk11_destroy_rsa_object_priv(sp, TRUE); + return (0); + } + return (1); + } +#endif + +#ifndef OPENSSL_NO_DSA +/* The DSA function implementation */ +/* ARGSUSED */ +static int pk11_DSA_init(DSA *dsa) + { + return (1); + } + +/* ARGSUSED */ +static int pk11_DSA_finish(DSA *dsa) + { + return (1); + } + + +static DSA_SIG * +pk11_dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa) + { + BIGNUM *r = NULL, *s = NULL; + int i; + DSA_SIG *dsa_sig = NULL; + + CK_RV rv; + CK_MECHANISM Mechanism_dsa = {CKM_DSA, NULL, 0}; + CK_MECHANISM *p_mech = &Mechanism_dsa; + CK_OBJECT_HANDLE h_priv_key; + + /* + * The signature is the concatenation of r and s, + * each is 20 bytes long + */ + unsigned char sigret[DSA_SIGNATURE_LEN]; + unsigned long siglen = DSA_SIGNATURE_LEN; + unsigned int siglen2 = DSA_SIGNATURE_LEN / 2; + + PK11_SESSION *sp = NULL; + + if ((dsa->p == NULL) || (dsa->q == NULL) || (dsa->g == NULL)) + { + PK11err(PK11_F_DSA_SIGN, PK11_R_MISSING_KEY_COMPONENT); + goto ret; + } + + i = BN_num_bytes(dsa->q); /* should be 20 */ + if (dlen > i) + { + PK11err(PK11_F_DSA_SIGN, PK11_R_INVALID_SIGNATURE_LENGTH); + goto ret; + } + + if ((sp = pk11_get_session(OP_DSA)) == NULL) + goto ret; + + (void) check_new_dsa_key_priv(sp, dsa); + + h_priv_key = sp->opdata_dsa_priv_key; + if (h_priv_key == CK_INVALID_HANDLE) + h_priv_key = sp->opdata_dsa_priv_key = + pk11_get_private_dsa_key((DSA *)dsa, + &sp->opdata_dsa_priv, + &sp->opdata_dsa_priv_num, sp->session); + + if (h_priv_key != CK_INVALID_HANDLE) + { + rv = pFuncList->C_SignInit(sp->session, p_mech, h_priv_key); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DSA_SIGN, PK11_R_SIGNINIT, rv); + goto ret; + } + + (void) memset(sigret, 0, siglen); + rv = pFuncList->C_Sign(sp->session, + (unsigned char*) dgst, dlen, sigret, + (CK_ULONG_PTR) &siglen); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DSA_SIGN, PK11_R_SIGN, rv); + goto ret; + } + } + + + if ((s = BN_new()) == NULL) + { + PK11err(PK11_F_DSA_SIGN, PK11_R_MALLOC_FAILURE); + goto ret; + } + + if ((r = BN_new()) == NULL) + { + PK11err(PK11_F_DSA_SIGN, PK11_R_MALLOC_FAILURE); + goto ret; + } + + if ((dsa_sig = DSA_SIG_new()) == NULL) + { + PK11err(PK11_F_DSA_SIGN, PK11_R_MALLOC_FAILURE); + goto ret; + } + + if (BN_bin2bn(sigret, siglen2, r) == NULL || + BN_bin2bn(&sigret[siglen2], siglen2, s) == NULL) + { + PK11err(PK11_F_DSA_SIGN, PK11_R_MALLOC_FAILURE); + goto ret; + } + + dsa_sig->r = r; + dsa_sig->s = s; + +ret: + if (dsa_sig == NULL) + { + if (r != NULL) + BN_free(r); + if (s != NULL) + BN_free(s); + } + + pk11_return_session(sp, OP_DSA); + return (dsa_sig); + } + +static int +pk11_dsa_do_verify(const unsigned char *dgst, int dlen, DSA_SIG *sig, + DSA *dsa) + { + int i; + CK_RV rv; + int retval = 0; + CK_MECHANISM Mechanism_dsa = {CKM_DSA, NULL, 0}; + CK_MECHANISM *p_mech = &Mechanism_dsa; + CK_OBJECT_HANDLE h_pub_key; + + unsigned char sigbuf[DSA_SIGNATURE_LEN]; + unsigned long siglen = DSA_SIGNATURE_LEN; + unsigned long siglen2 = DSA_SIGNATURE_LEN/2; + + PK11_SESSION *sp = NULL; + + if (BN_is_zero(sig->r) || sig->r->neg || BN_ucmp(sig->r, dsa->q) >= 0) + { + PK11err(PK11_F_DSA_VERIFY, + PK11_R_INVALID_DSA_SIGNATURE_R); + goto ret; + } + + if (BN_is_zero(sig->s) || sig->s->neg || BN_ucmp(sig->s, dsa->q) >= 0) + { + PK11err(PK11_F_DSA_VERIFY, + PK11_R_INVALID_DSA_SIGNATURE_S); + goto ret; + } + + i = BN_num_bytes(dsa->q); /* should be 20 */ + + if (dlen > i) + { + PK11err(PK11_F_DSA_VERIFY, + PK11_R_INVALID_SIGNATURE_LENGTH); + goto ret; + } + + if ((sp = pk11_get_session(OP_DSA)) == NULL) + goto ret; + + (void) check_new_dsa_key_pub(sp, dsa); + + h_pub_key = sp->opdata_dsa_pub_key; + if (h_pub_key == CK_INVALID_HANDLE) + h_pub_key = sp->opdata_dsa_pub_key = + pk11_get_public_dsa_key((DSA *)dsa, &sp->opdata_dsa_pub, + &sp->opdata_dsa_pub_num, sp->session); + + if (h_pub_key != CK_INVALID_HANDLE) + { + rv = pFuncList->C_VerifyInit(sp->session, p_mech, + h_pub_key); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DSA_VERIFY, PK11_R_VERIFYINIT, + rv); + goto ret; + } + + /* + * The representation of each of the two big numbers could + * be shorter than DSA_SIGNATURE_LEN/2 bytes so we need + * to act accordingly and shift if necessary. + */ + (void) memset(sigbuf, 0, siglen); + BN_bn2bin(sig->r, sigbuf + siglen2 - BN_num_bytes(sig->r)); + BN_bn2bin(sig->s, &sigbuf[siglen2] + siglen2 - + BN_num_bytes(sig->s)); + + rv = pFuncList->C_Verify(sp->session, + (unsigned char *) dgst, dlen, sigbuf, (CK_ULONG)siglen); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DSA_VERIFY, PK11_R_VERIFY, rv); + goto ret; + } + } + + retval = 1; +ret: + + pk11_return_session(sp, OP_DSA); + return (retval); + } + + +/* + * Create a public key object in a session from a given dsa structure. + * The *dsa_pub_num pointer is non-NULL for DSA public keys. + */ +static CK_OBJECT_HANDLE pk11_get_public_dsa_key(DSA* dsa, + DSA **key_ptr, BIGNUM **dsa_pub_num, CK_SESSION_HANDLE session) + { + CK_RV rv; + CK_OBJECT_CLASS o_key = CKO_PUBLIC_KEY; + CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE; + CK_ULONG found; + CK_KEY_TYPE k_type = CKK_DSA; + CK_ULONG ul_key_attr_count = 8; + CK_BBOOL rollback = FALSE; + int i; + + CK_ATTRIBUTE a_key_template[] = + { + {CKA_CLASS, (void *) NULL, sizeof (CK_OBJECT_CLASS)}, + {CKA_KEY_TYPE, (void *) NULL, sizeof (CK_KEY_TYPE)}, + {CKA_TOKEN, &myfalse, sizeof (myfalse)}, + {CKA_VERIFY, &mytrue, sizeof (mytrue)}, + {CKA_PRIME, (void *)NULL, 0}, /* p */ + {CKA_SUBPRIME, (void *)NULL, 0}, /* q */ + {CKA_BASE, (void *)NULL, 0}, /* g */ + {CKA_VALUE, (void *)NULL, 0} /* pub_key - y */ + }; + + a_key_template[0].pValue = &o_key; + a_key_template[1].pValue = &k_type; + + if (init_template_value(dsa->p, &a_key_template[4].pValue, + &a_key_template[4].ulValueLen) == 0 || + init_template_value(dsa->q, &a_key_template[5].pValue, + &a_key_template[5].ulValueLen) == 0 || + init_template_value(dsa->g, &a_key_template[6].pValue, + &a_key_template[6].ulValueLen) == 0 || + init_template_value(dsa->pub_key, &a_key_template[7].pValue, + &a_key_template[7].ulValueLen) == 0) + { + PK11err(PK11_F_GET_PUB_DSA_KEY, PK11_R_MALLOC_FAILURE); + goto malloc_err; + } + + /* see find_lock array definition for more info on object locking */ + LOCK_OBJSTORE(OP_DSA); + rv = pFuncList->C_FindObjectsInit(session, a_key_template, + ul_key_attr_count); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PUB_DSA_KEY, + PK11_R_FINDOBJECTSINIT, rv); + goto err; + } + + rv = pFuncList->C_FindObjects(session, &h_key, 1, &found); + + if (rv != CKR_OK) + { + (void) pFuncList->C_FindObjectsFinal(session); + PK11err_add_data(PK11_F_GET_PUB_DSA_KEY, + PK11_R_FINDOBJECTS, rv); + goto err; + } + + rv = pFuncList->C_FindObjectsFinal(session); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PUB_DSA_KEY, + PK11_R_FINDOBJECTSFINAL, rv); + goto err; + } + + if (found == 0) + { + rv = pFuncList->C_CreateObject(session, + a_key_template, ul_key_attr_count, &h_key); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PUB_DSA_KEY, + PK11_R_CREATEOBJECT, rv); + goto err; + } + } + + if (dsa_pub_num != NULL) + if ((*dsa_pub_num = BN_dup(dsa->pub_key)) == NULL) + { + PK11err(PK11_F_GET_PUB_DSA_KEY, PK11_R_MALLOC_FAILURE); + rollback = TRUE; + goto err; + } + + /* LINTED: E_CONSTANT_CONDITION */ + KEY_HANDLE_REFHOLD(h_key, OP_DSA, FALSE, rollback, err); + if (key_ptr != NULL) + *key_ptr = dsa; + +err: + if (rollback) + { + /* + * We do not care about the return value from C_DestroyObject() + * since we are doing rollback. + */ + if (found == 0) + (void) pFuncList->C_DestroyObject(session, h_key); + h_key = CK_INVALID_HANDLE; + } + + UNLOCK_OBJSTORE(OP_DSA); + +malloc_err: + for (i = 4; i <= 7; i++) + { + if (a_key_template[i].pValue != NULL) + { + OPENSSL_free(a_key_template[i].pValue); + a_key_template[i].pValue = NULL; + } + } + + return (h_key); + } + +/* + * Create a private key object in the session from a given dsa structure + * The *dsa_priv_num pointer is non-NULL for DSA private keys. + */ +static CK_OBJECT_HANDLE pk11_get_private_dsa_key(DSA* dsa, + DSA **key_ptr, BIGNUM **dsa_priv_num, CK_SESSION_HANDLE session) + { + CK_RV rv; + CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE; + CK_OBJECT_CLASS o_key = CKO_PRIVATE_KEY; + int i; + CK_ULONG found; + CK_KEY_TYPE k_type = CKK_DSA; + CK_ULONG ul_key_attr_count = 9; + CK_BBOOL rollback = FALSE; + + /* Both CKA_TOKEN and CKA_SENSITIVE have to be FALSE for session keys */ + CK_ATTRIBUTE a_key_template[] = + { + {CKA_CLASS, (void *) NULL, sizeof (CK_OBJECT_CLASS)}, + {CKA_KEY_TYPE, (void *) NULL, sizeof (CK_KEY_TYPE)}, + {CKA_TOKEN, &myfalse, sizeof (myfalse)}, + {CKA_SENSITIVE, &myfalse, sizeof (myfalse)}, + {CKA_SIGN, &mytrue, sizeof (mytrue)}, + {CKA_PRIME, (void *)NULL, 0}, /* p */ + {CKA_SUBPRIME, (void *)NULL, 0}, /* q */ + {CKA_BASE, (void *)NULL, 0}, /* g */ + {CKA_VALUE, (void *)NULL, 0} /* priv_key - x */ + }; + + a_key_template[0].pValue = &o_key; + a_key_template[1].pValue = &k_type; + + /* Put the private key components into the template */ + if (init_template_value(dsa->p, &a_key_template[5].pValue, + &a_key_template[5].ulValueLen) == 0 || + init_template_value(dsa->q, &a_key_template[6].pValue, + &a_key_template[6].ulValueLen) == 0 || + init_template_value(dsa->g, &a_key_template[7].pValue, + &a_key_template[7].ulValueLen) == 0 || + init_template_value(dsa->priv_key, &a_key_template[8].pValue, + &a_key_template[8].ulValueLen) == 0) + { + PK11err(PK11_F_GET_PRIV_DSA_KEY, PK11_R_MALLOC_FAILURE); + goto malloc_err; + } + + /* see find_lock array definition for more info on object locking */ + LOCK_OBJSTORE(OP_DSA); + rv = pFuncList->C_FindObjectsInit(session, a_key_template, + ul_key_attr_count); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PRIV_DSA_KEY, + PK11_R_FINDOBJECTSINIT, rv); + goto err; + } + + rv = pFuncList->C_FindObjects(session, &h_key, 1, &found); + + if (rv != CKR_OK) + { + (void) pFuncList->C_FindObjectsFinal(session); + PK11err_add_data(PK11_F_GET_PRIV_DSA_KEY, + PK11_R_FINDOBJECTS, rv); + goto err; + } + + rv = pFuncList->C_FindObjectsFinal(session); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PRIV_DSA_KEY, + PK11_R_FINDOBJECTSFINAL, rv); + goto err; + } + + if (found == 0) + { + rv = pFuncList->C_CreateObject(session, + a_key_template, ul_key_attr_count, &h_key); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PRIV_DSA_KEY, + PK11_R_CREATEOBJECT, rv); + goto err; + } + } + + if (dsa_priv_num != NULL) + if ((*dsa_priv_num = BN_dup(dsa->priv_key)) == NULL) + { + PK11err(PK11_F_GET_PRIV_DSA_KEY, PK11_R_MALLOC_FAILURE); + rollback = TRUE; + goto err; + } + + /* LINTED: E_CONSTANT_CONDITION */ + KEY_HANDLE_REFHOLD(h_key, OP_DSA, FALSE, rollback, err); + if (key_ptr != NULL) + *key_ptr = dsa; + +err: + if (rollback) + { + /* + * We do not care about the return value from C_DestroyObject() + * since we are doing rollback. + */ + if (found == 0) + (void) pFuncList->C_DestroyObject(session, h_key); + h_key = CK_INVALID_HANDLE; + } + + UNLOCK_OBJSTORE(OP_DSA); + +malloc_err: + /* + * 5 to 8 entries in the key template are key components. + * They need to be freed apon exit or error. + */ + for (i = 5; i <= 8; i++) + { + if (a_key_template[i].pValue != NULL) + { + (void) memset(a_key_template[i].pValue, 0, + a_key_template[i].ulValueLen); + OPENSSL_free(a_key_template[i].pValue); + a_key_template[i].pValue = NULL; + } + } + + return (h_key); + } + +/* + * Check for cache miss and clean the object pointer and handle + * in such case. Return 1 for cache hit, 0 for cache miss. + */ +static int check_new_dsa_key_pub(PK11_SESSION *sp, DSA *dsa) + { + /* + * Provide protection against DSA structure reuse by making the + * check for cache hit stronger. Only public key component of DSA + * key matters here so it is sufficient to compare it with value + * cached in PK11_SESSION structure. + */ + if ((sp->opdata_dsa_pub != dsa) || + (BN_cmp(sp->opdata_dsa_pub_num, dsa->pub_key) != 0)) + { + /* + * We do not check the return value because even in case of + * failure the sp structure will have both key pointer + * and object handle cleaned and pk11_destroy_object() + * reports the failure to the OpenSSL error message buffer. + */ + (void) pk11_destroy_dsa_object_pub(sp, TRUE); + return (0); + } + return (1); + } + +/* + * Check for cache miss and clean the object pointer and handle + * in such case. Return 1 for cache hit, 0 for cache miss. + */ +static int check_new_dsa_key_priv(PK11_SESSION *sp, DSA *dsa) + { + /* + * Provide protection against DSA structure reuse by making the + * check for cache hit stronger. Only private key component of DSA + * key matters here so it is sufficient to compare it with value + * cached in PK11_SESSION structure. + */ + if ((sp->opdata_dsa_priv != dsa) || + (BN_cmp(sp->opdata_dsa_priv_num, dsa->priv_key) != 0)) + { + /* + * We do not check the return value because even in case of + * failure the sp structure will have both key pointer + * and object handle cleaned and pk11_destroy_object() + * reports the failure to the OpenSSL error message buffer. + */ + (void) pk11_destroy_dsa_object_priv(sp, TRUE); + return (0); + } + return (1); + } +#endif + + +#ifndef OPENSSL_NO_DH +/* The DH function implementation */ +/* ARGSUSED */ +static int pk11_DH_init(DH *dh) + { + return (1); + } + +/* ARGSUSED */ +static int pk11_DH_finish(DH *dh) + { + return (1); + } + +/* + * Generate DH key-pair. + * + * Warning: Unlike OpenSSL's DH_generate_key(3) we ignore dh->priv_key + * and override it even if it is set. OpenSSL does not touch dh->priv_key + * if set and just computes dh->pub_key. It looks like PKCS#11 standard + * is not capable of providing this functionality. This could be a problem + * for applications relying on OpenSSL's semantics. + */ +static int pk11_DH_generate_key(DH *dh) + { + CK_ULONG i; + CK_RV rv, rv1; + int reuse_mem_len = 0, ret = 0; + PK11_SESSION *sp = NULL; + CK_BYTE_PTR reuse_mem; + + CK_MECHANISM mechanism = {CKM_DH_PKCS_KEY_PAIR_GEN, NULL_PTR, 0}; + CK_OBJECT_HANDLE h_pub_key = CK_INVALID_HANDLE; + CK_OBJECT_HANDLE h_priv_key = CK_INVALID_HANDLE; + + CK_ULONG ul_pub_key_attr_count = 3; + CK_ATTRIBUTE pub_key_template[] = + { + {CKA_PRIVATE, &myfalse, sizeof (myfalse)}, + {CKA_PRIME, (void *)NULL, 0}, + {CKA_BASE, (void *)NULL, 0} + }; + + CK_ULONG ul_priv_key_attr_count = 3; + CK_ATTRIBUTE priv_key_template[] = + { + {CKA_PRIVATE, &myfalse, sizeof (myfalse)}, + {CKA_SENSITIVE, &myfalse, sizeof (myfalse)}, + {CKA_DERIVE, &mytrue, sizeof (mytrue)} + }; + + CK_ULONG pub_key_attr_result_count = 1; + CK_ATTRIBUTE pub_key_result[] = + { + {CKA_VALUE, (void *)NULL, 0} + }; + + CK_ULONG priv_key_attr_result_count = 1; + CK_ATTRIBUTE priv_key_result[] = + { + {CKA_VALUE, (void *)NULL, 0} + }; + + pub_key_template[1].ulValueLen = BN_num_bytes(dh->p); + if (pub_key_template[1].ulValueLen > 0) + { + /* + * We must not increase ulValueLen by DH_BUF_RESERVE since that + * could cause the same rounding problem. See definition of + * DH_BUF_RESERVE above. + */ + pub_key_template[1].pValue = + OPENSSL_malloc(pub_key_template[1].ulValueLen + + DH_BUF_RESERVE); + if (pub_key_template[1].pValue == NULL) + { + PK11err(PK11_F_DH_GEN_KEY, PK11_R_MALLOC_FAILURE); + goto err; + } + + i = BN_bn2bin(dh->p, pub_key_template[1].pValue); + } + else + goto err; + + pub_key_template[2].ulValueLen = BN_num_bytes(dh->g); + if (pub_key_template[2].ulValueLen > 0) + { + pub_key_template[2].pValue = + OPENSSL_malloc(pub_key_template[2].ulValueLen + + DH_BUF_RESERVE); + if (pub_key_template[2].pValue == NULL) + { + PK11err(PK11_F_DH_GEN_KEY, PK11_R_MALLOC_FAILURE); + goto err; + } + + i = BN_bn2bin(dh->g, pub_key_template[2].pValue); + } + else + goto err; + + /* + * Note: we are only using PK11_SESSION structure for getting + * a session handle. The objects created in this function are + * destroyed before return and thus not cached. + */ + if ((sp = pk11_get_session(OP_DH)) == NULL) + goto err; + + rv = pFuncList->C_GenerateKeyPair(sp->session, + &mechanism, + pub_key_template, + ul_pub_key_attr_count, + priv_key_template, + ul_priv_key_attr_count, + &h_pub_key, + &h_priv_key); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DH_GEN_KEY, PK11_R_GEN_KEY, rv); + goto err; + } + + /* + * Reuse the larger memory allocated. We know the larger memory + * should be sufficient for reuse. + */ + if (pub_key_template[1].ulValueLen > pub_key_template[2].ulValueLen) + { + reuse_mem = pub_key_template[1].pValue; + reuse_mem_len = pub_key_template[1].ulValueLen + DH_BUF_RESERVE; + } + else + { + reuse_mem = pub_key_template[2].pValue; + reuse_mem_len = pub_key_template[2].ulValueLen + DH_BUF_RESERVE; + } + + rv = pFuncList->C_GetAttributeValue(sp->session, h_pub_key, + pub_key_result, pub_key_attr_result_count); + rv1 = pFuncList->C_GetAttributeValue(sp->session, h_priv_key, + priv_key_result, priv_key_attr_result_count); + + if (rv != CKR_OK || rv1 != CKR_OK) + { + rv = (rv != CKR_OK) ? rv : rv1; + PK11err_add_data(PK11_F_DH_GEN_KEY, + PK11_R_GETATTRIBUTVALUE, rv); + goto err; + } + + if (((CK_LONG) pub_key_result[0].ulValueLen) <= 0 || + ((CK_LONG) priv_key_result[0].ulValueLen) <= 0) + { + PK11err(PK11_F_DH_GEN_KEY, PK11_R_GETATTRIBUTVALUE); + goto err; + } + + /* Reuse the memory allocated */ + pub_key_result[0].pValue = reuse_mem; + pub_key_result[0].ulValueLen = reuse_mem_len; + + rv = pFuncList->C_GetAttributeValue(sp->session, h_pub_key, + pub_key_result, pub_key_attr_result_count); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DH_GEN_KEY, + PK11_R_GETATTRIBUTVALUE, rv); + goto err; + } + + if (pub_key_result[0].type == CKA_VALUE) + { + if (dh->pub_key == NULL) + if ((dh->pub_key = BN_new()) == NULL) + { + PK11err(PK11_F_DH_GEN_KEY, + PK11_R_MALLOC_FAILURE); + goto err; + } + dh->pub_key = BN_bin2bn(pub_key_result[0].pValue, + pub_key_result[0].ulValueLen, dh->pub_key); + if (dh->pub_key == NULL) + { + PK11err(PK11_F_DH_GEN_KEY, PK11_R_MALLOC_FAILURE); + goto err; + } + } + + /* Reuse the memory allocated */ + priv_key_result[0].pValue = reuse_mem; + priv_key_result[0].ulValueLen = reuse_mem_len; + + rv = pFuncList->C_GetAttributeValue(sp->session, h_priv_key, + priv_key_result, priv_key_attr_result_count); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DH_GEN_KEY, + PK11_R_GETATTRIBUTVALUE, rv); + goto err; + } + + if (priv_key_result[0].type == CKA_VALUE) + { + if (dh->priv_key == NULL) + if ((dh->priv_key = BN_new()) == NULL) + { + PK11err(PK11_F_DH_GEN_KEY, + PK11_R_MALLOC_FAILURE); + goto err; + } + dh->priv_key = BN_bin2bn(priv_key_result[0].pValue, + priv_key_result[0].ulValueLen, dh->priv_key); + if (dh->priv_key == NULL) + { + PK11err(PK11_F_DH_GEN_KEY, PK11_R_MALLOC_FAILURE); + goto err; + } + } + + ret = 1; + +err: + + if (h_pub_key != CK_INVALID_HANDLE) + { + rv = pFuncList->C_DestroyObject(sp->session, h_pub_key); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DH_GEN_KEY, + PK11_R_DESTROYOBJECT, rv); + } + } + + if (h_priv_key != CK_INVALID_HANDLE) + { + rv = pFuncList->C_DestroyObject(sp->session, h_priv_key); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DH_GEN_KEY, + PK11_R_DESTROYOBJECT, rv); + } + } + + for (i = 1; i <= 2; i++) + { + if (pub_key_template[i].pValue != NULL) + { + OPENSSL_free(pub_key_template[i].pValue); + pub_key_template[i].pValue = NULL; + } + } + + pk11_return_session(sp, OP_DH); + return (ret); + } + +static int pk11_DH_compute_key(unsigned char *key, const BIGNUM *pub_key, + DH *dh) + { + unsigned int i; + CK_MECHANISM mechanism = {CKM_DH_PKCS_DERIVE, NULL_PTR, 0}; + CK_OBJECT_CLASS key_class = CKO_SECRET_KEY; + CK_KEY_TYPE key_type = CKK_GENERIC_SECRET; + CK_OBJECT_HANDLE h_derived_key = CK_INVALID_HANDLE; + CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE; + + CK_ULONG seclen; + CK_ULONG ul_priv_key_attr_count = 3; + CK_ATTRIBUTE priv_key_template[] = + { + {CKA_CLASS, (void*) NULL, sizeof (key_class)}, + {CKA_KEY_TYPE, (void*) NULL, sizeof (key_type)}, + {CKA_VALUE_LEN, &seclen, sizeof (seclen)}, + }; + + CK_ULONG priv_key_attr_result_count = 1; + CK_ATTRIBUTE priv_key_result[] = + { + {CKA_VALUE, (void *)NULL, 0} + }; + + CK_RV rv; + int ret = -1; + PK11_SESSION *sp = NULL; + + if (dh->priv_key == NULL) + goto err; + + priv_key_template[0].pValue = &key_class; + priv_key_template[1].pValue = &key_type; + seclen = BN_num_bytes(dh->p); + + if ((sp = pk11_get_session(OP_DH)) == NULL) + goto err; + + mechanism.ulParameterLen = BN_num_bytes(pub_key); + mechanism.pParameter = OPENSSL_malloc(mechanism.ulParameterLen); + if (mechanism.pParameter == NULL) + { + PK11err(PK11_F_DH_COMP_KEY, PK11_R_MALLOC_FAILURE); + goto err; + } + BN_bn2bin(pub_key, mechanism.pParameter); + + (void) check_new_dh_key(sp, dh); + + h_key = sp->opdata_dh_key; + if (h_key == CK_INVALID_HANDLE) + h_key = sp->opdata_dh_key = + pk11_get_dh_key((DH*) dh, &sp->opdata_dh, + &sp->opdata_dh_priv_num, sp->session); + + if (h_key == CK_INVALID_HANDLE) + { + PK11err(PK11_F_DH_COMP_KEY, PK11_R_CREATEOBJECT); + goto err; + } + + rv = pFuncList->C_DeriveKey(sp->session, + &mechanism, + h_key, + priv_key_template, + ul_priv_key_attr_count, + &h_derived_key); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DH_COMP_KEY, PK11_R_DERIVEKEY, rv); + goto err; + } + + rv = pFuncList->C_GetAttributeValue(sp->session, h_derived_key, + priv_key_result, priv_key_attr_result_count); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DH_COMP_KEY, PK11_R_GETATTRIBUTVALUE, + rv); + goto err; + } + + if (((CK_LONG) priv_key_result[0].ulValueLen) <= 0) + { + PK11err(PK11_F_DH_COMP_KEY, PK11_R_GETATTRIBUTVALUE); + goto err; + } + priv_key_result[0].pValue = + OPENSSL_malloc(priv_key_result[0].ulValueLen); + if (!priv_key_result[0].pValue) + { + PK11err(PK11_F_DH_COMP_KEY, PK11_R_MALLOC_FAILURE); + goto err; + } + + rv = pFuncList->C_GetAttributeValue(sp->session, h_derived_key, + priv_key_result, priv_key_attr_result_count); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DH_COMP_KEY, PK11_R_GETATTRIBUTVALUE, + rv); + goto err; + } + + /* + * OpenSSL allocates the output buffer 'key' which is the same + * length of the public key. It is long enough for the derived key + */ + if (priv_key_result[0].type == CKA_VALUE) + { + /* + * CKM_DH_PKCS_DERIVE mechanism is not supposed to strip + * leading zeros from a computed shared secret. However, + * OpenSSL always did it so we must do the same here. The + * vagueness of the spec regarding leading zero bytes was + * finally cleared with TLS 1.1 (RFC 4346) saying that leading + * zeros are stripped before the computed data is used as the + * pre-master secret. + */ + for (i = 0; i < priv_key_result[0].ulValueLen; ++i) + { + if (((char *)priv_key_result[0].pValue)[i] != 0) + break; + } + + (void) memcpy(key, ((char *)priv_key_result[0].pValue) + i, + priv_key_result[0].ulValueLen - i); + ret = priv_key_result[0].ulValueLen - i; + } + +err: + + if (h_derived_key != CK_INVALID_HANDLE) + { + rv = pFuncList->C_DestroyObject(sp->session, h_derived_key); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DH_COMP_KEY, + PK11_R_DESTROYOBJECT, rv); + } + } + if (priv_key_result[0].pValue) + { + OPENSSL_free(priv_key_result[0].pValue); + priv_key_result[0].pValue = NULL; + } + + if (mechanism.pParameter) + { + OPENSSL_free(mechanism.pParameter); + mechanism.pParameter = NULL; + } + + pk11_return_session(sp, OP_DH); + return (ret); + } + + +static CK_OBJECT_HANDLE pk11_get_dh_key(DH* dh, + DH **key_ptr, BIGNUM **dh_priv_num, CK_SESSION_HANDLE session) + { + CK_RV rv; + CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE; + CK_OBJECT_CLASS class = CKO_PRIVATE_KEY; + CK_KEY_TYPE key_type = CKK_DH; + CK_ULONG found; + CK_BBOOL rollback = FALSE; + int i; + + CK_ULONG ul_key_attr_count = 7; + CK_ATTRIBUTE key_template[] = + { + {CKA_CLASS, (void*) NULL, sizeof (class)}, + {CKA_KEY_TYPE, (void*) NULL, sizeof (key_type)}, + {CKA_DERIVE, &mytrue, sizeof (mytrue)}, + {CKA_PRIVATE, &myfalse, sizeof (myfalse)}, + {CKA_PRIME, (void *) NULL, 0}, + {CKA_BASE, (void *) NULL, 0}, + {CKA_VALUE, (void *) NULL, 0}, + }; + + key_template[0].pValue = &class; + key_template[1].pValue = &key_type; + + key_template[4].ulValueLen = BN_num_bytes(dh->p); + key_template[4].pValue = (CK_VOID_PTR)OPENSSL_malloc( + (size_t)key_template[4].ulValueLen); + if (key_template[4].pValue == NULL) + { + PK11err(PK11_F_GET_DH_KEY, PK11_R_MALLOC_FAILURE); + goto malloc_err; + } + + BN_bn2bin(dh->p, key_template[4].pValue); + + key_template[5].ulValueLen = BN_num_bytes(dh->g); + key_template[5].pValue = (CK_VOID_PTR)OPENSSL_malloc( + (size_t)key_template[5].ulValueLen); + if (key_template[5].pValue == NULL) + { + PK11err(PK11_F_GET_DH_KEY, PK11_R_MALLOC_FAILURE); + goto malloc_err; + } + + BN_bn2bin(dh->g, key_template[5].pValue); + + key_template[6].ulValueLen = BN_num_bytes(dh->priv_key); + key_template[6].pValue = (CK_VOID_PTR)OPENSSL_malloc( + (size_t)key_template[6].ulValueLen); + if (key_template[6].pValue == NULL) + { + PK11err(PK11_F_GET_DH_KEY, PK11_R_MALLOC_FAILURE); + goto malloc_err; + } + + BN_bn2bin(dh->priv_key, key_template[6].pValue); + + /* see find_lock array definition for more info on object locking */ + LOCK_OBJSTORE(OP_DH); + rv = pFuncList->C_FindObjectsInit(session, key_template, + ul_key_attr_count); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_DH_KEY, PK11_R_FINDOBJECTSINIT, rv); + goto err; + } + + rv = pFuncList->C_FindObjects(session, &h_key, 1, &found); + + if (rv != CKR_OK) + { + (void) pFuncList->C_FindObjectsFinal(session); + PK11err_add_data(PK11_F_GET_DH_KEY, PK11_R_FINDOBJECTS, rv); + goto err; + } + + rv = pFuncList->C_FindObjectsFinal(session); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_DH_KEY, PK11_R_FINDOBJECTSFINAL, + rv); + goto err; + } + + if (found == 0) + { + rv = pFuncList->C_CreateObject(session, + key_template, ul_key_attr_count, &h_key); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_DH_KEY, PK11_R_CREATEOBJECT, + rv); + goto err; + } + } + + if (dh_priv_num != NULL) + if ((*dh_priv_num = BN_dup(dh->priv_key)) == NULL) + { + PK11err(PK11_F_GET_DH_KEY, PK11_R_MALLOC_FAILURE); + rollback = TRUE; + goto err; + } + + /* LINTED: E_CONSTANT_CONDITION */ + KEY_HANDLE_REFHOLD(h_key, OP_DH, FALSE, rollback, err); + if (key_ptr != NULL) + *key_ptr = dh; + +err: + if (rollback) + { + /* + * We do not care about the return value from C_DestroyObject() + * since we are doing rollback. + */ + if (found == 0) + (void) pFuncList->C_DestroyObject(session, h_key); + h_key = CK_INVALID_HANDLE; + } + + UNLOCK_OBJSTORE(OP_DH); + +malloc_err: + for (i = 4; i <= 6; i++) + { + if (key_template[i].pValue != NULL) + { + OPENSSL_free(key_template[i].pValue); + key_template[i].pValue = NULL; + } + } + + return (h_key); + } + +/* + * Check for cache miss and clean the object pointer and handle + * in such case. Return 1 for cache hit, 0 for cache miss. + * + * Note: we rely on pk11_destroy_dh_key_objects() to set sp->opdata_dh + * to CK_INVALID_HANDLE even when it fails to destroy the object. + */ +static int check_new_dh_key(PK11_SESSION *sp, DH *dh) + { + /* + * Provide protection against DH structure reuse by making the + * check for cache hit stronger. Private key component of DH key + * is unique so it is sufficient to compare it with value cached + * in PK11_SESSION structure. + */ + if ((sp->opdata_dh != dh) || + (BN_cmp(sp->opdata_dh_priv_num, dh->priv_key) != 0)) + { + /* + * We do not check the return value because even in case of + * failure the sp structure will have both key pointer + * and object handle cleaned and pk11_destroy_object() + * reports the failure to the OpenSSL error message buffer. + */ + (void) pk11_destroy_dh_object(sp, TRUE); + return (0); + } + return (1); + } +#endif + +/* + * Local function to simplify key template population + * Return 0 -- error, 1 -- no error + */ +static int +init_template_value(BIGNUM *bn, CK_VOID_PTR *p_value, + CK_ULONG *ul_value_len) + { + CK_ULONG len = 0; + + /* + * This function can be used on non-initialized BIGNUMs. It is + * easier to check that here than individually in the callers. + */ + if (bn != NULL) + len = BN_num_bytes(bn); + + if (bn == NULL || len == 0) + return (1); + + *ul_value_len = len; + *p_value = (CK_VOID_PTR)OPENSSL_malloc((size_t)*ul_value_len); + if (*p_value == NULL) + return (0); + + BN_bn2bin(bn, *p_value); + + return (1); + } + +static void +attr_to_BN(CK_ATTRIBUTE_PTR attr, CK_BYTE attr_data[], BIGNUM **bn) + { + if (attr->ulValueLen > 0) + *bn = BN_bin2bn(attr_data, attr->ulValueLen, NULL); + } + +/* + * Find one object in the token. It is an error if we can not find the + * object or if we find more objects based on the template we got. + * Assume object store locked. + * + * Returns: + * 1 OK + * 0 no object or more than 1 object found + */ +static int +find_one_object(PK11_OPTYPE op, CK_SESSION_HANDLE s, + CK_ATTRIBUTE_PTR ptempl, CK_ULONG nattr, CK_OBJECT_HANDLE_PTR pkey) + { + CK_RV rv; + CK_ULONG objcnt; + + if ((rv = pFuncList->C_FindObjectsInit(s, ptempl, nattr)) != CKR_OK) + { + PK11err_add_data(PK11_F_FIND_ONE_OBJECT, + PK11_R_FINDOBJECTSINIT, rv); + return (0); + } + + rv = pFuncList->C_FindObjects(s, pkey, 1, &objcnt); + if (rv != CKR_OK) + { + (void) pFuncList->C_FindObjectsFinal(s); + PK11err_add_data(PK11_F_FIND_ONE_OBJECT, PK11_R_FINDOBJECTS, + rv); + return (0); + } + + (void) pFuncList->C_FindObjectsFinal(s); + + if (objcnt > 1) + { + PK11err(PK11_F_FIND_ONE_OBJECT, + PK11_R_MORE_THAN_ONE_OBJECT_FOUND); + return (0); + } + else if (objcnt == 0) + { + PK11err(PK11_F_FIND_ONE_OBJECT, PK11_R_NO_OBJECT_FOUND); + return (0); + } + return (1); + } + +/* from uri stuff */ + +extern char *pk11_pin; + +static int pk11_get_pin(void); + +static int +pk11_get_pin(void) +{ + char *pin; + + /* The getpassphrase() function is not MT safe. */ +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_lock(token_lock) == 0); +#else + CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); +#endif + pin = getpassphrase("Enter PIN: "); + if (pin == NULL) + { + PK11err(PK11_F_GET_PIN, PK11_R_COULD_NOT_READ_PIN); +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0); +#else + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + return (0); + } + pk11_pin = BUF_strdup(pin); + if (pk11_pin == NULL) + { + PK11err(PK11_F_LOAD_PRIVKEY, PK11_R_MALLOC_FAILURE); +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0); +#else + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + return (0); + } + memset(pin, 0, strlen(pin)); +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0); +#else + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + return (1); + } + +/* + * Log in to the keystore if we are supposed to do that at all. Take care of + * reading and caching the PIN etc. Log in only once even when called from + * multiple threads. + * + * Returns: + * 1 on success + * 0 on failure + */ +static int +pk11_token_login(CK_SESSION_HANDLE session, CK_BBOOL *login_done, + CK_BBOOL is_private) + { + CK_RV rv; + +#if 0 + /* doesn't work on the AEP Keyper??? */ + if ((pubkey_token_flags & CKF_TOKEN_INITIALIZED) == 0) + { + PK11err(PK11_F_TOKEN_LOGIN, + PK11_R_TOKEN_NOT_INITIALIZED); + return (0); + } +#endif + + /* + * If login is required or needed but the PIN has not been + * even initialized we can bail out right now. Note that we + * are supposed to always log in if we are going to access + * private keys. However, we may need to log in even for + * accessing public keys in case that the CKF_LOGIN_REQUIRED + * flag is set. + */ + if (((pubkey_token_flags & CKF_LOGIN_REQUIRED) || + (is_private == CK_TRUE)) && + (~pubkey_token_flags & CKF_USER_PIN_INITIALIZED)) + { + PK11err(PK11_F_TOKEN_LOGIN, PK11_R_TOKEN_PIN_NOT_SET); + return (0); + } + + /* + * Note on locking: it is possible that more than one thread + * gets into pk11_get_pin() so we must deal with that. We + * cannot avoid it since we cannot guard fork() in there with + * a lock because we could end up in a dead lock in the + * child. Why? Remember we are in a multithreaded environment + * so we must lock all mutexes in the prefork function to + * avoid a situation in which a thread that did not call + * fork() held a lock, making future unlocking impossible. We + * lock right before C_Login(). + */ + if ((pubkey_token_flags & CKF_LOGIN_REQUIRED) || + (is_private == CK_TRUE)) + { + if (*login_done == CK_FALSE) + { + if ((pk11_pin == NULL) && (pk11_get_pin() == 0)) + { + PK11err(PK11_F_TOKEN_LOGIN, + PK11_R_TOKEN_PIN_NOT_PROVIDED); + return (0); + } + } + + /* + * Note that what we are logging into is the keystore from + * pubkey_SLOTID because we work with OP_RSA session type here. + * That also means that we can work with only one keystore in + * the engine. + * + * We must make sure we do not try to login more than once. + * Also, see the comment above on locking strategy. + */ + +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_lock(token_lock) == 0); +#else + CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); +#endif + if (*login_done == CK_FALSE) + { + if ((rv = pFuncList->C_Login(session, + CKU_USER, (CK_UTF8CHAR*)pk11_pin, + strlen(pk11_pin))) != CKR_OK) + { + PK11err_add_data(PK11_F_TOKEN_LOGIN, + PK11_R_TOKEN_LOGIN_FAILED, rv); + goto err_locked; + } + + *login_done = CK_TRUE; + + } +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0); +#else + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + } + else + { + /* + * If token does not require login we take it as the + * login was done. + */ + *login_done = CK_TRUE; + } + + return (1); + +err_locked: + if (pk11_pin) { + memset(pk11_pin, 0, strlen(pk11_pin)); + OPENSSL_free((void*)pk11_pin); + } + pk11_pin = NULL; +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0); +#else + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + return (0); + } + +/* + * Log in to the keystore in the child if we were logged in in the + * parent. There are similarities in the code with pk11_token_login() + * but still it is quite different so we need a separate function for + * this. + * + * Note that this function is called under the locked session mutex when fork is + * detected. That means that C_Login() will be called from the child just once. + * + * Returns: + * 1 on success + * 0 on failure + */ +int +pk11_token_relogin(CK_SESSION_HANDLE session) + { + CK_RV rv; + + if ((pk11_pin == NULL) && (pk11_get_pin() == 0)) + return (0); + +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_lock(token_lock) == 0); +#else + CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); +#endif + if ((rv = pFuncList->C_Login(session, CKU_USER, + (CK_UTF8CHAR_PTR)pk11_pin, strlen(pk11_pin))) != CKR_OK) + { + PK11err_add_data(PK11_F_TOKEN_RELOGIN, + PK11_R_TOKEN_LOGIN_FAILED, rv); +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0); +#else + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + return (0); + } +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0); +#else + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + + return (1); + } + +#ifdef OPENSSL_SYS_WIN32 +char *getpassphrase(const char *prompt) + { + static char buf[128]; + HANDLE h; + DWORD cc, mode; + int cnt; + + h = GetStdHandle(STD_INPUT_HANDLE); + fputs(prompt, stderr); + fflush(stderr); + fflush(stdout); + FlushConsoleInputBuffer(h); + GetConsoleMode(h, &mode); + SetConsoleMode(h, ENABLE_PROCESSED_INPUT); + + for (cnt = 0; cnt < sizeof(buf) - 1; cnt++) + { + ReadFile(h, buf + cnt, 1, &cc, NULL); + if (buf[cnt] == '\r') + break; + fputc('*', stdout); + fflush(stderr); + fflush(stdout); + } + + SetConsoleMode(h, mode); + buf[cnt] = '\0'; + fputs("\n", stderr); + return buf; + } +#endif /* OPENSSL_SYS_WIN32 */ +#endif /* OPENSSL_NO_HW_PK11CA */ +#endif /* OPENSSL_NO_HW_PK11 */ +#endif /* OPENSSL_NO_HW */ Index: openssl/crypto/engine/hw_pk11ca.h diff -u /dev/null openssl/crypto/engine/hw_pk11ca.h:1.4 --- /dev/null Mon Jun 13 15:26:30 2016 +++ openssl/crypto/engine/hw_pk11ca.h Wed Jun 15 21:12:20 2011 @@ -0,0 +1,32 @@ +/* Redefine all pk11/PK11 external symbols to pk11ca/PK11CA */ + +#define token_lock pk11ca_token_lock +#define find_lock pk11ca_find_lock +#define active_list pk11ca_active_list +#define pubkey_token_flags pk11ca_pubkey_token_flags +#define pubkey_SLOTID pk11ca_pubkey_SLOTID +#define ERR_pk11_error ERR_pk11ca_error +#define PK11err_add_data PK11CAerr_add_data +#define pk11_get_session pk11ca_get_session +#define pk11_return_session pk11ca_return_session +#define pk11_active_add pk11ca_active_add +#define pk11_active_delete pk11ca_active_delete +#define pk11_active_remove pk11ca_active_remove +#define pk11_free_active_list pk11ca_free_active_list +#define pk11_destroy_rsa_key_objects pk11ca_destroy_rsa_key_objects +#define pk11_destroy_rsa_object_pub pk11ca_destroy_rsa_object_pub +#define pk11_destroy_rsa_object_priv pk11ca_destroy_rsa_object_priv +#define pk11_load_privkey pk11ca_load_privkey +#define pk11_load_pubkey pk11ca_load_pubkey +#define PK11_RSA PK11CA_RSA +#define pk11_destroy_dsa_key_objects pk11ca_destroy_dsa_key_objects +#define pk11_destroy_dsa_object_pub pk11ca_destroy_dsa_object_pub +#define pk11_destroy_dsa_object_priv pk11ca_destroy_dsa_object_priv +#define PK11_DSA PK11CA_DSA +#define pk11_destroy_dh_key_objects pk11ca_destroy_dh_key_objects +#define pk11_destroy_dh_object pk11ca_destroy_dh_object +#define PK11_DH PK11CA_DH +#define pk11_token_relogin pk11ca_token_relogin +#define pFuncList pk11ca_pFuncList +#define pk11_pin pk11ca_pin +#define ENGINE_load_pk11 ENGINE_load_pk11ca Index: openssl/crypto/engine/hw_pk11so.c diff -u /dev/null openssl/crypto/engine/hw_pk11so.c:1.8 --- /dev/null Mon Jun 13 15:26:30 2016 +++ openssl/crypto/engine/hw_pk11so.c Fri Oct 4 14:05:16 2013 @@ -0,0 +1,1775 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* crypto/engine/hw_pk11.c */ +/* + * This product includes software developed by the OpenSSL Project for + * use in the OpenSSL Toolkit (http://www.openssl.org/). + * + * This project also referenced hw_pkcs11-0.9.7b.patch written by + * Afchine Madjlessi. + */ +/* + * ==================================================================== + * Copyright (c) 2000-2001 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +/* Modified to keep only RNG and RSA Sign */ + +#ifdef OPENSSL_NO_RSA +#error RSA is disabled +#endif + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef OPENSSL_SYS_WIN32 +typedef int pid_t; +#define getpid() GetCurrentProcessId() +#define NOPTHREADS +#ifndef NULL_PTR +#define NULL_PTR NULL +#endif +#define CK_DEFINE_FUNCTION(returnType, name) \ + returnType __declspec(dllexport) name +#define CK_DECLARE_FUNCTION(returnType, name) \ + returnType __declspec(dllimport) name +#define CK_DECLARE_FUNCTION_POINTER(returnType, name) \ + returnType __declspec(dllimport) (* name) +#else +#include +#include +#include +#endif + +/* Debug mutexes */ +/*#undef DEBUG_MUTEX */ +#define DEBUG_MUTEX + +#ifndef NOPTHREADS +/* for pthread error check on Linuxes */ +#ifdef DEBUG_MUTEX +#define __USE_UNIX98 +#endif +#include +#endif + +#ifndef OPENSSL_NO_HW +#ifndef OPENSSL_NO_HW_PK11 +#ifndef OPENSSL_NO_HW_PK11SO + +/* label for debug messages printed on stderr */ +#define PK11_DBG "PKCS#11 ENGINE DEBUG" +/* prints a lot of debug messages on stderr about slot selection process */ +/*#undef DEBUG_SLOT_SELECTION */ + +#ifndef OPENSSL_NO_DSA +#define OPENSSL_NO_DSA +#endif +#ifndef OPENSSL_NO_DH +#define OPENSSL_NO_DH +#endif + +#ifdef OPENSSL_SYS_WIN32 +#pragma pack(push, cryptoki, 1) +#include "cryptoki.h" +#include "pkcs11.h" +#pragma pack(pop, cryptoki) +#else +#include "cryptoki.h" +#include "pkcs11.h" +#endif +#include "hw_pk11so.h" +#include "hw_pk11_err.c" + +/* + * We use this lock to prevent multiple C_Login()s, guard getpassphrase(), + * uri_struct manipulation, and static token info. All of that is used by the + * RSA keys by reference feature. + */ +#ifndef NOPTHREADS +pthread_mutex_t *token_lock; +#endif + +/* PKCS#11 session caches and their locks for all operation types */ +static PK11_CACHE session_cache[OP_MAX]; + +/* + * We cache the flags so that we do not have to run C_GetTokenInfo() again when + * logging into the token. + */ +CK_FLAGS pubkey_token_flags; + +/* + * As stated in v2.20, 11.7 Object Management Function, in section for + * C_FindObjectsInit(), at most one search operation may be active at a given + * time in a given session. Therefore, C_Find{,Init,Final}Objects() should be + * grouped together to form one atomic search operation. This is already + * ensured by the property of unique PKCS#11 session handle used for each + * PK11_SESSION object. + * + * This is however not the biggest concern - maintaining consistency of the + * underlying object store is more important. The same section of the spec also + * says that one thread can be in the middle of a search operation while another + * thread destroys the object matching the search template which would result in + * invalid handle returned from the search operation. + * + * Hence, the following locks are used for both protection of the object stores. + * They are also used for active list protection. + */ +#ifndef NOPTHREADS +pthread_mutex_t *find_lock[OP_MAX] = { NULL }; +#endif + +/* + * lists of asymmetric key handles which are active (referenced by at least one + * PK11_SESSION structure, either held by a thread or present in free_session + * list) for given algorithm type + */ +PK11_active *active_list[OP_MAX] = { NULL }; + +/* + * Create all secret key objects in a global session so that they are available + * to use for other sessions. These other sessions may be opened or closed + * without losing the secret key objects. + */ +static CK_SESSION_HANDLE global_session = CK_INVALID_HANDLE; + +/* ENGINE level stuff */ +static int pk11_init(ENGINE *e); +static int pk11_library_init(ENGINE *e); +static int pk11_finish(ENGINE *e); +static int pk11_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void)); +static int pk11_destroy(ENGINE *e); + +/* RAND stuff */ +static void pk11_rand_seed(const void *buf, int num); +static void pk11_rand_add(const void *buf, int num, double add_entropy); +static void pk11_rand_cleanup(void); +static int pk11_rand_bytes(unsigned char *buf, int num); +static int pk11_rand_status(void); + +/* These functions are also used in other files */ +PK11_SESSION *pk11_get_session(PK11_OPTYPE optype); +void pk11_return_session(PK11_SESSION *sp, PK11_OPTYPE optype); + +/* active list manipulation functions used in this file */ +extern int pk11_active_delete(CK_OBJECT_HANDLE h, PK11_OPTYPE type); +extern void pk11_free_active_list(PK11_OPTYPE type); + +int pk11_destroy_rsa_key_objects(PK11_SESSION *session); +int pk11_destroy_rsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock); +int pk11_destroy_rsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock); + +/* Local helper functions */ +static int pk11_free_all_sessions(void); +static int pk11_free_session_list(PK11_OPTYPE optype); +static int pk11_setup_session(PK11_SESSION *sp, PK11_OPTYPE optype); +static int pk11_destroy_object(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE oh, + CK_BBOOL persistent); +static const char *get_PK11_LIBNAME(void); +static void free_PK11_LIBNAME(void); +static long set_PK11_LIBNAME(const char *name); + +static int pk11_choose_slots(int *any_slot_found); + +static int pk11_init_all_locks(void); +static void pk11_free_all_locks(void); + +#define TRY_OBJ_DESTROY(sp, obj_hdl, retval, uselock, alg_type, priv) \ + { \ + if (uselock) \ + LOCK_OBJSTORE(alg_type); \ + if (pk11_active_delete(obj_hdl, alg_type) == 1) \ + { \ + retval = pk11_destroy_object(sp->session, obj_hdl, \ + priv ? sp->priv_persistent : sp->pub_persistent); \ + } \ + if (uselock) \ + UNLOCK_OBJSTORE(alg_type); \ + } + +static CK_BBOOL pk11_have_rsa = CK_FALSE; +static CK_BBOOL pk11_have_random = CK_FALSE; + +/* + * Initialization function. Sets up various PKCS#11 library components. + * The definitions for control commands specific to this engine + */ +#define PK11_CMD_SO_PATH ENGINE_CMD_BASE +#define PK11_CMD_PIN (ENGINE_CMD_BASE+1) +#define PK11_CMD_SLOT (ENGINE_CMD_BASE+2) +static const ENGINE_CMD_DEFN pk11_cmd_defns[] = + { + { + PK11_CMD_SO_PATH, + "SO_PATH", + "Specifies the path to the 'pkcs#11' shared library", + ENGINE_CMD_FLAG_STRING + }, + { + PK11_CMD_PIN, + "PIN", + "Specifies the pin code", + ENGINE_CMD_FLAG_STRING + }, + { + PK11_CMD_SLOT, + "SLOT", + "Specifies the slot (default is auto select)", + ENGINE_CMD_FLAG_NUMERIC, + }, + {0, NULL, NULL, 0} + }; + + +static RAND_METHOD pk11_random = + { + pk11_rand_seed, + pk11_rand_bytes, + pk11_rand_cleanup, + pk11_rand_add, + pk11_rand_bytes, + pk11_rand_status + }; + + +/* Constants used when creating the ENGINE */ +#ifdef OPENSSL_NO_HW_PK11CA +#error "can't load both crypto-accelerator and sign-only PKCS#11 engines" +#endif +static const char *engine_pk11_id = "pkcs11"; +static const char *engine_pk11_name = "PKCS #11 engine support (sign only)"; + +CK_FUNCTION_LIST_PTR pFuncList = NULL; +static const char PK11_GET_FUNCTION_LIST[] = "C_GetFunctionList"; + +/* + * This is a static string constant for the DSO file name and the function + * symbol names to bind to. We set it in the Configure script based on whether + * this is 32 or 64 bit build. + */ +static const char def_PK11_LIBNAME[] = PK11_LIB_LOCATION; + +/* Needed in hw_pk11_pub.c as well so that's why it is not static. */ +CK_SLOT_ID pubkey_SLOTID = 0; +static CK_SLOT_ID rand_SLOTID = 0; +static CK_SLOT_ID SLOTID = 0; +char *pk11_pin = NULL; +static CK_BBOOL pk11_library_initialized = FALSE; +static CK_BBOOL pk11_atfork_initialized = FALSE; +static int pk11_pid = 0; + +static DSO *pk11_dso = NULL; + +/* allocate and initialize all locks used by the engine itself */ +static int pk11_init_all_locks(void) + { +#ifndef NOPTHREADS + int type; + pthread_mutexattr_t attr; + + if (pthread_mutexattr_init(&attr) != 0) + { + PK11err(PK11_F_INIT_ALL_LOCKS, 100); + return (0); + } + +#ifdef DEBUG_MUTEX + if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK) != 0) + { + PK11err(PK11_F_INIT_ALL_LOCKS, 101); + return (0); + } +#endif + + if ((token_lock = OPENSSL_malloc(sizeof (pthread_mutex_t))) == NULL) + goto malloc_err; + (void) pthread_mutex_init(token_lock, &attr); + + find_lock[OP_RSA] = OPENSSL_malloc(sizeof (pthread_mutex_t)); + if (find_lock[OP_RSA] == NULL) + goto malloc_err; + (void) pthread_mutex_init(find_lock[OP_RSA], &attr); + + for (type = 0; type < OP_MAX; type++) + { + session_cache[type].lock = + OPENSSL_malloc(sizeof (pthread_mutex_t)); + if (session_cache[type].lock == NULL) + goto malloc_err; + (void) pthread_mutex_init(session_cache[type].lock, &attr); + } + + return (1); + +malloc_err: + pk11_free_all_locks(); + PK11err(PK11_F_INIT_ALL_LOCKS, PK11_R_MALLOC_FAILURE); + return (0); +#else + return (1); +#endif + } + +static void pk11_free_all_locks(void) + { +#ifndef NOPTHREADS + int type; + + if (token_lock != NULL) + { + (void) pthread_mutex_destroy(token_lock); + OPENSSL_free(token_lock); + token_lock = NULL; + } + + if (find_lock[OP_RSA] != NULL) + { + (void) pthread_mutex_destroy(find_lock[OP_RSA]); + OPENSSL_free(find_lock[OP_RSA]); + find_lock[OP_RSA] = NULL; + } + + for (type = 0; type < OP_MAX; type++) + { + if (session_cache[type].lock != NULL) + { + (void) pthread_mutex_destroy(session_cache[type].lock); + OPENSSL_free(session_cache[type].lock); + session_cache[type].lock = NULL; + } + } +#endif + } + +/* + * This internal function is used by ENGINE_pk11() and "dynamic" ENGINE support. + */ +static int bind_pk11(ENGINE *e) + { + if (!pk11_library_initialized) + if (!pk11_library_init(e)) + return (0); + + if (!ENGINE_set_id(e, engine_pk11_id) || + !ENGINE_set_name(e, engine_pk11_name)) + return (0); + + if (pk11_have_rsa == CK_TRUE) + { + if (!ENGINE_set_RSA(e, PK11_RSA()) || + !ENGINE_set_load_privkey_function(e, pk11_load_privkey) || + !ENGINE_set_load_pubkey_function(e, pk11_load_pubkey)) + return (0); +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: registered RSA\n", PK11_DBG); +#endif /* DEBUG_SLOT_SELECTION */ + } + + if (pk11_have_random) + { + if (!ENGINE_set_RAND(e, &pk11_random)) + return (0); +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: registered random\n", PK11_DBG); +#endif /* DEBUG_SLOT_SELECTION */ + } + if (!ENGINE_set_init_function(e, pk11_init) || + !ENGINE_set_destroy_function(e, pk11_destroy) || + !ENGINE_set_finish_function(e, pk11_finish) || + !ENGINE_set_ctrl_function(e, pk11_ctrl) || + !ENGINE_set_cmd_defns(e, pk11_cmd_defns)) + return (0); + + /* Ensure the pk11 error handling is set up */ + ERR_load_pk11_strings(); + + return (1); + } + +/* Dynamic engine support is disabled at a higher level for Solaris */ +#ifdef ENGINE_DYNAMIC_SUPPORT +#error "dynamic engine not supported" +static int bind_helper(ENGINE *e, const char *id) + { + if (id && (strcmp(id, engine_pk11_id) != 0)) + return (0); + + if (!bind_pk11(e)) + return (0); + + return (1); + } + +IMPLEMENT_DYNAMIC_CHECK_FN() +IMPLEMENT_DYNAMIC_BIND_FN(bind_helper) + +#else +static ENGINE *engine_pk11(void) + { + ENGINE *ret = ENGINE_new(); + + if (!ret) + return (NULL); + + if (!bind_pk11(ret)) + { + ENGINE_free(ret); + return (NULL); + } + + return (ret); + } + +void +ENGINE_load_pk11(void) + { + ENGINE *e_pk11 = NULL; + + /* + * Do not use dynamic PKCS#11 library on Solaris due to + * security reasons. We will link it in statically. + */ + /* Attempt to load PKCS#11 library */ + if (!pk11_dso) + pk11_dso = DSO_load(NULL, get_PK11_LIBNAME(), NULL, 0); + + if (pk11_dso == NULL) + { + PK11err(PK11_F_LOAD, PK11_R_DSO_FAILURE); + return; + } + + e_pk11 = engine_pk11(); + if (!e_pk11) + { + DSO_free(pk11_dso); + pk11_dso = NULL; + return; + } + + /* + * At this point, the pk11 shared library is either dynamically + * loaded or statically linked in. So, initialize the pk11 + * library before calling ENGINE_set_default since the latter + * needs cipher and digest algorithm information + */ + if (!pk11_library_init(e_pk11)) + { + DSO_free(pk11_dso); + pk11_dso = NULL; + ENGINE_free(e_pk11); + return; + } + + ENGINE_add(e_pk11); + + ENGINE_free(e_pk11); + ERR_clear_error(); + } +#endif /* ENGINE_DYNAMIC_SUPPORT */ + +/* + * These are the static string constants for the DSO file name and + * the function symbol names to bind to. + */ +static const char *PK11_LIBNAME = NULL; + +static const char *get_PK11_LIBNAME(void) + { + if (PK11_LIBNAME) + return (PK11_LIBNAME); + + return (def_PK11_LIBNAME); + } + +static void free_PK11_LIBNAME(void) + { + if (PK11_LIBNAME) + OPENSSL_free((void*)PK11_LIBNAME); + + PK11_LIBNAME = NULL; + } + +static long set_PK11_LIBNAME(const char *name) + { + free_PK11_LIBNAME(); + + return ((PK11_LIBNAME = BUF_strdup(name)) != NULL ? 1 : 0); + } + +/* acquire all engine specific mutexes before fork */ +static void pk11_fork_prepare(void) + { +#ifndef NOPTHREADS + int i; + + if (!pk11_library_initialized) + return; + + LOCK_OBJSTORE(OP_RSA); + OPENSSL_assert(pthread_mutex_lock(token_lock) == 0); + for (i = 0; i < OP_MAX; i++) + { + OPENSSL_assert(pthread_mutex_lock(session_cache[i].lock) == 0); + } +#endif + } + +/* release all engine specific mutexes */ +static void pk11_fork_parent(void) + { +#ifndef NOPTHREADS + int i; + + if (!pk11_library_initialized) + return; + + for (i = OP_MAX - 1; i >= 0; i--) + { + OPENSSL_assert(pthread_mutex_unlock(session_cache[i].lock) == 0); + } + UNLOCK_OBJSTORE(OP_RSA); + OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0); +#endif + } + +/* + * same situation as in parent - we need to unlock all locks to make them + * accessible to all threads. + */ +static void pk11_fork_child(void) + { +#ifndef NOPTHREADS + int i; + + if (!pk11_library_initialized) + return; + + for (i = OP_MAX - 1; i >= 0; i--) + { + OPENSSL_assert(pthread_mutex_unlock(session_cache[i].lock) == 0); + } + UNLOCK_OBJSTORE(OP_RSA); + OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0); +#endif + } + +/* Initialization function for the pk11 engine */ +static int pk11_init(ENGINE *e) +{ + return (pk11_library_init(e)); +} + +static CK_C_INITIALIZE_ARGS pk11_init_args = + { + NULL_PTR, /* CreateMutex */ + NULL_PTR, /* DestroyMutex */ + NULL_PTR, /* LockMutex */ + NULL_PTR, /* UnlockMutex */ + CKF_OS_LOCKING_OK, /* flags */ + NULL_PTR, /* pReserved */ + }; + +/* + * Initialization function. Sets up various PKCS#11 library components. + * It selects a slot based on predefined critiera. In the process, it also + * count how many ciphers and digests to support. Since the cipher and + * digest information is needed when setting default engine, this function + * needs to be called before calling ENGINE_set_default. + */ +/* ARGSUSED */ +static int pk11_library_init(ENGINE *e) + { + CK_C_GetFunctionList p; + CK_RV rv = CKR_OK; + CK_INFO info; + int any_slot_found; + int i; +#ifndef OPENSSL_SYS_WIN32 + struct sigaction sigint_act, sigterm_act, sighup_act; +#endif + + /* + * pk11_library_initialized is set to 0 in pk11_finish() which + * is called from ENGINE_finish(). However, if there is still + * at least one existing functional reference to the engine + * (see engine(3) for more information), pk11_finish() is + * skipped. For example, this can happen if an application + * forgets to clear one cipher context. In case of a fork() + * when the application is finishing the engine so that it can + * be reinitialized in the child, forgotten functional + * reference causes pk11_library_initialized to stay 1. In + * that case we need the PID check so that we properly + * initialize the engine again. + */ + if (pk11_library_initialized) + { + if (pk11_pid == getpid()) + { + return (1); + } + else + { + global_session = CK_INVALID_HANDLE; + /* + * free the locks first to prevent memory leak in case + * the application calls fork() without finishing the + * engine first. + */ + pk11_free_all_locks(); + } + } + + if (pk11_dso == NULL) + { + PK11err(PK11_F_LIBRARY_INIT, PK11_R_DSO_FAILURE); + goto err; + } + + /* get the C_GetFunctionList function from the loaded library */ + p = (CK_C_GetFunctionList)DSO_bind_func(pk11_dso, + PK11_GET_FUNCTION_LIST); + if (!p) + { + PK11err(PK11_F_LIBRARY_INIT, PK11_R_DSO_FAILURE); + goto err; + } + + /* get the full function list from the loaded library */ + rv = p(&pFuncList); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_LIBRARY_INIT, PK11_R_DSO_FAILURE, rv); + goto err; + } + +#ifndef OPENSSL_SYS_WIN32 + /* Not all PKCS#11 library are signal safe! */ + + (void) memset(&sigint_act, 0, sizeof(sigint_act)); + (void) memset(&sigterm_act, 0, sizeof(sigterm_act)); + (void) memset(&sighup_act, 0, sizeof(sighup_act)); + (void) sigaction(SIGINT, NULL, &sigint_act); + (void) sigaction(SIGTERM, NULL, &sigterm_act); + (void) sigaction(SIGHUP, NULL, &sighup_act); +#endif + rv = pFuncList->C_Initialize((CK_VOID_PTR)&pk11_init_args); +#ifndef OPENSSL_SYS_WIN32 + (void) sigaction(SIGINT, &sigint_act, NULL); + (void) sigaction(SIGTERM, &sigterm_act, NULL); + (void) sigaction(SIGHUP, &sighup_act, NULL); +#endif + if ((rv != CKR_OK) && (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)) + { + PK11err_add_data(PK11_F_LIBRARY_INIT, PK11_R_INITIALIZE, rv); + goto err; + } + + rv = pFuncList->C_GetInfo(&info); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_LIBRARY_INIT, PK11_R_GETINFO, rv); + goto err; + } + + if (pk11_choose_slots(&any_slot_found) == 0) + goto err; + + /* + * The library we use, set in def_PK11_LIBNAME, may not offer any + * slot(s). In that case, we must not proceed but we must not return an + * error. The reason is that applications that try to set up the PKCS#11 + * engine don't exit on error during the engine initialization just + * because no slot was present. + */ + if (any_slot_found == 0) + return (1); + + if (global_session == CK_INVALID_HANDLE) + { + /* Open the global_session for the new process */ + rv = pFuncList->C_OpenSession(SLOTID, CKF_SERIAL_SESSION, + NULL_PTR, NULL_PTR, &global_session); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_LIBRARY_INIT, + PK11_R_OPENSESSION, rv); + goto err; + } + } + + pk11_library_initialized = TRUE; + pk11_pid = getpid(); + /* + * if initialization of the locks fails pk11_init_all_locks() + * will do the cleanup. + */ + if (!pk11_init_all_locks()) + goto err; + for (i = 0; i < OP_MAX; i++) + session_cache[i].head = NULL; + /* + * initialize active lists. We only use active lists + * for asymmetric ciphers. + */ + for (i = 0; i < OP_MAX; i++) + active_list[i] = NULL; + +#ifndef NOPTHREADS + if (!pk11_atfork_initialized) + { + if (pthread_atfork(pk11_fork_prepare, pk11_fork_parent, + pk11_fork_child) != 0) + { + PK11err(PK11_F_LIBRARY_INIT, PK11_R_ATFORK_FAILED); + goto err; + } + pk11_atfork_initialized = TRUE; + } +#endif + + return (1); + +err: + return (0); + } + +/* Destructor (complements the "ENGINE_pk11()" constructor) */ +/* ARGSUSED */ +static int pk11_destroy(ENGINE *e) + { + free_PK11_LIBNAME(); + ERR_unload_pk11_strings(); + if (pk11_pin) { + memset(pk11_pin, 0, strlen(pk11_pin)); + OPENSSL_free((void*)pk11_pin); + } + pk11_pin = NULL; + return (1); + } + +/* + * Termination function to clean up the session, the token, and the pk11 + * library. + */ +/* ARGSUSED */ +static int pk11_finish(ENGINE *e) + { + int i; + + if (pk11_pin) { + memset(pk11_pin, 0, strlen(pk11_pin)); + OPENSSL_free((void*)pk11_pin); + } + pk11_pin = NULL; + + if (pk11_dso == NULL) + { + PK11err(PK11_F_FINISH, PK11_R_NOT_LOADED); + goto err; + } + + OPENSSL_assert(pFuncList != NULL); + + if (pk11_free_all_sessions() == 0) + goto err; + + /* free all active lists */ + for (i = 0; i < OP_MAX; i++) + pk11_free_active_list(i); + + pFuncList->C_CloseSession(global_session); + global_session = CK_INVALID_HANDLE; + + /* + * Since we are part of a library (libcrypto.so), calling this function + * may have side-effects. + */ +#if 0 + pFuncList->C_Finalize(NULL); +#endif + + if (!DSO_free(pk11_dso)) + { + PK11err(PK11_F_FINISH, PK11_R_DSO_FAILURE); + goto err; + } + pk11_dso = NULL; + pFuncList = NULL; + pk11_library_initialized = FALSE; + pk11_pid = 0; + /* + * There is no way how to unregister atfork handlers (other than + * unloading the library) so we just free the locks. For this reason + * the atfork handlers check if the engine is initialized and bail out + * immediately if not. This is necessary in case a process finishes + * the engine before calling fork(). + */ + pk11_free_all_locks(); + + return (1); + +err: + return (0); + } + +/* Standard engine interface function to set the dynamic library path */ +/* ARGSUSED */ +static int pk11_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void)) + { + int initialized = ((pk11_dso == NULL) ? 0 : 1); + + switch (cmd) + { + case PK11_CMD_SO_PATH: + if (p == NULL) + { + PK11err(PK11_F_CTRL, ERR_R_PASSED_NULL_PARAMETER); + return (0); + } + + if (initialized) + { + PK11err(PK11_F_CTRL, PK11_R_ALREADY_LOADED); + return (0); + } + + return (set_PK11_LIBNAME((const char *)p)); + case PK11_CMD_PIN: + if (pk11_pin) { + memset(pk11_pin, 0, strlen(pk11_pin)); + OPENSSL_free((void*)pk11_pin); + } + pk11_pin = NULL; + + if (p == NULL) + { + PK11err(PK11_F_CTRL, ERR_R_PASSED_NULL_PARAMETER); + return (0); + } + + pk11_pin = BUF_strdup(p); + if (pk11_pin == NULL) + { + PK11err(PK11_F_GET_SESSION, PK11_R_MALLOC_FAILURE); + return (0); + } + return (1); + case PK11_CMD_SLOT: + SLOTID = (CK_SLOT_ID)i; +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: slot set\n", PK11_DBG); +#endif + return (1); + default: + break; + } + + PK11err(PK11_F_CTRL, PK11_R_CTRL_COMMAND_NOT_IMPLEMENTED); + + return (0); + } + + +/* Required function by the engine random interface. It does nothing here */ +static void pk11_rand_cleanup(void) + { + return; + } + +/* ARGSUSED */ +static void pk11_rand_add(const void *buf, int num, double add) + { + PK11_SESSION *sp; + + if ((sp = pk11_get_session(OP_RAND)) == NULL) + return; + + /* + * Ignore any errors (e.g. CKR_RANDOM_SEED_NOT_SUPPORTED) since + * the calling functions do not care anyway + */ + pFuncList->C_SeedRandom(sp->session, (unsigned char *) buf, num); + pk11_return_session(sp, OP_RAND); + + return; + } + +static void pk11_rand_seed(const void *buf, int num) + { + pk11_rand_add(buf, num, 0); + } + +static int pk11_rand_bytes(unsigned char *buf, int num) + { + CK_RV rv; + PK11_SESSION *sp; + + if ((sp = pk11_get_session(OP_RAND)) == NULL) + return (0); + + rv = pFuncList->C_GenerateRandom(sp->session, buf, num); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_RAND_BYTES, PK11_R_GENERATERANDOM, rv); + pk11_return_session(sp, OP_RAND); + return (0); + } + + pk11_return_session(sp, OP_RAND); + return (1); + } + +/* Required function by the engine random interface. It does nothing here */ +static int pk11_rand_status(void) + { + return (1); + } + +/* Free all BIGNUM structures from PK11_SESSION. */ +static void pk11_free_nums(PK11_SESSION *sp, PK11_OPTYPE optype) + { + switch (optype) + { + case OP_RSA: + if (sp->opdata_rsa_n_num != NULL) + { + BN_free(sp->opdata_rsa_n_num); + sp->opdata_rsa_n_num = NULL; + } + if (sp->opdata_rsa_e_num != NULL) + { + BN_free(sp->opdata_rsa_e_num); + sp->opdata_rsa_e_num = NULL; + } + if (sp->opdata_rsa_pn_num != NULL) + { + BN_free(sp->opdata_rsa_pn_num); + sp->opdata_rsa_pn_num = NULL; + } + if (sp->opdata_rsa_pe_num != NULL) + { + BN_free(sp->opdata_rsa_pe_num); + sp->opdata_rsa_pe_num = NULL; + } + if (sp->opdata_rsa_d_num != NULL) + { + BN_free(sp->opdata_rsa_d_num); + sp->opdata_rsa_d_num = NULL; + } + break; + default: + break; + } + } + +/* + * Get new PK11_SESSION structure ready for use. Every process must have + * its own freelist of PK11_SESSION structures so handle fork() here + * by destroying the old and creating new freelist. + * The returned PK11_SESSION structure is disconnected from the freelist. + */ +PK11_SESSION * +pk11_get_session(PK11_OPTYPE optype) + { + PK11_SESSION *sp = NULL, *sp1, *freelist; +#ifndef NOPTHREADS + pthread_mutex_t *freelist_lock = NULL; +#endif + static pid_t pid = 0; + pid_t new_pid; + CK_RV rv; + + switch (optype) + { + case OP_RSA: + case OP_DSA: + case OP_DH: + case OP_RAND: + case OP_DIGEST: + case OP_CIPHER: +#ifndef NOPTHREADS + freelist_lock = session_cache[optype].lock; +#endif + break; + default: + PK11err(PK11_F_GET_SESSION, + PK11_R_INVALID_OPERATION_TYPE); + return (NULL); + } +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_lock(freelist_lock) == 0); +#else + CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); +#endif + + /* + * Will use it to find out if we forked. We cannot use the PID field in + * the session structure because we could get a newly allocated session + * here, with no PID information. + */ + if (pid == 0) + pid = getpid(); + + freelist = session_cache[optype].head; + sp = freelist; + + /* + * If the free list is empty, allocate new unitialized (filled + * with zeroes) PK11_SESSION structure otherwise return first + * structure from the freelist. + */ + if (sp == NULL) + { + if ((sp = OPENSSL_malloc(sizeof (PK11_SESSION))) == NULL) + { + PK11err(PK11_F_GET_SESSION, + PK11_R_MALLOC_FAILURE); + goto err; + } + (void) memset(sp, 0, sizeof (PK11_SESSION)); + + /* + * It is a new session so it will look like a cache miss to the + * code below. So, we must not try to to destroy its members so + * mark them as unused. + */ + sp->opdata_rsa_priv_key = CK_INVALID_HANDLE; + sp->opdata_rsa_pub_key = CK_INVALID_HANDLE; + } + else + { + freelist = sp->next; + } + + /* + * Check whether we have forked. In that case, we must get rid of all + * inherited sessions and start allocating new ones. + */ + if (pid != (new_pid = getpid())) + { + pid = new_pid; + + /* + * We are a new process and thus need to free any inherited + * PK11_SESSION objects aside from the first session (sp) which + * is the only PK11_SESSION structure we will reuse (for the + * head of the list). + */ + while ((sp1 = freelist) != NULL) + { + freelist = sp1->next; + /* + * NOTE: we do not want to call pk11_free_all_sessions() + * here because it would close underlying PKCS#11 + * sessions and destroy all objects. + */ + pk11_free_nums(sp1, optype); + OPENSSL_free(sp1); + } + + /* we have to free the active list as well. */ + pk11_free_active_list(optype); + + /* Initialize the process */ + rv = pFuncList->C_Initialize((CK_VOID_PTR)&pk11_init_args); + if ((rv != CKR_OK) && (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)) + { + PK11err_add_data(PK11_F_GET_SESSION, PK11_R_INITIALIZE, + rv); + OPENSSL_free(sp); + sp = NULL; + goto err; + } + + /* + * Choose slot here since the slot table is different on this + * process. If we are here then we must have found at least one + * usable slot before so we don't need to check any_slot_found. + * See pk11_library_init()'s usage of this function for more + * information. + */ + if (pk11_choose_slots(NULL) == 0) + goto err; + + /* Open the global_session for the new process */ + rv = pFuncList->C_OpenSession(SLOTID, CKF_SERIAL_SESSION, + NULL_PTR, NULL_PTR, &global_session); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_SESSION, PK11_R_OPENSESSION, + rv); + OPENSSL_free(sp); + sp = NULL; + goto err; + } + + /* + * It is an inherited session from our parent so it needs + * re-initialization. + */ + if (pk11_setup_session(sp, optype) == 0) + { + OPENSSL_free(sp); + sp = NULL; + goto err; + } + if (pk11_token_relogin(sp->session) == 0) + { + /* + * We will keep the session in the cache list and let + * the caller cope with the situation. + */ + freelist = sp; + sp = NULL; + goto err; + } + } + + if (sp->pid == 0) + { + /* It is a new session and needs initialization. */ + if (pk11_setup_session(sp, optype) == 0) + { + OPENSSL_free(sp); + sp = NULL; + } + } + + /* set new head for the list of PK11_SESSION objects */ + session_cache[optype].head = freelist; + +err: + if (sp != NULL) + sp->next = NULL; + +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_unlock(freelist_lock) == 0); +#else + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + + return (sp); + } + + +void +pk11_return_session(PK11_SESSION *sp, PK11_OPTYPE optype) + { +#ifndef NOPTHREADS + pthread_mutex_t *freelist_lock; +#endif + PK11_SESSION *freelist; + + /* + * If this is a session from the parent it will be taken care of and + * freed in pk11_get_session() as part of the post-fork clean up the + * next time we will ask for a new session. + */ + if (sp == NULL || sp->pid != getpid()) + return; + + switch (optype) + { + case OP_RSA: + case OP_DSA: + case OP_DH: + case OP_RAND: + case OP_DIGEST: + case OP_CIPHER: +#ifndef NOPTHREADS + freelist_lock = session_cache[optype].lock; +#endif + break; + default: + PK11err(PK11_F_RETURN_SESSION, + PK11_R_INVALID_OPERATION_TYPE); + return; + } + +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_lock(freelist_lock) == 0); +#else + CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); +#endif + freelist = session_cache[optype].head; + sp->next = freelist; + session_cache[optype].head = sp; +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_unlock(freelist_lock) == 0); +#else + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + } + + +/* Destroy all objects. This function is called when the engine is finished */ +static int pk11_free_all_sessions() + { + int ret = 1; + int type; + + (void) pk11_destroy_rsa_key_objects(NULL); + + /* + * We try to release as much as we can but any error means that we will + * return 0 on exit. + */ + for (type = 0; type < OP_MAX; type++) + { + if (pk11_free_session_list(type) == 0) + ret = 0; + } + + return (ret); + } + +/* + * Destroy session structures from the linked list specified. Free as many + * sessions as possible but any failure in C_CloseSession() means that we + * return an error on return. + */ +static int pk11_free_session_list(PK11_OPTYPE optype) + { + CK_RV rv; + PK11_SESSION *sp = NULL; + PK11_SESSION *freelist = NULL; + pid_t mypid = getpid(); +#ifndef NOPTHREADS + pthread_mutex_t *freelist_lock; +#endif + int ret = 1; + + switch (optype) + { + case OP_RSA: + case OP_DSA: + case OP_DH: + case OP_RAND: + case OP_DIGEST: + case OP_CIPHER: +#ifndef NOPTHREADS + freelist_lock = session_cache[optype].lock; +#endif + break; + default: + PK11err(PK11_F_FREE_ALL_SESSIONS, + PK11_R_INVALID_OPERATION_TYPE); + return (0); + } + +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_lock(freelist_lock) == 0); +#else + CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); +#endif + freelist = session_cache[optype].head; + while ((sp = freelist) != NULL) + { + if (sp->session != CK_INVALID_HANDLE && sp->pid == mypid) + { + rv = pFuncList->C_CloseSession(sp->session); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_FREE_ALL_SESSIONS, + PK11_R_CLOSESESSION, rv); + ret = 0; + } + } + freelist = sp->next; + pk11_free_nums(sp, optype); + OPENSSL_free(sp); + } + +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_unlock(freelist_lock) == 0); +#else + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + return (ret); + } + + +static int +pk11_setup_session(PK11_SESSION *sp, PK11_OPTYPE optype) + { + CK_RV rv; + CK_SLOT_ID myslot; + + switch (optype) + { + case OP_RSA: + myslot = pubkey_SLOTID; + break; + case OP_RAND: + myslot = rand_SLOTID; + break; + default: + PK11err(PK11_F_SETUP_SESSION, + PK11_R_INVALID_OPERATION_TYPE); + return (0); + } + + sp->session = CK_INVALID_HANDLE; +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: myslot=%d optype=%d\n", PK11_DBG, myslot, optype); +#endif /* DEBUG_SLOT_SELECTION */ + rv = pFuncList->C_OpenSession(myslot, CKF_SERIAL_SESSION, + NULL_PTR, NULL_PTR, &sp->session); + if (rv == CKR_CRYPTOKI_NOT_INITIALIZED) + { + /* + * We are probably a child process so force the + * reinitialize of the session + */ + pk11_library_initialized = FALSE; + if (!pk11_library_init(NULL)) + return (0); + rv = pFuncList->C_OpenSession(myslot, CKF_SERIAL_SESSION, + NULL_PTR, NULL_PTR, &sp->session); + } + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_SETUP_SESSION, PK11_R_OPENSESSION, rv); + return (0); + } + + sp->pid = getpid(); + + if (optype == OP_RSA) + { + sp->opdata_rsa_pub_key = CK_INVALID_HANDLE; + sp->opdata_rsa_priv_key = CK_INVALID_HANDLE; + sp->opdata_rsa_pub = NULL; + sp->opdata_rsa_n_num = NULL; + sp->opdata_rsa_e_num = NULL; + sp->opdata_rsa_priv = NULL; + sp->opdata_rsa_pn_num = NULL; + sp->opdata_rsa_pe_num = NULL; + sp->opdata_rsa_d_num = NULL; + } + + /* + * We always initialize the session as containing a non-persistent + * object. The key load functions set it to persistent if that is so. + */ + sp->pub_persistent = CK_FALSE; + sp->priv_persistent = CK_FALSE; + return (1); + } + +/* Destroy RSA public key from single session. */ +int +pk11_destroy_rsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock) + { + int ret = 0; + + if (sp->opdata_rsa_pub_key != CK_INVALID_HANDLE) + { + TRY_OBJ_DESTROY(sp, sp->opdata_rsa_pub_key, + ret, uselock, OP_RSA, CK_FALSE); + sp->opdata_rsa_pub_key = CK_INVALID_HANDLE; + sp->opdata_rsa_pub = NULL; + if (sp->opdata_rsa_n_num != NULL) + { + BN_free(sp->opdata_rsa_n_num); + sp->opdata_rsa_n_num = NULL; + } + if (sp->opdata_rsa_e_num != NULL) + { + BN_free(sp->opdata_rsa_e_num); + sp->opdata_rsa_e_num = NULL; + } + } + + return (ret); + } + +/* Destroy RSA private key from single session. */ +int +pk11_destroy_rsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock) + { + int ret = 0; + + if (sp->opdata_rsa_priv_key != CK_INVALID_HANDLE) + { + TRY_OBJ_DESTROY(sp, sp->opdata_rsa_priv_key, + ret, uselock, OP_RSA, CK_TRUE); + sp->opdata_rsa_priv_key = CK_INVALID_HANDLE; + sp->opdata_rsa_priv = NULL; + if (sp->opdata_rsa_d_num != NULL) + { + BN_free(sp->opdata_rsa_d_num); + sp->opdata_rsa_d_num = NULL; + } + + /* + * For the RSA key by reference code, public components 'n'/'e' + * are the key components we use to check for the cache hit. We + * must free those as well. + */ + if (sp->opdata_rsa_pn_num != NULL) + { + BN_free(sp->opdata_rsa_pn_num); + sp->opdata_rsa_pn_num = NULL; + } + if (sp->opdata_rsa_pe_num != NULL) + { + BN_free(sp->opdata_rsa_pe_num); + sp->opdata_rsa_pe_num = NULL; + } + } + + return (ret); + } + +/* + * Destroy RSA key object wrapper. If session is NULL, try to destroy all + * objects in the free list. + */ +int +pk11_destroy_rsa_key_objects(PK11_SESSION *session) + { + int ret = 1; + PK11_SESSION *sp = NULL; + PK11_SESSION *local_free_session; + CK_BBOOL uselock = TRUE; + + if (session != NULL) + local_free_session = session; + else + { +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_lock(session_cache[OP_RSA].lock) == 0); +#else + CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); +#endif + local_free_session = session_cache[OP_RSA].head; + uselock = FALSE; + } + + /* + * go through the list of sessions and delete key objects + */ + while ((sp = local_free_session) != NULL) + { + local_free_session = sp->next; + + /* + * Do not terminate list traversal if one of the + * destroy operations fails. + */ + if (pk11_destroy_rsa_object_pub(sp, uselock) == 0) + { + ret = 0; + continue; + } + if (pk11_destroy_rsa_object_priv(sp, uselock) == 0) + { + ret = 0; + continue; + } + } + +#ifndef NOPTHREADS + if (session == NULL) + OPENSSL_assert(pthread_mutex_unlock(session_cache[OP_RSA].lock) == 0); +#else + if (session == NULL) + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + + return (ret); + } + +static int +pk11_destroy_object(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE oh, + CK_BBOOL persistent) + { + CK_RV rv; + + /* + * We never try to destroy persistent objects which are the objects + * stored in the keystore. Also, we always use read-only sessions so + * C_DestroyObject() would be returning CKR_SESSION_READ_ONLY here. + */ + if (persistent == CK_TRUE) + return (1); + + rv = pFuncList->C_DestroyObject(session, oh); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DESTROY_OBJECT, PK11_R_DESTROYOBJECT, + rv); + return (0); + } + + return (1); + } + + +/* + * Public key mechanisms optionally supported + * + * CKM_RSA_PKCS + * + * The first slot that supports at least one of those mechanisms is chosen as a + * public key slot. + * + * The output of this function is a set of global variables indicating which + * mechanisms from RSA, DSA, DH and RAND are present, and also two arrays of + * mechanisms, one for symmetric ciphers and one for digests. Also, 3 global + * variables carry information about which slot was chosen for (a) public key + * mechanisms, (b) random operations, and (c) symmetric ciphers and digests. + */ +static int +pk11_choose_slots(int *any_slot_found) + { + CK_SLOT_ID_PTR pSlotList = NULL_PTR; + CK_ULONG ulSlotCount = 0; + CK_MECHANISM_INFO mech_info; + CK_TOKEN_INFO token_info; + unsigned int i; + CK_RV rv; + CK_SLOT_ID best_slot_sofar = 0; + CK_BBOOL found_candidate_slot = CK_FALSE; + CK_SLOT_ID current_slot = 0; + + /* let's initialize the output parameter */ + if (any_slot_found != NULL) + *any_slot_found = 0; + + /* Get slot list for memory allocation */ + rv = pFuncList->C_GetSlotList(CK_FALSE, NULL_PTR, &ulSlotCount); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_CHOOSE_SLOT, PK11_R_GETSLOTLIST, rv); + return (0); + } + + /* it's not an error if we didn't find any providers */ + if (ulSlotCount == 0) + { +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: no crypto providers found\n", PK11_DBG); +#endif /* DEBUG_SLOT_SELECTION */ + return (1); + } + + pSlotList = OPENSSL_malloc(ulSlotCount * sizeof (CK_SLOT_ID)); + + if (pSlotList == NULL) + { + PK11err(PK11_F_CHOOSE_SLOT, PK11_R_MALLOC_FAILURE); + return (0); + } + + /* Get the slot list for processing */ + rv = pFuncList->C_GetSlotList(CK_FALSE, pSlotList, &ulSlotCount); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_CHOOSE_SLOT, PK11_R_GETSLOTLIST, rv); + OPENSSL_free(pSlotList); + return (0); + } + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: provider: %s\n", PK11_DBG, def_PK11_LIBNAME); + fprintf(stderr, "%s: number of slots: %d\n", PK11_DBG, ulSlotCount); + + fprintf(stderr, "%s: == checking rand slots ==\n", PK11_DBG); +#endif /* DEBUG_SLOT_SELECTION */ + for (i = 0; i < ulSlotCount; i++) + { + current_slot = pSlotList[i]; + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: checking slot: %d\n", PK11_DBG, i); +#endif /* DEBUG_SLOT_SELECTION */ + /* Check if slot has random support. */ + rv = pFuncList->C_GetTokenInfo(current_slot, &token_info); + if (rv != CKR_OK) + continue; + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: token label: %.32s\n", PK11_DBG, token_info.label); +#endif /* DEBUG_SLOT_SELECTION */ + + if (token_info.flags & CKF_RNG) + { +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: this token has CKF_RNG flag\n", PK11_DBG); +#endif /* DEBUG_SLOT_SELECTION */ + pk11_have_random = CK_TRUE; + rand_SLOTID = current_slot; + break; + } + } + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: == checking pubkey slots ==\n", PK11_DBG); +#endif /* DEBUG_SLOT_SELECTION */ + + pubkey_SLOTID = pSlotList[0]; + for (i = 0; i < ulSlotCount; i++) + { + CK_BBOOL slot_has_rsa = CK_FALSE; + current_slot = pSlotList[i]; + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: checking slot: %d\n", PK11_DBG, i); +#endif /* DEBUG_SLOT_SELECTION */ + rv = pFuncList->C_GetTokenInfo(current_slot, &token_info); + if (rv != CKR_OK) + continue; + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: token label: %.32s\n", PK11_DBG, token_info.label); +#endif /* DEBUG_SLOT_SELECTION */ + + /* + * Check if this slot is capable of signing with CKM_RSA_PKCS. + */ + rv = pFuncList->C_GetMechanismInfo(current_slot, CKM_RSA_PKCS, + &mech_info); + + if (rv == CKR_OK && ((mech_info.flags & CKF_SIGN))) + { + slot_has_rsa = CK_TRUE; + } + + if (!found_candidate_slot && slot_has_rsa) + { +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, + "%s: potential slot: %d\n", PK11_DBG, current_slot); +#endif /* DEBUG_SLOT_SELECTION */ + best_slot_sofar = current_slot; + pk11_have_rsa = slot_has_rsa; + found_candidate_slot = CK_TRUE; + /* + * Cache the flags for later use. We might + * need those if RSA keys by reference feature + * is used. + */ + pubkey_token_flags = token_info.flags; +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, + "%s: setting found_candidate_slot to CK_TRUE\n", + PK11_DBG); + fprintf(stderr, + "%s: best so far slot: %d\n", PK11_DBG, + best_slot_sofar); + fprintf(stderr, "%s: pubkey flags changed to " + "%lu.\n", PK11_DBG, pubkey_token_flags); + } + else + { + fprintf(stderr, + "%s: no rsa\n", PK11_DBG); + } +#else + } /* if */ +#endif /* DEBUG_SLOT_SELECTION */ + } /* for */ + + if (found_candidate_slot == CK_TRUE) + { + pubkey_SLOTID = best_slot_sofar; + } + + /*SLOTID = pSlotList[0];*/ + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, + "%s: chosen pubkey slot: %d\n", PK11_DBG, pubkey_SLOTID); + fprintf(stderr, + "%s: chosen rand slot: %d\n", PK11_DBG, rand_SLOTID); + fprintf(stderr, + "%s: pk11_have_rsa %d\n", PK11_DBG, pk11_have_rsa); + fprintf(stderr, + "%s: pk11_have_random %d\n", PK11_DBG, pk11_have_random); +#endif /* DEBUG_SLOT_SELECTION */ + + if (pSlotList != NULL) + OPENSSL_free(pSlotList); + + if (any_slot_found != NULL) + *any_slot_found = 1; + return (1); + } + +#endif /* OPENSSL_NO_HW_PK11SO */ +#endif /* OPENSSL_NO_HW_PK11 */ +#endif /* OPENSSL_NO_HW */ Index: openssl/crypto/engine/hw_pk11so.h diff -u /dev/null openssl/crypto/engine/hw_pk11so.h:1.4 --- /dev/null Mon Jun 13 15:26:30 2016 +++ openssl/crypto/engine/hw_pk11so.h Wed Jun 15 21:12:20 2011 @@ -0,0 +1,32 @@ +/* Redefine all pk11/PK11 external symbols to pk11so/PK11SO */ + +#define token_lock pk11so_token_lock +#define find_lock pk11so_find_lock +#define active_list pk11so_active_list +#define pubkey_token_flags pk11so_pubkey_token_flags +#define pubkey_SLOTID pk11so_pubkey_SLOTID +#define ERR_pk11_error ERR_pk11so_error +#define PK11err_add_data PK11SOerr_add_data +#define pk11_get_session pk11so_get_session +#define pk11_return_session pk11so_return_session +#define pk11_active_add pk11so_active_add +#define pk11_active_delete pk11so_active_delete +#define pk11_active_remove pk11so_active_remove +#define pk11_free_active_list pk11so_free_active_list +#define pk11_destroy_rsa_key_objects pk11so_destroy_rsa_key_objects +#define pk11_destroy_rsa_object_pub pk11so_destroy_rsa_object_pub +#define pk11_destroy_rsa_object_priv pk11so_destroy_rsa_object_priv +#define pk11_load_privkey pk11so_load_privkey +#define pk11_load_pubkey pk11so_load_pubkey +#define PK11_RSA PK11SO_RSA +#define pk11_destroy_dsa_key_objects pk11so_destroy_dsa_key_objects +#define pk11_destroy_dsa_object_pub pk11so_destroy_dsa_object_pub +#define pk11_destroy_dsa_object_priv pk11so_destroy_dsa_object_priv +#define PK11_DSA PK11SO_DSA +#define pk11_destroy_dh_key_objects pk11so_destroy_dh_key_objects +#define pk11_destroy_dh_object pk11so_destroy_dh_object +#define PK11_DH PK11SO_DH +#define pk11_token_relogin pk11so_token_relogin +#define pFuncList pk11so_pFuncList +#define pk11_pin pk11so_pin +#define ENGINE_load_pk11 ENGINE_load_pk11so Index: openssl/crypto/engine/hw_pk11so_pub.c diff -u /dev/null openssl/crypto/engine/hw_pk11so_pub.c:1.10 --- /dev/null Mon Jun 13 15:26:30 2016 +++ openssl/crypto/engine/hw_pk11so_pub.c Fri Oct 4 14:05:38 2013 @@ -0,0 +1,1642 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* crypto/engine/hw_pk11_pub.c */ +/* + * This product includes software developed by the OpenSSL Project for + * use in the OpenSSL Toolkit (http://www.openssl.org/). + * + * This project also referenced hw_pkcs11-0.9.7b.patch written by + * Afchine Madjlessi. + */ +/* + * ==================================================================== + * Copyright (c) 2000-2001 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +/* Modified to keep only RNG and RSA Sign */ + +#ifdef OPENSSL_NO_RSA +#error RSA is disabled +#endif + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef OPENSSL_SYS_WIN32 +#define NOPTHREADS +typedef int pid_t; +#define HAVE_GETPASSPHRASE +static char *getpassphrase(const char *prompt); +#ifndef NULL_PTR +#define NULL_PTR NULL +#endif +#define CK_DEFINE_FUNCTION(returnType, name) \ + returnType __declspec(dllexport) name +#define CK_DECLARE_FUNCTION(returnType, name) \ + returnType __declspec(dllimport) name +#define CK_DECLARE_FUNCTION_POINTER(returnType, name) \ + returnType __declspec(dllimport) (* name) +#else +#include +#endif + +#ifndef NOPTHREADS +#include +#endif + +#ifndef OPENSSL_NO_HW +#ifndef OPENSSL_NO_HW_PK11 +#ifndef OPENSSL_NO_HW_PK11SO + +#ifdef OPENSSL_SYS_WIN32 +#pragma pack(push, cryptoki, 1) +#include "cryptoki.h" +#include "pkcs11.h" +#pragma pack(pop, cryptoki) +#else +#include "cryptoki.h" +#include "pkcs11.h" +#endif +#include "hw_pk11so.h" +#include "hw_pk11_err.h" + +static CK_BBOOL pk11_login_done = CK_FALSE; +extern CK_SLOT_ID pubkey_SLOTID; +#ifndef NOPTHREADS +extern pthread_mutex_t *token_lock; +#endif + +#if !(defined(HAVE_GETPASSPHRASE) || (defined (__SVR4) && defined (__sun))) +#define getpassphrase(x) getpass(x) +#endif + +/* RSA stuff */ +static int pk11_RSA_sign(int type, const unsigned char *m, unsigned int m_len, + unsigned char *sigret, unsigned int *siglen, const RSA *rsa); +EVP_PKEY *pk11_load_privkey(ENGINE*, const char *privkey_file, + UI_METHOD *ui_method, void *callback_data); +EVP_PKEY *pk11_load_pubkey(ENGINE*, const char *pubkey_file, + UI_METHOD *ui_method, void *callback_data); + +static CK_OBJECT_HANDLE pk11_get_public_rsa_key(RSA* rsa, RSA** key_ptr, + BIGNUM **rsa_n_num, BIGNUM **rsa_e_num, CK_SESSION_HANDLE session); +static CK_OBJECT_HANDLE pk11_get_private_rsa_key(RSA* rsa, RSA** key_ptr, + BIGNUM **rsa_d_num, BIGNUM **rsa_n_num, BIGNUM **rsa_e_num, + CK_SESSION_HANDLE session); + +static int check_new_rsa_key_pub(PK11_SESSION *sp, const RSA *rsa); +static int check_new_rsa_key_priv(PK11_SESSION *sp, const RSA *rsa); + +static int find_one_object(PK11_OPTYPE op, CK_SESSION_HANDLE s, + CK_ATTRIBUTE_PTR ptempl, CK_ULONG nattr, CK_OBJECT_HANDLE_PTR pkey); +static int init_template_value(BIGNUM *bn, CK_VOID_PTR *pValue, + CK_ULONG *ulValueLen); +static void attr_to_BN(CK_ATTRIBUTE_PTR attr, CK_BYTE attr_data[], BIGNUM **bn); + +static int pk11_token_login(CK_SESSION_HANDLE session, CK_BBOOL *login_done, + CK_BBOOL is_private); + +/* Read mode string to be used for fopen() */ +#if SOLARIS_OPENSSL +static char *read_mode_flags = "rF"; +#else +static char *read_mode_flags = "r"; +#endif + +/* + * increment/create reference for an asymmetric key handle via active list + * manipulation. If active list operation fails, unlock (if locked), set error + * variable and jump to the specified label. + */ +#define KEY_HANDLE_REFHOLD(key_handle, alg_type, unlock, var, label) \ + { \ + if (pk11_active_add(key_handle, alg_type) < 0) \ + { \ + var = TRUE; \ + if (unlock) \ + UNLOCK_OBJSTORE(alg_type); \ + goto label; \ + } \ + } + +/* + * Find active list entry according to object handle and return pointer to the + * entry otherwise return NULL. + * + * This function presumes it is called with lock protecting the active list + * held. + */ +static PK11_active *pk11_active_find(CK_OBJECT_HANDLE h, PK11_OPTYPE type) + { + PK11_active *entry; + + for (entry = active_list[type]; entry != NULL; entry = entry->next) + if (entry->h == h) + return (entry); + + return (NULL); + } + +/* + * Search for an entry in the active list using PKCS#11 object handle as a + * search key and return refcnt of the found/created entry or -1 in case of + * failure. + * + * This function presumes it is called with lock protecting the active list + * held. + */ +int +pk11_active_add(CK_OBJECT_HANDLE h, PK11_OPTYPE type) + { + PK11_active *entry = NULL; + + if (h == CK_INVALID_HANDLE) + { + PK11err(PK11_F_ACTIVE_ADD, PK11_R_INVALID_HANDLE); + return (-1); + } + + /* search for entry in the active list */ + if ((entry = pk11_active_find(h, type)) != NULL) + entry->refcnt++; + else + { + /* not found, create new entry and add it to the list */ + entry = OPENSSL_malloc(sizeof (PK11_active)); + if (entry == NULL) + { + PK11err(PK11_F_ACTIVE_ADD, PK11_R_MALLOC_FAILURE); + return (-1); + } + entry->h = h; + entry->refcnt = 1; + entry->prev = NULL; + entry->next = NULL; + /* connect the newly created entry to the list */ + if (active_list[type] == NULL) + active_list[type] = entry; + else /* make the entry first in the list */ + { + entry->next = active_list[type]; + active_list[type]->prev = entry; + active_list[type] = entry; + } + } + + return (entry->refcnt); + } + +/* + * Remove active list entry from the list and free it. + * + * This function presumes it is called with lock protecting the active list + * held. + */ +void +pk11_active_remove(PK11_active *entry, PK11_OPTYPE type) + { + PK11_active *prev_entry; + + /* remove the entry from the list and free it */ + if ((prev_entry = entry->prev) != NULL) + { + prev_entry->next = entry->next; + if (entry->next != NULL) + entry->next->prev = prev_entry; + } + else + { + active_list[type] = entry->next; + /* we were the first but not the only one */ + if (entry->next != NULL) + entry->next->prev = NULL; + } + + /* sanitization */ + entry->h = CK_INVALID_HANDLE; + entry->prev = NULL; + entry->next = NULL; + OPENSSL_free(entry); + } + +/* Free all entries from the active list. */ +void +pk11_free_active_list(PK11_OPTYPE type) + { + PK11_active *entry; + + /* only for asymmetric types since only they have C_Find* locks. */ + switch (type) + { + case OP_RSA: + break; + default: + return; + } + + /* see find_lock array definition for more info on object locking */ + LOCK_OBJSTORE(type); + while ((entry = active_list[type]) != NULL) + pk11_active_remove(entry, type); + UNLOCK_OBJSTORE(type); + } + +/* + * Search for active list entry associated with given PKCS#11 object handle, + * decrement its refcnt and if it drops to 0, disconnect the entry and free it. + * + * Return 1 if the PKCS#11 object associated with the entry has no references, + * return 0 if there is at least one reference, -1 on error. + * + * This function presumes it is called with lock protecting the active list + * held. + */ +int +pk11_active_delete(CK_OBJECT_HANDLE h, PK11_OPTYPE type) + { + PK11_active *entry = NULL; + + if ((entry = pk11_active_find(h, type)) == NULL) + { + PK11err(PK11_F_ACTIVE_DELETE, PK11_R_INVALID_HANDLE); + return (-1); + } + + OPENSSL_assert(entry->refcnt > 0); + entry->refcnt--; + if (entry->refcnt == 0) + { + pk11_active_remove(entry, type); + return (1); + } + + return (0); + } + +/* Our internal RSA_METHOD that we provide pointers to */ +static RSA_METHOD pk11_rsa; + +RSA_METHOD * +PK11_RSA(void) + { + const RSA_METHOD *rsa; + + if (pk11_rsa.name == NULL) + { + rsa = RSA_PKCS1_SSLeay(); + memcpy(&pk11_rsa, rsa, sizeof(*rsa)); + pk11_rsa.name = "PKCS#11 RSA method"; + pk11_rsa.rsa_sign = pk11_RSA_sign; + } + return (&pk11_rsa); + } + +/* Size of an SSL signature: MD5+SHA1 */ +#define SSL_SIG_LENGTH 36 + +static CK_BBOOL mytrue = TRUE; +static CK_BBOOL myfalse = FALSE; + +/* + * Standard engine interface function. Majority codes here are from + * rsa/rsa_sign.c. We replaced the decrypt function call by C_Sign of PKCS#11. + * See more details in rsa/rsa_sign.c + */ +static int pk11_RSA_sign(int type, const unsigned char *m, unsigned int m_len, + unsigned char *sigret, unsigned int *siglen, const RSA *rsa) + { + X509_SIG sig; + ASN1_TYPE parameter; + int i, j = 0; + unsigned char *p, *s = NULL; + X509_ALGOR algor; + ASN1_OCTET_STRING digest; + CK_RV rv; + CK_MECHANISM mech_rsa = {CKM_RSA_PKCS, NULL, 0}; + CK_MECHANISM *p_mech = &mech_rsa; + CK_OBJECT_HANDLE h_priv_key; + PK11_SESSION *sp = NULL; + int ret = 0; + unsigned long ulsiglen; + + /* Encode the digest */ + /* Special case: SSL signature, just check the length */ + if (type == NID_md5_sha1) + { + if (m_len != SSL_SIG_LENGTH) + { + PK11err(PK11_F_RSA_SIGN, + PK11_R_INVALID_MESSAGE_LENGTH); + goto err; + } + i = SSL_SIG_LENGTH; + s = (unsigned char *)m; + } + else + { + sig.algor = &algor; + sig.algor->algorithm = OBJ_nid2obj(type); + if (sig.algor->algorithm == NULL) + { + PK11err(PK11_F_RSA_SIGN, + PK11_R_UNKNOWN_ALGORITHM_TYPE); + goto err; + } + if (sig.algor->algorithm->length == 0) + { + PK11err(PK11_F_RSA_SIGN, + PK11_R_UNKNOWN_ASN1_OBJECT_ID); + goto err; + } + parameter.type = V_ASN1_NULL; + parameter.value.ptr = NULL; + sig.algor->parameter = ¶meter; + + sig.digest = &digest; + sig.digest->data = (unsigned char *)m; + sig.digest->length = m_len; + + i = i2d_X509_SIG(&sig, NULL); + } + + j = RSA_size(rsa); + if ((i - RSA_PKCS1_PADDING) > j) + { + PK11err(PK11_F_RSA_SIGN, PK11_R_DIGEST_TOO_BIG); + goto err; + } + + if (type != NID_md5_sha1) + { + s = (unsigned char *)OPENSSL_malloc((unsigned int)(j + 1)); + if (s == NULL) + { + PK11err(PK11_F_RSA_SIGN, PK11_R_MALLOC_FAILURE); + goto err; + } + p = s; + (void) i2d_X509_SIG(&sig, &p); + } + + if ((sp = pk11_get_session(OP_RSA)) == NULL) + goto err; + + (void) check_new_rsa_key_priv(sp, rsa); + + h_priv_key = sp->opdata_rsa_priv_key; + if (h_priv_key == CK_INVALID_HANDLE) + h_priv_key = sp->opdata_rsa_priv_key = + pk11_get_private_rsa_key((RSA *)rsa, + &sp->opdata_rsa_priv, &sp->opdata_rsa_d_num, + &sp->opdata_rsa_pn_num, &sp->opdata_rsa_pe_num, + sp->session); + + if (h_priv_key != CK_INVALID_HANDLE) + { + rv = pFuncList->C_SignInit(sp->session, p_mech, h_priv_key); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_RSA_SIGN, PK11_R_SIGNINIT, rv); + goto err; + } + + ulsiglen = j; + rv = pFuncList->C_Sign(sp->session, s, i, sigret, + (CK_ULONG_PTR) &ulsiglen); + *siglen = ulsiglen; + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_RSA_SIGN, PK11_R_SIGN, rv); + goto err; + } + ret = 1; + } + +err: + if ((type != NID_md5_sha1) && (s != NULL)) + { + (void) memset(s, 0, (unsigned int)(j + 1)); + OPENSSL_free(s); + } + + pk11_return_session(sp, OP_RSA); + return (ret); + } + +static int hndidx_rsa = -1; + +#define MAXATTR 1024 + +/* + * Load RSA private key from a file or get its PKCS#11 handle if stored in the + * PKCS#11 token. + */ +/* ARGSUSED */ +EVP_PKEY *pk11_load_privkey(ENGINE *e, const char *privkey_file, + UI_METHOD *ui_method, void *callback_data) + { + EVP_PKEY *pkey = NULL; + FILE *privkey; + CK_OBJECT_HANDLE h_priv_key = CK_INVALID_HANDLE; + RSA *rsa = NULL; + PK11_SESSION *sp; + /* Anything else below is needed for the key by reference extension. */ + CK_RV rv; + CK_BBOOL is_token = TRUE; + CK_BBOOL rollback = FALSE; + CK_BYTE attr_data[2][MAXATTR]; + CK_OBJECT_CLASS key_class = CKO_PRIVATE_KEY; + CK_OBJECT_HANDLE ks_key = CK_INVALID_HANDLE; /* key in keystore */ + + /* we look for private keys only */ + CK_ATTRIBUTE search_templ[] = + { + {CKA_TOKEN, &is_token, sizeof(is_token)}, + {CKA_CLASS, &key_class, sizeof(key_class)}, + {CKA_LABEL, NULL, 0} + }; + + /* + * These public attributes are needed to initialize the OpenSSL RSA + * structure with something we can use to look up the key. Note that we + * never ask for private components. + */ + CK_ATTRIBUTE get_templ[] = + { + {CKA_MODULUS, (void *)attr_data[0], MAXATTR}, /* n */ + {CKA_PUBLIC_EXPONENT, (void *)attr_data[1], MAXATTR}, /* e */ + }; + + if ((sp = pk11_get_session(OP_RSA)) == NULL) + return (NULL); + + /* + * Use simple scheme "pkcs11:" for now. + */ + if (strstr(privkey_file, "pkcs11:") == privkey_file) + { + search_templ[2].pValue = strstr(privkey_file, ":") + 1; + search_templ[2].ulValueLen = strlen(search_templ[2].pValue); + + if (pk11_token_login(sp->session, &pk11_login_done, + CK_TRUE) == 0) + goto err; + + /* see find_lock array definition + for more info on object locking */ + LOCK_OBJSTORE(OP_RSA); + + /* + * Now let's try to find the key in the token. It is a failure + * if we can't find it. + */ + if (find_one_object(OP_RSA, sp->session, search_templ, 3, + &ks_key) == 0) + { + UNLOCK_OBJSTORE(OP_RSA); + goto err; + } + + if (hndidx_rsa == -1) + hndidx_rsa = RSA_get_ex_new_index(0, + "pkcs11 RSA HSM key handle", + NULL, NULL, NULL); + + /* + * We might have a cache hit which we could confirm + * according to the 'n'/'e' params, RSA public pointer + * as NULL, and non-NULL RSA private pointer. However, + * it is easier just to recreate everything. We expect + * the keys to be loaded once and used many times. We + * do not check the return value because even in case + * of failure the sp structure will have both key + * pointer and object handle cleaned and + * pk11_destroy_object() reports the failure to the + * OpenSSL error message buffer. + */ + (void) pk11_destroy_rsa_object_priv(sp, FALSE); + + sp->opdata_rsa_priv_key = ks_key; + /* This object shall not be deleted on a cache miss. */ + sp->priv_persistent = CK_TRUE; + + /* + * Cache the RSA private structure pointer. We do not + * use it now for key-by-ref keys but let's do it for + * consistency reasons. + */ + if ((rsa = sp->opdata_rsa_priv = RSA_new_method(e)) == NULL) + { + UNLOCK_OBJSTORE(OP_RSA); + goto err; + } + + /* + * Now we have to initialize an OpenSSL RSA structure, + * everything else is 0 or NULL. + */ + rsa->flags = RSA_FLAG_SIGN_VER | RSA_FLAG_EXT_PKEY; + RSA_set_ex_data(rsa, hndidx_rsa, (void *) ks_key); + + if ((rv = pFuncList->C_GetAttributeValue(sp->session, ks_key, + get_templ, 2)) != CKR_OK) + { + UNLOCK_OBJSTORE(OP_RSA); + PK11err_add_data(PK11_F_LOAD_PRIVKEY, + PK11_R_GETATTRIBUTVALUE, rv); + goto err; + } + + /* + * We do not use pk11_get_private_rsa_key() here so we + * must take care of handle management ourselves. + */ + KEY_HANDLE_REFHOLD(ks_key, OP_RSA, TRUE, rollback, err); + + /* + * Those are the sensitive components we do not want to export + * from the token at all: rsa->(d|p|q|dmp1|dmq1|iqmp). + */ + attr_to_BN(&get_templ[0], attr_data[0], &rsa->n); + attr_to_BN(&get_templ[1], attr_data[1], &rsa->e); + /* + * Must have 'n'/'e' components in the session structure as + * well. They serve as a public look-up key for the private key + * in the keystore. + */ + attr_to_BN(&get_templ[0], attr_data[0], + &sp->opdata_rsa_pn_num); + attr_to_BN(&get_templ[1], attr_data[1], + &sp->opdata_rsa_pe_num); + + UNLOCK_OBJSTORE(OP_RSA); + + if ((pkey = EVP_PKEY_new()) == NULL) + goto err; + + if (EVP_PKEY_assign_RSA(pkey, rsa) == 0) + goto err; + } + else if ((privkey = fopen(privkey_file, read_mode_flags)) != NULL) + { + pkey = PEM_read_PrivateKey(privkey, NULL, NULL, NULL); + (void) fclose(privkey); + if (pkey != NULL) + { + rsa = EVP_PKEY_get1_RSA(pkey); + if (rsa != NULL) + { + /* + * This will always destroy the RSA + * object since we have a new RSA + * structure here. + */ + (void) check_new_rsa_key_priv(sp, rsa); + sp->priv_persistent = CK_FALSE; + + h_priv_key = sp->opdata_rsa_priv_key = + pk11_get_private_rsa_key(rsa, + &sp->opdata_rsa_priv, + &sp->opdata_rsa_d_num, + &sp->opdata_rsa_pn_num, + &sp->opdata_rsa_pe_num, sp->session); + if (h_priv_key == CK_INVALID_HANDLE) + goto err; + } + else + goto err; + } + } + + pk11_return_session(sp, OP_RSA); + return (pkey); +err: + pk11_return_session(sp, OP_RSA); + if (rsa != NULL) + RSA_free(rsa); + if (pkey != NULL) + { + EVP_PKEY_free(pkey); + pkey = NULL; + } + rollback = rollback; + return (pkey); + } + +/* + * Load RSA public key from a file or get its PKCS#11 handle if stored in the + * PKCS#11 token. + */ +/* ARGSUSED */ +EVP_PKEY *pk11_load_pubkey(ENGINE *e, const char *pubkey_file, + UI_METHOD *ui_method, void *callback_data) + { + EVP_PKEY *pkey = NULL; + FILE *pubkey; + CK_OBJECT_HANDLE h_pub_key = CK_INVALID_HANDLE; + RSA *rsa = NULL; + PK11_SESSION *sp; + /* Anything else below is needed for the key by reference extension. */ + CK_RV rv; + CK_BBOOL is_token = TRUE; + CK_BYTE attr_data[2][MAXATTR]; + CK_OBJECT_CLASS key_class = CKO_PUBLIC_KEY; + CK_OBJECT_HANDLE ks_key = CK_INVALID_HANDLE; /* key in keystore */ + + /* we look for public keys only */ + CK_ATTRIBUTE search_templ[] = + { + {CKA_TOKEN, &is_token, sizeof(is_token)}, + {CKA_CLASS, &key_class, sizeof(key_class)}, + {CKA_LABEL, NULL, 0} + }; + + /* + * These public attributes are needed to initialize OpenSSL RSA + * structure with something we can use to look up the key. + */ + CK_ATTRIBUTE get_templ[] = + { + {CKA_MODULUS, (void *)attr_data[0], MAXATTR}, /* n */ + {CKA_PUBLIC_EXPONENT, (void *)attr_data[1], MAXATTR}, /* e */ + }; + + if ((sp = pk11_get_session(OP_RSA)) == NULL) + return (NULL); + + /* + * Use simple scheme "pkcs11:" for now. + */ + if (strstr(pubkey_file, "pkcs11:") == pubkey_file) + { + search_templ[2].pValue = strstr(pubkey_file, ":") + 1; + search_templ[2].ulValueLen = strlen(search_templ[2].pValue); + + if (pk11_token_login(sp->session, &pk11_login_done, + CK_FALSE) == 0) + goto err; + + /* see find_lock array definition + for more info on object locking */ + LOCK_OBJSTORE(OP_RSA); + + /* + * Now let's try to find the key in the token. It is a failure + * if we can't find it. + */ + if (find_one_object(OP_RSA, sp->session, search_templ, 3, + &ks_key) == 0) + { + UNLOCK_OBJSTORE(OP_RSA); + goto err; + } + + /* + * We load a new public key so we will create a new RSA + * structure. No cache hit is possible. + */ + (void) pk11_destroy_rsa_object_pub(sp, FALSE); + + sp->opdata_rsa_pub_key = ks_key; + /* This object shall not be deleted on a cache miss. */ + sp->pub_persistent = CK_TRUE; + + /* + * Cache the RSA public structure pointer. + */ + if ((rsa = sp->opdata_rsa_pub = RSA_new_method(e)) == NULL) + { + UNLOCK_OBJSTORE(OP_RSA); + goto err; + } + + /* + * Now we have to initialize an OpenSSL RSA structure, + * everything else is 0 or NULL. + */ + rsa->flags = RSA_FLAG_SIGN_VER; + + if ((rv = pFuncList->C_GetAttributeValue(sp->session, ks_key, + get_templ, 2)) != CKR_OK) + { + UNLOCK_OBJSTORE(OP_RSA); + PK11err_add_data(PK11_F_LOAD_PUBKEY, + PK11_R_GETATTRIBUTVALUE, rv); + goto err; + } + + attr_to_BN(&get_templ[0], attr_data[0], &rsa->n); + attr_to_BN(&get_templ[1], attr_data[1], &rsa->e); + + UNLOCK_OBJSTORE(OP_RSA); + + if ((pkey = EVP_PKEY_new()) == NULL) + goto err; + + if (EVP_PKEY_assign_RSA(pkey, rsa) == 0) + goto err; + + /* + * Create a session object from it so that when calling + * pk11_get_public_rsa_key() the next time, we can find it. The + * reason why we do that is that we cannot tell from the RSA + * structure (OpenSSL RSA structure does not have any room for + * additional data used by the engine, for example) if it bears + * a public key stored in the keystore or not so it's better if + * we always have a session key. Note that this is different + * from what we do for the private keystore objects but in that + * case, we can tell from the RSA structure that the keystore + * object is in play - the 'd' component is NULL in that case. + */ + h_pub_key = sp->opdata_rsa_pub_key = + pk11_get_public_rsa_key(rsa, + &sp->opdata_rsa_pub, &sp->opdata_rsa_n_num, + &sp->opdata_rsa_e_num, sp->session); + if (h_pub_key == CK_INVALID_HANDLE) + goto err; + } + else if ((pubkey = fopen(pubkey_file, read_mode_flags)) != NULL) + { + pkey = PEM_read_PUBKEY(pubkey, NULL, NULL, NULL); + (void) fclose(pubkey); + if (pkey != NULL) + { + rsa = EVP_PKEY_get1_RSA(pkey); + if (rsa != NULL) + { + /* + * This will always destroy the RSA + * object since we have a new RSA + * structure here. + */ + (void) check_new_rsa_key_pub(sp, rsa); + sp->pub_persistent = CK_FALSE; + + h_pub_key = sp->opdata_rsa_pub_key = + pk11_get_public_rsa_key(rsa, + &sp->opdata_rsa_pub, &sp->opdata_rsa_n_num, + &sp->opdata_rsa_e_num, sp->session); + if (h_pub_key == CK_INVALID_HANDLE) + goto err; + } + else + goto err; + } + } + + pk11_return_session(sp, OP_RSA); + return (pkey); +err: + pk11_return_session(sp, OP_RSA); + if (rsa != NULL) + RSA_free(rsa); + if (pkey != NULL) + { + EVP_PKEY_free(pkey); + pkey = NULL; + } + return (pkey); + } + +/* + * Create a public key object in a session from a given rsa structure. + * The *rsa_n_num and *rsa_e_num pointers are non-NULL for RSA public keys. + */ +static CK_OBJECT_HANDLE pk11_get_public_rsa_key(RSA *rsa, + RSA **key_ptr, BIGNUM **rsa_n_num, BIGNUM **rsa_e_num, + CK_SESSION_HANDLE session) + { + CK_RV rv; + CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE; + CK_ULONG found; + CK_OBJECT_CLASS o_key = CKO_PUBLIC_KEY; + CK_KEY_TYPE k_type = CKK_RSA; + CK_ULONG ul_key_attr_count = 8; + CK_BBOOL rollback = FALSE; + + CK_ATTRIBUTE a_key_template[] = + { + {CKA_CLASS, (void *) NULL, sizeof (CK_OBJECT_CLASS)}, + {CKA_KEY_TYPE, (void *) NULL, sizeof (CK_KEY_TYPE)}, + {CKA_TOKEN, &myfalse, sizeof (myfalse)}, + {CKA_ENCRYPT, &mytrue, sizeof (mytrue)}, + {CKA_VERIFY, &mytrue, sizeof (mytrue)}, + {CKA_VERIFY_RECOVER, &mytrue, sizeof (mytrue)}, + {CKA_MODULUS, (void *)NULL, 0}, + {CKA_PUBLIC_EXPONENT, (void *)NULL, 0} + }; + + int i; + + a_key_template[0].pValue = &o_key; + a_key_template[1].pValue = &k_type; + + a_key_template[6].ulValueLen = BN_num_bytes(rsa->n); + a_key_template[6].pValue = (CK_VOID_PTR)OPENSSL_malloc( + (size_t)a_key_template[6].ulValueLen); + if (a_key_template[6].pValue == NULL) + { + PK11err(PK11_F_GET_PUB_RSA_KEY, PK11_R_MALLOC_FAILURE); + goto malloc_err; + } + + BN_bn2bin(rsa->n, a_key_template[6].pValue); + + a_key_template[7].ulValueLen = BN_num_bytes(rsa->e); + a_key_template[7].pValue = (CK_VOID_PTR)OPENSSL_malloc( + (size_t)a_key_template[7].ulValueLen); + if (a_key_template[7].pValue == NULL) + { + PK11err(PK11_F_GET_PUB_RSA_KEY, PK11_R_MALLOC_FAILURE); + goto malloc_err; + } + + BN_bn2bin(rsa->e, a_key_template[7].pValue); + + /* see find_lock array definition for more info on object locking */ + LOCK_OBJSTORE(OP_RSA); + + rv = pFuncList->C_FindObjectsInit(session, a_key_template, + ul_key_attr_count); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PUB_RSA_KEY, + PK11_R_FINDOBJECTSINIT, rv); + goto err; + } + + rv = pFuncList->C_FindObjects(session, &h_key, 1, &found); + + if (rv != CKR_OK) + { + (void) pFuncList->C_FindObjectsFinal(session); + PK11err_add_data(PK11_F_GET_PUB_RSA_KEY, + PK11_R_FINDOBJECTS, rv); + goto err; + } + + rv = pFuncList->C_FindObjectsFinal(session); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PUB_RSA_KEY, + PK11_R_FINDOBJECTSFINAL, rv); + goto err; + } + + if (found == 0) + { + rv = pFuncList->C_CreateObject(session, + a_key_template, ul_key_attr_count, &h_key); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PUB_RSA_KEY, + PK11_R_CREATEOBJECT, rv); + goto err; + } + } + + if (rsa_n_num != NULL) + if ((*rsa_n_num = BN_dup(rsa->n)) == NULL) + { + PK11err(PK11_F_GET_PUB_RSA_KEY, PK11_R_MALLOC_FAILURE); + rollback = TRUE; + goto err; + } + if (rsa_e_num != NULL) + if ((*rsa_e_num = BN_dup(rsa->e)) == NULL) + { + PK11err(PK11_F_GET_PUB_RSA_KEY, PK11_R_MALLOC_FAILURE); + BN_free(*rsa_n_num); + *rsa_n_num = NULL; + rollback = TRUE; + goto err; + } + + /* LINTED: E_CONSTANT_CONDITION */ + KEY_HANDLE_REFHOLD(h_key, OP_RSA, FALSE, rollback, err); + if (key_ptr != NULL) + *key_ptr = rsa; + +err: + if (rollback) + { + /* + * We do not care about the return value from C_DestroyObject() + * since we are doing rollback. + */ + if (found == 0) + (void) pFuncList->C_DestroyObject(session, h_key); + h_key = CK_INVALID_HANDLE; + } + + UNLOCK_OBJSTORE(OP_RSA); + +malloc_err: + for (i = 6; i <= 7; i++) + { + if (a_key_template[i].pValue != NULL) + { + OPENSSL_free(a_key_template[i].pValue); + a_key_template[i].pValue = NULL; + } + } + + return (h_key); + } + +/* + * Create a private key object in the session from a given rsa structure. + * The *rsa_d_num pointer is non-NULL for RSA private keys. + */ +static CK_OBJECT_HANDLE +pk11_get_private_rsa_key(RSA *rsa, RSA **key_ptr, BIGNUM **rsa_d_num, + BIGNUM **rsa_n_num, BIGNUM **rsa_e_num, CK_SESSION_HANDLE session) + { + CK_RV rv; + CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE; + int i; + CK_ULONG found; + CK_OBJECT_CLASS o_key = CKO_PRIVATE_KEY; + CK_KEY_TYPE k_type = CKK_RSA; + CK_ULONG ul_key_attr_count = 14; + CK_BBOOL rollback = FALSE; + + /* Both CKA_TOKEN and CKA_SENSITIVE have to be FALSE for session keys */ + CK_ATTRIBUTE a_key_template[] = + { + {CKA_CLASS, (void *) NULL, sizeof (CK_OBJECT_CLASS)}, + {CKA_KEY_TYPE, (void *) NULL, sizeof (CK_KEY_TYPE)}, + {CKA_TOKEN, &myfalse, sizeof (myfalse)}, + {CKA_SENSITIVE, &myfalse, sizeof (myfalse)}, + {CKA_DECRYPT, &mytrue, sizeof (mytrue)}, + {CKA_SIGN, &mytrue, sizeof (mytrue)}, + {CKA_MODULUS, (void *)NULL, 0}, + {CKA_PUBLIC_EXPONENT, (void *)NULL, 0}, + {CKA_PRIVATE_EXPONENT, (void *)NULL, 0}, + {CKA_PRIME_1, (void *)NULL, 0}, + {CKA_PRIME_2, (void *)NULL, 0}, + {CKA_EXPONENT_1, (void *)NULL, 0}, + {CKA_EXPONENT_2, (void *)NULL, 0}, + {CKA_COEFFICIENT, (void *)NULL, 0}, + }; + + if ((rsa->flags & RSA_FLAG_EXT_PKEY) != 0) { + h_key = (CK_OBJECT_HANDLE)RSA_get_ex_data(rsa, hndidx_rsa); + LOCK_OBJSTORE(OP_RSA); + goto set; + } + + a_key_template[0].pValue = &o_key; + a_key_template[1].pValue = &k_type; + + /* Put the private key components into the template */ + if (init_template_value(rsa->n, &a_key_template[6].pValue, + &a_key_template[6].ulValueLen) == 0 || + init_template_value(rsa->e, &a_key_template[7].pValue, + &a_key_template[7].ulValueLen) == 0 || + init_template_value(rsa->d, &a_key_template[8].pValue, + &a_key_template[8].ulValueLen) == 0 || + init_template_value(rsa->p, &a_key_template[9].pValue, + &a_key_template[9].ulValueLen) == 0 || + init_template_value(rsa->q, &a_key_template[10].pValue, + &a_key_template[10].ulValueLen) == 0 || + init_template_value(rsa->dmp1, &a_key_template[11].pValue, + &a_key_template[11].ulValueLen) == 0 || + init_template_value(rsa->dmq1, &a_key_template[12].pValue, + &a_key_template[12].ulValueLen) == 0 || + init_template_value(rsa->iqmp, &a_key_template[13].pValue, + &a_key_template[13].ulValueLen) == 0) + { + PK11err(PK11_F_GET_PRIV_RSA_KEY, PK11_R_MALLOC_FAILURE); + goto malloc_err; + } + + /* see find_lock array definition for more info on object locking */ + LOCK_OBJSTORE(OP_RSA); + + /* + * We are getting the private key but the private 'd' + * component is NULL. That means this is key by reference RSA + * key. In that case, we can use only public components for + * searching for the private key handle. + */ + if (rsa->d == NULL) + { + ul_key_attr_count = 8; + /* + * We will perform the search in the token, not in the existing + * session keys. + */ + a_key_template[2].pValue = &mytrue; + } + + rv = pFuncList->C_FindObjectsInit(session, a_key_template, + ul_key_attr_count); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PRIV_RSA_KEY, + PK11_R_FINDOBJECTSINIT, rv); + goto err; + } + + rv = pFuncList->C_FindObjects(session, &h_key, 1, &found); + + if (rv != CKR_OK) + { + (void) pFuncList->C_FindObjectsFinal(session); + PK11err_add_data(PK11_F_GET_PRIV_RSA_KEY, + PK11_R_FINDOBJECTS, rv); + goto err; + } + + rv = pFuncList->C_FindObjectsFinal(session); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PRIV_RSA_KEY, + PK11_R_FINDOBJECTSFINAL, rv); + goto err; + } + + if (found == 0) + { + /* + * We have an RSA structure with 'n'/'e' components + * only so we tried to find the private key in the + * keystore. If it was really a token key we have a + * problem. Note that for other key types we just + * create a new session key using the private + * components from the RSA structure. + */ + if (rsa->d == NULL) + { + PK11err(PK11_F_GET_PRIV_RSA_KEY, + PK11_R_PRIV_KEY_NOT_FOUND); + goto err; + } + + rv = pFuncList->C_CreateObject(session, + a_key_template, ul_key_attr_count, &h_key); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PRIV_RSA_KEY, + PK11_R_CREATEOBJECT, rv); + goto err; + } + } + +set: + if (rsa_d_num != NULL) + { + /* + * When RSA keys by reference code is used, we never + * extract private components from the keystore. In + * that case 'd' was set to NULL and we expect the + * application to properly cope with that. It is + * documented in openssl(5). In general, if keys by + * reference are used we expect it to be used + * exclusively using the high level API and then there + * is no problem. If the application expects the + * private components to be read from the keystore + * then that is not a supported way of usage. + */ + if (rsa->d != NULL && (*rsa_d_num = BN_dup(rsa->d)) == NULL) + { + PK11err(PK11_F_GET_PRIV_RSA_KEY, PK11_R_MALLOC_FAILURE); + rollback = TRUE; + goto err; + } + else + *rsa_d_num = NULL; + } + + /* + * For the key by reference code, we need public components as well + * since 'd' component is always NULL. For that reason, we always cache + * 'n'/'e' components as well. + */ + *rsa_n_num = BN_dup(rsa->n); + *rsa_e_num = BN_dup(rsa->e); + + /* LINTED: E_CONSTANT_CONDITION */ + KEY_HANDLE_REFHOLD(h_key, OP_RSA, FALSE, rollback, err); + if (key_ptr != NULL) + *key_ptr = rsa; + +err: + if (rollback) + { + /* + * We do not care about the return value from C_DestroyObject() + * since we are doing rollback. + */ + if (found == 0 && + (rsa->flags & RSA_FLAG_EXT_PKEY) == 0) + (void) pFuncList->C_DestroyObject(session, h_key); + h_key = CK_INVALID_HANDLE; + } + + UNLOCK_OBJSTORE(OP_RSA); + +malloc_err: + /* + * 6 to 13 entries in the key template are key components. + * They need to be freed upon exit or error. + */ + for (i = 6; i <= 13; i++) + { + if (a_key_template[i].pValue != NULL) + { + (void) memset(a_key_template[i].pValue, 0, + a_key_template[i].ulValueLen); + OPENSSL_free(a_key_template[i].pValue); + a_key_template[i].pValue = NULL; + } + } + + return (h_key); + } + +/* + * Check for cache miss and clean the object pointer and handle + * in such case. Return 1 for cache hit, 0 for cache miss. + */ +static int check_new_rsa_key_pub(PK11_SESSION *sp, const RSA *rsa) + { + /* + * Provide protection against RSA structure reuse by making the + * check for cache hit stronger. Only public components of RSA + * key matter here so it is sufficient to compare them with values + * cached in PK11_SESSION structure. + * + * We must check the handle as well since with key by reference, public + * components 'n'/'e' are cached in private keys as well. That means we + * could have a cache hit in a private key when looking for a public + * key. That would not work, you cannot have one PKCS#11 object for + * both data signing and verifying. + */ + if ((sp->opdata_rsa_pub != rsa) || + (BN_cmp(sp->opdata_rsa_n_num, rsa->n) != 0) || + (BN_cmp(sp->opdata_rsa_e_num, rsa->e) != 0) || + (sp->opdata_rsa_priv_key != CK_INVALID_HANDLE)) + { + /* + * We do not check the return value because even in case of + * failure the sp structure will have both key pointer + * and object handle cleaned and pk11_destroy_object() + * reports the failure to the OpenSSL error message buffer. + */ + (void) pk11_destroy_rsa_object_pub(sp, TRUE); + return (0); + } + return (1); + } + +/* + * Check for cache miss and clean the object pointer and handle + * in such case. Return 1 for cache hit, 0 for cache miss. + */ +static int check_new_rsa_key_priv(PK11_SESSION *sp, const RSA *rsa) + { + /* + * Provide protection against RSA structure reuse by making + * the check for cache hit stronger. Comparing public exponent + * of RSA key with value cached in PK11_SESSION structure + * should be sufficient. Note that we want to compare the + * public component since with the keys by reference + * mechanism, private components are not in the RSA + * structure. Also, see check_new_rsa_key_pub() about why we + * compare the handle as well. + */ + if ((sp->opdata_rsa_priv != rsa) || + (BN_cmp(sp->opdata_rsa_pn_num, rsa->n) != 0) || + (BN_cmp(sp->opdata_rsa_pe_num, rsa->e) != 0) || + (sp->opdata_rsa_pn_num == NULL) || + (sp->opdata_rsa_pe_num == NULL) || + (sp->opdata_rsa_pub_key != CK_INVALID_HANDLE)) + { + /* + * We do not check the return value because even in case of + * failure the sp structure will have both key pointer + * and object handle cleaned and pk11_destroy_object() + * reports the failure to the OpenSSL error message buffer. + */ + (void) pk11_destroy_rsa_object_priv(sp, TRUE); + return (0); + } + return (1); + } + +/* + * Local function to simplify key template population + * Return 0 -- error, 1 -- no error + */ +static int +init_template_value(BIGNUM *bn, CK_VOID_PTR *p_value, + CK_ULONG *ul_value_len) + { + CK_ULONG len = 0; + + /* + * This function can be used on non-initialized BIGNUMs. It is + * easier to check that here than individually in the callers. + */ + if (bn != NULL) + len = BN_num_bytes(bn); + + if (bn == NULL || len == 0) + return (1); + + *ul_value_len = len; + *p_value = (CK_VOID_PTR)OPENSSL_malloc((size_t)*ul_value_len); + if (*p_value == NULL) + return (0); + + BN_bn2bin(bn, *p_value); + + return (1); + } + +static void +attr_to_BN(CK_ATTRIBUTE_PTR attr, CK_BYTE attr_data[], BIGNUM **bn) + { + if (attr->ulValueLen > 0) + *bn = BN_bin2bn(attr_data, attr->ulValueLen, NULL); + } + +/* + * Find one object in the token. It is an error if we can not find the + * object or if we find more objects based on the template we got. + * Assume object store locked. + * + * Returns: + * 1 OK + * 0 no object or more than 1 object found + */ +static int +find_one_object(PK11_OPTYPE op, CK_SESSION_HANDLE s, + CK_ATTRIBUTE_PTR ptempl, CK_ULONG nattr, CK_OBJECT_HANDLE_PTR pkey) + { + CK_RV rv; + CK_ULONG objcnt; + + if ((rv = pFuncList->C_FindObjectsInit(s, ptempl, nattr)) != CKR_OK) + { + PK11err_add_data(PK11_F_FIND_ONE_OBJECT, + PK11_R_FINDOBJECTSINIT, rv); + return (0); + } + + rv = pFuncList->C_FindObjects(s, pkey, 1, &objcnt); + if (rv != CKR_OK) + { + (void) pFuncList->C_FindObjectsFinal(s); + PK11err_add_data(PK11_F_FIND_ONE_OBJECT, PK11_R_FINDOBJECTS, + rv); + return (0); + } + + (void) pFuncList->C_FindObjectsFinal(s); + + if (objcnt > 1) + { + PK11err(PK11_F_FIND_ONE_OBJECT, + PK11_R_MORE_THAN_ONE_OBJECT_FOUND); + return (0); + } + else if (objcnt == 0) + { + PK11err(PK11_F_FIND_ONE_OBJECT, PK11_R_NO_OBJECT_FOUND); + return (0); + } + return (1); + } + +/* from uri stuff */ + +extern char *pk11_pin; + +static int pk11_get_pin(void); + +static int +pk11_get_pin(void) +{ + char *pin; + + /* The getpassphrase() function is not MT safe. */ +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_lock(token_lock) == 0); +#else + CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); +#endif + pin = getpassphrase("Enter PIN: "); + if (pin == NULL) + { + PK11err(PK11_F_GET_PIN, PK11_R_COULD_NOT_READ_PIN); +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0); +#else + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + return (0); + } + pk11_pin = BUF_strdup(pin); + if (pk11_pin == NULL) + { + PK11err(PK11_F_LOAD_PRIVKEY, PK11_R_MALLOC_FAILURE); +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0); +#else + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + return (0); + } + memset(pin, 0, strlen(pin)); +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0); +#else + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + return (1); + } + +/* + * Log in to the keystore if we are supposed to do that at all. Take care of + * reading and caching the PIN etc. Log in only once even when called from + * multiple threads. + * + * Returns: + * 1 on success + * 0 on failure + */ +static int +pk11_token_login(CK_SESSION_HANDLE session, CK_BBOOL *login_done, + CK_BBOOL is_private) + { + CK_RV rv; + +#if 0 + /* doesn't work on the AEP Keyper??? */ + if ((pubkey_token_flags & CKF_TOKEN_INITIALIZED) == 0) + { + PK11err(PK11_F_TOKEN_LOGIN, + PK11_R_TOKEN_NOT_INITIALIZED); + return (0); + } +#endif + + /* + * If login is required or needed but the PIN has not been + * even initialized we can bail out right now. Note that we + * are supposed to always log in if we are going to access + * private keys. However, we may need to log in even for + * accessing public keys in case that the CKF_LOGIN_REQUIRED + * flag is set. + */ + if (((pubkey_token_flags & CKF_LOGIN_REQUIRED) || + (is_private == CK_TRUE)) && + (~pubkey_token_flags & CKF_USER_PIN_INITIALIZED)) + { + PK11err(PK11_F_TOKEN_LOGIN, PK11_R_TOKEN_PIN_NOT_SET); + return (0); + } + + /* + * Note on locking: it is possible that more than one thread + * gets into pk11_get_pin() so we must deal with that. We + * cannot avoid it since we cannot guard fork() in there with + * a lock because we could end up in a dead lock in the + * child. Why? Remember we are in a multithreaded environment + * so we must lock all mutexes in the prefork function to + * avoid a situation in which a thread that did not call + * fork() held a lock, making future unlocking impossible. We + * lock right before C_Login(). + */ + if ((pubkey_token_flags & CKF_LOGIN_REQUIRED) || + (is_private == CK_TRUE)) + { + if (*login_done == CK_FALSE) + { + if ((pk11_pin == NULL) && (pk11_get_pin() == 0)) + { + PK11err(PK11_F_TOKEN_LOGIN, + PK11_R_TOKEN_PIN_NOT_PROVIDED); + return (0); + } + } + + /* + * Note that what we are logging into is the keystore from + * pubkey_SLOTID because we work with OP_RSA session type here. + * That also means that we can work with only one keystore in + * the engine. + * + * We must make sure we do not try to login more than once. + * Also, see the comment above on locking strategy. + */ + +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_lock(token_lock) == 0); +#else + CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); +#endif + if (*login_done == CK_FALSE) + { + if ((rv = pFuncList->C_Login(session, + CKU_USER, (CK_UTF8CHAR*)pk11_pin, + strlen(pk11_pin))) != CKR_OK) + { + PK11err_add_data(PK11_F_TOKEN_LOGIN, + PK11_R_TOKEN_LOGIN_FAILED, rv); + goto err_locked; + } + + *login_done = CK_TRUE; + + } +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0); +#else + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + } + else + { + /* + * If token does not require login we take it as the + * login was done. + */ + *login_done = CK_TRUE; + } + + return (1); + +err_locked: + if (pk11_pin) { + memset(pk11_pin, 0, strlen(pk11_pin)); + OPENSSL_free((void*)pk11_pin); + } + pk11_pin = NULL; +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0); +#else + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + return (0); + } + +/* + * Log in to the keystore in the child if we were logged in in the + * parent. There are similarities in the code with pk11_token_login() + * but still it is quite different so we need a separate function for + * this. + * + * Note that this function is called under the locked session mutex when fork is + * detected. That means that C_Login() will be called from the child just once. + * + * Returns: + * 1 on success + * 0 on failure + */ +int +pk11_token_relogin(CK_SESSION_HANDLE session) + { + CK_RV rv; + + if ((pk11_pin == NULL) && (pk11_get_pin() == 0)) + return (0); + +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_lock(token_lock) == 0); +#else + CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); +#endif + if ((rv = pFuncList->C_Login(session, CKU_USER, + (CK_UTF8CHAR_PTR)pk11_pin, strlen(pk11_pin))) != CKR_OK) + { + PK11err_add_data(PK11_F_TOKEN_RELOGIN, + PK11_R_TOKEN_LOGIN_FAILED, rv); +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0); +#else + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + return (0); + } +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0); +#else + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + + return (1); + } + +#ifdef OPENSSL_SYS_WIN32 +char *getpassphrase(const char *prompt) + { + static char buf[128]; + HANDLE h; + DWORD cc, mode; + int cnt; + + h = GetStdHandle(STD_INPUT_HANDLE); + fputs(prompt, stderr); + fflush(stderr); + fflush(stdout); + FlushConsoleInputBuffer(h); + GetConsoleMode(h, &mode); + SetConsoleMode(h, ENABLE_PROCESSED_INPUT); + + for (cnt = 0; cnt < sizeof(buf) - 1; cnt++) + { + ReadFile(h, buf + cnt, 1, &cc, NULL); + if (buf[cnt] == '\r') + break; + fputc('*', stdout); + fflush(stderr); + fflush(stdout); + } + + SetConsoleMode(h, mode); + buf[cnt] = '\0'; + fputs("\n", stderr); + return buf; + } +#endif /* OPENSSL_SYS_WIN32 */ +#endif /* OPENSSL_NO_HW_PK11SO */ +#endif /* OPENSSL_NO_HW_PK11 */ +#endif /* OPENSSL_NO_HW */ Index: openssl/crypto/engine/pkcs11.h diff -u /dev/null openssl/crypto/engine/pkcs11.h:1.1.1.1 --- /dev/null Mon Jun 13 15:26:30 2016 +++ openssl/crypto/engine/pkcs11.h Wed Oct 24 23:27:09 2007 @@ -0,0 +1,299 @@ +/* pkcs11.h include file for PKCS #11. */ +/* $Revision: 1.1.1.1 $ */ + +/* License to copy and use this software is granted provided that it is + * identified as "RSA Security Inc. PKCS #11 Cryptographic Token Interface + * (Cryptoki)" in all material mentioning or referencing this software. + + * License is also granted to make and use derivative works provided that + * such works are identified as "derived from the RSA Security Inc. PKCS #11 + * Cryptographic Token Interface (Cryptoki)" in all material mentioning or + * referencing the derived work. + + * RSA Security Inc. makes no representations concerning either the + * merchantability of this software or the suitability of this software for + * any particular purpose. It is provided "as is" without express or implied + * warranty of any kind. + */ + +#ifndef _PKCS11_H_ +#define _PKCS11_H_ 1 + +#ifdef __cplusplus +extern "C" { +#endif + +/* Before including this file (pkcs11.h) (or pkcs11t.h by + * itself), 6 platform-specific macros must be defined. These + * macros are described below, and typical definitions for them + * are also given. Be advised that these definitions can depend + * on both the platform and the compiler used (and possibly also + * on whether a Cryptoki library is linked statically or + * dynamically). + * + * In addition to defining these 6 macros, the packing convention + * for Cryptoki structures should be set. The Cryptoki + * convention on packing is that structures should be 1-byte + * aligned. + * + * If you're using Microsoft Developer Studio 5.0 to produce + * Win32 stuff, this might be done by using the following + * preprocessor directive before including pkcs11.h or pkcs11t.h: + * + * #pragma pack(push, cryptoki, 1) + * + * and using the following preprocessor directive after including + * pkcs11.h or pkcs11t.h: + * + * #pragma pack(pop, cryptoki) + * + * If you're using an earlier version of Microsoft Developer + * Studio to produce Win16 stuff, this might be done by using + * the following preprocessor directive before including + * pkcs11.h or pkcs11t.h: + * + * #pragma pack(1) + * + * In a UNIX environment, you're on your own for this. You might + * not need to do (or be able to do!) anything. + * + * + * Now for the macros: + * + * + * 1. CK_PTR: The indirection string for making a pointer to an + * object. It can be used like this: + * + * typedef CK_BYTE CK_PTR CK_BYTE_PTR; + * + * If you're using Microsoft Developer Studio 5.0 to produce + * Win32 stuff, it might be defined by: + * + * #define CK_PTR * + * + * If you're using an earlier version of Microsoft Developer + * Studio to produce Win16 stuff, it might be defined by: + * + * #define CK_PTR far * + * + * In a typical UNIX environment, it might be defined by: + * + * #define CK_PTR * + * + * + * 2. CK_DEFINE_FUNCTION(returnType, name): A macro which makes + * an exportable Cryptoki library function definition out of a + * return type and a function name. It should be used in the + * following fashion to define the exposed Cryptoki functions in + * a Cryptoki library: + * + * CK_DEFINE_FUNCTION(CK_RV, C_Initialize)( + * CK_VOID_PTR pReserved + * ) + * { + * ... + * } + * + * If you're using Microsoft Developer Studio 5.0 to define a + * function in a Win32 Cryptoki .dll, it might be defined by: + * + * #define CK_DEFINE_FUNCTION(returnType, name) \ + * returnType __declspec(dllexport) name + * + * If you're using an earlier version of Microsoft Developer + * Studio to define a function in a Win16 Cryptoki .dll, it + * might be defined by: + * + * #define CK_DEFINE_FUNCTION(returnType, name) \ + * returnType __export _far _pascal name + * + * In a UNIX environment, it might be defined by: + * + * #define CK_DEFINE_FUNCTION(returnType, name) \ + * returnType name + * + * + * 3. CK_DECLARE_FUNCTION(returnType, name): A macro which makes + * an importable Cryptoki library function declaration out of a + * return type and a function name. It should be used in the + * following fashion: + * + * extern CK_DECLARE_FUNCTION(CK_RV, C_Initialize)( + * CK_VOID_PTR pReserved + * ); + * + * If you're using Microsoft Developer Studio 5.0 to declare a + * function in a Win32 Cryptoki .dll, it might be defined by: + * + * #define CK_DECLARE_FUNCTION(returnType, name) \ + * returnType __declspec(dllimport) name + * + * If you're using an earlier version of Microsoft Developer + * Studio to declare a function in a Win16 Cryptoki .dll, it + * might be defined by: + * + * #define CK_DECLARE_FUNCTION(returnType, name) \ + * returnType __export _far _pascal name + * + * In a UNIX environment, it might be defined by: + * + * #define CK_DECLARE_FUNCTION(returnType, name) \ + * returnType name + * + * + * 4. CK_DECLARE_FUNCTION_POINTER(returnType, name): A macro + * which makes a Cryptoki API function pointer declaration or + * function pointer type declaration out of a return type and a + * function name. It should be used in the following fashion: + * + * // Define funcPtr to be a pointer to a Cryptoki API function + * // taking arguments args and returning CK_RV. + * CK_DECLARE_FUNCTION_POINTER(CK_RV, funcPtr)(args); + * + * or + * + * // Define funcPtrType to be the type of a pointer to a + * // Cryptoki API function taking arguments args and returning + * // CK_RV, and then define funcPtr to be a variable of type + * // funcPtrType. + * typedef CK_DECLARE_FUNCTION_POINTER(CK_RV, funcPtrType)(args); + * funcPtrType funcPtr; + * + * If you're using Microsoft Developer Studio 5.0 to access + * functions in a Win32 Cryptoki .dll, in might be defined by: + * + * #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \ + * returnType __declspec(dllimport) (* name) + * + * If you're using an earlier version of Microsoft Developer + * Studio to access functions in a Win16 Cryptoki .dll, it might + * be defined by: + * + * #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \ + * returnType __export _far _pascal (* name) + * + * In a UNIX environment, it might be defined by: + * + * #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \ + * returnType (* name) + * + * + * 5. CK_CALLBACK_FUNCTION(returnType, name): A macro which makes + * a function pointer type for an application callback out of + * a return type for the callback and a name for the callback. + * It should be used in the following fashion: + * + * CK_CALLBACK_FUNCTION(CK_RV, myCallback)(args); + * + * to declare a function pointer, myCallback, to a callback + * which takes arguments args and returns a CK_RV. It can also + * be used like this: + * + * typedef CK_CALLBACK_FUNCTION(CK_RV, myCallbackType)(args); + * myCallbackType myCallback; + * + * If you're using Microsoft Developer Studio 5.0 to do Win32 + * Cryptoki development, it might be defined by: + * + * #define CK_CALLBACK_FUNCTION(returnType, name) \ + * returnType (* name) + * + * If you're using an earlier version of Microsoft Developer + * Studio to do Win16 development, it might be defined by: + * + * #define CK_CALLBACK_FUNCTION(returnType, name) \ + * returnType _far _pascal (* name) + * + * In a UNIX environment, it might be defined by: + * + * #define CK_CALLBACK_FUNCTION(returnType, name) \ + * returnType (* name) + * + * + * 6. NULL_PTR: This macro is the value of a NULL pointer. + * + * In any ANSI/ISO C environment (and in many others as well), + * this should best be defined by + * + * #ifndef NULL_PTR + * #define NULL_PTR 0 + * #endif + */ + + +/* All the various Cryptoki types and #define'd values are in the + * file pkcs11t.h. */ +#include "pkcs11t.h" + +#define __PASTE(x,y) x##y + + +/* ============================================================== + * Define the "extern" form of all the entry points. + * ============================================================== + */ + +#define CK_NEED_ARG_LIST 1 +#define CK_PKCS11_FUNCTION_INFO(name) \ + extern CK_DECLARE_FUNCTION(CK_RV, name) + +/* pkcs11f.h has all the information about the Cryptoki + * function prototypes. */ +#include "pkcs11f.h" + +#undef CK_NEED_ARG_LIST +#undef CK_PKCS11_FUNCTION_INFO + + +/* ============================================================== + * Define the typedef form of all the entry points. That is, for + * each Cryptoki function C_XXX, define a type CK_C_XXX which is + * a pointer to that kind of function. + * ============================================================== + */ + +#define CK_NEED_ARG_LIST 1 +#define CK_PKCS11_FUNCTION_INFO(name) \ + typedef CK_DECLARE_FUNCTION_POINTER(CK_RV, __PASTE(CK_,name)) + +/* pkcs11f.h has all the information about the Cryptoki + * function prototypes. */ +#include "pkcs11f.h" + +#undef CK_NEED_ARG_LIST +#undef CK_PKCS11_FUNCTION_INFO + + +/* ============================================================== + * Define structed vector of entry points. A CK_FUNCTION_LIST + * contains a CK_VERSION indicating a library's Cryptoki version + * and then a whole slew of function pointers to the routines in + * the library. This type was declared, but not defined, in + * pkcs11t.h. + * ============================================================== + */ + +#define CK_PKCS11_FUNCTION_INFO(name) \ + __PASTE(CK_,name) name; + +struct CK_FUNCTION_LIST { + + CK_VERSION version; /* Cryptoki version */ + +/* Pile all the function pointers into the CK_FUNCTION_LIST. */ +/* pkcs11f.h has all the information about the Cryptoki + * function prototypes. */ +#include "pkcs11f.h" + +}; + +#undef CK_PKCS11_FUNCTION_INFO + + +#undef __PASTE + +#ifdef __cplusplus +} +#endif + +#endif Index: openssl/crypto/engine/pkcs11f.h diff -u /dev/null openssl/crypto/engine/pkcs11f.h:1.1.1.1 --- /dev/null Mon Jun 13 15:26:30 2016 +++ openssl/crypto/engine/pkcs11f.h Wed Oct 24 23:27:09 2007 @@ -0,0 +1,912 @@ +/* pkcs11f.h include file for PKCS #11. */ +/* $Revision: 1.1.1.1 $ */ + +/* License to copy and use this software is granted provided that it is + * identified as "RSA Security Inc. PKCS #11 Cryptographic Token Interface + * (Cryptoki)" in all material mentioning or referencing this software. + + * License is also granted to make and use derivative works provided that + * such works are identified as "derived from the RSA Security Inc. PKCS #11 + * Cryptographic Token Interface (Cryptoki)" in all material mentioning or + * referencing the derived work. + + * RSA Security Inc. makes no representations concerning either the + * merchantability of this software or the suitability of this software for + * any particular purpose. It is provided "as is" without express or implied + * warranty of any kind. + */ + +/* This header file contains pretty much everything about all the */ +/* Cryptoki function prototypes. Because this information is */ +/* used for more than just declaring function prototypes, the */ +/* order of the functions appearing herein is important, and */ +/* should not be altered. */ + +/* General-purpose */ + +/* C_Initialize initializes the Cryptoki library. */ +CK_PKCS11_FUNCTION_INFO(C_Initialize) +#ifdef CK_NEED_ARG_LIST +( + CK_VOID_PTR pInitArgs /* if this is not NULL_PTR, it gets + * cast to CK_C_INITIALIZE_ARGS_PTR + * and dereferenced */ +); +#endif + + +/* C_Finalize indicates that an application is done with the + * Cryptoki library. */ +CK_PKCS11_FUNCTION_INFO(C_Finalize) +#ifdef CK_NEED_ARG_LIST +( + CK_VOID_PTR pReserved /* reserved. Should be NULL_PTR */ +); +#endif + + +/* C_GetInfo returns general information about Cryptoki. */ +CK_PKCS11_FUNCTION_INFO(C_GetInfo) +#ifdef CK_NEED_ARG_LIST +( + CK_INFO_PTR pInfo /* location that receives information */ +); +#endif + + +/* C_GetFunctionList returns the function list. */ +CK_PKCS11_FUNCTION_INFO(C_GetFunctionList) +#ifdef CK_NEED_ARG_LIST +( + CK_FUNCTION_LIST_PTR_PTR ppFunctionList /* receives pointer to + * function list */ +); +#endif + + + +/* Slot and token management */ + +/* C_GetSlotList obtains a list of slots in the system. */ +CK_PKCS11_FUNCTION_INFO(C_GetSlotList) +#ifdef CK_NEED_ARG_LIST +( + CK_BBOOL tokenPresent, /* only slots with tokens? */ + CK_SLOT_ID_PTR pSlotList, /* receives array of slot IDs */ + CK_ULONG_PTR pulCount /* receives number of slots */ +); +#endif + + +/* C_GetSlotInfo obtains information about a particular slot in + * the system. */ +CK_PKCS11_FUNCTION_INFO(C_GetSlotInfo) +#ifdef CK_NEED_ARG_LIST +( + CK_SLOT_ID slotID, /* the ID of the slot */ + CK_SLOT_INFO_PTR pInfo /* receives the slot information */ +); +#endif + + +/* C_GetTokenInfo obtains information about a particular token + * in the system. */ +CK_PKCS11_FUNCTION_INFO(C_GetTokenInfo) +#ifdef CK_NEED_ARG_LIST +( + CK_SLOT_ID slotID, /* ID of the token's slot */ + CK_TOKEN_INFO_PTR pInfo /* receives the token information */ +); +#endif + + +/* C_GetMechanismList obtains a list of mechanism types + * supported by a token. */ +CK_PKCS11_FUNCTION_INFO(C_GetMechanismList) +#ifdef CK_NEED_ARG_LIST +( + CK_SLOT_ID slotID, /* ID of token's slot */ + CK_MECHANISM_TYPE_PTR pMechanismList, /* gets mech. array */ + CK_ULONG_PTR pulCount /* gets # of mechs. */ +); +#endif + + +/* C_GetMechanismInfo obtains information about a particular + * mechanism possibly supported by a token. */ +CK_PKCS11_FUNCTION_INFO(C_GetMechanismInfo) +#ifdef CK_NEED_ARG_LIST +( + CK_SLOT_ID slotID, /* ID of the token's slot */ + CK_MECHANISM_TYPE type, /* type of mechanism */ + CK_MECHANISM_INFO_PTR pInfo /* receives mechanism info */ +); +#endif + + +/* C_InitToken initializes a token. */ +CK_PKCS11_FUNCTION_INFO(C_InitToken) +#ifdef CK_NEED_ARG_LIST +/* pLabel changed from CK_CHAR_PTR to CK_UTF8CHAR_PTR for v2.10 */ +( + CK_SLOT_ID slotID, /* ID of the token's slot */ + CK_UTF8CHAR_PTR pPin, /* the SO's initial PIN */ + CK_ULONG ulPinLen, /* length in bytes of the PIN */ + CK_UTF8CHAR_PTR pLabel /* 32-byte token label (blank padded) */ +); +#endif + + +/* C_InitPIN initializes the normal user's PIN. */ +CK_PKCS11_FUNCTION_INFO(C_InitPIN) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_UTF8CHAR_PTR pPin, /* the normal user's PIN */ + CK_ULONG ulPinLen /* length in bytes of the PIN */ +); +#endif + + +/* C_SetPIN modifies the PIN of the user who is logged in. */ +CK_PKCS11_FUNCTION_INFO(C_SetPIN) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_UTF8CHAR_PTR pOldPin, /* the old PIN */ + CK_ULONG ulOldLen, /* length of the old PIN */ + CK_UTF8CHAR_PTR pNewPin, /* the new PIN */ + CK_ULONG ulNewLen /* length of the new PIN */ +); +#endif + + + +/* Session management */ + +/* C_OpenSession opens a session between an application and a + * token. */ +CK_PKCS11_FUNCTION_INFO(C_OpenSession) +#ifdef CK_NEED_ARG_LIST +( + CK_SLOT_ID slotID, /* the slot's ID */ + CK_FLAGS flags, /* from CK_SESSION_INFO */ + CK_VOID_PTR pApplication, /* passed to callback */ + CK_NOTIFY Notify, /* callback function */ + CK_SESSION_HANDLE_PTR phSession /* gets session handle */ +); +#endif + + +/* C_CloseSession closes a session between an application and a + * token. */ +CK_PKCS11_FUNCTION_INFO(C_CloseSession) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession /* the session's handle */ +); +#endif + + +/* C_CloseAllSessions closes all sessions with a token. */ +CK_PKCS11_FUNCTION_INFO(C_CloseAllSessions) +#ifdef CK_NEED_ARG_LIST +( + CK_SLOT_ID slotID /* the token's slot */ +); +#endif + + +/* C_GetSessionInfo obtains information about the session. */ +CK_PKCS11_FUNCTION_INFO(C_GetSessionInfo) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_SESSION_INFO_PTR pInfo /* receives session info */ +); +#endif + + +/* C_GetOperationState obtains the state of the cryptographic operation + * in a session. */ +CK_PKCS11_FUNCTION_INFO(C_GetOperationState) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* session's handle */ + CK_BYTE_PTR pOperationState, /* gets state */ + CK_ULONG_PTR pulOperationStateLen /* gets state length */ +); +#endif + + +/* C_SetOperationState restores the state of the cryptographic + * operation in a session. */ +CK_PKCS11_FUNCTION_INFO(C_SetOperationState) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* session's handle */ + CK_BYTE_PTR pOperationState, /* holds state */ + CK_ULONG ulOperationStateLen, /* holds state length */ + CK_OBJECT_HANDLE hEncryptionKey, /* en/decryption key */ + CK_OBJECT_HANDLE hAuthenticationKey /* sign/verify key */ +); +#endif + + +/* C_Login logs a user into a token. */ +CK_PKCS11_FUNCTION_INFO(C_Login) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_USER_TYPE userType, /* the user type */ + CK_UTF8CHAR_PTR pPin, /* the user's PIN */ + CK_ULONG ulPinLen /* the length of the PIN */ +); +#endif + + +/* C_Logout logs a user out from a token. */ +CK_PKCS11_FUNCTION_INFO(C_Logout) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession /* the session's handle */ +); +#endif + + + +/* Object management */ + +/* C_CreateObject creates a new object. */ +CK_PKCS11_FUNCTION_INFO(C_CreateObject) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_ATTRIBUTE_PTR pTemplate, /* the object's template */ + CK_ULONG ulCount, /* attributes in template */ + CK_OBJECT_HANDLE_PTR phObject /* gets new object's handle. */ +); +#endif + + +/* C_CopyObject copies an object, creating a new object for the + * copy. */ +CK_PKCS11_FUNCTION_INFO(C_CopyObject) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_OBJECT_HANDLE hObject, /* the object's handle */ + CK_ATTRIBUTE_PTR pTemplate, /* template for new object */ + CK_ULONG ulCount, /* attributes in template */ + CK_OBJECT_HANDLE_PTR phNewObject /* receives handle of copy */ +); +#endif + + +/* C_DestroyObject destroys an object. */ +CK_PKCS11_FUNCTION_INFO(C_DestroyObject) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_OBJECT_HANDLE hObject /* the object's handle */ +); +#endif + + +/* C_GetObjectSize gets the size of an object in bytes. */ +CK_PKCS11_FUNCTION_INFO(C_GetObjectSize) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_OBJECT_HANDLE hObject, /* the object's handle */ + CK_ULONG_PTR pulSize /* receives size of object */ +); +#endif + + +/* C_GetAttributeValue obtains the value of one or more object + * attributes. */ +CK_PKCS11_FUNCTION_INFO(C_GetAttributeValue) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_OBJECT_HANDLE hObject, /* the object's handle */ + CK_ATTRIBUTE_PTR pTemplate, /* specifies attrs; gets vals */ + CK_ULONG ulCount /* attributes in template */ +); +#endif + + +/* C_SetAttributeValue modifies the value of one or more object + * attributes */ +CK_PKCS11_FUNCTION_INFO(C_SetAttributeValue) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_OBJECT_HANDLE hObject, /* the object's handle */ + CK_ATTRIBUTE_PTR pTemplate, /* specifies attrs and values */ + CK_ULONG ulCount /* attributes in template */ +); +#endif + + +/* C_FindObjectsInit initializes a search for token and session + * objects that match a template. */ +CK_PKCS11_FUNCTION_INFO(C_FindObjectsInit) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_ATTRIBUTE_PTR pTemplate, /* attribute values to match */ + CK_ULONG ulCount /* attrs in search template */ +); +#endif + + +/* C_FindObjects continues a search for token and session + * objects that match a template, obtaining additional object + * handles. */ +CK_PKCS11_FUNCTION_INFO(C_FindObjects) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* session's handle */ + CK_OBJECT_HANDLE_PTR phObject, /* gets obj. handles */ + CK_ULONG ulMaxObjectCount, /* max handles to get */ + CK_ULONG_PTR pulObjectCount /* actual # returned */ +); +#endif + + +/* C_FindObjectsFinal finishes a search for token and session + * objects. */ +CK_PKCS11_FUNCTION_INFO(C_FindObjectsFinal) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession /* the session's handle */ +); +#endif + + + +/* Encryption and decryption */ + +/* C_EncryptInit initializes an encryption operation. */ +CK_PKCS11_FUNCTION_INFO(C_EncryptInit) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_MECHANISM_PTR pMechanism, /* the encryption mechanism */ + CK_OBJECT_HANDLE hKey /* handle of encryption key */ +); +#endif + + +/* C_Encrypt encrypts single-part data. */ +CK_PKCS11_FUNCTION_INFO(C_Encrypt) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* session's handle */ + CK_BYTE_PTR pData, /* the plaintext data */ + CK_ULONG ulDataLen, /* bytes of plaintext */ + CK_BYTE_PTR pEncryptedData, /* gets ciphertext */ + CK_ULONG_PTR pulEncryptedDataLen /* gets c-text size */ +); +#endif + + +/* C_EncryptUpdate continues a multiple-part encryption + * operation. */ +CK_PKCS11_FUNCTION_INFO(C_EncryptUpdate) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* session's handle */ + CK_BYTE_PTR pPart, /* the plaintext data */ + CK_ULONG ulPartLen, /* plaintext data len */ + CK_BYTE_PTR pEncryptedPart, /* gets ciphertext */ + CK_ULONG_PTR pulEncryptedPartLen /* gets c-text size */ +); +#endif + + +/* C_EncryptFinal finishes a multiple-part encryption + * operation. */ +CK_PKCS11_FUNCTION_INFO(C_EncryptFinal) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* session handle */ + CK_BYTE_PTR pLastEncryptedPart, /* last c-text */ + CK_ULONG_PTR pulLastEncryptedPartLen /* gets last size */ +); +#endif + + +/* C_DecryptInit initializes a decryption operation. */ +CK_PKCS11_FUNCTION_INFO(C_DecryptInit) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_MECHANISM_PTR pMechanism, /* the decryption mechanism */ + CK_OBJECT_HANDLE hKey /* handle of decryption key */ +); +#endif + + +/* C_Decrypt decrypts encrypted data in a single part. */ +CK_PKCS11_FUNCTION_INFO(C_Decrypt) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* session's handle */ + CK_BYTE_PTR pEncryptedData, /* ciphertext */ + CK_ULONG ulEncryptedDataLen, /* ciphertext length */ + CK_BYTE_PTR pData, /* gets plaintext */ + CK_ULONG_PTR pulDataLen /* gets p-text size */ +); +#endif + + +/* C_DecryptUpdate continues a multiple-part decryption + * operation. */ +CK_PKCS11_FUNCTION_INFO(C_DecryptUpdate) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* session's handle */ + CK_BYTE_PTR pEncryptedPart, /* encrypted data */ + CK_ULONG ulEncryptedPartLen, /* input length */ + CK_BYTE_PTR pPart, /* gets plaintext */ + CK_ULONG_PTR pulPartLen /* p-text size */ +); +#endif + + +/* C_DecryptFinal finishes a multiple-part decryption + * operation. */ +CK_PKCS11_FUNCTION_INFO(C_DecryptFinal) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_BYTE_PTR pLastPart, /* gets plaintext */ + CK_ULONG_PTR pulLastPartLen /* p-text size */ +); +#endif + + + +/* Message digesting */ + +/* C_DigestInit initializes a message-digesting operation. */ +CK_PKCS11_FUNCTION_INFO(C_DigestInit) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_MECHANISM_PTR pMechanism /* the digesting mechanism */ +); +#endif + + +/* C_Digest digests data in a single part. */ +CK_PKCS11_FUNCTION_INFO(C_Digest) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_BYTE_PTR pData, /* data to be digested */ + CK_ULONG ulDataLen, /* bytes of data to digest */ + CK_BYTE_PTR pDigest, /* gets the message digest */ + CK_ULONG_PTR pulDigestLen /* gets digest length */ +); +#endif + + +/* C_DigestUpdate continues a multiple-part message-digesting + * operation. */ +CK_PKCS11_FUNCTION_INFO(C_DigestUpdate) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_BYTE_PTR pPart, /* data to be digested */ + CK_ULONG ulPartLen /* bytes of data to be digested */ +); +#endif + + +/* C_DigestKey continues a multi-part message-digesting + * operation, by digesting the value of a secret key as part of + * the data already digested. */ +CK_PKCS11_FUNCTION_INFO(C_DigestKey) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_OBJECT_HANDLE hKey /* secret key to digest */ +); +#endif + + +/* C_DigestFinal finishes a multiple-part message-digesting + * operation. */ +CK_PKCS11_FUNCTION_INFO(C_DigestFinal) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_BYTE_PTR pDigest, /* gets the message digest */ + CK_ULONG_PTR pulDigestLen /* gets byte count of digest */ +); +#endif + + + +/* Signing and MACing */ + +/* C_SignInit initializes a signature (private key encryption) + * operation, where the signature is (will be) an appendix to + * the data, and plaintext cannot be recovered from the + *signature. */ +CK_PKCS11_FUNCTION_INFO(C_SignInit) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_MECHANISM_PTR pMechanism, /* the signature mechanism */ + CK_OBJECT_HANDLE hKey /* handle of signature key */ +); +#endif + + +/* C_Sign signs (encrypts with private key) data in a single + * part, where the signature is (will be) an appendix to the + * data, and plaintext cannot be recovered from the signature. */ +CK_PKCS11_FUNCTION_INFO(C_Sign) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_BYTE_PTR pData, /* the data to sign */ + CK_ULONG ulDataLen, /* count of bytes to sign */ + CK_BYTE_PTR pSignature, /* gets the signature */ + CK_ULONG_PTR pulSignatureLen /* gets signature length */ +); +#endif + + +/* C_SignUpdate continues a multiple-part signature operation, + * where the signature is (will be) an appendix to the data, + * and plaintext cannot be recovered from the signature. */ +CK_PKCS11_FUNCTION_INFO(C_SignUpdate) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_BYTE_PTR pPart, /* the data to sign */ + CK_ULONG ulPartLen /* count of bytes to sign */ +); +#endif + + +/* C_SignFinal finishes a multiple-part signature operation, + * returning the signature. */ +CK_PKCS11_FUNCTION_INFO(C_SignFinal) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_BYTE_PTR pSignature, /* gets the signature */ + CK_ULONG_PTR pulSignatureLen /* gets signature length */ +); +#endif + + +/* C_SignRecoverInit initializes a signature operation, where + * the data can be recovered from the signature. */ +CK_PKCS11_FUNCTION_INFO(C_SignRecoverInit) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_MECHANISM_PTR pMechanism, /* the signature mechanism */ + CK_OBJECT_HANDLE hKey /* handle of the signature key */ +); +#endif + + +/* C_SignRecover signs data in a single operation, where the + * data can be recovered from the signature. */ +CK_PKCS11_FUNCTION_INFO(C_SignRecover) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_BYTE_PTR pData, /* the data to sign */ + CK_ULONG ulDataLen, /* count of bytes to sign */ + CK_BYTE_PTR pSignature, /* gets the signature */ + CK_ULONG_PTR pulSignatureLen /* gets signature length */ +); +#endif + + + +/* Verifying signatures and MACs */ + +/* C_VerifyInit initializes a verification operation, where the + * signature is an appendix to the data, and plaintext cannot + * cannot be recovered from the signature (e.g. DSA). */ +CK_PKCS11_FUNCTION_INFO(C_VerifyInit) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_MECHANISM_PTR pMechanism, /* the verification mechanism */ + CK_OBJECT_HANDLE hKey /* verification key */ +); +#endif + + +/* C_Verify verifies a signature in a single-part operation, + * where the signature is an appendix to the data, and plaintext + * cannot be recovered from the signature. */ +CK_PKCS11_FUNCTION_INFO(C_Verify) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_BYTE_PTR pData, /* signed data */ + CK_ULONG ulDataLen, /* length of signed data */ + CK_BYTE_PTR pSignature, /* signature */ + CK_ULONG ulSignatureLen /* signature length*/ +); +#endif + + +/* C_VerifyUpdate continues a multiple-part verification + * operation, where the signature is an appendix to the data, + * and plaintext cannot be recovered from the signature. */ +CK_PKCS11_FUNCTION_INFO(C_VerifyUpdate) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_BYTE_PTR pPart, /* signed data */ + CK_ULONG ulPartLen /* length of signed data */ +); +#endif + + +/* C_VerifyFinal finishes a multiple-part verification + * operation, checking the signature. */ +CK_PKCS11_FUNCTION_INFO(C_VerifyFinal) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_BYTE_PTR pSignature, /* signature to verify */ + CK_ULONG ulSignatureLen /* signature length */ +); +#endif + + +/* C_VerifyRecoverInit initializes a signature verification + * operation, where the data is recovered from the signature. */ +CK_PKCS11_FUNCTION_INFO(C_VerifyRecoverInit) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_MECHANISM_PTR pMechanism, /* the verification mechanism */ + CK_OBJECT_HANDLE hKey /* verification key */ +); +#endif + + +/* C_VerifyRecover verifies a signature in a single-part + * operation, where the data is recovered from the signature. */ +CK_PKCS11_FUNCTION_INFO(C_VerifyRecover) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_BYTE_PTR pSignature, /* signature to verify */ + CK_ULONG ulSignatureLen, /* signature length */ + CK_BYTE_PTR pData, /* gets signed data */ + CK_ULONG_PTR pulDataLen /* gets signed data len */ +); +#endif + + + +/* Dual-function cryptographic operations */ + +/* C_DigestEncryptUpdate continues a multiple-part digesting + * and encryption operation. */ +CK_PKCS11_FUNCTION_INFO(C_DigestEncryptUpdate) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* session's handle */ + CK_BYTE_PTR pPart, /* the plaintext data */ + CK_ULONG ulPartLen, /* plaintext length */ + CK_BYTE_PTR pEncryptedPart, /* gets ciphertext */ + CK_ULONG_PTR pulEncryptedPartLen /* gets c-text length */ +); +#endif + + +/* C_DecryptDigestUpdate continues a multiple-part decryption and + * digesting operation. */ +CK_PKCS11_FUNCTION_INFO(C_DecryptDigestUpdate) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* session's handle */ + CK_BYTE_PTR pEncryptedPart, /* ciphertext */ + CK_ULONG ulEncryptedPartLen, /* ciphertext length */ + CK_BYTE_PTR pPart, /* gets plaintext */ + CK_ULONG_PTR pulPartLen /* gets plaintext len */ +); +#endif + + +/* C_SignEncryptUpdate continues a multiple-part signing and + * encryption operation. */ +CK_PKCS11_FUNCTION_INFO(C_SignEncryptUpdate) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* session's handle */ + CK_BYTE_PTR pPart, /* the plaintext data */ + CK_ULONG ulPartLen, /* plaintext length */ + CK_BYTE_PTR pEncryptedPart, /* gets ciphertext */ + CK_ULONG_PTR pulEncryptedPartLen /* gets c-text length */ +); +#endif + + +/* C_DecryptVerifyUpdate continues a multiple-part decryption and + * verify operation. */ +CK_PKCS11_FUNCTION_INFO(C_DecryptVerifyUpdate) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* session's handle */ + CK_BYTE_PTR pEncryptedPart, /* ciphertext */ + CK_ULONG ulEncryptedPartLen, /* ciphertext length */ + CK_BYTE_PTR pPart, /* gets plaintext */ + CK_ULONG_PTR pulPartLen /* gets p-text length */ +); +#endif + + + +/* Key management */ + +/* C_GenerateKey generates a secret key, creating a new key + * object. */ +CK_PKCS11_FUNCTION_INFO(C_GenerateKey) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_MECHANISM_PTR pMechanism, /* key generation mech. */ + CK_ATTRIBUTE_PTR pTemplate, /* template for new key */ + CK_ULONG ulCount, /* # of attrs in template */ + CK_OBJECT_HANDLE_PTR phKey /* gets handle of new key */ +); +#endif + + +/* C_GenerateKeyPair generates a public-key/private-key pair, + * creating new key objects. */ +CK_PKCS11_FUNCTION_INFO(C_GenerateKeyPair) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* session + * handle */ + CK_MECHANISM_PTR pMechanism, /* key-gen + * mech. */ + CK_ATTRIBUTE_PTR pPublicKeyTemplate, /* template + * for pub. + * key */ + CK_ULONG ulPublicKeyAttributeCount, /* # pub. + * attrs. */ + CK_ATTRIBUTE_PTR pPrivateKeyTemplate, /* template + * for priv. + * key */ + CK_ULONG ulPrivateKeyAttributeCount, /* # priv. + * attrs. */ + CK_OBJECT_HANDLE_PTR phPublicKey, /* gets pub. + * key + * handle */ + CK_OBJECT_HANDLE_PTR phPrivateKey /* gets + * priv. key + * handle */ +); +#endif + + +/* C_WrapKey wraps (i.e., encrypts) a key. */ +CK_PKCS11_FUNCTION_INFO(C_WrapKey) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_MECHANISM_PTR pMechanism, /* the wrapping mechanism */ + CK_OBJECT_HANDLE hWrappingKey, /* wrapping key */ + CK_OBJECT_HANDLE hKey, /* key to be wrapped */ + CK_BYTE_PTR pWrappedKey, /* gets wrapped key */ + CK_ULONG_PTR pulWrappedKeyLen /* gets wrapped key size */ +); +#endif + + +/* C_UnwrapKey unwraps (decrypts) a wrapped key, creating a new + * key object. */ +CK_PKCS11_FUNCTION_INFO(C_UnwrapKey) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* session's handle */ + CK_MECHANISM_PTR pMechanism, /* unwrapping mech. */ + CK_OBJECT_HANDLE hUnwrappingKey, /* unwrapping key */ + CK_BYTE_PTR pWrappedKey, /* the wrapped key */ + CK_ULONG ulWrappedKeyLen, /* wrapped key len */ + CK_ATTRIBUTE_PTR pTemplate, /* new key template */ + CK_ULONG ulAttributeCount, /* template length */ + CK_OBJECT_HANDLE_PTR phKey /* gets new handle */ +); +#endif + + +/* C_DeriveKey derives a key from a base key, creating a new key + * object. */ +CK_PKCS11_FUNCTION_INFO(C_DeriveKey) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* session's handle */ + CK_MECHANISM_PTR pMechanism, /* key deriv. mech. */ + CK_OBJECT_HANDLE hBaseKey, /* base key */ + CK_ATTRIBUTE_PTR pTemplate, /* new key template */ + CK_ULONG ulAttributeCount, /* template length */ + CK_OBJECT_HANDLE_PTR phKey /* gets new handle */ +); +#endif + + + +/* Random number generation */ + +/* C_SeedRandom mixes additional seed material into the token's + * random number generator. */ +CK_PKCS11_FUNCTION_INFO(C_SeedRandom) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_BYTE_PTR pSeed, /* the seed material */ + CK_ULONG ulSeedLen /* length of seed material */ +); +#endif + + +/* C_GenerateRandom generates random data. */ +CK_PKCS11_FUNCTION_INFO(C_GenerateRandom) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_BYTE_PTR RandomData, /* receives the random data */ + CK_ULONG ulRandomLen /* # of bytes to generate */ +); +#endif + + + +/* Parallel function management */ + +/* C_GetFunctionStatus is a legacy function; it obtains an + * updated status of a function running in parallel with an + * application. */ +CK_PKCS11_FUNCTION_INFO(C_GetFunctionStatus) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession /* the session's handle */ +); +#endif + + +/* C_CancelFunction is a legacy function; it cancels a function + * running in parallel. */ +CK_PKCS11_FUNCTION_INFO(C_CancelFunction) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession /* the session's handle */ +); +#endif + + + +/* Functions added in for Cryptoki Version 2.01 or later */ + +/* C_WaitForSlotEvent waits for a slot event (token insertion, + * removal, etc.) to occur. */ +CK_PKCS11_FUNCTION_INFO(C_WaitForSlotEvent) +#ifdef CK_NEED_ARG_LIST +( + CK_FLAGS flags, /* blocking/nonblocking flag */ + CK_SLOT_ID_PTR pSlot, /* location that receives the slot ID */ + CK_VOID_PTR pRserved /* reserved. Should be NULL_PTR */ +); +#endif Index: openssl/crypto/engine/pkcs11t.h diff -u /dev/null openssl/crypto/engine/pkcs11t.h:1.2 --- /dev/null Mon Jun 13 15:26:30 2016 +++ openssl/crypto/engine/pkcs11t.h Sat Aug 30 11:58:07 2008 @@ -0,0 +1,1885 @@ +/* pkcs11t.h include file for PKCS #11. */ +/* $Revision: 1.2 $ */ + +/* License to copy and use this software is granted provided that it is + * identified as "RSA Security Inc. PKCS #11 Cryptographic Token Interface + * (Cryptoki)" in all material mentioning or referencing this software. + + * License is also granted to make and use derivative works provided that + * such works are identified as "derived from the RSA Security Inc. PKCS #11 + * Cryptographic Token Interface (Cryptoki)" in all material mentioning or + * referencing the derived work. + + * RSA Security Inc. makes no representations concerning either the + * merchantability of this software or the suitability of this software for + * any particular purpose. It is provided "as is" without express or implied + * warranty of any kind. + */ + +/* See top of pkcs11.h for information about the macros that + * must be defined and the structure-packing conventions that + * must be set before including this file. */ + +#ifndef _PKCS11T_H_ +#define _PKCS11T_H_ 1 + +#define CRYPTOKI_VERSION_MAJOR 2 +#define CRYPTOKI_VERSION_MINOR 20 +#define CRYPTOKI_VERSION_AMENDMENT 3 + +#define CK_TRUE 1 +#define CK_FALSE 0 + +#ifndef CK_DISABLE_TRUE_FALSE +#ifndef FALSE +#define FALSE CK_FALSE +#endif + +#ifndef TRUE +#define TRUE CK_TRUE +#endif +#endif + +/* an unsigned 8-bit value */ +typedef unsigned char CK_BYTE; + +/* an unsigned 8-bit character */ +typedef CK_BYTE CK_CHAR; + +/* an 8-bit UTF-8 character */ +typedef CK_BYTE CK_UTF8CHAR; + +/* a BYTE-sized Boolean flag */ +typedef CK_BYTE CK_BBOOL; + +/* an unsigned value, at least 32 bits long */ +typedef unsigned long int CK_ULONG; + +/* a signed value, the same size as a CK_ULONG */ +/* CK_LONG is new for v2.0 */ +typedef long int CK_LONG; + +/* at least 32 bits; each bit is a Boolean flag */ +typedef CK_ULONG CK_FLAGS; + + +/* some special values for certain CK_ULONG variables */ +#define CK_UNAVAILABLE_INFORMATION (~0UL) +#define CK_EFFECTIVELY_INFINITE 0 + + +typedef CK_BYTE CK_PTR CK_BYTE_PTR; +typedef CK_CHAR CK_PTR CK_CHAR_PTR; +typedef CK_UTF8CHAR CK_PTR CK_UTF8CHAR_PTR; +typedef CK_ULONG CK_PTR CK_ULONG_PTR; +typedef void CK_PTR CK_VOID_PTR; + +/* Pointer to a CK_VOID_PTR-- i.e., pointer to pointer to void */ +typedef CK_VOID_PTR CK_PTR CK_VOID_PTR_PTR; + + +/* The following value is always invalid if used as a session */ +/* handle or object handle */ +#define CK_INVALID_HANDLE 0 + + +typedef struct CK_VERSION { + CK_BYTE major; /* integer portion of version number */ + CK_BYTE minor; /* 1/100ths portion of version number */ +} CK_VERSION; + +typedef CK_VERSION CK_PTR CK_VERSION_PTR; + + +typedef struct CK_INFO { + /* manufacturerID and libraryDecription have been changed from + * CK_CHAR to CK_UTF8CHAR for v2.10 */ + CK_VERSION cryptokiVersion; /* Cryptoki interface ver */ + CK_UTF8CHAR manufacturerID[32]; /* blank padded */ + CK_FLAGS flags; /* must be zero */ + + /* libraryDescription and libraryVersion are new for v2.0 */ + CK_UTF8CHAR libraryDescription[32]; /* blank padded */ + CK_VERSION libraryVersion; /* version of library */ +} CK_INFO; + +typedef CK_INFO CK_PTR CK_INFO_PTR; + + +/* CK_NOTIFICATION enumerates the types of notifications that + * Cryptoki provides to an application */ +/* CK_NOTIFICATION has been changed from an enum to a CK_ULONG + * for v2.0 */ +typedef CK_ULONG CK_NOTIFICATION; +#define CKN_SURRENDER 0 + +/* The following notification is new for PKCS #11 v2.20 amendment 3 */ +#define CKN_OTP_CHANGED 1 + + +typedef CK_ULONG CK_SLOT_ID; + +typedef CK_SLOT_ID CK_PTR CK_SLOT_ID_PTR; + + +/* CK_SLOT_INFO provides information about a slot */ +typedef struct CK_SLOT_INFO { + /* slotDescription and manufacturerID have been changed from + * CK_CHAR to CK_UTF8CHAR for v2.10 */ + CK_UTF8CHAR slotDescription[64]; /* blank padded */ + CK_UTF8CHAR manufacturerID[32]; /* blank padded */ + CK_FLAGS flags; + + /* hardwareVersion and firmwareVersion are new for v2.0 */ + CK_VERSION hardwareVersion; /* version of hardware */ + CK_VERSION firmwareVersion; /* version of firmware */ +} CK_SLOT_INFO; + +/* flags: bit flags that provide capabilities of the slot + * Bit Flag Mask Meaning + */ +#define CKF_TOKEN_PRESENT 0x00000001 /* a token is there */ +#define CKF_REMOVABLE_DEVICE 0x00000002 /* removable devices*/ +#define CKF_HW_SLOT 0x00000004 /* hardware slot */ + +typedef CK_SLOT_INFO CK_PTR CK_SLOT_INFO_PTR; + + +/* CK_TOKEN_INFO provides information about a token */ +typedef struct CK_TOKEN_INFO { + /* label, manufacturerID, and model have been changed from + * CK_CHAR to CK_UTF8CHAR for v2.10 */ + CK_UTF8CHAR label[32]; /* blank padded */ + CK_UTF8CHAR manufacturerID[32]; /* blank padded */ + CK_UTF8CHAR model[16]; /* blank padded */ + CK_CHAR serialNumber[16]; /* blank padded */ + CK_FLAGS flags; /* see below */ + + /* ulMaxSessionCount, ulSessionCount, ulMaxRwSessionCount, + * ulRwSessionCount, ulMaxPinLen, and ulMinPinLen have all been + * changed from CK_USHORT to CK_ULONG for v2.0 */ + CK_ULONG ulMaxSessionCount; /* max open sessions */ + CK_ULONG ulSessionCount; /* sess. now open */ + CK_ULONG ulMaxRwSessionCount; /* max R/W sessions */ + CK_ULONG ulRwSessionCount; /* R/W sess. now open */ + CK_ULONG ulMaxPinLen; /* in bytes */ + CK_ULONG ulMinPinLen; /* in bytes */ + CK_ULONG ulTotalPublicMemory; /* in bytes */ + CK_ULONG ulFreePublicMemory; /* in bytes */ + CK_ULONG ulTotalPrivateMemory; /* in bytes */ + CK_ULONG ulFreePrivateMemory; /* in bytes */ + + /* hardwareVersion, firmwareVersion, and time are new for + * v2.0 */ + CK_VERSION hardwareVersion; /* version of hardware */ + CK_VERSION firmwareVersion; /* version of firmware */ + CK_CHAR utcTime[16]; /* time */ +} CK_TOKEN_INFO; + +/* The flags parameter is defined as follows: + * Bit Flag Mask Meaning + */ +#define CKF_RNG 0x00000001 /* has random # + * generator */ +#define CKF_WRITE_PROTECTED 0x00000002 /* token is + * write- + * protected */ +#define CKF_LOGIN_REQUIRED 0x00000004 /* user must + * login */ +#define CKF_USER_PIN_INITIALIZED 0x00000008 /* normal user's + * PIN is set */ + +/* CKF_RESTORE_KEY_NOT_NEEDED is new for v2.0. If it is set, + * that means that *every* time the state of cryptographic + * operations of a session is successfully saved, all keys + * needed to continue those operations are stored in the state */ +#define CKF_RESTORE_KEY_NOT_NEEDED 0x00000020 + +/* CKF_CLOCK_ON_TOKEN is new for v2.0. If it is set, that means + * that the token has some sort of clock. The time on that + * clock is returned in the token info structure */ +#define CKF_CLOCK_ON_TOKEN 0x00000040 + +/* CKF_PROTECTED_AUTHENTICATION_PATH is new for v2.0. If it is + * set, that means that there is some way for the user to login + * without sending a PIN through the Cryptoki library itself */ +#define CKF_PROTECTED_AUTHENTICATION_PATH 0x00000100 + +/* CKF_DUAL_CRYPTO_OPERATIONS is new for v2.0. If it is true, + * that means that a single session with the token can perform + * dual simultaneous cryptographic operations (digest and + * encrypt; decrypt and digest; sign and encrypt; and decrypt + * and sign) */ +#define CKF_DUAL_CRYPTO_OPERATIONS 0x00000200 + +/* CKF_TOKEN_INITIALIZED if new for v2.10. If it is true, the + * token has been initialized using C_InitializeToken or an + * equivalent mechanism outside the scope of PKCS #11. + * Calling C_InitializeToken when this flag is set will cause + * the token to be reinitialized. */ +#define CKF_TOKEN_INITIALIZED 0x00000400 + +/* CKF_SECONDARY_AUTHENTICATION if new for v2.10. If it is + * true, the token supports secondary authentication for + * private key objects. This flag is deprecated in v2.11 and + onwards. */ +#define CKF_SECONDARY_AUTHENTICATION 0x00000800 + +/* CKF_USER_PIN_COUNT_LOW if new for v2.10. If it is true, an + * incorrect user login PIN has been entered at least once + * since the last successful authentication. */ +#define CKF_USER_PIN_COUNT_LOW 0x00010000 + +/* CKF_USER_PIN_FINAL_TRY if new for v2.10. If it is true, + * supplying an incorrect user PIN will it to become locked. */ +#define CKF_USER_PIN_FINAL_TRY 0x00020000 + +/* CKF_USER_PIN_LOCKED if new for v2.10. If it is true, the + * user PIN has been locked. User login to the token is not + * possible. */ +#define CKF_USER_PIN_LOCKED 0x00040000 + +/* CKF_USER_PIN_TO_BE_CHANGED if new for v2.10. If it is true, + * the user PIN value is the default value set by token + * initialization or manufacturing, or the PIN has been + * expired by the card. */ +#define CKF_USER_PIN_TO_BE_CHANGED 0x00080000 + +/* CKF_SO_PIN_COUNT_LOW if new for v2.10. If it is true, an + * incorrect SO login PIN has been entered at least once since + * the last successful authentication. */ +#define CKF_SO_PIN_COUNT_LOW 0x00100000 + +/* CKF_SO_PIN_FINAL_TRY if new for v2.10. If it is true, + * supplying an incorrect SO PIN will it to become locked. */ +#define CKF_SO_PIN_FINAL_TRY 0x00200000 + +/* CKF_SO_PIN_LOCKED if new for v2.10. If it is true, the SO + * PIN has been locked. SO login to the token is not possible. + */ +#define CKF_SO_PIN_LOCKED 0x00400000 + +/* CKF_SO_PIN_TO_BE_CHANGED if new for v2.10. If it is true, + * the SO PIN value is the default value set by token + * initialization or manufacturing, or the PIN has been + * expired by the card. */ +#define CKF_SO_PIN_TO_BE_CHANGED 0x00800000 + +typedef CK_TOKEN_INFO CK_PTR CK_TOKEN_INFO_PTR; + + +/* CK_SESSION_HANDLE is a Cryptoki-assigned value that + * identifies a session */ +typedef CK_ULONG CK_SESSION_HANDLE; + +typedef CK_SESSION_HANDLE CK_PTR CK_SESSION_HANDLE_PTR; + + +/* CK_USER_TYPE enumerates the types of Cryptoki users */ +/* CK_USER_TYPE has been changed from an enum to a CK_ULONG for + * v2.0 */ +typedef CK_ULONG CK_USER_TYPE; +/* Security Officer */ +#define CKU_SO 0 +/* Normal user */ +#define CKU_USER 1 +/* Context specific (added in v2.20) */ +#define CKU_CONTEXT_SPECIFIC 2 + +/* CK_STATE enumerates the session states */ +/* CK_STATE has been changed from an enum to a CK_ULONG for + * v2.0 */ +typedef CK_ULONG CK_STATE; +#define CKS_RO_PUBLIC_SESSION 0 +#define CKS_RO_USER_FUNCTIONS 1 +#define CKS_RW_PUBLIC_SESSION 2 +#define CKS_RW_USER_FUNCTIONS 3 +#define CKS_RW_SO_FUNCTIONS 4 + + +/* CK_SESSION_INFO provides information about a session */ +typedef struct CK_SESSION_INFO { + CK_SLOT_ID slotID; + CK_STATE state; + CK_FLAGS flags; /* see below */ + + /* ulDeviceError was changed from CK_USHORT to CK_ULONG for + * v2.0 */ + CK_ULONG ulDeviceError; /* device-dependent error code */ +} CK_SESSION_INFO; + +/* The flags are defined in the following table: + * Bit Flag Mask Meaning + */ +#define CKF_RW_SESSION 0x00000002 /* session is r/w */ +#define CKF_SERIAL_SESSION 0x00000004 /* no parallel */ + +typedef CK_SESSION_INFO CK_PTR CK_SESSION_INFO_PTR; + + +/* CK_OBJECT_HANDLE is a token-specific identifier for an + * object */ +typedef CK_ULONG CK_OBJECT_HANDLE; + +typedef CK_OBJECT_HANDLE CK_PTR CK_OBJECT_HANDLE_PTR; + + +/* CK_OBJECT_CLASS is a value that identifies the classes (or + * types) of objects that Cryptoki recognizes. It is defined + * as follows: */ +/* CK_OBJECT_CLASS was changed from CK_USHORT to CK_ULONG for + * v2.0 */ +typedef CK_ULONG CK_OBJECT_CLASS; + +/* The following classes of objects are defined: */ +/* CKO_HW_FEATURE is new for v2.10 */ +/* CKO_DOMAIN_PARAMETERS is new for v2.11 */ +/* CKO_MECHANISM is new for v2.20 */ +#define CKO_DATA 0x00000000 +#define CKO_CERTIFICATE 0x00000001 +#define CKO_PUBLIC_KEY 0x00000002 +#define CKO_PRIVATE_KEY 0x00000003 +#define CKO_SECRET_KEY 0x00000004 +#define CKO_HW_FEATURE 0x00000005 +#define CKO_DOMAIN_PARAMETERS 0x00000006 +#define CKO_MECHANISM 0x00000007 + +/* CKO_OTP_KEY is new for PKCS #11 v2.20 amendment 1 */ +#define CKO_OTP_KEY 0x00000008 + +#define CKO_VENDOR_DEFINED 0x80000000 + +typedef CK_OBJECT_CLASS CK_PTR CK_OBJECT_CLASS_PTR; + +/* CK_HW_FEATURE_TYPE is new for v2.10. CK_HW_FEATURE_TYPE is a + * value that identifies the hardware feature type of an object + * with CK_OBJECT_CLASS equal to CKO_HW_FEATURE. */ +typedef CK_ULONG CK_HW_FEATURE_TYPE; + +/* The following hardware feature types are defined */ +/* CKH_USER_INTERFACE is new for v2.20 */ +#define CKH_MONOTONIC_COUNTER 0x00000001 +#define CKH_CLOCK 0x00000002 +#define CKH_USER_INTERFACE 0x00000003 +#define CKH_VENDOR_DEFINED 0x80000000 + +/* CK_KEY_TYPE is a value that identifies a key type */ +/* CK_KEY_TYPE was changed from CK_USHORT to CK_ULONG for v2.0 */ +typedef CK_ULONG CK_KEY_TYPE; + +/* the following key types are defined: */ +#define CKK_RSA 0x00000000 +#define CKK_DSA 0x00000001 +#define CKK_DH 0x00000002 + +/* CKK_ECDSA and CKK_KEA are new for v2.0 */ +/* CKK_ECDSA is deprecated in v2.11, CKK_EC is preferred. */ +#define CKK_ECDSA 0x00000003 +#define CKK_EC 0x00000003 +#define CKK_X9_42_DH 0x00000004 +#define CKK_KEA 0x00000005 + +#define CKK_GENERIC_SECRET 0x00000010 +#define CKK_RC2 0x00000011 +#define CKK_RC4 0x00000012 +#define CKK_DES 0x00000013 +#define CKK_DES2 0x00000014 +#define CKK_DES3 0x00000015 + +/* all these key types are new for v2.0 */ +#define CKK_CAST 0x00000016 +#define CKK_CAST3 0x00000017 +/* CKK_CAST5 is deprecated in v2.11, CKK_CAST128 is preferred. */ +#define CKK_CAST5 0x00000018 +#define CKK_CAST128 0x00000018 +#define CKK_RC5 0x00000019 +#define CKK_IDEA 0x0000001A +#define CKK_SKIPJACK 0x0000001B +#define CKK_BATON 0x0000001C +#define CKK_JUNIPER 0x0000001D +#define CKK_CDMF 0x0000001E +#define CKK_AES 0x0000001F + +/* BlowFish and TwoFish are new for v2.20 */ +#define CKK_BLOWFISH 0x00000020 +#define CKK_TWOFISH 0x00000021 + +/* SecurID, HOTP, and ACTI are new for PKCS #11 v2.20 amendment 1 */ +#define CKK_SECURID 0x00000022 +#define CKK_HOTP 0x00000023 +#define CKK_ACTI 0x00000024 + +/* Camellia is new for PKCS #11 v2.20 amendment 3 */ +#define CKK_CAMELLIA 0x00000025 +/* ARIA is new for PKCS #11 v2.20 amendment 3 */ +#define CKK_ARIA 0x00000026 + + +#define CKK_VENDOR_DEFINED 0x80000000 + + +/* CK_CERTIFICATE_TYPE is a value that identifies a certificate + * type */ +/* CK_CERTIFICATE_TYPE was changed from CK_USHORT to CK_ULONG + * for v2.0 */ +typedef CK_ULONG CK_CERTIFICATE_TYPE; + +/* The following certificate types are defined: */ +/* CKC_X_509_ATTR_CERT is new for v2.10 */ +/* CKC_WTLS is new for v2.20 */ +#define CKC_X_509 0x00000000 +#define CKC_X_509_ATTR_CERT 0x00000001 +#define CKC_WTLS 0x00000002 +#define CKC_VENDOR_DEFINED 0x80000000 + + +/* CK_ATTRIBUTE_TYPE is a value that identifies an attribute + * type */ +/* CK_ATTRIBUTE_TYPE was changed from CK_USHORT to CK_ULONG for + * v2.0 */ +typedef CK_ULONG CK_ATTRIBUTE_TYPE; + +/* The CKF_ARRAY_ATTRIBUTE flag identifies an attribute which + consists of an array of values. */ +#define CKF_ARRAY_ATTRIBUTE 0x40000000 + +/* The following OTP-related defines are new for PKCS #11 v2.20 amendment 1 + and relates to the CKA_OTP_FORMAT attribute */ +#define CK_OTP_FORMAT_DECIMAL 0 +#define CK_OTP_FORMAT_HEXADECIMAL 1 +#define CK_OTP_FORMAT_ALPHANUMERIC 2 +#define CK_OTP_FORMAT_BINARY 3 + +/* The following OTP-related defines are new for PKCS #11 v2.20 amendment 1 + and relates to the CKA_OTP_..._REQUIREMENT attributes */ +#define CK_OTP_PARAM_IGNORED 0 +#define CK_OTP_PARAM_OPTIONAL 1 +#define CK_OTP_PARAM_MANDATORY 2 + +/* The following attribute types are defined: */ +#define CKA_CLASS 0x00000000 +#define CKA_TOKEN 0x00000001 +#define CKA_PRIVATE 0x00000002 +#define CKA_LABEL 0x00000003 +#define CKA_APPLICATION 0x00000010 +#define CKA_VALUE 0x00000011 + +/* CKA_OBJECT_ID is new for v2.10 */ +#define CKA_OBJECT_ID 0x00000012 + +#define CKA_CERTIFICATE_TYPE 0x00000080 +#define CKA_ISSUER 0x00000081 +#define CKA_SERIAL_NUMBER 0x00000082 + +/* CKA_AC_ISSUER, CKA_OWNER, and CKA_ATTR_TYPES are new + * for v2.10 */ +#define CKA_AC_ISSUER 0x00000083 +#define CKA_OWNER 0x00000084 +#define CKA_ATTR_TYPES 0x00000085 + +/* CKA_TRUSTED is new for v2.11 */ +#define CKA_TRUSTED 0x00000086 + +/* CKA_CERTIFICATE_CATEGORY ... + * CKA_CHECK_VALUE are new for v2.20 */ +#define CKA_CERTIFICATE_CATEGORY 0x00000087 +#define CKA_JAVA_MIDP_SECURITY_DOMAIN 0x00000088 +#define CKA_URL 0x00000089 +#define CKA_HASH_OF_SUBJECT_PUBLIC_KEY 0x0000008A +#define CKA_HASH_OF_ISSUER_PUBLIC_KEY 0x0000008B +#define CKA_CHECK_VALUE 0x00000090 + +#define CKA_KEY_TYPE 0x00000100 +#define CKA_SUBJECT 0x00000101 +#define CKA_ID 0x00000102 +#define CKA_SENSITIVE 0x00000103 +#define CKA_ENCRYPT 0x00000104 +#define CKA_DECRYPT 0x00000105 +#define CKA_WRAP 0x00000106 +#define CKA_UNWRAP 0x00000107 +#define CKA_SIGN 0x00000108 +#define CKA_SIGN_RECOVER 0x00000109 +#define CKA_VERIFY 0x0000010A +#define CKA_VERIFY_RECOVER 0x0000010B +#define CKA_DERIVE 0x0000010C +#define CKA_START_DATE 0x00000110 +#define CKA_END_DATE 0x00000111 +#define CKA_MODULUS 0x00000120 +#define CKA_MODULUS_BITS 0x00000121 +#define CKA_PUBLIC_EXPONENT 0x00000122 +#define CKA_PRIVATE_EXPONENT 0x00000123 +#define CKA_PRIME_1 0x00000124 +#define CKA_PRIME_2 0x00000125 +#define CKA_EXPONENT_1 0x00000126 +#define CKA_EXPONENT_2 0x00000127 +#define CKA_COEFFICIENT 0x00000128 +#define CKA_PRIME 0x00000130 +#define CKA_SUBPRIME 0x00000131 +#define CKA_BASE 0x00000132 + +/* CKA_PRIME_BITS and CKA_SUB_PRIME_BITS are new for v2.11 */ +#define CKA_PRIME_BITS 0x00000133 +#define CKA_SUBPRIME_BITS 0x00000134 +#define CKA_SUB_PRIME_BITS CKA_SUBPRIME_BITS +/* (To retain backwards-compatibility) */ + +#define CKA_VALUE_BITS 0x00000160 +#define CKA_VALUE_LEN 0x00000161 + +/* CKA_EXTRACTABLE, CKA_LOCAL, CKA_NEVER_EXTRACTABLE, + * CKA_ALWAYS_SENSITIVE, CKA_MODIFIABLE, CKA_ECDSA_PARAMS, + * and CKA_EC_POINT are new for v2.0 */ +#define CKA_EXTRACTABLE 0x00000162 +#define CKA_LOCAL 0x00000163 +#define CKA_NEVER_EXTRACTABLE 0x00000164 +#define CKA_ALWAYS_SENSITIVE 0x00000165 + +/* CKA_KEY_GEN_MECHANISM is new for v2.11 */ +#define CKA_KEY_GEN_MECHANISM 0x00000166 + +#define CKA_MODIFIABLE 0x00000170 + +/* CKA_ECDSA_PARAMS is deprecated in v2.11, + * CKA_EC_PARAMS is preferred. */ +#define CKA_ECDSA_PARAMS 0x00000180 +#define CKA_EC_PARAMS 0x00000180 + +#define CKA_EC_POINT 0x00000181 + +/* CKA_SECONDARY_AUTH, CKA_AUTH_PIN_FLAGS, + * are new for v2.10. Deprecated in v2.11 and onwards. */ +#define CKA_SECONDARY_AUTH 0x00000200 +#define CKA_AUTH_PIN_FLAGS 0x00000201 + +/* CKA_ALWAYS_AUTHENTICATE ... + * CKA_UNWRAP_TEMPLATE are new for v2.20 */ +#define CKA_ALWAYS_AUTHENTICATE 0x00000202 + +#define CKA_WRAP_WITH_TRUSTED 0x00000210 +#define CKA_WRAP_TEMPLATE (CKF_ARRAY_ATTRIBUTE|0x00000211) +#define CKA_UNWRAP_TEMPLATE (CKF_ARRAY_ATTRIBUTE|0x00000212) + +/* CKA_OTP... atttributes are new for PKCS #11 v2.20 amendment 3. */ +#define CKA_OTP_FORMAT 0x00000220 +#define CKA_OTP_LENGTH 0x00000221 +#define CKA_OTP_TIME_INTERVAL 0x00000222 +#define CKA_OTP_USER_FRIENDLY_MODE 0x00000223 +#define CKA_OTP_CHALLENGE_REQUIREMENT 0x00000224 +#define CKA_OTP_TIME_REQUIREMENT 0x00000225 +#define CKA_OTP_COUNTER_REQUIREMENT 0x00000226 +#define CKA_OTP_PIN_REQUIREMENT 0x00000227 +#define CKA_OTP_COUNTER 0x0000022E +#define CKA_OTP_TIME 0x0000022F +#define CKA_OTP_USER_IDENTIFIER 0x0000022A +#define CKA_OTP_SERVICE_IDENTIFIER 0x0000022B +#define CKA_OTP_SERVICE_LOGO 0x0000022C +#define CKA_OTP_SERVICE_LOGO_TYPE 0x0000022D + + +/* CKA_HW_FEATURE_TYPE, CKA_RESET_ON_INIT, and CKA_HAS_RESET + * are new for v2.10 */ +#define CKA_HW_FEATURE_TYPE 0x00000300 +#define CKA_RESET_ON_INIT 0x00000301 +#define CKA_HAS_RESET 0x00000302 + +/* The following attributes are new for v2.20 */ +#define CKA_PIXEL_X 0x00000400 +#define CKA_PIXEL_Y 0x00000401 +#define CKA_RESOLUTION 0x00000402 +#define CKA_CHAR_ROWS 0x00000403 +#define CKA_CHAR_COLUMNS 0x00000404 +#define CKA_COLOR 0x00000405 +#define CKA_BITS_PER_PIXEL 0x00000406 +#define CKA_CHAR_SETS 0x00000480 +#define CKA_ENCODING_METHODS 0x00000481 +#define CKA_MIME_TYPES 0x00000482 +#define CKA_MECHANISM_TYPE 0x00000500 +#define CKA_REQUIRED_CMS_ATTRIBUTES 0x00000501 +#define CKA_DEFAULT_CMS_ATTRIBUTES 0x00000502 +#define CKA_SUPPORTED_CMS_ATTRIBUTES 0x00000503 +#define CKA_ALLOWED_MECHANISMS (CKF_ARRAY_ATTRIBUTE|0x00000600) + +#define CKA_VENDOR_DEFINED 0x80000000 + +/* CK_ATTRIBUTE is a structure that includes the type, length + * and value of an attribute */ +typedef struct CK_ATTRIBUTE { + CK_ATTRIBUTE_TYPE type; + CK_VOID_PTR pValue; + + /* ulValueLen went from CK_USHORT to CK_ULONG for v2.0 */ + CK_ULONG ulValueLen; /* in bytes */ +} CK_ATTRIBUTE; + +typedef CK_ATTRIBUTE CK_PTR CK_ATTRIBUTE_PTR; + + +/* CK_DATE is a structure that defines a date */ +typedef struct CK_DATE{ + CK_CHAR year[4]; /* the year ("1900" - "9999") */ + CK_CHAR month[2]; /* the month ("01" - "12") */ + CK_CHAR day[2]; /* the day ("01" - "31") */ +} CK_DATE; + + +/* CK_MECHANISM_TYPE is a value that identifies a mechanism + * type */ +/* CK_MECHANISM_TYPE was changed from CK_USHORT to CK_ULONG for + * v2.0 */ +typedef CK_ULONG CK_MECHANISM_TYPE; + +/* the following mechanism types are defined: */ +#define CKM_RSA_PKCS_KEY_PAIR_GEN 0x00000000 +#define CKM_RSA_PKCS 0x00000001 +#define CKM_RSA_9796 0x00000002 +#define CKM_RSA_X_509 0x00000003 + +/* CKM_MD2_RSA_PKCS, CKM_MD5_RSA_PKCS, and CKM_SHA1_RSA_PKCS + * are new for v2.0. They are mechanisms which hash and sign */ +#define CKM_MD2_RSA_PKCS 0x00000004 +#define CKM_MD5_RSA_PKCS 0x00000005 +#define CKM_SHA1_RSA_PKCS 0x00000006 + +/* CKM_RIPEMD128_RSA_PKCS, CKM_RIPEMD160_RSA_PKCS, and + * CKM_RSA_PKCS_OAEP are new for v2.10 */ +#define CKM_RIPEMD128_RSA_PKCS 0x00000007 +#define CKM_RIPEMD160_RSA_PKCS 0x00000008 +#define CKM_RSA_PKCS_OAEP 0x00000009 + +/* CKM_RSA_X9_31_KEY_PAIR_GEN, CKM_RSA_X9_31, CKM_SHA1_RSA_X9_31, + * CKM_RSA_PKCS_PSS, and CKM_SHA1_RSA_PKCS_PSS are new for v2.11 */ +#define CKM_RSA_X9_31_KEY_PAIR_GEN 0x0000000A +#define CKM_RSA_X9_31 0x0000000B +#define CKM_SHA1_RSA_X9_31 0x0000000C +#define CKM_RSA_PKCS_PSS 0x0000000D +#define CKM_SHA1_RSA_PKCS_PSS 0x0000000E + +#define CKM_DSA_KEY_PAIR_GEN 0x00000010 +#define CKM_DSA 0x00000011 +#define CKM_DSA_SHA1 0x00000012 +#define CKM_DH_PKCS_KEY_PAIR_GEN 0x00000020 +#define CKM_DH_PKCS_DERIVE 0x00000021 + +/* CKM_X9_42_DH_KEY_PAIR_GEN, CKM_X9_42_DH_DERIVE, + * CKM_X9_42_DH_HYBRID_DERIVE, and CKM_X9_42_MQV_DERIVE are new for + * v2.11 */ +#define CKM_X9_42_DH_KEY_PAIR_GEN 0x00000030 +#define CKM_X9_42_DH_DERIVE 0x00000031 +#define CKM_X9_42_DH_HYBRID_DERIVE 0x00000032 +#define CKM_X9_42_MQV_DERIVE 0x00000033 + +/* CKM_SHA256/384/512 are new for v2.20 */ +#define CKM_SHA256_RSA_PKCS 0x00000040 +#define CKM_SHA384_RSA_PKCS 0x00000041 +#define CKM_SHA512_RSA_PKCS 0x00000042 +#define CKM_SHA256_RSA_PKCS_PSS 0x00000043 +#define CKM_SHA384_RSA_PKCS_PSS 0x00000044 +#define CKM_SHA512_RSA_PKCS_PSS 0x00000045 + +/* SHA-224 RSA mechanisms are new for PKCS #11 v2.20 amendment 3 */ +#define CKM_SHA224_RSA_PKCS 0x00000046 +#define CKM_SHA224_RSA_PKCS_PSS 0x00000047 + +#define CKM_RC2_KEY_GEN 0x00000100 +#define CKM_RC2_ECB 0x00000101 +#define CKM_RC2_CBC 0x00000102 +#define CKM_RC2_MAC 0x00000103 + +/* CKM_RC2_MAC_GENERAL and CKM_RC2_CBC_PAD are new for v2.0 */ +#define CKM_RC2_MAC_GENERAL 0x00000104 +#define CKM_RC2_CBC_PAD 0x00000105 + +#define CKM_RC4_KEY_GEN 0x00000110 +#define CKM_RC4 0x00000111 +#define CKM_DES_KEY_GEN 0x00000120 +#define CKM_DES_ECB 0x00000121 +#define CKM_DES_CBC 0x00000122 +#define CKM_DES_MAC 0x00000123 + +/* CKM_DES_MAC_GENERAL and CKM_DES_CBC_PAD are new for v2.0 */ +#define CKM_DES_MAC_GENERAL 0x00000124 +#define CKM_DES_CBC_PAD 0x00000125 + +#define CKM_DES2_KEY_GEN 0x00000130 +#define CKM_DES3_KEY_GEN 0x00000131 +#define CKM_DES3_ECB 0x00000132 +#define CKM_DES3_CBC 0x00000133 +#define CKM_DES3_MAC 0x00000134 + +/* CKM_DES3_MAC_GENERAL, CKM_DES3_CBC_PAD, CKM_CDMF_KEY_GEN, + * CKM_CDMF_ECB, CKM_CDMF_CBC, CKM_CDMF_MAC, + * CKM_CDMF_MAC_GENERAL, and CKM_CDMF_CBC_PAD are new for v2.0 */ +#define CKM_DES3_MAC_GENERAL 0x00000135 +#define CKM_DES3_CBC_PAD 0x00000136 +#define CKM_CDMF_KEY_GEN 0x00000140 +#define CKM_CDMF_ECB 0x00000141 +#define CKM_CDMF_CBC 0x00000142 +#define CKM_CDMF_MAC 0x00000143 +#define CKM_CDMF_MAC_GENERAL 0x00000144 +#define CKM_CDMF_CBC_PAD 0x00000145 + +/* the following four DES mechanisms are new for v2.20 */ +#define CKM_DES_OFB64 0x00000150 +#define CKM_DES_OFB8 0x00000151 +#define CKM_DES_CFB64 0x00000152 +#define CKM_DES_CFB8 0x00000153 + +#define CKM_MD2 0x00000200 + +/* CKM_MD2_HMAC and CKM_MD2_HMAC_GENERAL are new for v2.0 */ +#define CKM_MD2_HMAC 0x00000201 +#define CKM_MD2_HMAC_GENERAL 0x00000202 + +#define CKM_MD5 0x00000210 + +/* CKM_MD5_HMAC and CKM_MD5_HMAC_GENERAL are new for v2.0 */ +#define CKM_MD5_HMAC 0x00000211 +#define CKM_MD5_HMAC_GENERAL 0x00000212 + +#define CKM_SHA_1 0x00000220 + +/* CKM_SHA_1_HMAC and CKM_SHA_1_HMAC_GENERAL are new for v2.0 */ +#define CKM_SHA_1_HMAC 0x00000221 +#define CKM_SHA_1_HMAC_GENERAL 0x00000222 + +/* CKM_RIPEMD128, CKM_RIPEMD128_HMAC, + * CKM_RIPEMD128_HMAC_GENERAL, CKM_RIPEMD160, CKM_RIPEMD160_HMAC, + * and CKM_RIPEMD160_HMAC_GENERAL are new for v2.10 */ +#define CKM_RIPEMD128 0x00000230 +#define CKM_RIPEMD128_HMAC 0x00000231 +#define CKM_RIPEMD128_HMAC_GENERAL 0x00000232 +#define CKM_RIPEMD160 0x00000240 +#define CKM_RIPEMD160_HMAC 0x00000241 +#define CKM_RIPEMD160_HMAC_GENERAL 0x00000242 + +/* CKM_SHA256/384/512 are new for v2.20 */ +#define CKM_SHA256 0x00000250 +#define CKM_SHA256_HMAC 0x00000251 +#define CKM_SHA256_HMAC_GENERAL 0x00000252 + +/* SHA-224 is new for PKCS #11 v2.20 amendment 3 */ +#define CKM_SHA224 0x00000255 +#define CKM_SHA224_HMAC 0x00000256 +#define CKM_SHA224_HMAC_GENERAL 0x00000257 + +#define CKM_SHA384 0x00000260 +#define CKM_SHA384_HMAC 0x00000261 +#define CKM_SHA384_HMAC_GENERAL 0x00000262 +#define CKM_SHA512 0x00000270 +#define CKM_SHA512_HMAC 0x00000271 +#define CKM_SHA512_HMAC_GENERAL 0x00000272 + +/* SecurID is new for PKCS #11 v2.20 amendment 1 */ +#define CKM_SECURID_KEY_GEN 0x00000280 +#define CKM_SECURID 0x00000282 + +/* HOTP is new for PKCS #11 v2.20 amendment 1 */ +#define CKM_HOTP_KEY_GEN 0x00000290 +#define CKM_HOTP 0x00000291 + +/* ACTI is new for PKCS #11 v2.20 amendment 1 */ +#define CKM_ACTI 0x000002A0 +#define CKM_ACTI_KEY_GEN 0x000002A1 + +/* All of the following mechanisms are new for v2.0 */ +/* Note that CAST128 and CAST5 are the same algorithm */ +#define CKM_CAST_KEY_GEN 0x00000300 +#define CKM_CAST_ECB 0x00000301 +#define CKM_CAST_CBC 0x00000302 +#define CKM_CAST_MAC 0x00000303 +#define CKM_CAST_MAC_GENERAL 0x00000304 +#define CKM_CAST_CBC_PAD 0x00000305 +#define CKM_CAST3_KEY_GEN 0x00000310 +#define CKM_CAST3_ECB 0x00000311 +#define CKM_CAST3_CBC 0x00000312 +#define CKM_CAST3_MAC 0x00000313 +#define CKM_CAST3_MAC_GENERAL 0x00000314 +#define CKM_CAST3_CBC_PAD 0x00000315 +#define CKM_CAST5_KEY_GEN 0x00000320 +#define CKM_CAST128_KEY_GEN 0x00000320 +#define CKM_CAST5_ECB 0x00000321 +#define CKM_CAST128_ECB 0x00000321 +#define CKM_CAST5_CBC 0x00000322 +#define CKM_CAST128_CBC 0x00000322 +#define CKM_CAST5_MAC 0x00000323 +#define CKM_CAST128_MAC 0x00000323 +#define CKM_CAST5_MAC_GENERAL 0x00000324 +#define CKM_CAST128_MAC_GENERAL 0x00000324 +#define CKM_CAST5_CBC_PAD 0x00000325 +#define CKM_CAST128_CBC_PAD 0x00000325 +#define CKM_RC5_KEY_GEN 0x00000330 +#define CKM_RC5_ECB 0x00000331 +#define CKM_RC5_CBC 0x00000332 +#define CKM_RC5_MAC 0x00000333 +#define CKM_RC5_MAC_GENERAL 0x00000334 +#define CKM_RC5_CBC_PAD 0x00000335 +#define CKM_IDEA_KEY_GEN 0x00000340 +#define CKM_IDEA_ECB 0x00000341 +#define CKM_IDEA_CBC 0x00000342 +#define CKM_IDEA_MAC 0x00000343 +#define CKM_IDEA_MAC_GENERAL 0x00000344 +#define CKM_IDEA_CBC_PAD 0x00000345 +#define CKM_GENERIC_SECRET_KEY_GEN 0x00000350 +#define CKM_CONCATENATE_BASE_AND_KEY 0x00000360 +#define CKM_CONCATENATE_BASE_AND_DATA 0x00000362 +#define CKM_CONCATENATE_DATA_AND_BASE 0x00000363 +#define CKM_XOR_BASE_AND_DATA 0x00000364 +#define CKM_EXTRACT_KEY_FROM_KEY 0x00000365 +#define CKM_SSL3_PRE_MASTER_KEY_GEN 0x00000370 +#define CKM_SSL3_MASTER_KEY_DERIVE 0x00000371 +#define CKM_SSL3_KEY_AND_MAC_DERIVE 0x00000372 + +/* CKM_SSL3_MASTER_KEY_DERIVE_DH, CKM_TLS_PRE_MASTER_KEY_GEN, + * CKM_TLS_MASTER_KEY_DERIVE, CKM_TLS_KEY_AND_MAC_DERIVE, and + * CKM_TLS_MASTER_KEY_DERIVE_DH are new for v2.11 */ +#define CKM_SSL3_MASTER_KEY_DERIVE_DH 0x00000373 +#define CKM_TLS_PRE_MASTER_KEY_GEN 0x00000374 +#define CKM_TLS_MASTER_KEY_DERIVE 0x00000375 +#define CKM_TLS_KEY_AND_MAC_DERIVE 0x00000376 +#define CKM_TLS_MASTER_KEY_DERIVE_DH 0x00000377 + +/* CKM_TLS_PRF is new for v2.20 */ +#define CKM_TLS_PRF 0x00000378 + +#define CKM_SSL3_MD5_MAC 0x00000380 +#define CKM_SSL3_SHA1_MAC 0x00000381 +#define CKM_MD5_KEY_DERIVATION 0x00000390 +#define CKM_MD2_KEY_DERIVATION 0x00000391 +#define CKM_SHA1_KEY_DERIVATION 0x00000392 + +/* CKM_SHA256/384/512 are new for v2.20 */ +#define CKM_SHA256_KEY_DERIVATION 0x00000393 +#define CKM_SHA384_KEY_DERIVATION 0x00000394 +#define CKM_SHA512_KEY_DERIVATION 0x00000395 + +/* SHA-224 key derivation is new for PKCS #11 v2.20 amendment 3 */ +#define CKM_SHA224_KEY_DERIVATION 0x00000396 + +#define CKM_PBE_MD2_DES_CBC 0x000003A0 +#define CKM_PBE_MD5_DES_CBC 0x000003A1 +#define CKM_PBE_MD5_CAST_CBC 0x000003A2 +#define CKM_PBE_MD5_CAST3_CBC 0x000003A3 +#define CKM_PBE_MD5_CAST5_CBC 0x000003A4 +#define CKM_PBE_MD5_CAST128_CBC 0x000003A4 +#define CKM_PBE_SHA1_CAST5_CBC 0x000003A5 +#define CKM_PBE_SHA1_CAST128_CBC 0x000003A5 +#define CKM_PBE_SHA1_RC4_128 0x000003A6 +#define CKM_PBE_SHA1_RC4_40 0x000003A7 +#define CKM_PBE_SHA1_DES3_EDE_CBC 0x000003A8 +#define CKM_PBE_SHA1_DES2_EDE_CBC 0x000003A9 +#define CKM_PBE_SHA1_RC2_128_CBC 0x000003AA +#define CKM_PBE_SHA1_RC2_40_CBC 0x000003AB + +/* CKM_PKCS5_PBKD2 is new for v2.10 */ +#define CKM_PKCS5_PBKD2 0x000003B0 + +#define CKM_PBA_SHA1_WITH_SHA1_HMAC 0x000003C0 + +/* WTLS mechanisms are new for v2.20 */ +#define CKM_WTLS_PRE_MASTER_KEY_GEN 0x000003D0 +#define CKM_WTLS_MASTER_KEY_DERIVE 0x000003D1 +#define CKM_WTLS_MASTER_KEY_DERIVE_DH_ECC 0x000003D2 +#define CKM_WTLS_PRF 0x000003D3 +#define CKM_WTLS_SERVER_KEY_AND_MAC_DERIVE 0x000003D4 +#define CKM_WTLS_CLIENT_KEY_AND_MAC_DERIVE 0x000003D5 + +#define CKM_KEY_WRAP_LYNKS 0x00000400 +#define CKM_KEY_WRAP_SET_OAEP 0x00000401 + +/* CKM_CMS_SIG is new for v2.20 */ +#define CKM_CMS_SIG 0x00000500 + +/* CKM_KIP mechanisms are new for PKCS #11 v2.20 amendment 2 */ +#define CKM_KIP_DERIVE 0x00000510 +#define CKM_KIP_WRAP 0x00000511 +#define CKM_KIP_MAC 0x00000512 + +/* Camellia is new for PKCS #11 v2.20 amendment 3 */ +#define CKM_CAMELLIA_KEY_GEN 0x00000550 +#define CKM_CAMELLIA_ECB 0x00000551 +#define CKM_CAMELLIA_CBC 0x00000552 +#define CKM_CAMELLIA_MAC 0x00000553 +#define CKM_CAMELLIA_MAC_GENERAL 0x00000554 +#define CKM_CAMELLIA_CBC_PAD 0x00000555 +#define CKM_CAMELLIA_ECB_ENCRYPT_DATA 0x00000556 +#define CKM_CAMELLIA_CBC_ENCRYPT_DATA 0x00000557 +#define CKM_CAMELLIA_CTR 0x00000558 + +/* ARIA is new for PKCS #11 v2.20 amendment 3 */ +#define CKM_ARIA_KEY_GEN 0x00000560 +#define CKM_ARIA_ECB 0x00000561 +#define CKM_ARIA_CBC 0x00000562 +#define CKM_ARIA_MAC 0x00000563 +#define CKM_ARIA_MAC_GENERAL 0x00000564 +#define CKM_ARIA_CBC_PAD 0x00000565 +#define CKM_ARIA_ECB_ENCRYPT_DATA 0x00000566 +#define CKM_ARIA_CBC_ENCRYPT_DATA 0x00000567 + +/* Fortezza mechanisms */ +#define CKM_SKIPJACK_KEY_GEN 0x00001000 +#define CKM_SKIPJACK_ECB64 0x00001001 +#define CKM_SKIPJACK_CBC64 0x00001002 +#define CKM_SKIPJACK_OFB64 0x00001003 +#define CKM_SKIPJACK_CFB64 0x00001004 +#define CKM_SKIPJACK_CFB32 0x00001005 +#define CKM_SKIPJACK_CFB16 0x00001006 +#define CKM_SKIPJACK_CFB8 0x00001007 +#define CKM_SKIPJACK_WRAP 0x00001008 +#define CKM_SKIPJACK_PRIVATE_WRAP 0x00001009 +#define CKM_SKIPJACK_RELAYX 0x0000100a +#define CKM_KEA_KEY_PAIR_GEN 0x00001010 +#define CKM_KEA_KEY_DERIVE 0x00001011 +#define CKM_FORTEZZA_TIMESTAMP 0x00001020 +#define CKM_BATON_KEY_GEN 0x00001030 +#define CKM_BATON_ECB128 0x00001031 +#define CKM_BATON_ECB96 0x00001032 +#define CKM_BATON_CBC128 0x00001033 +#define CKM_BATON_COUNTER 0x00001034 +#define CKM_BATON_SHUFFLE 0x00001035 +#define CKM_BATON_WRAP 0x00001036 + +/* CKM_ECDSA_KEY_PAIR_GEN is deprecated in v2.11, + * CKM_EC_KEY_PAIR_GEN is preferred */ +#define CKM_ECDSA_KEY_PAIR_GEN 0x00001040 +#define CKM_EC_KEY_PAIR_GEN 0x00001040 + +#define CKM_ECDSA 0x00001041 +#define CKM_ECDSA_SHA1 0x00001042 + +/* CKM_ECDH1_DERIVE, CKM_ECDH1_COFACTOR_DERIVE, and CKM_ECMQV_DERIVE + * are new for v2.11 */ +#define CKM_ECDH1_DERIVE 0x00001050 +#define CKM_ECDH1_COFACTOR_DERIVE 0x00001051 +#define CKM_ECMQV_DERIVE 0x00001052 + +#define CKM_JUNIPER_KEY_GEN 0x00001060 +#define CKM_JUNIPER_ECB128 0x00001061 +#define CKM_JUNIPER_CBC128 0x00001062 +#define CKM_JUNIPER_COUNTER 0x00001063 +#define CKM_JUNIPER_SHUFFLE 0x00001064 +#define CKM_JUNIPER_WRAP 0x00001065 +#define CKM_FASTHASH 0x00001070 + +/* CKM_AES_KEY_GEN, CKM_AES_ECB, CKM_AES_CBC, CKM_AES_MAC, + * CKM_AES_MAC_GENERAL, CKM_AES_CBC_PAD, CKM_DSA_PARAMETER_GEN, + * CKM_DH_PKCS_PARAMETER_GEN, and CKM_X9_42_DH_PARAMETER_GEN are + * new for v2.11 */ +#define CKM_AES_KEY_GEN 0x00001080 +#define CKM_AES_ECB 0x00001081 +#define CKM_AES_CBC 0x00001082 +#define CKM_AES_MAC 0x00001083 +#define CKM_AES_MAC_GENERAL 0x00001084 +#define CKM_AES_CBC_PAD 0x00001085 + +/* AES counter mode is new for PKCS #11 v2.20 amendment 3 */ +#define CKM_AES_CTR 0x00001086 + +/* BlowFish and TwoFish are new for v2.20 */ +#define CKM_BLOWFISH_KEY_GEN 0x00001090 +#define CKM_BLOWFISH_CBC 0x00001091 +#define CKM_TWOFISH_KEY_GEN 0x00001092 +#define CKM_TWOFISH_CBC 0x00001093 + + +/* CKM_xxx_ENCRYPT_DATA mechanisms are new for v2.20 */ +#define CKM_DES_ECB_ENCRYPT_DATA 0x00001100 +#define CKM_DES_CBC_ENCRYPT_DATA 0x00001101 +#define CKM_DES3_ECB_ENCRYPT_DATA 0x00001102 +#define CKM_DES3_CBC_ENCRYPT_DATA 0x00001103 +#define CKM_AES_ECB_ENCRYPT_DATA 0x00001104 +#define CKM_AES_CBC_ENCRYPT_DATA 0x00001105 + +#define CKM_DSA_PARAMETER_GEN 0x00002000 +#define CKM_DH_PKCS_PARAMETER_GEN 0x00002001 +#define CKM_X9_42_DH_PARAMETER_GEN 0x00002002 + +#define CKM_VENDOR_DEFINED 0x80000000 + +typedef CK_MECHANISM_TYPE CK_PTR CK_MECHANISM_TYPE_PTR; + + +/* CK_MECHANISM is a structure that specifies a particular + * mechanism */ +typedef struct CK_MECHANISM { + CK_MECHANISM_TYPE mechanism; + CK_VOID_PTR pParameter; + + /* ulParameterLen was changed from CK_USHORT to CK_ULONG for + * v2.0 */ + CK_ULONG ulParameterLen; /* in bytes */ +} CK_MECHANISM; + +typedef CK_MECHANISM CK_PTR CK_MECHANISM_PTR; + + +/* CK_MECHANISM_INFO provides information about a particular + * mechanism */ +typedef struct CK_MECHANISM_INFO { + CK_ULONG ulMinKeySize; + CK_ULONG ulMaxKeySize; + CK_FLAGS flags; +} CK_MECHANISM_INFO; + +/* The flags are defined as follows: + * Bit Flag Mask Meaning */ +#define CKF_HW 0x00000001 /* performed by HW */ + +/* The flags CKF_ENCRYPT, CKF_DECRYPT, CKF_DIGEST, CKF_SIGN, + * CKG_SIGN_RECOVER, CKF_VERIFY, CKF_VERIFY_RECOVER, + * CKF_GENERATE, CKF_GENERATE_KEY_PAIR, CKF_WRAP, CKF_UNWRAP, + * and CKF_DERIVE are new for v2.0. They specify whether or not + * a mechanism can be used for a particular task */ +#define CKF_ENCRYPT 0x00000100 +#define CKF_DECRYPT 0x00000200 +#define CKF_DIGEST 0x00000400 +#define CKF_SIGN 0x00000800 +#define CKF_SIGN_RECOVER 0x00001000 +#define CKF_VERIFY 0x00002000 +#define CKF_VERIFY_RECOVER 0x00004000 +#define CKF_GENERATE 0x00008000 +#define CKF_GENERATE_KEY_PAIR 0x00010000 +#define CKF_WRAP 0x00020000 +#define CKF_UNWRAP 0x00040000 +#define CKF_DERIVE 0x00080000 + +/* CKF_EC_F_P, CKF_EC_F_2M, CKF_EC_ECPARAMETERS, CKF_EC_NAMEDCURVE, + * CKF_EC_UNCOMPRESS, and CKF_EC_COMPRESS are new for v2.11. They + * describe a token's EC capabilities not available in mechanism + * information. */ +#define CKF_EC_F_P 0x00100000 +#define CKF_EC_F_2M 0x00200000 +#define CKF_EC_ECPARAMETERS 0x00400000 +#define CKF_EC_NAMEDCURVE 0x00800000 +#define CKF_EC_UNCOMPRESS 0x01000000 +#define CKF_EC_COMPRESS 0x02000000 + +#define CKF_EXTENSION 0x80000000 /* FALSE for this version */ + +typedef CK_MECHANISM_INFO CK_PTR CK_MECHANISM_INFO_PTR; + + +/* CK_RV is a value that identifies the return value of a + * Cryptoki function */ +/* CK_RV was changed from CK_USHORT to CK_ULONG for v2.0 */ +typedef CK_ULONG CK_RV; + +#define CKR_OK 0x00000000 +#define CKR_CANCEL 0x00000001 +#define CKR_HOST_MEMORY 0x00000002 +#define CKR_SLOT_ID_INVALID 0x00000003 + +/* CKR_FLAGS_INVALID was removed for v2.0 */ + +/* CKR_GENERAL_ERROR and CKR_FUNCTION_FAILED are new for v2.0 */ +#define CKR_GENERAL_ERROR 0x00000005 +#define CKR_FUNCTION_FAILED 0x00000006 + +/* CKR_ARGUMENTS_BAD, CKR_NO_EVENT, CKR_NEED_TO_CREATE_THREADS, + * and CKR_CANT_LOCK are new for v2.01 */ +#define CKR_ARGUMENTS_BAD 0x00000007 +#define CKR_NO_EVENT 0x00000008 +#define CKR_NEED_TO_CREATE_THREADS 0x00000009 +#define CKR_CANT_LOCK 0x0000000A + +#define CKR_ATTRIBUTE_READ_ONLY 0x00000010 +#define CKR_ATTRIBUTE_SENSITIVE 0x00000011 +#define CKR_ATTRIBUTE_TYPE_INVALID 0x00000012 +#define CKR_ATTRIBUTE_VALUE_INVALID 0x00000013 +#define CKR_DATA_INVALID 0x00000020 +#define CKR_DATA_LEN_RANGE 0x00000021 +#define CKR_DEVICE_ERROR 0x00000030 +#define CKR_DEVICE_MEMORY 0x00000031 +#define CKR_DEVICE_REMOVED 0x00000032 +#define CKR_ENCRYPTED_DATA_INVALID 0x00000040 +#define CKR_ENCRYPTED_DATA_LEN_RANGE 0x00000041 +#define CKR_FUNCTION_CANCELED 0x00000050 +#define CKR_FUNCTION_NOT_PARALLEL 0x00000051 + +/* CKR_FUNCTION_NOT_SUPPORTED is new for v2.0 */ +#define CKR_FUNCTION_NOT_SUPPORTED 0x00000054 + +#define CKR_KEY_HANDLE_INVALID 0x00000060 + +/* CKR_KEY_SENSITIVE was removed for v2.0 */ + +#define CKR_KEY_SIZE_RANGE 0x00000062 +#define CKR_KEY_TYPE_INCONSISTENT 0x00000063 + +/* CKR_KEY_NOT_NEEDED, CKR_KEY_CHANGED, CKR_KEY_NEEDED, + * CKR_KEY_INDIGESTIBLE, CKR_KEY_FUNCTION_NOT_PERMITTED, + * CKR_KEY_NOT_WRAPPABLE, and CKR_KEY_UNEXTRACTABLE are new for + * v2.0 */ +#define CKR_KEY_NOT_NEEDED 0x00000064 +#define CKR_KEY_CHANGED 0x00000065 +#define CKR_KEY_NEEDED 0x00000066 +#define CKR_KEY_INDIGESTIBLE 0x00000067 +#define CKR_KEY_FUNCTION_NOT_PERMITTED 0x00000068 +#define CKR_KEY_NOT_WRAPPABLE 0x00000069 +#define CKR_KEY_UNEXTRACTABLE 0x0000006A + +#define CKR_MECHANISM_INVALID 0x00000070 +#define CKR_MECHANISM_PARAM_INVALID 0x00000071 + +/* CKR_OBJECT_CLASS_INCONSISTENT and CKR_OBJECT_CLASS_INVALID + * were removed for v2.0 */ +#define CKR_OBJECT_HANDLE_INVALID 0x00000082 +#define CKR_OPERATION_ACTIVE 0x00000090 +#define CKR_OPERATION_NOT_INITIALIZED 0x00000091 +#define CKR_PIN_INCORRECT 0x000000A0 +#define CKR_PIN_INVALID 0x000000A1 +#define CKR_PIN_LEN_RANGE 0x000000A2 + +/* CKR_PIN_EXPIRED and CKR_PIN_LOCKED are new for v2.0 */ +#define CKR_PIN_EXPIRED 0x000000A3 +#define CKR_PIN_LOCKED 0x000000A4 + +#define CKR_SESSION_CLOSED 0x000000B0 +#define CKR_SESSION_COUNT 0x000000B1 +#define CKR_SESSION_HANDLE_INVALID 0x000000B3 +#define CKR_SESSION_PARALLEL_NOT_SUPPORTED 0x000000B4 +#define CKR_SESSION_READ_ONLY 0x000000B5 +#define CKR_SESSION_EXISTS 0x000000B6 + +/* CKR_SESSION_READ_ONLY_EXISTS and + * CKR_SESSION_READ_WRITE_SO_EXISTS are new for v2.0 */ +#define CKR_SESSION_READ_ONLY_EXISTS 0x000000B7 +#define CKR_SESSION_READ_WRITE_SO_EXISTS 0x000000B8 + +#define CKR_SIGNATURE_INVALID 0x000000C0 +#define CKR_SIGNATURE_LEN_RANGE 0x000000C1 +#define CKR_TEMPLATE_INCOMPLETE 0x000000D0 +#define CKR_TEMPLATE_INCONSISTENT 0x000000D1 +#define CKR_TOKEN_NOT_PRESENT 0x000000E0 +#define CKR_TOKEN_NOT_RECOGNIZED 0x000000E1 +#define CKR_TOKEN_WRITE_PROTECTED 0x000000E2 +#define CKR_UNWRAPPING_KEY_HANDLE_INVALID 0x000000F0 +#define CKR_UNWRAPPING_KEY_SIZE_RANGE 0x000000F1 +#define CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT 0x000000F2 +#define CKR_USER_ALREADY_LOGGED_IN 0x00000100 +#define CKR_USER_NOT_LOGGED_IN 0x00000101 +#define CKR_USER_PIN_NOT_INITIALIZED 0x00000102 +#define CKR_USER_TYPE_INVALID 0x00000103 + +/* CKR_USER_ANOTHER_ALREADY_LOGGED_IN and CKR_USER_TOO_MANY_TYPES + * are new to v2.01 */ +#define CKR_USER_ANOTHER_ALREADY_LOGGED_IN 0x00000104 +#define CKR_USER_TOO_MANY_TYPES 0x00000105 + +#define CKR_WRAPPED_KEY_INVALID 0x00000110 +#define CKR_WRAPPED_KEY_LEN_RANGE 0x00000112 +#define CKR_WRAPPING_KEY_HANDLE_INVALID 0x00000113 +#define CKR_WRAPPING_KEY_SIZE_RANGE 0x00000114 +#define CKR_WRAPPING_KEY_TYPE_INCONSISTENT 0x00000115 +#define CKR_RANDOM_SEED_NOT_SUPPORTED 0x00000120 + +/* These are new to v2.0 */ +#define CKR_RANDOM_NO_RNG 0x00000121 + +/* These are new to v2.11 */ +#define CKR_DOMAIN_PARAMS_INVALID 0x00000130 + +/* These are new to v2.0 */ +#define CKR_BUFFER_TOO_SMALL 0x00000150 +#define CKR_SAVED_STATE_INVALID 0x00000160 +#define CKR_INFORMATION_SENSITIVE 0x00000170 +#define CKR_STATE_UNSAVEABLE 0x00000180 + +/* These are new to v2.01 */ +#define CKR_CRYPTOKI_NOT_INITIALIZED 0x00000190 +#define CKR_CRYPTOKI_ALREADY_INITIALIZED 0x00000191 +#define CKR_MUTEX_BAD 0x000001A0 +#define CKR_MUTEX_NOT_LOCKED 0x000001A1 + +/* The following return values are new for PKCS #11 v2.20 amendment 3 */ +#define CKR_NEW_PIN_MODE 0x000001B0 +#define CKR_NEXT_OTP 0x000001B1 + +/* This is new to v2.20 */ +#define CKR_FUNCTION_REJECTED 0x00000200 + +#define CKR_VENDOR_DEFINED 0x80000000 + + +/* CK_NOTIFY is an application callback that processes events */ +typedef CK_CALLBACK_FUNCTION(CK_RV, CK_NOTIFY)( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_NOTIFICATION event, + CK_VOID_PTR pApplication /* passed to C_OpenSession */ +); + + +/* CK_FUNCTION_LIST is a structure holding a Cryptoki spec + * version and pointers of appropriate types to all the + * Cryptoki functions */ +/* CK_FUNCTION_LIST is new for v2.0 */ +typedef struct CK_FUNCTION_LIST CK_FUNCTION_LIST; + +typedef CK_FUNCTION_LIST CK_PTR CK_FUNCTION_LIST_PTR; + +typedef CK_FUNCTION_LIST_PTR CK_PTR CK_FUNCTION_LIST_PTR_PTR; + + +/* CK_CREATEMUTEX is an application callback for creating a + * mutex object */ +typedef CK_CALLBACK_FUNCTION(CK_RV, CK_CREATEMUTEX)( + CK_VOID_PTR_PTR ppMutex /* location to receive ptr to mutex */ +); + + +/* CK_DESTROYMUTEX is an application callback for destroying a + * mutex object */ +typedef CK_CALLBACK_FUNCTION(CK_RV, CK_DESTROYMUTEX)( + CK_VOID_PTR pMutex /* pointer to mutex */ +); + + +/* CK_LOCKMUTEX is an application callback for locking a mutex */ +typedef CK_CALLBACK_FUNCTION(CK_RV, CK_LOCKMUTEX)( + CK_VOID_PTR pMutex /* pointer to mutex */ +); + + +/* CK_UNLOCKMUTEX is an application callback for unlocking a + * mutex */ +typedef CK_CALLBACK_FUNCTION(CK_RV, CK_UNLOCKMUTEX)( + CK_VOID_PTR pMutex /* pointer to mutex */ +); + + +/* CK_C_INITIALIZE_ARGS provides the optional arguments to + * C_Initialize */ +typedef struct CK_C_INITIALIZE_ARGS { + CK_CREATEMUTEX CreateMutex; + CK_DESTROYMUTEX DestroyMutex; + CK_LOCKMUTEX LockMutex; + CK_UNLOCKMUTEX UnlockMutex; + CK_FLAGS flags; + CK_VOID_PTR pReserved; +} CK_C_INITIALIZE_ARGS; + +/* flags: bit flags that provide capabilities of the slot + * Bit Flag Mask Meaning + */ +#define CKF_LIBRARY_CANT_CREATE_OS_THREADS 0x00000001 +#define CKF_OS_LOCKING_OK 0x00000002 + +typedef CK_C_INITIALIZE_ARGS CK_PTR CK_C_INITIALIZE_ARGS_PTR; + + +/* additional flags for parameters to functions */ + +/* CKF_DONT_BLOCK is for the function C_WaitForSlotEvent */ +#define CKF_DONT_BLOCK 1 + +/* CK_RSA_PKCS_OAEP_MGF_TYPE is new for v2.10. + * CK_RSA_PKCS_OAEP_MGF_TYPE is used to indicate the Message + * Generation Function (MGF) applied to a message block when + * formatting a message block for the PKCS #1 OAEP encryption + * scheme. */ +typedef CK_ULONG CK_RSA_PKCS_MGF_TYPE; + +typedef CK_RSA_PKCS_MGF_TYPE CK_PTR CK_RSA_PKCS_MGF_TYPE_PTR; + +/* The following MGFs are defined */ +/* CKG_MGF1_SHA256, CKG_MGF1_SHA384, and CKG_MGF1_SHA512 + * are new for v2.20 */ +#define CKG_MGF1_SHA1 0x00000001 +#define CKG_MGF1_SHA256 0x00000002 +#define CKG_MGF1_SHA384 0x00000003 +#define CKG_MGF1_SHA512 0x00000004 +/* SHA-224 is new for PKCS #11 v2.20 amendment 3 */ +#define CKG_MGF1_SHA224 0x00000005 + +/* CK_RSA_PKCS_OAEP_SOURCE_TYPE is new for v2.10. + * CK_RSA_PKCS_OAEP_SOURCE_TYPE is used to indicate the source + * of the encoding parameter when formatting a message block + * for the PKCS #1 OAEP encryption scheme. */ +typedef CK_ULONG CK_RSA_PKCS_OAEP_SOURCE_TYPE; + +typedef CK_RSA_PKCS_OAEP_SOURCE_TYPE CK_PTR CK_RSA_PKCS_OAEP_SOURCE_TYPE_PTR; + +/* The following encoding parameter sources are defined */ +#define CKZ_DATA_SPECIFIED 0x00000001 + +/* CK_RSA_PKCS_OAEP_PARAMS is new for v2.10. + * CK_RSA_PKCS_OAEP_PARAMS provides the parameters to the + * CKM_RSA_PKCS_OAEP mechanism. */ +typedef struct CK_RSA_PKCS_OAEP_PARAMS { + CK_MECHANISM_TYPE hashAlg; + CK_RSA_PKCS_MGF_TYPE mgf; + CK_RSA_PKCS_OAEP_SOURCE_TYPE source; + CK_VOID_PTR pSourceData; + CK_ULONG ulSourceDataLen; +} CK_RSA_PKCS_OAEP_PARAMS; + +typedef CK_RSA_PKCS_OAEP_PARAMS CK_PTR CK_RSA_PKCS_OAEP_PARAMS_PTR; + +/* CK_RSA_PKCS_PSS_PARAMS is new for v2.11. + * CK_RSA_PKCS_PSS_PARAMS provides the parameters to the + * CKM_RSA_PKCS_PSS mechanism(s). */ +typedef struct CK_RSA_PKCS_PSS_PARAMS { + CK_MECHANISM_TYPE hashAlg; + CK_RSA_PKCS_MGF_TYPE mgf; + CK_ULONG sLen; +} CK_RSA_PKCS_PSS_PARAMS; + +typedef CK_RSA_PKCS_PSS_PARAMS CK_PTR CK_RSA_PKCS_PSS_PARAMS_PTR; + +/* CK_EC_KDF_TYPE is new for v2.11. */ +typedef CK_ULONG CK_EC_KDF_TYPE; + +/* The following EC Key Derivation Functions are defined */ +#define CKD_NULL 0x00000001 +#define CKD_SHA1_KDF 0x00000002 + +/* CK_ECDH1_DERIVE_PARAMS is new for v2.11. + * CK_ECDH1_DERIVE_PARAMS provides the parameters to the + * CKM_ECDH1_DERIVE and CKM_ECDH1_COFACTOR_DERIVE mechanisms, + * where each party contributes one key pair. + */ +typedef struct CK_ECDH1_DERIVE_PARAMS { + CK_EC_KDF_TYPE kdf; + CK_ULONG ulSharedDataLen; + CK_BYTE_PTR pSharedData; + CK_ULONG ulPublicDataLen; + CK_BYTE_PTR pPublicData; +} CK_ECDH1_DERIVE_PARAMS; + +typedef CK_ECDH1_DERIVE_PARAMS CK_PTR CK_ECDH1_DERIVE_PARAMS_PTR; + + +/* CK_ECDH2_DERIVE_PARAMS is new for v2.11. + * CK_ECDH2_DERIVE_PARAMS provides the parameters to the + * CKM_ECMQV_DERIVE mechanism, where each party contributes two key pairs. */ +typedef struct CK_ECDH2_DERIVE_PARAMS { + CK_EC_KDF_TYPE kdf; + CK_ULONG ulSharedDataLen; + CK_BYTE_PTR pSharedData; + CK_ULONG ulPublicDataLen; + CK_BYTE_PTR pPublicData; + CK_ULONG ulPrivateDataLen; + CK_OBJECT_HANDLE hPrivateData; + CK_ULONG ulPublicDataLen2; + CK_BYTE_PTR pPublicData2; +} CK_ECDH2_DERIVE_PARAMS; + +typedef CK_ECDH2_DERIVE_PARAMS CK_PTR CK_ECDH2_DERIVE_PARAMS_PTR; + +typedef struct CK_ECMQV_DERIVE_PARAMS { + CK_EC_KDF_TYPE kdf; + CK_ULONG ulSharedDataLen; + CK_BYTE_PTR pSharedData; + CK_ULONG ulPublicDataLen; + CK_BYTE_PTR pPublicData; + CK_ULONG ulPrivateDataLen; + CK_OBJECT_HANDLE hPrivateData; + CK_ULONG ulPublicDataLen2; + CK_BYTE_PTR pPublicData2; + CK_OBJECT_HANDLE publicKey; +} CK_ECMQV_DERIVE_PARAMS; + +typedef CK_ECMQV_DERIVE_PARAMS CK_PTR CK_ECMQV_DERIVE_PARAMS_PTR; + +/* Typedefs and defines for the CKM_X9_42_DH_KEY_PAIR_GEN and the + * CKM_X9_42_DH_PARAMETER_GEN mechanisms (new for PKCS #11 v2.11) */ +typedef CK_ULONG CK_X9_42_DH_KDF_TYPE; +typedef CK_X9_42_DH_KDF_TYPE CK_PTR CK_X9_42_DH_KDF_TYPE_PTR; + +/* The following X9.42 DH key derivation functions are defined + (besides CKD_NULL already defined : */ +#define CKD_SHA1_KDF_ASN1 0x00000003 +#define CKD_SHA1_KDF_CONCATENATE 0x00000004 + +/* CK_X9_42_DH1_DERIVE_PARAMS is new for v2.11. + * CK_X9_42_DH1_DERIVE_PARAMS provides the parameters to the + * CKM_X9_42_DH_DERIVE key derivation mechanism, where each party + * contributes one key pair */ +typedef struct CK_X9_42_DH1_DERIVE_PARAMS { + CK_X9_42_DH_KDF_TYPE kdf; + CK_ULONG ulOtherInfoLen; + CK_BYTE_PTR pOtherInfo; + CK_ULONG ulPublicDataLen; + CK_BYTE_PTR pPublicData; +} CK_X9_42_DH1_DERIVE_PARAMS; + +typedef struct CK_X9_42_DH1_DERIVE_PARAMS CK_PTR CK_X9_42_DH1_DERIVE_PARAMS_PTR; + +/* CK_X9_42_DH2_DERIVE_PARAMS is new for v2.11. + * CK_X9_42_DH2_DERIVE_PARAMS provides the parameters to the + * CKM_X9_42_DH_HYBRID_DERIVE and CKM_X9_42_MQV_DERIVE key derivation + * mechanisms, where each party contributes two key pairs */ +typedef struct CK_X9_42_DH2_DERIVE_PARAMS { + CK_X9_42_DH_KDF_TYPE kdf; + CK_ULONG ulOtherInfoLen; + CK_BYTE_PTR pOtherInfo; + CK_ULONG ulPublicDataLen; + CK_BYTE_PTR pPublicData; + CK_ULONG ulPrivateDataLen; + CK_OBJECT_HANDLE hPrivateData; + CK_ULONG ulPublicDataLen2; + CK_BYTE_PTR pPublicData2; +} CK_X9_42_DH2_DERIVE_PARAMS; + +typedef CK_X9_42_DH2_DERIVE_PARAMS CK_PTR CK_X9_42_DH2_DERIVE_PARAMS_PTR; + +typedef struct CK_X9_42_MQV_DERIVE_PARAMS { + CK_X9_42_DH_KDF_TYPE kdf; + CK_ULONG ulOtherInfoLen; + CK_BYTE_PTR pOtherInfo; + CK_ULONG ulPublicDataLen; + CK_BYTE_PTR pPublicData; + CK_ULONG ulPrivateDataLen; + CK_OBJECT_HANDLE hPrivateData; + CK_ULONG ulPublicDataLen2; + CK_BYTE_PTR pPublicData2; + CK_OBJECT_HANDLE publicKey; +} CK_X9_42_MQV_DERIVE_PARAMS; + +typedef CK_X9_42_MQV_DERIVE_PARAMS CK_PTR CK_X9_42_MQV_DERIVE_PARAMS_PTR; + +/* CK_KEA_DERIVE_PARAMS provides the parameters to the + * CKM_KEA_DERIVE mechanism */ +/* CK_KEA_DERIVE_PARAMS is new for v2.0 */ +typedef struct CK_KEA_DERIVE_PARAMS { + CK_BBOOL isSender; + CK_ULONG ulRandomLen; + CK_BYTE_PTR pRandomA; + CK_BYTE_PTR pRandomB; + CK_ULONG ulPublicDataLen; + CK_BYTE_PTR pPublicData; +} CK_KEA_DERIVE_PARAMS; + +typedef CK_KEA_DERIVE_PARAMS CK_PTR CK_KEA_DERIVE_PARAMS_PTR; + + +/* CK_RC2_PARAMS provides the parameters to the CKM_RC2_ECB and + * CKM_RC2_MAC mechanisms. An instance of CK_RC2_PARAMS just + * holds the effective keysize */ +typedef CK_ULONG CK_RC2_PARAMS; + +typedef CK_RC2_PARAMS CK_PTR CK_RC2_PARAMS_PTR; + + +/* CK_RC2_CBC_PARAMS provides the parameters to the CKM_RC2_CBC + * mechanism */ +typedef struct CK_RC2_CBC_PARAMS { + /* ulEffectiveBits was changed from CK_USHORT to CK_ULONG for + * v2.0 */ + CK_ULONG ulEffectiveBits; /* effective bits (1-1024) */ + + CK_BYTE iv[8]; /* IV for CBC mode */ +} CK_RC2_CBC_PARAMS; + +typedef CK_RC2_CBC_PARAMS CK_PTR CK_RC2_CBC_PARAMS_PTR; + + +/* CK_RC2_MAC_GENERAL_PARAMS provides the parameters for the + * CKM_RC2_MAC_GENERAL mechanism */ +/* CK_RC2_MAC_GENERAL_PARAMS is new for v2.0 */ +typedef struct CK_RC2_MAC_GENERAL_PARAMS { + CK_ULONG ulEffectiveBits; /* effective bits (1-1024) */ + CK_ULONG ulMacLength; /* Length of MAC in bytes */ +} CK_RC2_MAC_GENERAL_PARAMS; + +typedef CK_RC2_MAC_GENERAL_PARAMS CK_PTR \ + CK_RC2_MAC_GENERAL_PARAMS_PTR; + + +/* CK_RC5_PARAMS provides the parameters to the CKM_RC5_ECB and + * CKM_RC5_MAC mechanisms */ +/* CK_RC5_PARAMS is new for v2.0 */ +typedef struct CK_RC5_PARAMS { + CK_ULONG ulWordsize; /* wordsize in bits */ + CK_ULONG ulRounds; /* number of rounds */ +} CK_RC5_PARAMS; + +typedef CK_RC5_PARAMS CK_PTR CK_RC5_PARAMS_PTR; + + +/* CK_RC5_CBC_PARAMS provides the parameters to the CKM_RC5_CBC + * mechanism */ +/* CK_RC5_CBC_PARAMS is new for v2.0 */ +typedef struct CK_RC5_CBC_PARAMS { + CK_ULONG ulWordsize; /* wordsize in bits */ + CK_ULONG ulRounds; /* number of rounds */ + CK_BYTE_PTR pIv; /* pointer to IV */ + CK_ULONG ulIvLen; /* length of IV in bytes */ +} CK_RC5_CBC_PARAMS; + +typedef CK_RC5_CBC_PARAMS CK_PTR CK_RC5_CBC_PARAMS_PTR; + + +/* CK_RC5_MAC_GENERAL_PARAMS provides the parameters for the + * CKM_RC5_MAC_GENERAL mechanism */ +/* CK_RC5_MAC_GENERAL_PARAMS is new for v2.0 */ +typedef struct CK_RC5_MAC_GENERAL_PARAMS { + CK_ULONG ulWordsize; /* wordsize in bits */ + CK_ULONG ulRounds; /* number of rounds */ + CK_ULONG ulMacLength; /* Length of MAC in bytes */ +} CK_RC5_MAC_GENERAL_PARAMS; + +typedef CK_RC5_MAC_GENERAL_PARAMS CK_PTR \ + CK_RC5_MAC_GENERAL_PARAMS_PTR; + + +/* CK_MAC_GENERAL_PARAMS provides the parameters to most block + * ciphers' MAC_GENERAL mechanisms. Its value is the length of + * the MAC */ +/* CK_MAC_GENERAL_PARAMS is new for v2.0 */ +typedef CK_ULONG CK_MAC_GENERAL_PARAMS; + +typedef CK_MAC_GENERAL_PARAMS CK_PTR CK_MAC_GENERAL_PARAMS_PTR; + +/* CK_DES/AES_ECB/CBC_ENCRYPT_DATA_PARAMS are new for v2.20 */ +typedef struct CK_DES_CBC_ENCRYPT_DATA_PARAMS { + CK_BYTE iv[8]; + CK_BYTE_PTR pData; + CK_ULONG length; +} CK_DES_CBC_ENCRYPT_DATA_PARAMS; + +typedef CK_DES_CBC_ENCRYPT_DATA_PARAMS CK_PTR CK_DES_CBC_ENCRYPT_DATA_PARAMS_PTR; + +typedef struct CK_AES_CBC_ENCRYPT_DATA_PARAMS { + CK_BYTE iv[16]; + CK_BYTE_PTR pData; + CK_ULONG length; +} CK_AES_CBC_ENCRYPT_DATA_PARAMS; + +typedef CK_AES_CBC_ENCRYPT_DATA_PARAMS CK_PTR CK_AES_CBC_ENCRYPT_DATA_PARAMS_PTR; + +/* CK_SKIPJACK_PRIVATE_WRAP_PARAMS provides the parameters to the + * CKM_SKIPJACK_PRIVATE_WRAP mechanism */ +/* CK_SKIPJACK_PRIVATE_WRAP_PARAMS is new for v2.0 */ +typedef struct CK_SKIPJACK_PRIVATE_WRAP_PARAMS { + CK_ULONG ulPasswordLen; + CK_BYTE_PTR pPassword; + CK_ULONG ulPublicDataLen; + CK_BYTE_PTR pPublicData; + CK_ULONG ulPAndGLen; + CK_ULONG ulQLen; + CK_ULONG ulRandomLen; + CK_BYTE_PTR pRandomA; + CK_BYTE_PTR pPrimeP; + CK_BYTE_PTR pBaseG; + CK_BYTE_PTR pSubprimeQ; +} CK_SKIPJACK_PRIVATE_WRAP_PARAMS; + +typedef CK_SKIPJACK_PRIVATE_WRAP_PARAMS CK_PTR \ + CK_SKIPJACK_PRIVATE_WRAP_PTR; + + +/* CK_SKIPJACK_RELAYX_PARAMS provides the parameters to the + * CKM_SKIPJACK_RELAYX mechanism */ +/* CK_SKIPJACK_RELAYX_PARAMS is new for v2.0 */ +typedef struct CK_SKIPJACK_RELAYX_PARAMS { + CK_ULONG ulOldWrappedXLen; + CK_BYTE_PTR pOldWrappedX; + CK_ULONG ulOldPasswordLen; + CK_BYTE_PTR pOldPassword; + CK_ULONG ulOldPublicDataLen; + CK_BYTE_PTR pOldPublicData; + CK_ULONG ulOldRandomLen; + CK_BYTE_PTR pOldRandomA; + CK_ULONG ulNewPasswordLen; + CK_BYTE_PTR pNewPassword; + CK_ULONG ulNewPublicDataLen; + CK_BYTE_PTR pNewPublicData; + CK_ULONG ulNewRandomLen; + CK_BYTE_PTR pNewRandomA; +} CK_SKIPJACK_RELAYX_PARAMS; + +typedef CK_SKIPJACK_RELAYX_PARAMS CK_PTR \ + CK_SKIPJACK_RELAYX_PARAMS_PTR; + + +typedef struct CK_PBE_PARAMS { + CK_BYTE_PTR pInitVector; + CK_UTF8CHAR_PTR pPassword; + CK_ULONG ulPasswordLen; + CK_BYTE_PTR pSalt; + CK_ULONG ulSaltLen; + CK_ULONG ulIteration; +} CK_PBE_PARAMS; + +typedef CK_PBE_PARAMS CK_PTR CK_PBE_PARAMS_PTR; + + +/* CK_KEY_WRAP_SET_OAEP_PARAMS provides the parameters to the + * CKM_KEY_WRAP_SET_OAEP mechanism */ +/* CK_KEY_WRAP_SET_OAEP_PARAMS is new for v2.0 */ +typedef struct CK_KEY_WRAP_SET_OAEP_PARAMS { + CK_BYTE bBC; /* block contents byte */ + CK_BYTE_PTR pX; /* extra data */ + CK_ULONG ulXLen; /* length of extra data in bytes */ +} CK_KEY_WRAP_SET_OAEP_PARAMS; + +typedef CK_KEY_WRAP_SET_OAEP_PARAMS CK_PTR \ + CK_KEY_WRAP_SET_OAEP_PARAMS_PTR; + + +typedef struct CK_SSL3_RANDOM_DATA { + CK_BYTE_PTR pClientRandom; + CK_ULONG ulClientRandomLen; + CK_BYTE_PTR pServerRandom; + CK_ULONG ulServerRandomLen; +} CK_SSL3_RANDOM_DATA; + + +typedef struct CK_SSL3_MASTER_KEY_DERIVE_PARAMS { + CK_SSL3_RANDOM_DATA RandomInfo; + CK_VERSION_PTR pVersion; +} CK_SSL3_MASTER_KEY_DERIVE_PARAMS; + +typedef struct CK_SSL3_MASTER_KEY_DERIVE_PARAMS CK_PTR \ + CK_SSL3_MASTER_KEY_DERIVE_PARAMS_PTR; + + +typedef struct CK_SSL3_KEY_MAT_OUT { + CK_OBJECT_HANDLE hClientMacSecret; + CK_OBJECT_HANDLE hServerMacSecret; + CK_OBJECT_HANDLE hClientKey; + CK_OBJECT_HANDLE hServerKey; + CK_BYTE_PTR pIVClient; + CK_BYTE_PTR pIVServer; +} CK_SSL3_KEY_MAT_OUT; + +typedef CK_SSL3_KEY_MAT_OUT CK_PTR CK_SSL3_KEY_MAT_OUT_PTR; + + +typedef struct CK_SSL3_KEY_MAT_PARAMS { + CK_ULONG ulMacSizeInBits; + CK_ULONG ulKeySizeInBits; + CK_ULONG ulIVSizeInBits; + CK_BBOOL bIsExport; + CK_SSL3_RANDOM_DATA RandomInfo; + CK_SSL3_KEY_MAT_OUT_PTR pReturnedKeyMaterial; +} CK_SSL3_KEY_MAT_PARAMS; + +typedef CK_SSL3_KEY_MAT_PARAMS CK_PTR CK_SSL3_KEY_MAT_PARAMS_PTR; + +/* CK_TLS_PRF_PARAMS is new for version 2.20 */ +typedef struct CK_TLS_PRF_PARAMS { + CK_BYTE_PTR pSeed; + CK_ULONG ulSeedLen; + CK_BYTE_PTR pLabel; + CK_ULONG ulLabelLen; + CK_BYTE_PTR pOutput; + CK_ULONG_PTR pulOutputLen; +} CK_TLS_PRF_PARAMS; + +typedef CK_TLS_PRF_PARAMS CK_PTR CK_TLS_PRF_PARAMS_PTR; + +/* WTLS is new for version 2.20 */ +typedef struct CK_WTLS_RANDOM_DATA { + CK_BYTE_PTR pClientRandom; + CK_ULONG ulClientRandomLen; + CK_BYTE_PTR pServerRandom; + CK_ULONG ulServerRandomLen; +} CK_WTLS_RANDOM_DATA; + +typedef CK_WTLS_RANDOM_DATA CK_PTR CK_WTLS_RANDOM_DATA_PTR; + +typedef struct CK_WTLS_MASTER_KEY_DERIVE_PARAMS { + CK_MECHANISM_TYPE DigestMechanism; + CK_WTLS_RANDOM_DATA RandomInfo; + CK_BYTE_PTR pVersion; +} CK_WTLS_MASTER_KEY_DERIVE_PARAMS; + +typedef CK_WTLS_MASTER_KEY_DERIVE_PARAMS CK_PTR \ + CK_WTLS_MASTER_KEY_DERIVE_PARAMS_PTR; + +typedef struct CK_WTLS_PRF_PARAMS { + CK_MECHANISM_TYPE DigestMechanism; + CK_BYTE_PTR pSeed; + CK_ULONG ulSeedLen; + CK_BYTE_PTR pLabel; + CK_ULONG ulLabelLen; + CK_BYTE_PTR pOutput; + CK_ULONG_PTR pulOutputLen; +} CK_WTLS_PRF_PARAMS; + +typedef CK_WTLS_PRF_PARAMS CK_PTR CK_WTLS_PRF_PARAMS_PTR; + +typedef struct CK_WTLS_KEY_MAT_OUT { + CK_OBJECT_HANDLE hMacSecret; + CK_OBJECT_HANDLE hKey; + CK_BYTE_PTR pIV; +} CK_WTLS_KEY_MAT_OUT; + +typedef CK_WTLS_KEY_MAT_OUT CK_PTR CK_WTLS_KEY_MAT_OUT_PTR; + +typedef struct CK_WTLS_KEY_MAT_PARAMS { + CK_MECHANISM_TYPE DigestMechanism; + CK_ULONG ulMacSizeInBits; + CK_ULONG ulKeySizeInBits; + CK_ULONG ulIVSizeInBits; + CK_ULONG ulSequenceNumber; + CK_BBOOL bIsExport; + CK_WTLS_RANDOM_DATA RandomInfo; + CK_WTLS_KEY_MAT_OUT_PTR pReturnedKeyMaterial; +} CK_WTLS_KEY_MAT_PARAMS; + +typedef CK_WTLS_KEY_MAT_PARAMS CK_PTR CK_WTLS_KEY_MAT_PARAMS_PTR; + +/* CMS is new for version 2.20 */ +typedef struct CK_CMS_SIG_PARAMS { + CK_OBJECT_HANDLE certificateHandle; + CK_MECHANISM_PTR pSigningMechanism; + CK_MECHANISM_PTR pDigestMechanism; + CK_UTF8CHAR_PTR pContentType; + CK_BYTE_PTR pRequestedAttributes; + CK_ULONG ulRequestedAttributesLen; + CK_BYTE_PTR pRequiredAttributes; + CK_ULONG ulRequiredAttributesLen; +} CK_CMS_SIG_PARAMS; + +typedef CK_CMS_SIG_PARAMS CK_PTR CK_CMS_SIG_PARAMS_PTR; + +typedef struct CK_KEY_DERIVATION_STRING_DATA { + CK_BYTE_PTR pData; + CK_ULONG ulLen; +} CK_KEY_DERIVATION_STRING_DATA; + +typedef CK_KEY_DERIVATION_STRING_DATA CK_PTR \ + CK_KEY_DERIVATION_STRING_DATA_PTR; + + +/* The CK_EXTRACT_PARAMS is used for the + * CKM_EXTRACT_KEY_FROM_KEY mechanism. It specifies which bit + * of the base key should be used as the first bit of the + * derived key */ +/* CK_EXTRACT_PARAMS is new for v2.0 */ +typedef CK_ULONG CK_EXTRACT_PARAMS; + +typedef CK_EXTRACT_PARAMS CK_PTR CK_EXTRACT_PARAMS_PTR; + +/* CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE is new for v2.10. + * CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE is used to + * indicate the Pseudo-Random Function (PRF) used to generate + * key bits using PKCS #5 PBKDF2. */ +typedef CK_ULONG CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE; + +typedef CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE CK_PTR CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE_PTR; + +/* The following PRFs are defined in PKCS #5 v2.0. */ +#define CKP_PKCS5_PBKD2_HMAC_SHA1 0x00000001 + + +/* CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE is new for v2.10. + * CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE is used to indicate the + * source of the salt value when deriving a key using PKCS #5 + * PBKDF2. */ +typedef CK_ULONG CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE; + +typedef CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE CK_PTR CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE_PTR; + +/* The following salt value sources are defined in PKCS #5 v2.0. */ +#define CKZ_SALT_SPECIFIED 0x00000001 + +/* CK_PKCS5_PBKD2_PARAMS is new for v2.10. + * CK_PKCS5_PBKD2_PARAMS is a structure that provides the + * parameters to the CKM_PKCS5_PBKD2 mechanism. */ +typedef struct CK_PKCS5_PBKD2_PARAMS { + CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE saltSource; + CK_VOID_PTR pSaltSourceData; + CK_ULONG ulSaltSourceDataLen; + CK_ULONG iterations; + CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE prf; + CK_VOID_PTR pPrfData; + CK_ULONG ulPrfDataLen; + CK_UTF8CHAR_PTR pPassword; + CK_ULONG_PTR ulPasswordLen; +} CK_PKCS5_PBKD2_PARAMS; + +typedef CK_PKCS5_PBKD2_PARAMS CK_PTR CK_PKCS5_PBKD2_PARAMS_PTR; + +/* All CK_OTP structs are new for PKCS #11 v2.20 amendment 3 */ + +typedef CK_ULONG CK_OTP_PARAM_TYPE; +typedef CK_OTP_PARAM_TYPE CK_PARAM_TYPE; /* B/w compatibility */ + +typedef struct CK_OTP_PARAM { + CK_OTP_PARAM_TYPE type; + CK_VOID_PTR pValue; + CK_ULONG ulValueLen; +} CK_OTP_PARAM; + +typedef CK_OTP_PARAM CK_PTR CK_OTP_PARAM_PTR; + +typedef struct CK_OTP_PARAMS { + CK_OTP_PARAM_PTR pParams; + CK_ULONG ulCount; +} CK_OTP_PARAMS; + +typedef CK_OTP_PARAMS CK_PTR CK_OTP_PARAMS_PTR; + +typedef struct CK_OTP_SIGNATURE_INFO { + CK_OTP_PARAM_PTR pParams; + CK_ULONG ulCount; +} CK_OTP_SIGNATURE_INFO; + +typedef CK_OTP_SIGNATURE_INFO CK_PTR CK_OTP_SIGNATURE_INFO_PTR; + +/* The following OTP-related defines are new for PKCS #11 v2.20 amendment 1 */ +#define CK_OTP_VALUE 0 +#define CK_OTP_PIN 1 +#define CK_OTP_CHALLENGE 2 +#define CK_OTP_TIME 3 +#define CK_OTP_COUNTER 4 +#define CK_OTP_FLAGS 5 +#define CK_OTP_OUTPUT_LENGTH 6 +#define CK_OTP_OUTPUT_FORMAT 7 + +/* The following OTP-related defines are new for PKCS #11 v2.20 amendment 1 */ +#define CKF_NEXT_OTP 0x00000001 +#define CKF_EXCLUDE_TIME 0x00000002 +#define CKF_EXCLUDE_COUNTER 0x00000004 +#define CKF_EXCLUDE_CHALLENGE 0x00000008 +#define CKF_EXCLUDE_PIN 0x00000010 +#define CKF_USER_FRIENDLY_OTP 0x00000020 + +/* CK_KIP_PARAMS is new for PKCS #11 v2.20 amendment 2 */ +typedef struct CK_KIP_PARAMS { + CK_MECHANISM_PTR pMechanism; + CK_OBJECT_HANDLE hKey; + CK_BYTE_PTR pSeed; + CK_ULONG ulSeedLen; +} CK_KIP_PARAMS; + +typedef CK_KIP_PARAMS CK_PTR CK_KIP_PARAMS_PTR; + +/* CK_AES_CTR_PARAMS is new for PKCS #11 v2.20 amendment 3 */ +typedef struct CK_AES_CTR_PARAMS { + CK_ULONG ulCounterBits; + CK_BYTE cb[16]; +} CK_AES_CTR_PARAMS; + +typedef CK_AES_CTR_PARAMS CK_PTR CK_AES_CTR_PARAMS_PTR; + +/* CK_CAMELLIA_CTR_PARAMS is new for PKCS #11 v2.20 amendment 3 */ +typedef struct CK_CAMELLIA_CTR_PARAMS { + CK_ULONG ulCounterBits; + CK_BYTE cb[16]; +} CK_CAMELLIA_CTR_PARAMS; + +typedef CK_CAMELLIA_CTR_PARAMS CK_PTR CK_CAMELLIA_CTR_PARAMS_PTR; + +/* CK_CAMELLIA_CBC_ENCRYPT_DATA_PARAMS is new for PKCS #11 v2.20 amendment 3 */ +typedef struct CK_CAMELLIA_CBC_ENCRYPT_DATA_PARAMS { + CK_BYTE iv[16]; + CK_BYTE_PTR pData; + CK_ULONG length; +} CK_CAMELLIA_CBC_ENCRYPT_DATA_PARAMS; + +typedef CK_CAMELLIA_CBC_ENCRYPT_DATA_PARAMS CK_PTR CK_CAMELLIA_CBC_ENCRYPT_DATA_PARAMS_PTR; + +/* CK_ARIA_CBC_ENCRYPT_DATA_PARAMS is new for PKCS #11 v2.20 amendment 3 */ +typedef struct CK_ARIA_CBC_ENCRYPT_DATA_PARAMS { + CK_BYTE iv[16]; + CK_BYTE_PTR pData; + CK_ULONG length; +} CK_ARIA_CBC_ENCRYPT_DATA_PARAMS; + +typedef CK_ARIA_CBC_ENCRYPT_DATA_PARAMS CK_PTR CK_ARIA_CBC_ENCRYPT_DATA_PARAMS_PTR; + +#endif Index: openssl/util/libeay.num diff -u openssl/util/libeay.num:1.8.2.1.4.1.2.1.4.1.6.1.4.1.2.1 openssl/util/libeay.num:1.15 --- openssl/util/libeay.num:1.8.2.1.4.1.2.1.4.1.6.1.4.1.2.1 Mon Jun 13 15:11:04 2016 +++ openssl/util/libeay.num Mon Jun 13 15:21:08 2016 @@ -4316,3 +4316,5 @@ BIO_s_datagram_sctp 4680 EXIST::FUNCTION:DGRAM,SCTP BIO_dgram_is_sctp 4681 EXIST::FUNCTION:SCTP BIO_dgram_sctp_notification_cb 4682 EXIST::FUNCTION:SCTP +ENGINE_load_pk11ca 4683 EXIST::FUNCTION:HW_PKCS11CA,ENGINE +ENGINE_load_pk11so 4683 EXIST::FUNCTION:HW_PKCS11SO,ENGINE Index: openssl/util/mk1mf.pl diff -u openssl/util/mk1mf.pl:1.9.2.1.4.1.10.1.2.1.4.1.2.1 openssl/util/mk1mf.pl:1.14 --- openssl/util/mk1mf.pl:1.9.2.1.4.1.10.1.2.1.4.1.2.1 Mon Jun 13 15:11:05 2016 +++ openssl/util/mk1mf.pl Mon Jun 13 15:21:08 2016 @@ -114,6 +114,8 @@ no-ecdh - No ECDH no-engine - No engine no-hw - No hw + no-hw-pkcs11ca - No hw PKCS#11 CA flavor + no-hw-pkcs11so - No hw PKCS#11 SO flavor nasm - Use NASM for x86 asm nw-nasm - Use NASM x86 asm for NetWare nw-mwasm - Use Metrowerks x86 asm for NetWare @@ -278,6 +280,8 @@ $cflags.=" -DOPENSSL_NO_GOST" if $no_gost; $cflags.=" -DOPENSSL_NO_ENGINE" if $no_engine; $cflags.=" -DOPENSSL_NO_HW" if $no_hw; +$cflags.=" -DOPENSSL_NO_HW_PKCS11CA" if $no_hw_pkcs11ca; +$cflags.=" -DOPENSSL_NO_HW_PKCS11SO" if $no_hw_pkcs11so; $cflags.=" -DOPENSSL_FIPS" if $fips; $cflags.=" -DOPENSSL_NO_JPAKE" if $no_jpake; $cflags.=" -DOPENSSL_NO_EC2M" if $no_ec2m; @@ -347,6 +351,9 @@ $dir=$val; } + if ($key eq "PK11_LIB_LOCATION") + { $cflags .= " -D$key=\\\"$val\\\"" if $val ne "";} + if ($key eq "KRB5_INCLUDES") { $cflags .= " $val";} @@ -1136,6 +1143,8 @@ "no-gost" => \$no_gost, "no-engine" => \$no_engine, "no-hw" => \$no_hw, + "no-hw-pkcs11ca" => \$no_hw_pkcs11ca, + "no-hw-pkcs11so" => \$no_hw_pkcs11so, "no-rsax" => 0, "just-ssl" => [\$no_rc2, \$no_idea, \$no_des, \$no_bf, \$no_cast, Index: openssl/util/mkdef.pl diff -u openssl/util/mkdef.pl:1.7.2.1.4.1.10.1.2.1.6.1 openssl/util/mkdef.pl:1.12 --- openssl/util/mkdef.pl:1.7.2.1.4.1.10.1.2.1.6.1 Mon Jun 13 15:11:05 2016 +++ openssl/util/mkdef.pl Mon Jun 13 15:21:08 2016 @@ -96,7 +96,7 @@ # External "algorithms" "FP_API", "STDIO", "SOCK", "KRB5", "DGRAM", # Engines - "STATIC_ENGINE", "ENGINE", "HW", "GMP", + "STATIC_ENGINE", "ENGINE", "HW", "GMP", "HW_PKCS11CA", "HW_PKCS11SO", # RFC3779 "RFC3779", # TLS @@ -141,6 +141,7 @@ my $no_md2; my $no_md4; my $no_md5; my $no_sha; my $no_ripemd; my $no_mdc2; my $no_rsa; my $no_dsa; my $no_dh; my $no_hmac=0; my $no_aes; my $no_krb5; my $no_ec; my $no_ecdsa; my $no_ecdh; my $no_engine; my $no_hw; +my $no_pkcs11ca; my $no_pkcs11so; my $no_fp_api; my $no_static_engine=1; my $no_gmp; my $no_deprecated; my $no_rfc3779; my $no_psk; my $no_tlsext; my $no_cms; my $no_capieng; my $no_jpake; my $no_srp; my $no_ssl2; my $no_ec2m; my $no_nistp_gcc; @@ -248,6 +249,8 @@ elsif (/^no-sctp$/) { $no_sctp=1; } elsif (/^no-srtp$/) { $no_srtp=1; } elsif (/^no-unit-test$/){ $no_unit_test=1; } + elsif (/^no-hw-pkcs11ca$/) { $no_pkcs11ca=1; } + elsif (/^no-hw-pkcs11so$/) { $no_pkcs11so=1; } } @@ -1202,6 +1205,8 @@ if ($keyword eq "KRB5" && $no_krb5) { return 0; } if ($keyword eq "ENGINE" && $no_engine) { return 0; } if ($keyword eq "HW" && $no_hw) { return 0; } + if ($keyword eq "HW_PKCS11CA" && $no_pkcs11ca) { return 0; } + if ($keyword eq "HW_PKCS11SO" && $no_pkcs11so) { return 0; } if ($keyword eq "FP_API" && $no_fp_api) { return 0; } if ($keyword eq "STATIC_ENGINE" && $no_static_engine) { return 0; } if ($keyword eq "GMP" && $no_gmp) { return 0; } Index: openssl/util/pl/VC-32.pl diff -u openssl/util/pl/VC-32.pl:1.7.2.1.4.1.2.1.4.1.10.1.2.1 openssl/util/pl/VC-32.pl:1.12 --- openssl/util/pl/VC-32.pl:1.7.2.1.4.1.2.1.4.1.10.1.2.1 Mon Jun 13 15:11:05 2016 +++ openssl/util/pl/VC-32.pl Mon Jun 13 15:21:08 2016 @@ -48,7 +48,7 @@ my $f = $shlib || $fips ?' /MD':' /MT'; $lib_cflag='/Zl' if (!$shlib); # remove /DEFAULTLIBs from static lib $opt_cflags=$f.' /Ox'; - $dbg_cflags=$f.'d /Od -DDEBUG -D_DEBUG'; + $dbg_cflags=$f.'d /Od /Zi -DDEBUG -D_DEBUG'; $lflags="/nologo /subsystem:console /opt:ref"; *::perlasm_compile_target = sub { bind9-9.11.3+dfsg/bin/pkcs11/openssl-1.0.2h-patch000066400000000000000000016427511325250447100207350ustar00rootroot00000000000000Index: openssl/Configure diff -u openssl/Configure:1.9.2.1.2.1.2.1.2.1.2.1.2.1.4.1.2.1.2.1.2.1.2.1 openssl/Configure:1.17.2.3 --- openssl/Configure:1.9.2.1.2.1.2.1.2.1.2.1.2.1.4.1.2.1.2.1.2.1.2.1 Mon Jun 13 15:41:03 2016 +++ openssl/Configure Mon Jun 13 15:51:06 2016 @@ -10,7 +10,7 @@ # see INSTALL for instructions. -my $usage="Usage: Configure [no- ...] [enable- ...] [experimental- ...] [-Dxxx] [-lxxx] [-Lxxx] [-fxxx] [-Kxxx] [no-hw-xxx|no-hw] [[no-]threads] [[no-]shared] [[no-]zlib|zlib-dynamic] [no-asm] [no-dso] [no-krb5] [sctp] [386] [--prefix=DIR] [--openssldir=OPENSSLDIR] [--with-xxx[=vvv]] [--test-sanity] os/compiler[:flags]\n"; +my $usage="Usage: Configure --pk11-libname=PK11_LIB_LOCATION --pk11-flavor=FLAVOR [no- ...] [enable- ...] [experimental- ...] [-Dxxx] [-lxxx] [-Lxxx] [-fxxx] [-Kxxx] [no-hw-xxx|no-hw] [[no-]threads] [[no-]shared] [[no-]zlib|zlib-dynamic] [no-asm] [no-dso] [no-krb5] [sctp] [386] [--prefix=DIR] [--openssldir=OPENSSLDIR] [--with-xxx[=vvv]] [--test-sanity] os/compiler[:flags]\n"; # Options: # @@ -23,6 +23,12 @@ # default). This needn't be set in advance, you can # just as well use "make INSTALL_PREFIX=/whatever install". # +# --pk11-libname PKCS#11 library name. +# (No default) +# +# --pk11-flavor either crypto-accelerator or sign-only +# (No default) +# # --with-krb5-dir Declare where Kerberos 5 lives. The libraries are expected # to live in the subdirectory lib/ and the header files in # include/. A value is required. @@ -402,31 +408,30 @@ # # ./Configure linux-armv4 -march=armv6 -D__ARM_MAX_ARCH__=8 # -"linux-armv4", "gcc: -O3 -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${armv4_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", -"linux-aarch64","gcc: -O3 -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${aarch64_asm}:linux64:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", +"linux-armv4", "gcc:-DTERMIO -O3 -Wall::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${armv4_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", +"linux-aarch64","gcc:-DTERMIO -O3 -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${aarch64_asm}:linux64:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", # Configure script adds minimally required -march for assembly support, # if no -march was specified at command line. mips32 and mips64 below # refer to contemporary MIPS Architecture specifications, MIPS32 and # MIPS64, rather than to kernel bitness. -"linux-mips32", "gcc:-mabi=32 -O3 -Wall -DBN_DIV3W::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${mips32_asm}:o32:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", -"linux-mips64", "gcc:-mabi=n32 -O3 -Wall -DBN_DIV3W::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${mips64_asm}:n32:dlfcn:linux-shared:-fPIC:-mabi=n32:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):::32", -"linux64-mips64", "gcc:-mabi=64 -O3 -Wall -DBN_DIV3W::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${mips64_asm}:64:dlfcn:linux-shared:-fPIC:-mabi=64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):::64", +"linux-mips32", "gcc:-mabi=32 -DTERMIO -O3 -Wall -DBN_DIV3W::-D_REENTRANT::-ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${mips32_asm}:o32:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", +"linux-mips64", "gcc:-mabi=n32 -DTERMIO -O3 -Wall -DBN_DIV3W::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${mips64_asm}:n32:dlfcn:linux-shared:-fPIC:-mabi=n32:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):::32", +"linux64-mips64", "gcc:-mabi=64 -DTERMIO -O3 -Wall -DBN_DIV3W::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${mips64_asm}:64:dlfcn:linux-shared:-fPIC:-mabi=64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):::64", #### IA-32 targets... -"linux-ia32-icc", "icc:-DL_ENDIAN -O2::-D_REENTRANT::-ldl -no_cpprt:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_elf_asm}:dlfcn:linux-shared:-KPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", -"linux-elf", "gcc:-DL_ENDIAN -O3 -fomit-frame-pointer -Wall::-D_REENTRANT::-ldl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_elf_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", -"linux-aout", "gcc:-DL_ENDIAN -O3 -fomit-frame-pointer -march=i486 -Wall::(unknown):::BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_asm}:a.out", +"linux-ia32-icc", "icc:-DL_ENDIAN -DTERMIO -O2::-D_REENTRANT::-ldl -no_cpprt:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_elf_asm}:dlfcn:linux-shared:-KPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", +"linux-elf", "gcc:-DL_ENDIAN -DTERMIO -O3 -fomit-frame-pointer -Wall::-D_REENTRANT -pthread::-ldl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_elf_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", +"linux-aout", "gcc:-DL_ENDIAN -DTERMIO -O3 -fomit-frame-pointer -march=i486 -Wall::(unknown):::BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_asm}:a.out", #### -"linux-generic64","gcc:-O3 -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${no_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", -"linux-ppc64", "gcc:-m64 -DB_ENDIAN -O3 -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_RISC1 DES_UNROLL:${ppc64_asm}:linux64:dlfcn:linux-shared:-fPIC:-m64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):::64", -"linux-ppc64le","gcc:-m64 -DL_ENDIAN -O3 -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_RISC1 DES_UNROLL:$ppc64_asm:linux64le:dlfcn:linux-shared:-fPIC:-m64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):::", +"linux-generic64","gcc:-DTERMIO -O3 -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${no_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", +"linux-ppc64", "gcc:-m64 -DB_ENDIAN -DTERMIO -O3 -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_RISC1 DES_UNROLL:${ppc64_asm}:linux64:dlfcn:linux-shared:-fPIC:-m64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):::64", +"linux-ppc64le","gcc:-m64 -DL_ENDIAN -DTERMIO -O3 -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_RISC1 DES_UNROLL:$ppc64_asm:linux64le:dlfcn:linux-shared:-fPIC:-m64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):::", "linux-ia64", "gcc:-DL_ENDIAN -DTERMIO -O3 -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_UNROLL DES_INT:${ia64_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", -"linux-ia64-icc","icc:-DL_ENDIAN -O2 -Wall::-D_REENTRANT::-ldl -no_cpprt:SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_RISC1 DES_INT:${ia64_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", -"linux-x86_64", "gcc:-m64 -DL_ENDIAN -O3 -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_INT DES_UNROLL:${x86_64_asm}:elf:dlfcn:linux-shared:-fPIC:-m64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):::64", -"linux-x86_64-clang", "clang: -m64 -DL_ENDIAN -O3 -Wall -Wextra $clang_disabled_warnings -Qunused-arguments::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_INT DES_UNROLL:${x86_64_asm}:elf:dlfcn:linux-shared:-fPIC:-m64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):::64", -"debug-linux-x86_64-clang", "clang: -DBN_DEBUG -DREF_CHECK -DCONF_DEBUG -DCRYPTO_MDEBUG -m64 -DL_ENDIAN -g -Wall -Wextra $clang_disabled_warnings -Qunused-arguments::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_INT DES_UNROLL:${x86_64_asm}:elf:dlfcn:linux-shared:-fPIC:-m64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):::64", -"linux-x86_64-icc", "icc:-DL_ENDIAN -O2::-D_REENTRANT::-ldl -no_cpprt:SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_INT DES_UNROLL:${x86_64_asm}:elf:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):::64", -"linux-x32", "gcc:-mx32 -DL_ENDIAN -O3 -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT RC4_CHUNK_LL DES_INT DES_UNROLL:${x86_64_asm}:elf:dlfcn:linux-shared:-fPIC:-mx32:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):::x32", -"linux64-s390x", "gcc:-m64 -DB_ENDIAN -O3 -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL:${s390x_asm}:64:dlfcn:linux-shared:-fPIC:-m64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):::64", +"linux-ia64-icc","icc:-DL_ENDIAN -DTERMIO -O2 -Wall::-D_REENTRANT::-ldl -no_cpprt:SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_RISC1 DES_INT:${ia64_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", +"linux-x86_64", "gcc:-m64 -DL_ENDIAN -DTERMIO -O3 -Wall::-D_REENTRANT -pthread::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_INT DES_UNROLL:${x86_64_asm}:elf:dlfcn:linux-shared:-fPIC:-m64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):::64", +"linux-x86_64-clang", "clang: -m64 -DL_ENDIAN -DTERMIO -O3 -Weverything $clang_disabled_warnings -Qunused-arguments::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_INT DES_UNROLL:${x86_64_asm}:elf:dlfcn:linux-shared:-fPIC:-m64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):::64", +"linux-x86_64-icc", "icc:-DL_ENDIAN -DTERMIO -O2::-D_REENTRANT::-ldl -no_cpprt:SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_INT DES_UNROLL:${x86_64_asm}:elf:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):::64", +"linux-x32", "gcc:-mx32 -DL_ENDIAN -DTERMIO -O3 -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT RC4_CHUNK_LL DES_INT DES_UNROLL:${x86_64_asm}:elf:dlfcn:linux-shared:-fPIC:-mx32:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):::x32", +"linux64-s390x", "gcc:-m64 -DB_ENDIAN -DTERMIO -O3 -Wall::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL:${s390x_asm}:64:dlfcn:linux-shared:-fPIC:-m64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):::64", #### So called "highgprs" target for z/Architecture CPUs # "Highgprs" is kernel feature first implemented in Linux 2.6.32, see # /proc/cpuinfo. The idea is to preserve most significant bits of @@ -724,6 +729,10 @@ my $idx_arflags = $idx++; my $idx_multilib = $idx++; +# PKCS#11 engine patch +my $pk11_libname=""; +my $pk11_flavor=""; + my $prefix=""; my $libdir=""; my $openssldir=""; @@ -944,7 +953,15 @@ } elsif (/^[-+]/) { - if (/^--prefix=(.*)$/) + if (/^--pk11-libname=(.*)$/) + { + $pk11_libname=$1; + } + elsif (/^--pk11-flavor=(.*)$/) + { + $pk11_flavor=$1; + } + elsif (/^--prefix=(.*)$/) { $prefix=$1; } @@ -1115,6 +1132,22 @@ exit 0; } +if (! $pk11_libname) + { + print STDERR "You must set --pk11-libname for PKCS#11 library.\n"; + print STDERR "See README.pkcs11 for more information.\n"; + exit 1; + } + +if (! $pk11_flavor + || !($pk11_flavor eq "crypto-accelerator" || $pk11_flavor eq "sign-only")) + { + print STDERR "You must set --pk11-flavor.\n"; + print STDERR "Choices are crypto-accelerator and sign-only.\n"; + print STDERR "See README.pkcs11 for more information.\n"; + exit 1; + } + if ($target =~ m/^CygWin32(-.*)$/) { $target = "Cygwin".$1; } @@ -1192,6 +1225,25 @@ $exp_cflags .= " -DOPENSSL_EXPERIMENTAL_$ALGO"; } +if ($pk11_flavor eq "crypto-accelerator") + { + $openssl_other_defines .= "#define OPENSSL_NO_HW_PKCS11SO\n"; + $default_depflags .= " -DOPENSSL_NO_HW_PKCS11SO"; + $depflags .= " -DOPENSSL_NO_HW_PKCS11SO"; + $options .= " no-hw-pkcs11so"; + print " no-hw-pkcs11so [pk11-flavor]"; + print " OPENSSL_NO_HW_PKCS11SO\n"; + } +else + { + $openssl_other_defines .= "#define OPENSSL_NO_HW_PKCS11CA\n"; + $default_depflags .= " -DOPENSSL_NO_HW_PKCS11CA"; + $depflags .= " -DOPENSSL_NO_HW_PKCS11CA"; + $options .= " no-hw-pkcs11ca"; + print " no-hw-pkcs11ca [pk11-flavor]"; + print " OPENSSL_NO_HW_PKCS11CA\n"; +} + my $IsMK1MF=scalar grep /^$target$/,@MK1MF_Builds; $exe_ext=".exe" if ($target eq "Cygwin" || $target eq "DJGPP" || $target =~ /^mingw/); @@ -1289,6 +1341,8 @@ if ($flags ne "") { $cflags="$flags$cflags"; } else { $no_user_cflags=1; } +$cflags="-DPK11_LIB_LOCATION=\"$pk11_libname\" $cflags"; + # Kerberos settings. The flavor must be provided from outside, either through # the script "config" or manually. if (!$no_krb5) @@ -1698,6 +1752,7 @@ s/^VERSION=.*/VERSION=$version/; s/^MAJOR=.*/MAJOR=$major/; s/^MINOR=.*/MINOR=$minor/; + s/^PK11_LIB_LOCATION=.*/PK11_LIB_LOCATION=$pk11_libname/; s/^SHLIB_VERSION_NUMBER=.*/SHLIB_VERSION_NUMBER=$shlib_version_number/; s/^SHLIB_VERSION_HISTORY=.*/SHLIB_VERSION_HISTORY=$shlib_version_history/; s/^SHLIB_MAJOR=.*/SHLIB_MAJOR=$shlib_major/; Index: openssl/Makefile.org diff -u openssl/Makefile.org:1.5.2.1.2.1.2.1.2.1.2.1.2.1.8.1.2.1.2.1 openssl/Makefile.org:1.10.2.3 --- openssl/Makefile.org:1.5.2.1.2.1.2.1.2.1.2.1.2.1.8.1.2.1.2.1 Mon Jun 13 15:41:03 2016 +++ openssl/Makefile.org Mon Jun 13 15:51:08 2016 @@ -26,6 +26,9 @@ INSTALL_PREFIX= INSTALLTOP=/usr/local/ssl +# You must set this through --pk11-libname configure option. +PK11_LIB_LOCATION= + # Do not edit this manually. Use Configure --openssldir=DIR do change this! OPENSSLDIR=/usr/local/ssl Index: openssl/README.pkcs11 diff -u /dev/null openssl/README.pkcs11:1.8 --- /dev/null Mon Jun 13 15:55:24 2016 +++ openssl/README.pkcs11 Fri Oct 4 14:16:43 2013 @@ -0,0 +1,266 @@ +ISC modified +============ + +The previous key naming scheme was kept for backward compatibility. + +The PKCS#11 engine exists in two flavors, crypto-accelerator and +sign-only. The first one is from the Solaris patch and uses the +PKCS#11 device for all crypto operations it supports. The second +is a stripped down version which provides only the useful +function (i.e., signature with a RSA private key in the device +protected key store and key loading). + +As a hint PKCS#11 boards should use the crypto-accelerator flavor, +external PKCS#11 devices the sign-only. SCA 6000 is an example +of the first, AEP Keyper of the second. + +Note it is mandatory to set a pk11-flavor (and only one) in +config/Configure. + +It is highly recommended to compile in (vs. as a DSO) the engine. +The way to configure this is system dependent, on Unixes it is no-shared +(and is in general the default), on WIN32 it is enable-static-engine +(and still enable to build the OpenSSL libraries as DLLs). + +PKCS#11 engine support for OpenSSL 0.9.8l +========================================= + +[Nov 19, 2009] + +Contents: + +Overview +Revisions of the patch for 0.9.8 branch +FAQs +Feedback + +Overview +======== + +This patch containing code available in OpenSolaris adds support for PKCS#11 +engine into OpenSSL and implements PKCS#11 v2.20. It is to be applied against +OpenSSL 0.9.8l source code distribution as shipped by OpenSSL.Org. Your system +must provide PKCS#11 backend otherwise the patch is useless. You provide the +PKCS#11 library name during the build configuration phase, see below. + +Patch can be applied like this: + + # NOTE: use gtar if on Solaris + tar xfzv openssl-0.9.8l.tar.gz + # now download the patch to the current directory + # ... + cd openssl-0.9.8l + # NOTE: must use gpatch if on Solaris (is part of the system) + patch -p1 < path-to/pkcs11_engine-0.9.8l.patch.2009-11-19 + +It is designed to support pure acceleration for RSA, DSA, DH and all the +symetric ciphers and message digest algorithms that PKCS#11 and OpenSSL share +except for missing support for patented algorithms MDC2, RC3, RC5 and IDEA. + +According to the PKCS#11 providers installed on your machine, it can support +following mechanisms: + + RSA, DSA, DH, RAND, DES-CBC, DES-EDE3-CBC, DES-ECB, DES-EDE3, RC4, + AES-128-CBC, AES-192-CBC, AES-256-CBC, AES-128-ECB, AES-192-ECB, + AES-256-ECB, AES-128-CTR, AES-192-CTR, AES-256-CTR, MD5, SHA1, SHA224, + SHA256, SHA384, SHA512 + +Note that for AES counter mode the application must provide their own EVP +functions since OpenSSL doesn't support counter mode through EVP yet. You may +see OpenSSH source code (cipher.c) to get the idea how to do that. SunSSH is an +example of code that uses the PKCS#11 engine and deals with the fork-safety +problem (see engine.c and packet.c files if interested). + +You must provide the location of PKCS#11 library in your system to the +configure script. You will be instructed to do that when you try to run the +config script: + + $ ./config + Operating system: i86pc-whatever-solaris2 + Configuring for solaris-x86-cc + You must set --pk11-libname for PKCS#11 library. + See README.pkcs11 for more information. + +Taking openCryptoki project on Linux AMD64 box as an example, you would run +configure script like this: + + ./config --pk11-libname=/usr/lib64/pkcs11/PKCS11_API.so + +To check whether newly built openssl really supports PKCS#11 it's enough to run +"apps/openssl engine" and look for "(pkcs11) PKCS #11 engine support" in the +output. If you see no PKCS#11 engine support check that the built openssl binary +and the PKCS#11 library from --pk11-libname don't conflict on 32/64 bits. + +The patch, during various phases of development, was tested on Solaris against +PKCS#11 engine available from Solaris Cryptographic Framework (Solaris 10 and +OpenSolaris) and also on Linux using PKCS#11 libraries from openCryptoki project +(see openCryptoki website http://sourceforge.net/projects/opencryptoki for more +information). Some Linux distributions even ship those libraries with the +system. The patch should work on any system that is supported by OpenSSL itself +and has functional PKCS#11 library. + +The patch contains "RSA Security Inc. PKCS #11 Cryptographic Token Interface +(Cryptoki)" - files cryptoki.h, pkcs11.h, pkcs11f.h and pkcs11t.h which are +copyrighted by RSA Security Inc., see pkcs11.h for more information. + +Other added/modified code in this patch is copyrighted by Sun Microsystems, +Inc. and is released under the OpenSSL license (see LICENSE file for more +information). + +Revisions of the patch for 0.9.8 branch +======================================= + +2009-11-19 +- adjusted for OpenSSL version 0.9.8l + +- bugs and RFEs: + + 6479874 OpenSSL should support RSA key by reference/hardware keystores + 6896677 PKCS#11 engine's hw_pk11_err.h needs to be split + 6732677 make check to trigger Solaris specific code automatic in the + PKCS#11 engine + +2009-03-11 +- adjusted for OpenSSL version 0.9.8j + +- README.pkcs11 moved out of the patch, and is shipped together with it in a + tarball instead so that it can be read before the patch is applied. + +- fixed bugs: + + 6804216 pkcs#11 engine should support a key length range for RC4 + 6734038 Apache SSL web server using the pkcs11 engine fails to start if + meta slot is disabled + +2008-12-02 +- fixed bugs and RFEs (most of the work done by Vladimir Kotal) + + 6723504 more granular locking in PKCS#11 engine + 6667128 CRYPTO_LOCK_PK11_ENGINE assumption does not hold true + 6710420 PKCS#11 engine source should be lint clean + 6747327 PKCS#11 engine atfork handlers need to be aware of guys who take + it seriously + 6746712 PKCS#11 engine source code should be cstyle clean + 6731380 return codes of several functions are not checked in the PKCS#11 + engine code + 6746735 PKCS#11 engine should use extended FILE space API + 6734038 Apache SSL web server using the pkcs11 engine fails to start if + meta slot is disabled + +2008-08-01 +- fixed bug + + 6731839 OpenSSL PKCS#11 engine no longer uses n2cp for symmetric ciphers + and digests + +- Solaris specific code for slot selection made automatic + +2008-07-29 +- update the patch to OpenSSL 0.9.8h version +- pkcs11t.h updated to the latest version: + + 6545665 make CKM_AES_CTR available to non-kernel users + +- fixed bugs in the engine code: + + 6602801 PK11_SESSION cache has to employ reference counting scheme for + asymmetric key operations + 6605538 pkcs11 functions C_FindObjects[{Init,Final}]() not called + atomically + 6607307 pkcs#11 engine can't read RSA private keys + 6652362 pk11_RSA_finish() is cutting corners + 6662112 pk11_destroy_{rsa,dsa,dh}_key_objects() use locking in + suboptimal way + 6666625 pk11_destroy_{rsa,dsa,dh}_key_objects() should be more + resilient to destroy failures + 6667273 OpenSSL engine should not use free() but OPENSSL_free() + 6670363 PKCS#11 engine fails to reuse existing symmetric keys + 6678135 memory corruption in pk11_DH_generate_key() in pkcs#11 engine + 6678503 DSA signature conversion in pk11_dsa_do_verify() ignores size + of big numbers leading to failures + 6706562 pk11_DH_compute_key() returns 0 in case of failure instead of + -1 + 6706622 pk11_load_{pub,priv}key create corrupted RSA key references + 6707129 return values from BN_new() in pk11_DH_generate_key() are not + checked + 6707274 DSA/RSA/DH PKCS#11 engine operations need to be resistant to + structure reuse + 6707782 OpenSSL PKCS#11 engine pretends to be aware of + OPENSSL_NO_{RSA,DSA,DH} + defines but fails miserably + 6709966 make check_new_*() to return values to indicate cache hit/miss + 6705200 pk11_dh struct initialization in PKCS#11 engine is missing + generate_params parameter + 6709513 PKCS#11 engine sets IV length even for ECB modes + 6728296 buffer length not initialized for C_(En|De)crypt_Final() in the + PKCS#11 engine + 6728871 PKCS#11 engine must reset global_session in pk11_finish() + +- new features and enhancements: + + 6562155 OpenSSL pkcs#11 engine needs support for SHA224/256/384/512 + 6685012 OpenSSL pkcs#11 engine needs support for new cipher modes + 6725903 OpenSSL PKCS#11 engine shouldn't use soft token for symmetric + ciphers and digests + +2007-10-15 +- update for 0.9.8f version +- update for "6607670 teach pkcs#11 engine how to use keys be reference" + +2007-10-02 +- draft for "6607670 teach pkcs#11 engine how to use keys be reference" +- draft for "6607307 pkcs#11 engine can't read RSA private keys" + +2007-09-26 +- 6375348 Using pkcs11 as the SSLCryptoDevice with Apache/OpenSSL causes + significant performance drop +- 6573196 memory is leaked when OpenSSL is used with PKCS#11 engine + +2007-05-25 +- 6558630 race in OpenSSL pkcs11 engine when using symetric block ciphers + +2007-05-19 +- initial patch for 0.9.8e using latest OpenSolaris code + +FAQs +==== + +(1) my build failed on Linux distro with this error: + +../libcrypto.a(hw_pk11.o): In function `pk11_library_init': +hw_pk11.c:(.text+0x20f5): undefined reference to `pthread_atfork' + +Answer: + + - don't use "no-threads" when configuring + - if you didn't then OpenSSL failed to create a threaded library by + default. You may manually edit Configure and try again. Look for the + architecture that Configure printed, for example: + +Configured for linux-elf. + + - then edit Configure, find string "linux-elf" (inluding the quotes), + and add flags to support threads to the 4th column of the 2nd string. + If you build with GCC then adding "-pthread" should be enough. With + "linux-elf" as an example, you would add " -pthread" right after + "-D_REENTRANT", like this: + +....-O3 -fomit-frame-pointer -Wall::-D_REENTRANT -pthread::-ldl:..... + +(2) I'm using MinGW/MSYS environment and get undeclared reference error for +pthread_atfork() function when trying to build OpenSSL with the patch. + +Answer: + + Sorry, pthread_atfork() is not implemented in the current pthread-win32 + (as of Nov 2009). You can not use the patch there. + + +Feedback +======== + +Please send feedback to security-discuss@opensolaris.org. The patch was +created by Jan.Pechanec@Sun.COM from code available in OpenSolaris. + +Latest version should be always available on http://blogs.sun.com/janp. + Index: openssl/crypto/opensslconf.h diff -u openssl/crypto/opensslconf.h:1.6.2.1.4.1.10.1.4.1.2.1.2.1 openssl/crypto/opensslconf.h:1.8.2.3 --- openssl/crypto/opensslconf.h:1.6.2.1.4.1.10.1.4.1.2.1.2.1 Mon Jun 13 15:41:06 2016 +++ openssl/crypto/opensslconf.h Mon Jun 13 15:51:23 2016 @@ -53,6 +53,9 @@ #endif /* OPENSSL_DOING_MAKEDEPEND */ +#ifndef OPENSSL_THREADS +# define OPENSSL_THREADS +#endif #ifndef OPENSSL_NO_DYNAMIC_ENGINE # define OPENSSL_NO_DYNAMIC_ENGINE #endif @@ -106,6 +109,8 @@ # endif #endif +#define OPENSSL_CPUID_OBJ + /* crypto/opensslconf.h.in */ /* Generate 80386 code? */ @@ -152,7 +157,7 @@ * This enables code handling data aligned at natural CPU word * boundary. See crypto/rc4/rc4_enc.c for further details. */ -#undef RC4_CHUNK +#define RC4_CHUNK unsigned long #endif #endif @@ -160,7 +165,7 @@ /* If this is set to 'unsigned int' on a DEC Alpha, this gives about a * %20 speed up (longs are 8 bytes, int's are 4). */ #ifndef DES_LONG -#define DES_LONG unsigned long +#define DES_LONG unsigned int #endif #endif @@ -171,9 +176,9 @@ /* Should we define BN_DIV2W here? */ /* Only one for the following should be defined */ -#undef SIXTY_FOUR_BIT_LONG +#define SIXTY_FOUR_BIT_LONG #undef SIXTY_FOUR_BIT -#define THIRTY_TWO_BIT +#undef THIRTY_TWO_BIT #endif #if defined(HEADER_RC4_LOCL_H) && !defined(CONFIG_HEADER_RC4_LOCL_H) @@ -185,7 +190,7 @@ #if defined(HEADER_BF_LOCL_H) && !defined(CONFIG_HEADER_BF_LOCL_H) #define CONFIG_HEADER_BF_LOCL_H -#undef BF_PTR +#define BF_PTR2 #endif /* HEADER_BF_LOCL_H */ #if defined(HEADER_DES_LOCL_H) && !defined(CONFIG_HEADER_DES_LOCL_H) @@ -215,7 +220,7 @@ /* Unroll the inner loop, this sometimes helps, sometimes hinders. * Very mucy CPU dependant */ #ifndef DES_UNROLL -#undef DES_UNROLL +#define DES_UNROLL #endif /* These default values were supplied by Index: openssl/crypto/bio/bss_file.c diff -u openssl/crypto/bio/bss_file.c:1.6.2.1.28.1.2.1 openssl/crypto/bio/bss_file.c:1.6.10.2 --- openssl/crypto/bio/bss_file.c:1.6.2.1.28.1.2.1 Wed Dec 23 18:55:13 2015 +++ openssl/crypto/bio/bss_file.c Wed Dec 23 19:28:46 2015 @@ -174,7 +174,7 @@ if (file == NULL) { SYSerr(SYS_F_FOPEN, get_last_sys_error()); ERR_add_error_data(5, "fopen('", filename, "','", mode, "')"); - if (errno == ENOENT) + if ((errno == ENOENT) || ((*mode == 'r') && (errno == EACCES))) BIOerr(BIO_F_BIO_NEW_FILE, BIO_R_NO_SUCH_FILE); else BIOerr(BIO_F_BIO_NEW_FILE, ERR_R_SYS_LIB); Index: openssl/crypto/engine/Makefile diff -u openssl/crypto/engine/Makefile:1.8.2.1.4.1.14.1.2.1 openssl/crypto/engine/Makefile:1.9.6.2 --- openssl/crypto/engine/Makefile:1.8.2.1.4.1.14.1.2.1 Wed Dec 23 18:55:22 2015 +++ openssl/crypto/engine/Makefile Wed Dec 23 19:28:56 2015 @@ -22,13 +22,15 @@ tb_rsa.c tb_dsa.c tb_ecdsa.c tb_dh.c tb_ecdh.c tb_rand.c tb_store.c \ tb_cipher.c tb_digest.c tb_pkmeth.c tb_asnmth.c \ eng_openssl.c eng_cnf.c eng_dyn.c eng_cryptodev.c \ - eng_rdrand.c + eng_rdrand.c \ + hw_pk11.c hw_pk11_pub.c hw_pk11so.c hw_pk11so_pub.c LIBOBJ= eng_err.o eng_lib.o eng_list.o eng_init.o eng_ctrl.o \ eng_table.o eng_pkey.o eng_fat.o eng_all.o \ tb_rsa.o tb_dsa.o tb_ecdsa.o tb_dh.o tb_ecdh.o tb_rand.o tb_store.o \ tb_cipher.o tb_digest.o tb_pkmeth.o tb_asnmth.o \ eng_openssl.o eng_cnf.o eng_dyn.o eng_cryptodev.o \ - eng_rdrand.o + eng_rdrand.o \ + hw_pk11.o hw_pk11_pub.o hw_pk11so.o hw_pk11so_pub.o SRC= $(LIBSRC) @@ -282,6 +284,83 @@ eng_table.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h eng_table.o: ../../include/openssl/x509_vfy.h ../cryptlib.h eng_int.h eng_table.o: eng_table.c +hw_pk11.o: ../../e_os.h ../../include/openssl/aes.h +hw_pk11.o: ../../include/openssl/asn1.h ../../include/openssl/bio.h +hw_pk11.o: ../../include/openssl/bn.h ../../include/openssl/buffer.h +hw_pk11.o: ../../include/openssl/crypto.h ../../include/openssl/dh.h +hw_pk11.o: ../../include/openssl/dsa.h ../../include/openssl/dso.h +hw_pk11.o: ../../include/openssl/e_os2.h ../../include/openssl/ec.h +hw_pk11.o: ../../include/openssl/ecdh.h ../../include/openssl/ecdsa.h +hw_pk11.o: ../../include/openssl/engine.h ../../include/openssl/err.h +hw_pk11.o: ../../include/openssl/evp.h ../../include/openssl/lhash.h +hw_pk11.o: ../../include/openssl/md5.h ../../include/openssl/obj_mac.h +hw_pk11.o: ../../include/openssl/objects.h ../../include/openssl/opensslconf.h +hw_pk11.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h +hw_pk11.o: ../../include/openssl/pem.h ../../include/openssl/pem2.h +hw_pk11.o: ../../include/openssl/pkcs7.h ../../include/openssl/rand.h +hw_pk11.o: ../../include/openssl/rsa.h ../../include/openssl/safestack.h +hw_pk11.o: ../../include/openssl/sha.h ../../include/openssl/stack.h +hw_pk11.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h +hw_pk11.o: ../../include/openssl/x509_vfy.h ../cryptlib.h cryptoki.h hw_pk11.c +hw_pk11.o: hw_pk11_err.c hw_pk11_err.h hw_pk11ca.h pkcs11.h pkcs11f.h pkcs11t.h +hw_pk11_pub.o: ../../e_os.h ../../include/openssl/asn1.h +hw_pk11_pub.o: ../../include/openssl/bio.h ../../include/openssl/bn.h +hw_pk11_pub.o: ../../include/openssl/buffer.h ../../include/openssl/crypto.h +hw_pk11_pub.o: ../../include/openssl/dh.h ../../include/openssl/dsa.h +hw_pk11_pub.o: ../../include/openssl/dso.h ../../include/openssl/e_os2.h +hw_pk11_pub.o: ../../include/openssl/ec.h ../../include/openssl/ecdh.h +hw_pk11_pub.o: ../../include/openssl/ecdsa.h ../../include/openssl/engine.h +hw_pk11_pub.o: ../../include/openssl/err.h ../../include/openssl/evp.h +hw_pk11_pub.o: ../../include/openssl/lhash.h ../../include/openssl/obj_mac.h +hw_pk11_pub.o: ../../include/openssl/objects.h +hw_pk11_pub.o: ../../include/openssl/opensslconf.h +hw_pk11_pub.o: ../../include/openssl/opensslv.h +hw_pk11_pub.o: ../../include/openssl/ossl_typ.h ../../include/openssl/pem.h +hw_pk11_pub.o: ../../include/openssl/pem2.h ../../include/openssl/pkcs7.h +hw_pk11_pub.o: ../../include/openssl/rand.h ../../include/openssl/rsa.h +hw_pk11_pub.o: ../../include/openssl/safestack.h ../../include/openssl/sha.h +hw_pk11_pub.o: ../../include/openssl/stack.h ../../include/openssl/symhacks.h +hw_pk11_pub.o: ../../include/openssl/x509.h ../../include/openssl/x509_vfy.h +hw_pk11_pub.o: ../cryptlib.h cryptoki.h hw_pk11_err.h hw_pk11_pub.c hw_pk11ca.h +hw_pk11_pub.o: pkcs11.h pkcs11f.h pkcs11t.h +hw_pk11so.o: ../../e_os.h ../../include/openssl/asn1.h +hw_pk11so.o: ../../include/openssl/bio.h ../../include/openssl/bn.h +hw_pk11so.o: ../../include/openssl/buffer.h ../../include/openssl/crypto.h +hw_pk11so.o: ../../include/openssl/dso.h ../../include/openssl/e_os2.h +hw_pk11so.o: ../../include/openssl/ec.h ../../include/openssl/ecdh.h +hw_pk11so.o: ../../include/openssl/ecdsa.h ../../include/openssl/engine.h +hw_pk11so.o: ../../include/openssl/err.h ../../include/openssl/evp.h +hw_pk11so.o: ../../include/openssl/lhash.h ../../include/openssl/md5.h +hw_pk11so.o: ../../include/openssl/obj_mac.h ../../include/openssl/objects.h +hw_pk11so.o: ../../include/openssl/opensslconf.h +hw_pk11so.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h +hw_pk11so.o: ../../include/openssl/pem.h ../../include/openssl/pem2.h +hw_pk11so.o: ../../include/openssl/pkcs7.h ../../include/openssl/rand.h +hw_pk11so.o: ../../include/openssl/rsa.h ../../include/openssl/safestack.h +hw_pk11so.o: ../../include/openssl/sha.h ../../include/openssl/stack.h +hw_pk11so.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h +hw_pk11so.o: ../../include/openssl/x509_vfy.h ../cryptlib.h cryptoki.h +hw_pk11so.o: hw_pk11_err.c hw_pk11_err.h hw_pk11so.c hw_pk11so.h pkcs11.h +hw_pk11so.o: pkcs11f.h pkcs11t.h +hw_pk11so_pub.o: ../../e_os.h ../../include/openssl/asn1.h +hw_pk11so_pub.o: ../../include/openssl/bio.h ../../include/openssl/bn.h +hw_pk11so_pub.o: ../../include/openssl/buffer.h ../../include/openssl/crypto.h +hw_pk11so_pub.o: ../../include/openssl/dso.h ../../include/openssl/e_os2.h +hw_pk11so_pub.o: ../../include/openssl/ec.h ../../include/openssl/ecdh.h +hw_pk11so_pub.o: ../../include/openssl/ecdsa.h ../../include/openssl/engine.h +hw_pk11so_pub.o: ../../include/openssl/err.h ../../include/openssl/evp.h +hw_pk11so_pub.o: ../../include/openssl/lhash.h ../../include/openssl/obj_mac.h +hw_pk11so_pub.o: ../../include/openssl/objects.h +hw_pk11so_pub.o: ../../include/openssl/opensslconf.h +hw_pk11so_pub.o: ../../include/openssl/opensslv.h +hw_pk11so_pub.o: ../../include/openssl/ossl_typ.h ../../include/openssl/pem.h +hw_pk11so_pub.o: ../../include/openssl/pem2.h ../../include/openssl/pkcs7.h +hw_pk11so_pub.o: ../../include/openssl/rand.h ../../include/openssl/rsa.h +hw_pk11so_pub.o: ../../include/openssl/safestack.h ../../include/openssl/sha.h +hw_pk11so_pub.o: ../../include/openssl/stack.h ../../include/openssl/symhacks.h +hw_pk11so_pub.o: ../../include/openssl/x509.h ../../include/openssl/x509_vfy.h +hw_pk11so_pub.o: ../cryptlib.h cryptoki.h hw_pk11_err.h hw_pk11so.h +hw_pk11so_pub.o: hw_pk11so_pub.c pkcs11.h pkcs11f.h pkcs11t.h tb_asnmth.o: ../../e_os.h ../../include/openssl/asn1.h tb_asnmth.o: ../../include/openssl/bio.h ../../include/openssl/buffer.h tb_asnmth.o: ../../include/openssl/crypto.h ../../include/openssl/e_os2.h Index: openssl/crypto/engine/cryptoki.h diff -u /dev/null openssl/crypto/engine/cryptoki.h:1.4 --- /dev/null Mon Jun 13 15:55:25 2016 +++ openssl/crypto/engine/cryptoki.h Thu Dec 18 00:14:12 2008 @@ -0,0 +1,103 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _CRYPTOKI_H +#define _CRYPTOKI_H + +/* ident "@(#)cryptoki.h 1.2 05/06/08 SMI" */ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef CK_PTR +#define CK_PTR * +#endif + +#ifndef CK_DEFINE_FUNCTION +#define CK_DEFINE_FUNCTION(returnType, name) returnType name +#endif + +#ifndef CK_DECLARE_FUNCTION +#define CK_DECLARE_FUNCTION(returnType, name) returnType name +#endif + +#ifndef CK_DECLARE_FUNCTION_POINTER +#define CK_DECLARE_FUNCTION_POINTER(returnType, name) returnType (* name) +#endif + +#ifndef CK_CALLBACK_FUNCTION +#define CK_CALLBACK_FUNCTION(returnType, name) returnType (* name) +#endif + +#ifndef NULL_PTR +#include /* For NULL */ +#define NULL_PTR NULL +#endif + +/* + * pkcs11t.h defines TRUE and FALSE in a way that upsets lint + */ +#ifndef CK_DISABLE_TRUE_FALSE +#define CK_DISABLE_TRUE_FALSE +#ifndef TRUE +#define TRUE 1 +#endif /* TRUE */ +#ifndef FALSE +#define FALSE 0 +#endif /* FALSE */ +#endif /* CK_DISABLE_TRUE_FALSE */ + +#undef CK_PKCS11_FUNCTION_INFO + +#include "pkcs11.h" + +/* Solaris specific functions */ + +#include + +/* + * SUNW_C_GetMechSession will initialize the framework and do all + * the necessary PKCS#11 calls to create a session capable of + * providing operations on the requested mechanism + */ +CK_RV SUNW_C_GetMechSession(CK_MECHANISM_TYPE mech, + CK_SESSION_HANDLE_PTR hSession); + +/* + * SUNW_C_KeyToObject will create a secret key object for the given + * mechanism from the rawkey data. + */ +CK_RV SUNW_C_KeyToObject(CK_SESSION_HANDLE hSession, + CK_MECHANISM_TYPE mech, const void *rawkey, size_t rawkey_len, + CK_OBJECT_HANDLE_PTR obj); + + +#ifdef __cplusplus +} +#endif + +#endif /* _CRYPTOKI_H */ Index: openssl/crypto/engine/eng_all.c diff -u openssl/crypto/engine/eng_all.c:1.5.2.1.4.1.14.1.4.1 openssl/crypto/engine/eng_all.c:1.6.6.2 --- openssl/crypto/engine/eng_all.c:1.5.2.1.4.1.14.1.4.1 Mon Jun 13 15:41:32 2016 +++ openssl/crypto/engine/eng_all.c Mon Jun 13 15:51:59 2016 @@ -119,6 +119,14 @@ # if defined(OPENSSL_SYS_WIN32) && !defined(OPENSSL_NO_CAPIENG) ENGINE_load_capi(); # endif +#ifndef OPENSSL_NO_HW_PKCS11 +#ifndef OPENSSL_NO_HW_PKCS11CA + ENGINE_load_pk11ca(); +#endif +#ifndef OPENSSL_NO_HW_PKCS11SO + ENGINE_load_pk11so(); +#endif +#endif #endif ENGINE_register_all_complete(); } Index: openssl/crypto/engine/engine.h diff -u openssl/crypto/engine/engine.h:1.5.2.1.4.1.14.1 openssl/crypto/engine/engine.h:1.6.6.1 --- openssl/crypto/engine/engine.h:1.5.2.1.4.1.14.1 Wed Mar 4 14:43:55 2015 +++ openssl/crypto/engine/engine.h Wed Mar 4 15:22:32 2015 @@ -405,6 +405,12 @@ void ENGINE_load_ubsec(void); void ENGINE_load_padlock(void); void ENGINE_load_capi(void); +#ifndef OPENSSL_NO_HW_PKCS11CA +void ENGINE_load_pk11ca(void); +#endif +#ifndef OPENSSL_NO_HW_PKCS11SO +void ENGINE_load_pk11so(void); +#endif # ifndef OPENSSL_NO_GMP void ENGINE_load_gmp(void); # endif Index: openssl/crypto/engine/hw_pk11.c diff -u /dev/null openssl/crypto/engine/hw_pk11.c:1.33 --- /dev/null Mon Jun 13 15:55:25 2016 +++ openssl/crypto/engine/hw_pk11.c Fri Oct 4 14:07:41 2013 @@ -0,0 +1,4010 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* crypto/engine/hw_pk11.c */ +/* + * This product includes software developed by the OpenSSL Project for + * use in the OpenSSL Toolkit (http://www.openssl.org/). + * + * This project also referenced hw_pkcs11-0.9.7b.patch written by + * Afchine Madjlessi. + */ +/* + * ==================================================================== + * Copyright (c) 2000-2001 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifndef OPENSSL_NO_RSA +#include +#endif +#ifndef OPENSSL_NO_DSA +#include +#endif +#ifndef OPENSSL_NO_DH +#include +#endif +#include +#include +#include +#include +#include + +#ifdef OPENSSL_SYS_WIN32 +typedef int pid_t; +#define getpid() GetCurrentProcessId() +#define NOPTHREADS +#ifndef NULL_PTR +#define NULL_PTR NULL +#endif +#define CK_DEFINE_FUNCTION(returnType, name) \ + returnType __declspec(dllexport) name +#define CK_DECLARE_FUNCTION(returnType, name) \ + returnType __declspec(dllimport) name +#define CK_DECLARE_FUNCTION_POINTER(returnType, name) \ + returnType __declspec(dllimport) (* name) +#else +#include +#include +#include +#endif + +/* Debug mutexes */ +/*#undef DEBUG_MUTEX */ +#define DEBUG_MUTEX + +#ifndef NOPTHREADS +/* for pthread error check on Linuxes */ +#ifdef DEBUG_MUTEX +#define __USE_UNIX98 +#endif +#include +#endif + +#ifndef OPENSSL_NO_HW +#ifndef OPENSSL_NO_HW_PK11 +#ifndef OPENSSL_NO_HW_PK11CA + +/* label for debug messages printed on stderr */ +#define PK11_DBG "PKCS#11 ENGINE DEBUG" +/* prints a lot of debug messages on stderr about slot selection process */ +/* #undef DEBUG_SLOT_SELECTION */ +/* + * Solaris specific code. See comment at check_hw_mechanisms() for more + * information. + */ +#if defined(__SVR4) && defined(__sun) +#undef SOLARIS_HW_SLOT_SELECTION +#endif + +#ifdef OPENSSL_SYS_WIN32 +#pragma pack(push, cryptoki, 1) +#include "cryptoki.h" +#include "pkcs11.h" +#pragma pack(pop, cryptoki) +#else +#include "cryptoki.h" +#include "pkcs11.h" +#endif +#include "hw_pk11ca.h" +#include "hw_pk11_err.c" + +/* + * We use this lock to prevent multiple C_Login()s, guard getpassphrase(), + * uri_struct manipulation, and static token info. All of that is used by the + * RSA keys by reference feature. + */ +#ifndef NOPTHREADS +pthread_mutex_t *token_lock; +#endif + +#ifdef SOLARIS_HW_SLOT_SELECTION +/* + * Tables for symmetric ciphers and digest mechs found in the pkcs11_kernel + * library. See comment at check_hw_mechanisms() for more information. + */ +static int *hw_cnids; +static int *hw_dnids; +#endif /* SOLARIS_HW_SLOT_SELECTION */ + +/* PKCS#11 session caches and their locks for all operation types */ +static PK11_CACHE session_cache[OP_MAX]; + +/* + * We cache the flags so that we do not have to run C_GetTokenInfo() again when + * logging into the token. + */ +CK_FLAGS pubkey_token_flags; + +/* + * As stated in v2.20, 11.7 Object Management Function, in section for + * C_FindObjectsInit(), at most one search operation may be active at a given + * time in a given session. Therefore, C_Find{,Init,Final}Objects() should be + * grouped together to form one atomic search operation. This is already + * ensured by the property of unique PKCS#11 session handle used for each + * PK11_SESSION object. + * + * This is however not the biggest concern - maintaining consistency of the + * underlying object store is more important. The same section of the spec also + * says that one thread can be in the middle of a search operation while another + * thread destroys the object matching the search template which would result in + * invalid handle returned from the search operation. + * + * Hence, the following locks are used for both protection of the object stores. + * They are also used for active list protection. + */ +#ifndef NOPTHREADS +pthread_mutex_t *find_lock[OP_MAX] = { NULL }; +#endif + +/* + * lists of asymmetric key handles which are active (referenced by at least one + * PK11_SESSION structure, either held by a thread or present in free_session + * list) for given algorithm type + */ +PK11_active *active_list[OP_MAX] = { NULL }; + +/* + * Create all secret key objects in a global session so that they are available + * to use for other sessions. These other sessions may be opened or closed + * without losing the secret key objects. + */ +static CK_SESSION_HANDLE global_session = CK_INVALID_HANDLE; + +/* ENGINE level stuff */ +static int pk11_init(ENGINE *e); +static int pk11_library_init(ENGINE *e); +static int pk11_finish(ENGINE *e); +static int pk11_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void)); +static int pk11_destroy(ENGINE *e); + +/* RAND stuff */ +static void pk11_rand_seed(const void *buf, int num); +static void pk11_rand_add(const void *buf, int num, double add_entropy); +static void pk11_rand_cleanup(void); +static int pk11_rand_bytes(unsigned char *buf, int num); +static int pk11_rand_status(void); + +/* These functions are also used in other files */ +PK11_SESSION *pk11_get_session(PK11_OPTYPE optype); +void pk11_return_session(PK11_SESSION *sp, PK11_OPTYPE optype); + +/* active list manipulation functions used in this file */ +extern int pk11_active_delete(CK_OBJECT_HANDLE h, PK11_OPTYPE type); +extern void pk11_free_active_list(PK11_OPTYPE type); + +#ifndef OPENSSL_NO_RSA +int pk11_destroy_rsa_key_objects(PK11_SESSION *session); +int pk11_destroy_rsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock); +int pk11_destroy_rsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock); +#endif +#ifndef OPENSSL_NO_DSA +int pk11_destroy_dsa_key_objects(PK11_SESSION *session); +int pk11_destroy_dsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock); +int pk11_destroy_dsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock); +#endif +#ifndef OPENSSL_NO_DH +int pk11_destroy_dh_key_objects(PK11_SESSION *session); +int pk11_destroy_dh_object(PK11_SESSION *session, CK_BBOOL uselock); +#endif + +/* Local helper functions */ +static int pk11_free_all_sessions(void); +static int pk11_free_session_list(PK11_OPTYPE optype); +static int pk11_setup_session(PK11_SESSION *sp, PK11_OPTYPE optype); +static int pk11_destroy_cipher_key_objects(PK11_SESSION *session); +static int pk11_destroy_object(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE oh, + CK_BBOOL persistent); +static const char *get_PK11_LIBNAME(void); +static void free_PK11_LIBNAME(void); +static long set_PK11_LIBNAME(const char *name); + +/* Symmetric cipher and digest support functions */ +static int cipher_nid_to_pk11(int nid); +static int pk11_usable_ciphers(const int **nids); +static int pk11_usable_digests(const int **nids); +static int pk11_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc); +static int pk11_cipher_final(PK11_SESSION *sp); +#if OPENSSL_VERSION_NUMBER < 0x10000000L +static int pk11_cipher_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, unsigned int inl); +#else +static int pk11_cipher_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t inl); +#endif +static int pk11_cipher_cleanup(EVP_CIPHER_CTX *ctx); +static int pk11_engine_ciphers(ENGINE *e, const EVP_CIPHER **cipher, + const int **nids, int nid); +static int pk11_engine_digests(ENGINE *e, const EVP_MD **digest, + const int **nids, int nid); +static CK_OBJECT_HANDLE pk11_get_cipher_key(EVP_CIPHER_CTX *ctx, + const unsigned char *key, CK_KEY_TYPE key_type, PK11_SESSION *sp); +static int check_new_cipher_key(PK11_SESSION *sp, const unsigned char *key, + int key_len); +static int md_nid_to_pk11(int nid); +static int pk11_digest_init(EVP_MD_CTX *ctx); +static int pk11_digest_update(EVP_MD_CTX *ctx, const void *data, + size_t count); +static int pk11_digest_final(EVP_MD_CTX *ctx, unsigned char *md); +static int pk11_digest_copy(EVP_MD_CTX *to, const EVP_MD_CTX *from); +static int pk11_digest_cleanup(EVP_MD_CTX *ctx); + +static int pk11_choose_slots(int *any_slot_found); +static void pk11_find_symmetric_ciphers(CK_FUNCTION_LIST_PTR pflist, + CK_SLOT_ID current_slot, int *current_slot_n_cipher, + int *local_cipher_nids); +static void pk11_find_digests(CK_FUNCTION_LIST_PTR pflist, + CK_SLOT_ID current_slot, int *current_slot_n_digest, + int *local_digest_nids); +static void pk11_get_symmetric_cipher(CK_FUNCTION_LIST_PTR, int slot_id, + CK_MECHANISM_TYPE mech, int *current_slot_n_cipher, int *local_cipher_nids, + int id); +static void pk11_get_digest(CK_FUNCTION_LIST_PTR pflist, int slot_id, + CK_MECHANISM_TYPE mech, int *current_slot_n_digest, int *local_digest_nids, + int id); + +static int pk11_init_all_locks(void); +static void pk11_free_all_locks(void); + +#ifdef SOLARIS_HW_SLOT_SELECTION +static int check_hw_mechanisms(void); +static int nid_in_table(int nid, int *nid_table); +#endif /* SOLARIS_HW_SLOT_SELECTION */ + +/* Index for the supported ciphers */ +enum pk11_cipher_id { + PK11_DES_CBC, + PK11_DES3_CBC, + PK11_DES_ECB, + PK11_DES3_ECB, + PK11_RC4, + PK11_AES_128_CBC, + PK11_AES_192_CBC, + PK11_AES_256_CBC, + PK11_AES_128_ECB, + PK11_AES_192_ECB, + PK11_AES_256_ECB, + PK11_AES_128_CTR, + PK11_AES_192_CTR, + PK11_AES_256_CTR, + PK11_BLOWFISH_CBC, + PK11_CIPHER_MAX +}; + +/* Index for the supported digests */ +enum pk11_digest_id { + PK11_MD5, + PK11_SHA1, + PK11_SHA224, + PK11_SHA256, + PK11_SHA384, + PK11_SHA512, + PK11_DIGEST_MAX +}; + +#define TRY_OBJ_DESTROY(sp, obj_hdl, retval, uselock, alg_type, priv) \ + { \ + if (uselock) \ + LOCK_OBJSTORE(alg_type); \ + if (pk11_active_delete(obj_hdl, alg_type) == 1) \ + { \ + retval = pk11_destroy_object(sp->session, obj_hdl, \ + priv ? sp->priv_persistent : sp->pub_persistent); \ + } \ + if (uselock) \ + UNLOCK_OBJSTORE(alg_type); \ + } + +static int cipher_nids[PK11_CIPHER_MAX]; +static int digest_nids[PK11_DIGEST_MAX]; +static int cipher_count = 0; +static int digest_count = 0; +static CK_BBOOL pk11_have_rsa = CK_FALSE; +static CK_BBOOL pk11_have_recover = CK_FALSE; +static CK_BBOOL pk11_have_dsa = CK_FALSE; +static CK_BBOOL pk11_have_dh = CK_FALSE; +static CK_BBOOL pk11_have_random = CK_FALSE; + +typedef struct PK11_CIPHER_st + { + enum pk11_cipher_id id; + int nid; + int iv_len; + int min_key_len; + int max_key_len; + CK_KEY_TYPE key_type; + CK_MECHANISM_TYPE mech_type; + } PK11_CIPHER; + +static PK11_CIPHER ciphers[] = + { + { PK11_DES_CBC, NID_des_cbc, 8, 8, 8, + CKK_DES, CKM_DES_CBC, }, + { PK11_DES3_CBC, NID_des_ede3_cbc, 8, 24, 24, + CKK_DES3, CKM_DES3_CBC, }, + { PK11_DES_ECB, NID_des_ecb, 0, 8, 8, + CKK_DES, CKM_DES_ECB, }, + { PK11_DES3_ECB, NID_des_ede3_ecb, 0, 24, 24, + CKK_DES3, CKM_DES3_ECB, }, + { PK11_RC4, NID_rc4, 0, 16, 256, + CKK_RC4, CKM_RC4, }, + { PK11_AES_128_CBC, NID_aes_128_cbc, 16, 16, 16, + CKK_AES, CKM_AES_CBC, }, + { PK11_AES_192_CBC, NID_aes_192_cbc, 16, 24, 24, + CKK_AES, CKM_AES_CBC, }, + { PK11_AES_256_CBC, NID_aes_256_cbc, 16, 32, 32, + CKK_AES, CKM_AES_CBC, }, + { PK11_AES_128_ECB, NID_aes_128_ecb, 0, 16, 16, + CKK_AES, CKM_AES_ECB, }, + { PK11_AES_192_ECB, NID_aes_192_ecb, 0, 24, 24, + CKK_AES, CKM_AES_ECB, }, + { PK11_AES_256_ECB, NID_aes_256_ecb, 0, 32, 32, + CKK_AES, CKM_AES_ECB, }, + { PK11_AES_128_CTR, NID_aes_128_ctr, 16, 16, 16, + CKK_AES, CKM_AES_CTR, }, + { PK11_AES_192_CTR, NID_aes_192_ctr, 16, 24, 24, + CKK_AES, CKM_AES_CTR, }, + { PK11_AES_256_CTR, NID_aes_256_ctr, 16, 32, 32, + CKK_AES, CKM_AES_CTR, }, + { PK11_BLOWFISH_CBC, NID_bf_cbc, 8, 16, 16, + CKK_BLOWFISH, CKM_BLOWFISH_CBC, }, + }; + +typedef struct PK11_DIGEST_st + { + enum pk11_digest_id id; + int nid; + CK_MECHANISM_TYPE mech_type; + } PK11_DIGEST; + +static PK11_DIGEST digests[] = + { + {PK11_MD5, NID_md5, CKM_MD5, }, + {PK11_SHA1, NID_sha1, CKM_SHA_1, }, + {PK11_SHA224, NID_sha224, CKM_SHA224, }, + {PK11_SHA256, NID_sha256, CKM_SHA256, }, + {PK11_SHA384, NID_sha384, CKM_SHA384, }, + {PK11_SHA512, NID_sha512, CKM_SHA512, }, + {0, NID_undef, 0xFFFF, }, + }; + +/* + * Structure to be used for the cipher_data/md_data in + * EVP_CIPHER_CTX/EVP_MD_CTX structures in order to use the same pk11 + * session in multiple cipher_update calls + */ +typedef struct PK11_CIPHER_STATE_st + { + PK11_SESSION *sp; + } PK11_CIPHER_STATE; + + +/* + * libcrypto EVP stuff - this is how we get wired to EVP so the engine gets + * called when libcrypto requests a cipher NID. + * + * Note how the PK11_CIPHER_STATE is used here. + */ + +/* DES CBC EVP */ +static const EVP_CIPHER pk11_des_cbc = + { + NID_des_cbc, + 8, 8, 8, + EVP_CIPH_CBC_MODE, + pk11_cipher_init, + pk11_cipher_do_cipher, + pk11_cipher_cleanup, + sizeof (PK11_CIPHER_STATE), + EVP_CIPHER_set_asn1_iv, + EVP_CIPHER_get_asn1_iv, + NULL + }; + +/* 3DES CBC EVP */ +static const EVP_CIPHER pk11_3des_cbc = + { + NID_des_ede3_cbc, + 8, 24, 8, + EVP_CIPH_CBC_MODE, + pk11_cipher_init, + pk11_cipher_do_cipher, + pk11_cipher_cleanup, + sizeof (PK11_CIPHER_STATE), + EVP_CIPHER_set_asn1_iv, + EVP_CIPHER_get_asn1_iv, + NULL + }; + +/* + * ECB modes don't use an Initial Vector so that's why set_asn1_parameters and + * get_asn1_parameters fields are set to NULL. + */ +static const EVP_CIPHER pk11_des_ecb = + { + NID_des_ecb, + 8, 8, 8, + EVP_CIPH_ECB_MODE, + pk11_cipher_init, + pk11_cipher_do_cipher, + pk11_cipher_cleanup, + sizeof (PK11_CIPHER_STATE), + NULL, + NULL, + NULL + }; + +static const EVP_CIPHER pk11_3des_ecb = + { + NID_des_ede3_ecb, + 8, 24, 8, + EVP_CIPH_ECB_MODE, + pk11_cipher_init, + pk11_cipher_do_cipher, + pk11_cipher_cleanup, + sizeof (PK11_CIPHER_STATE), + NULL, + NULL, + NULL + }; + + +static const EVP_CIPHER pk11_aes_128_cbc = + { + NID_aes_128_cbc, + 16, 16, 16, + EVP_CIPH_CBC_MODE, + pk11_cipher_init, + pk11_cipher_do_cipher, + pk11_cipher_cleanup, + sizeof (PK11_CIPHER_STATE), + EVP_CIPHER_set_asn1_iv, + EVP_CIPHER_get_asn1_iv, + NULL + }; + +static const EVP_CIPHER pk11_aes_192_cbc = + { + NID_aes_192_cbc, + 16, 24, 16, + EVP_CIPH_CBC_MODE, + pk11_cipher_init, + pk11_cipher_do_cipher, + pk11_cipher_cleanup, + sizeof (PK11_CIPHER_STATE), + EVP_CIPHER_set_asn1_iv, + EVP_CIPHER_get_asn1_iv, + NULL + }; + +static const EVP_CIPHER pk11_aes_256_cbc = + { + NID_aes_256_cbc, + 16, 32, 16, + EVP_CIPH_CBC_MODE, + pk11_cipher_init, + pk11_cipher_do_cipher, + pk11_cipher_cleanup, + sizeof (PK11_CIPHER_STATE), + EVP_CIPHER_set_asn1_iv, + EVP_CIPHER_get_asn1_iv, + NULL + }; + +/* + * ECB modes don't use IV so that's why set_asn1_parameters and + * get_asn1_parameters are set to NULL. + */ +static const EVP_CIPHER pk11_aes_128_ecb = + { + NID_aes_128_ecb, + 16, 16, 0, + EVP_CIPH_ECB_MODE, + pk11_cipher_init, + pk11_cipher_do_cipher, + pk11_cipher_cleanup, + sizeof (PK11_CIPHER_STATE), + NULL, + NULL, + NULL + }; + +static const EVP_CIPHER pk11_aes_192_ecb = + { + NID_aes_192_ecb, + 16, 24, 0, + EVP_CIPH_ECB_MODE, + pk11_cipher_init, + pk11_cipher_do_cipher, + pk11_cipher_cleanup, + sizeof (PK11_CIPHER_STATE), + NULL, + NULL, + NULL + }; + +static const EVP_CIPHER pk11_aes_256_ecb = + { + NID_aes_256_ecb, + 16, 32, 0, + EVP_CIPH_ECB_MODE, + pk11_cipher_init, + pk11_cipher_do_cipher, + pk11_cipher_cleanup, + sizeof (PK11_CIPHER_STATE), + NULL, + NULL, + NULL + }; + +static const EVP_CIPHER pk11_aes_128_ctr = + { + NID_aes_128_ctr, + 16, 16, 16, + EVP_CIPH_CBC_MODE, + pk11_cipher_init, + pk11_cipher_do_cipher, + pk11_cipher_cleanup, + sizeof (PK11_CIPHER_STATE), + EVP_CIPHER_set_asn1_iv, + EVP_CIPHER_get_asn1_iv, + NULL + }; + +static const EVP_CIPHER pk11_aes_192_ctr = + { + NID_aes_192_ctr, + 16, 24, 16, + EVP_CIPH_CBC_MODE, + pk11_cipher_init, + pk11_cipher_do_cipher, + pk11_cipher_cleanup, + sizeof (PK11_CIPHER_STATE), + EVP_CIPHER_set_asn1_iv, + EVP_CIPHER_get_asn1_iv, + NULL + }; + +static const EVP_CIPHER pk11_aes_256_ctr = + { + NID_aes_256_ctr, + 16, 32, 16, + EVP_CIPH_CBC_MODE, + pk11_cipher_init, + pk11_cipher_do_cipher, + pk11_cipher_cleanup, + sizeof (PK11_CIPHER_STATE), + EVP_CIPHER_set_asn1_iv, + EVP_CIPHER_get_asn1_iv, + NULL + }; + +static const EVP_CIPHER pk11_bf_cbc = + { + NID_bf_cbc, + 8, 16, 8, + EVP_CIPH_VARIABLE_LENGTH, + pk11_cipher_init, + pk11_cipher_do_cipher, + pk11_cipher_cleanup, + sizeof (PK11_CIPHER_STATE), + EVP_CIPHER_set_asn1_iv, + EVP_CIPHER_get_asn1_iv, + NULL + }; + +static const EVP_CIPHER pk11_rc4 = + { + NID_rc4, + 1, 16, 0, + EVP_CIPH_VARIABLE_LENGTH, + pk11_cipher_init, + pk11_cipher_do_cipher, + pk11_cipher_cleanup, + sizeof (PK11_CIPHER_STATE), + NULL, + NULL, + NULL + }; + +static const EVP_MD pk11_md5 = + { + NID_md5, + NID_md5WithRSAEncryption, + MD5_DIGEST_LENGTH, + 0, + pk11_digest_init, + pk11_digest_update, + pk11_digest_final, + pk11_digest_copy, + pk11_digest_cleanup, + EVP_PKEY_RSA_method, + MD5_CBLOCK, + sizeof (PK11_CIPHER_STATE), + }; + +static const EVP_MD pk11_sha1 = + { + NID_sha1, + NID_sha1WithRSAEncryption, + SHA_DIGEST_LENGTH, + EVP_MD_FLAG_PKEY_METHOD_SIGNATURE|EVP_MD_FLAG_DIGALGID_ABSENT, + pk11_digest_init, + pk11_digest_update, + pk11_digest_final, + pk11_digest_copy, + pk11_digest_cleanup, + EVP_PKEY_RSA_method, + SHA_CBLOCK, + sizeof (PK11_CIPHER_STATE), + }; + +static const EVP_MD pk11_sha224 = + { + NID_sha224, + NID_sha224WithRSAEncryption, + SHA224_DIGEST_LENGTH, + EVP_MD_FLAG_PKEY_METHOD_SIGNATURE|EVP_MD_FLAG_DIGALGID_ABSENT, + pk11_digest_init, + pk11_digest_update, + pk11_digest_final, + pk11_digest_copy, + pk11_digest_cleanup, + EVP_PKEY_RSA_method, + /* SHA-224 uses the same cblock size as SHA-256 */ + SHA256_CBLOCK, + sizeof (PK11_CIPHER_STATE), + }; + +static const EVP_MD pk11_sha256 = + { + NID_sha256, + NID_sha256WithRSAEncryption, + SHA256_DIGEST_LENGTH, + EVP_MD_FLAG_PKEY_METHOD_SIGNATURE|EVP_MD_FLAG_DIGALGID_ABSENT, + pk11_digest_init, + pk11_digest_update, + pk11_digest_final, + pk11_digest_copy, + pk11_digest_cleanup, + EVP_PKEY_RSA_method, + SHA256_CBLOCK, + sizeof (PK11_CIPHER_STATE), + }; + +static const EVP_MD pk11_sha384 = + { + NID_sha384, + NID_sha384WithRSAEncryption, + SHA384_DIGEST_LENGTH, + EVP_MD_FLAG_PKEY_METHOD_SIGNATURE|EVP_MD_FLAG_DIGALGID_ABSENT, + pk11_digest_init, + pk11_digest_update, + pk11_digest_final, + pk11_digest_copy, + pk11_digest_cleanup, + EVP_PKEY_RSA_method, + /* SHA-384 uses the same cblock size as SHA-512 */ + SHA512_CBLOCK, + sizeof (PK11_CIPHER_STATE), + }; + +static const EVP_MD pk11_sha512 = + { + NID_sha512, + NID_sha512WithRSAEncryption, + SHA512_DIGEST_LENGTH, + EVP_MD_FLAG_PKEY_METHOD_SIGNATURE|EVP_MD_FLAG_DIGALGID_ABSENT, + pk11_digest_init, + pk11_digest_update, + pk11_digest_final, + pk11_digest_copy, + pk11_digest_cleanup, + EVP_PKEY_RSA_method, + SHA512_CBLOCK, + sizeof (PK11_CIPHER_STATE), + }; + +/* + * Initialization function. Sets up various PKCS#11 library components. + * The definitions for control commands specific to this engine + */ +#define PK11_CMD_SO_PATH ENGINE_CMD_BASE +#define PK11_CMD_PIN (ENGINE_CMD_BASE+1) +#define PK11_CMD_SLOT (ENGINE_CMD_BASE+2) +static const ENGINE_CMD_DEFN pk11_cmd_defns[] = + { + { + PK11_CMD_SO_PATH, + "SO_PATH", + "Specifies the path to the 'pkcs#11' shared library", + ENGINE_CMD_FLAG_STRING + }, + { + PK11_CMD_PIN, + "PIN", + "Specifies the pin code", + ENGINE_CMD_FLAG_STRING + }, + { + PK11_CMD_SLOT, + "SLOT", + "Specifies the slot (default is auto select)", + ENGINE_CMD_FLAG_NUMERIC, + }, + {0, NULL, NULL, 0} + }; + + +static RAND_METHOD pk11_random = + { + pk11_rand_seed, + pk11_rand_bytes, + pk11_rand_cleanup, + pk11_rand_add, + pk11_rand_bytes, + pk11_rand_status + }; + + +/* Constants used when creating the ENGINE */ +#ifdef OPENSSL_NO_HW_PK11SO +#error "can't load both crypto-accelerator and sign-only PKCS#11 engines" +#endif +static const char *engine_pk11_id = "pkcs11"; +static const char *engine_pk11_name = + "PKCS #11 engine support (crypto accelerator)"; + +CK_FUNCTION_LIST_PTR pFuncList = NULL; +static const char PK11_GET_FUNCTION_LIST[] = "C_GetFunctionList"; + +/* + * This is a static string constant for the DSO file name and the function + * symbol names to bind to. We set it in the Configure script based on whether + * this is 32 or 64 bit build. + */ +static const char def_PK11_LIBNAME[] = PK11_LIB_LOCATION; + +static CK_BBOOL mytrue = TRUE; +static CK_BBOOL myfalse = FALSE; +/* Needed in hw_pk11_pub.c as well so that's why it is not static. */ +CK_SLOT_ID pubkey_SLOTID = 0; +static CK_SLOT_ID rand_SLOTID = 0; +static CK_SLOT_ID SLOTID = 0; +char *pk11_pin = NULL; +static CK_BBOOL pk11_library_initialized = FALSE; +static CK_BBOOL pk11_atfork_initialized = FALSE; +static int pk11_pid = 0; + +static DSO *pk11_dso = NULL; + +/* allocate and initialize all locks used by the engine itself */ +static int pk11_init_all_locks(void) + { +#ifndef NOPTHREADS + int type; + pthread_mutexattr_t attr; + + if (pthread_mutexattr_init(&attr) != 0) + { + PK11err(PK11_F_INIT_ALL_LOCKS, 100); + return (0); + } + +#ifdef DEBUG_MUTEX + if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK) != 0) + { + PK11err(PK11_F_INIT_ALL_LOCKS, 101); + return (0); + } +#endif + + if ((token_lock = OPENSSL_malloc(sizeof (pthread_mutex_t))) == NULL) + goto malloc_err; + (void) pthread_mutex_init(token_lock, &attr); + +#ifndef OPENSSL_NO_RSA + find_lock[OP_RSA] = OPENSSL_malloc(sizeof (pthread_mutex_t)); + if (find_lock[OP_RSA] == NULL) + goto malloc_err; + (void) pthread_mutex_init(find_lock[OP_RSA], &attr); +#endif /* OPENSSL_NO_RSA */ + +#ifndef OPENSSL_NO_DSA + find_lock[OP_DSA] = OPENSSL_malloc(sizeof (pthread_mutex_t)); + if (find_lock[OP_DSA] == NULL) + goto malloc_err; + (void) pthread_mutex_init(find_lock[OP_DSA], &attr); +#endif /* OPENSSL_NO_DSA */ + +#ifndef OPENSSL_NO_DH + find_lock[OP_DH] = OPENSSL_malloc(sizeof (pthread_mutex_t)); + if (find_lock[OP_DH] == NULL) + goto malloc_err; + (void) pthread_mutex_init(find_lock[OP_DH], &attr); +#endif /* OPENSSL_NO_DH */ + + for (type = 0; type < OP_MAX; type++) + { + session_cache[type].lock = + OPENSSL_malloc(sizeof (pthread_mutex_t)); + if (session_cache[type].lock == NULL) + goto malloc_err; + (void) pthread_mutex_init(session_cache[type].lock, &attr); + } + + return (1); + +malloc_err: + pk11_free_all_locks(); + PK11err(PK11_F_INIT_ALL_LOCKS, PK11_R_MALLOC_FAILURE); + return (0); +#else + return (1); +#endif + } + +static void pk11_free_all_locks(void) + { +#ifndef NOPTHREADS + int type; + + if (token_lock != NULL) + { + (void) pthread_mutex_destroy(token_lock); + OPENSSL_free(token_lock); + token_lock = NULL; + } + +#ifndef OPENSSL_NO_RSA + if (find_lock[OP_RSA] != NULL) + { + (void) pthread_mutex_destroy(find_lock[OP_RSA]); + OPENSSL_free(find_lock[OP_RSA]); + find_lock[OP_RSA] = NULL; + } +#endif /* OPENSSL_NO_RSA */ +#ifndef OPENSSL_NO_DSA + if (find_lock[OP_DSA] != NULL) + { + (void) pthread_mutex_destroy(find_lock[OP_DSA]); + OPENSSL_free(find_lock[OP_DSA]); + find_lock[OP_DSA] = NULL; + } +#endif /* OPENSSL_NO_DSA */ +#ifndef OPENSSL_NO_DH + if (find_lock[OP_DH] != NULL) + { + (void) pthread_mutex_destroy(find_lock[OP_DH]); + OPENSSL_free(find_lock[OP_DH]); + find_lock[OP_DH] = NULL; + } +#endif /* OPENSSL_NO_DH */ + + for (type = 0; type < OP_MAX; type++) + { + if (session_cache[type].lock != NULL) + { + (void) pthread_mutex_destroy(session_cache[type].lock); + OPENSSL_free(session_cache[type].lock); + session_cache[type].lock = NULL; + } + } +#endif + } + +/* + * This internal function is used by ENGINE_pk11() and "dynamic" ENGINE support. + */ +static int bind_pk11(ENGINE *e) + { +#ifndef OPENSSL_NO_RSA + const RSA_METHOD *rsa = NULL; + RSA_METHOD *pk11_rsa = PK11_RSA(); +#endif /* OPENSSL_NO_RSA */ + if (!pk11_library_initialized) + if (!pk11_library_init(e)) + return (0); + + if (!ENGINE_set_id(e, engine_pk11_id) || + !ENGINE_set_name(e, engine_pk11_name) || + !ENGINE_set_ciphers(e, pk11_engine_ciphers) || + !ENGINE_set_digests(e, pk11_engine_digests)) + return (0); +#ifndef OPENSSL_NO_RSA + if (pk11_have_rsa == CK_TRUE) + { + if (!ENGINE_set_RSA(e, PK11_RSA()) || + !ENGINE_set_load_privkey_function(e, pk11_load_privkey) || + !ENGINE_set_load_pubkey_function(e, pk11_load_pubkey)) + return (0); +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: registered RSA\n", PK11_DBG); +#endif /* DEBUG_SLOT_SELECTION */ + } +#endif /* OPENSSL_NO_RSA */ +#ifndef OPENSSL_NO_DSA + if (pk11_have_dsa == CK_TRUE) + { + if (!ENGINE_set_DSA(e, PK11_DSA())) + return (0); +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: registered DSA\n", PK11_DBG); +#endif /* DEBUG_SLOT_SELECTION */ + } +#endif /* OPENSSL_NO_DSA */ +#ifndef OPENSSL_NO_DH + if (pk11_have_dh == CK_TRUE) + { + if (!ENGINE_set_DH(e, PK11_DH())) + return (0); +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: registered DH\n", PK11_DBG); +#endif /* DEBUG_SLOT_SELECTION */ + } +#endif /* OPENSSL_NO_DH */ + if (pk11_have_random) + { + if (!ENGINE_set_RAND(e, &pk11_random)) + return (0); +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: registered random\n", PK11_DBG); +#endif /* DEBUG_SLOT_SELECTION */ + } + if (!ENGINE_set_init_function(e, pk11_init) || + !ENGINE_set_destroy_function(e, pk11_destroy) || + !ENGINE_set_finish_function(e, pk11_finish) || + !ENGINE_set_ctrl_function(e, pk11_ctrl) || + !ENGINE_set_cmd_defns(e, pk11_cmd_defns)) + return (0); + +/* + * Apache calls OpenSSL function RSA_blinding_on() once during startup + * which in turn calls bn_mod_exp. Since we do not implement bn_mod_exp + * here, we wire it back to the OpenSSL software implementation. + * Since it is used only once, performance is not a concern. + */ +#ifndef OPENSSL_NO_RSA + rsa = RSA_PKCS1_SSLeay(); + pk11_rsa->rsa_mod_exp = rsa->rsa_mod_exp; + pk11_rsa->bn_mod_exp = rsa->bn_mod_exp; + if (pk11_have_recover != CK_TRUE) + pk11_rsa->rsa_pub_dec = rsa->rsa_pub_dec; +#endif /* OPENSSL_NO_RSA */ + + /* Ensure the pk11 error handling is set up */ + ERR_load_pk11_strings(); + + return (1); + } + +/* Dynamic engine support is disabled at a higher level for Solaris */ +#ifdef ENGINE_DYNAMIC_SUPPORT +#error "dynamic engine not supported" +static int bind_helper(ENGINE *e, const char *id) + { + if (id && (strcmp(id, engine_pk11_id) != 0)) + return (0); + + if (!bind_pk11(e)) + return (0); + + return (1); + } + +IMPLEMENT_DYNAMIC_CHECK_FN() +IMPLEMENT_DYNAMIC_BIND_FN(bind_helper) + +#else +static ENGINE *engine_pk11(void) + { + ENGINE *ret = ENGINE_new(); + + if (!ret) + return (NULL); + + if (!bind_pk11(ret)) + { + ENGINE_free(ret); + return (NULL); + } + + return (ret); + } + +void +ENGINE_load_pk11(void) + { + ENGINE *e_pk11 = NULL; + + /* + * Do not use dynamic PKCS#11 library on Solaris due to + * security reasons. We will link it in statically. + */ + /* Attempt to load PKCS#11 library */ + if (!pk11_dso) + pk11_dso = DSO_load(NULL, get_PK11_LIBNAME(), NULL, 0); + + if (pk11_dso == NULL) + { + PK11err(PK11_F_LOAD, PK11_R_DSO_FAILURE); + return; + } + + e_pk11 = engine_pk11(); + if (!e_pk11) + { + DSO_free(pk11_dso); + pk11_dso = NULL; + return; + } + + /* + * At this point, the pk11 shared library is either dynamically + * loaded or statically linked in. So, initialize the pk11 + * library before calling ENGINE_set_default since the latter + * needs cipher and digest algorithm information + */ + if (!pk11_library_init(e_pk11)) + { + DSO_free(pk11_dso); + pk11_dso = NULL; + ENGINE_free(e_pk11); + return; + } + + ENGINE_add(e_pk11); + + ENGINE_free(e_pk11); + ERR_clear_error(); + } +#endif /* ENGINE_DYNAMIC_SUPPORT */ + +/* + * These are the static string constants for the DSO file name and + * the function symbol names to bind to. + */ +static const char *PK11_LIBNAME = NULL; + +static const char *get_PK11_LIBNAME(void) + { + if (PK11_LIBNAME) + return (PK11_LIBNAME); + + return (def_PK11_LIBNAME); + } + +static void free_PK11_LIBNAME(void) + { + if (PK11_LIBNAME) + OPENSSL_free((void*)PK11_LIBNAME); + + PK11_LIBNAME = NULL; + } + +static long set_PK11_LIBNAME(const char *name) + { + free_PK11_LIBNAME(); + + return ((PK11_LIBNAME = BUF_strdup(name)) != NULL ? 1 : 0); + } + +/* acquire all engine specific mutexes before fork */ +static void pk11_fork_prepare(void) + { +#ifndef NOPTHREADS + int i; + + if (!pk11_library_initialized) + return; + + LOCK_OBJSTORE(OP_RSA); + LOCK_OBJSTORE(OP_DSA); + LOCK_OBJSTORE(OP_DH); + OPENSSL_assert(pthread_mutex_lock(token_lock) == 0); + for (i = 0; i < OP_MAX; i++) + { + OPENSSL_assert(pthread_mutex_lock(session_cache[i].lock) == 0); + } +#endif + } + +/* release all engine specific mutexes */ +static void pk11_fork_parent(void) + { +#ifndef NOPTHREADS + int i; + + if (!pk11_library_initialized) + return; + + for (i = OP_MAX - 1; i >= 0; i--) + { + OPENSSL_assert(pthread_mutex_unlock(session_cache[i].lock) == 0); + } + UNLOCK_OBJSTORE(OP_DH); + UNLOCK_OBJSTORE(OP_DSA); + UNLOCK_OBJSTORE(OP_RSA); + OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0); +#endif + } + +/* + * same situation as in parent - we need to unlock all locks to make them + * accessible to all threads. + */ +static void pk11_fork_child(void) + { +#ifndef NOPTHREADS + int i; + + if (!pk11_library_initialized) + return; + + for (i = OP_MAX - 1; i >= 0; i--) + { + OPENSSL_assert(pthread_mutex_unlock(session_cache[i].lock) == 0); + } + UNLOCK_OBJSTORE(OP_DH); + UNLOCK_OBJSTORE(OP_DSA); + UNLOCK_OBJSTORE(OP_RSA); + OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0); +#endif + } + +/* Initialization function for the pk11 engine */ +static int pk11_init(ENGINE *e) +{ + return (pk11_library_init(e)); +} + +static CK_C_INITIALIZE_ARGS pk11_init_args = + { + NULL_PTR, /* CreateMutex */ + NULL_PTR, /* DestroyMutex */ + NULL_PTR, /* LockMutex */ + NULL_PTR, /* UnlockMutex */ + CKF_OS_LOCKING_OK, /* flags */ + NULL_PTR, /* pReserved */ + }; + +/* + * Initialization function. Sets up various PKCS#11 library components. + * It selects a slot based on predefined critiera. In the process, it also + * count how many ciphers and digests to support. Since the cipher and + * digest information is needed when setting default engine, this function + * needs to be called before calling ENGINE_set_default. + */ +/* ARGSUSED */ +static int pk11_library_init(ENGINE *e) + { + CK_C_GetFunctionList p; + CK_RV rv = CKR_OK; + CK_INFO info; + CK_ULONG ul_state_len; + int any_slot_found; + int i; +#ifndef OPENSSL_SYS_WIN32 + struct sigaction sigint_act, sigterm_act, sighup_act; +#endif + + /* + * pk11_library_initialized is set to 0 in pk11_finish() which + * is called from ENGINE_finish(). However, if there is still + * at least one existing functional reference to the engine + * (see engine(3) for more information), pk11_finish() is + * skipped. For example, this can happen if an application + * forgets to clear one cipher context. In case of a fork() + * when the application is finishing the engine so that it can + * be reinitialized in the child, forgotten functional + * reference causes pk11_library_initialized to stay 1. In + * that case we need the PID check so that we properly + * initialize the engine again. + */ + if (pk11_library_initialized) + { + if (pk11_pid == getpid()) + { + return (1); + } + else + { + global_session = CK_INVALID_HANDLE; + /* + * free the locks first to prevent memory leak in case + * the application calls fork() without finishing the + * engine first. + */ + pk11_free_all_locks(); + } + } + + if (pk11_dso == NULL) + { + PK11err(PK11_F_LIBRARY_INIT, PK11_R_DSO_FAILURE); + goto err; + } + +#ifdef SOLARIS_HW_SLOT_SELECTION + if (check_hw_mechanisms() == 0) + goto err; +#endif /* SOLARIS_HW_SLOT_SELECTION */ + + /* get the C_GetFunctionList function from the loaded library */ + p = (CK_C_GetFunctionList)DSO_bind_func(pk11_dso, + PK11_GET_FUNCTION_LIST); + if (!p) + { + PK11err(PK11_F_LIBRARY_INIT, PK11_R_DSO_FAILURE); + goto err; + } + + /* get the full function list from the loaded library */ + rv = p(&pFuncList); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_LIBRARY_INIT, PK11_R_DSO_FAILURE, rv); + goto err; + } + +#ifndef OPENSSL_SYS_WIN32 + /* Not all PKCS#11 library are signal safe! */ + + (void) memset(&sigint_act, 0, sizeof(sigint_act)); + (void) memset(&sigterm_act, 0, sizeof(sigterm_act)); + (void) memset(&sighup_act, 0, sizeof(sighup_act)); + (void) sigaction(SIGINT, NULL, &sigint_act); + (void) sigaction(SIGTERM, NULL, &sigterm_act); + (void) sigaction(SIGHUP, NULL, &sighup_act); +#endif + rv = pFuncList->C_Initialize((CK_VOID_PTR)&pk11_init_args); +#ifndef OPENSSL_SYS_WIN32 + (void) sigaction(SIGINT, &sigint_act, NULL); + (void) sigaction(SIGTERM, &sigterm_act, NULL); + (void) sigaction(SIGHUP, &sighup_act, NULL); +#endif + if ((rv != CKR_OK) && (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)) + { + PK11err_add_data(PK11_F_LIBRARY_INIT, PK11_R_INITIALIZE, rv); + goto err; + } + + rv = pFuncList->C_GetInfo(&info); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_LIBRARY_INIT, PK11_R_GETINFO, rv); + goto err; + } + + if (pk11_choose_slots(&any_slot_found) == 0) + goto err; + + /* + * The library we use, set in def_PK11_LIBNAME, may not offer any + * slot(s). In that case, we must not proceed but we must not return an + * error. The reason is that applications that try to set up the PKCS#11 + * engine don't exit on error during the engine initialization just + * because no slot was present. + */ + if (any_slot_found == 0) + return (1); + + if (global_session == CK_INVALID_HANDLE) + { + /* Open the global_session for the new process */ + rv = pFuncList->C_OpenSession(SLOTID, CKF_SERIAL_SESSION, + NULL_PTR, NULL_PTR, &global_session); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_LIBRARY_INIT, + PK11_R_OPENSESSION, rv); + goto err; + } + } + + /* + * Disable digest if C_GetOperationState is not supported since + * this function is required by OpenSSL digest copy function + */ + /* Keyper fails to return CKR_FUNCTION_NOT_SUPPORTED */ + if (pFuncList->C_GetOperationState(global_session, NULL, &ul_state_len) + != CKR_OK) { +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: C_GetOperationState() not supported, " + "setting digest_count to 0\n", PK11_DBG); +#endif /* DEBUG_SLOT_SELECTION */ + digest_count = 0; + } + + pk11_library_initialized = TRUE; + pk11_pid = getpid(); + /* + * if initialization of the locks fails pk11_init_all_locks() + * will do the cleanup. + */ + if (!pk11_init_all_locks()) + goto err; + for (i = 0; i < OP_MAX; i++) + session_cache[i].head = NULL; + /* + * initialize active lists. We only use active lists + * for asymmetric ciphers. + */ + for (i = 0; i < OP_MAX; i++) + active_list[i] = NULL; + +#ifndef NOPTHREADS + if (!pk11_atfork_initialized) + { + if (pthread_atfork(pk11_fork_prepare, pk11_fork_parent, + pk11_fork_child) != 0) + { + PK11err(PK11_F_LIBRARY_INIT, PK11_R_ATFORK_FAILED); + goto err; + } + pk11_atfork_initialized = TRUE; + } +#endif + + return (1); + +err: + return (0); + } + +/* Destructor (complements the "ENGINE_pk11()" constructor) */ +/* ARGSUSED */ +static int pk11_destroy(ENGINE *e) + { + free_PK11_LIBNAME(); + ERR_unload_pk11_strings(); + if (pk11_pin) { + memset(pk11_pin, 0, strlen(pk11_pin)); + OPENSSL_free((void*)pk11_pin); + } + pk11_pin = NULL; + return (1); + } + +/* + * Termination function to clean up the session, the token, and the pk11 + * library. + */ +/* ARGSUSED */ +static int pk11_finish(ENGINE *e) + { + int i; + + if (pk11_pin) { + memset(pk11_pin, 0, strlen(pk11_pin)); + OPENSSL_free((void*)pk11_pin); + } + pk11_pin = NULL; + + if (pk11_dso == NULL) + { + PK11err(PK11_F_FINISH, PK11_R_NOT_LOADED); + goto err; + } + + OPENSSL_assert(pFuncList != NULL); + + if (pk11_free_all_sessions() == 0) + goto err; + + /* free all active lists */ + for (i = 0; i < OP_MAX; i++) + pk11_free_active_list(i); + + pFuncList->C_CloseSession(global_session); + global_session = CK_INVALID_HANDLE; + + /* + * Since we are part of a library (libcrypto.so), calling this function + * may have side-effects. + */ +#if 0 + pFuncList->C_Finalize(NULL); +#endif + + if (!DSO_free(pk11_dso)) + { + PK11err(PK11_F_FINISH, PK11_R_DSO_FAILURE); + goto err; + } + pk11_dso = NULL; + pFuncList = NULL; + pk11_library_initialized = FALSE; + pk11_pid = 0; + /* + * There is no way how to unregister atfork handlers (other than + * unloading the library) so we just free the locks. For this reason + * the atfork handlers check if the engine is initialized and bail out + * immediately if not. This is necessary in case a process finishes + * the engine before calling fork(). + */ + pk11_free_all_locks(); + + return (1); + +err: + return (0); + } + +/* Standard engine interface function to set the dynamic library path */ +/* ARGSUSED */ +static int pk11_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void)) + { + int initialized = ((pk11_dso == NULL) ? 0 : 1); + + switch (cmd) + { + case PK11_CMD_SO_PATH: + if (p == NULL) + { + PK11err(PK11_F_CTRL, ERR_R_PASSED_NULL_PARAMETER); + return (0); + } + + if (initialized) + { + PK11err(PK11_F_CTRL, PK11_R_ALREADY_LOADED); + return (0); + } + + return (set_PK11_LIBNAME((const char *)p)); + case PK11_CMD_PIN: + if (pk11_pin) { + memset(pk11_pin, 0, strlen(pk11_pin)); + OPENSSL_free((void*)pk11_pin); + } + pk11_pin = NULL; + + if (p == NULL) + { + PK11err(PK11_F_CTRL, ERR_R_PASSED_NULL_PARAMETER); + return (0); + } + + pk11_pin = BUF_strdup(p); + if (pk11_pin == NULL) + { + PK11err(PK11_F_GET_SESSION, PK11_R_MALLOC_FAILURE); + return (0); + } + return (1); + case PK11_CMD_SLOT: + SLOTID = (CK_SLOT_ID)i; +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: slot set\n", PK11_DBG); +#endif + return (1); + default: + break; + } + + PK11err(PK11_F_CTRL, PK11_R_CTRL_COMMAND_NOT_IMPLEMENTED); + + return (0); + } + + +/* Required function by the engine random interface. It does nothing here */ +static void pk11_rand_cleanup(void) + { + return; + } + +/* ARGSUSED */ +static void pk11_rand_add(const void *buf, int num, double add) + { + PK11_SESSION *sp; + + if ((sp = pk11_get_session(OP_RAND)) == NULL) + return; + + /* + * Ignore any errors (e.g. CKR_RANDOM_SEED_NOT_SUPPORTED) since + * the calling functions do not care anyway + */ + pFuncList->C_SeedRandom(sp->session, (unsigned char *) buf, num); + pk11_return_session(sp, OP_RAND); + + return; + } + +static void pk11_rand_seed(const void *buf, int num) + { + pk11_rand_add(buf, num, 0); + } + +static int pk11_rand_bytes(unsigned char *buf, int num) + { + CK_RV rv; + PK11_SESSION *sp; + + if ((sp = pk11_get_session(OP_RAND)) == NULL) + return (0); + + rv = pFuncList->C_GenerateRandom(sp->session, buf, num); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_RAND_BYTES, PK11_R_GENERATERANDOM, rv); + pk11_return_session(sp, OP_RAND); + return (0); + } + + pk11_return_session(sp, OP_RAND); + return (1); + } + +/* Required function by the engine random interface. It does nothing here */ +static int pk11_rand_status(void) + { + return (1); + } + +/* Free all BIGNUM structures from PK11_SESSION. */ +static void pk11_free_nums(PK11_SESSION *sp, PK11_OPTYPE optype) + { + switch (optype) + { +#ifndef OPENSSL_NO_RSA + case OP_RSA: + if (sp->opdata_rsa_n_num != NULL) + { + BN_free(sp->opdata_rsa_n_num); + sp->opdata_rsa_n_num = NULL; + } + if (sp->opdata_rsa_e_num != NULL) + { + BN_free(sp->opdata_rsa_e_num); + sp->opdata_rsa_e_num = NULL; + } + if (sp->opdata_rsa_pn_num != NULL) + { + BN_free(sp->opdata_rsa_pn_num); + sp->opdata_rsa_pn_num = NULL; + } + if (sp->opdata_rsa_pe_num != NULL) + { + BN_free(sp->opdata_rsa_pe_num); + sp->opdata_rsa_pe_num = NULL; + } + if (sp->opdata_rsa_d_num != NULL) + { + BN_free(sp->opdata_rsa_d_num); + sp->opdata_rsa_d_num = NULL; + } + break; +#endif +#ifndef OPENSSL_NO_DSA + case OP_DSA: + if (sp->opdata_dsa_pub_num != NULL) + { + BN_free(sp->opdata_dsa_pub_num); + sp->opdata_dsa_pub_num = NULL; + } + if (sp->opdata_dsa_priv_num != NULL) + { + BN_free(sp->opdata_dsa_priv_num); + sp->opdata_dsa_priv_num = NULL; + } + break; +#endif +#ifndef OPENSSL_NO_DH + case OP_DH: + if (sp->opdata_dh_priv_num != NULL) + { + BN_free(sp->opdata_dh_priv_num); + sp->opdata_dh_priv_num = NULL; + } + break; +#endif + default: + break; + } + } + +/* + * Get new PK11_SESSION structure ready for use. Every process must have + * its own freelist of PK11_SESSION structures so handle fork() here + * by destroying the old and creating new freelist. + * The returned PK11_SESSION structure is disconnected from the freelist. + */ +PK11_SESSION * +pk11_get_session(PK11_OPTYPE optype) + { + PK11_SESSION *sp = NULL, *sp1, *freelist; +#ifndef NOPTHREADS + pthread_mutex_t *freelist_lock = NULL; +#endif + static pid_t pid = 0; + pid_t new_pid; + CK_RV rv; + + switch (optype) + { + case OP_RSA: + case OP_DSA: + case OP_DH: + case OP_RAND: + case OP_DIGEST: + case OP_CIPHER: +#ifndef NOPTHREADS + freelist_lock = session_cache[optype].lock; +#endif + break; + default: + PK11err(PK11_F_GET_SESSION, + PK11_R_INVALID_OPERATION_TYPE); + return (NULL); + } +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_lock(freelist_lock) == 0); +#else + CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); +#endif + + /* + * Will use it to find out if we forked. We cannot use the PID field in + * the session structure because we could get a newly allocated session + * here, with no PID information. + */ + if (pid == 0) + pid = getpid(); + + freelist = session_cache[optype].head; + sp = freelist; + + /* + * If the free list is empty, allocate new unitialized (filled + * with zeroes) PK11_SESSION structure otherwise return first + * structure from the freelist. + */ + if (sp == NULL) + { + if ((sp = OPENSSL_malloc(sizeof (PK11_SESSION))) == NULL) + { + PK11err(PK11_F_GET_SESSION, + PK11_R_MALLOC_FAILURE); + goto err; + } + (void) memset(sp, 0, sizeof (PK11_SESSION)); + + /* + * It is a new session so it will look like a cache miss to the + * code below. So, we must not try to to destroy its members so + * mark them as unused. + */ + sp->opdata_rsa_priv_key = CK_INVALID_HANDLE; + sp->opdata_rsa_pub_key = CK_INVALID_HANDLE; + } + else + { + freelist = sp->next; + } + + /* + * Check whether we have forked. In that case, we must get rid of all + * inherited sessions and start allocating new ones. + */ + if (pid != (new_pid = getpid())) + { + pid = new_pid; + + /* + * We are a new process and thus need to free any inherited + * PK11_SESSION objects aside from the first session (sp) which + * is the only PK11_SESSION structure we will reuse (for the + * head of the list). + */ + while ((sp1 = freelist) != NULL) + { + freelist = sp1->next; + /* + * NOTE: we do not want to call pk11_free_all_sessions() + * here because it would close underlying PKCS#11 + * sessions and destroy all objects. + */ + pk11_free_nums(sp1, optype); + OPENSSL_free(sp1); + } + + /* we have to free the active list as well. */ + pk11_free_active_list(optype); + + /* Initialize the process */ + rv = pFuncList->C_Initialize((CK_VOID_PTR)&pk11_init_args); + if ((rv != CKR_OK) && (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)) + { + PK11err_add_data(PK11_F_GET_SESSION, PK11_R_INITIALIZE, + rv); + OPENSSL_free(sp); + sp = NULL; + goto err; + } + + /* + * Choose slot here since the slot table is different on this + * process. If we are here then we must have found at least one + * usable slot before so we don't need to check any_slot_found. + * See pk11_library_init()'s usage of this function for more + * information. + */ +#ifdef SOLARIS_HW_SLOT_SELECTION + if (check_hw_mechanisms() == 0) + goto err; +#endif /* SOLARIS_HW_SLOT_SELECTION */ + if (pk11_choose_slots(NULL) == 0) + goto err; + + /* Open the global_session for the new process */ + rv = pFuncList->C_OpenSession(SLOTID, CKF_SERIAL_SESSION, + NULL_PTR, NULL_PTR, &global_session); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_SESSION, PK11_R_OPENSESSION, + rv); + OPENSSL_free(sp); + sp = NULL; + goto err; + } + + /* + * It is an inherited session from our parent so it needs + * re-initialization. + */ + if (pk11_setup_session(sp, optype) == 0) + { + OPENSSL_free(sp); + sp = NULL; + goto err; + } + if (pk11_token_relogin(sp->session) == 0) + { + /* + * We will keep the session in the cache list and let + * the caller cope with the situation. + */ + freelist = sp; + sp = NULL; + goto err; + } + } + + if (sp->pid == 0) + { + /* It is a new session and needs initialization. */ + if (pk11_setup_session(sp, optype) == 0) + { + OPENSSL_free(sp); + sp = NULL; + } + } + + /* set new head for the list of PK11_SESSION objects */ + session_cache[optype].head = freelist; + +err: + if (sp != NULL) + sp->next = NULL; + +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_unlock(freelist_lock) == 0); +#else + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + + return (sp); + } + + +void +pk11_return_session(PK11_SESSION *sp, PK11_OPTYPE optype) + { +#ifndef NOPTHREADS + pthread_mutex_t *freelist_lock; +#endif + PK11_SESSION *freelist; + + /* + * If this is a session from the parent it will be taken care of and + * freed in pk11_get_session() as part of the post-fork clean up the + * next time we will ask for a new session. + */ + if (sp == NULL || sp->pid != getpid()) + return; + + switch (optype) + { + case OP_RSA: + case OP_DSA: + case OP_DH: + case OP_RAND: + case OP_DIGEST: + case OP_CIPHER: +#ifndef NOPTHREADS + freelist_lock = session_cache[optype].lock; +#endif + break; + default: + PK11err(PK11_F_RETURN_SESSION, + PK11_R_INVALID_OPERATION_TYPE); + return; + } + +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_lock(freelist_lock) == 0); +#else + CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); +#endif + freelist = session_cache[optype].head; + sp->next = freelist; + session_cache[optype].head = sp; +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_unlock(freelist_lock) == 0); +#else + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + } + + +/* Destroy all objects. This function is called when the engine is finished */ +static int pk11_free_all_sessions() + { + int ret = 1; + int type; + +#ifndef OPENSSL_NO_RSA + (void) pk11_destroy_rsa_key_objects(NULL); +#endif /* OPENSSL_NO_RSA */ +#ifndef OPENSSL_NO_DSA + (void) pk11_destroy_dsa_key_objects(NULL); +#endif /* OPENSSL_NO_DSA */ +#ifndef OPENSSL_NO_DH + (void) pk11_destroy_dh_key_objects(NULL); +#endif /* OPENSSL_NO_DH */ + (void) pk11_destroy_cipher_key_objects(NULL); + + /* + * We try to release as much as we can but any error means that we will + * return 0 on exit. + */ + for (type = 0; type < OP_MAX; type++) + { + if (pk11_free_session_list(type) == 0) + ret = 0; + } + + return (ret); + } + +/* + * Destroy session structures from the linked list specified. Free as many + * sessions as possible but any failure in C_CloseSession() means that we + * return an error on return. + */ +static int pk11_free_session_list(PK11_OPTYPE optype) + { + CK_RV rv; + PK11_SESSION *sp = NULL; + PK11_SESSION *freelist = NULL; + pid_t mypid = getpid(); +#ifndef NOPTHREADS + pthread_mutex_t *freelist_lock; +#endif + int ret = 1; + + switch (optype) + { + case OP_RSA: + case OP_DSA: + case OP_DH: + case OP_RAND: + case OP_DIGEST: + case OP_CIPHER: +#ifndef NOPTHREADS + freelist_lock = session_cache[optype].lock; +#endif + break; + default: + PK11err(PK11_F_FREE_ALL_SESSIONS, + PK11_R_INVALID_OPERATION_TYPE); + return (0); + } + +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_lock(freelist_lock) == 0); +#else + CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); +#endif + freelist = session_cache[optype].head; + while ((sp = freelist) != NULL) + { + if (sp->session != CK_INVALID_HANDLE && sp->pid == mypid) + { + rv = pFuncList->C_CloseSession(sp->session); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_FREE_ALL_SESSIONS, + PK11_R_CLOSESESSION, rv); + ret = 0; + } + } + freelist = sp->next; + pk11_free_nums(sp, optype); + OPENSSL_free(sp); + } + +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_unlock(freelist_lock) == 0); +#else + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + return (ret); + } + + +static int +pk11_setup_session(PK11_SESSION *sp, PK11_OPTYPE optype) + { + CK_RV rv; + CK_SLOT_ID myslot; + + switch (optype) + { + case OP_RSA: + case OP_DSA: + case OP_DH: + myslot = pubkey_SLOTID; + break; + case OP_RAND: + myslot = rand_SLOTID; + break; + case OP_DIGEST: + case OP_CIPHER: + myslot = SLOTID; + break; + default: + PK11err(PK11_F_SETUP_SESSION, + PK11_R_INVALID_OPERATION_TYPE); + return (0); + } + + sp->session = CK_INVALID_HANDLE; +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: myslot=%d optype=%d\n", PK11_DBG, myslot, optype); +#endif /* DEBUG_SLOT_SELECTION */ + rv = pFuncList->C_OpenSession(myslot, CKF_SERIAL_SESSION, + NULL_PTR, NULL_PTR, &sp->session); + if (rv == CKR_CRYPTOKI_NOT_INITIALIZED) + { + /* + * We are probably a child process so force the + * reinitialize of the session + */ + pk11_library_initialized = FALSE; + if (!pk11_library_init(NULL)) + return (0); + rv = pFuncList->C_OpenSession(myslot, CKF_SERIAL_SESSION, + NULL_PTR, NULL_PTR, &sp->session); + } + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_SETUP_SESSION, PK11_R_OPENSESSION, rv); + return (0); + } + + sp->pid = getpid(); + + switch (optype) + { +#ifndef OPENSSL_NO_RSA + case OP_RSA: + sp->opdata_rsa_pub_key = CK_INVALID_HANDLE; + sp->opdata_rsa_priv_key = CK_INVALID_HANDLE; + sp->opdata_rsa_pub = NULL; + sp->opdata_rsa_n_num = NULL; + sp->opdata_rsa_e_num = NULL; + sp->opdata_rsa_priv = NULL; + sp->opdata_rsa_pn_num = NULL; + sp->opdata_rsa_pe_num = NULL; + sp->opdata_rsa_d_num = NULL; + break; +#endif /* OPENSSL_NO_RSA */ +#ifndef OPENSSL_NO_DSA + case OP_DSA: + sp->opdata_dsa_pub_key = CK_INVALID_HANDLE; + sp->opdata_dsa_priv_key = CK_INVALID_HANDLE; + sp->opdata_dsa_pub = NULL; + sp->opdata_dsa_pub_num = NULL; + sp->opdata_dsa_priv = NULL; + sp->opdata_dsa_priv_num = NULL; + break; +#endif /* OPENSSL_NO_DSA */ +#ifndef OPENSSL_NO_DH + case OP_DH: + sp->opdata_dh_key = CK_INVALID_HANDLE; + sp->opdata_dh = NULL; + sp->opdata_dh_priv_num = NULL; + break; +#endif /* OPENSSL_NO_DH */ + case OP_CIPHER: + sp->opdata_cipher_key = CK_INVALID_HANDLE; + sp->opdata_encrypt = -1; + break; + default: + break; + } + + /* + * We always initialize the session as containing a non-persistent + * object. The key load functions set it to persistent if that is so. + */ + sp->pub_persistent = CK_FALSE; + sp->priv_persistent = CK_FALSE; + return (1); + } + +#ifndef OPENSSL_NO_RSA +/* Destroy RSA public key from single session. */ +int +pk11_destroy_rsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock) + { + int ret = 0; + + if (sp->opdata_rsa_pub_key != CK_INVALID_HANDLE) + { + TRY_OBJ_DESTROY(sp, sp->opdata_rsa_pub_key, + ret, uselock, OP_RSA, CK_FALSE); + sp->opdata_rsa_pub_key = CK_INVALID_HANDLE; + sp->opdata_rsa_pub = NULL; + if (sp->opdata_rsa_n_num != NULL) + { + BN_free(sp->opdata_rsa_n_num); + sp->opdata_rsa_n_num = NULL; + } + if (sp->opdata_rsa_e_num != NULL) + { + BN_free(sp->opdata_rsa_e_num); + sp->opdata_rsa_e_num = NULL; + } + } + + return (ret); + } + +/* Destroy RSA private key from single session. */ +int +pk11_destroy_rsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock) + { + int ret = 0; + + if (sp->opdata_rsa_priv_key != CK_INVALID_HANDLE) + { + TRY_OBJ_DESTROY(sp, sp->opdata_rsa_priv_key, + ret, uselock, OP_RSA, CK_TRUE); + sp->opdata_rsa_priv_key = CK_INVALID_HANDLE; + sp->opdata_rsa_priv = NULL; + if (sp->opdata_rsa_d_num != NULL) + { + BN_free(sp->opdata_rsa_d_num); + sp->opdata_rsa_d_num = NULL; + } + + /* + * For the RSA key by reference code, public components 'n'/'e' + * are the key components we use to check for the cache hit. We + * must free those as well. + */ + if (sp->opdata_rsa_pn_num != NULL) + { + BN_free(sp->opdata_rsa_pn_num); + sp->opdata_rsa_pn_num = NULL; + } + if (sp->opdata_rsa_pe_num != NULL) + { + BN_free(sp->opdata_rsa_pe_num); + sp->opdata_rsa_pe_num = NULL; + } + } + + return (ret); + } + +/* + * Destroy RSA key object wrapper. If session is NULL, try to destroy all + * objects in the free list. + */ +int +pk11_destroy_rsa_key_objects(PK11_SESSION *session) + { + int ret = 1; + PK11_SESSION *sp = NULL; + PK11_SESSION *local_free_session; + CK_BBOOL uselock = TRUE; + + if (session != NULL) + local_free_session = session; + else + { +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_lock(session_cache[OP_RSA].lock) == 0); +#else + CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); +#endif + local_free_session = session_cache[OP_RSA].head; + uselock = FALSE; + } + + /* + * go through the list of sessions and delete key objects + */ + while ((sp = local_free_session) != NULL) + { + local_free_session = sp->next; + + /* + * Do not terminate list traversal if one of the + * destroy operations fails. + */ + if (pk11_destroy_rsa_object_pub(sp, uselock) == 0) + { + ret = 0; + continue; + } + if (pk11_destroy_rsa_object_priv(sp, uselock) == 0) + { + ret = 0; + continue; + } + } + +#ifndef NOPTHREADS + if (session == NULL) + OPENSSL_assert(pthread_mutex_unlock(session_cache[OP_RSA].lock) == 0); +#else + if (session == NULL) + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + + return (ret); + } +#endif /* OPENSSL_NO_RSA */ + +#ifndef OPENSSL_NO_DSA +/* Destroy DSA public key from single session. */ +int +pk11_destroy_dsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock) + { + int ret = 0; + + if (sp->opdata_dsa_pub_key != CK_INVALID_HANDLE) + { + TRY_OBJ_DESTROY(sp, sp->opdata_dsa_pub_key, + ret, uselock, OP_DSA, CK_FALSE); + sp->opdata_dsa_pub_key = CK_INVALID_HANDLE; + sp->opdata_dsa_pub = NULL; + if (sp->opdata_dsa_pub_num != NULL) + { + BN_free(sp->opdata_dsa_pub_num); + sp->opdata_dsa_pub_num = NULL; + } + } + + return (ret); + } + +/* Destroy DSA private key from single session. */ +int +pk11_destroy_dsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock) + { + int ret = 0; + + if (sp->opdata_dsa_priv_key != CK_INVALID_HANDLE) + { + TRY_OBJ_DESTROY(sp, sp->opdata_dsa_priv_key, + ret, uselock, OP_DSA, CK_TRUE); + sp->opdata_dsa_priv_key = CK_INVALID_HANDLE; + sp->opdata_dsa_priv = NULL; + if (sp->opdata_dsa_priv_num != NULL) + { + BN_free(sp->opdata_dsa_priv_num); + sp->opdata_dsa_priv_num = NULL; + } + } + + return (ret); + } + +/* + * Destroy DSA key object wrapper. If session is NULL, try to destroy all + * objects in the free list. + */ +int +pk11_destroy_dsa_key_objects(PK11_SESSION *session) + { + int ret = 1; + PK11_SESSION *sp = NULL; + PK11_SESSION *local_free_session; + CK_BBOOL uselock = TRUE; + + if (session != NULL) + local_free_session = session; + else + { +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_lock(session_cache[OP_DSA].lock) == 0); +#else + CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); +#endif + local_free_session = session_cache[OP_DSA].head; + uselock = FALSE; + } + + /* + * go through the list of sessions and delete key objects + */ + while ((sp = local_free_session) != NULL) + { + local_free_session = sp->next; + + /* + * Do not terminate list traversal if one of the + * destroy operations fails. + */ + if (pk11_destroy_dsa_object_pub(sp, uselock) == 0) + { + ret = 0; + continue; + } + if (pk11_destroy_dsa_object_priv(sp, uselock) == 0) + { + ret = 0; + continue; + } + } + +#ifndef NOPTHREADS + if (session == NULL) + OPENSSL_assert(pthread_mutex_unlock(session_cache[OP_DSA].lock) == 0); +#else + if (session == NULL) + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + + return (ret); + } +#endif /* OPENSSL_NO_DSA */ + +#ifndef OPENSSL_NO_DH +/* Destroy DH key from single session. */ +int +pk11_destroy_dh_object(PK11_SESSION *sp, CK_BBOOL uselock) + { + int ret = 0; + + if (sp->opdata_dh_key != CK_INVALID_HANDLE) + { + TRY_OBJ_DESTROY(sp, sp->opdata_dh_key, + ret, uselock, OP_DH, CK_TRUE); + sp->opdata_dh_key = CK_INVALID_HANDLE; + sp->opdata_dh = NULL; + if (sp->opdata_dh_priv_num != NULL) + { + BN_free(sp->opdata_dh_priv_num); + sp->opdata_dh_priv_num = NULL; + } + } + + return (ret); + } + +/* + * Destroy DH key object wrapper. + * + * arg0: pointer to PKCS#11 engine session structure + * if session is NULL, try to destroy all objects in the free list + */ +int +pk11_destroy_dh_key_objects(PK11_SESSION *session) + { + int ret = 1; + PK11_SESSION *sp = NULL; + PK11_SESSION *local_free_session; + CK_BBOOL uselock = TRUE; + + if (session != NULL) + local_free_session = session; + else + { +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_lock(session_cache[OP_DH].lock) == 0); +#else + CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); +#endif + local_free_session = session_cache[OP_DH].head; + uselock = FALSE; + } + + while ((sp = local_free_session) != NULL) + { + local_free_session = sp->next; + + /* + * Do not terminate list traversal if one of the + * destroy operations fails. + */ + if (pk11_destroy_dh_object(sp, uselock) == 0) + { + ret = 0; + continue; + } + } + +#ifndef NOPTHREADS + if (session == NULL) + OPENSSL_assert(pthread_mutex_unlock(session_cache[OP_DH].lock) == 0); +#else + if (session == NULL) + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + + return (ret); + } +#endif /* OPENSSL_NO_DH */ + +static int +pk11_destroy_object(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE oh, + CK_BBOOL persistent) + { + CK_RV rv; + + /* + * We never try to destroy persistent objects which are the objects + * stored in the keystore. Also, we always use read-only sessions so + * C_DestroyObject() would be returning CKR_SESSION_READ_ONLY here. + */ + if (persistent == CK_TRUE) + return (1); + + rv = pFuncList->C_DestroyObject(session, oh); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DESTROY_OBJECT, PK11_R_DESTROYOBJECT, + rv); + return (0); + } + + return (1); + } + + +/* Symmetric ciphers and digests support functions */ + +static int +cipher_nid_to_pk11(int nid) + { + int i; + + for (i = 0; i < PK11_CIPHER_MAX; i++) + if (ciphers[i].nid == nid) + return (ciphers[i].id); + return (-1); + } + +static int +pk11_usable_ciphers(const int **nids) + { + if (cipher_count > 0) + *nids = cipher_nids; + else + *nids = NULL; + return (cipher_count); + } + +static int +pk11_usable_digests(const int **nids) + { + if (digest_count > 0) + *nids = digest_nids; + else + *nids = NULL; + return (digest_count); + } + +/* + * Init context for encryption or decryption using a symmetric key. + */ +static int pk11_init_symmetric(EVP_CIPHER_CTX *ctx, PK11_CIPHER *pcipher, + PK11_SESSION *sp, CK_MECHANISM_PTR pmech) + { + CK_RV rv; + CK_AES_CTR_PARAMS ctr_params; + + /* + * We expect pmech->mechanism to be already set and + * pParameter/ulParameterLen initialized to NULL/0 before + * pk11_init_symetric() is called. + */ + OPENSSL_assert(pmech->mechanism != 0); + OPENSSL_assert(pmech->pParameter == NULL); + OPENSSL_assert(pmech->ulParameterLen == 0); + + if (ctx->cipher->nid == NID_aes_128_ctr || + ctx->cipher->nid == NID_aes_192_ctr || + ctx->cipher->nid == NID_aes_256_ctr) + { + pmech->pParameter = (void *)(&ctr_params); + pmech->ulParameterLen = sizeof (ctr_params); + /* + * For now, we are limited to the fixed length of the counter, + * it covers the whole counter block. That's what RFC 4344 + * needs. For more information on internal structure of the + * counter block, see RFC 3686. If needed in the future, we can + * add code so that the counter length can be set via + * ENGINE_ctrl() function. + */ + ctr_params.ulCounterBits = AES_BLOCK_SIZE * 8; + OPENSSL_assert(pcipher->iv_len == AES_BLOCK_SIZE); + (void) memcpy(ctr_params.cb, ctx->iv, AES_BLOCK_SIZE); + } + else + { + if (pcipher->iv_len > 0) + { + pmech->pParameter = (void *)ctx->iv; + pmech->ulParameterLen = pcipher->iv_len; + } + } + + /* if we get here, the encryption needs to be reinitialized */ + if (ctx->encrypt) + rv = pFuncList->C_EncryptInit(sp->session, pmech, + sp->opdata_cipher_key); + else + rv = pFuncList->C_DecryptInit(sp->session, pmech, + sp->opdata_cipher_key); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_CIPHER_INIT, ctx->encrypt ? + PK11_R_ENCRYPTINIT : PK11_R_DECRYPTINIT, rv); + pk11_return_session(sp, OP_CIPHER); + return (0); + } + + return (1); + } + +/* ARGSUSED */ +static int +pk11_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc) + { + CK_MECHANISM mech; + int index; + PK11_CIPHER_STATE *state = (PK11_CIPHER_STATE *) ctx->cipher_data; + PK11_SESSION *sp; + PK11_CIPHER *p_ciph_table_row; + + state->sp = NULL; + + index = cipher_nid_to_pk11(ctx->cipher->nid); + if (index < 0 || index >= PK11_CIPHER_MAX) + return (0); + + p_ciph_table_row = &ciphers[index]; + /* + * iv_len in the ctx->cipher structure is the maximum IV length for the + * current cipher and it must be less or equal to the IV length in our + * ciphers table. The key length must be in the allowed interval. From + * all cipher modes that the PKCS#11 engine supports only RC4 allows a + * key length to be in some range, all other NIDs have a precise key + * length. Every application can define its own EVP functions so this + * code serves as a sanity check. + * + * Note that the reason why the IV length in ctx->cipher might be + * greater than the actual length is that OpenSSL uses BLOCK_CIPHER_defs + * macro to define functions that return EVP structures for all DES + * modes. So, even ECB modes get 8 byte IV. + */ + if (ctx->cipher->iv_len < p_ciph_table_row->iv_len || + ctx->key_len < p_ciph_table_row->min_key_len || + ctx->key_len > p_ciph_table_row->max_key_len) { + PK11err(PK11_F_CIPHER_INIT, PK11_R_KEY_OR_IV_LEN_PROBLEM); + return (0); + } + + if ((sp = pk11_get_session(OP_CIPHER)) == NULL) + return (0); + + /* if applicable, the mechanism parameter is used for IV */ + mech.mechanism = p_ciph_table_row->mech_type; + mech.pParameter = NULL; + mech.ulParameterLen = 0; + + /* The key object is destroyed here if it is not the current key. */ + (void) check_new_cipher_key(sp, key, ctx->key_len); + + /* + * If the key is the same and the encryption is also the same, then + * just reuse it. However, we must not forget to reinitialize the + * context that was finalized in pk11_cipher_cleanup(). + */ + if (sp->opdata_cipher_key != CK_INVALID_HANDLE && + sp->opdata_encrypt == ctx->encrypt) + { + state->sp = sp; + if (pk11_init_symmetric(ctx, p_ciph_table_row, sp, &mech) == 0) + return (0); + + return (1); + } + + /* + * Check if the key has been invalidated. If so, a new key object + * needs to be created. + */ + if (sp->opdata_cipher_key == CK_INVALID_HANDLE) + { + sp->opdata_cipher_key = pk11_get_cipher_key( + ctx, key, p_ciph_table_row->key_type, sp); + } + + if (sp->opdata_encrypt != ctx->encrypt && sp->opdata_encrypt != -1) + { + /* + * The previous encryption/decryption is different. Need to + * terminate the previous * active encryption/decryption here. + */ + if (!pk11_cipher_final(sp)) + { + pk11_return_session(sp, OP_CIPHER); + return (0); + } + } + + if (sp->opdata_cipher_key == CK_INVALID_HANDLE) + { + pk11_return_session(sp, OP_CIPHER); + return (0); + } + + /* now initialize the context with a new key */ + if (pk11_init_symmetric(ctx, p_ciph_table_row, sp, &mech) == 0) + return (0); + + sp->opdata_encrypt = ctx->encrypt; + state->sp = sp; + + return (1); + } + +/* + * When reusing the same key in an encryption/decryption session for a + * decryption/encryption session, we need to close the active session + * and recreate a new one. Note that the key is in the global session so + * that it needs not be recreated. + * + * It is more appropriate to use C_En/DecryptFinish here. At the time of this + * development, these two functions in the PKCS#11 libraries used return + * unexpected errors when passing in 0 length output. It may be a good + * idea to try them again if performance is a problem here and fix + * C_En/DecryptFinial if there are bugs there causing the problem. + */ +static int +pk11_cipher_final(PK11_SESSION *sp) + { + CK_RV rv; + + rv = pFuncList->C_CloseSession(sp->session); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_CIPHER_FINAL, PK11_R_CLOSESESSION, rv); + return (0); + } + + rv = pFuncList->C_OpenSession(SLOTID, CKF_SERIAL_SESSION, + NULL_PTR, NULL_PTR, &sp->session); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_CIPHER_FINAL, PK11_R_OPENSESSION, rv); + return (0); + } + + return (1); + } + +/* + * An engine interface function. The calling function allocates sufficient + * memory for the output buffer "out" to hold the results. + */ +#if OPENSSL_VERSION_NUMBER < 0x10000000L +static int +pk11_cipher_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, unsigned int inl) +#else +static int +pk11_cipher_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t inl) +#endif + { + PK11_CIPHER_STATE *state = (PK11_CIPHER_STATE *) ctx->cipher_data; + PK11_SESSION *sp; + CK_RV rv; + unsigned long outl = inl; + + if (state == NULL || state->sp == NULL) + return (0); + + sp = (PK11_SESSION *) state->sp; + + if (!inl) + return (1); + + /* RC4 is the only stream cipher we support */ + if (ctx->cipher->nid != NID_rc4 && (inl % ctx->cipher->block_size) != 0) + return (0); + + if (ctx->encrypt) + { + rv = pFuncList->C_EncryptUpdate(sp->session, + (unsigned char *)in, inl, out, &outl); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_CIPHER_DO_CIPHER, + PK11_R_ENCRYPTUPDATE, rv); + return (0); + } + } + else + { + rv = pFuncList->C_DecryptUpdate(sp->session, + (unsigned char *)in, inl, out, &outl); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_CIPHER_DO_CIPHER, + PK11_R_DECRYPTUPDATE, rv); + return (0); + } + } + + /* + * For DES_CBC, DES3_CBC, AES_CBC, and RC4, the output size is always + * the same size of input. + * The application has guaranteed to call the block ciphers with + * correctly aligned buffers. + */ + if (inl != outl) + return (0); + + return (1); + } + +/* + * Return the session to the pool. Calling C_EncryptFinal() and C_DecryptFinal() + * here is the right thing because in EVP_DecryptFinal_ex(), engine's + * do_cipher() is not even called, and in EVP_EncryptFinal_ex() it is called but + * the engine can't find out that it's the finalizing call. We wouldn't + * necessarily have to finalize the context here since reinitializing it with + * C_(Encrypt|Decrypt)Init() should be fine but for the sake of correctness, + * let's do it. Some implementations might leak memory if the previously used + * context is initialized without finalizing it first. + */ +static int +pk11_cipher_cleanup(EVP_CIPHER_CTX *ctx) + { + CK_RV rv; + CK_ULONG len = EVP_MAX_BLOCK_LENGTH; + CK_BYTE buf[EVP_MAX_BLOCK_LENGTH]; + PK11_CIPHER_STATE *state = ctx->cipher_data; + + if (state != NULL && state->sp != NULL) + { + /* + * We are not interested in the data here, we just need to get + * rid of the context. + */ + if (ctx->encrypt) + rv = pFuncList->C_EncryptFinal( + state->sp->session, buf, &len); + else + rv = pFuncList->C_DecryptFinal( + state->sp->session, buf, &len); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_CIPHER_CLEANUP, ctx->encrypt ? + PK11_R_ENCRYPTFINAL : PK11_R_DECRYPTFINAL, rv); + pk11_return_session(state->sp, OP_CIPHER); + return (0); + } + + pk11_return_session(state->sp, OP_CIPHER); + state->sp = NULL; + } + + return (1); + } + +/* + * Registered by the ENGINE when used to find out how to deal with + * a particular NID in the ENGINE. This says what we'll do at the + * top level - note, that list is restricted by what we answer with + */ +/* ARGSUSED */ +static int +pk11_engine_ciphers(ENGINE *e, const EVP_CIPHER **cipher, + const int **nids, int nid) + { + if (!cipher) + return (pk11_usable_ciphers(nids)); + + switch (nid) + { + case NID_des_ede3_cbc: + *cipher = &pk11_3des_cbc; + break; + case NID_des_cbc: + *cipher = &pk11_des_cbc; + break; + case NID_des_ede3_ecb: + *cipher = &pk11_3des_ecb; + break; + case NID_des_ecb: + *cipher = &pk11_des_ecb; + break; + case NID_aes_128_cbc: + *cipher = &pk11_aes_128_cbc; + break; + case NID_aes_192_cbc: + *cipher = &pk11_aes_192_cbc; + break; + case NID_aes_256_cbc: + *cipher = &pk11_aes_256_cbc; + break; + case NID_aes_128_ecb: + *cipher = &pk11_aes_128_ecb; + break; + case NID_aes_192_ecb: + *cipher = &pk11_aes_192_ecb; + break; + case NID_aes_256_ecb: + *cipher = &pk11_aes_256_ecb; + break; + case NID_bf_cbc: + *cipher = &pk11_bf_cbc; + break; + case NID_rc4: + *cipher = &pk11_rc4; + break; + case NID_aes_128_ctr: + *cipher = &pk11_aes_128_ctr; + break; + case NID_aes_192_ctr: + *cipher = &pk11_aes_192_ctr; + break; + case NID_aes_256_ctr: + *cipher = &pk11_aes_256_ctr; + break; + default: + *cipher = NULL; + break; + } + return (*cipher != NULL); + } + +/* ARGSUSED */ +static int +pk11_engine_digests(ENGINE *e, const EVP_MD **digest, + const int **nids, int nid) + { + if (!digest) + return (pk11_usable_digests(nids)); + + switch (nid) + { + case NID_md5: + *digest = &pk11_md5; + break; + case NID_sha1: + *digest = &pk11_sha1; + break; + case NID_sha224: + *digest = &pk11_sha224; + break; + case NID_sha256: + *digest = &pk11_sha256; + break; + case NID_sha384: + *digest = &pk11_sha384; + break; + case NID_sha512: + *digest = &pk11_sha512; + break; + default: + *digest = NULL; + break; + } + return (*digest != NULL); + } + + +/* Create a secret key object in a PKCS#11 session */ +static CK_OBJECT_HANDLE pk11_get_cipher_key(EVP_CIPHER_CTX *ctx, + const unsigned char *key, CK_KEY_TYPE key_type, PK11_SESSION *sp) + { + CK_RV rv; + CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE; + CK_OBJECT_CLASS obj_key = CKO_SECRET_KEY; + CK_ULONG ul_key_attr_count = 6; + unsigned char key_buf[PK11_KEY_LEN_MAX]; + + CK_ATTRIBUTE a_key_template[] = + { + {CKA_CLASS, (void*) NULL, sizeof (CK_OBJECT_CLASS)}, + {CKA_KEY_TYPE, (void*) NULL, sizeof (CK_KEY_TYPE)}, + {CKA_TOKEN, &myfalse, sizeof (myfalse)}, + {CKA_ENCRYPT, &mytrue, sizeof (mytrue)}, + {CKA_DECRYPT, &mytrue, sizeof (mytrue)}, + {CKA_VALUE, (void*) NULL, 0}, + }; + + /* + * Create secret key object in global_session. All other sessions + * can use the key handles. Here is why: + * OpenSSL will call EncryptInit and EncryptUpdate using a secret key. + * It may then call DecryptInit and DecryptUpdate using the same key. + * To use the same key object, we need to call EncryptFinal with + * a 0 length message. Currently, this does not work for 3DES + * mechanism. To get around this problem, we close the session and + * then create a new session to use the same key object. When a session + * is closed, all the object handles will be invalid. Thus, create key + * objects in a global session, an individual session may be closed to + * terminate the active operation. + */ + CK_SESSION_HANDLE session = global_session; + a_key_template[0].pValue = &obj_key; + a_key_template[1].pValue = &key_type; + if (ctx->key_len > PK11_KEY_LEN_MAX) + { + a_key_template[5].pValue = (void *) key; + } + else + { + memset(key_buf, 0, PK11_KEY_LEN_MAX); + memcpy(key_buf, key, ctx->key_len); + if ((key_type == CKK_DES) || + (key_type == CKK_DES2) || + (key_type == CKK_DES3)) + DES_fixup_key_parity((DES_cblock *) &key_buf[0]); + if ((key_type == CKK_DES2) || + (key_type == CKK_DES3)) + DES_fixup_key_parity((DES_cblock *) &key_buf[8]); + if (key_type == CKK_DES3) + DES_fixup_key_parity((DES_cblock *) &key_buf[16]); + a_key_template[5].pValue = (void *) key_buf; + } + a_key_template[5].ulValueLen = (unsigned long) ctx->key_len; + + rv = pFuncList->C_CreateObject(session, + a_key_template, ul_key_attr_count, &h_key); + if (rv != CKR_OK) + { + memset(key_buf, 0, PK11_KEY_LEN_MAX); + PK11err_add_data(PK11_F_GET_CIPHER_KEY, PK11_R_CREATEOBJECT, + rv); + goto err; + } + + /* + * Save the key information used in this session. + * The max can be saved is PK11_KEY_LEN_MAX. + */ + if (ctx->key_len > PK11_KEY_LEN_MAX) + { + sp->opdata_key_len = PK11_KEY_LEN_MAX; + (void) memcpy(sp->opdata_key, key, sp->opdata_key_len); + } + else + { + sp->opdata_key_len = ctx->key_len; + (void) memcpy(sp->opdata_key, key_buf, sp->opdata_key_len); + } + memset(key_buf, 0, PK11_KEY_LEN_MAX); +err: + + return (h_key); + } + +static int +md_nid_to_pk11(int nid) + { + int i; + + for (i = 0; i < PK11_DIGEST_MAX; i++) + if (digests[i].nid == nid) + return (digests[i].id); + return (-1); + } + +static int +pk11_digest_init(EVP_MD_CTX *ctx) + { + CK_RV rv; + CK_MECHANISM mech; + int index; + PK11_SESSION *sp; + PK11_DIGEST *pdp; + PK11_CIPHER_STATE *state = (PK11_CIPHER_STATE *) ctx->md_data; + + state->sp = NULL; + + index = md_nid_to_pk11(ctx->digest->type); + if (index < 0 || index >= PK11_DIGEST_MAX) + return (0); + + pdp = &digests[index]; + if ((sp = pk11_get_session(OP_DIGEST)) == NULL) + return (0); + + /* at present, no parameter is needed for supported digests */ + mech.mechanism = pdp->mech_type; + mech.pParameter = NULL; + mech.ulParameterLen = 0; + + rv = pFuncList->C_DigestInit(sp->session, &mech); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DIGEST_INIT, PK11_R_DIGESTINIT, rv); + pk11_return_session(sp, OP_DIGEST); + return (0); + } + + state->sp = sp; + + return (1); + } + +static int +pk11_digest_update(EVP_MD_CTX *ctx, const void *data, size_t count) + { + CK_RV rv; + PK11_CIPHER_STATE *state = (PK11_CIPHER_STATE *) ctx->md_data; + + /* 0 length message will cause a failure in C_DigestFinal */ + if (count == 0) + return (1); + + if (state == NULL || state->sp == NULL) + return (0); + + rv = pFuncList->C_DigestUpdate(state->sp->session, (CK_BYTE *) data, + count); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DIGEST_UPDATE, PK11_R_DIGESTUPDATE, rv); + pk11_return_session(state->sp, OP_DIGEST); + state->sp = NULL; + return (0); + } + + return (1); + } + +static int +pk11_digest_final(EVP_MD_CTX *ctx, unsigned char *md) + { + CK_RV rv; + unsigned long len; + PK11_CIPHER_STATE *state = (PK11_CIPHER_STATE *) ctx->md_data; + len = ctx->digest->md_size; + + if (state == NULL || state->sp == NULL) + return (0); + + rv = pFuncList->C_DigestFinal(state->sp->session, md, &len); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DIGEST_FINAL, PK11_R_DIGESTFINAL, rv); + pk11_return_session(state->sp, OP_DIGEST); + state->sp = NULL; + return (0); + } + + if (ctx->digest->md_size != len) + return (0); + + /* + * Final is called and digest is returned, so return the session + * to the pool + */ + pk11_return_session(state->sp, OP_DIGEST); + state->sp = NULL; + + return (1); + } + +static int +pk11_digest_copy(EVP_MD_CTX *to, const EVP_MD_CTX *from) + { + CK_RV rv; + int ret = 0; + PK11_CIPHER_STATE *state, *state_to; + CK_BYTE_PTR pstate = NULL; + CK_ULONG ul_state_len; + + /* The copy-from state */ + state = (PK11_CIPHER_STATE *) from->md_data; + if (state == NULL || state->sp == NULL) + goto err; + + /* Initialize the copy-to state */ + if (!pk11_digest_init(to)) + goto err; + state_to = (PK11_CIPHER_STATE *) to->md_data; + + /* Get the size of the operation state of the copy-from session */ + rv = pFuncList->C_GetOperationState(state->sp->session, NULL, + &ul_state_len); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DIGEST_COPY, PK11_R_GET_OPERATION_STATE, + rv); + goto err; + } + if (ul_state_len == 0) + { + goto err; + } + + pstate = OPENSSL_malloc(ul_state_len); + if (pstate == NULL) + { + PK11err(PK11_F_DIGEST_COPY, PK11_R_MALLOC_FAILURE); + goto err; + } + + /* Get the operation state of the copy-from session */ + rv = pFuncList->C_GetOperationState(state->sp->session, pstate, + &ul_state_len); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DIGEST_COPY, PK11_R_GET_OPERATION_STATE, + rv); + goto err; + } + + /* Set the operation state of the copy-to session */ + rv = pFuncList->C_SetOperationState(state_to->sp->session, pstate, + ul_state_len, 0, 0); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DIGEST_COPY, + PK11_R_SET_OPERATION_STATE, rv); + goto err; + } + + ret = 1; +err: + if (pstate != NULL) + OPENSSL_free(pstate); + + return (ret); + } + +/* Return any pending session state to the pool */ +static int +pk11_digest_cleanup(EVP_MD_CTX *ctx) + { + PK11_CIPHER_STATE *state = ctx->md_data; + unsigned char buf[EVP_MAX_MD_SIZE]; + + if (state != NULL && state->sp != NULL) + { + /* + * If state->sp is not NULL then pk11_digest_final() has not + * been called yet. We must call it now to free any memory + * that might have been allocated in the token when + * pk11_digest_init() was called. pk11_digest_final() + * will return the session to the cache. + */ + if (!pk11_digest_final(ctx, buf)) + return (0); + } + + return (1); + } + +/* + * Check if the new key is the same as the key object in the session. If the key + * is the same, no need to create a new key object. Otherwise, the old key + * object needs to be destroyed and a new one will be created. Return 1 for + * cache hit, 0 for cache miss. Note that we must check the key length first + * otherwise we could end up reusing a different, longer key with the same + * prefix. + */ +static int check_new_cipher_key(PK11_SESSION *sp, const unsigned char *key, + int key_len) + { + if (sp->opdata_key_len != key_len || + memcmp(sp->opdata_key, key, key_len) != 0) + { + (void) pk11_destroy_cipher_key_objects(sp); + return (0); + } + return (1); + } + +/* Destroy one or more secret key objects. */ +static int pk11_destroy_cipher_key_objects(PK11_SESSION *session) + { + int ret = 0; + PK11_SESSION *sp = NULL; + PK11_SESSION *local_free_session; + + if (session != NULL) + local_free_session = session; + else + { +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_lock(session_cache[OP_CIPHER].lock) == 0); +#else + CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); +#endif + local_free_session = session_cache[OP_CIPHER].head; + } + + while ((sp = local_free_session) != NULL) + { + local_free_session = sp->next; + + if (sp->opdata_cipher_key != CK_INVALID_HANDLE) + { + /* + * The secret key object is created in the + * global_session. See pk11_get_cipher_key(). + */ + if (pk11_destroy_object(global_session, + sp->opdata_cipher_key, CK_FALSE) == 0) + goto err; + sp->opdata_cipher_key = CK_INVALID_HANDLE; + } + } + ret = 1; +err: + +#ifndef NOPTHREADS + if (session == NULL) + OPENSSL_assert(pthread_mutex_unlock(session_cache[OP_CIPHER].lock) == 0); +#else + if (session == NULL) + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + + return (ret); + } + + +/* + * Public key mechanisms optionally supported + * + * CKM_RSA_X_509 + * CKM_RSA_PKCS + * CKM_DSA + * + * The first slot that supports at least one of those mechanisms is chosen as a + * public key slot. + * + * Symmetric ciphers optionally supported + * + * CKM_DES3_CBC + * CKM_DES_CBC + * CKM_AES_CBC + * CKM_DES3_ECB + * CKM_DES_ECB + * CKM_AES_ECB + * CKM_AES_CTR + * CKM_RC4 + * CKM_BLOWFISH_CBC + * + * Digests optionally supported + * + * CKM_MD5 + * CKM_SHA_1 + * CKM_SHA224 + * CKM_SHA256 + * CKM_SHA384 + * CKM_SHA512 + * + * The output of this function is a set of global variables indicating which + * mechanisms from RSA, DSA, DH and RAND are present, and also two arrays of + * mechanisms, one for symmetric ciphers and one for digests. Also, 3 global + * variables carry information about which slot was chosen for (a) public key + * mechanisms, (b) random operations, and (c) symmetric ciphers and digests. + */ +static int +pk11_choose_slots(int *any_slot_found) + { + CK_SLOT_ID_PTR pSlotList = NULL_PTR; + CK_ULONG ulSlotCount = 0; + CK_MECHANISM_INFO mech_info; + CK_TOKEN_INFO token_info; + unsigned int i; + CK_RV rv; + CK_SLOT_ID best_slot_sofar = 0; + CK_BBOOL found_candidate_slot = CK_FALSE; + int slot_n_cipher = 0; + int slot_n_digest = 0; + CK_SLOT_ID current_slot = 0; + int current_slot_n_cipher = 0; + int current_slot_n_digest = 0; + + int local_cipher_nids[PK11_CIPHER_MAX]; + int local_digest_nids[PK11_DIGEST_MAX]; + + /* let's initialize the output parameter */ + if (any_slot_found != NULL) + *any_slot_found = 0; + + /* Get slot list for memory allocation */ + rv = pFuncList->C_GetSlotList(CK_FALSE, NULL_PTR, &ulSlotCount); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_CHOOSE_SLOT, PK11_R_GETSLOTLIST, rv); + return (0); + } + + /* it's not an error if we didn't find any providers */ + if (ulSlotCount == 0) + { +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: no crypto providers found\n", PK11_DBG); +#endif /* DEBUG_SLOT_SELECTION */ + return (1); + } + + pSlotList = OPENSSL_malloc(ulSlotCount * sizeof (CK_SLOT_ID)); + + if (pSlotList == NULL) + { + PK11err(PK11_F_CHOOSE_SLOT, PK11_R_MALLOC_FAILURE); + return (0); + } + + /* Get the slot list for processing */ + rv = pFuncList->C_GetSlotList(CK_FALSE, pSlotList, &ulSlotCount); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_CHOOSE_SLOT, PK11_R_GETSLOTLIST, rv); + OPENSSL_free(pSlotList); + return (0); + } + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: provider: %s\n", PK11_DBG, def_PK11_LIBNAME); + fprintf(stderr, "%s: number of slots: %d\n", PK11_DBG, ulSlotCount); + + fprintf(stderr, "%s: == checking rand slots ==\n", PK11_DBG); +#endif /* DEBUG_SLOT_SELECTION */ + for (i = 0; i < ulSlotCount; i++) + { + current_slot = pSlotList[i]; + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: checking slot: %d\n", PK11_DBG, i); +#endif /* DEBUG_SLOT_SELECTION */ + /* Check if slot has random support. */ + rv = pFuncList->C_GetTokenInfo(current_slot, &token_info); + if (rv != CKR_OK) + continue; + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: token label: %.32s\n", PK11_DBG, token_info.label); +#endif /* DEBUG_SLOT_SELECTION */ + + if (token_info.flags & CKF_RNG) + { +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: this token has CKF_RNG flag\n", PK11_DBG); +#endif /* DEBUG_SLOT_SELECTION */ + pk11_have_random = CK_TRUE; + rand_SLOTID = current_slot; + break; + } + } + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: == checking pubkey slots ==\n", PK11_DBG); +#endif /* DEBUG_SLOT_SELECTION */ + + pubkey_SLOTID = pSlotList[0]; + for (i = 0; i < ulSlotCount; i++) + { + CK_BBOOL slot_has_rsa = CK_FALSE; + CK_BBOOL slot_has_recover = CK_FALSE; + CK_BBOOL slot_has_dsa = CK_FALSE; + CK_BBOOL slot_has_dh = CK_FALSE; + current_slot = pSlotList[i]; + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: checking slot: %d\n", PK11_DBG, i); +#endif /* DEBUG_SLOT_SELECTION */ + rv = pFuncList->C_GetTokenInfo(current_slot, &token_info); + if (rv != CKR_OK) + continue; + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: token label: %.32s\n", PK11_DBG, token_info.label); +#endif /* DEBUG_SLOT_SELECTION */ + +#ifndef OPENSSL_NO_RSA + /* + * Check if this slot is capable of signing and + * verifying with CKM_RSA_PKCS. + */ + rv = pFuncList->C_GetMechanismInfo(current_slot, CKM_RSA_PKCS, + &mech_info); + + if (rv == CKR_OK && ((mech_info.flags & CKF_SIGN) && + (mech_info.flags & CKF_VERIFY))) + { + /* + * Check if this slot is capable of encryption, + * decryption, sign, and verify with CKM_RSA_X_509. + */ + rv = pFuncList->C_GetMechanismInfo(current_slot, + CKM_RSA_X_509, &mech_info); + + if (rv == CKR_OK && ((mech_info.flags & CKF_SIGN) && + (mech_info.flags & CKF_VERIFY) && + (mech_info.flags & CKF_ENCRYPT) && + (mech_info.flags & CKF_DECRYPT))) + { + slot_has_rsa = CK_TRUE; + if (mech_info.flags & CKF_VERIFY_RECOVER) + { + slot_has_recover = CK_TRUE; + } + } + } +#endif /* OPENSSL_NO_RSA */ + +#ifndef OPENSSL_NO_DSA + /* + * Check if this slot is capable of signing and + * verifying with CKM_DSA. + */ + rv = pFuncList->C_GetMechanismInfo(current_slot, CKM_DSA, + &mech_info); + if (rv == CKR_OK && ((mech_info.flags & CKF_SIGN) && + (mech_info.flags & CKF_VERIFY))) + { + slot_has_dsa = CK_TRUE; + } + +#endif /* OPENSSL_NO_DSA */ + +#ifndef OPENSSL_NO_DH + /* + * Check if this slot is capable of DH key generataion and + * derivation. + */ + rv = pFuncList->C_GetMechanismInfo(current_slot, + CKM_DH_PKCS_KEY_PAIR_GEN, &mech_info); + + if (rv == CKR_OK && (mech_info.flags & CKF_GENERATE_KEY_PAIR)) + { + rv = pFuncList->C_GetMechanismInfo(current_slot, + CKM_DH_PKCS_DERIVE, &mech_info); + if (rv == CKR_OK && (mech_info.flags & CKF_DERIVE)) + { + slot_has_dh = CK_TRUE; + } + } +#endif /* OPENSSL_NO_DH */ + + if (!found_candidate_slot && + (slot_has_rsa || slot_has_dsa || slot_has_dh)) + { +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, + "%s: potential slot: %d\n", PK11_DBG, current_slot); +#endif /* DEBUG_SLOT_SELECTION */ + best_slot_sofar = current_slot; + pk11_have_rsa = slot_has_rsa; + pk11_have_recover = slot_has_recover; + pk11_have_dsa = slot_has_dsa; + pk11_have_dh = slot_has_dh; + found_candidate_slot = CK_TRUE; + /* + * Cache the flags for later use. We might + * need those if RSA keys by reference feature + * is used. + */ + pubkey_token_flags = token_info.flags; +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, + "%s: setting found_candidate_slot to CK_TRUE\n", + PK11_DBG); + fprintf(stderr, + "%s: best so far slot: %d\n", PK11_DBG, + best_slot_sofar); + fprintf(stderr, "%s: pubkey flags changed to " + "%lu.\n", PK11_DBG, pubkey_token_flags); + } + else + { + fprintf(stderr, + "%s: no rsa/dsa/dh\n", PK11_DBG); + } +#else + } /* if */ +#endif /* DEBUG_SLOT_SELECTION */ + } /* for */ + + if (found_candidate_slot == CK_TRUE) + { + pubkey_SLOTID = best_slot_sofar; + } + + found_candidate_slot = CK_FALSE; + best_slot_sofar = 0; + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: == checking cipher/digest ==\n", PK11_DBG); +#endif /* DEBUG_SLOT_SELECTION */ + + SLOTID = pSlotList[0]; + for (i = 0; i < ulSlotCount; i++) + { +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: checking slot: %d\n", PK11_DBG, i); +#endif /* DEBUG_SLOT_SELECTION */ + + current_slot = pSlotList[i]; + current_slot_n_cipher = 0; + current_slot_n_digest = 0; + (void) memset(local_cipher_nids, 0, sizeof (local_cipher_nids)); + (void) memset(local_digest_nids, 0, sizeof (local_digest_nids)); + + pk11_find_symmetric_ciphers(pFuncList, current_slot, + ¤t_slot_n_cipher, local_cipher_nids); + + pk11_find_digests(pFuncList, current_slot, + ¤t_slot_n_digest, local_digest_nids); + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: current_slot_n_cipher %d\n", PK11_DBG, + current_slot_n_cipher); + fprintf(stderr, "%s: current_slot_n_digest %d\n", PK11_DBG, + current_slot_n_digest); + fprintf(stderr, "%s: best so far cipher/digest slot: %d\n", + PK11_DBG, best_slot_sofar); +#endif /* DEBUG_SLOT_SELECTION */ + + /* + * If the current slot supports more ciphers/digests than + * the previous best one we change the current best to this one, + * otherwise leave it where it is. + */ + if ((current_slot_n_cipher + current_slot_n_digest) > + (slot_n_cipher + slot_n_digest)) + { +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, + "%s: changing best so far slot to %d\n", + PK11_DBG, current_slot); +#endif /* DEBUG_SLOT_SELECTION */ + best_slot_sofar = SLOTID = current_slot; + cipher_count = slot_n_cipher = current_slot_n_cipher; + digest_count = slot_n_digest = current_slot_n_digest; + (void) memcpy(cipher_nids, local_cipher_nids, + sizeof (local_cipher_nids)); + (void) memcpy(digest_nids, local_digest_nids, + sizeof (local_digest_nids)); + } + } + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, + "%s: chosen pubkey slot: %d\n", PK11_DBG, pubkey_SLOTID); + fprintf(stderr, + "%s: chosen rand slot: %d\n", PK11_DBG, rand_SLOTID); + fprintf(stderr, + "%s: chosen cipher/digest slot: %d\n", PK11_DBG, SLOTID); + fprintf(stderr, + "%s: pk11_have_rsa %d\n", PK11_DBG, pk11_have_rsa); + fprintf(stderr, + "%s: pk11_have_recover %d\n", PK11_DBG, pk11_have_recover); + fprintf(stderr, + "%s: pk11_have_dsa %d\n", PK11_DBG, pk11_have_dsa); + fprintf(stderr, + "%s: pk11_have_dh %d\n", PK11_DBG, pk11_have_dh); + fprintf(stderr, + "%s: pk11_have_random %d\n", PK11_DBG, pk11_have_random); + fprintf(stderr, + "%s: cipher_count %d\n", PK11_DBG, cipher_count); + fprintf(stderr, + "%s: digest_count %d\n", PK11_DBG, digest_count); +#endif /* DEBUG_SLOT_SELECTION */ + + if (pSlotList != NULL) + OPENSSL_free(pSlotList); + +#ifdef SOLARIS_HW_SLOT_SELECTION + OPENSSL_free(hw_cnids); + OPENSSL_free(hw_dnids); +#endif /* SOLARIS_HW_SLOT_SELECTION */ + + if (any_slot_found != NULL) + *any_slot_found = 1; + return (1); + } + +static void pk11_get_symmetric_cipher(CK_FUNCTION_LIST_PTR pflist, + int slot_id, CK_MECHANISM_TYPE mech, int *current_slot_n_cipher, + int *local_cipher_nids, int id) + { + CK_MECHANISM_INFO mech_info; + CK_RV rv; + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: checking mech: %x", PK11_DBG, mech); +#endif /* DEBUG_SLOT_SELECTION */ + rv = pflist->C_GetMechanismInfo(slot_id, mech, &mech_info); + + if (rv != CKR_OK) + { +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, " not found\n"); +#endif /* DEBUG_SLOT_SELECTION */ + return; + } + + if ((mech_info.flags & CKF_ENCRYPT) && + (mech_info.flags & CKF_DECRYPT)) + { +#ifdef SOLARIS_HW_SLOT_SELECTION + if (nid_in_table(ciphers[id].nid, hw_cnids)) +#endif /* SOLARIS_HW_SLOT_SELECTION */ + { +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, " usable\n"); +#endif /* DEBUG_SLOT_SELECTION */ + local_cipher_nids[(*current_slot_n_cipher)++] = + ciphers[id].nid; + } +#ifdef SOLARIS_HW_SLOT_SELECTION +#ifdef DEBUG_SLOT_SELECTION + else + { + fprintf(stderr, " rejected, software implementation only\n"); + } +#endif /* DEBUG_SLOT_SELECTION */ +#endif /* SOLARIS_HW_SLOT_SELECTION */ + } +#ifdef DEBUG_SLOT_SELECTION + else + { + fprintf(stderr, " unusable\n"); + } +#endif /* DEBUG_SLOT_SELECTION */ + + return; + } + +static void pk11_get_digest(CK_FUNCTION_LIST_PTR pflist, int slot_id, + CK_MECHANISM_TYPE mech, int *current_slot_n_digest, int *local_digest_nids, + int id) + { + CK_MECHANISM_INFO mech_info; + CK_RV rv; + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: checking mech: %x", PK11_DBG, mech); +#endif /* DEBUG_SLOT_SELECTION */ + rv = pflist->C_GetMechanismInfo(slot_id, mech, &mech_info); + + if (rv != CKR_OK) + { +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, " not found\n"); +#endif /* DEBUG_SLOT_SELECTION */ + return; + } + + if (mech_info.flags & CKF_DIGEST) + { +#ifdef SOLARIS_HW_SLOT_SELECTION + if (nid_in_table(digests[id].nid, hw_dnids)) +#endif /* SOLARIS_HW_SLOT_SELECTION */ + { +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, " usable\n"); +#endif /* DEBUG_SLOT_SELECTION */ + local_digest_nids[(*current_slot_n_digest)++] = + digests[id].nid; + } +#ifdef SOLARIS_HW_SLOT_SELECTION +#ifdef DEBUG_SLOT_SELECTION + else + { + fprintf(stderr, " rejected, software implementation only\n"); + } +#endif /* DEBUG_SLOT_SELECTION */ +#endif /* SOLARIS_HW_SLOT_SELECTION */ + } +#ifdef DEBUG_SLOT_SELECTION + else + { + fprintf(stderr, " unusable\n"); + } +#endif /* DEBUG_SLOT_SELECTION */ + + return; + } + +/* Find what symmetric ciphers this slot supports. */ +static void pk11_find_symmetric_ciphers(CK_FUNCTION_LIST_PTR pflist, + CK_SLOT_ID current_slot, int *current_slot_n_cipher, int *local_cipher_nids) + { + int i; + + for (i = 0; i < PK11_CIPHER_MAX; ++i) + { + pk11_get_symmetric_cipher(pflist, current_slot, + ciphers[i].mech_type, current_slot_n_cipher, + local_cipher_nids, ciphers[i].id); + } + } + +/* Find what digest algorithms this slot supports. */ +static void pk11_find_digests(CK_FUNCTION_LIST_PTR pflist, + CK_SLOT_ID current_slot, int *current_slot_n_digest, int *local_digest_nids) + { + int i; + + for (i = 0; i < PK11_DIGEST_MAX; ++i) + { + pk11_get_digest(pflist, current_slot, digests[i].mech_type, + current_slot_n_digest, local_digest_nids, digests[i].id); + } + } + +#ifdef SOLARIS_HW_SLOT_SELECTION +/* + * It would be great if we could use pkcs11_kernel directly since this library + * offers hardware slots only. That's the easiest way to achieve the situation + * where we use the hardware accelerators when present and OpenSSL native code + * otherwise. That presumes the fact that OpenSSL native code is faster than the + * code in the soft token. It's a logical assumption - Crypto Framework has some + * inherent overhead so going there for the software implementation of a + * mechanism should be logically slower in contrast to the OpenSSL native code, + * presuming that both implementations are of similar speed. For example, the + * soft token for AES is roughly three times slower than OpenSSL for 64 byte + * blocks and still 20% slower for 8KB blocks. So, if we want to ship products + * that use the PKCS#11 engine by default, we must somehow avoid that regression + * on machines without hardware acceleration. That's why switching to the + * pkcs11_kernel library seems like a very good idea. + * + * The problem is that OpenSSL built with SunStudio is roughly 2x slower for + * asymmetric operations (RSA/DSA/DH) than the soft token built with the same + * compiler. That means that if we switched to pkcs11_kernel from the libpkcs11 + * library, we would have had a performance regression on machines without + * hardware acceleration for asymmetric operations for all applications that use + * the PKCS#11 engine. There is one such application - Apache web server since + * it's shipped configured to use the PKCS#11 engine by default. Having said + * that, we can't switch to the pkcs11_kernel library now and have to come with + * a solution that, on non-accelerated machines, uses the OpenSSL native code + * for all symmetric ciphers and digests while it uses the soft token for + * asymmetric operations. + * + * This is the idea: dlopen() pkcs11_kernel directly and find out what + * mechanisms are there. We don't care about duplications (more slots can + * support the same mechanism), we just want to know what mechanisms can be + * possibly supported in hardware on that particular machine. As said before, + * pkcs11_kernel will show you hardware providers only. + * + * Then, we rely on the fact that since we use libpkcs11 library we will find + * the metaslot. When we go through the metaslot's mechanisms for symmetric + * ciphers and digests, we check that any found mechanism is in the table + * created using the pkcs11_kernel library. So, as a result we have two arrays + * of mechanisms that were advertised as supported in hardware which was the + * goal of that whole excercise. Thus, we can use libpkcs11 but avoid soft token + * code for symmetric ciphers and digests. See pk11_choose_slots() for more + * information. + * + * This is Solaris specific code, if SOLARIS_HW_SLOT_SELECTION is not defined + * the code won't be used. + */ +#if defined(__sparcv9) || defined(__x86_64) || defined(__amd64) +static const char pkcs11_kernel[] = "/usr/lib/security/64/pkcs11_kernel.so.1"; +#else +static const char pkcs11_kernel[] = "/usr/lib/security/pkcs11_kernel.so.1"; +#endif + +/* + * Check hardware capabilities of the machines. The output are two lists, + * hw_cnids and hw_dnids, that contain hardware mechanisms found in all hardware + * providers together. They are not sorted and may contain duplicate mechanisms. + */ +static int check_hw_mechanisms(void) + { + int i; + CK_RV rv; + void *handle; + CK_C_GetFunctionList p; + CK_TOKEN_INFO token_info; + CK_ULONG ulSlotCount = 0; + int n_cipher = 0, n_digest = 0; + CK_FUNCTION_LIST_PTR pflist = NULL; + CK_SLOT_ID_PTR pSlotList = NULL_PTR; + int *tmp_hw_cnids = NULL, *tmp_hw_dnids = NULL; + int hw_ctable_size, hw_dtable_size; + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: SOLARIS_HW_SLOT_SELECTION code running\n", + PK11_DBG); +#endif + if ((handle = dlopen(pkcs11_kernel, RTLD_LAZY)) == NULL) + { + PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_DSO_FAILURE); + goto err; + } + + if ((p = (CK_C_GetFunctionList)dlsym(handle, + PK11_GET_FUNCTION_LIST)) == NULL) + { + PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_DSO_FAILURE); + goto err; + } + + /* get the full function list from the loaded library */ + if (p(&pflist) != CKR_OK) + { + PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_DSO_FAILURE); + goto err; + } + + rv = pflist->C_Initialize((CK_VOID_PTR)&pk11_init_args); + if ((rv != CKR_OK) && (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)) + { + PK11err_add_data(PK11_F_CHECK_HW_MECHANISMS, + PK11_R_INITIALIZE, rv); + goto err; + } + + if (pflist->C_GetSlotList(0, NULL_PTR, &ulSlotCount) != CKR_OK) + { + PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_GETSLOTLIST); + goto err; + } + + /* no slots, set the hw mechanism tables as empty */ + if (ulSlotCount == 0) + { +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: no hardware mechanisms found\n", PK11_DBG); +#endif + hw_cnids = OPENSSL_malloc(sizeof (int)); + hw_dnids = OPENSSL_malloc(sizeof (int)); + if (hw_cnids == NULL || hw_dnids == NULL) + { + PK11err(PK11_F_CHECK_HW_MECHANISMS, + PK11_R_MALLOC_FAILURE); + return (0); + } + /* this means empty tables */ + hw_cnids[0] = NID_undef; + hw_dnids[0] = NID_undef; + return (1); + } + + pSlotList = OPENSSL_malloc(ulSlotCount * sizeof (CK_SLOT_ID)); + if (pSlotList == NULL) + { + PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_MALLOC_FAILURE); + goto err; + } + + /* Get the slot list for processing */ + if (pflist->C_GetSlotList(0, pSlotList, &ulSlotCount) != CKR_OK) + { + PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_GETSLOTLIST); + goto err; + } + + /* + * We don't care about duplicit mechanisms in multiple slots and also + * reserve one slot for the terminal NID_undef which we use to stop the + * search. + */ + hw_ctable_size = ulSlotCount * PK11_CIPHER_MAX + 1; + hw_dtable_size = ulSlotCount * PK11_DIGEST_MAX + 1; + tmp_hw_cnids = OPENSSL_malloc(hw_ctable_size * sizeof (int)); + tmp_hw_dnids = OPENSSL_malloc(hw_dtable_size * sizeof (int)); + if (tmp_hw_cnids == NULL || tmp_hw_dnids == NULL) + { + PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_MALLOC_FAILURE); + goto err; + } + + /* + * Do not use memset since we should not rely on the fact that NID_undef + * is zero now. + */ + for (i = 0; i < hw_ctable_size; ++i) + tmp_hw_cnids[i] = NID_undef; + for (i = 0; i < hw_dtable_size; ++i) + tmp_hw_dnids[i] = NID_undef; + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: provider: %s\n", PK11_DBG, pkcs11_kernel); + fprintf(stderr, "%s: found %d hardware slots\n", PK11_DBG, ulSlotCount); + fprintf(stderr, "%s: now looking for mechs supported in hw\n", + PK11_DBG); +#endif /* DEBUG_SLOT_SELECTION */ + + for (i = 0; i < ulSlotCount; i++) + { + if (pflist->C_GetTokenInfo(pSlotList[i], &token_info) != CKR_OK) + continue; + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: token label: %.32s\n", PK11_DBG, token_info.label); +#endif /* DEBUG_SLOT_SELECTION */ + + /* + * We are filling the hw mech tables here. Global tables are + * still NULL so all mechanisms are put into tmp tables. + */ + pk11_find_symmetric_ciphers(pflist, pSlotList[i], + &n_cipher, tmp_hw_cnids); + pk11_find_digests(pflist, pSlotList[i], + &n_digest, tmp_hw_dnids); + } + + /* + * Since we are part of a library (libcrypto.so), calling this function + * may have side-effects. Also, C_Finalize() is triggered by + * dlclose(3C). + */ +#if 0 + pflist->C_Finalize(NULL); +#endif + OPENSSL_free(pSlotList); + (void) dlclose(handle); + hw_cnids = tmp_hw_cnids; + hw_dnids = tmp_hw_dnids; + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: hw mechs check complete\n", PK11_DBG); +#endif /* DEBUG_SLOT_SELECTION */ + return (1); + +err: + if (pSlotList != NULL) + OPENSSL_free(pSlotList); + if (tmp_hw_cnids != NULL) + OPENSSL_free(tmp_hw_cnids); + if (tmp_hw_dnids != NULL) + OPENSSL_free(tmp_hw_dnids); + + return (0); + } + +/* + * Check presence of a NID in the table of NIDs. The table may be NULL (i.e., + * non-existent). + */ +static int nid_in_table(int nid, int *nid_table) + { + int i = 0; + + /* + * a special case. NULL means that we are initializing a new + * table. + */ + if (nid_table == NULL) + return (1); + + /* + * the table is never full, there is always at least one + * NID_undef. + */ + while (nid_table[i] != NID_undef) + { + if (nid_table[i++] == nid) + { +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, " (NID %d in hw table, idx %d)", nid, i); +#endif /* DEBUG_SLOT_SELECTION */ + return (1); + } + } + + return (0); + } +#endif /* SOLARIS_HW_SLOT_SELECTION */ + +#endif /* OPENSSL_NO_HW_PK11CA */ +#endif /* OPENSSL_NO_HW_PK11 */ +#endif /* OPENSSL_NO_HW */ Index: openssl/crypto/engine/hw_pk11_err.c diff -u /dev/null openssl/crypto/engine/hw_pk11_err.c:1.5 --- /dev/null Mon Jun 13 15:55:26 2016 +++ openssl/crypto/engine/hw_pk11_err.c Tue Jun 14 00:43:26 2011 @@ -0,0 +1,288 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* crypto/engine/hw_pk11_err.c */ +/* + * This product includes software developed by the OpenSSL Project for + * use in the OpenSSL Toolkit (http://www.openssl.org/). + * + * This project also referenced hw_pkcs11-0.9.7b.patch written by + * Afchine Madjlessi. + */ +/* + * ==================================================================== + * Copyright (c) 2000-2001 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include +#include +#include "hw_pk11_err.h" + +/* BEGIN ERROR CODES */ +#ifndef OPENSSL_NO_ERR +static ERR_STRING_DATA pk11_str_functs[]= +{ +{ ERR_PACK(0, PK11_F_INIT, 0), "PK11_INIT"}, +{ ERR_PACK(0, PK11_F_FINISH, 0), "PK11_FINISH"}, +{ ERR_PACK(0, PK11_F_DESTROY, 0), "PK11_DESTROY"}, +{ ERR_PACK(0, PK11_F_CTRL, 0), "PK11_CTRL"}, +{ ERR_PACK(0, PK11_F_RSA_INIT, 0), "PK11_RSA_INIT"}, +{ ERR_PACK(0, PK11_F_RSA_FINISH, 0), "PK11_RSA_FINISH"}, +{ ERR_PACK(0, PK11_F_GET_PUB_RSA_KEY, 0), "PK11_GET_PUB_RSA_KEY"}, +{ ERR_PACK(0, PK11_F_GET_PRIV_RSA_KEY, 0), "PK11_GET_PRIV_RSA_KEY"}, +{ ERR_PACK(0, PK11_F_RSA_GEN_KEY, 0), "PK11_RSA_GEN_KEY"}, +{ ERR_PACK(0, PK11_F_RSA_PUB_ENC, 0), "PK11_RSA_PUB_ENC"}, +{ ERR_PACK(0, PK11_F_RSA_PRIV_ENC, 0), "PK11_RSA_PRIV_ENC"}, +{ ERR_PACK(0, PK11_F_RSA_PUB_DEC, 0), "PK11_RSA_PUB_DEC"}, +{ ERR_PACK(0, PK11_F_RSA_PRIV_DEC, 0), "PK11_RSA_PRIV_DEC"}, +{ ERR_PACK(0, PK11_F_RSA_SIGN, 0), "PK11_RSA_SIGN"}, +{ ERR_PACK(0, PK11_F_RSA_VERIFY, 0), "PK11_RSA_VERIFY"}, +{ ERR_PACK(0, PK11_F_RAND_ADD, 0), "PK11_RAND_ADD"}, +{ ERR_PACK(0, PK11_F_RAND_BYTES, 0), "PK11_RAND_BYTES"}, +{ ERR_PACK(0, PK11_F_GET_SESSION, 0), "PK11_GET_SESSION"}, +{ ERR_PACK(0, PK11_F_FREE_SESSION, 0), "PK11_FREE_SESSION"}, +{ ERR_PACK(0, PK11_F_LOAD_PUBKEY, 0), "PK11_LOAD_PUBKEY"}, +{ ERR_PACK(0, PK11_F_LOAD_PRIVKEY, 0), "PK11_LOAD_PRIV_KEY"}, +{ ERR_PACK(0, PK11_F_RSA_PUB_ENC_LOW, 0), "PK11_RSA_PUB_ENC_LOW"}, +{ ERR_PACK(0, PK11_F_RSA_PRIV_ENC_LOW, 0), "PK11_RSA_PRIV_ENC_LOW"}, +{ ERR_PACK(0, PK11_F_RSA_PUB_DEC_LOW, 0), "PK11_RSA_PUB_DEC_LOW"}, +{ ERR_PACK(0, PK11_F_RSA_PRIV_DEC_LOW, 0), "PK11_RSA_PRIV_DEC_LOW"}, +{ ERR_PACK(0, PK11_F_DSA_SIGN, 0), "PK11_DSA_SIGN"}, +{ ERR_PACK(0, PK11_F_DSA_VERIFY, 0), "PK11_DSA_VERIFY"}, +{ ERR_PACK(0, PK11_F_DSA_INIT, 0), "PK11_DSA_INIT"}, +{ ERR_PACK(0, PK11_F_DSA_FINISH, 0), "PK11_DSA_FINISH"}, +{ ERR_PACK(0, PK11_F_GET_PUB_DSA_KEY, 0), "PK11_GET_PUB_DSA_KEY"}, +{ ERR_PACK(0, PK11_F_GET_PRIV_DSA_KEY, 0), "PK11_GET_PRIV_DSA_KEY"}, +{ ERR_PACK(0, PK11_F_DH_INIT, 0), "PK11_DH_INIT"}, +{ ERR_PACK(0, PK11_F_DH_FINISH, 0), "PK11_DH_FINISH"}, +{ ERR_PACK(0, PK11_F_MOD_EXP_DH, 0), "PK11_MOD_EXP_DH"}, +{ ERR_PACK(0, PK11_F_GET_DH_KEY, 0), "PK11_GET_DH_KEY"}, +{ ERR_PACK(0, PK11_F_FREE_ALL_SESSIONS, 0), "PK11_FREE_ALL_SESSIONS"}, +{ ERR_PACK(0, PK11_F_SETUP_SESSION, 0), "PK11_SETUP_SESSION"}, +{ ERR_PACK(0, PK11_F_DESTROY_OBJECT, 0), "PK11_DESTROY_OBJECT"}, +{ ERR_PACK(0, PK11_F_CIPHER_INIT, 0), "PK11_CIPHER_INIT"}, +{ ERR_PACK(0, PK11_F_CIPHER_DO_CIPHER, 0), "PK11_CIPHER_DO_CIPHER"}, +{ ERR_PACK(0, PK11_F_GET_CIPHER_KEY, 0), "PK11_GET_CIPHER_KEY"}, +{ ERR_PACK(0, PK11_F_DIGEST_INIT, 0), "PK11_DIGEST_INIT"}, +{ ERR_PACK(0, PK11_F_DIGEST_UPDATE, 0), "PK11_DIGEST_UPDATE"}, +{ ERR_PACK(0, PK11_F_DIGEST_FINAL, 0), "PK11_DIGEST_FINAL"}, +{ ERR_PACK(0, PK11_F_CHOOSE_SLOT, 0), "PK11_CHOOSE_SLOT"}, +{ ERR_PACK(0, PK11_F_CIPHER_FINAL, 0), "PK11_CIPHER_FINAL"}, +{ ERR_PACK(0, PK11_F_LIBRARY_INIT, 0), "PK11_LIBRARY_INIT"}, +{ ERR_PACK(0, PK11_F_LOAD, 0), "ENGINE_LOAD_PK11"}, +{ ERR_PACK(0, PK11_F_DH_GEN_KEY, 0), "PK11_DH_GEN_KEY"}, +{ ERR_PACK(0, PK11_F_DH_COMP_KEY, 0), "PK11_DH_COMP_KEY"}, +{ ERR_PACK(0, PK11_F_DIGEST_COPY, 0), "PK11_DIGEST_COPY"}, +{ ERR_PACK(0, PK11_F_CIPHER_CLEANUP, 0), "PK11_CIPHER_CLEANUP"}, +{ ERR_PACK(0, PK11_F_ACTIVE_ADD, 0), "PK11_ACTIVE_ADD"}, +{ ERR_PACK(0, PK11_F_ACTIVE_DELETE, 0), "PK11_ACTIVE_DELETE"}, +{ ERR_PACK(0, PK11_F_CHECK_HW_MECHANISMS, 0), "PK11_CHECK_HW_MECHANISMS"}, +{ ERR_PACK(0, PK11_F_INIT_SYMMETRIC, 0), "PK11_INIT_SYMMETRIC"}, +{ ERR_PACK(0, PK11_F_ADD_AES_CTR_NIDS, 0), "PK11_ADD_AES_CTR_NIDS"}, +{ ERR_PACK(0, PK11_F_INIT_ALL_LOCKS, 0), "PK11_INIT_ALL_LOCKS"}, +{ ERR_PACK(0, PK11_F_RETURN_SESSION, 0), "PK11_RETURN_SESSION"}, +{ ERR_PACK(0, PK11_F_GET_PIN, 0), "PK11_GET_PIN"}, +{ ERR_PACK(0, PK11_F_FIND_ONE_OBJECT, 0), "PK11_FIND_ONE_OBJECT"}, +{ ERR_PACK(0, PK11_F_CHECK_TOKEN_ATTRS, 0), "PK11_CHECK_TOKEN_ATTRS"}, +{ ERR_PACK(0, PK11_F_CACHE_PIN, 0), "PK11_CACHE_PIN"}, +{ ERR_PACK(0, PK11_F_MLOCK_PIN_IN_MEMORY, 0), "PK11_MLOCK_PIN_IN_MEMORY"}, +{ ERR_PACK(0, PK11_F_TOKEN_LOGIN, 0), "PK11_TOKEN_LOGIN"}, +{ ERR_PACK(0, PK11_F_TOKEN_RELOGIN, 0), "PK11_TOKEN_RELOGIN"}, +{ ERR_PACK(0, PK11_F_RUN_ASKPASS, 0), "PK11_F_RUN_ASKPASS"}, +{ 0, NULL} +}; + +static ERR_STRING_DATA pk11_str_reasons[]= +{ +{ PK11_R_ALREADY_LOADED, "PKCS#11 DSO already loaded"}, +{ PK11_R_DSO_FAILURE, "unable to load PKCS#11 DSO"}, +{ PK11_R_NOT_LOADED, "PKCS#11 DSO not loaded"}, +{ PK11_R_PASSED_NULL_PARAMETER, "null parameter passed"}, +{ PK11_R_COMMAND_NOT_IMPLEMENTED, "command not implemented"}, +{ PK11_R_INITIALIZE, "C_Initialize failed"}, +{ PK11_R_FINALIZE, "C_Finalize failed"}, +{ PK11_R_GETINFO, "C_GetInfo faile"}, +{ PK11_R_GETSLOTLIST, "C_GetSlotList failed"}, +{ PK11_R_NO_MODULUS_OR_NO_EXPONENT, "no modulus or no exponent"}, +{ PK11_R_ATTRIBUT_SENSITIVE_OR_INVALID, "attr sensitive or invalid"}, +{ PK11_R_GETATTRIBUTVALUE, "C_GetAttributeValue failed"}, +{ PK11_R_NO_MODULUS, "no modulus"}, +{ PK11_R_NO_EXPONENT, "no exponent"}, +{ PK11_R_FINDOBJECTSINIT, "C_FindObjectsInit failed"}, +{ PK11_R_FINDOBJECTS, "C_FindObjects failed"}, +{ PK11_R_FINDOBJECTSFINAL, "C_FindObjectsFinal failed"}, +{ PK11_R_CREATEOBJECT, "C_CreateObject failed"}, +{ PK11_R_DESTROYOBJECT, "C_DestroyObject failed"}, +{ PK11_R_OPENSESSION, "C_OpenSession failed"}, +{ PK11_R_CLOSESESSION, "C_CloseSession failed"}, +{ PK11_R_ENCRYPTINIT, "C_EncryptInit failed"}, +{ PK11_R_ENCRYPT, "C_Encrypt failed"}, +{ PK11_R_SIGNINIT, "C_SignInit failed"}, +{ PK11_R_SIGN, "C_Sign failed"}, +{ PK11_R_DECRYPTINIT, "C_DecryptInit failed"}, +{ PK11_R_DECRYPT, "C_Decrypt failed"}, +{ PK11_R_VERIFYINIT, "C_VerifyRecover failed"}, +{ PK11_R_VERIFY, "C_Verify failed"}, +{ PK11_R_VERIFYRECOVERINIT, "C_VerifyRecoverInit failed"}, +{ PK11_R_VERIFYRECOVER, "C_VerifyRecover failed"}, +{ PK11_R_GEN_KEY, "C_GenerateKeyPair failed"}, +{ PK11_R_SEEDRANDOM, "C_SeedRandom failed"}, +{ PK11_R_GENERATERANDOM, "C_GenerateRandom failed"}, +{ PK11_R_INVALID_MESSAGE_LENGTH, "invalid message length"}, +{ PK11_R_UNKNOWN_ALGORITHM_TYPE, "unknown algorithm type"}, +{ PK11_R_UNKNOWN_ASN1_OBJECT_ID, "unknown asn1 onject id"}, +{ PK11_R_UNKNOWN_PADDING_TYPE, "unknown padding type"}, +{ PK11_R_PADDING_CHECK_FAILED, "padding check failed"}, +{ PK11_R_DIGEST_TOO_BIG, "digest too big"}, +{ PK11_R_MALLOC_FAILURE, "malloc failure"}, +{ PK11_R_CTRL_COMMAND_NOT_IMPLEMENTED, "ctl command not implemented"}, +{ PK11_R_DATA_GREATER_THAN_MOD_LEN, "data is bigger than mod"}, +{ PK11_R_DATA_TOO_LARGE_FOR_MODULUS, "data is too larger for mod"}, +{ PK11_R_MISSING_KEY_COMPONENT, "a dsa component is missing"}, +{ PK11_R_INVALID_SIGNATURE_LENGTH, "invalid signature length"}, +{ PK11_R_INVALID_DSA_SIGNATURE_R, "missing r in dsa verify"}, +{ PK11_R_INVALID_DSA_SIGNATURE_S, "missing s in dsa verify"}, +{ PK11_R_INCONSISTENT_KEY, "inconsistent key type"}, +{ PK11_R_ENCRYPTUPDATE, "C_EncryptUpdate failed"}, +{ PK11_R_DECRYPTUPDATE, "C_DecryptUpdate failed"}, +{ PK11_R_DIGESTINIT, "C_DigestInit failed"}, +{ PK11_R_DIGESTUPDATE, "C_DigestUpdate failed"}, +{ PK11_R_DIGESTFINAL, "C_DigestFinal failed"}, +{ PK11_R_ENCRYPTFINAL, "C_EncryptFinal failed"}, +{ PK11_R_DECRYPTFINAL, "C_DecryptFinal failed"}, +{ PK11_R_NO_PRNG_SUPPORT, "Slot does not support PRNG"}, +{ PK11_R_GETTOKENINFO, "C_GetTokenInfo failed"}, +{ PK11_R_DERIVEKEY, "C_DeriveKey failed"}, +{ PK11_R_GET_OPERATION_STATE, "C_GetOperationState failed"}, +{ PK11_R_SET_OPERATION_STATE, "C_SetOperationState failed"}, +{ PK11_R_INVALID_HANDLE, "invalid PKCS#11 object handle"}, +{ PK11_R_KEY_OR_IV_LEN_PROBLEM, "IV or key length incorrect"}, +{ PK11_R_INVALID_OPERATION_TYPE, "invalid operation type"}, +{ PK11_R_ADD_NID_FAILED, "failed to add NID" }, +{ PK11_R_ATFORK_FAILED, "atfork() failed" }, +{ PK11_R_TOKEN_LOGIN_FAILED, "C_Login() failed on token" }, +{ PK11_R_MORE_THAN_ONE_OBJECT_FOUND, "more than one object found" }, +{ PK11_R_INVALID_PKCS11_URI, "pkcs11 URI provided is invalid" }, +{ PK11_R_COULD_NOT_READ_PIN, "could not read PIN from terminal" }, +{ PK11_R_PIN_NOT_READ_FROM_COMMAND, "PIN not read from external command" }, +{ PK11_R_COULD_NOT_OPEN_COMMAND, "could not popen() dialog command" }, +{ PK11_R_PIPE_FAILED, "pipe() failed" }, +{ PK11_R_BAD_PASSPHRASE_SPEC, "bad passphrasedialog specification" }, +{ PK11_R_TOKEN_NOT_INITIALIZED, "token not initialized" }, +{ PK11_R_TOKEN_PIN_NOT_SET, "token PIN required but not set" }, +{ PK11_R_TOKEN_PIN_NOT_PROVIDED, "token PIN required but not provided" }, +{ PK11_R_MISSING_OBJECT_LABEL, "missing mandatory 'object' keyword" }, +{ PK11_R_TOKEN_ATTRS_DO_NOT_MATCH, "token attrs provided do not match" }, +{ PK11_R_PRIV_KEY_NOT_FOUND, "private key not found in keystore" }, +{ PK11_R_NO_OBJECT_FOUND, "specified object not found" }, +{ PK11_R_PIN_CACHING_POLICY_INVALID, "PIN set but caching policy invalid" }, +{ PK11_R_SYSCONF_FAILED, "sysconf() failed" }, +{ PK11_R_MMAP_FAILED, "mmap() failed" }, +{ PK11_R_PRIV_PROC_LOCK_MEMORY_MISSING, "PROC_LOCK_MEMORY privilege missing" }, +{ PK11_R_MLOCK_FAILED, "mlock() failed" }, +{ PK11_R_FORK_FAILED, "fork() failed" }, +{ 0, NULL} +}; +#endif /* OPENSSL_NO_ERR */ + +static int pk11_lib_error_code = 0; +static int pk11_error_init = 1; + +static void +ERR_load_pk11_strings(void) + { + if (pk11_lib_error_code == 0) + pk11_lib_error_code = ERR_get_next_error_library(); + + if (pk11_error_init) + { + pk11_error_init = 0; +#ifndef OPENSSL_NO_ERR + ERR_load_strings(pk11_lib_error_code, pk11_str_functs); + ERR_load_strings(pk11_lib_error_code, pk11_str_reasons); +#endif + } +} + +static void +ERR_unload_pk11_strings(void) + { + if (pk11_error_init == 0) + { +#ifndef OPENSSL_NO_ERR + ERR_unload_strings(pk11_lib_error_code, pk11_str_functs); + ERR_unload_strings(pk11_lib_error_code, pk11_str_reasons); +#endif + pk11_error_init = 1; + } +} + +void +ERR_pk11_error(int function, int reason, char *file, int line) +{ + if (pk11_lib_error_code == 0) + pk11_lib_error_code = ERR_get_next_error_library(); + ERR_PUT_error(pk11_lib_error_code, function, reason, file, line); +} + +void +PK11err_add_data(int function, int reason, CK_RV rv) +{ + char tmp_buf[20]; + + PK11err(function, reason); + (void) BIO_snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); + ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); +} Index: openssl/crypto/engine/hw_pk11_err.h diff -u /dev/null openssl/crypto/engine/hw_pk11_err.h:1.13 --- /dev/null Mon Jun 13 15:55:26 2016 +++ openssl/crypto/engine/hw_pk11_err.h Fri Oct 4 14:04:20 2013 @@ -0,0 +1,440 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * This product includes software developed by the OpenSSL Project for + * use in the OpenSSL Toolkit (http://www.openssl.org/). + * + * This project also referenced hw_pkcs11-0.9.7b.patch written by + * Afchine Madjlessi. + */ +/* + * ==================================================================== + * Copyright (c) 2000-2001 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#ifndef HW_PK11_ERR_H +#define HW_PK11_ERR_H + +void ERR_pk11_error(int function, int reason, char *file, int line); +void PK11err_add_data(int function, int reason, CK_RV rv); +#define PK11err(f, r) ERR_pk11_error((f), (r), __FILE__, __LINE__) + +/* Error codes for the PK11 functions. */ + +/* Function codes. */ + +#define PK11_F_INIT 100 +#define PK11_F_FINISH 101 +#define PK11_F_DESTROY 102 +#define PK11_F_CTRL 103 +#define PK11_F_RSA_INIT 104 +#define PK11_F_RSA_FINISH 105 +#define PK11_F_GET_PUB_RSA_KEY 106 +#define PK11_F_GET_PRIV_RSA_KEY 107 +#define PK11_F_RSA_GEN_KEY 108 +#define PK11_F_RSA_PUB_ENC 109 +#define PK11_F_RSA_PRIV_ENC 110 +#define PK11_F_RSA_PUB_DEC 111 +#define PK11_F_RSA_PRIV_DEC 112 +#define PK11_F_RSA_SIGN 113 +#define PK11_F_RSA_VERIFY 114 +#define PK11_F_RAND_ADD 115 +#define PK11_F_RAND_BYTES 116 +#define PK11_F_GET_SESSION 117 +#define PK11_F_FREE_SESSION 118 +#define PK11_F_LOAD_PUBKEY 119 +#define PK11_F_LOAD_PRIVKEY 120 +#define PK11_F_RSA_PUB_ENC_LOW 121 +#define PK11_F_RSA_PRIV_ENC_LOW 122 +#define PK11_F_RSA_PUB_DEC_LOW 123 +#define PK11_F_RSA_PRIV_DEC_LOW 124 +#define PK11_F_DSA_SIGN 125 +#define PK11_F_DSA_VERIFY 126 +#define PK11_F_DSA_INIT 127 +#define PK11_F_DSA_FINISH 128 +#define PK11_F_GET_PUB_DSA_KEY 129 +#define PK11_F_GET_PRIV_DSA_KEY 130 +#define PK11_F_DH_INIT 131 +#define PK11_F_DH_FINISH 132 +#define PK11_F_MOD_EXP_DH 133 +#define PK11_F_GET_DH_KEY 134 +#define PK11_F_FREE_ALL_SESSIONS 135 +#define PK11_F_SETUP_SESSION 136 +#define PK11_F_DESTROY_OBJECT 137 +#define PK11_F_CIPHER_INIT 138 +#define PK11_F_CIPHER_DO_CIPHER 139 +#define PK11_F_GET_CIPHER_KEY 140 +#define PK11_F_DIGEST_INIT 141 +#define PK11_F_DIGEST_UPDATE 142 +#define PK11_F_DIGEST_FINAL 143 +#define PK11_F_CHOOSE_SLOT 144 +#define PK11_F_CIPHER_FINAL 145 +#define PK11_F_LIBRARY_INIT 146 +#define PK11_F_LOAD 147 +#define PK11_F_DH_GEN_KEY 148 +#define PK11_F_DH_COMP_KEY 149 +#define PK11_F_DIGEST_COPY 150 +#define PK11_F_CIPHER_CLEANUP 151 +#define PK11_F_ACTIVE_ADD 152 +#define PK11_F_ACTIVE_DELETE 153 +#define PK11_F_CHECK_HW_MECHANISMS 154 +#define PK11_F_INIT_SYMMETRIC 155 +#define PK11_F_ADD_AES_CTR_NIDS 156 +#define PK11_F_INIT_ALL_LOCKS 157 +#define PK11_F_RETURN_SESSION 158 +#define PK11_F_GET_PIN 159 +#define PK11_F_FIND_ONE_OBJECT 160 +#define PK11_F_CHECK_TOKEN_ATTRS 161 +#define PK11_F_CACHE_PIN 162 +#define PK11_F_MLOCK_PIN_IN_MEMORY 163 +#define PK11_F_TOKEN_LOGIN 164 +#define PK11_F_TOKEN_RELOGIN 165 +#define PK11_F_RUN_ASKPASS 166 + +/* Reason codes. */ +#define PK11_R_ALREADY_LOADED 100 +#define PK11_R_DSO_FAILURE 101 +#define PK11_R_NOT_LOADED 102 +#define PK11_R_PASSED_NULL_PARAMETER 103 +#define PK11_R_COMMAND_NOT_IMPLEMENTED 104 +#define PK11_R_INITIALIZE 105 +#define PK11_R_FINALIZE 106 +#define PK11_R_GETINFO 107 +#define PK11_R_GETSLOTLIST 108 +#define PK11_R_NO_MODULUS_OR_NO_EXPONENT 109 +#define PK11_R_ATTRIBUT_SENSITIVE_OR_INVALID 110 +#define PK11_R_GETATTRIBUTVALUE 111 +#define PK11_R_NO_MODULUS 112 +#define PK11_R_NO_EXPONENT 113 +#define PK11_R_FINDOBJECTSINIT 114 +#define PK11_R_FINDOBJECTS 115 +#define PK11_R_FINDOBJECTSFINAL 116 +#define PK11_R_CREATEOBJECT 118 +#define PK11_R_DESTROYOBJECT 119 +#define PK11_R_OPENSESSION 120 +#define PK11_R_CLOSESESSION 121 +#define PK11_R_ENCRYPTINIT 122 +#define PK11_R_ENCRYPT 123 +#define PK11_R_SIGNINIT 124 +#define PK11_R_SIGN 125 +#define PK11_R_DECRYPTINIT 126 +#define PK11_R_DECRYPT 127 +#define PK11_R_VERIFYINIT 128 +#define PK11_R_VERIFY 129 +#define PK11_R_VERIFYRECOVERINIT 130 +#define PK11_R_VERIFYRECOVER 131 +#define PK11_R_GEN_KEY 132 +#define PK11_R_SEEDRANDOM 133 +#define PK11_R_GENERATERANDOM 134 +#define PK11_R_INVALID_MESSAGE_LENGTH 135 +#define PK11_R_UNKNOWN_ALGORITHM_TYPE 136 +#define PK11_R_UNKNOWN_ASN1_OBJECT_ID 137 +#define PK11_R_UNKNOWN_PADDING_TYPE 138 +#define PK11_R_PADDING_CHECK_FAILED 139 +#define PK11_R_DIGEST_TOO_BIG 140 +#define PK11_R_MALLOC_FAILURE 141 +#define PK11_R_CTRL_COMMAND_NOT_IMPLEMENTED 142 +#define PK11_R_DATA_GREATER_THAN_MOD_LEN 143 +#define PK11_R_DATA_TOO_LARGE_FOR_MODULUS 144 +#define PK11_R_MISSING_KEY_COMPONENT 145 +#define PK11_R_INVALID_SIGNATURE_LENGTH 146 +#define PK11_R_INVALID_DSA_SIGNATURE_R 147 +#define PK11_R_INVALID_DSA_SIGNATURE_S 148 +#define PK11_R_INCONSISTENT_KEY 149 +#define PK11_R_ENCRYPTUPDATE 150 +#define PK11_R_DECRYPTUPDATE 151 +#define PK11_R_DIGESTINIT 152 +#define PK11_R_DIGESTUPDATE 153 +#define PK11_R_DIGESTFINAL 154 +#define PK11_R_ENCRYPTFINAL 155 +#define PK11_R_DECRYPTFINAL 156 +#define PK11_R_NO_PRNG_SUPPORT 157 +#define PK11_R_GETTOKENINFO 158 +#define PK11_R_DERIVEKEY 159 +#define PK11_R_GET_OPERATION_STATE 160 +#define PK11_R_SET_OPERATION_STATE 161 +#define PK11_R_INVALID_HANDLE 162 +#define PK11_R_KEY_OR_IV_LEN_PROBLEM 163 +#define PK11_R_INVALID_OPERATION_TYPE 164 +#define PK11_R_ADD_NID_FAILED 165 +#define PK11_R_ATFORK_FAILED 166 + +#define PK11_R_TOKEN_LOGIN_FAILED 167 +#define PK11_R_MORE_THAN_ONE_OBJECT_FOUND 168 +#define PK11_R_INVALID_PKCS11_URI 169 +#define PK11_R_COULD_NOT_READ_PIN 170 +#define PK11_R_COULD_NOT_OPEN_COMMAND 171 +#define PK11_R_PIPE_FAILED 172 +#define PK11_R_PIN_NOT_READ_FROM_COMMAND 173 +#define PK11_R_BAD_PASSPHRASE_SPEC 174 +#define PK11_R_TOKEN_NOT_INITIALIZED 175 +#define PK11_R_TOKEN_PIN_NOT_SET 176 +#define PK11_R_TOKEN_PIN_NOT_PROVIDED 177 +#define PK11_R_MISSING_OBJECT_LABEL 178 +#define PK11_R_TOKEN_ATTRS_DO_NOT_MATCH 179 +#define PK11_R_PRIV_KEY_NOT_FOUND 180 +#define PK11_R_NO_OBJECT_FOUND 181 +#define PK11_R_PIN_CACHING_POLICY_INVALID 182 +#define PK11_R_SYSCONF_FAILED 183 +#define PK11_R_MMAP_FAILED 183 +#define PK11_R_PRIV_PROC_LOCK_MEMORY_MISSING 184 +#define PK11_R_MLOCK_FAILED 185 +#define PK11_R_FORK_FAILED 186 + +/* max byte length of a symetric key we support */ +#define PK11_KEY_LEN_MAX 32 + +#ifdef NOPTHREADS +/* + * CRYPTO_LOCK_PK11_ENGINE lock is primarily used for the protection of the + * free_session list and active_list but generally serves as a global + * per-process lock for the whole engine. + * + * We reuse CRYPTO_LOCK_EC lock (which is defined in OpenSSL for EC method) as + * the global engine lock. This is not optimal w.r.t. performance but + * it's safe. + */ +#define CRYPTO_LOCK_PK11_ENGINE CRYPTO_LOCK_EC +#endif + +/* + * This structure encapsulates all reusable information for a PKCS#11 + * session. A list of these objects is created on behalf of the + * calling application using an on-demand method. Each operation + * type (see PK11_OPTYPE below) has its own per-process list. + * Each of the lists is basically a cache for faster PKCS#11 object + * access to avoid expensive C_Find{,Init,Final}Object() calls. + * + * When a new request comes in, an object will be taken from the list + * (if there is one) or a new one is created to handle the request + * (if the list is empty). See pk11_get_session() on how it is done. + */ +typedef struct PK11_st_SESSION + { + struct PK11_st_SESSION *next; + CK_SESSION_HANDLE session; /* PK11 session handle */ + pid_t pid; /* Current process ID */ + CK_BBOOL pub_persistent; /* is pub key in keystore? */ + CK_BBOOL priv_persistent;/* is priv key in keystore? */ + union + { +#ifndef OPENSSL_NO_RSA + struct + { + CK_OBJECT_HANDLE rsa_pub_key; /* pub handle */ + CK_OBJECT_HANDLE rsa_priv_key; /* priv handle */ + RSA *rsa_pub; /* pub key addr */ + BIGNUM *rsa_n_num; /* pub modulus */ + BIGNUM *rsa_e_num; /* pub exponent */ + RSA *rsa_priv; /* priv key addr */ + BIGNUM *rsa_pn_num; /* pub modulus */ + BIGNUM *rsa_pe_num; /* pub exponent */ + BIGNUM *rsa_d_num; /* priv exponent */ + } u_RSA; +#endif /* OPENSSL_NO_RSA */ +#ifndef OPENSSL_NO_DSA + struct + { + CK_OBJECT_HANDLE dsa_pub_key; /* pub handle */ + CK_OBJECT_HANDLE dsa_priv_key; /* priv handle */ + DSA *dsa_pub; /* pub key addr */ + BIGNUM *dsa_pub_num; /* pub key */ + DSA *dsa_priv; /* priv key addr */ + BIGNUM *dsa_priv_num; /* priv key */ + } u_DSA; +#endif /* OPENSSL_NO_DSA */ +#ifndef OPENSSL_NO_DH + struct + { + CK_OBJECT_HANDLE dh_key; /* key handle */ + DH *dh; /* dh key addr */ + BIGNUM *dh_priv_num; /* priv dh key */ + } u_DH; +#endif /* OPENSSL_NO_DH */ + struct + { + CK_OBJECT_HANDLE cipher_key; /* key handle */ + unsigned char key[PK11_KEY_LEN_MAX]; + int key_len; /* priv key len */ + int encrypt; /* 1/0 enc/decr */ + } u_cipher; + } opdata_u; + } PK11_SESSION; + +#define opdata_rsa_pub_key opdata_u.u_RSA.rsa_pub_key +#define opdata_rsa_priv_key opdata_u.u_RSA.rsa_priv_key +#define opdata_rsa_pub opdata_u.u_RSA.rsa_pub +#define opdata_rsa_priv opdata_u.u_RSA.rsa_priv +#define opdata_rsa_n_num opdata_u.u_RSA.rsa_n_num +#define opdata_rsa_e_num opdata_u.u_RSA.rsa_e_num +#define opdata_rsa_pn_num opdata_u.u_RSA.rsa_pn_num +#define opdata_rsa_pe_num opdata_u.u_RSA.rsa_pe_num +#define opdata_rsa_d_num opdata_u.u_RSA.rsa_d_num +#define opdata_dsa_pub_key opdata_u.u_DSA.dsa_pub_key +#define opdata_dsa_priv_key opdata_u.u_DSA.dsa_priv_key +#define opdata_dsa_pub opdata_u.u_DSA.dsa_pub +#define opdata_dsa_pub_num opdata_u.u_DSA.dsa_pub_num +#define opdata_dsa_priv opdata_u.u_DSA.dsa_priv +#define opdata_dsa_priv_num opdata_u.u_DSA.dsa_priv_num +#define opdata_dh_key opdata_u.u_DH.dh_key +#define opdata_dh opdata_u.u_DH.dh +#define opdata_dh_priv_num opdata_u.u_DH.dh_priv_num +#define opdata_cipher_key opdata_u.u_cipher.cipher_key +#define opdata_key opdata_u.u_cipher.key +#define opdata_key_len opdata_u.u_cipher.key_len +#define opdata_encrypt opdata_u.u_cipher.encrypt + +/* + * We have 3 different groups of operation types: + * 1) asymmetric operations + * 2) random operations + * 3) symmetric and digest operations + * + * This division into groups stems from the fact that it's common that hardware + * providers may support operations from one group only. For example, hardware + * providers on UltraSPARC T2, n2rng(7d), ncp(7d), and n2cp(7d), each support + * only a single group of operations. + * + * For every group a different slot can be chosen. That means that we must have + * at least 3 different lists of cached PKCS#11 sessions since sessions from + * different groups may be initialized in different slots. + * + * To provide locking granularity in multithreaded environment, the groups are + * further splitted into types with each type having a separate session cache. + */ +typedef enum PK11_OPTYPE_ENUM + { + OP_RAND, + OP_RSA, + OP_DSA, + OP_DH, + OP_CIPHER, + OP_DIGEST, + OP_MAX + } PK11_OPTYPE; + +/* + * This structure contains the heads of the lists forming the object caches + * and locks associated with the lists. + */ +typedef struct PK11_st_CACHE + { + PK11_SESSION *head; +#ifndef NOPTHREADS + pthread_mutex_t *lock; +#endif + } PK11_CACHE; + +/* structure for tracking handles of asymmetric key objects */ +typedef struct PK11_active_st + { + CK_OBJECT_HANDLE h; + unsigned int refcnt; + struct PK11_active_st *prev; + struct PK11_active_st *next; + } PK11_active; + +#ifndef NOPTHREADS +extern pthread_mutex_t *find_lock[]; +#endif +extern PK11_active *active_list[]; +/* + * These variables are specific for the RSA keys by reference code. See + * hw_pk11_pub.c for explanation. + */ +extern CK_FLAGS pubkey_token_flags; + +#ifndef NOPTHREADS +#define LOCK_OBJSTORE(alg_type) \ + OPENSSL_assert(pthread_mutex_lock(find_lock[alg_type]) == 0) +#define UNLOCK_OBJSTORE(alg_type) \ + OPENSSL_assert(pthread_mutex_unlock(find_lock[alg_type]) == 0) +#else +#define LOCK_OBJSTORE(alg_type) \ + CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE) +#define UNLOCK_OBJSTORE(alg_type) \ + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE) +#endif + +extern PK11_SESSION *pk11_get_session(PK11_OPTYPE optype); +extern void pk11_return_session(PK11_SESSION *sp, PK11_OPTYPE optype); +extern int pk11_token_relogin(CK_SESSION_HANDLE session); + +#ifndef OPENSSL_NO_RSA +extern int pk11_destroy_rsa_key_objects(PK11_SESSION *session); +extern int pk11_destroy_rsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock); +extern int pk11_destroy_rsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock); +extern EVP_PKEY *pk11_load_privkey(ENGINE *e, const char *pubkey_file, + UI_METHOD *ui_method, void *callback_data); +extern EVP_PKEY *pk11_load_pubkey(ENGINE *e, const char *pubkey_file, + UI_METHOD *ui_method, void *callback_data); +extern RSA_METHOD *PK11_RSA(void); +#endif /* OPENSSL_NO_RSA */ +#ifndef OPENSSL_NO_DSA +extern int pk11_destroy_dsa_key_objects(PK11_SESSION *session); +extern int pk11_destroy_dsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock); +extern int pk11_destroy_dsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock); +extern DSA_METHOD *PK11_DSA(void); +#endif /* OPENSSL_NO_DSA */ +#ifndef OPENSSL_NO_DH +extern int pk11_destroy_dh_key_objects(PK11_SESSION *session); +extern int pk11_destroy_dh_object(PK11_SESSION *sp, CK_BBOOL uselock); +extern DH_METHOD *PK11_DH(void); +#endif /* OPENSSL_NO_DH */ + +extern CK_FUNCTION_LIST_PTR pFuncList; + +#endif /* HW_PK11_ERR_H */ Index: openssl/crypto/engine/hw_pk11_pub.c diff -u /dev/null openssl/crypto/engine/hw_pk11_pub.c:1.42 --- /dev/null Mon Jun 13 15:55:26 2016 +++ openssl/crypto/engine/hw_pk11_pub.c Fri Oct 4 14:27:06 2013 @@ -0,0 +1,3556 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* crypto/engine/hw_pk11_pub.c */ +/* + * This product includes software developed by the OpenSSL Project for + * use in the OpenSSL Toolkit (http://www.openssl.org/). + * + * This project also referenced hw_pkcs11-0.9.7b.patch written by + * Afchine Madjlessi. + */ +/* + * ==================================================================== + * Copyright (c) 2000-2001 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#ifndef OPENSSL_NO_RSA +#include +#endif /* OPENSSL_NO_RSA */ +#ifndef OPENSSL_NO_DSA +#include +#endif /* OPENSSL_NO_DSA */ +#ifndef OPENSSL_NO_DH +#include +#endif /* OPENSSL_NO_DH */ +#include +#include +#include + +#ifdef OPENSSL_SYS_WIN32 +#define NOPTHREADS +typedef int pid_t; +#define HAVE_GETPASSPHRASE +static char *getpassphrase(const char *prompt); +#ifndef NULL_PTR +#define NULL_PTR NULL +#endif +#define CK_DEFINE_FUNCTION(returnType, name) \ + returnType __declspec(dllexport) name +#define CK_DECLARE_FUNCTION(returnType, name) \ + returnType __declspec(dllimport) name +#define CK_DECLARE_FUNCTION_POINTER(returnType, name) \ + returnType __declspec(dllimport) (* name) +#else +#include +#endif + +#ifndef NOPTHREADS +#include +#endif + +#ifndef OPENSSL_NO_HW +#ifndef OPENSSL_NO_HW_PK11 +#ifndef OPENSSL_NO_HW_PK11CA + +#ifdef OPENSSL_SYS_WIN32 +#pragma pack(push, cryptoki, 1) +#include "cryptoki.h" +#include "pkcs11.h" +#pragma pack(pop, cryptoki) +#else +#include "cryptoki.h" +#include "pkcs11.h" +#endif +#include "hw_pk11ca.h" +#include "hw_pk11_err.h" + +static CK_BBOOL pk11_login_done = CK_FALSE; +extern CK_SLOT_ID pubkey_SLOTID; +#ifndef NOPTHREADS +extern pthread_mutex_t *token_lock; +#endif + +#if !(defined(HAVE_GETPASSPHRASE) || (defined (__SVR4) && defined (__sun))) +#define getpassphrase(x) getpass(x) +#endif + +#ifndef OPENSSL_NO_RSA +/* RSA stuff */ +static int pk11_RSA_public_encrypt(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding); +static int pk11_RSA_private_encrypt(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding); +static int pk11_RSA_public_decrypt(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding); +static int pk11_RSA_private_decrypt(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding); +static int pk11_RSA_init(RSA *rsa); +static int pk11_RSA_finish(RSA *rsa); +static int pk11_RSA_sign(int type, const unsigned char *m, unsigned int m_len, + unsigned char *sigret, unsigned int *siglen, const RSA *rsa); +#if OPENSSL_VERSION_NUMBER < 0x10000000L +static int pk11_RSA_verify(int dtype, const unsigned char *m, + unsigned int m_len, unsigned char *sigbuf, unsigned int siglen, + const RSA *rsa); +#else +static int pk11_RSA_verify(int dtype, const unsigned char *m, + unsigned int m_len, const unsigned char *sigbuf, unsigned int siglen, + const RSA *rsa); +#endif +EVP_PKEY *pk11_load_privkey(ENGINE*, const char *privkey_file, + UI_METHOD *ui_method, void *callback_data); +EVP_PKEY *pk11_load_pubkey(ENGINE*, const char *pubkey_file, + UI_METHOD *ui_method, void *callback_data); + +static int pk11_RSA_public_encrypt_low(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa); +static int pk11_RSA_private_encrypt_low(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa); +static int pk11_RSA_public_decrypt_low(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa); +static int pk11_RSA_private_decrypt_low(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa); + +static CK_OBJECT_HANDLE pk11_get_public_rsa_key(RSA* rsa, RSA** key_ptr, + BIGNUM **rsa_n_num, BIGNUM **rsa_e_num, CK_SESSION_HANDLE session); +static CK_OBJECT_HANDLE pk11_get_private_rsa_key(RSA* rsa, RSA** key_ptr, + BIGNUM **rsa_d_num, BIGNUM **rsa_n_num, BIGNUM **rsa_e_num, + CK_SESSION_HANDLE session); + +static int check_new_rsa_key_pub(PK11_SESSION *sp, const RSA *rsa); +static int check_new_rsa_key_priv(PK11_SESSION *sp, const RSA *rsa); +#endif + +/* DSA stuff */ +#ifndef OPENSSL_NO_DSA +static int pk11_DSA_init(DSA *dsa); +static int pk11_DSA_finish(DSA *dsa); +static DSA_SIG *pk11_dsa_do_sign(const unsigned char *dgst, int dlen, + DSA *dsa); +static int pk11_dsa_do_verify(const unsigned char *dgst, int dgst_len, + DSA_SIG *sig, DSA *dsa); + +static CK_OBJECT_HANDLE pk11_get_public_dsa_key(DSA* dsa, DSA **key_ptr, + BIGNUM **dsa_pub_num, CK_SESSION_HANDLE session); +static CK_OBJECT_HANDLE pk11_get_private_dsa_key(DSA* dsa, DSA **key_ptr, + BIGNUM **dsa_priv_num, CK_SESSION_HANDLE session); + +static int check_new_dsa_key_pub(PK11_SESSION *sp, DSA *dsa); +static int check_new_dsa_key_priv(PK11_SESSION *sp, DSA *dsa); +#endif + +/* DH stuff */ +#ifndef OPENSSL_NO_DH +static int pk11_DH_init(DH *dh); +static int pk11_DH_finish(DH *dh); +static int pk11_DH_generate_key(DH *dh); +static int pk11_DH_compute_key(unsigned char *key, + const BIGNUM *pub_key, DH *dh); + +static CK_OBJECT_HANDLE pk11_get_dh_key(DH* dh, DH **key_ptr, + BIGNUM **priv_key, CK_SESSION_HANDLE session); + +static int check_new_dh_key(PK11_SESSION *sp, DH *dh); +#endif + +static int find_one_object(PK11_OPTYPE op, CK_SESSION_HANDLE s, + CK_ATTRIBUTE_PTR ptempl, CK_ULONG nattr, CK_OBJECT_HANDLE_PTR pkey); +static int init_template_value(BIGNUM *bn, CK_VOID_PTR *pValue, + CK_ULONG *ulValueLen); +static void attr_to_BN(CK_ATTRIBUTE_PTR attr, CK_BYTE attr_data[], BIGNUM **bn); + +static int pk11_token_login(CK_SESSION_HANDLE session, CK_BBOOL *login_done, + CK_BBOOL is_private); + +/* Read mode string to be used for fopen() */ +#if SOLARIS_OPENSSL +static char *read_mode_flags = "rF"; +#else +static char *read_mode_flags = "r"; +#endif + +/* + * increment/create reference for an asymmetric key handle via active list + * manipulation. If active list operation fails, unlock (if locked), set error + * variable and jump to the specified label. + */ +#define KEY_HANDLE_REFHOLD(key_handle, alg_type, unlock, var, label) \ + { \ + if (pk11_active_add(key_handle, alg_type) < 0) \ + { \ + var = TRUE; \ + if (unlock) \ + UNLOCK_OBJSTORE(alg_type); \ + goto label; \ + } \ + } + +/* + * Find active list entry according to object handle and return pointer to the + * entry otherwise return NULL. + * + * This function presumes it is called with lock protecting the active list + * held. + */ +static PK11_active *pk11_active_find(CK_OBJECT_HANDLE h, PK11_OPTYPE type) + { + PK11_active *entry; + + for (entry = active_list[type]; entry != NULL; entry = entry->next) + if (entry->h == h) + return (entry); + + return (NULL); + } + +/* + * Search for an entry in the active list using PKCS#11 object handle as a + * search key and return refcnt of the found/created entry or -1 in case of + * failure. + * + * This function presumes it is called with lock protecting the active list + * held. + */ +int +pk11_active_add(CK_OBJECT_HANDLE h, PK11_OPTYPE type) + { + PK11_active *entry = NULL; + + if (h == CK_INVALID_HANDLE) + { + PK11err(PK11_F_ACTIVE_ADD, PK11_R_INVALID_HANDLE); + return (-1); + } + + /* search for entry in the active list */ + if ((entry = pk11_active_find(h, type)) != NULL) + entry->refcnt++; + else + { + /* not found, create new entry and add it to the list */ + entry = OPENSSL_malloc(sizeof (PK11_active)); + if (entry == NULL) + { + PK11err(PK11_F_ACTIVE_ADD, PK11_R_MALLOC_FAILURE); + return (-1); + } + entry->h = h; + entry->refcnt = 1; + entry->prev = NULL; + entry->next = NULL; + /* connect the newly created entry to the list */ + if (active_list[type] == NULL) + active_list[type] = entry; + else /* make the entry first in the list */ + { + entry->next = active_list[type]; + active_list[type]->prev = entry; + active_list[type] = entry; + } + } + + return (entry->refcnt); + } + +/* + * Remove active list entry from the list and free it. + * + * This function presumes it is called with lock protecting the active list + * held. + */ +void +pk11_active_remove(PK11_active *entry, PK11_OPTYPE type) + { + PK11_active *prev_entry; + + /* remove the entry from the list and free it */ + if ((prev_entry = entry->prev) != NULL) + { + prev_entry->next = entry->next; + if (entry->next != NULL) + entry->next->prev = prev_entry; + } + else + { + active_list[type] = entry->next; + /* we were the first but not the only one */ + if (entry->next != NULL) + entry->next->prev = NULL; + } + + /* sanitization */ + entry->h = CK_INVALID_HANDLE; + entry->prev = NULL; + entry->next = NULL; + OPENSSL_free(entry); + } + +/* Free all entries from the active list. */ +void +pk11_free_active_list(PK11_OPTYPE type) + { + PK11_active *entry; + + /* only for asymmetric types since only they have C_Find* locks. */ + switch (type) + { + case OP_RSA: + case OP_DSA: + case OP_DH: + break; + default: + return; + } + + /* see find_lock array definition for more info on object locking */ + LOCK_OBJSTORE(type); + while ((entry = active_list[type]) != NULL) + pk11_active_remove(entry, type); + UNLOCK_OBJSTORE(type); + } + +/* + * Search for active list entry associated with given PKCS#11 object handle, + * decrement its refcnt and if it drops to 0, disconnect the entry and free it. + * + * Return 1 if the PKCS#11 object associated with the entry has no references, + * return 0 if there is at least one reference, -1 on error. + * + * This function presumes it is called with lock protecting the active list + * held. + */ +int +pk11_active_delete(CK_OBJECT_HANDLE h, PK11_OPTYPE type) + { + PK11_active *entry = NULL; + + if ((entry = pk11_active_find(h, type)) == NULL) + { + PK11err(PK11_F_ACTIVE_DELETE, PK11_R_INVALID_HANDLE); + return (-1); + } + + OPENSSL_assert(entry->refcnt > 0); + entry->refcnt--; + if (entry->refcnt == 0) + { + pk11_active_remove(entry, type); + return (1); + } + + return (0); + } + +#ifndef OPENSSL_NO_RSA +/* Our internal RSA_METHOD that we provide pointers to */ +static RSA_METHOD pk11_rsa = + { + "PKCS#11 RSA method", + pk11_RSA_public_encrypt, /* rsa_pub_encrypt */ + pk11_RSA_public_decrypt, /* rsa_pub_decrypt */ + pk11_RSA_private_encrypt, /* rsa_priv_encrypt */ + pk11_RSA_private_decrypt, /* rsa_priv_decrypt */ + NULL, /* rsa_mod_exp */ + NULL, /* bn_mod_exp */ + pk11_RSA_init, /* init */ + pk11_RSA_finish, /* finish */ + RSA_FLAG_SIGN_VER, /* flags */ + NULL, /* app_data */ + pk11_RSA_sign, /* rsa_sign */ + pk11_RSA_verify /* rsa_verify */ + }; + +RSA_METHOD * +PK11_RSA(void) + { + return (&pk11_rsa); + } +#endif + +#ifndef OPENSSL_NO_DSA +/* Our internal DSA_METHOD that we provide pointers to */ +static DSA_METHOD pk11_dsa = + { + "PKCS#11 DSA method", + pk11_dsa_do_sign, /* dsa_do_sign */ + NULL, /* dsa_sign_setup */ + pk11_dsa_do_verify, /* dsa_do_verify */ + NULL, /* dsa_mod_exp */ + NULL, /* bn_mod_exp */ + pk11_DSA_init, /* init */ + pk11_DSA_finish, /* finish */ + 0, /* flags */ + NULL /* app_data */ + }; + +DSA_METHOD * +PK11_DSA(void) + { + return (&pk11_dsa); + } +#endif + +#ifndef OPENSSL_NO_DH +/* + * PKCS #11 V2.20, section 11.2 specifies that the number of bytes needed for + * output buffer may somewhat exceed the precise number of bytes needed, but + * should not exceed it by a large amount. That may be caused, for example, by + * rounding it up to multiple of X in the underlying bignum library. 8 should be + * enough. + */ +#define DH_BUF_RESERVE 8 + +/* Our internal DH_METHOD that we provide pointers to */ +static DH_METHOD pk11_dh = + { + "PKCS#11 DH method", + pk11_DH_generate_key, /* generate_key */ + pk11_DH_compute_key, /* compute_key */ + NULL, /* bn_mod_exp */ + pk11_DH_init, /* init */ + pk11_DH_finish, /* finish */ + 0, /* flags */ + NULL, /* app_data */ + NULL /* generate_params */ + }; + +DH_METHOD * +PK11_DH(void) + { + return (&pk11_dh); + } +#endif + +/* Size of an SSL signature: MD5+SHA1 */ +#define SSL_SIG_LENGTH 36 + +/* Lengths of DSA data and signature */ +#define DSA_DATA_LEN 20 +#define DSA_SIGNATURE_LEN 40 + +static CK_BBOOL mytrue = TRUE; +static CK_BBOOL myfalse = FALSE; + +#ifndef OPENSSL_NO_RSA +/* + * Similiar to OpenSSL to take advantage of the paddings. The goal is to + * support all paddings in this engine although PK11 library does not + * support all the paddings used in OpenSSL. + * The input errors should have been checked in the padding functions. + */ +static int pk11_RSA_public_encrypt(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding) + { + int i, num = 0, r = -1; + unsigned char *buf = NULL; + + num = BN_num_bytes(rsa->n); + if ((buf = (unsigned char *)OPENSSL_malloc(num)) == NULL) + { + RSAerr(PK11_F_RSA_PUB_ENC, PK11_R_MALLOC_FAILURE); + goto err; + } + + switch (padding) + { + case RSA_PKCS1_PADDING: + i = RSA_padding_add_PKCS1_type_2(buf, num, from, flen); + break; +#ifndef OPENSSL_NO_SHA + case RSA_PKCS1_OAEP_PADDING: + i = RSA_padding_add_PKCS1_OAEP(buf, num, from, flen, NULL, 0); + break; +#endif + case RSA_SSLV23_PADDING: + i = RSA_padding_add_SSLv23(buf, num, from, flen); + break; + case RSA_NO_PADDING: + i = RSA_padding_add_none(buf, num, from, flen); + break; + default: + RSAerr(PK11_F_RSA_PUB_ENC, PK11_R_UNKNOWN_PADDING_TYPE); + goto err; + } + if (i <= 0) goto err; + + /* PK11 functions are called here */ + r = pk11_RSA_public_encrypt_low(num, buf, to, rsa); +err: + if (buf != NULL) + { + OPENSSL_cleanse(buf, num); + OPENSSL_free(buf); + } + return (r); + } + + +/* + * Similar to Openssl to take advantage of the paddings. The input errors + * should be catched in the padding functions + */ +static int pk11_RSA_private_encrypt(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding) + { + int i, num = 0, r = -1; + unsigned char *buf = NULL; + + num = BN_num_bytes(rsa->n); + if ((buf = (unsigned char *)OPENSSL_malloc(num)) == NULL) + { + RSAerr(PK11_F_RSA_PRIV_ENC, PK11_R_MALLOC_FAILURE); + goto err; + } + + switch (padding) + { + case RSA_PKCS1_PADDING: + i = RSA_padding_add_PKCS1_type_1(buf, num, from, flen); + break; + case RSA_NO_PADDING: + i = RSA_padding_add_none(buf, num, from, flen); + break; + case RSA_SSLV23_PADDING: + default: + RSAerr(PK11_F_RSA_PRIV_ENC, PK11_R_UNKNOWN_PADDING_TYPE); + goto err; + } + if (i <= 0) goto err; + + /* PK11 functions are called here */ + r = pk11_RSA_private_encrypt_low(num, buf, to, rsa); +err: + if (buf != NULL) + { + OPENSSL_cleanse(buf, num); + OPENSSL_free(buf); + } + return (r); + } + +/* Similar to OpenSSL code. Input errors are also checked here */ +static int pk11_RSA_private_decrypt(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding) + { + BIGNUM f; + int j, num = 0, r = -1; + unsigned char *p; + unsigned char *buf = NULL; + + BN_init(&f); + + num = BN_num_bytes(rsa->n); + + if ((buf = (unsigned char *)OPENSSL_malloc(num)) == NULL) + { + RSAerr(PK11_F_RSA_PRIV_DEC, PK11_R_MALLOC_FAILURE); + goto err; + } + + /* + * This check was for equality but PGP does evil things + * and chops off the top '0' bytes + */ + if (flen > num) + { + RSAerr(PK11_F_RSA_PRIV_DEC, + PK11_R_DATA_GREATER_THAN_MOD_LEN); + goto err; + } + + /* make data into a big number */ + if (BN_bin2bn(from, (int)flen, &f) == NULL) + goto err; + + if (BN_ucmp(&f, rsa->n) >= 0) + { + RSAerr(PK11_F_RSA_PRIV_DEC, + PK11_R_DATA_TOO_LARGE_FOR_MODULUS); + goto err; + } + + /* PK11 functions are called here */ + r = pk11_RSA_private_decrypt_low(flen, from, buf, rsa); + + /* + * PK11 CKM_RSA_X_509 mechanism pads 0's at the beginning. + * Needs to skip these 0's paddings here. + */ + for (j = 0; j < r; j++) + if (buf[j] != 0) + break; + + p = buf + j; + j = r - j; /* j is only used with no-padding mode */ + + switch (padding) + { + case RSA_PKCS1_PADDING: + r = RSA_padding_check_PKCS1_type_2(to, num, p, j, num); + break; +#ifndef OPENSSL_NO_SHA + case RSA_PKCS1_OAEP_PADDING: + r = RSA_padding_check_PKCS1_OAEP(to, num, p, j, num, NULL, 0); + break; +#endif + case RSA_SSLV23_PADDING: + r = RSA_padding_check_SSLv23(to, num, p, j, num); + break; + case RSA_NO_PADDING: + r = RSA_padding_check_none(to, num, p, j, num); + break; + default: + RSAerr(PK11_F_RSA_PRIV_DEC, PK11_R_UNKNOWN_PADDING_TYPE); + goto err; + } + if (r < 0) + RSAerr(PK11_F_RSA_PRIV_DEC, PK11_R_PADDING_CHECK_FAILED); + +err: + BN_clear_free(&f); + if (buf != NULL) + { + OPENSSL_cleanse(buf, num); + OPENSSL_free(buf); + } + return (r); + } + +/* Similar to OpenSSL code. Input errors are also checked here */ +static int pk11_RSA_public_decrypt(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding) + { + BIGNUM f; + int i, num = 0, r = -1; + unsigned char *p; + unsigned char *buf = NULL; + + BN_init(&f); + num = BN_num_bytes(rsa->n); + buf = (unsigned char *)OPENSSL_malloc(num); + if (buf == NULL) + { + RSAerr(PK11_F_RSA_PUB_DEC, PK11_R_MALLOC_FAILURE); + goto err; + } + + /* + * This check was for equality but PGP does evil things + * and chops off the top '0' bytes + */ + if (flen > num) + { + RSAerr(PK11_F_RSA_PUB_DEC, PK11_R_DATA_GREATER_THAN_MOD_LEN); + goto err; + } + + if (BN_bin2bn(from, flen, &f) == NULL) + goto err; + + if (BN_ucmp(&f, rsa->n) >= 0) + { + RSAerr(PK11_F_RSA_PUB_DEC, + PK11_R_DATA_TOO_LARGE_FOR_MODULUS); + goto err; + } + + /* PK11 functions are called here */ + r = pk11_RSA_public_decrypt_low(flen, from, buf, rsa); + + /* + * PK11 CKM_RSA_X_509 mechanism pads 0's at the beginning. + * Needs to skip these 0's here + */ + for (i = 0; i < r; i++) + if (buf[i] != 0) + break; + + p = buf + i; + i = r - i; /* i is only used with no-padding mode */ + + switch (padding) + { + case RSA_PKCS1_PADDING: + r = RSA_padding_check_PKCS1_type_1(to, num, p, i, num); + break; + case RSA_NO_PADDING: + r = RSA_padding_check_none(to, num, p, i, num); + break; + default: + RSAerr(PK11_F_RSA_PUB_DEC, PK11_R_UNKNOWN_PADDING_TYPE); + goto err; + } + if (r < 0) + RSAerr(PK11_F_RSA_PUB_DEC, PK11_R_PADDING_CHECK_FAILED); + +err: + BN_clear_free(&f); + if (buf != NULL) + { + OPENSSL_cleanse(buf, num); + OPENSSL_free(buf); + } + return (r); + } + +/* + * This function implements RSA public encryption using C_EncryptInit and + * C_Encrypt pk11 interfaces. Note that the CKM_RSA_X_509 is used here. + * The calling function allocated sufficient memory in "to" to store results. + */ +static int pk11_RSA_public_encrypt_low(int flen, + const unsigned char *from, unsigned char *to, RSA *rsa) + { + CK_ULONG bytes_encrypted = flen; + int retval = -1; + CK_RV rv; + CK_MECHANISM mech_rsa = {CKM_RSA_X_509, NULL, 0}; + CK_MECHANISM *p_mech = &mech_rsa; + CK_OBJECT_HANDLE h_pub_key = CK_INVALID_HANDLE; + PK11_SESSION *sp; + + if ((sp = pk11_get_session(OP_RSA)) == NULL) + return (-1); + + (void) check_new_rsa_key_pub(sp, rsa); + + h_pub_key = sp->opdata_rsa_pub_key; + if (h_pub_key == CK_INVALID_HANDLE) + h_pub_key = sp->opdata_rsa_pub_key = + pk11_get_public_rsa_key(rsa, &sp->opdata_rsa_pub, + &sp->opdata_rsa_n_num, &sp->opdata_rsa_e_num, + sp->session); + + if (h_pub_key != CK_INVALID_HANDLE) + { + rv = pFuncList->C_EncryptInit(sp->session, p_mech, + h_pub_key); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_RSA_PUB_ENC_LOW, + PK11_R_ENCRYPTINIT, rv); + pk11_return_session(sp, OP_RSA); + return (-1); + } + + rv = pFuncList->C_Encrypt(sp->session, + (unsigned char *)from, flen, to, &bytes_encrypted); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_RSA_PUB_ENC_LOW, + PK11_R_ENCRYPT, rv); + pk11_return_session(sp, OP_RSA); + return (-1); + } + retval = bytes_encrypted; + } + + pk11_return_session(sp, OP_RSA); + return (retval); + } + + +/* + * This function implements RSA private encryption using C_SignInit and + * C_Sign pk11 APIs. Note that CKM_RSA_X_509 is used here. + * The calling function allocated sufficient memory in "to" to store results. + */ +static int pk11_RSA_private_encrypt_low(int flen, + const unsigned char *from, unsigned char *to, RSA *rsa) + { + CK_ULONG ul_sig_len = flen; + int retval = -1; + CK_RV rv; + CK_MECHANISM mech_rsa = {CKM_RSA_X_509, NULL, 0}; + CK_MECHANISM *p_mech = &mech_rsa; + CK_OBJECT_HANDLE h_priv_key = CK_INVALID_HANDLE; + PK11_SESSION *sp; + + if ((sp = pk11_get_session(OP_RSA)) == NULL) + return (-1); + + (void) check_new_rsa_key_priv(sp, rsa); + + h_priv_key = sp->opdata_rsa_priv_key; + if (h_priv_key == CK_INVALID_HANDLE) + { + h_priv_key = sp->opdata_rsa_priv_key = + pk11_get_private_rsa_key(rsa, &sp->opdata_rsa_priv, + &sp->opdata_rsa_d_num, &sp->opdata_rsa_pn_num, + &sp->opdata_rsa_pe_num, sp->session); + } + + if (h_priv_key != CK_INVALID_HANDLE) + { + rv = pFuncList->C_SignInit(sp->session, p_mech, + h_priv_key); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_RSA_PRIV_ENC_LOW, + PK11_R_SIGNINIT, rv); + pk11_return_session(sp, OP_RSA); + return (-1); + } + + rv = pFuncList->C_Sign(sp->session, + (unsigned char *)from, flen, to, &ul_sig_len); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_RSA_PRIV_ENC_LOW, PK11_R_SIGN, + rv); + pk11_return_session(sp, OP_RSA); + return (-1); + } + + retval = ul_sig_len; + } + + pk11_return_session(sp, OP_RSA); + return (retval); + } + + +/* + * This function implements RSA private decryption using C_DecryptInit and + * C_Decrypt pk11 APIs. Note that CKM_RSA_X_509 mechanism is used here. + * The calling function allocated sufficient memory in "to" to store results. + */ +static int pk11_RSA_private_decrypt_low(int flen, + const unsigned char *from, unsigned char *to, RSA *rsa) + { + CK_ULONG bytes_decrypted = flen; + int retval = -1; + CK_RV rv; + CK_MECHANISM mech_rsa = {CKM_RSA_X_509, NULL, 0}; + CK_MECHANISM *p_mech = &mech_rsa; + CK_OBJECT_HANDLE h_priv_key; + PK11_SESSION *sp; + + if ((sp = pk11_get_session(OP_RSA)) == NULL) + return (-1); + + (void) check_new_rsa_key_priv(sp, rsa); + + h_priv_key = sp->opdata_rsa_priv_key; + if (h_priv_key == CK_INVALID_HANDLE) + h_priv_key = sp->opdata_rsa_priv_key = + pk11_get_private_rsa_key(rsa, &sp->opdata_rsa_priv, + &sp->opdata_rsa_d_num, &sp->opdata_rsa_pn_num, + &sp->opdata_rsa_pe_num, sp->session); + + if (h_priv_key != CK_INVALID_HANDLE) + { + rv = pFuncList->C_DecryptInit(sp->session, p_mech, + h_priv_key); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_RSA_PRIV_DEC_LOW, + PK11_R_DECRYPTINIT, rv); + pk11_return_session(sp, OP_RSA); + return (-1); + } + + rv = pFuncList->C_Decrypt(sp->session, + (unsigned char *)from, flen, to, &bytes_decrypted); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_RSA_PRIV_DEC_LOW, + PK11_R_DECRYPT, rv); + pk11_return_session(sp, OP_RSA); + return (-1); + } + retval = bytes_decrypted; + } + + pk11_return_session(sp, OP_RSA); + return (retval); + } + + +/* + * This function implements RSA public decryption using C_VerifyRecoverInit + * and C_VerifyRecover pk11 APIs. Note that CKM_RSA_X_509 is used here. + * The calling function allocated sufficient memory in "to" to store results. + */ +static int pk11_RSA_public_decrypt_low(int flen, + const unsigned char *from, unsigned char *to, RSA *rsa) + { + CK_ULONG bytes_decrypted = flen; + int retval = -1; + CK_RV rv; + CK_MECHANISM mech_rsa = {CKM_RSA_X_509, NULL, 0}; + CK_MECHANISM *p_mech = &mech_rsa; + CK_OBJECT_HANDLE h_pub_key = CK_INVALID_HANDLE; + PK11_SESSION *sp; + + if ((sp = pk11_get_session(OP_RSA)) == NULL) + return (-1); + + (void) check_new_rsa_key_pub(sp, rsa); + + h_pub_key = sp->opdata_rsa_pub_key; + if (h_pub_key == CK_INVALID_HANDLE) + h_pub_key = sp->opdata_rsa_pub_key = + pk11_get_public_rsa_key(rsa, &sp->opdata_rsa_pub, + &sp->opdata_rsa_n_num, &sp->opdata_rsa_e_num, + sp->session); + + if (h_pub_key != CK_INVALID_HANDLE) + { + rv = pFuncList->C_VerifyRecoverInit(sp->session, + p_mech, h_pub_key); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_RSA_PUB_DEC_LOW, + PK11_R_VERIFYRECOVERINIT, rv); + pk11_return_session(sp, OP_RSA); + return (-1); + } + + rv = pFuncList->C_VerifyRecover(sp->session, + (unsigned char *)from, flen, to, &bytes_decrypted); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_RSA_PUB_DEC_LOW, + PK11_R_VERIFYRECOVER, rv); + pk11_return_session(sp, OP_RSA); + return (-1); + } + retval = bytes_decrypted; + } + + pk11_return_session(sp, OP_RSA); + return (retval); + } + +static int pk11_RSA_init(RSA *rsa) + { + /* + * This flag in the RSA_METHOD enables the new rsa_sign, + * rsa_verify functions. See rsa.h for details. + */ + rsa->flags |= RSA_FLAG_SIGN_VER; + + return (1); + } + +static int pk11_RSA_finish(RSA *rsa) + { + /* + * Since we are overloading OpenSSL's native RSA_eay_finish() we need + * to do the same as in the original function, i.e. to free bignum + * structures. + */ + if (rsa->_method_mod_n != NULL) + BN_MONT_CTX_free(rsa->_method_mod_n); + if (rsa->_method_mod_p != NULL) + BN_MONT_CTX_free(rsa->_method_mod_p); + if (rsa->_method_mod_q != NULL) + BN_MONT_CTX_free(rsa->_method_mod_q); + + return (1); + } + +/* + * Standard engine interface function. Majority codes here are from + * rsa/rsa_sign.c. We replaced the decrypt function call by C_Sign of PKCS#11. + * See more details in rsa/rsa_sign.c + */ +static int pk11_RSA_sign(int type, const unsigned char *m, unsigned int m_len, + unsigned char *sigret, unsigned int *siglen, const RSA *rsa) + { + X509_SIG sig; + ASN1_TYPE parameter; + int i, j = 0; + unsigned char *p, *s = NULL; + X509_ALGOR algor; + ASN1_OCTET_STRING digest; + CK_RV rv; + CK_MECHANISM mech_rsa = {CKM_RSA_PKCS, NULL, 0}; + CK_MECHANISM *p_mech = &mech_rsa; + CK_OBJECT_HANDLE h_priv_key; + PK11_SESSION *sp = NULL; + int ret = 0; + unsigned long ulsiglen; + + /* Encode the digest */ + /* Special case: SSL signature, just check the length */ + if (type == NID_md5_sha1) + { + if (m_len != SSL_SIG_LENGTH) + { + PK11err(PK11_F_RSA_SIGN, + PK11_R_INVALID_MESSAGE_LENGTH); + goto err; + } + i = SSL_SIG_LENGTH; + s = (unsigned char *)m; + } + else + { + sig.algor = &algor; + sig.algor->algorithm = OBJ_nid2obj(type); + if (sig.algor->algorithm == NULL) + { + PK11err(PK11_F_RSA_SIGN, + PK11_R_UNKNOWN_ALGORITHM_TYPE); + goto err; + } + if (sig.algor->algorithm->length == 0) + { + PK11err(PK11_F_RSA_SIGN, + PK11_R_UNKNOWN_ASN1_OBJECT_ID); + goto err; + } + parameter.type = V_ASN1_NULL; + parameter.value.ptr = NULL; + sig.algor->parameter = ¶meter; + + sig.digest = &digest; + sig.digest->data = (unsigned char *)m; + sig.digest->length = m_len; + + i = i2d_X509_SIG(&sig, NULL); + } + + j = RSA_size(rsa); + if ((i - RSA_PKCS1_PADDING) > j) + { + PK11err(PK11_F_RSA_SIGN, PK11_R_DIGEST_TOO_BIG); + goto err; + } + + if (type != NID_md5_sha1) + { + s = (unsigned char *)OPENSSL_malloc((unsigned int)(j + 1)); + if (s == NULL) + { + PK11err(PK11_F_RSA_SIGN, PK11_R_MALLOC_FAILURE); + goto err; + } + p = s; + (void) i2d_X509_SIG(&sig, &p); + } + + if ((sp = pk11_get_session(OP_RSA)) == NULL) + goto err; + + (void) check_new_rsa_key_priv(sp, rsa); + + h_priv_key = sp->opdata_rsa_priv_key; + if (h_priv_key == CK_INVALID_HANDLE) + h_priv_key = sp->opdata_rsa_priv_key = + pk11_get_private_rsa_key((RSA *)rsa, + &sp->opdata_rsa_priv, &sp->opdata_rsa_d_num, + &sp->opdata_rsa_pn_num, &sp->opdata_rsa_pe_num, + sp->session); + + if (h_priv_key != CK_INVALID_HANDLE) + { + rv = pFuncList->C_SignInit(sp->session, p_mech, h_priv_key); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_RSA_SIGN, PK11_R_SIGNINIT, rv); + goto err; + } + + ulsiglen = j; + rv = pFuncList->C_Sign(sp->session, s, i, sigret, + (CK_ULONG_PTR) &ulsiglen); + *siglen = ulsiglen; + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_RSA_SIGN, PK11_R_SIGN, rv); + goto err; + } + ret = 1; + } + +err: + if ((type != NID_md5_sha1) && (s != NULL)) + { + (void) memset(s, 0, (unsigned int)(j + 1)); + OPENSSL_free(s); + } + + pk11_return_session(sp, OP_RSA); + return (ret); + } + +#if OPENSSL_VERSION_NUMBER < 0x10000000L +static int pk11_RSA_verify(int type, const unsigned char *m, + unsigned int m_len, unsigned char *sigbuf, unsigned int siglen, + const RSA *rsa) +#else +static int pk11_RSA_verify(int type, const unsigned char *m, + unsigned int m_len, const unsigned char *sigbuf, unsigned int siglen, + const RSA *rsa) +#endif + { + X509_SIG sig; + ASN1_TYPE parameter; + int i, j = 0; + unsigned char *p, *s = NULL; + X509_ALGOR algor; + ASN1_OCTET_STRING digest; + CK_RV rv; + CK_MECHANISM mech_rsa = {CKM_RSA_PKCS, NULL, 0}; + CK_MECHANISM *p_mech = &mech_rsa; + CK_OBJECT_HANDLE h_pub_key; + PK11_SESSION *sp = NULL; + int ret = 0; + + /* Encode the digest */ + /* Special case: SSL signature, just check the length */ + if (type == NID_md5_sha1) + { + if (m_len != SSL_SIG_LENGTH) + { + PK11err(PK11_F_RSA_VERIFY, + PK11_R_INVALID_MESSAGE_LENGTH); + goto err; + } + i = SSL_SIG_LENGTH; + s = (unsigned char *)m; + } + else + { + sig.algor = &algor; + sig.algor->algorithm = OBJ_nid2obj(type); + if (sig.algor->algorithm == NULL) + { + PK11err(PK11_F_RSA_VERIFY, + PK11_R_UNKNOWN_ALGORITHM_TYPE); + goto err; + } + if (sig.algor->algorithm->length == 0) + { + PK11err(PK11_F_RSA_VERIFY, + PK11_R_UNKNOWN_ASN1_OBJECT_ID); + goto err; + } + parameter.type = V_ASN1_NULL; + parameter.value.ptr = NULL; + sig.algor->parameter = ¶meter; + sig.digest = &digest; + sig.digest->data = (unsigned char *)m; + sig.digest->length = m_len; + i = i2d_X509_SIG(&sig, NULL); + } + + j = RSA_size(rsa); + if ((i - RSA_PKCS1_PADDING) > j) + { + PK11err(PK11_F_RSA_VERIFY, PK11_R_DIGEST_TOO_BIG); + goto err; + } + + if (type != NID_md5_sha1) + { + s = (unsigned char *)OPENSSL_malloc((unsigned int)(j + 1)); + if (s == NULL) + { + PK11err(PK11_F_RSA_VERIFY, PK11_R_MALLOC_FAILURE); + goto err; + } + p = s; + (void) i2d_X509_SIG(&sig, &p); + } + + if ((sp = pk11_get_session(OP_RSA)) == NULL) + goto err; + + (void) check_new_rsa_key_pub(sp, rsa); + + h_pub_key = sp->opdata_rsa_pub_key; + if (h_pub_key == CK_INVALID_HANDLE) + h_pub_key = sp->opdata_rsa_pub_key = + pk11_get_public_rsa_key((RSA *)rsa, &sp->opdata_rsa_pub, + &sp->opdata_rsa_n_num, &sp->opdata_rsa_e_num, + sp->session); + + if (h_pub_key != CK_INVALID_HANDLE) + { + rv = pFuncList->C_VerifyInit(sp->session, p_mech, + h_pub_key); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_RSA_VERIFY, PK11_R_VERIFYINIT, + rv); + goto err; + } + rv = pFuncList->C_Verify(sp->session, s, i, + (CK_BYTE_PTR)sigbuf, (CK_ULONG)siglen); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_RSA_VERIFY, PK11_R_VERIFY, rv); + goto err; + } + ret = 1; + } + +err: + if ((type != NID_md5_sha1) && (s != NULL)) + { + (void) memset(s, 0, (unsigned int)(j + 1)); + OPENSSL_free(s); + } + + pk11_return_session(sp, OP_RSA); + return (ret); + } + +static int hndidx_rsa = -1; + +#define MAXATTR 1024 + +/* + * Load RSA private key from a file or get its PKCS#11 handle if stored in the + * PKCS#11 token. + */ +/* ARGSUSED */ +EVP_PKEY *pk11_load_privkey(ENGINE *e, const char *privkey_file, + UI_METHOD *ui_method, void *callback_data) + { + EVP_PKEY *pkey = NULL; + FILE *privkey; + CK_OBJECT_HANDLE h_priv_key = CK_INVALID_HANDLE; + RSA *rsa = NULL; + PK11_SESSION *sp; + /* Anything else below is needed for the key by reference extension. */ + CK_RV rv; + CK_BBOOL is_token = TRUE; + CK_BBOOL rollback = FALSE; + CK_BYTE attr_data[2][MAXATTR]; + CK_OBJECT_CLASS key_class = CKO_PRIVATE_KEY; + CK_OBJECT_HANDLE ks_key = CK_INVALID_HANDLE; /* key in keystore */ + + /* we look for private keys only */ + CK_ATTRIBUTE search_templ[] = + { + {CKA_TOKEN, &is_token, sizeof(is_token)}, + {CKA_CLASS, &key_class, sizeof(key_class)}, + {CKA_LABEL, NULL, 0} + }; + + /* + * These public attributes are needed to initialize the OpenSSL RSA + * structure with something we can use to look up the key. Note that we + * never ask for private components. + */ + CK_ATTRIBUTE get_templ[] = + { + {CKA_MODULUS, (void *)attr_data[0], MAXATTR}, /* n */ + {CKA_PUBLIC_EXPONENT, (void *)attr_data[1], MAXATTR}, /* e */ + }; + + if ((sp = pk11_get_session(OP_RSA)) == NULL) + return (NULL); + + /* + * Use simple scheme "pkcs11:" for now. + */ + if (strstr(privkey_file, "pkcs11:") == privkey_file) + { + search_templ[2].pValue = strstr(privkey_file, ":") + 1; + search_templ[2].ulValueLen = strlen(search_templ[2].pValue); + + if (pk11_token_login(sp->session, &pk11_login_done, + CK_TRUE) == 0) + goto err; + + /* see find_lock array definition + for more info on object locking */ + LOCK_OBJSTORE(OP_RSA); + + /* + * Now let's try to find the key in the token. It is a failure + * if we can't find it. + */ + if (find_one_object(OP_RSA, sp->session, search_templ, 3, + &ks_key) == 0) + { + UNLOCK_OBJSTORE(OP_RSA); + goto err; + } + + if (hndidx_rsa == -1) + hndidx_rsa = RSA_get_ex_new_index(0, + "pkcs11 RSA HSM key handle", + NULL, NULL, NULL); + + /* + * We might have a cache hit which we could confirm + * according to the 'n'/'e' params, RSA public pointer + * as NULL, and non-NULL RSA private pointer. However, + * it is easier just to recreate everything. We expect + * the keys to be loaded once and used many times. We + * do not check the return value because even in case + * of failure the sp structure will have both key + * pointer and object handle cleaned and + * pk11_destroy_object() reports the failure to the + * OpenSSL error message buffer. + */ + (void) pk11_destroy_rsa_object_priv(sp, FALSE); + + sp->opdata_rsa_priv_key = ks_key; + /* This object shall not be deleted on a cache miss. */ + sp->priv_persistent = CK_TRUE; + + /* + * Cache the RSA private structure pointer. We do not + * use it now for key-by-ref keys but let's do it for + * consistency reasons. + */ + if ((rsa = sp->opdata_rsa_priv = RSA_new_method(e)) == NULL) + { + UNLOCK_OBJSTORE(OP_RSA); + goto err; + } + + /* + * Now we have to initialize an OpenSSL RSA structure, + * everything else is 0 or NULL. + */ + rsa->flags = RSA_FLAG_SIGN_VER | RSA_FLAG_EXT_PKEY; + RSA_set_ex_data(rsa, hndidx_rsa, (void *) ks_key); + + if ((rv = pFuncList->C_GetAttributeValue(sp->session, ks_key, + get_templ, 2)) != CKR_OK) + { + UNLOCK_OBJSTORE(OP_RSA); + PK11err_add_data(PK11_F_LOAD_PRIVKEY, + PK11_R_GETATTRIBUTVALUE, rv); + goto err; + } + + /* + * We do not use pk11_get_private_rsa_key() here so we + * must take care of handle management ourselves. + */ + KEY_HANDLE_REFHOLD(ks_key, OP_RSA, TRUE, rollback, err); + + /* + * Those are the sensitive components we do not want to export + * from the token at all: rsa->(d|p|q|dmp1|dmq1|iqmp). + */ + attr_to_BN(&get_templ[0], attr_data[0], &rsa->n); + attr_to_BN(&get_templ[1], attr_data[1], &rsa->e); + /* + * Must have 'n'/'e' components in the session structure as + * well. They serve as a public look-up key for the private key + * in the keystore. + */ + attr_to_BN(&get_templ[0], attr_data[0], + &sp->opdata_rsa_pn_num); + attr_to_BN(&get_templ[1], attr_data[1], + &sp->opdata_rsa_pe_num); + + UNLOCK_OBJSTORE(OP_RSA); + + if ((pkey = EVP_PKEY_new()) == NULL) + goto err; + + if (EVP_PKEY_assign_RSA(pkey, rsa) == 0) + goto err; + } + else if ((privkey = fopen(privkey_file, read_mode_flags)) != NULL) + { + pkey = PEM_read_PrivateKey(privkey, NULL, NULL, NULL); + (void) fclose(privkey); + if (pkey != NULL) + { + rsa = EVP_PKEY_get1_RSA(pkey); + if (rsa != NULL) + { + /* + * This will always destroy the RSA + * object since we have a new RSA + * structure here. + */ + (void) check_new_rsa_key_priv(sp, rsa); + sp->priv_persistent = CK_FALSE; + + h_priv_key = sp->opdata_rsa_priv_key = + pk11_get_private_rsa_key(rsa, + &sp->opdata_rsa_priv, + &sp->opdata_rsa_d_num, + &sp->opdata_rsa_pn_num, + &sp->opdata_rsa_pe_num, sp->session); + if (h_priv_key == CK_INVALID_HANDLE) + goto err; + } + else + goto err; + } + } + + pk11_return_session(sp, OP_RSA); + return (pkey); +err: + pk11_return_session(sp, OP_RSA); + if (rsa != NULL) + RSA_free(rsa); + if (pkey != NULL) + { + EVP_PKEY_free(pkey); + pkey = NULL; + } + rollback = rollback; + return (pkey); + } + +/* + * Load RSA public key from a file or get its PKCS#11 handle if stored in the + * PKCS#11 token. + */ +/* ARGSUSED */ +EVP_PKEY *pk11_load_pubkey(ENGINE *e, const char *pubkey_file, + UI_METHOD *ui_method, void *callback_data) + { + EVP_PKEY *pkey = NULL; + FILE *pubkey; + CK_OBJECT_HANDLE h_pub_key = CK_INVALID_HANDLE; + RSA *rsa = NULL; + PK11_SESSION *sp; + /* Anything else below is needed for the key by reference extension. */ + CK_RV rv; + CK_BBOOL is_token = TRUE; + CK_BYTE attr_data[2][MAXATTR]; + CK_OBJECT_CLASS key_class = CKO_PUBLIC_KEY; + CK_OBJECT_HANDLE ks_key = CK_INVALID_HANDLE; /* key in keystore */ + + /* we look for public keys only */ + CK_ATTRIBUTE search_templ[] = + { + {CKA_TOKEN, &is_token, sizeof(is_token)}, + {CKA_CLASS, &key_class, sizeof(key_class)}, + {CKA_LABEL, NULL, 0} + }; + + /* + * These public attributes are needed to initialize OpenSSL RSA + * structure with something we can use to look up the key. + */ + CK_ATTRIBUTE get_templ[] = + { + {CKA_MODULUS, (void *)attr_data[0], MAXATTR}, /* n */ + {CKA_PUBLIC_EXPONENT, (void *)attr_data[1], MAXATTR}, /* e */ + }; + + if ((sp = pk11_get_session(OP_RSA)) == NULL) + return (NULL); + + /* + * Use simple scheme "pkcs11:" for now. + */ + if (strstr(pubkey_file, "pkcs11:") == pubkey_file) + { + search_templ[2].pValue = strstr(pubkey_file, ":") + 1; + search_templ[2].ulValueLen = strlen(search_templ[2].pValue); + + if (pk11_token_login(sp->session, &pk11_login_done, + CK_FALSE) == 0) + goto err; + + /* see find_lock array definition + for more info on object locking */ + LOCK_OBJSTORE(OP_RSA); + + /* + * Now let's try to find the key in the token. It is a failure + * if we can't find it. + */ + if (find_one_object(OP_RSA, sp->session, search_templ, 3, + &ks_key) == 0) + { + UNLOCK_OBJSTORE(OP_RSA); + goto err; + } + + /* + * We load a new public key so we will create a new RSA + * structure. No cache hit is possible. + */ + (void) pk11_destroy_rsa_object_pub(sp, FALSE); + + sp->opdata_rsa_pub_key = ks_key; + /* This object shall not be deleted on a cache miss. */ + sp->pub_persistent = CK_TRUE; + + /* + * Cache the RSA public structure pointer. + */ + if ((rsa = sp->opdata_rsa_pub = RSA_new_method(e)) == NULL) + { + UNLOCK_OBJSTORE(OP_RSA); + goto err; + } + + /* + * Now we have to initialize an OpenSSL RSA structure, + * everything else is 0 or NULL. + */ + rsa->flags = RSA_FLAG_SIGN_VER; + + if ((rv = pFuncList->C_GetAttributeValue(sp->session, ks_key, + get_templ, 2)) != CKR_OK) + { + UNLOCK_OBJSTORE(OP_RSA); + PK11err_add_data(PK11_F_LOAD_PUBKEY, + PK11_R_GETATTRIBUTVALUE, rv); + goto err; + } + + attr_to_BN(&get_templ[0], attr_data[0], &rsa->n); + attr_to_BN(&get_templ[1], attr_data[1], &rsa->e); + + UNLOCK_OBJSTORE(OP_RSA); + + if ((pkey = EVP_PKEY_new()) == NULL) + goto err; + + if (EVP_PKEY_assign_RSA(pkey, rsa) == 0) + goto err; + + /* + * Create a session object from it so that when calling + * pk11_get_public_rsa_key() the next time, we can find it. The + * reason why we do that is that we cannot tell from the RSA + * structure (OpenSSL RSA structure does not have any room for + * additional data used by the engine, for example) if it bears + * a public key stored in the keystore or not so it's better if + * we always have a session key. Note that this is different + * from what we do for the private keystore objects but in that + * case, we can tell from the RSA structure that the keystore + * object is in play - the 'd' component is NULL in that case. + */ + h_pub_key = sp->opdata_rsa_pub_key = + pk11_get_public_rsa_key(rsa, + &sp->opdata_rsa_pub, &sp->opdata_rsa_n_num, + &sp->opdata_rsa_e_num, sp->session); + if (h_pub_key == CK_INVALID_HANDLE) + goto err; + } + else if ((pubkey = fopen(pubkey_file, read_mode_flags)) != NULL) + { + pkey = PEM_read_PUBKEY(pubkey, NULL, NULL, NULL); + (void) fclose(pubkey); + if (pkey != NULL) + { + rsa = EVP_PKEY_get1_RSA(pkey); + if (rsa != NULL) + { + /* + * This will always destroy the RSA + * object since we have a new RSA + * structure here. + */ + (void) check_new_rsa_key_pub(sp, rsa); + sp->pub_persistent = CK_FALSE; + + h_pub_key = sp->opdata_rsa_pub_key = + pk11_get_public_rsa_key(rsa, + &sp->opdata_rsa_pub, &sp->opdata_rsa_n_num, + &sp->opdata_rsa_e_num, sp->session); + if (h_pub_key == CK_INVALID_HANDLE) + goto err; + } + else + goto err; + } + } + + pk11_return_session(sp, OP_RSA); + return (pkey); +err: + pk11_return_session(sp, OP_RSA); + if (rsa != NULL) + RSA_free(rsa); + if (pkey != NULL) + { + EVP_PKEY_free(pkey); + pkey = NULL; + } + return (pkey); + } + +/* + * Create a public key object in a session from a given rsa structure. + * The *rsa_n_num and *rsa_e_num pointers are non-NULL for RSA public keys. + */ +static CK_OBJECT_HANDLE pk11_get_public_rsa_key(RSA *rsa, + RSA **key_ptr, BIGNUM **rsa_n_num, BIGNUM **rsa_e_num, + CK_SESSION_HANDLE session) + { + CK_RV rv; + CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE; + CK_ULONG found; + CK_OBJECT_CLASS o_key = CKO_PUBLIC_KEY; + CK_KEY_TYPE k_type = CKK_RSA; + CK_ULONG ul_key_attr_count = 8; + CK_BBOOL rollback = FALSE; + + CK_ATTRIBUTE a_key_template[] = + { + {CKA_CLASS, (void *) NULL, sizeof (CK_OBJECT_CLASS)}, + {CKA_KEY_TYPE, (void *) NULL, sizeof (CK_KEY_TYPE)}, + {CKA_TOKEN, &myfalse, sizeof (myfalse)}, + {CKA_ENCRYPT, &mytrue, sizeof (mytrue)}, + {CKA_VERIFY, &mytrue, sizeof (mytrue)}, + {CKA_VERIFY_RECOVER, &mytrue, sizeof (mytrue)}, + {CKA_MODULUS, (void *)NULL, 0}, + {CKA_PUBLIC_EXPONENT, (void *)NULL, 0} + }; + + int i; + + a_key_template[0].pValue = &o_key; + a_key_template[1].pValue = &k_type; + + a_key_template[6].ulValueLen = BN_num_bytes(rsa->n); + a_key_template[6].pValue = (CK_VOID_PTR)OPENSSL_malloc( + (size_t)a_key_template[6].ulValueLen); + if (a_key_template[6].pValue == NULL) + { + PK11err(PK11_F_GET_PUB_RSA_KEY, PK11_R_MALLOC_FAILURE); + goto malloc_err; + } + + BN_bn2bin(rsa->n, a_key_template[6].pValue); + + a_key_template[7].ulValueLen = BN_num_bytes(rsa->e); + a_key_template[7].pValue = (CK_VOID_PTR)OPENSSL_malloc( + (size_t)a_key_template[7].ulValueLen); + if (a_key_template[7].pValue == NULL) + { + PK11err(PK11_F_GET_PUB_RSA_KEY, PK11_R_MALLOC_FAILURE); + goto malloc_err; + } + + BN_bn2bin(rsa->e, a_key_template[7].pValue); + + /* see find_lock array definition for more info on object locking */ + LOCK_OBJSTORE(OP_RSA); + + rv = pFuncList->C_FindObjectsInit(session, a_key_template, + ul_key_attr_count); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PUB_RSA_KEY, + PK11_R_FINDOBJECTSINIT, rv); + goto err; + } + + rv = pFuncList->C_FindObjects(session, &h_key, 1, &found); + + if (rv != CKR_OK) + { + (void) pFuncList->C_FindObjectsFinal(session); + PK11err_add_data(PK11_F_GET_PUB_RSA_KEY, + PK11_R_FINDOBJECTS, rv); + goto err; + } + + rv = pFuncList->C_FindObjectsFinal(session); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PUB_RSA_KEY, + PK11_R_FINDOBJECTSFINAL, rv); + goto err; + } + + if (found == 0) + { + rv = pFuncList->C_CreateObject(session, + a_key_template, ul_key_attr_count, &h_key); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PUB_RSA_KEY, + PK11_R_CREATEOBJECT, rv); + goto err; + } + } + + if (rsa_n_num != NULL) + if ((*rsa_n_num = BN_dup(rsa->n)) == NULL) + { + PK11err(PK11_F_GET_PUB_RSA_KEY, PK11_R_MALLOC_FAILURE); + rollback = TRUE; + goto err; + } + if (rsa_e_num != NULL) + if ((*rsa_e_num = BN_dup(rsa->e)) == NULL) + { + PK11err(PK11_F_GET_PUB_RSA_KEY, PK11_R_MALLOC_FAILURE); + BN_free(*rsa_n_num); + *rsa_n_num = NULL; + rollback = TRUE; + goto err; + } + + /* LINTED: E_CONSTANT_CONDITION */ + KEY_HANDLE_REFHOLD(h_key, OP_RSA, FALSE, rollback, err); + if (key_ptr != NULL) + *key_ptr = rsa; + +err: + if (rollback) + { + /* + * We do not care about the return value from C_DestroyObject() + * since we are doing rollback. + */ + if (found == 0) + (void) pFuncList->C_DestroyObject(session, h_key); + h_key = CK_INVALID_HANDLE; + } + + UNLOCK_OBJSTORE(OP_RSA); + +malloc_err: + for (i = 6; i <= 7; i++) + { + if (a_key_template[i].pValue != NULL) + { + OPENSSL_free(a_key_template[i].pValue); + a_key_template[i].pValue = NULL; + } + } + + return (h_key); + } + +/* + * Create a private key object in the session from a given rsa structure. + * The *rsa_d_num pointer is non-NULL for RSA private keys. + */ +static CK_OBJECT_HANDLE +pk11_get_private_rsa_key(RSA *rsa, RSA **key_ptr, BIGNUM **rsa_d_num, + BIGNUM **rsa_n_num, BIGNUM **rsa_e_num, CK_SESSION_HANDLE session) + { + CK_RV rv; + CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE; + int i; + CK_ULONG found; + CK_OBJECT_CLASS o_key = CKO_PRIVATE_KEY; + CK_KEY_TYPE k_type = CKK_RSA; + CK_ULONG ul_key_attr_count = 14; + CK_BBOOL rollback = FALSE; + + /* Both CKA_TOKEN and CKA_SENSITIVE have to be FALSE for session keys */ + CK_ATTRIBUTE a_key_template[] = + { + {CKA_CLASS, (void *) NULL, sizeof (CK_OBJECT_CLASS)}, + {CKA_KEY_TYPE, (void *) NULL, sizeof (CK_KEY_TYPE)}, + {CKA_TOKEN, &myfalse, sizeof (myfalse)}, + {CKA_SENSITIVE, &myfalse, sizeof (myfalse)}, + {CKA_DECRYPT, &mytrue, sizeof (mytrue)}, + {CKA_SIGN, &mytrue, sizeof (mytrue)}, + {CKA_MODULUS, (void *)NULL, 0}, + {CKA_PUBLIC_EXPONENT, (void *)NULL, 0}, + {CKA_PRIVATE_EXPONENT, (void *)NULL, 0}, + {CKA_PRIME_1, (void *)NULL, 0}, + {CKA_PRIME_2, (void *)NULL, 0}, + {CKA_EXPONENT_1, (void *)NULL, 0}, + {CKA_EXPONENT_2, (void *)NULL, 0}, + {CKA_COEFFICIENT, (void *)NULL, 0}, + }; + + if ((rsa->flags & RSA_FLAG_EXT_PKEY) != 0) { + h_key = (CK_OBJECT_HANDLE)RSA_get_ex_data(rsa, hndidx_rsa); + LOCK_OBJSTORE(OP_RSA); + goto set; + } + + a_key_template[0].pValue = &o_key; + a_key_template[1].pValue = &k_type; + + /* Put the private key components into the template */ + if (init_template_value(rsa->n, &a_key_template[6].pValue, + &a_key_template[6].ulValueLen) == 0 || + init_template_value(rsa->e, &a_key_template[7].pValue, + &a_key_template[7].ulValueLen) == 0 || + init_template_value(rsa->d, &a_key_template[8].pValue, + &a_key_template[8].ulValueLen) == 0 || + init_template_value(rsa->p, &a_key_template[9].pValue, + &a_key_template[9].ulValueLen) == 0 || + init_template_value(rsa->q, &a_key_template[10].pValue, + &a_key_template[10].ulValueLen) == 0 || + init_template_value(rsa->dmp1, &a_key_template[11].pValue, + &a_key_template[11].ulValueLen) == 0 || + init_template_value(rsa->dmq1, &a_key_template[12].pValue, + &a_key_template[12].ulValueLen) == 0 || + init_template_value(rsa->iqmp, &a_key_template[13].pValue, + &a_key_template[13].ulValueLen) == 0) + { + PK11err(PK11_F_GET_PRIV_RSA_KEY, PK11_R_MALLOC_FAILURE); + goto malloc_err; + } + + /* see find_lock array definition for more info on object locking */ + LOCK_OBJSTORE(OP_RSA); + + /* + * We are getting the private key but the private 'd' + * component is NULL. That means this is key by reference RSA + * key. In that case, we can use only public components for + * searching for the private key handle. + */ + if (rsa->d == NULL) + { + ul_key_attr_count = 8; + /* + * We will perform the search in the token, not in the existing + * session keys. + */ + a_key_template[2].pValue = &mytrue; + } + + rv = pFuncList->C_FindObjectsInit(session, a_key_template, + ul_key_attr_count); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PRIV_RSA_KEY, + PK11_R_FINDOBJECTSINIT, rv); + goto err; + } + + rv = pFuncList->C_FindObjects(session, &h_key, 1, &found); + + if (rv != CKR_OK) + { + (void) pFuncList->C_FindObjectsFinal(session); + PK11err_add_data(PK11_F_GET_PRIV_RSA_KEY, + PK11_R_FINDOBJECTS, rv); + goto err; + } + + rv = pFuncList->C_FindObjectsFinal(session); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PRIV_RSA_KEY, + PK11_R_FINDOBJECTSFINAL, rv); + goto err; + } + + if (found == 0) + { + /* + * We have an RSA structure with 'n'/'e' components + * only so we tried to find the private key in the + * keystore. If it was really a token key we have a + * problem. Note that for other key types we just + * create a new session key using the private + * components from the RSA structure. + */ + if (rsa->d == NULL) + { + PK11err(PK11_F_GET_PRIV_RSA_KEY, + PK11_R_PRIV_KEY_NOT_FOUND); + goto err; + } + + rv = pFuncList->C_CreateObject(session, + a_key_template, ul_key_attr_count, &h_key); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PRIV_RSA_KEY, + PK11_R_CREATEOBJECT, rv); + goto err; + } + } + +set: + if (rsa_d_num != NULL) + { + /* + * When RSA keys by reference code is used, we never + * extract private components from the keystore. In + * that case 'd' was set to NULL and we expect the + * application to properly cope with that. It is + * documented in openssl(5). In general, if keys by + * reference are used we expect it to be used + * exclusively using the high level API and then there + * is no problem. If the application expects the + * private components to be read from the keystore + * then that is not a supported way of usage. + */ + if (rsa->d != NULL && (*rsa_d_num = BN_dup(rsa->d)) == NULL) + { + PK11err(PK11_F_GET_PRIV_RSA_KEY, PK11_R_MALLOC_FAILURE); + rollback = TRUE; + goto err; + } + else + *rsa_d_num = NULL; + } + + /* + * For the key by reference code, we need public components as well + * since 'd' component is always NULL. For that reason, we always cache + * 'n'/'e' components as well. + */ + *rsa_n_num = BN_dup(rsa->n); + *rsa_e_num = BN_dup(rsa->e); + + /* LINTED: E_CONSTANT_CONDITION */ + KEY_HANDLE_REFHOLD(h_key, OP_RSA, FALSE, rollback, err); + if (key_ptr != NULL) + *key_ptr = rsa; + +err: + if (rollback) + { + /* + * We do not care about the return value from C_DestroyObject() + * since we are doing rollback. + */ + if (found == 0 && + (rsa->flags & RSA_FLAG_EXT_PKEY) == 0) + (void) pFuncList->C_DestroyObject(session, h_key); + h_key = CK_INVALID_HANDLE; + } + + UNLOCK_OBJSTORE(OP_RSA); + +malloc_err: + /* + * 6 to 13 entries in the key template are key components. + * They need to be freed upon exit or error. + */ + for (i = 6; i <= 13; i++) + { + if (a_key_template[i].pValue != NULL) + { + (void) memset(a_key_template[i].pValue, 0, + a_key_template[i].ulValueLen); + OPENSSL_free(a_key_template[i].pValue); + a_key_template[i].pValue = NULL; + } + } + + return (h_key); + } + +/* + * Check for cache miss and clean the object pointer and handle + * in such case. Return 1 for cache hit, 0 for cache miss. + */ +static int check_new_rsa_key_pub(PK11_SESSION *sp, const RSA *rsa) + { + /* + * Provide protection against RSA structure reuse by making the + * check for cache hit stronger. Only public components of RSA + * key matter here so it is sufficient to compare them with values + * cached in PK11_SESSION structure. + * + * We must check the handle as well since with key by reference, public + * components 'n'/'e' are cached in private keys as well. That means we + * could have a cache hit in a private key when looking for a public + * key. That would not work, you cannot have one PKCS#11 object for + * both data signing and verifying. + */ + if ((sp->opdata_rsa_pub != rsa) || + (BN_cmp(sp->opdata_rsa_n_num, rsa->n) != 0) || + (BN_cmp(sp->opdata_rsa_e_num, rsa->e) != 0) || + (sp->opdata_rsa_priv_key != CK_INVALID_HANDLE)) + { + /* + * We do not check the return value because even in case of + * failure the sp structure will have both key pointer + * and object handle cleaned and pk11_destroy_object() + * reports the failure to the OpenSSL error message buffer. + */ + (void) pk11_destroy_rsa_object_pub(sp, TRUE); + return (0); + } + return (1); + } + +/* + * Check for cache miss and clean the object pointer and handle + * in such case. Return 1 for cache hit, 0 for cache miss. + */ +static int check_new_rsa_key_priv(PK11_SESSION *sp, const RSA *rsa) + { + /* + * Provide protection against RSA structure reuse by making + * the check for cache hit stronger. Comparing public exponent + * of RSA key with value cached in PK11_SESSION structure + * should be sufficient. Note that we want to compare the + * public component since with the keys by reference + * mechanism, private components are not in the RSA + * structure. Also, see check_new_rsa_key_pub() about why we + * compare the handle as well. + */ + if ((sp->opdata_rsa_priv != rsa) || + (BN_cmp(sp->opdata_rsa_pn_num, rsa->n) != 0) || + (BN_cmp(sp->opdata_rsa_pe_num, rsa->e) != 0) || + (sp->opdata_rsa_pn_num == NULL) || + (sp->opdata_rsa_pe_num == NULL) || + (sp->opdata_rsa_pub_key != CK_INVALID_HANDLE)) + { + /* + * We do not check the return value because even in case of + * failure the sp structure will have both key pointer + * and object handle cleaned and pk11_destroy_object() + * reports the failure to the OpenSSL error message buffer. + */ + (void) pk11_destroy_rsa_object_priv(sp, TRUE); + return (0); + } + return (1); + } +#endif + +#ifndef OPENSSL_NO_DSA +/* The DSA function implementation */ +/* ARGSUSED */ +static int pk11_DSA_init(DSA *dsa) + { + return (1); + } + +/* ARGSUSED */ +static int pk11_DSA_finish(DSA *dsa) + { + return (1); + } + + +static DSA_SIG * +pk11_dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa) + { + BIGNUM *r = NULL, *s = NULL; + int i; + DSA_SIG *dsa_sig = NULL; + + CK_RV rv; + CK_MECHANISM Mechanism_dsa = {CKM_DSA, NULL, 0}; + CK_MECHANISM *p_mech = &Mechanism_dsa; + CK_OBJECT_HANDLE h_priv_key; + + /* + * The signature is the concatenation of r and s, + * each is 20 bytes long + */ + unsigned char sigret[DSA_SIGNATURE_LEN]; + unsigned long siglen = DSA_SIGNATURE_LEN; + unsigned int siglen2 = DSA_SIGNATURE_LEN / 2; + + PK11_SESSION *sp = NULL; + + if ((dsa->p == NULL) || (dsa->q == NULL) || (dsa->g == NULL)) + { + PK11err(PK11_F_DSA_SIGN, PK11_R_MISSING_KEY_COMPONENT); + goto ret; + } + + i = BN_num_bytes(dsa->q); /* should be 20 */ + if (dlen > i) + { + PK11err(PK11_F_DSA_SIGN, PK11_R_INVALID_SIGNATURE_LENGTH); + goto ret; + } + + if ((sp = pk11_get_session(OP_DSA)) == NULL) + goto ret; + + (void) check_new_dsa_key_priv(sp, dsa); + + h_priv_key = sp->opdata_dsa_priv_key; + if (h_priv_key == CK_INVALID_HANDLE) + h_priv_key = sp->opdata_dsa_priv_key = + pk11_get_private_dsa_key((DSA *)dsa, + &sp->opdata_dsa_priv, + &sp->opdata_dsa_priv_num, sp->session); + + if (h_priv_key != CK_INVALID_HANDLE) + { + rv = pFuncList->C_SignInit(sp->session, p_mech, h_priv_key); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DSA_SIGN, PK11_R_SIGNINIT, rv); + goto ret; + } + + (void) memset(sigret, 0, siglen); + rv = pFuncList->C_Sign(sp->session, + (unsigned char*) dgst, dlen, sigret, + (CK_ULONG_PTR) &siglen); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DSA_SIGN, PK11_R_SIGN, rv); + goto ret; + } + } + + + if ((s = BN_new()) == NULL) + { + PK11err(PK11_F_DSA_SIGN, PK11_R_MALLOC_FAILURE); + goto ret; + } + + if ((r = BN_new()) == NULL) + { + PK11err(PK11_F_DSA_SIGN, PK11_R_MALLOC_FAILURE); + goto ret; + } + + if ((dsa_sig = DSA_SIG_new()) == NULL) + { + PK11err(PK11_F_DSA_SIGN, PK11_R_MALLOC_FAILURE); + goto ret; + } + + if (BN_bin2bn(sigret, siglen2, r) == NULL || + BN_bin2bn(&sigret[siglen2], siglen2, s) == NULL) + { + PK11err(PK11_F_DSA_SIGN, PK11_R_MALLOC_FAILURE); + goto ret; + } + + dsa_sig->r = r; + dsa_sig->s = s; + +ret: + if (dsa_sig == NULL) + { + if (r != NULL) + BN_free(r); + if (s != NULL) + BN_free(s); + } + + pk11_return_session(sp, OP_DSA); + return (dsa_sig); + } + +static int +pk11_dsa_do_verify(const unsigned char *dgst, int dlen, DSA_SIG *sig, + DSA *dsa) + { + int i; + CK_RV rv; + int retval = 0; + CK_MECHANISM Mechanism_dsa = {CKM_DSA, NULL, 0}; + CK_MECHANISM *p_mech = &Mechanism_dsa; + CK_OBJECT_HANDLE h_pub_key; + + unsigned char sigbuf[DSA_SIGNATURE_LEN]; + unsigned long siglen = DSA_SIGNATURE_LEN; + unsigned long siglen2 = DSA_SIGNATURE_LEN/2; + + PK11_SESSION *sp = NULL; + + if (BN_is_zero(sig->r) || sig->r->neg || BN_ucmp(sig->r, dsa->q) >= 0) + { + PK11err(PK11_F_DSA_VERIFY, + PK11_R_INVALID_DSA_SIGNATURE_R); + goto ret; + } + + if (BN_is_zero(sig->s) || sig->s->neg || BN_ucmp(sig->s, dsa->q) >= 0) + { + PK11err(PK11_F_DSA_VERIFY, + PK11_R_INVALID_DSA_SIGNATURE_S); + goto ret; + } + + i = BN_num_bytes(dsa->q); /* should be 20 */ + + if (dlen > i) + { + PK11err(PK11_F_DSA_VERIFY, + PK11_R_INVALID_SIGNATURE_LENGTH); + goto ret; + } + + if ((sp = pk11_get_session(OP_DSA)) == NULL) + goto ret; + + (void) check_new_dsa_key_pub(sp, dsa); + + h_pub_key = sp->opdata_dsa_pub_key; + if (h_pub_key == CK_INVALID_HANDLE) + h_pub_key = sp->opdata_dsa_pub_key = + pk11_get_public_dsa_key((DSA *)dsa, &sp->opdata_dsa_pub, + &sp->opdata_dsa_pub_num, sp->session); + + if (h_pub_key != CK_INVALID_HANDLE) + { + rv = pFuncList->C_VerifyInit(sp->session, p_mech, + h_pub_key); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DSA_VERIFY, PK11_R_VERIFYINIT, + rv); + goto ret; + } + + /* + * The representation of each of the two big numbers could + * be shorter than DSA_SIGNATURE_LEN/2 bytes so we need + * to act accordingly and shift if necessary. + */ + (void) memset(sigbuf, 0, siglen); + BN_bn2bin(sig->r, sigbuf + siglen2 - BN_num_bytes(sig->r)); + BN_bn2bin(sig->s, &sigbuf[siglen2] + siglen2 - + BN_num_bytes(sig->s)); + + rv = pFuncList->C_Verify(sp->session, + (unsigned char *) dgst, dlen, sigbuf, (CK_ULONG)siglen); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DSA_VERIFY, PK11_R_VERIFY, rv); + goto ret; + } + } + + retval = 1; +ret: + + pk11_return_session(sp, OP_DSA); + return (retval); + } + + +/* + * Create a public key object in a session from a given dsa structure. + * The *dsa_pub_num pointer is non-NULL for DSA public keys. + */ +static CK_OBJECT_HANDLE pk11_get_public_dsa_key(DSA* dsa, + DSA **key_ptr, BIGNUM **dsa_pub_num, CK_SESSION_HANDLE session) + { + CK_RV rv; + CK_OBJECT_CLASS o_key = CKO_PUBLIC_KEY; + CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE; + CK_ULONG found; + CK_KEY_TYPE k_type = CKK_DSA; + CK_ULONG ul_key_attr_count = 8; + CK_BBOOL rollback = FALSE; + int i; + + CK_ATTRIBUTE a_key_template[] = + { + {CKA_CLASS, (void *) NULL, sizeof (CK_OBJECT_CLASS)}, + {CKA_KEY_TYPE, (void *) NULL, sizeof (CK_KEY_TYPE)}, + {CKA_TOKEN, &myfalse, sizeof (myfalse)}, + {CKA_VERIFY, &mytrue, sizeof (mytrue)}, + {CKA_PRIME, (void *)NULL, 0}, /* p */ + {CKA_SUBPRIME, (void *)NULL, 0}, /* q */ + {CKA_BASE, (void *)NULL, 0}, /* g */ + {CKA_VALUE, (void *)NULL, 0} /* pub_key - y */ + }; + + a_key_template[0].pValue = &o_key; + a_key_template[1].pValue = &k_type; + + if (init_template_value(dsa->p, &a_key_template[4].pValue, + &a_key_template[4].ulValueLen) == 0 || + init_template_value(dsa->q, &a_key_template[5].pValue, + &a_key_template[5].ulValueLen) == 0 || + init_template_value(dsa->g, &a_key_template[6].pValue, + &a_key_template[6].ulValueLen) == 0 || + init_template_value(dsa->pub_key, &a_key_template[7].pValue, + &a_key_template[7].ulValueLen) == 0) + { + PK11err(PK11_F_GET_PUB_DSA_KEY, PK11_R_MALLOC_FAILURE); + goto malloc_err; + } + + /* see find_lock array definition for more info on object locking */ + LOCK_OBJSTORE(OP_DSA); + rv = pFuncList->C_FindObjectsInit(session, a_key_template, + ul_key_attr_count); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PUB_DSA_KEY, + PK11_R_FINDOBJECTSINIT, rv); + goto err; + } + + rv = pFuncList->C_FindObjects(session, &h_key, 1, &found); + + if (rv != CKR_OK) + { + (void) pFuncList->C_FindObjectsFinal(session); + PK11err_add_data(PK11_F_GET_PUB_DSA_KEY, + PK11_R_FINDOBJECTS, rv); + goto err; + } + + rv = pFuncList->C_FindObjectsFinal(session); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PUB_DSA_KEY, + PK11_R_FINDOBJECTSFINAL, rv); + goto err; + } + + if (found == 0) + { + rv = pFuncList->C_CreateObject(session, + a_key_template, ul_key_attr_count, &h_key); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PUB_DSA_KEY, + PK11_R_CREATEOBJECT, rv); + goto err; + } + } + + if (dsa_pub_num != NULL) + if ((*dsa_pub_num = BN_dup(dsa->pub_key)) == NULL) + { + PK11err(PK11_F_GET_PUB_DSA_KEY, PK11_R_MALLOC_FAILURE); + rollback = TRUE; + goto err; + } + + /* LINTED: E_CONSTANT_CONDITION */ + KEY_HANDLE_REFHOLD(h_key, OP_DSA, FALSE, rollback, err); + if (key_ptr != NULL) + *key_ptr = dsa; + +err: + if (rollback) + { + /* + * We do not care about the return value from C_DestroyObject() + * since we are doing rollback. + */ + if (found == 0) + (void) pFuncList->C_DestroyObject(session, h_key); + h_key = CK_INVALID_HANDLE; + } + + UNLOCK_OBJSTORE(OP_DSA); + +malloc_err: + for (i = 4; i <= 7; i++) + { + if (a_key_template[i].pValue != NULL) + { + OPENSSL_free(a_key_template[i].pValue); + a_key_template[i].pValue = NULL; + } + } + + return (h_key); + } + +/* + * Create a private key object in the session from a given dsa structure + * The *dsa_priv_num pointer is non-NULL for DSA private keys. + */ +static CK_OBJECT_HANDLE pk11_get_private_dsa_key(DSA* dsa, + DSA **key_ptr, BIGNUM **dsa_priv_num, CK_SESSION_HANDLE session) + { + CK_RV rv; + CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE; + CK_OBJECT_CLASS o_key = CKO_PRIVATE_KEY; + int i; + CK_ULONG found; + CK_KEY_TYPE k_type = CKK_DSA; + CK_ULONG ul_key_attr_count = 9; + CK_BBOOL rollback = FALSE; + + /* Both CKA_TOKEN and CKA_SENSITIVE have to be FALSE for session keys */ + CK_ATTRIBUTE a_key_template[] = + { + {CKA_CLASS, (void *) NULL, sizeof (CK_OBJECT_CLASS)}, + {CKA_KEY_TYPE, (void *) NULL, sizeof (CK_KEY_TYPE)}, + {CKA_TOKEN, &myfalse, sizeof (myfalse)}, + {CKA_SENSITIVE, &myfalse, sizeof (myfalse)}, + {CKA_SIGN, &mytrue, sizeof (mytrue)}, + {CKA_PRIME, (void *)NULL, 0}, /* p */ + {CKA_SUBPRIME, (void *)NULL, 0}, /* q */ + {CKA_BASE, (void *)NULL, 0}, /* g */ + {CKA_VALUE, (void *)NULL, 0} /* priv_key - x */ + }; + + a_key_template[0].pValue = &o_key; + a_key_template[1].pValue = &k_type; + + /* Put the private key components into the template */ + if (init_template_value(dsa->p, &a_key_template[5].pValue, + &a_key_template[5].ulValueLen) == 0 || + init_template_value(dsa->q, &a_key_template[6].pValue, + &a_key_template[6].ulValueLen) == 0 || + init_template_value(dsa->g, &a_key_template[7].pValue, + &a_key_template[7].ulValueLen) == 0 || + init_template_value(dsa->priv_key, &a_key_template[8].pValue, + &a_key_template[8].ulValueLen) == 0) + { + PK11err(PK11_F_GET_PRIV_DSA_KEY, PK11_R_MALLOC_FAILURE); + goto malloc_err; + } + + /* see find_lock array definition for more info on object locking */ + LOCK_OBJSTORE(OP_DSA); + rv = pFuncList->C_FindObjectsInit(session, a_key_template, + ul_key_attr_count); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PRIV_DSA_KEY, + PK11_R_FINDOBJECTSINIT, rv); + goto err; + } + + rv = pFuncList->C_FindObjects(session, &h_key, 1, &found); + + if (rv != CKR_OK) + { + (void) pFuncList->C_FindObjectsFinal(session); + PK11err_add_data(PK11_F_GET_PRIV_DSA_KEY, + PK11_R_FINDOBJECTS, rv); + goto err; + } + + rv = pFuncList->C_FindObjectsFinal(session); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PRIV_DSA_KEY, + PK11_R_FINDOBJECTSFINAL, rv); + goto err; + } + + if (found == 0) + { + rv = pFuncList->C_CreateObject(session, + a_key_template, ul_key_attr_count, &h_key); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PRIV_DSA_KEY, + PK11_R_CREATEOBJECT, rv); + goto err; + } + } + + if (dsa_priv_num != NULL) + if ((*dsa_priv_num = BN_dup(dsa->priv_key)) == NULL) + { + PK11err(PK11_F_GET_PRIV_DSA_KEY, PK11_R_MALLOC_FAILURE); + rollback = TRUE; + goto err; + } + + /* LINTED: E_CONSTANT_CONDITION */ + KEY_HANDLE_REFHOLD(h_key, OP_DSA, FALSE, rollback, err); + if (key_ptr != NULL) + *key_ptr = dsa; + +err: + if (rollback) + { + /* + * We do not care about the return value from C_DestroyObject() + * since we are doing rollback. + */ + if (found == 0) + (void) pFuncList->C_DestroyObject(session, h_key); + h_key = CK_INVALID_HANDLE; + } + + UNLOCK_OBJSTORE(OP_DSA); + +malloc_err: + /* + * 5 to 8 entries in the key template are key components. + * They need to be freed apon exit or error. + */ + for (i = 5; i <= 8; i++) + { + if (a_key_template[i].pValue != NULL) + { + (void) memset(a_key_template[i].pValue, 0, + a_key_template[i].ulValueLen); + OPENSSL_free(a_key_template[i].pValue); + a_key_template[i].pValue = NULL; + } + } + + return (h_key); + } + +/* + * Check for cache miss and clean the object pointer and handle + * in such case. Return 1 for cache hit, 0 for cache miss. + */ +static int check_new_dsa_key_pub(PK11_SESSION *sp, DSA *dsa) + { + /* + * Provide protection against DSA structure reuse by making the + * check for cache hit stronger. Only public key component of DSA + * key matters here so it is sufficient to compare it with value + * cached in PK11_SESSION structure. + */ + if ((sp->opdata_dsa_pub != dsa) || + (BN_cmp(sp->opdata_dsa_pub_num, dsa->pub_key) != 0)) + { + /* + * We do not check the return value because even in case of + * failure the sp structure will have both key pointer + * and object handle cleaned and pk11_destroy_object() + * reports the failure to the OpenSSL error message buffer. + */ + (void) pk11_destroy_dsa_object_pub(sp, TRUE); + return (0); + } + return (1); + } + +/* + * Check for cache miss and clean the object pointer and handle + * in such case. Return 1 for cache hit, 0 for cache miss. + */ +static int check_new_dsa_key_priv(PK11_SESSION *sp, DSA *dsa) + { + /* + * Provide protection against DSA structure reuse by making the + * check for cache hit stronger. Only private key component of DSA + * key matters here so it is sufficient to compare it with value + * cached in PK11_SESSION structure. + */ + if ((sp->opdata_dsa_priv != dsa) || + (BN_cmp(sp->opdata_dsa_priv_num, dsa->priv_key) != 0)) + { + /* + * We do not check the return value because even in case of + * failure the sp structure will have both key pointer + * and object handle cleaned and pk11_destroy_object() + * reports the failure to the OpenSSL error message buffer. + */ + (void) pk11_destroy_dsa_object_priv(sp, TRUE); + return (0); + } + return (1); + } +#endif + + +#ifndef OPENSSL_NO_DH +/* The DH function implementation */ +/* ARGSUSED */ +static int pk11_DH_init(DH *dh) + { + return (1); + } + +/* ARGSUSED */ +static int pk11_DH_finish(DH *dh) + { + return (1); + } + +/* + * Generate DH key-pair. + * + * Warning: Unlike OpenSSL's DH_generate_key(3) we ignore dh->priv_key + * and override it even if it is set. OpenSSL does not touch dh->priv_key + * if set and just computes dh->pub_key. It looks like PKCS#11 standard + * is not capable of providing this functionality. This could be a problem + * for applications relying on OpenSSL's semantics. + */ +static int pk11_DH_generate_key(DH *dh) + { + CK_ULONG i; + CK_RV rv, rv1; + int reuse_mem_len = 0, ret = 0; + PK11_SESSION *sp = NULL; + CK_BYTE_PTR reuse_mem; + + CK_MECHANISM mechanism = {CKM_DH_PKCS_KEY_PAIR_GEN, NULL_PTR, 0}; + CK_OBJECT_HANDLE h_pub_key = CK_INVALID_HANDLE; + CK_OBJECT_HANDLE h_priv_key = CK_INVALID_HANDLE; + + CK_ULONG ul_pub_key_attr_count = 3; + CK_ATTRIBUTE pub_key_template[] = + { + {CKA_PRIVATE, &myfalse, sizeof (myfalse)}, + {CKA_PRIME, (void *)NULL, 0}, + {CKA_BASE, (void *)NULL, 0} + }; + + CK_ULONG ul_priv_key_attr_count = 3; + CK_ATTRIBUTE priv_key_template[] = + { + {CKA_PRIVATE, &myfalse, sizeof (myfalse)}, + {CKA_SENSITIVE, &myfalse, sizeof (myfalse)}, + {CKA_DERIVE, &mytrue, sizeof (mytrue)} + }; + + CK_ULONG pub_key_attr_result_count = 1; + CK_ATTRIBUTE pub_key_result[] = + { + {CKA_VALUE, (void *)NULL, 0} + }; + + CK_ULONG priv_key_attr_result_count = 1; + CK_ATTRIBUTE priv_key_result[] = + { + {CKA_VALUE, (void *)NULL, 0} + }; + + pub_key_template[1].ulValueLen = BN_num_bytes(dh->p); + if (pub_key_template[1].ulValueLen > 0) + { + /* + * We must not increase ulValueLen by DH_BUF_RESERVE since that + * could cause the same rounding problem. See definition of + * DH_BUF_RESERVE above. + */ + pub_key_template[1].pValue = + OPENSSL_malloc(pub_key_template[1].ulValueLen + + DH_BUF_RESERVE); + if (pub_key_template[1].pValue == NULL) + { + PK11err(PK11_F_DH_GEN_KEY, PK11_R_MALLOC_FAILURE); + goto err; + } + + i = BN_bn2bin(dh->p, pub_key_template[1].pValue); + } + else + goto err; + + pub_key_template[2].ulValueLen = BN_num_bytes(dh->g); + if (pub_key_template[2].ulValueLen > 0) + { + pub_key_template[2].pValue = + OPENSSL_malloc(pub_key_template[2].ulValueLen + + DH_BUF_RESERVE); + if (pub_key_template[2].pValue == NULL) + { + PK11err(PK11_F_DH_GEN_KEY, PK11_R_MALLOC_FAILURE); + goto err; + } + + i = BN_bn2bin(dh->g, pub_key_template[2].pValue); + } + else + goto err; + + /* + * Note: we are only using PK11_SESSION structure for getting + * a session handle. The objects created in this function are + * destroyed before return and thus not cached. + */ + if ((sp = pk11_get_session(OP_DH)) == NULL) + goto err; + + rv = pFuncList->C_GenerateKeyPair(sp->session, + &mechanism, + pub_key_template, + ul_pub_key_attr_count, + priv_key_template, + ul_priv_key_attr_count, + &h_pub_key, + &h_priv_key); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DH_GEN_KEY, PK11_R_GEN_KEY, rv); + goto err; + } + + /* + * Reuse the larger memory allocated. We know the larger memory + * should be sufficient for reuse. + */ + if (pub_key_template[1].ulValueLen > pub_key_template[2].ulValueLen) + { + reuse_mem = pub_key_template[1].pValue; + reuse_mem_len = pub_key_template[1].ulValueLen + DH_BUF_RESERVE; + } + else + { + reuse_mem = pub_key_template[2].pValue; + reuse_mem_len = pub_key_template[2].ulValueLen + DH_BUF_RESERVE; + } + + rv = pFuncList->C_GetAttributeValue(sp->session, h_pub_key, + pub_key_result, pub_key_attr_result_count); + rv1 = pFuncList->C_GetAttributeValue(sp->session, h_priv_key, + priv_key_result, priv_key_attr_result_count); + + if (rv != CKR_OK || rv1 != CKR_OK) + { + rv = (rv != CKR_OK) ? rv : rv1; + PK11err_add_data(PK11_F_DH_GEN_KEY, + PK11_R_GETATTRIBUTVALUE, rv); + goto err; + } + + if (((CK_LONG) pub_key_result[0].ulValueLen) <= 0 || + ((CK_LONG) priv_key_result[0].ulValueLen) <= 0) + { + PK11err(PK11_F_DH_GEN_KEY, PK11_R_GETATTRIBUTVALUE); + goto err; + } + + /* Reuse the memory allocated */ + pub_key_result[0].pValue = reuse_mem; + pub_key_result[0].ulValueLen = reuse_mem_len; + + rv = pFuncList->C_GetAttributeValue(sp->session, h_pub_key, + pub_key_result, pub_key_attr_result_count); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DH_GEN_KEY, + PK11_R_GETATTRIBUTVALUE, rv); + goto err; + } + + if (pub_key_result[0].type == CKA_VALUE) + { + if (dh->pub_key == NULL) + if ((dh->pub_key = BN_new()) == NULL) + { + PK11err(PK11_F_DH_GEN_KEY, + PK11_R_MALLOC_FAILURE); + goto err; + } + dh->pub_key = BN_bin2bn(pub_key_result[0].pValue, + pub_key_result[0].ulValueLen, dh->pub_key); + if (dh->pub_key == NULL) + { + PK11err(PK11_F_DH_GEN_KEY, PK11_R_MALLOC_FAILURE); + goto err; + } + } + + /* Reuse the memory allocated */ + priv_key_result[0].pValue = reuse_mem; + priv_key_result[0].ulValueLen = reuse_mem_len; + + rv = pFuncList->C_GetAttributeValue(sp->session, h_priv_key, + priv_key_result, priv_key_attr_result_count); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DH_GEN_KEY, + PK11_R_GETATTRIBUTVALUE, rv); + goto err; + } + + if (priv_key_result[0].type == CKA_VALUE) + { + if (dh->priv_key == NULL) + if ((dh->priv_key = BN_new()) == NULL) + { + PK11err(PK11_F_DH_GEN_KEY, + PK11_R_MALLOC_FAILURE); + goto err; + } + dh->priv_key = BN_bin2bn(priv_key_result[0].pValue, + priv_key_result[0].ulValueLen, dh->priv_key); + if (dh->priv_key == NULL) + { + PK11err(PK11_F_DH_GEN_KEY, PK11_R_MALLOC_FAILURE); + goto err; + } + } + + ret = 1; + +err: + + if (h_pub_key != CK_INVALID_HANDLE) + { + rv = pFuncList->C_DestroyObject(sp->session, h_pub_key); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DH_GEN_KEY, + PK11_R_DESTROYOBJECT, rv); + } + } + + if (h_priv_key != CK_INVALID_HANDLE) + { + rv = pFuncList->C_DestroyObject(sp->session, h_priv_key); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DH_GEN_KEY, + PK11_R_DESTROYOBJECT, rv); + } + } + + for (i = 1; i <= 2; i++) + { + if (pub_key_template[i].pValue != NULL) + { + OPENSSL_free(pub_key_template[i].pValue); + pub_key_template[i].pValue = NULL; + } + } + + pk11_return_session(sp, OP_DH); + return (ret); + } + +static int pk11_DH_compute_key(unsigned char *key, const BIGNUM *pub_key, + DH *dh) + { + unsigned int i; + CK_MECHANISM mechanism = {CKM_DH_PKCS_DERIVE, NULL_PTR, 0}; + CK_OBJECT_CLASS key_class = CKO_SECRET_KEY; + CK_KEY_TYPE key_type = CKK_GENERIC_SECRET; + CK_OBJECT_HANDLE h_derived_key = CK_INVALID_HANDLE; + CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE; + + CK_ULONG seclen; + CK_ULONG ul_priv_key_attr_count = 3; + CK_ATTRIBUTE priv_key_template[] = + { + {CKA_CLASS, (void*) NULL, sizeof (key_class)}, + {CKA_KEY_TYPE, (void*) NULL, sizeof (key_type)}, + {CKA_VALUE_LEN, &seclen, sizeof (seclen)}, + }; + + CK_ULONG priv_key_attr_result_count = 1; + CK_ATTRIBUTE priv_key_result[] = + { + {CKA_VALUE, (void *)NULL, 0} + }; + + CK_RV rv; + int ret = -1; + PK11_SESSION *sp = NULL; + + if (dh->priv_key == NULL) + goto err; + + priv_key_template[0].pValue = &key_class; + priv_key_template[1].pValue = &key_type; + seclen = BN_num_bytes(dh->p); + + if ((sp = pk11_get_session(OP_DH)) == NULL) + goto err; + + mechanism.ulParameterLen = BN_num_bytes(pub_key); + mechanism.pParameter = OPENSSL_malloc(mechanism.ulParameterLen); + if (mechanism.pParameter == NULL) + { + PK11err(PK11_F_DH_COMP_KEY, PK11_R_MALLOC_FAILURE); + goto err; + } + BN_bn2bin(pub_key, mechanism.pParameter); + + (void) check_new_dh_key(sp, dh); + + h_key = sp->opdata_dh_key; + if (h_key == CK_INVALID_HANDLE) + h_key = sp->opdata_dh_key = + pk11_get_dh_key((DH*) dh, &sp->opdata_dh, + &sp->opdata_dh_priv_num, sp->session); + + if (h_key == CK_INVALID_HANDLE) + { + PK11err(PK11_F_DH_COMP_KEY, PK11_R_CREATEOBJECT); + goto err; + } + + rv = pFuncList->C_DeriveKey(sp->session, + &mechanism, + h_key, + priv_key_template, + ul_priv_key_attr_count, + &h_derived_key); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DH_COMP_KEY, PK11_R_DERIVEKEY, rv); + goto err; + } + + rv = pFuncList->C_GetAttributeValue(sp->session, h_derived_key, + priv_key_result, priv_key_attr_result_count); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DH_COMP_KEY, PK11_R_GETATTRIBUTVALUE, + rv); + goto err; + } + + if (((CK_LONG) priv_key_result[0].ulValueLen) <= 0) + { + PK11err(PK11_F_DH_COMP_KEY, PK11_R_GETATTRIBUTVALUE); + goto err; + } + priv_key_result[0].pValue = + OPENSSL_malloc(priv_key_result[0].ulValueLen); + if (!priv_key_result[0].pValue) + { + PK11err(PK11_F_DH_COMP_KEY, PK11_R_MALLOC_FAILURE); + goto err; + } + + rv = pFuncList->C_GetAttributeValue(sp->session, h_derived_key, + priv_key_result, priv_key_attr_result_count); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DH_COMP_KEY, PK11_R_GETATTRIBUTVALUE, + rv); + goto err; + } + + /* + * OpenSSL allocates the output buffer 'key' which is the same + * length of the public key. It is long enough for the derived key + */ + if (priv_key_result[0].type == CKA_VALUE) + { + /* + * CKM_DH_PKCS_DERIVE mechanism is not supposed to strip + * leading zeros from a computed shared secret. However, + * OpenSSL always did it so we must do the same here. The + * vagueness of the spec regarding leading zero bytes was + * finally cleared with TLS 1.1 (RFC 4346) saying that leading + * zeros are stripped before the computed data is used as the + * pre-master secret. + */ + for (i = 0; i < priv_key_result[0].ulValueLen; ++i) + { + if (((char *)priv_key_result[0].pValue)[i] != 0) + break; + } + + (void) memcpy(key, ((char *)priv_key_result[0].pValue) + i, + priv_key_result[0].ulValueLen - i); + ret = priv_key_result[0].ulValueLen - i; + } + +err: + + if (h_derived_key != CK_INVALID_HANDLE) + { + rv = pFuncList->C_DestroyObject(sp->session, h_derived_key); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DH_COMP_KEY, + PK11_R_DESTROYOBJECT, rv); + } + } + if (priv_key_result[0].pValue) + { + OPENSSL_free(priv_key_result[0].pValue); + priv_key_result[0].pValue = NULL; + } + + if (mechanism.pParameter) + { + OPENSSL_free(mechanism.pParameter); + mechanism.pParameter = NULL; + } + + pk11_return_session(sp, OP_DH); + return (ret); + } + + +static CK_OBJECT_HANDLE pk11_get_dh_key(DH* dh, + DH **key_ptr, BIGNUM **dh_priv_num, CK_SESSION_HANDLE session) + { + CK_RV rv; + CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE; + CK_OBJECT_CLASS class = CKO_PRIVATE_KEY; + CK_KEY_TYPE key_type = CKK_DH; + CK_ULONG found; + CK_BBOOL rollback = FALSE; + int i; + + CK_ULONG ul_key_attr_count = 7; + CK_ATTRIBUTE key_template[] = + { + {CKA_CLASS, (void*) NULL, sizeof (class)}, + {CKA_KEY_TYPE, (void*) NULL, sizeof (key_type)}, + {CKA_DERIVE, &mytrue, sizeof (mytrue)}, + {CKA_PRIVATE, &myfalse, sizeof (myfalse)}, + {CKA_PRIME, (void *) NULL, 0}, + {CKA_BASE, (void *) NULL, 0}, + {CKA_VALUE, (void *) NULL, 0}, + }; + + key_template[0].pValue = &class; + key_template[1].pValue = &key_type; + + key_template[4].ulValueLen = BN_num_bytes(dh->p); + key_template[4].pValue = (CK_VOID_PTR)OPENSSL_malloc( + (size_t)key_template[4].ulValueLen); + if (key_template[4].pValue == NULL) + { + PK11err(PK11_F_GET_DH_KEY, PK11_R_MALLOC_FAILURE); + goto malloc_err; + } + + BN_bn2bin(dh->p, key_template[4].pValue); + + key_template[5].ulValueLen = BN_num_bytes(dh->g); + key_template[5].pValue = (CK_VOID_PTR)OPENSSL_malloc( + (size_t)key_template[5].ulValueLen); + if (key_template[5].pValue == NULL) + { + PK11err(PK11_F_GET_DH_KEY, PK11_R_MALLOC_FAILURE); + goto malloc_err; + } + + BN_bn2bin(dh->g, key_template[5].pValue); + + key_template[6].ulValueLen = BN_num_bytes(dh->priv_key); + key_template[6].pValue = (CK_VOID_PTR)OPENSSL_malloc( + (size_t)key_template[6].ulValueLen); + if (key_template[6].pValue == NULL) + { + PK11err(PK11_F_GET_DH_KEY, PK11_R_MALLOC_FAILURE); + goto malloc_err; + } + + BN_bn2bin(dh->priv_key, key_template[6].pValue); + + /* see find_lock array definition for more info on object locking */ + LOCK_OBJSTORE(OP_DH); + rv = pFuncList->C_FindObjectsInit(session, key_template, + ul_key_attr_count); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_DH_KEY, PK11_R_FINDOBJECTSINIT, rv); + goto err; + } + + rv = pFuncList->C_FindObjects(session, &h_key, 1, &found); + + if (rv != CKR_OK) + { + (void) pFuncList->C_FindObjectsFinal(session); + PK11err_add_data(PK11_F_GET_DH_KEY, PK11_R_FINDOBJECTS, rv); + goto err; + } + + rv = pFuncList->C_FindObjectsFinal(session); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_DH_KEY, PK11_R_FINDOBJECTSFINAL, + rv); + goto err; + } + + if (found == 0) + { + rv = pFuncList->C_CreateObject(session, + key_template, ul_key_attr_count, &h_key); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_DH_KEY, PK11_R_CREATEOBJECT, + rv); + goto err; + } + } + + if (dh_priv_num != NULL) + if ((*dh_priv_num = BN_dup(dh->priv_key)) == NULL) + { + PK11err(PK11_F_GET_DH_KEY, PK11_R_MALLOC_FAILURE); + rollback = TRUE; + goto err; + } + + /* LINTED: E_CONSTANT_CONDITION */ + KEY_HANDLE_REFHOLD(h_key, OP_DH, FALSE, rollback, err); + if (key_ptr != NULL) + *key_ptr = dh; + +err: + if (rollback) + { + /* + * We do not care about the return value from C_DestroyObject() + * since we are doing rollback. + */ + if (found == 0) + (void) pFuncList->C_DestroyObject(session, h_key); + h_key = CK_INVALID_HANDLE; + } + + UNLOCK_OBJSTORE(OP_DH); + +malloc_err: + for (i = 4; i <= 6; i++) + { + if (key_template[i].pValue != NULL) + { + OPENSSL_free(key_template[i].pValue); + key_template[i].pValue = NULL; + } + } + + return (h_key); + } + +/* + * Check for cache miss and clean the object pointer and handle + * in such case. Return 1 for cache hit, 0 for cache miss. + * + * Note: we rely on pk11_destroy_dh_key_objects() to set sp->opdata_dh + * to CK_INVALID_HANDLE even when it fails to destroy the object. + */ +static int check_new_dh_key(PK11_SESSION *sp, DH *dh) + { + /* + * Provide protection against DH structure reuse by making the + * check for cache hit stronger. Private key component of DH key + * is unique so it is sufficient to compare it with value cached + * in PK11_SESSION structure. + */ + if ((sp->opdata_dh != dh) || + (BN_cmp(sp->opdata_dh_priv_num, dh->priv_key) != 0)) + { + /* + * We do not check the return value because even in case of + * failure the sp structure will have both key pointer + * and object handle cleaned and pk11_destroy_object() + * reports the failure to the OpenSSL error message buffer. + */ + (void) pk11_destroy_dh_object(sp, TRUE); + return (0); + } + return (1); + } +#endif + +/* + * Local function to simplify key template population + * Return 0 -- error, 1 -- no error + */ +static int +init_template_value(BIGNUM *bn, CK_VOID_PTR *p_value, + CK_ULONG *ul_value_len) + { + CK_ULONG len = 0; + + /* + * This function can be used on non-initialized BIGNUMs. It is + * easier to check that here than individually in the callers. + */ + if (bn != NULL) + len = BN_num_bytes(bn); + + if (bn == NULL || len == 0) + return (1); + + *ul_value_len = len; + *p_value = (CK_VOID_PTR)OPENSSL_malloc((size_t)*ul_value_len); + if (*p_value == NULL) + return (0); + + BN_bn2bin(bn, *p_value); + + return (1); + } + +static void +attr_to_BN(CK_ATTRIBUTE_PTR attr, CK_BYTE attr_data[], BIGNUM **bn) + { + if (attr->ulValueLen > 0) + *bn = BN_bin2bn(attr_data, attr->ulValueLen, NULL); + } + +/* + * Find one object in the token. It is an error if we can not find the + * object or if we find more objects based on the template we got. + * Assume object store locked. + * + * Returns: + * 1 OK + * 0 no object or more than 1 object found + */ +static int +find_one_object(PK11_OPTYPE op, CK_SESSION_HANDLE s, + CK_ATTRIBUTE_PTR ptempl, CK_ULONG nattr, CK_OBJECT_HANDLE_PTR pkey) + { + CK_RV rv; + CK_ULONG objcnt; + + if ((rv = pFuncList->C_FindObjectsInit(s, ptempl, nattr)) != CKR_OK) + { + PK11err_add_data(PK11_F_FIND_ONE_OBJECT, + PK11_R_FINDOBJECTSINIT, rv); + return (0); + } + + rv = pFuncList->C_FindObjects(s, pkey, 1, &objcnt); + if (rv != CKR_OK) + { + (void) pFuncList->C_FindObjectsFinal(s); + PK11err_add_data(PK11_F_FIND_ONE_OBJECT, PK11_R_FINDOBJECTS, + rv); + return (0); + } + + (void) pFuncList->C_FindObjectsFinal(s); + + if (objcnt > 1) + { + PK11err(PK11_F_FIND_ONE_OBJECT, + PK11_R_MORE_THAN_ONE_OBJECT_FOUND); + return (0); + } + else if (objcnt == 0) + { + PK11err(PK11_F_FIND_ONE_OBJECT, PK11_R_NO_OBJECT_FOUND); + return (0); + } + return (1); + } + +/* from uri stuff */ + +extern char *pk11_pin; + +static int pk11_get_pin(void); + +static int +pk11_get_pin(void) +{ + char *pin; + + /* The getpassphrase() function is not MT safe. */ +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_lock(token_lock) == 0); +#else + CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); +#endif + pin = getpassphrase("Enter PIN: "); + if (pin == NULL) + { + PK11err(PK11_F_GET_PIN, PK11_R_COULD_NOT_READ_PIN); +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0); +#else + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + return (0); + } + pk11_pin = BUF_strdup(pin); + if (pk11_pin == NULL) + { + PK11err(PK11_F_LOAD_PRIVKEY, PK11_R_MALLOC_FAILURE); +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0); +#else + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + return (0); + } + memset(pin, 0, strlen(pin)); +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0); +#else + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + return (1); + } + +/* + * Log in to the keystore if we are supposed to do that at all. Take care of + * reading and caching the PIN etc. Log in only once even when called from + * multiple threads. + * + * Returns: + * 1 on success + * 0 on failure + */ +static int +pk11_token_login(CK_SESSION_HANDLE session, CK_BBOOL *login_done, + CK_BBOOL is_private) + { + CK_RV rv; + +#if 0 + /* doesn't work on the AEP Keyper??? */ + if ((pubkey_token_flags & CKF_TOKEN_INITIALIZED) == 0) + { + PK11err(PK11_F_TOKEN_LOGIN, + PK11_R_TOKEN_NOT_INITIALIZED); + return (0); + } +#endif + + /* + * If login is required or needed but the PIN has not been + * even initialized we can bail out right now. Note that we + * are supposed to always log in if we are going to access + * private keys. However, we may need to log in even for + * accessing public keys in case that the CKF_LOGIN_REQUIRED + * flag is set. + */ + if (((pubkey_token_flags & CKF_LOGIN_REQUIRED) || + (is_private == CK_TRUE)) && + (~pubkey_token_flags & CKF_USER_PIN_INITIALIZED)) + { + PK11err(PK11_F_TOKEN_LOGIN, PK11_R_TOKEN_PIN_NOT_SET); + return (0); + } + + /* + * Note on locking: it is possible that more than one thread + * gets into pk11_get_pin() so we must deal with that. We + * cannot avoid it since we cannot guard fork() in there with + * a lock because we could end up in a dead lock in the + * child. Why? Remember we are in a multithreaded environment + * so we must lock all mutexes in the prefork function to + * avoid a situation in which a thread that did not call + * fork() held a lock, making future unlocking impossible. We + * lock right before C_Login(). + */ + if ((pubkey_token_flags & CKF_LOGIN_REQUIRED) || + (is_private == CK_TRUE)) + { + if (*login_done == CK_FALSE) + { + if ((pk11_pin == NULL) && (pk11_get_pin() == 0)) + { + PK11err(PK11_F_TOKEN_LOGIN, + PK11_R_TOKEN_PIN_NOT_PROVIDED); + return (0); + } + } + + /* + * Note that what we are logging into is the keystore from + * pubkey_SLOTID because we work with OP_RSA session type here. + * That also means that we can work with only one keystore in + * the engine. + * + * We must make sure we do not try to login more than once. + * Also, see the comment above on locking strategy. + */ + +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_lock(token_lock) == 0); +#else + CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); +#endif + if (*login_done == CK_FALSE) + { + if ((rv = pFuncList->C_Login(session, + CKU_USER, (CK_UTF8CHAR*)pk11_pin, + strlen(pk11_pin))) != CKR_OK) + { + PK11err_add_data(PK11_F_TOKEN_LOGIN, + PK11_R_TOKEN_LOGIN_FAILED, rv); + goto err_locked; + } + + *login_done = CK_TRUE; + + } +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0); +#else + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + } + else + { + /* + * If token does not require login we take it as the + * login was done. + */ + *login_done = CK_TRUE; + } + + return (1); + +err_locked: + if (pk11_pin) { + memset(pk11_pin, 0, strlen(pk11_pin)); + OPENSSL_free((void*)pk11_pin); + } + pk11_pin = NULL; +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0); +#else + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + return (0); + } + +/* + * Log in to the keystore in the child if we were logged in in the + * parent. There are similarities in the code with pk11_token_login() + * but still it is quite different so we need a separate function for + * this. + * + * Note that this function is called under the locked session mutex when fork is + * detected. That means that C_Login() will be called from the child just once. + * + * Returns: + * 1 on success + * 0 on failure + */ +int +pk11_token_relogin(CK_SESSION_HANDLE session) + { + CK_RV rv; + + if ((pk11_pin == NULL) && (pk11_get_pin() == 0)) + return (0); + +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_lock(token_lock) == 0); +#else + CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); +#endif + if ((rv = pFuncList->C_Login(session, CKU_USER, + (CK_UTF8CHAR_PTR)pk11_pin, strlen(pk11_pin))) != CKR_OK) + { + PK11err_add_data(PK11_F_TOKEN_RELOGIN, + PK11_R_TOKEN_LOGIN_FAILED, rv); +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0); +#else + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + return (0); + } +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0); +#else + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + + return (1); + } + +#ifdef OPENSSL_SYS_WIN32 +char *getpassphrase(const char *prompt) + { + static char buf[128]; + HANDLE h; + DWORD cc, mode; + int cnt; + + h = GetStdHandle(STD_INPUT_HANDLE); + fputs(prompt, stderr); + fflush(stderr); + fflush(stdout); + FlushConsoleInputBuffer(h); + GetConsoleMode(h, &mode); + SetConsoleMode(h, ENABLE_PROCESSED_INPUT); + + for (cnt = 0; cnt < sizeof(buf) - 1; cnt++) + { + ReadFile(h, buf + cnt, 1, &cc, NULL); + if (buf[cnt] == '\r') + break; + fputc('*', stdout); + fflush(stderr); + fflush(stdout); + } + + SetConsoleMode(h, mode); + buf[cnt] = '\0'; + fputs("\n", stderr); + return buf; + } +#endif /* OPENSSL_SYS_WIN32 */ +#endif /* OPENSSL_NO_HW_PK11CA */ +#endif /* OPENSSL_NO_HW_PK11 */ +#endif /* OPENSSL_NO_HW */ Index: openssl/crypto/engine/hw_pk11ca.h diff -u /dev/null openssl/crypto/engine/hw_pk11ca.h:1.4 --- /dev/null Mon Jun 13 15:55:26 2016 +++ openssl/crypto/engine/hw_pk11ca.h Wed Jun 15 21:12:20 2011 @@ -0,0 +1,32 @@ +/* Redefine all pk11/PK11 external symbols to pk11ca/PK11CA */ + +#define token_lock pk11ca_token_lock +#define find_lock pk11ca_find_lock +#define active_list pk11ca_active_list +#define pubkey_token_flags pk11ca_pubkey_token_flags +#define pubkey_SLOTID pk11ca_pubkey_SLOTID +#define ERR_pk11_error ERR_pk11ca_error +#define PK11err_add_data PK11CAerr_add_data +#define pk11_get_session pk11ca_get_session +#define pk11_return_session pk11ca_return_session +#define pk11_active_add pk11ca_active_add +#define pk11_active_delete pk11ca_active_delete +#define pk11_active_remove pk11ca_active_remove +#define pk11_free_active_list pk11ca_free_active_list +#define pk11_destroy_rsa_key_objects pk11ca_destroy_rsa_key_objects +#define pk11_destroy_rsa_object_pub pk11ca_destroy_rsa_object_pub +#define pk11_destroy_rsa_object_priv pk11ca_destroy_rsa_object_priv +#define pk11_load_privkey pk11ca_load_privkey +#define pk11_load_pubkey pk11ca_load_pubkey +#define PK11_RSA PK11CA_RSA +#define pk11_destroy_dsa_key_objects pk11ca_destroy_dsa_key_objects +#define pk11_destroy_dsa_object_pub pk11ca_destroy_dsa_object_pub +#define pk11_destroy_dsa_object_priv pk11ca_destroy_dsa_object_priv +#define PK11_DSA PK11CA_DSA +#define pk11_destroy_dh_key_objects pk11ca_destroy_dh_key_objects +#define pk11_destroy_dh_object pk11ca_destroy_dh_object +#define PK11_DH PK11CA_DH +#define pk11_token_relogin pk11ca_token_relogin +#define pFuncList pk11ca_pFuncList +#define pk11_pin pk11ca_pin +#define ENGINE_load_pk11 ENGINE_load_pk11ca Index: openssl/crypto/engine/hw_pk11so.c diff -u /dev/null openssl/crypto/engine/hw_pk11so.c:1.8 --- /dev/null Mon Jun 13 15:55:26 2016 +++ openssl/crypto/engine/hw_pk11so.c Fri Oct 4 14:05:16 2013 @@ -0,0 +1,1775 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* crypto/engine/hw_pk11.c */ +/* + * This product includes software developed by the OpenSSL Project for + * use in the OpenSSL Toolkit (http://www.openssl.org/). + * + * This project also referenced hw_pkcs11-0.9.7b.patch written by + * Afchine Madjlessi. + */ +/* + * ==================================================================== + * Copyright (c) 2000-2001 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +/* Modified to keep only RNG and RSA Sign */ + +#ifdef OPENSSL_NO_RSA +#error RSA is disabled +#endif + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef OPENSSL_SYS_WIN32 +typedef int pid_t; +#define getpid() GetCurrentProcessId() +#define NOPTHREADS +#ifndef NULL_PTR +#define NULL_PTR NULL +#endif +#define CK_DEFINE_FUNCTION(returnType, name) \ + returnType __declspec(dllexport) name +#define CK_DECLARE_FUNCTION(returnType, name) \ + returnType __declspec(dllimport) name +#define CK_DECLARE_FUNCTION_POINTER(returnType, name) \ + returnType __declspec(dllimport) (* name) +#else +#include +#include +#include +#endif + +/* Debug mutexes */ +/*#undef DEBUG_MUTEX */ +#define DEBUG_MUTEX + +#ifndef NOPTHREADS +/* for pthread error check on Linuxes */ +#ifdef DEBUG_MUTEX +#define __USE_UNIX98 +#endif +#include +#endif + +#ifndef OPENSSL_NO_HW +#ifndef OPENSSL_NO_HW_PK11 +#ifndef OPENSSL_NO_HW_PK11SO + +/* label for debug messages printed on stderr */ +#define PK11_DBG "PKCS#11 ENGINE DEBUG" +/* prints a lot of debug messages on stderr about slot selection process */ +/*#undef DEBUG_SLOT_SELECTION */ + +#ifndef OPENSSL_NO_DSA +#define OPENSSL_NO_DSA +#endif +#ifndef OPENSSL_NO_DH +#define OPENSSL_NO_DH +#endif + +#ifdef OPENSSL_SYS_WIN32 +#pragma pack(push, cryptoki, 1) +#include "cryptoki.h" +#include "pkcs11.h" +#pragma pack(pop, cryptoki) +#else +#include "cryptoki.h" +#include "pkcs11.h" +#endif +#include "hw_pk11so.h" +#include "hw_pk11_err.c" + +/* + * We use this lock to prevent multiple C_Login()s, guard getpassphrase(), + * uri_struct manipulation, and static token info. All of that is used by the + * RSA keys by reference feature. + */ +#ifndef NOPTHREADS +pthread_mutex_t *token_lock; +#endif + +/* PKCS#11 session caches and their locks for all operation types */ +static PK11_CACHE session_cache[OP_MAX]; + +/* + * We cache the flags so that we do not have to run C_GetTokenInfo() again when + * logging into the token. + */ +CK_FLAGS pubkey_token_flags; + +/* + * As stated in v2.20, 11.7 Object Management Function, in section for + * C_FindObjectsInit(), at most one search operation may be active at a given + * time in a given session. Therefore, C_Find{,Init,Final}Objects() should be + * grouped together to form one atomic search operation. This is already + * ensured by the property of unique PKCS#11 session handle used for each + * PK11_SESSION object. + * + * This is however not the biggest concern - maintaining consistency of the + * underlying object store is more important. The same section of the spec also + * says that one thread can be in the middle of a search operation while another + * thread destroys the object matching the search template which would result in + * invalid handle returned from the search operation. + * + * Hence, the following locks are used for both protection of the object stores. + * They are also used for active list protection. + */ +#ifndef NOPTHREADS +pthread_mutex_t *find_lock[OP_MAX] = { NULL }; +#endif + +/* + * lists of asymmetric key handles which are active (referenced by at least one + * PK11_SESSION structure, either held by a thread or present in free_session + * list) for given algorithm type + */ +PK11_active *active_list[OP_MAX] = { NULL }; + +/* + * Create all secret key objects in a global session so that they are available + * to use for other sessions. These other sessions may be opened or closed + * without losing the secret key objects. + */ +static CK_SESSION_HANDLE global_session = CK_INVALID_HANDLE; + +/* ENGINE level stuff */ +static int pk11_init(ENGINE *e); +static int pk11_library_init(ENGINE *e); +static int pk11_finish(ENGINE *e); +static int pk11_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void)); +static int pk11_destroy(ENGINE *e); + +/* RAND stuff */ +static void pk11_rand_seed(const void *buf, int num); +static void pk11_rand_add(const void *buf, int num, double add_entropy); +static void pk11_rand_cleanup(void); +static int pk11_rand_bytes(unsigned char *buf, int num); +static int pk11_rand_status(void); + +/* These functions are also used in other files */ +PK11_SESSION *pk11_get_session(PK11_OPTYPE optype); +void pk11_return_session(PK11_SESSION *sp, PK11_OPTYPE optype); + +/* active list manipulation functions used in this file */ +extern int pk11_active_delete(CK_OBJECT_HANDLE h, PK11_OPTYPE type); +extern void pk11_free_active_list(PK11_OPTYPE type); + +int pk11_destroy_rsa_key_objects(PK11_SESSION *session); +int pk11_destroy_rsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock); +int pk11_destroy_rsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock); + +/* Local helper functions */ +static int pk11_free_all_sessions(void); +static int pk11_free_session_list(PK11_OPTYPE optype); +static int pk11_setup_session(PK11_SESSION *sp, PK11_OPTYPE optype); +static int pk11_destroy_object(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE oh, + CK_BBOOL persistent); +static const char *get_PK11_LIBNAME(void); +static void free_PK11_LIBNAME(void); +static long set_PK11_LIBNAME(const char *name); + +static int pk11_choose_slots(int *any_slot_found); + +static int pk11_init_all_locks(void); +static void pk11_free_all_locks(void); + +#define TRY_OBJ_DESTROY(sp, obj_hdl, retval, uselock, alg_type, priv) \ + { \ + if (uselock) \ + LOCK_OBJSTORE(alg_type); \ + if (pk11_active_delete(obj_hdl, alg_type) == 1) \ + { \ + retval = pk11_destroy_object(sp->session, obj_hdl, \ + priv ? sp->priv_persistent : sp->pub_persistent); \ + } \ + if (uselock) \ + UNLOCK_OBJSTORE(alg_type); \ + } + +static CK_BBOOL pk11_have_rsa = CK_FALSE; +static CK_BBOOL pk11_have_random = CK_FALSE; + +/* + * Initialization function. Sets up various PKCS#11 library components. + * The definitions for control commands specific to this engine + */ +#define PK11_CMD_SO_PATH ENGINE_CMD_BASE +#define PK11_CMD_PIN (ENGINE_CMD_BASE+1) +#define PK11_CMD_SLOT (ENGINE_CMD_BASE+2) +static const ENGINE_CMD_DEFN pk11_cmd_defns[] = + { + { + PK11_CMD_SO_PATH, + "SO_PATH", + "Specifies the path to the 'pkcs#11' shared library", + ENGINE_CMD_FLAG_STRING + }, + { + PK11_CMD_PIN, + "PIN", + "Specifies the pin code", + ENGINE_CMD_FLAG_STRING + }, + { + PK11_CMD_SLOT, + "SLOT", + "Specifies the slot (default is auto select)", + ENGINE_CMD_FLAG_NUMERIC, + }, + {0, NULL, NULL, 0} + }; + + +static RAND_METHOD pk11_random = + { + pk11_rand_seed, + pk11_rand_bytes, + pk11_rand_cleanup, + pk11_rand_add, + pk11_rand_bytes, + pk11_rand_status + }; + + +/* Constants used when creating the ENGINE */ +#ifdef OPENSSL_NO_HW_PK11CA +#error "can't load both crypto-accelerator and sign-only PKCS#11 engines" +#endif +static const char *engine_pk11_id = "pkcs11"; +static const char *engine_pk11_name = "PKCS #11 engine support (sign only)"; + +CK_FUNCTION_LIST_PTR pFuncList = NULL; +static const char PK11_GET_FUNCTION_LIST[] = "C_GetFunctionList"; + +/* + * This is a static string constant for the DSO file name and the function + * symbol names to bind to. We set it in the Configure script based on whether + * this is 32 or 64 bit build. + */ +static const char def_PK11_LIBNAME[] = PK11_LIB_LOCATION; + +/* Needed in hw_pk11_pub.c as well so that's why it is not static. */ +CK_SLOT_ID pubkey_SLOTID = 0; +static CK_SLOT_ID rand_SLOTID = 0; +static CK_SLOT_ID SLOTID = 0; +char *pk11_pin = NULL; +static CK_BBOOL pk11_library_initialized = FALSE; +static CK_BBOOL pk11_atfork_initialized = FALSE; +static int pk11_pid = 0; + +static DSO *pk11_dso = NULL; + +/* allocate and initialize all locks used by the engine itself */ +static int pk11_init_all_locks(void) + { +#ifndef NOPTHREADS + int type; + pthread_mutexattr_t attr; + + if (pthread_mutexattr_init(&attr) != 0) + { + PK11err(PK11_F_INIT_ALL_LOCKS, 100); + return (0); + } + +#ifdef DEBUG_MUTEX + if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK) != 0) + { + PK11err(PK11_F_INIT_ALL_LOCKS, 101); + return (0); + } +#endif + + if ((token_lock = OPENSSL_malloc(sizeof (pthread_mutex_t))) == NULL) + goto malloc_err; + (void) pthread_mutex_init(token_lock, &attr); + + find_lock[OP_RSA] = OPENSSL_malloc(sizeof (pthread_mutex_t)); + if (find_lock[OP_RSA] == NULL) + goto malloc_err; + (void) pthread_mutex_init(find_lock[OP_RSA], &attr); + + for (type = 0; type < OP_MAX; type++) + { + session_cache[type].lock = + OPENSSL_malloc(sizeof (pthread_mutex_t)); + if (session_cache[type].lock == NULL) + goto malloc_err; + (void) pthread_mutex_init(session_cache[type].lock, &attr); + } + + return (1); + +malloc_err: + pk11_free_all_locks(); + PK11err(PK11_F_INIT_ALL_LOCKS, PK11_R_MALLOC_FAILURE); + return (0); +#else + return (1); +#endif + } + +static void pk11_free_all_locks(void) + { +#ifndef NOPTHREADS + int type; + + if (token_lock != NULL) + { + (void) pthread_mutex_destroy(token_lock); + OPENSSL_free(token_lock); + token_lock = NULL; + } + + if (find_lock[OP_RSA] != NULL) + { + (void) pthread_mutex_destroy(find_lock[OP_RSA]); + OPENSSL_free(find_lock[OP_RSA]); + find_lock[OP_RSA] = NULL; + } + + for (type = 0; type < OP_MAX; type++) + { + if (session_cache[type].lock != NULL) + { + (void) pthread_mutex_destroy(session_cache[type].lock); + OPENSSL_free(session_cache[type].lock); + session_cache[type].lock = NULL; + } + } +#endif + } + +/* + * This internal function is used by ENGINE_pk11() and "dynamic" ENGINE support. + */ +static int bind_pk11(ENGINE *e) + { + if (!pk11_library_initialized) + if (!pk11_library_init(e)) + return (0); + + if (!ENGINE_set_id(e, engine_pk11_id) || + !ENGINE_set_name(e, engine_pk11_name)) + return (0); + + if (pk11_have_rsa == CK_TRUE) + { + if (!ENGINE_set_RSA(e, PK11_RSA()) || + !ENGINE_set_load_privkey_function(e, pk11_load_privkey) || + !ENGINE_set_load_pubkey_function(e, pk11_load_pubkey)) + return (0); +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: registered RSA\n", PK11_DBG); +#endif /* DEBUG_SLOT_SELECTION */ + } + + if (pk11_have_random) + { + if (!ENGINE_set_RAND(e, &pk11_random)) + return (0); +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: registered random\n", PK11_DBG); +#endif /* DEBUG_SLOT_SELECTION */ + } + if (!ENGINE_set_init_function(e, pk11_init) || + !ENGINE_set_destroy_function(e, pk11_destroy) || + !ENGINE_set_finish_function(e, pk11_finish) || + !ENGINE_set_ctrl_function(e, pk11_ctrl) || + !ENGINE_set_cmd_defns(e, pk11_cmd_defns)) + return (0); + + /* Ensure the pk11 error handling is set up */ + ERR_load_pk11_strings(); + + return (1); + } + +/* Dynamic engine support is disabled at a higher level for Solaris */ +#ifdef ENGINE_DYNAMIC_SUPPORT +#error "dynamic engine not supported" +static int bind_helper(ENGINE *e, const char *id) + { + if (id && (strcmp(id, engine_pk11_id) != 0)) + return (0); + + if (!bind_pk11(e)) + return (0); + + return (1); + } + +IMPLEMENT_DYNAMIC_CHECK_FN() +IMPLEMENT_DYNAMIC_BIND_FN(bind_helper) + +#else +static ENGINE *engine_pk11(void) + { + ENGINE *ret = ENGINE_new(); + + if (!ret) + return (NULL); + + if (!bind_pk11(ret)) + { + ENGINE_free(ret); + return (NULL); + } + + return (ret); + } + +void +ENGINE_load_pk11(void) + { + ENGINE *e_pk11 = NULL; + + /* + * Do not use dynamic PKCS#11 library on Solaris due to + * security reasons. We will link it in statically. + */ + /* Attempt to load PKCS#11 library */ + if (!pk11_dso) + pk11_dso = DSO_load(NULL, get_PK11_LIBNAME(), NULL, 0); + + if (pk11_dso == NULL) + { + PK11err(PK11_F_LOAD, PK11_R_DSO_FAILURE); + return; + } + + e_pk11 = engine_pk11(); + if (!e_pk11) + { + DSO_free(pk11_dso); + pk11_dso = NULL; + return; + } + + /* + * At this point, the pk11 shared library is either dynamically + * loaded or statically linked in. So, initialize the pk11 + * library before calling ENGINE_set_default since the latter + * needs cipher and digest algorithm information + */ + if (!pk11_library_init(e_pk11)) + { + DSO_free(pk11_dso); + pk11_dso = NULL; + ENGINE_free(e_pk11); + return; + } + + ENGINE_add(e_pk11); + + ENGINE_free(e_pk11); + ERR_clear_error(); + } +#endif /* ENGINE_DYNAMIC_SUPPORT */ + +/* + * These are the static string constants for the DSO file name and + * the function symbol names to bind to. + */ +static const char *PK11_LIBNAME = NULL; + +static const char *get_PK11_LIBNAME(void) + { + if (PK11_LIBNAME) + return (PK11_LIBNAME); + + return (def_PK11_LIBNAME); + } + +static void free_PK11_LIBNAME(void) + { + if (PK11_LIBNAME) + OPENSSL_free((void*)PK11_LIBNAME); + + PK11_LIBNAME = NULL; + } + +static long set_PK11_LIBNAME(const char *name) + { + free_PK11_LIBNAME(); + + return ((PK11_LIBNAME = BUF_strdup(name)) != NULL ? 1 : 0); + } + +/* acquire all engine specific mutexes before fork */ +static void pk11_fork_prepare(void) + { +#ifndef NOPTHREADS + int i; + + if (!pk11_library_initialized) + return; + + LOCK_OBJSTORE(OP_RSA); + OPENSSL_assert(pthread_mutex_lock(token_lock) == 0); + for (i = 0; i < OP_MAX; i++) + { + OPENSSL_assert(pthread_mutex_lock(session_cache[i].lock) == 0); + } +#endif + } + +/* release all engine specific mutexes */ +static void pk11_fork_parent(void) + { +#ifndef NOPTHREADS + int i; + + if (!pk11_library_initialized) + return; + + for (i = OP_MAX - 1; i >= 0; i--) + { + OPENSSL_assert(pthread_mutex_unlock(session_cache[i].lock) == 0); + } + UNLOCK_OBJSTORE(OP_RSA); + OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0); +#endif + } + +/* + * same situation as in parent - we need to unlock all locks to make them + * accessible to all threads. + */ +static void pk11_fork_child(void) + { +#ifndef NOPTHREADS + int i; + + if (!pk11_library_initialized) + return; + + for (i = OP_MAX - 1; i >= 0; i--) + { + OPENSSL_assert(pthread_mutex_unlock(session_cache[i].lock) == 0); + } + UNLOCK_OBJSTORE(OP_RSA); + OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0); +#endif + } + +/* Initialization function for the pk11 engine */ +static int pk11_init(ENGINE *e) +{ + return (pk11_library_init(e)); +} + +static CK_C_INITIALIZE_ARGS pk11_init_args = + { + NULL_PTR, /* CreateMutex */ + NULL_PTR, /* DestroyMutex */ + NULL_PTR, /* LockMutex */ + NULL_PTR, /* UnlockMutex */ + CKF_OS_LOCKING_OK, /* flags */ + NULL_PTR, /* pReserved */ + }; + +/* + * Initialization function. Sets up various PKCS#11 library components. + * It selects a slot based on predefined critiera. In the process, it also + * count how many ciphers and digests to support. Since the cipher and + * digest information is needed when setting default engine, this function + * needs to be called before calling ENGINE_set_default. + */ +/* ARGSUSED */ +static int pk11_library_init(ENGINE *e) + { + CK_C_GetFunctionList p; + CK_RV rv = CKR_OK; + CK_INFO info; + int any_slot_found; + int i; +#ifndef OPENSSL_SYS_WIN32 + struct sigaction sigint_act, sigterm_act, sighup_act; +#endif + + /* + * pk11_library_initialized is set to 0 in pk11_finish() which + * is called from ENGINE_finish(). However, if there is still + * at least one existing functional reference to the engine + * (see engine(3) for more information), pk11_finish() is + * skipped. For example, this can happen if an application + * forgets to clear one cipher context. In case of a fork() + * when the application is finishing the engine so that it can + * be reinitialized in the child, forgotten functional + * reference causes pk11_library_initialized to stay 1. In + * that case we need the PID check so that we properly + * initialize the engine again. + */ + if (pk11_library_initialized) + { + if (pk11_pid == getpid()) + { + return (1); + } + else + { + global_session = CK_INVALID_HANDLE; + /* + * free the locks first to prevent memory leak in case + * the application calls fork() without finishing the + * engine first. + */ + pk11_free_all_locks(); + } + } + + if (pk11_dso == NULL) + { + PK11err(PK11_F_LIBRARY_INIT, PK11_R_DSO_FAILURE); + goto err; + } + + /* get the C_GetFunctionList function from the loaded library */ + p = (CK_C_GetFunctionList)DSO_bind_func(pk11_dso, + PK11_GET_FUNCTION_LIST); + if (!p) + { + PK11err(PK11_F_LIBRARY_INIT, PK11_R_DSO_FAILURE); + goto err; + } + + /* get the full function list from the loaded library */ + rv = p(&pFuncList); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_LIBRARY_INIT, PK11_R_DSO_FAILURE, rv); + goto err; + } + +#ifndef OPENSSL_SYS_WIN32 + /* Not all PKCS#11 library are signal safe! */ + + (void) memset(&sigint_act, 0, sizeof(sigint_act)); + (void) memset(&sigterm_act, 0, sizeof(sigterm_act)); + (void) memset(&sighup_act, 0, sizeof(sighup_act)); + (void) sigaction(SIGINT, NULL, &sigint_act); + (void) sigaction(SIGTERM, NULL, &sigterm_act); + (void) sigaction(SIGHUP, NULL, &sighup_act); +#endif + rv = pFuncList->C_Initialize((CK_VOID_PTR)&pk11_init_args); +#ifndef OPENSSL_SYS_WIN32 + (void) sigaction(SIGINT, &sigint_act, NULL); + (void) sigaction(SIGTERM, &sigterm_act, NULL); + (void) sigaction(SIGHUP, &sighup_act, NULL); +#endif + if ((rv != CKR_OK) && (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)) + { + PK11err_add_data(PK11_F_LIBRARY_INIT, PK11_R_INITIALIZE, rv); + goto err; + } + + rv = pFuncList->C_GetInfo(&info); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_LIBRARY_INIT, PK11_R_GETINFO, rv); + goto err; + } + + if (pk11_choose_slots(&any_slot_found) == 0) + goto err; + + /* + * The library we use, set in def_PK11_LIBNAME, may not offer any + * slot(s). In that case, we must not proceed but we must not return an + * error. The reason is that applications that try to set up the PKCS#11 + * engine don't exit on error during the engine initialization just + * because no slot was present. + */ + if (any_slot_found == 0) + return (1); + + if (global_session == CK_INVALID_HANDLE) + { + /* Open the global_session for the new process */ + rv = pFuncList->C_OpenSession(SLOTID, CKF_SERIAL_SESSION, + NULL_PTR, NULL_PTR, &global_session); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_LIBRARY_INIT, + PK11_R_OPENSESSION, rv); + goto err; + } + } + + pk11_library_initialized = TRUE; + pk11_pid = getpid(); + /* + * if initialization of the locks fails pk11_init_all_locks() + * will do the cleanup. + */ + if (!pk11_init_all_locks()) + goto err; + for (i = 0; i < OP_MAX; i++) + session_cache[i].head = NULL; + /* + * initialize active lists. We only use active lists + * for asymmetric ciphers. + */ + for (i = 0; i < OP_MAX; i++) + active_list[i] = NULL; + +#ifndef NOPTHREADS + if (!pk11_atfork_initialized) + { + if (pthread_atfork(pk11_fork_prepare, pk11_fork_parent, + pk11_fork_child) != 0) + { + PK11err(PK11_F_LIBRARY_INIT, PK11_R_ATFORK_FAILED); + goto err; + } + pk11_atfork_initialized = TRUE; + } +#endif + + return (1); + +err: + return (0); + } + +/* Destructor (complements the "ENGINE_pk11()" constructor) */ +/* ARGSUSED */ +static int pk11_destroy(ENGINE *e) + { + free_PK11_LIBNAME(); + ERR_unload_pk11_strings(); + if (pk11_pin) { + memset(pk11_pin, 0, strlen(pk11_pin)); + OPENSSL_free((void*)pk11_pin); + } + pk11_pin = NULL; + return (1); + } + +/* + * Termination function to clean up the session, the token, and the pk11 + * library. + */ +/* ARGSUSED */ +static int pk11_finish(ENGINE *e) + { + int i; + + if (pk11_pin) { + memset(pk11_pin, 0, strlen(pk11_pin)); + OPENSSL_free((void*)pk11_pin); + } + pk11_pin = NULL; + + if (pk11_dso == NULL) + { + PK11err(PK11_F_FINISH, PK11_R_NOT_LOADED); + goto err; + } + + OPENSSL_assert(pFuncList != NULL); + + if (pk11_free_all_sessions() == 0) + goto err; + + /* free all active lists */ + for (i = 0; i < OP_MAX; i++) + pk11_free_active_list(i); + + pFuncList->C_CloseSession(global_session); + global_session = CK_INVALID_HANDLE; + + /* + * Since we are part of a library (libcrypto.so), calling this function + * may have side-effects. + */ +#if 0 + pFuncList->C_Finalize(NULL); +#endif + + if (!DSO_free(pk11_dso)) + { + PK11err(PK11_F_FINISH, PK11_R_DSO_FAILURE); + goto err; + } + pk11_dso = NULL; + pFuncList = NULL; + pk11_library_initialized = FALSE; + pk11_pid = 0; + /* + * There is no way how to unregister atfork handlers (other than + * unloading the library) so we just free the locks. For this reason + * the atfork handlers check if the engine is initialized and bail out + * immediately if not. This is necessary in case a process finishes + * the engine before calling fork(). + */ + pk11_free_all_locks(); + + return (1); + +err: + return (0); + } + +/* Standard engine interface function to set the dynamic library path */ +/* ARGSUSED */ +static int pk11_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void)) + { + int initialized = ((pk11_dso == NULL) ? 0 : 1); + + switch (cmd) + { + case PK11_CMD_SO_PATH: + if (p == NULL) + { + PK11err(PK11_F_CTRL, ERR_R_PASSED_NULL_PARAMETER); + return (0); + } + + if (initialized) + { + PK11err(PK11_F_CTRL, PK11_R_ALREADY_LOADED); + return (0); + } + + return (set_PK11_LIBNAME((const char *)p)); + case PK11_CMD_PIN: + if (pk11_pin) { + memset(pk11_pin, 0, strlen(pk11_pin)); + OPENSSL_free((void*)pk11_pin); + } + pk11_pin = NULL; + + if (p == NULL) + { + PK11err(PK11_F_CTRL, ERR_R_PASSED_NULL_PARAMETER); + return (0); + } + + pk11_pin = BUF_strdup(p); + if (pk11_pin == NULL) + { + PK11err(PK11_F_GET_SESSION, PK11_R_MALLOC_FAILURE); + return (0); + } + return (1); + case PK11_CMD_SLOT: + SLOTID = (CK_SLOT_ID)i; +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: slot set\n", PK11_DBG); +#endif + return (1); + default: + break; + } + + PK11err(PK11_F_CTRL, PK11_R_CTRL_COMMAND_NOT_IMPLEMENTED); + + return (0); + } + + +/* Required function by the engine random interface. It does nothing here */ +static void pk11_rand_cleanup(void) + { + return; + } + +/* ARGSUSED */ +static void pk11_rand_add(const void *buf, int num, double add) + { + PK11_SESSION *sp; + + if ((sp = pk11_get_session(OP_RAND)) == NULL) + return; + + /* + * Ignore any errors (e.g. CKR_RANDOM_SEED_NOT_SUPPORTED) since + * the calling functions do not care anyway + */ + pFuncList->C_SeedRandom(sp->session, (unsigned char *) buf, num); + pk11_return_session(sp, OP_RAND); + + return; + } + +static void pk11_rand_seed(const void *buf, int num) + { + pk11_rand_add(buf, num, 0); + } + +static int pk11_rand_bytes(unsigned char *buf, int num) + { + CK_RV rv; + PK11_SESSION *sp; + + if ((sp = pk11_get_session(OP_RAND)) == NULL) + return (0); + + rv = pFuncList->C_GenerateRandom(sp->session, buf, num); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_RAND_BYTES, PK11_R_GENERATERANDOM, rv); + pk11_return_session(sp, OP_RAND); + return (0); + } + + pk11_return_session(sp, OP_RAND); + return (1); + } + +/* Required function by the engine random interface. It does nothing here */ +static int pk11_rand_status(void) + { + return (1); + } + +/* Free all BIGNUM structures from PK11_SESSION. */ +static void pk11_free_nums(PK11_SESSION *sp, PK11_OPTYPE optype) + { + switch (optype) + { + case OP_RSA: + if (sp->opdata_rsa_n_num != NULL) + { + BN_free(sp->opdata_rsa_n_num); + sp->opdata_rsa_n_num = NULL; + } + if (sp->opdata_rsa_e_num != NULL) + { + BN_free(sp->opdata_rsa_e_num); + sp->opdata_rsa_e_num = NULL; + } + if (sp->opdata_rsa_pn_num != NULL) + { + BN_free(sp->opdata_rsa_pn_num); + sp->opdata_rsa_pn_num = NULL; + } + if (sp->opdata_rsa_pe_num != NULL) + { + BN_free(sp->opdata_rsa_pe_num); + sp->opdata_rsa_pe_num = NULL; + } + if (sp->opdata_rsa_d_num != NULL) + { + BN_free(sp->opdata_rsa_d_num); + sp->opdata_rsa_d_num = NULL; + } + break; + default: + break; + } + } + +/* + * Get new PK11_SESSION structure ready for use. Every process must have + * its own freelist of PK11_SESSION structures so handle fork() here + * by destroying the old and creating new freelist. + * The returned PK11_SESSION structure is disconnected from the freelist. + */ +PK11_SESSION * +pk11_get_session(PK11_OPTYPE optype) + { + PK11_SESSION *sp = NULL, *sp1, *freelist; +#ifndef NOPTHREADS + pthread_mutex_t *freelist_lock = NULL; +#endif + static pid_t pid = 0; + pid_t new_pid; + CK_RV rv; + + switch (optype) + { + case OP_RSA: + case OP_DSA: + case OP_DH: + case OP_RAND: + case OP_DIGEST: + case OP_CIPHER: +#ifndef NOPTHREADS + freelist_lock = session_cache[optype].lock; +#endif + break; + default: + PK11err(PK11_F_GET_SESSION, + PK11_R_INVALID_OPERATION_TYPE); + return (NULL); + } +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_lock(freelist_lock) == 0); +#else + CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); +#endif + + /* + * Will use it to find out if we forked. We cannot use the PID field in + * the session structure because we could get a newly allocated session + * here, with no PID information. + */ + if (pid == 0) + pid = getpid(); + + freelist = session_cache[optype].head; + sp = freelist; + + /* + * If the free list is empty, allocate new unitialized (filled + * with zeroes) PK11_SESSION structure otherwise return first + * structure from the freelist. + */ + if (sp == NULL) + { + if ((sp = OPENSSL_malloc(sizeof (PK11_SESSION))) == NULL) + { + PK11err(PK11_F_GET_SESSION, + PK11_R_MALLOC_FAILURE); + goto err; + } + (void) memset(sp, 0, sizeof (PK11_SESSION)); + + /* + * It is a new session so it will look like a cache miss to the + * code below. So, we must not try to to destroy its members so + * mark them as unused. + */ + sp->opdata_rsa_priv_key = CK_INVALID_HANDLE; + sp->opdata_rsa_pub_key = CK_INVALID_HANDLE; + } + else + { + freelist = sp->next; + } + + /* + * Check whether we have forked. In that case, we must get rid of all + * inherited sessions and start allocating new ones. + */ + if (pid != (new_pid = getpid())) + { + pid = new_pid; + + /* + * We are a new process and thus need to free any inherited + * PK11_SESSION objects aside from the first session (sp) which + * is the only PK11_SESSION structure we will reuse (for the + * head of the list). + */ + while ((sp1 = freelist) != NULL) + { + freelist = sp1->next; + /* + * NOTE: we do not want to call pk11_free_all_sessions() + * here because it would close underlying PKCS#11 + * sessions and destroy all objects. + */ + pk11_free_nums(sp1, optype); + OPENSSL_free(sp1); + } + + /* we have to free the active list as well. */ + pk11_free_active_list(optype); + + /* Initialize the process */ + rv = pFuncList->C_Initialize((CK_VOID_PTR)&pk11_init_args); + if ((rv != CKR_OK) && (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)) + { + PK11err_add_data(PK11_F_GET_SESSION, PK11_R_INITIALIZE, + rv); + OPENSSL_free(sp); + sp = NULL; + goto err; + } + + /* + * Choose slot here since the slot table is different on this + * process. If we are here then we must have found at least one + * usable slot before so we don't need to check any_slot_found. + * See pk11_library_init()'s usage of this function for more + * information. + */ + if (pk11_choose_slots(NULL) == 0) + goto err; + + /* Open the global_session for the new process */ + rv = pFuncList->C_OpenSession(SLOTID, CKF_SERIAL_SESSION, + NULL_PTR, NULL_PTR, &global_session); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_SESSION, PK11_R_OPENSESSION, + rv); + OPENSSL_free(sp); + sp = NULL; + goto err; + } + + /* + * It is an inherited session from our parent so it needs + * re-initialization. + */ + if (pk11_setup_session(sp, optype) == 0) + { + OPENSSL_free(sp); + sp = NULL; + goto err; + } + if (pk11_token_relogin(sp->session) == 0) + { + /* + * We will keep the session in the cache list and let + * the caller cope with the situation. + */ + freelist = sp; + sp = NULL; + goto err; + } + } + + if (sp->pid == 0) + { + /* It is a new session and needs initialization. */ + if (pk11_setup_session(sp, optype) == 0) + { + OPENSSL_free(sp); + sp = NULL; + } + } + + /* set new head for the list of PK11_SESSION objects */ + session_cache[optype].head = freelist; + +err: + if (sp != NULL) + sp->next = NULL; + +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_unlock(freelist_lock) == 0); +#else + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + + return (sp); + } + + +void +pk11_return_session(PK11_SESSION *sp, PK11_OPTYPE optype) + { +#ifndef NOPTHREADS + pthread_mutex_t *freelist_lock; +#endif + PK11_SESSION *freelist; + + /* + * If this is a session from the parent it will be taken care of and + * freed in pk11_get_session() as part of the post-fork clean up the + * next time we will ask for a new session. + */ + if (sp == NULL || sp->pid != getpid()) + return; + + switch (optype) + { + case OP_RSA: + case OP_DSA: + case OP_DH: + case OP_RAND: + case OP_DIGEST: + case OP_CIPHER: +#ifndef NOPTHREADS + freelist_lock = session_cache[optype].lock; +#endif + break; + default: + PK11err(PK11_F_RETURN_SESSION, + PK11_R_INVALID_OPERATION_TYPE); + return; + } + +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_lock(freelist_lock) == 0); +#else + CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); +#endif + freelist = session_cache[optype].head; + sp->next = freelist; + session_cache[optype].head = sp; +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_unlock(freelist_lock) == 0); +#else + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + } + + +/* Destroy all objects. This function is called when the engine is finished */ +static int pk11_free_all_sessions() + { + int ret = 1; + int type; + + (void) pk11_destroy_rsa_key_objects(NULL); + + /* + * We try to release as much as we can but any error means that we will + * return 0 on exit. + */ + for (type = 0; type < OP_MAX; type++) + { + if (pk11_free_session_list(type) == 0) + ret = 0; + } + + return (ret); + } + +/* + * Destroy session structures from the linked list specified. Free as many + * sessions as possible but any failure in C_CloseSession() means that we + * return an error on return. + */ +static int pk11_free_session_list(PK11_OPTYPE optype) + { + CK_RV rv; + PK11_SESSION *sp = NULL; + PK11_SESSION *freelist = NULL; + pid_t mypid = getpid(); +#ifndef NOPTHREADS + pthread_mutex_t *freelist_lock; +#endif + int ret = 1; + + switch (optype) + { + case OP_RSA: + case OP_DSA: + case OP_DH: + case OP_RAND: + case OP_DIGEST: + case OP_CIPHER: +#ifndef NOPTHREADS + freelist_lock = session_cache[optype].lock; +#endif + break; + default: + PK11err(PK11_F_FREE_ALL_SESSIONS, + PK11_R_INVALID_OPERATION_TYPE); + return (0); + } + +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_lock(freelist_lock) == 0); +#else + CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); +#endif + freelist = session_cache[optype].head; + while ((sp = freelist) != NULL) + { + if (sp->session != CK_INVALID_HANDLE && sp->pid == mypid) + { + rv = pFuncList->C_CloseSession(sp->session); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_FREE_ALL_SESSIONS, + PK11_R_CLOSESESSION, rv); + ret = 0; + } + } + freelist = sp->next; + pk11_free_nums(sp, optype); + OPENSSL_free(sp); + } + +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_unlock(freelist_lock) == 0); +#else + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + return (ret); + } + + +static int +pk11_setup_session(PK11_SESSION *sp, PK11_OPTYPE optype) + { + CK_RV rv; + CK_SLOT_ID myslot; + + switch (optype) + { + case OP_RSA: + myslot = pubkey_SLOTID; + break; + case OP_RAND: + myslot = rand_SLOTID; + break; + default: + PK11err(PK11_F_SETUP_SESSION, + PK11_R_INVALID_OPERATION_TYPE); + return (0); + } + + sp->session = CK_INVALID_HANDLE; +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: myslot=%d optype=%d\n", PK11_DBG, myslot, optype); +#endif /* DEBUG_SLOT_SELECTION */ + rv = pFuncList->C_OpenSession(myslot, CKF_SERIAL_SESSION, + NULL_PTR, NULL_PTR, &sp->session); + if (rv == CKR_CRYPTOKI_NOT_INITIALIZED) + { + /* + * We are probably a child process so force the + * reinitialize of the session + */ + pk11_library_initialized = FALSE; + if (!pk11_library_init(NULL)) + return (0); + rv = pFuncList->C_OpenSession(myslot, CKF_SERIAL_SESSION, + NULL_PTR, NULL_PTR, &sp->session); + } + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_SETUP_SESSION, PK11_R_OPENSESSION, rv); + return (0); + } + + sp->pid = getpid(); + + if (optype == OP_RSA) + { + sp->opdata_rsa_pub_key = CK_INVALID_HANDLE; + sp->opdata_rsa_priv_key = CK_INVALID_HANDLE; + sp->opdata_rsa_pub = NULL; + sp->opdata_rsa_n_num = NULL; + sp->opdata_rsa_e_num = NULL; + sp->opdata_rsa_priv = NULL; + sp->opdata_rsa_pn_num = NULL; + sp->opdata_rsa_pe_num = NULL; + sp->opdata_rsa_d_num = NULL; + } + + /* + * We always initialize the session as containing a non-persistent + * object. The key load functions set it to persistent if that is so. + */ + sp->pub_persistent = CK_FALSE; + sp->priv_persistent = CK_FALSE; + return (1); + } + +/* Destroy RSA public key from single session. */ +int +pk11_destroy_rsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock) + { + int ret = 0; + + if (sp->opdata_rsa_pub_key != CK_INVALID_HANDLE) + { + TRY_OBJ_DESTROY(sp, sp->opdata_rsa_pub_key, + ret, uselock, OP_RSA, CK_FALSE); + sp->opdata_rsa_pub_key = CK_INVALID_HANDLE; + sp->opdata_rsa_pub = NULL; + if (sp->opdata_rsa_n_num != NULL) + { + BN_free(sp->opdata_rsa_n_num); + sp->opdata_rsa_n_num = NULL; + } + if (sp->opdata_rsa_e_num != NULL) + { + BN_free(sp->opdata_rsa_e_num); + sp->opdata_rsa_e_num = NULL; + } + } + + return (ret); + } + +/* Destroy RSA private key from single session. */ +int +pk11_destroy_rsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock) + { + int ret = 0; + + if (sp->opdata_rsa_priv_key != CK_INVALID_HANDLE) + { + TRY_OBJ_DESTROY(sp, sp->opdata_rsa_priv_key, + ret, uselock, OP_RSA, CK_TRUE); + sp->opdata_rsa_priv_key = CK_INVALID_HANDLE; + sp->opdata_rsa_priv = NULL; + if (sp->opdata_rsa_d_num != NULL) + { + BN_free(sp->opdata_rsa_d_num); + sp->opdata_rsa_d_num = NULL; + } + + /* + * For the RSA key by reference code, public components 'n'/'e' + * are the key components we use to check for the cache hit. We + * must free those as well. + */ + if (sp->opdata_rsa_pn_num != NULL) + { + BN_free(sp->opdata_rsa_pn_num); + sp->opdata_rsa_pn_num = NULL; + } + if (sp->opdata_rsa_pe_num != NULL) + { + BN_free(sp->opdata_rsa_pe_num); + sp->opdata_rsa_pe_num = NULL; + } + } + + return (ret); + } + +/* + * Destroy RSA key object wrapper. If session is NULL, try to destroy all + * objects in the free list. + */ +int +pk11_destroy_rsa_key_objects(PK11_SESSION *session) + { + int ret = 1; + PK11_SESSION *sp = NULL; + PK11_SESSION *local_free_session; + CK_BBOOL uselock = TRUE; + + if (session != NULL) + local_free_session = session; + else + { +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_lock(session_cache[OP_RSA].lock) == 0); +#else + CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); +#endif + local_free_session = session_cache[OP_RSA].head; + uselock = FALSE; + } + + /* + * go through the list of sessions and delete key objects + */ + while ((sp = local_free_session) != NULL) + { + local_free_session = sp->next; + + /* + * Do not terminate list traversal if one of the + * destroy operations fails. + */ + if (pk11_destroy_rsa_object_pub(sp, uselock) == 0) + { + ret = 0; + continue; + } + if (pk11_destroy_rsa_object_priv(sp, uselock) == 0) + { + ret = 0; + continue; + } + } + +#ifndef NOPTHREADS + if (session == NULL) + OPENSSL_assert(pthread_mutex_unlock(session_cache[OP_RSA].lock) == 0); +#else + if (session == NULL) + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + + return (ret); + } + +static int +pk11_destroy_object(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE oh, + CK_BBOOL persistent) + { + CK_RV rv; + + /* + * We never try to destroy persistent objects which are the objects + * stored in the keystore. Also, we always use read-only sessions so + * C_DestroyObject() would be returning CKR_SESSION_READ_ONLY here. + */ + if (persistent == CK_TRUE) + return (1); + + rv = pFuncList->C_DestroyObject(session, oh); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DESTROY_OBJECT, PK11_R_DESTROYOBJECT, + rv); + return (0); + } + + return (1); + } + + +/* + * Public key mechanisms optionally supported + * + * CKM_RSA_PKCS + * + * The first slot that supports at least one of those mechanisms is chosen as a + * public key slot. + * + * The output of this function is a set of global variables indicating which + * mechanisms from RSA, DSA, DH and RAND are present, and also two arrays of + * mechanisms, one for symmetric ciphers and one for digests. Also, 3 global + * variables carry information about which slot was chosen for (a) public key + * mechanisms, (b) random operations, and (c) symmetric ciphers and digests. + */ +static int +pk11_choose_slots(int *any_slot_found) + { + CK_SLOT_ID_PTR pSlotList = NULL_PTR; + CK_ULONG ulSlotCount = 0; + CK_MECHANISM_INFO mech_info; + CK_TOKEN_INFO token_info; + unsigned int i; + CK_RV rv; + CK_SLOT_ID best_slot_sofar = 0; + CK_BBOOL found_candidate_slot = CK_FALSE; + CK_SLOT_ID current_slot = 0; + + /* let's initialize the output parameter */ + if (any_slot_found != NULL) + *any_slot_found = 0; + + /* Get slot list for memory allocation */ + rv = pFuncList->C_GetSlotList(CK_FALSE, NULL_PTR, &ulSlotCount); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_CHOOSE_SLOT, PK11_R_GETSLOTLIST, rv); + return (0); + } + + /* it's not an error if we didn't find any providers */ + if (ulSlotCount == 0) + { +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: no crypto providers found\n", PK11_DBG); +#endif /* DEBUG_SLOT_SELECTION */ + return (1); + } + + pSlotList = OPENSSL_malloc(ulSlotCount * sizeof (CK_SLOT_ID)); + + if (pSlotList == NULL) + { + PK11err(PK11_F_CHOOSE_SLOT, PK11_R_MALLOC_FAILURE); + return (0); + } + + /* Get the slot list for processing */ + rv = pFuncList->C_GetSlotList(CK_FALSE, pSlotList, &ulSlotCount); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_CHOOSE_SLOT, PK11_R_GETSLOTLIST, rv); + OPENSSL_free(pSlotList); + return (0); + } + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: provider: %s\n", PK11_DBG, def_PK11_LIBNAME); + fprintf(stderr, "%s: number of slots: %d\n", PK11_DBG, ulSlotCount); + + fprintf(stderr, "%s: == checking rand slots ==\n", PK11_DBG); +#endif /* DEBUG_SLOT_SELECTION */ + for (i = 0; i < ulSlotCount; i++) + { + current_slot = pSlotList[i]; + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: checking slot: %d\n", PK11_DBG, i); +#endif /* DEBUG_SLOT_SELECTION */ + /* Check if slot has random support. */ + rv = pFuncList->C_GetTokenInfo(current_slot, &token_info); + if (rv != CKR_OK) + continue; + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: token label: %.32s\n", PK11_DBG, token_info.label); +#endif /* DEBUG_SLOT_SELECTION */ + + if (token_info.flags & CKF_RNG) + { +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: this token has CKF_RNG flag\n", PK11_DBG); +#endif /* DEBUG_SLOT_SELECTION */ + pk11_have_random = CK_TRUE; + rand_SLOTID = current_slot; + break; + } + } + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: == checking pubkey slots ==\n", PK11_DBG); +#endif /* DEBUG_SLOT_SELECTION */ + + pubkey_SLOTID = pSlotList[0]; + for (i = 0; i < ulSlotCount; i++) + { + CK_BBOOL slot_has_rsa = CK_FALSE; + current_slot = pSlotList[i]; + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: checking slot: %d\n", PK11_DBG, i); +#endif /* DEBUG_SLOT_SELECTION */ + rv = pFuncList->C_GetTokenInfo(current_slot, &token_info); + if (rv != CKR_OK) + continue; + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, "%s: token label: %.32s\n", PK11_DBG, token_info.label); +#endif /* DEBUG_SLOT_SELECTION */ + + /* + * Check if this slot is capable of signing with CKM_RSA_PKCS. + */ + rv = pFuncList->C_GetMechanismInfo(current_slot, CKM_RSA_PKCS, + &mech_info); + + if (rv == CKR_OK && ((mech_info.flags & CKF_SIGN))) + { + slot_has_rsa = CK_TRUE; + } + + if (!found_candidate_slot && slot_has_rsa) + { +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, + "%s: potential slot: %d\n", PK11_DBG, current_slot); +#endif /* DEBUG_SLOT_SELECTION */ + best_slot_sofar = current_slot; + pk11_have_rsa = slot_has_rsa; + found_candidate_slot = CK_TRUE; + /* + * Cache the flags for later use. We might + * need those if RSA keys by reference feature + * is used. + */ + pubkey_token_flags = token_info.flags; +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, + "%s: setting found_candidate_slot to CK_TRUE\n", + PK11_DBG); + fprintf(stderr, + "%s: best so far slot: %d\n", PK11_DBG, + best_slot_sofar); + fprintf(stderr, "%s: pubkey flags changed to " + "%lu.\n", PK11_DBG, pubkey_token_flags); + } + else + { + fprintf(stderr, + "%s: no rsa\n", PK11_DBG); + } +#else + } /* if */ +#endif /* DEBUG_SLOT_SELECTION */ + } /* for */ + + if (found_candidate_slot == CK_TRUE) + { + pubkey_SLOTID = best_slot_sofar; + } + + /*SLOTID = pSlotList[0];*/ + +#ifdef DEBUG_SLOT_SELECTION + fprintf(stderr, + "%s: chosen pubkey slot: %d\n", PK11_DBG, pubkey_SLOTID); + fprintf(stderr, + "%s: chosen rand slot: %d\n", PK11_DBG, rand_SLOTID); + fprintf(stderr, + "%s: pk11_have_rsa %d\n", PK11_DBG, pk11_have_rsa); + fprintf(stderr, + "%s: pk11_have_random %d\n", PK11_DBG, pk11_have_random); +#endif /* DEBUG_SLOT_SELECTION */ + + if (pSlotList != NULL) + OPENSSL_free(pSlotList); + + if (any_slot_found != NULL) + *any_slot_found = 1; + return (1); + } + +#endif /* OPENSSL_NO_HW_PK11SO */ +#endif /* OPENSSL_NO_HW_PK11 */ +#endif /* OPENSSL_NO_HW */ Index: openssl/crypto/engine/hw_pk11so.h diff -u /dev/null openssl/crypto/engine/hw_pk11so.h:1.4 --- /dev/null Mon Jun 13 15:55:26 2016 +++ openssl/crypto/engine/hw_pk11so.h Wed Jun 15 21:12:20 2011 @@ -0,0 +1,32 @@ +/* Redefine all pk11/PK11 external symbols to pk11so/PK11SO */ + +#define token_lock pk11so_token_lock +#define find_lock pk11so_find_lock +#define active_list pk11so_active_list +#define pubkey_token_flags pk11so_pubkey_token_flags +#define pubkey_SLOTID pk11so_pubkey_SLOTID +#define ERR_pk11_error ERR_pk11so_error +#define PK11err_add_data PK11SOerr_add_data +#define pk11_get_session pk11so_get_session +#define pk11_return_session pk11so_return_session +#define pk11_active_add pk11so_active_add +#define pk11_active_delete pk11so_active_delete +#define pk11_active_remove pk11so_active_remove +#define pk11_free_active_list pk11so_free_active_list +#define pk11_destroy_rsa_key_objects pk11so_destroy_rsa_key_objects +#define pk11_destroy_rsa_object_pub pk11so_destroy_rsa_object_pub +#define pk11_destroy_rsa_object_priv pk11so_destroy_rsa_object_priv +#define pk11_load_privkey pk11so_load_privkey +#define pk11_load_pubkey pk11so_load_pubkey +#define PK11_RSA PK11SO_RSA +#define pk11_destroy_dsa_key_objects pk11so_destroy_dsa_key_objects +#define pk11_destroy_dsa_object_pub pk11so_destroy_dsa_object_pub +#define pk11_destroy_dsa_object_priv pk11so_destroy_dsa_object_priv +#define PK11_DSA PK11SO_DSA +#define pk11_destroy_dh_key_objects pk11so_destroy_dh_key_objects +#define pk11_destroy_dh_object pk11so_destroy_dh_object +#define PK11_DH PK11SO_DH +#define pk11_token_relogin pk11so_token_relogin +#define pFuncList pk11so_pFuncList +#define pk11_pin pk11so_pin +#define ENGINE_load_pk11 ENGINE_load_pk11so Index: openssl/crypto/engine/hw_pk11so_pub.c diff -u /dev/null openssl/crypto/engine/hw_pk11so_pub.c:1.10 --- /dev/null Mon Jun 13 15:55:26 2016 +++ openssl/crypto/engine/hw_pk11so_pub.c Fri Oct 4 14:05:38 2013 @@ -0,0 +1,1642 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* crypto/engine/hw_pk11_pub.c */ +/* + * This product includes software developed by the OpenSSL Project for + * use in the OpenSSL Toolkit (http://www.openssl.org/). + * + * This project also referenced hw_pkcs11-0.9.7b.patch written by + * Afchine Madjlessi. + */ +/* + * ==================================================================== + * Copyright (c) 2000-2001 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +/* Modified to keep only RNG and RSA Sign */ + +#ifdef OPENSSL_NO_RSA +#error RSA is disabled +#endif + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef OPENSSL_SYS_WIN32 +#define NOPTHREADS +typedef int pid_t; +#define HAVE_GETPASSPHRASE +static char *getpassphrase(const char *prompt); +#ifndef NULL_PTR +#define NULL_PTR NULL +#endif +#define CK_DEFINE_FUNCTION(returnType, name) \ + returnType __declspec(dllexport) name +#define CK_DECLARE_FUNCTION(returnType, name) \ + returnType __declspec(dllimport) name +#define CK_DECLARE_FUNCTION_POINTER(returnType, name) \ + returnType __declspec(dllimport) (* name) +#else +#include +#endif + +#ifndef NOPTHREADS +#include +#endif + +#ifndef OPENSSL_NO_HW +#ifndef OPENSSL_NO_HW_PK11 +#ifndef OPENSSL_NO_HW_PK11SO + +#ifdef OPENSSL_SYS_WIN32 +#pragma pack(push, cryptoki, 1) +#include "cryptoki.h" +#include "pkcs11.h" +#pragma pack(pop, cryptoki) +#else +#include "cryptoki.h" +#include "pkcs11.h" +#endif +#include "hw_pk11so.h" +#include "hw_pk11_err.h" + +static CK_BBOOL pk11_login_done = CK_FALSE; +extern CK_SLOT_ID pubkey_SLOTID; +#ifndef NOPTHREADS +extern pthread_mutex_t *token_lock; +#endif + +#if !(defined(HAVE_GETPASSPHRASE) || (defined (__SVR4) && defined (__sun))) +#define getpassphrase(x) getpass(x) +#endif + +/* RSA stuff */ +static int pk11_RSA_sign(int type, const unsigned char *m, unsigned int m_len, + unsigned char *sigret, unsigned int *siglen, const RSA *rsa); +EVP_PKEY *pk11_load_privkey(ENGINE*, const char *privkey_file, + UI_METHOD *ui_method, void *callback_data); +EVP_PKEY *pk11_load_pubkey(ENGINE*, const char *pubkey_file, + UI_METHOD *ui_method, void *callback_data); + +static CK_OBJECT_HANDLE pk11_get_public_rsa_key(RSA* rsa, RSA** key_ptr, + BIGNUM **rsa_n_num, BIGNUM **rsa_e_num, CK_SESSION_HANDLE session); +static CK_OBJECT_HANDLE pk11_get_private_rsa_key(RSA* rsa, RSA** key_ptr, + BIGNUM **rsa_d_num, BIGNUM **rsa_n_num, BIGNUM **rsa_e_num, + CK_SESSION_HANDLE session); + +static int check_new_rsa_key_pub(PK11_SESSION *sp, const RSA *rsa); +static int check_new_rsa_key_priv(PK11_SESSION *sp, const RSA *rsa); + +static int find_one_object(PK11_OPTYPE op, CK_SESSION_HANDLE s, + CK_ATTRIBUTE_PTR ptempl, CK_ULONG nattr, CK_OBJECT_HANDLE_PTR pkey); +static int init_template_value(BIGNUM *bn, CK_VOID_PTR *pValue, + CK_ULONG *ulValueLen); +static void attr_to_BN(CK_ATTRIBUTE_PTR attr, CK_BYTE attr_data[], BIGNUM **bn); + +static int pk11_token_login(CK_SESSION_HANDLE session, CK_BBOOL *login_done, + CK_BBOOL is_private); + +/* Read mode string to be used for fopen() */ +#if SOLARIS_OPENSSL +static char *read_mode_flags = "rF"; +#else +static char *read_mode_flags = "r"; +#endif + +/* + * increment/create reference for an asymmetric key handle via active list + * manipulation. If active list operation fails, unlock (if locked), set error + * variable and jump to the specified label. + */ +#define KEY_HANDLE_REFHOLD(key_handle, alg_type, unlock, var, label) \ + { \ + if (pk11_active_add(key_handle, alg_type) < 0) \ + { \ + var = TRUE; \ + if (unlock) \ + UNLOCK_OBJSTORE(alg_type); \ + goto label; \ + } \ + } + +/* + * Find active list entry according to object handle and return pointer to the + * entry otherwise return NULL. + * + * This function presumes it is called with lock protecting the active list + * held. + */ +static PK11_active *pk11_active_find(CK_OBJECT_HANDLE h, PK11_OPTYPE type) + { + PK11_active *entry; + + for (entry = active_list[type]; entry != NULL; entry = entry->next) + if (entry->h == h) + return (entry); + + return (NULL); + } + +/* + * Search for an entry in the active list using PKCS#11 object handle as a + * search key and return refcnt of the found/created entry or -1 in case of + * failure. + * + * This function presumes it is called with lock protecting the active list + * held. + */ +int +pk11_active_add(CK_OBJECT_HANDLE h, PK11_OPTYPE type) + { + PK11_active *entry = NULL; + + if (h == CK_INVALID_HANDLE) + { + PK11err(PK11_F_ACTIVE_ADD, PK11_R_INVALID_HANDLE); + return (-1); + } + + /* search for entry in the active list */ + if ((entry = pk11_active_find(h, type)) != NULL) + entry->refcnt++; + else + { + /* not found, create new entry and add it to the list */ + entry = OPENSSL_malloc(sizeof (PK11_active)); + if (entry == NULL) + { + PK11err(PK11_F_ACTIVE_ADD, PK11_R_MALLOC_FAILURE); + return (-1); + } + entry->h = h; + entry->refcnt = 1; + entry->prev = NULL; + entry->next = NULL; + /* connect the newly created entry to the list */ + if (active_list[type] == NULL) + active_list[type] = entry; + else /* make the entry first in the list */ + { + entry->next = active_list[type]; + active_list[type]->prev = entry; + active_list[type] = entry; + } + } + + return (entry->refcnt); + } + +/* + * Remove active list entry from the list and free it. + * + * This function presumes it is called with lock protecting the active list + * held. + */ +void +pk11_active_remove(PK11_active *entry, PK11_OPTYPE type) + { + PK11_active *prev_entry; + + /* remove the entry from the list and free it */ + if ((prev_entry = entry->prev) != NULL) + { + prev_entry->next = entry->next; + if (entry->next != NULL) + entry->next->prev = prev_entry; + } + else + { + active_list[type] = entry->next; + /* we were the first but not the only one */ + if (entry->next != NULL) + entry->next->prev = NULL; + } + + /* sanitization */ + entry->h = CK_INVALID_HANDLE; + entry->prev = NULL; + entry->next = NULL; + OPENSSL_free(entry); + } + +/* Free all entries from the active list. */ +void +pk11_free_active_list(PK11_OPTYPE type) + { + PK11_active *entry; + + /* only for asymmetric types since only they have C_Find* locks. */ + switch (type) + { + case OP_RSA: + break; + default: + return; + } + + /* see find_lock array definition for more info on object locking */ + LOCK_OBJSTORE(type); + while ((entry = active_list[type]) != NULL) + pk11_active_remove(entry, type); + UNLOCK_OBJSTORE(type); + } + +/* + * Search for active list entry associated with given PKCS#11 object handle, + * decrement its refcnt and if it drops to 0, disconnect the entry and free it. + * + * Return 1 if the PKCS#11 object associated with the entry has no references, + * return 0 if there is at least one reference, -1 on error. + * + * This function presumes it is called with lock protecting the active list + * held. + */ +int +pk11_active_delete(CK_OBJECT_HANDLE h, PK11_OPTYPE type) + { + PK11_active *entry = NULL; + + if ((entry = pk11_active_find(h, type)) == NULL) + { + PK11err(PK11_F_ACTIVE_DELETE, PK11_R_INVALID_HANDLE); + return (-1); + } + + OPENSSL_assert(entry->refcnt > 0); + entry->refcnt--; + if (entry->refcnt == 0) + { + pk11_active_remove(entry, type); + return (1); + } + + return (0); + } + +/* Our internal RSA_METHOD that we provide pointers to */ +static RSA_METHOD pk11_rsa; + +RSA_METHOD * +PK11_RSA(void) + { + const RSA_METHOD *rsa; + + if (pk11_rsa.name == NULL) + { + rsa = RSA_PKCS1_SSLeay(); + memcpy(&pk11_rsa, rsa, sizeof(*rsa)); + pk11_rsa.name = "PKCS#11 RSA method"; + pk11_rsa.rsa_sign = pk11_RSA_sign; + } + return (&pk11_rsa); + } + +/* Size of an SSL signature: MD5+SHA1 */ +#define SSL_SIG_LENGTH 36 + +static CK_BBOOL mytrue = TRUE; +static CK_BBOOL myfalse = FALSE; + +/* + * Standard engine interface function. Majority codes here are from + * rsa/rsa_sign.c. We replaced the decrypt function call by C_Sign of PKCS#11. + * See more details in rsa/rsa_sign.c + */ +static int pk11_RSA_sign(int type, const unsigned char *m, unsigned int m_len, + unsigned char *sigret, unsigned int *siglen, const RSA *rsa) + { + X509_SIG sig; + ASN1_TYPE parameter; + int i, j = 0; + unsigned char *p, *s = NULL; + X509_ALGOR algor; + ASN1_OCTET_STRING digest; + CK_RV rv; + CK_MECHANISM mech_rsa = {CKM_RSA_PKCS, NULL, 0}; + CK_MECHANISM *p_mech = &mech_rsa; + CK_OBJECT_HANDLE h_priv_key; + PK11_SESSION *sp = NULL; + int ret = 0; + unsigned long ulsiglen; + + /* Encode the digest */ + /* Special case: SSL signature, just check the length */ + if (type == NID_md5_sha1) + { + if (m_len != SSL_SIG_LENGTH) + { + PK11err(PK11_F_RSA_SIGN, + PK11_R_INVALID_MESSAGE_LENGTH); + goto err; + } + i = SSL_SIG_LENGTH; + s = (unsigned char *)m; + } + else + { + sig.algor = &algor; + sig.algor->algorithm = OBJ_nid2obj(type); + if (sig.algor->algorithm == NULL) + { + PK11err(PK11_F_RSA_SIGN, + PK11_R_UNKNOWN_ALGORITHM_TYPE); + goto err; + } + if (sig.algor->algorithm->length == 0) + { + PK11err(PK11_F_RSA_SIGN, + PK11_R_UNKNOWN_ASN1_OBJECT_ID); + goto err; + } + parameter.type = V_ASN1_NULL; + parameter.value.ptr = NULL; + sig.algor->parameter = ¶meter; + + sig.digest = &digest; + sig.digest->data = (unsigned char *)m; + sig.digest->length = m_len; + + i = i2d_X509_SIG(&sig, NULL); + } + + j = RSA_size(rsa); + if ((i - RSA_PKCS1_PADDING) > j) + { + PK11err(PK11_F_RSA_SIGN, PK11_R_DIGEST_TOO_BIG); + goto err; + } + + if (type != NID_md5_sha1) + { + s = (unsigned char *)OPENSSL_malloc((unsigned int)(j + 1)); + if (s == NULL) + { + PK11err(PK11_F_RSA_SIGN, PK11_R_MALLOC_FAILURE); + goto err; + } + p = s; + (void) i2d_X509_SIG(&sig, &p); + } + + if ((sp = pk11_get_session(OP_RSA)) == NULL) + goto err; + + (void) check_new_rsa_key_priv(sp, rsa); + + h_priv_key = sp->opdata_rsa_priv_key; + if (h_priv_key == CK_INVALID_HANDLE) + h_priv_key = sp->opdata_rsa_priv_key = + pk11_get_private_rsa_key((RSA *)rsa, + &sp->opdata_rsa_priv, &sp->opdata_rsa_d_num, + &sp->opdata_rsa_pn_num, &sp->opdata_rsa_pe_num, + sp->session); + + if (h_priv_key != CK_INVALID_HANDLE) + { + rv = pFuncList->C_SignInit(sp->session, p_mech, h_priv_key); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_RSA_SIGN, PK11_R_SIGNINIT, rv); + goto err; + } + + ulsiglen = j; + rv = pFuncList->C_Sign(sp->session, s, i, sigret, + (CK_ULONG_PTR) &ulsiglen); + *siglen = ulsiglen; + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_RSA_SIGN, PK11_R_SIGN, rv); + goto err; + } + ret = 1; + } + +err: + if ((type != NID_md5_sha1) && (s != NULL)) + { + (void) memset(s, 0, (unsigned int)(j + 1)); + OPENSSL_free(s); + } + + pk11_return_session(sp, OP_RSA); + return (ret); + } + +static int hndidx_rsa = -1; + +#define MAXATTR 1024 + +/* + * Load RSA private key from a file or get its PKCS#11 handle if stored in the + * PKCS#11 token. + */ +/* ARGSUSED */ +EVP_PKEY *pk11_load_privkey(ENGINE *e, const char *privkey_file, + UI_METHOD *ui_method, void *callback_data) + { + EVP_PKEY *pkey = NULL; + FILE *privkey; + CK_OBJECT_HANDLE h_priv_key = CK_INVALID_HANDLE; + RSA *rsa = NULL; + PK11_SESSION *sp; + /* Anything else below is needed for the key by reference extension. */ + CK_RV rv; + CK_BBOOL is_token = TRUE; + CK_BBOOL rollback = FALSE; + CK_BYTE attr_data[2][MAXATTR]; + CK_OBJECT_CLASS key_class = CKO_PRIVATE_KEY; + CK_OBJECT_HANDLE ks_key = CK_INVALID_HANDLE; /* key in keystore */ + + /* we look for private keys only */ + CK_ATTRIBUTE search_templ[] = + { + {CKA_TOKEN, &is_token, sizeof(is_token)}, + {CKA_CLASS, &key_class, sizeof(key_class)}, + {CKA_LABEL, NULL, 0} + }; + + /* + * These public attributes are needed to initialize the OpenSSL RSA + * structure with something we can use to look up the key. Note that we + * never ask for private components. + */ + CK_ATTRIBUTE get_templ[] = + { + {CKA_MODULUS, (void *)attr_data[0], MAXATTR}, /* n */ + {CKA_PUBLIC_EXPONENT, (void *)attr_data[1], MAXATTR}, /* e */ + }; + + if ((sp = pk11_get_session(OP_RSA)) == NULL) + return (NULL); + + /* + * Use simple scheme "pkcs11:" for now. + */ + if (strstr(privkey_file, "pkcs11:") == privkey_file) + { + search_templ[2].pValue = strstr(privkey_file, ":") + 1; + search_templ[2].ulValueLen = strlen(search_templ[2].pValue); + + if (pk11_token_login(sp->session, &pk11_login_done, + CK_TRUE) == 0) + goto err; + + /* see find_lock array definition + for more info on object locking */ + LOCK_OBJSTORE(OP_RSA); + + /* + * Now let's try to find the key in the token. It is a failure + * if we can't find it. + */ + if (find_one_object(OP_RSA, sp->session, search_templ, 3, + &ks_key) == 0) + { + UNLOCK_OBJSTORE(OP_RSA); + goto err; + } + + if (hndidx_rsa == -1) + hndidx_rsa = RSA_get_ex_new_index(0, + "pkcs11 RSA HSM key handle", + NULL, NULL, NULL); + + /* + * We might have a cache hit which we could confirm + * according to the 'n'/'e' params, RSA public pointer + * as NULL, and non-NULL RSA private pointer. However, + * it is easier just to recreate everything. We expect + * the keys to be loaded once and used many times. We + * do not check the return value because even in case + * of failure the sp structure will have both key + * pointer and object handle cleaned and + * pk11_destroy_object() reports the failure to the + * OpenSSL error message buffer. + */ + (void) pk11_destroy_rsa_object_priv(sp, FALSE); + + sp->opdata_rsa_priv_key = ks_key; + /* This object shall not be deleted on a cache miss. */ + sp->priv_persistent = CK_TRUE; + + /* + * Cache the RSA private structure pointer. We do not + * use it now for key-by-ref keys but let's do it for + * consistency reasons. + */ + if ((rsa = sp->opdata_rsa_priv = RSA_new_method(e)) == NULL) + { + UNLOCK_OBJSTORE(OP_RSA); + goto err; + } + + /* + * Now we have to initialize an OpenSSL RSA structure, + * everything else is 0 or NULL. + */ + rsa->flags = RSA_FLAG_SIGN_VER | RSA_FLAG_EXT_PKEY; + RSA_set_ex_data(rsa, hndidx_rsa, (void *) ks_key); + + if ((rv = pFuncList->C_GetAttributeValue(sp->session, ks_key, + get_templ, 2)) != CKR_OK) + { + UNLOCK_OBJSTORE(OP_RSA); + PK11err_add_data(PK11_F_LOAD_PRIVKEY, + PK11_R_GETATTRIBUTVALUE, rv); + goto err; + } + + /* + * We do not use pk11_get_private_rsa_key() here so we + * must take care of handle management ourselves. + */ + KEY_HANDLE_REFHOLD(ks_key, OP_RSA, TRUE, rollback, err); + + /* + * Those are the sensitive components we do not want to export + * from the token at all: rsa->(d|p|q|dmp1|dmq1|iqmp). + */ + attr_to_BN(&get_templ[0], attr_data[0], &rsa->n); + attr_to_BN(&get_templ[1], attr_data[1], &rsa->e); + /* + * Must have 'n'/'e' components in the session structure as + * well. They serve as a public look-up key for the private key + * in the keystore. + */ + attr_to_BN(&get_templ[0], attr_data[0], + &sp->opdata_rsa_pn_num); + attr_to_BN(&get_templ[1], attr_data[1], + &sp->opdata_rsa_pe_num); + + UNLOCK_OBJSTORE(OP_RSA); + + if ((pkey = EVP_PKEY_new()) == NULL) + goto err; + + if (EVP_PKEY_assign_RSA(pkey, rsa) == 0) + goto err; + } + else if ((privkey = fopen(privkey_file, read_mode_flags)) != NULL) + { + pkey = PEM_read_PrivateKey(privkey, NULL, NULL, NULL); + (void) fclose(privkey); + if (pkey != NULL) + { + rsa = EVP_PKEY_get1_RSA(pkey); + if (rsa != NULL) + { + /* + * This will always destroy the RSA + * object since we have a new RSA + * structure here. + */ + (void) check_new_rsa_key_priv(sp, rsa); + sp->priv_persistent = CK_FALSE; + + h_priv_key = sp->opdata_rsa_priv_key = + pk11_get_private_rsa_key(rsa, + &sp->opdata_rsa_priv, + &sp->opdata_rsa_d_num, + &sp->opdata_rsa_pn_num, + &sp->opdata_rsa_pe_num, sp->session); + if (h_priv_key == CK_INVALID_HANDLE) + goto err; + } + else + goto err; + } + } + + pk11_return_session(sp, OP_RSA); + return (pkey); +err: + pk11_return_session(sp, OP_RSA); + if (rsa != NULL) + RSA_free(rsa); + if (pkey != NULL) + { + EVP_PKEY_free(pkey); + pkey = NULL; + } + rollback = rollback; + return (pkey); + } + +/* + * Load RSA public key from a file or get its PKCS#11 handle if stored in the + * PKCS#11 token. + */ +/* ARGSUSED */ +EVP_PKEY *pk11_load_pubkey(ENGINE *e, const char *pubkey_file, + UI_METHOD *ui_method, void *callback_data) + { + EVP_PKEY *pkey = NULL; + FILE *pubkey; + CK_OBJECT_HANDLE h_pub_key = CK_INVALID_HANDLE; + RSA *rsa = NULL; + PK11_SESSION *sp; + /* Anything else below is needed for the key by reference extension. */ + CK_RV rv; + CK_BBOOL is_token = TRUE; + CK_BYTE attr_data[2][MAXATTR]; + CK_OBJECT_CLASS key_class = CKO_PUBLIC_KEY; + CK_OBJECT_HANDLE ks_key = CK_INVALID_HANDLE; /* key in keystore */ + + /* we look for public keys only */ + CK_ATTRIBUTE search_templ[] = + { + {CKA_TOKEN, &is_token, sizeof(is_token)}, + {CKA_CLASS, &key_class, sizeof(key_class)}, + {CKA_LABEL, NULL, 0} + }; + + /* + * These public attributes are needed to initialize OpenSSL RSA + * structure with something we can use to look up the key. + */ + CK_ATTRIBUTE get_templ[] = + { + {CKA_MODULUS, (void *)attr_data[0], MAXATTR}, /* n */ + {CKA_PUBLIC_EXPONENT, (void *)attr_data[1], MAXATTR}, /* e */ + }; + + if ((sp = pk11_get_session(OP_RSA)) == NULL) + return (NULL); + + /* + * Use simple scheme "pkcs11:" for now. + */ + if (strstr(pubkey_file, "pkcs11:") == pubkey_file) + { + search_templ[2].pValue = strstr(pubkey_file, ":") + 1; + search_templ[2].ulValueLen = strlen(search_templ[2].pValue); + + if (pk11_token_login(sp->session, &pk11_login_done, + CK_FALSE) == 0) + goto err; + + /* see find_lock array definition + for more info on object locking */ + LOCK_OBJSTORE(OP_RSA); + + /* + * Now let's try to find the key in the token. It is a failure + * if we can't find it. + */ + if (find_one_object(OP_RSA, sp->session, search_templ, 3, + &ks_key) == 0) + { + UNLOCK_OBJSTORE(OP_RSA); + goto err; + } + + /* + * We load a new public key so we will create a new RSA + * structure. No cache hit is possible. + */ + (void) pk11_destroy_rsa_object_pub(sp, FALSE); + + sp->opdata_rsa_pub_key = ks_key; + /* This object shall not be deleted on a cache miss. */ + sp->pub_persistent = CK_TRUE; + + /* + * Cache the RSA public structure pointer. + */ + if ((rsa = sp->opdata_rsa_pub = RSA_new_method(e)) == NULL) + { + UNLOCK_OBJSTORE(OP_RSA); + goto err; + } + + /* + * Now we have to initialize an OpenSSL RSA structure, + * everything else is 0 or NULL. + */ + rsa->flags = RSA_FLAG_SIGN_VER; + + if ((rv = pFuncList->C_GetAttributeValue(sp->session, ks_key, + get_templ, 2)) != CKR_OK) + { + UNLOCK_OBJSTORE(OP_RSA); + PK11err_add_data(PK11_F_LOAD_PUBKEY, + PK11_R_GETATTRIBUTVALUE, rv); + goto err; + } + + attr_to_BN(&get_templ[0], attr_data[0], &rsa->n); + attr_to_BN(&get_templ[1], attr_data[1], &rsa->e); + + UNLOCK_OBJSTORE(OP_RSA); + + if ((pkey = EVP_PKEY_new()) == NULL) + goto err; + + if (EVP_PKEY_assign_RSA(pkey, rsa) == 0) + goto err; + + /* + * Create a session object from it so that when calling + * pk11_get_public_rsa_key() the next time, we can find it. The + * reason why we do that is that we cannot tell from the RSA + * structure (OpenSSL RSA structure does not have any room for + * additional data used by the engine, for example) if it bears + * a public key stored in the keystore or not so it's better if + * we always have a session key. Note that this is different + * from what we do for the private keystore objects but in that + * case, we can tell from the RSA structure that the keystore + * object is in play - the 'd' component is NULL in that case. + */ + h_pub_key = sp->opdata_rsa_pub_key = + pk11_get_public_rsa_key(rsa, + &sp->opdata_rsa_pub, &sp->opdata_rsa_n_num, + &sp->opdata_rsa_e_num, sp->session); + if (h_pub_key == CK_INVALID_HANDLE) + goto err; + } + else if ((pubkey = fopen(pubkey_file, read_mode_flags)) != NULL) + { + pkey = PEM_read_PUBKEY(pubkey, NULL, NULL, NULL); + (void) fclose(pubkey); + if (pkey != NULL) + { + rsa = EVP_PKEY_get1_RSA(pkey); + if (rsa != NULL) + { + /* + * This will always destroy the RSA + * object since we have a new RSA + * structure here. + */ + (void) check_new_rsa_key_pub(sp, rsa); + sp->pub_persistent = CK_FALSE; + + h_pub_key = sp->opdata_rsa_pub_key = + pk11_get_public_rsa_key(rsa, + &sp->opdata_rsa_pub, &sp->opdata_rsa_n_num, + &sp->opdata_rsa_e_num, sp->session); + if (h_pub_key == CK_INVALID_HANDLE) + goto err; + } + else + goto err; + } + } + + pk11_return_session(sp, OP_RSA); + return (pkey); +err: + pk11_return_session(sp, OP_RSA); + if (rsa != NULL) + RSA_free(rsa); + if (pkey != NULL) + { + EVP_PKEY_free(pkey); + pkey = NULL; + } + return (pkey); + } + +/* + * Create a public key object in a session from a given rsa structure. + * The *rsa_n_num and *rsa_e_num pointers are non-NULL for RSA public keys. + */ +static CK_OBJECT_HANDLE pk11_get_public_rsa_key(RSA *rsa, + RSA **key_ptr, BIGNUM **rsa_n_num, BIGNUM **rsa_e_num, + CK_SESSION_HANDLE session) + { + CK_RV rv; + CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE; + CK_ULONG found; + CK_OBJECT_CLASS o_key = CKO_PUBLIC_KEY; + CK_KEY_TYPE k_type = CKK_RSA; + CK_ULONG ul_key_attr_count = 8; + CK_BBOOL rollback = FALSE; + + CK_ATTRIBUTE a_key_template[] = + { + {CKA_CLASS, (void *) NULL, sizeof (CK_OBJECT_CLASS)}, + {CKA_KEY_TYPE, (void *) NULL, sizeof (CK_KEY_TYPE)}, + {CKA_TOKEN, &myfalse, sizeof (myfalse)}, + {CKA_ENCRYPT, &mytrue, sizeof (mytrue)}, + {CKA_VERIFY, &mytrue, sizeof (mytrue)}, + {CKA_VERIFY_RECOVER, &mytrue, sizeof (mytrue)}, + {CKA_MODULUS, (void *)NULL, 0}, + {CKA_PUBLIC_EXPONENT, (void *)NULL, 0} + }; + + int i; + + a_key_template[0].pValue = &o_key; + a_key_template[1].pValue = &k_type; + + a_key_template[6].ulValueLen = BN_num_bytes(rsa->n); + a_key_template[6].pValue = (CK_VOID_PTR)OPENSSL_malloc( + (size_t)a_key_template[6].ulValueLen); + if (a_key_template[6].pValue == NULL) + { + PK11err(PK11_F_GET_PUB_RSA_KEY, PK11_R_MALLOC_FAILURE); + goto malloc_err; + } + + BN_bn2bin(rsa->n, a_key_template[6].pValue); + + a_key_template[7].ulValueLen = BN_num_bytes(rsa->e); + a_key_template[7].pValue = (CK_VOID_PTR)OPENSSL_malloc( + (size_t)a_key_template[7].ulValueLen); + if (a_key_template[7].pValue == NULL) + { + PK11err(PK11_F_GET_PUB_RSA_KEY, PK11_R_MALLOC_FAILURE); + goto malloc_err; + } + + BN_bn2bin(rsa->e, a_key_template[7].pValue); + + /* see find_lock array definition for more info on object locking */ + LOCK_OBJSTORE(OP_RSA); + + rv = pFuncList->C_FindObjectsInit(session, a_key_template, + ul_key_attr_count); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PUB_RSA_KEY, + PK11_R_FINDOBJECTSINIT, rv); + goto err; + } + + rv = pFuncList->C_FindObjects(session, &h_key, 1, &found); + + if (rv != CKR_OK) + { + (void) pFuncList->C_FindObjectsFinal(session); + PK11err_add_data(PK11_F_GET_PUB_RSA_KEY, + PK11_R_FINDOBJECTS, rv); + goto err; + } + + rv = pFuncList->C_FindObjectsFinal(session); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PUB_RSA_KEY, + PK11_R_FINDOBJECTSFINAL, rv); + goto err; + } + + if (found == 0) + { + rv = pFuncList->C_CreateObject(session, + a_key_template, ul_key_attr_count, &h_key); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PUB_RSA_KEY, + PK11_R_CREATEOBJECT, rv); + goto err; + } + } + + if (rsa_n_num != NULL) + if ((*rsa_n_num = BN_dup(rsa->n)) == NULL) + { + PK11err(PK11_F_GET_PUB_RSA_KEY, PK11_R_MALLOC_FAILURE); + rollback = TRUE; + goto err; + } + if (rsa_e_num != NULL) + if ((*rsa_e_num = BN_dup(rsa->e)) == NULL) + { + PK11err(PK11_F_GET_PUB_RSA_KEY, PK11_R_MALLOC_FAILURE); + BN_free(*rsa_n_num); + *rsa_n_num = NULL; + rollback = TRUE; + goto err; + } + + /* LINTED: E_CONSTANT_CONDITION */ + KEY_HANDLE_REFHOLD(h_key, OP_RSA, FALSE, rollback, err); + if (key_ptr != NULL) + *key_ptr = rsa; + +err: + if (rollback) + { + /* + * We do not care about the return value from C_DestroyObject() + * since we are doing rollback. + */ + if (found == 0) + (void) pFuncList->C_DestroyObject(session, h_key); + h_key = CK_INVALID_HANDLE; + } + + UNLOCK_OBJSTORE(OP_RSA); + +malloc_err: + for (i = 6; i <= 7; i++) + { + if (a_key_template[i].pValue != NULL) + { + OPENSSL_free(a_key_template[i].pValue); + a_key_template[i].pValue = NULL; + } + } + + return (h_key); + } + +/* + * Create a private key object in the session from a given rsa structure. + * The *rsa_d_num pointer is non-NULL for RSA private keys. + */ +static CK_OBJECT_HANDLE +pk11_get_private_rsa_key(RSA *rsa, RSA **key_ptr, BIGNUM **rsa_d_num, + BIGNUM **rsa_n_num, BIGNUM **rsa_e_num, CK_SESSION_HANDLE session) + { + CK_RV rv; + CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE; + int i; + CK_ULONG found; + CK_OBJECT_CLASS o_key = CKO_PRIVATE_KEY; + CK_KEY_TYPE k_type = CKK_RSA; + CK_ULONG ul_key_attr_count = 14; + CK_BBOOL rollback = FALSE; + + /* Both CKA_TOKEN and CKA_SENSITIVE have to be FALSE for session keys */ + CK_ATTRIBUTE a_key_template[] = + { + {CKA_CLASS, (void *) NULL, sizeof (CK_OBJECT_CLASS)}, + {CKA_KEY_TYPE, (void *) NULL, sizeof (CK_KEY_TYPE)}, + {CKA_TOKEN, &myfalse, sizeof (myfalse)}, + {CKA_SENSITIVE, &myfalse, sizeof (myfalse)}, + {CKA_DECRYPT, &mytrue, sizeof (mytrue)}, + {CKA_SIGN, &mytrue, sizeof (mytrue)}, + {CKA_MODULUS, (void *)NULL, 0}, + {CKA_PUBLIC_EXPONENT, (void *)NULL, 0}, + {CKA_PRIVATE_EXPONENT, (void *)NULL, 0}, + {CKA_PRIME_1, (void *)NULL, 0}, + {CKA_PRIME_2, (void *)NULL, 0}, + {CKA_EXPONENT_1, (void *)NULL, 0}, + {CKA_EXPONENT_2, (void *)NULL, 0}, + {CKA_COEFFICIENT, (void *)NULL, 0}, + }; + + if ((rsa->flags & RSA_FLAG_EXT_PKEY) != 0) { + h_key = (CK_OBJECT_HANDLE)RSA_get_ex_data(rsa, hndidx_rsa); + LOCK_OBJSTORE(OP_RSA); + goto set; + } + + a_key_template[0].pValue = &o_key; + a_key_template[1].pValue = &k_type; + + /* Put the private key components into the template */ + if (init_template_value(rsa->n, &a_key_template[6].pValue, + &a_key_template[6].ulValueLen) == 0 || + init_template_value(rsa->e, &a_key_template[7].pValue, + &a_key_template[7].ulValueLen) == 0 || + init_template_value(rsa->d, &a_key_template[8].pValue, + &a_key_template[8].ulValueLen) == 0 || + init_template_value(rsa->p, &a_key_template[9].pValue, + &a_key_template[9].ulValueLen) == 0 || + init_template_value(rsa->q, &a_key_template[10].pValue, + &a_key_template[10].ulValueLen) == 0 || + init_template_value(rsa->dmp1, &a_key_template[11].pValue, + &a_key_template[11].ulValueLen) == 0 || + init_template_value(rsa->dmq1, &a_key_template[12].pValue, + &a_key_template[12].ulValueLen) == 0 || + init_template_value(rsa->iqmp, &a_key_template[13].pValue, + &a_key_template[13].ulValueLen) == 0) + { + PK11err(PK11_F_GET_PRIV_RSA_KEY, PK11_R_MALLOC_FAILURE); + goto malloc_err; + } + + /* see find_lock array definition for more info on object locking */ + LOCK_OBJSTORE(OP_RSA); + + /* + * We are getting the private key but the private 'd' + * component is NULL. That means this is key by reference RSA + * key. In that case, we can use only public components for + * searching for the private key handle. + */ + if (rsa->d == NULL) + { + ul_key_attr_count = 8; + /* + * We will perform the search in the token, not in the existing + * session keys. + */ + a_key_template[2].pValue = &mytrue; + } + + rv = pFuncList->C_FindObjectsInit(session, a_key_template, + ul_key_attr_count); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PRIV_RSA_KEY, + PK11_R_FINDOBJECTSINIT, rv); + goto err; + } + + rv = pFuncList->C_FindObjects(session, &h_key, 1, &found); + + if (rv != CKR_OK) + { + (void) pFuncList->C_FindObjectsFinal(session); + PK11err_add_data(PK11_F_GET_PRIV_RSA_KEY, + PK11_R_FINDOBJECTS, rv); + goto err; + } + + rv = pFuncList->C_FindObjectsFinal(session); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PRIV_RSA_KEY, + PK11_R_FINDOBJECTSFINAL, rv); + goto err; + } + + if (found == 0) + { + /* + * We have an RSA structure with 'n'/'e' components + * only so we tried to find the private key in the + * keystore. If it was really a token key we have a + * problem. Note that for other key types we just + * create a new session key using the private + * components from the RSA structure. + */ + if (rsa->d == NULL) + { + PK11err(PK11_F_GET_PRIV_RSA_KEY, + PK11_R_PRIV_KEY_NOT_FOUND); + goto err; + } + + rv = pFuncList->C_CreateObject(session, + a_key_template, ul_key_attr_count, &h_key); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PRIV_RSA_KEY, + PK11_R_CREATEOBJECT, rv); + goto err; + } + } + +set: + if (rsa_d_num != NULL) + { + /* + * When RSA keys by reference code is used, we never + * extract private components from the keystore. In + * that case 'd' was set to NULL and we expect the + * application to properly cope with that. It is + * documented in openssl(5). In general, if keys by + * reference are used we expect it to be used + * exclusively using the high level API and then there + * is no problem. If the application expects the + * private components to be read from the keystore + * then that is not a supported way of usage. + */ + if (rsa->d != NULL && (*rsa_d_num = BN_dup(rsa->d)) == NULL) + { + PK11err(PK11_F_GET_PRIV_RSA_KEY, PK11_R_MALLOC_FAILURE); + rollback = TRUE; + goto err; + } + else + *rsa_d_num = NULL; + } + + /* + * For the key by reference code, we need public components as well + * since 'd' component is always NULL. For that reason, we always cache + * 'n'/'e' components as well. + */ + *rsa_n_num = BN_dup(rsa->n); + *rsa_e_num = BN_dup(rsa->e); + + /* LINTED: E_CONSTANT_CONDITION */ + KEY_HANDLE_REFHOLD(h_key, OP_RSA, FALSE, rollback, err); + if (key_ptr != NULL) + *key_ptr = rsa; + +err: + if (rollback) + { + /* + * We do not care about the return value from C_DestroyObject() + * since we are doing rollback. + */ + if (found == 0 && + (rsa->flags & RSA_FLAG_EXT_PKEY) == 0) + (void) pFuncList->C_DestroyObject(session, h_key); + h_key = CK_INVALID_HANDLE; + } + + UNLOCK_OBJSTORE(OP_RSA); + +malloc_err: + /* + * 6 to 13 entries in the key template are key components. + * They need to be freed upon exit or error. + */ + for (i = 6; i <= 13; i++) + { + if (a_key_template[i].pValue != NULL) + { + (void) memset(a_key_template[i].pValue, 0, + a_key_template[i].ulValueLen); + OPENSSL_free(a_key_template[i].pValue); + a_key_template[i].pValue = NULL; + } + } + + return (h_key); + } + +/* + * Check for cache miss and clean the object pointer and handle + * in such case. Return 1 for cache hit, 0 for cache miss. + */ +static int check_new_rsa_key_pub(PK11_SESSION *sp, const RSA *rsa) + { + /* + * Provide protection against RSA structure reuse by making the + * check for cache hit stronger. Only public components of RSA + * key matter here so it is sufficient to compare them with values + * cached in PK11_SESSION structure. + * + * We must check the handle as well since with key by reference, public + * components 'n'/'e' are cached in private keys as well. That means we + * could have a cache hit in a private key when looking for a public + * key. That would not work, you cannot have one PKCS#11 object for + * both data signing and verifying. + */ + if ((sp->opdata_rsa_pub != rsa) || + (BN_cmp(sp->opdata_rsa_n_num, rsa->n) != 0) || + (BN_cmp(sp->opdata_rsa_e_num, rsa->e) != 0) || + (sp->opdata_rsa_priv_key != CK_INVALID_HANDLE)) + { + /* + * We do not check the return value because even in case of + * failure the sp structure will have both key pointer + * and object handle cleaned and pk11_destroy_object() + * reports the failure to the OpenSSL error message buffer. + */ + (void) pk11_destroy_rsa_object_pub(sp, TRUE); + return (0); + } + return (1); + } + +/* + * Check for cache miss and clean the object pointer and handle + * in such case. Return 1 for cache hit, 0 for cache miss. + */ +static int check_new_rsa_key_priv(PK11_SESSION *sp, const RSA *rsa) + { + /* + * Provide protection against RSA structure reuse by making + * the check for cache hit stronger. Comparing public exponent + * of RSA key with value cached in PK11_SESSION structure + * should be sufficient. Note that we want to compare the + * public component since with the keys by reference + * mechanism, private components are not in the RSA + * structure. Also, see check_new_rsa_key_pub() about why we + * compare the handle as well. + */ + if ((sp->opdata_rsa_priv != rsa) || + (BN_cmp(sp->opdata_rsa_pn_num, rsa->n) != 0) || + (BN_cmp(sp->opdata_rsa_pe_num, rsa->e) != 0) || + (sp->opdata_rsa_pn_num == NULL) || + (sp->opdata_rsa_pe_num == NULL) || + (sp->opdata_rsa_pub_key != CK_INVALID_HANDLE)) + { + /* + * We do not check the return value because even in case of + * failure the sp structure will have both key pointer + * and object handle cleaned and pk11_destroy_object() + * reports the failure to the OpenSSL error message buffer. + */ + (void) pk11_destroy_rsa_object_priv(sp, TRUE); + return (0); + } + return (1); + } + +/* + * Local function to simplify key template population + * Return 0 -- error, 1 -- no error + */ +static int +init_template_value(BIGNUM *bn, CK_VOID_PTR *p_value, + CK_ULONG *ul_value_len) + { + CK_ULONG len = 0; + + /* + * This function can be used on non-initialized BIGNUMs. It is + * easier to check that here than individually in the callers. + */ + if (bn != NULL) + len = BN_num_bytes(bn); + + if (bn == NULL || len == 0) + return (1); + + *ul_value_len = len; + *p_value = (CK_VOID_PTR)OPENSSL_malloc((size_t)*ul_value_len); + if (*p_value == NULL) + return (0); + + BN_bn2bin(bn, *p_value); + + return (1); + } + +static void +attr_to_BN(CK_ATTRIBUTE_PTR attr, CK_BYTE attr_data[], BIGNUM **bn) + { + if (attr->ulValueLen > 0) + *bn = BN_bin2bn(attr_data, attr->ulValueLen, NULL); + } + +/* + * Find one object in the token. It is an error if we can not find the + * object or if we find more objects based on the template we got. + * Assume object store locked. + * + * Returns: + * 1 OK + * 0 no object or more than 1 object found + */ +static int +find_one_object(PK11_OPTYPE op, CK_SESSION_HANDLE s, + CK_ATTRIBUTE_PTR ptempl, CK_ULONG nattr, CK_OBJECT_HANDLE_PTR pkey) + { + CK_RV rv; + CK_ULONG objcnt; + + if ((rv = pFuncList->C_FindObjectsInit(s, ptempl, nattr)) != CKR_OK) + { + PK11err_add_data(PK11_F_FIND_ONE_OBJECT, + PK11_R_FINDOBJECTSINIT, rv); + return (0); + } + + rv = pFuncList->C_FindObjects(s, pkey, 1, &objcnt); + if (rv != CKR_OK) + { + (void) pFuncList->C_FindObjectsFinal(s); + PK11err_add_data(PK11_F_FIND_ONE_OBJECT, PK11_R_FINDOBJECTS, + rv); + return (0); + } + + (void) pFuncList->C_FindObjectsFinal(s); + + if (objcnt > 1) + { + PK11err(PK11_F_FIND_ONE_OBJECT, + PK11_R_MORE_THAN_ONE_OBJECT_FOUND); + return (0); + } + else if (objcnt == 0) + { + PK11err(PK11_F_FIND_ONE_OBJECT, PK11_R_NO_OBJECT_FOUND); + return (0); + } + return (1); + } + +/* from uri stuff */ + +extern char *pk11_pin; + +static int pk11_get_pin(void); + +static int +pk11_get_pin(void) +{ + char *pin; + + /* The getpassphrase() function is not MT safe. */ +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_lock(token_lock) == 0); +#else + CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); +#endif + pin = getpassphrase("Enter PIN: "); + if (pin == NULL) + { + PK11err(PK11_F_GET_PIN, PK11_R_COULD_NOT_READ_PIN); +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0); +#else + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + return (0); + } + pk11_pin = BUF_strdup(pin); + if (pk11_pin == NULL) + { + PK11err(PK11_F_LOAD_PRIVKEY, PK11_R_MALLOC_FAILURE); +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0); +#else + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + return (0); + } + memset(pin, 0, strlen(pin)); +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0); +#else + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + return (1); + } + +/* + * Log in to the keystore if we are supposed to do that at all. Take care of + * reading and caching the PIN etc. Log in only once even when called from + * multiple threads. + * + * Returns: + * 1 on success + * 0 on failure + */ +static int +pk11_token_login(CK_SESSION_HANDLE session, CK_BBOOL *login_done, + CK_BBOOL is_private) + { + CK_RV rv; + +#if 0 + /* doesn't work on the AEP Keyper??? */ + if ((pubkey_token_flags & CKF_TOKEN_INITIALIZED) == 0) + { + PK11err(PK11_F_TOKEN_LOGIN, + PK11_R_TOKEN_NOT_INITIALIZED); + return (0); + } +#endif + + /* + * If login is required or needed but the PIN has not been + * even initialized we can bail out right now. Note that we + * are supposed to always log in if we are going to access + * private keys. However, we may need to log in even for + * accessing public keys in case that the CKF_LOGIN_REQUIRED + * flag is set. + */ + if (((pubkey_token_flags & CKF_LOGIN_REQUIRED) || + (is_private == CK_TRUE)) && + (~pubkey_token_flags & CKF_USER_PIN_INITIALIZED)) + { + PK11err(PK11_F_TOKEN_LOGIN, PK11_R_TOKEN_PIN_NOT_SET); + return (0); + } + + /* + * Note on locking: it is possible that more than one thread + * gets into pk11_get_pin() so we must deal with that. We + * cannot avoid it since we cannot guard fork() in there with + * a lock because we could end up in a dead lock in the + * child. Why? Remember we are in a multithreaded environment + * so we must lock all mutexes in the prefork function to + * avoid a situation in which a thread that did not call + * fork() held a lock, making future unlocking impossible. We + * lock right before C_Login(). + */ + if ((pubkey_token_flags & CKF_LOGIN_REQUIRED) || + (is_private == CK_TRUE)) + { + if (*login_done == CK_FALSE) + { + if ((pk11_pin == NULL) && (pk11_get_pin() == 0)) + { + PK11err(PK11_F_TOKEN_LOGIN, + PK11_R_TOKEN_PIN_NOT_PROVIDED); + return (0); + } + } + + /* + * Note that what we are logging into is the keystore from + * pubkey_SLOTID because we work with OP_RSA session type here. + * That also means that we can work with only one keystore in + * the engine. + * + * We must make sure we do not try to login more than once. + * Also, see the comment above on locking strategy. + */ + +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_lock(token_lock) == 0); +#else + CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); +#endif + if (*login_done == CK_FALSE) + { + if ((rv = pFuncList->C_Login(session, + CKU_USER, (CK_UTF8CHAR*)pk11_pin, + strlen(pk11_pin))) != CKR_OK) + { + PK11err_add_data(PK11_F_TOKEN_LOGIN, + PK11_R_TOKEN_LOGIN_FAILED, rv); + goto err_locked; + } + + *login_done = CK_TRUE; + + } +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0); +#else + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + } + else + { + /* + * If token does not require login we take it as the + * login was done. + */ + *login_done = CK_TRUE; + } + + return (1); + +err_locked: + if (pk11_pin) { + memset(pk11_pin, 0, strlen(pk11_pin)); + OPENSSL_free((void*)pk11_pin); + } + pk11_pin = NULL; +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0); +#else + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + return (0); + } + +/* + * Log in to the keystore in the child if we were logged in in the + * parent. There are similarities in the code with pk11_token_login() + * but still it is quite different so we need a separate function for + * this. + * + * Note that this function is called under the locked session mutex when fork is + * detected. That means that C_Login() will be called from the child just once. + * + * Returns: + * 1 on success + * 0 on failure + */ +int +pk11_token_relogin(CK_SESSION_HANDLE session) + { + CK_RV rv; + + if ((pk11_pin == NULL) && (pk11_get_pin() == 0)) + return (0); + +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_lock(token_lock) == 0); +#else + CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); +#endif + if ((rv = pFuncList->C_Login(session, CKU_USER, + (CK_UTF8CHAR_PTR)pk11_pin, strlen(pk11_pin))) != CKR_OK) + { + PK11err_add_data(PK11_F_TOKEN_RELOGIN, + PK11_R_TOKEN_LOGIN_FAILED, rv); +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0); +#else + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + return (0); + } +#ifndef NOPTHREADS + OPENSSL_assert(pthread_mutex_unlock(token_lock) == 0); +#else + CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); +#endif + + return (1); + } + +#ifdef OPENSSL_SYS_WIN32 +char *getpassphrase(const char *prompt) + { + static char buf[128]; + HANDLE h; + DWORD cc, mode; + int cnt; + + h = GetStdHandle(STD_INPUT_HANDLE); + fputs(prompt, stderr); + fflush(stderr); + fflush(stdout); + FlushConsoleInputBuffer(h); + GetConsoleMode(h, &mode); + SetConsoleMode(h, ENABLE_PROCESSED_INPUT); + + for (cnt = 0; cnt < sizeof(buf) - 1; cnt++) + { + ReadFile(h, buf + cnt, 1, &cc, NULL); + if (buf[cnt] == '\r') + break; + fputc('*', stdout); + fflush(stderr); + fflush(stdout); + } + + SetConsoleMode(h, mode); + buf[cnt] = '\0'; + fputs("\n", stderr); + return buf; + } +#endif /* OPENSSL_SYS_WIN32 */ +#endif /* OPENSSL_NO_HW_PK11SO */ +#endif /* OPENSSL_NO_HW_PK11 */ +#endif /* OPENSSL_NO_HW */ Index: openssl/crypto/engine/pkcs11.h diff -u /dev/null openssl/crypto/engine/pkcs11.h:1.1.1.1 --- /dev/null Mon Jun 13 15:55:26 2016 +++ openssl/crypto/engine/pkcs11.h Wed Oct 24 23:27:09 2007 @@ -0,0 +1,299 @@ +/* pkcs11.h include file for PKCS #11. */ +/* $Revision: 1.1.1.1 $ */ + +/* License to copy and use this software is granted provided that it is + * identified as "RSA Security Inc. PKCS #11 Cryptographic Token Interface + * (Cryptoki)" in all material mentioning or referencing this software. + + * License is also granted to make and use derivative works provided that + * such works are identified as "derived from the RSA Security Inc. PKCS #11 + * Cryptographic Token Interface (Cryptoki)" in all material mentioning or + * referencing the derived work. + + * RSA Security Inc. makes no representations concerning either the + * merchantability of this software or the suitability of this software for + * any particular purpose. It is provided "as is" without express or implied + * warranty of any kind. + */ + +#ifndef _PKCS11_H_ +#define _PKCS11_H_ 1 + +#ifdef __cplusplus +extern "C" { +#endif + +/* Before including this file (pkcs11.h) (or pkcs11t.h by + * itself), 6 platform-specific macros must be defined. These + * macros are described below, and typical definitions for them + * are also given. Be advised that these definitions can depend + * on both the platform and the compiler used (and possibly also + * on whether a Cryptoki library is linked statically or + * dynamically). + * + * In addition to defining these 6 macros, the packing convention + * for Cryptoki structures should be set. The Cryptoki + * convention on packing is that structures should be 1-byte + * aligned. + * + * If you're using Microsoft Developer Studio 5.0 to produce + * Win32 stuff, this might be done by using the following + * preprocessor directive before including pkcs11.h or pkcs11t.h: + * + * #pragma pack(push, cryptoki, 1) + * + * and using the following preprocessor directive after including + * pkcs11.h or pkcs11t.h: + * + * #pragma pack(pop, cryptoki) + * + * If you're using an earlier version of Microsoft Developer + * Studio to produce Win16 stuff, this might be done by using + * the following preprocessor directive before including + * pkcs11.h or pkcs11t.h: + * + * #pragma pack(1) + * + * In a UNIX environment, you're on your own for this. You might + * not need to do (or be able to do!) anything. + * + * + * Now for the macros: + * + * + * 1. CK_PTR: The indirection string for making a pointer to an + * object. It can be used like this: + * + * typedef CK_BYTE CK_PTR CK_BYTE_PTR; + * + * If you're using Microsoft Developer Studio 5.0 to produce + * Win32 stuff, it might be defined by: + * + * #define CK_PTR * + * + * If you're using an earlier version of Microsoft Developer + * Studio to produce Win16 stuff, it might be defined by: + * + * #define CK_PTR far * + * + * In a typical UNIX environment, it might be defined by: + * + * #define CK_PTR * + * + * + * 2. CK_DEFINE_FUNCTION(returnType, name): A macro which makes + * an exportable Cryptoki library function definition out of a + * return type and a function name. It should be used in the + * following fashion to define the exposed Cryptoki functions in + * a Cryptoki library: + * + * CK_DEFINE_FUNCTION(CK_RV, C_Initialize)( + * CK_VOID_PTR pReserved + * ) + * { + * ... + * } + * + * If you're using Microsoft Developer Studio 5.0 to define a + * function in a Win32 Cryptoki .dll, it might be defined by: + * + * #define CK_DEFINE_FUNCTION(returnType, name) \ + * returnType __declspec(dllexport) name + * + * If you're using an earlier version of Microsoft Developer + * Studio to define a function in a Win16 Cryptoki .dll, it + * might be defined by: + * + * #define CK_DEFINE_FUNCTION(returnType, name) \ + * returnType __export _far _pascal name + * + * In a UNIX environment, it might be defined by: + * + * #define CK_DEFINE_FUNCTION(returnType, name) \ + * returnType name + * + * + * 3. CK_DECLARE_FUNCTION(returnType, name): A macro which makes + * an importable Cryptoki library function declaration out of a + * return type and a function name. It should be used in the + * following fashion: + * + * extern CK_DECLARE_FUNCTION(CK_RV, C_Initialize)( + * CK_VOID_PTR pReserved + * ); + * + * If you're using Microsoft Developer Studio 5.0 to declare a + * function in a Win32 Cryptoki .dll, it might be defined by: + * + * #define CK_DECLARE_FUNCTION(returnType, name) \ + * returnType __declspec(dllimport) name + * + * If you're using an earlier version of Microsoft Developer + * Studio to declare a function in a Win16 Cryptoki .dll, it + * might be defined by: + * + * #define CK_DECLARE_FUNCTION(returnType, name) \ + * returnType __export _far _pascal name + * + * In a UNIX environment, it might be defined by: + * + * #define CK_DECLARE_FUNCTION(returnType, name) \ + * returnType name + * + * + * 4. CK_DECLARE_FUNCTION_POINTER(returnType, name): A macro + * which makes a Cryptoki API function pointer declaration or + * function pointer type declaration out of a return type and a + * function name. It should be used in the following fashion: + * + * // Define funcPtr to be a pointer to a Cryptoki API function + * // taking arguments args and returning CK_RV. + * CK_DECLARE_FUNCTION_POINTER(CK_RV, funcPtr)(args); + * + * or + * + * // Define funcPtrType to be the type of a pointer to a + * // Cryptoki API function taking arguments args and returning + * // CK_RV, and then define funcPtr to be a variable of type + * // funcPtrType. + * typedef CK_DECLARE_FUNCTION_POINTER(CK_RV, funcPtrType)(args); + * funcPtrType funcPtr; + * + * If you're using Microsoft Developer Studio 5.0 to access + * functions in a Win32 Cryptoki .dll, in might be defined by: + * + * #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \ + * returnType __declspec(dllimport) (* name) + * + * If you're using an earlier version of Microsoft Developer + * Studio to access functions in a Win16 Cryptoki .dll, it might + * be defined by: + * + * #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \ + * returnType __export _far _pascal (* name) + * + * In a UNIX environment, it might be defined by: + * + * #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \ + * returnType (* name) + * + * + * 5. CK_CALLBACK_FUNCTION(returnType, name): A macro which makes + * a function pointer type for an application callback out of + * a return type for the callback and a name for the callback. + * It should be used in the following fashion: + * + * CK_CALLBACK_FUNCTION(CK_RV, myCallback)(args); + * + * to declare a function pointer, myCallback, to a callback + * which takes arguments args and returns a CK_RV. It can also + * be used like this: + * + * typedef CK_CALLBACK_FUNCTION(CK_RV, myCallbackType)(args); + * myCallbackType myCallback; + * + * If you're using Microsoft Developer Studio 5.0 to do Win32 + * Cryptoki development, it might be defined by: + * + * #define CK_CALLBACK_FUNCTION(returnType, name) \ + * returnType (* name) + * + * If you're using an earlier version of Microsoft Developer + * Studio to do Win16 development, it might be defined by: + * + * #define CK_CALLBACK_FUNCTION(returnType, name) \ + * returnType _far _pascal (* name) + * + * In a UNIX environment, it might be defined by: + * + * #define CK_CALLBACK_FUNCTION(returnType, name) \ + * returnType (* name) + * + * + * 6. NULL_PTR: This macro is the value of a NULL pointer. + * + * In any ANSI/ISO C environment (and in many others as well), + * this should best be defined by + * + * #ifndef NULL_PTR + * #define NULL_PTR 0 + * #endif + */ + + +/* All the various Cryptoki types and #define'd values are in the + * file pkcs11t.h. */ +#include "pkcs11t.h" + +#define __PASTE(x,y) x##y + + +/* ============================================================== + * Define the "extern" form of all the entry points. + * ============================================================== + */ + +#define CK_NEED_ARG_LIST 1 +#define CK_PKCS11_FUNCTION_INFO(name) \ + extern CK_DECLARE_FUNCTION(CK_RV, name) + +/* pkcs11f.h has all the information about the Cryptoki + * function prototypes. */ +#include "pkcs11f.h" + +#undef CK_NEED_ARG_LIST +#undef CK_PKCS11_FUNCTION_INFO + + +/* ============================================================== + * Define the typedef form of all the entry points. That is, for + * each Cryptoki function C_XXX, define a type CK_C_XXX which is + * a pointer to that kind of function. + * ============================================================== + */ + +#define CK_NEED_ARG_LIST 1 +#define CK_PKCS11_FUNCTION_INFO(name) \ + typedef CK_DECLARE_FUNCTION_POINTER(CK_RV, __PASTE(CK_,name)) + +/* pkcs11f.h has all the information about the Cryptoki + * function prototypes. */ +#include "pkcs11f.h" + +#undef CK_NEED_ARG_LIST +#undef CK_PKCS11_FUNCTION_INFO + + +/* ============================================================== + * Define structed vector of entry points. A CK_FUNCTION_LIST + * contains a CK_VERSION indicating a library's Cryptoki version + * and then a whole slew of function pointers to the routines in + * the library. This type was declared, but not defined, in + * pkcs11t.h. + * ============================================================== + */ + +#define CK_PKCS11_FUNCTION_INFO(name) \ + __PASTE(CK_,name) name; + +struct CK_FUNCTION_LIST { + + CK_VERSION version; /* Cryptoki version */ + +/* Pile all the function pointers into the CK_FUNCTION_LIST. */ +/* pkcs11f.h has all the information about the Cryptoki + * function prototypes. */ +#include "pkcs11f.h" + +}; + +#undef CK_PKCS11_FUNCTION_INFO + + +#undef __PASTE + +#ifdef __cplusplus +} +#endif + +#endif Index: openssl/crypto/engine/pkcs11f.h diff -u /dev/null openssl/crypto/engine/pkcs11f.h:1.1.1.1 --- /dev/null Mon Jun 13 15:55:26 2016 +++ openssl/crypto/engine/pkcs11f.h Wed Oct 24 23:27:09 2007 @@ -0,0 +1,912 @@ +/* pkcs11f.h include file for PKCS #11. */ +/* $Revision: 1.1.1.1 $ */ + +/* License to copy and use this software is granted provided that it is + * identified as "RSA Security Inc. PKCS #11 Cryptographic Token Interface + * (Cryptoki)" in all material mentioning or referencing this software. + + * License is also granted to make and use derivative works provided that + * such works are identified as "derived from the RSA Security Inc. PKCS #11 + * Cryptographic Token Interface (Cryptoki)" in all material mentioning or + * referencing the derived work. + + * RSA Security Inc. makes no representations concerning either the + * merchantability of this software or the suitability of this software for + * any particular purpose. It is provided "as is" without express or implied + * warranty of any kind. + */ + +/* This header file contains pretty much everything about all the */ +/* Cryptoki function prototypes. Because this information is */ +/* used for more than just declaring function prototypes, the */ +/* order of the functions appearing herein is important, and */ +/* should not be altered. */ + +/* General-purpose */ + +/* C_Initialize initializes the Cryptoki library. */ +CK_PKCS11_FUNCTION_INFO(C_Initialize) +#ifdef CK_NEED_ARG_LIST +( + CK_VOID_PTR pInitArgs /* if this is not NULL_PTR, it gets + * cast to CK_C_INITIALIZE_ARGS_PTR + * and dereferenced */ +); +#endif + + +/* C_Finalize indicates that an application is done with the + * Cryptoki library. */ +CK_PKCS11_FUNCTION_INFO(C_Finalize) +#ifdef CK_NEED_ARG_LIST +( + CK_VOID_PTR pReserved /* reserved. Should be NULL_PTR */ +); +#endif + + +/* C_GetInfo returns general information about Cryptoki. */ +CK_PKCS11_FUNCTION_INFO(C_GetInfo) +#ifdef CK_NEED_ARG_LIST +( + CK_INFO_PTR pInfo /* location that receives information */ +); +#endif + + +/* C_GetFunctionList returns the function list. */ +CK_PKCS11_FUNCTION_INFO(C_GetFunctionList) +#ifdef CK_NEED_ARG_LIST +( + CK_FUNCTION_LIST_PTR_PTR ppFunctionList /* receives pointer to + * function list */ +); +#endif + + + +/* Slot and token management */ + +/* C_GetSlotList obtains a list of slots in the system. */ +CK_PKCS11_FUNCTION_INFO(C_GetSlotList) +#ifdef CK_NEED_ARG_LIST +( + CK_BBOOL tokenPresent, /* only slots with tokens? */ + CK_SLOT_ID_PTR pSlotList, /* receives array of slot IDs */ + CK_ULONG_PTR pulCount /* receives number of slots */ +); +#endif + + +/* C_GetSlotInfo obtains information about a particular slot in + * the system. */ +CK_PKCS11_FUNCTION_INFO(C_GetSlotInfo) +#ifdef CK_NEED_ARG_LIST +( + CK_SLOT_ID slotID, /* the ID of the slot */ + CK_SLOT_INFO_PTR pInfo /* receives the slot information */ +); +#endif + + +/* C_GetTokenInfo obtains information about a particular token + * in the system. */ +CK_PKCS11_FUNCTION_INFO(C_GetTokenInfo) +#ifdef CK_NEED_ARG_LIST +( + CK_SLOT_ID slotID, /* ID of the token's slot */ + CK_TOKEN_INFO_PTR pInfo /* receives the token information */ +); +#endif + + +/* C_GetMechanismList obtains a list of mechanism types + * supported by a token. */ +CK_PKCS11_FUNCTION_INFO(C_GetMechanismList) +#ifdef CK_NEED_ARG_LIST +( + CK_SLOT_ID slotID, /* ID of token's slot */ + CK_MECHANISM_TYPE_PTR pMechanismList, /* gets mech. array */ + CK_ULONG_PTR pulCount /* gets # of mechs. */ +); +#endif + + +/* C_GetMechanismInfo obtains information about a particular + * mechanism possibly supported by a token. */ +CK_PKCS11_FUNCTION_INFO(C_GetMechanismInfo) +#ifdef CK_NEED_ARG_LIST +( + CK_SLOT_ID slotID, /* ID of the token's slot */ + CK_MECHANISM_TYPE type, /* type of mechanism */ + CK_MECHANISM_INFO_PTR pInfo /* receives mechanism info */ +); +#endif + + +/* C_InitToken initializes a token. */ +CK_PKCS11_FUNCTION_INFO(C_InitToken) +#ifdef CK_NEED_ARG_LIST +/* pLabel changed from CK_CHAR_PTR to CK_UTF8CHAR_PTR for v2.10 */ +( + CK_SLOT_ID slotID, /* ID of the token's slot */ + CK_UTF8CHAR_PTR pPin, /* the SO's initial PIN */ + CK_ULONG ulPinLen, /* length in bytes of the PIN */ + CK_UTF8CHAR_PTR pLabel /* 32-byte token label (blank padded) */ +); +#endif + + +/* C_InitPIN initializes the normal user's PIN. */ +CK_PKCS11_FUNCTION_INFO(C_InitPIN) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_UTF8CHAR_PTR pPin, /* the normal user's PIN */ + CK_ULONG ulPinLen /* length in bytes of the PIN */ +); +#endif + + +/* C_SetPIN modifies the PIN of the user who is logged in. */ +CK_PKCS11_FUNCTION_INFO(C_SetPIN) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_UTF8CHAR_PTR pOldPin, /* the old PIN */ + CK_ULONG ulOldLen, /* length of the old PIN */ + CK_UTF8CHAR_PTR pNewPin, /* the new PIN */ + CK_ULONG ulNewLen /* length of the new PIN */ +); +#endif + + + +/* Session management */ + +/* C_OpenSession opens a session between an application and a + * token. */ +CK_PKCS11_FUNCTION_INFO(C_OpenSession) +#ifdef CK_NEED_ARG_LIST +( + CK_SLOT_ID slotID, /* the slot's ID */ + CK_FLAGS flags, /* from CK_SESSION_INFO */ + CK_VOID_PTR pApplication, /* passed to callback */ + CK_NOTIFY Notify, /* callback function */ + CK_SESSION_HANDLE_PTR phSession /* gets session handle */ +); +#endif + + +/* C_CloseSession closes a session between an application and a + * token. */ +CK_PKCS11_FUNCTION_INFO(C_CloseSession) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession /* the session's handle */ +); +#endif + + +/* C_CloseAllSessions closes all sessions with a token. */ +CK_PKCS11_FUNCTION_INFO(C_CloseAllSessions) +#ifdef CK_NEED_ARG_LIST +( + CK_SLOT_ID slotID /* the token's slot */ +); +#endif + + +/* C_GetSessionInfo obtains information about the session. */ +CK_PKCS11_FUNCTION_INFO(C_GetSessionInfo) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_SESSION_INFO_PTR pInfo /* receives session info */ +); +#endif + + +/* C_GetOperationState obtains the state of the cryptographic operation + * in a session. */ +CK_PKCS11_FUNCTION_INFO(C_GetOperationState) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* session's handle */ + CK_BYTE_PTR pOperationState, /* gets state */ + CK_ULONG_PTR pulOperationStateLen /* gets state length */ +); +#endif + + +/* C_SetOperationState restores the state of the cryptographic + * operation in a session. */ +CK_PKCS11_FUNCTION_INFO(C_SetOperationState) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* session's handle */ + CK_BYTE_PTR pOperationState, /* holds state */ + CK_ULONG ulOperationStateLen, /* holds state length */ + CK_OBJECT_HANDLE hEncryptionKey, /* en/decryption key */ + CK_OBJECT_HANDLE hAuthenticationKey /* sign/verify key */ +); +#endif + + +/* C_Login logs a user into a token. */ +CK_PKCS11_FUNCTION_INFO(C_Login) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_USER_TYPE userType, /* the user type */ + CK_UTF8CHAR_PTR pPin, /* the user's PIN */ + CK_ULONG ulPinLen /* the length of the PIN */ +); +#endif + + +/* C_Logout logs a user out from a token. */ +CK_PKCS11_FUNCTION_INFO(C_Logout) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession /* the session's handle */ +); +#endif + + + +/* Object management */ + +/* C_CreateObject creates a new object. */ +CK_PKCS11_FUNCTION_INFO(C_CreateObject) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_ATTRIBUTE_PTR pTemplate, /* the object's template */ + CK_ULONG ulCount, /* attributes in template */ + CK_OBJECT_HANDLE_PTR phObject /* gets new object's handle. */ +); +#endif + + +/* C_CopyObject copies an object, creating a new object for the + * copy. */ +CK_PKCS11_FUNCTION_INFO(C_CopyObject) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_OBJECT_HANDLE hObject, /* the object's handle */ + CK_ATTRIBUTE_PTR pTemplate, /* template for new object */ + CK_ULONG ulCount, /* attributes in template */ + CK_OBJECT_HANDLE_PTR phNewObject /* receives handle of copy */ +); +#endif + + +/* C_DestroyObject destroys an object. */ +CK_PKCS11_FUNCTION_INFO(C_DestroyObject) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_OBJECT_HANDLE hObject /* the object's handle */ +); +#endif + + +/* C_GetObjectSize gets the size of an object in bytes. */ +CK_PKCS11_FUNCTION_INFO(C_GetObjectSize) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_OBJECT_HANDLE hObject, /* the object's handle */ + CK_ULONG_PTR pulSize /* receives size of object */ +); +#endif + + +/* C_GetAttributeValue obtains the value of one or more object + * attributes. */ +CK_PKCS11_FUNCTION_INFO(C_GetAttributeValue) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_OBJECT_HANDLE hObject, /* the object's handle */ + CK_ATTRIBUTE_PTR pTemplate, /* specifies attrs; gets vals */ + CK_ULONG ulCount /* attributes in template */ +); +#endif + + +/* C_SetAttributeValue modifies the value of one or more object + * attributes */ +CK_PKCS11_FUNCTION_INFO(C_SetAttributeValue) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_OBJECT_HANDLE hObject, /* the object's handle */ + CK_ATTRIBUTE_PTR pTemplate, /* specifies attrs and values */ + CK_ULONG ulCount /* attributes in template */ +); +#endif + + +/* C_FindObjectsInit initializes a search for token and session + * objects that match a template. */ +CK_PKCS11_FUNCTION_INFO(C_FindObjectsInit) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_ATTRIBUTE_PTR pTemplate, /* attribute values to match */ + CK_ULONG ulCount /* attrs in search template */ +); +#endif + + +/* C_FindObjects continues a search for token and session + * objects that match a template, obtaining additional object + * handles. */ +CK_PKCS11_FUNCTION_INFO(C_FindObjects) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* session's handle */ + CK_OBJECT_HANDLE_PTR phObject, /* gets obj. handles */ + CK_ULONG ulMaxObjectCount, /* max handles to get */ + CK_ULONG_PTR pulObjectCount /* actual # returned */ +); +#endif + + +/* C_FindObjectsFinal finishes a search for token and session + * objects. */ +CK_PKCS11_FUNCTION_INFO(C_FindObjectsFinal) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession /* the session's handle */ +); +#endif + + + +/* Encryption and decryption */ + +/* C_EncryptInit initializes an encryption operation. */ +CK_PKCS11_FUNCTION_INFO(C_EncryptInit) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_MECHANISM_PTR pMechanism, /* the encryption mechanism */ + CK_OBJECT_HANDLE hKey /* handle of encryption key */ +); +#endif + + +/* C_Encrypt encrypts single-part data. */ +CK_PKCS11_FUNCTION_INFO(C_Encrypt) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* session's handle */ + CK_BYTE_PTR pData, /* the plaintext data */ + CK_ULONG ulDataLen, /* bytes of plaintext */ + CK_BYTE_PTR pEncryptedData, /* gets ciphertext */ + CK_ULONG_PTR pulEncryptedDataLen /* gets c-text size */ +); +#endif + + +/* C_EncryptUpdate continues a multiple-part encryption + * operation. */ +CK_PKCS11_FUNCTION_INFO(C_EncryptUpdate) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* session's handle */ + CK_BYTE_PTR pPart, /* the plaintext data */ + CK_ULONG ulPartLen, /* plaintext data len */ + CK_BYTE_PTR pEncryptedPart, /* gets ciphertext */ + CK_ULONG_PTR pulEncryptedPartLen /* gets c-text size */ +); +#endif + + +/* C_EncryptFinal finishes a multiple-part encryption + * operation. */ +CK_PKCS11_FUNCTION_INFO(C_EncryptFinal) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* session handle */ + CK_BYTE_PTR pLastEncryptedPart, /* last c-text */ + CK_ULONG_PTR pulLastEncryptedPartLen /* gets last size */ +); +#endif + + +/* C_DecryptInit initializes a decryption operation. */ +CK_PKCS11_FUNCTION_INFO(C_DecryptInit) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_MECHANISM_PTR pMechanism, /* the decryption mechanism */ + CK_OBJECT_HANDLE hKey /* handle of decryption key */ +); +#endif + + +/* C_Decrypt decrypts encrypted data in a single part. */ +CK_PKCS11_FUNCTION_INFO(C_Decrypt) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* session's handle */ + CK_BYTE_PTR pEncryptedData, /* ciphertext */ + CK_ULONG ulEncryptedDataLen, /* ciphertext length */ + CK_BYTE_PTR pData, /* gets plaintext */ + CK_ULONG_PTR pulDataLen /* gets p-text size */ +); +#endif + + +/* C_DecryptUpdate continues a multiple-part decryption + * operation. */ +CK_PKCS11_FUNCTION_INFO(C_DecryptUpdate) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* session's handle */ + CK_BYTE_PTR pEncryptedPart, /* encrypted data */ + CK_ULONG ulEncryptedPartLen, /* input length */ + CK_BYTE_PTR pPart, /* gets plaintext */ + CK_ULONG_PTR pulPartLen /* p-text size */ +); +#endif + + +/* C_DecryptFinal finishes a multiple-part decryption + * operation. */ +CK_PKCS11_FUNCTION_INFO(C_DecryptFinal) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_BYTE_PTR pLastPart, /* gets plaintext */ + CK_ULONG_PTR pulLastPartLen /* p-text size */ +); +#endif + + + +/* Message digesting */ + +/* C_DigestInit initializes a message-digesting operation. */ +CK_PKCS11_FUNCTION_INFO(C_DigestInit) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_MECHANISM_PTR pMechanism /* the digesting mechanism */ +); +#endif + + +/* C_Digest digests data in a single part. */ +CK_PKCS11_FUNCTION_INFO(C_Digest) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_BYTE_PTR pData, /* data to be digested */ + CK_ULONG ulDataLen, /* bytes of data to digest */ + CK_BYTE_PTR pDigest, /* gets the message digest */ + CK_ULONG_PTR pulDigestLen /* gets digest length */ +); +#endif + + +/* C_DigestUpdate continues a multiple-part message-digesting + * operation. */ +CK_PKCS11_FUNCTION_INFO(C_DigestUpdate) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_BYTE_PTR pPart, /* data to be digested */ + CK_ULONG ulPartLen /* bytes of data to be digested */ +); +#endif + + +/* C_DigestKey continues a multi-part message-digesting + * operation, by digesting the value of a secret key as part of + * the data already digested. */ +CK_PKCS11_FUNCTION_INFO(C_DigestKey) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_OBJECT_HANDLE hKey /* secret key to digest */ +); +#endif + + +/* C_DigestFinal finishes a multiple-part message-digesting + * operation. */ +CK_PKCS11_FUNCTION_INFO(C_DigestFinal) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_BYTE_PTR pDigest, /* gets the message digest */ + CK_ULONG_PTR pulDigestLen /* gets byte count of digest */ +); +#endif + + + +/* Signing and MACing */ + +/* C_SignInit initializes a signature (private key encryption) + * operation, where the signature is (will be) an appendix to + * the data, and plaintext cannot be recovered from the + *signature. */ +CK_PKCS11_FUNCTION_INFO(C_SignInit) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_MECHANISM_PTR pMechanism, /* the signature mechanism */ + CK_OBJECT_HANDLE hKey /* handle of signature key */ +); +#endif + + +/* C_Sign signs (encrypts with private key) data in a single + * part, where the signature is (will be) an appendix to the + * data, and plaintext cannot be recovered from the signature. */ +CK_PKCS11_FUNCTION_INFO(C_Sign) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_BYTE_PTR pData, /* the data to sign */ + CK_ULONG ulDataLen, /* count of bytes to sign */ + CK_BYTE_PTR pSignature, /* gets the signature */ + CK_ULONG_PTR pulSignatureLen /* gets signature length */ +); +#endif + + +/* C_SignUpdate continues a multiple-part signature operation, + * where the signature is (will be) an appendix to the data, + * and plaintext cannot be recovered from the signature. */ +CK_PKCS11_FUNCTION_INFO(C_SignUpdate) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_BYTE_PTR pPart, /* the data to sign */ + CK_ULONG ulPartLen /* count of bytes to sign */ +); +#endif + + +/* C_SignFinal finishes a multiple-part signature operation, + * returning the signature. */ +CK_PKCS11_FUNCTION_INFO(C_SignFinal) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_BYTE_PTR pSignature, /* gets the signature */ + CK_ULONG_PTR pulSignatureLen /* gets signature length */ +); +#endif + + +/* C_SignRecoverInit initializes a signature operation, where + * the data can be recovered from the signature. */ +CK_PKCS11_FUNCTION_INFO(C_SignRecoverInit) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_MECHANISM_PTR pMechanism, /* the signature mechanism */ + CK_OBJECT_HANDLE hKey /* handle of the signature key */ +); +#endif + + +/* C_SignRecover signs data in a single operation, where the + * data can be recovered from the signature. */ +CK_PKCS11_FUNCTION_INFO(C_SignRecover) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_BYTE_PTR pData, /* the data to sign */ + CK_ULONG ulDataLen, /* count of bytes to sign */ + CK_BYTE_PTR pSignature, /* gets the signature */ + CK_ULONG_PTR pulSignatureLen /* gets signature length */ +); +#endif + + + +/* Verifying signatures and MACs */ + +/* C_VerifyInit initializes a verification operation, where the + * signature is an appendix to the data, and plaintext cannot + * cannot be recovered from the signature (e.g. DSA). */ +CK_PKCS11_FUNCTION_INFO(C_VerifyInit) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_MECHANISM_PTR pMechanism, /* the verification mechanism */ + CK_OBJECT_HANDLE hKey /* verification key */ +); +#endif + + +/* C_Verify verifies a signature in a single-part operation, + * where the signature is an appendix to the data, and plaintext + * cannot be recovered from the signature. */ +CK_PKCS11_FUNCTION_INFO(C_Verify) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_BYTE_PTR pData, /* signed data */ + CK_ULONG ulDataLen, /* length of signed data */ + CK_BYTE_PTR pSignature, /* signature */ + CK_ULONG ulSignatureLen /* signature length*/ +); +#endif + + +/* C_VerifyUpdate continues a multiple-part verification + * operation, where the signature is an appendix to the data, + * and plaintext cannot be recovered from the signature. */ +CK_PKCS11_FUNCTION_INFO(C_VerifyUpdate) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_BYTE_PTR pPart, /* signed data */ + CK_ULONG ulPartLen /* length of signed data */ +); +#endif + + +/* C_VerifyFinal finishes a multiple-part verification + * operation, checking the signature. */ +CK_PKCS11_FUNCTION_INFO(C_VerifyFinal) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_BYTE_PTR pSignature, /* signature to verify */ + CK_ULONG ulSignatureLen /* signature length */ +); +#endif + + +/* C_VerifyRecoverInit initializes a signature verification + * operation, where the data is recovered from the signature. */ +CK_PKCS11_FUNCTION_INFO(C_VerifyRecoverInit) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_MECHANISM_PTR pMechanism, /* the verification mechanism */ + CK_OBJECT_HANDLE hKey /* verification key */ +); +#endif + + +/* C_VerifyRecover verifies a signature in a single-part + * operation, where the data is recovered from the signature. */ +CK_PKCS11_FUNCTION_INFO(C_VerifyRecover) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_BYTE_PTR pSignature, /* signature to verify */ + CK_ULONG ulSignatureLen, /* signature length */ + CK_BYTE_PTR pData, /* gets signed data */ + CK_ULONG_PTR pulDataLen /* gets signed data len */ +); +#endif + + + +/* Dual-function cryptographic operations */ + +/* C_DigestEncryptUpdate continues a multiple-part digesting + * and encryption operation. */ +CK_PKCS11_FUNCTION_INFO(C_DigestEncryptUpdate) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* session's handle */ + CK_BYTE_PTR pPart, /* the plaintext data */ + CK_ULONG ulPartLen, /* plaintext length */ + CK_BYTE_PTR pEncryptedPart, /* gets ciphertext */ + CK_ULONG_PTR pulEncryptedPartLen /* gets c-text length */ +); +#endif + + +/* C_DecryptDigestUpdate continues a multiple-part decryption and + * digesting operation. */ +CK_PKCS11_FUNCTION_INFO(C_DecryptDigestUpdate) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* session's handle */ + CK_BYTE_PTR pEncryptedPart, /* ciphertext */ + CK_ULONG ulEncryptedPartLen, /* ciphertext length */ + CK_BYTE_PTR pPart, /* gets plaintext */ + CK_ULONG_PTR pulPartLen /* gets plaintext len */ +); +#endif + + +/* C_SignEncryptUpdate continues a multiple-part signing and + * encryption operation. */ +CK_PKCS11_FUNCTION_INFO(C_SignEncryptUpdate) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* session's handle */ + CK_BYTE_PTR pPart, /* the plaintext data */ + CK_ULONG ulPartLen, /* plaintext length */ + CK_BYTE_PTR pEncryptedPart, /* gets ciphertext */ + CK_ULONG_PTR pulEncryptedPartLen /* gets c-text length */ +); +#endif + + +/* C_DecryptVerifyUpdate continues a multiple-part decryption and + * verify operation. */ +CK_PKCS11_FUNCTION_INFO(C_DecryptVerifyUpdate) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* session's handle */ + CK_BYTE_PTR pEncryptedPart, /* ciphertext */ + CK_ULONG ulEncryptedPartLen, /* ciphertext length */ + CK_BYTE_PTR pPart, /* gets plaintext */ + CK_ULONG_PTR pulPartLen /* gets p-text length */ +); +#endif + + + +/* Key management */ + +/* C_GenerateKey generates a secret key, creating a new key + * object. */ +CK_PKCS11_FUNCTION_INFO(C_GenerateKey) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_MECHANISM_PTR pMechanism, /* key generation mech. */ + CK_ATTRIBUTE_PTR pTemplate, /* template for new key */ + CK_ULONG ulCount, /* # of attrs in template */ + CK_OBJECT_HANDLE_PTR phKey /* gets handle of new key */ +); +#endif + + +/* C_GenerateKeyPair generates a public-key/private-key pair, + * creating new key objects. */ +CK_PKCS11_FUNCTION_INFO(C_GenerateKeyPair) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* session + * handle */ + CK_MECHANISM_PTR pMechanism, /* key-gen + * mech. */ + CK_ATTRIBUTE_PTR pPublicKeyTemplate, /* template + * for pub. + * key */ + CK_ULONG ulPublicKeyAttributeCount, /* # pub. + * attrs. */ + CK_ATTRIBUTE_PTR pPrivateKeyTemplate, /* template + * for priv. + * key */ + CK_ULONG ulPrivateKeyAttributeCount, /* # priv. + * attrs. */ + CK_OBJECT_HANDLE_PTR phPublicKey, /* gets pub. + * key + * handle */ + CK_OBJECT_HANDLE_PTR phPrivateKey /* gets + * priv. key + * handle */ +); +#endif + + +/* C_WrapKey wraps (i.e., encrypts) a key. */ +CK_PKCS11_FUNCTION_INFO(C_WrapKey) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_MECHANISM_PTR pMechanism, /* the wrapping mechanism */ + CK_OBJECT_HANDLE hWrappingKey, /* wrapping key */ + CK_OBJECT_HANDLE hKey, /* key to be wrapped */ + CK_BYTE_PTR pWrappedKey, /* gets wrapped key */ + CK_ULONG_PTR pulWrappedKeyLen /* gets wrapped key size */ +); +#endif + + +/* C_UnwrapKey unwraps (decrypts) a wrapped key, creating a new + * key object. */ +CK_PKCS11_FUNCTION_INFO(C_UnwrapKey) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* session's handle */ + CK_MECHANISM_PTR pMechanism, /* unwrapping mech. */ + CK_OBJECT_HANDLE hUnwrappingKey, /* unwrapping key */ + CK_BYTE_PTR pWrappedKey, /* the wrapped key */ + CK_ULONG ulWrappedKeyLen, /* wrapped key len */ + CK_ATTRIBUTE_PTR pTemplate, /* new key template */ + CK_ULONG ulAttributeCount, /* template length */ + CK_OBJECT_HANDLE_PTR phKey /* gets new handle */ +); +#endif + + +/* C_DeriveKey derives a key from a base key, creating a new key + * object. */ +CK_PKCS11_FUNCTION_INFO(C_DeriveKey) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* session's handle */ + CK_MECHANISM_PTR pMechanism, /* key deriv. mech. */ + CK_OBJECT_HANDLE hBaseKey, /* base key */ + CK_ATTRIBUTE_PTR pTemplate, /* new key template */ + CK_ULONG ulAttributeCount, /* template length */ + CK_OBJECT_HANDLE_PTR phKey /* gets new handle */ +); +#endif + + + +/* Random number generation */ + +/* C_SeedRandom mixes additional seed material into the token's + * random number generator. */ +CK_PKCS11_FUNCTION_INFO(C_SeedRandom) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_BYTE_PTR pSeed, /* the seed material */ + CK_ULONG ulSeedLen /* length of seed material */ +); +#endif + + +/* C_GenerateRandom generates random data. */ +CK_PKCS11_FUNCTION_INFO(C_GenerateRandom) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_BYTE_PTR RandomData, /* receives the random data */ + CK_ULONG ulRandomLen /* # of bytes to generate */ +); +#endif + + + +/* Parallel function management */ + +/* C_GetFunctionStatus is a legacy function; it obtains an + * updated status of a function running in parallel with an + * application. */ +CK_PKCS11_FUNCTION_INFO(C_GetFunctionStatus) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession /* the session's handle */ +); +#endif + + +/* C_CancelFunction is a legacy function; it cancels a function + * running in parallel. */ +CK_PKCS11_FUNCTION_INFO(C_CancelFunction) +#ifdef CK_NEED_ARG_LIST +( + CK_SESSION_HANDLE hSession /* the session's handle */ +); +#endif + + + +/* Functions added in for Cryptoki Version 2.01 or later */ + +/* C_WaitForSlotEvent waits for a slot event (token insertion, + * removal, etc.) to occur. */ +CK_PKCS11_FUNCTION_INFO(C_WaitForSlotEvent) +#ifdef CK_NEED_ARG_LIST +( + CK_FLAGS flags, /* blocking/nonblocking flag */ + CK_SLOT_ID_PTR pSlot, /* location that receives the slot ID */ + CK_VOID_PTR pRserved /* reserved. Should be NULL_PTR */ +); +#endif Index: openssl/crypto/engine/pkcs11t.h diff -u /dev/null openssl/crypto/engine/pkcs11t.h:1.2 --- /dev/null Mon Jun 13 15:55:26 2016 +++ openssl/crypto/engine/pkcs11t.h Sat Aug 30 11:58:07 2008 @@ -0,0 +1,1885 @@ +/* pkcs11t.h include file for PKCS #11. */ +/* $Revision: 1.2 $ */ + +/* License to copy and use this software is granted provided that it is + * identified as "RSA Security Inc. PKCS #11 Cryptographic Token Interface + * (Cryptoki)" in all material mentioning or referencing this software. + + * License is also granted to make and use derivative works provided that + * such works are identified as "derived from the RSA Security Inc. PKCS #11 + * Cryptographic Token Interface (Cryptoki)" in all material mentioning or + * referencing the derived work. + + * RSA Security Inc. makes no representations concerning either the + * merchantability of this software or the suitability of this software for + * any particular purpose. It is provided "as is" without express or implied + * warranty of any kind. + */ + +/* See top of pkcs11.h for information about the macros that + * must be defined and the structure-packing conventions that + * must be set before including this file. */ + +#ifndef _PKCS11T_H_ +#define _PKCS11T_H_ 1 + +#define CRYPTOKI_VERSION_MAJOR 2 +#define CRYPTOKI_VERSION_MINOR 20 +#define CRYPTOKI_VERSION_AMENDMENT 3 + +#define CK_TRUE 1 +#define CK_FALSE 0 + +#ifndef CK_DISABLE_TRUE_FALSE +#ifndef FALSE +#define FALSE CK_FALSE +#endif + +#ifndef TRUE +#define TRUE CK_TRUE +#endif +#endif + +/* an unsigned 8-bit value */ +typedef unsigned char CK_BYTE; + +/* an unsigned 8-bit character */ +typedef CK_BYTE CK_CHAR; + +/* an 8-bit UTF-8 character */ +typedef CK_BYTE CK_UTF8CHAR; + +/* a BYTE-sized Boolean flag */ +typedef CK_BYTE CK_BBOOL; + +/* an unsigned value, at least 32 bits long */ +typedef unsigned long int CK_ULONG; + +/* a signed value, the same size as a CK_ULONG */ +/* CK_LONG is new for v2.0 */ +typedef long int CK_LONG; + +/* at least 32 bits; each bit is a Boolean flag */ +typedef CK_ULONG CK_FLAGS; + + +/* some special values for certain CK_ULONG variables */ +#define CK_UNAVAILABLE_INFORMATION (~0UL) +#define CK_EFFECTIVELY_INFINITE 0 + + +typedef CK_BYTE CK_PTR CK_BYTE_PTR; +typedef CK_CHAR CK_PTR CK_CHAR_PTR; +typedef CK_UTF8CHAR CK_PTR CK_UTF8CHAR_PTR; +typedef CK_ULONG CK_PTR CK_ULONG_PTR; +typedef void CK_PTR CK_VOID_PTR; + +/* Pointer to a CK_VOID_PTR-- i.e., pointer to pointer to void */ +typedef CK_VOID_PTR CK_PTR CK_VOID_PTR_PTR; + + +/* The following value is always invalid if used as a session */ +/* handle or object handle */ +#define CK_INVALID_HANDLE 0 + + +typedef struct CK_VERSION { + CK_BYTE major; /* integer portion of version number */ + CK_BYTE minor; /* 1/100ths portion of version number */ +} CK_VERSION; + +typedef CK_VERSION CK_PTR CK_VERSION_PTR; + + +typedef struct CK_INFO { + /* manufacturerID and libraryDecription have been changed from + * CK_CHAR to CK_UTF8CHAR for v2.10 */ + CK_VERSION cryptokiVersion; /* Cryptoki interface ver */ + CK_UTF8CHAR manufacturerID[32]; /* blank padded */ + CK_FLAGS flags; /* must be zero */ + + /* libraryDescription and libraryVersion are new for v2.0 */ + CK_UTF8CHAR libraryDescription[32]; /* blank padded */ + CK_VERSION libraryVersion; /* version of library */ +} CK_INFO; + +typedef CK_INFO CK_PTR CK_INFO_PTR; + + +/* CK_NOTIFICATION enumerates the types of notifications that + * Cryptoki provides to an application */ +/* CK_NOTIFICATION has been changed from an enum to a CK_ULONG + * for v2.0 */ +typedef CK_ULONG CK_NOTIFICATION; +#define CKN_SURRENDER 0 + +/* The following notification is new for PKCS #11 v2.20 amendment 3 */ +#define CKN_OTP_CHANGED 1 + + +typedef CK_ULONG CK_SLOT_ID; + +typedef CK_SLOT_ID CK_PTR CK_SLOT_ID_PTR; + + +/* CK_SLOT_INFO provides information about a slot */ +typedef struct CK_SLOT_INFO { + /* slotDescription and manufacturerID have been changed from + * CK_CHAR to CK_UTF8CHAR for v2.10 */ + CK_UTF8CHAR slotDescription[64]; /* blank padded */ + CK_UTF8CHAR manufacturerID[32]; /* blank padded */ + CK_FLAGS flags; + + /* hardwareVersion and firmwareVersion are new for v2.0 */ + CK_VERSION hardwareVersion; /* version of hardware */ + CK_VERSION firmwareVersion; /* version of firmware */ +} CK_SLOT_INFO; + +/* flags: bit flags that provide capabilities of the slot + * Bit Flag Mask Meaning + */ +#define CKF_TOKEN_PRESENT 0x00000001 /* a token is there */ +#define CKF_REMOVABLE_DEVICE 0x00000002 /* removable devices*/ +#define CKF_HW_SLOT 0x00000004 /* hardware slot */ + +typedef CK_SLOT_INFO CK_PTR CK_SLOT_INFO_PTR; + + +/* CK_TOKEN_INFO provides information about a token */ +typedef struct CK_TOKEN_INFO { + /* label, manufacturerID, and model have been changed from + * CK_CHAR to CK_UTF8CHAR for v2.10 */ + CK_UTF8CHAR label[32]; /* blank padded */ + CK_UTF8CHAR manufacturerID[32]; /* blank padded */ + CK_UTF8CHAR model[16]; /* blank padded */ + CK_CHAR serialNumber[16]; /* blank padded */ + CK_FLAGS flags; /* see below */ + + /* ulMaxSessionCount, ulSessionCount, ulMaxRwSessionCount, + * ulRwSessionCount, ulMaxPinLen, and ulMinPinLen have all been + * changed from CK_USHORT to CK_ULONG for v2.0 */ + CK_ULONG ulMaxSessionCount; /* max open sessions */ + CK_ULONG ulSessionCount; /* sess. now open */ + CK_ULONG ulMaxRwSessionCount; /* max R/W sessions */ + CK_ULONG ulRwSessionCount; /* R/W sess. now open */ + CK_ULONG ulMaxPinLen; /* in bytes */ + CK_ULONG ulMinPinLen; /* in bytes */ + CK_ULONG ulTotalPublicMemory; /* in bytes */ + CK_ULONG ulFreePublicMemory; /* in bytes */ + CK_ULONG ulTotalPrivateMemory; /* in bytes */ + CK_ULONG ulFreePrivateMemory; /* in bytes */ + + /* hardwareVersion, firmwareVersion, and time are new for + * v2.0 */ + CK_VERSION hardwareVersion; /* version of hardware */ + CK_VERSION firmwareVersion; /* version of firmware */ + CK_CHAR utcTime[16]; /* time */ +} CK_TOKEN_INFO; + +/* The flags parameter is defined as follows: + * Bit Flag Mask Meaning + */ +#define CKF_RNG 0x00000001 /* has random # + * generator */ +#define CKF_WRITE_PROTECTED 0x00000002 /* token is + * write- + * protected */ +#define CKF_LOGIN_REQUIRED 0x00000004 /* user must + * login */ +#define CKF_USER_PIN_INITIALIZED 0x00000008 /* normal user's + * PIN is set */ + +/* CKF_RESTORE_KEY_NOT_NEEDED is new for v2.0. If it is set, + * that means that *every* time the state of cryptographic + * operations of a session is successfully saved, all keys + * needed to continue those operations are stored in the state */ +#define CKF_RESTORE_KEY_NOT_NEEDED 0x00000020 + +/* CKF_CLOCK_ON_TOKEN is new for v2.0. If it is set, that means + * that the token has some sort of clock. The time on that + * clock is returned in the token info structure */ +#define CKF_CLOCK_ON_TOKEN 0x00000040 + +/* CKF_PROTECTED_AUTHENTICATION_PATH is new for v2.0. If it is + * set, that means that there is some way for the user to login + * without sending a PIN through the Cryptoki library itself */ +#define CKF_PROTECTED_AUTHENTICATION_PATH 0x00000100 + +/* CKF_DUAL_CRYPTO_OPERATIONS is new for v2.0. If it is true, + * that means that a single session with the token can perform + * dual simultaneous cryptographic operations (digest and + * encrypt; decrypt and digest; sign and encrypt; and decrypt + * and sign) */ +#define CKF_DUAL_CRYPTO_OPERATIONS 0x00000200 + +/* CKF_TOKEN_INITIALIZED if new for v2.10. If it is true, the + * token has been initialized using C_InitializeToken or an + * equivalent mechanism outside the scope of PKCS #11. + * Calling C_InitializeToken when this flag is set will cause + * the token to be reinitialized. */ +#define CKF_TOKEN_INITIALIZED 0x00000400 + +/* CKF_SECONDARY_AUTHENTICATION if new for v2.10. If it is + * true, the token supports secondary authentication for + * private key objects. This flag is deprecated in v2.11 and + onwards. */ +#define CKF_SECONDARY_AUTHENTICATION 0x00000800 + +/* CKF_USER_PIN_COUNT_LOW if new for v2.10. If it is true, an + * incorrect user login PIN has been entered at least once + * since the last successful authentication. */ +#define CKF_USER_PIN_COUNT_LOW 0x00010000 + +/* CKF_USER_PIN_FINAL_TRY if new for v2.10. If it is true, + * supplying an incorrect user PIN will it to become locked. */ +#define CKF_USER_PIN_FINAL_TRY 0x00020000 + +/* CKF_USER_PIN_LOCKED if new for v2.10. If it is true, the + * user PIN has been locked. User login to the token is not + * possible. */ +#define CKF_USER_PIN_LOCKED 0x00040000 + +/* CKF_USER_PIN_TO_BE_CHANGED if new for v2.10. If it is true, + * the user PIN value is the default value set by token + * initialization or manufacturing, or the PIN has been + * expired by the card. */ +#define CKF_USER_PIN_TO_BE_CHANGED 0x00080000 + +/* CKF_SO_PIN_COUNT_LOW if new for v2.10. If it is true, an + * incorrect SO login PIN has been entered at least once since + * the last successful authentication. */ +#define CKF_SO_PIN_COUNT_LOW 0x00100000 + +/* CKF_SO_PIN_FINAL_TRY if new for v2.10. If it is true, + * supplying an incorrect SO PIN will it to become locked. */ +#define CKF_SO_PIN_FINAL_TRY 0x00200000 + +/* CKF_SO_PIN_LOCKED if new for v2.10. If it is true, the SO + * PIN has been locked. SO login to the token is not possible. + */ +#define CKF_SO_PIN_LOCKED 0x00400000 + +/* CKF_SO_PIN_TO_BE_CHANGED if new for v2.10. If it is true, + * the SO PIN value is the default value set by token + * initialization or manufacturing, or the PIN has been + * expired by the card. */ +#define CKF_SO_PIN_TO_BE_CHANGED 0x00800000 + +typedef CK_TOKEN_INFO CK_PTR CK_TOKEN_INFO_PTR; + + +/* CK_SESSION_HANDLE is a Cryptoki-assigned value that + * identifies a session */ +typedef CK_ULONG CK_SESSION_HANDLE; + +typedef CK_SESSION_HANDLE CK_PTR CK_SESSION_HANDLE_PTR; + + +/* CK_USER_TYPE enumerates the types of Cryptoki users */ +/* CK_USER_TYPE has been changed from an enum to a CK_ULONG for + * v2.0 */ +typedef CK_ULONG CK_USER_TYPE; +/* Security Officer */ +#define CKU_SO 0 +/* Normal user */ +#define CKU_USER 1 +/* Context specific (added in v2.20) */ +#define CKU_CONTEXT_SPECIFIC 2 + +/* CK_STATE enumerates the session states */ +/* CK_STATE has been changed from an enum to a CK_ULONG for + * v2.0 */ +typedef CK_ULONG CK_STATE; +#define CKS_RO_PUBLIC_SESSION 0 +#define CKS_RO_USER_FUNCTIONS 1 +#define CKS_RW_PUBLIC_SESSION 2 +#define CKS_RW_USER_FUNCTIONS 3 +#define CKS_RW_SO_FUNCTIONS 4 + + +/* CK_SESSION_INFO provides information about a session */ +typedef struct CK_SESSION_INFO { + CK_SLOT_ID slotID; + CK_STATE state; + CK_FLAGS flags; /* see below */ + + /* ulDeviceError was changed from CK_USHORT to CK_ULONG for + * v2.0 */ + CK_ULONG ulDeviceError; /* device-dependent error code */ +} CK_SESSION_INFO; + +/* The flags are defined in the following table: + * Bit Flag Mask Meaning + */ +#define CKF_RW_SESSION 0x00000002 /* session is r/w */ +#define CKF_SERIAL_SESSION 0x00000004 /* no parallel */ + +typedef CK_SESSION_INFO CK_PTR CK_SESSION_INFO_PTR; + + +/* CK_OBJECT_HANDLE is a token-specific identifier for an + * object */ +typedef CK_ULONG CK_OBJECT_HANDLE; + +typedef CK_OBJECT_HANDLE CK_PTR CK_OBJECT_HANDLE_PTR; + + +/* CK_OBJECT_CLASS is a value that identifies the classes (or + * types) of objects that Cryptoki recognizes. It is defined + * as follows: */ +/* CK_OBJECT_CLASS was changed from CK_USHORT to CK_ULONG for + * v2.0 */ +typedef CK_ULONG CK_OBJECT_CLASS; + +/* The following classes of objects are defined: */ +/* CKO_HW_FEATURE is new for v2.10 */ +/* CKO_DOMAIN_PARAMETERS is new for v2.11 */ +/* CKO_MECHANISM is new for v2.20 */ +#define CKO_DATA 0x00000000 +#define CKO_CERTIFICATE 0x00000001 +#define CKO_PUBLIC_KEY 0x00000002 +#define CKO_PRIVATE_KEY 0x00000003 +#define CKO_SECRET_KEY 0x00000004 +#define CKO_HW_FEATURE 0x00000005 +#define CKO_DOMAIN_PARAMETERS 0x00000006 +#define CKO_MECHANISM 0x00000007 + +/* CKO_OTP_KEY is new for PKCS #11 v2.20 amendment 1 */ +#define CKO_OTP_KEY 0x00000008 + +#define CKO_VENDOR_DEFINED 0x80000000 + +typedef CK_OBJECT_CLASS CK_PTR CK_OBJECT_CLASS_PTR; + +/* CK_HW_FEATURE_TYPE is new for v2.10. CK_HW_FEATURE_TYPE is a + * value that identifies the hardware feature type of an object + * with CK_OBJECT_CLASS equal to CKO_HW_FEATURE. */ +typedef CK_ULONG CK_HW_FEATURE_TYPE; + +/* The following hardware feature types are defined */ +/* CKH_USER_INTERFACE is new for v2.20 */ +#define CKH_MONOTONIC_COUNTER 0x00000001 +#define CKH_CLOCK 0x00000002 +#define CKH_USER_INTERFACE 0x00000003 +#define CKH_VENDOR_DEFINED 0x80000000 + +/* CK_KEY_TYPE is a value that identifies a key type */ +/* CK_KEY_TYPE was changed from CK_USHORT to CK_ULONG for v2.0 */ +typedef CK_ULONG CK_KEY_TYPE; + +/* the following key types are defined: */ +#define CKK_RSA 0x00000000 +#define CKK_DSA 0x00000001 +#define CKK_DH 0x00000002 + +/* CKK_ECDSA and CKK_KEA are new for v2.0 */ +/* CKK_ECDSA is deprecated in v2.11, CKK_EC is preferred. */ +#define CKK_ECDSA 0x00000003 +#define CKK_EC 0x00000003 +#define CKK_X9_42_DH 0x00000004 +#define CKK_KEA 0x00000005 + +#define CKK_GENERIC_SECRET 0x00000010 +#define CKK_RC2 0x00000011 +#define CKK_RC4 0x00000012 +#define CKK_DES 0x00000013 +#define CKK_DES2 0x00000014 +#define CKK_DES3 0x00000015 + +/* all these key types are new for v2.0 */ +#define CKK_CAST 0x00000016 +#define CKK_CAST3 0x00000017 +/* CKK_CAST5 is deprecated in v2.11, CKK_CAST128 is preferred. */ +#define CKK_CAST5 0x00000018 +#define CKK_CAST128 0x00000018 +#define CKK_RC5 0x00000019 +#define CKK_IDEA 0x0000001A +#define CKK_SKIPJACK 0x0000001B +#define CKK_BATON 0x0000001C +#define CKK_JUNIPER 0x0000001D +#define CKK_CDMF 0x0000001E +#define CKK_AES 0x0000001F + +/* BlowFish and TwoFish are new for v2.20 */ +#define CKK_BLOWFISH 0x00000020 +#define CKK_TWOFISH 0x00000021 + +/* SecurID, HOTP, and ACTI are new for PKCS #11 v2.20 amendment 1 */ +#define CKK_SECURID 0x00000022 +#define CKK_HOTP 0x00000023 +#define CKK_ACTI 0x00000024 + +/* Camellia is new for PKCS #11 v2.20 amendment 3 */ +#define CKK_CAMELLIA 0x00000025 +/* ARIA is new for PKCS #11 v2.20 amendment 3 */ +#define CKK_ARIA 0x00000026 + + +#define CKK_VENDOR_DEFINED 0x80000000 + + +/* CK_CERTIFICATE_TYPE is a value that identifies a certificate + * type */ +/* CK_CERTIFICATE_TYPE was changed from CK_USHORT to CK_ULONG + * for v2.0 */ +typedef CK_ULONG CK_CERTIFICATE_TYPE; + +/* The following certificate types are defined: */ +/* CKC_X_509_ATTR_CERT is new for v2.10 */ +/* CKC_WTLS is new for v2.20 */ +#define CKC_X_509 0x00000000 +#define CKC_X_509_ATTR_CERT 0x00000001 +#define CKC_WTLS 0x00000002 +#define CKC_VENDOR_DEFINED 0x80000000 + + +/* CK_ATTRIBUTE_TYPE is a value that identifies an attribute + * type */ +/* CK_ATTRIBUTE_TYPE was changed from CK_USHORT to CK_ULONG for + * v2.0 */ +typedef CK_ULONG CK_ATTRIBUTE_TYPE; + +/* The CKF_ARRAY_ATTRIBUTE flag identifies an attribute which + consists of an array of values. */ +#define CKF_ARRAY_ATTRIBUTE 0x40000000 + +/* The following OTP-related defines are new for PKCS #11 v2.20 amendment 1 + and relates to the CKA_OTP_FORMAT attribute */ +#define CK_OTP_FORMAT_DECIMAL 0 +#define CK_OTP_FORMAT_HEXADECIMAL 1 +#define CK_OTP_FORMAT_ALPHANUMERIC 2 +#define CK_OTP_FORMAT_BINARY 3 + +/* The following OTP-related defines are new for PKCS #11 v2.20 amendment 1 + and relates to the CKA_OTP_..._REQUIREMENT attributes */ +#define CK_OTP_PARAM_IGNORED 0 +#define CK_OTP_PARAM_OPTIONAL 1 +#define CK_OTP_PARAM_MANDATORY 2 + +/* The following attribute types are defined: */ +#define CKA_CLASS 0x00000000 +#define CKA_TOKEN 0x00000001 +#define CKA_PRIVATE 0x00000002 +#define CKA_LABEL 0x00000003 +#define CKA_APPLICATION 0x00000010 +#define CKA_VALUE 0x00000011 + +/* CKA_OBJECT_ID is new for v2.10 */ +#define CKA_OBJECT_ID 0x00000012 + +#define CKA_CERTIFICATE_TYPE 0x00000080 +#define CKA_ISSUER 0x00000081 +#define CKA_SERIAL_NUMBER 0x00000082 + +/* CKA_AC_ISSUER, CKA_OWNER, and CKA_ATTR_TYPES are new + * for v2.10 */ +#define CKA_AC_ISSUER 0x00000083 +#define CKA_OWNER 0x00000084 +#define CKA_ATTR_TYPES 0x00000085 + +/* CKA_TRUSTED is new for v2.11 */ +#define CKA_TRUSTED 0x00000086 + +/* CKA_CERTIFICATE_CATEGORY ... + * CKA_CHECK_VALUE are new for v2.20 */ +#define CKA_CERTIFICATE_CATEGORY 0x00000087 +#define CKA_JAVA_MIDP_SECURITY_DOMAIN 0x00000088 +#define CKA_URL 0x00000089 +#define CKA_HASH_OF_SUBJECT_PUBLIC_KEY 0x0000008A +#define CKA_HASH_OF_ISSUER_PUBLIC_KEY 0x0000008B +#define CKA_CHECK_VALUE 0x00000090 + +#define CKA_KEY_TYPE 0x00000100 +#define CKA_SUBJECT 0x00000101 +#define CKA_ID 0x00000102 +#define CKA_SENSITIVE 0x00000103 +#define CKA_ENCRYPT 0x00000104 +#define CKA_DECRYPT 0x00000105 +#define CKA_WRAP 0x00000106 +#define CKA_UNWRAP 0x00000107 +#define CKA_SIGN 0x00000108 +#define CKA_SIGN_RECOVER 0x00000109 +#define CKA_VERIFY 0x0000010A +#define CKA_VERIFY_RECOVER 0x0000010B +#define CKA_DERIVE 0x0000010C +#define CKA_START_DATE 0x00000110 +#define CKA_END_DATE 0x00000111 +#define CKA_MODULUS 0x00000120 +#define CKA_MODULUS_BITS 0x00000121 +#define CKA_PUBLIC_EXPONENT 0x00000122 +#define CKA_PRIVATE_EXPONENT 0x00000123 +#define CKA_PRIME_1 0x00000124 +#define CKA_PRIME_2 0x00000125 +#define CKA_EXPONENT_1 0x00000126 +#define CKA_EXPONENT_2 0x00000127 +#define CKA_COEFFICIENT 0x00000128 +#define CKA_PRIME 0x00000130 +#define CKA_SUBPRIME 0x00000131 +#define CKA_BASE 0x00000132 + +/* CKA_PRIME_BITS and CKA_SUB_PRIME_BITS are new for v2.11 */ +#define CKA_PRIME_BITS 0x00000133 +#define CKA_SUBPRIME_BITS 0x00000134 +#define CKA_SUB_PRIME_BITS CKA_SUBPRIME_BITS +/* (To retain backwards-compatibility) */ + +#define CKA_VALUE_BITS 0x00000160 +#define CKA_VALUE_LEN 0x00000161 + +/* CKA_EXTRACTABLE, CKA_LOCAL, CKA_NEVER_EXTRACTABLE, + * CKA_ALWAYS_SENSITIVE, CKA_MODIFIABLE, CKA_ECDSA_PARAMS, + * and CKA_EC_POINT are new for v2.0 */ +#define CKA_EXTRACTABLE 0x00000162 +#define CKA_LOCAL 0x00000163 +#define CKA_NEVER_EXTRACTABLE 0x00000164 +#define CKA_ALWAYS_SENSITIVE 0x00000165 + +/* CKA_KEY_GEN_MECHANISM is new for v2.11 */ +#define CKA_KEY_GEN_MECHANISM 0x00000166 + +#define CKA_MODIFIABLE 0x00000170 + +/* CKA_ECDSA_PARAMS is deprecated in v2.11, + * CKA_EC_PARAMS is preferred. */ +#define CKA_ECDSA_PARAMS 0x00000180 +#define CKA_EC_PARAMS 0x00000180 + +#define CKA_EC_POINT 0x00000181 + +/* CKA_SECONDARY_AUTH, CKA_AUTH_PIN_FLAGS, + * are new for v2.10. Deprecated in v2.11 and onwards. */ +#define CKA_SECONDARY_AUTH 0x00000200 +#define CKA_AUTH_PIN_FLAGS 0x00000201 + +/* CKA_ALWAYS_AUTHENTICATE ... + * CKA_UNWRAP_TEMPLATE are new for v2.20 */ +#define CKA_ALWAYS_AUTHENTICATE 0x00000202 + +#define CKA_WRAP_WITH_TRUSTED 0x00000210 +#define CKA_WRAP_TEMPLATE (CKF_ARRAY_ATTRIBUTE|0x00000211) +#define CKA_UNWRAP_TEMPLATE (CKF_ARRAY_ATTRIBUTE|0x00000212) + +/* CKA_OTP... atttributes are new for PKCS #11 v2.20 amendment 3. */ +#define CKA_OTP_FORMAT 0x00000220 +#define CKA_OTP_LENGTH 0x00000221 +#define CKA_OTP_TIME_INTERVAL 0x00000222 +#define CKA_OTP_USER_FRIENDLY_MODE 0x00000223 +#define CKA_OTP_CHALLENGE_REQUIREMENT 0x00000224 +#define CKA_OTP_TIME_REQUIREMENT 0x00000225 +#define CKA_OTP_COUNTER_REQUIREMENT 0x00000226 +#define CKA_OTP_PIN_REQUIREMENT 0x00000227 +#define CKA_OTP_COUNTER 0x0000022E +#define CKA_OTP_TIME 0x0000022F +#define CKA_OTP_USER_IDENTIFIER 0x0000022A +#define CKA_OTP_SERVICE_IDENTIFIER 0x0000022B +#define CKA_OTP_SERVICE_LOGO 0x0000022C +#define CKA_OTP_SERVICE_LOGO_TYPE 0x0000022D + + +/* CKA_HW_FEATURE_TYPE, CKA_RESET_ON_INIT, and CKA_HAS_RESET + * are new for v2.10 */ +#define CKA_HW_FEATURE_TYPE 0x00000300 +#define CKA_RESET_ON_INIT 0x00000301 +#define CKA_HAS_RESET 0x00000302 + +/* The following attributes are new for v2.20 */ +#define CKA_PIXEL_X 0x00000400 +#define CKA_PIXEL_Y 0x00000401 +#define CKA_RESOLUTION 0x00000402 +#define CKA_CHAR_ROWS 0x00000403 +#define CKA_CHAR_COLUMNS 0x00000404 +#define CKA_COLOR 0x00000405 +#define CKA_BITS_PER_PIXEL 0x00000406 +#define CKA_CHAR_SETS 0x00000480 +#define CKA_ENCODING_METHODS 0x00000481 +#define CKA_MIME_TYPES 0x00000482 +#define CKA_MECHANISM_TYPE 0x00000500 +#define CKA_REQUIRED_CMS_ATTRIBUTES 0x00000501 +#define CKA_DEFAULT_CMS_ATTRIBUTES 0x00000502 +#define CKA_SUPPORTED_CMS_ATTRIBUTES 0x00000503 +#define CKA_ALLOWED_MECHANISMS (CKF_ARRAY_ATTRIBUTE|0x00000600) + +#define CKA_VENDOR_DEFINED 0x80000000 + +/* CK_ATTRIBUTE is a structure that includes the type, length + * and value of an attribute */ +typedef struct CK_ATTRIBUTE { + CK_ATTRIBUTE_TYPE type; + CK_VOID_PTR pValue; + + /* ulValueLen went from CK_USHORT to CK_ULONG for v2.0 */ + CK_ULONG ulValueLen; /* in bytes */ +} CK_ATTRIBUTE; + +typedef CK_ATTRIBUTE CK_PTR CK_ATTRIBUTE_PTR; + + +/* CK_DATE is a structure that defines a date */ +typedef struct CK_DATE{ + CK_CHAR year[4]; /* the year ("1900" - "9999") */ + CK_CHAR month[2]; /* the month ("01" - "12") */ + CK_CHAR day[2]; /* the day ("01" - "31") */ +} CK_DATE; + + +/* CK_MECHANISM_TYPE is a value that identifies a mechanism + * type */ +/* CK_MECHANISM_TYPE was changed from CK_USHORT to CK_ULONG for + * v2.0 */ +typedef CK_ULONG CK_MECHANISM_TYPE; + +/* the following mechanism types are defined: */ +#define CKM_RSA_PKCS_KEY_PAIR_GEN 0x00000000 +#define CKM_RSA_PKCS 0x00000001 +#define CKM_RSA_9796 0x00000002 +#define CKM_RSA_X_509 0x00000003 + +/* CKM_MD2_RSA_PKCS, CKM_MD5_RSA_PKCS, and CKM_SHA1_RSA_PKCS + * are new for v2.0. They are mechanisms which hash and sign */ +#define CKM_MD2_RSA_PKCS 0x00000004 +#define CKM_MD5_RSA_PKCS 0x00000005 +#define CKM_SHA1_RSA_PKCS 0x00000006 + +/* CKM_RIPEMD128_RSA_PKCS, CKM_RIPEMD160_RSA_PKCS, and + * CKM_RSA_PKCS_OAEP are new for v2.10 */ +#define CKM_RIPEMD128_RSA_PKCS 0x00000007 +#define CKM_RIPEMD160_RSA_PKCS 0x00000008 +#define CKM_RSA_PKCS_OAEP 0x00000009 + +/* CKM_RSA_X9_31_KEY_PAIR_GEN, CKM_RSA_X9_31, CKM_SHA1_RSA_X9_31, + * CKM_RSA_PKCS_PSS, and CKM_SHA1_RSA_PKCS_PSS are new for v2.11 */ +#define CKM_RSA_X9_31_KEY_PAIR_GEN 0x0000000A +#define CKM_RSA_X9_31 0x0000000B +#define CKM_SHA1_RSA_X9_31 0x0000000C +#define CKM_RSA_PKCS_PSS 0x0000000D +#define CKM_SHA1_RSA_PKCS_PSS 0x0000000E + +#define CKM_DSA_KEY_PAIR_GEN 0x00000010 +#define CKM_DSA 0x00000011 +#define CKM_DSA_SHA1 0x00000012 +#define CKM_DH_PKCS_KEY_PAIR_GEN 0x00000020 +#define CKM_DH_PKCS_DERIVE 0x00000021 + +/* CKM_X9_42_DH_KEY_PAIR_GEN, CKM_X9_42_DH_DERIVE, + * CKM_X9_42_DH_HYBRID_DERIVE, and CKM_X9_42_MQV_DERIVE are new for + * v2.11 */ +#define CKM_X9_42_DH_KEY_PAIR_GEN 0x00000030 +#define CKM_X9_42_DH_DERIVE 0x00000031 +#define CKM_X9_42_DH_HYBRID_DERIVE 0x00000032 +#define CKM_X9_42_MQV_DERIVE 0x00000033 + +/* CKM_SHA256/384/512 are new for v2.20 */ +#define CKM_SHA256_RSA_PKCS 0x00000040 +#define CKM_SHA384_RSA_PKCS 0x00000041 +#define CKM_SHA512_RSA_PKCS 0x00000042 +#define CKM_SHA256_RSA_PKCS_PSS 0x00000043 +#define CKM_SHA384_RSA_PKCS_PSS 0x00000044 +#define CKM_SHA512_RSA_PKCS_PSS 0x00000045 + +/* SHA-224 RSA mechanisms are new for PKCS #11 v2.20 amendment 3 */ +#define CKM_SHA224_RSA_PKCS 0x00000046 +#define CKM_SHA224_RSA_PKCS_PSS 0x00000047 + +#define CKM_RC2_KEY_GEN 0x00000100 +#define CKM_RC2_ECB 0x00000101 +#define CKM_RC2_CBC 0x00000102 +#define CKM_RC2_MAC 0x00000103 + +/* CKM_RC2_MAC_GENERAL and CKM_RC2_CBC_PAD are new for v2.0 */ +#define CKM_RC2_MAC_GENERAL 0x00000104 +#define CKM_RC2_CBC_PAD 0x00000105 + +#define CKM_RC4_KEY_GEN 0x00000110 +#define CKM_RC4 0x00000111 +#define CKM_DES_KEY_GEN 0x00000120 +#define CKM_DES_ECB 0x00000121 +#define CKM_DES_CBC 0x00000122 +#define CKM_DES_MAC 0x00000123 + +/* CKM_DES_MAC_GENERAL and CKM_DES_CBC_PAD are new for v2.0 */ +#define CKM_DES_MAC_GENERAL 0x00000124 +#define CKM_DES_CBC_PAD 0x00000125 + +#define CKM_DES2_KEY_GEN 0x00000130 +#define CKM_DES3_KEY_GEN 0x00000131 +#define CKM_DES3_ECB 0x00000132 +#define CKM_DES3_CBC 0x00000133 +#define CKM_DES3_MAC 0x00000134 + +/* CKM_DES3_MAC_GENERAL, CKM_DES3_CBC_PAD, CKM_CDMF_KEY_GEN, + * CKM_CDMF_ECB, CKM_CDMF_CBC, CKM_CDMF_MAC, + * CKM_CDMF_MAC_GENERAL, and CKM_CDMF_CBC_PAD are new for v2.0 */ +#define CKM_DES3_MAC_GENERAL 0x00000135 +#define CKM_DES3_CBC_PAD 0x00000136 +#define CKM_CDMF_KEY_GEN 0x00000140 +#define CKM_CDMF_ECB 0x00000141 +#define CKM_CDMF_CBC 0x00000142 +#define CKM_CDMF_MAC 0x00000143 +#define CKM_CDMF_MAC_GENERAL 0x00000144 +#define CKM_CDMF_CBC_PAD 0x00000145 + +/* the following four DES mechanisms are new for v2.20 */ +#define CKM_DES_OFB64 0x00000150 +#define CKM_DES_OFB8 0x00000151 +#define CKM_DES_CFB64 0x00000152 +#define CKM_DES_CFB8 0x00000153 + +#define CKM_MD2 0x00000200 + +/* CKM_MD2_HMAC and CKM_MD2_HMAC_GENERAL are new for v2.0 */ +#define CKM_MD2_HMAC 0x00000201 +#define CKM_MD2_HMAC_GENERAL 0x00000202 + +#define CKM_MD5 0x00000210 + +/* CKM_MD5_HMAC and CKM_MD5_HMAC_GENERAL are new for v2.0 */ +#define CKM_MD5_HMAC 0x00000211 +#define CKM_MD5_HMAC_GENERAL 0x00000212 + +#define CKM_SHA_1 0x00000220 + +/* CKM_SHA_1_HMAC and CKM_SHA_1_HMAC_GENERAL are new for v2.0 */ +#define CKM_SHA_1_HMAC 0x00000221 +#define CKM_SHA_1_HMAC_GENERAL 0x00000222 + +/* CKM_RIPEMD128, CKM_RIPEMD128_HMAC, + * CKM_RIPEMD128_HMAC_GENERAL, CKM_RIPEMD160, CKM_RIPEMD160_HMAC, + * and CKM_RIPEMD160_HMAC_GENERAL are new for v2.10 */ +#define CKM_RIPEMD128 0x00000230 +#define CKM_RIPEMD128_HMAC 0x00000231 +#define CKM_RIPEMD128_HMAC_GENERAL 0x00000232 +#define CKM_RIPEMD160 0x00000240 +#define CKM_RIPEMD160_HMAC 0x00000241 +#define CKM_RIPEMD160_HMAC_GENERAL 0x00000242 + +/* CKM_SHA256/384/512 are new for v2.20 */ +#define CKM_SHA256 0x00000250 +#define CKM_SHA256_HMAC 0x00000251 +#define CKM_SHA256_HMAC_GENERAL 0x00000252 + +/* SHA-224 is new for PKCS #11 v2.20 amendment 3 */ +#define CKM_SHA224 0x00000255 +#define CKM_SHA224_HMAC 0x00000256 +#define CKM_SHA224_HMAC_GENERAL 0x00000257 + +#define CKM_SHA384 0x00000260 +#define CKM_SHA384_HMAC 0x00000261 +#define CKM_SHA384_HMAC_GENERAL 0x00000262 +#define CKM_SHA512 0x00000270 +#define CKM_SHA512_HMAC 0x00000271 +#define CKM_SHA512_HMAC_GENERAL 0x00000272 + +/* SecurID is new for PKCS #11 v2.20 amendment 1 */ +#define CKM_SECURID_KEY_GEN 0x00000280 +#define CKM_SECURID 0x00000282 + +/* HOTP is new for PKCS #11 v2.20 amendment 1 */ +#define CKM_HOTP_KEY_GEN 0x00000290 +#define CKM_HOTP 0x00000291 + +/* ACTI is new for PKCS #11 v2.20 amendment 1 */ +#define CKM_ACTI 0x000002A0 +#define CKM_ACTI_KEY_GEN 0x000002A1 + +/* All of the following mechanisms are new for v2.0 */ +/* Note that CAST128 and CAST5 are the same algorithm */ +#define CKM_CAST_KEY_GEN 0x00000300 +#define CKM_CAST_ECB 0x00000301 +#define CKM_CAST_CBC 0x00000302 +#define CKM_CAST_MAC 0x00000303 +#define CKM_CAST_MAC_GENERAL 0x00000304 +#define CKM_CAST_CBC_PAD 0x00000305 +#define CKM_CAST3_KEY_GEN 0x00000310 +#define CKM_CAST3_ECB 0x00000311 +#define CKM_CAST3_CBC 0x00000312 +#define CKM_CAST3_MAC 0x00000313 +#define CKM_CAST3_MAC_GENERAL 0x00000314 +#define CKM_CAST3_CBC_PAD 0x00000315 +#define CKM_CAST5_KEY_GEN 0x00000320 +#define CKM_CAST128_KEY_GEN 0x00000320 +#define CKM_CAST5_ECB 0x00000321 +#define CKM_CAST128_ECB 0x00000321 +#define CKM_CAST5_CBC 0x00000322 +#define CKM_CAST128_CBC 0x00000322 +#define CKM_CAST5_MAC 0x00000323 +#define CKM_CAST128_MAC 0x00000323 +#define CKM_CAST5_MAC_GENERAL 0x00000324 +#define CKM_CAST128_MAC_GENERAL 0x00000324 +#define CKM_CAST5_CBC_PAD 0x00000325 +#define CKM_CAST128_CBC_PAD 0x00000325 +#define CKM_RC5_KEY_GEN 0x00000330 +#define CKM_RC5_ECB 0x00000331 +#define CKM_RC5_CBC 0x00000332 +#define CKM_RC5_MAC 0x00000333 +#define CKM_RC5_MAC_GENERAL 0x00000334 +#define CKM_RC5_CBC_PAD 0x00000335 +#define CKM_IDEA_KEY_GEN 0x00000340 +#define CKM_IDEA_ECB 0x00000341 +#define CKM_IDEA_CBC 0x00000342 +#define CKM_IDEA_MAC 0x00000343 +#define CKM_IDEA_MAC_GENERAL 0x00000344 +#define CKM_IDEA_CBC_PAD 0x00000345 +#define CKM_GENERIC_SECRET_KEY_GEN 0x00000350 +#define CKM_CONCATENATE_BASE_AND_KEY 0x00000360 +#define CKM_CONCATENATE_BASE_AND_DATA 0x00000362 +#define CKM_CONCATENATE_DATA_AND_BASE 0x00000363 +#define CKM_XOR_BASE_AND_DATA 0x00000364 +#define CKM_EXTRACT_KEY_FROM_KEY 0x00000365 +#define CKM_SSL3_PRE_MASTER_KEY_GEN 0x00000370 +#define CKM_SSL3_MASTER_KEY_DERIVE 0x00000371 +#define CKM_SSL3_KEY_AND_MAC_DERIVE 0x00000372 + +/* CKM_SSL3_MASTER_KEY_DERIVE_DH, CKM_TLS_PRE_MASTER_KEY_GEN, + * CKM_TLS_MASTER_KEY_DERIVE, CKM_TLS_KEY_AND_MAC_DERIVE, and + * CKM_TLS_MASTER_KEY_DERIVE_DH are new for v2.11 */ +#define CKM_SSL3_MASTER_KEY_DERIVE_DH 0x00000373 +#define CKM_TLS_PRE_MASTER_KEY_GEN 0x00000374 +#define CKM_TLS_MASTER_KEY_DERIVE 0x00000375 +#define CKM_TLS_KEY_AND_MAC_DERIVE 0x00000376 +#define CKM_TLS_MASTER_KEY_DERIVE_DH 0x00000377 + +/* CKM_TLS_PRF is new for v2.20 */ +#define CKM_TLS_PRF 0x00000378 + +#define CKM_SSL3_MD5_MAC 0x00000380 +#define CKM_SSL3_SHA1_MAC 0x00000381 +#define CKM_MD5_KEY_DERIVATION 0x00000390 +#define CKM_MD2_KEY_DERIVATION 0x00000391 +#define CKM_SHA1_KEY_DERIVATION 0x00000392 + +/* CKM_SHA256/384/512 are new for v2.20 */ +#define CKM_SHA256_KEY_DERIVATION 0x00000393 +#define CKM_SHA384_KEY_DERIVATION 0x00000394 +#define CKM_SHA512_KEY_DERIVATION 0x00000395 + +/* SHA-224 key derivation is new for PKCS #11 v2.20 amendment 3 */ +#define CKM_SHA224_KEY_DERIVATION 0x00000396 + +#define CKM_PBE_MD2_DES_CBC 0x000003A0 +#define CKM_PBE_MD5_DES_CBC 0x000003A1 +#define CKM_PBE_MD5_CAST_CBC 0x000003A2 +#define CKM_PBE_MD5_CAST3_CBC 0x000003A3 +#define CKM_PBE_MD5_CAST5_CBC 0x000003A4 +#define CKM_PBE_MD5_CAST128_CBC 0x000003A4 +#define CKM_PBE_SHA1_CAST5_CBC 0x000003A5 +#define CKM_PBE_SHA1_CAST128_CBC 0x000003A5 +#define CKM_PBE_SHA1_RC4_128 0x000003A6 +#define CKM_PBE_SHA1_RC4_40 0x000003A7 +#define CKM_PBE_SHA1_DES3_EDE_CBC 0x000003A8 +#define CKM_PBE_SHA1_DES2_EDE_CBC 0x000003A9 +#define CKM_PBE_SHA1_RC2_128_CBC 0x000003AA +#define CKM_PBE_SHA1_RC2_40_CBC 0x000003AB + +/* CKM_PKCS5_PBKD2 is new for v2.10 */ +#define CKM_PKCS5_PBKD2 0x000003B0 + +#define CKM_PBA_SHA1_WITH_SHA1_HMAC 0x000003C0 + +/* WTLS mechanisms are new for v2.20 */ +#define CKM_WTLS_PRE_MASTER_KEY_GEN 0x000003D0 +#define CKM_WTLS_MASTER_KEY_DERIVE 0x000003D1 +#define CKM_WTLS_MASTER_KEY_DERIVE_DH_ECC 0x000003D2 +#define CKM_WTLS_PRF 0x000003D3 +#define CKM_WTLS_SERVER_KEY_AND_MAC_DERIVE 0x000003D4 +#define CKM_WTLS_CLIENT_KEY_AND_MAC_DERIVE 0x000003D5 + +#define CKM_KEY_WRAP_LYNKS 0x00000400 +#define CKM_KEY_WRAP_SET_OAEP 0x00000401 + +/* CKM_CMS_SIG is new for v2.20 */ +#define CKM_CMS_SIG 0x00000500 + +/* CKM_KIP mechanisms are new for PKCS #11 v2.20 amendment 2 */ +#define CKM_KIP_DERIVE 0x00000510 +#define CKM_KIP_WRAP 0x00000511 +#define CKM_KIP_MAC 0x00000512 + +/* Camellia is new for PKCS #11 v2.20 amendment 3 */ +#define CKM_CAMELLIA_KEY_GEN 0x00000550 +#define CKM_CAMELLIA_ECB 0x00000551 +#define CKM_CAMELLIA_CBC 0x00000552 +#define CKM_CAMELLIA_MAC 0x00000553 +#define CKM_CAMELLIA_MAC_GENERAL 0x00000554 +#define CKM_CAMELLIA_CBC_PAD 0x00000555 +#define CKM_CAMELLIA_ECB_ENCRYPT_DATA 0x00000556 +#define CKM_CAMELLIA_CBC_ENCRYPT_DATA 0x00000557 +#define CKM_CAMELLIA_CTR 0x00000558 + +/* ARIA is new for PKCS #11 v2.20 amendment 3 */ +#define CKM_ARIA_KEY_GEN 0x00000560 +#define CKM_ARIA_ECB 0x00000561 +#define CKM_ARIA_CBC 0x00000562 +#define CKM_ARIA_MAC 0x00000563 +#define CKM_ARIA_MAC_GENERAL 0x00000564 +#define CKM_ARIA_CBC_PAD 0x00000565 +#define CKM_ARIA_ECB_ENCRYPT_DATA 0x00000566 +#define CKM_ARIA_CBC_ENCRYPT_DATA 0x00000567 + +/* Fortezza mechanisms */ +#define CKM_SKIPJACK_KEY_GEN 0x00001000 +#define CKM_SKIPJACK_ECB64 0x00001001 +#define CKM_SKIPJACK_CBC64 0x00001002 +#define CKM_SKIPJACK_OFB64 0x00001003 +#define CKM_SKIPJACK_CFB64 0x00001004 +#define CKM_SKIPJACK_CFB32 0x00001005 +#define CKM_SKIPJACK_CFB16 0x00001006 +#define CKM_SKIPJACK_CFB8 0x00001007 +#define CKM_SKIPJACK_WRAP 0x00001008 +#define CKM_SKIPJACK_PRIVATE_WRAP 0x00001009 +#define CKM_SKIPJACK_RELAYX 0x0000100a +#define CKM_KEA_KEY_PAIR_GEN 0x00001010 +#define CKM_KEA_KEY_DERIVE 0x00001011 +#define CKM_FORTEZZA_TIMESTAMP 0x00001020 +#define CKM_BATON_KEY_GEN 0x00001030 +#define CKM_BATON_ECB128 0x00001031 +#define CKM_BATON_ECB96 0x00001032 +#define CKM_BATON_CBC128 0x00001033 +#define CKM_BATON_COUNTER 0x00001034 +#define CKM_BATON_SHUFFLE 0x00001035 +#define CKM_BATON_WRAP 0x00001036 + +/* CKM_ECDSA_KEY_PAIR_GEN is deprecated in v2.11, + * CKM_EC_KEY_PAIR_GEN is preferred */ +#define CKM_ECDSA_KEY_PAIR_GEN 0x00001040 +#define CKM_EC_KEY_PAIR_GEN 0x00001040 + +#define CKM_ECDSA 0x00001041 +#define CKM_ECDSA_SHA1 0x00001042 + +/* CKM_ECDH1_DERIVE, CKM_ECDH1_COFACTOR_DERIVE, and CKM_ECMQV_DERIVE + * are new for v2.11 */ +#define CKM_ECDH1_DERIVE 0x00001050 +#define CKM_ECDH1_COFACTOR_DERIVE 0x00001051 +#define CKM_ECMQV_DERIVE 0x00001052 + +#define CKM_JUNIPER_KEY_GEN 0x00001060 +#define CKM_JUNIPER_ECB128 0x00001061 +#define CKM_JUNIPER_CBC128 0x00001062 +#define CKM_JUNIPER_COUNTER 0x00001063 +#define CKM_JUNIPER_SHUFFLE 0x00001064 +#define CKM_JUNIPER_WRAP 0x00001065 +#define CKM_FASTHASH 0x00001070 + +/* CKM_AES_KEY_GEN, CKM_AES_ECB, CKM_AES_CBC, CKM_AES_MAC, + * CKM_AES_MAC_GENERAL, CKM_AES_CBC_PAD, CKM_DSA_PARAMETER_GEN, + * CKM_DH_PKCS_PARAMETER_GEN, and CKM_X9_42_DH_PARAMETER_GEN are + * new for v2.11 */ +#define CKM_AES_KEY_GEN 0x00001080 +#define CKM_AES_ECB 0x00001081 +#define CKM_AES_CBC 0x00001082 +#define CKM_AES_MAC 0x00001083 +#define CKM_AES_MAC_GENERAL 0x00001084 +#define CKM_AES_CBC_PAD 0x00001085 + +/* AES counter mode is new for PKCS #11 v2.20 amendment 3 */ +#define CKM_AES_CTR 0x00001086 + +/* BlowFish and TwoFish are new for v2.20 */ +#define CKM_BLOWFISH_KEY_GEN 0x00001090 +#define CKM_BLOWFISH_CBC 0x00001091 +#define CKM_TWOFISH_KEY_GEN 0x00001092 +#define CKM_TWOFISH_CBC 0x00001093 + + +/* CKM_xxx_ENCRYPT_DATA mechanisms are new for v2.20 */ +#define CKM_DES_ECB_ENCRYPT_DATA 0x00001100 +#define CKM_DES_CBC_ENCRYPT_DATA 0x00001101 +#define CKM_DES3_ECB_ENCRYPT_DATA 0x00001102 +#define CKM_DES3_CBC_ENCRYPT_DATA 0x00001103 +#define CKM_AES_ECB_ENCRYPT_DATA 0x00001104 +#define CKM_AES_CBC_ENCRYPT_DATA 0x00001105 + +#define CKM_DSA_PARAMETER_GEN 0x00002000 +#define CKM_DH_PKCS_PARAMETER_GEN 0x00002001 +#define CKM_X9_42_DH_PARAMETER_GEN 0x00002002 + +#define CKM_VENDOR_DEFINED 0x80000000 + +typedef CK_MECHANISM_TYPE CK_PTR CK_MECHANISM_TYPE_PTR; + + +/* CK_MECHANISM is a structure that specifies a particular + * mechanism */ +typedef struct CK_MECHANISM { + CK_MECHANISM_TYPE mechanism; + CK_VOID_PTR pParameter; + + /* ulParameterLen was changed from CK_USHORT to CK_ULONG for + * v2.0 */ + CK_ULONG ulParameterLen; /* in bytes */ +} CK_MECHANISM; + +typedef CK_MECHANISM CK_PTR CK_MECHANISM_PTR; + + +/* CK_MECHANISM_INFO provides information about a particular + * mechanism */ +typedef struct CK_MECHANISM_INFO { + CK_ULONG ulMinKeySize; + CK_ULONG ulMaxKeySize; + CK_FLAGS flags; +} CK_MECHANISM_INFO; + +/* The flags are defined as follows: + * Bit Flag Mask Meaning */ +#define CKF_HW 0x00000001 /* performed by HW */ + +/* The flags CKF_ENCRYPT, CKF_DECRYPT, CKF_DIGEST, CKF_SIGN, + * CKG_SIGN_RECOVER, CKF_VERIFY, CKF_VERIFY_RECOVER, + * CKF_GENERATE, CKF_GENERATE_KEY_PAIR, CKF_WRAP, CKF_UNWRAP, + * and CKF_DERIVE are new for v2.0. They specify whether or not + * a mechanism can be used for a particular task */ +#define CKF_ENCRYPT 0x00000100 +#define CKF_DECRYPT 0x00000200 +#define CKF_DIGEST 0x00000400 +#define CKF_SIGN 0x00000800 +#define CKF_SIGN_RECOVER 0x00001000 +#define CKF_VERIFY 0x00002000 +#define CKF_VERIFY_RECOVER 0x00004000 +#define CKF_GENERATE 0x00008000 +#define CKF_GENERATE_KEY_PAIR 0x00010000 +#define CKF_WRAP 0x00020000 +#define CKF_UNWRAP 0x00040000 +#define CKF_DERIVE 0x00080000 + +/* CKF_EC_F_P, CKF_EC_F_2M, CKF_EC_ECPARAMETERS, CKF_EC_NAMEDCURVE, + * CKF_EC_UNCOMPRESS, and CKF_EC_COMPRESS are new for v2.11. They + * describe a token's EC capabilities not available in mechanism + * information. */ +#define CKF_EC_F_P 0x00100000 +#define CKF_EC_F_2M 0x00200000 +#define CKF_EC_ECPARAMETERS 0x00400000 +#define CKF_EC_NAMEDCURVE 0x00800000 +#define CKF_EC_UNCOMPRESS 0x01000000 +#define CKF_EC_COMPRESS 0x02000000 + +#define CKF_EXTENSION 0x80000000 /* FALSE for this version */ + +typedef CK_MECHANISM_INFO CK_PTR CK_MECHANISM_INFO_PTR; + + +/* CK_RV is a value that identifies the return value of a + * Cryptoki function */ +/* CK_RV was changed from CK_USHORT to CK_ULONG for v2.0 */ +typedef CK_ULONG CK_RV; + +#define CKR_OK 0x00000000 +#define CKR_CANCEL 0x00000001 +#define CKR_HOST_MEMORY 0x00000002 +#define CKR_SLOT_ID_INVALID 0x00000003 + +/* CKR_FLAGS_INVALID was removed for v2.0 */ + +/* CKR_GENERAL_ERROR and CKR_FUNCTION_FAILED are new for v2.0 */ +#define CKR_GENERAL_ERROR 0x00000005 +#define CKR_FUNCTION_FAILED 0x00000006 + +/* CKR_ARGUMENTS_BAD, CKR_NO_EVENT, CKR_NEED_TO_CREATE_THREADS, + * and CKR_CANT_LOCK are new for v2.01 */ +#define CKR_ARGUMENTS_BAD 0x00000007 +#define CKR_NO_EVENT 0x00000008 +#define CKR_NEED_TO_CREATE_THREADS 0x00000009 +#define CKR_CANT_LOCK 0x0000000A + +#define CKR_ATTRIBUTE_READ_ONLY 0x00000010 +#define CKR_ATTRIBUTE_SENSITIVE 0x00000011 +#define CKR_ATTRIBUTE_TYPE_INVALID 0x00000012 +#define CKR_ATTRIBUTE_VALUE_INVALID 0x00000013 +#define CKR_DATA_INVALID 0x00000020 +#define CKR_DATA_LEN_RANGE 0x00000021 +#define CKR_DEVICE_ERROR 0x00000030 +#define CKR_DEVICE_MEMORY 0x00000031 +#define CKR_DEVICE_REMOVED 0x00000032 +#define CKR_ENCRYPTED_DATA_INVALID 0x00000040 +#define CKR_ENCRYPTED_DATA_LEN_RANGE 0x00000041 +#define CKR_FUNCTION_CANCELED 0x00000050 +#define CKR_FUNCTION_NOT_PARALLEL 0x00000051 + +/* CKR_FUNCTION_NOT_SUPPORTED is new for v2.0 */ +#define CKR_FUNCTION_NOT_SUPPORTED 0x00000054 + +#define CKR_KEY_HANDLE_INVALID 0x00000060 + +/* CKR_KEY_SENSITIVE was removed for v2.0 */ + +#define CKR_KEY_SIZE_RANGE 0x00000062 +#define CKR_KEY_TYPE_INCONSISTENT 0x00000063 + +/* CKR_KEY_NOT_NEEDED, CKR_KEY_CHANGED, CKR_KEY_NEEDED, + * CKR_KEY_INDIGESTIBLE, CKR_KEY_FUNCTION_NOT_PERMITTED, + * CKR_KEY_NOT_WRAPPABLE, and CKR_KEY_UNEXTRACTABLE are new for + * v2.0 */ +#define CKR_KEY_NOT_NEEDED 0x00000064 +#define CKR_KEY_CHANGED 0x00000065 +#define CKR_KEY_NEEDED 0x00000066 +#define CKR_KEY_INDIGESTIBLE 0x00000067 +#define CKR_KEY_FUNCTION_NOT_PERMITTED 0x00000068 +#define CKR_KEY_NOT_WRAPPABLE 0x00000069 +#define CKR_KEY_UNEXTRACTABLE 0x0000006A + +#define CKR_MECHANISM_INVALID 0x00000070 +#define CKR_MECHANISM_PARAM_INVALID 0x00000071 + +/* CKR_OBJECT_CLASS_INCONSISTENT and CKR_OBJECT_CLASS_INVALID + * were removed for v2.0 */ +#define CKR_OBJECT_HANDLE_INVALID 0x00000082 +#define CKR_OPERATION_ACTIVE 0x00000090 +#define CKR_OPERATION_NOT_INITIALIZED 0x00000091 +#define CKR_PIN_INCORRECT 0x000000A0 +#define CKR_PIN_INVALID 0x000000A1 +#define CKR_PIN_LEN_RANGE 0x000000A2 + +/* CKR_PIN_EXPIRED and CKR_PIN_LOCKED are new for v2.0 */ +#define CKR_PIN_EXPIRED 0x000000A3 +#define CKR_PIN_LOCKED 0x000000A4 + +#define CKR_SESSION_CLOSED 0x000000B0 +#define CKR_SESSION_COUNT 0x000000B1 +#define CKR_SESSION_HANDLE_INVALID 0x000000B3 +#define CKR_SESSION_PARALLEL_NOT_SUPPORTED 0x000000B4 +#define CKR_SESSION_READ_ONLY 0x000000B5 +#define CKR_SESSION_EXISTS 0x000000B6 + +/* CKR_SESSION_READ_ONLY_EXISTS and + * CKR_SESSION_READ_WRITE_SO_EXISTS are new for v2.0 */ +#define CKR_SESSION_READ_ONLY_EXISTS 0x000000B7 +#define CKR_SESSION_READ_WRITE_SO_EXISTS 0x000000B8 + +#define CKR_SIGNATURE_INVALID 0x000000C0 +#define CKR_SIGNATURE_LEN_RANGE 0x000000C1 +#define CKR_TEMPLATE_INCOMPLETE 0x000000D0 +#define CKR_TEMPLATE_INCONSISTENT 0x000000D1 +#define CKR_TOKEN_NOT_PRESENT 0x000000E0 +#define CKR_TOKEN_NOT_RECOGNIZED 0x000000E1 +#define CKR_TOKEN_WRITE_PROTECTED 0x000000E2 +#define CKR_UNWRAPPING_KEY_HANDLE_INVALID 0x000000F0 +#define CKR_UNWRAPPING_KEY_SIZE_RANGE 0x000000F1 +#define CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT 0x000000F2 +#define CKR_USER_ALREADY_LOGGED_IN 0x00000100 +#define CKR_USER_NOT_LOGGED_IN 0x00000101 +#define CKR_USER_PIN_NOT_INITIALIZED 0x00000102 +#define CKR_USER_TYPE_INVALID 0x00000103 + +/* CKR_USER_ANOTHER_ALREADY_LOGGED_IN and CKR_USER_TOO_MANY_TYPES + * are new to v2.01 */ +#define CKR_USER_ANOTHER_ALREADY_LOGGED_IN 0x00000104 +#define CKR_USER_TOO_MANY_TYPES 0x00000105 + +#define CKR_WRAPPED_KEY_INVALID 0x00000110 +#define CKR_WRAPPED_KEY_LEN_RANGE 0x00000112 +#define CKR_WRAPPING_KEY_HANDLE_INVALID 0x00000113 +#define CKR_WRAPPING_KEY_SIZE_RANGE 0x00000114 +#define CKR_WRAPPING_KEY_TYPE_INCONSISTENT 0x00000115 +#define CKR_RANDOM_SEED_NOT_SUPPORTED 0x00000120 + +/* These are new to v2.0 */ +#define CKR_RANDOM_NO_RNG 0x00000121 + +/* These are new to v2.11 */ +#define CKR_DOMAIN_PARAMS_INVALID 0x00000130 + +/* These are new to v2.0 */ +#define CKR_BUFFER_TOO_SMALL 0x00000150 +#define CKR_SAVED_STATE_INVALID 0x00000160 +#define CKR_INFORMATION_SENSITIVE 0x00000170 +#define CKR_STATE_UNSAVEABLE 0x00000180 + +/* These are new to v2.01 */ +#define CKR_CRYPTOKI_NOT_INITIALIZED 0x00000190 +#define CKR_CRYPTOKI_ALREADY_INITIALIZED 0x00000191 +#define CKR_MUTEX_BAD 0x000001A0 +#define CKR_MUTEX_NOT_LOCKED 0x000001A1 + +/* The following return values are new for PKCS #11 v2.20 amendment 3 */ +#define CKR_NEW_PIN_MODE 0x000001B0 +#define CKR_NEXT_OTP 0x000001B1 + +/* This is new to v2.20 */ +#define CKR_FUNCTION_REJECTED 0x00000200 + +#define CKR_VENDOR_DEFINED 0x80000000 + + +/* CK_NOTIFY is an application callback that processes events */ +typedef CK_CALLBACK_FUNCTION(CK_RV, CK_NOTIFY)( + CK_SESSION_HANDLE hSession, /* the session's handle */ + CK_NOTIFICATION event, + CK_VOID_PTR pApplication /* passed to C_OpenSession */ +); + + +/* CK_FUNCTION_LIST is a structure holding a Cryptoki spec + * version and pointers of appropriate types to all the + * Cryptoki functions */ +/* CK_FUNCTION_LIST is new for v2.0 */ +typedef struct CK_FUNCTION_LIST CK_FUNCTION_LIST; + +typedef CK_FUNCTION_LIST CK_PTR CK_FUNCTION_LIST_PTR; + +typedef CK_FUNCTION_LIST_PTR CK_PTR CK_FUNCTION_LIST_PTR_PTR; + + +/* CK_CREATEMUTEX is an application callback for creating a + * mutex object */ +typedef CK_CALLBACK_FUNCTION(CK_RV, CK_CREATEMUTEX)( + CK_VOID_PTR_PTR ppMutex /* location to receive ptr to mutex */ +); + + +/* CK_DESTROYMUTEX is an application callback for destroying a + * mutex object */ +typedef CK_CALLBACK_FUNCTION(CK_RV, CK_DESTROYMUTEX)( + CK_VOID_PTR pMutex /* pointer to mutex */ +); + + +/* CK_LOCKMUTEX is an application callback for locking a mutex */ +typedef CK_CALLBACK_FUNCTION(CK_RV, CK_LOCKMUTEX)( + CK_VOID_PTR pMutex /* pointer to mutex */ +); + + +/* CK_UNLOCKMUTEX is an application callback for unlocking a + * mutex */ +typedef CK_CALLBACK_FUNCTION(CK_RV, CK_UNLOCKMUTEX)( + CK_VOID_PTR pMutex /* pointer to mutex */ +); + + +/* CK_C_INITIALIZE_ARGS provides the optional arguments to + * C_Initialize */ +typedef struct CK_C_INITIALIZE_ARGS { + CK_CREATEMUTEX CreateMutex; + CK_DESTROYMUTEX DestroyMutex; + CK_LOCKMUTEX LockMutex; + CK_UNLOCKMUTEX UnlockMutex; + CK_FLAGS flags; + CK_VOID_PTR pReserved; +} CK_C_INITIALIZE_ARGS; + +/* flags: bit flags that provide capabilities of the slot + * Bit Flag Mask Meaning + */ +#define CKF_LIBRARY_CANT_CREATE_OS_THREADS 0x00000001 +#define CKF_OS_LOCKING_OK 0x00000002 + +typedef CK_C_INITIALIZE_ARGS CK_PTR CK_C_INITIALIZE_ARGS_PTR; + + +/* additional flags for parameters to functions */ + +/* CKF_DONT_BLOCK is for the function C_WaitForSlotEvent */ +#define CKF_DONT_BLOCK 1 + +/* CK_RSA_PKCS_OAEP_MGF_TYPE is new for v2.10. + * CK_RSA_PKCS_OAEP_MGF_TYPE is used to indicate the Message + * Generation Function (MGF) applied to a message block when + * formatting a message block for the PKCS #1 OAEP encryption + * scheme. */ +typedef CK_ULONG CK_RSA_PKCS_MGF_TYPE; + +typedef CK_RSA_PKCS_MGF_TYPE CK_PTR CK_RSA_PKCS_MGF_TYPE_PTR; + +/* The following MGFs are defined */ +/* CKG_MGF1_SHA256, CKG_MGF1_SHA384, and CKG_MGF1_SHA512 + * are new for v2.20 */ +#define CKG_MGF1_SHA1 0x00000001 +#define CKG_MGF1_SHA256 0x00000002 +#define CKG_MGF1_SHA384 0x00000003 +#define CKG_MGF1_SHA512 0x00000004 +/* SHA-224 is new for PKCS #11 v2.20 amendment 3 */ +#define CKG_MGF1_SHA224 0x00000005 + +/* CK_RSA_PKCS_OAEP_SOURCE_TYPE is new for v2.10. + * CK_RSA_PKCS_OAEP_SOURCE_TYPE is used to indicate the source + * of the encoding parameter when formatting a message block + * for the PKCS #1 OAEP encryption scheme. */ +typedef CK_ULONG CK_RSA_PKCS_OAEP_SOURCE_TYPE; + +typedef CK_RSA_PKCS_OAEP_SOURCE_TYPE CK_PTR CK_RSA_PKCS_OAEP_SOURCE_TYPE_PTR; + +/* The following encoding parameter sources are defined */ +#define CKZ_DATA_SPECIFIED 0x00000001 + +/* CK_RSA_PKCS_OAEP_PARAMS is new for v2.10. + * CK_RSA_PKCS_OAEP_PARAMS provides the parameters to the + * CKM_RSA_PKCS_OAEP mechanism. */ +typedef struct CK_RSA_PKCS_OAEP_PARAMS { + CK_MECHANISM_TYPE hashAlg; + CK_RSA_PKCS_MGF_TYPE mgf; + CK_RSA_PKCS_OAEP_SOURCE_TYPE source; + CK_VOID_PTR pSourceData; + CK_ULONG ulSourceDataLen; +} CK_RSA_PKCS_OAEP_PARAMS; + +typedef CK_RSA_PKCS_OAEP_PARAMS CK_PTR CK_RSA_PKCS_OAEP_PARAMS_PTR; + +/* CK_RSA_PKCS_PSS_PARAMS is new for v2.11. + * CK_RSA_PKCS_PSS_PARAMS provides the parameters to the + * CKM_RSA_PKCS_PSS mechanism(s). */ +typedef struct CK_RSA_PKCS_PSS_PARAMS { + CK_MECHANISM_TYPE hashAlg; + CK_RSA_PKCS_MGF_TYPE mgf; + CK_ULONG sLen; +} CK_RSA_PKCS_PSS_PARAMS; + +typedef CK_RSA_PKCS_PSS_PARAMS CK_PTR CK_RSA_PKCS_PSS_PARAMS_PTR; + +/* CK_EC_KDF_TYPE is new for v2.11. */ +typedef CK_ULONG CK_EC_KDF_TYPE; + +/* The following EC Key Derivation Functions are defined */ +#define CKD_NULL 0x00000001 +#define CKD_SHA1_KDF 0x00000002 + +/* CK_ECDH1_DERIVE_PARAMS is new for v2.11. + * CK_ECDH1_DERIVE_PARAMS provides the parameters to the + * CKM_ECDH1_DERIVE and CKM_ECDH1_COFACTOR_DERIVE mechanisms, + * where each party contributes one key pair. + */ +typedef struct CK_ECDH1_DERIVE_PARAMS { + CK_EC_KDF_TYPE kdf; + CK_ULONG ulSharedDataLen; + CK_BYTE_PTR pSharedData; + CK_ULONG ulPublicDataLen; + CK_BYTE_PTR pPublicData; +} CK_ECDH1_DERIVE_PARAMS; + +typedef CK_ECDH1_DERIVE_PARAMS CK_PTR CK_ECDH1_DERIVE_PARAMS_PTR; + + +/* CK_ECDH2_DERIVE_PARAMS is new for v2.11. + * CK_ECDH2_DERIVE_PARAMS provides the parameters to the + * CKM_ECMQV_DERIVE mechanism, where each party contributes two key pairs. */ +typedef struct CK_ECDH2_DERIVE_PARAMS { + CK_EC_KDF_TYPE kdf; + CK_ULONG ulSharedDataLen; + CK_BYTE_PTR pSharedData; + CK_ULONG ulPublicDataLen; + CK_BYTE_PTR pPublicData; + CK_ULONG ulPrivateDataLen; + CK_OBJECT_HANDLE hPrivateData; + CK_ULONG ulPublicDataLen2; + CK_BYTE_PTR pPublicData2; +} CK_ECDH2_DERIVE_PARAMS; + +typedef CK_ECDH2_DERIVE_PARAMS CK_PTR CK_ECDH2_DERIVE_PARAMS_PTR; + +typedef struct CK_ECMQV_DERIVE_PARAMS { + CK_EC_KDF_TYPE kdf; + CK_ULONG ulSharedDataLen; + CK_BYTE_PTR pSharedData; + CK_ULONG ulPublicDataLen; + CK_BYTE_PTR pPublicData; + CK_ULONG ulPrivateDataLen; + CK_OBJECT_HANDLE hPrivateData; + CK_ULONG ulPublicDataLen2; + CK_BYTE_PTR pPublicData2; + CK_OBJECT_HANDLE publicKey; +} CK_ECMQV_DERIVE_PARAMS; + +typedef CK_ECMQV_DERIVE_PARAMS CK_PTR CK_ECMQV_DERIVE_PARAMS_PTR; + +/* Typedefs and defines for the CKM_X9_42_DH_KEY_PAIR_GEN and the + * CKM_X9_42_DH_PARAMETER_GEN mechanisms (new for PKCS #11 v2.11) */ +typedef CK_ULONG CK_X9_42_DH_KDF_TYPE; +typedef CK_X9_42_DH_KDF_TYPE CK_PTR CK_X9_42_DH_KDF_TYPE_PTR; + +/* The following X9.42 DH key derivation functions are defined + (besides CKD_NULL already defined : */ +#define CKD_SHA1_KDF_ASN1 0x00000003 +#define CKD_SHA1_KDF_CONCATENATE 0x00000004 + +/* CK_X9_42_DH1_DERIVE_PARAMS is new for v2.11. + * CK_X9_42_DH1_DERIVE_PARAMS provides the parameters to the + * CKM_X9_42_DH_DERIVE key derivation mechanism, where each party + * contributes one key pair */ +typedef struct CK_X9_42_DH1_DERIVE_PARAMS { + CK_X9_42_DH_KDF_TYPE kdf; + CK_ULONG ulOtherInfoLen; + CK_BYTE_PTR pOtherInfo; + CK_ULONG ulPublicDataLen; + CK_BYTE_PTR pPublicData; +} CK_X9_42_DH1_DERIVE_PARAMS; + +typedef struct CK_X9_42_DH1_DERIVE_PARAMS CK_PTR CK_X9_42_DH1_DERIVE_PARAMS_PTR; + +/* CK_X9_42_DH2_DERIVE_PARAMS is new for v2.11. + * CK_X9_42_DH2_DERIVE_PARAMS provides the parameters to the + * CKM_X9_42_DH_HYBRID_DERIVE and CKM_X9_42_MQV_DERIVE key derivation + * mechanisms, where each party contributes two key pairs */ +typedef struct CK_X9_42_DH2_DERIVE_PARAMS { + CK_X9_42_DH_KDF_TYPE kdf; + CK_ULONG ulOtherInfoLen; + CK_BYTE_PTR pOtherInfo; + CK_ULONG ulPublicDataLen; + CK_BYTE_PTR pPublicData; + CK_ULONG ulPrivateDataLen; + CK_OBJECT_HANDLE hPrivateData; + CK_ULONG ulPublicDataLen2; + CK_BYTE_PTR pPublicData2; +} CK_X9_42_DH2_DERIVE_PARAMS; + +typedef CK_X9_42_DH2_DERIVE_PARAMS CK_PTR CK_X9_42_DH2_DERIVE_PARAMS_PTR; + +typedef struct CK_X9_42_MQV_DERIVE_PARAMS { + CK_X9_42_DH_KDF_TYPE kdf; + CK_ULONG ulOtherInfoLen; + CK_BYTE_PTR pOtherInfo; + CK_ULONG ulPublicDataLen; + CK_BYTE_PTR pPublicData; + CK_ULONG ulPrivateDataLen; + CK_OBJECT_HANDLE hPrivateData; + CK_ULONG ulPublicDataLen2; + CK_BYTE_PTR pPublicData2; + CK_OBJECT_HANDLE publicKey; +} CK_X9_42_MQV_DERIVE_PARAMS; + +typedef CK_X9_42_MQV_DERIVE_PARAMS CK_PTR CK_X9_42_MQV_DERIVE_PARAMS_PTR; + +/* CK_KEA_DERIVE_PARAMS provides the parameters to the + * CKM_KEA_DERIVE mechanism */ +/* CK_KEA_DERIVE_PARAMS is new for v2.0 */ +typedef struct CK_KEA_DERIVE_PARAMS { + CK_BBOOL isSender; + CK_ULONG ulRandomLen; + CK_BYTE_PTR pRandomA; + CK_BYTE_PTR pRandomB; + CK_ULONG ulPublicDataLen; + CK_BYTE_PTR pPublicData; +} CK_KEA_DERIVE_PARAMS; + +typedef CK_KEA_DERIVE_PARAMS CK_PTR CK_KEA_DERIVE_PARAMS_PTR; + + +/* CK_RC2_PARAMS provides the parameters to the CKM_RC2_ECB and + * CKM_RC2_MAC mechanisms. An instance of CK_RC2_PARAMS just + * holds the effective keysize */ +typedef CK_ULONG CK_RC2_PARAMS; + +typedef CK_RC2_PARAMS CK_PTR CK_RC2_PARAMS_PTR; + + +/* CK_RC2_CBC_PARAMS provides the parameters to the CKM_RC2_CBC + * mechanism */ +typedef struct CK_RC2_CBC_PARAMS { + /* ulEffectiveBits was changed from CK_USHORT to CK_ULONG for + * v2.0 */ + CK_ULONG ulEffectiveBits; /* effective bits (1-1024) */ + + CK_BYTE iv[8]; /* IV for CBC mode */ +} CK_RC2_CBC_PARAMS; + +typedef CK_RC2_CBC_PARAMS CK_PTR CK_RC2_CBC_PARAMS_PTR; + + +/* CK_RC2_MAC_GENERAL_PARAMS provides the parameters for the + * CKM_RC2_MAC_GENERAL mechanism */ +/* CK_RC2_MAC_GENERAL_PARAMS is new for v2.0 */ +typedef struct CK_RC2_MAC_GENERAL_PARAMS { + CK_ULONG ulEffectiveBits; /* effective bits (1-1024) */ + CK_ULONG ulMacLength; /* Length of MAC in bytes */ +} CK_RC2_MAC_GENERAL_PARAMS; + +typedef CK_RC2_MAC_GENERAL_PARAMS CK_PTR \ + CK_RC2_MAC_GENERAL_PARAMS_PTR; + + +/* CK_RC5_PARAMS provides the parameters to the CKM_RC5_ECB and + * CKM_RC5_MAC mechanisms */ +/* CK_RC5_PARAMS is new for v2.0 */ +typedef struct CK_RC5_PARAMS { + CK_ULONG ulWordsize; /* wordsize in bits */ + CK_ULONG ulRounds; /* number of rounds */ +} CK_RC5_PARAMS; + +typedef CK_RC5_PARAMS CK_PTR CK_RC5_PARAMS_PTR; + + +/* CK_RC5_CBC_PARAMS provides the parameters to the CKM_RC5_CBC + * mechanism */ +/* CK_RC5_CBC_PARAMS is new for v2.0 */ +typedef struct CK_RC5_CBC_PARAMS { + CK_ULONG ulWordsize; /* wordsize in bits */ + CK_ULONG ulRounds; /* number of rounds */ + CK_BYTE_PTR pIv; /* pointer to IV */ + CK_ULONG ulIvLen; /* length of IV in bytes */ +} CK_RC5_CBC_PARAMS; + +typedef CK_RC5_CBC_PARAMS CK_PTR CK_RC5_CBC_PARAMS_PTR; + + +/* CK_RC5_MAC_GENERAL_PARAMS provides the parameters for the + * CKM_RC5_MAC_GENERAL mechanism */ +/* CK_RC5_MAC_GENERAL_PARAMS is new for v2.0 */ +typedef struct CK_RC5_MAC_GENERAL_PARAMS { + CK_ULONG ulWordsize; /* wordsize in bits */ + CK_ULONG ulRounds; /* number of rounds */ + CK_ULONG ulMacLength; /* Length of MAC in bytes */ +} CK_RC5_MAC_GENERAL_PARAMS; + +typedef CK_RC5_MAC_GENERAL_PARAMS CK_PTR \ + CK_RC5_MAC_GENERAL_PARAMS_PTR; + + +/* CK_MAC_GENERAL_PARAMS provides the parameters to most block + * ciphers' MAC_GENERAL mechanisms. Its value is the length of + * the MAC */ +/* CK_MAC_GENERAL_PARAMS is new for v2.0 */ +typedef CK_ULONG CK_MAC_GENERAL_PARAMS; + +typedef CK_MAC_GENERAL_PARAMS CK_PTR CK_MAC_GENERAL_PARAMS_PTR; + +/* CK_DES/AES_ECB/CBC_ENCRYPT_DATA_PARAMS are new for v2.20 */ +typedef struct CK_DES_CBC_ENCRYPT_DATA_PARAMS { + CK_BYTE iv[8]; + CK_BYTE_PTR pData; + CK_ULONG length; +} CK_DES_CBC_ENCRYPT_DATA_PARAMS; + +typedef CK_DES_CBC_ENCRYPT_DATA_PARAMS CK_PTR CK_DES_CBC_ENCRYPT_DATA_PARAMS_PTR; + +typedef struct CK_AES_CBC_ENCRYPT_DATA_PARAMS { + CK_BYTE iv[16]; + CK_BYTE_PTR pData; + CK_ULONG length; +} CK_AES_CBC_ENCRYPT_DATA_PARAMS; + +typedef CK_AES_CBC_ENCRYPT_DATA_PARAMS CK_PTR CK_AES_CBC_ENCRYPT_DATA_PARAMS_PTR; + +/* CK_SKIPJACK_PRIVATE_WRAP_PARAMS provides the parameters to the + * CKM_SKIPJACK_PRIVATE_WRAP mechanism */ +/* CK_SKIPJACK_PRIVATE_WRAP_PARAMS is new for v2.0 */ +typedef struct CK_SKIPJACK_PRIVATE_WRAP_PARAMS { + CK_ULONG ulPasswordLen; + CK_BYTE_PTR pPassword; + CK_ULONG ulPublicDataLen; + CK_BYTE_PTR pPublicData; + CK_ULONG ulPAndGLen; + CK_ULONG ulQLen; + CK_ULONG ulRandomLen; + CK_BYTE_PTR pRandomA; + CK_BYTE_PTR pPrimeP; + CK_BYTE_PTR pBaseG; + CK_BYTE_PTR pSubprimeQ; +} CK_SKIPJACK_PRIVATE_WRAP_PARAMS; + +typedef CK_SKIPJACK_PRIVATE_WRAP_PARAMS CK_PTR \ + CK_SKIPJACK_PRIVATE_WRAP_PTR; + + +/* CK_SKIPJACK_RELAYX_PARAMS provides the parameters to the + * CKM_SKIPJACK_RELAYX mechanism */ +/* CK_SKIPJACK_RELAYX_PARAMS is new for v2.0 */ +typedef struct CK_SKIPJACK_RELAYX_PARAMS { + CK_ULONG ulOldWrappedXLen; + CK_BYTE_PTR pOldWrappedX; + CK_ULONG ulOldPasswordLen; + CK_BYTE_PTR pOldPassword; + CK_ULONG ulOldPublicDataLen; + CK_BYTE_PTR pOldPublicData; + CK_ULONG ulOldRandomLen; + CK_BYTE_PTR pOldRandomA; + CK_ULONG ulNewPasswordLen; + CK_BYTE_PTR pNewPassword; + CK_ULONG ulNewPublicDataLen; + CK_BYTE_PTR pNewPublicData; + CK_ULONG ulNewRandomLen; + CK_BYTE_PTR pNewRandomA; +} CK_SKIPJACK_RELAYX_PARAMS; + +typedef CK_SKIPJACK_RELAYX_PARAMS CK_PTR \ + CK_SKIPJACK_RELAYX_PARAMS_PTR; + + +typedef struct CK_PBE_PARAMS { + CK_BYTE_PTR pInitVector; + CK_UTF8CHAR_PTR pPassword; + CK_ULONG ulPasswordLen; + CK_BYTE_PTR pSalt; + CK_ULONG ulSaltLen; + CK_ULONG ulIteration; +} CK_PBE_PARAMS; + +typedef CK_PBE_PARAMS CK_PTR CK_PBE_PARAMS_PTR; + + +/* CK_KEY_WRAP_SET_OAEP_PARAMS provides the parameters to the + * CKM_KEY_WRAP_SET_OAEP mechanism */ +/* CK_KEY_WRAP_SET_OAEP_PARAMS is new for v2.0 */ +typedef struct CK_KEY_WRAP_SET_OAEP_PARAMS { + CK_BYTE bBC; /* block contents byte */ + CK_BYTE_PTR pX; /* extra data */ + CK_ULONG ulXLen; /* length of extra data in bytes */ +} CK_KEY_WRAP_SET_OAEP_PARAMS; + +typedef CK_KEY_WRAP_SET_OAEP_PARAMS CK_PTR \ + CK_KEY_WRAP_SET_OAEP_PARAMS_PTR; + + +typedef struct CK_SSL3_RANDOM_DATA { + CK_BYTE_PTR pClientRandom; + CK_ULONG ulClientRandomLen; + CK_BYTE_PTR pServerRandom; + CK_ULONG ulServerRandomLen; +} CK_SSL3_RANDOM_DATA; + + +typedef struct CK_SSL3_MASTER_KEY_DERIVE_PARAMS { + CK_SSL3_RANDOM_DATA RandomInfo; + CK_VERSION_PTR pVersion; +} CK_SSL3_MASTER_KEY_DERIVE_PARAMS; + +typedef struct CK_SSL3_MASTER_KEY_DERIVE_PARAMS CK_PTR \ + CK_SSL3_MASTER_KEY_DERIVE_PARAMS_PTR; + + +typedef struct CK_SSL3_KEY_MAT_OUT { + CK_OBJECT_HANDLE hClientMacSecret; + CK_OBJECT_HANDLE hServerMacSecret; + CK_OBJECT_HANDLE hClientKey; + CK_OBJECT_HANDLE hServerKey; + CK_BYTE_PTR pIVClient; + CK_BYTE_PTR pIVServer; +} CK_SSL3_KEY_MAT_OUT; + +typedef CK_SSL3_KEY_MAT_OUT CK_PTR CK_SSL3_KEY_MAT_OUT_PTR; + + +typedef struct CK_SSL3_KEY_MAT_PARAMS { + CK_ULONG ulMacSizeInBits; + CK_ULONG ulKeySizeInBits; + CK_ULONG ulIVSizeInBits; + CK_BBOOL bIsExport; + CK_SSL3_RANDOM_DATA RandomInfo; + CK_SSL3_KEY_MAT_OUT_PTR pReturnedKeyMaterial; +} CK_SSL3_KEY_MAT_PARAMS; + +typedef CK_SSL3_KEY_MAT_PARAMS CK_PTR CK_SSL3_KEY_MAT_PARAMS_PTR; + +/* CK_TLS_PRF_PARAMS is new for version 2.20 */ +typedef struct CK_TLS_PRF_PARAMS { + CK_BYTE_PTR pSeed; + CK_ULONG ulSeedLen; + CK_BYTE_PTR pLabel; + CK_ULONG ulLabelLen; + CK_BYTE_PTR pOutput; + CK_ULONG_PTR pulOutputLen; +} CK_TLS_PRF_PARAMS; + +typedef CK_TLS_PRF_PARAMS CK_PTR CK_TLS_PRF_PARAMS_PTR; + +/* WTLS is new for version 2.20 */ +typedef struct CK_WTLS_RANDOM_DATA { + CK_BYTE_PTR pClientRandom; + CK_ULONG ulClientRandomLen; + CK_BYTE_PTR pServerRandom; + CK_ULONG ulServerRandomLen; +} CK_WTLS_RANDOM_DATA; + +typedef CK_WTLS_RANDOM_DATA CK_PTR CK_WTLS_RANDOM_DATA_PTR; + +typedef struct CK_WTLS_MASTER_KEY_DERIVE_PARAMS { + CK_MECHANISM_TYPE DigestMechanism; + CK_WTLS_RANDOM_DATA RandomInfo; + CK_BYTE_PTR pVersion; +} CK_WTLS_MASTER_KEY_DERIVE_PARAMS; + +typedef CK_WTLS_MASTER_KEY_DERIVE_PARAMS CK_PTR \ + CK_WTLS_MASTER_KEY_DERIVE_PARAMS_PTR; + +typedef struct CK_WTLS_PRF_PARAMS { + CK_MECHANISM_TYPE DigestMechanism; + CK_BYTE_PTR pSeed; + CK_ULONG ulSeedLen; + CK_BYTE_PTR pLabel; + CK_ULONG ulLabelLen; + CK_BYTE_PTR pOutput; + CK_ULONG_PTR pulOutputLen; +} CK_WTLS_PRF_PARAMS; + +typedef CK_WTLS_PRF_PARAMS CK_PTR CK_WTLS_PRF_PARAMS_PTR; + +typedef struct CK_WTLS_KEY_MAT_OUT { + CK_OBJECT_HANDLE hMacSecret; + CK_OBJECT_HANDLE hKey; + CK_BYTE_PTR pIV; +} CK_WTLS_KEY_MAT_OUT; + +typedef CK_WTLS_KEY_MAT_OUT CK_PTR CK_WTLS_KEY_MAT_OUT_PTR; + +typedef struct CK_WTLS_KEY_MAT_PARAMS { + CK_MECHANISM_TYPE DigestMechanism; + CK_ULONG ulMacSizeInBits; + CK_ULONG ulKeySizeInBits; + CK_ULONG ulIVSizeInBits; + CK_ULONG ulSequenceNumber; + CK_BBOOL bIsExport; + CK_WTLS_RANDOM_DATA RandomInfo; + CK_WTLS_KEY_MAT_OUT_PTR pReturnedKeyMaterial; +} CK_WTLS_KEY_MAT_PARAMS; + +typedef CK_WTLS_KEY_MAT_PARAMS CK_PTR CK_WTLS_KEY_MAT_PARAMS_PTR; + +/* CMS is new for version 2.20 */ +typedef struct CK_CMS_SIG_PARAMS { + CK_OBJECT_HANDLE certificateHandle; + CK_MECHANISM_PTR pSigningMechanism; + CK_MECHANISM_PTR pDigestMechanism; + CK_UTF8CHAR_PTR pContentType; + CK_BYTE_PTR pRequestedAttributes; + CK_ULONG ulRequestedAttributesLen; + CK_BYTE_PTR pRequiredAttributes; + CK_ULONG ulRequiredAttributesLen; +} CK_CMS_SIG_PARAMS; + +typedef CK_CMS_SIG_PARAMS CK_PTR CK_CMS_SIG_PARAMS_PTR; + +typedef struct CK_KEY_DERIVATION_STRING_DATA { + CK_BYTE_PTR pData; + CK_ULONG ulLen; +} CK_KEY_DERIVATION_STRING_DATA; + +typedef CK_KEY_DERIVATION_STRING_DATA CK_PTR \ + CK_KEY_DERIVATION_STRING_DATA_PTR; + + +/* The CK_EXTRACT_PARAMS is used for the + * CKM_EXTRACT_KEY_FROM_KEY mechanism. It specifies which bit + * of the base key should be used as the first bit of the + * derived key */ +/* CK_EXTRACT_PARAMS is new for v2.0 */ +typedef CK_ULONG CK_EXTRACT_PARAMS; + +typedef CK_EXTRACT_PARAMS CK_PTR CK_EXTRACT_PARAMS_PTR; + +/* CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE is new for v2.10. + * CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE is used to + * indicate the Pseudo-Random Function (PRF) used to generate + * key bits using PKCS #5 PBKDF2. */ +typedef CK_ULONG CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE; + +typedef CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE CK_PTR CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE_PTR; + +/* The following PRFs are defined in PKCS #5 v2.0. */ +#define CKP_PKCS5_PBKD2_HMAC_SHA1 0x00000001 + + +/* CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE is new for v2.10. + * CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE is used to indicate the + * source of the salt value when deriving a key using PKCS #5 + * PBKDF2. */ +typedef CK_ULONG CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE; + +typedef CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE CK_PTR CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE_PTR; + +/* The following salt value sources are defined in PKCS #5 v2.0. */ +#define CKZ_SALT_SPECIFIED 0x00000001 + +/* CK_PKCS5_PBKD2_PARAMS is new for v2.10. + * CK_PKCS5_PBKD2_PARAMS is a structure that provides the + * parameters to the CKM_PKCS5_PBKD2 mechanism. */ +typedef struct CK_PKCS5_PBKD2_PARAMS { + CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE saltSource; + CK_VOID_PTR pSaltSourceData; + CK_ULONG ulSaltSourceDataLen; + CK_ULONG iterations; + CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE prf; + CK_VOID_PTR pPrfData; + CK_ULONG ulPrfDataLen; + CK_UTF8CHAR_PTR pPassword; + CK_ULONG_PTR ulPasswordLen; +} CK_PKCS5_PBKD2_PARAMS; + +typedef CK_PKCS5_PBKD2_PARAMS CK_PTR CK_PKCS5_PBKD2_PARAMS_PTR; + +/* All CK_OTP structs are new for PKCS #11 v2.20 amendment 3 */ + +typedef CK_ULONG CK_OTP_PARAM_TYPE; +typedef CK_OTP_PARAM_TYPE CK_PARAM_TYPE; /* B/w compatibility */ + +typedef struct CK_OTP_PARAM { + CK_OTP_PARAM_TYPE type; + CK_VOID_PTR pValue; + CK_ULONG ulValueLen; +} CK_OTP_PARAM; + +typedef CK_OTP_PARAM CK_PTR CK_OTP_PARAM_PTR; + +typedef struct CK_OTP_PARAMS { + CK_OTP_PARAM_PTR pParams; + CK_ULONG ulCount; +} CK_OTP_PARAMS; + +typedef CK_OTP_PARAMS CK_PTR CK_OTP_PARAMS_PTR; + +typedef struct CK_OTP_SIGNATURE_INFO { + CK_OTP_PARAM_PTR pParams; + CK_ULONG ulCount; +} CK_OTP_SIGNATURE_INFO; + +typedef CK_OTP_SIGNATURE_INFO CK_PTR CK_OTP_SIGNATURE_INFO_PTR; + +/* The following OTP-related defines are new for PKCS #11 v2.20 amendment 1 */ +#define CK_OTP_VALUE 0 +#define CK_OTP_PIN 1 +#define CK_OTP_CHALLENGE 2 +#define CK_OTP_TIME 3 +#define CK_OTP_COUNTER 4 +#define CK_OTP_FLAGS 5 +#define CK_OTP_OUTPUT_LENGTH 6 +#define CK_OTP_OUTPUT_FORMAT 7 + +/* The following OTP-related defines are new for PKCS #11 v2.20 amendment 1 */ +#define CKF_NEXT_OTP 0x00000001 +#define CKF_EXCLUDE_TIME 0x00000002 +#define CKF_EXCLUDE_COUNTER 0x00000004 +#define CKF_EXCLUDE_CHALLENGE 0x00000008 +#define CKF_EXCLUDE_PIN 0x00000010 +#define CKF_USER_FRIENDLY_OTP 0x00000020 + +/* CK_KIP_PARAMS is new for PKCS #11 v2.20 amendment 2 */ +typedef struct CK_KIP_PARAMS { + CK_MECHANISM_PTR pMechanism; + CK_OBJECT_HANDLE hKey; + CK_BYTE_PTR pSeed; + CK_ULONG ulSeedLen; +} CK_KIP_PARAMS; + +typedef CK_KIP_PARAMS CK_PTR CK_KIP_PARAMS_PTR; + +/* CK_AES_CTR_PARAMS is new for PKCS #11 v2.20 amendment 3 */ +typedef struct CK_AES_CTR_PARAMS { + CK_ULONG ulCounterBits; + CK_BYTE cb[16]; +} CK_AES_CTR_PARAMS; + +typedef CK_AES_CTR_PARAMS CK_PTR CK_AES_CTR_PARAMS_PTR; + +/* CK_CAMELLIA_CTR_PARAMS is new for PKCS #11 v2.20 amendment 3 */ +typedef struct CK_CAMELLIA_CTR_PARAMS { + CK_ULONG ulCounterBits; + CK_BYTE cb[16]; +} CK_CAMELLIA_CTR_PARAMS; + +typedef CK_CAMELLIA_CTR_PARAMS CK_PTR CK_CAMELLIA_CTR_PARAMS_PTR; + +/* CK_CAMELLIA_CBC_ENCRYPT_DATA_PARAMS is new for PKCS #11 v2.20 amendment 3 */ +typedef struct CK_CAMELLIA_CBC_ENCRYPT_DATA_PARAMS { + CK_BYTE iv[16]; + CK_BYTE_PTR pData; + CK_ULONG length; +} CK_CAMELLIA_CBC_ENCRYPT_DATA_PARAMS; + +typedef CK_CAMELLIA_CBC_ENCRYPT_DATA_PARAMS CK_PTR CK_CAMELLIA_CBC_ENCRYPT_DATA_PARAMS_PTR; + +/* CK_ARIA_CBC_ENCRYPT_DATA_PARAMS is new for PKCS #11 v2.20 amendment 3 */ +typedef struct CK_ARIA_CBC_ENCRYPT_DATA_PARAMS { + CK_BYTE iv[16]; + CK_BYTE_PTR pData; + CK_ULONG length; +} CK_ARIA_CBC_ENCRYPT_DATA_PARAMS; + +typedef CK_ARIA_CBC_ENCRYPT_DATA_PARAMS CK_PTR CK_ARIA_CBC_ENCRYPT_DATA_PARAMS_PTR; + +#endif Index: openssl/util/libeay.num diff -u openssl/util/libeay.num:1.8.2.1.4.1.2.1.4.1.6.1.2.1.2.1.2.1 openssl/util/libeay.num:1.13.2.3 --- openssl/util/libeay.num:1.8.2.1.4.1.2.1.4.1.6.1.2.1.2.1.2.1 Mon Jun 13 15:42:32 2016 +++ openssl/util/libeay.num Mon Jun 13 15:52:51 2016 @@ -4415,4 +4415,5 @@ X509_VERIFY_PARAM_add1_host 4771 EXIST::FUNCTION: EC_GROUP_get_mont_data 4772 EXIST::FUNCTION:EC i2d_re_X509_tbs 4773 EXIST::FUNCTION: -EVP_PKEY_asn1_set_item 4774 EXIST::FUNCTION: +ENGINE_load_pk11ca 4774 EXIST::FUNCTION:HW_PKCS11CA,ENGINE +ENGINE_load_pk11so 4774 EXIST::FUNCTION:HW_PKCS11SO,ENGINE Index: openssl/util/mk1mf.pl diff -u openssl/util/mk1mf.pl:1.9.2.1.4.1.10.1.2.1.2.1.2.1.2.1 openssl/util/mk1mf.pl:1.12.2.3 --- openssl/util/mk1mf.pl:1.9.2.1.4.1.10.1.2.1.2.1.2.1.2.1 Mon Jun 13 15:42:33 2016 +++ openssl/util/mk1mf.pl Mon Jun 13 15:52:52 2016 @@ -122,6 +122,8 @@ no-ecdh - No ECDH no-engine - No engine no-hw - No hw + no-hw-pkcs11ca - No hw PKCS#11 CA flavor + no-hw-pkcs11so - No hw PKCS#11 SO flavor nasm - Use NASM for x86 asm nw-nasm - Use NASM x86 asm for NetWare nw-mwasm - Use Metrowerks x86 asm for NetWare @@ -287,6 +289,8 @@ $cflags.=" -DOPENSSL_NO_GOST" if $no_gost; $cflags.=" -DOPENSSL_NO_ENGINE" if $no_engine; $cflags.=" -DOPENSSL_NO_HW" if $no_hw; +$cflags.=" -DOPENSSL_NO_HW_PKCS11CA" if $no_hw_pkcs11ca; +$cflags.=" -DOPENSSL_NO_HW_PKCS11SO" if $no_hw_pkcs11so; $cflags.=" -DOPENSSL_FIPS" if $fips; $cflags.=" -DOPENSSL_NO_JPAKE" if $no_jpake; $cflags.=" -DOPENSSL_NO_EC2M" if $no_ec2m; @@ -361,6 +365,9 @@ $dir=$val; } + if ($key eq "PK11_LIB_LOCATION") + { $cflags .= " -D$key=\\\"$val\\\"" if $val ne "";} + if ($key eq "KRB5_INCLUDES") { $cflags .= " $val";} @@ -1219,6 +1226,8 @@ "no-gost" => \$no_gost, "no-engine" => \$no_engine, "no-hw" => \$no_hw, + "no-hw-pkcs11ca" => \$no_hw_pkcs11ca, + "no-hw-pkcs11so" => \$no_hw_pkcs11so, "no-rsax" => 0, "just-ssl" => [\$no_rc2, \$no_idea, \$no_des, \$no_bf, \$no_cast, Index: openssl/util/mkdef.pl diff -u openssl/util/mkdef.pl:1.7.2.1.4.1.10.1.2.1.2.1.4.1 openssl/util/mkdef.pl:1.11.2.2 --- openssl/util/mkdef.pl:1.7.2.1.4.1.10.1.2.1.2.1.4.1 Mon Jun 13 15:42:34 2016 +++ openssl/util/mkdef.pl Mon Jun 13 15:52:52 2016 @@ -96,7 +96,7 @@ # External "algorithms" "FP_API", "STDIO", "SOCK", "KRB5", "DGRAM", # Engines - "STATIC_ENGINE", "ENGINE", "HW", "GMP", + "STATIC_ENGINE", "ENGINE", "HW", "GMP", "HW_PKCS11CA", "HW_PKCS11SO", # RFC3779 "RFC3779", # TLS @@ -143,6 +143,7 @@ my $no_md2; my $no_md4; my $no_md5; my $no_sha; my $no_ripemd; my $no_mdc2; my $no_rsa; my $no_dsa; my $no_dh; my $no_hmac=0; my $no_aes; my $no_krb5; my $no_ec; my $no_ecdsa; my $no_ecdh; my $no_engine; my $no_hw; +my $no_pkcs11ca; my $no_pkcs11so; my $no_fp_api; my $no_static_engine=1; my $no_gmp; my $no_deprecated; my $no_rfc3779; my $no_psk; my $no_tlsext; my $no_cms; my $no_capieng; my $no_jpake; my $no_srp; my $no_ssl2; my $no_ec2m; my $no_nistp_gcc; @@ -251,6 +252,8 @@ elsif (/^no-sctp$/) { $no_sctp=1; } elsif (/^no-srtp$/) { $no_srtp=1; } elsif (/^no-unit-test$/){ $no_unit_test=1; } + elsif (/^no-hw-pkcs11ca$/) { $no_pkcs11ca=1; } + elsif (/^no-hw-pkcs11so$/) { $no_pkcs11so=1; } } @@ -1206,6 +1209,8 @@ if ($keyword eq "KRB5" && $no_krb5) { return 0; } if ($keyword eq "ENGINE" && $no_engine) { return 0; } if ($keyword eq "HW" && $no_hw) { return 0; } + if ($keyword eq "HW_PKCS11CA" && $no_pkcs11ca) { return 0; } + if ($keyword eq "HW_PKCS11SO" && $no_pkcs11so) { return 0; } if ($keyword eq "FP_API" && $no_fp_api) { return 0; } if ($keyword eq "STATIC_ENGINE" && $no_static_engine) { return 0; } if ($keyword eq "GMP" && $no_gmp) { return 0; } Index: openssl/util/pl/VC-32.pl diff -u openssl/util/pl/VC-32.pl:1.7.2.1.4.1.2.1.4.1.8.1.2.1.2.1 openssl/util/pl/VC-32.pl:1.10.2.3 --- openssl/util/pl/VC-32.pl:1.7.2.1.4.1.2.1.4.1.8.1.2.1.2.1 Mon Jun 13 15:42:35 2016 +++ openssl/util/pl/VC-32.pl Mon Jun 13 15:52:53 2016 @@ -47,7 +47,7 @@ $base_cflags= " $mf_cflag"; my $f = $shlib || $fips ?' /MD':' /MT'; $opt_cflags=$f.' /Ox'; - $dbg_cflags=$f.'d /Od -DDEBUG -D_DEBUG'; + $dbg_cflags=$f.'d /Od /Zi -DDEBUG -D_DEBUG'; $lflags="/nologo /subsystem:console /opt:ref"; *::perlasm_compile_target = sub { bind9-9.11.3+dfsg/bin/pkcs11/pkcs11-destroy.8000066400000000000000000000057551325250447100203040ustar00rootroot00000000000000.\" Copyright (C) 2009, 2014-2016 Internet Systems Consortium, Inc. ("ISC") .\" .\" This Source Code Form is subject to the terms of the Mozilla Public .\" License, v. 2.0. If a copy of the MPL was not distributed with this .\" file, You can obtain one at http://mozilla.org/MPL/2.0/. .\" .hy 0 .ad l '\" t .\" Title: pkcs11-destroy .\" Author: .\" Generator: DocBook XSL Stylesheets v1.78.1 .\" Date: 2014-01-15 .\" Manual: BIND9 .\" Source: ISC .\" Language: English .\" .TH "PKCS11\-DESTROY" "8" "2014\-01\-15" "ISC" "BIND9" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" pkcs11-destroy \- destroy PKCS#11 objects .SH "SYNOPSIS" .HP \w'\fBpkcs11\-destroy\fR\ 'u \fBpkcs11\-destroy\fR [\fB\-m\ \fR\fB\fImodule\fR\fR] [\fB\-s\ \fR\fB\fIslot\fR\fR] {\-i\ \fIID\fR | \-l\ \fIlabel\fR} [\fB\-p\ \fR\fB\fIPIN\fR\fR] [\fB\-w\ \fR\fB\fIseconds\fR\fR] .SH "DESCRIPTION" .PP \fBpkcs11\-destroy\fR destroys keys stored in a PKCS#11 device, identified by their \fBID\fR or \fBlabel\fR\&. .PP Matching keys are displayed before being destroyed\&. By default, there is a five second delay to allow the user to interrupt the process before the destruction takes place\&. .SH "ARGUMENTS" .PP \-m \fImodule\fR .RS 4 Specify the PKCS#11 provider module\&. This must be the full path to a shared library object implementing the PKCS#11 API for the device\&. .RE .PP \-s \fIslot\fR .RS 4 Open the session with the given PKCS#11 slot\&. The default is slot 0\&. .RE .PP \-i \fIID\fR .RS 4 Destroy keys with the given object ID\&. .RE .PP \-l \fIlabel\fR .RS 4 Destroy keys with the given label\&. .RE .PP \-p \fIPIN\fR .RS 4 Specify the PIN for the device\&. If no PIN is provided on the command line, \fBpkcs11\-destroy\fR will prompt for it\&. .RE .PP \-w \fIseconds\fR .RS 4 Specify how long to pause before carrying out key destruction\&. The default is five seconds\&. If set to 0, destruction will be immediate\&. .RE .SH "SEE ALSO" .PP \fBpkcs11-keygen\fR(8), \fBpkcs11-list\fR(8), \fBpkcs11-tokens\fR(8) .SH "AUTHOR" .PP \fBInternet Systems Consortium, Inc\&.\fR .SH "COPYRIGHT" .br Copyright \(co 2009, 2014-2016 Internet Systems Consortium, Inc. ("ISC") .br bind9-9.11.3+dfsg/bin/pkcs11/pkcs11-destroy.c000066400000000000000000000163701325250447100203520ustar00rootroot00000000000000/* * Copyright (C) 2009, 2015 Internet Systems Consortium, Inc. ("ISC") * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* * Portions copyright (c) 2008 Nominet UK. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* $Id: pkcs11-destroy.c,v 1.8 2010/01/13 21:19:52 fdupont Exp $ */ /* * pkcs11-destroy [-m module] [-s $slot] [-i $id | -l $label] * [-p $pin] [ -w $wait ] */ /*! \file */ #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef WIN32 #define sleep(x) Sleep(x) #endif #if !(defined(HAVE_GETPASSPHRASE) || (defined (__SVR4) && defined (__sun))) #define getpassphrase(x) getpass(x) #endif int main(int argc, char *argv[]) { isc_result_t result; CK_RV rv; CK_SLOT_ID slot = 0; CK_SESSION_HANDLE hSession; CK_BYTE attr_id[2]; CK_OBJECT_HANDLE akey[50]; pk11_context_t pctx; char *lib_name = NULL; char *label = NULL; char *pin = NULL; int error = 0; unsigned int id = 0, i = 0, wait = 5; int c, errflg = 0; CK_ULONG ulObjectCount; CK_ATTRIBUTE search_template[] = { {CKA_ID, &attr_id, sizeof(attr_id)} }; unsigned int j, len; while ((c = isc_commandline_parse(argc, argv, ":m:s:i:l:p:w:")) != -1) { switch (c) { case 'm': lib_name = isc_commandline_argument; break; case 's': slot = atoi(isc_commandline_argument); break; case 'i': id = atoi(isc_commandline_argument); id &= 0xffff; break; case 'l': label = isc_commandline_argument; break; case 'p': pin = isc_commandline_argument; break; case 'w': wait = atoi(isc_commandline_argument); break; case ':': fprintf(stderr, "Option -%c requires an operand\n", isc_commandline_option); errflg++; break; case '?': default: fprintf(stderr, "Unrecognised option: -%c\n", isc_commandline_option); errflg++; } } if (errflg || (id && (label != NULL))) { fprintf(stderr, "Usage:\n"); fprintf(stderr, "\tpkcs11-destroy [-m module] [-s slot] " "[-i id | -l label] [-p pin] [-w waittime]\n"); exit(1); } if (id) { attr_id[0] = (id >> 8) & 0xff; attr_id[1] = id & 0xff; } else if (label) { search_template[0].type = CKA_LABEL; search_template[0].pValue = label; search_template[0].ulValueLen = strlen(label); } pk11_result_register(); /* Initialize the CRYPTOKI library */ if (lib_name != NULL) pk11_set_lib_name(lib_name); if (pin == NULL) pin = getpassphrase("Enter Pin: "); result = pk11_get_session(&pctx, OP_ANY, ISC_FALSE, ISC_TRUE, ISC_TRUE, (const char *) pin, slot); if (result == PK11_R_NORANDOMSERVICE || result == PK11_R_NODIGESTSERVICE || result == PK11_R_NOAESSERVICE) { fprintf(stderr, "Warning: %s\n", isc_result_totext(result)); fprintf(stderr, "This HSM will not work with BIND 9 " "using native PKCS#11.\n"); } else if (result != ISC_R_SUCCESS) { fprintf(stderr, "Unrecoverable error initializing " "PKCS#11: %s\n", isc_result_totext(result)); exit(1); } memset(pin, 0, strlen(pin)); hSession = pctx.session; rv = pkcs_C_FindObjectsInit(hSession, search_template, ((id != 0) || (label != NULL)) ? 1 : 0); if (rv != CKR_OK) { fprintf(stderr, "C_FindObjectsInit: Error = 0x%.8lX\n", rv); error = 1; goto exit_session; } rv = pkcs_C_FindObjects(hSession, akey, 50, &ulObjectCount); if (rv != CKR_OK) { fprintf(stderr, "C_FindObjects: Error = 0x%.8lX\n", rv); error = 1; goto exit_search; } if (ulObjectCount == 0) { printf("No matching key objects found.\n"); goto exit_search; } else printf("Key object%s found:\n", ulObjectCount > 1 ? "s" : ""); for (i = 0; i < ulObjectCount; i++) { CK_OBJECT_CLASS oclass = 0; CK_BYTE labelbuf[64 + 1]; CK_BYTE idbuf[64]; CK_ATTRIBUTE attr_template[] = { {CKA_CLASS, &oclass, sizeof(oclass)}, {CKA_LABEL, labelbuf, sizeof(labelbuf) - 1}, {CKA_ID, idbuf, sizeof(idbuf)} }; memset(labelbuf, 0, sizeof(labelbuf)); memset(idbuf, 0, sizeof(idbuf)); rv = pkcs_C_GetAttributeValue(hSession, akey[i], attr_template, 3); if (rv != CKR_OK) { fprintf(stderr, "C_GetAttributeValue[%u]: rv = 0x%.8lX\n", i, rv); error = 1; goto exit_search; } len = attr_template[2].ulValueLen; printf(" object[%u]: class %lu, label '%s', id[%lu] ", i, oclass, labelbuf, attr_template[2].ulValueLen); if (len > 4) len = 4; if (len > 0) printf("0x"); for (j = 0; j < len; j++) printf("%02x", idbuf[j]); if (attr_template[2].ulValueLen > len) printf("...\n"); else printf("\n"); } if (wait != 0) { printf("WARNING: This action is irreversible! " "Destroying key objects in %d seconds\n ", wait); for (i = 0; i < wait; i++) { printf("."); fflush(stdout); sleep(1); } printf("\n"); } for (i = 0; i < ulObjectCount; i++) { rv = pkcs_C_DestroyObject(hSession, akey[i]); if (rv != CKR_OK) { fprintf(stderr, "C_DestroyObject[%u] failed: rv = 0x%.8lX\n", i, rv); error = 1; } } if (error == 0) printf("Destruction complete.\n"); exit_search: rv = pkcs_C_FindObjectsFinal(hSession); if (rv != CKR_OK) { fprintf(stderr, "C_FindObjectsFinal: Error = 0x%.8lX\n", rv); error = 1; } exit_session: pk11_return_session(&pctx); (void) pk11_finalize(); exit(error); } bind9-9.11.3+dfsg/bin/pkcs11/pkcs11-destroy.docbook000066400000000000000000000114521325250447100215440ustar00rootroot00000000000000 2014-01-15 ISC Internet Systems Consortium, Inc. pkcs11-destroy 8 BIND9 pkcs11-destroy destroy PKCS#11 objects 2009 2014 2015 2016 Internet Systems Consortium, Inc. ("ISC") pkcs11-destroy -i ID -l label DESCRIPTION pkcs11-destroy destroys keys stored in a PKCS#11 device, identified by their or . Matching keys are displayed before being destroyed. By default, there is a five second delay to allow the user to interrupt the process before the destruction takes place. ARGUMENTS -m module Specify the PKCS#11 provider module. This must be the full path to a shared library object implementing the PKCS#11 API for the device. -s slot Open the session with the given PKCS#11 slot. The default is slot 0. -i ID Destroy keys with the given object ID. -l label Destroy keys with the given label. -p PIN Specify the PIN for the device. If no PIN is provided on the command line, pkcs11-destroy will prompt for it. -w seconds Specify how long to pause before carrying out key destruction. The default is five seconds. If set to 0, destruction will be immediate. SEE ALSO pkcs11-keygen8 , pkcs11-list8 , pkcs11-tokens8 bind9-9.11.3+dfsg/bin/pkcs11/pkcs11-destroy.html000066400000000000000000000102021325250447100210600ustar00rootroot00000000000000 pkcs11-destroy

Name

pkcs11-destroy — destroy PKCS#11 objects

Synopsis

pkcs11-destroy [-m module] [-s slot] { -i ID | -l label } [-p PIN] [-w seconds]

DESCRIPTION

pkcs11-destroy destroys keys stored in a PKCS#11 device, identified by their ID or label.

Matching keys are displayed before being destroyed. By default, there is a five second delay to allow the user to interrupt the process before the destruction takes place.

ARGUMENTS

-m module

Specify the PKCS#11 provider module. This must be the full path to a shared library object implementing the PKCS#11 API for the device.

-s slot

Open the session with the given PKCS#11 slot. The default is slot 0.

-i ID

Destroy keys with the given object ID.

-l label

Destroy keys with the given label.

-p PIN

Specify the PIN for the device. If no PIN is provided on the command line, pkcs11-destroy will prompt for it.

-w seconds

Specify how long to pause before carrying out key destruction. The default is five seconds. If set to 0, destruction will be immediate.

SEE ALSO

pkcs11-keygen(8) , pkcs11-list(8) , pkcs11-tokens(8)

bind9-9.11.3+dfsg/bin/pkcs11/pkcs11-keygen.8000066400000000000000000000076431325250447100200730ustar00rootroot00000000000000.\" Copyright (C) 2009, 2014-2017 Internet Systems Consortium, Inc. ("ISC") .\" .\" This Source Code Form is subject to the terms of the Mozilla Public .\" License, v. 2.0. If a copy of the MPL was not distributed with this .\" file, You can obtain one at http://mozilla.org/MPL/2.0/. .\" .hy 0 .ad l '\" t .\" Title: pkcs11-keygen .\" Author: .\" Generator: DocBook XSL Stylesheets v1.78.1 .\" Date: 2014-01-15 .\" Manual: BIND9 .\" Source: ISC .\" Language: English .\" .TH "PKCS11\-KEYGEN" "8" "2014\-01\-15" "ISC" "BIND9" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" pkcs11-keygen \- generate keys on a PKCS#11 device .SH "SYNOPSIS" .HP \w'\fBpkcs11\-keygen\fR\ 'u \fBpkcs11\-keygen\fR {\-a\ \fIalgorithm\fR} [\fB\-b\ \fR\fB\fIkeysize\fR\fR] [\fB\-e\fR] [\fB\-i\ \fR\fB\fIid\fR\fR] [\fB\-m\ \fR\fB\fImodule\fR\fR] [\fB\-P\fR] [\fB\-p\ \fR\fB\fIPIN\fR\fR] [\fB\-q\fR] [\fB\-S\fR] [\fB\-s\ \fR\fB\fIslot\fR\fR] {label} .SH "DESCRIPTION" .PP \fBpkcs11\-keygen\fR causes a PKCS#11 device to generate a new key pair with the given \fBlabel\fR (which must be unique) and with \fBkeysize\fR bits of prime\&. .SH "ARGUMENTS" .PP \-a \fIalgorithm\fR .RS 4 Specify the key algorithm class: Supported classes are RSA, DSA, DH, ECC and ECX\&. In addition to these strings, the \fBalgorithm\fR can be specified as a DNSSEC signing algorithm that will be used with this key; for example, NSEC3RSASHA1 maps to RSA, ECDSAP256SHA256 maps to ECC, and ED25519 to ECX\&. The default class is "RSA"\&. .RE .PP \-b \fIkeysize\fR .RS 4 Create the key pair with \fBkeysize\fR bits of prime\&. For ECC keys, the only valid values are 256 and 384, and the default is 256\&. For ECX kyes, the only valid values are 256 and 456, and the default is 256\&. .RE .PP \-e .RS 4 For RSA keys only, use a large exponent\&. .RE .PP \-i \fIid\fR .RS 4 Create key objects with id\&. The id is either an unsigned short 2 byte or an unsigned long 4 byte number\&. .RE .PP \-m \fImodule\fR .RS 4 Specify the PKCS#11 provider module\&. This must be the full path to a shared library object implementing the PKCS#11 API for the device\&. .RE .PP \-P .RS 4 Set the new private key to be non\-sensitive and extractable\&. The allows the private key data to be read from the PKCS#11 device\&. The default is for private keys to be sensitive and non\-extractable\&. .RE .PP \-p \fIPIN\fR .RS 4 Specify the PIN for the device\&. If no PIN is provided on the command line, \fBpkcs11\-keygen\fR will prompt for it\&. .RE .PP \-q .RS 4 Quiet mode: suppress unnecessary output\&. .RE .PP \-S .RS 4 For Diffie\-Hellman (DH) keys only, use a special prime of 768, 1024 or 1536 bit size and base (aka generator) 2\&. If not specified, bit size will default to 1024\&. .RE .PP \-s \fIslot\fR .RS 4 Open the session with the given PKCS#11 slot\&. The default is slot 0\&. .RE .SH "SEE ALSO" .PP \fBpkcs11-destroy\fR(8), \fBpkcs11-list\fR(8), \fBpkcs11-tokens\fR(8), \fBdnssec-keyfromlabel\fR(8) .SH "AUTHOR" .PP \fBInternet Systems Consortium, Inc\&.\fR .SH "COPYRIGHT" .br Copyright \(co 2009, 2014-2017 Internet Systems Consortium, Inc. ("ISC") .br bind9-9.11.3+dfsg/bin/pkcs11/pkcs11-keygen.c000066400000000000000000000466511325250447100201500ustar00rootroot00000000000000/* * Copyright (C) 2009, 2012, 2015 Internet Systems Consortium, Inc. ("ISC") * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* * Portions copyright (c) 2008 Nominet UK. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* pkcs11-keygen - PKCS#11 key generator * * Create a key in the keystore of an HSM * * The calculation of key tag is left to the script * that converts the key into a DNSKEY RR and inserts * it into a zone file. * * usage: * pkcs11-keygen [-P] [-m module] [-s slot] [-e] [-b keysize] * [-i id] [-p pin] -l label * */ /*! \file */ #include #include #include #include #include #include #include #include #include #include #include #include #include #define WANT_DH_PRIMES #define WANT_ECC_CURVES #include #include #if !(defined(HAVE_GETPASSPHRASE) || (defined (__SVR4) && defined (__sun))) #define getpassphrase(x) getpass(x) #endif /* Define static key template values */ static CK_BBOOL truevalue = TRUE; static CK_BBOOL falsevalue = FALSE; /* Key class: RSA, ECC, ECX, DSA, DH, or unknown */ typedef enum { key_unknown, key_rsa, key_dsa, key_dh, key_ecc, key_ecx } key_class_t; /* * Private key template: usable for most key classes without * modificaton; override CKA_SIGN with CKA_DERIVE for DH */ #define PRIVATE_LABEL 0 #define PRIVATE_SIGN 1 #define PRIVATE_DERIVE 1 #define PRIVATE_TOKEN 2 #define PRIVATE_PRIVATE 3 #define PRIVATE_SENSITIVE 4 #define PRIVATE_EXTRACTABLE 5 #define PRIVATE_ID 6 #define PRIVATE_ATTRS 7 static CK_ATTRIBUTE private_template[] = { {CKA_LABEL, NULL_PTR, 0}, {CKA_SIGN, &truevalue, sizeof(truevalue)}, {CKA_TOKEN, &truevalue, sizeof(truevalue)}, {CKA_PRIVATE, &truevalue, sizeof(truevalue)}, {CKA_SENSITIVE, &truevalue, sizeof(truevalue)}, {CKA_EXTRACTABLE, &falsevalue, sizeof(falsevalue)}, {CKA_ID, NULL_PTR, 0} }; /* * Public key template for RSA keys */ #define RSA_LABEL 0 #define RSA_VERIFY 1 #define RSA_TOKEN 2 #define RSA_PRIVATE 3 #define RSA_MODULUS_BITS 4 #define RSA_PUBLIC_EXPONENT 5 #define RSA_ID 6 #define RSA_ATTRS 7 static CK_ATTRIBUTE rsa_template[] = { {CKA_LABEL, NULL_PTR, 0}, {CKA_VERIFY, &truevalue, sizeof(truevalue)}, {CKA_TOKEN, &truevalue, sizeof(truevalue)}, {CKA_PRIVATE, &falsevalue, sizeof(falsevalue)}, {CKA_MODULUS_BITS, NULL_PTR, 0}, {CKA_PUBLIC_EXPONENT, NULL_PTR, 0}, {CKA_ID, NULL_PTR, 0} }; /* * Public key template for ECC/ECX keys */ #define ECC_LABEL 0 #define ECC_VERIFY 1 #define ECC_TOKEN 2 #define ECC_PRIVATE 3 #define ECC_PARAMS 4 #define ECC_ID 5 #define ECC_ATTRS 6 static CK_ATTRIBUTE ecc_template[] = { {CKA_LABEL, NULL_PTR, 0}, {CKA_VERIFY, &truevalue, sizeof(truevalue)}, {CKA_TOKEN, &truevalue, sizeof(truevalue)}, {CKA_PRIVATE, &falsevalue, sizeof(falsevalue)}, {CKA_EC_PARAMS, NULL_PTR, 0}, {CKA_ID, NULL_PTR, 0} }; /* * Public key template for DSA keys */ #define DSA_LABEL 0 #define DSA_VERIFY 1 #define DSA_TOKEN 2 #define DSA_PRIVATE 3 #define DSA_PRIME 4 #define DSA_SUBPRIME 5 #define DSA_BASE 6 #define DSA_ID 7 #define DSA_ATTRS 8 static CK_ATTRIBUTE dsa_template[] = { {CKA_LABEL, NULL_PTR, 0}, {CKA_VERIFY, &truevalue, sizeof(truevalue)}, {CKA_TOKEN, &truevalue, sizeof(truevalue)}, {CKA_PRIVATE, &falsevalue, sizeof(falsevalue)}, {CKA_PRIME, NULL_PTR, 0}, {CKA_SUBPRIME, NULL_PTR, 0}, {CKA_BASE, NULL_PTR, 0}, {CKA_ID, NULL_PTR, 0} }; #define DSA_PARAM_PRIME 0 #define DSA_PARAM_SUBPRIME 1 #define DSA_PARAM_BASE 2 #define DSA_PARAM_ATTRS 3 static CK_ATTRIBUTE dsa_param_template[] = { {CKA_PRIME, NULL_PTR, 0}, {CKA_SUBPRIME, NULL_PTR, 0}, {CKA_BASE, NULL_PTR, 0}, }; #define DSA_DOMAIN_PRIMEBITS 0 #define DSA_DOMAIN_PRIVATE 1 #define DSA_DOMAIN_ATTRS 2 static CK_ATTRIBUTE dsa_domain_template[] = { {CKA_PRIME_BITS, NULL_PTR, 0}, {CKA_PRIVATE, &falsevalue, sizeof(falsevalue)}, }; /* * Public key template for DH keys */ #define DH_LABEL 0 #define DH_VERIFY 1 #define DH_TOKEN 2 #define DH_PRIVATE 3 #define DH_PRIME 4 #define DH_BASE 5 #define DH_ID 6 #define DH_ATTRS 7 static CK_ATTRIBUTE dh_template[] = { {CKA_LABEL, NULL_PTR, 0}, {CKA_VERIFY, &truevalue, sizeof(truevalue)}, {CKA_TOKEN, &truevalue, sizeof(truevalue)}, {CKA_PRIVATE, &falsevalue, sizeof(falsevalue)}, {CKA_PRIME, NULL_PTR, 0}, {CKA_BASE, NULL_PTR, 0}, {CKA_ID, NULL_PTR, 0} }; #define DH_PARAM_PRIME 0 #define DH_PARAM_BASE 1 #define DH_PARAM_ATTRS 2 static CK_ATTRIBUTE dh_param_template[] = { {CKA_PRIME, NULL_PTR, 0}, {CKA_BASE, NULL_PTR, 0}, }; #define DH_DOMAIN_PRIMEBITS 0 #define DH_DOMAIN_ATTRS 1 static CK_ATTRIBUTE dh_domain_template[] = { {CKA_PRIME_BITS, NULL_PTR, 0}, }; /* * Convert from text to key class. Accepts the names of DNSSEC * signing algorithms, so e.g., ECDSAP256SHA256 maps to ECC and * NSEC3RSASHA1 maps to RSA. */ static key_class_t keyclass_fromtext(const char *name) { if (name == NULL) return (key_unknown); if (strncasecmp(name, "rsa", 3) == 0 || strncasecmp(name, "nsec3rsa", 8) == 0) return (key_rsa); else if (strncasecmp(name, "dsa", 3) == 0 || strncasecmp(name, "nsec3dsa", 8) == 0) return (key_dsa); else if (strcasecmp(name, "dh") == 0) return (key_dh); else if (strncasecmp(name, "ecc", 3) == 0 || strncasecmp(name, "ecdsa", 5) == 0) return (key_ecc); else if (strncasecmp(name, "ecx", 3) == 0 || strncasecmp(name, "ed", 2) == 0) return (key_ecx); else return (key_unknown); } static void usage(void) { fprintf(stderr, "Usage:\n" "\tpkcs11-keygen -a algorithm -b keysize -l label\n" "\t [-P] [-m module] " "[-s slot] [-e] [-S] [-i id] [-p PIN]\n"); exit(2); } int main(int argc, char *argv[]) { isc_result_t result; CK_RV rv; CK_SLOT_ID slot = 0; CK_MECHANISM mech, dpmech; CK_SESSION_HANDLE hSession; char *lib_name = NULL; char *pin = NULL; CK_ULONG bits = 0; CK_CHAR *label = NULL; CK_OBJECT_HANDLE privatekey, publickey, domainparams; CK_BYTE exponent[5]; CK_ULONG expsize = 0; pk11_context_t pctx; int error = 0; int c, errflg = 0; int hide = 1, special = 0, quiet = 0; int idlen = 0, id_offset = 0; unsigned int i; unsigned long id = 0; CK_BYTE idbuf[4]; CK_ULONG ulObjectCount; CK_ATTRIBUTE search_template[] = { {CKA_LABEL, NULL_PTR, 0} }; CK_ATTRIBUTE *public_template = NULL; CK_ATTRIBUTE *domain_template = NULL; CK_ATTRIBUTE *param_template = NULL; CK_ULONG public_attrcnt = 0, private_attrcnt = PRIVATE_ATTRS; CK_ULONG domain_attrcnt = 0, param_attrcnt = 0; key_class_t keyclass = key_rsa; pk11_optype_t op_type = OP_ANY; #define OPTIONS ":a:b:ei:l:m:Pp:qSs:" while ((c = isc_commandline_parse(argc, argv, OPTIONS)) != -1) { switch (c) { case 'a': keyclass = keyclass_fromtext(isc_commandline_argument); break; case 'P': hide = 0; break; case 'm': lib_name = isc_commandline_argument; break; case 's': slot = atoi(isc_commandline_argument); break; case 'e': expsize = 5; break; case 'b': bits = atoi(isc_commandline_argument); break; case 'l': /* -l option is retained for backward compatibility * */ label = (CK_CHAR *)isc_commandline_argument; break; case 'i': id = strtoul(isc_commandline_argument, NULL, 0); idlen = 4; break; case 'p': pin = isc_commandline_argument; break; case 'q': quiet = 1; break; case 'S': special = 1; break; case ':': fprintf(stderr, "Option -%c requires an operand\n", isc_commandline_option); errflg++; break; case '?': default: fprintf(stderr, "Unrecognised option: -%c\n", isc_commandline_option); errflg++; } } if (label == NULL && isc_commandline_index < argc) label = (CK_CHAR *)argv[isc_commandline_index]; if (errflg || (label == NULL)) usage(); if (expsize != 0 && keyclass != key_rsa) { fprintf(stderr, "The -e option is only compatible " "with RSA key generation\n"); exit(2); } if (special != 0 && keyclass != key_dh) { fprintf(stderr, "The -S option is only compatible " "with Diffie-Hellman key generation\n"); exit(2); } switch (keyclass) { case key_rsa: op_type = OP_RSA; if (expsize == 0) expsize = 3; if (bits == 0) usage(); mech.mechanism = CKM_RSA_PKCS_KEY_PAIR_GEN; mech.pParameter = NULL; mech.ulParameterLen = 0; public_template = rsa_template; public_attrcnt = RSA_ATTRS; id_offset = RSA_ID; /* Set public exponent to F4 or F5 */ exponent[0] = 0x01; exponent[1] = 0x00; if (expsize == 3) exponent[2] = 0x01; else { exponent[2] = 0x00; exponent[3] = 0x00; exponent[4] = 0x01; } public_template[RSA_MODULUS_BITS].pValue = &bits; public_template[RSA_MODULUS_BITS].ulValueLen = sizeof(bits); public_template[RSA_PUBLIC_EXPONENT].pValue = &exponent; public_template[RSA_PUBLIC_EXPONENT].ulValueLen = expsize; break; case key_ecc: op_type = OP_EC; if (bits == 0) bits = 256; else if (bits != 256 && bits != 384) { fprintf(stderr, "ECC keys only support bit sizes of " "256 and 384\n"); exit(2); } mech.mechanism = CKM_EC_KEY_PAIR_GEN; mech.pParameter = NULL; mech.ulParameterLen = 0; public_template = ecc_template; public_attrcnt = ECC_ATTRS; id_offset = ECC_ID; if (bits == 256) { public_template[4].pValue = pk11_ecc_prime256v1; public_template[4].ulValueLen = sizeof(pk11_ecc_prime256v1); } else { public_template[4].pValue = pk11_ecc_secp384r1; public_template[4].ulValueLen = sizeof(pk11_ecc_secp384r1); } break; case key_ecx: #ifndef CKM_EDDSA_KEY_PAIR_GEN fprintf(stderr, "CKM_EDDSA_KEY_PAIR_GEN is not defined\n"); usage(); #endif op_type = OP_EC; if (bits == 0) bits = 256; else if (bits != 256 && bits != 456) { fprintf(stderr, "ECX keys only support bit sizes of " "256 and 456\n"); exit(2); } mech.mechanism = CKM_EDDSA_KEY_PAIR_GEN; mech.pParameter = NULL; mech.ulParameterLen = 0; public_template = ecc_template; public_attrcnt = ECC_ATTRS; id_offset = ECC_ID; if (bits == 256) { public_template[4].pValue = pk11_ecc_ed25519; public_template[4].ulValueLen = sizeof(pk11_ecc_ed25519); } else { public_template[4].pValue = pk11_ecc_ed448; public_template[4].ulValueLen = sizeof(pk11_ecc_ed448); } break; case key_dsa: op_type = OP_DSA; if (bits == 0) usage(); dpmech.mechanism = CKM_DSA_PARAMETER_GEN; dpmech.pParameter = NULL; dpmech.ulParameterLen = 0; mech.mechanism = CKM_DSA_KEY_PAIR_GEN; mech.pParameter = NULL; mech.ulParameterLen = 0; public_template = dsa_template; public_attrcnt = DSA_ATTRS; id_offset = DSA_ID; domain_template = dsa_domain_template; domain_attrcnt = DSA_DOMAIN_ATTRS; param_template = dsa_param_template; param_attrcnt = DSA_PARAM_ATTRS; domain_template[DSA_DOMAIN_PRIMEBITS].pValue = &bits; domain_template[DSA_DOMAIN_PRIMEBITS].ulValueLen = sizeof(bits); break; case key_dh: op_type = OP_DH; if (special && bits == 0) bits = 1024; else if (special && bits != 768 && bits != 1024 && bits != 1536) { fprintf(stderr, "When using the special prime (-S) " "option, only key sizes of\n" "768, 1024 or 1536 are supported.\n"); exit(2); } else if (bits == 0) usage(); dpmech.mechanism = CKM_DH_PKCS_PARAMETER_GEN; dpmech.pParameter = NULL; dpmech.ulParameterLen = 0; mech.mechanism = CKM_DH_PKCS_KEY_PAIR_GEN; mech.pParameter = NULL; mech.ulParameterLen = 0; /* Override CKA_SIGN attribute */ private_template[PRIVATE_DERIVE].type = CKA_DERIVE; public_template = dh_template; public_attrcnt = DH_ATTRS; id_offset = DH_ID; domain_template = dh_domain_template; domain_attrcnt = DH_DOMAIN_ATTRS; param_template = dh_param_template; param_attrcnt = DH_PARAM_ATTRS; domain_template[DH_DOMAIN_PRIMEBITS].pValue = &bits; domain_template[DH_DOMAIN_PRIMEBITS].ulValueLen = sizeof(bits); break; case key_unknown: usage(); } search_template[0].pValue = label; search_template[0].ulValueLen = strlen((char *)label); public_template[0].pValue = label; public_template[0].ulValueLen = strlen((char *)label); private_template[0].pValue = label; private_template[0].ulValueLen = strlen((char *)label); if (idlen == 0) { public_attrcnt--; private_attrcnt--; } else { if (id <= 0xffff) { idlen = 2; idbuf[0] = (CK_BYTE)(id >> 8); idbuf[1] = (CK_BYTE)id; } else { idbuf[0] = (CK_BYTE)(id >> 24); idbuf[1] = (CK_BYTE)(id >> 16); idbuf[2] = (CK_BYTE)(id >> 8); idbuf[3] = (CK_BYTE)id; } public_template[id_offset].pValue = idbuf; public_template[id_offset].ulValueLen = idlen; private_template[PRIVATE_ID].pValue = idbuf; private_template[PRIVATE_ID].ulValueLen = idlen; } pk11_result_register(); /* Initialize the CRYPTOKI library */ if (lib_name != NULL) pk11_set_lib_name(lib_name); if (pin == NULL) pin = getpassphrase("Enter Pin: "); result = pk11_get_session(&pctx, op_type, ISC_FALSE, ISC_TRUE, ISC_TRUE, (const char *) pin, slot); if (result == PK11_R_NORANDOMSERVICE || result == PK11_R_NODIGESTSERVICE || result == PK11_R_NOAESSERVICE) { fprintf(stderr, "Warning: %s\n", isc_result_totext(result)); fprintf(stderr, "This HSM will not work with BIND 9 " "using native PKCS#11.\n"); } else if (result != ISC_R_SUCCESS) { fprintf(stderr, "Unrecoverable error initializing " "PKCS#11: %s\n", isc_result_totext(result)); exit(1); } memset(pin, 0, strlen(pin)); hSession = pctx.session; /* check if a key with the same id already exists */ rv = pkcs_C_FindObjectsInit(hSession, search_template, 1); if (rv != CKR_OK) { fprintf(stderr, "C_FindObjectsInit: Error = 0x%.8lX\n", rv); error = 1; goto exit_session; } rv = pkcs_C_FindObjects(hSession, &privatekey, 1, &ulObjectCount); if (rv != CKR_OK) { fprintf(stderr, "C_FindObjects: Error = 0x%.8lX\n", rv); error = 1; goto exit_search; } if (ulObjectCount != 0) { fprintf(stderr, "Key already exists.\n"); error = 1; goto exit_search; } /* Set attributes if the key is not to be hidden */ if (!hide) { private_template[4].pValue = &falsevalue; private_template[5].pValue = &truevalue; } if (keyclass == key_rsa || keyclass == key_ecc || keyclass == key_ecx) goto generate_keys; /* * Special setup for Diffie-Hellman keys */ if (special != 0) { public_template[DH_BASE].pValue = pk11_dh_bn2; public_template[DH_BASE].ulValueLen = sizeof(pk11_dh_bn2); if (bits == 768) { public_template[DH_PRIME].pValue = pk11_dh_bn768; public_template[DH_PRIME].ulValueLen = sizeof(pk11_dh_bn768); } else if (bits == 1024) { public_template[DH_PRIME].pValue = pk11_dh_bn1024; public_template[DH_PRIME].ulValueLen = sizeof(pk11_dh_bn1024); } else { public_template[DH_PRIME].pValue = pk11_dh_bn1536; public_template[DH_PRIME].ulValueLen = sizeof(pk11_dh_bn1536); } param_attrcnt = 0; goto generate_keys; } /* Generate Domain parameters */ rv = pkcs_C_GenerateKey(hSession, &dpmech, domain_template, domain_attrcnt, &domainparams); if (rv != CKR_OK) { fprintf(stderr, "C_GenerateKey: Error = 0x%.8lX\n", rv); error = 1; goto exit_search; } /* Get Domain parameters */ rv = pkcs_C_GetAttributeValue(hSession, domainparams, param_template, param_attrcnt); if (rv != CKR_OK) { fprintf(stderr, "C_GetAttributeValue0: Error = 0x%.8lX\n", rv); error = 1; goto exit_domain; } /* Allocate space for parameter attributes */ for (i = 0; i < param_attrcnt; i++) param_template[i].pValue = malloc(param_template[i].ulValueLen); rv = pkcs_C_GetAttributeValue(hSession, domainparams, dsa_param_template, DSA_PARAM_ATTRS); if (rv != CKR_OK) { fprintf(stderr, "C_GetAttributeValue1: Error = 0x%.8lX\n", rv); error = 1; goto exit_params; } switch (keyclass) { case key_dsa: public_template[DSA_PRIME].pValue = param_template[DSA_PARAM_PRIME].pValue; public_template[DSA_PRIME].ulValueLen = param_template[DSA_PARAM_PRIME].ulValueLen; public_template[DSA_SUBPRIME].pValue = param_template[DSA_PARAM_SUBPRIME].pValue; public_template[DSA_SUBPRIME].ulValueLen = param_template[DSA_PARAM_SUBPRIME].ulValueLen; public_template[DSA_BASE].pValue = param_template[DSA_PARAM_BASE].pValue; public_template[DSA_BASE].ulValueLen = param_template[DSA_PARAM_BASE].ulValueLen; break; case key_dh: public_template[DH_PRIME].pValue = param_template[DH_PARAM_PRIME].pValue; public_template[DH_PRIME].ulValueLen = param_template[DH_PARAM_PRIME].ulValueLen; public_template[DH_BASE].pValue = param_template[DH_PARAM_BASE].pValue; public_template[DH_BASE].ulValueLen = param_template[DH_PARAM_BASE].ulValueLen; default: break; } generate_keys: /* Generate Key pair for signing/verifying */ rv = pkcs_C_GenerateKeyPair(hSession, &mech, public_template, public_attrcnt, private_template, private_attrcnt, &publickey, &privatekey); if (rv != CKR_OK) { fprintf(stderr, "C_GenerateKeyPair: Error = 0x%.8lX\n", rv); error = 1; } else if (!quiet) printf("Key pair generation complete.\n"); exit_params: /* Free parameter attributes */ if (keyclass == key_dsa || keyclass == key_dh) for (i = 0; i < param_attrcnt; i++) free(param_template[i].pValue); exit_domain: /* Destroy domain parameters */ if (keyclass == key_dsa || (keyclass == key_dh && !special)) { rv = pkcs_C_DestroyObject(hSession, domainparams); if (rv != CKR_OK) { fprintf(stderr, "C_DestroyObject: Error = 0x%.8lX\n", rv); error = 1; } } exit_search: rv = pkcs_C_FindObjectsFinal(hSession); if (rv != CKR_OK) { fprintf(stderr, "C_FindObjectsFinal: Error = 0x%.8lX\n", rv); error = 1; } exit_session: pk11_return_session(&pctx); (void) pk11_finalize(); exit(error); } bind9-9.11.3+dfsg/bin/pkcs11/pkcs11-keygen.docbook000066400000000000000000000152361325250447100213410ustar00rootroot00000000000000 2014-01-15 ISC Internet Systems Consortium, Inc. pkcs11-keygen 8 BIND9 pkcs11-keygen generate keys on a PKCS#11 device 2009 2014 2015 2016 2017 Internet Systems Consortium, Inc. ("ISC") pkcs11-keygen -a algorithm label DESCRIPTION pkcs11-keygen causes a PKCS#11 device to generate a new key pair with the given (which must be unique) and with bits of prime. ARGUMENTS -a algorithm Specify the key algorithm class: Supported classes are RSA, DSA, DH, ECC and ECX. In addition to these strings, the can be specified as a DNSSEC signing algorithm that will be used with this key; for example, NSEC3RSASHA1 maps to RSA, ECDSAP256SHA256 maps to ECC, and ED25519 to ECX. The default class is "RSA". -b keysize Create the key pair with bits of prime. For ECC keys, the only valid values are 256 and 384, and the default is 256. For ECX kyes, the only valid values are 256 and 456, and the default is 256. -e For RSA keys only, use a large exponent. -i id Create key objects with id. The id is either an unsigned short 2 byte or an unsigned long 4 byte number. -m module Specify the PKCS#11 provider module. This must be the full path to a shared library object implementing the PKCS#11 API for the device. -P Set the new private key to be non-sensitive and extractable. The allows the private key data to be read from the PKCS#11 device. The default is for private keys to be sensitive and non-extractable. -p PIN Specify the PIN for the device. If no PIN is provided on the command line, pkcs11-keygen will prompt for it. -q Quiet mode: suppress unnecessary output. -S For Diffie-Hellman (DH) keys only, use a special prime of 768, 1024 or 1536 bit size and base (aka generator) 2. If not specified, bit size will default to 1024. -s slot Open the session with the given PKCS#11 slot. The default is slot 0. SEE ALSO pkcs11-destroy8 , pkcs11-list8 , pkcs11-tokens8 , dnssec-keyfromlabel8 bind9-9.11.3+dfsg/bin/pkcs11/pkcs11-keygen.html000066400000000000000000000132601325250447100206600ustar00rootroot00000000000000 pkcs11-keygen

Name

pkcs11-keygen — generate keys on a PKCS#11 device

Synopsis

pkcs11-keygen {-a algorithm} [-b keysize] [-e] [-i id] [-m module] [-P] [-p PIN] [-q] [-S] [-s slot] {label}

DESCRIPTION

pkcs11-keygen causes a PKCS#11 device to generate a new key pair with the given label (which must be unique) and with keysize bits of prime.

ARGUMENTS

-a algorithm

Specify the key algorithm class: Supported classes are RSA, DSA, DH, ECC and ECX. In addition to these strings, the algorithm can be specified as a DNSSEC signing algorithm that will be used with this key; for example, NSEC3RSASHA1 maps to RSA, ECDSAP256SHA256 maps to ECC, and ED25519 to ECX. The default class is "RSA".

-b keysize

Create the key pair with keysize bits of prime. For ECC keys, the only valid values are 256 and 384, and the default is 256. For ECX kyes, the only valid values are 256 and 456, and the default is 256.

-e

For RSA keys only, use a large exponent.

-i id

Create key objects with id. The id is either an unsigned short 2 byte or an unsigned long 4 byte number.

-m module

Specify the PKCS#11 provider module. This must be the full path to a shared library object implementing the PKCS#11 API for the device.

-P

Set the new private key to be non-sensitive and extractable. The allows the private key data to be read from the PKCS#11 device. The default is for private keys to be sensitive and non-extractable.

-p PIN

Specify the PIN for the device. If no PIN is provided on the command line, pkcs11-keygen will prompt for it.

-q

Quiet mode: suppress unnecessary output.

-S

For Diffie-Hellman (DH) keys only, use a special prime of 768, 1024 or 1536 bit size and base (aka generator) 2. If not specified, bit size will default to 1024.

-s slot

Open the session with the given PKCS#11 slot. The default is slot 0.

SEE ALSO

pkcs11-destroy(8) , pkcs11-list(8) , pkcs11-tokens(8) , dnssec-keyfromlabel(8)

bind9-9.11.3+dfsg/bin/pkcs11/pkcs11-list.8000066400000000000000000000056151325250447100175610ustar00rootroot00000000000000.\" Copyright (C) 2009, 2014-2016 Internet Systems Consortium, Inc. ("ISC") .\" .\" This Source Code Form is subject to the terms of the Mozilla Public .\" License, v. 2.0. If a copy of the MPL was not distributed with this .\" file, You can obtain one at http://mozilla.org/MPL/2.0/. .\" .hy 0 .ad l '\" t .\" Title: pkcs11-list .\" Author: .\" Generator: DocBook XSL Stylesheets v1.78.1 .\" Date: 2009-10-05 .\" Manual: BIND9 .\" Source: ISC .\" Language: English .\" .TH "PKCS11\-LIST" "8" "2009\-10\-05" "ISC" "BIND9" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" pkcs11-list \- list PKCS#11 objects .SH "SYNOPSIS" .HP \w'\fBpkcs11\-list\fR\ 'u \fBpkcs11\-list\fR [\fB\-P\fR] [\fB\-m\ \fR\fB\fImodule\fR\fR] [\fB\-s\ \fR\fB\fIslot\fR\fR] [\-i\ \fIID\fR] [\-l\ \fIlabel\fR] [\fB\-p\ \fR\fB\fIPIN\fR\fR] .SH "DESCRIPTION" .PP \fBpkcs11\-list\fR lists the PKCS#11 objects with \fBID\fR or \fBlabel\fR or by default all objects\&. The object class, label, and ID are displayed for all keys\&. For private or secret keys, the extractability attribute is also displayed, as either true, false, or never\&. .SH "ARGUMENTS" .PP \-P .RS 4 List only the public objects\&. (Note that on some PKCS#11 devices, all objects are private\&.) .RE .PP \-m \fImodule\fR .RS 4 Specify the PKCS#11 provider module\&. This must be the full path to a shared library object implementing the PKCS#11 API for the device\&. .RE .PP \-s \fIslot\fR .RS 4 Open the session with the given PKCS#11 slot\&. The default is slot 0\&. .RE .PP \-i \fIID\fR .RS 4 List only key objects with the given object ID\&. .RE .PP \-l \fIlabel\fR .RS 4 List only key objects with the given label\&. .RE .PP \-p \fIPIN\fR .RS 4 Specify the PIN for the device\&. If no PIN is provided on the command line, \fBpkcs11\-list\fR will prompt for it\&. .RE .SH "SEE ALSO" .PP \fBpkcs11-destroy\fR(8), \fBpkcs11-keygen\fR(8), \fBpkcs11-tokens\fR(8) .SH "AUTHOR" .PP \fBInternet Systems Consortium, Inc\&.\fR .SH "COPYRIGHT" .br Copyright \(co 2009, 2014-2016 Internet Systems Consortium, Inc. ("ISC") .br bind9-9.11.3+dfsg/bin/pkcs11/pkcs11-list.c000066400000000000000000000161371325250447100176350ustar00rootroot00000000000000/* * Copyright (C) 2009, 2014-2016 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * Portions copyright (c) 2008 Nominet UK. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* $Id: pkcs11-list.c,v 1.7 2009/10/26 23:36:53 each Exp $ */ /* pkcs11-list [-P] [-m module] [-s slot] [-i $id | -l $label] [-p $pin] */ /*! \file */ #include #include #include #include #include #include #include #include #include #include #include #include #include #if !(defined(HAVE_GETPASSPHRASE) || (defined (__SVR4) && defined (__sun))) #define getpassphrase(x) getpass(x) #endif int main(int argc, char *argv[]) { isc_result_t result; CK_RV rv; CK_SLOT_ID slot = 0; CK_SESSION_HANDLE hSession; CK_BYTE attr_id[2]; CK_OBJECT_HANDLE akey[50]; pk11_context_t pctx; char *lib_name = NULL; char *label = NULL; char *pin = NULL; isc_boolean_t error = ISC_FALSE, logon = ISC_TRUE, all = ISC_FALSE; unsigned int i = 0, id = 0; int c, errflg = 0; CK_ULONG ulObjectCount; CK_ATTRIBUTE search_template[] = { {CKA_ID, &attr_id, sizeof(attr_id)} }; while ((c = isc_commandline_parse(argc, argv, ":m:s:i:l:p:P")) != -1) { switch (c) { case 'P': logon = ISC_FALSE; break; case 'm': lib_name = isc_commandline_argument; break; case 's': slot = atoi(isc_commandline_argument); break; case 'i': id = atoi(isc_commandline_argument); id &= 0xffff; break; case 'l': label = isc_commandline_argument; break; case 'p': pin = isc_commandline_argument; break; case ':': fprintf(stderr, "Option -%c requires an operand\n", isc_commandline_option); errflg++; break; case '?': default: fprintf(stderr, "Unrecognised option: -%c\n", isc_commandline_option); errflg++; } } if (errflg) { fprintf(stderr, "Usage:\n"); fprintf(stderr, "\tpkcs11-list [-P] [-m module] [-s slot] " "[-i id | -l label] [-p pin]\n"); exit(1); } if (!id && (label == NULL)) all = ISC_TRUE; if (slot) printf("slot %lu\n", slot); if (id) { printf("id %i\n", id); attr_id[0] = (id >> 8) & 0xff; attr_id[1] = id & 0xff; } else if (label != NULL) { printf("label %s\n", label); search_template[0].type = CKA_LABEL; search_template[0].pValue = label; search_template[0].ulValueLen = strlen(label); } pk11_result_register(); /* Initialize the CRYPTOKI library */ if (lib_name != NULL) pk11_set_lib_name(lib_name); if (logon && pin == NULL) pin = getpassphrase("Enter Pin: "); result = pk11_get_session(&pctx, OP_ANY, ISC_FALSE, ISC_FALSE, logon, pin, slot); if (result == PK11_R_NORANDOMSERVICE || result == PK11_R_NODIGESTSERVICE || result == PK11_R_NOAESSERVICE) { fprintf(stderr, "Warning: %s\n", isc_result_totext(result)); fprintf(stderr, "This HSM will not work with BIND 9 " "using native PKCS#11.\n"); } else if (result != ISC_R_SUCCESS) { fprintf(stderr, "Unrecoverable error initializing " "PKCS#11: %s\n", isc_result_totext(result)); fprintf(stderr, "Unrecoverable error initializing " "PKCS#11: %s\n", isc_result_totext(result)); exit(1); } if (pin != NULL) memset(pin, 0, strlen(pin)); hSession = pctx.session; rv = pkcs_C_FindObjectsInit(hSession, search_template, all ? 0 : 1); if (rv != CKR_OK) { fprintf(stderr, "C_FindObjectsInit: Error = 0x%.8lX\n", rv); error = 1; goto exit_session; } ulObjectCount = 1; while (ulObjectCount) { rv = pkcs_C_FindObjects(hSession, akey, 50, &ulObjectCount); if (rv != CKR_OK) { fprintf(stderr, "C_FindObjects: Error = 0x%.8lX\n", rv); error = 1; goto exit_search; } for (i = 0; i < ulObjectCount; i++) { unsigned int j, len; CK_OBJECT_CLASS oclass = 0; CK_BYTE labelbuf[64 + 1]; CK_BYTE idbuf[64]; CK_BBOOL extract = TRUE; CK_BBOOL never = FALSE; CK_ATTRIBUTE template[] = { {CKA_CLASS, &oclass, sizeof(oclass)}, {CKA_LABEL, labelbuf, sizeof(labelbuf) - 1}, {CKA_ID, idbuf, sizeof(idbuf)} }; CK_ATTRIBUTE priv_template[] = { {CKA_EXTRACTABLE, &extract, sizeof(extract)}, {CKA_NEVER_EXTRACTABLE, &never, sizeof(never)} }; memset(labelbuf, 0, sizeof(labelbuf)); memset(idbuf, 0, sizeof(idbuf)); rv = pkcs_C_GetAttributeValue(hSession, akey[i], template, 3); if (rv != CKR_OK) { fprintf(stderr, "C_GetAttributeValue[%u]: " "rv = 0x%.8lX\n", i, rv); if (rv == CKR_BUFFER_TOO_SMALL) fprintf(stderr, "%u too small: %lu %lu %lu\n", i, template[0].ulValueLen, template[1].ulValueLen, template[2].ulValueLen); error = 1; continue; } len = template[2].ulValueLen; printf("object[%u]: handle %lu class %lu " "label[%lu] '%s' id[%lu] ", i, akey[i], oclass, template[1].ulValueLen, labelbuf, template[2].ulValueLen); if (len == 2) { id = (idbuf[0] << 8) & 0xff00; id |= idbuf[1] & 0xff; printf("%u", id); } else { if (len > 8) len = 8; if (len > 0) printf("0x"); for (j = 0; j < len; j++) printf("%02x", idbuf[j]); if (template[2].ulValueLen > len) printf("..."); } if ((oclass == CKO_PRIVATE_KEY || oclass == CKO_SECRET_KEY) && pkcs_C_GetAttributeValue(hSession, akey[i], priv_template, 2) == CKR_OK) { printf(" E:%s", extract ? "true" : (never ? "never" : "false")); } printf("\n"); } } exit_search: rv = pkcs_C_FindObjectsFinal(hSession); if (rv != CKR_OK) { fprintf(stderr, "C_FindObjectsFinal: Error = 0x%.8lX\n", rv); error = 1; } exit_session: pk11_return_session(&pctx); (void) pk11_finalize(); exit(error); } bind9-9.11.3+dfsg/bin/pkcs11/pkcs11-list.docbook000066400000000000000000000111231325250447100210210ustar00rootroot00000000000000 2009-10-05 ISC Internet Systems Consortium, Inc. pkcs11-list 8 BIND9 pkcs11-list list PKCS#11 objects 2009 2014 2015 2016 Internet Systems Consortium, Inc. ("ISC") pkcs11-list -i ID -l label DESCRIPTION pkcs11-list lists the PKCS#11 objects with or or by default all objects. The object class, label, and ID are displayed for all keys. For private or secret keys, the extractability attribute is also displayed, as either true, false, or never. ARGUMENTS -P List only the public objects. (Note that on some PKCS#11 devices, all objects are private.) -m module Specify the PKCS#11 provider module. This must be the full path to a shared library object implementing the PKCS#11 API for the device. -s slot Open the session with the given PKCS#11 slot. The default is slot 0. -i ID List only key objects with the given object ID. -l label List only key objects with the given label. -p PIN Specify the PIN for the device. If no PIN is provided on the command line, pkcs11-list will prompt for it. SEE ALSO pkcs11-destroy8 , pkcs11-keygen8 , pkcs11-tokens8 bind9-9.11.3+dfsg/bin/pkcs11/pkcs11-list.html000066400000000000000000000077651325250447100203660ustar00rootroot00000000000000 pkcs11-list

Name

pkcs11-list — list PKCS#11 objects

Synopsis

pkcs11-list [-P] [-m module] [-s slot] [-i ID] [-l label] [-p PIN]

DESCRIPTION

pkcs11-list lists the PKCS#11 objects with ID or label or by default all objects. The object class, label, and ID are displayed for all keys. For private or secret keys, the extractability attribute is also displayed, as either true, false, or never.

ARGUMENTS

-P

List only the public objects. (Note that on some PKCS#11 devices, all objects are private.)

-m module

Specify the PKCS#11 provider module. This must be the full path to a shared library object implementing the PKCS#11 API for the device.

-s slot

Open the session with the given PKCS#11 slot. The default is slot 0.

-i ID

List only key objects with the given object ID.

-l label

List only key objects with the given label.

-p PIN

Specify the PIN for the device. If no PIN is provided on the command line, pkcs11-list will prompt for it.

SEE ALSO

pkcs11-destroy(8) , pkcs11-keygen(8) , pkcs11-tokens(8)

bind9-9.11.3+dfsg/bin/pkcs11/pkcs11-tokens.8000066400000000000000000000043531325250447100201070ustar00rootroot00000000000000.\" Copyright (C) 2014-2016 Internet Systems Consortium, Inc. ("ISC") .\" .\" This Source Code Form is subject to the terms of the Mozilla Public .\" License, v. 2.0. If a copy of the MPL was not distributed with this .\" file, You can obtain one at http://mozilla.org/MPL/2.0/. .\" .hy 0 .ad l '\" t .\" Title: pkcs11-tokens .\" Author: .\" Generator: DocBook XSL Stylesheets v1.78.1 .\" Date: 2014-01-15 .\" Manual: BIND9 .\" Source: ISC .\" Language: English .\" .TH "PKCS11\-TOKENS" "8" "2014\-01\-15" "ISC" "BIND9" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" pkcs11-tokens \- list PKCS#11 available tokens .SH "SYNOPSIS" .HP \w'\fBpkcs11\-tokens\fR\ 'u \fBpkcs11\-tokens\fR [\fB\-m\ \fR\fB\fImodule\fR\fR] [\fB\-v\fR] .SH "DESCRIPTION" .PP \fBpkcs11\-tokens\fR lists the PKCS#11 available tokens with defaults from the slot/token scan performed at application initialization\&. .SH "ARGUMENTS" .PP \-m \fImodule\fR .RS 4 Specify the PKCS#11 provider module\&. This must be the full path to a shared library object implementing the PKCS#11 API for the device\&. .RE .PP \-v .RS 4 Make the PKCS#11 libisc initialization verbose\&. .RE .SH "SEE ALSO" .PP \fBpkcs11-destroy\fR(8), \fBpkcs11-keygen\fR(8), \fBpkcs11-list\fR(8) .SH "AUTHOR" .PP \fBInternet Systems Consortium, Inc\&.\fR .SH "COPYRIGHT" .br Copyright \(co 2014-2016 Internet Systems Consortium, Inc. ("ISC") .br bind9-9.11.3+dfsg/bin/pkcs11/pkcs11-tokens.c000066400000000000000000000043611325250447100201610ustar00rootroot00000000000000/* * Copyright (C) 2014-2016 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* $Id$ */ /* pkcs11-tokens [-m module] */ /*! \file */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include int main(int argc, char *argv[]) { isc_result_t result; char *lib_name = NULL; int c, errflg = 0; isc_mem_t *mctx = NULL; pk11_context_t pctx; while ((c = isc_commandline_parse(argc, argv, ":m:v")) != -1) { switch (c) { case 'm': lib_name = isc_commandline_argument; break; case 'v': pk11_verbose_init = ISC_TRUE; break; case ':': fprintf(stderr, "Option -%c requires an operand\n", isc_commandline_option); errflg++; break; case '?': default: fprintf(stderr, "Unrecognised option: -%c\n", isc_commandline_option); errflg++; } } if (errflg) { fprintf(stderr, "Usage:\n"); fprintf(stderr, "\tpkcs11-tokens [-v] [-m module]\n"); exit(1); } if (isc_mem_create(0, 0, &mctx) != ISC_R_SUCCESS) { fprintf(stderr, "isc_mem_create() failed\n"); exit(1); } pk11_result_register(); /* Initialize the CRYPTOKI library */ if (lib_name != NULL) pk11_set_lib_name(lib_name); result = pk11_get_session(&pctx, OP_ANY, ISC_TRUE, ISC_FALSE, ISC_FALSE, NULL, 0); if (result == PK11_R_NORANDOMSERVICE || result == PK11_R_NODIGESTSERVICE || result == PK11_R_NOAESSERVICE) { fprintf(stderr, "Warning: %s\n", isc_result_totext(result)); fprintf(stderr, "This HSM will not work with BIND 9 " "using native PKCS#11.\n\n"); } else if ((result != ISC_R_SUCCESS) && (result != ISC_R_NOTFOUND)) { fprintf(stderr, "Unrecoverable error initializing " "PKCS#11: %s\n", isc_result_totext(result)); exit(1); } pk11_dump_tokens(); if (pctx.handle != NULL) pk11_return_session(&pctx); (void) pk11_finalize(); isc_mem_destroy(&mctx); exit(0); } bind9-9.11.3+dfsg/bin/pkcs11/pkcs11-tokens.docbook000066400000000000000000000054171325250447100213620ustar00rootroot00000000000000 2014-01-15 ISC Internet Systems Consortium, Inc. pkcs11-tokens 8 BIND9 pkcs11-tokens list PKCS#11 available tokens 2014 2015 2016 Internet Systems Consortium, Inc. ("ISC") pkcs11-tokens DESCRIPTION pkcs11-tokens lists the PKCS#11 available tokens with defaults from the slot/token scan performed at application initialization. ARGUMENTS -m module Specify the PKCS#11 provider module. This must be the full path to a shared library object implementing the PKCS#11 API for the device. -v Make the PKCS#11 libisc initialization verbose. SEE ALSO pkcs11-destroy8 , pkcs11-keygen8 , pkcs11-list8 bind9-9.11.3+dfsg/bin/pkcs11/pkcs11-tokens.html000066400000000000000000000047541325250447100207110ustar00rootroot00000000000000 pkcs11-tokens

Name

pkcs11-tokens — list PKCS#11 available tokens

Synopsis

pkcs11-tokens [-m module] [-v]

DESCRIPTION

pkcs11-tokens lists the PKCS#11 available tokens with defaults from the slot/token scan performed at application initialization.

ARGUMENTS

-m module

Specify the PKCS#11 provider module. This must be the full path to a shared library object implementing the PKCS#11 API for the device.

-v

Make the PKCS#11 libisc initialization verbose.

SEE ALSO

pkcs11-destroy(8) , pkcs11-keygen(8) , pkcs11-list(8)

bind9-9.11.3+dfsg/bin/pkcs11/win32/000077500000000000000000000000001325250447100163505ustar00rootroot00000000000000bind9-9.11.3+dfsg/bin/pkcs11/win32/pk11destroy.dsp.in000066400000000000000000000105271325250447100216600ustar00rootroot00000000000000# Microsoft Developer Studio Project File - Name="pk11destroy" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "@PLATFORM@ (x86) Console Application" 0x0103 CFG=pk11destroy - @PLATFORM@ Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "pk11destroy.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "pk11destroy.mak" CFG="pk11destroy - @PLATFORM@ Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "pk11destroy - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE "pk11destroy - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "pk11destroy - @PLATFORM@ Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 @COPTX@ @COPTI@ /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c # ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../.." /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" @PK11_LIB_LOCATION@ @COPTY@ /FD /c # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console @MACHINE@ # ADD LINK32 user32.lib advapi32.lib ../../../lib/isc/win32/Release/libisc.lib /nologo /subsystem:console @MACHINE@ /out:"../../../Build/Release/pkcs11-destroy.exe" !ELSEIF "$(CFG)" == "pk11destroy - @PLATFORM@ Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /GZ /c # ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../.." /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" @PK11_LIB_LOCATION@ /FR /FD /GZ /c # SUBTRACT CPP /X @COPTY@ # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug @MACHINE@ /pdbtype:sept # ADD LINK32 user32.lib advapi32.lib ../../../lib/isc/win32/Debug/libisc.lib /nologo /subsystem:console /debug @MACHINE@ /out:"../../../Build/Debug/pkcs11-destroy.exe" /pdbtype:sept !ENDIF # Begin Target # Name "pk11destroy - @PLATFORM@ Release" # Name "pk11destroy - @PLATFORM@ Debug" # Begin Group "Source Files" # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" # Begin Source File SOURCE="..\pkcs11-destroy.c" # End Source File # End Group # Begin Group "Header Files" # PROP Default_Filter "h;hpp;hxx;hm;inl" # End Group # Begin Group "Resource Files" # PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" # End Group # End Target # End Project bind9-9.11.3+dfsg/bin/pkcs11/win32/pk11destroy.dsw000066400000000000000000000010431325250447100212530ustar00rootroot00000000000000Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "pk11destroy"=".\pk11destroy.dsp" - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### bind9-9.11.3+dfsg/bin/pkcs11/win32/pk11destroy.mak.in000066400000000000000000000176701325250447100216500ustar00rootroot00000000000000# Microsoft Developer Studio Generated NMAKE File, Based on pk11destroy.dsp !IF "$(CFG)" == "" CFG=pk11destroy - @PLATFORM@ Debug !MESSAGE No configuration specified. Defaulting to pk11destroy - @PLATFORM@ Debug. !ENDIF !IF "$(CFG)" != "pk11destroy - @PLATFORM@ Release" && "$(CFG)" != "pk11destroy - @PLATFORM@ Debug" !MESSAGE Invalid configuration "$(CFG)" specified. !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "pk11destroy.mak" CFG="pk11destroy - @PLATFORM@ Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "pk11destroy - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE "pk11destroy - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE !ERROR An invalid configuration is specified. !ENDIF !IF "$(OS)" == "Windows_NT" NULL= !ELSE NULL=nul !ENDIF !IF "$(CFG)" == "pk11destroy - @PLATFORM@ Release" _VC_MANIFEST_INC=0 _VC_MANIFEST_BASENAME=__VC80 !ELSE _VC_MANIFEST_INC=1 _VC_MANIFEST_BASENAME=__VC80.Debug !ENDIF #################################################### # Specifying name of temporary resource file used only in incremental builds: !if "$(_VC_MANIFEST_INC)" == "1" _VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res !else _VC_MANIFEST_AUTO_RES= !endif #################################################### # _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE: !if "$(_VC_MANIFEST_INC)" == "1" #MT_SPECIAL_RETURN=1090650113 #MT_SPECIAL_SWITCH=-notify_resource_update MT_SPECIAL_RETURN=0 MT_SPECIAL_SWITCH= _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \ if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \ rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \ link $** /out:$@ $(LFLAGS) !else _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1 !endif #################################################### # _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL: !if "$(_VC_MANIFEST_INC)" == "1" #MT_SPECIAL_RETURN=1090650113 #MT_SPECIAL_SWITCH=-notify_resource_update MT_SPECIAL_RETURN=0 MT_SPECIAL_SWITCH= _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \ if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \ rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \ link $** /out:$@ $(LFLAGS) !else _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2 !endif #################################################### # _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily: !if "$(_VC_MANIFEST_INC)" == "1" _VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \ $(_VC_MANIFEST_BASENAME).auto.rc \ $(_VC_MANIFEST_BASENAME).auto.manifest !else _VC_MANIFEST_CLEAN= !endif !IF "$(CFG)" == "pk11destroy - @PLATFORM@ Release" OUTDIR=.\Release INTDIR=.\Release ALL : "..\..\..\Build\Release\pkcs11-destroy.exe" CLEAN : -@erase "$(INTDIR)\pkcs11-destroy.obj" -@erase "$(INTDIR)\vc60.idb" -@erase "..\..\..\Build\Release\pkcs11-destroy.exe" -@$(_VC_MANIFEST_CLEAN) "$(OUTDIR)" : if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" CPP=cl.exe CPP_PROJ=/nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../.." /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" @PK11_LIB_LOCATION@ /Fp"$(INTDIR)\pk11destroy.pch" @COPTY@ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c .c{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .c{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << RSC=rc.exe BSC32=bscmake.exe BSC32_FLAGS=/nologo /o"$(OUTDIR)\pk11destroy.bsc" BSC32_SBRS= \ LINK32=link.exe LINK32_FLAGS=user32.lib advapi32.lib ../../../lib/isc/win32/Release/libisc.lib /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\pkcs11-destroy.pdb" @MACHINE@ /out:"../../../Build/Release/pkcs11-destroy.exe" LINK32_OBJS= "$(INTDIR)\pkcs11-destroy.obj" "..\..\..\Build\Release\pkcs11-destroy.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) $(LINK32) @<< $(LINK32_FLAGS) $(LINK32_OBJS) << $(_VC_MANIFEST_EMBED_EXE) !ELSEIF "$(CFG)" == "pk11destroy - @PLATFORM@ Debug" OUTDIR=.\Debug INTDIR=.\Debug # Begin Custom Macros OutDir=.\Debug # End Custom Macros ALL : "..\..\..\Build\Debug\pkcs11-destroy.exe" "$(OUTDIR)\pk11destroy.bsc" CLEAN : -@erase "$(INTDIR)\pkcs11-destroy.obj" -@erase "$(INTDIR)\pkcs11-destroy.sbr" -@erase "$(INTDIR)\vc60.idb" -@erase "$(INTDIR)\vc60.pdb" -@erase "$(OUTDIR)\pkcs11-destroy.pdb" -@erase "$(OUTDIR)\pk11destroy.bsc" -@erase "..\..\..\Build\Debug\pkcs11-destroy.exe" -@erase "..\..\..\Build\Debug\pkcs11-destroy.ilk" -@$(_VC_MANIFEST_CLEAN) "$(OUTDIR)" : if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" CPP=cl.exe CPP_PROJ=/nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../.." /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" @PK11_LIB_LOCATION@ /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c .c{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .c{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << RSC=rc.exe BSC32=bscmake.exe BSC32_FLAGS=/nologo /o"$(OUTDIR)\pk11destroy.bsc" BSC32_SBRS= "$(INTDIR)\pkcs11-destroy.sbr" "$(OUTDIR)\pk11destroy.bsc" : "$(OUTDIR)" $(BSC32_SBRS) $(BSC32) @<< $(BSC32_FLAGS) $(BSC32_SBRS) << LINK32=link.exe LINK32_FLAGS=user32.lib advapi32.lib ../../../lib/isc/win32/Debug/libisc.lib /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\pkcs11-destroy.pdb" /debug @MACHINE@ /out:"../../../Build/Debug/pkcs11-destroy.exe" /pdbtype:sept LINK32_OBJS= "$(INTDIR)\pkcs11-destroy.obj" "..\..\..\Build\Debug\pkcs11-destroy.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) $(LINK32) @<< $(LINK32_FLAGS) $(LINK32_OBJS) << $(_VC_MANIFEST_EMBED_EXE) !ENDIF !IF "$(NO_EXTERNAL_DEPS)" != "1" !IF EXISTS("pk11destroy.dep") !INCLUDE "pk11destroy.dep" !ELSE !MESSAGE Warning: cannot find "pk11destroy.dep" !ENDIF !ENDIF !IF "$(CFG)" == "pk11destroy - @PLATFORM@ Release" || "$(CFG)" == "pk11destroy - @PLATFORM@ Debug" SOURCE="..\pkcs11-destroy.c" !IF "$(CFG)" == "pk11destroy - @PLATFORM@ Release" "$(INTDIR)\pkcs11-destroy.obj" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ELSEIF "$(CFG)" == "pk11destroy - @PLATFORM@ Debug" "$(INTDIR)\pkcs11-destroy.obj" "$(INTDIR)\pkcs11-destroy.sbr" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ENDIF !ENDIF #################################################### # Commands to generate initial empty manifest file and the RC file # that references it, and for generating the .res file: $(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc $(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest type <<$@ #include 1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest" << KEEP $(_VC_MANIFEST_BASENAME).auto.manifest : type <<$@ << KEEP bind9-9.11.3+dfsg/bin/pkcs11/win32/pk11destroy.vcxproj.filters.in000066400000000000000000000017041325250447100242310ustar00rootroot00000000000000 {4FC737F1-C7A5-4376-A066-2A32D752A2FF} cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx {93995380-89BD-4b04-88EB-625FBE52EBFB} h;hpp;hxx;hm;inl;inc;xsd {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms Source Files bind9-9.11.3+dfsg/bin/pkcs11/win32/pk11destroy.vcxproj.in000066400000000000000000000144541325250447100225700ustar00rootroot00000000000000 Debug @PLATFORM@ Release @PLATFORM@ {5B3137E5-7E1F-49AA-8810-A09AA417D326} Win32Proj pk11destroy Application true MultiByte Application false true MultiByte true ..\..\..\Build\$(Configuration)\ .\$(Configuration)\ pkcs11-destroy false ..\..\..\Build\$(Configuration)\ .\$(Configuration)\ pkcs11-destroy Level3 Disabled WIN32;@PK11_LIB_LOCATION@_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true .\$(Configuration)\$(ProjectName).pch .\$(Configuration)\ .\$(Configuration)\ $(OutDir)$(TargetName).pdb true .\;..\..\..\;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;%(AdditionalIncludeDirectories) CompileAsC Console true ..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt) $(Configuration);..\..\..\lib\isc\win32\$(Configuration);%(AdditionalLibraryDirectories) libisc.lib;%(AdditionalDependencies) Level3 MaxSpeed true @INTRINSIC@ WIN32;@PK11_LIB_LOCATION@NDEBUG;_CONSOLE;%(PreprocessorDefinitions) OnlyExplicitInline false true .\$(Configuration)\$(ProjectName).pch .\$(Configuration)\ .\$(Configuration)\ $(OutDir)$(TargetName).pdb .\;..\..\..\;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;%(AdditionalIncludeDirectories) CompileAsC Console false true true ..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt) Default $(Configuration);..\..\..\lib\isc\win32\$(Configuration);%(AdditionalLibraryDirectories) libisc.lib;%(AdditionalDependencies) bind9-9.11.3+dfsg/bin/pkcs11/win32/pk11destroy.vcxproj.user000066400000000000000000000002171325250447100231300ustar00rootroot00000000000000 bind9-9.11.3+dfsg/bin/pkcs11/win32/pk11keygen.dsp.in000066400000000000000000000105111325250447100214420ustar00rootroot00000000000000# Microsoft Developer Studio Project File - Name="pk11keygen" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "@PLATFORM@ (x86) Console Application" 0x0103 CFG=pk11keygen - @PLATFORM@ Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "pk11keygen.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "pk11keygen.mak" CFG="pk11keygen - @PLATFORM@ Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "pk11keygen - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE "pk11keygen - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "pk11keygen - @PLATFORM@ Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 @COPTX@ @COPTI@ /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c # ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../.." /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" @PK11_LIB_LOCATION@ @COPTY@ /FD /c # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console @MACHINE@ # ADD LINK32 user32.lib advapi32.lib ../../../lib/isc/win32/Release/libisc.lib /nologo /subsystem:console @MACHINE@ /out:"../../../Build/Release/pkcs11-keygen.exe" !ELSEIF "$(CFG)" == "pk11keygen - @PLATFORM@ Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /GZ /c # ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../.." /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" @PK11_LIB_LOCATION@ /FR /FD /GZ /c # SUBTRACT CPP /X @COPTY@ # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug @MACHINE@ /pdbtype:sept # ADD LINK32 user32.lib advapi32.lib ../../../lib/isc/win32/Debug/libisc.lib /nologo /subsystem:console /debug @MACHINE@ /out:"../../../Build/Debug/pkcs11-keygen.exe" /pdbtype:sept !ENDIF # Begin Target # Name "pk11keygen - @PLATFORM@ Release" # Name "pk11keygen - @PLATFORM@ Debug" # Begin Group "Source Files" # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" # Begin Source File SOURCE="..\pkcs11-keygen.c" # End Source File # End Group # Begin Group "Header Files" # PROP Default_Filter "h;hpp;hxx;hm;inl" # End Group # Begin Group "Resource Files" # PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" # End Group # End Target # End Project bind9-9.11.3+dfsg/bin/pkcs11/win32/pk11keygen.dsw000066400000000000000000000010411325250447100210420ustar00rootroot00000000000000Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "pk11keygen"=".\pk11keygen.dsp" - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### bind9-9.11.3+dfsg/bin/pkcs11/win32/pk11keygen.mak.in000066400000000000000000000176111325250447100214340ustar00rootroot00000000000000# Microsoft Developer Studio Generated NMAKE File, Based on pk11keygen.dsp !IF "$(CFG)" == "" CFG=pk11keygen - @PLATFORM@ Debug !MESSAGE No configuration specified. Defaulting to pk11keygen - @PLATFORM@ Debug. !ENDIF !IF "$(CFG)" != "pk11keygen - @PLATFORM@ Release" && "$(CFG)" != "pk11keygen - @PLATFORM@ Debug" !MESSAGE Invalid configuration "$(CFG)" specified. !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "pk11keygen.mak" CFG="pk11keygen - @PLATFORM@ Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "pk11keygen - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE "pk11keygen - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE !ERROR An invalid configuration is specified. !ENDIF !IF "$(OS)" == "Windows_NT" NULL= !ELSE NULL=nul !ENDIF !IF "$(CFG)" == "pk11keygen - @PLATFORM@ Release" _VC_MANIFEST_INC=0 _VC_MANIFEST_BASENAME=__VC80 !ELSE _VC_MANIFEST_INC=1 _VC_MANIFEST_BASENAME=__VC80.Debug !ENDIF #################################################### # Specifying name of temporary resource file used only in incremental builds: !if "$(_VC_MANIFEST_INC)" == "1" _VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res !else _VC_MANIFEST_AUTO_RES= !endif #################################################### # _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE: !if "$(_VC_MANIFEST_INC)" == "1" #MT_SPECIAL_RETURN=1090650113 #MT_SPECIAL_SWITCH=-notify_resource_update MT_SPECIAL_RETURN=0 MT_SPECIAL_SWITCH= _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \ if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \ rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \ link $** /out:$@ $(LFLAGS) !else _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1 !endif #################################################### # _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL: !if "$(_VC_MANIFEST_INC)" == "1" #MT_SPECIAL_RETURN=1090650113 #MT_SPECIAL_SWITCH=-notify_resource_update MT_SPECIAL_RETURN=0 MT_SPECIAL_SWITCH= _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \ if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \ rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \ link $** /out:$@ $(LFLAGS) !else _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2 !endif #################################################### # _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily: !if "$(_VC_MANIFEST_INC)" == "1" _VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \ $(_VC_MANIFEST_BASENAME).auto.rc \ $(_VC_MANIFEST_BASENAME).auto.manifest !else _VC_MANIFEST_CLEAN= !endif !IF "$(CFG)" == "pk11keygen - @PLATFORM@ Release" OUTDIR=.\Release INTDIR=.\Release ALL : "..\..\..\Build\Release\pkcs11-keygen.exe" CLEAN : -@erase "$(INTDIR)\pkcs11-keygen.obj" -@erase "$(INTDIR)\vc60.idb" -@erase "..\..\..\Build\Release\pkcs11-keygen.exe" -@$(_VC_MANIFEST_CLEAN) "$(OUTDIR)" : if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" CPP=cl.exe CPP_PROJ=/nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../.." /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" @PK11_LIB_LOCATION@ /Fp"$(INTDIR)\pk11keygen.pch" @COPTY@ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c .c{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .c{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << RSC=rc.exe BSC32=bscmake.exe BSC32_FLAGS=/nologo /o"$(OUTDIR)\pk11keygen.bsc" BSC32_SBRS= \ LINK32=link.exe LINK32_FLAGS=user32.lib advapi32.lib ../../../lib/isc/win32/Release/libisc.lib /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\pkcs11-keygen.pdb" @MACHINE@ /out:"../../../Build/Release/pkcs11-keygen.exe" LINK32_OBJS= "$(INTDIR)\pkcs11-keygen.obj" "..\..\..\Build\Release\pkcs11-keygen.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) $(LINK32) @<< $(LINK32_FLAGS) $(LINK32_OBJS) << $(_VC_MANIFEST_EMBED_EXE) !ELSEIF "$(CFG)" == "pk11keygen - @PLATFORM@ Debug" OUTDIR=.\Debug INTDIR=.\Debug # Begin Custom Macros OutDir=.\Debug # End Custom Macros ALL : "..\..\..\Build\Debug\pkcs11-keygen.exe" "$(OUTDIR)\pk11keygen.bsc" CLEAN : -@erase "$(INTDIR)\pkcs11-keygen.obj" -@erase "$(INTDIR)\pkcs11-keygen.sbr" -@erase "$(INTDIR)\vc60.idb" -@erase "$(INTDIR)\vc60.pdb" -@erase "$(OUTDIR)\pkcs11-keygen.pdb" -@erase "$(OUTDIR)\pk11keygen.bsc" -@erase "..\..\..\Build\Debug\pkcs11-keygen.exe" -@erase "..\..\..\Build\Debug\pkcs11-keygen.ilk" -@$(_VC_MANIFEST_CLEAN) "$(OUTDIR)" : if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" CPP=cl.exe CPP_PROJ=/nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../.." /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" @PK11_LIB_LOCATION@ /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c .c{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .c{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << RSC=rc.exe BSC32=bscmake.exe BSC32_FLAGS=/nologo /o"$(OUTDIR)\pk11keygen.bsc" BSC32_SBRS= "$(INTDIR)\pkcs11-keygen.sbr" "$(OUTDIR)\pk11keygen.bsc" : "$(OUTDIR)" $(BSC32_SBRS) $(BSC32) @<< $(BSC32_FLAGS) $(BSC32_SBRS) << LINK32=link.exe LINK32_FLAGS=user32.lib advapi32.lib ../../../lib/isc/win32/Debug/libisc.lib /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\pkcs11-keygen.pdb" /debug @MACHINE@ /out:"../../../Build/Debug/pkcs11-keygen.exe" /pdbtype:sept LINK32_OBJS= "$(INTDIR)\pkcs11-keygen.obj" "..\..\..\Build\Debug\pkcs11-keygen.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) $(LINK32) @<< $(LINK32_FLAGS) $(LINK32_OBJS) << $(_VC_MANIFEST_EMBED_EXE) !ENDIF !IF "$(NO_EXTERNAL_DEPS)" != "1" !IF EXISTS("pk11keygen.dep") !INCLUDE "pk11keygen.dep" !ELSE !MESSAGE Warning: cannot find "pk11keygen.dep" !ENDIF !ENDIF !IF "$(CFG)" == "pk11keygen - @PLATFORM@ Release" || "$(CFG)" == "pk11keygen - @PLATFORM@ Debug" SOURCE="..\pkcs11-keygen.c" !IF "$(CFG)" == "pk11keygen - @PLATFORM@ Release" "$(INTDIR)\pkcs11-keygen.obj" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ELSEIF "$(CFG)" == "pk11keygen - @PLATFORM@ Debug" "$(INTDIR)\pkcs11-keygen.obj" "$(INTDIR)\pkcs11-keygen.sbr" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ENDIF !ENDIF #################################################### # Commands to generate initial empty manifest file and the RC file # that references it, and for generating the .res file: $(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc $(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest type <<$@ #include 1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest" << KEEP $(_VC_MANIFEST_BASENAME).auto.manifest : type <<$@ << KEEP bind9-9.11.3+dfsg/bin/pkcs11/win32/pk11keygen.vcxproj.filters.in000066400000000000000000000017031325250447100240210ustar00rootroot00000000000000 {4FC737F1-C7A5-4376-A066-2A32D752A2FF} cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx {93995380-89BD-4b04-88EB-625FBE52EBFB} h;hpp;hxx;hm;inl;inc;xsd {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms Source Files bind9-9.11.3+dfsg/bin/pkcs11/win32/pk11keygen.vcxproj.in000066400000000000000000000144501325250447100223550ustar00rootroot00000000000000 Debug @PLATFORM@ Release @PLATFORM@ {5042D371-0402-4FA3-A52A-769708694422} Win32Proj pk11keygen Application true MultiByte Application false true MultiByte true ..\..\..\Build\$(Configuration)\ .\$(Configuration)\ pkcs11-keygen false ..\..\..\Build\$(Configuration)\ .\$(Configuration)\ pkcs11-keygen Level3 Disabled WIN32;@PK11_LIB_LOCATION@_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true .\$(Configuration)\$(ProjectName).pch .\$(Configuration)\ .\$(Configuration)\ $(OutDir)$(TargetName).pdb true .\;..\..\..\;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;%(AdditionalIncludeDirectories) CompileAsC Console true ..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt) $(Configuration);..\..\..\lib\isc\win32\$(Configuration);%(AdditionalLibraryDirectories) libisc.lib;%(AdditionalDependencies) Level3 MaxSpeed true @INTRINSIC@ WIN32;@PK11_LIB_LOCATION@NDEBUG;_CONSOLE;%(PreprocessorDefinitions) OnlyExplicitInline false true .\$(Configuration)\$(ProjectName).pch .\$(Configuration)\ .\$(Configuration)\ $(OutDir)$(TargetName).pdb .\;..\..\..\;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;%(AdditionalIncludeDirectories) CompileAsC Console false true true ..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt) Default $(Configuration);..\..\..\lib\isc\win32\$(Configuration);%(AdditionalLibraryDirectories) libisc.lib;%(AdditionalDependencies) bind9-9.11.3+dfsg/bin/pkcs11/win32/pk11keygen.vcxproj.user000066400000000000000000000002171325250447100227210ustar00rootroot00000000000000 bind9-9.11.3+dfsg/bin/pkcs11/win32/pk11list.dsp.in000066400000000000000000000104551325250447100211420ustar00rootroot00000000000000# Microsoft Developer Studio Project File - Name="pk11list" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "@PLATFORM@ (x86) Console Application" 0x0103 CFG=pk11list - @PLATFORM@ Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "pk11list.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "pk11list.mak" CFG="pk11list - @PLATFORM@ Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "pk11list - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE "pk11list - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "pk11list - @PLATFORM@ Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 @COPTX@ @COPTI@ /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c # ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../.." /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" @PK11_LIB_LOCATION@ @COPTY@ /FD /c # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console @MACHINE@ # ADD LINK32 user32.lib advapi32.lib ../../../lib/isc/win32/Release/libisc.lib /nologo /subsystem:console @MACHINE@ /out:"../../../Build/Release/pkcs11-list.exe" !ELSEIF "$(CFG)" == "pk11list - @PLATFORM@ Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /GZ /c # ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../.." /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" @PK11_LIB_LOCATION@ /FR /FD /GZ /c # SUBTRACT CPP /X @COPTY@ # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug @MACHINE@ /pdbtype:sept # ADD LINK32 user32.lib advapi32.lib ../../../lib/isc/win32/Debug/libisc.lib /nologo /subsystem:console /debug @MACHINE@ /out:"../../../Build/Debug/pkcs11-list.exe" /pdbtype:sept !ENDIF # Begin Target # Name "pk11list - @PLATFORM@ Release" # Name "pk11list - @PLATFORM@ Debug" # Begin Group "Source Files" # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" # Begin Source File SOURCE="..\pkcs11-list.c" # End Source File # End Group # Begin Group "Header Files" # PROP Default_Filter "h;hpp;hxx;hm;inl" # End Group # Begin Group "Resource Files" # PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" # End Group # End Target # End Project bind9-9.11.3+dfsg/bin/pkcs11/win32/pk11list.dsw000066400000000000000000000010351325250447100205360ustar00rootroot00000000000000Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "pk11list"=".\pk11list.dsp" - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### bind9-9.11.3+dfsg/bin/pkcs11/win32/pk11list.mak.in000066400000000000000000000174531325250447100211310ustar00rootroot00000000000000# Microsoft Developer Studio Generated NMAKE File, Based on pk11list.dsp !IF "$(CFG)" == "" CFG=pk11list - @PLATFORM@ Debug !MESSAGE No configuration specified. Defaulting to pk11list - @PLATFORM@ Debug. !ENDIF !IF "$(CFG)" != "pk11list - @PLATFORM@ Release" && "$(CFG)" != "pk11list - @PLATFORM@ Debug" !MESSAGE Invalid configuration "$(CFG)" specified. !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "pk11list.mak" CFG="pk11list - @PLATFORM@ Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "pk11list - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE "pk11list - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE !ERROR An invalid configuration is specified. !ENDIF !IF "$(OS)" == "Windows_NT" NULL= !ELSE NULL=nul !ENDIF !IF "$(CFG)" == "pk11list - @PLATFORM@ Release" _VC_MANIFEST_INC=0 _VC_MANIFEST_BASENAME=__VC80 !ELSE _VC_MANIFEST_INC=1 _VC_MANIFEST_BASENAME=__VC80.Debug !ENDIF #################################################### # Specifying name of temporary resource file used only in incremental builds: !if "$(_VC_MANIFEST_INC)" == "1" _VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res !else _VC_MANIFEST_AUTO_RES= !endif #################################################### # _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE: !if "$(_VC_MANIFEST_INC)" == "1" #MT_SPECIAL_RETURN=1090650113 #MT_SPECIAL_SWITCH=-notify_resource_update MT_SPECIAL_RETURN=0 MT_SPECIAL_SWITCH= _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \ if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \ rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \ link $** /out:$@ $(LFLAGS) !else _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1 !endif #################################################### # _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL: !if "$(_VC_MANIFEST_INC)" == "1" #MT_SPECIAL_RETURN=1090650113 #MT_SPECIAL_SWITCH=-notify_resource_update MT_SPECIAL_RETURN=0 MT_SPECIAL_SWITCH= _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \ if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \ rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \ link $** /out:$@ $(LFLAGS) !else _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2 !endif #################################################### # _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily: !if "$(_VC_MANIFEST_INC)" == "1" _VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \ $(_VC_MANIFEST_BASENAME).auto.rc \ $(_VC_MANIFEST_BASENAME).auto.manifest !else _VC_MANIFEST_CLEAN= !endif !IF "$(CFG)" == "pk11list - @PLATFORM@ Release" OUTDIR=.\Release INTDIR=.\Release ALL : "..\..\..\Build\Release\pkcs11-list.exe" CLEAN : -@erase "$(INTDIR)\pkcs11-list.obj" -@erase "$(INTDIR)\vc60.idb" -@erase "..\..\..\Build\Release\pkcs11-list.exe" -@$(_VC_MANIFEST_CLEAN) "$(OUTDIR)" : if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" CPP=cl.exe CPP_PROJ=/nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../.." /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" @PK11_LIB_LOCATION@ /Fp"$(INTDIR)\pk11list.pch" @COPTY@ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c .c{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .c{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << RSC=rc.exe BSC32=bscmake.exe BSC32_FLAGS=/nologo /o"$(OUTDIR)\pk11list.bsc" BSC32_SBRS= \ LINK32=link.exe LINK32_FLAGS=user32.lib advapi32.lib ../../../lib/isc/win32/Release/libisc.lib /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\pkcs11-list.pdb" @MACHINE@ /out:"../../../Build/Release/pkcs11-list.exe" LINK32_OBJS= "$(INTDIR)\pkcs11-list.obj" "..\..\..\Build\Release\pkcs11-list.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) $(LINK32) @<< $(LINK32_FLAGS) $(LINK32_OBJS) << $(_VC_MANIFEST_EMBED_EXE) !ELSEIF "$(CFG)" == "pk11list - @PLATFORM@ Debug" OUTDIR=.\Debug INTDIR=.\Debug # Begin Custom Macros OutDir=.\Debug # End Custom Macros ALL : "..\..\..\Build\Debug\pkcs11-list.exe" "$(OUTDIR)\pk11list.bsc" CLEAN : -@erase "$(INTDIR)\pkcs11-list.obj" -@erase "$(INTDIR)\pkcs11-list.sbr" -@erase "$(INTDIR)\vc60.idb" -@erase "$(INTDIR)\vc60.pdb" -@erase "$(OUTDIR)\pkcs11-list.pdb" -@erase "$(OUTDIR)\pk11list.bsc" -@erase "..\..\..\Build\Debug\pkcs11-list.exe" -@erase "..\..\..\Build\Debug\pkcs11-list.ilk" -@$(_VC_MANIFEST_CLEAN) "$(OUTDIR)" : if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" CPP=cl.exe CPP_PROJ=/nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../.." /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" @PK11_LIB_LOCATION@ /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c .c{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .c{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << RSC=rc.exe BSC32=bscmake.exe BSC32_FLAGS=/nologo /o"$(OUTDIR)\pk11list.bsc" BSC32_SBRS= "$(INTDIR)\pkcs11-list.sbr" "$(OUTDIR)\pk11list.bsc" : "$(OUTDIR)" $(BSC32_SBRS) $(BSC32) @<< $(BSC32_FLAGS) $(BSC32_SBRS) << LINK32=link.exe LINK32_FLAGS=user32.lib advapi32.lib ../../../lib/isc/win32/Debug/libisc.lib /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\pkcs11-list.pdb" /debug @MACHINE@ /out:"../../../Build/Debug/pkcs11-list.exe" /pdbtype:sept LINK32_OBJS= "$(INTDIR)\pkcs11-list.obj" "..\..\..\Build\Debug\pkcs11-list.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) $(LINK32) @<< $(LINK32_FLAGS) $(LINK32_OBJS) << $(_VC_MANIFEST_EMBED_EXE) !ENDIF !IF "$(NO_EXTERNAL_DEPS)" != "1" !IF EXISTS("pk11list.dep") !INCLUDE "pk11list.dep" !ELSE !MESSAGE Warning: cannot find "pk11list.dep" !ENDIF !ENDIF !IF "$(CFG)" == "pk11list - @PLATFORM@ Release" || "$(CFG)" == "pk11list - @PLATFORM@ Debug" SOURCE="..\pkcs11-list.c" !IF "$(CFG)" == "pk11list - @PLATFORM@ Release" "$(INTDIR)\pkcs11-list.obj" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ELSEIF "$(CFG)" == "pk11list - @PLATFORM@ Debug" "$(INTDIR)\pkcs11-list.obj" "$(INTDIR)\pkcs11-list.sbr" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ENDIF !ENDIF #################################################### # Commands to generate initial empty manifest file and the RC file # that references it, and for generating the .res file: $(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc $(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest type <<$@ #include 1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest" << KEEP $(_VC_MANIFEST_BASENAME).auto.manifest : type <<$@ << KEEP bind9-9.11.3+dfsg/bin/pkcs11/win32/pk11list.vcxproj.filters.in000066400000000000000000000017011325250447100235100ustar00rootroot00000000000000 {4FC737F1-C7A5-4376-A066-2A32D752A2FF} cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx {93995380-89BD-4b04-88EB-625FBE52EBFB} h;hpp;hxx;hm;inl;inc;xsd {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms Source Files bind9-9.11.3+dfsg/bin/pkcs11/win32/pk11list.vcxproj.in000066400000000000000000000144401325250447100220450ustar00rootroot00000000000000 Debug @PLATFORM@ Release @PLATFORM@ {C663B088-F7BC-4C8C-8D06-A76636EED651} Win32Proj pk11list Application true MultiByte Application false true MultiByte true ..\..\..\Build\$(Configuration)\ .\$(Configuration)\ pkcs11-list false ..\..\..\Build\$(Configuration)\ .\$(Configuration)\ pkcs11-list Level3 Disabled WIN32;@PK11_LIB_LOCATION@_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true .\$(Configuration)\$(ProjectName).pch .\$(Configuration)\ .\$(Configuration)\ $(OutDir)$(TargetName).pdb true .\;..\..\..\;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;%(AdditionalIncludeDirectories) CompileAsC Console true ..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt) $(Configuration);..\..\..\lib\isc\win32\$(Configuration);%(AdditionalLibraryDirectories) libisc.lib;%(AdditionalDependencies) Level3 MaxSpeed true @INTRINSIC@ WIN32;@PK11_LIB_LOCATION@NDEBUG;_CONSOLE;%(PreprocessorDefinitions) OnlyExplicitInline false true .\$(Configuration)\$(ProjectName).pch .\$(Configuration)\ .\$(Configuration)\ $(OutDir)$(TargetName).pdb .\;..\..\..\;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;%(AdditionalIncludeDirectories) CompileAsC Console false true true ..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt) Default $(Configuration);..\..\..\lib\isc\win32\$(Configuration);%(AdditionalLibraryDirectories) libisc.lib;%(AdditionalDependencies) bind9-9.11.3+dfsg/bin/pkcs11/win32/pk11list.vcxproj.user000066400000000000000000000002171325250447100224120ustar00rootroot00000000000000 bind9-9.11.3+dfsg/bin/pkcs11/win32/pk11tokens.dsp.in000066400000000000000000000105451325250447100214720ustar00rootroot00000000000000# Microsoft Developer Studio Project File - Name="pk11tokens" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "@PLATFORM@ (x86) Console Application" 0x0103 CFG=pk11tokens - @PLATFORM@ Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "pk11tokens.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "pk11tokens.mak" CFG="pk11tokens - @PLATFORM@ Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "pk11tokens - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE "pk11tokens - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "pk11tokens - @PLATFORM@ Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 @COPTX@ @COPTI@ /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c # ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../.." @LIBXML2_INC@ /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" @PK11_LIB_LOCATION@ @COPTY@ /FD /c # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console @MACHINE@ # ADD LINK32 user32.lib advapi32.lib ../../../lib/isc/win32/Release/libisc.lib /nologo /subsystem:console @MACHINE@ /out:"../../../Build/Release/pkcs11-tokens.exe" !ELSEIF "$(CFG)" == "pk11tokens - @PLATFORM@ Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /GZ /c # ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../.." @LIBXML2_INC@ /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" @PK11_LIB_LOCATION@ /FR /FD /GZ /c # SUBTRACT CPP /X @COPTY@ # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug @MACHINE@ /pdbtype:sept # ADD LINK32 user32.lib advapi32.lib ../../../lib/isc/win32/Debug/libisc.lib /nologo /subsystem:console /debug @MACHINE@ /out:"../../../Build/Debug/pkcs11-tokens.exe" /pdbtype:sept !ENDIF # Begin Target # Name "pk11tokens - @PLATFORM@ Release" # Name "pk11tokens - @PLATFORM@ Debug" # Begin Group "Source Files" # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" # Begin Source File SOURCE="..\pkcs11-tokens.c" # End Source File # End Group # Begin Group "Header Files" # PROP Default_Filter "h;hpp;hxx;hm;inl" # End Group # Begin Group "Resource Files" # PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" # End Group # End Target # End Project bind9-9.11.3+dfsg/bin/pkcs11/win32/pk11tokens.dsw000066400000000000000000000010411325250447100210630ustar00rootroot00000000000000Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "pk11tokens"=".\pk11tokens.dsp" - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### bind9-9.11.3+dfsg/bin/pkcs11/win32/pk11tokens.mak.in000066400000000000000000000176451325250447100214640ustar00rootroot00000000000000# Microsoft Developer Studio Generated NMAKE File, Based on pk11tokens.dsp !IF "$(CFG)" == "" CFG=pk11tokens - @PLATFORM@ Debug !MESSAGE No configuration specified. Defaulting to pk11tokens - @PLATFORM@ Debug. !ENDIF !IF "$(CFG)" != "pk11tokens - @PLATFORM@ Release" && "$(CFG)" != "pk11tokens - @PLATFORM@ Debug" !MESSAGE Invalid configuration "$(CFG)" specified. !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "pk11tokens.mak" CFG="pk11tokens - @PLATFORM@ Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "pk11tokens - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE "pk11tokens - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE !ERROR An invalid configuration is specified. !ENDIF !IF "$(OS)" == "Windows_NT" NULL= !ELSE NULL=nul !ENDIF !IF "$(CFG)" == "pk11tokens - @PLATFORM@ Release" _VC_MANIFEST_INC=0 _VC_MANIFEST_BASENAME=__VC80 !ELSE _VC_MANIFEST_INC=1 _VC_MANIFEST_BASENAME=__VC80.Debug !ENDIF #################################################### # Specifying name of temporary resource file used only in incremental builds: !if "$(_VC_MANIFEST_INC)" == "1" _VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res !else _VC_MANIFEST_AUTO_RES= !endif #################################################### # _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE: !if "$(_VC_MANIFEST_INC)" == "1" #MT_SPECIAL_RETURN=1090650113 #MT_SPECIAL_SWITCH=-notify_resource_update MT_SPECIAL_RETURN=0 MT_SPECIAL_SWITCH= _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \ if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \ rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \ link $** /out:$@ $(LFLAGS) !else _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1 !endif #################################################### # _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL: !if "$(_VC_MANIFEST_INC)" == "1" #MT_SPECIAL_RETURN=1090650113 #MT_SPECIAL_SWITCH=-notify_resource_update MT_SPECIAL_RETURN=0 MT_SPECIAL_SWITCH= _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \ if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \ rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \ link $** /out:$@ $(LFLAGS) !else _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2 !endif #################################################### # _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily: !if "$(_VC_MANIFEST_INC)" == "1" _VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \ $(_VC_MANIFEST_BASENAME).auto.rc \ $(_VC_MANIFEST_BASENAME).auto.manifest !else _VC_MANIFEST_CLEAN= !endif !IF "$(CFG)" == "pk11tokens - @PLATFORM@ Release" OUTDIR=.\Release INTDIR=.\Release ALL : "..\..\..\Build\Release\pkcs11-tokens.exe" CLEAN : -@erase "$(INTDIR)\pkcs11-tokens.obj" -@erase "$(INTDIR)\vc60.idb" -@erase "..\..\..\Build\Release\pkcs11-tokens.exe" -@$(_VC_MANIFEST_CLEAN) "$(OUTDIR)" : if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" CPP=cl.exe CPP_PROJ=/nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../.." @LIBXML2_INC@ /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" @PK11_LIB_LOCATION@ /Fp"$(INTDIR)\pk11tokens.pch" @COPTY@ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c .c{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .c{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << RSC=rc.exe BSC32=bscmake.exe BSC32_FLAGS=/nologo /o"$(OUTDIR)\pk11tokens.bsc" BSC32_SBRS= \ LINK32=link.exe LINK32_FLAGS=user32.lib advapi32.lib ../../../lib/isc/win32/Release/libisc.lib /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\pkcs11-tokens.pdb" @MACHINE@ /out:"../../../Build/Release/pkcs11-tokens.exe" LINK32_OBJS= "$(INTDIR)\pkcs11-tokens.obj" "..\..\..\Build\Release\pkcs11-tokens.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) $(LINK32) @<< $(LINK32_FLAGS) $(LINK32_OBJS) << $(_VC_MANIFEST_EMBED_EXE) !ELSEIF "$(CFG)" == "pk11tokens - @PLATFORM@ Debug" OUTDIR=.\Debug INTDIR=.\Debug # Begin Custom Macros OutDir=.\Debug # End Custom Macros ALL : "..\..\..\Build\Debug\pkcs11-tokens.exe" "$(OUTDIR)\pk11tokens.bsc" CLEAN : -@erase "$(INTDIR)\pkcs11-tokens.obj" -@erase "$(INTDIR)\pkcs11-tokens.sbr" -@erase "$(INTDIR)\vc60.idb" -@erase "$(INTDIR)\vc60.pdb" -@erase "$(OUTDIR)\pkcs11-tokens.pdb" -@erase "$(OUTDIR)\pk11tokens.bsc" -@erase "..\..\..\Build\Debug\pkcs11-tokens.exe" -@erase "..\..\..\Build\Debug\pkcs11-tokens.ilk" -@$(_VC_MANIFEST_CLEAN) "$(OUTDIR)" : if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" CPP=cl.exe CPP_PROJ=/nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../.." @LIBXML2_INC@ /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" @PK11_LIB_LOCATION@ /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c .c{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .c{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << RSC=rc.exe BSC32=bscmake.exe BSC32_FLAGS=/nologo /o"$(OUTDIR)\pk11tokens.bsc" BSC32_SBRS= "$(INTDIR)\pkcs11-tokens.sbr" "$(OUTDIR)\pk11tokens.bsc" : "$(OUTDIR)" $(BSC32_SBRS) $(BSC32) @<< $(BSC32_FLAGS) $(BSC32_SBRS) << LINK32=link.exe LINK32_FLAGS=user32.lib advapi32.lib ../../../lib/isc/win32/Debug/libisc.lib /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\pkcs11-tokens.pdb" /debug @MACHINE@ /out:"../../../Build/Debug/pkcs11-tokens.exe" /pdbtype:sept LINK32_OBJS= "$(INTDIR)\pkcs11-tokens.obj" "..\..\..\Build\Debug\pkcs11-tokens.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) $(LINK32) @<< $(LINK32_FLAGS) $(LINK32_OBJS) << $(_VC_MANIFEST_EMBED_EXE) !ENDIF !IF "$(NO_EXTERNAL_DEPS)" != "1" !IF EXISTS("pk11tokens.dep") !INCLUDE "pk11tokens.dep" !ELSE !MESSAGE Warning: cannot find "pk11tokens.dep" !ENDIF !ENDIF !IF "$(CFG)" == "pk11tokens - @PLATFORM@ Release" || "$(CFG)" == "pk11tokens - @PLATFORM@ Debug" SOURCE="..\pkcs11-tokens.c" !IF "$(CFG)" == "pk11tokens - @PLATFORM@ Release" "$(INTDIR)\pkcs11-tokens.obj" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ELSEIF "$(CFG)" == "pk11tokens - @PLATFORM@ Debug" "$(INTDIR)\pkcs11-tokens.obj" "$(INTDIR)\pkcs11-tokens.sbr" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ENDIF !ENDIF #################################################### # Commands to generate initial empty manifest file and the RC file # that references it, and for generating the .res file: $(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc $(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest type <<$@ #include 1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest" << KEEP $(_VC_MANIFEST_BASENAME).auto.manifest : type <<$@ << KEEP bind9-9.11.3+dfsg/bin/pkcs11/win32/pk11tokens.vcxproj.filters.in000066400000000000000000000017031325250447100240420ustar00rootroot00000000000000 {4FC737F1-C7A5-4376-A066-2A32D752A2FF} cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx {93995380-89BD-4b04-88EB-625FBE52EBFB} h;hpp;hxx;hm;inl;inc;xsd {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms Source Files bind9-9.11.3+dfsg/bin/pkcs11/win32/pk11tokens.vcxproj.in000066400000000000000000000145021325250447100223740ustar00rootroot00000000000000 Debug @PLATFORM@ Release @PLATFORM@ {403FD4B1-A4F9-4159-9013-5860E3A4417D} Win32Proj pk11tokens Application true MultiByte Application false true MultiByte true ..\..\..\Build\$(Configuration)\ .\$(Configuration)\ pkcs11-tokens false ..\..\..\Build\$(Configuration)\ .\$(Configuration)\ pkcs11-tokens Level3 Disabled WIN32;@PK11_LIB_LOCATION@_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true .\$(Configuration)\$(ProjectName).pch .\$(Configuration)\ .\$(Configuration)\ $(OutDir)$(TargetName).pdb true .\;..\..\..\;@LIBXML2_INC@..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;%(AdditionalIncludeDirectories) CompileAsC Console true ..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt) $(Configuration);..\..\..\lib\isc\win32\$(Configuration);%(AdditionalLibraryDirectories) libisc.lib;%(AdditionalDependencies) Level3 MaxSpeed true @INTRINSIC@ WIN32;@PK11_LIB_LOCATION@NDEBUG;_CONSOLE;%(PreprocessorDefinitions) OnlyExplicitInline false true .\$(Configuration)\$(ProjectName).pch .\$(Configuration)\ .\$(Configuration)\ $(OutDir)$(TargetName).pdb .\;..\..\..\;@LIBXML2_INC@..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;%(AdditionalIncludeDirectories) CompileAsC Console false true true ..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt) Default $(Configuration);..\..\..\lib\isc\win32\$(Configuration);%(AdditionalLibraryDirectories) libisc.lib;%(AdditionalDependencies) bind9-9.11.3+dfsg/bin/pkcs11/win32/pk11tokens.vcxproj.user000066400000000000000000000002171325250447100227420ustar00rootroot00000000000000 bind9-9.11.3+dfsg/bin/python/000077500000000000000000000000001325250447100156255ustar00rootroot00000000000000bind9-9.11.3+dfsg/bin/python/Makefile.in000066400000000000000000000045351325250447100177010ustar00rootroot00000000000000# Copyright (C) 2012-2014, 2016, 2017 Internet Systems Consortium, Inc. ("ISC") # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. srcdir = @srcdir@ VPATH = @srcdir@ top_srcdir = @top_srcdir@ @BIND9_MAKE_INCLUDES@ PYTHON = @PYTHON@ SUBDIRS = isc TARGETS = dnssec-checkds dnssec-coverage dnssec-keymgr PYSRCS = dnssec-checkds.py dnssec-coverage.py dnssec-keymgr.py MANPAGES = dnssec-checkds.8 dnssec-coverage.8 dnssec-keymgr.8 HTMLPAGES = dnssec-checkds.html dnssec-coverage.html dnssec-keymgr.html MANOBJS = ${MANPAGES} ${HTMLPAGES} @BIND9_MAKE_RULES@ dnssec-checkds: dnssec-checkds.py cp -f dnssec-checkds.py dnssec-checkds chmod +x dnssec-checkds dnssec-coverage: dnssec-coverage.py cp -f dnssec-coverage.py dnssec-coverage chmod +x dnssec-coverage dnssec-keymgr: dnssec-keymgr.py cp -f dnssec-keymgr.py dnssec-keymgr chmod +x dnssec-keymgr doc man:: ${MANOBJS} docclean manclean maintainer-clean:: rm -f ${MANOBJS} installdirs: $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${sbindir} $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${mandir}/man8 install:: ${TARGETS} installdirs ${INSTALL_SCRIPT} dnssec-checkds ${DESTDIR}${sbindir} ${INSTALL_SCRIPT} dnssec-coverage ${DESTDIR}${sbindir} ${INSTALL_SCRIPT} dnssec-keymgr ${DESTDIR}${sbindir} ${INSTALL_DATA} ${srcdir}/dnssec-checkds.8 ${DESTDIR}${mandir}/man8 ${INSTALL_DATA} ${srcdir}/dnssec-coverage.8 ${DESTDIR}${mandir}/man8 ${INSTALL_DATA} ${srcdir}/dnssec-keymgr.8 ${DESTDIR}${mandir}/man8 if test -n "${PYTHON}" ; then \ if test -n "${DESTDIR}" ; then \ ${PYTHON} ${srcdir}/setup.py install --root=${DESTDIR} --prefix=${prefix} @PYTHON_INSTALL_LIB@ ; \ else \ ${PYTHON} ${srcdir}/setup.py install --prefix=${prefix} @PYTHON_INSTALL_LIB@ ; \ fi ; \ rm -rf build ; \ fi uninstall:: rm -f ${DESTDIR}${mandir}/man8/dnssec-keymgr.8 rm -f ${DESTDIR}${mandir}/man8/dnssec-coverage.8 rm -f ${DESTDIR}${mandir}/man8/dnssec-checkds.8 rm -f ${DESTDIR}${sbindir}/dnssec-keymgr rm -f ${DESTDIR}${sbindir}/dnssec-coverage rm -f ${DESTDIR}${sbindir}/dnssec-checkds # only manually uninstall for the python package itself clean distclean:: rm -f ${TARGETS} rm -rf build distclean:: rm -f dnssec-checkds.py dnssec-coverage.py dnssec-keymgr.py bind9-9.11.3+dfsg/bin/python/dnssec-checkds.8000066400000000000000000000056141325250447100206050ustar00rootroot00000000000000.\" Copyright (C) 2012-2017 Internet Systems Consortium, Inc. ("ISC") .\" .\" This Source Code Form is subject to the terms of the Mozilla Public .\" License, v. 2.0. If a copy of the MPL was not distributed with this .\" file, You can obtain one at http://mozilla.org/MPL/2.0/. .\" .hy 0 .ad l '\" t .\" Title: dnssec-checkds .\" Author: .\" Generator: DocBook XSL Stylesheets v1.78.1 .\" Date: 2013-01-01 .\" Manual: BIND9 .\" Source: ISC .\" Language: English .\" .TH "DNSSEC\-CHECKDS" "8" "2013\-01\-01" "ISC" "BIND9" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" dnssec-checkds \- DNSSEC delegation consistency checking tool .SH "SYNOPSIS" .HP \w'\fBdnssec\-checkds\fR\ 'u \fBdnssec\-checkds\fR [\fB\-l\ \fR\fB\fIdomain\fR\fR] [\fB\-f\ \fR\fB\fIfile\fR\fR] [\fB\-d\ \fR\fB\fIdig\ path\fR\fR] [\fB\-D\ \fR\fB\fIdsfromkey\ path\fR\fR] {zone} .HP \w'\fBdnssec\-dsfromkey\fR\ 'u \fBdnssec\-dsfromkey\fR [\fB\-l\ \fR\fB\fIdomain\fR\fR] [\fB\-f\ \fR\fB\fIfile\fR\fR] [\fB\-d\ \fR\fB\fIdig\ path\fR\fR] [\fB\-D\ \fR\fB\fIdsfromkey\ path\fR\fR] {zone} .SH "DESCRIPTION" .PP \fBdnssec\-checkds\fR verifies the correctness of Delegation Signer (DS) or DNSSEC Lookaside Validation (DLV) resource records for keys in a specified zone\&. .SH "OPTIONS" .PP \-f \fIfile\fR .RS 4 If a \fBfile\fR is specified, then the zone is read from that file to find the DNSKEY records\&. If not, then the DNSKEY records for the zone are looked up in the DNS\&. .RE .PP \-l \fIdomain\fR .RS 4 Check for a DLV record in the specified lookaside domain, instead of checking for a DS record in the zone\*(Aqs parent\&. .RE .PP \-d \fIdig path\fR .RS 4 Specifies a path to a \fBdig\fR binary\&. Used for testing\&. .RE .PP \-D \fIdsfromkey path\fR .RS 4 Specifies a path to a \fBdnssec\-dsfromkey\fR binary\&. Used for testing\&. .RE .SH "SEE ALSO" .PP \fBdnssec-dsfromkey\fR(8), \fBdnssec-keygen\fR(8), \fBdnssec-signzone\fR(8), .SH "AUTHOR" .PP \fBInternet Systems Consortium, Inc\&.\fR .SH "COPYRIGHT" .br Copyright \(co 2012-2017 Internet Systems Consortium, Inc. ("ISC") .br bind9-9.11.3+dfsg/bin/python/dnssec-checkds.docbook000066400000000000000000000111011325250447100220420ustar00rootroot00000000000000 2013-01-01 ISC Internet Systems Consortium, Inc. dnssec-checkds 8 BIND9 dnssec-checkds DNSSEC delegation consistency checking tool 2012 2013 2014 2015 2016 2017 Internet Systems Consortium, Inc. ("ISC") dnssec-checkds zone dnssec-dsfromkey zone DESCRIPTION dnssec-checkds verifies the correctness of Delegation Signer (DS) or DNSSEC Lookaside Validation (DLV) resource records for keys in a specified zone. OPTIONS -f file If a is specified, then the zone is read from that file to find the DNSKEY records. If not, then the DNSKEY records for the zone are looked up in the DNS. -l domain Check for a DLV record in the specified lookaside domain, instead of checking for a DS record in the zone's parent. -d dig path Specifies a path to a dig binary. Used for testing. -D dsfromkey path Specifies a path to a dnssec-dsfromkey binary. Used for testing. SEE ALSO dnssec-dsfromkey8 , dnssec-keygen8 , dnssec-signzone8 , bind9-9.11.3+dfsg/bin/python/dnssec-checkds.html000066400000000000000000000076651325250447100214120ustar00rootroot00000000000000 dnssec-checkds

Name

dnssec-checkds — DNSSEC delegation consistency checking tool

Synopsis

dnssec-checkds [-l domain] [-f file] [-d dig path] [-D dsfromkey path] {zone}

dnssec-dsfromkey [-l domain] [-f file] [-d dig path] [-D dsfromkey path] {zone}

DESCRIPTION

dnssec-checkds verifies the correctness of Delegation Signer (DS) or DNSSEC Lookaside Validation (DLV) resource records for keys in a specified zone.

OPTIONS

-f file

If a file is specified, then the zone is read from that file to find the DNSKEY records. If not, then the DNSKEY records for the zone are looked up in the DNS.

-l domain

Check for a DLV record in the specified lookaside domain, instead of checking for a DS record in the zone's parent.

-d dig path

Specifies a path to a dig binary. Used for testing.

-D dsfromkey path

Specifies a path to a dnssec-dsfromkey binary. Used for testing.

SEE ALSO

dnssec-dsfromkey(8) , dnssec-keygen(8) , dnssec-signzone(8) ,

bind9-9.11.3+dfsg/bin/python/dnssec-checkds.py.in000066400000000000000000000015301325250447100214640ustar00rootroot00000000000000#!@PYTHON@ ############################################################################ # Copyright (C) 2012-2017 Internet Systems Consortium, Inc. ("ISC") # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. ############################################################################ import os import sys sys.path.insert(0, os.path.dirname(sys.argv[0])) if os.name != 'nt': if '@PYTHON_INSTALL_DIR@': # value of --with-python-install-dir sys.path.insert(1, '@PYTHON_INSTALL_DIR@') else: sys.path.insert(1, os.path.join('@prefix@', 'lib', 'python' + sys.version[:3], 'site-packages')) import isc.checkds if __name__ == "__main__": isc.checkds.main() bind9-9.11.3+dfsg/bin/python/dnssec-coverage.8000066400000000000000000000163671325250447100210030ustar00rootroot00000000000000.\" Copyright (C) 2013-2016 Internet Systems Consortium, Inc. ("ISC") .\" .\" This Source Code Form is subject to the terms of the Mozilla Public .\" License, v. 2.0. If a copy of the MPL was not distributed with this .\" file, You can obtain one at http://mozilla.org/MPL/2.0/. .\" .hy 0 .ad l '\" t .\" Title: dnssec-coverage .\" Author: .\" Generator: DocBook XSL Stylesheets v1.78.1 .\" Date: 2014-01-11 .\" Manual: BIND9 .\" Source: ISC .\" Language: English .\" .TH "DNSSEC\-COVERAGE" "8" "2014\-01\-11" "ISC" "BIND9" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" dnssec-coverage \- checks future DNSKEY coverage for a zone .SH "SYNOPSIS" .HP \w'\fBdnssec\-coverage\fR\ 'u \fBdnssec\-coverage\fR [\fB\-K\ \fR\fB\fIdirectory\fR\fR] [\fB\-l\ \fR\fB\fIlength\fR\fR] [\fB\-f\ \fR\fB\fIfile\fR\fR] [\fB\-d\ \fR\fB\fIDNSKEY\ TTL\fR\fR] [\fB\-m\ \fR\fB\fImax\ TTL\fR\fR] [\fB\-r\ \fR\fB\fIinterval\fR\fR] [\fB\-c\ \fR\fB\fIcompilezone\ path\fR\fR] [\fB\-k\fR] [\fB\-z\fR] [zone...] .SH "DESCRIPTION" .PP \fBdnssec\-coverage\fR verifies that the DNSSEC keys for a given zone or a set of zones have timing metadata set properly to ensure no future lapses in DNSSEC coverage\&. .PP If \fBzone\fR is specified, then keys found in the key repository matching that zone are scanned, and an ordered list is generated of the events scheduled for that key (i\&.e\&., publication, activation, inactivation, deletion)\&. The list of events is walked in order of occurrence\&. Warnings are generated if any event is scheduled which could cause the zone to enter a state in which validation failures might occur: for example, if the number of published or active keys for a given algorithm drops to zero, or if a key is deleted from the zone too soon after a new key is rolled, and cached data signed by the prior key has not had time to expire from resolver caches\&. .PP If \fBzone\fR is not specified, then all keys in the key repository will be scanned, and all zones for which there are keys will be analyzed\&. (Note: This method of reporting is only accurate if all the zones that have keys in a given repository share the same TTL parameters\&.) .SH "OPTIONS" .PP \-K \fIdirectory\fR .RS 4 Sets the directory in which keys can be found\&. Defaults to the current working directory\&. .RE .PP \-f \fIfile\fR .RS 4 If a \fBfile\fR is specified, then the zone is read from that file; the largest TTL and the DNSKEY TTL are determined directly from the zone data, and the \fB\-m\fR and \fB\-d\fR options do not need to be specified on the command line\&. .RE .PP \-l \fIduration\fR .RS 4 The length of time to check for DNSSEC coverage\&. Key events scheduled further into the future than \fBduration\fR will be ignored, and assumed to be correct\&. .sp The value of \fBduration\fR can be set in seconds, or in larger units of time by adding a suffix: \*(Aqmi\*(Aq for minutes, \*(Aqh\*(Aq for hours, \*(Aqd\*(Aq for days, \*(Aqw\*(Aq for weeks, \*(Aqmo\*(Aq for months, \*(Aqy\*(Aq for years\&. .RE .PP \-m \fImaximum TTL\fR .RS 4 Sets the value to be used as the maximum TTL for the zone or zones being analyzed when determining whether there is a possibility of validation failure\&. When a zone\-signing key is deactivated, there must be enough time for the record in the zone with the longest TTL to have expired from resolver caches before that key can be purged from the DNSKEY RRset\&. If that condition does not apply, a warning will be generated\&. .sp The length of the TTL can be set in seconds, or in larger units of time by adding a suffix: \*(Aqmi\*(Aq for minutes, \*(Aqh\*(Aq for hours, \*(Aqd\*(Aq for days, \*(Aqw\*(Aq for weeks, \*(Aqmo\*(Aq for months, \*(Aqy\*(Aq for years\&. .sp This option is not necessary if the \fB\-f\fR has been used to specify a zone file\&. If \fB\-f\fR has been specified, this option may still be used; it will override the value found in the file\&. .sp If this option is not used and the maximum TTL cannot be retrieved from a zone file, a warning is generated and a default value of 1 week is used\&. .RE .PP \-d \fIDNSKEY TTL\fR .RS 4 Sets the value to be used as the DNSKEY TTL for the zone or zones being analyzed when determining whether there is a possibility of validation failure\&. When a key is rolled (that is, replaced with a new key), there must be enough time for the old DNSKEY RRset to have expired from resolver caches before the new key is activated and begins generating signatures\&. If that condition does not apply, a warning will be generated\&. .sp The length of the TTL can be set in seconds, or in larger units of time by adding a suffix: \*(Aqmi\*(Aq for minutes, \*(Aqh\*(Aq for hours, \*(Aqd\*(Aq for days, \*(Aqw\*(Aq for weeks, \*(Aqmo\*(Aq for months, \*(Aqy\*(Aq for years\&. .sp This option is not necessary if \fB\-f\fR has been used to specify a zone file from which the TTL of the DNSKEY RRset can be read, or if a default key TTL was set using ith the \fB\-L\fR to \fBdnssec\-keygen\fR\&. If either of those is true, this option may still be used; it will override the values found in the zone file or the key file\&. .sp If this option is not used and the key TTL cannot be retrieved from the zone file or the key file, then a warning is generated and a default value of 1 day is used\&. .RE .PP \-r \fIresign interval\fR .RS 4 Sets the value to be used as the resign interval for the zone or zones being analyzed when determining whether there is a possibility of validation failure\&. This value defaults to 22\&.5 days, which is also the default in \fBnamed\fR\&. However, if it has been changed by the \fBsig\-validity\-interval\fR option in named\&.conf, then it should also be changed here\&. .sp The length of the interval can be set in seconds, or in larger units of time by adding a suffix: \*(Aqmi\*(Aq for minutes, \*(Aqh\*(Aq for hours, \*(Aqd\*(Aq for days, \*(Aqw\*(Aq for weeks, \*(Aqmo\*(Aq for months, \*(Aqy\*(Aq for years\&. .RE .PP \-k .RS 4 Only check KSK coverage; ignore ZSK events\&. Cannot be used with \fB\-z\fR\&. .RE .PP \-z .RS 4 Only check ZSK coverage; ignore KSK events\&. Cannot be used with \fB\-k\fR\&. .RE .PP \-c \fIcompilezone path\fR .RS 4 Specifies a path to a \fBnamed\-compilezone\fR binary\&. Used for testing\&. .RE .SH "SEE ALSO" .PP \fBdnssec-checkds\fR(8), \fBdnssec-dsfromkey\fR(8), \fBdnssec-keygen\fR(8), \fBdnssec-signzone\fR(8) .SH "AUTHOR" .PP \fBInternet Systems Consortium, Inc\&.\fR .SH "COPYRIGHT" .br Copyright \(co 2013-2016 Internet Systems Consortium, Inc. ("ISC") .br bind9-9.11.3+dfsg/bin/python/dnssec-coverage.docbook000066400000000000000000000251641325250447100222470ustar00rootroot00000000000000 2014-01-11 ISC Internet Systems Consortium, Inc. dnssec-coverage 8 BIND9 dnssec-coverage checks future DNSKEY coverage for a zone 2013 2014 2015 2016 Internet Systems Consortium, Inc. ("ISC") dnssec-coverage zone DESCRIPTION dnssec-coverage verifies that the DNSSEC keys for a given zone or a set of zones have timing metadata set properly to ensure no future lapses in DNSSEC coverage. If is specified, then keys found in the key repository matching that zone are scanned, and an ordered list is generated of the events scheduled for that key (i.e., publication, activation, inactivation, deletion). The list of events is walked in order of occurrence. Warnings are generated if any event is scheduled which could cause the zone to enter a state in which validation failures might occur: for example, if the number of published or active keys for a given algorithm drops to zero, or if a key is deleted from the zone too soon after a new key is rolled, and cached data signed by the prior key has not had time to expire from resolver caches. If is not specified, then all keys in the key repository will be scanned, and all zones for which there are keys will be analyzed. (Note: This method of reporting is only accurate if all the zones that have keys in a given repository share the same TTL parameters.) OPTIONS -K directory Sets the directory in which keys can be found. Defaults to the current working directory. -f file If a is specified, then the zone is read from that file; the largest TTL and the DNSKEY TTL are determined directly from the zone data, and the and options do not need to be specified on the command line. -l duration The length of time to check for DNSSEC coverage. Key events scheduled further into the future than will be ignored, and assumed to be correct. The value of can be set in seconds, or in larger units of time by adding a suffix: 'mi' for minutes, 'h' for hours, 'd' for days, 'w' for weeks, 'mo' for months, 'y' for years. -m maximum TTL Sets the value to be used as the maximum TTL for the zone or zones being analyzed when determining whether there is a possibility of validation failure. When a zone-signing key is deactivated, there must be enough time for the record in the zone with the longest TTL to have expired from resolver caches before that key can be purged from the DNSKEY RRset. If that condition does not apply, a warning will be generated. The length of the TTL can be set in seconds, or in larger units of time by adding a suffix: 'mi' for minutes, 'h' for hours, 'd' for days, 'w' for weeks, 'mo' for months, 'y' for years. This option is not necessary if the has been used to specify a zone file. If has been specified, this option may still be used; it will override the value found in the file. If this option is not used and the maximum TTL cannot be retrieved from a zone file, a warning is generated and a default value of 1 week is used. -d DNSKEY TTL Sets the value to be used as the DNSKEY TTL for the zone or zones being analyzed when determining whether there is a possibility of validation failure. When a key is rolled (that is, replaced with a new key), there must be enough time for the old DNSKEY RRset to have expired from resolver caches before the new key is activated and begins generating signatures. If that condition does not apply, a warning will be generated. The length of the TTL can be set in seconds, or in larger units of time by adding a suffix: 'mi' for minutes, 'h' for hours, 'd' for days, 'w' for weeks, 'mo' for months, 'y' for years. This option is not necessary if has been used to specify a zone file from which the TTL of the DNSKEY RRset can be read, or if a default key TTL was set using ith the to dnssec-keygen. If either of those is true, this option may still be used; it will override the values found in the zone file or the key file. If this option is not used and the key TTL cannot be retrieved from the zone file or the key file, then a warning is generated and a default value of 1 day is used. -r resign interval Sets the value to be used as the resign interval for the zone or zones being analyzed when determining whether there is a possibility of validation failure. This value defaults to 22.5 days, which is also the default in named. However, if it has been changed by the option in named.conf, then it should also be changed here. The length of the interval can be set in seconds, or in larger units of time by adding a suffix: 'mi' for minutes, 'h' for hours, 'd' for days, 'w' for weeks, 'mo' for months, 'y' for years. -k Only check KSK coverage; ignore ZSK events. Cannot be used with . -z Only check ZSK coverage; ignore KSK events. Cannot be used with . -c compilezone path Specifies a path to a named-compilezone binary. Used for testing. SEE ALSO dnssec-checkds8 , dnssec-dsfromkey8 , dnssec-keygen8 , dnssec-signzone8 bind9-9.11.3+dfsg/bin/python/dnssec-coverage.html000066400000000000000000000235521325250447100215720ustar00rootroot00000000000000 dnssec-coverage

Name

dnssec-coverage — checks future DNSKEY coverage for a zone

Synopsis

dnssec-coverage [-K directory] [-l length] [-f file] [-d DNSKEY TTL] [-m max TTL] [-r interval] [-c compilezone path] [-k] [-z] [zone...]

DESCRIPTION

dnssec-coverage verifies that the DNSSEC keys for a given zone or a set of zones have timing metadata set properly to ensure no future lapses in DNSSEC coverage.

If zone is specified, then keys found in the key repository matching that zone are scanned, and an ordered list is generated of the events scheduled for that key (i.e., publication, activation, inactivation, deletion). The list of events is walked in order of occurrence. Warnings are generated if any event is scheduled which could cause the zone to enter a state in which validation failures might occur: for example, if the number of published or active keys for a given algorithm drops to zero, or if a key is deleted from the zone too soon after a new key is rolled, and cached data signed by the prior key has not had time to expire from resolver caches.

If zone is not specified, then all keys in the key repository will be scanned, and all zones for which there are keys will be analyzed. (Note: This method of reporting is only accurate if all the zones that have keys in a given repository share the same TTL parameters.)

OPTIONS

-K directory

Sets the directory in which keys can be found. Defaults to the current working directory.

-f file

If a file is specified, then the zone is read from that file; the largest TTL and the DNSKEY TTL are determined directly from the zone data, and the -m and -d options do not need to be specified on the command line.

-l duration

The length of time to check for DNSSEC coverage. Key events scheduled further into the future than duration will be ignored, and assumed to be correct.

The value of duration can be set in seconds, or in larger units of time by adding a suffix: 'mi' for minutes, 'h' for hours, 'd' for days, 'w' for weeks, 'mo' for months, 'y' for years.

-m maximum TTL

Sets the value to be used as the maximum TTL for the zone or zones being analyzed when determining whether there is a possibility of validation failure. When a zone-signing key is deactivated, there must be enough time for the record in the zone with the longest TTL to have expired from resolver caches before that key can be purged from the DNSKEY RRset. If that condition does not apply, a warning will be generated.

The length of the TTL can be set in seconds, or in larger units of time by adding a suffix: 'mi' for minutes, 'h' for hours, 'd' for days, 'w' for weeks, 'mo' for months, 'y' for years.

This option is not necessary if the -f has been used to specify a zone file. If -f has been specified, this option may still be used; it will override the value found in the file.

If this option is not used and the maximum TTL cannot be retrieved from a zone file, a warning is generated and a default value of 1 week is used.

-d DNSKEY TTL

Sets the value to be used as the DNSKEY TTL for the zone or zones being analyzed when determining whether there is a possibility of validation failure. When a key is rolled (that is, replaced with a new key), there must be enough time for the old DNSKEY RRset to have expired from resolver caches before the new key is activated and begins generating signatures. If that condition does not apply, a warning will be generated.

The length of the TTL can be set in seconds, or in larger units of time by adding a suffix: 'mi' for minutes, 'h' for hours, 'd' for days, 'w' for weeks, 'mo' for months, 'y' for years.

This option is not necessary if -f has been used to specify a zone file from which the TTL of the DNSKEY RRset can be read, or if a default key TTL was set using ith the -L to dnssec-keygen. If either of those is true, this option may still be used; it will override the values found in the zone file or the key file.

If this option is not used and the key TTL cannot be retrieved from the zone file or the key file, then a warning is generated and a default value of 1 day is used.

-r resign interval

Sets the value to be used as the resign interval for the zone or zones being analyzed when determining whether there is a possibility of validation failure. This value defaults to 22.5 days, which is also the default in named. However, if it has been changed by the sig-validity-interval option in named.conf, then it should also be changed here.

The length of the interval can be set in seconds, or in larger units of time by adding a suffix: 'mi' for minutes, 'h' for hours, 'd' for days, 'w' for weeks, 'mo' for months, 'y' for years.

-k

Only check KSK coverage; ignore ZSK events. Cannot be used with -z.

-z

Only check ZSK coverage; ignore KSK events. Cannot be used with -k.

-c compilezone path

Specifies a path to a named-compilezone binary. Used for testing.

SEE ALSO

dnssec-checkds(8) , dnssec-dsfromkey(8) , dnssec-keygen(8) , dnssec-signzone(8)

bind9-9.11.3+dfsg/bin/python/dnssec-coverage.py.in000066400000000000000000000015321325250447100216550ustar00rootroot00000000000000#!@PYTHON@ ############################################################################ # Copyright (C) 2013-2017 Internet Systems Consortium, Inc. ("ISC") # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. ############################################################################ import os import sys sys.path.insert(0, os.path.dirname(sys.argv[0])) if os.name != 'nt': if '@PYTHON_INSTALL_DIR@': # value of --with-python-install-dir sys.path.insert(1, '@PYTHON_INSTALL_DIR@') else: sys.path.insert(1, os.path.join('@prefix@', 'lib', 'python' + sys.version[:3], 'site-packages')) import isc.coverage if __name__ == "__main__": isc.coverage.main() bind9-9.11.3+dfsg/bin/python/dnssec-keymgr.8000066400000000000000000000232761325250447100205030ustar00rootroot00000000000000.\" Copyright (C) 2016, 2017 Internet Systems Consortium, Inc. ("ISC") .\" .\" This Source Code Form is subject to the terms of the Mozilla Public .\" License, v. 2.0. If a copy of the MPL was not distributed with this .\" file, You can obtain one at http://mozilla.org/MPL/2.0/. .\" .hy 0 .ad l '\" t .\" Title: dnssec-keymgr .\" Author: .\" Generator: DocBook XSL Stylesheets v1.78.1 .\" Date: 2016-06-03 .\" Manual: BIND9 .\" Source: ISC .\" Language: English .\" .TH "DNSSEC\-KEYMGR" "8" "2016\-06\-03" "ISC" "BIND9" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" dnssec-keymgr \- Ensures correct DNSKEY coverage for a zone based on a defined policy .SH "SYNOPSIS" .HP \w'\fBdnssec\-keymgr\fR\ 'u \fBdnssec\-keymgr\fR [\fB\-K\ \fR\fB\fIdirectory\fR\fR] [\fB\-c\ \fR\fB\fIfile\fR\fR] [\fB\-f\fR] [\fB\-k\fR] [\fB\-q\fR] [\fB\-v\fR] [\fB\-z\fR] [\fB\-g\ \fR\fB\fIpath\fR\fR] [\fB\-r\ \fR\fB\fIpath\fR\fR] [\fB\-s\ \fR\fB\fIpath\fR\fR] [zone...] .SH "DESCRIPTION" .PP \fBdnssec\-keymgr\fR is a high level Python wrapper to facilitate the key rollover process for zones handled by BIND\&. It uses the BIND commands for manipulating DNSSEC key metadata: \fBdnssec\-keygen\fR and \fBdnssec\-settime\fR\&. .PP DNSSEC policy can be read from a configuration file (default /etc/dnssec\-policy\&.conf), from which the key parameters, publication and rollover schedule, and desired coverage duration for any given zone can be determined\&. This file may be used to define individual DNSSEC policies on a per\-zone basis, or to set a default policy used for all zones\&. .PP When \fBdnssec\-keymgr\fR runs, it examines the DNSSEC keys for one or more zones, comparing their timing metadata against the policies for those zones\&. If key settings do not conform to the DNSSEC policy (for example, because the policy has been changed), they are automatically corrected\&. .PP A zone policy can specify a duration for which we want to ensure the key correctness (\fBcoverage\fR)\&. It can also specify a rollover period (\fBroll\-period\fR)\&. If policy indicates that a key should roll over before the coverage period ends, then a successor key will automatically be created and added to the end of the key series\&. .PP If zones are specified on the command line, \fBdnssec\-keymgr\fR will examine only those zones\&. If a specified zone does not already have keys in place, then keys will be generated for it according to policy\&. .PP If zones are \fInot\fR specified on the command line, then \fBdnssec\-keymgr\fR will search the key directory (either the current working directory or the directory set by the \fB\-K\fR option), and check the keys for all the zones represented in the directory\&. .PP It is expected that this tool will be run automatically and unattended (for example, by \fBcron\fR)\&. .SH "OPTIONS" .PP \-c \fIfile\fR .RS 4 If \fB\-c\fR is specified, then the DNSSEC policy is read from \fBfile\fR\&. (If not specified, then the policy is read from /etc/dnssec\-policy\&.conf; if that file doesn\*(Aqt exist, a built\-in global default policy is used\&.) .RE .PP \-f .RS 4 Force: allow updating of key events even if they are already in the past\&. This is not recommended for use with zones in which keys have already been published\&. However, if a set of keys has been generated all of which have publication and activation dates in the past, but the keys have not been published in a zone as yet, then this option can be used to clean them up and turn them into a proper series of keys with appropriate rollover intervals\&. .RE .PP \-g \fIkeygen\-path\fR .RS 4 Specifies a path to a \fBdnssec\-keygen\fR binary\&. Used for testing\&. See also the \fB\-s\fR option\&. .RE .PP \-h .RS 4 Print the \fBdnssec\-keymgr\fR help summary and exit\&. .RE .PP \-K \fIdirectory\fR .RS 4 Sets the directory in which keys can be found\&. Defaults to the current working directory\&. .RE .PP \-k .RS 4 Only apply policies to KSK keys\&. See also the \fB\-z\fR option\&. .RE .PP \-q .RS 4 Quiet: suppress printing of \fBdnssec\-keygen\fR and \fBdnssec\-settime\fR\&. .RE .PP \-r \fIrandomdev\fR .RS 4 Specifies a path to a file containing random data\&. This is passed to the \fBdnssec\-keygen\fR binary using its \fB\-r\fR option\&. .RE .PP \-s \fIsettime\-path\fR .RS 4 Specifies a path to a \fBdnssec\-settime\fR binary\&. Used for testing\&. See also the \fB\-g\fR option\&. .RE .PP \-v .RS 4 Print the \fBdnssec\-keymgr\fR version and exit\&. .RE .PP \-z .RS 4 Only apply policies to ZSK keys\&. See also the \fB\-k\fR option\&. .RE .SH "POLICY CONFIGURATION" .PP The dnssec\-policy\&.conf file can specify three kinds of policies: .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} \fIPolicy classes\fR (\fBpolicy \fR\fB\fIname\fR\fR\fB { \&.\&.\&. };\fR) can be inherited by zone policies or other policy classes; these can be used to create sets of different security profiles\&. For example, a policy class \fBnormal\fR might specify 1024\-bit key sizes, but a class \fBextra\fR might specify 2048 bits instead; \fBextra\fR would be used for zones that had unusually high security needs\&. .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Algorithm policies: (\fBalgorithm\-policy \fR\fB\fIalgorithm\fR\fR\fB { \&.\&.\&. };\fR ) override default per\-algorithm settings\&. For example, by default, RSASHA256 keys use 2048\-bit key sizes for both KSK and ZSK\&. This can be modified using \fBalgorithm\-policy\fR, and the new key sizes would then be used for any key of type RSASHA256\&. .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Zone policies: (\fBzone \fR\fB\fIname\fR\fR\fB { \&.\&.\&. };\fR ) set policy for a single zone by name\&. A zone policy can inherit a policy class by including a \fBpolicy\fR option\&. Zone names beginning with digits (i\&.e\&., 0\-9) must be quoted\&. .RE .PP Options that can be specified in policies: .PP \fBalgorithm\fR .RS 4 The key algorithm\&. If no policy is defined, the default is RSASHA256\&. .RE .PP \fBcoverage\fR .RS 4 The length of time to ensure that keys will be correct; no action will be taken to create new keys to be activated after this time\&. This can be represented as a number of seconds, or as a duration using human\-readable units (examples: "1y" or "6 months")\&. A default value for this option can be set in algorithm policies as well as in policy classes or zone policies\&. If no policy is configured, the default is six months\&. .RE .PP \fBdirectory\fR .RS 4 Specifies the directory in which keys should be stored\&. .RE .PP \fBkey\-size\fR .RS 4 Specifies the number of bits to use in creating keys\&. Takes two arguments: keytype (eihter "zsk" or "ksk") and size\&. A default value for this option can be set in algorithm policies as well as in policy classes or zone policies\&. If no policy is configured, the default is 1024 bits for DSA keys and 2048 for RSA\&. .RE .PP \fBkeyttl\fR .RS 4 The key TTL\&. If no policy is defined, the default is one hour\&. .RE .PP \fBpost\-publish\fR .RS 4 How long after inactivation a key should be deleted from the zone\&. Note: If \fBroll\-period\fR is not set, this value is ignored\&. Takes two arguments: keytype (eihter "zsk" or "ksk") and a duration\&. A default value for this option can be set in algorithm policies as well as in policy classes or zone policies\&. The default is one month\&. .RE .PP \fBpre\-publish\fR .RS 4 How long before activation a key should be published\&. Note: If \fBroll\-period\fR is not set, this value is ignored\&. Takes two arguments: keytype (either "zsk" or "ksk") and a duration\&. A default value for this option can be set in algorithm policies as well as in policy classes or zone policies\&. The default is one month\&. .RE .PP \fBroll\-period\fR .RS 4 How frequently keys should be rolled over\&. Takes two arguments: keytype (eihter "zsk" or "ksk") and a duration\&. A default value for this option can be set in algorithm policies as well as in policy classes or zone policies\&. If no policy is configured, the default is one year for ZSK\*(Aqs\&. KSK\*(Aqs do not roll over by default\&. .RE .PP \fBstandby\fR .RS 4 Not yet implemented\&. .RE .SH "REMAINING WORK" .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Enable scheduling of KSK rollovers using the \fB\-P sync\fR and \fB\-D sync\fR options to \fBdnssec\-keygen\fR and \fBdnssec\-settime\fR\&. Check the parent zone (as in \fBdnssec\-checkds\fR) to determine when it\*(Aqs safe for the key to roll\&. .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Allow configuration of standby keys and use of the REVOKE bit, for keys that use RFC 5011 semantics\&. .RE .SH "SEE ALSO" .PP \fBdnssec-coverage\fR(8), \fBdnssec-keygen\fR(8), \fBdnssec-settime\fR(8), \fBdnssec-checkds\fR(8) .SH "AUTHOR" .PP \fBInternet Systems Consortium, Inc\&.\fR .SH "COPYRIGHT" .br Copyright \(co 2016, 2017 Internet Systems Consortium, Inc. ("ISC") .br bind9-9.11.3+dfsg/bin/python/dnssec-keymgr.docbook000066400000000000000000000333651325250447100217540ustar00rootroot00000000000000 2016-06-03 ISC Internet Systems Consortium, Inc. dnssec-keymgr 8 BIND9 dnssec-keymgr Ensures correct DNSKEY coverage for a zone based on a defined policy 2016 2017 Internet Systems Consortium, Inc. ("ISC") dnssec-keymgr zone DESCRIPTION dnssec-keymgr is a high level Python wrapper to facilitate the key rollover process for zones handled by BIND. It uses the BIND commands for manipulating DNSSEC key metadata: dnssec-keygen and dnssec-settime. DNSSEC policy can be read from a configuration file (default /etc/dnssec-policy.conf), from which the key parameters, publication and rollover schedule, and desired coverage duration for any given zone can be determined. This file may be used to define individual DNSSEC policies on a per-zone basis, or to set a default policy used for all zones. When dnssec-keymgr runs, it examines the DNSSEC keys for one or more zones, comparing their timing metadata against the policies for those zones. If key settings do not conform to the DNSSEC policy (for example, because the policy has been changed), they are automatically corrected. A zone policy can specify a duration for which we want to ensure the key correctness (). It can also specify a rollover period (). If policy indicates that a key should roll over before the coverage period ends, then a successor key will automatically be created and added to the end of the key series. If zones are specified on the command line, dnssec-keymgr will examine only those zones. If a specified zone does not already have keys in place, then keys will be generated for it according to policy. If zones are not specified on the command line, then dnssec-keymgr will search the key directory (either the current working directory or the directory set by the option), and check the keys for all the zones represented in the directory. It is expected that this tool will be run automatically and unattended (for example, by cron). OPTIONS -c file If is specified, then the DNSSEC policy is read from . (If not specified, then the policy is read from /etc/dnssec-policy.conf; if that file doesn't exist, a built-in global default policy is used.) -f Force: allow updating of key events even if they are already in the past. This is not recommended for use with zones in which keys have already been published. However, if a set of keys has been generated all of which have publication and activation dates in the past, but the keys have not been published in a zone as yet, then this option can be used to clean them up and turn them into a proper series of keys with appropriate rollover intervals. -g keygen-path Specifies a path to a dnssec-keygen binary. Used for testing. See also the option. -h Print the dnssec-keymgr help summary and exit. -K directory Sets the directory in which keys can be found. Defaults to the current working directory. -k Only apply policies to KSK keys. See also the option. -q Quiet: suppress printing of dnssec-keygen and dnssec-settime. -r randomdev Specifies a path to a file containing random data. This is passed to the dnssec-keygen binary using its option. -s settime-path Specifies a path to a dnssec-settime binary. Used for testing. See also the option. -v Print the dnssec-keymgr version and exit. -z Only apply policies to ZSK keys. See also the option. POLICY CONFIGURATION The dnssec-policy.conf file can specify three kinds of policies: Policy classes () can be inherited by zone policies or other policy classes; these can be used to create sets of different security profiles. For example, a policy class normal might specify 1024-bit key sizes, but a class extra might specify 2048 bits instead; extra would be used for zones that had unusually high security needs. Algorithm policies: ( ) override default per-algorithm settings. For example, by default, RSASHA256 keys use 2048-bit key sizes for both KSK and ZSK. This can be modified using algorithm-policy, and the new key sizes would then be used for any key of type RSASHA256. Zone policies: ( ) set policy for a single zone by name. A zone policy can inherit a policy class by including a option. Zone names beginning with digits (i.e., 0-9) must be quoted. Options that can be specified in policies: algorithm The key algorithm. If no policy is defined, the default is RSASHA256. coverage The length of time to ensure that keys will be correct; no action will be taken to create new keys to be activated after this time. This can be represented as a number of seconds, or as a duration using human-readable units (examples: "1y" or "6 months"). A default value for this option can be set in algorithm policies as well as in policy classes or zone policies. If no policy is configured, the default is six months. directory Specifies the directory in which keys should be stored. key-size Specifies the number of bits to use in creating keys. Takes two arguments: keytype (eihter "zsk" or "ksk") and size. A default value for this option can be set in algorithm policies as well as in policy classes or zone policies. If no policy is configured, the default is 1024 bits for DSA keys and 2048 for RSA. keyttl The key TTL. If no policy is defined, the default is one hour. post-publish How long after inactivation a key should be deleted from the zone. Note: If is not set, this value is ignored. Takes two arguments: keytype (eihter "zsk" or "ksk") and a duration. A default value for this option can be set in algorithm policies as well as in policy classes or zone policies. The default is one month. pre-publish How long before activation a key should be published. Note: If is not set, this value is ignored. Takes two arguments: keytype (either "zsk" or "ksk") and a duration. A default value for this option can be set in algorithm policies as well as in policy classes or zone policies. The default is one month. roll-period How frequently keys should be rolled over. Takes two arguments: keytype (eihter "zsk" or "ksk") and a duration. A default value for this option can be set in algorithm policies as well as in policy classes or zone policies. If no policy is configured, the default is one year for ZSK's. KSK's do not roll over by default. standby Not yet implemented. REMAINING WORK Enable scheduling of KSK rollovers using the and options to dnssec-keygen and dnssec-settime. Check the parent zone (as in dnssec-checkds) to determine when it's safe for the key to roll. Allow configuration of standby keys and use of the REVOKE bit, for keys that use RFC 5011 semantics. SEE ALSO dnssec-coverage8 , dnssec-keygen8 , dnssec-settime8 , dnssec-checkds8 bind9-9.11.3+dfsg/bin/python/dnssec-keymgr.html000066400000000000000000000332471325250447100212770ustar00rootroot00000000000000 dnssec-keymgr

Name

dnssec-keymgr — Ensures correct DNSKEY coverage for a zone based on a defined policy

Synopsis

dnssec-keymgr [-K directory] [-c file] [-f] [-k] [-q] [-v] [-z] [-g path] [-r path] [-s path] [zone...]

DESCRIPTION

dnssec-keymgr is a high level Python wrapper to facilitate the key rollover process for zones handled by BIND. It uses the BIND commands for manipulating DNSSEC key metadata: dnssec-keygen and dnssec-settime.

DNSSEC policy can be read from a configuration file (default /etc/dnssec-policy.conf), from which the key parameters, publication and rollover schedule, and desired coverage duration for any given zone can be determined. This file may be used to define individual DNSSEC policies on a per-zone basis, or to set a default policy used for all zones.

When dnssec-keymgr runs, it examines the DNSSEC keys for one or more zones, comparing their timing metadata against the policies for those zones. If key settings do not conform to the DNSSEC policy (for example, because the policy has been changed), they are automatically corrected.

A zone policy can specify a duration for which we want to ensure the key correctness (coverage). It can also specify a rollover period (roll-period). If policy indicates that a key should roll over before the coverage period ends, then a successor key will automatically be created and added to the end of the key series.

If zones are specified on the command line, dnssec-keymgr will examine only those zones. If a specified zone does not already have keys in place, then keys will be generated for it according to policy.

If zones are not specified on the command line, then dnssec-keymgr will search the key directory (either the current working directory or the directory set by the -K option), and check the keys for all the zones represented in the directory.

It is expected that this tool will be run automatically and unattended (for example, by cron).

OPTIONS

-c file

If -c is specified, then the DNSSEC policy is read from file. (If not specified, then the policy is read from /etc/dnssec-policy.conf; if that file doesn't exist, a built-in global default policy is used.)

-f

Force: allow updating of key events even if they are already in the past. This is not recommended for use with zones in which keys have already been published. However, if a set of keys has been generated all of which have publication and activation dates in the past, but the keys have not been published in a zone as yet, then this option can be used to clean them up and turn them into a proper series of keys with appropriate rollover intervals.

-g keygen-path

Specifies a path to a dnssec-keygen binary. Used for testing. See also the -s option.

-h

Print the dnssec-keymgr help summary and exit.

-K directory

Sets the directory in which keys can be found. Defaults to the current working directory.

-k

Only apply policies to KSK keys. See also the -z option.

-q

Quiet: suppress printing of dnssec-keygen and dnssec-settime.

-r randomdev

Specifies a path to a file containing random data. This is passed to the dnssec-keygen binary using its -r option.

-s settime-path

Specifies a path to a dnssec-settime binary. Used for testing. See also the -g option.

-v

Print the dnssec-keymgr version and exit.

-z

Only apply policies to ZSK keys. See also the -k option.

POLICY CONFIGURATION

The dnssec-policy.conf file can specify three kinds of policies:

  • Policy classes (policy name { ... };) can be inherited by zone policies or other policy classes; these can be used to create sets of different security profiles. For example, a policy class normal might specify 1024-bit key sizes, but a class extra might specify 2048 bits instead; extra would be used for zones that had unusually high security needs.

  • Algorithm policies: (algorithm-policy algorithm { ... }; ) override default per-algorithm settings. For example, by default, RSASHA256 keys use 2048-bit key sizes for both KSK and ZSK. This can be modified using algorithm-policy, and the new key sizes would then be used for any key of type RSASHA256.

  • Zone policies: (zone name { ... }; ) set policy for a single zone by name. A zone policy can inherit a policy class by including a policy option. Zone names beginning with digits (i.e., 0-9) must be quoted.

Options that can be specified in policies:

algorithm

The key algorithm. If no policy is defined, the default is RSASHA256.

coverage

The length of time to ensure that keys will be correct; no action will be taken to create new keys to be activated after this time. This can be represented as a number of seconds, or as a duration using human-readable units (examples: "1y" or "6 months"). A default value for this option can be set in algorithm policies as well as in policy classes or zone policies. If no policy is configured, the default is six months.

directory

Specifies the directory in which keys should be stored.

key-size

Specifies the number of bits to use in creating keys. Takes two arguments: keytype (eihter "zsk" or "ksk") and size. A default value for this option can be set in algorithm policies as well as in policy classes or zone policies. If no policy is configured, the default is 1024 bits for DSA keys and 2048 for RSA.

keyttl

The key TTL. If no policy is defined, the default is one hour.

post-publish

How long after inactivation a key should be deleted from the zone. Note: If roll-period is not set, this value is ignored. Takes two arguments: keytype (eihter "zsk" or "ksk") and a duration. A default value for this option can be set in algorithm policies as well as in policy classes or zone policies. The default is one month.

pre-publish

How long before activation a key should be published. Note: If roll-period is not set, this value is ignored. Takes two arguments: keytype (either "zsk" or "ksk") and a duration. A default value for this option can be set in algorithm policies as well as in policy classes or zone policies. The default is one month.

roll-period

How frequently keys should be rolled over. Takes two arguments: keytype (eihter "zsk" or "ksk") and a duration. A default value for this option can be set in algorithm policies as well as in policy classes or zone policies. If no policy is configured, the default is one year for ZSK's. KSK's do not roll over by default.

standby

Not yet implemented.

REMAINING WORK

  • Enable scheduling of KSK rollovers using the -P sync and -D sync options to dnssec-keygen and dnssec-settime. Check the parent zone (as in dnssec-checkds) to determine when it's safe for the key to roll.

  • Allow configuration of standby keys and use of the REVOKE bit, for keys that use RFC 5011 semantics.

SEE ALSO

dnssec-coverage(8) , dnssec-keygen(8) , dnssec-settime(8) , dnssec-checkds(8)

bind9-9.11.3+dfsg/bin/python/dnssec-keymgr.py.in000066400000000000000000000015271325250447100213640ustar00rootroot00000000000000#!@PYTHON@ ############################################################################ # Copyright (C) 2016, 2017 Internet Systems Consortium, Inc. ("ISC") # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. ############################################################################ import os import sys sys.path.insert(0, os.path.dirname(sys.argv[0])) if os.name != 'nt': if '@PYTHON_INSTALL_DIR@': # value of --with-python-install-dir sys.path.insert(1, '@PYTHON_INSTALL_DIR@') else: sys.path.insert(1, os.path.join('@prefix@', 'lib', 'python' + sys.version[:3], 'site-packages')) import isc.keymgr if __name__ == "__main__": isc.keymgr.main() bind9-9.11.3+dfsg/bin/python/isc/000077500000000000000000000000001325250447100164035ustar00rootroot00000000000000bind9-9.11.3+dfsg/bin/python/isc/Makefile.in000066400000000000000000000016011325250447100204460ustar00rootroot00000000000000# Copyright (C) 2016 Internet Systems Consortium, Inc. ("ISC") # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. srcdir = @srcdir@ VPATH = @srcdir@ top_srcdir = @top_srcdir@ @BIND9_MAKE_INCLUDES@ SUBDIRS = tests PYTHON = @PYTHON@ PYSRCS = __init__.py checkds.py coverage.py dnskey.py eventlist.py \ keydict.py keyevent.py keymgr.py keyseries.py keyzone.py \ policy.py rndc.py utils.py TARGETS = parsetab.py @BIND9_MAKE_RULES@ .SUFFIXES: .py .pyc .py.pyc: $(PYTHON) -m compileall . parsetab.py: policy.py $(PYTHON) policy.py parse /dev/null > /dev/null PYTHONPATH=${srcdir} $(PYTHON) -m parsetab check test: subdirs clean distclean:: rm -f *.pyc parser.out parsetab.py rm -rf __pycache__ build distclean:: rm -rf ${PYSRCS} bind9-9.11.3+dfsg/bin/python/isc/__init__.py.in000066400000000000000000000014741325250447100211270ustar00rootroot00000000000000############################################################################ # Copyright (C) 2016 Internet Systems Consortium, Inc. ("ISC") # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. ############################################################################ __all__ = ['checkds', 'coverage', 'keymgr', 'dnskey', 'eventlist', 'keydict', 'keyevent', 'keyseries', 'keyzone', 'policy', 'parsetab', 'rndc', 'utils'] from isc.dnskey import * from isc.eventlist import * from isc.keydict import * from isc.keyevent import * from isc.keyseries import * from isc.keyzone import * from isc.policy import * from isc.rndc import * from isc.utils import * bind9-9.11.3+dfsg/bin/python/isc/checkds.py.in000066400000000000000000000146141325250447100207740ustar00rootroot00000000000000############################################################################ # Copyright (C) 2012-2016 Internet Systems Consortium, Inc. ("ISC") # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. ############################################################################ import argparse import os import sys from subprocess import Popen, PIPE from isc.utils import prefix,version prog = 'dnssec-checkds' ############################################################################ # SECRR class: # Class for DS/DLV resource record ############################################################################ class SECRR: hashalgs = {1: 'SHA-1', 2: 'SHA-256', 3: 'GOST', 4: 'SHA-384'} rrname = '' rrclass = 'IN' keyid = None keyalg = None hashalg = None digest = '' ttl = 0 def __init__(self, rrtext, dlvname = None): if not rrtext: raise Exception fields = rrtext.decode('ascii').split() if len(fields) < 7: raise Exception if dlvname: self.rrtype = "DLV" self.dlvname = dlvname.lower() parent = fields[0].lower().strip('.').split('.') parent.reverse() dlv = dlvname.split('.') dlv.reverse() while len(dlv) != 0 and len(parent) != 0 and parent[0] == dlv[0]: parent = parent[1:] dlv = dlv[1:] if dlv: raise Exception parent.reverse() self.parent = '.'.join(parent) self.rrname = self.parent + '.' + self.dlvname + '.' else: self.rrtype = "DS" self.rrname = fields[0].lower() fields = fields[1:] if fields[0].upper() in ['IN', 'CH', 'HS']: self.rrclass = fields[0].upper() fields = fields[1:] else: self.ttl = int(fields[0]) self.rrclass = fields[1].upper() fields = fields[2:] if fields[0].upper() != self.rrtype: raise Exception('%s does not match %s' % (fields[0].upper(), self.rrtype)) self.keyid, self.keyalg, self.hashalg = map(int, fields[1:4]) self.digest = ''.join(fields[4:]).upper() def __repr__(self): return '%s %s %s %d %d %d %s' % \ (self.rrname, self.rrclass, self.rrtype, self.keyid, self.keyalg, self.hashalg, self.digest) def __eq__(self, other): return self.__repr__() == other.__repr__() ############################################################################ # check: # Fetch DS/DLV RRset for the given zone from the DNS; fetch DNSKEY # RRset from the masterfile if specified, or from DNS if not. # Generate a set of expected DS/DLV records from the DNSKEY RRset, # and report on congruency. ############################################################################ def check(zone, args, masterfile=None, lookaside=None): rrlist = [] cmd = [args.dig, "+noall", "+answer", "-t", "dlv" if lookaside else "ds", "-q", zone + "." + lookaside if lookaside else zone] fp, _ = Popen(cmd, stdout=PIPE).communicate() for line in fp.splitlines(): rrlist.append(SECRR(line, lookaside)) rrlist = sorted(rrlist, key=lambda rr: (rr.keyid, rr.keyalg, rr.hashalg)) klist = [] if masterfile: cmd = [args.dsfromkey, "-f", masterfile] if lookaside: cmd += ["-l", lookaside] cmd.append(zone) fp, _ = Popen(cmd, stdout=PIPE).communicate() else: intods, _ = Popen([args.dig, "+noall", "+answer", "-t", "dnskey", "-q", zone], stdout=PIPE).communicate() cmd = [args.dsfromkey, "-f", "-"] if lookaside: cmd += ["-l", lookaside] cmd.append(zone) fp, _ = Popen(cmd, stdin=PIPE, stdout=PIPE).communicate(intods) for line in fp.splitlines(): klist.append(SECRR(line, lookaside)) if len(klist) < 1: print("No DNSKEY records found in zone apex") return False found = False for rr in klist: if rr in rrlist: print("%s for KSK %s/%03d/%05d (%s) found in parent" % (rr.rrtype, rr.rrname.strip('.'), rr.keyalg, rr.keyid, SECRR.hashalgs[rr.hashalg])) found = True else: print("%s for KSK %s/%03d/%05d (%s) missing from parent" % (rr.rrtype, rr.rrname.strip('.'), rr.keyalg, rr.keyid, SECRR.hashalgs[rr.hashalg])) if not found: print("No %s records were found for any DNSKEY" % ("DLV" if lookaside else "DS")) return found ############################################################################ # parse_args: # Read command line arguments, set global 'args' structure ############################################################################ def parse_args(): parser = argparse.ArgumentParser(description=prog + ': checks DS coverage') bindir = 'bin' sbindir = 'bin' if os.name == 'nt' else 'sbin' parser.add_argument('zone', type=str, help='zone to check') parser.add_argument('-f', '--file', dest='masterfile', type=str, help='zone master file') parser.add_argument('-l', '--lookaside', dest='lookaside', type=str, help='DLV lookaside zone') parser.add_argument('-d', '--dig', dest='dig', default=os.path.join(prefix(bindir), 'dig'), type=str, help='path to \'dig\'') parser.add_argument('-D', '--dsfromkey', dest='dsfromkey', default=os.path.join(prefix(sbindir), 'dnssec-dsfromkey'), type=str, help='path to \'dig\'') parser.add_argument('-v', '--version', action='version', version=version) args = parser.parse_args() args.zone = args.zone.strip('.') if args.lookaside: args.lookaside = args.lookaside.strip('.') return args ############################################################################ # Main ############################################################################ def main(): args = parse_args() found = check(args.zone, args, args.masterfile, args.lookaside) exit(0 if found else 1) bind9-9.11.3+dfsg/bin/python/isc/coverage.py.in000066400000000000000000000230061325250447100211560ustar00rootroot00000000000000############################################################################ # Copyright (C) 2013-2017 Internet Systems Consortium, Inc. ("ISC") # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. ############################################################################ from __future__ import print_function import os import sys import argparse import glob import re import time import calendar import pprint from collections import defaultdict prog = 'dnssec-coverage' from isc import dnskey, eventlist, keydict, keyevent, keyzone, utils ############################################################################ # print a fatal error and exit ############################################################################ def fatal(*args, **kwargs): print(*args, **kwargs) sys.exit(1) ############################################################################ # output: ############################################################################ _firstline = True def output(*args, **kwargs): """output text, adding a vertical space this is *not* the first first section being printed since a call to vreset()""" global _firstline if 'skip' in kwargs: skip = kwargs['skip'] kwargs.pop('skip', None) else: skip = True if _firstline: _firstline = False elif skip: print('') if args: print(*args, **kwargs) def vreset(): """reset vertical spacing""" global _firstline _firstline = True ############################################################################ # parse_time ############################################################################ def parse_time(s): """ convert a formatted time (e.g., 1y, 6mo, 15mi, etc) into seconds :param s: String with some text representing a time interval :return: Integer with the number of seconds in the time interval """ s = s.strip() # if s is an integer, we're done already try: return int(s) except ValueError: pass # try to parse as a number with a suffix indicating unit of time r = re.compile(r'([0-9][0-9]*)\s*([A-Za-z]*)') m = r.match(s) if not m: raise ValueError("Cannot parse %s" % s) n, unit = m.groups() n = int(n) unit = unit.lower() if unit.startswith('y'): return n * 31536000 elif unit.startswith('mo'): return n * 2592000 elif unit.startswith('w'): return n * 604800 elif unit.startswith('d'): return n * 86400 elif unit.startswith('h'): return n * 3600 elif unit.startswith('mi'): return n * 60 elif unit.startswith('s'): return n else: raise ValueError("Invalid suffix %s" % unit) ############################################################################ # set_path: ############################################################################ def set_path(command, default=None): """ find the location of a specified command. if a default is supplied and it works, we use it; otherwise we search PATH for a match. :param command: string with a command to look for in the path :param default: default location to use :return: detected location for the desired command """ fpath = default if not fpath or not os.path.isfile(fpath) or not os.access(fpath, os.X_OK): path = os.environ["PATH"] if not path: path = os.path.defpath for directory in path.split(os.pathsep): fpath = os.path.join(directory, command) if os.path.isfile(fpath) and os.access(fpath, os.X_OK): break fpath = None return fpath ############################################################################ # parse_args: ############################################################################ def parse_args(): """Read command line arguments, set global 'args' structure""" compilezone = set_path('named-compilezone', os.path.join(utils.prefix('sbin'), 'named-compilezone')) parser = argparse.ArgumentParser(description=prog + ': checks future ' + 'DNSKEY coverage for a zone') parser.add_argument('zone', type=str, nargs='*', default=None, help='zone(s) to check' + '(default: all zones in the directory)') parser.add_argument('-K', dest='path', default='.', type=str, help='a directory containing keys to process', metavar='dir') parser.add_argument('-f', dest='filename', type=str, help='zone master file', metavar='file') parser.add_argument('-m', dest='maxttl', type=str, help='the longest TTL in the zone(s)', metavar='time') parser.add_argument('-d', dest='keyttl', type=str, help='the DNSKEY TTL', metavar='time') parser.add_argument('-r', dest='resign', default='1944000', type=str, help='the RRSIG refresh interval ' 'in seconds [default: 22.5 days]', metavar='time') parser.add_argument('-c', dest='compilezone', default=compilezone, type=str, help='path to \'named-compilezone\'', metavar='path') parser.add_argument('-l', dest='checklimit', type=str, default='0', help='Length of time to check for ' 'DNSSEC coverage [default: 0 (unlimited)]', metavar='time') parser.add_argument('-z', dest='no_ksk', action='store_true', default=False, help='Only check zone-signing keys (ZSKs)') parser.add_argument('-k', dest='no_zsk', action='store_true', default=False, help='Only check key-signing keys (KSKs)') parser.add_argument('-D', '--debug', dest='debug_mode', action='store_true', default=False, help='Turn on debugging output') parser.add_argument('-v', '--version', action='version', version=utils.version) args = parser.parse_args() if args.no_zsk and args.no_ksk: fatal("ERROR: -z and -k cannot be used together.") elif args.no_zsk or args.no_ksk: args.keytype = "KSK" if args.no_zsk else "ZSK" else: args.keytype = None if args.filename and len(args.zone) > 1: fatal("ERROR: -f can only be used with one zone.") # convert from time arguments to seconds try: if args.maxttl: m = parse_time(args.maxttl) args.maxttl = m except ValueError: pass try: if args.keyttl: k = parse_time(args.keyttl) args.keyttl = k except ValueError: pass try: if args.resign: r = parse_time(args.resign) args.resign = r except ValueError: pass try: if args.checklimit: lim = args.checklimit r = parse_time(args.checklimit) if r == 0: args.checklimit = None else: args.checklimit = time.time() + r except ValueError: pass # if we've got the values we need from the command line, stop now if args.maxttl and args.keyttl: return args # load keyttl and maxttl data from zonefile if args.zone and args.filename: try: zone = keyzone(args.zone[0], args.filename, args.compilezone) args.maxttl = args.maxttl or zone.maxttl args.keyttl = args.maxttl or zone.keyttl except Exception as e: print("Unable to load zone data from %s: " % args.filename, e) if not args.maxttl: output("WARNING: Maximum TTL value was not specified. Using 1 week\n" "\t (604800 seconds); re-run with the -m option to get more\n" "\t accurate results.") args.maxttl = 604800 return args ############################################################################ # Main ############################################################################ def main(): args = parse_args() print("PHASE 1--Loading keys to check for internal timing problems") try: kd = keydict(path=args.path, zone=args.zone, keyttl=args.keyttl) except Exception as e: fatal('ERROR: Unable to build key dictionary: ' + str(e)) for key in kd: key.check_prepub(output) if key.sep: key.check_postpub(output) else: key.check_postpub(output, args.maxttl + args.resign) output("PHASE 2--Scanning future key events for coverage failures") vreset() try: elist = eventlist(kd) except Exception as e: fatal('ERROR: Unable to build event list: ' + str(e)) errors = False if not args.zone: if not elist.coverage(None, args.keytype, args.checklimit, output): errors = True else: for zone in args.zone: try: if not elist.coverage(zone, args.keytype, args.checklimit, output): errors = True except: output('ERROR: Coverage check failed for zone ' + zone) sys.exit(1 if errors else 0) bind9-9.11.3+dfsg/bin/python/isc/dnskey.py.in000066400000000000000000000374621325250447100206730ustar00rootroot00000000000000############################################################################ # Copyright (C) 2013-2017 Internet Systems Consortium, Inc. ("ISC") # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. ############################################################################ import os import time import calendar from subprocess import Popen, PIPE ######################################################################## # Class dnskey ######################################################################## class TimePast(Exception): def __init__(self, key, prop, value): super(TimePast, self).__init__('%s time for key %s (%d) is already past' % (prop, key, value)) class dnskey: """An individual DNSSEC key. Identified by path, name, algorithm, keyid. Contains a dictionary of metadata events.""" _PROPS = ('Created', 'Publish', 'Activate', 'Inactive', 'Delete', 'Revoke', 'DSPublish', 'SyncPublish', 'SyncDelete') _OPTS = (None, '-P', '-A', '-I', '-D', '-R', None, '-Psync', '-Dsync') _ALGNAMES = (None, 'RSAMD5', 'DH', 'DSA', 'ECC', 'RSASHA1', 'NSEC3DSA', 'NSEC3RSASHA1', 'RSASHA256', None, 'RSASHA512', None, 'ECCGOST', 'ECDSAP256SHA256', 'ECDSAP384SHA384', 'ED25519', 'ED448') def __init__(self, key, directory=None, keyttl=None): # this makes it possible to use algname as a class or instance method if isinstance(key, tuple) and len(key) == 3: self._dir = directory or '.' (name, alg, keyid) = key self.fromtuple(name, alg, keyid, keyttl) self._dir = directory or os.path.dirname(key) or '.' key = os.path.basename(key) (name, alg, keyid) = key.split('+') name = name[1:-1] alg = int(alg) keyid = int(keyid.split('.')[0]) self.fromtuple(name, alg, keyid, keyttl) def fromtuple(self, name, alg, keyid, keyttl): if name.endswith('.'): fullname = name name = name.rstrip('.') else: fullname = name + '.' keystr = "K%s+%03d+%05d" % (fullname, alg, keyid) key_file = self._dir + (self._dir and os.sep or '') + keystr + ".key" private_file = (self._dir + (self._dir and os.sep or '') + keystr + ".private") self.keystr = keystr self.name = name self.alg = int(alg) self.keyid = int(keyid) self.fullname = fullname kfp = open(key_file, "r") for line in kfp: if line[0] == ';': continue tokens = line.split() if not tokens: continue if tokens[1].lower() in ('in', 'ch', 'hs'): septoken = 3 self.ttl = keyttl else: septoken = 4 self.ttl = int(tokens[1]) if not keyttl else keyttl if (int(tokens[septoken]) & 0x1) == 1: self.sep = True else: self.sep = False kfp.close() pfp = open(private_file, "rU") self.metadata = dict() self._changed = dict() self._delete = dict() self._times = dict() self._fmttime = dict() self._timestamps = dict() self._original = dict() self._origttl = None for line in pfp: line = line.strip() if not line or line[0] in ('!#'): continue punctuation = [line.find(c) for c in ':= '] + [len(line)] found = min([pos for pos in punctuation if pos != -1]) name = line[:found].rstrip() value = line[found:].lstrip(":= ").rstrip() self.metadata[name] = value for prop in dnskey._PROPS: self._changed[prop] = False if prop in self.metadata: t = self.parsetime(self.metadata[prop]) self._times[prop] = t self._fmttime[prop] = self.formattime(t) self._timestamps[prop] = self.epochfromtime(t) self._original[prop] = self._timestamps[prop] else: self._times[prop] = None self._fmttime[prop] = None self._timestamps[prop] = None self._original[prop] = None pfp.close() def commit(self, settime_bin, **kwargs): quiet = kwargs.get('quiet', False) cmd = [] first = True if self._origttl is not None: cmd += ["-L", str(self.ttl)] for prop, opt in zip(dnskey._PROPS, dnskey._OPTS): if not opt or not self._changed[prop]: continue delete = False if prop in self._delete and self._delete[prop]: delete = True when = 'none' if delete else self._fmttime[prop] cmd += [opt, when] first = False if cmd: fullcmd = [settime_bin, "-K", self._dir] + cmd + [self.keystr,] if not quiet: print('# ' + ' '.join(fullcmd)) try: p = Popen(fullcmd, stdout=PIPE, stderr=PIPE) stdout, stderr = p.communicate() if stderr: raise Exception(str(stderr)) except Exception as e: raise Exception('unable to run %s: %s' % (settime_bin, str(e))) self._origttl = None for prop in dnskey._PROPS: self._original[prop] = self._timestamps[prop] self._changed[prop] = False @classmethod def generate(cls, keygen_bin, randomdev, keys_dir, name, alg, keysize, sep, ttl, publish=None, activate=None, **kwargs): quiet = kwargs.get('quiet', False) keygen_cmd = [keygen_bin, "-q", "-K", keys_dir, "-L", str(ttl)] if randomdev: keygen_cmd += ["-r", randomdev] if sep: keygen_cmd.append("-fk") if alg: keygen_cmd += ["-a", alg] if keysize: keygen_cmd += ["-b", str(keysize)] if publish: t = dnskey.timefromepoch(publish) keygen_cmd += ["-P", dnskey.formattime(t)] if activate: t = dnskey.timefromepoch(activate) keygen_cmd += ["-A", dnskey.formattime(activate)] keygen_cmd.append(name) if not quiet: print('# ' + ' '.join(keygen_cmd)) p = Popen(keygen_cmd, stdout=PIPE, stderr=PIPE) stdout, stderr = p.communicate() if stderr: raise Exception('unable to generate key: ' + str(stderr)) try: keystr = stdout.splitlines()[0].decode('ascii') newkey = dnskey(keystr, keys_dir, ttl) return newkey except Exception as e: raise Exception('unable to parse generated key: %s' % str(e)) def generate_successor(self, keygen_bin, randomdev, prepublish, **kwargs): quiet = kwargs.get('quiet', False) if not self.inactive(): raise Exception("predecessor key %s has no inactive date" % self) keygen_cmd = [keygen_bin, "-q", "-K", self._dir, "-S", self.keystr] if self.ttl: keygen_cmd += ["-L", str(self.ttl)] if randomdev: keygen_cmd += ["-r", randomdev] if prepublish: keygen_cmd += ["-i", str(prepublish)] if not quiet: print('# ' + ' '.join(keygen_cmd)) p = Popen(keygen_cmd, stdout=PIPE, stderr=PIPE) stdout, stderr = p.communicate() if stderr: raise Exception('unable to generate key: ' + stderr) try: keystr = stdout.splitlines()[0].decode('ascii') newkey = dnskey(keystr, self._dir, self.ttl) return newkey except: raise Exception('unable to generate successor for key %s' % self) @staticmethod def algstr(alg): name = None if alg in range(len(dnskey._ALGNAMES)): name = dnskey._ALGNAMES[alg] return name if name else ("%03d" % alg) @staticmethod def algnum(alg): if not alg: return None alg = alg.upper() try: return dnskey._ALGNAMES.index(alg) except ValueError: return None def algname(self, alg=None): return self.algstr(alg or self.alg) @staticmethod def timefromepoch(secs): return time.gmtime(secs) @staticmethod def parsetime(string): return time.strptime(string, "%Y%m%d%H%M%S") @staticmethod def epochfromtime(t): return calendar.timegm(t) @staticmethod def formattime(t): return time.strftime("%Y%m%d%H%M%S", t) def setmeta(self, prop, secs, now, **kwargs): force = kwargs.get('force', False) if self._timestamps[prop] == secs: return if self._original[prop] is not None and \ self._original[prop] < now and not force: raise TimePast(self, prop, self._original[prop]) if secs is None: self._changed[prop] = False \ if self._original[prop] is None else True self._delete[prop] = True self._timestamps[prop] = None self._times[prop] = None self._fmttime[prop] = None return t = self.timefromepoch(secs) self._timestamps[prop] = secs self._times[prop] = t self._fmttime[prop] = self.formattime(t) self._changed[prop] = False if \ self._original[prop] == self._timestamps[prop] else True def gettime(self, prop): return self._times[prop] def getfmttime(self, prop): return self._fmttime[prop] def gettimestamp(self, prop): return self._timestamps[prop] def created(self): return self._timestamps["Created"] def syncpublish(self): return self._timestamps["SyncPublish"] def setsyncpublish(self, secs, now=time.time(), **kwargs): self.setmeta("SyncPublish", secs, now, **kwargs) def publish(self): return self._timestamps["Publish"] def setpublish(self, secs, now=time.time(), **kwargs): self.setmeta("Publish", secs, now, **kwargs) def activate(self): return self._timestamps["Activate"] def setactivate(self, secs, now=time.time(), **kwargs): self.setmeta("Activate", secs, now, **kwargs) def revoke(self): return self._timestamps["Revoke"] def setrevoke(self, secs, now=time.time(), **kwargs): self.setmeta("Revoke", secs, now, **kwargs) def inactive(self): return self._timestamps["Inactive"] def setinactive(self, secs, now=time.time(), **kwargs): self.setmeta("Inactive", secs, now, **kwargs) def delete(self): return self._timestamps["Delete"] def setdelete(self, secs, now=time.time(), **kwargs): self.setmeta("Delete", secs, now, **kwargs) def syncdelete(self): return self._timestamps["SyncDelete"] def setsyncdelete(self, secs, now=time.time(), **kwargs): self.setmeta("SyncDelete", secs, now, **kwargs) def setttl(self, ttl): if ttl is None or self.ttl == ttl: return elif self._origttl is None: self._origttl = self.ttl self.ttl = ttl elif self._origttl == ttl: self._origttl = None self.ttl = ttl else: self.ttl = ttl def keytype(self): return ("KSK" if self.sep else "ZSK") def __str__(self): return ("%s/%s/%05d" % (self.name, self.algname(), self.keyid)) def __repr__(self): return ("%s/%s/%05d (%s)" % (self.name, self.algname(), self.keyid, ("KSK" if self.sep else "ZSK"))) def date(self): return (self.activate() or self.publish() or self.created()) # keys are sorted first by zone name, then by algorithm. within # the same name/algorithm, they are sorted according to their # 'date' value: the activation date if set, OR the publication # if set, OR the creation date. def __lt__(self, other): if self.name != other.name: return self.name < other.name if self.alg != other.alg: return self.alg < other.alg return self.date() < other.date() def check_prepub(self, output=None): def noop(*args, **kwargs): pass if not output: output = noop now = int(time.time()) a = self.activate() p = self.publish() if not a: return False if not p: if a > now: output("WARNING: Key %s is scheduled for\n" "\t activation but not for publication." % repr(self)) return False if p <= now and a <= now: return True if p == a: output("WARNING: %s is scheduled to be\n" "\t published and activated at the same time. This\n" "\t could result in a coverage gap if the zone was\n" "\t previously signed. Activation should be at least\n" "\t %s after publication." % (repr(self), dnskey.duration(self.ttl) or 'one DNSKEY TTL')) return True if a < p: output("WARNING: Key %s is active before it is published" % repr(self)) return False if self.ttl is not None and a - p < self.ttl: output("WARNING: Key %s is activated too soon\n" "\t after publication; this could result in coverage \n" "\t gaps due to resolver caches containing old data.\n" "\t Activation should be at least %s after\n" "\t publication." % (repr(self), dnskey.duration(self.ttl) or 'one DNSKEY TTL')) return False return True def check_postpub(self, output = None, timespan = None): def noop(*args, **kwargs): pass if output is None: output = noop if timespan is None: timespan = self.ttl now = time.time() d = self.delete() i = self.inactive() if not d: return False if not i: if d > now: output("WARNING: Key %s is scheduled for\n" "\t deletion but not for inactivation." % repr(self)) return False if d < now and i < now: return True if d < i: output("WARNING: Key %s is scheduled for\n" "\t deletion before inactivation." % repr(self)) return False if d - i < timespan: output("WARNING: Key %s scheduled for\n" "\t deletion too soon after deactivation; this may \n" "\t result in coverage gaps due to resolver caches\n" "\t containing old data. Deletion should be at least\n" "\t %s after inactivation." % (repr(self), dnskey.duration(timespan))) return False return True @staticmethod def duration(secs): if not secs: return None units = [("year", 60*60*24*365), ("month", 60*60*24*30), ("day", 60*60*24), ("hour", 60*60), ("minute", 60), ("second", 1)] output = [] for unit in units: v, secs = secs // unit[1], secs % unit[1] if v > 0: output.append("%d %s%s" % (v, unit[0], "s" if v > 1 else "")) return ", ".join(output) bind9-9.11.3+dfsg/bin/python/isc/eventlist.py.in000066400000000000000000000131611325250447100214010ustar00rootroot00000000000000############################################################################ # Copyright (C) 2015, 2016 Internet Systems Consortium, Inc. ("ISC") # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. ############################################################################ from collections import defaultdict from .dnskey import * from .keydict import * from .keyevent import * class eventlist: _K = defaultdict(lambda: defaultdict(list)) _Z = defaultdict(lambda: defaultdict(list)) _zones = set() _kdict = None def __init__(self, kdict): properties = ["SyncPublish", "Publish", "SyncDelete", "Activate", "Inactive", "Delete"] self._kdict = kdict for zone in kdict.zones(): self._zones.add(zone) for alg, keys in kdict[zone].items(): for k in keys.values(): for prop in properties: t = k.gettime(prop) if not t: continue e = keyevent(prop, k, t) if k.sep: self._K[zone][alg].append(e) else: self._Z[zone][alg].append(e) self._K[zone][alg] = sorted(self._K[zone][alg], key=lambda event: event.when) self._Z[zone][alg] = sorted(self._Z[zone][alg], key=lambda event: event.when) # scan events per zone, algorithm, and key type, in order of # occurrance, noting inconsistent states when found def coverage(self, zone, keytype, until, output = None): def noop(*args, **kwargs): pass if not output: output = noop no_zsk = True if (keytype and keytype == "KSK") else False no_ksk = True if (keytype and keytype == "ZSK") else False kok = zok = True found = False if zone and not zone in self._zones: output("ERROR: No key events found for %s" % zone) return False if zone: found = True if not no_ksk: kok = self.checkzone(zone, "KSK", until, output) if not no_zsk: zok = self.checkzone(zone, "ZSK", until, output) else: for z in self._zones: if not no_ksk and z in self._K.keys(): found = True kok = self.checkzone(z, "KSK", until, output) if not no_zsk and z in self._Z.keys(): found = True kok = self.checkzone(z, "ZSK", until, output) if not found: output("ERROR: No key events found") return False return (kok and zok) def checkzone(self, zone, keytype, until, output): allok = True if keytype == "KSK": kz = self._K[zone] else: kz = self._Z[zone] for alg in kz.keys(): output("Checking scheduled %s events for zone %s, " "algorithm %s..." % (keytype, zone, dnskey.algstr(alg))) ok = eventlist.checkset(kz[alg], keytype, until, output) if ok: output("No errors found") allok = allok and ok return allok @staticmethod def showset(eventset, output): if not eventset: return output(" " + eventset[0].showtime() + ":", skip=False) for event in eventset: output(" %s: %s" % (event.what, repr(event.key)), skip=False) @staticmethod def checkset(eventset, keytype, until, output): groups = list() group = list() # collect up all events that have the same time eventsfound = False for event in eventset: # we found an event eventsfound = True # add event to current group if (not group or group[0].when == event.when): group.append(event) # if we're at the end of the list, we're done. if # we've found an event with a later time, start a new group if (group[0].when != event.when): groups.append(group) group = list() group.append(event) if group: groups.append(group) if not eventsfound: output("ERROR: No %s events found" % keytype) return False active = published = None for group in groups: if (until and calendar.timegm(group[0].when) > until): output("Ignoring events after %s" % time.strftime("%a %b %d %H:%M:%S UTC %Y", time.gmtime(until))) return True for event in group: (active, published) = event.status(active, published) eventlist.showset(group, output) # and then check for inconsistencies: if not active: output("ERROR: No %s's are active after this event" % keytype) return False elif not published: output("ERROR: No %s's are published after this event" % keytype) return False elif not published.intersection(active): output("ERROR: No %s's are both active and published " "after this event" % keytype) return False return True bind9-9.11.3+dfsg/bin/python/isc/keydict.py.in000066400000000000000000000051021325250447100210140ustar00rootroot00000000000000############################################################################ # Copyright (C) 2016 Internet Systems Consortium, Inc. ("ISC") # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. ############################################################################ from collections import defaultdict from . import dnskey import os import glob ######################################################################## # Class keydict ######################################################################## class keydict: """ A dictionary of keys, indexed by name, algorithm, and key id """ _keydict = defaultdict(lambda: defaultdict(dict)) _defttl = None _missing = [] def __init__(self, dp=None, **kwargs): self._defttl = kwargs.get('keyttl', None) zones = kwargs.get('zones', None) if not zones: path = kwargs.get('path',None) or '.' self.readall(path) else: for zone in zones: if 'path' in kwargs and kwargs['path'] is not None: path = kwargs['path'] else: path = dp and dp.policy(zone).directory or '.' if not self.readone(path, zone): self._missing.append(zone) def readall(self, path): files = glob.glob(os.path.join(path, '*.private')) for infile in files: key = dnskey(infile, path, self._defttl) self._keydict[key.name][key.alg][key.keyid] = key def readone(self, path, zone): match='K' + zone + '.+*.private' files = glob.glob(os.path.join(path, match)) found = False for infile in files: key = dnskey(infile, path, self._defttl) if key.name != zone: # shouldn't ever happen continue self._keydict[key.name][key.alg][key.keyid] = key found = True return found def __iter__(self): for zone, algorithms in self._keydict.items(): for alg, keys in algorithms.items(): for key in keys.values(): yield key def __getitem__(self, name): return self._keydict[name] def zones(self): return (self._keydict.keys()) def algorithms(self, zone): return (self._keydict[zone].keys()) def keys(self, zone, alg): return (self._keydict[zone][alg].keys()) def missing(self): return (self._missing) bind9-9.11.3+dfsg/bin/python/isc/keyevent.py.in000066400000000000000000000052431325250447100212200ustar00rootroot00000000000000############################################################################ # Copyright (C) 2013-2016 Internet Systems Consortium, Inc. ("ISC") # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. ############################################################################ import time ######################################################################## # Class keyevent ######################################################################## class keyevent: """ A discrete key event, e.g., Publish, Activate, Inactive, Delete, etc. Stores the date of the event, and identifying information about the key to which the event will occur.""" def __init__(self, what, key, when=None): self.what = what self.when = when or key.gettime(what) self.key = key self.sep = key.sep self.zone = key.name self.alg = key.alg self.keyid = key.keyid def __repr__(self): return repr((self.when, self.what, self.keyid, self.sep, self.zone, self.alg)) def showtime(self): return time.strftime("%a %b %d %H:%M:%S UTC %Y", self.when) # update sets of active and published keys, based on # the contents of this keyevent def status(self, active, published, output = None): def noop(*args, **kwargs): pass if not output: output = noop if not active: active = set() if not published: published = set() if self.what == "Activate": active.add(self.keyid) elif self.what == "Publish": published.add(self.keyid) elif self.what == "Inactive": if self.keyid not in active: output("\tWARNING: %s scheduled to become inactive " "before it is active" % repr(self.key)) else: active.remove(self.keyid) elif self.what == "Delete": if self.keyid in published: published.remove(self.keyid) else: output("WARNING: key %s is scheduled for deletion " "before it is published" % repr(self.key)) elif self.what == "Revoke": # We don't need to worry about the logic of this one; # just stop counting this key as either active or published if self.keyid in published: published.remove(self.keyid) if self.keyid in active: active.remove(self.keyid) return active, published bind9-9.11.3+dfsg/bin/python/isc/keymgr.py.in000066400000000000000000000143761325250447100206730ustar00rootroot00000000000000############################################################################ # Copyright (C) 2016 Internet Systems Consortium, Inc. ("ISC") # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. ############################################################################ from __future__ import print_function import os, sys, argparse, glob, re, time, calendar, pprint from collections import defaultdict prog='dnssec-keymgr' from isc import dnskey, keydict, keyseries, policy, parsetab, utils ############################################################################ # print a fatal error and exit ############################################################################ def fatal(*args, **kwargs): print(*args, **kwargs) sys.exit(1) ############################################################################ # find the location of an external command ############################################################################ def set_path(command, default=None): """ find the location of a specified command. If a default is supplied, exists and it's an executable, we use it; otherwise we search PATH for an alternative. :param command: command to look for :param default: default value to use :return: PATH with the location of a suitable binary """ fpath = default if not fpath or not os.path.isfile(fpath) or not os.access(fpath, os.X_OK): path = os.environ["PATH"] if not path: path = os.path.defpath for directory in path.split(os.pathsep): fpath = directory + os.sep + command if os.path.isfile(fpath) and os.access(fpath, os.X_OK): break fpath = None return fpath ############################################################################ # parse arguments ############################################################################ def parse_args(): """ Read command line arguments, returns 'args' object :return: args object properly prepared """ keygen = set_path('dnssec-keygen', os.path.join(utils.prefix('sbin'), 'dnssec-keygen')) settime = set_path('dnssec-settime', os.path.join(utils.prefix('sbin'), 'dnssec-settime')) parser = argparse.ArgumentParser(description=prog + ': schedule ' 'DNSSEC key rollovers according to a ' 'pre-defined policy') parser.add_argument('zone', type=str, nargs='*', default=None, help='Zone(s) to which the policy should be applied ' + '(default: all zones in the directory)') parser.add_argument('-K', dest='path', type=str, help='Directory containing keys', metavar='dir') parser.add_argument('-c', dest='policyfile', type=str, help='Policy definition file', metavar='file') parser.add_argument('-g', dest='keygen', default=keygen, type=str, help='Path to \'dnssec-keygen\'', metavar='path') parser.add_argument('-r', dest='randomdev', type=str, default=None, help='Path to a file containing random data to pass to \'dnssec-keygen\'', metavar='path') parser.add_argument('-s', dest='settime', default=settime, type=str, help='Path to \'dnssec-settime\'', metavar='path') parser.add_argument('-k', dest='no_zsk', action='store_true', default=False, help='Only apply policy to key-signing keys (KSKs)') parser.add_argument('-z', dest='no_ksk', action='store_true', default=False, help='Only apply policy to zone-signing keys (ZSKs)') parser.add_argument('-f', '--force', dest='force', action='store_true', default=False, help='Force updates to key events '+ 'even if they are in the past') parser.add_argument('-q', '--quiet', dest='quiet', action='store_true', default=False, help='Update keys silently') parser.add_argument('-v', '--version', action='version', version=utils.version) args = parser.parse_args() if args.no_zsk and args.no_ksk: fatal("ERROR: -z and -k cannot be used together.") if args.keygen is None: fatal("ERROR: dnssec-keygen not found") if args.settime is None: fatal("ERROR: dnssec-settime not found") # if a policy file was specified, check that it exists. # if not, use the default file, unless it doesn't exist if args.policyfile is not None: if not os.path.exists(args.policyfile): fatal('ERROR: Policy file "%s" not found' % args.policyfile) else: args.policyfile = os.path.join(utils.sysconfdir, 'dnssec-policy.conf') if not os.path.exists(args.policyfile): args.policyfile = None return args ############################################################################ # main ############################################################################ def main(): args = parse_args() # As we may have specific locations for the binaries, we put that info # into a context object that can be passed around context = {'keygen_path': args.keygen, 'settime_path': args.settime, 'keys_path': args.path, 'randomdev': args.randomdev} try: dp = policy.dnssec_policy(args.policyfile) except Exception as e: fatal('Unable to load DNSSEC policy: ' + str(e)) try: kd = keydict(dp, path=args.path, zones=args.zone) except Exception as e: fatal('Unable to build key dictionary: ' + str(e)) try: ks = keyseries(kd, context=context) except Exception as e: fatal('Unable to build key series: ' + str(e)) try: ks.enforce_policy(dp, ksk=args.no_zsk, zsk=args.no_ksk, force=args.force, quiet=args.quiet) except Exception as e: fatal('Unable to apply policy: ' + str(e)) bind9-9.11.3+dfsg/bin/python/isc/keyseries.py.in000066400000000000000000000163631325250447100213760ustar00rootroot00000000000000############################################################################ # Copyright (C) 2016 Internet Systems Consortium, Inc. ("ISC") # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. ############################################################################ from collections import defaultdict from .dnskey import * from .keydict import * from .keyevent import * from .policy import * import time class keyseries: _K = defaultdict(lambda: defaultdict(list)) _Z = defaultdict(lambda: defaultdict(list)) _zones = set() _kdict = None _context = None def __init__(self, kdict, now=time.time(), context=None): self._kdict = kdict self._context = context self._zones = set(kdict.missing()) for zone in kdict.zones(): self._zones.add(zone) for alg, keys in kdict[zone].items(): for k in keys.values(): if k.sep: if not (k.delete() and k.delete() < now): self._K[zone][alg].append(k) else: if not (k.delete() and k.delete() < now): self._Z[zone][alg].append(k) self._K[zone][alg].sort() self._Z[zone][alg].sort() def __iter__(self): for zone in self._zones: for collection in [self._K, self._Z]: if zone not in collection: continue for alg, keys in collection[zone].items(): for key in keys: yield key def dump(self): for k in self: print("%s" % repr(k)) def fixseries(self, keys, policy, now, **kwargs): force = kwargs.get('force', False) if not keys: return # handle the first key key = keys[0] if key.sep: rp = policy.ksk_rollperiod prepub = policy.ksk_prepublish or (30 * 86400) postpub = policy.ksk_postpublish or (30 * 86400) else: rp = policy.zsk_rollperiod prepub = policy.zsk_prepublish or (30 * 86400) postpub = policy.zsk_postpublish or (30 * 86400) # the first key should be published and active p = key.publish() a = key.activate() if not p or p > now: key.setpublish(now) if not a or a > now: key.setactivate(now) if not rp: key.setinactive(None, **kwargs) key.setdelete(None, **kwargs) else: key.setinactive(a + rp, **kwargs) key.setdelete(a + rp + postpub, **kwargs) if policy.keyttl != key.ttl: key.setttl(policy.keyttl) # handle all the subsequent keys prev = key for key in keys[1:]: # if no rollperiod, then all keys after the first in # the series kept inactive. # (XXX: we need to change this to allow standby keys) if not rp: key.setpublish(None, **kwargs) key.setactivate(None, **kwargs) key.setinactive(None, **kwargs) key.setdelete(None, **kwargs) if policy.keyttl != key.ttl: key.setttl(policy.keyttl) continue # otherwise, ensure all dates are set correctly based on # the initial key a = prev.inactive() p = a - prepub key.setactivate(a, **kwargs) key.setpublish(p, **kwargs) key.setinactive(a + rp, **kwargs) key.setdelete(a + rp + postpub, **kwargs) prev.setdelete(a + postpub, **kwargs) if policy.keyttl != key.ttl: key.setttl(policy.keyttl) prev = key # if we haven't got sufficient coverage, create successor key(s) while rp and prev.inactive() and \ prev.inactive() < now + policy.coverage: # commit changes to predecessor: a successor can only be # generated if Inactive has been set in the predecessor key prev.commit(self._context['settime_path'], **kwargs) key = prev.generate_successor(self._context['keygen_path'], self._context['randomdev'], prepub, **kwargs) key.setinactive(key.activate() + rp, **kwargs) key.setdelete(key.inactive() + postpub, **kwargs) keys.append(key) prev = key # last key? we already know we have sufficient coverage now, so # disable the inactivation of the final key (if it was set), # ensuring that if dnssec-keymgr isn't run again, the last key # in the series will at least remain usable. prev.setinactive(None, **kwargs) prev.setdelete(None, **kwargs) # commit changes for key in keys: key.commit(self._context['settime_path'], **kwargs) def enforce_policy(self, policies, now=time.time(), **kwargs): # If zones is provided as a parameter, use that list. # If not, use what we have in this object zones = kwargs.get('zones', self._zones) keys_dir = kwargs.get('dir', self._context.get('keys_path', None)) force = kwargs.get('force', False) for zone in zones: collections = [] policy = policies.policy(zone) keys_dir = keys_dir or policy.directory or '.' alg = policy.algorithm algnum = dnskey.algnum(alg) if 'ksk' not in kwargs or not kwargs['ksk']: if len(self._Z[zone][algnum]) == 0: k = dnskey.generate(self._context['keygen_path'], self._context['randomdev'], keys_dir, zone, alg, policy.zsk_keysize, False, policy.keyttl or 3600, **kwargs) self._Z[zone][algnum].append(k) collections.append(self._Z[zone]) if 'zsk' not in kwargs or not kwargs['zsk']: if len(self._K[zone][algnum]) == 0: k = dnskey.generate(self._context['keygen_path'], self._context['randomdev'], keys_dir, zone, alg, policy.ksk_keysize, True, policy.keyttl or 3600, **kwargs) self._K[zone][algnum].append(k) collections.append(self._K[zone]) for collection in collections: for algorithm, keys in collection.items(): if algorithm != algnum: continue try: self.fixseries(keys, policy, now, **kwargs) except Exception as e: raise Exception('%s/%s: %s' % (zone, dnskey.algstr(algnum), str(e))) bind9-9.11.3+dfsg/bin/python/isc/keyzone.py.in000066400000000000000000000034051325250447100210500ustar00rootroot00000000000000############################################################################ # Copyright (C) 2013-2016 Internet Systems Consortium, Inc. ("ISC") # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. ############################################################################ import os import sys import re from subprocess import Popen, PIPE ######################################################################## # Exceptions ######################################################################## class KeyZoneException(Exception): pass ######################################################################## # class keyzone ######################################################################## class keyzone: """reads a zone file to find data relevant to keys""" def __init__(self, name, filename, czpath): self.maxttl = None self.keyttl = None if not name: return if not czpath or not os.path.isfile(czpath) \ or not os.access(czpath, os.X_OK): raise KeyZoneException('"named-compilezone" not found') return maxttl = keyttl = None fp, _ = Popen([czpath, "-o", "-", name, filename], stdout=PIPE, stderr=PIPE).communicate() for line in fp.splitlines(): if re.search('^[:space:]*;', line): continue fields = line.split() if not maxttl or int(fields[1]) > maxttl: maxttl = int(fields[1]) if fields[3] == "DNSKEY": keyttl = int(fields[1]) self.keyttl = keyttl self.maxttl = maxttl bind9-9.11.3+dfsg/bin/python/isc/policy.py.in000066400000000000000000000633131325250447100206670ustar00rootroot00000000000000############################################################################ # Copyright (C) 2016, 2017 Internet Systems Consortium, Inc. ("ISC") # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. ############################################################################ import re import ply.lex as lex import ply.yacc as yacc from string import * from copy import copy ############################################################################ # PolicyLex: a lexer for the policy file syntax. ############################################################################ class PolicyLex: reserved = ('POLICY', 'ALGORITHM_POLICY', 'ZONE', 'ALGORITHM', 'DIRECTORY', 'KEYTTL', 'KEY_SIZE', 'ROLL_PERIOD', 'PRE_PUBLISH', 'POST_PUBLISH', 'COVERAGE', 'STANDBY', 'NONE') tokens = reserved + ('DATESUFFIX', 'KEYTYPE', 'ALGNAME', 'STR', 'QSTRING', 'NUMBER', 'LBRACE', 'RBRACE', 'SEMI') reserved_map = {} t_ignore = ' \t' t_ignore_olcomment = r'(//|\#).*' t_LBRACE = r'\{' t_RBRACE = r'\}' t_SEMI = r';'; def t_newline(self, t): r'\n+' t.lexer.lineno += t.value.count("\n") def t_comment(self, t): r'/\*(.|\n)*?\*/' t.lexer.lineno += t.value.count('\n') def t_DATESUFFIX(self, t): r'(?i)(?<=[0-9 \t])(y(?:ears|ear|ea|e)?|mo(?:nths|nth|nt|n)?|w(?:eeks|eek|ee|e)?|d(?:ays|ay|a)?|h(?:ours|our|ou|o)?|mi(?:nutes|nute|nut|nu|n)?|s(?:econds|econd|econ|eco|ec|e)?)\b' t.value = re.match(r'(?i)(y|mo|w|d|h|mi|s)([a-z]*)', t.value).group(1).lower() return t def t_KEYTYPE(self, t): r'(?i)\b(KSK|ZSK)\b' t.value = t.value.upper() return t def t_ALGNAME(self, t): r'(?i)\b(RSAMD5|DH|DSA|NSEC3DSA|ECC|RSASHA1|NSEC3RSASHA1|RSASHA256|RSASHA512|ECCGOST|ECDSAP256SHA256|ECDSAP384SHA384|ED25519|ED448)\b' t.value = t.value.upper() return t def t_STR(self, t): r'[A-Za-z._-][\w._-]*' t.type = self.reserved_map.get(t.value, "STR") return t def t_QSTRING(self, t): r'"([^"\n]|(\\"))*"' t.type = self.reserved_map.get(t.value, "QSTRING") t.value = t.value[1:-1] return t def t_NUMBER(self, t): r'\d+' t.value = int(t.value) return t def t_error(self, t): print("Illegal character '%s'" % t.value[0]) t.lexer.skip(1) def __init__(self, **kwargs): if 'maketrans' in dir(str): trans = str.maketrans('_', '-') else: trans = maketrans('_', '-') for r in self.reserved: self.reserved_map[r.lower().translate(trans)] = r self.lexer = lex.lex(object=self, **kwargs) def test(self, text): self.lexer.input(text) while True: t = self.lexer.token() if not t: break print(t) ############################################################################ # Policy: this object holds a set of DNSSEC policy settings. ############################################################################ class Policy: is_zone = False is_alg = False is_constructed = False ksk_rollperiod = None zsk_rollperiod = None ksk_prepublish = None zsk_prepublish = None ksk_postpublish = None zsk_postpublish = None ksk_keysize = None zsk_keysize = None ksk_standby = None zsk_standby = None keyttl = None coverage = None directory = None valid_key_sz_per_algo = {'DSA': [512, 1024], 'NSEC3DSA': [512, 1024], 'RSAMD5': [512, 4096], 'RSASHA1': [512, 4096], 'NSEC3RSASHA1': [512, 4096], 'RSASHA256': [512, 4096], 'RSASHA512': [512, 4096], 'ECCGOST': None, 'ECDSAP256SHA256': None, 'ECDSAP384SHA384': None, 'ED25519': None, 'ED448': None} def __init__(self, name=None, algorithm=None, parent=None): self.name = name self.algorithm = algorithm self.parent = parent pass def __repr__(self): return ("%spolicy %s:\n" "\tinherits %s\n" "\tdirectory %s\n" "\talgorithm %s\n" "\tcoverage %s\n" "\tksk_keysize %s\n" "\tzsk_keysize %s\n" "\tksk_rollperiod %s\n" "\tzsk_rollperiod %s\n" "\tksk_prepublish %s\n" "\tksk_postpublish %s\n" "\tzsk_prepublish %s\n" "\tzsk_postpublish %s\n" "\tksk_standby %s\n" "\tzsk_standby %s\n" "\tkeyttl %s\n" % ((self.is_constructed and 'constructed ' or \ self.is_zone and 'zone ' or \ self.is_alg and 'algorithm ' or ''), self.name or 'UNKNOWN', self.parent and self.parent.name or 'None', self.directory and ('"' + str(self.directory) + '"') or 'None', self.algorithm or 'None', self.coverage and str(self.coverage) or 'None', self.ksk_keysize and str(self.ksk_keysize) or 'None', self.zsk_keysize and str(self.zsk_keysize) or 'None', self.ksk_rollperiod and str(self.ksk_rollperiod) or 'None', self.zsk_rollperiod and str(self.zsk_rollperiod) or 'None', self.ksk_prepublish and str(self.ksk_prepublish) or 'None', self.ksk_postpublish and str(self.ksk_postpublish) or 'None', self.zsk_prepublish and str(self.zsk_prepublish) or 'None', self.zsk_postpublish and str(self.zsk_postpublish) or 'None', self.ksk_standby and str(self.ksk_standby) or 'None', self.zsk_standby and str(self.zsk_standby) or 'None', self.keyttl and str(self.keyttl) or 'None')) def __verify_size(self, key_size, size_range): return (size_range[0] <= key_size <= size_range[1]) def get_name(self): return self.name def constructed(self): return self.is_constructed def validate(self): """ Check if the values in the policy make sense :return: True/False if the policy passes validation """ if self.ksk_rollperiod and \ self.ksk_prepublish is not None and \ self.ksk_prepublish > self.ksk_rollperiod: print(self.ksk_rollperiod) return (False, ('KSK pre-publish period (%d) exceeds rollover period %d' % (self.ksk_prepublish, self.ksk_rollperiod))) if self.ksk_rollperiod and \ self.ksk_postpublish is not None and \ self.ksk_postpublish > self.ksk_rollperiod: return (False, ('KSK post-publish period (%d) exceeds rollover period %d' % (self.ksk_postpublish, self.ksk_rollperiod))) if self.zsk_rollperiod and \ self.zsk_prepublish is not None and \ self.zsk_prepublish >= self.zsk_rollperiod: return (False, ('ZSK pre-publish period (%d) exceeds rollover period %d' % (self.zsk_prepublish, self.zsk_rollperiod))) if self.zsk_rollperiod and \ self.zsk_postpublish is not None and \ self.zsk_postpublish >= self.zsk_rollperiod: return (False, ('ZSK post-publish period (%d) exceeds rollover period %d' % (self.zsk_postpublish, self.zsk_rollperiod))) if self.ksk_rollperiod and \ self.ksk_prepublish and self.ksk_postpublish and \ self.ksk_prepublish + self.ksk_postpublish >= self.ksk_rollperiod: return (False, (('KSK pre/post-publish periods (%d/%d) ' + 'combined exceed rollover period %d') % (self.ksk_prepublish, self.ksk_postpublish, self.ksk_rollperiod))) if self.zsk_rollperiod and \ self.zsk_prepublish and self.zsk_postpublish and \ self.zsk_prepublish + self.zsk_postpublish >= self.zsk_rollperiod: return (False, (('ZSK pre/post-publish periods (%d/%d) ' + 'combined exceed rollover period %d') % (self.zsk_prepublish, self.zsk_postpublish, self.zsk_rollperiod))) if self.algorithm is not None: # Validate the key size key_sz_range = self.valid_key_sz_per_algo.get(self.algorithm) if key_sz_range is not None: # Verify KSK if not self.__verify_size(self.ksk_keysize, key_sz_range): return False, 'KSK key size %d outside valid range %s' \ % (self.ksk_keysize, key_sz_range) # Verify ZSK if not self.__verify_size(self.zsk_keysize, key_sz_range): return False, 'ZSK key size %d outside valid range %s' \ % (self.zsk_keysize, key_sz_range) # Specific check for DSA keys if self.algorithm in ['DSA', 'NSEC3DSA'] and \ self.ksk_keysize % 64 != 0: return False, \ ('KSK key size %d not divisible by 64 ' + 'as required for DSA') % self.ksk_keysize if self.algorithm in ['DSA', 'NSEC3DSA'] and \ self.zsk_keysize % 64 != 0: return False, \ ('ZSK key size %d not divisible by 64 ' + 'as required for DSA') % self.zsk_keysize if self.algorithm in ['ECCGOST', \ 'ECDSAP256SHA256', \ 'ECDSAP384SHA384', \ 'ED25519', \ 'ED448']: self.ksk_keysize = None self.zsk_keysize = None return True, '' ############################################################################ # dnssec_policy: # This class reads a dnssec.policy file and creates a dictionary of # DNSSEC policy rules from which a policy for a specific zone can # be generated. ############################################################################ class PolicyException(Exception): pass class dnssec_policy: alg_policy = {} named_policy = {} zone_policy = {} current = None filename = None initial = True def __init__(self, filename=None, **kwargs): self.plex = PolicyLex() self.tokens = self.plex.tokens if 'debug' not in kwargs: kwargs['debug'] = False if 'write_tables' not in kwargs: kwargs['write_tables'] = False self.parser = yacc.yacc(module=self, **kwargs) # set defaults self.setup('''policy global { algorithm rsasha256; key-size ksk 2048; key-size zsk 2048; roll-period ksk 0; roll-period zsk 1y; pre-publish ksk 1mo; pre-publish zsk 1mo; post-publish ksk 1mo; post-publish zsk 1mo; standby ksk 0; standby zsk 0; keyttl 1h; coverage 6mo; }; policy default { policy global; };''') p = Policy() p.algorithm = None p.is_alg = True p.ksk_keysize = 2048; p.zsk_keysize = 2048; # set default algorithm policies # these need a lower default key size: self.alg_policy['DSA'] = copy(p) self.alg_policy['DSA'].algorithm = "DSA" self.alg_policy['DSA'].name = "DSA" self.alg_policy['DSA'].ksk_keysize = 1024; self.alg_policy['NSEC3DSA'] = copy(p) self.alg_policy['NSEC3DSA'].algorithm = "NSEC3DSA" self.alg_policy['NSEC3DSA'].name = "NSEC3DSA" self.alg_policy['NSEC3DSA'].ksk_keysize = 1024; # these can use default settings self.alg_policy['RSAMD5'] = copy(p) self.alg_policy['RSAMD5'].algorithm = "RSAMD5" self.alg_policy['RSAMD5'].name = "RSAMD5" self.alg_policy['RSASHA1'] = copy(p) self.alg_policy['RSASHA1'].algorithm = "RSASHA1" self.alg_policy['RSASHA1'].name = "RSASHA1" self.alg_policy['NSEC3RSASHA1'] = copy(p) self.alg_policy['NSEC3RSASHA1'].algorithm = "NSEC3RSASHA1" self.alg_policy['NSEC3RSASHA1'].name = "NSEC3RSASHA1" self.alg_policy['RSASHA256'] = copy(p) self.alg_policy['RSASHA256'].algorithm = "RSASHA256" self.alg_policy['RSASHA256'].name = "RSASHA256" self.alg_policy['RSASHA512'] = copy(p) self.alg_policy['RSASHA512'].algorithm = "RSASHA512" self.alg_policy['RSASHA512'].name = "RSASHA512" self.alg_policy['ECCGOST'] = copy(p) self.alg_policy['ECCGOST'].algorithm = "ECCGOST" self.alg_policy['ECCGOST'].name = "ECCGOST" self.alg_policy['ECDSAP256SHA256'] = copy(p) self.alg_policy['ECDSAP256SHA256'].algorithm = "ECDSAP256SHA256" self.alg_policy['ECDSAP256SHA256'].name = "ECDSAP256SHA256" self.alg_policy['ECDSAP256SHA256'].ksk_keysize = None; self.alg_policy['ECDSAP256SHA256'].zsk_keysize = None; self.alg_policy['ECDSAP384SHA384'] = copy(p) self.alg_policy['ECDSAP384SHA384'].algorithm = "ECDSAP384SHA384" self.alg_policy['ECDSAP384SHA384'].name = "ECDSAP384SHA384" self.alg_policy['ECDSAP384SHA384'].ksk_keysize = None; self.alg_policy['ECDSAP384SHA384'].zsk_keysize = None; self.alg_policy['ED25519'] = copy(p) self.alg_policy['ED25519'].algorithm = "ED25519" self.alg_policy['ED25519'].name = "ED25519" self.alg_policy['ED25519'].ksk_keysize = None; self.alg_policy['ED25519'].zsk_keysize = None; self.alg_policy['ED448'] = copy(p) self.alg_policy['ED448'].algorithm = "ED448" self.alg_policy['ED448'].name = "ED448" self.alg_policy['ED448'].ksk_keysize = None; self.alg_policy['ED448'].zsk_keysize = None; if filename: self.load(filename) def load(self, filename): self.filename = filename self.initial = True with open(filename) as f: text = f.read() self.plex.lexer.lineno = 0 self.parser.parse(text) self.filename = None def setup(self, text): self.initial = True self.plex.lexer.lineno = 0 self.parser.parse(text) def policy(self, zone, **kwargs): z = zone.lower() p = None if z in self.zone_policy: p = self.zone_policy[z] if p is None: p = copy(self.named_policy['default']) p.name = zone p.is_constructed = True if p.algorithm is None: parent = p.parent or self.named_policy['default'] while parent and not parent.algorithm: parent = parent.parent p.algorithm = parent and parent.algorithm or None if p.algorithm in self.alg_policy: ap = self.alg_policy[p.algorithm] else: raise PolicyException('algorithm not found') if p.directory is None: parent = p.parent or self.named_policy['default'] while parent is not None and not parent.directory: parent = parent.parent p.directory = parent and parent.directory if p.coverage is None: parent = p.parent or self.named_policy['default'] while parent and not parent.coverage: parent = parent.parent p.coverage = parent and parent.coverage or ap.coverage if p.ksk_keysize is None: parent = p.parent or self.named_policy['default'] while parent.parent and not parent.ksk_keysize: parent = parent.parent p.ksk_keysize = parent and parent.ksk_keysize or ap.ksk_keysize if p.zsk_keysize is None: parent = p.parent or self.named_policy['default'] while parent.parent and not parent.zsk_keysize: parent = parent.parent p.zsk_keysize = parent and parent.zsk_keysize or ap.zsk_keysize if p.ksk_rollperiod is None: parent = p.parent or self.named_policy['default'] while parent.parent and not parent.ksk_rollperiod: parent = parent.parent p.ksk_rollperiod = parent and \ parent.ksk_rollperiod or ap.ksk_rollperiod if p.zsk_rollperiod is None: parent = p.parent or self.named_policy['default'] while parent.parent and not parent.zsk_rollperiod: parent = parent.parent p.zsk_rollperiod = parent and \ parent.zsk_rollperiod or ap.zsk_rollperiod if p.ksk_prepublish is None: parent = p.parent or self.named_policy['default'] while parent.parent and not parent.ksk_prepublish: parent = parent.parent p.ksk_prepublish = parent and \ parent.ksk_prepublish or ap.ksk_prepublish if p.zsk_prepublish is None: parent = p.parent or self.named_policy['default'] while parent.parent and not parent.zsk_prepublish: parent = parent.parent p.zsk_prepublish = parent and \ parent.zsk_prepublish or ap.zsk_prepublish if p.ksk_postpublish is None: parent = p.parent or self.named_policy['default'] while parent.parent and not parent.ksk_postpublish: parent = parent.parent p.ksk_postpublish = parent and \ parent.ksk_postpublish or ap.ksk_postpublish if p.zsk_postpublish is None: parent = p.parent or self.named_policy['default'] while parent.parent and not parent.zsk_postpublish: parent = parent.parent p.zsk_postpublish = parent and \ parent.zsk_postpublish or ap.zsk_postpublish if p.keyttl is None: parent = p.parent or self.named_policy['default'] while parent is not None and not parent.keyttl: parent = parent.parent p.keyttl = parent and parent.keyttl if 'novalidate' not in kwargs or not kwargs['novalidate']: (valid, msg) = p.validate() if not valid: raise PolicyException(msg) return None return p def p_policylist(self, p): '''policylist : init policy | policylist policy''' pass def p_init(self, p): "init :" self.initial = False def p_policy(self, p): '''policy : alg_policy | zone_policy | named_policy''' pass def p_name(self, p): '''name : STR | KEYTYPE | DATESUFFIX''' p[0] = p[1] pass def p_domain(self, p): '''domain : STR | QSTRING | KEYTYPE | DATESUFFIX''' p[0] = p[1].strip() if not re.match(r'^[\w.-][\w.-]*$', p[0]): raise PolicyException('invalid domain') pass def p_new_policy(self, p): "new_policy :" self.current = Policy() def p_alg_policy(self, p): "alg_policy : ALGORITHM_POLICY ALGNAME new_policy alg_option_group SEMI" self.current.name = p[2] self.current.is_alg = True self.alg_policy[p[2]] = self.current pass def p_zone_policy(self, p): "zone_policy : ZONE domain new_policy policy_option_group SEMI" self.current.name = p[2].rstrip('.') self.current.is_zone = True self.zone_policy[p[2].rstrip('.').lower()] = self.current pass def p_named_policy(self, p): "named_policy : POLICY name new_policy policy_option_group SEMI" self.current.name = p[2] self.named_policy[p[2].lower()] = self.current pass def p_duration_1(self, p): "duration : NUMBER" p[0] = p[1] pass def p_duration_2(self, p): "duration : NONE" p[0] = None pass def p_duration_3(self, p): "duration : NUMBER DATESUFFIX" if p[2] == "y": p[0] = p[1] * 31536000 # year elif p[2] == "mo": p[0] = p[1] * 2592000 # month elif p[2] == "w": p[0] = p[1] * 604800 # week elif p[2] == "d": p[0] = p[1] * 86400 # day elif p[2] == "h": p[0] = p[1] * 3600 # hour elif p[2] == "mi": p[0] = p[1] * 60 # minute elif p[2] == "s": p[0] = p[1] # second else: raise PolicyException('invalid duration') def p_policy_option_group(self, p): "policy_option_group : LBRACE policy_option_list RBRACE" pass def p_policy_option_list(self, p): '''policy_option_list : policy_option SEMI | policy_option_list policy_option SEMI''' pass def p_policy_option(self, p): '''policy_option : parent_option | directory_option | coverage_option | rollperiod_option | prepublish_option | postpublish_option | keysize_option | algorithm_option | keyttl_option | standby_option''' pass def p_alg_option_group(self, p): "alg_option_group : LBRACE alg_option_list RBRACE" pass def p_alg_option_list(self, p): '''alg_option_list : alg_option SEMI | alg_option_list alg_option SEMI''' pass def p_alg_option(self, p): '''alg_option : coverage_option | rollperiod_option | prepublish_option | postpublish_option | keyttl_option | keysize_option | standby_option''' pass def p_parent_option(self, p): "parent_option : POLICY name" self.current.parent = self.named_policy[p[2].lower()] def p_directory_option(self, p): "directory_option : DIRECTORY QSTRING" self.current.directory = p[2] def p_coverage_option(self, p): "coverage_option : COVERAGE duration" self.current.coverage = p[2] def p_rollperiod_option(self, p): "rollperiod_option : ROLL_PERIOD KEYTYPE duration" if p[2] == "KSK": self.current.ksk_rollperiod = p[3] else: self.current.zsk_rollperiod = p[3] def p_prepublish_option(self, p): "prepublish_option : PRE_PUBLISH KEYTYPE duration" if p[2] == "KSK": self.current.ksk_prepublish = p[3] else: self.current.zsk_prepublish = p[3] def p_postpublish_option(self, p): "postpublish_option : POST_PUBLISH KEYTYPE duration" if p[2] == "KSK": self.current.ksk_postpublish = p[3] else: self.current.zsk_postpublish = p[3] def p_keysize_option(self, p): "keysize_option : KEY_SIZE KEYTYPE NUMBER" if p[2] == "KSK": self.current.ksk_keysize = p[3] else: self.current.zsk_keysize = p[3] def p_standby_option(self, p): "standby_option : STANDBY KEYTYPE NUMBER" if p[2] == "KSK": self.current.ksk_standby = p[3] else: self.current.zsk_standby = p[3] def p_keyttl_option(self, p): "keyttl_option : KEYTTL duration" self.current.keyttl = p[2] def p_algorithm_option(self, p): "algorithm_option : ALGORITHM ALGNAME" self.current.algorithm = p[2] def p_error(self, p): if p: print("%s%s%d:syntax error near '%s'" % (self.filename or "", ":" if self.filename else "", p.lineno, p.value)) else: if not self.initial: raise PolicyException("%s%s%d:unexpected end of input" % (self.filename or "", ":" if self.filename else "", p and p.lineno or 0)) if __name__ == "__main__": import sys if sys.argv[1] == "lex": file = open(sys.argv[2]) text = file.read() file.close() plex = PolicyLex(debug=1) plex.test(text) elif sys.argv[1] == "parse": try: pp = dnssec_policy(sys.argv[2], write_tables=True, debug=True) print(pp.named_policy['default']) print(pp.policy("nonexistent.zone")) except Exception as e: print(e.args[0]) bind9-9.11.3+dfsg/bin/python/isc/rndc.py.in000066400000000000000000000146761325250447100203260ustar00rootroot00000000000000############################################################################ # Copyright (C) 2016 Internet Systems Consortium, Inc. ("ISC") # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. ############################################################################ ############################################################################ # rndc.py # This module implements the RNDC control protocol. ############################################################################ from collections import OrderedDict import time import struct import hashlib import hmac import base64 import random import socket class rndc(object): """RNDC protocol client library""" __algos = {'md5': 157, 'sha1': 161, 'sha224': 162, 'sha256': 163, 'sha384': 164, 'sha512': 165} def __init__(self, host, algo, secret): """Creates a persistent connection to RNDC and logs in host - (ip, port) tuple algo - HMAC algorithm: one of md5, sha1, sha224, sha256, sha384, sha512 (with optional prefix 'hmac-') secret - HMAC secret, base64 encoded""" self.host = host algo = algo.lower() if algo.startswith('hmac-'): algo = algo[5:] self.algo = algo self.hlalgo = getattr(hashlib, algo) self.secret = base64.b64decode(secret) self.ser = random.randint(0, 1 << 24) self.nonce = None self.__connect_login() def call(self, cmd): """Call a RNDC command, all parsing is done on the server side cmd - a complete string with a command (eg 'reload zone example.com') """ return dict(self.__command(type=cmd)['_data']) def __serialize_dict(self, data, ignore_auth=False): rv = bytearray() for k, v in data.items(): if ignore_auth and k == '_auth': continue rv += struct.pack('B', len(k)) + k.encode('ascii') if type(v) == str: rv += struct.pack('>BI', 1, len(v)) + v.encode('ascii') elif type(v) == bytes: rv += struct.pack('>BI', 1, len(v)) + v elif type(v) == bytearray: rv += struct.pack('>BI', 1, len(v)) + v elif type(v) == OrderedDict: sd = self.__serialize_dict(v) rv += struct.pack('>BI', 2, len(sd)) + sd else: raise NotImplementedError('Cannot serialize element of type %s' % type(v)) return rv def __prep_message(self, *args, **kwargs): self.ser += 1 now = int(time.time()) data = OrderedDict(*args, **kwargs) d = OrderedDict() d['_auth'] = OrderedDict() d['_ctrl'] = OrderedDict() d['_ctrl']['_ser'] = str(self.ser) d['_ctrl']['_tim'] = str(now) d['_ctrl']['_exp'] = str(now+60) if self.nonce is not None: d['_ctrl']['_nonce'] = self.nonce d['_data'] = data msg = self.__serialize_dict(d, ignore_auth=True) hash = hmac.new(self.secret, msg, self.hlalgo).digest() bhash = base64.b64encode(hash) if self.algo == 'md5': d['_auth']['hmd5'] = struct.pack('22s', bhash) else: d['_auth']['hsha'] = bytearray(struct.pack('B88s', self.__algos[self.algo], bhash)) msg = self.__serialize_dict(d) msg = struct.pack('>II', len(msg) + 4, 1) + msg return msg def __verify_msg(self, msg): if self.nonce is not None and msg['_ctrl']['_nonce'] != self.nonce: return False if self.algo == 'md5': bhash = msg['_auth']['hmd5'] else: bhash = msg['_auth']['hsha'][1:] if type(bhash) == bytes: bhash = bhash.decode('ascii') bhash += '=' * (4 - (len(bhash) % 4)) remote_hash = base64.b64decode(bhash) my_msg = self.__serialize_dict(msg, ignore_auth=True) my_hash = hmac.new(self.secret, my_msg, self.hlalgo).digest() return (my_hash == remote_hash) def __command(self, *args, **kwargs): msg = self.__prep_message(*args, **kwargs) sent = self.socket.send(msg) if sent != len(msg): raise IOError("Cannot send the message") header = self.socket.recv(8) if len(header) != 8: # What should we throw here? Bad auth can cause this... raise IOError("Can't read response header") length, version = struct.unpack('>II', header) if version != 1: raise NotImplementedError('Wrong message version %d' % version) # it includes the header length -= 4 data = self.socket.recv(length, socket.MSG_WAITALL) if len(data) != length: raise IOError("Can't read response data") if type(data) == str: data = bytearray(data) msg = self.__parse_message(data) if not self.__verify_msg(msg): raise IOError("Authentication failure") return msg def __connect_login(self): self.socket = socket.create_connection(self.host) self.nonce = None msg = self.__command(type='null') self.nonce = msg['_ctrl']['_nonce'] def __parse_element(self, input): pos = 0 labellen = input[pos] pos += 1 label = input[pos:pos+labellen].decode('ascii') pos += labellen type = input[pos] pos += 1 datalen = struct.unpack('>I', input[pos:pos+4])[0] pos += 4 data = input[pos:pos+datalen] pos += datalen rest = input[pos:] if type == 1: # raw binary value return label, data, rest elif type == 2: # dictionary d = OrderedDict() while len(data) > 0: ilabel, value, data = self.__parse_element(data) d[ilabel] = value return label, d, rest # TODO type 3 - list else: raise NotImplementedError('Unknown element type %d' % type) def __parse_message(self, input): rv = OrderedDict() hdata = None while len(input) > 0: label, value, input = self.__parse_element(input) rv[label] = value return rv bind9-9.11.3+dfsg/bin/python/isc/tests/000077500000000000000000000000001325250447100175455ustar00rootroot00000000000000bind9-9.11.3+dfsg/bin/python/isc/tests/Makefile.in000066400000000000000000000011471325250447100216150ustar00rootroot00000000000000# Copyright (C) 2016 Internet Systems Consortium, Inc. ("ISC") # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. srcdir = @srcdir@ VPATH = @srcdir@ top_srcdir = @top_srcdir@ @BIND9_MAKE_INCLUDES@ PYTHON = @PYTHON@ PYTESTS = dnskey_test.py policy_test.py @BIND9_MAKE_RULES@ check test: for test in $(PYTESTS); do \ PYTHONPATH=${srcdir}/../.. $(PYTHON) ${srcdir}/$$test; \ done clean distclean:: rm -rf *.pyc __pycache__ distclean:: rm -f ${PYTESTS} bind9-9.11.3+dfsg/bin/python/isc/tests/dnskey_test.py.in000066400000000000000000000034231325250447100230620ustar00rootroot00000000000000############################################################################ # Copyright (C) 2016 Internet Systems Consortium, Inc. ("ISC") # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. ############################################################################ import sys import unittest sys.path.append('../..') from isc import * kdict = None def getkey(): global kdict if not kdict: kd = keydict(path='testdata') for key in kd: return key class DnskeyTest(unittest.TestCase): def test_metdata(self): key = getkey() self.assertEqual(key.created(), 1448055647) self.assertEqual(key.publish(), 1445463714) self.assertEqual(key.activate(), 1448055714) self.assertEqual(key.revoke(), 1479591714) self.assertEqual(key.inactive(), 1511127714) self.assertEqual(key.delete(), 1542663714) self.assertEqual(key.syncpublish(), 1442871714) self.assertEqual(key.syncdelete(), 1448919714) def test_fmttime(self): key = getkey() self.assertEqual(key.getfmttime('Created'), '20151120214047') self.assertEqual(key.getfmttime('Publish'), '20151021214154') self.assertEqual(key.getfmttime('Activate'), '20151120214154') self.assertEqual(key.getfmttime('Revoke'), '20161119214154') self.assertEqual(key.getfmttime('Inactive'), '20171119214154') self.assertEqual(key.getfmttime('Delete'), '20181119214154') self.assertEqual(key.getfmttime('SyncPublish'), '20150921214154') self.assertEqual(key.getfmttime('SyncDelete'), '20151130214154') if __name__ == "__main__": unittest.main() bind9-9.11.3+dfsg/bin/python/isc/tests/policy_test.py.in000066400000000000000000000071171325250447100230700ustar00rootroot00000000000000############################################################################ # Copyright (C) 2016, 2017 Internet Systems Consortium, Inc. ("ISC") # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. ############################################################################ import sys import unittest sys.path.append('../..') from isc import * class PolicyTest(unittest.TestCase): def test_keysize(self): pol = policy.dnssec_policy() pol.load('test-policies/01-keysize.pol') p = pol.policy('good_rsa.test', novalidate=True) self.assertEqual(p.get_name(), "good_rsa.test") self.assertEqual(p.constructed(), False) self.assertEqual(p.validate(), (True, "")) p = pol.policy('good_dsa.test', novalidate=True) self.assertEqual(p.get_name(), "good_dsa.test") self.assertEqual(p.constructed(), False) self.assertEqual(p.validate(), (True, "")) p = pol.policy('bad_dsa.test', novalidate=True) self.assertEqual(p.validate(), (False, 'ZSK key size 769 not divisible by 64 as required for DSA')) def test_prepublish(self): pol = policy.dnssec_policy() pol.load('test-policies/02-prepublish.pol') p = pol.policy('good_prepublish.test', novalidate=True) self.assertEqual(p.validate(), (True, "")) p = pol.policy('bad_prepublish.test', novalidate=True) self.assertEqual(p.validate(), (False, 'KSK pre/post-publish periods ' '(10368000/5184000) combined exceed ' 'rollover period 10368000')) def test_postpublish(self): pol = policy.dnssec_policy() pol.load('test-policies/03-postpublish.pol') p = pol.policy('good_postpublish.test', novalidate=True) self.assertEqual(p.validate(), (True, "")) p = pol.policy('bad_postpublish.test', novalidate=True) self.assertEqual(p.validate(), (False, 'KSK pre/post-publish periods ' '(10368000/5184000) combined exceed ' 'rollover period 10368000')) def test_combined_pre_post(self): pol = policy.dnssec_policy() pol.load('test-policies/04-combined-pre-post.pol') p = pol.policy('good_combined_pre_post_ksk.test', novalidate=True) self.assertEqual(p.validate(), (True, "")) p = pol.policy('bad_combined_pre_post_ksk.test', novalidate=True) self.assertEqual(p.validate(), (False, 'KSK pre/post-publish periods ' '(5184000/5184000) combined exceed ' 'rollover period 10368000')) p = pol.policy('good_combined_pre_post_zsk.test', novalidate=True) self.assertEqual(p.validate(), (True, "")) p = pol.policy('bad_combined_pre_post_zsk.test', novalidate=True) self.assertEqual(p.validate(), (False, 'ZSK pre/post-publish periods ' '(5184000/5184000) combined exceed ' 'rollover period 7776000')) def test_numeric_zone(self): pol = policy.dnssec_policy() pol.load('test-policies/05-numeric-zone.pol') p = pol.policy('99example.test', novalidate=True) self.assertEqual(p.validate(), (True, "")) if __name__ == "__main__": unittest.main() bind9-9.11.3+dfsg/bin/python/isc/tests/test-policies/000077500000000000000000000000001325250447100223315ustar00rootroot00000000000000bind9-9.11.3+dfsg/bin/python/isc/tests/test-policies/01-keysize.pol000066400000000000000000000015751325250447100247560ustar00rootroot00000000000000/* * Copyright (C) 2016 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ policy keysize_rsa { algorithm rsasha1; coverage 1y; roll-period zsk 3mo; pre-publish zsk 2w; post-publish zsk 2w; roll-period ksk 1y; pre-publish ksk 1mo; post-publish ksk 2mo; keyttl 1h; key-size ksk 2048; key-size zsk 1024; }; policy keysize_dsa { algorithm dsa; coverage 1y; key-size ksk 2048; key-size zsk 1024; }; zone good_rsa.test { policy keysize_rsa; }; zone bad_rsa.test { policy keysize_rsa; key-size ksk 511; }; zone good_dsa.test { policy keysize_dsa; key-size ksk 1024; key-size zsk 768; }; zone bad_dsa.test { policy keysize_dsa; key-size ksk 1024; key-size zsk 769; }; bind9-9.11.3+dfsg/bin/python/isc/tests/test-policies/02-prepublish.pol000066400000000000000000000016051325250447100254430ustar00rootroot00000000000000/* * Copyright (C) 2016 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ policy prepublish_rsa { algorithm rsasha1; coverage 1y; roll-period zsk 3mo; pre-publish zsk 2w; post-publish zsk 2w; roll-period ksk 1y; pre-publish ksk 1mo; post-publish ksk 2mo; keyttl 1h; key-size ksk 2048; key-size zsk 1024; }; // Policy that defines a pre-publish period lower than the rollover period zone good_prepublish.test { policy prepublish_rsa; coverage 6mo; roll-period ksk 4mo; pre-publish ksk 1mo; }; // Policy that defines a pre-publish period equal to the rollover period zone bad_prepublish.test { policy prepublish_rsa; coverage 6mo; roll-period ksk 4mo; pre-publish ksk 4mo; }; bind9-9.11.3+dfsg/bin/python/isc/tests/test-policies/03-postpublish.pol000066400000000000000000000016141325250447100256430ustar00rootroot00000000000000/* * Copyright (C) 2016 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ policy postpublish_rsa { algorithm rsasha1; coverage 1y; roll-period zsk 3mo; pre-publish zsk 2w; post-publish zsk 2w; roll-period ksk 1y; pre-publish ksk 1mo; post-publish ksk 2mo; keyttl 1h; key-size ksk 2048; key-size zsk 1024; }; // Policy that defines a post-publish period lower than the rollover period zone good_postpublish.test { policy postpublish_rsa; coverage 6mo; roll-period ksk 4mo; pre-publish ksk 1mo; }; // Policy that defines a post-publish period equal to the rollover period zone bad_postpublish.test { policy postpublish_rsa; coverage 6mo; roll-period ksk 4mo; pre-publish ksk 4mo; }; bind9-9.11.3+dfsg/bin/python/isc/tests/test-policies/04-combined-pre-post.pol000066400000000000000000000030411325250447100266130ustar00rootroot00000000000000/* * Copyright (C) 2016 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ policy combined_pre_post_rsa { algorithm rsasha1; coverage 1y; roll-period zsk 3mo; pre-publish zsk 2w; post-publish zsk 2w; roll-period ksk 1y; pre-publish ksk 1mo; post-publish ksk 2mo; keyttl 1h; key-size ksk 2048; key-size zsk 1024; }; // Policy that defines a combined pre-publish and post-publish period lower // than the rollover period zone good_combined_pre_post_ksk.test { policy combined_pre_post_rsa; coverage 6mo; roll-period ksk 4mo; pre-publish ksk 1mo; post-publish ksk 1mo; }; // Policy that defines a combined pre-publish and post-publish period higher // than the rollover period zone bad_combined_pre_post_ksk.test { policy combined_pre_post_rsa; coverage 6mo; roll-period ksk 4mo; pre-publish ksk 2mo; post-publish ksk 2mo; }; // Policy that defines a combined pre-publish and post-publish period lower // than the rollover period zone good_combined_pre_post_zsk.test { policy combined_pre_post_rsa; coverage 1y; roll-period zsk 3mo; pre-publish zsk 1mo; post-publish zsk 1mo; }; // Policy that defines a combined pre-publish and post-publish period higher // than the rollover period zone bad_combined_pre_post_zsk.test { policy combined_pre_post_rsa; coverage 1y; roll-period zsk 3mo; pre-publish zsk 2mo; post-publish zsk 2mo; }; bind9-9.11.3+dfsg/bin/python/isc/tests/test-policies/05-numeric-zone.pol000066400000000000000000000005501325250447100257020ustar00rootroot00000000000000/* * Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ // Zone policy that uses a numeric name zone "99example.test" { coverage 6mo; }; bind9-9.11.3+dfsg/bin/python/isc/tests/testdata/000077500000000000000000000000001325250447100213565ustar00rootroot00000000000000bind9-9.11.3+dfsg/bin/python/isc/tests/testdata/Kexample.com.+007+35529.key000066400000000000000000000013731325250447100254620ustar00rootroot00000000000000; This is a key-signing key, keyid 35529, for example.com. ; Created: 20151120214047 (Fri Nov 20 13:40:47 2015) ; Publish: 20151021214154 (Wed Oct 21 14:41:54 2015) ; Activate: 20151120214154 (Fri Nov 20 13:41:54 2015) ; Revoke: 20161119214154 (Sat Nov 19 13:41:54 2016) ; Inactive: 20171119214154 (Sun Nov 19 13:41:54 2017) ; Delete: 20181119214154 (Mon Nov 19 13:41:54 2018) example.com. IN DNSKEY 257 3 7 AwEAAbbJK96tY8d4sF6RLxh9SVIhho5s2ZhrcijT5j1SNLECen7QLutj VJPEiG8UgBLaJSGkxPDxOygYv4hwh4JXBSj89o9rNabAJtCa9XzIXSpt /cfiCfvqmcOZb9nepmDCXsC7gn/gbae/4Y5ym9XOiCp8lu+tlFWgRiJ+ kxDGN48rRPrGfpq+SfwM9NUtftVa7B0EFVzDkADKedRj0SSGYOqH+WYH CnWjhPFmgJoAw3/m4slTHW1l+mDwFvsCMjXopg4JV0CNnTybnOmyuIwO LWRhB3q8ze24sYBU1fpE9VAMxZ++4Kqh/2MZFeDAs7iPPKSmI3wkRCW5 pkwDLO5lJ9c= bind9-9.11.3+dfsg/bin/python/isc/tests/testdata/Kexample.com.+007+35529.private000066400000000000000000000035611325250447100263450ustar00rootroot00000000000000Private-key-format: v1.3 Algorithm: 7 (NSEC3RSASHA1) Modulus: tskr3q1jx3iwXpEvGH1JUiGGjmzZmGtyKNPmPVI0sQJ6ftAu62NUk8SIbxSAEtolIaTE8PE7KBi/iHCHglcFKPz2j2s1psAm0Jr1fMhdKm39x+IJ++qZw5lv2d6mYMJewLuCf+Btp7/hjnKb1c6IKnyW762UVaBGIn6TEMY3jytE+sZ+mr5J/Az01S1+1VrsHQQVXMOQAMp51GPRJIZg6of5ZgcKdaOE8WaAmgDDf+biyVMdbWX6YPAW+wIyNeimDglXQI2dPJuc6bK4jA4tZGEHerzN7bixgFTV+kT1UAzFn77gqqH/YxkV4MCzuI88pKYjfCREJbmmTAMs7mUn1w== PublicExponent: AQAB PrivateExponent: jfiM6YU1Rd6Y5qrPsK7HP1Ko54DmNbvmzI1hfGmYYZAyQsNCXjQloix5aAW9QGdNhecrzJUhxJAMXFZC+lrKuD5a56R25JDE1Sw21nft3SHXhuQrqw5Z5hIMTWXhRrBR1lMOFnLj2PJxqCmenp+vJYjl1z20RBmbv/keE15SExFRJIJ3G0lI4V0KxprY5rgsT/vID0pS32f7rmXhgEzyWDyuxceTMidBooD5BSeEmSTYa4rvCVZ2vgnzIGSxjYDPJE2rGve2dpvdXQuujRFaf4+/FzjaOgg35rTtUmC9klfB4D6KJIfc1PNUwcH7V0VJ2fFlgZgMYi4W331QORl9sQ== Prime1: 479rW3EeoBwHhUKDy5YeyfnMKjhaosrcYhW4resevLzatFrvS/n2KxJnsHoEzmGr2A13naI61RndgVBBOwNDWI3/tQ+aKvcr+V9m4omROV3xYa8s1FsDbEW0Z6G0UheaqRFir8WK98/Lj6Zht1uBXHSPPf91OW0qj+b5gbX7TK8= Prime2: zXXlxgIq+Ih6kxsUw4Ith0nd/d2P3d42QYPjxYjsg4xYicPAjva9HltnbBQ2lr4JEG9Yyb8KalSnJUSuvXtn7bGfBzLu8W6omCeVWXQVH4NIu9AjpO16NpMKWGRfiHHbbSYJs1daTZKHC2FEmi18MKX/RauHGGOakFQ/3A/GMVk= Exponent1: 0o9UQ1uHNAIWFedUEHJ/jr7LOrGVYnLpZCmu7+S0K0zzatGz8ets44+FnAyDywdUKFDzKSMm/4SFXRwE4vl2VzYZlp2RLG4PEuRYK9OCF6a6F1UsvjxTItQjIbjIDSnTjMINGnMps0lDa1EpgKsyI3eEQ46eI3TBZ//k6D6G0vM= Exponent2: d+CYJgXRyJzo17fvT3s+0TbaHWsOq+chROyNEw4m4UIbzpW2XjO8eF/gYgERMLbEVyCAb4XVr+CgfXArfEbqhpciMHMZUyi7mbtOupiuUmqpH1v70Bj3O6xjVtuJmfTEkFSnSEppV+VsgclI26Q6V7Ai1yWTdzl2T0u4zs8tVlE= Coefficient: E4EYw76gIChdQDn6+Uh44/xH9Uwmvq3OETR8w/kEZ0xQ8AkTdKFKUp84nlR6gN+ljb2mUxERKrVLwnBsU8EbUlo9UccMbBGkkZ/8MyfGCBb9nUyOFtOxdHY2M0MQadesRptXHt/m30XjdohwmT7qfSIENwtgUOHbwFnn7WPMc/k= Created: 20151120214047 Publish: 20151021214154 Activate: 20151120214154 Revoke: 20161119214154 Inactive: 20171119214154 Delete: 20181119214154 SyncPublish: 20150921214154 SyncDelete: 20151130214154 bind9-9.11.3+dfsg/bin/python/isc/utils.py.in000066400000000000000000000040651325250447100205270ustar00rootroot00000000000000############################################################################ # Copyright (C) 2016 Internet Systems Consortium, Inc. ("ISC") # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. ############################################################################ import os # These routines permit platform-independent location of BIND 9 tools if os.name == 'nt': import win32con import win32api def prefix(bindir=''): if os.name != 'nt': return os.path.join('@prefix@', bindir) hklm = win32con.HKEY_LOCAL_MACHINE bind_subkey = "Software\\ISC\\BIND" sam = win32con.KEY_READ h_key = None key_found = True # can fail if the registry redirected for 32/64 bits try: h_key = win32api.RegOpenKeyEx(hklm, bind_subkey, 0, sam) except: key_found = False # retry for 32 bit python with 64 bit bind9 if not key_found: key_found = True sam64 = sam | win32con.KEY_WOW64_64KEY try: h_key = win32api.RegOpenKeyEx(hklm, bind_subkey, 0, sam64) except: key_found = False # retry 64 bit python with 32 bit bind9 if not key_found: key_found = True sam32 = sam | win32con.KEY_WOW64_32KEY try: h_key = win32api.RegOpenKeyEx(hklm, bind_subkey, 0, sam32) except: key_found = False if key_found: try: (named_base, _) = win32api.RegQueryValueEx(h_key, "InstallDir") except: key_found = False win32api.RegCloseKey(h_key) if key_found: return os.path.join(named_base, bindir) return os.path.join(win32api.GetSystemDirectory(), bindir) def shellquote(s): if os.name == 'nt': return '"' + s.replace('"', '"\\"') + '"' return "'" + s.replace("'", "'\\''") + "'" version = '@BIND9_VERSION@' if os.name != 'nt': sysconfdir = '@expanded_sysconfdir@' else: sysconfdir = prefix('etc') bind9-9.11.3+dfsg/bin/python/setup.py000066400000000000000000000013611325250447100173400ustar00rootroot00000000000000############################################################################ # Copyright (C) 2016, 2018 Internet Systems Consortium, Inc. ("ISC") # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. ############################################################################ from distutils.core import setup setup(name='isc', version='2.0', description='Python functions to support BIND utilities', url='https://www.isc.org/bind', author='Internet Systems Consortium, Inc', author_email='info@isc.org', license='MPL', requires=['ply'], packages=['isc']) bind9-9.11.3+dfsg/bin/rndc/000077500000000000000000000000001325250447100152325ustar00rootroot00000000000000bind9-9.11.3+dfsg/bin/rndc/Makefile.in000066400000000000000000000050171325250447100173020ustar00rootroot00000000000000# Copyright (C) 2000-2002, 2004, 2007, 2009, 2012, 2014-2016 Internet Systems Consortium, Inc. ("ISC") # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. # $Id: Makefile.in,v 1.49 2009/12/05 23:31:40 each Exp $ srcdir = @srcdir@ VPATH = @srcdir@ top_srcdir = @top_srcdir@ VERSION=@BIND9_VERSION@ @BIND9_MAKE_INCLUDES@ CINCLUDES = -I${srcdir}/include ${ISC_INCLUDES} ${ISCCC_INCLUDES} \ ${ISCCFG_INCLUDES} ${DNS_INCLUDES} ${BIND9_INCLUDES} CDEFINES = CWARNINGS = ISCCFGLIBS = ../../lib/isccfg/libisccfg.@A@ ISCCCLIBS = ../../lib/isccc/libisccc.@A@ ISCLIBS = ../../lib/isc/libisc.@A@ ISCNOSYMLIBS = ../../lib/isc/libisc-nosymtbl.@A@ DNSLIBS = ../../lib/dns/libdns.@A@ @DNS_CRYPTO_LIBS@ BIND9LIBS = ../../lib/bind9/libbind9.@A@ ISCCFGDEPLIBS = ../../lib/isccfg/libisccfg.@A@ ISCCCDEPLIBS = ../../lib/isccc/libisccc.@A@ ISCDEPLIBS = ../../lib/isc/libisc.@A@ DNSDEPLIBS = ../../lib/dns/libdns.@A@ BIND9DEPLIBS = ../../lib/bind9/libbind9.@A@ LIBS = ${ISCLIBS} @LIBS@ NOSYMLIBS = ${ISCNOSYMLIBS} @LIBS@ RNDCDEPLIBS = ${ISCCFGDEPLIBS} ${ISCCCDEPLIBS} ${BIND9DEPLIBS} ${DNSDEPLIBS} ${ISCDEPLIBS} CONFDEPLIBS = ${DNSDEPLIBS} ${ISCDEPLIBS} SRCS= rndc.c TARGETS = rndc@EXEEXT@ MANPAGES = rndc.8 rndc.conf.5 HTMLPAGES = rndc.html rndc.conf.html MANOBJS = ${MANPAGES} ${HTMLPAGES} @BIND9_MAKE_RULES@ rndc.@O@: rndc.c ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} \ -DVERSION=\"${VERSION}\" \ -DRNDC_CONFFILE=\"${sysconfdir}/rndc.conf\" \ -DRNDC_KEYFILE=\"${sysconfdir}/rndc.key\" \ -c ${srcdir}/rndc.c rndc@EXEEXT@: rndc.@O@ util.@O@ ${RNDCDEPLIBS} export BASEOBJS="rndc.@O@ util.@O@"; \ export LIBS0="${ISCCFGLIBS} ${ISCCCLIBS} ${BIND9LIBS} ${DNSLIBS}"; \ ${FINALBUILDCMD} doc man:: ${MANOBJS} docclean manclean maintainer-clean:: rm -f ${MANOBJS} installdirs: $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${sbindir} $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${mandir}/man8 $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${mandir}/man5 install:: rndc@EXEEXT@ installdirs ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} rndc@EXEEXT@ ${DESTDIR}${sbindir} ${INSTALL_DATA} ${srcdir}/rndc.8 ${DESTDIR}${mandir}/man8 ${INSTALL_DATA} ${srcdir}/rndc.conf.5 ${DESTDIR}${mandir}/man5 uninstall:: rm -f ${DESTDIR}${mandir}/man5/rndc.conf.5 rm -f ${DESTDIR}${mandir}/man8/rndc.8 ${LIBTOOL_MODE_UNINSTALL} rm -f ${DESTDIR}${sbindir}/rndc@EXEEXT@ clean distclean maintainer-clean:: rm -f ${TARGETS} bind9-9.11.3+dfsg/bin/rndc/include/000077500000000000000000000000001325250447100166555ustar00rootroot00000000000000bind9-9.11.3+dfsg/bin/rndc/include/rndc/000077500000000000000000000000001325250447100176035ustar00rootroot00000000000000bind9-9.11.3+dfsg/bin/rndc/include/rndc/os.h000066400000000000000000000013021325250447100203710ustar00rootroot00000000000000/* * Copyright (C) 2001, 2004, 2005, 2007, 2009, 2016 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* $Id: os.h,v 1.12 2009/06/10 00:27:21 each Exp $ */ /*! \file */ #ifndef RNDC_OS_H #define RNDC_OS_H 1 #include #include ISC_LANG_BEGINDECLS int set_user(FILE *fd, const char *user); /*%< * Set the owner of the file referenced by 'fd' to 'user'. * Returns: * 0 success * -1 insufficient permissions, or 'user' does not exist. */ ISC_LANG_ENDDECLS #endif bind9-9.11.3+dfsg/bin/rndc/rndc.8000066400000000000000000000556541325250447100162700ustar00rootroot00000000000000.\" Copyright (C) 2000, 2001, 2004, 2005, 2007, 2013-2018 Internet Systems Consortium, Inc. ("ISC") .\" .\" This Source Code Form is subject to the terms of the Mozilla Public .\" License, v. 2.0. If a copy of the MPL was not distributed with this .\" file, You can obtain one at http://mozilla.org/MPL/2.0/. .\" .hy 0 .ad l '\" t .\" Title: rndc .\" Author: .\" Generator: DocBook XSL Stylesheets v1.78.1 .\" Date: 2014-08-15 .\" Manual: BIND9 .\" Source: ISC .\" Language: English .\" .TH "RNDC" "8" "2014\-08\-15" "ISC" "BIND9" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" rndc \- name server control utility .SH "SYNOPSIS" .HP \w'\fBrndc\fR\ 'u \fBrndc\fR [\fB\-b\ \fR\fB\fIsource\-address\fR\fR] [\fB\-c\ \fR\fB\fIconfig\-file\fR\fR] [\fB\-k\ \fR\fB\fIkey\-file\fR\fR] [\fB\-s\ \fR\fB\fIserver\fR\fR] [\fB\-p\ \fR\fB\fIport\fR\fR] [\fB\-q\fR] [\fB\-r\fR] [\fB\-V\fR] [\fB\-y\ \fR\fB\fIkey_id\fR\fR] {command} .SH "DESCRIPTION" .PP \fBrndc\fR controls the operation of a name server\&. It supersedes the \fBndc\fR utility that was provided in old BIND releases\&. If \fBrndc\fR is invoked with no command line options or arguments, it prints a short summary of the supported commands and the available options and their arguments\&. .PP \fBrndc\fR communicates with the name server over a TCP connection, sending commands authenticated with digital signatures\&. In the current versions of \fBrndc\fR and \fBnamed\fR, the only supported authentication algorithms are HMAC\-MD5 (for compatibility), HMAC\-SHA1, HMAC\-SHA224, HMAC\-SHA256 (default), HMAC\-SHA384 and HMAC\-SHA512\&. They use a shared secret on each end of the connection\&. This provides TSIG\-style authentication for the command request and the name server\*(Aqs response\&. All commands sent over the channel must be signed by a key_id known to the server\&. .PP \fBrndc\fR reads a configuration file to determine how to contact the name server and decide what algorithm and key it should use\&. .SH "OPTIONS" .PP \-b \fIsource\-address\fR .RS 4 Use \fIsource\-address\fR as the source address for the connection to the server\&. Multiple instances are permitted to allow setting of both the IPv4 and IPv6 source addresses\&. .RE .PP \-c \fIconfig\-file\fR .RS 4 Use \fIconfig\-file\fR as the configuration file instead of the default, /etc/rndc\&.conf\&. .RE .PP \-k \fIkey\-file\fR .RS 4 Use \fIkey\-file\fR as the key file instead of the default, /etc/rndc\&.key\&. The key in /etc/rndc\&.key will be used to authenticate commands sent to the server if the \fIconfig\-file\fR does not exist\&. .RE .PP \-s \fIserver\fR .RS 4 \fIserver\fR is the name or address of the server which matches a server statement in the configuration file for \fBrndc\fR\&. If no server is supplied on the command line, the host named by the default\-server clause in the options statement of the \fBrndc\fR configuration file will be used\&. .RE .PP \-p \fIport\fR .RS 4 Send commands to TCP port \fIport\fR instead of BIND 9\*(Aqs default control channel port, 953\&. .RE .PP \-q .RS 4 Quiet mode: Message text returned by the server will not be printed except when there is an error\&. .RE .PP \-r .RS 4 Instructs \fBrndc\fR to print the result code returned by \fBnamed\fR after executing the requested command (e\&.g\&., ISC_R_SUCCESS, ISC_R_FAILURE, etc)\&. .RE .PP \-V .RS 4 Enable verbose logging\&. .RE .PP \-y \fIkey_id\fR .RS 4 Use the key \fIkey_id\fR from the configuration file\&. \fIkey_id\fR must be known by \fBnamed\fR with the same algorithm and secret string in order for control message validation to succeed\&. If no \fIkey_id\fR is specified, \fBrndc\fR will first look for a key clause in the server statement of the server being used, or if no server statement is present for that host, then the default\-key clause of the options statement\&. Note that the configuration file contains shared secrets which are used to send authenticated control commands to name servers\&. It should therefore not have general read or write access\&. .RE .SH "COMMANDS" .PP A list of commands supported by \fBrndc\fR can be seen by running \fBrndc\fR without arguments\&. .PP Currently supported commands are: .PP \fBaddzone \fR\fB\fIzone\fR\fR\fB \fR\fB[\fIclass\fR [\fIview\fR]]\fR\fB \fR\fB\fIconfiguration\fR\fR\fB \fR .RS 4 Add a zone while the server is running\&. This command requires the \fBallow\-new\-zones\fR option to be set to \fByes\fR\&. The \fIconfiguration\fR string specified on the command line is the zone configuration text that would ordinarily be placed in named\&.conf\&. .sp The configuration is saved in a file called \fIname\fR\&.nzf, where \fIname\fR is the name of the view, or if it contains characters that are incompatible with use as a file name, a cryptographic hash generated from the name of the view\&. When \fBnamed\fR is restarted, the file will be loaded into the view configuration, so that zones that were added can persist after a restart\&. .sp This sample \fBaddzone\fR command would add the zone example\&.com to the default view: .sp $\fBrndc addzone example\&.com \*(Aq{ type master; file "example\&.com\&.db"; };\*(Aq\fR .sp (Note the brackets and semi\-colon around the zone configuration text\&.) .sp See also \fBrndc delzone\fR and \fBrndc modzone\fR\&. .RE .PP \fBdelzone \fR\fB[\-clean]\fR\fB \fR\fB\fIzone\fR\fR\fB \fR\fB[\fIclass\fR [\fIview\fR]]\fR\fB \fR .RS 4 Delete a zone while the server is running\&. .sp If the \fB\-clean\fR argument is specified, the zone\*(Aqs master file (and journal file, if any) will be deleted along with the zone\&. Without the \fB\-clean\fR option, zone files must be cleaned up by hand\&. (If the zone is of type "slave" or "stub", the files needing to be cleaned up will be reported in the output of the \fBrndc delzone\fR command\&.) .sp If the zone was originally added via \fBrndc addzone\fR, then it will be removed permanently\&. However, if it was originally configured in named\&.conf, then that original configuration is still in place; when the server is restarted or reconfigured, the zone will come back\&. To remove it permanently, it must also be removed from named\&.conf .sp See also \fBrndc addzone\fR and \fBrndc modzone\fR\&. .RE .PP \fBdnstap ( \-reopen | \-roll \fR\fB[\fInumber\fR]\fR\fB )\fR .RS 4 Close and re\-open DNSTAP output files\&. \fBrndc dnstap \-reopen\fR allows the output file to be renamed externally, so that \fBnamed\fR can truncate and re\-open it\&. \fBrndc dnstap \-roll\fR causes the output file to be rolled automatically, similar to log files; the most recent output file has "\&.0" appended to its name; the previous most recent output file is moved to "\&.1", and so on\&. If \fInumber\fR is specified, then the number of backup log files is limited to that number\&. .RE .PP \fBdumpdb \fR\fB[\-all|\-cache|\-zones|\-adb|\-bad|\-fail]\fR\fB \fR\fB[\fIview \&.\&.\&.\fR]\fR .RS 4 Dump the server\*(Aqs caches (default) and/or zones to the dump file for the specified views\&. If no view is specified, all views are dumped\&. (See the \fBdump\-file\fR option in the BIND 9 Administrator Reference Manual\&.) .RE .PP \fBflush\fR .RS 4 Flushes the server\*(Aqs cache\&. .RE .PP \fBflushname\fR \fIname\fR [\fIview\fR] .RS 4 Flushes the given name from the view\*(Aqs DNS cache and, if applicable, from the view\*(Aqs nameserver address database, bad server cache and SERVFAIL cache\&. .RE .PP \fBflushtree\fR \fIname\fR [\fIview\fR] .RS 4 Flushes the given name, and all of its subdomains, from the view\*(Aqs DNS cache, address database, bad server cache, and SERVFAIL cache\&. .RE .PP \fBfreeze \fR\fB[\fIzone\fR [\fIclass\fR [\fIview\fR]]]\fR .RS 4 Suspend updates to a dynamic zone\&. If no zone is specified, then all zones are suspended\&. This allows manual edits to be made to a zone normally updated by dynamic update\&. It also causes changes in the journal file to be synced into the master file\&. All dynamic update attempts will be refused while the zone is frozen\&. .sp See also \fBrndc thaw\fR\&. .RE .PP \fBhalt \fR\fB[\-p]\fR .RS 4 Stop the server immediately\&. Recent changes made through dynamic update or IXFR are not saved to the master files, but will be rolled forward from the journal files when the server is restarted\&. If \fB\-p\fR is specified \fBnamed\fR\*(Aqs process id is returned\&. This allows an external process to determine when \fBnamed\fR had completed halting\&. .sp See also \fBrndc stop\fR\&. .RE .PP \fBloadkeys \fR\fB\fIzone\fR\fR\fB \fR\fB[\fIclass\fR [\fIview\fR]]\fR .RS 4 Fetch all DNSSEC keys for the given zone from the key directory\&. If they are within their publication period, merge them into the zone\*(Aqs DNSKEY RRset\&. Unlike \fBrndc sign\fR, however, the zone is not immediately re\-signed by the new keys, but is allowed to incrementally re\-sign over time\&. .sp This command requires that the \fBauto\-dnssec\fR zone option be set to maintain, and also requires the zone to be configured to allow dynamic DNS\&. (See "Dynamic Update Policies" in the Administrator Reference Manual for more details\&.) .RE .PP \fBmanaged\-keys \fR\fB\fI(status | refresh | sync)\fR\fR\fB \fR\fB[\fIclass\fR [\fIview\fR]]\fR .RS 4 When run with the "status" keyword, print the current status of the managed\-keys database for the specified view, or for all views if none is specified\&. When run with the "refresh" keyword, force an immediate refresh of all the managed\-keys in the specified view, or all views\&. When run with the "sync" keyword, force an immediate dump of the managed\-keys database to disk (in the file managed\-keys\&.bind or (\fIviewname\fR\&.mkeys)\&. .RE .PP \fBmodzone \fR\fB\fIzone\fR\fR\fB \fR\fB[\fIclass\fR [\fIview\fR]]\fR\fB \fR\fB\fIconfiguration\fR\fR\fB \fR .RS 4 Modify the configuration of a zone while the server is running\&. This command requires the \fBallow\-new\-zones\fR option to be set to \fByes\fR\&. As with \fBaddzone\fR, the \fIconfiguration\fR string specified on the command line is the zone configuration text that would ordinarily be placed in named\&.conf\&. .sp If the zone was originally added via \fBrndc addzone\fR, the configuration changes will be recorded permanently and will still be in effect after the server is restarted or reconfigured\&. However, if it was originally configured in named\&.conf, then that original configuration is still in place; when the server is restarted or reconfigured, the zone will revert to its original configuration\&. To make the changes permanent, it must also be modified in named\&.conf .sp See also \fBrndc addzone\fR and \fBrndc delzone\fR\&. .RE .PP \fBnotify \fR\fB\fIzone\fR\fR\fB \fR\fB[\fIclass\fR [\fIview\fR]]\fR .RS 4 Resend NOTIFY messages for the zone\&. .RE .PP \fBnotrace\fR .RS 4 Sets the server\*(Aqs debugging level to 0\&. .sp See also \fBrndc trace\fR\&. .RE .PP \fBnta \fR\fB[( \-d | \-f | \-r | \-l \fIduration\fR)]\fR\fB \fR\fB\fIdomain\fR\fR\fB \fR\fB[\fIview\fR]\fR\fB \fR .RS 4 Sets a DNSSEC negative trust anchor (NTA) for \fBdomain\fR, with a lifetime of \fBduration\fR\&. The default lifetime is configured in named\&.conf via the \fBnta\-lifetime\fR option, and defaults to one hour\&. The lifetime cannot exceed one week\&. .sp A negative trust anchor selectively disables DNSSEC validation for zones that are known to be failing because of misconfiguration rather than an attack\&. When data to be validated is at or below an active NTA (and above any other configured trust anchors), \fBnamed\fR will abort the DNSSEC validation process and treat the data as insecure rather than bogus\&. This continues until the NTA\*(Aqs lifetime is elapsed\&. .sp NTAs persist across restarts of the \fBnamed\fR server\&. The NTAs for a view are saved in a file called \fIname\fR\&.nta, where \fIname\fR is the name of the view, or if it contains characters that are incompatible with use as a file name, a cryptographic hash generated from the name of the view\&. .sp An existing NTA can be removed by using the \fB\-remove\fR option\&. .sp An NTA\*(Aqs lifetime can be specified with the \fB\-lifetime\fR option\&. TTL\-style suffixes can be used to specify the lifetime in seconds, minutes, or hours\&. If the specified NTA already exists, its lifetime will be updated to the new value\&. Setting \fBlifetime\fR to zero is equivalent to \fB\-remove\fR\&. .sp If \fB\-dump\fR is used, any other arguments are ignored, and a list of existing NTAs is printed (note that this may include NTAs that are expired but have not yet been cleaned up)\&. .sp Normally, \fBnamed\fR will periodically test to see whether data below an NTA can now be validated (see the \fBnta\-recheck\fR option in the Administrator Reference Manual for details)\&. If data can be validated, then the NTA is regarded as no longer necessary, and will be allowed to expire early\&. The \fB\-force\fR overrides this behavior and forces an NTA to persist for its entire lifetime, regardless of whether data could be validated if the NTA were not present\&. .sp All of these options can be shortened, i\&.e\&., to \fB\-l\fR, \fB\-r\fR, \fB\-d\fR, and \fB\-f\fR\&. .RE .PP \fBquerylog\fR [ on | off ] .RS 4 Enable or disable query logging\&. (For backward compatibility, this command can also be used without an argument to toggle query logging on and off\&.) .sp Query logging can also be enabled by explicitly directing the \fBqueries\fR\fBcategory\fR to a \fBchannel\fR in the \fBlogging\fR section of named\&.conf or by specifying \fBquerylog yes;\fR in the \fBoptions\fR section of named\&.conf\&. .RE .PP \fBreconfig\fR .RS 4 Reload the configuration file and load new zones, but do not reload existing zone files even if they have changed\&. This is faster than a full \fBreload\fR when there is a large number of zones because it avoids the need to examine the modification times of the zones files\&. .RE .PP \fBrecursing\fR .RS 4 Dump the list of queries \fBnamed\fR is currently recursing on, and the list of domains to which iterative queries are currently being sent\&. (The second list includes the number of fetches currently active for the given domain, and how many have been passed or dropped because of the \fBfetches\-per\-zone\fR option\&.) .RE .PP \fBrefresh \fR\fB\fIzone\fR\fR\fB \fR\fB[\fIclass\fR [\fIview\fR]]\fR .RS 4 Schedule zone maintenance for the given zone\&. .RE .PP \fBreload\fR .RS 4 Reload configuration file and zones\&. .RE .PP \fBreload \fR\fB\fIzone\fR\fR\fB \fR\fB[\fIclass\fR [\fIview\fR]]\fR .RS 4 Reload the given zone\&. .RE .PP \fBretransfer \fR\fB\fIzone\fR\fR\fB \fR\fB[\fIclass\fR [\fIview\fR]]\fR .RS 4 Retransfer the given slave zone from the master server\&. .sp If the zone is configured to use \fBinline\-signing\fR, the signed version of the zone is discarded; after the retransfer of the unsigned version is complete, the signed version will be regenerated with all new signatures\&. .RE .PP \fBscan\fR .RS 4 Scan the list of available network interfaces for changes, without performing a full \fBreconfig\fR or waiting for the \fBinterface\-interval\fR timer\&. .RE .PP \fBsecroots \fR\fB[\-]\fR\fB \fR\fB[\fIview \&.\&.\&.\fR]\fR .RS 4 Dump the server\*(Aqs security roots and negative trust anchors for the specified views\&. If no view is specified, all views are dumped\&. .sp If the first argument is "\-", then the output is returned via the \fBrndc\fR response channel and printed to the standard output\&. Otherwise, it is written to the secroots dump file, which defaults to named\&.secroots, but can be overridden via the \fBsecroots\-file\fR option in named\&.conf\&. .sp See also \fBrndc managed\-keys\fR\&. .RE .PP \fBshowzone \fR\fB\fIzone\fR\fR\fB \fR\fB[\fIclass\fR [\fIview\fR]]\fR\fB \fR .RS 4 Print the configuration of a running zone\&. .sp See also \fBrndc zonestatus\fR\&. .RE .PP \fBsign \fR\fB\fIzone\fR\fR\fB \fR\fB[\fIclass\fR [\fIview\fR]]\fR .RS 4 Fetch all DNSSEC keys for the given zone from the key directory (see the \fBkey\-directory\fR option in the BIND 9 Administrator Reference Manual)\&. If they are within their publication period, merge them into the zone\*(Aqs DNSKEY RRset\&. If the DNSKEY RRset is changed, then the zone is automatically re\-signed with the new key set\&. .sp This command requires that the \fBauto\-dnssec\fR zone option be set to allow or maintain, and also requires the zone to be configured to allow dynamic DNS\&. (See "Dynamic Update Policies" in the Administrator Reference Manual for more details\&.) .sp See also \fBrndc loadkeys\fR\&. .RE .PP \fBsigning \fR\fB[( \-list | \-clear \fIkeyid/algorithm\fR | \-clear all | \-nsec3param ( \fIparameters\fR | none ) | \-serial \fIvalue\fR ) ]\fR\fB \fR\fB\fIzone\fR\fR\fB \fR\fB[\fIclass\fR [\fIview\fR]]\fR\fB \fR .RS 4 List, edit, or remove the DNSSEC signing state records for the specified zone\&. The status of ongoing DNSSEC operations (such as signing or generating NSEC3 chains) is stored in the zone in the form of DNS resource records of type \fBsig\-signing\-type\fR\&. \fBrndc signing \-list\fR converts these records into a human\-readable form, indicating which keys are currently signing or have finished signing the zone, and which NSEC3 chains are being created or removed\&. .sp \fBrndc signing \-clear\fR can remove a single key (specified in the same format that \fBrndc signing \-list\fR uses to display it), or all keys\&. In either case, only completed keys are removed; any record indicating that a key has not yet finished signing the zone will be retained\&. .sp \fBrndc signing \-nsec3param\fR sets the NSEC3 parameters for a zone\&. This is the only supported mechanism for using NSEC3 with \fBinline\-signing\fR zones\&. Parameters are specified in the same format as an NSEC3PARAM resource record: hash algorithm, flags, iterations, and salt, in that order\&. .sp Currently, the only defined value for hash algorithm is 1, representing SHA\-1\&. The \fBflags\fR may be set to 0 or 1, depending on whether you wish to set the opt\-out bit in the NSEC3 chain\&. \fBiterations\fR defines the number of additional times to apply the algorithm when generating an NSEC3 hash\&. The \fBsalt\fR is a string of data expressed in hexadecimal, a hyphen (`\-\*(Aq) if no salt is to be used, or the keyword auto, which causes \fBnamed\fR to generate a random 64\-bit salt\&. .sp So, for example, to create an NSEC3 chain using the SHA\-1 hash algorithm, no opt\-out flag, 10 iterations, and a salt value of "FFFF", use: \fBrndc signing \-nsec3param 1 0 10 FFFF \fR\fB\fIzone\fR\fR\&. To set the opt\-out flag, 15 iterations, and no salt, use: \fBrndc signing \-nsec3param 1 1 15 \- \fR\fB\fIzone\fR\fR\&. .sp \fBrndc signing \-nsec3param none\fR removes an existing NSEC3 chain and replaces it with NSEC\&. .sp \fBrndc signing \-serial value\fR sets the serial number of the zone to value\&. If the value would cause the serial number to go backwards it will be rejected\&. The primary use is to set the serial on inline signed zones\&. .RE .PP \fBstats\fR .RS 4 Write server statistics to the statistics file\&. (See the \fBstatistics\-file\fR option in the BIND 9 Administrator Reference Manual\&.) .RE .PP \fBstatus\fR .RS 4 Display status of the server\&. Note that the number of zones includes the internal \fBbind/CH\fR zone and the default \fB\&./IN\fR hint zone if there is not an explicit root zone configured\&. .RE .PP \fBstop \fR\fB[\-p]\fR .RS 4 Stop the server, making sure any recent changes made through dynamic update or IXFR are first saved to the master files of the updated zones\&. If \fB\-p\fR is specified \fBnamed\fR\*(Aqs process id is returned\&. This allows an external process to determine when \fBnamed\fR had completed stopping\&. .sp See also \fBrndc halt\fR\&. .RE .PP \fBsync \fR\fB[\-clean]\fR\fB \fR\fB[\fIzone\fR [\fIclass\fR [\fIview\fR]]]\fR .RS 4 Sync changes in the journal file for a dynamic zone to the master file\&. If the "\-clean" option is specified, the journal file is also removed\&. If no zone is specified, then all zones are synced\&. .RE .PP \fBthaw \fR\fB[\fIzone\fR [\fIclass\fR [\fIview\fR]]]\fR .RS 4 Enable updates to a frozen dynamic zone\&. If no zone is specified, then all frozen zones are enabled\&. This causes the server to reload the zone from disk, and re\-enables dynamic updates after the load has completed\&. After a zone is thawed, dynamic updates will no longer be refused\&. If the zone has changed and the \fBixfr\-from\-differences\fR option is in use, then the journal file will be updated to reflect changes in the zone\&. Otherwise, if the zone has changed, any existing journal file will be removed\&. .sp See also \fBrndc freeze\fR\&. .RE .PP \fBtrace\fR .RS 4 Increment the servers debugging level by one\&. .RE .PP \fBtrace \fR\fB\fIlevel\fR\fR .RS 4 Sets the server\*(Aqs debugging level to an explicit value\&. .sp See also \fBrndc notrace\fR\&. .RE .PP \fBtsig\-delete\fR \fIkeyname\fR [\fIview\fR] .RS 4 Delete a given TKEY\-negotiated key from the server\&. (This does not apply to statically configured TSIG keys\&.) .RE .PP \fBtsig\-list\fR .RS 4 List the names of all TSIG keys currently configured for use by \fBnamed\fR in each view\&. The list both statically configured keys and dynamic TKEY\-negotiated keys\&. .RE .PP \fBvalidation ( on | off | status ) \fR\fB[\fIview \&.\&.\&.\fR]\fR\fB \fR .RS 4 Enable, disable, or check the current status of DNSSEC validation\&. Note \fBdnssec\-enable\fR also needs to be set to \fByes\fR or \fBauto\fR to be effective\&. It defaults to enabled\&. .RE .PP \fBzonestatus \fR\fB\fIzone\fR\fR\fB \fR\fB[\fIclass\fR [\fIview\fR]]\fR .RS 4 Displays the current status of the given zone, including the master file name and any include files from which it was loaded, when it was most recently loaded, the current serial number, the number of nodes, whether the zone supports dynamic updates, whether the zone is DNSSEC signed, whether it uses automatic DNSSEC key management or inline signing, and the scheduled refresh or expiry times for the zone\&. .sp See also \fBrndc showzone\fR\&. .RE .SH "LIMITATIONS" .PP There is currently no way to provide the shared secret for a \fBkey_id\fR without using the configuration file\&. .PP Several error messages could be clearer\&. .SH "SEE ALSO" .PP \fBrndc.conf\fR(5), \fBrndc-confgen\fR(8), \fBnamed\fR(8), \fBnamed.conf\fR(5), \fBndc\fR(8), BIND 9 Administrator Reference Manual\&. .SH "AUTHOR" .PP \fBInternet Systems Consortium, Inc\&.\fR .SH "COPYRIGHT" .br Copyright \(co 2000, 2001, 2004, 2005, 2007, 2013-2018 Internet Systems Consortium, Inc. ("ISC") .br bind9-9.11.3+dfsg/bin/rndc/rndc.c000066400000000000000000000660351325250447100163360ustar00rootroot00000000000000/* * Copyright (C) 2000-2018 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /*! \file */ /* * Principal Author: DCL */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "util.h" #define SERVERADDRS 10 const char *progname; isc_boolean_t verbose; static const char *admin_conffile; static const char *admin_keyfile; static const char *version = VERSION; static const char *servername = NULL; static isc_sockaddr_t serveraddrs[SERVERADDRS]; static isc_sockaddr_t local4, local6; static isc_boolean_t local4set = ISC_FALSE, local6set = ISC_FALSE; static int nserveraddrs; static int currentaddr = 0; static unsigned int remoteport = 0; static isc_socketmgr_t *socketmgr = NULL; static isc_buffer_t *databuf; static isccc_ccmsg_t ccmsg; static isc_uint32_t algorithm; static isccc_region_t secret; static isc_boolean_t failed = ISC_FALSE; static isc_boolean_t c_flag = ISC_FALSE; static isc_mem_t *rndc_mctx; static int sends, recvs, connects; static char *command; static char *args; static char program[256]; static isc_socket_t *sock = NULL; static isc_uint32_t serial; static isc_boolean_t quiet = ISC_FALSE; static isc_boolean_t showresult = ISC_FALSE; static void rndc_startconnect(isc_sockaddr_t *addr, isc_task_t *task); ISC_PLATFORM_NORETURN_PRE static void usage(int status) ISC_PLATFORM_NORETURN_POST; static void usage(int status) { fprintf(stderr, "\ Usage: %s [-b address] [-c config] [-s server] [-p port]\n\ [-k key-file ] [-y key] [-r] [-V] command\n\ \n\ command is one of the following:\n\ \n\ addzone zone [class [view]] { zone-options }\n\ Add zone to given view. Requires allow-new-zones option.\n\ delzone [-clean] zone [class [view]]\n\ Removes zone from given view.\n\ dnstap -reopen\n\ Close, truncate and re-open the DNSTAP output file.\n\ dnstap -roll count\n\ Close, rename and re-open the DNSTAP output file(s).\n\ dumpdb [-all|-cache|-zones|-adb|-bad|-fail] [view ...]\n\ Dump cache(s) to the dump file (named_dump.db).\n\ flush Flushes all of the server's caches.\n\ flush [view] Flushes the server's cache for a view.\n\ flushname name [view]\n\ Flush the given name from the server's cache(s)\n\ flushtree name [view]\n\ Flush all names under the given name from the server's cache(s)\n\ freeze Suspend updates to all dynamic zones.\n\ freeze zone [class [view]]\n\ Suspend updates to a dynamic zone.\n\ halt Stop the server without saving pending updates.\n\ halt -p Stop the server without saving pending updates reporting\n\ process id.\n\ loadkeys zone [class [view]]\n\ Update keys without signing immediately.\n\ managed-keys refresh [class [view]]\n\ Check trust anchor for RFC 5011 key changes\n\ managed-keys status [class [view]]\n\ Display RFC 5011 managed keys information\n\ managed-keys sync [class [view]]\n\ Write RFC 5011 managed keys to disk\n\ modzone zone [class [view]] { zone-options }\n\ Modify a zone's configuration.\n\ Requires allow-new-zones option.\n\ notify zone [class [view]]\n\ Resend NOTIFY messages for the zone.\n\ notrace Set debugging level to 0.\n\ nta -dump\n\ List all negative trust anchors.\n\ nta [-lifetime duration] [-force] domain [view]\n\ Set a negative trust anchor, disabling DNSSEC validation\n\ for the given domain.\n\ Using -lifetime specifies the duration of the NTA, up\n\ to one week.\n\ Using -force prevents the NTA from expiring before its\n\ full lifetime, even if the domain can validate sooner.\n\ nta -remove domain [view]\n\ Remove a negative trust anchor, re-enabling validation\n\ for the given domain.\n\ querylog [ on | off ]\n\ Enable / disable query logging.\n\ reconfig Reload configuration file and new zones only.\n\ recursing Dump the queries that are currently recursing (named.recursing)\n\ refresh zone [class [view]]\n\ Schedule immediate maintenance for a zone.\n\ reload Reload configuration file and zones.\n\ reload zone [class [view]]\n\ Reload a single zone.\n\ retransfer zone [class [view]]\n\ Retransfer a single zone without checking serial number.\n\ scan Scan available network interfaces for changes.\n\ secroots [view ...]\n\ Write security roots to the secroots file.\n\ showzone zone [class [view]]\n\ Print a zone's configuration.\n\ sign zone [class [view]]\n\ Update zone keys, and sign as needed.\n\ signing -clear all zone [class [view]]\n\ Remove the private records for all keys that have\n\ finished signing the given zone.\n\ signing -clear / zone [class [view]]\n\ Remove the private record that indicating the given key\n\ has finished signing the given zone.\n\ signing -list zone [class [view]]\n\ List the private records showing the state of DNSSEC\n\ signing in the given zone.\n\ signing -nsec3param hash flags iterations salt zone [class [view]]\n\ Add NSEC3 chain to zone if already signed.\n\ Prime zone with NSEC3 chain if not yet signed.\n\ signing -nsec3param none zone [class [view]]\n\ Remove NSEC3 chains from zone.\n\ signing -serial zone [class [view]]\n\ Set the zones's serial to .\n\ stats Write server statistics to the statistics file.\n\ status Display status of the server.\n\ stop Save pending updates to master files and stop the server.\n\ stop -p Save pending updates to master files and stop the server\n\ reporting process id.\n\ sync [-clean] Dump changes to all dynamic zones to disk, and optionally\n\ remove their journal files.\n\ sync [-clean] zone [class [view]]\n\ Dump a single zone's changes to disk, and optionally\n\ remove its journal file.\n\ thaw Enable updates to all dynamic zones and reload them.\n\ thaw zone [class [view]]\n\ Enable updates to a frozen dynamic zone and reload it.\n\ trace Increment debugging level by one.\n\ trace level Change the debugging level.\n\ tsig-delete keyname [view]\n\ Delete a TKEY-negotiated TSIG key.\n\ tsig-list List all currently active TSIG keys, including both statically\n\ configured and TKEY-negotiated keys.\n\ validation [ yes | no | status ] [view]\n\ Enable / disable DNSSEC validation.\n\ zonestatus zone [class [view]]\n\ Display the current status of a zone.\n\ \n\ Version: %s\n", progname, version); exit(status); } static void get_addresses(const char *host, in_port_t port) { isc_result_t result; int found = 0, count; if (*host == '/') { result = isc_sockaddr_frompath(&serveraddrs[nserveraddrs], host); if (result == ISC_R_SUCCESS) nserveraddrs++; } else { count = SERVERADDRS - nserveraddrs; result = bind9_getaddresses(host, port, &serveraddrs[nserveraddrs], count, &found); nserveraddrs += found; } if (result != ISC_R_SUCCESS) fatal("couldn't get address for '%s': %s", host, isc_result_totext(result)); INSIST(nserveraddrs > 0); } static void rndc_senddone(isc_task_t *task, isc_event_t *event) { isc_socketevent_t *sevent = (isc_socketevent_t *)event; UNUSED(task); sends--; if (sevent->result != ISC_R_SUCCESS) fatal("send failed: %s", isc_result_totext(sevent->result)); isc_event_free(&event); if (sends == 0 && recvs == 0) { isc_socket_detach(&sock); isc_task_shutdown(task); RUNTIME_CHECK(isc_app_shutdown() == ISC_R_SUCCESS); } } static void rndc_recvdone(isc_task_t *task, isc_event_t *event) { isccc_sexpr_t *response = NULL; isccc_sexpr_t *data; isccc_region_t source; char *errormsg = NULL; char *textmsg = NULL; isc_result_t result; recvs--; if (ccmsg.result == ISC_R_EOF) fatal("connection to remote host closed\n" "This may indicate that\n" "* the remote server is using an older version of" " the command protocol,\n" "* this host is not authorized to connect,\n" "* the clocks are not synchronized, or\n" "* the key is invalid."); if (ccmsg.result != ISC_R_SUCCESS) fatal("recv failed: %s", isc_result_totext(ccmsg.result)); source.rstart = isc_buffer_base(&ccmsg.buffer); source.rend = isc_buffer_used(&ccmsg.buffer); DO("parse message", isccc_cc_fromwire(&source, &response, algorithm, &secret)); data = isccc_alist_lookup(response, "_data"); if (!isccc_alist_alistp(data)) fatal("bad or missing data section in response"); result = isccc_cc_lookupstring(data, "err", &errormsg); if (result == ISC_R_SUCCESS) { failed = ISC_TRUE; fprintf(stderr, "%s: '%s' failed: %s\n", progname, command, errormsg); } else if (result != ISC_R_NOTFOUND) fprintf(stderr, "%s: parsing response failed: %s\n", progname, isc_result_totext(result)); result = isccc_cc_lookupstring(data, "text", &textmsg); if (result == ISC_R_SUCCESS) { if ((!quiet || failed) && strlen(textmsg) != 0U) fprintf(failed ? stderr : stdout, "%s\n", textmsg); } else if (result != ISC_R_NOTFOUND) fprintf(stderr, "%s: parsing response failed: %s\n", progname, isc_result_totext(result)); if (showresult) { isc_result_t eresult; result = isccc_cc_lookupuint32(data, "result", &eresult); if (result == ISC_R_SUCCESS) printf("%s %u\n", isc_result_toid(eresult), eresult); else printf("NONE -1\n"); } isc_event_free(&event); isccc_sexpr_free(&response); if (sends == 0 && recvs == 0) { isc_socket_detach(&sock); isc_task_shutdown(task); RUNTIME_CHECK(isc_app_shutdown() == ISC_R_SUCCESS); } } static void rndc_recvnonce(isc_task_t *task, isc_event_t *event) { isccc_sexpr_t *response = NULL; isccc_sexpr_t *_ctrl; isccc_region_t source; isc_result_t result; isc_uint32_t nonce; isccc_sexpr_t *request = NULL; isccc_time_t now; isc_region_t r; isccc_sexpr_t *data; isc_buffer_t b; recvs--; if (ccmsg.result == ISC_R_EOF) fatal("connection to remote host closed\n" "This may indicate that\n" "* the remote server is using an older version of" " the command protocol,\n" "* this host is not authorized to connect,\n" "* the clocks are not synchronized,\n" "* the key signing algorithm is incorrect, or\n" "* the key is invalid."); if (ccmsg.result != ISC_R_SUCCESS) fatal("recv failed: %s", isc_result_totext(ccmsg.result)); source.rstart = isc_buffer_base(&ccmsg.buffer); source.rend = isc_buffer_used(&ccmsg.buffer); DO("parse message", isccc_cc_fromwire(&source, &response, algorithm, &secret)); _ctrl = isccc_alist_lookup(response, "_ctrl"); if (!isccc_alist_alistp(_ctrl)) fatal("bad or missing ctrl section in response"); nonce = 0; if (isccc_cc_lookupuint32(_ctrl, "_nonce", &nonce) != ISC_R_SUCCESS) nonce = 0; isc_stdtime_get(&now); DO("create message", isccc_cc_createmessage(1, NULL, NULL, ++serial, now, now + 60, &request)); data = isccc_alist_lookup(request, "_data"); if (data == NULL) fatal("_data section missing"); if (isccc_cc_definestring(data, "type", args) == NULL) fatal("out of memory"); if (nonce != 0) { _ctrl = isccc_alist_lookup(request, "_ctrl"); if (_ctrl == NULL) fatal("_ctrl section missing"); if (isccc_cc_defineuint32(_ctrl, "_nonce", nonce) == NULL) fatal("out of memory"); } isc_buffer_clear(databuf); /* Skip the length field (4 bytes) */ isc_buffer_add(databuf, 4); DO("render message", isccc_cc_towire(request, &databuf, algorithm, &secret)); isc_buffer_init(&b, databuf->base, 4); isc_buffer_putuint32(&b, databuf->used - 4); r.base = databuf->base; r.length = databuf->used; isccc_ccmsg_cancelread(&ccmsg); DO("schedule recv", isccc_ccmsg_readmessage(&ccmsg, task, rndc_recvdone, NULL)); recvs++; DO("send message", isc_socket_send(sock, &r, task, rndc_senddone, NULL)); sends++; isc_event_free(&event); isccc_sexpr_free(&response); isccc_sexpr_free(&request); return; } static void rndc_connected(isc_task_t *task, isc_event_t *event) { char socktext[ISC_SOCKADDR_FORMATSIZE]; isc_socketevent_t *sevent = (isc_socketevent_t *)event; isccc_sexpr_t *request = NULL; isccc_sexpr_t *data; isccc_time_t now; isc_region_t r; isc_buffer_t b; isc_result_t result; connects--; if (sevent->result != ISC_R_SUCCESS) { isc_sockaddr_format(&serveraddrs[currentaddr], socktext, sizeof(socktext)); if (sevent->result != ISC_R_CANCELED && ++currentaddr < nserveraddrs) { notify("connection failed: %s: %s", socktext, isc_result_totext(sevent->result)); isc_socket_detach(&sock); isc_event_free(&event); rndc_startconnect(&serveraddrs[currentaddr], task); return; } else fatal("connect failed: %s: %s", socktext, isc_result_totext(sevent->result)); } isc_stdtime_get(&now); DO("create message", isccc_cc_createmessage(1, NULL, NULL, ++serial, now, now + 60, &request)); data = isccc_alist_lookup(request, "_data"); if (data == NULL) fatal("_data section missing"); if (isccc_cc_definestring(data, "type", "null") == NULL) fatal("out of memory"); isc_buffer_clear(databuf); /* Skip the length field (4 bytes) */ isc_buffer_add(databuf, 4); DO("render message", isccc_cc_towire(request, &databuf, algorithm, &secret)); isc_buffer_init(&b, databuf->base, 4); isc_buffer_putuint32(&b, databuf->used - 4); r.base = databuf->base; r.length = databuf->used; isccc_ccmsg_init(rndc_mctx, sock, &ccmsg); isccc_ccmsg_setmaxsize(&ccmsg, 1024 * 1024); DO("schedule recv", isccc_ccmsg_readmessage(&ccmsg, task, rndc_recvnonce, NULL)); recvs++; DO("send message", isc_socket_send(sock, &r, task, rndc_senddone, NULL)); sends++; isc_event_free(&event); isccc_sexpr_free(&request); } static void rndc_startconnect(isc_sockaddr_t *addr, isc_task_t *task) { isc_result_t result; int pf; isc_sockettype_t type; char socktext[ISC_SOCKADDR_FORMATSIZE]; isc_sockaddr_format(addr, socktext, sizeof(socktext)); notify("using server %s (%s)", servername, socktext); pf = isc_sockaddr_pf(addr); if (pf == AF_INET || pf == AF_INET6) type = isc_sockettype_tcp; else type = isc_sockettype_unix; DO("create socket", isc_socket_create(socketmgr, pf, type, &sock)); switch (isc_sockaddr_pf(addr)) { case AF_INET: DO("bind socket", isc_socket_bind(sock, &local4, 0)); break; case AF_INET6: DO("bind socket", isc_socket_bind(sock, &local6, 0)); break; default: break; } DO("connect", isc_socket_connect(sock, addr, task, rndc_connected, NULL)); connects++; } static void rndc_start(isc_task_t *task, isc_event_t *event) { isc_event_free(&event); currentaddr = 0; rndc_startconnect(&serveraddrs[currentaddr], task); } static void parse_config(isc_mem_t *mctx, isc_log_t *log, const char *keyname, cfg_parser_t **pctxp, cfg_obj_t **configp) { isc_result_t result; const char *conffile = admin_conffile; const cfg_obj_t *addresses = NULL; const cfg_obj_t *defkey = NULL; const cfg_obj_t *options = NULL; const cfg_obj_t *servers = NULL; const cfg_obj_t *server = NULL; const cfg_obj_t *keys = NULL; const cfg_obj_t *key = NULL; const cfg_obj_t *defport = NULL; const cfg_obj_t *secretobj = NULL; const cfg_obj_t *algorithmobj = NULL; cfg_obj_t *config = NULL; const cfg_obj_t *address = NULL; const cfg_listelt_t *elt; const char *secretstr; const char *algorithmstr; static char secretarray[1024]; const cfg_type_t *conftype = &cfg_type_rndcconf; isc_boolean_t key_only = ISC_FALSE; const cfg_listelt_t *element; if (! isc_file_exists(conffile)) { conffile = admin_keyfile; conftype = &cfg_type_rndckey; if (c_flag) fatal("%s does not exist", admin_conffile); if (! isc_file_exists(conffile)) fatal("neither %s nor %s was found", admin_conffile, admin_keyfile); key_only = ISC_TRUE; } else if (! c_flag && isc_file_exists(admin_keyfile)) { fprintf(stderr, "WARNING: key file (%s) exists, but using " "default configuration file (%s)\n", admin_keyfile, admin_conffile); } DO("create parser", cfg_parser_create(mctx, log, pctxp)); /* * The parser will output its own errors, so DO() is not used. */ result = cfg_parse_file(*pctxp, conffile, conftype, &config); if (result != ISC_R_SUCCESS) fatal("could not load rndc configuration"); if (!key_only) (void)cfg_map_get(config, "options", &options); if (key_only && servername == NULL) servername = "127.0.0.1"; else if (servername == NULL && options != NULL) { const cfg_obj_t *defserverobj = NULL; (void)cfg_map_get(options, "default-server", &defserverobj); if (defserverobj != NULL) servername = cfg_obj_asstring(defserverobj); } if (servername == NULL) fatal("no server specified and no default"); if (!key_only) { (void)cfg_map_get(config, "server", &servers); if (servers != NULL) { for (elt = cfg_list_first(servers); elt != NULL; elt = cfg_list_next(elt)) { const char *name; server = cfg_listelt_value(elt); name = cfg_obj_asstring(cfg_map_getname(server)); if (strcasecmp(name, servername) == 0) break; server = NULL; } } } /* * Look for the name of the key to use. */ if (keyname != NULL) ; /* Was set on command line, do nothing. */ else if (server != NULL) { DO("get key for server", cfg_map_get(server, "key", &defkey)); keyname = cfg_obj_asstring(defkey); } else if (options != NULL) { DO("get default key", cfg_map_get(options, "default-key", &defkey)); keyname = cfg_obj_asstring(defkey); } else if (!key_only) fatal("no key for server and no default"); /* * Get the key's definition. */ if (key_only) DO("get key", cfg_map_get(config, "key", &key)); else { DO("get config key list", cfg_map_get(config, "key", &keys)); for (elt = cfg_list_first(keys); elt != NULL; elt = cfg_list_next(elt)) { key = cfg_listelt_value(elt); if (strcasecmp(cfg_obj_asstring(cfg_map_getname(key)), keyname) == 0) break; } if (elt == NULL) fatal("no key definition for name %s", keyname); } (void)cfg_map_get(key, "secret", &secretobj); (void)cfg_map_get(key, "algorithm", &algorithmobj); if (secretobj == NULL || algorithmobj == NULL) fatal("key must have algorithm and secret"); secretstr = cfg_obj_asstring(secretobj); algorithmstr = cfg_obj_asstring(algorithmobj); #ifndef PK11_MD5_DISABLE if (strcasecmp(algorithmstr, "hmac-md5") == 0) algorithm = ISCCC_ALG_HMACMD5; else #endif if (strcasecmp(algorithmstr, "hmac-sha1") == 0) algorithm = ISCCC_ALG_HMACSHA1; else if (strcasecmp(algorithmstr, "hmac-sha224") == 0) algorithm = ISCCC_ALG_HMACSHA224; else if (strcasecmp(algorithmstr, "hmac-sha256") == 0) algorithm = ISCCC_ALG_HMACSHA256; else if (strcasecmp(algorithmstr, "hmac-sha384") == 0) algorithm = ISCCC_ALG_HMACSHA384; else if (strcasecmp(algorithmstr, "hmac-sha512") == 0) algorithm = ISCCC_ALG_HMACSHA512; else fatal("unsupported algorithm: %s", algorithmstr); secret.rstart = (unsigned char *)secretarray; secret.rend = (unsigned char *)secretarray + sizeof(secretarray); DO("decode base64 secret", isccc_base64_decode(secretstr, &secret)); secret.rend = secret.rstart; secret.rstart = (unsigned char *)secretarray; /* * Find the port to connect to. */ if (remoteport != 0) ; /* Was set on command line, do nothing. */ else { if (server != NULL) (void)cfg_map_get(server, "port", &defport); if (defport == NULL && options != NULL) (void)cfg_map_get(options, "default-port", &defport); } if (defport != NULL) { remoteport = cfg_obj_asuint32(defport); if (remoteport > 65535 || remoteport == 0) fatal("port %u out of range", remoteport); } else if (remoteport == 0) remoteport = NS_CONTROL_PORT; if (server != NULL) result = cfg_map_get(server, "addresses", &addresses); else result = ISC_R_NOTFOUND; if (result == ISC_R_SUCCESS) { for (element = cfg_list_first(addresses); element != NULL; element = cfg_list_next(element)) { isc_sockaddr_t sa; address = cfg_listelt_value(element); if (!cfg_obj_issockaddr(address)) { unsigned int myport; const char *name; const cfg_obj_t *obj; obj = cfg_tuple_get(address, "name"); name = cfg_obj_asstring(obj); obj = cfg_tuple_get(address, "port"); if (cfg_obj_isuint32(obj)) { myport = cfg_obj_asuint32(obj); if (myport > ISC_UINT16_MAX || myport == 0) fatal("port %u out of range", myport); } else myport = remoteport; if (nserveraddrs < SERVERADDRS) get_addresses(name, (in_port_t) myport); else fprintf(stderr, "too many address: " "%s: dropped\n", name); continue; } sa = *cfg_obj_assockaddr(address); if (isc_sockaddr_getport(&sa) == 0) isc_sockaddr_setport(&sa, remoteport); if (nserveraddrs < SERVERADDRS) serveraddrs[nserveraddrs++] = sa; else { char socktext[ISC_SOCKADDR_FORMATSIZE]; isc_sockaddr_format(&sa, socktext, sizeof(socktext)); fprintf(stderr, "too many address: %s: dropped\n", socktext); } } } if (!local4set && server != NULL) { address = NULL; cfg_map_get(server, "source-address", &address); if (address != NULL) { local4 = *cfg_obj_assockaddr(address); local4set = ISC_TRUE; } } if (!local4set && options != NULL) { address = NULL; cfg_map_get(options, "default-source-address", &address); if (address != NULL) { local4 = *cfg_obj_assockaddr(address); local4set = ISC_TRUE; } } if (!local6set && server != NULL) { address = NULL; cfg_map_get(server, "source-address-v6", &address); if (address != NULL) { local6 = *cfg_obj_assockaddr(address); local6set = ISC_TRUE; } } if (!local6set && options != NULL) { address = NULL; cfg_map_get(options, "default-source-address-v6", &address); if (address != NULL) { local6 = *cfg_obj_assockaddr(address); local6set = ISC_TRUE; } } *configp = config; } int main(int argc, char **argv) { isc_result_t result = ISC_R_SUCCESS; isc_boolean_t show_final_mem = ISC_FALSE; isc_taskmgr_t *taskmgr = NULL; isc_task_t *task = NULL; isc_log_t *log = NULL; isc_logconfig_t *logconfig = NULL; isc_logdestination_t logdest; cfg_parser_t *pctx = NULL; cfg_obj_t *config = NULL; const char *keyname = NULL; struct in_addr in; struct in6_addr in6; char *p; size_t argslen; int ch; int i; result = isc_file_progname(*argv, program, sizeof(program)); if (result != ISC_R_SUCCESS) memmove(program, "rndc", 5); progname = program; admin_conffile = RNDC_CONFFILE; admin_keyfile = RNDC_KEYFILE; isc_sockaddr_any(&local4); isc_sockaddr_any6(&local6); result = isc_app_start(); if (result != ISC_R_SUCCESS) fatal("isc_app_start() failed: %s", isc_result_totext(result)); isc_commandline_errprint = ISC_FALSE; while ((ch = isc_commandline_parse(argc, argv, "b:c:hk:Mmp:qrs:Vy:")) != -1) { switch (ch) { case 'b': if (inet_pton(AF_INET, isc_commandline_argument, &in) == 1) { isc_sockaddr_fromin(&local4, &in, 0); local4set = ISC_TRUE; } else if (inet_pton(AF_INET6, isc_commandline_argument, &in6) == 1) { isc_sockaddr_fromin6(&local6, &in6, 0); local6set = ISC_TRUE; } break; case 'c': admin_conffile = isc_commandline_argument; c_flag = ISC_TRUE; break; case 'k': admin_keyfile = isc_commandline_argument; break; case 'M': isc_mem_debugging = ISC_MEM_DEBUGTRACE; break; case 'm': show_final_mem = ISC_TRUE; break; case 'p': remoteport = atoi(isc_commandline_argument); if (remoteport > 65535 || remoteport == 0) fatal("port '%s' out of range", isc_commandline_argument); break; case 'q': quiet = ISC_TRUE; break; case 'r': showresult = ISC_TRUE; break; case 's': servername = isc_commandline_argument; break; case 'V': verbose = ISC_TRUE; break; case 'y': keyname = isc_commandline_argument; break; case '?': if (isc_commandline_option != '?') { fprintf(stderr, "%s: invalid argument -%c\n", program, isc_commandline_option); usage(1); } /* FALLTHROUGH */ case 'h': usage(0); break; default: fprintf(stderr, "%s: unhandled option -%c\n", program, isc_commandline_option); exit(1); } } argc -= isc_commandline_index; argv += isc_commandline_index; if (argc < 1) usage(1); isc_random_get(&serial); DO("create memory context", isc_mem_create(0, 0, &rndc_mctx)); DO("create socket manager", isc_socketmgr_create(rndc_mctx, &socketmgr)); DO("create task manager", isc_taskmgr_create(rndc_mctx, 1, 0, &taskmgr)); DO("create task", isc_task_create(taskmgr, 0, &task)); DO("create logging context", isc_log_create(rndc_mctx, &log, &logconfig)); isc_log_setcontext(log); DO("setting log tag", isc_log_settag(logconfig, progname)); logdest.file.stream = stderr; logdest.file.name = NULL; logdest.file.versions = ISC_LOG_ROLLNEVER; logdest.file.maximum_size = 0; DO("creating log channel", isc_log_createchannel(logconfig, "stderr", ISC_LOG_TOFILEDESC, ISC_LOG_INFO, &logdest, ISC_LOG_PRINTTAG|ISC_LOG_PRINTLEVEL)); DO("enabling log channel", isc_log_usechannel(logconfig, "stderr", NULL, NULL)); parse_config(rndc_mctx, log, keyname, &pctx, &config); isccc_result_register(); command = *argv; DO("allocate data buffer", isc_buffer_allocate(rndc_mctx, &databuf, 2048)); /* * Convert argc/argv into a space-delimited command string * similar to what the user might enter in interactive mode * (if that were implemented). */ argslen = 0; for (i = 0; i < argc; i++) argslen += strlen(argv[i]) + 1; args = isc_mem_get(rndc_mctx, argslen); if (args == NULL) DO("isc_mem_get", ISC_R_NOMEMORY); p = args; for (i = 0; i < argc; i++) { size_t len = strlen(argv[i]); memmove(p, argv[i], len); p += len; *p++ = ' '; } p--; *p++ = '\0'; INSIST(p == args + argslen); notify("%s", command); if (strcmp(command, "restart") == 0) fatal("'%s' is not implemented", command); if (nserveraddrs == 0) get_addresses(servername, (in_port_t) remoteport); DO("post event", isc_app_onrun(rndc_mctx, task, rndc_start, NULL)); result = isc_app_run(); if (result != ISC_R_SUCCESS) fatal("isc_app_run() failed: %s", isc_result_totext(result)); if (connects > 0 || sends > 0 || recvs > 0) isc_socket_cancel(sock, task, ISC_SOCKCANCEL_ALL); isc_task_detach(&task); isc_taskmgr_destroy(&taskmgr); isc_socketmgr_destroy(&socketmgr); isc_log_destroy(&log); isc_log_setcontext(NULL); cfg_obj_destroy(pctx, &config); cfg_parser_destroy(&pctx); isc_mem_put(rndc_mctx, args, argslen); isccc_ccmsg_invalidate(&ccmsg); dns_name_destroy(); isc_buffer_free(&databuf); if (show_final_mem) isc_mem_stats(rndc_mctx, stderr); isc_mem_destroy(&rndc_mctx); if (failed) return (1); return (0); } bind9-9.11.3+dfsg/bin/rndc/rndc.conf000066400000000000000000000014311325250447100170260ustar00rootroot00000000000000/* * Copyright (C) 2000, 2001, 2004, 2007, 2013, 2014, 2016 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * Sample rndc configuration file. */ options { default-server localhost; default-key "key"; }; server localhost { key "key"; }; key "cc64b3d1db63fc88d7cb5d2f9f57d258" { algorithm hmac-sha256; secret "34f88008d07deabbe65bd01f1d233d47"; }; server "test1" { key "cc64b3d1db63fc88d7cb5d2f9f57d258"; port 5353; addresses { 10.53.0.1; }; }; key "key" { algorithm hmac-sha256; secret "c3Ryb25nIGVub3VnaCBmb3IgYSBtYW4gYnV0IG1hZGUgZm9yIGEgd29tYW4K"; }; bind9-9.11.3+dfsg/bin/rndc/rndc.conf.5000066400000000000000000000157131325250447100172010ustar00rootroot00000000000000.\" Copyright (C) 2000, 2001, 2004, 2005, 2007, 2013-2016 Internet Systems Consortium, Inc. ("ISC") .\" .\" This Source Code Form is subject to the terms of the Mozilla Public .\" License, v. 2.0. If a copy of the MPL was not distributed with this .\" file, You can obtain one at http://mozilla.org/MPL/2.0/. .\" .hy 0 .ad l '\" t .\" Title: rndc.conf .\" Author: .\" Generator: DocBook XSL Stylesheets v1.78.1 .\" Date: 2013-03-14 .\" Manual: BIND9 .\" Source: ISC .\" Language: English .\" .TH "RNDC\&.CONF" "5" "2013\-03\-14" "ISC" "BIND9" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" rndc.conf \- rndc configuration file .SH "SYNOPSIS" .HP \w'\fBrndc\&.conf\fR\ 'u \fBrndc\&.conf\fR .SH "DESCRIPTION" .PP rndc\&.conf is the configuration file for \fBrndc\fR, the BIND 9 name server control utility\&. This file has a similar structure and syntax to named\&.conf\&. Statements are enclosed in braces and terminated with a semi\-colon\&. Clauses in the statements are also semi\-colon terminated\&. The usual comment styles are supported: .PP C style: /* */ .PP C++ style: // to end of line .PP Unix style: # to end of line .PP rndc\&.conf is much simpler than named\&.conf\&. The file uses three statements: an options statement, a server statement and a key statement\&. .PP The \fBoptions\fR statement contains five clauses\&. The \fBdefault\-server\fR clause is followed by the name or address of a name server\&. This host will be used when no name server is given as an argument to \fBrndc\fR\&. The \fBdefault\-key\fR clause is followed by the name of a key which is identified by a \fBkey\fR statement\&. If no \fBkeyid\fR is provided on the rndc command line, and no \fBkey\fR clause is found in a matching \fBserver\fR statement, this default key will be used to authenticate the server\*(Aqs commands and responses\&. The \fBdefault\-port\fR clause is followed by the port to connect to on the remote name server\&. If no \fBport\fR option is provided on the rndc command line, and no \fBport\fR clause is found in a matching \fBserver\fR statement, this default port will be used to connect\&. The \fBdefault\-source\-address\fR and \fBdefault\-source\-address\-v6\fR clauses which can be used to set the IPv4 and IPv6 source addresses respectively\&. .PP After the \fBserver\fR keyword, the server statement includes a string which is the hostname or address for a name server\&. The statement has three possible clauses: \fBkey\fR, \fBport\fR and \fBaddresses\fR\&. The key name must match the name of a key statement in the file\&. The port number specifies the port to connect to\&. If an \fBaddresses\fR clause is supplied these addresses will be used instead of the server name\&. Each address can take an optional port\&. If an \fBsource\-address\fR or \fBsource\-address\-v6\fR of supplied then these will be used to specify the IPv4 and IPv6 source addresses respectively\&. .PP The \fBkey\fR statement begins with an identifying string, the name of the key\&. The statement has two clauses\&. \fBalgorithm\fR identifies the authentication algorithm for \fBrndc\fR to use; currently only HMAC\-MD5 (for compatibility), HMAC\-SHA1, HMAC\-SHA224, HMAC\-SHA256 (default), HMAC\-SHA384 and HMAC\-SHA512 are supported\&. This is followed by a secret clause which contains the base\-64 encoding of the algorithm\*(Aqs authentication key\&. The base\-64 string is enclosed in double quotes\&. .PP There are two common ways to generate the base\-64 string for the secret\&. The BIND 9 program \fBrndc\-confgen\fR can be used to generate a random key, or the \fBmmencode\fR program, also known as \fBmimencode\fR, can be used to generate a base\-64 string from known input\&. \fBmmencode\fR does not ship with BIND 9 but is available on many systems\&. See the EXAMPLE section for sample command lines for each\&. .SH "EXAMPLE" .PP .if n \{\ .RS 4 .\} .nf options { default\-server localhost; default\-key samplekey; }; .fi .if n \{\ .RE .\} .PP .if n \{\ .RS 4 .\} .nf server localhost { key samplekey; }; .fi .if n \{\ .RE .\} .PP .if n \{\ .RS 4 .\} .nf server testserver { key testkey; addresses { localhost port 5353; }; }; .fi .if n \{\ .RE .\} .PP .if n \{\ .RS 4 .\} .nf key samplekey { algorithm hmac\-sha256; secret "6FMfj43Osz4lyb24OIe2iGEz9lf1llJO+lz"; }; .fi .if n \{\ .RE .\} .PP .if n \{\ .RS 4 .\} .nf key testkey { algorithm hmac\-sha256; secret "R3HI8P6BKw9ZwXwN3VZKuQ=="; }; .fi .if n \{\ .RE .\} .PP In the above example, \fBrndc\fR will by default use the server at localhost (127\&.0\&.0\&.1) and the key called samplekey\&. Commands to the localhost server will use the samplekey key, which must also be defined in the server\*(Aqs configuration file with the same name and secret\&. The key statement indicates that samplekey uses the HMAC\-SHA256 algorithm and its secret clause contains the base\-64 encoding of the HMAC\-SHA256 secret enclosed in double quotes\&. .PP If \fBrndc \-s testserver\fR is used then \fBrndc\fR will connect to server on localhost port 5353 using the key testkey\&. .PP To generate a random secret with \fBrndc\-confgen\fR: .PP \fBrndc\-confgen\fR .PP A complete rndc\&.conf file, including the randomly generated key, will be written to the standard output\&. Commented\-out \fBkey\fR and \fBcontrols\fR statements for named\&.conf are also printed\&. .PP To generate a base\-64 secret with \fBmmencode\fR: .PP \fBecho "known plaintext for a secret" | mmencode\fR .SH "NAME SERVER CONFIGURATION" .PP The name server must be configured to accept rndc connections and to recognize the key specified in the rndc\&.conf file, using the controls statement in named\&.conf\&. See the sections on the \fBcontrols\fR statement in the BIND 9 Administrator Reference Manual for details\&. .SH "SEE ALSO" .PP \fBrndc\fR(8), \fBrndc-confgen\fR(8), \fBmmencode\fR(1), BIND 9 Administrator Reference Manual\&. .SH "AUTHOR" .PP \fBInternet Systems Consortium, Inc\&.\fR .SH "COPYRIGHT" .br Copyright \(co 2000, 2001, 2004, 2005, 2007, 2013-2016 Internet Systems Consortium, Inc. ("ISC") .br bind9-9.11.3+dfsg/bin/rndc/rndc.conf.docbook000066400000000000000000000207541325250447100204560ustar00rootroot00000000000000 2013-03-14 ISC Internet Systems Consortium, Inc. rndc.conf 5 BIND9 rndc.conf rndc configuration file 2000 2001 2004 2005 2007 2013 2014 2015 2016 Internet Systems Consortium, Inc. ("ISC") rndc.conf DESCRIPTION rndc.conf is the configuration file for rndc, the BIND 9 name server control utility. This file has a similar structure and syntax to named.conf. Statements are enclosed in braces and terminated with a semi-colon. Clauses in the statements are also semi-colon terminated. The usual comment styles are supported: C style: /* */ C++ style: // to end of line Unix style: # to end of line rndc.conf is much simpler than named.conf. The file uses three statements: an options statement, a server statement and a key statement. The statement contains five clauses. The clause is followed by the name or address of a name server. This host will be used when no name server is given as an argument to rndc. The clause is followed by the name of a key which is identified by a statement. If no is provided on the rndc command line, and no clause is found in a matching statement, this default key will be used to authenticate the server's commands and responses. The clause is followed by the port to connect to on the remote name server. If no option is provided on the rndc command line, and no clause is found in a matching statement, this default port will be used to connect. The and clauses which can be used to set the IPv4 and IPv6 source addresses respectively. After the keyword, the server statement includes a string which is the hostname or address for a name server. The statement has three possible clauses: , and . The key name must match the name of a key statement in the file. The port number specifies the port to connect to. If an clause is supplied these addresses will be used instead of the server name. Each address can take an optional port. If an or of supplied then these will be used to specify the IPv4 and IPv6 source addresses respectively. The statement begins with an identifying string, the name of the key. The statement has two clauses. identifies the authentication algorithm for rndc to use; currently only HMAC-MD5 (for compatibility), HMAC-SHA1, HMAC-SHA224, HMAC-SHA256 (default), HMAC-SHA384 and HMAC-SHA512 are supported. This is followed by a secret clause which contains the base-64 encoding of the algorithm's authentication key. The base-64 string is enclosed in double quotes. There are two common ways to generate the base-64 string for the secret. The BIND 9 program rndc-confgen can be used to generate a random key, or the mmencode program, also known as mimencode, can be used to generate a base-64 string from known input. mmencode does not ship with BIND 9 but is available on many systems. See the EXAMPLE section for sample command lines for each. EXAMPLE options { default-server localhost; default-key samplekey; }; server localhost { key samplekey; }; server testserver { key testkey; addresses { localhost port 5353; }; }; key samplekey { algorithm hmac-sha256; secret "6FMfj43Osz4lyb24OIe2iGEz9lf1llJO+lz"; }; key testkey { algorithm hmac-sha256; secret "R3HI8P6BKw9ZwXwN3VZKuQ=="; }; In the above example, rndc will by default use the server at localhost (127.0.0.1) and the key called samplekey. Commands to the localhost server will use the samplekey key, which must also be defined in the server's configuration file with the same name and secret. The key statement indicates that samplekey uses the HMAC-SHA256 algorithm and its secret clause contains the base-64 encoding of the HMAC-SHA256 secret enclosed in double quotes. If rndc -s testserver is used then rndc will connect to server on localhost port 5353 using the key testkey. To generate a random secret with rndc-confgen: rndc-confgen A complete rndc.conf file, including the randomly generated key, will be written to the standard output. Commented-out and statements for named.conf are also printed. To generate a base-64 secret with mmencode: echo "known plaintext for a secret" | mmencode NAME SERVER CONFIGURATION The name server must be configured to accept rndc connections and to recognize the key specified in the rndc.conf file, using the controls statement in named.conf. See the sections on the statement in the BIND 9 Administrator Reference Manual for details. SEE ALSO rndc8 , rndc-confgen8 , mmencode1 , BIND 9 Administrator Reference Manual. bind9-9.11.3+dfsg/bin/rndc/rndc.conf.html000066400000000000000000000214331325250447100177750ustar00rootroot00000000000000 rndc.conf

Name

rndc.conf — rndc configuration file

Synopsis

rndc.conf

DESCRIPTION

rndc.conf is the configuration file for rndc, the BIND 9 name server control utility. This file has a similar structure and syntax to named.conf. Statements are enclosed in braces and terminated with a semi-colon. Clauses in the statements are also semi-colon terminated. The usual comment styles are supported:

C style: /* */

C++ style: // to end of line

Unix style: # to end of line

rndc.conf is much simpler than named.conf. The file uses three statements: an options statement, a server statement and a key statement.

The options statement contains five clauses. The default-server clause is followed by the name or address of a name server. This host will be used when no name server is given as an argument to rndc. The default-key clause is followed by the name of a key which is identified by a key statement. If no keyid is provided on the rndc command line, and no key clause is found in a matching server statement, this default key will be used to authenticate the server's commands and responses. The default-port clause is followed by the port to connect to on the remote name server. If no port option is provided on the rndc command line, and no port clause is found in a matching server statement, this default port will be used to connect. The default-source-address and default-source-address-v6 clauses which can be used to set the IPv4 and IPv6 source addresses respectively.

After the server keyword, the server statement includes a string which is the hostname or address for a name server. The statement has three possible clauses: key, port and addresses. The key name must match the name of a key statement in the file. The port number specifies the port to connect to. If an addresses clause is supplied these addresses will be used instead of the server name. Each address can take an optional port. If an source-address or source-address-v6 of supplied then these will be used to specify the IPv4 and IPv6 source addresses respectively.

The key statement begins with an identifying string, the name of the key. The statement has two clauses. algorithm identifies the authentication algorithm for rndc to use; currently only HMAC-MD5 (for compatibility), HMAC-SHA1, HMAC-SHA224, HMAC-SHA256 (default), HMAC-SHA384 and HMAC-SHA512 are supported. This is followed by a secret clause which contains the base-64 encoding of the algorithm's authentication key. The base-64 string is enclosed in double quotes.

There are two common ways to generate the base-64 string for the secret. The BIND 9 program rndc-confgen can be used to generate a random key, or the mmencode program, also known as mimencode, can be used to generate a base-64 string from known input. mmencode does not ship with BIND 9 but is available on many systems. See the EXAMPLE section for sample command lines for each.

EXAMPLE

      options {
        default-server  localhost;
        default-key     samplekey;
      };

      server localhost {
        key             samplekey;
      };

      server testserver {
        key		testkey;
        addresses	{ localhost port 5353; };
      };

      key samplekey {
        algorithm       hmac-sha256;
        secret          "6FMfj43Osz4lyb24OIe2iGEz9lf1llJO+lz";
      };

      key testkey {
        algorithm	hmac-sha256;
        secret		"R3HI8P6BKw9ZwXwN3VZKuQ==";
      };
    

In the above example, rndc will by default use the server at localhost (127.0.0.1) and the key called samplekey. Commands to the localhost server will use the samplekey key, which must also be defined in the server's configuration file with the same name and secret. The key statement indicates that samplekey uses the HMAC-SHA256 algorithm and its secret clause contains the base-64 encoding of the HMAC-SHA256 secret enclosed in double quotes.

If rndc -s testserver is used then rndc will connect to server on localhost port 5353 using the key testkey.

To generate a random secret with rndc-confgen:

rndc-confgen

A complete rndc.conf file, including the randomly generated key, will be written to the standard output. Commented-out key and controls statements for named.conf are also printed.

To generate a base-64 secret with mmencode:

echo "known plaintext for a secret" | mmencode

NAME SERVER CONFIGURATION

The name server must be configured to accept rndc connections and to recognize the key specified in the rndc.conf file, using the controls statement in named.conf. See the sections on the controls statement in the BIND 9 Administrator Reference Manual for details.

SEE ALSO

rndc(8) , rndc-confgen(8) , mmencode(1) , BIND 9 Administrator Reference Manual.

bind9-9.11.3+dfsg/bin/rndc/rndc.docbook000066400000000000000000001075511325250447100175330ustar00rootroot00000000000000 2014-08-15 ISC Internet Systems Consortium, Inc. rndc 8 BIND9 rndc name server control utility 2000 2001 2004 2005 2007 2013 2014 2015 2016 2017 2018 Internet Systems Consortium, Inc. ("ISC") rndc command DESCRIPTION rndc controls the operation of a name server. It supersedes the ndc utility that was provided in old BIND releases. If rndc is invoked with no command line options or arguments, it prints a short summary of the supported commands and the available options and their arguments. rndc communicates with the name server over a TCP connection, sending commands authenticated with digital signatures. In the current versions of rndc and named, the only supported authentication algorithms are HMAC-MD5 (for compatibility), HMAC-SHA1, HMAC-SHA224, HMAC-SHA256 (default), HMAC-SHA384 and HMAC-SHA512. They use a shared secret on each end of the connection. This provides TSIG-style authentication for the command request and the name server's response. All commands sent over the channel must be signed by a key_id known to the server. rndc reads a configuration file to determine how to contact the name server and decide what algorithm and key it should use. OPTIONS -b source-address Use source-address as the source address for the connection to the server. Multiple instances are permitted to allow setting of both the IPv4 and IPv6 source addresses. -c config-file Use config-file as the configuration file instead of the default, /etc/rndc.conf. -k key-file Use key-file as the key file instead of the default, /etc/rndc.key. The key in /etc/rndc.key will be used to authenticate commands sent to the server if the config-file does not exist. -s server server is the name or address of the server which matches a server statement in the configuration file for rndc. If no server is supplied on the command line, the host named by the default-server clause in the options statement of the rndc configuration file will be used. -p port Send commands to TCP port port instead of BIND 9's default control channel port, 953. -q Quiet mode: Message text returned by the server will not be printed except when there is an error. -r Instructs rndc to print the result code returned by named after executing the requested command (e.g., ISC_R_SUCCESS, ISC_R_FAILURE, etc). -V Enable verbose logging. -y key_id Use the key key_id from the configuration file. key_id must be known by named with the same algorithm and secret string in order for control message validation to succeed. If no key_id is specified, rndc will first look for a key clause in the server statement of the server being used, or if no server statement is present for that host, then the default-key clause of the options statement. Note that the configuration file contains shared secrets which are used to send authenticated control commands to name servers. It should therefore not have general read or write access. COMMANDS A list of commands supported by rndc can be seen by running rndc without arguments. Currently supported commands are: addzone zone class view configuration Add a zone while the server is running. This command requires the allow-new-zones option to be set to yes. The configuration string specified on the command line is the zone configuration text that would ordinarily be placed in named.conf. The configuration is saved in a file called name.nzf, where name is the name of the view, or if it contains characters that are incompatible with use as a file name, a cryptographic hash generated from the name of the view. When named is restarted, the file will be loaded into the view configuration, so that zones that were added can persist after a restart. This sample addzone command would add the zone example.com to the default view: $ rndc addzone example.com '{ type master; file "example.com.db"; };' (Note the brackets and semi-colon around the zone configuration text.) See also rndc delzone and rndc modzone. delzone -clean zone class view Delete a zone while the server is running. If the argument is specified, the zone's master file (and journal file, if any) will be deleted along with the zone. Without the option, zone files must be cleaned up by hand. (If the zone is of type "slave" or "stub", the files needing to be cleaned up will be reported in the output of the rndc delzone command.) If the zone was originally added via rndc addzone, then it will be removed permanently. However, if it was originally configured in named.conf, then that original configuration is still in place; when the server is restarted or reconfigured, the zone will come back. To remove it permanently, it must also be removed from named.conf See also rndc addzone and rndc modzone. dnstap ( -reopen | -roll number ) Close and re-open DNSTAP output files. rndc dnstap -reopen allows the output file to be renamed externally, so that named can truncate and re-open it. rndc dnstap -roll causes the output file to be rolled automatically, similar to log files; the most recent output file has ".0" appended to its name; the previous most recent output file is moved to ".1", and so on. If number is specified, then the number of backup log files is limited to that number. dumpdb -all|-cache|-zones|-adb|-bad|-fail view ... Dump the server's caches (default) and/or zones to the dump file for the specified views. If no view is specified, all views are dumped. (See the dump-file option in the BIND 9 Administrator Reference Manual.) flush Flushes the server's cache. flushname name view Flushes the given name from the view's DNS cache and, if applicable, from the view's nameserver address database, bad server cache and SERVFAIL cache. flushtree name view Flushes the given name, and all of its subdomains, from the view's DNS cache, address database, bad server cache, and SERVFAIL cache. freeze zone class view Suspend updates to a dynamic zone. If no zone is specified, then all zones are suspended. This allows manual edits to be made to a zone normally updated by dynamic update. It also causes changes in the journal file to be synced into the master file. All dynamic update attempts will be refused while the zone is frozen. See also rndc thaw. halt -p Stop the server immediately. Recent changes made through dynamic update or IXFR are not saved to the master files, but will be rolled forward from the journal files when the server is restarted. If is specified named's process id is returned. This allows an external process to determine when named had completed halting. See also rndc stop. loadkeys zone class view Fetch all DNSSEC keys for the given zone from the key directory. If they are within their publication period, merge them into the zone's DNSKEY RRset. Unlike rndc sign, however, the zone is not immediately re-signed by the new keys, but is allowed to incrementally re-sign over time. This command requires that the auto-dnssec zone option be set to maintain, and also requires the zone to be configured to allow dynamic DNS. (See "Dynamic Update Policies" in the Administrator Reference Manual for more details.) managed-keys (status | refresh | sync) class view When run with the "status" keyword, print the current status of the managed-keys database for the specified view, or for all views if none is specified. When run with the "refresh" keyword, force an immediate refresh of all the managed-keys in the specified view, or all views. When run with the "sync" keyword, force an immediate dump of the managed-keys database to disk (in the file managed-keys.bind or (viewname.mkeys). modzone zone class view configuration Modify the configuration of a zone while the server is running. This command requires the allow-new-zones option to be set to yes. As with addzone, the configuration string specified on the command line is the zone configuration text that would ordinarily be placed in named.conf. If the zone was originally added via rndc addzone, the configuration changes will be recorded permanently and will still be in effect after the server is restarted or reconfigured. However, if it was originally configured in named.conf, then that original configuration is still in place; when the server is restarted or reconfigured, the zone will revert to its original configuration. To make the changes permanent, it must also be modified in named.conf See also rndc addzone and rndc delzone. notify zone class view Resend NOTIFY messages for the zone. notrace Sets the server's debugging level to 0. See also rndc trace. nta ( -d | -f | -r | -l duration) domain view Sets a DNSSEC negative trust anchor (NTA) for , with a lifetime of . The default lifetime is configured in named.conf via the option, and defaults to one hour. The lifetime cannot exceed one week. A negative trust anchor selectively disables DNSSEC validation for zones that are known to be failing because of misconfiguration rather than an attack. When data to be validated is at or below an active NTA (and above any other configured trust anchors), named will abort the DNSSEC validation process and treat the data as insecure rather than bogus. This continues until the NTA's lifetime is elapsed. NTAs persist across restarts of the named server. The NTAs for a view are saved in a file called name.nta, where name is the name of the view, or if it contains characters that are incompatible with use as a file name, a cryptographic hash generated from the name of the view. An existing NTA can be removed by using the option. An NTA's lifetime can be specified with the option. TTL-style suffixes can be used to specify the lifetime in seconds, minutes, or hours. If the specified NTA already exists, its lifetime will be updated to the new value. Setting to zero is equivalent to . If is used, any other arguments are ignored, and a list of existing NTAs is printed (note that this may include NTAs that are expired but have not yet been cleaned up). Normally, named will periodically test to see whether data below an NTA can now be validated (see the option in the Administrator Reference Manual for details). If data can be validated, then the NTA is regarded as no longer necessary, and will be allowed to expire early. The overrides this behavior and forces an NTA to persist for its entire lifetime, regardless of whether data could be validated if the NTA were not present. All of these options can be shortened, i.e., to , , , and . querylog on | off Enable or disable query logging. (For backward compatibility, this command can also be used without an argument to toggle query logging on and off.) Query logging can also be enabled by explicitly directing the queries category to a channel in the logging section of named.conf or by specifying querylog yes; in the options section of named.conf. reconfig Reload the configuration file and load new zones, but do not reload existing zone files even if they have changed. This is faster than a full reload when there is a large number of zones because it avoids the need to examine the modification times of the zones files. recursing Dump the list of queries named is currently recursing on, and the list of domains to which iterative queries are currently being sent. (The second list includes the number of fetches currently active for the given domain, and how many have been passed or dropped because of the option.) refresh zone class view Schedule zone maintenance for the given zone. reload Reload configuration file and zones. reload zone class view Reload the given zone. retransfer zone class view Retransfer the given slave zone from the master server. If the zone is configured to use inline-signing, the signed version of the zone is discarded; after the retransfer of the unsigned version is complete, the signed version will be regenerated with all new signatures. scan Scan the list of available network interfaces for changes, without performing a full reconfig or waiting for the interface-interval timer. secroots - view ... Dump the server's security roots and negative trust anchors for the specified views. If no view is specified, all views are dumped. If the first argument is "-", then the output is returned via the rndc response channel and printed to the standard output. Otherwise, it is written to the secroots dump file, which defaults to named.secroots, but can be overridden via the option in named.conf. See also rndc managed-keys. showzone zone class view Print the configuration of a running zone. See also rndc zonestatus. sign zone class view Fetch all DNSSEC keys for the given zone from the key directory (see the key-directory option in the BIND 9 Administrator Reference Manual). If they are within their publication period, merge them into the zone's DNSKEY RRset. If the DNSKEY RRset is changed, then the zone is automatically re-signed with the new key set. This command requires that the auto-dnssec zone option be set to allow or maintain, and also requires the zone to be configured to allow dynamic DNS. (See "Dynamic Update Policies" in the Administrator Reference Manual for more details.) See also rndc loadkeys. signing ( -list | -clear keyid/algorithm | -clear all | -nsec3param ( parameters | none ) | -serial value ) zone class view List, edit, or remove the DNSSEC signing state records for the specified zone. The status of ongoing DNSSEC operations (such as signing or generating NSEC3 chains) is stored in the zone in the form of DNS resource records of type sig-signing-type. rndc signing -list converts these records into a human-readable form, indicating which keys are currently signing or have finished signing the zone, and which NSEC3 chains are being created or removed. rndc signing -clear can remove a single key (specified in the same format that rndc signing -list uses to display it), or all keys. In either case, only completed keys are removed; any record indicating that a key has not yet finished signing the zone will be retained. rndc signing -nsec3param sets the NSEC3 parameters for a zone. This is the only supported mechanism for using NSEC3 with inline-signing zones. Parameters are specified in the same format as an NSEC3PARAM resource record: hash algorithm, flags, iterations, and salt, in that order. Currently, the only defined value for hash algorithm is 1, representing SHA-1. The may be set to 0 or 1, depending on whether you wish to set the opt-out bit in the NSEC3 chain. defines the number of additional times to apply the algorithm when generating an NSEC3 hash. The is a string of data expressed in hexadecimal, a hyphen (`-') if no salt is to be used, or the keyword auto, which causes named to generate a random 64-bit salt. So, for example, to create an NSEC3 chain using the SHA-1 hash algorithm, no opt-out flag, 10 iterations, and a salt value of "FFFF", use: rndc signing -nsec3param 1 0 10 FFFF zone. To set the opt-out flag, 15 iterations, and no salt, use: rndc signing -nsec3param 1 1 15 - zone. rndc signing -nsec3param none removes an existing NSEC3 chain and replaces it with NSEC. rndc signing -serial value sets the serial number of the zone to value. If the value would cause the serial number to go backwards it will be rejected. The primary use is to set the serial on inline signed zones. stats Write server statistics to the statistics file. (See the statistics-file option in the BIND 9 Administrator Reference Manual.) status Display status of the server. Note that the number of zones includes the internal bind/CH zone and the default ./IN hint zone if there is not an explicit root zone configured. stop -p Stop the server, making sure any recent changes made through dynamic update or IXFR are first saved to the master files of the updated zones. If is specified named's process id is returned. This allows an external process to determine when named had completed stopping. See also rndc halt. sync -clean zone class view Sync changes in the journal file for a dynamic zone to the master file. If the "-clean" option is specified, the journal file is also removed. If no zone is specified, then all zones are synced. thaw zone class view Enable updates to a frozen dynamic zone. If no zone is specified, then all frozen zones are enabled. This causes the server to reload the zone from disk, and re-enables dynamic updates after the load has completed. After a zone is thawed, dynamic updates will no longer be refused. If the zone has changed and the ixfr-from-differences option is in use, then the journal file will be updated to reflect changes in the zone. Otherwise, if the zone has changed, any existing journal file will be removed. See also rndc freeze. trace Increment the servers debugging level by one. trace level Sets the server's debugging level to an explicit value. See also rndc notrace. tsig-delete keyname view Delete a given TKEY-negotiated key from the server. (This does not apply to statically configured TSIG keys.) tsig-list List the names of all TSIG keys currently configured for use by named in each view. The list both statically configured keys and dynamic TKEY-negotiated keys. validation ( on | off | status ) view ... Enable, disable, or check the current status of DNSSEC validation. Note dnssec-enable also needs to be set to yes or auto to be effective. It defaults to enabled. zonestatus zone class view Displays the current status of the given zone, including the master file name and any include files from which it was loaded, when it was most recently loaded, the current serial number, the number of nodes, whether the zone supports dynamic updates, whether the zone is DNSSEC signed, whether it uses automatic DNSSEC key management or inline signing, and the scheduled refresh or expiry times for the zone. See also rndc showzone. LIMITATIONS There is currently no way to provide the shared secret for a without using the configuration file. Several error messages could be clearer. SEE ALSO rndc.conf5 , rndc-confgen8 , named8 , named.conf5 , ndc8 , BIND 9 Administrator Reference Manual. bind9-9.11.3+dfsg/bin/rndc/rndc.html000066400000000000000000001147661325250447100170650ustar00rootroot00000000000000 rndc

Name

rndc — name server control utility

Synopsis

rndc [-b source-address] [-c config-file] [-k key-file] [-s server] [-p port] [-q] [-r] [-V] [-y key_id] {command}

DESCRIPTION

rndc controls the operation of a name server. It supersedes the ndc utility that was provided in old BIND releases. If rndc is invoked with no command line options or arguments, it prints a short summary of the supported commands and the available options and their arguments.

rndc communicates with the name server over a TCP connection, sending commands authenticated with digital signatures. In the current versions of rndc and named, the only supported authentication algorithms are HMAC-MD5 (for compatibility), HMAC-SHA1, HMAC-SHA224, HMAC-SHA256 (default), HMAC-SHA384 and HMAC-SHA512. They use a shared secret on each end of the connection. This provides TSIG-style authentication for the command request and the name server's response. All commands sent over the channel must be signed by a key_id known to the server.

rndc reads a configuration file to determine how to contact the name server and decide what algorithm and key it should use.

OPTIONS

-b source-address

Use source-address as the source address for the connection to the server. Multiple instances are permitted to allow setting of both the IPv4 and IPv6 source addresses.

-c config-file

Use config-file as the configuration file instead of the default, /etc/rndc.conf.

-k key-file

Use key-file as the key file instead of the default, /etc/rndc.key. The key in /etc/rndc.key will be used to authenticate commands sent to the server if the config-file does not exist.

-s server

server is the name or address of the server which matches a server statement in the configuration file for rndc. If no server is supplied on the command line, the host named by the default-server clause in the options statement of the rndc configuration file will be used.

-p port

Send commands to TCP port port instead of BIND 9's default control channel port, 953.

-q

Quiet mode: Message text returned by the server will not be printed except when there is an error.

-r

Instructs rndc to print the result code returned by named after executing the requested command (e.g., ISC_R_SUCCESS, ISC_R_FAILURE, etc).

-V

Enable verbose logging.

-y key_id

Use the key key_id from the configuration file. key_id must be known by named with the same algorithm and secret string in order for control message validation to succeed. If no key_id is specified, rndc will first look for a key clause in the server statement of the server being used, or if no server statement is present for that host, then the default-key clause of the options statement. Note that the configuration file contains shared secrets which are used to send authenticated control commands to name servers. It should therefore not have general read or write access.

COMMANDS

A list of commands supported by rndc can be seen by running rndc without arguments.

Currently supported commands are:

addzone zone [class [view]] configuration

Add a zone while the server is running. This command requires the allow-new-zones option to be set to yes. The configuration string specified on the command line is the zone configuration text that would ordinarily be placed in named.conf.

The configuration is saved in a file called name.nzf, where name is the name of the view, or if it contains characters that are incompatible with use as a file name, a cryptographic hash generated from the name of the view. When named is restarted, the file will be loaded into the view configuration, so that zones that were added can persist after a restart.

This sample addzone command would add the zone example.com to the default view:

$ rndc addzone example.com '{ type master; file "example.com.db"; };'

(Note the brackets and semi-colon around the zone configuration text.)

See also rndc delzone and rndc modzone.

delzone [-clean] zone [class [view]]

Delete a zone while the server is running.

If the -clean argument is specified, the zone's master file (and journal file, if any) will be deleted along with the zone. Without the -clean option, zone files must be cleaned up by hand. (If the zone is of type "slave" or "stub", the files needing to be cleaned up will be reported in the output of the rndc delzone command.)

If the zone was originally added via rndc addzone, then it will be removed permanently. However, if it was originally configured in named.conf, then that original configuration is still in place; when the server is restarted or reconfigured, the zone will come back. To remove it permanently, it must also be removed from named.conf

See also rndc addzone and rndc modzone.

dnstap ( -reopen | -roll [number] )

Close and re-open DNSTAP output files. rndc dnstap -reopen allows the output file to be renamed externally, so that named can truncate and re-open it. rndc dnstap -roll causes the output file to be rolled automatically, similar to log files; the most recent output file has ".0" appended to its name; the previous most recent output file is moved to ".1", and so on. If number is specified, then the number of backup log files is limited to that number.

dumpdb [-all|-cache|-zones|-adb|-bad|-fail] [view ...]

Dump the server's caches (default) and/or zones to the dump file for the specified views. If no view is specified, all views are dumped. (See the dump-file option in the BIND 9 Administrator Reference Manual.)

flush

Flushes the server's cache.

flushname name [view]

Flushes the given name from the view's DNS cache and, if applicable, from the view's nameserver address database, bad server cache and SERVFAIL cache.

flushtree name [view]

Flushes the given name, and all of its subdomains, from the view's DNS cache, address database, bad server cache, and SERVFAIL cache.

freeze [zone [class [view]]]

Suspend updates to a dynamic zone. If no zone is specified, then all zones are suspended. This allows manual edits to be made to a zone normally updated by dynamic update. It also causes changes in the journal file to be synced into the master file. All dynamic update attempts will be refused while the zone is frozen.

See also rndc thaw.

halt [-p]

Stop the server immediately. Recent changes made through dynamic update or IXFR are not saved to the master files, but will be rolled forward from the journal files when the server is restarted. If -p is specified named's process id is returned. This allows an external process to determine when named had completed halting.

See also rndc stop.

loadkeys zone [class [view]]

Fetch all DNSSEC keys for the given zone from the key directory. If they are within their publication period, merge them into the zone's DNSKEY RRset. Unlike rndc sign, however, the zone is not immediately re-signed by the new keys, but is allowed to incrementally re-sign over time.

This command requires that the auto-dnssec zone option be set to maintain, and also requires the zone to be configured to allow dynamic DNS. (See "Dynamic Update Policies" in the Administrator Reference Manual for more details.)

managed-keys (status | refresh | sync) [class [view]]

When run with the "status" keyword, print the current status of the managed-keys database for the specified view, or for all views if none is specified. When run with the "refresh" keyword, force an immediate refresh of all the managed-keys in the specified view, or all views. When run with the "sync" keyword, force an immediate dump of the managed-keys database to disk (in the file managed-keys.bind or (viewname.mkeys).

modzone zone [class [view]] configuration

Modify the configuration of a zone while the server is running. This command requires the allow-new-zones option to be set to yes. As with addzone, the configuration string specified on the command line is the zone configuration text that would ordinarily be placed in named.conf.

If the zone was originally added via rndc addzone, the configuration changes will be recorded permanently and will still be in effect after the server is restarted or reconfigured. However, if it was originally configured in named.conf, then that original configuration is still in place; when the server is restarted or reconfigured, the zone will revert to its original configuration. To make the changes permanent, it must also be modified in named.conf

See also rndc addzone and rndc delzone.

notify zone [class [view]]

Resend NOTIFY messages for the zone.

notrace

Sets the server's debugging level to 0.

See also rndc trace.

nta [( -d | -f | -r | -l duration)] domain [view]

Sets a DNSSEC negative trust anchor (NTA) for domain, with a lifetime of duration. The default lifetime is configured in named.conf via the nta-lifetime option, and defaults to one hour. The lifetime cannot exceed one week.

A negative trust anchor selectively disables DNSSEC validation for zones that are known to be failing because of misconfiguration rather than an attack. When data to be validated is at or below an active NTA (and above any other configured trust anchors), named will abort the DNSSEC validation process and treat the data as insecure rather than bogus. This continues until the NTA's lifetime is elapsed.

NTAs persist across restarts of the named server. The NTAs for a view are saved in a file called name.nta, where name is the name of the view, or if it contains characters that are incompatible with use as a file name, a cryptographic hash generated from the name of the view.

An existing NTA can be removed by using the -remove option.

An NTA's lifetime can be specified with the -lifetime option. TTL-style suffixes can be used to specify the lifetime in seconds, minutes, or hours. If the specified NTA already exists, its lifetime will be updated to the new value. Setting lifetime to zero is equivalent to -remove.

If -dump is used, any other arguments are ignored, and a list of existing NTAs is printed (note that this may include NTAs that are expired but have not yet been cleaned up).

Normally, named will periodically test to see whether data below an NTA can now be validated (see the nta-recheck option in the Administrator Reference Manual for details). If data can be validated, then the NTA is regarded as no longer necessary, and will be allowed to expire early. The -force overrides this behavior and forces an NTA to persist for its entire lifetime, regardless of whether data could be validated if the NTA were not present.

All of these options can be shortened, i.e., to -l, -r, -d, and -f.

querylog [ on | off ]

Enable or disable query logging. (For backward compatibility, this command can also be used without an argument to toggle query logging on and off.)

Query logging can also be enabled by explicitly directing the queries category to a channel in the logging section of named.conf or by specifying querylog yes; in the options section of named.conf.

reconfig

Reload the configuration file and load new zones, but do not reload existing zone files even if they have changed. This is faster than a full reload when there is a large number of zones because it avoids the need to examine the modification times of the zones files.

recursing

Dump the list of queries named is currently recursing on, and the list of domains to which iterative queries are currently being sent. (The second list includes the number of fetches currently active for the given domain, and how many have been passed or dropped because of the fetches-per-zone option.)

refresh zone [class [view]]

Schedule zone maintenance for the given zone.

reload

Reload configuration file and zones.

reload zone [class [view]]

Reload the given zone.

retransfer zone [class [view]]

Retransfer the given slave zone from the master server.

If the zone is configured to use inline-signing, the signed version of the zone is discarded; after the retransfer of the unsigned version is complete, the signed version will be regenerated with all new signatures.

scan

Scan the list of available network interfaces for changes, without performing a full reconfig or waiting for the interface-interval timer.

secroots [-] [view ...]

Dump the server's security roots and negative trust anchors for the specified views. If no view is specified, all views are dumped.

If the first argument is "-", then the output is returned via the rndc response channel and printed to the standard output. Otherwise, it is written to the secroots dump file, which defaults to named.secroots, but can be overridden via the secroots-file option in named.conf.

See also rndc managed-keys.

showzone zone [class [view]]

Print the configuration of a running zone.

See also rndc zonestatus.

sign zone [class [view]]

Fetch all DNSSEC keys for the given zone from the key directory (see the key-directory option in the BIND 9 Administrator Reference Manual). If they are within their publication period, merge them into the zone's DNSKEY RRset. If the DNSKEY RRset is changed, then the zone is automatically re-signed with the new key set.

This command requires that the auto-dnssec zone option be set to allow or maintain, and also requires the zone to be configured to allow dynamic DNS. (See "Dynamic Update Policies" in the Administrator Reference Manual for more details.)

See also rndc loadkeys.

signing [( -list | -clear keyid/algorithm | -clear all | -nsec3param ( parameters | none ) | -serial value ) ] zone [class [view]]

List, edit, or remove the DNSSEC signing state records for the specified zone. The status of ongoing DNSSEC operations (such as signing or generating NSEC3 chains) is stored in the zone in the form of DNS resource records of type sig-signing-type. rndc signing -list converts these records into a human-readable form, indicating which keys are currently signing or have finished signing the zone, and which NSEC3 chains are being created or removed.

rndc signing -clear can remove a single key (specified in the same format that rndc signing -list uses to display it), or all keys. In either case, only completed keys are removed; any record indicating that a key has not yet finished signing the zone will be retained.

rndc signing -nsec3param sets the NSEC3 parameters for a zone. This is the only supported mechanism for using NSEC3 with inline-signing zones. Parameters are specified in the same format as an NSEC3PARAM resource record: hash algorithm, flags, iterations, and salt, in that order.

Currently, the only defined value for hash algorithm is 1, representing SHA-1. The flags may be set to 0 or 1, depending on whether you wish to set the opt-out bit in the NSEC3 chain. iterations defines the number of additional times to apply the algorithm when generating an NSEC3 hash. The salt is a string of data expressed in hexadecimal, a hyphen (`-') if no salt is to be used, or the keyword auto, which causes named to generate a random 64-bit salt.

So, for example, to create an NSEC3 chain using the SHA-1 hash algorithm, no opt-out flag, 10 iterations, and a salt value of "FFFF", use: rndc signing -nsec3param 1 0 10 FFFF zone. To set the opt-out flag, 15 iterations, and no salt, use: rndc signing -nsec3param 1 1 15 - zone.

rndc signing -nsec3param none removes an existing NSEC3 chain and replaces it with NSEC.

rndc signing -serial value sets the serial number of the zone to value. If the value would cause the serial number to go backwards it will be rejected. The primary use is to set the serial on inline signed zones.

stats

Write server statistics to the statistics file. (See the statistics-file option in the BIND 9 Administrator Reference Manual.)

status

Display status of the server. Note that the number of zones includes the internal bind/CH zone and the default ./IN hint zone if there is not an explicit root zone configured.

stop [-p]

Stop the server, making sure any recent changes made through dynamic update or IXFR are first saved to the master files of the updated zones. If -p is specified named's process id is returned. This allows an external process to determine when named had completed stopping.

See also rndc halt.

sync [-clean] [zone [class [view]]]

Sync changes in the journal file for a dynamic zone to the master file. If the "-clean" option is specified, the journal file is also removed. If no zone is specified, then all zones are synced.

thaw [zone [class [view]]]

Enable updates to a frozen dynamic zone. If no zone is specified, then all frozen zones are enabled. This causes the server to reload the zone from disk, and re-enables dynamic updates after the load has completed. After a zone is thawed, dynamic updates will no longer be refused. If the zone has changed and the ixfr-from-differences option is in use, then the journal file will be updated to reflect changes in the zone. Otherwise, if the zone has changed, any existing journal file will be removed.

See also rndc freeze.

trace

Increment the servers debugging level by one.

trace level

Sets the server's debugging level to an explicit value.

See also rndc notrace.

tsig-delete keyname [view]

Delete a given TKEY-negotiated key from the server. (This does not apply to statically configured TSIG keys.)

tsig-list

List the names of all TSIG keys currently configured for use by named in each view. The list both statically configured keys and dynamic TKEY-negotiated keys.

validation ( on | off | status ) [view ...]

Enable, disable, or check the current status of DNSSEC validation. Note dnssec-enable also needs to be set to yes or auto to be effective. It defaults to enabled.

zonestatus zone [class [view]]

Displays the current status of the given zone, including the master file name and any include files from which it was loaded, when it was most recently loaded, the current serial number, the number of nodes, whether the zone supports dynamic updates, whether the zone is DNSSEC signed, whether it uses automatic DNSSEC key management or inline signing, and the scheduled refresh or expiry times for the zone.

See also rndc showzone.

LIMITATIONS

There is currently no way to provide the shared secret for a key_id without using the configuration file.

Several error messages could be clearer.

SEE ALSO

rndc.conf(5) , rndc-confgen(8) , named(8) , named.conf(5) , ndc(8) , BIND 9 Administrator Reference Manual.

bind9-9.11.3+dfsg/bin/rndc/util.c000066400000000000000000000016671325250447100163650ustar00rootroot00000000000000/* * Copyright (C) 2000, 2001, 2004, 2005, 2007, 2015, 2016 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* $Id: util.c,v 1.7 2007/06/19 23:46:59 tbox Exp $ */ /*! \file */ #include #include #include #include #include #include #include "util.h" extern isc_boolean_t verbose; extern const char *progname; void notify(const char *fmt, ...) { va_list ap; if (verbose) { va_start(ap, fmt); vfprintf(stderr, fmt, ap); va_end(ap); fputs("\n", stderr); } } void fatal(const char *format, ...) { va_list args; fprintf(stderr, "%s: ", progname); va_start(args, format); vfprintf(stderr, format, args); va_end(args); fprintf(stderr, "\n"); exit(1); } bind9-9.11.3+dfsg/bin/rndc/util.h000066400000000000000000000017271325250447100163670ustar00rootroot00000000000000/* * Copyright (C) 2000, 2001, 2004, 2005, 2007, 2009, 2016 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* $Id: util.h,v 1.12 2009/09/29 23:48:03 tbox Exp $ */ #ifndef RNDC_UTIL_H #define RNDC_UTIL_H 1 /*! \file */ #include #include #include #define NS_CONTROL_PORT 953 #undef DO #define DO(name, function) \ do { \ result = function; \ if (result != ISC_R_SUCCESS) \ fatal("%s: %s", name, isc_result_totext(result)); \ else \ notify("%s", name); \ } while (0) ISC_LANG_BEGINDECLS void notify(const char *fmt, ...) ISC_FORMAT_PRINTF(1, 2); ISC_PLATFORM_NORETURN_PRE void fatal(const char *format, ...) ISC_FORMAT_PRINTF(1, 2) ISC_PLATFORM_NORETURN_POST; ISC_LANG_ENDDECLS #endif /* RNDC_UTIL_H */ bind9-9.11.3+dfsg/bin/rndc/win32/000077500000000000000000000000001325250447100161745ustar00rootroot00000000000000bind9-9.11.3+dfsg/bin/rndc/win32/rndc.dsp.in000066400000000000000000000115741325250447100202470ustar00rootroot00000000000000# Microsoft Developer Studio Project File - Name="rndc" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "@PLATFORM@ (x86) Console Application" 0x0103 CFG=rndc - @PLATFORM@ Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "rndc.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "rndc.mak" CFG="rndc - @PLATFORM@ Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "rndc - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE "rndc - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "rndc - @PLATFORM@ Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 @COPTX@ @COPTI@ /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c # ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" @LIBXML2_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isccc/include" /I "../../../lib/isccfg/include" /I "../../../lib/bind9/include" /I "../../../lib/dns/include" /D "WIN32" /D "NDEBUG" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console @MACHINE@ # ADD LINK32 user32.lib advapi32.lib ws2_32.lib Release/util.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib ../../../lib/isccfg/win32/Release/libisccfg.lib ../../../lib/isccc/win32/Release/libisccc.lib ../../../lib/bind9/win32/Release/libbind9.lib /nologo /subsystem:console /profile @MACHINE@ /out:"../../../Build/Release/rndc.exe" !ELSEIF "$(CFG)" == "rndc - @PLATFORM@ Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /GZ /c # ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" @LIBXML2_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isccc/include" /I "../../../lib/isccfg/include" /I "../../../lib/bind9/include" /I "../../../lib/dns/include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c # SUBTRACT CPP /X @COPTY@ # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug @MACHINE@ /pdbtype:sept # ADD LINK32 user32.lib advapi32.lib ws2_32.lib Debug/util.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib ../../../lib/isccfg/win32/Debug/libisccfg.lib ../../../lib/isccc/win32/Debug/libisccc.lib ../../../lib/bind9/win32/Debug/libbind9.lib /nologo /subsystem:console /debug @MACHINE@ /out:"../../../Build/Debug/rndc.exe" /pdbtype:sept !ENDIF # Begin Target # Name "rndc - @PLATFORM@ Release" # Name "rndc - @PLATFORM@ Debug" # Begin Group "Source Files" # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" # Begin Source File SOURCE=..\rndc.c # End Source File # End Group # Begin Group "Header Files" # PROP Default_Filter "h;hpp;hxx;hm;inl" # Begin Source File SOURCE=..\util.h # End Source File # End Group # Begin Group "Resource Files" # PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" # End Group # End Target # End Project bind9-9.11.3+dfsg/bin/rndc/win32/rndc.dsw000066400000000000000000000010251325250447100176370ustar00rootroot00000000000000Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "rndc"=".\rndc.dsp" - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### bind9-9.11.3+dfsg/bin/rndc/win32/rndc.mak.in000066400000000000000000000310321325250447100202200ustar00rootroot00000000000000# Microsoft Developer Studio Generated NMAKE File, Based on rndc.dsp !IF "$(CFG)" == "" CFG=rndc - @PLATFORM@ Debug !MESSAGE No configuration specified. Defaulting to rndc - @PLATFORM@ Debug. !ENDIF !IF "$(CFG)" != "rndc - @PLATFORM@ Release" && "$(CFG)" != "rndc - @PLATFORM@ Debug" !MESSAGE Invalid configuration "$(CFG)" specified. !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "rndc.mak" CFG="rndc - @PLATFORM@ Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "rndc - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE "rndc - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE !ERROR An invalid configuration is specified. !ENDIF !IF "$(OS)" == "Windows_NT" NULL= !ELSE NULL=nul !ENDIF CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "rndc - @PLATFORM@ Release" _VC_MANIFEST_INC=0 _VC_MANIFEST_BASENAME=__VC80 !ELSE _VC_MANIFEST_INC=1 _VC_MANIFEST_BASENAME=__VC80.Debug !ENDIF #################################################### # Specifying name of temporary resource file used only in incremental builds: !if "$(_VC_MANIFEST_INC)" == "1" _VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res !else _VC_MANIFEST_AUTO_RES= !endif #################################################### # _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE: !if "$(_VC_MANIFEST_INC)" == "1" #MT_SPECIAL_RETURN=1090650113 #MT_SPECIAL_SWITCH=-notify_resource_update MT_SPECIAL_RETURN=0 MT_SPECIAL_SWITCH= _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \ if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \ rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \ link $** /out:$@ $(LFLAGS) !else _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1 !endif #################################################### # _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL: !if "$(_VC_MANIFEST_INC)" == "1" #MT_SPECIAL_RETURN=1090650113 #MT_SPECIAL_SWITCH=-notify_resource_update MT_SPECIAL_RETURN=0 MT_SPECIAL_SWITCH= _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \ if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \ rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \ link $** /out:$@ $(LFLAGS) !else _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2 !endif #################################################### # _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily: !if "$(_VC_MANIFEST_INC)" == "1" _VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \ $(_VC_MANIFEST_BASENAME).auto.rc \ $(_VC_MANIFEST_BASENAME).auto.manifest !else _VC_MANIFEST_CLEAN= !endif !IF "$(CFG)" == "rndc - @PLATFORM@ Release" OUTDIR=.\Release INTDIR=.\Release !IF "$(RECURSE)" == "0" ALL : "..\..\..\Build\Release\rndc.exe" !ELSE ALL : "libbind9 - @PLATFORM@ Release" "libisccfg - @PLATFORM@ Release" "libisccc - @PLATFORM@ Release" "libisc - @PLATFORM@ Release" "..\..\..\Build\Release\rndc.exe" !ENDIF !IF "$(RECURSE)" == "1" CLEAN :"libisc - @PLATFORM@ ReleaseCLEAN" "libisccc - @PLATFORM@ ReleaseCLEAN" "libisccfg - @PLATFORM@ ReleaseCLEAN" "libbind9 - @PLATFORM@ ReleaseCLEAN" !ELSE CLEAN : !ENDIF -@erase "$(INTDIR)\rndc.obj" -@erase "$(INTDIR)\util.obj" -@erase "$(INTDIR)\vc60.idb" -@erase "..\..\..\Build\Release\rndc.exe" -@$(_VC_MANIFEST_CLEAN) "$(OUTDIR)" : if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" CPP_PROJ=/nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" @LIBXML2_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isccc/include" /I "../../../lib/isccfg/include" /I "../../../lib/bind9/include" /I "../../../lib/dns/include" /D "WIN32" /D "NDEBUG" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\rndc.pch" @COPTY@ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c BSC32=bscmake.exe BSC32_FLAGS=/nologo /o"$(OUTDIR)\rndc.bsc" BSC32_SBRS= \ LINK32=link.exe LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib ../../../lib/isccfg/win32/Release/libisccfg.lib ../../../lib/isccc/win32/Release/libisccc.lib ../../../lib/bind9/win32/Release/libbind9.lib /nologo /subsystem:console /profile @MACHINE@ /out:"../../../Build/Release/rndc.exe" LINK32_OBJS= \ "$(INTDIR)\rndc.obj" \ "$(INTDIR)\util.obj" \ "..\..\..\lib\isc\win32\Release\libisc.lib" \ "..\..\..\lib\isccc\win32\Release\libisccc.lib" \ "..\..\..\lib\isccfg\win32\Release\libisccfg.lib" \ "..\..\..\lib\bind9\win32\Release\libbind9.lib" "..\..\..\Build\Release\rndc.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) $(LINK32) @<< $(LINK32_FLAGS) $(LINK32_OBJS) << $(_VC_MANIFEST_EMBED_EXE) !ELSEIF "$(CFG)" == "rndc - @PLATFORM@ Debug" OUTDIR=.\Debug INTDIR=.\Debug # Begin Custom Macros OutDir=.\Debug # End Custom Macros !IF "$(RECURSE)" == "0" ALL : "..\..\..\Build\Debug\rndc.exe" "$(OUTDIR)\rndc.bsc" !ELSE ALL : "libbind9 - @PLATFORM@ Debug" "libisccfg - @PLATFORM@ Debug" "libisccc - @PLATFORM@ Debug" "libisc - @PLATFORM@ Debug" "..\..\..\Build\Debug\rndc.exe" "$(OUTDIR)\rndc.bsc" !ENDIF !IF "$(RECURSE)" == "1" CLEAN :"libisc - @PLATFORM@ DebugCLEAN" "libisccc - @PLATFORM@ DebugCLEAN" "libisccfg - @PLATFORM@ DebugCLEAN" "libbind9 - @PLATFORM@ DebugCLEAN" !ELSE CLEAN : !ENDIF -@erase "$(INTDIR)\rndc.obj" -@erase "$(INTDIR)\rndc.sbr" -@erase "$(INTDIR)\util.obj" -@erase "$(INTDIR)\util.sbr" -@erase "$(INTDIR)\vc60.idb" -@erase "$(INTDIR)\vc60.pdb" -@erase "$(OUTDIR)\rndc.bsc" -@erase "$(OUTDIR)\rndc.pdb" -@erase "..\..\..\Build\Debug\rndc.exe" -@erase "..\..\..\Build\Debug\rndc.ilk" -@$(_VC_MANIFEST_CLEAN) "$(OUTDIR)" : if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" CPP_PROJ=/nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" @LIBXML2_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isccc/include" /I "../../../lib/isccfg/include" /I "../../../lib/bind9/include" /I "../../../lib/dns/include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c BSC32=bscmake.exe BSC32_FLAGS=/nologo /o"$(OUTDIR)\rndc.bsc" BSC32_SBRS= \ "$(INTDIR)\rndc.sbr" \ "$(INTDIR)\util.sbr" "$(OUTDIR)\rndc.bsc" : "$(OUTDIR)" $(BSC32_SBRS) $(BSC32) @<< $(BSC32_FLAGS) $(BSC32_SBRS) << LINK32=link.exe LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib ../../../lib/isccfg/win32/Debug/libisccfg.lib ../../../lib/isccc/win32/Debug/libisccc.lib ../../../lib/bind9/win32/Debug/libbind9.lib /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\rndc.pdb" /debug @MACHINE@ /out:"../../../Build/Debug/rndc.exe" /pdbtype:sept LINK32_OBJS= \ "$(INTDIR)\rndc.obj" \ "$(INTDIR)\util.obj" \ "..\..\..\lib\isc\win32\Debug\libisc.lib" \ "..\..\..\lib\isccc\win32\Debug\libisccc.lib" \ "..\..\..\lib\isccfg\win32\Debug\libisccfg.lib" \ "..\..\..\lib\bind9\win32\Debug\libbind9.lib" "..\..\..\Build\Debug\rndc.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) $(LINK32) @<< $(LINK32_FLAGS) $(LINK32_OBJS) << $(_VC_MANIFEST_EMBED_EXE) !ENDIF .c{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .c{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << !IF "$(NO_EXTERNAL_DEPS)" != "1" !IF EXISTS("rndc.dep") !INCLUDE "rndc.dep" !ELSE !MESSAGE Warning: cannot find "rndc.dep" !ENDIF !ENDIF !IF "$(CFG)" == "rndc - @PLATFORM@ Release" || "$(CFG)" == "rndc - @PLATFORM@ Debug" SOURCE=..\rndc.c !IF "$(CFG)" == "rndc - @PLATFORM@ Release" "$(INTDIR)\rndc.obj" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ELSEIF "$(CFG)" == "rndc - @PLATFORM@ Debug" "$(INTDIR)\rndc.obj" "$(INTDIR)\rndc.sbr" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ENDIF SOURCE=..\util.c !IF "$(CFG)" == "rndc - @PLATFORM@ Release" "$(INTDIR)\util.obj" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ELSEIF "$(CFG)" == "rndc - @PLATFORM@ Debug" "$(INTDIR)\util.obj" "$(INTDIR)\util.sbr" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ENDIF !IF "$(CFG)" == "rndc - @PLATFORM@ Release" "libisc - @PLATFORM@ Release" : cd "..\..\..\lib\isc\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Release" cd "..\..\..\bin\rndc\win32" "libisc - @PLATFORM@ ReleaseCLEAN" : cd "..\..\..\lib\isc\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Release" RECURSE=1 CLEAN cd "..\..\..\bin\rndc\win32" !ELSEIF "$(CFG)" == "rndc - @PLATFORM@ Debug" "libisc - @PLATFORM@ Debug" : cd "..\..\..\lib\isc\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Debug" cd "..\..\..\bin\rndc\win32" "libisc - @PLATFORM@ DebugCLEAN" : cd "..\..\..\lib\isc\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Debug" RECURSE=1 CLEAN cd "..\..\..\bin\rndc\win32" !ENDIF !IF "$(CFG)" == "rndc - @PLATFORM@ Release" "libisccc - @PLATFORM@ Release" : cd "..\..\..\lib\isccc\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libisccc.mak" CFG="libisccc - @PLATFORM@ Release" cd "..\..\..\bin\rndc\win32" "libisccc - @PLATFORM@ ReleaseCLEAN" : cd "..\..\..\lib\isccc\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libisccc.mak" CFG="libisccc - @PLATFORM@ Release" RECURSE=1 CLEAN cd "..\..\..\bin\rndc\win32" !ELSEIF "$(CFG)" == "rndc - @PLATFORM@ Debug" "libisccc - @PLATFORM@ Debug" : cd "..\..\..\lib\isccc\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libisccc.mak" CFG="libisccc - @PLATFORM@ Debug" cd "..\..\..\bin\rndc\win32" "libisccc - @PLATFORM@ DebugCLEAN" : cd "..\..\..\lib\isccc\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libisccc.mak" CFG="libisccc - @PLATFORM@ Debug" RECURSE=1 CLEAN cd "..\..\..\bin\rndc\win32" !ENDIF !IF "$(CFG)" == "rndc - @PLATFORM@ Release" "libisccfg - @PLATFORM@ Release" : cd "..\..\..\lib\isccfg\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libisccfg.mak" CFG="libisccfg - @PLATFORM@ Release" cd "..\..\..\bin\rndc\win32" "libisccfg - @PLATFORM@ ReleaseCLEAN" : cd "..\..\..\lib\isccfg\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libisccfg.mak" CFG="libisccfg - @PLATFORM@ Release" RECURSE=1 CLEAN cd "..\..\..\bin\rndc\win32" !ELSEIF "$(CFG)" == "rndc - @PLATFORM@ Debug" "libisccfg - @PLATFORM@ Debug" : cd "..\..\..\lib\isccfg\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libisccfg.mak" CFG="libisccfg - @PLATFORM@ Debug" cd "..\..\..\bin\rndc\win32" "libisccfg - @PLATFORM@ DebugCLEAN" : cd "..\..\..\lib\isccfg\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libisccfg.mak" CFG="libisccfg - @PLATFORM@ Debug" RECURSE=1 CLEAN cd "..\..\..\bin\rndc\win32" !ENDIF !IF "$(CFG)" == "rndc - @PLATFORM@ Release" "libbind9 - @PLATFORM@ Release" : cd "..\..\..\lib\bind9\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - @PLATFORM@ Release" cd "..\..\..\bin\rndc\win32" "libbind9 - @PLATFORM@ ReleaseCLEAN" : cd "..\..\..\lib\bind9\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - @PLATFORM@ Release" RECURSE=1 CLEAN cd "..\..\..\bin\rndc\win32" !ELSEIF "$(CFG)" == "rndc - @PLATFORM@ Debug" "libbind9 - @PLATFORM@ Debug" : cd "..\..\..\lib\bind9\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - @PLATFORM@ Debug" cd "..\..\..\bin\rndc\win32" "libbind9 - @PLATFORM@ DebugCLEAN" : cd "..\..\..\lib\bind9\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - @PLATFORM@ Debug" RECURSE=1 CLEAN cd "..\..\..\bin\rndc\win32" !ENDIF !ENDIF #################################################### # Commands to generate initial empty manifest file and the RC file # that references it, and for generating the .res file: $(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc $(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest type <<$@ #include 1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest" << KEEP $(_VC_MANIFEST_BASENAME).auto.manifest : type <<$@ << KEEP bind9-9.11.3+dfsg/bin/rndc/win32/rndc.vcxproj.filters.in000066400000000000000000000020651325250447100226160ustar00rootroot00000000000000 {4FC737F1-C7A5-4376-A066-2A32D752A2FF} cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx {93995380-89BD-4b04-88EB-625FBE52EBFB} h;hpp;hxx;hm;inl;inc;xsd {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms Header Files Source Files bind9-9.11.3+dfsg/bin/rndc/win32/rndc.vcxproj.in000066400000000000000000000157311325250447100211530ustar00rootroot00000000000000 Debug @PLATFORM@ Release @PLATFORM@ {39721F26-8B80-4AA9-9826-2AEF7322C3D5} Win32Proj rndc Application true MultiByte Application false true MultiByte true ..\..\..\Build\$(Configuration)\ .\$(Configuration)\ false ..\..\..\Build\$(Configuration)\ .\$(Configuration)\ Level3 Disabled WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true .\$(Configuration)\$(TargetName).pch .\$(Configuration)\ .\$(Configuration)\ $(OutDir)$(TargetName).pdb true .\;..\..\..\;@LIBXML2_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\isccc\include;..\..\..\lib\isccfg\include;..\..\..\lib\bind9\include;..\..\..\lib\dns\include;%(AdditionalIncludeDirectories) CompileAsC Console true ..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt) $(Configuration);..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);..\..\..\lib\isccfg\win32\$(Configuration);..\..\..\lib\isccc\win32\$(Configuration);..\..\..\lib\bind9\win32\$(Configuration);%(AdditionalLibraryDirectories) util.lib;libisc.lib;libdns.lib;libisccfg.lib;libisccc.lib;libbind9.lib;ws2_32.lib;%(AdditionalDependencies) Level3 MaxSpeed true @INTRINSIC@ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) OnlyExplicitInline false true .\$(Configuration)\$(TargetName).pch .\$(Configuration)\ .\$(Configuration)\ $(OutDir)$(TargetName).pdb .\;..\..\..\;@LIBXML2_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\isccc\include;..\..\..\lib\isccfg\include;..\..\..\lib\bind9\include;..\..\..\lib\dns\include;%(AdditionalIncludeDirectories) CompileAsC Console false true true ..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt) Default $(Configuration);..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);..\..\..\lib\isccfg\win32\$(Configuration);..\..\..\lib\isccc\win32\$(Configuration);..\..\..\lib\bind9\win32\$(Configuration);%(AdditionalLibraryDirectories) util.lib;libisc.lib;libdns.lib;libisccfg.lib;libisccc.lib;libbind9.lib;ws2_32.lib;%(AdditionalDependencies) bind9-9.11.3+dfsg/bin/rndc/win32/rndc.vcxproj.user000066400000000000000000000002171325250447100215140ustar00rootroot00000000000000 bind9-9.11.3+dfsg/bin/rndc/win32/rndcutil.dsp.in000066400000000000000000000075631325250447100211500ustar00rootroot00000000000000# Microsoft Developer Studio Project File - Name="rndcutil" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "@PLATFORM@ (x86) Static-Link Library" 0x0104 CFG=rndcutil - @PLATFORM@ Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "rndcutil.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "rndcutil.mak" CFG="rndcutil - @PLATFORM@ Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "rndcutil - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Static-Link Library") !MESSAGE "rndcutil - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Static-Link Library") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe MTL=midl.exe RSC=rc.exe !IF "$(CFG)" == "rndcutil - @PLATFORM@ Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MT /W3 @COPTX@ @COPTI@ /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" @COPTY@ /FD /c # ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" /I "../include" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "__STDC__" /D "_MBCS" @COPTY@ /FD /c /Fdutil # SUBTRACT CPP /X # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 # ADD LINK32 /out:"Release/util.lib" LIB32=lib.exe # ADD BASE LIB32 # ADD LIB32 /out:"Release/util.lib" !ELSEIF "$(CFG)" == "rndcutil - @PLATFORM@ Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MTd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" @COPTY@ /FD /GZ /c # ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" /I "../include" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "__STDC__" /D "_MBCS" /FR @COPTY@ /FD /GZ /c /Fdutil # SUBTRACT CPP /X # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 # ADD LINK32 /debug /out:"Debug/util.lib" LIB32=lib.exe # ADD BASE LIB32 # ADD LIB32 /out:"Debug/util.lib" !ENDIF # Begin Target # Name "rndcutil - @PLATFORM@ Release" # Name "rndcutil - @PLATFORM@ Debug" # Begin Group "Source Files" # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" # End Group # Begin Group "Header Files" # PROP Default_Filter "h;hpp;hxx;hm;inl" # End Group # Begin Group "Resource Files" # PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" # End Group # Begin Group "Main Dns Lib" # PROP Default_Filter "c" # Begin Source File SOURCE=..\util.c # End Source File # End Group # End Target # End Project bind9-9.11.3+dfsg/bin/rndc/win32/rndcutil.dsw000066400000000000000000000010351325250447100205360ustar00rootroot00000000000000Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "rndcutil"=".\rndcutil.dsp" - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### bind9-9.11.3+dfsg/bin/rndc/win32/rndcutil.vcxproj.filters.in000066400000000000000000000020651325250447100235140ustar00rootroot00000000000000 {4FC737F1-C7A5-4376-A066-2A32D752A2FF} cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx {93995380-89BD-4b04-88EB-625FBE52EBFB} h;hpp;hxx;hm;inl;inc;xsd {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms Header Files Source Files bind9-9.11.3+dfsg/bin/rndc/win32/rndcutil.vcxproj.in000066400000000000000000000127521325250447100220510ustar00rootroot00000000000000 Debug @PLATFORM@ Release @PLATFORM@ {7C8681A1-E3A8-470E-9EEF-16054D111A19} Win32Proj rndcutil StaticLibrary true MultiByte StaticLibrary false true MultiByte true .\$(Configuration)\ .\$(Configuration)\ util false .\$(Configuration)\ .\$(Configuration)\ util Level3 Disabled WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true .\$(Configuration)\$(ProjectName).pch .\$(Configuration)\ .\$(Configuration)\ $(OutDir)$(TargetName).pdb true .\;..\..\..\;..\include;..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;%(AdditionalIncludeDirectories) CompileAsC $(OutDir)$(TargetName)$(TargetExt) Level3 MaxSpeed true @INTRINSIC@ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) OnlyExplicitInline false true .\$(Configuration)\$(ProjectName).pch .\$(Configuration)\ .\$(Configuration)\ $(OutDir)$(TargetName).pdb .\;..\..\..\;..\include;..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;%(AdditionalIncludeDirectories) CompileAsC $(OutDir)$(TargetName)$(TargetExt) bind9-9.11.3+dfsg/bin/rndc/win32/rndcutil.vcxproj.user000066400000000000000000000002171325250447100224120ustar00rootroot00000000000000 bind9-9.11.3+dfsg/bin/tests/000077500000000000000000000000001325250447100154465ustar00rootroot00000000000000bind9-9.11.3+dfsg/bin/tests/Kchild.example.+003+04017.key000066400000000000000000000005001325250447100220260ustar00rootroot00000000000000child.example. IN KEY 256 3 3 ALeiYGFXbil6PgHnkm5ZE67ygEVDvGT/gqZmLH7tGboofcPSfyhh1hpw dxZgJ26d/gynWMGVSYzaXfzsxpPoNeYn+qeevQoJOaxXXlfcy8Ik52Rm eW0J9mWlf9hsD7ShIhh1+0kRYGCOCaU25wIe3SLVkN3HgqiCBDYnBY0u nMkqRadiUnoEa3Tcvc9kJx9r9gDstR2A9A5sBhFLI/XQ0gViHHLVpQ4x hz+rTLb/xrBoAb5sQJT3xUjhhdNo9HuL6kwdLdSu//PCl1QnY9NpYPVV SKUo bind9-9.11.3+dfsg/bin/tests/Kchild.example.+003+04017.private000066400000000000000000000006641325250447100227230ustar00rootroot00000000000000Private-key-format: v1.2 Algorithm: 3 (DSA) Prime(p): vGT/gqZmLH7tGboofcPSfyhh1hpwdxZgJ26d/gynWMGVSYzaXfzsxpPoNeYn+qeevQoJOaxXXlfcy8Ik52RmeQ== Subprime(q): t6JgYVduKXo+AeeSblkTrvKARUM= Base(g): bQn2ZaV/2GwPtKEiGHX7SRFgYI4JpTbnAh7dItWQ3ceCqIIENicFjS6cySpFp2JSegRrdNy9z2QnH2v2AOy1HQ== Private_value(x): J1Ctez8+w1PTR56Hze3pGoe0Wag= Public_value(y): gPQObAYRSyP10NIFYhxy1aUOMYc/q0y2/8awaAG+bECU98VI4YXTaPR7i+pMHS3Urv/zwpdUJ2PTaWD1VUilKA== bind9-9.11.3+dfsg/bin/tests/Makefile.in000066400000000000000000000242621325250447100175210ustar00rootroot00000000000000# Copyright (C) 1998-2017 Internet Systems Consortium, Inc. ("ISC") # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. srcdir = @srcdir@ VPATH = @srcdir@ top_srcdir = @top_srcdir@ @BIND9_MAKE_INCLUDES@ CINCLUDES = ${DNS_INCLUDES} ${ISC_INCLUDES} ${ISCCFG_INCLUDES} \ ${LWRES_INCLUDES} @DST_OPENSSL_INC@ CDEFINES = @CRYPTO@ CWARNINGS = BACKTRACECFLAGS = @BACKTRACECFLAGS@ DNSLIBS = ../../lib/dns/libdns.@A@ @DNS_CRYPTO_LIBS@ ISCLIBS = ../../lib/isc/libisc.@A@ @ISC_OPENSSL_LIBS@ ISCNOSYMLIBS = ../../lib/isc/libisc-nosymtbl.@A@ @ISC_OPENSSL_LIBS@ ISCCFGLIBS = ../../lib/isccfg/libisccfg.@A@ LWRESLIBS = ../../lib/lwres/liblwres.@A@ DNSDEPLIBS = ../../lib/dns/libdns.@A@ ISCDEPLIBS = ../../lib/isc/libisc.@A@ ISCDEPNOSYMLIBS = ../../lib/isc/libisc-nosymtbl.@A@ ISCCFGDEPLIBS = ../../lib/isccfg/libisccfg.@A@ LWRESDEPLIBS = ../../lib/lwres/liblwres.@A@ LIBS = @LIBS@ SUBDIRS = atomic db dst master mem hashes names \ net rbt resolver sockaddr tasks timers system \ @PKCS11_TOOLS@ # Test programs that are built by default: # cfg_test is needed for regenerating doc/misc/options # makejournal is needed by system tests # Alphabetically TARGETS = @XTARGETS@ cfg_test@EXEEXT@ makejournal@EXEEXT@ \ wire_test@EXEEXT@ # All the other tests are optional and not built by default. # Alphabetically XTARGETS = adb_test@EXEEXT@ \ byaddr_test@EXEEXT@ \ backtrace_test@EXEEXT@ \ backtrace_test_nosymtbl@EXEEXT@ \ byname_test@EXEEXT@ \ db_test@EXEEXT@ \ entropy_test@EXEEXT@ \ entropy2_test@EXEEXT@ \ gxba_test@EXEEXT@ \ gxbn_test@EXEEXT@ \ hash_test@EXEEXT@ \ fsaccess_test@EXEEXT@ \ inter_test@EXEEXT@ \ keyboard_test@EXEEXT@ \ lex_test@EXEEXT@ \ lfsr_test@EXEEXT@ \ log_test@EXEEXT@ \ lwres_test@EXEEXT@ \ lwresconf_test@EXEEXT@ \ master_test@EXEEXT@ \ mempool_test@EXEEXT@ \ name_test@EXEEXT@ \ nsecify@EXEEXT@ \ ratelimiter_test@EXEEXT@ \ rbt_test@EXEEXT@ \ rwlock_test@EXEEXT@ \ serial_test@EXEEXT@ \ shutdown_test@EXEEXT@ \ sig0_test@EXEEXT@ \ sock_test@EXEEXT@ \ sym_test@EXEEXT@ \ task_test@EXEEXT@ \ timer_test@EXEEXT@ \ wire_test@EXEEXT@ \ zone_test@EXEEXT@ # Alphabetically SRCS = cfg_test.c makejournal.c wire_test.c ${XSRCS} XSRCS = adb_test.c \ byaddr_test.c \ backtrace_test.c \ byname_test.c \ db_test.c \ entropy_test.c \ entropy2_test.c \ gxba_test.c \ gxbn_test.c \ hash_test.c \ fsaccess_test.c \ inter_test.c \ keyboard_test.c \ lex_test.c \ lfsr_test.c \ log_test.c \ lwres_test.c \ lwresconf_test.c \ master_test.c \ mempool_test.c \ name_test.c \ nsecify.c \ ratelimiter_test.c \ rbt_test.c \ rwlock_test.c \ serial_test.c \ shutdown_test.c \ sig0_test.c \ sock_test.c \ sym_test.c \ task_test.c \ timer_test.c \ wire_test.c \ zone_test.c @BIND9_MAKE_RULES@ # disable optimization for backtrace test to get the expected result BTTEST_CFLAGS = ${BACKTRACECFLAGS} ${EXT_CFLAGS} ${ALL_CPPFLAGS} -g \ ${ALWAYS_WARNINGS} ${STD_CWARNINGS} ${CWARNINGS} all_tests: ${XTARGETS} adb_test@EXEEXT@: adb_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ adb_test.@O@ \ ${DNSLIBS} ${ISCLIBS} ${LIBS} backtrace_test_nosymtbl@EXEEXT@: ${srcdir}/backtrace_test.c ${ISCDEPLIBS} ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${BTTEST_CFLAGS} ${LDFLAGS} -o $@ \ ${srcdir}/backtrace_test.c ${ISCLIBS} ${LIBS} backtrace_test@EXEEXT@: ${srcdir}/backtrace_test.c backtrace_test_nosymtbl@EXEEXT@ #first step: create a first symbol table rm -f symtbl.c if test X${MKSYMTBL_PROGRAM} != X; then \ ${MKSYMTBL_PROGRAM} ${top_srcdir}/util/mksymtbl.pl \ backtrace_test_nosymtbl@EXEEXT@; else \ cp ${top_srcdir}/lib/isc/backtrace-emptytbl.c symtbl.c; fi #second step: build a binary with the first symbol table ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${BTTEST_CFLAGS} ${LDFLAGS} \ -o $@0 ${srcdir}/backtrace_test.c symtbl.c \ ${ISCNOSYMLIBS} ${LIBS} rm -f symtbl.c #third step: create a second symbol table if test X${MKSYMTBL_PROGRAM} != X; then \ ${MKSYMTBL_PROGRAM} ${top_srcdir}/util/mksymtbl.pl $@0; else \ cp ${top_srcdir}/lib/isc/backtrace-emptytbl.c symtbl.c; fi #fourth step: build the final binary rm -f $@0 ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${BTTEST_CFLAGS} ${LDFLAGS} \ -o $@ ${srcdir}/backtrace_test.c symtbl.c ${ISCNOSYMLIBS} ${LIBS} rm -f symtbl.c nsecify@EXEEXT@: nsecify.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ nsecify.@O@ \ ${DNSLIBS} ${ISCLIBS} ${LIBS} byaddr_test@EXEEXT@: byaddr_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ byaddr_test.@O@ \ ${DNSLIBS} ${ISCLIBS} ${LIBS} byname_test@EXEEXT@: byname_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ byname_test.@O@ \ ${DNSLIBS} ${ISCLIBS} ${LIBS} lex_test@EXEEXT@: lex_test.@O@ ${ISCDEPLIBS} ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ lex_test.@O@ \ ${ISCLIBS} ${LIBS} lfsr_test@EXEEXT@: lfsr_test.@O@ ${ISCDEPLIBS} ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ lfsr_test.@O@ \ ${ISCLIBS} ${LIBS} log_test@EXEEXT@: log_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ log_test.@O@ \ ${DNSLIBS} ${ISCLIBS} ${LIBS} name_test@EXEEXT@: name_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ name_test.@O@ \ ${DNSLIBS} ${ISCLIBS} ${LIBS} hash_test@EXEEXT@: hash_test.@O@ ${ISCDEPLIBS} ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ hash_test.@O@ \ ${ISCLIBS} ${LIBS} entropy_test@EXEEXT@: entropy_test.@O@ ${ISCDEPLIBS} ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ entropy_test.@O@ \ ${ISCLIBS} ${LIBS} entropy2_test@EXEEXT@: entropy2_test.@O@ ${ISCDEPLIBS} ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ entropy2_test.@O@ \ ${ISCLIBS} ${LIBS} sock_test@EXEEXT@: sock_test.@O@ ${ISCDEPLIBS} ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ sock_test.@O@ \ ${ISCLIBS} ${LIBS} sym_test@EXEEXT@: sym_test.@O@ ${ISCDEPLIBS} ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ sym_test.@O@ \ ${ISCLIBS} ${LIBS} task_test@EXEEXT@: task_test.@O@ ${ISCDEPLIBS} ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ task_test.@O@ \ ${ISCLIBS} ${LIBS} shutdown_test@EXEEXT@: shutdown_test.@O@ ${ISCDEPLIBS} ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ shutdown_test.@O@ \ ${ISCLIBS} ${LIBS} timer_test@EXEEXT@: timer_test.@O@ ${ISCDEPLIBS} ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ timer_test.@O@ \ ${ISCLIBS} ${LIBS} ratelimiter_test@EXEEXT@: ratelimiter_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ ratelimiter_test.@O@ \ ${DNSLIBS} ${ISCLIBS} ${LIBS} rbt_test@EXEEXT@: rbt_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ rbt_test.@O@ \ ${DNSLIBS} ${ISCLIBS} ${LIBS} rwlock_test@EXEEXT@: rwlock_test.@O@ ${ISCDEPLIBS} ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ rwlock_test.@O@ \ ${ISCLIBS} ${LIBS} wire_test@EXEEXT@: wire_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ wire_test.@O@ \ ${DNSLIBS} ${ISCLIBS} ${LIBS} master_test@EXEEXT@: master_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ master_test.@O@ \ ${DNSLIBS} ${ISCLIBS} ${LIBS} db_test@EXEEXT@: db_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ db_test.@O@ \ ${DNSLIBS} ${ISCLIBS} ${LIBS} mempool_test@EXEEXT@: mempool_test.@O@ ${ISCDEPLIBS} ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ mempool_test.@O@ \ ${ISCLIBS} ${LIBS} serial_test@EXEEXT@: serial_test.@O@ ${ISCDEPLIBS} ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ serial_test.@O@ \ ${ISCLIBS} ${LIBS} zone_test@EXEEXT@: zone_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ zone_test.@O@ \ ${DNSLIBS} ${ISCLIBS} ${LIBS} fsaccess_test@EXEEXT@: fsaccess_test.@O@ ${ISCDEPLIBS} ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ fsaccess_test.@O@ \ ${ISCLIBS} ${LIBS} inter_test@EXEEXT@: inter_test.@O@ ${ISCDEPLIBS} ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ inter_test.@O@ \ ${ISCLIBS} ${LIBS} keyboard_test@EXEEXT@: keyboard_test.@O@ ${ISCDEPLIBS} ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ keyboard_test.@O@ \ ${ISCLIBS} ${LIBS} lwresconf_test@EXEEXT@: lwresconf_test.@O@ ${ISCDEPLIBS} ${LWRESDEPLIBS} ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ lwresconf_test.@O@ \ ${LWRESLIBS} ${ISCLIBS} ${LIBS} lwres_test@EXEEXT@: lwres_test.@O@ ${ISCDEPLIBS} ${LWRESDEPLIBS} ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ lwres_test.@O@ \ ${LWRESLIBS} ${ISCLIBS} ${LIBS} gxbn_test@EXEEXT@: gxbn_test.@O@ ${LWRESDEPLIBS} ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ gxbn_test.@O@ \ ${LWRESLIBS} ${ISCLIBS} ${LIBS} gxba_test@EXEEXT@: gxba_test.@O@ ${LWRESDEPLIBS} ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ gxba_test.@O@ \ ${LWRESLIBS} ${ISCLIBS} ${LIBS} sig0_test@EXEEXT@: sig0_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ sig0_test.@O@ \ ${DNSLIBS} ${ISCLIBS} ${LIBS} cfg_test@EXEEXT@: cfg_test.@O@ ${ISCCFGDEPLIBS} ${ISCDEPLIBS} ${LIBTOOL_MODE_LINK} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ cfg_test.@O@ \ ${ISCCFGLIBS} ${DNSLIBS} ${ISCLIBS} ${LIBS} makejournal@EXEEXT@: makejournal.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ makejournal.@O@ \ ${DNSLIBS} ${ISCLIBS} ${LIBS} distclean:: rm -f headerdep_test.sh clean distclean:: rm -f ${TARGETS} ${XTARGETS} rm -f t_journal rm -f backtrace_test_symtbl.c check: test test: @for dir in $(SUBDIRS) ;\ do \ ( cd $$dir; $(MAKE) test ) ;\ done bind9-9.11.3+dfsg/bin/tests/adb_test.c000066400000000000000000000250521325250447100174030ustar00rootroot00000000000000/* * Copyright (C) 1999-2001, 2004, 2005, 2007, 2009, 2011-2013, 2015, 2016 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* $Id: adb_test.c,v 1.73 2011/08/30 23:46:51 tbox Exp $ */ /*! \file */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include typedef struct client client_t; struct client { dns_name_t name; const char *target; ISC_LINK(client_t) link; dns_adbfind_t *find; }; static isc_mem_t *mctx = NULL; static isc_entropy_t *ectx = NULL; static isc_mempool_t *cmp; static isc_log_t *lctx; static isc_logconfig_t *lcfg; static isc_taskmgr_t *taskmgr; static isc_socketmgr_t *socketmgr; static isc_timermgr_t *timermgr; static dns_dispatchmgr_t *dispatchmgr; static isc_task_t *t1, *t2; static dns_view_t *view; static dns_db_t *rootdb; static ISC_LIST(client_t) clients; static isc_mutex_t client_lock; static isc_stdtime_t now; static dns_adb_t *adb; static void check_result(isc_result_t result, const char *format, ...) ISC_FORMAT_PRINTF(2, 3); static void check_result(isc_result_t result, const char *format, ...) { va_list args; if (result == ISC_R_SUCCESS) return; va_start(args, format); vfprintf(stderr, format, args); va_end(args); fprintf(stderr, ": %s\n", isc_result_totext(result)); exit(1); } static client_t * new_client(void) { client_t *client; client = isc_mempool_get(cmp); INSIST(client != NULL); dns_name_init(&client->name, NULL); ISC_LINK_INIT(client, link); client->find = NULL; return (client); } static void free_client(client_t **c) { client_t *client; INSIST(c != NULL); client = *c; *c = NULL; INSIST(client != NULL); dns_name_free(&client->name, mctx); INSIST(!ISC_LINK_LINKED(client, link)); INSIST(client->find == NULL); isc_mempool_put(cmp, client); } static inline void CLOCK(void) { RUNTIME_CHECK(isc_mutex_lock(&client_lock) == ISC_R_SUCCESS); } static inline void CUNLOCK(void) { RUNTIME_CHECK(isc_mutex_unlock(&client_lock) == ISC_R_SUCCESS); } static void lookup_callback(isc_task_t *task, isc_event_t *ev) { client_t *client; client = ev->ev_arg; INSIST(client->find == ev->ev_sender); printf("NAME %s:\n\tTask %p got event %p type %08x from %p, client %p\n\terr4: %s err6: %s\n", client->target, task, ev, ev->ev_type, client->find, client, isc_result_totext(client->find->result_v4), isc_result_totext(client->find->result_v6)); isc_event_free(&ev); ev = NULL; CLOCK(); dns_adb_dumpfind(client->find, stderr); dns_adb_destroyfind(&client->find); ISC_LIST_UNLINK(clients, client, link); free_client(&client); CUNLOCK(); } static void create_managers(void) { isc_result_t result; taskmgr = NULL; result = isc_taskmgr_create(mctx, 5, 0, &taskmgr); check_result(result, "isc_taskmgr_create"); timermgr = NULL; result = isc_timermgr_create(mctx, &timermgr); check_result(result, "isc_timermgr_create"); socketmgr = NULL; result = isc_socketmgr_create(mctx, &socketmgr); check_result(result, "isc_socketmgr_create"); dispatchmgr = NULL; result = dns_dispatchmgr_create(mctx, NULL, &dispatchmgr); check_result(result, "dns_dispatchmgr_create"); } static void create_view(void) { dns_cache_t *cache; isc_result_t result; /* * View. */ view = NULL; result = dns_view_create(mctx, dns_rdataclass_in, "_default", &view); check_result(result, "dns_view_create"); /* * Cache. */ cache = NULL; result = dns_cache_create(mctx, taskmgr, timermgr, dns_rdataclass_in, "rbt", 0, NULL, &cache); check_result(result, "dns_cache_create"); dns_view_setcache(view, cache); dns_cache_detach(&cache); { unsigned int attrs; isc_sockaddr_t any4, any6; dns_dispatch_t *disp4 = NULL; dns_dispatch_t *disp6 = NULL; isc_sockaddr_any(&any4); isc_sockaddr_any6(&any6); attrs = DNS_DISPATCHATTR_IPV4 | DNS_DISPATCHATTR_UDP; RUNTIME_CHECK(dns_dispatch_getudp(dispatchmgr, socketmgr, taskmgr, &any4, 512, 6, 1024, 17, 19, attrs, attrs, &disp4) == ISC_R_SUCCESS); INSIST(disp4 != NULL); attrs = DNS_DISPATCHATTR_IPV6 | DNS_DISPATCHATTR_UDP; RUNTIME_CHECK(dns_dispatch_getudp(dispatchmgr, socketmgr, taskmgr, &any6, 512, 6, 1024, 17, 19, attrs, attrs, &disp6) == ISC_R_SUCCESS); INSIST(disp6 != NULL); RUNTIME_CHECK(dns_view_createresolver(view, taskmgr, 10, 1, socketmgr, timermgr, 0, dispatchmgr, disp4, disp6) == ISC_R_SUCCESS); } rootdb = NULL; result = dns_rootns_create(mctx, dns_rdataclass_in, NULL, &rootdb); check_result(result, "dns_rootns_create()"); dns_view_sethints(view, rootdb); dns_db_detach(&rootdb); dns_view_freeze(view); } static void lookup(const char *target) { dns_name_t name; unsigned char namedata[256]; client_t *client; isc_buffer_t t, namebuf; isc_result_t result; unsigned int options; INSIST(target != NULL); client = new_client(); isc_buffer_constinit(&t, target, strlen(target)); isc_buffer_add(&t, strlen(target)); isc_buffer_init(&namebuf, namedata, sizeof(namedata)); dns_name_init(&name, NULL); result = dns_name_fromtext(&name, &t, dns_rootname, 0, &namebuf); check_result(result, "dns_name_fromtext %s", target); result = dns_name_dup(&name, mctx, &client->name); check_result(result, "dns_name_dup %s", target); options = 0; options |= DNS_ADBFIND_INET; options |= DNS_ADBFIND_INET6; options |= DNS_ADBFIND_WANTEVENT; options |= DNS_ADBFIND_HINTOK; options |= DNS_ADBFIND_GLUEOK; result = dns_adb_createfind(adb, t2, lookup_callback, client, &client->name, dns_rootname, 0, options, now, NULL, view->dstport, &client->find); if (result != ISC_R_SUCCESS) printf("DNS_ADB_CREATEFIND -> %s\n", dns_result_totext(result)); dns_adb_dumpfind(client->find, stderr); if ((client->find->options & DNS_ADBFIND_WANTEVENT) != 0) { client->target = target; ISC_LIST_APPEND(clients, client, link); } else { printf("NAME %s: err4 %s, err6 %s\n", target, isc_result_totext(client->find->result_v4), isc_result_totext(client->find->result_v6)); dns_adb_destroyfind(&client->find); free_client(&client); } } int main(int argc, char **argv) { isc_result_t result; isc_logdestination_t destination; UNUSED(argc); UNUSED(argv); dns_result_register(); result = isc_app_start(); check_result(result, "isc_app_start()"); isc_stdtime_get(&now); result = isc_mutex_init(&client_lock); check_result(result, "isc_mutex_init(&client_lock)"); ISC_LIST_INIT(clients); /* * EVERYTHING needs a memory context. */ RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS); cmp = NULL; RUNTIME_CHECK(isc_mempool_create(mctx, sizeof(client_t), &cmp) == ISC_R_SUCCESS); isc_mempool_setname(cmp, "adb test clients"); result = isc_entropy_create(mctx, &ectx); check_result(result, "isc_entropy_create()"); result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE); check_result(result, "isc_hash_create()"); result = isc_log_create(mctx, &lctx, &lcfg); check_result(result, "isc_log_create()"); isc_log_setcontext(lctx); dns_log_init(lctx); dns_log_setcontext(lctx); /* * Create and install the default channel. */ destination.file.stream = stderr; destination.file.name = NULL; destination.file.versions = ISC_LOG_ROLLNEVER; destination.file.maximum_size = 0; result = isc_log_createchannel(lcfg, "_default", ISC_LOG_TOFILEDESC, ISC_LOG_DYNAMIC, &destination, ISC_LOG_PRINTTIME); check_result(result, "isc_log_createchannel()"); result = isc_log_usechannel(lcfg, "_default", NULL, NULL); check_result(result, "isc_log_usechannel()"); /* * Set the initial debug level. */ isc_log_setdebuglevel(lctx, 2); create_managers(); t1 = NULL; result = isc_task_create(taskmgr, 0, &t1); check_result(result, "isc_task_create t1"); t2 = NULL; result = isc_task_create(taskmgr, 0, &t2); check_result(result, "isc_task_create t2"); printf("task 1 = %p\n", t1); printf("task 2 = %p\n", t2); create_view(); adb = view->adb; /* * Lock the entire client list here. This will cause all events * for found names to block as well. */ CLOCK(); lookup("f.root-servers.net."); /* Should be in hints */ lookup("www.iengines.com"); /* should fetch */ lookup("www.isc.org"); /* should fetch */ lookup("www.flame.org"); /* should fetch */ lookup("kechara.flame.org."); /* should fetch */ lookup("moghedien.flame.org."); /* should fetch */ lookup("mailrelay.flame.org."); /* should fetch */ lookup("ipv4v6.flame.org."); /* should fetch */ lookup("nonexistant.flame.org."); /* should fail to be found */ lookup("foobar.badns.flame.org."); /* should fail utterly (NS) */ lookup("i.root-servers.net."); /* Should be in hints */ lookup("www.firstcard.com."); lookup("dns04.flame.org."); CUNLOCK(); sleep(10); dns_adb_dump(adb, stderr); sleep(10); CLOCK(); lookup("f.root-servers.net."); /* Should be in hints */ lookup("www.iengines.com"); /* should fetch */ lookup("www.isc.org"); /* should fetch */ lookup("www.flame.org"); /* should fetch */ lookup("kechara.flame.org."); /* should fetch */ lookup("moghedien.flame.org."); /* should fetch */ lookup("mailrelay.flame.org."); /* should fetch */ lookup("ipv4v6.flame.org."); /* should fetch */ lookup("nonexistant.flame.org."); /* should fail to be found */ lookup("foobar.badns.flame.org."); /* should fail utterly (NS) */ lookup("i.root-servers.net."); /* Should be in hints */ CUNLOCK(); sleep(20); dns_adb_dump(adb, stderr); isc_task_detach(&t1); isc_task_detach(&t2); isc_mem_stats(mctx, stdout); dns_adb_dump(adb, stderr); isc_app_run(); dns_adb_dump(adb, stderr); dns_view_detach(&view); adb = NULL; fprintf(stderr, "Destroying socket manager\n"); isc_socketmgr_destroy(&socketmgr); fprintf(stderr, "Destroying timer manager\n"); isc_timermgr_destroy(&timermgr); fprintf(stderr, "Destroying task manager\n"); isc_taskmgr_destroy(&taskmgr); isc_log_destroy(&lctx); isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mempool_destroy(&cmp); isc_mem_stats(mctx, stdout); isc_mem_destroy(&mctx); isc_app_finish(); return (0); } bind9-9.11.3+dfsg/bin/tests/atomic/000077500000000000000000000000001325250447100167225ustar00rootroot00000000000000bind9-9.11.3+dfsg/bin/tests/atomic/Makefile.in000066400000000000000000000020641325250447100207710ustar00rootroot00000000000000# Copyright (C) 2011, 2012, 2014, 2016 Internet Systems Consortium, Inc. ("ISC") # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. # $Id: Makefile.in,v 1.2 2011/01/11 23:47:12 tbox Exp $ srcdir = @srcdir@ VPATH = @srcdir@ top_srcdir = @top_srcdir@ @BIND9_MAKE_INCLUDES@ CINCLUDES = ${TEST_INCLUDES} ${DNS_INCLUDES} ${ISC_INCLUDES} CDEFINES = CWARNINGS = ISCLIBS = ../../../lib/isc/libisc.@A@ @ISC_OPENSSL_LIBS@ ISCDEPLIBS = ../../../lib/isc/libisc.@A@ DEPLIBS = ${ISCDEPLIBS} LIBS = ${ISCLIBS} @LIBS@ TLIB = ../../../lib/tests/libt_api.@A@ TARGETS = t_atomic@EXEEXT@ SRCS = t_atomic.c @BIND9_MAKE_RULES@ t_atomic@EXEEXT@: t_atomic.@O@ ${DEPLIBS} ${TLIB} ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ t_atomic.@O@ ${TLIB} ${LIBS} test: t_atomic@EXEEXT@ -@./t_atomic@EXEEXT@ -c @top_srcdir@/t_config -b @srcdir@ -a testhelp: @./t_atomic@EXEEXT@ -h clean distclean:: rm -f ${TARGETS} bind9-9.11.3+dfsg/bin/tests/atomic/t_atomic.c000066400000000000000000000171501325250447100206710ustar00rootroot00000000000000/* * Copyright (C) 2011, 2013, 2015-2017 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include #include #include #include #include #include #include #include #include #include #include char *progname; #define CHECK(x) RUNTIME_CHECK(ISC_R_SUCCESS == (x)) isc_mem_t *mctx = NULL; isc_taskmgr_t *task_manager = NULL; #if defined(ISC_PLATFORM_HAVEXADD) || defined(ISC_PLATFORM_HAVEXADDQ) || \ defined(ISC_PLATFORM_HAVEATOMICSTORE) || \ defined(ISC_PLATFORM_HAVEATOMICSTOREQ) static void setup(void) { /* 1 */ CHECK(isc_mem_create(0, 0, &mctx)); /* 2 */ CHECK(isc_taskmgr_create(mctx, 32, 0, &task_manager)); } static void teardown(void) { /* 2 */ isc_taskmgr_destroy(&task_manager); /* 1 */ isc_mem_destroy(&mctx); } #endif #define TASKS 32 #define ITERATIONS 10000 #define COUNTS_PER_ITERATION 1000 #define INCREMENT_64 (isc_int64_t)0x0000000010000000 #define EXPECTED_COUNT_32 (TASKS * ITERATIONS * COUNTS_PER_ITERATION) #define EXPECTED_COUNT_64 (TASKS * ITERATIONS * COUNTS_PER_ITERATION * INCREMENT_64) typedef struct { isc_uint32_t iteration; } counter_t; counter_t counters[TASKS]; #if defined(ISC_PLATFORM_HAVEXADD) static isc_int32_t counter_32; static void do_xadd(isc_task_t *task, isc_event_t *ev) { counter_t *state = (counter_t *)ev->ev_arg; int i; for (i = 0 ; i < COUNTS_PER_ITERATION ; i++) { isc_atomic_xadd(&counter_32, 1); } state->iteration++; if (state->iteration < ITERATIONS) { isc_task_send(task, &ev); } else { isc_event_free(&ev); } } static void test_atomic_xadd() { int test_result; isc_task_t *tasks[TASKS]; isc_event_t *event; int i; t_assert("test_atomic_xadd", 1, T_REQUIRED, "%s", "ensure that isc_atomic_xadd() works."); setup(); memset(counters, 0, sizeof(counters)); counter_32 = 0; /* * Create our tasks, and allocate an event to get the counters going. */ for (i = 0 ; i < TASKS ; i++) { tasks[i] = NULL; CHECK(isc_task_create(task_manager, 0, &tasks[i])); event = isc_event_allocate(mctx, NULL, 1000, do_xadd, &counters[i], sizeof(struct isc_event)); isc_task_sendanddetach(&tasks[i], &event); } teardown(); test_result = T_PASS; t_info("32-bit counter %d, expected %d\n", counter_32, EXPECTED_COUNT_32); if (counter_32 != EXPECTED_COUNT_32) test_result = T_FAIL; t_result(test_result); counter_32 = 0; } #endif #if defined(ISC_PLATFORM_HAVEXADDQ) static isc_int64_t counter_64; static void do_xaddq(isc_task_t *task, isc_event_t *ev) { counter_t *state = (counter_t *)ev->ev_arg; int i; for (i = 0 ; i < COUNTS_PER_ITERATION ; i++) { isc_atomic_xaddq(&counter_64, INCREMENT_64); } state->iteration++; if (state->iteration < ITERATIONS) { isc_task_send(task, &ev); } else { isc_event_free(&ev); } } static void test_atomic_xaddq() { int test_result; isc_task_t *tasks[TASKS]; isc_event_t *event; int i; t_assert("test_atomic_xaddq", 1, T_REQUIRED, "%s", "ensure that isc_atomic_xaddq() works."); setup(); memset(counters, 0, sizeof(counters)); counter_64 = 0; /* * Create our tasks, and allocate an event to get the counters going. */ for (i = 0 ; i < TASKS ; i++) { tasks[i] = NULL; CHECK(isc_task_create(task_manager, 0, &tasks[i])); event = isc_event_allocate(mctx, NULL, 1000, do_xaddq, &counters[i], sizeof(struct isc_event)); isc_task_sendanddetach(&tasks[i], &event); } teardown(); test_result = T_PASS; t_info("64-bit counter %"ISC_PRINT_QUADFORMAT"d, expected %"ISC_PRINT_QUADFORMAT"d\n", counter_64, EXPECTED_COUNT_64); if (counter_64 != EXPECTED_COUNT_64) test_result = T_FAIL; t_result(test_result); counter_64 = 0; } #endif #ifdef ISC_PLATFORM_HAVEATOMICSTORE static isc_int32_t store_32; static void do_store(isc_task_t *task, isc_event_t *ev) { counter_t *state = (counter_t *)ev->ev_arg; int i; isc_uint32_t r; isc_uint32_t val; r = random() % 256; val = (r << 24) | (r << 16) | (r << 8) | r; for (i = 0 ; i < COUNTS_PER_ITERATION ; i++) { isc_atomic_store(&store_32, val); } state->iteration++; if (state->iteration < ITERATIONS) { isc_task_send(task, &ev); } else { isc_event_free(&ev); } } static void test_atomic_store() { int test_result; isc_task_t *tasks[TASKS]; isc_event_t *event; int i; isc_uint32_t r; isc_uint32_t val; t_assert("test_atomic_store", 1, T_REQUIRED, "%s", "ensure that isc_atomic_store() works."); setup(); memset(counters, 0, sizeof(counters)); store_32 = 0; /* * Create our tasks, and allocate an event to get the counters * going. */ for (i = 0 ; i < TASKS ; i++) { tasks[i] = NULL; CHECK(isc_task_create(task_manager, 0, &tasks[i])); event = isc_event_allocate(mctx, NULL, 1000, do_store, &counters[i], sizeof(struct isc_event)); isc_task_sendanddetach(&tasks[i], &event); } teardown(); test_result = T_PASS; r = store_32 & 0xff; val = (r << 24) | (r << 16) | (r << 8) | r; t_info("32-bit store 0x%x, expected 0x%x\n", (isc_uint32_t) store_32, val); if ((isc_uint32_t) store_32 != val) test_result = T_FAIL; t_result(test_result); store_32 = 0; } #endif #if defined(ISC_PLATFORM_HAVEATOMICSTOREQ) static isc_int64_t store_64; static void do_storeq(isc_task_t *task, isc_event_t *ev) { counter_t *state = (counter_t *)ev->ev_arg; int i; isc_uint8_t r; isc_uint64_t val; r = random() % 256; val = (((isc_uint64_t) r << 24) | ((isc_uint64_t) r << 16) | ((isc_uint64_t) r << 8) | (isc_uint64_t) r); val |= ((isc_uint64_t) val << 32); for (i = 0 ; i < COUNTS_PER_ITERATION ; i++) { isc_atomic_storeq(&store_64, val); } state->iteration++; if (state->iteration < ITERATIONS) { isc_task_send(task, &ev); } else { isc_event_free(&ev); } } static void test_atomic_storeq() { int test_result; isc_task_t *tasks[TASKS]; isc_event_t *event; int i; isc_uint8_t r; isc_uint64_t val; t_assert("test_atomic_storeq", 1, T_REQUIRED, "%s", "ensure that isc_atomic_storeq() works."); setup(); memset(counters, 0, sizeof(counters)); store_64 = 0; /* * Create our tasks, and allocate an event to get the counters going. */ for (i = 0 ; i < TASKS ; i++) { tasks[i] = NULL; CHECK(isc_task_create(task_manager, 0, &tasks[i])); event = isc_event_allocate(mctx, NULL, 1000, do_storeq, &counters[i], sizeof(struct isc_event)); isc_task_sendanddetach(&tasks[i], &event); } teardown(); test_result = T_PASS; r = store_64 & 0xff; val = (((isc_uint64_t) r << 24) | ((isc_uint64_t) r << 16) | ((isc_uint64_t) r << 8) | (isc_uint64_t) r); val |= ((isc_uint64_t) val << 32); t_info("64-bit store 0x%"ISC_PRINT_QUADFORMAT"x, expected 0x%"ISC_PRINT_QUADFORMAT"x\n", (isc_uint64_t) store_64, val); if ((isc_uint64_t) store_64 != val) test_result = T_FAIL; t_result(test_result); store_64 = 0; } #endif /* ISC_PLATFORM_HAVEATOMICSTOREQ */ testspec_t T_testlist[] = { #if defined(ISC_PLATFORM_HAVEXADD) { (PFV) test_atomic_xadd, "test_atomic_xadd" }, #endif #if defined(ISC_PLATFORM_HAVEXADDQ) { (PFV) test_atomic_xaddq, "test_atomic_xaddq" }, #endif #ifdef ISC_PLATFORM_HAVEATOMICSTORE { (PFV) test_atomic_store, "test_atomic_store" }, #endif #if defined(ISC_PLATFORM_HAVEATOMICSTOREQ) { (PFV) test_atomic_storeq, "test_atomic_storeq" }, #endif { (PFV) 0, NULL } }; #ifdef WIN32 int main(int argc, char **argv) { t_settests(T_testlist); return (t_main(argc, argv)); } #endif bind9-9.11.3+dfsg/bin/tests/atomic/win32/000077500000000000000000000000001325250447100176645ustar00rootroot00000000000000bind9-9.11.3+dfsg/bin/tests/atomic/win32/t_atomic.dsp.in000066400000000000000000000111031325250447100225740ustar00rootroot00000000000000# Microsoft Developer Studio Project File - Name="t_atomic" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "@PLATFORM@ (x86) Console Application" 0x0103 CFG=t_atomic - @PLATFORM@ Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "t_atomic.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "t_atomic.mak" CFG="t_atomic - @PLATFORM@ Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "t_atomic - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE "t_atomic - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "t_atomic - @PLATFORM@ Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 @COPTX@ @COPTI@ /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c # ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../../" @LIBXML2_INC@ /I "../../../../lib/isc/win32" /I "../../../../lib/isc/win32/include" /I "../../../../lib/isc/include" /I "../../../../lib/dns/win32/include" /I "../../../../lib/dns/include" /I "../../../../lib/tests/include" /D "WIN32" /D "NDEBUG" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console @MACHINE@ # ADD LINK32 @LIBXML2_LIB@ user32.lib advapi32.lib kernel32.lib ws2_32.lib ../../../../lib/isc/win32/Release/libisc.lib ../../../../lib/dns/win32/Release/libdns.lib ../../../../lib/tests/win32/Release/libtests.lib /nologo /subsystem:console @MACHINE@ /out:"../../../../Build/Release/t_atomic.exe" !ELSEIF "$(CFG)" == "t_atomic - @PLATFORM@ Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /GZ /c # ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../../" @LIBXML2_INC@ /I "../../../../lib/isc/win32" /I "../../../../lib/isc/win32/include" /I "../../../../lib/isc/include" /I "../../../../lib/dns/win32/include" /I "../../../../lib/dns/include" /I "../../../../lib/tests/include" /I "../../../../lib/bind9/include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "i386" /FR /FD /GZ /c # SUBTRACT CPP /X @COPTY@ # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug @MACHINE@ /pdbtype:sept # ADD LINK32 @LIBXML2_LIB@ user32.lib advapi32.lib kernel32.lib ws2_32.lib ../../../../lib/isc/win32/Debug/libisc.lib ../../../../lib/dns/win32/Debug/libdns.lib ../../../../lib/tests/win32/Debug/libtests.lib /nologo /subsystem:console /map /debug @MACHINE@ /out:"../../../../Build/Debug/t_atomic.exe" /pdbtype:sept !ENDIF # Begin Target # Name "t_atomic - @PLATFORM@ Release" # Name "t_atomic - @PLATFORM@ Debug" # Begin Group "Source Files" # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" # Begin Source File SOURCE=..\t_atomic.c # End Source File # End Group # End Target # End Project bind9-9.11.3+dfsg/bin/tests/atomic/win32/t_atomic.dsw000066400000000000000000000010351325250447100222010ustar00rootroot00000000000000Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "t_atomic"=".\t_atomic.dsp" - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### bind9-9.11.3+dfsg/bin/tests/atomic/win32/t_atomic.mak.in000066400000000000000000000265021325250447100225670ustar00rootroot00000000000000# Microsoft Developer Studio Generated NMAKE File, Based on t_atomic.dsp !IF "$(CFG)" == "" CFG=t_atomic - @PLATFORM@ Debug !MESSAGE No configuration specified. Defaulting to t_atomic - @PLATFORM@ Debug. !ENDIF !IF "$(CFG)" != "t_atomic - @PLATFORM@ Release" && "$(CFG)" != "t_atomic - @PLATFORM@ Debug" !MESSAGE Invalid configuration "$(CFG)" specified. !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "t_atomic.mak" CFG="t_atomic - @PLATFORM@ Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "t_atomic - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE "t_atomic - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE !ERROR An invalid configuration is specified. !ENDIF !IF "$(OS)" == "Windows_NT" NULL= !ELSE NULL=nul !ENDIF CPP=cl.exe RSC=rc.exe LIBXML=@LIBXML2_LIB@ !IF "$(CFG)" == "t_atomic - @PLATFORM@ Release" _VC_MANIFEST_INC=0 _VC_MANIFEST_BASENAME=__VC80 !ELSE _VC_MANIFEST_INC=1 _VC_MANIFEST_BASENAME=__VC80.Debug !ENDIF #################################################### # Specifying name of temporary resource file used only in incremental builds: !if "$(_VC_MANIFEST_INC)" == "1" _VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res !else _VC_MANIFEST_AUTO_RES= !endif #################################################### # _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE: !if "$(_VC_MANIFEST_INC)" == "1" #MT_SPECIAL_RETURN=1090650113 #MT_SPECIAL_SWITCH=-notify_resource_update MT_SPECIAL_RETURN=0 MT_SPECIAL_SWITCH= _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \ if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \ rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \ link $** /out:$@ $(LFLAGS) !else _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1 !endif #################################################### # _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL: !if "$(_VC_MANIFEST_INC)" == "1" #MT_SPECIAL_RETURN=1090650113 #MT_SPECIAL_SWITCH=-notify_resource_update MT_SPECIAL_RETURN=0 MT_SPECIAL_SWITCH= _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \ if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \ rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \ link $** /out:$@ $(LFLAGS) !else _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2 !endif #################################################### # _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily: !if "$(_VC_MANIFEST_INC)" == "1" _VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \ $(_VC_MANIFEST_BASENAME).auto.rc \ $(_VC_MANIFEST_BASENAME).auto.manifest !else _VC_MANIFEST_CLEAN= !endif !IF "$(CFG)" == "t_atomic - @PLATFORM@ Release" OUTDIR=.\Release INTDIR=.\Release !IF "$(RECURSE)" == "0" ALL : "..\..\..\..\Build\Release\t_atomic.exe" !ELSE ALL : "libtests - @PLATFORM@ Release" "libisc - @PLATFORM@ Release" "libdns - @PLATFORM@ Release" "..\..\..\..\Build\Release\t_atomic.exe" !ENDIF !IF "$(RECURSE)" == "1" CLEAN :"libdns - @PLATFORM@ ReleaseCLEAN" "libisc - @PLATFORM@ ReleaseCLEAN" "libtests - @PLATFORM@ ReleaseCLEAN" !ELSE CLEAN : !ENDIF -@erase "$(INTDIR)\t_atomic.obj" -@erase "$(INTDIR)\vc60.idb" -@erase "..\..\..\..\Build\Release\t_atomic.exe" -@$(_VC_MANIFEST_CLEAN) "$(OUTDIR)" : if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" CPP_PROJ=/nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../../" @LIBXML2_INC@ /I "../../../../lib/isc/win32" /I "../../../../lib/isc/win32/include" /I "../../../../lib/isc/include" /I "../../../../lib/dns/win32/include" /I "../../../../lib/dns/include" /I "../../../../lib/tests/include" /D "WIN32" /D "NDEBUG" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\t_atomic.pch" @COPTY@ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c BSC32=bscmake.exe BSC32_FLAGS=/nologo /o"$(OUTDIR)\t_atomic.bsc" BSC32_SBRS= \ LINK32=link.exe LINK32_FLAGS=user32.lib advapi32.lib kernel32.lib ws2_32.lib ../../../../lib/isc/win32/Release/libisc.lib ../../../../lib/dns/win32/Release/libdns.lib ../../../../lib/tests/win32/Release/libtests.lib $(LIBXML) /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\t_atomic.pdb" @MACHINE@ /out:"../../../../Build/Release/t_atomic.exe" LINK32_OBJS= \ "$(INTDIR)\t_atomic.obj" \ "..\..\..\..\lib\dns\win32\Release\libdns.lib" \ "..\..\..\..\lib\isc\win32\Release\libisc.lib" \ "..\..\..\..\lib\tests\win32\Release\libtests.lib" "..\..\..\..\Build\Release\t_atomic.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) $(LINK32) @<< $(LINK32_FLAGS) $(LINK32_OBJS) << $(_VC_MANIFEST_EMBED_EXE) !ELSEIF "$(CFG)" == "t_atomic - @PLATFORM@ Debug" OUTDIR=.\Debug INTDIR=.\Debug # Begin Custom Macros OutDir=.\Debug # End Custom Macros !IF "$(RECURSE)" == "0" ALL : "..\..\..\..\Build\Debug\t_atomic.exe" "$(OUTDIR)\t_atomic.bsc" !ELSE ALL : "libtests - @PLATFORM@ Debug" "libisc - @PLATFORM@ Debug" "libdns - @PLATFORM@ Debug" "..\..\..\..\Build\Debug\t_atomic.exe" "$(OUTDIR)\t_atomic.bsc" !ENDIF !IF "$(RECURSE)" == "1" CLEAN :"libdns - @PLATFORM@ DebugCLEAN" "libisc - @PLATFORM@ DebugCLEAN" "libtests - @PLATFORM@ DebugCLEAN" !ELSE CLEAN : !ENDIF -@erase "$(INTDIR)\t_atomic.obj" -@erase "$(INTDIR)\t_atomic.sbr" -@erase "$(INTDIR)\vc60.idb" -@erase "$(INTDIR)\vc60.pdb" -@erase "$(OUTDIR)\t_atomic.bsc" -@erase "$(OUTDIR)\t_atomic.map" -@erase "$(OUTDIR)\t_atomic.pdb" -@erase "..\..\..\..\Build\Debug\t_atomic.exe" -@erase "..\..\..\..\Build\Debug\t_atomic.ilk" -@$(_VC_MANIFEST_CLEAN) "$(OUTDIR)" : if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" CPP_PROJ=/nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../../" @LIBXML2_INC@ /I "../../../../lib/isc/win32" /I "../../../../lib/isc/win32/include" /I "../../../../lib/isc/include" /I "../../../../lib/dns/win32/include" /I "../../../../lib/dns/include" /I "../../../../lib/tests/include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "i386" /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c BSC32=bscmake.exe BSC32_FLAGS=/nologo /o"$(OUTDIR)\t_atomic.bsc" BSC32_SBRS= \ "$(INTDIR)\t_atomic.sbr" "$(OUTDIR)\t_atomic.bsc" : "$(OUTDIR)" $(BSC32_SBRS) $(BSC32) @<< $(BSC32_FLAGS) $(BSC32_SBRS) << LINK32=link.exe LINK32_FLAGS=user32.lib advapi32.lib kernel32.lib ws2_32.lib ../../../../lib/isc/win32/Debug/libisc.lib ../../../../lib/dns/win32/Debug/libdns.lib ../../../../lib/tests/win32/Debug/libtests.lib $(LIBXML) /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\t_atomic.pdb" /map:"$(INTDIR)\t_atomic.map" /debug @MACHINE@ /out:"../../../../Build/Debug/t_atomic.exe" /pdbtype:sept LINK32_OBJS= \ "$(INTDIR)\t_atomic.obj" \ "..\..\..\..\lib\dns\win32\Debug\libdns.lib" \ "..\..\..\..\lib\isc\win32\Debug\libisc.lib" \ "..\..\..\..\lib\tests\win32\Debug\libtests.lib" "..\..\..\..\Build\Debug\t_atomic.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) $(LINK32) @<< $(LINK32_FLAGS) $(LINK32_OBJS) << $(_VC_MANIFEST_EMBED_EXE) !ENDIF .c{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .c{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << !IF "$(NO_EXTERNAL_DEPS)" != "1" !IF EXISTS("t_atomic.dep") !INCLUDE "t_atomic.dep" !ELSE !MESSAGE Warning: cannot find "t_atomic.dep" !ENDIF !ENDIF !IF "$(CFG)" == "t_atomic - @PLATFORM@ Release" || "$(CFG)" == "t_atomic - @PLATFORM@ Debug" SOURCE=..\t_atomic.c !IF "$(CFG)" == "t_atomic - @PLATFORM@ Release" "$(INTDIR)\t_atomic.obj" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ELSEIF "$(CFG)" == "t_atomic - @PLATFORM@ Debug" "$(INTDIR)\t_atomic.obj" "$(INTDIR)\t_atomic.sbr" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ENDIF !IF "$(CFG)" == "t_atomic - @PLATFORM@ Release" "libdns - @PLATFORM@ Release" : cd "..\..\..\..\lib\dns\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Release" cd "..\..\..\bin\tests\atomic\win32" "libdns - @PLATFORM@ ReleaseCLEAN" : cd "..\..\..\..\lib\dns\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Release" RECURSE=1 CLEAN cd "..\..\..\bin\tests\atomic\win32" !ELSEIF "$(CFG)" == "t_atomic - @PLATFORM@ Debug" "libdns - @PLATFORM@ Debug" : cd "..\..\..\..\lib\dns\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Debug" cd "..\..\..\bin\tests\atomic\win32" "libdns - @PLATFORM@ DebugCLEAN" : cd "..\..\..\..\lib\dns\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Debug" RECURSE=1 CLEAN cd "..\..\..\bin\tests\atomic\win32" !ENDIF !IF "$(CFG)" == "t_atomic - @PLATFORM@ Release" "libisc - @PLATFORM@ Release" : cd "..\..\..\..\lib\isc\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Release" cd "..\..\..\bin\tests\atomic\win32" "libisc - @PLATFORM@ ReleaseCLEAN" : cd "..\..\..\..\lib\isc\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Release" RECURSE=1 CLEAN cd "..\..\..\bin\tests\atomic\win32" !ELSEIF "$(CFG)" == "t_atomic - @PLATFORM@ Debug" "libisc - @PLATFORM@ Debug" : cd "..\..\..\..\lib\isc\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Debug" cd "..\..\..\bin\tests\atomic\win32" "libisc - @PLATFORM@ DebugCLEAN" : cd "..\..\..\..\lib\isc\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Debug" RECURSE=1 CLEAN cd "..\..\..\bin\tests\atomic\win32" !ENDIF !IF "$(CFG)" == "t_atomic - @PLATFORM@ Release" "libtests - @PLATFORM@ Release" : cd "..\..\..\..\lib\tests\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libtests.mak" CFG="libtests - @PLATFORM@ Release" cd "..\..\..\bin\tests\atomic\win32" "libtests - @PLATFORM@ ReleaseCLEAN" : cd "..\..\..\..\lib\tests\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libtests.mak" CFG="libtests - @PLATFORM@ Release" RECURSE=1 CLEAN cd "..\..\..\bin\tests\atomic\win32" !ELSEIF "$(CFG)" == "t_atomic - @PLATFORM@ Debug" "libtests - @PLATFORM@ Debug" : cd "..\..\..\..\lib\tests\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libtests.mak" CFG="libtests - @PLATFORM@ Debug" cd "..\..\..\bin\tests\atomic\win32" "libtests - @PLATFORM@ DebugCLEAN" : cd "..\..\..\..\lib\tests\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libtests.mak" CFG="libtests - @PLATFORM@ Debug" RECURSE=1 CLEAN cd "..\..\..\bin\tests\atomic\win32" !ENDIF !ENDIF #################################################### # Commands to generate initial empty manifest file and the RC file # that references it, and for generating the .res file: $(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc $(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest type <<$@ #include 1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest" << KEEP $(_VC_MANIFEST_BASENAME).auto.manifest : type <<$@ << KEEP bind9-9.11.3+dfsg/bin/tests/atomic/win32/t_atomic.vcxproj.filters.in000066400000000000000000000016761325250447100251660ustar00rootroot00000000000000 {4FC737F1-C7A5-4376-A066-2A32D752A2FF} cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx {93995380-89BD-4b04-88EB-625FBE52EBFB} h;hpp;hxx;hm;inl;inc;xsd {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms Source Files bind9-9.11.3+dfsg/bin/tests/atomic/win32/t_atomic.vcxproj.in000066400000000000000000000151651325250447100235150ustar00rootroot00000000000000 Debug @PLATFORM@ Release @PLATFORM@ {EC6ECB35-58C0-48EC-BAC9-9A652D9406C9} Win32Proj t_atomic Application true MultiByte Application false true MultiByte true ..\..\..\..\Build\$(Configuration)\ .\$(Configuration)\ false ..\..\..\..\Build\$(Configuration)\ .\$(Configuration)\ Level3 Disabled WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true .\$(Configuration)\$(TargetName).pch .\$(Configuration)\ .\$(Configuration)\ $(OutDir)$(TargetName).pdb true .\;..\..\..\..\;@LIBXML2_INC@..\..\..\..\lib\isc\win32;..\..\..\..\lib\isc\win32\include;..\..\..\..\lib\isc\include;..\..\..\..\lib\dns\include;..\..\..\..\lib\tests\include;%(AdditionalIncludeDirectories) CompileAsC Console true ..\..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt) ..\..\..\..\lib\isc\win32\$(Configuration);..\..\..\..\lib\dns\win32\$(Configuration);..\..\..\..\lib\tests\win32\$(Configuration);%(AdditionalLibraryDirectories) @LIBXML2_LIB@libisc.lib;libdns.lib;libtests.lib;ws2_32.lib;%(AdditionalDependencies) Level3 MaxSpeed true @INTRINSIC@ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) OnlyExplicitInline false true .\$(Configuration)\$(TargetName).pch .\$(Configuration)\ .\$(Configuration)\ $(OutDir)$(TargetName).pdb .\;..\..\..\..\;@LIBXML2_INC@..\..\..\..\lib\isc\win32;..\..\..\..\lib\isc\win32\include;..\..\..\..\lib\isc\include;..\..\..\..\lib\dns\include;..\..\..\..\lib\tests\include;%(AdditionalIncludeDirectories) CompileAsC Console false true true ..\..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt) Default ..\..\..\..\lib\isc\win32\$(Configuration);..\..\..\..\lib\dns\win32\$(Configuration);..\..\..\..\lib\tests\win32\$(Configuration);%(AdditionalLibraryDirectories) @LIBXML2_LIB@libisc.lib;libdns.lib;libtests.lib;ws2_32.lib;%(AdditionalDependencies) bind9-9.11.3+dfsg/bin/tests/atomic/win32/t_atomic.vcxproj.user000066400000000000000000000002171325250447100240550ustar00rootroot00000000000000 bind9-9.11.3+dfsg/bin/tests/b8t.mk000066400000000000000000000025571325250447100165050ustar00rootroot00000000000000# Copyright (C) 1999-2001, 2004, 2007, 2012, 2016 Internet Systems Consortium, Inc. ("ISC") # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. # $Id: b8t.mk,v 1.11 2007/06/19 23:46:59 tbox Exp $ # # bind 8 multi-host make # PLATFORM set in the environment by cron # MODULE = bind BASE = /build BDIR = $(BASE)/$(MODULE) RDIR = /proj/build-reports/bind8/hosts/$(PLATFORM) SDIR = $(HOME)/b8t/src CVSROOT = /proj/cvs/isc all: clobber populate config build clobber: @echo "CLOBBBER `date`" @if test ! -d $(BASE) ; then mkdir -p $(BASE) ; fi @rm -fr $(BDIR) @echo "DONE `date`" populate: @echo "POPULATE `date`" @( cd $(BASE) && tar -xvf $(SDIR)/$(MODULE).tar ) > $(RDIR)/.populate 2>&1 @echo "DONE `date`" tarsrc: @echo "TARSRC `date`" @rm -fr $(SDIR)/$(MODULE) @( cd $(SDIR) && cvs -d $(CVSROOT) checkout $(MODULE) ) @( cd $(SDIR) && tar -cvf $(MODULE).tar $(MODULE) ) @echo "DONE `date`" config: @echo "CONFIG `date`" @( cd $(BDIR)/src && make SRC=$(BDIR)/src DST=$(BDIR)/dst links ) > $(RDIR)/.config 2>&1 @echo "DONE `date`" build: @echo "BUILD `date`" @( cd $(BDIR)/dst && make -k clean depend all ) > $(RDIR)/.build 2>&1 @echo "DONE `date`" test: @echo "TEST `date`" @touch $(RDIR)/.test @echo "DONE `date`" bind9-9.11.3+dfsg/bin/tests/b9t.mk000066400000000000000000000030611325250447100164750ustar00rootroot00000000000000# Copyright (C) 1999-2001, 2004, 2007, 2012, 2016 Internet Systems Consortium, Inc. ("ISC") # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. # $Id: b9t.mk,v 1.13 2007/06/19 23:46:59 tbox Exp $ # # makefile to configure, build and test bind9 # this is run by cron (user wpk) on aa, sol, irix, hp and aix # $PLATFORM is set in the environment by cron # BASE = /build BDIR = $(BASE) MODULE = bind9 SDIR = $(HOME)/b9t/src # as it says CVSROOT = /proj/cvs/isc # where the config, build and test output goes RDIR = /proj/build-reports/$(MODULE)/hosts/$(PLATFORM) all: clobber populate config build test clobber: @echo "CLOBBBER `date`" @if test ! -d $(BDIR) ; then mkdir -p $(BDIR) > /dev/null 2>&1 ; fi @( cd $(BDIR) && rm -fr $(MODULE) ) @echo "DONE `date`" populate: @echo "POPULATE `date`" @( cd $(BDIR) && tar -xvf $(SDIR)/$(MODULE).tar ) > $(RDIR)/.populate 2>&1 @echo "DONE `date`" config: @echo "CONFIG `date`" @( cd $(BDIR)/$(MODULE) && ./configure ) > $(RDIR)/.config 2>&1 @echo "DONE `date`" build: @echo "BUILD `date`" @( cd $(BDIR)/$(MODULE) && $(MAKE) -k all ) > $(RDIR)/.build 2>&1 @echo "DONE `date`" test: @echo "TEST `date`" -@( cd $(BDIR)/$(MODULE)/bin/tests && $(MAKE) test ) > $(RDIR)/.test 2>&1 @echo "DONE `date`" tarsrc: @echo "TARSRC `date`" @rm -fr $(SDIR)/$(MODULE) @( cd $(SDIR) && cvs -d $(CVSROOT) checkout $(MODULE) && tar -cvf $(MODULE).tar $(MODULE) ) @echo "DONE `date`" bind9-9.11.3+dfsg/bin/tests/backtrace_test.c000066400000000000000000000033731325250447100205760ustar00rootroot00000000000000/* * Copyright (C) 2009, 2013, 2015, 2016 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* $Id: backtrace_test.c,v 1.4 2009/09/02 23:48:01 tbox Exp $ */ #include #include #include #include #include #include const char *expected_symbols[] = { "func3", "func2", "func1", "main" }; static int func3() { void *tracebuf[16]; int i, nframes; int error = 0; const char *fname; isc_result_t result; unsigned long offset; result = isc_backtrace_gettrace(tracebuf, 16, &nframes); if (result != ISC_R_SUCCESS) { printf("isc_backtrace_gettrace failed: %s\n", isc_result_totext(result)); return (1); } if (nframes < 4) error++; for (i = 0; i < 4 && i < nframes; i++) { fname = NULL; result = isc_backtrace_getsymbol(tracebuf[i], &fname, &offset); if (result != ISC_R_SUCCESS) { error++; continue; } if (strcmp(fname, expected_symbols[i]) != 0) error++; } if (error) { printf("Unexpected result:\n"); printf(" # of frames: %d (expected: at least 4)\n", nframes); printf(" symbols:\n"); for (i = 0; i < nframes; i++) { fname = NULL; result = isc_backtrace_getsymbol(tracebuf[i], &fname, &offset); if (result == ISC_R_SUCCESS) printf(" [%d] %s\n", i, fname); else { printf(" [%d] %p getsymbol failed: %s\n", i, tracebuf[i], isc_result_totext(result)); } } } return (error); } static int func2() { return (func3()); } static int func1() { return (func2()); } int main() { return (func1()); } bind9-9.11.3+dfsg/bin/tests/bigtest/000077500000000000000000000000001325250447100171075ustar00rootroot00000000000000bind9-9.11.3+dfsg/bin/tests/bigtest/README000066400000000000000000000011151325250447100177650ustar00rootroot00000000000000Copyright (C) 2013, 2016 Internet Systems Consortium, Inc. ("ISC") This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. bash buildzones.sh < zones # creates setup, run, servers/* master/* # named.conf sudo sh setup # configure interfaces sh run # setup ../named/named [-g] -c named.conf sh tests.sh < zones sudo sh teardown # teardown interfaces The test server can controlled with rndc -k rndc.key -s 127.127.0.0 -p 5300 bind9-9.11.3+dfsg/bin/tests/bigtest/buildzones.sh000066400000000000000000000144031325250447100216230ustar00rootroot00000000000000#!/bin/bash # # Copyright (C) 2013, 2016 Internet Systems Consortium, Inc. ("ISC") # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. SYSTEMTESTTOP=.. . ../conf.sh addr=127.127.0.0 ttl=300 named=${NAMED} keygen=${KEYGEN} dsfromkey=${DSFROMKEY} nextaddr() { OLDIF="$IFS" IFS="${IFS}." set $1 IFS="$OLDIFS" _a=$1 _b=$2 _c=$3 _d=$4 _d=$(($_d + 1)) case $_d in 256) _c=$(($_c + 1)); _d=0;; esac case $_c in 256) _b=$(($_b + 1)); _c=0;; esac echo $_a.$_b.$_c.$_d } parent() { OLDIF="$IFS" IFS="${IFS}." set $1 IFS="$OLDIFS" shift while [ $# -ne 0 ] do printf %s ${1} shift printf %s ${1:+.} done } blackhole() { echo 'options {' echo ' port 5300;' echo " listen-on { $1; };" echo " query-source $1;" echo " notify-source $1;" echo " transfer-source $1;" echo ' key-directory "keys";' echo " recursion ${2:-no};" echo ' pid-file "pids/'"${addr}"'.pid";' echo ' blackhole { 127.127.0.0; };' echo '};' } refuse() { echo 'options {' echo ' port 5300;' echo " listen-on { $1; };" echo " query-source $1;" echo " notify-source $1;" echo " transfer-source $1;" echo ' key-directory "keys";' echo " recursion ${2:-no};" echo ' pid-file "pids/'"${addr}"'.pid";' echo ' allow-query { !127.127.0.0; any; };' echo '};' } options() { echo 'options {' echo ' port 5300;' echo " listen-on { $1; };" echo " query-source $1;" echo " notify-source $1;" echo " transfer-source $1;" echo ' key-directory "keys";' echo " recursion ${2:-no};" echo ' pid-file "pids/'"${addr}"'.pid";' echo '};' } controls() { echo 'include "rndc.key";' echo "controls { inet $addr port 9953 allow { any; } keys { "rndc-key"; }; };" } delay() { _s=$1 OLDIF="$IFS" IFS="${IFS}/" set ${2:-.} IFS="$OLDIFS" case $1 in .) _d=;; *) _d=$1;; esac case $_s in 1) echo -T delay=${_d:-100};; 2) echo -T delay=${2:-50};; 3) echo -T delay=${3:-150};; 4) echo -T delay=${4:-250};; 5) echo -T delay=${5:-125};; 6) echo -T delay=${6:-25};; 7) echo -T delay=${7:-75};; 8) echo -T delay=${8:-125};; 9) echo -T delay=${9:-10};; 10) echo -T delay=${10:-40};; 11) echo -T delay=${11:-80};; 12) echo -T delay=${12:-90};; *) echo -T delay=50;; esac } trusted-keys () { awk '$3 == "DNSKEY" { b = ""; for (i=7; i <= NF; i++) { b = b $i; }; print "trusted-keys { \""$1"\"",$4,$5,$6,"\""b"\"; };" };' } signed-zone () { echo "zone "'"'"${1:-.}"'"'" {" echo " type master;" echo " file "'"'"master/${2}.db"'"'";" echo " auto-dnssec maintain;" echo " allow-update { any; };" echo "};" } unsigned-zone () { echo "zone "'"'"${1:-.}"'"'" {" echo " type master;" echo " file "'"'"master/${2}.db"'"'";" echo "};" } slave-zone () { echo "zone "'"'"${zone:-.}"'"'" {" echo " type slave;" echo " masters { ${master}; };" echo "};" } rm -rf servers master keys setup teardown run mkdir -p servers mkdir -p master mkdir -p keys echo "ifconfig lo0 $addr netmask 0xffffffff alias" >> setup echo "ifconfig lo0 $addr -alias" >> teardown controls $addr > named.conf options $addr yes >> named.conf echo 'zone "." { type hint; file "master/hint.db"; };' >> named.conf while read zone servers nsfmt signed delay blackhole refuse flags do i=1 case "${zone}" in .) file=root zone=;; *) file="$zone";; esac if [ "${zone}" != "" ] ; then p=$(parent $zone) case "${p}" in "") p=root;; esac else p=hint fi #echo "zone='${zone}' parent='${p}'" addr=$(nextaddr $addr) ns=$(printf "$nsfmt" ${i} "${zone}") d=$(delay $i ${delay:-.}) echo "${zone}. ${ttl} soa ${ns}. hostmaster.${zone}${zone:+.} 1 3600 1200 604800 1200" >> master/${file}.db echo "${zone}. ${ttl} ns ${ns}." >> master/${file}.db echo "${ns}. ${ttl} a ${addr}" >> master/${file}.db echo "${zone}. ${ttl} ns ${ns}." >> master/${p}.db echo "${ns}. ${ttl} a ${addr}" >> master/${p}.db if [ $signed = "S" ]; then kskkey=`${keygen} -K keys -f KSK ${zone:-.}` zskkey=`${keygen} -K keys ${zone:-.}` if [ "${zone}" != "" ] ; then ${dsfromkey} -T ${ttl} keys/${kskkey}.key >> master/${p}.db else trusted-keys < keys/${kskkey}.key >> named.conf fi fi echo "ifconfig lo0 $addr netmask 0xffffffff alias" >> setup echo "ifconfig lo0 $addr -alias" >> teardown echo "${named} -D bigtest -c servers/${addr}.conf $d $flags" >> run options ${addr} > servers/${addr}.conf case ${signed} in S) signed-zone ${zone:-.} ${file} >> servers/${addr}.conf;; P) unsigned-zone ${zone:-.} ${file} >> servers/${addr}.conf;; *) echo ${signed}; exit 1;; esac # slave servers while [ $i -lt $servers ] do master=$addr i=$(($i + 1)) ns=$(printf "$nsfmt" ${i} "${zone}") d=$(delay $i ${delay:-.}) addr=$(nextaddr $addr) echo "${zone}. ${ttl} ns ${ns}." >> master/${file}.db echo "${ns}. ${ttl} a ${addr}" >> master/${file}.db echo "${zone}. ${ttl} ns ${ns}." >> master/${p}.db echo "${ns}. ${ttl} a ${addr}" >> master/${p}.db echo "ifconfig lo0 $addr netmask 0xffffffff alias" >> setup echo "ifconfig lo0 $addr -alias" >> teardown echo "${named} -D bigtest -c servers/${addr}.conf $d $flags" >> run if [ $i = ${refuse:-.} ] then refuse $addr > servers/${addr}.conf elif [ $i = ${blackhole:-.} ] then blackhole $addr > servers/${addr}.conf else options $addr > servers/${addr}.conf fi slave-zone ${zone:-.} ${master} >> servers/${addr}.conf done if [ "${zone}" != "" ] ; then echo "www.${zone}. ${ttl} a 127.0.0.1" >> master/${file}.db echo "www.${zone}. ${ttl} aaaa ::1" >> master/${file}.db echo "${zone}. ${ttl} mx 10 mail.${zone}." >> master/${file}.db echo "mail.${zone}. ${ttl} a 127.0.0.1" >> master/${file}.db echo "mail.${zone}. ${ttl} aaaa ::1" >> master/${file}.db echo "*.big.${zone}. ${ttl} txt (" >> master/${file}.db i=0 while [ $i -lt 150 ] do echo "1234567890" >> master/${file}.db i=$(($i + 1)) done echo ")" >> master/${file}.db echo "*.medium.${zone}. ${ttl} txt (" >> master/${file}.db i=0 while [ $i -lt 120 ] do echo "1234567890" >> master/${file}.db i=$(($i + 1)) done echo ")" >> master/${file}.db echo "*.medium.${zone}. ${ttl} txt (" >> master/${file}.db i=0 while [ $i -lt 120 ] do echo "1234567890" >> master/${file}.db i=$(($i + 1)) done echo ")" >> master/${file}.db fi done bind9-9.11.3+dfsg/bin/tests/bigtest/rndc.key000066400000000000000000000001341325250447100205450ustar00rootroot00000000000000key "rndc-key" { algorithm hmac-md5; secret "xxxxxxxxxxxxxxxxxxxxHg=="; }; bind9-9.11.3+dfsg/bin/tests/bigtest/tests.sh000066400000000000000000000031701325250447100206060ustar00rootroot00000000000000#!/bin/bash # # Copyright (C) 2013, 2016 Internet Systems Consortium, Inc. ("ISC") # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. TOP=$( (cd ../../.. && pwd) ) dig=${TOP}/bin/dig/dig cmd="${dig} -p 5300 @127.127.0.0 txt" inner() { zone=$1 i=$2 to=$3 x=$i dout=dig$x.out tout=time$x.out while [ $i -lt $to ] do case $zone in .) zone=;; esac (time -p $cmd $i.${sub}$zone > $dout ) 2> $tout s=`sed -n '/real/s/[^0-9]*\([0-9]*\)\..*/\1/p' $tout` case $s in 0);; 1) t1=`expr ${t1:-0} + 1`;; 2) t2=`expr ${t2:-0} + 1`;; 3) t3=`expr ${t3:-0} + 1`;; *) echo $i `grep real $tout`;; esac grep "status: \(NXDOMAIN\|NOERROR\)" $dout > /dev/null || { echo $cmd $i.${sub}$zone cat $dout } i=`expr $i + 1` done if test ${t1:-0} -ne 0 -o ${t2:-0} -ne 0 -o ${t3:-0} -ne 0 then echo "$x timeouts: t1=${t1:-0} t2=${t2:-0} t3=${t3:-0}" fi } while read zone rest do for sub in "" medium. big. do case $zone in .) echo doing ${sub:-.};; *) echo doing $sub$zone;; esac ( inner $zone 1 100) & ( inner $zone 101 200) & ( inner $zone 201 300) & ( inner $zone 301 400) & ( inner $zone 401 500) & ( inner $zone 501 600) & ( inner $zone 601 700) & ( inner $zone 701 800) & ( inner $zone 801 900) & ( inner $zone 901 1000) & ( inner $zone 1001 1100) & ( inner $zone 1101 1200) & ( inner $zone 1201 1300) & ( inner $zone 1301 1400) & ( inner $zone 1401 1500) & ( inner $zone 1501 1600) & ( inner $zone 1601 1700) & wait done done bind9-9.11.3+dfsg/bin/tests/bigtest/zones000066400000000000000000000013611325250447100201710ustar00rootroot00000000000000noedns-1.tld 1 ns%u.%s P . x x -T noedns dropedns-1.tld 1 ns%u.%s P . x x -T dropedns maxudp512-1.tld 1 ns%u.%s S . x x -T maxudp=512 maxudp1460-1.tld 1 ns%u.%s S . x x -T maxudp=1460 plain-1.tld 1 ns%u.%s S . x x noedns-3.tld 3 ns%u.%s P . 2 x -T noedns dropedns-3.tld 3 ns%u.%s P . 2 x -T dropedns maxudp512-3.tld 3 ns%u.%s S . x x -T maxudp=512 maxudp1460-3.tld 3 ns%u.%s S . x x -T maxudp=1460 plain-3.tld 3 ns%u.%s S . x 3 noedns-5.tld 5 ns%u.%s P . 3 x -T noedns dropedns-5.tld 5 ns%u.%s P . x x -T dropedns maxudp512-5.tld 5 ns%u.%s S . x x -T maxudp=512 maxudp1460-5.tld 5 ns%u.%s S . x x -T maxudp=1460 400ms-1.tld 5 ns%u.%s S 400/400/400/400/400 2 x plain-5.tld 5 ns%u.%s S . x x tld 12 ns%u.%s S . 5 8 . 12 ns%u.root-servers.nil%s S . x x bind9-9.11.3+dfsg/bin/tests/byaddr_test.c000066400000000000000000000136761325250447100201330ustar00rootroot00000000000000/* * Copyright (C) 2000-2002, 2004, 2005, 2007, 2012, 2015, 2016 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* $Id: byaddr_test.c,v 1.28 2007/06/19 23:46:59 tbox Exp $ */ /*! \file * \author * Principal Author: Bob Halley */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static void done(isc_task_t *task, isc_event_t *event) { dns_byaddrevent_t *bevent; dns_byaddr_t *byaddr; dns_name_t *name; REQUIRE(event->ev_type == DNS_EVENT_BYADDRDONE); bevent = (dns_byaddrevent_t *)event; UNUSED(task); printf("byaddr event result = %s\n", isc_result_totext(bevent->result)); if (bevent->result == ISC_R_SUCCESS) { for (name = ISC_LIST_HEAD(bevent->names); name != NULL; name = ISC_LIST_NEXT(name, link)) { char text[DNS_NAME_FORMATSIZE]; dns_name_format(name, text, sizeof(text)); printf("%s\n", text); } } byaddr = event->ev_sender; dns_byaddr_destroy(&byaddr); isc_event_free(&event); isc_app_shutdown(); } int main(int argc, char *argv[]) { isc_mem_t *mctx; isc_boolean_t verbose = ISC_FALSE; unsigned int workers = 2; isc_taskmgr_t *taskmgr; isc_task_t *task; isc_timermgr_t *timermgr; dns_view_t *view; int ch; isc_socketmgr_t *socketmgr; dns_dispatchmgr_t *dispatchmgr; isc_netaddr_t na; dns_byaddr_t *byaddr; isc_result_t result; unsigned int options = 0; dns_cache_t *cache; RUNTIME_CHECK(isc_app_start() == ISC_R_SUCCESS); dns_result_register(); mctx = NULL; RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS); while ((ch = isc_commandline_parse(argc, argv, "nvw:")) != -1) { switch (ch) { case 'n': /* * We only try nibbles, so do nothing for this option. */ break; case 'v': verbose = ISC_TRUE; break; case 'w': workers = (unsigned int)atoi(isc_commandline_argument); break; } } if (verbose) { printf("%u workers\n", workers); printf("IPv4: %s\n", isc_result_totext(isc_net_probeipv4())); printf("IPv6: %s\n", isc_result_totext(isc_net_probeipv6())); } taskmgr = NULL; RUNTIME_CHECK(isc_taskmgr_create(mctx, workers, 0, &taskmgr) == ISC_R_SUCCESS); task = NULL; RUNTIME_CHECK(isc_task_create(taskmgr, 0, &task) == ISC_R_SUCCESS); isc_task_setname(task, "byaddr", NULL); dispatchmgr = NULL; RUNTIME_CHECK(dns_dispatchmgr_create(mctx, NULL, &dispatchmgr) == ISC_R_SUCCESS); timermgr = NULL; RUNTIME_CHECK(isc_timermgr_create(mctx, &timermgr) == ISC_R_SUCCESS); socketmgr = NULL; RUNTIME_CHECK(isc_socketmgr_create(mctx, &socketmgr) == ISC_R_SUCCESS); cache = NULL; RUNTIME_CHECK(dns_cache_create(mctx, taskmgr, timermgr, dns_rdataclass_in, "rbt", 0, NULL, &cache) == ISC_R_SUCCESS); view = NULL; RUNTIME_CHECK(dns_view_create(mctx, dns_rdataclass_in, "default", &view) == ISC_R_SUCCESS); { unsigned int attrs; dns_dispatch_t *disp4 = NULL; dns_dispatch_t *disp6 = NULL; if (isc_net_probeipv4() == ISC_R_SUCCESS) { isc_sockaddr_t any4; isc_sockaddr_any(&any4); attrs = DNS_DISPATCHATTR_IPV4 | DNS_DISPATCHATTR_UDP; RUNTIME_CHECK(dns_dispatch_getudp(dispatchmgr, socketmgr, taskmgr, &any4, 512, 6, 1024, 17, 19, attrs, attrs, &disp4) == ISC_R_SUCCESS); INSIST(disp4 != NULL); } if (isc_net_probeipv6() == ISC_R_SUCCESS) { isc_sockaddr_t any6; isc_sockaddr_any6(&any6); attrs = DNS_DISPATCHATTR_IPV6 | DNS_DISPATCHATTR_UDP; RUNTIME_CHECK(dns_dispatch_getudp(dispatchmgr, socketmgr, taskmgr, &any6, 512, 6, 1024, 17, 19, attrs, attrs, &disp6) == ISC_R_SUCCESS); INSIST(disp6 != NULL); } RUNTIME_CHECK(dns_view_createresolver(view, taskmgr, 10, 1, socketmgr, timermgr, 0, dispatchmgr, disp4, disp6) == ISC_R_SUCCESS); if (disp4 != NULL) dns_dispatch_detach(&disp4); if (disp6 != NULL) dns_dispatch_detach(&disp6); } { struct in_addr ina; isc_sockaddr_t sa; isc_sockaddrlist_t sal; ISC_LIST_INIT(sal); ina.s_addr = inet_addr("127.0.0.1"); isc_sockaddr_fromin(&sa, &ina, 53); ISC_LIST_APPEND(sal, &sa, link); RUNTIME_CHECK(dns_fwdtable_add(view->fwdtable, dns_rootname, &sal, dns_fwdpolicy_only) == ISC_R_SUCCESS); } dns_view_setcache(view, cache); dns_view_freeze(view); dns_cache_detach(&cache); printf("address = %s\n", argv[isc_commandline_index]); na.family = AF_INET; if (inet_pton(AF_INET, argv[isc_commandline_index], (char *)&na.type.in) != 1) { na.family = AF_INET6; if (inet_pton(AF_INET6, argv[isc_commandline_index], (char *)&na.type.in6) != 1) { printf("unknown address format\n"); exit(1); } } result = dns_byaddr_create(mctx, &na, view, options, task, done, NULL, &byaddr); if (result != ISC_R_SUCCESS) { printf("dns_byaddr_create() returned %s\n", isc_result_totext(result)); RUNTIME_CHECK(0); } (void)isc_app_run(); /* * XXXRTH if we get a control-C before we get to isc_app_run(), * we're in trouble (because we might try to destroy things before * they've been created. */ dns_view_detach(&view); isc_task_shutdown(task); isc_task_detach(&task); dns_dispatchmgr_destroy(&dispatchmgr); isc_taskmgr_destroy(&taskmgr); isc_socketmgr_destroy(&socketmgr); isc_timermgr_destroy(&timermgr); if (verbose) isc_mem_stats(mctx, stdout); isc_mem_destroy(&mctx); isc_app_finish(); return (0); } bind9-9.11.3+dfsg/bin/tests/byname_test.c000066400000000000000000000212771325250447100201350ustar00rootroot00000000000000/* * Copyright (C) 2000, 2001, 2004, 2005, 2007, 2009, 2012, 2015-2017 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /*! \file * \author * Principal Author: Bob Halley */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static isc_mem_t *mctx = NULL; static isc_entropy_t *ectx = NULL; static isc_taskmgr_t *taskmgr; static dns_view_t *view = NULL; static dns_adbfind_t *find = NULL; static isc_task_t *task = NULL; static dns_fixedname_t fixed; static dns_fixedname_t target; static isc_log_t *lctx; static isc_logconfig_t *lcfg; static unsigned int level = 0; static void adb_callback(isc_task_t *task, isc_event_t *event); static void log_init(void) { isc_logdestination_t destination; unsigned int flags; /* * Setup a logging context. */ RUNTIME_CHECK(isc_log_create(mctx, &lctx, &lcfg) == ISC_R_SUCCESS); isc_log_setcontext(lctx); dns_log_init(lctx); dns_log_setcontext(lctx); /* * Create and install the default channel. */ destination.file.stream = stderr; destination.file.name = NULL; destination.file.versions = ISC_LOG_ROLLNEVER; destination.file.maximum_size = 0; flags = ISC_LOG_PRINTTIME; RUNTIME_CHECK(isc_log_createchannel(lcfg, "_default", ISC_LOG_TOFILEDESC, ISC_LOG_DYNAMIC, &destination, flags) == ISC_R_SUCCESS); RUNTIME_CHECK(isc_log_usechannel(lcfg, "_default", NULL, NULL) == ISC_R_SUCCESS); isc_log_setdebuglevel(lctx, level); } static void print_addresses(dns_adbfind_t *adbfind) { dns_adbaddrinfo_t *address; for (address = ISC_LIST_HEAD(adbfind->list); address != NULL; address = ISC_LIST_NEXT(address, publink)) { isc_netaddr_t netaddr; char text[ISC_NETADDR_FORMATSIZE]; isc_netaddr_fromsockaddr(&netaddr, &address->sockaddr); isc_netaddr_format(&netaddr, text, sizeof(text)); printf("%s\n", text); } } static void print_name(dns_name_t *name) { char text[DNS_NAME_FORMATSIZE]; dns_name_format(name, text, sizeof(text)); printf("%s\n", text); } static void do_find(isc_boolean_t want_event) { isc_result_t result; isc_boolean_t done = ISC_FALSE; unsigned int options; options = DNS_ADBFIND_INET | DNS_ADBFIND_INET6; if (want_event) options |= DNS_ADBFIND_WANTEVENT | DNS_ADBFIND_EMPTYEVENT; dns_fixedname_init(&target); result = dns_adb_createfind(view->adb, task, adb_callback, NULL, dns_fixedname_name(&fixed), dns_rootname, 0, options, 0, dns_fixedname_name(&target), 0, &find); if (result == ISC_R_SUCCESS) { if (!ISC_LIST_EMPTY(find->list)) { /* * We have at least some of the addresses for the * name. */ INSIST((find->options & DNS_ADBFIND_WANTEVENT) == 0); print_addresses(find); done = ISC_TRUE; } else { /* * We don't know any of the addresses for this * name. */ if ((find->options & DNS_ADBFIND_WANTEVENT) == 0) { /* * And ADB isn't going to send us any events * either. This query loses. */ done = ISC_TRUE; } /* * If the DNS_ADBFIND_WANTEVENT flag was set, we'll * get an event when something happens. */ } } else if (result == DNS_R_ALIAS) { print_name(dns_fixedname_name(&target)); done = ISC_TRUE; } else { printf("dns_adb_createfind() returned %s\n", isc_result_totext(result)); done = ISC_TRUE; } if (done) { if (find != NULL) dns_adb_destroyfind(&find); isc_app_shutdown(); } } static void adb_callback(isc_task_t *etask, isc_event_t *event) { unsigned int type = event->ev_type; REQUIRE(etask == task); isc_event_free(&event); dns_adb_destroyfind(&find); if (type == DNS_EVENT_ADBMOREADDRESSES) do_find(ISC_FALSE); else if (type == DNS_EVENT_ADBNOMOREADDRESSES) { printf("no more addresses\n"); isc_app_shutdown(); } else { printf("unexpected ADB event type %u\n", type); isc_app_shutdown(); } } static void run(isc_task_t *xtask, isc_event_t *event) { UNUSED(xtask); do_find(ISC_TRUE); isc_event_free(&event); } int main(int argc, char *argv[]) { isc_boolean_t verbose = ISC_FALSE; unsigned int workers = 2; isc_timermgr_t *timermgr; int ch; isc_socketmgr_t *socketmgr; dns_dispatchmgr_t *dispatchmgr; dns_cache_t *cache; isc_buffer_t b; RUNTIME_CHECK(isc_app_start() == ISC_R_SUCCESS); dns_result_register(); mctx = NULL; RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS); RUNTIME_CHECK(isc_entropy_create(mctx, &ectx) == ISC_R_SUCCESS); RUNTIME_CHECK(isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE) == ISC_R_SUCCESS); while ((ch = isc_commandline_parse(argc, argv, "d:vw:")) != -1) { switch (ch) { case 'd': level = (unsigned int)atoi(isc_commandline_argument); break; case 'v': verbose = ISC_TRUE; break; case 'w': workers = (unsigned int)atoi(isc_commandline_argument); break; } } log_init(); if (verbose) { printf("%u workers\n", workers); printf("IPv4: %s\n", isc_result_totext(isc_net_probeipv4())); printf("IPv6: %s\n", isc_result_totext(isc_net_probeipv6())); } taskmgr = NULL; RUNTIME_CHECK(isc_taskmgr_create(mctx, workers, 0, &taskmgr) == ISC_R_SUCCESS); task = NULL; RUNTIME_CHECK(isc_task_create(taskmgr, 0, &task) == ISC_R_SUCCESS); isc_task_setname(task, "byname", NULL); dispatchmgr = NULL; RUNTIME_CHECK(dns_dispatchmgr_create(mctx, NULL, &dispatchmgr) == ISC_R_SUCCESS); timermgr = NULL; RUNTIME_CHECK(isc_timermgr_create(mctx, &timermgr) == ISC_R_SUCCESS); socketmgr = NULL; RUNTIME_CHECK(isc_socketmgr_create(mctx, &socketmgr) == ISC_R_SUCCESS); cache = NULL; RUNTIME_CHECK(dns_cache_create(mctx, taskmgr, timermgr, dns_rdataclass_in, "rbt", 0, NULL, &cache) == ISC_R_SUCCESS); view = NULL; RUNTIME_CHECK(dns_view_create(mctx, dns_rdataclass_in, "default", &view) == ISC_R_SUCCESS); { unsigned int attrs; dns_dispatch_t *disp4 = NULL; dns_dispatch_t *disp6 = NULL; if (isc_net_probeipv4() == ISC_R_SUCCESS) { isc_sockaddr_t any4; isc_sockaddr_any(&any4); attrs = DNS_DISPATCHATTR_IPV4 | DNS_DISPATCHATTR_UDP; RUNTIME_CHECK(dns_dispatch_getudp(dispatchmgr, socketmgr, taskmgr, &any4, 512, 6, 1024, 17, 19, attrs, attrs, &disp4) == ISC_R_SUCCESS); INSIST(disp4 != NULL); } if (isc_net_probeipv6() == ISC_R_SUCCESS) { isc_sockaddr_t any6; isc_sockaddr_any6(&any6); attrs = DNS_DISPATCHATTR_IPV6 | DNS_DISPATCHATTR_UDP; RUNTIME_CHECK(dns_dispatch_getudp(dispatchmgr, socketmgr, taskmgr, &any6, 512, 6, 1024, 17, 19, attrs, attrs, &disp6) == ISC_R_SUCCESS); INSIST(disp6 != NULL); } RUNTIME_CHECK(dns_view_createresolver(view, taskmgr, 10, 1, socketmgr, timermgr, 0, dispatchmgr, disp4, disp6) == ISC_R_SUCCESS); if (disp4 != NULL) dns_dispatch_detach(&disp4); if (disp6 != NULL) dns_dispatch_detach(&disp6); } { struct in_addr ina; isc_sockaddr_t sa; isc_sockaddrlist_t sal; ISC_LIST_INIT(sal); ina.s_addr = inet_addr("127.0.0.1"); isc_sockaddr_fromin(&sa, &ina, 53); ISC_LIST_APPEND(sal, &sa, link); RUNTIME_CHECK(dns_fwdtable_add(view->fwdtable, dns_rootname, &sal, dns_fwdpolicy_only) == ISC_R_SUCCESS); } dns_view_setcache(view, cache); dns_view_freeze(view); dns_cache_detach(&cache); printf("name = %s\n", argv[isc_commandline_index]); isc_buffer_init(&b, argv[isc_commandline_index], strlen(argv[isc_commandline_index])); isc_buffer_add(&b, strlen(argv[isc_commandline_index])); dns_fixedname_init(&fixed); dns_fixedname_init(&target); RUNTIME_CHECK(dns_name_fromtext(dns_fixedname_name(&fixed), &b, dns_rootname, 0, NULL) == ISC_R_SUCCESS); RUNTIME_CHECK(isc_app_onrun(mctx, task, run, NULL) == ISC_R_SUCCESS); (void)isc_app_run(); dns_view_detach(&view); isc_task_shutdown(task); isc_task_detach(&task); dns_dispatchmgr_destroy(&dispatchmgr); isc_taskmgr_destroy(&taskmgr); isc_socketmgr_destroy(&socketmgr); isc_timermgr_destroy(&timermgr); isc_log_destroy(&lctx); isc_hash_destroy(); isc_entropy_detach(&ectx); if (verbose) isc_mem_stats(mctx, stdout); isc_mem_destroy(&mctx); isc_app_finish(); return (0); } bind9-9.11.3+dfsg/bin/tests/cfg_test.c000066400000000000000000000106411325250447100174120ustar00rootroot00000000000000/* * Copyright (C) 2001, 2002, 2004, 2005, 2007, 2009-2011, 2015, 2016, 2018 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* $Id: cfg_test.c,v 1.25 2011/09/05 23:46:54 tbox Exp $ */ /*! \file */ #include #include #include #include #include #include #include #include #include #include static void check_result(isc_result_t result, const char *format, ...) { va_list args; if (result == ISC_R_SUCCESS) return; va_start(args, format); vfprintf(stderr, format, args); va_end(args); fprintf(stderr, ": %s\n", isc_result_totext(result)); exit(1); } static void output(void *closure, const char *text, int textlen) { UNUSED(closure); (void) fwrite(text, 1, textlen, stdout); } static void usage(void) { fprintf(stderr, "usage: cfg_test --rndc|--named " "[--grammar] [--memstats] conffile\n"); exit(1); } int main(int argc, char **argv) { isc_result_t result; isc_mem_t *mctx = NULL; isc_log_t *lctx = NULL; isc_logconfig_t *lcfg = NULL; isc_logdestination_t destination; cfg_parser_t *pctx = NULL; cfg_obj_t *cfg = NULL; cfg_type_t *type = NULL; isc_boolean_t grammar = ISC_FALSE; isc_boolean_t memstats = ISC_FALSE; char *filename = NULL; unsigned int zonetype = 0; RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS); result = isc_log_create(mctx, &lctx, &lcfg); check_result(result, "isc_log_create()"); isc_log_setcontext(lctx); /* * Create and install the default channel. */ destination.file.stream = stderr; destination.file.name = NULL; destination.file.versions = ISC_LOG_ROLLNEVER; destination.file.maximum_size = 0; result = isc_log_createchannel(lcfg, "_default", ISC_LOG_TOFILEDESC, ISC_LOG_DYNAMIC, &destination, ISC_LOG_PRINTTIME); check_result(result, "isc_log_createchannel()"); result = isc_log_usechannel(lcfg, "_default", NULL, NULL); check_result(result, "isc_log_usechannel()"); /* * Set the initial debug level. */ isc_log_setdebuglevel(lctx, 2); if (argc < 3) usage(); while (argc > 1) { if (strcmp(argv[1], "--grammar") == 0) { grammar = ISC_TRUE; } else if (strcmp(argv[1], "--zonegrammar") == 0) { argv++, argc--; if (argc <= 1) { usage(); } if (strcmp(argv[1], "master") == 0 || strcmp(argv[1], "primary") == 0) { zonetype = CFG_ZONE_MASTER; } else if (strcmp(argv[1], "slave") == 0 || strcmp(argv[1], "seconary") == 0) { zonetype = CFG_ZONE_SLAVE; } else if (strcmp(argv[1], "stub") == 0) { zonetype = CFG_ZONE_STUB; } else if (strcmp(argv[1], "static-stub") == 0) { zonetype = CFG_ZONE_STATICSTUB; } else if (strcmp(argv[1], "hint") == 0) { zonetype = CFG_ZONE_HINT; } else if (strcmp(argv[1], "forward") == 0) { zonetype = CFG_ZONE_FORWARD; } else if (strcmp(argv[1], "redirect") == 0) { zonetype = CFG_ZONE_REDIRECT; } else if (strcmp(argv[1], "delegation-only") == 0) { zonetype = CFG_ZONE_DELEGATION; } else if (strcmp(argv[1], "in-view") == 0) { zonetype = CFG_ZONE_INVIEW; } else { usage(); } } else if (strcmp(argv[1], "--memstats") == 0) { memstats = ISC_TRUE; } else if (strcmp(argv[1], "--named") == 0) { type = &cfg_type_namedconf; } else if (strcmp(argv[1], "--rndc") == 0) { type = &cfg_type_rndcconf; } else if (argv[1][0] == '-') { usage(); } else { filename = argv[1]; } argv++, argc--; } if (grammar) { if (type == NULL) usage(); cfg_print_grammar(type, output, NULL); } else if (zonetype != 0) { cfg_print_zonegrammar(zonetype, output, NULL); } else { if (type == NULL || filename == NULL) usage(); RUNTIME_CHECK(cfg_parser_create(mctx, lctx, &pctx) == ISC_R_SUCCESS); result = cfg_parse_file(pctx, filename, type, &cfg); fprintf(stderr, "read config: %s\n", isc_result_totext(result)); if (result != ISC_R_SUCCESS) exit(1); cfg_print(cfg, output, NULL); cfg_obj_destroy(pctx, &cfg); cfg_parser_destroy(&pctx); } isc_log_destroy(&lctx); if (memstats) isc_mem_stats(mctx, stderr); isc_mem_destroy(&mctx); fflush(stdout); if (ferror(stdout)) { fprintf(stderr, "write error\n"); return (1); } else return (0); } bind9-9.11.3+dfsg/bin/tests/db/000077500000000000000000000000001325250447100160335ustar00rootroot00000000000000bind9-9.11.3+dfsg/bin/tests/db/Makefile.in000066400000000000000000000024611325250447100201030ustar00rootroot00000000000000# Copyright (C) 1999-2002, 2004, 2007, 2009, 2010, 2012, 2014, 2016 Internet Systems Consortium, Inc. ("ISC") # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. # $Id: Makefile.in,v 1.34 2010/08/13 23:47:03 tbox Exp $ srcdir = @srcdir@ VPATH = @srcdir@ top_srcdir = @top_srcdir@ @BIND9_MAKE_INCLUDES@ CINCLUDES = ${TEST_INCLUDES} ${DNS_INCLUDES} \ ${ISC_INCLUDES} @DST_OPENSSL_INC@ CDEFINES = @CRYPTO@ CWARNINGS = DNSLIBS = ../../../lib/dns/libdns.@A@ @DNS_CRYPTO_LIBS@ ISCLIBS = ../../../lib/isc/libisc.@A@ ISCCFGLIBS = ../../../lib/isccfg/libisccfg.@A@ DNSDEPLIBS = ../../../lib/dns/libdns.@A@ ISCDEPLIBS = ../../../lib/isc/libisc.@A@ ISCCFGDEPLIBS = ../../../lib/isccfg/libisccfg.@A@ DEPLIBS = ${DNSDEPLIBS} ${ISCCFGDEPLIBS} ${ISCDEPLIBS} LIBS = ${DNSLIBS} ${ISCCFGLIBS} ${ISCLIBS} @LIBS@ TLIB = ../../../lib/tests/libt_api.@A@ SRCS = t_db.c TARGETS = t_db@EXEEXT@ @BIND9_MAKE_RULES@ t_db@EXEEXT@: t_db.@O@ ${DEPLIBS} ${TLIB} ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ t_db.@O@ ${TLIB} ${LIBS} test: t_db@EXEEXT@ -@./t_db@EXEEXT@ -c @top_srcdir@/t_config -b @srcdir@ -a testhelp: @./t_db -h clean distclean:: rm -f ${TARGETS} bind9-9.11.3+dfsg/bin/tests/db/dns_db_class_1.data000066400000000000000000000003601325250447100215230ustar00rootroot00000000000000$TTL 1000 @ in soa localhost. postmaster.localhost. ( 1993050801 ;serial 3600 ;refresh 1800 ;retry 604800 ;expiration 3600 ) ;minimum a in ns ns.vix.com. a in ns ns2.vix.com. a in ns ns3.vix.com. b in a 1.2.3.4 bind9-9.11.3+dfsg/bin/tests/db/dns_db_class_data000066400000000000000000000001611325250447100213630ustar00rootroot00000000000000# # test data for dns_db_class # # format: # filename class # # dns_db_class_1.data in # dns_db_class_1.data any bind9-9.11.3+dfsg/bin/tests/db/dns_db_closeversion_1.data000066400000000000000000000003601325250447100231310ustar00rootroot00000000000000$TTL 1000 @ in soa localhost. postmaster.localhost. ( 1993050801 ;serial 3600 ;refresh 1800 ;retry 604800 ;expiration 3600 ) ;minimum a in ns ns.vix.com. a in ns ns2.vix.com. a in ns ns3.vix.com. b in a 1.2.3.4 bind9-9.11.3+dfsg/bin/tests/db/dns_db_closeversion_1_data000066400000000000000000000003331325250447100232120ustar00rootroot00000000000000# # test data for dns_db_closeversion test 1 # # format: # filename type origin class cache new_name new_type existing_name existing_type # dns_db_closeversion_1.data rbt vix.com. in zone a.b.c.vix.com. A a.vix.com. NS bind9-9.11.3+dfsg/bin/tests/db/dns_db_closeversion_2.data000066400000000000000000000003601325250447100231320ustar00rootroot00000000000000$TTL 1000 @ in soa localhost. postmaster.localhost. ( 1993050801 ;serial 3600 ;refresh 1800 ;retry 604800 ;expiration 3600 ) ;minimum a in ns ns.vix.com. a in ns ns2.vix.com. a in ns ns3.vix.com. b in a 1.2.3.4 bind9-9.11.3+dfsg/bin/tests/db/dns_db_closeversion_2_data000066400000000000000000000003331325250447100232130ustar00rootroot00000000000000# # test data for dns_db_closeversion test 2 # # format: # filename type origin class cache new_name new_type existing_name existing_type # dns_db_closeversion_1.data rbt vix.com. in zone a.b.c.vix.com. A a.vix.com. NS bind9-9.11.3+dfsg/bin/tests/db/dns_db_currentversion.data000066400000000000000000000003651325250447100232730ustar00rootroot00000000000000$TTL 1000 @ in soa localhost. postmaster.localhost. ( 1993050801 ;serial 3600 ;refresh 1800 ;retry 604800 ;expiration 3600 ) ;minimum a.b.c.vix.com. a 1.2.3.4 a in ns ns2.vix.com. a in ns ns3.vix.com. b in a 1.2.3.4 bind9-9.11.3+dfsg/bin/tests/db/dns_db_currentversion_data000066400000000000000000000002241325250447100233460ustar00rootroot00000000000000# # test data for dns_db_currentversion # # format: # filename findname findtype # dns_db_currentversion.data rbt vix.com. IN zone a.b.c.vix.com. A bind9-9.11.3+dfsg/bin/tests/db/dns_db_expirenode.data000066400000000000000000000003601325250447100223400ustar00rootroot00000000000000$TTL 1000 @ in soa localhost. postmaster.localhost. ( 1993050801 ;serial 3600 ;refresh 1800 ;retry 604800 ;expiration 3600 ) ;minimum a in ns ns.vix.com. a in ns ns2.vix.com. a in ns ns3.vix.com. b in a 1.2.3.4 bind9-9.11.3+dfsg/bin/tests/db/dns_db_expirenode_data000066400000000000000000000002641325250447100224240ustar00rootroot00000000000000# # test data for dns_db_expirenode # # format: # filename type origin class existing_name existing_type # dns_db_expirenode.data rbt vix.com. in a.vix.com. 10000 0 ISC_R_NOTFOUND bind9-9.11.3+dfsg/bin/tests/db/dns_db_find_1.data000066400000000000000000000003771325250447100213460ustar00rootroot00000000000000$TTL 1000 @ in soa localhost. postmaster.localhost. ( 1993050801 ;serial 3600 ;refresh 1800 ;retry 604800 ;expiration 3600 ) ;minimum a in ns ns.vix.com. a in ns ns2.vix.com. a in ns ns3.vix.com. b in a 1.2.3.4 a.b.c in ns b bind9-9.11.3+dfsg/bin/tests/db/dns_db_find_10.data000066400000000000000000000003161325250447100214170ustar00rootroot00000000000000$TTL 1000 @ in soa localhost. postmaster.localhost. ( 1993050801 ;serial 3600 ;refresh 1800 ;retry 604800 ;expiration 3600 ) ;minimum a.b.c in NS ns1.vix.com. a.b.c in A 1.2.3.4 bind9-9.11.3+dfsg/bin/tests/db/dns_db_find_10_data000066400000000000000000000005031325250447100214760ustar00rootroot00000000000000# # test data for dns_db_find expiration time handling # # format: # dbfile dbtype dborigin dbclass dbcache findname findtype findopts findtime expected_results # dns_db_find_10.data rbt vix.com. in cache a.b.c.vix.com. NS 0 1010 ISC_R_NOTFOUND dns_db_find_10.data rbt vix.com. in cache a.b.c.vix.com. NS 0 0 ISC_R_SUCCESS bind9-9.11.3+dfsg/bin/tests/db/dns_db_find_1_data000066400000000000000000000003601325250447100214170ustar00rootroot00000000000000# # test data for dns_db_find best match # # format: # dbfile dbtype dborigin dbclass dbcache findname findtype findopts findtime expected_results # dns_db_find_1.data rbt vix.com. in zone a.b.c.vix.com. NS DNS_DB_GLUEOK 0 DNS_R_DELEGATION bind9-9.11.3+dfsg/bin/tests/db/dns_db_find_2.data000066400000000000000000000003121325250447100213340ustar00rootroot00000000000000$TTL 1000 @ in soa localhost. postmaster.localhost. ( 1993050801 ;serial 3600 ;refresh 1800 ;retry 604800 ;expiration 3600 ) ;minimum fx in ns a.fx.vix.com. a.fx in a 1.2.3.4 bind9-9.11.3+dfsg/bin/tests/db/dns_db_find_2_data000066400000000000000000000006401325250447100214210ustar00rootroot00000000000000# # test data for dns_db_find DNS_R_GLUE # # format: # dbfile dbtype dborigin dbclass dbcache findname findtype findopts findtime expected_results # dns_db_find_2.data rbt vix.com. in zone a.fx.vix.com. A DNS_DBFIND_GLUEOK 0 DNS_R_GLUE dns_db_find_2.data rbt vix.com. in zone fx.vix.com. NS DNS_DBFIND_GLUEOK 0 DNS_R_GLUE dns_db_find_2.data rbt vix.com. in zone a.fx.vix.com. NS DNS_DBFIND_GLUEOK 0 DNS_R_DELEGATION bind9-9.11.3+dfsg/bin/tests/db/dns_db_find_3.data000066400000000000000000000003261325250447100213420ustar00rootroot00000000000000$TTL 1000 @ in soa localhost. postmaster.localhost. ( 1993050801 ;serial 3600 ;refresh 1800 ;retry 604800 ;expiration 3600 ) ;minimum a.b.c in ns b a.a.b.c in a 10.0.0.1 b in a 10.0.0.2 bind9-9.11.3+dfsg/bin/tests/db/dns_db_find_3_data000066400000000000000000000006571325250447100214320ustar00rootroot00000000000000# # test data for dns_db_find DNS_R_DELAGATION # # format: # dbfile dbtype dborigin dbclass dbcache findname findtype findopts findtime expected_results # dns_db_find_3.data rbt vix.com. in zone a.b.c.vix.com. NS DNS_DB_GLUEOK 0 DNS_R_DELEGATION dns_db_find_3.data rbt vix.com. in zone a.a.b.c.vix.com. NS DNS_DB_GLUEOK 0 DNS_R_DELEGATION dns_db_find_3.data rbt vix.com. in zone a.a.b.c.vix.com. A DNS_DB_GLUEOK 0 DNS_R_DELEGATION bind9-9.11.3+dfsg/bin/tests/db/dns_db_find_4.data000066400000000000000000000003051325250447100213400ustar00rootroot00000000000000$TTL 1000 @ in soa localhost. postmaster.localhost. ( 1993050801 ;serial 3600 ;refresh 1800 ;retry 604800 ;expiration 3600 ) ;minimum a.b.c in ns b b.a.b.c in a 10.0.0.2 bind9-9.11.3+dfsg/bin/tests/db/dns_db_find_4_data000066400000000000000000000003531325250447100214240ustar00rootroot00000000000000# # test data for dns_db_find DNS_R_DELEGATION # # format: # dbfile dbtype dborigin dbclass dbcache findname findtype findopts findtime expected_results # dns_db_find_4.data rbt vix.com. in zone a.b.c.vix.com. ANY 0 0 DNS_R_DELEGATION bind9-9.11.3+dfsg/bin/tests/db/dns_db_find_5.data000066400000000000000000000003141325250447100213410ustar00rootroot00000000000000$TTL 1000 @ in soa localhost. postmaster.localhost. ( 1993050801 ;serial 3600 ;refresh 1800 ;retry 604800 ;expiration 3600 ) ;minimum a.b.c in DNAME x.y.z a.x.y.z in A 1.2.3.4 bind9-9.11.3+dfsg/bin/tests/db/dns_db_find_5_data000066400000000000000000000004601325250447100214240ustar00rootroot00000000000000# # test data for dns_db_find DNS_R_DNAME # # format: # dbfile dbtype dborigin dbclass dbcache findname findtype findopts findtime expected_results # dns_db_find_5.data rbt vix.com. in zone x.a.b.c.vix.com. ANY 0 0 DNS_R_DNAME dns_db_find_5.data rbt vix.com. in zone a.a.b.c.vix.com. ANY 0 0 DNS_R_DNAME bind9-9.11.3+dfsg/bin/tests/db/dns_db_find_6.data000066400000000000000000000003061325250447100213430ustar00rootroot00000000000000$TTL 1000 @ in soa localhost. postmaster.localhost. ( 1993050801 ;serial 3600 ;refresh 1800 ;retry 604800 ;expiration 3600 ) ;minimum exploder in CNAME mx mx in A 1.2.3.4 bind9-9.11.3+dfsg/bin/tests/db/dns_db_find_6_data000066400000000000000000000004621325250447100214270ustar00rootroot00000000000000# # test data for dns_db_find DNS_R_CNAME # # format: # dbfile dbtype dborigin dbclass dbcache findname findtype findopts findtime expected_results # dns_db_find_6.data rbt vix.com. in zone exploder.vix.com. A 0 0 DNS_R_CNAME dns_db_find_6.data rbt vix.com. in zone exploder.vix.com. ANY 0 0 ISC_R_SUCCESS bind9-9.11.3+dfsg/bin/tests/db/dns_db_find_7.data000066400000000000000000000003371325250447100213500ustar00rootroot00000000000000$TTL 1000 @ in soa localhost. postmaster.localhost. ( 1993050801 ;serial 3600 ;refresh 1800 ;retry 604800 ;expiration 3600 ) ;minimum a.b.c.d in A 1.2.3.4 a.b in A 1.2.3.4 a in NS ns1.vix.com. bind9-9.11.3+dfsg/bin/tests/db/dns_db_find_7_data000066400000000000000000000003471325250447100214320ustar00rootroot00000000000000# # test data for dns_db_find DNS_R_NXDOMAIN # # format: # dbfile dbtype dborigin dbclass dbcache findname findtype findopts findtime expected_results # dns_db_find_7.data rbt vix.com. in zone a.b.c.vix.com. ANY 0 0 DNS_R_NXDOMAIN bind9-9.11.3+dfsg/bin/tests/db/dns_db_find_8.data000066400000000000000000000003631325250447100213500ustar00rootroot00000000000000$TTL 1000 @ in soa localhost. postmaster.localhost. ( 1993050801 ;serial 3600 ;refresh 1800 ;retry 604800 ;expiration 3600 ) ;minimum a.b.c.d in A 1.2.3.4 a.b.c in A 1.2.3.4 a.b in A 1.2.3.4 a in NS ns1.vix.com. bind9-9.11.3+dfsg/bin/tests/db/dns_db_find_8_data000066400000000000000000000003441325250447100214300ustar00rootroot00000000000000# # test data for dns_db_find DNS_R_NXRRSET # # format: # dbfile dbtype dborigin dbclass dbcache findname findtype findopts findtime expected_results # dns_db_find_8.data rbt vix.com. in zone a.b.c.vix.com. NS 0 0 DNS_R_NXRRSET bind9-9.11.3+dfsg/bin/tests/db/dns_db_find_9.data000066400000000000000000000003771325250447100213560ustar00rootroot00000000000000$TTL 1000 @ in soa localhost. postmaster.localhost. ( 1993050801 ;serial 3600 ;refresh 1800 ;retry 604800 ;expiration 3600 ) ;minimum a.b.c.d in NS ns1.vix.com. a.b.c in A 1.2.3.4 a.b in NS ns1.vix.com. a in NS ns1.vix.com. bind9-9.11.3+dfsg/bin/tests/db/dns_db_find_9_data000066400000000000000000000003471325250447100214340ustar00rootroot00000000000000# # test data for dns_db_find ISC_R_NOTFOUND # # format: # dbfile dbtype dborigin dbclass dbcache findname findtype findopts findtime expected_results # dns_db_find_9.data rbt vix.com. in cache a.b.c.vix.com. NS 0 0 ISC_R_NOTFOUND bind9-9.11.3+dfsg/bin/tests/db/dns_db_findnode_1.data000066400000000000000000000003601325250447100222040ustar00rootroot00000000000000$TTL 1000 @ in soa localhost. postmaster.localhost. ( 1993050801 ;serial 3600 ;refresh 1800 ;retry 604800 ;expiration 3600 ) ;minimum a in ns ns.vix.com. a in ns ns2.vix.com. a in ns ns3.vix.com. b in a 1.2.3.4 bind9-9.11.3+dfsg/bin/tests/db/dns_db_findnode_1_data000066400000000000000000000005251325250447100222700ustar00rootroot00000000000000# # test data for dns_db_findnode, case ISC_R_SUCCESS # # format: # filename type origin class cache existingname rdatatype # dns_db_findnode_1.data rbt vix.com. in zone a.vix.com. NS ISC_R_SUCCESS dns_db_findnode_1.data rbt vix.com. in zone b.vix.com. A ISC_R_SUCCESS dns_db_findnode_1.data rbt vix.com. in zone c.vix.com. A ISC_R_NOTFOUND bind9-9.11.3+dfsg/bin/tests/db/dns_db_findnode_2.data000066400000000000000000000003601325250447100222050ustar00rootroot00000000000000$TTL 1000 @ in soa localhost. postmaster.localhost. ( 1993050801 ;serial 3600 ;refresh 1800 ;retry 604800 ;expiration 3600 ) ;minimum a in ns ns.vix.com. a in ns ns2.vix.com. a in ns ns3.vix.com. b in a 1.2.3.4 bind9-9.11.3+dfsg/bin/tests/db/dns_db_findnode_2_data000066400000000000000000000002301325250447100222620ustar00rootroot00000000000000# # test data for dns_db_findnode 2 # # format: # filename type origin class cache newname # dns_db_findnode_2.data rbt vix.com. in zone a.b.c.vix.com. bind9-9.11.3+dfsg/bin/tests/db/dns_db_iscache_1.data000066400000000000000000000003601325250447100220150ustar00rootroot00000000000000$TTL 1000 @ in soa localhost. postmaster.localhost. ( 1993050801 ;serial 3600 ;refresh 1800 ;retry 604800 ;expiration 3600 ) ;minimum a in ns ns.vix.com. a in ns ns2.vix.com. a in ns ns3.vix.com. b in a 1.2.3.4 bind9-9.11.3+dfsg/bin/tests/db/dns_db_iscache_1_data000066400000000000000000000001651325250447100221010ustar00rootroot00000000000000# # test data for dns_db_iscache test 1 # # format: # filename db_type origin class # dns_db_iscache_1.data rbt . in bind9-9.11.3+dfsg/bin/tests/db/dns_db_iscache_2.data000066400000000000000000000003601325250447100220160ustar00rootroot00000000000000$TTL 1000 @ in soa localhost. postmaster.localhost. ( 1993050801 ;serial 3600 ;refresh 1800 ;retry 604800 ;expiration 3600 ) ;minimum a in ns ns.vix.com. a in ns ns2.vix.com. a in ns ns3.vix.com. b in a 1.2.3.4 bind9-9.11.3+dfsg/bin/tests/db/dns_db_iscache_2_data000066400000000000000000000001651325250447100221020ustar00rootroot00000000000000# # test data for dns_db_iscache test 1 # # format: # filename db_type origin class # dns_db_iscache_2.data rbt . in bind9-9.11.3+dfsg/bin/tests/db/dns_db_iszone_1.data000066400000000000000000000003601325250447100217250ustar00rootroot00000000000000$TTL 1000 @ in soa localhost. postmaster.localhost. ( 1993050801 ;serial 3600 ;refresh 1800 ;retry 604800 ;expiration 3600 ) ;minimum a in ns ns.vix.com. a in ns ns2.vix.com. a in ns ns3.vix.com. b in a 1.2.3.4 bind9-9.11.3+dfsg/bin/tests/db/dns_db_iszone_1_data000066400000000000000000000001631325250447100220070ustar00rootroot00000000000000# # test data for dns_db_iszone test 1 # # format: # filename db_type origin class # dns_db_iszone_1.data rbt . in bind9-9.11.3+dfsg/bin/tests/db/dns_db_iszone_2.data000066400000000000000000000003601325250447100217260ustar00rootroot00000000000000$TTL 1000 @ in soa localhost. postmaster.localhost. ( 1993050801 ;serial 3600 ;refresh 1800 ;retry 604800 ;expiration 3600 ) ;minimum a in ns ns.vix.com. a in ns ns2.vix.com. a in ns ns3.vix.com. b in a 1.2.3.4 bind9-9.11.3+dfsg/bin/tests/db/dns_db_iszone_2_data000066400000000000000000000001631325250447100220100ustar00rootroot00000000000000# # test data for dns_db_iszone test 2 # # format: # filename db_type origin class # dns_db_iszone_2.data rbt . in bind9-9.11.3+dfsg/bin/tests/db/dns_db_load_1.data000066400000000000000000000003601325250447100213350ustar00rootroot00000000000000$TTL 1000 @ in soa localhost. postmaster.localhost. ( 1993050801 ;serial 3600 ;refresh 1800 ;retry 604800 ;expiration 3600 ) ;minimum a in ns ns.vix.com. a in ns ns2.vix.com. a in ns ns3.vix.com. b in a 1.2.3.4 bind9-9.11.3+dfsg/bin/tests/db/dns_db_load_25.data000066400000000000000000000002351325250447100214240ustar00rootroot00000000000000$TTL 5 @ IN SOA ns1 hostmaster 1 3600 1200 3600000 3600 @ IN NS ns1 ns1 IN A 10.0.0.1 sub IN SOA ns2 hostmaster 1 3600 1200 3600000 3600 ns2 IN A 10.0.0.2 bind9-9.11.3+dfsg/bin/tests/db/dns_db_load_data000066400000000000000000000002551325250447100212010ustar00rootroot00000000000000# # test data for dns_db_load # # format: # filename type origin cache class findname expected_result # dns_db_load_1.data rbt . zone in ISC_R_SUCCESS a. A DNS_R_DELEGATION bind9-9.11.3+dfsg/bin/tests/db/dns_db_load_soa_not_top000066400000000000000000000002751325250447100226160ustar00rootroot00000000000000# # test data for dns_db_load_soa_not_top # # format: # filename type origin cache class findname expected_result # dns_db_load_25.data rbt . zone in DNS_R_NOTZONETOP a. A DNS_R_DELEGATION bind9-9.11.3+dfsg/bin/tests/db/dns_db_newversion.data000066400000000000000000000003601325250447100223750ustar00rootroot00000000000000$TTL 1000 @ in soa localhost. postmaster.localhost. ( 1993050801 ;serial 3600 ;refresh 1800 ;retry 604800 ;expiration 3600 ) ;minimum a in ns ns.vix.com. a in ns ns2.vix.com. a in ns ns3.vix.com. b in a 1.2.3.4 bind9-9.11.3+dfsg/bin/tests/db/dns_db_newversion_data000066400000000000000000000002421325250447100224550ustar00rootroot00000000000000# # test data for dns_db_newversion # # format: # filename type origin class cache newname newtype # dns_db_newversion.data rbt vix.com. in zone a.b.c.vix.com. A bind9-9.11.3+dfsg/bin/tests/db/dns_db_origin_1.data000066400000000000000000000003601325250447100217050ustar00rootroot00000000000000$TTL 1000 @ in soa localhost. postmaster.localhost. ( 1993050801 ;serial 3600 ;refresh 1800 ;retry 604800 ;expiration 3600 ) ;minimum a in ns ns.vix.com. a in ns ns2.vix.com. a in ns ns3.vix.com. b in a 1.2.3.4 bind9-9.11.3+dfsg/bin/tests/db/dns_db_origin_data000066400000000000000000000001651325250447100215510ustar00rootroot00000000000000# # test data for dns_db_origin # # format: # filename origin # dns_db_origin_1.data . dns_db_origin_1.data vix.com. bind9-9.11.3+dfsg/bin/tests/db/t_db.c000066400000000000000000002322021325250447100171100ustar00rootroot00000000000000/* * Copyright (C) 1999-2001, 2004, 2005, 2007, 2009, 2011-2013, 2015-2017 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* $Id: t_db.c,v 1.41 2011/03/12 04:59:46 tbox Exp $ */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static isc_result_t t_create(const char *db_type, const char *origin, const char *classname, const char *model, isc_mem_t *mctx, dns_db_t **db) { int len; isc_result_t dns_result; dns_dbtype_t dbtype; isc_textregion_t region; isc_buffer_t origin_buffer; dns_fixedname_t dns_origin; dns_rdataclass_t rdataclass; dbtype = dns_dbtype_zone; if (strcasecmp(model, "cache") == 0) dbtype = dns_dbtype_cache; dns_fixedname_init(&dns_origin); len = strlen(origin); isc_buffer_constinit(&origin_buffer, origin, len); isc_buffer_add(&origin_buffer, len); dns_result = dns_name_fromtext(dns_fixedname_name(&dns_origin), &origin_buffer, NULL, 0, NULL); if (dns_result != ISC_R_SUCCESS) { t_info("dns_name_fromtext failed %s\n", dns_result_totext(dns_result)); return(dns_result); } DE_CONST(classname, region.base); region.length = strlen(classname); dns_result = dns_rdataclass_fromtext(&rdataclass, ®ion); if (dns_result != ISC_R_SUCCESS) { t_info("dns_rdataclass_fromtext failed %s\n", dns_result_totext(dns_result)); return(dns_result); } dns_result = dns_db_create(mctx, db_type, dns_fixedname_name(&dns_origin), dbtype, rdataclass, 0, NULL, db); if (dns_result != ISC_R_SUCCESS) t_info("dns_db_create failed %s\n", dns_result_totext(dns_result)); return(dns_result); } static int t_dns_db_load(char **av) { char *filename; char *db_type; char *origin; char *model; char *db_class; char *expected_load_result; char *findname; char *find_type; char *expected_find_result; int result; int len; dns_db_t *db; isc_result_t dns_result; isc_result_t isc_result; isc_mem_t *mctx; isc_entropy_t *ectx; dns_dbnode_t *nodep; isc_textregion_t textregion; isc_buffer_t findname_buffer; dns_fixedname_t dns_findname; dns_fixedname_t dns_foundname; dns_rdataset_t rdataset; dns_rdatatype_t rdatatype; dns_dbversion_t *versionp; isc_result_t exp_load_result; isc_result_t exp_find_result; db = NULL; mctx = NULL; ectx = NULL; filename = T_ARG(0); db_type = T_ARG(1); origin = T_ARG(2); model = T_ARG(3); db_class = T_ARG(4); expected_load_result = T_ARG(5); findname = T_ARG(6); find_type = T_ARG(7); expected_find_result = T_ARG(8); t_info("testing using file %s and name %s\n", filename, findname); exp_load_result = t_dns_result_fromtext(expected_load_result); exp_find_result = t_dns_result_fromtext(expected_find_result); isc_result = isc_mem_create(0, 0, &mctx); if (isc_result != ISC_R_SUCCESS) { t_info("isc_mem_create failed %s\n", isc_result_totext(isc_result)); return(T_UNRESOLVED); } isc_result = isc_entropy_create(mctx, &ectx); if (isc_result != ISC_R_SUCCESS) { t_info("isc_entropy_create failed %s\n", isc_result_totext(isc_result)); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } isc_result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE); if (isc_result != ISC_R_SUCCESS) { t_info("isc_hash_create failed %s\n", isc_result_totext(isc_result)); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } dns_result = t_create(db_type, origin, db_class, model, mctx, &db); if (dns_result != ISC_R_SUCCESS) { isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } dns_result = dns_db_load(db, filename); if (dns_result != exp_load_result) { t_info("dns_db_load returned %s, expected %s\n", dns_result_totext(dns_result), dns_result_totext(exp_load_result)); dns_db_detach(&db); isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(T_FAIL); } if (dns_result != ISC_R_SUCCESS) { result = T_PASS; goto cleanup_db; } dns_fixedname_init(&dns_findname); len = strlen(findname); isc_buffer_init(&findname_buffer, findname, len); isc_buffer_add(&findname_buffer, len); dns_result = dns_name_fromtext(dns_fixedname_name(&dns_findname), &findname_buffer, NULL, 0, NULL); if (dns_result != ISC_R_SUCCESS) { t_info("dns_name_fromtext failed %s\n", dns_result_totext(dns_result)); dns_db_detach(&db); isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } textregion.base = find_type; textregion.length = strlen(find_type); dns_result = dns_rdatatype_fromtext(&rdatatype, &textregion); if (dns_result != ISC_R_SUCCESS) { t_info("dns_rdatatype_fromtext %s failed %s\n", find_type, dns_result_totext(dns_result)); dns_db_detach(&db); isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } versionp = NULL; dns_fixedname_init(&dns_foundname); dns_rdataset_init(&rdataset); if (dns_db_iszone(db)) dns_db_currentversion(db, &versionp); nodep = NULL; dns_result = dns_db_find(db, dns_fixedname_name(&dns_findname), versionp, rdatatype, DNS_DBFIND_GLUEOK, 0, &nodep, dns_fixedname_name(&dns_foundname), &rdataset, NULL); if (dns_result != exp_find_result) { t_info("dns_db_find returned %s, expected %s\n", dns_result_totext(dns_result), dns_result_totext(exp_find_result)); result = T_FAIL; } else { result = T_PASS; } if (dns_result != ISC_R_NOTFOUND) { dns_db_detachnode(db, &nodep); if (dns_rdataset_isassociated(&rdataset)) dns_rdataset_disassociate(&rdataset); } if (dns_db_iszone(db)) dns_db_closeversion(db, &versionp, ISC_FALSE); cleanup_db: dns_db_detach(&db); isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(result); } static const char *a1 = "A call to dns_db_load(db, filename) loads the contents of " "the database in filename into db."; static void t1(void) { int result; t_assert("dns_db_load", 1, T_REQUIRED, "%s", a1); result = t_eval("dns_db_load_data", t_dns_db_load, 9); t_result(result); } static const char *a2 = "When the database db has cache semantics, a call to " "dns_db_iscache(db) returns ISC_TRUE."; static int t_dns_db_zc_x(char *filename, char *db_type, char *origin, char *db_class, dns_dbtype_t dbtype, isc_boolean_t(*cf)(dns_db_t *), isc_boolean_t exp_result) { int result; int len; dns_db_t *db; isc_result_t dns_result; isc_result_t isc_result; isc_mem_t *mctx; isc_entropy_t *ectx; dns_rdataclass_t rdataclass; isc_textregion_t textregion; isc_buffer_t origin_buffer; dns_fixedname_t dns_origin; db = NULL; mctx = NULL; ectx = NULL; t_info("testing using file %s\n", filename); dns_fixedname_init(&dns_origin); len = strlen(origin); isc_buffer_init(&origin_buffer, origin, len); isc_buffer_add(&origin_buffer, len); dns_result = dns_name_fromtext(dns_fixedname_name(&dns_origin), &origin_buffer, NULL, 0, NULL); if (dns_result != ISC_R_SUCCESS) { t_info("dns_name_fromtext failed %s\n", dns_result_totext(dns_result)); return(T_UNRESOLVED); } textregion.base = db_class; textregion.length = strlen(db_class); dns_result = dns_rdataclass_fromtext(&rdataclass, &textregion); if (dns_result != ISC_R_SUCCESS) { t_info("dns_rdataclass_fromtext failed %s\n", dns_result_totext(dns_result)); return(T_UNRESOLVED); } isc_result = isc_mem_create(0, 0, &mctx); if (isc_result != ISC_R_SUCCESS) { t_info("isc_mem_create failed %s\n", isc_result_totext(isc_result)); return(T_UNRESOLVED); } isc_result = isc_entropy_create(mctx, &ectx); if (isc_result != ISC_R_SUCCESS) { t_info("isc_entropy_create failed %s\n", isc_result_totext(isc_result)); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } isc_result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE); if (isc_result != ISC_R_SUCCESS) { t_info("isc_hash_create failed %s\n", isc_result_totext(isc_result)); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } dns_result = dns_db_create(mctx, db_type, dns_fixedname_name(&dns_origin), dbtype, rdataclass, 0, NULL, &db); if (dns_result != ISC_R_SUCCESS) { t_info("dns_db_create failed %s\n", dns_result_totext(dns_result)); isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } dns_result = dns_db_load(db, filename); if (dns_result == ISC_R_SUCCESS) { if ((*cf)(db) == exp_result) result = T_PASS; else result = T_FAIL; } else { t_info("dns_db_load failed %s\n", dns_result_totext(dns_result)); result = T_FAIL; } dns_db_detach(&db); isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(result); } static int test_dns_db_zc_x(const char *filename, dns_dbtype_t dbtype, isc_boolean_t(*cf)(dns_db_t *), isc_boolean_t exp_result) { FILE *fp; char *p; int line; int cnt; int result; int nfails; int nprobs; char *tokens[T_MAXTOKS]; nfails = 0; nprobs = 0; fp = fopen(filename, "r"); if (fp != NULL) { line = 0; while ((p = t_fgetbs(fp)) != NULL) { ++line; /* * Skip comment lines. */ if ((isspace((unsigned char)*p)) || (*p == '#')) { (void)free(p); continue; } cnt = t_bustline(p, tokens); if (cnt == 4) { result = t_dns_db_zc_x(tokens[0], /* file */ tokens[1], /* type */ tokens[2], /* origin */ tokens[3], /* class */ dbtype, /* cache */ cf, /* check func */ exp_result);/* expect */ if (result != T_PASS) { if (result == T_FAIL) ++nfails; else ++nprobs; } } else { t_info("bad format in %s at line %d\n", filename, line); ++nprobs; } (void)free(p); } (void)fclose(fp); } else { t_info("Missing datafile %s\n", filename); ++nprobs; } result = T_UNRESOLVED; if (nfails == 0 && nprobs == 0) result = T_PASS; else if (nfails) result = T_FAIL; return(result); } static void t2(void) { int result; t_assert("dns_db_iscache", 2, T_REQUIRED, "%s", a2); result = test_dns_db_zc_x("dns_db_iscache_1_data", dns_dbtype_cache, dns_db_iscache, ISC_TRUE); t_result(result); } static const char *a3 = "When the database db has zone semantics, a call to " "dns_db_iscache(db) returns ISC_FALSE."; static void t3(void) { int result; t_assert("dns_db_iscache", 3, T_REQUIRED, "%s", a3); result = test_dns_db_zc_x("dns_db_iscache_2_data", dns_dbtype_zone, dns_db_iscache, ISC_FALSE); t_result(result); } static const char *a4 = "When the database db has zone semantics, a call to " "dns_db_iszone(db) returns ISC_TRUE."; static void t4(void) { int result; t_assert("dns_db_iszone", 4, T_REQUIRED, "%s", a4); result = test_dns_db_zc_x("dns_db_iszone_1_data", dns_dbtype_zone, dns_db_iszone, ISC_TRUE); t_result(result); } static const char *a5 = "When the database db has cache semantics, a call to " "dns_db_iszone(db) returns ISC_FALSE."; static void t5(void) { int result; t_assert("dns_db_iszone", 5, T_REQUIRED, "%s", a5); result = test_dns_db_zc_x("dns_db_iszone_2_data", dns_dbtype_cache, dns_db_iszone, ISC_FALSE); t_result(result); } static int t_dns_db_origin(char **av) { char *filename; char *origin; int result; int len; int order; isc_result_t dns_result; isc_result_t isc_result; isc_mem_t *mctx; isc_entropy_t *ectx; dns_db_t *db; dns_fixedname_t dns_origin; dns_fixedname_t dns_dborigin; isc_buffer_t origin_buffer; db = NULL; mctx = NULL; ectx = NULL; filename = T_ARG(0); origin = T_ARG(1); t_info("testing with database %s and origin %s\n", filename, origin); isc_result = isc_mem_create(0, 0, &mctx); if (isc_result != ISC_R_SUCCESS) { t_info("isc_mem_create failed %s\n", isc_result_totext(isc_result)); return(T_UNRESOLVED); } isc_result = isc_entropy_create(mctx, &ectx); if (isc_result != ISC_R_SUCCESS) { t_info("isc_entropy_create failed %s\n", isc_result_totext(isc_result)); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } isc_result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE); if (isc_result != ISC_R_SUCCESS) { t_info("isc_hash_create failed %s\n", isc_result_totext(isc_result)); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } dns_result = t_create("rbt", origin, "in", "isc_true", mctx, &db); if (dns_result != ISC_R_SUCCESS) { t_info("t_create failed %s\n", dns_result_totext(dns_result)); isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } dns_fixedname_init(&dns_origin); dns_fixedname_init(&dns_dborigin); len = strlen(origin); isc_buffer_init(&origin_buffer, origin, len); isc_buffer_add(&origin_buffer, len); dns_result = dns_db_load(db, filename); if (dns_result != ISC_R_SUCCESS) { t_info("dns_db_load failed %s\n", dns_result_totext(dns_result)); dns_db_detach(&db); isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } dns_result = dns_name_fromtext(dns_fixedname_name(&dns_origin), &origin_buffer, NULL, 0, NULL); if (dns_result != ISC_R_SUCCESS) { t_info("dns_name_fromtext failed %s\n", dns_result_totext(dns_result)); dns_db_detach(&db); isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } order = dns_name_compare(dns_fixedname_name(&dns_origin), dns_db_origin(db)); if (order == 0) { result = T_PASS; } else { t_info("dns_name_compare returned %d\n", order); result = T_FAIL; } dns_db_detach(&db); isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(result); } static const char *a6 = "A call to dns_db_origin(db) returns the origin of the database."; static void t6(void) { int result; t_assert("dns_db_origin", 6, T_REQUIRED, "%s", a6); result = t_eval("dns_db_origin_data", t_dns_db_origin, 2); t_result(result); } static const char *a7 = "A call to dns_db_class(db) returns the class of the database."; #define CLASSBUFLEN 256 static int t_dns_db_class(char **av) { char *filename; char *db_class; int result; isc_result_t dns_result; isc_result_t isc_result; isc_mem_t *mctx; isc_entropy_t *ectx; dns_db_t *db; dns_rdataclass_t rdataclass; dns_rdataclass_t db_rdataclass; isc_textregion_t textregion; filename = T_ARG(0); db_class = T_ARG(1); db = NULL; mctx = NULL; ectx = NULL; t_info("testing with database %s and class %s\n", filename, db_class); textregion.base = db_class; textregion.length = strlen(db_class); dns_result = dns_rdataclass_fromtext(&rdataclass, &textregion); if (dns_result != ISC_R_SUCCESS) { t_info("dns_rdataclass_fromtext failed %s\n", dns_result_totext(dns_result)); return(T_UNRESOLVED); } isc_result = isc_mem_create(0, 0, &mctx); if (isc_result != ISC_R_SUCCESS) { t_info("isc_mem_create failed %s\n", isc_result_totext(isc_result)); return(T_UNRESOLVED); } isc_result = isc_entropy_create(mctx, &ectx); if (isc_result != ISC_R_SUCCESS) { t_info("isc_entropy_create failed %s\n", isc_result_totext(isc_result)); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } isc_result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE); if (isc_result != ISC_R_SUCCESS) { t_info("isc_hash_create failed %s\n", isc_result_totext(isc_result)); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } dns_result = t_create("rbt", ".", db_class, "isc_true", mctx, &db); if (dns_result != ISC_R_SUCCESS) { t_info("t_create failed %s\n", dns_result_totext(dns_result)); isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } dns_result = dns_db_load(db, filename); if (dns_result != ISC_R_SUCCESS) { t_info("dns_db_load failed %s\n", dns_result_totext(dns_result)); dns_db_detach(&db); isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } db_rdataclass = dns_db_class(db); if (db_rdataclass == rdataclass) result = T_PASS; else { char classbuf[DNS_RDATACLASS_FORMATSIZE]; dns_rdataclass_format(db_rdataclass, classbuf, sizeof(classbuf)); t_info("dns_db_class returned %s, expected %s\n", classbuf, db_class); result = T_FAIL; } dns_db_detach(&db); isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(result); } static void t7(void) { int result; t_assert("dns_db_class", 7, T_REQUIRED, "%s", a7); result = t_eval("dns_db_class_data", t_dns_db_class, 2); t_result(result); } static const char *a8 = "A call to dns_db_currentversion() opens the current " "version for reading."; static int t_dns_db_currentversion(char **av) { char *filename; char *db_type; char *origin; char *db_class; char *model; char *findname; char *findtype; int result; int len; dns_db_t *db; isc_result_t dns_result; isc_result_t isc_result; isc_mem_t *mctx; isc_entropy_t *ectx; dns_dbnode_t *nodep; isc_textregion_t textregion; isc_buffer_t findname_buffer; dns_fixedname_t dns_findname; dns_fixedname_t dns_foundname; dns_rdataset_t rdataset; dns_rdatatype_t rdatatype; dns_dbversion_t *cversionp; dns_dbversion_t *nversionp; filename = T_ARG(0); db_type = T_ARG(1); origin = T_ARG(2); db_class = T_ARG(3); model = T_ARG(4); findname = T_ARG(5); findtype = T_ARG(6); db = NULL; mctx = NULL; ectx = NULL; t_info("testing using file %s and name %s\n", filename, findname); isc_result = isc_mem_create(0, 0, &mctx); if (isc_result != ISC_R_SUCCESS) { t_info("isc_mem_create failed %s\n", isc_result_totext(isc_result)); return(T_UNRESOLVED); } isc_result = isc_entropy_create(mctx, &ectx); if (isc_result != ISC_R_SUCCESS) { t_info("isc_entropy_create failed %s\n", isc_result_totext(isc_result)); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } isc_result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE); if (isc_result != ISC_R_SUCCESS) { t_info("isc_hash_create failed %s\n", isc_result_totext(isc_result)); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } dns_result = t_create(db_type, origin, db_class, model, mctx, &db); if (dns_result != ISC_R_SUCCESS) { isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } dns_result = dns_db_load(db, filename); if (dns_result != ISC_R_SUCCESS) { t_info("dns_db_load returned %s\n", dns_result_totext(dns_result)); dns_db_detach(&db); isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } dns_fixedname_init(&dns_findname); len = strlen(findname); isc_buffer_init(&findname_buffer, findname, len); isc_buffer_add(&findname_buffer, len); dns_result = dns_name_fromtext(dns_fixedname_name(&dns_findname), &findname_buffer, NULL, 0, NULL); if (dns_result != ISC_R_SUCCESS) { t_info("dns_name_fromtext failed %s\n", dns_result_totext(dns_result)); dns_db_detach(&db); isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } textregion.base = findtype; textregion.length = strlen(findtype); dns_result = dns_rdatatype_fromtext(&rdatatype, &textregion); if (dns_result != ISC_R_SUCCESS) { t_info("dns_rdatatype_fromtext %s failed %s\n", findtype, dns_result_totext(dns_result)); dns_db_detach(&db); isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } /* * find a name we know is there */ cversionp = NULL; dns_fixedname_init(&dns_foundname); dns_rdataset_init(&rdataset); dns_db_currentversion(db, &cversionp); nodep = NULL; dns_result = dns_db_find(db, dns_fixedname_name(&dns_findname), cversionp, rdatatype, 0, 0, &nodep, dns_fixedname_name(&dns_foundname), &rdataset, NULL); if (dns_result != ISC_R_SUCCESS) { t_info("unable to find %s using current version\n", findname); dns_db_closeversion(db, &cversionp, ISC_FALSE); dns_db_detach(&db); isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } /* * create a new version * delete the found rdataset in the new version * attempt to find the rdataset again and expect the find to fail * close/commit the new version * attempt to find the rdataset in the current version and * expect the find to succeed */ nversionp = NULL; dns_result = dns_db_newversion(db, &nversionp); if (dns_result != ISC_R_SUCCESS) { t_info("dns_db_newversion failed %s\n", dns_result_totext(dns_result)); dns_db_detachnode(db, &nodep); dns_rdataset_disassociate(&rdataset); dns_db_closeversion(db, &cversionp, ISC_FALSE); dns_db_detach(&db); isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } /* * Delete the found rdataset in the new version. */ dns_result = dns_db_deleterdataset(db, nodep, nversionp, rdatatype, 0); if (dns_result != ISC_R_SUCCESS) { t_info("dns_db_deleterdataset failed %s\n", dns_result_totext(dns_result)); dns_rdataset_disassociate(&rdataset); dns_db_detachnode(db, &nodep); dns_db_closeversion(db, &nversionp, ISC_FALSE); dns_db_closeversion(db, &cversionp, ISC_FALSE); dns_db_detach(&db); isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } /* * Don't need these now. */ dns_rdataset_disassociate(&rdataset); dns_db_detachnode(db, &nodep); nodep = NULL; /* * Find the deleted rdataset and expect it to fail. */ dns_result = dns_db_find(db, dns_fixedname_name(&dns_findname), nversionp, rdatatype, 0, 0, &nodep, dns_fixedname_name(&dns_foundname), &rdataset, NULL); if ((dns_result != ISC_R_NOTFOUND) && (dns_result != DNS_R_NXDOMAIN)) { t_info("unexpectedly found %s using current version\n", findname); dns_db_closeversion(db, &cversionp, ISC_FALSE); dns_db_closeversion(db, &nversionp, ISC_FALSE); dns_db_detach(&db); isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(T_FAIL); } /* * Close/commit the new version. */ dns_db_closeversion(db, &nversionp, ISC_TRUE); /* * Find the deleted rdata in the current version. */ dns_result = dns_db_find(db, dns_fixedname_name(&dns_findname), cversionp, rdatatype, DNS_DBFIND_GLUEOK, 0, &nodep, dns_fixedname_name(&dns_foundname), &rdataset, NULL); /* * And expect it to succeed. */ if (dns_result == ISC_R_SUCCESS) { result = T_PASS; } else { t_info("cound not find %s using current version\n", findname); dns_db_closeversion(db, &cversionp, ISC_FALSE); dns_db_detach(&db); isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); result = T_FAIL; } dns_db_detachnode(db, &nodep); dns_rdataset_disassociate(&rdataset); dns_db_closeversion(db, &cversionp, ISC_FALSE); dns_db_detach(&db); isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(result); } static void t8(void) { int result; t_assert("dns_db_currentversion", 8, T_REQUIRED, "%s", a8); result = t_eval("dns_db_currentversion_data", t_dns_db_currentversion, 7); t_result(result); } static const char *a9 = "A call to dns_db_newversion() opens a new version for " "reading and writing."; static int t_dns_db_newversion(char **av) { char *filename; char *db_type; char *origin; char *db_class; char *model; char *newname; char *newtype; int result; int len; int rval; dns_db_t *db; isc_result_t dns_result; isc_result_t isc_result; isc_mem_t *mctx; isc_entropy_t *ectx; dns_dbnode_t *nodep; dns_dbnode_t *found_nodep; isc_textregion_t textregion; isc_buffer_t newname_buffer; dns_fixedname_t dns_newname; dns_fixedname_t dns_foundname; dns_rdata_t added_rdata = DNS_RDATA_INIT; const char * added_rdata_data; dns_rdataset_t added_rdataset; dns_rdata_t found_rdata = DNS_RDATA_INIT; dns_rdataset_t found_rdataset; dns_rdatatype_t rdatatype; dns_rdataclass_t rdataclass; dns_dbversion_t *nversionp; dns_rdatalist_t rdatalist; filename = T_ARG(0); db_type = T_ARG(1); origin = T_ARG(2); db_class = T_ARG(3); model = T_ARG(4); newname = T_ARG(5); newtype = T_ARG(6); db = NULL; mctx = NULL; ectx = NULL; /* * Open a new version, add some data, commit it, * close it, open a new version, and check that changes * are present. */ t_info("testing using file %s and name %s\n", filename, newname); isc_result = isc_mem_create(0, 0, &mctx); if (isc_result != ISC_R_SUCCESS) { t_info("isc_mem_create failed %s\n", isc_result_totext(isc_result)); return(T_UNRESOLVED); } isc_result = isc_entropy_create(mctx, &ectx); if (isc_result != ISC_R_SUCCESS) { t_info("isc_entropy_create failed %s\n", isc_result_totext(isc_result)); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } isc_result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE); if (isc_result != ISC_R_SUCCESS) { t_info("isc_hash_create failed %s\n", isc_result_totext(isc_result)); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } dns_result = t_create(db_type, origin, db_class, model, mctx, &db); if (dns_result != ISC_R_SUCCESS) { isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } dns_result = dns_db_load(db, filename); if (dns_result != ISC_R_SUCCESS) { t_info("dns_db_load returned %s\n", dns_result_totext(dns_result)); dns_db_detach(&db); isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } /* * Add a new name. */ dns_fixedname_init(&dns_newname); len = strlen(newname); isc_buffer_init(&newname_buffer, newname, len); isc_buffer_add(&newname_buffer, len); dns_result = dns_name_fromtext(dns_fixedname_name(&dns_newname), &newname_buffer, NULL, 0, NULL); if (dns_result != ISC_R_SUCCESS) { t_info("dns_name_fromtext failed %s\n", dns_result_totext(dns_result)); dns_db_detach(&db); isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } nodep = NULL; dns_result = dns_db_findnode(db, dns_fixedname_name(&dns_newname), ISC_TRUE, &nodep); if (dns_result != ISC_R_SUCCESS) { t_info("dns_db_findnode failed %s\n", dns_result_totext(dns_result)); dns_db_detach(&db); isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } /* * Open a new version and associate some rdata with the new name. */ textregion.base = newtype; textregion.length = strlen(newtype); dns_result = dns_rdatatype_fromtext(&rdatatype, &textregion); if (dns_result != ISC_R_SUCCESS) { t_info("dns_rdatatype_fromtext %s failed %s\n", newtype, dns_result_totext(dns_result)); dns_db_detachnode(db, &nodep); dns_db_detach(&db); isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } textregion.base = db_class; textregion.length = strlen(db_class); dns_result = dns_rdataclass_fromtext(&rdataclass, &textregion); if (dns_result != ISC_R_SUCCESS) { t_info("dns_rdataclass_fromtext failed %s\n", dns_result_totext(dns_result)); dns_db_detachnode(db, &nodep); dns_db_detach(&db); isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } dns_rdata_init(&added_rdata); added_rdata_data = "\x10\x00\x00\x01"; DE_CONST(added_rdata_data, added_rdata.data); added_rdata.length = 4; added_rdata.rdclass = rdataclass; added_rdata.type = rdatatype; dns_rdatalist_init(&rdatalist); rdatalist.type = rdatatype; rdatalist.rdclass = rdataclass; ISC_LIST_APPEND(rdatalist.rdata, &added_rdata, link); dns_rdataset_init(&added_rdataset); dns_result = dns_rdatalist_tordataset(&rdatalist, &added_rdataset); if (dns_result != ISC_R_SUCCESS) { t_info("dns_rdatalist_tordataset failed %s\n", dns_result_totext(dns_result)); dns_db_detachnode(db, &nodep); dns_db_detach(&db); isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } nversionp = NULL; dns_result = dns_db_newversion(db, &nversionp); if (dns_result != ISC_R_SUCCESS) { t_info("dns_db_newversion failed %s\n", dns_result_totext(dns_result)); dns_db_detachnode(db, &nodep); dns_db_detach(&db); isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } dns_result = dns_db_addrdataset(db, nodep, nversionp, 0, &added_rdataset, 0, NULL); if (dns_result != ISC_R_SUCCESS) { t_info("dns_db_addrdataset failed %s\n", dns_result_totext(dns_result)); dns_db_closeversion(db, &nversionp, ISC_FALSE); dns_db_detachnode(db, &nodep); dns_db_detach(&db); isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } /* * Close and commit the version. */ dns_db_closeversion(db, &nversionp, ISC_TRUE); dns_db_detachnode(db, &nodep); if (dns_rdataset_isassociated(&added_rdataset)) dns_rdataset_disassociate(&added_rdataset); nodep = NULL; /* * Open a new version and find the data we added. */ dns_fixedname_init(&dns_foundname); dns_rdataset_init(&found_rdataset); nversionp = NULL; found_nodep = NULL; dns_db_newversion(db, &nversionp); /* * Find the recently added name and rdata. */ dns_result = dns_db_find(db, dns_fixedname_name(&dns_newname), nversionp, rdatatype, 0, 0, &found_nodep, dns_fixedname_name(&dns_foundname), &found_rdataset, NULL); if (dns_result != ISC_R_SUCCESS) { /* XXXWPK - NXRRSET ??? reference counts ??? */ t_info("dns_db_find failed %s\n", dns_result_totext(dns_result)); dns_db_closeversion(db, &nversionp, ISC_FALSE); dns_db_detachnode(db, &found_nodep); if (dns_rdataset_isassociated(&found_rdataset)) dns_rdataset_disassociate(&found_rdataset); dns_db_detach(&db); isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(T_FAIL); } dns_result = dns_rdataset_first(&found_rdataset); if (dns_result != ISC_R_SUCCESS) { t_info("dns_rdataset_first failed %s\n", dns_result_totext(dns_result)); dns_db_detachnode(db, &nodep); if (dns_rdataset_isassociated(&found_rdataset)) dns_rdataset_disassociate(&found_rdataset); dns_db_closeversion(db, &nversionp, ISC_FALSE); dns_db_detach(&db); isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(T_FAIL); } /* * Now make sure its what we expect. */ dns_rdata_init(&found_rdata); dns_rdataset_current(&found_rdataset, &found_rdata); rval = dns_rdata_compare(&added_rdata, &found_rdata); if (rval == 0) { result = T_PASS; } else { t_info("dns_rdata_compare returned %d\n", rval); result = T_FAIL; } /* * Don't need these now. */ dns_db_closeversion(db, &nversionp, ISC_FALSE); if (dns_rdataset_isassociated(&found_rdataset)) dns_rdataset_disassociate(&found_rdataset); dns_db_detachnode(db, &found_nodep); dns_db_detach(&db); isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(result); } static void t9(void) { int result; t_assert("dns_db_newversion", 9, T_REQUIRED, "%s", a9); result = t_eval("dns_db_newversion_data", t_dns_db_newversion, 7); t_result(result); } static const char *a10 = "When versionp points to a read-write version and commit is " "ISC_TRUE, a call to dns_db_closeversion(db, versionp, commit) " "causes all changes made in the version to take effect, " "and returns ISC_R_SUCCESS."; static int t_dns_db_closeversion_1(char **av) { char *filename; char *db_type; char *origin; char *db_class; char *model; char *new_name; char *new_type; char *existing_name; char *existing_type; int result; int len; int rval; int nfails; dns_db_t *db; isc_result_t dns_result; isc_result_t isc_result; isc_mem_t *mctx; isc_entropy_t *ectx; dns_dbnode_t *nodep; isc_textregion_t textregion; isc_buffer_t name_buffer; dns_fixedname_t dns_newname; dns_fixedname_t dns_foundname; dns_fixedname_t dns_existingname; dns_rdata_t added_rdata = DNS_RDATA_INIT; const char * added_rdata_data; dns_rdataset_t added_rdataset; dns_rdata_t found_rdata = DNS_RDATA_INIT; dns_rdataset_t found_rdataset; dns_rdatatype_t new_rdatatype; dns_rdatatype_t existing_rdatatype; dns_rdataclass_t rdataclass; dns_dbversion_t *nversionp; dns_dbversion_t *cversionp; dns_rdatalist_t rdatalist; filename = T_ARG(0); db_type = T_ARG(1); origin = T_ARG(2); db_class = T_ARG(3); model = T_ARG(4); new_name = T_ARG(5); new_type = T_ARG(6); existing_name = T_ARG(7); existing_type = T_ARG(8); nfails = 0; db = NULL; mctx = NULL; ectx = NULL; /* * Open a new version, add some data, * remove some data, close with commit, open the current * version and check that changes are present. */ t_info("testing using file %s and name %s\n", filename, new_name); isc_result = isc_mem_create(0, 0, &mctx); if (isc_result != ISC_R_SUCCESS) { t_info("isc_mem_create failed %s\n", isc_result_totext(isc_result)); return(T_UNRESOLVED); } isc_result = isc_entropy_create(mctx, &ectx); if (isc_result != ISC_R_SUCCESS) { t_info("isc_entropy_create failed %s\n", isc_result_totext(isc_result)); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } isc_result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE); if (isc_result != ISC_R_SUCCESS) { t_info("isc_hash_create failed %s\n", isc_result_totext(isc_result)); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } dns_result = t_create(db_type, origin, db_class, model, mctx, &db); if (dns_result != ISC_R_SUCCESS) { isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } dns_result = dns_db_load(db, filename); if (dns_result != ISC_R_SUCCESS) { t_info("dns_db_load returned %s\n", dns_result_totext(dns_result)); dns_db_detach(&db); isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } /* * Remove all rdata for an existing name. */ dns_fixedname_init(&dns_existingname); len = strlen(existing_name); isc_buffer_init(&name_buffer, existing_name, len); isc_buffer_add(&name_buffer, len); dns_result = dns_name_fromtext(dns_fixedname_name(&dns_existingname), &name_buffer, NULL, 0, NULL); if (dns_result != ISC_R_SUCCESS) { t_info("dns_name_fromtext failed %s\n", dns_result_totext(dns_result)); dns_db_detach(&db); isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } textregion.base = existing_type; textregion.length = strlen(existing_type); dns_result = dns_rdatatype_fromtext(&existing_rdatatype, &textregion); if (dns_result != ISC_R_SUCCESS) { t_info("dns_rdatatype_fromtext %s failed %s\n", existing_type, dns_result_totext(dns_result)); dns_db_detachnode(db, &nodep); dns_db_detach(&db); isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } nodep = NULL; dns_result = dns_db_findnode(db, dns_fixedname_name(&dns_existingname), ISC_FALSE, &nodep); if (dns_result != ISC_R_SUCCESS) { t_info("dns_db_findnode %s\n", dns_result_totext(dns_result)); dns_db_detach(&db); isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } /* open a new version */ nversionp = NULL; dns_result = dns_db_newversion(db, &nversionp); if (dns_result != ISC_R_SUCCESS) { t_info("dns_db_newversion failed %s\n", dns_result_totext(dns_result)); dns_db_detachnode(db, &nodep); dns_db_detach(&db); isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } dns_result = dns_db_deleterdataset(db, nodep, nversionp, existing_rdatatype, 0); if (dns_result != ISC_R_SUCCESS) { t_info("dns_db_deleterdataset failed %s\n", dns_result_totext(dns_result)); dns_db_closeversion(db, &nversionp, ISC_FALSE); dns_db_detachnode(db, &nodep); dns_db_detach(&db); isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } /* * add a new name and associate some rdata with it */ dns_db_detachnode(db, &nodep); nodep = NULL; dns_fixedname_init(&dns_newname); len = strlen(new_name); isc_buffer_init(&name_buffer, new_name, len); isc_buffer_add(&name_buffer, len); dns_result = dns_name_fromtext(dns_fixedname_name(&dns_newname), &name_buffer, NULL, 0, NULL); if (dns_result != ISC_R_SUCCESS) { t_info("dns_name_fromtext failed %s\n", dns_result_totext(dns_result)); dns_db_closeversion(db, &nversionp, ISC_FALSE); dns_db_detach(&db); isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } dns_result = dns_db_findnode(db, dns_fixedname_name(&dns_newname), ISC_TRUE, &nodep); if (dns_result != ISC_R_SUCCESS) { t_info("dns_db_findnode failed %s\n", dns_result_totext(dns_result)); dns_db_closeversion(db, &nversionp, ISC_FALSE); dns_db_detach(&db); isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } /* * associate some rdata with the new name */ textregion.base = new_type; textregion.length = strlen(new_type); dns_result = dns_rdatatype_fromtext(&new_rdatatype, &textregion); if (dns_result != ISC_R_SUCCESS) { t_info("dns_rdatatype_fromtext %s failed %s\n", new_type, dns_result_totext(dns_result)); dns_db_detachnode(db, &nodep); dns_db_detach(&db); isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } textregion.base = db_class; textregion.length = strlen(db_class); dns_result = dns_rdataclass_fromtext(&rdataclass, &textregion); if (dns_result != ISC_R_SUCCESS) { t_info("dns_rdataclass_fromtext failed %s\n", dns_result_totext(dns_result)); dns_db_detachnode(db, &nodep); dns_db_detach(&db); isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } dns_rdata_init(&added_rdata); added_rdata_data = "\x10\x00\x00\x01"; DE_CONST(added_rdata_data, added_rdata.data); added_rdata.length = 4; added_rdata.rdclass = rdataclass; added_rdata.type = new_rdatatype; dns_rdatalist_init(&rdatalist); rdatalist.type = new_rdatatype; rdatalist.rdclass = rdataclass; ISC_LIST_APPEND(rdatalist.rdata, &added_rdata, link); dns_rdataset_init(&added_rdataset); dns_result = dns_rdatalist_tordataset(&rdatalist, &added_rdataset); if (dns_result != ISC_R_SUCCESS) { t_info("dns_rdatalist_tordataset failed %s\n", dns_result_totext(dns_result)); dns_db_detachnode(db, &nodep); dns_db_detach(&db); isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } dns_result = dns_db_addrdataset(db, nodep, nversionp, 0, &added_rdataset, 0, NULL); if (dns_result != ISC_R_SUCCESS) { t_info("dns_db_addrdataset failed %s\n", dns_result_totext(dns_result)); dns_db_closeversion(db, &nversionp, ISC_FALSE); dns_db_detachnode(db, &nodep); dns_db_detach(&db); isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } /* close and commit the version */ dns_db_closeversion(db, &nversionp, ISC_TRUE); dns_db_detachnode(db, &nodep); nodep = NULL; /* open the current version and check changes */ dns_fixedname_init(&dns_foundname); dns_rdataset_init(&found_rdataset); cversionp = NULL; dns_db_currentversion(db, &cversionp); /* find the recently added name and rdata */ dns_result = dns_db_find(db, dns_fixedname_name(&dns_newname), cversionp, new_rdatatype, 0, 0, &nodep, dns_fixedname_name(&dns_foundname), &found_rdataset, NULL); if (dns_result != ISC_R_SUCCESS) { /* XXXWPK NXRRSET ??? reference counting ??? */ t_info("dns_db_find failed %s\n", dns_result_totext(dns_result)); dns_db_closeversion(db, &cversionp, ISC_FALSE); dns_db_detachnode(db, &nodep); if (dns_rdataset_isassociated(&found_rdataset)) dns_rdataset_disassociate(&found_rdataset); dns_db_detach(&db); isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(T_FAIL); } dns_result = dns_rdataset_first(&found_rdataset); if (dns_result != ISC_R_SUCCESS) { t_info("dns_rdataset_first failed %s\n", dns_result_totext(dns_result)); dns_db_detachnode(db, &nodep); if (dns_rdataset_isassociated(&found_rdataset)) dns_rdataset_disassociate(&found_rdataset); dns_db_closeversion(db, &cversionp, ISC_FALSE); dns_db_detach(&db); isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(T_FAIL); } /* * Now make sure its what we expect. */ dns_rdata_init(&found_rdata); dns_rdataset_current(&found_rdataset, &found_rdata); rval = dns_rdata_compare(&added_rdata, &found_rdata); if (rval != 0) { t_info("dns_rdata_compare returned %d\n", rval); ++nfails; } /* * Now check the rdata deletion. */ if (dns_rdataset_isassociated(&found_rdataset)) dns_rdataset_disassociate(&found_rdataset); dns_rdataset_init(&found_rdataset); dns_db_detachnode(db, &nodep); nodep = NULL; dns_fixedname_init(&dns_foundname); dns_result = dns_db_find(db, dns_fixedname_name(&dns_existingname), cversionp, existing_rdatatype, 0, 0, &nodep, dns_fixedname_name(&dns_foundname), &found_rdataset, NULL); if ((dns_result != ISC_R_NOTFOUND) && (dns_result != DNS_R_NXDOMAIN)) { dns_rdataset_disassociate(&found_rdataset); dns_db_detachnode(db, &nodep); t_info("dns_db_find %s returned %s\n", existing_name, dns_result_totext(dns_result)); ++nfails; } dns_db_closeversion(db, &cversionp, ISC_FALSE); dns_db_detach(&db); isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); if (nfails == 0) result = T_PASS; else result = T_FAIL; return(result); } static void t10(void) { int result; t_assert("dns_db_closeversion", 10, T_REQUIRED, "%s", a10); result = t_eval("dns_db_closeversion_1_data", t_dns_db_closeversion_1, 9); t_result(result); } static const char *a11 = "When versionp points to a read-write version and commit is " "ISC_FALSE, a call to dns_db_closeversion(db, versionp, commit) " "causes all changes made in the version to to be rolled back, " "and returns ISC_R_SUCCESS."; static int t_dns_db_closeversion_2(char **av) { char *filename; char *db_type; char *origin; char *db_class; char *model; char *new_name; char *new_type; char *existing_name; char *existing_type; int result; int len; int rval; int nfails; dns_db_t *db; isc_result_t dns_result; isc_result_t isc_result; isc_mem_t *mctx; isc_entropy_t *ectx; dns_dbnode_t *nodep; isc_textregion_t textregion; isc_buffer_t name_buffer; dns_fixedname_t dns_newname; dns_fixedname_t dns_foundname; dns_fixedname_t dns_existingname; dns_rdata_t added_rdata = DNS_RDATA_INIT; const char * added_rdata_data; dns_rdataset_t added_rdataset; dns_rdata_t found_rdata = DNS_RDATA_INIT; dns_rdataset_t found_rdataset; dns_rdatatype_t new_rdatatype; dns_rdatatype_t existing_rdatatype; dns_rdataclass_t rdataclass; dns_dbversion_t *nversionp; dns_dbversion_t *cversionp; dns_rdatalist_t rdatalist; filename = T_ARG(0); db_type = T_ARG(1); origin = T_ARG(2); db_class = T_ARG(3); model = T_ARG(4); new_name = T_ARG(5); new_type = T_ARG(6); existing_name = T_ARG(7); existing_type = T_ARG(8); nfails = 0; db = NULL; mctx = NULL; ectx = NULL; /* * Open a new version, add some data, * remove some data, close with commit, open the current * version and check that changes are present. */ t_info("testing using file %s and name %s\n", filename, new_name); isc_result = isc_mem_create(0, 0, &mctx); if (isc_result != ISC_R_SUCCESS) { t_info("isc_mem_create failed %s\n", isc_result_totext(isc_result)); return(T_UNRESOLVED); } isc_result = isc_entropy_create(mctx, &ectx); if (isc_result != ISC_R_SUCCESS) { t_info("isc_entropy_create failed %s\n", isc_result_totext(isc_result)); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } isc_result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE); if (isc_result != ISC_R_SUCCESS) { t_info("isc_hash_create failed %s\n", isc_result_totext(isc_result)); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } dns_result = t_create(db_type, origin, db_class, model, mctx, &db); if (dns_result != ISC_R_SUCCESS) { isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } dns_result = dns_db_load(db, filename); if (dns_result != ISC_R_SUCCESS) { t_info("dns_db_load returned %s\n", dns_result_totext(dns_result)); dns_db_detach(&db); isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } /* * Remove all rdata for an existing name. */ dns_fixedname_init(&dns_existingname); len = strlen(existing_name); isc_buffer_init(&name_buffer, existing_name, len); isc_buffer_add(&name_buffer, len); dns_result = dns_name_fromtext(dns_fixedname_name(&dns_existingname), &name_buffer, NULL, 0, NULL); if (dns_result != ISC_R_SUCCESS) { t_info("dns_name_fromtext failed %s\n", dns_result_totext(dns_result)); dns_db_detach(&db); isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } textregion.base = existing_type; textregion.length = strlen(existing_type); dns_result = dns_rdatatype_fromtext(&existing_rdatatype, &textregion); if (dns_result != ISC_R_SUCCESS) { t_info("dns_rdatatype_fromtext %s failed %s\n", existing_type, dns_result_totext(dns_result)); dns_db_detachnode(db, &nodep); dns_db_detach(&db); isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } nodep = NULL; dns_result = dns_db_findnode(db, dns_fixedname_name(&dns_existingname), ISC_FALSE, &nodep); if (dns_result != ISC_R_SUCCESS) { t_info("dns_db_findnode %s\n", dns_result_totext(dns_result)); dns_db_detach(&db); isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } /* * Open a new version. */ nversionp = NULL; dns_result = dns_db_newversion(db, &nversionp); if (dns_result != ISC_R_SUCCESS) { t_info("dns_db_newversion failed %s\n", dns_result_totext(dns_result)); dns_db_detachnode(db, &nodep); dns_db_detach(&db); isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } dns_result = dns_db_deleterdataset(db, nodep, nversionp, existing_rdatatype, 0); if (dns_result != ISC_R_SUCCESS) { t_info("dns_db_deleterdataset failed %s\n", dns_result_totext(dns_result)); dns_db_closeversion(db, &nversionp, ISC_FALSE); dns_db_detachnode(db, &nodep); dns_db_detach(&db); isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } /* * add a new name and associate some rdata with it */ dns_db_detachnode(db, &nodep); nodep = NULL; dns_fixedname_init(&dns_newname); len = strlen(new_name); isc_buffer_init(&name_buffer, new_name, len); isc_buffer_add(&name_buffer, len); dns_result = dns_name_fromtext(dns_fixedname_name(&dns_newname), &name_buffer, NULL, 0, NULL); if (dns_result != ISC_R_SUCCESS) { t_info("dns_name_fromtext failed %s\n", dns_result_totext(dns_result)); dns_db_closeversion(db, &nversionp, ISC_FALSE); dns_db_detach(&db); isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } dns_result = dns_db_findnode(db, dns_fixedname_name(&dns_newname), ISC_TRUE, &nodep); if (dns_result != ISC_R_SUCCESS) { t_info("dns_db_findnode failed %s\n", dns_result_totext(dns_result)); dns_db_closeversion(db, &nversionp, ISC_FALSE); dns_db_detach(&db); isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } textregion.base = new_type; textregion.length = strlen(new_type); dns_result = dns_rdatatype_fromtext(&new_rdatatype, &textregion); if (dns_result != ISC_R_SUCCESS) { t_info("dns_rdatatype_fromtext %s failed %s\n", new_type, dns_result_totext(dns_result)); dns_db_detachnode(db, &nodep); dns_db_detach(&db); isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } textregion.base = db_class; textregion.length = strlen(db_class); dns_result = dns_rdataclass_fromtext(&rdataclass, &textregion); if (dns_result != ISC_R_SUCCESS) { t_info("dns_rdataclass_fromtext failed %s\n", dns_result_totext(dns_result)); dns_db_detachnode(db, &nodep); dns_db_detach(&db); isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } dns_rdata_init(&added_rdata); added_rdata_data = "\x10\x00\x00\x01"; DE_CONST(added_rdata_data, added_rdata.data); added_rdata.length = 4; added_rdata.rdclass = rdataclass; added_rdata.type = new_rdatatype; dns_rdatalist_init(&rdatalist); rdatalist.type = new_rdatatype; rdatalist.rdclass = rdataclass; ISC_LIST_APPEND(rdatalist.rdata, &added_rdata, link); dns_rdataset_init(&added_rdataset); dns_result = dns_rdatalist_tordataset(&rdatalist, &added_rdataset); if (dns_result != ISC_R_SUCCESS) { t_info("dns_rdatalist_tordataset failed %s\n", dns_result_totext(dns_result)); dns_db_detachnode(db, &nodep); dns_db_detach(&db); isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } dns_result = dns_db_addrdataset(db, nodep, nversionp, 0, &added_rdataset, 0, NULL); if (dns_result != ISC_R_SUCCESS) { t_info("dns_db_addrdataset failed %s\n", dns_result_totext(dns_result)); dns_db_closeversion(db, &nversionp, ISC_FALSE); dns_db_detachnode(db, &nodep); dns_db_detach(&db); isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } /* * Check that our changes took. */ dns_db_detachnode(db, &nodep); nodep = NULL; dns_fixedname_init(&dns_foundname); dns_rdataset_init(&found_rdataset); /* * Find the recently added name and rdata. */ dns_result = dns_db_find(db, dns_fixedname_name(&dns_newname), nversionp, new_rdatatype, 0, 0, &nodep, dns_fixedname_name(&dns_foundname), &found_rdataset, NULL); if ((dns_result == ISC_R_NOTFOUND) || (dns_result == DNS_R_NXDOMAIN) || (dns_result == DNS_R_NXRRSET)) { t_info("dns_db_find failed %s\n", dns_result_totext(dns_result)); dns_db_closeversion(db, &nversionp, ISC_FALSE); dns_db_detachnode(db, &nodep); if (dns_rdataset_isassociated(&found_rdataset)) dns_rdataset_disassociate(&found_rdataset); dns_db_detach(&db); isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(T_FAIL); } dns_result = dns_rdataset_first(&found_rdataset); if (dns_result != ISC_R_SUCCESS) { t_info("dns_rdataset_first failed %s\n", dns_result_totext(dns_result)); dns_db_detachnode(db, &nodep); if (dns_rdataset_isassociated(&found_rdataset)) dns_rdataset_disassociate(&found_rdataset); dns_db_closeversion(db, &nversionp, ISC_FALSE); dns_db_detach(&db); isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(T_FAIL); } /* * Now make sure its what we expect. */ dns_rdata_init(&found_rdata); dns_rdataset_current(&found_rdataset, &found_rdata); rval = dns_rdata_compare(&added_rdata, &found_rdata); if (rval != 0) { t_info("dns_rdata_compare returned %d\n", rval); ++nfails; } /* * Now check the rdata deletion. */ if (dns_rdataset_isassociated(&found_rdataset)) dns_rdataset_disassociate(&found_rdataset); dns_rdataset_init(&found_rdataset); dns_db_detachnode(db, &nodep); nodep = NULL; dns_fixedname_init(&dns_foundname); dns_result = dns_db_find(db, dns_fixedname_name(&dns_existingname), nversionp, existing_rdatatype, 0, 0, &nodep, dns_fixedname_name(&dns_foundname), &found_rdataset, NULL); if ((dns_result != ISC_R_NOTFOUND) && (dns_result != DNS_R_NXDOMAIN)) { t_info("dns_db_find %s returned %s\n", existing_name, dns_result_totext(dns_result)); if (dns_rdataset_isassociated(&found_rdataset)) dns_rdataset_disassociate(&found_rdataset); dns_db_detachnode(db, &nodep); ++nfails; } /* * Close the version without a commit. */ dns_db_closeversion(db, &nversionp, ISC_FALSE); /* * Open the current version and check changes. */ dns_fixedname_init(&dns_foundname); dns_rdataset_init(&found_rdataset); cversionp = NULL; dns_db_currentversion(db, &cversionp); /* * Find the recently added name and rdata. */ dns_result = dns_db_find(db, dns_fixedname_name(&dns_newname), cversionp, new_rdatatype, 0, 0, &nodep, dns_fixedname_name(&dns_foundname), &found_rdataset, NULL); if ((dns_result != ISC_R_NOTFOUND) && (dns_result != DNS_R_NXDOMAIN)) { t_info("dns_db_find %s returned %s\n", new_name, dns_result_totext(dns_result)); dns_rdataset_disassociate(&found_rdataset); dns_db_detachnode(db, &nodep); dns_db_closeversion(db, &cversionp, ISC_FALSE); dns_db_detach(&db); isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(T_FAIL); } /* * Now check the rdata deletion. */ nodep = NULL; dns_rdataset_init(&found_rdataset); dns_fixedname_init(&dns_foundname); dns_result = dns_db_find(db, dns_fixedname_name(&dns_existingname), cversionp, existing_rdatatype, 0, 0, &nodep, dns_fixedname_name(&dns_foundname), &found_rdataset, NULL); if ((dns_result == ISC_R_NOTFOUND) || (dns_result == DNS_R_NXDOMAIN) || (dns_result == DNS_R_NXRRSET)) { t_info("dns_db_find %s returned %s\n", existing_name, dns_result_totext(dns_result)); dns_rdataset_disassociate(&found_rdataset); dns_db_detachnode(db, &nodep); ++nfails; } dns_db_detachnode(db, &nodep); dns_rdataset_disassociate(&found_rdataset); dns_db_closeversion(db, &cversionp, ISC_FALSE); dns_db_detach(&db); isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); if (nfails == 0) result = T_PASS; else result = T_FAIL; return(result); } static void t11(void) { int result; t_assert("dns_db_closeversion", 11, T_REQUIRED, "%s", a11); result = t_eval("dns_db_closeversion_2_data", t_dns_db_closeversion_2, 9); t_result(result); } static const char *a12 = "A call to dns_db_expirenode() marks as stale all records at node " "which expire at or before 'now'. If 'now' is zero, then the current " "time will be used."; static int t_dns_db_expirenode(char **av) { char *filename; char *db_type; char *origin; char *db_class; char *existing_name; char *node_xtime; char *find_xtime; char *exp_find_result; int result; int len; dns_db_t *db; isc_result_t dns_result; isc_result_t exp_result; isc_result_t isc_result; isc_mem_t *mctx; isc_entropy_t *ectx; dns_dbnode_t *nodep; isc_buffer_t name_buffer; dns_fixedname_t dns_foundname; dns_fixedname_t dns_existingname; isc_stdtime_t node_expire_time; isc_stdtime_t find_expire_time; isc_stdtime_t now; dns_rdataset_t rdataset; filename = T_ARG(0); db_type = T_ARG(1); origin = T_ARG(2); db_class = T_ARG(3); existing_name = T_ARG(4); node_xtime = T_ARG(5); find_xtime = T_ARG(6); exp_find_result = T_ARG(7); mctx = NULL; ectx = NULL; /* * Find a node, mark it as stale, do a dns_db_find on the name and * expect it to fail. */ t_info("testing using file %s and name %s\n", filename, existing_name); node_expire_time = (isc_stdtime_t) strtol(node_xtime, NULL, 10); find_expire_time = (isc_stdtime_t) strtol(find_xtime, NULL, 10); exp_result = t_dns_result_fromtext(exp_find_result); isc_stdtime_get(&now); dns_fixedname_init(&dns_existingname); len = strlen(existing_name); isc_buffer_init(&name_buffer, existing_name, len); isc_buffer_add(&name_buffer, len); dns_result = dns_name_fromtext(dns_fixedname_name(&dns_existingname), &name_buffer, NULL, 0, NULL); if (dns_result != ISC_R_SUCCESS) { t_info("dns_name_fromtext failed %s\n", dns_result_totext(dns_result)); return(T_UNRESOLVED); } isc_result = isc_mem_create(0, 0, &mctx); if (isc_result != ISC_R_SUCCESS) { t_info("isc_mem_create failed %s\n", isc_result_totext(isc_result)); return(T_UNRESOLVED); } isc_result = isc_entropy_create(mctx, &ectx); if (isc_result != ISC_R_SUCCESS) { t_info("isc_entropy_create failed %s\n", isc_result_totext(isc_result)); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } isc_result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE); if (isc_result != ISC_R_SUCCESS) { t_info("isc_hash_create failed %s\n", isc_result_totext(isc_result)); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } db = NULL; dns_result = t_create(db_type, origin, db_class, "cache", mctx, &db); if (dns_result != ISC_R_SUCCESS) { isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } dns_result = dns_db_load(db, filename); if (dns_result != ISC_R_SUCCESS) { t_info("dns_db_load returned %s\n", dns_result_totext(dns_result)); dns_db_detach(&db); isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } nodep = NULL; /* * Check that the node is there. */ dns_result = dns_db_findnode(db, dns_fixedname_name(&dns_existingname), ISC_FALSE, &nodep); if (dns_result != ISC_R_SUCCESS) { t_info("unable to find %s\n", existing_name); dns_db_detach(&db); isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } /* * Expire it. */ if (node_expire_time != 0) node_expire_time += now; dns_result = dns_db_expirenode(db, nodep, node_expire_time); if (dns_result != ISC_R_SUCCESS) { t_info("dns_db_expirenode failed %s\n", dns_result_totext(dns_result)); dns_db_detachnode(db, &nodep); dns_db_detach(&db); isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(T_FAIL); } dns_fixedname_init(&dns_foundname); dns_rdataset_init(&rdataset); dns_db_detachnode(db, &nodep); nodep = NULL; if (find_expire_time != 0) find_expire_time += now; dns_result = dns_db_find(db, dns_fixedname_name(&dns_existingname), NULL, dns_rdatatype_any, 0, find_expire_time, &nodep, dns_fixedname_name(&dns_foundname), &rdataset, NULL); if (dns_result == exp_result) { result = T_PASS; } else { t_info("dns_db_find %s returned %s\n", existing_name, dns_result_totext(dns_result)); result = T_FAIL; } if ((dns_result != ISC_R_NOTFOUND) && (dns_result != DNS_R_NXDOMAIN) && (dns_result != DNS_R_NXRRSET)) { /* * Don't need to disassociate the rdataset because * we're searching with dns_rdatatype_any. */ dns_db_detachnode(db, &nodep); } dns_db_detach(&db); isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(result); } static void t12(void) { int result; t_assert("dns_db_expirenode", 12, T_REQUIRED, "%s", a12); result = t_eval("dns_db_expirenode_data", t_dns_db_expirenode, 8); t_result(result); } static const char *a13 = "If the node name exists, then a call to " "dns_db_findnode(db, name, ISC_FALSE, nodep) initializes nodep " "to point to the node and returns ISC_R_SUCCESS, otherwise " "it returns ISC_R_NOTFOUND."; static int t_dns_db_findnode_1(char **av) { char *filename; char *db_type; char *origin; char *db_class; char *model; char *find_name; char *find_type; char *expected_result; int result; int len; dns_db_t *db; isc_result_t dns_result; isc_result_t isc_result; isc_mem_t *mctx; isc_entropy_t *ectx; dns_dbnode_t *nodep; isc_buffer_t name_buffer; dns_rdataset_t rdataset; dns_rdatatype_t rdatatype; isc_textregion_t textregion; dns_fixedname_t dns_name; dns_dbversion_t *cversionp; isc_result_t exp_result; filename = T_ARG(0); db_type = T_ARG(1); origin = T_ARG(2); db_class = T_ARG(3); model = T_ARG(4); find_name = T_ARG(5); find_type = T_ARG(6); expected_result = T_ARG(7); db = NULL; mctx = NULL; ectx = NULL; t_info("testing using file %s and name %s\n", filename, find_name); exp_result = t_dns_result_fromtext(expected_result); textregion.base = find_type; textregion.length = strlen(find_type); dns_result = dns_rdatatype_fromtext(&rdatatype, &textregion); if (dns_result != ISC_R_SUCCESS) { t_info("dns_rdatatype_fromtext %s failed %s\n", find_type, dns_result_totext(dns_result)); return(T_UNRESOLVED); } isc_result = isc_mem_create(0, 0, &mctx); if (isc_result != ISC_R_SUCCESS) { t_info("isc_mem_create failed %s\n", isc_result_totext(isc_result)); return(T_UNRESOLVED); } isc_result = isc_entropy_create(mctx, &ectx); if (isc_result != ISC_R_SUCCESS) { t_info("isc_entropy_create failed %s\n", isc_result_totext(isc_result)); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } isc_result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE); if (isc_result != ISC_R_SUCCESS) { t_info("isc_hash_create failed %s\n", isc_result_totext(isc_result)); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } dns_result = t_create(db_type, origin, db_class, model, mctx, &db); if (dns_result != ISC_R_SUCCESS) { isc_mem_destroy(&mctx); return(T_UNRESOLVED); } dns_result = dns_db_load(db, filename); if (dns_result != ISC_R_SUCCESS) { t_info("dns_db_load returned %s\n", dns_result_totext(dns_result)); dns_db_detach(&db); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } nodep = NULL; dns_fixedname_init(&dns_name); len = strlen(find_name); isc_buffer_init(&name_buffer, find_name, len); isc_buffer_add(&name_buffer, len); dns_result = dns_name_fromtext(dns_fixedname_name(&dns_name), &name_buffer, NULL, 0, NULL); if (dns_result != ISC_R_SUCCESS) { t_info("dns_name_fromtext failed %s\n", dns_result_totext(dns_result)); dns_db_detach(&db); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } dns_result = dns_db_findnode(db, dns_fixedname_name(&dns_name), ISC_FALSE, &nodep); if (dns_result != exp_result) { t_info("dns_db_findnode failed %s\n", dns_result_totext(dns_result)); if (dns_result == ISC_R_SUCCESS) dns_db_detachnode(db, &nodep); dns_db_detach(&db); isc_mem_destroy(&mctx); return(T_FAIL); } /* * if we're expecting the find to succeed and it did, * check that the node has been initialized * by checking for the specified type of rdata * and expecting the search to succeed */ if (dns_result == ISC_R_SUCCESS) { cversionp = NULL; dns_db_currentversion(db, &cversionp); dns_rdataset_init(&rdataset); dns_result = dns_db_findrdataset(db, nodep, cversionp, rdatatype, 0, 0, &rdataset, NULL); if (dns_result == ISC_R_SUCCESS) { dns_rdataset_disassociate(&rdataset); result = T_PASS; } else { t_info("dns_db_findrdataset failed %s\n", dns_result_totext(dns_result)); result = T_FAIL; } dns_db_closeversion(db, &cversionp, ISC_FALSE); dns_db_detachnode(db, &nodep); } else { result = T_PASS; } dns_db_detach(&db); isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(result); } static void t13(void) { int result; t_assert("dns_db_findnode", 13, T_REQUIRED, "%s", a13); result = t_eval("dns_db_findnode_1_data", t_dns_db_findnode_1, 8); t_result(result); } static const char *a14 = "If the node name does not exist and create is ISC_TRUE, " "then a call to dns_db_findnode(db, name, create, nodep) " "creates the node, initializes nodep to point to the node, " "and returns ISC_R_SUCCESS."; static int t_dns_db_findnode_2(char **av) { char *filename; char *db_type; char *origin; char *db_class; char *model; char *newname; int nfails; int result; int len; dns_db_t *db; isc_result_t dns_result; isc_result_t isc_result; isc_mem_t *mctx; isc_entropy_t *ectx; dns_dbnode_t *nodep; dns_dbnode_t *newnodep; isc_buffer_t name_buffer; dns_rdataset_t rdataset; dns_fixedname_t dns_name; dns_fixedname_t dns_foundname; dns_dbversion_t *cversionp; filename = T_ARG(0); db_type = T_ARG(1); origin = T_ARG(2); db_class = T_ARG(3); model = T_ARG(4); newname = T_ARG(5); db = NULL; mctx = NULL; ectx = NULL; nfails = 0; t_info("testing using file %s and name %s\n", filename, newname); isc_result = isc_mem_create(0, 0, &mctx); if (isc_result != ISC_R_SUCCESS) { t_info("isc_mem_create failed %s\n", isc_result_totext(isc_result)); return(T_UNRESOLVED); } isc_result = isc_entropy_create(mctx, &ectx); if (isc_result != ISC_R_SUCCESS) { t_info("isc_entropy_create failed %s\n", isc_result_totext(isc_result)); return(T_UNRESOLVED); } isc_result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE); if (isc_result != ISC_R_SUCCESS) { t_info("isc_hash_create failed %s\n", isc_result_totext(isc_result)); return(T_UNRESOLVED); } dns_result = t_create(db_type, origin, db_class, model, mctx, &db); if (dns_result != ISC_R_SUCCESS) { isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } dns_result = dns_db_load(db, filename); if (dns_result != ISC_R_SUCCESS) { t_info("dns_db_load returned %s\n", dns_result_totext(dns_result)); dns_db_detach(&db); isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } nodep = NULL; dns_fixedname_init(&dns_name); /* * Make sure the name isn't there */ len = strlen(newname); isc_buffer_init(&name_buffer, newname, len); isc_buffer_add(&name_buffer, len); dns_result = dns_name_fromtext(dns_fixedname_name(&dns_name), &name_buffer, NULL, 0, NULL); if (dns_result != ISC_R_SUCCESS) { t_info("dns_name_fromtext returned %s\n", dns_result_totext(dns_result)); dns_db_detach(&db); isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } dns_result = dns_db_findnode(db, dns_fixedname_name(&dns_name), ISC_FALSE, &nodep); if ((dns_result != ISC_R_NOTFOUND) && (dns_result != DNS_R_NXDOMAIN) && (dns_result != DNS_R_NXRRSET)) { t_info("dns_db_findnode %s\n", dns_result_totext(dns_result)); dns_db_detachnode(db, &nodep); dns_db_detach(&db); isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } /* * Add it. */ dns_result = dns_db_findnode(db, dns_fixedname_name(&dns_name), ISC_TRUE, &nodep); if (dns_result != ISC_R_SUCCESS) { t_info("dns_db_findnode %s\n", dns_result_totext(dns_result)); dns_db_detach(&db); isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(T_FAIL); } /* * Check it. */ newnodep = NULL; dns_rdataset_init(&rdataset); dns_fixedname_init(&dns_foundname); cversionp = NULL; dns_db_currentversion(db, &cversionp); /* * First try dns_db_find DNS_R_NXDOMAIN. */ dns_result = dns_db_find(db, dns_fixedname_name(&dns_name), cversionp, dns_rdatatype_any, 0, 0, &newnodep, dns_fixedname_name(&dns_foundname), &rdataset, NULL); if ((dns_result != ISC_R_NOTFOUND) && (dns_result != DNS_R_NXDOMAIN)) { dns_db_detachnode(db, &newnodep); } if (dns_result != DNS_R_NXDOMAIN) { t_info("dns_db_find %s\n", dns_result_totext(dns_result)); ++nfails; } /* * Then try dns_db_findnode ISC_R_SUCCESS. */ dns_result = dns_db_findnode(db, dns_fixedname_name(&dns_name), ISC_FALSE, &newnodep); t_info("dns_db_findnode %s\n", dns_result_totext(dns_result)); if (dns_result == ISC_R_SUCCESS) { dns_db_detachnode(db, &newnodep); } else { t_info("dns_db_findnode %s failed %s\n", newname, dns_result_totext(dns_result)); ++nfails; } dns_db_detachnode(db, &nodep); dns_db_closeversion(db, &cversionp, ISC_FALSE); dns_db_detach(&db); isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); if (nfails == 0) result = T_PASS; else result = T_FAIL; return(result); } static void t14(void) { int result; t_assert("dns_db_findnode", 14, T_REQUIRED, "%s", a14); result = t_eval("dns_db_findnode_2_data", t_dns_db_findnode_2, 6); t_result(result); } static int t_dns_db_find_x(char **av) { char *dbfile; char *dbtype; char *dborigin; char *dbclass; char *dbmodel; char *findname; char *findtype; char *findopts; char *findtime; char *expected_result; int result; int len; int opts; dns_db_t *db; isc_result_t dns_result; isc_result_t isc_result; isc_stdtime_t ftime; isc_stdtime_t now; isc_result_t exp_result; isc_mem_t *mctx; isc_entropy_t *ectx; dns_dbnode_t *nodep; isc_textregion_t textregion; isc_buffer_t findname_buffer; dns_fixedname_t dns_findname; dns_fixedname_t dns_foundname; dns_rdataset_t rdataset; dns_rdatatype_t rdatatype; dns_dbversion_t *cversionp; dbfile = T_ARG(0); dbtype = T_ARG(1); dborigin = T_ARG(2); dbclass = T_ARG(3); dbmodel = T_ARG(4); findname = T_ARG(5); findtype = T_ARG(6); findopts = T_ARG(7); findtime = T_ARG(8); expected_result = T_ARG(9); db = NULL; mctx = NULL; ectx = NULL; opts = 0; t_info("testing using %s, name %s, type %s\n", dbfile, findname, findtype); isc_result = isc_mem_create(0, 0, &mctx); if (isc_result != ISC_R_SUCCESS) { t_info("isc_mem_create failed %s\n", isc_result_totext(isc_result)); return(T_UNRESOLVED); } isc_result = isc_entropy_create(mctx, &ectx); if (isc_result != ISC_R_SUCCESS) { t_info("isc_entropy_create failed %s\n", isc_result_totext(isc_result)); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } isc_result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE); if (isc_result != ISC_R_SUCCESS) { t_info("isc_hash_create failed %s\n", isc_result_totext(isc_result)); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } dns_result = t_create(dbtype, dborigin, dbclass, dbmodel, mctx, &db); if (dns_result != ISC_R_SUCCESS) { isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } dns_result = dns_db_load(db, dbfile); if (dns_result != ISC_R_SUCCESS) { t_info("dns_db_load returned %s\n", dns_result_totext(dns_result)); dns_db_detach(&db); isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } exp_result = t_dns_result_fromtext(expected_result); dns_fixedname_init(&dns_findname); len = strlen(findname); isc_buffer_init(&findname_buffer, findname, len); isc_buffer_add(&findname_buffer, len); dns_result = dns_name_fromtext(dns_fixedname_name(&dns_findname), &findname_buffer, NULL, 0, NULL); if (dns_result != ISC_R_SUCCESS) { t_info("dns_name_fromtext failed %s\n", dns_result_totext(dns_result)); dns_db_detach(&db); isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } textregion.base = findtype; textregion.length = strlen(findtype); dns_result = dns_rdatatype_fromtext(&rdatatype, &textregion); if (dns_result != ISC_R_SUCCESS) { t_info("dns_rdatatype_fromtext %s failed %s\n", findtype, dns_result_totext(dns_result)); dns_db_detach(&db); isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } if (strstr(findopts, "DNS_DBFIND_GLUEOK")) opts |= DNS_DBFIND_GLUEOK; if (strstr(findopts, "DNS_DBFIND_VALIDATEGLUE")) opts |= DNS_DBFIND_VALIDATEGLUE; isc_stdtime_get(&now); ftime = strtol(findtime, NULL, 10); if (ftime != 0) ftime += now; cversionp = NULL; dns_fixedname_init(&dns_foundname); dns_rdataset_init(&rdataset); if (dns_db_iszone(db)) dns_db_currentversion(db, &cversionp); nodep = NULL; dns_result = dns_db_find(db, dns_fixedname_name(&dns_findname), cversionp, rdatatype, opts, ftime, &nodep, dns_fixedname_name(&dns_foundname), &rdataset, NULL); if (dns_result != exp_result) { t_info("dns_db_find %s %s unexpectedly returned %s, " "expected %s\n", findname, findtype, dns_result_totext(dns_result), dns_result_totext(exp_result)); result = T_FAIL; } else { result = T_PASS; } if ((dns_result != ISC_R_NOTFOUND) && (dns_result != DNS_R_NXDOMAIN)) { if ((dns_result != DNS_R_NXRRSET) && (dns_result != DNS_R_ZONECUT)) if (dns_rdataset_isassociated(&rdataset)) dns_rdataset_disassociate(&rdataset); dns_db_detachnode(db, &nodep); } if (dns_db_iszone(db)) dns_db_closeversion(db, &cversionp, ISC_FALSE); dns_db_detach(&db); isc_hash_destroy(); isc_entropy_detach(&ectx); isc_mem_destroy(&mctx); return(result); } static const char *a15 = "A call to dns_db_find(db, name, version, type, options, now, ...) " "finds the best match for 'name' and 'type' in version 'version' " "of 'db'."; static void t15(void) { int result; t_assert("dns_db_find", 15, T_REQUIRED, "%s", a15); result = t_eval("dns_db_find_1_data", t_dns_db_find_x, 10); t_result(result); } static const char *a16 = "When the desired node and type were found, but are glue, " "and the DNS_DBFIND_GLUEOK option is set, a call to " "dns_db_find(db, name, version, type, options, now, ...) " "returns DNS_R_GLUE."; static void t16(void) { int result; t_assert("dns_db_find", 16, T_REQUIRED, "%s", a16); result = t_eval("dns_db_find_2_data", t_dns_db_find_x, 10); t_result(result); } static const char *a17 = "A call to dns_db_find() returns DNS_R_DELEGATION when the data " "requested is beneath a zone cut."; static void t17(void) { int result; t_assert("dns_db_find", 17, T_REQUIRED, "%s", a17); result = t_eval("dns_db_find_3_data", t_dns_db_find_x, 10); t_result(result); } static const char *a18 = "A call to dns_db_find() returns DNS_R_DELEGATION when type is " "dns_rdatatype_any and the desired node is a zone cut."; static void t18(void) { int result; t_assert("dns_db_find", 18, T_REQUIRED, "%s", a18); result = t_eval("dns_db_find_4_data", t_dns_db_find_x, 10); t_result(result); } static const char *a19 = "A call to dns_db_find() returns DNS_R_DNAME when the data " "requested is beneath a DNAME."; static void t19(void) { int result; t_assert("dns_db_find", 19, T_REQUIRED, "%s", a19); result = t_eval("dns_db_find_5_data", t_dns_db_find_x, 10); t_result(result); } static const char *a20 = "A call to dns_db_find() returns DNS_R_CNAME when the requested " "rdataset was not found but there is a CNAME at the desired name."; static void t20(void) { int result; t_assert("dns_db_find", 20, T_REQUIRED, "%s", a20); result = t_eval("dns_db_find_6_data", t_dns_db_find_x, 10); t_result(result); } static const char *a21 = "A call to dns_db_find() returns DNS_R_NXDOMAIN when name " "does not exist."; static void t21(void) { int result; t_assert("dns_db_find", 21, T_REQUIRED, "%s", a21); result = t_eval("dns_db_find_7_data", t_dns_db_find_x, 10); t_result(result); } static const char *a22 = "A call to dns_db_find() returns DNS_R_NXRRSET when " "the desired name exists, but the desired type does not."; static void t22(void) { int result; t_assert("dns_db_find", 22, T_REQUIRED, "%s", a22); result = t_eval("dns_db_find_8_data", t_dns_db_find_x, 10); t_result(result); } static const char *a23 = "When db is a cache database, a call to dns_db_find() " "returns ISC_R_NOTFOUND when the desired name does not exist, " "and no delegation could be found."; static void t23(void) { int result; t_assert("dns_db_find", 23, T_REQUIRED, "%s", a23); result = t_eval("dns_db_find_9_data", t_dns_db_find_x, 10); t_result(result); } static const char *a24 = "When db is a cache database, an rdataset will be found only " "if at least one rdataset at the found node expires after 'now'."; static void t24(void) { int result; t_assert("dns_db_find", 24, T_REQUIRED, "%s", a24); result = t_eval("dns_db_find_10_data", t_dns_db_find_x, 10); t_result(result); } static const char *a25 = "A call to dns_db_load(db, filename) returns DNS_R_NOTZONETOP " "when the zone data contains a SOA not at the zone apex."; static void t25(void) { int result; t_assert("dns_db_load", 25, T_REQUIRED, "%s", a25); result = t_eval("dns_db_load_soa_not_top", t_dns_db_load, 9); t_result(result); } testspec_t T_testlist[] = { { (PFV) t1, "dns_db_load" }, { (PFV) t2, "dns_db_iscache" }, { (PFV) t3, "dns_db_iscache" }, { (PFV) t4, "dns_db_iszone" }, { (PFV) t5, "dns_db_iszone" }, { (PFV) t6, "dns_db_origin" }, { (PFV) t7, "dns_db_class" }, { (PFV) t8, "dns_db_currentversion" }, { (PFV) t9, "dns_db_newversion" }, { (PFV) t10, "dns_db_closeversion" }, { (PFV) t11, "dns_db_closeversion" }, { (PFV) t12, "dns_db_expirenode" }, { (PFV) t13, "dns_db_findnode" }, { (PFV) t14, "dns_db_findnode" }, { (PFV) t15, "dns_db_find" }, { (PFV) t16, "dns_db_find" }, { (PFV) t17, "dns_db_find" }, { (PFV) t18, "dns_db_find" }, { (PFV) t19, "dns_db_find" }, { (PFV) t20, "dns_db_find" }, { (PFV) t21, "dns_db_find" }, { (PFV) t22, "dns_db_find" }, { (PFV) t23, "dns_db_find" }, { (PFV) t24, "dns_db_find" }, { (PFV) t25, "dns_db_load" }, { (PFV) 0, NULL } }; #ifdef WIN32 int main(int argc, char **argv) { t_settests(T_testlist); return (t_main(argc, argv)); } #endif bind9-9.11.3+dfsg/bin/tests/db/win32/000077500000000000000000000000001325250447100167755ustar00rootroot00000000000000bind9-9.11.3+dfsg/bin/tests/db/win32/t_db.dsp.in000066400000000000000000000113251325250447100210240ustar00rootroot00000000000000# Microsoft Developer Studio Project File - Name="t_db" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "@PLATFORM@ (x86) Console Application" 0x0103 CFG=t_db - @PLATFORM@ Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "t_db.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "t_db.mak" CFG="t_db - @PLATFORM@ Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "t_db - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE "t_db - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "t_db - @PLATFORM@ Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 @COPTX@ @COPTI@ /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c # ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../../lib/isc/win32" /I "../../../../lib/isc/win32/include" /I "../../../../lib/isc/include" /I "../../../../lib/dns/win32/include" /I "../../../../lib/dns/include" /I "../../../../lib/isccfg/include" /I "../../../../lib/tests/include" /D "WIN32" /D "NDEBUG" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console @MACHINE@ # ADD LINK32 @LIBXML2_LIB@ user32.lib advapi32.lib kernel32.lib ws2_32.lib ../../../../lib/isc/win32/Release/libisc.lib ../../../../lib/dns/win32/Release/libdns.lib ../../../../lib/isccfg/win32/Release/libisccfg.lib ../../../../lib/tests/win32/Release/libtests.lib /nologo /subsystem:console @MACHINE@ /out:"../../../../Build/Release/t_db.exe" !ELSEIF "$(CFG)" == "t_db - @PLATFORM@ Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /GZ /c # ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../../lib/isc/win32" /I "../../../../lib/isc/win32/include" /I "../../../../lib/isc/include" /I "../../../../lib/dns/win32/include" /I "../../../../lib/dns/include" /I "../../../../lib/isccfg/include" /I "../../../../lib/tests/include" /I "../../../../lib/bind9/include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "i386" /FR /FD /GZ /c # SUBTRACT CPP /X @COPTY@ # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug @MACHINE@ /pdbtype:sept # ADD LINK32 @LIBXML2_LIB@ user32.lib advapi32.lib kernel32.lib ws2_32.lib ../../../../lib/isc/win32/Debug/libisc.lib ../../../../lib/dns/win32/Debug/libdns.lib ../../../../lib/isccfg/win32/Release/libisccfg.lib ../../../../lib/tests/win32/Debug/libtests.lib /nologo /subsystem:console /map /debug @MACHINE@ /out:"../../../../Build/Debug/t_db.exe" /pdbtype:sept !ENDIF # Begin Target # Name "t_db - @PLATFORM@ Release" # Name "t_db - @PLATFORM@ Debug" # Begin Group "Source Files" # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" # Begin Source File SOURCE=..\t_db.c # End Source File # End Group # End Target # End Project bind9-9.11.3+dfsg/bin/tests/db/win32/t_db.dsw000066400000000000000000000010251325250447100204220ustar00rootroot00000000000000Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "t_db"=".\t_db.dsp" - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### bind9-9.11.3+dfsg/bin/tests/db/win32/t_db.mak.in000066400000000000000000000305731325250447100210140ustar00rootroot00000000000000# Microsoft Developer Studio Generated NMAKE File, Based on t_db.dsp !IF "$(CFG)" == "" CFG=t_db - @PLATFORM@ Debug !MESSAGE No configuration specified. Defaulting to t_db - @PLATFORM@ Debug. !ENDIF !IF "$(CFG)" != "t_db - @PLATFORM@ Release" && "$(CFG)" != "t_db - @PLATFORM@ Debug" !MESSAGE Invalid configuration "$(CFG)" specified. !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "t_db.mak" CFG="t_db - @PLATFORM@ Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "t_db - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE "t_db - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application") !MESSAGE !ERROR An invalid configuration is specified. !ENDIF !IF "$(OS)" == "Windows_NT" NULL= !ELSE NULL=nul !ENDIF CPP=cl.exe RSC=rc.exe LIBXML=@LIBXML2_LIB@ !IF "$(CFG)" == "t_db - @PLATFORM@ Release" _VC_MANIFEST_INC=0 _VC_MANIFEST_BASENAME=__VC80 !ELSE _VC_MANIFEST_INC=1 _VC_MANIFEST_BASENAME=__VC80.Debug !ENDIF #################################################### # Specifying name of temporary resource file used only in incremental builds: !if "$(_VC_MANIFEST_INC)" == "1" _VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res !else _VC_MANIFEST_AUTO_RES= !endif #################################################### # _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE: !if "$(_VC_MANIFEST_INC)" == "1" #MT_SPECIAL_RETURN=1090650113 #MT_SPECIAL_SWITCH=-notify_resource_update MT_SPECIAL_RETURN=0 MT_SPECIAL_SWITCH= _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \ if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \ rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \ link $** /out:$@ $(LFLAGS) !else _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1 !endif #################################################### # _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL: !if "$(_VC_MANIFEST_INC)" == "1" #MT_SPECIAL_RETURN=1090650113 #MT_SPECIAL_SWITCH=-notify_resource_update MT_SPECIAL_RETURN=0 MT_SPECIAL_SWITCH= _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \ if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \ rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \ link $** /out:$@ $(LFLAGS) !else _VC_MANIFEST_EMBED_EXE= \ if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2 !endif #################################################### # _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily: !if "$(_VC_MANIFEST_INC)" == "1" _VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \ $(_VC_MANIFEST_BASENAME).auto.rc \ $(_VC_MANIFEST_BASENAME).auto.manifest !else _VC_MANIFEST_CLEAN= !endif !IF "$(CFG)" == "t_db - @PLATFORM@ Release" OUTDIR=.\Release INTDIR=.\Release !IF "$(RECURSE)" == "0" ALL : "..\..\..\..\Build\Release\t_db.exe" !ELSE ALL : "libtests - @PLATFORM@ Release" "libisccfg - @PLATFORM@ Release" "libisc - @PLATFORM@ Release" "libdns - @PLATFORM@ Release" "..\..\..\..\Build\Release\t_db.exe" !ENDIF !IF "$(RECURSE)" == "1" CLEAN :"libdns - @PLATFORM@ ReleaseCLEAN" "libisc - @PLATFORM@ ReleaseCLEAN" "libtests - @PLATFORM@ ReleaseCLEAN" "libisccfg - @PLATFORM@ ReleaseCLEAN" !ELSE CLEAN : !ENDIF -@erase "$(INTDIR)\t_db.obj" -@erase "$(INTDIR)\vc60.idb" -@erase "..\..\..\..\Build\Release\t_db.exe" -@$(_VC_MANIFEST_CLEAN) "$(OUTDIR)" : if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" CPP_PROJ=/nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../../lib/isc/win32" /I "../../../../lib/isc/win32/include" /I "../../../../lib/isc/include" /I "../../../../lib/dns/win32/include" /I "../../../../lib/dns/include" /I "../../../../lib/isccfg/include" /I "../../../../lib/tests/include" /D "WIN32" /D "NDEBUG" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\t_db.pch" @COPTY@ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c BSC32=bscmake.exe BSC32_FLAGS=/nologo /o"$(OUTDIR)\t_db.bsc" BSC32_SBRS= \ LINK32=link.exe LINK32_FLAGS=user32.lib advapi32.lib kernel32.lib ws2_32.lib ../../../../lib/isc/win32/Release/libisc.lib ../../../../lib/dns/win32/Release/libdns.lib ../../../../lib/isccfg/win32/Release/libisccfg.lib ../../../../lib/tests/win32/Release/libtests.lib $(LIBXML) /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\t_db.pdb" @MACHINE@ /out:"../../../../Build/Release/t_db.exe" LINK32_OBJS= \ "$(INTDIR)\t_db.obj" \ "..\..\..\..\lib\dns\win32\Release\libdns.lib" \ "..\..\..\..\lib\isc\win32\Release\libisc.lib" \ "..\..\..\..\lib\isccfg\win32\Release\libisccfg.lib" \ "..\..\..\..\lib\tests\win32\Release\libtests.lib" "..\..\..\..\Build\Release\t_db.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) $(LINK32) @<< $(LINK32_FLAGS) $(LINK32_OBJS) << $(_VC_MANIFEST_EMBED_EXE) !ELSEIF "$(CFG)" == "t_db - @PLATFORM@ Debug" OUTDIR=.\Debug INTDIR=.\Debug # Begin Custom Macros OutDir=.\Debug # End Custom Macros !IF "$(RECURSE)" == "0" ALL : "..\..\..\..\Build\Debug\t_db.exe" "$(OUTDIR)\t_db.bsc" !ELSE ALL : "libtests - @PLATFORM@ Debug" "libisccfg - @PLATFORM@ Debug" "libisc - @PLATFORM@ Debug" "libdns - @PLATFORM@ Debug" "..\..\..\..\Build\Debug\t_db.exe" "$(OUTDIR)\t_db.bsc" !ENDIF !IF "$(RECURSE)" == "1" CLEAN :"libdns - @PLATFORM@ DebugCLEAN" "libisc - @PLATFORM@ DebugCLEAN" "libtests - @PLATFORM@ DebugCLEAN" "libisccfg - @PLATFORM@ DebugCLEAN" !ELSE CLEAN : !ENDIF -@erase "$(INTDIR)\t_db.obj" -@erase "$(INTDIR)\t_db.sbr" -@erase "$(INTDIR)\vc60.idb" -@erase "$(INTDIR)\vc60.pdb" -@erase "$(OUTDIR)\t_db.bsc" -@erase "$(OUTDIR)\t_db.map" -@erase "$(OUTDIR)\t_db.pdb" -@erase "..\..\..\..\Build\Debug\t_db.exe" -@erase "..\..\..\..\Build\Debug\t_db.ilk" -@$(_VC_MANIFEST_CLEAN) "$(OUTDIR)" : if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" CPP_PROJ=/nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../../" @LIBXML2_INC@ @OPENSSL_INC@ /I "../../../../lib/isc/win32" /I "../../../../lib/isc/win32/include" /I "../../../../lib/isc/include" /I "../../../../lib/dns/win32/include" /I "../../../../lib/dns/include" /I "../../../../lib/isccfg/include" /I "../../../../lib/tests/include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "i386" /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c BSC32=bscmake.exe BSC32_FLAGS=/nologo /o"$(OUTDIR)\t_db.bsc" BSC32_SBRS= \ "$(INTDIR)\t_db.sbr" "$(OUTDIR)\t_db.bsc" : "$(OUTDIR)" $(BSC32_SBRS) $(BSC32) @<< $(BSC32_FLAGS) $(BSC32_SBRS) << LINK32=link.exe LINK32_FLAGS=user32.lib advapi32.lib kernel32.lib ws2_32.lib ../../../../lib/isc/win32/Debug/libisc.lib ../../../../lib/dns/win32/Debug/libdns.lib ../../../../lib/isccfg/win32/Debug/libisccfg.lib ../../../../lib/tests/win32/Debug/libtests.lib $(LIBXML) /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\t_db.pdb" /map:"$(INTDIR)\t_db.map" /debug @MACHINE@ /out:"../../../../Build/Debug/t_db.exe" /pdbtype:sept LINK32_OBJS= \ "$(INTDIR)\t_db.obj" \ "..\..\..\..\lib\dns\win32\Debug\libdns.lib" \ "..\..\..\..\lib\isc\win32\Debug\libisc.lib" \ "..\..\..\..\lib\isccfg\win32\Debug\libisccfg.lib" \ "..\..\..\..\lib\tests\win32\Debug\libtests.lib" "..\..\..\..\Build\Debug\t_db.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) $(LINK32) @<< $(LINK32_FLAGS) $(LINK32_OBJS) << $(_VC_MANIFEST_EMBED_EXE) !ENDIF .c{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .c{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << !IF "$(NO_EXTERNAL_DEPS)" != "1" !IF EXISTS("t_db.dep") !INCLUDE "t_db.dep" !ELSE !MESSAGE Warning: cannot find "t_db.dep" !ENDIF !ENDIF !IF "$(CFG)" == "t_db - @PLATFORM@ Release" || "$(CFG)" == "t_db - @PLATFORM@ Debug" SOURCE=..\t_db.c !IF "$(CFG)" == "t_db - @PLATFORM@ Release" "$(INTDIR)\t_db.obj" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ELSEIF "$(CFG)" == "t_db - @PLATFORM@ Debug" "$(INTDIR)\t_db.obj" "$(INTDIR)\t_db.sbr" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) !ENDIF !IF "$(CFG)" == "t_db - @PLATFORM@ Release" "libdns - @PLATFORM@ Release" : cd "..\..\..\..\lib\dns\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Release" cd "..\..\..\bin\tests\db\win32" "libdns - @PLATFORM@ ReleaseCLEAN" : cd "..\..\..\..\lib\dns\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Release" RECURSE=1 CLEAN cd "..\..\..\bin\tests\db\win32" !ELSEIF "$(CFG)" == "t_db - @PLATFORM@ Debug" "libdns - @PLATFORM@ Debug" : cd "..\..\..\..\lib\dns\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Debug" cd "..\..\..\bin\tests\db\win32" "libdns - @PLATFORM@ DebugCLEAN" : cd "..\..\..\..\lib\dns\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Debug" RECURSE=1 CLEAN cd "..\..\..\bin\tests\db\win32" !ENDIF !IF "$(CFG)" == "t_db - @PLATFORM@ Release" "libisc - @PLATFORM@ Release" : cd "..\..\..\..\lib\isc\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Release" cd "..\..\..\bin\tests\db\win32" "libisc - @PLATFORM@ ReleaseCLEAN" : cd "..\..\..\..\lib\isc\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Release" RECURSE=1 CLEAN cd "..\..\..\bin\tests\db\win32" !ELSEIF "$(CFG)" == "t_db - @PLATFORM@ Debug" "libisc - @PLATFORM@ Debug" : cd "..\..\..\..\lib\isc\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Debug" cd "..\..\..\bin\tests\db\win32" "libisc - @PLATFORM@ DebugCLEAN" : cd "..\..\..\..\lib\isc\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Debug" RECURSE=1 CLEAN cd "..\..\..\bin\tests\db\win32" !ENDIF !IF "$(CFG)" == "t_db - @PLATFORM@ Release" "libisccfg - @PLATFORM@ Release" : cd "..\..\..\..\lib\isccfg\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libisccfg.mak" CFG="libisccfg - @PLATFORM@ Release" cd "..\..\..\bin\tests\db\win32" "libisccfg - @PLATFORM@ ReleaseCLEAN" : cd "..\..\..\..\lib\isccfg\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libisccfg.mak" CFG="libisccfg - @PLATFORM@ Release" RECURSE=1 CLEAN cd "..\..\..\bin\tests\db\win32" !ELSEIF "$(CFG)" == "t_db - @PLATFORM@ Debug" "libisccfg - @PLATFORM@ Debug" : cd "..\..\..\..\lib\isccfg\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libisccfg.mak" CFG="libisccfg - @PLATFORM@ Debug" cd "..\..\..\bin\tests\db\win32" "libisccfg - @PLATFORM@ DebugCLEAN" : cd "..\..\..\..\lib\isccfg\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libisccfg.mak" CFG="libisccfg - @PLATFORM@ Debug" RECURSE=1 CLEAN cd "..\..\..\bin\tests\db\win32" !ENDIF !IF "$(CFG)" == "t_db - @PLATFORM@ Release" "libtests - @PLATFORM@ Release" : cd "..\..\..\..\lib\tests\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libtests.mak" CFG="libtests - @PLATFORM@ Release" cd "..\..\..\bin\tests\db\win32" "libtests - @PLATFORM@ ReleaseCLEAN" : cd "..\..\..\..\lib\tests\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libtests.mak" CFG="libtests - @PLATFORM@ Release" RECURSE=1 CLEAN cd "..\..\..\bin\tests\db\win32" !ELSEIF "$(CFG)" == "t_db - @PLATFORM@ Debug" "libtests - @PLATFORM@ Debug" : cd "..\..\..\..\lib\tests\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libtests.mak" CFG="libtests - @PLATFORM@ Debug" cd "..\..\..\bin\tests\db\win32" "libtests - @PLATFORM@ DebugCLEAN" : cd "..\..\..\..\lib\tests\win32" $(MAKE) /$(MAKEFLAGS) /F ".\libtests.mak" CFG="libtests - @PLATFORM@ Debug" RECURSE=1 CLEAN cd "..\..\..\bin\tests\db\win32" !ENDIF !ENDIF #################################################### # Commands to generate initial empty manifest file and the RC file # that references it, and for generating the .res file: $(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc $(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest type <<$@ #include 1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest" << KEEP $(_VC_MANIFEST_BASENAME).auto.manifest : type <<$@ << KEEP bind9-9.11.3+dfsg/bin/tests/db/win32/t_db.vcxproj.filters.in000066400000000000000000000016721325250447100234040ustar00rootroot00000000000000 {4FC737F1-C7A5-4376-A066-2A32D752A2FF} cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx {93995380-89BD-4b04-88EB-625FBE52EBFB} h;hpp;hxx;hm;inl;inc;xsd {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms Source Files bind9-9.11.3+dfsg/bin/tests/db/win32/t_db.vcxproj.in000066400000000000000000000154751325250447100217430ustar00rootroot00000000000000 Debug @PLATFORM@ Release @PLATFORM@ {E6338E67-3224-4E66-9463-7AD719DA9346} Win32Proj t_db Application true MultiByte Application false true MultiByte true ..\..\..\..\Build\$(Configuration)\ .\$(Configuration)\ false ..\..\..\..\Build\$(Configuration)\ .\$(Configuration)\ Level3 Disabled WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true .\$(Configuration)\$(TargetName).pch .\$(Configuration)\ .\$(Configuration)\ $(OutDir)$(TargetName).pdb true .\;..\..\..\..\;@LIBXML2_INC@@OPENSSL_INC@..\..\..\..\lib\isc\win32;..\..\..\..\lib\isc\win32\include;..\..\..\..\lib\isc\include;..\..\..\..\lib\dns\include;..\..\..\..\lib\isccfg\include;..\..\..\..\lib\tests\include;%(AdditionalIncludeDirectories) CompileAsC Console true ..\..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt) ..\..\..\..\lib\isc\win32\$(Configuration);..\..\..\..\lib\dns\win32\$(Configuration);..\..\..\..\lib\isccfg\win32\$(Configuration);..\..\..\..\lib\tests\win32\$(Configuration);%(AdditionalLibraryDirectories) @LIBXML2_LIB@libisc.lib;libdns.lib;libisccfg.lib;libtests.lib;ws2_32.lib;%(AdditionalDependencies) Level3 MaxSpeed true @INTRINSIC@ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) OnlyExplicitInline false true .\$(Configuration)\$(TargetName).pch .\$(Configuration)\ .\$(Configuration)\ $(OutDir)$(TargetName).pdb .\;..\..\..\..\;@LIBXML2_INC@@OPENSSL_INC@..\..\..\..\lib\isc\win32;..\..\..\..\lib\isc\win32\include;..\..\..\..\lib\isc\include;..\..\..\..\lib\dns\include;..\..\..\..\lib\isccfg\include;..\..\..\..\lib\tests\include;%(AdditionalIncludeDirectories) CompileAsC Console false true true ..\..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt) Default ..\..\..\..\lib\isc\win32\$(Configuration);..\..\..\..\lib\dns\win32\$(Configuration);..\..\..\..\lib\isccfg\win32\$(Configuration);..\..\..\..\lib\tests\win32\$(Configuration);%(AdditionalLibraryDirectories) @LIBXML2_LIB@libisc.lib;libdns.lib;libisccfg.lib;libtests.lib;ws2_32.lib;%(AdditionalDependencies) bind9-9.11.3+dfsg/bin/tests/db/win32/t_db.vcxproj.user000066400000000000000000000002171325250447100222770ustar00rootroot00000000000000 bind9-9.11.3+dfsg/bin/tests/db_test.c000066400000000000000000000562671325250447100172560ustar00rootroot00000000000000/* * Copyright (C) 1999-2001, 2004, 2005, 2007-2009, 2011-2013, 2015-2017 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* $Id: db_test.c,v 1.70 2011/08/29 23:46:44 tbox Exp $ */ /*! \file * \author * Principal Author: Bob Halley */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define MAXHOLD 100 #define MAXVERSIONS 100 typedef struct dbinfo { dns_db_t * db; dns_dbversion_t * version; dns_dbversion_t * wversion; dns_dbversion_t * rversions[MAXVERSIONS]; int rcount; dns_dbnode_t * hold_nodes[MAXHOLD]; int hold_count; dns_dbiterator_t * dbiterator; dns_dbversion_t * iversion; int pause_every; isc_boolean_t ascending; ISC_LINK(struct dbinfo) link; } dbinfo; static isc_mem_t * mctx = NULL; static char dbtype[128]; static dns_dbtable_t * dbtable; static ISC_LIST(dbinfo) dbs; static dbinfo * cache_dbi = NULL; static int pause_every = 0; static isc_boolean_t ascending = ISC_TRUE; static void print_result(const char *message, isc_result_t result) { if (message == NULL) message = ""; printf("%s%sresult %08x: %s\n", message, (*message == '\0') ? "" : " ", result, isc_result_totext(result)); } static void print_rdataset(dns_name_t *name, dns_rdataset_t *rdataset) { isc_buffer_t text; char t[1000]; isc_result_t result; isc_region_t r; isc_buffer_init(&text, t, sizeof(t)); result = dns_rdataset_totext(rdataset, name, ISC_FALSE, ISC_FALSE, &text); isc_buffer_usedregion(&text, &r); if (result == ISC_R_SUCCESS) printf("%.*s", (int)r.length, (char *)r.base); else print_result("", result); } static void print_rdatasets(dns_name_t *name, dns_rdatasetiter_t *rdsiter) { isc_result_t result; dns_rdataset_t rdataset; dns_rdataset_init(&rdataset); result = dns_rdatasetiter_first(rdsiter); while (result == ISC_R_SUCCESS) { dns_rdatasetiter_current(rdsiter, &rdataset); print_rdataset(name, &rdataset); dns_rdataset_disassociate(&rdataset); result = dns_rdatasetiter_next(rdsiter); } if (result != ISC_R_NOMORE) print_result("", result); } static dbinfo * select_db(char *origintext) { dns_fixedname_t forigin; dns_name_t *origin; isc_buffer_t source; size_t len; dbinfo *dbi; isc_result_t result; if (strcasecmp(origintext, "cache") == 0) { if (cache_dbi == NULL) printf("the cache does not exist\n"); return (cache_dbi); } len = strlen(origintext); isc_buffer_init(&source, origintext, len); isc_buffer_add(&source, len); dns_fixedname_init(&forigin); origin = dns_fixedname_name(&forigin); result = dns_name_fromtext(origin, &source, dns_rootname, 0, NULL); if (result != ISC_R_SUCCESS) { print_result("bad name", result); return (NULL); } for (dbi = ISC_LIST_HEAD(dbs); dbi != NULL; dbi = ISC_LIST_NEXT(dbi, link)) { if (dns_name_compare(dns_db_origin(dbi->db), origin) == 0) break; } return (dbi); } static void list(dbinfo *dbi, char *seektext) { dns_fixedname_t fname; dns_name_t *name; dns_dbnode_t *node; dns_rdatasetiter_t *rdsiter; isc_result_t result; int i; size_t len; dns_fixedname_t fseekname; dns_name_t *seekname; isc_buffer_t source; dns_fixedname_init(&fname); name = dns_fixedname_name(&fname); if (dbi->dbiterator == NULL) { INSIST(dbi->iversion == NULL); if (dns_db_iszone(dbi->db)) { if (dbi->version != NULL) dns_db_attachversion(dbi->db, dbi->version, &dbi->iversion); else dns_db_currentversion(dbi->db, &dbi->iversion); } result = dns_db_createiterator(dbi->db, 0, &dbi->dbiterator); if (result == ISC_R_SUCCESS) { if (seektext != NULL) { len = strlen(seektext); isc_buffer_init(&source, seektext, len); isc_buffer_add(&source, len); dns_fixedname_init(&fseekname); seekname = dns_fixedname_name(&fseekname); result = dns_name_fromtext(seekname, &source, dns_db_origin( dbi->db), 0, NULL); if (result == ISC_R_SUCCESS) result = dns_dbiterator_seek( dbi->dbiterator, seekname); } else if (dbi->ascending) result = dns_dbiterator_first(dbi->dbiterator); else result = dns_dbiterator_last(dbi->dbiterator); } } else result = ISC_R_SUCCESS; node = NULL; rdsiter = NULL; i = 0; while (result == ISC_R_SUCCESS) { result = dns_dbiterator_current(dbi->dbiterator, &node, name); if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) break; result = dns_db_allrdatasets(dbi->db, node, dbi->iversion, 0, &rdsiter); if (result != ISC_R_SUCCESS) { dns_db_detachnode(dbi->db, &node); break; } print_rdatasets(name, rdsiter); dns_rdatasetiter_destroy(&rdsiter); dns_db_detachnode(dbi->db, &node); if (dbi->ascending) result = dns_dbiterator_next(dbi->dbiterator); else result = dns_dbiterator_prev(dbi->dbiterator); i++; if (result == ISC_R_SUCCESS && i == dbi->pause_every) { printf("[more...]\n"); result = dns_dbiterator_pause(dbi->dbiterator); if (result == ISC_R_SUCCESS) return; } } if (result != ISC_R_NOMORE) print_result("", result); dns_dbiterator_destroy(&dbi->dbiterator); if (dbi->iversion != NULL) dns_db_closeversion(dbi->db, &dbi->iversion, ISC_FALSE); } static isc_result_t load(const char *filename, const char *origintext, isc_boolean_t cache) { dns_fixedname_t forigin; dns_name_t *origin; isc_result_t result; isc_buffer_t source; size_t len; dbinfo *dbi; unsigned int i; dbi = isc_mem_get(mctx, sizeof(*dbi)); if (dbi == NULL) return (ISC_R_NOMEMORY); dbi->db = NULL; dbi->version = NULL; dbi->wversion = NULL; for (i = 0; i < MAXVERSIONS; i++) dbi->rversions[i] = NULL; dbi->hold_count = 0; for (i = 0; i < MAXHOLD; i++) dbi->hold_nodes[i] = NULL; dbi->dbiterator = NULL; dbi->iversion = NULL; dbi->pause_every = pause_every; dbi->ascending = ascending; ISC_LINK_INIT(dbi, link); len = strlen(origintext); isc_buffer_constinit(&source, origintext, len); isc_buffer_add(&source, len); dns_fixedname_init(&forigin); origin = dns_fixedname_name(&forigin); result = dns_name_fromtext(origin, &source, dns_rootname, 0, NULL); if (result != ISC_R_SUCCESS) { isc_mem_put(mctx, dbi, sizeof(*dbi)); return (result); } result = dns_db_create(mctx, dbtype, origin, cache ? dns_dbtype_cache : dns_dbtype_zone, dns_rdataclass_in, 0, NULL, &dbi->db); if (result != ISC_R_SUCCESS) { isc_mem_put(mctx, dbi, sizeof(*dbi)); return (result); } printf("loading %s (%s)\n", filename, origintext); result = dns_db_load(dbi->db, filename); if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE) { dns_db_detach(&dbi->db); isc_mem_put(mctx, dbi, sizeof(*dbi)); return (result); } printf("loaded\n"); if (cache) { INSIST(cache_dbi == NULL); dns_dbtable_adddefault(dbtable, dbi->db); cache_dbi = dbi; } else { result = dns_dbtable_add(dbtable, dbi->db); if (result != ISC_R_SUCCESS) { dns_db_detach(&dbi->db); isc_mem_put(mctx, dbi, sizeof(*dbi)); return (result); } } ISC_LIST_APPEND(dbs, dbi, link); return (ISC_R_SUCCESS); } static void unload_all(void) { dbinfo *dbi, *dbi_next; for (dbi = ISC_LIST_HEAD(dbs); dbi != NULL; dbi = dbi_next) { dbi_next = ISC_LIST_NEXT(dbi, link); if (dns_db_iszone(dbi->db)) dns_dbtable_remove(dbtable, dbi->db); else { INSIST(dbi == cache_dbi); dns_dbtable_removedefault(dbtable); cache_dbi = NULL; } dns_db_detach(&dbi->db); ISC_LIST_UNLINK(dbs, dbi, link); isc_mem_put(mctx, dbi, sizeof(*dbi)); } } #define DBI_CHECK(dbi) \ if ((dbi) == NULL) { \ printf("You must first select a database with !DB\n"); \ continue; \ } int main(int argc, char *argv[]) { dns_db_t *db; dns_dbnode_t *node; isc_result_t result; dns_name_t name; dns_offsets_t offsets; size_t len; isc_buffer_t source, target; char s[1000]; char b[255]; dns_rdataset_t rdataset, sigrdataset; int ch; dns_rdatatype_t type = 1; isc_boolean_t printnode = ISC_FALSE; isc_boolean_t addmode = ISC_FALSE; isc_boolean_t delmode = ISC_FALSE; isc_boolean_t holdmode = ISC_FALSE; isc_boolean_t verbose = ISC_FALSE; isc_boolean_t done = ISC_FALSE; isc_boolean_t quiet = ISC_FALSE; isc_boolean_t time_lookups = ISC_FALSE; isc_boolean_t found_as; isc_boolean_t find_zonecut = ISC_FALSE; isc_boolean_t noexact_zonecut = ISC_FALSE; int i, v; dns_rdatasetiter_t *rdsiter; char t1[256]; char t2[256]; isc_buffer_t tb1, tb2; isc_region_t r1, r2; dns_fixedname_t foundname; dns_name_t *fname; unsigned int options = 0, zcoptions; isc_time_t start, finish; const char *origintext; dbinfo *dbi; dns_dbversion_t *version; dns_name_t *origin; size_t memory_quota = 0; dns_trust_t trust = 0; unsigned int addopts; isc_log_t *lctx = NULL; size_t n; dns_result_register(); RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS); RUNTIME_CHECK(dns_dbtable_create(mctx, dns_rdataclass_in, &dbtable) == ISC_R_SUCCESS); snprintf(dbtype, sizeof(dbtype), "rbt"); while ((ch = isc_commandline_parse(argc, argv, "c:d:t:z:P:Q:glpqvT")) != -1) { switch (ch) { case 'c': result = load(isc_commandline_argument, ".", ISC_TRUE); if (result != ISC_R_SUCCESS) printf("cache load(%s) %08x: %s\n", isc_commandline_argument, result, isc_result_totext(result)); break; case 'd': n = strlcpy(dbtype, isc_commandline_argument, sizeof(dbtype)); if (n >= sizeof(dbtype)) { fprintf(stderr, "bad db type '%s'\n", isc_commandline_argument); exit(1); } break; case 'g': options |= (DNS_DBFIND_GLUEOK|DNS_DBFIND_VALIDATEGLUE); break; case 'l': RUNTIME_CHECK(isc_log_create(mctx, &lctx, NULL) == ISC_R_SUCCESS); isc_log_setcontext(lctx); dns_log_init(lctx); dns_log_setcontext(lctx); break; case 'q': quiet = ISC_TRUE; verbose = ISC_FALSE; break; case 'p': printnode = ISC_TRUE; break; case 'P': pause_every = atoi(isc_commandline_argument); break; case 'Q': memory_quota = atoi(isc_commandline_argument); isc_mem_setquota(mctx, memory_quota); break; case 't': type = atoi(isc_commandline_argument); break; case 'T': time_lookups = ISC_TRUE; break; case 'v': verbose = ISC_TRUE; break; case 'z': origintext = strrchr(isc_commandline_argument, '/'); if (origintext == NULL) origintext = isc_commandline_argument; else origintext++; /* Skip '/'. */ result = load(isc_commandline_argument, origintext, ISC_FALSE); if (result != ISC_R_SUCCESS) printf("zone load(%s) %08x: %s\n", isc_commandline_argument, result, isc_result_totext(result)); break; } } argc -= isc_commandline_index; argv += isc_commandline_index; POST(argv); if (argc != 0) printf("ignoring trailing arguments\n"); /* * Some final initialization... */ dns_fixedname_init(&foundname); fname = dns_fixedname_name(&foundname); dbi = NULL; origin = dns_rootname; version = NULL; if (time_lookups) { TIME_NOW(&start); } while (!done) { if (!quiet) printf("\n"); if (fgets(s, sizeof(s), stdin) == NULL) { done = ISC_TRUE; continue; } len = strlen(s); if (len > 0U && s[len - 1] == '\n') { s[len - 1] = '\0'; len--; } if (verbose && dbi != NULL) { if (dbi->wversion != NULL) printf("future version (%p)\n", dbi->wversion); for (i = 0; i < dbi->rcount; i++) if (dbi->rversions[i] != NULL) printf("open version %d (%p)\n", i, dbi->rversions[i]); } dns_name_init(&name, offsets); if (strcmp(s, "!R") == 0) { DBI_CHECK(dbi); if (dbi->rcount == MAXVERSIONS) { printf("too many open versions\n"); continue; } dns_db_currentversion(dbi->db, &dbi->rversions[dbi->rcount]); printf("opened version %d\n", dbi->rcount); dbi->version = dbi->rversions[dbi->rcount]; version = dbi->version; dbi->rcount++; continue; } else if (strcmp(s, "!W") == 0) { DBI_CHECK(dbi); if (dbi->wversion != NULL) { printf("using existing future version\n"); dbi->version = dbi->wversion; version = dbi->version; continue; } result = dns_db_newversion(dbi->db, &dbi->wversion); if (result != ISC_R_SUCCESS) print_result("", result); else printf("newversion\n"); dbi->version = dbi->wversion; version = dbi->version; continue; } else if (strcmp(s, "!C") == 0) { DBI_CHECK(dbi); addmode = ISC_FALSE; delmode = ISC_FALSE; if (dbi->version == NULL) continue; if (dbi->version == dbi->wversion) { printf("closing future version\n"); dbi->wversion = NULL; } else { for (i = 0; i < dbi->rcount; i++) { if (dbi->version == dbi->rversions[i]) { dbi->rversions[i] = NULL; printf("closing open version %d\n", i); break; } } } dns_db_closeversion(dbi->db, &dbi->version, ISC_TRUE); version = NULL; continue; } else if (strcmp(s, "!X") == 0) { DBI_CHECK(dbi); addmode = ISC_FALSE; delmode = ISC_FALSE; if (dbi->version == NULL) continue; if (dbi->version == dbi->wversion) { printf("aborting future version\n"); dbi->wversion = NULL; } else { for (i = 0; i < dbi->rcount; i++) { if (dbi->version == dbi->rversions[i]) { dbi->rversions[i] = NULL; printf("closing open version %d\n", i); break; } } } dns_db_closeversion(dbi->db, &dbi->version, ISC_FALSE); version = NULL; continue; } else if (strcmp(s, "!A") == 0) { DBI_CHECK(dbi); delmode = ISC_FALSE; if (addmode) addmode = ISC_FALSE; else addmode = ISC_TRUE; printf("addmode = %s\n", addmode ? "TRUE" : "FALSE"); continue; } else if (strcmp(s, "!D") == 0) { DBI_CHECK(dbi); addmode = ISC_FALSE; if (delmode) delmode = ISC_FALSE; else delmode = ISC_TRUE; printf("delmode = %s\n", delmode ? "TRUE" : "FALSE"); continue; } else if (strcmp(s, "!H") == 0) { DBI_CHECK(dbi); if (holdmode) holdmode = ISC_FALSE; else holdmode = ISC_TRUE; printf("holdmode = %s\n", holdmode ? "TRUE" : "FALSE"); continue; } else if (strcmp(s, "!HR") == 0) { DBI_CHECK(dbi); for (i = 0; i < dbi->hold_count; i++) dns_db_detachnode(dbi->db, &dbi->hold_nodes[i]); dbi->hold_count = 0; holdmode = ISC_FALSE; printf("held nodes have been detached\n"); continue; } else if (strcmp(s, "!VC") == 0) { DBI_CHECK(dbi); printf("switching to current version\n"); dbi->version = NULL; version = NULL; continue; } else if (strstr(s, "!V") == s) { DBI_CHECK(dbi); v = atoi(&s[2]); if (v >= dbi->rcount || v < 0) { printf("unknown open version %d\n", v); continue; } if (dbi->rversions[v] == NULL) { printf("version %d is not open\n", v); continue; } printf("switching to open version %d\n", v); dbi->version = dbi->rversions[v]; version = dbi->version; continue; } else if (strstr(s, "!TR") == s) { trust = (unsigned int)atoi(&s[3]); printf("trust level is now %u\n", (unsigned int)trust); continue; } else if (strstr(s, "!T") == s) { type = (unsigned int)atoi(&s[2]); printf("now searching for type %u\n", type); continue; } else if (strcmp(s, "!G") == 0) { if ((options & DNS_DBFIND_GLUEOK) != 0) options &= ~DNS_DBFIND_GLUEOK; else options |= DNS_DBFIND_GLUEOK; printf("glue ok = %s\n", ((options & DNS_DBFIND_GLUEOK) != 0) ? "TRUE" : "FALSE"); continue; } else if (strcmp(s, "!GV") == 0) { if ((options & DNS_DBFIND_VALIDATEGLUE) != 0) options &= ~DNS_DBFIND_VALIDATEGLUE; else options |= DNS_DBFIND_VALIDATEGLUE; printf("validate glue = %s\n", ((options & DNS_DBFIND_VALIDATEGLUE) != 0) ? "TRUE" : "FALSE"); continue; } else if (strcmp(s, "!WC") == 0) { if ((options & DNS_DBFIND_NOWILD) != 0) options &= ~DNS_DBFIND_NOWILD; else options |= DNS_DBFIND_NOWILD; printf("wildcard matching = %s\n", ((options & DNS_DBFIND_NOWILD) == 0) ? "TRUE" : "FALSE"); continue; } else if (strstr(s, "!LS ") == s) { DBI_CHECK(dbi); list(dbi, &s[4]); continue; } else if (strcmp(s, "!LS") == 0) { DBI_CHECK(dbi); list(dbi, NULL); continue; } else if (strstr(s, "!DU ") == s) { DBI_CHECK(dbi); result = dns_db_dump(dbi->db, dbi->version, s+4); if (result != ISC_R_SUCCESS) { printf("\n"); print_result("", result); } continue; } else if (strcmp(s, "!PN") == 0) { if (printnode) printnode = ISC_FALSE; else printnode = ISC_TRUE; printf("printnode = %s\n", printnode ? "TRUE" : "FALSE"); continue; } else if (strstr(s, "!P") == s) { DBI_CHECK(dbi); v = atoi(&s[2]); dbi->pause_every = v; continue; } else if (strcmp(s, "!+") == 0) { DBI_CHECK(dbi); dbi->ascending = ISC_TRUE; continue; } else if (strcmp(s, "!-") == 0) { DBI_CHECK(dbi); dbi->ascending = ISC_FALSE; continue; } else if (strcmp(s, "!DB") == 0) { dbi = NULL; origin = dns_rootname; version = NULL; printf("now searching all databases\n"); continue; } else if (strncmp(s, "!DB ", 4) == 0) { dbi = select_db(s+4); if (dbi != NULL) { db = dbi->db; origin = dns_db_origin(dbi->db); version = dbi->version; addmode = ISC_FALSE; delmode = ISC_FALSE; holdmode = ISC_FALSE; } else { db = NULL; version = NULL; origin = dns_rootname; printf("database not found; " "now searching all databases\n"); } continue; } else if (strcmp(s, "!ZC") == 0) { if (find_zonecut) find_zonecut = ISC_FALSE; else find_zonecut = ISC_TRUE; printf("find_zonecut = %s\n", find_zonecut ? "TRUE" : "FALSE"); continue; } else if (strcmp(s, "!NZ") == 0) { if (noexact_zonecut) noexact_zonecut = ISC_FALSE; else noexact_zonecut = ISC_TRUE; printf("noexact_zonecut = %s\n", noexact_zonecut ? "TRUE" : "FALSE"); continue; } isc_buffer_init(&source, s, len); isc_buffer_add(&source, len); isc_buffer_init(&target, b, sizeof(b)); result = dns_name_fromtext(&name, &source, origin, 0, &target); if (result != ISC_R_SUCCESS) { print_result("bad name: ", result); continue; } if (dbi == NULL) { zcoptions = 0; if (noexact_zonecut) zcoptions |= DNS_DBTABLEFIND_NOEXACT; db = NULL; result = dns_dbtable_find(dbtable, &name, zcoptions, &db); if (result != ISC_R_SUCCESS && result != DNS_R_PARTIALMATCH) { if (!quiet) { printf("\n"); print_result("", result); } continue; } isc_buffer_init(&tb1, t1, sizeof(t1)); result = dns_name_totext(dns_db_origin(db), ISC_FALSE, &tb1); if (result != ISC_R_SUCCESS) { printf("\n"); print_result("", result); dns_db_detach(&db); continue; } isc_buffer_usedregion(&tb1, &r1); printf("\ndatabase = %.*s (%s)\n", (int)r1.length, r1.base, (dns_db_iszone(db)) ? "zone" : "cache"); } node = NULL; dns_rdataset_init(&rdataset); dns_rdataset_init(&sigrdataset); if (find_zonecut && dns_db_iscache(db)) { zcoptions = options; if (noexact_zonecut) zcoptions |= DNS_DBFIND_NOEXACT; result = dns_db_findzonecut(db, &name, zcoptions, 0, &node, fname, &rdataset, &sigrdataset); } else { result = dns_db_find(db, &name, version, type, options, 0, &node, fname, &rdataset, &sigrdataset); } if (!quiet) { if (dbi != NULL) printf("\n"); print_result("", result); } found_as = ISC_FALSE; switch (result) { case ISC_R_SUCCESS: case DNS_R_GLUE: case DNS_R_CNAME: case DNS_R_ZONECUT: break; case DNS_R_DNAME: case DNS_R_DELEGATION: found_as = ISC_TRUE; break; case DNS_R_NXRRSET: if (dns_rdataset_isassociated(&rdataset)) break; if (dbi != NULL) { if (holdmode) { RUNTIME_CHECK(dbi->hold_count < MAXHOLD); dbi->hold_nodes[dbi->hold_count++] = node; node = NULL; } else dns_db_detachnode(db, &node); } else { dns_db_detachnode(db, &node); dns_db_detach(&db); } continue; case DNS_R_NXDOMAIN: if (dns_rdataset_isassociated(&rdataset)) break; /* FALLTHROUGH */ default: if (dbi == NULL) dns_db_detach(&db); if (quiet) print_result("", result); continue; } if (found_as && !quiet) { isc_buffer_init(&tb1, t1, sizeof(t1)); isc_buffer_init(&tb2, t2, sizeof(t2)); result = dns_name_totext(&name, ISC_FALSE, &tb1); if (result != ISC_R_SUCCESS) { print_result("", result); dns_db_detachnode(db, &node); if (dbi == NULL) dns_db_detach(&db); continue; } result = dns_name_totext(fname, ISC_FALSE, &tb2); if (result != ISC_R_SUCCESS) { print_result("", result); dns_db_detachnode(db, &node); if (dbi == NULL) dns_db_detach(&db); continue; } isc_buffer_usedregion(&tb1, &r1); isc_buffer_usedregion(&tb2, &r2); printf("found %.*s as %.*s\n", (int)r1.length, r1.base, (int)r2.length, r2.base); } if (printnode) dns_db_printnode(db, node, stdout); if (!found_as && type == dns_rdatatype_any) { rdsiter = NULL; result = dns_db_allrdatasets(db, node, version, 0, &rdsiter); if (result == ISC_R_SUCCESS) { if (!quiet) print_rdatasets(fname, rdsiter); dns_rdatasetiter_destroy(&rdsiter); } else print_result("", result); } else { if (!quiet) print_rdataset(fname, &rdataset); if (dns_rdataset_isassociated(&sigrdataset)) { if (!quiet) print_rdataset(fname, &sigrdataset); dns_rdataset_disassociate(&sigrdataset); } if (dbi != NULL && addmode && !found_as) { rdataset.ttl++; rdataset.trust = trust; if (dns_db_iszone(db)) addopts = DNS_DBADD_MERGE; else addopts = 0; result = dns_db_addrdataset(db, node, version, 0, &rdataset, addopts, NULL); if (result != ISC_R_SUCCESS) print_result("", result); if (printnode) dns_db_printnode(db, node, stdout); } else if (dbi != NULL && delmode && !found_as) { result = dns_db_deleterdataset(db, node, version, type, 0); if (result != ISC_R_SUCCESS) print_result("", result); if (printnode) dns_db_printnode(db, node, stdout); } dns_rdataset_disassociate(&rdataset); } if (dbi != NULL) { if (holdmode) { RUNTIME_CHECK(dbi->hold_count < MAXHOLD); dbi->hold_nodes[dbi->hold_count++] = node; node = NULL; } else dns_db_detachnode(db, &node); } else { dns_db_detachnode(db, &node); dns_db_detach(&db); } } if (time_lookups) { isc_uint64_t usec; TIME_NOW(&finish); usec = isc_time_microdiff(&finish, &start); printf("elapsed time: %lu.%06lu seconds\n", (unsigned long)(usec / 1000000), (unsigned long)(usec % 1000000)); } unload_all(); dns_dbtable_detach(&dbtable); if (lctx != NULL) isc_log_destroy(&lctx); if (!quiet) isc_mem_stats(mctx, stdout); return (0); } bind9-9.11.3+dfsg/bin/tests/dnssec-signzone/000077500000000000000000000000001325250447100205575ustar00rootroot00000000000000bind9-9.11.3+dfsg/bin/tests/dnssec-signzone/Kexample.com.+005+07065.key000066400000000000000000000003231325250447100246450ustar00rootroot00000000000000example.com. IN DNSKEY 256 3 5 AwEAAaF0z17DdkBAKiYScVNqzsqXw7Vz/Cx5OCw7T/6RnU/KiGv815kl H2obywRZX2ZcEg9R8SUzQiP9ygY0s1xF5IFYi32HsWftNV7V/gNwNrMn GC0gV2e3OawsQ2CYWZZVwObr/fmcKIXuY6eRdJtyOilMRhlvroJdXZw1 CQdicxpZ bind9-9.11.3+dfsg/bin/tests/dnssec-signzone/Kexample.com.+005+07065.private000066400000000000000000000016511325250447100255340ustar00rootroot00000000000000Private-key-format: v1.2 Algorithm: 5 (RSASHA1) Modulus: oXTPXsN2QEAqJhJxU2rOypfDtXP8LHk4LDtP/pGdT8qIa/zXmSUfahvLBFlfZlwSD1HxJTNCI/3KBjSzXEXkgViLfYexZ+01XtX+A3A2sycYLSBXZ7c5rCxDYJhZllXA5uv9+Zwohe5jp5F0m3I6KUxGGW+ugl1dnDUJB2JzGlk= PublicExponent: AQAB PrivateExponent: QrbJmRabHiFlSSYFvbo8iGn9bFTotlfAZkZ732y72+SMSlLHo3g7atThJoLncJxKuhnZ0s1DXyvW9omAM3iN2lxfVDW58at1amj/lWRDYkjI0fM8z6eyrF4U2lHKDM2YEstg+sGAAs5DUZBbli4Y7+zHjhxSKLYvRf4AJvX8aoE= Prime1: 0259CgdF0JW+miedRZXC6tn3FijZJ4/j5edzd8IpTpdUSZupQg9hMP1ot7crreNq7MnzO0Z2ImbowUx8CDOuXQ== Prime2: w31/WLM2275Z1tsHEOhrntUQCUk55B4PNOCmM4hjp0vAvA/SVSgAYRNb7rc/ujaLf0DnxnDsnVsFAS2PmvQELQ== Exponent1: yKPhJNMh/X8dEUzmglJMVnHheLXq3RA/RL0PZmZqrJoO8os1Y+sUYFkaNr0sRie6IFrE50tGb/8YgdcDHQVuQQ== Exponent2: lVhDuGy5RSjnk1eiz0zwIthctutlOZupPFk/P3E7yGv74vAnXH0BxSe3/Oer3MOc0GuyZYyRhyko6px28AbpRQ== Coefficient: Hjup1nDnPFkQrxU2qLQBJrDz+ipw0RkNhsjWs6IgAq1Mq4sFV50bR9hOTLDd9oNhhtAwVjF+Oc0WIq+M1Mi6Ow== bind9-9.11.3+dfsg/bin/tests/dnssec-signzone/Kexample.com.+005+23362.key000066400000000000000000000003231325250447100246430ustar00rootroot00000000000000example.com. IN DNSKEY 257 3 5 AwEAAbuWh5W3eGwixISqPwxszotQ0246KqhUB2Mb6JqNMJd6cWR66IrX YnevpIHsb6oanqJmVzOcJ6Yj3rXOIYtYYXgLbT7EJ8x7BNCZPHxG+w5C 7I1WsDbT6eGf//FLn2c4odKLOXaWCVITeNy61w43IlteIT9Q1egKdt+8 a7X9605j bind9-9.11.3+dfsg/bin/tests/dnssec-signzone/Kexample.com.+005+23362.private000066400000000000000000000016511325250447100255320ustar00rootroot00000000000000Private-key-format: v1.2 Algorithm: 5 (RSASHA1) Modulus: u5aHlbd4bCLEhKo/DGzOi1DTbjoqqFQHYxvomo0wl3pxZHroitdid6+kgexvqhqeomZXM5wnpiPetc4hi1hheAttPsQnzHsE0Jk8fEb7DkLsjVawNtPp4Z//8UufZzih0os5dpYJUhN43LrXDjciW14hP1DV6Ap237xrtf3rTmM= PublicExponent: AQAB PrivateExponent: XZSssv3CL3/wtZYQuewV5d4+e8C8wxiYTtL/aQqCcS7+HnhKRelJEBgpYz9GPX/mH3Iakn6WMQW39s6MYW2HwXUnqhsvHoyabGX0Dbc/1LcY4J2VPgzVHwSXYm+j4unOByOOS4KoBtUAQxJsTBokVZrZ5pKsLUK9X2gdywYw+PE= Prime1: 9fB7PaygjKoT1nbbeEMy1KYNqetg3zmN49Mk6ilEWxzJXKSSjTIhdkiLGXtYmE8rDBLBiYm8YWNe7YdA9PbQ7Q== Prime2: w0L7mTOLDecH3XAkC/wvALv8K9KSoZ31ajidKBxV15u8awj5AxDG7gjerYgCLjU1fq1GulMr11j8r4ftQn3Cjw== Exponent1: Up52yEE1rgt0npdPIxdv+//Ml0h7QoITKHXF8OPsEq+Y9YZTtRsiIpo8IFNPb9somuWyHoImxpCbUzAcoi5IAQ== Exponent2: uYTbvYx+UsAt9dOFPCnnkqAJEK3qCUomET0m/CQn30mldGC7DpGTIDgnMeLmh3agk/IYIBHDtsBinHfeEe2guw== Coefficient: FiHAet8On9Yaz1ksEAlCWulwck3zPWIsgqJBM2J4kHhgHTm17mZyxtVxIzLAMBNMIBcFl40FCpmPmTLY5QK5mw== bind9-9.11.3+dfsg/bin/tests/dnssec-signzone/bogus-ksk.key000066400000000000000000000004561325250447100232030ustar00rootroot00000000000000; ; This is a bogus key. It will not have a .private file. ; ; This will be key id 7091 ; example.com. IN DNSKEY 257 3 5 AwEAAaF0z17DdkBAKiYScVNqzsqXw7Vz/Cx5OCw7T/6RnU/KiGv815kl H2obywRZX2ZcEg9R8SUzQiP9ygY0s1xF5IFYi32HsWftNV7V/gNwNrMn GC0gV2e3OawsQ2CYWZZVwObr/fmcKIXuY6eRdJtyOilMRhlvroJdXZw1 CQdicxpz bind9-9.11.3+dfsg/bin/tests/dnssec-signzone/bogus-zsk.key000066400000000000000000000004561325250447100232220ustar00rootroot00000000000000; ; This is a bogus key. It will not have a .private file. ; ; This will be key id 7092 ; example.com. IN DNSKEY 256 3 5 AwEAAaF0z17DdkBAKiYScVNqzsqXw7Vz/Cx5OCw7T/6RnU/KiGv815kl H2obywRZX2ZcEg9R8SUzQiP9ygY0s1xF5IFYi32HsWftNV7V/gNwNrMn GC0gV2e3OawsQ2CYWZZVwObr/fmcKIXuY6eRdJtyOilMRhlvroJdXZw1 CQdicxpz bind9-9.11.3+dfsg/bin/tests/dnssec-signzone/run-test.sh000066400000000000000000000022351325250447100226760ustar00rootroot00000000000000#!/bin/sh # # Copyright (C) 2009, 2012, 2016 Internet Systems Consortium, Inc. ("ISC") # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. # $Id: run-test.sh,v 1.3 2009/06/04 02:56:47 tbox Exp $ sign="../../dnssec/dnssec-signzone -f signed.zone -o example.com." signit() { rm -f signed.zone grep '^;' $zone $sign $zone } expect_success() { if ! test -f signed.zone ; then echo "Error: expected success, but sign failed for $zone." else echo "Success: Sign succeeded for $zone." fi } expect_failure() { if test -f signed.zone ; then echo "Error: expected failure, but sign succeeded for $zone." else echo "Success: Sign failed (expected) for $zone" fi } zone="test1.zone" ; signit ; expect_success zone="test2.zone" ; signit ; expect_failure zone="test3.zone" ; signit ; expect_failure zone="test4.zone" ; signit ; expect_success zone="test5.zone" ; signit ; expect_failure zone="test6.zone" ; signit ; expect_failure zone="test7.zone" ; signit ; expect_failure zone="test8.zone" ; signit ; expect_failure bind9-9.11.3+dfsg/bin/tests/dnssec-signzone/test1.zone000066400000000000000000000005101325250447100225100ustar00rootroot00000000000000; ; This is a zone which has two DNSKEY records, both of which have ; existing private key files available. They should be loaded automatically ; and the zone correctly signed. ; $TTL 3600 example.com. IN SOA ns hostmaster 00090000 1200 3600 604800 300 $include Kexample.com.+005+07065.key $include Kexample.com.+005+23362.key bind9-9.11.3+dfsg/bin/tests/dnssec-signzone/test2.zone000066400000000000000000000004251325250447100225160ustar00rootroot00000000000000; ; This is a zone which has one non-KSK DNSKEY record for which the ; private key file exists. It should be loaded automatically and the zone ; correctly signed. ; $TTL 3600 example.com. IN SOA ns hostmaster 00090000 1200 3600 604800 300 $include Kexample.com.+005+07065.key bind9-9.11.3+dfsg/bin/tests/dnssec-signzone/test3.zone000066400000000000000000000004771325250447100225260ustar00rootroot00000000000000; ; This is a zone which has one KSK DNSKEY record for which the ; private key file exists. It should be loaded automatically. As there ; is no non-KSK DNSKEY the resulting zone should be rejected. ; $TTL 3600 example.com. IN SOA ns hostmaster 00090000 1200 3600 604800 300 $include Kexample.com.+005+23362.key bind9-9.11.3+dfsg/bin/tests/dnssec-signzone/test4.zone000066400000000000000000000005141325250447100225170ustar00rootroot00000000000000; ; This is a zone which has three DNSKEY records, two (KSK + ZSK) of ; which have existing private key files available. The third is a ; pre-published ZSK. ; $TTL 3600 example.com. IN SOA ns hostmaster 00090000 1200 3600 604800 300 $include Kexample.com.+005+07065.key $include Kexample.com.+005+23362.key $include bogus-zsk.key bind9-9.11.3+dfsg/bin/tests/dnssec-signzone/test5.zone000066400000000000000000000004721325250447100225230ustar00rootroot00000000000000; ; This is a zone which has three DNSKEY records, two (KSK +ZSK) of which ; have existing private key files available. The third is a KSK. ; $TTL 3600 example.com. IN SOA ns hostmaster 00090000 1200 3600 604800 300 $include Kexample.com.+005+07065.key $include Kexample.com.+005+23362.key $include bogus-ksk.key bind9-9.11.3+dfsg/bin/tests/dnssec-signzone/test6.zone000066400000000000000000000006021325250447100225170ustar00rootroot00000000000000; ; This is a zone which has four DNSKEY records, two (KK + ZSK) of which ; have existing private key files available. There are also a KSK and ZSK ; for which there will be no signatures. ; $TTL 3600 example.com. IN SOA ns hostmaster 00090000 1200 3600 604800 300 $include Kexample.com.+005+07065.key $include Kexample.com.+005+23362.key $include bogus-ksk.key $include bogus-zsk.key bind9-9.11.3+dfsg/bin/tests/dnssec-signzone/test7.zone000066400000000000000000000004401325250447100225200ustar00rootroot00000000000000; ; This is a zone which has two DNSKEY records, none of which have ; existing private key files available. The resulting zone should fail ; the consistancy tests. ; $TTL 3600 example.com. IN SOA ns hostmaster 00090000 1200 3600 604800 300 $include bogus-ksk.key $include bogus-zsk.key bind9-9.11.3+dfsg/bin/tests/dnssec-signzone/test8.zone000066400000000000000000000004531325250447100225250ustar00rootroot00000000000000; ; This is a zone which has two DNSKEY records, one of which, ; the KSK, has a private key. The resulting zone should be rejected as ; it has no ZSK signatures. ; $TTL 3600 example.com. IN SOA ns hostmaster 00090000 1200 3600 604800 300 $include Kexample.com.+005+23362.key $include bogus-zsk.key bind9-9.11.3+dfsg/bin/tests/dst/000077500000000000000000000000001325250447100162405ustar00rootroot00000000000000bind9-9.11.3+dfsg/bin/tests/dst/Kdh.+002+18602.key.in000066400000000000000000000002401325250447100211100ustar00rootroot00000000000000dh. IN KEY 0 2 2 AAEBAAAAYIHI/wjtOagNga9GILSoS02IVelgLilPE/TfhtvShsiDAXqb IfxQcj2JkuOnNLs5ttb2WZXWl5/jsSjIxHMwMF2XY4gwt/lwHBf/vgYH r7aIxnKXov1jk9rymTLHGKIOtg== bind9-9.11.3+dfsg/bin/tests/dst/Kdh.+002+18602.private.in000066400000000000000000000007561325250447100220060ustar00rootroot00000000000000Private-key-format: v1.2 Algorithm: 2 (DH) Prime(p): ///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxObIlFKCHmONATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjo2IP////////// Generator(g): Ag== Private_value(x): bpdsGQ1jbV3f2CGN/0Pk5KM1MlkFmMryPO1J1zoGn585fRmc9Ygw6l/HKmi2ViiDNorvd9/eV9uyYO6lYZC82R3D7rST1mAqCwbg/8gNE5dXBRbRIIq3qIl6GUYYs8mK Public_value(y): gcj/CO05qA2Br0YgtKhLTYhV6WAuKU8T9N+G29KGyIMBepsh/FByPYmS46c0uzm21vZZldaXn+OxKMjEczAwXZdjiDC3+XAcF/++BgevtojGcpei/WOT2vKZMscYog62 bind9-9.11.3+dfsg/bin/tests/dst/Kdh.+002+48957.key.in000066400000000000000000000002401325250447100211300ustar00rootroot00000000000000dh. IN KEY 0 2 2 AAEBAAAAYOuaKjyMXYame2F6/ZFdEmXv0a2edB+69PEZgrExA6SJlivn 4KqAsfBHr/+0BCb+7nfWeMDSh2BXnSzWkXF1wMaCHMuz9EleG1gKFKeV Q9gKli88Cb8/jbovWChrGBNp2w== bind9-9.11.3+dfsg/bin/tests/dst/Kdh.+002+48957.private.in000066400000000000000000000007561325250447100220260ustar00rootroot00000000000000Private-key-format: v1.2 Algorithm: 2 (DH) Prime(p): ///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxObIlFKCHmONATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjo2IP////////// Generator(g): Ag== Private_value(x): WJG0moh+QoZV+DYhqW7Z6O6TYpYGtSlN0Ym6JV6VRnzeH69OqMUFivqZorj3a3ofR/4zogNVyy5KLLj2NFTaLGP4Hcvt7uETJik6HrjLMhGf40QPXYgVK57Im0rv88Ca Public_value(y): 65oqPIxdhqZ7YXr9kV0SZe/RrZ50H7r08RmCsTEDpImWK+fgqoCx8Eev/7QEJv7ud9Z4wNKHYFedLNaRcXXAxoIcy7P0SV4bWAoUp5VD2AqWLzwJvz+Nui9YKGsYE2nb bind9-9.11.3+dfsg/bin/tests/dst/Ktest.+001+00002.key.in000066400000000000000000000000321325250447100214530ustar00rootroot00000000000000test. IN DNSKEY 49152 2 1 bind9-9.11.3+dfsg/bin/tests/dst/Ktest.+001+54622.key.in000066400000000000000000000002111325250447100214730ustar00rootroot00000000000000test. IN DNSKEY 257 3 1 AQPQjwSpaVzxIgRCpiUoozUQKGh2oX8NIFKDOvtxK+tn536OZg2cROKTlgGEHXJK9YHfW/6nzQULTVpb63P+SQMmjCCidb8IYyhItixRztVeJQ== bind9-9.11.3+dfsg/bin/tests/dst/Ktest.+001+54622.private.in000066400000000000000000000012051325250447100223610ustar00rootroot00000000000000Private-key-format: v1.2 Algorithm: 1 (RSA) Modulus: 0I8EqWlc8SIEQqYlKKM1EChodqF/DSBSgzr7cSvrZ+d+jmYNnETik5YBhB1ySvWB31v+p80FC01aW+tz/kkDJowgonW/CGMoSLYsUc7VXiU= PublicExponent: Aw== PrivateExponent: iwoDG5uTS2wC1xluGxd4tXBFpGuqCMA3AidSS3Kc7++ptEQJEtiXC9kfCJMvZhGfQLaujft2OgrmkcuDVtPIbQWEENhyJhb4Lk82kFXbfus= Prime1: /rSKuzcZY7R5cY2YWD4CiBNyj9WJMq1wWmBnb9+5M08nTl5E9NW5qQ== Prime2: 0Z5shXQYd16E2Gs6e5WxtO0Oqlly2KkSqXohwTQWDWTb8Pw0WTZmHQ== Exponent1: qc2x0iS7l82mS7O65X6sWrehtTkGIcj1kZWaSpUmIjTE3umDTePRGw== Exponent2: i77zA6K6+j8DOvIm/Q52eJ4JxuZMkHC3G6bBK3gOs5iSoKgi5iREEw== Coefficient: 3+wYZB0SJad7z2EsjzgbSlg6CawoaOvrROGSbwSiW5DCsMFROudOTw== bind9-9.11.3+dfsg/bin/tests/dst/Ktest.+003+23616.key.in000066400000000000000000000004671325250447100215110ustar00rootroot00000000000000test. IN DNSKEY 16641 3 3 ANp1//lqDlEfTavcFI+cyudNfgEz73V/K7fSDvkA0eDYcGg/kSvEjAEO/oLWCERltkuC55ZcM/mSv17WF1d/wR6kww/pLI9eXwkjftAYqs5sNxk+mbEGl6zwve9wq5z7IoTY5/J4l7XLCKftg/wGvrzXQhggIkRvEh3myhxd+ouILcpfvTIthWlTKiH59tSJpmgmiSMTE7nDYaf10iVRWN6DMSprgejiH05/fpmyZAt44tyAh4m1wXS5u4tam1PXDJYJozn7EfQ8e2weIv1yC+t6PHSx bind9-9.11.3+dfsg/bin/tests/dst/Ktest.+003+23616.private.in000066400000000000000000000006641325250447100223720ustar00rootroot00000000000000Private-key-format: v1.2 Algorithm: 3 (DSA) Prime(p): 73V/K7fSDvkA0eDYcGg/kSvEjAEO/oLWCERltkuC55ZcM/mSv17WF1d/wR6kww/pLI9eXwkjftAYqs5sNxk+mQ== Subprime(q): 2nX/+WoOUR9Nq9wUj5zK501+ATM= Base(g): sQaXrPC973CrnPsihNjn8niXtcsIp+2D/Aa+vNdCGCAiRG8SHebKHF36i4gtyl+9Mi2FaVMqIfn21ImmaCaJIw== Private_value(x): Nky4tvIwg6xlcyeHXr4k2DEZg0E= Public_value(y): ExO5w2Gn9dIlUVjegzEqa4Ho4h9Of36ZsmQLeOLcgIeJtcF0ubuLWptT1wyWCaM5+xH0PHtsHiL9cgvrejx0sQ== bind9-9.11.3+dfsg/bin/tests/dst/Ktest.+003+49667.key.in000066400000000000000000000000321325250447100215130ustar00rootroot00000000000000test. IN DNSKEY 49152 2 3 bind9-9.11.3+dfsg/bin/tests/dst/Makefile.in000066400000000000000000000037351325250447100203150ustar00rootroot00000000000000# Copyright (C) 1999-2002, 2004, 2006-2010, 2012-2014, 2016 Internet Systems Consortium, Inc. ("ISC") # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. # $Id: Makefile.in,v 1.52 2010/12/24 23:47:05 tbox Exp $ srcdir = @srcdir@ VPATH = @srcdir@ top_srcdir = @top_srcdir@ @BIND9_MAKE_INCLUDES@ CINCLUDES = ${TEST_INCLUDES} ${DNS_INCLUDES} \ ${ISC_INCLUDES} @DST_OPENSSL_INC@ @DST_GSSAPI_INC@ CDEFINES = @CRYPTO@ @USE_GSSAPI@ CWARNINGS = DNSLIBS = ../../../lib/dns/libdns.@A@ @DNS_CRYPTO_LIBS@ ISCLIBS = ../../../lib/isc/libisc.@A@ DNSDEPLIBS = ../../../lib/dns/libdns.@A@ ISCDEPLIBS = ../../../lib/isc/libisc.@A@ DEPLIBS = ${DNSDEPLIBS} ${ISCDEPLIBS} LIBS = ${DNSLIBS} ${ISCLIBS} @LIBS@ TLIB = ../../../lib/tests/libt_api.@A@ TARGETS = dst_test@EXEEXT@ t_dst@EXEEXT@ gsstest@EXEEXT@ SRCS = dst_test.c t_dst.c gsstest.c @BIND9_MAKE_RULES@ dst_test@EXEEXT@: dst_test.@O@ ${DEPLIBS} ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ dst_test.@O@ ${LIBS} t_dst@EXEEXT@: t_dst.@O@ ${DEPLIBS} ${TLIB} ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ t_dst.@O@ ${TLIB} ${LIBS} gsstest@EXEEXT@: gsstest.@O@ ${DEPLIBS} ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ gsstest.@O@ ${LIBS} test: t_dst@EXEEXT@ randomfile ../../tools/genrandom@EXEEXT@ 100 randomfile -@ ./t_dst@EXEEXT@ -q 1800 -a randomfile: ../../tools/genrandom@EXEEXT@ 100 randomfile clean distclean:: rm -f ${TARGETS} randomfile distclean:: rm -f Kdh.+002+18602.key rm -f Kdh.+002+18602.private rm -f Kdh.+002+48957.key rm -f Kdh.+002+48957.private rm -f Ktest.+001+00002.key rm -f Ktest.+001+54622.key rm -f Ktest.+001+54622.private rm -f Ktest.+003+23616.key rm -f Ktest.+003+23616.private rm -f Ktest.+003+49667.key rm -f dst_2_data rm -f t2_data_1 rm -f t2_data_2 rm -f t2_dsasig rm -f t2_rsasig bind9-9.11.3+dfsg/bin/tests/dst/dst_2_data.in000066400000000000000000000010101325250447100205640ustar00rootroot00000000000000# # data for signature verification test # # format: # datafile, sigpath, keyname, keyid, alg, exp_result # t2_data_1 t2_dsasig test. 23616 DST_ALG_DSA ISC_R_SUCCESS t2_data_1 t2_rsasig test. 54622 DST_ALG_RSAMD5 ISC_R_SUCCESS # wrong sig t2_data_1 t2_dsasig test. 54622 DST_ALG_RSAMD5 !ISC_R_SUCCESS # wrong key #t2_data_1 t2_dsasig test. 54622 DST_ALG_DSA !ISC_R_SUCCESS # wrong alg #t2_data_1 t2_dsasig test. 23616 DST_ALG_RSAMD5 !ISC_R_SUCCESS # wrong data t2_data_2 t2_dsasig test. 23616 DST_ALG_DSA !ISC_R_SUCCESS bind9-9.11.3+dfsg/bin/tests/dst/dst_test.c000066400000000000000000000174651325250447100202520ustar00rootroot00000000000000/* * Copyright (C) 1999-2001, 2004, 2005, 2007, 2009, 2012, 2014-2016 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* $Id: dst_test.c,v 1.46 2009/09/01 00:22:25 jinmei Exp $ */ #include #include #include /* XXX */ #include #include #include #include #include #include /* Required for HP/UX (and others?) */ #include #include #include #include #include #include char *current; const char *tmp = "/tmp"; static void use(dst_key_t *key, isc_mem_t *mctx) { isc_result_t ret; const char *data = "This is some data"; unsigned char sig[512]; isc_buffer_t databuf, sigbuf; isc_region_t datareg, sigreg; dst_context_t *ctx = NULL; isc_buffer_init(&sigbuf, sig, sizeof(sig)); /* * Advance 1 byte for fun. */ isc_buffer_add(&sigbuf, 1); isc_buffer_constinit(&databuf, data, strlen(data)); isc_buffer_add(&databuf, strlen(data)); isc_buffer_usedregion(&databuf, &datareg); ret = dst_context_create3(key, mctx, DNS_LOGCATEGORY_GENERAL, ISC_TRUE, &ctx); if (ret != ISC_R_SUCCESS) { printf("contextcreate(%d) returned: %s\n", dst_key_alg(key), isc_result_totext(ret)); return; } ret = dst_context_adddata(ctx, &datareg); if (ret != ISC_R_SUCCESS) { printf("adddata(%d) returned: %s\n", dst_key_alg(key), isc_result_totext(ret)); dst_context_destroy(&ctx); return; } ret = dst_context_sign(ctx, &sigbuf); printf("sign(%d) returned: %s\n", dst_key_alg(key), isc_result_totext(ret)); dst_context_destroy(&ctx); isc_buffer_forward(&sigbuf, 1); isc_buffer_remainingregion(&sigbuf, &sigreg); ret = dst_context_create3(key, mctx, DNS_LOGCATEGORY_GENERAL, ISC_FALSE, &ctx); if (ret != ISC_R_SUCCESS) { printf("contextcreate(%d) returned: %s\n", dst_key_alg(key), isc_result_totext(ret)); return; } ret = dst_context_adddata(ctx, &datareg); if (ret != ISC_R_SUCCESS) { printf("adddata(%d) returned: %s\n", dst_key_alg(key), isc_result_totext(ret)); dst_context_destroy(&ctx); return; } ret = dst_context_verify(ctx, &sigreg); printf("verify(%d) returned: %s\n", dst_key_alg(key), isc_result_totext(ret)); dst_context_destroy(&ctx); } static void dns(dst_key_t *key, isc_mem_t *mctx) { unsigned char buffer1[2048]; unsigned char buffer2[2048]; isc_buffer_t buf1, buf2; isc_region_t r1, r2; dst_key_t *newkey = NULL; isc_result_t ret; isc_boolean_t match; isc_buffer_init(&buf1, buffer1, sizeof(buffer1)); ret = dst_key_todns(key, &buf1); printf("todns(%d) returned: %s\n", dst_key_alg(key), isc_result_totext(ret)); if (ret != ISC_R_SUCCESS) return; ret = dst_key_fromdns(dst_key_name(key), dns_rdataclass_in, &buf1, mctx, &newkey); printf("fromdns(%d) returned: %s\n", dst_key_alg(key), isc_result_totext(ret)); if (ret != ISC_R_SUCCESS) return; isc_buffer_init(&buf2, buffer2, sizeof(buffer2)); ret = dst_key_todns(newkey, &buf2); printf("todns2(%d) returned: %s\n", dst_key_alg(key), isc_result_totext(ret)); if (ret != ISC_R_SUCCESS) return; isc_buffer_usedregion(&buf1, &r1); isc_buffer_usedregion(&buf2, &r2); match = ISC_TF(r1.length == r2.length && memcmp(r1.base, r2.base, r1.length) == 0); printf("compare(%d): %s\n", dst_key_alg(key), match ? "true" : "false"); dst_key_free(&newkey); } static void io(dns_name_t *name, int id, int alg, int type, isc_mem_t *mctx) { dst_key_t *key = NULL; isc_result_t ret; ret = dst_key_fromfile(name, id, alg, type, current, mctx, &key); printf("read(%d) returned: %s\n", alg, isc_result_totext(ret)); if (ret != 0) return; ret = dst_key_tofile(key, type, tmp); printf("write(%d) returned: %s\n", alg, isc_result_totext(ret)); if (ret != 0) return; use(key, mctx); dns(key, mctx); dst_key_free(&key); } static void dh(dns_name_t *name1, int id1, dns_name_t *name2, int id2, isc_mem_t *mctx) { dst_key_t *key1 = NULL, *key2 = NULL; isc_result_t ret; isc_buffer_t b1, b2; isc_region_t r1, r2; unsigned char array1[1024], array2[1024]; int alg = DST_ALG_DH; int type = DST_TYPE_PUBLIC|DST_TYPE_PRIVATE|DST_TYPE_KEY; ret = dst_key_fromfile(name1, id1, alg, type, current, mctx, &key1); printf("read(%d) returned: %s\n", alg, isc_result_totext(ret)); if (ret != 0) return; ret = dst_key_fromfile(name2, id2, alg, type, current, mctx, &key2); printf("read(%d) returned: %s\n", alg, isc_result_totext(ret)); if (ret != 0) return; ret = dst_key_tofile(key1, type, tmp); printf("write(%d) returned: %s\n", alg, isc_result_totext(ret)); if (ret != 0) return; ret = dst_key_tofile(key2, type, tmp); printf("write(%d) returned: %s\n", alg, isc_result_totext(ret)); if (ret != 0) return; isc_buffer_init(&b1, array1, sizeof(array1)); ret = dst_key_computesecret(key1, key2, &b1); printf("computesecret() returned: %s\n", isc_result_totext(ret)); if (ret != 0) return; isc_buffer_init(&b2, array2, sizeof(array2)); ret = dst_key_computesecret(key2, key1, &b2); printf("computesecret() returned: %s\n", isc_result_totext(ret)); if (ret != 0) return; isc_buffer_usedregion(&b1, &r1); isc_buffer_usedregion(&b2, &r2); if (r1.length != r2.length || memcmp(r1.base, r2.base, r1.length) != 0) { int i; printf("secrets don't match\n"); printf("secret 1: %d bytes\n", r1.length); for (i = 0; i < (int) r1.length; i++) printf("%02x ", r1.base[i]); printf("\n"); printf("secret 2: %d bytes\n", r2.length); for (i = 0; i < (int) r2.length; i++) printf("%02x ", r2.base[i]); printf("\n"); } dst_key_free(&key1); dst_key_free(&key2); } static void generate(int alg, isc_mem_t *mctx) { isc_result_t ret; dst_key_t *key = NULL; ret = dst_key_generate(dns_rootname, alg, 512, 0, 0, 0, dns_rdataclass_in, mctx, &key); printf("generate(%d) returned: %s\n", alg, isc_result_totext(ret)); if (ret != ISC_R_SUCCESS) return; if (alg != DST_ALG_DH) use(key, mctx); dst_key_free(&key); } int main(void) { isc_mem_t *mctx = NULL; isc_entropy_t *ectx = NULL; isc_buffer_t b; dns_fixedname_t fname; dns_name_t *name; isc_result_t result; result = isc_mem_create(0, 0, &mctx); if (result != ISC_R_SUCCESS) return (1); current = isc_mem_get(mctx, 256); if (current == NULL) return (1); if (getcwd(current, 256) == NULL) { perror("getcwd"); return (1); } dns_result_register(); result = isc_entropy_create(mctx, &ectx); if (result != ISC_R_SUCCESS) return (1); result = isc_entropy_createfilesource(ectx, "randomfile"); if (result != ISC_R_SUCCESS) return (1); dst_lib_init(mctx, ectx, ISC_ENTROPY_BLOCKING|ISC_ENTROPY_GOODONLY); dns_fixedname_init(&fname); name = dns_fixedname_name(&fname); isc_buffer_constinit(&b, "test.", 5); isc_buffer_add(&b, 5); result = dns_name_fromtext(name, &b, NULL, 0, NULL); if (result != ISC_R_SUCCESS) return (1); io(name, 23616, DST_ALG_DSA, DST_TYPE_PRIVATE|DST_TYPE_PUBLIC, mctx); io(name, 54622, DST_ALG_RSAMD5, DST_TYPE_PRIVATE|DST_TYPE_PUBLIC, mctx); io(name, 49667, DST_ALG_DSA, DST_TYPE_PRIVATE|DST_TYPE_PUBLIC, mctx); io(name, 2, DST_ALG_RSAMD5, DST_TYPE_PRIVATE|DST_TYPE_PUBLIC, mctx); isc_buffer_constinit(&b, "dh.", 3); isc_buffer_add(&b, 3); result = dns_name_fromtext(name, &b, NULL, 0, NULL); if (result != ISC_R_SUCCESS) return (1); dh(name, 18602, name, 48957, mctx); generate(DST_ALG_RSAMD5, mctx); generate(DST_ALG_DH, mctx); generate(DST_ALG_DSA, mctx); generate(DST_ALG_HMACMD5, mctx); dst_lib_destroy(); isc_entropy_detach(&ectx); isc_mem_put(mctx, current, 256); /* isc_mem_stats(mctx, stdout);*/ isc_mem_destroy(&mctx); return (0); } bind9-9.11.3+dfsg/bin/tests/dst/gsstest.c000066400000000000000000000331641325250447100201070ustar00rootroot00000000000000/* * Copyright (C) 2006, 2007, 2009-2011, 2013-2016 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* $Id: gsstest.c,v 1.19 2011/11/30 00:48:51 marka Exp $ */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef GSSAPI #include ISC_PLATFORM_GSSAPIHEADER struct dst_context { unsigned int magic; dst_key_t *key; isc_mem_t *mctx; void *opaque; }; #define CHECK(str, x) { \ if ((x) != ISC_R_SUCCESS) { \ fprintf(stderr, "I:%d:%s: %s\n", __LINE__, (str), isc_result_totext(x)); \ goto end; \ } \ } static dns_fixedname_t servername, gssname; static isc_mem_t *mctx; static dns_requestmgr_t *requestmgr; static isc_sockaddr_t address; static dns_tsig_keyring_t *ring; static dns_tsigkey_t *tsigkey = NULL; static gss_ctx_id_t gssctx; static gss_ctx_id_t *gssctxp = &gssctx; #define RUNCHECK(x) RUNTIME_CHECK((x) == ISC_R_SUCCESS) #define PORT 53 #define TIMEOUT 30 static void initctx1(isc_task_t *task, isc_event_t *event); static void sendquery(isc_task_t *task, isc_event_t *event); static void setup(); static void console(isc_task_t *task, isc_event_t *event) { char buf[32]; int c; isc_event_t *ev = NULL; isc_event_free(&event); for (;;) { printf("\nCommand => "); c = scanf("%31s", buf); if (c == EOF || strcmp(buf, "quit") == 0) { isc_app_shutdown(); return; } if (strcmp(buf, "initctx") == 0) { ev = isc_event_allocate(mctx, (void *)1, 1, initctx1, NULL, sizeof(*event)); isc_task_send(task, &ev); return; } if (strcmp(buf, "query") == 0) { ev = isc_event_allocate(mctx, (void *)1, 1, sendquery, NULL, sizeof(*event)); isc_task_send(task, &ev); return; } printf("Unknown command\n"); } } static void recvresponse(isc_task_t *task, isc_event_t *event) { dns_requestevent_t *reqev = (dns_requestevent_t *)event; isc_result_t result, result2; dns_message_t *query = NULL, *response = NULL; isc_buffer_t outtoken; isc_buffer_t outbuf; char output[10 * 1024]; unsigned char array[DNS_NAME_MAXTEXT + 1]; isc_buffer_init(&outtoken, array, sizeof(array)); UNUSED(task); REQUIRE(reqev != NULL); query = reqev->ev_arg; if (reqev->result != ISC_R_SUCCESS) { fprintf(stderr, "I:request event result: %s\n", isc_result_totext(reqev->result)); goto end; } response = NULL; result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &response); CHECK("dns_message_create", result); printf("\nReceived Response:\n"); result2 = dns_request_getresponse(reqev->request, response, DNS_MESSAGEPARSE_PRESERVEORDER); isc_buffer_init(&outbuf, output, sizeof(output)); result = dns_message_totext(response, &dns_master_style_debug, 0, &outbuf); CHECK("dns_message_totext", result); printf("%.*s\n", (int)isc_buffer_usedlength(&outbuf), (char *)isc_buffer_base(&outbuf)); CHECK("dns_request_getresponse", result2); if (response != NULL) dns_message_destroy(&response); end: if (query != NULL) dns_message_destroy(&query); if (reqev->request != NULL) dns_request_destroy(&reqev->request); isc_event_free(&event); event = isc_event_allocate(mctx, (void *)1, 1, console, NULL, sizeof(*event)); isc_task_send(task, &event); return; } static void sendquery(isc_task_t *task, isc_event_t *event) { dns_request_t *request = NULL; dns_message_t *message = NULL; dns_name_t *qname = NULL; dns_rdataset_t *qrdataset = NULL; isc_result_t result; dns_fixedname_t queryname; isc_buffer_t buf; isc_buffer_t outbuf; char output[10 * 1024]; static char host[256]; int c; isc_event_free(&event); printf("Query => "); c = scanf("%255s", host); if (c == EOF) return; dns_fixedname_init(&queryname); isc_buffer_init(&buf, host, strlen(host)); isc_buffer_add(&buf, strlen(host)); result = dns_name_fromtext(dns_fixedname_name(&queryname), &buf, dns_rootname, 0, NULL); CHECK("dns_name_fromtext", result); result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, &message); if (result != ISC_R_SUCCESS) goto end; message->opcode = dns_opcode_query; message->rdclass = dns_rdataclass_in; message->id = (unsigned short)(random() & 0xFFFF); result = dns_message_gettempname(message, &qname); if (result != ISC_R_SUCCESS) goto end; result = dns_message_gettemprdataset(message, &qrdataset); if (result != ISC_R_SUCCESS) goto end; dns_name_init(qname, NULL); dns_name_clone(dns_fixedname_name(&queryname), qname); dns_rdataset_makequestion(qrdataset, dns_rdataclass_in, dns_rdatatype_a); ISC_LIST_APPEND(qname->list, qrdataset, link); dns_message_addname(message, qname, DNS_SECTION_QUESTION); result = dns_request_create(requestmgr, message, &address, 0, tsigkey, TIMEOUT, task, recvresponse, message, &request); CHECK("dns_request_create", result); printf("Submitting query:\n"); isc_buffer_init(&outbuf, output, sizeof(output)); result = dns_message_totext(message, &dns_master_style_debug, 0, &outbuf); CHECK("dns_message_totext", result); printf("%.*s\n", (int)isc_buffer_usedlength(&outbuf), (char *)isc_buffer_base(&outbuf)); return; end: if (qname != NULL) dns_message_puttempname(message, &qname); if (qrdataset != NULL) dns_message_puttemprdataset(message, &qrdataset); if (message != NULL) dns_message_destroy(&message); } static void initctx2(isc_task_t *task, isc_event_t *event) { dns_requestevent_t *reqev = (dns_requestevent_t *)event; isc_result_t result; dns_message_t *query = NULL, *response = NULL; isc_buffer_t outtoken; unsigned char array[DNS_NAME_MAXTEXT + 1]; dns_rdataset_t *rdataset; dns_rdatatype_t qtype; dns_name_t *question_name; UNUSED(task); REQUIRE(reqev != NULL); query = reqev->ev_arg; if (reqev->result != ISC_R_SUCCESS) { fprintf(stderr, "I:request event result: %s\n", isc_result_totext(reqev->result)); goto end; } response = NULL; result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &response); CHECK("dns_message_create", result); result = dns_request_getresponse(reqev->request, response, DNS_MESSAGEPARSE_PRESERVEORDER); CHECK("dns_request_getresponse", result); if (response->rcode != dns_rcode_noerror) { result = ISC_RESULTCLASS_DNSRCODE + response->rcode; fprintf(stderr, "I:response rcode: %s\n", isc_result_totext(result)); goto end; } printf("Received token from server, calling gss_init_sec_context()\n"); isc_buffer_init(&outtoken, array, DNS_NAME_MAXTEXT + 1); result = dns_tkey_processgssresponse(query, response, dns_fixedname_name(&gssname), &gssctx, &outtoken, &tsigkey, ring, NULL); gssctx = *gssctxp; CHECK("dns_tkey_processgssresponse", result); printf("Context accepted\n"); question_name = NULL; dns_message_currentname(response, DNS_SECTION_ANSWER, &question_name); rdataset = ISC_LIST_HEAD(question_name->list); INSIST(rdataset != NULL); qtype = rdataset->type; if (qtype == dns_rdatatype_tkey) { printf("Received TKEY response from server\n"); printf("Context completed\n"); } else { printf("Did not receive TKEY response from server\n"); printf("Context not completed\n"); dns_tsigkey_detach(&tsigkey); tsigkey = NULL; } dns_message_destroy(&response); end: if (query != NULL) dns_message_destroy(&query); if (reqev->request != NULL) dns_request_destroy(&reqev->request); isc_event_free(&event); event = isc_event_allocate(mctx, (void *)1, 1, console, NULL, sizeof(*event)); isc_task_send(task, &event); return; } static void initctx1(isc_task_t *task, isc_event_t *event) { char gssid[512]; char contextname[512]; isc_result_t result; isc_buffer_t buf; dns_message_t *query; dns_request_t *request; int c; isc_event_free(&event); printf("Initctx - GSS name => "); c = scanf("%511s", gssid); if (c == EOF) return; snprintf(contextname, sizeof(contextname), "gsstest.context.%d.", (int)time(NULL)); printf("Initctx - context name we're using: %s\n", contextname); printf("Negotiating GSSAPI context: "); printf("%s", gssid); printf("\n"); /* * Setup a GSSAPI context with the server */ dns_fixedname_init(&servername); isc_buffer_init(&buf, contextname, strlen(contextname)); isc_buffer_add(&buf, strlen(contextname)); result = dns_name_fromtext(dns_fixedname_name(&servername), &buf, dns_rootname, 0, NULL); CHECK("dns_name_fromtext", result); /* Make name happen */ dns_fixedname_init(&gssname); isc_buffer_init(&buf, gssid, strlen(gssid)); isc_buffer_add(&buf, strlen(gssid)); result = dns_name_fromtext(dns_fixedname_name(&gssname), &buf, dns_rootname, 0, NULL); CHECK("dns_name_fromtext", result); query = NULL; result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, &query); CHECK("dns_message_create", result); printf("Calling gss_init_sec_context()\n"); gssctx = GSS_C_NO_CONTEXT; result = dns_tkey_buildgssquery(query, dns_fixedname_name(&servername), dns_fixedname_name(&gssname), NULL, 36000, &gssctx, ISC_TRUE, mctx, NULL); CHECK("dns_tkey_buildgssquery", result); printf("Sending context token to server\n"); request = NULL; result = dns_request_create(requestmgr, query, &address, 0, NULL, TIMEOUT, task, initctx2, query, &request); CHECK("dns_request_create", result); return; end: event = isc_event_allocate(mctx, (void *)1, 1, console, NULL, sizeof(*event)); isc_task_send(task, &event);return; } static void setup(void) { for (;;) { char serveraddress[512]; struct in_addr inaddr; int c; printf("Server IP => "); c = scanf("%511s", serveraddress); if (c == EOF || strcmp(serveraddress, "quit") == 0) { isc_app_shutdown(); return; } if (inet_pton(AF_INET, serveraddress, &inaddr) == 1) { isc_sockaddr_fromin(&address, &inaddr, PORT); return; } } } int main(int argc, char *argv[]) { isc_taskmgr_t *taskmgr; isc_timermgr_t *timermgr; isc_socketmgr_t *socketmgr; isc_socket_t *sock; unsigned int attrs, attrmask; isc_sockaddr_t bind_any; dns_dispatchmgr_t *dispatchmgr; dns_dispatch_t *dispatchv4; dns_view_t *view; isc_entropy_t *ectx; isc_task_t *task; isc_log_t *lctx = NULL; isc_logconfig_t *lcfg = NULL; isc_logdestination_t destination; UNUSED(argv); UNUSED(argc); RUNCHECK(isc_app_start()); dns_result_register(); mctx = NULL; RUNCHECK(isc_mem_create(0, 0, &mctx)); RUNCHECK(isc_log_create(mctx, &lctx, &lcfg)); isc_log_setcontext(lctx); dns_log_init(lctx); dns_log_setcontext(lctx); /* * Create and install the default channel. */ destination.file.stream = stderr; destination.file.name = NULL; destination.file.versions = ISC_LOG_ROLLNEVER; destination.file.maximum_size = 0; RUNCHECK(isc_log_createchannel(lcfg, "_default", ISC_LOG_TOFILEDESC, ISC_LOG_DYNAMIC, &destination, ISC_LOG_PRINTTIME)); RUNCHECK(isc_log_usechannel(lcfg, "_default", NULL, NULL)); isc_log_setdebuglevel(lctx, 9); ectx = NULL; RUNCHECK(isc_entropy_create(mctx, &ectx)); RUNCHECK(isc_entropy_createfilesource(ectx, "/dev/urandom")); RUNCHECK(dst_lib_init(mctx, ectx, ISC_ENTROPY_GOODONLY)); taskmgr = NULL; RUNCHECK(isc_taskmgr_create(mctx, 1, 0, &taskmgr)); task = NULL; RUNCHECK(isc_task_create(taskmgr, 0, &task)); timermgr = NULL; RUNCHECK(isc_timermgr_create(mctx, &timermgr)); socketmgr = NULL; RUNCHECK(isc_socketmgr_create(mctx, &socketmgr)); dispatchmgr = NULL; RUNCHECK(dns_dispatchmgr_create(mctx, ectx, &dispatchmgr)); isc_sockaddr_any(&bind_any); attrs = DNS_DISPATCHATTR_UDP | DNS_DISPATCHATTR_MAKEQUERY | DNS_DISPATCHATTR_IPV4; attrmask = DNS_DISPATCHATTR_UDP | DNS_DISPATCHATTR_TCP | DNS_DISPATCHATTR_IPV4 | DNS_DISPATCHATTR_IPV6; dispatchv4 = NULL; RUNCHECK(dns_dispatch_getudp(dispatchmgr, socketmgr, taskmgr, &bind_any, 4096, 4, 2, 3, 5, attrs, attrmask, &dispatchv4)); requestmgr = NULL; RUNCHECK(dns_requestmgr_create(mctx, timermgr, socketmgr, taskmgr, dispatchmgr, dispatchv4, NULL, &requestmgr)); ring = NULL; RUNCHECK(dns_tsigkeyring_create(mctx, &ring)); view = NULL; RUNCHECK(dns_view_create(mctx, 0, "_test", &view)); dns_view_setkeyring(view, ring); sock = NULL; RUNCHECK(isc_socket_create(socketmgr, PF_INET, isc_sockettype_udp, &sock)); setup(); RUNCHECK(isc_app_onrun(mctx, task, console, NULL)); (void)isc_app_run(); if (tsigkey) dns_tsigkey_detach(&tsigkey); dns_requestmgr_shutdown(requestmgr); dns_requestmgr_detach(&requestmgr); dns_dispatch_detach(&dispatchv4); dns_dispatchmgr_destroy(&dispatchmgr); isc_timermgr_destroy(&timermgr); isc_task_detach(&task); isc_taskmgr_destroy(&taskmgr); isc_socket_detach(&sock); isc_socketmgr_destroy(&socketmgr); isc_mem_stats(mctx, stdout); dns_view_detach(&view); dst_lib_destroy(); isc_entropy_detach(&ectx); isc_mem_stats(mctx, stdout); isc_mem_destroy(&mctx); isc_app_finish(); return (0); } #else int main(int argc, char *argv[]) { UNUSED(argc); UNUSED(argv); fprintf(stderr, "R:GSSAPIONLY\n"); return (0); } #endif bind9-9.11.3+dfsg/bin/tests/dst/t2_data_1.in000066400000000000000000003572651325250447100203500ustar00rootroot00000000000000Network Working Group P. Mockapetris Request for Comments: 1035 ISI November 1987 Obsoletes: RFCs 882, 883, 973 DOMAIN NAMES - IMPLEMENTATION AND SPECIFICATION 1. STATUS OF THIS MEMO This RFC describes the details of the domain system and protocol, and assumes that the reader is familiar with the concepts discussed in a companion RFC, "Domain Names - Concepts and Facilities" [RFC-1034]. The domain system is a mixture of functions and data types which are an official protocol and functions and data types which are still experimental. Since the domain system is intentionally extensible, new data types and experimental behavior should always be expected in parts of the system beyond the official protocol. The official protocol parts include standard queries, responses and the Internet class RR data formats (e.g., host addresses). Since the previous RFC set, several definitions have changed, so some previous definitions are obsolete. Experimental or obsolete features are clearly marked in these RFCs, and such information should be used with caution. The reader is especially cautioned not to depend on the values which appear in examples to be current or complete, since their purpose is primarily pedagogical. Distribution of this memo is unlimited. Table of Contents 1. STATUS OF THIS MEMO 1 2. INTRODUCTION 3 2.1. Overview 3 2.2. Common configurations 4 2.3. Conventions 7 2.3.1. Preferred name syntax 7 2.3.2. Data Transmission Order 8 2.3.3. Character Case 9 2.3.4. Size limits 10 3. DOMAIN NAME SPACE AND RR DEFINITIONS 10 3.1. Name space definitions 10 3.2. RR definitions 11 3.2.1. Format 11 3.2.2. TYPE values 12 3.2.3. QTYPE values 12 3.2.4. CLASS values 13 Mockapetris [Page 1] RFC 1035 Domain Implementation and Specification November 1987 3.2.5. QCLASS values 13 3.3. Standard RRs 13 3.3.1. CNAME RDATA format 14 3.3.2. HINFO RDATA format 14 3.3.3. MB RDATA format (EXPERIMENTAL) 14 3.3.4. MD RDATA format (Obsolete) 15 3.3.5. MF RDATA format (Obsolete) 15 3.3.6. MG RDATA format (EXPERIMENTAL) 16 3.3.7. MINFO RDATA format (EXPERIMENTAL) 16 3.3.8. MR RDATA format (EXPERIMENTAL) 17 3.3.9. MX RDATA format 17 3.3.10. NULL RDATA format (EXPERIMENTAL) 17 3.3.11. NS RDATA format 18 3.3.12. PTR RDATA format 18 3.3.13. SOA RDATA format 19 3.3.14. TXT RDATA format 20 3.4. ARPA Internet specific RRs 20 3.4.1. A RDATA format 20 3.4.2. WKS RDATA format 21 3.5. IN-ADDR.ARPA domain 22 3.6. Defining new types, classes, and special namespaces 24 4. MESSAGES 25 4.1. Format 25 4.1.1. Header section format 26 4.1.2. Question section format 28 4.1.3. Resource record format 29 4.1.4. Message compression 30 4.2. Transport 32 4.2.1. UDP usage 32 4.2.2. TCP usage 32 5. MASTER FILES 33 5.1. Format 33 5.2. Use of master files to define zones 35 5.3. Master file example 36 6. NAME SERVER IMPLEMENTATION 37 6.1. Architecture 37 6.1.1. Control 37 6.1.2. Database 37 6.1.3. Time 39 6.2. Standard query processing 39 6.3. Zone refresh and reload processing 39 6.4. Inverse queries (Optional) 40 6.4.1. The contents of inverse queries and responses 40 6.4.2. Inverse query and response example 41 6.4.3. Inverse query processing 42 Mockapetris [Page 2] RFC 1035 Domain Implementation and Specification November 1987 6.5. Completion queries and responses 42 7. RESOLVER IMPLEMENTATION 43 7.1. Transforming a user request into a query 43 7.2. Sending the queries 44 7.3. Processing responses 46 7.4. Using the cache 47 8. MAIL SUPPORT 47 8.1. Mail exchange binding 48 8.2. Mailbox binding (Experimental) 48 9. REFERENCES and BIBLIOGRAPHY 50 Index 54 2. INTRODUCTION 2.1. Overview The goal of domain names is to provide a mechanism for naming resources in such a way that the names are usable in different hosts, networks, protocol families, internets, and administrative organizations. From the user's point of view, domain names are useful as arguments to a local agent, called a resolver, which retrieves information associated with the domain name. Thus a user might ask for the host address or mail information associated with a particular domain name. To enable the user to request a particular type of information, an appropriate query type is passed to the resolver with the domain name. To the user, the domain tree is a single information space; the resolver is responsible for hiding the distribution of data among name servers from the user. From the resolver's point of view, the database that makes up the domain space is distributed among various name servers. Different parts of the domain space are stored in different name servers, although a particular data item will be stored redundantly in two or more name servers. The resolver starts with knowledge of at least one name server. When the resolver processes a user query it asks a known name server for the information; in return, the resolver either receives the desired information or a referral to another name server. Using these referrals, resolvers learn the identities and contents of other name servers. Resolvers are responsible for dealing with the distribution of the domain space and dealing with the effects of name server failure by consulting redundant databases in other servers. Name servers manage two kinds of data. The first kind of data held in sets called zones; each zone is the complete database for a particular "pruned" subtree of the domain space. This data is called authoritative. A name server periodically checks to make sure that its zones are up to date, and if not, obtains a new copy of updated zones Mockapetris [Page 3] RFC 1035 Domain Implementation and Specification November 1987 from master files stored locally or in another name server. The second kind of data is cached data which was acquired by a local resolver. This data may be incomplete, but improves the performance of the retrieval process when non-local data is repeatedly accessed. Cached data is eventually discarded by a timeout mechanism. This functional structure isolates the problems of user interface, failure recovery, and distribution in the resolvers and isolates the database update and refresh problems in the name servers. 2.2. Common configurations A host can participate in the domain name system in a number of ways, depending on whether the host runs programs that retrieve information from the domain system, name servers that answer queries from other hosts, or various combinations of both functions. The simplest, and perhaps most typical, configuration is shown below: Local Host | Foreign | +---------+ +----------+ | +--------+ | | user queries | |queries | | | | User |-------------->| |---------|->|Foreign | | Program | | Resolver | | | Name | | |<--------------| |<--------|--| Server | | | user responses| |responses| | | +---------+ +----------+ | +--------+ | A | cache additions | | references | V | | +----------+ | | cache | | +----------+ | User programs interact with the domain name space through resolvers; the format of user queries and user responses is specific to the host and its operating system. User queries will typically be operating system calls, and the resolver and its cache will be part of the host operating system. Less capable hosts may choose to implement the resolver as a subroutine to be linked in with every program that needs its services. Resolvers answer user queries with information they acquire via queries to foreign name servers and the local cache. Note that the resolver may have to make several queries to several different foreign name servers to answer a particular user query, and hence the resolution of a user query may involve several network accesses and an arbitrary amount of time. The queries to foreign name servers and the corresponding responses have a standard format described Mockapetris [Page 4] RFC 1035 Domain Implementation and Specification November 1987 in this memo, and may be datagrams. Depending on its capabilities, a name server could be a stand alone program on a dedicated machine or a process or processes on a large timeshared host. A simple configuration might be: Local Host | Foreign | +---------+ | / /| | +---------+ | +----------+ | +--------+ | | | | |responses| | | | | | | Name |---------|->|Foreign | | Master |-------------->| Server | | |Resolver| | files | | | |<--------|--| | | |/ | | queries | +--------+ +---------+ +----------+ | Here a primary name server acquires information about one or more zones by reading master files from its local file system, and answers queries about those zones that arrive from foreign resolvers. The DNS requires that all zones be redundantly supported by more than one name server. Designated secondary servers can acquire zones and check for updates from the primary server using the zone transfer protocol of the DNS. This configuration is shown below: Local Host | Foreign | +---------+ | / /| | +---------+ | +----------+ | +--------+ | | | | |responses| | | | | | | Name |---------|->|Foreign | | Master |-------------->| Server | | |Resolver| | files | | | |<--------|--| | | |/ | | queries | +--------+ +---------+ +----------+ | A |maintenance | +--------+ | +------------|->| | | queries | |Foreign | | | | Name | +------------------|--| Server | maintenance responses | +--------+ In this configuration, the name server periodically establishes a virtual circuit to a foreign name server to acquire a copy of a zone or to check that an existing copy has not changed. The messages sent for Mockapetris [Page 5] RFC 1035 Domain Implementation and Specification November 1987 these maintenance activities follow the same form as queries and responses, but the message sequences are somewhat different. The information flow in a host that supports all aspects of the domain name system is shown below: Local Host | Foreign | +---------+ +----------+ | +--------+ | | user queries | |queries | | | | User |-------------->| |---------|->|Foreign | | Program | | Resolver | | | Name | | |<--------------| |<--------|--| Server | | | user responses| |responses| | | +---------+ +----------+ | +--------+ | A | cache additions | | references | V | | +----------+ | | Shared | | | database | | +----------+ | A | | +---------+ refreshes | | references | / /| | V | +---------+ | +----------+ | +--------+ | | | | |responses| | | | | | | Name |---------|->|Foreign | | Master |-------------->| Server | | |Resolver| | files | | | |<--------|--| | | |/ | | queries | +--------+ +---------+ +----------+ | A |maintenance | +--------+ | +------------|->| | | queries | |Foreign | | | | Name | +------------------|--| Server | maintenance responses | +--------+ The shared database holds domain space data for the local name server and resolver. The contents of the shared database will typically be a mixture of authoritative data maintained by the periodic refresh operations of the name server and cached data from previous resolver requests. The structure of the domain data and the necessity for synchronization between name servers and resolvers imply the general characteristics of this database, but the actual format is up to the local implementor. Mockapetris [Page 6] RFC 1035 Domain Implementation and Specification November 1987 Information flow can also be tailored so that a group of hosts act together to optimize activities. Sometimes this is done to offload less capable hosts so that they do not have to implement a full resolver. This can be appropriate for PCs or hosts which want to minimize the amount of new network code which is required. This scheme can also allow a group of hosts can share a small number of caches rather than maintaining a large number of separate caches, on the premise that the centralized caches will have a higher hit ratio. In either case, resolvers are replaced with stub resolvers which act as front ends to resolvers located in a recursive server in one or more name servers known to perform that service: Local Hosts | Foreign | +---------+ | | | responses | | Stub |<--------------------+ | | Resolver| | | | |----------------+ | | +---------+ recursive | | | queries | | | V | | +---------+ recursive +----------+ | +--------+ | | queries | |queries | | | | Stub |-------------->| Recursive|---------|->|Foreign | | Resolver| | Server | | | Name | | |<--------------| |<--------|--| Server | +---------+ responses | |responses| | | +----------+ | +--------+ | Central | | | cache | | +----------+ | In any case, note that domain components are always replicated for reliability whenever possible. 2.3. Conventions The domain system has several conventions dealing with low-level, but fundamental, issues. While the implementor is free to violate these conventions WITHIN HIS OWN SYSTEM, he must observe these conventions in ALL behavior observed from other hosts. 2.3.1. Preferred name syntax The DNS specifications attempt to be as general as possible in the rules for constructing domain names. The idea is that the name of any existing object can be expressed as a domain name with minimal changes. Mockapetris [Page 7] RFC 1035 Domain Implementation and Specification November 1987 However, when assigning a domain name for an object, the prudent user will select a name which satisfies both the rules of the domain system and any existing rules for the object, whether these rules are published or implied by existing programs. For example, when naming a mail domain, the user should satisfy both the rules of this memo and those in RFC-822. When creating a new host name, the old rules for HOSTS.TXT should be followed. This avoids problems when old software is converted to use domain names. The following syntax will result in fewer problems with many applications that use domain names (e.g., mail, TELNET). ::= | " " ::=