From 1fbfdb89d1aeb093c2dc5036731864de3ed1c2e5 Mon Sep 17 00:00:00 2001 From: Eric Christensen Date: Mon, 11 Mar 2013 18:11:16 -0400 Subject: [PATCH] Adding Defensive Coding book --- defensive-coding/Makefile | 33 + defensive-coding/README | 32 + .../docbook-schema/.svn/all-wcprops | 47 + defensive-coding/docbook-schema/.svn/entries | 266 + .../.svn/text-base/README.svn-base | 3 + .../.svn/text-base/calstblx.rnc.svn-base | 164 + .../.svn/text-base/dbhierx.rnc.svn-base | 1549 +++++ .../.svn/text-base/dbnotnx.rnc.svn-base | 85 + .../.svn/text-base/dbpoolx.rnc.svn-base | 5785 +++++++++++++++++ .../.svn/text-base/docbook.rnc.svn-base | 499 ++ .../.svn/text-base/htmltblx.rnc.svn-base | 225 + defensive-coding/docbook-schema/README | 3 + defensive-coding/docbook-schema/calstblx.rnc | 164 + defensive-coding/docbook-schema/dbhierx.rnc | 1549 +++++ defensive-coding/docbook-schema/dbnotnx.rnc | 85 + defensive-coding/docbook-schema/dbpoolx.rnc | 5785 +++++++++++++++++ defensive-coding/docbook-schema/docbook.rnc | 499 ++ defensive-coding/docbook-schema/htmltblx.rnc | 225 + defensive-coding/en-US/.svn/all-wcprops | 23 + defensive-coding/en-US/.svn/entries | 145 + .../.svn/prop-base/Book_Info.xml.svn-base | 5 + .../prop-base/Defensive_Coding.xml.svn-base | 5 + .../.svn/text-base/Book_Info.xml.svn-base | 29 + .../text-base/Defensive_Coding.ent.svn-base | 2 + .../text-base/Defensive_Coding.xml.svn-base | 26 + defensive-coding/en-US/Author_Group.xml | 17 + defensive-coding/en-US/Book_Info.xml | 30 + defensive-coding/en-US/C/.svn/all-wcprops | 35 + defensive-coding/en-US/C/.svn/dir-prop-base | 6 + defensive-coding/en-US/C/.svn/entries | 198 + .../C/.svn/prop-base/Allocators.xml.svn-base | 5 + .../en-US/C/.svn/prop-base/C.xml.svn-base | 5 + .../C/.svn/prop-base/Language.xml.svn-base | 5 + .../en-US/C/.svn/prop-base/Libc.xml.svn-base | 5 + .../C/.svn/prop-base/schemas.xml.svn-base | 5 + .../C/.svn/text-base/Allocators.xml.svn-base | 207 + .../en-US/C/.svn/text-base/C.xml.svn-base | 11 + .../C/.svn/text-base/Language.xml.svn-base | 150 + .../en-US/C/.svn/text-base/Libc.xml.svn-base | 227 + .../C/.svn/text-base/schemas.xml.svn-base | 4 + defensive-coding/en-US/C/Allocators.xml | 207 + defensive-coding/en-US/C/C.xml | 11 + defensive-coding/en-US/C/Language.xml | 150 + defensive-coding/en-US/C/Libc.xml | 227 + defensive-coding/en-US/C/schemas.xml | 4 + .../en-US/C/snippets/Arithmetic-add.xml | 21 + .../en-US/C/snippets/Arithmetic-mult.xml | 14 + .../en-US/C/snippets/Pointers-remaining.xml | 49 + .../C/snippets/String-Functions-format.xml | 18 + .../C/snippets/String-Functions-snprintf.xml | 8 + .../C/snippets/String-Functions-strncpy.xml | 9 + defensive-coding/en-US/CXX/.svn/all-wcprops | 29 + defensive-coding/en-US/CXX/.svn/dir-prop-base | 6 + defensive-coding/en-US/CXX/.svn/entries | 164 + .../en-US/CXX/.svn/prop-base/CXX.xml.svn-base | 5 + .../CXX/.svn/prop-base/Language.xml.svn-base | 5 + .../en-US/CXX/.svn/prop-base/Std.xml.svn-base | 5 + .../CXX/.svn/prop-base/schemas.xml.svn-base | 5 + .../en-US/CXX/.svn/text-base/CXX.xml.svn-base | 10 + .../CXX/.svn/text-base/Language.xml.svn-base | 186 + .../en-US/CXX/.svn/text-base/Std.xml.svn-base | 32 + .../CXX/.svn/text-base/schemas.xml.svn-base | 4 + defensive-coding/en-US/CXX/CXX.xml | 10 + defensive-coding/en-US/CXX/Language.xml | 186 + defensive-coding/en-US/CXX/Std.xml | 32 + defensive-coding/en-US/CXX/schemas.xml | 4 + defensive-coding/en-US/Defensive_Coding.ent | 2 + defensive-coding/en-US/Defensive_Coding.xml | 27 + .../en-US/Features/.svn/all-wcprops | 23 + .../en-US/Features/.svn/dir-prop-base | 6 + defensive-coding/en-US/Features/.svn/entries | 130 + .../prop-base/Authentication.xml.svn-base | 5 + .../Features/.svn/prop-base/TLS.xml.svn-base | 5 + .../.svn/prop-base/schemas.xml.svn-base | 5 + .../text-base/Authentication.xml.svn-base | 189 + .../Features/.svn/text-base/TLS.xml.svn-base | 988 +++ .../.svn/text-base/schemas.xml.svn-base | 4 + .../en-US/Features/Authentication.xml | 189 + defensive-coding/en-US/Features/TLS.xml | 988 +++ defensive-coding/en-US/Features/schemas.xml | 4 + .../snippets/TLS-Client-GNUTLS-Connect.xml | 50 + .../TLS-Client-GNUTLS-Credentials.xml | 29 + .../snippets/TLS-Client-GNUTLS-Match.xml | 30 + .../snippets/TLS-Client-GNUTLS-Verify.xml | 42 + .../snippets/TLS-Client-NSS-Close.xml | 15 + .../snippets/TLS-Client-NSS-Connect.xml | 106 + .../snippets/TLS-Client-OpenJDK-Connect.xml | 26 + .../snippets/TLS-Client-OpenJDK-Context.xml | 26 + .../TLS-Client-OpenJDK-Context_For_Cert.xml | 22 + .../snippets/TLS-Client-OpenJDK-Hostname.xml | 7 + .../snippets/TLS-Client-OpenJDK-Import.xml | 18 + .../TLS-Client-OpenJDK-MyTrustManager.xml | 38 + .../snippets/TLS-Client-OpenJDK-Use.xml | 11 + .../snippets/TLS-Client-OpenSSL-CTX.xml | 71 + .../snippets/TLS-Client-OpenSSL-Connect.xml | 55 + .../TLS-Client-OpenSSL-Connection-Use.xml | 15 + .../snippets/TLS-Client-OpenSSL-Init.xml | 13 + .../snippets/TLS-Client-Python-Connect.xml | 14 + .../TLS-Client-Python-check_host_name.xml | 29 + .../snippets/TLS-GNUTLS-Credentials-Close.xml | 7 + .../snippets/TLS-GNUTLS-Disconnect.xml | 14 + .../Features/snippets/TLS-GNUTLS-Init.xml | 7 + .../Features/snippets/TLS-GNUTLS-Use.xml | 18 + .../en-US/Features/snippets/TLS-NSS-Close.xml | 8 + .../Features/snippets/TLS-NSS-Includes.xml | 20 + .../en-US/Features/snippets/TLS-NSS-Init.xml | 63 + .../en-US/Features/snippets/TLS-NSS-Use.xml | 22 + .../en-US/Features/snippets/TLS-Nagle.xml | 12 + .../snippets/TLS-OpenJDK-Parameters.xml | 27 + .../snippets/TLS-OpenSSL-Connection-Close.xml | 30 + .../snippets/TLS-OpenSSL-Context-Close.xml | 7 + .../Features/snippets/TLS-OpenSSL-Errors.xml | 31 + .../Features/snippets/TLS-Python-Close.xml | 7 + .../Features/snippets/TLS-Python-Use.xml | 8 + .../en-US/Python/.svn/all-wcprops | 17 + .../en-US/Python/.svn/dir-prop-base | 6 + defensive-coding/en-US/Python/.svn/entries | 96 + .../.svn/prop-base/Language.xml.svn-base | 5 + .../.svn/prop-base/schemas.xml.svn-base | 5 + .../.svn/text-base/Language.xml.svn-base | 74 + .../.svn/text-base/schemas.xml.svn-base | 4 + defensive-coding/en-US/Python/Language.xml | 74 + defensive-coding/en-US/Python/schemas.xml | 4 + defensive-coding/en-US/Revision_History.xml | 27 + defensive-coding/en-US/Tasks/.svn/all-wcprops | 59 + .../en-US/Tasks/.svn/dir-prop-base | 6 + defensive-coding/en-US/Tasks/.svn/entries | 334 + .../.svn/prop-base/Cryptography.xml.svn-base | 5 + .../.svn/prop-base/Descriptors.xml.svn-base | 5 + .../.svn/prop-base/File_System.xml.svn-base | 5 + .../prop-base/Library_Design.xml.svn-base | 5 + .../Tasks/.svn/prop-base/Locking.xml.svn-base | 5 + .../.svn/prop-base/Processes.xml.svn-base | 5 + .../.svn/prop-base/Serialization.xml.svn-base | 5 + .../prop-base/Temporary_Files.xml.svn-base | 5 + .../Tasks/.svn/prop-base/schemas.xml.svn-base | 5 + .../.svn/text-base/Cryptography.xml.svn-base | 111 + .../.svn/text-base/Descriptors.xml.svn-base | 266 + .../.svn/text-base/File_System.xml.svn-base | 339 + .../text-base/Library_Design.xml.svn-base | 195 + .../Tasks/.svn/text-base/Locking.xml.svn-base | 5 + .../.svn/text-base/Processes.xml.svn-base | 483 ++ .../.svn/text-base/Serialization.xml.svn-base | 397 ++ .../text-base/Temporary_Files.xml.svn-base | 257 + .../Tasks/.svn/text-base/schemas.xml.svn-base | 4 + defensive-coding/en-US/Tasks/Cryptography.xml | 111 + defensive-coding/en-US/Tasks/Descriptors.xml | 266 + defensive-coding/en-US/Tasks/File_System.xml | 339 + .../en-US/Tasks/Library_Design.xml | 195 + defensive-coding/en-US/Tasks/Locking.xml | 5 + defensive-coding/en-US/Tasks/Processes.xml | 483 ++ .../en-US/Tasks/Serialization.xml | 397 ++ .../en-US/Tasks/Temporary_Files.xml | 257 + defensive-coding/en-US/Tasks/schemas.xml | 4 + .../Serialization-XML-Expat-Create.xml | 17 + ...ialization-XML-Expat-EntityDeclHandler.xml | 16 + .../Serialization-XML-OpenJDK-Errors.xml | 22 + .../Serialization-XML-OpenJDK-Imports.xml | 27 + ...alization-XML-OpenJDK-NoEntityResolver.xml | 15 + ...ization-XML-OpenJDK-NoResourceResolver.xml | 17 + .../Serialization-XML-OpenJDK_Parse-DOM.xml | 19 + ...zation-XML-OpenJDK_Parse-XMLSchema_DOM.xml | 23 + ...zation-XML-OpenJDK_Parse-XMLSchema_SAX.xml | 26 + defensive-coding/publican.cfg | 10 + defensive-coding/schemas.xml | 6 + defensive-coding/scripts/.svn/all-wcprops | 11 + defensive-coding/scripts/.svn/entries | 62 + .../.svn/text-base/split-snippets.py.svn-base | 106 + defensive-coding/scripts/split-snippets.py | 106 + defensive-coding/src/.svn/all-wcprops | 107 + defensive-coding/src/.svn/dir-prop-base | 11 + defensive-coding/src/.svn/entries | 609 ++ .../text-base/C-Arithmetic-add.c.svn-base | 17 + .../text-base/C-Arithmetic-mult.c.svn-base | 12 + .../text-base/C-Pointers-remaining.c.svn-base | 51 + .../text-base/C-String-Functions.c.svn-base | 49 + .../.svn/text-base/DERParser.java.svn-base | 274 + .../text-base/TLS-Client-GNUTLS.c.svn-base | 279 + .../.svn/text-base/TLS-Client-NSS.c.svn-base | 297 + .../text-base/TLS-Client-OpenSSL.c.svn-base | 329 + .../text-base/TLS-Client-Python.py.svn-base | 56 + .../text-base/TLSClientOpenJDK.java.svn-base | 262 + .../text-base/XML-Parser-Expat.c.svn-base | 135 + .../text-base/XMLParserOpenJDK.java.svn-base | 286 + .../.svn/text-base/check-function.py.svn-base | 18 + .../src/.svn/text-base/src.mk.svn-base | 53 + .../src/.svn/text-base/tcp_connect.c.svn-base | 52 + .../src/.svn/text-base/tcp_connect.h.svn-base | 6 + .../.svn/text-base/x509_check_host.c.svn-base | 355 + defensive-coding/src/C-Arithmetic-add.c | 17 + defensive-coding/src/C-Arithmetic-mult.c | 12 + defensive-coding/src/C-Pointers-remaining.c | 51 + defensive-coding/src/C-String-Functions.c | 49 + defensive-coding/src/DERParser.java | 274 + defensive-coding/src/TLS-Client-GNUTLS.c | 279 + defensive-coding/src/TLS-Client-NSS.c | 297 + defensive-coding/src/TLS-Client-OpenSSL.c | 329 + defensive-coding/src/TLS-Client-Python.py | 56 + defensive-coding/src/TLSClientOpenJDK.java | 262 + defensive-coding/src/XML-Parser-Expat.c | 135 + defensive-coding/src/XMLParserOpenJDK.java | 286 + defensive-coding/src/check-function.py | 18 + defensive-coding/src/data/.svn/all-wcprops | 197 + defensive-coding/src/data/.svn/entries | 1116 ++++ .../XML-Parser-DTD_Public.xml.svn-base | 5 + .../XML-Parser-DTD_Public_URL.xml.svn-base | 5 + .../XML-Parser-DTD_System.xml.svn-base | 5 + .../XML-Parser-DTD_System_URL.xml.svn-base | 5 + ...Parser-External_Entity_Public.xml.svn-base | 5 + ...er-External_Entity_Public_URL.xml.svn-base | 5 + ...Parser-External_Entity_System.xml.svn-base | 5 + ...er-External_Entity_System_URL.xml.svn-base | 5 + .../XML-Parser-External_Regexp_3.xml.svn-base | 5 + ...r-Internal_Entity_Exponential.xml.svn-base | 5 + ..._Entity_Exponential_Attribute.xml.svn-base | 5 + ...er-Internal_Entity_Polynomial.xml.svn-base | 5 + ...l_Entity_Polynomial_Attribute.xml.svn-base | 5 + .../XML-Parser-Internal_Regexp_1.xml.svn-base | 5 + .../XML-Parser-Internal_Regexp_2.xml.svn-base | 5 + .../XML-Parser-Internal_Regexp_3.xml.svn-base | 5 + .../XML-Parser-Notation_Public.xml.svn-base | 5 + ...ML-Parser-Notation_Public_URL.xml.svn-base | 5 + .../XML-Parser-Notation_System.xml.svn-base | 5 + ...ML-Parser-Notation_System_URL.xml.svn-base | 5 + .../XML-Parser-Validate-Regexp_1.rng.svn-base | 5 + .../XML-Parser-Validate-Regexp_1.xml.svn-base | 5 + .../XML-Parser-Validate-Regexp_1.xsd.svn-base | 5 + .../XML-Parser-Validate-Regexp_4.xsd.svn-base | 5 + .../XML-Parser-XInclude-File.xml.svn-base | 5 + .../XML-Parser-XInclude-URL.xml.svn-base | 5 + .../XML-Parser-XSD-File.xml.svn-base | 5 + .../XML-Parser-XSD-Include_File.xml.svn-base | 5 + .../XML-Parser-XSD-Include_URL.xml.svn-base | 5 + .../prop-base/XML-Parser-XSD-URL.xml.svn-base | 5 + .../XML-Parser-DTD_Public.xml.svn-base | 4 + .../XML-Parser-DTD_Public_URL.xml.svn-base | 4 + .../XML-Parser-DTD_System.xml.svn-base | 4 + .../XML-Parser-DTD_System_URL.xml.svn-base | 4 + ...Parser-External_Entity_Public.xml.svn-base | 7 + ...er-External_Entity_Public_URL.xml.svn-base | 7 + ...Parser-External_Entity_System.xml.svn-base | 7 + ...er-External_Entity_System_URL.xml.svn-base | 7 + .../XML-Parser-External_Regexp_3.dtd.svn-base | 11 + .../XML-Parser-External_Regexp_3.xml.svn-base | 10 + ...r-Internal_Entity_Exponential.xml.svn-base | 37 + ..._Entity_Exponential_Attribute.xml.svn-base | 38 + ...er-Internal_Entity_Polynomial.xml.svn-base | 13 + ...l_Entity_Polynomial_Attribute.xml.svn-base | 15 + .../XML-Parser-Internal_Regexp_1.xml.svn-base | 41 + .../XML-Parser-Internal_Regexp_2.xml.svn-base | 43 + .../XML-Parser-Internal_Regexp_3.xml.svn-base | 22 + .../XML-Parser-Notation_Public.xml.svn-base | 8 + ...ML-Parser-Notation_Public_URL.xml.svn-base | 8 + .../XML-Parser-Notation_System.xml.svn-base | 8 + ...ML-Parser-Notation_System_URL.xml.svn-base | 8 + .../XML-Parser-Validate-Regexp_1.dtd.svn-base | 28 + .../XML-Parser-Validate-Regexp_1.rng.svn-base | 1010 +++ .../XML-Parser-Validate-Regexp_1.xml.svn-base | 5 + .../XML-Parser-Validate-Regexp_1.xsd.svn-base | 990 +++ .../XML-Parser-Validate-Regexp_4.xsd.svn-base | 38 + .../XML-Parser-XInclude-File.xml.svn-base | 5 + .../XML-Parser-XInclude-URL.xml.svn-base | 5 + .../XML-Parser-XSD-File.xml.svn-base | 4 + .../XML-Parser-XSD-Include_File.xml.svn-base | 19 + .../XML-Parser-XSD-Include_URL.xml.svn-base | 19 + .../text-base/XML-Parser-XSD-URL.xml.svn-base | 4 + .../src/data/XML-Parser-DTD_Public.xml | 4 + .../src/data/XML-Parser-DTD_Public_URL.xml | 4 + .../src/data/XML-Parser-DTD_System.xml | 4 + .../src/data/XML-Parser-DTD_System_URL.xml | 4 + .../XML-Parser-External_Entity_Public.xml | 7 + .../XML-Parser-External_Entity_Public_URL.xml | 7 + .../XML-Parser-External_Entity_System.xml | 7 + .../XML-Parser-External_Entity_System_URL.xml | 7 + .../src/data/XML-Parser-External_Regexp_3.dtd | 11 + .../src/data/XML-Parser-External_Regexp_3.xml | 10 + ...XML-Parser-Internal_Entity_Exponential.xml | 37 + ...-Internal_Entity_Exponential_Attribute.xml | 38 + .../XML-Parser-Internal_Entity_Polynomial.xml | 13 + ...r-Internal_Entity_Polynomial_Attribute.xml | 15 + .../src/data/XML-Parser-Internal_Regexp_1.xml | 41 + .../src/data/XML-Parser-Internal_Regexp_2.xml | 43 + .../src/data/XML-Parser-Internal_Regexp_3.xml | 22 + .../src/data/XML-Parser-Notation_Public.xml | 8 + .../data/XML-Parser-Notation_Public_URL.xml | 8 + .../src/data/XML-Parser-Notation_System.xml | 8 + .../data/XML-Parser-Notation_System_URL.xml | 8 + .../src/data/XML-Parser-Validate-Regexp_1.dtd | 28 + .../src/data/XML-Parser-Validate-Regexp_1.rng | 1010 +++ .../src/data/XML-Parser-Validate-Regexp_1.xml | 5 + .../src/data/XML-Parser-Validate-Regexp_1.xsd | 990 +++ .../src/data/XML-Parser-Validate-Regexp_4.xsd | 38 + .../src/data/XML-Parser-XInclude-File.xml | 5 + .../src/data/XML-Parser-XInclude-URL.xml | 5 + .../src/data/XML-Parser-XSD-File.xml | 4 + .../src/data/XML-Parser-XSD-Include_File.xml | 19 + .../src/data/XML-Parser-XSD-Include_URL.xml | 19 + .../src/data/XML-Parser-XSD-URL.xml | 4 + defensive-coding/src/src.mk | 53 + defensive-coding/src/tcp_connect.c | 52 + defensive-coding/src/tcp_connect.h | 6 + defensive-coding/src/x509_check_host.c | 355 + .../en-US/html/Common_Content/css/common.css | 1528 +++++ .../en-US/html/Common_Content/css/default.css | 3 + .../en-US/html/Common_Content/css/lang.css | 2 + .../html/Common_Content/css/overrides.css | 47 + .../en-US/html/Common_Content/css/print.css | 16 + .../en-US/html/Common_Content/images/1.png | Bin 0 -> 640 bytes .../en-US/html/Common_Content/images/1.svg | 27 + .../en-US/html/Common_Content/images/10.png | Bin 0 -> 942 bytes .../en-US/html/Common_Content/images/10.svg | 31 + .../en-US/html/Common_Content/images/11.png | Bin 0 -> 741 bytes .../en-US/html/Common_Content/images/11.svg | 31 + .../en-US/html/Common_Content/images/12.png | Bin 0 -> 943 bytes .../en-US/html/Common_Content/images/12.svg | 31 + .../en-US/html/Common_Content/images/13.png | Bin 0 -> 983 bytes .../en-US/html/Common_Content/images/13.svg | 31 + .../en-US/html/Common_Content/images/14.png | Bin 0 -> 862 bytes .../en-US/html/Common_Content/images/14.svg | 31 + .../en-US/html/Common_Content/images/15.png | Bin 0 -> 936 bytes .../en-US/html/Common_Content/images/15.svg | 31 + .../en-US/html/Common_Content/images/16.png | Bin 0 -> 975 bytes .../en-US/html/Common_Content/images/16.svg | 31 + .../en-US/html/Common_Content/images/17.png | Bin 0 -> 838 bytes .../en-US/html/Common_Content/images/17.svg | 31 + .../en-US/html/Common_Content/images/18.png | Bin 0 -> 1013 bytes .../en-US/html/Common_Content/images/18.svg | 31 + .../en-US/html/Common_Content/images/19.png | Bin 0 -> 989 bytes .../en-US/html/Common_Content/images/19.svg | 31 + .../en-US/html/Common_Content/images/2.png | Bin 0 -> 814 bytes .../en-US/html/Common_Content/images/2.svg | 27 + .../en-US/html/Common_Content/images/20.png | Bin 0 -> 1086 bytes .../en-US/html/Common_Content/images/20.svg | 31 + .../en-US/html/Common_Content/images/21.png | Bin 0 -> 925 bytes .../en-US/html/Common_Content/images/21.svg | 31 + .../en-US/html/Common_Content/images/22.png | Bin 0 -> 1059 bytes .../en-US/html/Common_Content/images/22.svg | 31 + .../en-US/html/Common_Content/images/23.png | Bin 0 -> 1152 bytes .../en-US/html/Common_Content/images/23.svg | 31 + .../en-US/html/Common_Content/images/24.png | Bin 0 -> 1013 bytes .../en-US/html/Common_Content/images/24.svg | 31 + .../en-US/html/Common_Content/images/25.png | Bin 0 -> 1108 bytes .../en-US/html/Common_Content/images/25.svg | 31 + .../en-US/html/Common_Content/images/26.png | Bin 0 -> 1149 bytes .../en-US/html/Common_Content/images/26.svg | 31 + .../en-US/html/Common_Content/images/27.png | Bin 0 -> 1007 bytes .../en-US/html/Common_Content/images/27.svg | 31 + .../en-US/html/Common_Content/images/28.png | Bin 0 -> 1177 bytes .../en-US/html/Common_Content/images/28.svg | 31 + .../en-US/html/Common_Content/images/29.png | Bin 0 -> 1135 bytes .../en-US/html/Common_Content/images/29.svg | 31 + .../en-US/html/Common_Content/images/3.png | Bin 0 -> 889 bytes .../en-US/html/Common_Content/images/3.svg | 27 + .../en-US/html/Common_Content/images/30.png | Bin 0 -> 1179 bytes .../en-US/html/Common_Content/images/30.svg | 31 + .../en-US/html/Common_Content/images/31.png | Bin 0 -> 1012 bytes .../en-US/html/Common_Content/images/31.svg | 31 + .../en-US/html/Common_Content/images/32.png | Bin 0 -> 1151 bytes .../en-US/html/Common_Content/images/32.svg | 31 + .../en-US/html/Common_Content/images/33.png | Bin 0 -> 1213 bytes .../en-US/html/Common_Content/images/33.svg | 31 + .../en-US/html/Common_Content/images/34.png | Bin 0 -> 1107 bytes .../en-US/html/Common_Content/images/34.svg | 31 + .../en-US/html/Common_Content/images/35.png | Bin 0 -> 1176 bytes .../en-US/html/Common_Content/images/35.svg | 31 + .../en-US/html/Common_Content/images/36.png | Bin 0 -> 1222 bytes .../en-US/html/Common_Content/images/36.svg | 31 + .../en-US/html/Common_Content/images/37.png | Bin 0 -> 1085 bytes .../en-US/html/Common_Content/images/37.svg | 31 + .../en-US/html/Common_Content/images/38.png | Bin 0 -> 1256 bytes .../en-US/html/Common_Content/images/38.svg | 31 + .../en-US/html/Common_Content/images/39.png | Bin 0 -> 1226 bytes .../en-US/html/Common_Content/images/39.svg | 31 + .../en-US/html/Common_Content/images/4.png | Bin 0 -> 783 bytes .../en-US/html/Common_Content/images/4.svg | 27 + .../en-US/html/Common_Content/images/40.png | Bin 0 -> 1082 bytes .../en-US/html/Common_Content/images/40.svg | 31 + .../en-US/html/Common_Content/images/5.png | Bin 0 -> 839 bytes .../en-US/html/Common_Content/images/5.svg | 27 + .../en-US/html/Common_Content/images/6.png | Bin 0 -> 868 bytes .../en-US/html/Common_Content/images/6.svg | 27 + .../en-US/html/Common_Content/images/7.png | Bin 0 -> 757 bytes .../en-US/html/Common_Content/images/7.svg | 27 + .../en-US/html/Common_Content/images/8.png | Bin 0 -> 914 bytes .../en-US/html/Common_Content/images/8.svg | 27 + .../en-US/html/Common_Content/images/9.png | Bin 0 -> 877 bytes .../en-US/html/Common_Content/images/9.svg | 27 + .../Common_Content/images/bkgrnd_greydots.png | Bin 0 -> 157 bytes .../images/bullet_arrowblue.png | Bin 0 -> 177 bytes .../Common_Content/images/documentation.png | Bin 0 -> 1358 bytes .../en-US/html/Common_Content/images/dot.png | Bin 0 -> 98 bytes .../en-US/html/Common_Content/images/dot2.png | Bin 0 -> 98 bytes .../html/Common_Content/images/green.png | Bin 0 -> 176 bytes .../html/Common_Content/images/h1-bg.png | Bin 0 -> 142 bytes .../html/Common_Content/images/image_left.png | Bin 0 -> 2278 bytes .../Common_Content/images/image_right.png | Bin 0 -> 1358 bytes .../html/Common_Content/images/important.png | Bin 0 -> 1918 bytes .../html/Common_Content/images/important.svg | 30 + .../en-US/html/Common_Content/images/note.png | Bin 0 -> 1616 bytes .../en-US/html/Common_Content/images/note.svg | 28 + .../en-US/html/Common_Content/images/red.png | Bin 0 -> 163 bytes .../Common_Content/images/redhat-logo.svg | 94 + .../html/Common_Content/images/rhlogo.png | Bin 0 -> 2278 bytes .../html/Common_Content/images/shade.png | Bin 0 -> 101 bytes .../html/Common_Content/images/shine.png | Bin 0 -> 146 bytes .../Common_Content/images/stock-go-back.png | Bin 0 -> 571 bytes .../images/stock-go-forward.png | Bin 0 -> 531 bytes .../Common_Content/images/stock-go-up.png | Bin 0 -> 582 bytes .../html/Common_Content/images/stock-home.png | Bin 0 -> 772 bytes .../html/Common_Content/images/title_logo.png | Bin 0 -> 2278 bytes .../html/Common_Content/images/title_logo.svg | 94 + .../html/Common_Content/images/warning.png | Bin 0 -> 1940 bytes .../html/Common_Content/images/warning.svg | 32 + .../Common_Content/images/watermark-draft.png | Bin 0 -> 25365 bytes .../html/Common_Content/images/yellow.png | Bin 0 -> 175 bytes .../tmp/en-US/html/ch01s03s04.html | 12 + .../tmp/en-US/html/ch01s03s05.html | 6 + defensive-coding/tmp/en-US/html/ch03s02.html | 14 + defensive-coding/tmp/en-US/html/ch03s03.html | 4 + defensive-coding/tmp/en-US/html/ch04s02.html | 6 + defensive-coding/tmp/en-US/html/ch04s04.html | 20 + defensive-coding/tmp/en-US/html/ch07s02.html | 10 + defensive-coding/tmp/en-US/html/ch07s03.html | 10 + defensive-coding/tmp/en-US/html/ch07s05.html | 16 + defensive-coding/tmp/en-US/html/ch08s02.html | 14 + defensive-coding/tmp/en-US/html/ch08s03.html | 34 + defensive-coding/tmp/en-US/html/ch08s05.html | 8 + defensive-coding/tmp/en-US/html/ch09s02.html | 4 + defensive-coding/tmp/en-US/html/ch09s03.html | 20 + defensive-coding/tmp/en-US/html/ch09s05.html | 8 + defensive-coding/tmp/en-US/html/ch10s02.html | 24 + .../chap-Defensive_Coding-Authentication.html | 16 + .../en-US/html/chap-Defensive_Coding-C.html | 105 + .../en-US/html/chap-Defensive_Coding-CXX.html | 48 + .../html/chap-Defensive_Coding-Python.html | 16 + .../en-US/html/chap-Defensive_Coding-TLS.html | 99 + ...p-Defensive_Coding-Tasks-Cryptography.html | 32 + ...ap-Defensive_Coding-Tasks-File_System.html | 34 + ...Defensive_Coding-Tasks-Library_Design.html | 22 + ...-Defensive_Coding-Tasks-Serialization.html | 8 + ...sive_Coding-Tasks-Temporary_Directory.html | 8 + ...efensive_Coding-Tasks-Temporary_Files.html | 28 + defensive-coding/tmp/en-US/html/index.html | 34 + defensive-coding/tmp/en-US/html/pt01.html | 2 + defensive-coding/tmp/en-US/html/pt02.html | 2 + defensive-coding/tmp/en-US/html/pt03.html | 2 + ...sive_Coding-Authentication-Host_based.html | 14 + ...fensive_Coding-Authentication-Netlink.html | 8 + ...ive_Coding-Authentication-UNIX_Domain.html | 10 + ...-Defensive_Coding-C-Allocators-Arrays.html | 6 + ...-Defensive_Coding-C-Allocators-alloca.html | 14 + .../sect-Defensive_Coding-C-Allocators.html | 16 + .../html/sect-Defensive_Coding-C-Avoid.html | 28 + .../html/sect-Defensive_Coding-C-Libc.html | 30 + ...sive_Coding-C-String-Functions-Length.html | 32 + .../html/sect-Defensive_Coding-CXX-Std.html | 8 + ...ct-Defensive_Coding-TLS-Client-GNUTLS.html | 183 + .../sect-Defensive_Coding-TLS-Client-NSS.html | 226 + ...t-Defensive_Coding-TLS-Client-OpenJDK.html | 165 + ...ct-Defensive_Coding-TLS-Client-Python.html | 62 + .../sect-Defensive_Coding-TLS-Client.html | 199 + ...ing-Tasks-Descriptors-Child_Processes.html | 18 + ...ensive_Coding-Tasks-Descriptors-Limit.html | 22 + ...ct-Defensive_Coding-Tasks-Descriptors.html | 26 + ...ive_Coding-Tasks-File_System-Features.html | 28 + ...sive_Coding-Tasks-File_System-Foreign.html | 10 + ...e_Coding-Tasks-File_System-Free_Space.html | 4 + ...nsive_Coding-Tasks-File_System-Limits.html | 6 + ...Coding-Tasks-Library_Design-Callbacks.html | 14 + ...ensive_Coding-Tasks-Processes-Daemons.html | 18 + ..._Coding-Tasks-Processes-Fork-Parallel.html | 4 + ...sect-Defensive_Coding-Tasks-Processes.html | 56 + ...ding-Tasks-Serialization-XML-Entities.html | 6 + ..._Coding-Tasks-Serialization-XML-Expat.html | 31 + ...s-Serialization-XML-OpenJDK_Parse-SAX.html | 47 + ...Tasks-Serialization-XML-OpenJDK_Parse.html | 74 + ...ng-Tasks-Serialization-XML-Validation.html | 6 + ...ding-Tasks-Serialization-XML-XInclude.html | 6 + ...ensive_Coding-Tasks-Serialization-XML.html | 30 + ...ensive_Coding-1-Defensive_Coding-en-US.pdf | Bin 0 -> 490100 bytes .../tmp/en-US/pdf/file.eng.rdu.redhat.com | Bin 0 -> 490100 bytes .../tmp/en-US/pdf/file.rdu.redhat.com | Bin 0 -> 490100 bytes .../tmp/en-US/xml/Author_Group.xml | 19 + defensive-coding/tmp/en-US/xml/Book_Info.xml | 32 + .../tmp/en-US/xml/C/Allocators.xml | 123 + defensive-coding/tmp/en-US/xml/C/C.xml | 12 + defensive-coding/tmp/en-US/xml/C/Language.xml | 114 + defensive-coding/tmp/en-US/xml/C/Libc.xml | 200 + defensive-coding/tmp/en-US/xml/C/schemas.xml | 6 + .../en-US/xml/C/snippets/Arithmetic-add.xml | 24 + .../en-US/xml/C/snippets/Arithmetic-mult.xml | 17 + .../xml/C/snippets/Pointers-remaining.xml | 52 + .../C/snippets/String-Functions-format.xml | 21 + .../C/snippets/String-Functions-snprintf.xml | 11 + .../C/snippets/String-Functions-strncpy.xml | 12 + defensive-coding/tmp/en-US/xml/CXX/CXX.xml | 11 + .../tmp/en-US/xml/CXX/Language.xml | 132 + defensive-coding/tmp/en-US/xml/CXX/Std.xml | 24 + .../tmp/en-US/xml/CXX/schemas.xml | 6 + .../en-US/xml/Common_Content/Conventions.xml | 178 + .../tmp/en-US/xml/Common_Content/Feedback.xml | 24 + .../en-US/xml/Common_Content/Legal_Notice.xml | 38 + .../en-US/xml/Common_Content/css/common.css | 1528 +++++ .../en-US/xml/Common_Content/css/default.css | 3 + .../tmp/en-US/xml/Common_Content/css/lang.css | 2 + .../xml/Common_Content/css/overrides.css | 51 + .../en-US/xml/Common_Content/css/print.css | 16 + .../tmp/en-US/xml/Common_Content/images/1.png | Bin 0 -> 710 bytes .../tmp/en-US/xml/Common_Content/images/1.svg | 27 + .../en-US/xml/Common_Content/images/10.png | Bin 0 -> 985 bytes .../en-US/xml/Common_Content/images/10.svg | 31 + .../en-US/xml/Common_Content/images/11.png | Bin 0 -> 810 bytes .../en-US/xml/Common_Content/images/11.svg | 31 + .../en-US/xml/Common_Content/images/12.png | Bin 0 -> 1012 bytes .../en-US/xml/Common_Content/images/12.svg | 31 + .../en-US/xml/Common_Content/images/13.png | Bin 0 -> 1048 bytes .../en-US/xml/Common_Content/images/13.svg | 31 + .../en-US/xml/Common_Content/images/14.png | Bin 0 -> 914 bytes .../en-US/xml/Common_Content/images/14.svg | 31 + .../en-US/xml/Common_Content/images/15.png | Bin 0 -> 989 bytes .../en-US/xml/Common_Content/images/15.svg | 31 + .../en-US/xml/Common_Content/images/16.png | Bin 0 -> 1047 bytes .../en-US/xml/Common_Content/images/16.svg | 31 + .../en-US/xml/Common_Content/images/17.png | Bin 0 -> 888 bytes .../en-US/xml/Common_Content/images/17.svg | 31 + .../en-US/xml/Common_Content/images/18.png | Bin 0 -> 1075 bytes .../en-US/xml/Common_Content/images/18.svg | 31 + .../en-US/xml/Common_Content/images/19.png | Bin 0 -> 1049 bytes .../en-US/xml/Common_Content/images/19.svg | 31 + .../tmp/en-US/xml/Common_Content/images/2.png | Bin 0 -> 896 bytes .../tmp/en-US/xml/Common_Content/images/2.svg | 27 + .../en-US/xml/Common_Content/images/20.png | Bin 0 -> 1151 bytes .../en-US/xml/Common_Content/images/20.svg | 31 + .../en-US/xml/Common_Content/images/21.png | Bin 0 -> 994 bytes .../en-US/xml/Common_Content/images/21.svg | 31 + .../en-US/xml/Common_Content/images/22.png | Bin 0 -> 1162 bytes .../en-US/xml/Common_Content/images/22.svg | 31 + .../en-US/xml/Common_Content/images/23.png | Bin 0 -> 1207 bytes .../en-US/xml/Common_Content/images/23.svg | 31 + .../en-US/xml/Common_Content/images/24.png | Bin 0 -> 1081 bytes .../en-US/xml/Common_Content/images/24.svg | 31 + .../en-US/xml/Common_Content/images/25.png | Bin 0 -> 1173 bytes .../en-US/xml/Common_Content/images/25.svg | 31 + .../en-US/xml/Common_Content/images/26.png | Bin 0 -> 1208 bytes .../en-US/xml/Common_Content/images/26.svg | 31 + .../en-US/xml/Common_Content/images/27.png | Bin 0 -> 1080 bytes .../en-US/xml/Common_Content/images/27.svg | 31 + .../en-US/xml/Common_Content/images/28.png | Bin 0 -> 1225 bytes .../en-US/xml/Common_Content/images/28.svg | 31 + .../en-US/xml/Common_Content/images/29.png | Bin 0 -> 1196 bytes .../en-US/xml/Common_Content/images/29.svg | 31 + .../tmp/en-US/xml/Common_Content/images/3.png | Bin 0 -> 958 bytes .../tmp/en-US/xml/Common_Content/images/3.svg | 27 + .../en-US/xml/Common_Content/images/30.png | Bin 0 -> 1250 bytes .../en-US/xml/Common_Content/images/30.svg | 31 + .../en-US/xml/Common_Content/images/31.png | Bin 0 -> 1078 bytes .../en-US/xml/Common_Content/images/31.svg | 31 + .../en-US/xml/Common_Content/images/32.png | Bin 0 -> 1241 bytes .../en-US/xml/Common_Content/images/32.svg | 31 + .../en-US/xml/Common_Content/images/33.png | Bin 0 -> 1268 bytes .../en-US/xml/Common_Content/images/33.svg | 31 + .../en-US/xml/Common_Content/images/34.png | Bin 0 -> 1175 bytes .../en-US/xml/Common_Content/images/34.svg | 31 + .../en-US/xml/Common_Content/images/35.png | Bin 0 -> 1224 bytes .../en-US/xml/Common_Content/images/35.svg | 31 + .../en-US/xml/Common_Content/images/36.png | Bin 0 -> 1281 bytes .../en-US/xml/Common_Content/images/36.svg | 31 + .../en-US/xml/Common_Content/images/37.png | Bin 0 -> 1140 bytes .../en-US/xml/Common_Content/images/37.svg | 31 + .../en-US/xml/Common_Content/images/38.png | Bin 0 -> 1300 bytes .../en-US/xml/Common_Content/images/38.svg | 31 + .../en-US/xml/Common_Content/images/39.png | Bin 0 -> 1294 bytes .../en-US/xml/Common_Content/images/39.svg | 31 + .../tmp/en-US/xml/Common_Content/images/4.png | Bin 0 -> 849 bytes .../tmp/en-US/xml/Common_Content/images/4.svg | 27 + .../en-US/xml/Common_Content/images/40.png | Bin 0 -> 1130 bytes .../en-US/xml/Common_Content/images/40.svg | 31 + .../tmp/en-US/xml/Common_Content/images/5.png | Bin 0 -> 900 bytes .../tmp/en-US/xml/Common_Content/images/5.svg | 27 + .../tmp/en-US/xml/Common_Content/images/6.png | Bin 0 -> 929 bytes .../tmp/en-US/xml/Common_Content/images/6.svg | 27 + .../tmp/en-US/xml/Common_Content/images/7.png | Bin 0 -> 807 bytes .../tmp/en-US/xml/Common_Content/images/7.svg | 27 + .../tmp/en-US/xml/Common_Content/images/8.png | Bin 0 -> 962 bytes .../tmp/en-US/xml/Common_Content/images/8.svg | 27 + .../tmp/en-US/xml/Common_Content/images/9.png | Bin 0 -> 936 bytes .../tmp/en-US/xml/Common_Content/images/9.svg | 27 + .../Common_Content/images/bkgrnd_greydots.png | Bin 0 -> 157 bytes .../images/bullet_arrowblue.png | Bin 0 -> 177 bytes .../Common_Content/images/documentation.png | Bin 0 -> 623 bytes .../en-US/xml/Common_Content/images/dot.png | Bin 0 -> 98 bytes .../en-US/xml/Common_Content/images/dot2.png | Bin 0 -> 98 bytes .../en-US/xml/Common_Content/images/green.png | Bin 0 -> 176 bytes .../en-US/xml/Common_Content/images/h1-bg.png | Bin 0 -> 565 bytes .../xml/Common_Content/images/image_left.png | Bin 0 -> 1114 bytes .../xml/Common_Content/images/image_right.png | Bin 0 -> 2260 bytes .../xml/Common_Content/images/important.png | Bin 0 -> 2080 bytes .../xml/Common_Content/images/important.svg | 106 + .../en-US/xml/Common_Content/images/logo.png | Bin 0 -> 1114 bytes .../en-US/xml/Common_Content/images/note.png | Bin 0 -> 1241 bytes .../en-US/xml/Common_Content/images/note.svg | 111 + .../en-US/xml/Common_Content/images/red.png | Bin 0 -> 163 bytes .../xml/Common_Content/images/redhat-logo.svg | 94 + .../xml/Common_Content/images/rhlogo.png | Bin 0 -> 2278 bytes .../en-US/xml/Common_Content/images/shade.png | Bin 0 -> 101 bytes .../en-US/xml/Common_Content/images/shine.png | Bin 0 -> 146 bytes .../Common_Content/images/stock-go-back.png | Bin 0 -> 828 bytes .../images/stock-go-forward.png | Bin 0 -> 828 bytes .../xml/Common_Content/images/stock-go-up.png | Bin 0 -> 760 bytes .../xml/Common_Content/images/stock-home.png | Bin 0 -> 808 bytes .../xml/Common_Content/images/title_logo.png | Bin 0 -> 13399 bytes .../xml/Common_Content/images/title_logo.svg | 61 + .../xml/Common_Content/images/warning.png | Bin 0 -> 1340 bytes .../xml/Common_Content/images/warning.svg | 89 + .../Common_Content/images/watermark-draft.png | Bin 0 -> 25365 bytes .../xml/Common_Content/images/yellow.png | Bin 0 -> 175 bytes .../tmp/en-US/xml/Defensive_Coding.ent | 2 + .../tmp/en-US/xml/Defensive_Coding.fo | 1946 ++++++ .../tmp/en-US/xml/Defensive_Coding.xml | 34 + .../tmp/en-US/xml/Features/Authentication.xml | 105 + .../tmp/en-US/xml/Features/TLS.xml | 579 ++ .../tmp/en-US/xml/Features/schemas.xml | 6 + .../snippets/TLS-Client-GNUTLS-Connect.xml | 53 + .../TLS-Client-GNUTLS-Credentials.xml | 32 + .../snippets/TLS-Client-GNUTLS-Match.xml | 33 + .../snippets/TLS-Client-GNUTLS-Verify.xml | 45 + .../snippets/TLS-Client-NSS-Close.xml | 18 + .../snippets/TLS-Client-NSS-Connect.xml | 109 + .../snippets/TLS-Client-OpenJDK-Connect.xml | 29 + .../snippets/TLS-Client-OpenJDK-Context.xml | 29 + .../TLS-Client-OpenJDK-Context_For_Cert.xml | 25 + .../snippets/TLS-Client-OpenJDK-Hostname.xml | 10 + .../snippets/TLS-Client-OpenJDK-Import.xml | 21 + .../TLS-Client-OpenJDK-MyTrustManager.xml | 41 + .../snippets/TLS-Client-OpenJDK-Use.xml | 14 + .../snippets/TLS-Client-OpenSSL-CTX.xml | 74 + .../snippets/TLS-Client-OpenSSL-Connect.xml | 58 + .../TLS-Client-OpenSSL-Connection-Use.xml | 18 + .../snippets/TLS-Client-OpenSSL-Init.xml | 16 + .../snippets/TLS-Client-Python-Connect.xml | 17 + .../TLS-Client-Python-check_host_name.xml | 32 + .../snippets/TLS-GNUTLS-Credentials-Close.xml | 10 + .../snippets/TLS-GNUTLS-Disconnect.xml | 17 + .../xml/Features/snippets/TLS-GNUTLS-Init.xml | 10 + .../xml/Features/snippets/TLS-GNUTLS-Use.xml | 21 + .../xml/Features/snippets/TLS-NSS-Close.xml | 11 + .../Features/snippets/TLS-NSS-Includes.xml | 23 + .../xml/Features/snippets/TLS-NSS-Init.xml | 66 + .../xml/Features/snippets/TLS-NSS-Use.xml | 25 + .../en-US/xml/Features/snippets/TLS-Nagle.xml | 15 + .../snippets/TLS-OpenJDK-Parameters.xml | 30 + .../snippets/TLS-OpenSSL-Connection-Close.xml | 33 + .../snippets/TLS-OpenSSL-Context-Close.xml | 10 + .../Features/snippets/TLS-OpenSSL-Errors.xml | 34 + .../Features/snippets/TLS-Python-Close.xml | 10 + .../xml/Features/snippets/TLS-Python-Use.xml | 11 + .../tmp/en-US/xml/Python/Language.xml | 92 + .../tmp/en-US/xml/Python/schemas.xml | 6 + .../tmp/en-US/xml/Revision_History.xml | 33 + .../tmp/en-US/xml/Tasks/Cryptography.xml | 158 + .../tmp/en-US/xml/Tasks/Descriptors.xml | 154 + .../tmp/en-US/xml/Tasks/File_System.xml | 196 + .../tmp/en-US/xml/Tasks/Library_Design.xml | 136 + .../tmp/en-US/xml/Tasks/Locking.xml | 8 + .../tmp/en-US/xml/Tasks/Processes.xml | 322 + .../tmp/en-US/xml/Tasks/Serialization.xml | 292 + .../tmp/en-US/xml/Tasks/Temporary_Files.xml | 172 + .../tmp/en-US/xml/Tasks/schemas.xml | 6 + .../Serialization-XML-Expat-Create.xml | 20 + ...ialization-XML-Expat-EntityDeclHandler.xml | 19 + .../Serialization-XML-OpenJDK-Errors.xml | 25 + .../Serialization-XML-OpenJDK-Imports.xml | 30 + ...alization-XML-OpenJDK-NoEntityResolver.xml | 18 + ...ization-XML-OpenJDK-NoResourceResolver.xml | 20 + .../Serialization-XML-OpenJDK_Parse-DOM.xml | 22 + ...zation-XML-OpenJDK_Parse-XMLSchema_DOM.xml | 26 + ...zation-XML-OpenJDK_Parse-XMLSchema_SAX.xml | 29 + .../tmp/en-US/xml_tmp/Author_Group.xml | 17 + .../tmp/en-US/xml_tmp/Book_Info.xml | 30 + .../tmp/en-US/xml_tmp/C/Allocators.xml | 207 + defensive-coding/tmp/en-US/xml_tmp/C/C.xml | 11 + .../tmp/en-US/xml_tmp/C/Language.xml | 150 + defensive-coding/tmp/en-US/xml_tmp/C/Libc.xml | 227 + .../tmp/en-US/xml_tmp/C/schemas.xml | 4 + .../xml_tmp/C/snippets/Arithmetic-add.xml | 21 + .../xml_tmp/C/snippets/Arithmetic-mult.xml | 14 + .../xml_tmp/C/snippets/Pointers-remaining.xml | 49 + .../C/snippets/String-Functions-format.xml | 18 + .../C/snippets/String-Functions-snprintf.xml | 8 + .../C/snippets/String-Functions-strncpy.xml | 9 + .../tmp/en-US/xml_tmp/CXX/CXX.xml | 10 + .../tmp/en-US/xml_tmp/CXX/Language.xml | 186 + .../tmp/en-US/xml_tmp/CXX/Std.xml | 32 + .../tmp/en-US/xml_tmp/CXX/schemas.xml | 4 + .../tmp/en-US/xml_tmp/Defensive_Coding.ent | 2 + .../tmp/en-US/xml_tmp/Defensive_Coding.xml | 27 + .../en-US/xml_tmp/Features/Authentication.xml | 189 + .../tmp/en-US/xml_tmp/Features/TLS.xml | 988 +++ .../tmp/en-US/xml_tmp/Features/schemas.xml | 4 + .../snippets/TLS-Client-GNUTLS-Connect.xml | 50 + .../TLS-Client-GNUTLS-Credentials.xml | 29 + .../snippets/TLS-Client-GNUTLS-Match.xml | 30 + .../snippets/TLS-Client-GNUTLS-Verify.xml | 42 + .../snippets/TLS-Client-NSS-Close.xml | 15 + .../snippets/TLS-Client-NSS-Connect.xml | 106 + .../snippets/TLS-Client-OpenJDK-Connect.xml | 26 + .../snippets/TLS-Client-OpenJDK-Context.xml | 26 + .../TLS-Client-OpenJDK-Context_For_Cert.xml | 22 + .../snippets/TLS-Client-OpenJDK-Hostname.xml | 7 + .../snippets/TLS-Client-OpenJDK-Import.xml | 18 + .../TLS-Client-OpenJDK-MyTrustManager.xml | 38 + .../snippets/TLS-Client-OpenJDK-Use.xml | 11 + .../snippets/TLS-Client-OpenSSL-CTX.xml | 71 + .../snippets/TLS-Client-OpenSSL-Connect.xml | 55 + .../TLS-Client-OpenSSL-Connection-Use.xml | 15 + .../snippets/TLS-Client-OpenSSL-Init.xml | 13 + .../snippets/TLS-Client-Python-Connect.xml | 14 + .../TLS-Client-Python-check_host_name.xml | 29 + .../snippets/TLS-GNUTLS-Credentials-Close.xml | 7 + .../snippets/TLS-GNUTLS-Disconnect.xml | 14 + .../Features/snippets/TLS-GNUTLS-Init.xml | 7 + .../Features/snippets/TLS-GNUTLS-Use.xml | 18 + .../Features/snippets/TLS-NSS-Close.xml | 8 + .../Features/snippets/TLS-NSS-Includes.xml | 20 + .../Features/snippets/TLS-NSS-Init.xml | 63 + .../xml_tmp/Features/snippets/TLS-NSS-Use.xml | 22 + .../xml_tmp/Features/snippets/TLS-Nagle.xml | 12 + .../snippets/TLS-OpenJDK-Parameters.xml | 27 + .../snippets/TLS-OpenSSL-Connection-Close.xml | 30 + .../snippets/TLS-OpenSSL-Context-Close.xml | 7 + .../Features/snippets/TLS-OpenSSL-Errors.xml | 31 + .../Features/snippets/TLS-Python-Close.xml | 7 + .../Features/snippets/TLS-Python-Use.xml | 8 + .../tmp/en-US/xml_tmp/Python/Language.xml | 74 + .../tmp/en-US/xml_tmp/Python/schemas.xml | 4 + .../tmp/en-US/xml_tmp/Revision_History.xml | 27 + .../tmp/en-US/xml_tmp/Tasks/Cryptography.xml | 111 + .../tmp/en-US/xml_tmp/Tasks/Descriptors.xml | 266 + .../tmp/en-US/xml_tmp/Tasks/File_System.xml | 339 + .../en-US/xml_tmp/Tasks/Library_Design.xml | 195 + .../tmp/en-US/xml_tmp/Tasks/Locking.xml | 5 + .../tmp/en-US/xml_tmp/Tasks/Processes.xml | 483 ++ .../tmp/en-US/xml_tmp/Tasks/Serialization.xml | 397 ++ .../en-US/xml_tmp/Tasks/Temporary_Files.xml | 257 + .../tmp/en-US/xml_tmp/Tasks/schemas.xml | 4 + .../Serialization-XML-Expat-Create.xml | 17 + ...ialization-XML-Expat-EntityDeclHandler.xml | 16 + .../Serialization-XML-OpenJDK-Errors.xml | 22 + .../Serialization-XML-OpenJDK-Imports.xml | 27 + ...alization-XML-OpenJDK-NoEntityResolver.xml | 15 + ...ization-XML-OpenJDK-NoResourceResolver.xml | 17 + .../Serialization-XML-OpenJDK_Parse-DOM.xml | 19 + ...zation-XML-OpenJDK_Parse-XMLSchema_DOM.xml | 23 + ...zation-XML-OpenJDK_Parse-XMLSchema_SAX.xml | 26 + 754 files changed, 60855 insertions(+) create mode 100644 defensive-coding/Makefile create mode 100644 defensive-coding/README create mode 100644 defensive-coding/docbook-schema/.svn/all-wcprops create mode 100644 defensive-coding/docbook-schema/.svn/entries create mode 100644 defensive-coding/docbook-schema/.svn/text-base/README.svn-base create mode 100644 defensive-coding/docbook-schema/.svn/text-base/calstblx.rnc.svn-base create mode 100644 defensive-coding/docbook-schema/.svn/text-base/dbhierx.rnc.svn-base create mode 100644 defensive-coding/docbook-schema/.svn/text-base/dbnotnx.rnc.svn-base create mode 100644 defensive-coding/docbook-schema/.svn/text-base/dbpoolx.rnc.svn-base create mode 100644 defensive-coding/docbook-schema/.svn/text-base/docbook.rnc.svn-base create mode 100644 defensive-coding/docbook-schema/.svn/text-base/htmltblx.rnc.svn-base create mode 100644 defensive-coding/docbook-schema/README create mode 100644 defensive-coding/docbook-schema/calstblx.rnc create mode 100644 defensive-coding/docbook-schema/dbhierx.rnc create mode 100644 defensive-coding/docbook-schema/dbnotnx.rnc create mode 100644 defensive-coding/docbook-schema/dbpoolx.rnc create mode 100644 defensive-coding/docbook-schema/docbook.rnc create mode 100644 defensive-coding/docbook-schema/htmltblx.rnc create mode 100644 defensive-coding/en-US/.svn/all-wcprops create mode 100644 defensive-coding/en-US/.svn/entries create mode 100644 defensive-coding/en-US/.svn/prop-base/Book_Info.xml.svn-base create mode 100644 defensive-coding/en-US/.svn/prop-base/Defensive_Coding.xml.svn-base create mode 100644 defensive-coding/en-US/.svn/text-base/Book_Info.xml.svn-base create mode 100644 defensive-coding/en-US/.svn/text-base/Defensive_Coding.ent.svn-base create mode 100644 defensive-coding/en-US/.svn/text-base/Defensive_Coding.xml.svn-base create mode 100644 defensive-coding/en-US/Author_Group.xml create mode 100644 defensive-coding/en-US/Book_Info.xml create mode 100644 defensive-coding/en-US/C/.svn/all-wcprops create mode 100644 defensive-coding/en-US/C/.svn/dir-prop-base create mode 100644 defensive-coding/en-US/C/.svn/entries create mode 100644 defensive-coding/en-US/C/.svn/prop-base/Allocators.xml.svn-base create mode 100644 defensive-coding/en-US/C/.svn/prop-base/C.xml.svn-base create mode 100644 defensive-coding/en-US/C/.svn/prop-base/Language.xml.svn-base create mode 100644 defensive-coding/en-US/C/.svn/prop-base/Libc.xml.svn-base create mode 100644 defensive-coding/en-US/C/.svn/prop-base/schemas.xml.svn-base create mode 100644 defensive-coding/en-US/C/.svn/text-base/Allocators.xml.svn-base create mode 100644 defensive-coding/en-US/C/.svn/text-base/C.xml.svn-base create mode 100644 defensive-coding/en-US/C/.svn/text-base/Language.xml.svn-base create mode 100644 defensive-coding/en-US/C/.svn/text-base/Libc.xml.svn-base create mode 100644 defensive-coding/en-US/C/.svn/text-base/schemas.xml.svn-base create mode 100644 defensive-coding/en-US/C/Allocators.xml create mode 100644 defensive-coding/en-US/C/C.xml create mode 100644 defensive-coding/en-US/C/Language.xml create mode 100644 defensive-coding/en-US/C/Libc.xml create mode 100644 defensive-coding/en-US/C/schemas.xml create mode 100644 defensive-coding/en-US/C/snippets/Arithmetic-add.xml create mode 100644 defensive-coding/en-US/C/snippets/Arithmetic-mult.xml create mode 100644 defensive-coding/en-US/C/snippets/Pointers-remaining.xml create mode 100644 defensive-coding/en-US/C/snippets/String-Functions-format.xml create mode 100644 defensive-coding/en-US/C/snippets/String-Functions-snprintf.xml create mode 100644 defensive-coding/en-US/C/snippets/String-Functions-strncpy.xml create mode 100644 defensive-coding/en-US/CXX/.svn/all-wcprops create mode 100644 defensive-coding/en-US/CXX/.svn/dir-prop-base create mode 100644 defensive-coding/en-US/CXX/.svn/entries create mode 100644 defensive-coding/en-US/CXX/.svn/prop-base/CXX.xml.svn-base create mode 100644 defensive-coding/en-US/CXX/.svn/prop-base/Language.xml.svn-base create mode 100644 defensive-coding/en-US/CXX/.svn/prop-base/Std.xml.svn-base create mode 100644 defensive-coding/en-US/CXX/.svn/prop-base/schemas.xml.svn-base create mode 100644 defensive-coding/en-US/CXX/.svn/text-base/CXX.xml.svn-base create mode 100644 defensive-coding/en-US/CXX/.svn/text-base/Language.xml.svn-base create mode 100644 defensive-coding/en-US/CXX/.svn/text-base/Std.xml.svn-base create mode 100644 defensive-coding/en-US/CXX/.svn/text-base/schemas.xml.svn-base create mode 100644 defensive-coding/en-US/CXX/CXX.xml create mode 100644 defensive-coding/en-US/CXX/Language.xml create mode 100644 defensive-coding/en-US/CXX/Std.xml create mode 100644 defensive-coding/en-US/CXX/schemas.xml create mode 100644 defensive-coding/en-US/Defensive_Coding.ent create mode 100644 defensive-coding/en-US/Defensive_Coding.xml create mode 100644 defensive-coding/en-US/Features/.svn/all-wcprops create mode 100644 defensive-coding/en-US/Features/.svn/dir-prop-base create mode 100644 defensive-coding/en-US/Features/.svn/entries create mode 100644 defensive-coding/en-US/Features/.svn/prop-base/Authentication.xml.svn-base create mode 100644 defensive-coding/en-US/Features/.svn/prop-base/TLS.xml.svn-base create mode 100644 defensive-coding/en-US/Features/.svn/prop-base/schemas.xml.svn-base create mode 100644 defensive-coding/en-US/Features/.svn/text-base/Authentication.xml.svn-base create mode 100644 defensive-coding/en-US/Features/.svn/text-base/TLS.xml.svn-base create mode 100644 defensive-coding/en-US/Features/.svn/text-base/schemas.xml.svn-base create mode 100644 defensive-coding/en-US/Features/Authentication.xml create mode 100644 defensive-coding/en-US/Features/TLS.xml create mode 100644 defensive-coding/en-US/Features/schemas.xml create mode 100644 defensive-coding/en-US/Features/snippets/TLS-Client-GNUTLS-Connect.xml create mode 100644 defensive-coding/en-US/Features/snippets/TLS-Client-GNUTLS-Credentials.xml create mode 100644 defensive-coding/en-US/Features/snippets/TLS-Client-GNUTLS-Match.xml create mode 100644 defensive-coding/en-US/Features/snippets/TLS-Client-GNUTLS-Verify.xml create mode 100644 defensive-coding/en-US/Features/snippets/TLS-Client-NSS-Close.xml create mode 100644 defensive-coding/en-US/Features/snippets/TLS-Client-NSS-Connect.xml create mode 100644 defensive-coding/en-US/Features/snippets/TLS-Client-OpenJDK-Connect.xml create mode 100644 defensive-coding/en-US/Features/snippets/TLS-Client-OpenJDK-Context.xml create mode 100644 defensive-coding/en-US/Features/snippets/TLS-Client-OpenJDK-Context_For_Cert.xml create mode 100644 defensive-coding/en-US/Features/snippets/TLS-Client-OpenJDK-Hostname.xml create mode 100644 defensive-coding/en-US/Features/snippets/TLS-Client-OpenJDK-Import.xml create mode 100644 defensive-coding/en-US/Features/snippets/TLS-Client-OpenJDK-MyTrustManager.xml create mode 100644 defensive-coding/en-US/Features/snippets/TLS-Client-OpenJDK-Use.xml create mode 100644 defensive-coding/en-US/Features/snippets/TLS-Client-OpenSSL-CTX.xml create mode 100644 defensive-coding/en-US/Features/snippets/TLS-Client-OpenSSL-Connect.xml create mode 100644 defensive-coding/en-US/Features/snippets/TLS-Client-OpenSSL-Connection-Use.xml create mode 100644 defensive-coding/en-US/Features/snippets/TLS-Client-OpenSSL-Init.xml create mode 100644 defensive-coding/en-US/Features/snippets/TLS-Client-Python-Connect.xml create mode 100644 defensive-coding/en-US/Features/snippets/TLS-Client-Python-check_host_name.xml create mode 100644 defensive-coding/en-US/Features/snippets/TLS-GNUTLS-Credentials-Close.xml create mode 100644 defensive-coding/en-US/Features/snippets/TLS-GNUTLS-Disconnect.xml create mode 100644 defensive-coding/en-US/Features/snippets/TLS-GNUTLS-Init.xml create mode 100644 defensive-coding/en-US/Features/snippets/TLS-GNUTLS-Use.xml create mode 100644 defensive-coding/en-US/Features/snippets/TLS-NSS-Close.xml create mode 100644 defensive-coding/en-US/Features/snippets/TLS-NSS-Includes.xml create mode 100644 defensive-coding/en-US/Features/snippets/TLS-NSS-Init.xml create mode 100644 defensive-coding/en-US/Features/snippets/TLS-NSS-Use.xml create mode 100644 defensive-coding/en-US/Features/snippets/TLS-Nagle.xml create mode 100644 defensive-coding/en-US/Features/snippets/TLS-OpenJDK-Parameters.xml create mode 100644 defensive-coding/en-US/Features/snippets/TLS-OpenSSL-Connection-Close.xml create mode 100644 defensive-coding/en-US/Features/snippets/TLS-OpenSSL-Context-Close.xml create mode 100644 defensive-coding/en-US/Features/snippets/TLS-OpenSSL-Errors.xml create mode 100644 defensive-coding/en-US/Features/snippets/TLS-Python-Close.xml create mode 100644 defensive-coding/en-US/Features/snippets/TLS-Python-Use.xml create mode 100644 defensive-coding/en-US/Python/.svn/all-wcprops create mode 100644 defensive-coding/en-US/Python/.svn/dir-prop-base create mode 100644 defensive-coding/en-US/Python/.svn/entries create mode 100644 defensive-coding/en-US/Python/.svn/prop-base/Language.xml.svn-base create mode 100644 defensive-coding/en-US/Python/.svn/prop-base/schemas.xml.svn-base create mode 100644 defensive-coding/en-US/Python/.svn/text-base/Language.xml.svn-base create mode 100644 defensive-coding/en-US/Python/.svn/text-base/schemas.xml.svn-base create mode 100644 defensive-coding/en-US/Python/Language.xml create mode 100644 defensive-coding/en-US/Python/schemas.xml create mode 100644 defensive-coding/en-US/Revision_History.xml create mode 100644 defensive-coding/en-US/Tasks/.svn/all-wcprops create mode 100644 defensive-coding/en-US/Tasks/.svn/dir-prop-base create mode 100644 defensive-coding/en-US/Tasks/.svn/entries create mode 100644 defensive-coding/en-US/Tasks/.svn/prop-base/Cryptography.xml.svn-base create mode 100644 defensive-coding/en-US/Tasks/.svn/prop-base/Descriptors.xml.svn-base create mode 100644 defensive-coding/en-US/Tasks/.svn/prop-base/File_System.xml.svn-base create mode 100644 defensive-coding/en-US/Tasks/.svn/prop-base/Library_Design.xml.svn-base create mode 100644 defensive-coding/en-US/Tasks/.svn/prop-base/Locking.xml.svn-base create mode 100644 defensive-coding/en-US/Tasks/.svn/prop-base/Processes.xml.svn-base create mode 100644 defensive-coding/en-US/Tasks/.svn/prop-base/Serialization.xml.svn-base create mode 100644 defensive-coding/en-US/Tasks/.svn/prop-base/Temporary_Files.xml.svn-base create mode 100644 defensive-coding/en-US/Tasks/.svn/prop-base/schemas.xml.svn-base create mode 100644 defensive-coding/en-US/Tasks/.svn/text-base/Cryptography.xml.svn-base create mode 100644 defensive-coding/en-US/Tasks/.svn/text-base/Descriptors.xml.svn-base create mode 100644 defensive-coding/en-US/Tasks/.svn/text-base/File_System.xml.svn-base create mode 100644 defensive-coding/en-US/Tasks/.svn/text-base/Library_Design.xml.svn-base create mode 100644 defensive-coding/en-US/Tasks/.svn/text-base/Locking.xml.svn-base create mode 100644 defensive-coding/en-US/Tasks/.svn/text-base/Processes.xml.svn-base create mode 100644 defensive-coding/en-US/Tasks/.svn/text-base/Serialization.xml.svn-base create mode 100644 defensive-coding/en-US/Tasks/.svn/text-base/Temporary_Files.xml.svn-base create mode 100644 defensive-coding/en-US/Tasks/.svn/text-base/schemas.xml.svn-base create mode 100644 defensive-coding/en-US/Tasks/Cryptography.xml create mode 100644 defensive-coding/en-US/Tasks/Descriptors.xml create mode 100644 defensive-coding/en-US/Tasks/File_System.xml create mode 100644 defensive-coding/en-US/Tasks/Library_Design.xml create mode 100644 defensive-coding/en-US/Tasks/Locking.xml create mode 100644 defensive-coding/en-US/Tasks/Processes.xml create mode 100644 defensive-coding/en-US/Tasks/Serialization.xml create mode 100644 defensive-coding/en-US/Tasks/Temporary_Files.xml create mode 100644 defensive-coding/en-US/Tasks/schemas.xml create mode 100644 defensive-coding/en-US/Tasks/snippets/Serialization-XML-Expat-Create.xml create mode 100644 defensive-coding/en-US/Tasks/snippets/Serialization-XML-Expat-EntityDeclHandler.xml create mode 100644 defensive-coding/en-US/Tasks/snippets/Serialization-XML-OpenJDK-Errors.xml create mode 100644 defensive-coding/en-US/Tasks/snippets/Serialization-XML-OpenJDK-Imports.xml create mode 100644 defensive-coding/en-US/Tasks/snippets/Serialization-XML-OpenJDK-NoEntityResolver.xml create mode 100644 defensive-coding/en-US/Tasks/snippets/Serialization-XML-OpenJDK-NoResourceResolver.xml create mode 100644 defensive-coding/en-US/Tasks/snippets/Serialization-XML-OpenJDK_Parse-DOM.xml create mode 100644 defensive-coding/en-US/Tasks/snippets/Serialization-XML-OpenJDK_Parse-XMLSchema_DOM.xml create mode 100644 defensive-coding/en-US/Tasks/snippets/Serialization-XML-OpenJDK_Parse-XMLSchema_SAX.xml create mode 100644 defensive-coding/publican.cfg create mode 100644 defensive-coding/schemas.xml create mode 100644 defensive-coding/scripts/.svn/all-wcprops create mode 100644 defensive-coding/scripts/.svn/entries create mode 100644 defensive-coding/scripts/.svn/text-base/split-snippets.py.svn-base create mode 100644 defensive-coding/scripts/split-snippets.py create mode 100644 defensive-coding/src/.svn/all-wcprops create mode 100644 defensive-coding/src/.svn/dir-prop-base create mode 100644 defensive-coding/src/.svn/entries create mode 100644 defensive-coding/src/.svn/text-base/C-Arithmetic-add.c.svn-base create mode 100644 defensive-coding/src/.svn/text-base/C-Arithmetic-mult.c.svn-base create mode 100644 defensive-coding/src/.svn/text-base/C-Pointers-remaining.c.svn-base create mode 100644 defensive-coding/src/.svn/text-base/C-String-Functions.c.svn-base create mode 100644 defensive-coding/src/.svn/text-base/DERParser.java.svn-base create mode 100644 defensive-coding/src/.svn/text-base/TLS-Client-GNUTLS.c.svn-base create mode 100644 defensive-coding/src/.svn/text-base/TLS-Client-NSS.c.svn-base create mode 100644 defensive-coding/src/.svn/text-base/TLS-Client-OpenSSL.c.svn-base create mode 100644 defensive-coding/src/.svn/text-base/TLS-Client-Python.py.svn-base create mode 100644 defensive-coding/src/.svn/text-base/TLSClientOpenJDK.java.svn-base create mode 100644 defensive-coding/src/.svn/text-base/XML-Parser-Expat.c.svn-base create mode 100644 defensive-coding/src/.svn/text-base/XMLParserOpenJDK.java.svn-base create mode 100644 defensive-coding/src/.svn/text-base/check-function.py.svn-base create mode 100644 defensive-coding/src/.svn/text-base/src.mk.svn-base create mode 100644 defensive-coding/src/.svn/text-base/tcp_connect.c.svn-base create mode 100644 defensive-coding/src/.svn/text-base/tcp_connect.h.svn-base create mode 100644 defensive-coding/src/.svn/text-base/x509_check_host.c.svn-base create mode 100644 defensive-coding/src/C-Arithmetic-add.c create mode 100644 defensive-coding/src/C-Arithmetic-mult.c create mode 100644 defensive-coding/src/C-Pointers-remaining.c create mode 100644 defensive-coding/src/C-String-Functions.c create mode 100644 defensive-coding/src/DERParser.java create mode 100644 defensive-coding/src/TLS-Client-GNUTLS.c create mode 100644 defensive-coding/src/TLS-Client-NSS.c create mode 100644 defensive-coding/src/TLS-Client-OpenSSL.c create mode 100644 defensive-coding/src/TLS-Client-Python.py create mode 100644 defensive-coding/src/TLSClientOpenJDK.java create mode 100644 defensive-coding/src/XML-Parser-Expat.c create mode 100644 defensive-coding/src/XMLParserOpenJDK.java create mode 100644 defensive-coding/src/check-function.py create mode 100644 defensive-coding/src/data/.svn/all-wcprops create mode 100644 defensive-coding/src/data/.svn/entries create mode 100644 defensive-coding/src/data/.svn/prop-base/XML-Parser-DTD_Public.xml.svn-base create mode 100644 defensive-coding/src/data/.svn/prop-base/XML-Parser-DTD_Public_URL.xml.svn-base create mode 100644 defensive-coding/src/data/.svn/prop-base/XML-Parser-DTD_System.xml.svn-base create mode 100644 defensive-coding/src/data/.svn/prop-base/XML-Parser-DTD_System_URL.xml.svn-base create mode 100644 defensive-coding/src/data/.svn/prop-base/XML-Parser-External_Entity_Public.xml.svn-base create mode 100644 defensive-coding/src/data/.svn/prop-base/XML-Parser-External_Entity_Public_URL.xml.svn-base create mode 100644 defensive-coding/src/data/.svn/prop-base/XML-Parser-External_Entity_System.xml.svn-base create mode 100644 defensive-coding/src/data/.svn/prop-base/XML-Parser-External_Entity_System_URL.xml.svn-base create mode 100644 defensive-coding/src/data/.svn/prop-base/XML-Parser-External_Regexp_3.xml.svn-base create mode 100644 defensive-coding/src/data/.svn/prop-base/XML-Parser-Internal_Entity_Exponential.xml.svn-base create mode 100644 defensive-coding/src/data/.svn/prop-base/XML-Parser-Internal_Entity_Exponential_Attribute.xml.svn-base create mode 100644 defensive-coding/src/data/.svn/prop-base/XML-Parser-Internal_Entity_Polynomial.xml.svn-base create mode 100644 defensive-coding/src/data/.svn/prop-base/XML-Parser-Internal_Entity_Polynomial_Attribute.xml.svn-base create mode 100644 defensive-coding/src/data/.svn/prop-base/XML-Parser-Internal_Regexp_1.xml.svn-base create mode 100644 defensive-coding/src/data/.svn/prop-base/XML-Parser-Internal_Regexp_2.xml.svn-base create mode 100644 defensive-coding/src/data/.svn/prop-base/XML-Parser-Internal_Regexp_3.xml.svn-base create mode 100644 defensive-coding/src/data/.svn/prop-base/XML-Parser-Notation_Public.xml.svn-base create mode 100644 defensive-coding/src/data/.svn/prop-base/XML-Parser-Notation_Public_URL.xml.svn-base create mode 100644 defensive-coding/src/data/.svn/prop-base/XML-Parser-Notation_System.xml.svn-base create mode 100644 defensive-coding/src/data/.svn/prop-base/XML-Parser-Notation_System_URL.xml.svn-base create mode 100644 defensive-coding/src/data/.svn/prop-base/XML-Parser-Validate-Regexp_1.rng.svn-base create mode 100644 defensive-coding/src/data/.svn/prop-base/XML-Parser-Validate-Regexp_1.xml.svn-base create mode 100644 defensive-coding/src/data/.svn/prop-base/XML-Parser-Validate-Regexp_1.xsd.svn-base create mode 100644 defensive-coding/src/data/.svn/prop-base/XML-Parser-Validate-Regexp_4.xsd.svn-base create mode 100644 defensive-coding/src/data/.svn/prop-base/XML-Parser-XInclude-File.xml.svn-base create mode 100644 defensive-coding/src/data/.svn/prop-base/XML-Parser-XInclude-URL.xml.svn-base create mode 100644 defensive-coding/src/data/.svn/prop-base/XML-Parser-XSD-File.xml.svn-base create mode 100644 defensive-coding/src/data/.svn/prop-base/XML-Parser-XSD-Include_File.xml.svn-base create mode 100644 defensive-coding/src/data/.svn/prop-base/XML-Parser-XSD-Include_URL.xml.svn-base create mode 100644 defensive-coding/src/data/.svn/prop-base/XML-Parser-XSD-URL.xml.svn-base create mode 100644 defensive-coding/src/data/.svn/text-base/XML-Parser-DTD_Public.xml.svn-base create mode 100644 defensive-coding/src/data/.svn/text-base/XML-Parser-DTD_Public_URL.xml.svn-base create mode 100644 defensive-coding/src/data/.svn/text-base/XML-Parser-DTD_System.xml.svn-base create mode 100644 defensive-coding/src/data/.svn/text-base/XML-Parser-DTD_System_URL.xml.svn-base create mode 100644 defensive-coding/src/data/.svn/text-base/XML-Parser-External_Entity_Public.xml.svn-base create mode 100644 defensive-coding/src/data/.svn/text-base/XML-Parser-External_Entity_Public_URL.xml.svn-base create mode 100644 defensive-coding/src/data/.svn/text-base/XML-Parser-External_Entity_System.xml.svn-base create mode 100644 defensive-coding/src/data/.svn/text-base/XML-Parser-External_Entity_System_URL.xml.svn-base create mode 100644 defensive-coding/src/data/.svn/text-base/XML-Parser-External_Regexp_3.dtd.svn-base create mode 100644 defensive-coding/src/data/.svn/text-base/XML-Parser-External_Regexp_3.xml.svn-base create mode 100644 defensive-coding/src/data/.svn/text-base/XML-Parser-Internal_Entity_Exponential.xml.svn-base create mode 100644 defensive-coding/src/data/.svn/text-base/XML-Parser-Internal_Entity_Exponential_Attribute.xml.svn-base create mode 100644 defensive-coding/src/data/.svn/text-base/XML-Parser-Internal_Entity_Polynomial.xml.svn-base create mode 100644 defensive-coding/src/data/.svn/text-base/XML-Parser-Internal_Entity_Polynomial_Attribute.xml.svn-base create mode 100644 defensive-coding/src/data/.svn/text-base/XML-Parser-Internal_Regexp_1.xml.svn-base create mode 100644 defensive-coding/src/data/.svn/text-base/XML-Parser-Internal_Regexp_2.xml.svn-base create mode 100644 defensive-coding/src/data/.svn/text-base/XML-Parser-Internal_Regexp_3.xml.svn-base create mode 100644 defensive-coding/src/data/.svn/text-base/XML-Parser-Notation_Public.xml.svn-base create mode 100644 defensive-coding/src/data/.svn/text-base/XML-Parser-Notation_Public_URL.xml.svn-base create mode 100644 defensive-coding/src/data/.svn/text-base/XML-Parser-Notation_System.xml.svn-base create mode 100644 defensive-coding/src/data/.svn/text-base/XML-Parser-Notation_System_URL.xml.svn-base create mode 100644 defensive-coding/src/data/.svn/text-base/XML-Parser-Validate-Regexp_1.dtd.svn-base create mode 100644 defensive-coding/src/data/.svn/text-base/XML-Parser-Validate-Regexp_1.rng.svn-base create mode 100644 defensive-coding/src/data/.svn/text-base/XML-Parser-Validate-Regexp_1.xml.svn-base create mode 100644 defensive-coding/src/data/.svn/text-base/XML-Parser-Validate-Regexp_1.xsd.svn-base create mode 100644 defensive-coding/src/data/.svn/text-base/XML-Parser-Validate-Regexp_4.xsd.svn-base create mode 100644 defensive-coding/src/data/.svn/text-base/XML-Parser-XInclude-File.xml.svn-base create mode 100644 defensive-coding/src/data/.svn/text-base/XML-Parser-XInclude-URL.xml.svn-base create mode 100644 defensive-coding/src/data/.svn/text-base/XML-Parser-XSD-File.xml.svn-base create mode 100644 defensive-coding/src/data/.svn/text-base/XML-Parser-XSD-Include_File.xml.svn-base create mode 100644 defensive-coding/src/data/.svn/text-base/XML-Parser-XSD-Include_URL.xml.svn-base create mode 100644 defensive-coding/src/data/.svn/text-base/XML-Parser-XSD-URL.xml.svn-base create mode 100644 defensive-coding/src/data/XML-Parser-DTD_Public.xml create mode 100644 defensive-coding/src/data/XML-Parser-DTD_Public_URL.xml create mode 100644 defensive-coding/src/data/XML-Parser-DTD_System.xml create mode 100644 defensive-coding/src/data/XML-Parser-DTD_System_URL.xml create mode 100644 defensive-coding/src/data/XML-Parser-External_Entity_Public.xml create mode 100644 defensive-coding/src/data/XML-Parser-External_Entity_Public_URL.xml create mode 100644 defensive-coding/src/data/XML-Parser-External_Entity_System.xml create mode 100644 defensive-coding/src/data/XML-Parser-External_Entity_System_URL.xml create mode 100644 defensive-coding/src/data/XML-Parser-External_Regexp_3.dtd create mode 100644 defensive-coding/src/data/XML-Parser-External_Regexp_3.xml create mode 100644 defensive-coding/src/data/XML-Parser-Internal_Entity_Exponential.xml create mode 100644 defensive-coding/src/data/XML-Parser-Internal_Entity_Exponential_Attribute.xml create mode 100644 defensive-coding/src/data/XML-Parser-Internal_Entity_Polynomial.xml create mode 100644 defensive-coding/src/data/XML-Parser-Internal_Entity_Polynomial_Attribute.xml create mode 100644 defensive-coding/src/data/XML-Parser-Internal_Regexp_1.xml create mode 100644 defensive-coding/src/data/XML-Parser-Internal_Regexp_2.xml create mode 100644 defensive-coding/src/data/XML-Parser-Internal_Regexp_3.xml create mode 100644 defensive-coding/src/data/XML-Parser-Notation_Public.xml create mode 100644 defensive-coding/src/data/XML-Parser-Notation_Public_URL.xml create mode 100644 defensive-coding/src/data/XML-Parser-Notation_System.xml create mode 100644 defensive-coding/src/data/XML-Parser-Notation_System_URL.xml create mode 100644 defensive-coding/src/data/XML-Parser-Validate-Regexp_1.dtd create mode 100644 defensive-coding/src/data/XML-Parser-Validate-Regexp_1.rng create mode 100644 defensive-coding/src/data/XML-Parser-Validate-Regexp_1.xml create mode 100644 defensive-coding/src/data/XML-Parser-Validate-Regexp_1.xsd create mode 100644 defensive-coding/src/data/XML-Parser-Validate-Regexp_4.xsd create mode 100644 defensive-coding/src/data/XML-Parser-XInclude-File.xml create mode 100644 defensive-coding/src/data/XML-Parser-XInclude-URL.xml create mode 100644 defensive-coding/src/data/XML-Parser-XSD-File.xml create mode 100644 defensive-coding/src/data/XML-Parser-XSD-Include_File.xml create mode 100644 defensive-coding/src/data/XML-Parser-XSD-Include_URL.xml create mode 100644 defensive-coding/src/data/XML-Parser-XSD-URL.xml create mode 100644 defensive-coding/src/src.mk create mode 100644 defensive-coding/src/tcp_connect.c create mode 100644 defensive-coding/src/tcp_connect.h create mode 100644 defensive-coding/src/x509_check_host.c create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/css/common.css create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/css/default.css create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/css/lang.css create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/css/overrides.css create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/css/print.css create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/1.png create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/1.svg create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/10.png create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/10.svg create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/11.png create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/11.svg create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/12.png create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/12.svg create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/13.png create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/13.svg create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/14.png create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/14.svg create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/15.png create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/15.svg create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/16.png create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/16.svg create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/17.png create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/17.svg create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/18.png create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/18.svg create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/19.png create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/19.svg create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/2.png create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/2.svg create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/20.png create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/20.svg create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/21.png create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/21.svg create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/22.png create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/22.svg create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/23.png create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/23.svg create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/24.png create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/24.svg create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/25.png create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/25.svg create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/26.png create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/26.svg create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/27.png create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/27.svg create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/28.png create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/28.svg create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/29.png create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/29.svg create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/3.png create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/3.svg create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/30.png create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/30.svg create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/31.png create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/31.svg create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/32.png create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/32.svg create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/33.png create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/33.svg create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/34.png create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/34.svg create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/35.png create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/35.svg create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/36.png create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/36.svg create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/37.png create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/37.svg create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/38.png create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/38.svg create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/39.png create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/39.svg create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/4.png create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/4.svg create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/40.png create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/40.svg create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/5.png create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/5.svg create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/6.png create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/6.svg create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/7.png create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/7.svg create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/8.png create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/8.svg create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/9.png create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/9.svg create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/bkgrnd_greydots.png create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/bullet_arrowblue.png create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/documentation.png create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/dot.png create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/dot2.png create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/green.png create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/h1-bg.png create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/image_left.png create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/image_right.png create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/important.png create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/important.svg create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/note.png create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/note.svg create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/red.png create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/redhat-logo.svg create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/rhlogo.png create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/shade.png create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/shine.png create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/stock-go-back.png create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/stock-go-forward.png create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/stock-go-up.png create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/stock-home.png create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/title_logo.png create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/title_logo.svg create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/warning.png create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/warning.svg create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/watermark-draft.png create mode 100644 defensive-coding/tmp/en-US/html/Common_Content/images/yellow.png create mode 100644 defensive-coding/tmp/en-US/html/ch01s03s04.html create mode 100644 defensive-coding/tmp/en-US/html/ch01s03s05.html create mode 100644 defensive-coding/tmp/en-US/html/ch03s02.html create mode 100644 defensive-coding/tmp/en-US/html/ch03s03.html create mode 100644 defensive-coding/tmp/en-US/html/ch04s02.html create mode 100644 defensive-coding/tmp/en-US/html/ch04s04.html create mode 100644 defensive-coding/tmp/en-US/html/ch07s02.html create mode 100644 defensive-coding/tmp/en-US/html/ch07s03.html create mode 100644 defensive-coding/tmp/en-US/html/ch07s05.html create mode 100644 defensive-coding/tmp/en-US/html/ch08s02.html create mode 100644 defensive-coding/tmp/en-US/html/ch08s03.html create mode 100644 defensive-coding/tmp/en-US/html/ch08s05.html create mode 100644 defensive-coding/tmp/en-US/html/ch09s02.html create mode 100644 defensive-coding/tmp/en-US/html/ch09s03.html create mode 100644 defensive-coding/tmp/en-US/html/ch09s05.html create mode 100644 defensive-coding/tmp/en-US/html/ch10s02.html create mode 100644 defensive-coding/tmp/en-US/html/chap-Defensive_Coding-Authentication.html create mode 100644 defensive-coding/tmp/en-US/html/chap-Defensive_Coding-C.html create mode 100644 defensive-coding/tmp/en-US/html/chap-Defensive_Coding-CXX.html create mode 100644 defensive-coding/tmp/en-US/html/chap-Defensive_Coding-Python.html create mode 100644 defensive-coding/tmp/en-US/html/chap-Defensive_Coding-TLS.html create mode 100644 defensive-coding/tmp/en-US/html/chap-Defensive_Coding-Tasks-Cryptography.html create mode 100644 defensive-coding/tmp/en-US/html/chap-Defensive_Coding-Tasks-File_System.html create mode 100644 defensive-coding/tmp/en-US/html/chap-Defensive_Coding-Tasks-Library_Design.html create mode 100644 defensive-coding/tmp/en-US/html/chap-Defensive_Coding-Tasks-Serialization.html create mode 100644 defensive-coding/tmp/en-US/html/chap-Defensive_Coding-Tasks-Temporary_Directory.html create mode 100644 defensive-coding/tmp/en-US/html/chap-Defensive_Coding-Tasks-Temporary_Files.html create mode 100644 defensive-coding/tmp/en-US/html/index.html create mode 100644 defensive-coding/tmp/en-US/html/pt01.html create mode 100644 defensive-coding/tmp/en-US/html/pt02.html create mode 100644 defensive-coding/tmp/en-US/html/pt03.html create mode 100644 defensive-coding/tmp/en-US/html/sect-Defensive_Coding-Authentication-Host_based.html create mode 100644 defensive-coding/tmp/en-US/html/sect-Defensive_Coding-Authentication-Netlink.html create mode 100644 defensive-coding/tmp/en-US/html/sect-Defensive_Coding-Authentication-UNIX_Domain.html create mode 100644 defensive-coding/tmp/en-US/html/sect-Defensive_Coding-C-Allocators-Arrays.html create mode 100644 defensive-coding/tmp/en-US/html/sect-Defensive_Coding-C-Allocators-alloca.html create mode 100644 defensive-coding/tmp/en-US/html/sect-Defensive_Coding-C-Allocators.html create mode 100644 defensive-coding/tmp/en-US/html/sect-Defensive_Coding-C-Avoid.html create mode 100644 defensive-coding/tmp/en-US/html/sect-Defensive_Coding-C-Libc.html create mode 100644 defensive-coding/tmp/en-US/html/sect-Defensive_Coding-C-String-Functions-Length.html create mode 100644 defensive-coding/tmp/en-US/html/sect-Defensive_Coding-CXX-Std.html create mode 100644 defensive-coding/tmp/en-US/html/sect-Defensive_Coding-TLS-Client-GNUTLS.html create mode 100644 defensive-coding/tmp/en-US/html/sect-Defensive_Coding-TLS-Client-NSS.html create mode 100644 defensive-coding/tmp/en-US/html/sect-Defensive_Coding-TLS-Client-OpenJDK.html create mode 100644 defensive-coding/tmp/en-US/html/sect-Defensive_Coding-TLS-Client-Python.html create mode 100644 defensive-coding/tmp/en-US/html/sect-Defensive_Coding-TLS-Client.html create mode 100644 defensive-coding/tmp/en-US/html/sect-Defensive_Coding-Tasks-Descriptors-Child_Processes.html create mode 100644 defensive-coding/tmp/en-US/html/sect-Defensive_Coding-Tasks-Descriptors-Limit.html create mode 100644 defensive-coding/tmp/en-US/html/sect-Defensive_Coding-Tasks-Descriptors.html create mode 100644 defensive-coding/tmp/en-US/html/sect-Defensive_Coding-Tasks-File_System-Features.html create mode 100644 defensive-coding/tmp/en-US/html/sect-Defensive_Coding-Tasks-File_System-Foreign.html create mode 100644 defensive-coding/tmp/en-US/html/sect-Defensive_Coding-Tasks-File_System-Free_Space.html create mode 100644 defensive-coding/tmp/en-US/html/sect-Defensive_Coding-Tasks-File_System-Limits.html create mode 100644 defensive-coding/tmp/en-US/html/sect-Defensive_Coding-Tasks-Library_Design-Callbacks.html create mode 100644 defensive-coding/tmp/en-US/html/sect-Defensive_Coding-Tasks-Processes-Daemons.html create mode 100644 defensive-coding/tmp/en-US/html/sect-Defensive_Coding-Tasks-Processes-Fork-Parallel.html create mode 100644 defensive-coding/tmp/en-US/html/sect-Defensive_Coding-Tasks-Processes.html create mode 100644 defensive-coding/tmp/en-US/html/sect-Defensive_Coding-Tasks-Serialization-XML-Entities.html create mode 100644 defensive-coding/tmp/en-US/html/sect-Defensive_Coding-Tasks-Serialization-XML-Expat.html create mode 100644 defensive-coding/tmp/en-US/html/sect-Defensive_Coding-Tasks-Serialization-XML-OpenJDK_Parse-SAX.html create mode 100644 defensive-coding/tmp/en-US/html/sect-Defensive_Coding-Tasks-Serialization-XML-OpenJDK_Parse.html create mode 100644 defensive-coding/tmp/en-US/html/sect-Defensive_Coding-Tasks-Serialization-XML-Validation.html create mode 100644 defensive-coding/tmp/en-US/html/sect-Defensive_Coding-Tasks-Serialization-XML-XInclude.html create mode 100644 defensive-coding/tmp/en-US/html/sect-Defensive_Coding-Tasks-Serialization-XML.html create mode 100644 defensive-coding/tmp/en-US/pdf/Defensive_Coding-1-Defensive_Coding-en-US.pdf create mode 100644 defensive-coding/tmp/en-US/pdf/file.eng.rdu.redhat.com create mode 100644 defensive-coding/tmp/en-US/pdf/file.rdu.redhat.com create mode 100644 defensive-coding/tmp/en-US/xml/Author_Group.xml create mode 100644 defensive-coding/tmp/en-US/xml/Book_Info.xml create mode 100644 defensive-coding/tmp/en-US/xml/C/Allocators.xml create mode 100644 defensive-coding/tmp/en-US/xml/C/C.xml create mode 100644 defensive-coding/tmp/en-US/xml/C/Language.xml create mode 100644 defensive-coding/tmp/en-US/xml/C/Libc.xml create mode 100644 defensive-coding/tmp/en-US/xml/C/schemas.xml create mode 100644 defensive-coding/tmp/en-US/xml/C/snippets/Arithmetic-add.xml create mode 100644 defensive-coding/tmp/en-US/xml/C/snippets/Arithmetic-mult.xml create mode 100644 defensive-coding/tmp/en-US/xml/C/snippets/Pointers-remaining.xml create mode 100644 defensive-coding/tmp/en-US/xml/C/snippets/String-Functions-format.xml create mode 100644 defensive-coding/tmp/en-US/xml/C/snippets/String-Functions-snprintf.xml create mode 100644 defensive-coding/tmp/en-US/xml/C/snippets/String-Functions-strncpy.xml create mode 100644 defensive-coding/tmp/en-US/xml/CXX/CXX.xml create mode 100644 defensive-coding/tmp/en-US/xml/CXX/Language.xml create mode 100644 defensive-coding/tmp/en-US/xml/CXX/Std.xml create mode 100644 defensive-coding/tmp/en-US/xml/CXX/schemas.xml create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/Conventions.xml create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/Feedback.xml create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/Legal_Notice.xml create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/css/common.css create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/css/default.css create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/css/lang.css create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/css/overrides.css create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/css/print.css create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/1.png create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/1.svg create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/10.png create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/10.svg create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/11.png create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/11.svg create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/12.png create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/12.svg create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/13.png create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/13.svg create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/14.png create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/14.svg create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/15.png create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/15.svg create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/16.png create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/16.svg create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/17.png create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/17.svg create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/18.png create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/18.svg create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/19.png create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/19.svg create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/2.png create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/2.svg create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/20.png create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/20.svg create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/21.png create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/21.svg create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/22.png create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/22.svg create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/23.png create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/23.svg create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/24.png create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/24.svg create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/25.png create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/25.svg create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/26.png create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/26.svg create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/27.png create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/27.svg create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/28.png create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/28.svg create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/29.png create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/29.svg create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/3.png create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/3.svg create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/30.png create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/30.svg create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/31.png create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/31.svg create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/32.png create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/32.svg create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/33.png create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/33.svg create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/34.png create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/34.svg create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/35.png create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/35.svg create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/36.png create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/36.svg create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/37.png create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/37.svg create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/38.png create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/38.svg create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/39.png create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/39.svg create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/4.png create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/4.svg create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/40.png create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/40.svg create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/5.png create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/5.svg create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/6.png create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/6.svg create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/7.png create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/7.svg create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/8.png create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/8.svg create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/9.png create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/9.svg create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/bkgrnd_greydots.png create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/bullet_arrowblue.png create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/documentation.png create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/dot.png create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/dot2.png create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/green.png create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/h1-bg.png create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/image_left.png create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/image_right.png create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/important.png create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/important.svg create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/logo.png create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/note.png create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/note.svg create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/red.png create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/redhat-logo.svg create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/rhlogo.png create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/shade.png create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/shine.png create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/stock-go-back.png create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/stock-go-forward.png create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/stock-go-up.png create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/stock-home.png create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/title_logo.png create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/title_logo.svg create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/warning.png create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/warning.svg create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/watermark-draft.png create mode 100644 defensive-coding/tmp/en-US/xml/Common_Content/images/yellow.png create mode 100644 defensive-coding/tmp/en-US/xml/Defensive_Coding.ent create mode 100644 defensive-coding/tmp/en-US/xml/Defensive_Coding.fo create mode 100644 defensive-coding/tmp/en-US/xml/Defensive_Coding.xml create mode 100644 defensive-coding/tmp/en-US/xml/Features/Authentication.xml create mode 100644 defensive-coding/tmp/en-US/xml/Features/TLS.xml create mode 100644 defensive-coding/tmp/en-US/xml/Features/schemas.xml create mode 100644 defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Client-GNUTLS-Connect.xml create mode 100644 defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Client-GNUTLS-Credentials.xml create mode 100644 defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Client-GNUTLS-Match.xml create mode 100644 defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Client-GNUTLS-Verify.xml create mode 100644 defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Client-NSS-Close.xml create mode 100644 defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Client-NSS-Connect.xml create mode 100644 defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Client-OpenJDK-Connect.xml create mode 100644 defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Client-OpenJDK-Context.xml create mode 100644 defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Client-OpenJDK-Context_For_Cert.xml create mode 100644 defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Client-OpenJDK-Hostname.xml create mode 100644 defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Client-OpenJDK-Import.xml create mode 100644 defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Client-OpenJDK-MyTrustManager.xml create mode 100644 defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Client-OpenJDK-Use.xml create mode 100644 defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Client-OpenSSL-CTX.xml create mode 100644 defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Client-OpenSSL-Connect.xml create mode 100644 defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Client-OpenSSL-Connection-Use.xml create mode 100644 defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Client-OpenSSL-Init.xml create mode 100644 defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Client-Python-Connect.xml create mode 100644 defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Client-Python-check_host_name.xml create mode 100644 defensive-coding/tmp/en-US/xml/Features/snippets/TLS-GNUTLS-Credentials-Close.xml create mode 100644 defensive-coding/tmp/en-US/xml/Features/snippets/TLS-GNUTLS-Disconnect.xml create mode 100644 defensive-coding/tmp/en-US/xml/Features/snippets/TLS-GNUTLS-Init.xml create mode 100644 defensive-coding/tmp/en-US/xml/Features/snippets/TLS-GNUTLS-Use.xml create mode 100644 defensive-coding/tmp/en-US/xml/Features/snippets/TLS-NSS-Close.xml create mode 100644 defensive-coding/tmp/en-US/xml/Features/snippets/TLS-NSS-Includes.xml create mode 100644 defensive-coding/tmp/en-US/xml/Features/snippets/TLS-NSS-Init.xml create mode 100644 defensive-coding/tmp/en-US/xml/Features/snippets/TLS-NSS-Use.xml create mode 100644 defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Nagle.xml create mode 100644 defensive-coding/tmp/en-US/xml/Features/snippets/TLS-OpenJDK-Parameters.xml create mode 100644 defensive-coding/tmp/en-US/xml/Features/snippets/TLS-OpenSSL-Connection-Close.xml create mode 100644 defensive-coding/tmp/en-US/xml/Features/snippets/TLS-OpenSSL-Context-Close.xml create mode 100644 defensive-coding/tmp/en-US/xml/Features/snippets/TLS-OpenSSL-Errors.xml create mode 100644 defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Python-Close.xml create mode 100644 defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Python-Use.xml create mode 100644 defensive-coding/tmp/en-US/xml/Python/Language.xml create mode 100644 defensive-coding/tmp/en-US/xml/Python/schemas.xml create mode 100644 defensive-coding/tmp/en-US/xml/Revision_History.xml create mode 100644 defensive-coding/tmp/en-US/xml/Tasks/Cryptography.xml create mode 100644 defensive-coding/tmp/en-US/xml/Tasks/Descriptors.xml create mode 100644 defensive-coding/tmp/en-US/xml/Tasks/File_System.xml create mode 100644 defensive-coding/tmp/en-US/xml/Tasks/Library_Design.xml create mode 100644 defensive-coding/tmp/en-US/xml/Tasks/Locking.xml create mode 100644 defensive-coding/tmp/en-US/xml/Tasks/Processes.xml create mode 100644 defensive-coding/tmp/en-US/xml/Tasks/Serialization.xml create mode 100644 defensive-coding/tmp/en-US/xml/Tasks/Temporary_Files.xml create mode 100644 defensive-coding/tmp/en-US/xml/Tasks/schemas.xml create mode 100644 defensive-coding/tmp/en-US/xml/Tasks/snippets/Serialization-XML-Expat-Create.xml create mode 100644 defensive-coding/tmp/en-US/xml/Tasks/snippets/Serialization-XML-Expat-EntityDeclHandler.xml create mode 100644 defensive-coding/tmp/en-US/xml/Tasks/snippets/Serialization-XML-OpenJDK-Errors.xml create mode 100644 defensive-coding/tmp/en-US/xml/Tasks/snippets/Serialization-XML-OpenJDK-Imports.xml create mode 100644 defensive-coding/tmp/en-US/xml/Tasks/snippets/Serialization-XML-OpenJDK-NoEntityResolver.xml create mode 100644 defensive-coding/tmp/en-US/xml/Tasks/snippets/Serialization-XML-OpenJDK-NoResourceResolver.xml create mode 100644 defensive-coding/tmp/en-US/xml/Tasks/snippets/Serialization-XML-OpenJDK_Parse-DOM.xml create mode 100644 defensive-coding/tmp/en-US/xml/Tasks/snippets/Serialization-XML-OpenJDK_Parse-XMLSchema_DOM.xml create mode 100644 defensive-coding/tmp/en-US/xml/Tasks/snippets/Serialization-XML-OpenJDK_Parse-XMLSchema_SAX.xml create mode 100644 defensive-coding/tmp/en-US/xml_tmp/Author_Group.xml create mode 100644 defensive-coding/tmp/en-US/xml_tmp/Book_Info.xml create mode 100644 defensive-coding/tmp/en-US/xml_tmp/C/Allocators.xml create mode 100644 defensive-coding/tmp/en-US/xml_tmp/C/C.xml create mode 100644 defensive-coding/tmp/en-US/xml_tmp/C/Language.xml create mode 100644 defensive-coding/tmp/en-US/xml_tmp/C/Libc.xml create mode 100644 defensive-coding/tmp/en-US/xml_tmp/C/schemas.xml create mode 100644 defensive-coding/tmp/en-US/xml_tmp/C/snippets/Arithmetic-add.xml create mode 100644 defensive-coding/tmp/en-US/xml_tmp/C/snippets/Arithmetic-mult.xml create mode 100644 defensive-coding/tmp/en-US/xml_tmp/C/snippets/Pointers-remaining.xml create mode 100644 defensive-coding/tmp/en-US/xml_tmp/C/snippets/String-Functions-format.xml create mode 100644 defensive-coding/tmp/en-US/xml_tmp/C/snippets/String-Functions-snprintf.xml create mode 100644 defensive-coding/tmp/en-US/xml_tmp/C/snippets/String-Functions-strncpy.xml create mode 100644 defensive-coding/tmp/en-US/xml_tmp/CXX/CXX.xml create mode 100644 defensive-coding/tmp/en-US/xml_tmp/CXX/Language.xml create mode 100644 defensive-coding/tmp/en-US/xml_tmp/CXX/Std.xml create mode 100644 defensive-coding/tmp/en-US/xml_tmp/CXX/schemas.xml create mode 100644 defensive-coding/tmp/en-US/xml_tmp/Defensive_Coding.ent create mode 100644 defensive-coding/tmp/en-US/xml_tmp/Defensive_Coding.xml create mode 100644 defensive-coding/tmp/en-US/xml_tmp/Features/Authentication.xml create mode 100644 defensive-coding/tmp/en-US/xml_tmp/Features/TLS.xml create mode 100644 defensive-coding/tmp/en-US/xml_tmp/Features/schemas.xml create mode 100644 defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Client-GNUTLS-Connect.xml create mode 100644 defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Client-GNUTLS-Credentials.xml create mode 100644 defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Client-GNUTLS-Match.xml create mode 100644 defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Client-GNUTLS-Verify.xml create mode 100644 defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Client-NSS-Close.xml create mode 100644 defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Client-NSS-Connect.xml create mode 100644 defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Client-OpenJDK-Connect.xml create mode 100644 defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Client-OpenJDK-Context.xml create mode 100644 defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Client-OpenJDK-Context_For_Cert.xml create mode 100644 defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Client-OpenJDK-Hostname.xml create mode 100644 defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Client-OpenJDK-Import.xml create mode 100644 defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Client-OpenJDK-MyTrustManager.xml create mode 100644 defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Client-OpenJDK-Use.xml create mode 100644 defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Client-OpenSSL-CTX.xml create mode 100644 defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Client-OpenSSL-Connect.xml create mode 100644 defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Client-OpenSSL-Connection-Use.xml create mode 100644 defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Client-OpenSSL-Init.xml create mode 100644 defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Client-Python-Connect.xml create mode 100644 defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Client-Python-check_host_name.xml create mode 100644 defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-GNUTLS-Credentials-Close.xml create mode 100644 defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-GNUTLS-Disconnect.xml create mode 100644 defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-GNUTLS-Init.xml create mode 100644 defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-GNUTLS-Use.xml create mode 100644 defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-NSS-Close.xml create mode 100644 defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-NSS-Includes.xml create mode 100644 defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-NSS-Init.xml create mode 100644 defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-NSS-Use.xml create mode 100644 defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Nagle.xml create mode 100644 defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-OpenJDK-Parameters.xml create mode 100644 defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-OpenSSL-Connection-Close.xml create mode 100644 defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-OpenSSL-Context-Close.xml create mode 100644 defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-OpenSSL-Errors.xml create mode 100644 defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Python-Close.xml create mode 100644 defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Python-Use.xml create mode 100644 defensive-coding/tmp/en-US/xml_tmp/Python/Language.xml create mode 100644 defensive-coding/tmp/en-US/xml_tmp/Python/schemas.xml create mode 100644 defensive-coding/tmp/en-US/xml_tmp/Revision_History.xml create mode 100644 defensive-coding/tmp/en-US/xml_tmp/Tasks/Cryptography.xml create mode 100644 defensive-coding/tmp/en-US/xml_tmp/Tasks/Descriptors.xml create mode 100644 defensive-coding/tmp/en-US/xml_tmp/Tasks/File_System.xml create mode 100644 defensive-coding/tmp/en-US/xml_tmp/Tasks/Library_Design.xml create mode 100644 defensive-coding/tmp/en-US/xml_tmp/Tasks/Locking.xml create mode 100644 defensive-coding/tmp/en-US/xml_tmp/Tasks/Processes.xml create mode 100644 defensive-coding/tmp/en-US/xml_tmp/Tasks/Serialization.xml create mode 100644 defensive-coding/tmp/en-US/xml_tmp/Tasks/Temporary_Files.xml create mode 100644 defensive-coding/tmp/en-US/xml_tmp/Tasks/schemas.xml create mode 100644 defensive-coding/tmp/en-US/xml_tmp/Tasks/snippets/Serialization-XML-Expat-Create.xml create mode 100644 defensive-coding/tmp/en-US/xml_tmp/Tasks/snippets/Serialization-XML-Expat-EntityDeclHandler.xml create mode 100644 defensive-coding/tmp/en-US/xml_tmp/Tasks/snippets/Serialization-XML-OpenJDK-Errors.xml create mode 100644 defensive-coding/tmp/en-US/xml_tmp/Tasks/snippets/Serialization-XML-OpenJDK-Imports.xml create mode 100644 defensive-coding/tmp/en-US/xml_tmp/Tasks/snippets/Serialization-XML-OpenJDK-NoEntityResolver.xml create mode 100644 defensive-coding/tmp/en-US/xml_tmp/Tasks/snippets/Serialization-XML-OpenJDK-NoResourceResolver.xml create mode 100644 defensive-coding/tmp/en-US/xml_tmp/Tasks/snippets/Serialization-XML-OpenJDK_Parse-DOM.xml create mode 100644 defensive-coding/tmp/en-US/xml_tmp/Tasks/snippets/Serialization-XML-OpenJDK_Parse-XMLSchema_DOM.xml create mode 100644 defensive-coding/tmp/en-US/xml_tmp/Tasks/snippets/Serialization-XML-OpenJDK_Parse-XMLSchema_SAX.xml diff --git a/defensive-coding/Makefile b/defensive-coding/Makefile new file mode 100644 index 0000000..63f819c --- /dev/null +++ b/defensive-coding/Makefile @@ -0,0 +1,33 @@ +all: build + +include src/src.mk + +.PHONY: all build build-manual build-snippets build-manual-html build-manual-epub force clean upload + +build: build-src build-manual + +build-snippets: + for p in en-US/* ; do test -d $$p && mkdir -p $$p/snippets; done + python scripts/split-snippets.py . src/*.c src/*.java src/*.py + +build-manual: build-snippets + publican build --format=html,epub,pdf --lang=en-US + +build-manual-html: build-snippets + publican build --format=html --lang=en-US + +build-manual-epub: build-snippets + publican build --format=epub --lang=en-US + +build-manual-pdf: build-snippets + publican build --format=pdf --lang=en-US + +clean: clean-src + -rm -rf tmp + -rm -rf en-US/*/snippets + +upload: clean build + rsync -avP --delete tmp/en-US/html/. file.rdu.redhat.com:public_html/defensive-coding/. + rsync -avP tmp/en-US/Defensive_Coding*.epub file.rdu.redhat.com:public_html/defensive-coding.epub + rsync -avP tmp/en-US/pdf/Defensive_Coding*.pdf file.rdu.redhat.com:public_html/defensive-coding.pdf + diff --git a/defensive-coding/README b/defensive-coding/README new file mode 100644 index 0000000..934d2a2 --- /dev/null +++ b/defensive-coding/README @@ -0,0 +1,32 @@ +TODO items +---------- + +Suggested items for inclusion are listed here: + +https://engineering.redhat.com/trac/product-security/wiki/DefensiveCodingTODO + +Building HTML documentation +--------------------------- + +Just type "make". + +When you type "make", the code examples in src/ are compiled (mainly +to check for obvious syntax errors, but also for manual testing). If +you lack the necessary libraries, you can type "make build-manual" +instead, which will skip this step. The code examples are still +included in the manual. + +Dependencies +------------ + +Building the manual needs the "publican" package and the +"publican-redhat-engservices" package available here: + +http://download.lab.bos.redhat.com/brewroot/packages/publican-redhat-engservices/ + +Version 0.4 of the publican-redhat-engservices package needs publican +3.0. This version of the package: + +http://download.lab.bos.redhat.com/brewroot/packages/publican-redhat-engservices/0.3/2.el6eng/noarch/publican-redhat-engservices-0.3-2.el6eng.noarch.rpm + +is known to work with publican 2.8 available in Fedora 17. diff --git a/defensive-coding/docbook-schema/.svn/all-wcprops b/defensive-coding/docbook-schema/.svn/all-wcprops new file mode 100644 index 0000000..bcae1ee --- /dev/null +++ b/defensive-coding/docbook-schema/.svn/all-wcprops @@ -0,0 +1,47 @@ +K 25 +svn:wc:ra_dav:version-url +V 74 +/repos/product-security/!svn/ver/291/defensive-coding/trunk/docbook-schema +END +htmltblx.rnc +K 25 +svn:wc:ra_dav:version-url +V 87 +/repos/product-security/!svn/ver/291/defensive-coding/trunk/docbook-schema/htmltblx.rnc +END +docbook.rnc +K 25 +svn:wc:ra_dav:version-url +V 86 +/repos/product-security/!svn/ver/291/defensive-coding/trunk/docbook-schema/docbook.rnc +END +dbhierx.rnc +K 25 +svn:wc:ra_dav:version-url +V 86 +/repos/product-security/!svn/ver/291/defensive-coding/trunk/docbook-schema/dbhierx.rnc +END +dbpoolx.rnc +K 25 +svn:wc:ra_dav:version-url +V 86 +/repos/product-security/!svn/ver/291/defensive-coding/trunk/docbook-schema/dbpoolx.rnc +END +README +K 25 +svn:wc:ra_dav:version-url +V 81 +/repos/product-security/!svn/ver/291/defensive-coding/trunk/docbook-schema/README +END +calstblx.rnc +K 25 +svn:wc:ra_dav:version-url +V 87 +/repos/product-security/!svn/ver/291/defensive-coding/trunk/docbook-schema/calstblx.rnc +END +dbnotnx.rnc +K 25 +svn:wc:ra_dav:version-url +V 86 +/repos/product-security/!svn/ver/291/defensive-coding/trunk/docbook-schema/dbnotnx.rnc +END diff --git a/defensive-coding/docbook-schema/.svn/entries b/defensive-coding/docbook-schema/.svn/entries new file mode 100644 index 0000000..4c68c74 --- /dev/null +++ b/defensive-coding/docbook-schema/.svn/entries @@ -0,0 +1,266 @@ +10 + +dir +305 +https://svn.devel.redhat.com/repos/product-security/defensive-coding/trunk/docbook-schema +https://svn.devel.redhat.com/repos/product-security + + + +2012-12-14T10:14:43.664315Z +291 +fweimer@REDHAT.COM + + + + + + + + + + + + + + +9bd5cf0f-f2b3-0410-b1a9-d5c590f50bf1 + +htmltblx.rnc +file + + + + +2013-01-10T17:17:56.371857Z +21e841469e23f4a9b92aeb9a459d8b53 +2012-12-14T10:14:43.664315Z +291 +fweimer@REDHAT.COM + + + + + + + + + + + + + + + + + + + + + +7626 + +docbook.rnc +file + + + + +2013-01-10T17:17:56.371857Z +d61460c3a0f4539fe94f63a6caf75ca0 +2012-12-14T10:14:43.664315Z +291 +fweimer@REDHAT.COM + + + + + + + + + + + + + + + + + + + + + +9150 + +dbhierx.rnc +file + + + + +2013-01-10T17:17:56.372857Z +31ef633724ef8f8f23159fefdd55a226 +2012-12-14T10:14:43.664315Z +291 +fweimer@REDHAT.COM + + + + + + + + + + + + + + + + + + + + + +43061 + +dbpoolx.rnc +file + + + + +2013-01-10T17:17:56.372857Z +ac617851f210fca2d4e1ef9340383bae +2012-12-14T10:14:43.664315Z +291 +fweimer@REDHAT.COM + + + + + + + + + + + + + + + + + + + + + +167400 + +README +file + + + + +2013-01-10T17:17:56.372857Z +6aa0b595c5fce9b9bb2d35cceac7411f +2012-12-14T10:14:43.664315Z +291 +fweimer@REDHAT.COM + + + + + + + + + + + + + + + + + + + + + +154 + +calstblx.rnc +file + + + + +2013-01-10T17:17:56.372857Z +3477bdcf199a10c15051d27b2b6e2d89 +2012-12-14T10:14:43.664315Z +291 +fweimer@REDHAT.COM + + + + + + + + + + + + + + + + + + + + + +6329 + +dbnotnx.rnc +file + + + + +2013-01-10T17:17:56.372857Z +8bf718c756c864dcb6c90fc81f537c50 +2012-12-14T10:14:43.664315Z +291 +fweimer@REDHAT.COM + + + + + + + + + + + + + + + + + + + + + +2588 + diff --git a/defensive-coding/docbook-schema/.svn/text-base/README.svn-base b/defensive-coding/docbook-schema/.svn/text-base/README.svn-base new file mode 100644 index 0000000..c636682 --- /dev/null +++ b/defensive-coding/docbook-schema/.svn/text-base/README.svn-base @@ -0,0 +1,3 @@ +This directory contains Relax NG Compact schema files, for use with +Emacs. These files were download from http://www.docbook.org/rng/4.5/ +on 2012-07-16. diff --git a/defensive-coding/docbook-schema/.svn/text-base/calstblx.rnc.svn-base b/defensive-coding/docbook-schema/.svn/text-base/calstblx.rnc.svn-base new file mode 100644 index 0000000..b6a2483 --- /dev/null +++ b/defensive-coding/docbook-schema/.svn/text-base/calstblx.rnc.svn-base @@ -0,0 +1,164 @@ +# ...................................................................... + +# DocBook CALS Table Model V4.5 ........................................ + +# File calstblx.mod .................................................... + +# Copyright 1992-2002 HaL Computer Systems, Inc., +# O'Reilly & Associates, Inc., ArborText, Inc., Fujitsu Software +# Corporation, Norman Walsh, Sun Microsystems, Inc., and the +# Organization for the Advancement of Structured Information +# Standards (OASIS). +# +# This DTD is based on the CALS Table Model +# PUBLIC "-//USA-DOD//DTD Table Model 951010//EN" +# +# $Id: calstblx.dtd 6340 2006-10-03 13:23:24Z nwalsh $ +# +# Permission to use, copy, modify and distribute the DocBook DTD +# and its accompanying documentation for any purpose and without fee +# is hereby granted in perpetuity, provided that the above copyright +# notice and this paragraph appear in all copies. The copyright +# holders make no representation about the suitability of the DTD for +# any purpose. It is provided "as is" without expressed or implied +# warranty. +# +# If you modify the DocBook DTD in any way, except for declaring and +# referencing additional sets of general entities and declaring +# additional notations, label your DTD as a variant of DocBook. See +# the maintenance documentation for more information. +# +# Please direct all questions, bug reports, or suggestions for +# changes to the docbook@lists.oasis-open.org mailing list. For more +# information, see http://www.oasis-open.org/docbook/. + +# ...................................................................... + +# This module contains the definitions for the CALS Table Model +# converted to XML. It has been modified slightly for use in the +# combined HTML/CALS models supported by DocBook V4.5. + +# These definitions are not directly related to the table model, but are +# used in the default CALS table model and are usually defined elsewhere +# (and prior to the inclusion of this table module) in a CALS DTD. + +# no if zero(s), +# yes if any other digits value + +yesorno = string +titles = title? +# default for use in entry content + +# The parameter entities as defined below provide the CALS table model +# as published (as part of the Example DTD) in MIL-HDBK-28001. +# +# These following declarations provide the CALS-compliant default definitions +# for these entities. However, these entities can and should be redefined +# (by giving the appropriate parameter entity declaration(s) prior to the +# reference to this Table Model declaration set entity) to fit the needs +# of the current application. +tbl.table-titles.mdl = titles +tbl.table-main.mdl = tgroup+ | graphic+ +tbl.tgroup.mdl = colspec*, spanspec*, thead?, tfoot?, tbody +tbl.tgroup.att = attribute tgroupstyle { text }? +tbl.row.mdl = (entry | entrytbl)+ +tbl.entrytbl.mdl = colspec*, spanspec*, thead?, tbody +# ===== Element and attribute declarations follow. ===== + +# doc:A formal table in a document. +table = element table { table.attlist, tbl.table.mdl } +table.attlist &= + attribute frame { tbl.frame.attval }?, + attribute colsep { yesorno }?, + attribute rowsep { yesorno }?, + tbl.table.att, + bodyatt, + secur +# doc:A wrapper for the main content of a table, or part of a table. +tgroup = element tgroup { tgroup.attlist, tbl.tgroup.mdl } +tgroup.attlist &= + attribute cols { text }, + tbl.tgroup.att, + attribute colsep { yesorno }?, + attribute rowsep { yesorno }?, + attribute align { "left" | "right" | "center" | "justify" | "char" }?, + attribute char { text }?, + attribute charoff { text }?, + secur +# doc:Specifications for a column in a table. +colspec = element colspec { colspec.attlist, empty } +colspec.attlist &= + attribute colnum { text }?, + attribute colname { text }?, + attribute colwidth { text }?, + attribute colsep { yesorno }?, + attribute rowsep { yesorno }?, + attribute align { "left" | "right" | "center" | "justify" | "char" }?, + attribute char { text }?, + attribute charoff { text }? +# doc:Formatting information for a spanned column in a table. +spanspec = element spanspec { spanspec.attlist, empty } +spanspec.attlist &= + attribute namest { text }, + attribute nameend { text }, + attribute spanname { text }, + attribute colsep { yesorno }?, + attribute rowsep { yesorno }?, + attribute align { "left" | "right" | "center" | "justify" | "char" }?, + attribute char { text }?, + attribute charoff { text }? +# doc:A table header consisting of one or more rows. +thead = element thead { thead.attlist, tbl.hdft.mdl } +thead.attlist &= + attribute valign { "top" | "middle" | "bottom" }?, + secur +# doc:A table footer consisting of one or more rows. +tfoot = element tfoot { tfoot.attlist, tbl.hdft.mdl } +tfoot.attlist &= + attribute valign { "top" | "middle" | "bottom" }?, + secur +# doc:A wrapper for the rows of a table or informal table. +tbody = element tbody { tbody.attlist, tbl.tbody.mdl } +tbody.attlist &= + attribute valign { "top" | "middle" | "bottom" }?, + secur +# doc:A row in a table. +row = element row { row.attlist, tbl.row.mdl } +row.attlist &= + attribute rowsep { yesorno }?, + attribute valign { "top" | "middle" | "bottom" }?, + secur +# doc:A subtable appearing in place of an Entry in a table. +entrytbl = element entrytbl { entrytbl.attlist, tbl.entrytbl.mdl } +entrytbl.attlist &= + attribute cols { text }, + tbl.tgroup.att, + attribute colname { text }?, + attribute spanname { text }?, + attribute namest { text }?, + attribute nameend { text }?, + attribute colsep { yesorno }?, + attribute rowsep { yesorno }?, + attribute align { "left" | "right" | "center" | "justify" | "char" }?, + attribute char { text }?, + attribute charoff { text }?, + secur +# doc:A cell in a table. +entry = element entry { entry.attlist, tbl.entry.mdl* } +entry.attlist &= + attribute colname { text }?, + attribute namest { text }?, + attribute nameend { text }?, + attribute spanname { text }?, + attribute morerows { text }?, + attribute colsep { yesorno }?, + attribute rowsep { yesorno }?, + attribute align { "left" | "right" | "center" | "justify" | "char" }?, + attribute char { text }?, + attribute charoff { text }?, + attribute rotate { yesorno }?, + attribute valign { "top" | "middle" | "bottom" }?, + secur +# End of DocBook CALS Table Model V4.5 ................................. + +# ...................................................................... diff --git a/defensive-coding/docbook-schema/.svn/text-base/dbhierx.rnc.svn-base b/defensive-coding/docbook-schema/.svn/text-base/dbhierx.rnc.svn-base new file mode 100644 index 0000000..56015a3 --- /dev/null +++ b/defensive-coding/docbook-schema/.svn/text-base/dbhierx.rnc.svn-base @@ -0,0 +1,1549 @@ +# ...................................................................... + +# DocBook document hierarchy module V4.5 ............................... + +# File dbhierx.mod ..................................................... + +# Copyright 1992-2004 HaL Computer Systems, Inc., +# O'Reilly & Associates, Inc., ArborText, Inc., Fujitsu Software +# Corporation, Norman Walsh, Sun Microsystems, Inc., and the +# Organization for the Advancement of Structured Information +# Standards (OASIS). +# +# $Id: dbhierx.mod 6340 2006-10-03 13:23:24Z nwalsh $ +# +# Permission to use, copy, modify and distribute the DocBook DTD +# and its accompanying documentation for any purpose and without fee +# is hereby granted in perpetuity, provided that the above copyright +# notice and this paragraph appear in all copies. The copyright +# holders make no representation about the suitability of the DTD for +# any purpose. It is provided "as is" without expressed or implied +# warranty. +# +# If you modify the DocBook DTD in any way, except for declaring and +# referencing additional sets of general entities and declaring +# additional notations, label your DTD as a variant of DocBook. See +# the maintenance documentation for more information. +# +# Please direct all questions, bug reports, or suggestions for +# changes to the docbook@lists.oasis-open.org mailing list. For more +# information, see http://www.oasis-open.org/docbook/. + +# ...................................................................... + +# This module contains the definitions for the overall document +# hierarchies of DocBook documents. It covers computer documentation +# manuals and manual fragments, as well as reference entries (such as +# man pages) and technical journals or anthologies containing +# articles. +# +# This module depends on the DocBook information pool module. All +# elements and entities referenced but not defined here are assumed +# to be defined in the information pool module. +# +# In DTD driver files referring to this module, please use an entity +# declaration that uses the public identifier shown below: +# +# +# %dbhier; +# +# See the documentation for detailed information on the parameter +# entity and module scheme used in DocBook, customizing DocBook and +# planning for interchange, and changes made since the last release +# of DocBook. + +# ...................................................................... + +# Entities for module inclusions ....................................... + +# ...................................................................... + +# Entities for element classes ......................................... + +local.appendix.class = notAllowed +appendix.class = appendix | local.appendix.class +local.article.class = notAllowed +article.class = article | local.article.class +local.book.class = notAllowed +book.class = book | local.book.class +local.chapter.class = notAllowed +chapter.class = chapter | local.chapter.class +local.index.class = notAllowed +index.class = index | setindex | local.index.class +local.refentry.class = notAllowed +refentry.class = refentry | local.refentry.class +local.section.class = notAllowed +section.class = section | local.section.class +local.nav.class = notAllowed +nav.class = + toc | lot | index | glossary | bibliography | local.nav.class +# Redeclaration placeholder ............................................ + +# For redeclaring entities that are declared after this point while +# retaining their references to the entities that are declared before +# this point + +# ...................................................................... + +# Entities for element mixtures ........................................ +local.divcomponent.mix = notAllowed +divcomponent.mix = + list.class + | admon.class + | linespecific.class + | synop.class + | para.class + | informal.class + | formal.class + | compound.class + | genobj.class + | descobj.class + | ndxterm.class + | beginpage + | forms.hook + | local.divcomponent.mix +local.refcomponent.mix = notAllowed +refcomponent.mix = + list.class + | admon.class + | linespecific.class + | synop.class + | para.class + | informal.class + | formal.class + | compound.class + | genobj.class + | descobj.class + | ndxterm.class + | beginpage + | forms.hook + | local.refcomponent.mix +local.indexdivcomponent.mix = notAllowed +indexdivcomponent.mix = + itemizedlist + | orderedlist + | variablelist + | simplelist + | linespecific.class + | synop.class + | para.class + | informal.class + | anchor + | remark + | link.char.class + | beginpage + | local.indexdivcomponent.mix +local.refname.char.mix = notAllowed +refname.char.mix = text | tech.char.class | local.refname.char.mix +local.partcontent.mix = notAllowed +partcontent.mix = + appendix.class + | chapter.class + | nav.class + | article.class + | preface + | refentry.class + | reference + | local.partcontent.mix +local.refinline.char.mix = notAllowed +refinline.char.mix = + text + | xref.char.class + | gen.char.class + | link.char.class + | tech.char.class + | base.char.class + | docinfo.char.class + | other.char.class + | ndxterm.class + | beginpage + | local.refinline.char.mix +local.refclass.char.mix = notAllowed +refclass.char.mix = text | application | local.refclass.char.mix +# Redeclaration placeholder 2 .......................................... + +# For redeclaring entities that are declared after this point while +# retaining their references to the entities that are declared before +# this point + +# ...................................................................... + +# Entities for content models .......................................... +div.title.content = title, subtitle?, titleabbrev? +bookcomponent.title.content = title, subtitle?, titleabbrev? +sect.title.content = title, subtitle?, titleabbrev? +refsect.title.content = title, subtitle?, titleabbrev? +bookcomponent.content = + (divcomponent.mix+, + (sect1* | refentry.class* | simplesect* | section.class*)) + | (sect1+ | refentry.class+ | simplesect+ | section.class+) +# ...................................................................... + +# Set and SetInfo ...................................................... +local.set.attrib = empty +set.role.attrib = role.attrib +# doc:A collection of books. +set = + element set { + set.attlist, + div.title.content?, + setinfo?, + toc?, + (set | book.class)+, + setindex? + } +# end of set.element + +# FPI: SGML formal public identifier +set.attlist &= + attribute fpi { text }?, + status.attrib, + common.attrib, + set.role.attrib, + local.set.attrib +# end of set.attlist + +# end of set.module +local.setinfo.attrib = empty +setinfo.role.attrib = role.attrib +# doc:Meta-information for a Set. +setinfo = element setinfo { setinfo.attlist, info.class+ } +# end of setinfo.element + +# Contents: IDs of the ToC, Books, and SetIndex that comprise +# the set, in the order of their appearance +setinfo.attlist &= + attribute contents { xsd:IDREFS }?, + common.attrib, + setinfo.role.attrib, + local.setinfo.attrib +# end of setinfo.attlist + +# end of setinfo.module + +# end of set.content.module + +# ...................................................................... + +# Book and BookInfo .................................................... +local.book.attrib = empty +book.role.attrib = role.attrib +# doc:A book. +book = + element book { + book.attlist, + div.title.content?, + bookinfo?, + (dedication + | toc + | lot + | glossary + | bibliography + | preface + | chapter.class + | reference + | part + | article.class + | appendix.class + | index.class + | colophon)* + } +# end of book.element + +# FPI: SGML formal public identifier +book.attlist &= + attribute fpi { text }?, + label.attrib, + status.attrib, + common.attrib, + book.role.attrib, + local.book.attrib +# end of book.attlist + +# end of book.module +local.bookinfo.attrib = empty +bookinfo.role.attrib = role.attrib +# doc:Meta-information for a Book. +bookinfo = element bookinfo { bookinfo.attlist, info.class+ } +# end of bookinfo.element + +# Contents: IDs of the ToC, LoTs, Prefaces, Parts, Chapters, +# Appendixes, References, GLossary, Bibliography, and indexes +# comprising the Book, in the order of their appearance +bookinfo.attlist &= + attribute contents { xsd:IDREFS }?, + common.attrib, + bookinfo.role.attrib, + local.bookinfo.attrib +# end of bookinfo.attlist + +# end of bookinfo.module + +# end of book.content.module + +# ...................................................................... + +# Dedication, ToC, and LoT ............................................. +local.dedication.attrib = empty +dedication.role.attrib = role.attrib +# doc:A wrapper for the dedication section of a book. +dedication = + element dedication { + dedication.attlist, sect.title.content?, legalnotice.mix+ + } +# end of dedication.element +dedication.attlist &= + status.attrib, + common.attrib, + dedication.role.attrib, + local.dedication.attrib +# end of dedication.attlist + +# end of dedication.module +local.colophon.attrib = empty +colophon.role.attrib = role.attrib +# doc:Text at the back of a book describing facts about its production. +colophon = + element colophon { + colophon.attlist, sect.title.content?, textobject.mix+ + } +# end of colophon.element +colophon.attlist &= + status.attrib, + common.attrib, + colophon.role.attrib, + local.colophon.attrib +# end of colophon.attlist + +# end of colophon.module +local.toc.attrib = empty +toc.role.attrib = role.attrib +# doc:A table of contents. +toc = + element toc { + toc.attlist, + beginpage?, + bookcomponent.title.content?, + tocfront*, + (tocpart | tocchap)*, + tocback* + } +# end of toc.element +toc.attlist &= + pagenum.attrib, common.attrib, toc.role.attrib, local.toc.attrib +# end of toc.attlist + +# end of toc.module +local.tocfront.attrib = empty +tocfront.role.attrib = role.attrib +# doc:An entry in a table of contents for a front matter component. +tocfront = element tocfront { tocfront.attlist, para.char.mix* } +# end of tocfront.element + +# to element that this entry represents +tocfront.attlist &= + label.attrib, + linkend.attrib, + pagenum.attrib, + common.attrib, + tocfront.role.attrib, + local.tocfront.attrib +# end of tocfront.attlist + +# end of tocfront.module +local.tocentry.attrib = empty +tocentry.role.attrib = role.attrib +# doc:A component title in a table of contents. +tocentry = element tocentry { tocentry.attlist, para.char.mix* } +# end of tocentry.element + +# to element that this entry represents +tocentry.attlist &= + linkend.attrib, + pagenum.attrib, + common.attrib, + tocentry.role.attrib, + local.tocentry.attrib +# end of tocentry.attlist + +# end of tocentry.module +local.tocpart.attrib = empty +tocpart.role.attrib = role.attrib +# doc:An entry in a table of contents for a part of a book. +tocpart = element tocpart { tocpart.attlist, tocentry+, tocchap* } +# end of tocpart.element +tocpart.attlist &= + common.attrib, tocpart.role.attrib, local.tocpart.attrib +# end of tocpart.attlist + +# end of tocpart.module +local.tocchap.attrib = empty +tocchap.role.attrib = role.attrib +# doc:An entry in a table of contents for a component in the body of a document. +tocchap = element tocchap { tocchap.attlist, tocentry+, toclevel1* } +# end of tocchap.element +tocchap.attlist &= + label.attrib, common.attrib, tocchap.role.attrib, local.tocchap.attrib +# end of tocchap.attlist + +# end of tocchap.module +local.toclevel1.attrib = empty +toclevel1.role.attrib = role.attrib +# doc:A top-level entry within a table of contents entry for a chapter-like component. +toclevel1 = + element toclevel1 { toclevel1.attlist, tocentry+, toclevel2* } +# end of toclevel1.element +toclevel1.attlist &= + common.attrib, toclevel1.role.attrib, local.toclevel1.attrib +# end of toclevel1.attlist + +# end of toclevel1.module +local.toclevel2.attrib = empty +toclevel2.role.attrib = role.attrib +# doc:A second-level entry within a table of contents entry for a chapter-like component. +toclevel2 = + element toclevel2 { toclevel2.attlist, tocentry+, toclevel3* } +# end of toclevel2.element +toclevel2.attlist &= + common.attrib, toclevel2.role.attrib, local.toclevel2.attrib +# end of toclevel2.attlist + +# end of toclevel2.module +local.toclevel3.attrib = empty +toclevel3.role.attrib = role.attrib +# doc:A third-level entry within a table of contents entry for a chapter-like component. +toclevel3 = + element toclevel3 { toclevel3.attlist, tocentry+, toclevel4* } +# end of toclevel3.element +toclevel3.attlist &= + common.attrib, toclevel3.role.attrib, local.toclevel3.attrib +# end of toclevel3.attlist + +# end of toclevel3.module +local.toclevel4.attrib = empty +toclevel4.role.attrib = role.attrib +# doc:A fourth-level entry within a table of contents entry for a chapter-like component. +toclevel4 = + element toclevel4 { toclevel4.attlist, tocentry+, toclevel5* } +# end of toclevel4.element +toclevel4.attlist &= + common.attrib, toclevel4.role.attrib, local.toclevel4.attrib +# end of toclevel4.attlist + +# end of toclevel4.module +local.toclevel5.attrib = empty +toclevel5.role.attrib = role.attrib +# doc:A fifth-level entry within a table of contents entry for a chapter-like component. +toclevel5 = element toclevel5 { toclevel5.attlist, tocentry+ } +# end of toclevel5.element +toclevel5.attlist &= + common.attrib, toclevel5.role.attrib, local.toclevel5.attrib +# end of toclevel5.attlist + +# end of toclevel5.module +local.tocback.attrib = empty +tocback.role.attrib = role.attrib +# doc:An entry in a table of contents for a back matter component. +tocback = element tocback { tocback.attlist, para.char.mix* } +# end of tocback.element + +# to element that this entry represents +tocback.attlist &= + label.attrib, + linkend.attrib, + pagenum.attrib, + common.attrib, + tocback.role.attrib, + local.tocback.attrib +# end of tocback.attlist + +# end of tocback.module + +# end of toc.content.module +local.lot.attrib = empty +lot.role.attrib = role.attrib +# doc:A list of the titles of formal objects (as tables or figures) in a document. +lot = + element lot { + lot.attlist, beginpage?, bookcomponent.title.content?, lotentry* + } +# end of lot.element +lot.attlist &= + label.attrib, common.attrib, lot.role.attrib, local.lot.attrib +# end of lot.attlist + +# end of lot.module +local.lotentry.attrib = empty +lotentry.role.attrib = role.attrib +# doc:An entry in a list of titles. +lotentry = element lotentry { lotentry.attlist, para.char.mix* } +# end of lotentry.element + +# SrcCredit: Information about the source of the entry, +# as for a list of illustrations + +# linkend: to element that this entry represents +lotentry.attlist &= + linkend.attrib, + pagenum.attrib, + attribute srccredit { text }?, + common.attrib, + lotentry.role.attrib, + local.lotentry.attrib +# end of lotentry.attlist + +# end of lotentry.module + +# end of lot.content.module + +# ...................................................................... + +# Appendix, Chapter, Part, Preface, Reference, PartIntro ............... +local.appendix.attrib = empty +appendix.role.attrib = role.attrib +# doc:An appendix in a Book or Article. +appendix = + element appendix { + appendix.attlist, + beginpage?, + appendixinfo?, + bookcomponent.title.content, + nav.class*, + tocchap?, + bookcomponent.content, + nav.class* + } +# end of appendix.element +appendix.attlist &= + label.attrib, + status.attrib, + common.attrib, + appendix.role.attrib, + local.appendix.attrib +# end of appendix.attlist + +# end of appendix.module +local.chapter.attrib = empty +chapter.role.attrib = role.attrib +# doc:A chapter, as of a book. +chapter = + element chapter { + chapter.attlist, + beginpage?, + chapterinfo?, + bookcomponent.title.content, + nav.class*, + tocchap?, + bookcomponent.content, + nav.class* + } +# end of chapter.element +chapter.attlist &= + label.attrib, + status.attrib, + common.attrib, + chapter.role.attrib, + local.chapter.attrib +# end of chapter.attlist + +# end of chapter.module + +# Note that Part was to have its content model reduced in V4.5. This +# change will not be made after all. +local.part.attrib = empty +part.role.attrib = role.attrib +# doc:A division in a book. +part = + element part { + part.attlist, + beginpage?, + partinfo?, + bookcomponent.title.content, + partintro?, + partcontent.mix+ + } +# end of part.element +part.attlist &= + label.attrib, + status.attrib, + common.attrib, + part.role.attrib, + local.part.attrib +# end of part.attlist + +# ELEMENT PartIntro (defined below) + +# end of part.module +local.preface.attrib = empty +preface.role.attrib = role.attrib +# doc:Introductory matter preceding the first chapter of a book. +preface = + element preface { + preface.attlist, + beginpage?, + prefaceinfo?, + bookcomponent.title.content, + nav.class*, + tocchap?, + bookcomponent.content, + nav.class* + } +# end of preface.element +preface.attlist &= + status.attrib, + common.attrib, + preface.role.attrib, + local.preface.attrib +# end of preface.attlist + +# end of preface.module +local.reference.attrib = empty +reference.role.attrib = role.attrib +# doc:A collection of reference entries. +reference = + element reference { + reference.attlist, + beginpage?, + referenceinfo?, + bookcomponent.title.content, + partintro?, + refentry.class+ + } +# end of reference.element +reference.attlist &= + label.attrib, + status.attrib, + common.attrib, + reference.role.attrib, + local.reference.attrib +# end of reference.attlist + +# ELEMENT PartIntro (defined below) + +# end of reference.module +local.partintro.attrib = empty +partintro.role.attrib = role.attrib +# doc:An introduction to the contents of a part. +partintro = + element partintro { + partintro.attlist, div.title.content?, bookcomponent.content + } +# end of partintro.element +partintro.attlist &= + label.attrib, + common.attrib, + partintro.role.attrib, + local.partintro.attrib +# end of partintro.attlist + +# end of partintro.module + +# ...................................................................... + +# Other Info elements .................................................. +local.appendixinfo.attrib = empty +appendixinfo.role.attrib = role.attrib +# doc:Meta-information for an Appendix. +appendixinfo = + element appendixinfo { appendixinfo.attlist, info.class+ } +# end of appendixinfo.element +appendixinfo.attlist &= + common.attrib, appendixinfo.role.attrib, local.appendixinfo.attrib +# end of appendixinfo.attlist + +# end of appendixinfo.module +local.bibliographyinfo.attrib = empty +bibliographyinfo.role.attrib = role.attrib +# doc:Meta-information for a Bibliography. +bibliographyinfo = + element bibliographyinfo { bibliographyinfo.attlist, info.class+ } +# end of bibliographyinfo.element +bibliographyinfo.attlist &= + common.attrib, + bibliographyinfo.role.attrib, + local.bibliographyinfo.attrib +# end of bibliographyinfo.attlist + +# end of bibliographyinfo.module +local.chapterinfo.attrib = empty +chapterinfo.role.attrib = role.attrib +# doc:Meta-information for a Chapter. +chapterinfo = element chapterinfo { chapterinfo.attlist, info.class+ } +# end of chapterinfo.element +chapterinfo.attlist &= + common.attrib, chapterinfo.role.attrib, local.chapterinfo.attrib +# end of chapterinfo.attlist + +# end of chapterinfo.module +local.glossaryinfo.attrib = empty +glossaryinfo.role.attrib = role.attrib +# doc:Meta-information for a Glossary. +glossaryinfo = + element glossaryinfo { glossaryinfo.attlist, info.class+ } +# end of glossaryinfo.element +glossaryinfo.attlist &= + common.attrib, glossaryinfo.role.attrib, local.glossaryinfo.attrib +# end of glossaryinfo.attlist + +# end of glossaryinfo.module +local.indexinfo.attrib = empty +indexinfo.role.attrib = role.attrib +# doc:Meta-information for an Index. +indexinfo = element indexinfo { indexinfo.attlist, info.class+ } +# end of indexinfo.element +indexinfo.attlist &= + common.attrib, indexinfo.role.attrib, local.indexinfo.attrib +# end of indexinfo.attlist + +# end of indexinfo.module +local.setindexinfo.attrib = empty +setindexinfo.role.attrib = role.attrib +# doc:Meta-information for a SetIndex. +setindexinfo = + element setindexinfo { setindexinfo.attlist, info.class+ } +# end of setindexinfo.element +setindexinfo.attlist &= + common.attrib, setindexinfo.role.attrib, local.setindexinfo.attrib +# end of setindexinfo.attlist + +# end of setindexinfo.module +local.partinfo.attrib = empty +partinfo.role.attrib = role.attrib +# doc:Meta-information for a Part. +partinfo = element partinfo { partinfo.attlist, info.class+ } +# end of partinfo.element +partinfo.attlist &= + common.attrib, partinfo.role.attrib, local.partinfo.attrib +# end of partinfo.attlist + +# end of partinfo.module +local.prefaceinfo.attrib = empty +prefaceinfo.role.attrib = role.attrib +# doc:Meta-information for a Preface. +prefaceinfo = element prefaceinfo { prefaceinfo.attlist, info.class+ } +# end of prefaceinfo.element +prefaceinfo.attlist &= + common.attrib, prefaceinfo.role.attrib, local.prefaceinfo.attrib +# end of prefaceinfo.attlist + +# end of prefaceinfo.module +local.refentryinfo.attrib = empty +refentryinfo.role.attrib = role.attrib +# doc:Meta-information for a Refentry. +refentryinfo = + element refentryinfo { refentryinfo.attlist, info.class+ } +# end of refentryinfo.element +refentryinfo.attlist &= + common.attrib, refentryinfo.role.attrib, local.refentryinfo.attrib +# end of refentryinfo.attlist + +# end of refentryinfo.module +local.refsectioninfo.attrib = empty +refsectioninfo.role.attrib = role.attrib +# doc:Meta-information for a refsection. +refsectioninfo = + element refsectioninfo { refsectioninfo.attlist, info.class+ } +# end of refsectioninfo.element +refsectioninfo.attlist &= + common.attrib, refsectioninfo.role.attrib, local.refsectioninfo.attrib +# end of refsectioninfo.attlist + +# end of refsectioninfo.module +local.refsect1info.attrib = empty +refsect1info.role.attrib = role.attrib +# doc:Meta-information for a RefSect1. +refsect1info = + element refsect1info { refsect1info.attlist, info.class+ } +# end of refsect1info.element +refsect1info.attlist &= + common.attrib, refsect1info.role.attrib, local.refsect1info.attrib +# end of refsect1info.attlist + +# end of refsect1info.module +local.refsect2info.attrib = empty +refsect2info.role.attrib = role.attrib +# doc:Meta-information for a RefSect2. +refsect2info = + element refsect2info { refsect2info.attlist, info.class+ } +# end of refsect2info.element +refsect2info.attlist &= + common.attrib, refsect2info.role.attrib, local.refsect2info.attrib +# end of refsect2info.attlist + +# end of refsect2info.module +local.refsect3info.attrib = empty +refsect3info.role.attrib = role.attrib +# doc:Meta-information for a RefSect3. +refsect3info = + element refsect3info { refsect3info.attlist, info.class+ } +# end of refsect3info.element +refsect3info.attlist &= + common.attrib, refsect3info.role.attrib, local.refsect3info.attrib +# end of refsect3info.attlist + +# end of refsect3info.module +local.refsynopsisdivinfo.attrib = empty +refsynopsisdivinfo.role.attrib = role.attrib +# doc:Meta-information for a RefSynopsisDiv. +refsynopsisdivinfo = + element refsynopsisdivinfo { refsynopsisdivinfo.attlist, info.class+ } +# end of refsynopsisdivinfo.element +refsynopsisdivinfo.attlist &= + common.attrib, + refsynopsisdivinfo.role.attrib, + local.refsynopsisdivinfo.attrib +# end of refsynopsisdivinfo.attlist + +# end of refsynopsisdivinfo.module +local.referenceinfo.attrib = empty +referenceinfo.role.attrib = role.attrib +# doc:Meta-information for a Reference. +referenceinfo = + element referenceinfo { referenceinfo.attlist, info.class+ } +# end of referenceinfo.element +referenceinfo.attlist &= + common.attrib, referenceinfo.role.attrib, local.referenceinfo.attrib +# end of referenceinfo.attlist + +# end of referenceinfo.module +local.sect1info.attrib = empty +sect1info.role.attrib = role.attrib +# doc:Meta-information for a Sect1. +sect1info = element sect1info { sect1info.attlist, info.class+ } +# end of sect1info.element +sect1info.attlist &= + common.attrib, sect1info.role.attrib, local.sect1info.attrib +# end of sect1info.attlist +local.sect2info.attrib = empty +sect2info.role.attrib = role.attrib +# doc:Meta-information for a Sect2. +sect2info = element sect2info { sect2info.attlist, info.class+ } +# end of sect2info.element +sect2info.attlist &= + common.attrib, sect2info.role.attrib, local.sect2info.attrib +# end of sect2info.attlist +local.sect3info.attrib = empty +sect3info.role.attrib = role.attrib +# doc:Meta-information for a Sect3. +sect3info = element sect3info { sect3info.attlist, info.class+ } +# end of sect3info.element +sect3info.attlist &= + common.attrib, sect3info.role.attrib, local.sect3info.attrib +# end of sect3info.attlist +local.sect4info.attrib = empty +sect4info.role.attrib = role.attrib +# doc:Meta-information for a Sect4. +sect4info = element sect4info { sect4info.attlist, info.class+ } +# end of sect4info.element +sect4info.attlist &= + common.attrib, sect4info.role.attrib, local.sect4info.attrib +# end of sect4info.attlist +local.sect5info.attrib = empty +sect5info.role.attrib = role.attrib +# doc:Meta-information for a Sect5. +sect5info = element sect5info { sect5info.attlist, info.class+ } +# end of sect5info.element +sect5info.attlist &= + common.attrib, sect5info.role.attrib, local.sect5info.attrib +# end of sect5info.attlist + +# ...................................................................... + +# Section (parallel to Sect*) ......................................... +local.section.attrib = empty +section.role.attrib = role.attrib +# doc:A recursive section. +section = + element section { + section.attlist, + sectioninfo?, + sect.title.content, + nav.class*, + ((divcomponent.mix+, + (refentry.class* | section.class* | simplesect*)) + | refentry.class+ + | section.class+ + | simplesect+), + nav.class* + } +# end of section.element +section.attlist &= + label.attrib, + status.attrib, + common.attrib, + section.role.attrib, + local.section.attrib +# end of section.attlist + +# end of section.module +sectioninfo.role.attrib = role.attrib +local.sectioninfo.attrib = empty +# doc:Meta-information for a recursive section. +sectioninfo = element sectioninfo { sectioninfo.attlist, info.class+ } +# end of sectioninfo.element +sectioninfo.attlist &= + common.attrib, sectioninfo.role.attrib, local.sectioninfo.attrib +# end of sectioninfo.attlist + +# end of sectioninfo.module + +# end of section.content.module + +# ...................................................................... + +# Sect1, Sect2, Sect3, Sect4, Sect5 .................................... +local.sect1.attrib = empty +sect1.role.attrib = role.attrib +# doc:A top-level section of document. +sect1 = + element sect1 { + sect1.attlist, + sect1info?, + sect.title.content, + nav.class*, + ((divcomponent.mix+, (refentry.class* | sect2* | simplesect*)) + | refentry.class+ + | sect2+ + | simplesect+), + nav.class* + } +# end of sect1.element + +# Renderas: Indicates the format in which the heading should +# appear +sect1.attlist &= + attribute renderas { "sect2" | "sect3" | "sect4" | "sect5" }?, + label.attrib, + status.attrib, + common.attrib, + sect1.role.attrib, + local.sect1.attrib +# end of sect1.attlist + +# end of sect1.module +local.sect2.attrib = empty +sect2.role.attrib = role.attrib +# doc:A subsection within a Sect1. +sect2 = + element sect2 { + sect2.attlist, + sect2info?, + sect.title.content, + nav.class*, + ((divcomponent.mix+, (refentry.class* | sect3* | simplesect*)) + | refentry.class+ + | sect3+ + | simplesect+), + nav.class* + } +# end of sect2.element + +# Renderas: Indicates the format in which the heading should +# appear +sect2.attlist &= + attribute renderas { "sect1" | "sect3" | "sect4" | "sect5" }?, + label.attrib, + status.attrib, + common.attrib, + sect2.role.attrib, + local.sect2.attrib +# end of sect2.attlist + +# end of sect2.module +local.sect3.attrib = empty +sect3.role.attrib = role.attrib +# doc:A subsection within a Sect2. +sect3 = + element sect3 { + sect3.attlist, + sect3info?, + sect.title.content, + nav.class*, + ((divcomponent.mix+, (refentry.class* | sect4* | simplesect*)) + | refentry.class+ + | sect4+ + | simplesect+), + nav.class* + } +# end of sect3.element + +# Renderas: Indicates the format in which the heading should +# appear +sect3.attlist &= + attribute renderas { "sect1" | "sect2" | "sect4" | "sect5" }?, + label.attrib, + status.attrib, + common.attrib, + sect3.role.attrib, + local.sect3.attrib +# end of sect3.attlist + +# end of sect3.module +local.sect4.attrib = empty +sect4.role.attrib = role.attrib +# doc:A subsection within a Sect3. +sect4 = + element sect4 { + sect4.attlist, + sect4info?, + sect.title.content, + nav.class*, + ((divcomponent.mix+, (refentry.class* | sect5* | simplesect*)) + | refentry.class+ + | sect5+ + | simplesect+), + nav.class* + } +# end of sect4.element + +# Renderas: Indicates the format in which the heading should +# appear +sect4.attlist &= + attribute renderas { "sect1" | "sect2" | "sect3" | "sect5" }?, + label.attrib, + status.attrib, + common.attrib, + sect4.role.attrib, + local.sect4.attrib +# end of sect4.attlist + +# end of sect4.module +local.sect5.attrib = empty +sect5.role.attrib = role.attrib +# doc:A subsection within a Sect4. +sect5 = + element sect5 { + sect5.attlist, + sect5info?, + sect.title.content, + nav.class*, + ((divcomponent.mix+, (refentry.class* | simplesect*)) + | refentry.class+ + | simplesect+), + nav.class* + } +# end of sect5.element + +# Renderas: Indicates the format in which the heading should +# appear +sect5.attlist &= + attribute renderas { "sect1" | "sect2" | "sect3" | "sect4" }?, + label.attrib, + status.attrib, + common.attrib, + sect5.role.attrib, + local.sect5.attrib +# end of sect5.attlist + +# end of sect5.module +local.simplesect.attrib = empty +simplesect.role.attrib = role.attrib +# doc:A section of a document with no subdivisions. +simplesect = + element simplesect { + simplesect.attlist, sect.title.content, divcomponent.mix+ + } +# end of simplesect.element +simplesect.attlist &= + common.attrib, simplesect.role.attrib, local.simplesect.attrib +# end of simplesect.attlist + +# end of simplesect.module + +# ...................................................................... + +# Bibliography ......................................................... +local.bibliography.attrib = empty +bibliography.role.attrib = role.attrib +# doc:A bibliography. +bibliography = + element bibliography { + bibliography.attlist, + bibliographyinfo?, + bookcomponent.title.content?, + component.mix*, + (bibliodiv+ | (biblioentry | bibliomixed)+) + } +# end of bibliography.element +bibliography.attlist &= + status.attrib, + common.attrib, + bibliography.role.attrib, + local.bibliography.attrib +# end of bibliography.attlist + +# end of bibliography.module +local.bibliodiv.attrib = empty +bibliodiv.role.attrib = role.attrib +# doc:A section of a Bibliography. +bibliodiv = + element bibliodiv { + bibliodiv.attlist, + sect.title.content?, + component.mix*, + (biblioentry | bibliomixed)+ + } +# end of bibliodiv.element +bibliodiv.attlist &= + status.attrib, + common.attrib, + bibliodiv.role.attrib, + local.bibliodiv.attrib +# end of bibliodiv.attlist + +# end of bibliodiv.module + +# end of bibliography.content.module + +# ...................................................................... + +# Glossary ............................................................. +local.glossary.attrib = empty +glossary.role.attrib = role.attrib +# doc:A glossary. +glossary = + element glossary { + glossary.attlist, + glossaryinfo?, + bookcomponent.title.content?, + component.mix*, + (glossdiv+ | glossentry+), + bibliography? + } +# end of glossary.element +glossary.attlist &= + status.attrib, + common.attrib, + glossary.role.attrib, + local.glossary.attrib +# end of glossary.attlist + +# end of glossary.module +local.glossdiv.attrib = empty +glossdiv.role.attrib = role.attrib +# doc:A division in a Glossary. +glossdiv = + element glossdiv { + glossdiv.attlist, sect.title.content, component.mix*, glossentry+ + } +# end of glossdiv.element +glossdiv.attlist &= + status.attrib, + common.attrib, + glossdiv.role.attrib, + local.glossdiv.attrib +# end of glossdiv.attlist + +# end of glossdiv.module + +# end of glossary.content.module + +# ...................................................................... + +# Index and SetIndex ................................................... +local.indexes.attrib = empty +indexes.role.attrib = role.attrib +# doc:An index. +index = + element index { + index.attlist, + indexinfo?, + bookcomponent.title.content?, + component.mix*, + (indexdiv* | indexentry*) + } +# end of index.element +index.attlist &= + attribute type { text }?, + common.attrib, + indexes.role.attrib, + local.indexes.attrib +# end of index.attlist + +# doc:An index to a set of books. +setindex = + element setindex { + setindex.attlist, + setindexinfo?, + bookcomponent.title.content?, + component.mix*, + (indexdiv* | indexentry*) + } +# end of setindex.element +setindex.attlist &= + common.attrib, indexes.role.attrib, local.indexes.attrib +# end of setindex.attlist + +# end of indexes.module + +# SegmentedList in this content is useful for marking up permuted +# indices. +local.indexdiv.attrib = empty +indexdiv.role.attrib = role.attrib +# doc:A division in an index. +indexdiv = + element indexdiv { + indexdiv.attlist, + sect.title.content?, + (indexdivcomponent.mix*, (indexentry+ | segmentedlist)) + } +# end of indexdiv.element +indexdiv.attlist &= + common.attrib, indexdiv.role.attrib, local.indexdiv.attrib +# end of indexdiv.attlist + +# end of indexdiv.module + +# Index entries appear in the index, not the text. +local.indexentry.attrib = empty +indexentry.role.attrib = role.attrib +# doc:An entry in an index. +indexentry = + element indexentry { + indexentry.attlist, + primaryie, + (seeie | seealsoie)*, + (secondaryie, (seeie | seealsoie | tertiaryie)*)* + } +# end of indexentry.element +indexentry.attlist &= + common.attrib, indexentry.role.attrib, local.indexentry.attrib +# end of indexentry.attlist + +# end of indexentry.module +local.primsecterie.attrib = empty +primsecterie.role.attrib = role.attrib +# doc:A primary term in an index entry, not in the text. +primaryie = element primaryie { primaryie.attlist, ndxterm.char.mix* } +# end of primaryie.element + +# to IndexTerms that these entries represent +primaryie.attlist &= + linkends.attrib, + common.attrib, + primsecterie.role.attrib, + local.primsecterie.attrib +# end of primaryie.attlist + +# doc:A secondary term in an index entry, rather than in the text. +secondaryie = + element secondaryie { secondaryie.attlist, ndxterm.char.mix* } +# end of secondaryie.element + +# to IndexTerms that these entries represent +secondaryie.attlist &= + linkends.attrib, + common.attrib, + primsecterie.role.attrib, + local.primsecterie.attrib +# end of secondaryie.attlist + +# doc:A tertiary term in an index entry, rather than in the text. +tertiaryie = + element tertiaryie { tertiaryie.attlist, ndxterm.char.mix* } +# end of tertiaryie.element + +# to IndexTerms that these entries represent +tertiaryie.attlist &= + linkends.attrib, + common.attrib, + primsecterie.role.attrib, + local.primsecterie.attrib +# end of tertiaryie.attlist + +# end of primsecterie.module +local.seeie.attrib = empty +seeie.role.attrib = role.attrib +# doc:A See entry in an index, rather than in the text. +seeie = element seeie { seeie.attlist, ndxterm.char.mix* } +# end of seeie.element + +# to IndexEntry to look up +seeie.attlist &= + linkend.attrib, common.attrib, seeie.role.attrib, local.seeie.attrib +# end of seeie.attlist + +# end of seeie.module +local.seealsoie.attrib = empty +seealsoie.role.attrib = role.attrib +# doc:A See also entry in an index, rather than in the text. +seealsoie = element seealsoie { seealsoie.attlist, ndxterm.char.mix* } +# end of seealsoie.element + +# to related IndexEntries +seealsoie.attlist &= + linkends.attrib, + common.attrib, + seealsoie.role.attrib, + local.seealsoie.attrib +# end of seealsoie.attlist + +# end of seealsoie.module + +# end of index.content.module + +# ...................................................................... + +# RefEntry ............................................................. +local.refentry.attrib = empty +refentry.role.attrib = role.attrib +# doc:A reference page (originally a UNIX man-style reference page). +refentry = + element refentry { + refentry.attlist, + beginpage?, + ndxterm.class*, + refentryinfo?, + refmeta?, + (remark | link.char.class)*, + refnamediv+, + refsynopsisdiv?, + (refsect1+ | refsection+) + } +# end of refentry.element +refentry.attlist &= + status.attrib, + common.attrib, + refentry.role.attrib, + local.refentry.attrib +# end of refentry.attlist + +# end of refentry.module +local.refmeta.attrib = empty +refmeta.role.attrib = role.attrib +# doc:Meta-information for a reference entry. +refmeta = + element refmeta { + refmeta.attlist, + ndxterm.class*, + refentrytitle, + manvolnum?, + refmiscinfo*, + ndxterm.class* + } +# end of refmeta.element +refmeta.attlist &= + common.attrib, refmeta.role.attrib, local.refmeta.attrib +# end of refmeta.attlist + +# end of refmeta.module +local.refmiscinfo.attrib = empty +refmiscinfo.role.attrib = role.attrib +# doc:Meta-information for a reference entry other than the title and volume number. +refmiscinfo = + element refmiscinfo { refmiscinfo.attlist, docinfo.char.mix* } +# end of refmiscinfo.element + +# Class: Freely assignable parameter; no default +refmiscinfo.attlist &= + attribute class { text }?, + common.attrib, + refmiscinfo.role.attrib, + local.refmiscinfo.attrib +# end of refmiscinfo.attlist + +# end of refmiscinfo.module +local.refnamediv.attrib = empty +refnamediv.role.attrib = role.attrib +# doc:The name, purpose, and classification of a reference page. +refnamediv = + element refnamediv { + refnamediv.attlist, + refdescriptor?, + refname+, + refpurpose, + refclass*, + (remark | link.char.class)* + } +# end of refnamediv.element +refnamediv.attlist &= + common.attrib, refnamediv.role.attrib, local.refnamediv.attrib +# end of refnamediv.attlist + +# end of refnamediv.module +local.refdescriptor.attrib = empty +refdescriptor.role.attrib = role.attrib +# doc:A description of the topic of a reference page. +refdescriptor = + element refdescriptor { refdescriptor.attlist, refname.char.mix* } +# end of refdescriptor.element +refdescriptor.attlist &= + common.attrib, refdescriptor.role.attrib, local.refdescriptor.attrib +# end of refdescriptor.attlist + +# end of refdescriptor.module +local.refname.attrib = empty +refname.role.attrib = role.attrib +# doc:The name of (one of) the subject(s) of a reference page. +refname = element refname { refname.attlist, refname.char.mix* } +# end of refname.element +refname.attlist &= + common.attrib, refname.role.attrib, local.refname.attrib +# end of refname.attlist + +# end of refname.module +local.refpurpose.attrib = empty +refpurpose.role.attrib = role.attrib +# doc:A short (one sentence) synopsis of the topic of a reference page. +refpurpose = + element refpurpose { refpurpose.attlist, refinline.char.mix* } +# end of refpurpose.element +refpurpose.attlist &= + common.attrib, refpurpose.role.attrib, local.refpurpose.attrib +# end of refpurpose.attlist + +# end of refpurpose.module +local.refclass.attrib = empty +refclass.role.attrib = role.attrib +# doc:The scope or other indication of applicability of a reference entry. +refclass = element refclass { refclass.attlist, refclass.char.mix* } +# end of refclass.element +refclass.attlist &= + common.attrib, refclass.role.attrib, local.refclass.attrib +# end of refclass.attlist + +# end of refclass.module +local.refsynopsisdiv.attrib = empty +refsynopsisdiv.role.attrib = role.attrib +# doc:A syntactic synopsis of the subject of the reference page. +refsynopsisdiv = + element refsynopsisdiv { + refsynopsisdiv.attlist, + refsynopsisdivinfo?, + refsect.title.content?, + ((refcomponent.mix+, refsect2*) | refsect2+) + } +# end of refsynopsisdiv.element +refsynopsisdiv.attlist &= + common.attrib, refsynopsisdiv.role.attrib, local.refsynopsisdiv.attrib +# end of refsynopsisdiv.attlist + +# end of refsynopsisdiv.module +local.refsection.attrib = empty +refsection.role.attrib = role.attrib +# doc:A recursive section in a refentry. +refsection = + element refsection { + refsection.attlist, + refsectioninfo?, + refsect.title.content, + ((refcomponent.mix+, refsection*) | refsection+) + } +# end of refsection.element +refsection.attlist &= + status.attrib, + common.attrib, + refsection.role.attrib, + local.refsection.attrib +# end of refsection.attlist + +# end of refsection.module +local.refsect1.attrib = empty +refsect1.role.attrib = role.attrib +# doc:A major subsection of a reference entry. +refsect1 = + element refsect1 { + refsect1.attlist, + refsect1info?, + refsect.title.content, + ((refcomponent.mix+, refsect2*) | refsect2+) + } +# end of refsect1.element +refsect1.attlist &= + status.attrib, + common.attrib, + refsect1.role.attrib, + local.refsect1.attrib +# end of refsect1.attlist + +# end of refsect1.module +local.refsect2.attrib = empty +refsect2.role.attrib = role.attrib +# doc:A subsection of a RefSect1. +refsect2 = + element refsect2 { + refsect2.attlist, + refsect2info?, + refsect.title.content, + ((refcomponent.mix+, refsect3*) | refsect3+) + } +# end of refsect2.element +refsect2.attlist &= + status.attrib, + common.attrib, + refsect2.role.attrib, + local.refsect2.attrib +# end of refsect2.attlist + +# end of refsect2.module +local.refsect3.attrib = empty +refsect3.role.attrib = role.attrib +# doc:A subsection of a RefSect2. +refsect3 = + element refsect3 { + refsect3.attlist, + refsect3info?, + refsect.title.content, + refcomponent.mix+ + } +# end of refsect3.element +refsect3.attlist &= + status.attrib, + common.attrib, + refsect3.role.attrib, + local.refsect3.attrib +# end of refsect3.attlist + +# end of refsect3.module + +# end of refentry.content.module + +# ...................................................................... + +# Article .............................................................. + +# An Article is a chapter-level, stand-alone document that is often, +# but need not be, collected into a Book. +local.article.attrib = empty +article.role.attrib = role.attrib +# doc:An article. +article = + element article { + article.attlist, + div.title.content?, + articleinfo?, + tocchap?, + lot*, + bookcomponent.content, + (nav.class | appendix.class | colophon | ackno)* + } +# end of article.element + +# Class: Indicates the type of a particular article; +# all articles have the same structure and general purpose. +# No default. + +# ParentBook: ID of the enclosing Book +article.attlist &= + attribute class { + "journalarticle" + | "productsheet" + | "whitepaper" + | "techreport" + | "specification" + | "faq" + }?, + attribute parentbook { xsd:IDREF }?, + status.attrib, + common.attrib, + article.role.attrib, + local.article.attrib +# end of article.attlist + +# end of article.module + +# End of DocBook document hierarchy module V4.5 ........................ + +# ...................................................................... diff --git a/defensive-coding/docbook-schema/.svn/text-base/dbnotnx.rnc.svn-base b/defensive-coding/docbook-schema/.svn/text-base/dbnotnx.rnc.svn-base new file mode 100644 index 0000000..9beb245 --- /dev/null +++ b/defensive-coding/docbook-schema/.svn/text-base/dbnotnx.rnc.svn-base @@ -0,0 +1,85 @@ +# ...................................................................... + +# DocBook notations module V4.5 ........................................ + +# File dbnotnx.mod ..................................................... + +# Copyright 1992-2004 HaL Computer Systems, Inc., +# O'Reilly & Associates, Inc., ArborText, Inc., Fujitsu Software +# Corporation, Norman Walsh, Sun Microsystems, Inc., and the +# Organization for the Advancement of Structured Information +# Standards (OASIS). +# +# $Id: dbnotnx.mod 6340 2006-10-03 13:23:24Z nwalsh $ +# +# Permission to use, copy, modify and distribute the DocBook DTD +# and its accompanying documentation for any purpose and without fee +# is hereby granted in perpetuity, provided that the above copyright +# notice and this paragraph appear in all copies. The copyright +# holders make no representation about the suitability of the DTD for +# any purpose. It is provided "as is" without expressed or implied +# warranty. +# +# If you modify the DocBook DTD in any way, except for declaring and +# referencing additional sets of general entities and declaring +# additional notations, label your DTD as a variant of DocBook. See +# the maintenance documentation for more information. +# +# Please direct all questions, bug reports, or suggestions for +# changes to the docbook@lists.oasis-open.org mailing list. For more +# information, see http://www.oasis-open.org/docbook/. + +# ...................................................................... + +# This module contains the notation declarations used by DocBook. +# +# In DTD driver files referring to this module, please use an entity +# declaration that uses the public identifier shown below: +# +# +# %dbnotn; +# +# See the documentation for detailed information on the parameter +# entity and module scheme used in DocBook, customizing DocBook and +# planning for interchange, and changes made since the last release +# of DocBook. + +local.notation.class = notAllowed +notation.class = + "BMP" + | "CGM-CHAR" + | "CGM-BINARY" + | "CGM-CLEAR" + | "DITROFF" + | "DVI" + | "EPS" + | "EQN" + | "FAX" + | "GIF" + | "GIF87a" + | "GIF89a" + | "JPG" + | "JPEG" + | "IGES" + | "PCX" + | "PIC" + | "PNG" + | "PS" + | "SGML" + | "TBL" + | "TEX" + | "TIFF" + | "WMF" + | "WPG" + | "SVG" + | "PDF" + | "SWF" + | "linespecific" + | local.notation.class +# WordPerfect Graphic format + +# End of DocBook notations module V4.5 ................................. + +# ...................................................................... diff --git a/defensive-coding/docbook-schema/.svn/text-base/dbpoolx.rnc.svn-base b/defensive-coding/docbook-schema/.svn/text-base/dbpoolx.rnc.svn-base new file mode 100644 index 0000000..47100a3 --- /dev/null +++ b/defensive-coding/docbook-schema/.svn/text-base/dbpoolx.rnc.svn-base @@ -0,0 +1,5785 @@ +# ...................................................................... + +# DocBook XML information pool module V4.5 ............................. + +# File dbpoolx.mod ..................................................... + +# Copyright 1992-2004 HaL Computer Systems, Inc., +# O'Reilly & Associates, Inc., ArborText, Inc., Fujitsu Software +# Corporation, Norman Walsh, Sun Microsystems, Inc., and the +# Organization for the Advancement of Structured Information +# Standards (OASIS). +# +# $Id: dbpoolx.mod 6340 2006-10-03 13:23:24Z nwalsh $ +# +# Permission to use, copy, modify and distribute the DocBook XML DTD +# and its accompanying documentation for any purpose and without fee +# is hereby granted in perpetuity, provided that the above copyright +# notice and this paragraph appear in all copies. The copyright +# holders make no representation about the suitability of the DTD for +# any purpose. It is provided "as is" without expressed or implied +# warranty. +# +# If you modify the DocBook XML DTD in any way, except for declaring and +# referencing additional sets of general entities and declaring +# additional notations, label your DTD as a variant of DocBook. See +# the maintenance documentation for more information. +# +# Please direct all questions, bug reports, or suggestions for +# changes to the docbook@lists.oasis-open.org mailing list. For more +# information, see http://www.oasis-open.org/docbook/. + +# ...................................................................... + +# This module contains the definitions for the objects, inline +# elements, and so on that are available to be used as the main +# content of DocBook documents. Some elements are useful for general +# publishing, and others are useful specifically for computer +# documentation. +# +# This module has the following dependencies on other modules: +# +# o It assumes that a %notation.class; entity is defined by the +# driver file or other high-level module. This entity is +# referenced in the NOTATION attributes for the graphic-related and +# ModeSpec elements. +# +# o It assumes that an appropriately parameterized table module is +# available for use with the table-related elements. +# +# In DTD driver files referring to this module, please use an entity +# declaration that uses the public identifier shown below: +# +# +# %dbpool; +# +# See the documentation for detailed information on the parameter +# entity and module scheme used in DocBook, customizing DocBook and +# planning for interchange, and changes made since the last release +# of DocBook. + +# ...................................................................... + +# Forms entities ....................................................... + +# These PEs provide the hook by which the forms module can be inserted + +# into the DTD. + +namespace a = "http://relaxng.org/ns/compatibility/annotations/1.0" + +forminlines.hook = notAllowed +forms.hook = notAllowed +# ...................................................................... + +# General-purpose semantics entities ................................... +yesorno.attvals = string +# ...................................................................... + +# Entities for module inclusions ....................................... + +# ...................................................................... + +# Entities for element classes and mixtures ............................ + +# "Ubiquitous" classes: ndxterm.class and beginpage +local.ndxterm.class = notAllowed +ndxterm.class = indexterm | local.ndxterm.class +# Object-level classes ................................................. +local.list.class = notAllowed +list.class = + calloutlist + | glosslist + | bibliolist + | itemizedlist + | orderedlist + | segmentedlist + | simplelist + | variablelist + | local.list.class +local.admon.class = notAllowed +admon.class = + caution | important | note | tip | warning | local.admon.class +local.linespecific.class = notAllowed +linespecific.class = + literallayout + | programlisting + | programlistingco + | screen + | screenco + | screenshot + | local.linespecific.class +local.method.synop.class = notAllowed +method.synop.class = + constructorsynopsis + | destructorsynopsis + | methodsynopsis + | local.method.synop.class +local.synop.class = notAllowed +synop.class = + synopsis + | cmdsynopsis + | funcsynopsis + | classsynopsis + | fieldsynopsis + | method.synop.class + | local.synop.class +local.para.class = notAllowed +para.class = formalpara | para | simpara | local.para.class +local.informal.class = notAllowed +informal.class = + address + | blockquote + | graphic + | graphicco + | mediaobject + | mediaobjectco + | informalequation + | informalexample + | informalfigure + | informaltable + | local.informal.class +local.formal.class = notAllowed +formal.class = equation | example | figure | table | local.formal.class +# The DocBook TC may produce an official EBNF module for DocBook. + +# This PE provides the hook by which it can be inserted into the DTD. +ebnf.block.hook = notAllowed +local.compound.class = notAllowed +compound.class = + msgset + | procedure + | sidebar + | qandaset + | task + | ebnf.block.hook + | local.compound.class +local.genobj.class = notAllowed +genobj.class = + anchor | bridgehead | remark | highlights | local.genobj.class +local.descobj.class = notAllowed +descobj.class = abstract | authorblurb | epigraph | local.descobj.class +# Character-level classes .............................................. +local.xref.char.class = notAllowed +xref.char.class = footnoteref | xref | biblioref | local.xref.char.class +local.gen.char.class = notAllowed +gen.char.class = + abbrev + | acronym + | citation + | citerefentry + | citetitle + | citebiblioid + | emphasis + | firstterm + | foreignphrase + | glossterm + | termdef + | footnote + | phrase + | orgname + | quote + | trademark + | wordasword + | personname + | local.gen.char.class +local.link.char.class = notAllowed +link.char.class = link | olink | ulink | local.link.char.class +# The DocBook TC may produce an official EBNF module for DocBook. + +# This PE provides the hook by which it can be inserted into the DTD. +ebnf.inline.hook = notAllowed +local.tech.char.class = notAllowed +tech.char.class = + action + | application + | classname + | methodname + | interfacename + | exceptionname + | ooclass + | oointerface + | ooexception + | package + | command + | computeroutput + | database + | email + | envar + | errorcode + | errorname + | errortype + | errortext + | filename + | function + | guibutton + | guiicon + | guilabel + | guimenu + | guimenuitem + | guisubmenu + | hardware + | interface + | keycap + | keycode + | keycombo + | keysym + | literal + | code + | constant + | markup + | medialabel + | menuchoice + | mousebutton + | option + | optional + | parameter + | prompt + | property + | replaceable + | returnvalue + | sgmltag + | structfield + | structname + | symbol + | systemitem + | uri + | \token + | type + | userinput + | varname + | ebnf.inline.hook + | local.tech.char.class +local.base.char.class = notAllowed +base.char.class = anchor | local.base.char.class +local.docinfo.char.class = notAllowed +docinfo.char.class = + author + | authorinitials + | corpauthor + | corpcredit + | modespec + | othercredit + | productname + | productnumber + | revhistory + | local.docinfo.char.class +local.other.char.class = notAllowed +other.char.class = + remark | subscript | superscript | local.other.char.class +local.inlineobj.char.class = notAllowed +inlineobj.char.class = + inlinegraphic + | inlinemediaobject + | inlineequation + | local.inlineobj.char.class +# ...................................................................... + +# Entities for content models .......................................... +formalobject.title.content = title, titleabbrev? +# Redeclaration placeholder ............................................ + +# For redeclaring entities that are declared after this point while +# retaining their references to the entities that are declared before +# this point + +# Object-level mixtures ................................................ + +# list admn line synp para infm form cmpd gen desc +# Component mixture X X X X X X X X X X +# Sidebar mixture X X X X X X X a X +# Footnote mixture X X X X X +# Example mixture X X X X X +# Highlights mixture X X X +# Paragraph mixture X X X X +# Admonition mixture X X X X X X b c +# Figure mixture X X X +# Table entry mixture X X X X d +# Glossary def mixture X X X X X e +# Legal notice mixture X X X X f +# +# a. Just Procedure; not Sidebar itself or MsgSet. +# b. No MsgSet. +# c. No Highlights. +# d. Just Graphic; no other informal objects. +# e. No Anchor, BridgeHead, or Highlights. +# f. Just BlockQuote; no other informal objects. +local.component.mix = notAllowed +component.mix = + list.class + | admon.class + | linespecific.class + | synop.class + | para.class + | informal.class + | formal.class + | compound.class + | genobj.class + | descobj.class + | ndxterm.class + | beginpage + | forms.hook + | local.component.mix +local.sidebar.mix = notAllowed +sidebar.mix = + list.class + | admon.class + | linespecific.class + | synop.class + | para.class + | informal.class + | formal.class + | procedure + | genobj.class + | ndxterm.class + | beginpage + | forms.hook + | local.sidebar.mix +local.qandaset.mix = notAllowed +qandaset.mix = + list.class + | admon.class + | linespecific.class + | synop.class + | para.class + | informal.class + | formal.class + | procedure + | genobj.class + | ndxterm.class + | forms.hook + | local.qandaset.mix +local.revdescription.mix = notAllowed +revdescription.mix = + list.class + | admon.class + | linespecific.class + | synop.class + | para.class + | informal.class + | formal.class + | procedure + | genobj.class + | ndxterm.class + | local.revdescription.mix +local.footnote.mix = notAllowed +footnote.mix = + list.class + | linespecific.class + | synop.class + | para.class + | informal.class + | local.footnote.mix +local.example.mix = notAllowed +example.mix = + list.class + | linespecific.class + | synop.class + | para.class + | informal.class + | ndxterm.class + | beginpage + | procedure + | forms.hook + | local.example.mix +local.highlights.mix = notAllowed +highlights.mix = + list.class + | admon.class + | para.class + | ndxterm.class + | local.highlights.mix +# %formal.class; is explicitly excluded from many contexts in which +# paragraphs are used +local.para.mix = notAllowed +para.mix = + list.class + | admon.class + | linespecific.class + | informal.class + | formal.class + | local.para.mix +local.admon.mix = notAllowed +admon.mix = + list.class + | linespecific.class + | synop.class + | para.class + | informal.class + | formal.class + | procedure + | sidebar + | anchor + | bridgehead + | remark + | ndxterm.class + | beginpage + | forms.hook + | local.admon.mix +local.figure.mix = notAllowed +figure.mix = + linespecific.class + | synop.class + | informal.class + | ndxterm.class + | beginpage + | forms.hook + | local.figure.mix +local.tabentry.mix = notAllowed +tabentry.mix = + list.class + | admon.class + | linespecific.class + | para.class + | graphic + | mediaobject + | forms.hook + | local.tabentry.mix +local.glossdef.mix = notAllowed +glossdef.mix = + list.class + | linespecific.class + | synop.class + | para.class + | informal.class + | formal.class + | remark + | ndxterm.class + | beginpage + | local.glossdef.mix +local.legalnotice.mix = notAllowed +legalnotice.mix = + list.class + | admon.class + | linespecific.class + | para.class + | blockquote + | ndxterm.class + | beginpage + | local.legalnotice.mix +local.textobject.mix = notAllowed +textobject.mix = + list.class + | admon.class + | linespecific.class + | para.class + | blockquote + | local.textobject.mix +local.mediaobject.mix = notAllowed +mediaobject.mix = + videoobject + | audioobject + | imageobject + | imageobjectco + | textobject + | local.mediaobject.mix +local.listpreamble.mix = notAllowed +listpreamble.mix = + admon.class + | linespecific.class + | synop.class + | para.class + | informal.class + | genobj.class + | descobj.class + | ndxterm.class + | beginpage + | forms.hook + | local.listpreamble.mix +# Character-level mixtures ............................................. + +# sgml.features + +# not [sgml.features[ + +# ]] not sgml.features + +# #PCD xref word link cptr base dnfo othr inob (synop) +# para.char.mix X X X X X X X X X +# title.char.mix X X X X X X X X X +# ndxterm.char.mix X X X X X X X X a +# cptr.char.mix X X X X X a +# smallcptr.char.mix X b a +# word.char.mix X c X X X a +# docinfo.char.mix X d X b X a +# +# a. Just InlineGraphic; no InlineEquation. +# b. Just Replaceable; no other computer terms. +# c. Just Emphasis and Trademark; no other word elements. +# d. Just Acronym, Emphasis, and Trademark; no other word elements. +local.para.char.mix = notAllowed +para.char.mix = + text + | xref.char.class + | gen.char.class + | link.char.class + | tech.char.class + | base.char.class + | docinfo.char.class + | other.char.class + | inlineobj.char.class + | synop.class + | ndxterm.class + | beginpage + | forminlines.hook + | local.para.char.mix +local.title.char.mix = notAllowed +title.char.mix = + text + | xref.char.class + | gen.char.class + | link.char.class + | tech.char.class + | base.char.class + | docinfo.char.class + | other.char.class + | inlineobj.char.class + | ndxterm.class + | local.title.char.mix +local.ndxterm.char.mix = notAllowed +ndxterm.char.mix = + text + | xref.char.class + | gen.char.class + | link.char.class + | tech.char.class + | base.char.class + | docinfo.char.class + | other.char.class + | inlinegraphic + | inlinemediaobject + | local.ndxterm.char.mix +local.cptr.char.mix = notAllowed +cptr.char.mix = + text + | link.char.class + | tech.char.class + | base.char.class + | other.char.class + | inlinegraphic + | inlinemediaobject + | ndxterm.class + | beginpage + | local.cptr.char.mix +local.smallcptr.char.mix = notAllowed +smallcptr.char.mix = + text + | replaceable + | inlinegraphic + | inlinemediaobject + | ndxterm.class + | beginpage + | local.smallcptr.char.mix +local.word.char.mix = notAllowed +word.char.mix = + text + | acronym + | emphasis + | trademark + | link.char.class + | base.char.class + | other.char.class + | inlinegraphic + | inlinemediaobject + | ndxterm.class + | beginpage + | local.word.char.mix +local.docinfo.char.mix = notAllowed +docinfo.char.mix = + text + | link.char.class + | emphasis + | trademark + | replaceable + | other.char.class + | inlinegraphic + | inlinemediaobject + | ndxterm.class + | local.docinfo.char.mix +# ENTITY % bibliocomponent.mix (see Bibliographic section, below) + +# ENTITY % person.ident.mix (see Bibliographic section, below) + +# ...................................................................... + +# Entities for attributes and attribute components ..................... + +# Effectivity attributes ............................................... + +# Arch: Computer or chip architecture to which element applies; no +# default +arch.attrib = attribute arch { text }? +# Condition: General-purpose effectivity attribute +condition.attrib = attribute condition { text }? +# Conformance: Standards conformance characteristics +conformance.attrib = attribute conformance { xsd:NMTOKENS }? +# OS: Operating system to which element applies; no default +os.attrib = attribute os { text }? +# Revision: Editorial revision to which element belongs; no default +revision.attrib = attribute revision { text }? +# Security: Security classification; no default +security.attrib = attribute security { text }? +# UserLevel: Level of user experience to which element applies; no +# default +userlevel.attrib = attribute userlevel { text }? +# Vendor: Computer vendor to which element applies; no default +vendor.attrib = attribute vendor { text }? +# Wordsize: Computer word size (32 bit, 64 bit, etc.); no default +wordsize.attrib = attribute wordsize { text }? +local.effectivity.attrib = empty +effectivity.attrib = + arch.attrib, + condition.attrib, + conformance.attrib, + os.attrib, + revision.attrib, + security.attrib, + userlevel.attrib, + vendor.attrib, + wordsize.attrib, + local.effectivity.attrib +# Common attributes .................................................... + +# Id: Unique identifier of element; no default +id.attrib = attribute id { xsd:ID }? +# Id: Unique identifier of element; a value must be supplied; no +# default +idreq.attrib = attribute id { xsd:ID } +# Lang: Indicator of language in which element is written, for +# translation, character set management, etc.; no default +lang.attrib = attribute lang { text }? +# Remap: Previous role of element before conversion; no default +remap.attrib = attribute remap { text }? +# Role: New role of element in local environment; no default +role.attrib = attribute role { text }? +# XRefLabel: Alternate labeling string for XRef text generation; +# default is usually title or other appropriate label text already +# contained in element +xreflabel.attrib = attribute xreflabel { text }? +# RevisionFlag: Revision status of element; default is that element +# wasn't revised +revisionflag.attrib = + attribute revisionflag { "changed" | "added" | "deleted" | "off" }? +local.common.attrib = empty +# dir: Bidirectional override +dir.attrib = attribute dir { "ltr" | "rtl" | "lro" | "rlo" }? +# xml:base: base URI +xml-base.attrib = attribute xml:base { text }? +# Role is included explicitly on each element +common.attrib = + id.attrib, + lang.attrib, + remap.attrib, + xreflabel.attrib, + revisionflag.attrib, + effectivity.attrib, + dir.attrib, + xml-base.attrib, + local.common.attrib +# Role is included explicitly on each element +idreq.common.attrib = + idreq.attrib, + lang.attrib, + remap.attrib, + xreflabel.attrib, + revisionflag.attrib, + effectivity.attrib, + dir.attrib, + xml-base.attrib, + local.common.attrib +# Semi-common attributes and other attribute entities .................. +local.graphics.attrib = empty +# EntityRef: Name of an external entity containing the content +# of the graphic + +# FileRef: Filename, qualified by a pathname if desired, +# designating the file containing the content of the graphic + +# Format: Notation of the element content, if any + +# SrcCredit: Information about the source of the Graphic + +# Width: Same as CALS reprowid (desired width) + +# Depth: Same as CALS reprodep (desired depth) + +# Align: Same as CALS hplace with 'none' removed; #IMPLIED means +# application-specific + +# Scale: Conflation of CALS hscale and vscale + +# Scalefit: Same as CALS scalefit +graphics.attrib = + attribute entityref { xsd:ENTITY }?, + attribute fileref { text }?, + attribute format { notation.class }?, + attribute srccredit { text }?, + attribute width { text }?, + attribute contentwidth { text }?, + attribute depth { text }?, + attribute contentdepth { text }?, + attribute align { "left" | "right" | "center" }?, + attribute valign { "top" | "middle" | "bottom" }?, + attribute scale { text }?, + attribute scalefit { yesorno.attvals }?, + local.graphics.attrib +local.keyaction.attrib = empty +# Action: Key combination type; default is unspecified if one +# child element, Simul if there is more than one; if value is +# Other, the OtherAction attribute must have a nonempty value + +# OtherAction: User-defined key combination type +keyaction.attrib = + attribute action { + "click" | "double-click" | "press" | "seq" | "simul" | "other" + }?, + attribute otheraction { text }?, + local.keyaction.attrib +# Label: Identifying number or string; default is usually the +# appropriate number or string autogenerated by a formatter +label.attrib = attribute label { text }? +# xml:space: whitespace treatment +xml-space.attrib = attribute xml:space { "preserve" }? +# Format: whether element is assumed to contain significant white +# space +linespecific.attrib = + [ a:defaultValue = "linespecific" ] + attribute format { "linespecific" }?, + xml-space.attrib, + attribute linenumbering { "numbered" | "unnumbered" }?, + attribute continuation { "continues" | "restarts" }?, + attribute startinglinenumber { text }?, + attribute language { text }? +# Linkend: link to related information; no default +linkend.attrib = attribute linkend { xsd:IDREF }? +# Linkend: required link to related information +linkendreq.attrib = attribute linkend { xsd:IDREF } +# Linkends: link to one or more sets of related information; no +# default +linkends.attrib = attribute linkends { xsd:IDREFS }? +local.mark.attrib = empty +mark.attrib = + attribute mark { text }?, + local.mark.attrib +# MoreInfo: whether element's content has an associated RefEntry +moreinfo.attrib = + [ a:defaultValue = "none" ] + attribute moreinfo { "refentry" | "none" }? +# Pagenum: number of page on which element appears; no default +pagenum.attrib = attribute pagenum { text }? +local.status.attrib = empty +# Status: Editorial or publication status of the element +# it applies to, such as "in review" or "approved for distribution" +status.attrib = + attribute status { text }?, + local.status.attrib +# Width: width of the longest line in the element to which it +# pertains, in number of characters +width.attrib = attribute width { text }? +# ...................................................................... + +# Title elements ....................................................... +local.title.attrib = empty +title.role.attrib = role.attrib +# doc:The text of the title of a section of a document or of a formal block-level element. +title = element title { title.attlist, title.char.mix* } +# end of title.element +title.attlist &= + pagenum.attrib, common.attrib, title.role.attrib, local.title.attrib +# end of title.attlist + +# end of title.module +local.titleabbrev.attrib = empty +titleabbrev.role.attrib = role.attrib +# doc:The abbreviation of a Title. +titleabbrev = + element titleabbrev { titleabbrev.attlist, title.char.mix* } +# end of titleabbrev.element +titleabbrev.attlist &= + common.attrib, titleabbrev.role.attrib, local.titleabbrev.attrib +# end of titleabbrev.attlist + +# end of titleabbrev.module +local.subtitle.attrib = empty +subtitle.role.attrib = role.attrib +# doc:The subtitle of a document. +subtitle = element subtitle { subtitle.attlist, title.char.mix* } +# end of subtitle.element +subtitle.attlist &= + common.attrib, subtitle.role.attrib, local.subtitle.attrib +# end of subtitle.attlist + +# end of subtitle.module + +# ...................................................................... + +# Bibliographic entities and elements .................................. + +# The bibliographic elements are typically used in the document +# hierarchy. They do not appear in content models of information +# pool elements. See also the document information elements, +# below. +local.person.ident.mix = notAllowed +person.ident.mix = + honorific + | firstname + | surname + | lineage + | othername + | affiliation + | authorblurb + | contrib + | local.person.ident.mix +local.bibliocomponent.mix = notAllowed +bibliocomponent.mix = + abbrev + | abstract + | address + | artpagenums + | author + | authorgroup + | authorinitials + | bibliomisc + | biblioset + | collab + | confgroup + | contractnum + | contractsponsor + | copyright + | corpauthor + | corpname + | corpcredit + | date + | edition + | editor + | invpartnumber + | isbn + | issn + | issuenum + | orgname + | biblioid + | citebiblioid + | bibliosource + | bibliorelation + | bibliocoverage + | othercredit + | pagenums + | printhistory + | productname + | productnumber + | pubdate + | publisher + | publishername + | pubsnumber + | releaseinfo + | revhistory + | seriesvolnums + | subtitle + | title + | titleabbrev + | volumenum + | citetitle + | personname + | person.ident.mix + | ndxterm.class + | local.bibliocomponent.mix +# I don't think this is well placed, but it needs to be here because of + +# the reference to bibliocomponent.mix +local.info.class = notAllowed +info.class = + graphic + | mediaobject + | legalnotice + | modespec + | subjectset + | keywordset + | itermset + | bibliocomponent.mix + | local.info.class +# BiblioList ........................ +local.bibliolist.attrib = empty +bibliolist.role.attrib = role.attrib +# doc:A wrapper for a set of bibliography entries. +bibliolist = + element bibliolist { + bibliolist.attlist, + blockinfo?, + formalobject.title.content?, + (biblioentry | bibliomixed)+ + } +# end of bibliolist.element +bibliolist.attlist &= + common.attrib, bibliolist.role.attrib, local.bibliolist.attrib +# end of bibliolist.attlist + +# end of bibliolist.module +local.biblioentry.attrib = empty +biblioentry.role.attrib = role.attrib +# doc:An entry in a Bibliography. +biblioentry = + element biblioentry { + biblioentry.attlist, (articleinfo | bibliocomponent.mix)+ + } +# end of biblioentry.element +biblioentry.attlist &= + common.attrib, biblioentry.role.attrib, local.biblioentry.attrib +# end of biblioentry.attlist + +# end of biblioentry.module +local.bibliomixed.attrib = empty +bibliomixed.role.attrib = role.attrib +# doc:An entry in a Bibliography. +bibliomixed = + element bibliomixed { + bibliomixed.attlist, (text | bibliocomponent.mix | bibliomset)* + } +# end of bibliomixed.element +bibliomixed.attlist &= + common.attrib, bibliomixed.role.attrib, local.bibliomixed.attrib +# end of bibliomixed.attlist + +# end of bibliomixed.module +local.articleinfo.attrib = empty +articleinfo.role.attrib = role.attrib +# doc:Meta-information for an Article. +articleinfo = element articleinfo { articleinfo.attlist, info.class+ } +# end of articleinfo.element +articleinfo.attlist &= + common.attrib, articleinfo.role.attrib, local.articleinfo.attrib +# end of articleinfo.attlist + +# end of articleinfo.module +local.biblioset.attrib = empty +biblioset.role.attrib = role.attrib +# doc:A "raw" container for related bibliographic information. +biblioset = + element biblioset { biblioset.attlist, bibliocomponent.mix+ } +# end of biblioset.element + +# Relation: Relationship of elements contained within BiblioSet +biblioset.attlist &= + attribute relation { text }?, + common.attrib, + biblioset.role.attrib, + local.biblioset.attrib +# end of biblioset.attlist + +# end of biblioset.module +bibliomset.role.attrib = role.attrib +local.bibliomset.attrib = empty +# doc:A "cooked" container for related bibliographic information. +bibliomset = + element bibliomset { + bibliomset.attlist, (text | bibliocomponent.mix | bibliomset)* + } +# end of bibliomset.element + +# Relation: Relationship of elements contained within BiblioMSet +bibliomset.attlist &= + attribute relation { text }?, + common.attrib, + bibliomset.role.attrib, + local.bibliomset.attrib +# end of bibliomset.attlist + +# end of bibliomset.module +local.bibliomisc.attrib = empty +bibliomisc.role.attrib = role.attrib +# doc:Untyped bibliographic information. +bibliomisc = element bibliomisc { bibliomisc.attlist, para.char.mix* } +# end of bibliomisc.element +bibliomisc.attlist &= + common.attrib, bibliomisc.role.attrib, local.bibliomisc.attrib +# end of bibliomisc.attlist + +# end of bibliomisc.module + +# ...................................................................... + +# Subject, Keyword, and ITermSet elements .............................. +local.subjectset.attrib = empty +subjectset.role.attrib = role.attrib +# doc:A set of terms describing the subject matter of a document. +subjectset = element subjectset { subjectset.attlist, subject+ } +# end of subjectset.element + +# Scheme: Controlled vocabulary employed in SubjectTerms +subjectset.attlist &= + attribute scheme { xsd:NMTOKEN }?, + common.attrib, + subjectset.role.attrib, + local.subjectset.attrib +# end of subjectset.attlist + +# end of subjectset.module +local.subject.attrib = empty +subject.role.attrib = role.attrib +# doc:One of a group of terms describing the subject matter of a document. +subject = element subject { subject.attlist, subjectterm+ } +# end of subject.element + +# Weight: Ranking of this group of SubjectTerms relative +# to others, 0 is low, no highest value specified +subject.attlist &= + attribute weight { text }?, + common.attrib, + subject.role.attrib, + local.subject.attrib +# end of subject.attlist + +# end of subject.module +local.subjectterm.attrib = empty +subjectterm.role.attrib = role.attrib +# doc:A term in a group of terms describing the subject matter of a document. +subjectterm = element subjectterm { subjectterm.attlist, text } +# end of subjectterm.element +subjectterm.attlist &= + common.attrib, subjectterm.role.attrib, local.subjectterm.attrib +# end of subjectterm.attlist + +# end of subjectterm.module + +# end of subjectset.content.module +local.keywordset.attrib = empty +keywordset.role.attrib = role.attrib +# doc:A set of keywords describing the content of a document. +keywordset = element keywordset { keywordset.attlist, keyword+ } +# end of keywordset.element +keywordset.attlist &= + common.attrib, keywordset.role.attrib, local.keywordset.attrib +# end of keywordset.attlist + +# end of keywordset.module +local.keyword.attrib = empty +keyword.role.attrib = role.attrib +# doc:One of a set of keywords describing the content of a document. +keyword = element keyword { keyword.attlist, text } +# end of keyword.element +keyword.attlist &= + common.attrib, keyword.role.attrib, local.keyword.attrib +# end of keyword.attlist + +# end of keyword.module + +# end of keywordset.content.module +local.itermset.attrib = empty +itermset.role.attrib = role.attrib +# doc:A set of index terms in the meta-information of a document. +itermset = element itermset { itermset.attlist, indexterm+ } +# end of itermset.element +itermset.attlist &= + common.attrib, itermset.role.attrib, local.itermset.attrib +# end of itermset.attlist + +# end of itermset.module + +# Bibliographic info for "blocks" +local.blockinfo.attrib = empty +blockinfo.role.attrib = role.attrib +# doc:Meta-information for a block element. +blockinfo = element blockinfo { blockinfo.attlist, info.class+ } +# end of blockinfo.element +blockinfo.attlist &= + common.attrib, blockinfo.role.attrib, local.blockinfo.attrib +# end of blockinfo.attlist + +# end of blockinfo.module + +# ...................................................................... + +# Compound (section-ish) elements ...................................... + +# Message set ...................... +local.msgset.attrib = empty +msgset.role.attrib = role.attrib +# doc:A detailed set of messages, usually error messages. +msgset = + element msgset { + msgset.attlist, + blockinfo?, + formalobject.title.content?, + (msgentry+ | simplemsgentry+) + } +# end of msgset.element +msgset.attlist &= common.attrib, msgset.role.attrib, local.msgset.attrib +# end of msgset.attlist + +# end of msgset.module +local.msgentry.attrib = empty +msgentry.role.attrib = role.attrib +# doc:A wrapper for an entry in a message set. +msgentry = + element msgentry { msgentry.attlist, msg+, msginfo?, msgexplan* } +# end of msgentry.element +msgentry.attlist &= + common.attrib, msgentry.role.attrib, local.msgentry.attrib +# end of msgentry.attlist + +# end of msgentry.module +local.simplemsgentry.attrib = empty +simplemsgentry.role.attrib = role.attrib +# doc:A wrapper for a simpler entry in a message set. +simplemsgentry = + element simplemsgentry { simplemsgentry.attlist, msgtext, msgexplan+ } +# end of simplemsgentry.element +simplemsgentry.attlist &= + attribute audience { text }?, + attribute level { text }?, + attribute origin { text }?, + common.attrib, + simplemsgentry.role.attrib, + local.simplemsgentry.attrib +# end of simplemsgentry.attlist + +# end of simplemsgentry.module +local.msg.attrib = empty +msg.role.attrib = role.attrib +# doc:A message in a message set. +msg = element msg { msg.attlist, title?, msgmain, (msgsub | msgrel)* } +# end of msg.element +msg.attlist &= common.attrib, msg.role.attrib, local.msg.attrib +# end of msg.attlist + +# end of msg.module +local.msgmain.attrib = empty +msgmain.role.attrib = role.attrib +# doc:The primary component of a message in a message set. +msgmain = element msgmain { msgmain.attlist, title?, msgtext } +# end of msgmain.element +msgmain.attlist &= + common.attrib, msgmain.role.attrib, local.msgmain.attrib +# end of msgmain.attlist + +# end of msgmain.module +local.msgsub.attrib = empty +msgsub.role.attrib = role.attrib +# doc:A subcomponent of a message in a message set. +msgsub = element msgsub { msgsub.attlist, title?, msgtext } +# end of msgsub.element +msgsub.attlist &= common.attrib, msgsub.role.attrib, local.msgsub.attrib +# end of msgsub.attlist + +# end of msgsub.module +local.msgrel.attrib = empty +msgrel.role.attrib = role.attrib +# doc:A related component of a message in a message set. +msgrel = element msgrel { msgrel.attlist, title?, msgtext } +# end of msgrel.element +msgrel.attlist &= common.attrib, msgrel.role.attrib, local.msgrel.attrib +# end of msgrel.attlist + +# end of msgrel.module + +# MsgText (defined in the Inlines section, below) +local.msginfo.attrib = empty +msginfo.role.attrib = role.attrib +# doc:Information about a message in a message set. +msginfo = + element msginfo { msginfo.attlist, (msglevel | msgorig | msgaud)* } +# end of msginfo.element +msginfo.attlist &= + common.attrib, msginfo.role.attrib, local.msginfo.attrib +# end of msginfo.attlist + +# end of msginfo.module +local.msglevel.attrib = empty +msglevel.role.attrib = role.attrib +# doc:The level of importance or severity of a message in a message set. +msglevel = element msglevel { msglevel.attlist, smallcptr.char.mix* } +# end of msglevel.element +msglevel.attlist &= + common.attrib, msglevel.role.attrib, local.msglevel.attrib +# end of msglevel.attlist + +# end of msglevel.module +local.msgorig.attrib = empty +msgorig.role.attrib = role.attrib +# doc:The origin of a message in a message set. +msgorig = element msgorig { msgorig.attlist, smallcptr.char.mix* } +# end of msgorig.element +msgorig.attlist &= + common.attrib, msgorig.role.attrib, local.msgorig.attrib +# end of msgorig.attlist + +# end of msgorig.module +local.msgaud.attrib = empty +msgaud.role.attrib = role.attrib +# doc:The audience to which a message in a message set is relevant. +msgaud = element msgaud { msgaud.attlist, para.char.mix* } +# end of msgaud.element +msgaud.attlist &= common.attrib, msgaud.role.attrib, local.msgaud.attrib +# end of msgaud.attlist + +# end of msgaud.module +local.msgexplan.attrib = empty +msgexplan.role.attrib = role.attrib +# doc:Explanatory material relating to a message in a message set. +msgexplan = + element msgexplan { msgexplan.attlist, title?, component.mix+ } +# end of msgexplan.element +msgexplan.attlist &= + common.attrib, msgexplan.role.attrib, local.msgexplan.attrib +# end of msgexplan.attlist + +# end of msgexplan.module + +# end of msgset.content.module +local.task.attrib = empty +task.role.attrib = role.attrib +# doc:A task to be completed. +task = + element task { + task.attlist, + blockinfo?, + ndxterm.class*, + formalobject.title.content, + tasksummary?, + taskprerequisites?, + procedure, + example*, + taskrelated? + } +# end of task.element +task.attlist &= common.attrib, task.role.attrib, local.task.attrib +# end of task.attlist + +# end of task.module +local.tasksummary.attrib = empty +tasksummary.role.attrib = role.attrib +# doc:A summary of a task. +tasksummary = + element tasksummary { + tasksummary.attlist, + blockinfo?, + formalobject.title.content?, + component.mix+ + } +# end of tasksummary.element +tasksummary.attlist &= + common.attrib, tasksummary.role.attrib, local.tasksummary.attrib +# end of tasksummary.attlist + +# end of tasksummary.module +local.taskprerequisites.attrib = empty +taskprerequisites.role.attrib = role.attrib +# doc:The prerequisites for a task. +taskprerequisites = + element taskprerequisites { + taskprerequisites.attlist, + blockinfo?, + formalobject.title.content?, + component.mix+ + } +# end of taskprerequisites.element +taskprerequisites.attlist &= + common.attrib, + taskprerequisites.role.attrib, + local.taskprerequisites.attrib +# end of taskprerequisites.attlist + +# end of taskprerequisites.module +local.taskrelated.attrib = empty +taskrelated.role.attrib = role.attrib +# doc:Information related to a task. +taskrelated = + element taskrelated { + taskrelated.attlist, + blockinfo?, + formalobject.title.content?, + component.mix+ + } +# end of taskrelated.element +taskrelated.attlist &= + common.attrib, taskrelated.role.attrib, local.taskrelated.attrib +# end of taskrelated.attlist + +# end of taskrelated.module + +# end of task.content.module + +# QandASet ........................ +local.qandaset.attrib = empty +qandaset.role.attrib = role.attrib +# doc:A question-and-answer set. +qandaset = + element qandaset { + qandaset.attlist, + blockinfo?, + formalobject.title.content?, + qandaset.mix*, + (qandadiv+ | qandaentry+) + } +# end of qandaset.element +qandaset.attlist &= + attribute defaultlabel { "qanda" | "number" | "none" }?, + common.attrib, + qandaset.role.attrib, + local.qandaset.attrib +# end of qandaset.attlist + +# end of qandaset.module +local.qandadiv.attrib = empty +qandadiv.role.attrib = role.attrib +# doc:A titled division in a QandASet. +qandadiv = + element qandadiv { + qandadiv.attlist, + blockinfo?, + formalobject.title.content?, + qandaset.mix*, + (qandadiv+ | qandaentry+) + } +# end of qandadiv.element +qandadiv.attlist &= + common.attrib, qandadiv.role.attrib, local.qandadiv.attrib +# end of qandadiv.attlist + +# end of qandadiv.module +local.qandaentry.attrib = empty +qandaentry.role.attrib = role.attrib +# doc:A question/answer set within a QandASet. +qandaentry = + element qandaentry { + qandaentry.attlist, blockinfo?, revhistory?, question, answer* + } +# end of qandaentry.element +qandaentry.attlist &= + common.attrib, qandaentry.role.attrib, local.qandaentry.attrib +# end of qandaentry.attlist + +# end of qandaentry.module +local.question.attrib = empty +question.role.attrib = role.attrib +# doc:A question in a QandASet. +question = element question { question.attlist, label?, qandaset.mix+ } +# end of question.element +question.attlist &= + common.attrib, question.role.attrib, local.question.attrib +# end of question.attlist + +# end of question.module +local.answer.attrib = empty +answer.role.attrib = role.attrib +# doc:An answer to a question posed in a QandASet. +answer = + element answer { answer.attlist, label?, qandaset.mix*, qandaentry* } +# end of answer.element +answer.attlist &= common.attrib, answer.role.attrib, local.answer.attrib +# end of answer.attlist + +# end of answer.module +local.label.attrib = empty +label.role.attrib = role.attrib +# doc:A label on a Question or Answer. +label = element label { label.attlist, word.char.mix* } +# end of label.element +label.attlist &= common.attrib, label.role.attrib, local.label.attrib +# end of label.attlist + +# end of label.module + +# end of qandaset.content.module + +# Procedure ........................ +local.procedure.attrib = empty +procedure.role.attrib = role.attrib +# doc:A list of operations to be performed in a well-defined sequence. +procedure = + element procedure { + procedure.attlist, + blockinfo?, + formalobject.title.content?, + component.mix*, + step+ + } +# end of procedure.element +procedure.attlist &= + common.attrib, procedure.role.attrib, local.procedure.attrib +# end of procedure.attlist + +# end of procedure.module +local.step.attrib = empty +step.role.attrib = role.attrib +# doc:A unit of action in a procedure. +step = + element step { + step.attlist, + title?, + ((component.mix+, + ((substeps | stepalternatives), component.mix*)?) + | ((substeps | stepalternatives), component.mix*)) + } +# end of step.element + +# Performance: Whether the Step must be performed + +# not #REQUIRED! +step.attlist &= + [ a:defaultValue = "required" ] + attribute performance { "optional" | "required" }?, + common.attrib, + step.role.attrib, + local.step.attrib +# end of step.attlist + +# end of step.module +local.substeps.attrib = empty +substeps.role.attrib = role.attrib +# doc:A wrapper for steps that occur within steps in a procedure. +substeps = element substeps { substeps.attlist, step+ } +# end of substeps.element + +# Performance: whether entire set of substeps must be performed + +# not #REQUIRED! +substeps.attlist &= + [ a:defaultValue = "required" ] + attribute performance { "optional" | "required" }?, + common.attrib, + substeps.role.attrib, + local.substeps.attrib +# end of substeps.attlist + +# end of substeps.module +local.stepalternatives.attrib = empty +stepalternatives.role.attrib = role.attrib +# doc:Alternative steps in a procedure. +stepalternatives = + element stepalternatives { stepalternatives.attlist, step+ } +# end of stepalternatives.element + +# Performance: Whether (one of) the alternatives must be performed + +# not #REQUIRED! +stepalternatives.attlist &= + [ a:defaultValue = "required" ] + attribute performance { "optional" | "required" }?, + common.attrib, + stepalternatives.role.attrib, + local.stepalternatives.attrib +# end of stepalternatives.attlist + +# end of stepalternatives.module + +# end of procedure.content.module + +# Sidebar .......................... +local.sidebarinfo.attrib = empty +sidebarinfo.role.attrib = role.attrib +# doc:Meta-information for a Sidebar. +sidebarinfo = element sidebarinfo { sidebarinfo.attlist, info.class+ } +# end of sidebarinfo.element +sidebarinfo.attlist &= + common.attrib, sidebarinfo.role.attrib, local.sidebarinfo.attrib +# end of sidebarinfo.attlist + +# end of sidebarinfo.module +local.sidebar.attrib = empty +sidebar.role.attrib = role.attrib +# doc:A portion of a document that is isolated from the main narrative flow. +sidebar = + element sidebar { + sidebar.attlist, + sidebarinfo?, + formalobject.title.content?, + sidebar.mix+ + } +# end of sidebar.element +sidebar.attlist &= + common.attrib, sidebar.role.attrib, local.sidebar.attrib +# end of sidebar.attlist + +# end of sidebar.module + +# end of sidebar.content.model + +# ...................................................................... + +# Paragraph-related elements ........................................... +local.abstract.attrib = empty +abstract.role.attrib = role.attrib +# doc:A summary. +abstract = element abstract { abstract.attlist, title?, para.class+ } +# end of abstract.element +abstract.attlist &= + common.attrib, abstract.role.attrib, local.abstract.attrib +# end of abstract.attlist + +# end of abstract.module +local.authorblurb.attrib = empty +authorblurb.role.attrib = role.attrib +# doc:A short description or note about an author. +authorblurb = + element authorblurb { authorblurb.attlist, title?, para.class+ } +# end of authorblurb.element +authorblurb.attlist &= + common.attrib, authorblurb.role.attrib, local.authorblurb.attrib +# end of authorblurb.attlist + +# end of authorblurb.module +local.personblurb.attrib = empty +personblurb.role.attrib = role.attrib +# doc:A short description or note about a person. +personblurb = + element personblurb { personblurb.attlist, title?, para.class+ } +# end of personblurb.element +personblurb.attlist &= + common.attrib, personblurb.role.attrib, local.personblurb.attrib +# end of personblurb.attlist + +# end of personblurb.module +local.blockquote.attrib = empty +blockquote.role.attrib = role.attrib +# doc:A quotation set off from the main text. +blockquote = + element blockquote { + blockquote.attlist, blockinfo?, title?, attribution?, component.mix+ + } +# end of blockquote.element +blockquote.attlist &= + common.attrib, blockquote.role.attrib, local.blockquote.attrib +# end of blockquote.attlist + +# end of blockquote.module +local.attribution.attrib = empty +attribution.role.attrib = role.attrib +# doc:The source of a block quote or epigraph. +attribution = + element attribution { attribution.attlist, para.char.mix* } +# end of attribution.element +attribution.attlist &= + common.attrib, attribution.role.attrib, local.attribution.attrib +# end of attribution.attlist + +# end of attribution.module +local.bridgehead.attrib = empty +bridgehead.role.attrib = role.attrib +# doc:A free-floating heading. +bridgehead = element bridgehead { bridgehead.attlist, title.char.mix* } +# end of bridgehead.element + +# Renderas: Indicates the format in which the BridgeHead +# should appear +bridgehead.attlist &= + attribute renderas { + "other" | "sect1" | "sect2" | "sect3" | "sect4" | "sect5" + }?, + common.attrib, + bridgehead.role.attrib, + local.bridgehead.attrib +# end of bridgehead.attlist + +# end of bridgehead.module +local.remark.attrib = empty +remark.role.attrib = role.attrib +# doc:A remark (or comment) intended for presentation in a draft manuscript. +remark = element remark { remark.attlist, para.char.mix* } +# end of remark.element +remark.attlist &= common.attrib, remark.role.attrib, local.remark.attrib +# end of remark.attlist + +# end of remark.module +local.epigraph.attrib = empty +epigraph.role.attrib = role.attrib +# doc:A short inscription at the beginning of a document or component. +epigraph = + element epigraph { + epigraph.attlist, attribution?, (para.class | literallayout)+ + } +# end of epigraph.element +epigraph.attlist &= + common.attrib, epigraph.role.attrib, local.epigraph.attrib +# end of epigraph.attlist + +# Attribution (defined above) + +# end of epigraph.module +local.footnote.attrib = empty +footnote.role.attrib = role.attrib +# doc:A footnote. +footnote = element footnote { footnote.attlist, footnote.mix+ } +# end of footnote.element +footnote.attlist &= + label.attrib, + common.attrib, + footnote.role.attrib, + local.footnote.attrib +# end of footnote.attlist + +# end of footnote.module +local.highlights.attrib = empty +highlights.role.attrib = role.attrib +# doc:A summary of the main points of the discussed component. +highlights = element highlights { highlights.attlist, highlights.mix+ } +# end of highlights.element +highlights.attlist &= + common.attrib, highlights.role.attrib, local.highlights.attrib +# end of highlights.attlist + +# end of highlights.module +local.formalpara.attrib = empty +formalpara.role.attrib = role.attrib +# doc:A paragraph with a title. +formalpara = + element formalpara { formalpara.attlist, title, ndxterm.class*, para } +# end of formalpara.element +formalpara.attlist &= + common.attrib, formalpara.role.attrib, local.formalpara.attrib +# end of formalpara.attlist + +# end of formalpara.module +local.para.attrib = empty +para.role.attrib = role.attrib +# doc:A paragraph. +para = element para { para.attlist, (para.char.mix | para.mix)* } +# end of para.element +para.attlist &= common.attrib, para.role.attrib, local.para.attrib +# end of para.attlist + +# end of para.module +local.simpara.attrib = empty +simpara.role.attrib = role.attrib +# doc:A paragraph that contains only text and inline markup, no block elements. +simpara = element simpara { simpara.attlist, para.char.mix* } +# end of simpara.element +simpara.attlist &= + common.attrib, simpara.role.attrib, local.simpara.attrib +# end of simpara.attlist + +# end of simpara.module +local.admon.attrib = empty +admon.role.attrib = role.attrib +# doc:A note of caution. +caution = element caution { caution.attlist, title?, admon.mix+ } +# end of caution.element +caution.attlist &= common.attrib, admon.role.attrib, local.admon.attrib +# end of caution.attlist + +# doc:An admonition set off from the text. +important = element important { important.attlist, title?, admon.mix+ } +# end of important.element +important.attlist &= + common.attrib, admon.role.attrib, local.admon.attrib +# end of important.attlist + +# doc:A message set off from the text. +note = element note { note.attlist, title?, admon.mix+ } +# end of note.element +note.attlist &= common.attrib, admon.role.attrib, local.admon.attrib +# end of note.attlist + +# doc:A suggestion to the user, set off from the text. +tip = element tip { tip.attlist, title?, admon.mix+ } +# end of tip.element +tip.attlist &= common.attrib, admon.role.attrib, local.admon.attrib +# end of tip.attlist + +# doc:An admonition set off from the text. +warning = element warning { warning.attlist, title?, admon.mix+ } +# end of warning.element +warning.attlist &= common.attrib, admon.role.attrib, local.admon.attrib +# end of warning.attlist + +# end of admon.module + +# ...................................................................... + +# Lists ................................................................ + +# GlossList ........................ +local.glosslist.attrib = empty +glosslist.role.attrib = role.attrib +# doc:A wrapper for a set of GlossEntrys. +glosslist = + element glosslist { + glosslist.attlist, + blockinfo?, + formalobject.title.content?, + glossentry+ + } +# end of glosslist.element +glosslist.attlist &= + common.attrib, glosslist.role.attrib, local.glosslist.attrib +# end of glosslist.attlist + +# end of glosslist.module +local.glossentry.attrib = empty +glossentry.role.attrib = role.attrib +# doc:An entry in a Glossary or GlossList. +glossentry = + element glossentry { + glossentry.attlist, + glossterm, + acronym?, + abbrev?, + ndxterm.class*, + revhistory?, + (glosssee | glossdef+) + } +# end of glossentry.element + +# SortAs: String by which the GlossEntry is to be sorted +# (alphabetized) in lieu of its proper content +glossentry.attlist &= + attribute sortas { text }?, + common.attrib, + glossentry.role.attrib, + local.glossentry.attrib +# end of glossentry.attlist + +# end of glossentry.module + +# GlossTerm (defined in the Inlines section, below) +local.glossdef.attrib = empty +glossdef.role.attrib = role.attrib +# doc:A definition in a GlossEntry. +glossdef = + element glossdef { glossdef.attlist, glossdef.mix+, glossseealso* } +# end of glossdef.element + +# Subject: List of subjects; keywords for the definition +glossdef.attlist &= + attribute subject { text }?, + common.attrib, + glossdef.role.attrib, + local.glossdef.attrib +# end of glossdef.attlist + +# end of glossdef.module +local.glosssee.attrib = empty +glosssee.role.attrib = role.attrib +# doc:A cross-reference from one GlossEntry to another. +glosssee = element glosssee { glosssee.attlist, para.char.mix* } +# end of glosssee.element + +# OtherTerm: Reference to the GlossEntry whose GlossTerm +# should be displayed at the point of the GlossSee +glosssee.attlist &= + attribute otherterm { xsd:IDREF }?, + common.attrib, + glosssee.role.attrib, + local.glosssee.attrib +# end of glosssee.attlist + +# end of glosssee.module +local.glossseealso.attrib = empty +glossseealso.role.attrib = role.attrib +# doc:A cross-reference from one GlossEntry to another. +glossseealso = + element glossseealso { glossseealso.attlist, para.char.mix* } +# end of glossseealso.element + +# OtherTerm: Reference to the GlossEntry whose GlossTerm +# should be displayed at the point of the GlossSeeAlso +glossseealso.attlist &= + attribute otherterm { xsd:IDREF }?, + common.attrib, + glossseealso.role.attrib, + local.glossseealso.attrib +# end of glossseealso.attlist + +# end of glossseealso.module + +# end of glossentry.content.module + +# ItemizedList and OrderedList ..... +local.itemizedlist.attrib = empty +itemizedlist.role.attrib = role.attrib +# doc:A list in which each entry is marked with a bullet or other dingbat. +itemizedlist = + element itemizedlist { + itemizedlist.attlist, + blockinfo?, + formalobject.title.content?, + listpreamble.mix*, + listitem+ + } +# end of itemizedlist.element + +# Spacing: Whether the vertical space in the list should be +# compressed + +# Mark: Keyword, e.g., bullet, dash, checkbox, none; +# list of keywords and defaults are implementation specific +itemizedlist.attlist &= + attribute spacing { "normal" | "compact" }?, + mark.attrib, + common.attrib, + itemizedlist.role.attrib, + local.itemizedlist.attrib +# end of itemizedlist.attlist + +# end of itemizedlist.module +local.orderedlist.attrib = empty +orderedlist.role.attrib = role.attrib +# doc:A list in which each entry is marked with a sequentially incremented label. +orderedlist = + element orderedlist { + orderedlist.attlist, + blockinfo?, + formalobject.title.content?, + listpreamble.mix*, + listitem+ + } +# end of orderedlist.element + +# Numeration: Style of ListItem numbered; default is expected +# to be Arabic + +# InheritNum: Specifies for a nested list that the numbering +# of ListItems should include the number of the item +# within which they are nested (e.g., 1a and 1b within 1, +# rather than a and b) + +# Continuation: Where list numbering begins afresh (Restarts, +# the default) or continues that of the immediately preceding +# list (Continues) + +# Spacing: Whether the vertical space in the list should be +# compressed +orderedlist.attlist &= + attribute numeration { + "arabic" | "upperalpha" | "loweralpha" | "upperroman" | "lowerroman" + }?, + [ a:defaultValue = "ignore" ] + attribute inheritnum { "inherit" | "ignore" }?, + [ a:defaultValue = "restarts" ] + attribute continuation { "continues" | "restarts" }?, + attribute spacing { "normal" | "compact" }?, + common.attrib, + orderedlist.role.attrib, + local.orderedlist.attrib +# end of orderedlist.attlist + +# end of orderedlist.module +local.listitem.attrib = empty +listitem.role.attrib = role.attrib +# doc:A wrapper for the elements of a list item. +listitem = element listitem { listitem.attlist, component.mix+ } +# end of listitem.element + +# Override: Indicates the mark to be used for this ListItem +# instead of the default mark or the mark specified by +# the Mark attribute on the enclosing ItemizedList +listitem.attlist &= + attribute override { text }?, + common.attrib, + listitem.role.attrib, + local.listitem.attrib +# end of listitem.attlist + +# end of listitem.module + +# SegmentedList .................... +local.segmentedlist.attrib = empty +segmentedlist.role.attrib = role.attrib +# doc:A segmented list, a list of sets of elements. +segmentedlist = + element segmentedlist { + segmentedlist.attlist, + formalobject.title.content?, + segtitle+, + seglistitem+ + } +# end of segmentedlist.element +segmentedlist.attlist &= + common.attrib, segmentedlist.role.attrib, local.segmentedlist.attrib +# end of segmentedlist.attlist + +# end of segmentedlist.module +local.segtitle.attrib = empty +segtitle.role.attrib = role.attrib +# doc:The title of an element of a list item in a segmented list. +segtitle = element segtitle { segtitle.attlist, title.char.mix* } +# end of segtitle.element +segtitle.attlist &= + common.attrib, segtitle.role.attrib, local.segtitle.attrib +# end of segtitle.attlist + +# end of segtitle.module +local.seglistitem.attrib = empty +seglistitem.role.attrib = role.attrib +# doc:A list item in a segmented list. +seglistitem = element seglistitem { seglistitem.attlist, seg+ } +# end of seglistitem.element +seglistitem.attlist &= + common.attrib, seglistitem.role.attrib, local.seglistitem.attrib +# end of seglistitem.attlist + +# end of seglistitem.module +local.seg.attrib = empty +seg.role.attrib = role.attrib +# doc:An element of a list item in a segmented list. +seg = element seg { seg.attlist, para.char.mix* } +# end of seg.element +seg.attlist &= common.attrib, seg.role.attrib, local.seg.attrib +# end of seg.attlist + +# end of seg.module + +# end of segmentedlist.content.module + +# SimpleList ....................... +local.simplelist.attrib = empty +simplelist.role.attrib = role.attrib +# doc:An undecorated list of single words or short phrases. +simplelist = element simplelist { simplelist.attlist, member+ } +# end of simplelist.element + +# Columns: The number of columns the array should contain + +# Type: How the Members of the SimpleList should be +# formatted: Inline (members separated with commas etc. +# inline), Vert (top to bottom in n Columns), or Horiz (in +# the direction of text flow) in n Columns. If Column +# is 1 or implied, Type=Vert and Type=Horiz give the same +# results. +simplelist.attlist &= + attribute columns { text }?, + [ a:defaultValue = "vert" ] + attribute type { "inline" | "vert" | "horiz" }?, + common.attrib, + simplelist.role.attrib, + local.simplelist.attrib +# end of simplelist.attlist + +# end of simplelist.module +local.member.attrib = empty +member.role.attrib = role.attrib +# doc:An element of a simple list. +member = element member { member.attlist, para.char.mix* } +# end of member.element +member.attlist &= common.attrib, member.role.attrib, local.member.attrib +# end of member.attlist + +# end of member.module + +# end of simplelist.content.module + +# VariableList ..................... +local.variablelist.attrib = empty +variablelist.role.attrib = role.attrib +# doc:A list in which each entry is composed of a set of one or more terms and an associated description. +variablelist = + element variablelist { + variablelist.attlist, + blockinfo?, + formalobject.title.content?, + listpreamble.mix*, + varlistentry+ + } +# end of variablelist.element + +# TermLength: Length beyond which the presentation engine +# may consider the Term too long and select an alternate +# presentation of the Term and, or, its associated ListItem. +variablelist.attlist &= + attribute termlength { text }?, + attribute spacing { "normal" | "compact" }?, + common.attrib, + variablelist.role.attrib, + local.variablelist.attrib +# end of variablelist.attlist + +# end of variablelist.module +local.varlistentry.attrib = empty +varlistentry.role.attrib = role.attrib +# doc:A wrapper for a set of terms and the associated description in a variable list. +varlistentry = + element varlistentry { varlistentry.attlist, term+, listitem } +# end of varlistentry.element +varlistentry.attlist &= + common.attrib, varlistentry.role.attrib, local.varlistentry.attrib +# end of varlistentry.attlist + +# end of varlistentry.module +local.term.attrib = empty +term.role.attrib = role.attrib +# doc:The word or phrase being defined or described in a variable list. +term = element term { term.attlist, para.char.mix* } +# end of term.element +term.attlist &= common.attrib, term.role.attrib, local.term.attrib +# end of term.attlist + +# end of term.module + +# ListItem (defined above) + +# end of variablelist.content.module + +# CalloutList ...................... +local.calloutlist.attrib = empty +calloutlist.role.attrib = role.attrib +# doc:A list of Callouts. +calloutlist = + element calloutlist { + calloutlist.attlist, formalobject.title.content?, callout+ + } +# end of calloutlist.element +calloutlist.attlist &= + common.attrib, calloutlist.role.attrib, local.calloutlist.attrib +# end of calloutlist.attlist + +# end of calloutlist.module +local.callout.attrib = empty +callout.role.attrib = role.attrib +# doc:A “called out” description of a marked Area. +callout = element callout { callout.attlist, component.mix+ } +# end of callout.element + +# AreaRefs: IDs of one or more Areas or AreaSets described +# by this Callout +callout.attlist &= + attribute arearefs { xsd:IDREFS }, + common.attrib, + callout.role.attrib, + local.callout.attrib +# end of callout.attlist + +# end of callout.module + +# end of calloutlist.content.module + +# ...................................................................... + +# Objects .............................................................. + +# Examples etc. .................... +local.example.attrib = empty +example.role.attrib = role.attrib +# doc:A formal example, with a title. +example = + element example { + example.attlist, + blockinfo?, + formalobject.title.content, + example.mix+ + } +# end of example.element +example.attlist &= + attribute floatstyle { text }?, + label.attrib, + width.attrib, + common.attrib, + example.role.attrib, + local.example.attrib +# end of example.attlist + +# end of example.module +local.informalexample.attrib = empty +informalexample.role.attrib = role.attrib +# doc:A displayed example without a title. +informalexample = + element informalexample { + informalexample.attlist, blockinfo?, example.mix+ + } +# end of informalexample.element +informalexample.attlist &= + attribute floatstyle { text }?, + width.attrib, + common.attrib, + informalexample.role.attrib, + local.informalexample.attrib +# end of informalexample.attlist + +# end of informalexample.module +local.programlistingco.attrib = empty +programlistingco.role.attrib = role.attrib +# doc:A program listing with associated areas used in callouts. +programlistingco = + element programlistingco { + programlistingco.attlist, areaspec, programlisting, calloutlist* + } +# end of programlistingco.element +programlistingco.attlist &= + common.attrib, + programlistingco.role.attrib, + local.programlistingco.attrib +# end of programlistingco.attlist + +# CalloutList (defined above in Lists) + +# end of informalexample.module +local.areaspec.attrib = empty +areaspec.role.attrib = role.attrib +# doc:A collection of regions in a graphic or code example. +areaspec = element areaspec { areaspec.attlist, (area | areaset)+ } +# end of areaspec.element + +# Units: global unit of measure in which coordinates in +# this spec are expressed: +# +# - CALSPair "x1,y1 x2,y2": lower-left and upper-right +# coordinates in a rectangle describing repro area in which +# graphic is placed, where X and Y dimensions are each some +# number 0..10000 (taken from CALS graphic attributes) +# +# - LineColumn "line column": line number and column number +# at which to start callout text in "linespecific" content +# +# - LineRange "startline endline": whole lines from startline +# to endline in "linespecific" content +# +# - LineColumnPair "line1 col1 line2 col2": starting and ending +# points of area in "linespecific" content that starts at +# first position and ends at second position (including the +# beginnings of any intervening lines) +# +# - Other: directive to look at value of OtherUnits attribute +# to get implementation-specific keyword +# +# The default is implementation-specific; usually dependent on +# the parent element (GraphicCO gets CALSPair, ProgramListingCO +# and ScreenCO get LineColumn) + +# OtherUnits: User-defined units +areaspec.attlist &= + attribute units { + "calspair" | "linecolumn" | "linerange" | "linecolumnpair" | "other" + }?, + attribute otherunits { xsd:NMTOKEN }?, + common.attrib, + areaspec.role.attrib, + local.areaspec.attrib +# end of areaspec.attlist + +# end of areaspec.module +local.area.attrib = empty +area.role.attrib = role.attrib +# doc:A region defined for a Callout in a graphic or code example. +area = element area { area.attlist, empty } +# end of area.element + +# bug number/symbol override or initialization + +# to any related information + +# Units: unit of measure in which coordinates in this +# area are expressed; inherits from AreaSet and AreaSpec + +# OtherUnits: User-defined units +area.attlist &= + label.attrib, + linkends.attrib, + attribute units { + "calspair" | "linecolumn" | "linerange" | "linecolumnpair" | "other" + }?, + attribute otherunits { xsd:NMTOKEN }?, + attribute coords { text }, + idreq.common.attrib, + area.role.attrib, + local.area.attrib +# end of area.attlist + +# end of area.module +local.areaset.attrib = empty +areaset.role.attrib = role.attrib +# doc:A set of related areas in a graphic or code example. +areaset = element areaset { areaset.attlist, area+ } +# end of areaset.element + +# bug number/symbol override or initialization + +# Units: unit of measure in which coordinates in this +# area are expressed; inherits from AreaSpec +areaset.attlist &= + label.attrib, + attribute units { + "calspair" | "linecolumn" | "linerange" | "linecolumnpair" | "other" + }?, + attribute otherunits { xsd:NMTOKEN }?, + attribute coords { text }, + idreq.common.attrib, + areaset.role.attrib, + local.areaset.attrib +# end of areaset.attlist + +# end of areaset.module + +# end of areaspec.content.module +local.programlisting.attrib = empty +programlisting.role.attrib = role.attrib +# doc:A literal listing of all or part of a program. +programlisting = + element programlisting { + programlisting.attlist, + (para.char.mix | co | coref | lineannotation | textobject)* + } +# end of programlisting.element +programlisting.attlist &= + width.attrib, + linespecific.attrib, + common.attrib, + programlisting.role.attrib, + local.programlisting.attrib +# end of programlisting.attlist + +# end of programlisting.module +local.literallayout.attrib = empty +literallayout.role.attrib = role.attrib +# doc:A block of text in which line breaks and white space are to be reproduced faithfully. +literallayout = + element literallayout { + literallayout.attlist, + (para.char.mix | co | coref | textobject | lineannotation)* + } +# end of literallayout.element +literallayout.attlist &= + width.attrib, + linespecific.attrib, + [ a:defaultValue = "normal" ] + attribute class { "monospaced" | "normal" }?, + common.attrib, + literallayout.role.attrib, + local.literallayout.attrib +# end of literallayout.attlist + +# LineAnnotation (defined in the Inlines section, below) + +# end of literallayout.module +local.screenco.attrib = empty +screenco.role.attrib = role.attrib +# doc:A screen with associated areas used in callouts. +screenco = + element screenco { screenco.attlist, areaspec, screen, calloutlist* } +# end of screenco.element +screenco.attlist &= + common.attrib, screenco.role.attrib, local.screenco.attrib +# end of screenco.attlist + +# AreaSpec (defined above) + +# CalloutList (defined above in Lists) + +# end of screenco.module +local.screen.attrib = empty +screen.role.attrib = role.attrib +# doc:Text that a user sees or might see on a computer screen. +screen = + element screen { + screen.attlist, + (para.char.mix | co | coref | textobject | lineannotation)* + } +# end of screen.element +screen.attlist &= + width.attrib, + linespecific.attrib, + common.attrib, + screen.role.attrib, + local.screen.attrib +# end of screen.attlist + +# end of screen.module +local.screenshot.attrib = empty +screenshot.role.attrib = role.attrib +# doc:A representation of what the user sees or might see on a computer screen. +screenshot = + element screenshot { + screenshot.attlist, + screeninfo?, + (graphic | graphicco | mediaobject | mediaobjectco) + } +# end of screenshot.element +screenshot.attlist &= + common.attrib, screenshot.role.attrib, local.screenshot.attrib +# end of screenshot.attlist + +# end of screenshot.module +local.screeninfo.attrib = empty +screeninfo.role.attrib = role.attrib +# doc:Information about how a screen shot was produced. +screeninfo = element screeninfo { screeninfo.attlist, para.char.mix* } +# end of screeninfo.element +screeninfo.attlist &= + common.attrib, screeninfo.role.attrib, local.screeninfo.attrib +# end of screeninfo.attlist + +# end of screeninfo.module + +# end of screenshot.content.module + +# Figures etc. ..................... +local.figure.attrib = empty +figure.role.attrib = role.attrib +# doc:A formal figure, generally an illustration, with a title. +figure = + element figure { + figure.attlist, + blockinfo?, + formalobject.title.content, + (figure.mix | link.char.class)+ + } +# end of figure.element + +# Float: Whether the Figure is supposed to be rendered +# where convenient (yes (1) value) or at the place it occurs +# in the text (no (0) value, the default) +figure.attlist &= + [ a:defaultValue = "0" ] attribute float { yesorno.attvals }?, + attribute floatstyle { text }?, + attribute pgwide { yesorno.attvals }?, + label.attrib, + common.attrib, + figure.role.attrib, + local.figure.attrib +# end of figure.attlist + +# end of figure.module +local.informalfigure.attrib = empty +informalfigure.role.attrib = role.attrib +# doc:A untitled figure. +informalfigure = + element informalfigure { + informalfigure.attlist, blockinfo?, (figure.mix | link.char.class)+ + } +# end of informalfigure.element + +# Float: Whether the Figure is supposed to be rendered +# where convenient (yes (1) value) or at the place it occurs +# in the text (no (0) value, the default) +informalfigure.attlist &= + [ a:defaultValue = "0" ] attribute float { yesorno.attvals }?, + attribute floatstyle { text }?, + attribute pgwide { yesorno.attvals }?, + label.attrib, + common.attrib, + informalfigure.role.attrib, + local.informalfigure.attrib +# end of informalfigure.attlist + +# end of informalfigure.module +local.graphicco.attrib = empty +graphicco.role.attrib = role.attrib +# doc:A graphic that contains callout areas. +graphicco = + element graphicco { + graphicco.attlist, areaspec, graphic, calloutlist* + } +# end of graphicco.element +graphicco.attlist &= + common.attrib, graphicco.role.attrib, local.graphicco.attrib +# end of graphicco.attlist + +# AreaSpec (defined above in Examples) + +# CalloutList (defined above in Lists) + +# end of graphicco.module + +# Graphical data can be the content of Graphic, or you can reference +# an external file either as an entity (Entitref) or a filename +# (Fileref). +local.graphic.attrib = empty +graphic.role.attrib = role.attrib +# doc:A displayed graphical object (not an inline). +graphic = element graphic { graphic.attlist, empty } +# end of graphic.element +graphic.attlist &= + graphics.attrib, + common.attrib, + graphic.role.attrib, + local.graphic.attrib +# end of graphic.attlist + +# end of graphic.module +local.inlinegraphic.attrib = empty +inlinegraphic.role.attrib = role.attrib +# doc:An object containing or pointing to graphical data that will be rendered inline. +inlinegraphic = element inlinegraphic { inlinegraphic.attlist, empty } +# end of inlinegraphic.element +inlinegraphic.attlist &= + graphics.attrib, + common.attrib, + inlinegraphic.role.attrib, + local.inlinegraphic.attrib +# end of inlinegraphic.attlist + +# end of inlinegraphic.module +local.mediaobject.attrib = empty +mediaobject.role.attrib = role.attrib +# doc:A displayed media object (video, audio, image, etc.). +mediaobject = + element mediaobject { + mediaobject.attlist, objectinfo?, mediaobject.mix+, caption? + } +# end of mediaobject.element +mediaobject.attlist &= + common.attrib, mediaobject.role.attrib, local.mediaobject.attrib +# end of mediaobject.attlist + +# end of mediaobject.module +local.inlinemediaobject.attrib = empty +inlinemediaobject.role.attrib = role.attrib +# doc:An inline media object (video, audio, image, and so on). +inlinemediaobject = + element inlinemediaobject { + inlinemediaobject.attlist, objectinfo?, mediaobject.mix+ + } +# end of inlinemediaobject.element +inlinemediaobject.attlist &= + common.attrib, + inlinemediaobject.role.attrib, + local.inlinemediaobject.attrib +# end of inlinemediaobject.attlist + +# end of inlinemediaobject.module +local.videoobject.attrib = empty +videoobject.role.attrib = role.attrib +# doc:A wrapper for video data and its associated meta-information. +videoobject = + element videoobject { videoobject.attlist, objectinfo?, videodata } +# end of videoobject.element +videoobject.attlist &= + common.attrib, videoobject.role.attrib, local.videoobject.attrib +# end of videoobject.attlist + +# end of videoobject.module +local.audioobject.attrib = empty +audioobject.role.attrib = role.attrib +# doc:A wrapper for audio data and its associated meta-information. +audioobject = + element audioobject { audioobject.attlist, objectinfo?, audiodata } +# end of audioobject.element +audioobject.attlist &= + common.attrib, audioobject.role.attrib, local.audioobject.attrib +# end of audioobject.attlist + +# end of audioobject.module +local.imageobject.attrib = empty +imageobject.role.attrib = role.attrib +# doc:A wrapper for image data and its associated meta-information. +imageobject = + element imageobject { imageobject.attlist, objectinfo?, imagedata } +# end of imageobject.element +imageobject.attlist &= + common.attrib, imageobject.role.attrib, local.imageobject.attrib +# end of imageobject.attlist + +# end of imageobject.module +local.textobject.attrib = empty +textobject.role.attrib = role.attrib +# doc:A wrapper for a text description of an object and its associated meta-information. +textobject = + element textobject { + textobject.attlist, + objectinfo?, + (phrase | textdata | textobject.mix+) + } +# end of textobject.element +textobject.attlist &= + common.attrib, textobject.role.attrib, local.textobject.attrib +# end of textobject.attlist + +# end of textobject.module +local.objectinfo.attrib = empty +objectinfo.role.attrib = role.attrib +# doc:Meta-information for an object. +objectinfo = element objectinfo { objectinfo.attlist, info.class+ } +# end of objectinfo.element +objectinfo.attlist &= + common.attrib, objectinfo.role.attrib, local.objectinfo.attrib +# end of objectinfo.attlist + +# end of objectinfo.module + +# EntityRef: Name of an external entity containing the content +# of the object data + +# FileRef: Filename, qualified by a pathname if desired, +# designating the file containing the content of the object data + +# Format: Notation of the element content, if any + +# SrcCredit: Information about the source of the image +local.objectdata.attrib = empty +objectdata.attrib = + attribute entityref { xsd:ENTITY }?, + attribute fileref { text }?, + attribute format { notation.class }?, + attribute srccredit { text }?, + local.objectdata.attrib +local.videodata.attrib = empty +videodata.role.attrib = role.attrib +# doc:Pointer to external video data. +videodata = element videodata { videodata.attlist, empty } +# end of videodata.element + +# Width: Same as CALS reprowid (desired width) + +# Depth: Same as CALS reprodep (desired depth) + +# Align: Same as CALS hplace with 'none' removed; #IMPLIED means +# application-specific + +# Scale: Conflation of CALS hscale and vscale + +# Scalefit: Same as CALS scalefit +videodata.attlist &= + attribute width { text }?, + attribute contentwidth { text }?, + attribute depth { text }?, + attribute contentdepth { text }?, + attribute align { "left" | "right" | "center" }?, + attribute valign { "top" | "middle" | "bottom" }?, + attribute scale { text }?, + attribute scalefit { yesorno.attvals }?, + objectdata.attrib, + common.attrib, + videodata.role.attrib, + local.videodata.attrib +# end of videodata.attlist + +# end of videodata.module +local.audiodata.attrib = empty +audiodata.role.attrib = role.attrib +# doc:Pointer to external audio data. +audiodata = element audiodata { audiodata.attlist, empty } +# end of audiodata.element +audiodata.attlist &= + objectdata.attrib, + common.attrib, + audiodata.role.attrib, + local.audiodata.attrib +# end of audiodata.attlist + +# end of audiodata.module +local.imagedata.attrib = empty +imagedata.role.attrib = role.attrib +# doc:Pointer to external image data. +imagedata = element imagedata { imagedata.attlist, empty } +# end of imagedata.element + +# Width: Same as CALS reprowid (desired width) + +# Depth: Same as CALS reprodep (desired depth) + +# Align: Same as CALS hplace with 'none' removed; #IMPLIED means +# application-specific + +# Scale: Conflation of CALS hscale and vscale + +# Scalefit: Same as CALS scalefit +imagedata.attlist &= + attribute width { text }?, + attribute contentwidth { text }?, + attribute depth { text }?, + attribute contentdepth { text }?, + attribute align { "left" | "right" | "center" }?, + attribute valign { "top" | "middle" | "bottom" }?, + attribute scale { text }?, + attribute scalefit { yesorno.attvals }?, + objectdata.attrib, + common.attrib, + imagedata.role.attrib, + local.imagedata.attrib +# end of imagedata.attlist + +# end of imagedata.module +local.textdata.attrib = empty +textdata.role.attrib = role.attrib +# doc:Pointer to external text data. +textdata = element textdata { textdata.attlist, empty } +# end of textdata.element +textdata.attlist &= + attribute encoding { text }?, + objectdata.attrib, + common.attrib, + textdata.role.attrib, + local.textdata.attrib +# end of textdata.attlist + +# end of textdata.module +local.mediaobjectco.attrib = empty +mediaobjectco.role.attrib = role.attrib +# doc:A media object that contains callouts. +mediaobjectco = + element mediaobjectco { + mediaobjectco.attlist, + objectinfo?, + imageobjectco, + (imageobjectco | textobject)* + } +# end of mediaobjectco.element +mediaobjectco.attlist &= + common.attrib, mediaobjectco.role.attrib, local.mediaobjectco.attrib +# end of mediaobjectco.attlist + +# end of mediaobjectco.module +local.imageobjectco.attrib = empty +imageobjectco.role.attrib = role.attrib +# doc:A wrapper for an image object with callouts. +imageobjectco = + element imageobjectco { + imageobjectco.attlist, areaspec, imageobject, calloutlist* + } +# end of imageobjectco.element +imageobjectco.attlist &= + common.attrib, imageobjectco.role.attrib, local.imageobjectco.attrib +# end of imageobjectco.attlist + +# end of imageobjectco.module + +# end of mediaobject.content.module + +# Equations ........................ + +# This PE provides a mechanism for replacing equation content, + +# perhaps adding a new or different model (e.g., MathML) +equation.content = alt?, (graphic+ | mediaobject+ | mathphrase+) +inlineequation.content = + alt?, (graphic+ | inlinemediaobject+ | mathphrase+) +local.equation.attrib = empty +equation.role.attrib = role.attrib +# doc:A displayed mathematical equation. +equation = + element equation { + equation.attlist, + blockinfo?, + formalobject.title.content?, + (informalequation | equation.content) + } +# end of equation.element +equation.attlist &= + attribute floatstyle { text }?, + label.attrib, + common.attrib, + equation.role.attrib, + local.equation.attrib +# end of equation.attlist + +# end of equation.module +local.informalequation.attrib = empty +informalequation.role.attrib = role.attrib +# doc:A displayed mathematical equation without a title. +informalequation = + element informalequation { + informalequation.attlist, blockinfo?, equation.content + } +# end of informalequation.element +informalequation.attlist &= + attribute floatstyle { text }?, + common.attrib, + informalequation.role.attrib, + local.informalequation.attrib +# end of informalequation.attlist + +# end of informalequation.module +local.inlineequation.attrib = empty +inlineequation.role.attrib = role.attrib +# doc:A mathematical equation or expression occurring inline. +inlineequation = + element inlineequation { + inlineequation.attlist, inlineequation.content + } +# end of inlineequation.element +inlineequation.attlist &= + common.attrib, inlineequation.role.attrib, local.inlineequation.attrib +# end of inlineequation.attlist + +# end of inlineequation.module +local.alt.attrib = empty +alt.role.attrib = role.attrib +# doc:Text representation for a graphical element. +alt = element alt { alt.attlist, text } +# end of alt.element +alt.attlist &= common.attrib, alt.role.attrib, local.alt.attrib +# end of alt.attlist + +# end of alt.module +local.mathphrase.attrib = empty +mathphrase.role.attrib = role.attrib +# doc:A mathematical phrase, an expression that can be represented with ordinary text and a small amount of markup. +mathphrase = + element mathphrase { + mathphrase.attlist, (text | subscript | superscript | emphasis)* + } +# end of mathphrase.element +mathphrase.attlist &= + common.attrib, mathphrase.role.attrib, local.mathphrase.attrib +# end of mathphrase.attlist + +# end of mathphrase.module + +# Tables ........................... + +# Choose a table model. CALS or OASIS XML Exchange + +# Do we allow the HTML table model as well? + +# ====================================================== + +# xhtmltbl.mod defines HTML tables and sets parameter +# entities so that, when the CALS table module is read, +# we end up allowing any table to be CALS or HTML. +# i.e. This include must come first! + +# ====================================================== +include "htmltblx.rnc" +# end of allow.html.tables + +# Add label and role attributes to table and informaltable + +# Add common attributes to Table, TGroup, TBody, THead, TFoot, Row, +# EntryTbl, and Entry (and InformalTable element). + +# Content model for Table. + +# Allow either objects or inlines; beware of REs between elements. + +# Reference CALS Table Model +include "calstblx.rnc" +# end of table.module + +# Note that InformalTable is dependent on some of the entity +# declarations that customize Table. +local.informaltable.attrib = empty +# the following entity may have been declared by the XHTML table module + +# doc:A table without a title. +informaltable = + element informaltable { + informaltable.attlist, blockinfo?, informal.tbl.table.mdl + } +# end of informaltable.element + +# Frame, Colsep, and Rowsep must be repeated because +# they are not in entities in the table module. + +# includes TabStyle, ToCentry, ShortEntry, +# Orient, PgWide + +# includes Label + +# includes common attributes +informaltable.attlist &= + attribute frame { tbl.frame.attval }?, + attribute colsep { yesorno.attvals }?, + attribute rowsep { yesorno.attvals }?, + common.table.attribs, + tbl.table.att, + local.informaltable.attrib +# end of informaltable.attlist + +# end of informaltable.module +local.caption.attrib = empty +caption.role.attrib = role.attrib +# doc:A caption. +caption = element caption { caption.attlist, (text | textobject.mix)* } +# end of caption.element + +# attrs comes from HTML tables ... + +# common.attrib, but without ID because ID is in attrs +caption.attlist.content = + caption.role.attrib, + attrs, + attribute align { "top" | "bottom" | "left" | "right" }?, + local.caption.attrib +caption.attlist &= caption.attlist.content +# end of caption.attlist + +# end of caption.module + +# ...................................................................... + +# Synopses ............................................................. + +# Synopsis ......................... +local.synopsis.attrib = empty +synopsis.role.attrib = role.attrib +# doc:A general-purpose element for representing the syntax of commands or functions. +synopsis = + element synopsis { + synopsis.attlist, + (para.char.mix + | graphic + | mediaobject + | co + | coref + | textobject + | lineannotation)* + } +# end of synopsis.element +synopsis.attlist &= + label.attrib, + linespecific.attrib, + common.attrib, + synopsis.role.attrib, + local.synopsis.attrib +# end of synopsis.attlist + +# LineAnnotation (defined in the Inlines section, below) + +# end of synopsis.module + +# CmdSynopsis ...................... +local.cmdsynopsis.attrib = empty +cmdsynopsis.role.attrib = role.attrib +# doc:A syntax summary for a software command. +cmdsynopsis = + element cmdsynopsis { + cmdsynopsis.attlist, (command | arg | group | sbr)+, synopfragment* + } +# end of cmdsynopsis.element + +# Sepchar: Character that should separate command and all +# top-level arguments; alternate value might be e.g., Δ +cmdsynopsis.attlist &= + label.attrib, + [ a:defaultValue = " " ] attribute sepchar { text }?, + attribute cmdlength { text }?, + common.attrib, + cmdsynopsis.role.attrib, + local.cmdsynopsis.attrib +# end of cmdsynopsis.attlist + +# end of cmdsynopsis.module +local.arg.attrib = empty +arg.role.attrib = role.attrib +# doc:An argument in a CmdSynopsis. +arg = + element arg { + arg.attlist, + (text + | arg + | group + | option + | synopfragmentref + | replaceable + | sbr)* + } +# end of arg.element + +# Choice: Whether Arg must be supplied: Opt (optional to +# supply, e.g. [arg]; the default), Req (required to supply, +# e.g. {arg}), or Plain (required to supply, e.g. arg) + +# Rep: whether Arg is repeatable: Norepeat (e.g. arg without +# ellipsis; the default), or Repeat (e.g. arg...) +arg.attlist &= + [ a:defaultValue = "opt" ] + attribute choice { "opt" | "req" | "plain" }?, + [ a:defaultValue = "norepeat" ] + attribute rep { "norepeat" | "repeat" }?, + common.attrib, + arg.role.attrib, + local.arg.attrib +# end of arg.attlist + +# end of arg.module +local.group.attrib = empty +group.role.attrib = role.attrib +# doc:A group of elements in a CmdSynopsis. +group = + element group { + group.attlist, + (arg | group | option | synopfragmentref | replaceable | sbr)+ + } +# end of group.element + +# Choice: Whether Group must be supplied: Opt (optional to +# supply, e.g. [g1|g2|g3]; the default), Req (required to +# supply, e.g. {g1|g2|g3}), Plain (required to supply, +# e.g. g1|g2|g3), OptMult (can supply zero or more, e.g. +# [[g1|g2|g3]]), or ReqMult (must supply one or more, e.g. +# {{g1|g2|g3}}) + +# Rep: whether Group is repeatable: Norepeat (e.g. group +# without ellipsis; the default), or Repeat (e.g. group...) +group.attlist &= + [ a:defaultValue = "opt" ] + attribute choice { "opt" | "req" | "plain" }?, + [ a:defaultValue = "norepeat" ] + attribute rep { "norepeat" | "repeat" }?, + common.attrib, + group.role.attrib, + local.group.attrib +# end of group.attlist + +# end of group.module +local.sbr.attrib = empty +# Synopsis break +sbr.role.attrib = role.attrib +# doc:An explicit line break in a command synopsis. +sbr = element sbr { sbr.attlist, empty } +# end of sbr.element +sbr.attlist &= common.attrib, sbr.role.attrib, local.sbr.attrib +# end of sbr.attlist + +# end of sbr.module +local.synopfragmentref.attrib = empty +synopfragmentref.role.attrib = role.attrib +# doc:A reference to a fragment of a command synopsis. +synopfragmentref = + element synopfragmentref { synopfragmentref.attlist, text } +# end of synopfragmentref.element + +# to SynopFragment of complex synopsis +# material for separate referencing +synopfragmentref.attlist &= + linkendreq.attrib, + common.attrib, + synopfragmentref.role.attrib, + local.synopfragmentref.attrib +# end of synopfragmentref.attlist + +# end of synopfragmentref.module +local.synopfragment.attrib = empty +synopfragment.role.attrib = role.attrib +# doc:A portion of a CmdSynopsis broken out from the main body of the synopsis. +synopfragment = + element synopfragment { synopfragment.attlist, (arg | group)+ } +# end of synopfragment.element +synopfragment.attlist &= + idreq.common.attrib, + synopfragment.role.attrib, + local.synopfragment.attrib +# end of synopfragment.attlist + +# end of synopfragment.module + +# Command (defined in the Inlines section, below) + +# Option (defined in the Inlines section, below) + +# Replaceable (defined in the Inlines section, below) + +# end of cmdsynopsis.content.module + +# FuncSynopsis ..................... +local.funcsynopsis.attrib = empty +funcsynopsis.role.attrib = role.attrib +# doc:The syntax summary for a function definition. +funcsynopsis = + element funcsynopsis { + funcsynopsis.attlist, (funcsynopsisinfo | funcprototype)+ + } +# end of funcsynopsis.element +funcsynopsis.attlist &= + label.attrib, + common.attrib, + funcsynopsis.role.attrib, + local.funcsynopsis.attrib +# end of funcsynopsis.attlist + +# end of funcsynopsis.module +local.funcsynopsisinfo.attrib = empty +funcsynopsisinfo.role.attrib = role.attrib +# doc:Information supplementing the FuncDefs of a FuncSynopsis. +funcsynopsisinfo = + element funcsynopsisinfo { + funcsynopsisinfo.attlist, + (cptr.char.mix | textobject | lineannotation)* + } +# end of funcsynopsisinfo.element +funcsynopsisinfo.attlist &= + linespecific.attrib, + common.attrib, + funcsynopsisinfo.role.attrib, + local.funcsynopsisinfo.attrib +# end of funcsynopsisinfo.attlist + +# end of funcsynopsisinfo.module +local.funcprototype.attrib = empty +funcprototype.role.attrib = role.attrib +# doc:The prototype of a function. +funcprototype = + element funcprototype { + funcprototype.attlist, + modifier*, + funcdef, + (void | varargs | (paramdef+, varargs?)), + modifier* + } +# end of funcprototype.element +funcprototype.attlist &= + common.attrib, funcprototype.role.attrib, local.funcprototype.attrib +# end of funcprototype.attlist + +# end of funcprototype.module +local.funcdef.attrib = empty +funcdef.role.attrib = role.attrib +# doc:A function (subroutine) name and its return type. +funcdef = + element funcdef { + funcdef.attlist, (text | type | replaceable | function)* + } +# end of funcdef.element +funcdef.attlist &= + common.attrib, funcdef.role.attrib, local.funcdef.attrib +# end of funcdef.attlist + +# end of funcdef.module +local.void.attrib = empty +void.role.attrib = role.attrib +# doc:An empty element in a function synopsis indicating that the function in question takes no arguments. +void = element void { void.attlist, empty } +# end of void.element +void.attlist &= common.attrib, void.role.attrib, local.void.attrib +# end of void.attlist + +# end of void.module +local.varargs.attrib = empty +varargs.role.attrib = role.attrib +# doc:An empty element in a function synopsis indicating a variable number of arguments. +varargs = element varargs { varargs.attlist, empty } +# end of varargs.element +varargs.attlist &= + common.attrib, varargs.role.attrib, local.varargs.attrib +# end of varargs.attlist + +# end of varargs.module + +# Processing assumes that only one Parameter will appear in a +# ParamDef, and that FuncParams will be used at most once, for +# providing information on the "inner parameters" for parameters that +# are pointers to functions. +local.paramdef.attrib = empty +paramdef.role.attrib = role.attrib +# doc:Information about a function parameter in a programming language. +paramdef = + element paramdef { + paramdef.attlist, + (text | initializer | type | replaceable | parameter | funcparams)* + } +# end of paramdef.element +paramdef.attlist &= + attribute choice { "opt" | "req" }?, + common.attrib, + paramdef.role.attrib, + local.paramdef.attrib +# end of paramdef.attlist + +# end of paramdef.module +local.funcparams.attrib = empty +funcparams.role.attrib = role.attrib +# doc:Parameters for a function referenced through a function pointer in a synopsis. +funcparams = element funcparams { funcparams.attlist, cptr.char.mix* } +# end of funcparams.element +funcparams.attlist &= + common.attrib, funcparams.role.attrib, local.funcparams.attrib +# end of funcparams.attlist + +# end of funcparams.module + +# LineAnnotation (defined in the Inlines section, below) + +# Replaceable (defined in the Inlines section, below) + +# Function (defined in the Inlines section, below) + +# Parameter (defined in the Inlines section, below) + +# end of funcsynopsis.content.module + +# ClassSynopsis ..................... +local.classsynopsis.attrib = empty +classsynopsis.role.attrib = role.attrib +# doc:The syntax summary for a class definition. +classsynopsis = + element classsynopsis { + classsynopsis.attlist, + (ooclass | oointerface | ooexception)+, + (classsynopsisinfo | fieldsynopsis | method.synop.class)* + } +# end of classsynopsis.element +classsynopsis.attlist &= + attribute language { text }?, + [ a:defaultValue = "class" ] + attribute class { "class" | "interface" }?, + common.attrib, + classsynopsis.role.attrib, + local.classsynopsis.attrib +# end of classsynopsis.attlist + +# end of classsynopsis.module +local.classsynopsisinfo.attrib = empty +classsynopsisinfo.role.attrib = role.attrib +# doc:Information supplementing the contents of a ClassSynopsis. +classsynopsisinfo = + element classsynopsisinfo { + classsynopsisinfo.attlist, + (cptr.char.mix | textobject | lineannotation)* + } +# end of classsynopsisinfo.element +classsynopsisinfo.attlist &= + linespecific.attrib, + common.attrib, + classsynopsisinfo.role.attrib, + local.classsynopsisinfo.attrib +# end of classsynopsisinfo.attlist + +# end of classsynopsisinfo.module +local.ooclass.attrib = empty +ooclass.role.attrib = role.attrib +# doc:A class in an object-oriented programming language. +ooclass = + element ooclass { ooclass.attlist, (modifier | package)*, classname } +# end of ooclass.element +ooclass.attlist &= + common.attrib, ooclass.role.attrib, local.ooclass.attrib +# end of ooclass.attlist + +# end of ooclass.module +local.oointerface.attrib = empty +oointerface.role.attrib = role.attrib +# doc:An interface in an object-oriented programming language. +oointerface = + element oointerface { + oointerface.attlist, (modifier | package)*, interfacename + } +# end of oointerface.element +oointerface.attlist &= + common.attrib, oointerface.role.attrib, local.oointerface.attrib +# end of oointerface.attlist + +# end of oointerface.module +local.ooexception.attrib = empty +ooexception.role.attrib = role.attrib +# doc:An exception in an object-oriented programming language. +ooexception = + element ooexception { + ooexception.attlist, (modifier | package)*, exceptionname + } +# end of ooexception.element +ooexception.attlist &= + common.attrib, ooexception.role.attrib, local.ooexception.attrib +# end of ooexception.attlist + +# end of ooexception.module +local.modifier.attrib = empty +modifier.role.attrib = role.attrib +# doc:Modifiers in a synopsis. +modifier = element modifier { modifier.attlist, smallcptr.char.mix* } +# end of modifier.element +modifier.attlist &= + common.attrib, modifier.role.attrib, local.modifier.attrib +# end of modifier.attlist + +# end of modifier.module +local.interfacename.attrib = empty +interfacename.role.attrib = role.attrib +# doc:The name of an interface. +interfacename = + element interfacename { interfacename.attlist, cptr.char.mix* } +# end of interfacename.element +interfacename.attlist &= + common.attrib, interfacename.role.attrib, local.interfacename.attrib +# end of interfacename.attlist + +# end of interfacename.module +local.exceptionname.attrib = empty +exceptionname.role.attrib = role.attrib +# doc:The name of an exception. +exceptionname = + element exceptionname { exceptionname.attlist, smallcptr.char.mix* } +# end of exceptionname.element +exceptionname.attlist &= + common.attrib, exceptionname.role.attrib, local.exceptionname.attrib +# end of exceptionname.attlist + +# end of exceptionname.module +local.fieldsynopsis.attrib = empty +fieldsynopsis.role.attrib = role.attrib +# doc:The name of a field in a class definition. +fieldsynopsis = + element fieldsynopsis { + fieldsynopsis.attlist, modifier*, type?, varname, initializer? + } +# end of fieldsynopsis.element +fieldsynopsis.attlist &= + attribute language { text }?, + common.attrib, + fieldsynopsis.role.attrib, + local.fieldsynopsis.attrib +# end of fieldsynopsis.attlist + +# end of fieldsynopsis.module +local.initializer.attrib = empty +initializer.role.attrib = role.attrib +# doc:The initializer for a FieldSynopsis. +initializer = + element initializer { initializer.attlist, smallcptr.char.mix* } +# end of initializer.element +initializer.attlist &= + common.attrib, initializer.role.attrib, local.initializer.attrib +# end of initializer.attlist + +# end of initializer.module +local.constructorsynopsis.attrib = empty +constructorsynopsis.role.attrib = role.attrib +# doc:A syntax summary for a constructor. +constructorsynopsis = + element constructorsynopsis { + constructorsynopsis.attlist, + modifier*, + methodname?, + (methodparam+ | void?), + exceptionname* + } +# end of constructorsynopsis.element +constructorsynopsis.attlist &= + attribute language { text }?, + common.attrib, + constructorsynopsis.role.attrib, + local.constructorsynopsis.attrib +# end of constructorsynopsis.attlist + +# end of constructorsynopsis.module +local.destructorsynopsis.attrib = empty +destructorsynopsis.role.attrib = role.attrib +# doc:A syntax summary for a destructor. +destructorsynopsis = + element destructorsynopsis { + destructorsynopsis.attlist, + modifier*, + methodname?, + (methodparam+ | void?), + exceptionname* + } +# end of destructorsynopsis.element +destructorsynopsis.attlist &= + attribute language { text }?, + common.attrib, + destructorsynopsis.role.attrib, + local.destructorsynopsis.attrib +# end of destructorsynopsis.attlist + +# end of destructorsynopsis.module +local.methodsynopsis.attrib = empty +methodsynopsis.role.attrib = role.attrib +# doc:A syntax summary for a method. +methodsynopsis = + element methodsynopsis { + methodsynopsis.attlist, + modifier*, + (type | void)?, + methodname, + (methodparam+ | void?), + exceptionname*, + modifier* + } +# end of methodsynopsis.element +methodsynopsis.attlist &= + attribute language { text }?, + common.attrib, + methodsynopsis.role.attrib, + local.methodsynopsis.attrib +# end of methodsynopsis.attlist + +# end of methodsynopsis.module +local.methodname.attrib = empty +methodname.role.attrib = role.attrib +# doc:The name of a method. +methodname = + element methodname { methodname.attlist, smallcptr.char.mix* } +# end of methodname.element +methodname.attlist &= + common.attrib, methodname.role.attrib, local.methodname.attrib +# end of methodname.attlist + +# end of methodname.module +local.methodparam.attrib = empty +methodparam.role.attrib = role.attrib +# doc:Parameters to a method. +methodparam = + element methodparam { + methodparam.attlist, + modifier*, + type?, + ((parameter, initializer?) | funcparams), + modifier* + } +# end of methodparam.element +methodparam.attlist &= + [ a:defaultValue = "req" ] + attribute choice { "opt" | "req" | "plain" }?, + [ a:defaultValue = "norepeat" ] + attribute rep { "norepeat" | "repeat" }?, + common.attrib, + methodparam.role.attrib, + local.methodparam.attrib +# end of methodparam.attlist + +# end of methodparam.module + +# end of classsynopsis.content.module + +# ...................................................................... + +# Document information entities and elements ........................... + +# The document information elements include some elements that are +# currently used only in the document hierarchy module. They are +# defined here so that they will be available for use in customized +# document hierarchies. + +# .................................. + +# Ackno ............................ +local.ackno.attrib = empty +ackno.role.attrib = role.attrib +# doc:Acknowledgements in an Article. +ackno = element ackno { ackno.attlist, docinfo.char.mix* } +# end of ackno.element +ackno.attlist &= common.attrib, ackno.role.attrib, local.ackno.attrib +# end of ackno.attlist + +# end of ackno.module + +# Address .......................... +local.address.attrib = empty +address.role.attrib = role.attrib +# doc:A real-world address, generally a postal address. +address = + element address { + address.attlist, + (text + | personname + | person.ident.mix + | street + | pob + | postcode + | city + | state + | country + | phone + | fax + | email + | otheraddr)* + } +# end of address.element +address.attlist &= + linespecific.attrib, + common.attrib, + address.role.attrib, + local.address.attrib +# end of address.attlist + +# end of address.module +local.street.attrib = empty +street.role.attrib = role.attrib +# doc:A street address in an address. +street = element street { street.attlist, docinfo.char.mix* } +# end of street.element +street.attlist &= common.attrib, street.role.attrib, local.street.attrib +# end of street.attlist + +# end of street.module +local.pob.attrib = empty +pob.role.attrib = role.attrib +# doc:A post office box in an address. +pob = element pob { pob.attlist, docinfo.char.mix* } +# end of pob.element +pob.attlist &= common.attrib, pob.role.attrib, local.pob.attrib +# end of pob.attlist + +# end of pob.module +local.postcode.attrib = empty +postcode.role.attrib = role.attrib +# doc:A postal code in an address. +postcode = element postcode { postcode.attlist, docinfo.char.mix* } +# end of postcode.element +postcode.attlist &= + common.attrib, postcode.role.attrib, local.postcode.attrib +# end of postcode.attlist + +# end of postcode.module +local.city.attrib = empty +city.role.attrib = role.attrib +# doc:The name of a city in an address. +city = element city { city.attlist, docinfo.char.mix* } +# end of city.element +city.attlist &= common.attrib, city.role.attrib, local.city.attrib +# end of city.attlist + +# end of city.module +local.state.attrib = empty +state.role.attrib = role.attrib +# doc:A state or province in an address. +state = element state { state.attlist, docinfo.char.mix* } +# end of state.element +state.attlist &= common.attrib, state.role.attrib, local.state.attrib +# end of state.attlist + +# end of state.module +local.country.attrib = empty +country.role.attrib = role.attrib +# doc:The name of a country. +country = element country { country.attlist, docinfo.char.mix* } +# end of country.element +country.attlist &= + common.attrib, country.role.attrib, local.country.attrib +# end of country.attlist + +# end of country.module +local.phone.attrib = empty +phone.role.attrib = role.attrib +# doc:A telephone number. +phone = element phone { phone.attlist, docinfo.char.mix* } +# end of phone.element +phone.attlist &= common.attrib, phone.role.attrib, local.phone.attrib +# end of phone.attlist + +# end of phone.module +local.fax.attrib = empty +fax.role.attrib = role.attrib +# doc:A fax number. +fax = element fax { fax.attlist, docinfo.char.mix* } +# end of fax.element +fax.attlist &= common.attrib, fax.role.attrib, local.fax.attrib +# end of fax.attlist + +# end of fax.module + +# Email (defined in the Inlines section, below) +local.otheraddr.attrib = empty +otheraddr.role.attrib = role.attrib +# doc:Uncategorized information in address. +otheraddr = element otheraddr { otheraddr.attlist, docinfo.char.mix* } +# end of otheraddr.element +otheraddr.attlist &= + common.attrib, otheraddr.role.attrib, local.otheraddr.attrib +# end of otheraddr.attlist + +# end of otheraddr.module + +# end of address.content.module + +# Affiliation ...................... +local.affiliation.attrib = empty +affiliation.role.attrib = role.attrib +# doc:The institutional affiliation of an individual. +affiliation = + element affiliation { + affiliation.attlist, + shortaffil?, + jobtitle*, + orgname?, + orgdiv*, + address* + } +# end of affiliation.element +affiliation.attlist &= + common.attrib, affiliation.role.attrib, local.affiliation.attrib +# end of affiliation.attlist + +# end of affiliation.module +local.shortaffil.attrib = empty +shortaffil.role.attrib = role.attrib +# doc:A brief description of an affiliation. +shortaffil = + element shortaffil { shortaffil.attlist, docinfo.char.mix* } +# end of shortaffil.element +shortaffil.attlist &= + common.attrib, shortaffil.role.attrib, local.shortaffil.attrib +# end of shortaffil.attlist + +# end of shortaffil.module +local.jobtitle.attrib = empty +jobtitle.role.attrib = role.attrib +# doc:The title of an individual in an organization. +jobtitle = element jobtitle { jobtitle.attlist, docinfo.char.mix* } +# end of jobtitle.element +jobtitle.attlist &= + common.attrib, jobtitle.role.attrib, local.jobtitle.attrib +# end of jobtitle.attlist + +# end of jobtitle.module + +# OrgName (defined elsewhere in this section) +local.orgdiv.attrib = empty +orgdiv.role.attrib = role.attrib +# doc:A division of an organization. +orgdiv = element orgdiv { orgdiv.attlist, docinfo.char.mix* } +# end of orgdiv.element +orgdiv.attlist &= common.attrib, orgdiv.role.attrib, local.orgdiv.attrib +# end of orgdiv.attlist + +# end of orgdiv.module + +# Address (defined elsewhere in this section) + +# end of affiliation.content.module + +# ArtPageNums ...................... +local.artpagenums.attrib = empty +artpagenums.role.attrib = role.attrib +# doc:The page numbers of an article as published. +artpagenums = + element artpagenums { artpagenums.attlist, docinfo.char.mix* } +# end of artpagenums.element +artpagenums.attlist &= + common.attrib, artpagenums.role.attrib, local.artpagenums.attrib +# end of artpagenums.attlist + +# end of artpagenums.module + +# PersonName +local.personname.attrib = empty +personname.role.attrib = role.attrib +# doc:The personal name of an individual. +personname = + element personname { + personname.attlist, + (honorific | firstname | surname | lineage | othername)+ + } +# end of personname.element +personname.attlist &= + common.attrib, personname.role.attrib, local.personname.attrib +# end of personname.attlist + +# end of personname.module + +# Author ........................... +local.author.attrib = empty +author.role.attrib = role.attrib +# doc:The name of an individual author. +author = + element author { + author.attlist, + (personname | person.ident.mix+), + (personblurb | email | address)* + } +# end of author.element +author.attlist &= common.attrib, author.role.attrib, local.author.attrib +# end of author.attlist + +# (see "Personal identity elements" for %person.ident.mix;) + +# end of author.module + +# AuthorGroup ...................... +local.authorgroup.attrib = empty +authorgroup.role.attrib = role.attrib +# doc:Wrapper for author information when a document has multiple authors or collabarators. +authorgroup = + element authorgroup { + authorgroup.attlist, + (author | editor | collab | corpauthor | corpcredit | othercredit)+ + } +# end of authorgroup.element +authorgroup.attlist &= + common.attrib, authorgroup.role.attrib, local.authorgroup.attrib +# end of authorgroup.attlist + +# end of authorgroup.module + +# Author (defined elsewhere in this section) + +# Editor (defined elsewhere in this section) +local.collab.attrib = empty +collab.role.attrib = role.attrib +# doc:Identifies a collaborator. +collab = element collab { collab.attlist, collabname, affiliation* } +# end of collab.element +collab.attlist &= common.attrib, collab.role.attrib, local.collab.attrib +# end of collab.attlist + +# end of collab.module +local.collabname.attrib = empty +collabname.role.attrib = role.attrib +# doc:The name of a collaborator. +collabname = + element collabname { collabname.attlist, docinfo.char.mix* } +# end of collabname.element +collabname.attlist &= + common.attrib, collabname.role.attrib, local.collabname.attrib +# end of collabname.attlist + +# end of collabname.module + +# Affiliation (defined elsewhere in this section) + +# end of collab.content.module + +# CorpAuthor (defined elsewhere in this section) + +# OtherCredit (defined elsewhere in this section) + +# end of authorgroup.content.module + +# AuthorInitials ................... +local.authorinitials.attrib = empty +authorinitials.role.attrib = role.attrib +# doc:The initials or other short identifier for an author. +authorinitials = + element authorinitials { authorinitials.attlist, docinfo.char.mix* } +# end of authorinitials.element +authorinitials.attlist &= + common.attrib, authorinitials.role.attrib, local.authorinitials.attrib +# end of authorinitials.attlist + +# end of authorinitials.module + +# ConfGroup ........................ +local.confgroup.attrib = empty +confgroup.role.attrib = role.attrib +# doc:A wrapper for document meta-information about a conference. +confgroup = + element confgroup { + confgroup.attlist, + (confdates | conftitle | confnum | address | confsponsor)* + } +# end of confgroup.element +confgroup.attlist &= + common.attrib, confgroup.role.attrib, local.confgroup.attrib +# end of confgroup.attlist + +# end of confgroup.module +local.confdates.attrib = empty +confdates.role.attrib = role.attrib +# doc:The dates of a conference for which a document was written. +confdates = element confdates { confdates.attlist, docinfo.char.mix* } +# end of confdates.element +confdates.attlist &= + common.attrib, confdates.role.attrib, local.confdates.attrib +# end of confdates.attlist + +# end of confdates.module +local.conftitle.attrib = empty +conftitle.role.attrib = role.attrib +# doc:The title of a conference for which a document was written. +conftitle = element conftitle { conftitle.attlist, docinfo.char.mix* } +# end of conftitle.element +conftitle.attlist &= + common.attrib, conftitle.role.attrib, local.conftitle.attrib +# end of conftitle.attlist + +# end of conftitle.module +local.confnum.attrib = empty +confnum.role.attrib = role.attrib +# doc:An identifier, frequently numerical, associated with a conference for which a document was written. +confnum = element confnum { confnum.attlist, docinfo.char.mix* } +# end of confnum.element +confnum.attlist &= + common.attrib, confnum.role.attrib, local.confnum.attrib +# end of confnum.attlist + +# end of confnum.module + +# Address (defined elsewhere in this section) +local.confsponsor.attrib = empty +confsponsor.role.attrib = role.attrib +# doc:The sponsor of a conference for which a document was written. +confsponsor = + element confsponsor { confsponsor.attlist, docinfo.char.mix* } +# end of confsponsor.element +confsponsor.attlist &= + common.attrib, confsponsor.role.attrib, local.confsponsor.attrib +# end of confsponsor.attlist + +# end of confsponsor.module + +# end of confgroup.content.module + +# ContractNum ...................... +local.contractnum.attrib = empty +contractnum.role.attrib = role.attrib +# doc:The contract number of a document. +contractnum = + element contractnum { contractnum.attlist, docinfo.char.mix* } +# end of contractnum.element +contractnum.attlist &= + common.attrib, contractnum.role.attrib, local.contractnum.attrib +# end of contractnum.attlist + +# end of contractnum.module + +# ContractSponsor .................. +local.contractsponsor.attrib = empty +contractsponsor.role.attrib = role.attrib +# doc:The sponsor of a contract. +contractsponsor = + element contractsponsor { contractsponsor.attlist, docinfo.char.mix* } +# end of contractsponsor.element +contractsponsor.attlist &= + common.attrib, + contractsponsor.role.attrib, + local.contractsponsor.attrib +# end of contractsponsor.attlist + +# end of contractsponsor.module + +# Copyright ........................ +local.copyright.attrib = empty +copyright.role.attrib = role.attrib +# doc:Copyright information about a document. +copyright = element copyright { copyright.attlist, year+, holder* } +# end of copyright.element +copyright.attlist &= + common.attrib, copyright.role.attrib, local.copyright.attrib +# end of copyright.attlist + +# end of copyright.module +local.year.attrib = empty +year.role.attrib = role.attrib +# doc:The year of publication of a document. +year = element year { year.attlist, docinfo.char.mix* } +# end of year.element +year.attlist &= common.attrib, year.role.attrib, local.year.attrib +# end of year.attlist + +# end of year.module +local.holder.attrib = empty +holder.role.attrib = role.attrib +# doc:The name of the individual or organization that holds a copyright. +holder = element holder { holder.attlist, docinfo.char.mix* } +# end of holder.element +holder.attlist &= common.attrib, holder.role.attrib, local.holder.attrib +# end of holder.attlist + +# end of holder.module + +# end of copyright.content.module + +# CorpAuthor ....................... +local.corpauthor.attrib = empty +corpauthor.role.attrib = role.attrib +# doc:A corporate author, as opposed to an individual. +corpauthor = + element corpauthor { corpauthor.attlist, docinfo.char.mix* } +# end of corpauthor.element +corpauthor.attlist &= + common.attrib, corpauthor.role.attrib, local.corpauthor.attrib +# end of corpauthor.attlist + +# end of corpauthor.module + +# CorpCredit ...................... +local.corpcredit.attrib = empty +corpcredit.role.attrib = role.attrib +# doc:A corporation or organization credited in a document. +corpcredit = + element corpcredit { corpcredit.attlist, docinfo.char.mix* } +# end of corpcredit.element +corpcredit.attlist &= + attribute class { + "graphicdesigner" + | "productioneditor" + | "copyeditor" + | "technicaleditor" + | "translator" + | "other" + }?, + common.attrib, + corpcredit.role.attrib, + local.corpcredit.attrib +# end of corpcredit.attlist + +# end of corpcredit.module + +# CorpName ......................... +local.corpname.attrib = empty +# doc:The name of a corporation. +corpname = element corpname { corpname.attlist, docinfo.char.mix* } +# end of corpname.element +corpname.role.attrib = role.attrib +corpname.attlist &= + common.attrib, corpname.role.attrib, local.corpname.attrib +# end of corpname.attlist + +# end of corpname.module + +# Date ............................. +local.date.attrib = empty +date.role.attrib = role.attrib +# doc:The date of publication or revision of a document. +date = element date { date.attlist, docinfo.char.mix* } +# end of date.element +date.attlist &= common.attrib, date.role.attrib, local.date.attrib +# end of date.attlist + +# end of date.module + +# Edition .......................... +local.edition.attrib = empty +edition.role.attrib = role.attrib +# doc:The name or number of an edition of a document. +edition = element edition { edition.attlist, docinfo.char.mix* } +# end of edition.element +edition.attlist &= + common.attrib, edition.role.attrib, local.edition.attrib +# end of edition.attlist + +# end of edition.module + +# Editor ........................... +local.editor.attrib = empty +editor.role.attrib = role.attrib +# doc:The name of the editor of a document. +editor = + element editor { + editor.attlist, + (personname | person.ident.mix+), + (personblurb | email | address)* + } +# end of editor.element +editor.attlist &= common.attrib, editor.role.attrib, local.editor.attrib +# end of editor.attlist + +# (see "Personal identity elements" for %person.ident.mix;) + +# end of editor.module + +# ISBN ............................. +local.isbn.attrib = empty +isbn.role.attrib = role.attrib +# doc:The International Standard Book Number of a document. +isbn = element isbn { isbn.attlist, docinfo.char.mix* } +# end of isbn.element +isbn.attlist &= common.attrib, isbn.role.attrib, local.isbn.attrib +# end of isbn.attlist + +# end of isbn.module + +# ISSN ............................. +local.issn.attrib = empty +issn.role.attrib = role.attrib +# doc:The International Standard Serial Number of a periodical. +issn = element issn { issn.attlist, docinfo.char.mix* } +# end of issn.element +issn.attlist &= common.attrib, issn.role.attrib, local.issn.attrib +# end of issn.attlist + +# end of issn.module + +# BiblioId ................. +biblio.class.attrib = + attribute class { + "uri" + | "doi" + | "isbn" + | "isrn" + | "issn" + | "libraryofcongress" + | "pubnumber" + | "other" + }?, + attribute otherclass { text }? +local.biblioid.attrib = empty +biblioid.role.attrib = role.attrib +# doc:An identifier for a document. +biblioid = element biblioid { biblioid.attlist, docinfo.char.mix* } +# end of biblioid.element +biblioid.attlist &= + biblio.class.attrib, + common.attrib, + biblioid.role.attrib, + local.biblioid.attrib +# end of biblioid.attlist + +# end of biblioid.module + +# CiteBiblioId ................. +local.citebiblioid.attrib = empty +citebiblioid.role.attrib = role.attrib +# doc:A citation of a bibliographic identifier. +citebiblioid = + element citebiblioid { citebiblioid.attlist, docinfo.char.mix* } +# end of citebiblioid.element +citebiblioid.attlist &= + biblio.class.attrib, + common.attrib, + citebiblioid.role.attrib, + local.citebiblioid.attrib +# end of citebiblioid.attlist + +# end of citebiblioid.module + +# BiblioSource ................. +local.bibliosource.attrib = empty +bibliosource.role.attrib = role.attrib +# doc:The source of a document. +bibliosource = + element bibliosource { bibliosource.attlist, docinfo.char.mix* } +# end of bibliosource.element +bibliosource.attlist &= + biblio.class.attrib, + common.attrib, + bibliosource.role.attrib, + local.bibliosource.attrib +# end of bibliosource.attlist + +# end of bibliosource.module + +# BiblioRelation ................. +local.bibliorelation.attrib = empty +local.bibliorelation.types = notAllowed +bibliorelation.type.attrib = + attribute type { + "isversionof" + | "hasversion" + | "isreplacedby" + | "replaces" + | "isrequiredby" + | "requires" + | "ispartof" + | "haspart" + | "isreferencedby" + | "references" + | "isformatof" + | "hasformat" + | "othertype" + | local.bibliorelation.types + }?, + attribute othertype { text }? +bibliorelation.role.attrib = role.attrib +# doc:The relationship of a document to another. +bibliorelation = + element bibliorelation { bibliorelation.attlist, docinfo.char.mix* } +# end of bibliorelation.element +bibliorelation.attlist &= + biblio.class.attrib, + bibliorelation.type.attrib, + common.attrib, + bibliorelation.role.attrib, + local.bibliorelation.attrib +# end of bibliorelation.attlist + +# end of bibliorelation.module + +# BiblioCoverage ................. +local.bibliocoverage.attrib = empty +bibliocoverage.role.attrib = role.attrib +# doc:The spatial or temporal coverage of a document. +bibliocoverage = + element bibliocoverage { bibliocoverage.attlist, docinfo.char.mix* } +# end of bibliocoverage.element +bibliocoverage.attlist &= + attribute spatial { + "dcmipoint" | "iso3166" | "dcmibox" | "tgn" | "otherspatial" + }?, + attribute otherspatial { text }?, + attribute temporal { "dcmiperiod" | "w3c-dtf" | "othertemporal" }?, + attribute othertemporal { text }?, + common.attrib, + bibliocoverage.role.attrib, + local.bibliocoverage.attrib +# end of bibliocoverage.attlist + +# end of bibliocoverage.module + +# InvPartNumber .................... +local.invpartnumber.attrib = empty +invpartnumber.role.attrib = role.attrib +# doc:An inventory part number. +invpartnumber = + element invpartnumber { invpartnumber.attlist, docinfo.char.mix* } +# end of invpartnumber.element +invpartnumber.attlist &= + common.attrib, invpartnumber.role.attrib, local.invpartnumber.attrib +# end of invpartnumber.attlist + +# end of invpartnumber.module + +# IssueNum ......................... +local.issuenum.attrib = empty +issuenum.role.attrib = role.attrib +# doc:The number of an issue of a journal. +issuenum = element issuenum { issuenum.attlist, docinfo.char.mix* } +# end of issuenum.element +issuenum.attlist &= + common.attrib, issuenum.role.attrib, local.issuenum.attrib +# end of issuenum.attlist + +# end of issuenum.module + +# LegalNotice ...................... +local.legalnotice.attrib = empty +legalnotice.role.attrib = role.attrib +# doc:A statement of legal obligations or requirements. +legalnotice = + element legalnotice { + legalnotice.attlist, blockinfo?, title?, legalnotice.mix+ + } +# end of legalnotice.element +legalnotice.attlist &= + common.attrib, legalnotice.role.attrib, local.legalnotice.attrib +# end of legalnotice.attlist + +# end of legalnotice.module + +# ModeSpec ......................... +local.modespec.attrib = empty +modespec.role.attrib = role.attrib +# doc:Application-specific information necessary for the completion of an OLink. +modespec = element modespec { modespec.attlist, docinfo.char.mix* } +# end of modespec.element + +# Application: Type of action required for completion +# of the links to which the ModeSpec is relevant (e.g., +# retrieval query) +modespec.attlist &= + attribute application { notation.class }?, + common.attrib, + modespec.role.attrib, + local.modespec.attrib +# end of modespec.attlist + +# end of modespec.module + +# OrgName .......................... +local.orgname.attrib = empty +orgname.role.attrib = role.attrib +# doc:The name of an organization other than a corporation. +orgname = element orgname { orgname.attlist, docinfo.char.mix* } +# end of orgname.element +orgname.attlist &= + common.attrib, + attribute class { + "corporation" | "nonprofit" | "consortium" | "informal" | "other" + }?, + attribute otherclass { text }?, + orgname.role.attrib, + local.orgname.attrib +# end of orgname.attlist + +# end of orgname.module + +# OtherCredit ...................... +local.othercredit.attrib = empty +othercredit.role.attrib = role.attrib +# doc:A person or entity, other than an author or editor, credited in a document. +othercredit = + element othercredit { + othercredit.attlist, + (personname | person.ident.mix+), + (personblurb | email | address)* + } +# end of othercredit.element +othercredit.attlist &= + attribute class { + "graphicdesigner" + | "productioneditor" + | "copyeditor" + | "technicaleditor" + | "translator" + | "other" + }?, + common.attrib, + othercredit.role.attrib, + local.othercredit.attrib +# end of othercredit.attlist + +# (see "Personal identity elements" for %person.ident.mix;) + +# end of othercredit.module + +# PageNums ......................... +local.pagenums.attrib = empty +pagenums.role.attrib = role.attrib +# doc:The numbers of the pages in a book, for use in a bibliographic entry. +pagenums = element pagenums { pagenums.attlist, docinfo.char.mix* } +# end of pagenums.element +pagenums.attlist &= + common.attrib, pagenums.role.attrib, local.pagenums.attrib +# end of pagenums.attlist + +# end of pagenums.module + +# Personal identity elements ....... + +# These elements are used only within Author, Editor, and +# OtherCredit. +local.contrib.attrib = empty +contrib.role.attrib = role.attrib +# doc:A summary of the contributions made to a document by a credited source. +contrib = element contrib { contrib.attlist, docinfo.char.mix* } +# end of contrib.element +contrib.attlist &= + common.attrib, contrib.role.attrib, local.contrib.attrib +# end of contrib.attlist + +# end of contrib.module +local.firstname.attrib = empty +firstname.role.attrib = role.attrib +# doc:The first name of a person. +firstname = element firstname { firstname.attlist, docinfo.char.mix* } +# end of firstname.element +firstname.attlist &= + common.attrib, firstname.role.attrib, local.firstname.attrib +# end of firstname.attlist + +# end of firstname.module +local.honorific.attrib = empty +honorific.role.attrib = role.attrib +# doc:The title of a person. +honorific = element honorific { honorific.attlist, docinfo.char.mix* } +# end of honorific.element +honorific.attlist &= + common.attrib, honorific.role.attrib, local.honorific.attrib +# end of honorific.attlist + +# end of honorific.module +local.lineage.attrib = empty +lineage.role.attrib = role.attrib +# doc:The portion of a person's name indicating a relationship to ancestors. +lineage = element lineage { lineage.attlist, docinfo.char.mix* } +# end of lineage.element +lineage.attlist &= + common.attrib, lineage.role.attrib, local.lineage.attrib +# end of lineage.attlist + +# end of lineage.module +local.othername.attrib = empty +othername.role.attrib = role.attrib +# doc:A component of a persons name that is not a first name, surname, or lineage. +othername = element othername { othername.attlist, docinfo.char.mix* } +# end of othername.element +othername.attlist &= + common.attrib, othername.role.attrib, local.othername.attrib +# end of othername.attlist + +# end of othername.module +local.surname.attrib = empty +surname.role.attrib = role.attrib +# doc:A family name; in western cultures the last name. +surname = element surname { surname.attlist, docinfo.char.mix* } +# end of surname.element +surname.attlist &= + common.attrib, surname.role.attrib, local.surname.attrib +# end of surname.attlist + +# end of surname.module + +# end of person.ident.module + +# PrintHistory ..................... +local.printhistory.attrib = empty +printhistory.role.attrib = role.attrib +# doc:The printing history of a document. +printhistory = + element printhistory { printhistory.attlist, para.class+ } +# end of printhistory.element +printhistory.attlist &= + common.attrib, printhistory.role.attrib, local.printhistory.attrib +# end of printhistory.attlist + +# end of printhistory.module + +# ProductName ...................... +local.productname.attrib = empty +productname.role.attrib = role.attrib +# doc:The formal name of a product. +productname = + element productname { productname.attlist, para.char.mix* } +# end of productname.element + +# Class: More precisely identifies the item the element names +productname.attlist &= + [ a:defaultValue = "trade" ] + attribute class { "service" | "trade" | "registered" | "copyright" }?, + common.attrib, + productname.role.attrib, + local.productname.attrib +# end of productname.attlist + +# end of productname.module + +# ProductNumber .................... +local.productnumber.attrib = empty +productnumber.role.attrib = role.attrib +# doc:A number assigned to a product. +productnumber = + element productnumber { productnumber.attlist, docinfo.char.mix* } +# end of productnumber.element +productnumber.attlist &= + common.attrib, productnumber.role.attrib, local.productnumber.attrib +# end of productnumber.attlist + +# end of productnumber.module + +# PubDate .......................... +local.pubdate.attrib = empty +pubdate.role.attrib = role.attrib +# doc:The date of publication of a document. +pubdate = element pubdate { pubdate.attlist, docinfo.char.mix* } +# end of pubdate.element +pubdate.attlist &= + common.attrib, pubdate.role.attrib, local.pubdate.attrib +# end of pubdate.attlist + +# end of pubdate.module + +# Publisher ........................ +local.publisher.attrib = empty +publisher.role.attrib = role.attrib +# doc:The publisher of a document. +publisher = + element publisher { publisher.attlist, publishername, address* } +# end of publisher.element +publisher.attlist &= + common.attrib, publisher.role.attrib, local.publisher.attrib +# end of publisher.attlist + +# end of publisher.module +local.publishername.attrib = empty +publishername.role.attrib = role.attrib +# doc:The name of the publisher of a document. +publishername = + element publishername { publishername.attlist, docinfo.char.mix* } +# end of publishername.element +publishername.attlist &= + common.attrib, publishername.role.attrib, local.publishername.attrib +# end of publishername.attlist + +# end of publishername.module + +# Address (defined elsewhere in this section) + +# end of publisher.content.module + +# PubsNumber ....................... +local.pubsnumber.attrib = empty +pubsnumber.role.attrib = role.attrib +# doc:A number assigned to a publication other than an ISBN or ISSN or inventory part number. +pubsnumber = + element pubsnumber { pubsnumber.attlist, docinfo.char.mix* } +# end of pubsnumber.element +pubsnumber.attlist &= + common.attrib, pubsnumber.role.attrib, local.pubsnumber.attrib +# end of pubsnumber.attlist + +# end of pubsnumber.module + +# ReleaseInfo ...................... +local.releaseinfo.attrib = empty +releaseinfo.role.attrib = role.attrib +# doc:Information about a particular release of a document. +releaseinfo = + element releaseinfo { releaseinfo.attlist, docinfo.char.mix* } +# end of releaseinfo.element +releaseinfo.attlist &= + common.attrib, releaseinfo.role.attrib, local.releaseinfo.attrib +# end of releaseinfo.attlist + +# end of releaseinfo.module + +# RevHistory ....................... +local.revhistory.attrib = empty +revhistory.role.attrib = role.attrib +# doc:A history of the revisions to a document. +revhistory = element revhistory { revhistory.attlist, revision+ } +# end of revhistory.element +revhistory.attlist &= + common.attrib, revhistory.role.attrib, local.revhistory.attrib +# end of revhistory.attlist + +# end of revhistory.module +local.revision.attrib = empty +revision.role.attrib = role.attrib +# doc:An entry describing a single revision in the history of the revisions to a document. +revision = + element revision { + revision.attlist, + revnumber?, + date, + (author | authorinitials)*, + (revremark | revdescription)? + } +# end of revision.element +revision.attlist &= + common.attrib, revision.role.attrib, local.revision.attrib +# end of revision.attlist + +# end of revision.module +local.revnumber.attrib = empty +revnumber.role.attrib = role.attrib +# doc:A document revision number. +revnumber = element revnumber { revnumber.attlist, docinfo.char.mix* } +# end of revnumber.element +revnumber.attlist &= + common.attrib, revnumber.role.attrib, local.revnumber.attrib +# end of revnumber.attlist + +# end of revnumber.module + +# Date (defined elsewhere in this section) + +# AuthorInitials (defined elsewhere in this section) +local.revremark.attrib = empty +revremark.role.attrib = role.attrib +# doc:A description of a revision to a document. +revremark = element revremark { revremark.attlist, docinfo.char.mix* } +# end of revremark.element +revremark.attlist &= + common.attrib, revremark.role.attrib, local.revremark.attrib +# end of revremark.attlist + +# end of revremark.module +local.revdescription.attrib = empty +revdescription.role.attrib = role.attrib +# doc:A extended description of a revision to a document. +revdescription = + element revdescription { revdescription.attlist, revdescription.mix+ } +# end of revdescription.element +revdescription.attlist &= + common.attrib, revdescription.role.attrib, local.revdescription.attrib +# end of revdescription.attlist + +# end of revdescription.module + +# end of revhistory.content.module + +# SeriesVolNums .................... +local.seriesvolnums.attrib = empty +seriesvolnums.role.attrib = role.attrib +# doc:Numbers of the volumes in a series of books. +seriesvolnums = + element seriesvolnums { seriesvolnums.attlist, docinfo.char.mix* } +# end of seriesvolnums.element +seriesvolnums.attlist &= + common.attrib, seriesvolnums.role.attrib, local.seriesvolnums.attrib +# end of seriesvolnums.attlist + +# end of seriesvolnums.module + +# VolumeNum ........................ +local.volumenum.attrib = empty +volumenum.role.attrib = role.attrib +# doc:The volume number of a document in a set (as of books in a set or articles in a journal). +volumenum = element volumenum { volumenum.attlist, docinfo.char.mix* } +# end of volumenum.element +volumenum.attlist &= + common.attrib, volumenum.role.attrib, local.volumenum.attrib +# end of volumenum.attlist + +# end of volumenum.module + +# .................................. + +# end of docinfo.content.module + +# ...................................................................... + +# Inline, link, and ubiquitous elements ................................ + +# Technical and computer terms ......................................... +local.accel.attrib = empty +accel.role.attrib = role.attrib +# doc:A graphical user interface (GUI) keyboard shortcut. +accel = element accel { accel.attlist, smallcptr.char.mix* } +# end of accel.element +accel.attlist &= common.attrib, accel.role.attrib, local.accel.attrib +# end of accel.attlist + +# end of accel.module +local.action.attrib = empty +action.role.attrib = role.attrib +# doc:A response to a user event. +action = element action { action.attlist, cptr.char.mix* } +# end of action.element +action.attlist &= + moreinfo.attrib, + common.attrib, + action.role.attrib, + local.action.attrib +# end of action.attlist + +# end of action.module +local.application.attrib = empty +application.role.attrib = role.attrib +# doc:The name of a software program. +application = + element application { application.attlist, para.char.mix* } +# end of application.element +application.attlist &= + attribute class { "hardware" | "software" }?, + moreinfo.attrib, + common.attrib, + application.role.attrib, + local.application.attrib +# end of application.attlist + +# end of application.module +local.classname.attrib = empty +classname.role.attrib = role.attrib +# doc:The name of a class, in the object-oriented programming sense. +classname = element classname { classname.attlist, smallcptr.char.mix* } +# end of classname.element +classname.attlist &= + common.attrib, classname.role.attrib, local.classname.attrib +# end of classname.attlist + +# end of classname.module +local.package.attrib = empty +package.role.attrib = role.attrib +# doc:A package. +package = element package { package.attlist, smallcptr.char.mix* } +# end of package.element +package.attlist &= + common.attrib, package.role.attrib, local.package.attrib +# end of package.attlist + +# end of package.module +local.co.attrib = empty +# CO is a callout area of the LineColumn unit type (a single character +# position); the position is directly indicated by the location of CO. +co.role.attrib = role.attrib +# doc:The location of a callout embedded in text. +co = element co { co.attlist, empty } +# end of co.element + +# bug number/symbol override or initialization + +# to any related information +co.attlist &= + label.attrib, + linkends.attrib, + idreq.common.attrib, + co.role.attrib, + local.co.attrib +# end of co.attlist + +# end of co.module +local.coref.attrib = empty +# COREF is a reference to a CO +coref.role.attrib = role.attrib +# doc:A cross reference to a co. +coref = element coref { coref.attlist, empty } +# end of coref.element + +# bug number/symbol override or initialization + +# to any related information +coref.attlist &= + label.attrib, + linkendreq.attrib, + common.attrib, + coref.role.attrib, + local.coref.attrib +# end of coref.attlist + +# end of coref.module +local.command.attrib = empty +command.role.attrib = role.attrib +# doc:The name of an executable program or other software command. +command = element command { command.attlist, cptr.char.mix* } +# end of command.element +command.attlist &= + moreinfo.attrib, + common.attrib, + command.role.attrib, + local.command.attrib +# end of command.attlist + +# end of command.module +local.computeroutput.attrib = empty +computeroutput.role.attrib = role.attrib +# doc:Data, generally text, displayed or presented by a computer. +computeroutput = + element computeroutput { + computeroutput.attlist, (cptr.char.mix | co)* + } +# end of computeroutput.element +computeroutput.attlist &= + moreinfo.attrib, + common.attrib, + computeroutput.role.attrib, + local.computeroutput.attrib +# end of computeroutput.attlist + +# end of computeroutput.module +local.database.attrib = empty +database.role.attrib = role.attrib +# doc:The name of a database, or part of a database. +database = element database { database.attlist, cptr.char.mix* } +# end of database.element + +# Class: Type of database the element names; no default +database.attlist &= + attribute class { + "name" + | "table" + | "field" + | "key1" + | "key2" + | "record" + | "index" + | "view" + | "primarykey" + | "secondarykey" + | "foreignkey" + | "altkey" + | "procedure" + | "datatype" + | "constraint" + | "rule" + | "user" + | "group" + }?, + moreinfo.attrib, + common.attrib, + database.role.attrib, + local.database.attrib +# end of database.attlist + +# end of database.module +local.email.attrib = empty +email.role.attrib = role.attrib +# doc:An email address. +email = element email { email.attlist, docinfo.char.mix* } +# end of email.element +email.attlist &= common.attrib, email.role.attrib, local.email.attrib +# end of email.attlist + +# end of email.module +local.envar.attrib = empty +envar.role.attrib = role.attrib +# doc:A software environment variable. +envar = element envar { envar.attlist, smallcptr.char.mix* } +# end of envar.element +envar.attlist &= common.attrib, envar.role.attrib, local.envar.attrib +# end of envar.attlist + +# end of envar.module +local.errorcode.attrib = empty +errorcode.role.attrib = role.attrib +# doc:An error code. +errorcode = element errorcode { errorcode.attlist, smallcptr.char.mix* } +# end of errorcode.element +errorcode.attlist &= + moreinfo.attrib, + common.attrib, + errorcode.role.attrib, + local.errorcode.attrib +# end of errorcode.attlist + +# end of errorcode.module +local.errorname.attrib = empty +errorname.role.attrib = role.attrib +# doc:An error name. +errorname = element errorname { errorname.attlist, smallcptr.char.mix* } +# end of errorname.element +errorname.attlist &= + common.attrib, errorname.role.attrib, local.errorname.attrib +# end of errorname.attlist + +# end of errorname.module +local.errortext.attrib = empty +errortext.role.attrib = role.attrib +# doc:An error message.. +errortext = element errortext { errortext.attlist, smallcptr.char.mix* } +# end of errortext.element +errortext.attlist &= + common.attrib, errortext.role.attrib, local.errortext.attrib +# end of errortext.attlist + +# end of errortext.module +local.errortype.attrib = empty +errortype.role.attrib = role.attrib +# doc:The classification of an error message. +errortype = element errortype { errortype.attlist, smallcptr.char.mix* } +# end of errortype.element +errortype.attlist &= + common.attrib, errortype.role.attrib, local.errortype.attrib +# end of errortype.attlist + +# end of errortype.module +local.filename.attrib = empty +filename.role.attrib = role.attrib +# doc:The name of a file. +filename = element filename { filename.attlist, cptr.char.mix* } +# end of filename.element + +# Class: Type of filename the element names; no default + +# Path: Search path (possibly system-specific) in which +# file can be found +filename.attlist &= + attribute class { + "headerfile" + | "partition" + | "devicefile" + | "libraryfile" + | "directory" + | "extension" + | "symlink" + }?, + attribute path { text }?, + moreinfo.attrib, + common.attrib, + filename.role.attrib, + local.filename.attrib +# end of filename.attlist + +# end of filename.module +local.function.attrib = empty +function.role.attrib = role.attrib +# doc:The name of a function or subroutine, as in a programming language. +function = element function { function.attlist, cptr.char.mix* } +# end of function.element +function.attlist &= + moreinfo.attrib, + common.attrib, + function.role.attrib, + local.function.attrib +# end of function.attlist + +# end of function.module +local.guibutton.attrib = empty +guibutton.role.attrib = role.attrib +# doc:The text on a button in a GUI. +guibutton = + element guibutton { + guibutton.attlist, + (smallcptr.char.mix | accel | superscript | subscript)* + } +# end of guibutton.element +guibutton.attlist &= + moreinfo.attrib, + common.attrib, + guibutton.role.attrib, + local.guibutton.attrib +# end of guibutton.attlist + +# end of guibutton.module +local.guiicon.attrib = empty +guiicon.role.attrib = role.attrib +# doc:Graphic and/or text appearing as a icon in a GUI. +guiicon = + element guiicon { + guiicon.attlist, + (smallcptr.char.mix | accel | superscript | subscript)* + } +# end of guiicon.element +guiicon.attlist &= + moreinfo.attrib, + common.attrib, + guiicon.role.attrib, + local.guiicon.attrib +# end of guiicon.attlist + +# end of guiicon.module +local.guilabel.attrib = empty +guilabel.role.attrib = role.attrib +# doc:The text of a label in a GUI. +guilabel = + element guilabel { + guilabel.attlist, + (smallcptr.char.mix | accel | superscript | subscript)* + } +# end of guilabel.element +guilabel.attlist &= + moreinfo.attrib, + common.attrib, + guilabel.role.attrib, + local.guilabel.attrib +# end of guilabel.attlist + +# end of guilabel.module +local.guimenu.attrib = empty +guimenu.role.attrib = role.attrib +# doc:The name of a menu in a GUI. +guimenu = + element guimenu { + guimenu.attlist, + (smallcptr.char.mix | accel | superscript | subscript)* + } +# end of guimenu.element +guimenu.attlist &= + moreinfo.attrib, + common.attrib, + guimenu.role.attrib, + local.guimenu.attrib +# end of guimenu.attlist + +# end of guimenu.module +local.guimenuitem.attrib = empty +guimenuitem.role.attrib = role.attrib +# doc:The name of a terminal menu item in a GUI. +guimenuitem = + element guimenuitem { + guimenuitem.attlist, + (smallcptr.char.mix | accel | superscript | subscript)* + } +# end of guimenuitem.element +guimenuitem.attlist &= + moreinfo.attrib, + common.attrib, + guimenuitem.role.attrib, + local.guimenuitem.attrib +# end of guimenuitem.attlist + +# end of guimenuitem.module +local.guisubmenu.attrib = empty +guisubmenu.role.attrib = role.attrib +# doc:The name of a submenu in a GUI. +guisubmenu = + element guisubmenu { + guisubmenu.attlist, + (smallcptr.char.mix | accel | superscript | subscript)* + } +# end of guisubmenu.element +guisubmenu.attlist &= + moreinfo.attrib, + common.attrib, + guisubmenu.role.attrib, + local.guisubmenu.attrib +# end of guisubmenu.attlist + +# end of guisubmenu.module +local.hardware.attrib = empty +hardware.role.attrib = role.attrib +# doc:A physical part of a computer system. +hardware = element hardware { hardware.attlist, cptr.char.mix* } +# end of hardware.element +hardware.attlist &= + moreinfo.attrib, + common.attrib, + hardware.role.attrib, + local.hardware.attrib +# end of hardware.attlist + +# end of hardware.module +local.interface.attrib = empty +interface.role.attrib = role.attrib +# doc:An element of a GUI. +interface = + element interface { interface.attlist, (smallcptr.char.mix | accel)* } +# end of interface.element + +# Class: Type of the Interface item; no default +interface.attlist &= + moreinfo.attrib, + common.attrib, + interface.role.attrib, + local.interface.attrib +# end of interface.attlist + +# end of interface.module +local.keycap.attrib = empty +keycap.role.attrib = role.attrib +# doc:The text printed on a key on a keyboard. +keycap = element keycap { keycap.attlist, cptr.char.mix* } +# end of keycap.element +keycap.attlist &= + attribute function { + "alt" + | "control" + | "shift" + | "meta" + | "escape" + | "enter" + | "tab" + | "backspace" + | "command" + | "option" + | "space" + | "delete" + | "insert" + | "up" + | "down" + | "left" + | "right" + | "home" + | "end" + | "pageup" + | "pagedown" + | "other" + }?, + attribute otherfunction { text }?, + moreinfo.attrib, + common.attrib, + keycap.role.attrib, + local.keycap.attrib +# end of keycap.attlist + +# end of keycap.module +local.keycode.attrib = empty +keycode.role.attrib = role.attrib +# doc:The internal, frequently numeric, identifier for a key on a keyboard. +keycode = element keycode { keycode.attlist, smallcptr.char.mix* } +# end of keycode.element +keycode.attlist &= + common.attrib, keycode.role.attrib, local.keycode.attrib +# end of keycode.attlist + +# end of keycode.module +local.keycombo.attrib = empty +keycombo.role.attrib = role.attrib +# doc:A combination of input actions. +keycombo = + element keycombo { + keycombo.attlist, (keycap | keycombo | keysym | mousebutton)+ + } +# end of keycombo.element +keycombo.attlist &= + keyaction.attrib, + moreinfo.attrib, + common.attrib, + keycombo.role.attrib, + local.keycombo.attrib +# end of keycombo.attlist + +# end of keycombo.module +local.keysym.attrib = empty +keysysm.role.attrib = role.attrib +# doc:The symbolic name of a key on a keyboard. +keysym = element keysym { keysym.attlist, smallcptr.char.mix* } +# end of keysym.element +keysym.attlist &= + common.attrib, keysysm.role.attrib, local.keysym.attrib +# end of keysym.attlist + +# end of keysym.module +local.lineannotation.attrib = empty +lineannotation.role.attrib = role.attrib +# doc:A comment on a line in a verbatim listing. +lineannotation = + element lineannotation { lineannotation.attlist, para.char.mix* } +# end of lineannotation.element +lineannotation.attlist &= + common.attrib, lineannotation.role.attrib, local.lineannotation.attrib +# end of lineannotation.attlist + +# end of lineannotation.module +local.literal.attrib = empty +literal.role.attrib = role.attrib +# doc:Inline text that is some literal value. +literal = element literal { literal.attlist, cptr.char.mix* } +# end of literal.element +literal.attlist &= + moreinfo.attrib, + common.attrib, + literal.role.attrib, + local.literal.attrib +# end of literal.attlist + +# end of literal.module +local.code.attrib = empty +code.role.attrib = role.attrib +# doc:An inline code fragment. +code = element code { code.attlist, cptr.char.mix* } +# end of code.element +code.attlist &= + attribute language { text }?, + common.attrib, + code.role.attrib, + local.code.attrib +# end of code.attlist + +# end of code.module +local.constant.attrib = empty +constant.role.attrib = role.attrib +# doc:A programming or system constant. +constant = element constant { constant.attlist, smallcptr.char.mix* } +# end of constant.element +constant.attlist &= + attribute class { "limit" }?, + common.attrib, + constant.role.attrib, + local.constant.attrib +# end of constant.attlist + +# end of constant.module +local.varname.attrib = empty +varname.role.attrib = role.attrib +# doc:The name of a variable. +varname = element varname { varname.attlist, smallcptr.char.mix* } +# end of varname.element +varname.attlist &= + common.attrib, varname.role.attrib, local.varname.attrib +# end of varname.attlist + +# end of varname.module +local.markup.attrib = empty +markup.role.attrib = role.attrib +# doc:A string of formatting markup in text that is to be represented literally. +markup = element markup { markup.attlist, smallcptr.char.mix* } +# end of markup.element +markup.attlist &= common.attrib, markup.role.attrib, local.markup.attrib +# end of markup.attlist + +# end of markup.module +local.medialabel.attrib = empty +medialabel.role.attrib = role.attrib +# doc:A name that identifies the physical medium on which some information resides. +medialabel = + element medialabel { medialabel.attlist, smallcptr.char.mix* } +# end of medialabel.element + +# Class: Type of medium named by the element; no default +medialabel.attlist &= + attribute class { "cartridge" | "cdrom" | "disk" | "tape" }?, + common.attrib, + medialabel.role.attrib, + local.medialabel.attrib +# end of medialabel.attlist + +# end of medialabel.module +local.menuchoice.attrib = empty +menuchoice.role.attrib = role.attrib +# doc:A selection or series of selections from a menu. +menuchoice = + element menuchoice { + menuchoice.attlist, + shortcut?, + (guibutton + | guiicon + | guilabel + | guimenu + | guimenuitem + | guisubmenu + | interface)+ + } +# end of menuchoice.element +menuchoice.attlist &= + moreinfo.attrib, + common.attrib, + menuchoice.role.attrib, + local.menuchoice.attrib +# end of menuchoice.attlist + +# end of menuchoice.module + +# See also KeyCombo +local.shortcut.attrib = empty +shortcut.role.attrib = role.attrib +# doc:A key combination for an action that is also accessible through a menu. +shortcut = + element shortcut { + shortcut.attlist, (keycap | keycombo | keysym | mousebutton)+ + } +# end of shortcut.element +shortcut.attlist &= + keyaction.attrib, + moreinfo.attrib, + common.attrib, + shortcut.role.attrib, + local.shortcut.attrib +# end of shortcut.attlist + +# end of shortcut.module + +# end of menuchoice.content.module +local.mousebutton.attrib = empty +mousebutton.role.attrib = role.attrib +# doc:The conventional name of a mouse button. +mousebutton = + element mousebutton { mousebutton.attlist, smallcptr.char.mix* } +# end of mousebutton.element +mousebutton.attlist &= + moreinfo.attrib, + common.attrib, + mousebutton.role.attrib, + local.mousebutton.attrib +# end of mousebutton.attlist + +# end of mousebutton.module +local.msgtext.attrib = empty +msgtext.role.attrib = role.attrib +# doc:The actual text of a message component in a message set. +msgtext = element msgtext { msgtext.attlist, component.mix+ } +# end of msgtext.element +msgtext.attlist &= + common.attrib, msgtext.role.attrib, local.msgtext.attrib +# end of msgtext.attlist + +# end of msgtext.module +local.option.attrib = empty +option.role.attrib = role.attrib +# doc:An option for a software command. +option = element option { option.attlist, cptr.char.mix* } +# end of option.element +option.attlist &= common.attrib, option.role.attrib, local.option.attrib +# end of option.attlist + +# end of option.module +local.optional.attrib = empty +optional.role.attrib = role.attrib +# doc:Optional information. +optional = element optional { optional.attlist, cptr.char.mix* } +# end of optional.element +optional.attlist &= + common.attrib, optional.role.attrib, local.optional.attrib +# end of optional.attlist + +# end of optional.module +local.parameter.attrib = empty +parameter.role.attrib = role.attrib +# doc:A value or a symbolic reference to a value. +parameter = element parameter { parameter.attlist, cptr.char.mix* } +# end of parameter.element + +# Class: Type of the Parameter; no default +parameter.attlist &= + attribute class { "command" | "function" | "option" }?, + moreinfo.attrib, + common.attrib, + parameter.role.attrib, + local.parameter.attrib +# end of parameter.attlist + +# end of parameter.module +local.prompt.attrib = empty +prompt.role.attrib = role.attrib +# doc:A character or string indicating the start of an input field in a computer display. +prompt = element prompt { prompt.attlist, (smallcptr.char.mix | co)* } +# end of prompt.element +prompt.attlist &= + moreinfo.attrib, + common.attrib, + prompt.role.attrib, + local.prompt.attrib +# end of prompt.attlist + +# end of prompt.module +local.property.attrib = empty +property.role.attrib = role.attrib +# doc:A unit of data associated with some part of a computer system. +property = element property { property.attlist, cptr.char.mix* } +# end of property.element +property.attlist &= + moreinfo.attrib, + common.attrib, + property.role.attrib, + local.property.attrib +# end of property.attlist + +# end of property.module +local.replaceable.attrib = empty +replaceable.role.attrib = role.attrib +# doc:Content that may or must be replaced by the user. +replaceable = + element replaceable { + replaceable.attlist, + (text + | link.char.class + | optional + | base.char.class + | other.char.class + | inlinegraphic + | inlinemediaobject + | co)* + } +# end of replaceable.element + +# Class: Type of information the element represents; no +# default +replaceable.attlist &= + attribute class { "command" | "function" | "option" | "parameter" }?, + common.attrib, + replaceable.role.attrib, + local.replaceable.attrib +# end of replaceable.attlist + +# end of replaceable.module +local.returnvalue.attrib = empty +returnvalue.role.attrib = role.attrib +# doc:The value returned by a function. +returnvalue = + element returnvalue { returnvalue.attlist, smallcptr.char.mix* } +# end of returnvalue.element +returnvalue.attlist &= + common.attrib, returnvalue.role.attrib, local.returnvalue.attrib +# end of returnvalue.attlist + +# end of returnvalue.module +local.sgmltag.attrib = empty +sgmltag.role.attrib = role.attrib +# doc:A component of SGML markup. +sgmltag = element sgmltag { sgmltag.attlist, smallcptr.char.mix* } +# end of sgmltag.element + +# Class: Type of SGML construct the element names; no default +sgmltag.attlist &= + attribute class { + "attribute" + | "attvalue" + | "element" + | "endtag" + | "emptytag" + | "genentity" + | "numcharref" + | "paramentity" + | "pi" + | "xmlpi" + | "starttag" + | "sgmlcomment" + | "prefix" + | "namespace" + | "localname" + }?, + attribute namespace { text }?, + common.attrib, + sgmltag.role.attrib, + local.sgmltag.attrib +# end of sgmltag.attlist + +# end of sgmltag.module +local.structfield.attrib = empty +structfield.role.attrib = role.attrib +# doc:A field in a structure (in the programming language sense). +structfield = + element structfield { structfield.attlist, smallcptr.char.mix* } +# end of structfield.element +structfield.attlist &= + common.attrib, structfield.role.attrib, local.structfield.attrib +# end of structfield.attlist + +# end of structfield.module +local.structname.attrib = empty +structname.role.attrib = role.attrib +# doc:The name of a structure (in the programming language sense). +structname = + element structname { structname.attlist, smallcptr.char.mix* } +# end of structname.element +structname.attlist &= + common.attrib, structname.role.attrib, local.structname.attrib +# end of structname.attlist + +# end of structname.module +local.symbol.attrib = empty +symbol.role.attrib = role.attrib +# doc:A name that is replaced by a value before processing. +symbol = element symbol { symbol.attlist, smallcptr.char.mix* } +# end of symbol.element + +# Class: Type of symbol; no default +symbol.attlist &= + attribute class { "limit" }?, + common.attrib, + symbol.role.attrib, + local.symbol.attrib +# end of symbol.attlist + +# end of symbol.module +local.systemitem.attrib = empty +systemitem.role.attrib = role.attrib +# doc:A system-related item or term. +systemitem = + element systemitem { + systemitem.attlist, (cptr.char.mix | acronym | co)* + } +# end of systemitem.element + +# Class: Type of system item the element names; no default +systemitem.attlist &= + attribute class { + "constant" + | "daemon" + | "domainname" + | "etheraddress" + | "event" + | "eventhandler" + | "filesystem" + | "fqdomainname" + | "groupname" + | "ipaddress" + | "library" + | "macro" + | "netmask" + | "newsgroup" + | "osname" + | "protocol" + | "resource" + | "systemname" + | "username" + | "process" + | "server" + | "service" + }?, + moreinfo.attrib, + common.attrib, + systemitem.role.attrib, + local.systemitem.attrib +# end of systemitem.attlist + +# end of systemitem.module +local.uri.attrib = empty +uri.role.attrib = role.attrib +# doc:A Uniform Resource Identifier. +uri = element uri { uri.attlist, smallcptr.char.mix* } +# end of uri.element + +# Type: Type of URI; no default +uri.attlist &= + attribute type { text }?, + common.attrib, + uri.role.attrib, + local.uri.attrib +# end of uri.attlist + +# end of uri.module +local.token.attrib = empty +token.role.attrib = role.attrib +# doc:A unit of information. +\token = element token { token.attlist, smallcptr.char.mix* } +# end of token.element +token.attlist &= common.attrib, token.role.attrib, local.token.attrib +# end of token.attlist + +# end of token.module +local.type.attrib = empty +type.role.attrib = role.attrib +# doc:The classification of a value. +type = element type { type.attlist, smallcptr.char.mix* } +# end of type.element +type.attlist &= common.attrib, type.role.attrib, local.type.attrib +# end of type.attlist + +# end of type.module +local.userinput.attrib = empty +userinput.role.attrib = role.attrib +# doc:Data entered by the user. +userinput = + element userinput { userinput.attlist, (cptr.char.mix | co)* } +# end of userinput.element +userinput.attlist &= + moreinfo.attrib, + common.attrib, + userinput.role.attrib, + local.userinput.attrib +# end of userinput.attlist + +# end of userinput.module +local.termdef.attrib = empty +termdef.role.attrib = role.attrib +# doc:An inline definition of a term. +termdef = element termdef { termdef.attlist, para.char.mix* } +# end of termdef.element +termdef.attlist &= + common.attrib, termdef.role.attrib, local.termdef.attrib +# end of termdef.attlist + +# end of termdef.module + +# General words and phrases ............................................ +local.abbrev.attrib = empty +abbrev.role.attrib = role.attrib +# doc:An abbreviation, especially one followed by a period. +abbrev = element abbrev { abbrev.attlist, word.char.mix* } +# end of abbrev.element +abbrev.attlist &= common.attrib, abbrev.role.attrib, local.abbrev.attrib +# end of abbrev.attlist + +# end of abbrev.module +local.acronym.attrib = empty +acronym.role.attrib = role.attrib +# doc:An often pronounceable word made from the initial (or selected) letters of a name or phrase. +acronym = element acronym { acronym.attlist, word.char.mix* } +# end of acronym.element +acronym.attlist &= + common.attrib, acronym.role.attrib, local.acronym.attrib +# end of acronym.attlist + +# end of acronym.module +local.citation.attrib = empty +citation.role.attrib = role.attrib +# doc:An inline bibliographic reference to another published work. +citation = element citation { citation.attlist, para.char.mix* } +# end of citation.element +citation.attlist &= + common.attrib, citation.role.attrib, local.citation.attrib +# end of citation.attlist + +# end of citation.module +local.citerefentry.attrib = empty +citerefentry.role.attrib = role.attrib +# doc:A citation to a reference page. +citerefentry = + element citerefentry { + citerefentry.attlist, refentrytitle, manvolnum? + } +# end of citerefentry.element +citerefentry.attlist &= + common.attrib, citerefentry.role.attrib, local.citerefentry.attrib +# end of citerefentry.attlist + +# end of citerefentry.module +local.refentrytitle.attrib = empty +refentrytitle.role.attrib = role.attrib +# doc:The title of a reference page. +refentrytitle = + element refentrytitle { refentrytitle.attlist, para.char.mix* } +# end of refentrytitle.element +refentrytitle.attlist &= + common.attrib, refentrytitle.role.attrib, local.refentrytitle.attrib +# end of refentrytitle.attlist + +# end of refentrytitle.module +local.manvolnum.attrib = empty +namvolnum.role.attrib = role.attrib +# doc:A reference volume number. +manvolnum = element manvolnum { manvolnum.attlist, word.char.mix* } +# end of manvolnum.element +manvolnum.attlist &= + common.attrib, namvolnum.role.attrib, local.manvolnum.attrib +# end of manvolnum.attlist + +# end of manvolnum.module +local.citetitle.attrib = empty +citetitle.role.attrib = role.attrib +# doc:The title of a cited work. +citetitle = element citetitle { citetitle.attlist, para.char.mix* } +# end of citetitle.element + +# Pubwork: Genre of published work cited; no default +citetitle.attlist &= + attribute pubwork { + "article" + | "book" + | "chapter" + | "part" + | "refentry" + | "section" + | "journal" + | "series" + | "set" + | "manuscript" + | "cdrom" + | "dvd" + | "wiki" + | "gopher" + | "bbs" + | "emailmessage" + | "webpage" + | "newsposting" + }?, + common.attrib, + citetitle.role.attrib, + local.citetitle.attrib +# end of citetitle.attlist + +# end of citetitle.module +local.emphasis.attrib = empty +emphasis.role.attrib = role.attrib +# doc:Emphasized text. +emphasis = element emphasis { emphasis.attlist, para.char.mix* } +# end of emphasis.element +emphasis.attlist &= + common.attrib, emphasis.role.attrib, local.emphasis.attrib +# end of emphasis.attlist + +# end of emphasis.module +local.foreignphrase.attrib = empty +foreignphrase.role.attrib = role.attrib +# doc:A word or phrase in a language other than the primary language of the document. +foreignphrase = + element foreignphrase { foreignphrase.attlist, para.char.mix* } +# end of foreignphrase.element +foreignphrase.attlist &= + common.attrib, foreignphrase.role.attrib, local.foreignphrase.attrib +# end of foreignphrase.attlist + +# end of foreignphrase.module +local.glossterm.attrib = empty +glossterm.role.attrib = role.attrib +# doc:A glossary term. +glossterm = element glossterm { glossterm.attlist, para.char.mix* } +# end of glossterm.element + +# to GlossEntry if Glossterm used in text + +# BaseForm: Provides the form of GlossTerm to be used +# for indexing +glossterm.attlist &= + attribute baseform { text }?, + linkend.attrib, + common.attrib, + glossterm.role.attrib, + local.glossterm.attrib +# end of glossterm.attlist + +# end of glossterm.module +local.firstterm.attrib = empty +firstterm.role.attrib = role.attrib +# doc:The first occurrence of a term. +firstterm = element firstterm { firstterm.attlist, para.char.mix* } +# end of firstterm.element + +# to GlossEntry or other explanation +firstterm.attlist &= + attribute baseform { text }?, + linkend.attrib, + common.attrib, + firstterm.role.attrib, + local.firstterm.attrib +# end of firstterm.attlist + +# end of firstterm.module +local.phrase.attrib = empty +phrase.role.attrib = role.attrib +# doc:A span of text. +phrase = element phrase { phrase.attlist, para.char.mix* } +# end of phrase.element +phrase.attlist &= common.attrib, phrase.role.attrib, local.phrase.attrib +# end of phrase.attlist + +# end of phrase.module +local.quote.attrib = empty +quote.role.attrib = role.attrib +# doc:An inline quotation. +quote = element quote { quote.attlist, para.char.mix* } +# end of quote.element +quote.attlist &= common.attrib, quote.role.attrib, local.quote.attrib +# end of quote.attlist + +# end of quote.module +local.ssscript.attrib = empty +ssscript.role.attrib = role.attrib +# doc:A subscript (as in H{^2}O, the molecular formula for water). +subscript = + element subscript { + subscript.attlist, + (text + | link.char.class + | emphasis + | replaceable + | symbol + | inlinegraphic + | inlinemediaobject + | base.char.class + | other.char.class)* + } +# end of subscript.element +subscript.attlist &= + common.attrib, ssscript.role.attrib, local.ssscript.attrib +# end of subscript.attlist + +# doc:A superscript (as in x^2, the mathematical notation for x multiplied by itself). +superscript = + element superscript { + superscript.attlist, + (text + | link.char.class + | emphasis + | replaceable + | symbol + | inlinegraphic + | inlinemediaobject + | base.char.class + | other.char.class)* + } +# end of superscript.element +superscript.attlist &= + common.attrib, ssscript.role.attrib, local.ssscript.attrib +# end of superscript.attlist + +# end of ssscript.module +local.trademark.attrib = empty +trademark.role.attrib = role.attrib +# doc:A trademark. +trademark = + element trademark { + trademark.attlist, + (text + | link.char.class + | tech.char.class + | base.char.class + | other.char.class + | inlinegraphic + | inlinemediaobject + | emphasis)* + } +# end of trademark.element + +# Class: More precisely identifies the item the element names +trademark.attlist &= + [ a:defaultValue = "trade" ] + attribute class { "service" | "trade" | "registered" | "copyright" }?, + common.attrib, + trademark.role.attrib, + local.trademark.attrib +# end of trademark.attlist + +# end of trademark.module +local.wordasword.attrib = empty +wordasword.role.attrib = role.attrib +# doc:A word meant specifically as a word and not representing anything else. +wordasword = element wordasword { wordasword.attlist, word.char.mix* } +# end of wordasword.element +wordasword.attlist &= + common.attrib, wordasword.role.attrib, local.wordasword.attrib +# end of wordasword.attlist + +# end of wordasword.module + +# Links and cross-references ........................................... +local.link.attrib = empty +link.role.attrib = role.attrib +# doc:A hypertext link. +link = element link { link.attlist, para.char.mix* } +# end of link.element + +# Endterm: ID of element containing text that is to be +# fetched from elsewhere in the document to appear as +# the content of this element + +# to linked-to object + +# Type: Freely assignable parameter +link.attlist &= + attribute endterm { xsd:IDREF }?, + attribute xrefstyle { text }?, + attribute type { text }?, + linkendreq.attrib, + common.attrib, + link.role.attrib, + local.link.attrib +# end of link.attlist + +# end of link.module +local.olink.attrib = empty +olink.role.attrib = role.attrib +# doc:A link that addresses its target indirectly, through an entity. +olink = element olink { olink.attlist, para.char.mix* } +# end of olink.element + +# TargetDocEnt: Name of an entity to be the target of the link + +# LinkMode: ID of a ModeSpec containing instructions for +# operating on the entity named by TargetDocEnt + +# LocalInfo: Information that may be passed to ModeSpec + +# Type: Freely assignable parameter +olink.attlist &= + attribute targetdocent { xsd:ENTITY }?, + attribute linkmode { xsd:IDREF }?, + attribute localinfo { text }?, + attribute type { text }?, + attribute targetdoc { text }?, + attribute targetptr { text }?, + attribute xrefstyle { text }?, + common.attrib, + olink.role.attrib, + local.olink.attrib +# end of olink.attlist + +# end of olink.module +local.ulink.attrib = empty +ulink.role.attrib = role.attrib +# doc:A link that addresses its target by means of a URL (Uniform Resource Locator). +ulink = element ulink { ulink.attlist, para.char.mix* } +# end of ulink.element + +# URL: uniform resource locator; the target of the ULink + +# Type: Freely assignable parameter +ulink.attlist &= + attribute url { text }, + attribute type { text }?, + attribute xrefstyle { text }?, + common.attrib, + ulink.role.attrib, + local.ulink.attrib +# end of ulink.attlist + +# end of ulink.module +local.footnoteref.attrib = empty +footnoteref.role.attrib = role.attrib +# doc:A cross reference to a footnote (a footnote mark). +footnoteref = element footnoteref { footnoteref.attlist, empty } +# end of footnoteref.element + +# to footnote content supplied elsewhere +footnoteref.attlist &= + linkendreq.attrib, + label.attrib, + common.attrib, + footnoteref.role.attrib, + local.footnoteref.attrib +# end of footnoteref.attlist + +# end of footnoteref.module +local.xref.attrib = empty +xref.role.attrib = role.attrib +# doc:A cross reference to another part of the document. +xref = element xref { xref.attlist, empty } +# end of xref.element + +# Endterm: ID of element containing text that is to be +# fetched from elsewhere in the document to appear as +# the content of this element + +# to linked-to object +xref.attlist &= + attribute endterm { xsd:IDREF }?, + attribute xrefstyle { text }?, + common.attrib, + linkendreq.attrib, + xref.role.attrib, + local.xref.attrib +# end of xref.attlist + +# end of xref.module +local.biblioref.attrib = empty +biblioref.role.attrib = role.attrib +# doc:A cross reference to a bibliographic entry. +biblioref = element biblioref { biblioref.attlist, empty } +# end of biblioref.element +biblioref.attlist &= + attribute endterm { xsd:IDREF }?, + attribute xrefstyle { text }?, + attribute units { text }?, + attribute begin { text }?, + attribute end { text }?, + common.attrib, + linkendreq.attrib, + biblioref.role.attrib, + local.biblioref.attrib +# end of biblioref.attlist + +# end of biblioref.module + +# Ubiquitous elements .................................................. +local.anchor.attrib = empty +anchor.role.attrib = role.attrib +# doc:A spot in the document. +anchor = element anchor { anchor.attlist, empty } +# end of anchor.element + +# required + +# replaces Lang +anchor.attlist &= + idreq.attrib, + pagenum.attrib, + remap.attrib, + xreflabel.attrib, + revisionflag.attrib, + effectivity.attrib, + anchor.role.attrib, + local.anchor.attrib +# end of anchor.attlist + +# end of anchor.module +local.beginpage.attrib = empty +beginpage.role.attrib = role.attrib +# doc:The location of a page break in a print version of the document. +beginpage = element beginpage { beginpage.attlist, empty } +# end of beginpage.element + +# PageNum: Number of page that begins at this point +beginpage.attlist &= + pagenum.attrib, + common.attrib, + beginpage.role.attrib, + local.beginpage.attrib +# end of beginpage.attlist + +# end of beginpage.module + +# IndexTerms appear in the text flow for generating or linking an +# index. +local.indexterm.attrib = empty +indexterm.role.attrib = role.attrib +# doc:A wrapper for terms to be indexed. +indexterm = + element indexterm { + indexterm.attlist, + primary?, + ((secondary, + ((tertiary, (see | seealso+)?) + | see + | seealso+)?) + | see + | seealso+)? + } +# end of indexterm.element + +# Scope: Indicates which generated indices the IndexTerm +# should appear in: Global (whole document set), Local (this +# document only), or All (both) + +# Significance: Whether this IndexTerm is the most pertinent +# of its series (Preferred) or not (Normal, the default) + +# Class: Indicates type of IndexTerm; default is Singular, +# or EndOfRange if StartRef is supplied; StartOfRange value +# must be supplied explicitly on starts of ranges + +# StartRef: ID of the IndexTerm that starts the indexing +# range ended by this IndexTerm + +# Zone: IDs of the elements to which the IndexTerm applies, +# and indicates that the IndexTerm applies to those entire +# elements rather than the point at which the IndexTerm +# occurs +indexterm.attlist &= + pagenum.attrib, + attribute scope { "all" | "global" | "local" }?, + [ a:defaultValue = "normal" ] + attribute significance { "preferred" | "normal" }?, + attribute class { "singular" | "startofrange" | "endofrange" }?, + attribute startref { xsd:IDREF }?, + attribute zone { xsd:IDREFS }?, + attribute type { text }?, + common.attrib, + indexterm.role.attrib, + local.indexterm.attrib +# end of indexterm.attlist + +# end of indexterm.module +local.primsecter.attrib = empty +primsecter.role.attrib = role.attrib +# doc:The primary word or phrase under which an index term should be sorted. +primary = element primary { primary.attlist, ndxterm.char.mix* } +# end of primary.element + +# SortAs: Alternate sort string for index sorting, e.g., +# "fourteen" for an element containing "14" +primary.attlist &= + attribute sortas { text }?, + common.attrib, + primsecter.role.attrib, + local.primsecter.attrib +# end of primary.attlist + +# doc:A secondary word or phrase in an index term. +secondary = element secondary { secondary.attlist, ndxterm.char.mix* } +# end of secondary.element + +# SortAs: Alternate sort string for index sorting, e.g., +# "fourteen" for an element containing "14" +secondary.attlist &= + attribute sortas { text }?, + common.attrib, + primsecter.role.attrib, + local.primsecter.attrib +# end of secondary.attlist + +# doc:A tertiary word or phrase in an index term. +tertiary = element tertiary { tertiary.attlist, ndxterm.char.mix* } +# end of tertiary.element + +# SortAs: Alternate sort string for index sorting, e.g., +# "fourteen" for an element containing "14" +tertiary.attlist &= + attribute sortas { text }?, + common.attrib, + primsecter.role.attrib, + local.primsecter.attrib +# end of tertiary.attlist + +# end of primsecter.module +local.seeseealso.attrib = empty +seeseealso.role.attrib = role.attrib +# doc:Part of an index term directing the reader instead to another entry in the index. +see = element see { see.attlist, ndxterm.char.mix* } +# end of see.element +see.attlist &= + common.attrib, seeseealso.role.attrib, local.seeseealso.attrib +# end of see.attlist + +# doc:Part of an index term directing the reader also to another entry in the index. +seealso = element seealso { seealso.attlist, ndxterm.char.mix* } +# end of seealso.element +seealso.attlist &= + common.attrib, seeseealso.role.attrib, local.seeseealso.attrib +# end of seealso.attlist + +# end of seeseealso.module + +# end of indexterm.content.module + +# End of DocBook XML information pool module V4.5 ...................... + +# ...................................................................... diff --git a/defensive-coding/docbook-schema/.svn/text-base/docbook.rnc.svn-base b/defensive-coding/docbook-schema/.svn/text-base/docbook.rnc.svn-base new file mode 100644 index 0000000..8a0a75a --- /dev/null +++ b/defensive-coding/docbook-schema/.svn/text-base/docbook.rnc.svn-base @@ -0,0 +1,499 @@ +# ...................................................................... + +# DocBook XML DTD V4.5 ................................................. + +# File docbookx.dtd .................................................... + +# Copyright 1992-2006 HaL Computer Systems, Inc., +# O'Reilly & Associates, Inc., ArborText, Inc., Fujitsu Software +# Corporation, Norman Walsh, Sun Microsystems, Inc., and the +# Organization for the Advancement of Structured Information +# Standards (OASIS). +# +# See also http://docbook.org/specs/ +# +# $Id: docbookx.dtd 6340 2006-10-03 13:23:24Z nwalsh $ +# +# Permission to use, copy, modify and distribute the DocBook XML DTD +# and its accompanying documentation for any purpose and without fee +# is hereby granted in perpetuity, provided that the above copyright +# notice and this paragraph appear in all copies. The copyright +# holders make no representation about the suitability of the DTD for +# any purpose. It is provided "as is" without expressed or implied +# warranty. +# +# If you modify the DocBook DTD in any way, except for declaring and +# referencing additional sets of general entities and declaring +# additional notations, label your DTD as a variant of DocBook. See +# the maintenance documentation for more information. +# +# Please direct all questions, bug reports, or suggestions for +# changes to the docbook@lists.oasis-open.org mailing list. For more +# information, see http://www.oasis-open.org/docbook/. + +# ...................................................................... + +# This is the driver file for V4.5 of the DocBook DTD. +# Please use the following formal public identifier to identify it: +# +# "-//OASIS//DTD DocBook XML V4.5//EN" +# +# For example, if your document's top-level element is Book, and +# you are using DocBook directly, use the FPI in the DOCTYPE +# declaration: +# +# +# +# Or, if you have a higher-level driver file that customizes DocBook, +# use the FPI in the parameter entity declaration: +# +# +# %DocBookDTD; +# +# See the documentation for detailed information on the parameter +# entity and module scheme used in DocBook, customizing DocBook and +# planning for interchange, and changes made since the last release +# of DocBook. + +# ...................................................................... + +# Enable SGML features ................................................. + +# ...................................................................... + +# Notation declarations ................................................ + +include "dbnotnx.rnc" +# ...................................................................... + +# ISO character entity sets ............................................ + +# euro sign, U+20AC NEW + +# ...................................................................... + +# DTD modules .......................................................... + +# Information pool .............. +include "dbpoolx.rnc" +# Redeclaration placeholder ..... + +# Document hierarchy ............ +include "dbhierx.rnc" +start = + articleinfo + | honorific + | legalnotice + | procedure + | simplelist + | keycode + | refsynopsisdiv + | article + | phrase + | destructorsynopsis + | itemizedlist + | audioobject + | link + | sect1info + | xref + | glossaryinfo + | varname + | keywordset + | informalequation + | toc + | pagenums + | lot + | shortcut + | glosslist + | option + | bibliosource + | variablelist + | filename + | pob + | colgroup + | foreignphrase + | group + | substeps + | conftitle + | textobject + | menuchoice + | colspec + | contractsponsor + | tocback + | contractnum + | constant + | dedication + | inlineequation + | bibliographyinfo + | country + | glossseealso + | bridgehead + | mousebutton + | surname + | stepalternatives + | tertiaryie + | mediaobject + | msgentry + | fax + | initializer + | table + | task + | setinfo + | videodata + | bibliodiv + | issuenum + | phone + | state + | refsynopsisdivinfo + | member + | glossentry + | term + | msgtext + | tr + | errortype + | confdates + | inlinegraphic + | th + | segmentedlist + | remark + | preface + | structname + | publisher + | td + | oointerface + | refsection + | type + | taskrelated + | msgrel + | artpagenums + | bibliomixed + | revnumber + | firstterm + | seeie + | spanspec + | toclevel5 + | trademark + | toclevel4 + | toclevel3 + | toclevel2 + | indexentry + | toclevel1 + | colophon + | methodparam + | sidebarinfo + | productnumber + | funcprototype + | inlinemediaobject + | refclass + | lotentry + | paramdef + | classsynopsisinfo + | qandaset + | footnote + | msglevel + | keysym + | citation + | simplemsgentry + | othercredit + | subjectset + | keycap + | orderedlist + | refmiscinfo + | blockinfo + | programlistingco + | abbrev + | sidebar + | informalfigure + | tip + | primaryie + | appendixinfo + | partintro + | glossdiv + | confgroup + | segtitle + | taskprerequisites + | street + | tbody + | caption + | markup + | setindex + | msgsub + | subscript + | orgname + | fieldsynopsis + | refname + | void + | sect5 + | sect4 + | sect3 + | chapter + | sect2 + | sect1 + | modifier + | col + | orgdiv + | city + | bibliolist + | funcparams + | application + | \token + | imageobject + | literal + | funcsynopsis + | olink + | package + | collab + | seealsoie + | primary + | glossterm + | termdef + | area + | ackno + | function + | collabname + | lineannotation + | guisubmenu + | msgexplan + | errorname + | property + | synopfragmentref + | refentryinfo + | entry + | manvolnum + | synopsis + | emphasis + | appendix + | bookinfo + | contrib + | otheraddr + | copyright + | methodname + | email + | ooclass + | videoobject + | abstract + | firstname + | revremark + | glossdef + | guibutton + | informalexample + | screen + | errorcode + | command + | seriesvolnums + | refpurpose + | parameter + | equation + | tfoot + | code + | jobtitle + | sgmltag + | screenco + | holder + | isbn + | corpcredit + | biblioset + | part + | symbol + | row + | bibliomisc + | imagedata + | secondary + | classname + | callout + | screenshot + | bibliomset + | indexterm + | refsect3 + | tocchap + | para + | refsect2 + | refsect1 + | date + | refdescriptor + | wordasword + | epigraph + | audiodata + | hardware + | confsponsor + | authorgroup + | warning + | authorinitials + | medialabel + | varlistentry + | authorblurb + | itermset + | refsect3info + | informaltable + | guimenuitem + | postcode + | subjectterm + | refnamediv + | note + | figure + | envar + | listitem + | methodsynopsis + | affiliation + | funcsynopsisinfo + | structfield + | blockquote + | keyword + | chapterinfo + | tertiary + | year + | subtitle + | personblurb + | refentry + | citebiblioid + | seglistitem + | bibliography + | msg + | constructorsynopsis + | refsect2info + | volumenum + | database + | funcdef + | uri + | graphicco + | biblioid + | msgmain + | printhistory + | glosssee + | beginpage + | glossary + | set + | highlights + | objectinfo + | tocpart + | guiicon + | revhistory + | seg + | see + | msgorig + | areaspec + | partinfo + | index + | sectioninfo + | refsectioninfo + | optional + | confnum + | replaceable + | refsect1info + | corpauthor + | step + | anchor + | arg + | mathphrase + | setindexinfo + | keycombo + | address + | cmdsynopsis + | computeroutput + | literallayout + | qandaentry + | sect5info + | bibliocoverage + | coref + | editor + | superscript + | personname + | pubsnumber + | graphic + | simplesect + | accel + | secondaryie + | biblioref + | publishername + | bibliorelation + | prefaceinfo + | revision + | screeninfo + | sbr + | example + | citetitle + | issn + | invpartnumber + | indexdiv + | sect4info + | corpname + | lineage + | ooexception + | reference + | revdescription + | title + | edition + | co + | msgaud + | guimenu + | shortaffil + | titleabbrev + | msginfo + | refmeta + | qandadiv + | mediaobjectco + | seealso + | exceptionname + | answer + | programlisting + | tgroup + | refentrytitle + | book + | errortext + | varargs + | sect3info + | citerefentry + | tasksummary + | quote + | othername + | prompt + | entrytbl + | interfacename + | acronym + | modespec + | msgset + | thead + | textdata + | userinput + | attribution + | footnoteref + | action + | tocentry + | tocfront + | author + | imageobjectco + | alt + | question + | ulink + | subject + | pubdate + | returnvalue + | label + | caution + | section + | systemitem + | referenceinfo + | sect2info + | calloutlist + | classsynopsis + | productname + | simpara + | synopfragment + | important + | interface + | releaseinfo + | formalpara + | areaset + | biblioentry + | indexinfo + | guilabel +# ...................................................................... + +# Other general entities ............................................... + +# End of DocBook XML DTD V4.5 .......................................... + +# ...................................................................... diff --git a/defensive-coding/docbook-schema/.svn/text-base/htmltblx.rnc.svn-base b/defensive-coding/docbook-schema/.svn/text-base/htmltblx.rnc.svn-base new file mode 100644 index 0000000..7e15972 --- /dev/null +++ b/defensive-coding/docbook-schema/.svn/text-base/htmltblx.rnc.svn-base @@ -0,0 +1,225 @@ +# ...................................................................... + +# DocBook XML HTML Table Module V4.5 ................................... + +# File htmltblx.mod .................................................... + +# Copyright 2003-2006 ArborText, Inc., Norman Walsh, Sun Microsystems, +# Inc., and the Organization for the Advancement of Structured Information +# Standards (OASIS). +# +# $Id: htmltblx.mod 6340 2006-10-03 13:23:24Z nwalsh $ +# +# Permission to use, copy, modify and distribute the DocBook XML DTD +# and its accompanying documentation for any purpose and without fee +# is hereby granted in perpetuity, provided that the above copyright +# notice and this paragraph appear in all copies. The copyright +# holders make no representation about the suitability of the DTD for +# any purpose. It is provided "as is" without expressed or implied +# warranty. +# +# If you modify the DocBook XML DTD in any way, except for declaring and +# referencing additional sets of general entities and declaring +# additional notations, label your DTD as a variant of DocBook. See +# the maintenance documentation for more information. +# +# Please direct all questions, bug reports, or suggestions for +# changes to the docbook@lists.oasis-open.org mailing list. For more +# information, see http://www.oasis-open.org/docbook/. + +# ...................................................................... + +# This module contains the definitions for elements that are +# isomorphic to the HTML elements. One could argue we should +# instead have based ourselves on the XHTML Table Module, but the +# HTML one is more like what browsers are likely to accept today +# and users are likely to use. +# +# This module has been developed for use with the DocBook V4.5 +# "union table model" in which elements and attlists common to both +# models are defined (as the union) in the CALS table module by +# setting various parameter entities appropriately in this file. +# +# In DTD driver files referring to this module, please use an entity +# declaration that uses the public identifier shown below: +# +# +# %htmltbl; +# +# See the documentation for detailed information on the parameter +# entity and module scheme used in DocBook, customizing DocBook and +# planning for interchange, and changes made since the last release +# of DocBook. + +# ======================= XHTML Tables ======================================= + +namespace a = "http://relaxng.org/ns/compatibility/annotations/1.0" + +html.coreattrs = + common.attrib, + attribute class { text }?, + attribute style { text }?, + attribute title { text }? +# Does not contain lang or dir because they are in %common.attribs +i18n = attribute xml:lang { xsd:NMTOKEN }? +events = + attribute onclick { text }?, + attribute ondblclick { text }?, + attribute onmousedown { text }?, + attribute onmouseup { text }?, + attribute onmouseover { text }?, + attribute onmousemove { text }?, + attribute onmouseout { text }?, + attribute onkeypress { text }?, + attribute onkeydown { text }?, + attribute onkeyup { text }? +attrs = html.coreattrs, i18n, events +cellhalign = + attribute align { "left" | "center" | "right" | "justify" | "char" }?, + attribute char { text }?, + attribute charoff { text }? +cellvalign = + attribute valign { "top" | "middle" | "bottom" | "baseline" }? +# doc:A group of columns in an HTML table. +colgroup = element colgroup { colgroup.attlist, col* } +# doc:Specifications for a column in an HTML table. +col = element col { col.attlist, empty } +# doc:A row in an HTML table. +tr = element tr { tr.attlist, (th | td)+ } +# doc:A table header entry in an HTML table. +th = + element th { + th.attlist, (para.char.mix | tabentry.mix | table | informaltable)* + } +# doc:A table ntry in an HTML table. +td = + element td { + td.attlist, (para.char.mix | tabentry.mix | table | informaltable)* + } +colgroup.attlist &= + attrs, + [ a:defaultValue = "1" ] attribute span { text }?, + attribute width { text }?, + cellhalign, + cellvalign +col.attlist &= + attrs, + [ a:defaultValue = "1" ] attribute span { text }?, + attribute width { text }?, + cellhalign, + cellvalign +tr.attlist &= + attrs, + cellhalign, + cellvalign, + attribute bgcolor { text }? +th.attlist &= + attrs, + attribute abbr { text }?, + attribute axis { text }?, + attribute headers { xsd:IDREFS }?, + attribute scope { "row" | "col" | "rowgroup" | "colgroup" }?, + [ a:defaultValue = "1" ] attribute rowspan { text }?, + [ a:defaultValue = "1" ] attribute colspan { text }?, + cellhalign, + cellvalign, + attribute nowrap { "nowrap" }?, + attribute bgcolor { text }?, + attribute width { text }?, + attribute height { text }? +td.attlist &= + attrs, + attribute abbr { text }?, + attribute axis { text }?, + attribute headers { xsd:IDREFS }?, + attribute scope { "row" | "col" | "rowgroup" | "colgroup" }?, + [ a:defaultValue = "1" ] attribute rowspan { text }?, + [ a:defaultValue = "1" ] attribute colspan { text }?, + cellhalign, + cellvalign, + attribute nowrap { "nowrap" }?, + attribute bgcolor { text }?, + attribute width { text }?, + attribute height { text }? +# ====================================================== + +# Set up to read in the CALS model configured to +# merge with the XHTML table model + +# ====================================================== +tables.role.attrib = role.attrib +# Add label and role attributes to table and informaltable +bodyatt = + attribute floatstyle { text }?, + attribute rowheader { "firstcol" | "norowheader" }?, + label.attrib +# Add common attributes to Table, TGroup, TBody, THead, TFoot, Row, +# EntryTbl, and Entry (and InformalTable element). +secur = + common.attrib, + attribute class { text }?, + attribute style { text }?, + attribute title { text }?, + i18n, + events, + tables.role.attrib +common.table.attribs = bodyatt, secur +# Content model for Table (that also allows HTML tables) +tbl.table.mdl = + (blockinfo?, + formalobject.title.content, + ndxterm.class*, + textobject*, + (graphic+ | mediaobject+ | tgroup+)) + | (caption, (col* | colgroup*), thead?, tfoot?, (tbody+ | tr+)) +informal.tbl.table.mdl = + (textobject*, (graphic+ | mediaobject+ | tgroup+)) + | ((col* | colgroup*), thead?, tfoot?, (tbody+ | tr+)) +# Attributes for Table (including HTML ones) + +# N.B. rules = (none | groups | rows | cols | all) but it can't be spec'd + +# that way because 'all' already occurs in a different enumeration in + +# CALS tables (frame). +tbl.table.att = + attribute tabstyle { text }?, + attribute tocentry { yesorno.attvals }?, + attribute shortentry { yesorno.attvals }?, + attribute orient { "port" | "land" }?, + attribute pgwide { yesorno.attvals }?, + attribute summary { text }?, + attribute width { text }?, + attribute border { text }?, + attribute rules { text }?, + attribute cellspacing { text }?, + attribute cellpadding { text }?, + attribute align { "left" | "center" | "right" }?, + attribute bgcolor { text }? +tbl.frame.attval = + "void" + | "above" + | "below" + | "hsides" + | "lhs" + | "rhs" + | "vsides" + | "box" + | "border" + | "top" + | "bottom" + | "topbot" + | "all" + | "sides" + | "none" +# Allow either objects or inlines; beware of REs between elements. +tbl.entry.mdl = para.char.mix | tabentry.mix +# thead, tfoot, and tbody are defined in both table models, +# so we set up parameter entities to define union models for them +tbl.hdft.mdl = tr+ | (colspec*, row+) +tbl.tbody.mdl = tr+ | row+ +# End of DocBook XML HTML Table Module V4.5 ............................ + +# ...................................................................... diff --git a/defensive-coding/docbook-schema/README b/defensive-coding/docbook-schema/README new file mode 100644 index 0000000..c636682 --- /dev/null +++ b/defensive-coding/docbook-schema/README @@ -0,0 +1,3 @@ +This directory contains Relax NG Compact schema files, for use with +Emacs. These files were download from http://www.docbook.org/rng/4.5/ +on 2012-07-16. diff --git a/defensive-coding/docbook-schema/calstblx.rnc b/defensive-coding/docbook-schema/calstblx.rnc new file mode 100644 index 0000000..b6a2483 --- /dev/null +++ b/defensive-coding/docbook-schema/calstblx.rnc @@ -0,0 +1,164 @@ +# ...................................................................... + +# DocBook CALS Table Model V4.5 ........................................ + +# File calstblx.mod .................................................... + +# Copyright 1992-2002 HaL Computer Systems, Inc., +# O'Reilly & Associates, Inc., ArborText, Inc., Fujitsu Software +# Corporation, Norman Walsh, Sun Microsystems, Inc., and the +# Organization for the Advancement of Structured Information +# Standards (OASIS). +# +# This DTD is based on the CALS Table Model +# PUBLIC "-//USA-DOD//DTD Table Model 951010//EN" +# +# $Id: calstblx.dtd 6340 2006-10-03 13:23:24Z nwalsh $ +# +# Permission to use, copy, modify and distribute the DocBook DTD +# and its accompanying documentation for any purpose and without fee +# is hereby granted in perpetuity, provided that the above copyright +# notice and this paragraph appear in all copies. The copyright +# holders make no representation about the suitability of the DTD for +# any purpose. It is provided "as is" without expressed or implied +# warranty. +# +# If you modify the DocBook DTD in any way, except for declaring and +# referencing additional sets of general entities and declaring +# additional notations, label your DTD as a variant of DocBook. See +# the maintenance documentation for more information. +# +# Please direct all questions, bug reports, or suggestions for +# changes to the docbook@lists.oasis-open.org mailing list. For more +# information, see http://www.oasis-open.org/docbook/. + +# ...................................................................... + +# This module contains the definitions for the CALS Table Model +# converted to XML. It has been modified slightly for use in the +# combined HTML/CALS models supported by DocBook V4.5. + +# These definitions are not directly related to the table model, but are +# used in the default CALS table model and are usually defined elsewhere +# (and prior to the inclusion of this table module) in a CALS DTD. + +# no if zero(s), +# yes if any other digits value + +yesorno = string +titles = title? +# default for use in entry content + +# The parameter entities as defined below provide the CALS table model +# as published (as part of the Example DTD) in MIL-HDBK-28001. +# +# These following declarations provide the CALS-compliant default definitions +# for these entities. However, these entities can and should be redefined +# (by giving the appropriate parameter entity declaration(s) prior to the +# reference to this Table Model declaration set entity) to fit the needs +# of the current application. +tbl.table-titles.mdl = titles +tbl.table-main.mdl = tgroup+ | graphic+ +tbl.tgroup.mdl = colspec*, spanspec*, thead?, tfoot?, tbody +tbl.tgroup.att = attribute tgroupstyle { text }? +tbl.row.mdl = (entry | entrytbl)+ +tbl.entrytbl.mdl = colspec*, spanspec*, thead?, tbody +# ===== Element and attribute declarations follow. ===== + +# doc:A formal table in a document. +table = element table { table.attlist, tbl.table.mdl } +table.attlist &= + attribute frame { tbl.frame.attval }?, + attribute colsep { yesorno }?, + attribute rowsep { yesorno }?, + tbl.table.att, + bodyatt, + secur +# doc:A wrapper for the main content of a table, or part of a table. +tgroup = element tgroup { tgroup.attlist, tbl.tgroup.mdl } +tgroup.attlist &= + attribute cols { text }, + tbl.tgroup.att, + attribute colsep { yesorno }?, + attribute rowsep { yesorno }?, + attribute align { "left" | "right" | "center" | "justify" | "char" }?, + attribute char { text }?, + attribute charoff { text }?, + secur +# doc:Specifications for a column in a table. +colspec = element colspec { colspec.attlist, empty } +colspec.attlist &= + attribute colnum { text }?, + attribute colname { text }?, + attribute colwidth { text }?, + attribute colsep { yesorno }?, + attribute rowsep { yesorno }?, + attribute align { "left" | "right" | "center" | "justify" | "char" }?, + attribute char { text }?, + attribute charoff { text }? +# doc:Formatting information for a spanned column in a table. +spanspec = element spanspec { spanspec.attlist, empty } +spanspec.attlist &= + attribute namest { text }, + attribute nameend { text }, + attribute spanname { text }, + attribute colsep { yesorno }?, + attribute rowsep { yesorno }?, + attribute align { "left" | "right" | "center" | "justify" | "char" }?, + attribute char { text }?, + attribute charoff { text }? +# doc:A table header consisting of one or more rows. +thead = element thead { thead.attlist, tbl.hdft.mdl } +thead.attlist &= + attribute valign { "top" | "middle" | "bottom" }?, + secur +# doc:A table footer consisting of one or more rows. +tfoot = element tfoot { tfoot.attlist, tbl.hdft.mdl } +tfoot.attlist &= + attribute valign { "top" | "middle" | "bottom" }?, + secur +# doc:A wrapper for the rows of a table or informal table. +tbody = element tbody { tbody.attlist, tbl.tbody.mdl } +tbody.attlist &= + attribute valign { "top" | "middle" | "bottom" }?, + secur +# doc:A row in a table. +row = element row { row.attlist, tbl.row.mdl } +row.attlist &= + attribute rowsep { yesorno }?, + attribute valign { "top" | "middle" | "bottom" }?, + secur +# doc:A subtable appearing in place of an Entry in a table. +entrytbl = element entrytbl { entrytbl.attlist, tbl.entrytbl.mdl } +entrytbl.attlist &= + attribute cols { text }, + tbl.tgroup.att, + attribute colname { text }?, + attribute spanname { text }?, + attribute namest { text }?, + attribute nameend { text }?, + attribute colsep { yesorno }?, + attribute rowsep { yesorno }?, + attribute align { "left" | "right" | "center" | "justify" | "char" }?, + attribute char { text }?, + attribute charoff { text }?, + secur +# doc:A cell in a table. +entry = element entry { entry.attlist, tbl.entry.mdl* } +entry.attlist &= + attribute colname { text }?, + attribute namest { text }?, + attribute nameend { text }?, + attribute spanname { text }?, + attribute morerows { text }?, + attribute colsep { yesorno }?, + attribute rowsep { yesorno }?, + attribute align { "left" | "right" | "center" | "justify" | "char" }?, + attribute char { text }?, + attribute charoff { text }?, + attribute rotate { yesorno }?, + attribute valign { "top" | "middle" | "bottom" }?, + secur +# End of DocBook CALS Table Model V4.5 ................................. + +# ...................................................................... diff --git a/defensive-coding/docbook-schema/dbhierx.rnc b/defensive-coding/docbook-schema/dbhierx.rnc new file mode 100644 index 0000000..56015a3 --- /dev/null +++ b/defensive-coding/docbook-schema/dbhierx.rnc @@ -0,0 +1,1549 @@ +# ...................................................................... + +# DocBook document hierarchy module V4.5 ............................... + +# File dbhierx.mod ..................................................... + +# Copyright 1992-2004 HaL Computer Systems, Inc., +# O'Reilly & Associates, Inc., ArborText, Inc., Fujitsu Software +# Corporation, Norman Walsh, Sun Microsystems, Inc., and the +# Organization for the Advancement of Structured Information +# Standards (OASIS). +# +# $Id: dbhierx.mod 6340 2006-10-03 13:23:24Z nwalsh $ +# +# Permission to use, copy, modify and distribute the DocBook DTD +# and its accompanying documentation for any purpose and without fee +# is hereby granted in perpetuity, provided that the above copyright +# notice and this paragraph appear in all copies. The copyright +# holders make no representation about the suitability of the DTD for +# any purpose. It is provided "as is" without expressed or implied +# warranty. +# +# If you modify the DocBook DTD in any way, except for declaring and +# referencing additional sets of general entities and declaring +# additional notations, label your DTD as a variant of DocBook. See +# the maintenance documentation for more information. +# +# Please direct all questions, bug reports, or suggestions for +# changes to the docbook@lists.oasis-open.org mailing list. For more +# information, see http://www.oasis-open.org/docbook/. + +# ...................................................................... + +# This module contains the definitions for the overall document +# hierarchies of DocBook documents. It covers computer documentation +# manuals and manual fragments, as well as reference entries (such as +# man pages) and technical journals or anthologies containing +# articles. +# +# This module depends on the DocBook information pool module. All +# elements and entities referenced but not defined here are assumed +# to be defined in the information pool module. +# +# In DTD driver files referring to this module, please use an entity +# declaration that uses the public identifier shown below: +# +# +# %dbhier; +# +# See the documentation for detailed information on the parameter +# entity and module scheme used in DocBook, customizing DocBook and +# planning for interchange, and changes made since the last release +# of DocBook. + +# ...................................................................... + +# Entities for module inclusions ....................................... + +# ...................................................................... + +# Entities for element classes ......................................... + +local.appendix.class = notAllowed +appendix.class = appendix | local.appendix.class +local.article.class = notAllowed +article.class = article | local.article.class +local.book.class = notAllowed +book.class = book | local.book.class +local.chapter.class = notAllowed +chapter.class = chapter | local.chapter.class +local.index.class = notAllowed +index.class = index | setindex | local.index.class +local.refentry.class = notAllowed +refentry.class = refentry | local.refentry.class +local.section.class = notAllowed +section.class = section | local.section.class +local.nav.class = notAllowed +nav.class = + toc | lot | index | glossary | bibliography | local.nav.class +# Redeclaration placeholder ............................................ + +# For redeclaring entities that are declared after this point while +# retaining their references to the entities that are declared before +# this point + +# ...................................................................... + +# Entities for element mixtures ........................................ +local.divcomponent.mix = notAllowed +divcomponent.mix = + list.class + | admon.class + | linespecific.class + | synop.class + | para.class + | informal.class + | formal.class + | compound.class + | genobj.class + | descobj.class + | ndxterm.class + | beginpage + | forms.hook + | local.divcomponent.mix +local.refcomponent.mix = notAllowed +refcomponent.mix = + list.class + | admon.class + | linespecific.class + | synop.class + | para.class + | informal.class + | formal.class + | compound.class + | genobj.class + | descobj.class + | ndxterm.class + | beginpage + | forms.hook + | local.refcomponent.mix +local.indexdivcomponent.mix = notAllowed +indexdivcomponent.mix = + itemizedlist + | orderedlist + | variablelist + | simplelist + | linespecific.class + | synop.class + | para.class + | informal.class + | anchor + | remark + | link.char.class + | beginpage + | local.indexdivcomponent.mix +local.refname.char.mix = notAllowed +refname.char.mix = text | tech.char.class | local.refname.char.mix +local.partcontent.mix = notAllowed +partcontent.mix = + appendix.class + | chapter.class + | nav.class + | article.class + | preface + | refentry.class + | reference + | local.partcontent.mix +local.refinline.char.mix = notAllowed +refinline.char.mix = + text + | xref.char.class + | gen.char.class + | link.char.class + | tech.char.class + | base.char.class + | docinfo.char.class + | other.char.class + | ndxterm.class + | beginpage + | local.refinline.char.mix +local.refclass.char.mix = notAllowed +refclass.char.mix = text | application | local.refclass.char.mix +# Redeclaration placeholder 2 .......................................... + +# For redeclaring entities that are declared after this point while +# retaining their references to the entities that are declared before +# this point + +# ...................................................................... + +# Entities for content models .......................................... +div.title.content = title, subtitle?, titleabbrev? +bookcomponent.title.content = title, subtitle?, titleabbrev? +sect.title.content = title, subtitle?, titleabbrev? +refsect.title.content = title, subtitle?, titleabbrev? +bookcomponent.content = + (divcomponent.mix+, + (sect1* | refentry.class* | simplesect* | section.class*)) + | (sect1+ | refentry.class+ | simplesect+ | section.class+) +# ...................................................................... + +# Set and SetInfo ...................................................... +local.set.attrib = empty +set.role.attrib = role.attrib +# doc:A collection of books. +set = + element set { + set.attlist, + div.title.content?, + setinfo?, + toc?, + (set | book.class)+, + setindex? + } +# end of set.element + +# FPI: SGML formal public identifier +set.attlist &= + attribute fpi { text }?, + status.attrib, + common.attrib, + set.role.attrib, + local.set.attrib +# end of set.attlist + +# end of set.module +local.setinfo.attrib = empty +setinfo.role.attrib = role.attrib +# doc:Meta-information for a Set. +setinfo = element setinfo { setinfo.attlist, info.class+ } +# end of setinfo.element + +# Contents: IDs of the ToC, Books, and SetIndex that comprise +# the set, in the order of their appearance +setinfo.attlist &= + attribute contents { xsd:IDREFS }?, + common.attrib, + setinfo.role.attrib, + local.setinfo.attrib +# end of setinfo.attlist + +# end of setinfo.module + +# end of set.content.module + +# ...................................................................... + +# Book and BookInfo .................................................... +local.book.attrib = empty +book.role.attrib = role.attrib +# doc:A book. +book = + element book { + book.attlist, + div.title.content?, + bookinfo?, + (dedication + | toc + | lot + | glossary + | bibliography + | preface + | chapter.class + | reference + | part + | article.class + | appendix.class + | index.class + | colophon)* + } +# end of book.element + +# FPI: SGML formal public identifier +book.attlist &= + attribute fpi { text }?, + label.attrib, + status.attrib, + common.attrib, + book.role.attrib, + local.book.attrib +# end of book.attlist + +# end of book.module +local.bookinfo.attrib = empty +bookinfo.role.attrib = role.attrib +# doc:Meta-information for a Book. +bookinfo = element bookinfo { bookinfo.attlist, info.class+ } +# end of bookinfo.element + +# Contents: IDs of the ToC, LoTs, Prefaces, Parts, Chapters, +# Appendixes, References, GLossary, Bibliography, and indexes +# comprising the Book, in the order of their appearance +bookinfo.attlist &= + attribute contents { xsd:IDREFS }?, + common.attrib, + bookinfo.role.attrib, + local.bookinfo.attrib +# end of bookinfo.attlist + +# end of bookinfo.module + +# end of book.content.module + +# ...................................................................... + +# Dedication, ToC, and LoT ............................................. +local.dedication.attrib = empty +dedication.role.attrib = role.attrib +# doc:A wrapper for the dedication section of a book. +dedication = + element dedication { + dedication.attlist, sect.title.content?, legalnotice.mix+ + } +# end of dedication.element +dedication.attlist &= + status.attrib, + common.attrib, + dedication.role.attrib, + local.dedication.attrib +# end of dedication.attlist + +# end of dedication.module +local.colophon.attrib = empty +colophon.role.attrib = role.attrib +# doc:Text at the back of a book describing facts about its production. +colophon = + element colophon { + colophon.attlist, sect.title.content?, textobject.mix+ + } +# end of colophon.element +colophon.attlist &= + status.attrib, + common.attrib, + colophon.role.attrib, + local.colophon.attrib +# end of colophon.attlist + +# end of colophon.module +local.toc.attrib = empty +toc.role.attrib = role.attrib +# doc:A table of contents. +toc = + element toc { + toc.attlist, + beginpage?, + bookcomponent.title.content?, + tocfront*, + (tocpart | tocchap)*, + tocback* + } +# end of toc.element +toc.attlist &= + pagenum.attrib, common.attrib, toc.role.attrib, local.toc.attrib +# end of toc.attlist + +# end of toc.module +local.tocfront.attrib = empty +tocfront.role.attrib = role.attrib +# doc:An entry in a table of contents for a front matter component. +tocfront = element tocfront { tocfront.attlist, para.char.mix* } +# end of tocfront.element + +# to element that this entry represents +tocfront.attlist &= + label.attrib, + linkend.attrib, + pagenum.attrib, + common.attrib, + tocfront.role.attrib, + local.tocfront.attrib +# end of tocfront.attlist + +# end of tocfront.module +local.tocentry.attrib = empty +tocentry.role.attrib = role.attrib +# doc:A component title in a table of contents. +tocentry = element tocentry { tocentry.attlist, para.char.mix* } +# end of tocentry.element + +# to element that this entry represents +tocentry.attlist &= + linkend.attrib, + pagenum.attrib, + common.attrib, + tocentry.role.attrib, + local.tocentry.attrib +# end of tocentry.attlist + +# end of tocentry.module +local.tocpart.attrib = empty +tocpart.role.attrib = role.attrib +# doc:An entry in a table of contents for a part of a book. +tocpart = element tocpart { tocpart.attlist, tocentry+, tocchap* } +# end of tocpart.element +tocpart.attlist &= + common.attrib, tocpart.role.attrib, local.tocpart.attrib +# end of tocpart.attlist + +# end of tocpart.module +local.tocchap.attrib = empty +tocchap.role.attrib = role.attrib +# doc:An entry in a table of contents for a component in the body of a document. +tocchap = element tocchap { tocchap.attlist, tocentry+, toclevel1* } +# end of tocchap.element +tocchap.attlist &= + label.attrib, common.attrib, tocchap.role.attrib, local.tocchap.attrib +# end of tocchap.attlist + +# end of tocchap.module +local.toclevel1.attrib = empty +toclevel1.role.attrib = role.attrib +# doc:A top-level entry within a table of contents entry for a chapter-like component. +toclevel1 = + element toclevel1 { toclevel1.attlist, tocentry+, toclevel2* } +# end of toclevel1.element +toclevel1.attlist &= + common.attrib, toclevel1.role.attrib, local.toclevel1.attrib +# end of toclevel1.attlist + +# end of toclevel1.module +local.toclevel2.attrib = empty +toclevel2.role.attrib = role.attrib +# doc:A second-level entry within a table of contents entry for a chapter-like component. +toclevel2 = + element toclevel2 { toclevel2.attlist, tocentry+, toclevel3* } +# end of toclevel2.element +toclevel2.attlist &= + common.attrib, toclevel2.role.attrib, local.toclevel2.attrib +# end of toclevel2.attlist + +# end of toclevel2.module +local.toclevel3.attrib = empty +toclevel3.role.attrib = role.attrib +# doc:A third-level entry within a table of contents entry for a chapter-like component. +toclevel3 = + element toclevel3 { toclevel3.attlist, tocentry+, toclevel4* } +# end of toclevel3.element +toclevel3.attlist &= + common.attrib, toclevel3.role.attrib, local.toclevel3.attrib +# end of toclevel3.attlist + +# end of toclevel3.module +local.toclevel4.attrib = empty +toclevel4.role.attrib = role.attrib +# doc:A fourth-level entry within a table of contents entry for a chapter-like component. +toclevel4 = + element toclevel4 { toclevel4.attlist, tocentry+, toclevel5* } +# end of toclevel4.element +toclevel4.attlist &= + common.attrib, toclevel4.role.attrib, local.toclevel4.attrib +# end of toclevel4.attlist + +# end of toclevel4.module +local.toclevel5.attrib = empty +toclevel5.role.attrib = role.attrib +# doc:A fifth-level entry within a table of contents entry for a chapter-like component. +toclevel5 = element toclevel5 { toclevel5.attlist, tocentry+ } +# end of toclevel5.element +toclevel5.attlist &= + common.attrib, toclevel5.role.attrib, local.toclevel5.attrib +# end of toclevel5.attlist + +# end of toclevel5.module +local.tocback.attrib = empty +tocback.role.attrib = role.attrib +# doc:An entry in a table of contents for a back matter component. +tocback = element tocback { tocback.attlist, para.char.mix* } +# end of tocback.element + +# to element that this entry represents +tocback.attlist &= + label.attrib, + linkend.attrib, + pagenum.attrib, + common.attrib, + tocback.role.attrib, + local.tocback.attrib +# end of tocback.attlist + +# end of tocback.module + +# end of toc.content.module +local.lot.attrib = empty +lot.role.attrib = role.attrib +# doc:A list of the titles of formal objects (as tables or figures) in a document. +lot = + element lot { + lot.attlist, beginpage?, bookcomponent.title.content?, lotentry* + } +# end of lot.element +lot.attlist &= + label.attrib, common.attrib, lot.role.attrib, local.lot.attrib +# end of lot.attlist + +# end of lot.module +local.lotentry.attrib = empty +lotentry.role.attrib = role.attrib +# doc:An entry in a list of titles. +lotentry = element lotentry { lotentry.attlist, para.char.mix* } +# end of lotentry.element + +# SrcCredit: Information about the source of the entry, +# as for a list of illustrations + +# linkend: to element that this entry represents +lotentry.attlist &= + linkend.attrib, + pagenum.attrib, + attribute srccredit { text }?, + common.attrib, + lotentry.role.attrib, + local.lotentry.attrib +# end of lotentry.attlist + +# end of lotentry.module + +# end of lot.content.module + +# ...................................................................... + +# Appendix, Chapter, Part, Preface, Reference, PartIntro ............... +local.appendix.attrib = empty +appendix.role.attrib = role.attrib +# doc:An appendix in a Book or Article. +appendix = + element appendix { + appendix.attlist, + beginpage?, + appendixinfo?, + bookcomponent.title.content, + nav.class*, + tocchap?, + bookcomponent.content, + nav.class* + } +# end of appendix.element +appendix.attlist &= + label.attrib, + status.attrib, + common.attrib, + appendix.role.attrib, + local.appendix.attrib +# end of appendix.attlist + +# end of appendix.module +local.chapter.attrib = empty +chapter.role.attrib = role.attrib +# doc:A chapter, as of a book. +chapter = + element chapter { + chapter.attlist, + beginpage?, + chapterinfo?, + bookcomponent.title.content, + nav.class*, + tocchap?, + bookcomponent.content, + nav.class* + } +# end of chapter.element +chapter.attlist &= + label.attrib, + status.attrib, + common.attrib, + chapter.role.attrib, + local.chapter.attrib +# end of chapter.attlist + +# end of chapter.module + +# Note that Part was to have its content model reduced in V4.5. This +# change will not be made after all. +local.part.attrib = empty +part.role.attrib = role.attrib +# doc:A division in a book. +part = + element part { + part.attlist, + beginpage?, + partinfo?, + bookcomponent.title.content, + partintro?, + partcontent.mix+ + } +# end of part.element +part.attlist &= + label.attrib, + status.attrib, + common.attrib, + part.role.attrib, + local.part.attrib +# end of part.attlist + +# ELEMENT PartIntro (defined below) + +# end of part.module +local.preface.attrib = empty +preface.role.attrib = role.attrib +# doc:Introductory matter preceding the first chapter of a book. +preface = + element preface { + preface.attlist, + beginpage?, + prefaceinfo?, + bookcomponent.title.content, + nav.class*, + tocchap?, + bookcomponent.content, + nav.class* + } +# end of preface.element +preface.attlist &= + status.attrib, + common.attrib, + preface.role.attrib, + local.preface.attrib +# end of preface.attlist + +# end of preface.module +local.reference.attrib = empty +reference.role.attrib = role.attrib +# doc:A collection of reference entries. +reference = + element reference { + reference.attlist, + beginpage?, + referenceinfo?, + bookcomponent.title.content, + partintro?, + refentry.class+ + } +# end of reference.element +reference.attlist &= + label.attrib, + status.attrib, + common.attrib, + reference.role.attrib, + local.reference.attrib +# end of reference.attlist + +# ELEMENT PartIntro (defined below) + +# end of reference.module +local.partintro.attrib = empty +partintro.role.attrib = role.attrib +# doc:An introduction to the contents of a part. +partintro = + element partintro { + partintro.attlist, div.title.content?, bookcomponent.content + } +# end of partintro.element +partintro.attlist &= + label.attrib, + common.attrib, + partintro.role.attrib, + local.partintro.attrib +# end of partintro.attlist + +# end of partintro.module + +# ...................................................................... + +# Other Info elements .................................................. +local.appendixinfo.attrib = empty +appendixinfo.role.attrib = role.attrib +# doc:Meta-information for an Appendix. +appendixinfo = + element appendixinfo { appendixinfo.attlist, info.class+ } +# end of appendixinfo.element +appendixinfo.attlist &= + common.attrib, appendixinfo.role.attrib, local.appendixinfo.attrib +# end of appendixinfo.attlist + +# end of appendixinfo.module +local.bibliographyinfo.attrib = empty +bibliographyinfo.role.attrib = role.attrib +# doc:Meta-information for a Bibliography. +bibliographyinfo = + element bibliographyinfo { bibliographyinfo.attlist, info.class+ } +# end of bibliographyinfo.element +bibliographyinfo.attlist &= + common.attrib, + bibliographyinfo.role.attrib, + local.bibliographyinfo.attrib +# end of bibliographyinfo.attlist + +# end of bibliographyinfo.module +local.chapterinfo.attrib = empty +chapterinfo.role.attrib = role.attrib +# doc:Meta-information for a Chapter. +chapterinfo = element chapterinfo { chapterinfo.attlist, info.class+ } +# end of chapterinfo.element +chapterinfo.attlist &= + common.attrib, chapterinfo.role.attrib, local.chapterinfo.attrib +# end of chapterinfo.attlist + +# end of chapterinfo.module +local.glossaryinfo.attrib = empty +glossaryinfo.role.attrib = role.attrib +# doc:Meta-information for a Glossary. +glossaryinfo = + element glossaryinfo { glossaryinfo.attlist, info.class+ } +# end of glossaryinfo.element +glossaryinfo.attlist &= + common.attrib, glossaryinfo.role.attrib, local.glossaryinfo.attrib +# end of glossaryinfo.attlist + +# end of glossaryinfo.module +local.indexinfo.attrib = empty +indexinfo.role.attrib = role.attrib +# doc:Meta-information for an Index. +indexinfo = element indexinfo { indexinfo.attlist, info.class+ } +# end of indexinfo.element +indexinfo.attlist &= + common.attrib, indexinfo.role.attrib, local.indexinfo.attrib +# end of indexinfo.attlist + +# end of indexinfo.module +local.setindexinfo.attrib = empty +setindexinfo.role.attrib = role.attrib +# doc:Meta-information for a SetIndex. +setindexinfo = + element setindexinfo { setindexinfo.attlist, info.class+ } +# end of setindexinfo.element +setindexinfo.attlist &= + common.attrib, setindexinfo.role.attrib, local.setindexinfo.attrib +# end of setindexinfo.attlist + +# end of setindexinfo.module +local.partinfo.attrib = empty +partinfo.role.attrib = role.attrib +# doc:Meta-information for a Part. +partinfo = element partinfo { partinfo.attlist, info.class+ } +# end of partinfo.element +partinfo.attlist &= + common.attrib, partinfo.role.attrib, local.partinfo.attrib +# end of partinfo.attlist + +# end of partinfo.module +local.prefaceinfo.attrib = empty +prefaceinfo.role.attrib = role.attrib +# doc:Meta-information for a Preface. +prefaceinfo = element prefaceinfo { prefaceinfo.attlist, info.class+ } +# end of prefaceinfo.element +prefaceinfo.attlist &= + common.attrib, prefaceinfo.role.attrib, local.prefaceinfo.attrib +# end of prefaceinfo.attlist + +# end of prefaceinfo.module +local.refentryinfo.attrib = empty +refentryinfo.role.attrib = role.attrib +# doc:Meta-information for a Refentry. +refentryinfo = + element refentryinfo { refentryinfo.attlist, info.class+ } +# end of refentryinfo.element +refentryinfo.attlist &= + common.attrib, refentryinfo.role.attrib, local.refentryinfo.attrib +# end of refentryinfo.attlist + +# end of refentryinfo.module +local.refsectioninfo.attrib = empty +refsectioninfo.role.attrib = role.attrib +# doc:Meta-information for a refsection. +refsectioninfo = + element refsectioninfo { refsectioninfo.attlist, info.class+ } +# end of refsectioninfo.element +refsectioninfo.attlist &= + common.attrib, refsectioninfo.role.attrib, local.refsectioninfo.attrib +# end of refsectioninfo.attlist + +# end of refsectioninfo.module +local.refsect1info.attrib = empty +refsect1info.role.attrib = role.attrib +# doc:Meta-information for a RefSect1. +refsect1info = + element refsect1info { refsect1info.attlist, info.class+ } +# end of refsect1info.element +refsect1info.attlist &= + common.attrib, refsect1info.role.attrib, local.refsect1info.attrib +# end of refsect1info.attlist + +# end of refsect1info.module +local.refsect2info.attrib = empty +refsect2info.role.attrib = role.attrib +# doc:Meta-information for a RefSect2. +refsect2info = + element refsect2info { refsect2info.attlist, info.class+ } +# end of refsect2info.element +refsect2info.attlist &= + common.attrib, refsect2info.role.attrib, local.refsect2info.attrib +# end of refsect2info.attlist + +# end of refsect2info.module +local.refsect3info.attrib = empty +refsect3info.role.attrib = role.attrib +# doc:Meta-information for a RefSect3. +refsect3info = + element refsect3info { refsect3info.attlist, info.class+ } +# end of refsect3info.element +refsect3info.attlist &= + common.attrib, refsect3info.role.attrib, local.refsect3info.attrib +# end of refsect3info.attlist + +# end of refsect3info.module +local.refsynopsisdivinfo.attrib = empty +refsynopsisdivinfo.role.attrib = role.attrib +# doc:Meta-information for a RefSynopsisDiv. +refsynopsisdivinfo = + element refsynopsisdivinfo { refsynopsisdivinfo.attlist, info.class+ } +# end of refsynopsisdivinfo.element +refsynopsisdivinfo.attlist &= + common.attrib, + refsynopsisdivinfo.role.attrib, + local.refsynopsisdivinfo.attrib +# end of refsynopsisdivinfo.attlist + +# end of refsynopsisdivinfo.module +local.referenceinfo.attrib = empty +referenceinfo.role.attrib = role.attrib +# doc:Meta-information for a Reference. +referenceinfo = + element referenceinfo { referenceinfo.attlist, info.class+ } +# end of referenceinfo.element +referenceinfo.attlist &= + common.attrib, referenceinfo.role.attrib, local.referenceinfo.attrib +# end of referenceinfo.attlist + +# end of referenceinfo.module +local.sect1info.attrib = empty +sect1info.role.attrib = role.attrib +# doc:Meta-information for a Sect1. +sect1info = element sect1info { sect1info.attlist, info.class+ } +# end of sect1info.element +sect1info.attlist &= + common.attrib, sect1info.role.attrib, local.sect1info.attrib +# end of sect1info.attlist +local.sect2info.attrib = empty +sect2info.role.attrib = role.attrib +# doc:Meta-information for a Sect2. +sect2info = element sect2info { sect2info.attlist, info.class+ } +# end of sect2info.element +sect2info.attlist &= + common.attrib, sect2info.role.attrib, local.sect2info.attrib +# end of sect2info.attlist +local.sect3info.attrib = empty +sect3info.role.attrib = role.attrib +# doc:Meta-information for a Sect3. +sect3info = element sect3info { sect3info.attlist, info.class+ } +# end of sect3info.element +sect3info.attlist &= + common.attrib, sect3info.role.attrib, local.sect3info.attrib +# end of sect3info.attlist +local.sect4info.attrib = empty +sect4info.role.attrib = role.attrib +# doc:Meta-information for a Sect4. +sect4info = element sect4info { sect4info.attlist, info.class+ } +# end of sect4info.element +sect4info.attlist &= + common.attrib, sect4info.role.attrib, local.sect4info.attrib +# end of sect4info.attlist +local.sect5info.attrib = empty +sect5info.role.attrib = role.attrib +# doc:Meta-information for a Sect5. +sect5info = element sect5info { sect5info.attlist, info.class+ } +# end of sect5info.element +sect5info.attlist &= + common.attrib, sect5info.role.attrib, local.sect5info.attrib +# end of sect5info.attlist + +# ...................................................................... + +# Section (parallel to Sect*) ......................................... +local.section.attrib = empty +section.role.attrib = role.attrib +# doc:A recursive section. +section = + element section { + section.attlist, + sectioninfo?, + sect.title.content, + nav.class*, + ((divcomponent.mix+, + (refentry.class* | section.class* | simplesect*)) + | refentry.class+ + | section.class+ + | simplesect+), + nav.class* + } +# end of section.element +section.attlist &= + label.attrib, + status.attrib, + common.attrib, + section.role.attrib, + local.section.attrib +# end of section.attlist + +# end of section.module +sectioninfo.role.attrib = role.attrib +local.sectioninfo.attrib = empty +# doc:Meta-information for a recursive section. +sectioninfo = element sectioninfo { sectioninfo.attlist, info.class+ } +# end of sectioninfo.element +sectioninfo.attlist &= + common.attrib, sectioninfo.role.attrib, local.sectioninfo.attrib +# end of sectioninfo.attlist + +# end of sectioninfo.module + +# end of section.content.module + +# ...................................................................... + +# Sect1, Sect2, Sect3, Sect4, Sect5 .................................... +local.sect1.attrib = empty +sect1.role.attrib = role.attrib +# doc:A top-level section of document. +sect1 = + element sect1 { + sect1.attlist, + sect1info?, + sect.title.content, + nav.class*, + ((divcomponent.mix+, (refentry.class* | sect2* | simplesect*)) + | refentry.class+ + | sect2+ + | simplesect+), + nav.class* + } +# end of sect1.element + +# Renderas: Indicates the format in which the heading should +# appear +sect1.attlist &= + attribute renderas { "sect2" | "sect3" | "sect4" | "sect5" }?, + label.attrib, + status.attrib, + common.attrib, + sect1.role.attrib, + local.sect1.attrib +# end of sect1.attlist + +# end of sect1.module +local.sect2.attrib = empty +sect2.role.attrib = role.attrib +# doc:A subsection within a Sect1. +sect2 = + element sect2 { + sect2.attlist, + sect2info?, + sect.title.content, + nav.class*, + ((divcomponent.mix+, (refentry.class* | sect3* | simplesect*)) + | refentry.class+ + | sect3+ + | simplesect+), + nav.class* + } +# end of sect2.element + +# Renderas: Indicates the format in which the heading should +# appear +sect2.attlist &= + attribute renderas { "sect1" | "sect3" | "sect4" | "sect5" }?, + label.attrib, + status.attrib, + common.attrib, + sect2.role.attrib, + local.sect2.attrib +# end of sect2.attlist + +# end of sect2.module +local.sect3.attrib = empty +sect3.role.attrib = role.attrib +# doc:A subsection within a Sect2. +sect3 = + element sect3 { + sect3.attlist, + sect3info?, + sect.title.content, + nav.class*, + ((divcomponent.mix+, (refentry.class* | sect4* | simplesect*)) + | refentry.class+ + | sect4+ + | simplesect+), + nav.class* + } +# end of sect3.element + +# Renderas: Indicates the format in which the heading should +# appear +sect3.attlist &= + attribute renderas { "sect1" | "sect2" | "sect4" | "sect5" }?, + label.attrib, + status.attrib, + common.attrib, + sect3.role.attrib, + local.sect3.attrib +# end of sect3.attlist + +# end of sect3.module +local.sect4.attrib = empty +sect4.role.attrib = role.attrib +# doc:A subsection within a Sect3. +sect4 = + element sect4 { + sect4.attlist, + sect4info?, + sect.title.content, + nav.class*, + ((divcomponent.mix+, (refentry.class* | sect5* | simplesect*)) + | refentry.class+ + | sect5+ + | simplesect+), + nav.class* + } +# end of sect4.element + +# Renderas: Indicates the format in which the heading should +# appear +sect4.attlist &= + attribute renderas { "sect1" | "sect2" | "sect3" | "sect5" }?, + label.attrib, + status.attrib, + common.attrib, + sect4.role.attrib, + local.sect4.attrib +# end of sect4.attlist + +# end of sect4.module +local.sect5.attrib = empty +sect5.role.attrib = role.attrib +# doc:A subsection within a Sect4. +sect5 = + element sect5 { + sect5.attlist, + sect5info?, + sect.title.content, + nav.class*, + ((divcomponent.mix+, (refentry.class* | simplesect*)) + | refentry.class+ + | simplesect+), + nav.class* + } +# end of sect5.element + +# Renderas: Indicates the format in which the heading should +# appear +sect5.attlist &= + attribute renderas { "sect1" | "sect2" | "sect3" | "sect4" }?, + label.attrib, + status.attrib, + common.attrib, + sect5.role.attrib, + local.sect5.attrib +# end of sect5.attlist + +# end of sect5.module +local.simplesect.attrib = empty +simplesect.role.attrib = role.attrib +# doc:A section of a document with no subdivisions. +simplesect = + element simplesect { + simplesect.attlist, sect.title.content, divcomponent.mix+ + } +# end of simplesect.element +simplesect.attlist &= + common.attrib, simplesect.role.attrib, local.simplesect.attrib +# end of simplesect.attlist + +# end of simplesect.module + +# ...................................................................... + +# Bibliography ......................................................... +local.bibliography.attrib = empty +bibliography.role.attrib = role.attrib +# doc:A bibliography. +bibliography = + element bibliography { + bibliography.attlist, + bibliographyinfo?, + bookcomponent.title.content?, + component.mix*, + (bibliodiv+ | (biblioentry | bibliomixed)+) + } +# end of bibliography.element +bibliography.attlist &= + status.attrib, + common.attrib, + bibliography.role.attrib, + local.bibliography.attrib +# end of bibliography.attlist + +# end of bibliography.module +local.bibliodiv.attrib = empty +bibliodiv.role.attrib = role.attrib +# doc:A section of a Bibliography. +bibliodiv = + element bibliodiv { + bibliodiv.attlist, + sect.title.content?, + component.mix*, + (biblioentry | bibliomixed)+ + } +# end of bibliodiv.element +bibliodiv.attlist &= + status.attrib, + common.attrib, + bibliodiv.role.attrib, + local.bibliodiv.attrib +# end of bibliodiv.attlist + +# end of bibliodiv.module + +# end of bibliography.content.module + +# ...................................................................... + +# Glossary ............................................................. +local.glossary.attrib = empty +glossary.role.attrib = role.attrib +# doc:A glossary. +glossary = + element glossary { + glossary.attlist, + glossaryinfo?, + bookcomponent.title.content?, + component.mix*, + (glossdiv+ | glossentry+), + bibliography? + } +# end of glossary.element +glossary.attlist &= + status.attrib, + common.attrib, + glossary.role.attrib, + local.glossary.attrib +# end of glossary.attlist + +# end of glossary.module +local.glossdiv.attrib = empty +glossdiv.role.attrib = role.attrib +# doc:A division in a Glossary. +glossdiv = + element glossdiv { + glossdiv.attlist, sect.title.content, component.mix*, glossentry+ + } +# end of glossdiv.element +glossdiv.attlist &= + status.attrib, + common.attrib, + glossdiv.role.attrib, + local.glossdiv.attrib +# end of glossdiv.attlist + +# end of glossdiv.module + +# end of glossary.content.module + +# ...................................................................... + +# Index and SetIndex ................................................... +local.indexes.attrib = empty +indexes.role.attrib = role.attrib +# doc:An index. +index = + element index { + index.attlist, + indexinfo?, + bookcomponent.title.content?, + component.mix*, + (indexdiv* | indexentry*) + } +# end of index.element +index.attlist &= + attribute type { text }?, + common.attrib, + indexes.role.attrib, + local.indexes.attrib +# end of index.attlist + +# doc:An index to a set of books. +setindex = + element setindex { + setindex.attlist, + setindexinfo?, + bookcomponent.title.content?, + component.mix*, + (indexdiv* | indexentry*) + } +# end of setindex.element +setindex.attlist &= + common.attrib, indexes.role.attrib, local.indexes.attrib +# end of setindex.attlist + +# end of indexes.module + +# SegmentedList in this content is useful for marking up permuted +# indices. +local.indexdiv.attrib = empty +indexdiv.role.attrib = role.attrib +# doc:A division in an index. +indexdiv = + element indexdiv { + indexdiv.attlist, + sect.title.content?, + (indexdivcomponent.mix*, (indexentry+ | segmentedlist)) + } +# end of indexdiv.element +indexdiv.attlist &= + common.attrib, indexdiv.role.attrib, local.indexdiv.attrib +# end of indexdiv.attlist + +# end of indexdiv.module + +# Index entries appear in the index, not the text. +local.indexentry.attrib = empty +indexentry.role.attrib = role.attrib +# doc:An entry in an index. +indexentry = + element indexentry { + indexentry.attlist, + primaryie, + (seeie | seealsoie)*, + (secondaryie, (seeie | seealsoie | tertiaryie)*)* + } +# end of indexentry.element +indexentry.attlist &= + common.attrib, indexentry.role.attrib, local.indexentry.attrib +# end of indexentry.attlist + +# end of indexentry.module +local.primsecterie.attrib = empty +primsecterie.role.attrib = role.attrib +# doc:A primary term in an index entry, not in the text. +primaryie = element primaryie { primaryie.attlist, ndxterm.char.mix* } +# end of primaryie.element + +# to IndexTerms that these entries represent +primaryie.attlist &= + linkends.attrib, + common.attrib, + primsecterie.role.attrib, + local.primsecterie.attrib +# end of primaryie.attlist + +# doc:A secondary term in an index entry, rather than in the text. +secondaryie = + element secondaryie { secondaryie.attlist, ndxterm.char.mix* } +# end of secondaryie.element + +# to IndexTerms that these entries represent +secondaryie.attlist &= + linkends.attrib, + common.attrib, + primsecterie.role.attrib, + local.primsecterie.attrib +# end of secondaryie.attlist + +# doc:A tertiary term in an index entry, rather than in the text. +tertiaryie = + element tertiaryie { tertiaryie.attlist, ndxterm.char.mix* } +# end of tertiaryie.element + +# to IndexTerms that these entries represent +tertiaryie.attlist &= + linkends.attrib, + common.attrib, + primsecterie.role.attrib, + local.primsecterie.attrib +# end of tertiaryie.attlist + +# end of primsecterie.module +local.seeie.attrib = empty +seeie.role.attrib = role.attrib +# doc:A See entry in an index, rather than in the text. +seeie = element seeie { seeie.attlist, ndxterm.char.mix* } +# end of seeie.element + +# to IndexEntry to look up +seeie.attlist &= + linkend.attrib, common.attrib, seeie.role.attrib, local.seeie.attrib +# end of seeie.attlist + +# end of seeie.module +local.seealsoie.attrib = empty +seealsoie.role.attrib = role.attrib +# doc:A See also entry in an index, rather than in the text. +seealsoie = element seealsoie { seealsoie.attlist, ndxterm.char.mix* } +# end of seealsoie.element + +# to related IndexEntries +seealsoie.attlist &= + linkends.attrib, + common.attrib, + seealsoie.role.attrib, + local.seealsoie.attrib +# end of seealsoie.attlist + +# end of seealsoie.module + +# end of index.content.module + +# ...................................................................... + +# RefEntry ............................................................. +local.refentry.attrib = empty +refentry.role.attrib = role.attrib +# doc:A reference page (originally a UNIX man-style reference page). +refentry = + element refentry { + refentry.attlist, + beginpage?, + ndxterm.class*, + refentryinfo?, + refmeta?, + (remark | link.char.class)*, + refnamediv+, + refsynopsisdiv?, + (refsect1+ | refsection+) + } +# end of refentry.element +refentry.attlist &= + status.attrib, + common.attrib, + refentry.role.attrib, + local.refentry.attrib +# end of refentry.attlist + +# end of refentry.module +local.refmeta.attrib = empty +refmeta.role.attrib = role.attrib +# doc:Meta-information for a reference entry. +refmeta = + element refmeta { + refmeta.attlist, + ndxterm.class*, + refentrytitle, + manvolnum?, + refmiscinfo*, + ndxterm.class* + } +# end of refmeta.element +refmeta.attlist &= + common.attrib, refmeta.role.attrib, local.refmeta.attrib +# end of refmeta.attlist + +# end of refmeta.module +local.refmiscinfo.attrib = empty +refmiscinfo.role.attrib = role.attrib +# doc:Meta-information for a reference entry other than the title and volume number. +refmiscinfo = + element refmiscinfo { refmiscinfo.attlist, docinfo.char.mix* } +# end of refmiscinfo.element + +# Class: Freely assignable parameter; no default +refmiscinfo.attlist &= + attribute class { text }?, + common.attrib, + refmiscinfo.role.attrib, + local.refmiscinfo.attrib +# end of refmiscinfo.attlist + +# end of refmiscinfo.module +local.refnamediv.attrib = empty +refnamediv.role.attrib = role.attrib +# doc:The name, purpose, and classification of a reference page. +refnamediv = + element refnamediv { + refnamediv.attlist, + refdescriptor?, + refname+, + refpurpose, + refclass*, + (remark | link.char.class)* + } +# end of refnamediv.element +refnamediv.attlist &= + common.attrib, refnamediv.role.attrib, local.refnamediv.attrib +# end of refnamediv.attlist + +# end of refnamediv.module +local.refdescriptor.attrib = empty +refdescriptor.role.attrib = role.attrib +# doc:A description of the topic of a reference page. +refdescriptor = + element refdescriptor { refdescriptor.attlist, refname.char.mix* } +# end of refdescriptor.element +refdescriptor.attlist &= + common.attrib, refdescriptor.role.attrib, local.refdescriptor.attrib +# end of refdescriptor.attlist + +# end of refdescriptor.module +local.refname.attrib = empty +refname.role.attrib = role.attrib +# doc:The name of (one of) the subject(s) of a reference page. +refname = element refname { refname.attlist, refname.char.mix* } +# end of refname.element +refname.attlist &= + common.attrib, refname.role.attrib, local.refname.attrib +# end of refname.attlist + +# end of refname.module +local.refpurpose.attrib = empty +refpurpose.role.attrib = role.attrib +# doc:A short (one sentence) synopsis of the topic of a reference page. +refpurpose = + element refpurpose { refpurpose.attlist, refinline.char.mix* } +# end of refpurpose.element +refpurpose.attlist &= + common.attrib, refpurpose.role.attrib, local.refpurpose.attrib +# end of refpurpose.attlist + +# end of refpurpose.module +local.refclass.attrib = empty +refclass.role.attrib = role.attrib +# doc:The scope or other indication of applicability of a reference entry. +refclass = element refclass { refclass.attlist, refclass.char.mix* } +# end of refclass.element +refclass.attlist &= + common.attrib, refclass.role.attrib, local.refclass.attrib +# end of refclass.attlist + +# end of refclass.module +local.refsynopsisdiv.attrib = empty +refsynopsisdiv.role.attrib = role.attrib +# doc:A syntactic synopsis of the subject of the reference page. +refsynopsisdiv = + element refsynopsisdiv { + refsynopsisdiv.attlist, + refsynopsisdivinfo?, + refsect.title.content?, + ((refcomponent.mix+, refsect2*) | refsect2+) + } +# end of refsynopsisdiv.element +refsynopsisdiv.attlist &= + common.attrib, refsynopsisdiv.role.attrib, local.refsynopsisdiv.attrib +# end of refsynopsisdiv.attlist + +# end of refsynopsisdiv.module +local.refsection.attrib = empty +refsection.role.attrib = role.attrib +# doc:A recursive section in a refentry. +refsection = + element refsection { + refsection.attlist, + refsectioninfo?, + refsect.title.content, + ((refcomponent.mix+, refsection*) | refsection+) + } +# end of refsection.element +refsection.attlist &= + status.attrib, + common.attrib, + refsection.role.attrib, + local.refsection.attrib +# end of refsection.attlist + +# end of refsection.module +local.refsect1.attrib = empty +refsect1.role.attrib = role.attrib +# doc:A major subsection of a reference entry. +refsect1 = + element refsect1 { + refsect1.attlist, + refsect1info?, + refsect.title.content, + ((refcomponent.mix+, refsect2*) | refsect2+) + } +# end of refsect1.element +refsect1.attlist &= + status.attrib, + common.attrib, + refsect1.role.attrib, + local.refsect1.attrib +# end of refsect1.attlist + +# end of refsect1.module +local.refsect2.attrib = empty +refsect2.role.attrib = role.attrib +# doc:A subsection of a RefSect1. +refsect2 = + element refsect2 { + refsect2.attlist, + refsect2info?, + refsect.title.content, + ((refcomponent.mix+, refsect3*) | refsect3+) + } +# end of refsect2.element +refsect2.attlist &= + status.attrib, + common.attrib, + refsect2.role.attrib, + local.refsect2.attrib +# end of refsect2.attlist + +# end of refsect2.module +local.refsect3.attrib = empty +refsect3.role.attrib = role.attrib +# doc:A subsection of a RefSect2. +refsect3 = + element refsect3 { + refsect3.attlist, + refsect3info?, + refsect.title.content, + refcomponent.mix+ + } +# end of refsect3.element +refsect3.attlist &= + status.attrib, + common.attrib, + refsect3.role.attrib, + local.refsect3.attrib +# end of refsect3.attlist + +# end of refsect3.module + +# end of refentry.content.module + +# ...................................................................... + +# Article .............................................................. + +# An Article is a chapter-level, stand-alone document that is often, +# but need not be, collected into a Book. +local.article.attrib = empty +article.role.attrib = role.attrib +# doc:An article. +article = + element article { + article.attlist, + div.title.content?, + articleinfo?, + tocchap?, + lot*, + bookcomponent.content, + (nav.class | appendix.class | colophon | ackno)* + } +# end of article.element + +# Class: Indicates the type of a particular article; +# all articles have the same structure and general purpose. +# No default. + +# ParentBook: ID of the enclosing Book +article.attlist &= + attribute class { + "journalarticle" + | "productsheet" + | "whitepaper" + | "techreport" + | "specification" + | "faq" + }?, + attribute parentbook { xsd:IDREF }?, + status.attrib, + common.attrib, + article.role.attrib, + local.article.attrib +# end of article.attlist + +# end of article.module + +# End of DocBook document hierarchy module V4.5 ........................ + +# ...................................................................... diff --git a/defensive-coding/docbook-schema/dbnotnx.rnc b/defensive-coding/docbook-schema/dbnotnx.rnc new file mode 100644 index 0000000..9beb245 --- /dev/null +++ b/defensive-coding/docbook-schema/dbnotnx.rnc @@ -0,0 +1,85 @@ +# ...................................................................... + +# DocBook notations module V4.5 ........................................ + +# File dbnotnx.mod ..................................................... + +# Copyright 1992-2004 HaL Computer Systems, Inc., +# O'Reilly & Associates, Inc., ArborText, Inc., Fujitsu Software +# Corporation, Norman Walsh, Sun Microsystems, Inc., and the +# Organization for the Advancement of Structured Information +# Standards (OASIS). +# +# $Id: dbnotnx.mod 6340 2006-10-03 13:23:24Z nwalsh $ +# +# Permission to use, copy, modify and distribute the DocBook DTD +# and its accompanying documentation for any purpose and without fee +# is hereby granted in perpetuity, provided that the above copyright +# notice and this paragraph appear in all copies. The copyright +# holders make no representation about the suitability of the DTD for +# any purpose. It is provided "as is" without expressed or implied +# warranty. +# +# If you modify the DocBook DTD in any way, except for declaring and +# referencing additional sets of general entities and declaring +# additional notations, label your DTD as a variant of DocBook. See +# the maintenance documentation for more information. +# +# Please direct all questions, bug reports, or suggestions for +# changes to the docbook@lists.oasis-open.org mailing list. For more +# information, see http://www.oasis-open.org/docbook/. + +# ...................................................................... + +# This module contains the notation declarations used by DocBook. +# +# In DTD driver files referring to this module, please use an entity +# declaration that uses the public identifier shown below: +# +# +# %dbnotn; +# +# See the documentation for detailed information on the parameter +# entity and module scheme used in DocBook, customizing DocBook and +# planning for interchange, and changes made since the last release +# of DocBook. + +local.notation.class = notAllowed +notation.class = + "BMP" + | "CGM-CHAR" + | "CGM-BINARY" + | "CGM-CLEAR" + | "DITROFF" + | "DVI" + | "EPS" + | "EQN" + | "FAX" + | "GIF" + | "GIF87a" + | "GIF89a" + | "JPG" + | "JPEG" + | "IGES" + | "PCX" + | "PIC" + | "PNG" + | "PS" + | "SGML" + | "TBL" + | "TEX" + | "TIFF" + | "WMF" + | "WPG" + | "SVG" + | "PDF" + | "SWF" + | "linespecific" + | local.notation.class +# WordPerfect Graphic format + +# End of DocBook notations module V4.5 ................................. + +# ...................................................................... diff --git a/defensive-coding/docbook-schema/dbpoolx.rnc b/defensive-coding/docbook-schema/dbpoolx.rnc new file mode 100644 index 0000000..47100a3 --- /dev/null +++ b/defensive-coding/docbook-schema/dbpoolx.rnc @@ -0,0 +1,5785 @@ +# ...................................................................... + +# DocBook XML information pool module V4.5 ............................. + +# File dbpoolx.mod ..................................................... + +# Copyright 1992-2004 HaL Computer Systems, Inc., +# O'Reilly & Associates, Inc., ArborText, Inc., Fujitsu Software +# Corporation, Norman Walsh, Sun Microsystems, Inc., and the +# Organization for the Advancement of Structured Information +# Standards (OASIS). +# +# $Id: dbpoolx.mod 6340 2006-10-03 13:23:24Z nwalsh $ +# +# Permission to use, copy, modify and distribute the DocBook XML DTD +# and its accompanying documentation for any purpose and without fee +# is hereby granted in perpetuity, provided that the above copyright +# notice and this paragraph appear in all copies. The copyright +# holders make no representation about the suitability of the DTD for +# any purpose. It is provided "as is" without expressed or implied +# warranty. +# +# If you modify the DocBook XML DTD in any way, except for declaring and +# referencing additional sets of general entities and declaring +# additional notations, label your DTD as a variant of DocBook. See +# the maintenance documentation for more information. +# +# Please direct all questions, bug reports, or suggestions for +# changes to the docbook@lists.oasis-open.org mailing list. For more +# information, see http://www.oasis-open.org/docbook/. + +# ...................................................................... + +# This module contains the definitions for the objects, inline +# elements, and so on that are available to be used as the main +# content of DocBook documents. Some elements are useful for general +# publishing, and others are useful specifically for computer +# documentation. +# +# This module has the following dependencies on other modules: +# +# o It assumes that a %notation.class; entity is defined by the +# driver file or other high-level module. This entity is +# referenced in the NOTATION attributes for the graphic-related and +# ModeSpec elements. +# +# o It assumes that an appropriately parameterized table module is +# available for use with the table-related elements. +# +# In DTD driver files referring to this module, please use an entity +# declaration that uses the public identifier shown below: +# +# +# %dbpool; +# +# See the documentation for detailed information on the parameter +# entity and module scheme used in DocBook, customizing DocBook and +# planning for interchange, and changes made since the last release +# of DocBook. + +# ...................................................................... + +# Forms entities ....................................................... + +# These PEs provide the hook by which the forms module can be inserted + +# into the DTD. + +namespace a = "http://relaxng.org/ns/compatibility/annotations/1.0" + +forminlines.hook = notAllowed +forms.hook = notAllowed +# ...................................................................... + +# General-purpose semantics entities ................................... +yesorno.attvals = string +# ...................................................................... + +# Entities for module inclusions ....................................... + +# ...................................................................... + +# Entities for element classes and mixtures ............................ + +# "Ubiquitous" classes: ndxterm.class and beginpage +local.ndxterm.class = notAllowed +ndxterm.class = indexterm | local.ndxterm.class +# Object-level classes ................................................. +local.list.class = notAllowed +list.class = + calloutlist + | glosslist + | bibliolist + | itemizedlist + | orderedlist + | segmentedlist + | simplelist + | variablelist + | local.list.class +local.admon.class = notAllowed +admon.class = + caution | important | note | tip | warning | local.admon.class +local.linespecific.class = notAllowed +linespecific.class = + literallayout + | programlisting + | programlistingco + | screen + | screenco + | screenshot + | local.linespecific.class +local.method.synop.class = notAllowed +method.synop.class = + constructorsynopsis + | destructorsynopsis + | methodsynopsis + | local.method.synop.class +local.synop.class = notAllowed +synop.class = + synopsis + | cmdsynopsis + | funcsynopsis + | classsynopsis + | fieldsynopsis + | method.synop.class + | local.synop.class +local.para.class = notAllowed +para.class = formalpara | para | simpara | local.para.class +local.informal.class = notAllowed +informal.class = + address + | blockquote + | graphic + | graphicco + | mediaobject + | mediaobjectco + | informalequation + | informalexample + | informalfigure + | informaltable + | local.informal.class +local.formal.class = notAllowed +formal.class = equation | example | figure | table | local.formal.class +# The DocBook TC may produce an official EBNF module for DocBook. + +# This PE provides the hook by which it can be inserted into the DTD. +ebnf.block.hook = notAllowed +local.compound.class = notAllowed +compound.class = + msgset + | procedure + | sidebar + | qandaset + | task + | ebnf.block.hook + | local.compound.class +local.genobj.class = notAllowed +genobj.class = + anchor | bridgehead | remark | highlights | local.genobj.class +local.descobj.class = notAllowed +descobj.class = abstract | authorblurb | epigraph | local.descobj.class +# Character-level classes .............................................. +local.xref.char.class = notAllowed +xref.char.class = footnoteref | xref | biblioref | local.xref.char.class +local.gen.char.class = notAllowed +gen.char.class = + abbrev + | acronym + | citation + | citerefentry + | citetitle + | citebiblioid + | emphasis + | firstterm + | foreignphrase + | glossterm + | termdef + | footnote + | phrase + | orgname + | quote + | trademark + | wordasword + | personname + | local.gen.char.class +local.link.char.class = notAllowed +link.char.class = link | olink | ulink | local.link.char.class +# The DocBook TC may produce an official EBNF module for DocBook. + +# This PE provides the hook by which it can be inserted into the DTD. +ebnf.inline.hook = notAllowed +local.tech.char.class = notAllowed +tech.char.class = + action + | application + | classname + | methodname + | interfacename + | exceptionname + | ooclass + | oointerface + | ooexception + | package + | command + | computeroutput + | database + | email + | envar + | errorcode + | errorname + | errortype + | errortext + | filename + | function + | guibutton + | guiicon + | guilabel + | guimenu + | guimenuitem + | guisubmenu + | hardware + | interface + | keycap + | keycode + | keycombo + | keysym + | literal + | code + | constant + | markup + | medialabel + | menuchoice + | mousebutton + | option + | optional + | parameter + | prompt + | property + | replaceable + | returnvalue + | sgmltag + | structfield + | structname + | symbol + | systemitem + | uri + | \token + | type + | userinput + | varname + | ebnf.inline.hook + | local.tech.char.class +local.base.char.class = notAllowed +base.char.class = anchor | local.base.char.class +local.docinfo.char.class = notAllowed +docinfo.char.class = + author + | authorinitials + | corpauthor + | corpcredit + | modespec + | othercredit + | productname + | productnumber + | revhistory + | local.docinfo.char.class +local.other.char.class = notAllowed +other.char.class = + remark | subscript | superscript | local.other.char.class +local.inlineobj.char.class = notAllowed +inlineobj.char.class = + inlinegraphic + | inlinemediaobject + | inlineequation + | local.inlineobj.char.class +# ...................................................................... + +# Entities for content models .......................................... +formalobject.title.content = title, titleabbrev? +# Redeclaration placeholder ............................................ + +# For redeclaring entities that are declared after this point while +# retaining their references to the entities that are declared before +# this point + +# Object-level mixtures ................................................ + +# list admn line synp para infm form cmpd gen desc +# Component mixture X X X X X X X X X X +# Sidebar mixture X X X X X X X a X +# Footnote mixture X X X X X +# Example mixture X X X X X +# Highlights mixture X X X +# Paragraph mixture X X X X +# Admonition mixture X X X X X X b c +# Figure mixture X X X +# Table entry mixture X X X X d +# Glossary def mixture X X X X X e +# Legal notice mixture X X X X f +# +# a. Just Procedure; not Sidebar itself or MsgSet. +# b. No MsgSet. +# c. No Highlights. +# d. Just Graphic; no other informal objects. +# e. No Anchor, BridgeHead, or Highlights. +# f. Just BlockQuote; no other informal objects. +local.component.mix = notAllowed +component.mix = + list.class + | admon.class + | linespecific.class + | synop.class + | para.class + | informal.class + | formal.class + | compound.class + | genobj.class + | descobj.class + | ndxterm.class + | beginpage + | forms.hook + | local.component.mix +local.sidebar.mix = notAllowed +sidebar.mix = + list.class + | admon.class + | linespecific.class + | synop.class + | para.class + | informal.class + | formal.class + | procedure + | genobj.class + | ndxterm.class + | beginpage + | forms.hook + | local.sidebar.mix +local.qandaset.mix = notAllowed +qandaset.mix = + list.class + | admon.class + | linespecific.class + | synop.class + | para.class + | informal.class + | formal.class + | procedure + | genobj.class + | ndxterm.class + | forms.hook + | local.qandaset.mix +local.revdescription.mix = notAllowed +revdescription.mix = + list.class + | admon.class + | linespecific.class + | synop.class + | para.class + | informal.class + | formal.class + | procedure + | genobj.class + | ndxterm.class + | local.revdescription.mix +local.footnote.mix = notAllowed +footnote.mix = + list.class + | linespecific.class + | synop.class + | para.class + | informal.class + | local.footnote.mix +local.example.mix = notAllowed +example.mix = + list.class + | linespecific.class + | synop.class + | para.class + | informal.class + | ndxterm.class + | beginpage + | procedure + | forms.hook + | local.example.mix +local.highlights.mix = notAllowed +highlights.mix = + list.class + | admon.class + | para.class + | ndxterm.class + | local.highlights.mix +# %formal.class; is explicitly excluded from many contexts in which +# paragraphs are used +local.para.mix = notAllowed +para.mix = + list.class + | admon.class + | linespecific.class + | informal.class + | formal.class + | local.para.mix +local.admon.mix = notAllowed +admon.mix = + list.class + | linespecific.class + | synop.class + | para.class + | informal.class + | formal.class + | procedure + | sidebar + | anchor + | bridgehead + | remark + | ndxterm.class + | beginpage + | forms.hook + | local.admon.mix +local.figure.mix = notAllowed +figure.mix = + linespecific.class + | synop.class + | informal.class + | ndxterm.class + | beginpage + | forms.hook + | local.figure.mix +local.tabentry.mix = notAllowed +tabentry.mix = + list.class + | admon.class + | linespecific.class + | para.class + | graphic + | mediaobject + | forms.hook + | local.tabentry.mix +local.glossdef.mix = notAllowed +glossdef.mix = + list.class + | linespecific.class + | synop.class + | para.class + | informal.class + | formal.class + | remark + | ndxterm.class + | beginpage + | local.glossdef.mix +local.legalnotice.mix = notAllowed +legalnotice.mix = + list.class + | admon.class + | linespecific.class + | para.class + | blockquote + | ndxterm.class + | beginpage + | local.legalnotice.mix +local.textobject.mix = notAllowed +textobject.mix = + list.class + | admon.class + | linespecific.class + | para.class + | blockquote + | local.textobject.mix +local.mediaobject.mix = notAllowed +mediaobject.mix = + videoobject + | audioobject + | imageobject + | imageobjectco + | textobject + | local.mediaobject.mix +local.listpreamble.mix = notAllowed +listpreamble.mix = + admon.class + | linespecific.class + | synop.class + | para.class + | informal.class + | genobj.class + | descobj.class + | ndxterm.class + | beginpage + | forms.hook + | local.listpreamble.mix +# Character-level mixtures ............................................. + +# sgml.features + +# not [sgml.features[ + +# ]] not sgml.features + +# #PCD xref word link cptr base dnfo othr inob (synop) +# para.char.mix X X X X X X X X X +# title.char.mix X X X X X X X X X +# ndxterm.char.mix X X X X X X X X a +# cptr.char.mix X X X X X a +# smallcptr.char.mix X b a +# word.char.mix X c X X X a +# docinfo.char.mix X d X b X a +# +# a. Just InlineGraphic; no InlineEquation. +# b. Just Replaceable; no other computer terms. +# c. Just Emphasis and Trademark; no other word elements. +# d. Just Acronym, Emphasis, and Trademark; no other word elements. +local.para.char.mix = notAllowed +para.char.mix = + text + | xref.char.class + | gen.char.class + | link.char.class + | tech.char.class + | base.char.class + | docinfo.char.class + | other.char.class + | inlineobj.char.class + | synop.class + | ndxterm.class + | beginpage + | forminlines.hook + | local.para.char.mix +local.title.char.mix = notAllowed +title.char.mix = + text + | xref.char.class + | gen.char.class + | link.char.class + | tech.char.class + | base.char.class + | docinfo.char.class + | other.char.class + | inlineobj.char.class + | ndxterm.class + | local.title.char.mix +local.ndxterm.char.mix = notAllowed +ndxterm.char.mix = + text + | xref.char.class + | gen.char.class + | link.char.class + | tech.char.class + | base.char.class + | docinfo.char.class + | other.char.class + | inlinegraphic + | inlinemediaobject + | local.ndxterm.char.mix +local.cptr.char.mix = notAllowed +cptr.char.mix = + text + | link.char.class + | tech.char.class + | base.char.class + | other.char.class + | inlinegraphic + | inlinemediaobject + | ndxterm.class + | beginpage + | local.cptr.char.mix +local.smallcptr.char.mix = notAllowed +smallcptr.char.mix = + text + | replaceable + | inlinegraphic + | inlinemediaobject + | ndxterm.class + | beginpage + | local.smallcptr.char.mix +local.word.char.mix = notAllowed +word.char.mix = + text + | acronym + | emphasis + | trademark + | link.char.class + | base.char.class + | other.char.class + | inlinegraphic + | inlinemediaobject + | ndxterm.class + | beginpage + | local.word.char.mix +local.docinfo.char.mix = notAllowed +docinfo.char.mix = + text + | link.char.class + | emphasis + | trademark + | replaceable + | other.char.class + | inlinegraphic + | inlinemediaobject + | ndxterm.class + | local.docinfo.char.mix +# ENTITY % bibliocomponent.mix (see Bibliographic section, below) + +# ENTITY % person.ident.mix (see Bibliographic section, below) + +# ...................................................................... + +# Entities for attributes and attribute components ..................... + +# Effectivity attributes ............................................... + +# Arch: Computer or chip architecture to which element applies; no +# default +arch.attrib = attribute arch { text }? +# Condition: General-purpose effectivity attribute +condition.attrib = attribute condition { text }? +# Conformance: Standards conformance characteristics +conformance.attrib = attribute conformance { xsd:NMTOKENS }? +# OS: Operating system to which element applies; no default +os.attrib = attribute os { text }? +# Revision: Editorial revision to which element belongs; no default +revision.attrib = attribute revision { text }? +# Security: Security classification; no default +security.attrib = attribute security { text }? +# UserLevel: Level of user experience to which element applies; no +# default +userlevel.attrib = attribute userlevel { text }? +# Vendor: Computer vendor to which element applies; no default +vendor.attrib = attribute vendor { text }? +# Wordsize: Computer word size (32 bit, 64 bit, etc.); no default +wordsize.attrib = attribute wordsize { text }? +local.effectivity.attrib = empty +effectivity.attrib = + arch.attrib, + condition.attrib, + conformance.attrib, + os.attrib, + revision.attrib, + security.attrib, + userlevel.attrib, + vendor.attrib, + wordsize.attrib, + local.effectivity.attrib +# Common attributes .................................................... + +# Id: Unique identifier of element; no default +id.attrib = attribute id { xsd:ID }? +# Id: Unique identifier of element; a value must be supplied; no +# default +idreq.attrib = attribute id { xsd:ID } +# Lang: Indicator of language in which element is written, for +# translation, character set management, etc.; no default +lang.attrib = attribute lang { text }? +# Remap: Previous role of element before conversion; no default +remap.attrib = attribute remap { text }? +# Role: New role of element in local environment; no default +role.attrib = attribute role { text }? +# XRefLabel: Alternate labeling string for XRef text generation; +# default is usually title or other appropriate label text already +# contained in element +xreflabel.attrib = attribute xreflabel { text }? +# RevisionFlag: Revision status of element; default is that element +# wasn't revised +revisionflag.attrib = + attribute revisionflag { "changed" | "added" | "deleted" | "off" }? +local.common.attrib = empty +# dir: Bidirectional override +dir.attrib = attribute dir { "ltr" | "rtl" | "lro" | "rlo" }? +# xml:base: base URI +xml-base.attrib = attribute xml:base { text }? +# Role is included explicitly on each element +common.attrib = + id.attrib, + lang.attrib, + remap.attrib, + xreflabel.attrib, + revisionflag.attrib, + effectivity.attrib, + dir.attrib, + xml-base.attrib, + local.common.attrib +# Role is included explicitly on each element +idreq.common.attrib = + idreq.attrib, + lang.attrib, + remap.attrib, + xreflabel.attrib, + revisionflag.attrib, + effectivity.attrib, + dir.attrib, + xml-base.attrib, + local.common.attrib +# Semi-common attributes and other attribute entities .................. +local.graphics.attrib = empty +# EntityRef: Name of an external entity containing the content +# of the graphic + +# FileRef: Filename, qualified by a pathname if desired, +# designating the file containing the content of the graphic + +# Format: Notation of the element content, if any + +# SrcCredit: Information about the source of the Graphic + +# Width: Same as CALS reprowid (desired width) + +# Depth: Same as CALS reprodep (desired depth) + +# Align: Same as CALS hplace with 'none' removed; #IMPLIED means +# application-specific + +# Scale: Conflation of CALS hscale and vscale + +# Scalefit: Same as CALS scalefit +graphics.attrib = + attribute entityref { xsd:ENTITY }?, + attribute fileref { text }?, + attribute format { notation.class }?, + attribute srccredit { text }?, + attribute width { text }?, + attribute contentwidth { text }?, + attribute depth { text }?, + attribute contentdepth { text }?, + attribute align { "left" | "right" | "center" }?, + attribute valign { "top" | "middle" | "bottom" }?, + attribute scale { text }?, + attribute scalefit { yesorno.attvals }?, + local.graphics.attrib +local.keyaction.attrib = empty +# Action: Key combination type; default is unspecified if one +# child element, Simul if there is more than one; if value is +# Other, the OtherAction attribute must have a nonempty value + +# OtherAction: User-defined key combination type +keyaction.attrib = + attribute action { + "click" | "double-click" | "press" | "seq" | "simul" | "other" + }?, + attribute otheraction { text }?, + local.keyaction.attrib +# Label: Identifying number or string; default is usually the +# appropriate number or string autogenerated by a formatter +label.attrib = attribute label { text }? +# xml:space: whitespace treatment +xml-space.attrib = attribute xml:space { "preserve" }? +# Format: whether element is assumed to contain significant white +# space +linespecific.attrib = + [ a:defaultValue = "linespecific" ] + attribute format { "linespecific" }?, + xml-space.attrib, + attribute linenumbering { "numbered" | "unnumbered" }?, + attribute continuation { "continues" | "restarts" }?, + attribute startinglinenumber { text }?, + attribute language { text }? +# Linkend: link to related information; no default +linkend.attrib = attribute linkend { xsd:IDREF }? +# Linkend: required link to related information +linkendreq.attrib = attribute linkend { xsd:IDREF } +# Linkends: link to one or more sets of related information; no +# default +linkends.attrib = attribute linkends { xsd:IDREFS }? +local.mark.attrib = empty +mark.attrib = + attribute mark { text }?, + local.mark.attrib +# MoreInfo: whether element's content has an associated RefEntry +moreinfo.attrib = + [ a:defaultValue = "none" ] + attribute moreinfo { "refentry" | "none" }? +# Pagenum: number of page on which element appears; no default +pagenum.attrib = attribute pagenum { text }? +local.status.attrib = empty +# Status: Editorial or publication status of the element +# it applies to, such as "in review" or "approved for distribution" +status.attrib = + attribute status { text }?, + local.status.attrib +# Width: width of the longest line in the element to which it +# pertains, in number of characters +width.attrib = attribute width { text }? +# ...................................................................... + +# Title elements ....................................................... +local.title.attrib = empty +title.role.attrib = role.attrib +# doc:The text of the title of a section of a document or of a formal block-level element. +title = element title { title.attlist, title.char.mix* } +# end of title.element +title.attlist &= + pagenum.attrib, common.attrib, title.role.attrib, local.title.attrib +# end of title.attlist + +# end of title.module +local.titleabbrev.attrib = empty +titleabbrev.role.attrib = role.attrib +# doc:The abbreviation of a Title. +titleabbrev = + element titleabbrev { titleabbrev.attlist, title.char.mix* } +# end of titleabbrev.element +titleabbrev.attlist &= + common.attrib, titleabbrev.role.attrib, local.titleabbrev.attrib +# end of titleabbrev.attlist + +# end of titleabbrev.module +local.subtitle.attrib = empty +subtitle.role.attrib = role.attrib +# doc:The subtitle of a document. +subtitle = element subtitle { subtitle.attlist, title.char.mix* } +# end of subtitle.element +subtitle.attlist &= + common.attrib, subtitle.role.attrib, local.subtitle.attrib +# end of subtitle.attlist + +# end of subtitle.module + +# ...................................................................... + +# Bibliographic entities and elements .................................. + +# The bibliographic elements are typically used in the document +# hierarchy. They do not appear in content models of information +# pool elements. See also the document information elements, +# below. +local.person.ident.mix = notAllowed +person.ident.mix = + honorific + | firstname + | surname + | lineage + | othername + | affiliation + | authorblurb + | contrib + | local.person.ident.mix +local.bibliocomponent.mix = notAllowed +bibliocomponent.mix = + abbrev + | abstract + | address + | artpagenums + | author + | authorgroup + | authorinitials + | bibliomisc + | biblioset + | collab + | confgroup + | contractnum + | contractsponsor + | copyright + | corpauthor + | corpname + | corpcredit + | date + | edition + | editor + | invpartnumber + | isbn + | issn + | issuenum + | orgname + | biblioid + | citebiblioid + | bibliosource + | bibliorelation + | bibliocoverage + | othercredit + | pagenums + | printhistory + | productname + | productnumber + | pubdate + | publisher + | publishername + | pubsnumber + | releaseinfo + | revhistory + | seriesvolnums + | subtitle + | title + | titleabbrev + | volumenum + | citetitle + | personname + | person.ident.mix + | ndxterm.class + | local.bibliocomponent.mix +# I don't think this is well placed, but it needs to be here because of + +# the reference to bibliocomponent.mix +local.info.class = notAllowed +info.class = + graphic + | mediaobject + | legalnotice + | modespec + | subjectset + | keywordset + | itermset + | bibliocomponent.mix + | local.info.class +# BiblioList ........................ +local.bibliolist.attrib = empty +bibliolist.role.attrib = role.attrib +# doc:A wrapper for a set of bibliography entries. +bibliolist = + element bibliolist { + bibliolist.attlist, + blockinfo?, + formalobject.title.content?, + (biblioentry | bibliomixed)+ + } +# end of bibliolist.element +bibliolist.attlist &= + common.attrib, bibliolist.role.attrib, local.bibliolist.attrib +# end of bibliolist.attlist + +# end of bibliolist.module +local.biblioentry.attrib = empty +biblioentry.role.attrib = role.attrib +# doc:An entry in a Bibliography. +biblioentry = + element biblioentry { + biblioentry.attlist, (articleinfo | bibliocomponent.mix)+ + } +# end of biblioentry.element +biblioentry.attlist &= + common.attrib, biblioentry.role.attrib, local.biblioentry.attrib +# end of biblioentry.attlist + +# end of biblioentry.module +local.bibliomixed.attrib = empty +bibliomixed.role.attrib = role.attrib +# doc:An entry in a Bibliography. +bibliomixed = + element bibliomixed { + bibliomixed.attlist, (text | bibliocomponent.mix | bibliomset)* + } +# end of bibliomixed.element +bibliomixed.attlist &= + common.attrib, bibliomixed.role.attrib, local.bibliomixed.attrib +# end of bibliomixed.attlist + +# end of bibliomixed.module +local.articleinfo.attrib = empty +articleinfo.role.attrib = role.attrib +# doc:Meta-information for an Article. +articleinfo = element articleinfo { articleinfo.attlist, info.class+ } +# end of articleinfo.element +articleinfo.attlist &= + common.attrib, articleinfo.role.attrib, local.articleinfo.attrib +# end of articleinfo.attlist + +# end of articleinfo.module +local.biblioset.attrib = empty +biblioset.role.attrib = role.attrib +# doc:A "raw" container for related bibliographic information. +biblioset = + element biblioset { biblioset.attlist, bibliocomponent.mix+ } +# end of biblioset.element + +# Relation: Relationship of elements contained within BiblioSet +biblioset.attlist &= + attribute relation { text }?, + common.attrib, + biblioset.role.attrib, + local.biblioset.attrib +# end of biblioset.attlist + +# end of biblioset.module +bibliomset.role.attrib = role.attrib +local.bibliomset.attrib = empty +# doc:A "cooked" container for related bibliographic information. +bibliomset = + element bibliomset { + bibliomset.attlist, (text | bibliocomponent.mix | bibliomset)* + } +# end of bibliomset.element + +# Relation: Relationship of elements contained within BiblioMSet +bibliomset.attlist &= + attribute relation { text }?, + common.attrib, + bibliomset.role.attrib, + local.bibliomset.attrib +# end of bibliomset.attlist + +# end of bibliomset.module +local.bibliomisc.attrib = empty +bibliomisc.role.attrib = role.attrib +# doc:Untyped bibliographic information. +bibliomisc = element bibliomisc { bibliomisc.attlist, para.char.mix* } +# end of bibliomisc.element +bibliomisc.attlist &= + common.attrib, bibliomisc.role.attrib, local.bibliomisc.attrib +# end of bibliomisc.attlist + +# end of bibliomisc.module + +# ...................................................................... + +# Subject, Keyword, and ITermSet elements .............................. +local.subjectset.attrib = empty +subjectset.role.attrib = role.attrib +# doc:A set of terms describing the subject matter of a document. +subjectset = element subjectset { subjectset.attlist, subject+ } +# end of subjectset.element + +# Scheme: Controlled vocabulary employed in SubjectTerms +subjectset.attlist &= + attribute scheme { xsd:NMTOKEN }?, + common.attrib, + subjectset.role.attrib, + local.subjectset.attrib +# end of subjectset.attlist + +# end of subjectset.module +local.subject.attrib = empty +subject.role.attrib = role.attrib +# doc:One of a group of terms describing the subject matter of a document. +subject = element subject { subject.attlist, subjectterm+ } +# end of subject.element + +# Weight: Ranking of this group of SubjectTerms relative +# to others, 0 is low, no highest value specified +subject.attlist &= + attribute weight { text }?, + common.attrib, + subject.role.attrib, + local.subject.attrib +# end of subject.attlist + +# end of subject.module +local.subjectterm.attrib = empty +subjectterm.role.attrib = role.attrib +# doc:A term in a group of terms describing the subject matter of a document. +subjectterm = element subjectterm { subjectterm.attlist, text } +# end of subjectterm.element +subjectterm.attlist &= + common.attrib, subjectterm.role.attrib, local.subjectterm.attrib +# end of subjectterm.attlist + +# end of subjectterm.module + +# end of subjectset.content.module +local.keywordset.attrib = empty +keywordset.role.attrib = role.attrib +# doc:A set of keywords describing the content of a document. +keywordset = element keywordset { keywordset.attlist, keyword+ } +# end of keywordset.element +keywordset.attlist &= + common.attrib, keywordset.role.attrib, local.keywordset.attrib +# end of keywordset.attlist + +# end of keywordset.module +local.keyword.attrib = empty +keyword.role.attrib = role.attrib +# doc:One of a set of keywords describing the content of a document. +keyword = element keyword { keyword.attlist, text } +# end of keyword.element +keyword.attlist &= + common.attrib, keyword.role.attrib, local.keyword.attrib +# end of keyword.attlist + +# end of keyword.module + +# end of keywordset.content.module +local.itermset.attrib = empty +itermset.role.attrib = role.attrib +# doc:A set of index terms in the meta-information of a document. +itermset = element itermset { itermset.attlist, indexterm+ } +# end of itermset.element +itermset.attlist &= + common.attrib, itermset.role.attrib, local.itermset.attrib +# end of itermset.attlist + +# end of itermset.module + +# Bibliographic info for "blocks" +local.blockinfo.attrib = empty +blockinfo.role.attrib = role.attrib +# doc:Meta-information for a block element. +blockinfo = element blockinfo { blockinfo.attlist, info.class+ } +# end of blockinfo.element +blockinfo.attlist &= + common.attrib, blockinfo.role.attrib, local.blockinfo.attrib +# end of blockinfo.attlist + +# end of blockinfo.module + +# ...................................................................... + +# Compound (section-ish) elements ...................................... + +# Message set ...................... +local.msgset.attrib = empty +msgset.role.attrib = role.attrib +# doc:A detailed set of messages, usually error messages. +msgset = + element msgset { + msgset.attlist, + blockinfo?, + formalobject.title.content?, + (msgentry+ | simplemsgentry+) + } +# end of msgset.element +msgset.attlist &= common.attrib, msgset.role.attrib, local.msgset.attrib +# end of msgset.attlist + +# end of msgset.module +local.msgentry.attrib = empty +msgentry.role.attrib = role.attrib +# doc:A wrapper for an entry in a message set. +msgentry = + element msgentry { msgentry.attlist, msg+, msginfo?, msgexplan* } +# end of msgentry.element +msgentry.attlist &= + common.attrib, msgentry.role.attrib, local.msgentry.attrib +# end of msgentry.attlist + +# end of msgentry.module +local.simplemsgentry.attrib = empty +simplemsgentry.role.attrib = role.attrib +# doc:A wrapper for a simpler entry in a message set. +simplemsgentry = + element simplemsgentry { simplemsgentry.attlist, msgtext, msgexplan+ } +# end of simplemsgentry.element +simplemsgentry.attlist &= + attribute audience { text }?, + attribute level { text }?, + attribute origin { text }?, + common.attrib, + simplemsgentry.role.attrib, + local.simplemsgentry.attrib +# end of simplemsgentry.attlist + +# end of simplemsgentry.module +local.msg.attrib = empty +msg.role.attrib = role.attrib +# doc:A message in a message set. +msg = element msg { msg.attlist, title?, msgmain, (msgsub | msgrel)* } +# end of msg.element +msg.attlist &= common.attrib, msg.role.attrib, local.msg.attrib +# end of msg.attlist + +# end of msg.module +local.msgmain.attrib = empty +msgmain.role.attrib = role.attrib +# doc:The primary component of a message in a message set. +msgmain = element msgmain { msgmain.attlist, title?, msgtext } +# end of msgmain.element +msgmain.attlist &= + common.attrib, msgmain.role.attrib, local.msgmain.attrib +# end of msgmain.attlist + +# end of msgmain.module +local.msgsub.attrib = empty +msgsub.role.attrib = role.attrib +# doc:A subcomponent of a message in a message set. +msgsub = element msgsub { msgsub.attlist, title?, msgtext } +# end of msgsub.element +msgsub.attlist &= common.attrib, msgsub.role.attrib, local.msgsub.attrib +# end of msgsub.attlist + +# end of msgsub.module +local.msgrel.attrib = empty +msgrel.role.attrib = role.attrib +# doc:A related component of a message in a message set. +msgrel = element msgrel { msgrel.attlist, title?, msgtext } +# end of msgrel.element +msgrel.attlist &= common.attrib, msgrel.role.attrib, local.msgrel.attrib +# end of msgrel.attlist + +# end of msgrel.module + +# MsgText (defined in the Inlines section, below) +local.msginfo.attrib = empty +msginfo.role.attrib = role.attrib +# doc:Information about a message in a message set. +msginfo = + element msginfo { msginfo.attlist, (msglevel | msgorig | msgaud)* } +# end of msginfo.element +msginfo.attlist &= + common.attrib, msginfo.role.attrib, local.msginfo.attrib +# end of msginfo.attlist + +# end of msginfo.module +local.msglevel.attrib = empty +msglevel.role.attrib = role.attrib +# doc:The level of importance or severity of a message in a message set. +msglevel = element msglevel { msglevel.attlist, smallcptr.char.mix* } +# end of msglevel.element +msglevel.attlist &= + common.attrib, msglevel.role.attrib, local.msglevel.attrib +# end of msglevel.attlist + +# end of msglevel.module +local.msgorig.attrib = empty +msgorig.role.attrib = role.attrib +# doc:The origin of a message in a message set. +msgorig = element msgorig { msgorig.attlist, smallcptr.char.mix* } +# end of msgorig.element +msgorig.attlist &= + common.attrib, msgorig.role.attrib, local.msgorig.attrib +# end of msgorig.attlist + +# end of msgorig.module +local.msgaud.attrib = empty +msgaud.role.attrib = role.attrib +# doc:The audience to which a message in a message set is relevant. +msgaud = element msgaud { msgaud.attlist, para.char.mix* } +# end of msgaud.element +msgaud.attlist &= common.attrib, msgaud.role.attrib, local.msgaud.attrib +# end of msgaud.attlist + +# end of msgaud.module +local.msgexplan.attrib = empty +msgexplan.role.attrib = role.attrib +# doc:Explanatory material relating to a message in a message set. +msgexplan = + element msgexplan { msgexplan.attlist, title?, component.mix+ } +# end of msgexplan.element +msgexplan.attlist &= + common.attrib, msgexplan.role.attrib, local.msgexplan.attrib +# end of msgexplan.attlist + +# end of msgexplan.module + +# end of msgset.content.module +local.task.attrib = empty +task.role.attrib = role.attrib +# doc:A task to be completed. +task = + element task { + task.attlist, + blockinfo?, + ndxterm.class*, + formalobject.title.content, + tasksummary?, + taskprerequisites?, + procedure, + example*, + taskrelated? + } +# end of task.element +task.attlist &= common.attrib, task.role.attrib, local.task.attrib +# end of task.attlist + +# end of task.module +local.tasksummary.attrib = empty +tasksummary.role.attrib = role.attrib +# doc:A summary of a task. +tasksummary = + element tasksummary { + tasksummary.attlist, + blockinfo?, + formalobject.title.content?, + component.mix+ + } +# end of tasksummary.element +tasksummary.attlist &= + common.attrib, tasksummary.role.attrib, local.tasksummary.attrib +# end of tasksummary.attlist + +# end of tasksummary.module +local.taskprerequisites.attrib = empty +taskprerequisites.role.attrib = role.attrib +# doc:The prerequisites for a task. +taskprerequisites = + element taskprerequisites { + taskprerequisites.attlist, + blockinfo?, + formalobject.title.content?, + component.mix+ + } +# end of taskprerequisites.element +taskprerequisites.attlist &= + common.attrib, + taskprerequisites.role.attrib, + local.taskprerequisites.attrib +# end of taskprerequisites.attlist + +# end of taskprerequisites.module +local.taskrelated.attrib = empty +taskrelated.role.attrib = role.attrib +# doc:Information related to a task. +taskrelated = + element taskrelated { + taskrelated.attlist, + blockinfo?, + formalobject.title.content?, + component.mix+ + } +# end of taskrelated.element +taskrelated.attlist &= + common.attrib, taskrelated.role.attrib, local.taskrelated.attrib +# end of taskrelated.attlist + +# end of taskrelated.module + +# end of task.content.module + +# QandASet ........................ +local.qandaset.attrib = empty +qandaset.role.attrib = role.attrib +# doc:A question-and-answer set. +qandaset = + element qandaset { + qandaset.attlist, + blockinfo?, + formalobject.title.content?, + qandaset.mix*, + (qandadiv+ | qandaentry+) + } +# end of qandaset.element +qandaset.attlist &= + attribute defaultlabel { "qanda" | "number" | "none" }?, + common.attrib, + qandaset.role.attrib, + local.qandaset.attrib +# end of qandaset.attlist + +# end of qandaset.module +local.qandadiv.attrib = empty +qandadiv.role.attrib = role.attrib +# doc:A titled division in a QandASet. +qandadiv = + element qandadiv { + qandadiv.attlist, + blockinfo?, + formalobject.title.content?, + qandaset.mix*, + (qandadiv+ | qandaentry+) + } +# end of qandadiv.element +qandadiv.attlist &= + common.attrib, qandadiv.role.attrib, local.qandadiv.attrib +# end of qandadiv.attlist + +# end of qandadiv.module +local.qandaentry.attrib = empty +qandaentry.role.attrib = role.attrib +# doc:A question/answer set within a QandASet. +qandaentry = + element qandaentry { + qandaentry.attlist, blockinfo?, revhistory?, question, answer* + } +# end of qandaentry.element +qandaentry.attlist &= + common.attrib, qandaentry.role.attrib, local.qandaentry.attrib +# end of qandaentry.attlist + +# end of qandaentry.module +local.question.attrib = empty +question.role.attrib = role.attrib +# doc:A question in a QandASet. +question = element question { question.attlist, label?, qandaset.mix+ } +# end of question.element +question.attlist &= + common.attrib, question.role.attrib, local.question.attrib +# end of question.attlist + +# end of question.module +local.answer.attrib = empty +answer.role.attrib = role.attrib +# doc:An answer to a question posed in a QandASet. +answer = + element answer { answer.attlist, label?, qandaset.mix*, qandaentry* } +# end of answer.element +answer.attlist &= common.attrib, answer.role.attrib, local.answer.attrib +# end of answer.attlist + +# end of answer.module +local.label.attrib = empty +label.role.attrib = role.attrib +# doc:A label on a Question or Answer. +label = element label { label.attlist, word.char.mix* } +# end of label.element +label.attlist &= common.attrib, label.role.attrib, local.label.attrib +# end of label.attlist + +# end of label.module + +# end of qandaset.content.module + +# Procedure ........................ +local.procedure.attrib = empty +procedure.role.attrib = role.attrib +# doc:A list of operations to be performed in a well-defined sequence. +procedure = + element procedure { + procedure.attlist, + blockinfo?, + formalobject.title.content?, + component.mix*, + step+ + } +# end of procedure.element +procedure.attlist &= + common.attrib, procedure.role.attrib, local.procedure.attrib +# end of procedure.attlist + +# end of procedure.module +local.step.attrib = empty +step.role.attrib = role.attrib +# doc:A unit of action in a procedure. +step = + element step { + step.attlist, + title?, + ((component.mix+, + ((substeps | stepalternatives), component.mix*)?) + | ((substeps | stepalternatives), component.mix*)) + } +# end of step.element + +# Performance: Whether the Step must be performed + +# not #REQUIRED! +step.attlist &= + [ a:defaultValue = "required" ] + attribute performance { "optional" | "required" }?, + common.attrib, + step.role.attrib, + local.step.attrib +# end of step.attlist + +# end of step.module +local.substeps.attrib = empty +substeps.role.attrib = role.attrib +# doc:A wrapper for steps that occur within steps in a procedure. +substeps = element substeps { substeps.attlist, step+ } +# end of substeps.element + +# Performance: whether entire set of substeps must be performed + +# not #REQUIRED! +substeps.attlist &= + [ a:defaultValue = "required" ] + attribute performance { "optional" | "required" }?, + common.attrib, + substeps.role.attrib, + local.substeps.attrib +# end of substeps.attlist + +# end of substeps.module +local.stepalternatives.attrib = empty +stepalternatives.role.attrib = role.attrib +# doc:Alternative steps in a procedure. +stepalternatives = + element stepalternatives { stepalternatives.attlist, step+ } +# end of stepalternatives.element + +# Performance: Whether (one of) the alternatives must be performed + +# not #REQUIRED! +stepalternatives.attlist &= + [ a:defaultValue = "required" ] + attribute performance { "optional" | "required" }?, + common.attrib, + stepalternatives.role.attrib, + local.stepalternatives.attrib +# end of stepalternatives.attlist + +# end of stepalternatives.module + +# end of procedure.content.module + +# Sidebar .......................... +local.sidebarinfo.attrib = empty +sidebarinfo.role.attrib = role.attrib +# doc:Meta-information for a Sidebar. +sidebarinfo = element sidebarinfo { sidebarinfo.attlist, info.class+ } +# end of sidebarinfo.element +sidebarinfo.attlist &= + common.attrib, sidebarinfo.role.attrib, local.sidebarinfo.attrib +# end of sidebarinfo.attlist + +# end of sidebarinfo.module +local.sidebar.attrib = empty +sidebar.role.attrib = role.attrib +# doc:A portion of a document that is isolated from the main narrative flow. +sidebar = + element sidebar { + sidebar.attlist, + sidebarinfo?, + formalobject.title.content?, + sidebar.mix+ + } +# end of sidebar.element +sidebar.attlist &= + common.attrib, sidebar.role.attrib, local.sidebar.attrib +# end of sidebar.attlist + +# end of sidebar.module + +# end of sidebar.content.model + +# ...................................................................... + +# Paragraph-related elements ........................................... +local.abstract.attrib = empty +abstract.role.attrib = role.attrib +# doc:A summary. +abstract = element abstract { abstract.attlist, title?, para.class+ } +# end of abstract.element +abstract.attlist &= + common.attrib, abstract.role.attrib, local.abstract.attrib +# end of abstract.attlist + +# end of abstract.module +local.authorblurb.attrib = empty +authorblurb.role.attrib = role.attrib +# doc:A short description or note about an author. +authorblurb = + element authorblurb { authorblurb.attlist, title?, para.class+ } +# end of authorblurb.element +authorblurb.attlist &= + common.attrib, authorblurb.role.attrib, local.authorblurb.attrib +# end of authorblurb.attlist + +# end of authorblurb.module +local.personblurb.attrib = empty +personblurb.role.attrib = role.attrib +# doc:A short description or note about a person. +personblurb = + element personblurb { personblurb.attlist, title?, para.class+ } +# end of personblurb.element +personblurb.attlist &= + common.attrib, personblurb.role.attrib, local.personblurb.attrib +# end of personblurb.attlist + +# end of personblurb.module +local.blockquote.attrib = empty +blockquote.role.attrib = role.attrib +# doc:A quotation set off from the main text. +blockquote = + element blockquote { + blockquote.attlist, blockinfo?, title?, attribution?, component.mix+ + } +# end of blockquote.element +blockquote.attlist &= + common.attrib, blockquote.role.attrib, local.blockquote.attrib +# end of blockquote.attlist + +# end of blockquote.module +local.attribution.attrib = empty +attribution.role.attrib = role.attrib +# doc:The source of a block quote or epigraph. +attribution = + element attribution { attribution.attlist, para.char.mix* } +# end of attribution.element +attribution.attlist &= + common.attrib, attribution.role.attrib, local.attribution.attrib +# end of attribution.attlist + +# end of attribution.module +local.bridgehead.attrib = empty +bridgehead.role.attrib = role.attrib +# doc:A free-floating heading. +bridgehead = element bridgehead { bridgehead.attlist, title.char.mix* } +# end of bridgehead.element + +# Renderas: Indicates the format in which the BridgeHead +# should appear +bridgehead.attlist &= + attribute renderas { + "other" | "sect1" | "sect2" | "sect3" | "sect4" | "sect5" + }?, + common.attrib, + bridgehead.role.attrib, + local.bridgehead.attrib +# end of bridgehead.attlist + +# end of bridgehead.module +local.remark.attrib = empty +remark.role.attrib = role.attrib +# doc:A remark (or comment) intended for presentation in a draft manuscript. +remark = element remark { remark.attlist, para.char.mix* } +# end of remark.element +remark.attlist &= common.attrib, remark.role.attrib, local.remark.attrib +# end of remark.attlist + +# end of remark.module +local.epigraph.attrib = empty +epigraph.role.attrib = role.attrib +# doc:A short inscription at the beginning of a document or component. +epigraph = + element epigraph { + epigraph.attlist, attribution?, (para.class | literallayout)+ + } +# end of epigraph.element +epigraph.attlist &= + common.attrib, epigraph.role.attrib, local.epigraph.attrib +# end of epigraph.attlist + +# Attribution (defined above) + +# end of epigraph.module +local.footnote.attrib = empty +footnote.role.attrib = role.attrib +# doc:A footnote. +footnote = element footnote { footnote.attlist, footnote.mix+ } +# end of footnote.element +footnote.attlist &= + label.attrib, + common.attrib, + footnote.role.attrib, + local.footnote.attrib +# end of footnote.attlist + +# end of footnote.module +local.highlights.attrib = empty +highlights.role.attrib = role.attrib +# doc:A summary of the main points of the discussed component. +highlights = element highlights { highlights.attlist, highlights.mix+ } +# end of highlights.element +highlights.attlist &= + common.attrib, highlights.role.attrib, local.highlights.attrib +# end of highlights.attlist + +# end of highlights.module +local.formalpara.attrib = empty +formalpara.role.attrib = role.attrib +# doc:A paragraph with a title. +formalpara = + element formalpara { formalpara.attlist, title, ndxterm.class*, para } +# end of formalpara.element +formalpara.attlist &= + common.attrib, formalpara.role.attrib, local.formalpara.attrib +# end of formalpara.attlist + +# end of formalpara.module +local.para.attrib = empty +para.role.attrib = role.attrib +# doc:A paragraph. +para = element para { para.attlist, (para.char.mix | para.mix)* } +# end of para.element +para.attlist &= common.attrib, para.role.attrib, local.para.attrib +# end of para.attlist + +# end of para.module +local.simpara.attrib = empty +simpara.role.attrib = role.attrib +# doc:A paragraph that contains only text and inline markup, no block elements. +simpara = element simpara { simpara.attlist, para.char.mix* } +# end of simpara.element +simpara.attlist &= + common.attrib, simpara.role.attrib, local.simpara.attrib +# end of simpara.attlist + +# end of simpara.module +local.admon.attrib = empty +admon.role.attrib = role.attrib +# doc:A note of caution. +caution = element caution { caution.attlist, title?, admon.mix+ } +# end of caution.element +caution.attlist &= common.attrib, admon.role.attrib, local.admon.attrib +# end of caution.attlist + +# doc:An admonition set off from the text. +important = element important { important.attlist, title?, admon.mix+ } +# end of important.element +important.attlist &= + common.attrib, admon.role.attrib, local.admon.attrib +# end of important.attlist + +# doc:A message set off from the text. +note = element note { note.attlist, title?, admon.mix+ } +# end of note.element +note.attlist &= common.attrib, admon.role.attrib, local.admon.attrib +# end of note.attlist + +# doc:A suggestion to the user, set off from the text. +tip = element tip { tip.attlist, title?, admon.mix+ } +# end of tip.element +tip.attlist &= common.attrib, admon.role.attrib, local.admon.attrib +# end of tip.attlist + +# doc:An admonition set off from the text. +warning = element warning { warning.attlist, title?, admon.mix+ } +# end of warning.element +warning.attlist &= common.attrib, admon.role.attrib, local.admon.attrib +# end of warning.attlist + +# end of admon.module + +# ...................................................................... + +# Lists ................................................................ + +# GlossList ........................ +local.glosslist.attrib = empty +glosslist.role.attrib = role.attrib +# doc:A wrapper for a set of GlossEntrys. +glosslist = + element glosslist { + glosslist.attlist, + blockinfo?, + formalobject.title.content?, + glossentry+ + } +# end of glosslist.element +glosslist.attlist &= + common.attrib, glosslist.role.attrib, local.glosslist.attrib +# end of glosslist.attlist + +# end of glosslist.module +local.glossentry.attrib = empty +glossentry.role.attrib = role.attrib +# doc:An entry in a Glossary or GlossList. +glossentry = + element glossentry { + glossentry.attlist, + glossterm, + acronym?, + abbrev?, + ndxterm.class*, + revhistory?, + (glosssee | glossdef+) + } +# end of glossentry.element + +# SortAs: String by which the GlossEntry is to be sorted +# (alphabetized) in lieu of its proper content +glossentry.attlist &= + attribute sortas { text }?, + common.attrib, + glossentry.role.attrib, + local.glossentry.attrib +# end of glossentry.attlist + +# end of glossentry.module + +# GlossTerm (defined in the Inlines section, below) +local.glossdef.attrib = empty +glossdef.role.attrib = role.attrib +# doc:A definition in a GlossEntry. +glossdef = + element glossdef { glossdef.attlist, glossdef.mix+, glossseealso* } +# end of glossdef.element + +# Subject: List of subjects; keywords for the definition +glossdef.attlist &= + attribute subject { text }?, + common.attrib, + glossdef.role.attrib, + local.glossdef.attrib +# end of glossdef.attlist + +# end of glossdef.module +local.glosssee.attrib = empty +glosssee.role.attrib = role.attrib +# doc:A cross-reference from one GlossEntry to another. +glosssee = element glosssee { glosssee.attlist, para.char.mix* } +# end of glosssee.element + +# OtherTerm: Reference to the GlossEntry whose GlossTerm +# should be displayed at the point of the GlossSee +glosssee.attlist &= + attribute otherterm { xsd:IDREF }?, + common.attrib, + glosssee.role.attrib, + local.glosssee.attrib +# end of glosssee.attlist + +# end of glosssee.module +local.glossseealso.attrib = empty +glossseealso.role.attrib = role.attrib +# doc:A cross-reference from one GlossEntry to another. +glossseealso = + element glossseealso { glossseealso.attlist, para.char.mix* } +# end of glossseealso.element + +# OtherTerm: Reference to the GlossEntry whose GlossTerm +# should be displayed at the point of the GlossSeeAlso +glossseealso.attlist &= + attribute otherterm { xsd:IDREF }?, + common.attrib, + glossseealso.role.attrib, + local.glossseealso.attrib +# end of glossseealso.attlist + +# end of glossseealso.module + +# end of glossentry.content.module + +# ItemizedList and OrderedList ..... +local.itemizedlist.attrib = empty +itemizedlist.role.attrib = role.attrib +# doc:A list in which each entry is marked with a bullet or other dingbat. +itemizedlist = + element itemizedlist { + itemizedlist.attlist, + blockinfo?, + formalobject.title.content?, + listpreamble.mix*, + listitem+ + } +# end of itemizedlist.element + +# Spacing: Whether the vertical space in the list should be +# compressed + +# Mark: Keyword, e.g., bullet, dash, checkbox, none; +# list of keywords and defaults are implementation specific +itemizedlist.attlist &= + attribute spacing { "normal" | "compact" }?, + mark.attrib, + common.attrib, + itemizedlist.role.attrib, + local.itemizedlist.attrib +# end of itemizedlist.attlist + +# end of itemizedlist.module +local.orderedlist.attrib = empty +orderedlist.role.attrib = role.attrib +# doc:A list in which each entry is marked with a sequentially incremented label. +orderedlist = + element orderedlist { + orderedlist.attlist, + blockinfo?, + formalobject.title.content?, + listpreamble.mix*, + listitem+ + } +# end of orderedlist.element + +# Numeration: Style of ListItem numbered; default is expected +# to be Arabic + +# InheritNum: Specifies for a nested list that the numbering +# of ListItems should include the number of the item +# within which they are nested (e.g., 1a and 1b within 1, +# rather than a and b) + +# Continuation: Where list numbering begins afresh (Restarts, +# the default) or continues that of the immediately preceding +# list (Continues) + +# Spacing: Whether the vertical space in the list should be +# compressed +orderedlist.attlist &= + attribute numeration { + "arabic" | "upperalpha" | "loweralpha" | "upperroman" | "lowerroman" + }?, + [ a:defaultValue = "ignore" ] + attribute inheritnum { "inherit" | "ignore" }?, + [ a:defaultValue = "restarts" ] + attribute continuation { "continues" | "restarts" }?, + attribute spacing { "normal" | "compact" }?, + common.attrib, + orderedlist.role.attrib, + local.orderedlist.attrib +# end of orderedlist.attlist + +# end of orderedlist.module +local.listitem.attrib = empty +listitem.role.attrib = role.attrib +# doc:A wrapper for the elements of a list item. +listitem = element listitem { listitem.attlist, component.mix+ } +# end of listitem.element + +# Override: Indicates the mark to be used for this ListItem +# instead of the default mark or the mark specified by +# the Mark attribute on the enclosing ItemizedList +listitem.attlist &= + attribute override { text }?, + common.attrib, + listitem.role.attrib, + local.listitem.attrib +# end of listitem.attlist + +# end of listitem.module + +# SegmentedList .................... +local.segmentedlist.attrib = empty +segmentedlist.role.attrib = role.attrib +# doc:A segmented list, a list of sets of elements. +segmentedlist = + element segmentedlist { + segmentedlist.attlist, + formalobject.title.content?, + segtitle+, + seglistitem+ + } +# end of segmentedlist.element +segmentedlist.attlist &= + common.attrib, segmentedlist.role.attrib, local.segmentedlist.attrib +# end of segmentedlist.attlist + +# end of segmentedlist.module +local.segtitle.attrib = empty +segtitle.role.attrib = role.attrib +# doc:The title of an element of a list item in a segmented list. +segtitle = element segtitle { segtitle.attlist, title.char.mix* } +# end of segtitle.element +segtitle.attlist &= + common.attrib, segtitle.role.attrib, local.segtitle.attrib +# end of segtitle.attlist + +# end of segtitle.module +local.seglistitem.attrib = empty +seglistitem.role.attrib = role.attrib +# doc:A list item in a segmented list. +seglistitem = element seglistitem { seglistitem.attlist, seg+ } +# end of seglistitem.element +seglistitem.attlist &= + common.attrib, seglistitem.role.attrib, local.seglistitem.attrib +# end of seglistitem.attlist + +# end of seglistitem.module +local.seg.attrib = empty +seg.role.attrib = role.attrib +# doc:An element of a list item in a segmented list. +seg = element seg { seg.attlist, para.char.mix* } +# end of seg.element +seg.attlist &= common.attrib, seg.role.attrib, local.seg.attrib +# end of seg.attlist + +# end of seg.module + +# end of segmentedlist.content.module + +# SimpleList ....................... +local.simplelist.attrib = empty +simplelist.role.attrib = role.attrib +# doc:An undecorated list of single words or short phrases. +simplelist = element simplelist { simplelist.attlist, member+ } +# end of simplelist.element + +# Columns: The number of columns the array should contain + +# Type: How the Members of the SimpleList should be +# formatted: Inline (members separated with commas etc. +# inline), Vert (top to bottom in n Columns), or Horiz (in +# the direction of text flow) in n Columns. If Column +# is 1 or implied, Type=Vert and Type=Horiz give the same +# results. +simplelist.attlist &= + attribute columns { text }?, + [ a:defaultValue = "vert" ] + attribute type { "inline" | "vert" | "horiz" }?, + common.attrib, + simplelist.role.attrib, + local.simplelist.attrib +# end of simplelist.attlist + +# end of simplelist.module +local.member.attrib = empty +member.role.attrib = role.attrib +# doc:An element of a simple list. +member = element member { member.attlist, para.char.mix* } +# end of member.element +member.attlist &= common.attrib, member.role.attrib, local.member.attrib +# end of member.attlist + +# end of member.module + +# end of simplelist.content.module + +# VariableList ..................... +local.variablelist.attrib = empty +variablelist.role.attrib = role.attrib +# doc:A list in which each entry is composed of a set of one or more terms and an associated description. +variablelist = + element variablelist { + variablelist.attlist, + blockinfo?, + formalobject.title.content?, + listpreamble.mix*, + varlistentry+ + } +# end of variablelist.element + +# TermLength: Length beyond which the presentation engine +# may consider the Term too long and select an alternate +# presentation of the Term and, or, its associated ListItem. +variablelist.attlist &= + attribute termlength { text }?, + attribute spacing { "normal" | "compact" }?, + common.attrib, + variablelist.role.attrib, + local.variablelist.attrib +# end of variablelist.attlist + +# end of variablelist.module +local.varlistentry.attrib = empty +varlistentry.role.attrib = role.attrib +# doc:A wrapper for a set of terms and the associated description in a variable list. +varlistentry = + element varlistentry { varlistentry.attlist, term+, listitem } +# end of varlistentry.element +varlistentry.attlist &= + common.attrib, varlistentry.role.attrib, local.varlistentry.attrib +# end of varlistentry.attlist + +# end of varlistentry.module +local.term.attrib = empty +term.role.attrib = role.attrib +# doc:The word or phrase being defined or described in a variable list. +term = element term { term.attlist, para.char.mix* } +# end of term.element +term.attlist &= common.attrib, term.role.attrib, local.term.attrib +# end of term.attlist + +# end of term.module + +# ListItem (defined above) + +# end of variablelist.content.module + +# CalloutList ...................... +local.calloutlist.attrib = empty +calloutlist.role.attrib = role.attrib +# doc:A list of Callouts. +calloutlist = + element calloutlist { + calloutlist.attlist, formalobject.title.content?, callout+ + } +# end of calloutlist.element +calloutlist.attlist &= + common.attrib, calloutlist.role.attrib, local.calloutlist.attrib +# end of calloutlist.attlist + +# end of calloutlist.module +local.callout.attrib = empty +callout.role.attrib = role.attrib +# doc:A “called out” description of a marked Area. +callout = element callout { callout.attlist, component.mix+ } +# end of callout.element + +# AreaRefs: IDs of one or more Areas or AreaSets described +# by this Callout +callout.attlist &= + attribute arearefs { xsd:IDREFS }, + common.attrib, + callout.role.attrib, + local.callout.attrib +# end of callout.attlist + +# end of callout.module + +# end of calloutlist.content.module + +# ...................................................................... + +# Objects .............................................................. + +# Examples etc. .................... +local.example.attrib = empty +example.role.attrib = role.attrib +# doc:A formal example, with a title. +example = + element example { + example.attlist, + blockinfo?, + formalobject.title.content, + example.mix+ + } +# end of example.element +example.attlist &= + attribute floatstyle { text }?, + label.attrib, + width.attrib, + common.attrib, + example.role.attrib, + local.example.attrib +# end of example.attlist + +# end of example.module +local.informalexample.attrib = empty +informalexample.role.attrib = role.attrib +# doc:A displayed example without a title. +informalexample = + element informalexample { + informalexample.attlist, blockinfo?, example.mix+ + } +# end of informalexample.element +informalexample.attlist &= + attribute floatstyle { text }?, + width.attrib, + common.attrib, + informalexample.role.attrib, + local.informalexample.attrib +# end of informalexample.attlist + +# end of informalexample.module +local.programlistingco.attrib = empty +programlistingco.role.attrib = role.attrib +# doc:A program listing with associated areas used in callouts. +programlistingco = + element programlistingco { + programlistingco.attlist, areaspec, programlisting, calloutlist* + } +# end of programlistingco.element +programlistingco.attlist &= + common.attrib, + programlistingco.role.attrib, + local.programlistingco.attrib +# end of programlistingco.attlist + +# CalloutList (defined above in Lists) + +# end of informalexample.module +local.areaspec.attrib = empty +areaspec.role.attrib = role.attrib +# doc:A collection of regions in a graphic or code example. +areaspec = element areaspec { areaspec.attlist, (area | areaset)+ } +# end of areaspec.element + +# Units: global unit of measure in which coordinates in +# this spec are expressed: +# +# - CALSPair "x1,y1 x2,y2": lower-left and upper-right +# coordinates in a rectangle describing repro area in which +# graphic is placed, where X and Y dimensions are each some +# number 0..10000 (taken from CALS graphic attributes) +# +# - LineColumn "line column": line number and column number +# at which to start callout text in "linespecific" content +# +# - LineRange "startline endline": whole lines from startline +# to endline in "linespecific" content +# +# - LineColumnPair "line1 col1 line2 col2": starting and ending +# points of area in "linespecific" content that starts at +# first position and ends at second position (including the +# beginnings of any intervening lines) +# +# - Other: directive to look at value of OtherUnits attribute +# to get implementation-specific keyword +# +# The default is implementation-specific; usually dependent on +# the parent element (GraphicCO gets CALSPair, ProgramListingCO +# and ScreenCO get LineColumn) + +# OtherUnits: User-defined units +areaspec.attlist &= + attribute units { + "calspair" | "linecolumn" | "linerange" | "linecolumnpair" | "other" + }?, + attribute otherunits { xsd:NMTOKEN }?, + common.attrib, + areaspec.role.attrib, + local.areaspec.attrib +# end of areaspec.attlist + +# end of areaspec.module +local.area.attrib = empty +area.role.attrib = role.attrib +# doc:A region defined for a Callout in a graphic or code example. +area = element area { area.attlist, empty } +# end of area.element + +# bug number/symbol override or initialization + +# to any related information + +# Units: unit of measure in which coordinates in this +# area are expressed; inherits from AreaSet and AreaSpec + +# OtherUnits: User-defined units +area.attlist &= + label.attrib, + linkends.attrib, + attribute units { + "calspair" | "linecolumn" | "linerange" | "linecolumnpair" | "other" + }?, + attribute otherunits { xsd:NMTOKEN }?, + attribute coords { text }, + idreq.common.attrib, + area.role.attrib, + local.area.attrib +# end of area.attlist + +# end of area.module +local.areaset.attrib = empty +areaset.role.attrib = role.attrib +# doc:A set of related areas in a graphic or code example. +areaset = element areaset { areaset.attlist, area+ } +# end of areaset.element + +# bug number/symbol override or initialization + +# Units: unit of measure in which coordinates in this +# area are expressed; inherits from AreaSpec +areaset.attlist &= + label.attrib, + attribute units { + "calspair" | "linecolumn" | "linerange" | "linecolumnpair" | "other" + }?, + attribute otherunits { xsd:NMTOKEN }?, + attribute coords { text }, + idreq.common.attrib, + areaset.role.attrib, + local.areaset.attrib +# end of areaset.attlist + +# end of areaset.module + +# end of areaspec.content.module +local.programlisting.attrib = empty +programlisting.role.attrib = role.attrib +# doc:A literal listing of all or part of a program. +programlisting = + element programlisting { + programlisting.attlist, + (para.char.mix | co | coref | lineannotation | textobject)* + } +# end of programlisting.element +programlisting.attlist &= + width.attrib, + linespecific.attrib, + common.attrib, + programlisting.role.attrib, + local.programlisting.attrib +# end of programlisting.attlist + +# end of programlisting.module +local.literallayout.attrib = empty +literallayout.role.attrib = role.attrib +# doc:A block of text in which line breaks and white space are to be reproduced faithfully. +literallayout = + element literallayout { + literallayout.attlist, + (para.char.mix | co | coref | textobject | lineannotation)* + } +# end of literallayout.element +literallayout.attlist &= + width.attrib, + linespecific.attrib, + [ a:defaultValue = "normal" ] + attribute class { "monospaced" | "normal" }?, + common.attrib, + literallayout.role.attrib, + local.literallayout.attrib +# end of literallayout.attlist + +# LineAnnotation (defined in the Inlines section, below) + +# end of literallayout.module +local.screenco.attrib = empty +screenco.role.attrib = role.attrib +# doc:A screen with associated areas used in callouts. +screenco = + element screenco { screenco.attlist, areaspec, screen, calloutlist* } +# end of screenco.element +screenco.attlist &= + common.attrib, screenco.role.attrib, local.screenco.attrib +# end of screenco.attlist + +# AreaSpec (defined above) + +# CalloutList (defined above in Lists) + +# end of screenco.module +local.screen.attrib = empty +screen.role.attrib = role.attrib +# doc:Text that a user sees or might see on a computer screen. +screen = + element screen { + screen.attlist, + (para.char.mix | co | coref | textobject | lineannotation)* + } +# end of screen.element +screen.attlist &= + width.attrib, + linespecific.attrib, + common.attrib, + screen.role.attrib, + local.screen.attrib +# end of screen.attlist + +# end of screen.module +local.screenshot.attrib = empty +screenshot.role.attrib = role.attrib +# doc:A representation of what the user sees or might see on a computer screen. +screenshot = + element screenshot { + screenshot.attlist, + screeninfo?, + (graphic | graphicco | mediaobject | mediaobjectco) + } +# end of screenshot.element +screenshot.attlist &= + common.attrib, screenshot.role.attrib, local.screenshot.attrib +# end of screenshot.attlist + +# end of screenshot.module +local.screeninfo.attrib = empty +screeninfo.role.attrib = role.attrib +# doc:Information about how a screen shot was produced. +screeninfo = element screeninfo { screeninfo.attlist, para.char.mix* } +# end of screeninfo.element +screeninfo.attlist &= + common.attrib, screeninfo.role.attrib, local.screeninfo.attrib +# end of screeninfo.attlist + +# end of screeninfo.module + +# end of screenshot.content.module + +# Figures etc. ..................... +local.figure.attrib = empty +figure.role.attrib = role.attrib +# doc:A formal figure, generally an illustration, with a title. +figure = + element figure { + figure.attlist, + blockinfo?, + formalobject.title.content, + (figure.mix | link.char.class)+ + } +# end of figure.element + +# Float: Whether the Figure is supposed to be rendered +# where convenient (yes (1) value) or at the place it occurs +# in the text (no (0) value, the default) +figure.attlist &= + [ a:defaultValue = "0" ] attribute float { yesorno.attvals }?, + attribute floatstyle { text }?, + attribute pgwide { yesorno.attvals }?, + label.attrib, + common.attrib, + figure.role.attrib, + local.figure.attrib +# end of figure.attlist + +# end of figure.module +local.informalfigure.attrib = empty +informalfigure.role.attrib = role.attrib +# doc:A untitled figure. +informalfigure = + element informalfigure { + informalfigure.attlist, blockinfo?, (figure.mix | link.char.class)+ + } +# end of informalfigure.element + +# Float: Whether the Figure is supposed to be rendered +# where convenient (yes (1) value) or at the place it occurs +# in the text (no (0) value, the default) +informalfigure.attlist &= + [ a:defaultValue = "0" ] attribute float { yesorno.attvals }?, + attribute floatstyle { text }?, + attribute pgwide { yesorno.attvals }?, + label.attrib, + common.attrib, + informalfigure.role.attrib, + local.informalfigure.attrib +# end of informalfigure.attlist + +# end of informalfigure.module +local.graphicco.attrib = empty +graphicco.role.attrib = role.attrib +# doc:A graphic that contains callout areas. +graphicco = + element graphicco { + graphicco.attlist, areaspec, graphic, calloutlist* + } +# end of graphicco.element +graphicco.attlist &= + common.attrib, graphicco.role.attrib, local.graphicco.attrib +# end of graphicco.attlist + +# AreaSpec (defined above in Examples) + +# CalloutList (defined above in Lists) + +# end of graphicco.module + +# Graphical data can be the content of Graphic, or you can reference +# an external file either as an entity (Entitref) or a filename +# (Fileref). +local.graphic.attrib = empty +graphic.role.attrib = role.attrib +# doc:A displayed graphical object (not an inline). +graphic = element graphic { graphic.attlist, empty } +# end of graphic.element +graphic.attlist &= + graphics.attrib, + common.attrib, + graphic.role.attrib, + local.graphic.attrib +# end of graphic.attlist + +# end of graphic.module +local.inlinegraphic.attrib = empty +inlinegraphic.role.attrib = role.attrib +# doc:An object containing or pointing to graphical data that will be rendered inline. +inlinegraphic = element inlinegraphic { inlinegraphic.attlist, empty } +# end of inlinegraphic.element +inlinegraphic.attlist &= + graphics.attrib, + common.attrib, + inlinegraphic.role.attrib, + local.inlinegraphic.attrib +# end of inlinegraphic.attlist + +# end of inlinegraphic.module +local.mediaobject.attrib = empty +mediaobject.role.attrib = role.attrib +# doc:A displayed media object (video, audio, image, etc.). +mediaobject = + element mediaobject { + mediaobject.attlist, objectinfo?, mediaobject.mix+, caption? + } +# end of mediaobject.element +mediaobject.attlist &= + common.attrib, mediaobject.role.attrib, local.mediaobject.attrib +# end of mediaobject.attlist + +# end of mediaobject.module +local.inlinemediaobject.attrib = empty +inlinemediaobject.role.attrib = role.attrib +# doc:An inline media object (video, audio, image, and so on). +inlinemediaobject = + element inlinemediaobject { + inlinemediaobject.attlist, objectinfo?, mediaobject.mix+ + } +# end of inlinemediaobject.element +inlinemediaobject.attlist &= + common.attrib, + inlinemediaobject.role.attrib, + local.inlinemediaobject.attrib +# end of inlinemediaobject.attlist + +# end of inlinemediaobject.module +local.videoobject.attrib = empty +videoobject.role.attrib = role.attrib +# doc:A wrapper for video data and its associated meta-information. +videoobject = + element videoobject { videoobject.attlist, objectinfo?, videodata } +# end of videoobject.element +videoobject.attlist &= + common.attrib, videoobject.role.attrib, local.videoobject.attrib +# end of videoobject.attlist + +# end of videoobject.module +local.audioobject.attrib = empty +audioobject.role.attrib = role.attrib +# doc:A wrapper for audio data and its associated meta-information. +audioobject = + element audioobject { audioobject.attlist, objectinfo?, audiodata } +# end of audioobject.element +audioobject.attlist &= + common.attrib, audioobject.role.attrib, local.audioobject.attrib +# end of audioobject.attlist + +# end of audioobject.module +local.imageobject.attrib = empty +imageobject.role.attrib = role.attrib +# doc:A wrapper for image data and its associated meta-information. +imageobject = + element imageobject { imageobject.attlist, objectinfo?, imagedata } +# end of imageobject.element +imageobject.attlist &= + common.attrib, imageobject.role.attrib, local.imageobject.attrib +# end of imageobject.attlist + +# end of imageobject.module +local.textobject.attrib = empty +textobject.role.attrib = role.attrib +# doc:A wrapper for a text description of an object and its associated meta-information. +textobject = + element textobject { + textobject.attlist, + objectinfo?, + (phrase | textdata | textobject.mix+) + } +# end of textobject.element +textobject.attlist &= + common.attrib, textobject.role.attrib, local.textobject.attrib +# end of textobject.attlist + +# end of textobject.module +local.objectinfo.attrib = empty +objectinfo.role.attrib = role.attrib +# doc:Meta-information for an object. +objectinfo = element objectinfo { objectinfo.attlist, info.class+ } +# end of objectinfo.element +objectinfo.attlist &= + common.attrib, objectinfo.role.attrib, local.objectinfo.attrib +# end of objectinfo.attlist + +# end of objectinfo.module + +# EntityRef: Name of an external entity containing the content +# of the object data + +# FileRef: Filename, qualified by a pathname if desired, +# designating the file containing the content of the object data + +# Format: Notation of the element content, if any + +# SrcCredit: Information about the source of the image +local.objectdata.attrib = empty +objectdata.attrib = + attribute entityref { xsd:ENTITY }?, + attribute fileref { text }?, + attribute format { notation.class }?, + attribute srccredit { text }?, + local.objectdata.attrib +local.videodata.attrib = empty +videodata.role.attrib = role.attrib +# doc:Pointer to external video data. +videodata = element videodata { videodata.attlist, empty } +# end of videodata.element + +# Width: Same as CALS reprowid (desired width) + +# Depth: Same as CALS reprodep (desired depth) + +# Align: Same as CALS hplace with 'none' removed; #IMPLIED means +# application-specific + +# Scale: Conflation of CALS hscale and vscale + +# Scalefit: Same as CALS scalefit +videodata.attlist &= + attribute width { text }?, + attribute contentwidth { text }?, + attribute depth { text }?, + attribute contentdepth { text }?, + attribute align { "left" | "right" | "center" }?, + attribute valign { "top" | "middle" | "bottom" }?, + attribute scale { text }?, + attribute scalefit { yesorno.attvals }?, + objectdata.attrib, + common.attrib, + videodata.role.attrib, + local.videodata.attrib +# end of videodata.attlist + +# end of videodata.module +local.audiodata.attrib = empty +audiodata.role.attrib = role.attrib +# doc:Pointer to external audio data. +audiodata = element audiodata { audiodata.attlist, empty } +# end of audiodata.element +audiodata.attlist &= + objectdata.attrib, + common.attrib, + audiodata.role.attrib, + local.audiodata.attrib +# end of audiodata.attlist + +# end of audiodata.module +local.imagedata.attrib = empty +imagedata.role.attrib = role.attrib +# doc:Pointer to external image data. +imagedata = element imagedata { imagedata.attlist, empty } +# end of imagedata.element + +# Width: Same as CALS reprowid (desired width) + +# Depth: Same as CALS reprodep (desired depth) + +# Align: Same as CALS hplace with 'none' removed; #IMPLIED means +# application-specific + +# Scale: Conflation of CALS hscale and vscale + +# Scalefit: Same as CALS scalefit +imagedata.attlist &= + attribute width { text }?, + attribute contentwidth { text }?, + attribute depth { text }?, + attribute contentdepth { text }?, + attribute align { "left" | "right" | "center" }?, + attribute valign { "top" | "middle" | "bottom" }?, + attribute scale { text }?, + attribute scalefit { yesorno.attvals }?, + objectdata.attrib, + common.attrib, + imagedata.role.attrib, + local.imagedata.attrib +# end of imagedata.attlist + +# end of imagedata.module +local.textdata.attrib = empty +textdata.role.attrib = role.attrib +# doc:Pointer to external text data. +textdata = element textdata { textdata.attlist, empty } +# end of textdata.element +textdata.attlist &= + attribute encoding { text }?, + objectdata.attrib, + common.attrib, + textdata.role.attrib, + local.textdata.attrib +# end of textdata.attlist + +# end of textdata.module +local.mediaobjectco.attrib = empty +mediaobjectco.role.attrib = role.attrib +# doc:A media object that contains callouts. +mediaobjectco = + element mediaobjectco { + mediaobjectco.attlist, + objectinfo?, + imageobjectco, + (imageobjectco | textobject)* + } +# end of mediaobjectco.element +mediaobjectco.attlist &= + common.attrib, mediaobjectco.role.attrib, local.mediaobjectco.attrib +# end of mediaobjectco.attlist + +# end of mediaobjectco.module +local.imageobjectco.attrib = empty +imageobjectco.role.attrib = role.attrib +# doc:A wrapper for an image object with callouts. +imageobjectco = + element imageobjectco { + imageobjectco.attlist, areaspec, imageobject, calloutlist* + } +# end of imageobjectco.element +imageobjectco.attlist &= + common.attrib, imageobjectco.role.attrib, local.imageobjectco.attrib +# end of imageobjectco.attlist + +# end of imageobjectco.module + +# end of mediaobject.content.module + +# Equations ........................ + +# This PE provides a mechanism for replacing equation content, + +# perhaps adding a new or different model (e.g., MathML) +equation.content = alt?, (graphic+ | mediaobject+ | mathphrase+) +inlineequation.content = + alt?, (graphic+ | inlinemediaobject+ | mathphrase+) +local.equation.attrib = empty +equation.role.attrib = role.attrib +# doc:A displayed mathematical equation. +equation = + element equation { + equation.attlist, + blockinfo?, + formalobject.title.content?, + (informalequation | equation.content) + } +# end of equation.element +equation.attlist &= + attribute floatstyle { text }?, + label.attrib, + common.attrib, + equation.role.attrib, + local.equation.attrib +# end of equation.attlist + +# end of equation.module +local.informalequation.attrib = empty +informalequation.role.attrib = role.attrib +# doc:A displayed mathematical equation without a title. +informalequation = + element informalequation { + informalequation.attlist, blockinfo?, equation.content + } +# end of informalequation.element +informalequation.attlist &= + attribute floatstyle { text }?, + common.attrib, + informalequation.role.attrib, + local.informalequation.attrib +# end of informalequation.attlist + +# end of informalequation.module +local.inlineequation.attrib = empty +inlineequation.role.attrib = role.attrib +# doc:A mathematical equation or expression occurring inline. +inlineequation = + element inlineequation { + inlineequation.attlist, inlineequation.content + } +# end of inlineequation.element +inlineequation.attlist &= + common.attrib, inlineequation.role.attrib, local.inlineequation.attrib +# end of inlineequation.attlist + +# end of inlineequation.module +local.alt.attrib = empty +alt.role.attrib = role.attrib +# doc:Text representation for a graphical element. +alt = element alt { alt.attlist, text } +# end of alt.element +alt.attlist &= common.attrib, alt.role.attrib, local.alt.attrib +# end of alt.attlist + +# end of alt.module +local.mathphrase.attrib = empty +mathphrase.role.attrib = role.attrib +# doc:A mathematical phrase, an expression that can be represented with ordinary text and a small amount of markup. +mathphrase = + element mathphrase { + mathphrase.attlist, (text | subscript | superscript | emphasis)* + } +# end of mathphrase.element +mathphrase.attlist &= + common.attrib, mathphrase.role.attrib, local.mathphrase.attrib +# end of mathphrase.attlist + +# end of mathphrase.module + +# Tables ........................... + +# Choose a table model. CALS or OASIS XML Exchange + +# Do we allow the HTML table model as well? + +# ====================================================== + +# xhtmltbl.mod defines HTML tables and sets parameter +# entities so that, when the CALS table module is read, +# we end up allowing any table to be CALS or HTML. +# i.e. This include must come first! + +# ====================================================== +include "htmltblx.rnc" +# end of allow.html.tables + +# Add label and role attributes to table and informaltable + +# Add common attributes to Table, TGroup, TBody, THead, TFoot, Row, +# EntryTbl, and Entry (and InformalTable element). + +# Content model for Table. + +# Allow either objects or inlines; beware of REs between elements. + +# Reference CALS Table Model +include "calstblx.rnc" +# end of table.module + +# Note that InformalTable is dependent on some of the entity +# declarations that customize Table. +local.informaltable.attrib = empty +# the following entity may have been declared by the XHTML table module + +# doc:A table without a title. +informaltable = + element informaltable { + informaltable.attlist, blockinfo?, informal.tbl.table.mdl + } +# end of informaltable.element + +# Frame, Colsep, and Rowsep must be repeated because +# they are not in entities in the table module. + +# includes TabStyle, ToCentry, ShortEntry, +# Orient, PgWide + +# includes Label + +# includes common attributes +informaltable.attlist &= + attribute frame { tbl.frame.attval }?, + attribute colsep { yesorno.attvals }?, + attribute rowsep { yesorno.attvals }?, + common.table.attribs, + tbl.table.att, + local.informaltable.attrib +# end of informaltable.attlist + +# end of informaltable.module +local.caption.attrib = empty +caption.role.attrib = role.attrib +# doc:A caption. +caption = element caption { caption.attlist, (text | textobject.mix)* } +# end of caption.element + +# attrs comes from HTML tables ... + +# common.attrib, but without ID because ID is in attrs +caption.attlist.content = + caption.role.attrib, + attrs, + attribute align { "top" | "bottom" | "left" | "right" }?, + local.caption.attrib +caption.attlist &= caption.attlist.content +# end of caption.attlist + +# end of caption.module + +# ...................................................................... + +# Synopses ............................................................. + +# Synopsis ......................... +local.synopsis.attrib = empty +synopsis.role.attrib = role.attrib +# doc:A general-purpose element for representing the syntax of commands or functions. +synopsis = + element synopsis { + synopsis.attlist, + (para.char.mix + | graphic + | mediaobject + | co + | coref + | textobject + | lineannotation)* + } +# end of synopsis.element +synopsis.attlist &= + label.attrib, + linespecific.attrib, + common.attrib, + synopsis.role.attrib, + local.synopsis.attrib +# end of synopsis.attlist + +# LineAnnotation (defined in the Inlines section, below) + +# end of synopsis.module + +# CmdSynopsis ...................... +local.cmdsynopsis.attrib = empty +cmdsynopsis.role.attrib = role.attrib +# doc:A syntax summary for a software command. +cmdsynopsis = + element cmdsynopsis { + cmdsynopsis.attlist, (command | arg | group | sbr)+, synopfragment* + } +# end of cmdsynopsis.element + +# Sepchar: Character that should separate command and all +# top-level arguments; alternate value might be e.g., Δ +cmdsynopsis.attlist &= + label.attrib, + [ a:defaultValue = " " ] attribute sepchar { text }?, + attribute cmdlength { text }?, + common.attrib, + cmdsynopsis.role.attrib, + local.cmdsynopsis.attrib +# end of cmdsynopsis.attlist + +# end of cmdsynopsis.module +local.arg.attrib = empty +arg.role.attrib = role.attrib +# doc:An argument in a CmdSynopsis. +arg = + element arg { + arg.attlist, + (text + | arg + | group + | option + | synopfragmentref + | replaceable + | sbr)* + } +# end of arg.element + +# Choice: Whether Arg must be supplied: Opt (optional to +# supply, e.g. [arg]; the default), Req (required to supply, +# e.g. {arg}), or Plain (required to supply, e.g. arg) + +# Rep: whether Arg is repeatable: Norepeat (e.g. arg without +# ellipsis; the default), or Repeat (e.g. arg...) +arg.attlist &= + [ a:defaultValue = "opt" ] + attribute choice { "opt" | "req" | "plain" }?, + [ a:defaultValue = "norepeat" ] + attribute rep { "norepeat" | "repeat" }?, + common.attrib, + arg.role.attrib, + local.arg.attrib +# end of arg.attlist + +# end of arg.module +local.group.attrib = empty +group.role.attrib = role.attrib +# doc:A group of elements in a CmdSynopsis. +group = + element group { + group.attlist, + (arg | group | option | synopfragmentref | replaceable | sbr)+ + } +# end of group.element + +# Choice: Whether Group must be supplied: Opt (optional to +# supply, e.g. [g1|g2|g3]; the default), Req (required to +# supply, e.g. {g1|g2|g3}), Plain (required to supply, +# e.g. g1|g2|g3), OptMult (can supply zero or more, e.g. +# [[g1|g2|g3]]), or ReqMult (must supply one or more, e.g. +# {{g1|g2|g3}}) + +# Rep: whether Group is repeatable: Norepeat (e.g. group +# without ellipsis; the default), or Repeat (e.g. group...) +group.attlist &= + [ a:defaultValue = "opt" ] + attribute choice { "opt" | "req" | "plain" }?, + [ a:defaultValue = "norepeat" ] + attribute rep { "norepeat" | "repeat" }?, + common.attrib, + group.role.attrib, + local.group.attrib +# end of group.attlist + +# end of group.module +local.sbr.attrib = empty +# Synopsis break +sbr.role.attrib = role.attrib +# doc:An explicit line break in a command synopsis. +sbr = element sbr { sbr.attlist, empty } +# end of sbr.element +sbr.attlist &= common.attrib, sbr.role.attrib, local.sbr.attrib +# end of sbr.attlist + +# end of sbr.module +local.synopfragmentref.attrib = empty +synopfragmentref.role.attrib = role.attrib +# doc:A reference to a fragment of a command synopsis. +synopfragmentref = + element synopfragmentref { synopfragmentref.attlist, text } +# end of synopfragmentref.element + +# to SynopFragment of complex synopsis +# material for separate referencing +synopfragmentref.attlist &= + linkendreq.attrib, + common.attrib, + synopfragmentref.role.attrib, + local.synopfragmentref.attrib +# end of synopfragmentref.attlist + +# end of synopfragmentref.module +local.synopfragment.attrib = empty +synopfragment.role.attrib = role.attrib +# doc:A portion of a CmdSynopsis broken out from the main body of the synopsis. +synopfragment = + element synopfragment { synopfragment.attlist, (arg | group)+ } +# end of synopfragment.element +synopfragment.attlist &= + idreq.common.attrib, + synopfragment.role.attrib, + local.synopfragment.attrib +# end of synopfragment.attlist + +# end of synopfragment.module + +# Command (defined in the Inlines section, below) + +# Option (defined in the Inlines section, below) + +# Replaceable (defined in the Inlines section, below) + +# end of cmdsynopsis.content.module + +# FuncSynopsis ..................... +local.funcsynopsis.attrib = empty +funcsynopsis.role.attrib = role.attrib +# doc:The syntax summary for a function definition. +funcsynopsis = + element funcsynopsis { + funcsynopsis.attlist, (funcsynopsisinfo | funcprototype)+ + } +# end of funcsynopsis.element +funcsynopsis.attlist &= + label.attrib, + common.attrib, + funcsynopsis.role.attrib, + local.funcsynopsis.attrib +# end of funcsynopsis.attlist + +# end of funcsynopsis.module +local.funcsynopsisinfo.attrib = empty +funcsynopsisinfo.role.attrib = role.attrib +# doc:Information supplementing the FuncDefs of a FuncSynopsis. +funcsynopsisinfo = + element funcsynopsisinfo { + funcsynopsisinfo.attlist, + (cptr.char.mix | textobject | lineannotation)* + } +# end of funcsynopsisinfo.element +funcsynopsisinfo.attlist &= + linespecific.attrib, + common.attrib, + funcsynopsisinfo.role.attrib, + local.funcsynopsisinfo.attrib +# end of funcsynopsisinfo.attlist + +# end of funcsynopsisinfo.module +local.funcprototype.attrib = empty +funcprototype.role.attrib = role.attrib +# doc:The prototype of a function. +funcprototype = + element funcprototype { + funcprototype.attlist, + modifier*, + funcdef, + (void | varargs | (paramdef+, varargs?)), + modifier* + } +# end of funcprototype.element +funcprototype.attlist &= + common.attrib, funcprototype.role.attrib, local.funcprototype.attrib +# end of funcprototype.attlist + +# end of funcprototype.module +local.funcdef.attrib = empty +funcdef.role.attrib = role.attrib +# doc:A function (subroutine) name and its return type. +funcdef = + element funcdef { + funcdef.attlist, (text | type | replaceable | function)* + } +# end of funcdef.element +funcdef.attlist &= + common.attrib, funcdef.role.attrib, local.funcdef.attrib +# end of funcdef.attlist + +# end of funcdef.module +local.void.attrib = empty +void.role.attrib = role.attrib +# doc:An empty element in a function synopsis indicating that the function in question takes no arguments. +void = element void { void.attlist, empty } +# end of void.element +void.attlist &= common.attrib, void.role.attrib, local.void.attrib +# end of void.attlist + +# end of void.module +local.varargs.attrib = empty +varargs.role.attrib = role.attrib +# doc:An empty element in a function synopsis indicating a variable number of arguments. +varargs = element varargs { varargs.attlist, empty } +# end of varargs.element +varargs.attlist &= + common.attrib, varargs.role.attrib, local.varargs.attrib +# end of varargs.attlist + +# end of varargs.module + +# Processing assumes that only one Parameter will appear in a +# ParamDef, and that FuncParams will be used at most once, for +# providing information on the "inner parameters" for parameters that +# are pointers to functions. +local.paramdef.attrib = empty +paramdef.role.attrib = role.attrib +# doc:Information about a function parameter in a programming language. +paramdef = + element paramdef { + paramdef.attlist, + (text | initializer | type | replaceable | parameter | funcparams)* + } +# end of paramdef.element +paramdef.attlist &= + attribute choice { "opt" | "req" }?, + common.attrib, + paramdef.role.attrib, + local.paramdef.attrib +# end of paramdef.attlist + +# end of paramdef.module +local.funcparams.attrib = empty +funcparams.role.attrib = role.attrib +# doc:Parameters for a function referenced through a function pointer in a synopsis. +funcparams = element funcparams { funcparams.attlist, cptr.char.mix* } +# end of funcparams.element +funcparams.attlist &= + common.attrib, funcparams.role.attrib, local.funcparams.attrib +# end of funcparams.attlist + +# end of funcparams.module + +# LineAnnotation (defined in the Inlines section, below) + +# Replaceable (defined in the Inlines section, below) + +# Function (defined in the Inlines section, below) + +# Parameter (defined in the Inlines section, below) + +# end of funcsynopsis.content.module + +# ClassSynopsis ..................... +local.classsynopsis.attrib = empty +classsynopsis.role.attrib = role.attrib +# doc:The syntax summary for a class definition. +classsynopsis = + element classsynopsis { + classsynopsis.attlist, + (ooclass | oointerface | ooexception)+, + (classsynopsisinfo | fieldsynopsis | method.synop.class)* + } +# end of classsynopsis.element +classsynopsis.attlist &= + attribute language { text }?, + [ a:defaultValue = "class" ] + attribute class { "class" | "interface" }?, + common.attrib, + classsynopsis.role.attrib, + local.classsynopsis.attrib +# end of classsynopsis.attlist + +# end of classsynopsis.module +local.classsynopsisinfo.attrib = empty +classsynopsisinfo.role.attrib = role.attrib +# doc:Information supplementing the contents of a ClassSynopsis. +classsynopsisinfo = + element classsynopsisinfo { + classsynopsisinfo.attlist, + (cptr.char.mix | textobject | lineannotation)* + } +# end of classsynopsisinfo.element +classsynopsisinfo.attlist &= + linespecific.attrib, + common.attrib, + classsynopsisinfo.role.attrib, + local.classsynopsisinfo.attrib +# end of classsynopsisinfo.attlist + +# end of classsynopsisinfo.module +local.ooclass.attrib = empty +ooclass.role.attrib = role.attrib +# doc:A class in an object-oriented programming language. +ooclass = + element ooclass { ooclass.attlist, (modifier | package)*, classname } +# end of ooclass.element +ooclass.attlist &= + common.attrib, ooclass.role.attrib, local.ooclass.attrib +# end of ooclass.attlist + +# end of ooclass.module +local.oointerface.attrib = empty +oointerface.role.attrib = role.attrib +# doc:An interface in an object-oriented programming language. +oointerface = + element oointerface { + oointerface.attlist, (modifier | package)*, interfacename + } +# end of oointerface.element +oointerface.attlist &= + common.attrib, oointerface.role.attrib, local.oointerface.attrib +# end of oointerface.attlist + +# end of oointerface.module +local.ooexception.attrib = empty +ooexception.role.attrib = role.attrib +# doc:An exception in an object-oriented programming language. +ooexception = + element ooexception { + ooexception.attlist, (modifier | package)*, exceptionname + } +# end of ooexception.element +ooexception.attlist &= + common.attrib, ooexception.role.attrib, local.ooexception.attrib +# end of ooexception.attlist + +# end of ooexception.module +local.modifier.attrib = empty +modifier.role.attrib = role.attrib +# doc:Modifiers in a synopsis. +modifier = element modifier { modifier.attlist, smallcptr.char.mix* } +# end of modifier.element +modifier.attlist &= + common.attrib, modifier.role.attrib, local.modifier.attrib +# end of modifier.attlist + +# end of modifier.module +local.interfacename.attrib = empty +interfacename.role.attrib = role.attrib +# doc:The name of an interface. +interfacename = + element interfacename { interfacename.attlist, cptr.char.mix* } +# end of interfacename.element +interfacename.attlist &= + common.attrib, interfacename.role.attrib, local.interfacename.attrib +# end of interfacename.attlist + +# end of interfacename.module +local.exceptionname.attrib = empty +exceptionname.role.attrib = role.attrib +# doc:The name of an exception. +exceptionname = + element exceptionname { exceptionname.attlist, smallcptr.char.mix* } +# end of exceptionname.element +exceptionname.attlist &= + common.attrib, exceptionname.role.attrib, local.exceptionname.attrib +# end of exceptionname.attlist + +# end of exceptionname.module +local.fieldsynopsis.attrib = empty +fieldsynopsis.role.attrib = role.attrib +# doc:The name of a field in a class definition. +fieldsynopsis = + element fieldsynopsis { + fieldsynopsis.attlist, modifier*, type?, varname, initializer? + } +# end of fieldsynopsis.element +fieldsynopsis.attlist &= + attribute language { text }?, + common.attrib, + fieldsynopsis.role.attrib, + local.fieldsynopsis.attrib +# end of fieldsynopsis.attlist + +# end of fieldsynopsis.module +local.initializer.attrib = empty +initializer.role.attrib = role.attrib +# doc:The initializer for a FieldSynopsis. +initializer = + element initializer { initializer.attlist, smallcptr.char.mix* } +# end of initializer.element +initializer.attlist &= + common.attrib, initializer.role.attrib, local.initializer.attrib +# end of initializer.attlist + +# end of initializer.module +local.constructorsynopsis.attrib = empty +constructorsynopsis.role.attrib = role.attrib +# doc:A syntax summary for a constructor. +constructorsynopsis = + element constructorsynopsis { + constructorsynopsis.attlist, + modifier*, + methodname?, + (methodparam+ | void?), + exceptionname* + } +# end of constructorsynopsis.element +constructorsynopsis.attlist &= + attribute language { text }?, + common.attrib, + constructorsynopsis.role.attrib, + local.constructorsynopsis.attrib +# end of constructorsynopsis.attlist + +# end of constructorsynopsis.module +local.destructorsynopsis.attrib = empty +destructorsynopsis.role.attrib = role.attrib +# doc:A syntax summary for a destructor. +destructorsynopsis = + element destructorsynopsis { + destructorsynopsis.attlist, + modifier*, + methodname?, + (methodparam+ | void?), + exceptionname* + } +# end of destructorsynopsis.element +destructorsynopsis.attlist &= + attribute language { text }?, + common.attrib, + destructorsynopsis.role.attrib, + local.destructorsynopsis.attrib +# end of destructorsynopsis.attlist + +# end of destructorsynopsis.module +local.methodsynopsis.attrib = empty +methodsynopsis.role.attrib = role.attrib +# doc:A syntax summary for a method. +methodsynopsis = + element methodsynopsis { + methodsynopsis.attlist, + modifier*, + (type | void)?, + methodname, + (methodparam+ | void?), + exceptionname*, + modifier* + } +# end of methodsynopsis.element +methodsynopsis.attlist &= + attribute language { text }?, + common.attrib, + methodsynopsis.role.attrib, + local.methodsynopsis.attrib +# end of methodsynopsis.attlist + +# end of methodsynopsis.module +local.methodname.attrib = empty +methodname.role.attrib = role.attrib +# doc:The name of a method. +methodname = + element methodname { methodname.attlist, smallcptr.char.mix* } +# end of methodname.element +methodname.attlist &= + common.attrib, methodname.role.attrib, local.methodname.attrib +# end of methodname.attlist + +# end of methodname.module +local.methodparam.attrib = empty +methodparam.role.attrib = role.attrib +# doc:Parameters to a method. +methodparam = + element methodparam { + methodparam.attlist, + modifier*, + type?, + ((parameter, initializer?) | funcparams), + modifier* + } +# end of methodparam.element +methodparam.attlist &= + [ a:defaultValue = "req" ] + attribute choice { "opt" | "req" | "plain" }?, + [ a:defaultValue = "norepeat" ] + attribute rep { "norepeat" | "repeat" }?, + common.attrib, + methodparam.role.attrib, + local.methodparam.attrib +# end of methodparam.attlist + +# end of methodparam.module + +# end of classsynopsis.content.module + +# ...................................................................... + +# Document information entities and elements ........................... + +# The document information elements include some elements that are +# currently used only in the document hierarchy module. They are +# defined here so that they will be available for use in customized +# document hierarchies. + +# .................................. + +# Ackno ............................ +local.ackno.attrib = empty +ackno.role.attrib = role.attrib +# doc:Acknowledgements in an Article. +ackno = element ackno { ackno.attlist, docinfo.char.mix* } +# end of ackno.element +ackno.attlist &= common.attrib, ackno.role.attrib, local.ackno.attrib +# end of ackno.attlist + +# end of ackno.module + +# Address .......................... +local.address.attrib = empty +address.role.attrib = role.attrib +# doc:A real-world address, generally a postal address. +address = + element address { + address.attlist, + (text + | personname + | person.ident.mix + | street + | pob + | postcode + | city + | state + | country + | phone + | fax + | email + | otheraddr)* + } +# end of address.element +address.attlist &= + linespecific.attrib, + common.attrib, + address.role.attrib, + local.address.attrib +# end of address.attlist + +# end of address.module +local.street.attrib = empty +street.role.attrib = role.attrib +# doc:A street address in an address. +street = element street { street.attlist, docinfo.char.mix* } +# end of street.element +street.attlist &= common.attrib, street.role.attrib, local.street.attrib +# end of street.attlist + +# end of street.module +local.pob.attrib = empty +pob.role.attrib = role.attrib +# doc:A post office box in an address. +pob = element pob { pob.attlist, docinfo.char.mix* } +# end of pob.element +pob.attlist &= common.attrib, pob.role.attrib, local.pob.attrib +# end of pob.attlist + +# end of pob.module +local.postcode.attrib = empty +postcode.role.attrib = role.attrib +# doc:A postal code in an address. +postcode = element postcode { postcode.attlist, docinfo.char.mix* } +# end of postcode.element +postcode.attlist &= + common.attrib, postcode.role.attrib, local.postcode.attrib +# end of postcode.attlist + +# end of postcode.module +local.city.attrib = empty +city.role.attrib = role.attrib +# doc:The name of a city in an address. +city = element city { city.attlist, docinfo.char.mix* } +# end of city.element +city.attlist &= common.attrib, city.role.attrib, local.city.attrib +# end of city.attlist + +# end of city.module +local.state.attrib = empty +state.role.attrib = role.attrib +# doc:A state or province in an address. +state = element state { state.attlist, docinfo.char.mix* } +# end of state.element +state.attlist &= common.attrib, state.role.attrib, local.state.attrib +# end of state.attlist + +# end of state.module +local.country.attrib = empty +country.role.attrib = role.attrib +# doc:The name of a country. +country = element country { country.attlist, docinfo.char.mix* } +# end of country.element +country.attlist &= + common.attrib, country.role.attrib, local.country.attrib +# end of country.attlist + +# end of country.module +local.phone.attrib = empty +phone.role.attrib = role.attrib +# doc:A telephone number. +phone = element phone { phone.attlist, docinfo.char.mix* } +# end of phone.element +phone.attlist &= common.attrib, phone.role.attrib, local.phone.attrib +# end of phone.attlist + +# end of phone.module +local.fax.attrib = empty +fax.role.attrib = role.attrib +# doc:A fax number. +fax = element fax { fax.attlist, docinfo.char.mix* } +# end of fax.element +fax.attlist &= common.attrib, fax.role.attrib, local.fax.attrib +# end of fax.attlist + +# end of fax.module + +# Email (defined in the Inlines section, below) +local.otheraddr.attrib = empty +otheraddr.role.attrib = role.attrib +# doc:Uncategorized information in address. +otheraddr = element otheraddr { otheraddr.attlist, docinfo.char.mix* } +# end of otheraddr.element +otheraddr.attlist &= + common.attrib, otheraddr.role.attrib, local.otheraddr.attrib +# end of otheraddr.attlist + +# end of otheraddr.module + +# end of address.content.module + +# Affiliation ...................... +local.affiliation.attrib = empty +affiliation.role.attrib = role.attrib +# doc:The institutional affiliation of an individual. +affiliation = + element affiliation { + affiliation.attlist, + shortaffil?, + jobtitle*, + orgname?, + orgdiv*, + address* + } +# end of affiliation.element +affiliation.attlist &= + common.attrib, affiliation.role.attrib, local.affiliation.attrib +# end of affiliation.attlist + +# end of affiliation.module +local.shortaffil.attrib = empty +shortaffil.role.attrib = role.attrib +# doc:A brief description of an affiliation. +shortaffil = + element shortaffil { shortaffil.attlist, docinfo.char.mix* } +# end of shortaffil.element +shortaffil.attlist &= + common.attrib, shortaffil.role.attrib, local.shortaffil.attrib +# end of shortaffil.attlist + +# end of shortaffil.module +local.jobtitle.attrib = empty +jobtitle.role.attrib = role.attrib +# doc:The title of an individual in an organization. +jobtitle = element jobtitle { jobtitle.attlist, docinfo.char.mix* } +# end of jobtitle.element +jobtitle.attlist &= + common.attrib, jobtitle.role.attrib, local.jobtitle.attrib +# end of jobtitle.attlist + +# end of jobtitle.module + +# OrgName (defined elsewhere in this section) +local.orgdiv.attrib = empty +orgdiv.role.attrib = role.attrib +# doc:A division of an organization. +orgdiv = element orgdiv { orgdiv.attlist, docinfo.char.mix* } +# end of orgdiv.element +orgdiv.attlist &= common.attrib, orgdiv.role.attrib, local.orgdiv.attrib +# end of orgdiv.attlist + +# end of orgdiv.module + +# Address (defined elsewhere in this section) + +# end of affiliation.content.module + +# ArtPageNums ...................... +local.artpagenums.attrib = empty +artpagenums.role.attrib = role.attrib +# doc:The page numbers of an article as published. +artpagenums = + element artpagenums { artpagenums.attlist, docinfo.char.mix* } +# end of artpagenums.element +artpagenums.attlist &= + common.attrib, artpagenums.role.attrib, local.artpagenums.attrib +# end of artpagenums.attlist + +# end of artpagenums.module + +# PersonName +local.personname.attrib = empty +personname.role.attrib = role.attrib +# doc:The personal name of an individual. +personname = + element personname { + personname.attlist, + (honorific | firstname | surname | lineage | othername)+ + } +# end of personname.element +personname.attlist &= + common.attrib, personname.role.attrib, local.personname.attrib +# end of personname.attlist + +# end of personname.module + +# Author ........................... +local.author.attrib = empty +author.role.attrib = role.attrib +# doc:The name of an individual author. +author = + element author { + author.attlist, + (personname | person.ident.mix+), + (personblurb | email | address)* + } +# end of author.element +author.attlist &= common.attrib, author.role.attrib, local.author.attrib +# end of author.attlist + +# (see "Personal identity elements" for %person.ident.mix;) + +# end of author.module + +# AuthorGroup ...................... +local.authorgroup.attrib = empty +authorgroup.role.attrib = role.attrib +# doc:Wrapper for author information when a document has multiple authors or collabarators. +authorgroup = + element authorgroup { + authorgroup.attlist, + (author | editor | collab | corpauthor | corpcredit | othercredit)+ + } +# end of authorgroup.element +authorgroup.attlist &= + common.attrib, authorgroup.role.attrib, local.authorgroup.attrib +# end of authorgroup.attlist + +# end of authorgroup.module + +# Author (defined elsewhere in this section) + +# Editor (defined elsewhere in this section) +local.collab.attrib = empty +collab.role.attrib = role.attrib +# doc:Identifies a collaborator. +collab = element collab { collab.attlist, collabname, affiliation* } +# end of collab.element +collab.attlist &= common.attrib, collab.role.attrib, local.collab.attrib +# end of collab.attlist + +# end of collab.module +local.collabname.attrib = empty +collabname.role.attrib = role.attrib +# doc:The name of a collaborator. +collabname = + element collabname { collabname.attlist, docinfo.char.mix* } +# end of collabname.element +collabname.attlist &= + common.attrib, collabname.role.attrib, local.collabname.attrib +# end of collabname.attlist + +# end of collabname.module + +# Affiliation (defined elsewhere in this section) + +# end of collab.content.module + +# CorpAuthor (defined elsewhere in this section) + +# OtherCredit (defined elsewhere in this section) + +# end of authorgroup.content.module + +# AuthorInitials ................... +local.authorinitials.attrib = empty +authorinitials.role.attrib = role.attrib +# doc:The initials or other short identifier for an author. +authorinitials = + element authorinitials { authorinitials.attlist, docinfo.char.mix* } +# end of authorinitials.element +authorinitials.attlist &= + common.attrib, authorinitials.role.attrib, local.authorinitials.attrib +# end of authorinitials.attlist + +# end of authorinitials.module + +# ConfGroup ........................ +local.confgroup.attrib = empty +confgroup.role.attrib = role.attrib +# doc:A wrapper for document meta-information about a conference. +confgroup = + element confgroup { + confgroup.attlist, + (confdates | conftitle | confnum | address | confsponsor)* + } +# end of confgroup.element +confgroup.attlist &= + common.attrib, confgroup.role.attrib, local.confgroup.attrib +# end of confgroup.attlist + +# end of confgroup.module +local.confdates.attrib = empty +confdates.role.attrib = role.attrib +# doc:The dates of a conference for which a document was written. +confdates = element confdates { confdates.attlist, docinfo.char.mix* } +# end of confdates.element +confdates.attlist &= + common.attrib, confdates.role.attrib, local.confdates.attrib +# end of confdates.attlist + +# end of confdates.module +local.conftitle.attrib = empty +conftitle.role.attrib = role.attrib +# doc:The title of a conference for which a document was written. +conftitle = element conftitle { conftitle.attlist, docinfo.char.mix* } +# end of conftitle.element +conftitle.attlist &= + common.attrib, conftitle.role.attrib, local.conftitle.attrib +# end of conftitle.attlist + +# end of conftitle.module +local.confnum.attrib = empty +confnum.role.attrib = role.attrib +# doc:An identifier, frequently numerical, associated with a conference for which a document was written. +confnum = element confnum { confnum.attlist, docinfo.char.mix* } +# end of confnum.element +confnum.attlist &= + common.attrib, confnum.role.attrib, local.confnum.attrib +# end of confnum.attlist + +# end of confnum.module + +# Address (defined elsewhere in this section) +local.confsponsor.attrib = empty +confsponsor.role.attrib = role.attrib +# doc:The sponsor of a conference for which a document was written. +confsponsor = + element confsponsor { confsponsor.attlist, docinfo.char.mix* } +# end of confsponsor.element +confsponsor.attlist &= + common.attrib, confsponsor.role.attrib, local.confsponsor.attrib +# end of confsponsor.attlist + +# end of confsponsor.module + +# end of confgroup.content.module + +# ContractNum ...................... +local.contractnum.attrib = empty +contractnum.role.attrib = role.attrib +# doc:The contract number of a document. +contractnum = + element contractnum { contractnum.attlist, docinfo.char.mix* } +# end of contractnum.element +contractnum.attlist &= + common.attrib, contractnum.role.attrib, local.contractnum.attrib +# end of contractnum.attlist + +# end of contractnum.module + +# ContractSponsor .................. +local.contractsponsor.attrib = empty +contractsponsor.role.attrib = role.attrib +# doc:The sponsor of a contract. +contractsponsor = + element contractsponsor { contractsponsor.attlist, docinfo.char.mix* } +# end of contractsponsor.element +contractsponsor.attlist &= + common.attrib, + contractsponsor.role.attrib, + local.contractsponsor.attrib +# end of contractsponsor.attlist + +# end of contractsponsor.module + +# Copyright ........................ +local.copyright.attrib = empty +copyright.role.attrib = role.attrib +# doc:Copyright information about a document. +copyright = element copyright { copyright.attlist, year+, holder* } +# end of copyright.element +copyright.attlist &= + common.attrib, copyright.role.attrib, local.copyright.attrib +# end of copyright.attlist + +# end of copyright.module +local.year.attrib = empty +year.role.attrib = role.attrib +# doc:The year of publication of a document. +year = element year { year.attlist, docinfo.char.mix* } +# end of year.element +year.attlist &= common.attrib, year.role.attrib, local.year.attrib +# end of year.attlist + +# end of year.module +local.holder.attrib = empty +holder.role.attrib = role.attrib +# doc:The name of the individual or organization that holds a copyright. +holder = element holder { holder.attlist, docinfo.char.mix* } +# end of holder.element +holder.attlist &= common.attrib, holder.role.attrib, local.holder.attrib +# end of holder.attlist + +# end of holder.module + +# end of copyright.content.module + +# CorpAuthor ....................... +local.corpauthor.attrib = empty +corpauthor.role.attrib = role.attrib +# doc:A corporate author, as opposed to an individual. +corpauthor = + element corpauthor { corpauthor.attlist, docinfo.char.mix* } +# end of corpauthor.element +corpauthor.attlist &= + common.attrib, corpauthor.role.attrib, local.corpauthor.attrib +# end of corpauthor.attlist + +# end of corpauthor.module + +# CorpCredit ...................... +local.corpcredit.attrib = empty +corpcredit.role.attrib = role.attrib +# doc:A corporation or organization credited in a document. +corpcredit = + element corpcredit { corpcredit.attlist, docinfo.char.mix* } +# end of corpcredit.element +corpcredit.attlist &= + attribute class { + "graphicdesigner" + | "productioneditor" + | "copyeditor" + | "technicaleditor" + | "translator" + | "other" + }?, + common.attrib, + corpcredit.role.attrib, + local.corpcredit.attrib +# end of corpcredit.attlist + +# end of corpcredit.module + +# CorpName ......................... +local.corpname.attrib = empty +# doc:The name of a corporation. +corpname = element corpname { corpname.attlist, docinfo.char.mix* } +# end of corpname.element +corpname.role.attrib = role.attrib +corpname.attlist &= + common.attrib, corpname.role.attrib, local.corpname.attrib +# end of corpname.attlist + +# end of corpname.module + +# Date ............................. +local.date.attrib = empty +date.role.attrib = role.attrib +# doc:The date of publication or revision of a document. +date = element date { date.attlist, docinfo.char.mix* } +# end of date.element +date.attlist &= common.attrib, date.role.attrib, local.date.attrib +# end of date.attlist + +# end of date.module + +# Edition .......................... +local.edition.attrib = empty +edition.role.attrib = role.attrib +# doc:The name or number of an edition of a document. +edition = element edition { edition.attlist, docinfo.char.mix* } +# end of edition.element +edition.attlist &= + common.attrib, edition.role.attrib, local.edition.attrib +# end of edition.attlist + +# end of edition.module + +# Editor ........................... +local.editor.attrib = empty +editor.role.attrib = role.attrib +# doc:The name of the editor of a document. +editor = + element editor { + editor.attlist, + (personname | person.ident.mix+), + (personblurb | email | address)* + } +# end of editor.element +editor.attlist &= common.attrib, editor.role.attrib, local.editor.attrib +# end of editor.attlist + +# (see "Personal identity elements" for %person.ident.mix;) + +# end of editor.module + +# ISBN ............................. +local.isbn.attrib = empty +isbn.role.attrib = role.attrib +# doc:The International Standard Book Number of a document. +isbn = element isbn { isbn.attlist, docinfo.char.mix* } +# end of isbn.element +isbn.attlist &= common.attrib, isbn.role.attrib, local.isbn.attrib +# end of isbn.attlist + +# end of isbn.module + +# ISSN ............................. +local.issn.attrib = empty +issn.role.attrib = role.attrib +# doc:The International Standard Serial Number of a periodical. +issn = element issn { issn.attlist, docinfo.char.mix* } +# end of issn.element +issn.attlist &= common.attrib, issn.role.attrib, local.issn.attrib +# end of issn.attlist + +# end of issn.module + +# BiblioId ................. +biblio.class.attrib = + attribute class { + "uri" + | "doi" + | "isbn" + | "isrn" + | "issn" + | "libraryofcongress" + | "pubnumber" + | "other" + }?, + attribute otherclass { text }? +local.biblioid.attrib = empty +biblioid.role.attrib = role.attrib +# doc:An identifier for a document. +biblioid = element biblioid { biblioid.attlist, docinfo.char.mix* } +# end of biblioid.element +biblioid.attlist &= + biblio.class.attrib, + common.attrib, + biblioid.role.attrib, + local.biblioid.attrib +# end of biblioid.attlist + +# end of biblioid.module + +# CiteBiblioId ................. +local.citebiblioid.attrib = empty +citebiblioid.role.attrib = role.attrib +# doc:A citation of a bibliographic identifier. +citebiblioid = + element citebiblioid { citebiblioid.attlist, docinfo.char.mix* } +# end of citebiblioid.element +citebiblioid.attlist &= + biblio.class.attrib, + common.attrib, + citebiblioid.role.attrib, + local.citebiblioid.attrib +# end of citebiblioid.attlist + +# end of citebiblioid.module + +# BiblioSource ................. +local.bibliosource.attrib = empty +bibliosource.role.attrib = role.attrib +# doc:The source of a document. +bibliosource = + element bibliosource { bibliosource.attlist, docinfo.char.mix* } +# end of bibliosource.element +bibliosource.attlist &= + biblio.class.attrib, + common.attrib, + bibliosource.role.attrib, + local.bibliosource.attrib +# end of bibliosource.attlist + +# end of bibliosource.module + +# BiblioRelation ................. +local.bibliorelation.attrib = empty +local.bibliorelation.types = notAllowed +bibliorelation.type.attrib = + attribute type { + "isversionof" + | "hasversion" + | "isreplacedby" + | "replaces" + | "isrequiredby" + | "requires" + | "ispartof" + | "haspart" + | "isreferencedby" + | "references" + | "isformatof" + | "hasformat" + | "othertype" + | local.bibliorelation.types + }?, + attribute othertype { text }? +bibliorelation.role.attrib = role.attrib +# doc:The relationship of a document to another. +bibliorelation = + element bibliorelation { bibliorelation.attlist, docinfo.char.mix* } +# end of bibliorelation.element +bibliorelation.attlist &= + biblio.class.attrib, + bibliorelation.type.attrib, + common.attrib, + bibliorelation.role.attrib, + local.bibliorelation.attrib +# end of bibliorelation.attlist + +# end of bibliorelation.module + +# BiblioCoverage ................. +local.bibliocoverage.attrib = empty +bibliocoverage.role.attrib = role.attrib +# doc:The spatial or temporal coverage of a document. +bibliocoverage = + element bibliocoverage { bibliocoverage.attlist, docinfo.char.mix* } +# end of bibliocoverage.element +bibliocoverage.attlist &= + attribute spatial { + "dcmipoint" | "iso3166" | "dcmibox" | "tgn" | "otherspatial" + }?, + attribute otherspatial { text }?, + attribute temporal { "dcmiperiod" | "w3c-dtf" | "othertemporal" }?, + attribute othertemporal { text }?, + common.attrib, + bibliocoverage.role.attrib, + local.bibliocoverage.attrib +# end of bibliocoverage.attlist + +# end of bibliocoverage.module + +# InvPartNumber .................... +local.invpartnumber.attrib = empty +invpartnumber.role.attrib = role.attrib +# doc:An inventory part number. +invpartnumber = + element invpartnumber { invpartnumber.attlist, docinfo.char.mix* } +# end of invpartnumber.element +invpartnumber.attlist &= + common.attrib, invpartnumber.role.attrib, local.invpartnumber.attrib +# end of invpartnumber.attlist + +# end of invpartnumber.module + +# IssueNum ......................... +local.issuenum.attrib = empty +issuenum.role.attrib = role.attrib +# doc:The number of an issue of a journal. +issuenum = element issuenum { issuenum.attlist, docinfo.char.mix* } +# end of issuenum.element +issuenum.attlist &= + common.attrib, issuenum.role.attrib, local.issuenum.attrib +# end of issuenum.attlist + +# end of issuenum.module + +# LegalNotice ...................... +local.legalnotice.attrib = empty +legalnotice.role.attrib = role.attrib +# doc:A statement of legal obligations or requirements. +legalnotice = + element legalnotice { + legalnotice.attlist, blockinfo?, title?, legalnotice.mix+ + } +# end of legalnotice.element +legalnotice.attlist &= + common.attrib, legalnotice.role.attrib, local.legalnotice.attrib +# end of legalnotice.attlist + +# end of legalnotice.module + +# ModeSpec ......................... +local.modespec.attrib = empty +modespec.role.attrib = role.attrib +# doc:Application-specific information necessary for the completion of an OLink. +modespec = element modespec { modespec.attlist, docinfo.char.mix* } +# end of modespec.element + +# Application: Type of action required for completion +# of the links to which the ModeSpec is relevant (e.g., +# retrieval query) +modespec.attlist &= + attribute application { notation.class }?, + common.attrib, + modespec.role.attrib, + local.modespec.attrib +# end of modespec.attlist + +# end of modespec.module + +# OrgName .......................... +local.orgname.attrib = empty +orgname.role.attrib = role.attrib +# doc:The name of an organization other than a corporation. +orgname = element orgname { orgname.attlist, docinfo.char.mix* } +# end of orgname.element +orgname.attlist &= + common.attrib, + attribute class { + "corporation" | "nonprofit" | "consortium" | "informal" | "other" + }?, + attribute otherclass { text }?, + orgname.role.attrib, + local.orgname.attrib +# end of orgname.attlist + +# end of orgname.module + +# OtherCredit ...................... +local.othercredit.attrib = empty +othercredit.role.attrib = role.attrib +# doc:A person or entity, other than an author or editor, credited in a document. +othercredit = + element othercredit { + othercredit.attlist, + (personname | person.ident.mix+), + (personblurb | email | address)* + } +# end of othercredit.element +othercredit.attlist &= + attribute class { + "graphicdesigner" + | "productioneditor" + | "copyeditor" + | "technicaleditor" + | "translator" + | "other" + }?, + common.attrib, + othercredit.role.attrib, + local.othercredit.attrib +# end of othercredit.attlist + +# (see "Personal identity elements" for %person.ident.mix;) + +# end of othercredit.module + +# PageNums ......................... +local.pagenums.attrib = empty +pagenums.role.attrib = role.attrib +# doc:The numbers of the pages in a book, for use in a bibliographic entry. +pagenums = element pagenums { pagenums.attlist, docinfo.char.mix* } +# end of pagenums.element +pagenums.attlist &= + common.attrib, pagenums.role.attrib, local.pagenums.attrib +# end of pagenums.attlist + +# end of pagenums.module + +# Personal identity elements ....... + +# These elements are used only within Author, Editor, and +# OtherCredit. +local.contrib.attrib = empty +contrib.role.attrib = role.attrib +# doc:A summary of the contributions made to a document by a credited source. +contrib = element contrib { contrib.attlist, docinfo.char.mix* } +# end of contrib.element +contrib.attlist &= + common.attrib, contrib.role.attrib, local.contrib.attrib +# end of contrib.attlist + +# end of contrib.module +local.firstname.attrib = empty +firstname.role.attrib = role.attrib +# doc:The first name of a person. +firstname = element firstname { firstname.attlist, docinfo.char.mix* } +# end of firstname.element +firstname.attlist &= + common.attrib, firstname.role.attrib, local.firstname.attrib +# end of firstname.attlist + +# end of firstname.module +local.honorific.attrib = empty +honorific.role.attrib = role.attrib +# doc:The title of a person. +honorific = element honorific { honorific.attlist, docinfo.char.mix* } +# end of honorific.element +honorific.attlist &= + common.attrib, honorific.role.attrib, local.honorific.attrib +# end of honorific.attlist + +# end of honorific.module +local.lineage.attrib = empty +lineage.role.attrib = role.attrib +# doc:The portion of a person's name indicating a relationship to ancestors. +lineage = element lineage { lineage.attlist, docinfo.char.mix* } +# end of lineage.element +lineage.attlist &= + common.attrib, lineage.role.attrib, local.lineage.attrib +# end of lineage.attlist + +# end of lineage.module +local.othername.attrib = empty +othername.role.attrib = role.attrib +# doc:A component of a persons name that is not a first name, surname, or lineage. +othername = element othername { othername.attlist, docinfo.char.mix* } +# end of othername.element +othername.attlist &= + common.attrib, othername.role.attrib, local.othername.attrib +# end of othername.attlist + +# end of othername.module +local.surname.attrib = empty +surname.role.attrib = role.attrib +# doc:A family name; in western cultures the last name. +surname = element surname { surname.attlist, docinfo.char.mix* } +# end of surname.element +surname.attlist &= + common.attrib, surname.role.attrib, local.surname.attrib +# end of surname.attlist + +# end of surname.module + +# end of person.ident.module + +# PrintHistory ..................... +local.printhistory.attrib = empty +printhistory.role.attrib = role.attrib +# doc:The printing history of a document. +printhistory = + element printhistory { printhistory.attlist, para.class+ } +# end of printhistory.element +printhistory.attlist &= + common.attrib, printhistory.role.attrib, local.printhistory.attrib +# end of printhistory.attlist + +# end of printhistory.module + +# ProductName ...................... +local.productname.attrib = empty +productname.role.attrib = role.attrib +# doc:The formal name of a product. +productname = + element productname { productname.attlist, para.char.mix* } +# end of productname.element + +# Class: More precisely identifies the item the element names +productname.attlist &= + [ a:defaultValue = "trade" ] + attribute class { "service" | "trade" | "registered" | "copyright" }?, + common.attrib, + productname.role.attrib, + local.productname.attrib +# end of productname.attlist + +# end of productname.module + +# ProductNumber .................... +local.productnumber.attrib = empty +productnumber.role.attrib = role.attrib +# doc:A number assigned to a product. +productnumber = + element productnumber { productnumber.attlist, docinfo.char.mix* } +# end of productnumber.element +productnumber.attlist &= + common.attrib, productnumber.role.attrib, local.productnumber.attrib +# end of productnumber.attlist + +# end of productnumber.module + +# PubDate .......................... +local.pubdate.attrib = empty +pubdate.role.attrib = role.attrib +# doc:The date of publication of a document. +pubdate = element pubdate { pubdate.attlist, docinfo.char.mix* } +# end of pubdate.element +pubdate.attlist &= + common.attrib, pubdate.role.attrib, local.pubdate.attrib +# end of pubdate.attlist + +# end of pubdate.module + +# Publisher ........................ +local.publisher.attrib = empty +publisher.role.attrib = role.attrib +# doc:The publisher of a document. +publisher = + element publisher { publisher.attlist, publishername, address* } +# end of publisher.element +publisher.attlist &= + common.attrib, publisher.role.attrib, local.publisher.attrib +# end of publisher.attlist + +# end of publisher.module +local.publishername.attrib = empty +publishername.role.attrib = role.attrib +# doc:The name of the publisher of a document. +publishername = + element publishername { publishername.attlist, docinfo.char.mix* } +# end of publishername.element +publishername.attlist &= + common.attrib, publishername.role.attrib, local.publishername.attrib +# end of publishername.attlist + +# end of publishername.module + +# Address (defined elsewhere in this section) + +# end of publisher.content.module + +# PubsNumber ....................... +local.pubsnumber.attrib = empty +pubsnumber.role.attrib = role.attrib +# doc:A number assigned to a publication other than an ISBN or ISSN or inventory part number. +pubsnumber = + element pubsnumber { pubsnumber.attlist, docinfo.char.mix* } +# end of pubsnumber.element +pubsnumber.attlist &= + common.attrib, pubsnumber.role.attrib, local.pubsnumber.attrib +# end of pubsnumber.attlist + +# end of pubsnumber.module + +# ReleaseInfo ...................... +local.releaseinfo.attrib = empty +releaseinfo.role.attrib = role.attrib +# doc:Information about a particular release of a document. +releaseinfo = + element releaseinfo { releaseinfo.attlist, docinfo.char.mix* } +# end of releaseinfo.element +releaseinfo.attlist &= + common.attrib, releaseinfo.role.attrib, local.releaseinfo.attrib +# end of releaseinfo.attlist + +# end of releaseinfo.module + +# RevHistory ....................... +local.revhistory.attrib = empty +revhistory.role.attrib = role.attrib +# doc:A history of the revisions to a document. +revhistory = element revhistory { revhistory.attlist, revision+ } +# end of revhistory.element +revhistory.attlist &= + common.attrib, revhistory.role.attrib, local.revhistory.attrib +# end of revhistory.attlist + +# end of revhistory.module +local.revision.attrib = empty +revision.role.attrib = role.attrib +# doc:An entry describing a single revision in the history of the revisions to a document. +revision = + element revision { + revision.attlist, + revnumber?, + date, + (author | authorinitials)*, + (revremark | revdescription)? + } +# end of revision.element +revision.attlist &= + common.attrib, revision.role.attrib, local.revision.attrib +# end of revision.attlist + +# end of revision.module +local.revnumber.attrib = empty +revnumber.role.attrib = role.attrib +# doc:A document revision number. +revnumber = element revnumber { revnumber.attlist, docinfo.char.mix* } +# end of revnumber.element +revnumber.attlist &= + common.attrib, revnumber.role.attrib, local.revnumber.attrib +# end of revnumber.attlist + +# end of revnumber.module + +# Date (defined elsewhere in this section) + +# AuthorInitials (defined elsewhere in this section) +local.revremark.attrib = empty +revremark.role.attrib = role.attrib +# doc:A description of a revision to a document. +revremark = element revremark { revremark.attlist, docinfo.char.mix* } +# end of revremark.element +revremark.attlist &= + common.attrib, revremark.role.attrib, local.revremark.attrib +# end of revremark.attlist + +# end of revremark.module +local.revdescription.attrib = empty +revdescription.role.attrib = role.attrib +# doc:A extended description of a revision to a document. +revdescription = + element revdescription { revdescription.attlist, revdescription.mix+ } +# end of revdescription.element +revdescription.attlist &= + common.attrib, revdescription.role.attrib, local.revdescription.attrib +# end of revdescription.attlist + +# end of revdescription.module + +# end of revhistory.content.module + +# SeriesVolNums .................... +local.seriesvolnums.attrib = empty +seriesvolnums.role.attrib = role.attrib +# doc:Numbers of the volumes in a series of books. +seriesvolnums = + element seriesvolnums { seriesvolnums.attlist, docinfo.char.mix* } +# end of seriesvolnums.element +seriesvolnums.attlist &= + common.attrib, seriesvolnums.role.attrib, local.seriesvolnums.attrib +# end of seriesvolnums.attlist + +# end of seriesvolnums.module + +# VolumeNum ........................ +local.volumenum.attrib = empty +volumenum.role.attrib = role.attrib +# doc:The volume number of a document in a set (as of books in a set or articles in a journal). +volumenum = element volumenum { volumenum.attlist, docinfo.char.mix* } +# end of volumenum.element +volumenum.attlist &= + common.attrib, volumenum.role.attrib, local.volumenum.attrib +# end of volumenum.attlist + +# end of volumenum.module + +# .................................. + +# end of docinfo.content.module + +# ...................................................................... + +# Inline, link, and ubiquitous elements ................................ + +# Technical and computer terms ......................................... +local.accel.attrib = empty +accel.role.attrib = role.attrib +# doc:A graphical user interface (GUI) keyboard shortcut. +accel = element accel { accel.attlist, smallcptr.char.mix* } +# end of accel.element +accel.attlist &= common.attrib, accel.role.attrib, local.accel.attrib +# end of accel.attlist + +# end of accel.module +local.action.attrib = empty +action.role.attrib = role.attrib +# doc:A response to a user event. +action = element action { action.attlist, cptr.char.mix* } +# end of action.element +action.attlist &= + moreinfo.attrib, + common.attrib, + action.role.attrib, + local.action.attrib +# end of action.attlist + +# end of action.module +local.application.attrib = empty +application.role.attrib = role.attrib +# doc:The name of a software program. +application = + element application { application.attlist, para.char.mix* } +# end of application.element +application.attlist &= + attribute class { "hardware" | "software" }?, + moreinfo.attrib, + common.attrib, + application.role.attrib, + local.application.attrib +# end of application.attlist + +# end of application.module +local.classname.attrib = empty +classname.role.attrib = role.attrib +# doc:The name of a class, in the object-oriented programming sense. +classname = element classname { classname.attlist, smallcptr.char.mix* } +# end of classname.element +classname.attlist &= + common.attrib, classname.role.attrib, local.classname.attrib +# end of classname.attlist + +# end of classname.module +local.package.attrib = empty +package.role.attrib = role.attrib +# doc:A package. +package = element package { package.attlist, smallcptr.char.mix* } +# end of package.element +package.attlist &= + common.attrib, package.role.attrib, local.package.attrib +# end of package.attlist + +# end of package.module +local.co.attrib = empty +# CO is a callout area of the LineColumn unit type (a single character +# position); the position is directly indicated by the location of CO. +co.role.attrib = role.attrib +# doc:The location of a callout embedded in text. +co = element co { co.attlist, empty } +# end of co.element + +# bug number/symbol override or initialization + +# to any related information +co.attlist &= + label.attrib, + linkends.attrib, + idreq.common.attrib, + co.role.attrib, + local.co.attrib +# end of co.attlist + +# end of co.module +local.coref.attrib = empty +# COREF is a reference to a CO +coref.role.attrib = role.attrib +# doc:A cross reference to a co. +coref = element coref { coref.attlist, empty } +# end of coref.element + +# bug number/symbol override or initialization + +# to any related information +coref.attlist &= + label.attrib, + linkendreq.attrib, + common.attrib, + coref.role.attrib, + local.coref.attrib +# end of coref.attlist + +# end of coref.module +local.command.attrib = empty +command.role.attrib = role.attrib +# doc:The name of an executable program or other software command. +command = element command { command.attlist, cptr.char.mix* } +# end of command.element +command.attlist &= + moreinfo.attrib, + common.attrib, + command.role.attrib, + local.command.attrib +# end of command.attlist + +# end of command.module +local.computeroutput.attrib = empty +computeroutput.role.attrib = role.attrib +# doc:Data, generally text, displayed or presented by a computer. +computeroutput = + element computeroutput { + computeroutput.attlist, (cptr.char.mix | co)* + } +# end of computeroutput.element +computeroutput.attlist &= + moreinfo.attrib, + common.attrib, + computeroutput.role.attrib, + local.computeroutput.attrib +# end of computeroutput.attlist + +# end of computeroutput.module +local.database.attrib = empty +database.role.attrib = role.attrib +# doc:The name of a database, or part of a database. +database = element database { database.attlist, cptr.char.mix* } +# end of database.element + +# Class: Type of database the element names; no default +database.attlist &= + attribute class { + "name" + | "table" + | "field" + | "key1" + | "key2" + | "record" + | "index" + | "view" + | "primarykey" + | "secondarykey" + | "foreignkey" + | "altkey" + | "procedure" + | "datatype" + | "constraint" + | "rule" + | "user" + | "group" + }?, + moreinfo.attrib, + common.attrib, + database.role.attrib, + local.database.attrib +# end of database.attlist + +# end of database.module +local.email.attrib = empty +email.role.attrib = role.attrib +# doc:An email address. +email = element email { email.attlist, docinfo.char.mix* } +# end of email.element +email.attlist &= common.attrib, email.role.attrib, local.email.attrib +# end of email.attlist + +# end of email.module +local.envar.attrib = empty +envar.role.attrib = role.attrib +# doc:A software environment variable. +envar = element envar { envar.attlist, smallcptr.char.mix* } +# end of envar.element +envar.attlist &= common.attrib, envar.role.attrib, local.envar.attrib +# end of envar.attlist + +# end of envar.module +local.errorcode.attrib = empty +errorcode.role.attrib = role.attrib +# doc:An error code. +errorcode = element errorcode { errorcode.attlist, smallcptr.char.mix* } +# end of errorcode.element +errorcode.attlist &= + moreinfo.attrib, + common.attrib, + errorcode.role.attrib, + local.errorcode.attrib +# end of errorcode.attlist + +# end of errorcode.module +local.errorname.attrib = empty +errorname.role.attrib = role.attrib +# doc:An error name. +errorname = element errorname { errorname.attlist, smallcptr.char.mix* } +# end of errorname.element +errorname.attlist &= + common.attrib, errorname.role.attrib, local.errorname.attrib +# end of errorname.attlist + +# end of errorname.module +local.errortext.attrib = empty +errortext.role.attrib = role.attrib +# doc:An error message.. +errortext = element errortext { errortext.attlist, smallcptr.char.mix* } +# end of errortext.element +errortext.attlist &= + common.attrib, errortext.role.attrib, local.errortext.attrib +# end of errortext.attlist + +# end of errortext.module +local.errortype.attrib = empty +errortype.role.attrib = role.attrib +# doc:The classification of an error message. +errortype = element errortype { errortype.attlist, smallcptr.char.mix* } +# end of errortype.element +errortype.attlist &= + common.attrib, errortype.role.attrib, local.errortype.attrib +# end of errortype.attlist + +# end of errortype.module +local.filename.attrib = empty +filename.role.attrib = role.attrib +# doc:The name of a file. +filename = element filename { filename.attlist, cptr.char.mix* } +# end of filename.element + +# Class: Type of filename the element names; no default + +# Path: Search path (possibly system-specific) in which +# file can be found +filename.attlist &= + attribute class { + "headerfile" + | "partition" + | "devicefile" + | "libraryfile" + | "directory" + | "extension" + | "symlink" + }?, + attribute path { text }?, + moreinfo.attrib, + common.attrib, + filename.role.attrib, + local.filename.attrib +# end of filename.attlist + +# end of filename.module +local.function.attrib = empty +function.role.attrib = role.attrib +# doc:The name of a function or subroutine, as in a programming language. +function = element function { function.attlist, cptr.char.mix* } +# end of function.element +function.attlist &= + moreinfo.attrib, + common.attrib, + function.role.attrib, + local.function.attrib +# end of function.attlist + +# end of function.module +local.guibutton.attrib = empty +guibutton.role.attrib = role.attrib +# doc:The text on a button in a GUI. +guibutton = + element guibutton { + guibutton.attlist, + (smallcptr.char.mix | accel | superscript | subscript)* + } +# end of guibutton.element +guibutton.attlist &= + moreinfo.attrib, + common.attrib, + guibutton.role.attrib, + local.guibutton.attrib +# end of guibutton.attlist + +# end of guibutton.module +local.guiicon.attrib = empty +guiicon.role.attrib = role.attrib +# doc:Graphic and/or text appearing as a icon in a GUI. +guiicon = + element guiicon { + guiicon.attlist, + (smallcptr.char.mix | accel | superscript | subscript)* + } +# end of guiicon.element +guiicon.attlist &= + moreinfo.attrib, + common.attrib, + guiicon.role.attrib, + local.guiicon.attrib +# end of guiicon.attlist + +# end of guiicon.module +local.guilabel.attrib = empty +guilabel.role.attrib = role.attrib +# doc:The text of a label in a GUI. +guilabel = + element guilabel { + guilabel.attlist, + (smallcptr.char.mix | accel | superscript | subscript)* + } +# end of guilabel.element +guilabel.attlist &= + moreinfo.attrib, + common.attrib, + guilabel.role.attrib, + local.guilabel.attrib +# end of guilabel.attlist + +# end of guilabel.module +local.guimenu.attrib = empty +guimenu.role.attrib = role.attrib +# doc:The name of a menu in a GUI. +guimenu = + element guimenu { + guimenu.attlist, + (smallcptr.char.mix | accel | superscript | subscript)* + } +# end of guimenu.element +guimenu.attlist &= + moreinfo.attrib, + common.attrib, + guimenu.role.attrib, + local.guimenu.attrib +# end of guimenu.attlist + +# end of guimenu.module +local.guimenuitem.attrib = empty +guimenuitem.role.attrib = role.attrib +# doc:The name of a terminal menu item in a GUI. +guimenuitem = + element guimenuitem { + guimenuitem.attlist, + (smallcptr.char.mix | accel | superscript | subscript)* + } +# end of guimenuitem.element +guimenuitem.attlist &= + moreinfo.attrib, + common.attrib, + guimenuitem.role.attrib, + local.guimenuitem.attrib +# end of guimenuitem.attlist + +# end of guimenuitem.module +local.guisubmenu.attrib = empty +guisubmenu.role.attrib = role.attrib +# doc:The name of a submenu in a GUI. +guisubmenu = + element guisubmenu { + guisubmenu.attlist, + (smallcptr.char.mix | accel | superscript | subscript)* + } +# end of guisubmenu.element +guisubmenu.attlist &= + moreinfo.attrib, + common.attrib, + guisubmenu.role.attrib, + local.guisubmenu.attrib +# end of guisubmenu.attlist + +# end of guisubmenu.module +local.hardware.attrib = empty +hardware.role.attrib = role.attrib +# doc:A physical part of a computer system. +hardware = element hardware { hardware.attlist, cptr.char.mix* } +# end of hardware.element +hardware.attlist &= + moreinfo.attrib, + common.attrib, + hardware.role.attrib, + local.hardware.attrib +# end of hardware.attlist + +# end of hardware.module +local.interface.attrib = empty +interface.role.attrib = role.attrib +# doc:An element of a GUI. +interface = + element interface { interface.attlist, (smallcptr.char.mix | accel)* } +# end of interface.element + +# Class: Type of the Interface item; no default +interface.attlist &= + moreinfo.attrib, + common.attrib, + interface.role.attrib, + local.interface.attrib +# end of interface.attlist + +# end of interface.module +local.keycap.attrib = empty +keycap.role.attrib = role.attrib +# doc:The text printed on a key on a keyboard. +keycap = element keycap { keycap.attlist, cptr.char.mix* } +# end of keycap.element +keycap.attlist &= + attribute function { + "alt" + | "control" + | "shift" + | "meta" + | "escape" + | "enter" + | "tab" + | "backspace" + | "command" + | "option" + | "space" + | "delete" + | "insert" + | "up" + | "down" + | "left" + | "right" + | "home" + | "end" + | "pageup" + | "pagedown" + | "other" + }?, + attribute otherfunction { text }?, + moreinfo.attrib, + common.attrib, + keycap.role.attrib, + local.keycap.attrib +# end of keycap.attlist + +# end of keycap.module +local.keycode.attrib = empty +keycode.role.attrib = role.attrib +# doc:The internal, frequently numeric, identifier for a key on a keyboard. +keycode = element keycode { keycode.attlist, smallcptr.char.mix* } +# end of keycode.element +keycode.attlist &= + common.attrib, keycode.role.attrib, local.keycode.attrib +# end of keycode.attlist + +# end of keycode.module +local.keycombo.attrib = empty +keycombo.role.attrib = role.attrib +# doc:A combination of input actions. +keycombo = + element keycombo { + keycombo.attlist, (keycap | keycombo | keysym | mousebutton)+ + } +# end of keycombo.element +keycombo.attlist &= + keyaction.attrib, + moreinfo.attrib, + common.attrib, + keycombo.role.attrib, + local.keycombo.attrib +# end of keycombo.attlist + +# end of keycombo.module +local.keysym.attrib = empty +keysysm.role.attrib = role.attrib +# doc:The symbolic name of a key on a keyboard. +keysym = element keysym { keysym.attlist, smallcptr.char.mix* } +# end of keysym.element +keysym.attlist &= + common.attrib, keysysm.role.attrib, local.keysym.attrib +# end of keysym.attlist + +# end of keysym.module +local.lineannotation.attrib = empty +lineannotation.role.attrib = role.attrib +# doc:A comment on a line in a verbatim listing. +lineannotation = + element lineannotation { lineannotation.attlist, para.char.mix* } +# end of lineannotation.element +lineannotation.attlist &= + common.attrib, lineannotation.role.attrib, local.lineannotation.attrib +# end of lineannotation.attlist + +# end of lineannotation.module +local.literal.attrib = empty +literal.role.attrib = role.attrib +# doc:Inline text that is some literal value. +literal = element literal { literal.attlist, cptr.char.mix* } +# end of literal.element +literal.attlist &= + moreinfo.attrib, + common.attrib, + literal.role.attrib, + local.literal.attrib +# end of literal.attlist + +# end of literal.module +local.code.attrib = empty +code.role.attrib = role.attrib +# doc:An inline code fragment. +code = element code { code.attlist, cptr.char.mix* } +# end of code.element +code.attlist &= + attribute language { text }?, + common.attrib, + code.role.attrib, + local.code.attrib +# end of code.attlist + +# end of code.module +local.constant.attrib = empty +constant.role.attrib = role.attrib +# doc:A programming or system constant. +constant = element constant { constant.attlist, smallcptr.char.mix* } +# end of constant.element +constant.attlist &= + attribute class { "limit" }?, + common.attrib, + constant.role.attrib, + local.constant.attrib +# end of constant.attlist + +# end of constant.module +local.varname.attrib = empty +varname.role.attrib = role.attrib +# doc:The name of a variable. +varname = element varname { varname.attlist, smallcptr.char.mix* } +# end of varname.element +varname.attlist &= + common.attrib, varname.role.attrib, local.varname.attrib +# end of varname.attlist + +# end of varname.module +local.markup.attrib = empty +markup.role.attrib = role.attrib +# doc:A string of formatting markup in text that is to be represented literally. +markup = element markup { markup.attlist, smallcptr.char.mix* } +# end of markup.element +markup.attlist &= common.attrib, markup.role.attrib, local.markup.attrib +# end of markup.attlist + +# end of markup.module +local.medialabel.attrib = empty +medialabel.role.attrib = role.attrib +# doc:A name that identifies the physical medium on which some information resides. +medialabel = + element medialabel { medialabel.attlist, smallcptr.char.mix* } +# end of medialabel.element + +# Class: Type of medium named by the element; no default +medialabel.attlist &= + attribute class { "cartridge" | "cdrom" | "disk" | "tape" }?, + common.attrib, + medialabel.role.attrib, + local.medialabel.attrib +# end of medialabel.attlist + +# end of medialabel.module +local.menuchoice.attrib = empty +menuchoice.role.attrib = role.attrib +# doc:A selection or series of selections from a menu. +menuchoice = + element menuchoice { + menuchoice.attlist, + shortcut?, + (guibutton + | guiicon + | guilabel + | guimenu + | guimenuitem + | guisubmenu + | interface)+ + } +# end of menuchoice.element +menuchoice.attlist &= + moreinfo.attrib, + common.attrib, + menuchoice.role.attrib, + local.menuchoice.attrib +# end of menuchoice.attlist + +# end of menuchoice.module + +# See also KeyCombo +local.shortcut.attrib = empty +shortcut.role.attrib = role.attrib +# doc:A key combination for an action that is also accessible through a menu. +shortcut = + element shortcut { + shortcut.attlist, (keycap | keycombo | keysym | mousebutton)+ + } +# end of shortcut.element +shortcut.attlist &= + keyaction.attrib, + moreinfo.attrib, + common.attrib, + shortcut.role.attrib, + local.shortcut.attrib +# end of shortcut.attlist + +# end of shortcut.module + +# end of menuchoice.content.module +local.mousebutton.attrib = empty +mousebutton.role.attrib = role.attrib +# doc:The conventional name of a mouse button. +mousebutton = + element mousebutton { mousebutton.attlist, smallcptr.char.mix* } +# end of mousebutton.element +mousebutton.attlist &= + moreinfo.attrib, + common.attrib, + mousebutton.role.attrib, + local.mousebutton.attrib +# end of mousebutton.attlist + +# end of mousebutton.module +local.msgtext.attrib = empty +msgtext.role.attrib = role.attrib +# doc:The actual text of a message component in a message set. +msgtext = element msgtext { msgtext.attlist, component.mix+ } +# end of msgtext.element +msgtext.attlist &= + common.attrib, msgtext.role.attrib, local.msgtext.attrib +# end of msgtext.attlist + +# end of msgtext.module +local.option.attrib = empty +option.role.attrib = role.attrib +# doc:An option for a software command. +option = element option { option.attlist, cptr.char.mix* } +# end of option.element +option.attlist &= common.attrib, option.role.attrib, local.option.attrib +# end of option.attlist + +# end of option.module +local.optional.attrib = empty +optional.role.attrib = role.attrib +# doc:Optional information. +optional = element optional { optional.attlist, cptr.char.mix* } +# end of optional.element +optional.attlist &= + common.attrib, optional.role.attrib, local.optional.attrib +# end of optional.attlist + +# end of optional.module +local.parameter.attrib = empty +parameter.role.attrib = role.attrib +# doc:A value or a symbolic reference to a value. +parameter = element parameter { parameter.attlist, cptr.char.mix* } +# end of parameter.element + +# Class: Type of the Parameter; no default +parameter.attlist &= + attribute class { "command" | "function" | "option" }?, + moreinfo.attrib, + common.attrib, + parameter.role.attrib, + local.parameter.attrib +# end of parameter.attlist + +# end of parameter.module +local.prompt.attrib = empty +prompt.role.attrib = role.attrib +# doc:A character or string indicating the start of an input field in a computer display. +prompt = element prompt { prompt.attlist, (smallcptr.char.mix | co)* } +# end of prompt.element +prompt.attlist &= + moreinfo.attrib, + common.attrib, + prompt.role.attrib, + local.prompt.attrib +# end of prompt.attlist + +# end of prompt.module +local.property.attrib = empty +property.role.attrib = role.attrib +# doc:A unit of data associated with some part of a computer system. +property = element property { property.attlist, cptr.char.mix* } +# end of property.element +property.attlist &= + moreinfo.attrib, + common.attrib, + property.role.attrib, + local.property.attrib +# end of property.attlist + +# end of property.module +local.replaceable.attrib = empty +replaceable.role.attrib = role.attrib +# doc:Content that may or must be replaced by the user. +replaceable = + element replaceable { + replaceable.attlist, + (text + | link.char.class + | optional + | base.char.class + | other.char.class + | inlinegraphic + | inlinemediaobject + | co)* + } +# end of replaceable.element + +# Class: Type of information the element represents; no +# default +replaceable.attlist &= + attribute class { "command" | "function" | "option" | "parameter" }?, + common.attrib, + replaceable.role.attrib, + local.replaceable.attrib +# end of replaceable.attlist + +# end of replaceable.module +local.returnvalue.attrib = empty +returnvalue.role.attrib = role.attrib +# doc:The value returned by a function. +returnvalue = + element returnvalue { returnvalue.attlist, smallcptr.char.mix* } +# end of returnvalue.element +returnvalue.attlist &= + common.attrib, returnvalue.role.attrib, local.returnvalue.attrib +# end of returnvalue.attlist + +# end of returnvalue.module +local.sgmltag.attrib = empty +sgmltag.role.attrib = role.attrib +# doc:A component of SGML markup. +sgmltag = element sgmltag { sgmltag.attlist, smallcptr.char.mix* } +# end of sgmltag.element + +# Class: Type of SGML construct the element names; no default +sgmltag.attlist &= + attribute class { + "attribute" + | "attvalue" + | "element" + | "endtag" + | "emptytag" + | "genentity" + | "numcharref" + | "paramentity" + | "pi" + | "xmlpi" + | "starttag" + | "sgmlcomment" + | "prefix" + | "namespace" + | "localname" + }?, + attribute namespace { text }?, + common.attrib, + sgmltag.role.attrib, + local.sgmltag.attrib +# end of sgmltag.attlist + +# end of sgmltag.module +local.structfield.attrib = empty +structfield.role.attrib = role.attrib +# doc:A field in a structure (in the programming language sense). +structfield = + element structfield { structfield.attlist, smallcptr.char.mix* } +# end of structfield.element +structfield.attlist &= + common.attrib, structfield.role.attrib, local.structfield.attrib +# end of structfield.attlist + +# end of structfield.module +local.structname.attrib = empty +structname.role.attrib = role.attrib +# doc:The name of a structure (in the programming language sense). +structname = + element structname { structname.attlist, smallcptr.char.mix* } +# end of structname.element +structname.attlist &= + common.attrib, structname.role.attrib, local.structname.attrib +# end of structname.attlist + +# end of structname.module +local.symbol.attrib = empty +symbol.role.attrib = role.attrib +# doc:A name that is replaced by a value before processing. +symbol = element symbol { symbol.attlist, smallcptr.char.mix* } +# end of symbol.element + +# Class: Type of symbol; no default +symbol.attlist &= + attribute class { "limit" }?, + common.attrib, + symbol.role.attrib, + local.symbol.attrib +# end of symbol.attlist + +# end of symbol.module +local.systemitem.attrib = empty +systemitem.role.attrib = role.attrib +# doc:A system-related item or term. +systemitem = + element systemitem { + systemitem.attlist, (cptr.char.mix | acronym | co)* + } +# end of systemitem.element + +# Class: Type of system item the element names; no default +systemitem.attlist &= + attribute class { + "constant" + | "daemon" + | "domainname" + | "etheraddress" + | "event" + | "eventhandler" + | "filesystem" + | "fqdomainname" + | "groupname" + | "ipaddress" + | "library" + | "macro" + | "netmask" + | "newsgroup" + | "osname" + | "protocol" + | "resource" + | "systemname" + | "username" + | "process" + | "server" + | "service" + }?, + moreinfo.attrib, + common.attrib, + systemitem.role.attrib, + local.systemitem.attrib +# end of systemitem.attlist + +# end of systemitem.module +local.uri.attrib = empty +uri.role.attrib = role.attrib +# doc:A Uniform Resource Identifier. +uri = element uri { uri.attlist, smallcptr.char.mix* } +# end of uri.element + +# Type: Type of URI; no default +uri.attlist &= + attribute type { text }?, + common.attrib, + uri.role.attrib, + local.uri.attrib +# end of uri.attlist + +# end of uri.module +local.token.attrib = empty +token.role.attrib = role.attrib +# doc:A unit of information. +\token = element token { token.attlist, smallcptr.char.mix* } +# end of token.element +token.attlist &= common.attrib, token.role.attrib, local.token.attrib +# end of token.attlist + +# end of token.module +local.type.attrib = empty +type.role.attrib = role.attrib +# doc:The classification of a value. +type = element type { type.attlist, smallcptr.char.mix* } +# end of type.element +type.attlist &= common.attrib, type.role.attrib, local.type.attrib +# end of type.attlist + +# end of type.module +local.userinput.attrib = empty +userinput.role.attrib = role.attrib +# doc:Data entered by the user. +userinput = + element userinput { userinput.attlist, (cptr.char.mix | co)* } +# end of userinput.element +userinput.attlist &= + moreinfo.attrib, + common.attrib, + userinput.role.attrib, + local.userinput.attrib +# end of userinput.attlist + +# end of userinput.module +local.termdef.attrib = empty +termdef.role.attrib = role.attrib +# doc:An inline definition of a term. +termdef = element termdef { termdef.attlist, para.char.mix* } +# end of termdef.element +termdef.attlist &= + common.attrib, termdef.role.attrib, local.termdef.attrib +# end of termdef.attlist + +# end of termdef.module + +# General words and phrases ............................................ +local.abbrev.attrib = empty +abbrev.role.attrib = role.attrib +# doc:An abbreviation, especially one followed by a period. +abbrev = element abbrev { abbrev.attlist, word.char.mix* } +# end of abbrev.element +abbrev.attlist &= common.attrib, abbrev.role.attrib, local.abbrev.attrib +# end of abbrev.attlist + +# end of abbrev.module +local.acronym.attrib = empty +acronym.role.attrib = role.attrib +# doc:An often pronounceable word made from the initial (or selected) letters of a name or phrase. +acronym = element acronym { acronym.attlist, word.char.mix* } +# end of acronym.element +acronym.attlist &= + common.attrib, acronym.role.attrib, local.acronym.attrib +# end of acronym.attlist + +# end of acronym.module +local.citation.attrib = empty +citation.role.attrib = role.attrib +# doc:An inline bibliographic reference to another published work. +citation = element citation { citation.attlist, para.char.mix* } +# end of citation.element +citation.attlist &= + common.attrib, citation.role.attrib, local.citation.attrib +# end of citation.attlist + +# end of citation.module +local.citerefentry.attrib = empty +citerefentry.role.attrib = role.attrib +# doc:A citation to a reference page. +citerefentry = + element citerefentry { + citerefentry.attlist, refentrytitle, manvolnum? + } +# end of citerefentry.element +citerefentry.attlist &= + common.attrib, citerefentry.role.attrib, local.citerefentry.attrib +# end of citerefentry.attlist + +# end of citerefentry.module +local.refentrytitle.attrib = empty +refentrytitle.role.attrib = role.attrib +# doc:The title of a reference page. +refentrytitle = + element refentrytitle { refentrytitle.attlist, para.char.mix* } +# end of refentrytitle.element +refentrytitle.attlist &= + common.attrib, refentrytitle.role.attrib, local.refentrytitle.attrib +# end of refentrytitle.attlist + +# end of refentrytitle.module +local.manvolnum.attrib = empty +namvolnum.role.attrib = role.attrib +# doc:A reference volume number. +manvolnum = element manvolnum { manvolnum.attlist, word.char.mix* } +# end of manvolnum.element +manvolnum.attlist &= + common.attrib, namvolnum.role.attrib, local.manvolnum.attrib +# end of manvolnum.attlist + +# end of manvolnum.module +local.citetitle.attrib = empty +citetitle.role.attrib = role.attrib +# doc:The title of a cited work. +citetitle = element citetitle { citetitle.attlist, para.char.mix* } +# end of citetitle.element + +# Pubwork: Genre of published work cited; no default +citetitle.attlist &= + attribute pubwork { + "article" + | "book" + | "chapter" + | "part" + | "refentry" + | "section" + | "journal" + | "series" + | "set" + | "manuscript" + | "cdrom" + | "dvd" + | "wiki" + | "gopher" + | "bbs" + | "emailmessage" + | "webpage" + | "newsposting" + }?, + common.attrib, + citetitle.role.attrib, + local.citetitle.attrib +# end of citetitle.attlist + +# end of citetitle.module +local.emphasis.attrib = empty +emphasis.role.attrib = role.attrib +# doc:Emphasized text. +emphasis = element emphasis { emphasis.attlist, para.char.mix* } +# end of emphasis.element +emphasis.attlist &= + common.attrib, emphasis.role.attrib, local.emphasis.attrib +# end of emphasis.attlist + +# end of emphasis.module +local.foreignphrase.attrib = empty +foreignphrase.role.attrib = role.attrib +# doc:A word or phrase in a language other than the primary language of the document. +foreignphrase = + element foreignphrase { foreignphrase.attlist, para.char.mix* } +# end of foreignphrase.element +foreignphrase.attlist &= + common.attrib, foreignphrase.role.attrib, local.foreignphrase.attrib +# end of foreignphrase.attlist + +# end of foreignphrase.module +local.glossterm.attrib = empty +glossterm.role.attrib = role.attrib +# doc:A glossary term. +glossterm = element glossterm { glossterm.attlist, para.char.mix* } +# end of glossterm.element + +# to GlossEntry if Glossterm used in text + +# BaseForm: Provides the form of GlossTerm to be used +# for indexing +glossterm.attlist &= + attribute baseform { text }?, + linkend.attrib, + common.attrib, + glossterm.role.attrib, + local.glossterm.attrib +# end of glossterm.attlist + +# end of glossterm.module +local.firstterm.attrib = empty +firstterm.role.attrib = role.attrib +# doc:The first occurrence of a term. +firstterm = element firstterm { firstterm.attlist, para.char.mix* } +# end of firstterm.element + +# to GlossEntry or other explanation +firstterm.attlist &= + attribute baseform { text }?, + linkend.attrib, + common.attrib, + firstterm.role.attrib, + local.firstterm.attrib +# end of firstterm.attlist + +# end of firstterm.module +local.phrase.attrib = empty +phrase.role.attrib = role.attrib +# doc:A span of text. +phrase = element phrase { phrase.attlist, para.char.mix* } +# end of phrase.element +phrase.attlist &= common.attrib, phrase.role.attrib, local.phrase.attrib +# end of phrase.attlist + +# end of phrase.module +local.quote.attrib = empty +quote.role.attrib = role.attrib +# doc:An inline quotation. +quote = element quote { quote.attlist, para.char.mix* } +# end of quote.element +quote.attlist &= common.attrib, quote.role.attrib, local.quote.attrib +# end of quote.attlist + +# end of quote.module +local.ssscript.attrib = empty +ssscript.role.attrib = role.attrib +# doc:A subscript (as in H{^2}O, the molecular formula for water). +subscript = + element subscript { + subscript.attlist, + (text + | link.char.class + | emphasis + | replaceable + | symbol + | inlinegraphic + | inlinemediaobject + | base.char.class + | other.char.class)* + } +# end of subscript.element +subscript.attlist &= + common.attrib, ssscript.role.attrib, local.ssscript.attrib +# end of subscript.attlist + +# doc:A superscript (as in x^2, the mathematical notation for x multiplied by itself). +superscript = + element superscript { + superscript.attlist, + (text + | link.char.class + | emphasis + | replaceable + | symbol + | inlinegraphic + | inlinemediaobject + | base.char.class + | other.char.class)* + } +# end of superscript.element +superscript.attlist &= + common.attrib, ssscript.role.attrib, local.ssscript.attrib +# end of superscript.attlist + +# end of ssscript.module +local.trademark.attrib = empty +trademark.role.attrib = role.attrib +# doc:A trademark. +trademark = + element trademark { + trademark.attlist, + (text + | link.char.class + | tech.char.class + | base.char.class + | other.char.class + | inlinegraphic + | inlinemediaobject + | emphasis)* + } +# end of trademark.element + +# Class: More precisely identifies the item the element names +trademark.attlist &= + [ a:defaultValue = "trade" ] + attribute class { "service" | "trade" | "registered" | "copyright" }?, + common.attrib, + trademark.role.attrib, + local.trademark.attrib +# end of trademark.attlist + +# end of trademark.module +local.wordasword.attrib = empty +wordasword.role.attrib = role.attrib +# doc:A word meant specifically as a word and not representing anything else. +wordasword = element wordasword { wordasword.attlist, word.char.mix* } +# end of wordasword.element +wordasword.attlist &= + common.attrib, wordasword.role.attrib, local.wordasword.attrib +# end of wordasword.attlist + +# end of wordasword.module + +# Links and cross-references ........................................... +local.link.attrib = empty +link.role.attrib = role.attrib +# doc:A hypertext link. +link = element link { link.attlist, para.char.mix* } +# end of link.element + +# Endterm: ID of element containing text that is to be +# fetched from elsewhere in the document to appear as +# the content of this element + +# to linked-to object + +# Type: Freely assignable parameter +link.attlist &= + attribute endterm { xsd:IDREF }?, + attribute xrefstyle { text }?, + attribute type { text }?, + linkendreq.attrib, + common.attrib, + link.role.attrib, + local.link.attrib +# end of link.attlist + +# end of link.module +local.olink.attrib = empty +olink.role.attrib = role.attrib +# doc:A link that addresses its target indirectly, through an entity. +olink = element olink { olink.attlist, para.char.mix* } +# end of olink.element + +# TargetDocEnt: Name of an entity to be the target of the link + +# LinkMode: ID of a ModeSpec containing instructions for +# operating on the entity named by TargetDocEnt + +# LocalInfo: Information that may be passed to ModeSpec + +# Type: Freely assignable parameter +olink.attlist &= + attribute targetdocent { xsd:ENTITY }?, + attribute linkmode { xsd:IDREF }?, + attribute localinfo { text }?, + attribute type { text }?, + attribute targetdoc { text }?, + attribute targetptr { text }?, + attribute xrefstyle { text }?, + common.attrib, + olink.role.attrib, + local.olink.attrib +# end of olink.attlist + +# end of olink.module +local.ulink.attrib = empty +ulink.role.attrib = role.attrib +# doc:A link that addresses its target by means of a URL (Uniform Resource Locator). +ulink = element ulink { ulink.attlist, para.char.mix* } +# end of ulink.element + +# URL: uniform resource locator; the target of the ULink + +# Type: Freely assignable parameter +ulink.attlist &= + attribute url { text }, + attribute type { text }?, + attribute xrefstyle { text }?, + common.attrib, + ulink.role.attrib, + local.ulink.attrib +# end of ulink.attlist + +# end of ulink.module +local.footnoteref.attrib = empty +footnoteref.role.attrib = role.attrib +# doc:A cross reference to a footnote (a footnote mark). +footnoteref = element footnoteref { footnoteref.attlist, empty } +# end of footnoteref.element + +# to footnote content supplied elsewhere +footnoteref.attlist &= + linkendreq.attrib, + label.attrib, + common.attrib, + footnoteref.role.attrib, + local.footnoteref.attrib +# end of footnoteref.attlist + +# end of footnoteref.module +local.xref.attrib = empty +xref.role.attrib = role.attrib +# doc:A cross reference to another part of the document. +xref = element xref { xref.attlist, empty } +# end of xref.element + +# Endterm: ID of element containing text that is to be +# fetched from elsewhere in the document to appear as +# the content of this element + +# to linked-to object +xref.attlist &= + attribute endterm { xsd:IDREF }?, + attribute xrefstyle { text }?, + common.attrib, + linkendreq.attrib, + xref.role.attrib, + local.xref.attrib +# end of xref.attlist + +# end of xref.module +local.biblioref.attrib = empty +biblioref.role.attrib = role.attrib +# doc:A cross reference to a bibliographic entry. +biblioref = element biblioref { biblioref.attlist, empty } +# end of biblioref.element +biblioref.attlist &= + attribute endterm { xsd:IDREF }?, + attribute xrefstyle { text }?, + attribute units { text }?, + attribute begin { text }?, + attribute end { text }?, + common.attrib, + linkendreq.attrib, + biblioref.role.attrib, + local.biblioref.attrib +# end of biblioref.attlist + +# end of biblioref.module + +# Ubiquitous elements .................................................. +local.anchor.attrib = empty +anchor.role.attrib = role.attrib +# doc:A spot in the document. +anchor = element anchor { anchor.attlist, empty } +# end of anchor.element + +# required + +# replaces Lang +anchor.attlist &= + idreq.attrib, + pagenum.attrib, + remap.attrib, + xreflabel.attrib, + revisionflag.attrib, + effectivity.attrib, + anchor.role.attrib, + local.anchor.attrib +# end of anchor.attlist + +# end of anchor.module +local.beginpage.attrib = empty +beginpage.role.attrib = role.attrib +# doc:The location of a page break in a print version of the document. +beginpage = element beginpage { beginpage.attlist, empty } +# end of beginpage.element + +# PageNum: Number of page that begins at this point +beginpage.attlist &= + pagenum.attrib, + common.attrib, + beginpage.role.attrib, + local.beginpage.attrib +# end of beginpage.attlist + +# end of beginpage.module + +# IndexTerms appear in the text flow for generating or linking an +# index. +local.indexterm.attrib = empty +indexterm.role.attrib = role.attrib +# doc:A wrapper for terms to be indexed. +indexterm = + element indexterm { + indexterm.attlist, + primary?, + ((secondary, + ((tertiary, (see | seealso+)?) + | see + | seealso+)?) + | see + | seealso+)? + } +# end of indexterm.element + +# Scope: Indicates which generated indices the IndexTerm +# should appear in: Global (whole document set), Local (this +# document only), or All (both) + +# Significance: Whether this IndexTerm is the most pertinent +# of its series (Preferred) or not (Normal, the default) + +# Class: Indicates type of IndexTerm; default is Singular, +# or EndOfRange if StartRef is supplied; StartOfRange value +# must be supplied explicitly on starts of ranges + +# StartRef: ID of the IndexTerm that starts the indexing +# range ended by this IndexTerm + +# Zone: IDs of the elements to which the IndexTerm applies, +# and indicates that the IndexTerm applies to those entire +# elements rather than the point at which the IndexTerm +# occurs +indexterm.attlist &= + pagenum.attrib, + attribute scope { "all" | "global" | "local" }?, + [ a:defaultValue = "normal" ] + attribute significance { "preferred" | "normal" }?, + attribute class { "singular" | "startofrange" | "endofrange" }?, + attribute startref { xsd:IDREF }?, + attribute zone { xsd:IDREFS }?, + attribute type { text }?, + common.attrib, + indexterm.role.attrib, + local.indexterm.attrib +# end of indexterm.attlist + +# end of indexterm.module +local.primsecter.attrib = empty +primsecter.role.attrib = role.attrib +# doc:The primary word or phrase under which an index term should be sorted. +primary = element primary { primary.attlist, ndxterm.char.mix* } +# end of primary.element + +# SortAs: Alternate sort string for index sorting, e.g., +# "fourteen" for an element containing "14" +primary.attlist &= + attribute sortas { text }?, + common.attrib, + primsecter.role.attrib, + local.primsecter.attrib +# end of primary.attlist + +# doc:A secondary word or phrase in an index term. +secondary = element secondary { secondary.attlist, ndxterm.char.mix* } +# end of secondary.element + +# SortAs: Alternate sort string for index sorting, e.g., +# "fourteen" for an element containing "14" +secondary.attlist &= + attribute sortas { text }?, + common.attrib, + primsecter.role.attrib, + local.primsecter.attrib +# end of secondary.attlist + +# doc:A tertiary word or phrase in an index term. +tertiary = element tertiary { tertiary.attlist, ndxterm.char.mix* } +# end of tertiary.element + +# SortAs: Alternate sort string for index sorting, e.g., +# "fourteen" for an element containing "14" +tertiary.attlist &= + attribute sortas { text }?, + common.attrib, + primsecter.role.attrib, + local.primsecter.attrib +# end of tertiary.attlist + +# end of primsecter.module +local.seeseealso.attrib = empty +seeseealso.role.attrib = role.attrib +# doc:Part of an index term directing the reader instead to another entry in the index. +see = element see { see.attlist, ndxterm.char.mix* } +# end of see.element +see.attlist &= + common.attrib, seeseealso.role.attrib, local.seeseealso.attrib +# end of see.attlist + +# doc:Part of an index term directing the reader also to another entry in the index. +seealso = element seealso { seealso.attlist, ndxterm.char.mix* } +# end of seealso.element +seealso.attlist &= + common.attrib, seeseealso.role.attrib, local.seeseealso.attrib +# end of seealso.attlist + +# end of seeseealso.module + +# end of indexterm.content.module + +# End of DocBook XML information pool module V4.5 ...................... + +# ...................................................................... diff --git a/defensive-coding/docbook-schema/docbook.rnc b/defensive-coding/docbook-schema/docbook.rnc new file mode 100644 index 0000000..8a0a75a --- /dev/null +++ b/defensive-coding/docbook-schema/docbook.rnc @@ -0,0 +1,499 @@ +# ...................................................................... + +# DocBook XML DTD V4.5 ................................................. + +# File docbookx.dtd .................................................... + +# Copyright 1992-2006 HaL Computer Systems, Inc., +# O'Reilly & Associates, Inc., ArborText, Inc., Fujitsu Software +# Corporation, Norman Walsh, Sun Microsystems, Inc., and the +# Organization for the Advancement of Structured Information +# Standards (OASIS). +# +# See also http://docbook.org/specs/ +# +# $Id: docbookx.dtd 6340 2006-10-03 13:23:24Z nwalsh $ +# +# Permission to use, copy, modify and distribute the DocBook XML DTD +# and its accompanying documentation for any purpose and without fee +# is hereby granted in perpetuity, provided that the above copyright +# notice and this paragraph appear in all copies. The copyright +# holders make no representation about the suitability of the DTD for +# any purpose. It is provided "as is" without expressed or implied +# warranty. +# +# If you modify the DocBook DTD in any way, except for declaring and +# referencing additional sets of general entities and declaring +# additional notations, label your DTD as a variant of DocBook. See +# the maintenance documentation for more information. +# +# Please direct all questions, bug reports, or suggestions for +# changes to the docbook@lists.oasis-open.org mailing list. For more +# information, see http://www.oasis-open.org/docbook/. + +# ...................................................................... + +# This is the driver file for V4.5 of the DocBook DTD. +# Please use the following formal public identifier to identify it: +# +# "-//OASIS//DTD DocBook XML V4.5//EN" +# +# For example, if your document's top-level element is Book, and +# you are using DocBook directly, use the FPI in the DOCTYPE +# declaration: +# +# +# +# Or, if you have a higher-level driver file that customizes DocBook, +# use the FPI in the parameter entity declaration: +# +# +# %DocBookDTD; +# +# See the documentation for detailed information on the parameter +# entity and module scheme used in DocBook, customizing DocBook and +# planning for interchange, and changes made since the last release +# of DocBook. + +# ...................................................................... + +# Enable SGML features ................................................. + +# ...................................................................... + +# Notation declarations ................................................ + +include "dbnotnx.rnc" +# ...................................................................... + +# ISO character entity sets ............................................ + +# euro sign, U+20AC NEW + +# ...................................................................... + +# DTD modules .......................................................... + +# Information pool .............. +include "dbpoolx.rnc" +# Redeclaration placeholder ..... + +# Document hierarchy ............ +include "dbhierx.rnc" +start = + articleinfo + | honorific + | legalnotice + | procedure + | simplelist + | keycode + | refsynopsisdiv + | article + | phrase + | destructorsynopsis + | itemizedlist + | audioobject + | link + | sect1info + | xref + | glossaryinfo + | varname + | keywordset + | informalequation + | toc + | pagenums + | lot + | shortcut + | glosslist + | option + | bibliosource + | variablelist + | filename + | pob + | colgroup + | foreignphrase + | group + | substeps + | conftitle + | textobject + | menuchoice + | colspec + | contractsponsor + | tocback + | contractnum + | constant + | dedication + | inlineequation + | bibliographyinfo + | country + | glossseealso + | bridgehead + | mousebutton + | surname + | stepalternatives + | tertiaryie + | mediaobject + | msgentry + | fax + | initializer + | table + | task + | setinfo + | videodata + | bibliodiv + | issuenum + | phone + | state + | refsynopsisdivinfo + | member + | glossentry + | term + | msgtext + | tr + | errortype + | confdates + | inlinegraphic + | th + | segmentedlist + | remark + | preface + | structname + | publisher + | td + | oointerface + | refsection + | type + | taskrelated + | msgrel + | artpagenums + | bibliomixed + | revnumber + | firstterm + | seeie + | spanspec + | toclevel5 + | trademark + | toclevel4 + | toclevel3 + | toclevel2 + | indexentry + | toclevel1 + | colophon + | methodparam + | sidebarinfo + | productnumber + | funcprototype + | inlinemediaobject + | refclass + | lotentry + | paramdef + | classsynopsisinfo + | qandaset + | footnote + | msglevel + | keysym + | citation + | simplemsgentry + | othercredit + | subjectset + | keycap + | orderedlist + | refmiscinfo + | blockinfo + | programlistingco + | abbrev + | sidebar + | informalfigure + | tip + | primaryie + | appendixinfo + | partintro + | glossdiv + | confgroup + | segtitle + | taskprerequisites + | street + | tbody + | caption + | markup + | setindex + | msgsub + | subscript + | orgname + | fieldsynopsis + | refname + | void + | sect5 + | sect4 + | sect3 + | chapter + | sect2 + | sect1 + | modifier + | col + | orgdiv + | city + | bibliolist + | funcparams + | application + | \token + | imageobject + | literal + | funcsynopsis + | olink + | package + | collab + | seealsoie + | primary + | glossterm + | termdef + | area + | ackno + | function + | collabname + | lineannotation + | guisubmenu + | msgexplan + | errorname + | property + | synopfragmentref + | refentryinfo + | entry + | manvolnum + | synopsis + | emphasis + | appendix + | bookinfo + | contrib + | otheraddr + | copyright + | methodname + | email + | ooclass + | videoobject + | abstract + | firstname + | revremark + | glossdef + | guibutton + | informalexample + | screen + | errorcode + | command + | seriesvolnums + | refpurpose + | parameter + | equation + | tfoot + | code + | jobtitle + | sgmltag + | screenco + | holder + | isbn + | corpcredit + | biblioset + | part + | symbol + | row + | bibliomisc + | imagedata + | secondary + | classname + | callout + | screenshot + | bibliomset + | indexterm + | refsect3 + | tocchap + | para + | refsect2 + | refsect1 + | date + | refdescriptor + | wordasword + | epigraph + | audiodata + | hardware + | confsponsor + | authorgroup + | warning + | authorinitials + | medialabel + | varlistentry + | authorblurb + | itermset + | refsect3info + | informaltable + | guimenuitem + | postcode + | subjectterm + | refnamediv + | note + | figure + | envar + | listitem + | methodsynopsis + | affiliation + | funcsynopsisinfo + | structfield + | blockquote + | keyword + | chapterinfo + | tertiary + | year + | subtitle + | personblurb + | refentry + | citebiblioid + | seglistitem + | bibliography + | msg + | constructorsynopsis + | refsect2info + | volumenum + | database + | funcdef + | uri + | graphicco + | biblioid + | msgmain + | printhistory + | glosssee + | beginpage + | glossary + | set + | highlights + | objectinfo + | tocpart + | guiicon + | revhistory + | seg + | see + | msgorig + | areaspec + | partinfo + | index + | sectioninfo + | refsectioninfo + | optional + | confnum + | replaceable + | refsect1info + | corpauthor + | step + | anchor + | arg + | mathphrase + | setindexinfo + | keycombo + | address + | cmdsynopsis + | computeroutput + | literallayout + | qandaentry + | sect5info + | bibliocoverage + | coref + | editor + | superscript + | personname + | pubsnumber + | graphic + | simplesect + | accel + | secondaryie + | biblioref + | publishername + | bibliorelation + | prefaceinfo + | revision + | screeninfo + | sbr + | example + | citetitle + | issn + | invpartnumber + | indexdiv + | sect4info + | corpname + | lineage + | ooexception + | reference + | revdescription + | title + | edition + | co + | msgaud + | guimenu + | shortaffil + | titleabbrev + | msginfo + | refmeta + | qandadiv + | mediaobjectco + | seealso + | exceptionname + | answer + | programlisting + | tgroup + | refentrytitle + | book + | errortext + | varargs + | sect3info + | citerefentry + | tasksummary + | quote + | othername + | prompt + | entrytbl + | interfacename + | acronym + | modespec + | msgset + | thead + | textdata + | userinput + | attribution + | footnoteref + | action + | tocentry + | tocfront + | author + | imageobjectco + | alt + | question + | ulink + | subject + | pubdate + | returnvalue + | label + | caution + | section + | systemitem + | referenceinfo + | sect2info + | calloutlist + | classsynopsis + | productname + | simpara + | synopfragment + | important + | interface + | releaseinfo + | formalpara + | areaset + | biblioentry + | indexinfo + | guilabel +# ...................................................................... + +# Other general entities ............................................... + +# End of DocBook XML DTD V4.5 .......................................... + +# ...................................................................... diff --git a/defensive-coding/docbook-schema/htmltblx.rnc b/defensive-coding/docbook-schema/htmltblx.rnc new file mode 100644 index 0000000..7e15972 --- /dev/null +++ b/defensive-coding/docbook-schema/htmltblx.rnc @@ -0,0 +1,225 @@ +# ...................................................................... + +# DocBook XML HTML Table Module V4.5 ................................... + +# File htmltblx.mod .................................................... + +# Copyright 2003-2006 ArborText, Inc., Norman Walsh, Sun Microsystems, +# Inc., and the Organization for the Advancement of Structured Information +# Standards (OASIS). +# +# $Id: htmltblx.mod 6340 2006-10-03 13:23:24Z nwalsh $ +# +# Permission to use, copy, modify and distribute the DocBook XML DTD +# and its accompanying documentation for any purpose and without fee +# is hereby granted in perpetuity, provided that the above copyright +# notice and this paragraph appear in all copies. The copyright +# holders make no representation about the suitability of the DTD for +# any purpose. It is provided "as is" without expressed or implied +# warranty. +# +# If you modify the DocBook XML DTD in any way, except for declaring and +# referencing additional sets of general entities and declaring +# additional notations, label your DTD as a variant of DocBook. See +# the maintenance documentation for more information. +# +# Please direct all questions, bug reports, or suggestions for +# changes to the docbook@lists.oasis-open.org mailing list. For more +# information, see http://www.oasis-open.org/docbook/. + +# ...................................................................... + +# This module contains the definitions for elements that are +# isomorphic to the HTML elements. One could argue we should +# instead have based ourselves on the XHTML Table Module, but the +# HTML one is more like what browsers are likely to accept today +# and users are likely to use. +# +# This module has been developed for use with the DocBook V4.5 +# "union table model" in which elements and attlists common to both +# models are defined (as the union) in the CALS table module by +# setting various parameter entities appropriately in this file. +# +# In DTD driver files referring to this module, please use an entity +# declaration that uses the public identifier shown below: +# +# +# %htmltbl; +# +# See the documentation for detailed information on the parameter +# entity and module scheme used in DocBook, customizing DocBook and +# planning for interchange, and changes made since the last release +# of DocBook. + +# ======================= XHTML Tables ======================================= + +namespace a = "http://relaxng.org/ns/compatibility/annotations/1.0" + +html.coreattrs = + common.attrib, + attribute class { text }?, + attribute style { text }?, + attribute title { text }? +# Does not contain lang or dir because they are in %common.attribs +i18n = attribute xml:lang { xsd:NMTOKEN }? +events = + attribute onclick { text }?, + attribute ondblclick { text }?, + attribute onmousedown { text }?, + attribute onmouseup { text }?, + attribute onmouseover { text }?, + attribute onmousemove { text }?, + attribute onmouseout { text }?, + attribute onkeypress { text }?, + attribute onkeydown { text }?, + attribute onkeyup { text }? +attrs = html.coreattrs, i18n, events +cellhalign = + attribute align { "left" | "center" | "right" | "justify" | "char" }?, + attribute char { text }?, + attribute charoff { text }? +cellvalign = + attribute valign { "top" | "middle" | "bottom" | "baseline" }? +# doc:A group of columns in an HTML table. +colgroup = element colgroup { colgroup.attlist, col* } +# doc:Specifications for a column in an HTML table. +col = element col { col.attlist, empty } +# doc:A row in an HTML table. +tr = element tr { tr.attlist, (th | td)+ } +# doc:A table header entry in an HTML table. +th = + element th { + th.attlist, (para.char.mix | tabentry.mix | table | informaltable)* + } +# doc:A table ntry in an HTML table. +td = + element td { + td.attlist, (para.char.mix | tabentry.mix | table | informaltable)* + } +colgroup.attlist &= + attrs, + [ a:defaultValue = "1" ] attribute span { text }?, + attribute width { text }?, + cellhalign, + cellvalign +col.attlist &= + attrs, + [ a:defaultValue = "1" ] attribute span { text }?, + attribute width { text }?, + cellhalign, + cellvalign +tr.attlist &= + attrs, + cellhalign, + cellvalign, + attribute bgcolor { text }? +th.attlist &= + attrs, + attribute abbr { text }?, + attribute axis { text }?, + attribute headers { xsd:IDREFS }?, + attribute scope { "row" | "col" | "rowgroup" | "colgroup" }?, + [ a:defaultValue = "1" ] attribute rowspan { text }?, + [ a:defaultValue = "1" ] attribute colspan { text }?, + cellhalign, + cellvalign, + attribute nowrap { "nowrap" }?, + attribute bgcolor { text }?, + attribute width { text }?, + attribute height { text }? +td.attlist &= + attrs, + attribute abbr { text }?, + attribute axis { text }?, + attribute headers { xsd:IDREFS }?, + attribute scope { "row" | "col" | "rowgroup" | "colgroup" }?, + [ a:defaultValue = "1" ] attribute rowspan { text }?, + [ a:defaultValue = "1" ] attribute colspan { text }?, + cellhalign, + cellvalign, + attribute nowrap { "nowrap" }?, + attribute bgcolor { text }?, + attribute width { text }?, + attribute height { text }? +# ====================================================== + +# Set up to read in the CALS model configured to +# merge with the XHTML table model + +# ====================================================== +tables.role.attrib = role.attrib +# Add label and role attributes to table and informaltable +bodyatt = + attribute floatstyle { text }?, + attribute rowheader { "firstcol" | "norowheader" }?, + label.attrib +# Add common attributes to Table, TGroup, TBody, THead, TFoot, Row, +# EntryTbl, and Entry (and InformalTable element). +secur = + common.attrib, + attribute class { text }?, + attribute style { text }?, + attribute title { text }?, + i18n, + events, + tables.role.attrib +common.table.attribs = bodyatt, secur +# Content model for Table (that also allows HTML tables) +tbl.table.mdl = + (blockinfo?, + formalobject.title.content, + ndxterm.class*, + textobject*, + (graphic+ | mediaobject+ | tgroup+)) + | (caption, (col* | colgroup*), thead?, tfoot?, (tbody+ | tr+)) +informal.tbl.table.mdl = + (textobject*, (graphic+ | mediaobject+ | tgroup+)) + | ((col* | colgroup*), thead?, tfoot?, (tbody+ | tr+)) +# Attributes for Table (including HTML ones) + +# N.B. rules = (none | groups | rows | cols | all) but it can't be spec'd + +# that way because 'all' already occurs in a different enumeration in + +# CALS tables (frame). +tbl.table.att = + attribute tabstyle { text }?, + attribute tocentry { yesorno.attvals }?, + attribute shortentry { yesorno.attvals }?, + attribute orient { "port" | "land" }?, + attribute pgwide { yesorno.attvals }?, + attribute summary { text }?, + attribute width { text }?, + attribute border { text }?, + attribute rules { text }?, + attribute cellspacing { text }?, + attribute cellpadding { text }?, + attribute align { "left" | "center" | "right" }?, + attribute bgcolor { text }? +tbl.frame.attval = + "void" + | "above" + | "below" + | "hsides" + | "lhs" + | "rhs" + | "vsides" + | "box" + | "border" + | "top" + | "bottom" + | "topbot" + | "all" + | "sides" + | "none" +# Allow either objects or inlines; beware of REs between elements. +tbl.entry.mdl = para.char.mix | tabentry.mix +# thead, tfoot, and tbody are defined in both table models, +# so we set up parameter entities to define union models for them +tbl.hdft.mdl = tr+ | (colspec*, row+) +tbl.tbody.mdl = tr+ | row+ +# End of DocBook XML HTML Table Module V4.5 ............................ + +# ...................................................................... diff --git a/defensive-coding/en-US/.svn/all-wcprops b/defensive-coding/en-US/.svn/all-wcprops new file mode 100644 index 0000000..3d941d7 --- /dev/null +++ b/defensive-coding/en-US/.svn/all-wcprops @@ -0,0 +1,23 @@ +K 25 +svn:wc:ra_dav:version-url +V 65 +/repos/product-security/!svn/ver/302/defensive-coding/trunk/en-US +END +Defensive_Coding.ent +K 25 +svn:wc:ra_dav:version-url +V 85 +/repos/product-security/!svn/ver/64/defensive-coding/trunk/en-US/Defensive_Coding.ent +END +Book_Info.xml +K 25 +svn:wc:ra_dav:version-url +V 79 +/repos/product-security/!svn/ver/281/defensive-coding/trunk/en-US/Book_Info.xml +END +Defensive_Coding.xml +K 25 +svn:wc:ra_dav:version-url +V 86 +/repos/product-security/!svn/ver/281/defensive-coding/trunk/en-US/Defensive_Coding.xml +END diff --git a/defensive-coding/en-US/.svn/entries b/defensive-coding/en-US/.svn/entries new file mode 100644 index 0000000..c3aaf37 --- /dev/null +++ b/defensive-coding/en-US/.svn/entries @@ -0,0 +1,145 @@ +10 + +dir +305 +https://svn.devel.redhat.com/repos/product-security/defensive-coding/trunk/en-US +https://svn.devel.redhat.com/repos/product-security + + + +2013-01-16T14:32:22.318444Z +302 +fweimer@REDHAT.COM + + + + + + + + + + + + + + +9bd5cf0f-f2b3-0410-b1a9-d5c590f50bf1 + +Defensive_Coding.ent +file + + + + +2013-01-10T17:17:49.038814Z +240837ebc2948c0404c903c2b25ee90a +2012-07-16T12:32:39.042163Z +64 +fweimer@REDHAT.COM + + + + + + + + + + + + + + + + + + + + + +54 + +Python +dir + +C +dir + +CXX +dir + +Book_Info.xml +file + + + + +2013-01-10T17:17:49.038814Z +0a9c514a2db8c6783b91a20eea2918c2 +2012-12-13T13:25:23.103424Z +281 +fweimer@REDHAT.COM +has-props + + + + + + + + + + + + + + + + + + + + +999 + +Tasks +dir + +Defensive_Coding.xml +file + + + + +2013-01-10T17:17:49.038814Z +81327d12a4be4bc9189fbd3eea5c5215 +2012-12-13T13:25:23.103424Z +281 +fweimer@REDHAT.COM +has-props + + + + + + + + + + + + + + + + + + + + +1522 + +Features +dir + diff --git a/defensive-coding/en-US/.svn/prop-base/Book_Info.xml.svn-base b/defensive-coding/en-US/.svn/prop-base/Book_Info.xml.svn-base new file mode 100644 index 0000000..bfec7d5 --- /dev/null +++ b/defensive-coding/en-US/.svn/prop-base/Book_Info.xml.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 8 +text/xml +END diff --git a/defensive-coding/en-US/.svn/prop-base/Defensive_Coding.xml.svn-base b/defensive-coding/en-US/.svn/prop-base/Defensive_Coding.xml.svn-base new file mode 100644 index 0000000..bfec7d5 --- /dev/null +++ b/defensive-coding/en-US/.svn/prop-base/Defensive_Coding.xml.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 8 +text/xml +END diff --git a/defensive-coding/en-US/.svn/text-base/Book_Info.xml.svn-base b/defensive-coding/en-US/.svn/text-base/Book_Info.xml.svn-base new file mode 100644 index 0000000..f51a71c --- /dev/null +++ b/defensive-coding/en-US/.svn/text-base/Book_Info.xml.svn-base @@ -0,0 +1,29 @@ + + + + Defensive Coding + A Guide to Improving Software Security + 1.0 + 1.0 + 20 + Internal + 6.4 + + + This document provides guidelines for improving software + security through secure coding. It covers common + programming languages and libraries, and focuses on + concrete recommendations. + + + + + + + + + + + + diff --git a/defensive-coding/en-US/.svn/text-base/Defensive_Coding.ent.svn-base b/defensive-coding/en-US/.svn/text-base/Defensive_Coding.ent.svn-base new file mode 100644 index 0000000..0bf84b7 --- /dev/null +++ b/defensive-coding/en-US/.svn/text-base/Defensive_Coding.ent.svn-base @@ -0,0 +1,2 @@ + + diff --git a/defensive-coding/en-US/.svn/text-base/Defensive_Coding.xml.svn-base b/defensive-coding/en-US/.svn/text-base/Defensive_Coding.xml.svn-base new file mode 100644 index 0000000..5fcc6eb --- /dev/null +++ b/defensive-coding/en-US/.svn/text-base/Defensive_Coding.xml.svn-base @@ -0,0 +1,26 @@ + + + + + + Programming Languages + + + + + + Specific Programming Tasks + + + + + + + + + + Implementing Security Features + + + + diff --git a/defensive-coding/en-US/Author_Group.xml b/defensive-coding/en-US/Author_Group.xml new file mode 100644 index 0000000..6b40228 --- /dev/null +++ b/defensive-coding/en-US/Author_Group.xml @@ -0,0 +1,17 @@ + + +%BOOK_ENTITIES; +]> + + + Florian + Weimer + + Red Hat + Product Security Team + + fweimer@redhat.com + + + diff --git a/defensive-coding/en-US/Book_Info.xml b/defensive-coding/en-US/Book_Info.xml new file mode 100644 index 0000000..6637802 --- /dev/null +++ b/defensive-coding/en-US/Book_Info.xml @@ -0,0 +1,30 @@ + + + + Defensive Coding + A Guide to Improving Software Security + 1.0 + 1.0 + + + + + + This document provides guidelines for improving software + security through secure coding. It covers common + programming languages and libraries, and focuses on + concrete recommendations. + + + + + + + + + + + + + diff --git a/defensive-coding/en-US/C/.svn/all-wcprops b/defensive-coding/en-US/C/.svn/all-wcprops new file mode 100644 index 0000000..d8e8e2f --- /dev/null +++ b/defensive-coding/en-US/C/.svn/all-wcprops @@ -0,0 +1,35 @@ +K 25 +svn:wc:ra_dav:version-url +V 67 +/repos/product-security/!svn/ver/292/defensive-coding/trunk/en-US/C +END +C.xml +K 25 +svn:wc:ra_dav:version-url +V 73 +/repos/product-security/!svn/ver/281/defensive-coding/trunk/en-US/C/C.xml +END +Allocators.xml +K 25 +svn:wc:ra_dav:version-url +V 82 +/repos/product-security/!svn/ver/281/defensive-coding/trunk/en-US/C/Allocators.xml +END +Language.xml +K 25 +svn:wc:ra_dav:version-url +V 80 +/repos/product-security/!svn/ver/281/defensive-coding/trunk/en-US/C/Language.xml +END +schemas.xml +K 25 +svn:wc:ra_dav:version-url +V 79 +/repos/product-security/!svn/ver/292/defensive-coding/trunk/en-US/C/schemas.xml +END +Libc.xml +K 25 +svn:wc:ra_dav:version-url +V 76 +/repos/product-security/!svn/ver/281/defensive-coding/trunk/en-US/C/Libc.xml +END diff --git a/defensive-coding/en-US/C/.svn/dir-prop-base b/defensive-coding/en-US/C/.svn/dir-prop-base new file mode 100644 index 0000000..b0e5252 --- /dev/null +++ b/defensive-coding/en-US/C/.svn/dir-prop-base @@ -0,0 +1,6 @@ +K 10 +svn:ignore +V 9 +snippets + +END diff --git a/defensive-coding/en-US/C/.svn/entries b/defensive-coding/en-US/C/.svn/entries new file mode 100644 index 0000000..cfeb91c --- /dev/null +++ b/defensive-coding/en-US/C/.svn/entries @@ -0,0 +1,198 @@ +10 + +dir +305 +https://svn.devel.redhat.com/repos/product-security/defensive-coding/trunk/en-US/C +https://svn.devel.redhat.com/repos/product-security + + + +2012-12-14T10:18:44.472257Z +292 +fweimer@REDHAT.COM +has-props + + + + + + + + + + + + + +9bd5cf0f-f2b3-0410-b1a9-d5c590f50bf1 + +C.xml +file + + + + +2013-01-10T17:17:40.330763Z +152059b0949055c27918169fb0406ee5 +2012-12-13T13:25:23.103424Z +281 +fweimer@REDHAT.COM +has-props + + + + + + + + + + + + + + + + + + + + +503 + +Allocators.xml +file + + + + +2013-01-10T17:17:40.330763Z +483d91643e7a6a8d6545649b2fa0b144 +2012-12-13T13:25:23.103424Z +281 +fweimer@REDHAT.COM +has-props + + + + + + + + + + + + + + + + + + + + +8762 + +Language.xml +file + + + + +2013-01-10T17:17:40.330763Z +11fb84b7e9a7c76cfc95dbe918118998 +2012-12-13T13:25:23.103424Z +281 +fweimer@REDHAT.COM +has-props + + + + + + + + + + + + + + + + + + + + +6528 + +schemas.xml +file + + + + +2013-01-10T17:17:40.331763Z +769bc2635d36b318161574a1adf2f6e7 +2012-12-14T10:18:44.472257Z +292 +fweimer@REDHAT.COM +has-props + + + + + + + + + + + + + + + + + + + + +150 + +Libc.xml +file + + + + +2013-01-10T17:17:40.331763Z +6e4999f743167fd393cbd521fd4d662c +2012-12-13T13:25:23.103424Z +281 +fweimer@REDHAT.COM +has-props + + + + + + + + + + + + + + + + + + + + +8733 + diff --git a/defensive-coding/en-US/C/.svn/prop-base/Allocators.xml.svn-base b/defensive-coding/en-US/C/.svn/prop-base/Allocators.xml.svn-base new file mode 100644 index 0000000..bfec7d5 --- /dev/null +++ b/defensive-coding/en-US/C/.svn/prop-base/Allocators.xml.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 8 +text/xml +END diff --git a/defensive-coding/en-US/C/.svn/prop-base/C.xml.svn-base b/defensive-coding/en-US/C/.svn/prop-base/C.xml.svn-base new file mode 100644 index 0000000..bfec7d5 --- /dev/null +++ b/defensive-coding/en-US/C/.svn/prop-base/C.xml.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 8 +text/xml +END diff --git a/defensive-coding/en-US/C/.svn/prop-base/Language.xml.svn-base b/defensive-coding/en-US/C/.svn/prop-base/Language.xml.svn-base new file mode 100644 index 0000000..bfec7d5 --- /dev/null +++ b/defensive-coding/en-US/C/.svn/prop-base/Language.xml.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 8 +text/xml +END diff --git a/defensive-coding/en-US/C/.svn/prop-base/Libc.xml.svn-base b/defensive-coding/en-US/C/.svn/prop-base/Libc.xml.svn-base new file mode 100644 index 0000000..bfec7d5 --- /dev/null +++ b/defensive-coding/en-US/C/.svn/prop-base/Libc.xml.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 8 +text/xml +END diff --git a/defensive-coding/en-US/C/.svn/prop-base/schemas.xml.svn-base b/defensive-coding/en-US/C/.svn/prop-base/schemas.xml.svn-base new file mode 100644 index 0000000..bfec7d5 --- /dev/null +++ b/defensive-coding/en-US/C/.svn/prop-base/schemas.xml.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 8 +text/xml +END diff --git a/defensive-coding/en-US/C/.svn/text-base/Allocators.xml.svn-base b/defensive-coding/en-US/C/.svn/text-base/Allocators.xml.svn-base new file mode 100644 index 0000000..974b6c1 --- /dev/null +++ b/defensive-coding/en-US/C/.svn/text-base/Allocators.xml.svn-base @@ -0,0 +1,207 @@ + + +
+ Memory allocators + +
+ <function>malloc</function> and related functions + + The C library interfaces for memory allocation are provided by + malloc, free and + realloc, and the + calloc function. In addition to these + generic functions, there are derived functions such as + strdup which perform allocation using + malloc internally, but do not return + untyped heap memory (which could be used for any object). + + + The C compiler knows about these functions and can use their + expected behavior for optimizations. For instance, the compiler + assumes that an existing pointer (or a pointer derived from an + existing pointer by arithmetic) will not point into the memory + area returned by malloc. + + + If the allocation fails, realloc does not + free the old pointer. Therefore, the idiom ptr = + realloc(ptr, size); is wrong because the memory + pointed to by ptr leaks in case of an error. + +
+ Use-after-free errors + + After free, the pointer is invalid. + Further pointer dereferences are not allowed (and are usually + detected by valgrind). Less obvious + is that any use of the old pointer value is + not allowed, either. In particular, comparisons with any other + pointer (or the null pointer) are undefined according to the C + standard. + + + The same rules apply to realloc if the + memory area cannot be enlarged in-place. For instance, the + compiler may assume that a comparison between the old and new + pointer will always return false, so it is impossible to detect + movement this way. + +
+
+ Handling memory allocation errors + + Recovering from out-of-memory errors is often difficult or even + impossible. In these cases, malloc and + other allocation functions return a null pointer. Dereferencing + this pointer lead to a crash. Such dereferences can even be + exploitable for code execution if the dereference is combined + with an array subscript. + + + In general, if you cannot check all allocation calls and + handle failure, you should abort the program on allocation + failure, and not rely on the null pointer dereference to + terminate the process. See + + for related memory allocation concerns. + +
+
+ +
+ <function>alloca</function> and other forms of stack-based + allocation + + Allocation on the stack is risky because stack overflow checking + is implicit. There is a guard page at the end of the memory + area reserved for the stack. If the program attempts to read + from or write to this guard page, a SIGSEGV + signal is generated and the program typically terminates. + + + This is sufficient for detecting typical stack overflow + situations such as unbounded recursion, but it fails when the + stack grows in increments larger than the size of the guard + page. In this case, it is possible that the stack pointer ends + up pointing into a memory area which has been allocated for a + different purposes. Such misbehavior can be exploitable. + + + A common source for large stack growth are calls to + alloca and related functions such as + strdupa. These functions should be avoided + because of the lack of error checking. (They can be used safely + if the allocated size is less than the page size (typically, + 4096 bytes), but this case is relatively rare.) Additionally, + relying on alloca makes it more difficult + to reorgnize the code because it is not allowed to use the + pointer after the function calling alloca + has returned, even if this function has been inlined into its + caller. + + + Similar concerns apply to variable-length + arrays (VLAs), a feature of the C99 standard which + started as a GNU extension. For large objects exceeding the + page size, there is no error checking, either. + + + In both cases, negative or very large sizes can trigger a + stack-pointer wraparound, and the stack pointer and end up + pointing into caller stack frames, which is fatal and can be + exploitable. + + + If you want to use alloca or VLAs for + performance reasons, consider using a small on-stack array (less + than the page size, large enough to fulfill most requests). If + the requested size is small enough, use the on-stack array. + Otherwise, call malloc. When exiting the + function, check if malloc had been called, + and free the buffer as needed. + +
+ +
+ Array allocation + + When allocating arrays, it is important to check for overflows. + The calloc function performs such checks. + + + If malloc or realloc + is used, the size check must be written manually. For instance, + to allocate an array of n elements of type + T, check that the requested size is not + greater than n / sizeof(T). + +
+ +
+ Custom memory allocators + + Custom memory allocates come in two forms: replacements for + malloc, and completely different interfaces + for memory management. Both approaches can reduce the + effectiveness of valgrind and similar + tools, and the heap corruption detection provided by GNU libc, so + they should be avoided. + + + Memory allocators are difficult to write and contain many + performance and security pitfalls. + + + + + When computing array sizes or rounding up allocation + requests (to the next allocation granularity, or for + alignment purposes), checks for arithmetic overflow are + required. + + + + + Size computations for array allocations need overflow + checking. See . + + + + + It can be difficult to beat well-tuned general-purpose + allocators. In micro-benchmarks, pool allocators can show + huge wins, and size-specific pools can reduce internal + fragmentation. But often, utilization of individual pools + is poor, and + + + +
+ +
+ Conservative garbage collection + + Garbage collection can be an alternative to explicit memory + management using malloc and + free. The Boehm-Dehmers-Weiser allocator + can be used from C programs, with minimal type annotations. + Performance is competitive with malloc on + 64-bit architectures, especially for multi-threaded programs. + The stop-the-world pauses may be problematic for some real-time + applications, though. + + + However, using a conservative garbage collector may reduce + opertunities for code reduce because once one library in a + program uses garbage collection, the whole process memory needs + to be subject to it, so that no pointers are missed. The + Boehm-Dehmers-Weiser collector also reserves certain signals for + internal use, so it is not fully transparent to the rest of the + program. + +
+
+ diff --git a/defensive-coding/en-US/C/.svn/text-base/C.xml.svn-base b/defensive-coding/en-US/C/.svn/text-base/C.xml.svn-base new file mode 100644 index 0000000..3dd659a --- /dev/null +++ b/defensive-coding/en-US/C/.svn/text-base/C.xml.svn-base @@ -0,0 +1,11 @@ + + + + The C Programming Language + + + + + + diff --git a/defensive-coding/en-US/C/.svn/text-base/Language.xml.svn-base b/defensive-coding/en-US/C/.svn/text-base/Language.xml.svn-base new file mode 100644 index 0000000..db7cc5d --- /dev/null +++ b/defensive-coding/en-US/C/.svn/text-base/Language.xml.svn-base @@ -0,0 +1,150 @@ + + +
+ The core language + + C provides no memory safety. Most recommendations in this section + deal with this aspect of the language. + + +
+ Undefined behavior + + Some C constructs are defined to be undefined by the C standard. + This does not only mean that the standard does not describe + what happens when the construct is executed. It also allows + optimizing compilers such as GCC to assume that this particular + construct is never reached. In some cases, this has caused + GCC to optimize security checks away. (This is not a flaw in GCC + or the C language. But C certainly has some areas which are more + difficult to use than others.) + + + + Common sources of undefined behavior are: + + + out-of-bounds array accesses + null pointer dereferences + overflow in signed integer arithmetic + +
+ +
+ Recommendations for pointers and array handling + + Always keep track of the size of the array you are working with. + Often, code is more obviously correct when you keep a pointer + past the last element of the array, and calculate the number of + remaining elements by substracting the current position from + that pointer. The alternative, updating a separate variable + every time when the position is advanced, is usually less + obviously correct. + + + + shows how to extract Pascal-style strings from a character + buffer. The two pointers kept for length checks are + inend and outend. + inp and outp are the + respective positions. + The number of input bytes is checked using the expression + len > (size_t)(inend - inp). + The cast silences a compiler warning; + inend is always larger than + inp. + + + Array processing in C + + + + It is important that the length checks always have the form + len > (size_t)(inend - inp), where + len is a variable of type + size_t which denotes the total + number of bytes which are about to be read or written next. In + general, it is not safe to fold multiple such checks into one, + as in len1 + len2 > (size_t)(inend - inp), + because the expression on the left can overflow or wrap around + (see ), and it + no longer reflects the number of bytes to be processed. + +
+ +
+ Recommendations for integer arithmetic + + Overflow in signed integer arithmetic is undefined. This means + that it is not possible to check for overflow after it happened, + see . + + + Incorrect overflow detection in C + + + + The following approaches can be used to check for overflow, + without actually causing it. + + + + + Use a wider type to perform the calculation, check that the + result is within bounds, and convert the result to the + original type. All intermediate results must be checked in + this way. + + + + + Perform the calculation in the corresponding unsigned type + and use bit fiddling to detect the overflow. + + + + + Compute bounds for acceptable input values which are known + to avoid overflow, and reject other values. This is the + preferred way for overflow checking on multiplications, + see . + + + + + + Overflow checking for unsigned multiplication + + + + Basic arithmetic operations a commutative, so for bounds checks, + there are two different but mathematically equivalent + expressions. Sometimes, one of the expressions results in + better code because parts of it can be reduced to a constant. + This applies to overflow checks for multiplication a * + b involving a constant a, where the + expression is reduced to b > C for some + constant C determined at compile time. The + other expression, b && a > ((unsigned)-1) / + b, is more difficult to optimize at compile time. + + + When a value is converted to a signed integer, GCC always + chooses the result based on 2's complement arithmetic. This GCC + extension (which is also implemented by other compilers) helps a + lot when implementing overflow checks. + + + Legacy code should be compiled with the + GCC option. As a result, GCC will provide 2's complement + semantics for integer arithmetic, including defined behavior on + integer overflow. + +
+
diff --git a/defensive-coding/en-US/C/.svn/text-base/Libc.xml.svn-base b/defensive-coding/en-US/C/.svn/text-base/Libc.xml.svn-base new file mode 100644 index 0000000..6173bf0 --- /dev/null +++ b/defensive-coding/en-US/C/.svn/text-base/Libc.xml.svn-base @@ -0,0 +1,227 @@ + + +
+ The C standard library + + Parts of the C standard library (and the UNIX and GNU extensions) + are difficult to use, so you shoud avoid them. + + + Please check the applicable documentation before using the + recommended replacements. Many of these functions allocate + buffers using malloc which your code must + deallocate explicitly using free. + +
+ Absolutely banned interfaces + + The functions listed below must not be used because they are + almost always unsafe. Use the indicated replacements instead. + + + gets + ⟶ fgets + getwd + ⟶ getcwd + or get_current_dir_name + + + readdir_rreaddir + + + + + + + realpath (with a non-NULL second parameter) + ⟶ realpath with NULL as the second parameter, + or canonicalize_file_name + + + + + + + The constants listed below must not be used, either. Instead, + code must allocate memory dynamically and use interfaces with + length checking. + + + + + NAME_MAX (limit not actually enforced by + the kernel) + + + + + PATH_MAX (limit not actually enforced by + the kernel) + + + + + _PC_NAME_MAX (This limit, returned by the + pathconf function, is not enforced by + the kernel.) + + + + + _PC_PATH_MAX (This limit, returned by the + pathconf function, is not enforced by + the kernel.) + + + + + The following structure members must not be used. + + + + + f_namemax in struct + statvfs (limit not actually enforced by the kernel, + see _PC_NAME_MAX above) + + + +
+
+ Functions to avoid + + The following string manipulation functions can be used securely + in principle, but their use should be avoided because they are + difficult to use correctly. Calls to these functions can be + replaced with asprintf or + vasprintf. (For non-GNU targets, these + functions are available from Gnulib.) In some cases, the + snprintf function might be a suitable + replacement, see . + + + sprintf + strcat + strcpy + vsprintf + + + Use the indicated replacements for the functions below. + + + + + alloca ⟶ + malloc and free + (see ) + + + + + putenv ⟶ + explicit envp argument in process creation + (see ) + + + + + setenv ⟶ + explicit envp argument in process creation + (see ) + + + + + strdupa ⟶ + strdup and free + (see ) + + + + + strndupa ⟶ + strndup and free + (see ) + + + + + system ⟶ + posix_spawn + or fork/execve/ + (see ) + + + + + unsetenv ⟶ + explicit envp argument in process creation + (see ) + + + +
+
+ String Functions With Explicit Length Arguments + + The snprintf function provides a way to + construct a string in a statically-sized buffer. (If the buffer + size is dynamic, use asprintf instead.) + + + + + + The second argument to the snprintf should + always be the size of the buffer in the first argument (which + should be a character array). Complex pointer and length + arithmetic can introduce errors and nullify the security + benefits of snprintf. If you need to + construct a string iteratively, by repeatedly appending + fragments, consider constructing the string on the heap, + increasing the buffer with realloc as + needed. (snprintf does not support + overlapping the result buffer with argument strings.) + + + If you use vsnprintf (or + snprintf) with a format string which is not + a constant, but a function argument, it is important to annotate + the function with a format function + attribute, so that GCC can warn about misuse of your function + (see ). + + + The <literal>format</literal> function attribute + + + + There are other functions which operator on NUL-terminated + strings and take a length argument which affects the number of + bytes written to the destination: strncpy, + strncat, and stpncpy. + These functions do not ensure that the result string is + NUL-terminated. For strncpy, + NUL termination can be added this way: + + + + + + Some systems support strlcpy and + strlcat functions which behave this way, + but these functions are not part of GNU libc. Using + snprintf with a suitable format string is a + simple (albeit slightly slower) replacement. + +
+
diff --git a/defensive-coding/en-US/C/.svn/text-base/schemas.xml.svn-base b/defensive-coding/en-US/C/.svn/text-base/schemas.xml.svn-base new file mode 100644 index 0000000..8e84245 --- /dev/null +++ b/defensive-coding/en-US/C/.svn/text-base/schemas.xml.svn-base @@ -0,0 +1,4 @@ + + + + diff --git a/defensive-coding/en-US/C/Allocators.xml b/defensive-coding/en-US/C/Allocators.xml new file mode 100644 index 0000000..974b6c1 --- /dev/null +++ b/defensive-coding/en-US/C/Allocators.xml @@ -0,0 +1,207 @@ + + +
+ Memory allocators + +
+ <function>malloc</function> and related functions + + The C library interfaces for memory allocation are provided by + malloc, free and + realloc, and the + calloc function. In addition to these + generic functions, there are derived functions such as + strdup which perform allocation using + malloc internally, but do not return + untyped heap memory (which could be used for any object). + + + The C compiler knows about these functions and can use their + expected behavior for optimizations. For instance, the compiler + assumes that an existing pointer (or a pointer derived from an + existing pointer by arithmetic) will not point into the memory + area returned by malloc. + + + If the allocation fails, realloc does not + free the old pointer. Therefore, the idiom ptr = + realloc(ptr, size); is wrong because the memory + pointed to by ptr leaks in case of an error. + +
+ Use-after-free errors + + After free, the pointer is invalid. + Further pointer dereferences are not allowed (and are usually + detected by valgrind). Less obvious + is that any use of the old pointer value is + not allowed, either. In particular, comparisons with any other + pointer (or the null pointer) are undefined according to the C + standard. + + + The same rules apply to realloc if the + memory area cannot be enlarged in-place. For instance, the + compiler may assume that a comparison between the old and new + pointer will always return false, so it is impossible to detect + movement this way. + +
+
+ Handling memory allocation errors + + Recovering from out-of-memory errors is often difficult or even + impossible. In these cases, malloc and + other allocation functions return a null pointer. Dereferencing + this pointer lead to a crash. Such dereferences can even be + exploitable for code execution if the dereference is combined + with an array subscript. + + + In general, if you cannot check all allocation calls and + handle failure, you should abort the program on allocation + failure, and not rely on the null pointer dereference to + terminate the process. See + + for related memory allocation concerns. + +
+
+ +
+ <function>alloca</function> and other forms of stack-based + allocation + + Allocation on the stack is risky because stack overflow checking + is implicit. There is a guard page at the end of the memory + area reserved for the stack. If the program attempts to read + from or write to this guard page, a SIGSEGV + signal is generated and the program typically terminates. + + + This is sufficient for detecting typical stack overflow + situations such as unbounded recursion, but it fails when the + stack grows in increments larger than the size of the guard + page. In this case, it is possible that the stack pointer ends + up pointing into a memory area which has been allocated for a + different purposes. Such misbehavior can be exploitable. + + + A common source for large stack growth are calls to + alloca and related functions such as + strdupa. These functions should be avoided + because of the lack of error checking. (They can be used safely + if the allocated size is less than the page size (typically, + 4096 bytes), but this case is relatively rare.) Additionally, + relying on alloca makes it more difficult + to reorgnize the code because it is not allowed to use the + pointer after the function calling alloca + has returned, even if this function has been inlined into its + caller. + + + Similar concerns apply to variable-length + arrays (VLAs), a feature of the C99 standard which + started as a GNU extension. For large objects exceeding the + page size, there is no error checking, either. + + + In both cases, negative or very large sizes can trigger a + stack-pointer wraparound, and the stack pointer and end up + pointing into caller stack frames, which is fatal and can be + exploitable. + + + If you want to use alloca or VLAs for + performance reasons, consider using a small on-stack array (less + than the page size, large enough to fulfill most requests). If + the requested size is small enough, use the on-stack array. + Otherwise, call malloc. When exiting the + function, check if malloc had been called, + and free the buffer as needed. + +
+ +
+ Array allocation + + When allocating arrays, it is important to check for overflows. + The calloc function performs such checks. + + + If malloc or realloc + is used, the size check must be written manually. For instance, + to allocate an array of n elements of type + T, check that the requested size is not + greater than n / sizeof(T). + +
+ +
+ Custom memory allocators + + Custom memory allocates come in two forms: replacements for + malloc, and completely different interfaces + for memory management. Both approaches can reduce the + effectiveness of valgrind and similar + tools, and the heap corruption detection provided by GNU libc, so + they should be avoided. + + + Memory allocators are difficult to write and contain many + performance and security pitfalls. + + + + + When computing array sizes or rounding up allocation + requests (to the next allocation granularity, or for + alignment purposes), checks for arithmetic overflow are + required. + + + + + Size computations for array allocations need overflow + checking. See . + + + + + It can be difficult to beat well-tuned general-purpose + allocators. In micro-benchmarks, pool allocators can show + huge wins, and size-specific pools can reduce internal + fragmentation. But often, utilization of individual pools + is poor, and + + + +
+ +
+ Conservative garbage collection + + Garbage collection can be an alternative to explicit memory + management using malloc and + free. The Boehm-Dehmers-Weiser allocator + can be used from C programs, with minimal type annotations. + Performance is competitive with malloc on + 64-bit architectures, especially for multi-threaded programs. + The stop-the-world pauses may be problematic for some real-time + applications, though. + + + However, using a conservative garbage collector may reduce + opertunities for code reduce because once one library in a + program uses garbage collection, the whole process memory needs + to be subject to it, so that no pointers are missed. The + Boehm-Dehmers-Weiser collector also reserves certain signals for + internal use, so it is not fully transparent to the rest of the + program. + +
+
+ diff --git a/defensive-coding/en-US/C/C.xml b/defensive-coding/en-US/C/C.xml new file mode 100644 index 0000000..3dd659a --- /dev/null +++ b/defensive-coding/en-US/C/C.xml @@ -0,0 +1,11 @@ + + + + The C Programming Language + + + + + + diff --git a/defensive-coding/en-US/C/Language.xml b/defensive-coding/en-US/C/Language.xml new file mode 100644 index 0000000..db7cc5d --- /dev/null +++ b/defensive-coding/en-US/C/Language.xml @@ -0,0 +1,150 @@ + + +
+ The core language + + C provides no memory safety. Most recommendations in this section + deal with this aspect of the language. + + +
+ Undefined behavior + + Some C constructs are defined to be undefined by the C standard. + This does not only mean that the standard does not describe + what happens when the construct is executed. It also allows + optimizing compilers such as GCC to assume that this particular + construct is never reached. In some cases, this has caused + GCC to optimize security checks away. (This is not a flaw in GCC + or the C language. But C certainly has some areas which are more + difficult to use than others.) + + + + Common sources of undefined behavior are: + + + out-of-bounds array accesses + null pointer dereferences + overflow in signed integer arithmetic + +
+ +
+ Recommendations for pointers and array handling + + Always keep track of the size of the array you are working with. + Often, code is more obviously correct when you keep a pointer + past the last element of the array, and calculate the number of + remaining elements by substracting the current position from + that pointer. The alternative, updating a separate variable + every time when the position is advanced, is usually less + obviously correct. + + + + shows how to extract Pascal-style strings from a character + buffer. The two pointers kept for length checks are + inend and outend. + inp and outp are the + respective positions. + The number of input bytes is checked using the expression + len > (size_t)(inend - inp). + The cast silences a compiler warning; + inend is always larger than + inp. + + + Array processing in C + + + + It is important that the length checks always have the form + len > (size_t)(inend - inp), where + len is a variable of type + size_t which denotes the total + number of bytes which are about to be read or written next. In + general, it is not safe to fold multiple such checks into one, + as in len1 + len2 > (size_t)(inend - inp), + because the expression on the left can overflow or wrap around + (see ), and it + no longer reflects the number of bytes to be processed. + +
+ +
+ Recommendations for integer arithmetic + + Overflow in signed integer arithmetic is undefined. This means + that it is not possible to check for overflow after it happened, + see . + + + Incorrect overflow detection in C + + + + The following approaches can be used to check for overflow, + without actually causing it. + + + + + Use a wider type to perform the calculation, check that the + result is within bounds, and convert the result to the + original type. All intermediate results must be checked in + this way. + + + + + Perform the calculation in the corresponding unsigned type + and use bit fiddling to detect the overflow. + + + + + Compute bounds for acceptable input values which are known + to avoid overflow, and reject other values. This is the + preferred way for overflow checking on multiplications, + see . + + + + + + Overflow checking for unsigned multiplication + + + + Basic arithmetic operations a commutative, so for bounds checks, + there are two different but mathematically equivalent + expressions. Sometimes, one of the expressions results in + better code because parts of it can be reduced to a constant. + This applies to overflow checks for multiplication a * + b involving a constant a, where the + expression is reduced to b > C for some + constant C determined at compile time. The + other expression, b && a > ((unsigned)-1) / + b, is more difficult to optimize at compile time. + + + When a value is converted to a signed integer, GCC always + chooses the result based on 2's complement arithmetic. This GCC + extension (which is also implemented by other compilers) helps a + lot when implementing overflow checks. + + + Legacy code should be compiled with the + GCC option. As a result, GCC will provide 2's complement + semantics for integer arithmetic, including defined behavior on + integer overflow. + +
+
diff --git a/defensive-coding/en-US/C/Libc.xml b/defensive-coding/en-US/C/Libc.xml new file mode 100644 index 0000000..6173bf0 --- /dev/null +++ b/defensive-coding/en-US/C/Libc.xml @@ -0,0 +1,227 @@ + + +
+ The C standard library + + Parts of the C standard library (and the UNIX and GNU extensions) + are difficult to use, so you shoud avoid them. + + + Please check the applicable documentation before using the + recommended replacements. Many of these functions allocate + buffers using malloc which your code must + deallocate explicitly using free. + +
+ Absolutely banned interfaces + + The functions listed below must not be used because they are + almost always unsafe. Use the indicated replacements instead. + + + gets + ⟶ fgets + getwd + ⟶ getcwd + or get_current_dir_name + + + readdir_rreaddir + + + + + + + realpath (with a non-NULL second parameter) + ⟶ realpath with NULL as the second parameter, + or canonicalize_file_name + + + + + + + The constants listed below must not be used, either. Instead, + code must allocate memory dynamically and use interfaces with + length checking. + + + + + NAME_MAX (limit not actually enforced by + the kernel) + + + + + PATH_MAX (limit not actually enforced by + the kernel) + + + + + _PC_NAME_MAX (This limit, returned by the + pathconf function, is not enforced by + the kernel.) + + + + + _PC_PATH_MAX (This limit, returned by the + pathconf function, is not enforced by + the kernel.) + + + + + The following structure members must not be used. + + + + + f_namemax in struct + statvfs (limit not actually enforced by the kernel, + see _PC_NAME_MAX above) + + + +
+
+ Functions to avoid + + The following string manipulation functions can be used securely + in principle, but their use should be avoided because they are + difficult to use correctly. Calls to these functions can be + replaced with asprintf or + vasprintf. (For non-GNU targets, these + functions are available from Gnulib.) In some cases, the + snprintf function might be a suitable + replacement, see . + + + sprintf + strcat + strcpy + vsprintf + + + Use the indicated replacements for the functions below. + + + + + alloca ⟶ + malloc and free + (see ) + + + + + putenv ⟶ + explicit envp argument in process creation + (see ) + + + + + setenv ⟶ + explicit envp argument in process creation + (see ) + + + + + strdupa ⟶ + strdup and free + (see ) + + + + + strndupa ⟶ + strndup and free + (see ) + + + + + system ⟶ + posix_spawn + or fork/execve/ + (see ) + + + + + unsetenv ⟶ + explicit envp argument in process creation + (see ) + + + +
+
+ String Functions With Explicit Length Arguments + + The snprintf function provides a way to + construct a string in a statically-sized buffer. (If the buffer + size is dynamic, use asprintf instead.) + + + + + + The second argument to the snprintf should + always be the size of the buffer in the first argument (which + should be a character array). Complex pointer and length + arithmetic can introduce errors and nullify the security + benefits of snprintf. If you need to + construct a string iteratively, by repeatedly appending + fragments, consider constructing the string on the heap, + increasing the buffer with realloc as + needed. (snprintf does not support + overlapping the result buffer with argument strings.) + + + If you use vsnprintf (or + snprintf) with a format string which is not + a constant, but a function argument, it is important to annotate + the function with a format function + attribute, so that GCC can warn about misuse of your function + (see ). + + + The <literal>format</literal> function attribute + + + + There are other functions which operator on NUL-terminated + strings and take a length argument which affects the number of + bytes written to the destination: strncpy, + strncat, and stpncpy. + These functions do not ensure that the result string is + NUL-terminated. For strncpy, + NUL termination can be added this way: + + + + + + Some systems support strlcpy and + strlcat functions which behave this way, + but these functions are not part of GNU libc. Using + snprintf with a suitable format string is a + simple (albeit slightly slower) replacement. + +
+
diff --git a/defensive-coding/en-US/C/schemas.xml b/defensive-coding/en-US/C/schemas.xml new file mode 100644 index 0000000..8e84245 --- /dev/null +++ b/defensive-coding/en-US/C/schemas.xml @@ -0,0 +1,4 @@ + + + + diff --git a/defensive-coding/en-US/C/snippets/Arithmetic-add.xml b/defensive-coding/en-US/C/snippets/Arithmetic-add.xml new file mode 100644 index 0000000..3c67512 --- /dev/null +++ b/defensive-coding/en-US/C/snippets/Arithmetic-add.xml @@ -0,0 +1,21 @@ + + + + +void report_overflow(void); + +int +add(int a, int b) +{ + int result = a + b; + if (a < 0 || b < 0) { + return -1; + } + // The compiler can optimize away the following if statement. + if (result < 0) { + report_overflow(); + } + return result; +} + diff --git a/defensive-coding/en-US/C/snippets/Arithmetic-mult.xml b/defensive-coding/en-US/C/snippets/Arithmetic-mult.xml new file mode 100644 index 0000000..ecb27a0 --- /dev/null +++ b/defensive-coding/en-US/C/snippets/Arithmetic-mult.xml @@ -0,0 +1,14 @@ + + + + +unsigned +mul(unsigned a, unsigned b) +{ + if (b && a > ((unsigned)-1) / b) { + report_overflow(); + } + return a * b; +} + diff --git a/defensive-coding/en-US/C/snippets/Pointers-remaining.xml b/defensive-coding/en-US/C/snippets/Pointers-remaining.xml new file mode 100644 index 0000000..f527d03 --- /dev/null +++ b/defensive-coding/en-US/C/snippets/Pointers-remaining.xml @@ -0,0 +1,49 @@ + + + + +ssize_t +extract_strings(const char *in, size_t inlen, char **out, size_t outlen) +{ + const char *inp = in; + const char *inend = in + inlen; + char **outp = out; + char **outend = out + outlen; + + while (inp != inend) { + size_t len; + char *s; + if (outp == outend) { + errno = ENOSPC; + goto err; + } + len = (unsigned char)*inp; + ++inp; + if (len > (size_t)(inend - inp)) { + errno = EINVAL; + goto err; + } + s = malloc(len + 1); + if (s == NULL) { + goto err; + } + memcpy(s, inp, len); + inp += len; + s[len] = '\0'; + *outp = s; + ++outp; + } + return outp - out; +err: + { + int errno_old = errno; + while (out != outp) { + free(*out); + ++out; + } + errno = errno_old; + } + return -1; +} + diff --git a/defensive-coding/en-US/C/snippets/String-Functions-format.xml b/defensive-coding/en-US/C/snippets/String-Functions-format.xml new file mode 100644 index 0000000..519f127 --- /dev/null +++ b/defensive-coding/en-US/C/snippets/String-Functions-format.xml @@ -0,0 +1,18 @@ + + + + +void log_format(const char *format, ...) __attribute__((format(printf, 1, 2))); + +void +log_format(const char *format, ...) +{ + char buf[1000]; + va_list ap; + va_start(ap, format); + vsnprintf(buf, sizeof(buf), format, ap); + va_end(ap); + log_string(buf); +} + diff --git a/defensive-coding/en-US/C/snippets/String-Functions-snprintf.xml b/defensive-coding/en-US/C/snippets/String-Functions-snprintf.xml new file mode 100644 index 0000000..dc790d8 --- /dev/null +++ b/defensive-coding/en-US/C/snippets/String-Functions-snprintf.xml @@ -0,0 +1,8 @@ + + + + +char fraction[30]; +snprintf(fraction, sizeof(fraction), "%d/%d", numerator, denominator); + diff --git a/defensive-coding/en-US/C/snippets/String-Functions-strncpy.xml b/defensive-coding/en-US/C/snippets/String-Functions-strncpy.xml new file mode 100644 index 0000000..bdbdd08 --- /dev/null +++ b/defensive-coding/en-US/C/snippets/String-Functions-strncpy.xml @@ -0,0 +1,9 @@ + + + + +char buf[10]; +strncpy(buf, data, sizeof(buf)); +buf[sizeof(buf) - 1] = '\0'; + diff --git a/defensive-coding/en-US/CXX/.svn/all-wcprops b/defensive-coding/en-US/CXX/.svn/all-wcprops new file mode 100644 index 0000000..5011e3d --- /dev/null +++ b/defensive-coding/en-US/CXX/.svn/all-wcprops @@ -0,0 +1,29 @@ +K 25 +svn:wc:ra_dav:version-url +V 69 +/repos/product-security/!svn/ver/292/defensive-coding/trunk/en-US/CXX +END +CXX.xml +K 25 +svn:wc:ra_dav:version-url +V 77 +/repos/product-security/!svn/ver/281/defensive-coding/trunk/en-US/CXX/CXX.xml +END +Language.xml +K 25 +svn:wc:ra_dav:version-url +V 82 +/repos/product-security/!svn/ver/281/defensive-coding/trunk/en-US/CXX/Language.xml +END +schemas.xml +K 25 +svn:wc:ra_dav:version-url +V 81 +/repos/product-security/!svn/ver/292/defensive-coding/trunk/en-US/CXX/schemas.xml +END +Std.xml +K 25 +svn:wc:ra_dav:version-url +V 77 +/repos/product-security/!svn/ver/281/defensive-coding/trunk/en-US/CXX/Std.xml +END diff --git a/defensive-coding/en-US/CXX/.svn/dir-prop-base b/defensive-coding/en-US/CXX/.svn/dir-prop-base new file mode 100644 index 0000000..b0e5252 --- /dev/null +++ b/defensive-coding/en-US/CXX/.svn/dir-prop-base @@ -0,0 +1,6 @@ +K 10 +svn:ignore +V 9 +snippets + +END diff --git a/defensive-coding/en-US/CXX/.svn/entries b/defensive-coding/en-US/CXX/.svn/entries new file mode 100644 index 0000000..20c613a --- /dev/null +++ b/defensive-coding/en-US/CXX/.svn/entries @@ -0,0 +1,164 @@ +10 + +dir +305 +https://svn.devel.redhat.com/repos/product-security/defensive-coding/trunk/en-US/CXX +https://svn.devel.redhat.com/repos/product-security + + + +2012-12-14T10:18:44.472257Z +292 +fweimer@REDHAT.COM +has-props + + + + + + + + + + + + + +9bd5cf0f-f2b3-0410-b1a9-d5c590f50bf1 + +CXX.xml +file + + + + +2013-01-10T17:17:40.360763Z +b0f0bf8b20378408157b933ace95025b +2012-12-13T13:25:23.103424Z +281 +fweimer@REDHAT.COM +has-props + + + + + + + + + + + + + + + + + + + + +419 + +Language.xml +file + + + + +2013-01-10T17:17:40.361763Z +0c223f5c8e653b24ad9ee512a9347ff6 +2012-12-13T13:25:23.103424Z +281 +fweimer@REDHAT.COM +has-props + + + + + + + + + + + + + + + + + + + + +7232 + +schemas.xml +file + + + + +2013-01-10T17:17:40.361763Z +769bc2635d36b318161574a1adf2f6e7 +2012-12-14T10:18:44.472257Z +292 +fweimer@REDHAT.COM +has-props + + + + + + + + + + + + + + + + + + + + +150 + +Std.xml +file + + + + +2013-01-10T17:17:40.362763Z +43d4998b7a340602a1cfb058cac483c9 +2012-12-13T13:25:23.103424Z +281 +fweimer@REDHAT.COM +has-props + + + + + + + + + + + + + + + + + + + + +1392 + diff --git a/defensive-coding/en-US/CXX/.svn/prop-base/CXX.xml.svn-base b/defensive-coding/en-US/CXX/.svn/prop-base/CXX.xml.svn-base new file mode 100644 index 0000000..bfec7d5 --- /dev/null +++ b/defensive-coding/en-US/CXX/.svn/prop-base/CXX.xml.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 8 +text/xml +END diff --git a/defensive-coding/en-US/CXX/.svn/prop-base/Language.xml.svn-base b/defensive-coding/en-US/CXX/.svn/prop-base/Language.xml.svn-base new file mode 100644 index 0000000..bfec7d5 --- /dev/null +++ b/defensive-coding/en-US/CXX/.svn/prop-base/Language.xml.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 8 +text/xml +END diff --git a/defensive-coding/en-US/CXX/.svn/prop-base/Std.xml.svn-base b/defensive-coding/en-US/CXX/.svn/prop-base/Std.xml.svn-base new file mode 100644 index 0000000..bfec7d5 --- /dev/null +++ b/defensive-coding/en-US/CXX/.svn/prop-base/Std.xml.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 8 +text/xml +END diff --git a/defensive-coding/en-US/CXX/.svn/prop-base/schemas.xml.svn-base b/defensive-coding/en-US/CXX/.svn/prop-base/schemas.xml.svn-base new file mode 100644 index 0000000..bfec7d5 --- /dev/null +++ b/defensive-coding/en-US/CXX/.svn/prop-base/schemas.xml.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 8 +text/xml +END diff --git a/defensive-coding/en-US/CXX/.svn/text-base/CXX.xml.svn-base b/defensive-coding/en-US/CXX/.svn/text-base/CXX.xml.svn-base new file mode 100644 index 0000000..fccfb75 --- /dev/null +++ b/defensive-coding/en-US/CXX/.svn/text-base/CXX.xml.svn-base @@ -0,0 +1,10 @@ + + + + The C++ Programming Language + + + + + diff --git a/defensive-coding/en-US/CXX/.svn/text-base/Language.xml.svn-base b/defensive-coding/en-US/CXX/.svn/text-base/Language.xml.svn-base new file mode 100644 index 0000000..9dbc4f3 --- /dev/null +++ b/defensive-coding/en-US/CXX/.svn/text-base/Language.xml.svn-base @@ -0,0 +1,186 @@ + + +
+ The core language + + C++ includes a large subset of the C language. As far as the C + subset is used, the recommendations in apply. + + +
+ Array allocation with <literal>operator new[]</literal> + + For very large values of n, an expression + like new T[n] can return a pointer to a heap + region which is too small. In other words, not all array + elements are actually backed with heap memory reserved to the + array. Current GCC versions generate code that performs a + computation of the form sizeof(T) * size_t(n) + + cookie_size, where cookie_size is + currently at most 8. This computation can overflow, and + GCC-generated code does not detect this. + + + The std::vector template can be used instead + an explicit array allocation. (The GCC implementation detects + overflow internally.) + + + If there is no alternative to operator new[], + code which allocates arrays with a variable length must check + for overflow manually. For the new T[n] + example, the size check could be n || (n > 0 && + n > (size_t(-1) - 8) / sizeof(T)). (See .) If there are + additional dimensions (which must be constants according to the + C++ standard), these should be included as factors in the + divisor. + + + These countermeasures prevent out-of-bounds writes and potential + code execution. Very large memory allocations can still lead to + a denial of service. + contains suggestions for mitigating this problem when processing + untrusted data. + + + See + for array allocation advice for C-style memory allocation. + +
+ +
+ Overloading + + Do not overload functions with versions that have different + security characteristics. For instance, do not implement a + function strcat which works on + std::string arguments. Similarly, do not name + methods after such functions. + +
+
+ ABI compatibility and preparing for security updates + + A stable binary interface (ABI) is vastly preferred for security + updates. Without a stable ABI, all reverse dependencies need + recompiling, which can be a lot of work and could even be + impossible in some cases. Ideally, a security update only + updates a single dynamic shared object, and is picked up + automatically after restarting affected processes. + + + Outside of extremely performance-critical code, you should + ensure that a wide range of changes is possible without breaking + ABI. Some very basic guidelines are: + + + + + Avoid inline functions. + + + + + Use the pointer-to-implementation idiom. + + + + + Try to avoid templates. Use them if the increased type + safety provides a benefit to the programmer. + + + + + Move security-critical code out of templated code, so that + it can be patched in a central place if necessary. + + + + + The KDE project publishes a document with more extensive + guidelines on ABI-preserving changes to C++ code, Policies/Binary + Compatibility Issues With C++ + (d-pointer refers to the + pointer-to-implementation idiom). + +
+ +
+ C++0X and C++11 support + + GCC offers different language compatibility modes: + + + + + for the original 1998 C++ + standard + + + + + for the 1998 standard with the + changes from the TR1 technical report + + + + + for the 2011 C++ standard. This + option should not be used. + + + + + for several different versions + of C++11 support in development, depending on the GCC + version. This option should not be used. + + + + + + For each of these flags, there are variants which also enable + GNU extensions (mostly language features also found in C99 or + C11): , + , . + Again, should not be used. + + + If you enable C++11 support, the ABI of the standard C++ library + libstdc++ will change in subtle ways. + Currently, no C++ libraries are compiled in C++11 mode, so if + you compile your code in C++11 mode, it will be incompatible + with the rest of the system. Unfortunately, this is also the + case if you do not use any C++11 features. Currently, there is + no safe way to enable C++11 mode (except for freestanding + applications). + + + The meaning of C++0X mode changed from GCC release to GCC + release. Earlier versions were still ABI-compatible with C++98 + mode, but in the most recent versions, switching to C++0X mode + activates C++11 support, with its compatibility problems. + + + Some C++11 features (or approximations thereof) are available + with TR1 support, that is, with or + and in the + <tr1/*> header files. This includes + std::tr1::shared_ptr (from + <tr1/memory>) and + std::tr1::function (from + <tr1/functional>). For other C++11 + features, the Boost C++ library contains replacements. + +
+
+ diff --git a/defensive-coding/en-US/CXX/.svn/text-base/Std.xml.svn-base b/defensive-coding/en-US/CXX/.svn/text-base/Std.xml.svn-base new file mode 100644 index 0000000..5ed53a4 --- /dev/null +++ b/defensive-coding/en-US/CXX/.svn/text-base/Std.xml.svn-base @@ -0,0 +1,32 @@ + + +
+ The C++ standard library + + The C++ standard library includes most of its C counterpart + by reference, see . + +
+ Containers and <literal>operator[]</literal> + + Many containers similar to std::vector + provide both operator[](size_type) and a + member function at(size_type). This applies + to std::vector itself, + std::array, std::string + and other instances of std::basic_string. + + + operator[](size_type) is not required by the + standard to perform bounds checking (and the implementation in + GCC does not). In contrast, at(size_type) + must perform such a check. Therefore, in code which is not + performance-critical, you should prefer + at(size_type) over + operator[](size_type), even though it is + slightly more verbose. + +
+
+ diff --git a/defensive-coding/en-US/CXX/.svn/text-base/schemas.xml.svn-base b/defensive-coding/en-US/CXX/.svn/text-base/schemas.xml.svn-base new file mode 100644 index 0000000..8e84245 --- /dev/null +++ b/defensive-coding/en-US/CXX/.svn/text-base/schemas.xml.svn-base @@ -0,0 +1,4 @@ + + + + diff --git a/defensive-coding/en-US/CXX/CXX.xml b/defensive-coding/en-US/CXX/CXX.xml new file mode 100644 index 0000000..fccfb75 --- /dev/null +++ b/defensive-coding/en-US/CXX/CXX.xml @@ -0,0 +1,10 @@ + + + + The C++ Programming Language + + + + + diff --git a/defensive-coding/en-US/CXX/Language.xml b/defensive-coding/en-US/CXX/Language.xml new file mode 100644 index 0000000..9dbc4f3 --- /dev/null +++ b/defensive-coding/en-US/CXX/Language.xml @@ -0,0 +1,186 @@ + + +
+ The core language + + C++ includes a large subset of the C language. As far as the C + subset is used, the recommendations in apply. + + +
+ Array allocation with <literal>operator new[]</literal> + + For very large values of n, an expression + like new T[n] can return a pointer to a heap + region which is too small. In other words, not all array + elements are actually backed with heap memory reserved to the + array. Current GCC versions generate code that performs a + computation of the form sizeof(T) * size_t(n) + + cookie_size, where cookie_size is + currently at most 8. This computation can overflow, and + GCC-generated code does not detect this. + + + The std::vector template can be used instead + an explicit array allocation. (The GCC implementation detects + overflow internally.) + + + If there is no alternative to operator new[], + code which allocates arrays with a variable length must check + for overflow manually. For the new T[n] + example, the size check could be n || (n > 0 && + n > (size_t(-1) - 8) / sizeof(T)). (See .) If there are + additional dimensions (which must be constants according to the + C++ standard), these should be included as factors in the + divisor. + + + These countermeasures prevent out-of-bounds writes and potential + code execution. Very large memory allocations can still lead to + a denial of service. + contains suggestions for mitigating this problem when processing + untrusted data. + + + See + for array allocation advice for C-style memory allocation. + +
+ +
+ Overloading + + Do not overload functions with versions that have different + security characteristics. For instance, do not implement a + function strcat which works on + std::string arguments. Similarly, do not name + methods after such functions. + +
+
+ ABI compatibility and preparing for security updates + + A stable binary interface (ABI) is vastly preferred for security + updates. Without a stable ABI, all reverse dependencies need + recompiling, which can be a lot of work and could even be + impossible in some cases. Ideally, a security update only + updates a single dynamic shared object, and is picked up + automatically after restarting affected processes. + + + Outside of extremely performance-critical code, you should + ensure that a wide range of changes is possible without breaking + ABI. Some very basic guidelines are: + + + + + Avoid inline functions. + + + + + Use the pointer-to-implementation idiom. + + + + + Try to avoid templates. Use them if the increased type + safety provides a benefit to the programmer. + + + + + Move security-critical code out of templated code, so that + it can be patched in a central place if necessary. + + + + + The KDE project publishes a document with more extensive + guidelines on ABI-preserving changes to C++ code, Policies/Binary + Compatibility Issues With C++ + (d-pointer refers to the + pointer-to-implementation idiom). + +
+ +
+ C++0X and C++11 support + + GCC offers different language compatibility modes: + + + + + for the original 1998 C++ + standard + + + + + for the 1998 standard with the + changes from the TR1 technical report + + + + + for the 2011 C++ standard. This + option should not be used. + + + + + for several different versions + of C++11 support in development, depending on the GCC + version. This option should not be used. + + + + + + For each of these flags, there are variants which also enable + GNU extensions (mostly language features also found in C99 or + C11): , + , . + Again, should not be used. + + + If you enable C++11 support, the ABI of the standard C++ library + libstdc++ will change in subtle ways. + Currently, no C++ libraries are compiled in C++11 mode, so if + you compile your code in C++11 mode, it will be incompatible + with the rest of the system. Unfortunately, this is also the + case if you do not use any C++11 features. Currently, there is + no safe way to enable C++11 mode (except for freestanding + applications). + + + The meaning of C++0X mode changed from GCC release to GCC + release. Earlier versions were still ABI-compatible with C++98 + mode, but in the most recent versions, switching to C++0X mode + activates C++11 support, with its compatibility problems. + + + Some C++11 features (or approximations thereof) are available + with TR1 support, that is, with or + and in the + <tr1/*> header files. This includes + std::tr1::shared_ptr (from + <tr1/memory>) and + std::tr1::function (from + <tr1/functional>). For other C++11 + features, the Boost C++ library contains replacements. + +
+
+ diff --git a/defensive-coding/en-US/CXX/Std.xml b/defensive-coding/en-US/CXX/Std.xml new file mode 100644 index 0000000..5ed53a4 --- /dev/null +++ b/defensive-coding/en-US/CXX/Std.xml @@ -0,0 +1,32 @@ + + +
+ The C++ standard library + + The C++ standard library includes most of its C counterpart + by reference, see . + +
+ Containers and <literal>operator[]</literal> + + Many containers similar to std::vector + provide both operator[](size_type) and a + member function at(size_type). This applies + to std::vector itself, + std::array, std::string + and other instances of std::basic_string. + + + operator[](size_type) is not required by the + standard to perform bounds checking (and the implementation in + GCC does not). In contrast, at(size_type) + must perform such a check. Therefore, in code which is not + performance-critical, you should prefer + at(size_type) over + operator[](size_type), even though it is + slightly more verbose. + +
+
+ diff --git a/defensive-coding/en-US/CXX/schemas.xml b/defensive-coding/en-US/CXX/schemas.xml new file mode 100644 index 0000000..8e84245 --- /dev/null +++ b/defensive-coding/en-US/CXX/schemas.xml @@ -0,0 +1,4 @@ + + + + diff --git a/defensive-coding/en-US/Defensive_Coding.ent b/defensive-coding/en-US/Defensive_Coding.ent new file mode 100644 index 0000000..0bf84b7 --- /dev/null +++ b/defensive-coding/en-US/Defensive_Coding.ent @@ -0,0 +1,2 @@ + + diff --git a/defensive-coding/en-US/Defensive_Coding.xml b/defensive-coding/en-US/Defensive_Coding.xml new file mode 100644 index 0000000..cef4bbf --- /dev/null +++ b/defensive-coding/en-US/Defensive_Coding.xml @@ -0,0 +1,27 @@ + + + + + + Programming Languages + + + + + + Specific Programming Tasks + + + + + + + + + + Implementing Security Features + + + + + diff --git a/defensive-coding/en-US/Features/.svn/all-wcprops b/defensive-coding/en-US/Features/.svn/all-wcprops new file mode 100644 index 0000000..9c19089 --- /dev/null +++ b/defensive-coding/en-US/Features/.svn/all-wcprops @@ -0,0 +1,23 @@ +K 25 +svn:wc:ra_dav:version-url +V 74 +/repos/product-security/!svn/ver/302/defensive-coding/trunk/en-US/Features +END +TLS.xml +K 25 +svn:wc:ra_dav:version-url +V 82 +/repos/product-security/!svn/ver/302/defensive-coding/trunk/en-US/Features/TLS.xml +END +schemas.xml +K 25 +svn:wc:ra_dav:version-url +V 86 +/repos/product-security/!svn/ver/292/defensive-coding/trunk/en-US/Features/schemas.xml +END +Authentication.xml +K 25 +svn:wc:ra_dav:version-url +V 93 +/repos/product-security/!svn/ver/281/defensive-coding/trunk/en-US/Features/Authentication.xml +END diff --git a/defensive-coding/en-US/Features/.svn/dir-prop-base b/defensive-coding/en-US/Features/.svn/dir-prop-base new file mode 100644 index 0000000..b0e5252 --- /dev/null +++ b/defensive-coding/en-US/Features/.svn/dir-prop-base @@ -0,0 +1,6 @@ +K 10 +svn:ignore +V 9 +snippets + +END diff --git a/defensive-coding/en-US/Features/.svn/entries b/defensive-coding/en-US/Features/.svn/entries new file mode 100644 index 0000000..f4cc53b --- /dev/null +++ b/defensive-coding/en-US/Features/.svn/entries @@ -0,0 +1,130 @@ +10 + +dir +305 +https://svn.devel.redhat.com/repos/product-security/defensive-coding/trunk/en-US/Features +https://svn.devel.redhat.com/repos/product-security + + + +2013-01-16T14:32:22.318444Z +302 +fweimer@REDHAT.COM +has-props + + + + + + + + + + + + + +9bd5cf0f-f2b3-0410-b1a9-d5c590f50bf1 + +TLS.xml +file + + + + +2013-01-16T22:05:55.369436Z +d466f82b291f65cf802244af678d52dd +2013-01-16T14:32:22.318444Z +302 +fweimer@REDHAT.COM +has-props + + + + + + + + + + + + + + + + + + + + +41635 + +schemas.xml +file + + + + +2013-01-10T17:17:49.036814Z +769bc2635d36b318161574a1adf2f6e7 +2012-12-14T10:18:44.472257Z +292 +fweimer@REDHAT.COM +has-props + + + + + + + + + + + + + + + + + + + + +150 + +Authentication.xml +file + + + + +2013-01-10T17:17:49.036814Z +6430a1389eb187d0fbcc79bea6c1a21e +2012-12-13T13:25:23.103424Z +281 +fweimer@REDHAT.COM +has-props + + + + + + + + + + + + + + + + + + + + +8257 + diff --git a/defensive-coding/en-US/Features/.svn/prop-base/Authentication.xml.svn-base b/defensive-coding/en-US/Features/.svn/prop-base/Authentication.xml.svn-base new file mode 100644 index 0000000..bfec7d5 --- /dev/null +++ b/defensive-coding/en-US/Features/.svn/prop-base/Authentication.xml.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 8 +text/xml +END diff --git a/defensive-coding/en-US/Features/.svn/prop-base/TLS.xml.svn-base b/defensive-coding/en-US/Features/.svn/prop-base/TLS.xml.svn-base new file mode 100644 index 0000000..bfec7d5 --- /dev/null +++ b/defensive-coding/en-US/Features/.svn/prop-base/TLS.xml.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 8 +text/xml +END diff --git a/defensive-coding/en-US/Features/.svn/prop-base/schemas.xml.svn-base b/defensive-coding/en-US/Features/.svn/prop-base/schemas.xml.svn-base new file mode 100644 index 0000000..bfec7d5 --- /dev/null +++ b/defensive-coding/en-US/Features/.svn/prop-base/schemas.xml.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 8 +text/xml +END diff --git a/defensive-coding/en-US/Features/.svn/text-base/Authentication.xml.svn-base b/defensive-coding/en-US/Features/.svn/text-base/Authentication.xml.svn-base new file mode 100644 index 0000000..c32792a --- /dev/null +++ b/defensive-coding/en-US/Features/.svn/text-base/Authentication.xml.svn-base @@ -0,0 +1,189 @@ + + + + Authentication and Authorization + +
+ Authenticating servers + + When connecting to a server, a client has to make sure that it + is actually talking to the server it expects. There are two + different aspects, securing the network path, and making sure + that the expected user runs the process on the target host. + There are several ways to ensure that: + + + + + The server uses a TLS certificate which is valid according + to the web browser public key infrastructure, and the client + verifies the certificate and the host name. + + + + + The server uses a TLS certificate which is expectedby the + client (perhaps it is stored in a configuration file read by + the client). In this case, no host name checking is + required. + + + + + On Linux, UNIX domain sockets (of the + PF_UNIX protocol family, sometimes called + PF_LOCAL) are restricted by file system + permissions. If the server socket path is not + world-writable, the server identity cannot be spoofed by + local users. + + + + + Port numbers less than 1024 (trusted + ports) can only be used by + root, so if a UDP or TCP server is + running on the local host and it uses a trusted port, its + identity is assured. (Not all operating systems enforce the + trusted ports concept, and the network might not be trusted, + so it is only useful on the local system.) + + + + + TLS () is the + recommended way for securing connections over untrusted + networks. + + + If the server port number is 1024 is higher, a local user can + impersonate the process by binding to this socket, perhaps after + crashing the real server by exploiting a denial-of-service + vulnerability. + +
+ +
+ Host-based authentication + + Host-based authentication uses access control lists (ACLs) to + accept or deny requests from clients. Thsis authentication + method comes in two flavors: IP-based (or, more generally, + address-based) and name-based (with the name coming from DNS or + /etc/hosts). IP-based ACLs often use + prefix notation to extend access to entire subnets. Name-based + ACLs sometimes use wildcards for adding groups of hosts (from + entire DNS subtrees). (In the SSH context, host-based + authentication means something completely different and is not + covered in this section.) + + + Host-based authentication trust the network and may not offer + sufficient granularity, so it has to be considered a weak form + of authentication. On the other hand, IP-based authentication + can be made extremely robust and can be applied very early in + input processing, so it offers an opportunity for significantly + reducing the number of potential attackers for many services. + + + The names returned by gethostbyaddr and + getnameinfo functions cannot be trusted. + (DNS PTR records can be set to arbitrary values, not just names + belong to the address owner.) If these names are used for ACL + matching, a forward lookup using + gethostbyaddr or + getaddrinfo has to be performed. The name + is only valid if the original address is found among the results + of the forward lookup (double-reverse + lookup). + + + An empty ACL should deny all access (deny-by-default). If empty + ACLs permits all access, configuring any access list must switch + to deny-by-default for all unconfigured protocols, in both + name-based and address-based variants. + + + Similarly, if an address or name is not matched by the list, it + should be denied. However, many implementations behave + differently, so the actual behavior must be documented properly. + + + IPv6 addresses can embed IPv4 addresses. There is no + universally correct way to deal with this ambiguity. The + behavior of the ACL implementation should be documented. + +
+ +
+ UNIX domain socket authentication + + UNIX domain sockets (with address family + AF_UNIX or AF_LOCAL) are + restricted to the local host and offer a special authentication + mechanism: credentials passing. + + + Nowadays, most systems support the + SO_PEERCRED (Linux) or + LOCAL_PEERCRED (FreeBSD) socket options, or + the getpeereid (other BSDs, MacOS X). + These interfaces provide direct access to the (effective) user + ID on the other end of a domain socket connect, without + cooperation from the other end. + + + Historically, credentials passing was implemented using + ancillary data in the sendmsg and + recvmsg functions. On some systems, only + credentials data that the peer has explicitly sent can be + received, and the kernel checks the data for correctness on the + sending side. This means that both peers need to deal with + ancillary data. Compared to that, the modern interfaces are + easier to use. Both sets of interfaces vary considerably among + UNIX-like systems, unfortunately. + + + If you want to authenticate based on supplementary groups, you + should obtain the user ID using one of these methods, and look + up the list of supplementary groups using + getpwuid (or + getpwuid_r) and + getgrouplist. Using the PID and + information from /proc/PID/status is prone + to race conditions and insecure. + +
+ + +
+ diff --git a/defensive-coding/en-US/Features/.svn/text-base/TLS.xml.svn-base b/defensive-coding/en-US/Features/.svn/text-base/TLS.xml.svn-base new file mode 100644 index 0000000..a0432f5 --- /dev/null +++ b/defensive-coding/en-US/Features/.svn/text-base/TLS.xml.svn-base @@ -0,0 +1,988 @@ + + + + Transport Layer Security + + Transport Layer Security (TLS, formerly Secure Sockets + Layer/SSL) is the recommended way to to protect integrity and + confidentiality while data is transferred over an untrusted + network connection, and to identify the endpoint. + +
+ Common Pitfalls + + TLS implementations are difficult to use, and most of them lack + a clean API design. The following sections contain + implementation-specific advice, and some generic pitfalls are + mentioned below. + + + + + Most TLS implementations have questionable default TLS + cipher suites. Most of them enable anonymous Diffie-Hellman + key exchange (but we generally want servers to authenticate + themselves). Many do not disable ciphers which are subject + to brute-force attacks because of restricted key lengths. + Some even disable all variants of AES in the default + configuration. + + + When overriding the cipher suite defaults, it is recommended + to disable all cipher suites which are not present on a + whitelist, instead of simply enabling a list of cipher + suites. This way, if an algorithm is disabled by default in + the TLS implementation in a future security update, the + application will not re-enable it. + + + + + The name which is used in certificate validation must match + the name provided by the user or configuration file. No host + name canonicalization or IP address lookup must be performed. + + + + + The TLS handshake has very poor performance if the TCP Nagle + algorithm is active. You should switch on the + TCP_NODELAY socket option (at least for the + duration of the handshake), or use the Linux-specific + TCP_CORK option. + + + Deactivating the TCP Nagle algorithm + + + + + + Implementing proper session resumption decreases handshake + overhead considerably. This is important if the upper-layer + protocol uses short-lived connections (like most application + of HTTPS). + + + + + Both client and server should work towards an orderly + connection shutdown, that is send + close_notify alerts and respond to them. + This is especially important if the upper-layer protocol + does not provide means to detect connection truncation (like + some uses of HTTP). + + + + + When implementing a server using event-driven programming, + it is important to handle the TLS handshake properly because + it includes multiple network round-trips which can block + when an ordinary TCP accept would not. + Otherwise, a client which fails to complete the TLS + handshake for some reason will prevent the server from + handling input from other clients. + + + + + Unlike regular file descriptors, TLS connections cannot be + passed between processes. Some TLS implementations add + additional restrictions, and TLS connections generally + cannot be used across fork function + calls (see ). + + + +
+ OpenSSL Pitfalls + + Some OpenSSL function use tri-state return + values. Correct error checking is extremely + important. Several functions return int + values with the following meaning: + + + + + The value 1 indicates success (for + example, a successful signature verification). + + + + + The value 0 indicates semantic + failure (for example, a signature verification which was + unsuccessful because the signing certificate was + self-signed). + + + + + The value -1 indicates a low-level + error in the system, such as failure to allocate memory + using malloc. + + + + + Treating such tri-state return values as booleans can lead + to security vulnerabilities. Note that some OpenSSL + functions return boolean results or yet another set of + status indicators. Each function needs to be checked + individually. + + + Recovering precise error information is difficult. + + shows how to obtain a more precise error code after a function + call on an SSL object has failed. However, + there are still cases where no detailed error information is + available (e.g., if SSL_shutdown fails + due to a connection teardown by the other end). + + + Obtaining OpenSSL error codes + + + + The OPENSSL_config function is + documented to never fail. In reality, it can terminate the + entire process if there is a failure accessing the + configuration file. An error message is written to standard + error, but which might not be visible if the function is + called from a daemon process. + + + OpenSSL contains two separate ASN.1 DER decoders. One set + of decoders operate on BIO handles (the input/output stream + abstraction provided by OpenSSL); their decoder function + names start with d2i_ and end in + _fp or _bio (e.g., + d2i_X509_fp or + d2i_X509_bio). These decoders must not + be used for parsing data from untrusted sources; instead, + the variants without the _fp and + _bio (e.g., + d2i_X509) shall be used. The BIO + variants have received considerably less testing and are not + very robust. + + + For the same reason, the OpenSSL command line tools (such as + openssl x509) are generally generally less + robust than the actual library code. They use the BIO + functions internally, and not the more robust variants. + + + The command line tools do not always indicate failure in the + exit status of the openssl process. + For instance, a verification failure in openssl + verify result in an exit status of zero. + + + The OpenSSL server and client applications (openssl + s_client and openssl s_server) + are debugging tools and should never be + used as generic clients. For instance, the + s_client tool reacts in a + surprisign way to lines starting with R and + Q. + + + OpenSSL allows application code to access private key + material over documented interfaces. This can significantly + increase the part of the code base which has to undergo + security certification. + +
+
+ GNUTLS Pitfalls + + libgnutls.so.26 links to + libpthread.so.0. Loading the threading + library too late causes problems, so the main program should + be linked with -lpthread as well. As a + result, it can be difficult to use GNUTLS in a plugin which is + loaded with the dlopen function. Another + side effect is that applications which merely link against + GNUTLS (even without actually using it) may incur a + substantial overhead because other libraries automatically + switch to thread-safe algorithms. + + + The gnutls_global_init function must be + called before using any functionality provided by the library. + This function is not thread-safe, so external locking is + required, but it is not clear which lock should be used. + Omitting the synchronization does not just lead to a memory + leak, as it is suggested in the GNUTLS documentation, but to + undefined behavior because there is no barrier that would + enforce memory ordering. + + + The gnutls_global_deinit function does + not actually deallocate all resources allocated by + gnutls_global_init. It is currently not + thread-safe. Therefore, it is best to avoid calling it + altogether. + + + The X.509 implementation in GNUTLS is rather lenient. For + example, it is possible to create and process X.509 + version 1 certificates which carry extensions. These + certificates are (correctly) rejected by other + implementations. + +
+
+ OpenJDK Pitfalls + + The Java cryptographic framework is highly modular. As a + result, when you request an object implementing some + cryptographic functionality, you cannot be completely sure + that you end up with the well-tested, reviewed implementation + in OpenJDK. + + + OpenJDK (in the source code as published by Oracle) and other + implementations of the Java platform require that the system + administrator has installed so-called unlimited + strength jurisdiction policy files. Without this + step, it is not possible to use the secure algorithms which + offer sufficient cryptographic strength. Most downstream + redistributors of OpenJDK remove this requirement. + + + Some versions of OpenJDK use /dev/random + as the randomness source for nonces and other random data + which is needed for TLS operation, but does not actually + require physical randomness. As a result, TLS applications + can block, waiting for more bits to become available in + /dev/random. + +
+
+ NSS Pitfalls + + NSS was not designed to be used by other libraries which can + be linked into applications without modifying them. There is + a lot of global state. There does not seem to be a way to + perform required NSS initialization without race conditions. + + + If the NSPR descriptor is in an unexpected state, the + SSL_ForceHandshake function can succeed, + but no TLS handshake takes place, the peer is not + authenticated, and subsequent data is exchanged in the clear. + + + NSS disables itself if it detects that the process underwent a + fork after the library has been + initialized. This behavior is required by the PKCS#11 API + specification. + +
+
+
+ TLS Clients + + Secure use of TLS in a client generally involves all of the + following steps. (Individual instructions for specific TLS + implementations follow in the next sections.) + + + + + The client must configure the TLS library to use a set of + trusted root certificates. These certificates are provided + by the system in /etc/ssl/certs or files derived + from it. + + + + + The client selects sufficiently strong cryptographic + primitives and disables insecure ones (such as no-op + encryption). Compression and SSL version 2 support must be + disabled (including the SSLv2-compatible handshake). + + + + + The client initiates the TLS connection. The Server Name + Indication extension should be used if supported by the + TLS implementation. Before switching to the encrypted + connection state, the contents of all input and output + buffers must be discarded. + + + + + The client needs to validate the peer certificate provided + by the server, that is, the client must check that there + is a cryptographically protected chain from a trusted root + certificate to the peer certificate. (Depending on the + TLS implementation, a TLS handshake can succeed even if + the certificate cannot be validated.) + + + + + The client must check that the configured or user-provided + server name matches the peer certificate provided by the + server. + + + + + It is safe to provide users detailed diagnostics on + certificate validation failures. Other causes of handshake + failures and, generally speaking, any details on other errors + reported by the TLS implementation (particularly exception + tracebacks), must not be divulged in ways that make them + accessible to potential attackers. Otherwise, it is possible + to create decryption oracles. + + + + Depending on the application, revocation checking (against + certificate revocations lists or via OCSP) and session + resumption are important aspects of production-quality + client. These aspects are not yet covered. + + +
+ Implementation TLS Clients With OpenSSL + + In the following code, the error handling is only exploratory. + Proper error handling is required for production use, + especially in libraries. + + + + The OpenSSL library needs explicit initialization (see ). + + + OpenSSL library initialization + + + + After that, a context object has to be created, which acts as + a factory for connection objects (). We + use an explicit cipher list so that we do not pick up any + strange ciphers when OpenSSL is upgraded. The actual version + requested in the client hello depends on additional + restrictions in the OpenSSL library. If possible, you should + follow the example code and use the default list of trusted + root certificate authorities provided by the system because + you would have to maintain your own set otherwise, which can + be cumbersome. + + + OpenSSL client context creation + + + + A single context object can be used to create multiple + connection objects. It is safe to use the same + SSL_CTX object for creating connections + concurrently from multiple threads, provided that the + SSL_CTX object is not modified (e.g., + callbacks must not be changed). + + + After creating the TCP socket and disabling the Nagle + algorithm (per ), the actual + connection object needs to be created, as show in . If + the handshake started by SSL_connect + fails, the ssl_print_error_and_exit + function from is called. + + + The certificate_validity_override + function provides an opportunity to override the validity of + the certificate in case the OpenSSL check fails. If such + functionality is not required, the call can be removed, + otherwise, the application developer has to implement it. + + + The host name passed to the functions + SSL_set_tlsext_host_name and + X509_check_host must be the name that was + passed to getaddrinfo or a similar name + resolution function. No host name canonicalization must be + performed. The X509_check_host function + used in the final step for host name matching is currently + only implemented in OpenSSL 1.1, which is not released yet. + In case host name matching fails, the function + certificate_host_name_override is called. + This function should check user-specific certificate store, to + allow a connection even if the host name does not match the + certificate. This function has to be provided by the + application developer. Note that the override must be keyed + by both the certificate and the host + name. + + + Creating a client connection using OpenSSL + + + + The connection object can be used for sending and receiving + data, as in . + It is also possible to create a BIO object + and use the SSL object as the underlying + transport, using BIO_set_ssl. + + + Using an OpenSSL connection to send and receive data + + + + When it is time to close the connection, the + SSL_shutdown function needs to be called + twice for an orderly, synchronous connection termination + (). + This exchanges close_notify alerts with the + server. The additional logic is required to deal with an + unexpected close_notify from the server. + Note that is necessary to explicitly close the underlying + socket after the connection object has been freed. + + + Closing an OpenSSL connection in an orderly fashion + + + + shows how + to deallocate the context object when it is no longer needed + because no further TLS connections will be established. + + + Closing an OpenSSL connection in an orderly fashion + + +
+
+ Implementation TLS Clients With GNUTLS + + This section describes how to implement a TLS client with full + certificate validation (but without certificate revocation + checking). Note that the error handling in is only + exploratory and needs to be replaced before production use. + + + The GNUTLS library needs explicit initialization: + + + + + + Failing to do so can result in obscure failures in Base64 + decoding. See for + additional aspects of initialization. + + + Before setting up TLS connections, a credentials objects has + to be allocated and initialized with the set of trusted root + CAs (). + + + Initializing a GNUTLS credentials structure + + + + After the last TLS connection has been closed, this credentials + object should be freed: + + + + + + During its lifetime, the credentials object can be used to + initialize TLS session objects from multiple threads, provided + that it is not changed. + + + Once the TCP connection has been established, the Nagle + algorithm should be disabled (see ). After that, the + socket can be associated with a new GNUTLS session object. + The previously allocated credentials object provides the set + of root CAs. The NORMAL set of cipher + suites and protocols provides a reasonable default. Then the + TLS handshake must be initiated. This is shown in . + + + Establishing a TLS client connection using GNUTLS + + + + After the handshake has been completed, the server certificate + needs to be verified (). In + the example, the user-defined + certificate_validity_override function is + called if the verification fails, so that a separate, + user-specific trust store can be checked. This function call + can be omitted if the functionality is not needed. + + + Verifying a server certificate using GNUTLS + + + + In the next step (, the + certificate must be matched against the host name (note the + unusual return value from + gnutls_x509_crt_check_hostname). Again, + an override function + certificate_host_name_override is called. + Note that the override must be keyed to the certificate + and the host name. The function call can + be omitted if the override is not needed. + + + Matching the server host name and certificate in a + GNUTLS client + + + + In newer GNUTLS versions, certificate checking and host name + validation can be combined using the + gnutls_certificate_verify_peers3 function. + + + An established TLS session can be used for sending and + receiving data, as in . + + + Using a GNUTLS session + + + + In order to shut down a connection in an orderly manner, you + should call the gnutls_bye function. + Finally, the session object can be deallocated using + gnutls_deinit (see ). + + + Using a GNUTLS session + + +
+
+ Implementing TLS Clients With OpenJDK + + The examples below use the following cryptographic-related + classes: + + + + + + If compatibility with OpenJDK 6 is required, it is necessary + to use the internal class + sun.security.util.HostnameChecker. (The + public OpenJDK API does not provide any support for dissecting + the subject distinguished name of an X.509 certificate, so a + custom-written DER parser is needed—or we have to use an + internal class, which we do below.) In OpenJDK 7, the + setEndpointIdentificationAlgorithm method + was added to the + javax.net.ssl.SSLParameters class, + providing an official way to implement host name checking. + + + TLS connections are established using an + SSLContext instance. With a properly + configured OpenJDK installation, the + SunJSSE provider uses the system-wide set + of trusted root certificate authorities, so no further + configuration is necessary. For backwards compatibility with + OpenJDK 6, the TLSv1 provider has to + be supported as a fall-back option. This is shown in . + + + Setting up an <literal>SSLContext</literal> for OpenJDK TLS + clients + + + + In addition to the context, a TLS parameter object will be + needed which adjusts the cipher suites and protocols (). Like + the context, these parameters can be reused for multiple TLS + connections. + + + Setting up <literal>SSLParameters</literal> for TLS use + with OpenJDK + + + + As initialized above, the parameter object does not yet + require host name checking. This has to be enabled + separately, and this is only supported by OpenJDK 7 and later: + + + + + + All application protocols can use the + "HTTPS" algorithm. (The algorithms have + minor differences with regard to wildcard handling, which + should not matter in practice.) + + + + shows how to establish the connection. Before the handshake + is initialized, the protocol and cipher configuration has to + be performed, by applying the parameter object + params. (After this point, changes to + params will not affect this TLS socket.) + As mentioned initially, host name checking requires using an + internal API on OpenJDK 6. + + + Establishing a TLS connection with OpenJDK + + + + Starting with OpenJDK 7, the last lines can be omitted, + provided that host name verification has been enabled by + calling the + setEndpointIdentificationAlgorithm method + on the params object (before it was applied + to the socket). + + + The TLS socket can be used as a regular socket, as shown in + . + + + Using a TLS client socket in OpenJDK + + +
+ Overriding server certificate validation with OpenJDK 6 + + Overriding certificate validation requires a custom trust + manager. With OpenJDK 6, the trust manager lacks + information about the TLS session, and to which server the + connection is made. Certificate overrides have to be tied + to specific servers (host names). Consequently, different + TrustManager and + SSLContext objects have to be used for + different servers. + + + In the trust manager shown in , + the server certificate is identified by its SHA-256 hash. + + + A customer trust manager for OpenJDK TLS clients + + + + This trust manager has to be passed to the + init method of the + SSLContext object, as show in . + + + Using a custom TLS trust manager with OpenJDK + + + + When certificate overrides are in place, host name + verification should not be performed because there is no + security requirement that the host name in the certificate + matches the host name used to establish the connection (and + it often will not). However, without host name + verification, it is not possible to perform transparent + fallback to certification validation using the system + certificate store. + + + The approach described above works with OpenJDK 6 and later + versions. Starting with OpenJDK 7, it is possible to use a + custom subclass of the + javax.net.ssl.X509ExtendedTrustManager + class. The OpenJDK TLS implementation will call the new + methods, passing along TLS session information. This can be + used to implement certificate overrides as a fallback (if + certificate or host name verification fails), and a trust + manager object can be used for multiple servers because the + server address is available to the trust manager. + +
+
+
+ Implementing TLS Clients With NSS + + The following code shows how to implement a simple TLS client + using NSS. Note that the error handling needs replacing + before production use. + + + Using NSS needs several header files, as shown in + . + + + Include files for NSS + + + + Initializing the NSS library is a complex task (). It is not + thread-safe. By default, the library is in export mode, and + all strong ciphers are disabled. Therefore, after creating + the NSSInitCContext object, we probe all + the strong ciphers we want to use, and check if at least one + of them is available. If not, we call + NSS_SetDomesticPolicy to switch to + unrestricted policy mode. This function replaces the existing + global cipher suite policy, that is why we avoid calling it + unless absolutely necessary. + + + The simplest way to configured the trusted root certificates + involves loading the libnssckbi.so NSS + module with a call to the + SECMOD_LoadUserModule function. The root + certificates are compiled into this module. (The PEM module + for NSS, libnsspem.so, offers a way to + load trusted CA certificates from a file.) + + + Initializing the NSS library + + + + Some of the effects of the initialization can be reverted with + the following function calls: + + + + + + After NSS has been initialized, the TLS connection can be + created (). The + internal PR_ImportTCPSocket function is + used to turn the POSIX file descriptor + sockfd into an NSPR file descriptor. (This + function is de-facto part of the NSS public ABI, so it will + not go away.) Creating the TLS-capable file descriptor + requires a model descriptor, which is + configured with the desired set of protocols and ciphers. + (The good_ciphers variable is part of .) We cannot + resort to disabling ciphers not on a whitelist because by + default, the AES cipher suites are disabled. The model + descriptor is not needed anymore after TLS support has been + activated for the existing connection descriptor. + + + The call to SSL_BadCertHook can be + omitted if no mechanism to override certificate verification + is needed. The bad_certificate function + must check both the host name specified for the connection and + the certificate before granting the override. + + + Triggering the actual handshake requires three function calls, + SSL_ResetHandshake, + SSL_SetURL, and + SSL_ForceHandshake. (If + SSL_ResetHandshake is omitted, + SSL_ForceHandshake will succeed, but the + data will not be encrypted.) During the handshake, the + certificate is verified and matched against the host name. + + + Creating a TLS connection with NSS + + + + After the connection has been established, shows how to use + the NSPR descriptor to communicate with the server. + + + Using NSS for sending and receiving data + + + + + shows how to close the connection. + + + Closing NSS client connections + + +
+
+ Implementing TLS Clients With Python + + The Python distribution provides a TLS implementation in the + ssl module (actually a wrapper around + OpenSSL). The exported interface is somewhat restricted, so + that the client code shown below does not fully implement the + recommendations in . + + + + Currently, most Python function which accept + https:// URLs or otherwise implement + HTTPS support do not perform certificate validation at all. + (For example, this is true for the httplib + and xmlrpclib modules.) If you use + HTTPS, you should not use the built-in HTTP clients. The + Curl class in the curl + module, as provided by the python-pycurl + package implements proper certificate validation. + + + + The ssl module currently does not perform + host name checking on the server certificate. + shows how to implement certificate matching, using the parsed + certificate returned by getpeercert. + + + Implementing TLS host name checking Python (without + wildcard support) + + + + To turn a regular, connected TCP socket into a TLS-enabled + socket, use the ssl.wrap_socket function. + The function call in + provides additional arguments to override questionable + defaults in OpenSSL and in the Python module. + + + + + ciphers="HIGH:-aNULL:-eNULL:-PSK:RC4-SHA:RC4-MD5" + selects relatively strong cipher suites with + certificate-based authentication. (The call to + check_host_name function provides + additional protection against anonymous cipher suites.) + + + + + ssl_version=ssl.PROTOCOL_TLSv1 disables + SSL 2.0 support. By default, the ssl + module sends an SSL 2.0 client hello, which is rejected by + some servers. Ideally, we would request OpenSSL to + negotiated the most recent TLS version supported by the + server and the client, but the Python module does not + allow this. + + + + + cert_reqs=ssl.CERT_REQUIRED turns on + certificate validation. + + + + + ca_certs='/etc/ssl/certs/ca-bundle.crt' + initializes the certificate store with a set of trusted + root CAs. Unfortunately, it is necessary to hard-code + this path into applications because the default path in + OpenSSL is not available through the Python + ssl module. + + + + + The ssl module (and OpenSSL) perform + certificate validation, but the certificate must be compared + manually against the host name, by calling the + check_host_name defined above. + + + Establishing a TLS client connection with Python + + + + After the connection has been established, the TLS socket can + be used like a regular socket: + + + + + + Closing the TLS socket is straightforward as well: + + + + +
+
+
diff --git a/defensive-coding/en-US/Features/.svn/text-base/schemas.xml.svn-base b/defensive-coding/en-US/Features/.svn/text-base/schemas.xml.svn-base new file mode 100644 index 0000000..8e84245 --- /dev/null +++ b/defensive-coding/en-US/Features/.svn/text-base/schemas.xml.svn-base @@ -0,0 +1,4 @@ + + + + diff --git a/defensive-coding/en-US/Features/Authentication.xml b/defensive-coding/en-US/Features/Authentication.xml new file mode 100644 index 0000000..c32792a --- /dev/null +++ b/defensive-coding/en-US/Features/Authentication.xml @@ -0,0 +1,189 @@ + + + + Authentication and Authorization + +
+ Authenticating servers + + When connecting to a server, a client has to make sure that it + is actually talking to the server it expects. There are two + different aspects, securing the network path, and making sure + that the expected user runs the process on the target host. + There are several ways to ensure that: + + + + + The server uses a TLS certificate which is valid according + to the web browser public key infrastructure, and the client + verifies the certificate and the host name. + + + + + The server uses a TLS certificate which is expectedby the + client (perhaps it is stored in a configuration file read by + the client). In this case, no host name checking is + required. + + + + + On Linux, UNIX domain sockets (of the + PF_UNIX protocol family, sometimes called + PF_LOCAL) are restricted by file system + permissions. If the server socket path is not + world-writable, the server identity cannot be spoofed by + local users. + + + + + Port numbers less than 1024 (trusted + ports) can only be used by + root, so if a UDP or TCP server is + running on the local host and it uses a trusted port, its + identity is assured. (Not all operating systems enforce the + trusted ports concept, and the network might not be trusted, + so it is only useful on the local system.) + + + + + TLS () is the + recommended way for securing connections over untrusted + networks. + + + If the server port number is 1024 is higher, a local user can + impersonate the process by binding to this socket, perhaps after + crashing the real server by exploiting a denial-of-service + vulnerability. + +
+ +
+ Host-based authentication + + Host-based authentication uses access control lists (ACLs) to + accept or deny requests from clients. Thsis authentication + method comes in two flavors: IP-based (or, more generally, + address-based) and name-based (with the name coming from DNS or + /etc/hosts). IP-based ACLs often use + prefix notation to extend access to entire subnets. Name-based + ACLs sometimes use wildcards for adding groups of hosts (from + entire DNS subtrees). (In the SSH context, host-based + authentication means something completely different and is not + covered in this section.) + + + Host-based authentication trust the network and may not offer + sufficient granularity, so it has to be considered a weak form + of authentication. On the other hand, IP-based authentication + can be made extremely robust and can be applied very early in + input processing, so it offers an opportunity for significantly + reducing the number of potential attackers for many services. + + + The names returned by gethostbyaddr and + getnameinfo functions cannot be trusted. + (DNS PTR records can be set to arbitrary values, not just names + belong to the address owner.) If these names are used for ACL + matching, a forward lookup using + gethostbyaddr or + getaddrinfo has to be performed. The name + is only valid if the original address is found among the results + of the forward lookup (double-reverse + lookup). + + + An empty ACL should deny all access (deny-by-default). If empty + ACLs permits all access, configuring any access list must switch + to deny-by-default for all unconfigured protocols, in both + name-based and address-based variants. + + + Similarly, if an address or name is not matched by the list, it + should be denied. However, many implementations behave + differently, so the actual behavior must be documented properly. + + + IPv6 addresses can embed IPv4 addresses. There is no + universally correct way to deal with this ambiguity. The + behavior of the ACL implementation should be documented. + +
+ +
+ UNIX domain socket authentication + + UNIX domain sockets (with address family + AF_UNIX or AF_LOCAL) are + restricted to the local host and offer a special authentication + mechanism: credentials passing. + + + Nowadays, most systems support the + SO_PEERCRED (Linux) or + LOCAL_PEERCRED (FreeBSD) socket options, or + the getpeereid (other BSDs, MacOS X). + These interfaces provide direct access to the (effective) user + ID on the other end of a domain socket connect, without + cooperation from the other end. + + + Historically, credentials passing was implemented using + ancillary data in the sendmsg and + recvmsg functions. On some systems, only + credentials data that the peer has explicitly sent can be + received, and the kernel checks the data for correctness on the + sending side. This means that both peers need to deal with + ancillary data. Compared to that, the modern interfaces are + easier to use. Both sets of interfaces vary considerably among + UNIX-like systems, unfortunately. + + + If you want to authenticate based on supplementary groups, you + should obtain the user ID using one of these methods, and look + up the list of supplementary groups using + getpwuid (or + getpwuid_r) and + getgrouplist. Using the PID and + information from /proc/PID/status is prone + to race conditions and insecure. + +
+ + +
+ diff --git a/defensive-coding/en-US/Features/TLS.xml b/defensive-coding/en-US/Features/TLS.xml new file mode 100644 index 0000000..a0432f5 --- /dev/null +++ b/defensive-coding/en-US/Features/TLS.xml @@ -0,0 +1,988 @@ + + + + Transport Layer Security + + Transport Layer Security (TLS, formerly Secure Sockets + Layer/SSL) is the recommended way to to protect integrity and + confidentiality while data is transferred over an untrusted + network connection, and to identify the endpoint. + +
+ Common Pitfalls + + TLS implementations are difficult to use, and most of them lack + a clean API design. The following sections contain + implementation-specific advice, and some generic pitfalls are + mentioned below. + + + + + Most TLS implementations have questionable default TLS + cipher suites. Most of them enable anonymous Diffie-Hellman + key exchange (but we generally want servers to authenticate + themselves). Many do not disable ciphers which are subject + to brute-force attacks because of restricted key lengths. + Some even disable all variants of AES in the default + configuration. + + + When overriding the cipher suite defaults, it is recommended + to disable all cipher suites which are not present on a + whitelist, instead of simply enabling a list of cipher + suites. This way, if an algorithm is disabled by default in + the TLS implementation in a future security update, the + application will not re-enable it. + + + + + The name which is used in certificate validation must match + the name provided by the user or configuration file. No host + name canonicalization or IP address lookup must be performed. + + + + + The TLS handshake has very poor performance if the TCP Nagle + algorithm is active. You should switch on the + TCP_NODELAY socket option (at least for the + duration of the handshake), or use the Linux-specific + TCP_CORK option. + + + Deactivating the TCP Nagle algorithm + + + + + + Implementing proper session resumption decreases handshake + overhead considerably. This is important if the upper-layer + protocol uses short-lived connections (like most application + of HTTPS). + + + + + Both client and server should work towards an orderly + connection shutdown, that is send + close_notify alerts and respond to them. + This is especially important if the upper-layer protocol + does not provide means to detect connection truncation (like + some uses of HTTP). + + + + + When implementing a server using event-driven programming, + it is important to handle the TLS handshake properly because + it includes multiple network round-trips which can block + when an ordinary TCP accept would not. + Otherwise, a client which fails to complete the TLS + handshake for some reason will prevent the server from + handling input from other clients. + + + + + Unlike regular file descriptors, TLS connections cannot be + passed between processes. Some TLS implementations add + additional restrictions, and TLS connections generally + cannot be used across fork function + calls (see ). + + + +
+ OpenSSL Pitfalls + + Some OpenSSL function use tri-state return + values. Correct error checking is extremely + important. Several functions return int + values with the following meaning: + + + + + The value 1 indicates success (for + example, a successful signature verification). + + + + + The value 0 indicates semantic + failure (for example, a signature verification which was + unsuccessful because the signing certificate was + self-signed). + + + + + The value -1 indicates a low-level + error in the system, such as failure to allocate memory + using malloc. + + + + + Treating such tri-state return values as booleans can lead + to security vulnerabilities. Note that some OpenSSL + functions return boolean results or yet another set of + status indicators. Each function needs to be checked + individually. + + + Recovering precise error information is difficult. + + shows how to obtain a more precise error code after a function + call on an SSL object has failed. However, + there are still cases where no detailed error information is + available (e.g., if SSL_shutdown fails + due to a connection teardown by the other end). + + + Obtaining OpenSSL error codes + + + + The OPENSSL_config function is + documented to never fail. In reality, it can terminate the + entire process if there is a failure accessing the + configuration file. An error message is written to standard + error, but which might not be visible if the function is + called from a daemon process. + + + OpenSSL contains two separate ASN.1 DER decoders. One set + of decoders operate on BIO handles (the input/output stream + abstraction provided by OpenSSL); their decoder function + names start with d2i_ and end in + _fp or _bio (e.g., + d2i_X509_fp or + d2i_X509_bio). These decoders must not + be used for parsing data from untrusted sources; instead, + the variants without the _fp and + _bio (e.g., + d2i_X509) shall be used. The BIO + variants have received considerably less testing and are not + very robust. + + + For the same reason, the OpenSSL command line tools (such as + openssl x509) are generally generally less + robust than the actual library code. They use the BIO + functions internally, and not the more robust variants. + + + The command line tools do not always indicate failure in the + exit status of the openssl process. + For instance, a verification failure in openssl + verify result in an exit status of zero. + + + The OpenSSL server and client applications (openssl + s_client and openssl s_server) + are debugging tools and should never be + used as generic clients. For instance, the + s_client tool reacts in a + surprisign way to lines starting with R and + Q. + + + OpenSSL allows application code to access private key + material over documented interfaces. This can significantly + increase the part of the code base which has to undergo + security certification. + +
+
+ GNUTLS Pitfalls + + libgnutls.so.26 links to + libpthread.so.0. Loading the threading + library too late causes problems, so the main program should + be linked with -lpthread as well. As a + result, it can be difficult to use GNUTLS in a plugin which is + loaded with the dlopen function. Another + side effect is that applications which merely link against + GNUTLS (even without actually using it) may incur a + substantial overhead because other libraries automatically + switch to thread-safe algorithms. + + + The gnutls_global_init function must be + called before using any functionality provided by the library. + This function is not thread-safe, so external locking is + required, but it is not clear which lock should be used. + Omitting the synchronization does not just lead to a memory + leak, as it is suggested in the GNUTLS documentation, but to + undefined behavior because there is no barrier that would + enforce memory ordering. + + + The gnutls_global_deinit function does + not actually deallocate all resources allocated by + gnutls_global_init. It is currently not + thread-safe. Therefore, it is best to avoid calling it + altogether. + + + The X.509 implementation in GNUTLS is rather lenient. For + example, it is possible to create and process X.509 + version 1 certificates which carry extensions. These + certificates are (correctly) rejected by other + implementations. + +
+
+ OpenJDK Pitfalls + + The Java cryptographic framework is highly modular. As a + result, when you request an object implementing some + cryptographic functionality, you cannot be completely sure + that you end up with the well-tested, reviewed implementation + in OpenJDK. + + + OpenJDK (in the source code as published by Oracle) and other + implementations of the Java platform require that the system + administrator has installed so-called unlimited + strength jurisdiction policy files. Without this + step, it is not possible to use the secure algorithms which + offer sufficient cryptographic strength. Most downstream + redistributors of OpenJDK remove this requirement. + + + Some versions of OpenJDK use /dev/random + as the randomness source for nonces and other random data + which is needed for TLS operation, but does not actually + require physical randomness. As a result, TLS applications + can block, waiting for more bits to become available in + /dev/random. + +
+
+ NSS Pitfalls + + NSS was not designed to be used by other libraries which can + be linked into applications without modifying them. There is + a lot of global state. There does not seem to be a way to + perform required NSS initialization without race conditions. + + + If the NSPR descriptor is in an unexpected state, the + SSL_ForceHandshake function can succeed, + but no TLS handshake takes place, the peer is not + authenticated, and subsequent data is exchanged in the clear. + + + NSS disables itself if it detects that the process underwent a + fork after the library has been + initialized. This behavior is required by the PKCS#11 API + specification. + +
+
+
+ TLS Clients + + Secure use of TLS in a client generally involves all of the + following steps. (Individual instructions for specific TLS + implementations follow in the next sections.) + + + + + The client must configure the TLS library to use a set of + trusted root certificates. These certificates are provided + by the system in /etc/ssl/certs or files derived + from it. + + + + + The client selects sufficiently strong cryptographic + primitives and disables insecure ones (such as no-op + encryption). Compression and SSL version 2 support must be + disabled (including the SSLv2-compatible handshake). + + + + + The client initiates the TLS connection. The Server Name + Indication extension should be used if supported by the + TLS implementation. Before switching to the encrypted + connection state, the contents of all input and output + buffers must be discarded. + + + + + The client needs to validate the peer certificate provided + by the server, that is, the client must check that there + is a cryptographically protected chain from a trusted root + certificate to the peer certificate. (Depending on the + TLS implementation, a TLS handshake can succeed even if + the certificate cannot be validated.) + + + + + The client must check that the configured or user-provided + server name matches the peer certificate provided by the + server. + + + + + It is safe to provide users detailed diagnostics on + certificate validation failures. Other causes of handshake + failures and, generally speaking, any details on other errors + reported by the TLS implementation (particularly exception + tracebacks), must not be divulged in ways that make them + accessible to potential attackers. Otherwise, it is possible + to create decryption oracles. + + + + Depending on the application, revocation checking (against + certificate revocations lists or via OCSP) and session + resumption are important aspects of production-quality + client. These aspects are not yet covered. + + +
+ Implementation TLS Clients With OpenSSL + + In the following code, the error handling is only exploratory. + Proper error handling is required for production use, + especially in libraries. + + + + The OpenSSL library needs explicit initialization (see ). + + + OpenSSL library initialization + + + + After that, a context object has to be created, which acts as + a factory for connection objects (). We + use an explicit cipher list so that we do not pick up any + strange ciphers when OpenSSL is upgraded. The actual version + requested in the client hello depends on additional + restrictions in the OpenSSL library. If possible, you should + follow the example code and use the default list of trusted + root certificate authorities provided by the system because + you would have to maintain your own set otherwise, which can + be cumbersome. + + + OpenSSL client context creation + + + + A single context object can be used to create multiple + connection objects. It is safe to use the same + SSL_CTX object for creating connections + concurrently from multiple threads, provided that the + SSL_CTX object is not modified (e.g., + callbacks must not be changed). + + + After creating the TCP socket and disabling the Nagle + algorithm (per ), the actual + connection object needs to be created, as show in . If + the handshake started by SSL_connect + fails, the ssl_print_error_and_exit + function from is called. + + + The certificate_validity_override + function provides an opportunity to override the validity of + the certificate in case the OpenSSL check fails. If such + functionality is not required, the call can be removed, + otherwise, the application developer has to implement it. + + + The host name passed to the functions + SSL_set_tlsext_host_name and + X509_check_host must be the name that was + passed to getaddrinfo or a similar name + resolution function. No host name canonicalization must be + performed. The X509_check_host function + used in the final step for host name matching is currently + only implemented in OpenSSL 1.1, which is not released yet. + In case host name matching fails, the function + certificate_host_name_override is called. + This function should check user-specific certificate store, to + allow a connection even if the host name does not match the + certificate. This function has to be provided by the + application developer. Note that the override must be keyed + by both the certificate and the host + name. + + + Creating a client connection using OpenSSL + + + + The connection object can be used for sending and receiving + data, as in . + It is also possible to create a BIO object + and use the SSL object as the underlying + transport, using BIO_set_ssl. + + + Using an OpenSSL connection to send and receive data + + + + When it is time to close the connection, the + SSL_shutdown function needs to be called + twice for an orderly, synchronous connection termination + (). + This exchanges close_notify alerts with the + server. The additional logic is required to deal with an + unexpected close_notify from the server. + Note that is necessary to explicitly close the underlying + socket after the connection object has been freed. + + + Closing an OpenSSL connection in an orderly fashion + + + + shows how + to deallocate the context object when it is no longer needed + because no further TLS connections will be established. + + + Closing an OpenSSL connection in an orderly fashion + + +
+
+ Implementation TLS Clients With GNUTLS + + This section describes how to implement a TLS client with full + certificate validation (but without certificate revocation + checking). Note that the error handling in is only + exploratory and needs to be replaced before production use. + + + The GNUTLS library needs explicit initialization: + + + + + + Failing to do so can result in obscure failures in Base64 + decoding. See for + additional aspects of initialization. + + + Before setting up TLS connections, a credentials objects has + to be allocated and initialized with the set of trusted root + CAs (). + + + Initializing a GNUTLS credentials structure + + + + After the last TLS connection has been closed, this credentials + object should be freed: + + + + + + During its lifetime, the credentials object can be used to + initialize TLS session objects from multiple threads, provided + that it is not changed. + + + Once the TCP connection has been established, the Nagle + algorithm should be disabled (see ). After that, the + socket can be associated with a new GNUTLS session object. + The previously allocated credentials object provides the set + of root CAs. The NORMAL set of cipher + suites and protocols provides a reasonable default. Then the + TLS handshake must be initiated. This is shown in . + + + Establishing a TLS client connection using GNUTLS + + + + After the handshake has been completed, the server certificate + needs to be verified (). In + the example, the user-defined + certificate_validity_override function is + called if the verification fails, so that a separate, + user-specific trust store can be checked. This function call + can be omitted if the functionality is not needed. + + + Verifying a server certificate using GNUTLS + + + + In the next step (, the + certificate must be matched against the host name (note the + unusual return value from + gnutls_x509_crt_check_hostname). Again, + an override function + certificate_host_name_override is called. + Note that the override must be keyed to the certificate + and the host name. The function call can + be omitted if the override is not needed. + + + Matching the server host name and certificate in a + GNUTLS client + + + + In newer GNUTLS versions, certificate checking and host name + validation can be combined using the + gnutls_certificate_verify_peers3 function. + + + An established TLS session can be used for sending and + receiving data, as in . + + + Using a GNUTLS session + + + + In order to shut down a connection in an orderly manner, you + should call the gnutls_bye function. + Finally, the session object can be deallocated using + gnutls_deinit (see ). + + + Using a GNUTLS session + + +
+
+ Implementing TLS Clients With OpenJDK + + The examples below use the following cryptographic-related + classes: + + + + + + If compatibility with OpenJDK 6 is required, it is necessary + to use the internal class + sun.security.util.HostnameChecker. (The + public OpenJDK API does not provide any support for dissecting + the subject distinguished name of an X.509 certificate, so a + custom-written DER parser is needed—or we have to use an + internal class, which we do below.) In OpenJDK 7, the + setEndpointIdentificationAlgorithm method + was added to the + javax.net.ssl.SSLParameters class, + providing an official way to implement host name checking. + + + TLS connections are established using an + SSLContext instance. With a properly + configured OpenJDK installation, the + SunJSSE provider uses the system-wide set + of trusted root certificate authorities, so no further + configuration is necessary. For backwards compatibility with + OpenJDK 6, the TLSv1 provider has to + be supported as a fall-back option. This is shown in . + + + Setting up an <literal>SSLContext</literal> for OpenJDK TLS + clients + + + + In addition to the context, a TLS parameter object will be + needed which adjusts the cipher suites and protocols (). Like + the context, these parameters can be reused for multiple TLS + connections. + + + Setting up <literal>SSLParameters</literal> for TLS use + with OpenJDK + + + + As initialized above, the parameter object does not yet + require host name checking. This has to be enabled + separately, and this is only supported by OpenJDK 7 and later: + + + + + + All application protocols can use the + "HTTPS" algorithm. (The algorithms have + minor differences with regard to wildcard handling, which + should not matter in practice.) + + + + shows how to establish the connection. Before the handshake + is initialized, the protocol and cipher configuration has to + be performed, by applying the parameter object + params. (After this point, changes to + params will not affect this TLS socket.) + As mentioned initially, host name checking requires using an + internal API on OpenJDK 6. + + + Establishing a TLS connection with OpenJDK + + + + Starting with OpenJDK 7, the last lines can be omitted, + provided that host name verification has been enabled by + calling the + setEndpointIdentificationAlgorithm method + on the params object (before it was applied + to the socket). + + + The TLS socket can be used as a regular socket, as shown in + . + + + Using a TLS client socket in OpenJDK + + +
+ Overriding server certificate validation with OpenJDK 6 + + Overriding certificate validation requires a custom trust + manager. With OpenJDK 6, the trust manager lacks + information about the TLS session, and to which server the + connection is made. Certificate overrides have to be tied + to specific servers (host names). Consequently, different + TrustManager and + SSLContext objects have to be used for + different servers. + + + In the trust manager shown in , + the server certificate is identified by its SHA-256 hash. + + + A customer trust manager for OpenJDK TLS clients + + + + This trust manager has to be passed to the + init method of the + SSLContext object, as show in . + + + Using a custom TLS trust manager with OpenJDK + + + + When certificate overrides are in place, host name + verification should not be performed because there is no + security requirement that the host name in the certificate + matches the host name used to establish the connection (and + it often will not). However, without host name + verification, it is not possible to perform transparent + fallback to certification validation using the system + certificate store. + + + The approach described above works with OpenJDK 6 and later + versions. Starting with OpenJDK 7, it is possible to use a + custom subclass of the + javax.net.ssl.X509ExtendedTrustManager + class. The OpenJDK TLS implementation will call the new + methods, passing along TLS session information. This can be + used to implement certificate overrides as a fallback (if + certificate or host name verification fails), and a trust + manager object can be used for multiple servers because the + server address is available to the trust manager. + +
+
+
+ Implementing TLS Clients With NSS + + The following code shows how to implement a simple TLS client + using NSS. Note that the error handling needs replacing + before production use. + + + Using NSS needs several header files, as shown in + . + + + Include files for NSS + + + + Initializing the NSS library is a complex task (). It is not + thread-safe. By default, the library is in export mode, and + all strong ciphers are disabled. Therefore, after creating + the NSSInitCContext object, we probe all + the strong ciphers we want to use, and check if at least one + of them is available. If not, we call + NSS_SetDomesticPolicy to switch to + unrestricted policy mode. This function replaces the existing + global cipher suite policy, that is why we avoid calling it + unless absolutely necessary. + + + The simplest way to configured the trusted root certificates + involves loading the libnssckbi.so NSS + module with a call to the + SECMOD_LoadUserModule function. The root + certificates are compiled into this module. (The PEM module + for NSS, libnsspem.so, offers a way to + load trusted CA certificates from a file.) + + + Initializing the NSS library + + + + Some of the effects of the initialization can be reverted with + the following function calls: + + + + + + After NSS has been initialized, the TLS connection can be + created (). The + internal PR_ImportTCPSocket function is + used to turn the POSIX file descriptor + sockfd into an NSPR file descriptor. (This + function is de-facto part of the NSS public ABI, so it will + not go away.) Creating the TLS-capable file descriptor + requires a model descriptor, which is + configured with the desired set of protocols and ciphers. + (The good_ciphers variable is part of .) We cannot + resort to disabling ciphers not on a whitelist because by + default, the AES cipher suites are disabled. The model + descriptor is not needed anymore after TLS support has been + activated for the existing connection descriptor. + + + The call to SSL_BadCertHook can be + omitted if no mechanism to override certificate verification + is needed. The bad_certificate function + must check both the host name specified for the connection and + the certificate before granting the override. + + + Triggering the actual handshake requires three function calls, + SSL_ResetHandshake, + SSL_SetURL, and + SSL_ForceHandshake. (If + SSL_ResetHandshake is omitted, + SSL_ForceHandshake will succeed, but the + data will not be encrypted.) During the handshake, the + certificate is verified and matched against the host name. + + + Creating a TLS connection with NSS + + + + After the connection has been established, shows how to use + the NSPR descriptor to communicate with the server. + + + Using NSS for sending and receiving data + + + + + shows how to close the connection. + + + Closing NSS client connections + + +
+
+ Implementing TLS Clients With Python + + The Python distribution provides a TLS implementation in the + ssl module (actually a wrapper around + OpenSSL). The exported interface is somewhat restricted, so + that the client code shown below does not fully implement the + recommendations in . + + + + Currently, most Python function which accept + https:// URLs or otherwise implement + HTTPS support do not perform certificate validation at all. + (For example, this is true for the httplib + and xmlrpclib modules.) If you use + HTTPS, you should not use the built-in HTTP clients. The + Curl class in the curl + module, as provided by the python-pycurl + package implements proper certificate validation. + + + + The ssl module currently does not perform + host name checking on the server certificate. + shows how to implement certificate matching, using the parsed + certificate returned by getpeercert. + + + Implementing TLS host name checking Python (without + wildcard support) + + + + To turn a regular, connected TCP socket into a TLS-enabled + socket, use the ssl.wrap_socket function. + The function call in + provides additional arguments to override questionable + defaults in OpenSSL and in the Python module. + + + + + ciphers="HIGH:-aNULL:-eNULL:-PSK:RC4-SHA:RC4-MD5" + selects relatively strong cipher suites with + certificate-based authentication. (The call to + check_host_name function provides + additional protection against anonymous cipher suites.) + + + + + ssl_version=ssl.PROTOCOL_TLSv1 disables + SSL 2.0 support. By default, the ssl + module sends an SSL 2.0 client hello, which is rejected by + some servers. Ideally, we would request OpenSSL to + negotiated the most recent TLS version supported by the + server and the client, but the Python module does not + allow this. + + + + + cert_reqs=ssl.CERT_REQUIRED turns on + certificate validation. + + + + + ca_certs='/etc/ssl/certs/ca-bundle.crt' + initializes the certificate store with a set of trusted + root CAs. Unfortunately, it is necessary to hard-code + this path into applications because the default path in + OpenSSL is not available through the Python + ssl module. + + + + + The ssl module (and OpenSSL) perform + certificate validation, but the certificate must be compared + manually against the host name, by calling the + check_host_name defined above. + + + Establishing a TLS client connection with Python + + + + After the connection has been established, the TLS socket can + be used like a regular socket: + + + + + + Closing the TLS socket is straightforward as well: + + + + +
+
+
diff --git a/defensive-coding/en-US/Features/schemas.xml b/defensive-coding/en-US/Features/schemas.xml new file mode 100644 index 0000000..8e84245 --- /dev/null +++ b/defensive-coding/en-US/Features/schemas.xml @@ -0,0 +1,4 @@ + + + + diff --git a/defensive-coding/en-US/Features/snippets/TLS-Client-GNUTLS-Connect.xml b/defensive-coding/en-US/Features/snippets/TLS-Client-GNUTLS-Connect.xml new file mode 100644 index 0000000..fbf1420 --- /dev/null +++ b/defensive-coding/en-US/Features/snippets/TLS-Client-GNUTLS-Connect.xml @@ -0,0 +1,50 @@ + + + + +// Create the session object. +gnutls_session_t session; +ret = gnutls_init(&session, GNUTLS_CLIENT); +if (ret != GNUTLS_E_SUCCESS) { + fprintf(stderr, "error: gnutls_init: %s\n", + gnutls_strerror(ret)); + exit(1); +} + +// Configure the cipher preferences. +const char *errptr = NULL; +ret = gnutls_priority_set_direct(session, "NORMAL", &errptr); +if (ret != GNUTLS_E_SUCCESS) { + fprintf(stderr, "error: gnutls_priority_set_direct: %s\n" + "error: at: \"%s\"\n", gnutls_strerror(ret), errptr); + exit(1); +} + +// Install the trusted certificates. +ret = gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, cred); +if (ret != GNUTLS_E_SUCCESS) { + fprintf(stderr, "error: gnutls_credentials_set: %s\n", + gnutls_strerror(ret)); + exit(1); +} + +// Associate the socket with the session object and set the server +// name. +gnutls_transport_set_ptr(session, (gnutls_transport_ptr_t)(uintptr_t)sockfd); +ret = gnutls_server_name_set(session, GNUTLS_NAME_DNS, + host, strlen(host)); +if (ret != GNUTLS_E_SUCCESS) { + fprintf(stderr, "error: gnutls_server_name_set: %s\n", + gnutls_strerror(ret)); + exit(1); +} + +// Establish the session. +ret = gnutls_handshake(session); +if (ret != GNUTLS_E_SUCCESS) { + fprintf(stderr, "error: gnutls_handshake: %s\n", + gnutls_strerror(ret)); + exit(1); +} + diff --git a/defensive-coding/en-US/Features/snippets/TLS-Client-GNUTLS-Credentials.xml b/defensive-coding/en-US/Features/snippets/TLS-Client-GNUTLS-Credentials.xml new file mode 100644 index 0000000..6a5cd09 --- /dev/null +++ b/defensive-coding/en-US/Features/snippets/TLS-Client-GNUTLS-Credentials.xml @@ -0,0 +1,29 @@ + + + + +// Load the trusted CA certificates. +gnutls_certificate_credentials_t cred = NULL; +int ret = gnutls_certificate_allocate_credentials (&cred); +if (ret != GNUTLS_E_SUCCESS) { + fprintf(stderr, "error: gnutls_certificate_allocate_credentials: %s\n", + gnutls_strerror(ret)); + exit(1); +} +// gnutls_certificate_set_x509_system_trust needs GNUTLS version 3.0 +// or newer, so we hard-code the path to the certificate store +// instead. +static const char ca_bundle[] = "/etc/ssl/certs/ca-bundle.crt"; +ret = gnutls_certificate_set_x509_trust_file + (cred, ca_bundle, GNUTLS_X509_FMT_PEM); +if (ret == 0) { + fprintf(stderr, "error: no certificates found in: %s\n", ca_bundle); + exit(1); +} +if (ret < 0) { + fprintf(stderr, "error: gnutls_certificate_set_x509_trust_files(%s): %s\n", + ca_bundle, gnutls_strerror(ret)); + exit(1); +} + diff --git a/defensive-coding/en-US/Features/snippets/TLS-Client-GNUTLS-Match.xml b/defensive-coding/en-US/Features/snippets/TLS-Client-GNUTLS-Match.xml new file mode 100644 index 0000000..c4a51ce --- /dev/null +++ b/defensive-coding/en-US/Features/snippets/TLS-Client-GNUTLS-Match.xml @@ -0,0 +1,30 @@ + + + + +// Match the peer certificate against the host name. +// We can only obtain a set of DER-encoded certificates from the +// session object, so we have to re-parse the peer certificate into +// a certificate object. +gnutls_x509_crt_t cert; +ret = gnutls_x509_crt_init(&cert); +if (ret != GNUTLS_E_SUCCESS) { + fprintf(stderr, "error: gnutls_x509_crt_init: %s\n", + gnutls_strerror(ret)); + exit(1); +} +// The peer certificate is the first certificate in the list. +ret = gnutls_x509_crt_import(cert, certs, GNUTLS_X509_FMT_DER); +if (ret != GNUTLS_E_SUCCESS) { + fprintf(stderr, "error: gnutls_x509_crt_import: %s\n", + gnutls_strerror(ret)); + exit(1); +} +ret = gnutls_x509_crt_check_hostname(cert, host); +if (ret == 0 && !certificate_host_name_override(certs[0], host)) { + fprintf(stderr, "error: host name does not match certificate\n"); + exit(1); +} +gnutls_x509_crt_deinit(cert); + diff --git a/defensive-coding/en-US/Features/snippets/TLS-Client-GNUTLS-Verify.xml b/defensive-coding/en-US/Features/snippets/TLS-Client-GNUTLS-Verify.xml new file mode 100644 index 0000000..a3c9365 --- /dev/null +++ b/defensive-coding/en-US/Features/snippets/TLS-Client-GNUTLS-Verify.xml @@ -0,0 +1,42 @@ + + + + +// Obtain the server certificate chain. The server certificate +// itself is stored in the first element of the array. +unsigned certslen = 0; +const gnutls_datum_t *const certs = + gnutls_certificate_get_peers(session, &certslen); +if (certs == NULL || certslen == 0) { + fprintf(stderr, "error: could not obtain peer certificate\n"); + exit(1); +} + +// Validate the certificate chain. +unsigned status = (unsigned)-1; +ret = gnutls_certificate_verify_peers2(session, &status); +if (ret != GNUTLS_E_SUCCESS) { + fprintf(stderr, "error: gnutls_certificate_verify_peers2: %s\n", + gnutls_strerror(ret)); + exit(1); +} +if (status != 0 && !certificate_validity_override(certs[0])) { + gnutls_datum_t msg; +#if GNUTLS_VERSION_AT_LEAST_3_1_4 + int type = gnutls_certificate_type_get (session); + ret = gnutls_certificate_verification_status_print(status, type, &out, 0); +#else + ret = -1; +#endif + if (ret == 0) { + fprintf(stderr, "error: %s\n", msg.data); + gnutls_free(msg.data); + exit(1); + } else { + fprintf(stderr, "error: certificate validation failed with code 0x%x\n", + status); + exit(1); + } +} + diff --git a/defensive-coding/en-US/Features/snippets/TLS-Client-NSS-Close.xml b/defensive-coding/en-US/Features/snippets/TLS-Client-NSS-Close.xml new file mode 100644 index 0000000..456e209 --- /dev/null +++ b/defensive-coding/en-US/Features/snippets/TLS-Client-NSS-Close.xml @@ -0,0 +1,15 @@ + + + + +// Send close_notify alert. +if (PR_Shutdown(nspr, PR_SHUTDOWN_BOTH) != PR_SUCCESS) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: PR_Read error %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); +} +// Closes the underlying POSIX file descriptor, too. +PR_Close(nspr); + diff --git a/defensive-coding/en-US/Features/snippets/TLS-Client-NSS-Connect.xml b/defensive-coding/en-US/Features/snippets/TLS-Client-NSS-Connect.xml new file mode 100644 index 0000000..692ad04 --- /dev/null +++ b/defensive-coding/en-US/Features/snippets/TLS-Client-NSS-Connect.xml @@ -0,0 +1,106 @@ + + + + +// Wrap the POSIX file descriptor. This is an internal NSPR +// function, but it is very unlikely to change. +PRFileDesc* nspr = PR_ImportTCPSocket(sockfd); +sockfd = -1; // Has been taken over by NSPR. + +// Add the SSL layer. +{ + PRFileDesc *model = PR_NewTCPSocket(); + PRFileDesc *newfd = SSL_ImportFD(NULL, model); + if (newfd == NULL) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: NSPR error code %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); + } + model = newfd; + newfd = NULL; + if (SSL_OptionSet(model, SSL_ENABLE_SSL2, PR_FALSE) != SECSuccess) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: set SSL_ENABLE_SSL2 error %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); + } + if (SSL_OptionSet(model, SSL_V2_COMPATIBLE_HELLO, PR_FALSE) != SECSuccess) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: set SSL_V2_COMPATIBLE_HELLO error %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); + } + if (SSL_OptionSet(model, SSL_ENABLE_DEFLATE, PR_FALSE) != SECSuccess) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: set SSL_ENABLE_DEFLATE error %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); + } + + // Disable all ciphers (except RC4-based ciphers, for backwards + // compatibility). + const PRUint16 *const ciphers = SSL_GetImplementedCiphers(); + for (unsigned i = 0; i < SSL_GetNumImplementedCiphers(); i++) { + if (ciphers[i] != SSL_RSA_WITH_RC4_128_SHA + && ciphers[i] != SSL_RSA_WITH_RC4_128_MD5) { + if (SSL_CipherPrefSet(model, ciphers[i], PR_FALSE) != SECSuccess) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: disable cipher %u: error %d: %s\n", + (unsigned)ciphers[i], err, PR_ErrorToName(err)); + exit(1); + } + } + } + + // Enable the strong ciphers. + for (const PRUint16 *p = good_ciphers; *p != SSL_NULL_WITH_NULL_NULL; + ++p) { + if (SSL_CipherPrefSet(model, *p, PR_TRUE) != SECSuccess) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: enable cipher %u: error %d: %s\n", + (unsigned)*p, err, PR_ErrorToName(err)); + exit(1); + } + } + + // Allow overriding invalid certificate. + if (SSL_BadCertHook(model, bad_certificate, (char *)host) != SECSuccess) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: SSL_BadCertHook error %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); + } + + newfd = SSL_ImportFD(model, nspr); + if (newfd == NULL) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: SSL_ImportFD error %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); + } + nspr = newfd; + PR_Close(model); +} + +// Perform the handshake. +if (SSL_ResetHandshake(nspr, PR_FALSE) != SECSuccess) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: SSL_ResetHandshake error %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); +} +if (SSL_SetURL(nspr, host) != SECSuccess) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: SSL_SetURL error %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); +} +if (SSL_ForceHandshake(nspr) != SECSuccess) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: SSL_ForceHandshake error %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); +} + diff --git a/defensive-coding/en-US/Features/snippets/TLS-Client-OpenJDK-Connect.xml b/defensive-coding/en-US/Features/snippets/TLS-Client-OpenJDK-Connect.xml new file mode 100644 index 0000000..40cc623 --- /dev/null +++ b/defensive-coding/en-US/Features/snippets/TLS-Client-OpenJDK-Connect.xml @@ -0,0 +1,26 @@ + + + + +// Create the socket and connect it at the TCP layer. +SSLSocket socket = (SSLSocket) ctx.getSocketFactory() + .createSocket(host, port); + +// Disable the Nagle algorithm. +socket.setTcpNoDelay(true); + +// Adjust ciphers and protocols. +socket.setSSLParameters(params); + +// Perform the handshake. +socket.startHandshake(); + +// Validate the host name. The match() method throws +// CertificateException on failure. +X509Certificate peer = (X509Certificate) + socket.getSession().getPeerCertificates()[0]; +// This is the only way to perform host name checking on OpenJDK 6. +HostnameChecker.getInstance(HostnameChecker.TYPE_TLS).match( + host, peer); + diff --git a/defensive-coding/en-US/Features/snippets/TLS-Client-OpenJDK-Context.xml b/defensive-coding/en-US/Features/snippets/TLS-Client-OpenJDK-Context.xml new file mode 100644 index 0000000..b7fde16 --- /dev/null +++ b/defensive-coding/en-US/Features/snippets/TLS-Client-OpenJDK-Context.xml @@ -0,0 +1,26 @@ + + + + +// Create the context. Specify the SunJSSE provider to avoid +// picking up third-party providers. Try the TLS 1.2 provider +// first, then fall back to TLS 1.0. +SSLContext ctx; +try { + ctx = SSLContext.getInstance("TLSv1.2", "SunJSSE"); +} catch (NoSuchAlgorithmException e) { + try { + ctx = SSLContext.getInstance("TLSv1", "SunJSSE"); + } catch (NoSuchAlgorithmException e1) { + // The TLS 1.0 provider should always be available. + throw new AssertionError(e1); + } catch (NoSuchProviderException e1) { + throw new AssertionError(e1); + } +} catch (NoSuchProviderException e) { + // The SunJSSE provider should always be available. + throw new AssertionError(e); +} +ctx.init(null, null, null); + diff --git a/defensive-coding/en-US/Features/snippets/TLS-Client-OpenJDK-Context_For_Cert.xml b/defensive-coding/en-US/Features/snippets/TLS-Client-OpenJDK-Context_For_Cert.xml new file mode 100644 index 0000000..6004157 --- /dev/null +++ b/defensive-coding/en-US/Features/snippets/TLS-Client-OpenJDK-Context_For_Cert.xml @@ -0,0 +1,22 @@ + + + + +SSLContext ctx; +try { + ctx = SSLContext.getInstance("TLSv1.2", "SunJSSE"); +} catch (NoSuchAlgorithmException e) { + try { + ctx = SSLContext.getInstance("TLSv1", "SunJSSE"); + } catch (NoSuchAlgorithmException e1) { + throw new AssertionError(e1); + } catch (NoSuchProviderException e1) { + throw new AssertionError(e1); + } +} catch (NoSuchProviderException e) { + throw new AssertionError(e); +} +MyTrustManager tm = new MyTrustManager(certHash); +ctx.init(null, new TrustManager[] {tm}, null); + diff --git a/defensive-coding/en-US/Features/snippets/TLS-Client-OpenJDK-Hostname.xml b/defensive-coding/en-US/Features/snippets/TLS-Client-OpenJDK-Hostname.xml new file mode 100644 index 0000000..586cb7b --- /dev/null +++ b/defensive-coding/en-US/Features/snippets/TLS-Client-OpenJDK-Hostname.xml @@ -0,0 +1,7 @@ + + + + +params.setEndpointIdentificationAlgorithm("HTTPS"); + diff --git a/defensive-coding/en-US/Features/snippets/TLS-Client-OpenJDK-Import.xml b/defensive-coding/en-US/Features/snippets/TLS-Client-OpenJDK-Import.xml new file mode 100644 index 0000000..57c9343 --- /dev/null +++ b/defensive-coding/en-US/Features/snippets/TLS-Client-OpenJDK-Import.xml @@ -0,0 +1,18 @@ + + + + +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.cert.CertificateEncodingException; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLParameters; +import javax.net.ssl.SSLSocket; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; + +import sun.security.util.HostnameChecker; + diff --git a/defensive-coding/en-US/Features/snippets/TLS-Client-OpenJDK-MyTrustManager.xml b/defensive-coding/en-US/Features/snippets/TLS-Client-OpenJDK-MyTrustManager.xml new file mode 100644 index 0000000..43fd12b --- /dev/null +++ b/defensive-coding/en-US/Features/snippets/TLS-Client-OpenJDK-MyTrustManager.xml @@ -0,0 +1,38 @@ + + + + +public class MyTrustManager implements X509TrustManager { + private final byte[] certHash; + + public MyTrustManager(byte[] certHash) throws Exception { + this.certHash = certHash; + } + + @Override + public void checkClientTrusted(X509Certificate[] chain, String authType) + throws CertificateException { + throw new UnsupportedOperationException(); + } + + @Override + public void checkServerTrusted(X509Certificate[] chain, + String authType) throws CertificateException { + byte[] digest = getCertificateDigest(chain[0]); + String digestHex = formatHex(digest); + + if (Arrays.equals(digest, certHash)) { + System.err.println("info: accepting certificate: " + digestHex); + } else { + throw new CertificateException("certificate rejected: " + + digestHex); + } + } + + @Override + public X509Certificate[] getAcceptedIssuers() { + return new X509Certificate[0]; + } +} + diff --git a/defensive-coding/en-US/Features/snippets/TLS-Client-OpenJDK-Use.xml b/defensive-coding/en-US/Features/snippets/TLS-Client-OpenJDK-Use.xml new file mode 100644 index 0000000..11d708a --- /dev/null +++ b/defensive-coding/en-US/Features/snippets/TLS-Client-OpenJDK-Use.xml @@ -0,0 +1,11 @@ + + + + +socket.getOutputStream().write("GET / HTTP/1.0\r\n\r\n" + .getBytes(Charset.forName("UTF-8"))); +byte[] buffer = new byte[4096]; +int count = socket.getInputStream().read(buffer); +System.out.write(buffer, 0, count); + diff --git a/defensive-coding/en-US/Features/snippets/TLS-Client-OpenSSL-CTX.xml b/defensive-coding/en-US/Features/snippets/TLS-Client-OpenSSL-CTX.xml new file mode 100644 index 0000000..05e2854 --- /dev/null +++ b/defensive-coding/en-US/Features/snippets/TLS-Client-OpenSSL-CTX.xml @@ -0,0 +1,71 @@ + + + + +// Configure a client connection context. Send a hendshake for the +// highest supported TLS version, and disable compression. +const SSL_METHOD *const req_method = SSLv23_client_method(); +SSL_CTX *const ctx = SSL_CTX_new(req_method); +if (ctx == NULL) { + ERR_print_errors(bio_err); + exit(1); +} +SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_COMPRESSION); + +// Adjust the ciphers list based on a whitelist. First enable all +// ciphers of at least medium strength, to get the list which is +// compiled into OpenSSL. +if (SSL_CTX_set_cipher_list(ctx, "HIGH:MEDIUM") != 1) { + ERR_print_errors(bio_err); + exit(1); +} +{ + // Create a dummy SSL session to obtain the cipher list. + SSL *ssl = SSL_new(ctx); + if (ssl == NULL) { + ERR_print_errors(bio_err); + exit(1); + } + STACK_OF(SSL_CIPHER) *active_ciphers = SSL_get_ciphers(ssl); + if (active_ciphers == NULL) { + ERR_print_errors(bio_err); + exit(1); + } + // Whitelist of candidate ciphers. + static const char *const candidates[] = { + "AES128-GCM-SHA256", "AES128-SHA256", "AES256-SHA256", // strong ciphers + "AES128-SHA", "AES256-SHA", // strong ciphers, also in older versions + "RC4-SHA", "RC4-MD5", // backwards compatibility, supposed to be weak + "DES-CBC3-SHA", "DES-CBC3-MD5", // more backwards compatibility + NULL + }; + // Actually selected ciphers. + char ciphers[300]; + ciphers[0] = '\0'; + for (const char *const *c = candidates; *c; ++c) { + for (int i = 0; i < sk_SSL_CIPHER_num(active_ciphers); ++i) { + if (strcmp(SSL_CIPHER_get_name(sk_SSL_CIPHER_value(active_ciphers, i)), + *c) == 0) { + if (*ciphers) { + strcat(ciphers, ":"); + } + strcat(ciphers, *c); + break; + } + } + } + SSL_free(ssl); + // Apply final cipher list. + if (SSL_CTX_set_cipher_list(ctx, ciphers) != 1) { + ERR_print_errors(bio_err); + exit(1); + } +} + +// Load the set of trusted root certificates. +if (!SSL_CTX_set_default_verify_paths(ctx)) { + ERR_print_errors(bio_err); + exit(1); +} + diff --git a/defensive-coding/en-US/Features/snippets/TLS-Client-OpenSSL-Connect.xml b/defensive-coding/en-US/Features/snippets/TLS-Client-OpenSSL-Connect.xml new file mode 100644 index 0000000..5cd433d --- /dev/null +++ b/defensive-coding/en-US/Features/snippets/TLS-Client-OpenSSL-Connect.xml @@ -0,0 +1,55 @@ + + + + +// Create the connection object. +SSL *ssl = SSL_new(ctx); +if (ssl == NULL) { + ERR_print_errors(bio_err); + exit(1); +} +SSL_set_fd(ssl, sockfd); + +// Enable the ServerNameIndication extension +if (!SSL_set_tlsext_host_name(ssl, host)) { + ERR_print_errors(bio_err); + exit(1); +} + +// Perform the TLS handshake with the server. +ret = SSL_connect(ssl); +if (ret != 1) { + // Error status can be 0 or negative. + ssl_print_error_and_exit(ssl, "SSL_connect", ret); +} + +// Obtain the server certificate. +X509 *peercert = SSL_get_peer_certificate(ssl); +if (peercert == NULL) { + fprintf(stderr, "peer certificate missing"); + exit(1); +} + +// Check the certificate verification result. Allow an explicit +// certificate validation override in case verification fails. +int verifystatus = SSL_get_verify_result(ssl); +if (verifystatus != X509_V_OK && !certificate_validity_override(peercert)) { + fprintf(stderr, "SSL_connect: verify result: %s\n", + X509_verify_cert_error_string(verifystatus)); + exit(1); +} + +// Check if the server certificate matches the host name used to +// establish the connection. +// FIXME: Currently needs OpenSSL 1.1. +if (X509_check_host(peercert, (const unsigned char *)host, strlen(host), + 0) != 1 + && !certificate_host_name_override(peercert, host)) { + fprintf(stderr, "SSL certificate does not match host name\n"); + exit(1); +} + +X509_free(peercert); + + diff --git a/defensive-coding/en-US/Features/snippets/TLS-Client-OpenSSL-Connection-Use.xml b/defensive-coding/en-US/Features/snippets/TLS-Client-OpenSSL-Connection-Use.xml new file mode 100644 index 0000000..ab54edf --- /dev/null +++ b/defensive-coding/en-US/Features/snippets/TLS-Client-OpenSSL-Connection-Use.xml @@ -0,0 +1,15 @@ + + + + +const char *const req = "GET / HTTP/1.0\r\n\r\n"; +if (SSL_write(ssl, req, strlen(req)) < 0) { + ssl_print_error_and_exit(ssl, "SSL_write", ret); +} +char buf[4096]; +ret = SSL_read(ssl, buf, sizeof(buf)); +if (ret < 0) { + ssl_print_error_and_exit(ssl, "SSL_read", ret); +} + diff --git a/defensive-coding/en-US/Features/snippets/TLS-Client-OpenSSL-Init.xml b/defensive-coding/en-US/Features/snippets/TLS-Client-OpenSSL-Init.xml new file mode 100644 index 0000000..8211ce8 --- /dev/null +++ b/defensive-coding/en-US/Features/snippets/TLS-Client-OpenSSL-Init.xml @@ -0,0 +1,13 @@ + + + + +// The following call prints an error message and calls exit() if +// the OpenSSL configuration file is unreadable. +OPENSSL_config(NULL); +// Provide human-readable error messages. +SSL_load_error_strings(); +// Register ciphers. +SSL_library_init(); + diff --git a/defensive-coding/en-US/Features/snippets/TLS-Client-Python-Connect.xml b/defensive-coding/en-US/Features/snippets/TLS-Client-Python-Connect.xml new file mode 100644 index 0000000..0e98e87 --- /dev/null +++ b/defensive-coding/en-US/Features/snippets/TLS-Client-Python-Connect.xml @@ -0,0 +1,14 @@ + + + + +sock = ssl.wrap_socket(sock, + ciphers="HIGH:-aNULL:-eNULL:-PSK:RC4-SHA:RC4-MD5", + ssl_version=ssl.PROTOCOL_TLSv1, + cert_reqs=ssl.CERT_REQUIRED, + ca_certs='/etc/ssl/certs/ca-bundle.crt') +# getpeercert() triggers the handshake as a side effect. +if not check_host_name(sock.getpeercert(), host): + raise IOError("peer certificate does not match host name") + diff --git a/defensive-coding/en-US/Features/snippets/TLS-Client-Python-check_host_name.xml b/defensive-coding/en-US/Features/snippets/TLS-Client-Python-check_host_name.xml new file mode 100644 index 0000000..3c325f8 --- /dev/null +++ b/defensive-coding/en-US/Features/snippets/TLS-Client-Python-check_host_name.xml @@ -0,0 +1,29 @@ + + + + +def check_host_name(peercert, name): + """Simple certificate/host name checker. Returns True if the + certificate matches, False otherwise. Does not support + wildcards.""" + # Check that the peer has supplied a certificate. + # None/{} is not acceptable. + if not peercert: + return False + if peercert.has_key("subjectAltName"): + for typ, val in peercert["subjectAltName"]: + if typ == "DNS" and val == name: + return True + else: + # Only check the subject DN if there is no subject alternative + # name. + cn = None + for attr, val in peercert["subject"]: + # Use most-specific (last) commonName attribute. + if attr == "commonName": + cn = val + if cn is not None: + return cn == name + return False + diff --git a/defensive-coding/en-US/Features/snippets/TLS-GNUTLS-Credentials-Close.xml b/defensive-coding/en-US/Features/snippets/TLS-GNUTLS-Credentials-Close.xml new file mode 100644 index 0000000..8c28b0f --- /dev/null +++ b/defensive-coding/en-US/Features/snippets/TLS-GNUTLS-Credentials-Close.xml @@ -0,0 +1,7 @@ + + + + +gnutls_certificate_free_credentials(cred); + diff --git a/defensive-coding/en-US/Features/snippets/TLS-GNUTLS-Disconnect.xml b/defensive-coding/en-US/Features/snippets/TLS-GNUTLS-Disconnect.xml new file mode 100644 index 0000000..b01464d --- /dev/null +++ b/defensive-coding/en-US/Features/snippets/TLS-GNUTLS-Disconnect.xml @@ -0,0 +1,14 @@ + + + + +// Initiate an orderly connection shutdown. +ret = gnutls_bye(session, GNUTLS_SHUT_RDWR); +if (ret < 0) { + fprintf(stderr, "error: gnutls_bye: %s\n", gnutls_strerror(ret)); + exit(1); +} +// Free the session object. +gnutls_deinit(session); + diff --git a/defensive-coding/en-US/Features/snippets/TLS-GNUTLS-Init.xml b/defensive-coding/en-US/Features/snippets/TLS-GNUTLS-Init.xml new file mode 100644 index 0000000..519522e --- /dev/null +++ b/defensive-coding/en-US/Features/snippets/TLS-GNUTLS-Init.xml @@ -0,0 +1,7 @@ + + + + +gnutls_global_init(); + diff --git a/defensive-coding/en-US/Features/snippets/TLS-GNUTLS-Use.xml b/defensive-coding/en-US/Features/snippets/TLS-GNUTLS-Use.xml new file mode 100644 index 0000000..a6a3f9c --- /dev/null +++ b/defensive-coding/en-US/Features/snippets/TLS-GNUTLS-Use.xml @@ -0,0 +1,18 @@ + + + + +char buf[4096]; +snprintf(buf, sizeof(buf), "GET / HTTP/1.0\r\nHost: %s\r\n\r\n", host); +ret = gnutls_record_send(session, buf, strlen(buf)); +if (ret < 0) { + fprintf(stderr, "error: gnutls_record_send: %s\n", gnutls_strerror(ret)); + exit(1); +} +ret = gnutls_record_recv(session, buf, sizeof(buf)); +if (ret < 0) { + fprintf(stderr, "error: gnutls_record_recv: %s\n", gnutls_strerror(ret)); + exit(1); +} + diff --git a/defensive-coding/en-US/Features/snippets/TLS-NSS-Close.xml b/defensive-coding/en-US/Features/snippets/TLS-NSS-Close.xml new file mode 100644 index 0000000..e34cea8 --- /dev/null +++ b/defensive-coding/en-US/Features/snippets/TLS-NSS-Close.xml @@ -0,0 +1,8 @@ + + + + +SECMOD_DestroyModule(module); +NSS_ShutdownContext(ctx); + diff --git a/defensive-coding/en-US/Features/snippets/TLS-NSS-Includes.xml b/defensive-coding/en-US/Features/snippets/TLS-NSS-Includes.xml new file mode 100644 index 0000000..ee183d0 --- /dev/null +++ b/defensive-coding/en-US/Features/snippets/TLS-NSS-Includes.xml @@ -0,0 +1,20 @@ + + + + +// NSPR include files +#include <prerror.h> +#include <prinit.h> + +// NSS include files +#include <nss.h> +#include <pk11pub.h> +#include <secmod.h> +#include <ssl.h> +#include <sslproto.h> + +// Private API, no other way to turn a POSIX file descriptor into an +// NSPR handle. +NSPR_API(PRFileDesc*) PR_ImportTCPSocket(int); + diff --git a/defensive-coding/en-US/Features/snippets/TLS-NSS-Init.xml b/defensive-coding/en-US/Features/snippets/TLS-NSS-Init.xml new file mode 100644 index 0000000..d56651b --- /dev/null +++ b/defensive-coding/en-US/Features/snippets/TLS-NSS-Init.xml @@ -0,0 +1,63 @@ + + + + +PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); +NSSInitContext *const ctx = + NSS_InitContext("sql:/etc/pki/nssdb", "", "", "", NULL, + NSS_INIT_READONLY | NSS_INIT_PK11RELOAD); +if (ctx == NULL) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: NSPR error code %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); +} + +// Ciphers to enable. +static const PRUint16 good_ciphers[] = { + TLS_RSA_WITH_AES_128_CBC_SHA, + TLS_RSA_WITH_AES_256_CBC_SHA, + SSL_RSA_WITH_3DES_EDE_CBC_SHA, + SSL_NULL_WITH_NULL_NULL // sentinel +}; + +// Check if the current policy allows any strong ciphers. If it +// doesn't, switch to the "domestic" (unrestricted) policy. This is +// not thread-safe and has global impact. Consequently, we only do +// it if absolutely necessary. +int found_good_cipher = 0; +for (const PRUint16 *p = good_ciphers; *p != SSL_NULL_WITH_NULL_NULL; + ++p) { + PRInt32 policy; + if (SSL_CipherPolicyGet(*p, &policy) != SECSuccess) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: policy for cipher %u: error %d: %s\n", + (unsigned)*p, err, PR_ErrorToName(err)); + exit(1); + } + if (policy == SSL_ALLOWED) { + fprintf(stderr, "info: found cipher %x\n", (unsigned)*p); + found_good_cipher = 1; + break; + } +} +if (!found_good_cipher) { + if (NSS_SetDomesticPolicy() != SECSuccess) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: NSS_SetDomesticPolicy: error %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); + } +} + +// Initialize the trusted certificate store. +char module_name[] = "library=libnssckbi.so name=\"Root Certs\""; +SECMODModule *module = SECMOD_LoadUserModule(module_name, NULL, PR_FALSE); +if (module == NULL || !module->loaded) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: NSPR error code %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); +} + diff --git a/defensive-coding/en-US/Features/snippets/TLS-NSS-Use.xml b/defensive-coding/en-US/Features/snippets/TLS-NSS-Use.xml new file mode 100644 index 0000000..f1a0c6d --- /dev/null +++ b/defensive-coding/en-US/Features/snippets/TLS-NSS-Use.xml @@ -0,0 +1,22 @@ + + + + +char buf[4096]; +snprintf(buf, sizeof(buf), "GET / HTTP/1.0\r\nHost: %s\r\n\r\n", host); +PRInt32 ret = PR_Write(nspr, buf, strlen(buf)); +if (ret < 0) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: PR_Write error %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); +} +ret = PR_Read(nspr, buf, sizeof(buf)); +if (ret < 0) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: PR_Read error %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); +} + diff --git a/defensive-coding/en-US/Features/snippets/TLS-Nagle.xml b/defensive-coding/en-US/Features/snippets/TLS-Nagle.xml new file mode 100644 index 0000000..824fab5 --- /dev/null +++ b/defensive-coding/en-US/Features/snippets/TLS-Nagle.xml @@ -0,0 +1,12 @@ + + + + +const int val = 1; +int ret = setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val)); +if (ret < 0) { + perror("setsockopt(TCP_NODELAY)"); + exit(1); +} + diff --git a/defensive-coding/en-US/Features/snippets/TLS-OpenJDK-Parameters.xml b/defensive-coding/en-US/Features/snippets/TLS-OpenJDK-Parameters.xml new file mode 100644 index 0000000..af48ca6 --- /dev/null +++ b/defensive-coding/en-US/Features/snippets/TLS-OpenJDK-Parameters.xml @@ -0,0 +1,27 @@ + + + + +// Prepare TLS parameters. These have to applied to every TLS +// socket before the handshake is triggered. +SSLParameters params = ctx.getDefaultSSLParameters(); +// Do not send an SSL-2.0-compatible Client Hello. +ArrayList<String> protocols = new ArrayList<String>( + Arrays.asList(params.getProtocols())); +protocols.remove("SSLv2Hello"); +params.setProtocols(protocols.toArray(new String[protocols.size()])); +// Adjust the supported ciphers. +ArrayList<String> ciphers = new ArrayList<String>( + Arrays.asList(params.getCipherSuites())); +ciphers.retainAll(Arrays.asList( + "TLS_RSA_WITH_AES_128_CBC_SHA256", + "TLS_RSA_WITH_AES_256_CBC_SHA256", + "TLS_RSA_WITH_AES_256_CBC_SHA", + "TLS_RSA_WITH_AES_128_CBC_SHA", + "SSL_RSA_WITH_3DES_EDE_CBC_SHA", + "SSL_RSA_WITH_RC4_128_SHA1", + "SSL_RSA_WITH_RC4_128_MD5", + "TLS_EMPTY_RENEGOTIATION_INFO_SCSV")); +params.setCipherSuites(ciphers.toArray(new String[ciphers.size()])); + diff --git a/defensive-coding/en-US/Features/snippets/TLS-OpenSSL-Connection-Close.xml b/defensive-coding/en-US/Features/snippets/TLS-OpenSSL-Connection-Close.xml new file mode 100644 index 0000000..0e446ef --- /dev/null +++ b/defensive-coding/en-US/Features/snippets/TLS-OpenSSL-Connection-Close.xml @@ -0,0 +1,30 @@ + + + + +// Send the close_notify alert. +ret = SSL_shutdown(ssl); +switch (ret) { +case 1: + // A close_notify alert has already been received. + break; +case 0: + // Wait for the close_notify alert from the peer. + ret = SSL_shutdown(ssl); + switch (ret) { + case 0: + fprintf(stderr, "info: second SSL_shutdown returned zero\n"); + break; + case 1: + break; + default: + ssl_print_error_and_exit(ssl, "SSL_shutdown 2", ret); + } + break; +default: + ssl_print_error_and_exit(ssl, "SSL_shutdown 1", ret); +} +SSL_free(ssl); +close(sockfd); + diff --git a/defensive-coding/en-US/Features/snippets/TLS-OpenSSL-Context-Close.xml b/defensive-coding/en-US/Features/snippets/TLS-OpenSSL-Context-Close.xml new file mode 100644 index 0000000..89a324e --- /dev/null +++ b/defensive-coding/en-US/Features/snippets/TLS-OpenSSL-Context-Close.xml @@ -0,0 +1,7 @@ + + + + +SSL_CTX_free(ctx); + diff --git a/defensive-coding/en-US/Features/snippets/TLS-OpenSSL-Errors.xml b/defensive-coding/en-US/Features/snippets/TLS-OpenSSL-Errors.xml new file mode 100644 index 0000000..ab16ce7 --- /dev/null +++ b/defensive-coding/en-US/Features/snippets/TLS-OpenSSL-Errors.xml @@ -0,0 +1,31 @@ + + + + +static void __attribute__((noreturn)) +ssl_print_error_and_exit(SSL *ssl, const char *op, int ret) +{ + int subcode = SSL_get_error(ssl, ret); + switch (subcode) { + case SSL_ERROR_NONE: + fprintf(stderr, "error: %s: no error to report\n", op); + break; + case SSL_ERROR_WANT_READ: + case SSL_ERROR_WANT_WRITE: + case SSL_ERROR_WANT_X509_LOOKUP: + case SSL_ERROR_WANT_CONNECT: + case SSL_ERROR_WANT_ACCEPT: + fprintf(stderr, "error: %s: invalid blocking state %d\n", op, subcode); + break; + case SSL_ERROR_SSL: + fprintf(stderr, "error: %s: TLS layer problem\n", op); + case SSL_ERROR_SYSCALL: + fprintf(stderr, "error: %s: system call failed: %s\n", op, strerror(errno)); + break; + case SSL_ERROR_ZERO_RETURN: + fprintf(stderr, "error: %s: zero return\n", op); + } + exit(1); +} + diff --git a/defensive-coding/en-US/Features/snippets/TLS-Python-Close.xml b/defensive-coding/en-US/Features/snippets/TLS-Python-Close.xml new file mode 100644 index 0000000..fd20ff2 --- /dev/null +++ b/defensive-coding/en-US/Features/snippets/TLS-Python-Close.xml @@ -0,0 +1,7 @@ + + + + +sock.close() + diff --git a/defensive-coding/en-US/Features/snippets/TLS-Python-Use.xml b/defensive-coding/en-US/Features/snippets/TLS-Python-Use.xml new file mode 100644 index 0000000..08690ca --- /dev/null +++ b/defensive-coding/en-US/Features/snippets/TLS-Python-Use.xml @@ -0,0 +1,8 @@ + + + + +sock.write("GET / HTTP/1.1\r\nHost: " + host + "\r\n\r\n") +print sock.read() + diff --git a/defensive-coding/en-US/Python/.svn/all-wcprops b/defensive-coding/en-US/Python/.svn/all-wcprops new file mode 100644 index 0000000..33d4e7b --- /dev/null +++ b/defensive-coding/en-US/Python/.svn/all-wcprops @@ -0,0 +1,17 @@ +K 25 +svn:wc:ra_dav:version-url +V 72 +/repos/product-security/!svn/ver/292/defensive-coding/trunk/en-US/Python +END +Language.xml +K 25 +svn:wc:ra_dav:version-url +V 85 +/repos/product-security/!svn/ver/281/defensive-coding/trunk/en-US/Python/Language.xml +END +schemas.xml +K 25 +svn:wc:ra_dav:version-url +V 84 +/repos/product-security/!svn/ver/292/defensive-coding/trunk/en-US/Python/schemas.xml +END diff --git a/defensive-coding/en-US/Python/.svn/dir-prop-base b/defensive-coding/en-US/Python/.svn/dir-prop-base new file mode 100644 index 0000000..b0e5252 --- /dev/null +++ b/defensive-coding/en-US/Python/.svn/dir-prop-base @@ -0,0 +1,6 @@ +K 10 +svn:ignore +V 9 +snippets + +END diff --git a/defensive-coding/en-US/Python/.svn/entries b/defensive-coding/en-US/Python/.svn/entries new file mode 100644 index 0000000..2f278e2 --- /dev/null +++ b/defensive-coding/en-US/Python/.svn/entries @@ -0,0 +1,96 @@ +10 + +dir +305 +https://svn.devel.redhat.com/repos/product-security/defensive-coding/trunk/en-US/Python +https://svn.devel.redhat.com/repos/product-security + + + +2012-12-14T10:18:44.472257Z +292 +fweimer@REDHAT.COM +has-props + + + + + + + + + + + + + +9bd5cf0f-f2b3-0410-b1a9-d5c590f50bf1 + +Language.xml +file + + + + +2013-01-10T17:17:40.317763Z +00327c6f05b6d4d52a043fe8caff08b9 +2012-12-13T13:25:23.103424Z +281 +fweimer@REDHAT.COM +has-props + + + + + + + + + + + + + + + + + + + + +2620 + +schemas.xml +file + + + + +2013-01-10T17:17:40.317763Z +769bc2635d36b318161574a1adf2f6e7 +2012-12-14T10:18:44.472257Z +292 +fweimer@REDHAT.COM +has-props + + + + + + + + + + + + + + + + + + + + +150 + diff --git a/defensive-coding/en-US/Python/.svn/prop-base/Language.xml.svn-base b/defensive-coding/en-US/Python/.svn/prop-base/Language.xml.svn-base new file mode 100644 index 0000000..bfec7d5 --- /dev/null +++ b/defensive-coding/en-US/Python/.svn/prop-base/Language.xml.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 8 +text/xml +END diff --git a/defensive-coding/en-US/Python/.svn/prop-base/schemas.xml.svn-base b/defensive-coding/en-US/Python/.svn/prop-base/schemas.xml.svn-base new file mode 100644 index 0000000..bfec7d5 --- /dev/null +++ b/defensive-coding/en-US/Python/.svn/prop-base/schemas.xml.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 8 +text/xml +END diff --git a/defensive-coding/en-US/Python/.svn/text-base/Language.xml.svn-base b/defensive-coding/en-US/Python/.svn/text-base/Language.xml.svn-base new file mode 100644 index 0000000..5cfec8f --- /dev/null +++ b/defensive-coding/en-US/Python/.svn/text-base/Language.xml.svn-base @@ -0,0 +1,74 @@ + + + + The Python Programming Language + + Python provides memory safety by default, so low-level security + vulnerabilities are rare and typically needs fixing the Python + interpreter or standard library itself. + + + Other sections with Python-specific advice include: + + + + + + + + + + + + + + + , in + particular + + + + + + + + +
+ Dangerous standard library features + + Some areas of the standard library, notably the + ctypes module, do not provide memory safety + guarantees comparable to the rest of Python. If such + functionality is used, the advice in should be followed. + +
+
+ Run-time compilation and code generation + + The following Python functions and statements related to code + execution should be avoided: + + + compile + eval + exec + execfile + + + If you need to parse integers or floating point values, use the + int and float + functions instead of eval. Sandboxing + untrusted Python code does not work reliably. + +
+
+ Sandboxing + + The rexec Python module cannot safely sandbox + untrusted code and should not be used. The standard CPython + implementation is not suitable for sandboxing. + +
+
diff --git a/defensive-coding/en-US/Python/.svn/text-base/schemas.xml.svn-base b/defensive-coding/en-US/Python/.svn/text-base/schemas.xml.svn-base new file mode 100644 index 0000000..8e84245 --- /dev/null +++ b/defensive-coding/en-US/Python/.svn/text-base/schemas.xml.svn-base @@ -0,0 +1,4 @@ + + + + diff --git a/defensive-coding/en-US/Python/Language.xml b/defensive-coding/en-US/Python/Language.xml new file mode 100644 index 0000000..5cfec8f --- /dev/null +++ b/defensive-coding/en-US/Python/Language.xml @@ -0,0 +1,74 @@ + + + + The Python Programming Language + + Python provides memory safety by default, so low-level security + vulnerabilities are rare and typically needs fixing the Python + interpreter or standard library itself. + + + Other sections with Python-specific advice include: + + + + + + + + + + + + + + + , in + particular + + + + + + + + +
+ Dangerous standard library features + + Some areas of the standard library, notably the + ctypes module, do not provide memory safety + guarantees comparable to the rest of Python. If such + functionality is used, the advice in should be followed. + +
+
+ Run-time compilation and code generation + + The following Python functions and statements related to code + execution should be avoided: + + + compile + eval + exec + execfile + + + If you need to parse integers or floating point values, use the + int and float + functions instead of eval. Sandboxing + untrusted Python code does not work reliably. + +
+
+ Sandboxing + + The rexec Python module cannot safely sandbox + untrusted code and should not be used. The standard CPython + implementation is not suitable for sandboxing. + +
+
diff --git a/defensive-coding/en-US/Python/schemas.xml b/defensive-coding/en-US/Python/schemas.xml new file mode 100644 index 0000000..8e84245 --- /dev/null +++ b/defensive-coding/en-US/Python/schemas.xml @@ -0,0 +1,4 @@ + + + + diff --git a/defensive-coding/en-US/Revision_History.xml b/defensive-coding/en-US/Revision_History.xml new file mode 100644 index 0000000..c9f6483 --- /dev/null +++ b/defensive-coding/en-US/Revision_History.xml @@ -0,0 +1,27 @@ + + +%BOOK_ENTITIES; +]> + + Revision History + + + + 0-1 + Thu Mar 7 2013 + + Eric + Christensen + sparks@redhat.com + + + + Initial publication. + + + + + + + diff --git a/defensive-coding/en-US/Tasks/.svn/all-wcprops b/defensive-coding/en-US/Tasks/.svn/all-wcprops new file mode 100644 index 0000000..0d902b9 --- /dev/null +++ b/defensive-coding/en-US/Tasks/.svn/all-wcprops @@ -0,0 +1,59 @@ +K 25 +svn:wc:ra_dav:version-url +V 71 +/repos/product-security/!svn/ver/294/defensive-coding/trunk/en-US/Tasks +END +Descriptors.xml +K 25 +svn:wc:ra_dav:version-url +V 87 +/repos/product-security/!svn/ver/281/defensive-coding/trunk/en-US/Tasks/Descriptors.xml +END +File_System.xml +K 25 +svn:wc:ra_dav:version-url +V 87 +/repos/product-security/!svn/ver/281/defensive-coding/trunk/en-US/Tasks/File_System.xml +END +schemas.xml +K 25 +svn:wc:ra_dav:version-url +V 83 +/repos/product-security/!svn/ver/292/defensive-coding/trunk/en-US/Tasks/schemas.xml +END +Temporary_Files.xml +K 25 +svn:wc:ra_dav:version-url +V 91 +/repos/product-security/!svn/ver/281/defensive-coding/trunk/en-US/Tasks/Temporary_Files.xml +END +Locking.xml +K 25 +svn:wc:ra_dav:version-url +V 83 +/repos/product-security/!svn/ver/292/defensive-coding/trunk/en-US/Tasks/Locking.xml +END +Processes.xml +K 25 +svn:wc:ra_dav:version-url +V 85 +/repos/product-security/!svn/ver/281/defensive-coding/trunk/en-US/Tasks/Processes.xml +END +Cryptography.xml +K 25 +svn:wc:ra_dav:version-url +V 88 +/repos/product-security/!svn/ver/281/defensive-coding/trunk/en-US/Tasks/Cryptography.xml +END +Library_Design.xml +K 25 +svn:wc:ra_dav:version-url +V 90 +/repos/product-security/!svn/ver/281/defensive-coding/trunk/en-US/Tasks/Library_Design.xml +END +Serialization.xml +K 25 +svn:wc:ra_dav:version-url +V 89 +/repos/product-security/!svn/ver/294/defensive-coding/trunk/en-US/Tasks/Serialization.xml +END diff --git a/defensive-coding/en-US/Tasks/.svn/dir-prop-base b/defensive-coding/en-US/Tasks/.svn/dir-prop-base new file mode 100644 index 0000000..b0e5252 --- /dev/null +++ b/defensive-coding/en-US/Tasks/.svn/dir-prop-base @@ -0,0 +1,6 @@ +K 10 +svn:ignore +V 9 +snippets + +END diff --git a/defensive-coding/en-US/Tasks/.svn/entries b/defensive-coding/en-US/Tasks/.svn/entries new file mode 100644 index 0000000..5e2b13e --- /dev/null +++ b/defensive-coding/en-US/Tasks/.svn/entries @@ -0,0 +1,334 @@ +10 + +dir +305 +https://svn.devel.redhat.com/repos/product-security/defensive-coding/trunk/en-US/Tasks +https://svn.devel.redhat.com/repos/product-security + + + +2012-12-19T14:04:47.671665Z +294 +fweimer@REDHAT.COM +has-props + + + + + + + + + + + + + +9bd5cf0f-f2b3-0410-b1a9-d5c590f50bf1 + +Descriptors.xml +file + + + + +2013-01-10T17:17:40.559764Z +a351aa6cb2ff552031644c821a1562d7 +2012-12-13T13:25:23.103424Z +281 +fweimer@REDHAT.COM +has-props + + + + + + + + + + + + + + + + + + + + +10998 + +File_System.xml +file + + + + +2013-01-10T17:17:40.559764Z +bf703da532d93a853979e09b04a2f21f +2012-12-13T13:25:23.103424Z +281 +fweimer@REDHAT.COM +has-props + + + + + + + + + + + + + + + + + + + + +14682 + +schemas.xml +file + + + + +2013-01-10T17:17:40.559764Z +769bc2635d36b318161574a1adf2f6e7 +2012-12-14T10:18:44.472257Z +292 +fweimer@REDHAT.COM +has-props + + + + + + + + + + + + + + + + + + + + +150 + +Temporary_Files.xml +file + + + + +2013-01-10T17:17:40.559764Z +c3db39345e4baab59ab738e3912a73ca +2012-12-13T13:25:23.103424Z +281 +fweimer@REDHAT.COM +has-props + + + + + + + + + + + + + + + + + + + + +10131 + +Locking.xml +file + + + + +2013-01-10T17:17:40.560764Z +f44d72a773df72e1e5f5101a3c9a66af +2012-12-14T10:18:44.472257Z +292 +fweimer@REDHAT.COM +has-props + + + + + + + + + + + + + + + + + + + + +226 + +Processes.xml +file + + + + +2013-01-10T17:17:40.560764Z +46f3a354235a27a94fd915ebe73f3db5 +2012-12-13T13:25:23.103424Z +281 +fweimer@REDHAT.COM +has-props + + + + + + + + + + + + + + + + + + + + +18957 + +Cryptography.xml +file + + + + +2013-01-10T17:17:40.560764Z +dfd01ca248a464c524b4badbdce2679c +2012-12-13T13:25:23.103424Z +281 +fweimer@REDHAT.COM +has-props + + + + + + + + + + + + + + + + + + + + +4180 + +Library_Design.xml +file + + + + +2013-01-10T17:17:40.560764Z +db4969b9abc8c5d9272ea395488a8896 +2012-12-13T13:25:23.103424Z +281 +fweimer@REDHAT.COM +has-props + + + + + + + + + + + + + + + + + + + + +7787 + +Serialization.xml +file + + + + +2013-01-10T17:17:40.560764Z +bc8c4dc03264854d83747d8f2cd1ab6f +2012-12-19T14:04:47.671665Z +294 +fweimer@REDHAT.COM +has-props + + + + + + + + + + + + + + + + + + + + +16361 + diff --git a/defensive-coding/en-US/Tasks/.svn/prop-base/Cryptography.xml.svn-base b/defensive-coding/en-US/Tasks/.svn/prop-base/Cryptography.xml.svn-base new file mode 100644 index 0000000..bfec7d5 --- /dev/null +++ b/defensive-coding/en-US/Tasks/.svn/prop-base/Cryptography.xml.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 8 +text/xml +END diff --git a/defensive-coding/en-US/Tasks/.svn/prop-base/Descriptors.xml.svn-base b/defensive-coding/en-US/Tasks/.svn/prop-base/Descriptors.xml.svn-base new file mode 100644 index 0000000..bfec7d5 --- /dev/null +++ b/defensive-coding/en-US/Tasks/.svn/prop-base/Descriptors.xml.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 8 +text/xml +END diff --git a/defensive-coding/en-US/Tasks/.svn/prop-base/File_System.xml.svn-base b/defensive-coding/en-US/Tasks/.svn/prop-base/File_System.xml.svn-base new file mode 100644 index 0000000..bfec7d5 --- /dev/null +++ b/defensive-coding/en-US/Tasks/.svn/prop-base/File_System.xml.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 8 +text/xml +END diff --git a/defensive-coding/en-US/Tasks/.svn/prop-base/Library_Design.xml.svn-base b/defensive-coding/en-US/Tasks/.svn/prop-base/Library_Design.xml.svn-base new file mode 100644 index 0000000..bfec7d5 --- /dev/null +++ b/defensive-coding/en-US/Tasks/.svn/prop-base/Library_Design.xml.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 8 +text/xml +END diff --git a/defensive-coding/en-US/Tasks/.svn/prop-base/Locking.xml.svn-base b/defensive-coding/en-US/Tasks/.svn/prop-base/Locking.xml.svn-base new file mode 100644 index 0000000..bfec7d5 --- /dev/null +++ b/defensive-coding/en-US/Tasks/.svn/prop-base/Locking.xml.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 8 +text/xml +END diff --git a/defensive-coding/en-US/Tasks/.svn/prop-base/Processes.xml.svn-base b/defensive-coding/en-US/Tasks/.svn/prop-base/Processes.xml.svn-base new file mode 100644 index 0000000..bfec7d5 --- /dev/null +++ b/defensive-coding/en-US/Tasks/.svn/prop-base/Processes.xml.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 8 +text/xml +END diff --git a/defensive-coding/en-US/Tasks/.svn/prop-base/Serialization.xml.svn-base b/defensive-coding/en-US/Tasks/.svn/prop-base/Serialization.xml.svn-base new file mode 100644 index 0000000..bfec7d5 --- /dev/null +++ b/defensive-coding/en-US/Tasks/.svn/prop-base/Serialization.xml.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 8 +text/xml +END diff --git a/defensive-coding/en-US/Tasks/.svn/prop-base/Temporary_Files.xml.svn-base b/defensive-coding/en-US/Tasks/.svn/prop-base/Temporary_Files.xml.svn-base new file mode 100644 index 0000000..bfec7d5 --- /dev/null +++ b/defensive-coding/en-US/Tasks/.svn/prop-base/Temporary_Files.xml.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 8 +text/xml +END diff --git a/defensive-coding/en-US/Tasks/.svn/prop-base/schemas.xml.svn-base b/defensive-coding/en-US/Tasks/.svn/prop-base/schemas.xml.svn-base new file mode 100644 index 0000000..bfec7d5 --- /dev/null +++ b/defensive-coding/en-US/Tasks/.svn/prop-base/schemas.xml.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 8 +text/xml +END diff --git a/defensive-coding/en-US/Tasks/.svn/text-base/Cryptography.xml.svn-base b/defensive-coding/en-US/Tasks/.svn/text-base/Cryptography.xml.svn-base new file mode 100644 index 0000000..88f14a3 --- /dev/null +++ b/defensive-coding/en-US/Tasks/.svn/text-base/Cryptography.xml.svn-base @@ -0,0 +1,111 @@ + + + + Cryptography + +
+ Primitives + + Chosing from the following cryptographic primitives is + recommended: + + + RSA with 2048 bit keys and OAEP + AES-128 in CBC mode + SHA-256 + HMAC-SHA-256 + HMAC-SHA-1 + + + Other cryptographic algorithms can be used if they are required + for interoperability with existing software: + + + RSA with key sizes larger than 1024 + and legacy padding + AES-192 + AES-256 + 3DES (triple DES, with two or three 56 bit keys) + RC4 (but very, very strongly discouraged) + SHA-1 + HMAC-MD5 + + + Important + + These primitives are difficult to use in a secure way. Custom + implementation of security protocols should be avoided. For + protecting confidentiality and integrity of network + transmissions, TLS should be used (). + + + +
+ +
+ Randomness + + The following facilities can be used to generate unpredictable + and non-repeating values. When these functions are used without + special safeguards, each individual rnadom value should be at + least 12 bytes long. + + + + PK11_GenerateRandom in the NSS library + (usable for high data rates) + + + RAND_bytes in the OpenSSL library + (usable for high data rates) + + + gnutls_rnd in GNUTLS, with + GNUTLS_RND_RANDOM as the first argument + (usable for high data rates) + + + java.security.SecureRandom in Java + (usable for high data rates) + + + os.urandom in Python + + + Reading from the /dev/urandom + character device + + + + All these functions should be non-blocking, and they should not + wait until physical randomness becomes available. (Some + cryptography providers for Java can cause + java.security.SecureRandom to block, however.) + Those functions which do not obtain all bits directly from + /dev/urandom are suitable for high data + rates because they do not deplete the system-wide entropy pool. + + + Difficult to use API + + Both RAND_bytes and + PK11_GenerateRandom have three-state + return values (with conflicting meanings). Careful error + checking is required. Please review the documentation when + using these functions. + + + + Other sources of randomness should be considered predictable. + + + Generating randomness for cryptographic keys in long-term use + may need different steps and is best left to cryptographic + libraries. + +
+ +
diff --git a/defensive-coding/en-US/Tasks/.svn/text-base/Descriptors.xml.svn-base b/defensive-coding/en-US/Tasks/.svn/text-base/Descriptors.xml.svn-base new file mode 100644 index 0000000..bdf1fb2 --- /dev/null +++ b/defensive-coding/en-US/Tasks/.svn/text-base/Descriptors.xml.svn-base @@ -0,0 +1,266 @@ + + + + File Descriptor Management + + File descriptors underlie all input/output mechanisms offered by + the system. They are used to implementation the FILE + *-based functions found in + <stdio.h>, and all the file and network + communication facilities provided by the Python and Java + environments are eventually implemented in them. + + + File descriptors are small, non-negative integers in userspace, + and are backed on the kernel side with complicated data structures + which can sometimes grow very large. + +
+ Closing descriptors + + If a descriptor is no longer used by a program and is not closed + explicitly, its number cannot be reused (which is problematic in + itself, see ), and + the kernel resources are not freed. Therefore, it is important + to close all descriptors at the earlierst point in time + possible, but not earlier. + +
+ Error handling during descriptor close + + The close system call is always + successful in the sense that the passed file descriptor is + never valid after the function has been called. However, + close still can return an error, for + example if there was a file system failure. But this error is + not very useful because the absence of an error does not mean + that all caches have been emptied and previous writes have + been made durable. Programs which need such guarantees must + open files with O_SYNC or use + fsync or fdatasync, and + may also have to fsync the directory + containing the file. + +
+
+ Closing descriptors and race conditions + + Unlike process IDs, which are recycle only gradually, the + kernel always allocates the lowest unused file descriptor when + a new descriptor is created. This means that in a + multi-threaded program which constantly opens and closes file + descriptors, descriptors are reused very quickly. Unless + descriptor closing and other operations on the same file + descriptor are synchronized (typically, using a mutex), there + will be race coniditons and I/O operations will be applied to + the wrong file descriptor. + + + Sometimes, it is necessary to close a file descriptor + concurrently, while another thread might be about to use it in + a system call. In order to support this, a program needs to + create a single special file descriptor, one on which all I/O + operations fail. One way to achieve this is to use + socketpair, close one of the descriptors, + and call shutdown(fd, SHUTRDWR) on the + other. + + + When a descriptor is closed concurrently, the program does not + call close on the descriptor. Instead it + program uses dup2 to replace the + descriptor to be closed with the dummy descriptor created + earlier. This way, the kernel will not reuse the descriptor, + but it will carry out all other steps associated with calling + a descriptor (for instance, if the descriptor refers to a + stream socket, the peer will be notified). + + + This is just a sketch, and many details are missing. + Additional data structures are needed to determine when it is + safe to really close the descriptor, and proper locking is + required for that. + +
+
+ Lingering state after close + + By default, closing a stream socket returns immediately, and + the kernel will try to send the data in the background. This + means that it is impossible to implement accurate accounting + of network-related resource utilization from userspace. + + + The SO_LINGER socket option alters the + behavior of close, so that it will return + only after the lingering data has been processed, either by + sending it to the peer successfully, or by discarding it after + the configured timeout. However, there is no interface which + could perform this operation in the background, so a separate + userspace thread is needed for each close + call, causing scalability issues. + + + Currently, there is no application-level countermeasure which + applies universally. Mitigation is possible with + iptables (the + connlimit match type in particular) and + specialized filtering devices for denial-of-service network + traffic. + + + These problems are not related to the + TIME_WAIT state commonly seen in + netstat output. The kernel + automatically expires such sockets if necessary. + +
+
+ +
+ Preventing file descriptor leaks to child processes + + Child processes created with fork share + the initial set of file descriptors with their parent + process. By default, file descriptors are also preserved if + a new process image is created with execve + (or any of the other functions such as system + or posix_spawn). + + + Usually, this behavior is not desirable. There are two ways to + turn it off, that is, to prevent new process images from + inheriting the file descriptors in the parent process: + + + + + Set the close-on-exec flag on all newly created file + descriptors. Traditionally, this flag is controlled by the + FD_CLOEXEC flag, using + F_GETFD and F_SETFD + operations of the fcntl function. + + + However, in a multi-threaded process, there is a race + condition: a subprocess could have been created between the + time the descriptor was created and the + FD_CLOEXEC was set. Therefore, many system + calls which create descriptors (such as + open and openat) + now accept the O_CLOEXEC flag + (SOCK_CLOEXEC for + socket and + socketpair), which cause the + FD_CLOEXEC flag to be set for the file + descriptor in an atomic fashion. In addition, a few new + systems calls were introduced, such as + pipe2 and dup3. + + + The downside of this approach is that every descriptor needs + to receive special treatment at the time of creation, + otherwise it is not completely effective. + + + + + After calling fork, but before creating + a new process image with execve, all + file descriptors which the child process will not need are + closed. + + + Traditionally, this was implemented as a loop over file + descriptors ranging from 3 to + 255 and later 1023. + But this is only an approximatio because it is possible to + create file descriptors outside this range easily (see ). + Another approach reads /proc/self/fd + and closes the unexpected descriptors listed there, but this + approach is much slower. + + + + + At present, environments which care about file descriptor + leakage implement the second approach. OpenJDK 6 and 7 + are among them. + +
+ +
+ Dealing with the <function>select</function> limit + + By default, a user is allowed to open only 1024 files in a + single process, but the system administrator can easily change + this limit (which is necessary for busy network servers). + However, there is another restriction which is more difficult to + overcome. + + + The select function only supports a + maximum of FD_SETSIZE file descriptors + (that is, the maximum permitted value for a file descriptor + is FD_SETSIZE - 1, usually 1023.) If a + process opens many files, descriptors may exceed such + limits. It is impossible to query such descriptors using + select. + + + If a library which creates many file descriptors is used in + the same process as a library which uses + select, at least one of them needs to + be changed. + Calls to select can be replaced with + calls to poll or another event handling + mechanism. + + + Alternatively, the library with high descriptor usage can + relocate descriptors above the FD_SETSIZE + limit using the following procedure. + + + + + Create the file descriptor fd as + usual, preferably with the O_CLOEXEC + flag. + + + + + Before doing anything else with the descriptor + fd, invoke: + + + int newfd = fcntl(fd, F_DUPFD_CLOEXEC, (long)FD_SETSIZE); + + + + + Check that newfd result is + non-negative, otherwise close fd and + report an error, and return. + + + + + Close fd and continue to use + newfd. + + + + + The new descriptor has been allocated above the + FD_SETSIZE. Even though this algorithm + is racy in the sense that the FD_SETSIZE + first descriptors could fill up, a very high degree of + physical parallelism is required before this becomes a problem. + +
+
diff --git a/defensive-coding/en-US/Tasks/.svn/text-base/File_System.xml.svn-base b/defensive-coding/en-US/Tasks/.svn/text-base/File_System.xml.svn-base new file mode 100644 index 0000000..ee3eb17 --- /dev/null +++ b/defensive-coding/en-US/Tasks/.svn/text-base/File_System.xml.svn-base @@ -0,0 +1,339 @@ + + + + File system manipulation + + In this chapter, we discuss general file system manipulation, with + a focus on access files and directories to which an other, + potentially untrusted user has write access. + + + Temporary files are covered in their own chapter, . + +
+ Working with files and directories owned by other users + + Sometimes, it is necessary to operate on files and directories + owned by other (potentially untrusted) users. For example, a + system administrator could remove the home directory of a user, + or a package manager could update a file in a directory which is + owned by an application-specific user. This differs from + accessing the file system as a specific user; see + . + + + Accessing files across trust boundaries faces several + challenges, particularly if an entire directory tree is being + traversed: + + + + + Another user might add file names to a writable directory at + any time. This can interfere with file creation and the + order of names returned by readdir. + + + + + Merely opening and closing a file can have side effects. + For instance, an automounter can be triggered, or a tape + device rewound. Opening a file on a local file system can + block indefinitely, due to mandatory file locking, unless + the O_NONBLOCK flag is specified. + + + + + Hard links and symbolic links can redirect the effect of + file system operations in unexpected ways. The + O_NOFOLLOW and + AT_SYMLINK_NOFOLLOW variants of system + calls only affected final path name component. + + + + + The structure of a directory tree can change. For example, + the parent directory of what used to be a subdirectory + within the directory tree being processed could suddenly + point outside that directory tree. + + + + + Files should always be created with the + O_CREAT and O_EXCL flags, + so that creating the file will fail if it already exists. This + guards against the unexpected appearance of file names, either + due to creation of a new file, or hard-linking of an existing + file. In multi-threaded programs, rather than manipulating the + umask, create the files with mode 000 if + possible, and adjust it afterwards with + fchmod. + + + To avoid issues related to symbolic links and directory tree + restructuring, the “at” variants of system + calls have to be used (that is, functions like + openat, fchownat, + fchmodat, and + unlinkat, together with + O_NOFOLLOW or + AT_SYMLINK_NOFOLLOW). Path names passed to + these functions must have just a single component (that is, + without a slash). When descending, the descriptors of parent + directories must be kept open. The missing + opendirat function can be emulated with + openat (with an + O_DIRECTORY flag, to avoid opening special + files with side effects), followed by + fdopendir. + + + If the “at” functions are not available, it + is possible to emulate them by changing the current directory. + (Obviously, this only works if the process is not multi-threaded.) + fchdir has to be used to change the current + directory, and the descriptors of the parent directories have to + be kept open, just as with the “at”-based + approach. chdir("...") is unsafe because it + might ascend outside the intended directory tree. + + + This “at” function emulation is currently + required when manipulating extended attributes. In this case, + the lsetxattr function can be used, with a + relative path name consisting of a single component. This also + applies to SELinux contexts and the + lsetfilecon function. + + + Currently, it is not possible to avoid opening special files + and changes to files with hard links if the + directory containing them is owned by an untrusted user. + (Device nodes can be hard-linked, just as regular files.) + fchmodat and fchownat + affect files whose link count is greater than one. But opening + the files, checking that the link count is one with + fstat, and using + fchmod and fchown on + the file descriptor may have unwanted side effects, due to item + 2 above. When creating directories, it is therefore important + to change the ownership and permissions only after it has been + fully created. Until that point, file names are stable, and no + files with unexpected hard links can be introduced. + + + Similarly, when just reading a directory owned by an untrusted + user, it is currently impossible to reliably avoid opening + special files. + + + There is no workaround against the instability of the file list + returned by readdir. Concurrent + modification of the directory can result in a list of files + being returned which never actually existed on disk. + + + Hard links and symbolic links can be safely deleted using + unlinkat without further checks because + deletion only affects the name within the directory tree being + processed. + +
+
+ Accessing the file system as a different user + + This section deals with access to the file system as a specific + user. This is different from accessing files and directories owned by a + different, potentially untrusted user; see . + + + One approach is to spawn a child process which runs under the + target user and group IDs (both effective and real IDs). Note + that this child process can block indefinitely, even when + processing regular files only. For example, a special FUSE file + system could cause the process to hang in uninterruptible sleep + inside a stat system call. + + + An existing process could change its user and group ID using + setfsuid and setfsgid. + (These functions are preferred over seteuid + and setegid because they do not allow the + impersonated user to send signals to the process.) These + functions are not thread safe. In multi-threaded processes, + these operations need to be performed in a single-threaded child + process. Unexpected blocking may occur as well. + + + It is not recommended to try to reimplement the kernel + permission checks in user space because the required checks are + complex. It is also very difficult to avoid race conditions + during path name resolution. + +
+
+ File system limits + + For historical reasons, there are preprocessor constants such as + PATH_MAX, NAME_MAX. + However, on most systems, the length of canonical path names + (absolute path names with all symbolic links resolved, as + returned by realpath or + canonicalize_file_name) can exceed + PATH_MAX bytes, and individual file name + components can be longer than NAME_MAX. This + is also true of the _PC_PATH_MAX and + _PC_NAME_MAX values returned by + pathconf, and the + f_namemax member of struct + statvfs. Therefore, these constants should not be + used. This is also reason why the + readdir_r should never be used (instead, + use readdir). + + + You should not write code in a way that assumes that there is an + upper limit on the number of subdirectories of a directory, the + number of regular files in a directory, or the link count of an + inode. + +
+
+ File system features + + Not all file systems support all features. This makes it very + difficult to write general-purpose tools for copying files. For + example, a copy operation intending to preserve file permissions + will generally fail when copying to a FAT file system. + + + + + Some file systems are case-insensitive. Most should be + case-preserving, though. + + + + + Name length limits vary greatly, from eight to thousands of + bytes. Path length limits differ as well. Most systems + impose an upper bound on path names passed to the kernel, + but using relative path names, it is possible to create and + access files whose absolute path name is essentially of + unbounded length. + + + + + Some file systems do not store names as fairly unrestricted + byte sequences, as it has been traditionally the case on GNU + systems. This means that some byte sequences (outside the + POSIX safe character set) are not valid names. Conversely, + names of existing files may not be representable as byte + sequences, and the files are thus inaccessible on GNU + systems. Some file systems perform Unicode canonicalization + on file names. These file systems preserve case, but + reading the name of a just-created file using + readdir might still result in a + different byte sequence. + + + + + Permissions and owners are not universally supported (and + SUID/SGID bits may not be available). For example, FAT file + systems assign ownership based on a mount option, and + generally mark all files as executable. Any attempt to + change permissions would result in an error. + + + + + Non-regular files (device nodes, FIFOs) are not generally + available. + + + + + Only on some file systems, files can have holes, that is, + not all of their contents is backed by disk storage. + + + + + ioctl support (even fairly generic + functionality such as FIEMAP for + discovering physical file layout and holes) is + file-system-specific. + + + + + Not all file systems support extended attributes, ACLs and + SELinux metadata. Size and naming restriction on extended + attributes vary. + + + + + Hard links may not be supported at all (FAT) or only within + the same directory (AFS). Symbolic links may not be + available, either. Reflinks (hard links with copy-on-write + semantics) are still very rare. Recent systems restrict + creation of hard links to users which own the target file or + have read/write access to it, but older systems do not. + + + + + Renaming (or moving) files using rename + can fail (even when stat indicates that + the source and target directories are located on the same + file system). This system call should work if the old and + new paths are located in the same directory, though. + + + + + Locking semantics vary among file systems. This affects + advisory and mandatory locks. For example, some network + file systems do not allow deleting files which are opened by + any process. + + + + + Resolution of time stamps varies from two seconds to + nanoseconds. Not all time stamps are available on all file + systems. File creation time (birth + time) is not exposed over the + stat/fstat + interface, even if stored by the file system. + + + +
+
+ Checking free space + + The statvfs and + fstatvfs functions allow programs to + examine the number of available blocks and inodes, through the + members f_bfree, f_bavail, + f_ffree, and f_favail of + struct statvfs. Some file systems return + fictional values in the f_ffree and + f_favail fields, so the only reliable way to + discover if the file system still has space for a file is to try + to create it. The f_bfree field should be + reasonably accurate, though. + +
+
+ diff --git a/defensive-coding/en-US/Tasks/.svn/text-base/Library_Design.xml.svn-base b/defensive-coding/en-US/Tasks/.svn/text-base/Library_Design.xml.svn-base new file mode 100644 index 0000000..7c959ab --- /dev/null +++ b/defensive-coding/en-US/Tasks/.svn/text-base/Library_Design.xml.svn-base @@ -0,0 +1,195 @@ + + + + Library Design + + Throught this section, the term client code + refers to applications and other libraries using the library. + + +
+ State management + + +
+ Global state + + Global state should be avoided. + + + If this is impossible, the global state must be protected with + a lock. For C/C++, you can use the + pthread_mutex_lock + and pthread_mutex_unlock + functions without linking against -lpthread + because the system provides stubs for non-threaded processes. + + + For compatibility with fork, these locks + should be acquired and released in helpers registered with + pthread_atfork. This function is not + available without -lpthread, so you need to + use dlsym or a weak symbol to obtain its + address. + + + If you need fork protection for other + reasons, you should store the process ID and compare it to the + value returned by getpid each time you + access the global state. (getpid is not + implemented as a system call and is fast.) If the value + changes, you know that you have to re-create the state object. + (This needs to be combined with locking, of course.) + +
+
+ Handles + + Library state should be kept behind a curtain. Client code + should receive only a handle. In C, the handle can be a + pointer to an incomplete struct. In C++, + the handle can be a pointer to an abstract base class, or it + can be hidden using the pointer-to-implementation idiom. + + + The library should provide functions for creating and + destroying handles. (In C++, it is possible to use virtual + destructors for the latter.) Consistency between creation and + destruction of handles is strongly recommended: If the client + code created a handle, it is the responsibility of the client + code to destroy it. (This is not always possible or + convenient, so sometimes, a transfer of ownership has to + happen.) + + + Using handles ensures that it is possible to change the way + the library represents state in a way that is transparent to + client code. This is important to facilitate security updates + and many other code changes. + + + It is not always necessary to protect state behind a handle + with a lock. This depends on the level of thread safety + the library provides. + +
+
+ +
+ Object orientation + + Classes should be either designed as base classes, or it should + be impossible to use them as base classes (like + final classes in Java). Classes which are + not designed for inheritance and are used as base classes + nevertheless create potential maintenance hazards because it is + difficult to predict how client code will react when calls to + virtual methods are added, reordered or removed. + + + Virtual member functions can be used as callbacks. See + + for some of the challenges involved. + +
+ +
+ Callbacks + + Higher-order code is difficult to analyze for humans and + computers alike, so it should be avoided. Often, an + iterator-based interface (a library function which is called + repeatedly by client code and returns a stream of events) leads + to a better design which is easier to document and use. + + + If callbacks are unavoidable, some guidelines for them follow. + + + In modern C++ code, std::function objects + should be used for callbacks. + + + In older C++ code and in C code, all callbacks must have an + additional closure parameter of type void *, + the value of which can be specified by client code. If + possible, the value of the closure parameter should be provided + by client code at the same time a specific callback is + registered (or specified as a function argument). If a single + closure parameter is shared by multiple callbacks, flexibility + is greatly reduced, and conflicts between different pieces of + client code using the same library object could be unresolvable. + In some cases, it makes sense to provide a de-registration + callback which can be used to destroy the closure parameter when + the callback is no longer used. + + + Callbacks can throw exceptions or call + longjmp. If possible, all library objects + should remain in a valid state. (All further operations on them + can fail, but it should be possible to deallocate them without + causing resource leaks.) + + + The presence of callbacks raises the question if functions + provided by the library are reentrant. + Unless a library was designed for such use, bad things will + happen if a callback function uses functions in the same library + (particularly if they are invoked on the same objects and + manipulate the same state). When the callback is invoked, the + library can be in an inconsistent state. Reentrant functions + are more difficult to write than thread-safe functions (by + definition, simple locking would immediately lead to deadlocks). + It is also difficult to decide what to do when destruction of an + object which is currently processing a callback is requested. + +
+ +
+ Process attributes + + Several attributes are global and affect all code in the + process, not just the library that manipulates them. + + + + environment variables + (see ) + + + umask + + + user IDs, group IDs and capabilities + + + current working directory + + + signal handlers, signal masks and signal delivery + + + file locks (especially fcntl locks + behave in surprising ways, not just in a multi-threaded + environment) + + + + Library code should avoid manipulating these global process + attributes. It should not rely on environment variables, umask, + the current working directory and signal masks because these + attributes can be inherted from an untrusted source. + + + In addition, there are obvious process-wide aspects such as the + virtual memory layout, the set of open files and dynamic shared + objects, but with the exception of shared objects, these can be + manipulated in a relatively isolated way. + + +
+ +
+ + diff --git a/defensive-coding/en-US/Tasks/.svn/text-base/Locking.xml.svn-base b/defensive-coding/en-US/Tasks/.svn/text-base/Locking.xml.svn-base new file mode 100644 index 0000000..f85e61e --- /dev/null +++ b/defensive-coding/en-US/Tasks/.svn/text-base/Locking.xml.svn-base @@ -0,0 +1,5 @@ + + + + diff --git a/defensive-coding/en-US/Tasks/.svn/text-base/Processes.xml.svn-base b/defensive-coding/en-US/Tasks/.svn/text-base/Processes.xml.svn-base new file mode 100644 index 0000000..90f01f0 --- /dev/null +++ b/defensive-coding/en-US/Tasks/.svn/text-base/Processes.xml.svn-base @@ -0,0 +1,483 @@ + + + + Processes + +
+ Safe process creation + + This section describes how to create new child processes in a + safe manner. In addition to the concerns addressed below, there + is the possibility of file descriptor leaks, see . + +
+ Obtaining the program path and the command line + template + + The name and path to the program being invoked should be + hard-coded or controlled by a static configuration file stored + at a fixed location (at an file system absolute path). The + same applies to the template for generating the command line. + + + The configured program name should be an absolute path. If it + is a relative path, the contents of the PATH + must be obtained in s secure manner (see ). + If the PATH variable is not set or untrusted, + the safe default /bin:/usr/bin must be + used. + + + If too much flexibility is provided here, it may allow + invocation of arbitrary programs without proper authorization. + +
+ +
+ Bypassing the shell + + Child processes should be created without involving the system + shell. + + + For C/C++, system should not be used. + The posix_spawn function can be used + instead, or a combination fork and + execve. (In some cases, it may be + preferable to use vfork or the + Linux-specific clone system call instead + of fork.) + + + In Python, the subprocess module bypasses + the shell by default (when the shell + keyword argument is not set to true). + os.system should not be used. + + + The Java class java.lang.ProcessBuilder can be + used to create subprocesses without interference from the + system shell. + + + Portability notice + + On Windows, there is no argument vector, only a single + argument string. Each application is responsible for parsing + this string into an argument vector. There is considerable + variance among the quoting style recognized by applications. + Some of them expand shell wildcards, others do not. Extensive + application-specific testing is required to make this secure. + + + + Note that some common applications (notably + ssh) unconditionally introduce the + use of a shell, even if invoked directly without a shell. It is + difficult to use these applications in a secure manner. In this + case, untrusted data should be supplied by other means. For + example, standard input could be used, instead of the command + line. + +
+ +
+ Specifying the process environment + + Child processes should be created with a minimal set of + environment variables. This is absolutely essential if there + is a trust transition involved, either when the parent process + was created, or during the creation of the child process. + + + In C/C++, the environment should be constructed as an array of + strings and passed as the envp argument to + posix_spawn or execve. + The functions setenv, + unsetenv and putenv + should not be used. They are not thread-safe and suffer from + memory leaks. + + + Python programs need to specify a dict for + the the env argument of the + subprocess.Popen constructor. + The Java class java.lang.ProcessBuilder + provides a environment() method, + which returns a map that can be manipulated. + + + The following list provides guidelines for selecting the set + of environment variables passed to the child process. + + + + + PATH should be initialized to + /bin:/usr/bin. + + + + + USER and HOME can be inhereted + from the parent process environment, or they can be + initialized from the pwent structure + for the user. + + + + The DISPLAY and XAUTHORITY + variables should be passed to the subprocess if it is an X + program. Note that this will typically not work across trust + boundaries because XAUTHORITY refers to a file + with 0600 permissions. + + + + + The location-related environment variables + LANG, LANGUAGE, + LC_ADDRESS, LC_ALL, + LC_COLLATE, LC_CTYPE, + LC_IDENTIFICATION, + LC_MEASUREMENT, LC_MESSAGES, + LC_MONETARY, LC_NAME, + LC_NUMERIC, LC_PAPER, + LC_TELEPHONE and LC_TIME + can be passed to the subprocess if present. + + + + + The called process may need application-specific + environment variables, for example for passing passwords. + (See .) + + + + + All other environment variables should be dropped. Names + for new environment variables should not be accepted from + untrusted sources. + + + +
+ +
+ Robust argument list processing + + When invoking a program, it is sometimes necessary to include + data from untrusted sources. Such data should be check + against embedded NUL characters because the + system APIs will sliently truncate argument strings at the first + NUL character. + + + The following recommendations assume that the program being + invoked uses GNU-style option processing using + getopt_long. This convention is widely + used, but it is just that, and individual programs might + interpret a command line in a different way. + + + If the untrusted data has to go into an option, use the + --option-name=VALUE syntax, placing the + option and its value into the same command line argument. + This avoids any potential confusion if the data starts with + -. + + + For positional arguments, terminate the option list with a + single marker after the last option, and + include the data at the right position. The + marker terminates option processing, and + the data will not be treated as an option even if it starts + with a dash. + +
+ +
+ Passing secrets to subprocesses + + The command line (the name of the program and its argument) of + a running process is traditionally available to all local + users. The called program can overwrite this information, but + only after it has run for a bit of time, during which the + information may have been read by other processes. However, + on Linux, the process environment is restricted to the user + who runs the process. Therefore, if you need a convenient way + to pass a password to a child process, use an environment + variable, and not a command line argument. (See .) + + + Portability notice + + On some UNIX-like systems (notably Solaris), environment + variables can be read by any system user, just like command + lines. + + + + If the environment-based approach cannot be used due to + portability concerns, the data can be passed on standard + input. Some programs (notably gpg) + use special file descriptors whose numbers are specified on + the command line. Temporary files are an option as well, but + they might give digital forensics access to sensitive data + (such as passphrases) because it is difficult to safely delete + them in all cases. + +
+
+ +
+ Handling child process termination + + When child processes terminate, the parent process is signalled. + A stub of the terminated processes (a + zombie, shown as + <defunct> by + ps) is kept around until the status + information is collected (reaped) by the + parent process. Over the years, several interfaces for this + have been invented: + + + + + The parent process calls wait, + waitpid, waitid, + wait3 or wait4, + without specifying a process ID. This will deliver any + matching process ID. This approach is typically used from + within event loops. + + + + + The parent process calls waitpid, + waitid, or wait4, + with a specific process ID. Only data for the specific + process ID is returned. This is typically used in code + which spawns a single subprocess in a synchronous manner. + + + + + The parent process installs a handler for the + SIGCHLD signal, using + sigaction, and specifies to the + SA_NOCLDWAIT flag. + This approach could be used by event loops as well. + + + + + None of these approaches can be used to wait for child process + terminated in a completely thread-safe manner. The parent + process might execute an event loop in another thread, which + could pick up the termination signal. This means that libraries + typically cannot make free use of child processes (for example, + to run problematic code with reduced privileges in a separate + address space). + + + At the moment, the parent process should explicitly wait for + termination of the child process using + waitpid or waitpid, + and hope that the status is not collected by an event loop + first. + +
+ +
+ <literal>SUID</literal>/<literal>SGID</literal> + processes + + + Programs can be marked in the file system to indicate to the + kernel that a trust transition should happen if the program is + run. The SUID file permission bit indicates + that an executable should run with the effective user ID equal + to the owner of the executable file. Similarly, with the + SGID bit, the effective group ID is set to + the group of the executable file. + + + Linux supports fscaps, which can grant + additional capabilities to a process in a finer-grained manner. + Additional mechanisms can be provided by loadable security + modules. + + + When such a trust transition has happened, the process runs in a + potentially hostile environment. Additional care is necessary + not to rely on any untrusted information. These concerns also + apply to libraries which can be linked into such processes. + + +
+ Accessing environment variables + + The following steps are required so that a program does not + accidentally pick up untrusted data from environment + variables. + + + + Compile your C/C++ sources with -D_GNU_SOURCE. + The Autoconf macro AC_GNU_SOURCE ensures this. + + + Check for the presence of the secure_getenv + and __secure_getenv function. The Autoconf + directive AC_CHECK_FUNCS([__secure_getenv secure_getenv]) + performs these checks. + + + Arrange for a proper definition of the + secure_getenv function. See . + + + Use secure_getenv instead of + getenv to obtain the value of critical + environment variables. secure_getenv + will pretend the variable has not bee set if the process + environment is not trusted. + + + + Critical environment variables are debugging flags, + configuration file locations, plug-in and log file locations, + and anything else that might be used to bypass security + restrictions or cause a privileged process to behave in an + unexpected way. + + + Either the secure_getenv function or the + __secure_getenv is available from GNU libc. + + + Obtaining a definition for <function>secure_getenv</function> + + + +#ifndef HAVE_SECURE_GETENV +# ifdef HAVE__SECURE_GETENV +# define secure_getenv __secure_getenv +# else +# error neither secure_getenv nor __secure_getenv are available +# endif +#endif +]]> + + +
+
+ +
+ Daemons + + Background processes providing system services + (daemons) need to decouple themselves from + the controlling terminal and the parent process environment: + + + + Fork. + + + + In the child process, call setsid. The + parent process can simply exit (using + _exit, to avoid running clean-up + actions twice). + + + + + In the child process, fork again. Processing continues in + the child process. Again, the parent process should just + exit. + + + + + Replace the descriptors 0, 1, 2 with a descriptor for + /dev/null. Logging should be + redirected to syslog. + + + + + Older instructions for creating daemon processes recommended a + call to umask(0). This is risky because it + often leads to world-writable files and directories, resulting + in security vulnerabilities such as arbitrary process + termination by untrusted local users, or log file truncation. + If the umask needs setting, a restrictive + value such as 027 or 077 + is recommended. + + + Other aspects of the process environment may have to changed as + well (environment variables, signal handler disposition). + + + It is increasingly common that server processes do not run as + background processes, but as regular foreground process under a + supervising master process (such as + systemd). Server processes should + offer a command line option which disables forking and + replacement of the standard output and standard error streams. + Such an option is also useful for debugging. + +
+ +
+ Semantics of command line arguments + + + After process creation and option processing, it is up to the + child process to interpret the arguments. Arguments can be + file names, host names, or URLs, and many other things. URLs + can refer to the local network, some server on the Internet, + or to the local file system. Some applications even accept + arbitrary code in arguments (for example, + python with the + option). + + + Similar concerns apply to environment variables, the contents + of the current directory and its subdirectories. + + + + Consequently, careful analysis is required if it is safe to + pass untrusted data to another program. + +
+ +
+ <function>fork</function> as a primitive for parallelism + + A call to fork which is not immediately + followed by a call to execve (perhaps after + rearranging and closing file descriptors) is typically unsafe, + especially from a library which does not control the state of + the entire process. Such use of fork + should be replaced with proper child processes or threads. + +
+ +
diff --git a/defensive-coding/en-US/Tasks/.svn/text-base/Serialization.xml.svn-base b/defensive-coding/en-US/Tasks/.svn/text-base/Serialization.xml.svn-base new file mode 100644 index 0000000..60427c5 --- /dev/null +++ b/defensive-coding/en-US/Tasks/.svn/text-base/Serialization.xml.svn-base @@ -0,0 +1,397 @@ + + + + Serialization and Deserialization + + Protocol decoders and file format parsers are often the + most-exposed part of an application because they are exposed with + little or no user interaction and before any authentication and + security checks are made. They are also difficult to write + robustly in languages which are not memory-safe. + + +
+ Recommendations for manually written decoders + + For C and C++, the advice in applies. In + addition, avoid non-character pointers directly into input + buffers. Pointer misalignment causes crashes on some + architectures. + + + When reading variable-sized objects, do not allocate large + amounts of data solely based on the value of a size field. If + possible, grow the data structure as more data is read from the + source, and stop when no data is available. This helps to avoid + denial-of-service attacks where little amounts of input data + results in enormous memory allocations during decoding. + Alternatively, you can impose reasonable bounds on memory + allocations, but some protocols do not permit this. + +
+ +
+ Protocol design + + Binary formats with explicit length fields are more difficult to + parse robustly than those where the length of dynamically-sized + elements is derived from sentinel values. A protocol which does + not use length fields and can be written in printable ASCII + characters simplifies testing and debugging. However, binary + protocols with length fields may be more efficient to parse. + +
+ +
+ Library + support for deserialization + + For some languages, generic libraries are available which allow + to serialize and deserialize user-defined objects. The + deserialization part comes in one of two flavors, depending on + the library. The first kind uses type information in the data + stream to control which objects are instantiated. The second + kind uses type definitions supplied by the programmer. The + first one allows arbitrary object instantiation, the second one + generally does not. + + + The following serialization frameworks are in the first category, + are known to be unsafe, and must not be used for untrusted data: + + + + Python's pickle and cPickle + modules + + + Perl's Storable package + + + Java serialization (java.io.ObjectInputStream) + + + PHP serialization (unserialize) + + + Most implementations of YAML + + + + When using a type-directed deserialization format where the + types of the deserialized objects are specified by the + programmer, make sure that the objects which can be instantiated + cannot perform any destructive actions in their destructors, + even when the data members have been manipulated. + + + JSON decoders do not suffer from this problem. But you must not + use the eval function to parse JSON objects + in Javascript; even with the regular expression filter from RFC + 4627, there are still information leaks remaining. + +
+ +
+ XML serialization + + +
+ External references + + XML documents can contain external references. They can occur + in various places. + + + + + In the DTD declaration in the header of an XML document: + + + +]]> + + + + + + In a namespace declaration: + + + +]]> + + + + + + In an entity defintion: + + + + +]]> + + + + + + In a notation: + + + +]]> + + + + + + Originally, these external references were intended as unique + identifiers, but by many XML implementations, they are used + for locating the data for the referenced element. This causes + unwanted network traffic, and may disclose file system + contents or otherwise unreachable network resources, so this + functionality should be disabled. + + + Depending on the XML library, external referenced might be + processed not just when parsing XML, but also when generating + it. + +
+
+ Entity expansion + + When external DTD processing is disabled, an internal DTD + subset can still contain entity definitions. Entity + declarations can reference other entities. Some XML libraries + expand entities automatically, and this processing cannot be + switched off in some places (such as attribute values or + content models). Without limits on the entity nesting level, + this expansion results in data which can grow exponentially in + length with size of the input. (If there is a limit on the + nesting level, the growth is still polynomial, unless further + limits are imposed.) + + + Consequently, the processing internal DTD subsets should be + disabled if possible, and only trusted DTDs should be + processed. If a particular XML application does not permit + such restrictions, then application-specific limits are called + for. + +
+ +
+ XInclude processing + + XInclude processing can reference file and network resources + and include them into the document, much like external entity + references. When parsing untrusted XML documents, XInclude + processing should be truned off. + + + XInclude processing is also fairly complex and may pull in + support for the XPointer and XPath specifications, + considerably increasing the amount of code required for XML + processing. + +
+ +
+ Algorithmic complexity of XML validation + + DTD-based XML validation uses regular expressions for content + models. The XML specification requires that content models + are deterministic, which means that efficient validation is + possible. However, some implementations do not enforce + determinism, and require exponential (or just polynomial) + amount of space or time for validating some DTD/document + combinations. + + + XML schemas and RELAX NG (via the xsd: + prefix) directly support textual regular expressions which are + not required to be deterministic. + +
+
+ Using Expat for XML parsing + + By default, Expat does not try to resolve external IDs, so no + steps are required to block them. However, internal entity + declarations are processed. Installing a callback which stops + parsing as soon as such entities are encountered disables + them, see . + Expat does not perform any validation, so there are no + problems related to that. + + + Disabling XML entity processing with Expat + + + + This handler must be installed when the + XML_Parser object is created (). + + + Creating an Expat XML parser + + + + It is also possible to reject internal DTD subsets altogeher, + using a suitable + XML_StartDoctypeDeclHandler handler + installed with XML_SetDoctypeDeclHandler. + +
+ +
+ Using OpenJDK for XML parsing and validation + + OpenJDK contains facilities for DOM-based, SAX-based, and + StAX-based document parsing. Documents can be validated + against DTDs or XML schemas. + + + The approach taken to deal with entity expansion differs from + the general recommendation in . + We enable the the feature flag + javax.xml.XMLConstants.FEATURE_SECURE_PROCESSING, + which enforces heuristic restrictions on the number of entity + expansions. Note that this flag alone does not prevent + resolution of external references (system IDs or public IDs), + so it is slightly misnamed. + + + In the following sections, we use helper classes to prevent + external ID resolution. + + + Helper class to prevent DTD external entity resolution in OpenJDK + + + + Helper class to prevent schema resolution in + OpenJDK + + + + + shows the imports used by the examples. + + + Java imports for OpenJDK XML parsing + + +
+ DOM-based XML parsing and DTD validation in OpenJDK + + This approach produces a + org.w3c.dom.Document object from an input + stream. + use the data from the java.io.InputStream + instance in the inputStream variable. + + + DOM-based XML parsing in OpenJDK + + + + External entity references are prohibited using the + NoEntityResolver class in + . + Because external DTD references are prohibited, DTD validation + (if enabled) will only happen against the internal DTD subset + embedded in the XML document. + + + To validate the document against an external DTD, use a + javax.xml.transform.Transformer class to + add the DTD reference to the document, and an entity + resolver which whitelists this external reference. + +
+ +
+ XML Schema validation in OpenJDK + + + shows how to validate a document against an XML Schema, + using a SAX-based approach. The XML data is read from an + java.io.InputStream in the + inputStream variable. + + + SAX-based validation against an XML schema in + OpenJDK + + + + The NoResourceResolver class is defined + in . + + + If you need to validate a document against an XML schema, + use the code in + to create the document, but do not enable validation at this + point. Then use + + to perform the schema-based validation on the + org.w3c.dom.Document instance + document. + + + Validation of a DOM document against an XML schema in + OpenJDK + + +
+
+
+ +
+ Protocol Encoders + + For protocol encoders, you should write bytes to a buffer which + grows as needed, using an exponential sizing policy. Explicit + lengths can be patched in later, once they are known. + Allocating the required number of bytes upfront typically + requires separate code to compute the final size, which must be + kept in sync with the actual encoding step, or vulnerabilities + may result. In multi-threaded code, parts of the object being + deserialized might change, so that the computed size is out of + date. + + + You should avoid copying data directly from a received packet + during encoding, disregarding the format. Propagating malformed + data could enable attacks on other recipients of that data. + + + When using C or C++ and copying whole data structures directly + into the output, make sure that you do not leak information in + padding bytes between fields or at the end of the + struct. + +
+ +
+ diff --git a/defensive-coding/en-US/Tasks/.svn/text-base/Temporary_Files.xml.svn-base b/defensive-coding/en-US/Tasks/.svn/text-base/Temporary_Files.xml.svn-base new file mode 100644 index 0000000..d78bad7 --- /dev/null +++ b/defensive-coding/en-US/Tasks/.svn/text-base/Temporary_Files.xml.svn-base @@ -0,0 +1,257 @@ + + + + Temporary files + + In this chapter, we describe how to create temporary files and + directories, how to remove them, and how to work with programs + which do not create files in ways that a safe with a shared + directory for temporary files. General file system manipulation + is treated in a separate chapter, . + + + Secure creation of temporary files has four different aspects. + + + + + The location of the directory for temporary files must be + obtained in a secure manner (that is, untrusted environment + variables must be ignored, see ). + + + + + A new file must be created. Reusing an existing file must be + avoided (the /tmp race + condition). This is tricky because traditionally, system-wide + temporary directories shared by all users are used. + + + + + The file must be created in a way that makes it impossible for + other users to open it. + + + + + The descriptor for the temporary file should not leak to + subprocesses. + + + + + All functions mentioned below will take care of these aspects. + + + Traditionally, temporary files are often used to reduce memory + usage of programs. More and more systems use RAM-based file + systems such as tmpfs for storing temporary + files, to increase performance and decrease wear on Flash storage. + As a result, spooling data to temporary files does not result in + any memory savings, and the related complexity can be avoided if + the data is kept in process memory. + + +
+ Obtaining the location of temporary directory + + Some functions below need the location of a directory which + stores temporary files. For C/C++ programs, use the following + steps to obtain that directory: + + + + + Use secure_getenv to obtain the value + of the TMPDIR environment variable. If + it is set, convert the path to a fully-resolved absolute + path, using realpath(path, NULL). Check + if the new path refers to a directory and is writeable. In + this case, use it as the temporary directory. + + + + + Fall back to /tmp. + + + + + In Python, you can use the tempfile.tempdir + variable. + + + Java does not support SUID/SGID programs, so you can use the + java.lang.System.getenv(String) method to + obtain the value of the TMPDIR environment + variable, and follow the two steps described above. (Java's + default directory selection does not honor + TMPDIR.) + +
+ +
+ Named temporary files + + The mkostemp function creates a named + temporary file. You should specify the + O_CLOEXEC flag to avoid file descriptor leaks + to subprocesses. (Applications which do not use multiple threads + can also use mkstemp, but libraries should + use mkostemp.) For determining the + directory part of the file name pattern, see . + + + The file is not removed automatically. It is not safe to rename + or delete the file before processing, or transform the name in + any way (for example, by adding a file extension). If you need + multiple temporary files, call mkostemp + multiple times. Do not create additional file names derived + from the name provided by a previous + mkostemp call. However, it is safe to close + the descriptor returned by mkostemp and + reopen the file using the generated name. + + + The Python class tempfile.NamedTemporaryFile + provides similar functionality, except that the file is deleted + automatically by default. Note that you may have to use the + file attribute to obtain the actual file + object because some programming interfaces cannot deal with + file-like objects. The C function mkostemp + is also available as tempfile.mkstemp. + + + In Java, you can use the + java.io.File.createTempFile(String, String, + File) function, using the temporary file location + determined according to . + Do not use java.io.File.deleteOnExit() to + delete temporary files, and do not register a shutdown hook for + each temporary file you create. In both cases, the deletion + hint cannot be removed from the system if you delete the + temporary file prior to termination of the VM, causing a memory + leak. + +
+ +
+ Temporary files without names + + The tmpfile function creates a temporary + file and immediately deletes it, while keeping the file open. + As a result, the file lacks a name and its space is deallocated + as soon as the file descriptor is closed (including the implicit + close when the process terminates). This avoids cluttering the + temporary directory with orphaned files. + + + Alternatively, if the maximum size of the temporary file is + known beforehand, the fmemopen function can + be used to create a FILE * object which is + backed by memory. + + + In Python, unnamed temporary files are provided by the + tempfile.TemporaryFile class, and the + tempfile.SpooledTemporaryFile class provides + a way to avoid creation of small temporary files. + + + Java does not support unnamed temporary files. + +
+ +
+ Temporary directories + + The mkdtemp function can be used to create + a temporary directory. (For determining the directory part of + the file name pattern, see .) + The directory is not automatically removed. In Python, this + function is available as tempfile.mkdtemp. + In Java 7, temporary directories can be created using the + java.nio.file.Files.createTempDirectory(Path, String, + FileAttribute...) function. + + + When creating files in the temporary directory, use + automatically generated names, e.g., derived from a sequential + counter. Files with externally provided names could be picked + up in unexpected contexts, and crafted names could actually + point outside of the tempoary directory (due to + directory traversal). + + + Removing a directory tree in a completely safe manner is + complicated. Unless there are overriding performance concerns, + the rm program should be used, with + the and options. + +
+ +
+ Compensating for unsafe file creation + + There are two ways to make a function or program which excepts a + file name safe for use with temporary files. See + , + for details on subprocess creation. + + + + + Create a temporary directory and place the file there. If + possible, run the program in a subprocess which uses the + temporary directory as its current directory, with a + restricted environment. + Use generated names for all files in that temporary + directory. (See .) + + + + + Create the temporary file and pass the generated file name + to the function or program. This only works if the function + or program can cope with a zero-length existing file. It is + safe only under additional assumptions: + + + + + The function or program must not create additional files + whose name is derived from the specified file name or + are otherwise predictable. + + + + + The function or program must not delete the file before + processing it. + + + + + It must not access any existing files in the same + directory. + + + + + It is often difficult to check whether these additional + assumptions are matched, therefore this approach is not + recommended. + + + +
+
diff --git a/defensive-coding/en-US/Tasks/.svn/text-base/schemas.xml.svn-base b/defensive-coding/en-US/Tasks/.svn/text-base/schemas.xml.svn-base new file mode 100644 index 0000000..8e84245 --- /dev/null +++ b/defensive-coding/en-US/Tasks/.svn/text-base/schemas.xml.svn-base @@ -0,0 +1,4 @@ + + + + diff --git a/defensive-coding/en-US/Tasks/Cryptography.xml b/defensive-coding/en-US/Tasks/Cryptography.xml new file mode 100644 index 0000000..88f14a3 --- /dev/null +++ b/defensive-coding/en-US/Tasks/Cryptography.xml @@ -0,0 +1,111 @@ + + + + Cryptography + +
+ Primitives + + Chosing from the following cryptographic primitives is + recommended: + + + RSA with 2048 bit keys and OAEP + AES-128 in CBC mode + SHA-256 + HMAC-SHA-256 + HMAC-SHA-1 + + + Other cryptographic algorithms can be used if they are required + for interoperability with existing software: + + + RSA with key sizes larger than 1024 + and legacy padding + AES-192 + AES-256 + 3DES (triple DES, with two or three 56 bit keys) + RC4 (but very, very strongly discouraged) + SHA-1 + HMAC-MD5 + + + Important + + These primitives are difficult to use in a secure way. Custom + implementation of security protocols should be avoided. For + protecting confidentiality and integrity of network + transmissions, TLS should be used (). + + + +
+ +
+ Randomness + + The following facilities can be used to generate unpredictable + and non-repeating values. When these functions are used without + special safeguards, each individual rnadom value should be at + least 12 bytes long. + + + + PK11_GenerateRandom in the NSS library + (usable for high data rates) + + + RAND_bytes in the OpenSSL library + (usable for high data rates) + + + gnutls_rnd in GNUTLS, with + GNUTLS_RND_RANDOM as the first argument + (usable for high data rates) + + + java.security.SecureRandom in Java + (usable for high data rates) + + + os.urandom in Python + + + Reading from the /dev/urandom + character device + + + + All these functions should be non-blocking, and they should not + wait until physical randomness becomes available. (Some + cryptography providers for Java can cause + java.security.SecureRandom to block, however.) + Those functions which do not obtain all bits directly from + /dev/urandom are suitable for high data + rates because they do not deplete the system-wide entropy pool. + + + Difficult to use API + + Both RAND_bytes and + PK11_GenerateRandom have three-state + return values (with conflicting meanings). Careful error + checking is required. Please review the documentation when + using these functions. + + + + Other sources of randomness should be considered predictable. + + + Generating randomness for cryptographic keys in long-term use + may need different steps and is best left to cryptographic + libraries. + +
+ +
diff --git a/defensive-coding/en-US/Tasks/Descriptors.xml b/defensive-coding/en-US/Tasks/Descriptors.xml new file mode 100644 index 0000000..bdf1fb2 --- /dev/null +++ b/defensive-coding/en-US/Tasks/Descriptors.xml @@ -0,0 +1,266 @@ + + + + File Descriptor Management + + File descriptors underlie all input/output mechanisms offered by + the system. They are used to implementation the FILE + *-based functions found in + <stdio.h>, and all the file and network + communication facilities provided by the Python and Java + environments are eventually implemented in them. + + + File descriptors are small, non-negative integers in userspace, + and are backed on the kernel side with complicated data structures + which can sometimes grow very large. + +
+ Closing descriptors + + If a descriptor is no longer used by a program and is not closed + explicitly, its number cannot be reused (which is problematic in + itself, see ), and + the kernel resources are not freed. Therefore, it is important + to close all descriptors at the earlierst point in time + possible, but not earlier. + +
+ Error handling during descriptor close + + The close system call is always + successful in the sense that the passed file descriptor is + never valid after the function has been called. However, + close still can return an error, for + example if there was a file system failure. But this error is + not very useful because the absence of an error does not mean + that all caches have been emptied and previous writes have + been made durable. Programs which need such guarantees must + open files with O_SYNC or use + fsync or fdatasync, and + may also have to fsync the directory + containing the file. + +
+
+ Closing descriptors and race conditions + + Unlike process IDs, which are recycle only gradually, the + kernel always allocates the lowest unused file descriptor when + a new descriptor is created. This means that in a + multi-threaded program which constantly opens and closes file + descriptors, descriptors are reused very quickly. Unless + descriptor closing and other operations on the same file + descriptor are synchronized (typically, using a mutex), there + will be race coniditons and I/O operations will be applied to + the wrong file descriptor. + + + Sometimes, it is necessary to close a file descriptor + concurrently, while another thread might be about to use it in + a system call. In order to support this, a program needs to + create a single special file descriptor, one on which all I/O + operations fail. One way to achieve this is to use + socketpair, close one of the descriptors, + and call shutdown(fd, SHUTRDWR) on the + other. + + + When a descriptor is closed concurrently, the program does not + call close on the descriptor. Instead it + program uses dup2 to replace the + descriptor to be closed with the dummy descriptor created + earlier. This way, the kernel will not reuse the descriptor, + but it will carry out all other steps associated with calling + a descriptor (for instance, if the descriptor refers to a + stream socket, the peer will be notified). + + + This is just a sketch, and many details are missing. + Additional data structures are needed to determine when it is + safe to really close the descriptor, and proper locking is + required for that. + +
+
+ Lingering state after close + + By default, closing a stream socket returns immediately, and + the kernel will try to send the data in the background. This + means that it is impossible to implement accurate accounting + of network-related resource utilization from userspace. + + + The SO_LINGER socket option alters the + behavior of close, so that it will return + only after the lingering data has been processed, either by + sending it to the peer successfully, or by discarding it after + the configured timeout. However, there is no interface which + could perform this operation in the background, so a separate + userspace thread is needed for each close + call, causing scalability issues. + + + Currently, there is no application-level countermeasure which + applies universally. Mitigation is possible with + iptables (the + connlimit match type in particular) and + specialized filtering devices for denial-of-service network + traffic. + + + These problems are not related to the + TIME_WAIT state commonly seen in + netstat output. The kernel + automatically expires such sockets if necessary. + +
+
+ +
+ Preventing file descriptor leaks to child processes + + Child processes created with fork share + the initial set of file descriptors with their parent + process. By default, file descriptors are also preserved if + a new process image is created with execve + (or any of the other functions such as system + or posix_spawn). + + + Usually, this behavior is not desirable. There are two ways to + turn it off, that is, to prevent new process images from + inheriting the file descriptors in the parent process: + + + + + Set the close-on-exec flag on all newly created file + descriptors. Traditionally, this flag is controlled by the + FD_CLOEXEC flag, using + F_GETFD and F_SETFD + operations of the fcntl function. + + + However, in a multi-threaded process, there is a race + condition: a subprocess could have been created between the + time the descriptor was created and the + FD_CLOEXEC was set. Therefore, many system + calls which create descriptors (such as + open and openat) + now accept the O_CLOEXEC flag + (SOCK_CLOEXEC for + socket and + socketpair), which cause the + FD_CLOEXEC flag to be set for the file + descriptor in an atomic fashion. In addition, a few new + systems calls were introduced, such as + pipe2 and dup3. + + + The downside of this approach is that every descriptor needs + to receive special treatment at the time of creation, + otherwise it is not completely effective. + + + + + After calling fork, but before creating + a new process image with execve, all + file descriptors which the child process will not need are + closed. + + + Traditionally, this was implemented as a loop over file + descriptors ranging from 3 to + 255 and later 1023. + But this is only an approximatio because it is possible to + create file descriptors outside this range easily (see ). + Another approach reads /proc/self/fd + and closes the unexpected descriptors listed there, but this + approach is much slower. + + + + + At present, environments which care about file descriptor + leakage implement the second approach. OpenJDK 6 and 7 + are among them. + +
+ +
+ Dealing with the <function>select</function> limit + + By default, a user is allowed to open only 1024 files in a + single process, but the system administrator can easily change + this limit (which is necessary for busy network servers). + However, there is another restriction which is more difficult to + overcome. + + + The select function only supports a + maximum of FD_SETSIZE file descriptors + (that is, the maximum permitted value for a file descriptor + is FD_SETSIZE - 1, usually 1023.) If a + process opens many files, descriptors may exceed such + limits. It is impossible to query such descriptors using + select. + + + If a library which creates many file descriptors is used in + the same process as a library which uses + select, at least one of them needs to + be changed. + Calls to select can be replaced with + calls to poll or another event handling + mechanism. + + + Alternatively, the library with high descriptor usage can + relocate descriptors above the FD_SETSIZE + limit using the following procedure. + + + + + Create the file descriptor fd as + usual, preferably with the O_CLOEXEC + flag. + + + + + Before doing anything else with the descriptor + fd, invoke: + + + int newfd = fcntl(fd, F_DUPFD_CLOEXEC, (long)FD_SETSIZE); + + + + + Check that newfd result is + non-negative, otherwise close fd and + report an error, and return. + + + + + Close fd and continue to use + newfd. + + + + + The new descriptor has been allocated above the + FD_SETSIZE. Even though this algorithm + is racy in the sense that the FD_SETSIZE + first descriptors could fill up, a very high degree of + physical parallelism is required before this becomes a problem. + +
+
diff --git a/defensive-coding/en-US/Tasks/File_System.xml b/defensive-coding/en-US/Tasks/File_System.xml new file mode 100644 index 0000000..ee3eb17 --- /dev/null +++ b/defensive-coding/en-US/Tasks/File_System.xml @@ -0,0 +1,339 @@ + + + + File system manipulation + + In this chapter, we discuss general file system manipulation, with + a focus on access files and directories to which an other, + potentially untrusted user has write access. + + + Temporary files are covered in their own chapter, . + +
+ Working with files and directories owned by other users + + Sometimes, it is necessary to operate on files and directories + owned by other (potentially untrusted) users. For example, a + system administrator could remove the home directory of a user, + or a package manager could update a file in a directory which is + owned by an application-specific user. This differs from + accessing the file system as a specific user; see + . + + + Accessing files across trust boundaries faces several + challenges, particularly if an entire directory tree is being + traversed: + + + + + Another user might add file names to a writable directory at + any time. This can interfere with file creation and the + order of names returned by readdir. + + + + + Merely opening and closing a file can have side effects. + For instance, an automounter can be triggered, or a tape + device rewound. Opening a file on a local file system can + block indefinitely, due to mandatory file locking, unless + the O_NONBLOCK flag is specified. + + + + + Hard links and symbolic links can redirect the effect of + file system operations in unexpected ways. The + O_NOFOLLOW and + AT_SYMLINK_NOFOLLOW variants of system + calls only affected final path name component. + + + + + The structure of a directory tree can change. For example, + the parent directory of what used to be a subdirectory + within the directory tree being processed could suddenly + point outside that directory tree. + + + + + Files should always be created with the + O_CREAT and O_EXCL flags, + so that creating the file will fail if it already exists. This + guards against the unexpected appearance of file names, either + due to creation of a new file, or hard-linking of an existing + file. In multi-threaded programs, rather than manipulating the + umask, create the files with mode 000 if + possible, and adjust it afterwards with + fchmod. + + + To avoid issues related to symbolic links and directory tree + restructuring, the “at” variants of system + calls have to be used (that is, functions like + openat, fchownat, + fchmodat, and + unlinkat, together with + O_NOFOLLOW or + AT_SYMLINK_NOFOLLOW). Path names passed to + these functions must have just a single component (that is, + without a slash). When descending, the descriptors of parent + directories must be kept open. The missing + opendirat function can be emulated with + openat (with an + O_DIRECTORY flag, to avoid opening special + files with side effects), followed by + fdopendir. + + + If the “at” functions are not available, it + is possible to emulate them by changing the current directory. + (Obviously, this only works if the process is not multi-threaded.) + fchdir has to be used to change the current + directory, and the descriptors of the parent directories have to + be kept open, just as with the “at”-based + approach. chdir("...") is unsafe because it + might ascend outside the intended directory tree. + + + This “at” function emulation is currently + required when manipulating extended attributes. In this case, + the lsetxattr function can be used, with a + relative path name consisting of a single component. This also + applies to SELinux contexts and the + lsetfilecon function. + + + Currently, it is not possible to avoid opening special files + and changes to files with hard links if the + directory containing them is owned by an untrusted user. + (Device nodes can be hard-linked, just as regular files.) + fchmodat and fchownat + affect files whose link count is greater than one. But opening + the files, checking that the link count is one with + fstat, and using + fchmod and fchown on + the file descriptor may have unwanted side effects, due to item + 2 above. When creating directories, it is therefore important + to change the ownership and permissions only after it has been + fully created. Until that point, file names are stable, and no + files with unexpected hard links can be introduced. + + + Similarly, when just reading a directory owned by an untrusted + user, it is currently impossible to reliably avoid opening + special files. + + + There is no workaround against the instability of the file list + returned by readdir. Concurrent + modification of the directory can result in a list of files + being returned which never actually existed on disk. + + + Hard links and symbolic links can be safely deleted using + unlinkat without further checks because + deletion only affects the name within the directory tree being + processed. + +
+
+ Accessing the file system as a different user + + This section deals with access to the file system as a specific + user. This is different from accessing files and directories owned by a + different, potentially untrusted user; see . + + + One approach is to spawn a child process which runs under the + target user and group IDs (both effective and real IDs). Note + that this child process can block indefinitely, even when + processing regular files only. For example, a special FUSE file + system could cause the process to hang in uninterruptible sleep + inside a stat system call. + + + An existing process could change its user and group ID using + setfsuid and setfsgid. + (These functions are preferred over seteuid + and setegid because they do not allow the + impersonated user to send signals to the process.) These + functions are not thread safe. In multi-threaded processes, + these operations need to be performed in a single-threaded child + process. Unexpected blocking may occur as well. + + + It is not recommended to try to reimplement the kernel + permission checks in user space because the required checks are + complex. It is also very difficult to avoid race conditions + during path name resolution. + +
+
+ File system limits + + For historical reasons, there are preprocessor constants such as + PATH_MAX, NAME_MAX. + However, on most systems, the length of canonical path names + (absolute path names with all symbolic links resolved, as + returned by realpath or + canonicalize_file_name) can exceed + PATH_MAX bytes, and individual file name + components can be longer than NAME_MAX. This + is also true of the _PC_PATH_MAX and + _PC_NAME_MAX values returned by + pathconf, and the + f_namemax member of struct + statvfs. Therefore, these constants should not be + used. This is also reason why the + readdir_r should never be used (instead, + use readdir). + + + You should not write code in a way that assumes that there is an + upper limit on the number of subdirectories of a directory, the + number of regular files in a directory, or the link count of an + inode. + +
+
+ File system features + + Not all file systems support all features. This makes it very + difficult to write general-purpose tools for copying files. For + example, a copy operation intending to preserve file permissions + will generally fail when copying to a FAT file system. + + + + + Some file systems are case-insensitive. Most should be + case-preserving, though. + + + + + Name length limits vary greatly, from eight to thousands of + bytes. Path length limits differ as well. Most systems + impose an upper bound on path names passed to the kernel, + but using relative path names, it is possible to create and + access files whose absolute path name is essentially of + unbounded length. + + + + + Some file systems do not store names as fairly unrestricted + byte sequences, as it has been traditionally the case on GNU + systems. This means that some byte sequences (outside the + POSIX safe character set) are not valid names. Conversely, + names of existing files may not be representable as byte + sequences, and the files are thus inaccessible on GNU + systems. Some file systems perform Unicode canonicalization + on file names. These file systems preserve case, but + reading the name of a just-created file using + readdir might still result in a + different byte sequence. + + + + + Permissions and owners are not universally supported (and + SUID/SGID bits may not be available). For example, FAT file + systems assign ownership based on a mount option, and + generally mark all files as executable. Any attempt to + change permissions would result in an error. + + + + + Non-regular files (device nodes, FIFOs) are not generally + available. + + + + + Only on some file systems, files can have holes, that is, + not all of their contents is backed by disk storage. + + + + + ioctl support (even fairly generic + functionality such as FIEMAP for + discovering physical file layout and holes) is + file-system-specific. + + + + + Not all file systems support extended attributes, ACLs and + SELinux metadata. Size and naming restriction on extended + attributes vary. + + + + + Hard links may not be supported at all (FAT) or only within + the same directory (AFS). Symbolic links may not be + available, either. Reflinks (hard links with copy-on-write + semantics) are still very rare. Recent systems restrict + creation of hard links to users which own the target file or + have read/write access to it, but older systems do not. + + + + + Renaming (or moving) files using rename + can fail (even when stat indicates that + the source and target directories are located on the same + file system). This system call should work if the old and + new paths are located in the same directory, though. + + + + + Locking semantics vary among file systems. This affects + advisory and mandatory locks. For example, some network + file systems do not allow deleting files which are opened by + any process. + + + + + Resolution of time stamps varies from two seconds to + nanoseconds. Not all time stamps are available on all file + systems. File creation time (birth + time) is not exposed over the + stat/fstat + interface, even if stored by the file system. + + + +
+
+ Checking free space + + The statvfs and + fstatvfs functions allow programs to + examine the number of available blocks and inodes, through the + members f_bfree, f_bavail, + f_ffree, and f_favail of + struct statvfs. Some file systems return + fictional values in the f_ffree and + f_favail fields, so the only reliable way to + discover if the file system still has space for a file is to try + to create it. The f_bfree field should be + reasonably accurate, though. + +
+
+ diff --git a/defensive-coding/en-US/Tasks/Library_Design.xml b/defensive-coding/en-US/Tasks/Library_Design.xml new file mode 100644 index 0000000..7c959ab --- /dev/null +++ b/defensive-coding/en-US/Tasks/Library_Design.xml @@ -0,0 +1,195 @@ + + + + Library Design + + Throught this section, the term client code + refers to applications and other libraries using the library. + + +
+ State management + + +
+ Global state + + Global state should be avoided. + + + If this is impossible, the global state must be protected with + a lock. For C/C++, you can use the + pthread_mutex_lock + and pthread_mutex_unlock + functions without linking against -lpthread + because the system provides stubs for non-threaded processes. + + + For compatibility with fork, these locks + should be acquired and released in helpers registered with + pthread_atfork. This function is not + available without -lpthread, so you need to + use dlsym or a weak symbol to obtain its + address. + + + If you need fork protection for other + reasons, you should store the process ID and compare it to the + value returned by getpid each time you + access the global state. (getpid is not + implemented as a system call and is fast.) If the value + changes, you know that you have to re-create the state object. + (This needs to be combined with locking, of course.) + +
+
+ Handles + + Library state should be kept behind a curtain. Client code + should receive only a handle. In C, the handle can be a + pointer to an incomplete struct. In C++, + the handle can be a pointer to an abstract base class, or it + can be hidden using the pointer-to-implementation idiom. + + + The library should provide functions for creating and + destroying handles. (In C++, it is possible to use virtual + destructors for the latter.) Consistency between creation and + destruction of handles is strongly recommended: If the client + code created a handle, it is the responsibility of the client + code to destroy it. (This is not always possible or + convenient, so sometimes, a transfer of ownership has to + happen.) + + + Using handles ensures that it is possible to change the way + the library represents state in a way that is transparent to + client code. This is important to facilitate security updates + and many other code changes. + + + It is not always necessary to protect state behind a handle + with a lock. This depends on the level of thread safety + the library provides. + +
+
+ +
+ Object orientation + + Classes should be either designed as base classes, or it should + be impossible to use them as base classes (like + final classes in Java). Classes which are + not designed for inheritance and are used as base classes + nevertheless create potential maintenance hazards because it is + difficult to predict how client code will react when calls to + virtual methods are added, reordered or removed. + + + Virtual member functions can be used as callbacks. See + + for some of the challenges involved. + +
+ +
+ Callbacks + + Higher-order code is difficult to analyze for humans and + computers alike, so it should be avoided. Often, an + iterator-based interface (a library function which is called + repeatedly by client code and returns a stream of events) leads + to a better design which is easier to document and use. + + + If callbacks are unavoidable, some guidelines for them follow. + + + In modern C++ code, std::function objects + should be used for callbacks. + + + In older C++ code and in C code, all callbacks must have an + additional closure parameter of type void *, + the value of which can be specified by client code. If + possible, the value of the closure parameter should be provided + by client code at the same time a specific callback is + registered (or specified as a function argument). If a single + closure parameter is shared by multiple callbacks, flexibility + is greatly reduced, and conflicts between different pieces of + client code using the same library object could be unresolvable. + In some cases, it makes sense to provide a de-registration + callback which can be used to destroy the closure parameter when + the callback is no longer used. + + + Callbacks can throw exceptions or call + longjmp. If possible, all library objects + should remain in a valid state. (All further operations on them + can fail, but it should be possible to deallocate them without + causing resource leaks.) + + + The presence of callbacks raises the question if functions + provided by the library are reentrant. + Unless a library was designed for such use, bad things will + happen if a callback function uses functions in the same library + (particularly if they are invoked on the same objects and + manipulate the same state). When the callback is invoked, the + library can be in an inconsistent state. Reentrant functions + are more difficult to write than thread-safe functions (by + definition, simple locking would immediately lead to deadlocks). + It is also difficult to decide what to do when destruction of an + object which is currently processing a callback is requested. + +
+ +
+ Process attributes + + Several attributes are global and affect all code in the + process, not just the library that manipulates them. + + + + environment variables + (see ) + + + umask + + + user IDs, group IDs and capabilities + + + current working directory + + + signal handlers, signal masks and signal delivery + + + file locks (especially fcntl locks + behave in surprising ways, not just in a multi-threaded + environment) + + + + Library code should avoid manipulating these global process + attributes. It should not rely on environment variables, umask, + the current working directory and signal masks because these + attributes can be inherted from an untrusted source. + + + In addition, there are obvious process-wide aspects such as the + virtual memory layout, the set of open files and dynamic shared + objects, but with the exception of shared objects, these can be + manipulated in a relatively isolated way. + + +
+ +
+ + diff --git a/defensive-coding/en-US/Tasks/Locking.xml b/defensive-coding/en-US/Tasks/Locking.xml new file mode 100644 index 0000000..f85e61e --- /dev/null +++ b/defensive-coding/en-US/Tasks/Locking.xml @@ -0,0 +1,5 @@ + + + + diff --git a/defensive-coding/en-US/Tasks/Processes.xml b/defensive-coding/en-US/Tasks/Processes.xml new file mode 100644 index 0000000..90f01f0 --- /dev/null +++ b/defensive-coding/en-US/Tasks/Processes.xml @@ -0,0 +1,483 @@ + + + + Processes + +
+ Safe process creation + + This section describes how to create new child processes in a + safe manner. In addition to the concerns addressed below, there + is the possibility of file descriptor leaks, see . + +
+ Obtaining the program path and the command line + template + + The name and path to the program being invoked should be + hard-coded or controlled by a static configuration file stored + at a fixed location (at an file system absolute path). The + same applies to the template for generating the command line. + + + The configured program name should be an absolute path. If it + is a relative path, the contents of the PATH + must be obtained in s secure manner (see ). + If the PATH variable is not set or untrusted, + the safe default /bin:/usr/bin must be + used. + + + If too much flexibility is provided here, it may allow + invocation of arbitrary programs without proper authorization. + +
+ +
+ Bypassing the shell + + Child processes should be created without involving the system + shell. + + + For C/C++, system should not be used. + The posix_spawn function can be used + instead, or a combination fork and + execve. (In some cases, it may be + preferable to use vfork or the + Linux-specific clone system call instead + of fork.) + + + In Python, the subprocess module bypasses + the shell by default (when the shell + keyword argument is not set to true). + os.system should not be used. + + + The Java class java.lang.ProcessBuilder can be + used to create subprocesses without interference from the + system shell. + + + Portability notice + + On Windows, there is no argument vector, only a single + argument string. Each application is responsible for parsing + this string into an argument vector. There is considerable + variance among the quoting style recognized by applications. + Some of them expand shell wildcards, others do not. Extensive + application-specific testing is required to make this secure. + + + + Note that some common applications (notably + ssh) unconditionally introduce the + use of a shell, even if invoked directly without a shell. It is + difficult to use these applications in a secure manner. In this + case, untrusted data should be supplied by other means. For + example, standard input could be used, instead of the command + line. + +
+ +
+ Specifying the process environment + + Child processes should be created with a minimal set of + environment variables. This is absolutely essential if there + is a trust transition involved, either when the parent process + was created, or during the creation of the child process. + + + In C/C++, the environment should be constructed as an array of + strings and passed as the envp argument to + posix_spawn or execve. + The functions setenv, + unsetenv and putenv + should not be used. They are not thread-safe and suffer from + memory leaks. + + + Python programs need to specify a dict for + the the env argument of the + subprocess.Popen constructor. + The Java class java.lang.ProcessBuilder + provides a environment() method, + which returns a map that can be manipulated. + + + The following list provides guidelines for selecting the set + of environment variables passed to the child process. + + + + + PATH should be initialized to + /bin:/usr/bin. + + + + + USER and HOME can be inhereted + from the parent process environment, or they can be + initialized from the pwent structure + for the user. + + + + The DISPLAY and XAUTHORITY + variables should be passed to the subprocess if it is an X + program. Note that this will typically not work across trust + boundaries because XAUTHORITY refers to a file + with 0600 permissions. + + + + + The location-related environment variables + LANG, LANGUAGE, + LC_ADDRESS, LC_ALL, + LC_COLLATE, LC_CTYPE, + LC_IDENTIFICATION, + LC_MEASUREMENT, LC_MESSAGES, + LC_MONETARY, LC_NAME, + LC_NUMERIC, LC_PAPER, + LC_TELEPHONE and LC_TIME + can be passed to the subprocess if present. + + + + + The called process may need application-specific + environment variables, for example for passing passwords. + (See .) + + + + + All other environment variables should be dropped. Names + for new environment variables should not be accepted from + untrusted sources. + + + +
+ +
+ Robust argument list processing + + When invoking a program, it is sometimes necessary to include + data from untrusted sources. Such data should be check + against embedded NUL characters because the + system APIs will sliently truncate argument strings at the first + NUL character. + + + The following recommendations assume that the program being + invoked uses GNU-style option processing using + getopt_long. This convention is widely + used, but it is just that, and individual programs might + interpret a command line in a different way. + + + If the untrusted data has to go into an option, use the + --option-name=VALUE syntax, placing the + option and its value into the same command line argument. + This avoids any potential confusion if the data starts with + -. + + + For positional arguments, terminate the option list with a + single marker after the last option, and + include the data at the right position. The + marker terminates option processing, and + the data will not be treated as an option even if it starts + with a dash. + +
+ +
+ Passing secrets to subprocesses + + The command line (the name of the program and its argument) of + a running process is traditionally available to all local + users. The called program can overwrite this information, but + only after it has run for a bit of time, during which the + information may have been read by other processes. However, + on Linux, the process environment is restricted to the user + who runs the process. Therefore, if you need a convenient way + to pass a password to a child process, use an environment + variable, and not a command line argument. (See .) + + + Portability notice + + On some UNIX-like systems (notably Solaris), environment + variables can be read by any system user, just like command + lines. + + + + If the environment-based approach cannot be used due to + portability concerns, the data can be passed on standard + input. Some programs (notably gpg) + use special file descriptors whose numbers are specified on + the command line. Temporary files are an option as well, but + they might give digital forensics access to sensitive data + (such as passphrases) because it is difficult to safely delete + them in all cases. + +
+
+ +
+ Handling child process termination + + When child processes terminate, the parent process is signalled. + A stub of the terminated processes (a + zombie, shown as + <defunct> by + ps) is kept around until the status + information is collected (reaped) by the + parent process. Over the years, several interfaces for this + have been invented: + + + + + The parent process calls wait, + waitpid, waitid, + wait3 or wait4, + without specifying a process ID. This will deliver any + matching process ID. This approach is typically used from + within event loops. + + + + + The parent process calls waitpid, + waitid, or wait4, + with a specific process ID. Only data for the specific + process ID is returned. This is typically used in code + which spawns a single subprocess in a synchronous manner. + + + + + The parent process installs a handler for the + SIGCHLD signal, using + sigaction, and specifies to the + SA_NOCLDWAIT flag. + This approach could be used by event loops as well. + + + + + None of these approaches can be used to wait for child process + terminated in a completely thread-safe manner. The parent + process might execute an event loop in another thread, which + could pick up the termination signal. This means that libraries + typically cannot make free use of child processes (for example, + to run problematic code with reduced privileges in a separate + address space). + + + At the moment, the parent process should explicitly wait for + termination of the child process using + waitpid or waitpid, + and hope that the status is not collected by an event loop + first. + +
+ +
+ <literal>SUID</literal>/<literal>SGID</literal> + processes + + + Programs can be marked in the file system to indicate to the + kernel that a trust transition should happen if the program is + run. The SUID file permission bit indicates + that an executable should run with the effective user ID equal + to the owner of the executable file. Similarly, with the + SGID bit, the effective group ID is set to + the group of the executable file. + + + Linux supports fscaps, which can grant + additional capabilities to a process in a finer-grained manner. + Additional mechanisms can be provided by loadable security + modules. + + + When such a trust transition has happened, the process runs in a + potentially hostile environment. Additional care is necessary + not to rely on any untrusted information. These concerns also + apply to libraries which can be linked into such processes. + + +
+ Accessing environment variables + + The following steps are required so that a program does not + accidentally pick up untrusted data from environment + variables. + + + + Compile your C/C++ sources with -D_GNU_SOURCE. + The Autoconf macro AC_GNU_SOURCE ensures this. + + + Check for the presence of the secure_getenv + and __secure_getenv function. The Autoconf + directive AC_CHECK_FUNCS([__secure_getenv secure_getenv]) + performs these checks. + + + Arrange for a proper definition of the + secure_getenv function. See . + + + Use secure_getenv instead of + getenv to obtain the value of critical + environment variables. secure_getenv + will pretend the variable has not bee set if the process + environment is not trusted. + + + + Critical environment variables are debugging flags, + configuration file locations, plug-in and log file locations, + and anything else that might be used to bypass security + restrictions or cause a privileged process to behave in an + unexpected way. + + + Either the secure_getenv function or the + __secure_getenv is available from GNU libc. + + + Obtaining a definition for <function>secure_getenv</function> + + + +#ifndef HAVE_SECURE_GETENV +# ifdef HAVE__SECURE_GETENV +# define secure_getenv __secure_getenv +# else +# error neither secure_getenv nor __secure_getenv are available +# endif +#endif +]]> + + +
+
+ +
+ Daemons + + Background processes providing system services + (daemons) need to decouple themselves from + the controlling terminal and the parent process environment: + + + + Fork. + + + + In the child process, call setsid. The + parent process can simply exit (using + _exit, to avoid running clean-up + actions twice). + + + + + In the child process, fork again. Processing continues in + the child process. Again, the parent process should just + exit. + + + + + Replace the descriptors 0, 1, 2 with a descriptor for + /dev/null. Logging should be + redirected to syslog. + + + + + Older instructions for creating daemon processes recommended a + call to umask(0). This is risky because it + often leads to world-writable files and directories, resulting + in security vulnerabilities such as arbitrary process + termination by untrusted local users, or log file truncation. + If the umask needs setting, a restrictive + value such as 027 or 077 + is recommended. + + + Other aspects of the process environment may have to changed as + well (environment variables, signal handler disposition). + + + It is increasingly common that server processes do not run as + background processes, but as regular foreground process under a + supervising master process (such as + systemd). Server processes should + offer a command line option which disables forking and + replacement of the standard output and standard error streams. + Such an option is also useful for debugging. + +
+ +
+ Semantics of command line arguments + + + After process creation and option processing, it is up to the + child process to interpret the arguments. Arguments can be + file names, host names, or URLs, and many other things. URLs + can refer to the local network, some server on the Internet, + or to the local file system. Some applications even accept + arbitrary code in arguments (for example, + python with the + option). + + + Similar concerns apply to environment variables, the contents + of the current directory and its subdirectories. + + + + Consequently, careful analysis is required if it is safe to + pass untrusted data to another program. + +
+ +
+ <function>fork</function> as a primitive for parallelism + + A call to fork which is not immediately + followed by a call to execve (perhaps after + rearranging and closing file descriptors) is typically unsafe, + especially from a library which does not control the state of + the entire process. Such use of fork + should be replaced with proper child processes or threads. + +
+ +
diff --git a/defensive-coding/en-US/Tasks/Serialization.xml b/defensive-coding/en-US/Tasks/Serialization.xml new file mode 100644 index 0000000..60427c5 --- /dev/null +++ b/defensive-coding/en-US/Tasks/Serialization.xml @@ -0,0 +1,397 @@ + + + + Serialization and Deserialization + + Protocol decoders and file format parsers are often the + most-exposed part of an application because they are exposed with + little or no user interaction and before any authentication and + security checks are made. They are also difficult to write + robustly in languages which are not memory-safe. + + +
+ Recommendations for manually written decoders + + For C and C++, the advice in applies. In + addition, avoid non-character pointers directly into input + buffers. Pointer misalignment causes crashes on some + architectures. + + + When reading variable-sized objects, do not allocate large + amounts of data solely based on the value of a size field. If + possible, grow the data structure as more data is read from the + source, and stop when no data is available. This helps to avoid + denial-of-service attacks where little amounts of input data + results in enormous memory allocations during decoding. + Alternatively, you can impose reasonable bounds on memory + allocations, but some protocols do not permit this. + +
+ +
+ Protocol design + + Binary formats with explicit length fields are more difficult to + parse robustly than those where the length of dynamically-sized + elements is derived from sentinel values. A protocol which does + not use length fields and can be written in printable ASCII + characters simplifies testing and debugging. However, binary + protocols with length fields may be more efficient to parse. + +
+ +
+ Library + support for deserialization + + For some languages, generic libraries are available which allow + to serialize and deserialize user-defined objects. The + deserialization part comes in one of two flavors, depending on + the library. The first kind uses type information in the data + stream to control which objects are instantiated. The second + kind uses type definitions supplied by the programmer. The + first one allows arbitrary object instantiation, the second one + generally does not. + + + The following serialization frameworks are in the first category, + are known to be unsafe, and must not be used for untrusted data: + + + + Python's pickle and cPickle + modules + + + Perl's Storable package + + + Java serialization (java.io.ObjectInputStream) + + + PHP serialization (unserialize) + + + Most implementations of YAML + + + + When using a type-directed deserialization format where the + types of the deserialized objects are specified by the + programmer, make sure that the objects which can be instantiated + cannot perform any destructive actions in their destructors, + even when the data members have been manipulated. + + + JSON decoders do not suffer from this problem. But you must not + use the eval function to parse JSON objects + in Javascript; even with the regular expression filter from RFC + 4627, there are still information leaks remaining. + +
+ +
+ XML serialization + + +
+ External references + + XML documents can contain external references. They can occur + in various places. + + + + + In the DTD declaration in the header of an XML document: + + + +]]> + + + + + + In a namespace declaration: + + + +]]> + + + + + + In an entity defintion: + + + + +]]> + + + + + + In a notation: + + + +]]> + + + + + + Originally, these external references were intended as unique + identifiers, but by many XML implementations, they are used + for locating the data for the referenced element. This causes + unwanted network traffic, and may disclose file system + contents or otherwise unreachable network resources, so this + functionality should be disabled. + + + Depending on the XML library, external referenced might be + processed not just when parsing XML, but also when generating + it. + +
+
+ Entity expansion + + When external DTD processing is disabled, an internal DTD + subset can still contain entity definitions. Entity + declarations can reference other entities. Some XML libraries + expand entities automatically, and this processing cannot be + switched off in some places (such as attribute values or + content models). Without limits on the entity nesting level, + this expansion results in data which can grow exponentially in + length with size of the input. (If there is a limit on the + nesting level, the growth is still polynomial, unless further + limits are imposed.) + + + Consequently, the processing internal DTD subsets should be + disabled if possible, and only trusted DTDs should be + processed. If a particular XML application does not permit + such restrictions, then application-specific limits are called + for. + +
+ +
+ XInclude processing + + XInclude processing can reference file and network resources + and include them into the document, much like external entity + references. When parsing untrusted XML documents, XInclude + processing should be truned off. + + + XInclude processing is also fairly complex and may pull in + support for the XPointer and XPath specifications, + considerably increasing the amount of code required for XML + processing. + +
+ +
+ Algorithmic complexity of XML validation + + DTD-based XML validation uses regular expressions for content + models. The XML specification requires that content models + are deterministic, which means that efficient validation is + possible. However, some implementations do not enforce + determinism, and require exponential (or just polynomial) + amount of space or time for validating some DTD/document + combinations. + + + XML schemas and RELAX NG (via the xsd: + prefix) directly support textual regular expressions which are + not required to be deterministic. + +
+
+ Using Expat for XML parsing + + By default, Expat does not try to resolve external IDs, so no + steps are required to block them. However, internal entity + declarations are processed. Installing a callback which stops + parsing as soon as such entities are encountered disables + them, see . + Expat does not perform any validation, so there are no + problems related to that. + + + Disabling XML entity processing with Expat + + + + This handler must be installed when the + XML_Parser object is created (). + + + Creating an Expat XML parser + + + + It is also possible to reject internal DTD subsets altogeher, + using a suitable + XML_StartDoctypeDeclHandler handler + installed with XML_SetDoctypeDeclHandler. + +
+ +
+ Using OpenJDK for XML parsing and validation + + OpenJDK contains facilities for DOM-based, SAX-based, and + StAX-based document parsing. Documents can be validated + against DTDs or XML schemas. + + + The approach taken to deal with entity expansion differs from + the general recommendation in . + We enable the the feature flag + javax.xml.XMLConstants.FEATURE_SECURE_PROCESSING, + which enforces heuristic restrictions on the number of entity + expansions. Note that this flag alone does not prevent + resolution of external references (system IDs or public IDs), + so it is slightly misnamed. + + + In the following sections, we use helper classes to prevent + external ID resolution. + + + Helper class to prevent DTD external entity resolution in OpenJDK + + + + Helper class to prevent schema resolution in + OpenJDK + + + + + shows the imports used by the examples. + + + Java imports for OpenJDK XML parsing + + +
+ DOM-based XML parsing and DTD validation in OpenJDK + + This approach produces a + org.w3c.dom.Document object from an input + stream. + use the data from the java.io.InputStream + instance in the inputStream variable. + + + DOM-based XML parsing in OpenJDK + + + + External entity references are prohibited using the + NoEntityResolver class in + . + Because external DTD references are prohibited, DTD validation + (if enabled) will only happen against the internal DTD subset + embedded in the XML document. + + + To validate the document against an external DTD, use a + javax.xml.transform.Transformer class to + add the DTD reference to the document, and an entity + resolver which whitelists this external reference. + +
+ +
+ XML Schema validation in OpenJDK + + + shows how to validate a document against an XML Schema, + using a SAX-based approach. The XML data is read from an + java.io.InputStream in the + inputStream variable. + + + SAX-based validation against an XML schema in + OpenJDK + + + + The NoResourceResolver class is defined + in . + + + If you need to validate a document against an XML schema, + use the code in + to create the document, but do not enable validation at this + point. Then use + + to perform the schema-based validation on the + org.w3c.dom.Document instance + document. + + + Validation of a DOM document against an XML schema in + OpenJDK + + +
+
+
+ +
+ Protocol Encoders + + For protocol encoders, you should write bytes to a buffer which + grows as needed, using an exponential sizing policy. Explicit + lengths can be patched in later, once they are known. + Allocating the required number of bytes upfront typically + requires separate code to compute the final size, which must be + kept in sync with the actual encoding step, or vulnerabilities + may result. In multi-threaded code, parts of the object being + deserialized might change, so that the computed size is out of + date. + + + You should avoid copying data directly from a received packet + during encoding, disregarding the format. Propagating malformed + data could enable attacks on other recipients of that data. + + + When using C or C++ and copying whole data structures directly + into the output, make sure that you do not leak information in + padding bytes between fields or at the end of the + struct. + +
+ +
+ diff --git a/defensive-coding/en-US/Tasks/Temporary_Files.xml b/defensive-coding/en-US/Tasks/Temporary_Files.xml new file mode 100644 index 0000000..d78bad7 --- /dev/null +++ b/defensive-coding/en-US/Tasks/Temporary_Files.xml @@ -0,0 +1,257 @@ + + + + Temporary files + + In this chapter, we describe how to create temporary files and + directories, how to remove them, and how to work with programs + which do not create files in ways that a safe with a shared + directory for temporary files. General file system manipulation + is treated in a separate chapter, . + + + Secure creation of temporary files has four different aspects. + + + + + The location of the directory for temporary files must be + obtained in a secure manner (that is, untrusted environment + variables must be ignored, see ). + + + + + A new file must be created. Reusing an existing file must be + avoided (the /tmp race + condition). This is tricky because traditionally, system-wide + temporary directories shared by all users are used. + + + + + The file must be created in a way that makes it impossible for + other users to open it. + + + + + The descriptor for the temporary file should not leak to + subprocesses. + + + + + All functions mentioned below will take care of these aspects. + + + Traditionally, temporary files are often used to reduce memory + usage of programs. More and more systems use RAM-based file + systems such as tmpfs for storing temporary + files, to increase performance and decrease wear on Flash storage. + As a result, spooling data to temporary files does not result in + any memory savings, and the related complexity can be avoided if + the data is kept in process memory. + + +
+ Obtaining the location of temporary directory + + Some functions below need the location of a directory which + stores temporary files. For C/C++ programs, use the following + steps to obtain that directory: + + + + + Use secure_getenv to obtain the value + of the TMPDIR environment variable. If + it is set, convert the path to a fully-resolved absolute + path, using realpath(path, NULL). Check + if the new path refers to a directory and is writeable. In + this case, use it as the temporary directory. + + + + + Fall back to /tmp. + + + + + In Python, you can use the tempfile.tempdir + variable. + + + Java does not support SUID/SGID programs, so you can use the + java.lang.System.getenv(String) method to + obtain the value of the TMPDIR environment + variable, and follow the two steps described above. (Java's + default directory selection does not honor + TMPDIR.) + +
+ +
+ Named temporary files + + The mkostemp function creates a named + temporary file. You should specify the + O_CLOEXEC flag to avoid file descriptor leaks + to subprocesses. (Applications which do not use multiple threads + can also use mkstemp, but libraries should + use mkostemp.) For determining the + directory part of the file name pattern, see . + + + The file is not removed automatically. It is not safe to rename + or delete the file before processing, or transform the name in + any way (for example, by adding a file extension). If you need + multiple temporary files, call mkostemp + multiple times. Do not create additional file names derived + from the name provided by a previous + mkostemp call. However, it is safe to close + the descriptor returned by mkostemp and + reopen the file using the generated name. + + + The Python class tempfile.NamedTemporaryFile + provides similar functionality, except that the file is deleted + automatically by default. Note that you may have to use the + file attribute to obtain the actual file + object because some programming interfaces cannot deal with + file-like objects. The C function mkostemp + is also available as tempfile.mkstemp. + + + In Java, you can use the + java.io.File.createTempFile(String, String, + File) function, using the temporary file location + determined according to . + Do not use java.io.File.deleteOnExit() to + delete temporary files, and do not register a shutdown hook for + each temporary file you create. In both cases, the deletion + hint cannot be removed from the system if you delete the + temporary file prior to termination of the VM, causing a memory + leak. + +
+ +
+ Temporary files without names + + The tmpfile function creates a temporary + file and immediately deletes it, while keeping the file open. + As a result, the file lacks a name and its space is deallocated + as soon as the file descriptor is closed (including the implicit + close when the process terminates). This avoids cluttering the + temporary directory with orphaned files. + + + Alternatively, if the maximum size of the temporary file is + known beforehand, the fmemopen function can + be used to create a FILE * object which is + backed by memory. + + + In Python, unnamed temporary files are provided by the + tempfile.TemporaryFile class, and the + tempfile.SpooledTemporaryFile class provides + a way to avoid creation of small temporary files. + + + Java does not support unnamed temporary files. + +
+ +
+ Temporary directories + + The mkdtemp function can be used to create + a temporary directory. (For determining the directory part of + the file name pattern, see .) + The directory is not automatically removed. In Python, this + function is available as tempfile.mkdtemp. + In Java 7, temporary directories can be created using the + java.nio.file.Files.createTempDirectory(Path, String, + FileAttribute...) function. + + + When creating files in the temporary directory, use + automatically generated names, e.g., derived from a sequential + counter. Files with externally provided names could be picked + up in unexpected contexts, and crafted names could actually + point outside of the tempoary directory (due to + directory traversal). + + + Removing a directory tree in a completely safe manner is + complicated. Unless there are overriding performance concerns, + the rm program should be used, with + the and options. + +
+ +
+ Compensating for unsafe file creation + + There are two ways to make a function or program which excepts a + file name safe for use with temporary files. See + , + for details on subprocess creation. + + + + + Create a temporary directory and place the file there. If + possible, run the program in a subprocess which uses the + temporary directory as its current directory, with a + restricted environment. + Use generated names for all files in that temporary + directory. (See .) + + + + + Create the temporary file and pass the generated file name + to the function or program. This only works if the function + or program can cope with a zero-length existing file. It is + safe only under additional assumptions: + + + + + The function or program must not create additional files + whose name is derived from the specified file name or + are otherwise predictable. + + + + + The function or program must not delete the file before + processing it. + + + + + It must not access any existing files in the same + directory. + + + + + It is often difficult to check whether these additional + assumptions are matched, therefore this approach is not + recommended. + + + +
+
diff --git a/defensive-coding/en-US/Tasks/schemas.xml b/defensive-coding/en-US/Tasks/schemas.xml new file mode 100644 index 0000000..8e84245 --- /dev/null +++ b/defensive-coding/en-US/Tasks/schemas.xml @@ -0,0 +1,4 @@ + + + + diff --git a/defensive-coding/en-US/Tasks/snippets/Serialization-XML-Expat-Create.xml b/defensive-coding/en-US/Tasks/snippets/Serialization-XML-Expat-Create.xml new file mode 100644 index 0000000..dd8724d --- /dev/null +++ b/defensive-coding/en-US/Tasks/snippets/Serialization-XML-Expat-Create.xml @@ -0,0 +1,17 @@ + + + + +XML_Parser parser = XML_ParserCreate("UTF-8"); +if (parser == NULL) { + fprintf(stderr, "XML_ParserCreate failed\n"); + close(fd); + exit(1); +} +// EntityDeclHandler needs a reference to the parser to stop +// parsing. +XML_SetUserData(parser, parser); +// Disable entity processing, to inhibit entity expansion. +XML_SetEntityDeclHandler(parser, EntityDeclHandler); + diff --git a/defensive-coding/en-US/Tasks/snippets/Serialization-XML-Expat-EntityDeclHandler.xml b/defensive-coding/en-US/Tasks/snippets/Serialization-XML-Expat-EntityDeclHandler.xml new file mode 100644 index 0000000..2a982f4 --- /dev/null +++ b/defensive-coding/en-US/Tasks/snippets/Serialization-XML-Expat-EntityDeclHandler.xml @@ -0,0 +1,16 @@ + + + + +// Stop the parser when an entity declaration is encountered. +static void +EntityDeclHandler(void *userData, + const XML_Char *entityName, int is_parameter_entity, + const XML_Char *value, int value_length, + const XML_Char *base, const XML_Char *systemId, + const XML_Char *publicId, const XML_Char *notationName) +{ + XML_StopParser((XML_Parser)userData, XML_FALSE); +} + diff --git a/defensive-coding/en-US/Tasks/snippets/Serialization-XML-OpenJDK-Errors.xml b/defensive-coding/en-US/Tasks/snippets/Serialization-XML-OpenJDK-Errors.xml new file mode 100644 index 0000000..928d79b --- /dev/null +++ b/defensive-coding/en-US/Tasks/snippets/Serialization-XML-OpenJDK-Errors.xml @@ -0,0 +1,22 @@ + + + + +class Errors implements ErrorHandler { + @Override + public void warning(SAXParseException exception) { + exception.printStackTrace(); + } + + @Override + public void fatalError(SAXParseException exception) { + exception.printStackTrace(); + } + + @Override + public void error(SAXParseException exception) { + exception.printStackTrace(); + } +} + diff --git a/defensive-coding/en-US/Tasks/snippets/Serialization-XML-OpenJDK-Imports.xml b/defensive-coding/en-US/Tasks/snippets/Serialization-XML-OpenJDK-Imports.xml new file mode 100644 index 0000000..61f0965 --- /dev/null +++ b/defensive-coding/en-US/Tasks/snippets/Serialization-XML-OpenJDK-Imports.xml @@ -0,0 +1,27 @@ + + + + +import javax.xml.XMLConstants; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.sax.SAXSource; +import javax.xml.validation.Schema; +import javax.xml.validation.SchemaFactory; +import javax.xml.validation.Validator; + +import org.w3c.dom.Document; +import org.w3c.dom.ls.LSInput; +import org.w3c.dom.ls.LSResourceResolver; +import org.xml.sax.EntityResolver; +import org.xml.sax.ErrorHandler; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.SAXParseException; +import org.xml.sax.XMLReader; + diff --git a/defensive-coding/en-US/Tasks/snippets/Serialization-XML-OpenJDK-NoEntityResolver.xml b/defensive-coding/en-US/Tasks/snippets/Serialization-XML-OpenJDK-NoEntityResolver.xml new file mode 100644 index 0000000..e1d1049 --- /dev/null +++ b/defensive-coding/en-US/Tasks/snippets/Serialization-XML-OpenJDK-NoEntityResolver.xml @@ -0,0 +1,15 @@ + + + + +class NoEntityResolver implements EntityResolver { + @Override + public InputSource resolveEntity(String publicId, String systemId) + throws SAXException, IOException { + // Throwing an exception stops validation. + throw new IOException(String.format( + "attempt to resolve \"%s\" \"%s\"", publicId, systemId)); + } +} + diff --git a/defensive-coding/en-US/Tasks/snippets/Serialization-XML-OpenJDK-NoResourceResolver.xml b/defensive-coding/en-US/Tasks/snippets/Serialization-XML-OpenJDK-NoResourceResolver.xml new file mode 100644 index 0000000..6eae01a --- /dev/null +++ b/defensive-coding/en-US/Tasks/snippets/Serialization-XML-OpenJDK-NoResourceResolver.xml @@ -0,0 +1,17 @@ + + + + +class NoResourceResolver implements LSResourceResolver { + @Override + public LSInput resolveResource(String type, String namespaceURI, + String publicId, String systemId, String baseURI) { + // Throwing an exception stops validation. + throw new RuntimeException(String.format( + "resolution attempt: type=%s namespace=%s " + + "publicId=%s systemId=%s baseURI=%s", + type, namespaceURI, publicId, systemId, baseURI)); + } +} + diff --git a/defensive-coding/en-US/Tasks/snippets/Serialization-XML-OpenJDK_Parse-DOM.xml b/defensive-coding/en-US/Tasks/snippets/Serialization-XML-OpenJDK_Parse-DOM.xml new file mode 100644 index 0000000..f04a2af --- /dev/null +++ b/defensive-coding/en-US/Tasks/snippets/Serialization-XML-OpenJDK_Parse-DOM.xml @@ -0,0 +1,19 @@ + + + + +DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); +// Impose restrictions on the complexity of the DTD. +factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); + +// Turn on validation. +// This step can be omitted if validation is not desired. +factory.setValidating(true); + +// Parse the document. +DocumentBuilder builder = factory.newDocumentBuilder(); +builder.setEntityResolver(new NoEntityResolver()); +builder.setErrorHandler(new Errors()); +Document document = builder.parse(inputStream); + diff --git a/defensive-coding/en-US/Tasks/snippets/Serialization-XML-OpenJDK_Parse-XMLSchema_DOM.xml b/defensive-coding/en-US/Tasks/snippets/Serialization-XML-OpenJDK_Parse-XMLSchema_DOM.xml new file mode 100644 index 0000000..b4ecf6c --- /dev/null +++ b/defensive-coding/en-US/Tasks/snippets/Serialization-XML-OpenJDK_Parse-XMLSchema_DOM.xml @@ -0,0 +1,23 @@ + + + + +SchemaFactory factory = SchemaFactory.newInstance( + XMLConstants.W3C_XML_SCHEMA_NS_URI); + +// This enables restrictions on schema complexity. +factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); + +// The following line prevents resource resolution +// by the schema itself. +factory.setResourceResolver(new NoResourceResolver()); + +Schema schema = factory.newSchema(schemaFile); + +Validator validator = schema.newValidator(); + +// This prevents external resource resolution. +validator.setResourceResolver(new NoResourceResolver()); +validator.validate(new DOMSource(document)); + diff --git a/defensive-coding/en-US/Tasks/snippets/Serialization-XML-OpenJDK_Parse-XMLSchema_SAX.xml b/defensive-coding/en-US/Tasks/snippets/Serialization-XML-OpenJDK_Parse-XMLSchema_SAX.xml new file mode 100644 index 0000000..2f6c6c9 --- /dev/null +++ b/defensive-coding/en-US/Tasks/snippets/Serialization-XML-OpenJDK_Parse-XMLSchema_SAX.xml @@ -0,0 +1,26 @@ + + + + +SchemaFactory factory = SchemaFactory.newInstance( + XMLConstants.W3C_XML_SCHEMA_NS_URI); + +// This enables restrictions on the schema and document +// complexity. +factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); + +// This prevents resource resolution by the schema itself. +// If the schema is trusted and references additional files, +// this line must be omitted, otherwise loading these files +// will fail. +factory.setResourceResolver(new NoResourceResolver()); + +Schema schema = factory.newSchema(schemaFile); +Validator validator = schema.newValidator(); + +// This prevents external resource resolution. +validator.setResourceResolver(new NoResourceResolver()); + +validator.validate(new SAXSource(new InputSource(inputStream))); + diff --git a/defensive-coding/publican.cfg b/defensive-coding/publican.cfg new file mode 100644 index 0000000..9310838 --- /dev/null +++ b/defensive-coding/publican.cfg @@ -0,0 +1,10 @@ +xml_lang: en-US +#brand: RedHat-EngServices +brand: fedora +chunk_section_depth: 3 +product: Defensive_Coding +mainfile: Defensive_Coding +docname: Defensive_Coding +web_version_label: UNUSED +version: 1 +git_branch: eng-docs-rhel-6 diff --git a/defensive-coding/schemas.xml b/defensive-coding/schemas.xml new file mode 100644 index 0000000..7d50b63 --- /dev/null +++ b/defensive-coding/schemas.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/defensive-coding/scripts/.svn/all-wcprops b/defensive-coding/scripts/.svn/all-wcprops new file mode 100644 index 0000000..a74e619 --- /dev/null +++ b/defensive-coding/scripts/.svn/all-wcprops @@ -0,0 +1,11 @@ +K 25 +svn:wc:ra_dav:version-url +V 67 +/repos/product-security/!svn/ver/288/defensive-coding/trunk/scripts +END +split-snippets.py +K 25 +svn:wc:ra_dav:version-url +V 85 +/repos/product-security/!svn/ver/288/defensive-coding/trunk/scripts/split-snippets.py +END diff --git a/defensive-coding/scripts/.svn/entries b/defensive-coding/scripts/.svn/entries new file mode 100644 index 0000000..9c80cd2 --- /dev/null +++ b/defensive-coding/scripts/.svn/entries @@ -0,0 +1,62 @@ +10 + +dir +305 +https://svn.devel.redhat.com/repos/product-security/defensive-coding/trunk/scripts +https://svn.devel.redhat.com/repos/product-security + + + +2012-12-14T09:21:42.199416Z +288 +fweimer@REDHAT.COM + + + + + + + + + + + + + + +9bd5cf0f-f2b3-0410-b1a9-d5c590f50bf1 + +split-snippets.py +file + + + + +2013-01-10T17:17:49.053814Z +a3a947246ad0000e1e2f3836674da5ce +2012-12-14T09:21:42.199416Z +288 +fweimer@REDHAT.COM + + + + + + + + + + + + + + + + + + + + + +3637 + diff --git a/defensive-coding/scripts/.svn/text-base/split-snippets.py.svn-base b/defensive-coding/scripts/.svn/text-base/split-snippets.py.svn-base new file mode 100644 index 0000000..411fbd3 --- /dev/null +++ b/defensive-coding/scripts/.svn/text-base/split-snippets.py.svn-base @@ -0,0 +1,106 @@ +#!/usr/bin/python + +# Split source code files into XML snippets for inclusion in the +# documentation. +# +# Usage: python split-snippets.py TARGET-ROOT INPUT-FILE... +# +# Directives in the input files have the form: +# +# //+ Directory File-Base-Name +# lines to be included in +# the file +# //- +# +# In this example, the lines are written to the file +# en-US/Directory/snippets/File-Base-Name.xml under the TARGET-ROOT +# directory. Whitespace shared with the starting line is stripped. +# Instead of "//", it is possible to use "#". + +import re +import sys + +target_root = sys.argv[1] + +def output_file_name(dirname, basename): + return "{0}/en-US/{1}/snippets/{2}.xml".format( + target_root, dirname, basename) + +re_open_file = re.compile( + r'^(\s*)(?://|#)\+\s+([a-zA-Z0-9_-]+)\s+([a-zA-Z0-9_-]+)\s*\n?$') +re_close_file = re.compile(r'^\s*(?://|#)\-\s*\n?$') + +def extension_to_language(path, map={ + 'c' : 'C', + 'py' : 'Python', + 'java' : 'Java', + }): + return map.get(path.split('.')[-1], 'C') + +def write_single_file(path, contents, language): + assert not [ch for ch in language if ch in "<>&\""] + with file(path, "w") as out: + out.write(''' + + + +''') + for line in contents: + for ch in line: + if ch in "<>&": + out.write("&#{0};".format(ord(ch))) + else: + out.write(ch) + out.write("\n") + +def write_output(output): + for (outpath, (origpath, contents)) in output.items(): + write_single_file(outpath, contents, + extension_to_language(origpath)) + +def process_file(path): + output = {} + with file(path) as f: + current_file = None + current_contents = None + indent = None + for line in f.readlines(): + match = re_open_file.match(line) + if match is not None: + if current_file is None: + current_file = output_file_name( + match.group(2), match.group(3)) + if current_file in output: + raise IOError("{0} written by {1} and {2}", + current_file, output[current_file][0], + path) + indent = match.group(1) + current_contents = [] + output[current_file] = (path, current_contents) + else: + raise IOError("{0}: unterminated export to {1}".format( + path, current_file)) + continue + + match = re_close_file.match(line) + if match is not None: + if current_file is None: + raise IOError("{0}: closing file which is not open") + else: + current_file = None + current_contents = None + indent = None + continue + + if current_file is not None: + if line.startswith(indent): + line = line[len(indent):] + current_contents.append(line) + if current_file is not None: + raise IOError("{0}: unterminated export to {1}".format( + path, current_file)) + write_output(output) + +for path in sys.argv[2:]: + process_file(path) diff --git a/defensive-coding/scripts/split-snippets.py b/defensive-coding/scripts/split-snippets.py new file mode 100644 index 0000000..411fbd3 --- /dev/null +++ b/defensive-coding/scripts/split-snippets.py @@ -0,0 +1,106 @@ +#!/usr/bin/python + +# Split source code files into XML snippets for inclusion in the +# documentation. +# +# Usage: python split-snippets.py TARGET-ROOT INPUT-FILE... +# +# Directives in the input files have the form: +# +# //+ Directory File-Base-Name +# lines to be included in +# the file +# //- +# +# In this example, the lines are written to the file +# en-US/Directory/snippets/File-Base-Name.xml under the TARGET-ROOT +# directory. Whitespace shared with the starting line is stripped. +# Instead of "//", it is possible to use "#". + +import re +import sys + +target_root = sys.argv[1] + +def output_file_name(dirname, basename): + return "{0}/en-US/{1}/snippets/{2}.xml".format( + target_root, dirname, basename) + +re_open_file = re.compile( + r'^(\s*)(?://|#)\+\s+([a-zA-Z0-9_-]+)\s+([a-zA-Z0-9_-]+)\s*\n?$') +re_close_file = re.compile(r'^\s*(?://|#)\-\s*\n?$') + +def extension_to_language(path, map={ + 'c' : 'C', + 'py' : 'Python', + 'java' : 'Java', + }): + return map.get(path.split('.')[-1], 'C') + +def write_single_file(path, contents, language): + assert not [ch for ch in language if ch in "<>&\""] + with file(path, "w") as out: + out.write(''' + + + +''') + for line in contents: + for ch in line: + if ch in "<>&": + out.write("&#{0};".format(ord(ch))) + else: + out.write(ch) + out.write("\n") + +def write_output(output): + for (outpath, (origpath, contents)) in output.items(): + write_single_file(outpath, contents, + extension_to_language(origpath)) + +def process_file(path): + output = {} + with file(path) as f: + current_file = None + current_contents = None + indent = None + for line in f.readlines(): + match = re_open_file.match(line) + if match is not None: + if current_file is None: + current_file = output_file_name( + match.group(2), match.group(3)) + if current_file in output: + raise IOError("{0} written by {1} and {2}", + current_file, output[current_file][0], + path) + indent = match.group(1) + current_contents = [] + output[current_file] = (path, current_contents) + else: + raise IOError("{0}: unterminated export to {1}".format( + path, current_file)) + continue + + match = re_close_file.match(line) + if match is not None: + if current_file is None: + raise IOError("{0}: closing file which is not open") + else: + current_file = None + current_contents = None + indent = None + continue + + if current_file is not None: + if line.startswith(indent): + line = line[len(indent):] + current_contents.append(line) + if current_file is not None: + raise IOError("{0}: unterminated export to {1}".format( + path, current_file)) + write_output(output) + +for path in sys.argv[2:]: + process_file(path) diff --git a/defensive-coding/src/.svn/all-wcprops b/defensive-coding/src/.svn/all-wcprops new file mode 100644 index 0000000..fec8a06 --- /dev/null +++ b/defensive-coding/src/.svn/all-wcprops @@ -0,0 +1,107 @@ +K 25 +svn:wc:ra_dav:version-url +V 63 +/repos/product-security/!svn/ver/302/defensive-coding/trunk/src +END +tcp_connect.c +K 25 +svn:wc:ra_dav:version-url +V 77 +/repos/product-security/!svn/ver/230/defensive-coding/trunk/src/tcp_connect.c +END +TLS-Client-OpenSSL.c +K 25 +svn:wc:ra_dav:version-url +V 84 +/repos/product-security/!svn/ver/276/defensive-coding/trunk/src/TLS-Client-OpenSSL.c +END +C-Arithmetic-add.c +K 25 +svn:wc:ra_dav:version-url +V 82 +/repos/product-security/!svn/ver/203/defensive-coding/trunk/src/C-Arithmetic-add.c +END +x509_check_host.c +K 25 +svn:wc:ra_dav:version-url +V 81 +/repos/product-security/!svn/ver/235/defensive-coding/trunk/src/x509_check_host.c +END +TLS-Client-Python.py +K 25 +svn:wc:ra_dav:version-url +V 84 +/repos/product-security/!svn/ver/269/defensive-coding/trunk/src/TLS-Client-Python.py +END +tcp_connect.h +K 25 +svn:wc:ra_dav:version-url +V 77 +/repos/product-security/!svn/ver/230/defensive-coding/trunk/src/tcp_connect.h +END +check-function.py +K 25 +svn:wc:ra_dav:version-url +V 81 +/repos/product-security/!svn/ver/235/defensive-coding/trunk/src/check-function.py +END +XML-Parser-Expat.c +K 25 +svn:wc:ra_dav:version-url +V 82 +/repos/product-security/!svn/ver/277/defensive-coding/trunk/src/XML-Parser-Expat.c +END +TLSClientOpenJDK.java +K 25 +svn:wc:ra_dav:version-url +V 85 +/repos/product-security/!svn/ver/302/defensive-coding/trunk/src/TLSClientOpenJDK.java +END +src.mk +K 25 +svn:wc:ra_dav:version-url +V 70 +/repos/product-security/!svn/ver/277/defensive-coding/trunk/src/src.mk +END +TLS-Client-NSS.c +K 25 +svn:wc:ra_dav:version-url +V 80 +/repos/product-security/!svn/ver/259/defensive-coding/trunk/src/TLS-Client-NSS.c +END +DERParser.java +K 25 +svn:wc:ra_dav:version-url +V 78 +/repos/product-security/!svn/ver/298/defensive-coding/trunk/src/DERParser.java +END +XMLParserOpenJDK.java +K 25 +svn:wc:ra_dav:version-url +V 85 +/repos/product-security/!svn/ver/287/defensive-coding/trunk/src/XMLParserOpenJDK.java +END +TLS-Client-GNUTLS.c +K 25 +svn:wc:ra_dav:version-url +V 83 +/repos/product-security/!svn/ver/264/defensive-coding/trunk/src/TLS-Client-GNUTLS.c +END +C-Arithmetic-mult.c +K 25 +svn:wc:ra_dav:version-url +V 83 +/repos/product-security/!svn/ver/203/defensive-coding/trunk/src/C-Arithmetic-mult.c +END +C-Pointers-remaining.c +K 25 +svn:wc:ra_dav:version-url +V 86 +/repos/product-security/!svn/ver/199/defensive-coding/trunk/src/C-Pointers-remaining.c +END +C-String-Functions.c +K 25 +svn:wc:ra_dav:version-url +V 84 +/repos/product-security/!svn/ver/266/defensive-coding/trunk/src/C-String-Functions.c +END diff --git a/defensive-coding/src/.svn/dir-prop-base b/defensive-coding/src/.svn/dir-prop-base new file mode 100644 index 0000000..9582a52 --- /dev/null +++ b/defensive-coding/src/.svn/dir-prop-base @@ -0,0 +1,11 @@ +K 10 +svn:ignore +V 96 +TLS-Client-GNUTLS +TLS-Client-NSS +TLS-Client-OpenSSL +*.class +XML-Parser-Expat +C-String-Functions + +END diff --git a/defensive-coding/src/.svn/entries b/defensive-coding/src/.svn/entries new file mode 100644 index 0000000..e31ad85 --- /dev/null +++ b/defensive-coding/src/.svn/entries @@ -0,0 +1,609 @@ +10 + +dir +305 +https://svn.devel.redhat.com/repos/product-security/defensive-coding/trunk/src +https://svn.devel.redhat.com/repos/product-security + + + +2013-01-16T14:32:22.318444Z +302 +fweimer@REDHAT.COM +has-props + + + + + + + + + + + + + +9bd5cf0f-f2b3-0410-b1a9-d5c590f50bf1 + +x509_check_host.c +file + + + + +2013-01-10T17:17:51.274827Z +cf59145b923348078c5b629bbc36a612 +2012-11-15T13:30:09.956181Z +235 +fweimer@REDHAT.COM + + + + + + + + + + + + + + + + + + + + + +10523 + +C-Arithmetic-add.c +file + + + + +2013-01-10T17:17:51.273827Z +ba6ae49b4b718e5adfa2a8d1f9cf3447 +2012-11-08T17:22:27.237361Z +203 +fweimer@REDHAT.COM + + + + + + + + + + + + + + + + + + + + + +273 + +TLS-Client-OpenSSL.c +file + + + + +2013-01-10T17:17:51.273827Z +8225e11e3ec21df2a67e39b36565a1c9 +2012-12-11T10:28:32.959649Z +276 +fweimer@REDHAT.COM + + + + + + + + + + + + + + + + + + + + + +9290 + +tcp_connect.c +file + + + + +2013-01-10T17:17:51.273827Z +b2d13024e62b0e1ba54bbd7daf9ae36d +2012-11-14T11:42:15.218138Z +230 +fweimer@REDHAT.COM + + + + + + + + + + + + + + + + + + + + + +1260 + +TLS-Client-Python.py +file + + + + +2013-01-10T17:17:51.274827Z +20864f5c6dd1badf9eeb2f5942296628 +2012-12-06T16:39:47.679456Z +269 +fweimer@REDHAT.COM + + + + + + + + + + + + + + + + + + + + + +1785 + +tcp_connect.h +file + + + + +2013-01-10T17:17:51.274827Z +12a090a3cf7b1a3bc3328907aac1c9a1 +2012-11-14T11:42:15.218138Z +230 +fweimer@REDHAT.COM + + + + + + + + + + + + + + + + + + + + + +212 + +check-function.py +file + + + + +2013-01-10T17:17:51.274827Z +c2c9d4e9c7d1c9f6e47546cf282447ba +2012-11-15T13:30:09.956181Z +235 +fweimer@REDHAT.COM + + + + + + + + + + + + + + + + + + + + + +502 + +XML-Parser-Expat.c +file + + + + +2013-01-10T17:17:51.274827Z +49a0ea5daaf9083655ad0aff29b6b75c +2012-12-11T13:38:24.215899Z +277 +fweimer@REDHAT.COM + + + + + + + + + + + + + + + + + + + + + +3193 + +TLSClientOpenJDK.java +file + + + + +2013-01-16T22:05:55.401436Z +4abb6802c85413ee92c77e48cbb9b286 +2013-01-16T14:32:22.318444Z +302 +fweimer@REDHAT.COM + + + + + + + + + + + + + + + + + + + + + +9265 + +src.mk +file + + + + +2013-01-10T17:17:51.274827Z +4906704e783cba97d0a39690cf24d67a +2012-12-11T13:38:24.215899Z +277 +fweimer@REDHAT.COM + + + + + + + + + + + + + + + + + + + + + +1783 + +TLS-Client-NSS.c +file + + + + +2013-01-10T17:17:51.274827Z +61e2a46efaa13617ee79c1959caf9e57 +2012-11-22T09:09:14.707205Z +259 +fweimer@REDHAT.COM + + + + + + + + + + + + + + + + + + + + + +8741 + +DERParser.java +file + + + + +2013-01-10T17:17:51.275827Z +31258b320a9b296256618b29be2770e4 +2012-12-20T14:35:12.581576Z +298 +fweimer@REDHAT.COM + + + + + + + + + + + + + + + + + + + + + +8895 + +XMLParserOpenJDK.java +file + + + + +2013-01-10T17:17:51.275827Z +bdaea7ab5c87509aa6fe9ecd7e9b8ee9 +2012-12-14T09:12:55.055726Z +287 +fweimer@REDHAT.COM + + + + + + + + + + + + + + + + + + + + + +11200 + +TLS-Client-GNUTLS.c +file + + + + +2013-01-10T17:17:51.275827Z +e6414ded83341422b06e84ac93cef929 +2012-11-27T10:01:21.025921Z +264 +fweimer@REDHAT.COM + + + + + + + + + + + + + + + + + + + + + +8435 + +data +dir + +C-Arithmetic-mult.c +file + + + + +2013-01-10T17:17:51.276827Z +f38568ac032b21c11f048af0b7ddbad5 +2012-11-08T17:22:27.237361Z +203 +fweimer@REDHAT.COM + + + + + + + + + + + + + + + + + + + + + +176 + +C-Pointers-remaining.c +file + + + + +2013-01-10T17:17:51.276827Z +ccd36adf2f3ecdeec33c83fa3a232156 +2012-11-08T16:59:17.247803Z +199 +fweimer@REDHAT.COM + + + + + + + + + + + + + + + + + + + + + +896 + +C-String-Functions.c +file + + + + +2013-01-10T17:17:51.276827Z +1b5f94f6d6c566d3d9ff3a4c76680636 +2012-11-27T11:25:03.476147Z +266 +fweimer@REDHAT.COM + + + + + + + + + + + + + + + + + + + + + +961 + diff --git a/defensive-coding/src/.svn/text-base/C-Arithmetic-add.c.svn-base b/defensive-coding/src/.svn/text-base/C-Arithmetic-add.c.svn-base new file mode 100644 index 0000000..3e70286 --- /dev/null +++ b/defensive-coding/src/.svn/text-base/C-Arithmetic-add.c.svn-base @@ -0,0 +1,17 @@ +//+ C Arithmetic-add +void report_overflow(void); + +int +add(int a, int b) +{ + int result = a + b; + if (a < 0 || b < 0) { + return -1; + } + // The compiler can optimize away the following if statement. + if (result < 0) { + report_overflow(); + } + return result; +} +//- diff --git a/defensive-coding/src/.svn/text-base/C-Arithmetic-mult.c.svn-base b/defensive-coding/src/.svn/text-base/C-Arithmetic-mult.c.svn-base new file mode 100644 index 0000000..82b7f40 --- /dev/null +++ b/defensive-coding/src/.svn/text-base/C-Arithmetic-mult.c.svn-base @@ -0,0 +1,12 @@ +void report_overflow(void); + +//+ C Arithmetic-mult +unsigned +mul(unsigned a, unsigned b) +{ + if (b && a > ((unsigned)-1) / b) { + report_overflow(); + } + return a * b; +} +//- diff --git a/defensive-coding/src/.svn/text-base/C-Pointers-remaining.c.svn-base b/defensive-coding/src/.svn/text-base/C-Pointers-remaining.c.svn-base new file mode 100644 index 0000000..e9f7be7 --- /dev/null +++ b/defensive-coding/src/.svn/text-base/C-Pointers-remaining.c.svn-base @@ -0,0 +1,51 @@ +#include +#include +#include +#include +#include + +//+ C Pointers-remaining +ssize_t +extract_strings(const char *in, size_t inlen, char **out, size_t outlen) +{ + const char *inp = in; + const char *inend = in + inlen; + char **outp = out; + char **outend = out + outlen; + + while (inp != inend) { + size_t len; + char *s; + if (outp == outend) { + errno = ENOSPC; + goto err; + } + len = (unsigned char)*inp; + ++inp; + if (len > (size_t)(inend - inp)) { + errno = EINVAL; + goto err; + } + s = malloc(len + 1); + if (s == NULL) { + goto err; + } + memcpy(s, inp, len); + inp += len; + s[len] = '\0'; + *outp = s; + ++outp; + } + return outp - out; +err: + { + int errno_old = errno; + while (out != outp) { + free(*out); + ++out; + } + errno = errno_old; + } + return -1; +} +//- diff --git a/defensive-coding/src/.svn/text-base/C-String-Functions.c.svn-base b/defensive-coding/src/.svn/text-base/C-String-Functions.c.svn-base new file mode 100644 index 0000000..b2139ac --- /dev/null +++ b/defensive-coding/src/.svn/text-base/C-String-Functions.c.svn-base @@ -0,0 +1,49 @@ +#include +#include +#include +#include + +static void +log_string(const char *s) +{ + puts(s); +} + +//+ C String-Functions-format +void log_format(const char *format, ...) __attribute__((format(printf, 1, 2))); + +void +log_format(const char *format, ...) +{ + char buf[1000]; + va_list ap; + va_start(ap, format); + vsnprintf(buf, sizeof(buf), format, ap); + va_end(ap); + log_string(buf); +} +//- + +int +main(void) +{ + { + int numerator = 3, denominator = 4; + //+ C String-Functions-snprintf + char fraction[30]; + snprintf(fraction, sizeof(fraction), "%d/%d", numerator, denominator); + //- + puts(fraction); + } + log_format("%s %x", "foo", 0xba4); + { + const char *const data = "this message is quite long"; + //+ C String-Functions-strncpy + char buf[10]; + strncpy(buf, data, sizeof(buf)); + buf[sizeof(buf) - 1] = '\0'; + //- + assert(strlen(buf) == 9); + assert(strncmp(buf, data, 9) == 0); + } +} diff --git a/defensive-coding/src/.svn/text-base/DERParser.java.svn-base b/defensive-coding/src/.svn/text-base/DERParser.java.svn-base new file mode 100644 index 0000000..67157db --- /dev/null +++ b/defensive-coding/src/.svn/text-base/DERParser.java.svn-base @@ -0,0 +1,274 @@ +import java.io.BufferedInputStream; +import java.io.FileInputStream; +import java.io.InputStream; +import java.nio.charset.Charset; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; + +/** + * Minimalistic DER parser suitable for extracting the commonName attribute from + * a subject distinguished name of an X.509 certificate. + * + *

+ * All elements in the DER structure can be parsed using: + * + *

+ * while (parser.isRemaining()) {
+ *     if (!parser.next()) {
+ *         handleError();
+ *         break;
+ *     }
+ *     // Examine parser.getTagClass() etc. here.
+ * }
+ * 
+ *

+ * Note that this parser only handles structures of up to 16 MB in size. + * + * @author Florian Weimer + * + */ +public final class DERParser { + private final byte[] data; + private final int end; + private int offset; + + private int tag = -1; + private int contentLength = -1; + + // Content starts at offset - contentLength. + + /** + * Creates a new parser for the specified array. + * + * @param data + * the data to parse (not copied) + * @throws NullPointerException + * the argument is null + */ + public DERParser(byte[] data) { + this(data, 0, data.length); + } + + /** + * Creates an new parser for the slice [offset, offset + length) of the byte + * array. + * + * @param data + * the array to parse from (not copied) + * @param offset + * the offset at which to start parsing + * @param length + * the number of bytes to parse + * @throws NullPointerException + * the array argument is null + * @throws ArrayIndexOutOfBoundsException + * offset or length are negative or extend past the end of the + * array + */ + public DERParser(byte[] data, int offset, int length) { + this.data = data; + this.offset = offset; + end = offset + length; + if (offset < 0 || length < 0 || offset > data.length || end < 0 + || end > data.length) + throw new ArrayIndexOutOfBoundsException(); + } + + /** + * Returns true if more data can be extracted from the input. + */ + public boolean isRemaining() { + return offset < end; + } + + /** + * Decodes the next tag/length/value element in the input data. After that, + * the parsed data can be examined using + * {@link #getTag()}, {@link #getLength()}, {@link #getString()}, and + * {@link #open()}. + * @return true if the TLV could be parsed successfully, false otherwise + */ + public boolean next() { + if (offset >= end) + throw new IllegalStateException("input exhausted"); + int identifier = data[offset]; + tag = identifier & ~0x20; // mask out P/C bit + if ((tag & 0x1f) == 31) + return false; // long form of type not supported + ++offset; + if (offset >= end) + return false; + contentLength = data[offset]; + if (contentLength < 0) { + int subLength = contentLength & 0x7f; + contentLength = 0; + switch (subLength) { + case 3: + ++offset; + if (offset >= end) + return false; + contentLength = (data[offset] & 0xFF) << 16; + //$FALL-THROUGH$ + case 2: + ++offset; + if (offset >= end) + return false; + contentLength = contentLength | ((data[offset] & 0xFF) << 8); + //$FALL-THROUGH$ + case 1: + ++offset; + if (offset >= end) + return false; + contentLength = contentLength | (data[offset] & 0xFF); + break; + case 0: + default: + // We only need to support DER values up to 16 MB. + return false; + } + } + ++offset; + if (offset + contentLength < 0 || offset + contentLength > end) + return false; + offset += contentLength; + return true; + } + + public static final int TAG_OBJECT_IDENTIFIER = 6; + public static final int TAG_UTF8_STRING = 12; + public static final int TAG_SEQUENCE = 16; + public static final int TAG_SET = 17; + public static final int TAG_PRINTABLE_STRING = 19; + public static final int TAG_TELETEX_STRING = 20; + public static final int TAG_IA5_STRING = 22; + public static final int TAG_UNIVERSAL_STRING = 28; + public static final int TAG_BMP_STRING = 30; + + /** + * Returns the tag value encountered by the most recent call to + * {@link #next()}. + * @return if the class is universal, an integer between 0 and 31, + * otherwise a positive integer less than 255 (which includes + * the class bits as well) + */ + public int getTag() { + return tag; + } + + /** + * Returns the length (in bytes) of the content encountered by the most + * recent call to {@link #next()}. + * + * @return a non-negative integer + */ + public int getLength() { + return contentLength; + } + + /** + * Returns true if the current content bytes are equal to the specified + * bytes. + * + * @param reference + * the byte array to compare the current content to + * @return true if length the byte content match + */ + public boolean isContent(byte[] reference) { + if (reference.length != contentLength) + return false; + int off = offset - contentLength; + for (int i = 0; i < reference.length; ++i) { + if (data[off + i] != reference[i]) + return false; + } + return true; + } + + /** + * Returns the current object as a string. + * + * @return a new string which contains the current content in decoded form + * @throws IllegalStateException + * the parser is not positioned at a string type + */ + public String getString() { + String charset; + switch (tag) { + case TAG_UTF8_STRING: + charset = "UTF-8"; + break; + case TAG_PRINTABLE_STRING: + case TAG_TELETEX_STRING: // ASCII super-set not supported by Java + case TAG_IA5_STRING: + charset = "ASCII"; + break; + case TAG_UNIVERSAL_STRING: + charset = "UTF-32BE"; + break; + case TAG_BMP_STRING: + charset = "UTF-16BE"; + break; + default: + throw new IllegalStateException( + "string requested for non-string type " + tag); + } + return new String(data, offset - contentLength, contentLength, + Charset.forName(charset)); + } + + /** + * Returns a DER parser for the current substructure + * + * @return a new DER parser object which shares the underlying byte array + * with this one + */ + public DERParser open() { + return new DERParser(data, offset - contentLength, contentLength); + } + + // Code below only included for exploratory purposes. + + private static final byte[] OID_COMMON_NAME = { 2 * 40 + 5, 4, 3 }; + + public static String getHostname(X509Certificate peer) { + DERParser outer = new DERParser(peer.getSubjectX500Principal() + .getEncoded()); + if (!outer.next() || outer.getTag() != DERParser.TAG_SEQUENCE) + return null; + outer = outer.open(); + String mostSpecificCN = null; + while (outer.isRemaining()) { + if (!outer.next() || outer.getTag() != DERParser.TAG_SET) + return null; + DERParser inner = outer.open(); + if (!inner.next() || inner.getTag() != DERParser.TAG_SEQUENCE) + continue; + inner = inner.open(); + if (inner.next() && inner.getTag() == TAG_OBJECT_IDENTIFIER + && inner.isContent(OID_COMMON_NAME)) { + inner.next(); // read value + try { + mostSpecificCN = inner.getString(); + } catch (IllegalArgumentException e) { + // Ignore unsupported string types. + } + } + } + return mostSpecificCN; + } + + public static void main(String[] args) throws Exception { + CertificateFactory factory = CertificateFactory.getInstance("X.509"); + for (String arg : args) { + InputStream in = new BufferedInputStream( + new FileInputStream(arg)); + try { + X509Certificate cert = + (X509Certificate) factory.generateCertificate(in); + System.out.format("%s: %s%n", arg, getHostname(cert)); + } finally { + in.close(); + } + } + } +} diff --git a/defensive-coding/src/.svn/text-base/TLS-Client-GNUTLS.c.svn-base b/defensive-coding/src/.svn/text-base/TLS-Client-GNUTLS.c.svn-base new file mode 100644 index 0000000..4ee2c82 --- /dev/null +++ b/defensive-coding/src/.svn/text-base/TLS-Client-GNUTLS.c.svn-base @@ -0,0 +1,279 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "tcp_connect.h" + +static void __attribute__((noreturn)) +usage(const char *progname) +{ + fprintf(stderr, "usage: %s HOST PORT\n", progname); + exit(2); +} + +static void +info_certificate_override(const char *reason, + const gnutls_datum_t cert, const char *host) +{ +#ifdef HAVE_GNUTLS_HASH_FAST + unsigned char digest[20]; + assert(gnutls_hash_get_len(GNUTLS_DIG_SHA1) == sizeof(digest)); + int ret = gnutls_hash_fast(GNUTLS_DIG_SHA1, + cert.data, cert.size, digest); + if (ret < 0) { + fprintf(stderr, "error: SHA1 digest failed: %s\n", gnutls_strerror(ret)); + exit(1); + } + fprintf(stderr, "info: %s override for " + "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:" + "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x%s%s%s\n", + reason, + digest[0], digest[1], digest[2], digest[3], digest[4], + digest[5], digest[6], digest[7], digest[8], digest[9], + digest[10], digest[11], digest[12], digest[13], digest[14], + digest[15], digest[16], digest[17], digest[18], digest[19], + host ? " (host name \"" : "", host ? host : "", host ? "\")" : ""); +#endif +} + +/* If certificate host name checking fails, this function is called to + implement an alternative matching, based on user overrides. */ +static int +certificate_host_name_override(const gnutls_datum_t cert, const char *host) +{ + // Just a dummy implementation. User overrides must be keyed both + // by certificate (or its hash) and host name. + if (getenv("CERT_OVERRIDE") != NULL) { + info_certificate_override("host name", cert, host); + return 1; + } + return 0; +} + +/* If certificate validity checking fails, this function provides a + second chance to accept the peer certificate. If no user overrides + are needed, this function can be removed. */ +static int +certificate_validity_override(const gnutls_datum_t cert) +{ + // Just a dummy implementation for testing. This should check a + // user-maintained certificate store containing explicitly accepted + // certificates. + if (getenv("CERT_OVERRIDE") != NULL) { + info_certificate_override("certificate validity", cert, NULL); + return 1; + } + return 0; +} + +int +main(int argc, char **argv) +{ + if (argc != 3) { + usage(argv[0]); + } + + //+ Features TLS-GNUTLS-Init + gnutls_global_init(); + //- + + //+ Features TLS-Client-GNUTLS-Credentials + // Load the trusted CA certificates. + gnutls_certificate_credentials_t cred = NULL; + int ret = gnutls_certificate_allocate_credentials (&cred); + if (ret != GNUTLS_E_SUCCESS) { + fprintf(stderr, "error: gnutls_certificate_allocate_credentials: %s\n", + gnutls_strerror(ret)); + exit(1); + } + // gnutls_certificate_set_x509_system_trust needs GNUTLS version 3.0 + // or newer, so we hard-code the path to the certificate store + // instead. + static const char ca_bundle[] = "/etc/ssl/certs/ca-bundle.crt"; + ret = gnutls_certificate_set_x509_trust_file + (cred, ca_bundle, GNUTLS_X509_FMT_PEM); + if (ret == 0) { + fprintf(stderr, "error: no certificates found in: %s\n", ca_bundle); + exit(1); + } + if (ret < 0) { + fprintf(stderr, "error: gnutls_certificate_set_x509_trust_files(%s): %s\n", + ca_bundle, gnutls_strerror(ret)); + exit(1); + } + //- + + const char *host = argv[1]; + const char *service = argv[2]; + // Perform name lookup, create the TCP client socket, and connect to + // the server. + int sockfd = tcp_connect(host, service); + if (sockfd < 0) { + perror("connect"); + exit(1); + } + + // Deactivate the Nagle algorithm. + { + const int val = 1; + int ret = setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val)); + if (ret < 0) { + perror("setsockopt(TCP_NODELAY)"); + exit(1); + } + } + + //+ Features TLS-Client-GNUTLS-Connect + // Create the session object. + gnutls_session_t session; + ret = gnutls_init(&session, GNUTLS_CLIENT); + if (ret != GNUTLS_E_SUCCESS) { + fprintf(stderr, "error: gnutls_init: %s\n", + gnutls_strerror(ret)); + exit(1); + } + + // Configure the cipher preferences. + const char *errptr = NULL; + ret = gnutls_priority_set_direct(session, "NORMAL", &errptr); + if (ret != GNUTLS_E_SUCCESS) { + fprintf(stderr, "error: gnutls_priority_set_direct: %s\n" + "error: at: \"%s\"\n", gnutls_strerror(ret), errptr); + exit(1); + } + + // Install the trusted certificates. + ret = gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, cred); + if (ret != GNUTLS_E_SUCCESS) { + fprintf(stderr, "error: gnutls_credentials_set: %s\n", + gnutls_strerror(ret)); + exit(1); + } + + // Associate the socket with the session object and set the server + // name. + gnutls_transport_set_ptr(session, (gnutls_transport_ptr_t)(uintptr_t)sockfd); + ret = gnutls_server_name_set(session, GNUTLS_NAME_DNS, + host, strlen(host)); + if (ret != GNUTLS_E_SUCCESS) { + fprintf(stderr, "error: gnutls_server_name_set: %s\n", + gnutls_strerror(ret)); + exit(1); + } + + // Establish the session. + ret = gnutls_handshake(session); + if (ret != GNUTLS_E_SUCCESS) { + fprintf(stderr, "error: gnutls_handshake: %s\n", + gnutls_strerror(ret)); + exit(1); + } + //- + + //+ Features TLS-Client-GNUTLS-Verify + // Obtain the server certificate chain. The server certificate + // itself is stored in the first element of the array. + unsigned certslen = 0; + const gnutls_datum_t *const certs = + gnutls_certificate_get_peers(session, &certslen); + if (certs == NULL || certslen == 0) { + fprintf(stderr, "error: could not obtain peer certificate\n"); + exit(1); + } + + // Validate the certificate chain. + unsigned status = (unsigned)-1; + ret = gnutls_certificate_verify_peers2(session, &status); + if (ret != GNUTLS_E_SUCCESS) { + fprintf(stderr, "error: gnutls_certificate_verify_peers2: %s\n", + gnutls_strerror(ret)); + exit(1); + } + if (status != 0 && !certificate_validity_override(certs[0])) { + gnutls_datum_t msg; +#if GNUTLS_VERSION_AT_LEAST_3_1_4 + int type = gnutls_certificate_type_get (session); + ret = gnutls_certificate_verification_status_print(status, type, &out, 0); +#else + ret = -1; +#endif + if (ret == 0) { + fprintf(stderr, "error: %s\n", msg.data); + gnutls_free(msg.data); + exit(1); + } else { + fprintf(stderr, "error: certificate validation failed with code 0x%x\n", + status); + exit(1); + } + } + //- + + //+ Features TLS-Client-GNUTLS-Match + // Match the peer certificate against the host name. + // We can only obtain a set of DER-encoded certificates from the + // session object, so we have to re-parse the peer certificate into + // a certificate object. + gnutls_x509_crt_t cert; + ret = gnutls_x509_crt_init(&cert); + if (ret != GNUTLS_E_SUCCESS) { + fprintf(stderr, "error: gnutls_x509_crt_init: %s\n", + gnutls_strerror(ret)); + exit(1); + } + // The peer certificate is the first certificate in the list. + ret = gnutls_x509_crt_import(cert, certs, GNUTLS_X509_FMT_DER); + if (ret != GNUTLS_E_SUCCESS) { + fprintf(stderr, "error: gnutls_x509_crt_import: %s\n", + gnutls_strerror(ret)); + exit(1); + } + ret = gnutls_x509_crt_check_hostname(cert, host); + if (ret == 0 && !certificate_host_name_override(certs[0], host)) { + fprintf(stderr, "error: host name does not match certificate\n"); + exit(1); + } + gnutls_x509_crt_deinit(cert); + //- + + //+ Features TLS-GNUTLS-Use + char buf[4096]; + snprintf(buf, sizeof(buf), "GET / HTTP/1.0\r\nHost: %s\r\n\r\n", host); + ret = gnutls_record_send(session, buf, strlen(buf)); + if (ret < 0) { + fprintf(stderr, "error: gnutls_record_send: %s\n", gnutls_strerror(ret)); + exit(1); + } + ret = gnutls_record_recv(session, buf, sizeof(buf)); + if (ret < 0) { + fprintf(stderr, "error: gnutls_record_recv: %s\n", gnutls_strerror(ret)); + exit(1); + } + //- + write(STDOUT_FILENO, buf, ret); + + //+ Features TLS-GNUTLS-Disconnect + // Initiate an orderly connection shutdown. + ret = gnutls_bye(session, GNUTLS_SHUT_RDWR); + if (ret < 0) { + fprintf(stderr, "error: gnutls_bye: %s\n", gnutls_strerror(ret)); + exit(1); + } + // Free the session object. + gnutls_deinit(session); + //- + + //+ Features TLS-GNUTLS-Credentials-Close + gnutls_certificate_free_credentials(cred); + //- +} diff --git a/defensive-coding/src/.svn/text-base/TLS-Client-NSS.c.svn-base b/defensive-coding/src/.svn/text-base/TLS-Client-NSS.c.svn-base new file mode 100644 index 0000000..de9e6db --- /dev/null +++ b/defensive-coding/src/.svn/text-base/TLS-Client-NSS.c.svn-base @@ -0,0 +1,297 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "tcp_connect.h" + +//+ Features TLS-NSS-Includes +// NSPR include files +#include +#include + +// NSS include files +#include +#include +#include +#include +#include + +// Private API, no other way to turn a POSIX file descriptor into an +// NSPR handle. +NSPR_API(PRFileDesc*) PR_ImportTCPSocket(int); +//- + +static void __attribute__((noreturn)) +usage(const char *progname) +{ + fprintf(stderr, "usage: %s HOST PORT\n", progname); + exit(2); +} + +SECStatus +bad_certificate(void *arg, PRFileDesc *fd) +{ + const char *host = arg; + CERTCertificate *cert = SSL_PeerCertificate(fd); + if (cert == NULL) { + return SECFailure; + } + + // Just a dummy implementation. User overrides must be keyed both + // by certificate (or its hash) and host name. + if (getenv("CERT_OVERRIDE") != NULL) { + unsigned char sha1[20]; + if (PK11_HashBuf(SEC_OID_SHA1, sha1, + cert->derCert.data, cert->derCert.len) != SECSuccess) { + fprintf(stderr, "error: could not hash certificate\n"); + return SECFailure; + } + SECItem si = {.data = sha1, .len = sizeof(sha1)}; + char *hex = CERT_Hexify(&si, 1); + if (hex == NULL) { + fprintf(stderr, "error: could not hash certificate\n"); + return SECFailure; + } + fprintf(stderr, "info: certificate override for %s (host name %s)\n", + hex, host); + PORT_Free(hex); + CERT_DestroyCertificate(cert); + return SECSuccess; + } + CERT_DestroyCertificate(cert); + return SECFailure; +} + +int +main(int argc, char **argv) +{ + if (argc != 3) { + usage(argv[0]); + } + + const char *host = argv[1]; + const char *service = argv[2]; + // Perform name lookup, create the TCP client socket, and connect to + // the server. + int sockfd = tcp_connect(host, service); + if (sockfd < 0) { + perror("connect"); + exit(1); + } + + // Deactivate the Nagle algorithm. + { + const int val = 1; + int ret = setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val)); + if (ret < 0) { + perror("setsockopt(TCP_NODELAY)"); + exit(1); + } + } + + //+ Features TLS-NSS-Init + PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); + NSSInitContext *const ctx = + NSS_InitContext("sql:/etc/pki/nssdb", "", "", "", NULL, + NSS_INIT_READONLY | NSS_INIT_PK11RELOAD); + if (ctx == NULL) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: NSPR error code %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); + } + + // Ciphers to enable. + static const PRUint16 good_ciphers[] = { + TLS_RSA_WITH_AES_128_CBC_SHA, + TLS_RSA_WITH_AES_256_CBC_SHA, + SSL_RSA_WITH_3DES_EDE_CBC_SHA, + SSL_NULL_WITH_NULL_NULL // sentinel + }; + + // Check if the current policy allows any strong ciphers. If it + // doesn't, switch to the "domestic" (unrestricted) policy. This is + // not thread-safe and has global impact. Consequently, we only do + // it if absolutely necessary. + int found_good_cipher = 0; + for (const PRUint16 *p = good_ciphers; *p != SSL_NULL_WITH_NULL_NULL; + ++p) { + PRInt32 policy; + if (SSL_CipherPolicyGet(*p, &policy) != SECSuccess) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: policy for cipher %u: error %d: %s\n", + (unsigned)*p, err, PR_ErrorToName(err)); + exit(1); + } + if (policy == SSL_ALLOWED) { + fprintf(stderr, "info: found cipher %x\n", (unsigned)*p); + found_good_cipher = 1; + break; + } + } + if (!found_good_cipher) { + if (NSS_SetDomesticPolicy() != SECSuccess) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: NSS_SetDomesticPolicy: error %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); + } + } + + // Initialize the trusted certificate store. + char module_name[] = "library=libnssckbi.so name=\"Root Certs\""; + SECMODModule *module = SECMOD_LoadUserModule(module_name, NULL, PR_FALSE); + if (module == NULL || !module->loaded) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: NSPR error code %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); + } + //- + + //+ Features TLS-Client-NSS-Connect + // Wrap the POSIX file descriptor. This is an internal NSPR + // function, but it is very unlikely to change. + PRFileDesc* nspr = PR_ImportTCPSocket(sockfd); + sockfd = -1; // Has been taken over by NSPR. + + // Add the SSL layer. + { + PRFileDesc *model = PR_NewTCPSocket(); + PRFileDesc *newfd = SSL_ImportFD(NULL, model); + if (newfd == NULL) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: NSPR error code %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); + } + model = newfd; + newfd = NULL; + if (SSL_OptionSet(model, SSL_ENABLE_SSL2, PR_FALSE) != SECSuccess) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: set SSL_ENABLE_SSL2 error %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); + } + if (SSL_OptionSet(model, SSL_V2_COMPATIBLE_HELLO, PR_FALSE) != SECSuccess) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: set SSL_V2_COMPATIBLE_HELLO error %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); + } + if (SSL_OptionSet(model, SSL_ENABLE_DEFLATE, PR_FALSE) != SECSuccess) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: set SSL_ENABLE_DEFLATE error %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); + } + + // Disable all ciphers (except RC4-based ciphers, for backwards + // compatibility). + const PRUint16 *const ciphers = SSL_GetImplementedCiphers(); + for (unsigned i = 0; i < SSL_GetNumImplementedCiphers(); i++) { + if (ciphers[i] != SSL_RSA_WITH_RC4_128_SHA + && ciphers[i] != SSL_RSA_WITH_RC4_128_MD5) { + if (SSL_CipherPrefSet(model, ciphers[i], PR_FALSE) != SECSuccess) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: disable cipher %u: error %d: %s\n", + (unsigned)ciphers[i], err, PR_ErrorToName(err)); + exit(1); + } + } + } + + // Enable the strong ciphers. + for (const PRUint16 *p = good_ciphers; *p != SSL_NULL_WITH_NULL_NULL; + ++p) { + if (SSL_CipherPrefSet(model, *p, PR_TRUE) != SECSuccess) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: enable cipher %u: error %d: %s\n", + (unsigned)*p, err, PR_ErrorToName(err)); + exit(1); + } + } + + // Allow overriding invalid certificate. + if (SSL_BadCertHook(model, bad_certificate, (char *)host) != SECSuccess) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: SSL_BadCertHook error %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); + } + + newfd = SSL_ImportFD(model, nspr); + if (newfd == NULL) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: SSL_ImportFD error %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); + } + nspr = newfd; + PR_Close(model); + } + + // Perform the handshake. + if (SSL_ResetHandshake(nspr, PR_FALSE) != SECSuccess) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: SSL_ResetHandshake error %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); + } + if (SSL_SetURL(nspr, host) != SECSuccess) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: SSL_SetURL error %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); + } + if (SSL_ForceHandshake(nspr) != SECSuccess) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: SSL_ForceHandshake error %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); + } + //- + + //+ Features TLS-NSS-Use + char buf[4096]; + snprintf(buf, sizeof(buf), "GET / HTTP/1.0\r\nHost: %s\r\n\r\n", host); + PRInt32 ret = PR_Write(nspr, buf, strlen(buf)); + if (ret < 0) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: PR_Write error %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); + } + ret = PR_Read(nspr, buf, sizeof(buf)); + if (ret < 0) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: PR_Read error %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); + } + //- + write(STDOUT_FILENO, buf, ret); + + //+ Features TLS-Client-NSS-Close + // Send close_notify alert. + if (PR_Shutdown(nspr, PR_SHUTDOWN_BOTH) != PR_SUCCESS) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: PR_Read error %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); + } + // Closes the underlying POSIX file descriptor, too. + PR_Close(nspr); + //- + + //+ Features TLS-NSS-Close + SECMOD_DestroyModule(module); + NSS_ShutdownContext(ctx); + //- + + return 0; +} diff --git a/defensive-coding/src/.svn/text-base/TLS-Client-OpenSSL.c.svn-base b/defensive-coding/src/.svn/text-base/TLS-Client-OpenSSL.c.svn-base new file mode 100644 index 0000000..b8a279a --- /dev/null +++ b/defensive-coding/src/.svn/text-base/TLS-Client-OpenSSL.c.svn-base @@ -0,0 +1,329 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "tcp_connect.h" + +int X509_check_host(X509 *, const unsigned char *chk, size_t chklen, + unsigned int flags); + +static void __attribute__((noreturn)) +usage(const char *progname) +{ + fprintf(stderr, "usage: %s HOST PORT\n", progname); + exit(2); +} + +static void +info_certificate_override(const char *reason, X509 *crt, const char *host) +{ + int derlen = i2d_X509(crt, NULL); + if (derlen < 0) { + fprintf(stderr, "error: could not DER-encode certificate\n"); + exit(1); + } + unsigned char *der = malloc(derlen); + if (der == NULL) { + perror("malloc"); + exit(1); + } + { + unsigned char *p = der; + if (i2d_X509(crt, &p) < 0) { + fprintf(stderr, "error: could not DER-encode certificate\n"); + exit(1); + } + } + unsigned char digest[20]; + SHA1(der, derlen, digest); + fprintf(stderr, "info: %s override for " + "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:" + "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x%s%s%s\n", + reason, + digest[0], digest[1], digest[2], digest[3], digest[4], + digest[5], digest[6], digest[7], digest[8], digest[9], + digest[10], digest[11], digest[12], digest[13], digest[14], + digest[15], digest[16], digest[17], digest[18], digest[19], + host ? " (host name \"" : "", host ? host : "", host ? "\")" : ""); + free(der); +} + +/* If certificate host name checking fails, this function is called to + implement an alternative matching, based on user overrides. */ +static int +certificate_host_name_override(X509 *crt, const char *host) +{ + // Just a dummy implementation. User overrides must be keyed both + // by certificate (or its hash) and host name. + if (getenv("CERT_OVERRIDE") != NULL) { + info_certificate_override("host name", crt, host); + return 1; + } + return 0; +} + +/* If certificate validity checking fails, this function provides a + second chance to accept the peer certificate. If no user overrides + are needed, this function can be removed. */ +static int +certificate_validity_override(X509 *crt) +{ + // Just a dummy implementation for testing. This should check a + // user-maintained certificate store containing explicitly accepted + // certificates. + if (getenv("CERT_OVERRIDE") != NULL) { + info_certificate_override("certificate validity", crt, NULL); + return 1; + } + return 0; +} + +static void __attribute__((noreturn)) +failure(const char *msg) +{ + fprintf(stderr, "error: %s: %s\n", msg, strerror(errno)); + exit(2); +} + +//+ Features TLS-OpenSSL-Errors +static void __attribute__((noreturn)) +ssl_print_error_and_exit(SSL *ssl, const char *op, int ret) +{ + int subcode = SSL_get_error(ssl, ret); + switch (subcode) { + case SSL_ERROR_NONE: + fprintf(stderr, "error: %s: no error to report\n", op); + break; + case SSL_ERROR_WANT_READ: + case SSL_ERROR_WANT_WRITE: + case SSL_ERROR_WANT_X509_LOOKUP: + case SSL_ERROR_WANT_CONNECT: + case SSL_ERROR_WANT_ACCEPT: + fprintf(stderr, "error: %s: invalid blocking state %d\n", op, subcode); + break; + case SSL_ERROR_SSL: + fprintf(stderr, "error: %s: TLS layer problem\n", op); + case SSL_ERROR_SYSCALL: + fprintf(stderr, "error: %s: system call failed: %s\n", op, strerror(errno)); + break; + case SSL_ERROR_ZERO_RETURN: + fprintf(stderr, "error: %s: zero return\n", op); + } + exit(1); +} +//- + +int +main(int argc, char **argv) +{ + if (argc != 3) { + usage(argv[0]); + } + + BIO *bio_err=BIO_new_fp(stderr, BIO_NOCLOSE); + if (bio_err == NULL) { + perror("BIO_ne_fp(stderr)"); + exit(1); + } + + //+ Features TLS-Client-OpenSSL-Init + // The following call prints an error message and calls exit() if + // the OpenSSL configuration file is unreadable. + OPENSSL_config(NULL); + // Provide human-readable error messages. + SSL_load_error_strings(); + // Register ciphers. + SSL_library_init(); + //- + + //+ Features TLS-Client-OpenSSL-CTX + // Configure a client connection context. Send a hendshake for the + // highest supported TLS version, and disable compression. + const SSL_METHOD *const req_method = SSLv23_client_method(); + SSL_CTX *const ctx = SSL_CTX_new(req_method); + if (ctx == NULL) { + ERR_print_errors(bio_err); + exit(1); + } + SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_COMPRESSION); + + // Adjust the ciphers list based on a whitelist. First enable all + // ciphers of at least medium strength, to get the list which is + // compiled into OpenSSL. + if (SSL_CTX_set_cipher_list(ctx, "HIGH:MEDIUM") != 1) { + ERR_print_errors(bio_err); + exit(1); + } + { + // Create a dummy SSL session to obtain the cipher list. + SSL *ssl = SSL_new(ctx); + if (ssl == NULL) { + ERR_print_errors(bio_err); + exit(1); + } + STACK_OF(SSL_CIPHER) *active_ciphers = SSL_get_ciphers(ssl); + if (active_ciphers == NULL) { + ERR_print_errors(bio_err); + exit(1); + } + // Whitelist of candidate ciphers. + static const char *const candidates[] = { + "AES128-GCM-SHA256", "AES128-SHA256", "AES256-SHA256", // strong ciphers + "AES128-SHA", "AES256-SHA", // strong ciphers, also in older versions + "RC4-SHA", "RC4-MD5", // backwards compatibility, supposed to be weak + "DES-CBC3-SHA", "DES-CBC3-MD5", // more backwards compatibility + NULL + }; + // Actually selected ciphers. + char ciphers[300]; + ciphers[0] = '\0'; + for (const char *const *c = candidates; *c; ++c) { + for (int i = 0; i < sk_SSL_CIPHER_num(active_ciphers); ++i) { + if (strcmp(SSL_CIPHER_get_name(sk_SSL_CIPHER_value(active_ciphers, i)), + *c) == 0) { + if (*ciphers) { + strcat(ciphers, ":"); + } + strcat(ciphers, *c); + break; + } + } + } + SSL_free(ssl); + // Apply final cipher list. + if (SSL_CTX_set_cipher_list(ctx, ciphers) != 1) { + ERR_print_errors(bio_err); + exit(1); + } + } + + // Load the set of trusted root certificates. + if (!SSL_CTX_set_default_verify_paths(ctx)) { + ERR_print_errors(bio_err); + exit(1); + } + //- + + const char *host = argv[1]; + const char *service = argv[2]; + // Perform name lookup, create the TCP client socket, and connect to + // the server. + int sockfd = tcp_connect(host, service); + if (sockfd < 0) { + perror("connect"); + exit(1); + } + // Deactivate the Nagle algorithm. + //+ Features TLS-Nagle + const int val = 1; + int ret = setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val)); + if (ret < 0) { + perror("setsockopt(TCP_NODELAY)"); + exit(1); + } + //- + //+ Features TLS-Client-OpenSSL-Connect + // Create the connection object. + SSL *ssl = SSL_new(ctx); + if (ssl == NULL) { + ERR_print_errors(bio_err); + exit(1); + } + SSL_set_fd(ssl, sockfd); + + // Enable the ServerNameIndication extension + if (!SSL_set_tlsext_host_name(ssl, host)) { + ERR_print_errors(bio_err); + exit(1); + } + + // Perform the TLS handshake with the server. + ret = SSL_connect(ssl); + if (ret != 1) { + // Error status can be 0 or negative. + ssl_print_error_and_exit(ssl, "SSL_connect", ret); + } + + // Obtain the server certificate. + X509 *peercert = SSL_get_peer_certificate(ssl); + if (peercert == NULL) { + fprintf(stderr, "peer certificate missing"); + exit(1); + } + + // Check the certificate verification result. Allow an explicit + // certificate validation override in case verification fails. + int verifystatus = SSL_get_verify_result(ssl); + if (verifystatus != X509_V_OK && !certificate_validity_override(peercert)) { + fprintf(stderr, "SSL_connect: verify result: %s\n", + X509_verify_cert_error_string(verifystatus)); + exit(1); + } + + // Check if the server certificate matches the host name used to + // establish the connection. + // FIXME: Currently needs OpenSSL 1.1. + if (X509_check_host(peercert, (const unsigned char *)host, strlen(host), + 0) != 1 + && !certificate_host_name_override(peercert, host)) { + fprintf(stderr, "SSL certificate does not match host name\n"); + exit(1); + } + + X509_free(peercert); + + //- + //+ Features TLS-Client-OpenSSL-Connection-Use + const char *const req = "GET / HTTP/1.0\r\n\r\n"; + if (SSL_write(ssl, req, strlen(req)) < 0) { + ssl_print_error_and_exit(ssl, "SSL_write", ret); + } + char buf[4096]; + ret = SSL_read(ssl, buf, sizeof(buf)); + if (ret < 0) { + ssl_print_error_and_exit(ssl, "SSL_read", ret); + } + //- + write(STDOUT_FILENO, buf, ret); + //+ Features TLS-OpenSSL-Connection-Close + // Send the close_notify alert. + ret = SSL_shutdown(ssl); + switch (ret) { + case 1: + // A close_notify alert has already been received. + break; + case 0: + // Wait for the close_notify alert from the peer. + ret = SSL_shutdown(ssl); + switch (ret) { + case 0: + fprintf(stderr, "info: second SSL_shutdown returned zero\n"); + break; + case 1: + break; + default: + ssl_print_error_and_exit(ssl, "SSL_shutdown 2", ret); + } + break; + default: + ssl_print_error_and_exit(ssl, "SSL_shutdown 1", ret); + } + SSL_free(ssl); + close(sockfd); + //- + //+ Features TLS-OpenSSL-Context-Close + SSL_CTX_free(ctx); + //- + BIO_free(bio_err); + return 0; +} diff --git a/defensive-coding/src/.svn/text-base/TLS-Client-Python.py.svn-base b/defensive-coding/src/.svn/text-base/TLS-Client-Python.py.svn-base new file mode 100644 index 0000000..c91f47b --- /dev/null +++ b/defensive-coding/src/.svn/text-base/TLS-Client-Python.py.svn-base @@ -0,0 +1,56 @@ +#!/usr/bin/python + +# WARNING: See the guidelines for problems with this code! + +import socket +import ssl +import sys + +_, host, port = sys.argv + +#+ Features TLS-Client-Python-check_host_name +def check_host_name(peercert, name): + """Simple certificate/host name checker. Returns True if the + certificate matches, False otherwise. Does not support + wildcards.""" + # Check that the peer has supplied a certificate. + # None/{} is not acceptable. + if not peercert: + return False + if peercert.has_key("subjectAltName"): + for typ, val in peercert["subjectAltName"]: + if typ == "DNS" and val == name: + return True + else: + # Only check the subject DN if there is no subject alternative + # name. + cn = None + for attr, val in peercert["subject"]: + # Use most-specific (last) commonName attribute. + if attr == "commonName": + cn = val + if cn is not None: + return cn == name + return False +#- + +# WARNING: See the guidelines for problems with this code! + +sock = socket.create_connection((host, port)) +#+ Features TLS-Client-Python-Connect +sock = ssl.wrap_socket(sock, + ciphers="HIGH:-aNULL:-eNULL:-PSK:RC4-SHA:RC4-MD5", + ssl_version=ssl.PROTOCOL_TLSv1, + cert_reqs=ssl.CERT_REQUIRED, + ca_certs='/etc/ssl/certs/ca-bundle.crt') +# getpeercert() triggers the handshake as a side effect. +if not check_host_name(sock.getpeercert(), host): + raise IOError("peer certificate does not match host name") +#- +#+ Features TLS-Python-Use +sock.write("GET / HTTP/1.1\r\nHost: " + host + "\r\n\r\n") +print sock.read() +#- +#+ Features TLS-Python-Close +sock.close() +#- diff --git a/defensive-coding/src/.svn/text-base/TLSClientOpenJDK.java.svn-base b/defensive-coding/src/.svn/text-base/TLSClientOpenJDK.java.svn-base new file mode 100644 index 0000000..f791857 --- /dev/null +++ b/defensive-coding/src/.svn/text-base/TLSClientOpenJDK.java.svn-base @@ -0,0 +1,262 @@ +//+ Features TLS-Client-OpenJDK-Import +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.cert.CertificateEncodingException; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLParameters; +import javax.net.ssl.SSLSocket; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; + +import sun.security.util.HostnameChecker; +//- + +import java.security.MessageDigest; +import java.util.Arrays; +import java.util.ArrayList; +import java.nio.charset.Charset; + +public class TLSClientOpenJDK { + public static void main(String[] args) throws Exception { + if (args.length == 0) { + usage(); + } + int index = 0; + byte[] certHash = null; + if (args[index].equals("--accept")) { + ++index; + if (args.length != 4) { + usage(); + } + certHash = decodeHex(args[index++]); + } else if (args.length != 2) { + usage(); + } + + String host = args[index++]; + int port; + try { + port = Integer.parseInt(args[index]); + } catch (NumberFormatException e) { + port = 0; + } + if (port <= 0 || port > 65535) { + usage(); + } + + SSLContext ctx; + if (certHash == null) { + ctx = createContext(); + } else { + ctx = createContextForCertificate(certHash); + } + + SSLParameters params = createParameters(ctx); + if (certHash == null) { + params.setEndpointIdentificationAlgorithm(null); + } + runDemo(ctx, params, host, port); + } + + private static SSLContext createContext() throws Exception { + //+ Features TLS-Client-OpenJDK-Context + // Create the context. Specify the SunJSSE provider to avoid + // picking up third-party providers. Try the TLS 1.2 provider + // first, then fall back to TLS 1.0. + SSLContext ctx; + try { + ctx = SSLContext.getInstance("TLSv1.2", "SunJSSE"); + } catch (NoSuchAlgorithmException e) { + try { + ctx = SSLContext.getInstance("TLSv1", "SunJSSE"); + } catch (NoSuchAlgorithmException e1) { + // The TLS 1.0 provider should always be available. + throw new AssertionError(e1); + } catch (NoSuchProviderException e1) { + throw new AssertionError(e1); + } + } catch (NoSuchProviderException e) { + // The SunJSSE provider should always be available. + throw new AssertionError(e); + } + ctx.init(null, null, null); + //- + return ctx; + } + + static + //+ Features TLS-Client-OpenJDK-MyTrustManager + public class MyTrustManager implements X509TrustManager { + private final byte[] certHash; + + public MyTrustManager(byte[] certHash) throws Exception { + this.certHash = certHash; + } + + @Override + public void checkClientTrusted(X509Certificate[] chain, String authType) + throws CertificateException { + throw new UnsupportedOperationException(); + } + + @Override + public void checkServerTrusted(X509Certificate[] chain, + String authType) throws CertificateException { + byte[] digest = getCertificateDigest(chain[0]); + String digestHex = formatHex(digest); + + if (Arrays.equals(digest, certHash)) { + System.err.println("info: accepting certificate: " + digestHex); + } else { + throw new CertificateException("certificate rejected: " + + digestHex); + } + } + + @Override + public X509Certificate[] getAcceptedIssuers() { + return new X509Certificate[0]; + } + } + //- + + private static SSLContext createContextForCertificate(byte[] certHash) + throws Exception { + //+ Features TLS-Client-OpenJDK-Context_For_Cert + SSLContext ctx; + try { + ctx = SSLContext.getInstance("TLSv1.2", "SunJSSE"); + } catch (NoSuchAlgorithmException e) { + try { + ctx = SSLContext.getInstance("TLSv1", "SunJSSE"); + } catch (NoSuchAlgorithmException e1) { + throw new AssertionError(e1); + } catch (NoSuchProviderException e1) { + throw new AssertionError(e1); + } + } catch (NoSuchProviderException e) { + throw new AssertionError(e); + } + MyTrustManager tm = new MyTrustManager(certHash); + ctx.init(null, new TrustManager[] {tm}, null); + //- + return ctx; + } + + private static SSLParameters createParameters(SSLContext ctx) + throws Exception { + //+ Features TLS-OpenJDK-Parameters + // Prepare TLS parameters. These have to applied to every TLS + // socket before the handshake is triggered. + SSLParameters params = ctx.getDefaultSSLParameters(); + // Do not send an SSL-2.0-compatible Client Hello. + ArrayList protocols = new ArrayList( + Arrays.asList(params.getProtocols())); + protocols.remove("SSLv2Hello"); + params.setProtocols(protocols.toArray(new String[protocols.size()])); + // Adjust the supported ciphers. + ArrayList ciphers = new ArrayList( + Arrays.asList(params.getCipherSuites())); + ciphers.retainAll(Arrays.asList( + "TLS_RSA_WITH_AES_128_CBC_SHA256", + "TLS_RSA_WITH_AES_256_CBC_SHA256", + "TLS_RSA_WITH_AES_256_CBC_SHA", + "TLS_RSA_WITH_AES_128_CBC_SHA", + "SSL_RSA_WITH_3DES_EDE_CBC_SHA", + "SSL_RSA_WITH_RC4_128_SHA1", + "SSL_RSA_WITH_RC4_128_MD5", + "TLS_EMPTY_RENEGOTIATION_INFO_SCSV")); + params.setCipherSuites(ciphers.toArray(new String[ciphers.size()])); + //- + // Activate host name verification. Requires OpenJDK 7. + //+ Features TLS-Client-OpenJDK-Hostname + params.setEndpointIdentificationAlgorithm("HTTPS"); + //- + return params; + } + + private static void runDemo(SSLContext ctx, SSLParameters params, + String host, int port) throws Exception { + // Note: The code below misses the close() call, to avoid + // messing up the indentation in the generated documentation. + + //+ Features TLS-Client-OpenJDK-Connect + // Create the socket and connect it at the TCP layer. + SSLSocket socket = (SSLSocket) ctx.getSocketFactory() + .createSocket(host, port); + + // Disable the Nagle algorithm. + socket.setTcpNoDelay(true); + + // Adjust ciphers and protocols. + socket.setSSLParameters(params); + + // Perform the handshake. + socket.startHandshake(); + + // Validate the host name. The match() method throws + // CertificateException on failure. + X509Certificate peer = (X509Certificate) + socket.getSession().getPeerCertificates()[0]; + // This is the only way to perform host name checking on OpenJDK 6. + HostnameChecker.getInstance(HostnameChecker.TYPE_TLS).match( + host, peer); + //- + + //+ Features TLS-Client-OpenJDK-Use + socket.getOutputStream().write("GET / HTTP/1.0\r\n\r\n" + .getBytes(Charset.forName("UTF-8"))); + byte[] buffer = new byte[4096]; + int count = socket.getInputStream().read(buffer); + System.out.write(buffer, 0, count); + //- + } + + private static byte[] decodeHex(String s) { + byte[] result = new byte[32]; + if (s.length() != result.length * 2) { + throw new IllegalArgumentException(s); + } + for (int i = 0; i < result.length; ++i) { + int a = Character.digit(s.charAt(2 * i), 16); + int b = Character.digit(s.charAt(2 * i + 1), 16); + if (a < 0 || b < 0) { + throw new IllegalArgumentException(s); + } + result[i] = (byte) ((a << 4) | b); + } + return result; + } + + private static String formatHex(byte[] digest) { + String digestHex; + { + StringBuilder sb = new StringBuilder(digest.length * 2); + for (byte b : digest) { + sb.append(String.format("%02x", b & 0xFF)); + } + digestHex = sb.toString(); + } + return digestHex; + } + + private static byte[] getCertificateDigest(X509Certificate chain) + throws AssertionError, CertificateEncodingException { + MessageDigest md; + try { + md = MessageDigest.getInstance("SHA-256"); + } catch (NoSuchAlgorithmException e1) { + throw new AssertionError(e1); + } + byte[] digest = md.digest(chain.getEncoded()); + return digest; + } + + private static void usage() { + System.err.format("usage: %s [--accept CERT-HASH] HOST PORT%n", + TLSClientOpenJDK.class.getName()); + System.exit(1); + } +} diff --git a/defensive-coding/src/.svn/text-base/XML-Parser-Expat.c.svn-base b/defensive-coding/src/.svn/text-base/XML-Parser-Expat.c.svn-base new file mode 100644 index 0000000..0f2c609 --- /dev/null +++ b/defensive-coding/src/.svn/text-base/XML-Parser-Expat.c.svn-base @@ -0,0 +1,135 @@ +#include +#include +#include +#include + +#include + +static void +print_escaped(const char *p, size_t len) +{ + const char *end = p + len; + while (p < end) { + unsigned char ch = *p; + // Technically, we should also match on certain UTF-8 sequences, + // but this is not implemented here. + if ((0x01 <= ch && ch <= 0x08) + || ch == 0x0B || ch == 0x0C + || (0x0E <= ch && ch <= 0x1F) + || ch == '"' || ch == '\'' || ch == '<' || ch == '>' || ch == '"' + || ch == 0x7F) { + printf("&#%d;", (int)ch); + } else { + putc(ch, stdout); + } + ++p; + } +} + +static void +StartElementHandler(void *userData, + const XML_Char *name, const XML_Char **attrs) +{ + printf("<%s", name); + while (*attrs) { + printf(" %s=\"", *attrs); + ++attrs; + print_escaped(*attrs, strlen(*attrs)); + ++attrs; + putc('"', stdout); + } + putc('>', stdout); +} + +static void +EndElementHandler(void *userData, const XML_Char *name) +{ + printf("", name); +} + +static void +CharacterDataHandler(void *userData, const XML_Char *s, int len) +{ + print_escaped(s, len); +} + +static void +CommentHandler(void *userData, const XML_Char *s) +{ + printf("", s); +} + +//+ Tasks Serialization-XML-Expat-EntityDeclHandler +// Stop the parser when an entity declaration is encountered. +static void +EntityDeclHandler(void *userData, + const XML_Char *entityName, int is_parameter_entity, + const XML_Char *value, int value_length, + const XML_Char *base, const XML_Char *systemId, + const XML_Char *publicId, const XML_Char *notationName) +{ + XML_StopParser((XML_Parser)userData, XML_FALSE); +} +//- + +int +main(int argc, char **argv) +{ + if (argc != 2) { + fprintf(stderr, "usage: %s XML-FILE\n", argv[0]); + return 2; + } + + const char *file = argv[1]; + int fd = open(file, O_RDONLY | O_CLOEXEC); + if (fd < 0) { + perror("open"); + return 1; + } + + //+ Tasks Serialization-XML-Expat-Create + XML_Parser parser = XML_ParserCreate("UTF-8"); + if (parser == NULL) { + fprintf(stderr, "XML_ParserCreate failed\n"); + close(fd); + exit(1); + } + // EntityDeclHandler needs a reference to the parser to stop + // parsing. + XML_SetUserData(parser, parser); + // Disable entity processing, to inhibit entity expansion. + XML_SetEntityDeclHandler(parser, EntityDeclHandler); + //- + + // Handlers for demonstration purposes. + XML_SetElementHandler(parser, StartElementHandler, EndElementHandler); + XML_SetCharacterDataHandler(parser, CharacterDataHandler); + XML_SetCommentHandler(parser, CommentHandler); + + + char buffer[8192]; + ssize_t ret; + do { + ret = read(fd, buffer, sizeof(buffer)); + if (ret < 0) { + perror("read"); + XML_ParserFree(parser); + close(fd); + return 1; + } + enum XML_Status status = XML_Parse(parser, buffer, ret, ret == 0); + if (status != XML_STATUS_OK) { + fprintf(stderr, "%s:%zu:%zu: error: %s\n", + file, XML_GetCurrentLineNumber(parser), + XML_GetCurrentColumnNumber(parser), + XML_ErrorString(XML_GetErrorCode(parser))); + XML_ParserFree(parser); + close(fd); + return 1; + } + } while (ret != 0); + + XML_ParserFree(parser); + close(fd); + return 0; +} diff --git a/defensive-coding/src/.svn/text-base/XMLParserOpenJDK.java.svn-base b/defensive-coding/src/.svn/text-base/XMLParserOpenJDK.java.svn-base new file mode 100644 index 0000000..be3bef3 --- /dev/null +++ b/defensive-coding/src/.svn/text-base/XMLParserOpenJDK.java.svn-base @@ -0,0 +1,286 @@ +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; + +//+ Tasks Serialization-XML-OpenJDK-Imports +import javax.xml.XMLConstants; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.sax.SAXSource; +import javax.xml.validation.Schema; +import javax.xml.validation.SchemaFactory; +import javax.xml.validation.Validator; + +import org.w3c.dom.Document; +import org.w3c.dom.ls.LSInput; +import org.w3c.dom.ls.LSResourceResolver; +import org.xml.sax.EntityResolver; +import org.xml.sax.ErrorHandler; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.SAXParseException; +import org.xml.sax.XMLReader; +//- + +public final class XMLParserOpenJDK { + public static void main(String[] args) throws Exception { + String validationType = args[0]; + File schema = new File(args[1]); + String file = args[2]; + if (validationType.equals("OpenJDK-XSD-SAX")) { + validateXSDSAX(schema, file); + } else if (validationType.equals("OpenJDK-RNG-SAX")) { + validateSAX(XMLConstants.RELAXNG_NS_URI, schema, file); + } else if (validationType.equals("OpenJDK-DTD-SAX")) { + validateSAX(XMLConstants.XML_DTD_NS_URI, schema, file); + } else if (validationType.equals("OpenJDK-XSD-DOM")) { + validateXSDDOM(schema, file); + } else if (validationType.equals("OpenJDK-RNG-DOM")) { + validateDOM(XMLConstants.W3C_XML_SCHEMA_NS_URI, + schema, file, false); + } else if (validationType.equals("OpenJDK-DTD-DOM")) { + validateDOM(XMLConstants.XML_DTD_NS_URI, schema, file, false); + } else if (validationType.equals("OpenJDK-XSD-DOM-Validate")) { + validateDOM(XMLConstants.W3C_XML_SCHEMA_NS_URI, + schema, file, true); + } else if (validationType.equals("OpenJDK-RNG-DOM-Validate")) { + validateDOM(XMLConstants.W3C_XML_SCHEMA_NS_URI, + schema, file, true); + } else if (validationType.equals("OpenJDK-DTD-DOM-Validate")) { + validateDOM(XMLConstants.XML_DTD_NS_URI, schema, file, true); + } else if (validationType.equals("OpenJDK-SAX")) { + parseSAX(file, false); + } else if (validationType.equals("OpenJDK-DOM")) { + parseDOM(file, false); + } else if (validationType.equals("OpenJDK-SAX-Validate")) { + parseSAX(file, true); + } else if (validationType.equals("OpenJDK-DOM-Validate")) { + parseDOM(file, true); + } else { + throw new Exception("invalid validator: " + validationType); + } + } + + static + //+ Tasks Serialization-XML-OpenJDK-NoResourceResolver + class NoResourceResolver implements LSResourceResolver { + @Override + public LSInput resolveResource(String type, String namespaceURI, + String publicId, String systemId, String baseURI) { + // Throwing an exception stops validation. + throw new RuntimeException(String.format( + "resolution attempt: type=%s namespace=%s " + + "publicId=%s systemId=%s baseURI=%s", + type, namespaceURI, publicId, systemId, baseURI)); + } + } + //- + + private static void validateXSDSAX( File schemaFile, String file) + throws Exception { + FileInputStream inputStream = new FileInputStream(file); + try { + //+ Tasks Serialization-XML-OpenJDK_Parse-XMLSchema_SAX + SchemaFactory factory = SchemaFactory.newInstance( + XMLConstants.W3C_XML_SCHEMA_NS_URI); + + // This enables restrictions on the schema and document + // complexity. + factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); + + // This prevents resource resolution by the schema itself. + // If the schema is trusted and references additional files, + // this line must be omitted, otherwise loading these files + // will fail. + factory.setResourceResolver(new NoResourceResolver()); + + Schema schema = factory.newSchema(schemaFile); + Validator validator = schema.newValidator(); + + // This prevents external resource resolution. + validator.setResourceResolver(new NoResourceResolver()); + + validator.validate(new SAXSource(new InputSource(inputStream))); + //- + } finally { + inputStream.close(); + } + } + + /** + * Same as {@link #validateXSDSAX(File, String)}, but the schema type URI + * is not hard-coded. + */ + private static void validateSAX(String uri, File schemaFile, String file) + throws Exception { + FileInputStream inputStream = new FileInputStream(file); + try { + SchemaFactory factory = SchemaFactory.newInstance(uri); + + // This enables restrictions on the schema and document + // complexity. + factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); + + // This prevents resource resolution by the schema itself. + // If the schema is trusted and references additional files, + // this line must be omitted, otherwise loading these files + // will fail. + factory.setResourceResolver(new NoResourceResolver()); + + Schema schema = factory.newSchema(schemaFile); + Validator validator = schema.newValidator(); + + // This prevents external resource resolution. + validator.setResourceResolver(new NoResourceResolver()); + + validator.validate(new SAXSource(new InputSource(inputStream))); + } finally { + inputStream.close(); + } + } + + private static void validateXSDDOM(File schemaFile, String file) throws Exception { + FileInputStream inputStream = new FileInputStream(file); + try { + Document document = parseDOM(file, false); + + //+ Tasks Serialization-XML-OpenJDK_Parse-XMLSchema_DOM + SchemaFactory factory = SchemaFactory.newInstance( + XMLConstants.W3C_XML_SCHEMA_NS_URI); + + // This enables restrictions on schema complexity. + factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); + + // The following line prevents resource resolution + // by the schema itself. + factory.setResourceResolver(new NoResourceResolver()); + + Schema schema = factory.newSchema(schemaFile); + + Validator validator = schema.newValidator(); + + // This prevents external resource resolution. + validator.setResourceResolver(new NoResourceResolver()); + validator.validate(new DOMSource(document)); + //- + } finally { + inputStream.close(); + } + } + + /** + * Same as {@link #validateXSDDOM(File, String)}, but does not hard-code + * the schema type URI. + */ + private static void validateDOM(String uri, File schemaFile, String file, + boolean validate) throws Exception { + FileInputStream inputStream = new FileInputStream(file); + try { + Document document = parseDOM(file, validate); + + SchemaFactory factory = SchemaFactory.newInstance(uri); + + // This enables restrictions on schema complexity. + factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); + + // The following line prevents resource resolution + // by the schema itself. + factory.setResourceResolver(new NoResourceResolver()); + + Schema schema = factory.newSchema(schemaFile); + + Validator validator = schema.newValidator(); + // This prevents external resource resolution. + validator.setResourceResolver(new NoResourceResolver()); + validator.validate(new DOMSource(document)); + } finally { + inputStream.close(); + } + } + + static + //+ Tasks Serialization-XML-OpenJDK-Errors + class Errors implements ErrorHandler { + @Override + public void warning(SAXParseException exception) { + exception.printStackTrace(); + } + + @Override + public void fatalError(SAXParseException exception) { + exception.printStackTrace(); + } + + @Override + public void error(SAXParseException exception) { + exception.printStackTrace(); + } + } + //- + + static + //+ Tasks Serialization-XML-OpenJDK-NoEntityResolver + class NoEntityResolver implements EntityResolver { + @Override + public InputSource resolveEntity(String publicId, String systemId) + throws SAXException, IOException { + // Throwing an exception stops validation. + throw new IOException(String.format( + "attempt to resolve \"%s\" \"%s\"", publicId, systemId)); + } + } + //- + + private static void parseSAX(String file, boolean validate) + throws Exception { + SAXParserFactory factory = SAXParserFactory.newInstance(); + factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); + if (validate) { + factory.setValidating(true); + } + SAXParser parser = factory.newSAXParser(); + FileInputStream in = new FileInputStream(file); + try { + XMLReader reader = parser.getXMLReader(); + reader.setEntityResolver(new NoEntityResolver()); + reader.setErrorHandler(new Errors()); + reader.parse(new InputSource(in)); + } finally { + in.close(); + } + } + + private static Document parseDOM(String file, boolean validate) + throws Exception { + FileInputStream inputStream = new FileInputStream(file); + try { + return parseDOMInternal(inputStream); + } finally { + inputStream.close(); + } + } + + private static Document parseDOMInternal(FileInputStream inputStream) + throws ParserConfigurationException, SAXException, IOException { + //+ Tasks Serialization-XML-OpenJDK_Parse-DOM + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + // Impose restrictions on the complexity of the DTD. + factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); + + // Turn on validation. + // This step can be omitted if validation is not desired. + factory.setValidating(true); + + // Parse the document. + DocumentBuilder builder = factory.newDocumentBuilder(); + builder.setEntityResolver(new NoEntityResolver()); + builder.setErrorHandler(new Errors()); + Document document = builder.parse(inputStream); + //- + return document; + } +} diff --git a/defensive-coding/src/.svn/text-base/check-function.py.svn-base b/defensive-coding/src/.svn/text-base/check-function.py.svn-base new file mode 100644 index 0000000..ee647d6 --- /dev/null +++ b/defensive-coding/src/.svn/text-base/check-function.py.svn-base @@ -0,0 +1,18 @@ +#!/usr/bin/python + +# Usage: python check-function.py DSO/FUNCTION-NAME/OUTPUT +# +# Prints OUTPUT if libDSO.so can be loaded and defines FUNCTION-NAME +# as a function, or nothing otherwise. + +import ctypes +import sys + +for (dsoname, funcname, output) in [arg.split("/", 3) + for arg in sys.argv[1:]]: + try: + dso = ctypes.CDLL("lib{0}.so".format(dsoname)) + except OSError: + continue + if getattr(dso, funcname, None) is not None: + print output diff --git a/defensive-coding/src/.svn/text-base/src.mk.svn-base b/defensive-coding/src/.svn/text-base/src.mk.svn-base new file mode 100644 index 0000000..7987680 --- /dev/null +++ b/defensive-coding/src/.svn/text-base/src.mk.svn-base @@ -0,0 +1,53 @@ +.PHONY: build-sources + +CC = gcc +CWARNFLAGS = -Wall -W -Wno-unused-parameter -Werror=implicit-function-declaration +CFLAGS = -std=gnu99 -O2 $(CWARNFLAGS) -g + +# List files which should only be compiled for syntax checking. +compile_only += C-Pointers-remaining +compile_only += C-Arithmetic-add +compile_only += C-Arithmetic-mult + +# List Java files which sould be compiled +compile_java += TLSClientOpenJDK + +# List fiels which will be compiled and linked, together with +# additional dependencies. +compile_and_link += C-String-Functions +compile_and_link += TLS-Client-OpenSSL +LIBS_TLS-Client-OpenSSL = -lssl -lcrypto +compile_and_link += TLS-Client-GNUTLS +LIBS_TLS-Client-GNUTLS = -lgnutls +compile_and_link += TLS-Client-NSS +CFLAGS_TLS-Client-NSS = -I/usr/include/nspr4 -I/usr/include/nss3 +LIBS_TLS-Client-NSS = -lnss3 -lnspr4 -lssl3 +compile_and_link += XML-Parser-Expat +LIBS_XML-Parser-Expat = -lexpat + +# Define preprocessor symbols if certain functions exist. +CHECK_FUNCTION = crypto/X509_check_host/-DHAVE_X509_CHECK_HOST \ + gnutls/gnutls_hash_fast/-DHAVE_GNUTLS_HASH_FAST +DEFINES := $(shell python src/check-function.py $(CHECK_FUNCTION)) + +CLASS_compile_java := $(patsubst %,src/%.class,$(compile_java)) +BIN_compile_and_link := $(patsubst %,src/%,$(compile_and_link)) + +build-src: $(patsubst %,src/%.o,$(compile_only)) $(CLASS_compile_java) \ + $(BIN_compile_and_link) + +clean-src: + -rm src/*.o src/*.class $(BIN_compile_and_link) + +src/%.o: src/%.c + $(CC) $(CFLAGS) $(DEFINES) $(CFLAGS_$(basename $(notdir $@))) -c $< -o $@ + +src/%.class: src/%.java + javac -source 1.6 -target 1.6 -Xlint:all $^ + +src/%: src/%.o + $(CC) $^ -o $@ $(LIBS_$(notdir $@)) + +src/TLS-Client-GNUTLS: src/tcp_connect.o +src/TLS-Client-OpenSSL: src/tcp_connect.o src/x509_check_host.o +src/TLS-Client-NSS: src/tcp_connect.o diff --git a/defensive-coding/src/.svn/text-base/tcp_connect.c.svn-base b/defensive-coding/src/.svn/text-base/tcp_connect.c.svn-base new file mode 100644 index 0000000..fe72b31 --- /dev/null +++ b/defensive-coding/src/.svn/text-base/tcp_connect.c.svn-base @@ -0,0 +1,52 @@ +#include "tcp_connect.h" + +#include +#include +#include +#include +#include +#include +#include +#include + + +int +tcp_connect(const char *host, const char *service) +{ + // A real-world implementation should connect to one IPv4 and one + // IPv address in parallel, until a responsive server is found. + const struct addrinfo hints = { + .ai_family = AF_UNSPEC, + .ai_socktype = SOCK_STREAM, + }; + struct addrinfo *result; + int ret = getaddrinfo(host, service, &hints, &result); + if (ret != 0) { + fprintf(stderr, "error: name lookup failure for %s/%s: %s\n", + host, service, gai_strerror(ret)); + exit(1); + } + if (result == NULL) { + fprintf(stderr, "error: no addresses found for %s/%s\n", host, service); + freeaddrinfo(result); + return -1; + } + for (const struct addrinfo *ai = result; ai; ai = ai->ai_next) { + ret = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); + if (ret < 0) { + continue; + } + if (connect(ret, ai->ai_addr, ai->ai_addrlen) == 0) { + break; + } + int save = errno; + close(ret); + errno = save; + ret = -1; + } + if (ret < 0) { + return -1; + } + freeaddrinfo(result); + return ret; +} diff --git a/defensive-coding/src/.svn/text-base/tcp_connect.h.svn-base b/defensive-coding/src/.svn/text-base/tcp_connect.h.svn-base new file mode 100644 index 0000000..0234999 --- /dev/null +++ b/defensive-coding/src/.svn/text-base/tcp_connect.h.svn-base @@ -0,0 +1,6 @@ +#pragma once + +/* Establishes a TCP connect to SERVICE at HOST and returns the socket + descriptor. Calls exit on error (and prints an error message). */ +int tcp_connect(const char *host, const char *service); + diff --git a/defensive-coding/src/.svn/text-base/x509_check_host.c.svn-base b/defensive-coding/src/.svn/text-base/x509_check_host.c.svn-base new file mode 100644 index 0000000..9797b56 --- /dev/null +++ b/defensive-coding/src/.svn/text-base/x509_check_host.c.svn-base @@ -0,0 +1,355 @@ +// This file is based on a (currently patched) file from OpenSSL, +// namely crypto/x509v3/v3_utl.c. It is included here for testing +// purposes only. + +/* v3_utl.c */ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project. + */ +/* ==================================================================== + * Copyright (c) 1999-2003 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 HAVE_X509_CHECK_HOST + +#include +#include +#include + +/* Always check subject name for host match even if subject alt names present */ +#define X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT 0x1 +/* Disable wild-card matching for dnsName fields and common name. */ +#define X509_CHECK_FLAG_NO_WILDCARDS 0x2 + +typedef int (*equal_fn)(const unsigned char *pattern, size_t pattern_len, + const unsigned char *subject, size_t subject_len); + +/* Compare while ASCII ignoring case. */ +static int equal_nocase(const unsigned char *pattern, size_t pattern_len, + const unsigned char *subject, size_t subject_len) + { + if (pattern_len != subject_len) + return 0; + while (pattern_len) + { + unsigned char l = *pattern; + unsigned char r = *subject; + /* The pattern must not contain NUL characters. */ + if (l == 0) + return 0; + if (l != r) + { + if ('A' <= l && l <= 'Z') + l = (l - 'A') + 'a'; + if ('A' <= r && r <= 'Z') + r = (r - 'A') + 'a'; + if (l != r) + return 0; + } + ++pattern; + ++subject; + --pattern_len; + } + return 1; + } + +/* Compare using memcmp. */ +static int equal_case(const unsigned char *pattern, size_t pattern_len, + const unsigned char *subject, size_t subject_len) +{ + /* The pattern must not contain NUL characters. */ + if (memchr(pattern, '\0', pattern_len) != NULL) + return 0; + if (pattern_len != subject_len) + return 0; + return !memcmp(pattern, subject, pattern_len); +} + +/* RFC 5280, section 7.5, requires that only the domain is compared in + a case-insensitive manner. */ +static int equal_email(const unsigned char *a, size_t a_len, + const unsigned char *b, size_t b_len) + { + if (a_len != b_len) + return 0; + size_t i = a_len; + /* We search backwards for the '@' character, so that we do + not have to deal with quoted local-parts. The domain part + is compared in a case-insensitive manner. */ + while (i > 0) + { + --i; + if (a[i] == '@' || b[i] == '@') + { + if (!equal_nocase(a + i, a_len - i, + b + i, a_len - i)) + return 0; + break; + } + } + if (i == 0) + i = a_len; + return equal_case(a, i, b, i); + } + +/* Compare the prefix and suffix with the subject, and check that the + characters in-between are valid. */ +static int wildcard_match(const unsigned char *prefix, size_t prefix_len, + const unsigned char *suffix, size_t suffix_len, + const unsigned char *subject, size_t subject_len) + { + const unsigned char *wildcard_start; + const unsigned char *wildcard_end; + const unsigned char *p; + if (subject_len < prefix_len + suffix_len) + return 0; + if (!equal_nocase(prefix, prefix_len, subject, prefix_len)) + return 0; + wildcard_start = subject + prefix_len; + wildcard_end = subject + (subject_len - suffix_len); + if (!equal_nocase(wildcard_end, suffix_len, suffix, suffix_len)) + return 0; + /* The wildcard must match at least one character. */ + if (wildcard_start == wildcard_end) + return 0; + /* Check that the part matched by the wildcard contains only + permitted characters and only matches a single label. */ + for (p = wildcard_start; p != wildcard_end; ++p) + if (!(('0' <= *p && *p <= '9') || + ('A' <= *p && *p <= 'Z') || + ('a' <= *p && *p <= 'z') || + *p == '-')) + return 0; + return 1; + } + +/* Checks if the memory region consistens of [0-9A-Za-z.-]. */ +static int valid_domain_characters(const unsigned char *p, size_t len) + { + while (len) + { + if (!(('0' <= *p && *p <= '9') || + ('A' <= *p && *p <= 'Z') || + ('a' <= *p && *p <= 'z') || + *p == '-' || *p == '.')) + return 0; + ++p; + --len; + } + return 1; + } + +/* Find the '*' in a wildcard pattern. If no such character is found + or the pattern is otherwise invalid, returns NULL. */ +static const unsigned char *wildcard_find_star(const unsigned char *pattern, + size_t pattern_len) + { + const unsigned char *star = memchr(pattern, '*', pattern_len); + size_t dot_count = 0; + const unsigned char *suffix_start; + size_t suffix_length; + if (star == NULL) + return NULL; + suffix_start = star + 1; + suffix_length = (pattern + pattern_len) - (star + 1); + if (!(valid_domain_characters(pattern, star - pattern) && + valid_domain_characters(suffix_start, suffix_length))) + return NULL; + /* Check that the suffix matches at least two labels. */ + while (suffix_length) + { + if (*suffix_start == '.') + ++dot_count; + ++suffix_start; + --suffix_length; + } + if (dot_count < 2) + return NULL; + return star; + } + +/* Compare using wildcards. */ +static int equal_wildcard(const unsigned char *pattern, size_t pattern_len, + const unsigned char *subject, size_t subject_len) + { + const unsigned char *star; + /* Do not match IDNA names. */ + if (subject_len >=4 && memcmp(subject, "xn--", 4) == 0) + star = NULL; + else + star = wildcard_find_star(pattern, pattern_len); + if (star == NULL) + return equal_nocase(pattern, pattern_len, + subject, subject_len); + return wildcard_match(pattern, star - pattern, + star + 1, (pattern + pattern_len) - star - 1, + subject, subject_len); + } + +/* Compare an ASN1_STRING to a supplied string. If they match + * return 1. If cmp_type > 0 only compare if string matches the + * type, otherwise convert it to UTF8. + */ + +static int do_check_string(ASN1_STRING *a, int cmp_type, equal_fn equal, + const unsigned char *b, size_t blen) + { + if (!a->data || !a->length) + return 0; + if (cmp_type > 0) + { + if (cmp_type != a->type) + return 0; + if (cmp_type == V_ASN1_IA5STRING) + return equal(a->data, a->length, b, blen); + if (a->length == (int)blen && !memcmp(a->data, b, blen)) + return 1; + else + return 0; + } + else + { + int astrlen, rv; + unsigned char *astr; + astrlen = ASN1_STRING_to_UTF8(&astr, a); + if (astrlen < 0) + return 0; + rv = equal(astr, astrlen, b, blen); + OPENSSL_free(astr); + return rv; + } + } + +static int do_x509_check(X509 *x, const unsigned char *chk, size_t chklen, + unsigned int flags, int check_type) + { + GENERAL_NAMES *gens = NULL; + X509_NAME *name = NULL; + int i; + int cnid; + int alt_type; + equal_fn equal; + if (check_type == GEN_EMAIL) + { + cnid = NID_pkcs9_emailAddress; + alt_type = V_ASN1_IA5STRING; + equal = equal_email; + } + else if (check_type == GEN_DNS) + { + cnid = NID_commonName; + alt_type = V_ASN1_IA5STRING; + if (flags & X509_CHECK_FLAG_NO_WILDCARDS) + equal = equal_nocase; + else + equal = equal_wildcard; + } + else + { + cnid = 0; + alt_type = V_ASN1_OCTET_STRING; + equal = equal_case; + } + + if (chklen == 0) + chklen = strlen((const char *)chk); + + gens = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL); + if (gens) + { + int rv = 0; + for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) + { + GENERAL_NAME *gen; + ASN1_STRING *cstr; + gen = sk_GENERAL_NAME_value(gens, i); + if(gen->type != check_type) + continue; + if (check_type == GEN_EMAIL) + cstr = gen->d.rfc822Name; + else if (check_type == GEN_DNS) + cstr = gen->d.dNSName; + else + cstr = gen->d.iPAddress; + if (do_check_string(cstr, alt_type, equal, chk, chklen)) + { + rv = 1; + break; + } + } + GENERAL_NAMES_free(gens); + if (rv) + return 1; + if (!(flags & X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT) || !cnid) + return 0; + } + i = -1; + name = X509_get_subject_name(x); + while((i = X509_NAME_get_index_by_NID(name, cnid, i)) >= 0) + { + X509_NAME_ENTRY *ne; + ASN1_STRING *str; + ne = X509_NAME_get_entry(name, i); + str = X509_NAME_ENTRY_get_data(ne); + if (do_check_string(str, -1, equal, chk, chklen)) + return 1; + } + return 0; + } + +int X509_check_host(X509 *x, const unsigned char *chk, size_t chklen, + unsigned int flags) + { + return do_x509_check(x, chk, chklen, flags, GEN_DNS); + } +#endif diff --git a/defensive-coding/src/C-Arithmetic-add.c b/defensive-coding/src/C-Arithmetic-add.c new file mode 100644 index 0000000..3e70286 --- /dev/null +++ b/defensive-coding/src/C-Arithmetic-add.c @@ -0,0 +1,17 @@ +//+ C Arithmetic-add +void report_overflow(void); + +int +add(int a, int b) +{ + int result = a + b; + if (a < 0 || b < 0) { + return -1; + } + // The compiler can optimize away the following if statement. + if (result < 0) { + report_overflow(); + } + return result; +} +//- diff --git a/defensive-coding/src/C-Arithmetic-mult.c b/defensive-coding/src/C-Arithmetic-mult.c new file mode 100644 index 0000000..82b7f40 --- /dev/null +++ b/defensive-coding/src/C-Arithmetic-mult.c @@ -0,0 +1,12 @@ +void report_overflow(void); + +//+ C Arithmetic-mult +unsigned +mul(unsigned a, unsigned b) +{ + if (b && a > ((unsigned)-1) / b) { + report_overflow(); + } + return a * b; +} +//- diff --git a/defensive-coding/src/C-Pointers-remaining.c b/defensive-coding/src/C-Pointers-remaining.c new file mode 100644 index 0000000..e9f7be7 --- /dev/null +++ b/defensive-coding/src/C-Pointers-remaining.c @@ -0,0 +1,51 @@ +#include +#include +#include +#include +#include + +//+ C Pointers-remaining +ssize_t +extract_strings(const char *in, size_t inlen, char **out, size_t outlen) +{ + const char *inp = in; + const char *inend = in + inlen; + char **outp = out; + char **outend = out + outlen; + + while (inp != inend) { + size_t len; + char *s; + if (outp == outend) { + errno = ENOSPC; + goto err; + } + len = (unsigned char)*inp; + ++inp; + if (len > (size_t)(inend - inp)) { + errno = EINVAL; + goto err; + } + s = malloc(len + 1); + if (s == NULL) { + goto err; + } + memcpy(s, inp, len); + inp += len; + s[len] = '\0'; + *outp = s; + ++outp; + } + return outp - out; +err: + { + int errno_old = errno; + while (out != outp) { + free(*out); + ++out; + } + errno = errno_old; + } + return -1; +} +//- diff --git a/defensive-coding/src/C-String-Functions.c b/defensive-coding/src/C-String-Functions.c new file mode 100644 index 0000000..b2139ac --- /dev/null +++ b/defensive-coding/src/C-String-Functions.c @@ -0,0 +1,49 @@ +#include +#include +#include +#include + +static void +log_string(const char *s) +{ + puts(s); +} + +//+ C String-Functions-format +void log_format(const char *format, ...) __attribute__((format(printf, 1, 2))); + +void +log_format(const char *format, ...) +{ + char buf[1000]; + va_list ap; + va_start(ap, format); + vsnprintf(buf, sizeof(buf), format, ap); + va_end(ap); + log_string(buf); +} +//- + +int +main(void) +{ + { + int numerator = 3, denominator = 4; + //+ C String-Functions-snprintf + char fraction[30]; + snprintf(fraction, sizeof(fraction), "%d/%d", numerator, denominator); + //- + puts(fraction); + } + log_format("%s %x", "foo", 0xba4); + { + const char *const data = "this message is quite long"; + //+ C String-Functions-strncpy + char buf[10]; + strncpy(buf, data, sizeof(buf)); + buf[sizeof(buf) - 1] = '\0'; + //- + assert(strlen(buf) == 9); + assert(strncmp(buf, data, 9) == 0); + } +} diff --git a/defensive-coding/src/DERParser.java b/defensive-coding/src/DERParser.java new file mode 100644 index 0000000..67157db --- /dev/null +++ b/defensive-coding/src/DERParser.java @@ -0,0 +1,274 @@ +import java.io.BufferedInputStream; +import java.io.FileInputStream; +import java.io.InputStream; +import java.nio.charset.Charset; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; + +/** + * Minimalistic DER parser suitable for extracting the commonName attribute from + * a subject distinguished name of an X.509 certificate. + * + *

+ * All elements in the DER structure can be parsed using: + * + *

+ * while (parser.isRemaining()) {
+ *     if (!parser.next()) {
+ *         handleError();
+ *         break;
+ *     }
+ *     // Examine parser.getTagClass() etc. here.
+ * }
+ * 
+ *

+ * Note that this parser only handles structures of up to 16 MB in size. + * + * @author Florian Weimer + * + */ +public final class DERParser { + private final byte[] data; + private final int end; + private int offset; + + private int tag = -1; + private int contentLength = -1; + + // Content starts at offset - contentLength. + + /** + * Creates a new parser for the specified array. + * + * @param data + * the data to parse (not copied) + * @throws NullPointerException + * the argument is null + */ + public DERParser(byte[] data) { + this(data, 0, data.length); + } + + /** + * Creates an new parser for the slice [offset, offset + length) of the byte + * array. + * + * @param data + * the array to parse from (not copied) + * @param offset + * the offset at which to start parsing + * @param length + * the number of bytes to parse + * @throws NullPointerException + * the array argument is null + * @throws ArrayIndexOutOfBoundsException + * offset or length are negative or extend past the end of the + * array + */ + public DERParser(byte[] data, int offset, int length) { + this.data = data; + this.offset = offset; + end = offset + length; + if (offset < 0 || length < 0 || offset > data.length || end < 0 + || end > data.length) + throw new ArrayIndexOutOfBoundsException(); + } + + /** + * Returns true if more data can be extracted from the input. + */ + public boolean isRemaining() { + return offset < end; + } + + /** + * Decodes the next tag/length/value element in the input data. After that, + * the parsed data can be examined using + * {@link #getTag()}, {@link #getLength()}, {@link #getString()}, and + * {@link #open()}. + * @return true if the TLV could be parsed successfully, false otherwise + */ + public boolean next() { + if (offset >= end) + throw new IllegalStateException("input exhausted"); + int identifier = data[offset]; + tag = identifier & ~0x20; // mask out P/C bit + if ((tag & 0x1f) == 31) + return false; // long form of type not supported + ++offset; + if (offset >= end) + return false; + contentLength = data[offset]; + if (contentLength < 0) { + int subLength = contentLength & 0x7f; + contentLength = 0; + switch (subLength) { + case 3: + ++offset; + if (offset >= end) + return false; + contentLength = (data[offset] & 0xFF) << 16; + //$FALL-THROUGH$ + case 2: + ++offset; + if (offset >= end) + return false; + contentLength = contentLength | ((data[offset] & 0xFF) << 8); + //$FALL-THROUGH$ + case 1: + ++offset; + if (offset >= end) + return false; + contentLength = contentLength | (data[offset] & 0xFF); + break; + case 0: + default: + // We only need to support DER values up to 16 MB. + return false; + } + } + ++offset; + if (offset + contentLength < 0 || offset + contentLength > end) + return false; + offset += contentLength; + return true; + } + + public static final int TAG_OBJECT_IDENTIFIER = 6; + public static final int TAG_UTF8_STRING = 12; + public static final int TAG_SEQUENCE = 16; + public static final int TAG_SET = 17; + public static final int TAG_PRINTABLE_STRING = 19; + public static final int TAG_TELETEX_STRING = 20; + public static final int TAG_IA5_STRING = 22; + public static final int TAG_UNIVERSAL_STRING = 28; + public static final int TAG_BMP_STRING = 30; + + /** + * Returns the tag value encountered by the most recent call to + * {@link #next()}. + * @return if the class is universal, an integer between 0 and 31, + * otherwise a positive integer less than 255 (which includes + * the class bits as well) + */ + public int getTag() { + return tag; + } + + /** + * Returns the length (in bytes) of the content encountered by the most + * recent call to {@link #next()}. + * + * @return a non-negative integer + */ + public int getLength() { + return contentLength; + } + + /** + * Returns true if the current content bytes are equal to the specified + * bytes. + * + * @param reference + * the byte array to compare the current content to + * @return true if length the byte content match + */ + public boolean isContent(byte[] reference) { + if (reference.length != contentLength) + return false; + int off = offset - contentLength; + for (int i = 0; i < reference.length; ++i) { + if (data[off + i] != reference[i]) + return false; + } + return true; + } + + /** + * Returns the current object as a string. + * + * @return a new string which contains the current content in decoded form + * @throws IllegalStateException + * the parser is not positioned at a string type + */ + public String getString() { + String charset; + switch (tag) { + case TAG_UTF8_STRING: + charset = "UTF-8"; + break; + case TAG_PRINTABLE_STRING: + case TAG_TELETEX_STRING: // ASCII super-set not supported by Java + case TAG_IA5_STRING: + charset = "ASCII"; + break; + case TAG_UNIVERSAL_STRING: + charset = "UTF-32BE"; + break; + case TAG_BMP_STRING: + charset = "UTF-16BE"; + break; + default: + throw new IllegalStateException( + "string requested for non-string type " + tag); + } + return new String(data, offset - contentLength, contentLength, + Charset.forName(charset)); + } + + /** + * Returns a DER parser for the current substructure + * + * @return a new DER parser object which shares the underlying byte array + * with this one + */ + public DERParser open() { + return new DERParser(data, offset - contentLength, contentLength); + } + + // Code below only included for exploratory purposes. + + private static final byte[] OID_COMMON_NAME = { 2 * 40 + 5, 4, 3 }; + + public static String getHostname(X509Certificate peer) { + DERParser outer = new DERParser(peer.getSubjectX500Principal() + .getEncoded()); + if (!outer.next() || outer.getTag() != DERParser.TAG_SEQUENCE) + return null; + outer = outer.open(); + String mostSpecificCN = null; + while (outer.isRemaining()) { + if (!outer.next() || outer.getTag() != DERParser.TAG_SET) + return null; + DERParser inner = outer.open(); + if (!inner.next() || inner.getTag() != DERParser.TAG_SEQUENCE) + continue; + inner = inner.open(); + if (inner.next() && inner.getTag() == TAG_OBJECT_IDENTIFIER + && inner.isContent(OID_COMMON_NAME)) { + inner.next(); // read value + try { + mostSpecificCN = inner.getString(); + } catch (IllegalArgumentException e) { + // Ignore unsupported string types. + } + } + } + return mostSpecificCN; + } + + public static void main(String[] args) throws Exception { + CertificateFactory factory = CertificateFactory.getInstance("X.509"); + for (String arg : args) { + InputStream in = new BufferedInputStream( + new FileInputStream(arg)); + try { + X509Certificate cert = + (X509Certificate) factory.generateCertificate(in); + System.out.format("%s: %s%n", arg, getHostname(cert)); + } finally { + in.close(); + } + } + } +} diff --git a/defensive-coding/src/TLS-Client-GNUTLS.c b/defensive-coding/src/TLS-Client-GNUTLS.c new file mode 100644 index 0000000..4ee2c82 --- /dev/null +++ b/defensive-coding/src/TLS-Client-GNUTLS.c @@ -0,0 +1,279 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "tcp_connect.h" + +static void __attribute__((noreturn)) +usage(const char *progname) +{ + fprintf(stderr, "usage: %s HOST PORT\n", progname); + exit(2); +} + +static void +info_certificate_override(const char *reason, + const gnutls_datum_t cert, const char *host) +{ +#ifdef HAVE_GNUTLS_HASH_FAST + unsigned char digest[20]; + assert(gnutls_hash_get_len(GNUTLS_DIG_SHA1) == sizeof(digest)); + int ret = gnutls_hash_fast(GNUTLS_DIG_SHA1, + cert.data, cert.size, digest); + if (ret < 0) { + fprintf(stderr, "error: SHA1 digest failed: %s\n", gnutls_strerror(ret)); + exit(1); + } + fprintf(stderr, "info: %s override for " + "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:" + "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x%s%s%s\n", + reason, + digest[0], digest[1], digest[2], digest[3], digest[4], + digest[5], digest[6], digest[7], digest[8], digest[9], + digest[10], digest[11], digest[12], digest[13], digest[14], + digest[15], digest[16], digest[17], digest[18], digest[19], + host ? " (host name \"" : "", host ? host : "", host ? "\")" : ""); +#endif +} + +/* If certificate host name checking fails, this function is called to + implement an alternative matching, based on user overrides. */ +static int +certificate_host_name_override(const gnutls_datum_t cert, const char *host) +{ + // Just a dummy implementation. User overrides must be keyed both + // by certificate (or its hash) and host name. + if (getenv("CERT_OVERRIDE") != NULL) { + info_certificate_override("host name", cert, host); + return 1; + } + return 0; +} + +/* If certificate validity checking fails, this function provides a + second chance to accept the peer certificate. If no user overrides + are needed, this function can be removed. */ +static int +certificate_validity_override(const gnutls_datum_t cert) +{ + // Just a dummy implementation for testing. This should check a + // user-maintained certificate store containing explicitly accepted + // certificates. + if (getenv("CERT_OVERRIDE") != NULL) { + info_certificate_override("certificate validity", cert, NULL); + return 1; + } + return 0; +} + +int +main(int argc, char **argv) +{ + if (argc != 3) { + usage(argv[0]); + } + + //+ Features TLS-GNUTLS-Init + gnutls_global_init(); + //- + + //+ Features TLS-Client-GNUTLS-Credentials + // Load the trusted CA certificates. + gnutls_certificate_credentials_t cred = NULL; + int ret = gnutls_certificate_allocate_credentials (&cred); + if (ret != GNUTLS_E_SUCCESS) { + fprintf(stderr, "error: gnutls_certificate_allocate_credentials: %s\n", + gnutls_strerror(ret)); + exit(1); + } + // gnutls_certificate_set_x509_system_trust needs GNUTLS version 3.0 + // or newer, so we hard-code the path to the certificate store + // instead. + static const char ca_bundle[] = "/etc/ssl/certs/ca-bundle.crt"; + ret = gnutls_certificate_set_x509_trust_file + (cred, ca_bundle, GNUTLS_X509_FMT_PEM); + if (ret == 0) { + fprintf(stderr, "error: no certificates found in: %s\n", ca_bundle); + exit(1); + } + if (ret < 0) { + fprintf(stderr, "error: gnutls_certificate_set_x509_trust_files(%s): %s\n", + ca_bundle, gnutls_strerror(ret)); + exit(1); + } + //- + + const char *host = argv[1]; + const char *service = argv[2]; + // Perform name lookup, create the TCP client socket, and connect to + // the server. + int sockfd = tcp_connect(host, service); + if (sockfd < 0) { + perror("connect"); + exit(1); + } + + // Deactivate the Nagle algorithm. + { + const int val = 1; + int ret = setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val)); + if (ret < 0) { + perror("setsockopt(TCP_NODELAY)"); + exit(1); + } + } + + //+ Features TLS-Client-GNUTLS-Connect + // Create the session object. + gnutls_session_t session; + ret = gnutls_init(&session, GNUTLS_CLIENT); + if (ret != GNUTLS_E_SUCCESS) { + fprintf(stderr, "error: gnutls_init: %s\n", + gnutls_strerror(ret)); + exit(1); + } + + // Configure the cipher preferences. + const char *errptr = NULL; + ret = gnutls_priority_set_direct(session, "NORMAL", &errptr); + if (ret != GNUTLS_E_SUCCESS) { + fprintf(stderr, "error: gnutls_priority_set_direct: %s\n" + "error: at: \"%s\"\n", gnutls_strerror(ret), errptr); + exit(1); + } + + // Install the trusted certificates. + ret = gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, cred); + if (ret != GNUTLS_E_SUCCESS) { + fprintf(stderr, "error: gnutls_credentials_set: %s\n", + gnutls_strerror(ret)); + exit(1); + } + + // Associate the socket with the session object and set the server + // name. + gnutls_transport_set_ptr(session, (gnutls_transport_ptr_t)(uintptr_t)sockfd); + ret = gnutls_server_name_set(session, GNUTLS_NAME_DNS, + host, strlen(host)); + if (ret != GNUTLS_E_SUCCESS) { + fprintf(stderr, "error: gnutls_server_name_set: %s\n", + gnutls_strerror(ret)); + exit(1); + } + + // Establish the session. + ret = gnutls_handshake(session); + if (ret != GNUTLS_E_SUCCESS) { + fprintf(stderr, "error: gnutls_handshake: %s\n", + gnutls_strerror(ret)); + exit(1); + } + //- + + //+ Features TLS-Client-GNUTLS-Verify + // Obtain the server certificate chain. The server certificate + // itself is stored in the first element of the array. + unsigned certslen = 0; + const gnutls_datum_t *const certs = + gnutls_certificate_get_peers(session, &certslen); + if (certs == NULL || certslen == 0) { + fprintf(stderr, "error: could not obtain peer certificate\n"); + exit(1); + } + + // Validate the certificate chain. + unsigned status = (unsigned)-1; + ret = gnutls_certificate_verify_peers2(session, &status); + if (ret != GNUTLS_E_SUCCESS) { + fprintf(stderr, "error: gnutls_certificate_verify_peers2: %s\n", + gnutls_strerror(ret)); + exit(1); + } + if (status != 0 && !certificate_validity_override(certs[0])) { + gnutls_datum_t msg; +#if GNUTLS_VERSION_AT_LEAST_3_1_4 + int type = gnutls_certificate_type_get (session); + ret = gnutls_certificate_verification_status_print(status, type, &out, 0); +#else + ret = -1; +#endif + if (ret == 0) { + fprintf(stderr, "error: %s\n", msg.data); + gnutls_free(msg.data); + exit(1); + } else { + fprintf(stderr, "error: certificate validation failed with code 0x%x\n", + status); + exit(1); + } + } + //- + + //+ Features TLS-Client-GNUTLS-Match + // Match the peer certificate against the host name. + // We can only obtain a set of DER-encoded certificates from the + // session object, so we have to re-parse the peer certificate into + // a certificate object. + gnutls_x509_crt_t cert; + ret = gnutls_x509_crt_init(&cert); + if (ret != GNUTLS_E_SUCCESS) { + fprintf(stderr, "error: gnutls_x509_crt_init: %s\n", + gnutls_strerror(ret)); + exit(1); + } + // The peer certificate is the first certificate in the list. + ret = gnutls_x509_crt_import(cert, certs, GNUTLS_X509_FMT_DER); + if (ret != GNUTLS_E_SUCCESS) { + fprintf(stderr, "error: gnutls_x509_crt_import: %s\n", + gnutls_strerror(ret)); + exit(1); + } + ret = gnutls_x509_crt_check_hostname(cert, host); + if (ret == 0 && !certificate_host_name_override(certs[0], host)) { + fprintf(stderr, "error: host name does not match certificate\n"); + exit(1); + } + gnutls_x509_crt_deinit(cert); + //- + + //+ Features TLS-GNUTLS-Use + char buf[4096]; + snprintf(buf, sizeof(buf), "GET / HTTP/1.0\r\nHost: %s\r\n\r\n", host); + ret = gnutls_record_send(session, buf, strlen(buf)); + if (ret < 0) { + fprintf(stderr, "error: gnutls_record_send: %s\n", gnutls_strerror(ret)); + exit(1); + } + ret = gnutls_record_recv(session, buf, sizeof(buf)); + if (ret < 0) { + fprintf(stderr, "error: gnutls_record_recv: %s\n", gnutls_strerror(ret)); + exit(1); + } + //- + write(STDOUT_FILENO, buf, ret); + + //+ Features TLS-GNUTLS-Disconnect + // Initiate an orderly connection shutdown. + ret = gnutls_bye(session, GNUTLS_SHUT_RDWR); + if (ret < 0) { + fprintf(stderr, "error: gnutls_bye: %s\n", gnutls_strerror(ret)); + exit(1); + } + // Free the session object. + gnutls_deinit(session); + //- + + //+ Features TLS-GNUTLS-Credentials-Close + gnutls_certificate_free_credentials(cred); + //- +} diff --git a/defensive-coding/src/TLS-Client-NSS.c b/defensive-coding/src/TLS-Client-NSS.c new file mode 100644 index 0000000..de9e6db --- /dev/null +++ b/defensive-coding/src/TLS-Client-NSS.c @@ -0,0 +1,297 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "tcp_connect.h" + +//+ Features TLS-NSS-Includes +// NSPR include files +#include +#include + +// NSS include files +#include +#include +#include +#include +#include + +// Private API, no other way to turn a POSIX file descriptor into an +// NSPR handle. +NSPR_API(PRFileDesc*) PR_ImportTCPSocket(int); +//- + +static void __attribute__((noreturn)) +usage(const char *progname) +{ + fprintf(stderr, "usage: %s HOST PORT\n", progname); + exit(2); +} + +SECStatus +bad_certificate(void *arg, PRFileDesc *fd) +{ + const char *host = arg; + CERTCertificate *cert = SSL_PeerCertificate(fd); + if (cert == NULL) { + return SECFailure; + } + + // Just a dummy implementation. User overrides must be keyed both + // by certificate (or its hash) and host name. + if (getenv("CERT_OVERRIDE") != NULL) { + unsigned char sha1[20]; + if (PK11_HashBuf(SEC_OID_SHA1, sha1, + cert->derCert.data, cert->derCert.len) != SECSuccess) { + fprintf(stderr, "error: could not hash certificate\n"); + return SECFailure; + } + SECItem si = {.data = sha1, .len = sizeof(sha1)}; + char *hex = CERT_Hexify(&si, 1); + if (hex == NULL) { + fprintf(stderr, "error: could not hash certificate\n"); + return SECFailure; + } + fprintf(stderr, "info: certificate override for %s (host name %s)\n", + hex, host); + PORT_Free(hex); + CERT_DestroyCertificate(cert); + return SECSuccess; + } + CERT_DestroyCertificate(cert); + return SECFailure; +} + +int +main(int argc, char **argv) +{ + if (argc != 3) { + usage(argv[0]); + } + + const char *host = argv[1]; + const char *service = argv[2]; + // Perform name lookup, create the TCP client socket, and connect to + // the server. + int sockfd = tcp_connect(host, service); + if (sockfd < 0) { + perror("connect"); + exit(1); + } + + // Deactivate the Nagle algorithm. + { + const int val = 1; + int ret = setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val)); + if (ret < 0) { + perror("setsockopt(TCP_NODELAY)"); + exit(1); + } + } + + //+ Features TLS-NSS-Init + PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); + NSSInitContext *const ctx = + NSS_InitContext("sql:/etc/pki/nssdb", "", "", "", NULL, + NSS_INIT_READONLY | NSS_INIT_PK11RELOAD); + if (ctx == NULL) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: NSPR error code %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); + } + + // Ciphers to enable. + static const PRUint16 good_ciphers[] = { + TLS_RSA_WITH_AES_128_CBC_SHA, + TLS_RSA_WITH_AES_256_CBC_SHA, + SSL_RSA_WITH_3DES_EDE_CBC_SHA, + SSL_NULL_WITH_NULL_NULL // sentinel + }; + + // Check if the current policy allows any strong ciphers. If it + // doesn't, switch to the "domestic" (unrestricted) policy. This is + // not thread-safe and has global impact. Consequently, we only do + // it if absolutely necessary. + int found_good_cipher = 0; + for (const PRUint16 *p = good_ciphers; *p != SSL_NULL_WITH_NULL_NULL; + ++p) { + PRInt32 policy; + if (SSL_CipherPolicyGet(*p, &policy) != SECSuccess) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: policy for cipher %u: error %d: %s\n", + (unsigned)*p, err, PR_ErrorToName(err)); + exit(1); + } + if (policy == SSL_ALLOWED) { + fprintf(stderr, "info: found cipher %x\n", (unsigned)*p); + found_good_cipher = 1; + break; + } + } + if (!found_good_cipher) { + if (NSS_SetDomesticPolicy() != SECSuccess) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: NSS_SetDomesticPolicy: error %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); + } + } + + // Initialize the trusted certificate store. + char module_name[] = "library=libnssckbi.so name=\"Root Certs\""; + SECMODModule *module = SECMOD_LoadUserModule(module_name, NULL, PR_FALSE); + if (module == NULL || !module->loaded) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: NSPR error code %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); + } + //- + + //+ Features TLS-Client-NSS-Connect + // Wrap the POSIX file descriptor. This is an internal NSPR + // function, but it is very unlikely to change. + PRFileDesc* nspr = PR_ImportTCPSocket(sockfd); + sockfd = -1; // Has been taken over by NSPR. + + // Add the SSL layer. + { + PRFileDesc *model = PR_NewTCPSocket(); + PRFileDesc *newfd = SSL_ImportFD(NULL, model); + if (newfd == NULL) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: NSPR error code %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); + } + model = newfd; + newfd = NULL; + if (SSL_OptionSet(model, SSL_ENABLE_SSL2, PR_FALSE) != SECSuccess) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: set SSL_ENABLE_SSL2 error %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); + } + if (SSL_OptionSet(model, SSL_V2_COMPATIBLE_HELLO, PR_FALSE) != SECSuccess) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: set SSL_V2_COMPATIBLE_HELLO error %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); + } + if (SSL_OptionSet(model, SSL_ENABLE_DEFLATE, PR_FALSE) != SECSuccess) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: set SSL_ENABLE_DEFLATE error %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); + } + + // Disable all ciphers (except RC4-based ciphers, for backwards + // compatibility). + const PRUint16 *const ciphers = SSL_GetImplementedCiphers(); + for (unsigned i = 0; i < SSL_GetNumImplementedCiphers(); i++) { + if (ciphers[i] != SSL_RSA_WITH_RC4_128_SHA + && ciphers[i] != SSL_RSA_WITH_RC4_128_MD5) { + if (SSL_CipherPrefSet(model, ciphers[i], PR_FALSE) != SECSuccess) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: disable cipher %u: error %d: %s\n", + (unsigned)ciphers[i], err, PR_ErrorToName(err)); + exit(1); + } + } + } + + // Enable the strong ciphers. + for (const PRUint16 *p = good_ciphers; *p != SSL_NULL_WITH_NULL_NULL; + ++p) { + if (SSL_CipherPrefSet(model, *p, PR_TRUE) != SECSuccess) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: enable cipher %u: error %d: %s\n", + (unsigned)*p, err, PR_ErrorToName(err)); + exit(1); + } + } + + // Allow overriding invalid certificate. + if (SSL_BadCertHook(model, bad_certificate, (char *)host) != SECSuccess) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: SSL_BadCertHook error %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); + } + + newfd = SSL_ImportFD(model, nspr); + if (newfd == NULL) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: SSL_ImportFD error %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); + } + nspr = newfd; + PR_Close(model); + } + + // Perform the handshake. + if (SSL_ResetHandshake(nspr, PR_FALSE) != SECSuccess) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: SSL_ResetHandshake error %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); + } + if (SSL_SetURL(nspr, host) != SECSuccess) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: SSL_SetURL error %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); + } + if (SSL_ForceHandshake(nspr) != SECSuccess) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: SSL_ForceHandshake error %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); + } + //- + + //+ Features TLS-NSS-Use + char buf[4096]; + snprintf(buf, sizeof(buf), "GET / HTTP/1.0\r\nHost: %s\r\n\r\n", host); + PRInt32 ret = PR_Write(nspr, buf, strlen(buf)); + if (ret < 0) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: PR_Write error %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); + } + ret = PR_Read(nspr, buf, sizeof(buf)); + if (ret < 0) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: PR_Read error %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); + } + //- + write(STDOUT_FILENO, buf, ret); + + //+ Features TLS-Client-NSS-Close + // Send close_notify alert. + if (PR_Shutdown(nspr, PR_SHUTDOWN_BOTH) != PR_SUCCESS) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: PR_Read error %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); + } + // Closes the underlying POSIX file descriptor, too. + PR_Close(nspr); + //- + + //+ Features TLS-NSS-Close + SECMOD_DestroyModule(module); + NSS_ShutdownContext(ctx); + //- + + return 0; +} diff --git a/defensive-coding/src/TLS-Client-OpenSSL.c b/defensive-coding/src/TLS-Client-OpenSSL.c new file mode 100644 index 0000000..b8a279a --- /dev/null +++ b/defensive-coding/src/TLS-Client-OpenSSL.c @@ -0,0 +1,329 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "tcp_connect.h" + +int X509_check_host(X509 *, const unsigned char *chk, size_t chklen, + unsigned int flags); + +static void __attribute__((noreturn)) +usage(const char *progname) +{ + fprintf(stderr, "usage: %s HOST PORT\n", progname); + exit(2); +} + +static void +info_certificate_override(const char *reason, X509 *crt, const char *host) +{ + int derlen = i2d_X509(crt, NULL); + if (derlen < 0) { + fprintf(stderr, "error: could not DER-encode certificate\n"); + exit(1); + } + unsigned char *der = malloc(derlen); + if (der == NULL) { + perror("malloc"); + exit(1); + } + { + unsigned char *p = der; + if (i2d_X509(crt, &p) < 0) { + fprintf(stderr, "error: could not DER-encode certificate\n"); + exit(1); + } + } + unsigned char digest[20]; + SHA1(der, derlen, digest); + fprintf(stderr, "info: %s override for " + "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:" + "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x%s%s%s\n", + reason, + digest[0], digest[1], digest[2], digest[3], digest[4], + digest[5], digest[6], digest[7], digest[8], digest[9], + digest[10], digest[11], digest[12], digest[13], digest[14], + digest[15], digest[16], digest[17], digest[18], digest[19], + host ? " (host name \"" : "", host ? host : "", host ? "\")" : ""); + free(der); +} + +/* If certificate host name checking fails, this function is called to + implement an alternative matching, based on user overrides. */ +static int +certificate_host_name_override(X509 *crt, const char *host) +{ + // Just a dummy implementation. User overrides must be keyed both + // by certificate (or its hash) and host name. + if (getenv("CERT_OVERRIDE") != NULL) { + info_certificate_override("host name", crt, host); + return 1; + } + return 0; +} + +/* If certificate validity checking fails, this function provides a + second chance to accept the peer certificate. If no user overrides + are needed, this function can be removed. */ +static int +certificate_validity_override(X509 *crt) +{ + // Just a dummy implementation for testing. This should check a + // user-maintained certificate store containing explicitly accepted + // certificates. + if (getenv("CERT_OVERRIDE") != NULL) { + info_certificate_override("certificate validity", crt, NULL); + return 1; + } + return 0; +} + +static void __attribute__((noreturn)) +failure(const char *msg) +{ + fprintf(stderr, "error: %s: %s\n", msg, strerror(errno)); + exit(2); +} + +//+ Features TLS-OpenSSL-Errors +static void __attribute__((noreturn)) +ssl_print_error_and_exit(SSL *ssl, const char *op, int ret) +{ + int subcode = SSL_get_error(ssl, ret); + switch (subcode) { + case SSL_ERROR_NONE: + fprintf(stderr, "error: %s: no error to report\n", op); + break; + case SSL_ERROR_WANT_READ: + case SSL_ERROR_WANT_WRITE: + case SSL_ERROR_WANT_X509_LOOKUP: + case SSL_ERROR_WANT_CONNECT: + case SSL_ERROR_WANT_ACCEPT: + fprintf(stderr, "error: %s: invalid blocking state %d\n", op, subcode); + break; + case SSL_ERROR_SSL: + fprintf(stderr, "error: %s: TLS layer problem\n", op); + case SSL_ERROR_SYSCALL: + fprintf(stderr, "error: %s: system call failed: %s\n", op, strerror(errno)); + break; + case SSL_ERROR_ZERO_RETURN: + fprintf(stderr, "error: %s: zero return\n", op); + } + exit(1); +} +//- + +int +main(int argc, char **argv) +{ + if (argc != 3) { + usage(argv[0]); + } + + BIO *bio_err=BIO_new_fp(stderr, BIO_NOCLOSE); + if (bio_err == NULL) { + perror("BIO_ne_fp(stderr)"); + exit(1); + } + + //+ Features TLS-Client-OpenSSL-Init + // The following call prints an error message and calls exit() if + // the OpenSSL configuration file is unreadable. + OPENSSL_config(NULL); + // Provide human-readable error messages. + SSL_load_error_strings(); + // Register ciphers. + SSL_library_init(); + //- + + //+ Features TLS-Client-OpenSSL-CTX + // Configure a client connection context. Send a hendshake for the + // highest supported TLS version, and disable compression. + const SSL_METHOD *const req_method = SSLv23_client_method(); + SSL_CTX *const ctx = SSL_CTX_new(req_method); + if (ctx == NULL) { + ERR_print_errors(bio_err); + exit(1); + } + SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_COMPRESSION); + + // Adjust the ciphers list based on a whitelist. First enable all + // ciphers of at least medium strength, to get the list which is + // compiled into OpenSSL. + if (SSL_CTX_set_cipher_list(ctx, "HIGH:MEDIUM") != 1) { + ERR_print_errors(bio_err); + exit(1); + } + { + // Create a dummy SSL session to obtain the cipher list. + SSL *ssl = SSL_new(ctx); + if (ssl == NULL) { + ERR_print_errors(bio_err); + exit(1); + } + STACK_OF(SSL_CIPHER) *active_ciphers = SSL_get_ciphers(ssl); + if (active_ciphers == NULL) { + ERR_print_errors(bio_err); + exit(1); + } + // Whitelist of candidate ciphers. + static const char *const candidates[] = { + "AES128-GCM-SHA256", "AES128-SHA256", "AES256-SHA256", // strong ciphers + "AES128-SHA", "AES256-SHA", // strong ciphers, also in older versions + "RC4-SHA", "RC4-MD5", // backwards compatibility, supposed to be weak + "DES-CBC3-SHA", "DES-CBC3-MD5", // more backwards compatibility + NULL + }; + // Actually selected ciphers. + char ciphers[300]; + ciphers[0] = '\0'; + for (const char *const *c = candidates; *c; ++c) { + for (int i = 0; i < sk_SSL_CIPHER_num(active_ciphers); ++i) { + if (strcmp(SSL_CIPHER_get_name(sk_SSL_CIPHER_value(active_ciphers, i)), + *c) == 0) { + if (*ciphers) { + strcat(ciphers, ":"); + } + strcat(ciphers, *c); + break; + } + } + } + SSL_free(ssl); + // Apply final cipher list. + if (SSL_CTX_set_cipher_list(ctx, ciphers) != 1) { + ERR_print_errors(bio_err); + exit(1); + } + } + + // Load the set of trusted root certificates. + if (!SSL_CTX_set_default_verify_paths(ctx)) { + ERR_print_errors(bio_err); + exit(1); + } + //- + + const char *host = argv[1]; + const char *service = argv[2]; + // Perform name lookup, create the TCP client socket, and connect to + // the server. + int sockfd = tcp_connect(host, service); + if (sockfd < 0) { + perror("connect"); + exit(1); + } + // Deactivate the Nagle algorithm. + //+ Features TLS-Nagle + const int val = 1; + int ret = setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val)); + if (ret < 0) { + perror("setsockopt(TCP_NODELAY)"); + exit(1); + } + //- + //+ Features TLS-Client-OpenSSL-Connect + // Create the connection object. + SSL *ssl = SSL_new(ctx); + if (ssl == NULL) { + ERR_print_errors(bio_err); + exit(1); + } + SSL_set_fd(ssl, sockfd); + + // Enable the ServerNameIndication extension + if (!SSL_set_tlsext_host_name(ssl, host)) { + ERR_print_errors(bio_err); + exit(1); + } + + // Perform the TLS handshake with the server. + ret = SSL_connect(ssl); + if (ret != 1) { + // Error status can be 0 or negative. + ssl_print_error_and_exit(ssl, "SSL_connect", ret); + } + + // Obtain the server certificate. + X509 *peercert = SSL_get_peer_certificate(ssl); + if (peercert == NULL) { + fprintf(stderr, "peer certificate missing"); + exit(1); + } + + // Check the certificate verification result. Allow an explicit + // certificate validation override in case verification fails. + int verifystatus = SSL_get_verify_result(ssl); + if (verifystatus != X509_V_OK && !certificate_validity_override(peercert)) { + fprintf(stderr, "SSL_connect: verify result: %s\n", + X509_verify_cert_error_string(verifystatus)); + exit(1); + } + + // Check if the server certificate matches the host name used to + // establish the connection. + // FIXME: Currently needs OpenSSL 1.1. + if (X509_check_host(peercert, (const unsigned char *)host, strlen(host), + 0) != 1 + && !certificate_host_name_override(peercert, host)) { + fprintf(stderr, "SSL certificate does not match host name\n"); + exit(1); + } + + X509_free(peercert); + + //- + //+ Features TLS-Client-OpenSSL-Connection-Use + const char *const req = "GET / HTTP/1.0\r\n\r\n"; + if (SSL_write(ssl, req, strlen(req)) < 0) { + ssl_print_error_and_exit(ssl, "SSL_write", ret); + } + char buf[4096]; + ret = SSL_read(ssl, buf, sizeof(buf)); + if (ret < 0) { + ssl_print_error_and_exit(ssl, "SSL_read", ret); + } + //- + write(STDOUT_FILENO, buf, ret); + //+ Features TLS-OpenSSL-Connection-Close + // Send the close_notify alert. + ret = SSL_shutdown(ssl); + switch (ret) { + case 1: + // A close_notify alert has already been received. + break; + case 0: + // Wait for the close_notify alert from the peer. + ret = SSL_shutdown(ssl); + switch (ret) { + case 0: + fprintf(stderr, "info: second SSL_shutdown returned zero\n"); + break; + case 1: + break; + default: + ssl_print_error_and_exit(ssl, "SSL_shutdown 2", ret); + } + break; + default: + ssl_print_error_and_exit(ssl, "SSL_shutdown 1", ret); + } + SSL_free(ssl); + close(sockfd); + //- + //+ Features TLS-OpenSSL-Context-Close + SSL_CTX_free(ctx); + //- + BIO_free(bio_err); + return 0; +} diff --git a/defensive-coding/src/TLS-Client-Python.py b/defensive-coding/src/TLS-Client-Python.py new file mode 100644 index 0000000..c91f47b --- /dev/null +++ b/defensive-coding/src/TLS-Client-Python.py @@ -0,0 +1,56 @@ +#!/usr/bin/python + +# WARNING: See the guidelines for problems with this code! + +import socket +import ssl +import sys + +_, host, port = sys.argv + +#+ Features TLS-Client-Python-check_host_name +def check_host_name(peercert, name): + """Simple certificate/host name checker. Returns True if the + certificate matches, False otherwise. Does not support + wildcards.""" + # Check that the peer has supplied a certificate. + # None/{} is not acceptable. + if not peercert: + return False + if peercert.has_key("subjectAltName"): + for typ, val in peercert["subjectAltName"]: + if typ == "DNS" and val == name: + return True + else: + # Only check the subject DN if there is no subject alternative + # name. + cn = None + for attr, val in peercert["subject"]: + # Use most-specific (last) commonName attribute. + if attr == "commonName": + cn = val + if cn is not None: + return cn == name + return False +#- + +# WARNING: See the guidelines for problems with this code! + +sock = socket.create_connection((host, port)) +#+ Features TLS-Client-Python-Connect +sock = ssl.wrap_socket(sock, + ciphers="HIGH:-aNULL:-eNULL:-PSK:RC4-SHA:RC4-MD5", + ssl_version=ssl.PROTOCOL_TLSv1, + cert_reqs=ssl.CERT_REQUIRED, + ca_certs='/etc/ssl/certs/ca-bundle.crt') +# getpeercert() triggers the handshake as a side effect. +if not check_host_name(sock.getpeercert(), host): + raise IOError("peer certificate does not match host name") +#- +#+ Features TLS-Python-Use +sock.write("GET / HTTP/1.1\r\nHost: " + host + "\r\n\r\n") +print sock.read() +#- +#+ Features TLS-Python-Close +sock.close() +#- diff --git a/defensive-coding/src/TLSClientOpenJDK.java b/defensive-coding/src/TLSClientOpenJDK.java new file mode 100644 index 0000000..f791857 --- /dev/null +++ b/defensive-coding/src/TLSClientOpenJDK.java @@ -0,0 +1,262 @@ +//+ Features TLS-Client-OpenJDK-Import +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.cert.CertificateEncodingException; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLParameters; +import javax.net.ssl.SSLSocket; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; + +import sun.security.util.HostnameChecker; +//- + +import java.security.MessageDigest; +import java.util.Arrays; +import java.util.ArrayList; +import java.nio.charset.Charset; + +public class TLSClientOpenJDK { + public static void main(String[] args) throws Exception { + if (args.length == 0) { + usage(); + } + int index = 0; + byte[] certHash = null; + if (args[index].equals("--accept")) { + ++index; + if (args.length != 4) { + usage(); + } + certHash = decodeHex(args[index++]); + } else if (args.length != 2) { + usage(); + } + + String host = args[index++]; + int port; + try { + port = Integer.parseInt(args[index]); + } catch (NumberFormatException e) { + port = 0; + } + if (port <= 0 || port > 65535) { + usage(); + } + + SSLContext ctx; + if (certHash == null) { + ctx = createContext(); + } else { + ctx = createContextForCertificate(certHash); + } + + SSLParameters params = createParameters(ctx); + if (certHash == null) { + params.setEndpointIdentificationAlgorithm(null); + } + runDemo(ctx, params, host, port); + } + + private static SSLContext createContext() throws Exception { + //+ Features TLS-Client-OpenJDK-Context + // Create the context. Specify the SunJSSE provider to avoid + // picking up third-party providers. Try the TLS 1.2 provider + // first, then fall back to TLS 1.0. + SSLContext ctx; + try { + ctx = SSLContext.getInstance("TLSv1.2", "SunJSSE"); + } catch (NoSuchAlgorithmException e) { + try { + ctx = SSLContext.getInstance("TLSv1", "SunJSSE"); + } catch (NoSuchAlgorithmException e1) { + // The TLS 1.0 provider should always be available. + throw new AssertionError(e1); + } catch (NoSuchProviderException e1) { + throw new AssertionError(e1); + } + } catch (NoSuchProviderException e) { + // The SunJSSE provider should always be available. + throw new AssertionError(e); + } + ctx.init(null, null, null); + //- + return ctx; + } + + static + //+ Features TLS-Client-OpenJDK-MyTrustManager + public class MyTrustManager implements X509TrustManager { + private final byte[] certHash; + + public MyTrustManager(byte[] certHash) throws Exception { + this.certHash = certHash; + } + + @Override + public void checkClientTrusted(X509Certificate[] chain, String authType) + throws CertificateException { + throw new UnsupportedOperationException(); + } + + @Override + public void checkServerTrusted(X509Certificate[] chain, + String authType) throws CertificateException { + byte[] digest = getCertificateDigest(chain[0]); + String digestHex = formatHex(digest); + + if (Arrays.equals(digest, certHash)) { + System.err.println("info: accepting certificate: " + digestHex); + } else { + throw new CertificateException("certificate rejected: " + + digestHex); + } + } + + @Override + public X509Certificate[] getAcceptedIssuers() { + return new X509Certificate[0]; + } + } + //- + + private static SSLContext createContextForCertificate(byte[] certHash) + throws Exception { + //+ Features TLS-Client-OpenJDK-Context_For_Cert + SSLContext ctx; + try { + ctx = SSLContext.getInstance("TLSv1.2", "SunJSSE"); + } catch (NoSuchAlgorithmException e) { + try { + ctx = SSLContext.getInstance("TLSv1", "SunJSSE"); + } catch (NoSuchAlgorithmException e1) { + throw new AssertionError(e1); + } catch (NoSuchProviderException e1) { + throw new AssertionError(e1); + } + } catch (NoSuchProviderException e) { + throw new AssertionError(e); + } + MyTrustManager tm = new MyTrustManager(certHash); + ctx.init(null, new TrustManager[] {tm}, null); + //- + return ctx; + } + + private static SSLParameters createParameters(SSLContext ctx) + throws Exception { + //+ Features TLS-OpenJDK-Parameters + // Prepare TLS parameters. These have to applied to every TLS + // socket before the handshake is triggered. + SSLParameters params = ctx.getDefaultSSLParameters(); + // Do not send an SSL-2.0-compatible Client Hello. + ArrayList protocols = new ArrayList( + Arrays.asList(params.getProtocols())); + protocols.remove("SSLv2Hello"); + params.setProtocols(protocols.toArray(new String[protocols.size()])); + // Adjust the supported ciphers. + ArrayList ciphers = new ArrayList( + Arrays.asList(params.getCipherSuites())); + ciphers.retainAll(Arrays.asList( + "TLS_RSA_WITH_AES_128_CBC_SHA256", + "TLS_RSA_WITH_AES_256_CBC_SHA256", + "TLS_RSA_WITH_AES_256_CBC_SHA", + "TLS_RSA_WITH_AES_128_CBC_SHA", + "SSL_RSA_WITH_3DES_EDE_CBC_SHA", + "SSL_RSA_WITH_RC4_128_SHA1", + "SSL_RSA_WITH_RC4_128_MD5", + "TLS_EMPTY_RENEGOTIATION_INFO_SCSV")); + params.setCipherSuites(ciphers.toArray(new String[ciphers.size()])); + //- + // Activate host name verification. Requires OpenJDK 7. + //+ Features TLS-Client-OpenJDK-Hostname + params.setEndpointIdentificationAlgorithm("HTTPS"); + //- + return params; + } + + private static void runDemo(SSLContext ctx, SSLParameters params, + String host, int port) throws Exception { + // Note: The code below misses the close() call, to avoid + // messing up the indentation in the generated documentation. + + //+ Features TLS-Client-OpenJDK-Connect + // Create the socket and connect it at the TCP layer. + SSLSocket socket = (SSLSocket) ctx.getSocketFactory() + .createSocket(host, port); + + // Disable the Nagle algorithm. + socket.setTcpNoDelay(true); + + // Adjust ciphers and protocols. + socket.setSSLParameters(params); + + // Perform the handshake. + socket.startHandshake(); + + // Validate the host name. The match() method throws + // CertificateException on failure. + X509Certificate peer = (X509Certificate) + socket.getSession().getPeerCertificates()[0]; + // This is the only way to perform host name checking on OpenJDK 6. + HostnameChecker.getInstance(HostnameChecker.TYPE_TLS).match( + host, peer); + //- + + //+ Features TLS-Client-OpenJDK-Use + socket.getOutputStream().write("GET / HTTP/1.0\r\n\r\n" + .getBytes(Charset.forName("UTF-8"))); + byte[] buffer = new byte[4096]; + int count = socket.getInputStream().read(buffer); + System.out.write(buffer, 0, count); + //- + } + + private static byte[] decodeHex(String s) { + byte[] result = new byte[32]; + if (s.length() != result.length * 2) { + throw new IllegalArgumentException(s); + } + for (int i = 0; i < result.length; ++i) { + int a = Character.digit(s.charAt(2 * i), 16); + int b = Character.digit(s.charAt(2 * i + 1), 16); + if (a < 0 || b < 0) { + throw new IllegalArgumentException(s); + } + result[i] = (byte) ((a << 4) | b); + } + return result; + } + + private static String formatHex(byte[] digest) { + String digestHex; + { + StringBuilder sb = new StringBuilder(digest.length * 2); + for (byte b : digest) { + sb.append(String.format("%02x", b & 0xFF)); + } + digestHex = sb.toString(); + } + return digestHex; + } + + private static byte[] getCertificateDigest(X509Certificate chain) + throws AssertionError, CertificateEncodingException { + MessageDigest md; + try { + md = MessageDigest.getInstance("SHA-256"); + } catch (NoSuchAlgorithmException e1) { + throw new AssertionError(e1); + } + byte[] digest = md.digest(chain.getEncoded()); + return digest; + } + + private static void usage() { + System.err.format("usage: %s [--accept CERT-HASH] HOST PORT%n", + TLSClientOpenJDK.class.getName()); + System.exit(1); + } +} diff --git a/defensive-coding/src/XML-Parser-Expat.c b/defensive-coding/src/XML-Parser-Expat.c new file mode 100644 index 0000000..0f2c609 --- /dev/null +++ b/defensive-coding/src/XML-Parser-Expat.c @@ -0,0 +1,135 @@ +#include +#include +#include +#include + +#include + +static void +print_escaped(const char *p, size_t len) +{ + const char *end = p + len; + while (p < end) { + unsigned char ch = *p; + // Technically, we should also match on certain UTF-8 sequences, + // but this is not implemented here. + if ((0x01 <= ch && ch <= 0x08) + || ch == 0x0B || ch == 0x0C + || (0x0E <= ch && ch <= 0x1F) + || ch == '"' || ch == '\'' || ch == '<' || ch == '>' || ch == '"' + || ch == 0x7F) { + printf("&#%d;", (int)ch); + } else { + putc(ch, stdout); + } + ++p; + } +} + +static void +StartElementHandler(void *userData, + const XML_Char *name, const XML_Char **attrs) +{ + printf("<%s", name); + while (*attrs) { + printf(" %s=\"", *attrs); + ++attrs; + print_escaped(*attrs, strlen(*attrs)); + ++attrs; + putc('"', stdout); + } + putc('>', stdout); +} + +static void +EndElementHandler(void *userData, const XML_Char *name) +{ + printf("", name); +} + +static void +CharacterDataHandler(void *userData, const XML_Char *s, int len) +{ + print_escaped(s, len); +} + +static void +CommentHandler(void *userData, const XML_Char *s) +{ + printf("", s); +} + +//+ Tasks Serialization-XML-Expat-EntityDeclHandler +// Stop the parser when an entity declaration is encountered. +static void +EntityDeclHandler(void *userData, + const XML_Char *entityName, int is_parameter_entity, + const XML_Char *value, int value_length, + const XML_Char *base, const XML_Char *systemId, + const XML_Char *publicId, const XML_Char *notationName) +{ + XML_StopParser((XML_Parser)userData, XML_FALSE); +} +//- + +int +main(int argc, char **argv) +{ + if (argc != 2) { + fprintf(stderr, "usage: %s XML-FILE\n", argv[0]); + return 2; + } + + const char *file = argv[1]; + int fd = open(file, O_RDONLY | O_CLOEXEC); + if (fd < 0) { + perror("open"); + return 1; + } + + //+ Tasks Serialization-XML-Expat-Create + XML_Parser parser = XML_ParserCreate("UTF-8"); + if (parser == NULL) { + fprintf(stderr, "XML_ParserCreate failed\n"); + close(fd); + exit(1); + } + // EntityDeclHandler needs a reference to the parser to stop + // parsing. + XML_SetUserData(parser, parser); + // Disable entity processing, to inhibit entity expansion. + XML_SetEntityDeclHandler(parser, EntityDeclHandler); + //- + + // Handlers for demonstration purposes. + XML_SetElementHandler(parser, StartElementHandler, EndElementHandler); + XML_SetCharacterDataHandler(parser, CharacterDataHandler); + XML_SetCommentHandler(parser, CommentHandler); + + + char buffer[8192]; + ssize_t ret; + do { + ret = read(fd, buffer, sizeof(buffer)); + if (ret < 0) { + perror("read"); + XML_ParserFree(parser); + close(fd); + return 1; + } + enum XML_Status status = XML_Parse(parser, buffer, ret, ret == 0); + if (status != XML_STATUS_OK) { + fprintf(stderr, "%s:%zu:%zu: error: %s\n", + file, XML_GetCurrentLineNumber(parser), + XML_GetCurrentColumnNumber(parser), + XML_ErrorString(XML_GetErrorCode(parser))); + XML_ParserFree(parser); + close(fd); + return 1; + } + } while (ret != 0); + + XML_ParserFree(parser); + close(fd); + return 0; +} diff --git a/defensive-coding/src/XMLParserOpenJDK.java b/defensive-coding/src/XMLParserOpenJDK.java new file mode 100644 index 0000000..be3bef3 --- /dev/null +++ b/defensive-coding/src/XMLParserOpenJDK.java @@ -0,0 +1,286 @@ +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; + +//+ Tasks Serialization-XML-OpenJDK-Imports +import javax.xml.XMLConstants; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.sax.SAXSource; +import javax.xml.validation.Schema; +import javax.xml.validation.SchemaFactory; +import javax.xml.validation.Validator; + +import org.w3c.dom.Document; +import org.w3c.dom.ls.LSInput; +import org.w3c.dom.ls.LSResourceResolver; +import org.xml.sax.EntityResolver; +import org.xml.sax.ErrorHandler; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.SAXParseException; +import org.xml.sax.XMLReader; +//- + +public final class XMLParserOpenJDK { + public static void main(String[] args) throws Exception { + String validationType = args[0]; + File schema = new File(args[1]); + String file = args[2]; + if (validationType.equals("OpenJDK-XSD-SAX")) { + validateXSDSAX(schema, file); + } else if (validationType.equals("OpenJDK-RNG-SAX")) { + validateSAX(XMLConstants.RELAXNG_NS_URI, schema, file); + } else if (validationType.equals("OpenJDK-DTD-SAX")) { + validateSAX(XMLConstants.XML_DTD_NS_URI, schema, file); + } else if (validationType.equals("OpenJDK-XSD-DOM")) { + validateXSDDOM(schema, file); + } else if (validationType.equals("OpenJDK-RNG-DOM")) { + validateDOM(XMLConstants.W3C_XML_SCHEMA_NS_URI, + schema, file, false); + } else if (validationType.equals("OpenJDK-DTD-DOM")) { + validateDOM(XMLConstants.XML_DTD_NS_URI, schema, file, false); + } else if (validationType.equals("OpenJDK-XSD-DOM-Validate")) { + validateDOM(XMLConstants.W3C_XML_SCHEMA_NS_URI, + schema, file, true); + } else if (validationType.equals("OpenJDK-RNG-DOM-Validate")) { + validateDOM(XMLConstants.W3C_XML_SCHEMA_NS_URI, + schema, file, true); + } else if (validationType.equals("OpenJDK-DTD-DOM-Validate")) { + validateDOM(XMLConstants.XML_DTD_NS_URI, schema, file, true); + } else if (validationType.equals("OpenJDK-SAX")) { + parseSAX(file, false); + } else if (validationType.equals("OpenJDK-DOM")) { + parseDOM(file, false); + } else if (validationType.equals("OpenJDK-SAX-Validate")) { + parseSAX(file, true); + } else if (validationType.equals("OpenJDK-DOM-Validate")) { + parseDOM(file, true); + } else { + throw new Exception("invalid validator: " + validationType); + } + } + + static + //+ Tasks Serialization-XML-OpenJDK-NoResourceResolver + class NoResourceResolver implements LSResourceResolver { + @Override + public LSInput resolveResource(String type, String namespaceURI, + String publicId, String systemId, String baseURI) { + // Throwing an exception stops validation. + throw new RuntimeException(String.format( + "resolution attempt: type=%s namespace=%s " + + "publicId=%s systemId=%s baseURI=%s", + type, namespaceURI, publicId, systemId, baseURI)); + } + } + //- + + private static void validateXSDSAX( File schemaFile, String file) + throws Exception { + FileInputStream inputStream = new FileInputStream(file); + try { + //+ Tasks Serialization-XML-OpenJDK_Parse-XMLSchema_SAX + SchemaFactory factory = SchemaFactory.newInstance( + XMLConstants.W3C_XML_SCHEMA_NS_URI); + + // This enables restrictions on the schema and document + // complexity. + factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); + + // This prevents resource resolution by the schema itself. + // If the schema is trusted and references additional files, + // this line must be omitted, otherwise loading these files + // will fail. + factory.setResourceResolver(new NoResourceResolver()); + + Schema schema = factory.newSchema(schemaFile); + Validator validator = schema.newValidator(); + + // This prevents external resource resolution. + validator.setResourceResolver(new NoResourceResolver()); + + validator.validate(new SAXSource(new InputSource(inputStream))); + //- + } finally { + inputStream.close(); + } + } + + /** + * Same as {@link #validateXSDSAX(File, String)}, but the schema type URI + * is not hard-coded. + */ + private static void validateSAX(String uri, File schemaFile, String file) + throws Exception { + FileInputStream inputStream = new FileInputStream(file); + try { + SchemaFactory factory = SchemaFactory.newInstance(uri); + + // This enables restrictions on the schema and document + // complexity. + factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); + + // This prevents resource resolution by the schema itself. + // If the schema is trusted and references additional files, + // this line must be omitted, otherwise loading these files + // will fail. + factory.setResourceResolver(new NoResourceResolver()); + + Schema schema = factory.newSchema(schemaFile); + Validator validator = schema.newValidator(); + + // This prevents external resource resolution. + validator.setResourceResolver(new NoResourceResolver()); + + validator.validate(new SAXSource(new InputSource(inputStream))); + } finally { + inputStream.close(); + } + } + + private static void validateXSDDOM(File schemaFile, String file) throws Exception { + FileInputStream inputStream = new FileInputStream(file); + try { + Document document = parseDOM(file, false); + + //+ Tasks Serialization-XML-OpenJDK_Parse-XMLSchema_DOM + SchemaFactory factory = SchemaFactory.newInstance( + XMLConstants.W3C_XML_SCHEMA_NS_URI); + + // This enables restrictions on schema complexity. + factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); + + // The following line prevents resource resolution + // by the schema itself. + factory.setResourceResolver(new NoResourceResolver()); + + Schema schema = factory.newSchema(schemaFile); + + Validator validator = schema.newValidator(); + + // This prevents external resource resolution. + validator.setResourceResolver(new NoResourceResolver()); + validator.validate(new DOMSource(document)); + //- + } finally { + inputStream.close(); + } + } + + /** + * Same as {@link #validateXSDDOM(File, String)}, but does not hard-code + * the schema type URI. + */ + private static void validateDOM(String uri, File schemaFile, String file, + boolean validate) throws Exception { + FileInputStream inputStream = new FileInputStream(file); + try { + Document document = parseDOM(file, validate); + + SchemaFactory factory = SchemaFactory.newInstance(uri); + + // This enables restrictions on schema complexity. + factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); + + // The following line prevents resource resolution + // by the schema itself. + factory.setResourceResolver(new NoResourceResolver()); + + Schema schema = factory.newSchema(schemaFile); + + Validator validator = schema.newValidator(); + // This prevents external resource resolution. + validator.setResourceResolver(new NoResourceResolver()); + validator.validate(new DOMSource(document)); + } finally { + inputStream.close(); + } + } + + static + //+ Tasks Serialization-XML-OpenJDK-Errors + class Errors implements ErrorHandler { + @Override + public void warning(SAXParseException exception) { + exception.printStackTrace(); + } + + @Override + public void fatalError(SAXParseException exception) { + exception.printStackTrace(); + } + + @Override + public void error(SAXParseException exception) { + exception.printStackTrace(); + } + } + //- + + static + //+ Tasks Serialization-XML-OpenJDK-NoEntityResolver + class NoEntityResolver implements EntityResolver { + @Override + public InputSource resolveEntity(String publicId, String systemId) + throws SAXException, IOException { + // Throwing an exception stops validation. + throw new IOException(String.format( + "attempt to resolve \"%s\" \"%s\"", publicId, systemId)); + } + } + //- + + private static void parseSAX(String file, boolean validate) + throws Exception { + SAXParserFactory factory = SAXParserFactory.newInstance(); + factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); + if (validate) { + factory.setValidating(true); + } + SAXParser parser = factory.newSAXParser(); + FileInputStream in = new FileInputStream(file); + try { + XMLReader reader = parser.getXMLReader(); + reader.setEntityResolver(new NoEntityResolver()); + reader.setErrorHandler(new Errors()); + reader.parse(new InputSource(in)); + } finally { + in.close(); + } + } + + private static Document parseDOM(String file, boolean validate) + throws Exception { + FileInputStream inputStream = new FileInputStream(file); + try { + return parseDOMInternal(inputStream); + } finally { + inputStream.close(); + } + } + + private static Document parseDOMInternal(FileInputStream inputStream) + throws ParserConfigurationException, SAXException, IOException { + //+ Tasks Serialization-XML-OpenJDK_Parse-DOM + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + // Impose restrictions on the complexity of the DTD. + factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); + + // Turn on validation. + // This step can be omitted if validation is not desired. + factory.setValidating(true); + + // Parse the document. + DocumentBuilder builder = factory.newDocumentBuilder(); + builder.setEntityResolver(new NoEntityResolver()); + builder.setErrorHandler(new Errors()); + Document document = builder.parse(inputStream); + //- + return document; + } +} diff --git a/defensive-coding/src/check-function.py b/defensive-coding/src/check-function.py new file mode 100644 index 0000000..ee647d6 --- /dev/null +++ b/defensive-coding/src/check-function.py @@ -0,0 +1,18 @@ +#!/usr/bin/python + +# Usage: python check-function.py DSO/FUNCTION-NAME/OUTPUT +# +# Prints OUTPUT if libDSO.so can be loaded and defines FUNCTION-NAME +# as a function, or nothing otherwise. + +import ctypes +import sys + +for (dsoname, funcname, output) in [arg.split("/", 3) + for arg in sys.argv[1:]]: + try: + dso = ctypes.CDLL("lib{0}.so".format(dsoname)) + except OSError: + continue + if getattr(dso, funcname, None) is not None: + print output diff --git a/defensive-coding/src/data/.svn/all-wcprops b/defensive-coding/src/data/.svn/all-wcprops new file mode 100644 index 0000000..ae22847 --- /dev/null +++ b/defensive-coding/src/data/.svn/all-wcprops @@ -0,0 +1,197 @@ +K 25 +svn:wc:ra_dav:version-url +V 68 +/repos/product-security/!svn/ver/290/defensive-coding/trunk/src/data +END +XML-Parser-DTD_Public_URL.xml +K 25 +svn:wc:ra_dav:version-url +V 98 +/repos/product-security/!svn/ver/281/defensive-coding/trunk/src/data/XML-Parser-DTD_Public_URL.xml +END +XML-Parser-Internal_Entity_Polynomial_Attribute.xml +K 25 +svn:wc:ra_dav:version-url +V 120 +/repos/product-security/!svn/ver/281/defensive-coding/trunk/src/data/XML-Parser-Internal_Entity_Polynomial_Attribute.xml +END +XML-Parser-Notation_System.xml +K 25 +svn:wc:ra_dav:version-url +V 99 +/repos/product-security/!svn/ver/281/defensive-coding/trunk/src/data/XML-Parser-Notation_System.xml +END +XML-Parser-Internal_Entity_Exponential_Attribute.xml +K 25 +svn:wc:ra_dav:version-url +V 121 +/repos/product-security/!svn/ver/281/defensive-coding/trunk/src/data/XML-Parser-Internal_Entity_Exponential_Attribute.xml +END +XML-Parser-External_Entity_System_URL.xml +K 25 +svn:wc:ra_dav:version-url +V 110 +/repos/product-security/!svn/ver/281/defensive-coding/trunk/src/data/XML-Parser-External_Entity_System_URL.xml +END +XML-Parser-Internal_Regexp_1.xml +K 25 +svn:wc:ra_dav:version-url +V 101 +/repos/product-security/!svn/ver/281/defensive-coding/trunk/src/data/XML-Parser-Internal_Regexp_1.xml +END +XML-Parser-Internal_Regexp_2.xml +K 25 +svn:wc:ra_dav:version-url +V 101 +/repos/product-security/!svn/ver/281/defensive-coding/trunk/src/data/XML-Parser-Internal_Regexp_2.xml +END +XML-Parser-Internal_Regexp_3.xml +K 25 +svn:wc:ra_dav:version-url +V 101 +/repos/product-security/!svn/ver/281/defensive-coding/trunk/src/data/XML-Parser-Internal_Regexp_3.xml +END +XML-Parser-DTD_Public.xml +K 25 +svn:wc:ra_dav:version-url +V 94 +/repos/product-security/!svn/ver/281/defensive-coding/trunk/src/data/XML-Parser-DTD_Public.xml +END +XML-Parser-Notation_Public_URL.xml +K 25 +svn:wc:ra_dav:version-url +V 103 +/repos/product-security/!svn/ver/281/defensive-coding/trunk/src/data/XML-Parser-Notation_Public_URL.xml +END +XML-Parser-Internal_Entity_Polynomial.xml +K 25 +svn:wc:ra_dav:version-url +V 110 +/repos/product-security/!svn/ver/281/defensive-coding/trunk/src/data/XML-Parser-Internal_Entity_Polynomial.xml +END +XML-Parser-XSD-Include_File.xml +K 25 +svn:wc:ra_dav:version-url +V 100 +/repos/product-security/!svn/ver/284/defensive-coding/trunk/src/data/XML-Parser-XSD-Include_File.xml +END +XML-Parser-External_Regexp_3.xml +K 25 +svn:wc:ra_dav:version-url +V 101 +/repos/product-security/!svn/ver/281/defensive-coding/trunk/src/data/XML-Parser-External_Regexp_3.xml +END +XML-Parser-Internal_Entity_Exponential.xml +K 25 +svn:wc:ra_dav:version-url +V 111 +/repos/product-security/!svn/ver/281/defensive-coding/trunk/src/data/XML-Parser-Internal_Entity_Exponential.xml +END +XML-Parser-External_Entity_System.xml +K 25 +svn:wc:ra_dav:version-url +V 106 +/repos/product-security/!svn/ver/281/defensive-coding/trunk/src/data/XML-Parser-External_Entity_System.xml +END +XML-Parser-XInclude-File.xml +K 25 +svn:wc:ra_dav:version-url +V 97 +/repos/product-security/!svn/ver/290/defensive-coding/trunk/src/data/XML-Parser-XInclude-File.xml +END +XML-Parser-External_Regexp_3.dtd +K 25 +svn:wc:ra_dav:version-url +V 101 +/repos/product-security/!svn/ver/279/defensive-coding/trunk/src/data/XML-Parser-External_Regexp_3.dtd +END +XML-Parser-Notation_Public.xml +K 25 +svn:wc:ra_dav:version-url +V 99 +/repos/product-security/!svn/ver/281/defensive-coding/trunk/src/data/XML-Parser-Notation_Public.xml +END +XML-Parser-External_Entity_Public_URL.xml +K 25 +svn:wc:ra_dav:version-url +V 110 +/repos/product-security/!svn/ver/281/defensive-coding/trunk/src/data/XML-Parser-External_Entity_Public_URL.xml +END +XML-Parser-XSD-URL.xml +K 25 +svn:wc:ra_dav:version-url +V 91 +/repos/product-security/!svn/ver/284/defensive-coding/trunk/src/data/XML-Parser-XSD-URL.xml +END +XML-Parser-Validate-Regexp_1.xsd +K 25 +svn:wc:ra_dav:version-url +V 101 +/repos/product-security/!svn/ver/283/defensive-coding/trunk/src/data/XML-Parser-Validate-Regexp_1.xsd +END +XML-Parser-DTD_System_URL.xml +K 25 +svn:wc:ra_dav:version-url +V 98 +/repos/product-security/!svn/ver/281/defensive-coding/trunk/src/data/XML-Parser-DTD_System_URL.xml +END +XML-Parser-Validate-Regexp_1.xml +K 25 +svn:wc:ra_dav:version-url +V 101 +/repos/product-security/!svn/ver/282/defensive-coding/trunk/src/data/XML-Parser-Validate-Regexp_1.xml +END +XML-Parser-XSD-Include_URL.xml +K 25 +svn:wc:ra_dav:version-url +V 99 +/repos/product-security/!svn/ver/284/defensive-coding/trunk/src/data/XML-Parser-XSD-Include_URL.xml +END +XML-Parser-Validate-Regexp_4.xsd +K 25 +svn:wc:ra_dav:version-url +V 101 +/repos/product-security/!svn/ver/283/defensive-coding/trunk/src/data/XML-Parser-Validate-Regexp_4.xsd +END +XML-Parser-XInclude-URL.xml +K 25 +svn:wc:ra_dav:version-url +V 96 +/repos/product-security/!svn/ver/290/defensive-coding/trunk/src/data/XML-Parser-XInclude-URL.xml +END +XML-Parser-XSD-File.xml +K 25 +svn:wc:ra_dav:version-url +V 92 +/repos/product-security/!svn/ver/284/defensive-coding/trunk/src/data/XML-Parser-XSD-File.xml +END +XML-Parser-External_Entity_Public.xml +K 25 +svn:wc:ra_dav:version-url +V 106 +/repos/product-security/!svn/ver/281/defensive-coding/trunk/src/data/XML-Parser-External_Entity_Public.xml +END +XML-Parser-Validate-Regexp_1.dtd +K 25 +svn:wc:ra_dav:version-url +V 101 +/repos/product-security/!svn/ver/282/defensive-coding/trunk/src/data/XML-Parser-Validate-Regexp_1.dtd +END +XML-Parser-DTD_System.xml +K 25 +svn:wc:ra_dav:version-url +V 94 +/repos/product-security/!svn/ver/281/defensive-coding/trunk/src/data/XML-Parser-DTD_System.xml +END +XML-Parser-Notation_System_URL.xml +K 25 +svn:wc:ra_dav:version-url +V 103 +/repos/product-security/!svn/ver/281/defensive-coding/trunk/src/data/XML-Parser-Notation_System_URL.xml +END +XML-Parser-Validate-Regexp_1.rng +K 25 +svn:wc:ra_dav:version-url +V 101 +/repos/product-security/!svn/ver/283/defensive-coding/trunk/src/data/XML-Parser-Validate-Regexp_1.rng +END diff --git a/defensive-coding/src/data/.svn/entries b/defensive-coding/src/data/.svn/entries new file mode 100644 index 0000000..a6441d2 --- /dev/null +++ b/defensive-coding/src/data/.svn/entries @@ -0,0 +1,1116 @@ +10 + +dir +305 +https://svn.devel.redhat.com/repos/product-security/defensive-coding/trunk/src/data +https://svn.devel.redhat.com/repos/product-security + + + +2012-12-14T09:56:46.394074Z +290 +fweimer@REDHAT.COM + + + + + + + + + + + + + + +9bd5cf0f-f2b3-0410-b1a9-d5c590f50bf1 + +XML-Parser-DTD_Public_URL.xml +file + + + + +2013-01-10T17:17:51.229827Z +869b431ed9e7f200340094d1d79e38f2 +2012-12-13T13:25:23.103424Z +281 +fweimer@REDHAT.COM +has-props + + + + + + + + + + + + + + + + + + + + +142 + +XML-Parser-Internal_Entity_Polynomial_Attribute.xml +file + + + + +2013-01-10T17:17:51.230827Z +1a3b26c00352413667f38df1e0533238 +2012-12-13T13:25:23.103424Z +281 +fweimer@REDHAT.COM +has-props + + + + + + + + + + + + + + + + + + + + +687 + +XML-Parser-Notation_System.xml +file + + + + +2013-01-10T17:17:51.230827Z +889faad5991dae5ecea3ee591a867053 +2012-12-13T13:25:23.103424Z +281 +fweimer@REDHAT.COM +has-props + + + + + + + + + + + + + + + + + + + + +226 + +XML-Parser-Internal_Entity_Exponential_Attribute.xml +file + + + + +2013-01-10T17:17:51.231827Z +f5a857fa435e11d8e88cc63bfc8bba2b +2012-12-13T13:25:23.103424Z +281 +fweimer@REDHAT.COM +has-props + + + + + + + + + + + + + + + + + + + + +991 + +XML-Parser-External_Entity_System_URL.xml +file + + + + +2013-01-10T17:17:51.231827Z +ae97ab4d247363e5d94ab2b13af3c99f +2012-12-13T13:25:23.103424Z +281 +fweimer@REDHAT.COM +has-props + + + + + + + + + + + + + + + + + + + + +202 + +XML-Parser-Internal_Regexp_1.xml +file + + + + +2013-01-10T17:17:51.232827Z +dd38cd30bd5af1a813ef115c8a326525 +2012-12-13T13:25:23.103424Z +281 +fweimer@REDHAT.COM +has-props + + + + + + + + + + + + + + + + + + + + +1968 + +XML-Parser-Internal_Regexp_2.xml +file + + + + +2013-01-10T17:17:51.232827Z +b83ec2586401b78a9ef21e488d97ee47 +2012-12-13T13:25:23.103424Z +281 +fweimer@REDHAT.COM +has-props + + + + + + + + + + + + + + + + + + + + +1040 + +XML-Parser-Internal_Regexp_3.xml +file + + + + +2013-01-10T17:17:51.233827Z +e4749f47ced3a7bdd949b10382c337f0 +2012-12-13T13:25:23.103424Z +281 +fweimer@REDHAT.COM +has-props + + + + + + + + + + + + + + + + + + + + +928 + +XML-Parser-DTD_Public.xml +file + + + + +2013-01-10T17:17:51.233827Z +35da8117213594909cd8d375cb787e2e +2012-12-13T13:25:23.103424Z +281 +fweimer@REDHAT.COM +has-props + + + + + + + + + + + + + + + + + + + + +139 + +XML-Parser-Notation_Public_URL.xml +file + + + + +2013-01-10T17:17:51.234827Z +82b5df6efa8704b0bb6a35c491329f0e +2012-12-13T13:25:23.103424Z +281 +fweimer@REDHAT.COM +has-props + + + + + + + + + + + + + + + + + + + + +242 + +XML-Parser-Internal_Entity_Polynomial.xml +file + + + + +2013-01-10T17:17:51.235827Z +985019512466a10d9ee9bc76bc2ecd26 +2012-12-13T13:25:23.103424Z +281 +fweimer@REDHAT.COM +has-props + + + + + + + + + + + + + + + + + + + + +658 + +XML-Parser-XSD-Include_File.xml +file + + + + +2013-01-10T17:17:51.235827Z +e6d2f280e2d079b5f7286d00e1b29e0d +2012-12-13T16:18:36.596123Z +284 +fweimer@REDHAT.COM +has-props + + + + + + + + + + + + + + + + + + + + +562 + +XML-Parser-External_Regexp_3.xml +file + + + + +2013-01-10T17:17:51.236827Z +55df86c4cb70b6324f31061a40f9b1f9 +2012-12-13T13:25:23.103424Z +281 +fweimer@REDHAT.COM +has-props + + + + + + + + + + + + + + + + + + + + +214 + +XML-Parser-Internal_Entity_Exponential.xml +file + + + + +2013-01-10T17:17:51.236827Z +5af629a3428064cd3ae7c251607b8b75 +2012-12-13T13:25:23.103424Z +281 +fweimer@REDHAT.COM +has-props + + + + + + + + + + + + + + + + + + + + +963 + +XML-Parser-External_Entity_System.xml +file + + + + +2013-01-10T17:17:51.236827Z +da6e3b3d71fbe30b6fc9f0bd937f5564 +2012-12-13T13:25:23.103424Z +281 +fweimer@REDHAT.COM +has-props + + + + + + + + + + + + + + + + + + + + +191 + +XML-Parser-XInclude-File.xml +file + + + + +2013-01-10T17:17:51.237827Z +074294be6fbc0885ab50385d5369350c +2012-12-14T09:56:46.394074Z +290 +fweimer@REDHAT.COM +has-props + + + + + + + + + + + + + + + + + + + + +124 + +XML-Parser-External_Regexp_3.dtd +file + + + + +2013-01-10T17:17:51.237827Z +6e9f960ae6fae80f2f1af9d15bee4e7d +2012-12-11T17:20:43.846695Z +279 +fweimer@REDHAT.COM + + + + + + + + + + + + + + + + + + + + + +741 + +XML-Parser-Notation_Public.xml +file + + + + +2013-01-10T17:17:51.237827Z +c2d44d02ed8817af336fd79b3807d7dc +2012-12-13T13:25:23.103424Z +281 +fweimer@REDHAT.COM +has-props + + + + + + + + + + + + + + + + + + + + +234 + +XML-Parser-External_Entity_Public_URL.xml +file + + + + +2013-01-10T17:17:51.237827Z +347a775c3109f69ec8fa7f6d62f821d2 +2012-12-13T13:25:23.103424Z +281 +fweimer@REDHAT.COM +has-props + + + + + + + + + + + + + + + + + + + + +205 + +XML-Parser-XSD-URL.xml +file + + + + +2013-01-10T17:17:51.237827Z +5ecbfe43ff2987ae98fccf42d344c346 +2012-12-13T16:18:36.596123Z +284 +fweimer@REDHAT.COM +has-props + + + + + + + + + + + + + + + + + + + + +209 + +XML-Parser-Validate-Regexp_1.xsd +file + + + + +2013-01-10T17:17:51.238827Z +4520a3678005156cd43141d5263e60e5 +2012-12-13T14:47:55.060580Z +283 +fweimer@REDHAT.COM +has-props + + + + + + + + + + + + + + + + + + + + +29478 + +XML-Parser-DTD_System_URL.xml +file + + + + +2013-01-10T17:17:51.238827Z +7c427b73646ce262d458240da1b9a186 +2012-12-13T13:25:23.103424Z +281 +fweimer@REDHAT.COM +has-props + + + + + + + + + + + + + + + + + + + + +132 + +XML-Parser-Validate-Regexp_1.xml +file + + + + +2013-01-10T17:17:51.238827Z +019cd575cac5678e40f20d7baa4047d1 +2012-12-13T14:46:38.504321Z +282 +fweimer@REDHAT.COM +has-props + + + + + + + + + + + + + + + + + + + + +232 + +XML-Parser-XSD-Include_URL.xml +file + + + + +2013-01-10T17:17:51.238827Z +1ef30f90e596d729a28c7828883ea82b +2012-12-13T16:18:36.596123Z +284 +fweimer@REDHAT.COM +has-props + + + + + + + + + + + + + + + + + + + + +577 + +XML-Parser-Validate-Regexp_4.xsd +file + + + + +2013-01-10T17:17:51.238827Z +e786c676475116dd14cc5196761a1f1b +2012-12-13T14:47:55.060580Z +283 +fweimer@REDHAT.COM +has-props + + + + + + + + + + + + + + + + + + + + +1074 + +XML-Parser-XInclude-URL.xml +file + + + + +2013-01-10T17:17:51.239827Z +9c27dd5bc74aef33c090b6e8fc8b9529 +2012-12-14T09:56:46.394074Z +290 +fweimer@REDHAT.COM +has-props + + + + + + + + + + + + + + + + + + + + +143 + +XML-Parser-XSD-File.xml +file + + + + +2013-01-10T17:17:51.238827Z +2a9ca74fe9cabead7f49d4d542d98def +2012-12-13T16:18:36.596123Z +284 +fweimer@REDHAT.COM +has-props + + + + + + + + + + + + + + + + + + + + +194 + +XML-Parser-External_Entity_Public.xml +file + + + + +2013-01-10T17:17:51.239827Z +fb902fb338961c2664409f8515850fcb +2012-12-13T13:25:23.103424Z +281 +fweimer@REDHAT.COM +has-props + + + + + + + + + + + + + + + + + + + + +199 + +XML-Parser-Validate-Regexp_1.dtd +file + + + + +2013-01-10T17:17:51.239827Z +ced5e4ccad136727cefc561fb51facb8 +2012-12-13T14:46:38.504321Z +282 +fweimer@REDHAT.COM + + + + + + + + + + + + + + + + + + + + + +1594 + +XML-Parser-DTD_System.xml +file + + + + +2013-01-10T17:17:51.239827Z +7bd4d6b9ce1a7dd1bc519c69e0b06e22 +2012-12-13T13:25:23.103424Z +281 +fweimer@REDHAT.COM +has-props + + + + + + + + + + + + + + + + + + + + +129 + +XML-Parser-Notation_System_URL.xml +file + + + + +2013-01-10T17:17:51.239827Z +798501c7c170ba483afc44a52be06c0d +2012-12-13T13:25:23.103424Z +281 +fweimer@REDHAT.COM +has-props + + + + + + + + + + + + + + + + + + + + +234 + +XML-Parser-Validate-Regexp_1.rng +file + + + + +2013-01-10T17:17:51.239827Z +249193cd5d0356d8c0a6a578b05da265 +2012-12-13T14:47:55.060580Z +283 +fweimer@REDHAT.COM +has-props + + + + + + + + + + + + + + + + + + + + +23524 + diff --git a/defensive-coding/src/data/.svn/prop-base/XML-Parser-DTD_Public.xml.svn-base b/defensive-coding/src/data/.svn/prop-base/XML-Parser-DTD_Public.xml.svn-base new file mode 100644 index 0000000..bfec7d5 --- /dev/null +++ b/defensive-coding/src/data/.svn/prop-base/XML-Parser-DTD_Public.xml.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 8 +text/xml +END diff --git a/defensive-coding/src/data/.svn/prop-base/XML-Parser-DTD_Public_URL.xml.svn-base b/defensive-coding/src/data/.svn/prop-base/XML-Parser-DTD_Public_URL.xml.svn-base new file mode 100644 index 0000000..bfec7d5 --- /dev/null +++ b/defensive-coding/src/data/.svn/prop-base/XML-Parser-DTD_Public_URL.xml.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 8 +text/xml +END diff --git a/defensive-coding/src/data/.svn/prop-base/XML-Parser-DTD_System.xml.svn-base b/defensive-coding/src/data/.svn/prop-base/XML-Parser-DTD_System.xml.svn-base new file mode 100644 index 0000000..bfec7d5 --- /dev/null +++ b/defensive-coding/src/data/.svn/prop-base/XML-Parser-DTD_System.xml.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 8 +text/xml +END diff --git a/defensive-coding/src/data/.svn/prop-base/XML-Parser-DTD_System_URL.xml.svn-base b/defensive-coding/src/data/.svn/prop-base/XML-Parser-DTD_System_URL.xml.svn-base new file mode 100644 index 0000000..bfec7d5 --- /dev/null +++ b/defensive-coding/src/data/.svn/prop-base/XML-Parser-DTD_System_URL.xml.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 8 +text/xml +END diff --git a/defensive-coding/src/data/.svn/prop-base/XML-Parser-External_Entity_Public.xml.svn-base b/defensive-coding/src/data/.svn/prop-base/XML-Parser-External_Entity_Public.xml.svn-base new file mode 100644 index 0000000..bfec7d5 --- /dev/null +++ b/defensive-coding/src/data/.svn/prop-base/XML-Parser-External_Entity_Public.xml.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 8 +text/xml +END diff --git a/defensive-coding/src/data/.svn/prop-base/XML-Parser-External_Entity_Public_URL.xml.svn-base b/defensive-coding/src/data/.svn/prop-base/XML-Parser-External_Entity_Public_URL.xml.svn-base new file mode 100644 index 0000000..bfec7d5 --- /dev/null +++ b/defensive-coding/src/data/.svn/prop-base/XML-Parser-External_Entity_Public_URL.xml.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 8 +text/xml +END diff --git a/defensive-coding/src/data/.svn/prop-base/XML-Parser-External_Entity_System.xml.svn-base b/defensive-coding/src/data/.svn/prop-base/XML-Parser-External_Entity_System.xml.svn-base new file mode 100644 index 0000000..bfec7d5 --- /dev/null +++ b/defensive-coding/src/data/.svn/prop-base/XML-Parser-External_Entity_System.xml.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 8 +text/xml +END diff --git a/defensive-coding/src/data/.svn/prop-base/XML-Parser-External_Entity_System_URL.xml.svn-base b/defensive-coding/src/data/.svn/prop-base/XML-Parser-External_Entity_System_URL.xml.svn-base new file mode 100644 index 0000000..bfec7d5 --- /dev/null +++ b/defensive-coding/src/data/.svn/prop-base/XML-Parser-External_Entity_System_URL.xml.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 8 +text/xml +END diff --git a/defensive-coding/src/data/.svn/prop-base/XML-Parser-External_Regexp_3.xml.svn-base b/defensive-coding/src/data/.svn/prop-base/XML-Parser-External_Regexp_3.xml.svn-base new file mode 100644 index 0000000..bfec7d5 --- /dev/null +++ b/defensive-coding/src/data/.svn/prop-base/XML-Parser-External_Regexp_3.xml.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 8 +text/xml +END diff --git a/defensive-coding/src/data/.svn/prop-base/XML-Parser-Internal_Entity_Exponential.xml.svn-base b/defensive-coding/src/data/.svn/prop-base/XML-Parser-Internal_Entity_Exponential.xml.svn-base new file mode 100644 index 0000000..bfec7d5 --- /dev/null +++ b/defensive-coding/src/data/.svn/prop-base/XML-Parser-Internal_Entity_Exponential.xml.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 8 +text/xml +END diff --git a/defensive-coding/src/data/.svn/prop-base/XML-Parser-Internal_Entity_Exponential_Attribute.xml.svn-base b/defensive-coding/src/data/.svn/prop-base/XML-Parser-Internal_Entity_Exponential_Attribute.xml.svn-base new file mode 100644 index 0000000..bfec7d5 --- /dev/null +++ b/defensive-coding/src/data/.svn/prop-base/XML-Parser-Internal_Entity_Exponential_Attribute.xml.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 8 +text/xml +END diff --git a/defensive-coding/src/data/.svn/prop-base/XML-Parser-Internal_Entity_Polynomial.xml.svn-base b/defensive-coding/src/data/.svn/prop-base/XML-Parser-Internal_Entity_Polynomial.xml.svn-base new file mode 100644 index 0000000..bfec7d5 --- /dev/null +++ b/defensive-coding/src/data/.svn/prop-base/XML-Parser-Internal_Entity_Polynomial.xml.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 8 +text/xml +END diff --git a/defensive-coding/src/data/.svn/prop-base/XML-Parser-Internal_Entity_Polynomial_Attribute.xml.svn-base b/defensive-coding/src/data/.svn/prop-base/XML-Parser-Internal_Entity_Polynomial_Attribute.xml.svn-base new file mode 100644 index 0000000..bfec7d5 --- /dev/null +++ b/defensive-coding/src/data/.svn/prop-base/XML-Parser-Internal_Entity_Polynomial_Attribute.xml.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 8 +text/xml +END diff --git a/defensive-coding/src/data/.svn/prop-base/XML-Parser-Internal_Regexp_1.xml.svn-base b/defensive-coding/src/data/.svn/prop-base/XML-Parser-Internal_Regexp_1.xml.svn-base new file mode 100644 index 0000000..bfec7d5 --- /dev/null +++ b/defensive-coding/src/data/.svn/prop-base/XML-Parser-Internal_Regexp_1.xml.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 8 +text/xml +END diff --git a/defensive-coding/src/data/.svn/prop-base/XML-Parser-Internal_Regexp_2.xml.svn-base b/defensive-coding/src/data/.svn/prop-base/XML-Parser-Internal_Regexp_2.xml.svn-base new file mode 100644 index 0000000..bfec7d5 --- /dev/null +++ b/defensive-coding/src/data/.svn/prop-base/XML-Parser-Internal_Regexp_2.xml.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 8 +text/xml +END diff --git a/defensive-coding/src/data/.svn/prop-base/XML-Parser-Internal_Regexp_3.xml.svn-base b/defensive-coding/src/data/.svn/prop-base/XML-Parser-Internal_Regexp_3.xml.svn-base new file mode 100644 index 0000000..bfec7d5 --- /dev/null +++ b/defensive-coding/src/data/.svn/prop-base/XML-Parser-Internal_Regexp_3.xml.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 8 +text/xml +END diff --git a/defensive-coding/src/data/.svn/prop-base/XML-Parser-Notation_Public.xml.svn-base b/defensive-coding/src/data/.svn/prop-base/XML-Parser-Notation_Public.xml.svn-base new file mode 100644 index 0000000..bfec7d5 --- /dev/null +++ b/defensive-coding/src/data/.svn/prop-base/XML-Parser-Notation_Public.xml.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 8 +text/xml +END diff --git a/defensive-coding/src/data/.svn/prop-base/XML-Parser-Notation_Public_URL.xml.svn-base b/defensive-coding/src/data/.svn/prop-base/XML-Parser-Notation_Public_URL.xml.svn-base new file mode 100644 index 0000000..bfec7d5 --- /dev/null +++ b/defensive-coding/src/data/.svn/prop-base/XML-Parser-Notation_Public_URL.xml.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 8 +text/xml +END diff --git a/defensive-coding/src/data/.svn/prop-base/XML-Parser-Notation_System.xml.svn-base b/defensive-coding/src/data/.svn/prop-base/XML-Parser-Notation_System.xml.svn-base new file mode 100644 index 0000000..bfec7d5 --- /dev/null +++ b/defensive-coding/src/data/.svn/prop-base/XML-Parser-Notation_System.xml.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 8 +text/xml +END diff --git a/defensive-coding/src/data/.svn/prop-base/XML-Parser-Notation_System_URL.xml.svn-base b/defensive-coding/src/data/.svn/prop-base/XML-Parser-Notation_System_URL.xml.svn-base new file mode 100644 index 0000000..bfec7d5 --- /dev/null +++ b/defensive-coding/src/data/.svn/prop-base/XML-Parser-Notation_System_URL.xml.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 8 +text/xml +END diff --git a/defensive-coding/src/data/.svn/prop-base/XML-Parser-Validate-Regexp_1.rng.svn-base b/defensive-coding/src/data/.svn/prop-base/XML-Parser-Validate-Regexp_1.rng.svn-base new file mode 100644 index 0000000..bfec7d5 --- /dev/null +++ b/defensive-coding/src/data/.svn/prop-base/XML-Parser-Validate-Regexp_1.rng.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 8 +text/xml +END diff --git a/defensive-coding/src/data/.svn/prop-base/XML-Parser-Validate-Regexp_1.xml.svn-base b/defensive-coding/src/data/.svn/prop-base/XML-Parser-Validate-Regexp_1.xml.svn-base new file mode 100644 index 0000000..bfec7d5 --- /dev/null +++ b/defensive-coding/src/data/.svn/prop-base/XML-Parser-Validate-Regexp_1.xml.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 8 +text/xml +END diff --git a/defensive-coding/src/data/.svn/prop-base/XML-Parser-Validate-Regexp_1.xsd.svn-base b/defensive-coding/src/data/.svn/prop-base/XML-Parser-Validate-Regexp_1.xsd.svn-base new file mode 100644 index 0000000..bfec7d5 --- /dev/null +++ b/defensive-coding/src/data/.svn/prop-base/XML-Parser-Validate-Regexp_1.xsd.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 8 +text/xml +END diff --git a/defensive-coding/src/data/.svn/prop-base/XML-Parser-Validate-Regexp_4.xsd.svn-base b/defensive-coding/src/data/.svn/prop-base/XML-Parser-Validate-Regexp_4.xsd.svn-base new file mode 100644 index 0000000..bfec7d5 --- /dev/null +++ b/defensive-coding/src/data/.svn/prop-base/XML-Parser-Validate-Regexp_4.xsd.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 8 +text/xml +END diff --git a/defensive-coding/src/data/.svn/prop-base/XML-Parser-XInclude-File.xml.svn-base b/defensive-coding/src/data/.svn/prop-base/XML-Parser-XInclude-File.xml.svn-base new file mode 100644 index 0000000..bfec7d5 --- /dev/null +++ b/defensive-coding/src/data/.svn/prop-base/XML-Parser-XInclude-File.xml.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 8 +text/xml +END diff --git a/defensive-coding/src/data/.svn/prop-base/XML-Parser-XInclude-URL.xml.svn-base b/defensive-coding/src/data/.svn/prop-base/XML-Parser-XInclude-URL.xml.svn-base new file mode 100644 index 0000000..bfec7d5 --- /dev/null +++ b/defensive-coding/src/data/.svn/prop-base/XML-Parser-XInclude-URL.xml.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 8 +text/xml +END diff --git a/defensive-coding/src/data/.svn/prop-base/XML-Parser-XSD-File.xml.svn-base b/defensive-coding/src/data/.svn/prop-base/XML-Parser-XSD-File.xml.svn-base new file mode 100644 index 0000000..bfec7d5 --- /dev/null +++ b/defensive-coding/src/data/.svn/prop-base/XML-Parser-XSD-File.xml.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 8 +text/xml +END diff --git a/defensive-coding/src/data/.svn/prop-base/XML-Parser-XSD-Include_File.xml.svn-base b/defensive-coding/src/data/.svn/prop-base/XML-Parser-XSD-Include_File.xml.svn-base new file mode 100644 index 0000000..bfec7d5 --- /dev/null +++ b/defensive-coding/src/data/.svn/prop-base/XML-Parser-XSD-Include_File.xml.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 8 +text/xml +END diff --git a/defensive-coding/src/data/.svn/prop-base/XML-Parser-XSD-Include_URL.xml.svn-base b/defensive-coding/src/data/.svn/prop-base/XML-Parser-XSD-Include_URL.xml.svn-base new file mode 100644 index 0000000..bfec7d5 --- /dev/null +++ b/defensive-coding/src/data/.svn/prop-base/XML-Parser-XSD-Include_URL.xml.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 8 +text/xml +END diff --git a/defensive-coding/src/data/.svn/prop-base/XML-Parser-XSD-URL.xml.svn-base b/defensive-coding/src/data/.svn/prop-base/XML-Parser-XSD-URL.xml.svn-base new file mode 100644 index 0000000..bfec7d5 --- /dev/null +++ b/defensive-coding/src/data/.svn/prop-base/XML-Parser-XSD-URL.xml.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 8 +text/xml +END diff --git a/defensive-coding/src/data/.svn/text-base/XML-Parser-DTD_Public.xml.svn-base b/defensive-coding/src/data/.svn/text-base/XML-Parser-DTD_Public.xml.svn-base new file mode 100644 index 0000000..1904358 --- /dev/null +++ b/defensive-coding/src/data/.svn/text-base/XML-Parser-DTD_Public.xml.svn-base @@ -0,0 +1,4 @@ + + + +&e1; diff --git a/defensive-coding/src/data/.svn/text-base/XML-Parser-DTD_Public_URL.xml.svn-base b/defensive-coding/src/data/.svn/text-base/XML-Parser-DTD_Public_URL.xml.svn-base new file mode 100644 index 0000000..593d191 --- /dev/null +++ b/defensive-coding/src/data/.svn/text-base/XML-Parser-DTD_Public_URL.xml.svn-base @@ -0,0 +1,4 @@ + + + +&e1; diff --git a/defensive-coding/src/data/.svn/text-base/XML-Parser-DTD_System.xml.svn-base b/defensive-coding/src/data/.svn/text-base/XML-Parser-DTD_System.xml.svn-base new file mode 100644 index 0000000..5d809c9 --- /dev/null +++ b/defensive-coding/src/data/.svn/text-base/XML-Parser-DTD_System.xml.svn-base @@ -0,0 +1,4 @@ + + + +&e1; diff --git a/defensive-coding/src/data/.svn/text-base/XML-Parser-DTD_System_URL.xml.svn-base b/defensive-coding/src/data/.svn/text-base/XML-Parser-DTD_System_URL.xml.svn-base new file mode 100644 index 0000000..c6db833 --- /dev/null +++ b/defensive-coding/src/data/.svn/text-base/XML-Parser-DTD_System_URL.xml.svn-base @@ -0,0 +1,4 @@ + + + +&e1; diff --git a/defensive-coding/src/data/.svn/text-base/XML-Parser-External_Entity_Public.xml.svn-base b/defensive-coding/src/data/.svn/text-base/XML-Parser-External_Entity_Public.xml.svn-base new file mode 100644 index 0000000..b976d59 --- /dev/null +++ b/defensive-coding/src/data/.svn/text-base/XML-Parser-External_Entity_Public.xml.svn-base @@ -0,0 +1,7 @@ + + + + +]> +&e1; diff --git a/defensive-coding/src/data/.svn/text-base/XML-Parser-External_Entity_Public_URL.xml.svn-base b/defensive-coding/src/data/.svn/text-base/XML-Parser-External_Entity_Public_URL.xml.svn-base new file mode 100644 index 0000000..d9a7552 --- /dev/null +++ b/defensive-coding/src/data/.svn/text-base/XML-Parser-External_Entity_Public_URL.xml.svn-base @@ -0,0 +1,7 @@ + + + + +]> +&e1; diff --git a/defensive-coding/src/data/.svn/text-base/XML-Parser-External_Entity_System.xml.svn-base b/defensive-coding/src/data/.svn/text-base/XML-Parser-External_Entity_System.xml.svn-base new file mode 100644 index 0000000..bb33a91 --- /dev/null +++ b/defensive-coding/src/data/.svn/text-base/XML-Parser-External_Entity_System.xml.svn-base @@ -0,0 +1,7 @@ + + + + +]> +&e1; diff --git a/defensive-coding/src/data/.svn/text-base/XML-Parser-External_Entity_System_URL.xml.svn-base b/defensive-coding/src/data/.svn/text-base/XML-Parser-External_Entity_System_URL.xml.svn-base new file mode 100644 index 0000000..cc0fbe0 --- /dev/null +++ b/defensive-coding/src/data/.svn/text-base/XML-Parser-External_Entity_System_URL.xml.svn-base @@ -0,0 +1,7 @@ + + + + +]> +&e1; diff --git a/defensive-coding/src/data/.svn/text-base/XML-Parser-External_Regexp_3.dtd.svn-base b/defensive-coding/src/data/.svn/text-base/XML-Parser-External_Regexp_3.dtd.svn-base new file mode 100644 index 0000000..bc6d7af --- /dev/null +++ b/defensive-coding/src/data/.svn/text-base/XML-Parser-External_Regexp_3.dtd.svn-base @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/defensive-coding/src/data/.svn/text-base/XML-Parser-External_Regexp_3.xml.svn-base b/defensive-coding/src/data/.svn/text-base/XML-Parser-External_Regexp_3.xml.svn-base new file mode 100644 index 0000000..5616c7a --- /dev/null +++ b/defensive-coding/src/data/.svn/text-base/XML-Parser-External_Regexp_3.xml.svn-base @@ -0,0 +1,10 @@ + + + + + + diff --git a/defensive-coding/src/data/.svn/text-base/XML-Parser-Internal_Entity_Exponential.xml.svn-base b/defensive-coding/src/data/.svn/text-base/XML-Parser-Internal_Entity_Exponential.xml.svn-base new file mode 100644 index 0000000..b5a67ff --- /dev/null +++ b/defensive-coding/src/data/.svn/text-base/XML-Parser-Internal_Entity_Exponential.xml.svn-base @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +]> +&e30; diff --git a/defensive-coding/src/data/.svn/text-base/XML-Parser-Internal_Entity_Exponential_Attribute.xml.svn-base b/defensive-coding/src/data/.svn/text-base/XML-Parser-Internal_Entity_Exponential_Attribute.xml.svn-base new file mode 100644 index 0000000..7b02965 --- /dev/null +++ b/defensive-coding/src/data/.svn/text-base/XML-Parser-Internal_Entity_Exponential_Attribute.xml.svn-base @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +]> + diff --git a/defensive-coding/src/data/.svn/text-base/XML-Parser-Internal_Entity_Polynomial.xml.svn-base b/defensive-coding/src/data/.svn/text-base/XML-Parser-Internal_Entity_Polynomial.xml.svn-base new file mode 100644 index 0000000..cc181a3 --- /dev/null +++ b/defensive-coding/src/data/.svn/text-base/XML-Parser-Internal_Entity_Polynomial.xml.svn-base @@ -0,0 +1,13 @@ + + + + + + + + + +]> +&e6; diff --git a/defensive-coding/src/data/.svn/text-base/XML-Parser-Internal_Entity_Polynomial_Attribute.xml.svn-base b/defensive-coding/src/data/.svn/text-base/XML-Parser-Internal_Entity_Polynomial_Attribute.xml.svn-base new file mode 100644 index 0000000..f73b9d4 --- /dev/null +++ b/defensive-coding/src/data/.svn/text-base/XML-Parser-Internal_Entity_Polynomial_Attribute.xml.svn-base @@ -0,0 +1,15 @@ + + + + + + + + + + +]> + + diff --git a/defensive-coding/src/data/.svn/text-base/XML-Parser-Internal_Regexp_1.xml.svn-base b/defensive-coding/src/data/.svn/text-base/XML-Parser-Internal_Regexp_1.xml.svn-base new file mode 100644 index 0000000..89d00d8 --- /dev/null +++ b/defensive-coding/src/data/.svn/text-base/XML-Parser-Internal_Regexp_1.xml.svn-base @@ -0,0 +1,41 @@ + + + + + +]> + + + + diff --git a/defensive-coding/src/data/.svn/text-base/XML-Parser-Internal_Regexp_2.xml.svn-base b/defensive-coding/src/data/.svn/text-base/XML-Parser-Internal_Regexp_2.xml.svn-base new file mode 100644 index 0000000..a5c11e8 --- /dev/null +++ b/defensive-coding/src/data/.svn/text-base/XML-Parser-Internal_Regexp_2.xml.svn-base @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +]> + + + + diff --git a/defensive-coding/src/data/.svn/text-base/XML-Parser-Internal_Regexp_3.xml.svn-base b/defensive-coding/src/data/.svn/text-base/XML-Parser-Internal_Regexp_3.xml.svn-base new file mode 100644 index 0000000..24c48a2 --- /dev/null +++ b/defensive-coding/src/data/.svn/text-base/XML-Parser-Internal_Regexp_3.xml.svn-base @@ -0,0 +1,22 @@ + + + + + + + + + + + + + +]> + + + diff --git a/defensive-coding/src/data/.svn/text-base/XML-Parser-Notation_Public.xml.svn-base b/defensive-coding/src/data/.svn/text-base/XML-Parser-Notation_Public.xml.svn-base new file mode 100644 index 0000000..aade0f9 --- /dev/null +++ b/defensive-coding/src/data/.svn/text-base/XML-Parser-Notation_Public.xml.svn-base @@ -0,0 +1,8 @@ + + + + + +]> + diff --git a/defensive-coding/src/data/.svn/text-base/XML-Parser-Notation_Public_URL.xml.svn-base b/defensive-coding/src/data/.svn/text-base/XML-Parser-Notation_Public_URL.xml.svn-base new file mode 100644 index 0000000..4fe750f --- /dev/null +++ b/defensive-coding/src/data/.svn/text-base/XML-Parser-Notation_Public_URL.xml.svn-base @@ -0,0 +1,8 @@ + + + + + +]> + diff --git a/defensive-coding/src/data/.svn/text-base/XML-Parser-Notation_System.xml.svn-base b/defensive-coding/src/data/.svn/text-base/XML-Parser-Notation_System.xml.svn-base new file mode 100644 index 0000000..8ba042b --- /dev/null +++ b/defensive-coding/src/data/.svn/text-base/XML-Parser-Notation_System.xml.svn-base @@ -0,0 +1,8 @@ + + + + + +]> + diff --git a/defensive-coding/src/data/.svn/text-base/XML-Parser-Notation_System_URL.xml.svn-base b/defensive-coding/src/data/.svn/text-base/XML-Parser-Notation_System_URL.xml.svn-base new file mode 100644 index 0000000..78b5138 --- /dev/null +++ b/defensive-coding/src/data/.svn/text-base/XML-Parser-Notation_System_URL.xml.svn-base @@ -0,0 +1,8 @@ + + + + + +]> + diff --git a/defensive-coding/src/data/.svn/text-base/XML-Parser-Validate-Regexp_1.dtd.svn-base b/defensive-coding/src/data/.svn/text-base/XML-Parser-Validate-Regexp_1.dtd.svn-base new file mode 100644 index 0000000..4bc85b4 --- /dev/null +++ b/defensive-coding/src/data/.svn/text-base/XML-Parser-Validate-Regexp_1.dtd.svn-base @@ -0,0 +1,28 @@ + + + + diff --git a/defensive-coding/src/data/.svn/text-base/XML-Parser-Validate-Regexp_1.rng.svn-base b/defensive-coding/src/data/.svn/text-base/XML-Parser-Validate-Regexp_1.rng.svn-base new file mode 100644 index 0000000..191f835 --- /dev/null +++ b/defensive-coding/src/data/.svn/text-base/XML-Parser-Validate-Regexp_1.rng.svn-base @@ -0,0 +1,1010 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/defensive-coding/src/data/.svn/text-base/XML-Parser-Validate-Regexp_1.xml.svn-base b/defensive-coding/src/data/.svn/text-base/XML-Parser-Validate-Regexp_1.xml.svn-base new file mode 100644 index 0000000..e3c57a7 --- /dev/null +++ b/defensive-coding/src/data/.svn/text-base/XML-Parser-Validate-Regexp_1.xml.svn-base @@ -0,0 +1,5 @@ + + + + + diff --git a/defensive-coding/src/data/.svn/text-base/XML-Parser-Validate-Regexp_1.xsd.svn-base b/defensive-coding/src/data/.svn/text-base/XML-Parser-Validate-Regexp_1.xsd.svn-base new file mode 100644 index 0000000..e5a9f13 --- /dev/null +++ b/defensive-coding/src/data/.svn/text-base/XML-Parser-Validate-Regexp_1.xsd.svn-base @@ -0,0 +1,990 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/defensive-coding/src/data/.svn/text-base/XML-Parser-Validate-Regexp_4.xsd.svn-base b/defensive-coding/src/data/.svn/text-base/XML-Parser-Validate-Regexp_4.xsd.svn-base new file mode 100644 index 0000000..7c2eba4 --- /dev/null +++ b/defensive-coding/src/data/.svn/text-base/XML-Parser-Validate-Regexp_4.xsd.svn-base @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/defensive-coding/src/data/.svn/text-base/XML-Parser-XInclude-File.xml.svn-base b/defensive-coding/src/data/.svn/text-base/XML-Parser-XInclude-File.xml.svn-base new file mode 100644 index 0000000..e6fc009 --- /dev/null +++ b/defensive-coding/src/data/.svn/text-base/XML-Parser-XInclude-File.xml.svn-base @@ -0,0 +1,5 @@ + + + + diff --git a/defensive-coding/src/data/.svn/text-base/XML-Parser-XInclude-URL.xml.svn-base b/defensive-coding/src/data/.svn/text-base/XML-Parser-XInclude-URL.xml.svn-base new file mode 100644 index 0000000..3afe285 --- /dev/null +++ b/defensive-coding/src/data/.svn/text-base/XML-Parser-XInclude-URL.xml.svn-base @@ -0,0 +1,5 @@ + + + + diff --git a/defensive-coding/src/data/.svn/text-base/XML-Parser-XSD-File.xml.svn-base b/defensive-coding/src/data/.svn/text-base/XML-Parser-XSD-File.xml.svn-base new file mode 100644 index 0000000..f12aba4 --- /dev/null +++ b/defensive-coding/src/data/.svn/text-base/XML-Parser-XSD-File.xml.svn-base @@ -0,0 +1,4 @@ + + + diff --git a/defensive-coding/src/data/.svn/text-base/XML-Parser-XSD-Include_File.xml.svn-base b/defensive-coding/src/data/.svn/text-base/XML-Parser-XSD-Include_File.xml.svn-base new file mode 100644 index 0000000..0443d70 --- /dev/null +++ b/defensive-coding/src/data/.svn/text-base/XML-Parser-XSD-Include_File.xml.svn-base @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/defensive-coding/src/data/.svn/text-base/XML-Parser-XSD-Include_URL.xml.svn-base b/defensive-coding/src/data/.svn/text-base/XML-Parser-XSD-Include_URL.xml.svn-base new file mode 100644 index 0000000..282fb87 --- /dev/null +++ b/defensive-coding/src/data/.svn/text-base/XML-Parser-XSD-Include_URL.xml.svn-base @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/defensive-coding/src/data/.svn/text-base/XML-Parser-XSD-URL.xml.svn-base b/defensive-coding/src/data/.svn/text-base/XML-Parser-XSD-URL.xml.svn-base new file mode 100644 index 0000000..45df87f --- /dev/null +++ b/defensive-coding/src/data/.svn/text-base/XML-Parser-XSD-URL.xml.svn-base @@ -0,0 +1,4 @@ + + + diff --git a/defensive-coding/src/data/XML-Parser-DTD_Public.xml b/defensive-coding/src/data/XML-Parser-DTD_Public.xml new file mode 100644 index 0000000..1904358 --- /dev/null +++ b/defensive-coding/src/data/XML-Parser-DTD_Public.xml @@ -0,0 +1,4 @@ + + + +&e1; diff --git a/defensive-coding/src/data/XML-Parser-DTD_Public_URL.xml b/defensive-coding/src/data/XML-Parser-DTD_Public_URL.xml new file mode 100644 index 0000000..593d191 --- /dev/null +++ b/defensive-coding/src/data/XML-Parser-DTD_Public_URL.xml @@ -0,0 +1,4 @@ + + + +&e1; diff --git a/defensive-coding/src/data/XML-Parser-DTD_System.xml b/defensive-coding/src/data/XML-Parser-DTD_System.xml new file mode 100644 index 0000000..5d809c9 --- /dev/null +++ b/defensive-coding/src/data/XML-Parser-DTD_System.xml @@ -0,0 +1,4 @@ + + + +&e1; diff --git a/defensive-coding/src/data/XML-Parser-DTD_System_URL.xml b/defensive-coding/src/data/XML-Parser-DTD_System_URL.xml new file mode 100644 index 0000000..c6db833 --- /dev/null +++ b/defensive-coding/src/data/XML-Parser-DTD_System_URL.xml @@ -0,0 +1,4 @@ + + + +&e1; diff --git a/defensive-coding/src/data/XML-Parser-External_Entity_Public.xml b/defensive-coding/src/data/XML-Parser-External_Entity_Public.xml new file mode 100644 index 0000000..b976d59 --- /dev/null +++ b/defensive-coding/src/data/XML-Parser-External_Entity_Public.xml @@ -0,0 +1,7 @@ + + + + +]> +&e1; diff --git a/defensive-coding/src/data/XML-Parser-External_Entity_Public_URL.xml b/defensive-coding/src/data/XML-Parser-External_Entity_Public_URL.xml new file mode 100644 index 0000000..d9a7552 --- /dev/null +++ b/defensive-coding/src/data/XML-Parser-External_Entity_Public_URL.xml @@ -0,0 +1,7 @@ + + + + +]> +&e1; diff --git a/defensive-coding/src/data/XML-Parser-External_Entity_System.xml b/defensive-coding/src/data/XML-Parser-External_Entity_System.xml new file mode 100644 index 0000000..bb33a91 --- /dev/null +++ b/defensive-coding/src/data/XML-Parser-External_Entity_System.xml @@ -0,0 +1,7 @@ + + + + +]> +&e1; diff --git a/defensive-coding/src/data/XML-Parser-External_Entity_System_URL.xml b/defensive-coding/src/data/XML-Parser-External_Entity_System_URL.xml new file mode 100644 index 0000000..cc0fbe0 --- /dev/null +++ b/defensive-coding/src/data/XML-Parser-External_Entity_System_URL.xml @@ -0,0 +1,7 @@ + + + + +]> +&e1; diff --git a/defensive-coding/src/data/XML-Parser-External_Regexp_3.dtd b/defensive-coding/src/data/XML-Parser-External_Regexp_3.dtd new file mode 100644 index 0000000..bc6d7af --- /dev/null +++ b/defensive-coding/src/data/XML-Parser-External_Regexp_3.dtd @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/defensive-coding/src/data/XML-Parser-External_Regexp_3.xml b/defensive-coding/src/data/XML-Parser-External_Regexp_3.xml new file mode 100644 index 0000000..5616c7a --- /dev/null +++ b/defensive-coding/src/data/XML-Parser-External_Regexp_3.xml @@ -0,0 +1,10 @@ + + + + + + diff --git a/defensive-coding/src/data/XML-Parser-Internal_Entity_Exponential.xml b/defensive-coding/src/data/XML-Parser-Internal_Entity_Exponential.xml new file mode 100644 index 0000000..b5a67ff --- /dev/null +++ b/defensive-coding/src/data/XML-Parser-Internal_Entity_Exponential.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +]> +&e30; diff --git a/defensive-coding/src/data/XML-Parser-Internal_Entity_Exponential_Attribute.xml b/defensive-coding/src/data/XML-Parser-Internal_Entity_Exponential_Attribute.xml new file mode 100644 index 0000000..7b02965 --- /dev/null +++ b/defensive-coding/src/data/XML-Parser-Internal_Entity_Exponential_Attribute.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +]> + diff --git a/defensive-coding/src/data/XML-Parser-Internal_Entity_Polynomial.xml b/defensive-coding/src/data/XML-Parser-Internal_Entity_Polynomial.xml new file mode 100644 index 0000000..cc181a3 --- /dev/null +++ b/defensive-coding/src/data/XML-Parser-Internal_Entity_Polynomial.xml @@ -0,0 +1,13 @@ + + + + + + + + + +]> +&e6; diff --git a/defensive-coding/src/data/XML-Parser-Internal_Entity_Polynomial_Attribute.xml b/defensive-coding/src/data/XML-Parser-Internal_Entity_Polynomial_Attribute.xml new file mode 100644 index 0000000..f73b9d4 --- /dev/null +++ b/defensive-coding/src/data/XML-Parser-Internal_Entity_Polynomial_Attribute.xml @@ -0,0 +1,15 @@ + + + + + + + + + + +]> + + diff --git a/defensive-coding/src/data/XML-Parser-Internal_Regexp_1.xml b/defensive-coding/src/data/XML-Parser-Internal_Regexp_1.xml new file mode 100644 index 0000000..89d00d8 --- /dev/null +++ b/defensive-coding/src/data/XML-Parser-Internal_Regexp_1.xml @@ -0,0 +1,41 @@ + + + + + +]> + + + + diff --git a/defensive-coding/src/data/XML-Parser-Internal_Regexp_2.xml b/defensive-coding/src/data/XML-Parser-Internal_Regexp_2.xml new file mode 100644 index 0000000..a5c11e8 --- /dev/null +++ b/defensive-coding/src/data/XML-Parser-Internal_Regexp_2.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +]> + + + + diff --git a/defensive-coding/src/data/XML-Parser-Internal_Regexp_3.xml b/defensive-coding/src/data/XML-Parser-Internal_Regexp_3.xml new file mode 100644 index 0000000..24c48a2 --- /dev/null +++ b/defensive-coding/src/data/XML-Parser-Internal_Regexp_3.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + +]> + + + diff --git a/defensive-coding/src/data/XML-Parser-Notation_Public.xml b/defensive-coding/src/data/XML-Parser-Notation_Public.xml new file mode 100644 index 0000000..aade0f9 --- /dev/null +++ b/defensive-coding/src/data/XML-Parser-Notation_Public.xml @@ -0,0 +1,8 @@ + + + + + +]> + diff --git a/defensive-coding/src/data/XML-Parser-Notation_Public_URL.xml b/defensive-coding/src/data/XML-Parser-Notation_Public_URL.xml new file mode 100644 index 0000000..4fe750f --- /dev/null +++ b/defensive-coding/src/data/XML-Parser-Notation_Public_URL.xml @@ -0,0 +1,8 @@ + + + + + +]> + diff --git a/defensive-coding/src/data/XML-Parser-Notation_System.xml b/defensive-coding/src/data/XML-Parser-Notation_System.xml new file mode 100644 index 0000000..8ba042b --- /dev/null +++ b/defensive-coding/src/data/XML-Parser-Notation_System.xml @@ -0,0 +1,8 @@ + + + + + +]> + diff --git a/defensive-coding/src/data/XML-Parser-Notation_System_URL.xml b/defensive-coding/src/data/XML-Parser-Notation_System_URL.xml new file mode 100644 index 0000000..78b5138 --- /dev/null +++ b/defensive-coding/src/data/XML-Parser-Notation_System_URL.xml @@ -0,0 +1,8 @@ + + + + + +]> + diff --git a/defensive-coding/src/data/XML-Parser-Validate-Regexp_1.dtd b/defensive-coding/src/data/XML-Parser-Validate-Regexp_1.dtd new file mode 100644 index 0000000..4bc85b4 --- /dev/null +++ b/defensive-coding/src/data/XML-Parser-Validate-Regexp_1.dtd @@ -0,0 +1,28 @@ + + + + diff --git a/defensive-coding/src/data/XML-Parser-Validate-Regexp_1.rng b/defensive-coding/src/data/XML-Parser-Validate-Regexp_1.rng new file mode 100644 index 0000000..191f835 --- /dev/null +++ b/defensive-coding/src/data/XML-Parser-Validate-Regexp_1.rng @@ -0,0 +1,1010 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/defensive-coding/src/data/XML-Parser-Validate-Regexp_1.xml b/defensive-coding/src/data/XML-Parser-Validate-Regexp_1.xml new file mode 100644 index 0000000..e3c57a7 --- /dev/null +++ b/defensive-coding/src/data/XML-Parser-Validate-Regexp_1.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/defensive-coding/src/data/XML-Parser-Validate-Regexp_1.xsd b/defensive-coding/src/data/XML-Parser-Validate-Regexp_1.xsd new file mode 100644 index 0000000..e5a9f13 --- /dev/null +++ b/defensive-coding/src/data/XML-Parser-Validate-Regexp_1.xsd @@ -0,0 +1,990 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/defensive-coding/src/data/XML-Parser-Validate-Regexp_4.xsd b/defensive-coding/src/data/XML-Parser-Validate-Regexp_4.xsd new file mode 100644 index 0000000..7c2eba4 --- /dev/null +++ b/defensive-coding/src/data/XML-Parser-Validate-Regexp_4.xsd @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/defensive-coding/src/data/XML-Parser-XInclude-File.xml b/defensive-coding/src/data/XML-Parser-XInclude-File.xml new file mode 100644 index 0000000..e6fc009 --- /dev/null +++ b/defensive-coding/src/data/XML-Parser-XInclude-File.xml @@ -0,0 +1,5 @@ + + + + diff --git a/defensive-coding/src/data/XML-Parser-XInclude-URL.xml b/defensive-coding/src/data/XML-Parser-XInclude-URL.xml new file mode 100644 index 0000000..3afe285 --- /dev/null +++ b/defensive-coding/src/data/XML-Parser-XInclude-URL.xml @@ -0,0 +1,5 @@ + + + + diff --git a/defensive-coding/src/data/XML-Parser-XSD-File.xml b/defensive-coding/src/data/XML-Parser-XSD-File.xml new file mode 100644 index 0000000..f12aba4 --- /dev/null +++ b/defensive-coding/src/data/XML-Parser-XSD-File.xml @@ -0,0 +1,4 @@ + + + diff --git a/defensive-coding/src/data/XML-Parser-XSD-Include_File.xml b/defensive-coding/src/data/XML-Parser-XSD-Include_File.xml new file mode 100644 index 0000000..0443d70 --- /dev/null +++ b/defensive-coding/src/data/XML-Parser-XSD-Include_File.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/defensive-coding/src/data/XML-Parser-XSD-Include_URL.xml b/defensive-coding/src/data/XML-Parser-XSD-Include_URL.xml new file mode 100644 index 0000000..282fb87 --- /dev/null +++ b/defensive-coding/src/data/XML-Parser-XSD-Include_URL.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/defensive-coding/src/data/XML-Parser-XSD-URL.xml b/defensive-coding/src/data/XML-Parser-XSD-URL.xml new file mode 100644 index 0000000..45df87f --- /dev/null +++ b/defensive-coding/src/data/XML-Parser-XSD-URL.xml @@ -0,0 +1,4 @@ + + + diff --git a/defensive-coding/src/src.mk b/defensive-coding/src/src.mk new file mode 100644 index 0000000..7987680 --- /dev/null +++ b/defensive-coding/src/src.mk @@ -0,0 +1,53 @@ +.PHONY: build-sources + +CC = gcc +CWARNFLAGS = -Wall -W -Wno-unused-parameter -Werror=implicit-function-declaration +CFLAGS = -std=gnu99 -O2 $(CWARNFLAGS) -g + +# List files which should only be compiled for syntax checking. +compile_only += C-Pointers-remaining +compile_only += C-Arithmetic-add +compile_only += C-Arithmetic-mult + +# List Java files which sould be compiled +compile_java += TLSClientOpenJDK + +# List fiels which will be compiled and linked, together with +# additional dependencies. +compile_and_link += C-String-Functions +compile_and_link += TLS-Client-OpenSSL +LIBS_TLS-Client-OpenSSL = -lssl -lcrypto +compile_and_link += TLS-Client-GNUTLS +LIBS_TLS-Client-GNUTLS = -lgnutls +compile_and_link += TLS-Client-NSS +CFLAGS_TLS-Client-NSS = -I/usr/include/nspr4 -I/usr/include/nss3 +LIBS_TLS-Client-NSS = -lnss3 -lnspr4 -lssl3 +compile_and_link += XML-Parser-Expat +LIBS_XML-Parser-Expat = -lexpat + +# Define preprocessor symbols if certain functions exist. +CHECK_FUNCTION = crypto/X509_check_host/-DHAVE_X509_CHECK_HOST \ + gnutls/gnutls_hash_fast/-DHAVE_GNUTLS_HASH_FAST +DEFINES := $(shell python src/check-function.py $(CHECK_FUNCTION)) + +CLASS_compile_java := $(patsubst %,src/%.class,$(compile_java)) +BIN_compile_and_link := $(patsubst %,src/%,$(compile_and_link)) + +build-src: $(patsubst %,src/%.o,$(compile_only)) $(CLASS_compile_java) \ + $(BIN_compile_and_link) + +clean-src: + -rm src/*.o src/*.class $(BIN_compile_and_link) + +src/%.o: src/%.c + $(CC) $(CFLAGS) $(DEFINES) $(CFLAGS_$(basename $(notdir $@))) -c $< -o $@ + +src/%.class: src/%.java + javac -source 1.6 -target 1.6 -Xlint:all $^ + +src/%: src/%.o + $(CC) $^ -o $@ $(LIBS_$(notdir $@)) + +src/TLS-Client-GNUTLS: src/tcp_connect.o +src/TLS-Client-OpenSSL: src/tcp_connect.o src/x509_check_host.o +src/TLS-Client-NSS: src/tcp_connect.o diff --git a/defensive-coding/src/tcp_connect.c b/defensive-coding/src/tcp_connect.c new file mode 100644 index 0000000..fe72b31 --- /dev/null +++ b/defensive-coding/src/tcp_connect.c @@ -0,0 +1,52 @@ +#include "tcp_connect.h" + +#include +#include +#include +#include +#include +#include +#include +#include + + +int +tcp_connect(const char *host, const char *service) +{ + // A real-world implementation should connect to one IPv4 and one + // IPv address in parallel, until a responsive server is found. + const struct addrinfo hints = { + .ai_family = AF_UNSPEC, + .ai_socktype = SOCK_STREAM, + }; + struct addrinfo *result; + int ret = getaddrinfo(host, service, &hints, &result); + if (ret != 0) { + fprintf(stderr, "error: name lookup failure for %s/%s: %s\n", + host, service, gai_strerror(ret)); + exit(1); + } + if (result == NULL) { + fprintf(stderr, "error: no addresses found for %s/%s\n", host, service); + freeaddrinfo(result); + return -1; + } + for (const struct addrinfo *ai = result; ai; ai = ai->ai_next) { + ret = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); + if (ret < 0) { + continue; + } + if (connect(ret, ai->ai_addr, ai->ai_addrlen) == 0) { + break; + } + int save = errno; + close(ret); + errno = save; + ret = -1; + } + if (ret < 0) { + return -1; + } + freeaddrinfo(result); + return ret; +} diff --git a/defensive-coding/src/tcp_connect.h b/defensive-coding/src/tcp_connect.h new file mode 100644 index 0000000..0234999 --- /dev/null +++ b/defensive-coding/src/tcp_connect.h @@ -0,0 +1,6 @@ +#pragma once + +/* Establishes a TCP connect to SERVICE at HOST and returns the socket + descriptor. Calls exit on error (and prints an error message). */ +int tcp_connect(const char *host, const char *service); + diff --git a/defensive-coding/src/x509_check_host.c b/defensive-coding/src/x509_check_host.c new file mode 100644 index 0000000..9797b56 --- /dev/null +++ b/defensive-coding/src/x509_check_host.c @@ -0,0 +1,355 @@ +// This file is based on a (currently patched) file from OpenSSL, +// namely crypto/x509v3/v3_utl.c. It is included here for testing +// purposes only. + +/* v3_utl.c */ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project. + */ +/* ==================================================================== + * Copyright (c) 1999-2003 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 HAVE_X509_CHECK_HOST + +#include +#include +#include + +/* Always check subject name for host match even if subject alt names present */ +#define X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT 0x1 +/* Disable wild-card matching for dnsName fields and common name. */ +#define X509_CHECK_FLAG_NO_WILDCARDS 0x2 + +typedef int (*equal_fn)(const unsigned char *pattern, size_t pattern_len, + const unsigned char *subject, size_t subject_len); + +/* Compare while ASCII ignoring case. */ +static int equal_nocase(const unsigned char *pattern, size_t pattern_len, + const unsigned char *subject, size_t subject_len) + { + if (pattern_len != subject_len) + return 0; + while (pattern_len) + { + unsigned char l = *pattern; + unsigned char r = *subject; + /* The pattern must not contain NUL characters. */ + if (l == 0) + return 0; + if (l != r) + { + if ('A' <= l && l <= 'Z') + l = (l - 'A') + 'a'; + if ('A' <= r && r <= 'Z') + r = (r - 'A') + 'a'; + if (l != r) + return 0; + } + ++pattern; + ++subject; + --pattern_len; + } + return 1; + } + +/* Compare using memcmp. */ +static int equal_case(const unsigned char *pattern, size_t pattern_len, + const unsigned char *subject, size_t subject_len) +{ + /* The pattern must not contain NUL characters. */ + if (memchr(pattern, '\0', pattern_len) != NULL) + return 0; + if (pattern_len != subject_len) + return 0; + return !memcmp(pattern, subject, pattern_len); +} + +/* RFC 5280, section 7.5, requires that only the domain is compared in + a case-insensitive manner. */ +static int equal_email(const unsigned char *a, size_t a_len, + const unsigned char *b, size_t b_len) + { + if (a_len != b_len) + return 0; + size_t i = a_len; + /* We search backwards for the '@' character, so that we do + not have to deal with quoted local-parts. The domain part + is compared in a case-insensitive manner. */ + while (i > 0) + { + --i; + if (a[i] == '@' || b[i] == '@') + { + if (!equal_nocase(a + i, a_len - i, + b + i, a_len - i)) + return 0; + break; + } + } + if (i == 0) + i = a_len; + return equal_case(a, i, b, i); + } + +/* Compare the prefix and suffix with the subject, and check that the + characters in-between are valid. */ +static int wildcard_match(const unsigned char *prefix, size_t prefix_len, + const unsigned char *suffix, size_t suffix_len, + const unsigned char *subject, size_t subject_len) + { + const unsigned char *wildcard_start; + const unsigned char *wildcard_end; + const unsigned char *p; + if (subject_len < prefix_len + suffix_len) + return 0; + if (!equal_nocase(prefix, prefix_len, subject, prefix_len)) + return 0; + wildcard_start = subject + prefix_len; + wildcard_end = subject + (subject_len - suffix_len); + if (!equal_nocase(wildcard_end, suffix_len, suffix, suffix_len)) + return 0; + /* The wildcard must match at least one character. */ + if (wildcard_start == wildcard_end) + return 0; + /* Check that the part matched by the wildcard contains only + permitted characters and only matches a single label. */ + for (p = wildcard_start; p != wildcard_end; ++p) + if (!(('0' <= *p && *p <= '9') || + ('A' <= *p && *p <= 'Z') || + ('a' <= *p && *p <= 'z') || + *p == '-')) + return 0; + return 1; + } + +/* Checks if the memory region consistens of [0-9A-Za-z.-]. */ +static int valid_domain_characters(const unsigned char *p, size_t len) + { + while (len) + { + if (!(('0' <= *p && *p <= '9') || + ('A' <= *p && *p <= 'Z') || + ('a' <= *p && *p <= 'z') || + *p == '-' || *p == '.')) + return 0; + ++p; + --len; + } + return 1; + } + +/* Find the '*' in a wildcard pattern. If no such character is found + or the pattern is otherwise invalid, returns NULL. */ +static const unsigned char *wildcard_find_star(const unsigned char *pattern, + size_t pattern_len) + { + const unsigned char *star = memchr(pattern, '*', pattern_len); + size_t dot_count = 0; + const unsigned char *suffix_start; + size_t suffix_length; + if (star == NULL) + return NULL; + suffix_start = star + 1; + suffix_length = (pattern + pattern_len) - (star + 1); + if (!(valid_domain_characters(pattern, star - pattern) && + valid_domain_characters(suffix_start, suffix_length))) + return NULL; + /* Check that the suffix matches at least two labels. */ + while (suffix_length) + { + if (*suffix_start == '.') + ++dot_count; + ++suffix_start; + --suffix_length; + } + if (dot_count < 2) + return NULL; + return star; + } + +/* Compare using wildcards. */ +static int equal_wildcard(const unsigned char *pattern, size_t pattern_len, + const unsigned char *subject, size_t subject_len) + { + const unsigned char *star; + /* Do not match IDNA names. */ + if (subject_len >=4 && memcmp(subject, "xn--", 4) == 0) + star = NULL; + else + star = wildcard_find_star(pattern, pattern_len); + if (star == NULL) + return equal_nocase(pattern, pattern_len, + subject, subject_len); + return wildcard_match(pattern, star - pattern, + star + 1, (pattern + pattern_len) - star - 1, + subject, subject_len); + } + +/* Compare an ASN1_STRING to a supplied string. If they match + * return 1. If cmp_type > 0 only compare if string matches the + * type, otherwise convert it to UTF8. + */ + +static int do_check_string(ASN1_STRING *a, int cmp_type, equal_fn equal, + const unsigned char *b, size_t blen) + { + if (!a->data || !a->length) + return 0; + if (cmp_type > 0) + { + if (cmp_type != a->type) + return 0; + if (cmp_type == V_ASN1_IA5STRING) + return equal(a->data, a->length, b, blen); + if (a->length == (int)blen && !memcmp(a->data, b, blen)) + return 1; + else + return 0; + } + else + { + int astrlen, rv; + unsigned char *astr; + astrlen = ASN1_STRING_to_UTF8(&astr, a); + if (astrlen < 0) + return 0; + rv = equal(astr, astrlen, b, blen); + OPENSSL_free(astr); + return rv; + } + } + +static int do_x509_check(X509 *x, const unsigned char *chk, size_t chklen, + unsigned int flags, int check_type) + { + GENERAL_NAMES *gens = NULL; + X509_NAME *name = NULL; + int i; + int cnid; + int alt_type; + equal_fn equal; + if (check_type == GEN_EMAIL) + { + cnid = NID_pkcs9_emailAddress; + alt_type = V_ASN1_IA5STRING; + equal = equal_email; + } + else if (check_type == GEN_DNS) + { + cnid = NID_commonName; + alt_type = V_ASN1_IA5STRING; + if (flags & X509_CHECK_FLAG_NO_WILDCARDS) + equal = equal_nocase; + else + equal = equal_wildcard; + } + else + { + cnid = 0; + alt_type = V_ASN1_OCTET_STRING; + equal = equal_case; + } + + if (chklen == 0) + chklen = strlen((const char *)chk); + + gens = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL); + if (gens) + { + int rv = 0; + for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) + { + GENERAL_NAME *gen; + ASN1_STRING *cstr; + gen = sk_GENERAL_NAME_value(gens, i); + if(gen->type != check_type) + continue; + if (check_type == GEN_EMAIL) + cstr = gen->d.rfc822Name; + else if (check_type == GEN_DNS) + cstr = gen->d.dNSName; + else + cstr = gen->d.iPAddress; + if (do_check_string(cstr, alt_type, equal, chk, chklen)) + { + rv = 1; + break; + } + } + GENERAL_NAMES_free(gens); + if (rv) + return 1; + if (!(flags & X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT) || !cnid) + return 0; + } + i = -1; + name = X509_get_subject_name(x); + while((i = X509_NAME_get_index_by_NID(name, cnid, i)) >= 0) + { + X509_NAME_ENTRY *ne; + ASN1_STRING *str; + ne = X509_NAME_get_entry(name, i); + str = X509_NAME_ENTRY_get_data(ne); + if (do_check_string(str, -1, equal, chk, chklen)) + return 1; + } + return 0; + } + +int X509_check_host(X509 *x, const unsigned char *chk, size_t chklen, + unsigned int flags) + { + return do_x509_check(x, chk, chklen, flags, GEN_DNS); + } +#endif diff --git a/defensive-coding/tmp/en-US/html/Common_Content/css/common.css b/defensive-coding/tmp/en-US/html/Common_Content/css/common.css new file mode 100644 index 0000000..d7dc3f2 --- /dev/null +++ b/defensive-coding/tmp/en-US/html/Common_Content/css/common.css @@ -0,0 +1,1528 @@ +* { + widows: 2 !important; + orphans: 2 !important; +} + +body, h1, h2, h3, h4, h5, h6, pre, li, div { + line-height: 1.29em; +} + +body { + background-color: white; + margin:0 auto; + font-family: "liberation sans", "Myriad ", "Bitstream Vera Sans", "Lucida Grande", "Luxi Sans", "Trebuchet MS", helvetica, verdana, arial, sans-serif; + font-size:12px; + max-width:55em; + color:black; +} + +body.toc_embeded { + /*for web hosting system only*/ + margin-left: 300px; +} + +object.toc, iframe.toc { + /*for web hosting system only*/ + border-style:none; + position:fixed; + width:290px; + height:99.99%; + top:0; + left:0; + z-index: 100; + border-style:none; + border-right:1px solid #999; +} + +/* Hide web menu */ + +body.notoc { + margin-left: 3em; +} + +iframe.notoc { + border-style:none; + border: none; + padding: 0em; + position:fixed; + width: 21px; + height: 29px; + top: 0px; + left:0; + overflow: hidden; + margin: 0em; + margin-left: -3px; +} +/* End hide web menu */ + +/* desktop styles */ +body.desktop { + margin-left: 26em; +} + +body.desktop .book > .toc { + display:block; + width:24em; + height:99%; + position:fixed; + overflow:auto; + top:0px; + left:0px; + padding-left:1em; + background-color:#EEEEEE; +} + +.toc { + line-height:1.35em; +} + +.toc .glossary, +.toc .chapter, .toc .appendix { + margin-top:1em; +} + +.toc .part { + margin-top:1em; + display:block; +} + +span.glossary, +span.appendix { + display:block; + margin-top:0.5em; +} + +div { + padding-top:0px; +} + +div.section { + padding-top:1em; +} + +p, div.para, div.formalpara { + padding-top:0px; + margin-top:0.3em; + padding-bottom:0px; + margin-bottom:1em; +} + +/*Links*/ +a { + outline: none; +} + +a:link { + text-decoration:none; + border-bottom: 1px dotted ; + color:#3366cc; +} + +a:visited { + text-decoration:none; + border-bottom: 1px dotted ; + color:#003366; +} + +div.longdesc-link { + float:right; + color:#999; +} + +.toc a, .qandaset a { + font-weight:normal; + border:none; +} + +.toc a:hover, .qandaset a:hover +{ + border-bottom: 1px dotted; +} + +/*headings*/ +h1, h2, h3, h4, h5, h6 { + color: #336699; + margin-top: 0em; + margin-bottom: 0em; + background-color: transparent; + page-break-inside: avoid; + page-break-after: avoid; +} + +h1 { + font-size:2.0em; +} + +.titlepage h1.title { + font-size: 3.0em; + padding-top: 1em; + text-align:left; +} + +.book > .titlepage h1.title { + text-align:center; +} + +.article > .titlepage h1.title { + text-align:center; +} + +.set .titlepage > div > div > h1.title { + text-align:center; +} + +.producttitle { + margin-top: 0em; + margin-bottom: 0em; + font-size: 3.0em; + font-weight: bold; + background: #003d6e url(../images/h1-bg.png) top left repeat-x; + color: white; + text-align: center; + padding: 0.7em; +} + +.titlepage .corpauthor { + margin-top: 1em; + text-align: center; +} + +.section h1.title { + font-size: 1.6em; + padding: 0em; + color: #336699; + text-align: left; + background: white; +} + +h2 { + font-size:1.6em; +} + + +h2.subtitle, h3.subtitle { + margin-top: 1em; + margin-bottom: 1em; + font-size: 1.4em; + text-align: center; +} + +.preface > div > div > div > h2.title { + margin-top: 1em; + font-size: 2.0em; +} + +.appendix h2 { + margin-top: 1em; + font-size: 2.0em; +} + + + +h3 { + font-size:1.3em; + padding-top:0em; + padding-bottom:0em; +} +h4 { + font-size:1.1em; + padding-top:0em; + padding-bottom:0em; +} + +h5 { + font-size:1em; +} + +h6 { + font-size:1em; +} + +h5.formalpara { + font-size:1em; + margin-top:2em; + margin-bottom:.8em; +} + +.abstract h6 { + margin-top:1em; + margin-bottom:.5em; + font-size:2em; +} + +/*element rules*/ +hr { + border-collapse: collapse; + border-style:none; + border-top: 1px dotted #ccc; + width:100%; + margin-top: 3em; +} + +/* web site rules */ +ul.languages, .languages li { + display:inline; + padding:0em; +} + +.languages li a { + padding:0em .5em; + text-decoration: none; +} + +.languages li p, .languages li div.para { + display:inline; +} + +.languages li a:link, .languages li a:visited { + color:#444; +} + +.languages li a:hover, .languages li a:focus, .languages li a:active { + color:black; +} + +ul.languages { + display:block; + background-color:#eee; + padding:.5em; +} + +/*supporting stylesheets*/ + +/*unique to the webpage only*/ +.books { + position:relative; +} + +.versions li { + width:100%; + clear:both; + display:block; +} + +a.version { + font-size:2em; + text-decoration:none; + width:100%; + display:block; + padding:1em 0em .2em 0em; + clear:both; +} + +a.version:before { + content:"Version"; + font-size:smaller; +} + +a.version:visited, a.version:link { + color:#666; +} + +a.version:focus, a.version:hover { + color:black; +} + +.books { + display:block; + position:relative; + clear:both; + width:100%; +} + +.books li { + display:block; + width:200px; + float:left; + position:relative; + clear: none ; +} + +.books .html { + width:170px; + display:block; +} + +.books .pdf { + position:absolute; + left:170px; + top:0px; + font-size:smaller; +} + +.books .pdf:link, .books .pdf:visited { + color:#555; +} + +.books .pdf:hover, .books .pdf:focus { + color:#000; +} + +.books li a { + text-decoration:none; +} + +.books li a:hover { + color:black; +} + +/*products*/ +.products li { + display: block; + width:300px; + float:left; +} + +.products li a { + width:300px; + padding:.5em 0em; +} + +.products ul { + clear:both; +} + +/*revision history*/ +.revhistory { + display:block; +} + +.revhistory table { + background-color:transparent; + border-color:#fff; + padding:0em; + margin: 0; + border-collapse:collapse; + border-style:none; +} + +.revhistory td { + text-align :left; + padding:0em; + border: none; + border-top: 1px solid #fff; + font-weight: bold; +} + +.revhistory .simplelist td { + font-weight: normal; +} + +.revhistory .simplelist { + margin-bottom: 1.5em; + margin-left: 1em; +} + +.revhistory table th { + display: none; +} + + +/*credits*/ +.authorgroup div { + clear:both; + text-align: center; +} + +h3.author { + margin: 0em; + padding: 0em; + padding-top: 1em; +} + +.authorgroup h4 { + padding: 0em; + margin: 0em; + padding-top: 1em; + margin-top: 1em; +} + +.author, +.editor, +.translator, +.othercredit, +.contrib { + display: block; +} + +.revhistory .author { + display: inline; +} + +.othercredit h3 { + padding-top: 1em; +} + + +.othercredit { + margin:0em; + padding:0em; +} + +.releaseinfo { + clear: both; +} + +.copyright { + margin-top: 1em; +} + +/* qanda sets */ +.answer { + margin-bottom:1em; + border-bottom:1px dotted #ccc; +} + +.qandaset .toc { + border-bottom:1px dotted #ccc; +} + +.question { + font-weight:bold; +} + +.answer .data, .question .data { + padding-left: 2.6em; +} + +.answer label, .question label { + float:left; + font-weight:bold; +} + +/* inline syntax highlighting */ +.perl_Alert { + color: #0000ff; +} + +.perl_BaseN { + color: #007f00; +} + +.perl_BString { + color: #5C3566; +} + +.perl_Char { + color: #ff00ff; +} + +.perl_Comment { + color: #FF00FF; +} + + +.perl_DataType { + color: #0000ff; +} + + +.perl_DecVal { + color: #00007f; +} + + +.perl_Error { + color: #ff0000; +} + + +.perl_Float { + color: #00007f; +} + + +.perl_Function { + color: #007f00; +} + + +.perl_IString { + color: #5C3566; +} + + +.perl_Keyword { + color: #002F5D; +} + + +.perl_Operator { + color: #ffa500; +} + + +.perl_Others { + color: #b03060; +} + + +.perl_RegionMarker { + color: #96b9ff; +} + + +.perl_Reserved { + color: #9b30ff; +} + + +.perl_String { + color: #5C3566; +} + + +.perl_Variable { + color: #0000ff; +} + + +.perl_Warning { + color: #0000ff; +} + +/*Lists*/ +ul { + padding-left:1.6em; + list-style-image:url(../images/dot.png); + list-style-type: circle; +} + +ul ul { + list-style-image:url(../images/dot2.png); + list-style-type: circle; +} + +ol { + list-style-image:none; + list-style-type: decimal; +} + +ol ol { + list-style-type: lower-alpha; +} + +ol.arabic { + list-style-type: decimal; +} + +ol.loweralpha { + list-style-type: lower-alpha; +} + +ol.lowerroman { + list-style-type: lower-roman; +} + +ol.upperalpha { + list-style-type: upper-alpha; +} + +ol.upperroman { + list-style-type: upper-roman; +} + +dt { + font-weight:bold; + margin-bottom:0em; + padding-bottom:0em; +} + +dd { + margin:0em; + margin-left:2em; + padding-top:0em; + padding-bottom: 1em; +} + +li { + padding-top:0px; + margin-top:0em; + padding-bottom:0px; + margin-bottom:0.4em; +} + +li p, li div.para { + padding-top:0px; + margin-top:0em; + padding-bottom:0px; + margin-bottom:0.3em; +} + +/*images*/ +img { + display:block; + margin: 2em 0; +} + +.inlinemediaobject, .inlinemediaobject img { + display:inline; + margin:0em; +} + +.figure img { + display:block; + margin:0; + page-break-inside: avoid; +} + +.figure .title { + margin:0em; + margin-bottom:2em; + padding:0px; +} + +/*document modes*/ +.confidential { + background-color:#900; + color:White; + padding:.5em .5em; + text-transform:uppercase; + text-align:center; +} + +.longdesc-link { + display:none; +} + +.longdesc { + display:none; +} + +.prompt { + padding:0em .3em; +} + +/*user interface styles*/ +.screen .replaceable { +} + +.guibutton, .guilabel { + font-family: "liberation mono", "bitstream vera mono", "dejavu mono", monospace; + font-weight: bold; + white-space: nowrap; +} + +.example { + background-color: #ffffff; + border-left: 3px solid #aaaaaa; + padding-top: 1em; + padding-bottom: 0.1em; +} + +.example h6 { + padding-left: 10px; +} + +.example-contents { + padding-left: 10px; + background-color: #ffffff; +} + +.example-contents .para { +/* padding: 10px;*/ +} + +/*terminal/console text*/ +.computeroutput, +.option { + font-family:"liberation mono", "bitstream vera mono", "dejavu mono", monospace; + font-weight:bold; +} + +.replaceable { + font-family:"liberation mono", "bitstream vera mono", "dejavu mono", monospace; + font-style: italic; +} + +.command, .filename, .keycap, .classname, .literal { + font-family:"liberation mono", "bitstream vera mono", "dejavu mono", monospace; + font-weight:bold; +} + +/* no bold in toc */ +.toc * { + font-weight: inherit; +} + +pre { + font-family:"liberation mono", "bitstream vera mono", "dejavu mono", monospace; + display:block; + background-color: #f5f5f5; + color: #000000; + border: 1px solid #aaaaaa; + margin-bottom: 0.3em; + padding:.5em 1em; + white-space: pre-wrap; /* css-3 */ + white-space: -moz-pre-wrap !important; /* Mozilla, since 1999 */ + white-space: -pre-wrap; /* Opera 4-6 */ + white-space: -o-pre-wrap; /* Opera 7 */ + word-wrap: break-word; /* Internet Explorer 5.5+ */ + font-size: 0.9em; +} + +pre .replaceable, +pre .keycap { +} + +code { + font-family:"liberation mono", "bitstream vera mono", "dejavu mono", monospace; +/* white-space: nowrap;*/ + white-space: pre-wrap; + word-wrap: break-word; + font-weight:bold; +} + +.parameter code { + display: inline; + white-space: pre-wrap; /* css-3 */ + white-space: -moz-pre-wrap !important; /* Mozilla, since 1999 */ + white-space: -pre-wrap; /* Opera 4-6 */ + white-space: -o-pre-wrap; /* Opera 7 */ + word-wrap: break-word; /* Internet Explorer 5.5+ */ +} + +/*Notifications*/ +div.warning:before { + content:url(../images/warning.png); + padding-left: 5px; +} + +div.note:before { + content:url(../images/note.png); + padding-left: 5px; +} + +div.important:before { + content:url(../images/important.png); + padding-left: 5px; +} + +div.warning, div.note, div.important { + color: black; + margin: 0em; + padding: 0em; + background: none; + background-color: white; + margin-bottom: 1em; + border-bottom: 1px solid #aaaaaa; + page-break-inside: avoid; +} + +div.warning h2, div.note h2,div.important h2 { + margin: 0em; + padding: 0em; + color: #eeeeec; + padding-top: 0px; + padding-bottom: 0px; + height: 1.4em; + line-height: 1.4em; + font-size: 1.4em; + display:inline; +} + +div.admonition_header { + clear: both; + margin: 0em; + padding: 0em; + margin-top: -3.3em; + padding-left: 58px; + line-height: 1.0em; + font-size: 1.0em; +} + +div.warning div.admonition_header { + background: url(../images/red.png) top left repeat-x; + background-color: #590000; +} + +div.note div.admonition_header { + background: url(../images/green.png) top right repeat-x; + background-color: #597800; +} + +div.important div.admonition_header { + background: url(../images/yellow.png) top right repeat-x; + background-color: #a6710f; +} + +div.warning p, div.warning div.para, +div.note p, div.note div.para, +div.important p, div.important div.para { + padding: 0em; + margin: 0em; +} + +div.admonition { + border: none; + border-left: 1px solid #aaaaaa; + border-right: 1px solid #aaaaaa; + padding:0em; + margin:0em; + padding-top: 1.5em; + padding-bottom: 1em; + padding-left: 2em; + padding-right: 1em; + background-color: #eeeeec; + -moz-border-radius: 0px; + -webkit-border-radius: 0px; + border-radius: 0px; +} + +/*Page Title*/ +#title { + display:block; + height:45px; + padding-bottom:1em; + margin:0em; +} + +#title a.left{ + display:inline; + border:none; +} + +#title a.left img{ + border:none; + float:left; + margin:0em; + margin-top:.7em; +} + +#title a.right { + padding-bottom:1em; +} + +#title a.right img { + border:none; + float:right; + margin:0em; + margin-top:.7em; +} + +/*Table*/ +div.table { + page-break-inside: avoid; +} + +table { + border:1px solid #6c614b; + width:100%; + border-collapse:collapse; +} + +table.simplelist, .calloutlist table { + border-style: none; +} + +table th { + text-align:left; + background-color:#6699cc; + padding:.3em .5em; + color:white; +} + +table td { + padding:.15em .5em; +} + +table tr.even td { + background-color:#f5f5f5; +} + +table th p:first-child, table td p:first-child, table li p:first-child, +table th div.para:first-child, table td div.para:first-child, table li div.para:first-child { + margin-top:0em; + padding-top:0em; + display:inline; +} + +th, td { + border-style:none; + vertical-align: top; + border: 1px solid #000; +} + +.simplelist th, .simplelist td { + border: none; +} + +table table td { + border-bottom:1px dotted #aaa; + background-color:white; + padding:.6em 0em; +} + +table table { + border:1px solid white; +} + +td.remarkval { + color:#444; +} + +td.fieldval { + font-weight:bold; +} + +.lbname, .lbtype, .lbdescr, .lbdriver, .lbhost { + color:white; + font-weight:bold; + background-color:#999; + width:120px; +} + +td.remarkval { + width:230px; +} + +td.tname { + font-weight:bold; +} + +th.dbfield { + width:120px; +} + +th.dbtype { + width:70px; +} + +th.dbdefault { + width:70px; +} + +th.dbnul { + width:70px; +} + +th.dbkey { + width:70px; +} + +span.book { + margin-top:4em; + display:block; + font-size:11pt; +} + +span.book a{ + font-weight:bold; +} +span.chapter { + display:block; + margin-top:0.5em; +} + +table.simplelist td, .calloutlist table td { + border-style: none; +} + +/*Breadcrumbs*/ +#breadcrumbs ul li.first:before { + content:" "; +} + +#breadcrumbs { + color:#900; + padding:3px; + margin-bottom:25px; +} + +#breadcrumbs ul { + margin-left:0; + padding-left:0; + display:inline; + border:none; +} + +#breadcrumbs ul li { + margin-left:0; + padding-left:2px; + border:none; + list-style:none; + display:inline; +} + +#breadcrumbs ul li:before { + content:"\0020 \0020 \0020 \00BB \0020"; + color:#333; +} + +/*index*/ +.glossary h3, +.index h3 { + font-size: 2em; + color:#aaa; + margin:0em; +} + +.indexdiv { + margin-bottom:1em; +} + +.glossary dt, +.index dt { + color:#444; + padding-top:.5em; +} + +.glossary dl dl dt, +.index dl dl dt { + color:#777; + font-weight:normal; + padding-top:0em; +} + +.index dl dl dt:before { + content:"- "; + color:#ccc; +} + +/*changes*/ +.footnote { + font-size: .7em; + margin:0em; + color:#222; +} + +table .footnote { +} + +sup { + color:#999; + margin:0em; + padding:0em; + line-height: .4em; + font-size: 1em; + padding-left:0em; +} + +.footnote { + position:relative; +} + +.footnote sup { + color:#e3dcc0; + position:absolute; + left: .4em; +} + +.footnote sup a:link, +.footnote sup a:visited { + color:#92917d; + text-decoration:none; +} + +.footnote:hover sup a { + text-decoration:none; +} + +.footnote p,.footnote div.para { + padding-left:2em; +} + +.footnote a:link, +.footnote a:visited { + color:#00537c; +} + +.footnote a:hover { +} + +/**/ +div.chapter { + margin-top:3em; + page-break-inside: avoid; +} + +div.preface { + page-break-inside: avoid; +} + +div.section { + margin-top:1em; + page-break-inside: auto; +} + +div.note .replaceable, +div.important .replaceable, +div.warning .replaceable, +div.note .keycap, +div.important .keycap, +div.warning .keycap +{ +} + +ul li p:last-child, ul li div.para:last-child { + margin-bottom:0em; + padding-bottom:0em; +} + +/*document navigation*/ +.docnav a, .docnav strong { + border:none; + text-decoration:none; + font-weight:normal; +} + +.docnav { + list-style:none; + margin:0em; + padding:0em; + position:relative; + width:100%; + padding-bottom:2em; + padding-top:1em; + border-top:1px dotted #ccc; +} + +.docnav li { + list-style:none; + margin:0em; + padding:0em; + display:inline; + font-size:.8em; +} + +.docnav li:before { + content:" "; +} + +.docnav li.previous, .docnav li.next { + position:absolute; + top:1em; +} + +.docnav li.up, .docnav li.home { + margin:0em 1.5em; +} + +.docnav li.previous { + left:0px; + text-align:left; +} + +.docnav li.next { + right:0px; + text-align:right; +} + +.docnav li.previous strong, .docnav li.next strong { + height:22px; + display:block; +} + +.docnav { + margin:0 auto; + text-align:center; +} + +.docnav li.next a strong { + background: url(../images/stock-go-forward.png) top right no-repeat; + padding-top:3px; + padding-bottom:4px; + padding-right:28px; + font-size:1.2em; +} + +.docnav li.previous a strong { + background: url(../images/stock-go-back.png) top left no-repeat; + padding-top:3px; + padding-bottom:4px; + padding-left:28px; + padding-right:0.5em; + font-size:1.2em; +} + +.docnav li.home a strong { + background: url(../images/stock-home.png) top left no-repeat; + padding:5px; + padding-left:28px; + font-size:1.2em; +} + +.docnav li.up a strong { + background: url(../images/stock-go-up.png) top left no-repeat; + padding:5px; + padding-left:28px; + font-size:1.2em; +} + +.docnav a:link, .docnav a:visited { + color:#666; +} + +.docnav a:hover, .docnav a:focus, .docnav a:active { + color:black; +} + +.docnav a { + max-width: 10em; + overflow:hidden; +} + +.docnav a:link strong { + text-decoration:none; +} + +.docnav { + margin:0 auto; + text-align:center; +} + +ul.docnav { + margin-bottom: 1em; +} +/* Reports */ +.reports ul { + list-style:none; + margin:0em; + padding:0em; +} + +.reports li{ + margin:0em; + padding:0em; +} + +.reports li.odd { + background-color: #eeeeee; + margin:0em; + padding:0em; +} + +.reports dl { + display:inline; + margin:0em; + padding:0em; + float:right; + margin-right: 17em; + margin-top:-1.3em; +} + +.reports dt { + display:inline; + margin:0em; + padding:0em; +} + +.reports dd { + display:inline; + margin:0em; + padding:0em; + padding-right:.5em; +} + +.reports h2, .reports h3{ + display:inline; + padding-right:.5em; + font-size:10pt; + font-weight:normal; +} + +.reports div.progress { + display:inline; + float:right; + width:16em; + background:#c00 url(../images/shine.png) top left repeat-x; + margin:0em; + margin-top:-1.3em; + padding:0em; + border:none; +} + +/*uniform*/ +body.results, body.reports { + max-width:57em ; + padding:0em; +} + +/*Progress Bar*/ +div.progress { + display:block; + float:left; + width:16em; + background:#c00 url(../images/shine.png) top left repeat-x; + height:1em; +} + +div.progress span { + height:1em; + float:left; +} + +div.progress span.translated { + background:#6c3 url(../images/shine.png) top left repeat-x; +} + +div.progress span.fuzzy { + background:#ff9f00 url(../images/shine.png) top left repeat-x; +} + + +/*Results*/ + +.results ul { + list-style:none; + margin:0em; + padding:0em; +} + +.results li{ + margin:0em; + padding:0em; +} + +.results li.odd { + background-color: #eeeeee; + margin:0em; + padding:0em; +} + +.results dl { + display:inline; + margin:0em; + padding:0em; + float:right; + margin-right: 17em; + margin-top:-1.3em; +} + +.results dt { + display:inline; + margin:0em; + padding:0em; +} + +.results dd { + display:inline; + margin:0em; + padding:0em; + padding-right:.5em; +} + +.results h2, .results h3 { + display:inline; + padding-right:.5em; + font-size:10pt; + font-weight:normal; +} + +.results div.progress { + display:inline; + float:right; + width:16em; + background:#c00 url(../images/shine.png) top left repeat-x; + margin:0em; + margin-top:-1.3em; + padding:0em; + border:none; +} + +/* Dirty EVIL Mozilla hack for round corners */ +pre { + -moz-border-radius:11px; + -webkit-border-radius:11px; + border-radius: 11px; + page-break-inside: avoid; +} + +.example { + -moz-border-radius:0px; + -webkit-border-radius:0px; + border-radius: 0px; + page-break-inside: avoid; +} + +.package, .citetitle { + font-style: italic; +} + +.titlepage .edition { + color: #336699; + background-color: transparent; + margin-top: 1em; + margin-bottom: 1em; + font-size: 1.4em; + font-weight: bold; + text-align: center; +} + +span.remark { + background-color: #ff00ff; +} + +.draft { + background-image: url(../images/watermark-draft.png); + background-repeat: repeat-y; + background-position: center; +} + +.foreignphrase { + font-style: inherit; +} + +dt { + clear:both; +} + +dt img { + border-style: none; + max-width: 112px; +} + +dt object { + max-width: 112px; +} + +dt .inlinemediaobject, dt object { + display: inline; + float: left; + margin-bottom: 1em; + padding-right: 1em; + width: 112px; +} + +dl:after { + display: block; + clear: both; + content: ""; +} + +.toc dd { + padding-bottom: 0em; + margin-bottom: 1em; + padding-left: 1.3em; + margin-left: 0em; +} + +div.toc > dl > dt { + padding-bottom: 0em; + margin-bottom: 0em; + margin-top: 1em; +} + + +.strikethrough { + text-decoration: line-through; +} + +.underline { + text-decoration: underline; +} + +.calloutlist img, .callout { + padding: 0em; + margin: 0em; + width: 12pt; + display: inline; + vertical-align: middle; +} + +.stepalternatives { + list-style-image: none; + list-style-type: none; +} + + diff --git a/defensive-coding/tmp/en-US/html/Common_Content/css/default.css b/defensive-coding/tmp/en-US/html/Common_Content/css/default.css new file mode 100644 index 0000000..bf38ebb --- /dev/null +++ b/defensive-coding/tmp/en-US/html/Common_Content/css/default.css @@ -0,0 +1,3 @@ +@import url("common.css"); +@import url("overrides.css"); +@import url("lang.css"); diff --git a/defensive-coding/tmp/en-US/html/Common_Content/css/lang.css b/defensive-coding/tmp/en-US/html/Common_Content/css/lang.css new file mode 100644 index 0000000..81c3115 --- /dev/null +++ b/defensive-coding/tmp/en-US/html/Common_Content/css/lang.css @@ -0,0 +1,2 @@ +/* place holder */ + diff --git a/defensive-coding/tmp/en-US/html/Common_Content/css/overrides.css b/defensive-coding/tmp/en-US/html/Common_Content/css/overrides.css new file mode 100644 index 0000000..bd5f3c7 --- /dev/null +++ b/defensive-coding/tmp/en-US/html/Common_Content/css/overrides.css @@ -0,0 +1,47 @@ +a:link { + color:#0066cc; +} + +a:visited { + color:#6699cc; +} + +h1 { + color:#a70000; +} + +.producttitle { + background: #a70000 url(../images/h1-bg.png) top left repeat; +} + +.section h1.title { + color:#a70000; +} + +h2,h3,h4,h5,h6 { + color:#a70000; +} + +table { + border:1px solid #aaa; +} + +table th { + background-color:#900; +} + +table tr.even td { + background-color:#f5f5f5; +} + +.revhistory table th { + color:#a70000; +} + +.titlepage .edition { + color: #a70000; +} + +span.remark{ + background-color: #ffff00; +} diff --git a/defensive-coding/tmp/en-US/html/Common_Content/css/print.css b/defensive-coding/tmp/en-US/html/Common_Content/css/print.css new file mode 100644 index 0000000..773d8ae --- /dev/null +++ b/defensive-coding/tmp/en-US/html/Common_Content/css/print.css @@ -0,0 +1,16 @@ +@import url("common.css"); +@import url("overrides.css"); +@import url("lang.css"); + +#tocframe { + display: none; +} + +body.toc_embeded { + margin-left: 30px; +} + +.producttitle { + color: #336699; +} + diff --git a/defensive-coding/tmp/en-US/html/Common_Content/images/1.png b/defensive-coding/tmp/en-US/html/Common_Content/images/1.png new file mode 100644 index 0000000000000000000000000000000000000000..270707b882810bd175124ce2126ebf7ea889a9b8 GIT binary patch literal 640 zcmV-`0)PF9P)iSFE1%=ZcYLoX4|lm0%nJMFyc78JwE1L z5U^A#ao=v|5lFD&LvZkDOA%h}?J?+f`EztcyI#*F5NE~Dg4K)%6VZO3-@Z?2Yl}{^ z$-3|76^K|)*3E~~?R4lgo2GT{!!%Q%ki-S<7RZfQPf8&7l+KZe6$uRBY*F+$D-tke zRBHkJR=i|O9LMIMIGwXVHD0Qv>VZI{PW}??u{1o@#EzTV2V6J=!a2Z0({~~%fvW1Q zfCuzu2=57aS;cAQPFPdD5U4PlFABa literal 0 HcmV?d00001 diff --git a/defensive-coding/tmp/en-US/html/Common_Content/images/1.svg b/defensive-coding/tmp/en-US/html/Common_Content/images/1.svg new file mode 100644 index 0000000..0a7036e --- /dev/null +++ b/defensive-coding/tmp/en-US/html/Common_Content/images/1.svg @@ -0,0 +1,27 @@ + + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/html/Common_Content/images/10.png b/defensive-coding/tmp/en-US/html/Common_Content/images/10.png new file mode 100644 index 0000000000000000000000000000000000000000..ec548f3f3d682ee8fcecf664b23d75e1ff3fe640 GIT binary patch literal 942 zcmV;f15x~mP)wBfU#9dg&s9u;*4%L9EkiZtCv6T;t&Xje4nUplrW4NL za#7)SW3k%}>&q`*#M#w_-RU$NqFwbc1|YrE@}xK%+?bf)&gv?+zkTC;ON*|)?A$pz z-@W7B))qGx7PudY&^A472CDPW0Q^E+!(g3PxZQLwEm8mYvDsJA76?$&*$Gmz6AA%v z>ET1JzkF%byixVi1E@QkPR^blZY?iU)!fW}Bw}cOwy6nccQ*hZo;+dx>Qz3CjR8!D*Wrv_6w_#;N1GWnn_z?*3ab(00pzgsD_jkV^fXz2=(u3P<)ZV>o)J^ls zJ`3t{TYY`?iul?ZTl4c=>F+lLD6g#rAi2BCK{N_Ld~HpuKXduAA$R7*VpN!|t+_e) z!**@2sR1Cdy{(lU#9|!A<7ogDun>TvB$G)1tPaOfp%4f~N!S17u*(M6Cn4Go!S!2ge6CsSIGc-;iH{36K{vhrIr0!UoRM7u^52$sVP#41OTqVL4?(c zYiI~ahi7AU)~K82r2(X1rWk;OXq460uK{Qp9mTV^M}yA?KzMwdgP%Y1`eb`)0BRZ) zDh6W3=i~G9=OlM_u-I%Qwzv86;swjY!$!?R*(sauI93meKrs*iLQ!zk*Aowik*Snf zGf#G^mX{Aq3b9D>DcIi>^h&AQar5>81qOlGKQND}W9yU$;E^&czzZZ!&^#f)Ym}TC z?u30(z8BET$^40!Sw3hAkbzL36$qAK9#o*!%pCsri%G6d?P~Tfb?Ud{-#POw>BGk4 Qy8r+H07*qoM6N<$g1JJft^fc4 literal 0 HcmV?d00001 diff --git a/defensive-coding/tmp/en-US/html/Common_Content/images/10.svg b/defensive-coding/tmp/en-US/html/Common_Content/images/10.svg new file mode 100644 index 0000000..d1c32c7 --- /dev/null +++ b/defensive-coding/tmp/en-US/html/Common_Content/images/10.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/html/Common_Content/images/11.png b/defensive-coding/tmp/en-US/html/Common_Content/images/11.png new file mode 100644 index 0000000000000000000000000000000000000000..f59d84b46e58c303ecc1af40c008d4628398de5e GIT binary patch literal 741 zcmV(%B=XYM8q6WeG>1bGnYRbJ=Ksc9Ua%02I z(Z;9=>`{5qq_A+M<-tbAE8ZvslcrQYoJ&9S&0}6!?94iC5QK5vZ~L zD*$l5zu&alujAu?KZIyYVBp8GRp6|T+#2g%38eZcP-E2uZeg!qbStYSpxUTxANW~o z%Vs-{)j^Tyu|UMysx|ZjaUoLNy#;HQbW}>)j@z&gXs`+tdjK!0+O{+ZM5H_w5Ctk- zgjWPaotjg}op4FYq<}@b^CXIH{h+HrRYHRxknRAU)*$Exhx`6vQlEi+n)NaRKaT$Z XA5h?O1!Vg;00000NkvXXu0mjfvUEnC literal 0 HcmV?d00001 diff --git a/defensive-coding/tmp/en-US/html/Common_Content/images/11.svg b/defensive-coding/tmp/en-US/html/Common_Content/images/11.svg new file mode 100644 index 0000000..872d14a --- /dev/null +++ b/defensive-coding/tmp/en-US/html/Common_Content/images/11.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/html/Common_Content/images/12.png b/defensive-coding/tmp/en-US/html/Common_Content/images/12.png new file mode 100644 index 0000000000000000000000000000000000000000..c8a39069a0098758364ed518985987e56fd93aa8 GIT binary patch literal 943 zcmV;g15o^lP)FhH#YFh%;<&qS^F9Q`10~)NU)x=Dl0L!wE^(%;Y0pxZtiO!rq^+b#ljVv4Pi90 zHayI`2M_)k6KG&18u*FaT*?LqiBC`GyUWEyLj!VmH&k~&D<%dKGBPM18Y0PT=Ew9j z&e~eM9?yOuepcWbZ~_&P!sAj?DRVeTEi7bvZH=jp4iZcz5=xDqvj$tV2F>8G-NKYWQ*uB zijh>8k)|H73E|}6CD^|-YL!xT;%d$TBeVkULx8)L+$w1d)JwT2zzTR{2=@xG>J_KD zCt;(MBLZrP%}BUI)q^1o?3pk^DKHuZeAEb~q2TbpKTLvkWKXlh)RDiA{{jL7HwE<~ Rj5GiM002ovPDHLkV1k^as9gX6 literal 0 HcmV?d00001 diff --git a/defensive-coding/tmp/en-US/html/Common_Content/images/12.svg b/defensive-coding/tmp/en-US/html/Common_Content/images/12.svg new file mode 100644 index 0000000..6bc95d2 --- /dev/null +++ b/defensive-coding/tmp/en-US/html/Common_Content/images/12.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/html/Common_Content/images/13.png b/defensive-coding/tmp/en-US/html/Common_Content/images/13.png new file mode 100644 index 0000000000000000000000000000000000000000..2db67434a4ed1be635b63a962a035ad3e7e25f23 GIT binary patch literal 983 zcmV;|11S87P)gqbm^tgT^AMBLN7{Ui_(Hcl2KPuSygsm%~Fi-39;7#r-6e&wekRrD^G74x|*eYlW$Cs z&k}SBaRz7u+FE3`C9IkIE{_k}ntp%bWBCV2)? z0sga6KFeExLjD9ODv&&bq=4gQA`AkQY44}-Ki4B_1&@9?4BJpy^OYtCs8C{SpqT+B z+XJ~G6xY-sgy7f21nJpX%{RN#Noidj2*Hn!ADJ1+nRkuZyF*_G+RQwx#l?7T-D2Ch za{xTuw~tsjJpWt!_fvoKCXR*%jZZ8b=JkaOBnAid;o1OIfVu?tgxHJ8J}+^(IP&tP zN^THmx3kIXMW#}Gd;gxfSPTG%*GogdbTZuvmsWsM;WVf`dX!`R{gmz5!|zDMR6ryc zB;3@*quN@Y)YsEpS;^>~I{=i{)nRu!4L;di*-3a%Z@7N@cGfx^d-@KW*csy6}$v|@$8Tx@vA$nPU z3$_^g{8DNvuAvTCp#_Nk1M;X6TLXiDMkz-G_yNP>6@a7wzgcr?S_#ie`AooZR%Rxm zx%$DJ0x}}3-~svyAn&t+Cl@*V?-vt2R_$u`FR|*k + + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/html/Common_Content/images/14.png b/defensive-coding/tmp/en-US/html/Common_Content/images/14.png new file mode 100644 index 0000000000000000000000000000000000000000..1a12fb322ceb98039b600cc9a10c44e6e5b18008 GIT binary patch literal 862 zcmV-k1EKthP)#=t+@`JuF6~ z8=;^NJ_-8jLocaM;e!Z1$i&A$6#s<22;qZn*pn0l1=626s*!bHjmp~Tp*y{Iceia$ zu`gU0=brQXes<2ezw{Q)>@?tvA3DH;vcYzkbtv&!L^@*in`M#9T3ymoX zS%P^X?g5X0+5+Ql0}monJ}C)cNeJ(6cnmZbXq>IM1-jd%Oco8WAVjN#dBAl<^NbV$ zk+78O1p}z&Pl1XO%`@5;5Xc2#08poWi_-sjwiF9AWiN-}GgR07xXl4vYHXc!0P1cx z-EcOq7rW0#S!JcUjS$#HG?cR8#iZWxU;iEFp=PVLxZXR zmA*cLi3Gt!f=i)Lt}Z%{1AsXp8p-jU+kHN6ZEoV}>@+pa$ma2IeRMQmw_4Rp51?i^ zoi4PsaeHeEM}0ltcX#swG)+%qF;2TdS}*Mqv}AXz^82wmoqSqa;^pArKZ9QG?d4)1 zKx$R15IR99nlIsx$Z^cddPbaYVV_ZJKh16qp#_^Bwo z9vRWKSzRvt{rv!ZTwLVK+FGumF#|vvmdoH_F#talg;&GFy0&w5b%y{83w)TJHH=Hc za_0BJCREF)?P36qsBLY@raO++gJS7~0ot{tnxP(;7b3>dOR#*3N2JtcTtgnPKsTVA zfVrZ^*2w_SE@e_c1TfFN#cN+cBv)~oGZTiTTo(}FcxFN|s|QU1G7uJM0^%i@$1Tug oW)A=R#Uxv&b~QUmo%-$g5BX61tekHiWdHyG07*qoM6N<$f_vzGG5`Po literal 0 HcmV?d00001 diff --git a/defensive-coding/tmp/en-US/html/Common_Content/images/14.svg b/defensive-coding/tmp/en-US/html/Common_Content/images/14.svg new file mode 100644 index 0000000..1009bce --- /dev/null +++ b/defensive-coding/tmp/en-US/html/Common_Content/images/14.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/html/Common_Content/images/15.png b/defensive-coding/tmp/en-US/html/Common_Content/images/15.png new file mode 100644 index 0000000000000000000000000000000000000000..2532d138f5c9a8d7bc77062a02c0c13400d28742 GIT binary patch literal 936 zcmV;Z16TZsP)3y4 z6GB`A?gCXQ#$5z%yQO@bl>m^))|ea)2T|b_`->K>yo4 zi6Rt~mm`GW$J!c^-Ce_;Us{SiFE7sjXE4ZaAYe7S%-LZT@D4?)*$WD&yLXQ>9UTBX zZ)jk1cGh^``t~i(nwmHP{?Sohc6C|Ji*6~aqYuUsj0;h#B0pMD!R475gIooNrX_r* zK$Xq~n07*ahl@dRb2AO&<2W>p(8dP&B_&A(_jr1 zacCM}JRaWk^(lkpI-S^Ze`o7=zn}2-w$b)?c9dhxTxJ1fRQP>7|$LF3s! zI?A@sNA1uM2*HW^dX<3HXvd~9W{cp54@O_A{~e`(=}gE@wzYAxwH5o3BLEz)uBOVA zF=vAw85Qp1!xy8aK67E8Hw;S7$n!}G~Ru_f1lveQrwsbOh)_04CrOl zV!8shU%zH&Wd&ig8RVh0H5P8&V!pduHDu9TvZZwxC4)oL$S*D?w7$;X)>bmt#D|eC zVw%iLu)o3UmNI6?jjIRj&>`(`Ivmp1{p)L_Q{O=bND-P{y_Ahbhx8q-?jXrK{af(6!0000< KMNUMnLSTZ0Qlx7D literal 0 HcmV?d00001 diff --git a/defensive-coding/tmp/en-US/html/Common_Content/images/15.svg b/defensive-coding/tmp/en-US/html/Common_Content/images/15.svg new file mode 100644 index 0000000..52daf8d --- /dev/null +++ b/defensive-coding/tmp/en-US/html/Common_Content/images/15.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/html/Common_Content/images/16.png b/defensive-coding/tmp/en-US/html/Common_Content/images/16.png new file mode 100644 index 0000000000000000000000000000000000000000..3b3f17fc25e57e7850b691c14420e503f3871de8 GIT binary patch literal 975 zcmV;=12FuFP)js2CDxGfabp!|-#t)5YGsZ12u;ZiW5f zg~Rro=l^@pd(Lyt5v3H{DciQX136m>?h-j`gImC5;E?eEd^4Vb2=v}nY9!s9lFldS z7P$jF2P)FcI|;OUl=5Z;&?8d30Uf}lG>xtD+2MYZQh_Z4yb-ygpc^R2&^)G~fTvlh z_h|zd=I?;qEX`vI3)Jf%k^qchA13=Zw<>6dD(mM+T873q|J&vO1xD@!C5(VE+j~-F za26LMBCO2K5m{T)#@HPW^2*9^xLmBx&9V6DlQpC%esx$!;JG%b(@Aw_CpW%)p>cYe z1C^CYF?pq>RCjiAXK9Is@o{SV`>B5YT9+=t!z@Hbkx5$Tc_k&(c)jdDb4Hg8h>pxv zzaNL&4ZzCmEX#oatMl`^@QN;xv$0}j0vHu8K?kp0<3d*#JM!~c{r(+?%cTXVY;VWm zb`$jb`S{=gOH)%RVdK0;jJB!E*1+B6vR z=zfgXd|%%mUIca@KMugI!-u)(^@0ch`%a(6b^SVh6&3vY`790Lx#$^0~bofMbszb2}8Gw!c66-^>g%uU;kfiT5%AjLI~b3B*`S3uCRVghQd| zq!i)D&=3O+4Q#BeSi>jdk8E4oj5d`Bc_k&R1%tY!7gNG!lyn~G78xM(BiLs0d6Y`1 zxJh-u4)=lJKQIp(xf7HG(4b*cce`h3usm_Bb0b&q# xr~-UhnEUKdmC79c_lt>D+jcekm)iE*@o$6@PI~A1Spon6002ovPDHLkV1oYi#hd^D literal 0 HcmV?d00001 diff --git a/defensive-coding/tmp/en-US/html/Common_Content/images/16.svg b/defensive-coding/tmp/en-US/html/Common_Content/images/16.svg new file mode 100644 index 0000000..95dedc2 --- /dev/null +++ b/defensive-coding/tmp/en-US/html/Common_Content/images/16.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/html/Common_Content/images/17.png b/defensive-coding/tmp/en-US/html/Common_Content/images/17.png new file mode 100644 index 0000000000000000000000000000000000000000..d0f12f79c167f81bc3fc08e4c09cc82184a2bd2e GIT binary patch literal 838 zcmV-M1G)T(P)eo}K~z|U&6i6{TR|9xpYdp$+Crf*RYJYcTI|Y&4Wf%`sNhN{ z6{9E!x^dygm5cs@{s9GpZltS_5^<$;Q9@E7(CWff1NNdcYG|ZZLcJu-bkUPTa&nGI zOiKE~Kr(!1-e+##%m^tZl~h$l-GS<2f;~cXRKYW#2e7LJU|%hP6s(R&xm9SJqL3-@ z3h^9x3A7d1ZWwssl5(Xa0G|-ezu^_|q(Ec6f(nceO1WD!z-u9#61+g&70uI%32+Tb z=`R>SHGc!tlxUt-LO{O}L=J#D>>nt-=X%8yaOkHaXB(<>UT$-MI<@UAWsQKk+I?m% z)HXLGgy8hxfYkXp0G5UZ6pO{wH5rd{9*bpG4QB2RJ-|l{wwh8~i(_etrqNLV-gb9$ z6bb?0^!u^(_L>5GU0&w>#6)IQ*d^to^dD^sJVJCBncr+_;pxVPW?rn4Cnx%~u34>|MWa~i>vIg=4GbWvvlD9L@Gy_vZs6|-=%spXslPS#=mT%H zwsOsCCF1k3Jv(dEL6Y$}iR0s}(lR*-z)>i~kIhY^&or-0bh|$4v)j$Dy*&=s*J&IX zF$B=-PG=|9t}Xy}=H|@8G_Okm01nsI3NlXX;miyGXVEC%yxzP3Wj&5>*zMeNxd8aG zxJc^aBJVeu0Q;o^JeZ!Qs-^~+O!8@A;j&Q8t84&@#lromDF7lXE1X6mMFRv%0caW< z^tAe*gdg literal 0 HcmV?d00001 diff --git a/defensive-coding/tmp/en-US/html/Common_Content/images/17.svg b/defensive-coding/tmp/en-US/html/Common_Content/images/17.svg new file mode 100644 index 0000000..7b3e327 --- /dev/null +++ b/defensive-coding/tmp/en-US/html/Common_Content/images/17.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/html/Common_Content/images/18.png b/defensive-coding/tmp/en-US/html/Common_Content/images/18.png new file mode 100644 index 0000000000000000000000000000000000000000..ed2f1fe3373cb2cad8424950c940ddff34b3c2ea GIT binary patch literal 1013 zcmV1h<;)*%%Dge z5hx+}7X-UVFTLodyzxT3sf&IU z>ht*bj=Ud`b9LO4ut9yktI)dyfkeFkFi_@b1r)6FT; zSpts`7l3O(b((qoz*U!&53>U37outrZUe{CG)|UJf!0PTCsz&dK!}qPJiw+5&6gDv z;A)oAn>K)I{sP#LrTMa=0-Qz=Iso;v50m}OlND5;HhDR8+fZHee{Bx1NzJX120;DW zQ~q!TRaF$)Y?yL$^)H2B5Mc7o9e&NtQEaz!QpRJWR=f1B7R14FNV* zSChASGXSqHU*=V7E5q&W0OVIzQfRa3ViLU)m*9Bvz@nWy$+1|N?(b*R?KT96%+DiZ zu_ePTTL387x)p#}Btm3<-Y6{Yl?Y%>9`&)W4_`wAL(R>^qESPD@a!xfdU^nG^!9S_ z=1ul@cLVUYvyBu9>#qO+f#=U*h4W(M$`z(O9+doiY;A3ra&j1TyYXMYo+`u; zAY<+6=%BKx34qY#Qk~h`)kRfH%Zjmy05h4Gm)F%{@9ILBOuTGq;n|KIjNiC{l9$K9 zTem2-+l|8FUReWFIGq42ynDyzyLXYX7$a^s;XnXkHe)@n+gvFD1~LIy{P`1ryow4o zl#~EaxP3dhWn}>T{_(>oEbbKth{5Ab0Hz;3Vlf;h$711(-%s7p5cTihBNTF3Z)v>nAoc6`T>s+17zNUtt6jIN=?Pp)d2-sf#4dL2i4pf z=>Qs~oD|>!jB9UZiVAQUHK&G^uvtp404M+EO9WH(gDC-)Arz^V literal 0 HcmV?d00001 diff --git a/defensive-coding/tmp/en-US/html/Common_Content/images/18.svg b/defensive-coding/tmp/en-US/html/Common_Content/images/18.svg new file mode 100644 index 0000000..fc744d5 --- /dev/null +++ b/defensive-coding/tmp/en-US/html/Common_Content/images/18.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/html/Common_Content/images/19.png b/defensive-coding/tmp/en-US/html/Common_Content/images/19.png new file mode 100644 index 0000000000000000000000000000000000000000..a145b4afa180d560ae7e9fe7df125f8a6003a51f GIT binary patch literal 989 zcmV<310wv1P)Ig>bO6GiAy`2#{)jWj{VSP@~1 zN*tnvizV|uj-1FV<2q`7oDciQX1CFgU?iJ#Q4K4sDfxY?#FsEO`t1x(3%GcS( z6xl36pAeUT+dyTOaVLQrVJRQw1TY{(Sppsa^;sIHDr$$8CMiE|8K7T?kc2*<#G?7S zGy&meDI-|}=;luVXO8CUiVHZaf=C0wjadfh_}z}i+zlf9sTV?8~bpPi*~W(M!! z!=~rnqenS6K2GC@51e}Sii@!rH60z;^72&SOdbY6uMkI2>~pu@ L$DZO$004&Aw<>QbqDnE~_+XOi#qY0iv}QdC>Z()_#2B zE}svXNboEeWT?EH@mse5IB@M61*N5FeUiPBm*8Y-L(jp3*0P^?j!RA~` z8$yUbgD5Xobu+v+1OWItGz1%@>)6;B01l6b+Pinz6$(+;-EBN~78Yg=U`aDwUHqDz z1=iL)^x_4+h6WZUCIE=XVjK2P2AHz~kXT&gSzR6PJ35$u`jpT8{X`lXNGvS@@Z;S( zRX4-Sk@9DS6^La`W2~*sxG$`(rl_U{xw69dk&z7nl4oGpig~KMfdI#QdqD_3J$#sH z`x;)x46MSS4Q^U74Mig4@7~Rhefw~DJOC_AOfYu+y0ZN$46gq+WpJV+)F|bttm(Pc*q=aQnWBJ>+&6+nQmuhMC zK%Wr9STDggQ#354DdVQ)0Xwt+%DKx?njYJvG=L^4KMDu~>fCEhaRFgfajMLO%~D1L zoaOJ#gqEou%m}a!VTS+^&A~ishd?HC_}>pEsoJ)q*}v4bpN@Y6P((Brt!PiB00000 LNkvXXu0mjfChWNt literal 0 HcmV?d00001 diff --git a/defensive-coding/tmp/en-US/html/Common_Content/images/19.svg b/defensive-coding/tmp/en-US/html/Common_Content/images/19.svg new file mode 100644 index 0000000..69c6f5f --- /dev/null +++ b/defensive-coding/tmp/en-US/html/Common_Content/images/19.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/html/Common_Content/images/2.png b/defensive-coding/tmp/en-US/html/Common_Content/images/2.png new file mode 100644 index 0000000000000000000000000000000000000000..126f8fd39218e731a293ddd52b0d6aa5208a3230 GIT binary patch literal 814 zcmV+}1JV46P)e-gD-@xo7SZQc5a`s*17$-eMkpBgBI$cn%Bz&E^5HXC5&F-o2D^Lp7&RS%Rn# zFMw&_zGB`4@G2g>#=pN{HFGp4znrnX5-i#mn#Qy3ZM?O$7sSaVzJ>+>j8uxn&Q5+M5(O0)@X#_V`x`JFE-zBL&ezFF zeypwWv7>|cjg5Q?1TNxzKAQagg5+*4=MoI41aHsIvJ;6Q4FdpuWyQW%U00_hz{%z8 zg613#=7dEKaA#=9K0jPtRZU@Yl_bD|Pt)j}nE@^;vA?ubmVlz*si~oFVS$@1Eu@l3 zK8Hdj<#7twQw9wElk5M@Pi{e*Wz47Q<_E6)!*t9z`PD4FpIZ9}^oH;pckZ z?#(N}*#$9Ruux=II7~|@gftAkO-+$LIiaq-9RPWD#_z2y6#+5pq$nf0-PgxcN87n^ zy1&ndrlx}IIgQA?kk`hlZrmuCTmcE^$X4>ts0?KMjI!o|s1PwqAHfPC9+Wb}akG5D z1LJ^x4dl9+I|Eq)My1>l5Cqa!NS+oD%r%_mbiy$ymjw)SHI>jWn+GoyV2SWRHxMs_ sJnn(+%gEt>-PdZbNfyZ`_I07*qoM6N<$g0`_-NB{r; literal 0 HcmV?d00001 diff --git a/defensive-coding/tmp/en-US/html/Common_Content/images/2.svg b/defensive-coding/tmp/en-US/html/Common_Content/images/2.svg new file mode 100644 index 0000000..15424b2 --- /dev/null +++ b/defensive-coding/tmp/en-US/html/Common_Content/images/2.svg @@ -0,0 +1,27 @@ + + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/html/Common_Content/images/20.png b/defensive-coding/tmp/en-US/html/Common_Content/images/20.png new file mode 100644 index 0000000000000000000000000000000000000000..b23618fb0bcb69979163944d247e1d012f5a6bf4 GIT binary patch literal 1086 zcmV-E1i|}>P)r&1MYVr$Asu~!BL0~11o-oQ7&!5W3_n9?9RAZ6;E z4U7xXD`5->yr*~(X#wG5QYLCPV2b|$)NN9{2wlKoClh4`%*XzO&EL5lX$`vU=_q>* z&75zwI6%ORU4jw==58eN$64&OuW{!CnW3?ZO>buM&zz zad|udNW)-pWQ3W)K@442yzY3M#@=3a?X!5C>Ep*S*4OPOhJlUOQ%Z@Hl6%lO3eq~3 zVli2Sp3Ta9E~oy_4h<>Z^T&@1lZGKP$)w^ejEqQo%u$f{ptGo}QealN68w7pJlXkq zevCwj@7l$;O-;O7SOB2q$PoZOZf_@e=nw$EoIT5TZEZZgZ~=hUNCa=7d^=gStb3rx zPRuPY^L=|eOLy-g^Lg^wEPv0=0-!ZC6pS3*@Vy+10kHPyQ6ad;Lvw$BnE|Vo)j*2_ z5os9ex7+V0(A^EdU(?e7)HgQ+kbn7-^%pM+#+R1VH4S_AIE7VORSj6tapel0-McY# zow>`G0q{090-$FyinpFl^Cp)o7%&aiV&JX#^xQcy^}~h%YpYh)4~z*h$@{lp z)i4#7vZUgc)d3BnK>7oSr_I-r7Z7%8P8}=ZF)0%Q4zo2+B3-E; ztZ1NULW3?~Y7^p98gx|>hyVMBi5=VaY4#zp?O(_L0oq2cd`c78dH?_b07*qoM6N<$ Ef;AcP!T + + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/html/Common_Content/images/21.png b/defensive-coding/tmp/en-US/html/Common_Content/images/21.png new file mode 100644 index 0000000000000000000000000000000000000000..91b602bfa9577a7013f3bfc71529ad454d30c67a GIT binary patch literal 925 zcmV;O17iG%P)JS>*Wx0{UnuN?|wYhJHo;^L!v#mXI z#(Kj856?dPyx!m6pRbToQco#$r2~#?f}aX;LV-(w4`|UIfK~08%fs{)Dc{-6DeMfv zq!5>ZJ3yPwyvxA#pp?&RGB72?(QSAHoU;kGDyqUjK+2V>4LlQ~OTr}3yhC_FDFMMg zDI>NGXz*8nvqpG9SpgSHnJ6-#b^9A?Z@E<|6};BrC|ZWvnC~_mpjpdplBox@**;|r za=P8PJsuRNla0kiek7A+DX#tdaW*!RO{e*}zFsOMU|b#69=Kx#d&6NaCX@K1QO?iK z(z~{X_x^npXYuqna`h@bi3HuT7@pg=%Xu_0bOTR?IDuuIpBx{jb#M^H%C{)|cDiK!C%6 zfGJDF@8?S-QZ+pf(}j0^2(&V4*%+v}TvaExp=D#qX6rE8Wtk46qIzIbh&gs%f>ly9 zD5Yt~E!qcE7ywfL0G`rvn^a^VAmxgHAduZfcve8LRB>8zC+w3lBH#kM(-Wz3^k6Zs literal 0 HcmV?d00001 diff --git a/defensive-coding/tmp/en-US/html/Common_Content/images/21.svg b/defensive-coding/tmp/en-US/html/Common_Content/images/21.svg new file mode 100644 index 0000000..8d33472 --- /dev/null +++ b/defensive-coding/tmp/en-US/html/Common_Content/images/21.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/html/Common_Content/images/22.png b/defensive-coding/tmp/en-US/html/Common_Content/images/22.png new file mode 100644 index 0000000000000000000000000000000000000000..33e0374fb47025868214d49c9e0f3aa3b5880725 GIT binary patch literal 1059 zcmV+;1l;?HP)#FY91_!{`A&bafyS7DJm8!|Aa)CVQ_2I#3%xDr!NIN2|5*a6SSEj>u47HqZ zwm5)Ki*12r1+?8hR!MSuy?8r2ak$-N6A23Gv@N=FIPmV>%R7MpuNN2jBb7qR}ibVK!`*!XI0=!;W0HEdQQ2<_ykFz{7!otm)-1Ykz_xt(f`gH(2 z?d>!NgSH%)waleBR7uP)FEi26VdQc(mm@nj$F@Cta5gpRIpk3!V#)Wf)6=w_KM#Q0 zty<2!KRACZR-t8xGWhY$a2IFYCp*3eqhfEoL)U87;g4$8$M z^H;A{Y}dCk6&s7#gy1ns)D|XJUeeojZ9oGsE=p za=CahHpcVeVLa{a#{c=HB^)jnJ@@YMZbt`&bebQ}oue@jpfL~tpqS0_*UOic2IBgI zQHr&0=La+Evs8-awzitnnC$Ik*P%mveCbk6&hz169&4LYM;SiRyCx$A+7I()qNAaq zX5jU3Dll(u+3NZjZ89t$BU?WZQ!37zw_s~wDlB5DxVAdrgp)w#Er@5d*cR9f^ouMi z2m{4U6fY_WS8GnIR>Bh^lM4FSoR!Gb>IZ8Y&`mg@8<^UF_>>d6Yl*}E{bEvyExVe% dO>Ft?_;0Su^w!AS?REeF002ovPDHLkV1m?u_No8? literal 0 HcmV?d00001 diff --git a/defensive-coding/tmp/en-US/html/Common_Content/images/22.svg b/defensive-coding/tmp/en-US/html/Common_Content/images/22.svg new file mode 100644 index 0000000..0224965 --- /dev/null +++ b/defensive-coding/tmp/en-US/html/Common_Content/images/22.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/html/Common_Content/images/23.png b/defensive-coding/tmp/en-US/html/Common_Content/images/23.png new file mode 100644 index 0000000000000000000000000000000000000000..cc961c161f95b1323533f727b54a21901ccff723 GIT binary patch literal 1152 zcmV-`1b_R9P)Y5MH}zV?V*Ur+!oO1&F_MxZ85;dr!LVQ0Na|4RpO zRjJPent{Am6ptaGz_VSXE$sj_@tc5cf#NZQ6l_iwL_z>s+J9l;BacVG3RUsbk+2Q5 zIe*>a0C}2k6HFPwt5s;tCfvoYS)#mvY^f_G;@0ofH5pcE629x>IQa^2ON zc87@Q)&$*6AThh{a>?U!=Oi*SBQZoH5qW&}tX#F(qzUB54I3nI=Z?f9aQCi!?{>Dxq5@|@K|%yZE#o4rjVDeG4DdsFIZrQMM8aXh!64%g zAI^;X`v8Q4L1vymPnHE;%Xk(PB_SfwsQ#Rhl||nA^#F`^ zbeMRVD^_67$swnz3irW-Ai{6^_al)=GPkT{>hWrb90G?LiC(CVS4we-_KI_ z+!Ffd*)x9Lw22YFKb0$8EA8XBw4s5LJ$nGSw|6hW?rzijVV{p-pO4ADKAeSxRA0VK z`H>^@`qk?|vr;`kX)@AEua}P+8$l_$jvnQYW5@o}>3jS3@xkfSAi|B35+?il;wilz z5jU7KFqF($VO<>`o<9#t(S7{*yy5^ut*vtpN>Q|JTT)8w!5F};c-A|$wS3&vgv!X^ zua*}2E?i(~S($FuB}-W8_2R0m)W5Mf9F#UR=)YszHV(R$J_TC0^Q)2dd2cUSt5>HS zY1_t)lpQ)m!ImwAUc6v-Y>dppLM#pk0Arn<{8UpzG!!y@7ln1Pu1U{;_D7GAXtCQ< zipMbG_cJ{>h%Gytw^psf;&2cS2Kn>UDQ?%*C5Qt(#+EIu!zdltmMz1XpU>>rSgPU^ zgXu6z=m(mWy2Y!vVDq8fBVww!33b2&ZkQRX> + + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/html/Common_Content/images/24.png b/defensive-coding/tmp/en-US/html/Common_Content/images/24.png new file mode 100644 index 0000000000000000000000000000000000000000..17b153100e51cfe78a8d1af0c363f0707af55fbd GIT binary patch literal 1013 zcmV)he`g*ys+A5#%0$|fVnnJ@6N!k@O@kPs zIuRNcNCrnK8%acHGybx295G za+8~Lzx)5b^ZK9v5mHJf6OKt$2VCPJ-w>kG0h@s;z^6U{gX+_shI`wjd~P?UurmcM zLTmv}0*h?M?FEj8q`Z@pfmR_(e!*2>wM}6oB2L&@D`o$<4cro9t%Mf9`*=2+vzoZ0!pF=~W5(y)tR=YclBXH6v9B6K4Q!GYxB*L0U zj|hJHM4+h&hueC2%-_GC4bdnYqEY4qgH{xsM#jJmAu2KK^W~Q=QMzXj4n-mL^(()= ze@8eRlY zY-=0SfL2Ruz-K{3rqh{sS3v>ZRjUB_($SG=&-3}HICqXzBEjqP=j|BCXt}H!v!UYb zS(F(wNGFr@o;j0guWW3@?eXy9&>?<&{yZ)NwvXe5hYvGv-#!4IA2`5BPY(daJ9gj; z1{r$%m^T+Mf)I8?0{Rgc1QuG6itFpCPc+k+mzX}QD)8rpk&uBlkvG*w^C46 zX4^nJuvW{ORaM2xn>P_I7av<&d3WUs)BOI-_f#T5*YV@J$cooX*};PVe7Jp^*u#e= zW2zRQNyTcl^GwTH-`7XMf(2Fq00>uCGZYT%+NSyatn2Oupkw=X2CiQ>{g;O2qg7L8 z5vmQnTB1WyvWn+`UTw){>oA&N=nf-OJ + + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/html/Common_Content/images/25.png b/defensive-coding/tmp/en-US/html/Common_Content/images/25.png new file mode 100644 index 0000000000000000000000000000000000000000..193686c6da9259644b3c454796ed58295778e6b6 GIT binary patch literal 1108 zcmV-a1grarP)a;(@nMKN12AjH?ed7!??d1Ju0VJUxDmw-VbwynZ>&!?t%`RrNF`_h^k93>?d#+7uMm&v4g zIAn|tvw-^;Le1s%(s1b#+d4W>+-?A*s*>pMXRNy$HIo70i^)kmyLMRwBq9-h>+CcS z$HGzuvJd(e+!CS@Q=IR)c8$8OE)=($m2{fbr6q)-PjVo7x zmf>>n$Ej1K;&Fa$Z|9EB$4}MOyqKN_p!VQFi-3va$GPM4>20jL+g5>*%b1FTX2Zpq z8HRT5M5-zPE2$LECntHYt`5hREdaPY9u(Jq(fT5hAhWRWdLJ0Lj8RZ)W2ln@ILpeY zY-s^t?(SV6*ZrUL^bi~xqWQ)R-VcQe3DCKmc7yrQ(AS5%q5?IOA$IX1040_GM{IRl zo8JGZvy%sxFEerCL_q<16buNF0?P7{?>KpqhQ2-kMvoq4`ucSM9HpgveC!y)>EzYi z9R8LTJ~(s;cSQwA$n)vF)`zUF2-0kheTVmD|+&4B~#y?GOa;QoaR{B`b}omuYk9zN9jQp*+j z1QRLenXewqD<*H(3FoH-t~)#8Jl)Bdz;ww a+ws3D$$&5D8Tdc|0000 + + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/html/Common_Content/images/26.png b/defensive-coding/tmp/en-US/html/Common_Content/images/26.png new file mode 100644 index 0000000000000000000000000000000000000000..e8bf82a53eeeb12679670c41900a03a1578937d1 GIT binary patch literal 1149 zcmV-@1cLjCP)lU&-1>||9xK}rDP*v+E8{N?OlTJ2(jA)-vISMo_Ya1 zQ?I@-{Ln1raH=^)DnrmE#J4~@P@ZDm382j-WzV_)l+*7l z;5#9{l+Xp_u8}+np8(e(DSJ~EppyRvnAb@jMMyw{k%$BVYT1Wa|DWsOQ=nEq90_fx zj`{m02gp@($04o)>TK`U2br_8$=1p1)cwtne@;gH8j+&J=2ULfP!^p{#1Sco?v!#Xab8`66Zs(t=DFE^g9MIxE zyM7&u!-3D^;pfs)e#+11kGeVr4jwcT5XTie1oisBg{M!sS6PV+ha*)826^@HAsNNR zC{`-~*8F@Njg5qtml-^AgvFT|LsA_yuGlWfGYHhk0n#!v$*rpcU~X^_fZV-%5hfG! zLqp`$)Zp}ZXc!%3Pe%u~f`ViMG_EwGhsjWV^(yIGwh#`5n7DEUfXuQo0IXZLQrFW1 zLI99mRfT=uK7J`L=WQ^UR6xqhaoLFzlpH?}z_8m*aC{s9^XAP!WFk&?c5-jW4sCK; z91e<)9{ta}u>zhY3o2}Bp<4apv9o8Hx_MK3w>&=|xsj4#x0`_1i}%6>LViC0S(TMW zDK)ND1vnZT*>n3g2*LQJOL)(pk9!~O3WUJ4X;VbY$_k-CAaWn$6{`v8(?@+&U(e@v z?;_IDnCZU#9%jDF8x&0OqVL5Q2p#Px!T>f|bR^xbMPHlVC*Z zgNfL{sQs>n(bK0HZEGXs_eUnB5X=n>(6@ho0y!`dyJbshF-jRikg;tWOFo}b>qQZ_ z7$xinx`gOs?OU+b(C?Bm&T$ibK!H}k_W{U#YVJ5B2xyXWT7U~M?4LCvB*0~~IW=^` zLsIq%XyE-+!k276m{dSigaWld|2oL~6{t-{4*&Oqi5?qvH2aX)@YC_X#dD0?g~6qA P00000NkvXXu0mjf!Uhxh literal 0 HcmV?d00001 diff --git a/defensive-coding/tmp/en-US/html/Common_Content/images/26.svg b/defensive-coding/tmp/en-US/html/Common_Content/images/26.svg new file mode 100644 index 0000000..aff5a90 --- /dev/null +++ b/defensive-coding/tmp/en-US/html/Common_Content/images/26.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/html/Common_Content/images/27.png b/defensive-coding/tmp/en-US/html/Common_Content/images/27.png new file mode 100644 index 0000000000000000000000000000000000000000..06dfc67dafa189f7b710137ab24d76d5700c3ffb GIT binary patch literal 1007 zcmVgKQ$qxq5A!dGDfc zKF;@N{+M&|K5#bYJiO0y&ilRRdyf(kHWHoT#v;iSw0K7NGSQh>~ zA@Zcun5vW%M3p)Q{0{6XG43?*TUcadT?U4g`Z)uC0Kb$dY{$44PIimDUbBI_O0^3_ zf!gmB&mpNGd|V_}vH?T8wQ63NVXU@=g=~CeX&z-=RFZQWDh8CcG1I7(!!Q{n@EY8gEsJEBV z>T3SlyqUif2>?Pzj{@+ZtBcXAg9 zTx8+dGk&bE$6HzXZ7!8^2<$j@3V=@!AM$x(!m+Mv=~WPNA)4X<6;)N#9zJXacSB8U zD?c4P2*8UQH(WWoR#5{wny+8SUsFRioo4#lHCIl<`SSq$^Wg*UqR}-OD2Uw`F0j+c z?UTMf7UOXTr!o{`TR03rqQ9T)*RMt6>IUBDBW>^PrPX^GHxOXw*|Px5jf}87H&>DYy$Z&FcAZt% z*2bYo1XWSN-0(27Lqlw8Y&6%G-n=2Rv;@HRo*sUvs{;yte7Y8(UByPXW2u=VGc!~* zG~|sE>*(NPECxX5)29TRnpl{e&g$aPI-3XF+qo#^rVi|qt}y7qR0O-%s2 zxOuY}eOhnXO8Oa<8J3@sqaTPWHOBY1V8t*V7O~v8j(flhCxN7Wz6?kju`O^I=oWdc zAPl6-D4tdjc56;uZ^GjuF$JBJ=OmK(`oX*gawfdc0*tRieB28y`NZM>{xGp)!=7gU dB{uwZ{4dlhoostdJfr{s002ovPDHLkV1i9V&Wr#6 literal 0 HcmV?d00001 diff --git a/defensive-coding/tmp/en-US/html/Common_Content/images/27.svg b/defensive-coding/tmp/en-US/html/Common_Content/images/27.svg new file mode 100644 index 0000000..0769006 --- /dev/null +++ b/defensive-coding/tmp/en-US/html/Common_Content/images/27.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/html/Common_Content/images/28.png b/defensive-coding/tmp/en-US/html/Common_Content/images/28.png new file mode 100644 index 0000000000000000000000000000000000000000..065ce1ab60ff81268bfed38201831868ff784e28 GIT binary patch literal 1177 zcmV;K1ZMk*P)e`jYGb_)ctT$fOUgn}sqL!l`#C2Es3 zO;A%5`v4naVq(Ih%0u}2)^t6=CqnPf8OoA3WW-UQvIFKf32qgl$OK1#GQh4~0F&C) zslpFmN!b%=P7%oxvCyTHYK24h|E>^2KX#O;y`pM;H;2x<`)e%mXp2Kyl!51ht{I z=37k;kf`PMgI@)-uf07m$Pynnv1g95*xSSlUX=%KgoMh?Qvv5Kx zjNK9F0}X-1g-uOlI-QuJq5zPp%8TY^dTMJ?yx0gR^YWSxo z$PyX=U4UKz&1C*GMt<7bO2+Zy0Q|eOgisU|n+<@zix=s?bP1s-l#h>NO-*HGYKrN5 z_eec>km#f&UQJB!Q$_{^d}k_r>@zF<8_*oi4^PgXWpQYT2US&kpOC)X?p8^6=zI0Bq^$#O&G?nAVTWxCCW^f$p&}e%ZYnsj6#LSX^Yj zx0jf#EWHvQmkX(?2$Kn0S{eZFWn`?))Z@Y9as>%6av8h89wJaD2QbIRlDKy-0IvJ@ z0a%%y=CAA50Vuk0gOcWE3a?!Qp!fWFybBAV(&}6r3NWIuv5}~qJ5jw}2CrV#pFci* zn(?+a6q}7*Cr)6BisDIK9fOUH;ZlVZur5A4bB63wrvT`wtz~gwKp)FHcaHRyKsTwn>Y2bh?R(gH#-aODd9moNK`r#Kt{EcEv?dgl&ORe4-j$I8?c z!feKVB&fOkxQt!U3G6dQC6$#?diO5EY-Xapofo%n6PK5#kGn@lSzTTRz?zbRWycP@ zb92OGWf7f}1gv#V2z2^x)-|FphK7jE$qAJJfR6q9@wi-k-rbF2weosqhNb7vNhmJH zWU=6R`I6uE?7=-Y=J#GmBhnrW8UuayyB_ABKIQkrhnaiyi0I^G-Y+f1WH$46M+cn_ zM-VwMXxy?z^fQVS=Ga(lc02CzaaP^#aAAHwqoDmjn-HD6{T6H^bX7{}=eR*WpnwyY zeFx;TT5dlC38;{AL_j6r-9mD&fXYyt(~wShOv(-c4z{Kev*GrGVFma^C{PS^ZGyZ@ rf#PuF@P9v;1Y+BcX73W)emedS$Ml{3*-7uj00000NkvXXu0mjf0IwSL literal 0 HcmV?d00001 diff --git a/defensive-coding/tmp/en-US/html/Common_Content/images/28.svg b/defensive-coding/tmp/en-US/html/Common_Content/images/28.svg new file mode 100644 index 0000000..60cf157 --- /dev/null +++ b/defensive-coding/tmp/en-US/html/Common_Content/images/28.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/html/Common_Content/images/29.png b/defensive-coding/tmp/en-US/html/Common_Content/images/29.png new file mode 100644 index 0000000000000000000000000000000000000000..8f28d5b185a6902a9b3da4c08f3784498756f5ca GIT binary patch literal 1135 zcmV-#1d#iQP)h6Kby8%UFAGASm;Ru~-@(_x0h z`T4rYo!dKiX3S_((iaZgd(U^@_r2$w`PvqQ4nKW8yS%_;*p3XVln-GzQ12aLGC&nvK|bIh)5zDmB{k4 z9ux5S#LPJgG7L>=U40E`87>3A_x2JA1o)+^i@Od7-&a=?U0DI3_S7i=K0I@V5~mYM zCb{3%#t-%NJi2fJfRE3eJWZ78MmckK1`xoCB*Ee#mqx^ji$y?aT;<1Agi3_y5xRyX&F&&NKuo7SNr z{T*9*dBFzWh(qVk^U>L}0L=9C5LsLVVCCjbqN}UG=A64HCvkc_dVf3|ej~5Z!1H`T zbzNP!v@c%h?`P%ub-gbci*diTmB8R2!F%`kb9@}X$3t>`9e}?dKh8y|YgtVX51Aut zPM+k`p&?L;#Y>lXbn#*q+eRqFY;UiAU*6bArOSmR61;lwpkM=2fZG_gucL#{M@Las zD}PN)uzKs3o@@YOYilH9u?%KMON(xJZFrdVU@(_~sq}@OinVIzH)GTnfk3`h41nL` z;icb?+wZ5ex|*{6`?1>X07MoSnQU)oBNWPdF9pr%s!3l1+JhxyU^@M71zTk$dm0+B z+U+DF5dv4Q^7HZIImLk`W64&~X0#PboK8xrs@MpHa&J_b$k>ds>VYw(rg--fY%5HA zMKUsORvxfGH;{Aewuz9&oq;R^ogz;ac!Bs1ipLdra}}pKGvR3wzk(C&%t(at)q{Br zq)k|$1(@E3__PID@`=O${a|9ot{u((OYHjT_#b>)(czm-ocRC%002ovPDHLkV1lW; B2;Tqz literal 0 HcmV?d00001 diff --git a/defensive-coding/tmp/en-US/html/Common_Content/images/29.svg b/defensive-coding/tmp/en-US/html/Common_Content/images/29.svg new file mode 100644 index 0000000..6dc6635 --- /dev/null +++ b/defensive-coding/tmp/en-US/html/Common_Content/images/29.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/html/Common_Content/images/3.png b/defensive-coding/tmp/en-US/html/Common_Content/images/3.png new file mode 100644 index 0000000000000000000000000000000000000000..9e3ae40280043ed0251b8ec588b6909d88ee80e7 GIT binary patch literal 889 zcmV-<1BU#GP)bkhVq{`)F<~H`${)aL7)TAm03;4d${<9MB2yV4fS|z|YYY(SkL$qeOJ7^ywm|Tk zyyU)@d(QX!&bjy8bA^7lyA-?U|fhhF?a}q-{ez=jTlhP^$Yj!4v^~wU3|X zNh>PiT3sD^c02o9Tl@(IkDwqmi_*jry`Z*2{LqRL7hjg4`|=~NL=qjQ-B=oRin z{N3H(}CW1NVH0t~KX z0p%GcW`xz@z~*pJ>~wN(a1em6J|92)epMF+S55+IhlZ%`>jOYWqkI_{V0Cy{)!f9D z({UUQ1o%EPLwI=^p=sP78sg#TD0y~!*1n87;1ePU+|Aa()!JH~EG(cE7P8pa$J)q< zirK1L${H|7U?*F0fZr=C?5(c@aJ#cp)y&{Z7I5kcy4lvot@d^-R;%%?qN@vg%~APC z2vLB+Wh}xtOj_XONmkbz8>#hph#wwuu)U4d;UK@H1b|35Owj99VvoaQVr)b}Z=-@I z8HSgZ2nPaKtX7Jvs>m-XAs&hFZEA}5&CRNHAeh{;<#req7E(}FhK$8H*xEwI<0`}n zm=2?~e!wS$pWIup(=g|j(o}KN>VO74K + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/html/Common_Content/images/30.png b/defensive-coding/tmp/en-US/html/Common_Content/images/30.png new file mode 100644 index 0000000000000000000000000000000000000000..d5831850f9995ab65d52d45fa65152b07d5c1617 GIT binary patch literal 1179 zcmV;M1Z4Y(P)?J;*x0ld6B820NCbgF%#FeTcNp%> zoG#|hWq$5tM#0cGImz5J@BQBQobR0PoGYZ1Y$Y69st)9R47pc`dIz)t&46k)0KeHr zqww2LQjX;sQ{<9@J|TVtdVrc70AGhj~pQ#L;GRA^3UNKHrDHZ*g- z+2Q~tX6z&+&49Vu2a*|r;<`Fqm6aF^3j|)gz*tzYRVXYgqiFYT7RSd4y?d9*NPFV$ zNUZ}si4QdwFY@h$3%FF(>WhX#yuN*#XXnl#BM|`di;HO-9K_SoV)14N2l?yB5u%|` zs(~KBGGL{kSBQF2_W75!wYXFjV{wti=g)~61`b8xn=@yqy>!XqeLpY|6PJ=DpAUeq z4jp3O&6{>JP-AK(8!#(e5}tK;^UtYM43(DhV9y>#RF&|`3ILwwW&nzI?V_}`HO4=G zp5JS08NYG`fU4uiQA*O6Q=(SlB5Y12MuI^m@7^W4wgx~*)6gd;0a%`x06=Y9_dVU) z3&7m{`?25!1yme3U^fevR^l2^ZHPD&1(&L#csx`cJxWns9jkBO;=6hkfWnFj0K&`5 z*22@@ys_SQRaV-CwY0Jt*s*sntxuj<&;H?I{_W~wb$%WI#p40M2m~xnNYjYuI!?D6 zmuWDQfvm^z+WYtThlbD|KgI|IP!AsDhmjFV8XEzS;c#puZuk02LLi*Z*#B7$yF>$i zJHpb-m;Bk*#ve^h440RqdA;mtXyCh^*p6MDn*$(!`*!lSZ3CdNv=oP;0A#8MmR42+ ziHHP)%s+exKuJ>*ipRss)Oux&=i6OfZS@6bW^y(#n#jm6F6Qggr>z_Ve6e#URmYA2 zu=e2tAx&eZzn`dK08ri8iO9>N`osw!mLC7`u$_T*Eh!~ZO721ZFCgP>sJvXp5%l|| zK07OAG-~yYb$46biCed<{zxcf{eFGtj!cXhZ}*@+u4~PJd5!YLpTjFF%#Dl?(RB(d zDq`hW2$p<4{yuq_+cPys~9IjD*91 zQdUNOQ4#v|G!b353mW4(ow%#2(5I%5(P$=G(qWW#ALtWeluy5cWrMdv%A|^$RtKEW z322`|Tr*=QA!z2}3_G$JxvE^UK{{d%U;_;qlHVXg%002ovPDHLkV1hD45$*s0 literal 0 HcmV?d00001 diff --git a/defensive-coding/tmp/en-US/html/Common_Content/images/30.svg b/defensive-coding/tmp/en-US/html/Common_Content/images/30.svg new file mode 100644 index 0000000..717ae1c --- /dev/null +++ b/defensive-coding/tmp/en-US/html/Common_Content/images/30.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/html/Common_Content/images/31.png b/defensive-coding/tmp/en-US/html/Common_Content/images/31.png new file mode 100644 index 0000000000000000000000000000000000000000..9146925618f88cbb1837fe112e386daa16d95e0b GIT binary patch literal 1012 zcmVE+7PG)&nqQJ);>I z{8h@o%k5K?GXw)d90&SIX}g%blsli-aB=zxQp^$Fp>d4JN zpR=*|;zf?Ue^1AY7X%+X;PBWO$7W_|zjX_tD0w|M_4IHg9;fr|TUxJOE9TL~unpW3 zqMe*|Uenx+s%e;s1c~R*$(SY{ua}?BpQriKB|AdFbIo_FTAtnMjaMCQBJ`v7AE?$_-2} zFEerbHknikfE8WGn3w?I^P4vSRQY_=wYFkRPBL=n5OQ_3qyZ<(c@}5|0`YjgsG5e? z@2BbHNoreKNY2a<$y}cX<({Qz~bxI z{MpsTAHg8QJ9eN)qihWXXzlAO6ke`uR!IX+rI(kPef$`JhF}n{-@l;-Mx7DWb#?rB z?wkwa+r68no*n>Fb91cddZh+zmOTkGFzA6R*|wsp?C1m{tsEv*GBzt-F zDpXicW?(S;+s=ShM#Zx2)ukn-BN5Vu!4Hj%sG0^suo#Q+*Xh&zd-G;Ra3JO^*-9Qp z!sEfaeLK~)wHWa@X~U=#oR#Y^%Bu$kgczmr60DS>VJTfZZr(niz$u{O+4T+SR^Kk= z8R(Ysoq#Z4ZXnzg5H3`l7TgI>NI4>)gN@0AUaTH0Y9MPufdCL)2Ry1kpcowf?-!F? iZQ9lBdur2f$6o+AM_w|dP|KzO0000< literal 0 HcmV?d00001 diff --git a/defensive-coding/tmp/en-US/html/Common_Content/images/31.svg b/defensive-coding/tmp/en-US/html/Common_Content/images/31.svg new file mode 100644 index 0000000..25c7b52 --- /dev/null +++ b/defensive-coding/tmp/en-US/html/Common_Content/images/31.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/html/Common_Content/images/32.png b/defensive-coding/tmp/en-US/html/Common_Content/images/32.png new file mode 100644 index 0000000000000000000000000000000000000000..cbc972e24c1f5675c5bb76e2033eb7d7e5baae34 GIT binary patch literal 1151 zcmV-_1c3XAP);MU7EI^uoxU7w*=Z87?*68AGxgq>Bs4g-FaCC7Mm9%!H(68X<&E$l*^xT4-s% zU3gl~=_wRM!=B{3I45u3=Q;2Deb4tEA*EzHVcJ%9;FHY+-w~qT1m6LEz@sjJsJi+y z(Dj3q&o-JFb8ho`v3fkDVliSbUXV$pFj*{ob@3wJD^~!hJa&wRTem26yOEg; z$?0hTKC7$aU}q=7Wax5@$^~flfa-8MJa28~>A7=sS5)wzu8tm$hn2-e0Gxh5025tZ zjCXYK`u1(Qold%(PX4)mJ@)~hR#zK(pykra^XCVq6A4D!+sP!804ysC@zGHL-oAR3 z?IC}hI>lg13(1)okdo=gk8?RnY&L@cEtmE#@DvEdWU*lNc(6E~>^^Yg-tn z!fkD&?idZsRxAGAUK~CjN+`r{{?%<`t*oSRV1Tl!DrN@<`Tg)=QnA=tsYU`) z)_}eO(PC=Ti3F2LoJ}gcr02YS>e_tPERaMLl4bk7!v>v&RODmvX8&OhT&X*T1 ziQWYi*UCAcwDBmFwYkd%M96JD}d+gz6X-$v&?vF7j_r z59xTEQnwqc#{)vJ5Q*^TnKQh+apPSHckEcN)P)eyj%-CQBVjUOak(h5+lh~luXU_8 z1Knk0m + + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/html/Common_Content/images/33.png b/defensive-coding/tmp/en-US/html/Common_Content/images/33.png new file mode 100644 index 0000000000000000000000000000000000000000..7c1ab6a2114063e0482610738d5f7115a2a1ee1a GIT binary patch literal 1213 zcmV;u1Va0XP)&dZEU+_y;WU&Y<@uyHH`WtP-c#P6rsKn`6@(x?zNYVD+`~!xm_1 z&n|e|^=-?FqG8|UB=6gP^L)SWbDnd~bA*(V#e`{5)q%HOhI~Bw4! z`kcRRae!hywgH9==+)k8WC#jtYOtS_>z7kzz12Ij20 zM#JimQl>^T^frS`jz5kalaWV{WIEzgQ?l>uS=nMX%Vv;2*4Inz)-9O{t-D+P;B?CL zc>3r~*Gx^pMIqLcvCfxPRbf?CVq;^B-MdF37Q>_{yno;TRVPjWV76Fzr>+hek27}v zKGA2-0C=~qj*nZ7$<*Q0wScr5(04ckdJY}pm%V%OmX^}Kb}enH%1k&6K#AK8K+xyo z=k43MQc*$snl*S!OZof!c>rwH)mZHIEC=aY=|$+yB*rHv=|6XlL^KM(w5Ad1?+4(; zg9j-em@JM}(%`7(F+?PDq! zH1Iz0`&sIoEupEA5q{dZktcqCu8;<;yvK1g6k^!xMeFJ!Ha?Ep&_I1#8^s$o7f|3lQ%#L+xDR@PEIUWMa{-W^WRU bemnjLj&J^g4O3A|00000NkvXXu0mjfy^S|h literal 0 HcmV?d00001 diff --git a/defensive-coding/tmp/en-US/html/Common_Content/images/33.svg b/defensive-coding/tmp/en-US/html/Common_Content/images/33.svg new file mode 100644 index 0000000..01c3222 --- /dev/null +++ b/defensive-coding/tmp/en-US/html/Common_Content/images/33.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/html/Common_Content/images/34.png b/defensive-coding/tmp/en-US/html/Common_Content/images/34.png new file mode 100644 index 0000000000000000000000000000000000000000..2585ddc9ce06b0f885214c3ab78588d9caf3988d GIT binary patch literal 1107 zcmV-Z1g!gsP)jX3b025-c+qwys_A#-)fC zVaQThZ73F06a?|>$_sZTUKIr?C`!Q_VK+*rWicRrTxi?TvCS0}rm>c`v`bnOw5=xn zNYk^6y~*HhFS&dI~`|DWeM=Q+<2Qc6}6rd4GJ*1V7L4Iyexup6ic6!ilL zsbALu{M;<%pGJKOBPr+*;(MSK*kaIc5ct6-W#_U4+!CTP2|ogEgT&eBHp9L~DTm)% zz)wQ#kkA3xmPnpLRDiEZ%7=ypsO0y6f@PAYkPzU>B|;}a4f`J~f92VTnxQT`9lB$v z=6t2e0c@&o4Kxu@cl#}^g`mXc!ctyNVq$`+=g&z@Oe{_#1lGz*0A?c*=3}vJi^j~; zksX27%)ypZr}%Dk6wlMAxbNIyXKybJV`J1_zKk%NbMkLKa)e!jgX|g{#P0RxGSP6P z1>6v#maKEW&gsOWC?qB)nSAnug+u~VQ4yPu9>sb3w9fNK6%~AW?p#h`nd?%yv;x!$ zr$OI|6a0SgApVUTxmR6HKvB{m{j|Pb=eh3cRm@gvJ^>o8%oON6Ca0$vx^|6)xj6u4 zqfz2RLjb%R7|_@{4jrP*<00ht=M|92l_@~UVTh@y2&==vC)>91Ra+ayE*CRnV+7Bi zPuo}&h3X3zn2*KiZ)-CmAkDQV*JLKv*VM4Hw>Lcw-M-D^!-ts}A5YKKwzpGIT1wyX z^=LbG!MXwUwTR25K%|1Ry>PNa1 ztKH7y)E{d%ZNeK4127W~Bc;S*x2JR5ck(1JFJ01kUgvc3?Xzb9{JM89BiFC%Y!=|_ zRM(W=gz7{vHJ*>f2nPZr<8jv7?N}5Agy3y3$ZrP@jyf7=wj(DSUz<7q|{VgT^%sPJ|Ox5$fK%n4Rit;r5qOE0}?Ap zo)F;6)tu(6giTUD6yRZHA`xAzA6!&GN`x8efbM0GcblPZF>?67KTNW*YEQEdiB*3c Z{{wKjd#&biR9pZ6002ovPDHLkV1h9y^wt0X literal 0 HcmV?d00001 diff --git a/defensive-coding/tmp/en-US/html/Common_Content/images/34.svg b/defensive-coding/tmp/en-US/html/Common_Content/images/34.svg new file mode 100644 index 0000000..cf9cf7c --- /dev/null +++ b/defensive-coding/tmp/en-US/html/Common_Content/images/34.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/html/Common_Content/images/35.png b/defensive-coding/tmp/en-US/html/Common_Content/images/35.png new file mode 100644 index 0000000000000000000000000000000000000000..86ff09ca842520cceb787e9c0bf195afc69888a2 GIT binary patch literal 1176 zcmV;J1ZVq+P) zLwYGSSxQ1ea)}2e#6tr1Qct0foI>#6B}hsFiNzx3&@_hzHzBmxsA)=FHDnWURhY0^ z*LB_1eLXlk-PswVQH%Y;gL%Vue&6rB_kQpFo{&ZXvz`z5^;Z7&iob6Oi)9Eg9$$;^P(g9;n-(a4v!hoNbiy z%?BI!L5R;JbOWAEif5n-2%MDi@rDg(;y(lSEsAH563}2}!el@j_5rs3=ebZ7sLh=Y zQyOY>zTM&g9xb*3h7r(KdykPJDE9ktmY0*7o#pS55mK|W21%O%Q8MWDYLPXNXYSy4%w|JI&bdfOKFAIU0pIep4LXPHT5aD zCqxZ7d0tdih12IFH8;oHix;F*DQpf02b!CyYHQPZ`EK{x18+v9rUhi}gxU^gz~IG; zs862o_U>KM$s`VshcCim@(K$nt*_^=t5*#MhAv$qeEYWkeL9)6bf9THHyB`bdo^HX zaglIWm)>7eRpQ|=F2A4Ht5*QnT`p|))ofh|hfV8a4d`0g27DGoYz_xbpAScADSJ5k6^P{7=VPgR)i*gNwfC?+S z87NLC^$#E7sjEW`2KlAlv}^!4(A-Q-M+X4Eo;kzYJ9ly^qX8)^!MGDf-X{*Li*n}C zBLF;gbvQ~(EqSr=as64QQdSgQE89SSHp5Je(gGk}Nee6Ab8h~Up%95(G=lF5< z96N^MbONh;N9C0(`Zv+RK`R5gmc9tn&})NlGkwMBVa+{`q_L5wjP23DGjM(ss|J}3z*K( zZGfu9Ho#<{QOY+00)S=yY!WE}0juKF@?vsQ%Etm4*q)J4*Qy8CG>|c&KrIm5f_PAY q+O@>t|9&ya#g1Lg{!8rm?f4&+CF41Uhu3BR0000 + + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/html/Common_Content/images/36.png b/defensive-coding/tmp/en-US/html/Common_Content/images/36.png new file mode 100644 index 0000000000000000000000000000000000000000..c4a7f794c27d1309bbb8cb23d97b207b2d62f778 GIT binary patch literal 1222 zcmV;%1UdVOP)X%<4?8rm|_PyJUK?IA_gH{)P;}`6e!e1R0v+ybr1+qxFnmxet5CrjJAX+*`gU+evy-Kv~gT#oH@;$ zy_hqH`8e*F7VaMoocBEs&;Ng(_kEuCd4-}V>?903$`0)M5aato95g^ZPzyNJ2Vg;c z2E*`klcJ1n)~DFa67&f1BhU$yY|`%((9x(Uz1tG-K!}16bOSY;Bu<1g4Nf;G%IpUV z_(_QG73cx1TO^M{63}>3Q66ntfJ**5kiJdwC}aW0^h6{HP{TgL_WwK)QW{hxE=N)t zs%!qS$pNgY?>NLoK;7*R;w=Q0vNFthdB`3Q-WM;BJ)R9&(o7~YiiJ0989OMsc#$tJT)^ybXmjB}fa%+}8Eb1p35B%zjG`jSuV3ejrY3|T5?If( zXAB%TkSL%N&;)2pa9@anB;h?Lhjg#3PH?%W|93<404Bz!Y70Q{r= zojETL`-u~TgF*gmZca&_$Q8Q>96E*=j7H232S%HX{N`q|%F0-O`_Lv?R22myelyquh)NBO0sg!ikf8wyBy90!+|S$Oym$>l=!dU4d%@m+sE*6L~i z(zCLF$VQy)?&i0$GA6EG1;AvtQ+VdgfBKIVu%KtK`tl`1_4WKwQ$t^FE|Swpc2yN$ zcSbTc`0icAP*E6dZN)n=!Nj#|TCK?3zhBR-#+6b)EJA)iivt4ySZiu9+H9;%Pe(oq zfx&2uXbFXoz23;XEN@!CV5~*D#X`}!a~N$lZ7!p*ko;4pfXJT*B#EV=A;N(G0AF3X z0z&Zl;lu3C&j-LWKCUM~lOgt zbahd3=@J04*Gqb4CJ2FVZjN6|O9}b?aqMBJjCM_01k{PC==lBG8t(pnLOvfRyFF5l zgTVK89K$ss)}3*Y=a zA)ik#q^hwXWA9!9lBAbHn0 zXi$_{0gZre{%jGlfJVLMRJRhIRFp>oj`49KA#KzTZYUrsA`Pkl=QhZlX;8HhIsD%* kCW+XwtJ$Z-j^B>|1%S@MEi-(_fB*mh07*qoM6N<$f}eLS?f?J) literal 0 HcmV?d00001 diff --git a/defensive-coding/tmp/en-US/html/Common_Content/images/36.svg b/defensive-coding/tmp/en-US/html/Common_Content/images/36.svg new file mode 100644 index 0000000..cff32b5 --- /dev/null +++ b/defensive-coding/tmp/en-US/html/Common_Content/images/36.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/html/Common_Content/images/37.png b/defensive-coding/tmp/en-US/html/Common_Content/images/37.png new file mode 100644 index 0000000000000000000000000000000000000000..91cf6ae3e19ade4c2532ab3605fad47562233dde GIT binary patch literal 1085 zcmV-D1j74?P)K~z|U&6nS6lUEqWKPPEOLRo`bg6T`wO=VaJtEfQ)mr{1o zi(x4%#$iFk3wu#eZ@h4SfE2vdg5phOAlMAcY_IfUrO8mnshMS!G7g(Ufwrv+PAfp?hEJQob&K}zvnsUJm)z=O36;bv7_uj&1Q`63USB*9Y719XboUi zYojah+fPzH*{Dykku8V`@gvX+?BAf@B=B=o%E2uOxF^I{CHMu1Y>>DTaVMPal=8)< z1^g;RtArTf|48yOQ~}WwQjTm`fJXiRaBY#ijG}mE$)d}Is?XX-! zZO^xx9Kf&nHo+7D?X=%BTL^ri5Z;Cciu3ag$s+r&A7qd_6KE*TeJverfbM0Fy>eeGBdi zafph0{#jEKUPYm}u)xB^1S`cN4!4_qJv}sCzHA$FfaS%-%Ax%l7huSQT81;>>G|`h zi3I=Lxx-4KfZOlqhg6E1+FAlFE&P4u3W?*#5jEz7`sK-!9KLxIfYj~V7Ev146O#Z| z)2j)kT#i(KzuteZs$^3s>Ovuwrl(g|xU^&;`1U;^ZAh@d~x(B08`hmSG6&6*$UWo@F3qmdZhPfhlUtC zcaD4}Q`Pe~7cT;k&t&*F7PA##`y3bEykYkKebhvP;^HDodpq9^592>}%wp?R6dIyY z0G{8v#Y&-I=iVe>wwl4)XV3Vfql4cg5r%?6)Oeg-;V|F!_F8QB_4MFyxsc1tOy9V% z94ghSUAv}x zY#SfP*WAp)!~_ox99Wlq1rC?1COrb$K(gFle)o>_@Gzxp7EgUWUPS>Rc$-Y}=b1Am z@<3}VzUJoD)%W$;tv+ci*=!#p;c(#Iy&G3u9od&JDP^;E1a>ezMwWUYCd4QoUxL{o z9+lFRaV>ek38w+Ia(o-0YQ9ad2RR>S zngYrqoDc@$TOf}+A-onj{NFz&mDsVb*{8&g|BgQZ#R + + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/html/Common_Content/images/38.png b/defensive-coding/tmp/en-US/html/Common_Content/images/38.png new file mode 100644 index 0000000000000000000000000000000000000000..882f8cdc7d608c33ab36ee9c9133e0064acee122 GIT binary patch literal 1256 zcmVP)h&6~#b%S9uC6GYr@LFW*laS=pSpS@ zIkgnr5yD1Hou?EOU{(|Ylaow#brA{#&>4+(;m&L~=!bg!WiqaBhx)>(>eS{Q%6n-FOEE0GR3T z2f#l*jtqqs39VKDzSz7OfRNvhe|$VnKqOb>S)e2UqB9yXD+)%7h1|o3Ni8hI=W^k! zuLr<4I!a$d19@l9V!L(?OL;lDM~?!~bLkR+si{P6H7>0R8ikk!l4FsZN=m4B`c!)! zzJH(RCr;oS9o6=PPDjb@+vGSL+Fn;(9nLFP5|IPUIHXL06&%O@i3x_Ans7gPLSSkN zW#2ybHaC-ATB>0RE?y-2;6VVqgNuEp@bYE0R97$OJ}LrEVEc!_db1h(!-u4omEmr0 z=MTG`jEV}%A3p}*uj*=sZr$RW`g*pXJBM6Ypk?=NCVP5fUH#*bGCwu~!^^1+&do8} z(gHwwSs6x)h0MxI0H$8O;@_J$k)aST>+0~iTnK{!}$Q#P=N?=uIZ(-@Rj|zn?FQi_s+|;h&hGW!EmeLqk#Q zA^0{tHE9u0H=N<;h1pp~nwtrFy_l?4%!&d+Fzs~GQCmx2LjwSl-QE1Te?OkiPK+5D zY}&I2ox#9ZYb$M)m2u>NGje2G_AnAU9mdQ|l2TLg4h<3XdJ}~d07G&zW<|mK=FNw2 zQHN37JkTga8=pRcEobcxDWf`WTp!Rw4dDI^l*I|Cl5$Xh0|=}kc|d?8(Qulu z6CRSXRX`5)OOeC>{bCYp>vlE!oVM<_ + + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/html/Common_Content/images/39.png b/defensive-coding/tmp/en-US/html/Common_Content/images/39.png new file mode 100644 index 0000000000000000000000000000000000000000..cc0726d78e9b5c1d991ebc9682eef81f40d0e332 GIT binary patch literal 1226 zcmV;*1U37KP)3kK~z|U&6izhQ)e8;e{a$>%}mplC212%w@#{ouytyL4x3_k z;ho5eWhjXBLZO0QNI`e$m7o+6(OZSx*bf}D#epAdX`RA0C$(UcQk|}|wR)yaW74$A z>AMS04*59!&^o#Y-iz~||9PJ0{NJztE2NaHB}{9o4ivmgaEB0^O|T1S0K8fQn9$n5 z0{r-`lz*(0Q>a4rVTu&+tVr|)c_ zTZruvx&Y^Uil?CnXx=Sl|B4N0;@1JoD#g=C3fN&}BF})9_TO3kpXWj`Lm+oJ@|K}C z<{w%dz^QR(Au9vgY`>BnAt>?tu~k-*oStST6e2l2olh?W>#D0Ma=VEP50i?;7BkY6 zwK}Afdh3KxC&+XgYHO46XU}9N)I>s#oj)(T%w|3A#+EH|W@JQF=7Z%D) zKCOi^HT5Cr5Mnbq>%7?K!{+spj6{e$c)&t3iOFhZ{h>qnjvoi0u&j*WwQCgne5mm_ zZ^p(DW-}X(9_5SEr;ReOQPTo4=76@tW#Rte!~E9L!d17M>$SD?dcAsTT@4KYeA?22 z)$K;AD!1zD_^GCbhbK+|u)ejGkE*Kj9As)`PQr%VKy`MOCzmd~_99dzSIePJG9X>G2kaV@U(c9>?>qUNLd?D$4EKBxh#u?%YXzZ!gYm+W`3U z;zeTGu&i%wWqV&A?#4!e%ZB)zF?4^iVBp$LCOLFK0kR9 z05u-x*4C|zwzo5N^Co|Hchle4h?+Fuhu=?WZ7njD;-5QrmNbx=fq~2jOGycz9XyED<07Z@?c7VhD5|Jn=j0>+iOET%l-N8T&}R7k zBS#oJcMgE<{rwb`mt(7}q`+`N3S^xk5 literal 0 HcmV?d00001 diff --git a/defensive-coding/tmp/en-US/html/Common_Content/images/39.svg b/defensive-coding/tmp/en-US/html/Common_Content/images/39.svg new file mode 100644 index 0000000..082c1b1 --- /dev/null +++ b/defensive-coding/tmp/en-US/html/Common_Content/images/39.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/html/Common_Content/images/4.png b/defensive-coding/tmp/en-US/html/Common_Content/images/4.png new file mode 100644 index 0000000000000000000000000000000000000000..266e71432209940b25f4952bd7343bdaa305198f GIT binary patch literal 783 zcmV+q1MvKbP)pL1`5v6aTqfaqeNiikxdrr@I3#i3G4 z#n4G`6sIf-PG%6gpa=zNXikTognM(NIX8*K z7w(YDIp6!_eCK@kJ3>lHD`m9Q9q_mrye&l7fLFi-(4!uJoO%w6@ZpV=N4hbEP70Dj zyawI^1DbJ9fR(6}dkq2X3eo!)-T~v9#+6E$FgGJ*)-}L;Atogxfnc5HCFKP~XQe#Q z22kdo0B?ilB^3lrRfBK2MrFmGfqs0|ZrUn`{7Tx4YVKzV2=w zhC;LjwV211M|A-HA2n_HhliQYW_fXT#&9B`JI&@%2G|xNjQ%-CcsxAY+{Ey@-lqe~ z%MPF_oPLz0B?93v)bTB`dRbF2p&Q`Q;2=Y*tNcDaH#Qwxd!Nu#dth6#;?6Se(vmGcwBwYZUv~Rj=nyguC4Ls;)0{a#d?e# zvI6944IW)z$82xsDxK!Z!U99_INr`q06IrT7>dU+^-@yyDwpD<5TAj`+h)ByKgZYA zb!+7PK!C#KWi5b%sFcsa-jE#D0{D?g;OXeFz3Y#~@cR8+9v_q2-=}zeUCX@W1z1)< zbvxg5W?MC#$?%}Jm(11{U*_kv<`iMH)HRj&fO>J_7N8EDSX;KrGqeKix{3BN6mko& zV*TOh2a-Y@Qhy6pOR1=owu + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/html/Common_Content/images/40.png b/defensive-coding/tmp/en-US/html/Common_Content/images/40.png new file mode 100644 index 0000000000000000000000000000000000000000..b92fd2ffd1fbbf3a788bf03816080963db473634 GIT binary patch literal 1082 zcmV-A1jYM_P)gI|_yI;e znW)4~O%x9##t;u2O)oA767}ZAkHi=cJrP>O5RGX(81O)%(vvBhw5DqX8nS8SqsX$b zZx8dq&dv<3fWdzAW*4a0Au+T2Va8g-*Mplg`0q@YKL5nMhs;qlP? z{5ho!4dgNzehvoBn6IRS#=btvnwre9(Y`*0&YU5a$rMs0<5JcdH|7d-3$fQt9N_DY z4oVvu9An@0_G;o%GM!8Uu=V6g>Tln6n!a7vvKr8LI7ftQYN+e#LgsR|*ybHOh#o!+ zz^@%0JgKea^_43CRG&RdAYw14e69Q%IOwP@1hISfP(mU8e*D-Lt~{~i`>*b90LC9Z z(#ZXODvlp_Vl}n$4OBWzq^7-{vO|X$>+k2^SFddGU_}K03o|ohCME!wef!poZ>Xwr zqBXUaH4su&c3;0vc5;&8_I5mhfQ>0oRt7+JYRVkTq|+?U&T0m9gKh?v{Ts&a-o+aZ z^P;Vd52K?Xgl&#oSkQ<jDZmMwV0VE}^BsJU83S_)ulc?$-=F>W^3)oH{fCG1QjEKdtX zVP_)2{QLL(ms;9cH&j(IJu+h1s6M=VSG0ivpvkzIc>0vw+??g9=#e8t8XJ*|i~QEr z#Xmzs%)EKSo*Ost_2gt%RCR?Ub{x^<;%96 zu>Q^+zPfl3fZY5%9={)eKkwh?MO&MVCkORL*JRd!K9F3_fE$J{UE=qfH(8jT#^d*s zotom0Teo<5;eyljWPZz5_%ApG^sdANXtfclu4Xosa@;j_wB)yHwtk>ThyhmKf_)5w zaVaf3uB{(XpcP1e2Jy7cZGp`|if;#mQ4r{>i0U~*c@X9A9~HY<^K>jzy8 z7$y{m0fVa$A5 + + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/html/Common_Content/images/5.png b/defensive-coding/tmp/en-US/html/Common_Content/images/5.png new file mode 100644 index 0000000000000000000000000000000000000000..94153bdbb7b9f1bbae2c620b970f09e9ecad1373 GIT binary patch literal 839 zcmV-N1GxN&P)nu~K~z|U&6i6{8&MdBpObhi-mQvQp{16l#f3Cj1;J8WNOz(* zbfxIVm4Bcvy6q1LxRM}rB^HYexF{5?SqNHbbue&Otoho507SMGRh-IN9b*BDgb^>$|s2js|yx|aNC&! zR5UfInB}n1lA7>p0q3vxx_w^CK zxKIH&)1<700(V1zZcDJq+*_!V08agW_U7l6+~cs4 zxVKusOr!kyDnph%zaMi$z=}z`@tk#B|Dnkrb>P~{tM{XAX_3d Rwio~a002ovPDHLkV1k+FYBT@< literal 0 HcmV?d00001 diff --git a/defensive-coding/tmp/en-US/html/Common_Content/images/5.svg b/defensive-coding/tmp/en-US/html/Common_Content/images/5.svg new file mode 100644 index 0000000..7d1dabd --- /dev/null +++ b/defensive-coding/tmp/en-US/html/Common_Content/images/5.svg @@ -0,0 +1,27 @@ + + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/html/Common_Content/images/6.png b/defensive-coding/tmp/en-US/html/Common_Content/images/6.png new file mode 100644 index 0000000000000000000000000000000000000000..792940e9fd8292d27efe53104ccf51bec3d09369 GIT binary patch literal 868 zcmV-q1DpJbP)wb(Ku^3DKp%FwhTlXbs>*YnvHZelO*&S)anp5%`682P^BliUoWU;*A79&~i`mEFuEDqf%~|7NC)T z1*}z)XOR*xR7ymV0BzfMsD9;zh*+Sz@HmRXP&@O7CI@KIeCHu=2ejM1WY(il6dD~4 z8XXSOi3C?WJIHj}$ZRAxItuf^f*InvrY2movpA=xu{JmB<6qj_xj8#CGG73S1!zge zFwPaLm6wZ)w7J~?q+&6y!(kMw)y(PvTs|SXvdKyppk+8iJe!=P&F$vq^px$13C>nm z&6wpc;*M)q>+9$@W9*!o0$_h`?q1}DT)6@|N=(dyYPVx^Isv#2g?P2R%-e$ldRJDk z4-8ZyK;KXQhG8)zUKj!DT+}`G=&&T=tIsi{QJI(Uy zTonn3hr@c`QeXd9*u@2a*)S|CVAIIz_VSY0-X3rl4Rtmfs@+bz#{)oYf8VSColC!j zS|a*xWN9B9KlD7R#*>M^QsZ3Q9B9l0p3!@X~|4DD&>ZNAs%KYBIWAAvI4RqEYJ-E us~`_rpt~G7{O=!=Le%VQ_L!*o@AwZ~&Ni4a%N9ET0000 + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/html/Common_Content/images/7.png b/defensive-coding/tmp/en-US/html/Common_Content/images/7.png new file mode 100644 index 0000000000000000000000000000000000000000..59eaefd807aae8f2d8642775768df24dd5b51f27 GIT binary patch literal 757 zcmV5SV}|@8bm5>Qyip=xVCh#4lbp^ z&_xFq!9g6wzaXQ7f`Ts6DW)jet&=2^5Cq4xwXFmKYG@%t>6s>PhhC1{ujIWX62EZE z@jlPz`@ZkJ&poe@QqoOnU8Mu}f(%XyF|NTI;3Y6*J^%&tNmt?Uos_4lIfcp=q=a}2 zB!E%Hyg6VsF6BX62KI#*sla>Sg(BFgj1F@#DK7#W_#nh92`ON(MR-j`0r43rkChFW z@J~RfO?XXZ0aIQkTn5Z#&(i+Pohs@u;oJ__F*NtQ({O-6Gq+8)6)?Z{eZLH$zCL>T z`+W(rQsH+#-^@s?{&YC&K%!CP)5S%eC;W%}xxD0KB+|@40YP$^V%BcTU)kw_lJjheRhV>G=A*vDj79dr#1upFRu+%H4LhTVSD#z zWd)&WRBvwhw!N)npq^EK3WhueHk97m%aer#0P=f#7*|)Sp%$wx10%Du^b8CD@O5J& zNT{cQztra%Vp#^NaHtv`U0OnD8nRO1d~-7>+{UsDm~B+9S#T&E=JEVI z0EMF?mD=xAuD)e+{tH%V@G}A^mr5Lj!$F}=h9y@&kP;$I>n&I_W#UrWDz2*z=r9Kq zZvkF3bKB%H5R>vkKpZG{5MCA#_i9c(E8&ck#{#D4%t{pf`axd + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/html/Common_Content/images/8.png b/defensive-coding/tmp/en-US/html/Common_Content/images/8.png new file mode 100644 index 0000000000000000000000000000000000000000..6aad94b5c4d6146709a7a6350478b6c6ac754360 GIT binary patch literal 914 zcmV;D18w|?P)n^#R|uXxlyY7*r%;&! zhYLPfC&2zd z$~k2K&3qOxr)VBgP(VW>h&TXk*gul`Ki@B(5z6;ZN8D$q&G~Vg1LSDAV-y3Rt#+ja zclOdHa%?s%Rx5_IG*t+j=8+hH@Tc}qnKLt~o}8q4ZH-!&i-yHTnpRi2+SR2B5#yn+ z0jR| zz77rXzP+6{)z!$|U4+3vc2$*1iWslxDY&f?{KxABAU!W!h12u%5vFiO|E)b!knR<| z7vv>)F-~9l`>A$1x!m54FqybeQ31e@*;&?~KUW3Nz4SHU5Mm2BuM%C@(?jX-u>Sk| z%na{ZS_lOKssP(|DKp>*+i`AP9XAKU3;EYdxTaieY~IMR0)ZwHM&)c>jxY{xHx(XmP~HDlra@It_~QX6Y!mY zxlhX-qd0(8DOUv8f#5Nk2L;#@HKz$H;R7k>1T=6wBjG!!A3P8s0%3%5z@37*+X&?c onZy5nFxjtDJDQ!OPW^QJ7nl(%Cu@k>8UO$Q07*qoM6N<$f>SD!(EtDd literal 0 HcmV?d00001 diff --git a/defensive-coding/tmp/en-US/html/Common_Content/images/8.svg b/defensive-coding/tmp/en-US/html/Common_Content/images/8.svg new file mode 100644 index 0000000..23b1e20 --- /dev/null +++ b/defensive-coding/tmp/en-US/html/Common_Content/images/8.svg @@ -0,0 +1,27 @@ + + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/html/Common_Content/images/9.png b/defensive-coding/tmp/en-US/html/Common_Content/images/9.png new file mode 100644 index 0000000000000000000000000000000000000000..2478355b21432cf79e68d0d034853dae1685f5c1 GIT binary patch literal 877 zcmV-z1CsoSP)j;n`t7J!ei?UpR0$ z=Y5{f_q@N(^9m^?l~h$l>4346#&beEsDkG}KhUUL0Q<@nOhMqKlwbAc6nchWUWgaK z8^ED6ZxndtmGWI#1{Q^ANy1yer4yX1kO6$dQtp&&U_pq-66OKx1>tGM1b9cJT+?kp zfv*79%7mwt5HL{4M4kbq+dotOm**;GfS%mp$XkZWm|r#=z^dfVQkDT_w(FX3CaV=| zUmxcB`ch1|6h>hKoGrEU!FD@+fdJ1A4{?XXJUuwz(dsJIO-*`DWHHn^plmW{UO$RA>nBJ_^9#D3;b9J+$;|vabo0#BzdpjRI z9`#*|&!-8`Wn~UQzovoCPW66oVF7@{V36M%8vxk)HB;oVG7U5qXqc^xC0pH?(Od`s zEO+nfHJ}C?3q35RlSo9pcTP?cou0<(a&fD>`z)EoQkDTtokSvhpPAv#*cf)V8@t;L z!13lLwN590kB&-7muFxfxTh8HX?&bt>+9G(9tE-TU*nmtX z+4lR{_WJ=4Mk7z6Q2=7WV95qDC!y}>w9E|+^v=$5qqUXz-X1>!0llFrOYMOa1ghY* zR^$z}r}8ISXEbQF1ds*9ci)v4M8%FYzk3O1O{)HocNY&KGf1V5LS zSncg477puz1JTTqE$erz{3sUBi#A#;R5v%1jK_)Z?jlnuz2LNlGfTC+dSG6NAQvye zv=s76nYCT!)dL3b0kJE9$CTVz$}=!5<&FR^khny6LV&kWaa! + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/html/Common_Content/images/bkgrnd_greydots.png b/defensive-coding/tmp/en-US/html/Common_Content/images/bkgrnd_greydots.png new file mode 100644 index 0000000000000000000000000000000000000000..2333a6db928dc56f52786759d315f7be908687ca GIT binary patch literal 157 zcmV;O0Al}%P)2tmvjXH`8H6WbhDeM00000 LNkvXXu0mjfOXD}+ literal 0 HcmV?d00001 diff --git a/defensive-coding/tmp/en-US/html/Common_Content/images/bullet_arrowblue.png b/defensive-coding/tmp/en-US/html/Common_Content/images/bullet_arrowblue.png new file mode 100644 index 0000000000000000000000000000000000000000..c2355345e2e68b8893abb5691945dea82572079c GIT binary patch literal 177 zcmeAS@N?(olHy`uVBq!ia0y~yU|?ooU|?eekv7`f{6PZ6PM#qg92~bF`ab~41^9%x zGNhgP|Nno#flnU;0|RG)M`SSr1J?%-W^`I(GJ}DELAAs+q9iy!t)x7$D3!rCF}Wx| zH#H?QQNb;OP;Zyx!NyMd+js}b0_(dSSs`#* zy0-cAE0XY8WrY}jxPVOiQ3r93`e z3wE_#SOdFetb+Se4r7JD!C`F2YBSb4|wep=SH0+nkd8#xQ$Ned5w zPx6Gy#&a3VQ!`i|HP=Tg;Ne3nFOX5g#of==LV-&{UW+f2*Mi-?-r)4U>CIILeCbJ* zEh(~iy)c3mrO_9O>q6ePR4L)Vg%TfeKJD4i^{~@R+{v>M^3ya@XXwr zU{G5{+zw&6P(Ir`VuH}XaqR@4Ujz;TyrrSt48C_-k^y%E9Com8B|O4%u~-%(*zbqT zR@XB4K@s>I25=WVoCW)zd0;Qt&JZ6!wE*82%l$e7_6ffi0#0A6umZkKy_o>wcnr`d zAhji>r6o@!_(`po!F59-6>`Cea&UhD2<3sr@Zw!sE;JQt!sL?zUsQmDB0GUcv>)|g zkKuy(^J*ujX(k|e>!vOYxy}VqE5jBEO zO2FP&0}Yuey6|80W@0Z-3{EJj-U5Vdf&c&j literal 0 HcmV?d00001 diff --git a/defensive-coding/tmp/en-US/html/Common_Content/images/dot2.png b/defensive-coding/tmp/en-US/html/Common_Content/images/dot2.png new file mode 100644 index 0000000000000000000000000000000000000000..40aff923752ff2e4c8d578c17f06e7cb1a466f58 GIT binary patch literal 98 zcmV-o0Gitvj0Gw%K#)UFWUmdzZrlcTbA_!@qZLigjxgu0C+PbX<)r{dH?_b07*qoM6N<$ Ef(jfR!~g&Q literal 0 HcmV?d00001 diff --git a/defensive-coding/tmp/en-US/html/Common_Content/images/green.png b/defensive-coding/tmp/en-US/html/Common_Content/images/green.png new file mode 100644 index 0000000000000000000000000000000000000000..ebb3c247deab027489ee3897272943da9807c187 GIT binary patch literal 176 zcmeAS@N?(olHy`uVBq!ia0y~yU|?imV36ZrV_;x-JGJCE0|Ns~v6E*A2L}g74M$1` z0|NtRfk$L90|W1M5N34Jm|elZz#v)T8c`CQpH@mmtT}V z`<;yx0|SGur;B3<$IN7n+2=pZ?`&*rWHkTyU!Ixy^8R{*Yybai#N_CdbpGF=62RLU b&B-v&T8Dd6onHe30|SGntDnm{r-UW|O^`Ia literal 0 HcmV?d00001 diff --git a/defensive-coding/tmp/en-US/html/Common_Content/images/h1-bg.png b/defensive-coding/tmp/en-US/html/Common_Content/images/h1-bg.png new file mode 100644 index 0000000000000000000000000000000000000000..31397b5c3e74629101843ffcaf847462bbb51cc2 GIT binary patch literal 142 zcmeAS@N?(olHy`uVBq!ia0y~yVBiB`7G?$phPP=3j~EyjBm#UwTlv6D7#JED zn41_FIv5z6nHXA_83ey)@-i?m7<#%mhHzX@=4fSLOL`$xZV;Q4^M-5D+}_@^jU_ua uZrsQ@#msGy^TJ09j|O~QsP}Fm!@fJRZIer_Ll_ts7(8A5T-G@yGywn|Rw>N@ literal 0 HcmV?d00001 diff --git a/defensive-coding/tmp/en-US/html/Common_Content/images/image_left.png b/defensive-coding/tmp/en-US/html/Common_Content/images/image_left.png new file mode 100644 index 0000000000000000000000000000000000000000..ecd48565264f8553645a70206b72a5683c6ca469 GIT binary patch literal 2278 zcmV5Kdx!ZfsC)7PN zKaqRRx%b@jKg;)h_u$bq&EpiL5HJ|b10RCTU@tfZeg|KJJg^ju0quQxj!WQiD)jka z88`$q2h@Wv!QCL#?f4chI8r=#8#Fr~?+&6dcJ5X7N(31(;2srz=7W5gaKR z*umY?C7%f^4W6^1AxYQNmGz*S&Ciqq*($!$A3He|F zxEZtq7lY5i5M$BnK&mUoX%d`gwo+`Y@7kvpf)gbm6|@EY!8)$j##rE35^tX>INr5*!!LovoqWdV>ea9Ulr}cox&%-4&$xAh3$w)}m*(GQl4f+Wu{8 z5PZ4bU=sLw#qyjcxMgen6nvt!;B~EOFP8*ACgo9pX+R5Vt0xTnp*J|oK%{g*5Sa4X zx!^9a6cjlW{4slxxI6wMg3~{vg3t!?u)5n3e5lybpP9H=BMro950Xs=i_A7`J9?6ZUwt3wY%(*K+7Nsc8*lpW&$87o-K&~Ltt+_gHWb+v ze6`ro5n#TBV8vYK5{|x!_0P6&&$bvu>po?FUJ|{V&6mB4UY6;{*G7PMz)nSZEHIuY zz(*Wad>2eHv$FX^QVM?_-T|-}dS=ryYFBWiNH82M0dLTCy06JIuLaNWdr*vIB;7+Q zb0_l?_(J%d=&cfbi#$tdkDg|8dCuioKZGrL5Buf57<2cZEcit>1%F?tGa5V~-bX4s z#U$SF8+j~>`*-C79jZE|;7u#R0lLU@lm;Mpkv~jT^5K!TQXLu?-!L>dp5o8bWn8|q zPg!-8 zThd}2ptocU$&;d%SB5488=OUSLsx z{BIwu_cWV=FIBXC8<+}iQ$!L;>^{|zrI;f zFOt6jmo^0y`MsFH2$Dc?Z71wXZUVKew4v}YsO&iVDZ|( zQ{k5JDc?ELwNM_29}8PiC6_(vo=yaR(d@-%%$TuB6H-}O*|x&M!cEhsPcPIh`YXV6 zu#8W<*by2gr1l`_Wc=*y4g_B;)cabI-@}J9cZuLe`C2dp=Vg8sdkqu$v~UNrdpZ$( znEbL)QBie?iHT%AYT@DG_2uQ|J2WXZH#aw?rKOdqI;$HG0{V3ND44+C(kTvqAvnuk zhp%)X_!2Y0xy(_aOcKv}xc;7YOf)ay?a3fw>%5O0uYtr0u;7c>dXF%n^YZdGR#a5%gqZatYH4X{NnBi91?}TCH8npdM6b=v%*+oB4Q)IjcoPv(7a18z zu8S5H7S<3Q9sQ@C7ZVdxZF7d*?LhEM8-f=({pQZ1*9i4;6lEeLJ17u>?;}^v#K`kq zaQ@HBnn9|ns@h3|VZ(+E`9@`$nwpLrJa}+hb#?Ww#>U3-=6_Nx)y2<0K@$xaY% z$@$8L*rmGbV^f${Z3vz&lxfi2HAT60CO$sd0h5HhaK$O1dVd6`S5tJ zyJ=#*?`gJ!!-8Kg=6n4R+{?z%-|wsq@PEjKq;!^}P*zhlRal@?+j<~=paf#9!M3C`un)mm?3z}+s@OXfqCsb`F_a+{ov{LN>4@&pAjt4766MM41-Ui&l!J4thXSz^{4jdfz zS8(k6+T_WTwSN8jX~TyP*BTlc{>`IhUG6Zi*V~+skgz{KKK?*RNC=JGr}+ggkYmgy z9rifyVZ;g><>}?=k05u0M&oZ_16<~M&U;g3+&lr zE5F13UM(1bJF>I0W1KAK{=)lkh{HNjL2O@?4|SpyhMre6+H}If>Qf;$Me5k)tIf*F z$|plkD)Kw%6-=@JkEkw^=pO}A?AqGepCEM2xN+mQ*VotYR}>*v<}z21(<3+$266%+ zHfHj%L4yYENli`NqWkw!Y6Rn5F;1`G1pVRuN`D2%jNYe;)N%S1TmhX4Qo07*qoM6N<$f;VST Ai~s-t literal 0 HcmV?d00001 diff --git a/defensive-coding/tmp/en-US/html/Common_Content/images/image_right.png b/defensive-coding/tmp/en-US/html/Common_Content/images/image_right.png new file mode 100644 index 0000000000000000000000000000000000000000..7ae45bdf6799a6870b82f86429c8c58f6d2b9288 GIT binary patch literal 1358 zcmV-U1+n^xP)OP;Zyx!NyMd+js}b0_(dSSs`#* zy0-cAE0XY8WrY}jxPVOiQ3r93`e z3wE_#SOdFetb+Se4r7JD!C`F2YBSb4|wep=SH0+nkd8#xQ$Ned5w zPx6Gy#&a3VQ!`i|HP=Tg;Ne3nFOX5g#of==LV-&{UW+f2*Mi-?-r)4U>CIILeCbJ* zEh(~iy)c3mrO_9O>q6ePR4L)Vg%TfeKJD4i^{~@R+{v>M^3ya@XXwr zU{G5{+zw&6P(Ir`VuH}XaqR@4Ujz;TyrrSt48C_-k^y%E9Com8B|O4%u~-%(*zbqT zR@XB4K@s>I25=WVoCW)zd0;Qt&JZ6!wE*82%l$e7_6ffi0#0A6umZkKy_o>wcnr`d zAhji>r6o@!_(`po!F59-6>`Cea&UhD2<3sr@Zw!sE;JQt!sL?zUsQmDB0GUcv>)|g zkKuy(^J*ujX(k|e>!vOYxy}VqE5jBEO zO2FP&0}Yuey6|80W@0Z-3{EJj-U5?+Dt zVa7i`1MEHb_xpa&J@=g7Im;LT7&Dp~^W12YnCQ&@A5jor614W4}qBpTRE#F>l4C^lO|JWJZ9Sk?fIh(?S76l2SXg7i&GQEWL+cp3M*qO%BO&L6WT zYLRiz+yIJr38^QdoLyunQm!8R-EyFB?$I#ORJnuyLdT8-197aN#)>p`&-au9-JSvT zjqT8XD@)^v#4QVE4ctX0JTn8B+z7cx#KbR~hoX5eZu@SaTYpm1k;h%T+jbbl4)&~x zf~RT#6TXG`AwMInM1(}@0C#WXsE5w2Y@q+zq{SBK?=Irn6dhX2A4;XjN<@mhET{nt z_&VZ=Y-GlIKQFP0qMTLgp6@yW^tEK?Qv53x+xf_(1^cT?=bsq= z51?9iLgVpxNLcF0H}M{8AcXyJ+j?J6UWn4q#c1Sf6ubg^awQ5`gTKc<_#QpbmsbHz zhSlW+rURDZ=h1rG->HiPFE1xn{6+o~7>CH&T1K831j_S^w1@yj)6+vcKh+oki^FH| zdw-7hOZ*0LMK0Pp*h2HMxu9$cSJM~@%5x!4hsI#c8K#kc!)lEw_dA`_C|)pTcT+B( z*h9z3xu7@~%t1BG14Vt{6DA0AEzrn&aGMujd=A-jKWH5wYk-n8UJy79?$ri>q9Jeq zOrUI-jX(XK7*zcnbw1?GL2t0O6Z0!rgNLrf*eHs1oDefzM_QV~U3q-UB=ZmecSIeVI^zm4Upn%~eaK@Kb9m#M$W;==UMhx5dAMPzaaMC?*06h? zI*SHsW@yCSx>}fC&|3 z+8YKG8Aes=m<#;5-cJ*3N5*VwRDlb(TLN{`e1IxDTxjMG3#!gf9S>O)Y|R?jE2M!B zSOe9Wra)Dgs8Cef;j$k-JctP<9w9Emk~MHtNCW1qf#&SVK$RP*P@J*{Wpm{4IKPmK zM_3zU#u}&+(ts0dpe=7AP-Wu>sF4AEDNZNKrY~?x#8te~0$)~7RT-|c9hT8tJY>r^ zrW)n4PzJbJ=o+J_%|e5^0E1HUt2Dee=L(q!y>c3Zucob)cv;$3kr`8c9;!PgPFku4Qj9 zW(_EWG!RLGN~hUq3c((ws>OPR{!=_2-x>X;?w1+jIxq_jm~x*Lq)q0p!UjSaSgBfx zXIc%ZhnusEAn7YpaFh;AiN2nekomna^vDe#dhf}MNqhtE3S}UL1oZc^)SI}k*bs73 zjbWajg}&nu5KC+zevui}WKPl>r*WSV{~lAJ4D28QLjx=ZC2ZP15fWpjfP>UpTQI4g z(veVd1fp%m+rtueC7D2Xf#y@Wo;!ix&QT}>*(BhS&j((%J2(?%;ma1}qqDcG7|{k= zF(x7Fn2ib7UW89&#X>VUwR_;H^b{KMW4Q@sAddtL3$%c5qo#nw(MDS|*+*|drVb$% z*=P7N=bswqtX^(bkdbJ@uSNreGO$?BxGrU;*jFC&cz!%NVL;k+#3o;kn+aLWWing4 zPGkdOBH;IH + + + + + + + + diff --git a/defensive-coding/tmp/en-US/html/Common_Content/images/note.png b/defensive-coding/tmp/en-US/html/Common_Content/images/note.png new file mode 100644 index 0000000000000000000000000000000000000000..2b421d271f3c6bfaf7e38435be090cf6c28067f5 GIT binary patch literal 1616 zcmV-W2Cw;vP)6vr*AnWm*b*eX+puTHtifo!_M&xNHmT z?ho(Gci3I-@BGf^-gD2rzk7c(0AR+$tSK9CadUqa<%#+b6^;7TMp50>D0kG$P6fal zx}x@>6ezHhs!@AUa~uYM#$QAIIi3@43%qUCJWnrcFy~P(*%bf{#-L36CZ2u^VQ1_& zkeZPN_p9Wf)EYo*>YI?7w0bD6tcE|*GGObMu`u7)PYhv1McD-a4ecLkWiKE2@yKyd z>W$Fe-OC*5>>GgYelzq83_`EjHc?%=#)#LF4YJjYjc_3Gr?I^gJ0$=#ki?Azhetq( zTmkB?Ug+o@fPujwuvh6vTZW!~X1k!G3RVS&iXpz66o8N|n30I+&!N6u$6Bi2j*gEl z)H?)G+u9Bx;h%^hLMH@(7tBU=)5T$t>!CqoV1@^Whr!XsJTwfdt{$jUYq2N7IDi55 z%0vLN=|T^`04SqYK#2Wes(kqLZ&0u6Vy(>! zg^L1zbEN2=Mhq(|lZ#;lmyqkVcO~)4R8p+FKpiN9fxElWHOUbF<@&nx6q)Ut_$ zN{i71+}-D}aYjCe6K zPYm#;C4kwy!iB%`So~2AE^5|Eu6s&7oVt8N4Dg&KfM9f>Yzhwsp$g#GRI7*e42L?lagN7}nN?Q%= zv()l=Zz%_ew+8SLRhsMW0cj<2xP#=Cm<4j{+a;AOXVe_9#2Ua0!jcufK9~r%6>1zr zTJ~2;eX%=^JKu?V>i-^S&QWFW#Y-WprUkO=)RO9EMI*TT_;Y|HTb{@k@b21o>@3`> zRY|Jd3CZH{dCS&^`h2zn=l?ETDXNAnG$e&C=9hq*m+!IHzgC^KESZqqhNoX?cE zK~Q8gcb>L*UZ3d3Rw7+Y+Zs{;#O#R|hfd67cII}o!MtdR)1BY7KSAvLRn()C0a!-{ zT;G`w*URgj;`og+1w?M%DR!PV*q)s1-lz*VbTT#5p^j%%E8))q*1E{9z zki(8y(J>i^h}!lQr2o@20+1}bCJu@1(-q)(zCL1G?`wh}CA(+@B5cD(4nQZFZ%oUR zdfLuIC2$B=eCS#IaRkKTYVpYBG;sF~;1D;b^{WQx;2Pl^cT`3pAkp`TY5lH*@Z`1u zmC7f(G17?-BBt%j9sYNYA_ O0000 + + + + + + + + diff --git a/defensive-coding/tmp/en-US/html/Common_Content/images/red.png b/defensive-coding/tmp/en-US/html/Common_Content/images/red.png new file mode 100644 index 0000000000000000000000000000000000000000..d32d5e2e80a459c02ec55c71091350a134df7f88 GIT binary patch literal 163 zcmeAS@N?(olHy`uVBq!ia0y~yU|?imV36ZrV_;x-JGJCE0|Ns~v6E*A2L}g74M$1` z0|NtRfk$L90|W1M5N34Jm|elZz#v)T8c`CQpH@mmtT}V z`<;yx0|SGCr;B3<$IRr2LkB+0?`&*rWbFKL{=k6)U&Uns07&a`Dp8O`gpP7My Ofx*+&&t;ucLK6VZGBDWy literal 0 HcmV?d00001 diff --git a/defensive-coding/tmp/en-US/html/Common_Content/images/redhat-logo.svg b/defensive-coding/tmp/en-US/html/Common_Content/images/redhat-logo.svg new file mode 100644 index 0000000..1001776 --- /dev/null +++ b/defensive-coding/tmp/en-US/html/Common_Content/images/redhat-logo.svg @@ -0,0 +1,94 @@ + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/html/Common_Content/images/rhlogo.png b/defensive-coding/tmp/en-US/html/Common_Content/images/rhlogo.png new file mode 100644 index 0000000000000000000000000000000000000000..ecd48565264f8553645a70206b72a5683c6ca469 GIT binary patch literal 2278 zcmV5Kdx!ZfsC)7PN zKaqRRx%b@jKg;)h_u$bq&EpiL5HJ|b10RCTU@tfZeg|KJJg^ju0quQxj!WQiD)jka z88`$q2h@Wv!QCL#?f4chI8r=#8#Fr~?+&6dcJ5X7N(31(;2srz=7W5gaKR z*umY?C7%f^4W6^1AxYQNmGz*S&Ciqq*($!$A3He|F zxEZtq7lY5i5M$BnK&mUoX%d`gwo+`Y@7kvpf)gbm6|@EY!8)$j##rE35^tX>INr5*!!LovoqWdV>ea9Ulr}cox&%-4&$xAh3$w)}m*(GQl4f+Wu{8 z5PZ4bU=sLw#qyjcxMgen6nvt!;B~EOFP8*ACgo9pX+R5Vt0xTnp*J|oK%{g*5Sa4X zx!^9a6cjlW{4slxxI6wMg3~{vg3t!?u)5n3e5lybpP9H=BMro950Xs=i_A7`J9?6ZUwt3wY%(*K+7Nsc8*lpW&$87o-K&~Ltt+_gHWb+v ze6`ro5n#TBV8vYK5{|x!_0P6&&$bvu>po?FUJ|{V&6mB4UY6;{*G7PMz)nSZEHIuY zz(*Wad>2eHv$FX^QVM?_-T|-}dS=ryYFBWiNH82M0dLTCy06JIuLaNWdr*vIB;7+Q zb0_l?_(J%d=&cfbi#$tdkDg|8dCuioKZGrL5Buf57<2cZEcit>1%F?tGa5V~-bX4s z#U$SF8+j~>`*-C79jZE|;7u#R0lLU@lm;Mpkv~jT^5K!TQXLu?-!L>dp5o8bWn8|q zPg!-8 zThd}2ptocU$&;d%SB5488=OUSLsx z{BIwu_cWV=FIBXC8<+}iQ$!L;>^{|zrI;f zFOt6jmo^0y`MsFH2$Dc?Z71wXZUVKew4v}YsO&iVDZ|( zQ{k5JDc?ELwNM_29}8PiC6_(vo=yaR(d@-%%$TuB6H-}O*|x&M!cEhsPcPIh`YXV6 zu#8W<*by2gr1l`_Wc=*y4g_B;)cabI-@}J9cZuLe`C2dp=Vg8sdkqu$v~UNrdpZ$( znEbL)QBie?iHT%AYT@DG_2uQ|J2WXZH#aw?rKOdqI;$HG0{V3ND44+C(kTvqAvnuk zhp%)X_!2Y0xy(_aOcKv}xc;7YOf)ay?a3fw>%5O0uYtr0u;7c>dXF%n^YZdGR#a5%gqZatYH4X{NnBi91?}TCH8npdM6b=v%*+oB4Q)IjcoPv(7a18z zu8S5H7S<3Q9sQ@C7ZVdxZF7d*?LhEM8-f=({pQZ1*9i4;6lEeLJ17u>?;}^v#K`kq zaQ@HBnn9|ns@h3|VZ(+E`9@`$nwpLrJa}+hb#?Ww#>U3-=6_Nx)y2<0K@$xaY% z$@$8L*rmGbV^f${Z3vz&lxfi2HAT60CO$sd0h5HhaK$O1dVd6`S5tJ zyJ=#*?`gJ!!-8Kg=6n4R+{?z%-|wsq@PEjKq;!^}P*zhlRal@?+j<~=paf#9!M3C`un)mm?3z}+s@OXfqCsb`F_a+{ov{LN>4@&pAjt4766MM41-Ui&l!J4thXSz^{4jdfz zS8(k6+T_WTwSN8jX~TyP*BTlc{>`IhUG6Zi*V~+skgz{KKK?*RNC=JGr}+ggkYmgy z9rifyVZ;g><>}?=k05u0M&oZ_16<~M&U;g3+&lr zE5F13UM(1bJF>I0W1KAK{=)lkh{HNjL2O@?4|SpyhMre6+H}If>Qf;$Me5k)tIf*F z$|plkD)Kw%6-=@JkEkw^=pO}A?AqGepCEM2xN+mQ*VotYR}>*v<}z21(<3+$266%+ zHfHj%L4yYENli`NqWkw!Y6Rn5F;1`G1pVRuN`D2%jNYe;)N%S1TmhX4Qo07*qoM6N<$f;VST Ai~s-t literal 0 HcmV?d00001 diff --git a/defensive-coding/tmp/en-US/html/Common_Content/images/shade.png b/defensive-coding/tmp/en-US/html/Common_Content/images/shade.png new file mode 100644 index 0000000000000000000000000000000000000000..a73afdf6a78818968c7574a20cbaf12116ab0924 GIT binary patch literal 101 zcmV-r0Gj`aP)i9VDNPHb6Mw<&;$Uy{362u literal 0 HcmV?d00001 diff --git a/defensive-coding/tmp/en-US/html/Common_Content/images/stock-go-back.png b/defensive-coding/tmp/en-US/html/Common_Content/images/stock-go-back.png new file mode 100644 index 0000000000000000000000000000000000000000..81602901515605bdae4651cb25ea781c982d3e1c GIT binary patch literal 571 zcmV-B0>u4^P)&|4~%IinQyDwd;+x?2xzYk+|-Yx$c&{@R+^unZEIxzww;F@}kA_qsH~6$M&bm z_NdDDs>}DR%=oU&_^;0SvCsLl(fYR2{I}Hoxz_!?+5W)W|H9n=$>IOaIy000eiQchC<4}Xup@9*#L@9*#LRjSgT00001VoOIvSnajMjsO4v#Ysd# zR4C75U>E?v$i&KwRhV1Engxq6mzaZ&JPW3f0t=Eb4^TMR(?mr{Nm)e|E&)^>6dvkpp|7E)uA!-^1()FU2oDSKw$#A~m z(|2@sc5!vZ^f?>9nVXll54Nyk6Lj(qV8I%?9Kvoaq{Ig$005q;8ybs}C71vJ002ov JPDHLkV1kE-9QptN literal 0 HcmV?d00001 diff --git a/defensive-coding/tmp/en-US/html/Common_Content/images/stock-go-forward.png b/defensive-coding/tmp/en-US/html/Common_Content/images/stock-go-forward.png new file mode 100644 index 0000000000000000000000000000000000000000..be8647411763bed05c7cfe2bf239ed1d2a829824 GIT binary patch literal 531 zcmV+u0_^>XP)EJPbEM;tCl9x_cIG*BQo zRwFrBBRX0oKVc?8WhX*rDMV>1Mr$ibZY)W1Fi?ClQ-MEdqDOYNNqfIjiq%z%)>n}cV=!LK8iL>g8wCjwu>y5VTk+|-Yx$cy^ z@0Psqn7#0uzwx5Q^Qz1Dv(fst)BMTd|IFk6|NsAvACCn9000GaQchClA<%_I9D2i?_toxPKTXsN+$Q9N4YAn2ANW;(Qm zCkKp+JkP6e6tSwwff=e;Ta~5h_tiohm;?a{RTahqSOttb6@df+C`5YM-g+Qdn&Rj VQlw5L0`LF;002ovPDHLkV1h7@>6-um literal 0 HcmV?d00001 diff --git a/defensive-coding/tmp/en-US/html/Common_Content/images/stock-go-up.png b/defensive-coding/tmp/en-US/html/Common_Content/images/stock-go-up.png new file mode 100644 index 0000000000000000000000000000000000000000..52a31edf4a3cfc277b5e16ba083e324216aedc70 GIT binary patch literal 582 zcmeAS@N?(olHy`uVBq!ia0y~yV2}V|4rT@hhU+WOo?>8Nlnw9+ab+M5aPSJVbMbTV z3iF98F)%Q22}<*b$O*{kNN74pX*)~ny33meX}Ra>dY2jnHyVXDTf|PVO<(Acx!9v} zk8k5~|CTd>9hZYTuLO5p4eh=b-g_;g|3>75n=un_#!kAGGW|~4j63Nw?`F)ppFR72 z&YTB%^B&|ccv!UXVez6zWlJBIFMCq8{7LnSXSFMz)vbEoxaN7&+7~VBUbL=%*|yR|DoW1|!oCBX09QnNX*w>}U zzb!xcZN;hY>(Bk%c>d?+i@&yC`MdkZzr8pA9k~7f*n|IPpZve{^8eM>|NsC0U&BA~ zF9QREU`dc)Fay85y?=auegFLZ=kMQt|Ni~=$?V%17#J9nyxm>mSgs}RW?*30<>}%W zqA_vr`MrEi4gxF>X0q-KX8E&P$H(K!p^U`DFMs3RlbdE$aLf_oa#~Wh>UNF!O`Q+d zS1b&k{p2?n-!9QB8AdO*G<^Afer^_{?e?(#J@N&IZp?bU>a@_EqQfTUop0OJa?S2I z)>z-mHCwGEe}TK$Na3%C`2yh|Cz(}JZ%&p9IR0Ek-Qi;6sz&jp)0tEpZ?gHZhFpBh z*rcMF9NH)@Ch5q;vZF4XrD1*0p8b=TbP0 Hl+XkK8W9I^ literal 0 HcmV?d00001 diff --git a/defensive-coding/tmp/en-US/html/Common_Content/images/stock-home.png b/defensive-coding/tmp/en-US/html/Common_Content/images/stock-home.png new file mode 100644 index 0000000000000000000000000000000000000000..b9ce2b86f16a501e464c9d121b28152d3956bebf GIT binary patch literal 772 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 Ai~s-t literal 0 HcmV?d00001 diff --git a/defensive-coding/tmp/en-US/html/Common_Content/images/title_logo.svg b/defensive-coding/tmp/en-US/html/Common_Content/images/title_logo.svg new file mode 100644 index 0000000..1001776 --- /dev/null +++ b/defensive-coding/tmp/en-US/html/Common_Content/images/title_logo.svg @@ -0,0 +1,94 @@ + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/html/Common_Content/images/warning.png b/defensive-coding/tmp/en-US/html/Common_Content/images/warning.png new file mode 100644 index 0000000000000000000000000000000000000000..3745cf6a3e6497a47f2128105ac411e00e77fe93 GIT binary patch literal 1940 zcmV;F2W$9=P)5haS8 zL}bLMg9QsJ33d?-MKKnX0ZR}CtXM%51VzdzpcFY!toN2D&+gs6_u`ctigHf8ncob< z?epyazx(d9yDzi@fOao4?Oqu$LdS01+atk94srqsK)!q_44}|XND~52P>XzR)dt8Y zBNarjjlDhm7B~r}P8|=OZF?{ig~*52Y#@mU?b5>zPG`k~*m#PPma-mxwy|X<)>@?j z6sBO0OVqjrl6c0_upnlDM}D*_11RV<VM#@EpPnTt(ir1_R59pibR;K;ija zl31ZW1B6?NAXNViqB=|Z{fR@d@>!VCrUp>JH^^fmCUl-sKiUn)K)4wPLe*w1__Nq> zLi*l++5~2x5&5(&4I~pGb`B0uSDvmnP_qMs%BW_DHM^zn%koobsnwa-&?W}3<38+B zh}pPEFTVaT2o>v$BC0c`cFUIp%ggFdFVp~b_&Rcl2yh+j3Xf!EQ>cmo;YOrU#GA2F zyE~Pc;ON|knaFt22K?CQAKo9O7hjtK!u6HrsXHLG-=45SzM$P-hym>A1Kq(4Ci;$+ zmB|w*@J|p_%gj@;8W(gnjp5bVFwD!H87M*CdJzU9SlKMfP128kbs{_{UI2wz!6vEB zoeO+<7znt?SzLBzoO~97pQ{1vpaY^Ioh=Lv)Q>*adA@8RROf_%kz=$(bks5sn=S%R zW1@(Kxk^Q6fG?ddwHIoWq$Bh& zZx7bK40*dX3`A)YHik)TOxj)a|A4C3AqgJkBV8tsHFBz)rqMW|Y=M;jMt%Zx z)0frFPh|iDU0CM{n|{X;N~Q=^n}91AZIV43jT`Xs`&Db;{uSe~m&a)D4Z40J!>7y3 zYL^xnz<@V&?{HvfyAWNkHWAZS*I)&RL$nuz7E21xxhskTDz zzS2v8V=XnHWE~&fyBN#mHVUs=0^B7}v*e|?88r~LESwq;>Qc$G?+v6+ zt}+h1y``d{Lf)~&z#0^Jnjvw z-?Qn98A@+v;2!doIRj~=p@UN|P!~nu(8#RDm3}RE2xM7O+c16INuQ~5%F?Gir!M3NZ z!6J^2-wfiz>)1wNS*{!fo|zU%I#w+m&vJ=~O)~@J4Vmsu8F+X&gQhebPm0SyC=bUe z9SE9p_7-z)hn>+XG&5v2?!x!*7#(bRzC3rW4y37QDfHHgByP;(AP|J3)-40pkW?y%34=e(1o>&VVY^2ew>G4QVL^&YHR + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/html/Common_Content/images/watermark-draft.png b/defensive-coding/tmp/en-US/html/Common_Content/images/watermark-draft.png new file mode 100644 index 0000000000000000000000000000000000000000..0ead5af8bb8848a33500be3d5124c19a424bb7c8 GIT binary patch literal 25365 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 bmtpr7qXd-&e_k*!Ffe$!`njxgN@xNACz&=4 literal 0 HcmV?d00001 diff --git a/defensive-coding/tmp/en-US/html/ch01s03s04.html b/defensive-coding/tmp/en-US/html/ch01s03s04.html new file mode 100644 index 0000000..14dc3a3 --- /dev/null +++ b/defensive-coding/tmp/en-US/html/ch01s03s04.html @@ -0,0 +1,12 @@ + +1.3.4. Custom memory allocators

Product SiteDocumentation Site

1.3.4. Custom memory allocators

+ Custom memory allocates come in two forms: replacements for malloc, and completely different interfaces for memory management. Both approaches can reduce the effectiveness of valgrind and similar tools, and the heap corruption detection provided by GNU libc, so they should be avoided. +
+ Memory allocators are difficult to write and contain many performance and security pitfalls. +
  • + When computing array sizes or rounding up allocation requests (to the next allocation granularity, or for alignment purposes), checks for arithmetic overflow are required. +
  • + Size computations for array allocations need overflow checking. See Section 1.3.3, “Array allocation”. +
  • + It can be difficult to beat well-tuned general-purpose allocators. In micro-benchmarks, pool allocators can show huge wins, and size-specific pools can reduce internal fragmentation. But often, utilization of individual pools is poor, and +
\ No newline at end of file diff --git a/defensive-coding/tmp/en-US/html/ch01s03s05.html b/defensive-coding/tmp/en-US/html/ch01s03s05.html new file mode 100644 index 0000000..accb5f0 --- /dev/null +++ b/defensive-coding/tmp/en-US/html/ch01s03s05.html @@ -0,0 +1,6 @@ + +1.3.5. Conservative garbage collection

Product SiteDocumentation Site

1.3.5. Conservative garbage collection

+ Garbage collection can be an alternative to explicit memory management using malloc and free. The Boehm-Dehmers-Weiser allocator can be used from C programs, with minimal type annotations. Performance is competitive with malloc on 64-bit architectures, especially for multi-threaded programs. The stop-the-world pauses may be problematic for some real-time applications, though. +
+ However, using a conservative garbage collector may reduce opertunities for code reduce because once one library in a program uses garbage collection, the whole process memory needs to be subject to it, so that no pointers are missed. The Boehm-Dehmers-Weiser collector also reserves certain signals for internal use, so it is not fully transparent to the rest of the program. +
\ No newline at end of file diff --git a/defensive-coding/tmp/en-US/html/ch03s02.html b/defensive-coding/tmp/en-US/html/ch03s02.html new file mode 100644 index 0000000..62c8422 --- /dev/null +++ b/defensive-coding/tmp/en-US/html/ch03s02.html @@ -0,0 +1,14 @@ + +3.2. Run-time compilation and code generation

Product SiteDocumentation Site

3.2. Run-time compilation and code generation

+ The following Python functions and statements related to code execution should be avoided: +
  • + compile +
  • + eval +
  • + exec +
  • + execfile +
+ If you need to parse integers or floating point values, use the int and float functions instead of eval. Sandboxing untrusted Python code does not work reliably. +
\ No newline at end of file diff --git a/defensive-coding/tmp/en-US/html/ch03s03.html b/defensive-coding/tmp/en-US/html/ch03s03.html new file mode 100644 index 0000000..5452b7d --- /dev/null +++ b/defensive-coding/tmp/en-US/html/ch03s03.html @@ -0,0 +1,4 @@ + +3.3. Sandboxing

Product SiteDocumentation Site

3.3. Sandboxing

+ The rexec Python module cannot safely sandbox untrusted code and should not be used. The standard CPython implementation is not suitable for sandboxing. +
\ No newline at end of file diff --git a/defensive-coding/tmp/en-US/html/ch04s02.html b/defensive-coding/tmp/en-US/html/ch04s02.html new file mode 100644 index 0000000..8b9faf7 --- /dev/null +++ b/defensive-coding/tmp/en-US/html/ch04s02.html @@ -0,0 +1,6 @@ + +4.2. Object orientation

Product SiteDocumentation Site

4.2. Object orientation

+ Classes should be either designed as base classes, or it should be impossible to use them as base classes (like final classes in Java). Classes which are not designed for inheritance and are used as base classes nevertheless create potential maintenance hazards because it is difficult to predict how client code will react when calls to virtual methods are added, reordered or removed. +
+ Virtual member functions can be used as callbacks. See Section 4.3, “Callbacks” for some of the challenges involved. +
\ No newline at end of file diff --git a/defensive-coding/tmp/en-US/html/ch04s04.html b/defensive-coding/tmp/en-US/html/ch04s04.html new file mode 100644 index 0000000..dc8c688 --- /dev/null +++ b/defensive-coding/tmp/en-US/html/ch04s04.html @@ -0,0 +1,20 @@ + +4.4. Process attributes

Product SiteDocumentation Site

4.4. Process attributes

+ Several attributes are global and affect all code in the process, not just the library that manipulates them. +
  • + umask +
  • + user IDs, group IDs and capabilities +
  • + current working directory +
  • + signal handlers, signal masks and signal delivery +
  • + file locks (especially fcntl locks behave in surprising ways, not just in a multi-threaded environment) +
+ Library code should avoid manipulating these global process attributes. It should not rely on environment variables, umask, the current working directory and signal masks because these attributes can be inherted from an untrusted source. +
+ In addition, there are obvious process-wide aspects such as the virtual memory layout, the set of open files and dynamic shared objects, but with the exception of shared objects, these can be manipulated in a relatively isolated way. +
\ No newline at end of file diff --git a/defensive-coding/tmp/en-US/html/ch07s02.html b/defensive-coding/tmp/en-US/html/ch07s02.html new file mode 100644 index 0000000..8e45a3e --- /dev/null +++ b/defensive-coding/tmp/en-US/html/ch07s02.html @@ -0,0 +1,10 @@ + +7.2. Named temporary files

Product SiteDocumentation Site

7.2. Named temporary files

+ The mkostemp function creates a named temporary file. You should specify the O_CLOEXEC flag to avoid file descriptor leaks to subprocesses. (Applications which do not use multiple threads can also use mkstemp, but libraries should use mkostemp.) For determining the directory part of the file name pattern, see Section 7.1, “Obtaining the location of temporary directory”. +
+ The file is not removed automatically. It is not safe to rename or delete the file before processing, or transform the name in any way (for example, by adding a file extension). If you need multiple temporary files, call mkostemp multiple times. Do not create additional file names derived from the name provided by a previous mkostemp call. However, it is safe to close the descriptor returned by mkostemp and reopen the file using the generated name. +
+ The Python class tempfile.NamedTemporaryFile provides similar functionality, except that the file is deleted automatically by default. Note that you may have to use the file attribute to obtain the actual file object because some programming interfaces cannot deal with file-like objects. The C function mkostemp is also available as tempfile.mkstemp. +
+ In Java, you can use the java.io.File.createTempFile(String, String, File) function, using the temporary file location determined according to Section 7.1, “Obtaining the location of temporary directory”. Do not use java.io.File.deleteOnExit() to delete temporary files, and do not register a shutdown hook for each temporary file you create. In both cases, the deletion hint cannot be removed from the system if you delete the temporary file prior to termination of the VM, causing a memory leak. +
\ No newline at end of file diff --git a/defensive-coding/tmp/en-US/html/ch07s03.html b/defensive-coding/tmp/en-US/html/ch07s03.html new file mode 100644 index 0000000..401cd33 --- /dev/null +++ b/defensive-coding/tmp/en-US/html/ch07s03.html @@ -0,0 +1,10 @@ + +7.3. Temporary files without names

Product SiteDocumentation Site

7.3. Temporary files without names

+ The tmpfile function creates a temporary file and immediately deletes it, while keeping the file open. As a result, the file lacks a name and its space is deallocated as soon as the file descriptor is closed (including the implicit close when the process terminates). This avoids cluttering the temporary directory with orphaned files. +
+ Alternatively, if the maximum size of the temporary file is known beforehand, the fmemopen function can be used to create a FILE * object which is backed by memory. +
+ In Python, unnamed temporary files are provided by the tempfile.TemporaryFile class, and the tempfile.SpooledTemporaryFile class provides a way to avoid creation of small temporary files. +
+ Java does not support unnamed temporary files. +
\ No newline at end of file diff --git a/defensive-coding/tmp/en-US/html/ch07s05.html b/defensive-coding/tmp/en-US/html/ch07s05.html new file mode 100644 index 0000000..8966542 --- /dev/null +++ b/defensive-coding/tmp/en-US/html/ch07s05.html @@ -0,0 +1,16 @@ + +7.5. Compensating for unsafe file creation

Product SiteDocumentation Site

7.5. Compensating for unsafe file creation

+ There are two ways to make a function or program which excepts a file name safe for use with temporary files. See Section 8.1, “Safe process creation”, for details on subprocess creation. +
  • + Create a temporary directory and place the file there. If possible, run the program in a subprocess which uses the temporary directory as its current directory, with a restricted environment. Use generated names for all files in that temporary directory. (See Section 7.4, “Temporary directories”.) +
  • + Create the temporary file and pass the generated file name to the function or program. This only works if the function or program can cope with a zero-length existing file. It is safe only under additional assumptions: +
    • + The function or program must not create additional files whose name is derived from the specified file name or are otherwise predictable. +
    • + The function or program must not delete the file before processing it. +
    • + It must not access any existing files in the same directory. +
    + It is often difficult to check whether these additional assumptions are matched, therefore this approach is not recommended. +
\ No newline at end of file diff --git a/defensive-coding/tmp/en-US/html/ch08s02.html b/defensive-coding/tmp/en-US/html/ch08s02.html new file mode 100644 index 0000000..0781cb1 --- /dev/null +++ b/defensive-coding/tmp/en-US/html/ch08s02.html @@ -0,0 +1,14 @@ + +8.2. Handling child process termination

Product SiteDocumentation Site

8.2. Handling child process termination

+ When child processes terminate, the parent process is signalled. A stub of the terminated processes (a zombie, shown as <defunct> by ps) is kept around until the status information is collected (reaped) by the parent process. Over the years, several interfaces for this have been invented: +
  • + The parent process calls wait, waitpid, waitid, wait3 or wait4, without specifying a process ID. This will deliver any matching process ID. This approach is typically used from within event loops. +
  • + The parent process calls waitpid, waitid, or wait4, with a specific process ID. Only data for the specific process ID is returned. This is typically used in code which spawns a single subprocess in a synchronous manner. +
  • + The parent process installs a handler for the SIGCHLD signal, using sigaction, and specifies to the SA_NOCLDWAIT flag. This approach could be used by event loops as well. +
+ None of these approaches can be used to wait for child process terminated in a completely thread-safe manner. The parent process might execute an event loop in another thread, which could pick up the termination signal. This means that libraries typically cannot make free use of child processes (for example, to run problematic code with reduced privileges in a separate address space). +
+ At the moment, the parent process should explicitly wait for termination of the child process using waitpid or waitpid, and hope that the status is not collected by an event loop first. +
\ No newline at end of file diff --git a/defensive-coding/tmp/en-US/html/ch08s03.html b/defensive-coding/tmp/en-US/html/ch08s03.html new file mode 100644 index 0000000..05b82d8 --- /dev/null +++ b/defensive-coding/tmp/en-US/html/ch08s03.html @@ -0,0 +1,34 @@ + +8.3. SUID/SGID processes

Product SiteDocumentation Site

8.3. SUID/SGID processes

+ Programs can be marked in the file system to indicate to the kernel that a trust transition should happen if the program is run. The SUID file permission bit indicates that an executable should run with the effective user ID equal to the owner of the executable file. Similarly, with the SGID bit, the effective group ID is set to the group of the executable file. +
+ Linux supports fscaps, which can grant additional capabilities to a process in a finer-grained manner. Additional mechanisms can be provided by loadable security modules. +
+ When such a trust transition has happened, the process runs in a potentially hostile environment. Additional care is necessary not to rely on any untrusted information. These concerns also apply to libraries which can be linked into such processes. +

8.3.1. Accessing environment variables

+ The following steps are required so that a program does not accidentally pick up untrusted data from environment variables. +
  • + Compile your C/C++ sources with -D_GNU_SOURCE. The Autoconf macro AC_GNU_SOURCE ensures this. +
  • + Check for the presence of the secure_getenv and __secure_getenv function. The Autoconf directive AC_CHECK_FUNCS([__secure_getenv secure_getenv]) performs these checks. +
  • + Arrange for a proper definition of the secure_getenv function. See Example 8.1, “Obtaining a definition for secure_getenv. +
  • + Use secure_getenv instead of getenv to obtain the value of critical environment variables. secure_getenv will pretend the variable has not bee set if the process environment is not trusted. +
+ Critical environment variables are debugging flags, configuration file locations, plug-in and log file locations, and anything else that might be used to bypass security restrictions or cause a privileged process to behave in an unexpected way. +
+ Either the secure_getenv function or the __secure_getenv is available from GNU libc. +
Example 8.1. Obtaining a definition for secure_getenv
+
+#include <stdlib.h>
+
+#ifndef HAVE_SECURE_GETENV
+#  ifdef HAVE__SECURE_GETENV
+#    define secure_getenv __secure_getenv
+#  else
+#    error neither secure_getenv nor __secure_getenv are available
+#  endif
+#endif
+
+

\ No newline at end of file diff --git a/defensive-coding/tmp/en-US/html/ch08s05.html b/defensive-coding/tmp/en-US/html/ch08s05.html new file mode 100644 index 0000000..2cfd640 --- /dev/null +++ b/defensive-coding/tmp/en-US/html/ch08s05.html @@ -0,0 +1,8 @@ + +8.5. Semantics of command line arguments

Product SiteDocumentation Site

8.5. Semantics of command line arguments

+ After process creation and option processing, it is up to the child process to interpret the arguments. Arguments can be file names, host names, or URLs, and many other things. URLs can refer to the local network, some server on the Internet, or to the local file system. Some applications even accept arbitrary code in arguments (for example, python with the -c option). +
+ Similar concerns apply to environment variables, the contents of the current directory and its subdirectories. +
+ Consequently, careful analysis is required if it is safe to pass untrusted data to another program. +
\ No newline at end of file diff --git a/defensive-coding/tmp/en-US/html/ch09s02.html b/defensive-coding/tmp/en-US/html/ch09s02.html new file mode 100644 index 0000000..d5aa39b --- /dev/null +++ b/defensive-coding/tmp/en-US/html/ch09s02.html @@ -0,0 +1,4 @@ + +9.2. Protocol design

Product SiteDocumentation Site

9.2. Protocol design

+ Binary formats with explicit length fields are more difficult to parse robustly than those where the length of dynamically-sized elements is derived from sentinel values. A protocol which does not use length fields and can be written in printable ASCII characters simplifies testing and debugging. However, binary protocols with length fields may be more efficient to parse. +
\ No newline at end of file diff --git a/defensive-coding/tmp/en-US/html/ch09s03.html b/defensive-coding/tmp/en-US/html/ch09s03.html new file mode 100644 index 0000000..c2b359e --- /dev/null +++ b/defensive-coding/tmp/en-US/html/ch09s03.html @@ -0,0 +1,20 @@ + +9.3. Library support for deserialization

Product SiteDocumentation Site

9.3. Library support for deserialization

+ For some languages, generic libraries are available which allow to serialize and deserialize user-defined objects. The deserialization part comes in one of two flavors, depending on the library. The first kind uses type information in the data stream to control which objects are instantiated. The second kind uses type definitions supplied by the programmer. The first one allows arbitrary object instantiation, the second one generally does not. +
+ The following serialization frameworks are in the first category, are known to be unsafe, and must not be used for untrusted data: +
  • + Python's pickle and cPickle modules +
  • + Perl's Storable package +
  • + Java serialization (java.io.ObjectInputStream) +
  • + PHP serialization (unserialize) +
  • + Most implementations of YAML +
+ When using a type-directed deserialization format where the types of the deserialized objects are specified by the programmer, make sure that the objects which can be instantiated cannot perform any destructive actions in their destructors, even when the data members have been manipulated. +
+ JSON decoders do not suffer from this problem. But you must not use the eval function to parse JSON objects in Javascript; even with the regular expression filter from RFC 4627, there are still information leaks remaining. +
\ No newline at end of file diff --git a/defensive-coding/tmp/en-US/html/ch09s05.html b/defensive-coding/tmp/en-US/html/ch09s05.html new file mode 100644 index 0000000..a80e585 --- /dev/null +++ b/defensive-coding/tmp/en-US/html/ch09s05.html @@ -0,0 +1,8 @@ + +9.5. Protocol Encoders

Product SiteDocumentation Site

9.5. Protocol Encoders

+ For protocol encoders, you should write bytes to a buffer which grows as needed, using an exponential sizing policy. Explicit lengths can be patched in later, once they are known. Allocating the required number of bytes upfront typically requires separate code to compute the final size, which must be kept in sync with the actual encoding step, or vulnerabilities may result. In multi-threaded code, parts of the object being deserialized might change, so that the computed size is out of date. +
+ You should avoid copying data directly from a received packet during encoding, disregarding the format. Propagating malformed data could enable attacks on other recipients of that data. +
+ When using C or C++ and copying whole data structures directly into the output, make sure that you do not leak information in padding bytes between fields or at the end of the struct. +
\ No newline at end of file diff --git a/defensive-coding/tmp/en-US/html/ch10s02.html b/defensive-coding/tmp/en-US/html/ch10s02.html new file mode 100644 index 0000000..91b3c8f --- /dev/null +++ b/defensive-coding/tmp/en-US/html/ch10s02.html @@ -0,0 +1,24 @@ + +10.2. Randomness

Product SiteDocumentation Site

10.2. Randomness

+ The following facilities can be used to generate unpredictable and non-repeating values. When these functions are used without special safeguards, each individual rnadom value should be at least 12 bytes long. +
  • + PK11_GenerateRandom in the NSS library (usable for high data rates) +
  • + RAND_bytes in the OpenSSL library (usable for high data rates) +
  • + gnutls_rnd in GNUTLS, with GNUTLS_RND_RANDOM as the first argument (usable for high data rates) +
  • + java.security.SecureRandom in Java (usable for high data rates) +
  • + os.urandom in Python +
  • + Reading from the /dev/urandom character device +
+ All these functions should be non-blocking, and they should not wait until physical randomness becomes available. (Some cryptography providers for Java can cause java.security.SecureRandom to block, however.) Those functions which do not obtain all bits directly from /dev/urandom are suitable for high data rates because they do not deplete the system-wide entropy pool. +

Difficult to use API

+ Both RAND_bytes and PK11_GenerateRandom have three-state return values (with conflicting meanings). Careful error checking is required. Please review the documentation when using these functions. +
+ Other sources of randomness should be considered predictable. +
+ Generating randomness for cryptographic keys in long-term use may need different steps and is best left to cryptographic libraries. +
\ No newline at end of file diff --git a/defensive-coding/tmp/en-US/html/chap-Defensive_Coding-Authentication.html b/defensive-coding/tmp/en-US/html/chap-Defensive_Coding-Authentication.html new file mode 100644 index 0000000..0b6019c --- /dev/null +++ b/defensive-coding/tmp/en-US/html/chap-Defensive_Coding-Authentication.html @@ -0,0 +1,16 @@ + +Chapter 11. Authentication and Authorization

Product SiteDocumentation Site

Chapter 11. Authentication and Authorization

11.1. Authenticating servers

+ When connecting to a server, a client has to make sure that it is actually talking to the server it expects. There are two different aspects, securing the network path, and making sure that the expected user runs the process on the target host. There are several ways to ensure that: +
  • + The server uses a TLS certificate which is valid according to the web browser public key infrastructure, and the client verifies the certificate and the host name. +
  • + The server uses a TLS certificate which is expectedby the client (perhaps it is stored in a configuration file read by the client). In this case, no host name checking is required. +
  • + On Linux, UNIX domain sockets (of the PF_UNIX protocol family, sometimes called PF_LOCAL) are restricted by file system permissions. If the server socket path is not world-writable, the server identity cannot be spoofed by local users. +
  • + Port numbers less than 1024 (trusted ports) can only be used by root, so if a UDP or TCP server is running on the local host and it uses a trusted port, its identity is assured. (Not all operating systems enforce the trusted ports concept, and the network might not be trusted, so it is only useful on the local system.) +
+ TLS (Chapter 12, Transport Layer Security) is the recommended way for securing connections over untrusted networks. +
+ If the server port number is 1024 is higher, a local user can impersonate the process by binding to this socket, perhaps after crashing the real server by exploiting a denial-of-service vulnerability. +
\ No newline at end of file diff --git a/defensive-coding/tmp/en-US/html/chap-Defensive_Coding-C.html b/defensive-coding/tmp/en-US/html/chap-Defensive_Coding-C.html new file mode 100644 index 0000000..42c5195 --- /dev/null +++ b/defensive-coding/tmp/en-US/html/chap-Defensive_Coding-C.html @@ -0,0 +1,105 @@ + +Chapter 1. The C Programming Language

Product SiteDocumentation Site

Chapter 1. The C Programming Language

1.1. The core language

+ C provides no memory safety. Most recommendations in this section deal with this aspect of the language. +

1.1.1. Undefined behavior

+ Some C constructs are defined to be undefined by the C standard. This does not only mean that the standard does not describe what happens when the construct is executed. It also allows optimizing compilers such as GCC to assume that this particular construct is never reached. In some cases, this has caused GCC to optimize security checks away. (This is not a flaw in GCC or the C language. But C certainly has some areas which are more difficult to use than others.) +
+ Common sources of undefined behavior are: +
  • + out-of-bounds array accesses +
  • + null pointer dereferences +
  • + overflow in signed integer arithmetic +

1.1.2. Recommendations for pointers and array handling

+ Always keep track of the size of the array you are working with. Often, code is more obviously correct when you keep a pointer past the last element of the array, and calculate the number of remaining elements by substracting the current position from that pointer. The alternative, updating a separate variable every time when the position is advanced, is usually less obviously correct. +
+ Example 1.1, “Array processing in C” shows how to extract Pascal-style strings from a character buffer. The two pointers kept for length checks are inend and outend. inp and outp are the respective positions. The number of input bytes is checked using the expression len > (size_t)(inend - inp). The cast silences a compiler warning; inend is always larger than inp. +
Example 1.1. Array processing in C
+ssize_t
+extract_strings(const char *in, size_t inlen, char **out, size_t outlen)
+{
+  const char *inp = in;
+  const char *inend = in + inlen;
+  char **outp = out;
+  char **outend = out + outlen;
+
+  while (inp != inend) {
+    size_t len;
+    char *s;
+    if (outp == outend) {
+      errno = ENOSPC;
+      goto err;
+    }
+    len = (unsigned char)*inp;
+    ++inp;
+    if (len > (size_t)(inend - inp)) {
+      errno = EINVAL;
+      goto err;
+    }
+    s = malloc(len + 1);
+    if (s == NULL) {
+      goto err;
+    }
+    memcpy(s, inp, len);
+    inp += len;
+    s[len] = '\0';
+    *outp = s;
+    ++outp;
+  }
+  return outp - out;
+err:
+  {
+    int errno_old = errno;
+    while (out != outp) {
+      free(*out);
+      ++out;
+    }
+    errno = errno_old;
+  }
+  return -1;
+}
+

+ It is important that the length checks always have the form len > (size_t)(inend - inp), where len is a variable of type size_t which denotes the total number of bytes which are about to be read or written next. In general, it is not safe to fold multiple such checks into one, as in len1 + len2 > (size_t)(inend - inp), because the expression on the left can overflow or wrap around (see Section 1.1.3, “Recommendations for integer arithmetic”), and it no longer reflects the number of bytes to be processed. +

1.1.3. Recommendations for integer arithmetic

+ Overflow in signed integer arithmetic is undefined. This means that it is not possible to check for overflow after it happened, see Example 1.2, “Incorrect overflow detection in C”. +
Example 1.2. Incorrect overflow detection in C
+void report_overflow(void);
+
+int
+add(int a, int b)
+{
+  int result = a + b;
+  if (a < 0 || b < 0) {
+    return -1;
+  }
+  // The compiler can optimize away the following if statement.
+  if (result < 0) {
+    report_overflow();
+  }
+  return result;
+}
+

+ The following approaches can be used to check for overflow, without actually causing it. +
  • + Use a wider type to perform the calculation, check that the result is within bounds, and convert the result to the original type. All intermediate results must be checked in this way. +
  • + Perform the calculation in the corresponding unsigned type and use bit fiddling to detect the overflow. +
  • + Compute bounds for acceptable input values which are known to avoid overflow, and reject other values. This is the preferred way for overflow checking on multiplications, see Example 1.3, “Overflow checking for unsigned multiplication”. +
Example 1.3. Overflow checking for unsigned multiplication
+unsigned
+mul(unsigned a, unsigned b)
+{
+  if (b && a > ((unsigned)-1) / b) {
+    report_overflow();
+  }
+  return a * b;
+}
+

+ Basic arithmetic operations a commutative, so for bounds checks, there are two different but mathematically equivalent expressions. Sometimes, one of the expressions results in better code because parts of it can be reduced to a constant. This applies to overflow checks for multiplication a * b involving a constant a, where the expression is reduced to b > C for some constant C determined at compile time. The other expression, b && a > ((unsigned)-1) / b, is more difficult to optimize at compile time. +
+ When a value is converted to a signed integer, GCC always chooses the result based on 2's complement arithmetic. This GCC extension (which is also implemented by other compilers) helps a lot when implementing overflow checks. +
+ Legacy code should be compiled with the -fwrapv GCC option. As a result, GCC will provide 2's complement semantics for integer arithmetic, including defined behavior on integer overflow. +
\ No newline at end of file diff --git a/defensive-coding/tmp/en-US/html/chap-Defensive_Coding-CXX.html b/defensive-coding/tmp/en-US/html/chap-Defensive_Coding-CXX.html new file mode 100644 index 0000000..bc7ca5a --- /dev/null +++ b/defensive-coding/tmp/en-US/html/chap-Defensive_Coding-CXX.html @@ -0,0 +1,48 @@ + +Chapter 2. The C++ Programming Language

Product SiteDocumentation Site

Chapter 2. The C++ Programming Language

2.1. The core language

+ C++ includes a large subset of the C language. As far as the C subset is used, the recommendations in Chapter 1, The C Programming Language apply. +

2.1.1. Array allocation with operator new[]

+ For very large values of n, an expression like new T[n] can return a pointer to a heap region which is too small. In other words, not all array elements are actually backed with heap memory reserved to the array. Current GCC versions generate code that performs a computation of the form sizeof(T) * size_t(n) + cookie_size, where cookie_size is currently at most 8. This computation can overflow, and GCC-generated code does not detect this. +
+ The std::vector template can be used instead an explicit array allocation. (The GCC implementation detects overflow internally.) +
+ If there is no alternative to operator new[], code which allocates arrays with a variable length must check for overflow manually. For the new T[n] example, the size check could be n || (n > 0 && n > (size_t(-1) - 8) / sizeof(T)). (See Section 1.1.3, “Recommendations for integer arithmetic”.) If there are additional dimensions (which must be constants according to the C++ standard), these should be included as factors in the divisor. +
+ These countermeasures prevent out-of-bounds writes and potential code execution. Very large memory allocations can still lead to a denial of service. Section 9.1, “Recommendations for manually written decoders” contains suggestions for mitigating this problem when processing untrusted data. +
+ See Section 1.3.3, “Array allocation” for array allocation advice for C-style memory allocation. +

2.1.2. Overloading

+ Do not overload functions with versions that have different security characteristics. For instance, do not implement a function strcat which works on std::string arguments. Similarly, do not name methods after such functions. +

2.1.3. ABI compatibility and preparing for security updates

+ A stable binary interface (ABI) is vastly preferred for security updates. Without a stable ABI, all reverse dependencies need recompiling, which can be a lot of work and could even be impossible in some cases. Ideally, a security update only updates a single dynamic shared object, and is picked up automatically after restarting affected processes. +
+ Outside of extremely performance-critical code, you should ensure that a wide range of changes is possible without breaking ABI. Some very basic guidelines are: +
  • + Avoid inline functions. +
  • + Use the pointer-to-implementation idiom. +
  • + Try to avoid templates. Use them if the increased type safety provides a benefit to the programmer. +
  • + Move security-critical code out of templated code, so that it can be patched in a central place if necessary. +
+ The KDE project publishes a document with more extensive guidelines on ABI-preserving changes to C++ code, Policies/Binary Compatibility Issues With C++ (d-pointer refers to the pointer-to-implementation idiom). +

2.1.4. C++0X and C++11 support

+ GCC offers different language compatibility modes: +
  • + -std=c++98 for the original 1998 C++ standard +
  • + -std=c++03 for the 1998 standard with the changes from the TR1 technical report +
  • + -std=c++11 for the 2011 C++ standard. This option should not be used. +
  • + -std=c++0x for several different versions of C++11 support in development, depending on the GCC version. This option should not be used. +
+ For each of these flags, there are variants which also enable GNU extensions (mostly language features also found in C99 or C11): -std=gnu++98, -std=gnu++03, -std=gnu++11. Again, -std=gnu++11 should not be used. +
+ If you enable C++11 support, the ABI of the standard C++ library libstdc++ will change in subtle ways. Currently, no C++ libraries are compiled in C++11 mode, so if you compile your code in C++11 mode, it will be incompatible with the rest of the system. Unfortunately, this is also the case if you do not use any C++11 features. Currently, there is no safe way to enable C++11 mode (except for freestanding applications). +
+ The meaning of C++0X mode changed from GCC release to GCC release. Earlier versions were still ABI-compatible with C++98 mode, but in the most recent versions, switching to C++0X mode activates C++11 support, with its compatibility problems. +
+ Some C++11 features (or approximations thereof) are available with TR1 support, that is, with -std=c++03 or -std=gnu++03 and in the <tr1/*> header files. This includes std::tr1::shared_ptr (from <tr1/memory>) and std::tr1::function (from <tr1/functional>). For other C++11 features, the Boost C++ library contains replacements. +
\ No newline at end of file diff --git a/defensive-coding/tmp/en-US/html/chap-Defensive_Coding-Python.html b/defensive-coding/tmp/en-US/html/chap-Defensive_Coding-Python.html new file mode 100644 index 0000000..d8d3d9c --- /dev/null +++ b/defensive-coding/tmp/en-US/html/chap-Defensive_Coding-Python.html @@ -0,0 +1,16 @@ + +Chapter 3. The Python Programming Language

Product SiteDocumentation Site

Chapter 3. The Python Programming Language

+ Python provides memory safety by default, so low-level security vulnerabilities are rare and typically needs fixing the Python interpreter or standard library itself. +
+ Other sections with Python-specific advice include: +

3.1. Dangerous standard library features

+ Some areas of the standard library, notably the ctypes module, do not provide memory safety guarantees comparable to the rest of Python. If such functionality is used, the advice in Section 1.1, “The core language” should be followed. +
\ No newline at end of file diff --git a/defensive-coding/tmp/en-US/html/chap-Defensive_Coding-TLS.html b/defensive-coding/tmp/en-US/html/chap-Defensive_Coding-TLS.html new file mode 100644 index 0000000..0cccaf4 --- /dev/null +++ b/defensive-coding/tmp/en-US/html/chap-Defensive_Coding-TLS.html @@ -0,0 +1,99 @@ + +Chapter 12. Transport Layer Security

Product SiteDocumentation Site

Chapter 12. Transport Layer Security

+ Transport Layer Security (TLS, formerly Secure Sockets Layer/SSL) is the recommended way to to protect integrity and confidentiality while data is transferred over an untrusted network connection, and to identify the endpoint. +

12.1. Common Pitfalls

+ TLS implementations are difficult to use, and most of them lack a clean API design. The following sections contain implementation-specific advice, and some generic pitfalls are mentioned below. +
  • + Most TLS implementations have questionable default TLS cipher suites. Most of them enable anonymous Diffie-Hellman key exchange (but we generally want servers to authenticate themselves). Many do not disable ciphers which are subject to brute-force attacks because of restricted key lengths. Some even disable all variants of AES in the default configuration. +
    + When overriding the cipher suite defaults, it is recommended to disable all cipher suites which are not present on a whitelist, instead of simply enabling a list of cipher suites. This way, if an algorithm is disabled by default in the TLS implementation in a future security update, the application will not re-enable it. +
  • + The name which is used in certificate validation must match the name provided by the user or configuration file. No host name canonicalization or IP address lookup must be performed. +
  • + The TLS handshake has very poor performance if the TCP Nagle algorithm is active. You should switch on the TCP_NODELAY socket option (at least for the duration of the handshake), or use the Linux-specific TCP_CORK option. +
    Example 12.1. Deactivating the TCP Nagle algorithm
    +const int val = 1;
    +int ret = setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val));
    +if (ret < 0) {
    +  perror("setsockopt(TCP_NODELAY)");
    +  exit(1);
    +}
    +

  • + Implementing proper session resumption decreases handshake overhead considerably. This is important if the upper-layer protocol uses short-lived connections (like most application of HTTPS). +
  • + Both client and server should work towards an orderly connection shutdown, that is send close_notify alerts and respond to them. This is especially important if the upper-layer protocol does not provide means to detect connection truncation (like some uses of HTTP). +
  • + When implementing a server using event-driven programming, it is important to handle the TLS handshake properly because it includes multiple network round-trips which can block when an ordinary TCP accept would not. Otherwise, a client which fails to complete the TLS handshake for some reason will prevent the server from handling input from other clients. +
  • + Unlike regular file descriptors, TLS connections cannot be passed between processes. Some TLS implementations add additional restrictions, and TLS connections generally cannot be used across fork function calls (see Section 8.6, “fork as a primitive for parallelism”). +

12.1.1. OpenSSL Pitfalls

+ Some OpenSSL function use tri-state return values. Correct error checking is extremely important. Several functions return int values with the following meaning: +
  • + The value 1 indicates success (for example, a successful signature verification). +
  • + The value 0 indicates semantic failure (for example, a signature verification which was unsuccessful because the signing certificate was self-signed). +
  • + The value -1 indicates a low-level error in the system, such as failure to allocate memory using malloc. +
+ Treating such tri-state return values as booleans can lead to security vulnerabilities. Note that some OpenSSL functions return boolean results or yet another set of status indicators. Each function needs to be checked individually. +
+ Recovering precise error information is difficult. Example 12.2, “Obtaining OpenSSL error codes” shows how to obtain a more precise error code after a function call on an SSL object has failed. However, there are still cases where no detailed error information is available (e.g., if SSL_shutdown fails due to a connection teardown by the other end). +
Example 12.2. Obtaining OpenSSL error codes
+static void __attribute__((noreturn))
+ssl_print_error_and_exit(SSL *ssl, const char *op, int ret)
+{
+  int subcode = SSL_get_error(ssl, ret);
+  switch (subcode) {
+  case SSL_ERROR_NONE:
+    fprintf(stderr, "error: %s: no error to report\n", op);
+    break;
+  case SSL_ERROR_WANT_READ:
+  case SSL_ERROR_WANT_WRITE:
+  case SSL_ERROR_WANT_X509_LOOKUP:
+  case SSL_ERROR_WANT_CONNECT:
+  case SSL_ERROR_WANT_ACCEPT:
+    fprintf(stderr, "error: %s: invalid blocking state %d\n", op, subcode);
+    break;
+  case SSL_ERROR_SSL:
+    fprintf(stderr, "error: %s: TLS layer problem\n", op);
+  case SSL_ERROR_SYSCALL:
+    fprintf(stderr, "error: %s: system call failed: %s\n", op, strerror(errno));
+    break;
+  case SSL_ERROR_ZERO_RETURN:
+    fprintf(stderr, "error: %s: zero return\n", op);
+  }
+  exit(1);
+}
+

+ The OPENSSL_config function is documented to never fail. In reality, it can terminate the entire process if there is a failure accessing the configuration file. An error message is written to standard error, but which might not be visible if the function is called from a daemon process. +
+ OpenSSL contains two separate ASN.1 DER decoders. One set of decoders operate on BIO handles (the input/output stream abstraction provided by OpenSSL); their decoder function names start with d2i_ and end in _fp or _bio (e.g., d2i_X509_fp or d2i_X509_bio). These decoders must not be used for parsing data from untrusted sources; instead, the variants without the _fp and _bio (e.g., d2i_X509) shall be used. The BIO variants have received considerably less testing and are not very robust. +
+ For the same reason, the OpenSSL command line tools (such as openssl x509) are generally generally less robust than the actual library code. They use the BIO functions internally, and not the more robust variants. +
+ The command line tools do not always indicate failure in the exit status of the openssl process. For instance, a verification failure in openssl verify result in an exit status of zero. +
+ The OpenSSL server and client applications (openssl s_client and openssl s_server) are debugging tools and should never be used as generic clients. For instance, the s_client tool reacts in a surprisign way to lines starting with R and Q. +
+ OpenSSL allows application code to access private key material over documented interfaces. This can significantly increase the part of the code base which has to undergo security certification. +

12.1.2. GNUTLS Pitfalls

+ libgnutls.so.26 links to libpthread.so.0. Loading the threading library too late causes problems, so the main program should be linked with -lpthread as well. As a result, it can be difficult to use GNUTLS in a plugin which is loaded with the dlopen function. Another side effect is that applications which merely link against GNUTLS (even without actually using it) may incur a substantial overhead because other libraries automatically switch to thread-safe algorithms. +
+ The gnutls_global_init function must be called before using any functionality provided by the library. This function is not thread-safe, so external locking is required, but it is not clear which lock should be used. Omitting the synchronization does not just lead to a memory leak, as it is suggested in the GNUTLS documentation, but to undefined behavior because there is no barrier that would enforce memory ordering. +
+ The gnutls_global_deinit function does not actually deallocate all resources allocated by gnutls_global_init. It is currently not thread-safe. Therefore, it is best to avoid calling it altogether. +
+ The X.509 implementation in GNUTLS is rather lenient. For example, it is possible to create and process X.509 version 1 certificates which carry extensions. These certificates are (correctly) rejected by other implementations. +

12.1.3. OpenJDK Pitfalls

+ The Java cryptographic framework is highly modular. As a result, when you request an object implementing some cryptographic functionality, you cannot be completely sure that you end up with the well-tested, reviewed implementation in OpenJDK. +
+ OpenJDK (in the source code as published by Oracle) and other implementations of the Java platform require that the system administrator has installed so-called unlimited strength jurisdiction policy files. Without this step, it is not possible to use the secure algorithms which offer sufficient cryptographic strength. Most downstream redistributors of OpenJDK remove this requirement. +
+ Some versions of OpenJDK use /dev/random as the randomness source for nonces and other random data which is needed for TLS operation, but does not actually require physical randomness. As a result, TLS applications can block, waiting for more bits to become available in /dev/random. +

12.1.4. NSS Pitfalls

+ NSS was not designed to be used by other libraries which can be linked into applications without modifying them. There is a lot of global state. There does not seem to be a way to perform required NSS initialization without race conditions. +
+ If the NSPR descriptor is in an unexpected state, the SSL_ForceHandshake function can succeed, but no TLS handshake takes place, the peer is not authenticated, and subsequent data is exchanged in the clear. +
+ NSS disables itself if it detects that the process underwent a fork after the library has been initialized. This behavior is required by the PKCS#11 API specification. +
\ No newline at end of file diff --git a/defensive-coding/tmp/en-US/html/chap-Defensive_Coding-Tasks-Cryptography.html b/defensive-coding/tmp/en-US/html/chap-Defensive_Coding-Tasks-Cryptography.html new file mode 100644 index 0000000..9136d8f --- /dev/null +++ b/defensive-coding/tmp/en-US/html/chap-Defensive_Coding-Tasks-Cryptography.html @@ -0,0 +1,32 @@ + +Chapter 10. Cryptography

Product SiteDocumentation Site

Chapter 10. Cryptography

10.1. Primitives

+ Chosing from the following cryptographic primitives is recommended: +
  • + RSA with 2048 bit keys and OAEP +
  • + AES-128 in CBC mode +
  • + SHA-256 +
  • + HMAC-SHA-256 +
  • + HMAC-SHA-1 +
+ Other cryptographic algorithms can be used if they are required for interoperability with existing software: +
  • + RSA with key sizes larger than 1024 and legacy padding +
  • + AES-192 +
  • + AES-256 +
  • + 3DES (triple DES, with two or three 56 bit keys) +
  • + RC4 (but very, very strongly discouraged) +
  • + SHA-1 +
  • + HMAC-MD5 +

Important

+ These primitives are difficult to use in a secure way. Custom implementation of security protocols should be avoided. For protecting confidentiality and integrity of network transmissions, TLS should be used (Chapter 12, Transport Layer Security). +
\ No newline at end of file diff --git a/defensive-coding/tmp/en-US/html/chap-Defensive_Coding-Tasks-File_System.html b/defensive-coding/tmp/en-US/html/chap-Defensive_Coding-Tasks-File_System.html new file mode 100644 index 0000000..b1468c4 --- /dev/null +++ b/defensive-coding/tmp/en-US/html/chap-Defensive_Coding-Tasks-File_System.html @@ -0,0 +1,34 @@ + +Chapter 6. File system manipulation

Product SiteDocumentation Site

Chapter 6. File system manipulation

+ In this chapter, we discuss general file system manipulation, with a focus on access files and directories to which an other, potentially untrusted user has write access. +
+ Temporary files are covered in their own chapter, Chapter 7, Temporary files. +

6.1. Working with files and directories owned by other users

+ Sometimes, it is necessary to operate on files and directories owned by other (potentially untrusted) users. For example, a system administrator could remove the home directory of a user, or a package manager could update a file in a directory which is owned by an application-specific user. This differs from accessing the file system as a specific user; see Section 6.2, “Accessing the file system as a different user”. +
+ Accessing files across trust boundaries faces several challenges, particularly if an entire directory tree is being traversed: +
  1. + Another user might add file names to a writable directory at any time. This can interfere with file creation and the order of names returned by readdir. +
  2. + Merely opening and closing a file can have side effects. For instance, an automounter can be triggered, or a tape device rewound. Opening a file on a local file system can block indefinitely, due to mandatory file locking, unless the O_NONBLOCK flag is specified. +
  3. + Hard links and symbolic links can redirect the effect of file system operations in unexpected ways. The O_NOFOLLOW and AT_SYMLINK_NOFOLLOW variants of system calls only affected final path name component. +
  4. + The structure of a directory tree can change. For example, the parent directory of what used to be a subdirectory within the directory tree being processed could suddenly point outside that directory tree. +
+ Files should always be created with the O_CREAT and O_EXCL flags, so that creating the file will fail if it already exists. This guards against the unexpected appearance of file names, either due to creation of a new file, or hard-linking of an existing file. In multi-threaded programs, rather than manipulating the umask, create the files with mode 000 if possible, and adjust it afterwards with fchmod. +
+ To avoid issues related to symbolic links and directory tree restructuring, the “at” variants of system calls have to be used (that is, functions like openat, fchownat, fchmodat, and unlinkat, together with O_NOFOLLOW or AT_SYMLINK_NOFOLLOW). Path names passed to these functions must have just a single component (that is, without a slash). When descending, the descriptors of parent directories must be kept open. The missing opendirat function can be emulated with openat (with an O_DIRECTORY flag, to avoid opening special files with side effects), followed by fdopendir. +
+ If the “at” functions are not available, it is possible to emulate them by changing the current directory. (Obviously, this only works if the process is not multi-threaded.) fchdir has to be used to change the current directory, and the descriptors of the parent directories have to be kept open, just as with the “at”-based approach. chdir("...") is unsafe because it might ascend outside the intended directory tree. +
+ This “at” function emulation is currently required when manipulating extended attributes. In this case, the lsetxattr function can be used, with a relative path name consisting of a single component. This also applies to SELinux contexts and the lsetfilecon function. +
+ Currently, it is not possible to avoid opening special files and changes to files with hard links if the directory containing them is owned by an untrusted user. (Device nodes can be hard-linked, just as regular files.) fchmodat and fchownat affect files whose link count is greater than one. But opening the files, checking that the link count is one with fstat, and using fchmod and fchown on the file descriptor may have unwanted side effects, due to item 2 above. When creating directories, it is therefore important to change the ownership and permissions only after it has been fully created. Until that point, file names are stable, and no files with unexpected hard links can be introduced. +
+ Similarly, when just reading a directory owned by an untrusted user, it is currently impossible to reliably avoid opening special files. +
+ There is no workaround against the instability of the file list returned by readdir. Concurrent modification of the directory can result in a list of files being returned which never actually existed on disk. +
+ Hard links and symbolic links can be safely deleted using unlinkat without further checks because deletion only affects the name within the directory tree being processed. +
\ No newline at end of file diff --git a/defensive-coding/tmp/en-US/html/chap-Defensive_Coding-Tasks-Library_Design.html b/defensive-coding/tmp/en-US/html/chap-Defensive_Coding-Tasks-Library_Design.html new file mode 100644 index 0000000..f4573fe --- /dev/null +++ b/defensive-coding/tmp/en-US/html/chap-Defensive_Coding-Tasks-Library_Design.html @@ -0,0 +1,22 @@ + +Chapter 4. Library Design

Product SiteDocumentation Site

Chapter 4. Library Design

+ Throught this section, the term client code refers to applications and other libraries using the library. +

4.1. State management

+ +

4.1.1. Global state

+ Global state should be avoided. +
+ If this is impossible, the global state must be protected with a lock. For C/C++, you can use the pthread_mutex_lock and pthread_mutex_unlock functions without linking against -lpthread because the system provides stubs for non-threaded processes. +
+ For compatibility with fork, these locks should be acquired and released in helpers registered with pthread_atfork. This function is not available without -lpthread, so you need to use dlsym or a weak symbol to obtain its address. +
+ If you need fork protection for other reasons, you should store the process ID and compare it to the value returned by getpid each time you access the global state. (getpid is not implemented as a system call and is fast.) If the value changes, you know that you have to re-create the state object. (This needs to be combined with locking, of course.) +

4.1.2. Handles

+ Library state should be kept behind a curtain. Client code should receive only a handle. In C, the handle can be a pointer to an incomplete struct. In C++, the handle can be a pointer to an abstract base class, or it can be hidden using the pointer-to-implementation idiom. +
+ The library should provide functions for creating and destroying handles. (In C++, it is possible to use virtual destructors for the latter.) Consistency between creation and destruction of handles is strongly recommended: If the client code created a handle, it is the responsibility of the client code to destroy it. (This is not always possible or convenient, so sometimes, a transfer of ownership has to happen.) +
+ Using handles ensures that it is possible to change the way the library represents state in a way that is transparent to client code. This is important to facilitate security updates and many other code changes. +
+ It is not always necessary to protect state behind a handle with a lock. This depends on the level of thread safety the library provides. +
\ No newline at end of file diff --git a/defensive-coding/tmp/en-US/html/chap-Defensive_Coding-Tasks-Serialization.html b/defensive-coding/tmp/en-US/html/chap-Defensive_Coding-Tasks-Serialization.html new file mode 100644 index 0000000..3a60d65 --- /dev/null +++ b/defensive-coding/tmp/en-US/html/chap-Defensive_Coding-Tasks-Serialization.html @@ -0,0 +1,8 @@ + +Chapter 9. Serialization and Deserialization

Product SiteDocumentation Site

Chapter 9. Serialization and Deserialization

+ Protocol decoders and file format parsers are often the most-exposed part of an application because they are exposed with little or no user interaction and before any authentication and security checks are made. They are also difficult to write robustly in languages which are not memory-safe. +

9.1. Recommendations for manually written decoders

+ For C and C++, the advice in Section 1.1.2, “Recommendations for pointers and array handling” applies. In addition, avoid non-character pointers directly into input buffers. Pointer misalignment causes crashes on some architectures. +
+ When reading variable-sized objects, do not allocate large amounts of data solely based on the value of a size field. If possible, grow the data structure as more data is read from the source, and stop when no data is available. This helps to avoid denial-of-service attacks where little amounts of input data results in enormous memory allocations during decoding. Alternatively, you can impose reasonable bounds on memory allocations, but some protocols do not permit this. +
\ No newline at end of file diff --git a/defensive-coding/tmp/en-US/html/chap-Defensive_Coding-Tasks-Temporary_Directory.html b/defensive-coding/tmp/en-US/html/chap-Defensive_Coding-Tasks-Temporary_Directory.html new file mode 100644 index 0000000..c5f6cbf --- /dev/null +++ b/defensive-coding/tmp/en-US/html/chap-Defensive_Coding-Tasks-Temporary_Directory.html @@ -0,0 +1,8 @@ + +7.4. Temporary directories

Product SiteDocumentation Site

7.4. Temporary directories

+ The mkdtemp function can be used to create a temporary directory. (For determining the directory part of the file name pattern, see Section 7.1, “Obtaining the location of temporary directory”.) The directory is not automatically removed. In Python, this function is available as tempfile.mkdtemp. In Java 7, temporary directories can be created using the java.nio.file.Files.createTempDirectory(Path, String, FileAttribute...) function. +
+ When creating files in the temporary directory, use automatically generated names, e.g., derived from a sequential counter. Files with externally provided names could be picked up in unexpected contexts, and crafted names could actually point outside of the tempoary directory (due to directory traversal). +
+ Removing a directory tree in a completely safe manner is complicated. Unless there are overriding performance concerns, the rm program should be used, with the -rf and -- options. +
\ No newline at end of file diff --git a/defensive-coding/tmp/en-US/html/chap-Defensive_Coding-Tasks-Temporary_Files.html b/defensive-coding/tmp/en-US/html/chap-Defensive_Coding-Tasks-Temporary_Files.html new file mode 100644 index 0000000..cdd7de6 --- /dev/null +++ b/defensive-coding/tmp/en-US/html/chap-Defensive_Coding-Tasks-Temporary_Files.html @@ -0,0 +1,28 @@ + +Chapter 7. Temporary files

Product SiteDocumentation Site

Chapter 7. Temporary files

+ In this chapter, we describe how to create temporary files and directories, how to remove them, and how to work with programs which do not create files in ways that a safe with a shared directory for temporary files. General file system manipulation is treated in a separate chapter, Chapter 6, File system manipulation. +
+ Secure creation of temporary files has four different aspects. +
  • + The location of the directory for temporary files must be obtained in a secure manner (that is, untrusted environment variables must be ignored, see Section 8.3.1, “Accessing environment variables”). +
  • + A new file must be created. Reusing an existing file must be avoided (the /tmp race condition). This is tricky because traditionally, system-wide temporary directories shared by all users are used. +
  • + The file must be created in a way that makes it impossible for other users to open it. +
  • + The descriptor for the temporary file should not leak to subprocesses. +
+ All functions mentioned below will take care of these aspects. +
+ Traditionally, temporary files are often used to reduce memory usage of programs. More and more systems use RAM-based file systems such as tmpfs for storing temporary files, to increase performance and decrease wear on Flash storage. As a result, spooling data to temporary files does not result in any memory savings, and the related complexity can be avoided if the data is kept in process memory. +

7.1. Obtaining the location of temporary directory

+ Some functions below need the location of a directory which stores temporary files. For C/C++ programs, use the following steps to obtain that directory: +
  • + Use secure_getenv to obtain the value of the TMPDIR environment variable. If it is set, convert the path to a fully-resolved absolute path, using realpath(path, NULL). Check if the new path refers to a directory and is writeable. In this case, use it as the temporary directory. +
  • + Fall back to /tmp. +
+ In Python, you can use the tempfile.tempdir variable. +
+ Java does not support SUID/SGID programs, so you can use the java.lang.System.getenv(String) method to obtain the value of the TMPDIR environment variable, and follow the two steps described above. (Java's default directory selection does not honor TMPDIR.) +
\ No newline at end of file diff --git a/defensive-coding/tmp/en-US/html/index.html b/defensive-coding/tmp/en-US/html/index.html new file mode 100644 index 0000000..cf88211 --- /dev/null +++ b/defensive-coding/tmp/en-US/html/index.html @@ -0,0 +1,34 @@ + +Defensive Coding

Product SiteDocumentation Site

Internal 6.4

Defensive Coding

A Guide to Improving Software Security

Edition 1.0

+ + +


Legal Notice

+ Copyright © 2012 Red Hat, Inc. +
+ The text of and illustrations in this document are licensed by Red Hat under a Creative Commons Attribution–Share Alike 3.0 Unported license ("CC-BY-SA"). An explanation of CC-BY-SA is available at http://creativecommons.org/licenses/by-sa/3.0/. In accordance with CC-BY-SA, if you distribute this document or an adaptation of it, you must provide the URL for the original version. +
+ Red Hat, as the licensor of this document, waives the right to enforce, and agrees not to assert, Section 4d of CC-BY-SA to the fullest extent permitted by applicable law. +
+ Red Hat, Red Hat Enterprise Linux, the Shadowman logo, JBoss, MetaMatrix, Fedora, the Infinity Logo, and RHCE are trademarks of Red Hat, Inc., registered in the United States and other countries. +
+ Linux® is the registered trademark of Linus Torvalds in the United States and other countries. +
+ Java® is a registered trademark of Oracle and/or its affiliates. +
+ XFS® is a trademark of Silicon Graphics International Corp. or its subsidiaries in the United States and/or other countries. +
+ MySQL® is a registered trademark of MySQL AB in the United States, the European Union and other countries. +
+ All other trademarks are the property of their respective owners. +
+ +


+ 1801 Varsity Drive
+ RaleighNC 27606-2072 USA
+ Phone: +1 919 754 3700
+ Phone: 888 733 4281
+ Fax: +1 919 754 3701

+ +
Abstract
+ This document provides guidelines for improving software security through secure coding. It covers common programming languages and libraries, and focuses on concrete recommendations. +

I. Programming Languages
1. The C Programming Language
1.1. The core language
1.1.1. Undefined behavior
1.1.2. Recommendations for pointers and array handling
1.1.3. Recommendations for integer arithmetic
1.2. The C standard library
1.2.1. Absolutely banned interfaces
1.2.2. Functions to avoid
1.2.3. String Functions With Explicit Length Arguments
1.3. Memory allocators
1.3.1. malloc and related functions
1.3.2. alloca and other forms of stack-based allocation
1.3.3. Array allocation
1.3.4. Custom memory allocators
1.3.5. Conservative garbage collection
2. The C++ Programming Language
2.1. The core language
2.1.1. Array allocation with operator new[]
2.1.2. Overloading
2.1.3. ABI compatibility and preparing for security updates
2.1.4. C++0X and C++11 support
2.2. The C++ standard library
2.2.1. Containers and operator[]
3. The Python Programming Language
3.1. Dangerous standard library features
3.2. Run-time compilation and code generation
3.3. Sandboxing
II. Specific Programming Tasks
4. Library Design
4.1. State management
4.1.1. Global state
4.1.2. Handles
4.2. Object orientation
4.3. Callbacks
4.4. Process attributes
5. File Descriptor Management
5.1. Closing descriptors
5.1.1. Error handling during descriptor close
5.1.2. Closing descriptors and race conditions
5.1.3. Lingering state after close
5.2. Preventing file descriptor leaks to child processes
5.3. Dealing with the select limit
6. File system manipulation
6.1. Working with files and directories owned by other users
6.2. Accessing the file system as a different user
6.3. File system limits
6.4. File system features
6.5. Checking free space
7. Temporary files
7.1. Obtaining the location of temporary directory
7.2. Named temporary files
7.3. Temporary files without names
7.4. Temporary directories
7.5. Compensating for unsafe file creation
8. Processes
8.1. Safe process creation
8.1.1. Obtaining the program path and the command line template
8.1.2. Bypassing the shell
8.1.3. Specifying the process environment
8.1.4. Robust argument list processing
8.1.5. Passing secrets to subprocesses
8.2. Handling child process termination
8.3. SUID/SGID processes
8.3.1. Accessing environment variables
8.4. Daemons
8.5. Semantics of command line arguments
8.6. fork as a primitive for parallelism
9. Serialization and Deserialization
9.1. Recommendations for manually written decoders
9.2. Protocol design
9.3. Library support for deserialization
9.4. XML serialization
9.4.1. External references
9.4.2. Entity expansion
9.4.3. XInclude processing
9.4.4. Algorithmic complexity of XML validation
9.4.5. Using Expat for XML parsing
9.4.6. Using OpenJDK for XML parsing and validation
9.5. Protocol Encoders
10. Cryptography
10.1. Primitives
10.2. Randomness
III. Implementing Security Features
11. Authentication and Authorization
11.1. Authenticating servers
11.2. Host-based authentication
11.3. UNIX domain socket authentication
11.4. AF_NETLINK authentication of origin
12. Transport Layer Security
12.1. Common Pitfalls
12.1.1. OpenSSL Pitfalls
12.1.2. GNUTLS Pitfalls
12.1.3. OpenJDK Pitfalls
12.1.4. NSS Pitfalls
12.2. TLS Clients
12.2.1. Implementation TLS Clients With OpenSSL
12.2.2. Implementation TLS Clients With GNUTLS
12.2.3. Implementing TLS Clients With OpenJDK
12.2.4. Implementing TLS Clients With NSS
12.2.5. Implementing TLS Clients With Python
\ No newline at end of file diff --git a/defensive-coding/tmp/en-US/html/pt01.html b/defensive-coding/tmp/en-US/html/pt01.html new file mode 100644 index 0000000..2956dc9 --- /dev/null +++ b/defensive-coding/tmp/en-US/html/pt01.html @@ -0,0 +1,2 @@ + +Part I. Programming Languages

Product SiteDocumentation Site

\ No newline at end of file diff --git a/defensive-coding/tmp/en-US/html/pt02.html b/defensive-coding/tmp/en-US/html/pt02.html new file mode 100644 index 0000000..06a5b00 --- /dev/null +++ b/defensive-coding/tmp/en-US/html/pt02.html @@ -0,0 +1,2 @@ + +Part II. Specific Programming Tasks

Product SiteDocumentation Site

Part II. Specific Programming Tasks

Table of Contents

4. Library Design
4.1. State management
4.1.1. Global state
4.1.2. Handles
4.2. Object orientation
4.3. Callbacks
4.4. Process attributes
5. File Descriptor Management
5.1. Closing descriptors
5.1.1. Error handling during descriptor close
5.1.2. Closing descriptors and race conditions
5.1.3. Lingering state after close
5.2. Preventing file descriptor leaks to child processes
5.3. Dealing with the select limit
6. File system manipulation
6.1. Working with files and directories owned by other users
6.2. Accessing the file system as a different user
6.3. File system limits
6.4. File system features
6.5. Checking free space
7. Temporary files
7.1. Obtaining the location of temporary directory
7.2. Named temporary files
7.3. Temporary files without names
7.4. Temporary directories
7.5. Compensating for unsafe file creation
8. Processes
8.1. Safe process creation
8.1.1. Obtaining the program path and the command line template
8.1.2. Bypassing the shell
8.1.3. Specifying the process environment
8.1.4. Robust argument list processing
8.1.5. Passing secrets to subprocesses
8.2. Handling child process termination
8.3. SUID/SGID processes
8.3.1. Accessing environment variables
8.4. Daemons
8.5. Semantics of command line arguments
8.6. fork as a primitive for parallelism
9. Serialization and Deserialization
9.1. Recommendations for manually written decoders
9.2. Protocol design
9.3. Library support for deserialization
9.4. XML serialization
9.4.1. External references
9.4.2. Entity expansion
9.4.3. XInclude processing
9.4.4. Algorithmic complexity of XML validation
9.4.5. Using Expat for XML parsing
9.4.6. Using OpenJDK for XML parsing and validation
9.5. Protocol Encoders
10. Cryptography
10.1. Primitives
10.2. Randomness
\ No newline at end of file diff --git a/defensive-coding/tmp/en-US/html/pt03.html b/defensive-coding/tmp/en-US/html/pt03.html new file mode 100644 index 0000000..df42c39 --- /dev/null +++ b/defensive-coding/tmp/en-US/html/pt03.html @@ -0,0 +1,2 @@ + +Part III. Implementing Security Features

Product SiteDocumentation Site

\ No newline at end of file diff --git a/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-Authentication-Host_based.html b/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-Authentication-Host_based.html new file mode 100644 index 0000000..60dbe7d --- /dev/null +++ b/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-Authentication-Host_based.html @@ -0,0 +1,14 @@ + +11.2. Host-based authentication

Product SiteDocumentation Site

11.2. Host-based authentication

+ Host-based authentication uses access control lists (ACLs) to accept or deny requests from clients. Thsis authentication method comes in two flavors: IP-based (or, more generally, address-based) and name-based (with the name coming from DNS or /etc/hosts). IP-based ACLs often use prefix notation to extend access to entire subnets. Name-based ACLs sometimes use wildcards for adding groups of hosts (from entire DNS subtrees). (In the SSH context, host-based authentication means something completely different and is not covered in this section.) +
+ Host-based authentication trust the network and may not offer sufficient granularity, so it has to be considered a weak form of authentication. On the other hand, IP-based authentication can be made extremely robust and can be applied very early in input processing, so it offers an opportunity for significantly reducing the number of potential attackers for many services. +
+ The names returned by gethostbyaddr and getnameinfo functions cannot be trusted. (DNS PTR records can be set to arbitrary values, not just names belong to the address owner.) If these names are used for ACL matching, a forward lookup using gethostbyaddr or getaddrinfo has to be performed. The name is only valid if the original address is found among the results of the forward lookup (double-reverse lookup). +
+ An empty ACL should deny all access (deny-by-default). If empty ACLs permits all access, configuring any access list must switch to deny-by-default for all unconfigured protocols, in both name-based and address-based variants. +
+ Similarly, if an address or name is not matched by the list, it should be denied. However, many implementations behave differently, so the actual behavior must be documented properly. +
+ IPv6 addresses can embed IPv4 addresses. There is no universally correct way to deal with this ambiguity. The behavior of the ACL implementation should be documented. +
\ No newline at end of file diff --git a/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-Authentication-Netlink.html b/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-Authentication-Netlink.html new file mode 100644 index 0000000..d3536c8 --- /dev/null +++ b/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-Authentication-Netlink.html @@ -0,0 +1,8 @@ + +11.4. AF_NETLINK authentication of origin

Product SiteDocumentation Site

\ No newline at end of file diff --git a/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-Authentication-UNIX_Domain.html b/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-Authentication-UNIX_Domain.html new file mode 100644 index 0000000..9e30ada --- /dev/null +++ b/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-Authentication-UNIX_Domain.html @@ -0,0 +1,10 @@ + +11.3. UNIX domain socket authentication

Product SiteDocumentation Site

11.3. UNIX domain socket authentication

+ UNIX domain sockets (with address family AF_UNIX or AF_LOCAL) are restricted to the local host and offer a special authentication mechanism: credentials passing. +
+ Nowadays, most systems support the SO_PEERCRED (Linux) or LOCAL_PEERCRED (FreeBSD) socket options, or the getpeereid (other BSDs, MacOS X). These interfaces provide direct access to the (effective) user ID on the other end of a domain socket connect, without cooperation from the other end. +
+ Historically, credentials passing was implemented using ancillary data in the sendmsg and recvmsg functions. On some systems, only credentials data that the peer has explicitly sent can be received, and the kernel checks the data for correctness on the sending side. This means that both peers need to deal with ancillary data. Compared to that, the modern interfaces are easier to use. Both sets of interfaces vary considerably among UNIX-like systems, unfortunately. +
+ If you want to authenticate based on supplementary groups, you should obtain the user ID using one of these methods, and look up the list of supplementary groups using getpwuid (or getpwuid_r) and getgrouplist. Using the PID and information from /proc/PID/status is prone to race conditions and insecure. +
\ No newline at end of file diff --git a/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-C-Allocators-Arrays.html b/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-C-Allocators-Arrays.html new file mode 100644 index 0000000..cb1fa45 --- /dev/null +++ b/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-C-Allocators-Arrays.html @@ -0,0 +1,6 @@ + +1.3.3. Array allocation

Product SiteDocumentation Site

1.3.3. Array allocation

+ When allocating arrays, it is important to check for overflows. The calloc function performs such checks. +
+ If malloc or realloc is used, the size check must be written manually. For instance, to allocate an array of n elements of type T, check that the requested size is not greater than n / sizeof(T). +
\ No newline at end of file diff --git a/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-C-Allocators-alloca.html b/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-C-Allocators-alloca.html new file mode 100644 index 0000000..471595d --- /dev/null +++ b/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-C-Allocators-alloca.html @@ -0,0 +1,14 @@ + +1.3.2. alloca and other forms of stack-based allocation

Product SiteDocumentation Site

1.3.2. alloca and other forms of stack-based allocation

+ Allocation on the stack is risky because stack overflow checking is implicit. There is a guard page at the end of the memory area reserved for the stack. If the program attempts to read from or write to this guard page, a SIGSEGV signal is generated and the program typically terminates. +
+ This is sufficient for detecting typical stack overflow situations such as unbounded recursion, but it fails when the stack grows in increments larger than the size of the guard page. In this case, it is possible that the stack pointer ends up pointing into a memory area which has been allocated for a different purposes. Such misbehavior can be exploitable. +
+ A common source for large stack growth are calls to alloca and related functions such as strdupa. These functions should be avoided because of the lack of error checking. (They can be used safely if the allocated size is less than the page size (typically, 4096 bytes), but this case is relatively rare.) Additionally, relying on alloca makes it more difficult to reorgnize the code because it is not allowed to use the pointer after the function calling alloca has returned, even if this function has been inlined into its caller. +
+ Similar concerns apply to variable-length arrays (VLAs), a feature of the C99 standard which started as a GNU extension. For large objects exceeding the page size, there is no error checking, either. +
+ In both cases, negative or very large sizes can trigger a stack-pointer wraparound, and the stack pointer and end up pointing into caller stack frames, which is fatal and can be exploitable. +
+ If you want to use alloca or VLAs for performance reasons, consider using a small on-stack array (less than the page size, large enough to fulfill most requests). If the requested size is small enough, use the on-stack array. Otherwise, call malloc. When exiting the function, check if malloc had been called, and free the buffer as needed. +
\ No newline at end of file diff --git a/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-C-Allocators.html b/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-C-Allocators.html new file mode 100644 index 0000000..b378289 --- /dev/null +++ b/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-C-Allocators.html @@ -0,0 +1,16 @@ + +1.3. Memory allocators

Product SiteDocumentation Site

1.3. Memory allocators

1.3.1. malloc and related functions

+ The C library interfaces for memory allocation are provided by malloc, free and realloc, and the calloc function. In addition to these generic functions, there are derived functions such as strdup which perform allocation using malloc internally, but do not return untyped heap memory (which could be used for any object). +
+ The C compiler knows about these functions and can use their expected behavior for optimizations. For instance, the compiler assumes that an existing pointer (or a pointer derived from an existing pointer by arithmetic) will not point into the memory area returned by malloc. +
+ If the allocation fails, realloc does not free the old pointer. Therefore, the idiom ptr = realloc(ptr, size); is wrong because the memory pointed to by ptr leaks in case of an error. +

1.3.1.1. Use-after-free errors

+ After free, the pointer is invalid. Further pointer dereferences are not allowed (and are usually detected by valgrind). Less obvious is that any use of the old pointer value is not allowed, either. In particular, comparisons with any other pointer (or the null pointer) are undefined according to the C standard. +
+ The same rules apply to realloc if the memory area cannot be enlarged in-place. For instance, the compiler may assume that a comparison between the old and new pointer will always return false, so it is impossible to detect movement this way. +

1.3.1.2. Handling memory allocation errors

+ Recovering from out-of-memory errors is often difficult or even impossible. In these cases, malloc and other allocation functions return a null pointer. Dereferencing this pointer lead to a crash. Such dereferences can even be exploitable for code execution if the dereference is combined with an array subscript. +
+ In general, if you cannot check all allocation calls and handle failure, you should abort the program on allocation failure, and not rely on the null pointer dereference to terminate the process. See Section 9.1, “Recommendations for manually written decoders” for related memory allocation concerns. +
\ No newline at end of file diff --git a/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-C-Avoid.html b/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-C-Avoid.html new file mode 100644 index 0000000..0c44c7a --- /dev/null +++ b/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-C-Avoid.html @@ -0,0 +1,28 @@ + +1.2.2. Functions to avoid

Product SiteDocumentation Site

1.2.2. Functions to avoid

+ The following string manipulation functions can be used securely in principle, but their use should be avoided because they are difficult to use correctly. Calls to these functions can be replaced with asprintf or vasprintf. (For non-GNU targets, these functions are available from Gnulib.) In some cases, the snprintf function might be a suitable replacement, see Section 1.2.3, “String Functions With Explicit Length Arguments”. +
  • + sprintf +
  • + strcat +
  • + strcpy +
  • + vsprintf +
+ Use the indicated replacements for the functions below. +
\ No newline at end of file diff --git a/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-C-Libc.html b/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-C-Libc.html new file mode 100644 index 0000000..fe94d1b --- /dev/null +++ b/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-C-Libc.html @@ -0,0 +1,30 @@ + +1.2. The C standard library

Product SiteDocumentation Site

1.2. The C standard library

+ Parts of the C standard library (and the UNIX and GNU extensions) are difficult to use, so you shoud avoid them. +
+ Please check the applicable documentation before using the recommended replacements. Many of these functions allocate buffers using malloc which your code must deallocate explicitly using free. +

1.2.1. Absolutely banned interfaces

+ The functions listed below must not be used because they are almost always unsafe. Use the indicated replacements instead. +
  • + getsfgets +
  • + getwdgetcwd or get_current_dir_name +
  • + readdir_rreaddir +
  • + realpath (with a non-NULL second parameter) ⟶ realpath with NULL as the second parameter, or canonicalize_file_name +
+ The constants listed below must not be used, either. Instead, code must allocate memory dynamically and use interfaces with length checking. +
  • + NAME_MAX (limit not actually enforced by the kernel) +
  • + PATH_MAX (limit not actually enforced by the kernel) +
  • + _PC_NAME_MAX (This limit, returned by the pathconf function, is not enforced by the kernel.) +
  • + _PC_PATH_MAX (This limit, returned by the pathconf function, is not enforced by the kernel.) +
+ The following structure members must not be used. +
  • + f_namemax in struct statvfs (limit not actually enforced by the kernel, see _PC_NAME_MAX above) +
\ No newline at end of file diff --git a/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-C-String-Functions-Length.html b/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-C-String-Functions-Length.html new file mode 100644 index 0000000..aee5e94 --- /dev/null +++ b/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-C-String-Functions-Length.html @@ -0,0 +1,32 @@ + +1.2.3. String Functions With Explicit Length Arguments

Product SiteDocumentation Site

1.2.3. String Functions With Explicit Length Arguments

+ The snprintf function provides a way to construct a string in a statically-sized buffer. (If the buffer size is dynamic, use asprintf instead.) +
+char fraction[30];
+snprintf(fraction, sizeof(fraction), "%d/%d", numerator, denominator);
+
+ The second argument to the snprintf should always be the size of the buffer in the first argument (which should be a character array). Complex pointer and length arithmetic can introduce errors and nullify the security benefits of snprintf. If you need to construct a string iteratively, by repeatedly appending fragments, consider constructing the string on the heap, increasing the buffer with realloc as needed. (snprintf does not support overlapping the result buffer with argument strings.) +
+ If you use vsnprintf (or snprintf) with a format string which is not a constant, but a function argument, it is important to annotate the function with a format function attribute, so that GCC can warn about misuse of your function (see Example 1.4, “The format function attribute”). +
Example 1.4. The format function attribute
+void log_format(const char *format, ...) __attribute__((format(printf, 1, 2)));
+
+void
+log_format(const char *format, ...)
+{
+  char buf[1000];
+  va_list ap;
+  va_start(ap, format);
+  vsnprintf(buf, sizeof(buf), format, ap);
+  va_end(ap);
+  log_string(buf);
+}
+

+ There are other functions which operator on NUL-terminated strings and take a length argument which affects the number of bytes written to the destination: strncpy, strncat, and stpncpy. These functions do not ensure that the result string is NUL-terminated. For strncpy, NUL termination can be added this way: +
+char buf[10];
+strncpy(buf, data, sizeof(buf));
+buf[sizeof(buf) - 1] = '\0';
+
+ Some systems support strlcpy and strlcat functions which behave this way, but these functions are not part of GNU libc. Using snprintf with a suitable format string is a simple (albeit slightly slower) replacement. +
\ No newline at end of file diff --git a/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-CXX-Std.html b/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-CXX-Std.html new file mode 100644 index 0000000..61d73c9 --- /dev/null +++ b/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-CXX-Std.html @@ -0,0 +1,8 @@ + +2.2. The C++ standard library

Product SiteDocumentation Site

2.2. The C++ standard library

+ The C++ standard library includes most of its C counterpart by reference, see Section 1.2, “The C standard library”. +

2.2.1. Containers and operator[]

+ Many containers similar to std::vector provide both operator[](size_type) and a member function at(size_type). This applies to std::vector itself, std::array, std::string and other instances of std::basic_string. +
+ operator[](size_type) is not required by the standard to perform bounds checking (and the implementation in GCC does not). In contrast, at(size_type) must perform such a check. Therefore, in code which is not performance-critical, you should prefer at(size_type) over operator[](size_type), even though it is slightly more verbose. +
\ No newline at end of file diff --git a/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-TLS-Client-GNUTLS.html b/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-TLS-Client-GNUTLS.html new file mode 100644 index 0000000..df506ec --- /dev/null +++ b/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-TLS-Client-GNUTLS.html @@ -0,0 +1,183 @@ + +12.2.2. Implementation TLS Clients With GNUTLS

Product SiteDocumentation Site

12.2.2. Implementation TLS Clients With GNUTLS

+ This section describes how to implement a TLS client with full certificate validation (but without certificate revocation checking). Note that the error handling in is only exploratory and needs to be replaced before production use. +
+ The GNUTLS library needs explicit initialization: +
+gnutls_global_init();
+
+ Failing to do so can result in obscure failures in Base64 decoding. See Section 12.1.2, “GNUTLS Pitfalls” for additional aspects of initialization. +
+ Before setting up TLS connections, a credentials objects has to be allocated and initialized with the set of trusted root CAs (Example 12.9, “Initializing a GNUTLS credentials structure”). +
Example 12.9. Initializing a GNUTLS credentials structure
+// Load the trusted CA certificates.
+gnutls_certificate_credentials_t cred = NULL;
+int ret = gnutls_certificate_allocate_credentials (&cred);
+if (ret != GNUTLS_E_SUCCESS) {
+  fprintf(stderr, "error: gnutls_certificate_allocate_credentials: %s\n",
+	    gnutls_strerror(ret));
+  exit(1);
+}
+// gnutls_certificate_set_x509_system_trust needs GNUTLS version 3.0
+// or newer, so we hard-code the path to the certificate store
+// instead.
+static const char ca_bundle[] = "/etc/ssl/certs/ca-bundle.crt";
+ret = gnutls_certificate_set_x509_trust_file
+  (cred, ca_bundle, GNUTLS_X509_FMT_PEM);
+if (ret == 0) {
+  fprintf(stderr, "error: no certificates found in: %s\n", ca_bundle);
+  exit(1);
+}
+if (ret < 0) {
+  fprintf(stderr, "error: gnutls_certificate_set_x509_trust_files(%s): %s\n",
+	    ca_bundle, gnutls_strerror(ret));
+  exit(1);
+}
+

+ After the last TLS connection has been closed, this credentials object should be freed: +
+gnutls_certificate_free_credentials(cred);
+
+ During its lifetime, the credentials object can be used to initialize TLS session objects from multiple threads, provided that it is not changed. +
+ Once the TCP connection has been established, the Nagle algorithm should be disabled (see Example 12.1, “Deactivating the TCP Nagle algorithm”). After that, the socket can be associated with a new GNUTLS session object. The previously allocated credentials object provides the set of root CAs. The NORMAL set of cipher suites and protocols provides a reasonable default. Then the TLS handshake must be initiated. This is shown in Example 12.10, “Establishing a TLS client connection using GNUTLS”. +
Example 12.10. Establishing a TLS client connection using GNUTLS
+// Create the session object.
+gnutls_session_t session;
+ret = gnutls_init(&session, GNUTLS_CLIENT);
+if (ret != GNUTLS_E_SUCCESS) {
+  fprintf(stderr, "error: gnutls_init: %s\n",
+	    gnutls_strerror(ret));
+  exit(1);
+}
+
+// Configure the cipher preferences.
+const char *errptr = NULL;
+ret = gnutls_priority_set_direct(session, "NORMAL", &errptr);
+if (ret != GNUTLS_E_SUCCESS) {
+  fprintf(stderr, "error: gnutls_priority_set_direct: %s\n"
+	    "error: at: \"%s\"\n", gnutls_strerror(ret), errptr);
+  exit(1);
+}
+
+// Install the trusted certificates.
+ret = gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, cred);
+if (ret != GNUTLS_E_SUCCESS) {
+  fprintf(stderr, "error: gnutls_credentials_set: %s\n",
+	    gnutls_strerror(ret));
+  exit(1);
+}
+
+// Associate the socket with the session object and set the server
+// name.
+gnutls_transport_set_ptr(session, (gnutls_transport_ptr_t)(uintptr_t)sockfd);
+ret = gnutls_server_name_set(session, GNUTLS_NAME_DNS,
+			       host, strlen(host));
+if (ret != GNUTLS_E_SUCCESS) {
+  fprintf(stderr, "error: gnutls_server_name_set: %s\n",
+	    gnutls_strerror(ret));
+  exit(1);
+}
+
+// Establish the session.
+ret = gnutls_handshake(session);
+if (ret != GNUTLS_E_SUCCESS) {
+  fprintf(stderr, "error: gnutls_handshake: %s\n",
+	    gnutls_strerror(ret));
+  exit(1);
+}
+

+ After the handshake has been completed, the server certificate needs to be verified (Example 12.11, “Verifying a server certificate using GNUTLS”). In the example, the user-defined certificate_validity_override function is called if the verification fails, so that a separate, user-specific trust store can be checked. This function call can be omitted if the functionality is not needed. +
Example 12.11. Verifying a server certificate using GNUTLS
+// Obtain the server certificate chain.  The server certificate
+// itself is stored in the first element of the array.
+unsigned certslen = 0;
+const gnutls_datum_t *const certs =
+  gnutls_certificate_get_peers(session, &certslen);
+if (certs == NULL || certslen == 0) {
+  fprintf(stderr, "error: could not obtain peer certificate\n");
+  exit(1);
+}
+
+// Validate the certificate chain.
+unsigned status = (unsigned)-1;
+ret = gnutls_certificate_verify_peers2(session, &status);
+if (ret != GNUTLS_E_SUCCESS) {
+  fprintf(stderr, "error: gnutls_certificate_verify_peers2: %s\n",
+	    gnutls_strerror(ret));
+  exit(1);
+}
+if (status != 0 && !certificate_validity_override(certs[0])) {
+  gnutls_datum_t msg;
+#if GNUTLS_VERSION_AT_LEAST_3_1_4
+  int type = gnutls_certificate_type_get (session);
+  ret = gnutls_certificate_verification_status_print(status, type, &out, 0);
+#else
+  ret = -1;
+#endif
+  if (ret == 0) {
+    fprintf(stderr, "error: %s\n", msg.data);
+    gnutls_free(msg.data);
+    exit(1);
+  } else {
+    fprintf(stderr, "error: certificate validation failed with code 0x%x\n",
+	      status);
+    exit(1);
+  }
+}
+

+ In the next step (Example 12.12, “Matching the server host name and certificate in a GNUTLS client”, the certificate must be matched against the host name (note the unusual return value from gnutls_x509_crt_check_hostname). Again, an override function certificate_host_name_override is called. Note that the override must be keyed to the certificate and the host name. The function call can be omitted if the override is not needed. +
Example 12.12. Matching the server host name and certificate in a GNUTLS client
+// Match the peer certificate against the host name.
+// We can only obtain a set of DER-encoded certificates from the
+// session object, so we have to re-parse the peer certificate into
+// a certificate object.
+gnutls_x509_crt_t cert;
+ret = gnutls_x509_crt_init(&cert);
+if (ret != GNUTLS_E_SUCCESS) {
+  fprintf(stderr, "error: gnutls_x509_crt_init: %s\n",
+	    gnutls_strerror(ret));
+  exit(1);
+}
+// The peer certificate is the first certificate in the list.
+ret = gnutls_x509_crt_import(cert, certs, GNUTLS_X509_FMT_DER);
+if (ret != GNUTLS_E_SUCCESS) {
+  fprintf(stderr, "error: gnutls_x509_crt_import: %s\n",
+	    gnutls_strerror(ret));
+  exit(1);
+}
+ret = gnutls_x509_crt_check_hostname(cert, host);
+if (ret == 0 && !certificate_host_name_override(certs[0], host)) {
+  fprintf(stderr, "error: host name does not match certificate\n");
+  exit(1);
+}
+gnutls_x509_crt_deinit(cert);
+

+ In newer GNUTLS versions, certificate checking and host name validation can be combined using the gnutls_certificate_verify_peers3 function. +
+ An established TLS session can be used for sending and receiving data, as in Example 12.13, “Using a GNUTLS session”. +
Example 12.13. Using a GNUTLS session
+char buf[4096];
+snprintf(buf, sizeof(buf), "GET / HTTP/1.0\r\nHost: %s\r\n\r\n", host);
+ret = gnutls_record_send(session, buf, strlen(buf));
+if (ret < 0) {
+  fprintf(stderr, "error: gnutls_record_send: %s\n", gnutls_strerror(ret));
+  exit(1);
+}
+ret = gnutls_record_recv(session, buf, sizeof(buf));
+if (ret < 0) {
+  fprintf(stderr, "error: gnutls_record_recv: %s\n", gnutls_strerror(ret));
+  exit(1);
+}
+

+ In order to shut down a connection in an orderly manner, you should call the gnutls_bye function. Finally, the session object can be deallocated using gnutls_deinit (see Example 12.14, “Using a GNUTLS session”). +
Example 12.14. Using a GNUTLS session
+// Initiate an orderly connection shutdown.
+ret = gnutls_bye(session, GNUTLS_SHUT_RDWR);
+if (ret < 0) {
+  fprintf(stderr, "error: gnutls_bye: %s\n", gnutls_strerror(ret));
+  exit(1);
+}
+// Free the session object.
+gnutls_deinit(session);
+

\ No newline at end of file diff --git a/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-TLS-Client-NSS.html b/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-TLS-Client-NSS.html new file mode 100644 index 0000000..36f588b --- /dev/null +++ b/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-TLS-Client-NSS.html @@ -0,0 +1,226 @@ + +12.2.4. Implementing TLS Clients With NSS

Product SiteDocumentation Site

12.2.4. Implementing TLS Clients With NSS

+ The following code shows how to implement a simple TLS client using NSS. Note that the error handling needs replacing before production use. +
+ Using NSS needs several header files, as shown in Example 12.21, “Include files for NSS”. +
Example 12.21. Include files for NSS
+// NSPR include files
+#include <prerror.h>
+#include <prinit.h>
+
+// NSS include files
+#include <nss.h>
+#include <pk11pub.h>
+#include <secmod.h>
+#include <ssl.h>
+#include <sslproto.h>
+
+// Private API, no other way to turn a POSIX file descriptor into an
+// NSPR handle.
+NSPR_API(PRFileDesc*) PR_ImportTCPSocket(int);
+

+ Initializing the NSS library is a complex task (Example 12.22, “Initializing the NSS library”). It is not thread-safe. By default, the library is in export mode, and all strong ciphers are disabled. Therefore, after creating the NSSInitCContext object, we probe all the strong ciphers we want to use, and check if at least one of them is available. If not, we call NSS_SetDomesticPolicy to switch to unrestricted policy mode. This function replaces the existing global cipher suite policy, that is why we avoid calling it unless absolutely necessary. +
+ The simplest way to configured the trusted root certificates involves loading the libnssckbi.so NSS module with a call to the SECMOD_LoadUserModule function. The root certificates are compiled into this module. (The PEM module for NSS, libnsspem.so, offers a way to load trusted CA certificates from a file.) +
Example 12.22. Initializing the NSS library
+PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
+NSSInitContext *const ctx =
+  NSS_InitContext("sql:/etc/pki/nssdb", "", "", "", NULL,
+		    NSS_INIT_READONLY | NSS_INIT_PK11RELOAD);
+if (ctx == NULL) {
+  const PRErrorCode err = PR_GetError();
+  fprintf(stderr, "error: NSPR error code %d: %s\n",
+	    err, PR_ErrorToName(err));
+  exit(1);
+}
+
+// Ciphers to enable.
+static const PRUint16 good_ciphers[] = {
+  TLS_RSA_WITH_AES_128_CBC_SHA,
+  TLS_RSA_WITH_AES_256_CBC_SHA,
+  SSL_RSA_WITH_3DES_EDE_CBC_SHA,
+  SSL_NULL_WITH_NULL_NULL // sentinel
+};
+
+// Check if the current policy allows any strong ciphers.  If it
+// doesn't, switch to the "domestic" (unrestricted) policy.  This is
+// not thread-safe and has global impact.  Consequently, we only do
+// it if absolutely necessary.
+int found_good_cipher = 0;
+for (const PRUint16 *p = good_ciphers; *p != SSL_NULL_WITH_NULL_NULL;
+     ++p) {
+  PRInt32 policy;
+  if (SSL_CipherPolicyGet(*p, &policy) != SECSuccess) {
+    const PRErrorCode err = PR_GetError();
+    fprintf(stderr, "error: policy for cipher %u: error %d: %s\n",
+	      (unsigned)*p, err, PR_ErrorToName(err));
+    exit(1);
+  }
+  if (policy == SSL_ALLOWED) {
+    fprintf(stderr, "info: found cipher %x\n", (unsigned)*p);
+    found_good_cipher = 1;
+    break;
+  }
+}
+if (!found_good_cipher) {
+  if (NSS_SetDomesticPolicy() != SECSuccess) {
+    const PRErrorCode err = PR_GetError();
+    fprintf(stderr, "error: NSS_SetDomesticPolicy: error %d: %s\n",
+	      err, PR_ErrorToName(err));
+    exit(1);
+  }
+}
+
+// Initialize the trusted certificate store.
+char module_name[] = "library=libnssckbi.so name=\"Root Certs\"";
+SECMODModule *module = SECMOD_LoadUserModule(module_name, NULL, PR_FALSE);
+if (module == NULL || !module->loaded) {
+  const PRErrorCode err = PR_GetError();
+  fprintf(stderr, "error: NSPR error code %d: %s\n",
+	    err, PR_ErrorToName(err));
+  exit(1);
+}
+

+ Some of the effects of the initialization can be reverted with the following function calls: +
+SECMOD_DestroyModule(module);
+NSS_ShutdownContext(ctx);
+
+ After NSS has been initialized, the TLS connection can be created (Example 12.23, “Creating a TLS connection with NSS”). The internal PR_ImportTCPSocket function is used to turn the POSIX file descriptor sockfd into an NSPR file descriptor. (This function is de-facto part of the NSS public ABI, so it will not go away.) Creating the TLS-capable file descriptor requires a model descriptor, which is configured with the desired set of protocols and ciphers. (The good_ciphers variable is part of Example 12.22, “Initializing the NSS library”.) We cannot resort to disabling ciphers not on a whitelist because by default, the AES cipher suites are disabled. The model descriptor is not needed anymore after TLS support has been activated for the existing connection descriptor. +
+ The call to SSL_BadCertHook can be omitted if no mechanism to override certificate verification is needed. The bad_certificate function must check both the host name specified for the connection and the certificate before granting the override. +
+ Triggering the actual handshake requires three function calls, SSL_ResetHandshake, SSL_SetURL, and SSL_ForceHandshake. (If SSL_ResetHandshake is omitted, SSL_ForceHandshake will succeed, but the data will not be encrypted.) During the handshake, the certificate is verified and matched against the host name. +
Example 12.23. Creating a TLS connection with NSS
+// Wrap the POSIX file descriptor.  This is an internal NSPR
+// function, but it is very unlikely to change.
+PRFileDesc* nspr = PR_ImportTCPSocket(sockfd);
+sockfd = -1; // Has been taken over by NSPR.
+
+// Add the SSL layer.
+{
+  PRFileDesc *model = PR_NewTCPSocket();
+  PRFileDesc *newfd = SSL_ImportFD(NULL, model);
+  if (newfd == NULL) {
+    const PRErrorCode err = PR_GetError();
+    fprintf(stderr, "error: NSPR error code %d: %s\n",
+	      err, PR_ErrorToName(err));
+    exit(1);
+  }
+  model = newfd;
+  newfd = NULL;
+  if (SSL_OptionSet(model, SSL_ENABLE_SSL2, PR_FALSE) != SECSuccess) {
+    const PRErrorCode err = PR_GetError();
+    fprintf(stderr, "error: set SSL_ENABLE_SSL2 error %d: %s\n",
+	      err, PR_ErrorToName(err));
+    exit(1);
+  }
+  if (SSL_OptionSet(model, SSL_V2_COMPATIBLE_HELLO, PR_FALSE) != SECSuccess) {
+    const PRErrorCode err = PR_GetError();
+    fprintf(stderr, "error: set SSL_V2_COMPATIBLE_HELLO error %d: %s\n",
+	      err, PR_ErrorToName(err));
+    exit(1);
+  }
+  if (SSL_OptionSet(model, SSL_ENABLE_DEFLATE, PR_FALSE) != SECSuccess) {
+    const PRErrorCode err = PR_GetError();
+    fprintf(stderr, "error: set SSL_ENABLE_DEFLATE error %d: %s\n",
+	      err, PR_ErrorToName(err));
+    exit(1);
+  }
+
+  // Disable all ciphers (except RC4-based ciphers, for backwards
+  // compatibility).
+  const PRUint16 *const ciphers = SSL_GetImplementedCiphers();
+  for (unsigned i = 0; i < SSL_GetNumImplementedCiphers(); i++) {
+    if (ciphers[i] != SSL_RSA_WITH_RC4_128_SHA
+	  && ciphers[i] != SSL_RSA_WITH_RC4_128_MD5) {
+	if (SSL_CipherPrefSet(model, ciphers[i], PR_FALSE) != SECSuccess) {
+	  const PRErrorCode err = PR_GetError();
+	  fprintf(stderr, "error: disable cipher %u: error %d: %s\n",
+		  (unsigned)ciphers[i], err, PR_ErrorToName(err));
+	  exit(1);
+	}
+    }
+  }
+
+  // Enable the strong ciphers.
+  for (const PRUint16 *p = good_ciphers; *p != SSL_NULL_WITH_NULL_NULL;
+	 ++p) {
+    if (SSL_CipherPrefSet(model, *p, PR_TRUE) != SECSuccess) {
+	const PRErrorCode err = PR_GetError();
+	fprintf(stderr, "error: enable cipher %u: error %d: %s\n",
+		(unsigned)*p, err, PR_ErrorToName(err));
+	exit(1);
+    }
+  }
+
+  // Allow overriding invalid certificate.
+  if (SSL_BadCertHook(model, bad_certificate, (char *)host) != SECSuccess) {
+    const PRErrorCode err = PR_GetError();
+    fprintf(stderr, "error: SSL_BadCertHook error %d: %s\n",
+	      err, PR_ErrorToName(err));
+    exit(1);
+  }
+
+  newfd = SSL_ImportFD(model, nspr);
+  if (newfd == NULL) {
+    const PRErrorCode err = PR_GetError();
+    fprintf(stderr, "error: SSL_ImportFD error %d: %s\n",
+	      err, PR_ErrorToName(err));
+    exit(1);
+  }
+  nspr = newfd;
+  PR_Close(model);
+}
+
+// Perform the handshake.
+if (SSL_ResetHandshake(nspr, PR_FALSE) != SECSuccess) {
+  const PRErrorCode err = PR_GetError();
+  fprintf(stderr, "error: SSL_ResetHandshake error %d: %s\n",
+	    err, PR_ErrorToName(err));
+  exit(1);
+}
+if (SSL_SetURL(nspr, host) != SECSuccess) {
+  const PRErrorCode err = PR_GetError();
+  fprintf(stderr, "error: SSL_SetURL error %d: %s\n",
+	    err, PR_ErrorToName(err));
+  exit(1);
+}
+if (SSL_ForceHandshake(nspr) != SECSuccess) {
+  const PRErrorCode err = PR_GetError();
+  fprintf(stderr, "error: SSL_ForceHandshake error %d: %s\n",
+	    err, PR_ErrorToName(err));
+  exit(1);
+}
+

+ After the connection has been established, Example 12.24, “Using NSS for sending and receiving data” shows how to use the NSPR descriptor to communicate with the server. +
Example 12.24. Using NSS for sending and receiving data
+char buf[4096];
+snprintf(buf, sizeof(buf), "GET / HTTP/1.0\r\nHost: %s\r\n\r\n", host);
+PRInt32 ret = PR_Write(nspr, buf, strlen(buf));
+if (ret < 0) {
+  const PRErrorCode err = PR_GetError();
+  fprintf(stderr, "error: PR_Write error %d: %s\n",
+	    err, PR_ErrorToName(err));
+  exit(1);
+}
+ret = PR_Read(nspr, buf, sizeof(buf));
+if (ret < 0) {
+  const PRErrorCode err = PR_GetError();
+  fprintf(stderr, "error: PR_Read error %d: %s\n",
+	    err, PR_ErrorToName(err));
+  exit(1);
+}
+

+ Example 12.25, “Closing NSS client connections” shows how to close the connection. +
Example 12.25. Closing NSS client connections
+// Send close_notify alert.
+if (PR_Shutdown(nspr, PR_SHUTDOWN_BOTH) != PR_SUCCESS) {
+  const PRErrorCode err = PR_GetError();
+  fprintf(stderr, "error: PR_Read error %d: %s\n",
+	    err, PR_ErrorToName(err));
+  exit(1);
+}
+// Closes the underlying POSIX file descriptor, too.
+PR_Close(nspr);
+

\ No newline at end of file diff --git a/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-TLS-Client-OpenJDK.html b/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-TLS-Client-OpenJDK.html new file mode 100644 index 0000000..e26973d --- /dev/null +++ b/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-TLS-Client-OpenJDK.html @@ -0,0 +1,165 @@ + +12.2.3. Implementing TLS Clients With OpenJDK

Product SiteDocumentation Site

12.2.3. Implementing TLS Clients With OpenJDK

+ The examples below use the following cryptographic-related classes: +
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLParameters;
+import javax.net.ssl.SSLSocket;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509TrustManager;
+
+import sun.security.util.HostnameChecker;
+
+ If compatibility with OpenJDK 6 is required, it is necessary to use the internal class sun.security.util.HostnameChecker. (The public OpenJDK API does not provide any support for dissecting the subject distinguished name of an X.509 certificate, so a custom-written DER parser is needed—or we have to use an internal class, which we do below.) In OpenJDK 7, the setEndpointIdentificationAlgorithm method was added to the javax.net.ssl.SSLParameters class, providing an official way to implement host name checking. +
+ TLS connections are established using an SSLContext instance. With a properly configured OpenJDK installation, the SunJSSE provider uses the system-wide set of trusted root certificate authorities, so no further configuration is necessary. For backwards compatibility with OpenJDK 6, the TLSv1 provider has to be supported as a fall-back option. This is shown in Example 12.15, “Setting up an SSLContext for OpenJDK TLS clients”. +
Example 12.15. Setting up an SSLContext for OpenJDK TLS clients
+// Create the context.  Specify the SunJSSE provider to avoid
+// picking up third-party providers.  Try the TLS 1.2 provider
+// first, then fall back to TLS 1.0.
+SSLContext ctx;
+try {
+    ctx = SSLContext.getInstance("TLSv1.2", "SunJSSE");
+} catch (NoSuchAlgorithmException e) {
+    try {
+        ctx = SSLContext.getInstance("TLSv1", "SunJSSE");
+    } catch (NoSuchAlgorithmException e1) {
+        // The TLS 1.0 provider should always be available.
+        throw new AssertionError(e1);
+    } catch (NoSuchProviderException e1) {
+        throw new AssertionError(e1);
+    } 
+} catch (NoSuchProviderException e) {
+    // The SunJSSE provider should always be available.
+    throw new AssertionError(e);
+}
+ctx.init(null, null, null);
+

+ In addition to the context, a TLS parameter object will be needed which adjusts the cipher suites and protocols (Example 12.16, “Setting up SSLParameters for TLS use with OpenJDK”). Like the context, these parameters can be reused for multiple TLS connections. +
Example 12.16. Setting up SSLParameters for TLS use with OpenJDK
+// Prepare TLS parameters.  These have to applied to every TLS
+// socket before the handshake is triggered.
+SSLParameters params = ctx.getDefaultSSLParameters();
+// Do not send an SSL-2.0-compatible Client Hello.
+ArrayList<String> protocols = new ArrayList<String>(
+    Arrays.asList(params.getProtocols()));
+protocols.remove("SSLv2Hello");
+params.setProtocols(protocols.toArray(new String[protocols.size()]));
+// Adjust the supported ciphers.
+ArrayList<String> ciphers = new ArrayList<String>(
+    Arrays.asList(params.getCipherSuites()));
+ciphers.retainAll(Arrays.asList(
+    "TLS_RSA_WITH_AES_128_CBC_SHA256",
+    "TLS_RSA_WITH_AES_256_CBC_SHA256",
+    "TLS_RSA_WITH_AES_256_CBC_SHA",
+    "TLS_RSA_WITH_AES_128_CBC_SHA",
+    "SSL_RSA_WITH_3DES_EDE_CBC_SHA",
+    "SSL_RSA_WITH_RC4_128_SHA1",
+    "SSL_RSA_WITH_RC4_128_MD5",
+    "TLS_EMPTY_RENEGOTIATION_INFO_SCSV"));
+params.setCipherSuites(ciphers.toArray(new String[ciphers.size()]));
+

+ As initialized above, the parameter object does not yet require host name checking. This has to be enabled separately, and this is only supported by OpenJDK 7 and later: +
+params.setEndpointIdentificationAlgorithm("HTTPS");
+
+ All application protocols can use the "HTTPS" algorithm. (The algorithms have minor differences with regard to wildcard handling, which should not matter in practice.) +
+ Example 12.17, “Establishing a TLS connection with OpenJDK” shows how to establish the connection. Before the handshake is initialized, the protocol and cipher configuration has to be performed, by applying the parameter object params. (After this point, changes to params will not affect this TLS socket.) As mentioned initially, host name checking requires using an internal API on OpenJDK 6. +
Example 12.17. Establishing a TLS connection with OpenJDK
+// Create the socket and connect it at the TCP layer.
+SSLSocket socket = (SSLSocket) ctx.getSocketFactory()
+    .createSocket(host, port);
+
+// Disable the Nagle algorithm.
+socket.setTcpNoDelay(true);
+
+// Adjust ciphers and protocols.
+socket.setSSLParameters(params);
+
+// Perform the handshake.
+socket.startHandshake();
+
+// Validate the host name.  The match() method throws
+// CertificateException on failure.
+X509Certificate peer = (X509Certificate)
+    socket.getSession().getPeerCertificates()[0];
+// This is the only way to perform host name checking on OpenJDK 6.
+HostnameChecker.getInstance(HostnameChecker.TYPE_TLS).match(
+    host, peer);
+

+ Starting with OpenJDK 7, the last lines can be omitted, provided that host name verification has been enabled by calling the setEndpointIdentificationAlgorithm method on the params object (before it was applied to the socket). +
+ The TLS socket can be used as a regular socket, as shown in Example 12.18, “Using a TLS client socket in OpenJDK”. +
Example 12.18. Using a TLS client socket in OpenJDK
+socket.getOutputStream().write("GET / HTTP/1.0\r\n\r\n"
+    .getBytes(Charset.forName("UTF-8")));
+byte[] buffer = new byte[4096];
+int count = socket.getInputStream().read(buffer);
+System.out.write(buffer, 0, count);
+

12.2.3.1. Overriding server certificate validation with OpenJDK 6

+ Overriding certificate validation requires a custom trust manager. With OpenJDK 6, the trust manager lacks information about the TLS session, and to which server the connection is made. Certificate overrides have to be tied to specific servers (host names). Consequently, different TrustManager and SSLContext objects have to be used for different servers. +
+ In the trust manager shown in Example 12.19, “A customer trust manager for OpenJDK TLS clients”, the server certificate is identified by its SHA-256 hash. +
Example 12.19. A customer trust manager for OpenJDK TLS clients
+public class MyTrustManager implements X509TrustManager {
+    private final byte[] certHash;
+
+    public MyTrustManager(byte[] certHash) throws Exception {
+        this.certHash = certHash;
+    }
+
+    @Override
+    public void checkClientTrusted(X509Certificate[] chain, String authType)
+            throws CertificateException {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void checkServerTrusted(X509Certificate[] chain,
+            String authType) throws CertificateException {
+        byte[] digest = getCertificateDigest(chain[0]);
+        String digestHex = formatHex(digest);
+
+        if (Arrays.equals(digest, certHash)) {
+            System.err.println("info: accepting certificate: " + digestHex);
+        } else {
+            throw new CertificateException("certificate rejected: "  +
+                    digestHex);
+        }
+    }
+
+    @Override
+    public X509Certificate[] getAcceptedIssuers() {
+        return new X509Certificate[0];
+    }
+}
+

+ This trust manager has to be passed to the init method of the SSLContext object, as show in Example 12.20, “Using a custom TLS trust manager with OpenJDK”. +
Example 12.20. Using a custom TLS trust manager with OpenJDK
+SSLContext ctx;
+try {
+    ctx = SSLContext.getInstance("TLSv1.2", "SunJSSE");
+} catch (NoSuchAlgorithmException e) {
+    try {
+        ctx = SSLContext.getInstance("TLSv1", "SunJSSE");
+    } catch (NoSuchAlgorithmException e1) {
+        throw new AssertionError(e1);
+    } catch (NoSuchProviderException e1) {
+        throw new AssertionError(e1);
+    }
+} catch (NoSuchProviderException e) {
+    throw new AssertionError(e);
+}
+MyTrustManager tm = new MyTrustManager(certHash);
+ctx.init(null, new TrustManager[] {tm}, null);
+

+ When certificate overrides are in place, host name verification should not be performed because there is no security requirement that the host name in the certificate matches the host name used to establish the connection (and it often will not). However, without host name verification, it is not possible to perform transparent fallback to certification validation using the system certificate store. +
+ The approach described above works with OpenJDK 6 and later versions. Starting with OpenJDK 7, it is possible to use a custom subclass of the javax.net.ssl.X509ExtendedTrustManager class. The OpenJDK TLS implementation will call the new methods, passing along TLS session information. This can be used to implement certificate overrides as a fallback (if certificate or host name verification fails), and a trust manager object can be used for multiple servers because the server address is available to the trust manager. +
\ No newline at end of file diff --git a/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-TLS-Client-Python.html b/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-TLS-Client-Python.html new file mode 100644 index 0000000..e54eca2 --- /dev/null +++ b/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-TLS-Client-Python.html @@ -0,0 +1,62 @@ + +12.2.5. Implementing TLS Clients With Python

Product SiteDocumentation Site

12.2.5. Implementing TLS Clients With Python

+ The Python distribution provides a TLS implementation in the ssl module (actually a wrapper around OpenSSL). The exported interface is somewhat restricted, so that the client code shown below does not fully implement the recommendations in Section 12.1.1, “OpenSSL Pitfalls”. +

Important

+ Currently, most Python function which accept https:// URLs or otherwise implement HTTPS support do not perform certificate validation at all. (For example, this is true for the httplib and xmlrpclib modules.) If you use HTTPS, you should not use the built-in HTTP clients. The Curl class in the curl module, as provided by the python-pycurl package implements proper certificate validation. +
+ The ssl module currently does not perform host name checking on the server certificate. Example 12.26, “Implementing TLS host name checking Python (without wildcard support)” shows how to implement certificate matching, using the parsed certificate returned by getpeercert. +
Example 12.26. Implementing TLS host name checking Python (without wildcard support)
+def check_host_name(peercert, name):
+    """Simple certificate/host name checker.  Returns True if the
+    certificate matches, False otherwise.  Does not support
+    wildcards."""
+    # Check that the peer has supplied a certificate.
+    # None/{} is not acceptable.
+    if not peercert:
+        return False
+    if peercert.has_key("subjectAltName"):
+        for typ, val in peercert["subjectAltName"]:
+            if typ == "DNS" and val == name:
+                return True
+    else:
+        # Only check the subject DN if there is no subject alternative
+        # name.
+        cn = None
+        for attr, val in peercert["subject"]:
+            # Use most-specific (last) commonName attribute.
+            if attr == "commonName":
+                cn = val
+        if cn is not None:
+            return cn == name
+    return False
+

+ To turn a regular, connected TCP socket into a TLS-enabled socket, use the ssl.wrap_socket function. The function call in Example 12.27, “Establishing a TLS client connection with Python” provides additional arguments to override questionable defaults in OpenSSL and in the Python module. +
  • + ciphers="HIGH:-aNULL:-eNULL:-PSK:RC4-SHA:RC4-MD5" selects relatively strong cipher suites with certificate-based authentication. (The call to check_host_name function provides additional protection against anonymous cipher suites.) +
  • + ssl_version=ssl.PROTOCOL_TLSv1 disables SSL 2.0 support. By default, the ssl module sends an SSL 2.0 client hello, which is rejected by some servers. Ideally, we would request OpenSSL to negotiated the most recent TLS version supported by the server and the client, but the Python module does not allow this. +
  • + cert_reqs=ssl.CERT_REQUIRED turns on certificate validation. +
  • + ca_certs='/etc/ssl/certs/ca-bundle.crt' initializes the certificate store with a set of trusted root CAs. Unfortunately, it is necessary to hard-code this path into applications because the default path in OpenSSL is not available through the Python ssl module. +
+ The ssl module (and OpenSSL) perform certificate validation, but the certificate must be compared manually against the host name, by calling the check_host_name defined above. +
Example 12.27. Establishing a TLS client connection with Python
+sock = ssl.wrap_socket(sock,
+                       ciphers="HIGH:-aNULL:-eNULL:-PSK:RC4-SHA:RC4-MD5",
+                       ssl_version=ssl.PROTOCOL_TLSv1,
+                       cert_reqs=ssl.CERT_REQUIRED,
+                       ca_certs='/etc/ssl/certs/ca-bundle.crt')
+# getpeercert() triggers the handshake as a side effect.
+if not check_host_name(sock.getpeercert(), host):
+    raise IOError("peer certificate does not match host name")
+

+ After the connection has been established, the TLS socket can be used like a regular socket: +
+sock.write("GET / HTTP/1.1\r\nHost: " + host + "\r\n\r\n")
+print sock.read()
+
+ Closing the TLS socket is straightforward as well: +
+sock.close()
+
\ No newline at end of file diff --git a/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-TLS-Client.html b/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-TLS-Client.html new file mode 100644 index 0000000..b8f4ac1 --- /dev/null +++ b/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-TLS-Client.html @@ -0,0 +1,199 @@ + +12.2. TLS Clients

Product SiteDocumentation Site

12.2. TLS Clients

+ Secure use of TLS in a client generally involves all of the following steps. (Individual instructions for specific TLS implementations follow in the next sections.) +
  • + The client must configure the TLS library to use a set of trusted root certificates. These certificates are provided by the system in /etc/ssl/certs or files derived from it. +
  • + The client selects sufficiently strong cryptographic primitives and disables insecure ones (such as no-op encryption). Compression and SSL version 2 support must be disabled (including the SSLv2-compatible handshake). +
  • + The client initiates the TLS connection. The Server Name Indication extension should be used if supported by the TLS implementation. Before switching to the encrypted connection state, the contents of all input and output buffers must be discarded. +
  • + The client needs to validate the peer certificate provided by the server, that is, the client must check that there is a cryptographically protected chain from a trusted root certificate to the peer certificate. (Depending on the TLS implementation, a TLS handshake can succeed even if the certificate cannot be validated.) +
  • + The client must check that the configured or user-provided server name matches the peer certificate provided by the server. +
+ It is safe to provide users detailed diagnostics on certificate validation failures. Other causes of handshake failures and, generally speaking, any details on other errors reported by the TLS implementation (particularly exception tracebacks), must not be divulged in ways that make them accessible to potential attackers. Otherwise, it is possible to create decryption oracles. +

Important

+ Depending on the application, revocation checking (against certificate revocations lists or via OCSP) and session resumption are important aspects of production-quality client. These aspects are not yet covered. +

12.2.1. Implementation TLS Clients With OpenSSL

+ In the following code, the error handling is only exploratory. Proper error handling is required for production use, especially in libraries. +
+ The OpenSSL library needs explicit initialization (see Example 12.3, “OpenSSL library initialization”). +
Example 12.3. OpenSSL library initialization
+// The following call prints an error message and calls exit() if
+// the OpenSSL configuration file is unreadable.
+OPENSSL_config(NULL);
+// Provide human-readable error messages.
+SSL_load_error_strings();
+// Register ciphers.
+SSL_library_init();
+

+ After that, a context object has to be created, which acts as a factory for connection objects (Example 12.4, “OpenSSL client context creation”). We use an explicit cipher list so that we do not pick up any strange ciphers when OpenSSL is upgraded. The actual version requested in the client hello depends on additional restrictions in the OpenSSL library. If possible, you should follow the example code and use the default list of trusted root certificate authorities provided by the system because you would have to maintain your own set otherwise, which can be cumbersome. +
Example 12.4. OpenSSL client context creation
+// Configure a client connection context.  Send a hendshake for the
+// highest supported TLS version, and disable compression.
+const SSL_METHOD *const req_method = SSLv23_client_method();
+SSL_CTX *const ctx = SSL_CTX_new(req_method);
+if (ctx == NULL) {
+  ERR_print_errors(bio_err);
+  exit(1);
+}
+SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_COMPRESSION);
+
+// Adjust the ciphers list based on a whitelist.  First enable all
+// ciphers of at least medium strength, to get the list which is
+// compiled into OpenSSL.
+if (SSL_CTX_set_cipher_list(ctx, "HIGH:MEDIUM") != 1) {
+  ERR_print_errors(bio_err);
+  exit(1);
+}
+{
+  // Create a dummy SSL session to obtain the cipher list.
+  SSL *ssl = SSL_new(ctx);
+  if (ssl == NULL) {
+    ERR_print_errors(bio_err);
+    exit(1);
+  }
+  STACK_OF(SSL_CIPHER) *active_ciphers = SSL_get_ciphers(ssl);
+  if (active_ciphers == NULL) {
+    ERR_print_errors(bio_err);
+    exit(1);
+  }
+  // Whitelist of candidate ciphers.
+  static const char *const candidates[] =  {
+    "AES128-GCM-SHA256", "AES128-SHA256", "AES256-SHA256", // strong ciphers
+    "AES128-SHA", "AES256-SHA", // strong ciphers, also in older versions
+    "RC4-SHA", "RC4-MD5", // backwards compatibility, supposed to be weak
+    "DES-CBC3-SHA", "DES-CBC3-MD5", // more backwards compatibility
+    NULL
+  };
+  // Actually selected ciphers.
+  char ciphers[300];
+  ciphers[0] = '\0';
+  for (const char *const *c = candidates; *c; ++c) {
+    for (int i = 0; i < sk_SSL_CIPHER_num(active_ciphers); ++i) {
+	if (strcmp(SSL_CIPHER_get_name(sk_SSL_CIPHER_value(active_ciphers, i)),
+		   *c) == 0) {
+	  if (*ciphers) {
+	    strcat(ciphers, ":");
+	  }
+	  strcat(ciphers, *c);
+	  break;
+	}
+    }
+  }
+  SSL_free(ssl);
+  // Apply final cipher list.
+  if (SSL_CTX_set_cipher_list(ctx, ciphers) != 1) {
+    ERR_print_errors(bio_err);
+    exit(1);
+  }
+}
+
+// Load the set of trusted root certificates.
+if (!SSL_CTX_set_default_verify_paths(ctx)) {
+  ERR_print_errors(bio_err);
+  exit(1);
+}
+

+ A single context object can be used to create multiple connection objects. It is safe to use the same SSL_CTX object for creating connections concurrently from multiple threads, provided that the SSL_CTX object is not modified (e.g., callbacks must not be changed). +
+ After creating the TCP socket and disabling the Nagle algorithm (per Example 12.1, “Deactivating the TCP Nagle algorithm”), the actual connection object needs to be created, as show in Example 12.4, “OpenSSL client context creation”. If the handshake started by SSL_connect fails, the ssl_print_error_and_exit function from Example 12.2, “Obtaining OpenSSL error codes” is called. +
+ The certificate_validity_override function provides an opportunity to override the validity of the certificate in case the OpenSSL check fails. If such functionality is not required, the call can be removed, otherwise, the application developer has to implement it. +
+ The host name passed to the functions SSL_set_tlsext_host_name and X509_check_host must be the name that was passed to getaddrinfo or a similar name resolution function. No host name canonicalization must be performed. The X509_check_host function used in the final step for host name matching is currently only implemented in OpenSSL 1.1, which is not released yet. In case host name matching fails, the function certificate_host_name_override is called. This function should check user-specific certificate store, to allow a connection even if the host name does not match the certificate. This function has to be provided by the application developer. Note that the override must be keyed by both the certificate and the host name. +
Example 12.5. Creating a client connection using OpenSSL
+// Create the connection object.
+SSL *ssl = SSL_new(ctx);
+if (ssl == NULL) {
+  ERR_print_errors(bio_err);
+  exit(1);
+}
+SSL_set_fd(ssl, sockfd);
+
+// Enable the ServerNameIndication extension
+if (!SSL_set_tlsext_host_name(ssl, host)) {
+  ERR_print_errors(bio_err);
+  exit(1);
+}
+
+// Perform the TLS handshake with the server.
+ret = SSL_connect(ssl);
+if (ret != 1) {
+  // Error status can be 0 or negative.
+  ssl_print_error_and_exit(ssl, "SSL_connect", ret);
+}
+
+// Obtain the server certificate.
+X509 *peercert = SSL_get_peer_certificate(ssl);
+if (peercert == NULL) {
+  fprintf(stderr, "peer certificate missing");
+  exit(1);
+}
+
+// Check the certificate verification result.  Allow an explicit
+// certificate validation override in case verification fails.
+int verifystatus = SSL_get_verify_result(ssl);
+if (verifystatus != X509_V_OK && !certificate_validity_override(peercert)) {
+  fprintf(stderr, "SSL_connect: verify result: %s\n",
+	    X509_verify_cert_error_string(verifystatus));
+  exit(1);
+}
+
+// Check if the server certificate matches the host name used to
+// establish the connection.
+// FIXME: Currently needs OpenSSL 1.1.
+if (X509_check_host(peercert, (const unsigned char *)host, strlen(host),
+		      0) != 1
+    && !certificate_host_name_override(peercert, host)) {
+  fprintf(stderr, "SSL certificate does not match host name\n");
+  exit(1);
+}
+
+X509_free(peercert);
+
+

+ The connection object can be used for sending and receiving data, as in Example 12.6, “Using an OpenSSL connection to send and receive data”. It is also possible to create a BIO object and use the SSL object as the underlying transport, using BIO_set_ssl. +
Example 12.6. Using an OpenSSL connection to send and receive data
+const char *const req = "GET / HTTP/1.0\r\n\r\n";
+if (SSL_write(ssl, req, strlen(req)) < 0) {
+  ssl_print_error_and_exit(ssl, "SSL_write", ret);
+}
+char buf[4096];
+ret = SSL_read(ssl, buf, sizeof(buf));
+if (ret < 0) {
+  ssl_print_error_and_exit(ssl, "SSL_read", ret);
+}
+

+ When it is time to close the connection, the SSL_shutdown function needs to be called twice for an orderly, synchronous connection termination (Example 12.7, “Closing an OpenSSL connection in an orderly fashion”). This exchanges close_notify alerts with the server. The additional logic is required to deal with an unexpected close_notify from the server. Note that is necessary to explicitly close the underlying socket after the connection object has been freed. +
Example 12.7. Closing an OpenSSL connection in an orderly fashion
+// Send the close_notify alert.
+ret = SSL_shutdown(ssl);
+switch (ret) {
+case 1:
+  // A close_notify alert has already been received.
+  break;
+case 0:
+  // Wait for the close_notify alert from the peer.
+  ret = SSL_shutdown(ssl);
+  switch (ret) {
+  case 0:
+    fprintf(stderr, "info: second SSL_shutdown returned zero\n");
+    break;
+  case 1:
+    break;
+  default:
+    ssl_print_error_and_exit(ssl, "SSL_shutdown 2", ret);
+  }
+  break;
+default:
+  ssl_print_error_and_exit(ssl, "SSL_shutdown 1", ret);
+}
+SSL_free(ssl);
+close(sockfd);
+

+ Example 12.8, “Closing an OpenSSL connection in an orderly fashion” shows how to deallocate the context object when it is no longer needed because no further TLS connections will be established. +
Example 12.8. Closing an OpenSSL connection in an orderly fashion
+SSL_CTX_free(ctx);
+

\ No newline at end of file diff --git a/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-Tasks-Descriptors-Child_Processes.html b/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-Tasks-Descriptors-Child_Processes.html new file mode 100644 index 0000000..26fd42d --- /dev/null +++ b/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-Tasks-Descriptors-Child_Processes.html @@ -0,0 +1,18 @@ + +5.2. Preventing file descriptor leaks to child processes

Product SiteDocumentation Site

5.2. Preventing file descriptor leaks to child processes

+ Child processes created with fork share the initial set of file descriptors with their parent process. By default, file descriptors are also preserved if a new process image is created with execve (or any of the other functions such as system or posix_spawn). +
+ Usually, this behavior is not desirable. There are two ways to turn it off, that is, to prevent new process images from inheriting the file descriptors in the parent process: +
  • + Set the close-on-exec flag on all newly created file descriptors. Traditionally, this flag is controlled by the FD_CLOEXEC flag, using F_GETFD and F_SETFD operations of the fcntl function. +
    + However, in a multi-threaded process, there is a race condition: a subprocess could have been created between the time the descriptor was created and the FD_CLOEXEC was set. Therefore, many system calls which create descriptors (such as open and openat) now accept the O_CLOEXEC flag (SOCK_CLOEXEC for socket and socketpair), which cause the FD_CLOEXEC flag to be set for the file descriptor in an atomic fashion. In addition, a few new systems calls were introduced, such as pipe2 and dup3. +
    + The downside of this approach is that every descriptor needs to receive special treatment at the time of creation, otherwise it is not completely effective. +
  • + After calling fork, but before creating a new process image with execve, all file descriptors which the child process will not need are closed. +
    + Traditionally, this was implemented as a loop over file descriptors ranging from 3 to 255 and later 1023. But this is only an approximatio because it is possible to create file descriptors outside this range easily (see Section 5.3, “Dealing with the select limit”). Another approach reads /proc/self/fd and closes the unexpected descriptors listed there, but this approach is much slower. +
+ At present, environments which care about file descriptor leakage implement the second approach. OpenJDK 6 and 7 are among them. +
\ No newline at end of file diff --git a/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-Tasks-Descriptors-Limit.html b/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-Tasks-Descriptors-Limit.html new file mode 100644 index 0000000..8a4667a --- /dev/null +++ b/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-Tasks-Descriptors-Limit.html @@ -0,0 +1,22 @@ + +5.3. Dealing with the select limit

Product SiteDocumentation Site

5.3. Dealing with the select limit

+ By default, a user is allowed to open only 1024 files in a single process, but the system administrator can easily change this limit (which is necessary for busy network servers). However, there is another restriction which is more difficult to overcome. +
+ The select function only supports a maximum of FD_SETSIZE file descriptors (that is, the maximum permitted value for a file descriptor is FD_SETSIZE - 1, usually 1023.) If a process opens many files, descriptors may exceed such limits. It is impossible to query such descriptors using select. +
+ If a library which creates many file descriptors is used in the same process as a library which uses select, at least one of them needs to be changed. Calls to select can be replaced with calls to poll or another event handling mechanism. +
+ Alternatively, the library with high descriptor usage can relocate descriptors above the FD_SETSIZE limit using the following procedure. +
  • + Create the file descriptor fd as usual, preferably with the O_CLOEXEC flag. +
  • + Before doing anything else with the descriptor fd, invoke: +
    +	  int newfd = fcntl(fd, F_DUPFD_CLOEXEC, (long)FD_SETSIZE);
    +
  • + Check that newfd result is non-negative, otherwise close fd and report an error, and return. +
  • + Close fd and continue to use newfd. +
+ The new descriptor has been allocated above the FD_SETSIZE. Even though this algorithm is racy in the sense that the FD_SETSIZE first descriptors could fill up, a very high degree of physical parallelism is required before this becomes a problem. +
\ No newline at end of file diff --git a/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-Tasks-Descriptors.html b/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-Tasks-Descriptors.html new file mode 100644 index 0000000..6abfdc8 --- /dev/null +++ b/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-Tasks-Descriptors.html @@ -0,0 +1,26 @@ + +Chapter 5. File Descriptor Management

Product SiteDocumentation Site

Chapter 5. File Descriptor Management

+ File descriptors underlie all input/output mechanisms offered by the system. They are used to implementation the FILE *-based functions found in <stdio.h>, and all the file and network communication facilities provided by the Python and Java environments are eventually implemented in them. +
+ File descriptors are small, non-negative integers in userspace, and are backed on the kernel side with complicated data structures which can sometimes grow very large. +

5.1. Closing descriptors

+ If a descriptor is no longer used by a program and is not closed explicitly, its number cannot be reused (which is problematic in itself, see Section 5.3, “Dealing with the select limit”), and the kernel resources are not freed. Therefore, it is important to close all descriptors at the earlierst point in time possible, but not earlier. +

5.1.1. Error handling during descriptor close

+ The close system call is always successful in the sense that the passed file descriptor is never valid after the function has been called. However, close still can return an error, for example if there was a file system failure. But this error is not very useful because the absence of an error does not mean that all caches have been emptied and previous writes have been made durable. Programs which need such guarantees must open files with O_SYNC or use fsync or fdatasync, and may also have to fsync the directory containing the file. +

5.1.2. Closing descriptors and race conditions

+ Unlike process IDs, which are recycle only gradually, the kernel always allocates the lowest unused file descriptor when a new descriptor is created. This means that in a multi-threaded program which constantly opens and closes file descriptors, descriptors are reused very quickly. Unless descriptor closing and other operations on the same file descriptor are synchronized (typically, using a mutex), there will be race coniditons and I/O operations will be applied to the wrong file descriptor. +
+ Sometimes, it is necessary to close a file descriptor concurrently, while another thread might be about to use it in a system call. In order to support this, a program needs to create a single special file descriptor, one on which all I/O operations fail. One way to achieve this is to use socketpair, close one of the descriptors, and call shutdown(fd, SHUTRDWR) on the other. +
+ When a descriptor is closed concurrently, the program does not call close on the descriptor. Instead it program uses dup2 to replace the descriptor to be closed with the dummy descriptor created earlier. This way, the kernel will not reuse the descriptor, but it will carry out all other steps associated with calling a descriptor (for instance, if the descriptor refers to a stream socket, the peer will be notified). +
+ This is just a sketch, and many details are missing. Additional data structures are needed to determine when it is safe to really close the descriptor, and proper locking is required for that. +

5.1.3. Lingering state after close

+ By default, closing a stream socket returns immediately, and the kernel will try to send the data in the background. This means that it is impossible to implement accurate accounting of network-related resource utilization from userspace. +
+ The SO_LINGER socket option alters the behavior of close, so that it will return only after the lingering data has been processed, either by sending it to the peer successfully, or by discarding it after the configured timeout. However, there is no interface which could perform this operation in the background, so a separate userspace thread is needed for each close call, causing scalability issues. +
+ Currently, there is no application-level countermeasure which applies universally. Mitigation is possible with iptables (the connlimit match type in particular) and specialized filtering devices for denial-of-service network traffic. +
+ These problems are not related to the TIME_WAIT state commonly seen in netstat output. The kernel automatically expires such sockets if necessary. +
\ No newline at end of file diff --git a/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-Tasks-File_System-Features.html b/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-Tasks-File_System-Features.html new file mode 100644 index 0000000..2bd8def --- /dev/null +++ b/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-Tasks-File_System-Features.html @@ -0,0 +1,28 @@ + +6.4. File system features

Product SiteDocumentation Site

6.4. File system features

+ Not all file systems support all features. This makes it very difficult to write general-purpose tools for copying files. For example, a copy operation intending to preserve file permissions will generally fail when copying to a FAT file system. +
  • + Some file systems are case-insensitive. Most should be case-preserving, though. +
  • + Name length limits vary greatly, from eight to thousands of bytes. Path length limits differ as well. Most systems impose an upper bound on path names passed to the kernel, but using relative path names, it is possible to create and access files whose absolute path name is essentially of unbounded length. +
  • + Some file systems do not store names as fairly unrestricted byte sequences, as it has been traditionally the case on GNU systems. This means that some byte sequences (outside the POSIX safe character set) are not valid names. Conversely, names of existing files may not be representable as byte sequences, and the files are thus inaccessible on GNU systems. Some file systems perform Unicode canonicalization on file names. These file systems preserve case, but reading the name of a just-created file using readdir might still result in a different byte sequence. +
  • + Permissions and owners are not universally supported (and SUID/SGID bits may not be available). For example, FAT file systems assign ownership based on a mount option, and generally mark all files as executable. Any attempt to change permissions would result in an error. +
  • + Non-regular files (device nodes, FIFOs) are not generally available. +
  • + Only on some file systems, files can have holes, that is, not all of their contents is backed by disk storage. +
  • + ioctl support (even fairly generic functionality such as FIEMAP for discovering physical file layout and holes) is file-system-specific. +
  • + Not all file systems support extended attributes, ACLs and SELinux metadata. Size and naming restriction on extended attributes vary. +
  • + Hard links may not be supported at all (FAT) or only within the same directory (AFS). Symbolic links may not be available, either. Reflinks (hard links with copy-on-write semantics) are still very rare. Recent systems restrict creation of hard links to users which own the target file or have read/write access to it, but older systems do not. +
  • + Renaming (or moving) files using rename can fail (even when stat indicates that the source and target directories are located on the same file system). This system call should work if the old and new paths are located in the same directory, though. +
  • + Locking semantics vary among file systems. This affects advisory and mandatory locks. For example, some network file systems do not allow deleting files which are opened by any process. +
  • + Resolution of time stamps varies from two seconds to nanoseconds. Not all time stamps are available on all file systems. File creation time (birth time) is not exposed over the stat/fstat interface, even if stored by the file system. +
\ No newline at end of file diff --git a/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-Tasks-File_System-Foreign.html b/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-Tasks-File_System-Foreign.html new file mode 100644 index 0000000..2d9adeb --- /dev/null +++ b/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-Tasks-File_System-Foreign.html @@ -0,0 +1,10 @@ + +6.2. Accessing the file system as a different user

Product SiteDocumentation Site

6.2. Accessing the file system as a different user

+ This section deals with access to the file system as a specific user. This is different from accessing files and directories owned by a different, potentially untrusted user; see Section 6.2, “Accessing the file system as a different user”. +
+ One approach is to spawn a child process which runs under the target user and group IDs (both effective and real IDs). Note that this child process can block indefinitely, even when processing regular files only. For example, a special FUSE file system could cause the process to hang in uninterruptible sleep inside a stat system call. +
+ An existing process could change its user and group ID using setfsuid and setfsgid. (These functions are preferred over seteuid and setegid because they do not allow the impersonated user to send signals to the process.) These functions are not thread safe. In multi-threaded processes, these operations need to be performed in a single-threaded child process. Unexpected blocking may occur as well. +
+ It is not recommended to try to reimplement the kernel permission checks in user space because the required checks are complex. It is also very difficult to avoid race conditions during path name resolution. +
\ No newline at end of file diff --git a/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-Tasks-File_System-Free_Space.html b/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-Tasks-File_System-Free_Space.html new file mode 100644 index 0000000..15c45c1 --- /dev/null +++ b/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-Tasks-File_System-Free_Space.html @@ -0,0 +1,4 @@ + +6.5. Checking free space

Product SiteDocumentation Site

6.5. Checking free space

+ The statvfs and fstatvfs functions allow programs to examine the number of available blocks and inodes, through the members f_bfree, f_bavail, f_ffree, and f_favail of struct statvfs. Some file systems return fictional values in the f_ffree and f_favail fields, so the only reliable way to discover if the file system still has space for a file is to try to create it. The f_bfree field should be reasonably accurate, though. +
\ No newline at end of file diff --git a/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-Tasks-File_System-Limits.html b/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-Tasks-File_System-Limits.html new file mode 100644 index 0000000..f9788df --- /dev/null +++ b/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-Tasks-File_System-Limits.html @@ -0,0 +1,6 @@ + +6.3. File system limits

Product SiteDocumentation Site

6.3. File system limits

+ For historical reasons, there are preprocessor constants such as PATH_MAX, NAME_MAX. However, on most systems, the length of canonical path names (absolute path names with all symbolic links resolved, as returned by realpath or canonicalize_file_name) can exceed PATH_MAX bytes, and individual file name components can be longer than NAME_MAX. This is also true of the _PC_PATH_MAX and _PC_NAME_MAX values returned by pathconf, and the f_namemax member of struct statvfs. Therefore, these constants should not be used. This is also reason why the readdir_r should never be used (instead, use readdir). +
+ You should not write code in a way that assumes that there is an upper limit on the number of subdirectories of a directory, the number of regular files in a directory, or the link count of an inode. +
\ No newline at end of file diff --git a/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-Tasks-Library_Design-Callbacks.html b/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-Tasks-Library_Design-Callbacks.html new file mode 100644 index 0000000..d79bc76 --- /dev/null +++ b/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-Tasks-Library_Design-Callbacks.html @@ -0,0 +1,14 @@ + +4.3. Callbacks

Product SiteDocumentation Site

4.3. Callbacks

+ Higher-order code is difficult to analyze for humans and computers alike, so it should be avoided. Often, an iterator-based interface (a library function which is called repeatedly by client code and returns a stream of events) leads to a better design which is easier to document and use. +
+ If callbacks are unavoidable, some guidelines for them follow. +
+ In modern C++ code, std::function objects should be used for callbacks. +
+ In older C++ code and in C code, all callbacks must have an additional closure parameter of type void *, the value of which can be specified by client code. If possible, the value of the closure parameter should be provided by client code at the same time a specific callback is registered (or specified as a function argument). If a single closure parameter is shared by multiple callbacks, flexibility is greatly reduced, and conflicts between different pieces of client code using the same library object could be unresolvable. In some cases, it makes sense to provide a de-registration callback which can be used to destroy the closure parameter when the callback is no longer used. +
+ Callbacks can throw exceptions or call longjmp. If possible, all library objects should remain in a valid state. (All further operations on them can fail, but it should be possible to deallocate them without causing resource leaks.) +
+ The presence of callbacks raises the question if functions provided by the library are reentrant. Unless a library was designed for such use, bad things will happen if a callback function uses functions in the same library (particularly if they are invoked on the same objects and manipulate the same state). When the callback is invoked, the library can be in an inconsistent state. Reentrant functions are more difficult to write than thread-safe functions (by definition, simple locking would immediately lead to deadlocks). It is also difficult to decide what to do when destruction of an object which is currently processing a callback is requested. +
\ No newline at end of file diff --git a/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-Tasks-Processes-Daemons.html b/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-Tasks-Processes-Daemons.html new file mode 100644 index 0000000..7db21c7 --- /dev/null +++ b/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-Tasks-Processes-Daemons.html @@ -0,0 +1,18 @@ + +8.4. Daemons

Product SiteDocumentation Site

8.4. Daemons

+ Background processes providing system services (daemons) need to decouple themselves from the controlling terminal and the parent process environment: +
  • + Fork. +
  • + In the child process, call setsid. The parent process can simply exit (using _exit, to avoid running clean-up actions twice). +
  • + In the child process, fork again. Processing continues in the child process. Again, the parent process should just exit. +
  • + Replace the descriptors 0, 1, 2 with a descriptor for /dev/null. Logging should be redirected to syslog. +
+ Older instructions for creating daemon processes recommended a call to umask(0). This is risky because it often leads to world-writable files and directories, resulting in security vulnerabilities such as arbitrary process termination by untrusted local users, or log file truncation. If the umask needs setting, a restrictive value such as 027 or 077 is recommended. +
+ Other aspects of the process environment may have to changed as well (environment variables, signal handler disposition). +
+ It is increasingly common that server processes do not run as background processes, but as regular foreground process under a supervising master process (such as systemd). Server processes should offer a command line option which disables forking and replacement of the standard output and standard error streams. Such an option is also useful for debugging. +
\ No newline at end of file diff --git a/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-Tasks-Processes-Fork-Parallel.html b/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-Tasks-Processes-Fork-Parallel.html new file mode 100644 index 0000000..e184d1f --- /dev/null +++ b/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-Tasks-Processes-Fork-Parallel.html @@ -0,0 +1,4 @@ + +8.6. fork as a primitive for parallelism

Product SiteDocumentation Site

8.6. fork as a primitive for parallelism

+ A call to fork which is not immediately followed by a call to execve (perhaps after rearranging and closing file descriptors) is typically unsafe, especially from a library which does not control the state of the entire process. Such use of fork should be replaced with proper child processes or threads. +
\ No newline at end of file diff --git a/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-Tasks-Processes.html b/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-Tasks-Processes.html new file mode 100644 index 0000000..435ba94 --- /dev/null +++ b/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-Tasks-Processes.html @@ -0,0 +1,56 @@ + +Chapter 8. Processes

Product SiteDocumentation Site

Chapter 8. Processes

8.1. Safe process creation

+ This section describes how to create new child processes in a safe manner. In addition to the concerns addressed below, there is the possibility of file descriptor leaks, see Section 5.2, “Preventing file descriptor leaks to child processes”. +

8.1.1. Obtaining the program path and the command line template

+ The name and path to the program being invoked should be hard-coded or controlled by a static configuration file stored at a fixed location (at an file system absolute path). The same applies to the template for generating the command line. +
+ The configured program name should be an absolute path. If it is a relative path, the contents of the PATH must be obtained in s secure manner (see Section 8.3.1, “Accessing environment variables”). If the PATH variable is not set or untrusted, the safe default /bin:/usr/bin must be used. +
+ If too much flexibility is provided here, it may allow invocation of arbitrary programs without proper authorization. +

8.1.2. Bypassing the shell

+ Child processes should be created without involving the system shell. +
+ For C/C++, system should not be used. The posix_spawn function can be used instead, or a combination fork and execve. (In some cases, it may be preferable to use vfork or the Linux-specific clone system call instead of fork.) +
+ In Python, the subprocess module bypasses the shell by default (when the shell keyword argument is not set to true). os.system should not be used. +
+ The Java class java.lang.ProcessBuilder can be used to create subprocesses without interference from the system shell. +

Portability notice

+ On Windows, there is no argument vector, only a single argument string. Each application is responsible for parsing this string into an argument vector. There is considerable variance among the quoting style recognized by applications. Some of them expand shell wildcards, others do not. Extensive application-specific testing is required to make this secure. +
+ Note that some common applications (notably ssh) unconditionally introduce the use of a shell, even if invoked directly without a shell. It is difficult to use these applications in a secure manner. In this case, untrusted data should be supplied by other means. For example, standard input could be used, instead of the command line. +

8.1.3. Specifying the process environment

+ Child processes should be created with a minimal set of environment variables. This is absolutely essential if there is a trust transition involved, either when the parent process was created, or during the creation of the child process. +
+ In C/C++, the environment should be constructed as an array of strings and passed as the envp argument to posix_spawn or execve. The functions setenv, unsetenv and putenv should not be used. They are not thread-safe and suffer from memory leaks. +
+ Python programs need to specify a dict for the the env argument of the subprocess.Popen constructor. The Java class java.lang.ProcessBuilder provides a environment() method, which returns a map that can be manipulated. +
+ The following list provides guidelines for selecting the set of environment variables passed to the child process. +
  • + PATH should be initialized to /bin:/usr/bin. +
  • + USER and HOME can be inhereted from the parent process environment, or they can be initialized from the pwent structure for the user. +
  • + The DISPLAY and XAUTHORITY variables should be passed to the subprocess if it is an X program. Note that this will typically not work across trust boundaries because XAUTHORITY refers to a file with 0600 permissions. +
  • + The location-related environment variables LANG, LANGUAGE, LC_ADDRESS, LC_ALL, LC_COLLATE, LC_CTYPE, LC_IDENTIFICATION, LC_MEASUREMENT, LC_MESSAGES, LC_MONETARY, LC_NAME, LC_NUMERIC, LC_PAPER, LC_TELEPHONE and LC_TIME can be passed to the subprocess if present. +
  • + The called process may need application-specific environment variables, for example for passing passwords. (See Section 8.1.5, “Passing secrets to subprocesses”.) +
  • + All other environment variables should be dropped. Names for new environment variables should not be accepted from untrusted sources. +

8.1.4. Robust argument list processing

+ When invoking a program, it is sometimes necessary to include data from untrusted sources. Such data should be check against embedded NUL characters because the system APIs will sliently truncate argument strings at the first NUL character. +
+ The following recommendations assume that the program being invoked uses GNU-style option processing using getopt_long. This convention is widely used, but it is just that, and individual programs might interpret a command line in a different way. +
+ If the untrusted data has to go into an option, use the --option-name=VALUE syntax, placing the option and its value into the same command line argument. This avoids any potential confusion if the data starts with -. +
+ For positional arguments, terminate the option list with a single -- marker after the last option, and include the data at the right position. The -- marker terminates option processing, and the data will not be treated as an option even if it starts with a dash. +

8.1.5. Passing secrets to subprocesses

+ The command line (the name of the program and its argument) of a running process is traditionally available to all local users. The called program can overwrite this information, but only after it has run for a bit of time, during which the information may have been read by other processes. However, on Linux, the process environment is restricted to the user who runs the process. Therefore, if you need a convenient way to pass a password to a child process, use an environment variable, and not a command line argument. (See Section 8.1.3, “Specifying the process environment”.) +

Portability notice

+ On some UNIX-like systems (notably Solaris), environment variables can be read by any system user, just like command lines. +
+ If the environment-based approach cannot be used due to portability concerns, the data can be passed on standard input. Some programs (notably gpg) use special file descriptors whose numbers are specified on the command line. Temporary files are an option as well, but they might give digital forensics access to sensitive data (such as passphrases) because it is difficult to safely delete them in all cases. +
\ No newline at end of file diff --git a/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-Tasks-Serialization-XML-Entities.html b/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-Tasks-Serialization-XML-Entities.html new file mode 100644 index 0000000..955c416 --- /dev/null +++ b/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-Tasks-Serialization-XML-Entities.html @@ -0,0 +1,6 @@ + +9.4.2. Entity expansion

Product SiteDocumentation Site

9.4.2. Entity expansion

+ When external DTD processing is disabled, an internal DTD subset can still contain entity definitions. Entity declarations can reference other entities. Some XML libraries expand entities automatically, and this processing cannot be switched off in some places (such as attribute values or content models). Without limits on the entity nesting level, this expansion results in data which can grow exponentially in length with size of the input. (If there is a limit on the nesting level, the growth is still polynomial, unless further limits are imposed.) +
+ Consequently, the processing internal DTD subsets should be disabled if possible, and only trusted DTDs should be processed. If a particular XML application does not permit such restrictions, then application-specific limits are called for. +
\ No newline at end of file diff --git a/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-Tasks-Serialization-XML-Expat.html b/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-Tasks-Serialization-XML-Expat.html new file mode 100644 index 0000000..9354658 --- /dev/null +++ b/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-Tasks-Serialization-XML-Expat.html @@ -0,0 +1,31 @@ + +9.4.5. Using Expat for XML parsing

Product SiteDocumentation Site

9.4.5. Using Expat for XML parsing

+ By default, Expat does not try to resolve external IDs, so no steps are required to block them. However, internal entity declarations are processed. Installing a callback which stops parsing as soon as such entities are encountered disables them, see Example 9.1, “Disabling XML entity processing with Expat”. Expat does not perform any validation, so there are no problems related to that. +
Example 9.1. Disabling XML entity processing with Expat
+// Stop the parser when an entity declaration is encountered.
+static void
+EntityDeclHandler(void *userData,
+		  const XML_Char *entityName, int is_parameter_entity,
+		  const XML_Char *value, int value_length,
+		  const XML_Char *base, const XML_Char *systemId,
+		  const XML_Char *publicId, const XML_Char *notationName)
+{
+  XML_StopParser((XML_Parser)userData, XML_FALSE);
+}
+

+ This handler must be installed when the XML_Parser object is created (Example 9.2, “Creating an Expat XML parser”). +
Example 9.2. Creating an Expat XML parser
+XML_Parser parser = XML_ParserCreate("UTF-8");
+if (parser == NULL) {
+  fprintf(stderr, "XML_ParserCreate failed\n");
+  close(fd);
+  exit(1);
+}
+// EntityDeclHandler needs a reference to the parser to stop
+// parsing.
+XML_SetUserData(parser, parser);
+// Disable entity processing, to inhibit entity expansion.
+XML_SetEntityDeclHandler(parser, EntityDeclHandler);
+

+ It is also possible to reject internal DTD subsets altogeher, using a suitable XML_StartDoctypeDeclHandler handler installed with XML_SetDoctypeDeclHandler. +
\ No newline at end of file diff --git a/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-Tasks-Serialization-XML-OpenJDK_Parse-SAX.html b/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-Tasks-Serialization-XML-OpenJDK_Parse-SAX.html new file mode 100644 index 0000000..1fe7ed9 --- /dev/null +++ b/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-Tasks-Serialization-XML-OpenJDK_Parse-SAX.html @@ -0,0 +1,47 @@ + +9.4.6.2. XML Schema validation in OpenJDK

Product SiteDocumentation Site

9.4.6.2. XML Schema validation in OpenJDK

+ Example 9.7, “SAX-based validation against an XML schema in OpenJDK” shows how to validate a document against an XML Schema, using a SAX-based approach. The XML data is read from an java.io.InputStream in the inputStream variable. +
Example 9.7. SAX-based validation against an XML schema in OpenJDK
+SchemaFactory factory = SchemaFactory.newInstance(
+        XMLConstants.W3C_XML_SCHEMA_NS_URI);
+
+// This enables restrictions on the schema and document
+// complexity.
+factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
+
+// This prevents resource resolution by the schema itself.
+// If the schema is trusted and references additional files,
+// this line must be omitted, otherwise loading these files
+// will fail.
+factory.setResourceResolver(new NoResourceResolver());
+
+Schema schema = factory.newSchema(schemaFile);
+Validator validator = schema.newValidator();
+
+// This prevents external resource resolution.
+validator.setResourceResolver(new NoResourceResolver());
+
+validator.validate(new SAXSource(new InputSource(inputStream)));
+

+ The NoResourceResolver class is defined in Example 9.4, “Helper class to prevent schema resolution in OpenJDK”. +
+ If you need to validate a document against an XML schema, use the code in Example 9.6, “DOM-based XML parsing in OpenJDK” to create the document, but do not enable validation at this point. Then use Example 9.8, “Validation of a DOM document against an XML schema in OpenJDK” to perform the schema-based validation on the org.w3c.dom.Document instance document. +
Example 9.8. Validation of a DOM document against an XML schema in OpenJDK
+SchemaFactory factory = SchemaFactory.newInstance(
+        XMLConstants.W3C_XML_SCHEMA_NS_URI);
+
+// This enables restrictions on schema complexity.
+factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
+
+// The following line prevents resource resolution
+// by the schema itself.
+factory.setResourceResolver(new NoResourceResolver());
+
+Schema schema = factory.newSchema(schemaFile);
+
+Validator validator = schema.newValidator();
+
+// This prevents external resource resolution.
+validator.setResourceResolver(new NoResourceResolver());
+validator.validate(new DOMSource(document));
+

\ No newline at end of file diff --git a/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-Tasks-Serialization-XML-OpenJDK_Parse.html b/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-Tasks-Serialization-XML-OpenJDK_Parse.html new file mode 100644 index 0000000..c0825be --- /dev/null +++ b/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-Tasks-Serialization-XML-OpenJDK_Parse.html @@ -0,0 +1,74 @@ + +9.4.6. Using OpenJDK for XML parsing and validation

Product SiteDocumentation Site

9.4.6. Using OpenJDK for XML parsing and validation

+ OpenJDK contains facilities for DOM-based, SAX-based, and StAX-based document parsing. Documents can be validated against DTDs or XML schemas. +
+ The approach taken to deal with entity expansion differs from the general recommendation in Section 9.4.2, “Entity expansion”. We enable the the feature flag javax.xml.XMLConstants.FEATURE_SECURE_PROCESSING, which enforces heuristic restrictions on the number of entity expansions. Note that this flag alone does not prevent resolution of external references (system IDs or public IDs), so it is slightly misnamed. +
+ In the following sections, we use helper classes to prevent external ID resolution. +
Example 9.3. Helper class to prevent DTD external entity resolution in OpenJDK
+class NoEntityResolver implements EntityResolver {
+    @Override
+    public InputSource resolveEntity(String publicId, String systemId)
+            throws SAXException, IOException {
+        // Throwing an exception stops validation.
+        throw new IOException(String.format(
+                "attempt to resolve \"%s\" \"%s\"", publicId, systemId));
+    }
+}
+

Example 9.4. Helper class to prevent schema resolution in OpenJDK
+class NoResourceResolver implements LSResourceResolver {
+    @Override
+    public LSInput resolveResource(String type, String namespaceURI,
+            String publicId, String systemId, String baseURI) {
+        // Throwing an exception stops validation.
+        throw new RuntimeException(String.format(
+                "resolution attempt: type=%s namespace=%s " +
+                "publicId=%s systemId=%s baseURI=%s",
+                type, namespaceURI, publicId, systemId, baseURI));
+    }
+}
+

+ Example 9.5, “Java imports for OpenJDK XML parsing” shows the imports used by the examples. +
Example 9.5. Java imports for OpenJDK XML parsing
+import javax.xml.XMLConstants;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.sax.SAXSource;
+import javax.xml.validation.Schema;
+import javax.xml.validation.SchemaFactory;
+import javax.xml.validation.Validator;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.ls.LSInput;
+import org.w3c.dom.ls.LSResourceResolver;
+import org.xml.sax.EntityResolver;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+import org.xml.sax.XMLReader;
+

9.4.6.1. DOM-based XML parsing and DTD validation in OpenJDK

+ This approach produces a org.w3c.dom.Document object from an input stream. Example 9.6, “DOM-based XML parsing in OpenJDK” use the data from the java.io.InputStream instance in the inputStream variable. +
Example 9.6. DOM-based XML parsing in OpenJDK
+DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+// Impose restrictions on the complexity of the DTD.
+factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
+
+// Turn on validation.
+// This step can be omitted if validation is not desired.
+factory.setValidating(true);
+
+// Parse the document.
+DocumentBuilder builder = factory.newDocumentBuilder();
+builder.setEntityResolver(new NoEntityResolver());
+builder.setErrorHandler(new Errors());
+Document document = builder.parse(inputStream);
+

+ External entity references are prohibited using the NoEntityResolver class in Example 9.3, “Helper class to prevent DTD external entity resolution in OpenJDK”. Because external DTD references are prohibited, DTD validation (if enabled) will only happen against the internal DTD subset embedded in the XML document. +
+ To validate the document against an external DTD, use a javax.xml.transform.Transformer class to add the DTD reference to the document, and an entity resolver which whitelists this external reference. +
\ No newline at end of file diff --git a/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-Tasks-Serialization-XML-Validation.html b/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-Tasks-Serialization-XML-Validation.html new file mode 100644 index 0000000..06fae75 --- /dev/null +++ b/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-Tasks-Serialization-XML-Validation.html @@ -0,0 +1,6 @@ + +9.4.4. Algorithmic complexity of XML validation

Product SiteDocumentation Site

9.4.4. Algorithmic complexity of XML validation

+ DTD-based XML validation uses regular expressions for content models. The XML specification requires that content models are deterministic, which means that efficient validation is possible. However, some implementations do not enforce determinism, and require exponential (or just polynomial) amount of space or time for validating some DTD/document combinations. +
+ XML schemas and RELAX NG (via the xsd: prefix) directly support textual regular expressions which are not required to be deterministic. +
\ No newline at end of file diff --git a/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-Tasks-Serialization-XML-XInclude.html b/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-Tasks-Serialization-XML-XInclude.html new file mode 100644 index 0000000..c4ed55e --- /dev/null +++ b/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-Tasks-Serialization-XML-XInclude.html @@ -0,0 +1,6 @@ + +9.4.3. XInclude processing

Product SiteDocumentation Site

9.4.3. XInclude processing

+ XInclude processing can reference file and network resources and include them into the document, much like external entity references. When parsing untrusted XML documents, XInclude processing should be truned off. +
+ XInclude processing is also fairly complex and may pull in support for the XPointer and XPath specifications, considerably increasing the amount of code required for XML processing. +
\ No newline at end of file diff --git a/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-Tasks-Serialization-XML.html b/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-Tasks-Serialization-XML.html new file mode 100644 index 0000000..8833c89 --- /dev/null +++ b/defensive-coding/tmp/en-US/html/sect-Defensive_Coding-Tasks-Serialization-XML.html @@ -0,0 +1,30 @@ + +9.4. XML serialization

Product SiteDocumentation Site

9.4. XML serialization

+ +

9.4.1. External references

+ XML documents can contain external references. They can occur in various places. +
  • + In the DTD declaration in the header of an XML document: +
    +<!DOCTYPE html PUBLIC
    +  "-//W3C//DTD XHTML 1.0 Transitional//EN"
    +  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    +
  • + In a namespace declaration: +
    +<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    +
  • + In an entity defintion: +
    +<!ENTITY sys SYSTEM "http://www.example.com/ent.xml">
    +<!ENTITY pub PUBLIC "-//Example//Public Entity//EN"
    +  "http://www.example.com/pub-ent.xml">
    +
  • + In a notation: +
    +<!NOTATION not SYSTEM "../not.xml">
    +
+ Originally, these external references were intended as unique identifiers, but by many XML implementations, they are used for locating the data for the referenced element. This causes unwanted network traffic, and may disclose file system contents or otherwise unreachable network resources, so this functionality should be disabled. +
+ Depending on the XML library, external referenced might be processed not just when parsing XML, but also when generating it. +
\ No newline at end of file diff --git a/defensive-coding/tmp/en-US/pdf/Defensive_Coding-1-Defensive_Coding-en-US.pdf b/defensive-coding/tmp/en-US/pdf/Defensive_Coding-1-Defensive_Coding-en-US.pdf new file mode 100644 index 0000000000000000000000000000000000000000..ee0d315741c66cebd968adc64b519d97916cfe5c GIT binary patch literal 490100 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"EKa)I1V^s8}+a#FN}$p)v0 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"EKa)I1V^s8}+a#FN}$p)v0 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"EKa)I1V^s8}+a#FN}$p)v0 zxHO5!dpJL!J86Owxy1_`AxZ)fOgPmCC1r9qW52jtFiMPGHe&AzeFVJp#loXbHEDC& zC)n2T>&&2sK9gDGVY_r`aG2F$){+t1bSSDibfkQk=(o70b}PgCmdYYNp-d`sjl{V) zTVK7%R)JVw^SW?UawSh>oZ^DK6yHK7C&x7{cd z#8q=HE(Iqg^uiQyZh(9ow9d%8K*ht7iSL3@C0rP9DY`3*;@!@1i+?ce%Dk+ePmh$6U&WASulqw1j6)NaJR)C$Eo}Ars=!RDm^bcEUeo`;LEH7{9x6 z_+)~Am?nFANnF)EFlj`7jr}a$wjP$)nzx7i>bkbS(#hP|a2lROdX*lt;cW(%3@n|g zT<-%nLbk(UmlY*swxTyqyWyNtic2tkA_Tu3^wNRXdoF7@@w#6ru3)rsavii3l^o40 zZMXbY5=M25J2SCTqhs^SYRKNjOPS*e@n^o_29oqVa2XF%jUpv)`@|SfLqK_N{}@d6 zkSGn_Sa}$zt*wZ1x*BJIz@}<$WV7BHhNs$?)#CRU--9v8;tHxL5ZyWXK0LI1-e}-*Wf^e4uMoYtIkjH1hMGa5Qc) zxv;ZjnA5*t?7k*TV3f=V=%VL|#HQDg_jza7z9bm26VLbVqWYsTVOL}pjbG!}={=?@ z--uvFn2-d;SGT(@M91)}^+rpBZAO$5Uv%dBN%IG#6^WHjGZ&UND&f%45raLTR`Zw` zW(Rs#xwf5mEjD(k$^g(}b zd^mY%Br1~@b-`f0VEzt#@8PLogmYo$y(b-5074bg8A(w`eCcX|%d+|_9Q8>}4PERzESpEWK z{nhZrU!2Lr#tHy~S^wh9pMD_!1tMVvvHU_LKvp0C2xKN=1v3BIX8{6P0bmy9zel8g zHRrFUFMe6p{5RDASpdvTAR-nA?DHbgVm zetvf(1|WI5d3TE-Tu$7(JHYUz0t9$hGOyF4H)BTLEpUtwhB_B?ShG5twK?{4|vfp9AA6Fo`U!!;QS+l0o`_LWx3`Q^dm!PR_fY$(Ra zm&{wWEt(wBmpm;VPqp@!C@(Ai!YJXjse$}RY5nt)Y3KVggZn(7_-4&ZqiT!Cf^jEJ zv~o{*rMjk#=C(yBr}arW^Ts9E6CP3q}p`43zLr7kg9 zIoaFJ17BZcKyBMeV8p^~(R&>g9B!SZb}TO-|Bo|HA0z9dmfE0Km7;DRcF^EaO?PSh zEIyrq<_4b5A8s~HZI`WLh4ab?gwzYJ(95w+8Z7UsfP(!)j$qoDO9MOem1t z#$s#|pL4~c_1F>6yjEm4t#6TFdd>p*OIT16j!vXSSuX zm;F@XAPj^qoI>OsOMoYkC4~WZ6@t5`BUuoSIYs10PT#--EvsQH>%9H) zxcI{uIRo4_J)gc5<Pa!$V;QNf`CA2^?EWZbKpYd`7QzrbjFdFqOg&Ur88 zz_Jw7d?#A3)6PcKVnDALj`pQ$*atJ!wN1~pk@9#Ox>ggHJhxNd3&nv|VkbcCsxJOp zza84>Ld4BJIkokV%>YPR8-NQ(_j(3ml;iSN+&9hou%1Qdbh4Z&jQ6sjJtjcDQ^t_zyWxYkO2vyb~suhT*Ga-jMc zf?X65hQqdJB!~b|*3_?NKjtR&1Mle`uXswbELI3&8TTgYVVufTBZON_QB+a;rmOUo zYO9F~3y0(*E3hx%6(_0*6LTfQRMA)}v4*OKCoCOZ^&sN;s(anxl*AS=?B3RjAM7ys zZ?X9wM(#e4h;z&9WhF6vpxCLM+5F6!LB^>2eUQrz8n4{*XfD3RDt4AU^Vdt0*#w~3_d+=HC69=57{JvmE#xJiPdy0S67gVJ*Q@k|9} z%_K-&`87!#iw7l&f|HdM1qzsY(9AKxL51w}G3nwaLbcQONN8M!1tki&-2@$)Ebi6I z1sgOeYWXfx77BS*vJ#-%Ksk3M{zXyq25PVg3`D{eijj-N=$h`N#x(Lk2rtetVLrBX zVGCa17^-54gkySBz+FTgLk)Qm-aeGXEjXBY=_!%(!NlGp1BHt_PG=Q8TJKyCYI_RD z4h+Vbze-YW+`Y_s5MgV=h*p7p@hBrd+MSQpr2qI}=;LDqoQX5!@Qd@v@$phid8dD& zIl}Ow?d7&XiBddXSpwg)SSQfIS0!tlM^xn_jV?K)Rji5}PF6L%GF?NLNgQ z$rB9Z*z|+2DoLHb}4?Qx&LLxZP(hA8}c|yqxL=8RbCndLK2ouc;jaGRJ)K!s zTu9vf;Wg0Bv(9miwQJ^eW3mp-omCPmd!|=v4<1TMyq2S$55^AwY&W5hXW0o6x{QKv zfT44d_MY701R!atu$m+7tin+A58>Oo^#;=T^NEwRrP%uOKAgHi1Ac-$JPlyi>%Zb@7dL z_>>r<0BHD>bb_*&Py8r@=xBBN4&QZvM3j+7E7ZgFZ^I}iXj(T*pz=S(wO0X>vw7~) z0Si%ya>UWaH#2v+JX~i=7t+G`ka{#(apl#hr8;*85%J&Z`DfDoWu%MF?IIkx2dgS; z1%&87cL3#yGb0K&oQO%WxjKe1y6R%$?y5hHoJ&6E&q*>>%wBcA>KLNdwjgx}Tc{nr zSETAZR+sfW4{7>Rn#Cez2}H@?;B)A0HXiDHc)dXz(|@*-Wgtgb9@jXeQ{6nf+RQYP zD*+LMWcd*>cZt4b*3N-fGy~^UOODl@B`4G3CKc0S$IuS3GwfL4$JLm!SsAK?vDA#Q zM$pihJ7+*fK$_MoR0q-OdW@>5>%d?VmZyacF=x0_?bVF+(7|B2sGy4E zM_^sA*e92``RJF)NPL}lpHoWSm6FcHF*nelOC<(H47Dh$BkfSn3vn2q7gBbXDK92! z?Iu@So48@&yg#xPu2?(}%`foZDhlf*3QOzg%5Wep#)Bay>vy5`>96I%(mmPoG;sSc zI0j&LYPYK!$Mf&%o}Ka12of~p&LA0>$;f>GV3@?vuO6o9Epw(WEi(Y1FfbCC=SvGc zWP7cavSQWU3w8t2znrN>O?=?qSK21^q<52!MmvHSHNCJEi!-_zEJ*j2Fo$Or91(Ii z$eXe+Ieq&XQD3;~ zS*^)}J5E1UU&h$Ii^JqR`hw*B2+tZKNu+h)qly<}Zx%i2NT_?J)${qrXKZ**lTSX5 zb7Npsx@l`v%gp(EiI}iax#v<4&ku6>UZA?@l6(rA0Aps~saSr~F*u;>g0~a(3YN+& zQb8PIzj@-z>j<*E@c}61CH?^3ll@(cWaF?i*7HaDzLq!s54BO(Y$=GH{zttX`I?3x z8m9D*ci^`Pb~~0_PJlI^%Af~#j45di#vS<6l_o^$9{Sc){BNS@Ls$aS4> z08VHAtjOWEwsQqB;!rw!5ZC`%YM>N_eXOzB@-+DS0Bjj};p^BYXhqiqhhSqa7*^oa z;=j)V4ygTyro!DtI>h{-z-IIh(}`Nc{2JR3D1Nwayyq zHgNB_SjlnM5J~gO_0u@uIj}ta8e{nRRznWXyW^5T^>v>4`=)Zw#T&?IhP(22Qt*x7 z%xm+(caiDo`BhJMGkDW1$M<#onh@BEZu@@fDUrk`Ol6l=$X+q&H5)D$SqmIIRY8 zHdat_(y%?>Hmj9Tnm!`3QUSdRY5bVPgfZJ40fOvfb{U_@A5ZE#MfOj=hm$E z0jOsjblLRdYFUl^g&w&X#N9xfVqt!Wi|+{PA;Ez)vlB_;gI_-&`F#(f!Z_oHrguur zQw4k7_^yK|!|+G-apu0Kous~4BZRfxoh^58KD{CFl3)4@8p87D+JgoH`yckIzqRT= z(vM%V`?q-ge}I1cy7IrQiTvRt`;YD&zvS>Q`T=BO`ycx8%VPGw(D8o`-2mBs8F(_Y zvH^f>AR=})w!dxQ`5$EbKcbjFWjyOomhyLG{7(bVderutim!yhqc@O@Sl^7jSFp5+ zV0$PjolsgJ=H9({)(q0b#DpB4u6`f2AgNWC!aBNB!Yuke@0TWczs|csiVY5W`{iQ? ze*2a^SdAMNk0RHI_B&<%%JHwIj?rQ1j|ID=oSuPAtKm53PFWNl9HG({Wwht0oxzEXL`1&;0bL-^`7e z&F^L>nJAGcJ+U$UWx}Dtpm_>E|GedeQH}FSRk)Kb+6Yo9i5_sPxor{}Hz85Xym6z@ zjKRa3;Ck`6nRqbWfif?X-X26h+xk z3FNlIzD1qR0=ZdsSw8x6!V}MwW%)H?)edI9%Zom}uJSN~sxs6jFkZ%mG07Z>kA~eh z>IGxEox=y`N%t9du7iwY<;DnhY~T^GZKM5K!)_UeqIBiAV(}1cdT6l%cBluKQ7{rR z30u~=c&4ENKAT*pA;a9cZ`m;-=9)43UUL}}M1W*ijzl~Pq6e;ufcy{8$dt?K$q@|0 zhg^I`WzrVOYWdEFY^LNdR;dnZh|S?+wB3h^(sZ+`Xz>`Y8~bbmPZ}A_pR5su?fT=6C5F1qcjslU>Pitb{UqMWRjhsVy4< zIx&G~D(Vt9ORUJTSU&bccjkQR1vQLzD-Wu3z9Od7jZg9<`F-*%v`5C_#cPzXReaA< zOGk63o-a(aau9jF!WC?z;(b>P5M)A~O9E7A<71raVedkUT$W#z!rQ-!7A!t$G~{pc z#??txGAXz!;tNyIm`nRAX|rk~26J}xoPwu%G%8g|qJ-F3=UTIPH9W}_T%61=LO4bT zZ^~)nFJqH?*lf@|Eq{IOyk7R{VCUTO(RWSfcqsrO5^vz#4iICeQpXNwNT6Pj2Z}a|+PueF!*&-C+v1r5Pt3pRaFE z6%!sZ5_Tr!>Iw=sG%bWtGG%aLXbwn#WOgi3t0ol0+oNbfPny23aw% ztDLoBF;Qo=`Kp!X2Wo@%2M?!)5t0!0^YYdd($cc9O{Ip{x1*2n@lI&S3v$We`iO6G zgO#9geRbHXiB4{K2b&rQiG1N}Vt8g|;(c|@&$Zb0CZp-lJBCO8;ueAQ`j&K2VKoq6 zQP-***s!wW+=QG#o|!^<;_q9;h>mi0ao&E5l}(brtEY@&s_|o@@E;&^(yF<0Xx>nJwcFq`~EV+2tmU#C7#a$*;q z2DVMr$s-=K>j$Bys|Y5y(s0umqXg+SH`5~-)y<0E9c-4z3_4FLt$Pq&f`?|N<5CLk zhnXc!N7$Z(o)j>PB-s zE9dS0azsqVGuPna5Bm86>l`OeQJJ1}7E1I5r0^&cg3 z)db3DjlwDZKknW!%93sC7ERl>U1{64ZQE9*ZKKk*tx8mym9}j=^R}ve_WAbtzJ1R- z_qEsFkNa!26)Re-Ip&-ZEqWh)^dVl}EQPrYi4RjsKmSfx)Jb6kBN3dSY+jUQ(=H)F zRdHjr;5zz){cg;-vh2lnim&9bo#*lV*|Dq+Ui`|xUKOJfHEdAM<7@n(F@x1MA8u&D zA-ofmRaoyzfJTA+w>>S8Da95oouW(lA96FeAo5d@IKl{LBZ@eM!ssam2*rC54bX9; znoiYp`#_8J>oFOHbDp9Q`MTsO6N_g77TJVu;CIMJo z3__3!uVo+E_0&8y9cF1|H;=Rhlxz3E-4mP+0kTQoM8v~(VJi};(M{^YUJ!7(ciE$d z6kW*WDlg){;$qimvay$8ZvypyDtFJOmD5qVy+i<8oM^44=?<5gl!wh4n;BKX8J4X| z7OkC`hVeC~lVH-XO3Vsmn)3oSGD-*VQuHgi@}hT`LPSFZ=LK?BVv@Q*puRnzw>FN-o`O%;}S8zTzULxIQ^o$h@b5|EgpjSHGhP-sSXqL8dR6P~yEIp<#0 zpk$RCiJzW;!PfC8RnA_ar*OV*V+?7jZC7z^6G8kW7UcDbFgh#$O(4c6u06_75r&e!qL*6IxB5x^XPP79)q zS#Y;&%jbMq+OqK&&1ig^({89zWvtG&5hx#WuMfM0Z5&+uO}-p$HL6>b(bB*a6v5hA zeN?^QIfW3_TmI3)tkXWSR^r`m!v`&+B-zEuKwIJ!?SPnU&q2>Y#luQOU)v!jon(1H zHmeoII~V~vhJ#9hda7YEYKf;kTAgrn6m|!d&ayJ*%c?73M=F-|;VsU37yI;RwUBQa z!;Gwc>FALxk(DWjoAvI^I~d@TT6LjP31AK3D=Wjm;6eHE0=jmV)>3 zWLTCjY>JZb)E=C1l6aB{OA43Wb7|qIfi}m8)OahJwVdVJ)ggxZWv9PM6K+1UmyL9b zpx$5u^M;vmapEU(yNKLn`>y{WTzu=H3=)=^@z?z6Ej0Z|n4wr)M%#4&T@jyT1BQ(@ z2F`VfKpe$-ZVx`F!wwBg&_?R#Ijd{ldsxiiynA&~O#1lQ1J3yuTVTPki0$_cH&<2K zDn*1!3(cS`EsleU(fa(0vRQSbCw|5!OPOqRd)nR(jbvD~v2T7l@+dBLNt6DrOon%E z0jGIU!wMdp#Bk~!c9=6^^f0H3a^W~^kB)|4wXeG1I#cCx#cN=d`8ZDytEPWS53J7CV%gA?B;LXO8c59P(eGU2R%UV>XWrGFXjz})5` zscv28{<=K=gPLAiXM729SCt-nk*jS?GWm*>1mgW-?nj&_g%hm0J3KD3wR>Mz?={Qh z`6@YOMYGrS6gg$eXoH01z^Ip$qN-gC!UnAv!}wcP*KGEe9(~S}3{27Q*fkxV?g00zc z7nMq}^R#1em5o>8b=|JsBJE;>&bgcB;2$4x0qM(;Ze;XUbNxbZ&{f`V-YECA3EU`? z-n|Z@hh4H!%^PAKRfj2A@8Y@*j6Dpff!9K4Cx~sDWRO|BHauRqb(FytkCCYh3 z=kh9U-`t(SI*04tJ?KGU{M8?^;NEFwrqkVS>Ju-DBIIL~Vev(yMWapd>NyG^|QB}jd}i`&}|cQPxUFqm>C79q2> zoN~B)4KOg+69RpdZU~95Dj(AQFQqdZ?Sw9_m+W>+Q4bjh6x>OT>$pUhwU{onQ4zap z*1{s+Oa}Of4cXfl<0V~6D)F9aT~gX-Jk#NnMHWx;tN7(yb0Ou_tL)H-@-JF zKKH2JUSFYaz+NH#9ccZtLgN=`{lnYfpFJ$tnEp$U{(l2l{iERGUsCn|Xm9dYu=*SH z{RXRy%#8m8tH1l6{5P=rcWL$CQ}(Z^dRBTyS`PZZ@ih3|L*>6+^WRmS{I-Q;XC`1^ z;Gm_aXCq)?WT$0fXZz36>i=lq@;|E&es^;DKN!tF92OYpS$_|Pft`t# znf}+{SpL5l%zy2?|0;!G{zpZRsD-t&i6a4>sI`H!iLi;0ov{f4FE5mnv!jWD4V3%0 z3GLNMoEF&b&m2R&T%{~AARyq^%RK(e2&^NKxQb>8x*ecn8NHrD63ICjmX6cb=JO~s zGtqpCh&S<*xXq0_iQY}VEgH_Qfi&5#pLY*hJ~eUJzejwGFcyY54&>m2l(Wm_aCptWCKiPJ>BoY*XmGP zN(VKI%CT(p0f za=t$SzqR+8Y&l-N0J-VpY*$~{SJ~@~+2L;4`XhKZ$ZrhXRN9n9?z{8sp17%45L9Un zEh}yg!1HDCemtK))J1SKe4B4D-@$s%pN;6lEm=H&jK*uIdB>iXr)VqZi4fKH zr*2w|jPZQa8Cb&~drE$F{!X;ql31zY_JJ$<%RBb&a)2Wt>Ix({U{;?j`9q0EmX3NP72C08m_$% z7R4#IeIq>yDG65jf$x+19p;Vw@`xD8I2Ksvu!`Tvy#~&G;X6};s*#kWd6|CAIJmQV zY*AhylW)kQSd>YIfyCV4w5!)HHaEEWt>GG%tK?RF^>ZHk=DlAAS*YWtX}l->?b^aB@G?#W6Ahq~b$8K9b# zg1GGS*6W0;tg?H#PILM(sG^%mK5tHbd76LD1P8P4sO1 z?KYelEbaXqCi*CL%lSbRWQM5Gcq)X42(ADL*;8zYGHSCKuL5Zflx{;!bu9A0UR%lp z90lC~KXIL?=u|6oM1x}ok0ne1c!K~f>{G9?$YMRup`D9WgsUTiG zlU)rB^4qd|#)7a(?7)w#0nsE39+sExmKpyZQT66lI}|UpdmCygLVdhGDO@C_x4oG- zdxbno0=wte^zbw4Fc_fhGxk8q{BdWSSR&pNwrgC=9vz!6a|T4|!Mp}>$Mc-gHFGM% zitowSXI42vsUx{)W-Kr4xtB&NR@IYM@k-EL)VuK~H996^>XI|rpsOO{th!0)#}f;8 z6lv@Y*Th+#n~gG0@oBbk*0#(W;JslnuK4DZNFe}{3wH!E<WVF5J_%H-3_G|*M^W0x>2Xv+7J+iXimBx{+{~T~ zoqf+OxHOB$?|eKJX~Fszl;A{fjK$h*QbF#5%I1x$d8!2pBG%P9oz)>8Vh~jIHgA(F zQe0EVG-TXVk=n&72!e{b;#5vQSftbW+3K-}B(jYX)-2p=Olaq6RD1~2oGoeTv2wF? zpZh`yF=V|cxNx*j4=GP6-lAvV6cbCiO}btH5vz>^e{OIiWxiq@NTg}pLIUujAnEA* zAUmNfj6+(3SzJsv22zS^^zZ1f z#d>BFB_o%W@n_y^4lW$ssvI+FEwZ`*3ti6SnL+!3bXJJhWnPB7g{EamI@57Zc$6vg zEtvkE;oQ>&%mx5G56}UMX4vGA$=5`bamV^;fukFGpICMb6ruffo!3_Ggae(tA&&48 z0HgMUIlrwTEGR#nQ_bPXM={GI>h^f8CbZDY6ekwv3q5Nsvfy0_0Mn%3)X|*3-PCyG z?G+gf)*)7J(Wp+M>0T8Dm|y^h^EE0+`1guw6T>4ZU?hPUodyjXRQ#PAbeRUc@A1ve zv0>l8L5QtH;3B?O>;l91z!|ZtiZeTzPMDI+y$k4*BO-F?|CCaV}9y3Id=PAOG)F@wCdWlySZ8aJ*HjfZt>np{$KyS#( zC&Ffll(M(JZk-gqG*jVoI99Aw2cI3?m*&3ycs#tOc>vMfBH7i(4Mt06nBTDyB_gFsmR)iU`nW%bPRAd!d#P%#KNW3wK-e{o>IQ*A)_98sry`=KM&v*# z$Z$QiGDYzoFvDC^s{@4C864>Y6yScS{vu4fweXHKq%`8E9B;TSR&RT=VUyzbNxPq) z<|YZfyWPGsI%Lw4Kr_%y`yxTWHgV%IRkSiS(CLjo9~FE_bKo)}x0_khlcl_M@VYKX zMgRH|qF6T+>zX7<16^04wrwE)1Z$*Pb(>@$0Bv zQSgn!I|KqBrNd1eOf}>OCxkXk7J%O#VL??fFfx6VfDEJU9bVr*6=&Ao;gUL(W|L;5^NH?Ka_oCGLX*f5B3~5XH`->T3!Nkt3qW)7A3W$p5Cgn>WZMRQ(!uQj=TT?M6a|atL8f z%VYJulq4S*l%c%}!$F0Liauc;Tp{11dZoe_#;Iya+JWcfdzEnPb9RJhGfq@~5EYB$ zdBcha*)dhsHzjMflRka$CVXqn(1PejbQWvRLOTt8lsS0-qp=5CX|9|54I?m#bpohc zvLR!IJ<<}JayKF8AKH{{WA%jx25h`5C8Wu~MzYrKVH?%um%h(J7 z6Kj*w>am#a3lh6d(At8}6Dq3nMTHNU&2JmY=9;aaGYfFrM=NfFV@*IKXhZz*svV~R z)g8V}Qp~}^n22>QcwnQ}`+I#zlFBFhtQRKM_K)oK5zU5Y+7~l^Uwg@f5RPq7E5c(4 z!Se7TBy&iwm3Q6CKk;S#-uUQQdYn}b17FJ-ZMz4UbzH#Z4}@wF{q_<9`I!m7?c5LQJ^L`oN_lq zhC^jTL+%!W#RV}0ucs6tSqed7WUF;vJ4~ z^@?}RM)!=FK3!xLcQYB(wbdJ#WNr&>yToLZ2?BuyL_#XkOZbHp`&jvf0trz}L@11@#9|RD}8iqWv|S z%=}-%?Eeb@`tOkcTQ>P0eMSETp#NDwz{JS%7l8iP1n$4l(*Mz*^j}N|8CW>}-gJ=V zZ?yFP4xlr#anQ2-0_5y}xDK)~`~v381PmPi2d;zv=$!gL0s8M2s{bzlIveY63q%G6 zdfH#@R~gt@{&Ne&|NUV8Y76mazWk5ouK$7TUF$CmFAE-lA<#)0J!; zZcP}^S(EZ8j!yiNzLQK;p51wz*exG_U21vG8>M4+vDtp$T!)mTq=+Q`gq6@L<4^amqTJcS%DucJu;It5%oz{pEQy zCbQ%oa~h$PqaIJeRNIfXD7gWq{xfS{o9^~)|JJ@Q>?~qfq;c9i zG)ywKQ1d*Oq#rPd`zu0O4HC^=B$9#a-$&KfTMsw^e2F1|4|Q%=lx6jJ=Xpn`mT)v{ zv+h~&Ex4t&U}f&YzrRQW>+7?#Es_JhX@T9LFca}aVqP)iQv2Ap#rjS}<&$Z(NvFY< z69QyLX@?;*V!#3_0x)CJt;tKq%q90tMq{p*&K%t|Ms@$B%2mlY(dS;}P^~hSVc7NT zkOMXYIl`E(S1nXXZ>rw5mRP+J%)?%VZWr4n$E&T`%t3`Y#MUhSIcC5)1@Tjn_Ey;% z`%=R?bOD5U!ehG}qgxUmM8 z&&i-cM9hF{&Oy^8w3u2#HhV#AKSKj%;7cz1*3knvfWa==;HWAH*X_mDkP z)~rdRO8o(PL)C#uZcgQO7@;8ucXL?3hq<2`v2~3~O<59z<`}mDJ3(=j-MI5%5sX79 z2>guCxXh5Q5jIG!2# zA!15XqViW-r(CcctM;<&nTO$;jO(nHHmEi-VhTg04{3R*n*cQXEBd$wYg#h|1j0j) zl=>aBRyw3B8fnz)rrYM)1vpcAQ`bzBBqd86AGUHI@>SAa?07V{< zw!4)aiMqfJo!Jqw$+a*iu|iid4@+?*RK9fz?Lj)BV%{O7rtAtKp+nk^J2=r9dBh_7 zj!FMu`S>1oZ9b`Z3$IIwV;yeor${++`@M)}hTjwTypdiA*gO_LiI&1Z^jKwVMJQe9 zv=+vP)xq9+mT>VWj35U7Lvpi_8+CXN6>XVnT&-?^ZbNb6DO$fMx!)!kp1N(y!0gtqKeO1Wd>S4@e65|BL*&f@XiOG;LFFpj4`PK7;v4fgO!^yZ22l<+=YZH) z1{}87!8EVxd)VCwH7SBE_OJAn-#s%@bEK|U;s#?Tf{^!}FuC=EKhygq0OkM<3NgjH z+=3Hn-VNB7S#ce4%dYTax{MGE)DzVGy-pu-bRE~sF$a6AvicRpsHFTD)wHiL#j91; zmQ=ntUa~CpMl_YTv)Ffh)6}Ixkkho*O-%YB?@^NNtcE5Y6zziBfqxap)lxN)`_M+e z*!8shfK4L`O9K`;nELh@gCaFxEyTB*9_FGh@%?&q=iH0tjCrBy;R~Rb-B{~}n4ygp z30B>eb+0No2iR6DWPKW5fwKDC-jWCNifoFOPrl4HlIJ-Gu)Zq&j_E`szm-AC$ z?a4y507LvazH&~pMm&O9L+kW>6rYmcEn_z6u>!E&@{)v9fM>VX& z$B|Y{|BZP2h7-)a)wN-m2(9CvYF~BRucGK}=VbvOc-SWqyP@~AO9&6u8AC%P)!RfJ zFT5NXG-Bswj2!QD?lpufbw`-B=FJqlq;I1dhx`WQkLrRB4yDVBFuj~MM?;L9%|bP- zMopgrG)VJWSy-Od`;h9LR3yasO_B6VGSivU@&nzxu!jZCj-moR=B?GLoe2_s525Wq za^dVA{vzwbSHmih9x3S@iMHXNU+S1A7`SKKC!M_P>hctC+}d>NN}7C13^)Z=HLRuyq35r1qP zYTXKk70AEa_}u7&nbn$%qz*puOSXNFu1p9`RJwsyS(VT#JbXi8Edg4}8T6aP&H78!$IBwC?@M9)5e6&$ZTYH$kdK3;_IW?uoq@}B% zZPNzVf}(^5cl|!AibR|VZZINv&@^!@tbei+3r_42-f6|UXE}-{jUi=%E=%sdefpiSRY>=1&Yy#K6tlr%n-~Hk3pn zzuL^b4);FUoprdDm@co={zl07QJ8`}P!281N{3TXZ`6sq&Dw`2&F^zmAWQ(Xp!QXP z$Nt50ot-HCD0)hh;T{&A1|j$!J63pn((@*3*z$^sulj(Zp)aINJx>@zfOuR`(%|J@v+{YzoNry;RF7h4Nu9O~3jmp+4@AD})EIoC2%ClQrbvkh9a%#Kq zt8${$-9vz&Y!2V~UYcR*{swii{0XSEp#FIKSA_cGz58EK*Pl64?*AK5*YA-38|wP~ zcK@#x%)j65f1wXXRt~m*rbSu)ny33WsEg$v1+nTHnt$qeSvc5f+5XPzo#jt__s8_g z8rYZ+&`H=ZF#LkJfBc8KoS~(Ok@K$u|HK}D7}yc~E&BL%SjolE*~9+#r3}n|A5pU~ zb~Yzq|MjD|iG`WDGXdl8{}8lrc9J)76tc6ix3e{|b^hZNAv-gai$oOpFPBucprLS(PzxvLg6n&3v*-&22AYR>v6CG;N-hLM?rmg$!fBs(K5 z3mXFgGd=wu#*iEgv>Yr9|B+sRmFY4d_iT`$L{`wsH^O3;%AL<46ab#-Nny6dePw&UzI&ID zp_A3~1-0qUM!9=^E_C%nm)HBID;Q`eH>H=w+X2R7!P502I!QW3_2p^S*Yn=><;Lmh zB{xapY7Zs{03Ukl3Tqo`GdcwRjv?e?w_)V<_;v-zi}EO1zOJQx+DWR4N5J{x(sb71o>UrEMc`Ac9n-1J`nl-{9r1isQvn#tB(EFR)8xml|DqMA7 zxV3@v)I8uMmc8h7Ilcs}=u7^zT@<*q`eT(rfY+1rR4l?5dVh0nQ8rhv$+UY6lqh8p zVc07Uyi_%Z&ZvpER!W!r@>!IFBp&@V7bZSqiimA~{#bhvgN1qKB3!F#~3_^A`O0 znF^|>tB7l+lmRHRXhp@B$#Oap9@7_ccDEjMLQSE!jp7@3b!2ph#)Et)KaGqR%MbaE zpex{GDwvz^%t4vSB^aT>p`E+CkZh;%wGh7f* z^}Pu{JFed+)rBtzgu{is7DKPh+t0n(l>T`*&Q{m*T&6QM@0Ht>mz2hUXw;6M7wtO3 zaTO>c_8^?BI_i!^1R%TxlWhqpYAQTY?n+m;a6scM#MjJwuWZSk3%*`!ZaU`70a~pN zVzh=E=!be60Wh^55s(^@+g{B0xqKN{Fty(KfPmKx!xXvjp-OmI2nNog7%4~=T-=2B zp~E#uf+tzQ5xpvR!qg%YCZB_pS;R(ID1L6n8i#T-uswK{<_PLq>Zyi{u!p%tykPfj zOJCyu;QCVXeomjpyfrQ?=7cNLDgC`H<)+r#?$vCcHvx;5DhFY#$%hcDMPkgyBGjk) zK5%NRK|OrpG75hX~%G{ev6WPaVY2jYa}o^WhOBw4ywOUfKWtKzVX?yiigdrUCI9@F2;R)R zK5Iib4Xrb1hM2Q@y*n~m zdM(=?!h^!sd^6Ancoq>VX_noh!}p7teg+_pL(KT}fMCqNtHLl2>nDI<;GM);P4Cp% zh9`hxAPgXC<_Ny??T8w}M;hXLZ#<)@+Ch z*8K zjWUoZeO3hrW+q!+v-7?b9Hl}q6poRC4Y|mm0ZgP05=_PYHgCBwQn(~$jLwUgU6V;pZha#F?4fV zbFI!8?^8HhsiO=b@RuLrd;dET+nhffcLa5@N5 zX?|iGp#y7>zZ7;!J~s;)!N#aUXeg>E6iAv^(B>#Quay;1G1i9)Ej?oNPvIUlRYe1H zlFAA?KP6eQXpba!s1?7z3j+(@7r%? z(SB7PA~9wvkVubw_O+IBr_c=h_Iv2G=_Fzi9`{slRF;mZ7BlpB+72-D16puf5dZ@U zMEJ@x0NeC0Z9_jo4cEsG+>(n86Rm>7lgS?Oxcu?V9THu1fD;$$;;LU?dCEbXYT3X1 z6pBNWuWLdnmf>U*m5xRIdW(ax5xjE!Ga=n_L4#8*)kkRor;MUI5z$f?;Sd94WEmN2 z|4OTHz}o9r#`JYkR~o^+CiOuUeNmLJWTzTF)wDm0nMZdS(To!}mY>xUvc)MVomSwb zoy`(msy8NIQPYduus4hpe^^YsaxU2R5= zC0wK1FEzRhWX(F{WA3$tuj{q!>6JDO!D)1^VBPn`fV6U!?7Q0*06|@JUXpg;CR`*| zZ`Cbw5IJGrfKJ9$@DL4omJ-CxMCJ$Vg1T|lH?fvC8SslO74XXrB^O#I)8krZuH-u$ z&Lk*q9JT&rbaG$^xhTA4`%!oLA0-ez0BZ0v22dQpcCwI>9!`uBySb3=2*p+?R|F6K zs6Qt~+>wzx6~s|PB?-Qu8v>=cJB=dv8pFq+E?nmcVMoJ(Y7TGlTkX5p>$967D>iExe#5cd;)E55;KTpaX*U?gV(4#*7=xa>aH1MoJJf%8KK5Q*5n0FLsx zG6fuzT6n_TAfhXxG6Bo!|9Z98u-O&Nq3v7RJ81WfPm3AXpSW`wNTo~lM)l{^Bxz#Af|PIr(vPp21!Juk}VWA!|swR)!Us|D)(a40@jwM}MHWxTJZ(6&|J+!emFivKA8XdSDl zX3|88B@nzPKXBu~=_z>FTJnQYi z7>7#*MZ26%*@Ha~KRHEnO$E^z{^mYjX$VT z{?g%e{E$t#bf?jw`Od1DI1}=spSb4LaPDbuxqSf}OHLNkh&bhLBq1(12C5k2MofCT z0z8_7I%4nRdsWuTV$(}XX4a(qXy+Is18o}wE)9rRjUV5cl&TWHY=s77yFREu-3gZAY-xM)d(88+5$g@X7b2Oz1#fQ82PjHotphwe`7^i`|1*vUA?VIlPvg6nVN|5_TRxLu@7)R*E$6z>g5T@%O6pWD*nlXHTOfqPQ z*VN^p@;Alhs46g{Mkb;xoX5uXpHNE0k715n#6P$5L;E_NUJO55@R&h>(qad-zf|y6 zr{Lla0UWwM+k^<1xyET~&_N29m2Ma8X&X&Zb*X4vE?`zr`{Eh|F{#aM$j|zq(ovXJ ztKkFf(@ekG2f5#43@L8%Rg=MyO;Q>-C%F0M8Q7^yU+f0(t1|=zki$M1wVth26cGeH z+HzTzxgL~g|Inptu1h^Pw1sS%g5i!ap<9Vif>XxQZmhe?rs=SE^`Brz!>CH}wzuC5 z$O@eoclbP{%cl2vuw7;1_;K6E7Q>@T8?eU34+!pCdU8v3}r_Pn}2(Pyn*8{=JppQ z_?sU6O-(rw{1N(pW4nKoNB_!p|E7+91PYV`X?Um)UQ74< zex)FSR+L|uy)M%!sN!(gS9PR-pQ2 zJ6X~8UU%RK%|g{ARWGG(gqH8HZZERW?wH|DrsuQi?RoEtN z0Z^C!{eGVgWN3x(lj`X{eg_BJ0TGg6+=u@4GKkag`FQ{Sb_{>BO1Ds*_j8HE=KRD3 z3&BwPPru90dhbu2mj`kDWL`3so}!YV&11@q*`boDF5gsIo+bpUuGz94sQZ>V7wZeL zAxhv&(C@>w`cad&>OWJiJwNaIZ=R>E}OsfgxK@^v;#Bt_q?K4RyQ z*}Zmv2pKa5P(T{@hzBLBRx=J?dlh+nYNTuAC|v+9!NygYZ=Y_$i)xmtaNU0$JmPOn zT&nIP)nJ?~bgNhoYZ<9I6Rm7^%v0NxmYB9m5zSkLVtLEyw5(9q`8a$vbk>ZJhDP!r zJ?4O+veGC(=1prPDN|%i6kfzaO>`X1t-ZAS)b^Er!mzqB0TcIyvyYyKiOSQ#*`h|C z#B9VcLmHQ!N4Rw_1Rbk$)7*l|$$N)j@GEnOnOO52upY?OC!rz==sk4T-6NV3MHwM+ zHAot+ZDkS8q>n=SL9f;MQMQvtstZ<-xQ;F{5`}L2d|m=4{;IN18SDl#V5x+NglU@a zb(p7sk(y|cOiofA3~aY;gcReP4GeH7Piu|e6};xk!*68h5T-Hh7lq-yQzlgb zi_E$k$f|fz1$%z!gE(Mxud%S}LPg$*gizOp=c1cYzfO``WaSuAa+i_bkuR03Rmz?a zf{K|7N+XH}^B#t{8bNl$z&bRpH{#FfZ@reH{F-jIjB!ywjgD(hV{nkuv8X=54yqp) z`k2#0rI;_2P)0Mp@dD4)rYZ!L;Ywh>(Fk>G*J==$oxS^23PFp3112)v?1tLQUH zj5w3Yq)95OR20ZKeCDg2+Dw%wz4m@hZPfl7xCT$rAk#>7htn-i63hlH8uo#3izL@Z z3CA{WM&n6JnZgsdFe*gJhPFnfkA?&$gA~0pVNhQp`%ISQU*aG%*rh9@rZ90Cy@iLK z$jZc)zLn*w$jEZg!y(JVfgZ|I^kssEP%7XEW-yX=u?y=7na|Ccm2-~b0A^T3!;;7E zx6I_5bGEUgRDu8PeaPx*cUCQzh+^TA*;5`yjI5 zjq`SN(uQp;fe27ep4x>ju(3RAgFM`3l_@bT^=00=a9{*~4iDoRHX@laya;T~00E~? z0C#9oz8NUcVFSWaotEwfy>7=%aNptzjREXSlSNn~q?mF?d%KS8OfYsJ-iHNQ-Tvu_ z>R^Syn380^Mkd*ut`Q)!eW(@slQ@>miALBk=%AtYIzoAd143tDfMbMcU-AN z0BHHS=1`VrV2=Qmv}gFHt#52g{YZ(FjmqO;P7V6jLBQ{2b=Pp(NLmAlUd?1f0SWh`&Zt!DZjk z9+?t&Mfb`E5cDmT#=7yF6A|~oPngz%EOc9REo#YfZ;TR8EaT|6q}`r~4gHw$ zH(W7ku!kZr9K;D5U%tGwB`)rIAbfUm2HVF`87K$WGj$L)EEv!%ka|ujcE+Lh^>&sN z+9Sfb;>YEje}{^|l^wlNUFNZ40P(ymq$2?-m301jUz8PVbrzgerz*z(fDk;^j#jTt z-ssktFj`fO0dDt$m-$1TiX~RZ;NT;X|RF$Ws9Ka=_T~7z)?nRw~Nwr(9J?H z(iAybtD8J4O2R5Dr$i^DZK#?5Y5R`Ck2%e=Nrq9keDN^4JF5_k(=&5M{46w?Rt1An zePm!cgSwaDcGE_*my+G9g?Txf++#x$&4g{|jl znBXsH6AWg9= zLmJZ}z#`+YIxV(8%DEqsR=|uYI09WdTqNz<+Pai#iw+hN@Qyd50=00=){FwD&R@t9 z!aJ#1f85{SU&G{lTe}U1HIHqqU&W+`W|0t!73_kU$!LCzby`;lc-$aLE9nAd5>6B^ zDWc13)*#j->AXiO!a^u7q1gD|`zYU1b&_pp*B>Zc8G04*Bf6r2S-P)#zp)=(-yn6hV;kZ(z&@<%`4;aJodVAF6CW@bgKD@Qn4$(y+ zdpyvGig)LWX%^%<`Uc3)81uFb}iA!AZ(0r_YEAM{NBcrwj zTVOOQ^(&7b=~AzCqsbS4{}xP}s$3v@`!d0(;1WdN^z2WTZV)%&H0!ic+mmf}b|eYclk&Y^^Zd>o>N6YsVs6 z{_F`2z@g{?RjL(_gd>e-;JMAO!?R2{qICdEO4xUdq+DN$VfAXqd>luEGF3O43FIy? z>i92Sfyow*R6Oy0YVmn5U*^E!D$qD*c86LhZ4?1U43?MNd?DhqefIg2v9)VhK3OmC zJ3<=JNZCi9yNOP}yVcyfwf$7I4SZfnIgLJ1<>5JaFqw4w@Y(1ecjK?jT%(w+)=Sz# z`{Briji~2JMz?YD(FZ@1REe5_#~A7ax|(F~)tHEbd^k;4-6rGYc#;O3yB#NOz(07c zkduzN-vY3PfA2K{LG+{^GZ;=6j%ZQ&;Tb9=#~iV-pMsFN$BGTd5{YwmP|HhtZhsgS zC~xjn;h2{tZF)Xag&Z?>=cFjEhF=Z*Zf*K$SW`i(Kld$Y zIseRnU|(N(Q-rHUjcVpm;rK2~D7&%4(&lQ(8`7U&lqj@lkC3HB)}%s(B1?*7-=(q(iR_UGxgXb=bB!~ockj>l z^SkfI_xDGSY39rvujToAzLs;H>kPhiC#tnCH2Afm0_WebL&j2ixzm-!X(C06(xXRs zL}FiDtgK+L7j?!HB$u22ap}8vz%p<;kbd0|_Jd(Jo zdj3>q!QhuYddh*1uiSn3+<8$nqvwGK#QVqBs7_@1*^XN&+wdQePBralGTYVEQT452 zuf`x}-F3!Wd}~8Z#S_<5t}wEtPbm_Xe6rqu$-cm?X=bXyZkL7De2I9!FO0=r|5McS z`{uIExe8Kd!b^tJ-=_Lc@X63?KfIl3Ap0RAb#2d%hY>QkTNg4nY$|bMOpsa@J6_~= z!{^g`Q-{%4F*?k5b;HZ6>^$!Xs|^enklwZWrTgMHt- zmubY*@YP(aOSa0tKX!K<#~kVU!OdyP!IALLu8Bt@Nv`4N>%cg!q!uRg0Pgy)TAaHN z8#EOqT(3=c+VGlBImc);`N7npkoRkU&M~f%gbTZjm?+~C?05>9wfz5PJcXz_V?2e- zWN61z$V3JiPZ3Ddi!mj!E3&A=8?Z9!Z-zH|rS|psrCHsZM;BD@m^2jAV&9Qu`Px2v zX^+YJ{){ADRY z=_n~6DYV;G?c)z_t*0V6^Xn28mq$q(y>NW1v%YxPVbtu`YVRieWg{?-oefjCz@`M2TP8q${6O8 zW2%L77fb3XKJ$D2_R*m>j>aE?+%@0sKUdq^MP!K`k9(wgr~c&XtXsYKVprLCE&dNW zs|I>YTBX^p?B@CL;pNn(pvQ#ZBDF(x0h?9TJpy(Zkv4Mr1y5{ODu2Ot-7exq&AYan zBJJA*0%CUcrsqlde;+uO<-U)Yfvqy{~+SD^rFR|Vwlz{v*nIznLVgbm~Uke8C$UV=%s`l z-p}k(N8?(mH{%AghH88VUK-reTg0vF{)~U3)mlgOW*viFvsuxZ8?SdP$0^fKw*1Uu z=(qj)`CN#}fT7?QnN3o;_$&Cyl4tUjPHhi0_HC*!47u;LXLGQ{-56o%_uYr~@%rrF zWnt*k{n5C=Q=C2V+7itZeO+7PFK@mp!x3{Nu_V=`ocWG(^x*s0BXl|2xngh{v% zlZQSJBpHUeyF1afcerm@yuvTjB|AKfz4*U)jy(MkbR^nlge6>sNF-0+m?}BFuoow)r@a#=U}t7y z>*BE0`KX!G5$A1AR+fj%TtqA!>^3ur>QKIddEB|=95d%XEwcoRJf#Q{I7u-v5h(&0 zN5q3y37n)jK}1aKFCS5j$UN74SPD`xn1Dlykpe^Gzo8i2QhRp7(yT9=Cl)MA84~5Y zXJ5O$RiCip;-gIwM@{|fmOQzB*YfzmDq-E16~@~gZS#Lk)ZRL&bo$$?3gMGUWR6iM zi66$Aem6=B&slRmxN|dlH>3LHZB0(6*W2pN_x#!z^g4M%eV##?d`t3})pEI;cZ>$d zm;`=!a-LduV%hh?{ZH^D23fsR#k(gY*PhzAxS{=*`iMb}#v4Ovqm%V@H=Um92CQqm zdG1-0&f4BL%j4s(?lzCO-}|m@7YEaFCdrAR23z0G8J84uuJuYo6zB49XHn{)vC$i7ru6+ z9Zg|gwDb0ok*%6LNGC*MPOmQ}Zjd>3PI~=={VnS>-b*_bUiQPcmkd-WsJQ8P(yci2 zxmsDFHArUt`ekeD6^-}4Kk%MEN~e~{+p#gDV)A$?gL-rGkBqNu9Gqzfqc?Pa&3&!? zk|96%`2gFi1s*L1T!pRMzB)%dz5gSr`pN{qn_$%=4m#6^m-$(b*&DiL+CJCkdC;v+ zm*dpYxEE(0++SYoZ(9DS)>T;Oz%dt_&b)@tNdd-6F>Ozjf{tCYtf;;zn;i3CXnlB^ zxK!Zf+e+W-9Gj0t-W{xn6&CJY_x41NQ!w|Hmg3hXZK{{FcV(&FC{5~gIlwU z6G_N5s(-aLJEF&&oHOles)B!FK%zKa1TQu%4N-z1LXeR7Z%KotbJR9-nR|}A3?ztB zB4iR__BBAMf64JwdrOETTj7h7NFq{1DV!ux{O`BIM--XM-eeeen5&%sY;OV%N<*)CH~&r zh#qsA8(xh67v>hji&Lcm<`x$d|8GfyWfPd-$;g_3zqkNgS8QLezdUd7W!PEKiN}F`0Y*KoBa4OJO7f&u^bWNsBur*2GPgiwAtZ-dKOJv3tDrYSFiW@vi&>(Fczm zkc zr@#Buu$=kM+$|K(`@r)Tv+4Je59i0y#Y_x3x{FRV-h9G2bj%{lzT!jV6D5<2S@S*U ze$o#MSEO!hUf{80IH4j{v6;z(bJ(sTRiT;LLwdNkB2}q*z6ZlFcZsC;*adv^@(#|T zQ%biS1csJbWto*oUK_ihU~(~w*<+}GdtCW@`41OVvhqI^^ws41=$6>0@86!39R6j5 zKVhw@)CMnqXz$Lcou9~Z$?1SNm zs&i^A0^AE?lpEIupc!D#fDNty8=O0%79$k&ST|j}OC^Rg$X+*Hr%NM7 zI*3QtU8_qWh9Qu2rfQ>B-9oiHiZ(g|c1$tJT@mvIUQX>=xlEB%#t7xa3*j{d)@RsT`DosL4A}{GJsQVv*8fvT@Yg&@k}W2`1z{GT6HVcG8Aki z1$tFt?y5-#9T()*-TJ^qt1F`FJjLoUh}9b(xI|N|{t&S`3$Xg>Dn6~P3)L=e>sl_r z%@m^)=^_xwe6Gq&YwI<&>XViV{r;unwR^@_N1n0oDXXuww`e-^-Y9#lc1g9c%V@*c ztJpTd{<-Q&*qs?MQ7Rm5CP}2W0I!t#l9KzhnJ5_oyiyi9P1l`L(`@~}xQj*dxid}@ zG0BX&6UhLybtl6Apzb6PNJL;+@PA1%wl1Tl3UukyKkm`1{ZfODu(WBC-E;o6yW#5V z_%5iO&ednV9Qk!&)YAPi8kus1{ITj9>>t&{KKk~ShjWK-^Q(SYl*7r_PnUJ==%fC# z`ZrQ}eAWro#Jt;9=D3*d3ZIo@?ytgD)iOJF;*p&$iG`l|)=~@F=z2yrcdR6T_E-=; zKRhDLwEpOp`L(x4g>OwrbN*V-*mrnJYchOS?9ot9l1^N6XC^6Pf#(t=FqFAUc?gW zYj|yapZ!fAwcw0Ki&NeiAD@$>O;RF*{SR(;*W$1qZWKH8=w#A)(TOd!Tyvn53{m>O z`sVWKF$sc_8E}Fnv=~VOqKQCLc>JNxBO{SYv$pPcbsm8Rq5tljL@9y@d5+pq3_nM8 zJXifchnz$_Va|FKRCBYQul<+j6i2ogo4vWX)Le4@sfs5{A}t(=L=*wCixG$-Vk8M1 zNs=f+_{%$&#n4Ihtb2u}@c**lhQdgQQG_9qL?p!|a3rGG-wT5j`EwN9Qgd1RZ!AL~ zQ-qPCZ1M)0=fAZK2@lHZIfcR2+kerDNJvVENJvQFhy)_iix9;mMa1wDIHDNwuX_;! z`gFQE{PZsyf3z_IGe)E_l9UvYk^;hs{WpY}W$?=#C+EG?MvKc229XA{0yWDz*m)Okgt~EL( z(sVE`-;Mc=g9%G>X9mwf`LZVFRe3wBm!IZ*X~6eFp`P{rr|zc{63e{upSR8*Wpucj zHu~$sK=-Hcb89{2PW`;*?8(dic>G61-*U}+ay)X2d4{}4gGb|pYUCupDr|gb?m(Py zlal52Oef18BFcC@bU(##{F%z9@JglCdY7)duMK;}9NyH{ws-T*!D3d?iw2=<`{f?L zPGmbUFzj~X*XN@iO)G{N2yZUtTC9*I?-}8c*NkSCb4p(wR*@e+(tD!K&it7#-?Ejd z{G385R~1!;@2Sdme|GLj%sTjKX!7whqp1-HCH72X+rFee+{&<_=}ChxD(x9&EbDaj;|QDdyVM_ctpG+dGv--pMi(v$kwU`&eHI2QeM^D`W+jr?380hBp%T(-MHiM($^(xcXPU}Tl@9kp|d61 zbe|XRI$R>T&pNM~tDt`{?EQ+NEurbHjqPN|>tdvuFN)ReV>=zKZ+o#mQ}ooZ7`1Ip zF73B@8SPP~nC73#St%0`#m}qJ;~M>4we@7w*q3yXu5AV3qq0?7bv}q>8DAc`++;I# zuX)L!Ym7(K79G;Prwx_{!4~$_#~yL<3m-7oTW7MVp)e> zQD;2El{f9;zEawOZ3XgCFQbLeIDXvKEuiYetX3rBpQ{>tCqbqwB! zdmSm^XUF6f!gKS}nTZ;hs_r+rb8*%lXfxef`IC^j_P)mM^V z3teqYZaAcD7<+U1xcRW&fbrlmg_=Vh_i`WfaI*EZZ;`fRvkVP$Df+al=4Om~vyy7n zUAdNHvagw{Bg71Bk6h>ol`p)uREEQ@VE2n_#*a5&FgN(7_%6@t4b=?OW}=6T)MfvMpL?vM@LZ4!T)Kt?7Teq;mJv!KuO3&xJ_7E9)g)m^pJCE>eP z$Ce12-g#v%L)%IYUs-Cnls!loAAE2=pHRH1!@g7lwFPQyHfK|e<*pEFTe#!{m9#~R z$rq*h^clWCj8WHlqWNnh_W|7cvR!dKyoX05*&fP%JMwVCY1b9)vaMBtMdURB< zRc*UV(Z0uqUk+wTF}CRHYTqo0*RAG=U2Ru%;*9Hkm(D|B1+9ZkT@pTeLOS>yMULJx zkD3CW)rYo8WovKO4(;P0-t+b!ttypPH;=-{uX>fncmIXYGK2H`e}pI(E*%SXG~(Q+ zyg)SYY3e=P=nZ_2l3)tG{yWP>>XC2KqvwUFY6x+x3QFawckvC7;C;s(vh6Wf6&}BY zXj@nDK1HqgS@9VjgFOauZVv+UJ-}RB( zczjvKrj42j4J37fcIxGq8+IPZmF8V~;C#r2rN>OfhPNvxKJhVr+W2{Ck?Da)s|yk` zHr>;BQJt8sekV<`y!7O)(6i2t#~WH~*XPVz9Z|%j_&wz~PeXL(BE65bzInHo$EOJC zIzD=!Sgy`K?_I&2y_dr`k35o2l1mrhG^~Hp$H^#pjZZPT#Un(cwI#dfh`;{+$BhlK z&#l{}Cv_9$C53!^3?}_Lac=S5v7!T|VN=KUlyK)hZQZ->()}?3g1+sGU%iTVo)_{S zD*f)u$kfguKmYkQ+dZ6y?nawH_UD~r0{UO zYJ`@I+Gw=~UMbD56k5DUA=LqP?FCZff?n`{b+3Xp!xU4{Hp5a#4MNksP%03l8I~eY zn_($D>}fDl+&M~kv^xgdV8NmCZ-&%T_&F{L%yCAr!4Gov6|=RLq=eX1}6As>u z2Cl;+_oInwSeq;!~|j;8I|oSDtJ5*kH?b;c)X+- z9xo|@$1C9RcnLBdFSecXe{dWeBdOr=BuVuD1U#OkjQ%6z@ucmPV`AX9N|f`#&m@WH zdr3T=M8xAI#pUMm0;&_@aH>v}4Z@kg)ea|T;3Udu5GT6J47`P#l#41k9J6=935$^t z^$B7W*JAxg6Tn#YCB*S~k`!tJpsEBarWi$iaRSB^;28KW5l>N7obvkLH4%+@pi?Oz zr99DW+8$znL%@5AJt&uznW*+4kWhP2&VsQA@Tlu!dC!?nR=6e%~Vh*ptd0W z(d{%kK_^mlLY+nRu^8Ymj82rqN7YH3q7vFRV^yNzKCFwODl=aZ)c`sHdQrENNO(LI z(cqW_#l<8L0pLA^3j7{o2CRBipP=d?3vy7QXWZB}dDKwgH&n_1vVgw@CfFqy}L&Q3pCV~9X*+6GVW&dTnLA{{8s1yf$g|QL%9`YSv8$g?Y z2BB|g=#UB?)F#v5K^`wbL+ME1{24n~%>0JCfPWELF#d(UrGg*CHt-=x5zyb@|75H` zsd0_U4!H^SCuA~|%EgcpWSY7l@uO5u33KYYK58OHe)d;N!)QnH8Bh)g3B?{S^?A%C>x;J3yW%+Dq~JmqaKB?h;k%~ zGKjFyn?TSRQI9CAfqz!ryWi<&_kG8k$GSeU?S6Ey?H%a|}me)s1PK%o!K0AFE6g76e5tbn(H zX@FV)mH^Ix0>J0sGnmj|5r!T|KA+R`RM(;^L!Cg^L-9IRk$*0!W-5ZoI1+!X1W+FO zPhpMWHv}htuQ-L%sJ>OeQ95y&*hG->BVGl;fGN#@aj4}N zh-(t%Tr?>g#JVDi2$-7DOaz1GcXAn zNVEuYvE}3(#DE+Jw)-2|sX>j(4yjH7hwLX!>vnMP@7xaf2(2nX7YK3#)h)nP%Kt-r z&mFvwuTTs_KcK2XnpVIOknO2ybpuELPB%a%7~K$k(C&d6X8@*SJPg&T<*V8TbcU;{WPY z1gk8y<)=8AnyM*Irj9&dj)KJ)IuU^>j5bxH8;4_~^!H^NY6Y5{gkdVI3lSGXx1%W; zN!Or^0&WG-i?|-EA$5v@ssv?*DnXQ^D!~+msw6>4yOfQPXjJ-rK{Z1qtZM%=;z0>{ zj>;2>U_j_-W}-$58rg^$(e?uTo~Ve&6P0Pq1YL`UHzZ*N9D#BpA&v6CFTG|ek3qQv z5C#oh#Fwyw1b%}I3xuR;+^K@0Gz9&Hx)WASK+ahu1#)z58k#BRjO-vGhR!8{Q6YtZ z3<=(2s0g7PkQsn3Xqit_DPx8h$iNS+p{VBp@4@d8y-^wmHo`cLnqeXJqrU-J3H~i4 zB>>rg9ieBA0q$|i|;(*DdP#uBK zF}6X5n<(RffI)%=upZPIGdKeJOVYHEGcbY$1#(9Vts;N{{tOBXXlIfUR#2*dsL`Q9 zhy#F=;5ZKj2LKE5IhwC%CmK|uLY)Hx5+y1Ln14~Cf^SixB2b75y|)9yy~r2;N?jVF zf|y5JPsCpkr?C75F@wefR2_K_unRu_4H?ZQA1Wy;fGaM@&;qN$ZwsY=%(0lLp6N&= zr(zm-AT`heXz+h6-%@=JoeZlg)X5M7sFTrgGP05!6D&LzaiE4%rmE$6y3&6q?_IbHgeHH7*hzQ1Myko6`ss5}@J% zwF$(70*OnC z0ip5fOMo<&0Rio!6oNPg2n3J>UQu-Z+aN^<02m)At_WVShNoVjr6@`5Lj(pE(njv8b@HB|wchJ%bTLuliwS|7~qS z1uTX$kr+k2iFg=#cTP%~DHp8RP`O~LSHR6Kc`#cq&n&iK9AW5yh6#ZvXy{`LG+;*L z9}pR^D4G%x^Um`BOwqA6q|iRrhQH0l|Hx?|;NkEG(mRM8ln7{e45S29c%&Nuc^1VB z$iK)n3z*OTjx-<#qWKKMh~gh)t873LXlaH#oDjUHa0oijqf$OfiRkbWYn|U`WmJ0_ z?f~vXxdTa5)J%+)Q)qR89Q%VsXp(J*qkm@vEDQeE z{EQj~A|GW^BvQa>ChMk`nZN3i<=hD1M~fg5NDlvyE8P#8g+0J~5QVeCSEP~+^} zITIXMh6PT+I2NHMNLiQ}3BW(X05CJ4jDhGp^ZFGiBxl-tZil0KVjMnuB?Rr$CTa36 zR1D*2DmMev!(IqB)fhz)A?KjLzYTcg_b7EDMnEcDwCF&ol4=N8;)Cx)z+gwrC}Pf??0so)EAHrs09=P(m&ZB z8XVOD#=HVf49)#m9l+5)>wwZbvWyJi6Ac;!t8)Z9keiAh43#5;A!=>&C;2f(N1=rk z__u`{RX6~0z^7;q0>S{{#X&WSIs=(1p?r)82H6Ds7RwYf07uIRGq{)<2Nc7j3lpiW z2zr4Paxt>MB4(U{axr!HQ0nlB_K7nzl?$p7mWyGdj%W|e4Jib^qBZ#}DgmJa%1Pkj zSs4iBW^f!XFo78!4qks}L6lyokeI>Wv{zH8`3p56Y_iLsnR-G8p?bn$i2{x|J9MeL;QroU7{2^#J^uk<2=HffCM=Xte?bSKdSE6e zvoG6Vc1E2!=7Ij2$(bN;dGi~VeX^MM9}SmsN)_2 zWoAr7VT(yC)U9A=V-pn}OS06fFldfOeDnvk{+&;#i38OUViT?DDLdy;^9Z`{BvnT= zkD%LWU{(BmxiUjVtg8QMKA|zkj9bE>xv0?m&GLd-ISPaf8cGO_&+HXoxrf&N$lsYs z@7NBDrVOEC2jzh2x`{Y@Ee*{s!8D;T%b3_4gq9Xa$pPZ>FYA1SD`4FP6i~v(Fja7r z%V7P4>H#B00Vj^!Q%Q5Jgm$}Pn&M(6D6lyQ$UVn}KG0zOQ=vfv4B$|-=>j?;aRT`f z&9?}T0jC3}!rVRUQqoKtKVp}c7`XXY9FJTarG5q+_3xYoyK0L3)P#o0509ex4c%B6_DR&Y=*)_;WQsWZ>KpCG z%5zc~swqu=gDvR{Dw+Y%o_a6)E|Nn)gR_ipg)CEvHtky zN(vqFA@?o;B*5+%T^f$a3KJfB`v*0qfL(y>ut@{2m_ieKJ{XHs-GP0P0s++>yn^2Y zAJD8Eo~i$|!zIvb+*pNwJ0<$Z!XJ!WVc`!$41@s;2`C^~S1^kN(a=Ld1Dy{qE+9&Q zQ2OihVKc~##)4`O1OU@(gCHrv#ELW)WMmr_%p%yjl-G_{BZ7AK}~~YqyPHd z$C%hb5-kQFa2gH<0?>p=oWP11njgLg?gKH2z6Zad}N}K_qGR(k$AY z-T$N^He{){4?_W@@G$(CDZh($^F@IADiniY-!h%grbI|A^| zO260;oM{{ARMa-p^%80JQZw3pegBA0Y~6_Z3y}};6~zYBfP;_im;MKL|Vohh(ZP!L8|(^f%2#l%szxRZtG1 z8W58gW*P=5+kx@m01~Y!|1TIV$wAp%QU4<#6W-UFWv=(y;`j5>NxWx`X-B5w=BWwmT22cnH2o!)7Jz#XeARv>| z?87so`Ju{BiCi+elO$R}krs<`z^>k;3 zMgmOI3OLfNReu!8|5+d``cb+-G6S?H5Da7rY6XD_&1r!Ulup|Y2t*MMYoXtkJJh)< zNKZ3vu)*GBgOoip(mx{LjB*Z}GGXTpkc`Z#fs!*yK4fhTI0sq=P``&LjZt{!O*d35 zQ5-U3qZl%JHx0xR%2re?5zumc)-FMmAI|B!zlsygo_xst+dvKAPsn1J$`=XnS=G{u`5E3NV;S5u{=|ni+9QQ#p~54Oc0{0Me{ofhb4k^fiqFm^ekI^uYE2(jc3G z82wGEM|}Hllm#40>o=$j8spGUC8jx=kd7s}Cp)*Y=zkR@gWJVHf86+9lX z0TC^;l+ddZz%H-?{*QD+?FsZmyCd*_NQp=%hS-)SZfE!( zia-KgK8XQ8^20f8fdn?HD-Br#nSpaaK!bk>AW?llF$3FUY`qQIe{7DLW>%DFp}bn{1EfK!{Eg4`rnMztH*f2>4y(o_L<)5nzXoMNB zNTC0}HpZMpGp8X?{6M@=>_Xi{RslysuiIkmf*k#OkYGvVZ|nlTgDH*wzW~QHdHu;I z5FDsYW`r1Z<770%;1v^?zbThQ(Ca~1>-~PHg3WgjRjBo7LJdG2+a#c^CsNPOu-@+) z3lK6$j|S>mv^_?C3(gD90ZIlKuIOrje>0Aoxg>h75S{h{C9K6sSZ`o3NO^DpcD)4o z&pUWitp}}$O$7h1Fi1^6SS_i9M2SPH(kSL&O{IW?4+qC0>CdAfs5^YcjOzYh*#Hy? z$Yc#p4Q6#lGwlI`4j5q8Yz&!;%t=H@FAn|~raXk<0WR#owg~p_aFGB4aZn8d_yeF| zDrKZSMvoy1z>Wc1_0O2(Oiw2iaPaxpSPz0)f}#L;lq%&37b*_+F3MKU7EU%tT^yXi z=in0!GdnAs=ynAK1qBtMT{h-cPG&AP4)(hp>>Y#^9c(S(_Y@T!PT-7$#Yi||aXcPJ zB1qt*#Knw}!?tGD&Ny)*_`j0b(H&Mc)`whhB%&1fK*8C<%H9Qh7rX<1AG`(U0PlCY znAzG`DA-%uTH%lnbX=_L^eO+{ZR6~0V{dI>W9f1TN2GioNUUOGYbAyw!|j-HqDniJ zb*x-)WOOHMIXNcyWD?4krVT-Plqvy7AWKOh(xJ~*CE(#IRIohV*2T&RC#qs==3=F6 zW#M3H1y1Sg;$&rJ$8;hz;gp*x+lS{rWL*zFGg`a%j$LiAWo@usZLpo2LX*S^f63S1 z=nvpivNs-l&Zw@0JHKJWat5ZIY_}zBB0cPqCD{FIHf;7IiQ3iO+aPLupkAUvVt3UC z?aq^hNA8%8NxN=H^qBlL?%j8&qpZZZ?5FgX14^ftM{VTyULPHoV(0k&r3%kRZw-sR zY3@JoFRRzgVOjjiOXHIE3!BN2n!UGvrYxqLcxF;G&)JT4iQO zyjzAgoOF5I@N61&uB*-MpXhdG8S>JXIaB^^@_vyxdP7{9{KAZ8qdWr7fTzCnAKjeT2SAa-`qRcy(V*{t>3UG zv~iR4(@aiYh9i>vO-&kG=nOxu<}%cOJKn(ImAXcKbFj~#r$F%XFlR&GPh+Bq6MVmZ z(QlEoSmXP{4NuxMved@sm9u8%HMY}n_sdg?GQ=} zT3o>DKU#p}+fT4oS`(eax#32`MhUhhd)M(k86T+0-IcYiV8Y~MO^t<1?L>3oRKDge zU))Nk!sddL+X^#Y--s>X53DvQAbevcpX{w}na?mU&Aa^6HaWij0N$x?{X|*r_JUZ4 z8$SwE+lfw{CUPA7%{g*jnj_gf-(+OwowF3bS?Dm>wJBR8OXK)@pX=Y`7jm4M=f$5N zL9fMiDBrZ z7t?GyeYnT#QqMY*%aTuTH5`94;8bYb&MM~UA^S~Dm7{!$#Vst9PoD1;pR3!jyuT=Na* zcGdRc2E(`Er)7@baNZHVto@FqY+AUCYS@M;#+MN|6MmL$Y!c-h0jjN6%KTZ*J1llx z&P`T(@3%2~vF7r1M3&(n-$z_r&r64FIq3!Xb!}f=54Fwi;cOO3Th;GRvK_NBu zQ*XDQcMEF>wRH_H_BSV8q4x;TkJjJ3azXhX-1*YJiU;BW(rZ6CHzp)(@2Qi$u+rj# z?lqNA!O z`HFU)qbec=U#@<3mNUrOk+URZN%K)s>@E^{J^rh$uXoDsGKuRXvy+>i-BxjJ^S=MU zFSO#&pzc*`f0-W=+UY#)Y_~t`_c*&kZ$&pL=d;9hAJrV=$oZ#h7+C@>b=o#M-e&p+=2LS!c!AJGbmrm~I@E&mu}swZ0tLacF9rGS^-2ucMYq zjohp{AGEx@JG?`0SQwsbj;MeBx=)OGLm1=KD|@yL3j^qEzB(mdZk87E4?4kG+gQV! zaXcVsB=&Oq5VLZpK!)>1$NZ}Nz8;N+v~NEjaHiE(R?D+}a<0p3EZxy|GJjo$L6l5_ zRs7Mbtdmo9#(lReqs3b|{lbs6KB&w4AhljmBw$f<`pBX{_K~7%0w$ePk|WO9zTE9= zZ`_?PNqSRfb6oOz-mChJI#1_Y?=ibq!)f8+;H7*xhs|b7S#$>*zuYMcTlT%r?(aNk zlKUmh_h#cVgVDkZHJSHgO+5L3?aOUgt?-o9OQ`jTy}7LP9cz_4=1Qh^X&FB?S4>Te zv3=GU7x&cGpuhd`&3l!=xQ32fzXoeq^B;I{5$&EQH}_rHL08Z+-*qZ?9-G8HtzT|E zW&A%@NBX>+nYltvV6*Ch*D%RhIf8;!WMvTS+S z3(muXtM_y~czS8a(X`;phm{hNdF@WL+Hk3CXs(s1WcTtlHu>=2b?(DNV&(0##^%yK z3CBO278=#y(nEJd)qo$pq2vayDkt0>0G(WJ2-Z?2+vVElQm&$EIL1|midFB*ei^oH(9lXgF7 z*w%OAT<1flx^>={pFVqiDCBu~SF*Ik1+{Byg}aAJ78EM@f$XnA0&7gqN97n<=N|kKyLr2^8rzo^hsb^TF%_BXPdI*E*E>;MVDg~9 zJX^k+BU}AzL`!Yf)T42o=A8nkCt{CqmxbVXtxZo)aI|Rh#***LU#J}u*Z!J+*jV5j zYtPStmW!%#?Pb4M@5ygXR^pI9y|>`T0bS6&J-E$K!-9PE^SWTSErRP5(k%-Iyw~L) z=5BtoLXPC#Gm)sCf5K*!Soo^lkvE2{aY{*@OC$T`E~kcbd3>9=5fauOE^soFq{($TG*}_(*M{62QWQXJjM?o#O+&@=4*6nM+mfz3|s!r!T$6M}C*aq0+ZaKW68B zQTDAVc4f}CjiFyZp0#q8svY$3&eqqy^yJ>@?_G-dkE>6(EiY!>!c|uP&E@b`r{*m| z-b~!pkz)Dm!9D`_Z2YQ1zG`;q{7jQuq*h+!Z=1h5c+ZygpLFwwuU-;%J=Z}_Ul-Wh z8M^33AXBl@L*K}3v3yg3QZqsIKDN`{ZN)FL_G;}E$*4AKiC|Ez@re-%?J`_ZRmRrC2XReqM@7cF<0_#1Pl`8P&AFW!J(T7J?IE6<#pB$4HjuN<8!QUvle%8a($JbKM->! zgP9ArYz?=6QrNG8LwVa&Ex9x|98coZ%)Q2@Uxk0_R@@LNi+c98nQlYD!bYj~i}bTaQd(tY-Z-BMAab8%EXReH-Hy(rz0kN*_q$AIWOq$difp4;124nOb)K^WwvV`vq@0Sw+(>;^lG+ z)L*-AC-JFe#-5s2%&++F;Fc4Qv)@Z-vPLzkUb1H|c2f+%e^hr5SuT5^d(h(?b1|p) zC4NIg5ertn!tTUVyDr%*3D#UpX!9tR3N~O&U5>RfCP!@WBqO z0kvwE&W(jQDejNY+_mHV0>y^i-j>mK3i1X&n;MZn9u&!H%N{&&l*>)(N# zPg{(bn{5B6QJL(`ZgH1oe9+98F)XA-M$MXWP;-U0Z_I-F2d^FVTR#dVPA(d4TEJy7 zFMsvxpI;aA5ic70((j({d(L->#|~xw&2sZ|4aT1Zh-PUWSLDky8kbNV3=C~CeE#}T zxW3@2kR##r`u&pW*T^E#ahJD7*A8g8Xm^hHWNgtq8=t+S$IPBr_H^&sFeUnzi$!m= zEE*V7Q;*28I>6R&aJlP}VQjR&^XZRoaS ziWkp*!IO7mo9$-dgb{)Lky}VTmd_s(g+8<-#jd;{tRE>8ztXY5s)uu7_z%UsYnUgB z9*C2#z6!ITOUd2T;&>)mo>;N31#AQ&g6+HC-Z#xXb*Mxek&3)HP!(u~#C2 zV-tyKOFrO*==Oh87K&RaoBv5U=&`wPQ|5OD@v96xQZL! zRk6jLm&VyLOb!EK=_1ZUXH2+GwSRHdXW^1fHK=*^{E5UzQ=zc^t6DTH7v?K1F(AEY zXP@u3tXE~;m(RGB#6Tb-Z@5%_dJj-|u5TqG#;kZkpEqUckTUh<}sGTSvW!3-$qO&*U=7yW6~%E)R@| zv@i?*HR9XlhwcEsdT^8Cm6b&FRfmEpcSx9{D1O-$#}7WcBdLEVnsut}7dJUT^Ix7Q1fmXX|k>6gAi>Zdz8@?$|&?HaBJ?{|D&Y4!MSg+LX@ zaUU;t*UEs?agXmOrEaY5=}kLU*m>8O{Mw+#C3x>}-|clC#qVRXK9ngt6eg6W3h-zj zVxMSN-fOK#ucuRy&PjJw`iivv&o#WS2vhQz`kmY5L_!YtXtYOYuaW2#<0d$6yrCY+ zNWR}??|#W?RJ8NsXQ|eft=#KUaWHN zK0)t#zS;Xid8=4njLv;!g30`Z>#`qs&(ud}EHo%qv~k79+6`(?Ro(Si*>%|d%jO+d zJx?6&ds4g1^P*hW_VXITmVrd!zEW$8=Br|>RisEoLq67vRk4TH|-s2OoE>`y?UP8}{y^j*Zt>;fE4_Ob@TT+pweVeuj~&VgByU zZPsF&LqoH~IFkm2qOuDH7cOlfo>u6Wh`FV$?uf^5>y_u739I#Dzf z&c(h`W?s1sk!7NM3Gc8#zzKy4!Tyt0uM~@iG7pf4Rxcv2Yp{1ldXHk&f>E98`d7vTANS2vA-Nev+iC!{`oY1 z#{$dLz(n`?@gnC_GS6fZ-5Rue4-4B>D)wnP|jdFFgxR>6Tw($e;3+VA?9K>vInK9ZggbD6uctfgRJ_^g1m^}#X6Q*R6! zol`b#Vl)4>^n8lprCP7J-IqA^b;XVDzvex3+wI6yc=XiXd23R}U2A+LtQhiB^v3M> z)i$?ujaT)Ijun$De$03fjA3OF_k^v@2iTWBpZ9*ZZtuEZq>qu3q<@z2w}+ z8^+`Zrs5ygeO|e7QHaFZql*~(t$#^Jo=vKi$lI;t(W9%`m9#8BRdnI?T24WsBckf_ zH9O00bUZSi8Wb>a9J8jA-nze!--N66o5)m0rAedSxk;~O-xJu!KLqgD%=g#brW^gp zrp9gM6YYnQI`huq`FmD~FbQN#v;_W)az9W?uHirYs6%gkk)?+8*;Wp^)kzgW1f4vI zLu~s_=7Qt!>mzma-`Z_1MA&M+eo2gO@~V=x zPn}Kkj~=YJr5m7pBS5>9aJ$p;_B8?W(4}=`J|B+OsMV_Gx-9lRc;B2%Q|0=?=2f1Z zuH(^4PdmE9PsNJg~Um~byTIijb$>rl#V9uvh78(#5P3FqEeobK~n~F>4n&M*T``1?A7heAC^jq_m zyXzIN+3aB7%fl8ic!e!6|IYe5F552e@~th8%Mln)d&IPXNB)+yWBsHoLsOWI?Tat+ zeVkK8@1g=bO?rjyy&wEJoY7xs7e8<)+AF5)M%nxHOrq!lnTge}2eXUx#9s!rSrG5M zlJ@9(<&&cOJ=|-3n^2B^wO^B(`9@dufUvfe=8{iZFD^X4cR4#flUgFDE?znCV3aQ7 zjfHD>NJeh)+w}gdX-d zmoC$@F+F>9=4I2%CWE)))+6^X4JKCwoNC!0x@3Q6OVA1Zl0gR*uVk5YQ@7y{11pB* zw?B{Cnar~);loX3;b*Gh9Jj+i1n%Unt(1K#o}naYA#-x+ml~fT?HheJyp_y$R#`rC z3RR4$I=h^Wmt(8sBKZ~Gn?EjM_#_odzi3CwHT`*KB6Jz0227XM6`y@8!;_J2u6%3F zoBszreR(s@PRk zb!QI4#dc!8thUh4ID2l1?ucCsXUn3BD;+229bt^eRg|@A2&^;R#i?}Ck;2-+WU2H zra!3GX%dy8$E49>TdY4Od*?cZBMeSVi?p%_5BEc(atwOb!=xN-8G1iuM>o<_+ex;PxxUSbeHn{lGZ=J}mZ5<@%!>fMo9sW@H z{1l7)$QY|<58bWucJ3Z){*m>|e>k6wXg43KdT_&t@#y|jf{w`>u5+tSGN0(&u%dUz zsrd2Mtq-=Zc|gCQ(NZgpaOC;gWiD}nk5(S`*_*I8;ezh5dAk$bBU9AXC-)Upty5m{ zTsLmFwzj>WHFqpdVT_gODl6M*?KeY*gI?P(hL;TRd$Q)^imeEj9=716i}n@hRtRNX zxk(>rdsF4;!!z~llfOjXNwdf-DUSMl)OVG~=B*ng%4HQoNxkzu+9+eW{h<+m?;im&uDwk9wQ!Hz}F;oGYtz{;K-9#B%wIC!_l- zZ|lTr41Usyzs~5yS^j=vrRBIYQ)gan=~?3ymveTpUpjW8v*YGU^PokUrYae4bk1L~ zKB&g0)h@o7%}%}ZYXx6RW$z3rA84@iGA+*HRZdmaEH)x)vN|A7whEppYVP zVbPv$%X8LbU!kX8nI0>?e|xls_*Bq;ctF?6$-r!7$l^G=B6E$hGkC+dgP+bzhc}+8 zcD3(*K4EO2)vU9pN+(3GF4fJfI&9~|y31Jxp$4XynZ1Pg(o$Bg#E^ZF&T{^l) zCACN_eOnS^2=is!mE8L;?^PO#^lrRZuxD65>1NcPEd5<be{ zP4_l#Af?-O_sjosX>QV#_w*`$=OF*{OSY)TufYtRf{TQ}>hmAHNDnt03pjaqRi2Mu z+fqj6`~@agbxfjS-5EA7j=h=<03y3*O7cMRB zYFQb7j3M245#6{!X_nv1VXe^o`U=lYH>|Y32M&h%uk~qFxwiKg+v|Dj#ge3!99sE( zomJDuUDvC`hlQ``8$GGJ#uu*WUAkd=2O;_xPQ>YrlgjIhX7_pDF3UDsM0cj-oXld^ zTj}q64e9hz*0uf&Tyge<qO%iRE{_ zFP0^HcaIs4OCN3WxO6qSQ2*i6-QZLIRXF1;N$Pr6(yqu#Fhg}Sp}numq` zdx_I8_An0`KFU3zEF%)OO7zN56i#icQk=j+e!E0Lz9UCMxd@|gx!$kj+cNaFO^SWY zJtovgH#bSysWreLeT#HbKFPM}X;Mvw`JtoAypz%QJ%s#L0LSA9dXclZj~v9M=}D)ZA8 z$9wC}uX*?A9+NqLns@c)WsBYP)}9%_Imu{#ci$c0xi6V>Q{3vBb7314v;!1!AD#>D zO!?YZwTD?L#<=d>AtODe=NdvA7?rzpg9T!PwlwGq1npE#c~PP>zI-F+3{||OX&Eq< z^R(JtnB|DiI!(*QYn#6;yJhM1^4i)`rsP(W_8XN4ZswJW}@JtOX#?|n6XopLccY;{Xjr&8atPj(`i zdyA(1;B$k0g2h96?_U1Oim6Rbj$>ZB%JMtcj$8+ph|mr{x&YC8dmrsh_@sCx=1L9I z<3@7l{_b``AHQI_Rj02-mhAez{E1jxk{*{o-EHymoAC)f27(o9_vs0;tO?v@#zst2 z)joU6@7ArHkO!|H3hvpi8)EpN#HVxbv;3TW!<6GaIciKaDo$)dBwAFA@RQLfl`TG7e zOXmA6@zmEFey5_hF3-dO{cs)w6b7TZ?OX%MD{NnSM9?ZGq_{_W@k2vR_+ddb-b20E zXa;Mlki%nM0zzS>cqOshLBT?SLy;M4D3O;Hjxd-Qpp=Ne9>|i#Ld2r23agybD^FR; z5@_K1wQn{fWxn5y{Y7}R*w`jHSN=M2Bb7@;84uHDww@(U&=j4PU8~a~mdkZ^RaL;{ zd3BlByb8BcT2&&uvyS1ABPVH#vYwYUyZYz2{3$Zh)!2WSX=X-}IItusQMrBYC7e?$ zVkRLmE-rC%?y#zc_DXW^aOO=gEiTv$=&6w*))9y$kOBc5wqF3V(2{ZGJ?rkWYcA}hN8i!j;#Jms&}Wjt8Sx-MP?G~Z9Q`nzJc~@ zNb&ul^)}PG@l2&^=zzSY2-zgfinROS+}E|JmVG8stA%}s`Y@zC-77s@tP|BvLubPE zS|qDfM0-y(s@W39^{0#s)a4w`f-mKpQSIQ!8A&b_t2tw3A7v10;j0Pd+ zh;rmz%WY;v*eqz&)OWO+JHjl-?4iEEz{8NxxH;Oj?emj}S-mVcVAKfG8MM=;F2snv zT*XCYf8J(gMm@r_W=THqw*@H0p*1L1mtOtTD1Is@hd4gIJ+KDji_@IerYbI{>zbEB z9=8bx2QY`outu~+6b=`HisAGlO%%LDE$fFH=ts&BgIVR3-|6wgVB`k|7cEOK8^Lh4 zp2d|N5sR}_s;kfVCxB_bEwshaRgu%`xVU$?({H2({1VR1&GVkGJ|5V?L)LW8(_!^)EEw-lqg%CO_Rfe2e+HPyuH7KmsBZ zL1d6qSt!r~871|fp&3eGAOreZ)FW8YG*-lO(*syB#Ym^BQq=uP{w+zkp}yQPn{8^| z=TD2<)v&nMRkp+I7bLdFhddioN<5ET!-1pe8cD2^%j&<_QLqX?hF?I(YC~(CzA-@# z&OtoW$JOo{0t9(Me|w6fM8oe3u{4JUq$#2rU@e4*5Hds*D#BWxAxjCLnc1&UC@M%7 z$8WAmF5+XdTjE>uQoBBpG1U|Pnaqd>Q42KXV2$j*@&1uQksyR5Z{p|>Zcf|=ez&cf zkq{**Qa76a%5soDu${BIBA=74xI7ap!8UkQ3w2zJ%3#c}N=M>?8jUQA;+WpoAb6IU zm6L>e0$UZ21X?nvv3mgXwy`m>w<`!18E+vNSePIm7Bouk5s_;~>rlMT7*fLIW;Q2X z{7bZ|i$%$xp2HC~MDS+{MMB=oQC5<0F@1uSbs(P+77iE3X-Jcbq!$f_6JI5#7*2UMdm+ zf_d_k4`V(vqfzh6sBcmkBwj8mWfYnad~C>SswHdl9CpO?;dT*J(?)e^vCGn3Aca#py|bjQk8EY0C)p z8WxxePGiDfcb0HbBKGEOhLYsR15W!Cw>B<%AH6!?xSuSU+wW^Qy(fUHj{Cd?jCULu~yi4XSxa;V+oY^P`;jj3@NV38QY620l zBuN&@VU*E!PC{f3?8HpzsPFx`0{AhE5|^F4M<>2t>BqG4NC`hkK_*w8aXt_S7_j6J zuRmVR7KT*Ow73Bx>&~q9wEQ48E1iHv1sJ74d{iL^2buEfN5eU9L|8H$NzU{E5*6n| zlcJ*{$~Nr$(H*Jqst<uuBqVI~-yWTJd#2V|^E3dbH>7ux$|lf>s7(X% z9*CUsNezm!*V8>bAepK43;u+<&%C`a6Vmhxotd+WbDCzKp6t8jnRm3RYAGt5m%Y7K zv{u{)e-cT8ZbSdodBsz7oae@*A{1IaW`^Skp64jL37#Qyh42Pm=lZ+kXu79#GE;)=riU z4mbFYe20#@5I%MA#{3f+q=Ky&4P-DwUE2wGc*Z?V*a9djF$_d?h$NqCveqssYCG}S zgU)|*w3VWRwz%SnTVIM8Ana=ioIG3tE|LYkbXRMSwwoFa5Y&K=V^2rEAe#87hX% ze)o<(Zh3M#KJxu+-yXcDg*X&3PQ8R zs7}0HBly9?cfR_YUlx=h)eoFIs2&bj^9E}Y)hga0oMJyev z4u@ASds0sJ=IqJ9>mpalMfMhAT#lFCk|BZ{q#6#Do={q5B^lJ-NT>$jO9h2bRos;B!O46ZO7^ z!Mz=+)<9PwesLxx=q`5oUXQ`ittI(z^g4jC>ItcyMdLrQO@UY zf1`Xh&(C)IwRc{w=knfjoMTE0;)m&d4mw0!T9Y215ki{8&z_MQ} zcx1IjJIC3Og@yXg7PB;%a^2#aYGKcVff=_I>Xw&0TGxq;B)@se$h|(0Yn9q&Es2+% zR^^9WIvy~u=C8ES{8GPIPcGK(xIEjS14XyQHU(NB>5Mx)b4}r>m#e{q?n#oYDSi$y>(RQP*)l z6&F4>%Of==+FtI`QQTpc&gqDnTv(DqJ>kHt+*)6Od9*cVQ!zSKeR-4UylC2b?s>3s zZ(3-@Hpdd798V`sVkJ|<3bs_-CrnB`rkO4B*%0?6KPAqZ?ULi9)V$us&s8*wY{R^Q zbK-gsMMbXa+N61GOslTfv}(C{Y~w)rxIB_btrnYmw0PtBqS+fRR+^+z3nLuab|8wd z-!A0V{Wh5QzT~DZV1jGe^(t#=d!nIG_i?kvzmKN3at9fE0=P($`sjLc^wM0-SCkWz zVdcRH^S#@++qgkXIdpF5`fMs;ovyQA-)F1xGSs4fyND}Kx(vS3_Y*ng44nCNxo&A~#w*MZqeWBcS4;(h(|#Pm4}pnPaw#Urv`_ktUt&3y9JMxbBCV zO4dvD4?fMSmgFq!hGQ|8Ohtmr*lnk8Y0xXutI+H9pdsTYJY>_5NPaF=92kNkV({L> zjbq$X87DX)l_vDN-(&iBn0CWo2Zs+}E$$oz19Q zN|chj3Fwv!yaW;e$_Sgg*c&UhJI;D?n@tz9X#B&jG(iAmr#eEm+S|ft_%{I^U1j*D zUj=fmsKZ4o?@T+oS@2Y^fT zyswYH0go~X2-KGP>U(z`o@U?nGv@T+wp`lFu%Y`tbs3tKv ztw6L0b&RD5SR27~sLhhg)pORBcdyG_ z7`}x#GOx$7=I0)SKAkq5h3vT#iLS9fx^6_Bvz!ca*~6mf*xDk$;r0yRIS62nj`?L+ z6HEA8VI6JcE&Pj)7ERX-L(+{$+D*4E0FdiCNPS`(}CNvXt8 zNZodb;sYjF{H@;W1zPHObh}mPwXNIWX2V4$g@s7FJK9+{>i#SuMIa0!4!a9UTLGtR ziIfa33>City25=j!j$u+sz)o$uds26$U6kYG9}coEtF66z~9rx8~(8Tk`HLjw%c7s z!%vsZbHn*DwfH~4Z?^RxxMqjH9=`DSK5qJgQ@t5sUN{Z;Q83~i8zt#W<=K9DQ42)~ByD@D+kiz+lq#4%GN){~!iypj5SQG_<9BWyZY!4P<*{=yQ zd@exeT5pq-n>YvKS?^zk=8)N&i<>yFke_NBF+4L$9kMi!kP)RW1`30+hvjKF^URce7UCG*GsZ2x09w8ZCI*rXd@BQ-t z?Ps_}b=jP7#zv>@TH<1c2$l{Ht)&By+(cp6L%ai_dBWu=&ZyAnc|2GHnn-rOhP+gp zp&>0TDQzv*0zEXQ#IZvjYg?vavw}?`)m-LL1G8D(ij6E&z1p4hsA&QP$AQLKo{a^F z#X^DXzO-SjGB)i|c!ZR6Hglsfe#ByAdNMJOMxkpFN7hlk;naXX!>gt2pUaO&uTGeq z5wB=S;QPsVOHq zs*voH+I*9%j?A%}nm=9m_g085&M0>kzc)xVREfIDrHPq77!QF{q@;>zB1w}MYHLdy+6-3pLIk=I+GFb013l2|)H`Mw5r`SK zf9zf|&>#9X8mpHFn}Qt~QhETE8~6R2>xAnXm^w)cU8QyTfTdH22jw7eoZ0SV$1EoV zt=_AyQM*lTXh4*ootl=u;WlDMMHg|uMt4UsHeU5eQBF6G4?{`*ZL;0?yQ?$JzCIJ$v@?(iAbY?fpTtuydVjtD14zY z*FdRdkVfbLs#?QkEuVq@kPb260_A|75&@00$@qrN?@P?n_zL|wtCitxzqu6zuhYYW zGGsL^>!rBEtw;85gmbidmw)E>i7e&?b5v^aN)AG7Z^3DtGbO;*{Fg~l30h%`kr(=^ zFI{jd%TgNfJwyrhwa^;D{CnI%T*GwgGln5fF`OFe4Iv91Qc|MNkCL zs2%Ov=RkNXngt?ar|mS)whyW2^UhxL_UYN>7?ksYA9(Dt>S55jU7Ozu74z})m2TUs z6~<^x|EY=1tXiLfn8!#4c9z6b6BG6)Msw(U@J%r`6{x9v;GhZBfw=u7 z8oq)ES3fiSZm-$C#J)6IJFg<5Hvmt=wDZaD_b*QPotgn-jv@?oq>$d&y$HwMjH_<2{S`KF(AuN7K4w2SPc^?X|B% z6W=(;F6}M%+PQ=Zrhz%ax7xNljm7+A-~05sHxa5ccpMxE>a#J zWETQSIhu9IR)Z{p1xvERON!tKhy}`ixzzgHw5j6E+Q=wEP~1+YZ>6RVH|6^a2Fez5 zN2%6!&dF5dY|J8m+6-qOFHN#I0B$O-qrPa~QckY%d?D(3pxU^24e#bLH+%2|w+aiu z;UraXoI|S%GKW@dv6-t`?ly8YDo6q`h(R(jNH7*M4W`KL;X@GaImPB)HW;R?6{9dr z1yHmMrFXDV1FQ|P+y`D{wc;q#Zrj_!Go`*!zB~>KTk9CK6A4UIZK0#EwdZZWZ~Z=` zsGWJ=61&SAdrA>~^N}i+H@Yi-ydgwx{D}Hpnf(p@+}bhRf*QyisE@sHY8_4>@MT03 z)ul2MgTB(FRgw>yB;Tw0bNqnE53Tx$-MfgSZ}CKF3G~$tW=ze;N2(oYAKEjZ#$wRcs9< zm{xTN!6O`#-MWgDthu_SL;1_MUh)@;D%Cpk@Cw}@|F6{6o8d2r1f5Z>pgpRn z9mY4Bo_K_l*xtcU?l(xxXxvg?jHBR9u1u zGOnpuMbYYNV+^co>A%=gtgq7{hm?Bv4}=2bFRdIjrDmoMFjwF(;x1!r@1C%pt95RM z*)D1yjhd=er%+Q{zrFm^q&`~Bwck+{!P1kh*hZwiJqq1d<4L)uA^W1Rj9<6Ds9qdR>RmFrveE{6T%px6ZJMkA@y(6Y-1EFw)30GEMy=Ht-&8%=rd! zUY4}~s}ui=6Pnl>|J8~Aq>KM8PXC1x{~^WyBT2;ncar%2jR*eq4WN-l=Z9`+{xG@}0yn1TjQCV!db{|SYP*c#axTiBZ6(@7Yc*g9J{d(epg z&8TdrVr%hNP2zJf{Z|>u|8}3o2DZ+BQ#;{nas0C+r_TSXHUF2w2>le41- zKDmIgouLT@KAoJSv5Di~QIe|&DN+2LFME4y6Pv$=mHzKL_}^45KF2@kts)eiuo^x+ z6rCEr7Ct?`7VAHXKr%5g;s3q+|F8dV=0FEu2mkN-`R`5ikLC7%*+l>R-^l-Y6X_&Q z+pg2Y{JHjk!f6+Z6ED0#B?pGV06(bVQ*ZidZ_U9{!ydAaefQ+_P)orHBJs{d5so)% z-@59%`m}kF%r~smDV1Q=-i0y$>Wp!I@N_!!2#u#bznD<=p@UapP@4&VU42Y})9mBr z7@+2aF)`nI2zbr8XV%^9KR#-Z%h66)TYtwhN*JoMvH5v<#R%g!&+wR_b?8=R zcej0bq{ZS5h#sYJ${e;~;&PdPbm0BEx_##)Myq=|kk3hX#x3WJQt=ayNLl=-+#Fwi z)!5GeHuKYTu-;w*EV{ed9h+q(edqT5B&ko|u96S8ls8co5#}*b0bgKZjVZ68u#BO} zv$Q5DAEmrffHZk-Bp)3E$ZuTvsJ=x)kzd`@le4*_Cr)?^qm%}u)_A=na`SjwKKG(s zg1yg6MkG_>p(0sF1yTt#42c5O z?of?r?jYR<(arqymn)6vL8D>HkgM+{QMhS`kDtin~ zlSfa4qJ){{HVAzXw*fEf=)-pwF$guTqA$&=$4#rl-NmSamzHbTj$76LbwrIB=z%Ge zh8Ams>9Njr?FH4G^av?xK%40Qi%Q|06*zhbF-5!?$8CM_8B9}e$YCqXL*=;0Ln}om z=ZedZ9kyBN^&bAb$e! K-)8n)IKJ;s0BcFZgdJU&+AM=|7o#26pDZpq>ezfu5BS zpMjo<>EBsC)89k+-&j67+usNO#q$3K|84%8%l}9F|Aou{uOh+!=JJ{TS#9FqUH(6U z{xuo@)8(@>{L}gW&rjfg{}$;#?%)5-<$LiXFL!>wW~Z%gu7bIux&BNRaZNew?4hma z1~XPxmsjTJ2O1n?<0Zs5&nHztQbI9exh}NGZ(c6;Xh%nCJhhR=v$&oVa!O!kV{2X{ zZIZAvd|b|HwJCt--)%PO(LneEs4^<{ zdDi4{ItksSfKiD%JHzH@LLba0{yQ z#d`E^ZnfgQ-S7w8M6((n*tk9iTz4O^Vo?S5H|Dr%J?E?jy$xN3Tz8JVw3*H2zzy$5 zlcj<5GEaq1!fdT8*30oI@W~gmYGA`3^yG_zll#ou1bJQ4X38Kdiy= zgZtjdi&a(5xpH66l8FiAD8bbc4Z$9qWi@K(@*JIs@02 zvNlc&ve$Fupt&vf!_O!G91d=TP%n;-l%zv;i-?aH!O_&wcEq2XzdT6T(O;Xu?xR4n zmKSYew&QrD{owfE&@VP7-b_F8<0tzFoFlLgb#<~g49`lA8G|j-D*UoOwEKubjd|Ii zx*PC~Ur9A4I@xip8+`ozfj}wIaWKJ@KjgQ7pKRCoWuaXHTkZ7yiEktp8D4xd{*OoF zP;4?e3ltawuXnQL5rjLQJMz|d(aM|rHzETvpJ4Uj?>`-azJ-%Lu8e}70JJt3zo0zVPf%GqTLWS*-sv>|qXNWle6;Z`3O>hkTv#;$NTgZLo8sN$Qcj_(qE2!ouQ01Y> zW1?peHG$aa&%(eD$aftw^<50X#JB3H=%=RFDw@grqbZAYo{CxmWj!{hA?G4jO&OQP zg|YCvy1BjI-K917Y-C(i^BKDiMJtu4PJ$hyS980iJfH%Q&M~Q8%kwLqme7 zPqc%fMG1tSM7EJoo0(*LSBrJ6c2i~gQ!3jdWx`IB%T57N4sZU>i~fOlf& zX4iZ_zpUnQoYvCUV@qFNE$9KGp8a0LtGC21PB&1`&BwTzqprBOEzU~21>?-qtkyYo zb$-z((uedJw9!YnNWm-S8E)og-!pQO5cehPpz(6OHp02NH4VMv2lqB8Xj2iy4i`nPw3Eqw3LX{bMnyjj5D?!XW3x z+KD;o!itNxxG9th!fM@Ps11vXjVxI?;nO~_t2@`~3&WrgrbIW~jC*q$(UXa%sbW?; zB`Y^GkxHUjP*t29mG3Caj;twj7I8-eq2%68i7ah2(+2$@t{~j&NK0?A2Mus%)J%Jt zg9B4xxCakP%TDb=b>fF?eXqHG4 z7;8l=viKHiVc^ID^(fTABgWv_j`sQXx%I>VdeZn!B5*sUb%=@$tcqCuX)_TBB7>s7vjtba z_35n{#f^cMg2qp7#&U9Ny60LOuDz^A!-4fBjjBUY(ANIeq{bxi^xQHZQ3IfW)kp=p z3kw_-eK{?+V~T_1E1t`&Ve*-@PNp_dCWfl}L@bYBR4EPW2xA~N=$iB+qn_MDw`@g- z)x4rR%^*}=U&K&Uv(!+Kx)0*0Aq~<>!Sgsq{(!!KDxzf1Yc-1C z1C}{p&x<%cFFY_^i{JG|H*4tXL%H9SJl|-pGjskcy!l^f!IcXf5}2+P?n0&(>wYe+t6d3q)sCp%Z(|%=eYG$ z-tdW=C~Xn8L$cO_Y>~DQI$J;3fBwe$O$BmO;lB+((*<;b`8#1hC21EZbKwg%sv4GH zH3^CWCt6?f5ATS}iM>m*;p$e+1=PNqgj<1?1Nm@c={u{MTj@#?F_|kwkIN0?^6a#K zTE(Gx3v6Q3MnLRba<)I9FmdK%Nn6dzDZK(LtAGQL=E?%FC?+FN7=<=zH4VnD9*P}a z{2llu1wjTxyt-uo=JZE|)h*Y15y*JM1+j8ClhBu164sYSc2I&wwwY-M+y0K$sfxpT z%l2r}w7Ye6!;V*<*9@2Kyr4E^!kf>Z-X8}M!X6PWx~ciqTZZg$e`NNNCW5erEPiol zOVY|sxS33lvklE98rZx2Jp1!~G?GFFp|y%>j;pAGq7Ik`>i&X1#$>Ei*wh&o79Q3P z6Z1&~FZ69hcwlCR6m>k`8%d+#Brk7w*8q`*@c@gki(vbPv+oqBzf@ekzNG_z&sd~jhAHRHsE$ITb^{~Y$A6K+WfpFU$ z!Pd7Un7Bhdt+5?`AsZ_WP2-_O8Ox51-cBbOf}~lwV%@3`>`{RQ-bRGp=OO_|zS(RF zqs>roPUT8LopWfZr-a(ns3t#XUtlzR92q*`OFHToK<*4yk98!HCn780sR!OMQ^Hj9 zcszF1vhni(huK-n^JRLh!>e|^yDSrZHa<*-zAfGk_D#J`m+Rqeqhe6EFVWkqQ>|q- zM*5AS-QA0GjuK1)*ageVGzg&kXEL$%3P`4NmNU_&&ZoH&$&59zK+iuWq(@n{&Eqt~ z27%yy#)(&5T-WNWAyIv7ITEmw2yXmdG;|Fp3jC`I2gdzXP5Wz4Ng zjIgB8u5y3mKF8r@k6FV~tJTWUl)qZk+hiH@hGCy5h&=^Atj6niUbl&}%BpjVq_uw=CG??K2lIJqD<^e6yH4DN1DTEI}qSF zl7u(rRBQVO`$|+Tn`+t|K8xTO!e)rlQqvM&9;qx(686Qa2bpoqwRb!H_4<`Q7QWis zk9TrK^%10*{L`@@}c z^kt$VE3C){s0rzL1iM|xRP;ew=G1NVX)_+4=H~*=`}M@8D!KcNNlNIIO7(!Hs@kH>t_HXKc(ZFJN4GnVrJ{y#)7%l&>=3Oze)8yJ z=qtKaixY|m7VD_!2y|Yi_pCC2!nJ;Ixj|#y@25Rtj%b@n>SAT0|F3+&sXqVDW9M8X zlvs(XP(i@NY&$X1E&J z#kx|dYcA`VF54Pc&j9y5pYP1Ay&|V8ywdK&l3#8o@A}>@hYKt}QJImOC^#OubkDZ! z4VNz!8p1VDpdt8O|nWJM3aXWE4a@jB`Nk3?ay83r3 zhw?A>u9uS~6?mFQG=Qg}&uQIL8#2@nI2;we$*ip-DyxdjyYr7H43ChGc*gg1kxTgQ zPLp*m_(my_C;_8r?W5m5YMYbmjHPayU#xPz&z<9ofoafJL~GgRYR9*mp%em&a%)NY zrh*bDnRp-8-d`d9;4{IX2Ach+4fPhxvEUZ3M`K6QF(#f)igh~HB%C;mK*o~E5eYxB z9^^3T=$S_(f5O6+=XG2h%}TMm7c$8KuT-_fOCS|AOH}@_(R-d2dc57Cr?ZP&FX#Tz z;O=~W_9yxEa8a&O?_2xFv1qP-q4(w{0QQK|=GDYTY5wQi{krKv`MtN(GDY@j{k*BI zxlBfSd~%zq#JSIR+hH`@wViIqnlA3dqS@A>?`3mF44mAdZ@uO8N94y8k5n}7eM8hv z2dF|<3;ZE8PwlK+;t}x}Bz;cAaq>+-)Uc`zzcYQ#Kmv(pmJA@`_)#)`p>&z-yi9`b zQ}9hbKSuI~2J%6%E|G{P(KabatPoF}tZ%g&AsllX;X{5@?z#A%ySz_tPA zlc`w3UNE49*j+eao!DHzcbd3O%u_kPqE=LsK%fqk6B73m4{|GoR{Y@@v4gM|WR6eD zIR%ueNCwd+MZXv{O)*UPQuBxk@gv&gPfAga)I%sJyoC)QHiU#z$uhw_3{(SA98n(f z>w3G&Jpr_WxF`MGZec=d=9%l1D$H;)^_>KA!~pUtMPGf5WYz?+K^$L-i8#G%vC2EN zQ7?H13DTFelWx`sQC|&C(jJWp=)TAVu__@qlH~_#6&+e372+q#IQ(`(w8Vn|B&*bR z{0UStj$|Qcn5mThJh;X!Su!5|vm7yd_2eFHG7eW~fC;n&vjQ-FC2Qql4YI)_j1;`2 zHgrYc;?QN^j>D-LyRQL%0H;c0PbO+ei2`7 z-A@wi4JjTe&%O~(mS~0+hK}2z`a-igCii(K9=R7g#;1?ZNVdAo#Ja-a5)pOZU|y?3 z+ilzJY3dR=t&#Kg;6(Kw3Ss?tH=*(ahs5@tQ~leH!z*TPrFeOnb*b^S@B8spq(2H+ zIBfB_L4D2&`lbNQPIz8e<#iM(JdM2-)$<2#Lj}H}+~u(_nS@~bIo&~q?m%^=De|nN zycn=%Ov#7C5X*bcJYNT=s1d%+d^;r`5x}hU>)NcA^M7E$<1t)YwBfRYCL>iWtSKqq zhSZZteFlVM$onZD6Fn=xspiL2Spn8EDmld!z+Ty(%e`uge4Q&xuZXE~8%{^JEVPe~ zhAzv+#jt^WbIY-&iu-;vVsA848 zMh%NbibhRXl}@nhz`;u({p8kyW{M(jVbb%$(hRkYz>%0pGI-!z`p*qX=OtN1fmkT9 zhf_0#80?)BG{RAE8&M|b2BhtO4EuY6fkq=y>bAI?W=C85o~`i7K%_TZt&K(&Lkc*p z|DO9cC*ujJ| zmYI~J!I0hPOxb!hQu(}H;hK~I-;7YTa?VzG4umjd5?dmt=me%;6-59K!s)Zvt;{vM zgEc9p8&uYwa~JS`pBR>VXSV+13 ze9f^(X-_INv&k}=hu{DUHVSHz7(n-DobqO3TGeiNwT)Bf8J>F6$D2Op=dk2Na$efz zA%%hpY5Mqbhr!W`f(-a-73~51O%=IOQe3tYF$ft0Y$Nkj6rd7Z#*F|41Vuj86gEpH zXdu;gs7sRY%rvZZ(!w^vxQX-7w4k^qH#8cM8bVq?&xpQw3aB8{#pcAadNRh5LBc5@ z&l`>YDZizO20@paR1SjO^_JG-p9F<{7&y#YoDx0P$s{v?jeC@1j$#ouFvfGcZeO~Hr=iAB6AgIJe7sry6 zgnE29MMYm&8(Tp9bZxh4KaY*bcJbdvam8_Qa8MF7t5vs#T2TudjvSapOfjF$U}?P{ znu$ZL6zGnL;$gQKZ9SK4oQlRAk7{f@R%=q`2;a{-T(x3#Slse}O}ceZ$@BD5nRW)0 zz6+A^z6aJuRBo$;-g6GTVmgjfz<5_rgr4Oa+xog?Z%jVOrZALcETp$hil)@AqO(3> zff>b9BZn|43?9%J$PB`yw)~cuWu7FKna6IB-r+t=<3Y3g?Tvf{0O+GC(U0f971`^= zqvj_Elm<{hw9SBYd);m6@t`*KC${7-(Lm$!7FOa|ly_YwlRR=&Yo~J9EX*4-qTzhO}#iw)DY8|f9|MY`( zO?kCBqSCmcE*d9JP&;cNYQHW*+s)rtd{_;HU><-t81rDTz1@4jlRkVH9>`Q@Ar z(05@(L_}_&fW}T?4HX{3$jgZ3VI*+Ll<;KIQ9V9%$hn;m-5&$qc87CH@yc@o{Ue=J zmVKvGbbJEW-7nWyge1%3%r5zTpc}F3o|E>F8Ds-%$0bo|i?XZ8QV7#WG8tEq$Jn#n zSYwV3O@efx1)LxXLySfJJf0GV4i3)11;Uz{p$_k(h8i?e4pN$=e#$Q-RaRLfXRev9 z0#*UWrVqU)O`@;t^}4UAvzIiJb%V&@Lt|u>8jbRtKw=t55Ji`=2WTU+^-i&uB&SF% zscrI5UdJ|C^2|;z?OA>`$Eqe?<4!mMZw{G^FP~pYa<-}Ea(Bh8^Ej=o!KYSgm@X({ z-PPMz|JGkDlmzsYy5G~&!P9VobW>*^AMy!7;0Pxss6rV{wn(Y8C*-v($c4GWdm z8jRmJCBJWX`8<0)PnM~-S;-2n-{D1<6H%!RuwCjXjl;$M(tEdWOq2BqKOv}RMSOlT zH=KYlxEH(VCM*bZKoSilhCg}Wv=fyr3#v+41a>#yUyiM6YNmzpGds+jgCk){O(|^> z+WOu#)!F>Mf7Q9|W+q;{R|9kRi{!f}$3u);pj;*QLT~Vq6*zG{2j(o_@AqBMOA6W( z{ox;^kgLy~BH!mrsPy1oc!8g>Y{FK~B;F+Ctm|7pboZ3@_Y2mO;&dR^a{hgFUFZ zi+1)V4KaWFj}hcdi7W#AUZ#rCHO0l{^43U5eyNS=x~No>IU|xeBEH~*AGs}!^c}Zt z=U`@h{`7w3*KZNDSl|U@h>SgibM5Jl64Oqs;h1&iW}PxyOyw*rq(!DexniA`!e~Lc$?Jj4&hmLunA>nFMqq zIr-1+RhcBkn_w7HP<_TeRNOCaiESAu4H*mdSaDLMg#Bz~HnU{Ol|}DqZZ(9V)IJh& zBJ>QcbC@uqeg!q7+1xwf_+(sSCCd-&H^fCkb&1-lyirtgeLv7(e}FsFK6(MdTxW?1 zpIOp{cZbiO7yk61F_fh5MIM3b2zqzi5KizGM?^#*%?xJDA!dW&9ZzebkORug#UWAA zh;_ZxRy;229K9S&Mla;s7^@i5z8t6-iprZH zCNB@y0i9xWF&Zsk5J+bUXbYccHJ@1**+flt#5UnnO5_Mwe;UTbzY(jjQ zKydseIGXBFw^0!H4#3l=&fw^z6f3;dU+Z-&2)`-=Aoite1#$^_cm$NWgB4wCOtv9; z&LV1%BkAvTt{$I#Kiey4t_|Pc?Gdy87!H&(llXhFb7}_2Kd=*gMQCR6FhH#R!R}D! zL28_BWNhaf)080oV@&0`9>S!qq5B3t2q8Kgt8tBkh|N$yj+6?{QbE3mET}J8L%JE@ z`r9SJ`#jy}S;}e|cYSunet8^AHRdX_=t~!Bf(Bqo(In;Xk#u-}VEp#hU8cvq%>2$# z)BOrW%*Wz%q;!VI>wZ!qB=WVJ!)w1S#|j3V;VWo(?0}lN4!VbbFB{jA8e*p_oC#zG zaO!F8A8pUnpLc7A1p;9?>GM@4PXd)Im@Jlqipc!R;MTX_BbG&aWv2a=Fq>wFi9*fd z_H}?;xDs=cylJqYEr8?#u>4HJMBtFx@m@($?EQ4e!@HSIew^|UusD04x z0dE?iVv`)RzxbF5b|uxU#2IVWA}#_wv$=&2tWF%@;ZYn_fmzs(!0Fyn{$y%~SD@Y!f66W$GO4%}rufGF4=OpGUqOK(4@U zTbpU!v6cEV?R?v8Y_FXqZ)Bn_k?SNQQ2{_WEQ`rKlEfG`#!(y~P81zE>9Zb9`J16+ zqa7Erjl~-@ozJ=}IO|yy8YHkS%g&Z-uG1M-kyB!S0R&$3^y!-MTe@nLZEeNX%BA9~ zKjWmNDa%ynu+mFZL6?rSy-;gEq}1Ge9V{ezbYpXDj<6?ofQT`kC)X!%WkJSVeSj$$ zAxUxHmT&dM0%8;vvE9A|uDEK>4EjOj=EIl+$YGKe+Ge z13Gp^rIe7j`J%4T%l-Y)krJ`oiBlO>L^iBtlrF3 zT|;h#@4cKw?X~6Tj?Ny*H<5T^U@Gh0j>zR(jStUB+LnJI#76xJ{+n0(e!KUXZcxjD z^W{mh@QwUx@z;@G{5V7tazSdIX_c0mGcZ4#b2ax-feqqez zU!1;;nYi!KJ7LOG;_U3KK3hX@>l)emhUUJXr)f&7zJM( zi@0sDSHA$xpR-~QB44_;^iUvhJ9-pOL~RUV0UjjHkPV0`Ac4=q;q7d>7mo19O|boN zA+6}AZPZqhz1nhxmjNR?J?o22{hG@bE=AbK;m4wKa8!otbr-|7OLc?iGu!QA1cfa zxC)Sbr*7TagVQ?mP31AC&e5=7Ie3YzELU%kEZFeo<9wyXcSK$fB5$|Kg&{K3Kc<4J ztrKrCFE-0`$}ov&Myz=EWftD96=Za{lLEdV6D?Uj`OGG7r!on@)SgL`SoLr52uHNT zzt&GV?hZ{wDZ{P7y>FTxom5`)J_{)`UH>7v_I+gR+_+CG(A5<4)4zQ}J2Cwd>)6`! zxQd!I)|ig-zUup1M<@ZinTKh280=e5zsoxL`N#LYs2A^)ToW>hinaANGmLi zy>uR`Mp)jJ-=QX!*F=}5#Z^A7&Z==X)ZN^SrwPxB%X?(0vrs3}xtSTeymai{s5`q{ zoIHW=dj(d2T-}bW&nD8j-xIf4n-*ZWndREVZia^CbL>?vC}VA3JWn5 z?T!U{WKc~BQus0vMEArt-~H%-QR|Y<>4RoKim>ne>dQ zL95u)IqG?;1$aIvK6I7%ehKztIP=cQJLJSZY8UDlP!iPmDM37Bm9r!(0l4@P{qkO2 zTd^&CLDMl_I@wOTzAd(f@mi2ntT&owp50bf?@;ZlSnhLKoVHex=TqeJVeCGF$_yc7 zzwI!q;eLmlcRPpKGD}j6)18M#>a8eGQ`Y@H;=28?hP~*Y(tTS_%-G4C5esMSY2Mn; zNvOqbz1a!$AR7JxYfPN?Cgf;iX#7xl&L*pH6M(*0HRR%1+tuvig9rIY>rv^u*7zaX zakSNrM|OL&cu_&QCYq9*LW^rosk_O;9K)L8vLQiviy5F;41#&vfI-Q~Si%yMb>FmL zWGrn-O?6Q@c}<}$pTP$_We7KANK%G3o@5RQCQ_^ZF0`RX$F^E_Xq zf(=*S&aA_Fh+Rh6Z0QyU3bdB@Hg4GkU5{!e_8)?;smgRe3jbAAv&F9cKBLY;dz_=a zE0uhNbi|}=JO{tnb=tK`?MgFYVL`QiJs~IKTbE@dtdtA{~nMdAvBji+Q?sG>nGW6kA2{j2?qm)gto&p2JO@VIk6L90s#!q zQ60=0*d2T$=t9y*mhm&<>X{knG#rNwG(NR9!yCsFTUv3it+Q_W_*{3UWczKoZpc=4 zg*&^q%aGXIh|ipWew;S7bu>tG-O5?LY*E9~f<;~tz{f#1bZ5trI^o>$@&k3)-TOP z#Z$#o(fj-AoU8Op+jTa?OS!9c?@$1BtEEUQ*p10KeE(FrCXVi!*HgL2xLS~>>jPBN zvNAiZNlC@*xszjZuD?@`AVjQf_*FD+*pbU1ZdA#H4yyjhoJV!W4jWQ7<8`BI4JxUw zU${Z zARI(ud;LK-v>mTR@54@TFD3ZvsQT@_Y4e)r6wW?a4fkSG12w5_U$wB-coXTBr|n)!>c8v$CMt^iIkrQZfHK%DU-*&oyXSb*EF_3 zF`>i*yr~)&?LM?=A&x9OxfpB+Df2_PJO^KPoT(8($G1E;C=bGsJFvb9;h|Q&B4Bn> z&H*ufr|(7t*a%V!scPoZa2hT-Jd;?=nJjd%znFIOObqDg%VM(7@~u!ii_39)yH0Jc zeIGr^hOfS^6l{sSFBI}Xjt_q@Jj&eD6keN8z`381Cvbm^uUKc_ox8v{1lHANV7o~T zgfR_^6Ft^bdqijULEQqmOX%2c@omL)4!Co;ZXIx?cON%?2NKZ>9b7nu$Z)q+6HBi( z$0sdVz43mKEqS%sI8%Qhe3%vm=&s50+7mXNWFtZpSn*a0dq@$PysSxoFxeVLu)0hc|Af#~z{{M=ali}iNCF}!-`cOu zzLRq#f+hj89am6gjG%+c*XI&~`blXxRnT>k~E5%uMk6QIrf^@FL|U_$)(+1(kR zs~`)OB=IQOlW0=QlFpA=2%e~ac5oSimN4?gnYZp4=zH^5+)aG7AR%#zPyj- z{7K{-j8sH1#()8BU+50gk7XNw-#`V)$3_C5yTzIN2Wn8(DNVE(Qhd`fA+CBBghXfh z80OjP70vT57n|Ph0h!H5zxUer#w=EbYl&Vfkr~>U^b=_*$XatQYLAd`Ib&q@0g%y# z@z3tkz6I8=_x133IMo@H_?#tT^R}(BBi)48ow+`+RgF0>d?U+9NJg%QI-c4q?hm0a z!tCQlG|$Yhw7AVT@a8GaF8+!^hC)GXKRrk>f!Gn3RcqD;Rb`S-&@hq?(J;zt z(JsT~1&gnRnVjia5!zfRYGzo+8Bf4Wjh<)~`iNMTSfe)~-}AUc)|4}+b-Dw;-#1t? zpXsbHyaP0_mLHcCBd{SRz$H@BqF54ts+EMQe;G#ek^y`O+Y>}#Y_P6`n?TowEk}R( zDNp!?lfM7}`2(oQyV>GK4FweeCee-I^sUrHxF|fW|Eea8;%#kv>&3&v1sWx%&-7*0 zXfx+Z$(hz-!voVPhFkb)cJnE!Y_#5W?!s_d*E6>FIdzZYBm2fht7Z@}DNYrVqGYg# z9#Ep`QD}i+F({ttBKpD@Y)4bJ)B@VM%v|BQ1o{&6q=&p79ww7+<~f9mJI;++4s zPyd(ToPW2v|IaulBg^l*{f%=nu(JNyvobK?F*CFLIcA}!`*Zv|?|0hoyx(bmZNJZ1 zSy}&_|5XPY8~fkRfA3jX{^b9@_OI>twZH3QXJY)5|2zG!`hS=IozM0gFa3Kvf39O= z{EzE@pa0JLtG@rVr=$B@pMLl2@AvV$e}DST^0#(=AOF?fUuFIae))TN{Pnv3G3fum zU;p!<*G?L@S*QCZ{PY1uGcSyHM@-D8mun~A8_6Trf{PcQM3|cbqOS9NMR_BIRS5Lf zx^H)w9WOHUaeXl3+CbqWBgj^)-lUCN;)GtUC{`|BQoU_fV1Q~O|H7GhX0J#U8rw3S zIThNCokUEbBO0z${@nD|HZd>F?G+=K$WxZK=KMZ_G{5jb`fzRP+gXECv-ixJrN~=h ztt06@(KGa+$?a1!Eso4Sy@yZ3zv<whADS0XIo|p}tv|T}kMrGE~BthOH@>uT9-Sa{} z=|hlgXRoRRkyr9U;B;SgFm3M6-9A%4c%c8ZLSL`xag+b_?pp7WaNmwTt3zzI9G%)T z3`{Y9pPoJ)T~a-GU~*Gu0Hu>cEdZ@>({>1W;2Qf}tM^ ziI;Pzk&J>UqTt>cqCzHpUDCs^MEVYq9SZI6q2IsQq?&JQ6!J|nt2;T|S&)kWoSBwY zC%i8QoYPa{r)|@?&d!otz1w@rhxN5&52ksw7^nyT-Mq&7AH(POO!iOn#lOyL^uJU7 zfvGE*TN^u4E7)4=+x*V>$3&)TZo_ZmX#Q8ie+Cf$J1GADNMnlr6OH*F4#|IGC4V>l zn=SvlPcr)-B$E!0g`M?Ze3IGOe;55HAoKsNPck+AA1memy;Cyd-wo&g;grnuH!%M{ z5t;vB?|=92FCvqj`ESO}|M;GN|NSWZx!eEADA~i^OVc&^>S{xHy~(M@`ezE&c!C$P zZ9S3ZZMV2R)oM(F+Lpm;jDdT&p=r}kfmFUZ7HNgVxaJuqZ@zh;U|C>%2Tm_L&6F>U zcPE~Wuvs$OUlQ~1nHrH`++!IICYf$IpCqQh?zYKzo<4kzT5=9Nr>=Yie!C?r2a$yT z1b($DV%~2E>eUx04LNDE?zr@Z^bvyS5(-P$Y`)t%0rq$V6>wrB>#;C7dtUHe_y(%d z9j3$@2=f4%86D><;xKW(<~qH?uHbjjgEx7;!N?BBOK2j{7;ET#RDI)lSo$fd)T#q? z*4!p*m4*4CdW(ghezga%{cdg>_ufH^>SH~EwtZ`AFjW2QdEpA0s(O0jS{~8)W0QrL0}I((+v?{k+Kd}NgGZ) zpePD3HiHr~7K0(R`k5eod>eM3PTOLX|zI!b6Rr1Cn;JE1vfW75TR8t*Z)yTX)i zlhLh#6rverZnwHISV;5s0dBS#gs_XAD(C!LsP#|dwoZN;Mq&ryNaPM|(G`K=A8?uo z2+eW~UV0|@Nyoh}DD0CO_7^JA9SKwxY*Y?v5-H)1k#b954*nF-%+v}(Mae1Bb5k?V zN(^h5(9UTWkNU30t_q|sqtZrIT*eA@EM-Y0jgu0Zq&aoeDmq$hbwqLDL6nvfnHbwx zl5=}(F8*-TR9KQG9SH{pqV;dxuF-C{RX-)_2$P(|8$KB8vSBRzT51zx8fnmZLE=my1t}^zA5rY+ zJoK4J2#hmH>{hL`2@@CC(ZuAYD=dsLSZ~l_k6;blo^DOD_dOOQWDrQ;V+%H^a34R4 z@P714+}hbvX}82f-a!)`JHwKe1uZz(Hx1E|HDT#kx3P2K=d%#L*98;poo6EmlI=}L zk;2R7a$Bb=;X{dU_GDb_3dl59&2mybHT|k?FEOzeZw46(D6qlxOCf+&|F$1-xjkQF z%t#}bkY#9zWRGE<9fu}i^Z_@4W)GCn!LWKDQQ?D^0^_2G&z3zaZ&o)JNjQvHn!gIC z?k!%!mbwsm!TLaMP06&5n;2>oLi}Kvh$hEakgz2e+E`EB7BczOQ)rTG-?u20{RQaVY`P z@F@H}=7|REm)ob=hKxpCV#%hYAR)1`@~_O7SMA0}&FJ zwm#%yqxx;h@#qfT4v=9JidDCMQZ(}B*|lQ@aU+H9{69$FX<#4?H|UJ0jjDJ zRaaX6R|X;TVC+WU90Ii{xu0dudSE~5A8vOrzRtsa0Y)cc@dEmFKw3;#2o)ZXiRy== z6>zTSr&ITVsfE+14fes%d0YPz<9+JamE2q8H|`uZ--EY@y9w55$fe`9!8XdH>KwyP zS;6~AyJKj(=ZON-Y<5A~DlM4m%-Q4qx5OQ91h_0P2Mx9?HtASzI2>;*ne5T}ThdC> zPSWEYdOXqKg4u$`r(eAT3-O^2Rm$*vz#S@;q4w~vPivL0kLi`31?)?*=Z~64t~F{; zLEcN7VxW3hOfS)a61?1{z1;^LdZgVX!&po9g&=ck3r3p=G_^PYYOPOdD}WvVSmNQU z*SD#L$3cBY31_4ubjbC}w(d-RlADS12F+mh7!xFtMAHeeU)_1Qod|U2j=I zfjC>X)1&0H-j$ewJ(oC`sEA?YmmF-L=Y8=xn{XoU_d26~1}t$IeS9)xI79wgs>Arl zUtO<{m+MyvzP0eUuVI$kA6+K^9RlPp<~5eMkAx>a4wMdz%I8OG9jd1tuC!wFZM9U$ z+H=r9=Hj|MRa4_uUKtuB6VI8ei@obQ#HN&Pw&VhT7~^ljbVs-s;@BF)rgi1;^=tYA zu5J#4SZU$N&rIFM`+3@3A-^vnCPXJiIs+F2+?B;3PryR&6y~_Y(hb0GSn`Roh4Hph zP?MtUS6fQ;Xj?k@6xE0#8wX8@AE70JPxew!`F39$E>>kco4W$*i?HlSm%fTF5{*>bI4MXRdvcWFb?&@TQ8F5!8TlS%(6 znf8QIi@T$3&x0nnzM!rx2m+6BM3~ zL?!Ew&w}L`@5j6IMEmOX_0vJdkdWs5$+N3E#jsiy(%1KVSNJPA=9`GEjG?pg252Mq zvW{(yZNYnYr&kg9paJ$!ptg9IJI}+%3-T@qff2JW!AtLbY6g}yX?wbdMT8Po=WZdq zk5>@S^ZQ40prSw4WI_bxb#;~58_$^A``FbF!U+)r0-QPI%5;~&RoDiCV_`B%u;E-* zxy-T3{98`yl=3;58j{?T*%=H?CehNcdUv8)tT>S7CO@-2M8STe-zkiL*otc8I1(WxH_1>9< zqazq#jfB8iX||6w``9+q+rUv=cBrc+2d6X#a9$jdNAXEAveas6gkMM8X*kF10Q7K& zrm>@X&E?{tYe%RGfx>ugLTBtx0v)2HXTm=YWZSYDsZILVi>wOv)GH=Ny zGh>H=Y+AVZNbdnJJu580QX{{uq`LFa%1er?oV=7MIhR7}>8&g_ra30mQin4X- z<4J`#&(|^yD;*7WsF<_%0_vHKxq5%S!mr=rX3&8bxfe^y&2e;1D`=H;%Y8~T;zC)X6BB2Q zP*;HIHd9q*idF*K-DVmBn4bWw<4(q9e zNpeb}a(W&!6~@c9luDUkj7x1aufl`<7+9NauZQ!oTz9qGDtrgqb38hY6PwB_J)Y+= zZ91i%P(_zi$X9RIz`V^(vzX}*E*_DsvMHijx2{b*cwWz=Yb4PQL_bfGA8NC?kQWxJ zLgjg#Ui&D>4Um5MmkU_$CnqH>B+n2x)8%ZNGtE_LaWCZTPT!(FOQH#_M8BbALtR4< zVhUzC#f@L&k9$_!X;^Pyxuz97?E|MyAGjXgYXkwN$bL#jy04jl8{oaz~^GDTiO$XHa6lfNX#!2BYYbZ?U# z9A9vGjKNwWwlLJ;jq%A= zP$yD&>yUrQg@vh1$24U6_5q7tl=_~~I-5P4`%d(REsFkKXg1FtlA7!tC3VI*3YkdC z@3}7WTdLGraC$2!jQzK>_couk>c(*e+Wfcf_Qs8QJ4n**%eTieBW|u8DeSdjvZhB9 z*XuqPQS(C6QC?>^?YszKtk8f3+iu@Icz5JBcNxZ-`R>Y5g@z(a7I$b&D0vZ>wf)%D z?{hLT;F!g0e&&lU92%S&;2NvpC}~wd#ZtP5WCiSztGo5*wRG4oz%L6p`5vh=HDN59+2v*M=?dpO zvttC0WAP*EdBJI*c(r^f)Fni@&2jq8?sSY6&-sUV6nIF66;yk@W#d>D+J&_HwK){3Es+71s8gmcV`L$8k#IJNuhOycnOPl1S1`|C>1ke3CiF%8 zQ-EERK3(MaPH0PiNU+@Jm~Icfyvm!}=1z_Ml&jS*#zLc9K<95z-}n1us(g! z&WOpjt3)rW`tdebeaQUeZFw{ms0*HeWxnQOQQK8sGxVXup-aKvhHd0AqdVO#R7t5C zkcb6FYJ-^_#xj3wKckBEHDB~34~-r}J8latAyX>_a==AbMW|xl(wT$5qQN3hl(V?2 z&|7reEKtBE6-BDuU`H+gxB&v7rL$nNi4wr@6+*CylIK(P7l!(1e3$Z4aKq3h`5N> z^oVJAFJWu71Cd?|4cUBOJVT(`$)E!ZmCWV#$BRl+`ElOer=`c?&v1%pFdHPx+luyz ztY1qOU(xQ42WW$|1mjJ<>J*fkciEnnnVUA=LVv!=Dc)6o(jRW^s=kz0cxG4yG_7S{ z{Xn-UM5XpGqth+T*djTguF2?KofC@)b;QU|p_E?uAi-6xl! zBm=D=(j$<~TWB?5=~v*@|4c4gA!f>VR`*&)0-w|h!aOibF=TK5x!#t&=J zrM`Mk(^Me|7L+ZDRoytc3?2NXTvRU z^a+DjYK_fI}tN4r0ei9Cdw}9-)gD^?(TqzSqOR2I) zlSUDW(z8<34=IVgv~(46MzcNLrU0f5h##0j!%K`ik*$>41ijhfKZyfH!G`e;4WVn2yd73mFkzccvaW><$qh{l}`8XHx7da>k$BXVJ{f1d6hv7FMVL zbMUo0nfog|b{wZuP0M|{fd%C+M_(F>RuSr=G}1(n>5vv&)Pc3Z*lQQ`^!i#2W|UlV z9CDl$128u(U8*^;)nJ+`X)RnjHj+A&zU6yN`J3TyGJjjWgrU2;^Cj%vh@f%eXg4w# zFNfc!q+b(j%NK~CZseb4d;XQUz20&0qwR~NikYRLt@WawXOV*PS_9_{6RVOaqt|DA z&pM)~mnU?glrlE5Vn;*L>g{g28bIvk*It%E_ zZYJy#T>C{<2P;YvAd<~DvSH3($9ZaL692ok{()&3{vq914HmH*4V!+szl&^6sDqnb zYz9RMWf=lC9fuG>UZQPKorsy0m1{U$iZfph;V#uIXBP3ZYu^hnY4B4|5aUVbZs(;@ zCNZ4C6lWG(Lq!n>1;*V<3K{9f1m-&g!q*;FKgehhtUH|vlcl6&2$`ewo+%TXwb?gn z^rI@0-FjkUhBSo<%=y%8z=kH8BjZ7#TCO_s02^zx&5h7uJGMnMy~}f3)ups{(@MFL z`AYYKCobgbd1S!qrrhz#mDPlD1%bAKZeyUig37`I`YC~q;N~FVd$RrKyKN@UOh<<$ za}h**8TEuH_Y>;&v#~E8-43f#RA%P=eHbHSjCAZz`%+-ho4l=hsw>8GbsD^0E1Q!W<%;E>1JlbE>e8$P8p2APk%A#m^0=0j3+Gk5r^$Dp+p-y zOr|4Zewx>xSf_aJSQ}Q~^sX1-$QqX|qtPiS7wJ(kr`SODbOn+bxYJWCeLkY>CNrch zYDzb6Um?#-2OIZ*SSO5>Y;x1s6Tb|N6rN3`fh+_dJr%yjK;Hl!Wxp|-1@2nw5~=+( zOaAcS&FcQOzd6P~E8(wDZE`p|*~462{RPY1G1X3S3XuVo^yjeop@P2ErC91u0KS_{)&)vI@bK2eX%dfGeN%f44Yc=$tS7`E{5ki0hzL7l-+X8 zNVpi4>3uIFfK$2Rdp5ZFPSxlFNu{OtHHWIBIPb3giw-{CJwzj33fma040xGYvyy1E zfMe1D!?I4NG1V*4GgM*EkD~ePXD$F-zFO@Bey!Ct4bp%anN||kX!0<%J49$|MNgS+#tX09x4oWqkDR(?;{>wJ*h=8U8gM(EX}{HZmAp zN(TroRd*N`Be740DNdi5viIAAG;A+9EQ2)Vt-NT*H7rUnIcZq1w(Ey0_s7=kOk-+9 zr~!aH0y$(1=rVjnyVXN0i!k6|Bn44=Vh1w64nkv;Mmv7!=LL(bK_$I9BtBjKL9J3& zR1~N~feLhw3ByClL)VEYb&1kR4oQ6c%&EZ{lg_W`_ulsw6LAWKnM`(@$+Fw=ay5tZ z=Inw14}9Okwmr+3Al+l{>$5FfZw3ZLDy1?UnJ(WNg~j@<9(DrK6@)@-rR#R8^lUaZ zRg7#al;z~j;{q4RNC#b#vV4`cDC*x;j{} zJzdTcnC?a_cCVik&!2R?v5NmD2>K^5_g`b^f5a94a}53U^YioT7sw9a?tfP`{r@(; z`tOzj{~scsf5lk;vF!GLSqz-%Z>zxmTlEOjA7#vcR*(Ei`|DBsQ#AOWBEQ1?{QUo? zp8emVA^9C^{{Lr5@PE~4{CNp~J=A~1bpHr@{^#+foiJ___*kLNl5csVl;(mo+i|8WUSOtCfDQY;j})G6 zQ?)uObgUBX|6JWZWN!1+NUUR~4W`XjWF~6_j zh`3&3*`_i6a}D=&G>X6k6Mb^}7@)AaTu%7iK1(~#TaI&zGv@>KhFuc@vOx&Ge3@xQ zBEDiGn&oIECz6f#)lt3t^Ny5#?o`BE)dtq~t&Q#{r^F@M!@e~=8L;_GHu*F^JJ~*V z8XV*?gzhM(KT)ZG5m@<;M{+TGW2i#@KG9NvT(Cyd1bPb`egx(`ev<3Fh@fu4Ykpmw zz+77B?p%0piR1AB)LdGAT83juceGzMw1(2(jYti9s*Pp50| zNk=)5PCzXD_Pa1JC2MR4mb?=hem$lSwqTeiCO&(Q#e4HFTzCx3Zwy?~ za(nxyc?W^M^7!bDc328OEy(1^a+!mCpvbKssP{D28D zmiJnywmHU-@j*K+nHTJ%Z7?vnJ21E-;sD^+Q%zwHu$Vk;OfS6$KHiI{qmatKp0-HE zaVN4&eVOj?p5o8ZTb1w#xcyh;A15XPXNF%Jc+=mxpX58=0Jh{$Jmse7w^S8F2s$7~ z$#Eq37r~8`+1;S#@P(}S()IMOKBw~{{p4}^Ib;Mg+-^CE)=60{%b>24I1bZ&SwoSb?K+A}9Vs@Fv z!so9p*|aZ1nI?w`Cwmn#Bl^t{Zs-(&ZVPaN%xIc`uD*Y8e{ef-Zu?Q0@o{Y3?@`2| zTl1SeD!MqoqiF|x_`VN4Lw5yj@lEF^9%GMQgm16Ky5y4124|G#h+gF%&1fGx-_y0f z`kFstH9BS_aYg_>eVE^vF!(iR5wEv6^SYL27`TG@X=d5lfwO{LMOzs+G-pljA$`7f z1t%Y?oD+`Z!jF8&1U}`L%yO`GLyd&0e|-UNPhH4`-4|c;gX@I=7h^=~0lm@*%I@tl zL!X$!I0g;aIL%m-D1n~gaiZKOvFRMRBKTUE{f_0~^@VAK-pzyXRM`4vo%S2lNJkl> z$es0ly^@RFrTQwPQ&Oi45?G?Kjw6&KbyiCnx87HV-t`9WW;%0I8Ai`U_b7 zH**u;X0kD@z1x4Lc_3CC%?Z!nPLAgBQ0s$+BgRS96c& z>Ak>$0?*TsL2YW8t}){&J8o(z2Bi<^mXQxzL@Zkv^eG3IJ2+~=;w<04KHw~?Z_KZO zzI2>%Z&sg-EBNFk9nBR%Q){(uUI$h5HMeguM}up@&gV^5lwg3J=5;YzC})+}h$UwP zPL(diDGS9*Onobysb7{+v>mwZI}x)~73|u)xSX0a&s=gpEz&HN zv2f5(VWmz@cdF9Y76sQfb)b>jbXMV`1oKMgpWeAG(w=u>=i(H`EG~YO#`Kz3&jy@S zUi8%UjfNIGay`J#^DJ2?t~Wg~Y5NjqA9e+dFh76>{Boo5^>F-o>lQvi>E*A+0ZTQ7dKx9d$h`IiNhF@e?ezTI6>hCW(A8NM8o0t<*sC_Lx!7FM z(sr5YCPb?uRS@zG-ebeqr6td^T4w)hQ-lu!4}50f!UUMtO+|=u$H1e$iPGglfbyIc zZ}#den*{iLD!7d^1e-kxM z*z6Gh=g-Ls>lr^vR#T4iNNI1+ud?*I(fWz;wcvr$r|jkDekWliBXe zhl$P=`jfjfC-KjQ^M~!`Ur=vKir--$&L^uw%KQOpsA`(oOVy5Kbe<{?1JOEc&(Q-wI#Z|_c{Tr89!6DU>@0Y6eDF94=GmK%XadEaNA~zLX>diCN3^lXNzDKrv)V$3 z-`e&N8GJ>3a>_#dB6Deb<>9ZVz)Dy1DuuCe#&IMdmLvg5X&ijsKSZM@X>FGmce*|u z4k0b!%3j9TuH%kESSCfU8ZtZ9K%_!4k^G%(&%iieY1oHOvU!ouaAq5}nxBQY#knRM zzY0!N^0-&PL{iqCnsg zv?dJ#cydxkpRN!?mM?@c$0ujfMJED<3(nj7K#%X`lhdXtI4@z1cSz1N%sTJcyVa&? z(re>~Vm^R~>Fh0byO5LjL%Qj%rAOTU1F$V9^Uz~>vn>cYrK=6auG?`xAlcI@G$iSt zFjEva`NF|cfMF$sy+UMBZayNq*mM5eathC>Q=z;Ik}JxI1&$xT3eEOQSXuz$T)iJU zEq6IjPLH+rAQ-+P%e0PPOWZW8pH{mE$rt_QV4t?cm)y}C?ZxhP-~^uiJ@h%Bc<0>L zbU!QWYUZOwWNYmOh5M8HZBwk>@m~7egYk0`+IDW1m2{g3u$)zc_<7d1EULr%4iK%m zJIa=IZJ#>KiO$64=5$Zt<@Ds2;;|fqf~+xEu83D9)y?ur&hT;v80Y)aKku5-&NZk} z0HN`=TS?_KAo6#EqS2OXdL8&GqIn>;E-gVjPg zzA&BWiE-=)FhPY2dQgR-V6pSqdEK*lU#qp>`OCF4e)`<_0KL22s0lcPJ&?YpO??A| zcrTUldH{}J3Y54`$soc-5zp;rjs*d)Z%?3C>+aj8Pd9)oJy?uBj9KB!F3wH&>0R|B zQBk{(@8?{*yaFOI=Uf6a`oC(==!`Gg;noubs|8;|#l|<^U1K+-@2>g*9ht5#SNXfz z0pvuPBNoS%7zcv+bo{5NmDMxsDc=bL*q!WD+wXbx;={1Cl5Z}kv>AcYM=2wDzxwdtEL_t z0d~;+q=!iOV&Cn!7(=|eZ|vD5QRlG5Mp>T* z&VgQshet+siLXJlqF+f03v8{VJibZF61sh5;%13i0p9DT=L%VY%+{j~BE4Y?uzZ|R z`%JqxIl;EmVIk>45d`B8zNu3a9kzNO-@WcSqdb9t7(CmVUB$Bo&4E=Sf!_+YLc)Ks zxvuIxQuT_7yJZugXjRb$<^41dVk-GI2ZvV}=+Pbtak7r@-$E2cXyj)}*l5@p6n9br z@xu|1+b<4OApmSnKBzMH%v$xEM36`L6<(4Ps(_0bC3?2A6hYE0h=7b3&GnPE++m2R zVyXZ~cw7n0+|{>Rfu}AyFxvYO=qrg&SON4G2xA8b5zJ>QBy&lqa%m| zSOJbmIi5`DotFS!LL@)HS2x-3oiz~Ek@}s)<`Bswgi0tPrC0!M{Sc6=@&GU9{lM!e zi1%{fwZ#E6Oucjb<5w>;Qm#=0YCV-)ZiZ1;zZNP{cT>7s)h@iF1X|SW_#0f6E>ocxzXakY}8bjZlx((g9*vL(k&anNxNK)B)v~h{FJ${?-6r!P1dFQKLrwMg7C5*3*>3{KGgNOdiwfwX0Tc`K{5~48?7e}_)gIW zEIJ_*2e$!UdKxWxWU+1v&VvTmwN@f{!5To!Omb;@$ui`Qu3Tjdk^X5+E;-}cNj5%U zhygu)a6%a<5C_iG^xq3=sLpF_XzO_$^pF}~&mgG{c#CRi@I`T?HQI@a z+VL{#OSx6);EpShbuC8p1^l{SbxO~^jM<0q5BuIUc7S0B1O*24G2VZ$bKuuwTi`zn zMK($^M$=Hy{bgoh8+`xl?Cg&J^bRE@NyBL+5$gW#xRjK+tF<%)#NIx$`4%QT7bTFr zPg6~>yiQA$`Vhn>k4HFFBNfMNqCsBW!F#zFG&a-fhgavjqNlm1y1r$w>SKGk)Afh* zRc8kGT}@<5i%GXS$DH;OcmJ$>aKFx)hQfl*35T=QroXVvgz^$~MeP~mDG-?bCc(C) zX}){Bin^U%XKTg);BD)$nSW=Xt2b2gG&I~w;0rqTx~knXgXJq zef~{@2R#b7BA4QXJ|irNODU2wtJc{iYr?ar*4Y(nBC`+kuY~;Hz(6P>WtAWVUtr9J=Ow ze!y<`HyK=nq-gn$r{Au{i_wU)-zRopoL&Kb>RSzk&wfVubnb;CqpMTqv^tL@QZg{A za1HGzM;E{h{}SFtS_ebC&h=|4!V<#|6mQ*{v%!}R(E zKC^P9T&c<(&~@(iGU^_`?)ES{#eLmss|e)AvMCUcA%jKo(XTTmGV&${nhC-Vjw_!s z-yuOl{0mTh2gjp9uM)=(p%H*!2y5~~1`axxosT4>xcl2t;!v<8%kr7Wa#FRso89$b zNJLYM*{O}D%9i`*>&&a|SL(S|5~YyGFzqvIw~PnB+H zaFzMuN!K)ykwz>gM!B^^yOnaRq^KOb=$k^HNYZ@KwpHzs+J*Sp2o!n@#--d#uAa|^Xw_{`E0-pXolXmXwN_MEvQ zJ*%jx%tBDb+DG5nCE{nCI%n&3cL`QsGVI|7L(Abu=dDu*|0vvM|FaML3>nDVt^kjd z5Eh2iKp+yUiL+_d&-`ffO>?9Ex)J_nqAN)fP3KofjqljDZQHhO^E-KwnSHG%J^`HkCB-ty;&Pw+1_h$h%71@3Z zxFBAxiX=+O$C6h_p<>4k=;<&fL_?8~JKato35bKhFXvTCkU&66AxNl_J4oO}MOC_E zM}}bz90oCprH(w5KI}`UBzMCbeq6|6r=z&mk}vZRMp)&o^SnyIb)of=gWr08DB)kq zVqembkWg1>vIqUiiyf?-Kz6EFbae8<{@xej>->C^b4zL7{auv6{;4 z7Pgzw{p+{CnSkpOL26~QX`{quIjMXxz?3n6wwLm^h*+PMQ35Gu$3C%aB}4&9c0srb z5())SW+v#dPr1I&84+go6k7bMUlj9>`EuEe3NF1*S8FR@qZm=saAWoEq!Cr?-kD{g zp1ZNIxIYy^lS%tw&FE=~FdOCjZEnh4s!_XmAASrZ=b}%+QSjmx<*bKnE=IQL3P*8T z7g4HjjKe-0B*Qg1AsHno4`du-T>=g{H{8??gPX;W04!}2Yo1~HeD4_}*^Ggqly~xb z?v{5hFVuZkqm>audG4>%qJA?&>~gu#E4q+x;3lIb8Ke6e23)B$2;Yd z6U14SXz6ga!Mo|ZE+?*XEVUc;dG#9sSxg&tZGV%(d^N%4T=f}2K};Do;_~|XZbXKq z5Jn}67L$eedh7{D!089PkV!XHXiMTsWJ{1{ zY+U0y-8wn#AnH5|$by@aGz(;sMKIKtM#c&5{aL;lpYLD)5)KAC&*@-}*J?L2oRWe8 z&bc)ukUJKg&Xu>=%#0Wr%NRp)A_GN z$UK){mj{(MmDjb}>kwA=Sus+o8tB?4$c?>@aiXRT*_@Ve%%Dt&A`tj=%YxkR> zpHST&>SZzwsPK}esj4Rgug2wS>%{k-oL3+2;*8B;`)X&_I_Yy|YlBXy1*JDKKigBa zFZ;~NDBqB{wPdA|9}4S;SI_hjCbMOTF056Nrqg2esjr&F$Y>Jq{;^KK{Dn1o7*gp4 z+%=@VfrzZcV%F{9wUc1Au@d6x++c2t%wP*0UY|;+ublOBIk~|k`5ijB9zH{|#X}d! zD1(BHcn(V8P+r%NSb4WEtlbndK8HNdT6`^W60y}T@7p{Bgi^O7fHpH(22q3|G|mo= zn2ahaf@JIN*F{sfuZJ|MP&yDCPyVKzO4|pd`}!j^(F+B1YC^};^4Gbpab|*p6y+3R&W!8a>V>-AOQHC_`;O-1U*gNx-Bf z(KD(dF)|anD&f=D`E&2y#boEW^d-i}$;0(MbkvZE9n5JB*jrjb-Wf;OoonFO92OxG zN`LGHL0d3%+?0Tom&@x|WoQb|eNX&grhy;d32PlP8wwAc!RO!toPN%b+3&ozM*Z_O zK>8FQj-o#`b>ax}!P%oUJL!;(fnSEHU4x9g0T2_cGe2ITf)`MTCyvr9E?Sg>Csj;d zyIXuGe;z6n@(S_ehIglR_LYsJ$|u0^%2c;<(-Ggp)Rf#N_nZVDC;uEAUi*7BXfAA> z-fXeWFLN8#XsKHm(GwO&H=TM;#?d|c^yhsr0IQ`kFwrPR83h4h)QPZi-^g9YyaA2){Y&)ZySsDdnxf9zB*n&PbvX=t<&=B|R*O7bup*o>3y0 z0(2TZ(PPE{4S^vr`a{ilrg+G0a1L?LWZSD@MthjxBzj9u#1zIG2>QwZUrIq5rXP{= z2`W6`s;XAASZs8(x7E)GO2-GV`}@RFK0QC+Y}Q|@bSC-NoMaY!E~l+9sH@coN{WG# zr>O8^Pz5^Yk7~-KY|SNXHrHRercNPdJ3IJSosZp}=v5lI>PndsDLoY<(UrTu&vxhF z*!UV5Nu3W_*yOSFlXtM(FxFd`I)Zkf?+y9Vi~{jGjAtI?a_&2kH3Y1x(Bh_It13SJ z`!w989|yohp;a}&z;<-otJjY%w^|=3eE~HzhS?uqhk7S@|z29juS$@y= zr-`zrY|0H%0*pq=?B&GSD^<9wH!F^z@$+XV5|R)BT)=%3`t5O^_dp9Vx@X_5j7J)2$Yy`(f#O7R3dSp9B1o zo-MrkzHj>QS|g+Vlx*EXGr&CsI9%wB1VejOcd68jU>5Hv=7NnuR*l8@dfQIcA8PG{ z|IndVvVOLct6tlFSz#n;p!_%;?znJBMRw1hv5!rzfq#^0Pss~3=l|4z&oQJz-c@Lldz>E6m^IeE^F*|t>tN;UqQ{)X=S-Lu;8P!KIDBg z8Rtjnu($*mG5B-b>SyryVpW%=>#hcvi4c?Z?DcFMW0-XSK*5bIzvAuslBf=axoHeY zM*-31_>=YeAOO2!4#VXU4Z!TVtarvrn~4a^Q^i?Lh$Z8DfXTwx*?5+iJtod`15ZaOK?E+YXkiA62NBa^jNf!bOA*1V($ho; z{zlWs!pS(oI+9Q<)_{?cG+HExG@5agkD^oW2jKw3Hj!%}Cm7CQ z^gRsq%-|$Jw`W8#y4J@jdUy+HL|ctF;wIrO>Y|?hqmlkqQhVgY7pHrOb{`M0bB)4t z`47y%80CFq0nA5PL9ls~Ji)2UyCaR*)}!Q)2v`JE@9wD(fh4|E0VorScp#HR2QQdu zbbBJ$2}si7t4QbF;_H6tIDZpvUI%(!WXmr0B0AcfnOOkXdYcT&h>~k*yu73tl!O$e zBq7|03$%309U?ehA`P;P6AEYeRKgy?I9;0q5oWDa59_-=lMBfynHss03scXs@0{!v z-Q9)@oqc7Z^LhsqZis<}hLh|{Hkw!S@CM{H9&K2$DZ|VNsyi0|vZ@&hUL(K-t!VND z!pc4yp@8|q<&sMRvJsJ-tnAnXTAA*xM7sD|5pWyczM?_;D9?SsoUBAVw<6>i%M~ zF+;1slneqT|DWgXL8wNgxhPEwRow6WO8O^2e}%Gr$)4NJPGhoS&Eh%pvpJR@zbja} z+SRO+?Az!QAPT>w6~?-ygsfu=mc!CQsi{XE4G&75@0^I>>jYx!Qw)!^+BA1=sV4b% z;NW`teU1>MI!hb?(gs0{m%1BKcDYyw*WnW6-Vkf zu)SrxdPTa5sr=`JNJX?fP^*Hg2wHE7k7w`r-EsVrc0`Wsz1c_n`#UAa?{uoq1P574 zn=NM^{$U18aajRh8b@TQxcN^rrt$j>fynpJ!};8>f`G$&Ut=LYY4gf-Q|(A=Ng)gw ztXK>>EIQ1#d_X;a98AV5792MDpnjrZ2*>`V@*^oRR18XxVTs|UK&7pafZIE)XjpZL zTjfJYRy?phe-zOXRECK9!r&|@pZkzRfFxUX*}4*a({^AE9%6Xr+Q^mJFHC!i->Y84 z0FUR=w&tF#r<>?XvG-7Vc#{*8Du}s&-X63^hp>Kjj1#YTK+ZX~dZ$LC+8`9pyOW{r zh$0F`G}-E=1Dg_HGDVAl93Wc+d-2V3(wGNZPK%=LJ?`fh?0N-hX*gmI?3|XJa42XR z^_|+&tM4ugI(540>!)|N9UP{VFLI)4d4Dk-<0`-_@EXVjZ+$eO(@>$#S-Wiy1I4Oc zm!Fp3{zx}`kG;2hF+A@t3XhZbGrd`7dN0JsT~E9urJQ;4!r8#Oi9)}KAHW}n-e^|Q?m-gNcu`j1CZfWcFZO`C0^+JF-hjosc0wkk@1 z(iBdo=X!p0__(_gSt5!FsA963d z=r7r$2-r;#tt8OzA$+V3@rc5#J1$?}X4i1*d3d z`v}EKjn)Lhk{lq1>CAeP>W%>%7b0?G)6T@9JGH5rJ+Uw{|E_@f^HZhBVG&(Sw}z*N zgL-rI3)1{8njty3mUC=RSKamrt|SB> zO(X5CskhYDRpDi(^~d9627d>2Mvp~X5qqOi6z5OWII*08cSmcJ-DcNDSIx)OhtDrY zq*x+dkU+*ObwO{BjO?bt1yPg#&IX13`QM zig5{pF53ic{=HDU@2XbT#+K={Wj6ZBY@Mu6=Bh6$mS{T8wQjUm)u-iCpq)tzbJ20qK25$Pi9rYMXM}x1vqYF14-GJ_fDp!?Q2_2)2{3hZ zVVe~D5l!b5Nr%%oa-2j;_KcInhy7>g{nw-Y96RVSsSJV)-3(*=9?g6ReQbWaoBnVi zw>O90K&i2IQf69H6=`VH4vb(^YfjIUAD3ZxL&WZbLh~lKqaUL^m3@h@S7?*QOfY-W zvGI!RP_J!x-ArZNRos7%H2V%WAlKoO@hMFLk*HI!XiLx1u**C0hJ%XorKZjXto@CQ z`v9}>y$c2T`c~RNjsI@r&n=v7wq0Cwwo!esVf54gx_@z$#ypFF`n=;kiSTz0!F59u zSf%!8%XxctW!w}O<-jQ_3JN6`DZoHT)GpB@$7>+;bz2llc0~Jsj3!e=5ab4QIkhpGBY_JrZXLet0i@c;fH>OwcYS`Bed*9Z!Ntf{&RZyg zXg|{J+Piq&JY0GE+4`@nrw%ZA5Hc8Vl zPnu}T0x;0Xt&QV?(EyLt>{>HDn>!?-S((V^07eUzA0l~u*1GV9p3rHx!JX{^S#!E5 z!AG4R&BNfPD6yAjW_tYgZE}3jzeQ#Iu8?WL;*hH&H@_aj-^HHM_3YQy&fgZ%L!nx+ zkp30fF=w9|Ho*{Ljt&qzHv}3Tw}`{P!i%^kEn$K4N?+4SHGBnx%+=$SlLh*t?wCD& zs_-%m*JJ>)LnQ`g%>Y3x{MX*FYE)n=@blhaD$w0A+6AZ|2$M7k#2X|@gRw+eF-N-3 zXpD?ejbD>|xSj%@s}7X8g@+J88uX$n{hW0r!0tdz2DlYJvvu#z23SIF|M+z-W9nUG zrm%eZIz*3cm-v32aBg#Xu2#57x(dHRTKz@+EZ$eJHw-gF;u7&v`iXh93!E5z|}x9Ke3%Z&?d$v z>)JnN1LVY)3l&NT3ILWtw6+4qpmfoOB|E2^r~;-y6QAv>!2o-4Ub7mZ1yV3lpf=(z zaRwFuKalzCH3c+1hSJD$ReeSk0JGyN361vCI~_8iNijoVYQUaUV2UJC(~6=E@~CrX zEV4REky^XNTWGT1+lb{8NVQCdQdO{;Qg(WoUCrC6C^6}_(D@M;G~3TKtlPvOMp0*b z>43mZ`~!#&q~#d4j@I!AJt;!F=IFQY3d~?4kzv3=&p$GU8O7R{L>HDJj;SQ^PG|_Z z8$3=pZHyf5=XgG--qmH!Heks%)jZ|bz+Znr+dUb++EMRr)dt>a>X6VIN2`?yz#J!H z2e_J!lj4%^%?wRx#IFE)oKMQ((O5w$uKrnh;6AYg0_>n>;yArfPl znH0Iz_{A)7s)|PLAYJzc^APz|`s{PHRgVGBl)A$QyVj=vjjBSnf25X9#Jzv;Kojl8 z!@_+T+Kr9%+SlTGE@OMT)|74o!xqnOe9CftiNjARihko6(&MZ8?3bI-@8?kcdBscJ zNf1R&n9uKaNX`uf_4aK%BFvXtLzV6QaH;o8&penZR zICB$pU_kiTuaU!tF^YH`Ts;f_hi2mexJm(I8Z2YVxP_wbUFR-gI9T6j&Jc12nk@dd zo|S4Z!J|)$PB}O=>ait>Qt$%!I-noG=Hbb6#lsvlE-H!fwuys0+bbIzPteO9{b`Nd5!@cZ$k+Gc9XT3ZPl2Vt9p^&{(SG>1A-@^LGBK@D|gk4~%; z_ZU)Qh4p)0uAmpo$5}<-rozm2^FiDXOiQH;Q>)+m9*5q58k1=ffgZSQSrm|KxK73U zrbd8T9u8+er~z?Z7BhuWowU#sL3&8r4ehBLtOjVH_xtJAfEpQqnl$ymL2e#T@txQA z>hD?iyceFaXK;Ff)EKA4O?5#eFZk9d@M(j5FkZQagsP2YvlwR9M{}vFo z==5BW1Y{Zw0`yV+8qUpp5&=Ll@)7sD|CpwDZ`0!;@B?B3q_hHM@)TvEx?@?5P**M3 zDa{f7PBfdn$QH96-F`0T%$1+CYq7d(Vp+r_Z9ISCx|QZEZqjmkwBk|FJ>LYq@NyaG zbK$JW=2`(4dV)3 zL%R_cP!N3BaiWTe7t=j!zZAfA|AF%#ZyAWk#>`79q{LIVnu@ODg#ExRkxR=b*Qk+J zV>h?KlbNp%nO9oJl_mPI8Mw?_2~EX4t=x=cyZRIny~g86OwO2L%5zl*BeDL#8?jRt z8mEX!E9Mh5RC5|UKSe`>j%q`9ss{Vf3RN{nAEUc0&&MFcDwHu|%_K~HA=-{EQj;jrayzV-~pJjZwA4~3AY#|Y;OJ-@xb4EV@>lhoL zPPGVLG&R}eTS{{3$$E7>N^-5J7xaW@k+$-(*6`?0x6cR~JExr;?haBbJv5EmVIJMC zg>dlZHle8XMBsHYJ_7QEg|F%(0zy&=Q0%}OUv!7|Ij|)20h*@)vYrV;X!49i>57Xd zSWL_dSnJXav-%uMVUrUrYBBJL?x}%GmbudVZM>auu{qP3$~BDX8Pjz)f9@-RA}OkOwZP z-9Rm@SH7(}OD%nO5q%-M<6N%Rtx^vS-1g^$8`{|_cz0|uw5IKyo53v4TTGgA9k={> z`4(s0jaZv!o?*yQWU0;|t5$3L`DdBulT_HPdG(G8r6s3{3Q{YhmsLUZ1vL^M5;4qz z3_M^8626l(Ms!gy3{kRxbpKxa8RT$aOv($-)xT3x3Q{=pQ(OJ=ut0G@)4ns`;dUmT zi1soFw4%E_VV0(TbQk>jlS~5PQA|ce-%ex)kY!Zgu> z{fvkVTFNC1g{bGzR0Dx=id*<XXqSC1(v5>Ww23o*Yy`d!`kl$l9ewKX({ zzlT5cw}0if+@6hxD?-}aqg2&Ysx^|6I?blwVgNh&ngVYjYNC z5fh!zao_6Mlw~8omLbxj`J^$H8t4IO5Di&{Y}4xVMv|3tv$m%Sgkmb-s0E0FH^E|0 zmo_J`VXL}ITrkt5k#h_*|*zqqEkpo z>ZBEOjOG40%6*A`pQM)h5afJllyo?%Z?@`TRak7ljW|rAdq|2nmfLFljOBr@NKM{U zs_3AGo%RZ&diX5qNaOJ|UOmG7>xD^`2k@l_&z%>JQzkH#&2Y_#Xt7v3UD7~8YtJDc zZqv|O#GxV)bv=eve;(3iMZyWXYFHoIt`qu|?T(KFxKYSd3I@qCWoR zPXnNa!5@ngKt5bYksf(S6rdreyP4x}hA=6aRI@aqTmF$#mfP!W>HgsVc$BaXle2V?}l`MRTc6^ z2s{=sxtH(y^B>DI$H+w?o!TM2ukzi_gSI1 zM;Jy08dFZ7#z0L_PUSnR>!;8qQBOI7rbuBMKc6rd;#>oC_KzbbIw@bL0V$wNVvdkT z`hq!~vc(U-#Jzj7+YlJ_(r~v%MRz_<-YyPcQh)C(A2S%WByF*P(@FRV$I4BV9xHMj{uyQD!O&`nx^_)1LC&w%WPl<1W6W6 zk}dv56CfqdpZa5k8wZX8ReQVnssqLdSXv>Uh*6i%d*oy!=glYz#F36>0(cmhS!5@C z`~B_lb*rVfrI<0_Q;ClM?(}5%1l2;jv$jXlpK<#D8*r>7WofIkT$Se$+w-fy!qr$K zR`83v!21f89E8UmrfBL%p4k*??31;!jyLySk_b=oMeI)MI57J;qPmqY10x!rkB;=Z)ZE| zqG#Q_j1B-`4gumVE%ElTW@bTJOj_(jec{1E%yYQGRCVrowGM(z;}c=ZaJJP!4#!Qp zcn%seKh$-elr~FQZ5g9ls<4@S>MH^cY~=(5T0GnybUqLIhU$~r+o!6TqLgg&Ef?H^6Krkv=u$om3TFJKQX8WF(&z7Yy3wkR;zkbehMH)`a`7ViLUHyRyetI^o7Ev*Vb2582 zJLPp#-$4H(AZguSE%!kZ0+?o{hvxn}!lZSj1>AxK8;c7J zxHZu9a}ON#;_H{D-gub<9P}E;vYso&$Fa~@IQ%$O{x$3Zx^YH-C+1~M+D>WJ6LcT6 zJMiW#r|{Ym+5o$W_40jKb9Ora%cPE+!r_=W{#nt+t42tBfe^Ji)-nz^b|%|mSlCCb zxsK?VSf_$G9S(pT*2V~0yUM}pI~^XnXbvDbR%c^t2~_h!fc3=*C)yhorM-{+}8_c_&fULtA#*u#>#IMxy zOtvjx!U0%nWVv*?ls!>oPol-qh~#WYWOj(0P3b6W%9_LUSZchY)I!1s+mN%hluD0m zf{2M~O^4lX+-XQ`nlVkrtdz2;KWCm?x`qb_TFP1NqHn{5B#Vti8;S;O%lL%N%Pb#s zCJlSLgtwAAw}58Dr_LC((x)Y(JWR|N#ELYt3*n0$PTh79a<6n1RlVk`)za#ID0-fR z&i8m2GFkOBGL-KRuf)*5WMnw5gyVn221+3XNa2=sX5^9{_0wV{WcGx8jlHq^t+MTB zep4Qh6Va$d2h1Gn8I@T_36Gv}TzSKq)s|Uj9C=kx0r% znU(6mWMt~+=$MLY?YWXIljme()WO}-WlM2;*@=fAU0u~#J4$ueeC(n$wZq&!Bh!NK z>EptJjGxEBrEyw=U3J^mNKOCo`FZ<$rdFLbaI?a{TQjCoW!cru?r*2%QiM)p;W=rO zVidQ?Rl?Ab79xKW+8V5>j=#eyRPekeOk>oz8IQGeqo^=n5E|1_czSFY&ycHAcj4jy zvlxmMTO$a}bvAw67K2%%Jb=~MaJHBVIwja%a&FBAFYlBlH42NA4S0`ruVtx7SrtJQ zYf7>haK8meufIXin2rV{YSUDfiJlpA`l?qhLs&+TkdB6iiSoOgw*0%Cg_X6uPuNES zqLg%>1Q-HoDuuO0jg@X>wZ+ee^#zAdM~hcD-=Y5Y1Yh0!t^M!>(i%19_9rrnoa*|w zz+M4k_t(XNwRZ9H7%XU>VD-}FYa@!!;}9(*^ORE{{_^S1I&G;PAaqF*G*D_eOT)6= z9+!+rN`JEaJ6W=dD%XYJ^WdhGIqspy zxtFlSsam1xQ)HVFk&_(RdewR*q1L#sU<=g?^%&YHFZg<@Cqare>kWHiGhvtNkPsqw z69Bx*{$HeQGL9%V^=#}0+B>-rws2OAW$m)|vB1EnL2SD6nlgweu!M9Sapd5R`iF;* z#Lr87sYJU&_&Z|*YuaLZ3e2F%<3zVPx5YrHMTC)uT2TKxSU^CFq=A@vUMZ+=OZo3g z0bn|1-us8^*6yz2tz9N%#dUP&v^ZXu$u(wT(i?p}m*2y_7`9MVuq0%vP~x1y zVlX+!Z*{Xt@t{f6jirfH{QH*|uN5`5+D^0kulg4v($Y!`e43hGpZqREeKDVTeXr(F zCDc|s58{jG9zJsNt;1Rz&G?+W<2AO&d!c_wEC>VI8Or-?tWn2K_d(^rF}O=BRu5 zL*c_*(GF&J4)H*12NN;Q65@5PMtC!&g~aVVnWECwR9pHSs$wfmhoqkMb?MA3u6a4h z#xFhvSmTP7AC7Wmmdyb{$`^9bB=K@8N(mLo*402Xcg!ofYq>v|&Qh%%134kYzt;1Q zsVTo#GgH#iqvy8W!xr~ivg)#0Z^SoAwg;vv)six8;|H!fMyY^LB` zQPnHi8!M#RM-q_J$CP7u_HOR zxSDG}XMT8{kJaP)&LU+C)MzFfE|y-g)JDD{xv5k~IPZrEv$C)dI~6zuD`ga)ixAD1 zaCGLpEq(>WyEpJ9+xW+gTG*AeA{Gf=JKL_K#id{`KVnZg%AGKs5hiLABLwR zQ5@eXego8uZnr0H1%5kSFR9rj{V`e-m8z`olHl<4jHoFnTL^rnYrpYrG(FGWG1(%4 z=Rj6*DJa za<`OAy+m@>8Bo9or^j`h7_&FEwXAbqlwPOs#C{S|ta5i~4pzbQI$4#MI(dx8tt+11 zh>&AcDl>fq8&;)#edU}ZTGh8O9v^SPGC>5?O8zoE6}6dk8cGVZOqL!Qr&vW<m^_&xBpsP5B5xpota%T3ZA?lKY+Sl1m$8>A|G=i< zsNoy|gNwrT3*d+tk!6`nLTp-hT-7VL+eVw|F(z0AJaBY-2XHjkh?=Q{?tp4>LDd!4+v%+L4PH_QY01TTf9%?MVXuZ*s)aFg z|6PU+sYF9hdNeEWb8nu-#j>e?bzQpk{e=4s^zZilWEQH-TmM7}+nJ9zL_vbD42(%#gQ->qNguS#-g82Qd3wIRHb%OZO$>1g97 z)6QWuHYq0k7Jgn7kuHt;^A2N+DuR>)DeC1KEC%Erop!pS-TOj`oLcm~fi9JszDiLJ z+)|I~_xwpZ*tMT(iEWTanPaMZIJp3R7SX@*cLTrc9gWeHPF+c>w`(Ion{`gU-BW?C zm4L9eKTlnE@9)Ia2dax+>YiE>Ria`da8zWHJy8q43~D7r)-xGS5ASjroXOC>%w<(&4cy*)#IE>xt8K<@rZh5jsAU1Rf_d&z1n)Y z39!2x{c#r2X8I3<)5X(6!JBC4 z+pdZ}G$Q+uB-_t+Z}pwaD2?ko>k5=wEDx9C<@)t9Y^Uxf&Q85$!n5*2bv1NL%PCqH z1KZtnLWSDmfRzwvP<6mmN%NznTFBykR?zG=-UZk5FtAyjeG6Z)t|BS z?Ygt0&bB$ps!nGCoA+qs!&b{ZhHFmlck)l=Q>$&3E-n&TFb|MQWA#pXez`Om=mjGN z%8JCvM7>R|u)zhpk`5nVE2Vn)t$4(He!Y%{zM5g7OrDmOp)C3LYTsNv>TLI^hfIpj ze0sB|%#+R+sITGOeSIc69mjAF)#yIu#19R!z~KC5dkn)U-CPOyFzPTTGN+fLxdT~{ zW)qQ**N5_-YVqydKPi%{7%iA^7-v8=VZ?-HrAgv`upzgMmCI$T+qWaOlnnAN{XZ$A ze+6s)FCyk2BFsO(%m4nD(n;Bj&Ekg%y?sP+YVTH0s5cuB)fA~vRGAQgx7+|HU@%U= z;t$q7x`y_)t)NweXLy36l$J!PI&2Ih!!T(%EiWj<4Cap-AE?c3Q0IYOA0W zQ<`-1p!`r_v*F#THR{0G=x~~-xLDbgJZ->V%)8{++Fl&3;3|f%k$m?4-IOo>YcYFs zzWVdl=GFE5ed{c7eYP^$y`(y6*Yd0Qq!%USxb8Uf_%{=c_3+zcGh zUFCcO-2^N0C0n)j@_eIxb#}2iOYV2JN2l>xIn8ePPF+`S)mGsrC(%ukoON5P5U4_M zSj0x!MjkJvP;v=+VrHuVMTLfn-DLnxfwaZHqRvJhGArNGx>V$y)iUa#EEoyJ%=69h z%j3<_oW~mx3|>z+e=iEb)7NQeX(NQeO&rrjeG>8x> z0}I%U3I>t484EE=kvKrLJYgXJjBuOw@d6&z!GI&i3zdV*FEkfdY%xGH-t^oZvcHi zOE5F+uME$x8yK%?33ujjz=Y-1BTCLLSRA6xPN+fV%;cm#=Hw&4?Z%UP<&zHIttPJ@ zfGmDc`M+7KS^p7U`j>35jbG4B$PRgBepa&(vTd(PAyt&^4AA9UaVWeFaEAhH)1dW77w%?-~f}D(+vDUN>S4 zC@4A{W`_(k5EAT9!$JF$qwJvU7PeBJjc`(Nd2k0-E=JShDi8jDJX2P{6S0Y z$Hz=59qt_(pL(!No%-UPAi%OV;Lru7W)wOfS&jHWr<+k}ht;<1gj_!S^osl(Q*lo2(Ol$nN){ilhpmZF5jQNP8@TGQ%Dz4A4s}tDE)Gx;v^!$5);B}v- zSEfZbtN-ja1lP!qbfhvaA;3z>#|BpqbU{YG4q6EX&MSTDw^~(yv#WChhsw{Q#U4F+Ms2^G+ANMs)a~QpA(9B z-G}QuxX`dRLW#C6eX`Wz-sqr?Plg6@?S12~t zW<_N-o}8C%o$K0BwPKWb@y1bIiKDu5mUFFv5c%hJY2az-%^%_u<+}U~K@jRr|DuE|B*k$)^R-tVnso7{)y2lQa+d0Z0gR)vIMro{#x|NLjv=^>0 zs~b!F)K0a*r~C00mStFSHac7E5)IayWhq8*K2%+~`b8s)xIvb$Lc_pterEz%9z3@D zZ!?qz7`sq#>`lX0+lHxk8U?|C7lVyy$(doPL{0T^{VwAI&sKD`Mq7c+Ifguy&BJO@ zoLjv=+-)%D7PMMWwcOSpQ|I?^r0QFwe_c^mVhSs+H4gF68W3sKtsFs%P*hFCRqdqn zhJER{>VvGM0y~GIrt4fQx|g>P^QJ3t*ZjHYIdEWyQhVBM)XN8g8=SpkD&&sC>P8l9 zwF_8PE*@aRx_kyzZ>u7njRz}q8}ntVnRIQ|G&!T8`rNDcXSvWg^m^HYxg3IkgQYixf6u0CU<=siqt=SpRv6g^IzcB6?VDu}0gX zgz4hB!BgMcMKEmm>OQJ2G#QT-gYKX)2FVa-$ZUx=SR6Fp)j8ccuz90%ji-vWv9^Wb zsZ0|`EHwQ7rpc=3#tx|wPIl0L@CGY%VlUIjiP=8bxcnKhd6pJwbvS%OSlw#dk6^XM zwL{RKunLDPIv`m;Tz=!*lGn{D<$!z`tNQvlM=4_9<-xkyBDAxSOL!aD!i0*&Id(l$ zT~!OB2<|f7_z*ZYWt#Ia&@-Y0b){8Tb}fRb(&IC2Gpm@Nvfa2LXJV+a8D%So!kX5g zojPv2brssY6wI!Py7OKjIF_$DQHgo+{lLt>#BIY3KlZ@Pl1e`MNO5vs&n+@-6U)1^Y=*CL-c+3B;6Eppc zpJu6TMxWE`e2-MB9f`7{UE$F7V>2?G>X+BwtPN6g+`5%M`324JYj}n3e1&d*pyPge zYEsk47l_Yh+}WXb?qza^D$BX(Q*sOAW_p!fz?Fnh!`Lf-55xluIh*^^G2^e1@$9{3 z;#+gjPCe_;akJlJ;Hm$1ba%(V{+0v0`o08-G=q`!nN%$6d=}Y(|NuJPKL#hGq5fSXt?yuz6&6|EsRp+WRAw;T)p%v``w>d zwLwOAdxfRvz69yj5aP60dA5-iVo|B-m(RbK_P6_wVf1(>(_uPct@u5!cWVawJwhgQ z$MHPXqMSv{OX=`}tNqB}d7SPqdnrLi;H(qTxG+hARaee;Pp4o%^RH6lSW+^)z+J0O>g%Q4HH zcNJOXz_c1LQ|X+cyZl@EKDL$yuopO*CYCL|B~A)!%|)gaR*XbOh(BbZ$eJM9y1Y}( zPmcO0R2-f~xS?4ytUBg~)bH9#J55-j)!GR zyD18VS!vvHqNmN%pU+)<)1SK@13`~{jO@&{BaH0RI*)r>qo)fUnM7(fF`KBv<5MG- z8CY%VPQ{^cEB>_EONM|>Q8;X^`6VkrAlh_JA?=f0+f!N7gihV?y1;aL_05=x9KCj!x zs+!yO?gE?kZkk@(_V8pVsTf1S*{&0!rp@qA@LM?geh5KOUMo<1G9S8nlc?om*#6|w&zL{17KK}F2T3r*cu_^{FVgF3g$5>F;1d~6MxCa+&bq+b@MfibLhe(OB1HM>-ONPMya z|M(P|?>k5~I2KS}&mT73PkKKkr!wmHZA_qorEU`J_; zlF)`U6bVRTu@o*8a#fa=PAad2ZG~^5yA%}yjpO%!gByj%Gm~gwgSA$6((+T$sVx&j zJpjWYgTKbfQ^+@|!GrBD<>hx4N^+(h%WO7_=H*4t17?1hP0PTA;80{Mo<~F;U{C zA(-STmHZoXOe125>5S_z513)joNhBsax&qmm08jpo`(kj`nE&TAqi_q=5@_bIKujf zI!S_>MeGqE*9jv_?vL#RBkRva1&dF>9P@S3gde~7YyTLbgc+IX48(~YMRH$!;oiKEd3?ZRdN}3(f_Z4BozWYI$zU`z zepX6dY@5|)Mg>TmTYEg}tqLXc$uzE!1bzX0OGX7!71Ymq9Oo6pCESgd49GM(4Q$1d zk*kk?tJifzXN$FZD(jgtDZmz%4h^RnG>avbct);MmNZNeq#>+}{U|D-xWyI70rpaWaMQ6XwzSsah+f~RA*UuAKfYi$a{>G zr?0$Cb;j!IeypVhaRt?%H^rw)e%5h$8H$Q{8F->E4 zP=>t_^!#AHaEjjdu11d)lXo;dBOVNviS?Y7avx&0F39_OT*ILpd4x>(74+^*h*(8+ zXZCQsTZ8j~@X@Rw3=va#-R+>~1GXhKh_#K|g=J0Gyjajuk!m4bQCeAvngLUnAT>X5 zJ3LR5e|_UZ>LO;nV~v-!T2%G!pd@1Vq1to01DVF!482v7j6qXm$8d& z5~PtnlJriAc<4*=;Np<&ZU?3kMgE&(KxK|jMqlY0f1&S_$aP*?-@smJROe$um8ZUi z`20$lR#J6qX^xMbS%7`GRMdE?W@m0Ak3_Lv|y0z94qz0`U!&`K`%AyAzxU4(mzF8=v^lGQ6I zJ3*&kR&yr}T;{V2$E4-DK;w?PNY;}^VAPxgTxp&4;wjJ&HTsTMc4LWSYx6s^a6pFx zO1@#r*F7FNQvH3;y*sPoPfMsm3hKjHq@y}cd>A)QxqOe_7lYc-`+~N%0>R}9*7`>3H4?xdEW$)- zlyI^dbNU9a<7cU7HaO-L%e7c$nj-|m@pDmnAL ztd%M>Qh6W{jJCoq@}5O5FmoH~npD30a6`E1l~dUy1?C3T8FKACbF2{&)?uEOM0cNKY&lLWGih{X$fdOce41wv>D> z+{E9u4cx!M+ya5qu?#6aN<&q1r9kY+gZ$`XlI1+*;v;E=l?oy5@H8kA#&5_1Aw;N9 zH4YHr+}}G<$rHx;9a@(NAs)WzVt*>!Q^q7mkQ6z&?h}ukbw3S0>gx7}VFgGYEG(FA&0f<)9Pcvsp3(DvZBguMXsZ^qAIOIMpwNkebfC-PyH$X ztWhYcmZ~N3sSD*-5}coCr#w56IIRm6lBi!fUQv)HiKrxF8jlH8CflTL5+P!Wk?+vj z&`WPtn1=duUrSLW&uS#r=AhJ|o<|AZDOe&Mpw{P=c(o__q)W=92^C6hAV;c?FgAa! ztRmQg%tYO*3e|wjR~n2!wUeB9rAeAm6)Z-zBTss!xRY3m$7WrkAckHZAoO~iT&9n~ zvBFJdkb|r`)ZPPqAt_!0)`iR$(f`S@IT+`TQ43!-RP2juZ%x8+BNN|K#OPh;K(N0A zP`ZAsTD{1pI+8@Ik_QiOyiW@c3Hv|=&w#WyPWd+WXpkp7%hr7HyWV2rWQslta-> zOiayN%^K%(&H22#KHo^uVhI4AvOb{p#SZKp&D}Wq!JYycOHGXi$putSRU_wCQ>Ae< z1&?nfubzZIjMzCdWNAU*>lcJF)}^zy(?sX=cdpk}r&dRv0N&*2Gjcz+;Jd zg0Q<{{@k^88&h+>^B6Cg+d?4PugxHHEIuz>h7HS!DTI{M6Jp$UY%#nYbmMuIg9yQz zg85(8gIa7q(y2QfA{gPZb?eF<_R~)UN-TxeV%hg&gXn><`%pF`IKT;lYuPN*Lw==6 zk}gCdc{$nG2#N`D+wfj<2Eq8+N#mxpaZ^lsl(lX$P~&tZFe0{=-z4QL=D)&hG|{e? zq;sk%!u0A=X7;bO%}D*A(y8!{*WzJ+&&4CTO(bg077Nw3xND$LZ6T>-Kk@=de$;IXc&*ERNK!lfcsZwlU9XTl7LcK z!e_^EUw+cC)Nt(KD98?xw~=HM6`MdS$06a=gi%V#!xVl4E|W>rf+|NYTh$UO_IUOO z=jb&(m)H7ET(`;+>5eI!vWqhL#R(W=HTrDE+k=O|6|Jt;5{s>08b9n-nyRRdN=7HD zbTw5Soy;)D%~v)vPP1xT8kW_NYDi_mM7>D^Dh3MdWs+y-@$U;J)ipD<^@z=6rzU7` zypU0D%&LFxG<@m)HTo*f$R;949joCF7L9~F2UUE)oZn4&Wx4(SsKT2lw&p`QyXQPB z{Grt9B0HJ~Y$VlA!dP6@PlhC|w=|oX0G|fd6PdZeA5MYzSW1=w63Zo6&`<@H3^FN~ zESY}qlCv8J^38FgRI&$*&Sz}F22JFYs(_i+3|5pT#+7g)uuY*eXcZ;Yx$Jxxu=iVRo6cwvxBy zcJZUb28s$PQKv16opvvx17UZlKQ-&>YUjnl>qq&s1-X|h-c4sSDyJfKb?WPC+&nsE z$|o{b&?)t1j(;I27lj7WM0r}wly1^$ePt5t!9*e)?I{6{MLR+I#=?8*vho<#|$Y=14o*0h4j?;CqRce9jRsfdC`rK2ATk!6W`!*66Bo@|31VAEev=y2(8pSM@N;=al2iKQ#{f6saUmX!t2aXO^g zdT?PUPl@Du!Iia37?hKvM~n;u2zf;EmN?1HLYqes#(?+9TYp&xMRK6y%vXm3y)XHNUvzvRbIbGM8YAzR+ z)<|a~K4y{1nd?%>t?motWwmr|!I>v4CRZO9mStjroOJMltc-}}|4GX)rk`)AYc2dr z)Zh?rY2v*wBL7I?>~2_|V>{aionr0kt=Uj#XBJV+wP6CK-Uh$OvE`L3XT)^Ge>piS z6I`^^9{rdYv5P1BeI0AJIFjesR+oXhSCz4SQfjH(ix~gdq0~NjoB*H#Y(_^wo0Czx zND;&^shU_%8>PLey0^V|q%<3%qX0G6hH4_wN{W)AcCtpC=&UmnG7!=5!JMF1hA!1s zRaYl-3J|#V7xx-G-|ZwK4@c|W^v|mo1+_2%y^l;lDSj|Jgh)r?JVBCcdZOyIx z;5p!FwP^U2S|;W@QIt=k)60qDn+x@rt<+)0Dv93UZuoXa;9X^BQF0bSqn%wwcW1rw zu2NTR<^2=?!uZ14*ljUQ7BgwHtB8ii+Fiq5S%!sJ2fa{7aV~9(a4IL_3R*Oe{tZuTj2UOZUuP5p=!QEy$+{y~LlGg-ORj~ZmB)2Q-4@d2 zTtibJCP!@|Yr->!^3=CFyMPF%>oY4^z{}c@*V1?_O_$D=Z>v);Z@FZtXtfKQ^P^4I z`EzT~X_^lD9_{HK)QOTWE8Rv_Mh5 zd4(BC5rrZm`kUmG_h_d0aLTlTZ=i(Q`ASAb3_Dt8H?{Dhq9a(@|wP{M1#t}}b2byg!QK02d>*Kr*%S|IC+@9VU0 zO!6`~T%1jG0>zrhL@oR=0U$Ozo=mAO_dKJ2L*W?4Sy$OoNthV*0v@l@m@`&0Y*`;j z1~v+uB==N9@Fw>?bIQV-aLmR@Eto7I_6bVWKEv5ND&vB7PQPke7KMd^3)WQDl_))^xnBcJ7d5vErpsAyI2*Opq4 z8wGW^-gtf~1IFofYsmeC1DvrP#SKwTE@CwA(w?0nsoR2uFnu%;aS;?Lmc=#2N;WO3 zU$Z!JliK*TFWv)SGIcUl%;^>89*yBKVe~(>YspV6ZqIIcE|9`)6tvQ9vZI>A@M6sO z#`!e%>YveHR9~J1w@kP2wvg~IZ=bWT`jG$$Pgd{eAGE%k2cg}sJINn_r(>*+?zt(n z7prMegLeMx{hxR@{d9lvcF$Bc6>igC>vBi3|u9P?vxB6yKdTyVsG9;Seu_|dFMAl%i9OyPrmMW zs!0teJsgi?^f&+^C>39Mwz@Eo0g`u#oCH(1#wxk+79o8_GI zytSn*at!RG&VvAb#eXap^re1A4lkxo{Kw&DAnPaJ&DJzX_6A#0vPTtdpxzJD_FulV=)9=Vsp|+(A|NuH+rAm7uqgo zFvE1W;zcA7b!cnAhI@+!9v@#WxK!%#`-AfXuZh5(l52rcWYVw3vlb2E@Y6cV;*F-1fld zxv=n1jZI&aICr)0;Wt}hPq)Y)A*|wB$j@oB)5VzcIMepF^DL~MQPFX5tk9acQ}s&s z)rgHvW2F3@H9GF1EksvSkQm@pkX&6b92+E>W*_7SR8Kc_QJe}Y^n@@;;r?QG_O&q0 zAlVtd_cLsCyzeKMZ7rECn9(swK0YkR9Q9k>5j>T!7LtK1g=E;6NDIfQ@uHznadVa= zaPk8`R0#s{l*}RQHI*3|S(E29Ib|cpp#lz|2B;u~fi87dv&&-3S7MU#^j{|zBjfXc zB;sF}azN{&alIVBWloAm)?F7|2VMge7_d@h8Hwp}NVP%5&NB=fL^(56r$DDf2~!*n zB}hhXz*Zm!AW88tcYsKA-*+;Qeni>NLM{a>XJm_{MCc`oQA8^r2NzNSuZDCLBmKOp zG?DzzAjW%K$i{V7qmdO|7p~;ow zR`R+`xt7-lh3EK;9K5scK1TS$n%0Y3Cd7-}GZ+mP`%G|I8!Cir9V*VZuc+J>R~sPQ zXP!S2Pl0N}c%dE(Urravw;e(o|skp<-q#H@ZU(mPD*pB2TG+ zs~>3ss(!Pu*mK9>`1_Fr1=GzJ*Z0sd(sAm{LeH`s$S5wzqfE??1RGM9A-2!*xWL6W zjf>QF)2^6@6@v>{h@U8+5@h9xSTaD`Fv|uu+D7b3avTKlAsbQ6aJ|>4;m9`)V)^{Q zv+)x0U8v)Lday|*F@mzh;56KfJNdeuFk!e*ny2_H6EAg_)R?ybPK$Q?^crQF@f`8{ zyuj~Byh}iPN)_A#Rkrc7xR~onZ1EMQ&dKGhiA+uw8w2b4YF(+^cPH4#v25jM1JdGz ziAJ!Cd4JWt=_eMOw1qS+g$pu8S$;B${UnCt2#km_0mKj%j_ET)VD$_wkf z(vf)>>846_(KOIi7aD4!Db|KUnc_3bK`|<0|-A zCKqmQniRXXhfE<*1pMgH-`3t1!e9TvFxf>1d_;I7so^f8i(c5iY=jR>_%pKemwre5yT*=QhsOagn9*vxj)#uhe zL>H1u$-Y^x*(6WmY3XUM`m9yt$y>QxwBbiamT%@mnbJ=8q}ogB{CwU(|MfSK&(WCfQUi58d^%Vb#dh=3lnVw_5P zh?~u!K>;;o&*v~_~X4DKqS!E!)2!^3J zX2za@Wukms1b;gA*=1ZQk#}qd4` zmtEcqo{&{P4pt?f=g6Ig;&gbL%D93cf18B@xPCQ+EdJ;zNYcuXuk0hXtdK>_xGF{Q zy$p8CxGF=*a_MW%u+K(uuKaey5ha?(8C{kb|=bWOJ$ zNzO1(F7%?0Ec#fYzf6;E)`hYz+kmGso`uf>Ce9rEF`BIG5rM;J( z`9VDONf7DD&eSt`T_-~kCRnx-78W)xL-DmuSridNuCI~g9WETi_@xZ;Y369g%8~k2 zFYt6B2!)aiyO{V>DfTlF=%;X@&5p|y@h#k3k1#=0-vRGz)ITdS0CqK=D^^kp zS3V64G)&&al5K{{rasAb=VJee3%)MN*ffbINhsn)@tcylWcW07KRBkgqj**9Wuk{h zR;~sSg{PGAGFo5=VF_GsCDZ&UA~39bEiv);ZXsQsIo7o4Osw#{=XWt>ggAxKFwPuu z!ON6gca1I_JcN$+3%RFav61xx;(ZcoIkm0plP=NcgxVIT5~r2x^dd8st@f_-Wqy^V zux55^58qeqTetC$3HB*HAG>z?W)Cr~(`JansE>Ip&5m}~a_`YdXS2cZHt_}$;01+E zr_D^-D;H?*3mh}?bBTl(wI*>$eSa(b@ZE#X*ysHgCcO#QJ>Pzz=`O*RnyrB->_$=p zAdF60J(XVzx2M9W9!k1^`2ZH11(zX{#euiz3yO_?ad(D>gm`q?#Oy9;7&(eX9#Lvu zSQsVzua)yMAI=p~QI!n#8M@G*<@S_@-xChMwNxkx5?i*y8{!k-EdaNe7RyoqZldnUz;#ger1MytFu9jwTaVMK znbZmMGWix73$$T$45pxFNXVw;%N?Cd;RrjE02|=SRF}%Ps=CzxLvN5DZD)fkmu8=& z>D{q#E7Fd|27}hh9n*DZlKxe}n_y|N`WJ3LV|o3ll^i(HZ(5NQZe8`?ShQJHW8akB z{Kmuj*$SFVv@q^LUv5F=w^_vz>%@+Kt&9tqSQGTK6GEFZX z@7Zjx;D#iw<|zS98G=iQIfZg;?MMcqAP#dT1!3`6O3JLrll#Dq8bX?3dZqy~s}{;{ z^1d;PqIYV>P}t}7c!-a8b6!o48*Qa2HchBMbI%t=ha=8;iPlV z*O43JOb(y-r4V9TJwG@5leD+$&-3=o%B`n~Ny-hS81Dz^rKQ95`?+3ztI0OID(aH< z*QmAkh&o1%@3+adomyd5ImD;g`6a)Z$CI%f^E4~LI{ZVXNt`W(*WvRblYgA^!EK=h z(j9@rqe^L_@)PI~6(d!(YNohuIT*ok8 zBSgKytajI4XA%i>gAXT9ac8d)2Zbt#YpTxocepSE74zG9LV1gM*G&;vyg=5gD$IG| zqXO5muy_$LG=3RI*?ubt8mxh9LG}mnX9hEMRqv6_PsJqPDQeC3PUnefa5p`Zn_8J$ zA?(XeV9aDZaa~i&vs&+IY|Tv?)FQtA!s6k`>*S)paNJWVy0OT;t{U1Ol|h$)eKJnI z`1W=^cQ?6g@siKw&JW?`%%HVYmOr!Jr0vOqVLK6`(z-oHJ6ZUk?LK|o5)=;KZq$^& zQ2UFJ!@0GU3&LzP8RMXOy!iRqK%7CyUhqH?omUL&;-YaEH#cwhA z61E%Z!%KZWSfIF`KP@B^Q}ad$FO$0$cb7)HD#*VdHY3A-!UyRGAatjbp#$j$M*o%Y z_vku4kaV5m$l4}CbS*AS;|?C!bAytI{tm|0%;LV95b%7apPFby?69K-Jp%89umJe} zIED(?enD11(sNbXXNhKmOr;ifbx0-tAmJM+>}BZA1VcxKtGzVt2)YXaE|s&z_nW?L zW$Nt#Iz5CKlr{WNy$X1o9Z;$cR57r=?#ezu@2VOe)}?`rcUj>{Y|RfOW({1NIg!Sg zdINV++_?`9N3s`4nUlR=_dSngJ@LbguJ1W=1K4LOU&en*d5WB)VCzGG#k1D<6|K6w z>$PnIRPgM;Zen6cQcj6cYlY{tTl|XSzksvZhJ#1TWw4Yat}J~z>?0n@S042|r3yhr zARCnWV_8Qp-nbmX>o>2ga8`QW^z6VHRUjgDxjL{x!^3l&h|5BgM!ITu9O|8b!xhFR znc5eTNZId(aQ$M2^l#7?VB&fB*38S;okP(oU7EsZBlNI<+ZSEVP1O`qELUD7ovxs2 zd}!O|nO)i9EUIZDbALiR*K&ShWhB0{9QsDJ;|mm$9N}>kl~`46?v94f372e^SpkG> zYIn4!m@@Mj3C?5=g8Aivb|b5+5|e2Tpb;%_^JjwxV!aKZ-Fg0oYphz0-!!1VU-Yz6 zy17H^`*H5^creq^@e&S48NP%squ>lRgW5U9+PQT|tnw}~`h1ND`A{PkCIaUeEZ|!Pb^Xe2JmIOyfUEau!_9H8+%phtkcG@*VqlZ zbr$H(0h8SCi|n(_yQd$0zZTY{FdoO-&Ye|Ge?Y%Zo-?aX-4`d&%2}^2rlc!$l4<&! z=2;vkvO_%{HgE7%ds>;b4x|?^xFplPKO~(16JOJl;9bzMp3fju8#fyp^!LRD_GUXw z*jp1!RJvZEw>~IgzL|=xCXBED&^igCt#@3w*RPWm)i5Nc+a(7meocp~S%jd4nl{uh z$ZZ@wAGHFuu1Zf|$ycAw-k-E6;vTWs&Jn5fS_)LMaIY0<;5e#soMz%+nLuQaXU>n# zs}wVvKep@8C49S(#jah2jJvL546vAcZl7Gq-R#i}S2mG0JKui0 zoe_80gIwbE(e8GEL*>N(p7! z9?P6b{M&=3KWE?&RgF43DJ^sOs<&hU0%4MiW}w#6h(a9hfpq~eQ4$!LY|7!9Hb-wB zh0{bBP%tW>SS$3ZqiFW*a((vU$Hv$``WG1r~1^=f#QXD7(d-t33 zvv_xWM2GLeYbl0kmcLt$;a#Y_1IA-#xzpv2rKtQN32RHSm4csfEwvl<2D{uEZ-s_CD1K)d}rxM0n)phw^=C)%<>kZ~k|$*k&QP^Aq_>tOpLVwU)RRTZt;(DfF#W zl&PA*z_hx(FBM^X0hCL-$gSMJvemoq?B$FnyXw>1qpRqDi*%;2K2@qE`P>$chvKAT zu%B&AYbP)|IY>BLz0OD8gv|9>ahs--yf`1q)U)AKY(2%lYK=9++BvE&Oiny~9GS&T zao2EHn~Y|7(f4rAB~Lt{ReI*M=V@IV&sUUZA~mB~#koqC1XQb0HIu=S&MX=u8vf9u zKte{zG#!o27{`OV?07J5i909GpEpr;E~!t28`UA3G;h(}dxH?8W2EJo9PE%jmsWlp zMRlFyx!T2Ly?^Yiw`#DVEz1e1xm~CBka=g#-$HgpeZbLf*h!^j7Td&djZDA;usKO+ zP@NRG#m>D!e-IMIS&}|QgSC@B(IN=(9BoTXXcR0yQlQTHBq;Xzi9Jdog%5NRp@kgU z7vSPX%BL<&A=i?EMJ(-7Ua1qI%OSt_`sCYOJ^5U5oa5R2C`Ra=%by4}Y`bc2xy%w- zA2n{u8$;z^&sj)|l=gGsR?HU?HD|A4v}JT0f~(8WHw=&`GsI%BYRDsY1qpu=m~D-` z!}n@KunV3{w0bccoHBvy8 z2;TWzFBpb~a(9YRaLp9o+!SjR^m|FD2YGAb$t%$x&EiXt4!<^jCBO_6C6+K7`i5pl zfn$@HBVQJ0o&<(9N;ZRI(bOR6DebBAl7Gi8VT|C%mz;p3g8!8@6(w)5W$(H_K-LF$ zEM*kaq%V~M-7JB^(tv=~E*ZAZ}Z_W0I;-$NDq|xudFyRqGs- zo8zSltXk4uGtf@LJ{ydi^e9=s6%2-?Btbt7Oc$!cTwCHQ3=ChK0rR5<8gPZ?4)jk3 z!jq8D~mpMJ4w-18ov9vDgcYeZJv}v1)put`_}6Isu!4DI7!I7={q`n z4b72rO*vh4&5-;l2YuomQst+be=BwVp+w7ezz9`-y&YNUT-H{k8ETUsox&4#ol^Qd zZgoQY6&GSRwm5Wa%SD6!xe}3nDl!y^VCnQF}@EH<2P8-3{ECELv1I0h3-4KPylyhh2h+FvTu_? zf`1{1;^k|0F_$GosG2X$Sqb1{7{cw-)!j^sfB8Bj|9mYuX8mPDMkG?M)-2U-@ELp* zA;B6wPqaCf8)_qsH9>@(^U{7+B&iX-Ona$d|7OYbUE+I>)4}V@R?wE zSrcycFa!IRQ}AnNZ%%(hFN}Q;jP7N^zHVrqR5(|lfF8h40YaGkv_w{H_7w#i*dA}; z=xE5q&Od};NG_qU-ySEwevIWb@Ppy-oWDmA8FD}mG-o&DnS!iCPY)`>bdr(2!7-~L zE;Ah&#!9oO34evb=wVu`eF?9-lJ&@e%C(R!e%l3VO?sds|)v(nt&F zsuE^0_BoHkuPSSE@nE^0*_VmBeYCT5O6sg}=-r?$7IW)n@?6e$PMGL2F*r)<>Z7GL z)yU`0(ot$?-+k5pu#GRbl+iIY(wfi#taX=^>p$zjc=_FI6S+GKy$n$@FXCEXY^68q z$Gmv=d$nXo*QCIUtB}lOredI(cuAtBghJT)duU9g#Eoz2#iK>8&WED%DViF*$l@)2 zd5hl%;;wX&@Os6D*CPinifKL%;H(YpE3RsOP>ENpER;NzfGN3({%0qyPY zofD9Srh}hF2)uGcgontbYoQZ=&S4ctiO;3<&<&qU+jaisUdV8e4m{ms)t@FQB75N= zPc~q9aY)B(MIDOTLg-5uaHoPC4y@6`gz0M{xC6`Ogj5k2f$h@^ywXIJEq_0Q?rR{p zQr|0;cvOG;nTDrNY{0ol;GM_z>ex}qk61u}Glv({Z4vOR^c9n1RMVAvg6)q*?-+7p=wX*YVMf2RjByiTfT%3d^4)XT- z*GO$UR+6f&7H3V3p5zZ?o~eM;g}g6}@f&Ltk?))B*E1#4KaR2tY*HBKb>QGN)+3!Oh1fmH-y^NQy1&2HpoMM5u0uM(lxk7g0I zyboYg#;m=1{#vDSjN1DC-t7DogHJYj;WP3wOF1>s435pF>fkY4ZTiT=B##7md@92F zyskduOqcrQnopWmF|n{{c{zV$@hvu%JB~#Vyp%t0DbH6U!;U=SmQ_3t9uvAa9XkRf ziGK>y82uJ|cImWKcWT^D)~SC^inUKIf6nRbX|_kt&D)||z~4@Km?k>du(#8Zf9wWa zjKhy~h|g zqsr^AT5Q%NKt7`pCQH62^79&BPON%QK6EKO59^IYCgWEv2nFlMvD9_d zwrq1)U)kM}Bo7-ga>1NWojYFeP&IrI!e3tE_Yo_LbsCayl-bf1keMB1T)>dkLEeYL zQ!v`|-FGX=+1>FR_C%+Wn{0!9Ux)JnpEEHcK{-gsHetD_nl4}1bGWNF($nJ;Pi+t! zl6UW(P%@;5o&}+PLX{&QN$nT!vj-EyC)2;c-Qdo{q}sJ4@y3@h3(KAA&2^WX*-5t- zkPr?KzV~~!3HsIhHfI@KpD0hsjyRvpt;={yOzEbDp%bR<2^&s**1T2(3tI^a8U|*h zq^M{6i<0H-rUutTHP9QxX5x~6@mhil8lOI?&@2G!Xs{k_ghHRzLM#tMCd^~I_#yBO zOO^LS5AHGA<_apwBU249iO$W%!_W&NAVNSK{3u3eB^;&k%H!DPRth&)_wigTR((Y; zGdguX(z^QdVR)S1_aYqfk#=ZoWTqA&B%6?q*I1derO&0_syV`{S;&fNUvZjb8M%Zm zkymap^{j!6ocnr@WYm#~7E|_vBDD>;<9#z|ED6L0B9LTD5hZ`@ z8&|Kvd_xc4pp;ZqNVp;nliay84_c;u2-8k((J9CyA{8A}E}qNCNT5Rw8X$EUzpSpGiTF5QE=MNk{yxuO z-o(1<`AJJF5z~ERZ21}A-H86cyOOP}tQ|XIQN@?dN$)fH zva+fFSgTugc+%TGb(tRGt{dR~fzY6IGm@R)?ReLr?H5#IIZ`ahlWK9U}D zpF+8(E;RICb6ef7ac#ut0UbFtkD~#D2Oc)X=I?H4m_RVwZgDWgoJ9x%TsJyAL{H)UGy57x%r zQaNWrVfzNWFZobSvEUwS@l040AR~77k>aEoYB_-QFSnk$)eeT`CsNOBOj%_4NaJ|3 z{kWxVVD5&sWXqi^94n}r1C7zX3@_S(7zB0I(&vU6O`wn*DNH+flJ*BCgZca<%0%YonzqpE;sD9-zh zfH2ctqI=_ZE^B3SmS7Geqo~MReOKi{U5&BDkTH@Z3l?%iDe=0K(kHG0!G{5Pu{FNp z%$glEbFZu38M}^`w<9;PshAI!o6lSR4}64ZB(49B ze9%tLjwS{+(C&X&HfSsmHf1RH|E@Ii|1SLpt@)Sq^XH$Ei=nfJy~#hq|DDSAKZrm7 zA8E}{hj}F{1azo_(#s4*xxu4)8E*iIR`WIKjI7w|JwIw{ZB3f!#~D|IhJH-k-XEuJ`AsL!d+Ohh#FbHU9Gm{Nv&I=fm(1kBNYhf%7lj^nZUR zbQ0F0(-{!?w{FpV*ZC@b@_utIR4JfRDdf4!D|!d%Arr9#LAr_Urhk%Fw25=%T+T{m z{$}>tUo5mWLH5cAH^DerbpFCHIA))jW`5#+@)G4j<~&i6(3S4QYFlS=eeIgM_dMMk zgk&0WTEZMP>PzECck9e7hu<$hj6gQv+WBb%?QrrE@A1+I;Jd)9-g_d?G6JOAv|+r) z`qsZETfS*#=8r07915wEx!j(6XnfcWO|5;8lCmz%#T4v_R6!{&0}M{Axwg6G_0=);z7%2mAD6l3m1k;iZ6AN0HHle!%a(m z63I_+L9j;tmiMPY%~dNg(TN+e#Uu_I%q0m@356^bg4&U1L4*fyRL7CL(ZCTl+9g=l z#DT69!99vlf#5Q5pkU>O7s(vi*)APi5$06L2)c4Q5lhDL)rIN?@;W|2;W|HYPSm`# zHm(ald1QuV4=*l^?^D`8{pR|iCp(4Xn-`p29F*tF0qL8S74|ZN(JN<oZyFl8l;<2X?T-{N(07wK^_?r^0^K9yQLnW1w%e>`^A zcH(t>X?MI=*~BskEF>tNw#%K#`_lY)E(vgdy3x%v@RJaIx=&G$X&=U%*Dki;^qsXx zp3J--IDUEJU>i2jRx6y+gH@DJ`0q~1f4P|dc}o6|9-6>^@zDONV0O07f`WGL1X{FA z49x$8&{!D=I2jrK%|T=S>ze(a95hbGzlZVv#Gw66P;xf0QT@kM#=^;3C3{PR)yTkZdbpjC8u zc`Gk8a&#?i9*&QviXDtokM6TFr*@bzIgP}!$Kw!Sl8F-VfAv5_X5jfM{uPP>fs}#( zETIHdMBZG4y6Zb4Qbbb2y`@c~<3iI?^#gFts&k1dWKHT_l{9{9(~PX6;obZ52`DUA3=9i8lud|Sq008FR{8BW44#wPB))9oGkBd!P|?8 zyv?-pdZJN~qz$u=Kh`idSEL>Y;B3l&^l^AC(OhKueU}jvcSD$Xr8R5_IF2yEKj&RC z$hc$Q&&j!aoW!6!9Lk=VoC#%>S}=Gi6HqS=Sk}=&%M2*8{E?qIGnQ6({btq8`6M;4 zD*UA3nMggw=1aHR!q*Vh#eH=9#dD(YnY-mvc&bOsJXV+6Vw1=7Tz)GCEJ=07@q@M@ zvZ&b+^11@PGikOwKo`Pdg_$OXmvVFN&NH)bB7ce*wK}FK-kd9wZ)}fa{w|Dy_MC-R ze2&?CgPa04{rYl-C+!oq6Z*J4t8k~XcI(P6DoT-KF*^JAjHj&R5_6ejL+pLj!Lzw1 zrB^XSee0ouS_Yk{n;XxDV708K+t>cyqyEc0jY!ifyEA|~{x%=DZqDzoHr-h|X;1F? zoDAucXSM@#8i;ZDGniy@SN+a91|PT|xXu{e;49OfzkT~-%K25DAq0)|>YA+{k9h7r zPwAUnrzP&VxPHKI$v1#*$Xrfs#k!%tf8{MMfX{jTgj!XbslT4rZNT4nMA%8n_oB=q zZg{uqmQ8EN*|rpWUu&#vjC6J@q-^*{hG`5JL#LTWeWp35bjw5RkvhEG}#Pgv@>5s@#?c~g!o zA8Qj#3<+qZm6ncmIG(k@;52lnb!t}%BL}mvD4ofqQB?&kTUJ3qPfbgiMeytsve~ho zaYo}-G!|#g8a4zLBui~RPnAXdJ+^rf_rzJ$k&9S6nj44C`11b&0zm!0?u9gC;dL3E z5hu+G-3SwLb}C@b8zE&1x#T8DIR+_Tg#^(#2~8^WI&0m|$h$Re=V@r2)lAd(*SK4p zkqb(Cx{~H{lotbiak*#>XKnJb8fOGLowbqBx@Cj4oi!BSah-Omd+K6sp%)$3>S$6& zQ;|G(?{Ubh0wsa-YAcRoq%p8&BP6?aVOOMKR&#Als>{_<=&g$+xNDRmG*v+vQB94g z6_n0yMmpN%JnkJH+c$-@KvhIJ!m#L z%l$11tdmkz*VXNe@Huo?Xszoj(3Qff42sH2!dJ1!g;d%=j>+sScT+SBPp!MQGyZ?w zvSfvn^G$AjH&r$7h$xmx6?4(oFU8782#P9BnSlv^u&L<3rt8=LFrxa()NHkZW- zi4`z(Tz2hEXxz=IF*J0^MKswOXERPEEfi3s8O{(*xTj2__lP=MLobmIxRT43>Xb>& zW=KWj(3FfwzO#05O&pHB-++{7%V}zO9Gi;0Qan?`sje1R>{sZ;wAdMMnAXs+K@E== zk!;EdXdb3$lq@!u$!yI#o861uE$(H`h}_W3`o@Mw8Rht3C}SRjyV7O?kii8osHxZoJqzsBzcN8Dz-aafFCcUKc@Z3Cm@sRORbu-?KZk zkbcDUi&nnp!Q-;bzU5`?vmJETbq%`bG*42XDF?YLbpvb5jOwAjaY~_=GP5bi-LPZU zaT#{ZX>ER0q^iq~#^w_k@YK#JEyuHHS@Ww-Dl3#+%yL;KdvUTChG{l^(J1h#ugVAw zD5ac|p}gOA8jzBw8P5ZB+i4uj6UXx~&EsNuvXaMsbe58r(J`j{yVlvo=4VsOvcb+4 zw#HE+9TEB;BH*r~qvNhR4p^m+Xx)paM0D;cEWeuNSI6>IEMHAm1|&kEcf+7q>;7AE zAv!L|KLs@<$)Vg20Vh8I!=rF)6woMWXMPLLZ{cqZd5*t^@*MvYDsWs1c^n-VH($iY zi!(2FT-3L=ID~Db=_KLdq#NiW>6U2A|hF*rq%V2yNG{%>zU%L1b8Hfx; za3nGuITs=RW7Ws-;TIw=;Ncg}y@37CS3i#rJqN?jo_iM0Ji6y7_8;vzdiLnpQSRV@ zEJwou=-CHn_rbnUy5k3XlN_7(?%6xGmq-uF58{Cbp?A-~9z3)MhWDJ?gJ(RX6+2QOxyc?#Zc+zGlZy7ala_VRYkp{gqpdaU zXr)g}k-3SdW5N}YrXB)DQcdv1S!1)XJgc}YB+tsu3%w^dHb7m-=?GJt)97_91m{B+ zLwFzriAA<16BwJsB4ZO(N16bE!(ps8b{IDsIit~UoN4Sa?lGP>jv3X}H1DF3^dJ~W z1RhSq(DBAO9#8#g^%xaz>V~!m?1*H~VRv~}Yecmpf|^>}nvVlK(6a6R`_Yv2`bg27 z=16CHOMRq^CS;Zvpb0Vkcp{q8(%;v=*28`fOQ3#_r>~EtfW3KQWl9P>eYBW@_4W7B zm;SY=&(qfreSQ6?ub<}k!2+7@>toq{Kx@#e&l5vWF;K({C<1!xkD>1CqwsySeqZu} zYg%ISP1jzkk5X$8k5J9=2-W`YqqjX08H7@(^_EKOrO{^^g~`w(hhYbBzF3PRFEYV^=HifH=*+D?GtpGYm(Qi{KnS|VjsXRn|zRg~5$+Ez8S zcI9MxeS*+bny#VsYW@wOX+sEwX}w!09rg3+Mbo#^{!agIgl5pTW>PD9RvJRHsg6B| z($+}nXryILv`=%Xc`}#wWgg9&_e+FYD7~$ed9~8^+Z1b?5{jA4io5tGYE`L`?>Hd; zq!VgRbD`+CivMKN34&=79VaZCXW1vzD&fkc6TtEVCYLGOWpdSEXEX~QjV|MxzIm>O zdzTp$s145HnYfqYb;(vl8DK9a7@;$V;61>80NPUf>I>law@;8P#V%VLT!wRp4=Xe= zvv)SN>(s~!X8AWu@H)I5lO>jQmhBeO4eMbikZ$XG>rN}_Q{Ah=i&e0R-_7IYJZzw5 z2emL;sAWOcl5GT+khx?DA*~#QIcQSDG&NW-0V}epvQ@<@qEf+Us;^Wyg)iVMcp~ud zIsY|}RlLE#rJw>-frxpuK&yzdg{tdbKG)M}sBI z{Mqd=u6ODiqlG2SQ zu@MeNyZ9~NZ02y@?5Tx3@2i=e7o9-oXWQ79PiQjbLSTY~+S|co&A@@8DqL&|uw;_kM~dAE z#GUD*Sx}KQv8h^KT9`N}4n}HHgChC_f*E@GQaevy@G`ucxdm>(M-f71B^iS(Cr?={{PDmB7j!)&O5@y9% zji$*%Mlfa#NLi4@`f1H@htFq$eVRi98f$}A%!p45Xkb#L7Ao zU9^kp@&3gZB$xipUsj*kI2rzQ_bY45UeB#xSyS6HBi}o{yQ;Q#Mgh)q&L{`RJ81tLs7lTgZITV!Y%aYcG|YTkB9hPu zx`cQQvgcV6!*;z{R2z{ERaaLB-u1+1gE55(Qh<$pZXko$0&F@GlWabSO~nJT&w>!( zES`#n^29uyS<0xISDHeqGN(-SQ#@aG+s;{|?=ae^G~ynl{8d2R zuOd7)e9Dj<##p6cBUz!=hcy}<@U2KCs$>;Wt0Wz89Tx$NPz^n>84kfQ%EZruMgwwE zMi_uc9csc;&Q^WFT<-TU;*~E!>4Jx4O_0FkvbpH$aoJ!gF<<%1S@Jper_sw#jQ$J1 zD>58T|%4&jqsOve4d90Kg{DpJoNGdJT~$U9$(^t=JSmB z)XePgOdiH!#l!qLeuSqWRM;qEOZjd4Y7brF%8w25nhR`z1E#@~{5#)FWb1M#r6Z`& zp+<|D6a7if;7`Ta1 zBmm9ljhqe5p_I^7Nh!HT$C@>!*r-tk!en8v!rg&Z7)W%ct#i z14>kQ#RVp*7{Tn@@-X>Db36)TFDgp8P~@lb%G2(l+?~(NDV|t`tD!jlajA2a1#F8m zKO5tTbZJwDpG!ZvAgB|F&6)^LJb7f+z0b`1-?WN(l@lAQa#XKr%a$Hk_0De!DvcQl znNxEDb-rYxO0S*2);)JiQ^CJXxudnX!}|Qb6+35SV6JlNf{IjQ?$m%uUNOUS=6KZC zFpDF-8ck~Htdfb1mCpOB7xfpna9}EGt!wU#f2-s#bX>C;f6W{lQTS^%<*x`1p)oq} zxdTX%cO$vna4r~gVIVH=7=N|vL&F9@2GJlHMhuq>yvD#pplC4~*s6<(!0+X+uIt(A z4PQB9x}^M{$v^z!xbz#npUk;g`aRe+>W|3|foi|o>9_9V=E-&Iy|C5<8}TlT>oD}| zx9V|74;wNDGjLr-OGbAFS?k#5z|$P_97`SKfkJ32Tv52OkZcj5OY9eMlL+86n8JqB zbdbhq;$8%65!9eY)P+b1g53$QApzr#;cLJ) zI!(ohs1SUHzCzSI%H5a?{fS$txK`)psuPJZrLdr|qL2_xA^dmY-wSc!$3A$^2WNb6 z%m)X2u*U}*ebD2BHXqFN0iNmG<2&XfKG~iYcKReAHu^yD@gn?5{F{hRiEoO(6A2MD z#xmob#vR5-ji-$&y-}9O>^WiM9nvGx?Ns@9UtdgKqS}NTk{aAWMdQ18* z>HkWa90}A?l7!!Wi$edGMDCOxm7bAKOI)`Ec~Y6wED<{cf&Z4^BMF|7ektMo5)4Yv zEG?689YYBkDOtk*CBZKx_;KtlPYO#rB!2%}F}NKHR=$qm1VOS(_}`@emhi77cuaa$ z`iVq#Ngxex+8i#Ipg;oJqE>>hCHS+_=&vL=Ex}G{zjTxl2$Zx6=@zL~BKZ=eNT8Qs z*{B3xO7I5>-jP5adtHL(BseGm#k)y@6%x#spk9JW5_lv?lRziI6$!qO;1dZb6|arM zqx&V;EWzy(bVx8=0>4x(;dBX%63`YdDlNPx0mXkzg2yG;!(i`{aGL^MDM6tGsS+3@ zDEn4|3le-R!MhTik>CXh4oE=JZ&c9NOKlP^SIDs|#4! zlz>%mNK|!~HcN-3v(kBKOj02_=r!s_HCAU75+li#jfoo*chQCC6cWOTkU%A1AmC{? z1*($*?LbwHj@7H_|LcBhZu~8{NwXgZ>-c`~8{rv%=PJ~K>+7$+2F~6T;nKm34VvR= zzm6noX>_bMCsCt=8e)|2xaINP1m#xoW<8#ph<3S&4{~#IRq6y#GsDD^0ZEBTC8brQ z)IwhfeWCoFruqN+^s>&b)$0v7L6b# zryIY1i)_wW<}WR;D3zAvT-m~Jxw55t(}aqNwNuloCY2_U+pj#FR9ab;HZ@ecZ2d&C zd0a*&Q(m4%*~ALj*XmyG#;qC4GjJ1GOs&~EK}ek@JJMk&9ny0Lve7h$2~1MVno(G~ zg^EFqhDQzA*}StMQREvEVwxnAd8Tqdc$my9igWQIKV{_Y%$89!$CA<{X1-t(6?}|~ zr$cT`TT_G8UALxT?fv#AOu;4lS6=$|)~%7Q9k2BGe_|ZEukg0U3J(5n)1IZ}3&Mqk zZFPRgfRsl+*jm|q;QbBBgU>yle#_=XC@!m1ZrZ;}{PR~)!Pv-48eQ0_uw$CYtfbnC z!58|-|Fs{V@f1*F+Cu%>HUvC;fWk@uX z7#LHg^6T3mydC@~_<4|=3Bvv$>!B>NC2YFgN{Tf6J32O>pZRoBb{rH0Q!M5OvAm<1I z$C~&eh>r!&1~Dz)9K4}e7lg;g7#evD&If^_ImXZ&2;$9*m=!@hGYFMI$WlOQYgd5| zFkE|rxGMmnnS&@NnN6`l)z93-^TiXco>Dj9=Neuid#8zhH=(9f#G`bJ{Sv9@U0 z5eCe%HwHP1=v)wRXK*NZI5-^SXzNlC{6RpnB?y|#;)Xmiu73Dq`iG)`FdZbuJvtPg za3eptk=@*sdov@tuDIhn?B+YHY;{cY@h`ZVt9(f1%sT!j3Q%HF;CqZuf~bB|T0VcW z`=x6tQF2-RLV4q!G?F~2p-Y~9$E{f>#-aY1lC)^WHB~7F=V`oq&glL08(TK^CBL5E zhjP&i@=WF~z-tZL40vPqu57$K2R3Ex&ce&HV0jvID76wONMD|gwB!) z?~-e`oLM{jzT4-z4(9Yea(3Nw(XkiiwjBd>0<+WR*^Qa9!9p#`3v{x3p%hs3S?t=9Nczf2q zES$x-l0~fz*Ew1oxK7=o#@oq0I$}Ck;$UGlq~TijsIq!uu z-bq7~uwxR8O@iS`Ba?8Nw;@wZG#XPiB@KMc7Ev^7wx|?i?m|(~xRuXD6uZEhKvzyq zuA45a@2c3}HTv_~_xJX{=%WTBfTDE2NUdwa+2z@bt9$pi=e?d>x#*Tj%V+v>>Q;v8 zZ>vnknH$gTYijPoPN_0I+QO@H!<7XB$qH1YOsw;yz8^h~@P_ok^vBXkcRD0i6~h^|Curz;(iBgcR-5+LJqJyfU40NhuNe6np7@O zxpG`3u8?bqYn^Mm>uJ|1*PE`-Twl5LZ?QXeDH}5%eI9^fhk;^U^aly}B@4N6x7aVrMJ+6mbxZeexE|}t)?ZOjX;B*0YnO*o(*JT%0 zK##aiy08M-D1aT0EBl=D`MlOb+ z!NoPW23$j~VHf9j0dk2htfn)KoEavgzJX6=N=bk!Xr_R|+2hRkJF4O}jq)F8lHbqc zl~)f-_{#!u?%iG%FqczZG1*U>rC(V`Od-6E4Y?T8$;mCw0ICaB11RdBq6gynIWrgC zIU}>eX^~7bcLYq)Im4f79gbv7lF~D@AO3XF<2{v}`aVL|ZSio$qtB+cwuS}WSC1y3TJ(_|-Y{Ws0$!)yuEvY2ph>@2k6SC2SKu5{LU4{5@?9V#*^|~M z?M&iS>51v<(zmB`fr(xqX|1^AV+9j3(O};U+l*(G;Nuy^gDMFqaDCt^N^r3i6)DlhZU59R4=Iar&rEd_572SvO%8|G%y z*=TWfyGXYi(%fLT!P?YqsaTZ?x#_E9jhs^umNl?P1Db*X^D0Y!&ej}k$q|v0&N`bO zM@CKuMg!+i5f^CmOVnp4c!Z0Ji?Lry>aAgV8vQ~5|o&s+|EPdhbP{IT)%q%e<~ zvO1OZ$)17YD*i@?6xA`T2`aVAwlwhYj}8sY%&O_ADCxMxuRbkI>3?!X_mS0;0!_Ue zHr+lq8K2+0_N50mZQ3z+Qd^ZHV^T|{>DKLwD~c8kEtodYzjEo~CEexwW4^iuYKOS# zm{_P5(JME!WOrxd7<(jhQsMgH8kM)jQRA9obGWhe3^2 z$wSt|R&325$XLZT9PE8YwY!hEU-fN&*Rie0J*+s_fJy%`A2mkEX(J!96<(6l`_Reo1>FKFcpN@Y1 z+h@*iD=pi0{>MN1_xma<@B4Q;{|D*(8~H6rix$XEC-Z{}f@T#S;(+tR9>4&ciXbdv ztj0W(MJZxpxQ1`!yLiHLM5J#VQK>W#o6RC-Mf(HoiXS|Q>O1~+@q)6U5-4_=_~Pt< z$z?kTOQS!B=}*JF{oJJgeD+V@Chu3q{TYP#Wt0{Z%0TbSRYwglXnoB3td;CdhqdY3 z((#K39!IbV?MC<()QXlPLJkA0fqUQ~Aow-_nX)Z_Yyd))wO)CisjgQX5Qjw4D0Yc> ziU`;(21E>^Xg9a&bO@OwlWgiV4Vey`R3_Ou=@7~5cZ;e*MyR+|{o{j59U*WfuF59OCuGh@(Fw zU&;%r9ixBG4=+OFdotuA{|<7X0NX8V%3Pd@TZ@(#;c}=0T%rwWvB256_1sR5Q>hcx zjQ?_$kX(TFm@m>#vUtEb%|RJpZ}Ctub`--{F$@=v6l1&1jCB46jfk>i+cFAYtX5RF z_!5q@!r1avcFV9ybSX^F2NSQ~AB6Ee!}xk8#YInTc=u=Uz{Vp*IIgxmPuU$F{Xc0{ zowd_$ugl4~WkqO8r|fufSu0o}8JDy!(t7*_0zCPxB{w|DBWSaw;uPrZJ-k%%Eq(e< zrmFdtJc;6aCA^caCmmWUr|Vi}%^q|J9Yg04hYSO<0c69l;hbT_z!?~?%1$ta)z?iu z?r2a$L_MO$Mm1>EYT?=za5)pIYzLgpy{BE-p;88c&Ze@<=Asw3a8z~nEdJ&!zJIij z-!l3{cmr<7^Z_SXbFqfB+qRu-1K3X0vuutl(@TQ?R?X#V(_ z;(7H`oRhas{y4_-U#GWCbX*A9Acsh+5rLlVoG`Y14v|jOOV<+;k&GHp1o3KgjBTMF z<|8~|JE=0?pu7z8mw1hnAEFP!WbsR7!Lafyl$7TwN+=LEV%01pgi@*Ouu@S z^ZHq~zpc-1EhwM+$h&vm{^Prv0!c;l*3~4mE)Og{7#sgH^maF$e}a6nlk7ui z2;taZD;tYL=rElCHqQtSAmqQmBx7v5t2kgg^NWu^rZ{|*Z=Ymw7Vx1wCJ6Ah@R9Jf zK+XtIC$tFbg`EOd$;Qks;I9POFT5?_U9tB%pL0+e19U_fpchJ2h=--4fk)9m{)@LI@fi9i^9(9bp~w5nPgW z0s(=P6Rahaxemzv=RXgxGeDOC<{F^J03`;`zzG9vHS9GUF_3=* z{MJ_n_|yQuGr$`LIAwq%%>5ZM%r$H`>@z%Vc+>DZ!)FFzA5CC|tDkvgIJ}i1T4Gpd zAQV}Sp~QeGqDNSQWj<{@;Ufe7-oE@!X_dUe5HM;&2Cj68LXYChRp>7XP6?MAAkzTKHYL8y#)%0na?$_; zh9SdY1L-$FrvVz7K!b?}a2i0VnrTiBA2!e>OY1cldJPO(rPgvBRXwmqWklG9ssq&l zb5gkp0&F>YuJamp#7xNRY|LwF>P=am_V4o|UWM{dw!elNqAa*TS^A18>i3tG(Uyzi z;Y1zR*K`Ts7Fd)N{ZCxcKSV$NIc$kO_!cC9{_W_4upM5D)?hDAh_=B~qnAhDk9`;E zR1uoQ|BBjhKa_PuYtaU@Q?;By%bZrrHTrOhQG^81E<%V$7|hs_?oXeY-jTjJeNXzK zbhRpG`lXelcBL*+Ek{Rz}k0xn1FOIoBI@rc3Fa>ExIKMC5cZQY_fgKt(8N zu&a!~q7?#6O^SsqcvdThxDq13T&b+TbR^gZ?k*0D+lTSMkaP&xp!?*bk0w?wndPia zF%_Eg0_nOB$SYUs$Se15s9ap{QK@zkJ~4k%?!tR%pUbJ-JVkBmQuMmq)bHEs!#%dm zwmmkoA`!Anpdb}&6G3rl>M~L@a8{k$jlwcD;`Pie2v?VbSPm91pWom_Sum7!DGO(1ImLtqzEjt$!vi|d>6mwq z30m<&{6S|Lloi542CrJrrmvjrX>F=6bAjj9 zJ7#&(`hS?Hdyegaj}hU#MYj+&j_kS>~$-p2bI@c)B{lzDDIbTR*EOywhro~=@=)B$ERn#p$@ zq|r4SpA1mtn!t-p&pycas z#AU6~FQb1{bnPWi-`W4fZC7<|HC_H+Q<)^IramTpb)~_(LRJLjJFu^V@BvU zt~c&9l44Rz@DB)(rQ{BBA0Y{%!4&40;HaVrD!&D66h)7?QN)~RjooU*MscgSSA0YK zP}F=Z!nJokRRm51jYu#dkHDUFHMkUz7Jr`6bl zP`I1h8~H9h4jYZWbZefyQ+py2i(ym2nZlqG{=B_s|wrE0LJ(t6lEv-I9xc z8@*%rFKUa`q*7U|HqBROxr$LavAU+(W~-i3orr%PlM4ub!L7l!QhnPaXHe7TCq{5U zHOyo#4i*-749)`&a*l_tJf>>1(B=t}iK<`R8u-Od7FLGZDKGdtzYkTTKgz52RY6S^ zJY5OfOJM5+cq9*wxr7D4nxBta zWFo1U z2$qSwzoVxBS_+`P08|A~ki{i*bP6zAfEudh^Az3Z?fo(1OZV#S*F}t*N za#s4Jjw!Ws%W@J84o}6b6``&@^9%B4uWxV#8cNdKlVk;YKZq@G9k{T_5R;w$}0MQ6yKQoA^ zw%e%d*X`92b~~y2Q1_|svW^8#Vy4r|-ISN>)Fc#(B)r6N8qQ&;Hehz^FpL>Eqal{u zY~afc@|?NhPO51gR$L4Gc@|t2d*@vInzq zn`wm!r{sf;j;(LI4^w-%E*ElEmDndRw;0Z~=i0Rv=c)-4&??zs@mmgA$PiuH!2#W> zi&|iQ&k}ooN{V=Y4$RM4nX@T}Xme6>aE`mrs}}pV=wOcSHeH{NSarZt4T8BxV~cj& zFYLci4*v1@b7jq%6!o#4J}#`jx_+z-X1$PD+)Xu5lL zK5Sd~Xm{!46+7!pW%H+GZQnYhqu6}VR=S{W^}QQ<650pb3M&`ym|nGVZk5OhmCe0u z?4KC>lFz3$yB+P2gNhTmg>)0#g1a%U6`@uOwpLj-H<%BbiDVw4`U2TwK4d;-Cg#)u zIThs8;nZ`fBdJ^}TbNl1rm&`UCf~vL@MI5vh{x~6LfvJasCkQu7&?$e*=PdAUA5*y z+*8GZ_{aTqyb`V-xFMK70ppMR&pkf>Z26L1b7nuZs`{txhktLay7%otvgOL26+c+u z@pc~QAzfD&L-zgb)8g4FV-M#R|1v{HPp5~nkUR=1lwE$ap zMgROsclRH@i0;}I{gS3W`Sa-RSez|+6Avi9Ej3yuyCebwRLu~v6L;cXJb-!jzzy^* zf`>7OnZqhOFN~FlP|ed+-S*X= zC_XKkpw_yZ1lWa_KVUr_U4OsrG2x|+s72*w9gISMd5ngB0W$TCvC*mATo-@NCGpsOgq*9!i(+sUiGF6X~l9>E( zWcoAlu}sL62Ga7c1$>+HIyR?4T3UW;hnnPfsLbQ>PpjEywBTCw6N_8EV4`xN{pvPL zobkJ^`KU7p&`&1jqqbb-yqi11qV}IB= zYr_034bg+pSGTdH2<~6;NQal-lH0hYwQ^Zg(5S6wy#r5KvnV>n6`VWz)2Rz4rA4{q zNnLc53lUPj5e=RrTQk(4r*o04H-=3-5FSM4Y5Z?_jArm$0tQWjx?6KpgH@VDO^GI? z;Sw||XwAWM@jgt};mf>q1V5~PLhPqmk|_?%WgMO#0qeM3tIv_o1<324xEYB7~= zPKM5^#kBR2cRR^a!m=dRZZB zoFU+q#)q|VQVa1~tYE8_|4{p>7N1c@gx0_kqs6H8YcV2~q@HYKHiw3bdCjO^*KP{H z^=jjHbjI&)baz}I(Da?%@T=anSjZB6j+Xz1K8rk%EKdK7v6hYnF_Vc(O2w~0grAQ7 z@qKs!o_imMM^EE0DIZ;k55@FFJ>_Q}g`b6G!wv)N5MZ7a=23n|7vD>arP1d}g{v{$ zOmt9AfmP_Qd#L;p5!>BoTy6Avt_I^)+ISob_IwXp6L*g?w)V-FjIDj~2gcT-yU_UF zn8HI6P!d`z&pC?W;UqX9J||)=Ng)M<@Oqm*TTduwFxm%XJJA1Dbt`j-%Nn9lbvUek z>r88hb+eT>THmvdS&7;z3#PEus>aC`E+A_0ZyT ztc^W(%=Y*W(P|W%ok@ennX|*^?Z7Zc?8I+p^;w;uT`n#Q_u2<2brCzqh`?iZu*>e8 zFr}9gK;Kv~YjwoVJM55X6dQ!p@e?E$Vux8)d+4h5C~MqvZT-e@vt){rg&&naokm63hX>-D`^jBPEIpq8FD71X=BGvTC0}NDCGEEn6rAO`nad) z+8!IF{Pi7brx%dpa@L=cpd$a4e7qrlF#oZ9QY_Yrc&)fi{DDYH(nIOEBpuS(3Qwd` zr#!7L4VP2V!c29=ut%&&(9t(TNb$B_k^}TjG5$ehsf4-&%#IS6!U=}N^fWafcb*%X z-H@nuyIHt@et}rP#=6d56s{|Pi3N~T0ACltn+2a0;3EaFuK?B;KuJNUU`YY77r^BL zIK_VIs+OA6K%;BuvkRk4CJ1)@=L00_nwBl9$HTH~AE&%9rG$q_H?^TK*BEb&64 z7fQS#FSdK(vKKz{!W&*V<%RuT*zSdX1*F^yR&SOUtGrY;u&SrL3=!8IuPS)$UQBDg z>V>)9CEo2`LTh+fC7@M4^}_GQvHr*ldlkfMywJsrWa^m9#SBec-MLHcyF>8EO4w(@^9n4 zI-vkF`u2HAjknQ@OUB#n{)*v*563%4`n_9Oafo(@WHFFLFTTvW@R=9y^&atJ+J|nX z12wF)#EY+X^J$6!?^L=7os5Po+7u}};(f#Wq4%2Nmz2T#H5;m}-o4(FUar~;7b$k!zCdu+WF;+JTo}1$TuLoH0-Tc+pxi@YE z_mlj@Mu4&6({Oy@jh7btO%8X6NQ)Ib<9D zuTgu-l=MtDeVdws&ySx$^ix^HqcS;I=KPvFg22?v~P`VArmzMLOPJ5 zhbjuFpJ~i&_t#~6<}CgtzvbK1gE1NBr+7=1SQIAX8XhykeiiIc0b@vboe0T^z)qO% zOC*WBtha^vHth=SMlI25peIS?z|f0FFlNCj64mfWFt4G6^=T3lL8nqda!mVB4sR

Z})owjG(ybsBF6drOpNkM9nT2S^ezjGQ92eH={#XwAwV$M|g|Xs)D~lb@XRY zy_=l6a_a-+4n93ATR-}xCM7jR9Ur5p5_>THWi?S#?M;a>Q0u~4t$`P=jgHd*nvTsp z@Vvlv01@It6;s)7IEq=$yix(>EN1L_hAX`C5GlIy8}bOhFUd0H zZ>w#RjXN>i!^1|ZOse{+mcl-wDfA;k3C;vOkT8@ml5i=3OGqFlYI^D$^qqRrqX&J` zfRUO_&LnUq$w>`Kok?6mhmjE{bHH)Tt}J3Z>1>l@wSVuZ{{?5qXH*`cJw8hqdaM5hH}n= z78vwdS*hOn1zBh!!XF|~yhI!V4f5^sLB9_weei1^ob-Xt2k$-SgNZ(H`oQV~T8cFjYv2tZ*U5?-eK>}GDZ?1U&o{&{*7%6k7sIgC$M9bE zX;{t6KC+8Ju-g4Tu2i1$snR)CBZh^ion+wnj1O34T+axgO6s>hI1=l_fDf?jYw-2@ zNHrS-rw?bO&PQo-8dj&NY|6n@(M-qQmQL!k02#7Knpt7LEEdcZh(}1pSnZ7p|MwkO z_&)xs6vRyg@e?Icbm5wVSoyWHtKDUqSW;S2s&Ghfv%j*Clbe{70m|Wbh zm}(|QgTolzyFI!`WiT4mCJ|`vv){rUYOC2uh-kBFp!aX&`M`2-KnfIj7Uo`&$*?i6 z(4SOXURLT~ntP>@-*Uxot)5aTij$^PS;@aD;VhJwEgbuj|9w1$aHV`pTQ;O*gOClg zU0`#8+69fNU`vIzB(NvJ5)&-b18S3vRm#-9O!2J$du%8@Ha_Sc%_yD*D&qW!H`mEO{;Z)svgg?QMu1G1%WUcmIdXzdrUQ zE?0E=fSj@(?L-)o=@*%g0gH?qJMjSK6m{_=gSII4QQ5ogWy*PD8w=Sx@IgpdPg$oR7*8uEC8M=im~I1!5=pgv`=1|5-o_Ds7?` zw`<^54R|z_8Z2n+8a!JCQ&m86R3$2`Rwb#h{$ph$|2YE;DSQ60{c}m#oJR(@Y=CnL zz+nUIH9)Ttj1b#h7nQC1cSa2Gp#dUFAi#hD`VG*a?C(={Ze>^+4OkN=;s5fjhJZJdW!0$4gF??YloWV-rYYg0S7J#tTuvb1v(Y!$s zT{dVc74mcnc~|MDQ`+q0C{3hb9w84G@xsK>Yh0MzaPFCUvBm-7yv}(%vh4BcH zVcjKN%t0=uWQ33DU`Pj>b%3Y|%pyT_#_>pye33W_9wCmzz(?UgJ=fU;bo(b;!p5Xqrb=bql-qHFxLXS*=BAslMVVoJ#Nu=>+x~|%Q4htw`AkubUK&23|Q8J zR+}~7A-h~?vty3~JNyGqf2V)IPi$?+&{>3?2#mBvSI4DH$jszZI`S=I2QTSl9Ujt+ z(3#Qk+|`|UcJ#6R8qavAoxZ2U!*Z3q_v?CYi7|~EcX^aUNySWt#}6hgZ8;9A7w&mu zsLOpSrEb~I=7HBY1*hEev(0mMub!J8ZNp9e%}>0x;zabT<1LhnFy7&tyK#ES#HLBE zao&+uSeh0+98HntP03*_CeAmbcPV@`3zeZC$*WgdH(7UE$+BcvmJW+EVV(+_CO~U0 zv=+ij%O=Zi3rVrGT5w8UYaX_Fo4h!sq_qTVO2AgsRD{(NU!S zmPgslf$wbOTnigkyDd}!CQ5KT=F;W6&ur{@YR%MyQ@Xs`#o^GJS>A#ftHXu2PA*Q0 z_=#)u-c)Jmw(e)v$?)stko5nps_4jGA?*kod)4?Yk400gAvnnRiF#ZTb8Qwt?h=<@&WXu=cH4d%wi(qE<3}w5?aIO{Vo|g=o&9Fg1zkN}GQQrf zoxHdj{%ec9e&-y9y|VAwo{gtB1Z(d(vo3u1(iut5r)`{d%bksd6HfGX9_$Iek`-Pa zn$R^XkXOHa%H*Zt9C&y6@y*i~90xe^8l?TSGh^zi21nbh(60A)w{=vl{c&&Ix;cgE zlb7E*oonwvCTa(1((w0$my4#7?}22!;X`SM|I>$?&6Q4zm5KD z^k*lJLM@bo@8SLEhFE$FdgE23rM6VA-V;_fF_4p{m{L}Uh)zs*g>}pbW09daUkAYK zHJYi!MHSP6$CRVLIRKXVh=uU%70C!yypbr0ve+vQi|0g@DBD1`4cpGyMr>Tnz@R)x ztDYZsXR9@!WTtzUUF4SLw18Pwnn>OnQWw)fst zySNrN)i18ct&^8e#uHcB3RXFcS&o^M%{pujEnWD=Dn}J|RQan8Rgs}8sG2hnW^7lR zWt_UUynMQUZHjvO+W5&LWyic6{MY_sn~AAU>`&5(7sLzWu8!-@9$$;TV<8@;#VpKy z2{=_<)PHl)oaXVC1~T2V&s-WLqKGmilEh6iW{OIqD5O#}p(0I+Mj|w7j*xhqFF2+0)b`PgihyZ!j~+x=aISadtBuQ}vd*2e>pnRyd-g)TvsDkfjY`~@zmClh zTQYpXfE%lZ`G0I)XR+|dL8UL-cRtOzv$i(gE`CwG^Gc_ipSG-YH|l2+tQq5OQXJzW zSarNit02PTM#Pm(17qe2`W*UfcR(v}&&z`?Roh1F+N9OFZCbkJtA)pHe+}PTqCFti zBA$KjckM!MRB3{9T-@~@RiXnbHPNZc=jX50ycpf=XWQ$0>~livM5EG;$^I(rk^y5n z2awd!s+wb~o{s7}Cn3GM+W*-5>0Kr-9$gWYo>gtyCH>BcG|dX#!$*(SGK8Ug-MD zvIVQc;AiZ^{0~oS-F(EWdwP32^!69Lot2nscrW?kffrq8xjcS%*rK&{UW@%vF@0~% zkJFyi)MD98Wy@9FW*t+dbrX|JCY1m9H6k~Xrk z1-sUB_4Ef@4%|8!KCw%ii`Gt_A*~MNwIya6eQI_we9!%Ex5K919;CI}^5M9t`m1zz zYjmwKR~~*sU?iy8f4ulad0g?0)GvCkwDH;xjsx^&zhQIlveA~^4xQax*kjGs z{%4-X57j70m|0W(4#ZLsPoBkmTdvbIwOQQ!8S|gvXU=Y@n$5VLo_neGop-m#V*@+& zGjQqrdi>#sEq8njyWS+V>7}O~-g(bgYTkYD(3wG*IRP_v&YGRvZBO>eaYZ|v7TR4_ z`|;XjrPewBi>tRK&nl0$b9>yaF#J_i)sKqTu0OsfRrz0kQeL<&`Niw%Z=NGEt4_sa zv^8yO*EViJ=ZMo2-)$~7b&D%uOmBw8QRL)d>U(C~8J9fRz}WgUp;LNXE2x&(<-Ik2 z$jbdig~^r^huUrP7fK3}`ktR%%|R>vd#o}ZdBQ-wU1X@Wa< zO<(8VCDwWCTEkQ227r31b+BKii$~Lv`Mb|wnwL>Ur7qfQdhcP+(kjpWc@D%EPy3vO z8hsvTOut8eP`RXj-0mGS%1AGMTu!$InRnJI-}4G`82aq9PTP~&#yi|kM@5gjkmq~s zVB|F;->!j^FDDug>z(UMB z=MKnh-TCau1L3WeZ6<8l{ARU9SlOYLTawyl9@QKe&_3>6TA@xq!{mKk>beYgtE@k* z^YL#xhcr3TAxTUz&Y+tbG5&A;HKqQO9;_7zgHE zd_$#M(LLQ$lzWDFwd#|my#7|e&aGocgf4K=uIT%O{kkt$=|}wee!~0Mqffpg5|%9w z@DchhQM-NVarpBW1AF#5nrQOWyi7OJW=T+?bwK;BRm2jvV`)!qt^>hBO$fdV*4C(|D;zp4aPiD_1s192_Oq|QP2HV- zENjl4@NI9RMtolHG`&ye+ON)TH}V6MdOMCa{I1=z{FJac(f|Ia&GstIW@vN{5O|zh zbf_w2>bt_|nIYL0>4NgSQK{u!TfU0Y{`m7pvq`zd)8ZGD?;7}3N3=Oh5UMn7r*2?~ zqiv1Zw8Mh}Pp0Q?eDrf}g=gExb1H8|`1Z?QxyhxY*U|k-V|wef4Ih@hS$}fqS!&l^ zCsis|`||sVbim2xiH6Qj%gZ{2_-yQG9KG~vzlENkABXJ^0lX+uc9A4W$u4<>7dOf- zbF6p4r1Ww}>2L5ayhKuZfhGLQT{bDbs8U*1@|VLR`8O=fT>wcE93B3~;i4!Glk^?% zozij~F3I~K4gMSc&*5U~VJ5{FT1xT4cXD#!rIY0EOElr{7%RRU6aLQO!Epg56bg}B zDY@Y#9WKA`!{aVG{r7y~-%450lqwuPHRiz7{tKtvUeaXN#zEw=HbIx4_E)cXX_7vF}>oGrVR@;tni(mwG@;pl=( zhgj_dg;w}17}`3u*Txfju&PAr)DgwtO?5e^7j3&Q98b{cRVUj zZR`KM!ly!oyOq*mZf3@+7Ru%cMw*s`hx_geX|d4QGJEVuBeQ+0{mgG9v@GgWJhtfr zz0QTV?bL=IeK`56 zFifOohs0s~nrAY7`x!@&Go)fl z`{(7=y_T@m@S;kCx+>jji*q`c?xyUBu9*^)HtK-j$Hd_uKB)|U^{KKb@5M0Zvez44 zX@64+{`yVn!_G?u>iY*6&aBPQyFov)6T)^R%~`Qy{nl5D3~7Vfv2zlG-i-KM zRpY*S;qL0L6)O$rB{*x9PLJL?cfe)aySnzpg$r(t9-H|>YdtZ-&+ziY3xOs*C)vhk z1=S4xa_DsE8!zGAp*^qW?mA+d;b)T+cBF2^(Yv>5w}jpB*cLlw%TTXv%imVLt@+mT z`3qrcN@2OqqcTyE0xe7ZzB^c6%l`H1%JKECt~B-X^wKi+b98rgf)eW8V965j0!yKQ z77_vm2lei+WLd~s@BT`XfdoBYCy}Qgt2X+#S&F*Y;(Wp(^hb5wwO6h_3&mM6) zd^UB!Ytq!+>4i&Nk#X+sjedp4gQ#->sq+(#--v%Wxlm`TapA+-J6i)s1mEa!>U~c9 z@yZj}Bmb!J?t8Z`{kro+!4tPJ`A^>Fq?<15lsNch$iOulMp=9bzjTEi_pH;v<6hS; zJpTIrRJ$>QLo&y$UXin?HdpKV>8oVO$AT`=!6Ns{o39+KJF%%BTa3HWbI>N^8Ee;f z?5uq8ef)!wK2bJ@f9`1WFk{`icDH&M_0LZ`|K&oC{-R-9ZVzsLnhy7=L z>v5K+2ZvM)EO|2am+QTi1qUBqXgON7S%-4R^hJ%5l*=Kz7g^R?&VG}Co;qt7)jOx0X(mS|+xeZdu#0maKKbIxqp@P1S9 z=HShX`v_qFe^(Je-2>-gFvUJL4VR6+R zhuDj2U+haN-CjD(yVJczYu!WWCZgzf=TDS>dN{v0?%jllex(*~hK*@9gl#f&VbuFG z_KT~1V|6E`I|V6CdcEt{=D6gympjz7QyF^cV~ElNycO3US-*Iy*2}b7D@tp0__)5ILiX6VVY7!mbv#ewtLMD_ z`Yx%8dHO=F^r5l_(q+w?rvf_s6@{6H0Sr4|o3HNcB?z(30&5GgPWg|n}lM>4PY)?$w zx@-M05ZX*#X{4&sqQZEitB>;M9=CKK8P*B&>oaJ>an<2IGH)J9CdN0;^yX6mlYj|$&cA?l|00Ga`MFkz1@u0`Ofa3dqZHgZ`dPYSm=0- zCDfIZ=k$}V1iCn!yi?*`wK?|qF#mk({SgN@#hP55Hndw|^p`^=cdyK^opI&dyEQ=x z?S^G`(ZgH2acrbsZ{$XKFC_t=t*($>f8OdnqKd4L&vn^$ck*=fXPW) zq0 z`m6j(%Tnsn?8ba^9Nh=+9a%foV`Q)NxM2f#WQ;LZnO$(s$ILqIKA!Wa zGOsE`C9~Jt_uEac&ZtPr7Z!f|X701F=gZgqH*}jkdVlT4yytP`tBUH}C9VhiEx0o} z>rR66W25eI{QD|fTcD`0o)41IkyA=f4Yzni%$O*?0UW!TBM z>)n19g8b2w=Jo2D=^UzY{>cO_lQA7iJ3FqMl~>&54A}225_~lBR?-NcH|fli*4>Zl z_RiR#c{Gg9*mG%3#mMd=gZZ|->}Q&4Q}g3vrbHw?-LP=tB(;Etw+CG8)oaj{q-*w( zZMB+~sA;S28gDx%0(gD!^$hqj^3uC2=GkVt+l~6Kx#~LGh%l=>P#$&H1EbsN{GJy!ie2hHU-?^g8ag8WtE61CT@nK$yS`+#`=fUhlg-shR`{Zzbebc71hq{G?wqntrLaPgm&@ec19sxX}^E9(_tC+TXvt{-T|B z*v$;%9H2Dt#DuctMkgaheb;XY+IH^KH71;yuG}NqyJY2ztNrzRC)IU$IKklOqkChh z?XP->;XlM9PO5b$M1p{q8uZWcI$&eP(M_*H+D6 zue!c|&zjeDyI;R}veY%Ju=auSkS*(HjaFbgjjW{b_1nX^{3o#oKvXp=FkPpw)*pZz)K`}Ve8K*ekFY2&AXqXgMC(bG@|F2wo>2yE&5#?-C|Pzvr)pP zSrJFQMmcu65Z`CV&DW}5E?pgvv@RZRv(E5QvtMmiPZ;TPbz_wE;ts7B-#$9nyW{B} zAMHBgyTT52+i>&z(9-Jjy|vGcDqW=Z?dI7qPu&YXX)9XkYnoo3T#(?`wqt;f(vG<0 zpK(Flr}$kjTskD|DkYXaSYkWaUhS7(z|4>_qA^xW!ly6txqao+Mw9PK&nCASws_c< zn@XecbEjL*dvv(>^aDfNeV!To#C_e2?iy(yFJ7*iKYz!rb1zOtIHfc@cT2yiW69;J z&NZdaH+MYkzeWA@fZX{XqJ?Xl3D>lX56f=bIp<8l$|1)K# z9pSvutdpAaj&-F2AN1|AKD-Y-e$}Z#-Oe@1rJs#FR(SJTqRG|a2AS8}yw+^G-09hj zUkhqq2h!K|J@@sWRuOI&(kFgWJW({=zK4>3mhOhHC5O{h1qaU>SgURs@u(l!FEX+D zl82wlJM@mQ+%g=|*+Xk2O-GI_!o%dK}(TBmMKD_w}qt7zG5 z#hI3wrjPU{Uz|VMQ;W`zFB|W7~sAoJ9*9fMdnFArp>t>7sGl=J_Gt zp@oHGSdu;QP-FD^RFf_rN{hN$cN+Ss^+xBZZzc%Tk57BE!JJ{%F5iFUisgiPtJFVu z?yuT&OHggvdH?9G3lH~c8(s5caNvUcp;z5DPckJTj zmCDm^RbOSSi$)zx;f; z${IU8p|*3#*R2*?lt9R$Rb4(0&(>RU?`(OBT9|EEvlY#>dOWM!o6zM$wE6ie z^LIB@$+*g1e)IN2W%R6@OLIV=ea9tFcNV<;`aOGjue8lew>vy@>E3C3#qBi@hQg=Bj=aBRcqa$<)}rkOOo?W+lu?BMdQ8`q7? ze$aev_qm13rnR5f1e~r4`<41U(NOp0kHR}Qb1r7@BMVXsCscM(Rx`I$S4(ShqFGnv z)YV<}r+s=eXz!8B>`cGIt3Mlt}OVlabJs=g}ZM)d$#lG$ki?S zZd$*vdC?@J3pF|2Uap*ZWb`X zRk}|SwWm+VKi+=wnyqcAJALk0#M`wV`HA3RsOejuef#K5CR+9ztFPQ$KW?gNRA{S? zmi^Ka7fp=XWS-Q+`TNBmD;Dp$uiSm(z40+a@9!PGXOGjo`>JCG?R^knf7!azo!47d zv{5&;Y_k8E##{pft=oo2zq@ZcbZ5@`Kv&n$VcH*ieKJv*=<{(z^xLf5C#`eOzFj!@ zW`51WBd>F!EWejD?dROfqsXDy#O=n2P5XhZeN6YGnyRgrjoaf*==)psT4k7duJ@~s zMI9ETdS#l5lS}KI=|}TcioQk$YWBQM`Cw%+(GwaO;mA9?a=bRs7H?3b^YD9I#`Q?3IXN8`ea_{Jr zdz;2j3Yal9t!7dCxkO^8(1}G^bC+jNoE+n0-sROG%-Yj=I{UNq-~l_+()mLs+-Ejg z>rBZUAM>Tws5ClXwS2nu-p`+#jy0(Ke5+UN=F+*|H#L;I6z07&-x;-Lp|#E1X*Y*G z%gru`sC;&6ozBlQ&6X}MtaiG$-(qjihx?b#v=Kx2?yGn z2l|HxZiuISZ0&;#mJM+ov_)eG?j*eT_S3Na1xMqJ`}FF%GCpIydi$(9p%aZ~W#@58%$;~}!8(cEo^;P)%+9fr05Be`kDj4%^Z21i@{PFiAF)x+V z_hseV+_zR8Y#3Y-leu7R_YQZTRwYju{WWL%unhye1Y7>nTr_DXuD>=bJ{dU*N)*EaRAGLd8*lmsZpdmZk zFE)9>nxU90|r_cRt70T>g0;7BO zf^BQt*FSTPEqeX)@v&2`=hY&elU%ju9q>wQIcnCsCTCyzwzQ9=duYC#o9N0eRPT*n zP_u7Y@vt`I!^0)+ry@PWiao|==v|q=@_>ndwn_Dw)_1cyTIP1V+9IW(_i+%XeDJ_g z5ED}jzBhG!ZZ~(*wUzM$KHANil=S>^!O`M((RE`qG&M8^H~+CLcv-KWm$k2J&$##H zR)?eSlXeBQ%eUyh?@4*e*Y=6upQj~dUQF~U?rT3`Q0-#1#XtN%nRyASf3!Pw`0%oy zv}k*_`a`YQ!J?GHFZ=hTE8mEzv_7^qCNA-`_0hM9#<+3!LxzOiWv#6xDc5J1dYEc= z-L2WrZez6j)^WMInOisHY`#a&SKIcYTf44Xjr2T~$KUO~xn2g;C!M+P52@Kyyk-{oE%3_B>!BIwyg}=|yVupip7`g;Ppy|8^}2L3)c0X? z(--Sbe~%cYwaAVBRhPOauB6qah11+l+#Fpy=Dpj9u64tDHZ3l`zhPRsX}e9QtPiTK zS^NHnZLot{r__Fk(JF6sh zzrD%BHn=GHpmpKF5$lU%vgYo&JK^Z{o1&=X#1YuZ^UEGiSm7L(ZSX|(VB{Ht&(yBH zN?ljaIezO-*~XQ+rRrUCTzc}otLmKq$<|Le9j7kwsu8}iY62dYMvT8`&AFT zO_}S64p}FArqQ1ljw*OjkZ+N&z-Id4;@!_SwYl7G`Nw9l2Rk@T8{(zXQ(I$XYUzgd z>dhi%-hMZsdd8P-i?2@KowI6b@zC(_;rrDDc}?02j5>@x9(gT%*f!%WfkXCOy(84n z34Za7tynW{PEqDdtyODPRv!BCGveK;h*}MLv&Vz^PfhBSkC$COb+y~7#jYRjjl8vU z61X2V-=h74D#Jp(FAhUv0-x>M7Ew4+f5_w5w$oou3@*AGoi_zt2nMX*JcmJlwJ; z3=nQE*NzS9mp3y=h*>?>X`Z@xr)t6dzA-)nZWIo1UXtFrx@PfQlcL9meKI~DjxRd8ppd%g4XzYze7paeX7D^g+pQ2BQ|& zy{Dcw-8+6<>eaJ(zNWpRn2Xo944m(J@6E=zCS|(Sp$oeX8%(y^bLvN7TatdNAEbBr z*YF#8o75_L@4UNiMEI`WzLQ3Eb6rwYG-t)d&p+~WPOLw!d9mZvJxRBZr5@87cJEQH z(2~)@S$@w9XYF}@yVXbSB_WSh)KZevQVdF;n}1EnRt@r7_kH!& z_qY4rHqU7Gs9ou+vj_KCna60{vwAoCphtjR=Gq7D)74JTn`wGyo|pCZg60>_FWMJo z6XbSogkyZVw$0Ow;Rh2lZydj$Xzk|t$h9!9*i2|(aV*rgs z^4Ra*uJQ?&cJ$OvPT#w9w7q@i60;P~^P^7K4H)qFICWTk)6#;RZ82Xx4yK*1t;*8A zvS7x>_Jgz{cSlBsKF~})e98BM{@Q^1F6^9LAZLohPM7Qv<}Nm1Zqw$W>B;U!FY)4+ zuR2-ojPAQ4{LW9>0`bm+4sqJ zPo;`h{95p0W-+iytSFdg5qa1cxBRsTQ1u^WU*2-Ol)h+HG+qtQH*3r+&CdtbV z%~p@tul#-Lfk7?f_O%$UZZW0qP?y~oepyG48(=%x{Achdm9~pRuB_1vn)v8ihuy(8 z-Bq=msZEE&x(poNw)aZEM8~Yw z{6kGaVg9$8uqS6nPQ4-e+4b&&Eq1r2JNEL`cy3v=`ufB*$;B6)du<)#YyUKG{@aVk z?A|yRn41M!1fP!$TpO)!cj{1PfSp;)jEsdJZYQ~Q95OGr?f2!WM+@9d90yOCmN9I3 z+=u&5?dG`Vp3>iEzai~zk3(wr+}hT)v>sJ{aOT6govlsta_&Aex^H7!epC0{Tjj-H z`bPPZ2fdCMEm_dYHSqMo<$-6qUk!MjQtenbr_Qs^F=xg;{jgIJIRlE-X0|ZhN&D!L zA&&UF(DQ<6J#3WsMPGZqudumoKbMz&)=~7>%>(DWjI`DW8q-Jss#6TL zTEBkX^YO?nS=+L-vSJhWYL@qCn)ON*f9?|2E&O1iQPAAPF&8S98cb}yW3xsKxR|-n zTh}KbcH}^}lf_myH@)@HT%SEA{>P7G%Lmh@KAl_TZ)vx;L#w+tmqyP{Og^<)+4)nl z{@fk@J+QS)+OO8}_usqEU#+%KaQjR`tg4ou z)s4{J4?N${x2&hFb1TX_`8lQ1^{(>zTGgMUeyT2+p4#)$UC}&^l$|NV_h=FGPOSQ- zp}TWbYF$d~t$8C~dT91>eNnlr^ivR#wkaioyrj{#E$*xQ%|_Ry_xb4?%=&&d)=n!d zb5?(`|J&8DrUy^=pT6QtZ!5zOJ@ltvnNu4a{oY7-^&;h=`e$DlhnKI zeo^$m?v}Bs$8hy-=WWLr4vd@;U^h1)!tG;8Xziki*M0oHrPe$@u~s)FMx$#{VXo_f zsx_@oY>P{6{`BFIN_Xw^J|o%(FF)Wn<6_37*vqFs=3gX-Xk_@)TZ^{!U3xHa;iWcH zA3dh}US8v0cIiv%HIE~#eL_^L@{9z{r=1r+d%Q6vy~9i5-ol>A^v#*yzK{9wFm3DC z60KWW8V8eApFSvNN?jwT%?VOjr*kPM<>u0pS8lC;Ftv$Y-$i{V^o`Vy418$bRIA;| zM>k(abrvRGD^oIiciE@p)*H?4{rq0f?(0<=m{1hq6XlC%JYKgm z(a5%>cKh}XI;*mxMmBr+&~xl8_D#~#9Mx>owj(Z1HF=v778P%$Hu+Jn678oRtHfWqYbC(~SnC<<(WYeR02|a`Q7d**R z+uF0GYVtEHYIsMrbsD0HLqdO^scbbaXrlW0PwigX#*CVH;CPZr;eK3Vr;SGpdtLk72F%Z1HX*NPcQvb!cI=dvL*3%yhD4eK?`^VLd5vpw;Fz+U zx)qv3S}%EO(&~dK@1ZblykJU47tkFH);G#lA2oi&n$6d?v|sL^WOA!yz<}w#o!|A) zDeN}jQFha}&(@ufc=7Jkj*e3*5WH*{vxKZvtj5+E?V97=5Jl z{OQR2eD~UYp`rb^BnGTGJ>4MvHl1FVW$ku+Tjcj$3CEpWS8uR>zIBGfyh_`z7oyEw zrVZD5^C-LW_0sTy;!f9^`7U1Bx9i$HvCeM6NjHX6r_9>yaymS@=5(Ej;E?Of1s>Ca z-cIYh`stK_35(1|$FArgXgQ+QRbTV|Ms3!gdD7XhS-hT$`N65GI?c)D9X{zQy==OB z?66MDnSBP`)Pll44DJ->)A8!qkC&e7Y!-Y|nWD6`S%2n7Kc|^htuu6MBFfM1IJ5Nm z$IbLE@<{7R8)F^qhK-$kx27y?dRu#kn#ZoTVRzfjxuSee=fgDNR6XVy!)Yj+4bpa2EKvWC(DeU}Mqgck0dA7< z0Knwch61p$`7;C?n+AY@0x+)5d>Fq|%Kq73=0SdQ|I$yApa0oEQZbk~^_bTzzrSJs zPdt_;7JqCO_}f2`Z~_R$iZKzs`JiNWcP44O=a+27W#+GPc6%@V-urlH{{Vf}gOW%JCcRqKc zDYdAW4#7X-X_x`XDb_N)?ctcg2^i(BeSJEKA}t$&v@2WGM?p za7!E>W`#z?)!Bn4aFP;A+C%yvFIh?z0HLC$R;cR5k{OcvEtz{jB#T)vpg=`%9gDan zoMZxEfDyMdEqUNemas5F1?GuSs54!iy)m4?Fp?6B{{18;`!`tt0C((%*VGC%8x&4p zEQSdQ4)^aTo^TlxgDDz&3bhRn zoI6s(6aI%;>5b8VAt_4Qq0%Rwa4A^;aEOvG{0|e;8)Gmbkj|gqPdwo=CQ^J*frtDL zbJH7R2mpk*w9TbYeBn|iOwsa+JIkQ3Lm7&pF;XU6^28S|Wuh=e&GN??%3>rV#KcP0 zTlT~gE@J|Of*HyM8WbXDae^TUX@^Rm_`;=3q{3$T;|yhKQb@AWW|2Peg-e-$0>7F& z8>V2X2B#=XQy48#x4)kd=@KTOV4!0{;UCPVH^68X6AC5TMfM~wT}Bp=oI5Q)7%`#n zPm>e?60ig#l`ehaNtcoZ07EA!Cgd!&qD}>X!~rX98QBveUBW~uaI!HW=fWzKjx#tb zlwp@X@uW-10*rGWke2z=JOuw60(w+DtqEdmoWhaY5)$oKa6)kF+!3crP8HOJn2%h0AQ#a zfC;&-R@gEWO8}X{lRfdJOPMInz2f&O_9t@+7>p8P5_j(R6HmH~2~#+mus_aKhG7Us zs@r8xeCbjqM&WqpIzwU0FbpdsCC(R=E`CC!OPDb6h5>Ixa-NMs>8ud1*D}&4o^&Z$ zfQio`^QHgEqyiQL7$$N4e?Rf1OPMGIwgVG#%11GF78f!SSK1p$pZLX#XND@F|nq*J%(q&`;#w|;cmig0M#f3taVWe|a_Jl~6Fad7o0FnNuxr*Zq zDFjj-DSP5cmodT9)O=& zNtZD(+@wdOE1avoA}7CpMWVHgynOu}W;^RCrsqMUrTScua~>OpU6E(Yn-E}=U?W7 zBHn+(S5!!VDfD;b3H_Uu12q;brw|R!(X@uR<*E08V_4E_{RprQ7 z8h}g2E5LB5SrBjvJ?=k^E(<>&xaDr>@96|L+kLgf86bb@*gutM0Q5f<6<`Xs;xQo? z7HM#|TX{N*=D7ad7X9XF0NUTo0*q@^q@@+E5B|{7Ha7K!c|(}~jZjV`#_fdDj6x3R&nKaT>GwNY@T;xTT+0s-9^%VT4sW#RW1{V4gpLGU<1n8Gy)-UzE=X=0(J z@9rw{^!sB2)?@i6vUxK!5Mp&czZ-BR900hSgLkP4kU&K+$; z*UPZ{OBu*9HV!c-n&Q%8kh#?e<0RM2vN_w3c9t?X4z{$EfKuqTa=BIwZD}qM?Dzd~ ze;LUL=f6QCMFfCbw(%RAa|{0~VlDl-uI|nb=009dB41xFx91O9iVp`V+4veEA_PET z{DN$ZAw+O;8Hj&Yf`8!u54DlJNZ|$o*%%YaL8_MmsAVW}^z--mXYVL1(!h!+EGqyC z_vg3>PNPPgoOCZAkvIYIZzD}niT_d+>B}%~lLeVOjaUaN=oTN5$ic$f(do}?{J$3Z zFZHSSN}wQv0uz#rvBJnm6Q}F`W46@q8%crxP!;K`0I6t&&IR-T^BA-8^jh$@RW4d_ zX^H<(5ou8Y;AS~8#u~A_6yuUlqt()Pba$Wa=;ZdVZuw)e2G;419$udRnm50@TFT$(N=OR|Nb!Zaygj^ncMsP~d2d+D8hZJ-X_-6vIJ&!w+#5XT z;X#1trU z3iy}l|2?=Q?2WI1h8F*Z-G-|Fu^2UQH;> zwo-i3@^8~d0m?vc$A7KM{#5F}S4{j;O0mUkw3na=pP$Ib)A3)L`Y#3l2X&Lano^iN zsQB1s<2p?eJ#jF1^zr?d>O<=&U-~~+R9=jLQjn&O2^F6a{U6j;YrL81KkV;6YRpOa z->J1248!GA^6j$XW2yg>np^0>GqnFx3I9tq=fE%ulW!FtfNdOZYe#oi=Y}}HXlK_e z`k(7sPlkX}m~pB2cx~e_!%rK_@65%lOUkD)HY=FHadRcD?ZlmBJvY? z2K-~3%JVj`67q!vIJe)0;8wV`(8$XN{??1~DC`9~lU$vB1$M0XT%JIDd%#qI_;fz} z3!|p+FAP1xzg&KvfaS&y{0kcz{)NEdUoH$IV8s!A0W0>+1mYu?@UKLk_&|Vw6(_w4 zSn-yifE9033&f}3;9rS6@m`jIGraULI}NF|F8|3QjWviM#dNRdjGOfpQ!`H1i*@fIlj zhg7m;qG4h)#Qh{~4TW1xatGnZi+ufjVOeo=)w>o16UvUBV+0{2q}PRDLfJ`f4F64( zoscG3?v^ANL&b!$^TiloL49u6gB(kJB5WB*Bv`7RU|1PQrC5TlM~02YNdWbTuojSr z<7_=DY)y`p77FW2mTniyfq-4ey$-8aW!Z^OjAn^?A~|9A}H%eFa<(L7JIAJWV0; z6)@uAEafxxaux}6tb9dM2Ka;cQYB2RBIQ0^CRI(ky2{)a*aTw0h7=I6;%0&64Jk~( zibnm0#@8~VqQYPibtOKS3z$e7vDR$JoQsMKn(GS6`rGDGKxx*emPUn9ZIia+0Do_P{U!EjC+Fs<8(qz{Qh6 z{74E2vDuaUDijc6H%a`=2newm6F(9HTx|Kok3fKny$bOoEg-}bT>MB02(eNSKe7Ts z?1+gUF(9Dp%fbb?1SYJlzL&d~54YhdY4-7=IgbABep4rm6L5A5a*ZA>9aB;b4%OUb ze-B@QolpS(Z7xuARfi@{fXSXE1n`?6q2Mw~fVd1HB}kr0*|VesB_&|u0<`oQh@Tnh zGcJB+rO$-;8Iz$TB?K8vNJY3JokzuAJm?;@%N`je^VWuRQDH&#Xl?IeU%P>i1kUFpD2jm2zC0h!-H<9zBS`2m@o8`= z#-~BgNuEZN(94vk5fqF8@M+MSm8a1p^xfrY1OvT29*u<_p*)S`*5f=H1{d@^8i3v@ zk48WrOrAz_V?v(BV9;Zfr_l`bHsxsy0UduHje%Y+k4C^Khdhnt())Nc9J*LM8n@8q z(MafN%h52vKyO=)CS>7vwhBR#BeV1AzzjvV0cBIhI2s%9u0%5 z3LXu>6^J~I!r{V8o`&NvGQp#f@VX3n8pY+d%F%!jz*UzV4WlSzJYy6MSA}wXK**iW zm!n}63s*1lG@1*=$k70tTs%HN5HMWD=R@Wj5R%XrmFFYSu?B<`T-fsXD7e~`r_m%_ zG0M{jbQ}PJTQSM=(F9zT%F_rInMZ)+LRRv8Gz~p)c^ZQua{Dv7e6sV#{!vfFVyFABor~oTibvMPLk!KFF7)X}C({(HOY+lcNz3AdiOAEHWkuz(r={ z%aRO?y2#T2YG(+NL39`a05Ycu3PWreL339C%D;o+!d>z-nnA`h!5}_}kf0evuMrG) zSFM~p65udqD@P+30tPR6G!kih65xofB^VkR_XNWrL9%S9Y{e8@ULNV42!q8uM3MC>4jGu-`sJU#$JUOXDXudk32l1SYsA$P!% zSC&C+3MFJ=gjJqTyamOhVK6ewqXEQkqA&vKO9BAIf2J@Jts6$e&CB}lzzDzv3G35@ z6viO_B!zLCul4yb0w`!JfFXVu1-K|ZzbuUR*QW_7Kp^9Q0?0ZFBLJ6?%_~ds*N8$2 zFfa4&b(~d|4dzn<$(>#xsR0z=zXl-Jrol-of%Q<8ZCPx5*U2?aImH zBLLt3!-Xu;=R%6Wk+m*GAU;1Vi}n#gA^s3W(0p5g3t0y7mEqDEnQtVQd?H^D5+G|` ziUi2og(A7IGp{U(_`4J|D*SdP8MtG^E6XCj6h)yro1!qpXP_t?#jIexMNuT&CXjzG zMZs-19*suUWfa9CJ|;zTJKgeSX$)C6QZ%||r)UE487LZAA7L0n@^y}oqA9dLXa;Tr z@UU>n9r84W+YRT@Q2&`?aCi`r$49_D7#NKAoZShzzbFOL->{u;${ zpKIXp;iztBQ6HUx_f{kCKimSYudjmzu|i`aZOfLF_(_2@%^!V;K5g3`gEeV>sgf(eS=vK4y$NL@tjH zqv4J!kH(<#0GH(=&j+{@emok0JGDF-4l@hnXbgj{XBdV?^e)3-NIZgJxI`v7c`T0e zV{RD0Sh$fU$H%Z3%+`>ju{e&{D2B!PwnE6T1d5NP5Ie}?6rvAUg1fPh_g-{;&Jx`1 zfbx7Ks!v%0jghe=fvi8E`^U2>7yw*45$_#noRDQ{L{G9LiL?Pr(r6oy4BX$X{|*dL z=-Q7Z5x)tVbHqntDKwVGQaInwhJHKpULlF`*Df$$jjwZHP8451!z+XNF=R|AMD#t( zZR7is7$)TQb>-SXC}a>HQwT=~udRd_qGK`Gb38o+lj8X66qpvr*Sql2Q2tsMCd={T zG#H==e(V8WtI1z?V?w|s3dq+D0KOlF2>}i>JmmREf*+@bSKh-taXug4m%_M(EyBko zSn|qpNsaO}O2}U~!uKNm#w`wb?|>O*2#p~5@fQpeGW?huh6!1;z68OKpJEus<-EyZ z#t51pFTpSdv9*v7=}U}Y`0FEBmOrO4jO217<=;zU{8$x?x$*apFo1Day~vkkxUaeJ zX?&Xp%PM#W!`H=7k0av`z(pdjj{v~-{MIt%}P&7Y2gaI1y2_cQ|hhc!m_@)^w#E-ymj6`$e=P^7;)YNJKZmcrnjsz;J>_bTLkI8>w>rixbFx z6o%6bKYoDW1dGg7oWT%%N?=@~xBNR8WW9jl3=XrFF z<@pE_@j*yNK|Kf(8EYiLUFyq|MVDlVM1o&qv{a@AG36O(Elo!qGmW z;9cRou}0xsR;nCkibmoV7=?46Es^KLX~buxa8x%@1b03_zAS;{24FCzz@H1W5Qz;# zK4h#>46=U1CiS zSD{&gzvqR~EXCi`#Ap_YsX`j!tI#Zx{{pe_<8>I#a#^`@ZNT8%`2cwuMI(M9gCqOX z7(=0b$>4w=kHFxzIKMwwxRU41O9lpr_%sE66AWLWd`Nr^euxVhL#zV7oyCwC1;!FI zqK8-pwV^CQBlB0m+8&nWuZc01;0~I}wLQyFeBBAZ;e@OkS%y-854CSBiy^)l%VNly zgk>>)%m`yyWG@;BaSZVpSQd%10wGTD^MU|WYdqZ!`S|(@2yv2c2Vq&hz6U~_=C4(M#P5U=GX8vneEirF5YjB)Z-35 zD3%}hK*(VHm>UqHV+df-GVsb`B(e?w7(743=fk+WNqJase!Li97|S1P00Z1XFZr?n znS-!y{CGCNSR`)_U?k1=vjKFHc(DQiKdHrwcLIz=avK3gVaRyFD2#7=0Owrr+l4~n z#Q>v_H4a?<^5+Zya66SJ58&Ka;pEy12!(uI2LQ}2L(3xi0ETjTJ_7)7am6o-=FUJq z{`>_1M`D|B$CYol0HAUHejWfg_iZ8hy5TH;-3^!LXj>5gnOlIS_;Coj?A43L!<_^NjV`eb^z7+rr;O|?(PyyO549Sl@0Kg!59sn>jG8X_0n)B<% z3i*3G0I(Q3u2{t11pxJ_0bohK{Q!VP_7VV4Ft-4U__hG1pz+5V{Gt(BWnhOSCIxEtq09g|Q9FT}UfO&%a`GEsuZyVr%<@+E2$GKzK z^6dfxMErKa0YCo$;5d>~1T(x4oefiPQF#nvFL9jZ$BO|@Ap6q*Cy<;XfD<^{=LCVw zeVpLFiYi}U7^vabmtYW^hZ8K?=OmJg4R8`e`nc>dW%a>&^#74n*BHxd|83p~z zko*`Uz!{34YYK1%_04bw*@pl)%iXvjj}P_v0nTzCHs|qirlh}5&+rfgfv9w!0;|256AeqQGmda*f1b)?sU0)-EfkhzY7SQyY`01Mbx(&gF|hMV}hm+}x`8tfokyt693GOBv`FAiv zWZW}AL46qv(JwTEu3>2gAi9Kst89L|Fvz(lZb`?VZw#DWys`|5#5*A$KjsVhka57k znZ%bz0e-F;VBq(UQNI6I*wwSzaYMoW{fgJPwxpS(4+tq@=Ygw0Qic>R9593!oLA-7 zhgmn?nG0!!?p^Kb?9us{nRUFt*fZaSeNM#6dot{0&)~a^Bc_*K_ka;|9i_WIuSFkw z90U$!oEBKWaau*}BkG~=$D`We!3-aJaA`W+Z0#^OPUG-WII(%iXP|?|@0XV%=l!>5 zIKFNi23}yCfz<{GM><@xL znQcI@Nb|9p=l)M)Ucc9Gy*H-R-k+7w=y|_8df=Mp@frl~Hd{m6(K|t#!7)b5zJ|uU z9)>pKOo2e3mLsAGka@Q?v=x3FZPDvt>bm5!KXAXMc^+Tk0^Qkl1*kE*M?1&QD3w7x z&w~JLb}m4`FTc0mB40pHEFHQK_d{Tkc%}^8lGx5(`$A7XJ04)X&@0XWh$<7;&DuKp zyws(>_mfZqJ@#_O8Gt^Q$A9Q6uv_RW@Ptr)|&>qsM<3LcQC)jkdi$iR;_;KCi>i6bvCpV%`d$ zGy3*^57c1rGhmDd_c1PYv75b&8*|-LRr+$?{Ex*LT@f;CKy#0Ms0_Q$^ zF#1O-sphjvoep)jy?&2T({n$J3jQj_yuS5$e^w$~`5r0piLv0yV64yr!B`{zZ(T}O z_v@~}mO(v{Sj&!@4Akq0ecQ`x4;VXe;VM5zj5N-r+I3&wiGCEu*|Fyk7~7r|THs%x zL*Ab$TI6Mb(7*nFJ@-hC*KJbH&V88r0Wmg$rwOQ1*1M3LtbB04&d4 zRK9mU7=W|`2zcn%WqEEY_MqclfokE4QPGP51a$Lj)N&3vP?zZL&0a8j#59X^Vv|AG}5DqsaZ4A__K=zT34Y0t@bhU&m!Yv)pSz5QPycx@;|4-$po zN~4(XOjYO)p(@`6aoF6(=MK#V%pDw0%oF%E%oBY-%#$(tYL|BG?HR1qy>E)O0$U~t zh_KVOR>T5p_c$9x0dzlks=QW!Q-M#!sf=lkK!#@bXXXB$6*&`oU22`*KLZMYYU`sg z80P=jXYd0kD2cs;d=SHlUF)?QVg_c1n9H9ZvEcnnKG4-5c3}M|eG6Y7lUJnDtM4y4 zV}HrjJ+B}a9EU=#=bqBYH`XTr;C+9|9X&%zlf&$Q+>slQJ7RBgM_rlRmniwo zHkepM^1$O$@`PRsc_J<$PvDkR9d|7OA@0Kdcp~;@wZIayvR6bwqRnS(%;RxZgV!in zQY*3jC@EaTSmbo9w!9Y3YN7SQYQeK+eN+Cv?MLo`d_1N)0d;Lt8}bh1?HD zty$GhkDtZl@!XVEf%B01U-*rx<#{Np0vE}eEzXac(Z6KP=zp+g=nAoBXgZ0R;XO1~ za#mO?@_p7~+QxeD9<7znZv{q#wF4_IHnGR@muyt*`Cbp^1?Gu$diu2ozP(Px*;r>g z?^q}quhnz5;1zKyY_NA>w%|=rW#yRn?F$aK_k8x@bxcYVCVv|}e?HK4;T+9tH=IKD z`I<*?f;mUzADjrTB`1QDL~%^w8p!i5w#jpZIy=oCq_ z_4_rye*O6QuTNhuIrZN@|NH5i;_KUAzkGRpzO?+G-hTM|&o9r{7YLr-et7@<`w#2o z{i*RH)r8S^{e + +%BOOK_ENTITIES; +]> + + + Florian + Weimer + + Red Hat + Product Security Team + + + fweimer@redhat.com + + + + diff --git a/defensive-coding/tmp/en-US/xml/Book_Info.xml b/defensive-coding/tmp/en-US/xml/Book_Info.xml new file mode 100644 index 0000000..94391ed --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Book_Info.xml @@ -0,0 +1,32 @@ + + +%BOOK_ENTITIES; +]> + + Defensive Coding + A Guide to Improving Software Security + 1.0 + 1.0 + + + + + + This document provides guidelines for improving software security through secure coding. It covers common programming languages and libraries, and focuses on concrete recommendations. + + + + + + + + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/xml/C/Allocators.xml b/defensive-coding/tmp/en-US/xml/C/Allocators.xml new file mode 100644 index 0000000..7aa5712 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/C/Allocators.xml @@ -0,0 +1,123 @@ + + +%BOOK_ENTITIES; +]> +

+ Memory allocators +
+ <function>malloc</function> and related functions + + The C library interfaces for memory allocation are provided by malloc, free and realloc, and the calloc function. In addition to these generic functions, there are derived functions such as strdup which perform allocation using malloc internally, but do not return untyped heap memory (which could be used for any object). + + + The C compiler knows about these functions and can use their expected behavior for optimizations. For instance, the compiler assumes that an existing pointer (or a pointer derived from an existing pointer by arithmetic) will not point into the memory area returned by malloc. + + + If the allocation fails, realloc does not free the old pointer. Therefore, the idiom ptr = realloc(ptr, size); is wrong because the memory pointed to by ptr leaks in case of an error. + +
+ Use-after-free errors + + After free, the pointer is invalid. Further pointer dereferences are not allowed (and are usually detected by valgrind). Less obvious is that any use of the old pointer value is not allowed, either. In particular, comparisons with any other pointer (or the null pointer) are undefined according to the C standard. + + + The same rules apply to realloc if the memory area cannot be enlarged in-place. For instance, the compiler may assume that a comparison between the old and new pointer will always return false, so it is impossible to detect movement this way. + + +
+ +
+ Handling memory allocation errors + + Recovering from out-of-memory errors is often difficult or even impossible. In these cases, malloc and other allocation functions return a null pointer. Dereferencing this pointer lead to a crash. Such dereferences can even be exploitable for code execution if the dereference is combined with an array subscript. + + + In general, if you cannot check all allocation calls and handle failure, you should abort the program on allocation failure, and not rely on the null pointer dereference to terminate the process. See for related memory allocation concerns. + + +
+ + +
+ +
+ <function>alloca</function> and other forms of stack-based allocation + + Allocation on the stack is risky because stack overflow checking is implicit. There is a guard page at the end of the memory area reserved for the stack. If the program attempts to read from or write to this guard page, a SIGSEGV signal is generated and the program typically terminates. + + + This is sufficient for detecting typical stack overflow situations such as unbounded recursion, but it fails when the stack grows in increments larger than the size of the guard page. In this case, it is possible that the stack pointer ends up pointing into a memory area which has been allocated for a different purposes. Such misbehavior can be exploitable. + + + A common source for large stack growth are calls to alloca and related functions such as strdupa. These functions should be avoided because of the lack of error checking. (They can be used safely if the allocated size is less than the page size (typically, 4096 bytes), but this case is relatively rare.) Additionally, relying on alloca makes it more difficult to reorgnize the code because it is not allowed to use the pointer after the function calling alloca has returned, even if this function has been inlined into its caller. + + + Similar concerns apply to variable-length arrays (VLAs), a feature of the C99 standard which started as a GNU extension. For large objects exceeding the page size, there is no error checking, either. + + + In both cases, negative or very large sizes can trigger a stack-pointer wraparound, and the stack pointer and end up pointing into caller stack frames, which is fatal and can be exploitable. + + + If you want to use alloca or VLAs for performance reasons, consider using a small on-stack array (less than the page size, large enough to fulfill most requests). If the requested size is small enough, use the on-stack array. Otherwise, call malloc. When exiting the function, check if malloc had been called, and free the buffer as needed. + + +
+ +
+ Array allocation + + When allocating arrays, it is important to check for overflows. The calloc function performs such checks. + + + If malloc or realloc is used, the size check must be written manually. For instance, to allocate an array of n elements of type T, check that the requested size is not greater than n / sizeof(T). + + +
+ +
+ Custom memory allocators + + Custom memory allocates come in two forms: replacements for malloc, and completely different interfaces for memory management. Both approaches can reduce the effectiveness of valgrind and similar tools, and the heap corruption detection provided by GNU libc, so they should be avoided. + + + Memory allocators are difficult to write and contain many performance and security pitfalls. + + + + + When computing array sizes or rounding up allocation requests (to the next allocation granularity, or for alignment purposes), checks for arithmetic overflow are required. + + + + + + Size computations for array allocations need overflow checking. See . + + + + + + It can be difficult to beat well-tuned general-purpose allocators. In micro-benchmarks, pool allocators can show huge wins, and size-specific pools can reduce internal fragmentation. But often, utilization of individual pools is poor, and + + + + + + +
+ +
+ Conservative garbage collection + + Garbage collection can be an alternative to explicit memory management using malloc and free. The Boehm-Dehmers-Weiser allocator can be used from C programs, with minimal type annotations. Performance is competitive with malloc on 64-bit architectures, especially for multi-threaded programs. The stop-the-world pauses may be problematic for some real-time applications, though. + + + However, using a conservative garbage collector may reduce opertunities for code reduce because once one library in a program uses garbage collection, the whole process memory needs to be subject to it, so that no pointers are missed. The Boehm-Dehmers-Weiser collector also reserves certain signals for internal use, so it is not fully transparent to the rest of the program. + + +
+ +
+ + diff --git a/defensive-coding/tmp/en-US/xml/C/C.xml b/defensive-coding/tmp/en-US/xml/C/C.xml new file mode 100644 index 0000000..8021dfb --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/C/C.xml @@ -0,0 +1,12 @@ + + +%BOOK_ENTITIES; +]> + + The C Programming Language + + + + + diff --git a/defensive-coding/tmp/en-US/xml/C/Language.xml b/defensive-coding/tmp/en-US/xml/C/Language.xml new file mode 100644 index 0000000..98a4a96 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/C/Language.xml @@ -0,0 +1,114 @@ + + +%BOOK_ENTITIES; +]> +
+ The core language + + C provides no memory safety. Most recommendations in this section deal with this aspect of the language. + +
+ Undefined behavior + + Some C constructs are defined to be undefined by the C standard. This does not only mean that the standard does not describe what happens when the construct is executed. It also allows optimizing compilers such as GCC to assume that this particular construct is never reached. In some cases, this has caused GCC to optimize security checks away. (This is not a flaw in GCC or the C language. But C certainly has some areas which are more difficult to use than others.) + + + Common sources of undefined behavior are: + + + + + out-of-bounds array accesses + + + + + null pointer dereferences + + + + + overflow in signed integer arithmetic + + + + + +
+ +
+ Recommendations for pointers and array handling + + Always keep track of the size of the array you are working with. Often, code is more obviously correct when you keep a pointer past the last element of the array, and calculate the number of remaining elements by substracting the current position from that pointer. The alternative, updating a separate variable every time when the position is advanced, is usually less obviously correct. + + + shows how to extract Pascal-style strings from a character buffer. The two pointers kept for length checks are inend and outend. inp and outp are the respective positions. The number of input bytes is checked using the expression len > (size_t)(inend - inp). The cast silences a compiler warning; inend is always larger than inp. + + + Array processing in C + + + + + It is important that the length checks always have the form len > (size_t)(inend - inp), where len is a variable of type size_t which denotes the total number of bytes which are about to be read or written next. In general, it is not safe to fold multiple such checks into one, as in len1 + len2 > (size_t)(inend - inp), because the expression on the left can overflow or wrap around (see ), and it no longer reflects the number of bytes to be processed. + + +
+ +
+ Recommendations for integer arithmetic + + Overflow in signed integer arithmetic is undefined. This means that it is not possible to check for overflow after it happened, see . + + + Incorrect overflow detection in C + + + + + The following approaches can be used to check for overflow, without actually causing it. + + + + + Use a wider type to perform the calculation, check that the result is within bounds, and convert the result to the original type. All intermediate results must be checked in this way. + + + + + + Perform the calculation in the corresponding unsigned type and use bit fiddling to detect the overflow. + + + + + + Compute bounds for acceptable input values which are known to avoid overflow, and reject other values. This is the preferred way for overflow checking on multiplications, see . + + + + + + + Overflow checking for unsigned multiplication + + + + + Basic arithmetic operations a commutative, so for bounds checks, there are two different but mathematically equivalent expressions. Sometimes, one of the expressions results in better code because parts of it can be reduced to a constant. This applies to overflow checks for multiplication a * b involving a constant a, where the expression is reduced to b > C for some constant C determined at compile time. The other expression, b && a > ((unsigned)-1) / b, is more difficult to optimize at compile time. + + + When a value is converted to a signed integer, GCC always chooses the result based on 2's complement arithmetic. This GCC extension (which is also implemented by other compilers) helps a lot when implementing overflow checks. + + + Legacy code should be compiled with the GCC option. As a result, GCC will provide 2's complement semantics for integer arithmetic, including defined behavior on integer overflow. + + +
+ +
+ + diff --git a/defensive-coding/tmp/en-US/xml/C/Libc.xml b/defensive-coding/tmp/en-US/xml/C/Libc.xml new file mode 100644 index 0000000..dbaa331 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/C/Libc.xml @@ -0,0 +1,200 @@ + + +%BOOK_ENTITIES; +]> +
+ The C standard library + + Parts of the C standard library (and the UNIX and GNU extensions) are difficult to use, so you shoud avoid them. + + + Please check the applicable documentation before using the recommended replacements. Many of these functions allocate buffers using malloc which your code must deallocate explicitly using free. + +
+ Absolutely banned interfaces + + The functions listed below must not be used because they are almost always unsafe. Use the indicated replacements instead. + + + + + getsfgets + + + + + getwdgetcwd or get_current_dir_name + + + + + readdir_rreaddir + + + + + + realpath (with a non-NULL second parameter) ⟶ realpath with NULL as the second parameter, or canonicalize_file_name + + + + + + + The constants listed below must not be used, either. Instead, code must allocate memory dynamically and use interfaces with length checking. + + + + + NAME_MAX (limit not actually enforced by the kernel) + + + + + + PATH_MAX (limit not actually enforced by the kernel) + + + + + + _PC_NAME_MAX (This limit, returned by the pathconf function, is not enforced by the kernel.) + + + + + + _PC_PATH_MAX (This limit, returned by the pathconf function, is not enforced by the kernel.) + + + + + + + The following structure members must not be used. + + + + + f_namemax in struct statvfs (limit not actually enforced by the kernel, see _PC_NAME_MAX above) + + + + + + +
+ +
+ Functions to avoid + + The following string manipulation functions can be used securely in principle, but their use should be avoided because they are difficult to use correctly. Calls to these functions can be replaced with asprintf or vasprintf. (For non-GNU targets, these functions are available from Gnulib.) In some cases, the snprintf function might be a suitable replacement, see . + + + + + sprintf + + + + + strcat + + + + + strcpy + + + + + vsprintf + + + + + + Use the indicated replacements for the functions below. + + + + + allocamalloc and free (see ) + + + + + + putenv ⟶ explicit envp argument in process creation (see ) + + + + + + setenv ⟶ explicit envp argument in process creation (see ) + + + + + + strdupastrdup and free (see ) + + + + + + strndupastrndup and free (see ) + + + + + + systemposix_spawn or fork/execve/ (see ) + + + + + + unsetenv ⟶ explicit envp argument in process creation (see ) + + + + + + +
+ +
+ String Functions With Explicit Length Arguments + + The snprintf function provides a way to construct a string in a statically-sized buffer. (If the buffer size is dynamic, use asprintf instead.) + + + + The second argument to the snprintf should always be the size of the buffer in the first argument (which should be a character array). Complex pointer and length arithmetic can introduce errors and nullify the security benefits of snprintf. If you need to construct a string iteratively, by repeatedly appending fragments, consider constructing the string on the heap, increasing the buffer with realloc as needed. (snprintf does not support overlapping the result buffer with argument strings.) + + + If you use vsnprintf (or snprintf) with a format string which is not a constant, but a function argument, it is important to annotate the function with a format function attribute, so that GCC can warn about misuse of your function (see ). + + + The <literal>format</literal> function attribute + + + + + There are other functions which operator on NUL-terminated strings and take a length argument which affects the number of bytes written to the destination: strncpy, strncat, and stpncpy. These functions do not ensure that the result string is NUL-terminated. For strncpy, NUL termination can be added this way: + + + + Some systems support strlcpy and strlcat functions which behave this way, but these functions are not part of GNU libc. Using snprintf with a suitable format string is a simple (albeit slightly slower) replacement. + + +
+ +
+ + diff --git a/defensive-coding/tmp/en-US/xml/C/schemas.xml b/defensive-coding/tmp/en-US/xml/C/schemas.xml new file mode 100644 index 0000000..31581c3 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/C/schemas.xml @@ -0,0 +1,6 @@ + + +%BOOK_ENTITIES; +]> + diff --git a/defensive-coding/tmp/en-US/xml/C/snippets/Arithmetic-add.xml b/defensive-coding/tmp/en-US/xml/C/snippets/Arithmetic-add.xml new file mode 100644 index 0000000..b1b417c --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/C/snippets/Arithmetic-add.xml @@ -0,0 +1,24 @@ + + +%BOOK_ENTITIES; +]> + + +void report_overflow(void); + +int +add(int a, int b) +{ + int result = a + b; + if (a < 0 || b < 0) { + return -1; + } + // The compiler can optimize away the following if statement. + if (result < 0) { + report_overflow(); + } + return result; +} + + diff --git a/defensive-coding/tmp/en-US/xml/C/snippets/Arithmetic-mult.xml b/defensive-coding/tmp/en-US/xml/C/snippets/Arithmetic-mult.xml new file mode 100644 index 0000000..945f1b3 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/C/snippets/Arithmetic-mult.xml @@ -0,0 +1,17 @@ + + +%BOOK_ENTITIES; +]> + + +unsigned +mul(unsigned a, unsigned b) +{ + if (b && a > ((unsigned)-1) / b) { + report_overflow(); + } + return a * b; +} + + diff --git a/defensive-coding/tmp/en-US/xml/C/snippets/Pointers-remaining.xml b/defensive-coding/tmp/en-US/xml/C/snippets/Pointers-remaining.xml new file mode 100644 index 0000000..cb781d0 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/C/snippets/Pointers-remaining.xml @@ -0,0 +1,52 @@ + + +%BOOK_ENTITIES; +]> + + +ssize_t +extract_strings(const char *in, size_t inlen, char **out, size_t outlen) +{ + const char *inp = in; + const char *inend = in + inlen; + char **outp = out; + char **outend = out + outlen; + + while (inp != inend) { + size_t len; + char *s; + if (outp == outend) { + errno = ENOSPC; + goto err; + } + len = (unsigned char)*inp; + ++inp; + if (len > (size_t)(inend - inp)) { + errno = EINVAL; + goto err; + } + s = malloc(len + 1); + if (s == NULL) { + goto err; + } + memcpy(s, inp, len); + inp += len; + s[len] = '\0'; + *outp = s; + ++outp; + } + return outp - out; +err: + { + int errno_old = errno; + while (out != outp) { + free(*out); + ++out; + } + errno = errno_old; + } + return -1; +} + + diff --git a/defensive-coding/tmp/en-US/xml/C/snippets/String-Functions-format.xml b/defensive-coding/tmp/en-US/xml/C/snippets/String-Functions-format.xml new file mode 100644 index 0000000..ebc531e --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/C/snippets/String-Functions-format.xml @@ -0,0 +1,21 @@ + + +%BOOK_ENTITIES; +]> + + +void log_format(const char *format, ...) __attribute__((format(printf, 1, 2))); + +void +log_format(const char *format, ...) +{ + char buf[1000]; + va_list ap; + va_start(ap, format); + vsnprintf(buf, sizeof(buf), format, ap); + va_end(ap); + log_string(buf); +} + + diff --git a/defensive-coding/tmp/en-US/xml/C/snippets/String-Functions-snprintf.xml b/defensive-coding/tmp/en-US/xml/C/snippets/String-Functions-snprintf.xml new file mode 100644 index 0000000..ceec25c --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/C/snippets/String-Functions-snprintf.xml @@ -0,0 +1,11 @@ + + +%BOOK_ENTITIES; +]> + + +char fraction[30]; +snprintf(fraction, sizeof(fraction), "%d/%d", numerator, denominator); + + diff --git a/defensive-coding/tmp/en-US/xml/C/snippets/String-Functions-strncpy.xml b/defensive-coding/tmp/en-US/xml/C/snippets/String-Functions-strncpy.xml new file mode 100644 index 0000000..89ef63d --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/C/snippets/String-Functions-strncpy.xml @@ -0,0 +1,12 @@ + + +%BOOK_ENTITIES; +]> + + +char buf[10]; +strncpy(buf, data, sizeof(buf)); +buf[sizeof(buf) - 1] = '\0'; + + diff --git a/defensive-coding/tmp/en-US/xml/CXX/CXX.xml b/defensive-coding/tmp/en-US/xml/CXX/CXX.xml new file mode 100644 index 0000000..8cf2f42 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/CXX/CXX.xml @@ -0,0 +1,11 @@ + + +%BOOK_ENTITIES; +]> + + The C++ Programming Language + + + + diff --git a/defensive-coding/tmp/en-US/xml/CXX/Language.xml b/defensive-coding/tmp/en-US/xml/CXX/Language.xml new file mode 100644 index 0000000..d8d7c18 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/CXX/Language.xml @@ -0,0 +1,132 @@ + + +%BOOK_ENTITIES; +]> +
+ The core language + + C++ includes a large subset of the C language. As far as the C subset is used, the recommendations in apply. + +
+ Array allocation with <literal>operator new[]</literal> + + For very large values of n, an expression like new T[n] can return a pointer to a heap region which is too small. In other words, not all array elements are actually backed with heap memory reserved to the array. Current GCC versions generate code that performs a computation of the form sizeof(T) * size_t(n) + cookie_size, where cookie_size is currently at most 8. This computation can overflow, and GCC-generated code does not detect this. + + + The std::vector template can be used instead an explicit array allocation. (The GCC implementation detects overflow internally.) + + + If there is no alternative to operator new[], code which allocates arrays with a variable length must check for overflow manually. For the new T[n] example, the size check could be n || (n > 0 && n > (size_t(-1) - 8) / sizeof(T)). (See .) If there are additional dimensions (which must be constants according to the C++ standard), these should be included as factors in the divisor. + + + These countermeasures prevent out-of-bounds writes and potential code execution. Very large memory allocations can still lead to a denial of service. contains suggestions for mitigating this problem when processing untrusted data. + + + See for array allocation advice for C-style memory allocation. + + +
+ +
+ Overloading + + Do not overload functions with versions that have different security characteristics. For instance, do not implement a function strcat which works on std::string arguments. Similarly, do not name methods after such functions. + + +
+ +
+ ABI compatibility and preparing for security updates + + A stable binary interface (ABI) is vastly preferred for security updates. Without a stable ABI, all reverse dependencies need recompiling, which can be a lot of work and could even be impossible in some cases. Ideally, a security update only updates a single dynamic shared object, and is picked up automatically after restarting affected processes. + + + Outside of extremely performance-critical code, you should ensure that a wide range of changes is possible without breaking ABI. Some very basic guidelines are: + + + + + Avoid inline functions. + + + + + + Use the pointer-to-implementation idiom. + + + + + + Try to avoid templates. Use them if the increased type safety provides a benefit to the programmer. + + + + + + Move security-critical code out of templated code, so that it can be patched in a central place if necessary. + + + + + + + The KDE project publishes a document with more extensive guidelines on ABI-preserving changes to C++ code, Policies/Binary Compatibility Issues With C++ (d-pointer refers to the pointer-to-implementation idiom). + + +
+ +
+ C++0X and C++11 support + + GCC offers different language compatibility modes: + + + + + for the original 1998 C++ standard + + + + + + for the 1998 standard with the changes from the TR1 technical report + + + + + + for the 2011 C++ standard. This option should not be used. + + + + + + for several different versions of C++11 support in development, depending on the GCC version. This option should not be used. + + + + + + + For each of these flags, there are variants which also enable GNU extensions (mostly language features also found in C99 or C11): , , . Again, should not be used. + + + If you enable C++11 support, the ABI of the standard C++ library libstdc++ will change in subtle ways. Currently, no C++ libraries are compiled in C++11 mode, so if you compile your code in C++11 mode, it will be incompatible with the rest of the system. Unfortunately, this is also the case if you do not use any C++11 features. Currently, there is no safe way to enable C++11 mode (except for freestanding applications). + + + The meaning of C++0X mode changed from GCC release to GCC release. Earlier versions were still ABI-compatible with C++98 mode, but in the most recent versions, switching to C++0X mode activates C++11 support, with its compatibility problems. + + + Some C++11 features (or approximations thereof) are available with TR1 support, that is, with or and in the <tr1/*> header files. This includes std::tr1::shared_ptr (from <tr1/memory>) and std::tr1::function (from <tr1/functional>). For other C++11 features, the Boost C++ library contains replacements. + + +
+ +
+ + diff --git a/defensive-coding/tmp/en-US/xml/CXX/Std.xml b/defensive-coding/tmp/en-US/xml/CXX/Std.xml new file mode 100644 index 0000000..7fa43d7 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/CXX/Std.xml @@ -0,0 +1,24 @@ + + +%BOOK_ENTITIES; +]> +
+ The C++ standard library + + The C++ standard library includes most of its C counterpart by reference, see . + +
+ Containers and <literal>operator[]</literal> + + Many containers similar to std::vector provide both operator[](size_type) and a member function at(size_type). This applies to std::vector itself, std::array, std::string and other instances of std::basic_string. + + + operator[](size_type) is not required by the standard to perform bounds checking (and the implementation in GCC does not). In contrast, at(size_type) must perform such a check. Therefore, in code which is not performance-critical, you should prefer at(size_type) over operator[](size_type), even though it is slightly more verbose. + + +
+ +
+ + diff --git a/defensive-coding/tmp/en-US/xml/CXX/schemas.xml b/defensive-coding/tmp/en-US/xml/CXX/schemas.xml new file mode 100644 index 0000000..31581c3 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/CXX/schemas.xml @@ -0,0 +1,6 @@ + + +%BOOK_ENTITIES; +]> + diff --git a/defensive-coding/tmp/en-US/xml/Common_Content/Conventions.xml b/defensive-coding/tmp/en-US/xml/Common_Content/Conventions.xml new file mode 100644 index 0000000..e9a14f2 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Common_Content/Conventions.xml @@ -0,0 +1,178 @@ + + +%BOOK_ENTITIES; +]> +
+ Document Conventions + + This manual uses several conventions to highlight certain words and phrases and draw attention to specific pieces of information. + + + In PDF and paper editions, this manual uses typefaces drawn from the Liberation Fonts set. The Liberation Fonts set is also used in HTML editions if the set is installed on your system. If not, alternative but equivalent typefaces are displayed. Note: Red Hat Enterprise Linux 5 and later includes the Liberation Fonts set by default. + +
+ Typographic Conventions + + Four typographic conventions are used to call attention to specific words and phrases. These conventions, and the circumstances they apply to, are as follows. + + + Mono-spaced Bold + + + Used to highlight system input, including shell commands, file names and paths. Also used to highlight keycaps and key combinations. For example: + +
+ + To see the contents of the file my_next_bestselling_novel in your current working directory, enter the cat my_next_bestselling_novel command at the shell prompt and press Enter to execute the command. + + +
+ + The above includes a file name, a shell command and a keycap, all presented in mono-spaced bold and all distinguishable thanks to context. + + + Key combinations can be distinguished from keycaps by the hyphen connecting each part of a key combination. For example: + +
+ + Press Enter to execute the command. + + + Press CtrlAltF2 to switch to the first virtual terminal. Press CtrlAltF1 to return to your X-Windows session. + + +
+ + The first paragraph highlights the particular keycap to press. The second highlights two key combinations (each a set of three keycaps with each set pressed simultaneously). + + + If source code is discussed, class names, methods, functions, variable names and returned values mentioned within a paragraph will be presented as above, in mono-spaced bold. For example: + +
+ + File-related classes include filesystem for file systems, file for files, and dir for directories. Each class has its own associated set of permissions. + + +
+ + Proportional Bold + + + This denotes words or phrases encountered on a system, including application names; dialog box text; labeled buttons; check-box and radio button labels; menu titles and sub-menu titles. For example: + +
+ + Choose SystemPreferencesMouse from the main menu bar to launch Mouse Preferences. In the Buttons tab, click the Left-handed mouse check box and click Close to switch the primary mouse button from the left to the right (making the mouse suitable for use in the left hand). + + + To insert a special character into a gedit file, choose ApplicationsAccessoriesCharacter Map from the main menu bar. Next, choose SearchFind… from the Character Map menu bar, type the name of the character in the Search field and click Next. The character you sought will be highlighted in the Character Table. Double-click this highlighted character to place it in the Text to copy field and then click the Copy button. Now switch back to your document and choose EditPaste from the gedit menu bar. + + +
+ + The above text includes application names; system-wide menu names and items; application-specific menu names; and buttons and text found within a GUI interface, all presented in proportional bold and all distinguishable by context. + + + Mono-spaced Bold Italic or Proportional Bold Italic + + + Whether mono-spaced bold or proportional bold, the addition of italics indicates replaceable or variable text. Italics denotes text you do not input literally or displayed text that changes depending on circumstance. For example: + +
+ + To connect to a remote machine using ssh, type ssh username@domain.name at a shell prompt. If the remote machine is example.com and your username on that machine is john, type ssh john@example.com. + + + The mount -o remount file-system command remounts the named file system. For example, to remount the /home file system, the command is mount -o remount /home. + + + To see the version of a currently installed package, use the rpm -q package command. It will return a result as follows: package-version-release. + + +
+ + Note the words in bold italics above — username, domain.name, file-system, package, version and release. Each word is a placeholder, either for text you enter when issuing a command or for text displayed by the system. + + + Aside from standard usage for presenting the title of a work, italics denotes the first use of a new and important term. For example: + +
+ + Publican is a DocBook publishing system. + + +
+ +
+ +
+ Pull-quote Conventions + + Terminal output and source code listings are set off visually from the surrounding text. + + + Output sent to a terminal is set in mono-spaced roman and presented thus: + + +books Desktop documentation drafts mss photos stuff svn +books_tests Desktop1 downloads images notes scripts svgs + + Source-code listings are also set in mono-spaced roman but add syntax highlighting as follows: + + +package org.jboss.book.jca.ex1; + +import javax.naming.InitialContext; + +public class ExClient +{ + public static void main(String args[]) + throws Exception + { + InitialContext iniCtx = new InitialContext(); + Object ref = iniCtx.lookup("EchoBean"); + EchoHome home = (EchoHome) ref; + Echo echo = home.create(); + + System.out.println("Created Echo"); + + System.out.println("Echo.echo('Hello') = " + echo.echo("Hello")); + } +} + +
+ +
+ Notes and Warnings + + Finally, we use three visual styles to draw attention to information that might otherwise be overlooked. + + + Note + + Notes are tips, shortcuts or alternative approaches to the task at hand. Ignoring a note should have no negative consequences, but you might miss out on a trick that makes your life easier. + + + + + Important + + Important boxes detail things that are easily missed: configuration changes that only apply to the current session, or services that need restarting before an update will apply. Ignoring a box labeled 'Important' will not cause data loss but may cause irritation and frustration. + + + + + Warning + + Warnings should not be ignored. Ignoring warnings will most likely cause data loss. + + + + +
+ + +
+ + diff --git a/defensive-coding/tmp/en-US/xml/Common_Content/Feedback.xml b/defensive-coding/tmp/en-US/xml/Common_Content/Feedback.xml new file mode 100644 index 0000000..c8d09ad --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Common_Content/Feedback.xml @@ -0,0 +1,24 @@ + + +%BOOK_ENTITIES; +]> +
+ We Need Feedback! + + feedback + contact information for this manual + + + + If you find a typographical error in this manual, or if you have thought of a way to make this manual better, we would love to hear from you! Please submit a report in Bugzilla: http://bugzilla.redhat.com/bugzilla/ against the product &PRODUCT;. + + + When submitting a bug report, be sure to mention the manual's identifier: &BOOKID; + + + If you have a suggestion for improving the documentation, try to be as specific as possible when describing it. If you have found an error, please include the section number and some of the surrounding text so we can find it easily. + +
+ + diff --git a/defensive-coding/tmp/en-US/xml/Common_Content/Legal_Notice.xml b/defensive-coding/tmp/en-US/xml/Common_Content/Legal_Notice.xml new file mode 100644 index 0000000..0ef1087 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Common_Content/Legal_Notice.xml @@ -0,0 +1,38 @@ + + +%BOOK_ENTITIES; +]> + + + Copyright &YEAR; &HOLDER;. + + + The text of and illustrations in this document are licensed by Red Hat under a Creative Commons Attribution–Share Alike 3.0 Unported license ("CC-BY-SA"). An explanation of CC-BY-SA is available at . The original authors of this document, and Red Hat, designate the Fedora Project as the "Attribution Party" for purposes of CC-BY-SA. In accordance with CC-BY-SA, if you distribute this document or an adaptation of it, you must provide the URL for the original version. + + + Red Hat, as the licensor of this document, waives the right to enforce, and agrees not to assert, Section 4d of CC-BY-SA to the fullest extent permitted by applicable law. + + + Red Hat, Red Hat Enterprise Linux, the Shadowman logo, JBoss, MetaMatrix, Fedora, the Infinity Logo, and RHCE are trademarks of Red Hat, Inc., registered in the United States and other countries. + + + For guidelines on the permitted uses of the Fedora trademarks, refer to . + + + Linux is the registered trademark of Linus Torvalds in the United States and other countries. + + + Java is a registered trademark of Oracle and/or its affiliates. + + + XFS is a trademark of Silicon Graphics International Corp. or its subsidiaries in the United States and/or other countries. + + + MySQL is a registered trademark of MySQL AB in the United States, the European Union and other countries. + + + All other trademarks are the property of their respective owners. + + + diff --git a/defensive-coding/tmp/en-US/xml/Common_Content/css/common.css b/defensive-coding/tmp/en-US/xml/Common_Content/css/common.css new file mode 100644 index 0000000..d7dc3f2 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Common_Content/css/common.css @@ -0,0 +1,1528 @@ +* { + widows: 2 !important; + orphans: 2 !important; +} + +body, h1, h2, h3, h4, h5, h6, pre, li, div { + line-height: 1.29em; +} + +body { + background-color: white; + margin:0 auto; + font-family: "liberation sans", "Myriad ", "Bitstream Vera Sans", "Lucida Grande", "Luxi Sans", "Trebuchet MS", helvetica, verdana, arial, sans-serif; + font-size:12px; + max-width:55em; + color:black; +} + +body.toc_embeded { + /*for web hosting system only*/ + margin-left: 300px; +} + +object.toc, iframe.toc { + /*for web hosting system only*/ + border-style:none; + position:fixed; + width:290px; + height:99.99%; + top:0; + left:0; + z-index: 100; + border-style:none; + border-right:1px solid #999; +} + +/* Hide web menu */ + +body.notoc { + margin-left: 3em; +} + +iframe.notoc { + border-style:none; + border: none; + padding: 0em; + position:fixed; + width: 21px; + height: 29px; + top: 0px; + left:0; + overflow: hidden; + margin: 0em; + margin-left: -3px; +} +/* End hide web menu */ + +/* desktop styles */ +body.desktop { + margin-left: 26em; +} + +body.desktop .book > .toc { + display:block; + width:24em; + height:99%; + position:fixed; + overflow:auto; + top:0px; + left:0px; + padding-left:1em; + background-color:#EEEEEE; +} + +.toc { + line-height:1.35em; +} + +.toc .glossary, +.toc .chapter, .toc .appendix { + margin-top:1em; +} + +.toc .part { + margin-top:1em; + display:block; +} + +span.glossary, +span.appendix { + display:block; + margin-top:0.5em; +} + +div { + padding-top:0px; +} + +div.section { + padding-top:1em; +} + +p, div.para, div.formalpara { + padding-top:0px; + margin-top:0.3em; + padding-bottom:0px; + margin-bottom:1em; +} + +/*Links*/ +a { + outline: none; +} + +a:link { + text-decoration:none; + border-bottom: 1px dotted ; + color:#3366cc; +} + +a:visited { + text-decoration:none; + border-bottom: 1px dotted ; + color:#003366; +} + +div.longdesc-link { + float:right; + color:#999; +} + +.toc a, .qandaset a { + font-weight:normal; + border:none; +} + +.toc a:hover, .qandaset a:hover +{ + border-bottom: 1px dotted; +} + +/*headings*/ +h1, h2, h3, h4, h5, h6 { + color: #336699; + margin-top: 0em; + margin-bottom: 0em; + background-color: transparent; + page-break-inside: avoid; + page-break-after: avoid; +} + +h1 { + font-size:2.0em; +} + +.titlepage h1.title { + font-size: 3.0em; + padding-top: 1em; + text-align:left; +} + +.book > .titlepage h1.title { + text-align:center; +} + +.article > .titlepage h1.title { + text-align:center; +} + +.set .titlepage > div > div > h1.title { + text-align:center; +} + +.producttitle { + margin-top: 0em; + margin-bottom: 0em; + font-size: 3.0em; + font-weight: bold; + background: #003d6e url(../images/h1-bg.png) top left repeat-x; + color: white; + text-align: center; + padding: 0.7em; +} + +.titlepage .corpauthor { + margin-top: 1em; + text-align: center; +} + +.section h1.title { + font-size: 1.6em; + padding: 0em; + color: #336699; + text-align: left; + background: white; +} + +h2 { + font-size:1.6em; +} + + +h2.subtitle, h3.subtitle { + margin-top: 1em; + margin-bottom: 1em; + font-size: 1.4em; + text-align: center; +} + +.preface > div > div > div > h2.title { + margin-top: 1em; + font-size: 2.0em; +} + +.appendix h2 { + margin-top: 1em; + font-size: 2.0em; +} + + + +h3 { + font-size:1.3em; + padding-top:0em; + padding-bottom:0em; +} +h4 { + font-size:1.1em; + padding-top:0em; + padding-bottom:0em; +} + +h5 { + font-size:1em; +} + +h6 { + font-size:1em; +} + +h5.formalpara { + font-size:1em; + margin-top:2em; + margin-bottom:.8em; +} + +.abstract h6 { + margin-top:1em; + margin-bottom:.5em; + font-size:2em; +} + +/*element rules*/ +hr { + border-collapse: collapse; + border-style:none; + border-top: 1px dotted #ccc; + width:100%; + margin-top: 3em; +} + +/* web site rules */ +ul.languages, .languages li { + display:inline; + padding:0em; +} + +.languages li a { + padding:0em .5em; + text-decoration: none; +} + +.languages li p, .languages li div.para { + display:inline; +} + +.languages li a:link, .languages li a:visited { + color:#444; +} + +.languages li a:hover, .languages li a:focus, .languages li a:active { + color:black; +} + +ul.languages { + display:block; + background-color:#eee; + padding:.5em; +} + +/*supporting stylesheets*/ + +/*unique to the webpage only*/ +.books { + position:relative; +} + +.versions li { + width:100%; + clear:both; + display:block; +} + +a.version { + font-size:2em; + text-decoration:none; + width:100%; + display:block; + padding:1em 0em .2em 0em; + clear:both; +} + +a.version:before { + content:"Version"; + font-size:smaller; +} + +a.version:visited, a.version:link { + color:#666; +} + +a.version:focus, a.version:hover { + color:black; +} + +.books { + display:block; + position:relative; + clear:both; + width:100%; +} + +.books li { + display:block; + width:200px; + float:left; + position:relative; + clear: none ; +} + +.books .html { + width:170px; + display:block; +} + +.books .pdf { + position:absolute; + left:170px; + top:0px; + font-size:smaller; +} + +.books .pdf:link, .books .pdf:visited { + color:#555; +} + +.books .pdf:hover, .books .pdf:focus { + color:#000; +} + +.books li a { + text-decoration:none; +} + +.books li a:hover { + color:black; +} + +/*products*/ +.products li { + display: block; + width:300px; + float:left; +} + +.products li a { + width:300px; + padding:.5em 0em; +} + +.products ul { + clear:both; +} + +/*revision history*/ +.revhistory { + display:block; +} + +.revhistory table { + background-color:transparent; + border-color:#fff; + padding:0em; + margin: 0; + border-collapse:collapse; + border-style:none; +} + +.revhistory td { + text-align :left; + padding:0em; + border: none; + border-top: 1px solid #fff; + font-weight: bold; +} + +.revhistory .simplelist td { + font-weight: normal; +} + +.revhistory .simplelist { + margin-bottom: 1.5em; + margin-left: 1em; +} + +.revhistory table th { + display: none; +} + + +/*credits*/ +.authorgroup div { + clear:both; + text-align: center; +} + +h3.author { + margin: 0em; + padding: 0em; + padding-top: 1em; +} + +.authorgroup h4 { + padding: 0em; + margin: 0em; + padding-top: 1em; + margin-top: 1em; +} + +.author, +.editor, +.translator, +.othercredit, +.contrib { + display: block; +} + +.revhistory .author { + display: inline; +} + +.othercredit h3 { + padding-top: 1em; +} + + +.othercredit { + margin:0em; + padding:0em; +} + +.releaseinfo { + clear: both; +} + +.copyright { + margin-top: 1em; +} + +/* qanda sets */ +.answer { + margin-bottom:1em; + border-bottom:1px dotted #ccc; +} + +.qandaset .toc { + border-bottom:1px dotted #ccc; +} + +.question { + font-weight:bold; +} + +.answer .data, .question .data { + padding-left: 2.6em; +} + +.answer label, .question label { + float:left; + font-weight:bold; +} + +/* inline syntax highlighting */ +.perl_Alert { + color: #0000ff; +} + +.perl_BaseN { + color: #007f00; +} + +.perl_BString { + color: #5C3566; +} + +.perl_Char { + color: #ff00ff; +} + +.perl_Comment { + color: #FF00FF; +} + + +.perl_DataType { + color: #0000ff; +} + + +.perl_DecVal { + color: #00007f; +} + + +.perl_Error { + color: #ff0000; +} + + +.perl_Float { + color: #00007f; +} + + +.perl_Function { + color: #007f00; +} + + +.perl_IString { + color: #5C3566; +} + + +.perl_Keyword { + color: #002F5D; +} + + +.perl_Operator { + color: #ffa500; +} + + +.perl_Others { + color: #b03060; +} + + +.perl_RegionMarker { + color: #96b9ff; +} + + +.perl_Reserved { + color: #9b30ff; +} + + +.perl_String { + color: #5C3566; +} + + +.perl_Variable { + color: #0000ff; +} + + +.perl_Warning { + color: #0000ff; +} + +/*Lists*/ +ul { + padding-left:1.6em; + list-style-image:url(../images/dot.png); + list-style-type: circle; +} + +ul ul { + list-style-image:url(../images/dot2.png); + list-style-type: circle; +} + +ol { + list-style-image:none; + list-style-type: decimal; +} + +ol ol { + list-style-type: lower-alpha; +} + +ol.arabic { + list-style-type: decimal; +} + +ol.loweralpha { + list-style-type: lower-alpha; +} + +ol.lowerroman { + list-style-type: lower-roman; +} + +ol.upperalpha { + list-style-type: upper-alpha; +} + +ol.upperroman { + list-style-type: upper-roman; +} + +dt { + font-weight:bold; + margin-bottom:0em; + padding-bottom:0em; +} + +dd { + margin:0em; + margin-left:2em; + padding-top:0em; + padding-bottom: 1em; +} + +li { + padding-top:0px; + margin-top:0em; + padding-bottom:0px; + margin-bottom:0.4em; +} + +li p, li div.para { + padding-top:0px; + margin-top:0em; + padding-bottom:0px; + margin-bottom:0.3em; +} + +/*images*/ +img { + display:block; + margin: 2em 0; +} + +.inlinemediaobject, .inlinemediaobject img { + display:inline; + margin:0em; +} + +.figure img { + display:block; + margin:0; + page-break-inside: avoid; +} + +.figure .title { + margin:0em; + margin-bottom:2em; + padding:0px; +} + +/*document modes*/ +.confidential { + background-color:#900; + color:White; + padding:.5em .5em; + text-transform:uppercase; + text-align:center; +} + +.longdesc-link { + display:none; +} + +.longdesc { + display:none; +} + +.prompt { + padding:0em .3em; +} + +/*user interface styles*/ +.screen .replaceable { +} + +.guibutton, .guilabel { + font-family: "liberation mono", "bitstream vera mono", "dejavu mono", monospace; + font-weight: bold; + white-space: nowrap; +} + +.example { + background-color: #ffffff; + border-left: 3px solid #aaaaaa; + padding-top: 1em; + padding-bottom: 0.1em; +} + +.example h6 { + padding-left: 10px; +} + +.example-contents { + padding-left: 10px; + background-color: #ffffff; +} + +.example-contents .para { +/* padding: 10px;*/ +} + +/*terminal/console text*/ +.computeroutput, +.option { + font-family:"liberation mono", "bitstream vera mono", "dejavu mono", monospace; + font-weight:bold; +} + +.replaceable { + font-family:"liberation mono", "bitstream vera mono", "dejavu mono", monospace; + font-style: italic; +} + +.command, .filename, .keycap, .classname, .literal { + font-family:"liberation mono", "bitstream vera mono", "dejavu mono", monospace; + font-weight:bold; +} + +/* no bold in toc */ +.toc * { + font-weight: inherit; +} + +pre { + font-family:"liberation mono", "bitstream vera mono", "dejavu mono", monospace; + display:block; + background-color: #f5f5f5; + color: #000000; + border: 1px solid #aaaaaa; + margin-bottom: 0.3em; + padding:.5em 1em; + white-space: pre-wrap; /* css-3 */ + white-space: -moz-pre-wrap !important; /* Mozilla, since 1999 */ + white-space: -pre-wrap; /* Opera 4-6 */ + white-space: -o-pre-wrap; /* Opera 7 */ + word-wrap: break-word; /* Internet Explorer 5.5+ */ + font-size: 0.9em; +} + +pre .replaceable, +pre .keycap { +} + +code { + font-family:"liberation mono", "bitstream vera mono", "dejavu mono", monospace; +/* white-space: nowrap;*/ + white-space: pre-wrap; + word-wrap: break-word; + font-weight:bold; +} + +.parameter code { + display: inline; + white-space: pre-wrap; /* css-3 */ + white-space: -moz-pre-wrap !important; /* Mozilla, since 1999 */ + white-space: -pre-wrap; /* Opera 4-6 */ + white-space: -o-pre-wrap; /* Opera 7 */ + word-wrap: break-word; /* Internet Explorer 5.5+ */ +} + +/*Notifications*/ +div.warning:before { + content:url(../images/warning.png); + padding-left: 5px; +} + +div.note:before { + content:url(../images/note.png); + padding-left: 5px; +} + +div.important:before { + content:url(../images/important.png); + padding-left: 5px; +} + +div.warning, div.note, div.important { + color: black; + margin: 0em; + padding: 0em; + background: none; + background-color: white; + margin-bottom: 1em; + border-bottom: 1px solid #aaaaaa; + page-break-inside: avoid; +} + +div.warning h2, div.note h2,div.important h2 { + margin: 0em; + padding: 0em; + color: #eeeeec; + padding-top: 0px; + padding-bottom: 0px; + height: 1.4em; + line-height: 1.4em; + font-size: 1.4em; + display:inline; +} + +div.admonition_header { + clear: both; + margin: 0em; + padding: 0em; + margin-top: -3.3em; + padding-left: 58px; + line-height: 1.0em; + font-size: 1.0em; +} + +div.warning div.admonition_header { + background: url(../images/red.png) top left repeat-x; + background-color: #590000; +} + +div.note div.admonition_header { + background: url(../images/green.png) top right repeat-x; + background-color: #597800; +} + +div.important div.admonition_header { + background: url(../images/yellow.png) top right repeat-x; + background-color: #a6710f; +} + +div.warning p, div.warning div.para, +div.note p, div.note div.para, +div.important p, div.important div.para { + padding: 0em; + margin: 0em; +} + +div.admonition { + border: none; + border-left: 1px solid #aaaaaa; + border-right: 1px solid #aaaaaa; + padding:0em; + margin:0em; + padding-top: 1.5em; + padding-bottom: 1em; + padding-left: 2em; + padding-right: 1em; + background-color: #eeeeec; + -moz-border-radius: 0px; + -webkit-border-radius: 0px; + border-radius: 0px; +} + +/*Page Title*/ +#title { + display:block; + height:45px; + padding-bottom:1em; + margin:0em; +} + +#title a.left{ + display:inline; + border:none; +} + +#title a.left img{ + border:none; + float:left; + margin:0em; + margin-top:.7em; +} + +#title a.right { + padding-bottom:1em; +} + +#title a.right img { + border:none; + float:right; + margin:0em; + margin-top:.7em; +} + +/*Table*/ +div.table { + page-break-inside: avoid; +} + +table { + border:1px solid #6c614b; + width:100%; + border-collapse:collapse; +} + +table.simplelist, .calloutlist table { + border-style: none; +} + +table th { + text-align:left; + background-color:#6699cc; + padding:.3em .5em; + color:white; +} + +table td { + padding:.15em .5em; +} + +table tr.even td { + background-color:#f5f5f5; +} + +table th p:first-child, table td p:first-child, table li p:first-child, +table th div.para:first-child, table td div.para:first-child, table li div.para:first-child { + margin-top:0em; + padding-top:0em; + display:inline; +} + +th, td { + border-style:none; + vertical-align: top; + border: 1px solid #000; +} + +.simplelist th, .simplelist td { + border: none; +} + +table table td { + border-bottom:1px dotted #aaa; + background-color:white; + padding:.6em 0em; +} + +table table { + border:1px solid white; +} + +td.remarkval { + color:#444; +} + +td.fieldval { + font-weight:bold; +} + +.lbname, .lbtype, .lbdescr, .lbdriver, .lbhost { + color:white; + font-weight:bold; + background-color:#999; + width:120px; +} + +td.remarkval { + width:230px; +} + +td.tname { + font-weight:bold; +} + +th.dbfield { + width:120px; +} + +th.dbtype { + width:70px; +} + +th.dbdefault { + width:70px; +} + +th.dbnul { + width:70px; +} + +th.dbkey { + width:70px; +} + +span.book { + margin-top:4em; + display:block; + font-size:11pt; +} + +span.book a{ + font-weight:bold; +} +span.chapter { + display:block; + margin-top:0.5em; +} + +table.simplelist td, .calloutlist table td { + border-style: none; +} + +/*Breadcrumbs*/ +#breadcrumbs ul li.first:before { + content:" "; +} + +#breadcrumbs { + color:#900; + padding:3px; + margin-bottom:25px; +} + +#breadcrumbs ul { + margin-left:0; + padding-left:0; + display:inline; + border:none; +} + +#breadcrumbs ul li { + margin-left:0; + padding-left:2px; + border:none; + list-style:none; + display:inline; +} + +#breadcrumbs ul li:before { + content:"\0020 \0020 \0020 \00BB \0020"; + color:#333; +} + +/*index*/ +.glossary h3, +.index h3 { + font-size: 2em; + color:#aaa; + margin:0em; +} + +.indexdiv { + margin-bottom:1em; +} + +.glossary dt, +.index dt { + color:#444; + padding-top:.5em; +} + +.glossary dl dl dt, +.index dl dl dt { + color:#777; + font-weight:normal; + padding-top:0em; +} + +.index dl dl dt:before { + content:"- "; + color:#ccc; +} + +/*changes*/ +.footnote { + font-size: .7em; + margin:0em; + color:#222; +} + +table .footnote { +} + +sup { + color:#999; + margin:0em; + padding:0em; + line-height: .4em; + font-size: 1em; + padding-left:0em; +} + +.footnote { + position:relative; +} + +.footnote sup { + color:#e3dcc0; + position:absolute; + left: .4em; +} + +.footnote sup a:link, +.footnote sup a:visited { + color:#92917d; + text-decoration:none; +} + +.footnote:hover sup a { + text-decoration:none; +} + +.footnote p,.footnote div.para { + padding-left:2em; +} + +.footnote a:link, +.footnote a:visited { + color:#00537c; +} + +.footnote a:hover { +} + +/**/ +div.chapter { + margin-top:3em; + page-break-inside: avoid; +} + +div.preface { + page-break-inside: avoid; +} + +div.section { + margin-top:1em; + page-break-inside: auto; +} + +div.note .replaceable, +div.important .replaceable, +div.warning .replaceable, +div.note .keycap, +div.important .keycap, +div.warning .keycap +{ +} + +ul li p:last-child, ul li div.para:last-child { + margin-bottom:0em; + padding-bottom:0em; +} + +/*document navigation*/ +.docnav a, .docnav strong { + border:none; + text-decoration:none; + font-weight:normal; +} + +.docnav { + list-style:none; + margin:0em; + padding:0em; + position:relative; + width:100%; + padding-bottom:2em; + padding-top:1em; + border-top:1px dotted #ccc; +} + +.docnav li { + list-style:none; + margin:0em; + padding:0em; + display:inline; + font-size:.8em; +} + +.docnav li:before { + content:" "; +} + +.docnav li.previous, .docnav li.next { + position:absolute; + top:1em; +} + +.docnav li.up, .docnav li.home { + margin:0em 1.5em; +} + +.docnav li.previous { + left:0px; + text-align:left; +} + +.docnav li.next { + right:0px; + text-align:right; +} + +.docnav li.previous strong, .docnav li.next strong { + height:22px; + display:block; +} + +.docnav { + margin:0 auto; + text-align:center; +} + +.docnav li.next a strong { + background: url(../images/stock-go-forward.png) top right no-repeat; + padding-top:3px; + padding-bottom:4px; + padding-right:28px; + font-size:1.2em; +} + +.docnav li.previous a strong { + background: url(../images/stock-go-back.png) top left no-repeat; + padding-top:3px; + padding-bottom:4px; + padding-left:28px; + padding-right:0.5em; + font-size:1.2em; +} + +.docnav li.home a strong { + background: url(../images/stock-home.png) top left no-repeat; + padding:5px; + padding-left:28px; + font-size:1.2em; +} + +.docnav li.up a strong { + background: url(../images/stock-go-up.png) top left no-repeat; + padding:5px; + padding-left:28px; + font-size:1.2em; +} + +.docnav a:link, .docnav a:visited { + color:#666; +} + +.docnav a:hover, .docnav a:focus, .docnav a:active { + color:black; +} + +.docnav a { + max-width: 10em; + overflow:hidden; +} + +.docnav a:link strong { + text-decoration:none; +} + +.docnav { + margin:0 auto; + text-align:center; +} + +ul.docnav { + margin-bottom: 1em; +} +/* Reports */ +.reports ul { + list-style:none; + margin:0em; + padding:0em; +} + +.reports li{ + margin:0em; + padding:0em; +} + +.reports li.odd { + background-color: #eeeeee; + margin:0em; + padding:0em; +} + +.reports dl { + display:inline; + margin:0em; + padding:0em; + float:right; + margin-right: 17em; + margin-top:-1.3em; +} + +.reports dt { + display:inline; + margin:0em; + padding:0em; +} + +.reports dd { + display:inline; + margin:0em; + padding:0em; + padding-right:.5em; +} + +.reports h2, .reports h3{ + display:inline; + padding-right:.5em; + font-size:10pt; + font-weight:normal; +} + +.reports div.progress { + display:inline; + float:right; + width:16em; + background:#c00 url(../images/shine.png) top left repeat-x; + margin:0em; + margin-top:-1.3em; + padding:0em; + border:none; +} + +/*uniform*/ +body.results, body.reports { + max-width:57em ; + padding:0em; +} + +/*Progress Bar*/ +div.progress { + display:block; + float:left; + width:16em; + background:#c00 url(../images/shine.png) top left repeat-x; + height:1em; +} + +div.progress span { + height:1em; + float:left; +} + +div.progress span.translated { + background:#6c3 url(../images/shine.png) top left repeat-x; +} + +div.progress span.fuzzy { + background:#ff9f00 url(../images/shine.png) top left repeat-x; +} + + +/*Results*/ + +.results ul { + list-style:none; + margin:0em; + padding:0em; +} + +.results li{ + margin:0em; + padding:0em; +} + +.results li.odd { + background-color: #eeeeee; + margin:0em; + padding:0em; +} + +.results dl { + display:inline; + margin:0em; + padding:0em; + float:right; + margin-right: 17em; + margin-top:-1.3em; +} + +.results dt { + display:inline; + margin:0em; + padding:0em; +} + +.results dd { + display:inline; + margin:0em; + padding:0em; + padding-right:.5em; +} + +.results h2, .results h3 { + display:inline; + padding-right:.5em; + font-size:10pt; + font-weight:normal; +} + +.results div.progress { + display:inline; + float:right; + width:16em; + background:#c00 url(../images/shine.png) top left repeat-x; + margin:0em; + margin-top:-1.3em; + padding:0em; + border:none; +} + +/* Dirty EVIL Mozilla hack for round corners */ +pre { + -moz-border-radius:11px; + -webkit-border-radius:11px; + border-radius: 11px; + page-break-inside: avoid; +} + +.example { + -moz-border-radius:0px; + -webkit-border-radius:0px; + border-radius: 0px; + page-break-inside: avoid; +} + +.package, .citetitle { + font-style: italic; +} + +.titlepage .edition { + color: #336699; + background-color: transparent; + margin-top: 1em; + margin-bottom: 1em; + font-size: 1.4em; + font-weight: bold; + text-align: center; +} + +span.remark { + background-color: #ff00ff; +} + +.draft { + background-image: url(../images/watermark-draft.png); + background-repeat: repeat-y; + background-position: center; +} + +.foreignphrase { + font-style: inherit; +} + +dt { + clear:both; +} + +dt img { + border-style: none; + max-width: 112px; +} + +dt object { + max-width: 112px; +} + +dt .inlinemediaobject, dt object { + display: inline; + float: left; + margin-bottom: 1em; + padding-right: 1em; + width: 112px; +} + +dl:after { + display: block; + clear: both; + content: ""; +} + +.toc dd { + padding-bottom: 0em; + margin-bottom: 1em; + padding-left: 1.3em; + margin-left: 0em; +} + +div.toc > dl > dt { + padding-bottom: 0em; + margin-bottom: 0em; + margin-top: 1em; +} + + +.strikethrough { + text-decoration: line-through; +} + +.underline { + text-decoration: underline; +} + +.calloutlist img, .callout { + padding: 0em; + margin: 0em; + width: 12pt; + display: inline; + vertical-align: middle; +} + +.stepalternatives { + list-style-image: none; + list-style-type: none; +} + + diff --git a/defensive-coding/tmp/en-US/xml/Common_Content/css/default.css b/defensive-coding/tmp/en-US/xml/Common_Content/css/default.css new file mode 100644 index 0000000..bf38ebb --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Common_Content/css/default.css @@ -0,0 +1,3 @@ +@import url("common.css"); +@import url("overrides.css"); +@import url("lang.css"); diff --git a/defensive-coding/tmp/en-US/xml/Common_Content/css/lang.css b/defensive-coding/tmp/en-US/xml/Common_Content/css/lang.css new file mode 100644 index 0000000..81c3115 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Common_Content/css/lang.css @@ -0,0 +1,2 @@ +/* place holder */ + diff --git a/defensive-coding/tmp/en-US/xml/Common_Content/css/overrides.css b/defensive-coding/tmp/en-US/xml/Common_Content/css/overrides.css new file mode 100644 index 0000000..057be29 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Common_Content/css/overrides.css @@ -0,0 +1,51 @@ +a:link { + color:#0066cc; +} + +a:hover, a:active { + color:#003366; +} + +a:visited { + color:#6699cc; +} + + +h1 { + color:#3c6eb4 +} + +.producttitle { + background: #3c6eb4 url(../images/h1-bg.png) top left repeat; +} + +.section h1.title { + color:#3c6eb4; +} + + +h2,h3,h4,h5,h6 { + color:#3c6eb4; +} + +table { + border:1px solid #3c6eb4; +} + +table th { + background-color:#3c6eb4; +} + + +table tr.even td { + background-color:#f5f5f5; +} + +.revhistory table th { + color:#3c6eb4; +} + +.titlepage .edition { + color: #3c6eb4; +} + diff --git a/defensive-coding/tmp/en-US/xml/Common_Content/css/print.css b/defensive-coding/tmp/en-US/xml/Common_Content/css/print.css new file mode 100644 index 0000000..773d8ae --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Common_Content/css/print.css @@ -0,0 +1,16 @@ +@import url("common.css"); +@import url("overrides.css"); +@import url("lang.css"); + +#tocframe { + display: none; +} + +body.toc_embeded { + margin-left: 30px; +} + +.producttitle { + color: #336699; +} + diff --git a/defensive-coding/tmp/en-US/xml/Common_Content/images/1.png b/defensive-coding/tmp/en-US/xml/Common_Content/images/1.png new file mode 100644 index 0000000000000000000000000000000000000000..c21d7a326810ac2f4a6cdbd611b4f55246b7fd20 GIT binary patch literal 710 zcmV;%0y+JOP)(EN)seDG5ceLmLPV znIv0Bp#-N)PBmjF6znL7lb{r$gHy<(i%6hLA%jC4GDwgh>R@>HI^^Z$<-LU5{P(v# zl5@V_JNMpm&l6f}<|#Q>I&f~7KgTnL4W&g=DB=j#fHmi*8k(Axl%&wdrF^1nnp2o8 zL2R$^7|4NGH%qH4K-M})ydTTJgQp*_%LV-!h?#){vXm{-Cx_eBp$)_`g-w)r3xr36 zw^c{#l$B2ujSV>PPr&&x;cYdMdaIX-fB~oMUl{+*{i-WlME%PVIEK!ePZ|yoc5-*~ zybsQ9H{Nhdiwj)6a)Fi0OQs<)hvCZK2XdyFZmeEnfA=1daENc;fAeI&Xd0RW+~et1 zAf72~n4a^^JF6UJ?h^@zOrai$^%koow*pFwq!FR*ZWE->1fA}b-zstq3A9T?Kb zL5Jl%1xDF^{%LYnZM1?%ze{@>n2WpyYBS`ztd0RaLj$^p0WB%bjPGH&2Bgr(vohdi zxdvKel&(x4uPfe>&3_kUfp?~bQYEplp!_ z>QjK%o!ngt7&tlHt|D~`XigB`MCw$p;k0KbwDO4}Qg1PtO4R$!gMAIOO(EbH9%N0pGpjPbJgw2><{907*qoM6N<$g7^(KoB#j- literal 0 HcmV?d00001 diff --git a/defensive-coding/tmp/en-US/xml/Common_Content/images/1.svg b/defensive-coding/tmp/en-US/xml/Common_Content/images/1.svg new file mode 100644 index 0000000..a2b3903 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Common_Content/images/1.svg @@ -0,0 +1,27 @@ + + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/xml/Common_Content/images/10.png b/defensive-coding/tmp/en-US/xml/Common_Content/images/10.png new file mode 100644 index 0000000000000000000000000000000000000000..15b81da125432029b944848974810a022d451616 GIT binary patch literal 985 zcmV;~119{5P)ZPD2hVN!cJLXnwx8xxvsl!I=uDy_Pw{Y zJq`PwcIVB^_cQaGKfe)5DdtmhUfqGbzo}f;)KQ}=u~+ESAy^J9Pk$OfF`y(}QmFQ> zmim{u_9=1+LHKybKA;)I>fE|jeZXn0wf^?305%=FTP1z!IuOpy*da|%iN?sK-Ti+J z5N_(&f-Y_XWgg9^6-BBBt);#*XMnW%eZW6U^Jz^X)ebiZ2S9q-UoiWT+ZEMQB4iJT zV;iPpKG)^|W$C^%{j7h|t3B(2s|W_D2nO)yxgQ_Fg$2~CDy3v$ezq>cX%AEObD-I+ zRbjr5QwP_vt=8D~M_VHFz8^Ke7X|WYJ`!U6%2KmT>lx(CwO33fb$fTsfVn-*q0}{X z)VS^QieP}tCpMbqZaR0^Fjopbd>J=}y0(Io2iCaM7OM>}8-T9FUVGKr>N2jJ+{~)V zMU0G1x|&y&7gJMhjJ&n2mqTYexq9~<0NX>AEG}|}!|G)M2%S26#T82zu(&9nN8N*5 zZhz|v5MEnu{(kss0DvdGUjXp?BpcT(bF{H~&8z`|V~*P+9~g>F@a*j{Ti3gXpmb3o z027l*Vq*yahGG-u_hm~8osBGB*5&N#@bt|vzq>A$6dO}K9#5KO-^LTf6R8Y9n_K}r zDWw~9h50_SObGBv0q|RRJHUV!fUn=<02BxO1PY9ZmJ}D5XGQFX>*6)NW&o5ofWZ-G zyvu_Dvut=Y?rfx70F{nE*x_rTV-;T)g#~Hm#qZlS%wO$#^`; z?Z^F`ztQ7TTlHB}wv6l8xF|%M7YG0;1?43HhDIjPvo3$N- + + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/xml/Common_Content/images/11.png b/defensive-coding/tmp/en-US/xml/Common_Content/images/11.png new file mode 100644 index 0000000000000000000000000000000000000000..2fcc2dd50c63cf3c683f7d5822d1fae8017f5acf GIT binary patch literal 810 zcmV+_1J(SAP)r!GP$l!CLHf)a=hPBlmH4^j}(lFe2K)&^54613)?LoV0L-K9;N zCh@z4`{nof-tWEld%qJ>N;)Z}qjaEaFTwGt^q?-qsL+Wc=mmO>M|mW9sgO~GOl6XZ zrABj#MwTEpnZ69ng6MB7t;_-Uw7JByrVO09_2Pu$k&l2_V_=6gy)4GF^CK&JHV~Ui zpG6l>fY3hSRTWU=n3hZ|Hf+FvzXZHZ!mHXsk;85#90rWCzo+>(x2vF+#gKhD9LLaD z^Mi&1gpAy^JnIi*x7Xcp;h>Lj(1*9He)|acRl-3Z0l(_@IA$L&JEu*! zn-oQG^U^8qUyso3_0)~4Nc2}&6`2*#r5F{q&}d(XnTZGizsirz-vkeLJJJRGDl-!i zqJ1HLmHy)GQc%4+cX(ZjQD6xy6%aacd*Jb-hY0vpUVZq+LTcGHS&!=BG%a+rguM4{e1Sl2++gkBayfYtmO_G#8ib^JR12XY()>GN#pD*ylh07*qoM6N<$f*!_o=l}o! literal 0 HcmV?d00001 diff --git a/defensive-coding/tmp/en-US/xml/Common_Content/images/11.svg b/defensive-coding/tmp/en-US/xml/Common_Content/images/11.svg new file mode 100644 index 0000000..cb82b70 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Common_Content/images/11.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/xml/Common_Content/images/12.png b/defensive-coding/tmp/en-US/xml/Common_Content/images/12.png new file mode 100644 index 0000000000000000000000000000000000000000..edebe20dbbe505eac8200860eea02c2dc1e05736 GIT binary patch literal 1012 zcmVwrn3W?U@R(*bRyzK z4HU-;dLbz6LQ&S$8ySLN1?!ClLF(NuHn&}DD1oZr5L~jt9J8oYYd4*%e?mK>)zli> zG~e+e>1Vz_!K8`Q=j!8o&v~Ecyytz-d5=&^F_Vxp$_~sbWN=e^w@*`|MQAi3s0C^> zrYMT2l7yvDp>QzJo3Bri&ldRGy0-wGAR6*>s|J8?A}0c8ixTkZ-t+acOnndd^CPw( zqNT+4o|Dak1q<-EcdthiKLgd%B%eYIsahk!z~#IJWXLZ9vx_93LK3Mq*@>_S$b|hb zieI@IF)bw;&D&uq!_1zSnjD}yB=9l_ByE@G0K&KsXxucBzTUW4gRl4kV1$(&p-!t7FSX;-Jn;WRAbn5@^ zJc@Jp^fmsCj+)(d0=fWw3!2)yeRg$TvcN08U9ad*uQNBRh3ROrFcFz0l?Bl zm2~XzA%!r_5DjUrH1r5)O0<}Vu3A>jp&cvnxEwqk9mnf-V#e=%LtN^O@@gVQSE!%S zM3S$zEa!{QKA?W#TAt0`wXpAT*lH&KJ+0gU99Ix9dZ6h5BtHpcHg` zca5Vz-5~xliBiyaZ$!7xaavFNY_2y}fhESFp8E`sB)HQ5m<=oKw;;VDW3n}VoGzl5 zv*r>I!3t$=nmNxbz%QlCV&$FO=L>K8s_!S5v=mE+eB81b^wn>vrlT`y!F#NqpSM zF9}-&NTEVXiGzg-*t+3E8tOa%%yT>FYFlTpU-EBZy={8CY6e?hL zS)qBX2C`eWf-a-dz<3#1`T>92xiHgj!QO^Q + + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/xml/Common_Content/images/13.png b/defensive-coding/tmp/en-US/xml/Common_Content/images/13.png new file mode 100644 index 0000000000000000000000000000000000000000..ec48cef31c82c971936d3f281ed2d8944abdfea5 GIT binary patch literal 1048 zcmV+z1n2vSP)ccK~z|U&6i(jQ&$|vKj)f1t^Ma>b)gQeI;?C?tj%D!r3@z> zbj31RK^Psvd~hJRylnWO;Dh!t6Q!`HJq(`|CD84`C)=#BvaC!tThfQk3XNTQ?b3E_ zj7jd)cY_j`Z8bAIP{gp`tvgtDRRfTNPhoq?glniRc4qZ2_3 z(31ZYLlTn;BZ`orkzmhwxjscXDe#{g`WP4h(N>;Y83oRVulC%jO2E5kf83>PlHUXV z@`x=6Ygy4hdcAwPVgdfZ(EDiOCeXY_@&Z&8*%uD>+$&o^p8PK0tdhKdG>Yu96JZgM z4|{~_|J)2!%L<=49hPmF&-r?j12pG-8(@e)ZncZsr95~&wE#R>Op(rLhHsumH?7`! z1cDiLnc4Yd2`}xtL!{;c0MN+(n`)7rz^4a(aPyB8egd z7y1uztfPfiZ#|wyH}i`rgN-IdFEDP1fY9hPJAZB4W}50;4Bww+Ff?f!0f6EAv&0k0 zymQIa%mM%_sSJsKpIKv2#I?Ex1eO?wMj!F_KS{P{O`$8|Dqe)P3_nlIJ(swEZ_d8M&h2$TZkGfG$M|(hEj3-|TDRjk5><&r zRc7atY;AON=~O$Pb-n&VyW$AMfPHHf5WMw=K0e{!Mc|VIobGPpZe+%;Cd3MZ)dHcCb-6%d(HnM*vS zuEv4aQ;XA~u#(DfbNDa5`t}zxS@SlO(c+e^qQmHUsIPV6X>hT)lC~{AMFI?mk)n0L$G SHqJc&0000 + + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/xml/Common_Content/images/14.png b/defensive-coding/tmp/en-US/xml/Common_Content/images/14.png new file mode 100644 index 0000000000000000000000000000000000000000..33d5637c063a55e953390687c38f9b1145ce0420 GIT binary patch literal 914 zcmV;D18w|?P)E zFCM&+NM<3#i+I~(BN1MNh$oStQhy?mO{)os_>*8666T?{C?m+&(tA9#y>0Kk)!ubd z-=}-;Ip_EN-1GN$gp`tUN-3*5FvUvcw(ighRf-Ow(uSZ8s7n>aki?`ySP?Q94)~rF z8&ecB1m3RDPM`^5RqOJ&Eb7^Z?rO)PAL{JG8=Vox5usoH?{cGyj`v zXF52rePMxGVnNbN2cSyPp|9H9;NskowalM8gD>BI7X&!Er^&3_4a)Y?0E9}LzGD6C zX*jFw+_ZU-{Ea?7a+)ZWlv{Qhlj5|QRuihvb&LLhmEs0`WY!=sIt9EK8`mv*U{Qo z%d@wix%OZXA%vy&*~>5nG+1d|?Xc0cYcT*rBctrw(txwdu9dG}HizjB8`q + + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/xml/Common_Content/images/15.png b/defensive-coding/tmp/en-US/xml/Common_Content/images/15.png new file mode 100644 index 0000000000000000000000000000000000000000..f1a4eb2ae6e401ee104b710f55b51aff47b3bc6b GIT binary patch literal 989 zcmV<310wv1P)D9;YZg{>`oJnGTuwfHi%~VLMCr2J zl@QR{*2C?tezX6VZYbv)QZxXMz!Cvr;LV&kr>2Ywmy?d}K`!{8DxJAXizsp=qz?{9 z`5uj%zn`PJ(#Fa)wgv>Y82f{7`S3Z)gQr7mS*1=v>gxd-J#HF3Zic_c2=;uSqkB+k zW970gLM6lfCqrr{NmN<{tX*7Vws)+X!xyP100000 LNkvXXu0mjf@y) + + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/xml/Common_Content/images/16.png b/defensive-coding/tmp/en-US/xml/Common_Content/images/16.png new file mode 100644 index 0000000000000000000000000000000000000000..d38a155eaa64996030dbfa05fdd5ca98ad1cc577 GIT binary patch literal 1047 zcmV+y1nB#TP)JKRukH)vI7;R7`OFBLWYtqF=#_* z0-Ca)VklxtV^|Xv9vCmGxKRO4-8iu&svQq z0zT?$Jj~3cnVd@6EYyqnyTjfG`rVvXde(6Gl^r~{%iQ*F4vg^6#B700Q=pnRI)dyA zZA23R;PQ=mUi&C&ch?VC0<09Y^+iH%`@GR##fi7~SmbWVx6wqHp1aT3)dV-<_gt(c zXmXjbB48-#5}WC+C+j(SXeYHk54Z26@vrl`3g~@lJAoQ6e_grF2j83}HseOT07FR^ za2oO=AO>xA!%Yp<)cQOOoxRD4@Of8f4Ubo{XZw0Gy1{#2omrCH&b3ejf+NP^k!wsP zQv7j#nteOnQ}EQ5Iy4c^U7ID?T+7jeA$(O8T)aNV=aGxtnoYSVSm4SpLRW_0&rLt{ zZ<^Qp0I096 z6;?{#Emgp+*%aRoP4McoTX}i!7CLq}Q|&d~P9;+OHtGzlCMs+_=N`;4N{yE)0N~S; z7x?Vt1(K-@zRC(jVC-swcRu-(bVj#XtMUAit)#5%p>IO0^NS;Ac-EPCFYbT5j zbPl4a{j5wR;)~6LiwekzFm!1F91}$eh#I=IEJhCh_lt=gt9CVelvwrK@qf!@cKQZG Rz)t`G002ovPDHLkV1f&K=&b+% literal 0 HcmV?d00001 diff --git a/defensive-coding/tmp/en-US/xml/Common_Content/images/16.svg b/defensive-coding/tmp/en-US/xml/Common_Content/images/16.svg new file mode 100644 index 0000000..cb7e2f5 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Common_Content/images/16.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/xml/Common_Content/images/17.png b/defensive-coding/tmp/en-US/xml/Common_Content/images/17.png new file mode 100644 index 0000000000000000000000000000000000000000..d83e898e1cee5f31fb0f5ff85758dc85502a943c GIT binary patch literal 888 zcmV-;1Bd*HP)7J<2_Xz3=GB8ZE&(JC^Ate{Ocmx&573`|@Inqh{M`BUjM&iz`x|!hGw!R8YiYB2^i=YT7iu^T&WJ)S{6(K#|PS;?( zIYm4}P}ADi40M1fi!ZGl1@5U`uBQnZIDPX)v63Pm0yXi0O;WXxXz_J7PHfshOs~rUK#FE_&@U6y#IZ(<)wMH23~&n%Kb+}Mn=>?)Ou}OUxn2=FUZZL z=T>zTzFGZQUNJloWnorW(F$l%Gzmj!<9Oq|eaIU-%fM;(f35K){-_aYGO4LB}nPO5?1R+i0@!6g~ zF|0KMGBE>=G=)pmhXC+?nr3Ex**;iW7?29yL=0T0+)vJK2LMmJ;I}AMl O0000 + + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/xml/Common_Content/images/18.png b/defensive-coding/tmp/en-US/xml/Common_Content/images/18.png new file mode 100644 index 0000000000000000000000000000000000000000..9e39de4c188a444f42449ce17b9ba8503e88dd2e GIT binary patch literal 1075 zcmV-31kC%1P)fA3pbzSc3yhrqxOMDSwDWK|Pg*ID}v+mLLLOmLYEY6vrfG3hFn zF+OU~>jj6ia?Yu13k&|Q+H>CL`Tx)Re7w&qlu~Rb73$HmGmNL|1zSZOa)w=JEe3^grY|ol-b)Hh{Jf%2`tnEVxXsRt|Z%Y-8 zHRah{_;d~f=04D8XI0{I@XpJR^6b8~vVX0Agv(R&#{1UB3XUIXr@6sxJe$0>z{$_X z`St4GW_NvnQJ%)9boPcj?CQMEQ%dlSrwnp4q!fJe>f|T z#fuPT3(>a5WfGt%aoD_cUu!j=zP+D^cJCyyuwpCV-r90JJBtB0`S~~}2FLjL%+CPS zRFqKXDYMvQav1`IMyGjUV@(+qJMDhCz-r3IkUjKr+?(Pt4S)|F817Ci9-s0`uzrP1~2gE{F2E+O=OO28;;|( zgF<|huZVS&78g-nQOw-@vJo09)C-xTnq?mF9s4#y;Un0c5RIOCZbQel^Z_j`dVu&{ zAdl<5H^3rbWWav~sk(vG7Luoss@rZjwe5t_{=hk;>SAklBA#s?%qn1Agq9XwAi4?i tsFoJqY~=8NznGY@ZCA6qiEY0f{|l3SX|JZ;d%OSu002ovPDHLkV1k8`>WKgV literal 0 HcmV?d00001 diff --git a/defensive-coding/tmp/en-US/xml/Common_Content/images/18.svg b/defensive-coding/tmp/en-US/xml/Common_Content/images/18.svg new file mode 100644 index 0000000..9ea672c --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Common_Content/images/18.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/xml/Common_Content/images/19.png b/defensive-coding/tmp/en-US/xml/Common_Content/images/19.png new file mode 100644 index 0000000000000000000000000000000000000000..9eeedfb93ef5996fbd10d9a9788eb9597d761b79 GIT binary patch literal 1049 zcmV+!1m^pRP)fA2|}G;PywZK%#{>Q<#7t}8lpDJo+Z zwNN)GD$tNm zx}`nu>qSmZPtG~fH0h}StAz7D&+mVp_v<-ADaBe!TT?pVUCH2{;ju2MM8A;qAZQ2L zjYnw|X{9l)2^AZU_MI&?rzm9#B12<4fe{cLrKMFV;N8S%-_eQ;JpIP8u;x);0Flzb z4ke^629pPSCs%ABGCcMSQXB?a%Y^5ZK~n>XXkWZ!0|xwipsGT6UW;gIhnoq90i*0^ zsQk_C%1B*w+o!{^4UIWpZ8$)yk-Ly*{bQ{5q6;q693a#jpvvn!K7@ewmKr+OH&X5M z6iX2?7^dv!z=&H^wa>#lFFnTgExB#~YBb3&SN<}ecdTpRy}`!`x77h4rQ-1M2|oQM z#iB0l=|%u^dz!D(Gd$Miw$DS&0S>+OlnJ*hSX0GEd!HcOR>$qE&ehC3nkIPh*#~*8 z|529+(UD`>3`iyV?L)V0YUQ)Hx3TfQdT!3%aW&BU9G&I|DGBeYJD6(f1N|IORfesgmPt1|9Okc=~)1dp11;l*CXg$ z-{^?3vX<9?z)|B^@^_}D7dU$gAt1|Z<~GPJ9cAAi2aE88D3pVwBq-ghRe;_LX>>8o77xd7zmeE+_!bZu;5 za%v8MxrL>Fjkg*|mt){|R%g%0C;0NG%bZDNh@ZR0n+HyjUCM30yb+sB)^dFmX#|_f zF)=fr<&&?M7wLvjkcZpr(WTrl608S|2m>S*B;*palkYSz9$n zKM)!EcAWBCu>VpbG5UPLiR(BAq%H=5%w2$IjNAos7)T!MokUXuz~U;x7tz#!TXX7q z5+ + + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/xml/Common_Content/images/2.png b/defensive-coding/tmp/en-US/xml/Common_Content/images/2.png new file mode 100644 index 0000000000000000000000000000000000000000..ff9cc578a005385bd860956c68779c58ffa8ec91 GIT binary patch literal 896 zcmV-`1AqL9P)Xq(VORUMx8s3 zVgJ>A_ug~<|99@WhjWFLl8uD6q3l3XJexfYUB$W-RYJ#uAP2}Xmd22bNe!hQ7x~^kDGl)Djx6%(Z`dTX=CL~~gZI4T{$@_p?jW`NEJtR)|wN;G7Ex_H- zbpTyF0Gw+i4n%y~+X%^2dNZLGmzyXtI1c5m5q+un&;p*iX4+X9a>Q5Guzb(U@ zo0y*GR{IdWufM8@Xa>ydY36{Zp{rQx;^k_V>8TFduO4KR!v?_Q%sd%s4gi7+I%jTr z`TTu0rUIeKl5nvyW2Z||70YmHcAl2@Vcv~QQgh=ON1C2+@$L%%>`5AX3$kL8M{=1* zV3gOG=y^WMqy8`GM&#an95>felGQ4^(D8)Fi`gU0x*ij{0oxTq)U^o0*)M=i0r&HTkg$7*jQ}X@cu# zi`lg!lbN|77w+`)ZDKASUXyE4fK(G81T@v`VP9buvvUiazuk|2bSfV5C0wQeso_EQbxxa+zTRnTbt zi0TL2b=_Xp-h#z~&)0g`W1WbKsU8xi0p*Gk2LgugC5RHx*H$rtCaZzqI+6#`Wc6~* z>9SenYpLu-ljW>WBmyh-gDVOMi_k-&6!0ZL?$bk}bR}~5-ybHC*s!PBzr=>Wj{g9a W=`M=Oaengv0000 + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/xml/Common_Content/images/20.png b/defensive-coding/tmp/en-US/xml/Common_Content/images/20.png new file mode 100644 index 0000000000000000000000000000000000000000..b28b4aa1816878ee1fa710ad184b1782c5bade8d GIT binary patch literal 1151 zcmV-_1c3XAP)TPaK9bTDjf>~qbl;jFE(N&clDn0 z^x|BP=bm%SyXmkm+!yzp@A-Yd&+mDDzw)0x|UKyiLfxJM6eau z8oxD&Vo*uirBKc74WXZtjVY4Zf{H^ePXqNJb|e>8^#X53j)zXK%0T(S)_kd{Pk@T# zgk6Xjx~T0qv9Ir@4OG;%Jd7b4fi1TvzKAiTs);m&+LAU97e5F1Rw=%S1*EF>GT|~1 zPy3Ioe&tS#8M+8Mx5HJ2@jYK_aeyuH*ok`fKk?J1{nHy7=Rmj?y zwi2fzu3^F12kM=|2cNo+y=8g$G}Ei06s?^D9Bb?*rYnnA|8kHA3bU04_M`CWuUUIrPNvHZ#-8_=)rCHG|6l} zQg`L@`m;qINf0|sEr$U^iLjIU(U-r_KRV5kkGpvM@Hw7*`vODbGXRtq1pvqoWKepq zx$@&pJsfzijgzfc0jLV*apwm2cG$Hn1Hz!vNgSP=<%Oe{IRDcix}lhf#<(_g1AsK2 z7GG(=;$Q3<1mN4AQ2>0JWOq@HI|nwcr9&vJzV2|lRHpv46m}J40nqcu1OVBa(gB!_ z#+bM<55UO8to2OJ=5%*Zo0h!_JPp|KYIrA`?(h-Q6`x(a2EgVFGsV+$F^l*2^gMI( zdV)a*JPrIO_CHcUxO_VR#~Qoo8<_$?H_QyBr)m~g2+*VeV5N7R-N4{-r0QTEuY`93 zaPq6Gw0zfZ-5dXB4uA~54}Y3j)tMP-_)^T!6H`&Ike1ex0p)FA_x(A%b)W1zo|0Vll;kD^dhNqb zx_%qyOlLpg^6k`C6|(=)0;_9&{lfs0Q}ZqZQmAHE2Fx)^_1cLkT5@OfgDnCL-7Tqs_`05Jx^Jr zA=HLc)vQe>#+I80mo>0x!q7z!h^#_9V(22coH+d7KTMohw@ + + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/xml/Common_Content/images/21.png b/defensive-coding/tmp/en-US/xml/Common_Content/images/21.png new file mode 100644 index 0000000000000000000000000000000000000000..eda952cd63f1a83a466bceabb6ab8904c9558549 GIT binary patch literal 994 zcmV<810DQ{P)NNl*&a8f@}CbUUVSQ-aDPfiHjt5Nq5Gt9pPFp>w`#SsAD}cw?p1)McR39XLfH zLl?De&AWQ1Y@o6(unj}B0E?#yA6FQuYC=uEyRHo+;kN*9mhf@Kkg7VJi4+6LwBIND zFLx?z=%Uy_k5Vh@K{F52Mcn@ z%hiaE>bx9D7pL}ESBG;SXmElL?q18zP0R3ViDVf{aiilYjV;~8b$j`CY%JpVSL@03 zYP7aJ;q1@d={z<7rUA1ARdsu_{i%;us@%hO+JR5oqK*fgzKqBQo z?E9F#+lv{A#uX+RgaMV_z$fdL@cq}N2mx2_{L96ge`gD~vCKK3 zBtfCrW{oRdwTRQ-m7z(&y+59Fv-2q{3l^I12O?44jOkP7OM)o|q)@F&iBs0V`sA(# zu(fn4TT7SP20Hv>2VMURP1%4Hs?~fRe@L`Zs>d4W(PpD%R6W*~&DCKv!v<`JQA$5h zdF0n1({I5hQz&%qGuw`vl4C;`wLo|l;Nj%hHl-M7Yu?q1R5d_s2H`QJs!7+Jrk!P> zCf{A8s%B;~5zf>PW;8Hv!q7!I5Xu4`GIUX%2@dc3#l)#OyPD0W=KOa27EefF$5 Q1^@s607*qoM6N<$f@H?cQvd(} literal 0 HcmV?d00001 diff --git a/defensive-coding/tmp/en-US/xml/Common_Content/images/21.svg b/defensive-coding/tmp/en-US/xml/Common_Content/images/21.svg new file mode 100644 index 0000000..7bc03af --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Common_Content/images/21.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/xml/Common_Content/images/22.png b/defensive-coding/tmp/en-US/xml/Common_Content/images/22.png new file mode 100644 index 0000000000000000000000000000000000000000..90b14b09978cbafd8ca7f8cf639b4e984cdd2c34 GIT binary patch literal 1162 zcmV;51anR`DgnnX>gk(z`PI> z)}+pi=%OSp@n&ur!3*b~#0yNu6_Uj{uXKx|USL!b+{kpx*19+shg*i3fPgs0V5zC2 z!wyQ%=S55DIj5Cwu;6oba?aEDdHTNZ_kHgtq?D{AloeG6QtpOa)7x{2jVY2TL3LC24xkl8S#n`zKk%mKkn`&$8K~NKyhJg{Pl4*> zgbnbhA<=m5aQ*0A8>nvX-i9hVf!uo(pNAJkHh9{dXOcD$5kCo-mnc4uAd0MuXTo40 zlJ=ij`ajphtA<3Sz8r>S7^(Skiv#3FVr!tuK)Bn*S9(%LS_-9wR#HrYkqJLO|EwXp zA_S#HS**&kFzE|$?dCLU-2Rf!#jXzhKG3Qc-uLWdJo7{`W>Yv>s+1f*KSo>U73M-= z0p}JwuWT>FX0=3r`}_4N-tD-=@VH;^pcRN3h?bzHx!a*%=dV9sj&qA0vq>Q^GsjFY zgdzmaC+##oy*8Y+jRhRoRgTSSL6wqQ)8Xu_Ew<9~vI9j3oxUgwYw0qeO5xH|KltV< z>x!)$?HSky=+B3)xeG{DO9p}z$h$CHB@dtwJ-?4$6wW}$~ z&%~aW!RX{|OxAMs{u&27|0Np=cGjJZvet`G(Y$iJ+ zmEZon#oHfWB%~%h=%QK+24s8#TQ}tK){7Mg0Uh5Daja+1z{$=?rG4*a3UbmIygtQi zAO6I2U@nokMl0H)Qo$`G+hTbYr8%_hc3@HjXD?6Cb772<{LJY0NnZeyB52#QiIV(G zeEwP5zw9F?%R)|8cvHF^2=dp|j8M&YfXb&U9JW$>At($uv!4`wZb7*@_>=Kufz literal 0 HcmV?d00001 diff --git a/defensive-coding/tmp/en-US/xml/Common_Content/images/22.svg b/defensive-coding/tmp/en-US/xml/Common_Content/images/22.svg new file mode 100644 index 0000000..fe086f6 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Common_Content/images/22.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/xml/Common_Content/images/23.png b/defensive-coding/tmp/en-US/xml/Common_Content/images/23.png new file mode 100644 index 0000000000000000000000000000000000000000..8b35a747a3e7adac0755a9142caf63b83c803f20 GIT binary patch literal 1207 zcmV;o1W5adP)GxO6Qj{DDskbf)vyy5L4&kqsRev10`W zU2XdwKTyhhDWMw}{3lJ`_I>*N|L1?6^PF>pl#-={vZU;Q^>%_Q>RU@xDXN7^1%fOf zEAna($)Hr|P=svhXmoYPn^VLy1?78Mp8*;`6vUTS_5km=54nynNI+TLi8YEveg>4s zM{I&y4U5_{N2>a7TR?ez>%*v`8CY?LvY@#BIG9l+XBgF5JZucu|${z zL~Qr4@R1wgRl}mxI31>C7@70MCI?s%$*qIVf$3@&$BaQKNmlY#Ij~v;SB59JG4YQn zyVGGOH!~H1V8A=c@Th+d9df63br}0VgORxI>5c5znvKmeZI&t}C(d5uU~?Ctu%sx@ z$!kxor*Q3Ex}aKZ+3StKGum_h*rtnTpe4 zXLLNE%d1LJ4Rq=p5GoZ$ts_1^FC1v+yYqvDRmoH!MBmT^0Ct-t8rObdm=T{pl3da| zFb2R>AcXIxxn8tfvo#>1echmTwn&rgRyOB30l0YehA!^zWr?IE+bGCc#_q@RkrECc zzl5sBXmlDbZ4t&4pv4>28*n7s2!$nIp6b)R`><{sIV)2DxIP}B{^N6;@Ab}=D#{i2 zcD(D6JgUob065s(MgLznb?-erUOYWshDZIRJM6so(tW&Gxo+OPS_cM!dt(JvmS*#M z^#%Yw{kE6ZAOAGPG=BA4^m%9b8tR`dY?2lSJxM?Nt?k+|M z`273dIofu4zCrOr*9ZVYz(boe%mFfn0IASnj4RG}^8U*uSQJ6~g<;x$y2hG})aWNM z!9rzeHhEcT(f`=23cDU%8~r|X-P{qiT+t~|glv&g?AHdq{d`e$xot1bWP5R@F43EZ z&$44{Hv86ZVe(dpiK!sz4m&pM^tdkd`#9G40;I=J&A*nDui4?U^txF(O)u&4#*>>vw(H&J@*s+=iFG)Q zS!M1<*J%`4$>KQSo$EX}r+^s|YFLy4?gfy$)vzd?iyZ#%7ZW3v>}vL3V##mE{{rAV VwA8P~@EHIA002ovPDHLkV1n2-JSG4D literal 0 HcmV?d00001 diff --git a/defensive-coding/tmp/en-US/xml/Common_Content/images/23.svg b/defensive-coding/tmp/en-US/xml/Common_Content/images/23.svg new file mode 100644 index 0000000..f17ec29 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Common_Content/images/23.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/xml/Common_Content/images/24.png b/defensive-coding/tmp/en-US/xml/Common_Content/images/24.png new file mode 100644 index 0000000000000000000000000000000000000000..6041b021c1251e10f94e9eb876bca5b88e49ad8b GIT binary patch literal 1081 zcmV-91jhS`P)mZi7-=vAPQ?)AO`spG-ROQ0_g@R8Oe}s z-R?a;th>ASp3W9JGQUqZ=l=TpetORNo%6dwO37?Wn^kwfeLunVZP8joiij|%M^FJ& zq+cbFB&0@66S6DT5k8x1PLazJgj%C70_`A{zAe5W2 zqPU@p=AQi<`|cYc)D~TXAv%Gw2Q;5l5=}P6JHjV&21uJ91w470PihQJHfDlQ0MgTb zhW!7zQ%OS?b z-#jk>ckZSbN$HLVxz$=7&U2vMY23198857=#N(QnEJI2ToxZ`|&Wnue>i&rY{k+vw z1HcDgp5y1U31>(y+P~R40|W#elsh8)oZE> zgn6zzXs6cMTj*xR!ubIF@%NxPURFAXmMztcq;$SJel072)yrCj83C+%BT`MtTo2>A z|6`SuzQaYbofB;I13fLO*1JHe8 zfHS>G1x#wh6aY=gE-A(P*1+A{SDNM45Gbc1P;N`~=0~Ub?C@pVnBP}y0vtczpXnq- z6SB*Eo_v^Sqhzl&(CvB{Eu-wUwrn|FMl%dxyNr~6Ak_L}j0bPQvMC + + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/xml/Common_Content/images/25.png b/defensive-coding/tmp/en-US/xml/Common_Content/images/25.png new file mode 100644 index 0000000000000000000000000000000000000000..ecb15e64779df483a7b165544552fd4285d4a9bc GIT binary patch literal 1173 zcmV;G1Zw++(N>vd{uus66-)iBJr_T_VB_JMOaJ`0#!;b^msYhe3`{?M114X z18gsNz#yQ#*UO1-`x2)c08M}<+fmn6mUzzJdwoC7r?z4-DFlLx1VdpIA#gsumD=Zb zYIYkl*BQuDL+p-lMW97MmBJ+wOuzX4FLo7KIo&Zx=WpX=SWKLG-%ep(CKY@0Io)vu z0Bcr6KvPRU9lfL4`-@>UsRUID7jP*~K(xHZVd`dpw@!4SM)PDoxX9JK=%F&*G`AhdD}R2+r~L~DBzwXr1KkYQ$DaV`M;*Jps(*8^1BZB*NBOy3I9 z-9JfJ-$V)pF)n=)CKaH^QCA7pObd%)$#_9;UhL8lScNnaovE z0n6fzXNz%FYy;qA^JRu7Zv!wi?x(4xACscspIcyG@g^!u3$bQec+Ih$b3YF=GBuad zuU^0y@JKSFs`4V;W3n7)WUDvhe_FgYnynf!T*^3ZRvMnc>fU%`P zta`}Uq#n;a_7ESwS&9(w%}+y|iDv$C81>C-jUs+0tRVY1f8cJ+ME2;P5<`>zPus*RThkv2*W z=nc)Lm0QMtM*U3P44??1kx%=BeEGxQe0uheByY$8ean`33hDvvXH@fX=ZXRV+`mt- zF>4(;+3UD58)SBV*+)|xEXo1TD#$%*Sd^zC nhyVM + + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/xml/Common_Content/images/26.png b/defensive-coding/tmp/en-US/xml/Common_Content/images/26.png new file mode 100644 index 0000000000000000000000000000000000000000..4b2f560aa0b76dd11b71e25968138a4f0ff0e8e5 GIT binary patch literal 1208 zcmV;p1V{UcP)Qc^)J6uBs+v;`Lm za_O>j{ISEZJ3G{+(BPZQpP4V;`_6m5@0{-lDJ5$OWlh-u>vDoiYMSy?DcnM(1VJj0 zs(l(pGAtF^6d@bi>MPDfno~rw1jW@&4+FIzvLj0?yMfm{`zyX#k$|GT$1)U)`~oPB zj5rJ))i0_}9w-}Jwt(WArX8r_FpzMA)@k(HkMik654XyiWtwiS{uz=tAB%|wI= z&}?sK<$rF(sOlH_#^nfWLv77hn;alP%N>Fc2LjbDzBUHMIIL_+iN$IW^p8y9oxHXr zOO#C^%@spjY!qV?a|~XZGDOHng1f`G57Zio_dawdJGZ4_vjogirR3PDA?glyGVfm$ zpXze*YuxNTcat=NyO(@dGqrQu8hxKmt5yEI-u?C zCTbVg*WI&IARC10NC10X#y27rY1(d>IBAFck#Ou2<^*&BHBoff9&=8dUzu85E0 zC+^L}U35DDb%#6k_KL9wHp}FA2gloosH$z%Yr_?5r>x+%>*fs>FuYVyX?_~dxi9N@q=^8j&}NLw-4xH;d-AX-g4VMmG@l+KBWa!f zL`PZZ?DOKAR{_|)GYcUgFUv(zoCAQ~;j7{NL0ozfDnd3&Dc%SUe0A4Wz1_CwCbK;^ zIV8~w@1LThcZ?&g1MIp#lgD;!q`V*lA%{`e zJWyQyT^lz(g8dgfp8e$|!7su*R{f$17`+MPqgw6|gb6r#pllFDRsz0NB=@1nO0(hA zw8}j76)h;Tl+|%!bg6l8NdXHYRKLgv!X}Dkz@z#_{!--df4`U*v1V7Zn~62Q9sdiX Wz_FqA8Yk=k0000 + + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/xml/Common_Content/images/27.png b/defensive-coding/tmp/en-US/xml/Common_Content/images/27.png new file mode 100644 index 0000000000000000000000000000000000000000..ecf058ec04236748b30a82c72b10d3f9aad042fb GIT binary patch literal 1080 zcmV-81jqY{P)J(V4@H0Q$rf-i-~CyH9ing;@T2pYP%D(X_^w+7(*)+0s*RP zDWY8#cINu9v%~D{4BZwQJWn_Gp83w1?|%26kW#XmP*znP@ZJeI)ER5irHBZf5Q0je z(ioaRG9eY>ijckWuJFY|V~RqiAb23Q7dQ-Jb75iS5b&;gH2n3l47BV&S)+L5XF#wp z;XJ6iCOZ0$wU6GhfnaBBC%WhcD(+G|iv)^{s$JnT1sgELzXyEF6whJ-MYcJa$TMK1 z{Q}GXb2}2cCYtTjk+%$uIbUgUfC?ja4stS(sdmw0C*8lsOKrf9*CY6SYL@BQd2_7H zUrdqLeLG2}G-m#txAe#ttgFMm4;;1&?|=Rgo_)LupC==tOUcP|;~eR}Oj?tC@M&jgXoH{?wp)UsQ8m0l$dZ;tjWMAh8_iZEmWHmmILNb*mwVJNehzJ|?<8OXtQt~ElM8s1 z+%KPL4Di;zt!4)7(4~j~7jq04+iMQ~xS8aYLub*AI=Pifb8T{#KzRwpJ`VuNl>HB( z{fTM-ei^yR(AZ4gxX=k@+l$pB%zfSFcCkp;6nojavCIfQ?L?=(rj#ukN&)CmM;tj; zEo=EY8nEJxNIm`%A8AeU<>_mVoM`LA0Nj{O@#DaxTPQ~ZOX9^{8;P_$1i+E*%Zy(C zCy!I{ze8E#t%2n(!!svx8Igogb%W-CA?}`gD@Hc@2Qwk5y5+wg`Z);v??jhE|>dMaW($ z#rsy`J1=cBms@MYdRiOS=LCB5qjL=W_7?!r)(rp*PyEf`@Qo!6C_?s{?QA1+jgmuF zqSsScjW*VmQ(Nf=phsPD?g2Suy|NW_7_BUF52L*MK=8nKaqj*Kb~~u*(LEt+M_!I~ zO>_W>dmx@LV&@>wK>xA!Q4|>k7FJMv0YyfgE~k!FrgnwTpvX2>CKCy_`=G0VtO;Ec y&49WLaaGquvzs{l-ybG+tlHD;USic>$NvEv>3C-1M6tR60000 + + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/xml/Common_Content/images/28.png b/defensive-coding/tmp/en-US/xml/Common_Content/images/28.png new file mode 100644 index 0000000000000000000000000000000000000000..e64efb24c8576ddca4f9d1e9985da68f6f1cf3a1 GIT binary patch literal 1225 zcmV;)1UCDLP)z=yWurDrxIAot+eor*~|0eQX=8(>o% zqViHhN&j67$g8pxqKal9<{rt{FpeV2ZS|!Wd=}s$Zw1U7BwvFaMHYJ#VG!U7dpjHd zb3MjYhse>V!_bDVoNqQcK#a?`2RtI+takCe-Y6u;a{7iy>M`oFtT`_nU0=CD7 z5FH-K_{}8-Zp^QvL%!_Z9r}HsPEUOB#fN!zUovKsGgzvWoV`52vF0vT9ZvDPwntD? zkwt1!nD%Y&@GM79c5-##rd~lEpb5}YkY8oV*7x}b`}b1%L<(k;!s7BO%XSBf5R^Wd zLS<39(}5!R?5%yICWSFMvrKFIAk%Xzq$Y;($(uO{VTe_RlS?N+m7+{<`o$03TpydK z_UkJ=SKZ1BHRli`rX78WiBip42D+{_2|oU~+bu)7C!93m)YCS2B4tJ&K~7WB^WBdYE5YH9B?U za&JSg0^IRV*>1vv&8#{kr+)6$-Zz}-rmbU`0JDjb$DK9P*wXD`qk~rgx5cZ^q*9i< z1At@AUG$I6X=|0mX%u8705CGS2*81o42oTmxE7aYqx@|1TD{Nc=z+mSi453EJ`OL#Gh|#3K^W3=b@BsD2iZa!H%_a)F40+vPFAd zdvK0Xvd7)f&vfS+?H!t>`o!;C8<-(7%%98$A~7j~D}PV$UgNKfO)u*IzsG%K^XV}1 z6+r=h#6$#eV|qzTjS-%QkzpRlJM^QKdmq8>1e@*n^ZD*C3^7(6q7oRt59H%6-ySds zxYSV6k0Q$f`zDgxQDnKd;nZuD+3HI#pvYo2Clcf9&4cR-SQDW-L=Irv0J%+dh@ADv n;s1Uy(PPW5X7>|YemnjTMNzsqdq-^Y00000NkvXXu0mjfteZBE literal 0 HcmV?d00001 diff --git a/defensive-coding/tmp/en-US/xml/Common_Content/images/28.svg b/defensive-coding/tmp/en-US/xml/Common_Content/images/28.svg new file mode 100644 index 0000000..5acce93 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Common_Content/images/28.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/xml/Common_Content/images/29.png b/defensive-coding/tmp/en-US/xml/Common_Content/images/29.png new file mode 100644 index 0000000000000000000000000000000000000000..dbbca1b3a227c0f472ebc798d8615e88f427952b GIT binary patch literal 1196 zcmV;d1XKHoP)O-{0~aP!A$MHn*||c-7nJIld?XWqVq46`TARD36WU z0=@)=*k)ov-cM3EtGx46S_wm$2t8mytS~V$Y?Hb@v^Cg06D1G@kDZEkpAi0@I zAsbE7+}_7~U-U4mYGx7jfZm>Z1S;xUip_og%JxD$r8zik3R5#dW@c3sA@Dq!L+z96 z0dOZccxTtcHL2DZ7`Wz( zQ0V)*N$q@_x}0_%$V&&{m#ZTY>lw*T>^2d0CG>CZzAMq{)WBsd!l(j_*j>GmfKbj4?=7WxLx#RSJ{9~|zeWMRg^VgoR_PV}{#U=za{ijWHXTrT>D_aD_H8d0 zdi=EgILN-HE&{<&`^^b4LFbx}kHm-I9<$|R1uJ=NXAwfcCujcP!*GQgF**_8=!whv z``Row>$8(lHObF?BUXADMSxW35R%PCyP|dJ9DK1Dn<8lc={l#rAJ8`&fT58orUPn( z?|WCL=z_nw=;P+tjFn%Z!y-Tt@}!jFO{3v~9ff+kZ7RxQQ&CogqkTTcM zZYL{K<8e7dF8hbZIehF_>)(gD^yj&U&=@6qjD~hwY&DwXa*&&ugv)7Xawf>%ka0000< KMNUMnLSTZC+brM! literal 0 HcmV?d00001 diff --git a/defensive-coding/tmp/en-US/xml/Common_Content/images/29.svg b/defensive-coding/tmp/en-US/xml/Common_Content/images/29.svg new file mode 100644 index 0000000..507dd44 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Common_Content/images/29.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/xml/Common_Content/images/3.png b/defensive-coding/tmp/en-US/xml/Common_Content/images/3.png new file mode 100644 index 0000000000000000000000000000000000000000..4febe437e000c7a194c6f57b6071c82aa03c84eb GIT binary patch literal 958 zcmV;v13~|MpdeZlgzbzFTDcTKTC`}>rigwFYtf>@ixp8)RF?f%R*t2kQx+;s_nsCrbLUT; zGiunoI`__e@B7~Gob#RU2q`6V32jc*0edcguC8mVFr}ywCe;Xvf#TRtK_o$`(XI*E z+TIlCROJ*ZQ{X?*wijpw;ZviP-9WwG9Jn?k169XwtLlIiGED0B?*t1t}Sbu6A)X8&iIsjWx?XxSVzd!sC1z_=RDr7Bsmpd3U7OfySvq z3q4Mb?^(x|vLYPzMDo6c$7sINh5r1jii1YLGGMV(*R@q-+vlc~l&>zpVb|y%8YMV1 z3c!*@^Eh*8Bg?!l1%2U*YDHmXz?7m!WC;!b{LSg}PY?)Rd<+AyWAk!O?JvV&)7Y@8 zfWFXZRtu&SH9%*IfmnIXikBb1r#yFm{$Y)S3gVVl42d-$th$~R3*32l+zys`T^!y~ z3c%f`{XBa=tVWQemAnX*4IJ6!qo%3^0K=4=ZGFY1yB}1;Q?#aa9KY)u;bGSx@A^j2 zgy2ZPN5jE#T+W;hS0FV5L7-G6=z2#l*E^yGZDsL%&Yi4cTSYOQZ-=;X|C0(uFg{3R zKqg-1f}Y?{`iI5<@UJgY3z8EUkQ(jT;wnlD+2r%$uqAwNDJ!C6u^WK?VYOY5tYuAs zCS59FIE>cYc)O*I0y$cY2fzXhODHvwYkpu=#;GB@lUug*Wm^wSdKf)=J;F3O!Ct zDH#ZlW9HUb*C#(@^aK7AH`|$h3ziMK-n^?i`9($@Fb#142>k=`P>eeT83sC9cJ`vl zS|Bou;t@1iJ5h5wVI|a?0{775c4j9Np~?EeNe#qJn1-kX^cjfjrXeaP6Nmr(Vv>$I gyPEw=%=zv3FLn7)*%swhwg3PC07*qoM6N<$f*}X5GXMYp literal 0 HcmV?d00001 diff --git a/defensive-coding/tmp/en-US/xml/Common_Content/images/3.svg b/defensive-coding/tmp/en-US/xml/Common_Content/images/3.svg new file mode 100644 index 0000000..5e87e1f --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Common_Content/images/3.svg @@ -0,0 +1,27 @@ + + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/xml/Common_Content/images/30.png b/defensive-coding/tmp/en-US/xml/Common_Content/images/30.png new file mode 100644 index 0000000000000000000000000000000000000000..f4ffb14d6e1bd6bc1a0104a4777736059e3b2a1b GIT binary patch literal 1250 zcmV<81ReW{P)Jp0btl3OlF%AQ%bD%qM@p5Y=2X}0sw7_n>i$pct7w>T5%m|vMmoL|0ru)rCwr(sj z>^#@*bNtIIM50=%h;G2xo<;^*y4($^`+QxQlhOh^fw?F*ywgNgiN&n2|M~U2va`yt z``~q*TuQh-9?(OrTg|%%YcnK4Y|^<>GN4J(E>cWSoF3uoO+P;ld5NeR1-VvEzu$`8 zYNEcX7=ZOSgQnUk?lQJMQT2i%! zA}Z&9ze_~b(>N6fbI(5ufY&!0i?qzJ|M`j+fL}+(0kD`9w%4vo&p`s$d=Cg?t|!4_ zRwym7Q|Pp^v!R>~tMl+rhxqEJ8vvB#>-{koiZU^yM>;k!XZ(Lvp*`Jc0#{-aW)x7f zHlNSBnvM0~@E9L`eGUIi2!KMT-tmE8)UcTfgb9XK>{gQ@Fa-wJg2(anY=mEi$GCda zPaqhjxwecC-)f?+vIqb*wiE1D(|mveOp4x73!Qa|8Snx%sRnn(104H&2mqVK#K-S! zqrR$`x7#*z9F9inVAbkDRSDdnDy8u9)>dUdgBlC8IbcYvmq2w85;Eg zP+wI{q0`EJe|o*kiXFzge78{!gTYiJ36xF5aQNc^!v$ZRDlaN-QQlt{*PlW%6P242W~ZpOa2QSEu`W zd>ZE1%p8ApD-G2pNey;;Jiw{`zxe*r-Fb(Kp!2{M_HL^n$7UuFjM6{!Ptv$fh=0`6 z+qOBIfc+rOCaV<`m_CqV9t`A$NbfWeddZlTByAhL|)5fs^x>2jKJ5_)>tE}+QW zEKeqU+3tf`1;j;Ys%Qi}OCa}Xs%Xqc4*&NLlT@tOr`eOlihmvd2h?7_ + + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/xml/Common_Content/images/31.png b/defensive-coding/tmp/en-US/xml/Common_Content/images/31.png new file mode 100644 index 0000000000000000000000000000000000000000..0b29e87fe85efabca034af0d83a45deee1af4309 GIT binary patch literal 1078 zcmV-61j+k}P)fA7iX>_@sbvaQHQTj&&4%i8LNwPlRD ziy5pFx-oF#l`@=+UKH8Q&Y6w)JAHUz!v==N{Rhy+H-NWJctJ4~IToDqU9Qdz)m+K<;T5-|&FL#>x?Uv%X4d*MAdJ3llEbdx^|)zibTZP{PRGtB;wx#s z{P{Kjk)czn=U&)$mg{#Q4NucnQAp~dC( zy{&aDFN0O}I9^#(`Q=uG8+YO)QdtJ~?clxFo}#C7drhQjD$YO{=(YwdMiZR*bPfQQ z!^VdvpQg8~mDhcbbLyij^>V|7i}ei1^_!KHRyF2AF#vkIT4`x?)`yp63`m7QaZJND zJ1;!5+XUIw_6Q^Wx$>>9sTDe14g4aOQ36HC87alt!rJAqF>$PiiDNzdvyw(iNn5kq zc*s7x^au5hlZuct#&zK$H%7@&VVz2A{5l^cmCb_7XyFRM@NQ= zN4Bbmks<`!o18Sb?L_aTNM*D-!G;0TVN@~?44wWyK>Z_FH3fs`pEq^fl0Kko;sg+T z2=G{bZ<9(4%uXL(K#^lWhsx#6^ICk#&cE~CgpJeW+xD$Rox4HQi1niv3r wn}7#(O$=0m!~gxm#Hua(G<%rZ@~`860c?AQC+tQi+5i9m07*qoM6N<$f~!me*8l(j literal 0 HcmV?d00001 diff --git a/defensive-coding/tmp/en-US/xml/Common_Content/images/31.svg b/defensive-coding/tmp/en-US/xml/Common_Content/images/31.svg new file mode 100644 index 0000000..08c3f2d --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Common_Content/images/31.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/xml/Common_Content/images/32.png b/defensive-coding/tmp/en-US/xml/Common_Content/images/32.png new file mode 100644 index 0000000000000000000000000000000000000000..a4740a3fa105367dd0fb7ac6000bd3000cc2c5e2 GIT binary patch literal 1241 zcmV;~1Sb25P)bYq)=hT{mGQrHnOgF~Z zAMQwutu<&+5QQ`ngApT$FlrPmw-_sk`lDO~ZH3?xDq(oDTDY+-rCjN9Zr7Ac^T(-o z=lA>RkNdIv-uI6AW5eEm-RE-;&-?v-p3mobo{x}HvXW3%lpRQ2jB!mozSR3 zkO$<2|MDR5NQEv%$hNK)*TseU6bnf~bz^%ya2Q0%!raP!;E?;6>zic>s5L5w!`{R4zdRmZO%)aK=`dWwaL(^GIY4&Uw+^}pgigEoT4x}jFxSqS3=7k$$?gi&H+J7GA z=;=N*EkxjYJf9bKmEcS_NA3Q+ImuhCml*U+#Va@rLWY|pXD9@uX*Us3apOc*fF<+!VY!#bA zmuSX6&$U~IGoa&&m6uS!#&zj@)KnE+clVC)-j}~JHsw!bPWgjQYAe?P@I~hUa{)Dx zS(NLJ?Rat~$hqDTt_+Uho13TV;T+z5@i9t^G7Yx*YppatUyh;(E?o7}`u#uxk9x#L zzyoZIHy9rEap>b70L*DA9BHVetT>C8T$?!X!B0`UH4Y2!H*CgXHSzoP310v70;-m@ z(Rm_2Zbv}g-b@C6P^G8e3qV + + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/xml/Common_Content/images/33.png b/defensive-coding/tmp/en-US/xml/Common_Content/images/33.png new file mode 100644 index 0000000000000000000000000000000000000000..f23ccea3a9cd7bda2b855206547d3aac3191246b GIT binary patch literal 1268 zcmV{N4#sVsqK=fFmw2Sm%%(n>$@wzt3Q@U#T1-0|H4rA&SW zc&0{df>+nXw$uC8j@-8ZPxruTba4Qvc|h`Ugiz#WZ*SL$DGSJv9|x?{Bp-*0B0Eco zFbT+&-N*E2UW|~giMHb9Fdf6(nm=rEfSO!x0}K_&?soC5AwWQ5Z6$N79NbN)jNFcK zH=&xcyPb9#YAX;3ZiHgo3MVGeAvYDCj$$9^DIC1Krim@98>w+Q^54{q&cH8!(syVG zU6(x7yoR1F-Bu)0G@29V(%MmB`P3VvRp+K(52WQibDGi z4srf!nD2c7R87ZKZsXuPYjD`gSkmkUz~>LK=gYHP9vLMVNuUV9?rlrySYAg%Z3S+p zop3Z|$g4}S0XS=@fY50#)|yf^j-B}nRnq|&jitF6jsp+~#q)6|&)p&zN#v4ChHs1l z5Km=@+)bNnP{4I>4~V?48(_64)VLf}RoLiQR!3uPCE;j_{XbkW#Laa%sGM!3rQXFW z&o?6_d~)~_x?aNQ3b+b4VMzfCA9M0q_sabE^u^nJ_{{~vW5%-f?Rb{@N6G=X6HU?m z=^1_-4wXu2;F|P0j>c6^UA)ctt6^fv3@aDU(As3&^*(IWA7Td>_)#z)(qVM()_b63Lb`1t3Nahp5~=zeiAQo@$^ek|n) z!`}XNEl^kiNnkRyDOJPg&z5ybvzw|4TgkXn7lPT@30T!S&m2&|l@}lt1`A`#XIWVP zT)lzh(dyZBEYB|ASX^Z^mZr09K23F%`53E3;iWZ=`SHy=W=AaK%5OqN$RkpUJ>z4$ zwTxX`TiLa>l{?WCQc9|w4n)o@zBo3Fl<>le`Rrb_lvpyuSX`yrX~$~G&g;@hgfo|e zCIO0&M@$vSwo%eQK2D}Iei{mrOlwp-?bNuk{&B0G6Fl?YAL4^AjxT!gNPHo!X#a<8t5wu#8$|Nby3#*979 e{!7gG>-ZnIROgaNZK*E+0000 + + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/xml/Common_Content/images/34.png b/defensive-coding/tmp/en-US/xml/Common_Content/images/34.png new file mode 100644 index 0000000000000000000000000000000000000000..7e2ab31f60cbda8ef4ce7f7761787a27c506e939 GIT binary patch literal 1175 zcmV;I1Zew-P)neWWT$&eK=d6BAXPrx(4+w{H2lE%PK*EoK93{5lF zPe*eluXfe}aO|UBI6Lf1Ht7L$0eT8rx(6DQ&-nw+LL7D*fyE`R_~uwrC6-);y^mM& zVq3L|+*y*(p=WAM`$mW@QLZTT2xwAth$PeFePfJVo#A`0kBF*aFR;>gYzH=L4h_|% zCfBb&Uyse2lR-d~3mArk2ndaqWW!KIW$@?gL{trce*$4{%q#%l^Dh`|_dIq#+iN#4 zG&+@0KqA+24G8^SH^7ps;IP|RUudPRv4X1dB4*}7e0uhZZsV}qIQ;BG1j8zypZfz> zeR&22%Up>?m{LH^refafZr0aBqf@-|*{{sp4(WTZ?XROS-$HNSD7O;!?*N@EV>_N( zh;U(aijk``1cFO6*ExCn(Ms=;1h)&KkCBO58oxA4`FsTb*I zb6J4IhcF9BL@1)-9rx2vT}nfBDG!zx>V&(tZ8F(E(NNBPj&)`MGKB!C;1-hB__`oJ zm!}@Bz&$d_?0gu2jb-a-+Zs*Z?S%-}{|@lsx4#*D+Y7Ahb5#QH!=*{Q<9?Gcso*vV zP=xH4QoI>o=UH+%a-g0g2kN;w7eY!&S+R|Hir*i+%Xn^KjUsEcddA zFm!VF1d8kg(l`B;BZ4A3Qw^snZ$eLR`*{?(lY0{hf4X@vt$?@)O%+XmXBFfgO%+Y) p$l?F~VUmnB`!xG6vF2aL{{lTZrfBFqLht|p002ovPDHLkV1l&P9T)%r literal 0 HcmV?d00001 diff --git a/defensive-coding/tmp/en-US/xml/Common_Content/images/34.svg b/defensive-coding/tmp/en-US/xml/Common_Content/images/34.svg new file mode 100644 index 0000000..c67f8ec --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Common_Content/images/34.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/xml/Common_Content/images/35.png b/defensive-coding/tmp/en-US/xml/Common_Content/images/35.png new file mode 100644 index 0000000000000000000000000000000000000000..02118e34f29570d8edfd20eff74f47e93941af98 GIT binary patch literal 1224 zcmV;(1ULJMP)7L*H-QV|nf4_5n=NuuWWHX^`Dm!3(5a;@~{u)h+W}#7! zpcE)gyz(RQONBv2$iBgjrfb>86xo!(bE3ZmXa})7yRdQ`IOXkZ>fMlly5rxJD;D_$ z;K`2I0I#NsV?$>SPd=~!Ph0;%G;tm%dPwqB1W;tFx1;G&)&dgb-vPD_lCL6$A`h8~ zFbGJbeT0qwc{&1`Dr(cqVOWNVnm=lCfTBd~6r^MzKHEi4ii3cPl6;B_9NZ7bn4Af5 zKO9R5Qs~OTW;M2ya71Mx6iu_rSCUspdLL*{9vp4h$!iBIC~`Y=TWm$6|LPQ{FZj^3 zxcH8D4p32&ZxAprJk5vaM$^shfG$9nUEkJUlfKT&w&hXeb`T1$FyRlfqDpL5g_h^a zdA+ex_jBjk4dj_2cE`Em&@-S((JazjPj~zH<>ox!kNAnH8g8eZ?)MvT*ez67Zq@x< z&bWZi9v|Nh-`4Fbs%9!dlcE{8mLee0UQ-Z>sSNx)t&bN%QSQtyQBjhQKd=OV(_zJG ziGO%^E^L?|ra924H)J5u+YPW;6^h&r3i9kU)|66FlFxiF!nq$NQvM#G#Zyj;r<}Qk z2t&RZE|1>LpkR$Fc@mlm*tNsO*|s`;JTx}L$6sA%elY?-L6U&|dy4hv7Z2><{N+FC z>iN|ytf>G~1eao58JoeCYooH%Mcuw_eDtP+u3jJ4Z~nu?ogke(J}intFchU~=N6u? z-i|BR#;f%e^j?`{YBrQHezE{Ruq)kRYBt2F&qe^qv03=!?fq0&Zso0}Jsj`)iD*ot z`|>T_e_(i;-=~AT+qw@S;Hk0#GXeh9hqdk@*NmAEiK&c?2LPz9+)6>7`SQD+n4pkh zB}fwiQeiOJ$N7Ynm!B<5A=zG-OXJh=@+~gKSO`UVW^Xb3_Y{+3vj9-OEsvuOJN0jF zOb3npNnCmf6e0Vh6z{E$b8Hq)9;xEwkt*hb5u}t9x*UkaQvH1322#S_@-4ja!jouH z5{{@i9cxv+cy)^Dzm4@*gzPh9AbyOJYBQ0; m|NUZ;j!nCoJx*-;?f75OO37E%35a_D0000 + + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/xml/Common_Content/images/36.png b/defensive-coding/tmp/en-US/xml/Common_Content/images/36.png new file mode 100644 index 0000000000000000000000000000000000000000..30f4fdf7a2d1479c72f0c96eae0e15fd572b3219 GIT binary patch literal 1281 zcmV+c1^)VpP)fq8U?coPh%m@TLQFx*kf_KYN(*simVxeOzZix(!%a6gf85%--u=A0 z_wMYRw?FRP*}dnUwaqE(``>%c!}t3=&-=X3`y3&qWFes}s5)SqOK^2#OSvvZz0j#f zPy`gkUipytq(ZAA}|I zr$E*0gp=UaHL>ITq0PN>Hc-{rvJqW;33%>Nd=h>X+2C!iJ3DIwG4bz#)Om_eLPe3A ztV|>sh^4)a`G2_?eq9q4=Iuy2hOs@r-{JtC74}vx8EZok*;u?a8?7+X-?*ivpj=gaal@wglWLlboQ zhMCYLsWyeJk1prg+7(7zL0&rVy;@1_+9DJo_-80g`;7ta_{S`ABub-NrVQv()C*JS zfn!&=)E(eVn-5jfaXIZA+gpRfp2C_Hc}Co>r&i<6PUBK{fPF_V;=5}lJOy2fdf-Ar z282$vIWVGXocirHs-^=l6ddQTK$P4U`?^Ir4k}kKM%8roe)7kR;%2R>8W2WbPe7_o z!Q*m}lWC{6yoln0ECRz3KKro?fU@FT6e0NY<{+g@UA(!o9A~`}gQkccM(nUP;)>+0P z6J}aNYsTw%cueJ|_C79k2MC5I*zia`@4UE9*VKXgbG7-(3U1 zot?(!^-KPfKi+`PD&SUskUdA*c=_Nj)W3d)i(LU$Epzcw-6{Y^Vm(1hc=wBTdj1~e zqs(~8#6nld1*4a6g&YP5Cu0a&vlkDN@qQFKCp-4>3XXHRdjNGJdP;Uaz7ipze5ITG+;jl0 z`-YSCu^Nl=PUh$$2Hv9X?R>w@tgfY_8q;* z@zx%L@bJm2d~otAqahWi!-f#heq(^w-v6D5s+qsPBYtF?@iJ0`AUDg7(_y23Fid#d zOgIH0pdc@Uq0w=xqc>?F;WA2^2dZ{`)5^V%U^Bt%J-8*I<0kb1T@yP1{{s;B$G8)a zWZ?Xv&AlkH0hs>MpF30(* + + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/xml/Common_Content/images/37.png b/defensive-coding/tmp/en-US/xml/Common_Content/images/37.png new file mode 100644 index 0000000000000000000000000000000000000000..6174706f91fc8e2dcdbf07350163a4c3c5b25494 GIT binary patch literal 1140 zcmV-)1dIELP)O zASuBFiHVJG8j~gs5191D=z}(z7+TW@qwz_bnAl>7D2dV7?3VfwQUjI;OlUyNR&d=E z=zcLfbA8y|>CEgdOG_L4Kh3@O%=!QCIdjiFBczmUCzNev2b_0e+%Y)TqD#>$bUF~! z05$2QAd;X|@GC-&`iFb2Zq}#RObXghj`abjLG0U{TR97y3Y_ivYD)szPJCOZIOJzQ z`{szV5YRPoeBxa9!W|1}9~?V^F1`eOcS)W>2u1b>hI=k;T0oloJHWL?@(ffIc{G=Z zECK1TPqOu$+Y!<=(P~de)-g=y{9cm-_|m>DutXsBwTlspfq?p|QXVSza4V*=uoU4| zOf}Xk%8GD1^OuuYLSrSeZkmxVm`{hj4xBa*Uh3S>P#wLwd*HSd0Cf*X}IA=k*YYC7BDZlGG$Fr$XPMI$rK- z$V+NQG@i80h6r^NOkWT4{bUeT)A1I&x$sse9=C(0h6(`Q_;?bB zVtuo-xtgJYMk4}t=u-3oS1kh4<<)|Osxkh{Z3ionb#8>C)K`@f3`GHmCG0zd?q?na zU}pX%vx_TP>q4g^D+1}-o&}dv!RPf*UgD;!rH1;dQo^eV&i^o%%bdsS%6Vc}IRGPp z`J6UpF7rp2Q^4Lw%J^uo%@|KyTjKpMekZ(^$mzTPa6JIwwFE!@b|bd{6Ia3Ocr~hW z`PvfG*TY2ON!p&=$$PIpMdR)rS++i}hiCU!1Mu~gMN~~M|iYb{^`H@XCTZ^ie3isTB zhYj0{{`n0zV&*bZpa?lCrFb(lE^;{-8fau_ppk!96G$nkEb}1JNA=V3KQP~8{fBn} zFc(~9YA(E?07b}A<2mz?YNO)6 zG5|&b8|EI6v*wnq;ANx;!H!Zl#U3ZiH{-{VkqG7M z2lEQZh|o3B3Iw)59?&(>nvWd*?>{DXY}>Ed{lvEa9sdV#RG?>vx|O#80000 + + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/xml/Common_Content/images/38.png b/defensive-coding/tmp/en-US/xml/Common_Content/images/38.png new file mode 100644 index 0000000000000000000000000000000000000000..161661da62645c03518657942ebf633a3591ad05 GIT binary patch literal 1300 zcmV+v1?&2WP)T-oF()ugBs8kGog zf!xqfgGdIYf>RN)&3Ul)!dyAUT$Z3>k7FCq45Damw6X`-=W3}vwIBoQ-}z~U5+_@M zin$3J;L-x3vEy*f&Br!S(d4K?6W;^&d5X`#jUww^2W!vI*+59V9f)6`_zYAOSslxS z!9XbOohRB2oR8;Z6!0+!q|k$%^@FS z6RLq-2*}G!A|u6udt{RSd%jtG$XCO6M|2-(4j;U>setWO`Pgk1eNLU$aQtzLLnp7I zX+iU=^K9(jQ9?nkRgdetJ<5S^y13py678TF&<*HIP}$@tjo#ocL%H7IPdWh3P?)OOr@XNdVx$u`d3)c8?8fvuJ*^j7*z_ z?DRx#506LiYEskz7a}qsG%BOL`qcnu{_IB$XaJ1(rnv11k`20ppI)De7OJC+kddWn z!6j1z8eZR2G;M^|gBlQeUyne%Nx^QjkeX~}b7?O5*}+sF`=u8E�f1&KuNk%;(+h zYgxB4oh@b00C3dNgKu)$NE)UUUW73XtjwXCsn3INa+>vPv-oURImHEOdQ4+=Asb7w z0l4Ft0AOcL5!IngJPhFm24e->y6a=#(N5lO`JKA=&(hWFVa;+IyKC0~P`WyUoi#-$ zLhwoJMH)Un$MJK0nBx`R+fhP6jx`pouJyoxjBOwselQ3BZjz zW3+b;ph?M*wr)ILKXHm+LvfaoNX9TA6`bKQNlQ#@eQ7zV$!2{nCnJ%~&j*)pbX;Y` zH^t;s0Dv^BndBwGvnwY(QUBk#-&lmp_si5#SDA>NGZuk zvFMHE>oeDp5}cRs(70tKwj?v(?yq8C*vFb>sVIuTJFepF8ZsDAglwDn9(@*Eo9Tv$ z2_`;#<2g!KWneMK=`sJ__0ih?4?q9iug{ei*?DX0v#iQX2|l5Oi@n2q`C~Udx1w9I z>~Xb(3MhsF!(pTdL7LS}lEuW``;&UgV_`{x3A-(Udk>9^Jd6zYfr>q+oy`9V_9(bq zEw4m$Ttgqw0-_OcKLv4jh&uuX109EJZlcI~z + + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/xml/Common_Content/images/39.png b/defensive-coding/tmp/en-US/xml/Common_Content/images/39.png new file mode 100644 index 0000000000000000000000000000000000000000..2d46b24fc269d99dd6e7de7c543b03ca10c7215b GIT binary patch literal 1294 zcmV+p1@ZccP)8H{ zYQ!dZbxkz1AKKV=+XAW@o7bR=BS66&l8?iOBI~?OH7!#X5GVf@uuhYF91#?`A)N@5 zfVk})On>F6@adYUOihPr8^&{fx5)tt;<1yEw=H$&H*Jb09Izlk4O`=0?N!%T&=fJ+i!82q)R$6bjr9a-25SRTNWF*&fvObJ02d5&~~w(3q6Abf>Bm2E99*g9%1={TmVj;zsf&@u^ew& z?cw0Al~gRsr?1}+fPXCdpYaprsX$rkgewC9_I}&}fZdwGdoQk_yflv;HA~oe@EpOg z#`EvCv2A@R3yZVyk45<6Y%i~DT?SwXNr7q>AW;!!0f`7jG&;I{l$YjFUYbXa)5cAI zn4v(J55D@{m{(HdVqtMMnl8E6d&3+^P6#kkAQf5@=VWDCc>1yVkN?QNvys`Zugn%=hs!=OR{0Ur!1B#F*r4+A?kL}hB_S7$DPyKSP4~LLa zlArBB#0&hB(|<62iod^WCAls;_vJXqw8ujB_4_$^{5SLJ<6I^OV%I3yJw6VGG=A(F zAQ;xj&$d(Gj*2g4 z6d}lU*~oHO7`Pcs+hlTGHr!b@h5})3jHDw?5|Gr4O!tAR-QTow=U1>>!RtNnRMLrS zItO%3GyuMPK< + + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/xml/Common_Content/images/4.png b/defensive-coding/tmp/en-US/xml/Common_Content/images/4.png new file mode 100644 index 0000000000000000000000000000000000000000..9b9dd883ee29cff445c2a98c0def7972f75e616e GIT binary patch literal 849 zcmV-X1FrmuP)0(<#AgKfE zumZzFLbpH!FY6F=$y10RouW%bkx&RLp@Z07yhH?65LTE%4uy5G@Zj3}bnxALw|CC> z-IVn`z5kxy=lec?e$Vd_Qc6lGrKEJgY3Jj>NTgkpqF-nP5YzxQ`l}d{m{f==LQY4= zgCDHM6jp}7KODINjDcvi7FI3-VRa(-vM2+cw_evP4*3}HTLYVG9>^v}L2i{cU<>BagoDRXvyPw>9 zvS6jz7?56`=^hA-MB1&db8skv+t<(FbO<}10nxh6$}*ry(QhZrz{Mtfb(Ivdl^9uR z141KUH9-BbL)^I3LhRQj%j>^w8!)nVCZR~@^}JGqAUtpums8=v^cTvU4%-HdEaNJ$ zWFXYlz^RjmiGEz;?ZO%k#qJ!)WZBw|>#9B6?DO$^Gr|3-&xL?ZG8%~O_3`Mn)0Dd$ zEU*3Ha%Vk5Jw7Vj+u6FM*2_?jk205~e@e4<@_;0Uz?ZL8!-)z2+8V29Yplw6*IetR zxz@|`xgTsLwETFP!+=zX3Q1SKcF$&)aF=K1uB#Us@VK3PU)@0cw9eMwWPZ5LG8s^W zoR(7D$=C4d?2_qO&$&80ZYSSXH+VGjbx(MTmA+10Y?o1T(Nct>Bo~b(TlQWM242_+ z7rHxZ*Fo5LW2y)I!>^(gUV`l45I+ETT#ub0lY#lk-W3!X0uuWO zPoT(9uHrOj)= + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/xml/Common_Content/images/40.png b/defensive-coding/tmp/en-US/xml/Common_Content/images/40.png new file mode 100644 index 0000000000000000000000000000000000000000..fe2a68febc5550a62595bb5bc0b225a7305530ae GIT binary patch literal 1130 zcmV-w1eN=VP)R@1acfYO7p;2xjz*lIQ!0Xv^P6RXH<^7e^IyXcUT#F)6cUl^?G0M+HF4l<|^ro zTIy;H(8E(-f!@)Xu78X3S6^tRz1eAM`+P(rmlAH?i31Sm@bJNF?Ixo|o5oclK$T*! z9C@RAA8(y#Lp6z*riL22eA>(>CYO2RvpLSst^jb<-^kz(=ol zQe9=?^7U1NJ=vU=ZMOIe7b}r->&roc&=5o7H%E*41cB z98YHSzV&#DWGY)Eumq+84EXR=Cl0%nucofEx}HRsjLE9nxu~wP=zT(fMbSn-?5-;m z5GgeD`5WnOa}!Tw@VFd|9P`oXbpe|5kz+m%HP>nWgw-N=vAdD;vn%v>KM82tv#=C3 z@+-_61SmpIODR6l1%zTOhGIoOR#_D~yiT&J`a z=PQ45e + + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/xml/Common_Content/images/5.png b/defensive-coding/tmp/en-US/xml/Common_Content/images/5.png new file mode 100644 index 0000000000000000000000000000000000000000..f239fb6b34771b6a06a7cb602cc3fa5b57c1e82e GIT binary patch literal 900 zcmV-~1AF|5P)Cq^BOP+L2zSj{DG1>$z(r9otbxAyqP!Sym7qa z5A3_T@60>r`<-*ox$j&drQ|4~9Vt6dn9s}p?$Jg=igsb(M^Fh=CVpB%vLrPEnvf%b zzP3r#m_lU>d|jhAfL;*wYGLIJ(4+Ua4ev|9l?U&twF3DP@Tn2opc`?~860Sx%Ugi2 zd$butyavklNS;IpO?K#gZR5%U667C%qJ5Gl5k-?N*+kd`B+~wc{r~e!gp9ao%G?fH z8z%PrpveKs60x^oTL#Q(7jJS!DRvd%cG|nwFkmGdQP3f8rgukXq~6`!@3z))%Xh|R zU;DL5`=gHv0_X)S0oE4yyGI*U`rPAksF37V~PSt?0&h?xqcAEmu)s*u5{zW#nVocA5 z8U8fOR@6{bkm5=&LL~vo8mRSpsP&q*=JOR?z2N2Eiy+aMl8CGVl<@S`6m_ROEQbD4 zQ&Eh+;Urb%ZfdymSFeK;3Q*!Rcj!)63TL`_BsuK5Rw^I9px9kQ(n& za*;X-Wy+WjLO(aHw8!F#H6XJHkQ#yA{Jdo@S}&dEgxjox(qadlEwwm`%rIXU*46ma zxU4PEgdCAlJkI4}$}Z765bN4Cr^=mB>87=2%haOath(@{WqiId1yoYnA# z0;!F|f^8n~b&Uns`v|rhbiMzYKiy!P2aLGr1VV>E9!kXC2AhE3K;U$5&}T;! zO?G4(PP1N2^uD%nG}*$zWFoZFJh-EPqzEG}ngD$t + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/xml/Common_Content/images/6.png b/defensive-coding/tmp/en-US/xml/Common_Content/images/6.png new file mode 100644 index 0000000000000000000000000000000000000000..18866e6e7e07fc7b50288b96318e9e64694ec40e GIT binary patch literal 929 zcmV;S177@zP)BQY+2Tl1xk@lU61@(Ii8{hNNIx z6hRQRDG+JpB8b4;6k-^(38Dz1sIaU+3dM^;5k^QjW(iu&LZ`CHM>ftqEu6XYQs(%= z{;M<0{l4G-o^!wNoFk-^ET^<(r303^JX})UTxdv9DGW*wWC2;eznn;%QlniHvZ=k^ z)}@+Ls4PKoRr6t>4#Z})w6Yhd(Hm@!7i3`1x#u}rjJyLBtAQh=8(wjuqp@OO&IXFB zn@cgo10a2#aKBt=(yrIr+LR6W;4MJx0^xpn&}8{cCL#>@ru{7ofAes;46i5(Uyg_} z^sV_~!vWHLxkD5(1Jhr-c%+(96N1dNMAoJzGU@T+`0@+Gh*nkdNN{z8_klVUa6()R z$IJ4tm*$d`5J*vZ;Uz!ZlhMNK0MmfE1SQqYg(`J!i4oME+Q!KPn@CEqFgoF(XK;kR zZ*GOR2N0X5S-yP!fgweuPzXP?djs3^t$cS+a{2Ci-Z+L8qC#azQ3-TG&4 z-dq4~JaNnm9?l9ZpfLOTtV&IZW4$#AfWe_r>P{DtZB4@I8s}bXKV5y_6&(av!5?8% z1KHMO06bF$wWqd`zA6ELoXli)7G!YtS|{E8KUFN4tT}DR{x3e(qTwF%aOP?U7jL~| zVsZ*0;Ml&rxulCQ;EeY0ud%=8_~wg`^bC&h>YdY^`i)sBs$7#5Fd(BF_&Pjhj^knj zp(CTy#?;C%lx1d-8tu{I+~XelzPf?wYDkQ?keU+5u7V5zK0AM_@q<{V0ZqszmEh}5 zJxB=!IjebEyPt;_%Sc-pk0B+uTRtfn2xf)v1rC*NxMPcz^Y*Q*TeAXy;gLUFx!+Ca zham;L?A04=`Tk$wdqE8lbu)V1GtALTt)!*IgFvPKhciq?oCk`lp0zXoBUm))dc(nx zjvLVj46ir=xRwC!^5qUugn^F6iUBlf2Rw@i_n=ApOo!7MJE2~0YeSReEY3{0W;+kg zYQS&8@QNZpUjSS;yrO6}IQ;JylW;BD)odxX?6>285N1lQmgg4v00000NkvXXu0mjf Du8XHz literal 0 HcmV?d00001 diff --git a/defensive-coding/tmp/en-US/xml/Common_Content/images/6.svg b/defensive-coding/tmp/en-US/xml/Common_Content/images/6.svg new file mode 100644 index 0000000..e2f62af --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Common_Content/images/6.svg @@ -0,0 +1,27 @@ + + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/xml/Common_Content/images/7.png b/defensive-coding/tmp/en-US/xml/Common_Content/images/7.png new file mode 100644 index 0000000000000000000000000000000000000000..52c3a182a6f2297b5a4a636fb64ef189c337159e GIT binary patch literal 807 zcmV+?1K9kDP)n6C4x+~_tzH4ftjXA;ngIH4Jn57T`YsSLGxo?*c`>{&HMklWATpZlM~VAD zXqV-T2P;3?5l@G8h&0i{J;R0+K|_krn!wCmc@!_C~e6+sHY z)7PJjK$RA8V95ngY_B^in^R z<+CRMc(weQ?;BfYfetTc83qOz2p{Lr!9rC$NPP?vS`i?y68&8Oyifn&-Rkjq%`=N2!Q1BJT0Yyd4unZ|d7TIoG~1c2Gaw5Kwv z`a8UA04em0X@aZKE~F4BrJ0^LD?O*2UN%5sjM6LBf?Jy#8SL! + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/xml/Common_Content/images/8.png b/defensive-coding/tmp/en-US/xml/Common_Content/images/8.png new file mode 100644 index 0000000000000000000000000000000000000000..8a8cb215382f369b8a9ef3001c78b14310dcacd2 GIT binary patch literal 962 zcmV;z13mnSP)$Y%bf_%r#!%=+pwwv6gluT4 z^S7zS6e?5Ttq!aMYC)8!g_Rw^e!bp*Wkd!lc3qpPIpjsas|HSzZW?0Cy_2in4%vXW zCa@e+Tmtfk36Cm-Cad&1|6OGR7W^iVF+zA${b+J!DicWttk2%c$p3kwLZ%_g6Q?7o z46Ql;+i-ws@N|tiKNG6{SAjNJZ48-GlnVAgrIcRM3oS6EZcxE@u>{{6#fA~ zeoiI;1-Y3xw8&h9!rzq)#IpY6fUx`epgMo!700$MVuhy=hbEX;lncOv_K!3_?N%}n z%Zg23B?J1C51hF46oBOmr&5rcMa%P#>^t3xslK$QG@vBUoIJL#iR9{s&wT(anKzm0 z^`&UmR18J227>8c9yiv>k*yxaXJrs*dB?`1ci4OSA-@bsWyK6O_=;4yHtUZ8nchHY zQ7$>IF#w!t?7%c7&Cj~I)z$^TvNE?CUZyZ0HJZ|m>-%BY*R$Lc0B|~lUH{*D`_=d{ zEV~LcAseI=hXxzi@jgsvcMmfPTpZuNm=~R2D4v>)D=QKva9^ntq6yg$y^dQAz14yC zblq@zzKfk}=TcER#ZJ1eP%r1MzvO0XmjYgP==J`&(YwU8U_Wqqu;K4RJsddu2&Y5f zo;Z$gef@-ceky?D7`Br31K#S!CWgNSODA2gUme$Rllp*Zh%G?qAHYLa>^LPExOZ~Z zTQpe(sHL=;`q5-ns?BN2PN>)U@1n_-{GBfm8fZT_pn<3f(-7r=J_5LI8lrq4IQ;Ji klSGZ$(d=Jp)KAC10U?b&z$9oiK>z>%07*qoM6N<$g4=w#2LJ#7 literal 0 HcmV?d00001 diff --git a/defensive-coding/tmp/en-US/xml/Common_Content/images/8.svg b/defensive-coding/tmp/en-US/xml/Common_Content/images/8.svg new file mode 100644 index 0000000..2c82d3f --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Common_Content/images/8.svg @@ -0,0 +1,27 @@ + + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/xml/Common_Content/images/9.png b/defensive-coding/tmp/en-US/xml/Common_Content/images/9.png new file mode 100644 index 0000000000000000000000000000000000000000..0ae412fc5dea2fb6ad8f26fa66ae91cf5996257c GIT binary patch literal 936 zcmV;Z16TZsP)%Yi>}w}jCRkY zVgJ>+bLabh|2gM7XTBqpQp~30tkQwhWWHQk+u}Es*eOgZ5flIg)~g7Lh?2BRp+fDA z!3VlIh0YQLYFc&y4IoPO(yDHtE_^n4ZCVC49l5borl^ZRKo6XtuxW^W9ZlQ%lQs~j zZP|h;nt|NEgpVnTRMp|eV5_zP3w{$wn{UJgQ@&0kF5HJp+}sEqMUf?+EBB|gp^-iVY!gD*;d zv*HYxO6+tCU6!B8#+3^II2U@x-qUT=G~Kt~ZQW3)VPGQ5HXuwY-2#{Ad+l*+*B}6o zdWU)O`U?PSSLA3JaI(gWP}t}ClyYv^+T@Ac?`_&#F2$pgA zRxfK-M08*sj z%JD4#boCDD;nlbSy9kw}T`ziEzN~cW_phVCHO$I^gP`!p~ptA=ELz_n5)^kE58$chz;yhlGA0P;;t0z03Nk+Pf&t^j;3w>NL3BQW)L1js_My_(@8HT;l^MqQdKcC zGZCGtADq&_m + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/xml/Common_Content/images/bkgrnd_greydots.png b/defensive-coding/tmp/en-US/xml/Common_Content/images/bkgrnd_greydots.png new file mode 100644 index 0000000000000000000000000000000000000000..2333a6db928dc56f52786759d315f7be908687ca GIT binary patch literal 157 zcmV;O0Al}%P)2tmvjXH`8H6WbhDeM00000 LNkvXXu0mjfOXD}+ literal 0 HcmV?d00001 diff --git a/defensive-coding/tmp/en-US/xml/Common_Content/images/bullet_arrowblue.png b/defensive-coding/tmp/en-US/xml/Common_Content/images/bullet_arrowblue.png new file mode 100644 index 0000000000000000000000000000000000000000..c2355345e2e68b8893abb5691945dea82572079c GIT binary patch literal 177 zcmeAS@N?(olHy`uVBq!ia0y~yU|?ooU|?eekv7`f{6PZ6PM#qg92~bF`ab~41^9%x zGNhgP|Nno#flnU;0|RG)M`SSr1J?%-W^`I(GJ}DELAAs+q9iy!t)x7$D3!rCF}Wx| zH#H?QQNb;_fg#`8R}Ao(1Rn~g>DZHLiFSuGo*Gp|fI z*SXwbmivS2_OpIw<^_yiK4yKBv!jvKDF-_JA(u}iNjH$=dO)f1U*&8V#-=|qpZMDd z+B#>hYrT*pTY}WOlo~g-Ju4S;@sFOuTqp)ek7nn<004yDT7QH2Pthqb5B**U#NS~0 z{qealDai=dWo%PQasZ>aCBUHPSlz>In#Zm%{1>ibPnh9i+vOVZ$uUg?hZwWb240G_ znFTNDhC@!RR$`(-0_JT5{5d72JOA4TvO~=Mh9T~XwMV$yL%v><2?Pn;Y z@(`1fJ($I%jb#7LMs|VYn|2CJ^!hf=d5lT7f4^UfeX0xvP!=XFPV=vX1a2|VL3`WQ zfSX07V+4L}qOXJ+qGDhSOYYiw9F&f!0aksNaNB!;F)Id22X?3TIAj1Paez*_n0MEB zTI~`5qcJ{wXJpF}W^Kf2P2A7!g%ZzgFx{m+=002ov JPDHLkV1kKNA&~$8 literal 0 HcmV?d00001 diff --git a/defensive-coding/tmp/en-US/xml/Common_Content/images/dot.png b/defensive-coding/tmp/en-US/xml/Common_Content/images/dot.png new file mode 100644 index 0000000000000000000000000000000000000000..36a68599510b4b29c9bb5633181a2f1d28e8146c GIT binary patch literal 98 zcmV-o0GVdf&c&j literal 0 HcmV?d00001 diff --git a/defensive-coding/tmp/en-US/xml/Common_Content/images/dot2.png b/defensive-coding/tmp/en-US/xml/Common_Content/images/dot2.png new file mode 100644 index 0000000000000000000000000000000000000000..40aff923752ff2e4c8d578c17f06e7cb1a466f58 GIT binary patch literal 98 zcmV-o0Gitvj0Gw%K#)UFWUmdzZrlcTbA_!@qZLigjxgu0C+PbX<)r{dH?_b07*qoM6N<$ Ef(jfR!~g&Q literal 0 HcmV?d00001 diff --git a/defensive-coding/tmp/en-US/xml/Common_Content/images/green.png b/defensive-coding/tmp/en-US/xml/Common_Content/images/green.png new file mode 100644 index 0000000000000000000000000000000000000000..ebb3c247deab027489ee3897272943da9807c187 GIT binary patch literal 176 zcmeAS@N?(olHy`uVBq!ia0y~yU|?imV36ZrV_;x-JGJCE0|Ns~v6E*A2L}g74M$1` z0|NtRfk$L90|W1M5N34Jm|elZz#v)T8c`CQpH@mmtT}V z`<;yx0|SGur;B3<$IN7n+2=pZ?`&*rWHkTyU!Ixy^8R{*Yybai#N_CdbpGF=62RLU b&B-v&T8Dd6onHe30|SGntDnm{r-UW|O^`Ia literal 0 HcmV?d00001 diff --git a/defensive-coding/tmp/en-US/xml/Common_Content/images/h1-bg.png b/defensive-coding/tmp/en-US/xml/Common_Content/images/h1-bg.png new file mode 100644 index 0000000000000000000000000000000000000000..a2aad24b32996761bcb142b3d366b8ff1abbdff5 GIT binary patch literal 565 zcmV-50?Pe~P)2Q~Kqx`G3^T)W2OX?omx_ABPjS)~KA#-VxS- z0RcI4yJgiv4~YXtJG)r8rPJ>>Ht)Td>4K#{{J@EPAT9a*g%qD|i3c4%*nIi$Vfff| zdY-&)>6yZpPfcv-d|fZOJ;Kkt8vl4Z@rxg7GxhDKkTCs061YGO+8x;}{>v~i@02P#Uz1=Nb|2K4|2yGqbyM}}Zp;%s9Tu-Dqc@*E z4>v!_LBSS%D4M_<|^}`GT?dm+n|W4*WKCYZgb|@tLts6U@Gid$9iV@sE$8 z{N0E4uQiHUxD#z{W$PJtk?+3c=`F541DvLtN&Eb16;(gG_~C`;V72Qx3I6!8-EUS= zfg^Z-60NV;#52>mde^Udbm3}>Km4tBr`6ckFA?}32vOnn?6(vv00000NkvXXu0mjf DjiL)L literal 0 HcmV?d00001 diff --git a/defensive-coding/tmp/en-US/xml/Common_Content/images/image_left.png b/defensive-coding/tmp/en-US/xml/Common_Content/images/image_left.png new file mode 100644 index 0000000000000000000000000000000000000000..e8fe7a4da8d032fe38515065e210e960e8b416c3 GIT binary patch literal 1114 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 GC;tc3tTVv? literal 0 HcmV?d00001 diff --git a/defensive-coding/tmp/en-US/xml/Common_Content/images/important.png b/defensive-coding/tmp/en-US/xml/Common_Content/images/important.png new file mode 100644 index 0000000000000000000000000000000000000000..f7594a326c87aa0982f3db07af0b8ccf2bd98eb9 GIT binary patch literal 2080 zcmV+*2;cXKP)vO(LSjSG5)lPe z1&Ok#f>c66LKG!IR4G3YDn9}e7A;gxk%K_cg-y_=ix5Hr#3B_6vY~Mjia<*3c!^y* zp7AUm&&+%C<}H^Wc7_?xjOR@}KL6gi_nz;3@1Et}OE~A)Eiq!RJm%;#H?{qbzr0%* zWVZ+y(HA5twI{9gKjYx;pw@pbzZ*DoH;e)Rp~{azRX>0}0AJlToZZ*~Bl==LmAj@v z1ZJiF0&rIcFsSvPTWmJguIvC|+N&S}D^d9XjP3?j(+L>Smp(znmcvzsPG;vujyD^x z=>&)ves+td^y5NyZiJzU(o_OQ?A0d-)AnpL9`2=yFZoZDdjL4Z^?+3ExcsN4xcy;R*I z3b-WH!NlsqJa^r2q_qeB;2wxl0F9C%gu>0g4XX5PKaZ-n2O$(x z?m}r^xlSHNE{Rlf1$r)14+@l09t>y?^$nl@b*a8;AD9_GeOA}AV~rfO1Hm=~Bb`uv zEg)3fD6PJCz)DYo$sGU@;n)U@Tms3&3i3wIvu#2MfB0epGa7z~?*$>xsP%sNfCT_wsjfQOz0t5ouH~ZiB-EUMIubGht?|bHJs?Yzk z#sLWgMnQN1Rz3;B3y@?5ek}m%y*Cy`)3oPnIS+U^3r+p~3xCKP`UBg|p^PCEYJ(Pt zK$KJf1f08gd+rJXnuwO};~-1{xC5)Oj_i6IsbmbcZP#($_qzi}#y+~;oVo=5{in|m zSy3m=yixYjAP6GDkv;HfVF-eZt&MMWWeVB#I6@%>q8LE9^8;H-unW78gPu(wm0W>o znq}+#e)aOfqZfv^b zS~~BAptRM+;&%G8zMe1r!i!&?vx+g{U3G!Ei{*v?)Er-nz5(u~@C%Jm0@d=h$kx}ID6 zygJnY0aDYbW1EOBPkFYKO-{i!6Wc)14zIQv*@5<|+HK>WRNn>wYb%$w$p;$o>Qo~; zP}OKWHUr!Cl9=V3uInNf11dR0cDhrvQ zFFz+#4pfRK0@?Y|05)FJisCKq>t9PV$!oC9D(}3m<*Af($}Ge25vF%)XcmRI0$UU{nA@y1EQqpvf}$WIKI+< z?{nK;v$}_Wx&+`;HzpnyBqeyxvCT&v+bmv`Gs$ZZ)iwxH1YVn&r^8%!{;7X}Zwn1*M8En^g(bA$|SV*oB+TVeO-_AHjBV) zA~xHf%_O+01|}t0{c_LH_s8olY(Q47o*LlX{hn><_lt513$`Ch`??;f`vT@Eg!F7O z#<_c`rM2s9=X=MZJ9oEI_8xj>8o)=EFMnPEtnZk)r3bupv;P56oF0g+^wg~Y0000< KMNUMnLSTaIGuU + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/xml/Common_Content/images/logo.png b/defensive-coding/tmp/en-US/xml/Common_Content/images/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..66a3104e9187f4140856bec9393120c95deef9a6 GIT binary patch literal 1114 zcmV-g1f~0lP)J00001b5ch_0Itp) z=>Px#%uq~JMF2&907!xWONIbWiU3iL09l#TsMctY#c-FmaIo5Nu-kT-%YUN2f4Sa(qQ8%>$B)9|k*?LAx7we%&Y!u@ zpUUT-%jc}Z->=2juhZ+g%;mq(-@nu2zufQ0*6PpP=g;Ny*5L2o=dc^KiuEztU<-=K<*yR{`8C(V!LVvJY6LruwsskLxr)B=!t>>_~qeVT?v?V8;=*r=vw}U=6JE zYNSJ)j^1|l-tLAKTVp#tEZr~I1iOmODaJV4Xhc#><#yPE7a0G9XWlzRYuF51*=U4o z1->2j5MvGNL%MCJim(%)4)=}i;ci`0M!tsF(l8n4a{t)p5TeK4gjl8x&h9m`1NIrl zPf`CuDc3hnqAr!(x2?NkpS&c+@1;^dfI3!c{(XLarB44iZ1Nyj)OlyV7s1BP)qJi# zUaey}W3%XlmN{dEjId(HSmlD`0+#XG0C&yt;Qe$8*U$*AAB{ad|8wNrP2iAvsgwx`AXU;;RYivo9YGmdrIjh1I?urgr>*`IgCODF7oJidwyWLE8pUk%ldpT!9 zm3FF#u`}BiOIUBz{f)B`8x<8aHyTwLU#a&@#aNZCs=FI!GZu1VC54k96JOUp0V*d! z7hl2FTvlPtjdK@P5K{HAG8@{yTyKkgsl-{Sy>rgV3Fwr*vcj&c{D@=MiJZo15>*j`sA)vf&}>n~ z1yS_~y&)tn9FaJ4sDv>R5|ub3aiM=ePh1c;;6yg1Kq*8;imF1J2Q+fqkUB5#{x~=< zzw%f+N&S_4@XYMY@3Zs$&Cbq>s?uoPPbNoH^^#?bG4M@qE_Y}DS7&WzIExVnQ3u6A z<#T#Ix?Zid-Kd}eraL?1w&(p|ENf)5%!kkJCzD@?qS1HKGc);$i{`TZh&ZS^z&J35 zAqonc_g3^(;BWzMh(tzXu?MELHC|q4jCpe{pT9;fdzEE5k6|3t0UV&4y|h+jTfz;&d__#`+t4qMpo?IyHXT$A{=Nq0DN(P@5_t#0g$zsHN%LG zZ>i?M&jkbrWt{!33R?hnGRkT$ zPd9MW^O#v&WT>TuxMh)7WqN&`l;;s2>%}Y7wP2)~{j`sss}D*6lrMo7%J1%eWZ8zq z<(J5Rv49P{4E&+W!?iU$AO#Eptw7rwFJjqJ4*-~g1C#(56gOypwq=ogcZ}%Cb_56k z=YWgAC13;y1JTz8h+i2d5^4z^Jb+I{9vD;t16Y>Oo`}$U{cRFM-PnL^`~buV?QfkW z^~q&o@i4~JIRjD&AUgN)cs;Y=`^x;I|5#u3Sh+pJ%B_cZ3(sgd-9h+#AFTtOghDna zQ!zy91b{qg5|Alu7TDzYl_aYa9dKY7Bc!|9$vw`)XfNTBQ(JXnghYFocsztqcklpF zX3a1?{IWGZXEJN(c0mw{2%Q~m^z|g@O2z2xh|=BFPH#F+A|7s3@Ee2qB{nKP+9kM! zN;)$_B-}!*Ekr0}V@%yUl}ag90P0BOBbQVIu(f#rV35bx5}SXD09~1Tz@y`e=ztQI zSI0O1Y@4)>rS!;y=D_!PK% zToD~u1#zJKowx}TxfGxY6S-^#O!EK;qfBL6O96WPI}~4Un?WHu7%AIrWeUKpV+kjS zd~qtbi%piul>nxh0B|bLg?!sZ3RPM^H=0M7L~#)&svqvoWoLo(k%v~PJn%E%BI2Uz zlFt0Svq7z+#R=fbVMkXcAGnL)qT-@5SzHw}yV{{TfQpOgVFSzqE-;BNE)l&+M`rP$ zom2-f>Na>=x2F|?sycwhPZaQgASbb3r literal 0 HcmV?d00001 diff --git a/defensive-coding/tmp/en-US/xml/Common_Content/images/note.svg b/defensive-coding/tmp/en-US/xml/Common_Content/images/note.svg new file mode 100644 index 0000000..70e43b6 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Common_Content/images/note.svg @@ -0,0 +1,111 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/xml/Common_Content/images/red.png b/defensive-coding/tmp/en-US/xml/Common_Content/images/red.png new file mode 100644 index 0000000000000000000000000000000000000000..d32d5e2e80a459c02ec55c71091350a134df7f88 GIT binary patch literal 163 zcmeAS@N?(olHy`uVBq!ia0y~yU|?imV36ZrV_;x-JGJCE0|Ns~v6E*A2L}g74M$1` z0|NtRfk$L90|W1M5N34Jm|elZz#v)T8c`CQpH@mmtT}V z`<;yx0|SGCr;B3<$IRr2LkB+0?`&*rWbFKL{=k6)U&Uns07&a`Dp8O`gpP7My Ofx*+&&t;ucLK6VZGBDWy literal 0 HcmV?d00001 diff --git a/defensive-coding/tmp/en-US/xml/Common_Content/images/redhat-logo.svg b/defensive-coding/tmp/en-US/xml/Common_Content/images/redhat-logo.svg new file mode 100644 index 0000000..1001776 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Common_Content/images/redhat-logo.svg @@ -0,0 +1,94 @@ + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/xml/Common_Content/images/rhlogo.png b/defensive-coding/tmp/en-US/xml/Common_Content/images/rhlogo.png new file mode 100644 index 0000000000000000000000000000000000000000..ecd48565264f8553645a70206b72a5683c6ca469 GIT binary patch literal 2278 zcmV5Kdx!ZfsC)7PN zKaqRRx%b@jKg;)h_u$bq&EpiL5HJ|b10RCTU@tfZeg|KJJg^ju0quQxj!WQiD)jka z88`$q2h@Wv!QCL#?f4chI8r=#8#Fr~?+&6dcJ5X7N(31(;2srz=7W5gaKR z*umY?C7%f^4W6^1AxYQNmGz*S&Ciqq*($!$A3He|F zxEZtq7lY5i5M$BnK&mUoX%d`gwo+`Y@7kvpf)gbm6|@EY!8)$j##rE35^tX>INr5*!!LovoqWdV>ea9Ulr}cox&%-4&$xAh3$w)}m*(GQl4f+Wu{8 z5PZ4bU=sLw#qyjcxMgen6nvt!;B~EOFP8*ACgo9pX+R5Vt0xTnp*J|oK%{g*5Sa4X zx!^9a6cjlW{4slxxI6wMg3~{vg3t!?u)5n3e5lybpP9H=BMro950Xs=i_A7`J9?6ZUwt3wY%(*K+7Nsc8*lpW&$87o-K&~Ltt+_gHWb+v ze6`ro5n#TBV8vYK5{|x!_0P6&&$bvu>po?FUJ|{V&6mB4UY6;{*G7PMz)nSZEHIuY zz(*Wad>2eHv$FX^QVM?_-T|-}dS=ryYFBWiNH82M0dLTCy06JIuLaNWdr*vIB;7+Q zb0_l?_(J%d=&cfbi#$tdkDg|8dCuioKZGrL5Buf57<2cZEcit>1%F?tGa5V~-bX4s z#U$SF8+j~>`*-C79jZE|;7u#R0lLU@lm;Mpkv~jT^5K!TQXLu?-!L>dp5o8bWn8|q zPg!-8 zThd}2ptocU$&;d%SB5488=OUSLsx z{BIwu_cWV=FIBXC8<+}iQ$!L;>^{|zrI;f zFOt6jmo^0y`MsFH2$Dc?Z71wXZUVKew4v}YsO&iVDZ|( zQ{k5JDc?ELwNM_29}8PiC6_(vo=yaR(d@-%%$TuB6H-}O*|x&M!cEhsPcPIh`YXV6 zu#8W<*by2gr1l`_Wc=*y4g_B;)cabI-@}J9cZuLe`C2dp=Vg8sdkqu$v~UNrdpZ$( znEbL)QBie?iHT%AYT@DG_2uQ|J2WXZH#aw?rKOdqI;$HG0{V3ND44+C(kTvqAvnuk zhp%)X_!2Y0xy(_aOcKv}xc;7YOf)ay?a3fw>%5O0uYtr0u;7c>dXF%n^YZdGR#a5%gqZatYH4X{NnBi91?}TCH8npdM6b=v%*+oB4Q)IjcoPv(7a18z zu8S5H7S<3Q9sQ@C7ZVdxZF7d*?LhEM8-f=({pQZ1*9i4;6lEeLJ17u>?;}^v#K`kq zaQ@HBnn9|ns@h3|VZ(+E`9@`$nwpLrJa}+hb#?Ww#>U3-=6_Nx)y2<0K@$xaY% z$@$8L*rmGbV^f${Z3vz&lxfi2HAT60CO$sd0h5HhaK$O1dVd6`S5tJ zyJ=#*?`gJ!!-8Kg=6n4R+{?z%-|wsq@PEjKq;!^}P*zhlRal@?+j<~=paf#9!M3C`un)mm?3z}+s@OXfqCsb`F_a+{ov{LN>4@&pAjt4766MM41-Ui&l!J4thXSz^{4jdfz zS8(k6+T_WTwSN8jX~TyP*BTlc{>`IhUG6Zi*V~+skgz{KKK?*RNC=JGr}+ggkYmgy z9rifyVZ;g><>}?=k05u0M&oZ_16<~M&U;g3+&lr zE5F13UM(1bJF>I0W1KAK{=)lkh{HNjL2O@?4|SpyhMre6+H}If>Qf;$Me5k)tIf*F z$|plkD)Kw%6-=@JkEkw^=pO}A?AqGepCEM2xN+mQ*VotYR}>*v<}z21(<3+$266%+ zHfHj%L4yYENli`NqWkw!Y6Rn5F;1`G1pVRuN`D2%jNYe;)N%S1TmhX4Qo07*qoM6N<$f;VST Ai~s-t literal 0 HcmV?d00001 diff --git a/defensive-coding/tmp/en-US/xml/Common_Content/images/shade.png b/defensive-coding/tmp/en-US/xml/Common_Content/images/shade.png new file mode 100644 index 0000000000000000000000000000000000000000..a73afdf6a78818968c7574a20cbaf12116ab0924 GIT binary patch literal 101 zcmV-r0Gj`aP)i9VDNPHb6Mw<&;$Uy{362u literal 0 HcmV?d00001 diff --git a/defensive-coding/tmp/en-US/xml/Common_Content/images/stock-go-back.png b/defensive-coding/tmp/en-US/xml/Common_Content/images/stock-go-back.png new file mode 100644 index 0000000000000000000000000000000000000000..d320f26c65fcb350e5dd31541d098675b55f224d GIT binary patch literal 828 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 dd=3bnMa5!_3776ZDFOfh$V)3rRY-t?{tp{D(E + + + + + + + + + + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/xml/Common_Content/images/warning.png b/defensive-coding/tmp/en-US/xml/Common_Content/images/warning.png new file mode 100644 index 0000000000000000000000000000000000000000..ce099518f3dad603c5653d163f484c435cdfd7a3 GIT binary patch literal 1340 zcmV-C1;hG@P)K~z|UwVBIL8&?#@zjMbZHIf}{NZVAA8`=^YUhN_#qEgp@ zvLID=JhnjFO{G>vD%rHqD$8yv1-5}m5mJ;L;SV5DA?gAGC77hCleDxHJAUvec;<9r zd+4S++k$&a~nRFD{yg%!u2asrS5z!Xw7Z8Evi*C})Qv7qtg z{%%06EM!gu3TYaoU`sywDF&p~<3 z><>i+iy?p8&3lePlS>0#DrF|f47safVQd}owRF)RSW2}mK7>avIEJ+a%{r+~m>+j$ zSH&-5>v-i7GOu8>58=@Uc)W@siqbVsg#*WE)8^< zuQ529TxAGwi6>Rb$e9g{Tjxv>H;5G`Z5(scKpg$OvMqm4`fnO=Dqf9hqGtEP+A<)?q2}sJByNZ4yjH zAX8E|Bt=2{_ut`-%a_3#WApwz9*&KJRkK_63S9J|{aOP&)z$&VpkZZXxMdEY`obo4 zU&G=L@{j=V_LVF6@awN|s-^~~0s+*vwIQ*wfkY%Cb^ZRo2iRUs;jNE?5LJdTewvuW zLSJAQAlDIFk%t5T@0mJl?DaE_a=cp0b%ULZsfDX7ucybiUSRu?Ge`i~`}-fM*l~)l zrS(~_P!>=p%f3RTpFfw1xf0ocl4)rvt5h^96_b&jR{~7#EHvpLk-$MBQS`Vx5!pEE zK3$=MZruc6YpJ!5!aZra04`k)s11VD3SU+gbJRux1cT4k&LFRfIck3LTo#s9sXwB& z-zy=HIZ(z}LSkbBPw(8(zq^&)>&XII4(Wff7#@5x;y!^cE2+o0D=Sk(c(bDeAYk+U z1AA*+L)l%S7t3MY(|(X)nDz=ApyX5{yge? zdR*nQo5n4p{=HAnBG}|}oILRUMN6!vvC(m!V2clpz2_`(0nlM#z*DUtJlfzGHgfy6 zCH7=y#!-&i79ZN}_xy*-$mbtCA>d;Gr}JS^C2+PQfcRP(ds_!mH`(9XLh|YF@YdB~ z=jEUH_4;*e&d*Cj7TxO;M}-id5i=Jpf@OA9Jp3_&ZHKFUrz!@?;HV<96+Zz0f!3*6 z1`RXVFr9d+6ARQ7Y7);sCzA_9mtT)$ZPXM;IRB1=RP&+mB+Cb~n ztYFWO#n}^p4L133>Dv+f!QTsi-bdd}I{B1Yy2^K>D**JRv z!4~(<7K3E4^Ri=J#hg|5H9Wrc0?e$>B1A{KgZ$!=^bcgGX3kD1Rwp?s*yFB{tHTy4 zo>fZO@nEdn+3DDYv%h(IP6!N|2Uul9Qjmb;p2^=lJ*NmU2&yD(w)iCj2{`zl3CMQ? y{@GlwveX80`!E9K{%+7y literal 0 HcmV?d00001 diff --git a/defensive-coding/tmp/en-US/xml/Common_Content/images/warning.svg b/defensive-coding/tmp/en-US/xml/Common_Content/images/warning.svg new file mode 100644 index 0000000..5f2612c --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Common_Content/images/warning.svg @@ -0,0 +1,89 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/xml/Common_Content/images/watermark-draft.png b/defensive-coding/tmp/en-US/xml/Common_Content/images/watermark-draft.png new file mode 100644 index 0000000000000000000000000000000000000000..0ead5af8bb8848a33500be3d5124c19a424bb7c8 GIT binary patch literal 25365 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 bmtpr7qXd-&e_k*!Ffe$!`njxgN@xNACz&=4 literal 0 HcmV?d00001 diff --git a/defensive-coding/tmp/en-US/xml/Defensive_Coding.ent b/defensive-coding/tmp/en-US/xml/Defensive_Coding.ent new file mode 100644 index 0000000..0bf84b7 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Defensive_Coding.ent @@ -0,0 +1,2 @@ + + diff --git a/defensive-coding/tmp/en-US/xml/Defensive_Coding.fo b/defensive-coding/tmp/en-US/xml/Defensive_Coding.fo new file mode 100644 index 0000000..d7b8779 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Defensive_Coding.fo @@ -0,0 +1,1946 @@ + +Defensive Coding - A Guide to Improving Software SecurityDocBook XSL Stylesheets with Apache FOPDefensive CodingTable of ContentsPart I. Programming LanguagesChapter 1. The C Programming Language1.1. The core language1.1.1. Undefined behavior1.1.2. Recommendations for pointers and array handling1.1.3. Recommendations for integer arithmetic1.2. The C standard library1.2.1. Absolutely banned interfaces1.2.2. Functions to avoid1.2.3. String Functions With Explicit Length Arguments1.3. Memory allocators1.3.1. malloc and related functions1.3.1.1. Use-after-free errors1.3.1.2. Handling memory allocation errors1.3.2. alloca and other forms of stack-based allocation1.3.3. Array allocation1.3.4. Custom memory allocators1.3.5. Conservative garbage collectionChapter 2. The C++ Programming Language2.1. The core language2.1.1. Array allocation with operator new[]2.1.2. Overloading2.1.3. ABI compatibility and preparing for security updates2.1.4. C++0X and C++11 support2.2. The C++ standard library2.2.1. Containers and operator[]Chapter 3. The Python Programming Language3.1. Dangerous standard library features3.2. Run-time compilation and code generation3.3. SandboxingPart II. Specific Programming TasksChapter 4. Library Design4.1. State management4.1.1. Global state4.1.2. Handles4.2. Object orientation4.3. Callbacks4.4. Process attributesChapter 5. File Descriptor Management5.1. Closing descriptors5.1.1. Error handling during descriptor close5.1.2. Closing descriptors and race conditions5.1.3. Lingering state after close5.2. Preventing file descriptor leaks to child processes5.3. Dealing with the select limitChapter 6. File system manipulation6.1. Working with files and directories owned by other users6.2. Accessing the file system as a different user6.3. File system limits6.4. File system features6.5. Checking free spaceChapter 7. Temporary files7.1. Obtaining the location of temporary directory7.2. Named temporary files7.3. Temporary files without names7.4. Temporary directories7.5. Compensating for unsafe file creationChapter 8. Processes8.1. Safe process creation8.1.1. Obtaining the program path and the command line template8.1.2. Bypassing the shell8.1.3. Specifying the process environment8.1.4. Robust argument list processing8.1.5. Passing secrets to subprocesses8.2. Handling child process termination8.3. SUID/SGID processes8.3.1. Accessing environment variables8.4. Daemons8.5. Semantics of command line arguments8.6. fork as a primitive for parallelismChapter 9. Serialization and Deserialization9.1. Recommendations for manually written decoders9.2. Protocol design9.3. Library support for deserialization9.4. XML serialization9.4.1. External references9.4.2. Entity expansion9.4.3. XInclude processing9.4.4. Algorithmic complexity of XML validation9.4.5. Using Expat for XML parsing9.4.6. Using OpenJDK for XML parsing and validation9.4.6.1. DOM-based XML parsing and DTD validation in OpenJDK9.4.6.2. XML Schema validation in OpenJDK9.5. Protocol EncodersChapter 10. Cryptography10.1. Primitives10.2. RandomnessPart III. Implementing Security FeaturesChapter 11. Authentication and Authorization11.1. Authenticating servers11.2. Host-based authentication11.3. UNIX domain socket authentication11.4. AF_NETLINK authentication of originChapter 12. Transport Layer Security12.1. Common Pitfalls12.1.1. OpenSSL Pitfalls12.1.2. GNUTLS Pitfalls12.1.3. OpenJDK Pitfalls12.1.4. NSS Pitfalls12.2. TLS Clients12.2.1. Implementation TLS Clients With OpenSSL12.2.2. Implementation TLS Clients With GNUTLS12.2.3. Implementing TLS Clients With OpenJDK12.2.3.1. Overriding server certificate validation with OpenJDK 612.2.4. Implementing TLS Clients With NSS12.2.5. Implementing TLS Clients With PythonAppendix A. Revision HistoryDefensive Coding Defensive CodingA Guide to Improving Software Security + + + Florian Weimer Defensive CodingA Guide to Improving Software SecurityEdition 1.0AuthorFlorian Weimerfweimer@redhat.com + Copyright © 2012 Red Hat, Inc. + + The text of and illustrations in this document are licensed by Red Hat under a Creative Commons Attribution–Share Alike 3.0 Unported license ("CC-BY-SA"). An explanation of CC-BY-SA is available at http://creativecommons.org/licenses/by-sa/3.0/. The original authors of this document, and Red Hat, designate the Fedora Project as the "Attribution Party" for purposes of CC-BY-SA. In accordance with CC-BY-SA, if you distribute this document or an adaptation of it, you must provide the URL for the original version. + + Red Hat, as the licensor of this document, waives the right to enforce, and agrees not to assert, Section 4d of CC-BY-SA to the fullest extent permitted by applicable law. + + Red Hat, Red Hat Enterprise Linux, the Shadowman logo, JBoss, MetaMatrix, Fedora, the Infinity Logo, and RHCE are trademarks of Red Hat, Inc., registered in the United States and other countries. + + For guidelines on the permitted uses of the Fedora trademarks, refer to https://fedoraproject.org/wiki/Legal:Trademark_guidelines. + + Linux® is the registered trademark of Linus Torvalds in the United States and other countries. + + Java® is a registered trademark of Oracle and/or its affiliates. + + XFS® is a trademark of Silicon Graphics International Corp. or its subsidiaries in the United States and/or other countries. + + MySQL® is a registered trademark of MySQL AB in the United States, the European Union and other countries. + + All other trademarks are the property of their respective owners. + + This document provides guidelines for improving software security through secure coding. It covers common programming languages and libraries, and focuses on concrete recommendations. + Defensive CodingI. Programming Languages   1. The C Programming Language   1.1. The core language 1.1.1. Undefined behavior 1.1.2. Recommendations for pointers and array handling 1.1.3. Recommendations for integer arithmetic 1.2. The C standard library 1.2.1. Absolutely banned interfaces 1.2.2. Functions to avoid 1.2.3. String Functions With Explicit Length Arguments 1.3. Memory allocators 1.3.1. malloc and related functions 1.3.2. alloca and other forms of stack-based allocation 1.3.3. Array allocation 1.3.4. Custom memory allocators 1.3.5. Conservative garbage collection 2. The C++ Programming Language   2.1. The core language 2.1.1. Array allocation with operator new[] 2.1.2. Overloading 2.1.3. ABI compatibility and preparing for security updates 2.1.4. C++0X and C++11 support 2.2. The C++ standard library 2.2.1. Containers and operator[] 3. The Python Programming Language   3.1. Dangerous standard library features 3.2. Run-time compilation and code generation 3.3. Sandboxing II. Specific Programming Tasks   4. Library Design   4.1. State management 4.1.1. Global state 4.1.2. Handles 4.2. Object orientation 4.3. Callbacks 4.4. Process attributes 5. File Descriptor Management   5.1. Closing descriptors 5.1.1. Error handling during descriptor close 5.1.2. Closing descriptors and race conditions 5.1.3. Lingering state after close 5.2. Preventing file descriptor leaks to child processes 5.3. Dealing with the select limit 6. File system manipulation   6.1. Working with files and directories owned by other users 6.2. Accessing the file system as a different user 6.3. File system limits 6.4. File system features 6.5. Checking free space 7. Temporary files   7.1. Obtaining the location of temporary directory 7.2. Named temporary files 7.3. Temporary files without names 7.4. Temporary directories 7.5. Compensating for unsafe file creation 8. Processes   8.1. Safe process creation 8.1.1. Obtaining the program path and the command line template 8.1.2. Bypassing the shell 8.1.3. Specifying the process environment 8.1.4. Robust argument list processing 8.1.5. Passing secrets to subprocesses 8.2. Handling child process termination 8.3. SUID/SGID processes 8.3.1. Accessing environment variables 8.4. Daemons 8.5. Semantics of command line arguments 8.6. fork as a primitive for parallelism 9. Serialization and Deserialization   9.1. Recommendations for manually written decoders 9.2. Protocol design 9.3. Library support for deserialization 9.4. XML serialization 9.4.1. External references 9.4.2. Entity expansion 9.4.3. XInclude processing 9.4.4. Algorithmic complexity of XML validation 9.4.5. Using Expat for XML parsing 9.4.6. Using OpenJDK for XML parsing and validation 9.5. Protocol Encoders 10. Cryptography   10.1. Primitives 10.2. Randomness III. Implementing Security Features   11. Authentication and Authorization   11.1. Authenticating servers 11.2. Host-based authentication 11.3. UNIX domain socket authentication 11.4. AF_NETLINK authentication of origin 12. Transport Layer Security   12.1. Common Pitfalls 12.1.1. OpenSSL Pitfalls 12.1.2. GNUTLS Pitfalls 12.1.3. OpenJDK Pitfalls 12.1.4. NSS Pitfalls 12.2. TLS Clients 12.2.1. Implementation TLS Clients With OpenSSL 12.2.2. Implementation TLS Clients With GNUTLS 12.2.3. Implementing TLS Clients With OpenJDK 12.2.4. Implementing TLS Clients With NSS 12.2.5. Implementing TLS Clients With Python A. Revision History   Part I. Programming LanguagesPart I. Programming LanguagesChapter 1.Chapter 1. The C Programming LanguageThe C Programming LanguageThe core language1.1. The core language + C provides no memory safety. Most recommendations in this section deal with this aspect of the language. + Undefined behavior1.1.1. Undefined behavior + Some C constructs are defined to be undefined by the C standard. This does not only mean that the standard does not describe what happens when the construct is executed. It also allows optimizing compilers such as GCC to assume that this particular construct is never reached. In some cases, this has caused GCC to optimize security checks away. (This is not a flaw in GCC or the C language. But C certainly has some areas which are more difficult to use than others.) + + Common sources of undefined behavior are: + + out-of-bounds array accesses + + null pointer dereferences + + overflow in signed integer arithmetic + Recommendations for pointers and array handling1.1.2. Recommendations for pointers and array handling + Always keep track of the size of the array you are working with. Often, code is more obviously correct when you keep a pointer past the last element of the array, and calculate the number of remaining elements by substracting the current position from that pointer. The alternative, updating a separate variable every time when the position is advanced, is usually less obviously correct. + + Example 1.1, “Array processing in C” shows how to extract Pascal-style strings from a character buffer. The two pointers kept for length checks are inend and outend. inp and outp are the respective positions. The number of input bytes is checked using the expression len > (size_t)(inend - inp). The cast silences a compiler warning; inend is always larger than inp. + Example 1.1. Array processing in C +ssize_t +extract_strings(const char *in, size_t inlen, char **out, size_t outlen) +{ + const char *inp = in; + const char *inend = in + inlen; + char **outp = out; + char **outend = out + outlen; + + while (inp != inend) { + size_t len; + char *s; + if (outp == outend) { + errno = ENOSPC; + goto err; + } + len = (unsigned char)*inp; + ++inp; + if (len > (size_t)(inend - inp)) { + errno = EINVAL; + goto err; + } + s = malloc(len + 1); + if (s == NULL) { + goto err; + } + memcpy(s, inp, len); + inp += len; + s[len] = '\0'; + *outp = s; + ++outp; + } + return outp - out; +err: + { + int errno_old = errno; + while (out != outp) { + free(*out); + ++out; + } + errno = errno_old; + } + return -1; +} + + It is important that the length checks always have the form len > (size_t)(inend - inp), where len is a variable of type size_t which denotes the total number of bytes which are about to be read or written next. In general, it is not safe to fold multiple such checks into one, as in len1 + len2 > (size_t)(inend - inp), because the expression on the left can overflow or wrap around (see Section 1.1.3, “Recommendations for integer arithmetic”), and it no longer reflects the number of bytes to be processed. + Recommendations for integer arithmetic1.1.3. Recommendations for integer arithmetic + Overflow in signed integer arithmetic is undefined. This means that it is not possible to check for overflow after it happened, see Example 1.2, “Incorrect overflow detection in C”. + Example 1.2. Incorrect overflow detection in C +void report_overflow(void); + +int +add(int a, int b) +{ + int result = a + b; + if (a < 0 || b < 0) { + return -1; + } + // The compiler can optimize away the following if statement. + if (result < 0) { + report_overflow(); + } + return result; +} + + The following approaches can be used to check for overflow, without actually causing it. + + Use a wider type to perform the calculation, check that the result is within bounds, and convert the result to the original type. All intermediate results must be checked in this way. + + Perform the calculation in the corresponding unsigned type and use bit fiddling to detect the overflow. + + Compute bounds for acceptable input values which are known to avoid overflow, and reject other values. This is the preferred way for overflow checking on multiplications, see Example 1.3, “Overflow checking for unsigned multiplication”. + Example 1.3. Overflow checking for unsigned multiplication +unsigned +mul(unsigned a, unsigned b) +{ + if (b && a > ((unsigned)-1) / b) { + report_overflow(); + } + return a * b; +} + + Basic arithmetic operations a commutative, so for bounds checks, there are two different but mathematically equivalent expressions. Sometimes, one of the expressions results in better code because parts of it can be reduced to a constant. This applies to overflow checks for multiplication a * b involving a constant a, where the expression is reduced to b > C for some constant C determined at compile time. The other expression, b && a > ((unsigned)-1) / b, is more difficult to optimize at compile time. + + When a value is converted to a signed integer, GCC always chooses the result based on 2's complement arithmetic. This GCC extension (which is also implemented by other compilers) helps a lot when implementing overflow checks. + + Legacy code should be compiled with the -fwrapv GCC option. As a result, GCC will provide 2's complement semantics for integer arithmetic, including defined behavior on integer overflow. + The C standard library1.2. The C standard library + Parts of the C standard library (and the UNIX and GNU extensions) are difficult to use, so you shoud avoid them. + + Please check the applicable documentation before using the recommended replacements. Many of these functions allocate buffers using malloc which your code must deallocate explicitly using free. + Absolutely banned interfaces1.2.1. Absolutely banned interfaces + The functions listed below must not be used because they are almost always unsafe. Use the indicated replacements instead. + + getsfgets + + getwdgetcwd or get_current_dir_name + + readdir_rreaddir + + realpath (with a non-NULL second parameter) ⟶ realpath with NULL as the second parameter, or canonicalize_file_name + + The constants listed below must not be used, either. Instead, code must allocate memory dynamically and use interfaces with length checking. + + NAME_MAX (limit not actually enforced by the kernel) + + PATH_MAX (limit not actually enforced by the kernel) + + _PC_NAME_MAX (This limit, returned by the pathconf function, is not enforced by the kernel.) + + _PC_PATH_MAX (This limit, returned by the pathconf function, is not enforced by the kernel.) + + The following structure members must not be used. + + f_namemax in struct statvfs (limit not actually enforced by the kernel, see _PC_NAME_MAX above) + Functions to avoid1.2.2. Functions to avoid + The following string manipulation functions can be used securely in principle, but their use should be avoided because they are difficult to use correctly. Calls to these functions can be replaced with asprintf or vasprintf. (For non-GNU targets, these functions are available from Gnulib.) In some cases, the snprintf function might be a suitable replacement, see Section 1.2.3, “String Functions With Explicit Length Arguments”. + + sprintf + + strcat + + strcpy + + vsprintf + + Use the indicated replacements for the functions below. + + allocamalloc and free (see Section 1.3.2, “alloca and other forms of stack-based allocation”) + + putenv ⟶ explicit envp argument in process creation (see Section 8.1.3, “Specifying the process environment”) + + setenv ⟶ explicit envp argument in process creation (see Section 8.1.3, “Specifying the process environment”) + + strdupastrdup and free (see Section 1.3.2, “alloca and other forms of stack-based allocation”) + + strndupastrndup and free (see Section 1.3.2, “alloca and other forms of stack-based allocation”) + + systemposix_spawn or fork/execve/ (see Section 8.1.2, “Bypassing the shell”) + + unsetenv ⟶ explicit envp argument in process creation (see Section 8.1.3, “Specifying the process environment”) + String Functions With Explicit Length Arguments1.2.3. String Functions With Explicit Length Arguments + The snprintf function provides a way to construct a string in a statically-sized buffer. (If the buffer size is dynamic, use asprintf instead.) + +char fraction[30]; +snprintf(fraction, sizeof(fraction), "%d/%d", numerator, denominator); + + The second argument to the snprintf should always be the size of the buffer in the first argument (which should be a character array). Complex pointer and length arithmetic can introduce errors and nullify the security benefits of snprintf. If you need to construct a string iteratively, by repeatedly appending fragments, consider constructing the string on the heap, increasing the buffer with realloc as needed. (snprintf does not support overlapping the result buffer with argument strings.) + + If you use vsnprintf (or snprintf) with a format string which is not a constant, but a function argument, it is important to annotate the function with a format function attribute, so that GCC can warn about misuse of your function (see Example 1.4, “The format function attribute”). + Example 1.4. The format function attribute +void log_format(const char *format, ...) __attribute__((format(printf, 1, 2))); + +void +log_format(const char *format, ...) +{ + char buf[1000]; + va_list ap; + va_start(ap, format); + vsnprintf(buf, sizeof(buf), format, ap); + va_end(ap); + log_string(buf); +} + + There are other functions which operator on NUL-terminated strings and take a length argument which affects the number of bytes written to the destination: strncpy, strncat, and stpncpy. These functions do not ensure that the result string is NUL-terminated. For strncpy, NUL termination can be added this way: + +char buf[10]; +strncpy(buf, data, sizeof(buf)); +buf[sizeof(buf) - 1] = '\0'; + + Some systems support strlcpy and strlcat functions which behave this way, but these functions are not part of GNU libc. Using snprintf with a suitable format string is a simple (albeit slightly slower) replacement. + Memory allocators1.3. Memory allocatorsmalloc and related functions1.3.1. malloc and related functions + The C library interfaces for memory allocation are provided by malloc, free and realloc, and the calloc function. In addition to these generic functions, there are derived functions such as strdup which perform allocation using malloc internally, but do not return untyped heap memory (which could be used for any object). + + The C compiler knows about these functions and can use their expected behavior for optimizations. For instance, the compiler assumes that an existing pointer (or a pointer derived from an existing pointer by arithmetic) will not point into the memory area returned by malloc. + + If the allocation fails, realloc does not free the old pointer. Therefore, the idiom ptr = realloc(ptr, size); is wrong because the memory pointed to by ptr leaks in case of an error. + 1.3.1.1. Use-after-free errors + After free, the pointer is invalid. Further pointer dereferences are not allowed (and are usually detected by valgrind). Less obvious is that any use of the old pointer value is not allowed, either. In particular, comparisons with any other pointer (or the null pointer) are undefined according to the C standard. + + The same rules apply to realloc if the memory area cannot be enlarged in-place. For instance, the compiler may assume that a comparison between the old and new pointer will always return false, so it is impossible to detect movement this way. + 1.3.1.2. Handling memory allocation errors + Recovering from out-of-memory errors is often difficult or even impossible. In these cases, malloc and other allocation functions return a null pointer. Dereferencing this pointer lead to a crash. Such dereferences can even be exploitable for code execution if the dereference is combined with an array subscript. + + In general, if you cannot check all allocation calls and handle failure, you should abort the program on allocation failure, and not rely on the null pointer dereference to terminate the process. See Section 9.1, “Recommendations for manually written decoders” for related memory allocation concerns. + alloca and other forms of stack-based allocation1.3.2. alloca and other forms of stack-based allocation + Allocation on the stack is risky because stack overflow checking is implicit. There is a guard page at the end of the memory area reserved for the stack. If the program attempts to read from or write to this guard page, a SIGSEGV signal is generated and the program typically terminates. + + This is sufficient for detecting typical stack overflow situations such as unbounded recursion, but it fails when the stack grows in increments larger than the size of the guard page. In this case, it is possible that the stack pointer ends up pointing into a memory area which has been allocated for a different purposes. Such misbehavior can be exploitable. + + A common source for large stack growth are calls to alloca and related functions such as strdupa. These functions should be avoided because of the lack of error checking. (They can be used safely if the allocated size is less than the page size (typically, 4096 bytes), but this case is relatively rare.) Additionally, relying on alloca makes it more difficult to reorgnize the code because it is not allowed to use the pointer after the function calling alloca has returned, even if this function has been inlined into its caller. + + Similar concerns apply to variable-length arrays (VLAs), a feature of the C99 standard which started as a GNU extension. For large objects exceeding the page size, there is no error checking, either. + + In both cases, negative or very large sizes can trigger a stack-pointer wraparound, and the stack pointer and end up pointing into caller stack frames, which is fatal and can be exploitable. + + If you want to use alloca or VLAs for performance reasons, consider using a small on-stack array (less than the page size, large enough to fulfill most requests). If the requested size is small enough, use the on-stack array. Otherwise, call malloc. When exiting the function, check if malloc had been called, and free the buffer as needed. + Array allocation1.3.3. Array allocation + When allocating arrays, it is important to check for overflows. The calloc function performs such checks. + + If malloc or realloc is used, the size check must be written manually. For instance, to allocate an array of n elements of type T, check that the requested size is not greater than n / sizeof(T). + Custom memory allocators1.3.4. Custom memory allocators + Custom memory allocates come in two forms: replacements for malloc, and completely different interfaces for memory management. Both approaches can reduce the effectiveness of valgrind and similar tools, and the heap corruption detection provided by GNU libc, so they should be avoided. + + Memory allocators are difficult to write and contain many performance and security pitfalls. + + When computing array sizes or rounding up allocation requests (to the next allocation granularity, or for alignment purposes), checks for arithmetic overflow are required. + + Size computations for array allocations need overflow checking. See Section 1.3.3, “Array allocation”. + + It can be difficult to beat well-tuned general-purpose allocators. In micro-benchmarks, pool allocators can show huge wins, and size-specific pools can reduce internal fragmentation. But often, utilization of individual pools is poor, and + Conservative garbage collection1.3.5. Conservative garbage collection + Garbage collection can be an alternative to explicit memory management using malloc and free. The Boehm-Dehmers-Weiser allocator can be used from C programs, with minimal type annotations. Performance is competitive with malloc on 64-bit architectures, especially for multi-threaded programs. The stop-the-world pauses may be problematic for some real-time applications, though. + + However, using a conservative garbage collector may reduce opertunities for code reduce because once one library in a program uses garbage collection, the whole process memory needs to be subject to it, so that no pointers are missed. The Boehm-Dehmers-Weiser collector also reserves certain signals for internal use, so it is not fully transparent to the rest of the program. + Chapter 2.Chapter 2. The C++ Programming LanguageThe C++ Programming LanguageThe core language2.1. The core language + C++ includes a large subset of the C language. As far as the C subset is used, the recommendations in Chapter 1, The C Programming Language apply. + Array allocation with operator new[]2.1.1. Array allocation with operator new[] + For very large values of n, an expression like new T[n] can return a pointer to a heap region which is too small. In other words, not all array elements are actually backed with heap memory reserved to the array. Current GCC versions generate code that performs a computation of the form sizeof(T) * size_t(n) + cookie_size, where cookie_size is currently at most 8. This computation can overflow, and GCC-generated code does not detect this. + + The std::vector template can be used instead an explicit array allocation. (The GCC implementation detects overflow internally.) + + If there is no alternative to operator new[], code which allocates arrays with a variable length must check for overflow manually. For the new T[n] example, the size check could be n || (n > 0 && n > (size_t(-1) - 8) / sizeof(T)). (See Section 1.1.3, “Recommendations for integer arithmetic”.) If there are additional dimensions (which must be constants according to the C++ standard), these should be included as factors in the divisor. + + These countermeasures prevent out-of-bounds writes and potential code execution. Very large memory allocations can still lead to a denial of service. Section 9.1, “Recommendations for manually written decoders” contains suggestions for mitigating this problem when processing untrusted data. + + See Section 1.3.3, “Array allocation” for array allocation advice for C-style memory allocation. + Overloading2.1.2. Overloading + Do not overload functions with versions that have different security characteristics. For instance, do not implement a function strcat which works on std::string arguments. Similarly, do not name methods after such functions. + ABI compatibility and preparing for security updates2.1.3. ABI compatibility and preparing for security updates + A stable binary interface (ABI) is vastly preferred for security updates. Without a stable ABI, all reverse dependencies need recompiling, which can be a lot of work and could even be impossible in some cases. Ideally, a security update only updates a single dynamic shared object, and is picked up automatically after restarting affected processes. + + Outside of extremely performance-critical code, you should ensure that a wide range of changes is possible without breaking ABI. Some very basic guidelines are: + + Avoid inline functions. + + Use the pointer-to-implementation idiom. + + Try to avoid templates. Use them if the increased type safety provides a benefit to the programmer. + + Move security-critical code out of templated code, so that it can be patched in a central place if necessary. + + The KDE project publishes a document with more extensive guidelines on ABI-preserving changes to C++ code, Policies/Binary Compatibility Issues With C++11 http://techbase.kde.org/Policies/Binary_Compatibility_Issues_With_C++ (d-pointer refers to the pointer-to-implementation idiom). + C++0X and C++11 support2.1.4. C++0X and C++11 support + GCC offers different language compatibility modes: + + -std=c++98 for the original 1998 C++ standard + + -std=c++03 for the 1998 standard with the changes from the TR1 technical report + + -std=c++11 for the 2011 C++ standard. This option should not be used. + + -std=c++0x for several different versions of C++11 support in development, depending on the GCC version. This option should not be used. + + For each of these flags, there are variants which also enable GNU extensions (mostly language features also found in C99 or C11): -std=gnu++98, -std=gnu++03, -std=gnu++11. Again, -std=gnu++11 should not be used. + + If you enable C++11 support, the ABI of the standard C++ library libstdc++ will change in subtle ways. Currently, no C++ libraries are compiled in C++11 mode, so if you compile your code in C++11 mode, it will be incompatible with the rest of the system. Unfortunately, this is also the case if you do not use any C++11 features. Currently, there is no safe way to enable C++11 mode (except for freestanding applications). + + The meaning of C++0X mode changed from GCC release to GCC release. Earlier versions were still ABI-compatible with C++98 mode, but in the most recent versions, switching to C++0X mode activates C++11 support, with its compatibility problems. + + Some C++11 features (or approximations thereof) are available with TR1 support, that is, with -std=c++03 or -std=gnu++03 and in the <tr1/*> header files. This includes std::tr1::shared_ptr (from <tr1/memory>) and std::tr1::function (from <tr1/functional>). For other C++11 features, the Boost C++ library contains replacements. + The C++ standard library2.2. The C++ standard library + The C++ standard library includes most of its C counterpart by reference, see Section 1.2, “The C standard library”. + Containers and operator[]2.2.1. Containers and operator[] + Many containers similar to std::vector provide both operator[](size_type) and a member function at(size_type). This applies to std::vector itself, std::array, std::string and other instances of std::basic_string. + + operator[](size_type) is not required by the standard to perform bounds checking (and the implementation in GCC does not). In contrast, at(size_type) must perform such a check. Therefore, in code which is not performance-critical, you should prefer at(size_type) over operator[](size_type), even though it is slightly more verbose. + Chapter 3.Chapter 3. The Python Programming LanguageThe Python Programming Language + Python provides memory safety by default, so low-level security vulnerabilities are rare and typically needs fixing the Python interpreter or standard library itself. + + Other sections with Python-specific advice include: + + Chapter 7, Temporary files + + Section 8.1, “Safe process creation” + + Chapter 9, Serialization and Deserialization, in particular Section 9.3, “Library support for deserialization” + + Section 10.2, “Randomness” + Dangerous standard library features3.1. Dangerous standard library features + Some areas of the standard library, notably the ctypes module, do not provide memory safety guarantees comparable to the rest of Python. If such functionality is used, the advice in Section 1.1, “The core language” should be followed. + Run-time compilation and code generation3.2. Run-time compilation and code generation + The following Python functions and statements related to code execution should be avoided: + + compile + + eval + + exec + + execfile + + If you need to parse integers or floating point values, use the int and float functions instead of eval. Sandboxing untrusted Python code does not work reliably. + Sandboxing3.3. Sandboxing + The rexec Python module cannot safely sandbox untrusted code and should not be used. The standard CPython implementation is not suitable for sandboxing. + Part II. Specific Programming TasksPart II. Specific Programming TasksChapter 4.Chapter 4. Library DesignLibrary Design + Throught this section, the term client code refers to applications and other libraries using the library. + State management4.1. State management + + Global state4.1.1. Global state + Global state should be avoided. + + If this is impossible, the global state must be protected with a lock. For C/C++, you can use the pthread_mutex_lock and pthread_mutex_unlock functions without linking against -lpthread because the system provides stubs for non-threaded processes. + + For compatibility with fork, these locks should be acquired and released in helpers registered with pthread_atfork. This function is not available without -lpthread, so you need to use dlsym or a weak symbol to obtain its address. + + If you need fork protection for other reasons, you should store the process ID and compare it to the value returned by getpid each time you access the global state. (getpid is not implemented as a system call and is fast.) If the value changes, you know that you have to re-create the state object. (This needs to be combined with locking, of course.) + Handles4.1.2. Handles + Library state should be kept behind a curtain. Client code should receive only a handle. In C, the handle can be a pointer to an incomplete struct. In C++, the handle can be a pointer to an abstract base class, or it can be hidden using the pointer-to-implementation idiom. + + The library should provide functions for creating and destroying handles. (In C++, it is possible to use virtual destructors for the latter.) Consistency between creation and destruction of handles is strongly recommended: If the client code created a handle, it is the responsibility of the client code to destroy it. (This is not always possible or convenient, so sometimes, a transfer of ownership has to happen.) + + Using handles ensures that it is possible to change the way the library represents state in a way that is transparent to client code. This is important to facilitate security updates and many other code changes. + + It is not always necessary to protect state behind a handle with a lock. This depends on the level of thread safety the library provides. + Object orientation4.2. Object orientation + Classes should be either designed as base classes, or it should be impossible to use them as base classes (like final classes in Java). Classes which are not designed for inheritance and are used as base classes nevertheless create potential maintenance hazards because it is difficult to predict how client code will react when calls to virtual methods are added, reordered or removed. + + Virtual member functions can be used as callbacks. See Section 4.3, “Callbacks” for some of the challenges involved. + Callbacks4.3. Callbacks + Higher-order code is difficult to analyze for humans and computers alike, so it should be avoided. Often, an iterator-based interface (a library function which is called repeatedly by client code and returns a stream of events) leads to a better design which is easier to document and use. + + If callbacks are unavoidable, some guidelines for them follow. + + In modern C++ code, std::function objects should be used for callbacks. + + In older C++ code and in C code, all callbacks must have an additional closure parameter of type void *, the value of which can be specified by client code. If possible, the value of the closure parameter should be provided by client code at the same time a specific callback is registered (or specified as a function argument). If a single closure parameter is shared by multiple callbacks, flexibility is greatly reduced, and conflicts between different pieces of client code using the same library object could be unresolvable. In some cases, it makes sense to provide a de-registration callback which can be used to destroy the closure parameter when the callback is no longer used. + + Callbacks can throw exceptions or call longjmp. If possible, all library objects should remain in a valid state. (All further operations on them can fail, but it should be possible to deallocate them without causing resource leaks.) + + The presence of callbacks raises the question if functions provided by the library are reentrant. Unless a library was designed for such use, bad things will happen if a callback function uses functions in the same library (particularly if they are invoked on the same objects and manipulate the same state). When the callback is invoked, the library can be in an inconsistent state. Reentrant functions are more difficult to write than thread-safe functions (by definition, simple locking would immediately lead to deadlocks). It is also difficult to decide what to do when destruction of an object which is currently processing a callback is requested. + Process attributes4.4. Process attributes + Several attributes are global and affect all code in the process, not just the library that manipulates them. + + environment variables (see Section 8.3.1, “Accessing environment variables”) + + umask + + user IDs, group IDs and capabilities + + current working directory + + signal handlers, signal masks and signal delivery + + file locks (especially fcntl locks behave in surprising ways, not just in a multi-threaded environment) + + Library code should avoid manipulating these global process attributes. It should not rely on environment variables, umask, the current working directory and signal masks because these attributes can be inherted from an untrusted source. + + In addition, there are obvious process-wide aspects such as the virtual memory layout, the set of open files and dynamic shared objects, but with the exception of shared objects, these can be manipulated in a relatively isolated way. + Chapter 5.Chapter 5. File Descriptor ManagementFile Descriptor Management + File descriptors underlie all input/output mechanisms offered by the system. They are used to implementation the FILE *-based functions found in <stdio.h>, and all the file and network communication facilities provided by the Python and Java environments are eventually implemented in them. + + File descriptors are small, non-negative integers in userspace, and are backed on the kernel side with complicated data structures which can sometimes grow very large. + Closing descriptors5.1. Closing descriptors + If a descriptor is no longer used by a program and is not closed explicitly, its number cannot be reused (which is problematic in itself, see Section 5.3, “Dealing with the select limit”), and the kernel resources are not freed. Therefore, it is important to close all descriptors at the earlierst point in time possible, but not earlier. + Error handling during descriptor close5.1.1. Error handling during descriptor close + The close system call is always successful in the sense that the passed file descriptor is never valid after the function has been called. However, close still can return an error, for example if there was a file system failure. But this error is not very useful because the absence of an error does not mean that all caches have been emptied and previous writes have been made durable. Programs which need such guarantees must open files with O_SYNC or use fsync or fdatasync, and may also have to fsync the directory containing the file. + Closing descriptors and race conditions5.1.2. Closing descriptors and race conditions + Unlike process IDs, which are recycle only gradually, the kernel always allocates the lowest unused file descriptor when a new descriptor is created. This means that in a multi-threaded program which constantly opens and closes file descriptors, descriptors are reused very quickly. Unless descriptor closing and other operations on the same file descriptor are synchronized (typically, using a mutex), there will be race coniditons and I/O operations will be applied to the wrong file descriptor. + + Sometimes, it is necessary to close a file descriptor concurrently, while another thread might be about to use it in a system call. In order to support this, a program needs to create a single special file descriptor, one on which all I/O operations fail. One way to achieve this is to use socketpair, close one of the descriptors, and call shutdown(fd, SHUTRDWR) on the other. + + When a descriptor is closed concurrently, the program does not call close on the descriptor. Instead it program uses dup2 to replace the descriptor to be closed with the dummy descriptor created earlier. This way, the kernel will not reuse the descriptor, but it will carry out all other steps associated with calling a descriptor (for instance, if the descriptor refers to a stream socket, the peer will be notified). + + This is just a sketch, and many details are missing. Additional data structures are needed to determine when it is safe to really close the descriptor, and proper locking is required for that. + Lingering state after close5.1.3. Lingering state after close + By default, closing a stream socket returns immediately, and the kernel will try to send the data in the background. This means that it is impossible to implement accurate accounting of network-related resource utilization from userspace. + + The SO_LINGER socket option alters the behavior of close, so that it will return only after the lingering data has been processed, either by sending it to the peer successfully, or by discarding it after the configured timeout. However, there is no interface which could perform this operation in the background, so a separate userspace thread is needed for each close call, causing scalability issues. + + Currently, there is no application-level countermeasure which applies universally. Mitigation is possible with iptables (the connlimit match type in particular) and specialized filtering devices for denial-of-service network traffic. + + These problems are not related to the TIME_WAIT state commonly seen in netstat output. The kernel automatically expires such sockets if necessary. + Preventing file descriptor leaks to child processes5.2. Preventing file descriptor leaks to child processes + Child processes created with fork share the initial set of file descriptors with their parent process. By default, file descriptors are also preserved if a new process image is created with execve (or any of the other functions such as system or posix_spawn). + + Usually, this behavior is not desirable. There are two ways to turn it off, that is, to prevent new process images from inheriting the file descriptors in the parent process: + + Set the close-on-exec flag on all newly created file descriptors. Traditionally, this flag is controlled by the FD_CLOEXEC flag, using F_GETFD and F_SETFD operations of the fcntl function. + + However, in a multi-threaded process, there is a race condition: a subprocess could have been created between the time the descriptor was created and the FD_CLOEXEC was set. Therefore, many system calls which create descriptors (such as open and openat) now accept the O_CLOEXEC flag (SOCK_CLOEXEC for socket and socketpair), which cause the FD_CLOEXEC flag to be set for the file descriptor in an atomic fashion. In addition, a few new systems calls were introduced, such as pipe2 and dup3. + + The downside of this approach is that every descriptor needs to receive special treatment at the time of creation, otherwise it is not completely effective. + + After calling fork, but before creating a new process image with execve, all file descriptors which the child process will not need are closed. + + Traditionally, this was implemented as a loop over file descriptors ranging from 3 to 255 and later 1023. But this is only an approximatio because it is possible to create file descriptors outside this range easily (see Section 5.3, “Dealing with the select limit”). Another approach reads /proc/self/fd and closes the unexpected descriptors listed there, but this approach is much slower. + + At present, environments which care about file descriptor leakage implement the second approach. OpenJDK 6 and 7 are among them. + Dealing with the select limit5.3. Dealing with the select limit + By default, a user is allowed to open only 1024 files in a single process, but the system administrator can easily change this limit (which is necessary for busy network servers). However, there is another restriction which is more difficult to overcome. + + The select function only supports a maximum of FD_SETSIZE file descriptors (that is, the maximum permitted value for a file descriptor is FD_SETSIZE - 1, usually 1023.) If a process opens many files, descriptors may exceed such limits. It is impossible to query such descriptors using select. + + If a library which creates many file descriptors is used in the same process as a library which uses select, at least one of them needs to be changed. Calls to select can be replaced with calls to poll or another event handling mechanism. + + Alternatively, the library with high descriptor usage can relocate descriptors above the FD_SETSIZE limit using the following procedure. + + Create the file descriptor fd as usual, preferably with the O_CLOEXEC flag. + + Before doing anything else with the descriptor fd, invoke: + + int newfd = fcntl(fd, F_DUPFD_CLOEXEC, (long)FD_SETSIZE); + + Check that newfd result is non-negative, otherwise close fd and report an error, and return. + + Close fd and continue to use newfd. + + The new descriptor has been allocated above the FD_SETSIZE. Even though this algorithm is racy in the sense that the FD_SETSIZE first descriptors could fill up, a very high degree of physical parallelism is required before this becomes a problem. + Chapter 6.Chapter 6. File system manipulationFile system manipulation + In this chapter, we discuss general file system manipulation, with a focus on access files and directories to which an other, potentially untrusted user has write access. + + Temporary files are covered in their own chapter, Chapter 7, Temporary files. + Working with files and directories owned by other users6.1. Working with files and directories owned by other users + Sometimes, it is necessary to operate on files and directories owned by other (potentially untrusted) users. For example, a system administrator could remove the home directory of a user, or a package manager could update a file in a directory which is owned by an application-specific user. This differs from accessing the file system as a specific user; see Section 6.2, “Accessing the file system as a different user”. + + Accessing files across trust boundaries faces several challenges, particularly if an entire directory tree is being traversed: + 1. + Another user might add file names to a writable directory at any time. This can interfere with file creation and the order of names returned by readdir. + 2. + Merely opening and closing a file can have side effects. For instance, an automounter can be triggered, or a tape device rewound. Opening a file on a local file system can block indefinitely, due to mandatory file locking, unless the O_NONBLOCK flag is specified. + 3. + Hard links and symbolic links can redirect the effect of file system operations in unexpected ways. The O_NOFOLLOW and AT_SYMLINK_NOFOLLOW variants of system calls only affected final path name component. + 4. + The structure of a directory tree can change. For example, the parent directory of what used to be a subdirectory within the directory tree being processed could suddenly point outside that directory tree. + + Files should always be created with the O_CREAT and O_EXCL flags, so that creating the file will fail if it already exists. This guards against the unexpected appearance of file names, either due to creation of a new file, or hard-linking of an existing file. In multi-threaded programs, rather than manipulating the umask, create the files with mode 000 if possible, and adjust it afterwards with fchmod. + + To avoid issues related to symbolic links and directory tree restructuring, the “at” variants of system calls have to be used (that is, functions like openat, fchownat, fchmodat, and unlinkat, together with O_NOFOLLOW or AT_SYMLINK_NOFOLLOW). Path names passed to these functions must have just a single component (that is, without a slash). When descending, the descriptors of parent directories must be kept open. The missing opendirat function can be emulated with openat (with an O_DIRECTORY flag, to avoid opening special files with side effects), followed by fdopendir. + + If the “at” functions are not available, it is possible to emulate them by changing the current directory. (Obviously, this only works if the process is not multi-threaded.) fchdir has to be used to change the current directory, and the descriptors of the parent directories have to be kept open, just as with the “at”-based approach. chdir("...") is unsafe because it might ascend outside the intended directory tree. + + This “at” function emulation is currently required when manipulating extended attributes. In this case, the lsetxattr function can be used, with a relative path name consisting of a single component. This also applies to SELinux contexts and the lsetfilecon function. + + Currently, it is not possible to avoid opening special files and changes to files with hard links if the directory containing them is owned by an untrusted user. (Device nodes can be hard-linked, just as regular files.) fchmodat and fchownat affect files whose link count is greater than one. But opening the files, checking that the link count is one with fstat, and using fchmod and fchown on the file descriptor may have unwanted side effects, due to item 2 above. When creating directories, it is therefore important to change the ownership and permissions only after it has been fully created. Until that point, file names are stable, and no files with unexpected hard links can be introduced. + + Similarly, when just reading a directory owned by an untrusted user, it is currently impossible to reliably avoid opening special files. + + There is no workaround against the instability of the file list returned by readdir. Concurrent modification of the directory can result in a list of files being returned which never actually existed on disk. + + Hard links and symbolic links can be safely deleted using unlinkat without further checks because deletion only affects the name within the directory tree being processed. + Accessing the file system as a different user6.2. Accessing the file system as a different user + This section deals with access to the file system as a specific user. This is different from accessing files and directories owned by a different, potentially untrusted user; see Section 6.2, “Accessing the file system as a different user”. + + One approach is to spawn a child process which runs under the target user and group IDs (both effective and real IDs). Note that this child process can block indefinitely, even when processing regular files only. For example, a special FUSE file system could cause the process to hang in uninterruptible sleep inside a stat system call. + + An existing process could change its user and group ID using setfsuid and setfsgid. (These functions are preferred over seteuid and setegid because they do not allow the impersonated user to send signals to the process.) These functions are not thread safe. In multi-threaded processes, these operations need to be performed in a single-threaded child process. Unexpected blocking may occur as well. + + It is not recommended to try to reimplement the kernel permission checks in user space because the required checks are complex. It is also very difficult to avoid race conditions during path name resolution. + File system limits6.3. File system limits + For historical reasons, there are preprocessor constants such as PATH_MAX, NAME_MAX. However, on most systems, the length of canonical path names (absolute path names with all symbolic links resolved, as returned by realpath or canonicalize_file_name) can exceed PATH_MAX bytes, and individual file name components can be longer than NAME_MAX. This is also true of the _PC_PATH_MAX and _PC_NAME_MAX values returned by pathconf, and the f_namemax member of struct statvfs. Therefore, these constants should not be used. This is also reason why the readdir_r should never be used (instead, use readdir). + + You should not write code in a way that assumes that there is an upper limit on the number of subdirectories of a directory, the number of regular files in a directory, or the link count of an inode. + File system features6.4. File system features + Not all file systems support all features. This makes it very difficult to write general-purpose tools for copying files. For example, a copy operation intending to preserve file permissions will generally fail when copying to a FAT file system. + + Some file systems are case-insensitive. Most should be case-preserving, though. + + Name length limits vary greatly, from eight to thousands of bytes. Path length limits differ as well. Most systems impose an upper bound on path names passed to the kernel, but using relative path names, it is possible to create and access files whose absolute path name is essentially of unbounded length. + + Some file systems do not store names as fairly unrestricted byte sequences, as it has been traditionally the case on GNU systems. This means that some byte sequences (outside the POSIX safe character set) are not valid names. Conversely, names of existing files may not be representable as byte sequences, and the files are thus inaccessible on GNU systems. Some file systems perform Unicode canonicalization on file names. These file systems preserve case, but reading the name of a just-created file using readdir might still result in a different byte sequence. + + Permissions and owners are not universally supported (and SUID/SGID bits may not be available). For example, FAT file systems assign ownership based on a mount option, and generally mark all files as executable. Any attempt to change permissions would result in an error. + + Non-regular files (device nodes, FIFOs) are not generally available. + + Only on some file systems, files can have holes, that is, not all of their contents is backed by disk storage. + + ioctl support (even fairly generic functionality such as FIEMAP for discovering physical file layout and holes) is file-system-specific. + + Not all file systems support extended attributes, ACLs and SELinux metadata. Size and naming restriction on extended attributes vary. + + Hard links may not be supported at all (FAT) or only within the same directory (AFS). Symbolic links may not be available, either. Reflinks (hard links with copy-on-write semantics) are still very rare. Recent systems restrict creation of hard links to users which own the target file or have read/write access to it, but older systems do not. + + Renaming (or moving) files using rename can fail (even when stat indicates that the source and target directories are located on the same file system). This system call should work if the old and new paths are located in the same directory, though. + + Locking semantics vary among file systems. This affects advisory and mandatory locks. For example, some network file systems do not allow deleting files which are opened by any process. + + Resolution of time stamps varies from two seconds to nanoseconds. Not all time stamps are available on all file systems. File creation time (birth time) is not exposed over the stat/fstat interface, even if stored by the file system. + Checking free space6.5. Checking free space + The statvfs and fstatvfs functions allow programs to examine the number of available blocks and inodes, through the members f_bfree, f_bavail, f_ffree, and f_favail of struct statvfs. Some file systems return fictional values in the f_ffree and f_favail fields, so the only reliable way to discover if the file system still has space for a file is to try to create it. The f_bfree field should be reasonably accurate, though. + Chapter 7.Chapter 7. Temporary filesTemporary files + In this chapter, we describe how to create temporary files and directories, how to remove them, and how to work with programs which do not create files in ways that a safe with a shared directory for temporary files. General file system manipulation is treated in a separate chapter, Chapter 6, File system manipulation. + + Secure creation of temporary files has four different aspects. + + The location of the directory for temporary files must be obtained in a secure manner (that is, untrusted environment variables must be ignored, see Section 8.3.1, “Accessing environment variables”). + + A new file must be created. Reusing an existing file must be avoided (the /tmp race condition). This is tricky because traditionally, system-wide temporary directories shared by all users are used. + + The file must be created in a way that makes it impossible for other users to open it. + + The descriptor for the temporary file should not leak to subprocesses. + + All functions mentioned below will take care of these aspects. + + Traditionally, temporary files are often used to reduce memory usage of programs. More and more systems use RAM-based file systems such as tmpfs for storing temporary files, to increase performance and decrease wear on Flash storage. As a result, spooling data to temporary files does not result in any memory savings, and the related complexity can be avoided if the data is kept in process memory. + Obtaining the location of temporary directory7.1. Obtaining the location of temporary directory + Some functions below need the location of a directory which stores temporary files. For C/C++ programs, use the following steps to obtain that directory: + + Use secure_getenv to obtain the value of the TMPDIR environment variable. If it is set, convert the path to a fully-resolved absolute path, using realpath(path, NULL). Check if the new path refers to a directory and is writeable. In this case, use it as the temporary directory. + + Fall back to /tmp. + + In Python, you can use the tempfile.tempdir variable. + + Java does not support SUID/SGID programs, so you can use the java.lang.System.getenv(String) method to obtain the value of the TMPDIR environment variable, and follow the two steps described above. (Java's default directory selection does not honor TMPDIR.) + Named temporary files7.2. Named temporary files + The mkostemp function creates a named temporary file. You should specify the O_CLOEXEC flag to avoid file descriptor leaks to subprocesses. (Applications which do not use multiple threads can also use mkstemp, but libraries should use mkostemp.) For determining the directory part of the file name pattern, see Section 7.1, “Obtaining the location of temporary directory”. + + The file is not removed automatically. It is not safe to rename or delete the file before processing, or transform the name in any way (for example, by adding a file extension). If you need multiple temporary files, call mkostemp multiple times. Do not create additional file names derived from the name provided by a previous mkostemp call. However, it is safe to close the descriptor returned by mkostemp and reopen the file using the generated name. + + The Python class tempfile.NamedTemporaryFile provides similar functionality, except that the file is deleted automatically by default. Note that you may have to use the file attribute to obtain the actual file object because some programming interfaces cannot deal with file-like objects. The C function mkostemp is also available as tempfile.mkstemp. + + In Java, you can use the java.io.File.createTempFile(String, String, File) function, using the temporary file location determined according to Section 7.1, “Obtaining the location of temporary directory”. Do not use java.io.File.deleteOnExit() to delete temporary files, and do not register a shutdown hook for each temporary file you create. In both cases, the deletion hint cannot be removed from the system if you delete the temporary file prior to termination of the VM, causing a memory leak. + Temporary files without names7.3. Temporary files without names + The tmpfile function creates a temporary file and immediately deletes it, while keeping the file open. As a result, the file lacks a name and its space is deallocated as soon as the file descriptor is closed (including the implicit close when the process terminates). This avoids cluttering the temporary directory with orphaned files. + + Alternatively, if the maximum size of the temporary file is known beforehand, the fmemopen function can be used to create a FILE * object which is backed by memory. + + In Python, unnamed temporary files are provided by the tempfile.TemporaryFile class, and the tempfile.SpooledTemporaryFile class provides a way to avoid creation of small temporary files. + + Java does not support unnamed temporary files. + Temporary directories7.4. Temporary directories + The mkdtemp function can be used to create a temporary directory. (For determining the directory part of the file name pattern, see Section 7.1, “Obtaining the location of temporary directory”.) The directory is not automatically removed. In Python, this function is available as tempfile.mkdtemp. In Java 7, temporary directories can be created using the java.nio.file.Files.createTempDirectory(Path, String, FileAttribute...) function. + + When creating files in the temporary directory, use automatically generated names, e.g., derived from a sequential counter. Files with externally provided names could be picked up in unexpected contexts, and crafted names could actually point outside of the tempoary directory (due to directory traversal). + + Removing a directory tree in a completely safe manner is complicated. Unless there are overriding performance concerns, the rm program should be used, with the -rf and -- options. + Compensating for unsafe file creation7.5. Compensating for unsafe file creation + There are two ways to make a function or program which excepts a file name safe for use with temporary files. See Section 8.1, “Safe process creation”, for details on subprocess creation. + + Create a temporary directory and place the file there. If possible, run the program in a subprocess which uses the temporary directory as its current directory, with a restricted environment. Use generated names for all files in that temporary directory. (See Section 7.4, “Temporary directories”.) + + Create the temporary file and pass the generated file name to the function or program. This only works if the function or program can cope with a zero-length existing file. It is safe only under additional assumptions: + + The function or program must not create additional files whose name is derived from the specified file name or are otherwise predictable. + + The function or program must not delete the file before processing it. + + It must not access any existing files in the same directory. + + It is often difficult to check whether these additional assumptions are matched, therefore this approach is not recommended. + Chapter 8.Chapter 8. ProcessesProcessesSafe process creation8.1. Safe process creation + This section describes how to create new child processes in a safe manner. In addition to the concerns addressed below, there is the possibility of file descriptor leaks, see Section 5.2, “Preventing file descriptor leaks to child processes”. + Obtaining the program path and the command line template8.1.1. Obtaining the program path and the command line template + The name and path to the program being invoked should be hard-coded or controlled by a static configuration file stored at a fixed location (at an file system absolute path). The same applies to the template for generating the command line. + + The configured program name should be an absolute path. If it is a relative path, the contents of the PATH must be obtained in s secure manner (see Section 8.3.1, “Accessing environment variables”). If the PATH variable is not set or untrusted, the safe default /bin:/usr/bin must be used. + + If too much flexibility is provided here, it may allow invocation of arbitrary programs without proper authorization. + Bypassing the shell8.1.2. Bypassing the shell + Child processes should be created without involving the system shell. + + For C/C++, system should not be used. The posix_spawn function can be used instead, or a combination fork and execve. (In some cases, it may be preferable to use vfork or the Linux-specific clone system call instead of fork.) + + In Python, the subprocess module bypasses the shell by default (when the shell keyword argument is not set to true). os.system should not be used. + + The Java class java.lang.ProcessBuilder can be used to create subprocesses without interference from the system shell. + Portability notice + On Windows, there is no argument vector, only a single argument string. Each application is responsible for parsing this string into an argument vector. There is considerable variance among the quoting style recognized by applications. Some of them expand shell wildcards, others do not. Extensive application-specific testing is required to make this secure. + + Note that some common applications (notably ssh) unconditionally introduce the use of a shell, even if invoked directly without a shell. It is difficult to use these applications in a secure manner. In this case, untrusted data should be supplied by other means. For example, standard input could be used, instead of the command line. + Specifying the process environment8.1.3. Specifying the process environment + Child processes should be created with a minimal set of environment variables. This is absolutely essential if there is a trust transition involved, either when the parent process was created, or during the creation of the child process. + + In C/C++, the environment should be constructed as an array of strings and passed as the envp argument to posix_spawn or execve. The functions setenv, unsetenv and putenv should not be used. They are not thread-safe and suffer from memory leaks. + + Python programs need to specify a dict for the the env argument of the subprocess.Popen constructor. The Java class java.lang.ProcessBuilder provides a environment() method, which returns a map that can be manipulated. + + The following list provides guidelines for selecting the set of environment variables passed to the child process. + + PATH should be initialized to /bin:/usr/bin. + + USER and HOME can be inhereted from the parent process environment, or they can be initialized from the pwent structure for the user. + + The DISPLAY and XAUTHORITY variables should be passed to the subprocess if it is an X program. Note that this will typically not work across trust boundaries because XAUTHORITY refers to a file with 0600 permissions. + + The location-related environment variables LANG, LANGUAGE, LC_ADDRESS, LC_ALL, LC_COLLATE, LC_CTYPE, LC_IDENTIFICATION, LC_MEASUREMENT, LC_MESSAGES, LC_MONETARY, LC_NAME, LC_NUMERIC, LC_PAPER, LC_TELEPHONE and LC_TIME can be passed to the subprocess if present. + + The called process may need application-specific environment variables, for example for passing passwords. (See Section 8.1.5, “Passing secrets to subprocesses”.) + + All other environment variables should be dropped. Names for new environment variables should not be accepted from untrusted sources. + Robust argument list processing8.1.4. Robust argument list processing + When invoking a program, it is sometimes necessary to include data from untrusted sources. Such data should be check against embedded NUL characters because the system APIs will sliently truncate argument strings at the first NUL character. + + The following recommendations assume that the program being invoked uses GNU-style option processing using getopt_long. This convention is widely used, but it is just that, and individual programs might interpret a command line in a different way. + + If the untrusted data has to go into an option, use the --option-name=VALUE syntax, placing the option and its value into the same command line argument. This avoids any potential confusion if the data starts with -. + + For positional arguments, terminate the option list with a single -- marker after the last option, and include the data at the right position. The -- marker terminates option processing, and the data will not be treated as an option even if it starts with a dash. + Passing secrets to subprocesses8.1.5. Passing secrets to subprocesses + The command line (the name of the program and its argument) of a running process is traditionally available to all local users. The called program can overwrite this information, but only after it has run for a bit of time, during which the information may have been read by other processes. However, on Linux, the process environment is restricted to the user who runs the process. Therefore, if you need a convenient way to pass a password to a child process, use an environment variable, and not a command line argument. (See Section 8.1.3, “Specifying the process environment”.) + Portability notice + On some UNIX-like systems (notably Solaris), environment variables can be read by any system user, just like command lines. + + If the environment-based approach cannot be used due to portability concerns, the data can be passed on standard input. Some programs (notably gpg) use special file descriptors whose numbers are specified on the command line. Temporary files are an option as well, but they might give digital forensics access to sensitive data (such as passphrases) because it is difficult to safely delete them in all cases. + Handling child process termination8.2. Handling child process termination + When child processes terminate, the parent process is signalled. A stub of the terminated processes (a zombie, shown as <defunct> by ps) is kept around until the status information is collected (reaped) by the parent process. Over the years, several interfaces for this have been invented: + + The parent process calls wait, waitpid, waitid, wait3 or wait4, without specifying a process ID. This will deliver any matching process ID. This approach is typically used from within event loops. + + The parent process calls waitpid, waitid, or wait4, with a specific process ID. Only data for the specific process ID is returned. This is typically used in code which spawns a single subprocess in a synchronous manner. + + The parent process installs a handler for the SIGCHLD signal, using sigaction, and specifies to the SA_NOCLDWAIT flag. This approach could be used by event loops as well. + + None of these approaches can be used to wait for child process terminated in a completely thread-safe manner. The parent process might execute an event loop in another thread, which could pick up the termination signal. This means that libraries typically cannot make free use of child processes (for example, to run problematic code with reduced privileges in a separate address space). + + At the moment, the parent process should explicitly wait for termination of the child process using waitpid or waitpid, and hope that the status is not collected by an event loop first. + SUID/SGID processes8.3. SUID/SGID processes + Programs can be marked in the file system to indicate to the kernel that a trust transition should happen if the program is run. The SUID file permission bit indicates that an executable should run with the effective user ID equal to the owner of the executable file. Similarly, with the SGID bit, the effective group ID is set to the group of the executable file. + + Linux supports fscaps, which can grant additional capabilities to a process in a finer-grained manner. Additional mechanisms can be provided by loadable security modules. + + When such a trust transition has happened, the process runs in a potentially hostile environment. Additional care is necessary not to rely on any untrusted information. These concerns also apply to libraries which can be linked into such processes. + Accessing environment variables8.3.1. Accessing environment variables + The following steps are required so that a program does not accidentally pick up untrusted data from environment variables. + + Compile your C/C++ sources with -D_GNU_SOURCE. The Autoconf macro AC_GNU_SOURCE ensures this. + + Check for the presence of the secure_getenv and __secure_getenv function. The Autoconf directive AC_CHECK_FUNCS([__secure_getenv secure_getenv]) performs these checks. + + Arrange for a proper definition of the secure_getenv function. See Example 8.1, “Obtaining a definition for secure_getenv. + + Use secure_getenv instead of getenv to obtain the value of critical environment variables. secure_getenv will pretend the variable has not bee set if the process environment is not trusted. + + Critical environment variables are debugging flags, configuration file locations, plug-in and log file locations, and anything else that might be used to bypass security restrictions or cause a privileged process to behave in an unexpected way. + + Either the secure_getenv function or the __secure_getenv is available from GNU libc. + Example 8.1. Obtaining a definition for secure_getenv + +#include <stdlib.h> + +#ifndef HAVE_SECURE_GETENV +# ifdef HAVE__SECURE_GETENV +# define secure_getenv __secure_getenv +# else +# error neither secure_getenv nor __secure_getenv are available +# endif +#endif + +Daemons8.4. Daemons + Background processes providing system services (daemons) need to decouple themselves from the controlling terminal and the parent process environment: + + Fork. + + In the child process, call setsid. The parent process can simply exit (using _exit, to avoid running clean-up actions twice). + + In the child process, fork again. Processing continues in the child process. Again, the parent process should just exit. + + Replace the descriptors 0, 1, 2 with a descriptor for /dev/null. Logging should be redirected to syslog. + + Older instructions for creating daemon processes recommended a call to umask(0). This is risky because it often leads to world-writable files and directories, resulting in security vulnerabilities such as arbitrary process termination by untrusted local users, or log file truncation. If the umask needs setting, a restrictive value such as 027 or 077 is recommended. + + Other aspects of the process environment may have to changed as well (environment variables, signal handler disposition). + + It is increasingly common that server processes do not run as background processes, but as regular foreground process under a supervising master process (such as systemd). Server processes should offer a command line option which disables forking and replacement of the standard output and standard error streams. Such an option is also useful for debugging. + Semantics of command line arguments8.5. Semantics of command line arguments + After process creation and option processing, it is up to the child process to interpret the arguments. Arguments can be file names, host names, or URLs, and many other things. URLs can refer to the local network, some server on the Internet, or to the local file system. Some applications even accept arbitrary code in arguments (for example, python with the -c option). + + Similar concerns apply to environment variables, the contents of the current directory and its subdirectories. + + Consequently, careful analysis is required if it is safe to pass untrusted data to another program. + fork as a primitive for parallelism8.6. fork as a primitive for parallelism + A call to fork which is not immediately followed by a call to execve (perhaps after rearranging and closing file descriptors) is typically unsafe, especially from a library which does not control the state of the entire process. Such use of fork should be replaced with proper child processes or threads. + Chapter 9.Chapter 9. Serialization and DeserializationSerialization and Deserialization + Protocol decoders and file format parsers are often the most-exposed part of an application because they are exposed with little or no user interaction and before any authentication and security checks are made. They are also difficult to write robustly in languages which are not memory-safe. + Recommendations for manually written decoders9.1. Recommendations for manually written decoders + For C and C++, the advice in Section 1.1.2, “Recommendations for pointers and array handling” applies. In addition, avoid non-character pointers directly into input buffers. Pointer misalignment causes crashes on some architectures. + + When reading variable-sized objects, do not allocate large amounts of data solely based on the value of a size field. If possible, grow the data structure as more data is read from the source, and stop when no data is available. This helps to avoid denial-of-service attacks where little amounts of input data results in enormous memory allocations during decoding. Alternatively, you can impose reasonable bounds on memory allocations, but some protocols do not permit this. + Protocol design9.2. Protocol design + Binary formats with explicit length fields are more difficult to parse robustly than those where the length of dynamically-sized elements is derived from sentinel values. A protocol which does not use length fields and can be written in printable ASCII characters simplifies testing and debugging. However, binary protocols with length fields may be more efficient to parse. + Library support for deserialization9.3. Library support for deserialization + For some languages, generic libraries are available which allow to serialize and deserialize user-defined objects. The deserialization part comes in one of two flavors, depending on the library. The first kind uses type information in the data stream to control which objects are instantiated. The second kind uses type definitions supplied by the programmer. The first one allows arbitrary object instantiation, the second one generally does not. + + The following serialization frameworks are in the first category, are known to be unsafe, and must not be used for untrusted data: + + Python's pickle and cPickle modules + + Perl's Storable package + + Java serialization (java.io.ObjectInputStream) + + PHP serialization (unserialize) + + Most implementations of YAML + + When using a type-directed deserialization format where the types of the deserialized objects are specified by the programmer, make sure that the objects which can be instantiated cannot perform any destructive actions in their destructors, even when the data members have been manipulated. + + JSON decoders do not suffer from this problem. But you must not use the eval function to parse JSON objects in Javascript; even with the regular expression filter from RFC 4627, there are still information leaks remaining. + XML serialization9.4. XML serialization + + External references9.4.1. External references + XML documents can contain external references. They can occur in various places. + + In the DTD declaration in the header of an XML document: + +<!DOCTYPE html PUBLIC + "-//W3C//DTD XHTML 1.0 Transitional//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> + + In a namespace declaration: + +<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"> + + In an entity defintion: + +<!ENTITY sys SYSTEM "http://www.example.com/ent.xml"> +<!ENTITY pub PUBLIC "-//Example//Public Entity//EN" + "http://www.example.com/pub-ent.xml"> + + In a notation: + +<!NOTATION not SYSTEM "../not.xml"> + + Originally, these external references were intended as unique identifiers, but by many XML implementations, they are used for locating the data for the referenced element. This causes unwanted network traffic, and may disclose file system contents or otherwise unreachable network resources, so this functionality should be disabled. + + Depending on the XML library, external referenced might be processed not just when parsing XML, but also when generating it. + Entity expansion9.4.2. Entity expansion + When external DTD processing is disabled, an internal DTD subset can still contain entity definitions. Entity declarations can reference other entities. Some XML libraries expand entities automatically, and this processing cannot be switched off in some places (such as attribute values or content models). Without limits on the entity nesting level, this expansion results in data which can grow exponentially in length with size of the input. (If there is a limit on the nesting level, the growth is still polynomial, unless further limits are imposed.) + + Consequently, the processing internal DTD subsets should be disabled if possible, and only trusted DTDs should be processed. If a particular XML application does not permit such restrictions, then application-specific limits are called for. + XInclude processing9.4.3. XInclude processing + XInclude processing can reference file and network resources and include them into the document, much like external entity references. When parsing untrusted XML documents, XInclude processing should be truned off. + + XInclude processing is also fairly complex and may pull in support for the XPointer and XPath specifications, considerably increasing the amount of code required for XML processing. + Algorithmic complexity of XML validation9.4.4. Algorithmic complexity of XML validation + DTD-based XML validation uses regular expressions for content models. The XML specification requires that content models are deterministic, which means that efficient validation is possible. However, some implementations do not enforce determinism, and require exponential (or just polynomial) amount of space or time for validating some DTD/document combinations. + + XML schemas and RELAX NG (via the xsd: prefix) directly support textual regular expressions which are not required to be deterministic. + Using Expat for XML parsing9.4.5. Using Expat for XML parsing + By default, Expat does not try to resolve external IDs, so no steps are required to block them. However, internal entity declarations are processed. Installing a callback which stops parsing as soon as such entities are encountered disables them, see Example 9.1, “Disabling XML entity processing with Expat”. Expat does not perform any validation, so there are no problems related to that. + Example 9.1. Disabling XML entity processing with Expat +// Stop the parser when an entity declaration is encountered. +static void +EntityDeclHandler(void *userData, + const XML_Char *entityName, int is_parameter_entity, + const XML_Char *value, int value_length, + const XML_Char *base, const XML_Char *systemId, + const XML_Char *publicId, const XML_Char *notationName) +{ + XML_StopParser((XML_Parser)userData, XML_FALSE); +} + + This handler must be installed when the XML_Parser object is created (Example 9.2, “Creating an Expat XML parser”). + Example 9.2. Creating an Expat XML parser +XML_Parser parser = XML_ParserCreate("UTF-8"); +if (parser == NULL) { + fprintf(stderr, "XML_ParserCreate failed\n"); + close(fd); + exit(1); +} +// EntityDeclHandler needs a reference to the parser to stop +// parsing. +XML_SetUserData(parser, parser); +// Disable entity processing, to inhibit entity expansion. +XML_SetEntityDeclHandler(parser, EntityDeclHandler); + + It is also possible to reject internal DTD subsets altogeher, using a suitable XML_StartDoctypeDeclHandler handler installed with XML_SetDoctypeDeclHandler. + Using OpenJDK for XML parsing and validation9.4.6. Using OpenJDK for XML parsing and validation + OpenJDK contains facilities for DOM-based, SAX-based, and StAX-based document parsing. Documents can be validated against DTDs or XML schemas. + + The approach taken to deal with entity expansion differs from the general recommendation in Section 9.4.2, “Entity expansion”. We enable the the feature flag javax.xml.XMLConstants.FEATURE_SECURE_PROCESSING, which enforces heuristic restrictions on the number of entity expansions. Note that this flag alone does not prevent resolution of external references (system IDs or public IDs), so it is slightly misnamed. + + In the following sections, we use helper classes to prevent external ID resolution. + Example 9.3. Helper class to prevent DTD external entity resolution in OpenJDK +class NoEntityResolver implements EntityResolver { + @Override + public InputSource resolveEntity(String publicId, String systemId) + throws SAXException, IOException { + // Throwing an exception stops validation. + throw new IOException(String.format( + "attempt to resolve \"%s\" \"%s\"", publicId, systemId)); + } +} +Example 9.4. Helper class to prevent schema resolution in OpenJDK +class NoResourceResolver implements LSResourceResolver { + @Override + public LSInput resolveResource(String type, String namespaceURI, + String publicId, String systemId, String baseURI) { + // Throwing an exception stops validation. + throw new RuntimeException(String.format( + "resolution attempt: type=%s namespace=%s " + + "publicId=%s systemId=%s baseURI=%s", + type, namespaceURI, publicId, systemId, baseURI)); + } +} + + Example 9.5, “Java imports for OpenJDK XML parsing” shows the imports used by the examples. + Example 9.5. Java imports for OpenJDK XML parsing +import javax.xml.XMLConstants; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.sax.SAXSource; +import javax.xml.validation.Schema; +import javax.xml.validation.SchemaFactory; +import javax.xml.validation.Validator; + +import org.w3c.dom.Document; +import org.w3c.dom.ls.LSInput; +import org.w3c.dom.ls.LSResourceResolver; +import org.xml.sax.EntityResolver; +import org.xml.sax.ErrorHandler; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.SAXParseException; +import org.xml.sax.XMLReader; +9.4.6.1. DOM-based XML parsing and DTD validation in OpenJDK + This approach produces a org.w3c.dom.Document object from an input stream. Example 9.6, “DOM-based XML parsing in OpenJDK” use the data from the java.io.InputStream instance in the inputStream variable. + Example 9.6. DOM-based XML parsing in OpenJDK +DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); +// Impose restrictions on the complexity of the DTD. +factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); + +// Turn on validation. +// This step can be omitted if validation is not desired. +factory.setValidating(true); + +// Parse the document. +DocumentBuilder builder = factory.newDocumentBuilder(); +builder.setEntityResolver(new NoEntityResolver()); +builder.setErrorHandler(new Errors()); +Document document = builder.parse(inputStream); + + External entity references are prohibited using the NoEntityResolver class in Example 9.3, “Helper class to prevent DTD external entity resolution in OpenJDK”. Because external DTD references are prohibited, DTD validation (if enabled) will only happen against the internal DTD subset embedded in the XML document. + + To validate the document against an external DTD, use a javax.xml.transform.Transformer class to add the DTD reference to the document, and an entity resolver which whitelists this external reference. + 9.4.6.2. XML Schema validation in OpenJDK + Example 9.7, “SAX-based validation against an XML schema in OpenJDK” shows how to validate a document against an XML Schema, using a SAX-based approach. The XML data is read from an java.io.InputStream in the inputStream variable. + Example 9.7. SAX-based validation against an XML schema in OpenJDK +SchemaFactory factory = SchemaFactory.newInstance( + XMLConstants.W3C_XML_SCHEMA_NS_URI); + +// This enables restrictions on the schema and document +// complexity. +factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); + +// This prevents resource resolution by the schema itself. +// If the schema is trusted and references additional files, +// this line must be omitted, otherwise loading these files +// will fail. +factory.setResourceResolver(new NoResourceResolver()); + +Schema schema = factory.newSchema(schemaFile); +Validator validator = schema.newValidator(); + +// This prevents external resource resolution. +validator.setResourceResolver(new NoResourceResolver()); + +validator.validate(new SAXSource(new InputSource(inputStream))); + + The NoResourceResolver class is defined in Example 9.4, “Helper class to prevent schema resolution in OpenJDK”. + + If you need to validate a document against an XML schema, use the code in Example 9.6, “DOM-based XML parsing in OpenJDK” to create the document, but do not enable validation at this point. Then use Example 9.8, “Validation of a DOM document against an XML schema in OpenJDK” to perform the schema-based validation on the org.w3c.dom.Document instance document. + Example 9.8. Validation of a DOM document against an XML schema in OpenJDK +SchemaFactory factory = SchemaFactory.newInstance( + XMLConstants.W3C_XML_SCHEMA_NS_URI); + +// This enables restrictions on schema complexity. +factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); + +// The following line prevents resource resolution +// by the schema itself. +factory.setResourceResolver(new NoResourceResolver()); + +Schema schema = factory.newSchema(schemaFile); + +Validator validator = schema.newValidator(); + +// This prevents external resource resolution. +validator.setResourceResolver(new NoResourceResolver()); +validator.validate(new DOMSource(document)); +Protocol Encoders9.5. Protocol Encoders + For protocol encoders, you should write bytes to a buffer which grows as needed, using an exponential sizing policy. Explicit lengths can be patched in later, once they are known. Allocating the required number of bytes upfront typically requires separate code to compute the final size, which must be kept in sync with the actual encoding step, or vulnerabilities may result. In multi-threaded code, parts of the object being deserialized might change, so that the computed size is out of date. + + You should avoid copying data directly from a received packet during encoding, disregarding the format. Propagating malformed data could enable attacks on other recipients of that data. + + When using C or C++ and copying whole data structures directly into the output, make sure that you do not leak information in padding bytes between fields or at the end of the struct. + Chapter 10.Chapter 10. CryptographyCryptographyPrimitives10.1. Primitives + Chosing from the following cryptographic primitives is recommended: + + RSA with 2048 bit keys and OAEP + + AES-128 in CBC mode + + SHA-256 + + HMAC-SHA-256 + + HMAC-SHA-1 + + Other cryptographic algorithms can be used if they are required for interoperability with existing software: + + RSA with key sizes larger than 1024 and legacy padding + + AES-192 + + AES-256 + + 3DES (triple DES, with two or three 56 bit keys) + + RC4 (but very, very strongly discouraged) + + SHA-1 + + HMAC-MD5 + Important + These primitives are difficult to use in a secure way. Custom implementation of security protocols should be avoided. For protecting confidentiality and integrity of network transmissions, TLS should be used (Chapter 12, Transport Layer Security). + Randomness10.2. Randomness + The following facilities can be used to generate unpredictable and non-repeating values. When these functions are used without special safeguards, each individual rnadom value should be at least 12 bytes long. + + PK11_GenerateRandom in the NSS library (usable for high data rates) + + RAND_bytes in the OpenSSL library (usable for high data rates) + + gnutls_rnd in GNUTLS, with GNUTLS_RND_RANDOM as the first argument (usable for high data rates) + + java.security.SecureRandom in Java (usable for high data rates) + + os.urandom in Python + + Reading from the /dev/urandom character device + + All these functions should be non-blocking, and they should not wait until physical randomness becomes available. (Some cryptography providers for Java can cause java.security.SecureRandom to block, however.) Those functions which do not obtain all bits directly from /dev/urandom are suitable for high data rates because they do not deplete the system-wide entropy pool. + Difficult to use API + Both RAND_bytes and PK11_GenerateRandom have three-state return values (with conflicting meanings). Careful error checking is required. Please review the documentation when using these functions. + + Other sources of randomness should be considered predictable. + + Generating randomness for cryptographic keys in long-term use may need different steps and is best left to cryptographic libraries. + Part III. Implementing Security FeaturesPart III. Implementing Security FeaturesChapter 11.Chapter 11. Authentication and AuthorizationAuthentication and AuthorizationAuthenticating servers11.1. Authenticating servers + When connecting to a server, a client has to make sure that it is actually talking to the server it expects. There are two different aspects, securing the network path, and making sure that the expected user runs the process on the target host. There are several ways to ensure that: + + The server uses a TLS certificate which is valid according to the web browser public key infrastructure, and the client verifies the certificate and the host name. + + The server uses a TLS certificate which is expectedby the client (perhaps it is stored in a configuration file read by the client). In this case, no host name checking is required. + + On Linux, UNIX domain sockets (of the PF_UNIX protocol family, sometimes called PF_LOCAL) are restricted by file system permissions. If the server socket path is not world-writable, the server identity cannot be spoofed by local users. + + Port numbers less than 1024 (trusted ports) can only be used by root, so if a UDP or TCP server is running on the local host and it uses a trusted port, its identity is assured. (Not all operating systems enforce the trusted ports concept, and the network might not be trusted, so it is only useful on the local system.) + + TLS (Chapter 12, Transport Layer Security) is the recommended way for securing connections over untrusted networks. + + If the server port number is 1024 is higher, a local user can impersonate the process by binding to this socket, perhaps after crashing the real server by exploiting a denial-of-service vulnerability. + Host-based authentication11.2. Host-based authentication + Host-based authentication uses access control lists (ACLs) to accept or deny requests from clients. Thsis authentication method comes in two flavors: IP-based (or, more generally, address-based) and name-based (with the name coming from DNS or /etc/hosts). IP-based ACLs often use prefix notation to extend access to entire subnets. Name-based ACLs sometimes use wildcards for adding groups of hosts (from entire DNS subtrees). (In the SSH context, host-based authentication means something completely different and is not covered in this section.) + + Host-based authentication trust the network and may not offer sufficient granularity, so it has to be considered a weak form of authentication. On the other hand, IP-based authentication can be made extremely robust and can be applied very early in input processing, so it offers an opportunity for significantly reducing the number of potential attackers for many services. + + The names returned by gethostbyaddr and getnameinfo functions cannot be trusted. (DNS PTR records can be set to arbitrary values, not just names belong to the address owner.) If these names are used for ACL matching, a forward lookup using gethostbyaddr or getaddrinfo has to be performed. The name is only valid if the original address is found among the results of the forward lookup (double-reverse lookup). + + An empty ACL should deny all access (deny-by-default). If empty ACLs permits all access, configuring any access list must switch to deny-by-default for all unconfigured protocols, in both name-based and address-based variants. + + Similarly, if an address or name is not matched by the list, it should be denied. However, many implementations behave differently, so the actual behavior must be documented properly. + + IPv6 addresses can embed IPv4 addresses. There is no universally correct way to deal with this ambiguity. The behavior of the ACL implementation should be documented. + UNIX domain socket authentication11.3. UNIX domain socket authentication + UNIX domain sockets (with address family AF_UNIX or AF_LOCAL) are restricted to the local host and offer a special authentication mechanism: credentials passing. + + Nowadays, most systems support the SO_PEERCRED (Linux) or LOCAL_PEERCRED (FreeBSD) socket options, or the getpeereid (other BSDs, MacOS X). These interfaces provide direct access to the (effective) user ID on the other end of a domain socket connect, without cooperation from the other end. + + Historically, credentials passing was implemented using ancillary data in the sendmsg and recvmsg functions. On some systems, only credentials data that the peer has explicitly sent can be received, and the kernel checks the data for correctness on the sending side. This means that both peers need to deal with ancillary data. Compared to that, the modern interfaces are easier to use. Both sets of interfaces vary considerably among UNIX-like systems, unfortunately. + + If you want to authenticate based on supplementary groups, you should obtain the user ID using one of these methods, and look up the list of supplementary groups using getpwuid (or getpwuid_r) and getgrouplist. Using the PID and information from /proc/PID/status is prone to race conditions and insecure. + AF_NETLINK authentication of origin11.4. AF_NETLINK authentication of origin + Netlink messages are used as a high-performance data transfer mechanism between the kernel and the userspace. Traditionally, they are used to exchange information related to the network statck, such as routing table entries. + + When processing Netlink messages from the kernel, it is important to check that these messages actually originate from the kernel, by checking that the port ID (or PID) field nl_pid in the sockaddr_nl structure is 0. (This structure can be obtained using recvfrom or recvmsg, it is different from the nlmsghdr structure.) The kernel does not prevent other processes from sending unicast Netlink messages, but the nl_pid field in the sender's socket address will be non-zero in such cases. + + Applications should not use AF_NETLINK sockets as an IPC mechanism among processes, but prefer UNIX domain sockets for this tasks. + Chapter 12.Chapter 12. Transport Layer SecurityTransport Layer Security + Transport Layer Security (TLS, formerly Secure Sockets Layer/SSL) is the recommended way to to protect integrity and confidentiality while data is transferred over an untrusted network connection, and to identify the endpoint. + Common Pitfalls12.1. Common Pitfalls + TLS implementations are difficult to use, and most of them lack a clean API design. The following sections contain implementation-specific advice, and some generic pitfalls are mentioned below. + + Most TLS implementations have questionable default TLS cipher suites. Most of them enable anonymous Diffie-Hellman key exchange (but we generally want servers to authenticate themselves). Many do not disable ciphers which are subject to brute-force attacks because of restricted key lengths. Some even disable all variants of AES in the default configuration. + + When overriding the cipher suite defaults, it is recommended to disable all cipher suites which are not present on a whitelist, instead of simply enabling a list of cipher suites. This way, if an algorithm is disabled by default in the TLS implementation in a future security update, the application will not re-enable it. + + The name which is used in certificate validation must match the name provided by the user or configuration file. No host name canonicalization or IP address lookup must be performed. + + The TLS handshake has very poor performance if the TCP Nagle algorithm is active. You should switch on the TCP_NODELAY socket option (at least for the duration of the handshake), or use the Linux-specific TCP_CORK option. + Example 12.1. Deactivating the TCP Nagle algorithm +const int val = 1; +int ret = setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val)); +if (ret < 0) { + perror("setsockopt(TCP_NODELAY)"); + exit(1); +} + + Implementing proper session resumption decreases handshake overhead considerably. This is important if the upper-layer protocol uses short-lived connections (like most application of HTTPS). + + Both client and server should work towards an orderly connection shutdown, that is send close_notify alerts and respond to them. This is especially important if the upper-layer protocol does not provide means to detect connection truncation (like some uses of HTTP). + + When implementing a server using event-driven programming, it is important to handle the TLS handshake properly because it includes multiple network round-trips which can block when an ordinary TCP accept would not. Otherwise, a client which fails to complete the TLS handshake for some reason will prevent the server from handling input from other clients. + + Unlike regular file descriptors, TLS connections cannot be passed between processes. Some TLS implementations add additional restrictions, and TLS connections generally cannot be used across fork function calls (see Section 8.6, “fork as a primitive for parallelism”). + OpenSSL Pitfalls12.1.1. OpenSSL Pitfalls + Some OpenSSL function use tri-state return values. Correct error checking is extremely important. Several functions return int values with the following meaning: + + The value 1 indicates success (for example, a successful signature verification). + + The value 0 indicates semantic failure (for example, a signature verification which was unsuccessful because the signing certificate was self-signed). + + The value -1 indicates a low-level error in the system, such as failure to allocate memory using malloc. + + Treating such tri-state return values as booleans can lead to security vulnerabilities. Note that some OpenSSL functions return boolean results or yet another set of status indicators. Each function needs to be checked individually. + + Recovering precise error information is difficult. Example 12.2, “Obtaining OpenSSL error codes” shows how to obtain a more precise error code after a function call on an SSL object has failed. However, there are still cases where no detailed error information is available (e.g., if SSL_shutdown fails due to a connection teardown by the other end). + Example 12.2. Obtaining OpenSSL error codes +static void __attribute__((noreturn)) +ssl_print_error_and_exit(SSL *ssl, const char *op, int ret) +{ + int subcode = SSL_get_error(ssl, ret); + switch (subcode) { + case SSL_ERROR_NONE: + fprintf(stderr, "error: %s: no error to report\n", op); + break; + case SSL_ERROR_WANT_READ: + case SSL_ERROR_WANT_WRITE: + case SSL_ERROR_WANT_X509_LOOKUP: + case SSL_ERROR_WANT_CONNECT: + case SSL_ERROR_WANT_ACCEPT: + fprintf(stderr, "error: %s: invalid blocking state %d\n", op, subcode); + break; + case SSL_ERROR_SSL: + fprintf(stderr, "error: %s: TLS layer problem\n", op); + case SSL_ERROR_SYSCALL: + fprintf(stderr, "error: %s: system call failed: %s\n", op, strerror(errno)); + break; + case SSL_ERROR_ZERO_RETURN: + fprintf(stderr, "error: %s: zero return\n", op); + } + exit(1); +} + + The OPENSSL_config function is documented to never fail. In reality, it can terminate the entire process if there is a failure accessing the configuration file. An error message is written to standard error, but which might not be visible if the function is called from a daemon process. + + OpenSSL contains two separate ASN.1 DER decoders. One set of decoders operate on BIO handles (the input/output stream abstraction provided by OpenSSL); their decoder function names start with d2i_ and end in _fp or _bio (e.g., d2i_X509_fp or d2i_X509_bio). These decoders must not be used for parsing data from untrusted sources; instead, the variants without the _fp and _bio (e.g., d2i_X509) shall be used. The BIO variants have received considerably less testing and are not very robust. + + For the same reason, the OpenSSL command line tools (such as openssl x509) are generally generally less robust than the actual library code. They use the BIO functions internally, and not the more robust variants. + + The command line tools do not always indicate failure in the exit status of the openssl process. For instance, a verification failure in openssl verify result in an exit status of zero. + + The OpenSSL server and client applications (openssl s_client and openssl s_server) are debugging tools and should never be used as generic clients. For instance, the s_client tool reacts in a surprisign way to lines starting with R and Q. + + OpenSSL allows application code to access private key material over documented interfaces. This can significantly increase the part of the code base which has to undergo security certification. + GNUTLS Pitfalls12.1.2. GNUTLS Pitfalls + libgnutls.so.26 links to libpthread.so.0. Loading the threading library too late causes problems, so the main program should be linked with -lpthread as well. As a result, it can be difficult to use GNUTLS in a plugin which is loaded with the dlopen function. Another side effect is that applications which merely link against GNUTLS (even without actually using it) may incur a substantial overhead because other libraries automatically switch to thread-safe algorithms. + + The gnutls_global_init function must be called before using any functionality provided by the library. This function is not thread-safe, so external locking is required, but it is not clear which lock should be used. Omitting the synchronization does not just lead to a memory leak, as it is suggested in the GNUTLS documentation, but to undefined behavior because there is no barrier that would enforce memory ordering. + + The gnutls_global_deinit function does not actually deallocate all resources allocated by gnutls_global_init. It is currently not thread-safe. Therefore, it is best to avoid calling it altogether. + + The X.509 implementation in GNUTLS is rather lenient. For example, it is possible to create and process X.509 version 1 certificates which carry extensions. These certificates are (correctly) rejected by other implementations. + OpenJDK Pitfalls12.1.3. OpenJDK Pitfalls + The Java cryptographic framework is highly modular. As a result, when you request an object implementing some cryptographic functionality, you cannot be completely sure that you end up with the well-tested, reviewed implementation in OpenJDK. + + OpenJDK (in the source code as published by Oracle) and other implementations of the Java platform require that the system administrator has installed so-called unlimited strength jurisdiction policy files. Without this step, it is not possible to use the secure algorithms which offer sufficient cryptographic strength. Most downstream redistributors of OpenJDK remove this requirement. + + Some versions of OpenJDK use /dev/random as the randomness source for nonces and other random data which is needed for TLS operation, but does not actually require physical randomness. As a result, TLS applications can block, waiting for more bits to become available in /dev/random. + NSS Pitfalls12.1.4. NSS Pitfalls + NSS was not designed to be used by other libraries which can be linked into applications without modifying them. There is a lot of global state. There does not seem to be a way to perform required NSS initialization without race conditions. + + If the NSPR descriptor is in an unexpected state, the SSL_ForceHandshake function can succeed, but no TLS handshake takes place, the peer is not authenticated, and subsequent data is exchanged in the clear. + + NSS disables itself if it detects that the process underwent a fork after the library has been initialized. This behavior is required by the PKCS#11 API specification. + TLS Clients12.2. TLS Clients + Secure use of TLS in a client generally involves all of the following steps. (Individual instructions for specific TLS implementations follow in the next sections.) + + The client must configure the TLS library to use a set of trusted root certificates. These certificates are provided by the system in /etc/ssl/certs or files derived from it. + + The client selects sufficiently strong cryptographic primitives and disables insecure ones (such as no-op encryption). Compression and SSL version 2 support must be disabled (including the SSLv2-compatible handshake). + + The client initiates the TLS connection. The Server Name Indication extension should be used if supported by the TLS implementation. Before switching to the encrypted connection state, the contents of all input and output buffers must be discarded. + + The client needs to validate the peer certificate provided by the server, that is, the client must check that there is a cryptographically protected chain from a trusted root certificate to the peer certificate. (Depending on the TLS implementation, a TLS handshake can succeed even if the certificate cannot be validated.) + + The client must check that the configured or user-provided server name matches the peer certificate provided by the server. + + It is safe to provide users detailed diagnostics on certificate validation failures. Other causes of handshake failures and, generally speaking, any details on other errors reported by the TLS implementation (particularly exception tracebacks), must not be divulged in ways that make them accessible to potential attackers. Otherwise, it is possible to create decryption oracles. + Important + Depending on the application, revocation checking (against certificate revocations lists or via OCSP) and session resumption are important aspects of production-quality client. These aspects are not yet covered. + Implementation TLS Clients With OpenSSL12.2.1. Implementation TLS Clients With OpenSSL + In the following code, the error handling is only exploratory. Proper error handling is required for production use, especially in libraries. + + The OpenSSL library needs explicit initialization (see Example 12.3, “OpenSSL library initialization”). + Example 12.3. OpenSSL library initialization +// The following call prints an error message and calls exit() if +// the OpenSSL configuration file is unreadable. +OPENSSL_config(NULL); +// Provide human-readable error messages. +SSL_load_error_strings(); +// Register ciphers. +SSL_library_init(); + + After that, a context object has to be created, which acts as a factory for connection objects (Example 12.4, “OpenSSL client context creation”). We use an explicit cipher list so that we do not pick up any strange ciphers when OpenSSL is upgraded. The actual version requested in the client hello depends on additional restrictions in the OpenSSL library. If possible, you should follow the example code and use the default list of trusted root certificate authorities provided by the system because you would have to maintain your own set otherwise, which can be cumbersome. + Example 12.4. OpenSSL client context creation +// Configure a client connection context. Send a hendshake for the +// highest supported TLS version, and disable compression. +const SSL_METHOD *const req_method = SSLv23_client_method(); +SSL_CTX *const ctx = SSL_CTX_new(req_method); +if (ctx == NULL) { + ERR_print_errors(bio_err); + exit(1); +} +SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_COMPRESSION); + +// Adjust the ciphers list based on a whitelist. First enable all +// ciphers of at least medium strength, to get the list which is +// compiled into OpenSSL. +if (SSL_CTX_set_cipher_list(ctx, "HIGH:MEDIUM") != 1) { + ERR_print_errors(bio_err); + exit(1); +} +{ + // Create a dummy SSL session to obtain the cipher list. + SSL *ssl = SSL_new(ctx); + if (ssl == NULL) { + ERR_print_errors(bio_err); + exit(1); + } + STACK_OF(SSL_CIPHER) *active_ciphers = SSL_get_ciphers(ssl); + if (active_ciphers == NULL) { + ERR_print_errors(bio_err); + exit(1); + } + // Whitelist of candidate ciphers. + static const char *const candidates[] = { + "AES128-GCM-SHA256", "AES128-SHA256", "AES256-SHA256", // strong ciphers + "AES128-SHA", "AES256-SHA", // strong ciphers, also in older versions + "RC4-SHA", "RC4-MD5", // backwards compatibility, supposed to be weak + "DES-CBC3-SHA", "DES-CBC3-MD5", // more backwards compatibility + NULL + }; + // Actually selected ciphers. + char ciphers[300]; + ciphers[0] = '\0'; + for (const char *const *c = candidates; *c; ++c) { + for (int i = 0; i < sk_SSL_CIPHER_num(active_ciphers); ++i) { + if (strcmp(SSL_CIPHER_get_name(sk_SSL_CIPHER_value(active_ciphers, i)), + *c) == 0) { + if (*ciphers) { + strcat(ciphers, ":"); + } + strcat(ciphers, *c); + break; + } + } + } + SSL_free(ssl); + // Apply final cipher list. + if (SSL_CTX_set_cipher_list(ctx, ciphers) != 1) { + ERR_print_errors(bio_err); + exit(1); + } +} + +// Load the set of trusted root certificates. +if (!SSL_CTX_set_default_verify_paths(ctx)) { + ERR_print_errors(bio_err); + exit(1); +} + + A single context object can be used to create multiple connection objects. It is safe to use the same SSL_CTX object for creating connections concurrently from multiple threads, provided that the SSL_CTX object is not modified (e.g., callbacks must not be changed). + + After creating the TCP socket and disabling the Nagle algorithm (per Example 12.1, “Deactivating the TCP Nagle algorithm”), the actual connection object needs to be created, as show in Example 12.4, “OpenSSL client context creation”. If the handshake started by SSL_connect fails, the ssl_print_error_and_exit function from Example 12.2, “Obtaining OpenSSL error codes” is called. + + The certificate_validity_override function provides an opportunity to override the validity of the certificate in case the OpenSSL check fails. If such functionality is not required, the call can be removed, otherwise, the application developer has to implement it. + + The host name passed to the functions SSL_set_tlsext_host_name and X509_check_host must be the name that was passed to getaddrinfo or a similar name resolution function. No host name canonicalization must be performed. The X509_check_host function used in the final step for host name matching is currently only implemented in OpenSSL 1.1, which is not released yet. In case host name matching fails, the function certificate_host_name_override is called. This function should check user-specific certificate store, to allow a connection even if the host name does not match the certificate. This function has to be provided by the application developer. Note that the override must be keyed by both the certificate and the host name. + Example 12.5. Creating a client connection using OpenSSL +// Create the connection object. +SSL *ssl = SSL_new(ctx); +if (ssl == NULL) { + ERR_print_errors(bio_err); + exit(1); +} +SSL_set_fd(ssl, sockfd); + +// Enable the ServerNameIndication extension +if (!SSL_set_tlsext_host_name(ssl, host)) { + ERR_print_errors(bio_err); + exit(1); +} + +// Perform the TLS handshake with the server. +ret = SSL_connect(ssl); +if (ret != 1) { + // Error status can be 0 or negative. + ssl_print_error_and_exit(ssl, "SSL_connect", ret); +} + +// Obtain the server certificate. +X509 *peercert = SSL_get_peer_certificate(ssl); +if (peercert == NULL) { + fprintf(stderr, "peer certificate missing"); + exit(1); +} + +// Check the certificate verification result. Allow an explicit +// certificate validation override in case verification fails. +int verifystatus = SSL_get_verify_result(ssl); +if (verifystatus != X509_V_OK && !certificate_validity_override(peercert)) { + fprintf(stderr, "SSL_connect: verify result: %s\n", + X509_verify_cert_error_string(verifystatus)); + exit(1); +} + +// Check if the server certificate matches the host name used to +// establish the connection. +// FIXME: Currently needs OpenSSL 1.1. +if (X509_check_host(peercert, (const unsigned char *)host, strlen(host), + 0) != 1 + && !certificate_host_name_override(peercert, host)) { + fprintf(stderr, "SSL certificate does not match host name\n"); + exit(1); +} + +X509_free(peercert); + + + The connection object can be used for sending and receiving data, as in Example 12.6, “Using an OpenSSL connection to send and receive data”. It is also possible to create a BIO object and use the SSL object as the underlying transport, using BIO_set_ssl. + Example 12.6. Using an OpenSSL connection to send and receive data +const char *const req = "GET / HTTP/1.0\r\n\r\n"; +if (SSL_write(ssl, req, strlen(req)) < 0) { + ssl_print_error_and_exit(ssl, "SSL_write", ret); +} +char buf[4096]; +ret = SSL_read(ssl, buf, sizeof(buf)); +if (ret < 0) { + ssl_print_error_and_exit(ssl, "SSL_read", ret); +} + + When it is time to close the connection, the SSL_shutdown function needs to be called twice for an orderly, synchronous connection termination (Example 12.7, “Closing an OpenSSL connection in an orderly fashion”). This exchanges close_notify alerts with the server. The additional logic is required to deal with an unexpected close_notify from the server. Note that is necessary to explicitly close the underlying socket after the connection object has been freed. + Example 12.7. Closing an OpenSSL connection in an orderly fashion +// Send the close_notify alert. +ret = SSL_shutdown(ssl); +switch (ret) { +case 1: + // A close_notify alert has already been received. + break; +case 0: + // Wait for the close_notify alert from the peer. + ret = SSL_shutdown(ssl); + switch (ret) { + case 0: + fprintf(stderr, "info: second SSL_shutdown returned zero\n"); + break; + case 1: + break; + default: + ssl_print_error_and_exit(ssl, "SSL_shutdown 2", ret); + } + break; +default: + ssl_print_error_and_exit(ssl, "SSL_shutdown 1", ret); +} +SSL_free(ssl); +close(sockfd); + + Example 12.8, “Closing an OpenSSL connection in an orderly fashion” shows how to deallocate the context object when it is no longer needed because no further TLS connections will be established. + Example 12.8. Closing an OpenSSL connection in an orderly fashion +SSL_CTX_free(ctx); +Implementation TLS Clients With GNUTLS12.2.2. Implementation TLS Clients With GNUTLS + This section describes how to implement a TLS client with full certificate validation (but without certificate revocation checking). Note that the error handling in is only exploratory and needs to be replaced before production use. + + The GNUTLS library needs explicit initialization: + +gnutls_global_init(); + + Failing to do so can result in obscure failures in Base64 decoding. See Section 12.1.2, “GNUTLS Pitfalls” for additional aspects of initialization. + + Before setting up TLS connections, a credentials objects has to be allocated and initialized with the set of trusted root CAs (Example 12.9, “Initializing a GNUTLS credentials structure”). + Example 12.9. Initializing a GNUTLS credentials structure +// Load the trusted CA certificates. +gnutls_certificate_credentials_t cred = NULL; +int ret = gnutls_certificate_allocate_credentials (&cred); +if (ret != GNUTLS_E_SUCCESS) { + fprintf(stderr, "error: gnutls_certificate_allocate_credentials: %s\n", + gnutls_strerror(ret)); + exit(1); +} +// gnutls_certificate_set_x509_system_trust needs GNUTLS version 3.0 +// or newer, so we hard-code the path to the certificate store +// instead. +static const char ca_bundle[] = "/etc/ssl/certs/ca-bundle.crt"; +ret = gnutls_certificate_set_x509_trust_file + (cred, ca_bundle, GNUTLS_X509_FMT_PEM); +if (ret == 0) { + fprintf(stderr, "error: no certificates found in: %s\n", ca_bundle); + exit(1); +} +if (ret < 0) { + fprintf(stderr, "error: gnutls_certificate_set_x509_trust_files(%s): %s\n", + ca_bundle, gnutls_strerror(ret)); + exit(1); +} + + After the last TLS connection has been closed, this credentials object should be freed: + +gnutls_certificate_free_credentials(cred); + + During its lifetime, the credentials object can be used to initialize TLS session objects from multiple threads, provided that it is not changed. + + Once the TCP connection has been established, the Nagle algorithm should be disabled (see Example 12.1, “Deactivating the TCP Nagle algorithm”). After that, the socket can be associated with a new GNUTLS session object. The previously allocated credentials object provides the set of root CAs. The NORMAL set of cipher suites and protocols provides a reasonable default. Then the TLS handshake must be initiated. This is shown in Example 12.10, “Establishing a TLS client connection using GNUTLS”. + Example 12.10. Establishing a TLS client connection using GNUTLS +// Create the session object. +gnutls_session_t session; +ret = gnutls_init(&session, GNUTLS_CLIENT); +if (ret != GNUTLS_E_SUCCESS) { + fprintf(stderr, "error: gnutls_init: %s\n", + gnutls_strerror(ret)); + exit(1); +} + +// Configure the cipher preferences. +const char *errptr = NULL; +ret = gnutls_priority_set_direct(session, "NORMAL", &errptr); +if (ret != GNUTLS_E_SUCCESS) { + fprintf(stderr, "error: gnutls_priority_set_direct: %s\n" + "error: at: \"%s\"\n", gnutls_strerror(ret), errptr); + exit(1); +} + +// Install the trusted certificates. +ret = gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, cred); +if (ret != GNUTLS_E_SUCCESS) { + fprintf(stderr, "error: gnutls_credentials_set: %s\n", + gnutls_strerror(ret)); + exit(1); +} + +// Associate the socket with the session object and set the server +// name. +gnutls_transport_set_ptr(session, (gnutls_transport_ptr_t)(uintptr_t)sockfd); +ret = gnutls_server_name_set(session, GNUTLS_NAME_DNS, + host, strlen(host)); +if (ret != GNUTLS_E_SUCCESS) { + fprintf(stderr, "error: gnutls_server_name_set: %s\n", + gnutls_strerror(ret)); + exit(1); +} + +// Establish the session. +ret = gnutls_handshake(session); +if (ret != GNUTLS_E_SUCCESS) { + fprintf(stderr, "error: gnutls_handshake: %s\n", + gnutls_strerror(ret)); + exit(1); +} + + After the handshake has been completed, the server certificate needs to be verified (Example 12.11, “Verifying a server certificate using GNUTLS”). In the example, the user-defined certificate_validity_override function is called if the verification fails, so that a separate, user-specific trust store can be checked. This function call can be omitted if the functionality is not needed. + Example 12.11. Verifying a server certificate using GNUTLS +// Obtain the server certificate chain. The server certificate +// itself is stored in the first element of the array. +unsigned certslen = 0; +const gnutls_datum_t *const certs = + gnutls_certificate_get_peers(session, &certslen); +if (certs == NULL || certslen == 0) { + fprintf(stderr, "error: could not obtain peer certificate\n"); + exit(1); +} + +// Validate the certificate chain. +unsigned status = (unsigned)-1; +ret = gnutls_certificate_verify_peers2(session, &status); +if (ret != GNUTLS_E_SUCCESS) { + fprintf(stderr, "error: gnutls_certificate_verify_peers2: %s\n", + gnutls_strerror(ret)); + exit(1); +} +if (status != 0 && !certificate_validity_override(certs[0])) { + gnutls_datum_t msg; +#if GNUTLS_VERSION_AT_LEAST_3_1_4 + int type = gnutls_certificate_type_get (session); + ret = gnutls_certificate_verification_status_print(status, type, &out, 0); +#else + ret = -1; +#endif + if (ret == 0) { + fprintf(stderr, "error: %s\n", msg.data); + gnutls_free(msg.data); + exit(1); + } else { + fprintf(stderr, "error: certificate validation failed with code 0x%x\n", + status); + exit(1); + } +} + + In the next step (Example 12.12, “Matching the server host name and certificate in a GNUTLS client”, the certificate must be matched against the host name (note the unusual return value from gnutls_x509_crt_check_hostname). Again, an override function certificate_host_name_override is called. Note that the override must be keyed to the certificate and the host name. The function call can be omitted if the override is not needed. + Example 12.12. Matching the server host name and certificate in a GNUTLS client +// Match the peer certificate against the host name. +// We can only obtain a set of DER-encoded certificates from the +// session object, so we have to re-parse the peer certificate into +// a certificate object. +gnutls_x509_crt_t cert; +ret = gnutls_x509_crt_init(&cert); +if (ret != GNUTLS_E_SUCCESS) { + fprintf(stderr, "error: gnutls_x509_crt_init: %s\n", + gnutls_strerror(ret)); + exit(1); +} +// The peer certificate is the first certificate in the list. +ret = gnutls_x509_crt_import(cert, certs, GNUTLS_X509_FMT_DER); +if (ret != GNUTLS_E_SUCCESS) { + fprintf(stderr, "error: gnutls_x509_crt_import: %s\n", + gnutls_strerror(ret)); + exit(1); +} +ret = gnutls_x509_crt_check_hostname(cert, host); +if (ret == 0 && !certificate_host_name_override(certs[0], host)) { + fprintf(stderr, "error: host name does not match certificate\n"); + exit(1); +} +gnutls_x509_crt_deinit(cert); + + In newer GNUTLS versions, certificate checking and host name validation can be combined using the gnutls_certificate_verify_peers3 function. + + An established TLS session can be used for sending and receiving data, as in Example 12.13, “Using a GNUTLS session”. + Example 12.13. Using a GNUTLS session +char buf[4096]; +snprintf(buf, sizeof(buf), "GET / HTTP/1.0\r\nHost: %s\r\n\r\n", host); +ret = gnutls_record_send(session, buf, strlen(buf)); +if (ret < 0) { + fprintf(stderr, "error: gnutls_record_send: %s\n", gnutls_strerror(ret)); + exit(1); +} +ret = gnutls_record_recv(session, buf, sizeof(buf)); +if (ret < 0) { + fprintf(stderr, "error: gnutls_record_recv: %s\n", gnutls_strerror(ret)); + exit(1); +} + + In order to shut down a connection in an orderly manner, you should call the gnutls_bye function. Finally, the session object can be deallocated using gnutls_deinit (see Example 12.14, “Using a GNUTLS session”). + Example 12.14. Using a GNUTLS session +// Initiate an orderly connection shutdown. +ret = gnutls_bye(session, GNUTLS_SHUT_RDWR); +if (ret < 0) { + fprintf(stderr, "error: gnutls_bye: %s\n", gnutls_strerror(ret)); + exit(1); +} +// Free the session object. +gnutls_deinit(session); +Implementing TLS Clients With OpenJDK12.2.3. Implementing TLS Clients With OpenJDK + The examples below use the following cryptographic-related classes: + +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.cert.CertificateEncodingException; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLParameters; +import javax.net.ssl.SSLSocket; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; + +import sun.security.util.HostnameChecker; + + If compatibility with OpenJDK 6 is required, it is necessary to use the internal class sun.security.util.HostnameChecker. (The public OpenJDK API does not provide any support for dissecting the subject distinguished name of an X.509 certificate, so a custom-written DER parser is needed—or we have to use an internal class, which we do below.) In OpenJDK 7, the setEndpointIdentificationAlgorithm method was added to the javax.net.ssl.SSLParameters class, providing an official way to implement host name checking. + + TLS connections are established using an SSLContext instance. With a properly configured OpenJDK installation, the SunJSSE provider uses the system-wide set of trusted root certificate authorities, so no further configuration is necessary. For backwards compatibility with OpenJDK 6, the TLSv1 provider has to be supported as a fall-back option. This is shown in Example 12.15, “Setting up an SSLContext for OpenJDK TLS clients”. + Example 12.15. Setting up an SSLContext for OpenJDK TLS clients +// Create the context. Specify the SunJSSE provider to avoid +// picking up third-party providers. Try the TLS 1.2 provider +// first, then fall back to TLS 1.0. +SSLContext ctx; +try { + ctx = SSLContext.getInstance("TLSv1.2", "SunJSSE"); +} catch (NoSuchAlgorithmException e) { + try { + ctx = SSLContext.getInstance("TLSv1", "SunJSSE"); + } catch (NoSuchAlgorithmException e1) { + // The TLS 1.0 provider should always be available. + throw new AssertionError(e1); + } catch (NoSuchProviderException e1) { + throw new AssertionError(e1); + } +} catch (NoSuchProviderException e) { + // The SunJSSE provider should always be available. + throw new AssertionError(e); +} +ctx.init(null, null, null); + + In addition to the context, a TLS parameter object will be needed which adjusts the cipher suites and protocols (Example 12.16, “Setting up SSLParameters for TLS use with OpenJDK”). Like the context, these parameters can be reused for multiple TLS connections. + Example 12.16. Setting up SSLParameters for TLS use with OpenJDK +// Prepare TLS parameters. These have to applied to every TLS +// socket before the handshake is triggered. +SSLParameters params = ctx.getDefaultSSLParameters(); +// Do not send an SSL-2.0-compatible Client Hello. +ArrayList<String> protocols = new ArrayList<String>( + Arrays.asList(params.getProtocols())); +protocols.remove("SSLv2Hello"); +params.setProtocols(protocols.toArray(new String[protocols.size()])); +// Adjust the supported ciphers. +ArrayList<String> ciphers = new ArrayList<String>( + Arrays.asList(params.getCipherSuites())); +ciphers.retainAll(Arrays.asList( + "TLS_RSA_WITH_AES_128_CBC_SHA256", + "TLS_RSA_WITH_AES_256_CBC_SHA256", + "TLS_RSA_WITH_AES_256_CBC_SHA", + "TLS_RSA_WITH_AES_128_CBC_SHA", + "SSL_RSA_WITH_3DES_EDE_CBC_SHA", + "SSL_RSA_WITH_RC4_128_SHA1", + "SSL_RSA_WITH_RC4_128_MD5", + "TLS_EMPTY_RENEGOTIATION_INFO_SCSV")); +params.setCipherSuites(ciphers.toArray(new String[ciphers.size()])); + + As initialized above, the parameter object does not yet require host name checking. This has to be enabled separately, and this is only supported by OpenJDK 7 and later: + +params.setEndpointIdentificationAlgorithm("HTTPS"); + + All application protocols can use the "HTTPS" algorithm. (The algorithms have minor differences with regard to wildcard handling, which should not matter in practice.) + + Example 12.17, “Establishing a TLS connection with OpenJDK” shows how to establish the connection. Before the handshake is initialized, the protocol and cipher configuration has to be performed, by applying the parameter object params. (After this point, changes to params will not affect this TLS socket.) As mentioned initially, host name checking requires using an internal API on OpenJDK 6. + Example 12.17. Establishing a TLS connection with OpenJDK +// Create the socket and connect it at the TCP layer. +SSLSocket socket = (SSLSocket) ctx.getSocketFactory() + .createSocket(host, port); + +// Disable the Nagle algorithm. +socket.setTcpNoDelay(true); + +// Adjust ciphers and protocols. +socket.setSSLParameters(params); + +// Perform the handshake. +socket.startHandshake(); + +// Validate the host name. The match() method throws +// CertificateException on failure. +X509Certificate peer = (X509Certificate) + socket.getSession().getPeerCertificates()[0]; +// This is the only way to perform host name checking on OpenJDK 6. +HostnameChecker.getInstance(HostnameChecker.TYPE_TLS).match( + host, peer); + + Starting with OpenJDK 7, the last lines can be omitted, provided that host name verification has been enabled by calling the setEndpointIdentificationAlgorithm method on the params object (before it was applied to the socket). + + The TLS socket can be used as a regular socket, as shown in Example 12.18, “Using a TLS client socket in OpenJDK”. + Example 12.18. Using a TLS client socket in OpenJDK +socket.getOutputStream().write("GET / HTTP/1.0\r\n\r\n" + .getBytes(Charset.forName("UTF-8"))); +byte[] buffer = new byte[4096]; +int count = socket.getInputStream().read(buffer); +System.out.write(buffer, 0, count); +12.2.3.1. Overriding server certificate validation with OpenJDK 6 + Overriding certificate validation requires a custom trust manager. With OpenJDK 6, the trust manager lacks information about the TLS session, and to which server the connection is made. Certificate overrides have to be tied to specific servers (host names). Consequently, different TrustManager and SSLContext objects have to be used for different servers. + + In the trust manager shown in Example 12.19, “A customer trust manager for OpenJDK TLS clients”, the server certificate is identified by its SHA-256 hash. + Example 12.19. A customer trust manager for OpenJDK TLS clients +public class MyTrustManager implements X509TrustManager { + private final byte[] certHash; + + public MyTrustManager(byte[] certHash) throws Exception { + this.certHash = certHash; + } + + @Override + public void checkClientTrusted(X509Certificate[] chain, String authType) + throws CertificateException { + throw new UnsupportedOperationException(); + } + + @Override + public void checkServerTrusted(X509Certificate[] chain, + String authType) throws CertificateException { + byte[] digest = getCertificateDigest(chain[0]); + String digestHex = formatHex(digest); + + if (Arrays.equals(digest, certHash)) { + System.err.println("info: accepting certificate: " + digestHex); + } else { + throw new CertificateException("certificate rejected: " + + digestHex); + } + } + + @Override + public X509Certificate[] getAcceptedIssuers() { + return new X509Certificate[0]; + } +} + + This trust manager has to be passed to the init method of the SSLContext object, as show in Example 12.20, “Using a custom TLS trust manager with OpenJDK”. + Example 12.20. Using a custom TLS trust manager with OpenJDK +SSLContext ctx; +try { + ctx = SSLContext.getInstance("TLSv1.2", "SunJSSE"); +} catch (NoSuchAlgorithmException e) { + try { + ctx = SSLContext.getInstance("TLSv1", "SunJSSE"); + } catch (NoSuchAlgorithmException e1) { + throw new AssertionError(e1); + } catch (NoSuchProviderException e1) { + throw new AssertionError(e1); + } +} catch (NoSuchProviderException e) { + throw new AssertionError(e); +} +MyTrustManager tm = new MyTrustManager(certHash); +ctx.init(null, new TrustManager[] {tm}, null); + + When certificate overrides are in place, host name verification should not be performed because there is no security requirement that the host name in the certificate matches the host name used to establish the connection (and it often will not). However, without host name verification, it is not possible to perform transparent fallback to certification validation using the system certificate store. + + The approach described above works with OpenJDK 6 and later versions. Starting with OpenJDK 7, it is possible to use a custom subclass of the javax.net.ssl.X509ExtendedTrustManager class. The OpenJDK TLS implementation will call the new methods, passing along TLS session information. This can be used to implement certificate overrides as a fallback (if certificate or host name verification fails), and a trust manager object can be used for multiple servers because the server address is available to the trust manager. + Implementing TLS Clients With NSS12.2.4. Implementing TLS Clients With NSS + The following code shows how to implement a simple TLS client using NSS. Note that the error handling needs replacing before production use. + + Using NSS needs several header files, as shown in Example 12.21, “Include files for NSS”. + Example 12.21. Include files for NSS +// NSPR include files +#include <prerror.h> +#include <prinit.h> + +// NSS include files +#include <nss.h> +#include <pk11pub.h> +#include <secmod.h> +#include <ssl.h> +#include <sslproto.h> + +// Private API, no other way to turn a POSIX file descriptor into an +// NSPR handle. +NSPR_API(PRFileDesc*) PR_ImportTCPSocket(int); + + Initializing the NSS library is a complex task (Example 12.22, “Initializing the NSS library”). It is not thread-safe. By default, the library is in export mode, and all strong ciphers are disabled. Therefore, after creating the NSSInitCContext object, we probe all the strong ciphers we want to use, and check if at least one of them is available. If not, we call NSS_SetDomesticPolicy to switch to unrestricted policy mode. This function replaces the existing global cipher suite policy, that is why we avoid calling it unless absolutely necessary. + + The simplest way to configured the trusted root certificates involves loading the libnssckbi.so NSS module with a call to the SECMOD_LoadUserModule function. The root certificates are compiled into this module. (The PEM module for NSS, libnsspem.so, offers a way to load trusted CA certificates from a file.) + Example 12.22. Initializing the NSS library +PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); +NSSInitContext *const ctx = + NSS_InitContext("sql:/etc/pki/nssdb", "", "", "", NULL, + NSS_INIT_READONLY | NSS_INIT_PK11RELOAD); +if (ctx == NULL) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: NSPR error code %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); +} + +// Ciphers to enable. +static const PRUint16 good_ciphers[] = { + TLS_RSA_WITH_AES_128_CBC_SHA, + TLS_RSA_WITH_AES_256_CBC_SHA, + SSL_RSA_WITH_3DES_EDE_CBC_SHA, + SSL_NULL_WITH_NULL_NULL // sentinel +}; + +// Check if the current policy allows any strong ciphers. If it +// doesn't, switch to the "domestic" (unrestricted) policy. This is +// not thread-safe and has global impact. Consequently, we only do +// it if absolutely necessary. +int found_good_cipher = 0; +for (const PRUint16 *p = good_ciphers; *p != SSL_NULL_WITH_NULL_NULL; + ++p) { + PRInt32 policy; + if (SSL_CipherPolicyGet(*p, &policy) != SECSuccess) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: policy for cipher %u: error %d: %s\n", + (unsigned)*p, err, PR_ErrorToName(err)); + exit(1); + } + if (policy == SSL_ALLOWED) { + fprintf(stderr, "info: found cipher %x\n", (unsigned)*p); + found_good_cipher = 1; + break; + } +} +if (!found_good_cipher) { + if (NSS_SetDomesticPolicy() != SECSuccess) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: NSS_SetDomesticPolicy: error %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); + } +} + +// Initialize the trusted certificate store. +char module_name[] = "library=libnssckbi.so name=\"Root Certs\""; +SECMODModule *module = SECMOD_LoadUserModule(module_name, NULL, PR_FALSE); +if (module == NULL || !module->loaded) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: NSPR error code %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); +} + + Some of the effects of the initialization can be reverted with the following function calls: + +SECMOD_DestroyModule(module); +NSS_ShutdownContext(ctx); + + After NSS has been initialized, the TLS connection can be created (Example 12.23, “Creating a TLS connection with NSS”). The internal PR_ImportTCPSocket function is used to turn the POSIX file descriptor sockfd into an NSPR file descriptor. (This function is de-facto part of the NSS public ABI, so it will not go away.) Creating the TLS-capable file descriptor requires a model descriptor, which is configured with the desired set of protocols and ciphers. (The good_ciphers variable is part of Example 12.22, “Initializing the NSS library”.) We cannot resort to disabling ciphers not on a whitelist because by default, the AES cipher suites are disabled. The model descriptor is not needed anymore after TLS support has been activated for the existing connection descriptor. + + The call to SSL_BadCertHook can be omitted if no mechanism to override certificate verification is needed. The bad_certificate function must check both the host name specified for the connection and the certificate before granting the override. + + Triggering the actual handshake requires three function calls, SSL_ResetHandshake, SSL_SetURL, and SSL_ForceHandshake. (If SSL_ResetHandshake is omitted, SSL_ForceHandshake will succeed, but the data will not be encrypted.) During the handshake, the certificate is verified and matched against the host name. + Example 12.23. Creating a TLS connection with NSS +// Wrap the POSIX file descriptor. This is an internal NSPR +// function, but it is very unlikely to change. +PRFileDesc* nspr = PR_ImportTCPSocket(sockfd); +sockfd = -1; // Has been taken over by NSPR. + +// Add the SSL layer. +{ + PRFileDesc *model = PR_NewTCPSocket(); + PRFileDesc *newfd = SSL_ImportFD(NULL, model); + if (newfd == NULL) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: NSPR error code %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); + } + model = newfd; + newfd = NULL; + if (SSL_OptionSet(model, SSL_ENABLE_SSL2, PR_FALSE) != SECSuccess) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: set SSL_ENABLE_SSL2 error %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); + } + if (SSL_OptionSet(model, SSL_V2_COMPATIBLE_HELLO, PR_FALSE) != SECSuccess) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: set SSL_V2_COMPATIBLE_HELLO error %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); + } + if (SSL_OptionSet(model, SSL_ENABLE_DEFLATE, PR_FALSE) != SECSuccess) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: set SSL_ENABLE_DEFLATE error %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); + } + + // Disable all ciphers (except RC4-based ciphers, for backwards + // compatibility). + const PRUint16 *const ciphers = SSL_GetImplementedCiphers(); + for (unsigned i = 0; i < SSL_GetNumImplementedCiphers(); i++) { + if (ciphers[i] != SSL_RSA_WITH_RC4_128_SHA + && ciphers[i] != SSL_RSA_WITH_RC4_128_MD5) { + if (SSL_CipherPrefSet(model, ciphers[i], PR_FALSE) != SECSuccess) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: disable cipher %u: error %d: %s\n", + (unsigned)ciphers[i], err, PR_ErrorToName(err)); + exit(1); + } + } + } + + // Enable the strong ciphers. + for (const PRUint16 *p = good_ciphers; *p != SSL_NULL_WITH_NULL_NULL; + ++p) { + if (SSL_CipherPrefSet(model, *p, PR_TRUE) != SECSuccess) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: enable cipher %u: error %d: %s\n", + (unsigned)*p, err, PR_ErrorToName(err)); + exit(1); + } + } + + // Allow overriding invalid certificate. + if (SSL_BadCertHook(model, bad_certificate, (char *)host) != SECSuccess) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: SSL_BadCertHook error %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); + } + + newfd = SSL_ImportFD(model, nspr); + if (newfd == NULL) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: SSL_ImportFD error %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); + } + nspr = newfd; + PR_Close(model); +} + +// Perform the handshake. +if (SSL_ResetHandshake(nspr, PR_FALSE) != SECSuccess) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: SSL_ResetHandshake error %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); +} +if (SSL_SetURL(nspr, host) != SECSuccess) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: SSL_SetURL error %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); +} +if (SSL_ForceHandshake(nspr) != SECSuccess) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: SSL_ForceHandshake error %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); +} + + After the connection has been established, Example 12.24, “Using NSS for sending and receiving data” shows how to use the NSPR descriptor to communicate with the server. + Example 12.24. Using NSS for sending and receiving data +char buf[4096]; +snprintf(buf, sizeof(buf), "GET / HTTP/1.0\r\nHost: %s\r\n\r\n", host); +PRInt32 ret = PR_Write(nspr, buf, strlen(buf)); +if (ret < 0) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: PR_Write error %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); +} +ret = PR_Read(nspr, buf, sizeof(buf)); +if (ret < 0) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: PR_Read error %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); +} + + Example 12.25, “Closing NSS client connections” shows how to close the connection. + Example 12.25. Closing NSS client connections +// Send close_notify alert. +if (PR_Shutdown(nspr, PR_SHUTDOWN_BOTH) != PR_SUCCESS) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: PR_Read error %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); +} +// Closes the underlying POSIX file descriptor, too. +PR_Close(nspr); +Implementing TLS Clients With Python12.2.5. Implementing TLS Clients With Python + The Python distribution provides a TLS implementation in the ssl module (actually a wrapper around OpenSSL). The exported interface is somewhat restricted, so that the client code shown below does not fully implement the recommendations in Section 12.1.1, “OpenSSL Pitfalls”. + Important + Currently, most Python function which accept https:// URLs or otherwise implement HTTPS support do not perform certificate validation at all. (For example, this is true for the httplib and xmlrpclib modules.) If you use HTTPS, you should not use the built-in HTTP clients. The Curl class in the curl module, as provided by the python-pycurl package implements proper certificate validation. + + The ssl module currently does not perform host name checking on the server certificate. Example 12.26, “Implementing TLS host name checking Python (without wildcard support)” shows how to implement certificate matching, using the parsed certificate returned by getpeercert. + Example 12.26. Implementing TLS host name checking Python (without wildcard support) +def check_host_name(peercert, name): + """Simple certificate/host name checker. Returns True if the + certificate matches, False otherwise. Does not support + wildcards.""" + # Check that the peer has supplied a certificate. + # None/{} is not acceptable. + if not peercert: + return False + if peercert.has_key("subjectAltName"): + for typ, val in peercert["subjectAltName"]: + if typ == "DNS" and val == name: + return True + else: + # Only check the subject DN if there is no subject alternative + # name. + cn = None + for attr, val in peercert["subject"]: + # Use most-specific (last) commonName attribute. + if attr == "commonName": + cn = val + if cn is not None: + return cn == name + return False + + To turn a regular, connected TCP socket into a TLS-enabled socket, use the ssl.wrap_socket function. The function call in Example 12.27, “Establishing a TLS client connection with Python” provides additional arguments to override questionable defaults in OpenSSL and in the Python module. + + ciphers="HIGH:-aNULL:-eNULL:-PSK:RC4-SHA:RC4-MD5" selects relatively strong cipher suites with certificate-based authentication. (The call to check_host_name function provides additional protection against anonymous cipher suites.) + + ssl_version=ssl.PROTOCOL_TLSv1 disables SSL 2.0 support. By default, the ssl module sends an SSL 2.0 client hello, which is rejected by some servers. Ideally, we would request OpenSSL to negotiated the most recent TLS version supported by the server and the client, but the Python module does not allow this. + + cert_reqs=ssl.CERT_REQUIRED turns on certificate validation. + + ca_certs='/etc/ssl/certs/ca-bundle.crt' initializes the certificate store with a set of trusted root CAs. Unfortunately, it is necessary to hard-code this path into applications because the default path in OpenSSL is not available through the Python ssl module. + + The ssl module (and OpenSSL) perform certificate validation, but the certificate must be compared manually against the host name, by calling the check_host_name defined above. + Example 12.27. Establishing a TLS client connection with Python +sock = ssl.wrap_socket(sock, + ciphers="HIGH:-aNULL:-eNULL:-PSK:RC4-SHA:RC4-MD5", + ssl_version=ssl.PROTOCOL_TLSv1, + cert_reqs=ssl.CERT_REQUIRED, + ca_certs='/etc/ssl/certs/ca-bundle.crt') +# getpeercert() triggers the handshake as a side effect. +if not check_host_name(sock.getpeercert(), host): + raise IOError("peer certificate does not match host name") + + After the connection has been established, the TLS socket can be used like a regular socket: + +sock.write("GET / HTTP/1.1\r\nHost: " + host + "\r\n\r\n") +print sock.read() + + Closing the TLS socket is straightforward as well: + +sock.close() +Appendix A. Revision HistoryAppendix A. Revision History + Revision 0-1Thu Mar 7 2013Eric Christensen sparks@redhat.com + Initial publication. + + + + \ No newline at end of file diff --git a/defensive-coding/tmp/en-US/xml/Defensive_Coding.xml b/defensive-coding/tmp/en-US/xml/Defensive_Coding.xml new file mode 100644 index 0000000..27e4b13 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Defensive_Coding.xml @@ -0,0 +1,34 @@ + + +%BOOK_ENTITIES; +]> + + + + Programming Languages + + + + + + + Specific Programming Tasks + + + + + + + + + + + Implementing Security Features + + + + + + + diff --git a/defensive-coding/tmp/en-US/xml/Features/Authentication.xml b/defensive-coding/tmp/en-US/xml/Features/Authentication.xml new file mode 100644 index 0000000..32d294d --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Features/Authentication.xml @@ -0,0 +1,105 @@ + + +%BOOK_ENTITIES; +]> + + Authentication and Authorization +
+ Authenticating servers + + When connecting to a server, a client has to make sure that it is actually talking to the server it expects. There are two different aspects, securing the network path, and making sure that the expected user runs the process on the target host. There are several ways to ensure that: + + + + + The server uses a TLS certificate which is valid according to the web browser public key infrastructure, and the client verifies the certificate and the host name. + + + + + + The server uses a TLS certificate which is expectedby the client (perhaps it is stored in a configuration file read by the client). In this case, no host name checking is required. + + + + + + On Linux, UNIX domain sockets (of the PF_UNIX protocol family, sometimes called PF_LOCAL) are restricted by file system permissions. If the server socket path is not world-writable, the server identity cannot be spoofed by local users. + + + + + + Port numbers less than 1024 (trusted ports) can only be used by root, so if a UDP or TCP server is running on the local host and it uses a trusted port, its identity is assured. (Not all operating systems enforce the trusted ports concept, and the network might not be trusted, so it is only useful on the local system.) + + + + + + + TLS () is the recommended way for securing connections over untrusted networks. + + + If the server port number is 1024 is higher, a local user can impersonate the process by binding to this socket, perhaps after crashing the real server by exploiting a denial-of-service vulnerability. + + +
+ +
+ Host-based authentication + + Host-based authentication uses access control lists (ACLs) to accept or deny requests from clients. Thsis authentication method comes in two flavors: IP-based (or, more generally, address-based) and name-based (with the name coming from DNS or /etc/hosts). IP-based ACLs often use prefix notation to extend access to entire subnets. Name-based ACLs sometimes use wildcards for adding groups of hosts (from entire DNS subtrees). (In the SSH context, host-based authentication means something completely different and is not covered in this section.) + + + Host-based authentication trust the network and may not offer sufficient granularity, so it has to be considered a weak form of authentication. On the other hand, IP-based authentication can be made extremely robust and can be applied very early in input processing, so it offers an opportunity for significantly reducing the number of potential attackers for many services. + + + The names returned by gethostbyaddr and getnameinfo functions cannot be trusted. (DNS PTR records can be set to arbitrary values, not just names belong to the address owner.) If these names are used for ACL matching, a forward lookup using gethostbyaddr or getaddrinfo has to be performed. The name is only valid if the original address is found among the results of the forward lookup (double-reverse lookup). + + + An empty ACL should deny all access (deny-by-default). If empty ACLs permits all access, configuring any access list must switch to deny-by-default for all unconfigured protocols, in both name-based and address-based variants. + + + Similarly, if an address or name is not matched by the list, it should be denied. However, many implementations behave differently, so the actual behavior must be documented properly. + + + IPv6 addresses can embed IPv4 addresses. There is no universally correct way to deal with this ambiguity. The behavior of the ACL implementation should be documented. + + +
+ +
+ UNIX domain socket authentication + + UNIX domain sockets (with address family AF_UNIX or AF_LOCAL) are restricted to the local host and offer a special authentication mechanism: credentials passing. + + + Nowadays, most systems support the SO_PEERCRED (Linux) or LOCAL_PEERCRED (FreeBSD) socket options, or the getpeereid (other BSDs, MacOS X). These interfaces provide direct access to the (effective) user ID on the other end of a domain socket connect, without cooperation from the other end. + + + Historically, credentials passing was implemented using ancillary data in the sendmsg and recvmsg functions. On some systems, only credentials data that the peer has explicitly sent can be received, and the kernel checks the data for correctness on the sending side. This means that both peers need to deal with ancillary data. Compared to that, the modern interfaces are easier to use. Both sets of interfaces vary considerably among UNIX-like systems, unfortunately. + + + If you want to authenticate based on supplementary groups, you should obtain the user ID using one of these methods, and look up the list of supplementary groups using getpwuid (or getpwuid_r) and getgrouplist. Using the PID and information from /proc/PID/status is prone to race conditions and insecure. + + +
+ + + +
+ diff --git a/defensive-coding/tmp/en-US/xml/Features/TLS.xml b/defensive-coding/tmp/en-US/xml/Features/TLS.xml new file mode 100644 index 0000000..e3d4a73 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Features/TLS.xml @@ -0,0 +1,579 @@ + + +%BOOK_ENTITIES; +]> + + Transport Layer Security + + Transport Layer Security (TLS, formerly Secure Sockets Layer/SSL) is the recommended way to to protect integrity and confidentiality while data is transferred over an untrusted network connection, and to identify the endpoint. + +
+ Common Pitfalls + + TLS implementations are difficult to use, and most of them lack a clean API design. The following sections contain implementation-specific advice, and some generic pitfalls are mentioned below. + + + + + Most TLS implementations have questionable default TLS cipher suites. Most of them enable anonymous Diffie-Hellman key exchange (but we generally want servers to authenticate themselves). Many do not disable ciphers which are subject to brute-force attacks because of restricted key lengths. Some even disable all variants of AES in the default configuration. + + + When overriding the cipher suite defaults, it is recommended to disable all cipher suites which are not present on a whitelist, instead of simply enabling a list of cipher suites. This way, if an algorithm is disabled by default in the TLS implementation in a future security update, the application will not re-enable it. + + + + + + The name which is used in certificate validation must match the name provided by the user or configuration file. No host name canonicalization or IP address lookup must be performed. + + + + + + The TLS handshake has very poor performance if the TCP Nagle algorithm is active. You should switch on the TCP_NODELAY socket option (at least for the duration of the handshake), or use the Linux-specific TCP_CORK option. + + + Deactivating the TCP Nagle algorithm + + + + + + + + Implementing proper session resumption decreases handshake overhead considerably. This is important if the upper-layer protocol uses short-lived connections (like most application of HTTPS). + + + + + + Both client and server should work towards an orderly connection shutdown, that is send close_notify alerts and respond to them. This is especially important if the upper-layer protocol does not provide means to detect connection truncation (like some uses of HTTP). + + + + + + When implementing a server using event-driven programming, it is important to handle the TLS handshake properly because it includes multiple network round-trips which can block when an ordinary TCP accept would not. Otherwise, a client which fails to complete the TLS handshake for some reason will prevent the server from handling input from other clients. + + + + + + Unlike regular file descriptors, TLS connections cannot be passed between processes. Some TLS implementations add additional restrictions, and TLS connections generally cannot be used across fork function calls (see ). + + + + + +
+ OpenSSL Pitfalls + + Some OpenSSL function use tri-state return values. Correct error checking is extremely important. Several functions return int values with the following meaning: + + + + + The value 1 indicates success (for example, a successful signature verification). + + + + + + The value 0 indicates semantic failure (for example, a signature verification which was unsuccessful because the signing certificate was self-signed). + + + + + + The value -1 indicates a low-level error in the system, such as failure to allocate memory using malloc. + + + + + + + Treating such tri-state return values as booleans can lead to security vulnerabilities. Note that some OpenSSL functions return boolean results or yet another set of status indicators. Each function needs to be checked individually. + + + Recovering precise error information is difficult. shows how to obtain a more precise error code after a function call on an SSL object has failed. However, there are still cases where no detailed error information is available (e.g., if SSL_shutdown fails due to a connection teardown by the other end). + + + Obtaining OpenSSL error codes + + + + + The OPENSSL_config function is documented to never fail. In reality, it can terminate the entire process if there is a failure accessing the configuration file. An error message is written to standard error, but which might not be visible if the function is called from a daemon process. + + + OpenSSL contains two separate ASN.1 DER decoders. One set of decoders operate on BIO handles (the input/output stream abstraction provided by OpenSSL); their decoder function names start with d2i_ and end in _fp or _bio (e.g., d2i_X509_fp or d2i_X509_bio). These decoders must not be used for parsing data from untrusted sources; instead, the variants without the _fp and _bio (e.g., d2i_X509) shall be used. The BIO variants have received considerably less testing and are not very robust. + + + For the same reason, the OpenSSL command line tools (such as openssl x509) are generally generally less robust than the actual library code. They use the BIO functions internally, and not the more robust variants. + + + The command line tools do not always indicate failure in the exit status of the openssl process. For instance, a verification failure in openssl verify result in an exit status of zero. + + + The OpenSSL server and client applications (openssl s_client and openssl s_server) are debugging tools and should never be used as generic clients. For instance, the s_client tool reacts in a surprisign way to lines starting with R and Q. + + + OpenSSL allows application code to access private key material over documented interfaces. This can significantly increase the part of the code base which has to undergo security certification. + + +
+ +
+ GNUTLS Pitfalls + + libgnutls.so.26 links to libpthread.so.0. Loading the threading library too late causes problems, so the main program should be linked with -lpthread as well. As a result, it can be difficult to use GNUTLS in a plugin which is loaded with the dlopen function. Another side effect is that applications which merely link against GNUTLS (even without actually using it) may incur a substantial overhead because other libraries automatically switch to thread-safe algorithms. + + + The gnutls_global_init function must be called before using any functionality provided by the library. This function is not thread-safe, so external locking is required, but it is not clear which lock should be used. Omitting the synchronization does not just lead to a memory leak, as it is suggested in the GNUTLS documentation, but to undefined behavior because there is no barrier that would enforce memory ordering. + + + The gnutls_global_deinit function does not actually deallocate all resources allocated by gnutls_global_init. It is currently not thread-safe. Therefore, it is best to avoid calling it altogether. + + + The X.509 implementation in GNUTLS is rather lenient. For example, it is possible to create and process X.509 version 1 certificates which carry extensions. These certificates are (correctly) rejected by other implementations. + + +
+ +
+ OpenJDK Pitfalls + + The Java cryptographic framework is highly modular. As a result, when you request an object implementing some cryptographic functionality, you cannot be completely sure that you end up with the well-tested, reviewed implementation in OpenJDK. + + + OpenJDK (in the source code as published by Oracle) and other implementations of the Java platform require that the system administrator has installed so-called unlimited strength jurisdiction policy files. Without this step, it is not possible to use the secure algorithms which offer sufficient cryptographic strength. Most downstream redistributors of OpenJDK remove this requirement. + + + Some versions of OpenJDK use /dev/random as the randomness source for nonces and other random data which is needed for TLS operation, but does not actually require physical randomness. As a result, TLS applications can block, waiting for more bits to become available in /dev/random. + + +
+ +
+ NSS Pitfalls + + NSS was not designed to be used by other libraries which can be linked into applications without modifying them. There is a lot of global state. There does not seem to be a way to perform required NSS initialization without race conditions. + + + If the NSPR descriptor is in an unexpected state, the SSL_ForceHandshake function can succeed, but no TLS handshake takes place, the peer is not authenticated, and subsequent data is exchanged in the clear. + + + NSS disables itself if it detects that the process underwent a fork after the library has been initialized. This behavior is required by the PKCS#11 API specification. + + +
+ + +
+ +
+ TLS Clients + + Secure use of TLS in a client generally involves all of the following steps. (Individual instructions for specific TLS implementations follow in the next sections.) + + + + + The client must configure the TLS library to use a set of trusted root certificates. These certificates are provided by the system in /etc/ssl/certs or files derived from it. + + + + + + The client selects sufficiently strong cryptographic primitives and disables insecure ones (such as no-op encryption). Compression and SSL version 2 support must be disabled (including the SSLv2-compatible handshake). + + + + + + The client initiates the TLS connection. The Server Name Indication extension should be used if supported by the TLS implementation. Before switching to the encrypted connection state, the contents of all input and output buffers must be discarded. + + + + + + The client needs to validate the peer certificate provided by the server, that is, the client must check that there is a cryptographically protected chain from a trusted root certificate to the peer certificate. (Depending on the TLS implementation, a TLS handshake can succeed even if the certificate cannot be validated.) + + + + + + The client must check that the configured or user-provided server name matches the peer certificate provided by the server. + + + + + + + It is safe to provide users detailed diagnostics on certificate validation failures. Other causes of handshake failures and, generally speaking, any details on other errors reported by the TLS implementation (particularly exception tracebacks), must not be divulged in ways that make them accessible to potential attackers. Otherwise, it is possible to create decryption oracles. + + + + Depending on the application, revocation checking (against certificate revocations lists or via OCSP) and session resumption are important aspects of production-quality client. These aspects are not yet covered. + + + +
+ Implementation TLS Clients With OpenSSL + + In the following code, the error handling is only exploratory. Proper error handling is required for production use, especially in libraries. + + + The OpenSSL library needs explicit initialization (see ). + + + OpenSSL library initialization + + + + + After that, a context object has to be created, which acts as a factory for connection objects (). We use an explicit cipher list so that we do not pick up any strange ciphers when OpenSSL is upgraded. The actual version requested in the client hello depends on additional restrictions in the OpenSSL library. If possible, you should follow the example code and use the default list of trusted root certificate authorities provided by the system because you would have to maintain your own set otherwise, which can be cumbersome. + + + OpenSSL client context creation + + + + + A single context object can be used to create multiple connection objects. It is safe to use the same SSL_CTX object for creating connections concurrently from multiple threads, provided that the SSL_CTX object is not modified (e.g., callbacks must not be changed). + + + After creating the TCP socket and disabling the Nagle algorithm (per ), the actual connection object needs to be created, as show in . If the handshake started by SSL_connect fails, the ssl_print_error_and_exit function from is called. + + + The certificate_validity_override function provides an opportunity to override the validity of the certificate in case the OpenSSL check fails. If such functionality is not required, the call can be removed, otherwise, the application developer has to implement it. + + + The host name passed to the functions SSL_set_tlsext_host_name and X509_check_host must be the name that was passed to getaddrinfo or a similar name resolution function. No host name canonicalization must be performed. The X509_check_host function used in the final step for host name matching is currently only implemented in OpenSSL 1.1, which is not released yet. In case host name matching fails, the function certificate_host_name_override is called. This function should check user-specific certificate store, to allow a connection even if the host name does not match the certificate. This function has to be provided by the application developer. Note that the override must be keyed by both the certificate and the host name. + + + Creating a client connection using OpenSSL + + + + + The connection object can be used for sending and receiving data, as in . It is also possible to create a BIO object and use the SSL object as the underlying transport, using BIO_set_ssl. + + + Using an OpenSSL connection to send and receive data + + + + + When it is time to close the connection, the SSL_shutdown function needs to be called twice for an orderly, synchronous connection termination (). This exchanges close_notify alerts with the server. The additional logic is required to deal with an unexpected close_notify from the server. Note that is necessary to explicitly close the underlying socket after the connection object has been freed. + + + Closing an OpenSSL connection in an orderly fashion + + + + + shows how to deallocate the context object when it is no longer needed because no further TLS connections will be established. + + + Closing an OpenSSL connection in an orderly fashion + + + + +
+ +
+ Implementation TLS Clients With GNUTLS + + This section describes how to implement a TLS client with full certificate validation (but without certificate revocation checking). Note that the error handling in is only exploratory and needs to be replaced before production use. + + + The GNUTLS library needs explicit initialization: + + + + Failing to do so can result in obscure failures in Base64 decoding. See for additional aspects of initialization. + + + Before setting up TLS connections, a credentials objects has to be allocated and initialized with the set of trusted root CAs (). + + + Initializing a GNUTLS credentials structure + + + + + After the last TLS connection has been closed, this credentials object should be freed: + + + + During its lifetime, the credentials object can be used to initialize TLS session objects from multiple threads, provided that it is not changed. + + + Once the TCP connection has been established, the Nagle algorithm should be disabled (see ). After that, the socket can be associated with a new GNUTLS session object. The previously allocated credentials object provides the set of root CAs. The NORMAL set of cipher suites and protocols provides a reasonable default. Then the TLS handshake must be initiated. This is shown in . + + + Establishing a TLS client connection using GNUTLS + + + + + After the handshake has been completed, the server certificate needs to be verified (). In the example, the user-defined certificate_validity_override function is called if the verification fails, so that a separate, user-specific trust store can be checked. This function call can be omitted if the functionality is not needed. + + + Verifying a server certificate using GNUTLS + + + + + In the next step (, the certificate must be matched against the host name (note the unusual return value from gnutls_x509_crt_check_hostname). Again, an override function certificate_host_name_override is called. Note that the override must be keyed to the certificate and the host name. The function call can be omitted if the override is not needed. + + + Matching the server host name and certificate in a GNUTLS client + + + + + In newer GNUTLS versions, certificate checking and host name validation can be combined using the gnutls_certificate_verify_peers3 function. + + + An established TLS session can be used for sending and receiving data, as in . + + + Using a GNUTLS session + + + + + In order to shut down a connection in an orderly manner, you should call the gnutls_bye function. Finally, the session object can be deallocated using gnutls_deinit (see ). + + + Using a GNUTLS session + + + + +
+ +
+ Implementing TLS Clients With OpenJDK + + The examples below use the following cryptographic-related classes: + + + + If compatibility with OpenJDK 6 is required, it is necessary to use the internal class sun.security.util.HostnameChecker. (The public OpenJDK API does not provide any support for dissecting the subject distinguished name of an X.509 certificate, so a custom-written DER parser is needed—or we have to use an internal class, which we do below.) In OpenJDK 7, the setEndpointIdentificationAlgorithm method was added to the javax.net.ssl.SSLParameters class, providing an official way to implement host name checking. + + + TLS connections are established using an SSLContext instance. With a properly configured OpenJDK installation, the SunJSSE provider uses the system-wide set of trusted root certificate authorities, so no further configuration is necessary. For backwards compatibility with OpenJDK 6, the TLSv1 provider has to be supported as a fall-back option. This is shown in . + + + Setting up an <literal>SSLContext</literal> for OpenJDK TLS clients + + + + + In addition to the context, a TLS parameter object will be needed which adjusts the cipher suites and protocols (). Like the context, these parameters can be reused for multiple TLS connections. + + + Setting up <literal>SSLParameters</literal> for TLS use with OpenJDK + + + + + As initialized above, the parameter object does not yet require host name checking. This has to be enabled separately, and this is only supported by OpenJDK 7 and later: + + + + All application protocols can use the "HTTPS" algorithm. (The algorithms have minor differences with regard to wildcard handling, which should not matter in practice.) + + + shows how to establish the connection. Before the handshake is initialized, the protocol and cipher configuration has to be performed, by applying the parameter object params. (After this point, changes to params will not affect this TLS socket.) As mentioned initially, host name checking requires using an internal API on OpenJDK 6. + + + Establishing a TLS connection with OpenJDK + + + + + Starting with OpenJDK 7, the last lines can be omitted, provided that host name verification has been enabled by calling the setEndpointIdentificationAlgorithm method on the params object (before it was applied to the socket). + + + The TLS socket can be used as a regular socket, as shown in . + + + Using a TLS client socket in OpenJDK + + + +
+ Overriding server certificate validation with OpenJDK 6 + + Overriding certificate validation requires a custom trust manager. With OpenJDK 6, the trust manager lacks information about the TLS session, and to which server the connection is made. Certificate overrides have to be tied to specific servers (host names). Consequently, different TrustManager and SSLContext objects have to be used for different servers. + + + In the trust manager shown in , the server certificate is identified by its SHA-256 hash. + + + A customer trust manager for OpenJDK TLS clients + + + + + This trust manager has to be passed to the init method of the SSLContext object, as show in . + + + Using a custom TLS trust manager with OpenJDK + + + + + When certificate overrides are in place, host name verification should not be performed because there is no security requirement that the host name in the certificate matches the host name used to establish the connection (and it often will not). However, without host name verification, it is not possible to perform transparent fallback to certification validation using the system certificate store. + + + The approach described above works with OpenJDK 6 and later versions. Starting with OpenJDK 7, it is possible to use a custom subclass of the javax.net.ssl.X509ExtendedTrustManager class. The OpenJDK TLS implementation will call the new methods, passing along TLS session information. This can be used to implement certificate overrides as a fallback (if certificate or host name verification fails), and a trust manager object can be used for multiple servers because the server address is available to the trust manager. + + +
+ + +
+ +
+ Implementing TLS Clients With NSS + + The following code shows how to implement a simple TLS client using NSS. Note that the error handling needs replacing before production use. + + + Using NSS needs several header files, as shown in . + + + Include files for NSS + + + + + Initializing the NSS library is a complex task (). It is not thread-safe. By default, the library is in export mode, and all strong ciphers are disabled. Therefore, after creating the NSSInitCContext object, we probe all the strong ciphers we want to use, and check if at least one of them is available. If not, we call NSS_SetDomesticPolicy to switch to unrestricted policy mode. This function replaces the existing global cipher suite policy, that is why we avoid calling it unless absolutely necessary. + + + The simplest way to configured the trusted root certificates involves loading the libnssckbi.so NSS module with a call to the SECMOD_LoadUserModule function. The root certificates are compiled into this module. (The PEM module for NSS, libnsspem.so, offers a way to load trusted CA certificates from a file.) + + + Initializing the NSS library + + + + + Some of the effects of the initialization can be reverted with the following function calls: + + + + After NSS has been initialized, the TLS connection can be created (). The internal PR_ImportTCPSocket function is used to turn the POSIX file descriptor sockfd into an NSPR file descriptor. (This function is de-facto part of the NSS public ABI, so it will not go away.) Creating the TLS-capable file descriptor requires a model descriptor, which is configured with the desired set of protocols and ciphers. (The good_ciphers variable is part of .) We cannot resort to disabling ciphers not on a whitelist because by default, the AES cipher suites are disabled. The model descriptor is not needed anymore after TLS support has been activated for the existing connection descriptor. + + + The call to SSL_BadCertHook can be omitted if no mechanism to override certificate verification is needed. The bad_certificate function must check both the host name specified for the connection and the certificate before granting the override. + + + Triggering the actual handshake requires three function calls, SSL_ResetHandshake, SSL_SetURL, and SSL_ForceHandshake. (If SSL_ResetHandshake is omitted, SSL_ForceHandshake will succeed, but the data will not be encrypted.) During the handshake, the certificate is verified and matched against the host name. + + + Creating a TLS connection with NSS + + + + + After the connection has been established, shows how to use the NSPR descriptor to communicate with the server. + + + Using NSS for sending and receiving data + + + + + shows how to close the connection. + + + Closing NSS client connections + + + + +
+ +
+ Implementing TLS Clients With Python + + The Python distribution provides a TLS implementation in the ssl module (actually a wrapper around OpenSSL). The exported interface is somewhat restricted, so that the client code shown below does not fully implement the recommendations in . + + + + Currently, most Python function which accept https:// URLs or otherwise implement HTTPS support do not perform certificate validation at all. (For example, this is true for the httplib and xmlrpclib modules.) If you use HTTPS, you should not use the built-in HTTP clients. The Curl class in the curl module, as provided by the python-pycurl package implements proper certificate validation. + + + + + The ssl module currently does not perform host name checking on the server certificate. shows how to implement certificate matching, using the parsed certificate returned by getpeercert. + + + Implementing TLS host name checking Python (without wildcard support) + + + + + To turn a regular, connected TCP socket into a TLS-enabled socket, use the ssl.wrap_socket function. The function call in provides additional arguments to override questionable defaults in OpenSSL and in the Python module. + + + + + ciphers="HIGH:-aNULL:-eNULL:-PSK:RC4-SHA:RC4-MD5" selects relatively strong cipher suites with certificate-based authentication. (The call to check_host_name function provides additional protection against anonymous cipher suites.) + + + + + + ssl_version=ssl.PROTOCOL_TLSv1 disables SSL 2.0 support. By default, the ssl module sends an SSL 2.0 client hello, which is rejected by some servers. Ideally, we would request OpenSSL to negotiated the most recent TLS version supported by the server and the client, but the Python module does not allow this. + + + + + + cert_reqs=ssl.CERT_REQUIRED turns on certificate validation. + + + + + + ca_certs='/etc/ssl/certs/ca-bundle.crt' initializes the certificate store with a set of trusted root CAs. Unfortunately, it is necessary to hard-code this path into applications because the default path in OpenSSL is not available through the Python ssl module. + + + + + + + The ssl module (and OpenSSL) perform certificate validation, but the certificate must be compared manually against the host name, by calling the check_host_name defined above. + + + Establishing a TLS client connection with Python + + + + + After the connection has been established, the TLS socket can be used like a regular socket: + + + + Closing the TLS socket is straightforward as well: + + + +
+ + +
+ +
+ diff --git a/defensive-coding/tmp/en-US/xml/Features/schemas.xml b/defensive-coding/tmp/en-US/xml/Features/schemas.xml new file mode 100644 index 0000000..31581c3 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Features/schemas.xml @@ -0,0 +1,6 @@ + + +%BOOK_ENTITIES; +]> + diff --git a/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Client-GNUTLS-Connect.xml b/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Client-GNUTLS-Connect.xml new file mode 100644 index 0000000..9ff46c4 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Client-GNUTLS-Connect.xml @@ -0,0 +1,53 @@ + + +%BOOK_ENTITIES; +]> + + +// Create the session object. +gnutls_session_t session; +ret = gnutls_init(&session, GNUTLS_CLIENT); +if (ret != GNUTLS_E_SUCCESS) { + fprintf(stderr, "error: gnutls_init: %s\n", + gnutls_strerror(ret)); + exit(1); +} + +// Configure the cipher preferences. +const char *errptr = NULL; +ret = gnutls_priority_set_direct(session, "NORMAL", &errptr); +if (ret != GNUTLS_E_SUCCESS) { + fprintf(stderr, "error: gnutls_priority_set_direct: %s\n" + "error: at: \"%s\"\n", gnutls_strerror(ret), errptr); + exit(1); +} + +// Install the trusted certificates. +ret = gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, cred); +if (ret != GNUTLS_E_SUCCESS) { + fprintf(stderr, "error: gnutls_credentials_set: %s\n", + gnutls_strerror(ret)); + exit(1); +} + +// Associate the socket with the session object and set the server +// name. +gnutls_transport_set_ptr(session, (gnutls_transport_ptr_t)(uintptr_t)sockfd); +ret = gnutls_server_name_set(session, GNUTLS_NAME_DNS, + host, strlen(host)); +if (ret != GNUTLS_E_SUCCESS) { + fprintf(stderr, "error: gnutls_server_name_set: %s\n", + gnutls_strerror(ret)); + exit(1); +} + +// Establish the session. +ret = gnutls_handshake(session); +if (ret != GNUTLS_E_SUCCESS) { + fprintf(stderr, "error: gnutls_handshake: %s\n", + gnutls_strerror(ret)); + exit(1); +} + + diff --git a/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Client-GNUTLS-Credentials.xml b/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Client-GNUTLS-Credentials.xml new file mode 100644 index 0000000..1360058 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Client-GNUTLS-Credentials.xml @@ -0,0 +1,32 @@ + + +%BOOK_ENTITIES; +]> + + +// Load the trusted CA certificates. +gnutls_certificate_credentials_t cred = NULL; +int ret = gnutls_certificate_allocate_credentials (&cred); +if (ret != GNUTLS_E_SUCCESS) { + fprintf(stderr, "error: gnutls_certificate_allocate_credentials: %s\n", + gnutls_strerror(ret)); + exit(1); +} +// gnutls_certificate_set_x509_system_trust needs GNUTLS version 3.0 +// or newer, so we hard-code the path to the certificate store +// instead. +static const char ca_bundle[] = "/etc/ssl/certs/ca-bundle.crt"; +ret = gnutls_certificate_set_x509_trust_file + (cred, ca_bundle, GNUTLS_X509_FMT_PEM); +if (ret == 0) { + fprintf(stderr, "error: no certificates found in: %s\n", ca_bundle); + exit(1); +} +if (ret < 0) { + fprintf(stderr, "error: gnutls_certificate_set_x509_trust_files(%s): %s\n", + ca_bundle, gnutls_strerror(ret)); + exit(1); +} + + diff --git a/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Client-GNUTLS-Match.xml b/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Client-GNUTLS-Match.xml new file mode 100644 index 0000000..5b6a42e --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Client-GNUTLS-Match.xml @@ -0,0 +1,33 @@ + + +%BOOK_ENTITIES; +]> + + +// Match the peer certificate against the host name. +// We can only obtain a set of DER-encoded certificates from the +// session object, so we have to re-parse the peer certificate into +// a certificate object. +gnutls_x509_crt_t cert; +ret = gnutls_x509_crt_init(&cert); +if (ret != GNUTLS_E_SUCCESS) { + fprintf(stderr, "error: gnutls_x509_crt_init: %s\n", + gnutls_strerror(ret)); + exit(1); +} +// The peer certificate is the first certificate in the list. +ret = gnutls_x509_crt_import(cert, certs, GNUTLS_X509_FMT_DER); +if (ret != GNUTLS_E_SUCCESS) { + fprintf(stderr, "error: gnutls_x509_crt_import: %s\n", + gnutls_strerror(ret)); + exit(1); +} +ret = gnutls_x509_crt_check_hostname(cert, host); +if (ret == 0 && !certificate_host_name_override(certs[0], host)) { + fprintf(stderr, "error: host name does not match certificate\n"); + exit(1); +} +gnutls_x509_crt_deinit(cert); + + diff --git a/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Client-GNUTLS-Verify.xml b/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Client-GNUTLS-Verify.xml new file mode 100644 index 0000000..11dbb65 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Client-GNUTLS-Verify.xml @@ -0,0 +1,45 @@ + + +%BOOK_ENTITIES; +]> + + +// Obtain the server certificate chain. The server certificate +// itself is stored in the first element of the array. +unsigned certslen = 0; +const gnutls_datum_t *const certs = + gnutls_certificate_get_peers(session, &certslen); +if (certs == NULL || certslen == 0) { + fprintf(stderr, "error: could not obtain peer certificate\n"); + exit(1); +} + +// Validate the certificate chain. +unsigned status = (unsigned)-1; +ret = gnutls_certificate_verify_peers2(session, &status); +if (ret != GNUTLS_E_SUCCESS) { + fprintf(stderr, "error: gnutls_certificate_verify_peers2: %s\n", + gnutls_strerror(ret)); + exit(1); +} +if (status != 0 && !certificate_validity_override(certs[0])) { + gnutls_datum_t msg; +#if GNUTLS_VERSION_AT_LEAST_3_1_4 + int type = gnutls_certificate_type_get (session); + ret = gnutls_certificate_verification_status_print(status, type, &out, 0); +#else + ret = -1; +#endif + if (ret == 0) { + fprintf(stderr, "error: %s\n", msg.data); + gnutls_free(msg.data); + exit(1); + } else { + fprintf(stderr, "error: certificate validation failed with code 0x%x\n", + status); + exit(1); + } +} + + diff --git a/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Client-NSS-Close.xml b/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Client-NSS-Close.xml new file mode 100644 index 0000000..46dd372 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Client-NSS-Close.xml @@ -0,0 +1,18 @@ + + +%BOOK_ENTITIES; +]> + + +// Send close_notify alert. +if (PR_Shutdown(nspr, PR_SHUTDOWN_BOTH) != PR_SUCCESS) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: PR_Read error %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); +} +// Closes the underlying POSIX file descriptor, too. +PR_Close(nspr); + + diff --git a/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Client-NSS-Connect.xml b/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Client-NSS-Connect.xml new file mode 100644 index 0000000..5fea050 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Client-NSS-Connect.xml @@ -0,0 +1,109 @@ + + +%BOOK_ENTITIES; +]> + + +// Wrap the POSIX file descriptor. This is an internal NSPR +// function, but it is very unlikely to change. +PRFileDesc* nspr = PR_ImportTCPSocket(sockfd); +sockfd = -1; // Has been taken over by NSPR. + +// Add the SSL layer. +{ + PRFileDesc *model = PR_NewTCPSocket(); + PRFileDesc *newfd = SSL_ImportFD(NULL, model); + if (newfd == NULL) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: NSPR error code %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); + } + model = newfd; + newfd = NULL; + if (SSL_OptionSet(model, SSL_ENABLE_SSL2, PR_FALSE) != SECSuccess) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: set SSL_ENABLE_SSL2 error %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); + } + if (SSL_OptionSet(model, SSL_V2_COMPATIBLE_HELLO, PR_FALSE) != SECSuccess) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: set SSL_V2_COMPATIBLE_HELLO error %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); + } + if (SSL_OptionSet(model, SSL_ENABLE_DEFLATE, PR_FALSE) != SECSuccess) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: set SSL_ENABLE_DEFLATE error %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); + } + + // Disable all ciphers (except RC4-based ciphers, for backwards + // compatibility). + const PRUint16 *const ciphers = SSL_GetImplementedCiphers(); + for (unsigned i = 0; i < SSL_GetNumImplementedCiphers(); i++) { + if (ciphers[i] != SSL_RSA_WITH_RC4_128_SHA + && ciphers[i] != SSL_RSA_WITH_RC4_128_MD5) { + if (SSL_CipherPrefSet(model, ciphers[i], PR_FALSE) != SECSuccess) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: disable cipher %u: error %d: %s\n", + (unsigned)ciphers[i], err, PR_ErrorToName(err)); + exit(1); + } + } + } + + // Enable the strong ciphers. + for (const PRUint16 *p = good_ciphers; *p != SSL_NULL_WITH_NULL_NULL; + ++p) { + if (SSL_CipherPrefSet(model, *p, PR_TRUE) != SECSuccess) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: enable cipher %u: error %d: %s\n", + (unsigned)*p, err, PR_ErrorToName(err)); + exit(1); + } + } + + // Allow overriding invalid certificate. + if (SSL_BadCertHook(model, bad_certificate, (char *)host) != SECSuccess) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: SSL_BadCertHook error %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); + } + + newfd = SSL_ImportFD(model, nspr); + if (newfd == NULL) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: SSL_ImportFD error %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); + } + nspr = newfd; + PR_Close(model); +} + +// Perform the handshake. +if (SSL_ResetHandshake(nspr, PR_FALSE) != SECSuccess) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: SSL_ResetHandshake error %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); +} +if (SSL_SetURL(nspr, host) != SECSuccess) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: SSL_SetURL error %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); +} +if (SSL_ForceHandshake(nspr) != SECSuccess) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: SSL_ForceHandshake error %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); +} + + diff --git a/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Client-OpenJDK-Connect.xml b/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Client-OpenJDK-Connect.xml new file mode 100644 index 0000000..96024e6 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Client-OpenJDK-Connect.xml @@ -0,0 +1,29 @@ + + +%BOOK_ENTITIES; +]> + + +// Create the socket and connect it at the TCP layer. +SSLSocket socket = (SSLSocket) ctx.getSocketFactory() + .createSocket(host, port); + +// Disable the Nagle algorithm. +socket.setTcpNoDelay(true); + +// Adjust ciphers and protocols. +socket.setSSLParameters(params); + +// Perform the handshake. +socket.startHandshake(); + +// Validate the host name. The match() method throws +// CertificateException on failure. +X509Certificate peer = (X509Certificate) + socket.getSession().getPeerCertificates()[0]; +// This is the only way to perform host name checking on OpenJDK 6. +HostnameChecker.getInstance(HostnameChecker.TYPE_TLS).match( + host, peer); + + diff --git a/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Client-OpenJDK-Context.xml b/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Client-OpenJDK-Context.xml new file mode 100644 index 0000000..523b156 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Client-OpenJDK-Context.xml @@ -0,0 +1,29 @@ + + +%BOOK_ENTITIES; +]> + + +// Create the context. Specify the SunJSSE provider to avoid +// picking up third-party providers. Try the TLS 1.2 provider +// first, then fall back to TLS 1.0. +SSLContext ctx; +try { + ctx = SSLContext.getInstance("TLSv1.2", "SunJSSE"); +} catch (NoSuchAlgorithmException e) { + try { + ctx = SSLContext.getInstance("TLSv1", "SunJSSE"); + } catch (NoSuchAlgorithmException e1) { + // The TLS 1.0 provider should always be available. + throw new AssertionError(e1); + } catch (NoSuchProviderException e1) { + throw new AssertionError(e1); + } +} catch (NoSuchProviderException e) { + // The SunJSSE provider should always be available. + throw new AssertionError(e); +} +ctx.init(null, null, null); + + diff --git a/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Client-OpenJDK-Context_For_Cert.xml b/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Client-OpenJDK-Context_For_Cert.xml new file mode 100644 index 0000000..efc38b1 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Client-OpenJDK-Context_For_Cert.xml @@ -0,0 +1,25 @@ + + +%BOOK_ENTITIES; +]> + + +SSLContext ctx; +try { + ctx = SSLContext.getInstance("TLSv1.2", "SunJSSE"); +} catch (NoSuchAlgorithmException e) { + try { + ctx = SSLContext.getInstance("TLSv1", "SunJSSE"); + } catch (NoSuchAlgorithmException e1) { + throw new AssertionError(e1); + } catch (NoSuchProviderException e1) { + throw new AssertionError(e1); + } +} catch (NoSuchProviderException e) { + throw new AssertionError(e); +} +MyTrustManager tm = new MyTrustManager(certHash); +ctx.init(null, new TrustManager[] {tm}, null); + + diff --git a/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Client-OpenJDK-Hostname.xml b/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Client-OpenJDK-Hostname.xml new file mode 100644 index 0000000..a32d143 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Client-OpenJDK-Hostname.xml @@ -0,0 +1,10 @@ + + +%BOOK_ENTITIES; +]> + + +params.setEndpointIdentificationAlgorithm("HTTPS"); + + diff --git a/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Client-OpenJDK-Import.xml b/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Client-OpenJDK-Import.xml new file mode 100644 index 0000000..20bab18 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Client-OpenJDK-Import.xml @@ -0,0 +1,21 @@ + + +%BOOK_ENTITIES; +]> + + +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.cert.CertificateEncodingException; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLParameters; +import javax.net.ssl.SSLSocket; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; + +import sun.security.util.HostnameChecker; + + diff --git a/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Client-OpenJDK-MyTrustManager.xml b/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Client-OpenJDK-MyTrustManager.xml new file mode 100644 index 0000000..539603c --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Client-OpenJDK-MyTrustManager.xml @@ -0,0 +1,41 @@ + + +%BOOK_ENTITIES; +]> + + +public class MyTrustManager implements X509TrustManager { + private final byte[] certHash; + + public MyTrustManager(byte[] certHash) throws Exception { + this.certHash = certHash; + } + + @Override + public void checkClientTrusted(X509Certificate[] chain, String authType) + throws CertificateException { + throw new UnsupportedOperationException(); + } + + @Override + public void checkServerTrusted(X509Certificate[] chain, + String authType) throws CertificateException { + byte[] digest = getCertificateDigest(chain[0]); + String digestHex = formatHex(digest); + + if (Arrays.equals(digest, certHash)) { + System.err.println("info: accepting certificate: " + digestHex); + } else { + throw new CertificateException("certificate rejected: " + + digestHex); + } + } + + @Override + public X509Certificate[] getAcceptedIssuers() { + return new X509Certificate[0]; + } +} + + diff --git a/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Client-OpenJDK-Use.xml b/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Client-OpenJDK-Use.xml new file mode 100644 index 0000000..f31033d --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Client-OpenJDK-Use.xml @@ -0,0 +1,14 @@ + + +%BOOK_ENTITIES; +]> + + +socket.getOutputStream().write("GET / HTTP/1.0\r\n\r\n" + .getBytes(Charset.forName("UTF-8"))); +byte[] buffer = new byte[4096]; +int count = socket.getInputStream().read(buffer); +System.out.write(buffer, 0, count); + + diff --git a/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Client-OpenSSL-CTX.xml b/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Client-OpenSSL-CTX.xml new file mode 100644 index 0000000..7a9ac3e --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Client-OpenSSL-CTX.xml @@ -0,0 +1,74 @@ + + +%BOOK_ENTITIES; +]> + + +// Configure a client connection context. Send a hendshake for the +// highest supported TLS version, and disable compression. +const SSL_METHOD *const req_method = SSLv23_client_method(); +SSL_CTX *const ctx = SSL_CTX_new(req_method); +if (ctx == NULL) { + ERR_print_errors(bio_err); + exit(1); +} +SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_COMPRESSION); + +// Adjust the ciphers list based on a whitelist. First enable all +// ciphers of at least medium strength, to get the list which is +// compiled into OpenSSL. +if (SSL_CTX_set_cipher_list(ctx, "HIGH:MEDIUM") != 1) { + ERR_print_errors(bio_err); + exit(1); +} +{ + // Create a dummy SSL session to obtain the cipher list. + SSL *ssl = SSL_new(ctx); + if (ssl == NULL) { + ERR_print_errors(bio_err); + exit(1); + } + STACK_OF(SSL_CIPHER) *active_ciphers = SSL_get_ciphers(ssl); + if (active_ciphers == NULL) { + ERR_print_errors(bio_err); + exit(1); + } + // Whitelist of candidate ciphers. + static const char *const candidates[] = { + "AES128-GCM-SHA256", "AES128-SHA256", "AES256-SHA256", // strong ciphers + "AES128-SHA", "AES256-SHA", // strong ciphers, also in older versions + "RC4-SHA", "RC4-MD5", // backwards compatibility, supposed to be weak + "DES-CBC3-SHA", "DES-CBC3-MD5", // more backwards compatibility + NULL + }; + // Actually selected ciphers. + char ciphers[300]; + ciphers[0] = '\0'; + for (const char *const *c = candidates; *c; ++c) { + for (int i = 0; i < sk_SSL_CIPHER_num(active_ciphers); ++i) { + if (strcmp(SSL_CIPHER_get_name(sk_SSL_CIPHER_value(active_ciphers, i)), + *c) == 0) { + if (*ciphers) { + strcat(ciphers, ":"); + } + strcat(ciphers, *c); + break; + } + } + } + SSL_free(ssl); + // Apply final cipher list. + if (SSL_CTX_set_cipher_list(ctx, ciphers) != 1) { + ERR_print_errors(bio_err); + exit(1); + } +} + +// Load the set of trusted root certificates. +if (!SSL_CTX_set_default_verify_paths(ctx)) { + ERR_print_errors(bio_err); + exit(1); +} + + diff --git a/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Client-OpenSSL-Connect.xml b/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Client-OpenSSL-Connect.xml new file mode 100644 index 0000000..5f74292 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Client-OpenSSL-Connect.xml @@ -0,0 +1,58 @@ + + +%BOOK_ENTITIES; +]> + + +// Create the connection object. +SSL *ssl = SSL_new(ctx); +if (ssl == NULL) { + ERR_print_errors(bio_err); + exit(1); +} +SSL_set_fd(ssl, sockfd); + +// Enable the ServerNameIndication extension +if (!SSL_set_tlsext_host_name(ssl, host)) { + ERR_print_errors(bio_err); + exit(1); +} + +// Perform the TLS handshake with the server. +ret = SSL_connect(ssl); +if (ret != 1) { + // Error status can be 0 or negative. + ssl_print_error_and_exit(ssl, "SSL_connect", ret); +} + +// Obtain the server certificate. +X509 *peercert = SSL_get_peer_certificate(ssl); +if (peercert == NULL) { + fprintf(stderr, "peer certificate missing"); + exit(1); +} + +// Check the certificate verification result. Allow an explicit +// certificate validation override in case verification fails. +int verifystatus = SSL_get_verify_result(ssl); +if (verifystatus != X509_V_OK && !certificate_validity_override(peercert)) { + fprintf(stderr, "SSL_connect: verify result: %s\n", + X509_verify_cert_error_string(verifystatus)); + exit(1); +} + +// Check if the server certificate matches the host name used to +// establish the connection. +// FIXME: Currently needs OpenSSL 1.1. +if (X509_check_host(peercert, (const unsigned char *)host, strlen(host), + 0) != 1 + && !certificate_host_name_override(peercert, host)) { + fprintf(stderr, "SSL certificate does not match host name\n"); + exit(1); +} + +X509_free(peercert); + + + diff --git a/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Client-OpenSSL-Connection-Use.xml b/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Client-OpenSSL-Connection-Use.xml new file mode 100644 index 0000000..eb0ca16 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Client-OpenSSL-Connection-Use.xml @@ -0,0 +1,18 @@ + + +%BOOK_ENTITIES; +]> + + +const char *const req = "GET / HTTP/1.0\r\n\r\n"; +if (SSL_write(ssl, req, strlen(req)) < 0) { + ssl_print_error_and_exit(ssl, "SSL_write", ret); +} +char buf[4096]; +ret = SSL_read(ssl, buf, sizeof(buf)); +if (ret < 0) { + ssl_print_error_and_exit(ssl, "SSL_read", ret); +} + + diff --git a/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Client-OpenSSL-Init.xml b/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Client-OpenSSL-Init.xml new file mode 100644 index 0000000..9750b5c --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Client-OpenSSL-Init.xml @@ -0,0 +1,16 @@ + + +%BOOK_ENTITIES; +]> + + +// The following call prints an error message and calls exit() if +// the OpenSSL configuration file is unreadable. +OPENSSL_config(NULL); +// Provide human-readable error messages. +SSL_load_error_strings(); +// Register ciphers. +SSL_library_init(); + + diff --git a/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Client-Python-Connect.xml b/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Client-Python-Connect.xml new file mode 100644 index 0000000..c0e0395 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Client-Python-Connect.xml @@ -0,0 +1,17 @@ + + +%BOOK_ENTITIES; +]> + + +sock = ssl.wrap_socket(sock, + ciphers="HIGH:-aNULL:-eNULL:-PSK:RC4-SHA:RC4-MD5", + ssl_version=ssl.PROTOCOL_TLSv1, + cert_reqs=ssl.CERT_REQUIRED, + ca_certs='/etc/ssl/certs/ca-bundle.crt') +# getpeercert() triggers the handshake as a side effect. +if not check_host_name(sock.getpeercert(), host): + raise IOError("peer certificate does not match host name") + + diff --git a/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Client-Python-check_host_name.xml b/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Client-Python-check_host_name.xml new file mode 100644 index 0000000..0e22858 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Client-Python-check_host_name.xml @@ -0,0 +1,32 @@ + + +%BOOK_ENTITIES; +]> + + +def check_host_name(peercert, name): + """Simple certificate/host name checker. Returns True if the + certificate matches, False otherwise. Does not support + wildcards.""" + # Check that the peer has supplied a certificate. + # None/{} is not acceptable. + if not peercert: + return False + if peercert.has_key("subjectAltName"): + for typ, val in peercert["subjectAltName"]: + if typ == "DNS" and val == name: + return True + else: + # Only check the subject DN if there is no subject alternative + # name. + cn = None + for attr, val in peercert["subject"]: + # Use most-specific (last) commonName attribute. + if attr == "commonName": + cn = val + if cn is not None: + return cn == name + return False + + diff --git a/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-GNUTLS-Credentials-Close.xml b/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-GNUTLS-Credentials-Close.xml new file mode 100644 index 0000000..e0170b1 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-GNUTLS-Credentials-Close.xml @@ -0,0 +1,10 @@ + + +%BOOK_ENTITIES; +]> + + +gnutls_certificate_free_credentials(cred); + + diff --git a/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-GNUTLS-Disconnect.xml b/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-GNUTLS-Disconnect.xml new file mode 100644 index 0000000..9a18ea7 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-GNUTLS-Disconnect.xml @@ -0,0 +1,17 @@ + + +%BOOK_ENTITIES; +]> + + +// Initiate an orderly connection shutdown. +ret = gnutls_bye(session, GNUTLS_SHUT_RDWR); +if (ret < 0) { + fprintf(stderr, "error: gnutls_bye: %s\n", gnutls_strerror(ret)); + exit(1); +} +// Free the session object. +gnutls_deinit(session); + + diff --git a/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-GNUTLS-Init.xml b/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-GNUTLS-Init.xml new file mode 100644 index 0000000..2842eaf --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-GNUTLS-Init.xml @@ -0,0 +1,10 @@ + + +%BOOK_ENTITIES; +]> + + +gnutls_global_init(); + + diff --git a/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-GNUTLS-Use.xml b/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-GNUTLS-Use.xml new file mode 100644 index 0000000..f67cc61 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-GNUTLS-Use.xml @@ -0,0 +1,21 @@ + + +%BOOK_ENTITIES; +]> + + +char buf[4096]; +snprintf(buf, sizeof(buf), "GET / HTTP/1.0\r\nHost: %s\r\n\r\n", host); +ret = gnutls_record_send(session, buf, strlen(buf)); +if (ret < 0) { + fprintf(stderr, "error: gnutls_record_send: %s\n", gnutls_strerror(ret)); + exit(1); +} +ret = gnutls_record_recv(session, buf, sizeof(buf)); +if (ret < 0) { + fprintf(stderr, "error: gnutls_record_recv: %s\n", gnutls_strerror(ret)); + exit(1); +} + + diff --git a/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-NSS-Close.xml b/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-NSS-Close.xml new file mode 100644 index 0000000..74bb39d --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-NSS-Close.xml @@ -0,0 +1,11 @@ + + +%BOOK_ENTITIES; +]> + + +SECMOD_DestroyModule(module); +NSS_ShutdownContext(ctx); + + diff --git a/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-NSS-Includes.xml b/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-NSS-Includes.xml new file mode 100644 index 0000000..ec955dd --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-NSS-Includes.xml @@ -0,0 +1,23 @@ + + +%BOOK_ENTITIES; +]> + + +// NSPR include files +#include <prerror.h> +#include <prinit.h> + +// NSS include files +#include <nss.h> +#include <pk11pub.h> +#include <secmod.h> +#include <ssl.h> +#include <sslproto.h> + +// Private API, no other way to turn a POSIX file descriptor into an +// NSPR handle. +NSPR_API(PRFileDesc*) PR_ImportTCPSocket(int); + + diff --git a/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-NSS-Init.xml b/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-NSS-Init.xml new file mode 100644 index 0000000..f7ee2ef --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-NSS-Init.xml @@ -0,0 +1,66 @@ + + +%BOOK_ENTITIES; +]> + + +PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); +NSSInitContext *const ctx = + NSS_InitContext("sql:/etc/pki/nssdb", "", "", "", NULL, + NSS_INIT_READONLY | NSS_INIT_PK11RELOAD); +if (ctx == NULL) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: NSPR error code %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); +} + +// Ciphers to enable. +static const PRUint16 good_ciphers[] = { + TLS_RSA_WITH_AES_128_CBC_SHA, + TLS_RSA_WITH_AES_256_CBC_SHA, + SSL_RSA_WITH_3DES_EDE_CBC_SHA, + SSL_NULL_WITH_NULL_NULL // sentinel +}; + +// Check if the current policy allows any strong ciphers. If it +// doesn't, switch to the "domestic" (unrestricted) policy. This is +// not thread-safe and has global impact. Consequently, we only do +// it if absolutely necessary. +int found_good_cipher = 0; +for (const PRUint16 *p = good_ciphers; *p != SSL_NULL_WITH_NULL_NULL; + ++p) { + PRInt32 policy; + if (SSL_CipherPolicyGet(*p, &policy) != SECSuccess) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: policy for cipher %u: error %d: %s\n", + (unsigned)*p, err, PR_ErrorToName(err)); + exit(1); + } + if (policy == SSL_ALLOWED) { + fprintf(stderr, "info: found cipher %x\n", (unsigned)*p); + found_good_cipher = 1; + break; + } +} +if (!found_good_cipher) { + if (NSS_SetDomesticPolicy() != SECSuccess) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: NSS_SetDomesticPolicy: error %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); + } +} + +// Initialize the trusted certificate store. +char module_name[] = "library=libnssckbi.so name=\"Root Certs\""; +SECMODModule *module = SECMOD_LoadUserModule(module_name, NULL, PR_FALSE); +if (module == NULL || !module->loaded) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: NSPR error code %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); +} + + diff --git a/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-NSS-Use.xml b/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-NSS-Use.xml new file mode 100644 index 0000000..c3b3faf --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-NSS-Use.xml @@ -0,0 +1,25 @@ + + +%BOOK_ENTITIES; +]> + + +char buf[4096]; +snprintf(buf, sizeof(buf), "GET / HTTP/1.0\r\nHost: %s\r\n\r\n", host); +PRInt32 ret = PR_Write(nspr, buf, strlen(buf)); +if (ret < 0) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: PR_Write error %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); +} +ret = PR_Read(nspr, buf, sizeof(buf)); +if (ret < 0) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: PR_Read error %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); +} + + diff --git a/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Nagle.xml b/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Nagle.xml new file mode 100644 index 0000000..2dbf3de --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Nagle.xml @@ -0,0 +1,15 @@ + + +%BOOK_ENTITIES; +]> + + +const int val = 1; +int ret = setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val)); +if (ret < 0) { + perror("setsockopt(TCP_NODELAY)"); + exit(1); +} + + diff --git a/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-OpenJDK-Parameters.xml b/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-OpenJDK-Parameters.xml new file mode 100644 index 0000000..178978f --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-OpenJDK-Parameters.xml @@ -0,0 +1,30 @@ + + +%BOOK_ENTITIES; +]> + + +// Prepare TLS parameters. These have to applied to every TLS +// socket before the handshake is triggered. +SSLParameters params = ctx.getDefaultSSLParameters(); +// Do not send an SSL-2.0-compatible Client Hello. +ArrayList<String> protocols = new ArrayList<String>( + Arrays.asList(params.getProtocols())); +protocols.remove("SSLv2Hello"); +params.setProtocols(protocols.toArray(new String[protocols.size()])); +// Adjust the supported ciphers. +ArrayList<String> ciphers = new ArrayList<String>( + Arrays.asList(params.getCipherSuites())); +ciphers.retainAll(Arrays.asList( + "TLS_RSA_WITH_AES_128_CBC_SHA256", + "TLS_RSA_WITH_AES_256_CBC_SHA256", + "TLS_RSA_WITH_AES_256_CBC_SHA", + "TLS_RSA_WITH_AES_128_CBC_SHA", + "SSL_RSA_WITH_3DES_EDE_CBC_SHA", + "SSL_RSA_WITH_RC4_128_SHA1", + "SSL_RSA_WITH_RC4_128_MD5", + "TLS_EMPTY_RENEGOTIATION_INFO_SCSV")); +params.setCipherSuites(ciphers.toArray(new String[ciphers.size()])); + + diff --git a/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-OpenSSL-Connection-Close.xml b/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-OpenSSL-Connection-Close.xml new file mode 100644 index 0000000..c2c507e --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-OpenSSL-Connection-Close.xml @@ -0,0 +1,33 @@ + + +%BOOK_ENTITIES; +]> + + +// Send the close_notify alert. +ret = SSL_shutdown(ssl); +switch (ret) { +case 1: + // A close_notify alert has already been received. + break; +case 0: + // Wait for the close_notify alert from the peer. + ret = SSL_shutdown(ssl); + switch (ret) { + case 0: + fprintf(stderr, "info: second SSL_shutdown returned zero\n"); + break; + case 1: + break; + default: + ssl_print_error_and_exit(ssl, "SSL_shutdown 2", ret); + } + break; +default: + ssl_print_error_and_exit(ssl, "SSL_shutdown 1", ret); +} +SSL_free(ssl); +close(sockfd); + + diff --git a/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-OpenSSL-Context-Close.xml b/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-OpenSSL-Context-Close.xml new file mode 100644 index 0000000..f74338d --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-OpenSSL-Context-Close.xml @@ -0,0 +1,10 @@ + + +%BOOK_ENTITIES; +]> + + +SSL_CTX_free(ctx); + + diff --git a/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-OpenSSL-Errors.xml b/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-OpenSSL-Errors.xml new file mode 100644 index 0000000..68c3668 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-OpenSSL-Errors.xml @@ -0,0 +1,34 @@ + + +%BOOK_ENTITIES; +]> + + +static void __attribute__((noreturn)) +ssl_print_error_and_exit(SSL *ssl, const char *op, int ret) +{ + int subcode = SSL_get_error(ssl, ret); + switch (subcode) { + case SSL_ERROR_NONE: + fprintf(stderr, "error: %s: no error to report\n", op); + break; + case SSL_ERROR_WANT_READ: + case SSL_ERROR_WANT_WRITE: + case SSL_ERROR_WANT_X509_LOOKUP: + case SSL_ERROR_WANT_CONNECT: + case SSL_ERROR_WANT_ACCEPT: + fprintf(stderr, "error: %s: invalid blocking state %d\n", op, subcode); + break; + case SSL_ERROR_SSL: + fprintf(stderr, "error: %s: TLS layer problem\n", op); + case SSL_ERROR_SYSCALL: + fprintf(stderr, "error: %s: system call failed: %s\n", op, strerror(errno)); + break; + case SSL_ERROR_ZERO_RETURN: + fprintf(stderr, "error: %s: zero return\n", op); + } + exit(1); +} + + diff --git a/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Python-Close.xml b/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Python-Close.xml new file mode 100644 index 0000000..8820cef --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Python-Close.xml @@ -0,0 +1,10 @@ + + +%BOOK_ENTITIES; +]> + + +sock.close() + + diff --git a/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Python-Use.xml b/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Python-Use.xml new file mode 100644 index 0000000..cef5941 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Features/snippets/TLS-Python-Use.xml @@ -0,0 +1,11 @@ + + +%BOOK_ENTITIES; +]> + + +sock.write("GET / HTTP/1.1\r\nHost: " + host + "\r\n\r\n") +print sock.read() + + diff --git a/defensive-coding/tmp/en-US/xml/Python/Language.xml b/defensive-coding/tmp/en-US/xml/Python/Language.xml new file mode 100644 index 0000000..3700f39 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Python/Language.xml @@ -0,0 +1,92 @@ + + +%BOOK_ENTITIES; +]> + + The Python Programming Language + + Python provides memory safety by default, so low-level security vulnerabilities are rare and typically needs fixing the Python interpreter or standard library itself. + + + Other sections with Python-specific advice include: + + + + + + + + + + + + + + + + + , in particular + + + + + + + + + + + +
+ Dangerous standard library features + + Some areas of the standard library, notably the ctypes module, do not provide memory safety guarantees comparable to the rest of Python. If such functionality is used, the advice in should be followed. + + +
+ +
+ Run-time compilation and code generation + + The following Python functions and statements related to code execution should be avoided: + + + + + compile + + + + + eval + + + + + exec + + + + + execfile + + + + + + If you need to parse integers or floating point values, use the int and float functions instead of eval. Sandboxing untrusted Python code does not work reliably. + + +
+ +
+ Sandboxing + + The rexec Python module cannot safely sandbox untrusted code and should not be used. The standard CPython implementation is not suitable for sandboxing. + + +
+ +
+ diff --git a/defensive-coding/tmp/en-US/xml/Python/schemas.xml b/defensive-coding/tmp/en-US/xml/Python/schemas.xml new file mode 100644 index 0000000..31581c3 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Python/schemas.xml @@ -0,0 +1,6 @@ + + +%BOOK_ENTITIES; +]> + diff --git a/defensive-coding/tmp/en-US/xml/Revision_History.xml b/defensive-coding/tmp/en-US/xml/Revision_History.xml new file mode 100644 index 0000000..366debc --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Revision_History.xml @@ -0,0 +1,33 @@ + + +%BOOK_ENTITIES; +]> + + Revision History + + + + 0-1 + Thu Mar 7 2013 + + Eric + Christensen + sparks@redhat.com + + + + + Initial publication. + + + + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/xml/Tasks/Cryptography.xml b/defensive-coding/tmp/en-US/xml/Tasks/Cryptography.xml new file mode 100644 index 0000000..ac00335 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Tasks/Cryptography.xml @@ -0,0 +1,158 @@ + + +%BOOK_ENTITIES; +]> + + Cryptography +
+ Primitives + + Chosing from the following cryptographic primitives is recommended: + + + + + RSA with 2048 bit keys and OAEP + + + + + AES-128 in CBC mode + + + + + SHA-256 + + + + + HMAC-SHA-256 + + + + + HMAC-SHA-1 + + + + + + Other cryptographic algorithms can be used if they are required for interoperability with existing software: + + + + + RSA with key sizes larger than 1024 and legacy padding + + + + + AES-192 + + + + + AES-256 + + + + + 3DES (triple DES, with two or three 56 bit keys) + + + + + RC4 (but very, very strongly discouraged) + + + + + SHA-1 + + + + + HMAC-MD5 + + + + + + Important + + These primitives are difficult to use in a secure way. Custom implementation of security protocols should be avoided. For protecting confidentiality and integrity of network transmissions, TLS should be used (). + + + + +
+ +
+ Randomness + + The following facilities can be used to generate unpredictable and non-repeating values. When these functions are used without special safeguards, each individual rnadom value should be at least 12 bytes long. + + + + + PK11_GenerateRandom in the NSS library (usable for high data rates) + + + + + + RAND_bytes in the OpenSSL library (usable for high data rates) + + + + + + gnutls_rnd in GNUTLS, with GNUTLS_RND_RANDOM as the first argument (usable for high data rates) + + + + + + java.security.SecureRandom in Java (usable for high data rates) + + + + + + os.urandom in Python + + + + + + Reading from the /dev/urandom character device + + + + + + + All these functions should be non-blocking, and they should not wait until physical randomness becomes available. (Some cryptography providers for Java can cause java.security.SecureRandom to block, however.) Those functions which do not obtain all bits directly from /dev/urandom are suitable for high data rates because they do not deplete the system-wide entropy pool. + + + Difficult to use API + + Both RAND_bytes and PK11_GenerateRandom have three-state return values (with conflicting meanings). Careful error checking is required. Please review the documentation when using these functions. + + + + + Other sources of randomness should be considered predictable. + + + Generating randomness for cryptographic keys in long-term use may need different steps and is best left to cryptographic libraries. + + +
+ + +
+ diff --git a/defensive-coding/tmp/en-US/xml/Tasks/Descriptors.xml b/defensive-coding/tmp/en-US/xml/Tasks/Descriptors.xml new file mode 100644 index 0000000..fe273df --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Tasks/Descriptors.xml @@ -0,0 +1,154 @@ + + +%BOOK_ENTITIES; +]> + + File Descriptor Management + + File descriptors underlie all input/output mechanisms offered by the system. They are used to implementation the FILE *-based functions found in <stdio.h>, and all the file and network communication facilities provided by the Python and Java environments are eventually implemented in them. + + + File descriptors are small, non-negative integers in userspace, and are backed on the kernel side with complicated data structures which can sometimes grow very large. + +
+ Closing descriptors + + If a descriptor is no longer used by a program and is not closed explicitly, its number cannot be reused (which is problematic in itself, see ), and the kernel resources are not freed. Therefore, it is important to close all descriptors at the earlierst point in time possible, but not earlier. + +
+ Error handling during descriptor close + + The close system call is always successful in the sense that the passed file descriptor is never valid after the function has been called. However, close still can return an error, for example if there was a file system failure. But this error is not very useful because the absence of an error does not mean that all caches have been emptied and previous writes have been made durable. Programs which need such guarantees must open files with O_SYNC or use fsync or fdatasync, and may also have to fsync the directory containing the file. + + +
+ +
+ Closing descriptors and race conditions + + Unlike process IDs, which are recycle only gradually, the kernel always allocates the lowest unused file descriptor when a new descriptor is created. This means that in a multi-threaded program which constantly opens and closes file descriptors, descriptors are reused very quickly. Unless descriptor closing and other operations on the same file descriptor are synchronized (typically, using a mutex), there will be race coniditons and I/O operations will be applied to the wrong file descriptor. + + + Sometimes, it is necessary to close a file descriptor concurrently, while another thread might be about to use it in a system call. In order to support this, a program needs to create a single special file descriptor, one on which all I/O operations fail. One way to achieve this is to use socketpair, close one of the descriptors, and call shutdown(fd, SHUTRDWR) on the other. + + + When a descriptor is closed concurrently, the program does not call close on the descriptor. Instead it program uses dup2 to replace the descriptor to be closed with the dummy descriptor created earlier. This way, the kernel will not reuse the descriptor, but it will carry out all other steps associated with calling a descriptor (for instance, if the descriptor refers to a stream socket, the peer will be notified). + + + This is just a sketch, and many details are missing. Additional data structures are needed to determine when it is safe to really close the descriptor, and proper locking is required for that. + + +
+ +
+ Lingering state after close + + By default, closing a stream socket returns immediately, and the kernel will try to send the data in the background. This means that it is impossible to implement accurate accounting of network-related resource utilization from userspace. + + + The SO_LINGER socket option alters the behavior of close, so that it will return only after the lingering data has been processed, either by sending it to the peer successfully, or by discarding it after the configured timeout. However, there is no interface which could perform this operation in the background, so a separate userspace thread is needed for each close call, causing scalability issues. + + + Currently, there is no application-level countermeasure which applies universally. Mitigation is possible with iptables (the connlimit match type in particular) and specialized filtering devices for denial-of-service network traffic. + + + These problems are not related to the TIME_WAIT state commonly seen in netstat output. The kernel automatically expires such sockets if necessary. + + +
+ + +
+ +
+ Preventing file descriptor leaks to child processes + + Child processes created with fork share the initial set of file descriptors with their parent process. By default, file descriptors are also preserved if a new process image is created with execve (or any of the other functions such as system or posix_spawn). + + + Usually, this behavior is not desirable. There are two ways to turn it off, that is, to prevent new process images from inheriting the file descriptors in the parent process: + + + + + Set the close-on-exec flag on all newly created file descriptors. Traditionally, this flag is controlled by the FD_CLOEXEC flag, using F_GETFD and F_SETFD operations of the fcntl function. + + + However, in a multi-threaded process, there is a race condition: a subprocess could have been created between the time the descriptor was created and the FD_CLOEXEC was set. Therefore, many system calls which create descriptors (such as open and openat) now accept the O_CLOEXEC flag (SOCK_CLOEXEC for socket and socketpair), which cause the FD_CLOEXEC flag to be set for the file descriptor in an atomic fashion. In addition, a few new systems calls were introduced, such as pipe2 and dup3. + + + The downside of this approach is that every descriptor needs to receive special treatment at the time of creation, otherwise it is not completely effective. + + + + + + After calling fork, but before creating a new process image with execve, all file descriptors which the child process will not need are closed. + + + Traditionally, this was implemented as a loop over file descriptors ranging from 3 to 255 and later 1023. But this is only an approximatio because it is possible to create file descriptors outside this range easily (see ). Another approach reads /proc/self/fd and closes the unexpected descriptors listed there, but this approach is much slower. + + + + + + + At present, environments which care about file descriptor leakage implement the second approach. OpenJDK 6 and 7 are among them. + + +
+ +
+ Dealing with the <function>select</function> limit + + By default, a user is allowed to open only 1024 files in a single process, but the system administrator can easily change this limit (which is necessary for busy network servers). However, there is another restriction which is more difficult to overcome. + + + The select function only supports a maximum of FD_SETSIZE file descriptors (that is, the maximum permitted value for a file descriptor is FD_SETSIZE - 1, usually 1023.) If a process opens many files, descriptors may exceed such limits. It is impossible to query such descriptors using select. + + + If a library which creates many file descriptors is used in the same process as a library which uses select, at least one of them needs to be changed. Calls to select can be replaced with calls to poll or another event handling mechanism. + + + Alternatively, the library with high descriptor usage can relocate descriptors above the FD_SETSIZE limit using the following procedure. + + + + + Create the file descriptor fd as usual, preferably with the O_CLOEXEC flag. + + + + + + Before doing anything else with the descriptor fd, invoke: + + + + int newfd = fcntl(fd, F_DUPFD_CLOEXEC, (long)FD_SETSIZE); + + + + + + Check that newfd result is non-negative, otherwise close fd and report an error, and return. + + + + + + Close fd and continue to use newfd. + + + + + + + The new descriptor has been allocated above the FD_SETSIZE. Even though this algorithm is racy in the sense that the FD_SETSIZE first descriptors could fill up, a very high degree of physical parallelism is required before this becomes a problem. + + +
+ +
+ diff --git a/defensive-coding/tmp/en-US/xml/Tasks/File_System.xml b/defensive-coding/tmp/en-US/xml/Tasks/File_System.xml new file mode 100644 index 0000000..644c570 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Tasks/File_System.xml @@ -0,0 +1,196 @@ + + +%BOOK_ENTITIES; +]> + + File system manipulation + + In this chapter, we discuss general file system manipulation, with a focus on access files and directories to which an other, potentially untrusted user has write access. + + + Temporary files are covered in their own chapter, . + +
+ Working with files and directories owned by other users + + Sometimes, it is necessary to operate on files and directories owned by other (potentially untrusted) users. For example, a system administrator could remove the home directory of a user, or a package manager could update a file in a directory which is owned by an application-specific user. This differs from accessing the file system as a specific user; see . + + + Accessing files across trust boundaries faces several challenges, particularly if an entire directory tree is being traversed: + + + + + Another user might add file names to a writable directory at any time. This can interfere with file creation and the order of names returned by readdir. + + + + + + Merely opening and closing a file can have side effects. For instance, an automounter can be triggered, or a tape device rewound. Opening a file on a local file system can block indefinitely, due to mandatory file locking, unless the O_NONBLOCK flag is specified. + + + + + + Hard links and symbolic links can redirect the effect of file system operations in unexpected ways. The O_NOFOLLOW and AT_SYMLINK_NOFOLLOW variants of system calls only affected final path name component. + + + + + + The structure of a directory tree can change. For example, the parent directory of what used to be a subdirectory within the directory tree being processed could suddenly point outside that directory tree. + + + + + + + Files should always be created with the O_CREAT and O_EXCL flags, so that creating the file will fail if it already exists. This guards against the unexpected appearance of file names, either due to creation of a new file, or hard-linking of an existing file. In multi-threaded programs, rather than manipulating the umask, create the files with mode 000 if possible, and adjust it afterwards with fchmod. + + + To avoid issues related to symbolic links and directory tree restructuring, the “at” variants of system calls have to be used (that is, functions like openat, fchownat, fchmodat, and unlinkat, together with O_NOFOLLOW or AT_SYMLINK_NOFOLLOW). Path names passed to these functions must have just a single component (that is, without a slash). When descending, the descriptors of parent directories must be kept open. The missing opendirat function can be emulated with openat (with an O_DIRECTORY flag, to avoid opening special files with side effects), followed by fdopendir. + + + If the “at” functions are not available, it is possible to emulate them by changing the current directory. (Obviously, this only works if the process is not multi-threaded.) fchdir has to be used to change the current directory, and the descriptors of the parent directories have to be kept open, just as with the “at”-based approach. chdir("...") is unsafe because it might ascend outside the intended directory tree. + + + This “at” function emulation is currently required when manipulating extended attributes. In this case, the lsetxattr function can be used, with a relative path name consisting of a single component. This also applies to SELinux contexts and the lsetfilecon function. + + + Currently, it is not possible to avoid opening special files and changes to files with hard links if the directory containing them is owned by an untrusted user. (Device nodes can be hard-linked, just as regular files.) fchmodat and fchownat affect files whose link count is greater than one. But opening the files, checking that the link count is one with fstat, and using fchmod and fchown on the file descriptor may have unwanted side effects, due to item 2 above. When creating directories, it is therefore important to change the ownership and permissions only after it has been fully created. Until that point, file names are stable, and no files with unexpected hard links can be introduced. + + + Similarly, when just reading a directory owned by an untrusted user, it is currently impossible to reliably avoid opening special files. + + + There is no workaround against the instability of the file list returned by readdir. Concurrent modification of the directory can result in a list of files being returned which never actually existed on disk. + + + Hard links and symbolic links can be safely deleted using unlinkat without further checks because deletion only affects the name within the directory tree being processed. + + +
+ +
+ Accessing the file system as a different user + + This section deals with access to the file system as a specific user. This is different from accessing files and directories owned by a different, potentially untrusted user; see . + + + One approach is to spawn a child process which runs under the target user and group IDs (both effective and real IDs). Note that this child process can block indefinitely, even when processing regular files only. For example, a special FUSE file system could cause the process to hang in uninterruptible sleep inside a stat system call. + + + An existing process could change its user and group ID using setfsuid and setfsgid. (These functions are preferred over seteuid and setegid because they do not allow the impersonated user to send signals to the process.) These functions are not thread safe. In multi-threaded processes, these operations need to be performed in a single-threaded child process. Unexpected blocking may occur as well. + + + It is not recommended to try to reimplement the kernel permission checks in user space because the required checks are complex. It is also very difficult to avoid race conditions during path name resolution. + + +
+ +
+ File system limits + + For historical reasons, there are preprocessor constants such as PATH_MAX, NAME_MAX. However, on most systems, the length of canonical path names (absolute path names with all symbolic links resolved, as returned by realpath or canonicalize_file_name) can exceed PATH_MAX bytes, and individual file name components can be longer than NAME_MAX. This is also true of the _PC_PATH_MAX and _PC_NAME_MAX values returned by pathconf, and the f_namemax member of struct statvfs. Therefore, these constants should not be used. This is also reason why the readdir_r should never be used (instead, use readdir). + + + You should not write code in a way that assumes that there is an upper limit on the number of subdirectories of a directory, the number of regular files in a directory, or the link count of an inode. + + +
+ +
+ File system features + + Not all file systems support all features. This makes it very difficult to write general-purpose tools for copying files. For example, a copy operation intending to preserve file permissions will generally fail when copying to a FAT file system. + + + + + Some file systems are case-insensitive. Most should be case-preserving, though. + + + + + + Name length limits vary greatly, from eight to thousands of bytes. Path length limits differ as well. Most systems impose an upper bound on path names passed to the kernel, but using relative path names, it is possible to create and access files whose absolute path name is essentially of unbounded length. + + + + + + Some file systems do not store names as fairly unrestricted byte sequences, as it has been traditionally the case on GNU systems. This means that some byte sequences (outside the POSIX safe character set) are not valid names. Conversely, names of existing files may not be representable as byte sequences, and the files are thus inaccessible on GNU systems. Some file systems perform Unicode canonicalization on file names. These file systems preserve case, but reading the name of a just-created file using readdir might still result in a different byte sequence. + + + + + + Permissions and owners are not universally supported (and SUID/SGID bits may not be available). For example, FAT file systems assign ownership based on a mount option, and generally mark all files as executable. Any attempt to change permissions would result in an error. + + + + + + Non-regular files (device nodes, FIFOs) are not generally available. + + + + + + Only on some file systems, files can have holes, that is, not all of their contents is backed by disk storage. + + + + + + ioctl support (even fairly generic functionality such as FIEMAP for discovering physical file layout and holes) is file-system-specific. + + + + + + Not all file systems support extended attributes, ACLs and SELinux metadata. Size and naming restriction on extended attributes vary. + + + + + + Hard links may not be supported at all (FAT) or only within the same directory (AFS). Symbolic links may not be available, either. Reflinks (hard links with copy-on-write semantics) are still very rare. Recent systems restrict creation of hard links to users which own the target file or have read/write access to it, but older systems do not. + + + + + + Renaming (or moving) files using rename can fail (even when stat indicates that the source and target directories are located on the same file system). This system call should work if the old and new paths are located in the same directory, though. + + + + + + Locking semantics vary among file systems. This affects advisory and mandatory locks. For example, some network file systems do not allow deleting files which are opened by any process. + + + + + + Resolution of time stamps varies from two seconds to nanoseconds. Not all time stamps are available on all file systems. File creation time (birth time) is not exposed over the stat/fstat interface, even if stored by the file system. + + + + + + +
+ +
+ Checking free space + + The statvfs and fstatvfs functions allow programs to examine the number of available blocks and inodes, through the members f_bfree, f_bavail, f_ffree, and f_favail of struct statvfs. Some file systems return fictional values in the f_ffree and f_favail fields, so the only reliable way to discover if the file system still has space for a file is to try to create it. The f_bfree field should be reasonably accurate, though. + + +
+ +
+ diff --git a/defensive-coding/tmp/en-US/xml/Tasks/Library_Design.xml b/defensive-coding/tmp/en-US/xml/Tasks/Library_Design.xml new file mode 100644 index 0000000..94e8ffd --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Tasks/Library_Design.xml @@ -0,0 +1,136 @@ + + +%BOOK_ENTITIES; +]> + + Library Design + + Throught this section, the term client code refers to applications and other libraries using the library. + +
+ State management + + + +
+ Global state + + Global state should be avoided. + + + If this is impossible, the global state must be protected with a lock. For C/C++, you can use the pthread_mutex_lock and pthread_mutex_unlock functions without linking against -lpthread because the system provides stubs for non-threaded processes. + + + For compatibility with fork, these locks should be acquired and released in helpers registered with pthread_atfork. This function is not available without -lpthread, so you need to use dlsym or a weak symbol to obtain its address. + + + If you need fork protection for other reasons, you should store the process ID and compare it to the value returned by getpid each time you access the global state. (getpid is not implemented as a system call and is fast.) If the value changes, you know that you have to re-create the state object. (This needs to be combined with locking, of course.) + + +
+ +
+ Handles + + Library state should be kept behind a curtain. Client code should receive only a handle. In C, the handle can be a pointer to an incomplete struct. In C++, the handle can be a pointer to an abstract base class, or it can be hidden using the pointer-to-implementation idiom. + + + The library should provide functions for creating and destroying handles. (In C++, it is possible to use virtual destructors for the latter.) Consistency between creation and destruction of handles is strongly recommended: If the client code created a handle, it is the responsibility of the client code to destroy it. (This is not always possible or convenient, so sometimes, a transfer of ownership has to happen.) + + + Using handles ensures that it is possible to change the way the library represents state in a way that is transparent to client code. This is important to facilitate security updates and many other code changes. + + + It is not always necessary to protect state behind a handle with a lock. This depends on the level of thread safety the library provides. + + +
+ + +
+ +
+ Object orientation + + Classes should be either designed as base classes, or it should be impossible to use them as base classes (like final classes in Java). Classes which are not designed for inheritance and are used as base classes nevertheless create potential maintenance hazards because it is difficult to predict how client code will react when calls to virtual methods are added, reordered or removed. + + + Virtual member functions can be used as callbacks. See for some of the challenges involved. + + +
+ +
+ Callbacks + + Higher-order code is difficult to analyze for humans and computers alike, so it should be avoided. Often, an iterator-based interface (a library function which is called repeatedly by client code and returns a stream of events) leads to a better design which is easier to document and use. + + + If callbacks are unavoidable, some guidelines for them follow. + + + In modern C++ code, std::function objects should be used for callbacks. + + + In older C++ code and in C code, all callbacks must have an additional closure parameter of type void *, the value of which can be specified by client code. If possible, the value of the closure parameter should be provided by client code at the same time a specific callback is registered (or specified as a function argument). If a single closure parameter is shared by multiple callbacks, flexibility is greatly reduced, and conflicts between different pieces of client code using the same library object could be unresolvable. In some cases, it makes sense to provide a de-registration callback which can be used to destroy the closure parameter when the callback is no longer used. + + + Callbacks can throw exceptions or call longjmp. If possible, all library objects should remain in a valid state. (All further operations on them can fail, but it should be possible to deallocate them without causing resource leaks.) + + + The presence of callbacks raises the question if functions provided by the library are reentrant. Unless a library was designed for such use, bad things will happen if a callback function uses functions in the same library (particularly if they are invoked on the same objects and manipulate the same state). When the callback is invoked, the library can be in an inconsistent state. Reentrant functions are more difficult to write than thread-safe functions (by definition, simple locking would immediately lead to deadlocks). It is also difficult to decide what to do when destruction of an object which is currently processing a callback is requested. + + +
+ +
+ Process attributes + + Several attributes are global and affect all code in the process, not just the library that manipulates them. + + + + + environment variables (see ) + + + + + umask + + + + + user IDs, group IDs and capabilities + + + + + current working directory + + + + + signal handlers, signal masks and signal delivery + + + + + file locks (especially fcntl locks behave in surprising ways, not just in a multi-threaded environment) + + + + + + Library code should avoid manipulating these global process attributes. It should not rely on environment variables, umask, the current working directory and signal masks because these attributes can be inherted from an untrusted source. + + + In addition, there are obvious process-wide aspects such as the virtual memory layout, the set of open files and dynamic shared objects, but with the exception of shared objects, these can be manipulated in a relatively isolated way. + + +
+ + +
+ diff --git a/defensive-coding/tmp/en-US/xml/Tasks/Locking.xml b/defensive-coding/tmp/en-US/xml/Tasks/Locking.xml new file mode 100644 index 0000000..270f4b2 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Tasks/Locking.xml @@ -0,0 +1,8 @@ + + +%BOOK_ENTITIES; +]> + + + diff --git a/defensive-coding/tmp/en-US/xml/Tasks/Processes.xml b/defensive-coding/tmp/en-US/xml/Tasks/Processes.xml new file mode 100644 index 0000000..9de6cc5 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Tasks/Processes.xml @@ -0,0 +1,322 @@ + + +%BOOK_ENTITIES; +]> + + Processes +
+ Safe process creation + + This section describes how to create new child processes in a safe manner. In addition to the concerns addressed below, there is the possibility of file descriptor leaks, see . + +
+ Obtaining the program path and the command line template + + The name and path to the program being invoked should be hard-coded or controlled by a static configuration file stored at a fixed location (at an file system absolute path). The same applies to the template for generating the command line. + + + The configured program name should be an absolute path. If it is a relative path, the contents of the PATH must be obtained in s secure manner (see ). If the PATH variable is not set or untrusted, the safe default /bin:/usr/bin must be used. + + + If too much flexibility is provided here, it may allow invocation of arbitrary programs without proper authorization. + + +
+ +
+ Bypassing the shell + + Child processes should be created without involving the system shell. + + + For C/C++, system should not be used. The posix_spawn function can be used instead, or a combination fork and execve. (In some cases, it may be preferable to use vfork or the Linux-specific clone system call instead of fork.) + + + In Python, the subprocess module bypasses the shell by default (when the shell keyword argument is not set to true). os.system should not be used. + + + The Java class java.lang.ProcessBuilder can be used to create subprocesses without interference from the system shell. + + + Portability notice + + On Windows, there is no argument vector, only a single argument string. Each application is responsible for parsing this string into an argument vector. There is considerable variance among the quoting style recognized by applications. Some of them expand shell wildcards, others do not. Extensive application-specific testing is required to make this secure. + + + + + Note that some common applications (notably ssh) unconditionally introduce the use of a shell, even if invoked directly without a shell. It is difficult to use these applications in a secure manner. In this case, untrusted data should be supplied by other means. For example, standard input could be used, instead of the command line. + + +
+ +
+ Specifying the process environment + + Child processes should be created with a minimal set of environment variables. This is absolutely essential if there is a trust transition involved, either when the parent process was created, or during the creation of the child process. + + + In C/C++, the environment should be constructed as an array of strings and passed as the envp argument to posix_spawn or execve. The functions setenv, unsetenv and putenv should not be used. They are not thread-safe and suffer from memory leaks. + + + Python programs need to specify a dict for the the env argument of the subprocess.Popen constructor. The Java class java.lang.ProcessBuilder provides a environment() method, which returns a map that can be manipulated. + + + The following list provides guidelines for selecting the set of environment variables passed to the child process. + + + + + PATH should be initialized to /bin:/usr/bin. + + + + + + USER and HOME can be inhereted from the parent process environment, or they can be initialized from the pwent structure for the user. + + + + + + The DISPLAY and XAUTHORITY variables should be passed to the subprocess if it is an X program. Note that this will typically not work across trust boundaries because XAUTHORITY refers to a file with 0600 permissions. + + + + + + The location-related environment variables LANG, LANGUAGE, LC_ADDRESS, LC_ALL, LC_COLLATE, LC_CTYPE, LC_IDENTIFICATION, LC_MEASUREMENT, LC_MESSAGES, LC_MONETARY, LC_NAME, LC_NUMERIC, LC_PAPER, LC_TELEPHONE and LC_TIME can be passed to the subprocess if present. + + + + + + The called process may need application-specific environment variables, for example for passing passwords. (See .) + + + + + + All other environment variables should be dropped. Names for new environment variables should not be accepted from untrusted sources. + + + + + + +
+ +
+ Robust argument list processing + + When invoking a program, it is sometimes necessary to include data from untrusted sources. Such data should be check against embedded NUL characters because the system APIs will sliently truncate argument strings at the first NUL character. + + + The following recommendations assume that the program being invoked uses GNU-style option processing using getopt_long. This convention is widely used, but it is just that, and individual programs might interpret a command line in a different way. + + + If the untrusted data has to go into an option, use the --option-name=VALUE syntax, placing the option and its value into the same command line argument. This avoids any potential confusion if the data starts with -. + + + For positional arguments, terminate the option list with a single marker after the last option, and include the data at the right position. The marker terminates option processing, and the data will not be treated as an option even if it starts with a dash. + + +
+ +
+ Passing secrets to subprocesses + + The command line (the name of the program and its argument) of a running process is traditionally available to all local users. The called program can overwrite this information, but only after it has run for a bit of time, during which the information may have been read by other processes. However, on Linux, the process environment is restricted to the user who runs the process. Therefore, if you need a convenient way to pass a password to a child process, use an environment variable, and not a command line argument. (See .) + + + Portability notice + + On some UNIX-like systems (notably Solaris), environment variables can be read by any system user, just like command lines. + + + + + If the environment-based approach cannot be used due to portability concerns, the data can be passed on standard input. Some programs (notably gpg) use special file descriptors whose numbers are specified on the command line. Temporary files are an option as well, but they might give digital forensics access to sensitive data (such as passphrases) because it is difficult to safely delete them in all cases. + + +
+ + +
+ +
+ Handling child process termination + + When child processes terminate, the parent process is signalled. A stub of the terminated processes (a zombie, shown as <defunct> by ps) is kept around until the status information is collected (reaped) by the parent process. Over the years, several interfaces for this have been invented: + + + + + The parent process calls wait, waitpid, waitid, wait3 or wait4, without specifying a process ID. This will deliver any matching process ID. This approach is typically used from within event loops. + + + + + + The parent process calls waitpid, waitid, or wait4, with a specific process ID. Only data for the specific process ID is returned. This is typically used in code which spawns a single subprocess in a synchronous manner. + + + + + + The parent process installs a handler for the SIGCHLD signal, using sigaction, and specifies to the SA_NOCLDWAIT flag. This approach could be used by event loops as well. + + + + + + + None of these approaches can be used to wait for child process terminated in a completely thread-safe manner. The parent process might execute an event loop in another thread, which could pick up the termination signal. This means that libraries typically cannot make free use of child processes (for example, to run problematic code with reduced privileges in a separate address space). + + + At the moment, the parent process should explicitly wait for termination of the child process using waitpid or waitpid, and hope that the status is not collected by an event loop first. + + +
+ +
+ <literal>SUID</literal>/<literal>SGID</literal> processes + + Programs can be marked in the file system to indicate to the kernel that a trust transition should happen if the program is run. The SUID file permission bit indicates that an executable should run with the effective user ID equal to the owner of the executable file. Similarly, with the SGID bit, the effective group ID is set to the group of the executable file. + + + Linux supports fscaps, which can grant additional capabilities to a process in a finer-grained manner. Additional mechanisms can be provided by loadable security modules. + + + When such a trust transition has happened, the process runs in a potentially hostile environment. Additional care is necessary not to rely on any untrusted information. These concerns also apply to libraries which can be linked into such processes. + +
+ Accessing environment variables + + The following steps are required so that a program does not accidentally pick up untrusted data from environment variables. + + + + + Compile your C/C++ sources with -D_GNU_SOURCE. The Autoconf macro AC_GNU_SOURCE ensures this. + + + + + Check for the presence of the secure_getenv and __secure_getenv function. The Autoconf directive AC_CHECK_FUNCS([__secure_getenv secure_getenv]) performs these checks. + + + + + Arrange for a proper definition of the secure_getenv function. See . + + + + + Use secure_getenv instead of getenv to obtain the value of critical environment variables. secure_getenv will pretend the variable has not bee set if the process environment is not trusted. + + + + + + Critical environment variables are debugging flags, configuration file locations, plug-in and log file locations, and anything else that might be used to bypass security restrictions or cause a privileged process to behave in an unexpected way. + + + Either the secure_getenv function or the __secure_getenv is available from GNU libc. + + + Obtaining a definition for <function>secure_getenv</function> + + + +#include <stdlib.h> + +#ifndef HAVE_SECURE_GETENV +# ifdef HAVE__SECURE_GETENV +# define secure_getenv __secure_getenv +# else +# error neither secure_getenv nor __secure_getenv are available +# endif +#endif + + + + + +
+ + +
+ +
+ Daemons + + Background processes providing system services (daemons) need to decouple themselves from the controlling terminal and the parent process environment: + + + + + Fork. + + + + + + In the child process, call setsid. The parent process can simply exit (using _exit, to avoid running clean-up actions twice). + + + + + + In the child process, fork again. Processing continues in the child process. Again, the parent process should just exit. + + + + + + Replace the descriptors 0, 1, 2 with a descriptor for /dev/null. Logging should be redirected to syslog. + + + + + + + Older instructions for creating daemon processes recommended a call to umask(0). This is risky because it often leads to world-writable files and directories, resulting in security vulnerabilities such as arbitrary process termination by untrusted local users, or log file truncation. If the umask needs setting, a restrictive value such as 027 or 077 is recommended. + + + Other aspects of the process environment may have to changed as well (environment variables, signal handler disposition). + + + It is increasingly common that server processes do not run as background processes, but as regular foreground process under a supervising master process (such as systemd). Server processes should offer a command line option which disables forking and replacement of the standard output and standard error streams. Such an option is also useful for debugging. + + +
+ +
+ Semantics of command line arguments + + After process creation and option processing, it is up to the child process to interpret the arguments. Arguments can be file names, host names, or URLs, and many other things. URLs can refer to the local network, some server on the Internet, or to the local file system. Some applications even accept arbitrary code in arguments (for example, python with the option). + + + Similar concerns apply to environment variables, the contents of the current directory and its subdirectories. + + + Consequently, careful analysis is required if it is safe to pass untrusted data to another program. + + +
+ +
+ <function>fork</function> as a primitive for parallelism + + A call to fork which is not immediately followed by a call to execve (perhaps after rearranging and closing file descriptors) is typically unsafe, especially from a library which does not control the state of the entire process. Such use of fork should be replaced with proper child processes or threads. + + +
+ + +
+ diff --git a/defensive-coding/tmp/en-US/xml/Tasks/Serialization.xml b/defensive-coding/tmp/en-US/xml/Tasks/Serialization.xml new file mode 100644 index 0000000..a6f9db2 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Tasks/Serialization.xml @@ -0,0 +1,292 @@ + + +%BOOK_ENTITIES; +]> + + Serialization and Deserialization + + Protocol decoders and file format parsers are often the most-exposed part of an application because they are exposed with little or no user interaction and before any authentication and security checks are made. They are also difficult to write robustly in languages which are not memory-safe. + +
+ Recommendations for manually written decoders + + For C and C++, the advice in applies. In addition, avoid non-character pointers directly into input buffers. Pointer misalignment causes crashes on some architectures. + + + When reading variable-sized objects, do not allocate large amounts of data solely based on the value of a size field. If possible, grow the data structure as more data is read from the source, and stop when no data is available. This helps to avoid denial-of-service attacks where little amounts of input data results in enormous memory allocations during decoding. Alternatively, you can impose reasonable bounds on memory allocations, but some protocols do not permit this. + + +
+ +
+ Protocol design + + Binary formats with explicit length fields are more difficult to parse robustly than those where the length of dynamically-sized elements is derived from sentinel values. A protocol which does not use length fields and can be written in printable ASCII characters simplifies testing and debugging. However, binary protocols with length fields may be more efficient to parse. + + +
+ +
+ Library support for deserialization + + For some languages, generic libraries are available which allow to serialize and deserialize user-defined objects. The deserialization part comes in one of two flavors, depending on the library. The first kind uses type information in the data stream to control which objects are instantiated. The second kind uses type definitions supplied by the programmer. The first one allows arbitrary object instantiation, the second one generally does not. + + + The following serialization frameworks are in the first category, are known to be unsafe, and must not be used for untrusted data: + + + + + Python's pickle and cPickle modules + + + + + Perl's Storable package + + + + + Java serialization (java.io.ObjectInputStream) + + + + + PHP serialization (unserialize) + + + + + Most implementations of YAML + + + + + + When using a type-directed deserialization format where the types of the deserialized objects are specified by the programmer, make sure that the objects which can be instantiated cannot perform any destructive actions in their destructors, even when the data members have been manipulated. + + + JSON decoders do not suffer from this problem. But you must not use the eval function to parse JSON objects in Javascript; even with the regular expression filter from RFC 4627, there are still information leaks remaining. + + +
+ +
+ XML serialization + + + +
+ External references + + XML documents can contain external references. They can occur in various places. + + + + + In the DTD declaration in the header of an XML document: + + + +<!DOCTYPE html PUBLIC + "-//W3C//DTD XHTML 1.0 Transitional//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> + + + + + + In a namespace declaration: + + + +<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"> + + + + + + In an entity defintion: + + + +<!ENTITY sys SYSTEM "http://www.example.com/ent.xml"> +<!ENTITY pub PUBLIC "-//Example//Public Entity//EN" + "http://www.example.com/pub-ent.xml"> + + + + + + In a notation: + + + +<!NOTATION not SYSTEM "../not.xml"> + + + + + + + Originally, these external references were intended as unique identifiers, but by many XML implementations, they are used for locating the data for the referenced element. This causes unwanted network traffic, and may disclose file system contents or otherwise unreachable network resources, so this functionality should be disabled. + + + Depending on the XML library, external referenced might be processed not just when parsing XML, but also when generating it. + + +
+ +
+ Entity expansion + + When external DTD processing is disabled, an internal DTD subset can still contain entity definitions. Entity declarations can reference other entities. Some XML libraries expand entities automatically, and this processing cannot be switched off in some places (such as attribute values or content models). Without limits on the entity nesting level, this expansion results in data which can grow exponentially in length with size of the input. (If there is a limit on the nesting level, the growth is still polynomial, unless further limits are imposed.) + + + Consequently, the processing internal DTD subsets should be disabled if possible, and only trusted DTDs should be processed. If a particular XML application does not permit such restrictions, then application-specific limits are called for. + + +
+ +
+ XInclude processing + + XInclude processing can reference file and network resources and include them into the document, much like external entity references. When parsing untrusted XML documents, XInclude processing should be truned off. + + + XInclude processing is also fairly complex and may pull in support for the XPointer and XPath specifications, considerably increasing the amount of code required for XML processing. + + +
+ +
+ Algorithmic complexity of XML validation + + DTD-based XML validation uses regular expressions for content models. The XML specification requires that content models are deterministic, which means that efficient validation is possible. However, some implementations do not enforce determinism, and require exponential (or just polynomial) amount of space or time for validating some DTD/document combinations. + + + XML schemas and RELAX NG (via the xsd: prefix) directly support textual regular expressions which are not required to be deterministic. + + +
+ +
+ Using Expat for XML parsing + + By default, Expat does not try to resolve external IDs, so no steps are required to block them. However, internal entity declarations are processed. Installing a callback which stops parsing as soon as such entities are encountered disables them, see . Expat does not perform any validation, so there are no problems related to that. + + + Disabling XML entity processing with Expat + + + + + This handler must be installed when the XML_Parser object is created (). + + + Creating an Expat XML parser + + + + + It is also possible to reject internal DTD subsets altogeher, using a suitable XML_StartDoctypeDeclHandler handler installed with XML_SetDoctypeDeclHandler. + + +
+ +
+ Using OpenJDK for XML parsing and validation + + OpenJDK contains facilities for DOM-based, SAX-based, and StAX-based document parsing. Documents can be validated against DTDs or XML schemas. + + + The approach taken to deal with entity expansion differs from the general recommendation in . We enable the the feature flag javax.xml.XMLConstants.FEATURE_SECURE_PROCESSING, which enforces heuristic restrictions on the number of entity expansions. Note that this flag alone does not prevent resolution of external references (system IDs or public IDs), so it is slightly misnamed. + + + In the following sections, we use helper classes to prevent external ID resolution. + + + Helper class to prevent DTD external entity resolution in OpenJDK + + + + + Helper class to prevent schema resolution in OpenJDK + + + + + shows the imports used by the examples. + + + Java imports for OpenJDK XML parsing + + + +
+ DOM-based XML parsing and DTD validation in OpenJDK + + This approach produces a org.w3c.dom.Document object from an input stream. use the data from the java.io.InputStream instance in the inputStream variable. + + + DOM-based XML parsing in OpenJDK + + + + + External entity references are prohibited using the NoEntityResolver class in . Because external DTD references are prohibited, DTD validation (if enabled) will only happen against the internal DTD subset embedded in the XML document. + + + To validate the document against an external DTD, use a javax.xml.transform.Transformer class to add the DTD reference to the document, and an entity resolver which whitelists this external reference. + + +
+ +
+ XML Schema validation in OpenJDK + + shows how to validate a document against an XML Schema, using a SAX-based approach. The XML data is read from an java.io.InputStream in the inputStream variable. + + + SAX-based validation against an XML schema in OpenJDK + + + + + The NoResourceResolver class is defined in . + + + If you need to validate a document against an XML schema, use the code in to create the document, but do not enable validation at this point. Then use to perform the schema-based validation on the org.w3c.dom.Document instance document. + + + Validation of a DOM document against an XML schema in OpenJDK + + + + +
+ + +
+ + +
+ +
+ Protocol Encoders + + For protocol encoders, you should write bytes to a buffer which grows as needed, using an exponential sizing policy. Explicit lengths can be patched in later, once they are known. Allocating the required number of bytes upfront typically requires separate code to compute the final size, which must be kept in sync with the actual encoding step, or vulnerabilities may result. In multi-threaded code, parts of the object being deserialized might change, so that the computed size is out of date. + + + You should avoid copying data directly from a received packet during encoding, disregarding the format. Propagating malformed data could enable attacks on other recipients of that data. + + + When using C or C++ and copying whole data structures directly into the output, make sure that you do not leak information in padding bytes between fields or at the end of the struct. + + +
+ + +
+ diff --git a/defensive-coding/tmp/en-US/xml/Tasks/Temporary_Files.xml b/defensive-coding/tmp/en-US/xml/Tasks/Temporary_Files.xml new file mode 100644 index 0000000..3b0160d --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Tasks/Temporary_Files.xml @@ -0,0 +1,172 @@ + + +%BOOK_ENTITIES; +]> + + Temporary files + + In this chapter, we describe how to create temporary files and directories, how to remove them, and how to work with programs which do not create files in ways that a safe with a shared directory for temporary files. General file system manipulation is treated in a separate chapter, . + + + Secure creation of temporary files has four different aspects. + + + + + The location of the directory for temporary files must be obtained in a secure manner (that is, untrusted environment variables must be ignored, see ). + + + + + + A new file must be created. Reusing an existing file must be avoided (the /tmp race condition). This is tricky because traditionally, system-wide temporary directories shared by all users are used. + + + + + + The file must be created in a way that makes it impossible for other users to open it. + + + + + + The descriptor for the temporary file should not leak to subprocesses. + + + + + + + All functions mentioned below will take care of these aspects. + + + Traditionally, temporary files are often used to reduce memory usage of programs. More and more systems use RAM-based file systems such as tmpfs for storing temporary files, to increase performance and decrease wear on Flash storage. As a result, spooling data to temporary files does not result in any memory savings, and the related complexity can be avoided if the data is kept in process memory. + +
+ Obtaining the location of temporary directory + + Some functions below need the location of a directory which stores temporary files. For C/C++ programs, use the following steps to obtain that directory: + + + + + Use secure_getenv to obtain the value of the TMPDIR environment variable. If it is set, convert the path to a fully-resolved absolute path, using realpath(path, NULL). Check if the new path refers to a directory and is writeable. In this case, use it as the temporary directory. + + + + + + Fall back to /tmp. + + + + + + + In Python, you can use the tempfile.tempdir variable. + + + Java does not support SUID/SGID programs, so you can use the java.lang.System.getenv(String) method to obtain the value of the TMPDIR environment variable, and follow the two steps described above. (Java's default directory selection does not honor TMPDIR.) + + +
+ +
+ Named temporary files + + The mkostemp function creates a named temporary file. You should specify the O_CLOEXEC flag to avoid file descriptor leaks to subprocesses. (Applications which do not use multiple threads can also use mkstemp, but libraries should use mkostemp.) For determining the directory part of the file name pattern, see . + + + The file is not removed automatically. It is not safe to rename or delete the file before processing, or transform the name in any way (for example, by adding a file extension). If you need multiple temporary files, call mkostemp multiple times. Do not create additional file names derived from the name provided by a previous mkostemp call. However, it is safe to close the descriptor returned by mkostemp and reopen the file using the generated name. + + + The Python class tempfile.NamedTemporaryFile provides similar functionality, except that the file is deleted automatically by default. Note that you may have to use the file attribute to obtain the actual file object because some programming interfaces cannot deal with file-like objects. The C function mkostemp is also available as tempfile.mkstemp. + + + In Java, you can use the java.io.File.createTempFile(String, String, File) function, using the temporary file location determined according to . Do not use java.io.File.deleteOnExit() to delete temporary files, and do not register a shutdown hook for each temporary file you create. In both cases, the deletion hint cannot be removed from the system if you delete the temporary file prior to termination of the VM, causing a memory leak. + + +
+ +
+ Temporary files without names + + The tmpfile function creates a temporary file and immediately deletes it, while keeping the file open. As a result, the file lacks a name and its space is deallocated as soon as the file descriptor is closed (including the implicit close when the process terminates). This avoids cluttering the temporary directory with orphaned files. + + + Alternatively, if the maximum size of the temporary file is known beforehand, the fmemopen function can be used to create a FILE * object which is backed by memory. + + + In Python, unnamed temporary files are provided by the tempfile.TemporaryFile class, and the tempfile.SpooledTemporaryFile class provides a way to avoid creation of small temporary files. + + + Java does not support unnamed temporary files. + + +
+ +
+ Temporary directories + + The mkdtemp function can be used to create a temporary directory. (For determining the directory part of the file name pattern, see .) The directory is not automatically removed. In Python, this function is available as tempfile.mkdtemp. In Java 7, temporary directories can be created using the java.nio.file.Files.createTempDirectory(Path, String, FileAttribute...) function. + + + When creating files in the temporary directory, use automatically generated names, e.g., derived from a sequential counter. Files with externally provided names could be picked up in unexpected contexts, and crafted names could actually point outside of the tempoary directory (due to directory traversal). + + + Removing a directory tree in a completely safe manner is complicated. Unless there are overriding performance concerns, the rm program should be used, with the and options. + + +
+ +
+ Compensating for unsafe file creation + + There are two ways to make a function or program which excepts a file name safe for use with temporary files. See , for details on subprocess creation. + + + + + Create a temporary directory and place the file there. If possible, run the program in a subprocess which uses the temporary directory as its current directory, with a restricted environment. Use generated names for all files in that temporary directory. (See .) + + + + + + Create the temporary file and pass the generated file name to the function or program. This only works if the function or program can cope with a zero-length existing file. It is safe only under additional assumptions: + + + + + The function or program must not create additional files whose name is derived from the specified file name or are otherwise predictable. + + + + + + The function or program must not delete the file before processing it. + + + + + + It must not access any existing files in the same directory. + + + + + + + It is often difficult to check whether these additional assumptions are matched, therefore this approach is not recommended. + + + + + + +
+ +
+ diff --git a/defensive-coding/tmp/en-US/xml/Tasks/schemas.xml b/defensive-coding/tmp/en-US/xml/Tasks/schemas.xml new file mode 100644 index 0000000..31581c3 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Tasks/schemas.xml @@ -0,0 +1,6 @@ + + +%BOOK_ENTITIES; +]> + diff --git a/defensive-coding/tmp/en-US/xml/Tasks/snippets/Serialization-XML-Expat-Create.xml b/defensive-coding/tmp/en-US/xml/Tasks/snippets/Serialization-XML-Expat-Create.xml new file mode 100644 index 0000000..e587406 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Tasks/snippets/Serialization-XML-Expat-Create.xml @@ -0,0 +1,20 @@ + + +%BOOK_ENTITIES; +]> + + +XML_Parser parser = XML_ParserCreate("UTF-8"); +if (parser == NULL) { + fprintf(stderr, "XML_ParserCreate failed\n"); + close(fd); + exit(1); +} +// EntityDeclHandler needs a reference to the parser to stop +// parsing. +XML_SetUserData(parser, parser); +// Disable entity processing, to inhibit entity expansion. +XML_SetEntityDeclHandler(parser, EntityDeclHandler); + + diff --git a/defensive-coding/tmp/en-US/xml/Tasks/snippets/Serialization-XML-Expat-EntityDeclHandler.xml b/defensive-coding/tmp/en-US/xml/Tasks/snippets/Serialization-XML-Expat-EntityDeclHandler.xml new file mode 100644 index 0000000..fbbfea5 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Tasks/snippets/Serialization-XML-Expat-EntityDeclHandler.xml @@ -0,0 +1,19 @@ + + +%BOOK_ENTITIES; +]> + + +// Stop the parser when an entity declaration is encountered. +static void +EntityDeclHandler(void *userData, + const XML_Char *entityName, int is_parameter_entity, + const XML_Char *value, int value_length, + const XML_Char *base, const XML_Char *systemId, + const XML_Char *publicId, const XML_Char *notationName) +{ + XML_StopParser((XML_Parser)userData, XML_FALSE); +} + + diff --git a/defensive-coding/tmp/en-US/xml/Tasks/snippets/Serialization-XML-OpenJDK-Errors.xml b/defensive-coding/tmp/en-US/xml/Tasks/snippets/Serialization-XML-OpenJDK-Errors.xml new file mode 100644 index 0000000..33dc271 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Tasks/snippets/Serialization-XML-OpenJDK-Errors.xml @@ -0,0 +1,25 @@ + + +%BOOK_ENTITIES; +]> + + +class Errors implements ErrorHandler { + @Override + public void warning(SAXParseException exception) { + exception.printStackTrace(); + } + + @Override + public void fatalError(SAXParseException exception) { + exception.printStackTrace(); + } + + @Override + public void error(SAXParseException exception) { + exception.printStackTrace(); + } +} + + diff --git a/defensive-coding/tmp/en-US/xml/Tasks/snippets/Serialization-XML-OpenJDK-Imports.xml b/defensive-coding/tmp/en-US/xml/Tasks/snippets/Serialization-XML-OpenJDK-Imports.xml new file mode 100644 index 0000000..e4fcf56 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Tasks/snippets/Serialization-XML-OpenJDK-Imports.xml @@ -0,0 +1,30 @@ + + +%BOOK_ENTITIES; +]> + + +import javax.xml.XMLConstants; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.sax.SAXSource; +import javax.xml.validation.Schema; +import javax.xml.validation.SchemaFactory; +import javax.xml.validation.Validator; + +import org.w3c.dom.Document; +import org.w3c.dom.ls.LSInput; +import org.w3c.dom.ls.LSResourceResolver; +import org.xml.sax.EntityResolver; +import org.xml.sax.ErrorHandler; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.SAXParseException; +import org.xml.sax.XMLReader; + + diff --git a/defensive-coding/tmp/en-US/xml/Tasks/snippets/Serialization-XML-OpenJDK-NoEntityResolver.xml b/defensive-coding/tmp/en-US/xml/Tasks/snippets/Serialization-XML-OpenJDK-NoEntityResolver.xml new file mode 100644 index 0000000..86eb111 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Tasks/snippets/Serialization-XML-OpenJDK-NoEntityResolver.xml @@ -0,0 +1,18 @@ + + +%BOOK_ENTITIES; +]> + + +class NoEntityResolver implements EntityResolver { + @Override + public InputSource resolveEntity(String publicId, String systemId) + throws SAXException, IOException { + // Throwing an exception stops validation. + throw new IOException(String.format( + "attempt to resolve \"%s\" \"%s\"", publicId, systemId)); + } +} + + diff --git a/defensive-coding/tmp/en-US/xml/Tasks/snippets/Serialization-XML-OpenJDK-NoResourceResolver.xml b/defensive-coding/tmp/en-US/xml/Tasks/snippets/Serialization-XML-OpenJDK-NoResourceResolver.xml new file mode 100644 index 0000000..33c35bc --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Tasks/snippets/Serialization-XML-OpenJDK-NoResourceResolver.xml @@ -0,0 +1,20 @@ + + +%BOOK_ENTITIES; +]> + + +class NoResourceResolver implements LSResourceResolver { + @Override + public LSInput resolveResource(String type, String namespaceURI, + String publicId, String systemId, String baseURI) { + // Throwing an exception stops validation. + throw new RuntimeException(String.format( + "resolution attempt: type=%s namespace=%s " + + "publicId=%s systemId=%s baseURI=%s", + type, namespaceURI, publicId, systemId, baseURI)); + } +} + + diff --git a/defensive-coding/tmp/en-US/xml/Tasks/snippets/Serialization-XML-OpenJDK_Parse-DOM.xml b/defensive-coding/tmp/en-US/xml/Tasks/snippets/Serialization-XML-OpenJDK_Parse-DOM.xml new file mode 100644 index 0000000..413e09b --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Tasks/snippets/Serialization-XML-OpenJDK_Parse-DOM.xml @@ -0,0 +1,22 @@ + + +%BOOK_ENTITIES; +]> + + +DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); +// Impose restrictions on the complexity of the DTD. +factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); + +// Turn on validation. +// This step can be omitted if validation is not desired. +factory.setValidating(true); + +// Parse the document. +DocumentBuilder builder = factory.newDocumentBuilder(); +builder.setEntityResolver(new NoEntityResolver()); +builder.setErrorHandler(new Errors()); +Document document = builder.parse(inputStream); + + diff --git a/defensive-coding/tmp/en-US/xml/Tasks/snippets/Serialization-XML-OpenJDK_Parse-XMLSchema_DOM.xml b/defensive-coding/tmp/en-US/xml/Tasks/snippets/Serialization-XML-OpenJDK_Parse-XMLSchema_DOM.xml new file mode 100644 index 0000000..0e06ac3 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Tasks/snippets/Serialization-XML-OpenJDK_Parse-XMLSchema_DOM.xml @@ -0,0 +1,26 @@ + + +%BOOK_ENTITIES; +]> + + +SchemaFactory factory = SchemaFactory.newInstance( + XMLConstants.W3C_XML_SCHEMA_NS_URI); + +// This enables restrictions on schema complexity. +factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); + +// The following line prevents resource resolution +// by the schema itself. +factory.setResourceResolver(new NoResourceResolver()); + +Schema schema = factory.newSchema(schemaFile); + +Validator validator = schema.newValidator(); + +// This prevents external resource resolution. +validator.setResourceResolver(new NoResourceResolver()); +validator.validate(new DOMSource(document)); + + diff --git a/defensive-coding/tmp/en-US/xml/Tasks/snippets/Serialization-XML-OpenJDK_Parse-XMLSchema_SAX.xml b/defensive-coding/tmp/en-US/xml/Tasks/snippets/Serialization-XML-OpenJDK_Parse-XMLSchema_SAX.xml new file mode 100644 index 0000000..5b16c31 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml/Tasks/snippets/Serialization-XML-OpenJDK_Parse-XMLSchema_SAX.xml @@ -0,0 +1,29 @@ + + +%BOOK_ENTITIES; +]> + + +SchemaFactory factory = SchemaFactory.newInstance( + XMLConstants.W3C_XML_SCHEMA_NS_URI); + +// This enables restrictions on the schema and document +// complexity. +factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); + +// This prevents resource resolution by the schema itself. +// If the schema is trusted and references additional files, +// this line must be omitted, otherwise loading these files +// will fail. +factory.setResourceResolver(new NoResourceResolver()); + +Schema schema = factory.newSchema(schemaFile); +Validator validator = schema.newValidator(); + +// This prevents external resource resolution. +validator.setResourceResolver(new NoResourceResolver()); + +validator.validate(new SAXSource(new InputSource(inputStream))); + + diff --git a/defensive-coding/tmp/en-US/xml_tmp/Author_Group.xml b/defensive-coding/tmp/en-US/xml_tmp/Author_Group.xml new file mode 100644 index 0000000..6b40228 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml_tmp/Author_Group.xml @@ -0,0 +1,17 @@ + + +%BOOK_ENTITIES; +]> + + + Florian + Weimer + + Red Hat + Product Security Team + + fweimer@redhat.com + + + diff --git a/defensive-coding/tmp/en-US/xml_tmp/Book_Info.xml b/defensive-coding/tmp/en-US/xml_tmp/Book_Info.xml new file mode 100644 index 0000000..6637802 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml_tmp/Book_Info.xml @@ -0,0 +1,30 @@ + + + + Defensive Coding + A Guide to Improving Software Security + 1.0 + 1.0 + + + + + + This document provides guidelines for improving software + security through secure coding. It covers common + programming languages and libraries, and focuses on + concrete recommendations. + + + + + + + + + + + + + diff --git a/defensive-coding/tmp/en-US/xml_tmp/C/Allocators.xml b/defensive-coding/tmp/en-US/xml_tmp/C/Allocators.xml new file mode 100644 index 0000000..974b6c1 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml_tmp/C/Allocators.xml @@ -0,0 +1,207 @@ + + +
+ Memory allocators + +
+ <function>malloc</function> and related functions + + The C library interfaces for memory allocation are provided by + malloc, free and + realloc, and the + calloc function. In addition to these + generic functions, there are derived functions such as + strdup which perform allocation using + malloc internally, but do not return + untyped heap memory (which could be used for any object). + + + The C compiler knows about these functions and can use their + expected behavior for optimizations. For instance, the compiler + assumes that an existing pointer (or a pointer derived from an + existing pointer by arithmetic) will not point into the memory + area returned by malloc. + + + If the allocation fails, realloc does not + free the old pointer. Therefore, the idiom ptr = + realloc(ptr, size); is wrong because the memory + pointed to by ptr leaks in case of an error. + +
+ Use-after-free errors + + After free, the pointer is invalid. + Further pointer dereferences are not allowed (and are usually + detected by valgrind). Less obvious + is that any use of the old pointer value is + not allowed, either. In particular, comparisons with any other + pointer (or the null pointer) are undefined according to the C + standard. + + + The same rules apply to realloc if the + memory area cannot be enlarged in-place. For instance, the + compiler may assume that a comparison between the old and new + pointer will always return false, so it is impossible to detect + movement this way. + +
+
+ Handling memory allocation errors + + Recovering from out-of-memory errors is often difficult or even + impossible. In these cases, malloc and + other allocation functions return a null pointer. Dereferencing + this pointer lead to a crash. Such dereferences can even be + exploitable for code execution if the dereference is combined + with an array subscript. + + + In general, if you cannot check all allocation calls and + handle failure, you should abort the program on allocation + failure, and not rely on the null pointer dereference to + terminate the process. See + + for related memory allocation concerns. + +
+
+ +
+ <function>alloca</function> and other forms of stack-based + allocation + + Allocation on the stack is risky because stack overflow checking + is implicit. There is a guard page at the end of the memory + area reserved for the stack. If the program attempts to read + from or write to this guard page, a SIGSEGV + signal is generated and the program typically terminates. + + + This is sufficient for detecting typical stack overflow + situations such as unbounded recursion, but it fails when the + stack grows in increments larger than the size of the guard + page. In this case, it is possible that the stack pointer ends + up pointing into a memory area which has been allocated for a + different purposes. Such misbehavior can be exploitable. + + + A common source for large stack growth are calls to + alloca and related functions such as + strdupa. These functions should be avoided + because of the lack of error checking. (They can be used safely + if the allocated size is less than the page size (typically, + 4096 bytes), but this case is relatively rare.) Additionally, + relying on alloca makes it more difficult + to reorgnize the code because it is not allowed to use the + pointer after the function calling alloca + has returned, even if this function has been inlined into its + caller. + + + Similar concerns apply to variable-length + arrays (VLAs), a feature of the C99 standard which + started as a GNU extension. For large objects exceeding the + page size, there is no error checking, either. + + + In both cases, negative or very large sizes can trigger a + stack-pointer wraparound, and the stack pointer and end up + pointing into caller stack frames, which is fatal and can be + exploitable. + + + If you want to use alloca or VLAs for + performance reasons, consider using a small on-stack array (less + than the page size, large enough to fulfill most requests). If + the requested size is small enough, use the on-stack array. + Otherwise, call malloc. When exiting the + function, check if malloc had been called, + and free the buffer as needed. + +
+ +
+ Array allocation + + When allocating arrays, it is important to check for overflows. + The calloc function performs such checks. + + + If malloc or realloc + is used, the size check must be written manually. For instance, + to allocate an array of n elements of type + T, check that the requested size is not + greater than n / sizeof(T). + +
+ +
+ Custom memory allocators + + Custom memory allocates come in two forms: replacements for + malloc, and completely different interfaces + for memory management. Both approaches can reduce the + effectiveness of valgrind and similar + tools, and the heap corruption detection provided by GNU libc, so + they should be avoided. + + + Memory allocators are difficult to write and contain many + performance and security pitfalls. + + + + + When computing array sizes or rounding up allocation + requests (to the next allocation granularity, or for + alignment purposes), checks for arithmetic overflow are + required. + + + + + Size computations for array allocations need overflow + checking. See . + + + + + It can be difficult to beat well-tuned general-purpose + allocators. In micro-benchmarks, pool allocators can show + huge wins, and size-specific pools can reduce internal + fragmentation. But often, utilization of individual pools + is poor, and + + + +
+ +
+ Conservative garbage collection + + Garbage collection can be an alternative to explicit memory + management using malloc and + free. The Boehm-Dehmers-Weiser allocator + can be used from C programs, with minimal type annotations. + Performance is competitive with malloc on + 64-bit architectures, especially for multi-threaded programs. + The stop-the-world pauses may be problematic for some real-time + applications, though. + + + However, using a conservative garbage collector may reduce + opertunities for code reduce because once one library in a + program uses garbage collection, the whole process memory needs + to be subject to it, so that no pointers are missed. The + Boehm-Dehmers-Weiser collector also reserves certain signals for + internal use, so it is not fully transparent to the rest of the + program. + +
+
+ diff --git a/defensive-coding/tmp/en-US/xml_tmp/C/C.xml b/defensive-coding/tmp/en-US/xml_tmp/C/C.xml new file mode 100644 index 0000000..3dd659a --- /dev/null +++ b/defensive-coding/tmp/en-US/xml_tmp/C/C.xml @@ -0,0 +1,11 @@ + + + + The C Programming Language + + + + + + diff --git a/defensive-coding/tmp/en-US/xml_tmp/C/Language.xml b/defensive-coding/tmp/en-US/xml_tmp/C/Language.xml new file mode 100644 index 0000000..db7cc5d --- /dev/null +++ b/defensive-coding/tmp/en-US/xml_tmp/C/Language.xml @@ -0,0 +1,150 @@ + + +
+ The core language + + C provides no memory safety. Most recommendations in this section + deal with this aspect of the language. + + +
+ Undefined behavior + + Some C constructs are defined to be undefined by the C standard. + This does not only mean that the standard does not describe + what happens when the construct is executed. It also allows + optimizing compilers such as GCC to assume that this particular + construct is never reached. In some cases, this has caused + GCC to optimize security checks away. (This is not a flaw in GCC + or the C language. But C certainly has some areas which are more + difficult to use than others.) + + + + Common sources of undefined behavior are: + + + out-of-bounds array accesses + null pointer dereferences + overflow in signed integer arithmetic + +
+ +
+ Recommendations for pointers and array handling + + Always keep track of the size of the array you are working with. + Often, code is more obviously correct when you keep a pointer + past the last element of the array, and calculate the number of + remaining elements by substracting the current position from + that pointer. The alternative, updating a separate variable + every time when the position is advanced, is usually less + obviously correct. + + + + shows how to extract Pascal-style strings from a character + buffer. The two pointers kept for length checks are + inend and outend. + inp and outp are the + respective positions. + The number of input bytes is checked using the expression + len > (size_t)(inend - inp). + The cast silences a compiler warning; + inend is always larger than + inp. + + + Array processing in C + + + + It is important that the length checks always have the form + len > (size_t)(inend - inp), where + len is a variable of type + size_t which denotes the total + number of bytes which are about to be read or written next. In + general, it is not safe to fold multiple such checks into one, + as in len1 + len2 > (size_t)(inend - inp), + because the expression on the left can overflow or wrap around + (see ), and it + no longer reflects the number of bytes to be processed. + +
+ +
+ Recommendations for integer arithmetic + + Overflow in signed integer arithmetic is undefined. This means + that it is not possible to check for overflow after it happened, + see . + + + Incorrect overflow detection in C + + + + The following approaches can be used to check for overflow, + without actually causing it. + + + + + Use a wider type to perform the calculation, check that the + result is within bounds, and convert the result to the + original type. All intermediate results must be checked in + this way. + + + + + Perform the calculation in the corresponding unsigned type + and use bit fiddling to detect the overflow. + + + + + Compute bounds for acceptable input values which are known + to avoid overflow, and reject other values. This is the + preferred way for overflow checking on multiplications, + see . + + + + + + Overflow checking for unsigned multiplication + + + + Basic arithmetic operations a commutative, so for bounds checks, + there are two different but mathematically equivalent + expressions. Sometimes, one of the expressions results in + better code because parts of it can be reduced to a constant. + This applies to overflow checks for multiplication a * + b involving a constant a, where the + expression is reduced to b > C for some + constant C determined at compile time. The + other expression, b && a > ((unsigned)-1) / + b, is more difficult to optimize at compile time. + + + When a value is converted to a signed integer, GCC always + chooses the result based on 2's complement arithmetic. This GCC + extension (which is also implemented by other compilers) helps a + lot when implementing overflow checks. + + + Legacy code should be compiled with the + GCC option. As a result, GCC will provide 2's complement + semantics for integer arithmetic, including defined behavior on + integer overflow. + +
+
diff --git a/defensive-coding/tmp/en-US/xml_tmp/C/Libc.xml b/defensive-coding/tmp/en-US/xml_tmp/C/Libc.xml new file mode 100644 index 0000000..6173bf0 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml_tmp/C/Libc.xml @@ -0,0 +1,227 @@ + + +
+ The C standard library + + Parts of the C standard library (and the UNIX and GNU extensions) + are difficult to use, so you shoud avoid them. + + + Please check the applicable documentation before using the + recommended replacements. Many of these functions allocate + buffers using malloc which your code must + deallocate explicitly using free. + +
+ Absolutely banned interfaces + + The functions listed below must not be used because they are + almost always unsafe. Use the indicated replacements instead. + + + gets + ⟶ fgets + getwd + ⟶ getcwd + or get_current_dir_name + + + readdir_rreaddir + + + + + + + realpath (with a non-NULL second parameter) + ⟶ realpath with NULL as the second parameter, + or canonicalize_file_name + + + + + + + The constants listed below must not be used, either. Instead, + code must allocate memory dynamically and use interfaces with + length checking. + + + + + NAME_MAX (limit not actually enforced by + the kernel) + + + + + PATH_MAX (limit not actually enforced by + the kernel) + + + + + _PC_NAME_MAX (This limit, returned by the + pathconf function, is not enforced by + the kernel.) + + + + + _PC_PATH_MAX (This limit, returned by the + pathconf function, is not enforced by + the kernel.) + + + + + The following structure members must not be used. + + + + + f_namemax in struct + statvfs (limit not actually enforced by the kernel, + see _PC_NAME_MAX above) + + + +
+
+ Functions to avoid + + The following string manipulation functions can be used securely + in principle, but their use should be avoided because they are + difficult to use correctly. Calls to these functions can be + replaced with asprintf or + vasprintf. (For non-GNU targets, these + functions are available from Gnulib.) In some cases, the + snprintf function might be a suitable + replacement, see . + + + sprintf + strcat + strcpy + vsprintf + + + Use the indicated replacements for the functions below. + + + + + alloca ⟶ + malloc and free + (see ) + + + + + putenv ⟶ + explicit envp argument in process creation + (see ) + + + + + setenv ⟶ + explicit envp argument in process creation + (see ) + + + + + strdupa ⟶ + strdup and free + (see ) + + + + + strndupa ⟶ + strndup and free + (see ) + + + + + system ⟶ + posix_spawn + or fork/execve/ + (see ) + + + + + unsetenv ⟶ + explicit envp argument in process creation + (see ) + + + +
+
+ String Functions With Explicit Length Arguments + + The snprintf function provides a way to + construct a string in a statically-sized buffer. (If the buffer + size is dynamic, use asprintf instead.) + + + + + + The second argument to the snprintf should + always be the size of the buffer in the first argument (which + should be a character array). Complex pointer and length + arithmetic can introduce errors and nullify the security + benefits of snprintf. If you need to + construct a string iteratively, by repeatedly appending + fragments, consider constructing the string on the heap, + increasing the buffer with realloc as + needed. (snprintf does not support + overlapping the result buffer with argument strings.) + + + If you use vsnprintf (or + snprintf) with a format string which is not + a constant, but a function argument, it is important to annotate + the function with a format function + attribute, so that GCC can warn about misuse of your function + (see ). + + + The <literal>format</literal> function attribute + + + + There are other functions which operator on NUL-terminated + strings and take a length argument which affects the number of + bytes written to the destination: strncpy, + strncat, and stpncpy. + These functions do not ensure that the result string is + NUL-terminated. For strncpy, + NUL termination can be added this way: + + + + + + Some systems support strlcpy and + strlcat functions which behave this way, + but these functions are not part of GNU libc. Using + snprintf with a suitable format string is a + simple (albeit slightly slower) replacement. + +
+
diff --git a/defensive-coding/tmp/en-US/xml_tmp/C/schemas.xml b/defensive-coding/tmp/en-US/xml_tmp/C/schemas.xml new file mode 100644 index 0000000..8e84245 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml_tmp/C/schemas.xml @@ -0,0 +1,4 @@ + + + + diff --git a/defensive-coding/tmp/en-US/xml_tmp/C/snippets/Arithmetic-add.xml b/defensive-coding/tmp/en-US/xml_tmp/C/snippets/Arithmetic-add.xml new file mode 100644 index 0000000..3c67512 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml_tmp/C/snippets/Arithmetic-add.xml @@ -0,0 +1,21 @@ + + + + +void report_overflow(void); + +int +add(int a, int b) +{ + int result = a + b; + if (a < 0 || b < 0) { + return -1; + } + // The compiler can optimize away the following if statement. + if (result < 0) { + report_overflow(); + } + return result; +} + diff --git a/defensive-coding/tmp/en-US/xml_tmp/C/snippets/Arithmetic-mult.xml b/defensive-coding/tmp/en-US/xml_tmp/C/snippets/Arithmetic-mult.xml new file mode 100644 index 0000000..ecb27a0 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml_tmp/C/snippets/Arithmetic-mult.xml @@ -0,0 +1,14 @@ + + + + +unsigned +mul(unsigned a, unsigned b) +{ + if (b && a > ((unsigned)-1) / b) { + report_overflow(); + } + return a * b; +} + diff --git a/defensive-coding/tmp/en-US/xml_tmp/C/snippets/Pointers-remaining.xml b/defensive-coding/tmp/en-US/xml_tmp/C/snippets/Pointers-remaining.xml new file mode 100644 index 0000000..f527d03 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml_tmp/C/snippets/Pointers-remaining.xml @@ -0,0 +1,49 @@ + + + + +ssize_t +extract_strings(const char *in, size_t inlen, char **out, size_t outlen) +{ + const char *inp = in; + const char *inend = in + inlen; + char **outp = out; + char **outend = out + outlen; + + while (inp != inend) { + size_t len; + char *s; + if (outp == outend) { + errno = ENOSPC; + goto err; + } + len = (unsigned char)*inp; + ++inp; + if (len > (size_t)(inend - inp)) { + errno = EINVAL; + goto err; + } + s = malloc(len + 1); + if (s == NULL) { + goto err; + } + memcpy(s, inp, len); + inp += len; + s[len] = '\0'; + *outp = s; + ++outp; + } + return outp - out; +err: + { + int errno_old = errno; + while (out != outp) { + free(*out); + ++out; + } + errno = errno_old; + } + return -1; +} + diff --git a/defensive-coding/tmp/en-US/xml_tmp/C/snippets/String-Functions-format.xml b/defensive-coding/tmp/en-US/xml_tmp/C/snippets/String-Functions-format.xml new file mode 100644 index 0000000..519f127 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml_tmp/C/snippets/String-Functions-format.xml @@ -0,0 +1,18 @@ + + + + +void log_format(const char *format, ...) __attribute__((format(printf, 1, 2))); + +void +log_format(const char *format, ...) +{ + char buf[1000]; + va_list ap; + va_start(ap, format); + vsnprintf(buf, sizeof(buf), format, ap); + va_end(ap); + log_string(buf); +} + diff --git a/defensive-coding/tmp/en-US/xml_tmp/C/snippets/String-Functions-snprintf.xml b/defensive-coding/tmp/en-US/xml_tmp/C/snippets/String-Functions-snprintf.xml new file mode 100644 index 0000000..dc790d8 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml_tmp/C/snippets/String-Functions-snprintf.xml @@ -0,0 +1,8 @@ + + + + +char fraction[30]; +snprintf(fraction, sizeof(fraction), "%d/%d", numerator, denominator); + diff --git a/defensive-coding/tmp/en-US/xml_tmp/C/snippets/String-Functions-strncpy.xml b/defensive-coding/tmp/en-US/xml_tmp/C/snippets/String-Functions-strncpy.xml new file mode 100644 index 0000000..bdbdd08 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml_tmp/C/snippets/String-Functions-strncpy.xml @@ -0,0 +1,9 @@ + + + + +char buf[10]; +strncpy(buf, data, sizeof(buf)); +buf[sizeof(buf) - 1] = '\0'; + diff --git a/defensive-coding/tmp/en-US/xml_tmp/CXX/CXX.xml b/defensive-coding/tmp/en-US/xml_tmp/CXX/CXX.xml new file mode 100644 index 0000000..fccfb75 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml_tmp/CXX/CXX.xml @@ -0,0 +1,10 @@ + + + + The C++ Programming Language + + + + + diff --git a/defensive-coding/tmp/en-US/xml_tmp/CXX/Language.xml b/defensive-coding/tmp/en-US/xml_tmp/CXX/Language.xml new file mode 100644 index 0000000..9dbc4f3 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml_tmp/CXX/Language.xml @@ -0,0 +1,186 @@ + + +
+ The core language + + C++ includes a large subset of the C language. As far as the C + subset is used, the recommendations in apply. + + +
+ Array allocation with <literal>operator new[]</literal> + + For very large values of n, an expression + like new T[n] can return a pointer to a heap + region which is too small. In other words, not all array + elements are actually backed with heap memory reserved to the + array. Current GCC versions generate code that performs a + computation of the form sizeof(T) * size_t(n) + + cookie_size, where cookie_size is + currently at most 8. This computation can overflow, and + GCC-generated code does not detect this. + + + The std::vector template can be used instead + an explicit array allocation. (The GCC implementation detects + overflow internally.) + + + If there is no alternative to operator new[], + code which allocates arrays with a variable length must check + for overflow manually. For the new T[n] + example, the size check could be n || (n > 0 && + n > (size_t(-1) - 8) / sizeof(T)). (See .) If there are + additional dimensions (which must be constants according to the + C++ standard), these should be included as factors in the + divisor. + + + These countermeasures prevent out-of-bounds writes and potential + code execution. Very large memory allocations can still lead to + a denial of service. + contains suggestions for mitigating this problem when processing + untrusted data. + + + See + for array allocation advice for C-style memory allocation. + +
+ +
+ Overloading + + Do not overload functions with versions that have different + security characteristics. For instance, do not implement a + function strcat which works on + std::string arguments. Similarly, do not name + methods after such functions. + +
+
+ ABI compatibility and preparing for security updates + + A stable binary interface (ABI) is vastly preferred for security + updates. Without a stable ABI, all reverse dependencies need + recompiling, which can be a lot of work and could even be + impossible in some cases. Ideally, a security update only + updates a single dynamic shared object, and is picked up + automatically after restarting affected processes. + + + Outside of extremely performance-critical code, you should + ensure that a wide range of changes is possible without breaking + ABI. Some very basic guidelines are: + + + + + Avoid inline functions. + + + + + Use the pointer-to-implementation idiom. + + + + + Try to avoid templates. Use them if the increased type + safety provides a benefit to the programmer. + + + + + Move security-critical code out of templated code, so that + it can be patched in a central place if necessary. + + + + + The KDE project publishes a document with more extensive + guidelines on ABI-preserving changes to C++ code, Policies/Binary + Compatibility Issues With C++ + (d-pointer refers to the + pointer-to-implementation idiom). + +
+ +
+ C++0X and C++11 support + + GCC offers different language compatibility modes: + + + + + for the original 1998 C++ + standard + + + + + for the 1998 standard with the + changes from the TR1 technical report + + + + + for the 2011 C++ standard. This + option should not be used. + + + + + for several different versions + of C++11 support in development, depending on the GCC + version. This option should not be used. + + + + + + For each of these flags, there are variants which also enable + GNU extensions (mostly language features also found in C99 or + C11): , + , . + Again, should not be used. + + + If you enable C++11 support, the ABI of the standard C++ library + libstdc++ will change in subtle ways. + Currently, no C++ libraries are compiled in C++11 mode, so if + you compile your code in C++11 mode, it will be incompatible + with the rest of the system. Unfortunately, this is also the + case if you do not use any C++11 features. Currently, there is + no safe way to enable C++11 mode (except for freestanding + applications). + + + The meaning of C++0X mode changed from GCC release to GCC + release. Earlier versions were still ABI-compatible with C++98 + mode, but in the most recent versions, switching to C++0X mode + activates C++11 support, with its compatibility problems. + + + Some C++11 features (or approximations thereof) are available + with TR1 support, that is, with or + and in the + <tr1/*> header files. This includes + std::tr1::shared_ptr (from + <tr1/memory>) and + std::tr1::function (from + <tr1/functional>). For other C++11 + features, the Boost C++ library contains replacements. + +
+
+ diff --git a/defensive-coding/tmp/en-US/xml_tmp/CXX/Std.xml b/defensive-coding/tmp/en-US/xml_tmp/CXX/Std.xml new file mode 100644 index 0000000..5ed53a4 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml_tmp/CXX/Std.xml @@ -0,0 +1,32 @@ + + +
+ The C++ standard library + + The C++ standard library includes most of its C counterpart + by reference, see . + +
+ Containers and <literal>operator[]</literal> + + Many containers similar to std::vector + provide both operator[](size_type) and a + member function at(size_type). This applies + to std::vector itself, + std::array, std::string + and other instances of std::basic_string. + + + operator[](size_type) is not required by the + standard to perform bounds checking (and the implementation in + GCC does not). In contrast, at(size_type) + must perform such a check. Therefore, in code which is not + performance-critical, you should prefer + at(size_type) over + operator[](size_type), even though it is + slightly more verbose. + +
+
+ diff --git a/defensive-coding/tmp/en-US/xml_tmp/CXX/schemas.xml b/defensive-coding/tmp/en-US/xml_tmp/CXX/schemas.xml new file mode 100644 index 0000000..8e84245 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml_tmp/CXX/schemas.xml @@ -0,0 +1,4 @@ + + + + diff --git a/defensive-coding/tmp/en-US/xml_tmp/Defensive_Coding.ent b/defensive-coding/tmp/en-US/xml_tmp/Defensive_Coding.ent new file mode 100644 index 0000000..0bf84b7 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml_tmp/Defensive_Coding.ent @@ -0,0 +1,2 @@ + + diff --git a/defensive-coding/tmp/en-US/xml_tmp/Defensive_Coding.xml b/defensive-coding/tmp/en-US/xml_tmp/Defensive_Coding.xml new file mode 100644 index 0000000..cef4bbf --- /dev/null +++ b/defensive-coding/tmp/en-US/xml_tmp/Defensive_Coding.xml @@ -0,0 +1,27 @@ + + + + + + Programming Languages + + + + + + Specific Programming Tasks + + + + + + + + + + Implementing Security Features + + + + + diff --git a/defensive-coding/tmp/en-US/xml_tmp/Features/Authentication.xml b/defensive-coding/tmp/en-US/xml_tmp/Features/Authentication.xml new file mode 100644 index 0000000..c32792a --- /dev/null +++ b/defensive-coding/tmp/en-US/xml_tmp/Features/Authentication.xml @@ -0,0 +1,189 @@ + + + + Authentication and Authorization + +
+ Authenticating servers + + When connecting to a server, a client has to make sure that it + is actually talking to the server it expects. There are two + different aspects, securing the network path, and making sure + that the expected user runs the process on the target host. + There are several ways to ensure that: + + + + + The server uses a TLS certificate which is valid according + to the web browser public key infrastructure, and the client + verifies the certificate and the host name. + + + + + The server uses a TLS certificate which is expectedby the + client (perhaps it is stored in a configuration file read by + the client). In this case, no host name checking is + required. + + + + + On Linux, UNIX domain sockets (of the + PF_UNIX protocol family, sometimes called + PF_LOCAL) are restricted by file system + permissions. If the server socket path is not + world-writable, the server identity cannot be spoofed by + local users. + + + + + Port numbers less than 1024 (trusted + ports) can only be used by + root, so if a UDP or TCP server is + running on the local host and it uses a trusted port, its + identity is assured. (Not all operating systems enforce the + trusted ports concept, and the network might not be trusted, + so it is only useful on the local system.) + + + + + TLS () is the + recommended way for securing connections over untrusted + networks. + + + If the server port number is 1024 is higher, a local user can + impersonate the process by binding to this socket, perhaps after + crashing the real server by exploiting a denial-of-service + vulnerability. + +
+ +
+ Host-based authentication + + Host-based authentication uses access control lists (ACLs) to + accept or deny requests from clients. Thsis authentication + method comes in two flavors: IP-based (or, more generally, + address-based) and name-based (with the name coming from DNS or + /etc/hosts). IP-based ACLs often use + prefix notation to extend access to entire subnets. Name-based + ACLs sometimes use wildcards for adding groups of hosts (from + entire DNS subtrees). (In the SSH context, host-based + authentication means something completely different and is not + covered in this section.) + + + Host-based authentication trust the network and may not offer + sufficient granularity, so it has to be considered a weak form + of authentication. On the other hand, IP-based authentication + can be made extremely robust and can be applied very early in + input processing, so it offers an opportunity for significantly + reducing the number of potential attackers for many services. + + + The names returned by gethostbyaddr and + getnameinfo functions cannot be trusted. + (DNS PTR records can be set to arbitrary values, not just names + belong to the address owner.) If these names are used for ACL + matching, a forward lookup using + gethostbyaddr or + getaddrinfo has to be performed. The name + is only valid if the original address is found among the results + of the forward lookup (double-reverse + lookup). + + + An empty ACL should deny all access (deny-by-default). If empty + ACLs permits all access, configuring any access list must switch + to deny-by-default for all unconfigured protocols, in both + name-based and address-based variants. + + + Similarly, if an address or name is not matched by the list, it + should be denied. However, many implementations behave + differently, so the actual behavior must be documented properly. + + + IPv6 addresses can embed IPv4 addresses. There is no + universally correct way to deal with this ambiguity. The + behavior of the ACL implementation should be documented. + +
+ +
+ UNIX domain socket authentication + + UNIX domain sockets (with address family + AF_UNIX or AF_LOCAL) are + restricted to the local host and offer a special authentication + mechanism: credentials passing. + + + Nowadays, most systems support the + SO_PEERCRED (Linux) or + LOCAL_PEERCRED (FreeBSD) socket options, or + the getpeereid (other BSDs, MacOS X). + These interfaces provide direct access to the (effective) user + ID on the other end of a domain socket connect, without + cooperation from the other end. + + + Historically, credentials passing was implemented using + ancillary data in the sendmsg and + recvmsg functions. On some systems, only + credentials data that the peer has explicitly sent can be + received, and the kernel checks the data for correctness on the + sending side. This means that both peers need to deal with + ancillary data. Compared to that, the modern interfaces are + easier to use. Both sets of interfaces vary considerably among + UNIX-like systems, unfortunately. + + + If you want to authenticate based on supplementary groups, you + should obtain the user ID using one of these methods, and look + up the list of supplementary groups using + getpwuid (or + getpwuid_r) and + getgrouplist. Using the PID and + information from /proc/PID/status is prone + to race conditions and insecure. + +
+ + +
+ diff --git a/defensive-coding/tmp/en-US/xml_tmp/Features/TLS.xml b/defensive-coding/tmp/en-US/xml_tmp/Features/TLS.xml new file mode 100644 index 0000000..a0432f5 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml_tmp/Features/TLS.xml @@ -0,0 +1,988 @@ + + + + Transport Layer Security + + Transport Layer Security (TLS, formerly Secure Sockets + Layer/SSL) is the recommended way to to protect integrity and + confidentiality while data is transferred over an untrusted + network connection, and to identify the endpoint. + +
+ Common Pitfalls + + TLS implementations are difficult to use, and most of them lack + a clean API design. The following sections contain + implementation-specific advice, and some generic pitfalls are + mentioned below. + + + + + Most TLS implementations have questionable default TLS + cipher suites. Most of them enable anonymous Diffie-Hellman + key exchange (but we generally want servers to authenticate + themselves). Many do not disable ciphers which are subject + to brute-force attacks because of restricted key lengths. + Some even disable all variants of AES in the default + configuration. + + + When overriding the cipher suite defaults, it is recommended + to disable all cipher suites which are not present on a + whitelist, instead of simply enabling a list of cipher + suites. This way, if an algorithm is disabled by default in + the TLS implementation in a future security update, the + application will not re-enable it. + + + + + The name which is used in certificate validation must match + the name provided by the user or configuration file. No host + name canonicalization or IP address lookup must be performed. + + + + + The TLS handshake has very poor performance if the TCP Nagle + algorithm is active. You should switch on the + TCP_NODELAY socket option (at least for the + duration of the handshake), or use the Linux-specific + TCP_CORK option. + + + Deactivating the TCP Nagle algorithm + + + + + + Implementing proper session resumption decreases handshake + overhead considerably. This is important if the upper-layer + protocol uses short-lived connections (like most application + of HTTPS). + + + + + Both client and server should work towards an orderly + connection shutdown, that is send + close_notify alerts and respond to them. + This is especially important if the upper-layer protocol + does not provide means to detect connection truncation (like + some uses of HTTP). + + + + + When implementing a server using event-driven programming, + it is important to handle the TLS handshake properly because + it includes multiple network round-trips which can block + when an ordinary TCP accept would not. + Otherwise, a client which fails to complete the TLS + handshake for some reason will prevent the server from + handling input from other clients. + + + + + Unlike regular file descriptors, TLS connections cannot be + passed between processes. Some TLS implementations add + additional restrictions, and TLS connections generally + cannot be used across fork function + calls (see ). + + + +
+ OpenSSL Pitfalls + + Some OpenSSL function use tri-state return + values. Correct error checking is extremely + important. Several functions return int + values with the following meaning: + + + + + The value 1 indicates success (for + example, a successful signature verification). + + + + + The value 0 indicates semantic + failure (for example, a signature verification which was + unsuccessful because the signing certificate was + self-signed). + + + + + The value -1 indicates a low-level + error in the system, such as failure to allocate memory + using malloc. + + + + + Treating such tri-state return values as booleans can lead + to security vulnerabilities. Note that some OpenSSL + functions return boolean results or yet another set of + status indicators. Each function needs to be checked + individually. + + + Recovering precise error information is difficult. + + shows how to obtain a more precise error code after a function + call on an SSL object has failed. However, + there are still cases where no detailed error information is + available (e.g., if SSL_shutdown fails + due to a connection teardown by the other end). + + + Obtaining OpenSSL error codes + + + + The OPENSSL_config function is + documented to never fail. In reality, it can terminate the + entire process if there is a failure accessing the + configuration file. An error message is written to standard + error, but which might not be visible if the function is + called from a daemon process. + + + OpenSSL contains two separate ASN.1 DER decoders. One set + of decoders operate on BIO handles (the input/output stream + abstraction provided by OpenSSL); their decoder function + names start with d2i_ and end in + _fp or _bio (e.g., + d2i_X509_fp or + d2i_X509_bio). These decoders must not + be used for parsing data from untrusted sources; instead, + the variants without the _fp and + _bio (e.g., + d2i_X509) shall be used. The BIO + variants have received considerably less testing and are not + very robust. + + + For the same reason, the OpenSSL command line tools (such as + openssl x509) are generally generally less + robust than the actual library code. They use the BIO + functions internally, and not the more robust variants. + + + The command line tools do not always indicate failure in the + exit status of the openssl process. + For instance, a verification failure in openssl + verify result in an exit status of zero. + + + The OpenSSL server and client applications (openssl + s_client and openssl s_server) + are debugging tools and should never be + used as generic clients. For instance, the + s_client tool reacts in a + surprisign way to lines starting with R and + Q. + + + OpenSSL allows application code to access private key + material over documented interfaces. This can significantly + increase the part of the code base which has to undergo + security certification. + +
+
+ GNUTLS Pitfalls + + libgnutls.so.26 links to + libpthread.so.0. Loading the threading + library too late causes problems, so the main program should + be linked with -lpthread as well. As a + result, it can be difficult to use GNUTLS in a plugin which is + loaded with the dlopen function. Another + side effect is that applications which merely link against + GNUTLS (even without actually using it) may incur a + substantial overhead because other libraries automatically + switch to thread-safe algorithms. + + + The gnutls_global_init function must be + called before using any functionality provided by the library. + This function is not thread-safe, so external locking is + required, but it is not clear which lock should be used. + Omitting the synchronization does not just lead to a memory + leak, as it is suggested in the GNUTLS documentation, but to + undefined behavior because there is no barrier that would + enforce memory ordering. + + + The gnutls_global_deinit function does + not actually deallocate all resources allocated by + gnutls_global_init. It is currently not + thread-safe. Therefore, it is best to avoid calling it + altogether. + + + The X.509 implementation in GNUTLS is rather lenient. For + example, it is possible to create and process X.509 + version 1 certificates which carry extensions. These + certificates are (correctly) rejected by other + implementations. + +
+
+ OpenJDK Pitfalls + + The Java cryptographic framework is highly modular. As a + result, when you request an object implementing some + cryptographic functionality, you cannot be completely sure + that you end up with the well-tested, reviewed implementation + in OpenJDK. + + + OpenJDK (in the source code as published by Oracle) and other + implementations of the Java platform require that the system + administrator has installed so-called unlimited + strength jurisdiction policy files. Without this + step, it is not possible to use the secure algorithms which + offer sufficient cryptographic strength. Most downstream + redistributors of OpenJDK remove this requirement. + + + Some versions of OpenJDK use /dev/random + as the randomness source for nonces and other random data + which is needed for TLS operation, but does not actually + require physical randomness. As a result, TLS applications + can block, waiting for more bits to become available in + /dev/random. + +
+
+ NSS Pitfalls + + NSS was not designed to be used by other libraries which can + be linked into applications without modifying them. There is + a lot of global state. There does not seem to be a way to + perform required NSS initialization without race conditions. + + + If the NSPR descriptor is in an unexpected state, the + SSL_ForceHandshake function can succeed, + but no TLS handshake takes place, the peer is not + authenticated, and subsequent data is exchanged in the clear. + + + NSS disables itself if it detects that the process underwent a + fork after the library has been + initialized. This behavior is required by the PKCS#11 API + specification. + +
+
+
+ TLS Clients + + Secure use of TLS in a client generally involves all of the + following steps. (Individual instructions for specific TLS + implementations follow in the next sections.) + + + + + The client must configure the TLS library to use a set of + trusted root certificates. These certificates are provided + by the system in /etc/ssl/certs or files derived + from it. + + + + + The client selects sufficiently strong cryptographic + primitives and disables insecure ones (such as no-op + encryption). Compression and SSL version 2 support must be + disabled (including the SSLv2-compatible handshake). + + + + + The client initiates the TLS connection. The Server Name + Indication extension should be used if supported by the + TLS implementation. Before switching to the encrypted + connection state, the contents of all input and output + buffers must be discarded. + + + + + The client needs to validate the peer certificate provided + by the server, that is, the client must check that there + is a cryptographically protected chain from a trusted root + certificate to the peer certificate. (Depending on the + TLS implementation, a TLS handshake can succeed even if + the certificate cannot be validated.) + + + + + The client must check that the configured or user-provided + server name matches the peer certificate provided by the + server. + + + + + It is safe to provide users detailed diagnostics on + certificate validation failures. Other causes of handshake + failures and, generally speaking, any details on other errors + reported by the TLS implementation (particularly exception + tracebacks), must not be divulged in ways that make them + accessible to potential attackers. Otherwise, it is possible + to create decryption oracles. + + + + Depending on the application, revocation checking (against + certificate revocations lists or via OCSP) and session + resumption are important aspects of production-quality + client. These aspects are not yet covered. + + +
+ Implementation TLS Clients With OpenSSL + + In the following code, the error handling is only exploratory. + Proper error handling is required for production use, + especially in libraries. + + + + The OpenSSL library needs explicit initialization (see ). + + + OpenSSL library initialization + + + + After that, a context object has to be created, which acts as + a factory for connection objects (). We + use an explicit cipher list so that we do not pick up any + strange ciphers when OpenSSL is upgraded. The actual version + requested in the client hello depends on additional + restrictions in the OpenSSL library. If possible, you should + follow the example code and use the default list of trusted + root certificate authorities provided by the system because + you would have to maintain your own set otherwise, which can + be cumbersome. + + + OpenSSL client context creation + + + + A single context object can be used to create multiple + connection objects. It is safe to use the same + SSL_CTX object for creating connections + concurrently from multiple threads, provided that the + SSL_CTX object is not modified (e.g., + callbacks must not be changed). + + + After creating the TCP socket and disabling the Nagle + algorithm (per ), the actual + connection object needs to be created, as show in . If + the handshake started by SSL_connect + fails, the ssl_print_error_and_exit + function from is called. + + + The certificate_validity_override + function provides an opportunity to override the validity of + the certificate in case the OpenSSL check fails. If such + functionality is not required, the call can be removed, + otherwise, the application developer has to implement it. + + + The host name passed to the functions + SSL_set_tlsext_host_name and + X509_check_host must be the name that was + passed to getaddrinfo or a similar name + resolution function. No host name canonicalization must be + performed. The X509_check_host function + used in the final step for host name matching is currently + only implemented in OpenSSL 1.1, which is not released yet. + In case host name matching fails, the function + certificate_host_name_override is called. + This function should check user-specific certificate store, to + allow a connection even if the host name does not match the + certificate. This function has to be provided by the + application developer. Note that the override must be keyed + by both the certificate and the host + name. + + + Creating a client connection using OpenSSL + + + + The connection object can be used for sending and receiving + data, as in . + It is also possible to create a BIO object + and use the SSL object as the underlying + transport, using BIO_set_ssl. + + + Using an OpenSSL connection to send and receive data + + + + When it is time to close the connection, the + SSL_shutdown function needs to be called + twice for an orderly, synchronous connection termination + (). + This exchanges close_notify alerts with the + server. The additional logic is required to deal with an + unexpected close_notify from the server. + Note that is necessary to explicitly close the underlying + socket after the connection object has been freed. + + + Closing an OpenSSL connection in an orderly fashion + + + + shows how + to deallocate the context object when it is no longer needed + because no further TLS connections will be established. + + + Closing an OpenSSL connection in an orderly fashion + + +
+
+ Implementation TLS Clients With GNUTLS + + This section describes how to implement a TLS client with full + certificate validation (but without certificate revocation + checking). Note that the error handling in is only + exploratory and needs to be replaced before production use. + + + The GNUTLS library needs explicit initialization: + + + + + + Failing to do so can result in obscure failures in Base64 + decoding. See for + additional aspects of initialization. + + + Before setting up TLS connections, a credentials objects has + to be allocated and initialized with the set of trusted root + CAs (). + + + Initializing a GNUTLS credentials structure + + + + After the last TLS connection has been closed, this credentials + object should be freed: + + + + + + During its lifetime, the credentials object can be used to + initialize TLS session objects from multiple threads, provided + that it is not changed. + + + Once the TCP connection has been established, the Nagle + algorithm should be disabled (see ). After that, the + socket can be associated with a new GNUTLS session object. + The previously allocated credentials object provides the set + of root CAs. The NORMAL set of cipher + suites and protocols provides a reasonable default. Then the + TLS handshake must be initiated. This is shown in . + + + Establishing a TLS client connection using GNUTLS + + + + After the handshake has been completed, the server certificate + needs to be verified (). In + the example, the user-defined + certificate_validity_override function is + called if the verification fails, so that a separate, + user-specific trust store can be checked. This function call + can be omitted if the functionality is not needed. + + + Verifying a server certificate using GNUTLS + + + + In the next step (, the + certificate must be matched against the host name (note the + unusual return value from + gnutls_x509_crt_check_hostname). Again, + an override function + certificate_host_name_override is called. + Note that the override must be keyed to the certificate + and the host name. The function call can + be omitted if the override is not needed. + + + Matching the server host name and certificate in a + GNUTLS client + + + + In newer GNUTLS versions, certificate checking and host name + validation can be combined using the + gnutls_certificate_verify_peers3 function. + + + An established TLS session can be used for sending and + receiving data, as in . + + + Using a GNUTLS session + + + + In order to shut down a connection in an orderly manner, you + should call the gnutls_bye function. + Finally, the session object can be deallocated using + gnutls_deinit (see ). + + + Using a GNUTLS session + + +
+
+ Implementing TLS Clients With OpenJDK + + The examples below use the following cryptographic-related + classes: + + + + + + If compatibility with OpenJDK 6 is required, it is necessary + to use the internal class + sun.security.util.HostnameChecker. (The + public OpenJDK API does not provide any support for dissecting + the subject distinguished name of an X.509 certificate, so a + custom-written DER parser is needed—or we have to use an + internal class, which we do below.) In OpenJDK 7, the + setEndpointIdentificationAlgorithm method + was added to the + javax.net.ssl.SSLParameters class, + providing an official way to implement host name checking. + + + TLS connections are established using an + SSLContext instance. With a properly + configured OpenJDK installation, the + SunJSSE provider uses the system-wide set + of trusted root certificate authorities, so no further + configuration is necessary. For backwards compatibility with + OpenJDK 6, the TLSv1 provider has to + be supported as a fall-back option. This is shown in . + + + Setting up an <literal>SSLContext</literal> for OpenJDK TLS + clients + + + + In addition to the context, a TLS parameter object will be + needed which adjusts the cipher suites and protocols (). Like + the context, these parameters can be reused for multiple TLS + connections. + + + Setting up <literal>SSLParameters</literal> for TLS use + with OpenJDK + + + + As initialized above, the parameter object does not yet + require host name checking. This has to be enabled + separately, and this is only supported by OpenJDK 7 and later: + + + + + + All application protocols can use the + "HTTPS" algorithm. (The algorithms have + minor differences with regard to wildcard handling, which + should not matter in practice.) + + + + shows how to establish the connection. Before the handshake + is initialized, the protocol and cipher configuration has to + be performed, by applying the parameter object + params. (After this point, changes to + params will not affect this TLS socket.) + As mentioned initially, host name checking requires using an + internal API on OpenJDK 6. + + + Establishing a TLS connection with OpenJDK + + + + Starting with OpenJDK 7, the last lines can be omitted, + provided that host name verification has been enabled by + calling the + setEndpointIdentificationAlgorithm method + on the params object (before it was applied + to the socket). + + + The TLS socket can be used as a regular socket, as shown in + . + + + Using a TLS client socket in OpenJDK + + +
+ Overriding server certificate validation with OpenJDK 6 + + Overriding certificate validation requires a custom trust + manager. With OpenJDK 6, the trust manager lacks + information about the TLS session, and to which server the + connection is made. Certificate overrides have to be tied + to specific servers (host names). Consequently, different + TrustManager and + SSLContext objects have to be used for + different servers. + + + In the trust manager shown in , + the server certificate is identified by its SHA-256 hash. + + + A customer trust manager for OpenJDK TLS clients + + + + This trust manager has to be passed to the + init method of the + SSLContext object, as show in . + + + Using a custom TLS trust manager with OpenJDK + + + + When certificate overrides are in place, host name + verification should not be performed because there is no + security requirement that the host name in the certificate + matches the host name used to establish the connection (and + it often will not). However, without host name + verification, it is not possible to perform transparent + fallback to certification validation using the system + certificate store. + + + The approach described above works with OpenJDK 6 and later + versions. Starting with OpenJDK 7, it is possible to use a + custom subclass of the + javax.net.ssl.X509ExtendedTrustManager + class. The OpenJDK TLS implementation will call the new + methods, passing along TLS session information. This can be + used to implement certificate overrides as a fallback (if + certificate or host name verification fails), and a trust + manager object can be used for multiple servers because the + server address is available to the trust manager. + +
+
+
+ Implementing TLS Clients With NSS + + The following code shows how to implement a simple TLS client + using NSS. Note that the error handling needs replacing + before production use. + + + Using NSS needs several header files, as shown in + . + + + Include files for NSS + + + + Initializing the NSS library is a complex task (). It is not + thread-safe. By default, the library is in export mode, and + all strong ciphers are disabled. Therefore, after creating + the NSSInitCContext object, we probe all + the strong ciphers we want to use, and check if at least one + of them is available. If not, we call + NSS_SetDomesticPolicy to switch to + unrestricted policy mode. This function replaces the existing + global cipher suite policy, that is why we avoid calling it + unless absolutely necessary. + + + The simplest way to configured the trusted root certificates + involves loading the libnssckbi.so NSS + module with a call to the + SECMOD_LoadUserModule function. The root + certificates are compiled into this module. (The PEM module + for NSS, libnsspem.so, offers a way to + load trusted CA certificates from a file.) + + + Initializing the NSS library + + + + Some of the effects of the initialization can be reverted with + the following function calls: + + + + + + After NSS has been initialized, the TLS connection can be + created (). The + internal PR_ImportTCPSocket function is + used to turn the POSIX file descriptor + sockfd into an NSPR file descriptor. (This + function is de-facto part of the NSS public ABI, so it will + not go away.) Creating the TLS-capable file descriptor + requires a model descriptor, which is + configured with the desired set of protocols and ciphers. + (The good_ciphers variable is part of .) We cannot + resort to disabling ciphers not on a whitelist because by + default, the AES cipher suites are disabled. The model + descriptor is not needed anymore after TLS support has been + activated for the existing connection descriptor. + + + The call to SSL_BadCertHook can be + omitted if no mechanism to override certificate verification + is needed. The bad_certificate function + must check both the host name specified for the connection and + the certificate before granting the override. + + + Triggering the actual handshake requires three function calls, + SSL_ResetHandshake, + SSL_SetURL, and + SSL_ForceHandshake. (If + SSL_ResetHandshake is omitted, + SSL_ForceHandshake will succeed, but the + data will not be encrypted.) During the handshake, the + certificate is verified and matched against the host name. + + + Creating a TLS connection with NSS + + + + After the connection has been established, shows how to use + the NSPR descriptor to communicate with the server. + + + Using NSS for sending and receiving data + + + + + shows how to close the connection. + + + Closing NSS client connections + + +
+
+ Implementing TLS Clients With Python + + The Python distribution provides a TLS implementation in the + ssl module (actually a wrapper around + OpenSSL). The exported interface is somewhat restricted, so + that the client code shown below does not fully implement the + recommendations in . + + + + Currently, most Python function which accept + https:// URLs or otherwise implement + HTTPS support do not perform certificate validation at all. + (For example, this is true for the httplib + and xmlrpclib modules.) If you use + HTTPS, you should not use the built-in HTTP clients. The + Curl class in the curl + module, as provided by the python-pycurl + package implements proper certificate validation. + + + + The ssl module currently does not perform + host name checking on the server certificate. + shows how to implement certificate matching, using the parsed + certificate returned by getpeercert. + + + Implementing TLS host name checking Python (without + wildcard support) + + + + To turn a regular, connected TCP socket into a TLS-enabled + socket, use the ssl.wrap_socket function. + The function call in + provides additional arguments to override questionable + defaults in OpenSSL and in the Python module. + + + + + ciphers="HIGH:-aNULL:-eNULL:-PSK:RC4-SHA:RC4-MD5" + selects relatively strong cipher suites with + certificate-based authentication. (The call to + check_host_name function provides + additional protection against anonymous cipher suites.) + + + + + ssl_version=ssl.PROTOCOL_TLSv1 disables + SSL 2.0 support. By default, the ssl + module sends an SSL 2.0 client hello, which is rejected by + some servers. Ideally, we would request OpenSSL to + negotiated the most recent TLS version supported by the + server and the client, but the Python module does not + allow this. + + + + + cert_reqs=ssl.CERT_REQUIRED turns on + certificate validation. + + + + + ca_certs='/etc/ssl/certs/ca-bundle.crt' + initializes the certificate store with a set of trusted + root CAs. Unfortunately, it is necessary to hard-code + this path into applications because the default path in + OpenSSL is not available through the Python + ssl module. + + + + + The ssl module (and OpenSSL) perform + certificate validation, but the certificate must be compared + manually against the host name, by calling the + check_host_name defined above. + + + Establishing a TLS client connection with Python + + + + After the connection has been established, the TLS socket can + be used like a regular socket: + + + + + + Closing the TLS socket is straightforward as well: + + + + +
+
+
diff --git a/defensive-coding/tmp/en-US/xml_tmp/Features/schemas.xml b/defensive-coding/tmp/en-US/xml_tmp/Features/schemas.xml new file mode 100644 index 0000000..8e84245 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml_tmp/Features/schemas.xml @@ -0,0 +1,4 @@ + + + + diff --git a/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Client-GNUTLS-Connect.xml b/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Client-GNUTLS-Connect.xml new file mode 100644 index 0000000..fbf1420 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Client-GNUTLS-Connect.xml @@ -0,0 +1,50 @@ + + + + +// Create the session object. +gnutls_session_t session; +ret = gnutls_init(&session, GNUTLS_CLIENT); +if (ret != GNUTLS_E_SUCCESS) { + fprintf(stderr, "error: gnutls_init: %s\n", + gnutls_strerror(ret)); + exit(1); +} + +// Configure the cipher preferences. +const char *errptr = NULL; +ret = gnutls_priority_set_direct(session, "NORMAL", &errptr); +if (ret != GNUTLS_E_SUCCESS) { + fprintf(stderr, "error: gnutls_priority_set_direct: %s\n" + "error: at: \"%s\"\n", gnutls_strerror(ret), errptr); + exit(1); +} + +// Install the trusted certificates. +ret = gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, cred); +if (ret != GNUTLS_E_SUCCESS) { + fprintf(stderr, "error: gnutls_credentials_set: %s\n", + gnutls_strerror(ret)); + exit(1); +} + +// Associate the socket with the session object and set the server +// name. +gnutls_transport_set_ptr(session, (gnutls_transport_ptr_t)(uintptr_t)sockfd); +ret = gnutls_server_name_set(session, GNUTLS_NAME_DNS, + host, strlen(host)); +if (ret != GNUTLS_E_SUCCESS) { + fprintf(stderr, "error: gnutls_server_name_set: %s\n", + gnutls_strerror(ret)); + exit(1); +} + +// Establish the session. +ret = gnutls_handshake(session); +if (ret != GNUTLS_E_SUCCESS) { + fprintf(stderr, "error: gnutls_handshake: %s\n", + gnutls_strerror(ret)); + exit(1); +} + diff --git a/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Client-GNUTLS-Credentials.xml b/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Client-GNUTLS-Credentials.xml new file mode 100644 index 0000000..6a5cd09 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Client-GNUTLS-Credentials.xml @@ -0,0 +1,29 @@ + + + + +// Load the trusted CA certificates. +gnutls_certificate_credentials_t cred = NULL; +int ret = gnutls_certificate_allocate_credentials (&cred); +if (ret != GNUTLS_E_SUCCESS) { + fprintf(stderr, "error: gnutls_certificate_allocate_credentials: %s\n", + gnutls_strerror(ret)); + exit(1); +} +// gnutls_certificate_set_x509_system_trust needs GNUTLS version 3.0 +// or newer, so we hard-code the path to the certificate store +// instead. +static const char ca_bundle[] = "/etc/ssl/certs/ca-bundle.crt"; +ret = gnutls_certificate_set_x509_trust_file + (cred, ca_bundle, GNUTLS_X509_FMT_PEM); +if (ret == 0) { + fprintf(stderr, "error: no certificates found in: %s\n", ca_bundle); + exit(1); +} +if (ret < 0) { + fprintf(stderr, "error: gnutls_certificate_set_x509_trust_files(%s): %s\n", + ca_bundle, gnutls_strerror(ret)); + exit(1); +} + diff --git a/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Client-GNUTLS-Match.xml b/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Client-GNUTLS-Match.xml new file mode 100644 index 0000000..c4a51ce --- /dev/null +++ b/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Client-GNUTLS-Match.xml @@ -0,0 +1,30 @@ + + + + +// Match the peer certificate against the host name. +// We can only obtain a set of DER-encoded certificates from the +// session object, so we have to re-parse the peer certificate into +// a certificate object. +gnutls_x509_crt_t cert; +ret = gnutls_x509_crt_init(&cert); +if (ret != GNUTLS_E_SUCCESS) { + fprintf(stderr, "error: gnutls_x509_crt_init: %s\n", + gnutls_strerror(ret)); + exit(1); +} +// The peer certificate is the first certificate in the list. +ret = gnutls_x509_crt_import(cert, certs, GNUTLS_X509_FMT_DER); +if (ret != GNUTLS_E_SUCCESS) { + fprintf(stderr, "error: gnutls_x509_crt_import: %s\n", + gnutls_strerror(ret)); + exit(1); +} +ret = gnutls_x509_crt_check_hostname(cert, host); +if (ret == 0 && !certificate_host_name_override(certs[0], host)) { + fprintf(stderr, "error: host name does not match certificate\n"); + exit(1); +} +gnutls_x509_crt_deinit(cert); + diff --git a/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Client-GNUTLS-Verify.xml b/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Client-GNUTLS-Verify.xml new file mode 100644 index 0000000..a3c9365 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Client-GNUTLS-Verify.xml @@ -0,0 +1,42 @@ + + + + +// Obtain the server certificate chain. The server certificate +// itself is stored in the first element of the array. +unsigned certslen = 0; +const gnutls_datum_t *const certs = + gnutls_certificate_get_peers(session, &certslen); +if (certs == NULL || certslen == 0) { + fprintf(stderr, "error: could not obtain peer certificate\n"); + exit(1); +} + +// Validate the certificate chain. +unsigned status = (unsigned)-1; +ret = gnutls_certificate_verify_peers2(session, &status); +if (ret != GNUTLS_E_SUCCESS) { + fprintf(stderr, "error: gnutls_certificate_verify_peers2: %s\n", + gnutls_strerror(ret)); + exit(1); +} +if (status != 0 && !certificate_validity_override(certs[0])) { + gnutls_datum_t msg; +#if GNUTLS_VERSION_AT_LEAST_3_1_4 + int type = gnutls_certificate_type_get (session); + ret = gnutls_certificate_verification_status_print(status, type, &out, 0); +#else + ret = -1; +#endif + if (ret == 0) { + fprintf(stderr, "error: %s\n", msg.data); + gnutls_free(msg.data); + exit(1); + } else { + fprintf(stderr, "error: certificate validation failed with code 0x%x\n", + status); + exit(1); + } +} + diff --git a/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Client-NSS-Close.xml b/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Client-NSS-Close.xml new file mode 100644 index 0000000..456e209 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Client-NSS-Close.xml @@ -0,0 +1,15 @@ + + + + +// Send close_notify alert. +if (PR_Shutdown(nspr, PR_SHUTDOWN_BOTH) != PR_SUCCESS) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: PR_Read error %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); +} +// Closes the underlying POSIX file descriptor, too. +PR_Close(nspr); + diff --git a/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Client-NSS-Connect.xml b/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Client-NSS-Connect.xml new file mode 100644 index 0000000..692ad04 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Client-NSS-Connect.xml @@ -0,0 +1,106 @@ + + + + +// Wrap the POSIX file descriptor. This is an internal NSPR +// function, but it is very unlikely to change. +PRFileDesc* nspr = PR_ImportTCPSocket(sockfd); +sockfd = -1; // Has been taken over by NSPR. + +// Add the SSL layer. +{ + PRFileDesc *model = PR_NewTCPSocket(); + PRFileDesc *newfd = SSL_ImportFD(NULL, model); + if (newfd == NULL) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: NSPR error code %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); + } + model = newfd; + newfd = NULL; + if (SSL_OptionSet(model, SSL_ENABLE_SSL2, PR_FALSE) != SECSuccess) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: set SSL_ENABLE_SSL2 error %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); + } + if (SSL_OptionSet(model, SSL_V2_COMPATIBLE_HELLO, PR_FALSE) != SECSuccess) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: set SSL_V2_COMPATIBLE_HELLO error %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); + } + if (SSL_OptionSet(model, SSL_ENABLE_DEFLATE, PR_FALSE) != SECSuccess) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: set SSL_ENABLE_DEFLATE error %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); + } + + // Disable all ciphers (except RC4-based ciphers, for backwards + // compatibility). + const PRUint16 *const ciphers = SSL_GetImplementedCiphers(); + for (unsigned i = 0; i < SSL_GetNumImplementedCiphers(); i++) { + if (ciphers[i] != SSL_RSA_WITH_RC4_128_SHA + && ciphers[i] != SSL_RSA_WITH_RC4_128_MD5) { + if (SSL_CipherPrefSet(model, ciphers[i], PR_FALSE) != SECSuccess) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: disable cipher %u: error %d: %s\n", + (unsigned)ciphers[i], err, PR_ErrorToName(err)); + exit(1); + } + } + } + + // Enable the strong ciphers. + for (const PRUint16 *p = good_ciphers; *p != SSL_NULL_WITH_NULL_NULL; + ++p) { + if (SSL_CipherPrefSet(model, *p, PR_TRUE) != SECSuccess) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: enable cipher %u: error %d: %s\n", + (unsigned)*p, err, PR_ErrorToName(err)); + exit(1); + } + } + + // Allow overriding invalid certificate. + if (SSL_BadCertHook(model, bad_certificate, (char *)host) != SECSuccess) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: SSL_BadCertHook error %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); + } + + newfd = SSL_ImportFD(model, nspr); + if (newfd == NULL) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: SSL_ImportFD error %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); + } + nspr = newfd; + PR_Close(model); +} + +// Perform the handshake. +if (SSL_ResetHandshake(nspr, PR_FALSE) != SECSuccess) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: SSL_ResetHandshake error %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); +} +if (SSL_SetURL(nspr, host) != SECSuccess) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: SSL_SetURL error %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); +} +if (SSL_ForceHandshake(nspr) != SECSuccess) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: SSL_ForceHandshake error %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); +} + diff --git a/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Client-OpenJDK-Connect.xml b/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Client-OpenJDK-Connect.xml new file mode 100644 index 0000000..40cc623 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Client-OpenJDK-Connect.xml @@ -0,0 +1,26 @@ + + + + +// Create the socket and connect it at the TCP layer. +SSLSocket socket = (SSLSocket) ctx.getSocketFactory() + .createSocket(host, port); + +// Disable the Nagle algorithm. +socket.setTcpNoDelay(true); + +// Adjust ciphers and protocols. +socket.setSSLParameters(params); + +// Perform the handshake. +socket.startHandshake(); + +// Validate the host name. The match() method throws +// CertificateException on failure. +X509Certificate peer = (X509Certificate) + socket.getSession().getPeerCertificates()[0]; +// This is the only way to perform host name checking on OpenJDK 6. +HostnameChecker.getInstance(HostnameChecker.TYPE_TLS).match( + host, peer); + diff --git a/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Client-OpenJDK-Context.xml b/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Client-OpenJDK-Context.xml new file mode 100644 index 0000000..b7fde16 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Client-OpenJDK-Context.xml @@ -0,0 +1,26 @@ + + + + +// Create the context. Specify the SunJSSE provider to avoid +// picking up third-party providers. Try the TLS 1.2 provider +// first, then fall back to TLS 1.0. +SSLContext ctx; +try { + ctx = SSLContext.getInstance("TLSv1.2", "SunJSSE"); +} catch (NoSuchAlgorithmException e) { + try { + ctx = SSLContext.getInstance("TLSv1", "SunJSSE"); + } catch (NoSuchAlgorithmException e1) { + // The TLS 1.0 provider should always be available. + throw new AssertionError(e1); + } catch (NoSuchProviderException e1) { + throw new AssertionError(e1); + } +} catch (NoSuchProviderException e) { + // The SunJSSE provider should always be available. + throw new AssertionError(e); +} +ctx.init(null, null, null); + diff --git a/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Client-OpenJDK-Context_For_Cert.xml b/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Client-OpenJDK-Context_For_Cert.xml new file mode 100644 index 0000000..6004157 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Client-OpenJDK-Context_For_Cert.xml @@ -0,0 +1,22 @@ + + + + +SSLContext ctx; +try { + ctx = SSLContext.getInstance("TLSv1.2", "SunJSSE"); +} catch (NoSuchAlgorithmException e) { + try { + ctx = SSLContext.getInstance("TLSv1", "SunJSSE"); + } catch (NoSuchAlgorithmException e1) { + throw new AssertionError(e1); + } catch (NoSuchProviderException e1) { + throw new AssertionError(e1); + } +} catch (NoSuchProviderException e) { + throw new AssertionError(e); +} +MyTrustManager tm = new MyTrustManager(certHash); +ctx.init(null, new TrustManager[] {tm}, null); + diff --git a/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Client-OpenJDK-Hostname.xml b/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Client-OpenJDK-Hostname.xml new file mode 100644 index 0000000..586cb7b --- /dev/null +++ b/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Client-OpenJDK-Hostname.xml @@ -0,0 +1,7 @@ + + + + +params.setEndpointIdentificationAlgorithm("HTTPS"); + diff --git a/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Client-OpenJDK-Import.xml b/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Client-OpenJDK-Import.xml new file mode 100644 index 0000000..57c9343 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Client-OpenJDK-Import.xml @@ -0,0 +1,18 @@ + + + + +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.cert.CertificateEncodingException; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLParameters; +import javax.net.ssl.SSLSocket; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; + +import sun.security.util.HostnameChecker; + diff --git a/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Client-OpenJDK-MyTrustManager.xml b/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Client-OpenJDK-MyTrustManager.xml new file mode 100644 index 0000000..43fd12b --- /dev/null +++ b/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Client-OpenJDK-MyTrustManager.xml @@ -0,0 +1,38 @@ + + + + +public class MyTrustManager implements X509TrustManager { + private final byte[] certHash; + + public MyTrustManager(byte[] certHash) throws Exception { + this.certHash = certHash; + } + + @Override + public void checkClientTrusted(X509Certificate[] chain, String authType) + throws CertificateException { + throw new UnsupportedOperationException(); + } + + @Override + public void checkServerTrusted(X509Certificate[] chain, + String authType) throws CertificateException { + byte[] digest = getCertificateDigest(chain[0]); + String digestHex = formatHex(digest); + + if (Arrays.equals(digest, certHash)) { + System.err.println("info: accepting certificate: " + digestHex); + } else { + throw new CertificateException("certificate rejected: " + + digestHex); + } + } + + @Override + public X509Certificate[] getAcceptedIssuers() { + return new X509Certificate[0]; + } +} + diff --git a/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Client-OpenJDK-Use.xml b/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Client-OpenJDK-Use.xml new file mode 100644 index 0000000..11d708a --- /dev/null +++ b/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Client-OpenJDK-Use.xml @@ -0,0 +1,11 @@ + + + + +socket.getOutputStream().write("GET / HTTP/1.0\r\n\r\n" + .getBytes(Charset.forName("UTF-8"))); +byte[] buffer = new byte[4096]; +int count = socket.getInputStream().read(buffer); +System.out.write(buffer, 0, count); + diff --git a/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Client-OpenSSL-CTX.xml b/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Client-OpenSSL-CTX.xml new file mode 100644 index 0000000..05e2854 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Client-OpenSSL-CTX.xml @@ -0,0 +1,71 @@ + + + + +// Configure a client connection context. Send a hendshake for the +// highest supported TLS version, and disable compression. +const SSL_METHOD *const req_method = SSLv23_client_method(); +SSL_CTX *const ctx = SSL_CTX_new(req_method); +if (ctx == NULL) { + ERR_print_errors(bio_err); + exit(1); +} +SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_COMPRESSION); + +// Adjust the ciphers list based on a whitelist. First enable all +// ciphers of at least medium strength, to get the list which is +// compiled into OpenSSL. +if (SSL_CTX_set_cipher_list(ctx, "HIGH:MEDIUM") != 1) { + ERR_print_errors(bio_err); + exit(1); +} +{ + // Create a dummy SSL session to obtain the cipher list. + SSL *ssl = SSL_new(ctx); + if (ssl == NULL) { + ERR_print_errors(bio_err); + exit(1); + } + STACK_OF(SSL_CIPHER) *active_ciphers = SSL_get_ciphers(ssl); + if (active_ciphers == NULL) { + ERR_print_errors(bio_err); + exit(1); + } + // Whitelist of candidate ciphers. + static const char *const candidates[] = { + "AES128-GCM-SHA256", "AES128-SHA256", "AES256-SHA256", // strong ciphers + "AES128-SHA", "AES256-SHA", // strong ciphers, also in older versions + "RC4-SHA", "RC4-MD5", // backwards compatibility, supposed to be weak + "DES-CBC3-SHA", "DES-CBC3-MD5", // more backwards compatibility + NULL + }; + // Actually selected ciphers. + char ciphers[300]; + ciphers[0] = '\0'; + for (const char *const *c = candidates; *c; ++c) { + for (int i = 0; i < sk_SSL_CIPHER_num(active_ciphers); ++i) { + if (strcmp(SSL_CIPHER_get_name(sk_SSL_CIPHER_value(active_ciphers, i)), + *c) == 0) { + if (*ciphers) { + strcat(ciphers, ":"); + } + strcat(ciphers, *c); + break; + } + } + } + SSL_free(ssl); + // Apply final cipher list. + if (SSL_CTX_set_cipher_list(ctx, ciphers) != 1) { + ERR_print_errors(bio_err); + exit(1); + } +} + +// Load the set of trusted root certificates. +if (!SSL_CTX_set_default_verify_paths(ctx)) { + ERR_print_errors(bio_err); + exit(1); +} + diff --git a/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Client-OpenSSL-Connect.xml b/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Client-OpenSSL-Connect.xml new file mode 100644 index 0000000..5cd433d --- /dev/null +++ b/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Client-OpenSSL-Connect.xml @@ -0,0 +1,55 @@ + + + + +// Create the connection object. +SSL *ssl = SSL_new(ctx); +if (ssl == NULL) { + ERR_print_errors(bio_err); + exit(1); +} +SSL_set_fd(ssl, sockfd); + +// Enable the ServerNameIndication extension +if (!SSL_set_tlsext_host_name(ssl, host)) { + ERR_print_errors(bio_err); + exit(1); +} + +// Perform the TLS handshake with the server. +ret = SSL_connect(ssl); +if (ret != 1) { + // Error status can be 0 or negative. + ssl_print_error_and_exit(ssl, "SSL_connect", ret); +} + +// Obtain the server certificate. +X509 *peercert = SSL_get_peer_certificate(ssl); +if (peercert == NULL) { + fprintf(stderr, "peer certificate missing"); + exit(1); +} + +// Check the certificate verification result. Allow an explicit +// certificate validation override in case verification fails. +int verifystatus = SSL_get_verify_result(ssl); +if (verifystatus != X509_V_OK && !certificate_validity_override(peercert)) { + fprintf(stderr, "SSL_connect: verify result: %s\n", + X509_verify_cert_error_string(verifystatus)); + exit(1); +} + +// Check if the server certificate matches the host name used to +// establish the connection. +// FIXME: Currently needs OpenSSL 1.1. +if (X509_check_host(peercert, (const unsigned char *)host, strlen(host), + 0) != 1 + && !certificate_host_name_override(peercert, host)) { + fprintf(stderr, "SSL certificate does not match host name\n"); + exit(1); +} + +X509_free(peercert); + + diff --git a/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Client-OpenSSL-Connection-Use.xml b/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Client-OpenSSL-Connection-Use.xml new file mode 100644 index 0000000..ab54edf --- /dev/null +++ b/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Client-OpenSSL-Connection-Use.xml @@ -0,0 +1,15 @@ + + + + +const char *const req = "GET / HTTP/1.0\r\n\r\n"; +if (SSL_write(ssl, req, strlen(req)) < 0) { + ssl_print_error_and_exit(ssl, "SSL_write", ret); +} +char buf[4096]; +ret = SSL_read(ssl, buf, sizeof(buf)); +if (ret < 0) { + ssl_print_error_and_exit(ssl, "SSL_read", ret); +} + diff --git a/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Client-OpenSSL-Init.xml b/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Client-OpenSSL-Init.xml new file mode 100644 index 0000000..8211ce8 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Client-OpenSSL-Init.xml @@ -0,0 +1,13 @@ + + + + +// The following call prints an error message and calls exit() if +// the OpenSSL configuration file is unreadable. +OPENSSL_config(NULL); +// Provide human-readable error messages. +SSL_load_error_strings(); +// Register ciphers. +SSL_library_init(); + diff --git a/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Client-Python-Connect.xml b/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Client-Python-Connect.xml new file mode 100644 index 0000000..0e98e87 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Client-Python-Connect.xml @@ -0,0 +1,14 @@ + + + + +sock = ssl.wrap_socket(sock, + ciphers="HIGH:-aNULL:-eNULL:-PSK:RC4-SHA:RC4-MD5", + ssl_version=ssl.PROTOCOL_TLSv1, + cert_reqs=ssl.CERT_REQUIRED, + ca_certs='/etc/ssl/certs/ca-bundle.crt') +# getpeercert() triggers the handshake as a side effect. +if not check_host_name(sock.getpeercert(), host): + raise IOError("peer certificate does not match host name") + diff --git a/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Client-Python-check_host_name.xml b/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Client-Python-check_host_name.xml new file mode 100644 index 0000000..3c325f8 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Client-Python-check_host_name.xml @@ -0,0 +1,29 @@ + + + + +def check_host_name(peercert, name): + """Simple certificate/host name checker. Returns True if the + certificate matches, False otherwise. Does not support + wildcards.""" + # Check that the peer has supplied a certificate. + # None/{} is not acceptable. + if not peercert: + return False + if peercert.has_key("subjectAltName"): + for typ, val in peercert["subjectAltName"]: + if typ == "DNS" and val == name: + return True + else: + # Only check the subject DN if there is no subject alternative + # name. + cn = None + for attr, val in peercert["subject"]: + # Use most-specific (last) commonName attribute. + if attr == "commonName": + cn = val + if cn is not None: + return cn == name + return False + diff --git a/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-GNUTLS-Credentials-Close.xml b/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-GNUTLS-Credentials-Close.xml new file mode 100644 index 0000000..8c28b0f --- /dev/null +++ b/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-GNUTLS-Credentials-Close.xml @@ -0,0 +1,7 @@ + + + + +gnutls_certificate_free_credentials(cred); + diff --git a/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-GNUTLS-Disconnect.xml b/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-GNUTLS-Disconnect.xml new file mode 100644 index 0000000..b01464d --- /dev/null +++ b/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-GNUTLS-Disconnect.xml @@ -0,0 +1,14 @@ + + + + +// Initiate an orderly connection shutdown. +ret = gnutls_bye(session, GNUTLS_SHUT_RDWR); +if (ret < 0) { + fprintf(stderr, "error: gnutls_bye: %s\n", gnutls_strerror(ret)); + exit(1); +} +// Free the session object. +gnutls_deinit(session); + diff --git a/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-GNUTLS-Init.xml b/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-GNUTLS-Init.xml new file mode 100644 index 0000000..519522e --- /dev/null +++ b/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-GNUTLS-Init.xml @@ -0,0 +1,7 @@ + + + + +gnutls_global_init(); + diff --git a/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-GNUTLS-Use.xml b/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-GNUTLS-Use.xml new file mode 100644 index 0000000..a6a3f9c --- /dev/null +++ b/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-GNUTLS-Use.xml @@ -0,0 +1,18 @@ + + + + +char buf[4096]; +snprintf(buf, sizeof(buf), "GET / HTTP/1.0\r\nHost: %s\r\n\r\n", host); +ret = gnutls_record_send(session, buf, strlen(buf)); +if (ret < 0) { + fprintf(stderr, "error: gnutls_record_send: %s\n", gnutls_strerror(ret)); + exit(1); +} +ret = gnutls_record_recv(session, buf, sizeof(buf)); +if (ret < 0) { + fprintf(stderr, "error: gnutls_record_recv: %s\n", gnutls_strerror(ret)); + exit(1); +} + diff --git a/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-NSS-Close.xml b/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-NSS-Close.xml new file mode 100644 index 0000000..e34cea8 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-NSS-Close.xml @@ -0,0 +1,8 @@ + + + + +SECMOD_DestroyModule(module); +NSS_ShutdownContext(ctx); + diff --git a/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-NSS-Includes.xml b/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-NSS-Includes.xml new file mode 100644 index 0000000..ee183d0 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-NSS-Includes.xml @@ -0,0 +1,20 @@ + + + + +// NSPR include files +#include <prerror.h> +#include <prinit.h> + +// NSS include files +#include <nss.h> +#include <pk11pub.h> +#include <secmod.h> +#include <ssl.h> +#include <sslproto.h> + +// Private API, no other way to turn a POSIX file descriptor into an +// NSPR handle. +NSPR_API(PRFileDesc*) PR_ImportTCPSocket(int); + diff --git a/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-NSS-Init.xml b/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-NSS-Init.xml new file mode 100644 index 0000000..d56651b --- /dev/null +++ b/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-NSS-Init.xml @@ -0,0 +1,63 @@ + + + + +PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); +NSSInitContext *const ctx = + NSS_InitContext("sql:/etc/pki/nssdb", "", "", "", NULL, + NSS_INIT_READONLY | NSS_INIT_PK11RELOAD); +if (ctx == NULL) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: NSPR error code %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); +} + +// Ciphers to enable. +static const PRUint16 good_ciphers[] = { + TLS_RSA_WITH_AES_128_CBC_SHA, + TLS_RSA_WITH_AES_256_CBC_SHA, + SSL_RSA_WITH_3DES_EDE_CBC_SHA, + SSL_NULL_WITH_NULL_NULL // sentinel +}; + +// Check if the current policy allows any strong ciphers. If it +// doesn't, switch to the "domestic" (unrestricted) policy. This is +// not thread-safe and has global impact. Consequently, we only do +// it if absolutely necessary. +int found_good_cipher = 0; +for (const PRUint16 *p = good_ciphers; *p != SSL_NULL_WITH_NULL_NULL; + ++p) { + PRInt32 policy; + if (SSL_CipherPolicyGet(*p, &policy) != SECSuccess) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: policy for cipher %u: error %d: %s\n", + (unsigned)*p, err, PR_ErrorToName(err)); + exit(1); + } + if (policy == SSL_ALLOWED) { + fprintf(stderr, "info: found cipher %x\n", (unsigned)*p); + found_good_cipher = 1; + break; + } +} +if (!found_good_cipher) { + if (NSS_SetDomesticPolicy() != SECSuccess) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: NSS_SetDomesticPolicy: error %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); + } +} + +// Initialize the trusted certificate store. +char module_name[] = "library=libnssckbi.so name=\"Root Certs\""; +SECMODModule *module = SECMOD_LoadUserModule(module_name, NULL, PR_FALSE); +if (module == NULL || !module->loaded) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: NSPR error code %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); +} + diff --git a/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-NSS-Use.xml b/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-NSS-Use.xml new file mode 100644 index 0000000..f1a0c6d --- /dev/null +++ b/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-NSS-Use.xml @@ -0,0 +1,22 @@ + + + + +char buf[4096]; +snprintf(buf, sizeof(buf), "GET / HTTP/1.0\r\nHost: %s\r\n\r\n", host); +PRInt32 ret = PR_Write(nspr, buf, strlen(buf)); +if (ret < 0) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: PR_Write error %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); +} +ret = PR_Read(nspr, buf, sizeof(buf)); +if (ret < 0) { + const PRErrorCode err = PR_GetError(); + fprintf(stderr, "error: PR_Read error %d: %s\n", + err, PR_ErrorToName(err)); + exit(1); +} + diff --git a/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Nagle.xml b/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Nagle.xml new file mode 100644 index 0000000..824fab5 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Nagle.xml @@ -0,0 +1,12 @@ + + + + +const int val = 1; +int ret = setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val)); +if (ret < 0) { + perror("setsockopt(TCP_NODELAY)"); + exit(1); +} + diff --git a/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-OpenJDK-Parameters.xml b/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-OpenJDK-Parameters.xml new file mode 100644 index 0000000..af48ca6 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-OpenJDK-Parameters.xml @@ -0,0 +1,27 @@ + + + + +// Prepare TLS parameters. These have to applied to every TLS +// socket before the handshake is triggered. +SSLParameters params = ctx.getDefaultSSLParameters(); +// Do not send an SSL-2.0-compatible Client Hello. +ArrayList<String> protocols = new ArrayList<String>( + Arrays.asList(params.getProtocols())); +protocols.remove("SSLv2Hello"); +params.setProtocols(protocols.toArray(new String[protocols.size()])); +// Adjust the supported ciphers. +ArrayList<String> ciphers = new ArrayList<String>( + Arrays.asList(params.getCipherSuites())); +ciphers.retainAll(Arrays.asList( + "TLS_RSA_WITH_AES_128_CBC_SHA256", + "TLS_RSA_WITH_AES_256_CBC_SHA256", + "TLS_RSA_WITH_AES_256_CBC_SHA", + "TLS_RSA_WITH_AES_128_CBC_SHA", + "SSL_RSA_WITH_3DES_EDE_CBC_SHA", + "SSL_RSA_WITH_RC4_128_SHA1", + "SSL_RSA_WITH_RC4_128_MD5", + "TLS_EMPTY_RENEGOTIATION_INFO_SCSV")); +params.setCipherSuites(ciphers.toArray(new String[ciphers.size()])); + diff --git a/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-OpenSSL-Connection-Close.xml b/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-OpenSSL-Connection-Close.xml new file mode 100644 index 0000000..0e446ef --- /dev/null +++ b/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-OpenSSL-Connection-Close.xml @@ -0,0 +1,30 @@ + + + + +// Send the close_notify alert. +ret = SSL_shutdown(ssl); +switch (ret) { +case 1: + // A close_notify alert has already been received. + break; +case 0: + // Wait for the close_notify alert from the peer. + ret = SSL_shutdown(ssl); + switch (ret) { + case 0: + fprintf(stderr, "info: second SSL_shutdown returned zero\n"); + break; + case 1: + break; + default: + ssl_print_error_and_exit(ssl, "SSL_shutdown 2", ret); + } + break; +default: + ssl_print_error_and_exit(ssl, "SSL_shutdown 1", ret); +} +SSL_free(ssl); +close(sockfd); + diff --git a/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-OpenSSL-Context-Close.xml b/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-OpenSSL-Context-Close.xml new file mode 100644 index 0000000..89a324e --- /dev/null +++ b/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-OpenSSL-Context-Close.xml @@ -0,0 +1,7 @@ + + + + +SSL_CTX_free(ctx); + diff --git a/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-OpenSSL-Errors.xml b/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-OpenSSL-Errors.xml new file mode 100644 index 0000000..ab16ce7 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-OpenSSL-Errors.xml @@ -0,0 +1,31 @@ + + + + +static void __attribute__((noreturn)) +ssl_print_error_and_exit(SSL *ssl, const char *op, int ret) +{ + int subcode = SSL_get_error(ssl, ret); + switch (subcode) { + case SSL_ERROR_NONE: + fprintf(stderr, "error: %s: no error to report\n", op); + break; + case SSL_ERROR_WANT_READ: + case SSL_ERROR_WANT_WRITE: + case SSL_ERROR_WANT_X509_LOOKUP: + case SSL_ERROR_WANT_CONNECT: + case SSL_ERROR_WANT_ACCEPT: + fprintf(stderr, "error: %s: invalid blocking state %d\n", op, subcode); + break; + case SSL_ERROR_SSL: + fprintf(stderr, "error: %s: TLS layer problem\n", op); + case SSL_ERROR_SYSCALL: + fprintf(stderr, "error: %s: system call failed: %s\n", op, strerror(errno)); + break; + case SSL_ERROR_ZERO_RETURN: + fprintf(stderr, "error: %s: zero return\n", op); + } + exit(1); +} + diff --git a/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Python-Close.xml b/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Python-Close.xml new file mode 100644 index 0000000..fd20ff2 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Python-Close.xml @@ -0,0 +1,7 @@ + + + + +sock.close() + diff --git a/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Python-Use.xml b/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Python-Use.xml new file mode 100644 index 0000000..08690ca --- /dev/null +++ b/defensive-coding/tmp/en-US/xml_tmp/Features/snippets/TLS-Python-Use.xml @@ -0,0 +1,8 @@ + + + + +sock.write("GET / HTTP/1.1\r\nHost: " + host + "\r\n\r\n") +print sock.read() + diff --git a/defensive-coding/tmp/en-US/xml_tmp/Python/Language.xml b/defensive-coding/tmp/en-US/xml_tmp/Python/Language.xml new file mode 100644 index 0000000..5cfec8f --- /dev/null +++ b/defensive-coding/tmp/en-US/xml_tmp/Python/Language.xml @@ -0,0 +1,74 @@ + + + + The Python Programming Language + + Python provides memory safety by default, so low-level security + vulnerabilities are rare and typically needs fixing the Python + interpreter or standard library itself. + + + Other sections with Python-specific advice include: + + + + + + + + + + + + + + + , in + particular + + + + + + + + +
+ Dangerous standard library features + + Some areas of the standard library, notably the + ctypes module, do not provide memory safety + guarantees comparable to the rest of Python. If such + functionality is used, the advice in should be followed. + +
+
+ Run-time compilation and code generation + + The following Python functions and statements related to code + execution should be avoided: + + + compile + eval + exec + execfile + + + If you need to parse integers or floating point values, use the + int and float + functions instead of eval. Sandboxing + untrusted Python code does not work reliably. + +
+
+ Sandboxing + + The rexec Python module cannot safely sandbox + untrusted code and should not be used. The standard CPython + implementation is not suitable for sandboxing. + +
+
diff --git a/defensive-coding/tmp/en-US/xml_tmp/Python/schemas.xml b/defensive-coding/tmp/en-US/xml_tmp/Python/schemas.xml new file mode 100644 index 0000000..8e84245 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml_tmp/Python/schemas.xml @@ -0,0 +1,4 @@ + + + + diff --git a/defensive-coding/tmp/en-US/xml_tmp/Revision_History.xml b/defensive-coding/tmp/en-US/xml_tmp/Revision_History.xml new file mode 100644 index 0000000..c9f6483 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml_tmp/Revision_History.xml @@ -0,0 +1,27 @@ + + +%BOOK_ENTITIES; +]> + + Revision History + + + + 0-1 + Thu Mar 7 2013 + + Eric + Christensen + sparks@redhat.com + + + + Initial publication. + + + + + + + diff --git a/defensive-coding/tmp/en-US/xml_tmp/Tasks/Cryptography.xml b/defensive-coding/tmp/en-US/xml_tmp/Tasks/Cryptography.xml new file mode 100644 index 0000000..88f14a3 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml_tmp/Tasks/Cryptography.xml @@ -0,0 +1,111 @@ + + + + Cryptography + +
+ Primitives + + Chosing from the following cryptographic primitives is + recommended: + + + RSA with 2048 bit keys and OAEP + AES-128 in CBC mode + SHA-256 + HMAC-SHA-256 + HMAC-SHA-1 + + + Other cryptographic algorithms can be used if they are required + for interoperability with existing software: + + + RSA with key sizes larger than 1024 + and legacy padding + AES-192 + AES-256 + 3DES (triple DES, with two or three 56 bit keys) + RC4 (but very, very strongly discouraged) + SHA-1 + HMAC-MD5 + + + Important + + These primitives are difficult to use in a secure way. Custom + implementation of security protocols should be avoided. For + protecting confidentiality and integrity of network + transmissions, TLS should be used (). + + + +
+ +
+ Randomness + + The following facilities can be used to generate unpredictable + and non-repeating values. When these functions are used without + special safeguards, each individual rnadom value should be at + least 12 bytes long. + + + + PK11_GenerateRandom in the NSS library + (usable for high data rates) + + + RAND_bytes in the OpenSSL library + (usable for high data rates) + + + gnutls_rnd in GNUTLS, with + GNUTLS_RND_RANDOM as the first argument + (usable for high data rates) + + + java.security.SecureRandom in Java + (usable for high data rates) + + + os.urandom in Python + + + Reading from the /dev/urandom + character device + + + + All these functions should be non-blocking, and they should not + wait until physical randomness becomes available. (Some + cryptography providers for Java can cause + java.security.SecureRandom to block, however.) + Those functions which do not obtain all bits directly from + /dev/urandom are suitable for high data + rates because they do not deplete the system-wide entropy pool. + + + Difficult to use API + + Both RAND_bytes and + PK11_GenerateRandom have three-state + return values (with conflicting meanings). Careful error + checking is required. Please review the documentation when + using these functions. + + + + Other sources of randomness should be considered predictable. + + + Generating randomness for cryptographic keys in long-term use + may need different steps and is best left to cryptographic + libraries. + +
+ +
diff --git a/defensive-coding/tmp/en-US/xml_tmp/Tasks/Descriptors.xml b/defensive-coding/tmp/en-US/xml_tmp/Tasks/Descriptors.xml new file mode 100644 index 0000000..bdf1fb2 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml_tmp/Tasks/Descriptors.xml @@ -0,0 +1,266 @@ + + + + File Descriptor Management + + File descriptors underlie all input/output mechanisms offered by + the system. They are used to implementation the FILE + *-based functions found in + <stdio.h>, and all the file and network + communication facilities provided by the Python and Java + environments are eventually implemented in them. + + + File descriptors are small, non-negative integers in userspace, + and are backed on the kernel side with complicated data structures + which can sometimes grow very large. + +
+ Closing descriptors + + If a descriptor is no longer used by a program and is not closed + explicitly, its number cannot be reused (which is problematic in + itself, see ), and + the kernel resources are not freed. Therefore, it is important + to close all descriptors at the earlierst point in time + possible, but not earlier. + +
+ Error handling during descriptor close + + The close system call is always + successful in the sense that the passed file descriptor is + never valid after the function has been called. However, + close still can return an error, for + example if there was a file system failure. But this error is + not very useful because the absence of an error does not mean + that all caches have been emptied and previous writes have + been made durable. Programs which need such guarantees must + open files with O_SYNC or use + fsync or fdatasync, and + may also have to fsync the directory + containing the file. + +
+
+ Closing descriptors and race conditions + + Unlike process IDs, which are recycle only gradually, the + kernel always allocates the lowest unused file descriptor when + a new descriptor is created. This means that in a + multi-threaded program which constantly opens and closes file + descriptors, descriptors are reused very quickly. Unless + descriptor closing and other operations on the same file + descriptor are synchronized (typically, using a mutex), there + will be race coniditons and I/O operations will be applied to + the wrong file descriptor. + + + Sometimes, it is necessary to close a file descriptor + concurrently, while another thread might be about to use it in + a system call. In order to support this, a program needs to + create a single special file descriptor, one on which all I/O + operations fail. One way to achieve this is to use + socketpair, close one of the descriptors, + and call shutdown(fd, SHUTRDWR) on the + other. + + + When a descriptor is closed concurrently, the program does not + call close on the descriptor. Instead it + program uses dup2 to replace the + descriptor to be closed with the dummy descriptor created + earlier. This way, the kernel will not reuse the descriptor, + but it will carry out all other steps associated with calling + a descriptor (for instance, if the descriptor refers to a + stream socket, the peer will be notified). + + + This is just a sketch, and many details are missing. + Additional data structures are needed to determine when it is + safe to really close the descriptor, and proper locking is + required for that. + +
+
+ Lingering state after close + + By default, closing a stream socket returns immediately, and + the kernel will try to send the data in the background. This + means that it is impossible to implement accurate accounting + of network-related resource utilization from userspace. + + + The SO_LINGER socket option alters the + behavior of close, so that it will return + only after the lingering data has been processed, either by + sending it to the peer successfully, or by discarding it after + the configured timeout. However, there is no interface which + could perform this operation in the background, so a separate + userspace thread is needed for each close + call, causing scalability issues. + + + Currently, there is no application-level countermeasure which + applies universally. Mitigation is possible with + iptables (the + connlimit match type in particular) and + specialized filtering devices for denial-of-service network + traffic. + + + These problems are not related to the + TIME_WAIT state commonly seen in + netstat output. The kernel + automatically expires such sockets if necessary. + +
+
+ +
+ Preventing file descriptor leaks to child processes + + Child processes created with fork share + the initial set of file descriptors with their parent + process. By default, file descriptors are also preserved if + a new process image is created with execve + (or any of the other functions such as system + or posix_spawn). + + + Usually, this behavior is not desirable. There are two ways to + turn it off, that is, to prevent new process images from + inheriting the file descriptors in the parent process: + + + + + Set the close-on-exec flag on all newly created file + descriptors. Traditionally, this flag is controlled by the + FD_CLOEXEC flag, using + F_GETFD and F_SETFD + operations of the fcntl function. + + + However, in a multi-threaded process, there is a race + condition: a subprocess could have been created between the + time the descriptor was created and the + FD_CLOEXEC was set. Therefore, many system + calls which create descriptors (such as + open and openat) + now accept the O_CLOEXEC flag + (SOCK_CLOEXEC for + socket and + socketpair), which cause the + FD_CLOEXEC flag to be set for the file + descriptor in an atomic fashion. In addition, a few new + systems calls were introduced, such as + pipe2 and dup3. + + + The downside of this approach is that every descriptor needs + to receive special treatment at the time of creation, + otherwise it is not completely effective. + + + + + After calling fork, but before creating + a new process image with execve, all + file descriptors which the child process will not need are + closed. + + + Traditionally, this was implemented as a loop over file + descriptors ranging from 3 to + 255 and later 1023. + But this is only an approximatio because it is possible to + create file descriptors outside this range easily (see ). + Another approach reads /proc/self/fd + and closes the unexpected descriptors listed there, but this + approach is much slower. + + + + + At present, environments which care about file descriptor + leakage implement the second approach. OpenJDK 6 and 7 + are among them. + +
+ +
+ Dealing with the <function>select</function> limit + + By default, a user is allowed to open only 1024 files in a + single process, but the system administrator can easily change + this limit (which is necessary for busy network servers). + However, there is another restriction which is more difficult to + overcome. + + + The select function only supports a + maximum of FD_SETSIZE file descriptors + (that is, the maximum permitted value for a file descriptor + is FD_SETSIZE - 1, usually 1023.) If a + process opens many files, descriptors may exceed such + limits. It is impossible to query such descriptors using + select. + + + If a library which creates many file descriptors is used in + the same process as a library which uses + select, at least one of them needs to + be changed. + Calls to select can be replaced with + calls to poll or another event handling + mechanism. + + + Alternatively, the library with high descriptor usage can + relocate descriptors above the FD_SETSIZE + limit using the following procedure. + + + + + Create the file descriptor fd as + usual, preferably with the O_CLOEXEC + flag. + + + + + Before doing anything else with the descriptor + fd, invoke: + + + int newfd = fcntl(fd, F_DUPFD_CLOEXEC, (long)FD_SETSIZE); + + + + + Check that newfd result is + non-negative, otherwise close fd and + report an error, and return. + + + + + Close fd and continue to use + newfd. + + + + + The new descriptor has been allocated above the + FD_SETSIZE. Even though this algorithm + is racy in the sense that the FD_SETSIZE + first descriptors could fill up, a very high degree of + physical parallelism is required before this becomes a problem. + +
+
diff --git a/defensive-coding/tmp/en-US/xml_tmp/Tasks/File_System.xml b/defensive-coding/tmp/en-US/xml_tmp/Tasks/File_System.xml new file mode 100644 index 0000000..ee3eb17 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml_tmp/Tasks/File_System.xml @@ -0,0 +1,339 @@ + + + + File system manipulation + + In this chapter, we discuss general file system manipulation, with + a focus on access files and directories to which an other, + potentially untrusted user has write access. + + + Temporary files are covered in their own chapter, . + +
+ Working with files and directories owned by other users + + Sometimes, it is necessary to operate on files and directories + owned by other (potentially untrusted) users. For example, a + system administrator could remove the home directory of a user, + or a package manager could update a file in a directory which is + owned by an application-specific user. This differs from + accessing the file system as a specific user; see + . + + + Accessing files across trust boundaries faces several + challenges, particularly if an entire directory tree is being + traversed: + + + + + Another user might add file names to a writable directory at + any time. This can interfere with file creation and the + order of names returned by readdir. + + + + + Merely opening and closing a file can have side effects. + For instance, an automounter can be triggered, or a tape + device rewound. Opening a file on a local file system can + block indefinitely, due to mandatory file locking, unless + the O_NONBLOCK flag is specified. + + + + + Hard links and symbolic links can redirect the effect of + file system operations in unexpected ways. The + O_NOFOLLOW and + AT_SYMLINK_NOFOLLOW variants of system + calls only affected final path name component. + + + + + The structure of a directory tree can change. For example, + the parent directory of what used to be a subdirectory + within the directory tree being processed could suddenly + point outside that directory tree. + + + + + Files should always be created with the + O_CREAT and O_EXCL flags, + so that creating the file will fail if it already exists. This + guards against the unexpected appearance of file names, either + due to creation of a new file, or hard-linking of an existing + file. In multi-threaded programs, rather than manipulating the + umask, create the files with mode 000 if + possible, and adjust it afterwards with + fchmod. + + + To avoid issues related to symbolic links and directory tree + restructuring, the “at” variants of system + calls have to be used (that is, functions like + openat, fchownat, + fchmodat, and + unlinkat, together with + O_NOFOLLOW or + AT_SYMLINK_NOFOLLOW). Path names passed to + these functions must have just a single component (that is, + without a slash). When descending, the descriptors of parent + directories must be kept open. The missing + opendirat function can be emulated with + openat (with an + O_DIRECTORY flag, to avoid opening special + files with side effects), followed by + fdopendir. + + + If the “at” functions are not available, it + is possible to emulate them by changing the current directory. + (Obviously, this only works if the process is not multi-threaded.) + fchdir has to be used to change the current + directory, and the descriptors of the parent directories have to + be kept open, just as with the “at”-based + approach. chdir("...") is unsafe because it + might ascend outside the intended directory tree. + + + This “at” function emulation is currently + required when manipulating extended attributes. In this case, + the lsetxattr function can be used, with a + relative path name consisting of a single component. This also + applies to SELinux contexts and the + lsetfilecon function. + + + Currently, it is not possible to avoid opening special files + and changes to files with hard links if the + directory containing them is owned by an untrusted user. + (Device nodes can be hard-linked, just as regular files.) + fchmodat and fchownat + affect files whose link count is greater than one. But opening + the files, checking that the link count is one with + fstat, and using + fchmod and fchown on + the file descriptor may have unwanted side effects, due to item + 2 above. When creating directories, it is therefore important + to change the ownership and permissions only after it has been + fully created. Until that point, file names are stable, and no + files with unexpected hard links can be introduced. + + + Similarly, when just reading a directory owned by an untrusted + user, it is currently impossible to reliably avoid opening + special files. + + + There is no workaround against the instability of the file list + returned by readdir. Concurrent + modification of the directory can result in a list of files + being returned which never actually existed on disk. + + + Hard links and symbolic links can be safely deleted using + unlinkat without further checks because + deletion only affects the name within the directory tree being + processed. + +
+
+ Accessing the file system as a different user + + This section deals with access to the file system as a specific + user. This is different from accessing files and directories owned by a + different, potentially untrusted user; see . + + + One approach is to spawn a child process which runs under the + target user and group IDs (both effective and real IDs). Note + that this child process can block indefinitely, even when + processing regular files only. For example, a special FUSE file + system could cause the process to hang in uninterruptible sleep + inside a stat system call. + + + An existing process could change its user and group ID using + setfsuid and setfsgid. + (These functions are preferred over seteuid + and setegid because they do not allow the + impersonated user to send signals to the process.) These + functions are not thread safe. In multi-threaded processes, + these operations need to be performed in a single-threaded child + process. Unexpected blocking may occur as well. + + + It is not recommended to try to reimplement the kernel + permission checks in user space because the required checks are + complex. It is also very difficult to avoid race conditions + during path name resolution. + +
+
+ File system limits + + For historical reasons, there are preprocessor constants such as + PATH_MAX, NAME_MAX. + However, on most systems, the length of canonical path names + (absolute path names with all symbolic links resolved, as + returned by realpath or + canonicalize_file_name) can exceed + PATH_MAX bytes, and individual file name + components can be longer than NAME_MAX. This + is also true of the _PC_PATH_MAX and + _PC_NAME_MAX values returned by + pathconf, and the + f_namemax member of struct + statvfs. Therefore, these constants should not be + used. This is also reason why the + readdir_r should never be used (instead, + use readdir). + + + You should not write code in a way that assumes that there is an + upper limit on the number of subdirectories of a directory, the + number of regular files in a directory, or the link count of an + inode. + +
+
+ File system features + + Not all file systems support all features. This makes it very + difficult to write general-purpose tools for copying files. For + example, a copy operation intending to preserve file permissions + will generally fail when copying to a FAT file system. + + + + + Some file systems are case-insensitive. Most should be + case-preserving, though. + + + + + Name length limits vary greatly, from eight to thousands of + bytes. Path length limits differ as well. Most systems + impose an upper bound on path names passed to the kernel, + but using relative path names, it is possible to create and + access files whose absolute path name is essentially of + unbounded length. + + + + + Some file systems do not store names as fairly unrestricted + byte sequences, as it has been traditionally the case on GNU + systems. This means that some byte sequences (outside the + POSIX safe character set) are not valid names. Conversely, + names of existing files may not be representable as byte + sequences, and the files are thus inaccessible on GNU + systems. Some file systems perform Unicode canonicalization + on file names. These file systems preserve case, but + reading the name of a just-created file using + readdir might still result in a + different byte sequence. + + + + + Permissions and owners are not universally supported (and + SUID/SGID bits may not be available). For example, FAT file + systems assign ownership based on a mount option, and + generally mark all files as executable. Any attempt to + change permissions would result in an error. + + + + + Non-regular files (device nodes, FIFOs) are not generally + available. + + + + + Only on some file systems, files can have holes, that is, + not all of their contents is backed by disk storage. + + + + + ioctl support (even fairly generic + functionality such as FIEMAP for + discovering physical file layout and holes) is + file-system-specific. + + + + + Not all file systems support extended attributes, ACLs and + SELinux metadata. Size and naming restriction on extended + attributes vary. + + + + + Hard links may not be supported at all (FAT) or only within + the same directory (AFS). Symbolic links may not be + available, either. Reflinks (hard links with copy-on-write + semantics) are still very rare. Recent systems restrict + creation of hard links to users which own the target file or + have read/write access to it, but older systems do not. + + + + + Renaming (or moving) files using rename + can fail (even when stat indicates that + the source and target directories are located on the same + file system). This system call should work if the old and + new paths are located in the same directory, though. + + + + + Locking semantics vary among file systems. This affects + advisory and mandatory locks. For example, some network + file systems do not allow deleting files which are opened by + any process. + + + + + Resolution of time stamps varies from two seconds to + nanoseconds. Not all time stamps are available on all file + systems. File creation time (birth + time) is not exposed over the + stat/fstat + interface, even if stored by the file system. + + + +
+
+ Checking free space + + The statvfs and + fstatvfs functions allow programs to + examine the number of available blocks and inodes, through the + members f_bfree, f_bavail, + f_ffree, and f_favail of + struct statvfs. Some file systems return + fictional values in the f_ffree and + f_favail fields, so the only reliable way to + discover if the file system still has space for a file is to try + to create it. The f_bfree field should be + reasonably accurate, though. + +
+
+ diff --git a/defensive-coding/tmp/en-US/xml_tmp/Tasks/Library_Design.xml b/defensive-coding/tmp/en-US/xml_tmp/Tasks/Library_Design.xml new file mode 100644 index 0000000..7c959ab --- /dev/null +++ b/defensive-coding/tmp/en-US/xml_tmp/Tasks/Library_Design.xml @@ -0,0 +1,195 @@ + + + + Library Design + + Throught this section, the term client code + refers to applications and other libraries using the library. + + +
+ State management + + +
+ Global state + + Global state should be avoided. + + + If this is impossible, the global state must be protected with + a lock. For C/C++, you can use the + pthread_mutex_lock + and pthread_mutex_unlock + functions without linking against -lpthread + because the system provides stubs for non-threaded processes. + + + For compatibility with fork, these locks + should be acquired and released in helpers registered with + pthread_atfork. This function is not + available without -lpthread, so you need to + use dlsym or a weak symbol to obtain its + address. + + + If you need fork protection for other + reasons, you should store the process ID and compare it to the + value returned by getpid each time you + access the global state. (getpid is not + implemented as a system call and is fast.) If the value + changes, you know that you have to re-create the state object. + (This needs to be combined with locking, of course.) + +
+
+ Handles + + Library state should be kept behind a curtain. Client code + should receive only a handle. In C, the handle can be a + pointer to an incomplete struct. In C++, + the handle can be a pointer to an abstract base class, or it + can be hidden using the pointer-to-implementation idiom. + + + The library should provide functions for creating and + destroying handles. (In C++, it is possible to use virtual + destructors for the latter.) Consistency between creation and + destruction of handles is strongly recommended: If the client + code created a handle, it is the responsibility of the client + code to destroy it. (This is not always possible or + convenient, so sometimes, a transfer of ownership has to + happen.) + + + Using handles ensures that it is possible to change the way + the library represents state in a way that is transparent to + client code. This is important to facilitate security updates + and many other code changes. + + + It is not always necessary to protect state behind a handle + with a lock. This depends on the level of thread safety + the library provides. + +
+
+ +
+ Object orientation + + Classes should be either designed as base classes, or it should + be impossible to use them as base classes (like + final classes in Java). Classes which are + not designed for inheritance and are used as base classes + nevertheless create potential maintenance hazards because it is + difficult to predict how client code will react when calls to + virtual methods are added, reordered or removed. + + + Virtual member functions can be used as callbacks. See + + for some of the challenges involved. + +
+ +
+ Callbacks + + Higher-order code is difficult to analyze for humans and + computers alike, so it should be avoided. Often, an + iterator-based interface (a library function which is called + repeatedly by client code and returns a stream of events) leads + to a better design which is easier to document and use. + + + If callbacks are unavoidable, some guidelines for them follow. + + + In modern C++ code, std::function objects + should be used for callbacks. + + + In older C++ code and in C code, all callbacks must have an + additional closure parameter of type void *, + the value of which can be specified by client code. If + possible, the value of the closure parameter should be provided + by client code at the same time a specific callback is + registered (or specified as a function argument). If a single + closure parameter is shared by multiple callbacks, flexibility + is greatly reduced, and conflicts between different pieces of + client code using the same library object could be unresolvable. + In some cases, it makes sense to provide a de-registration + callback which can be used to destroy the closure parameter when + the callback is no longer used. + + + Callbacks can throw exceptions or call + longjmp. If possible, all library objects + should remain in a valid state. (All further operations on them + can fail, but it should be possible to deallocate them without + causing resource leaks.) + + + The presence of callbacks raises the question if functions + provided by the library are reentrant. + Unless a library was designed for such use, bad things will + happen if a callback function uses functions in the same library + (particularly if they are invoked on the same objects and + manipulate the same state). When the callback is invoked, the + library can be in an inconsistent state. Reentrant functions + are more difficult to write than thread-safe functions (by + definition, simple locking would immediately lead to deadlocks). + It is also difficult to decide what to do when destruction of an + object which is currently processing a callback is requested. + +
+ +
+ Process attributes + + Several attributes are global and affect all code in the + process, not just the library that manipulates them. + + + + environment variables + (see ) + + + umask + + + user IDs, group IDs and capabilities + + + current working directory + + + signal handlers, signal masks and signal delivery + + + file locks (especially fcntl locks + behave in surprising ways, not just in a multi-threaded + environment) + + + + Library code should avoid manipulating these global process + attributes. It should not rely on environment variables, umask, + the current working directory and signal masks because these + attributes can be inherted from an untrusted source. + + + In addition, there are obvious process-wide aspects such as the + virtual memory layout, the set of open files and dynamic shared + objects, but with the exception of shared objects, these can be + manipulated in a relatively isolated way. + + +
+ +
+ + diff --git a/defensive-coding/tmp/en-US/xml_tmp/Tasks/Locking.xml b/defensive-coding/tmp/en-US/xml_tmp/Tasks/Locking.xml new file mode 100644 index 0000000..f85e61e --- /dev/null +++ b/defensive-coding/tmp/en-US/xml_tmp/Tasks/Locking.xml @@ -0,0 +1,5 @@ + + + + diff --git a/defensive-coding/tmp/en-US/xml_tmp/Tasks/Processes.xml b/defensive-coding/tmp/en-US/xml_tmp/Tasks/Processes.xml new file mode 100644 index 0000000..90f01f0 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml_tmp/Tasks/Processes.xml @@ -0,0 +1,483 @@ + + + + Processes + +
+ Safe process creation + + This section describes how to create new child processes in a + safe manner. In addition to the concerns addressed below, there + is the possibility of file descriptor leaks, see . + +
+ Obtaining the program path and the command line + template + + The name and path to the program being invoked should be + hard-coded or controlled by a static configuration file stored + at a fixed location (at an file system absolute path). The + same applies to the template for generating the command line. + + + The configured program name should be an absolute path. If it + is a relative path, the contents of the PATH + must be obtained in s secure manner (see ). + If the PATH variable is not set or untrusted, + the safe default /bin:/usr/bin must be + used. + + + If too much flexibility is provided here, it may allow + invocation of arbitrary programs without proper authorization. + +
+ +
+ Bypassing the shell + + Child processes should be created without involving the system + shell. + + + For C/C++, system should not be used. + The posix_spawn function can be used + instead, or a combination fork and + execve. (In some cases, it may be + preferable to use vfork or the + Linux-specific clone system call instead + of fork.) + + + In Python, the subprocess module bypasses + the shell by default (when the shell + keyword argument is not set to true). + os.system should not be used. + + + The Java class java.lang.ProcessBuilder can be + used to create subprocesses without interference from the + system shell. + + + Portability notice + + On Windows, there is no argument vector, only a single + argument string. Each application is responsible for parsing + this string into an argument vector. There is considerable + variance among the quoting style recognized by applications. + Some of them expand shell wildcards, others do not. Extensive + application-specific testing is required to make this secure. + + + + Note that some common applications (notably + ssh) unconditionally introduce the + use of a shell, even if invoked directly without a shell. It is + difficult to use these applications in a secure manner. In this + case, untrusted data should be supplied by other means. For + example, standard input could be used, instead of the command + line. + +
+ +
+ Specifying the process environment + + Child processes should be created with a minimal set of + environment variables. This is absolutely essential if there + is a trust transition involved, either when the parent process + was created, or during the creation of the child process. + + + In C/C++, the environment should be constructed as an array of + strings and passed as the envp argument to + posix_spawn or execve. + The functions setenv, + unsetenv and putenv + should not be used. They are not thread-safe and suffer from + memory leaks. + + + Python programs need to specify a dict for + the the env argument of the + subprocess.Popen constructor. + The Java class java.lang.ProcessBuilder + provides a environment() method, + which returns a map that can be manipulated. + + + The following list provides guidelines for selecting the set + of environment variables passed to the child process. + + + + + PATH should be initialized to + /bin:/usr/bin. + + + + + USER and HOME can be inhereted + from the parent process environment, or they can be + initialized from the pwent structure + for the user. + + + + The DISPLAY and XAUTHORITY + variables should be passed to the subprocess if it is an X + program. Note that this will typically not work across trust + boundaries because XAUTHORITY refers to a file + with 0600 permissions. + + + + + The location-related environment variables + LANG, LANGUAGE, + LC_ADDRESS, LC_ALL, + LC_COLLATE, LC_CTYPE, + LC_IDENTIFICATION, + LC_MEASUREMENT, LC_MESSAGES, + LC_MONETARY, LC_NAME, + LC_NUMERIC, LC_PAPER, + LC_TELEPHONE and LC_TIME + can be passed to the subprocess if present. + + + + + The called process may need application-specific + environment variables, for example for passing passwords. + (See .) + + + + + All other environment variables should be dropped. Names + for new environment variables should not be accepted from + untrusted sources. + + + +
+ +
+ Robust argument list processing + + When invoking a program, it is sometimes necessary to include + data from untrusted sources. Such data should be check + against embedded NUL characters because the + system APIs will sliently truncate argument strings at the first + NUL character. + + + The following recommendations assume that the program being + invoked uses GNU-style option processing using + getopt_long. This convention is widely + used, but it is just that, and individual programs might + interpret a command line in a different way. + + + If the untrusted data has to go into an option, use the + --option-name=VALUE syntax, placing the + option and its value into the same command line argument. + This avoids any potential confusion if the data starts with + -. + + + For positional arguments, terminate the option list with a + single marker after the last option, and + include the data at the right position. The + marker terminates option processing, and + the data will not be treated as an option even if it starts + with a dash. + +
+ +
+ Passing secrets to subprocesses + + The command line (the name of the program and its argument) of + a running process is traditionally available to all local + users. The called program can overwrite this information, but + only after it has run for a bit of time, during which the + information may have been read by other processes. However, + on Linux, the process environment is restricted to the user + who runs the process. Therefore, if you need a convenient way + to pass a password to a child process, use an environment + variable, and not a command line argument. (See .) + + + Portability notice + + On some UNIX-like systems (notably Solaris), environment + variables can be read by any system user, just like command + lines. + + + + If the environment-based approach cannot be used due to + portability concerns, the data can be passed on standard + input. Some programs (notably gpg) + use special file descriptors whose numbers are specified on + the command line. Temporary files are an option as well, but + they might give digital forensics access to sensitive data + (such as passphrases) because it is difficult to safely delete + them in all cases. + +
+
+ +
+ Handling child process termination + + When child processes terminate, the parent process is signalled. + A stub of the terminated processes (a + zombie, shown as + <defunct> by + ps) is kept around until the status + information is collected (reaped) by the + parent process. Over the years, several interfaces for this + have been invented: + + + + + The parent process calls wait, + waitpid, waitid, + wait3 or wait4, + without specifying a process ID. This will deliver any + matching process ID. This approach is typically used from + within event loops. + + + + + The parent process calls waitpid, + waitid, or wait4, + with a specific process ID. Only data for the specific + process ID is returned. This is typically used in code + which spawns a single subprocess in a synchronous manner. + + + + + The parent process installs a handler for the + SIGCHLD signal, using + sigaction, and specifies to the + SA_NOCLDWAIT flag. + This approach could be used by event loops as well. + + + + + None of these approaches can be used to wait for child process + terminated in a completely thread-safe manner. The parent + process might execute an event loop in another thread, which + could pick up the termination signal. This means that libraries + typically cannot make free use of child processes (for example, + to run problematic code with reduced privileges in a separate + address space). + + + At the moment, the parent process should explicitly wait for + termination of the child process using + waitpid or waitpid, + and hope that the status is not collected by an event loop + first. + +
+ +
+ <literal>SUID</literal>/<literal>SGID</literal> + processes + + + Programs can be marked in the file system to indicate to the + kernel that a trust transition should happen if the program is + run. The SUID file permission bit indicates + that an executable should run with the effective user ID equal + to the owner of the executable file. Similarly, with the + SGID bit, the effective group ID is set to + the group of the executable file. + + + Linux supports fscaps, which can grant + additional capabilities to a process in a finer-grained manner. + Additional mechanisms can be provided by loadable security + modules. + + + When such a trust transition has happened, the process runs in a + potentially hostile environment. Additional care is necessary + not to rely on any untrusted information. These concerns also + apply to libraries which can be linked into such processes. + + +
+ Accessing environment variables + + The following steps are required so that a program does not + accidentally pick up untrusted data from environment + variables. + + + + Compile your C/C++ sources with -D_GNU_SOURCE. + The Autoconf macro AC_GNU_SOURCE ensures this. + + + Check for the presence of the secure_getenv + and __secure_getenv function. The Autoconf + directive AC_CHECK_FUNCS([__secure_getenv secure_getenv]) + performs these checks. + + + Arrange for a proper definition of the + secure_getenv function. See . + + + Use secure_getenv instead of + getenv to obtain the value of critical + environment variables. secure_getenv + will pretend the variable has not bee set if the process + environment is not trusted. + + + + Critical environment variables are debugging flags, + configuration file locations, plug-in and log file locations, + and anything else that might be used to bypass security + restrictions or cause a privileged process to behave in an + unexpected way. + + + Either the secure_getenv function or the + __secure_getenv is available from GNU libc. + + + Obtaining a definition for <function>secure_getenv</function> + + + +#ifndef HAVE_SECURE_GETENV +# ifdef HAVE__SECURE_GETENV +# define secure_getenv __secure_getenv +# else +# error neither secure_getenv nor __secure_getenv are available +# endif +#endif +]]> + + +
+
+ +
+ Daemons + + Background processes providing system services + (daemons) need to decouple themselves from + the controlling terminal and the parent process environment: + + + + Fork. + + + + In the child process, call setsid. The + parent process can simply exit (using + _exit, to avoid running clean-up + actions twice). + + + + + In the child process, fork again. Processing continues in + the child process. Again, the parent process should just + exit. + + + + + Replace the descriptors 0, 1, 2 with a descriptor for + /dev/null. Logging should be + redirected to syslog. + + + + + Older instructions for creating daemon processes recommended a + call to umask(0). This is risky because it + often leads to world-writable files and directories, resulting + in security vulnerabilities such as arbitrary process + termination by untrusted local users, or log file truncation. + If the umask needs setting, a restrictive + value such as 027 or 077 + is recommended. + + + Other aspects of the process environment may have to changed as + well (environment variables, signal handler disposition). + + + It is increasingly common that server processes do not run as + background processes, but as regular foreground process under a + supervising master process (such as + systemd). Server processes should + offer a command line option which disables forking and + replacement of the standard output and standard error streams. + Such an option is also useful for debugging. + +
+ +
+ Semantics of command line arguments + + + After process creation and option processing, it is up to the + child process to interpret the arguments. Arguments can be + file names, host names, or URLs, and many other things. URLs + can refer to the local network, some server on the Internet, + or to the local file system. Some applications even accept + arbitrary code in arguments (for example, + python with the + option). + + + Similar concerns apply to environment variables, the contents + of the current directory and its subdirectories. + + + + Consequently, careful analysis is required if it is safe to + pass untrusted data to another program. + +
+ +
+ <function>fork</function> as a primitive for parallelism + + A call to fork which is not immediately + followed by a call to execve (perhaps after + rearranging and closing file descriptors) is typically unsafe, + especially from a library which does not control the state of + the entire process. Such use of fork + should be replaced with proper child processes or threads. + +
+ +
diff --git a/defensive-coding/tmp/en-US/xml_tmp/Tasks/Serialization.xml b/defensive-coding/tmp/en-US/xml_tmp/Tasks/Serialization.xml new file mode 100644 index 0000000..60427c5 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml_tmp/Tasks/Serialization.xml @@ -0,0 +1,397 @@ + + + + Serialization and Deserialization + + Protocol decoders and file format parsers are often the + most-exposed part of an application because they are exposed with + little or no user interaction and before any authentication and + security checks are made. They are also difficult to write + robustly in languages which are not memory-safe. + + +
+ Recommendations for manually written decoders + + For C and C++, the advice in applies. In + addition, avoid non-character pointers directly into input + buffers. Pointer misalignment causes crashes on some + architectures. + + + When reading variable-sized objects, do not allocate large + amounts of data solely based on the value of a size field. If + possible, grow the data structure as more data is read from the + source, and stop when no data is available. This helps to avoid + denial-of-service attacks where little amounts of input data + results in enormous memory allocations during decoding. + Alternatively, you can impose reasonable bounds on memory + allocations, but some protocols do not permit this. + +
+ +
+ Protocol design + + Binary formats with explicit length fields are more difficult to + parse robustly than those where the length of dynamically-sized + elements is derived from sentinel values. A protocol which does + not use length fields and can be written in printable ASCII + characters simplifies testing and debugging. However, binary + protocols with length fields may be more efficient to parse. + +
+ +
+ Library + support for deserialization + + For some languages, generic libraries are available which allow + to serialize and deserialize user-defined objects. The + deserialization part comes in one of two flavors, depending on + the library. The first kind uses type information in the data + stream to control which objects are instantiated. The second + kind uses type definitions supplied by the programmer. The + first one allows arbitrary object instantiation, the second one + generally does not. + + + The following serialization frameworks are in the first category, + are known to be unsafe, and must not be used for untrusted data: + + + + Python's pickle and cPickle + modules + + + Perl's Storable package + + + Java serialization (java.io.ObjectInputStream) + + + PHP serialization (unserialize) + + + Most implementations of YAML + + + + When using a type-directed deserialization format where the + types of the deserialized objects are specified by the + programmer, make sure that the objects which can be instantiated + cannot perform any destructive actions in their destructors, + even when the data members have been manipulated. + + + JSON decoders do not suffer from this problem. But you must not + use the eval function to parse JSON objects + in Javascript; even with the regular expression filter from RFC + 4627, there are still information leaks remaining. + +
+ +
+ XML serialization + + +
+ External references + + XML documents can contain external references. They can occur + in various places. + + + + + In the DTD declaration in the header of an XML document: + + + +]]> + + + + + + In a namespace declaration: + + + +]]> + + + + + + In an entity defintion: + + + + +]]> + + + + + + In a notation: + + + +]]> + + + + + + Originally, these external references were intended as unique + identifiers, but by many XML implementations, they are used + for locating the data for the referenced element. This causes + unwanted network traffic, and may disclose file system + contents or otherwise unreachable network resources, so this + functionality should be disabled. + + + Depending on the XML library, external referenced might be + processed not just when parsing XML, but also when generating + it. + +
+
+ Entity expansion + + When external DTD processing is disabled, an internal DTD + subset can still contain entity definitions. Entity + declarations can reference other entities. Some XML libraries + expand entities automatically, and this processing cannot be + switched off in some places (such as attribute values or + content models). Without limits on the entity nesting level, + this expansion results in data which can grow exponentially in + length with size of the input. (If there is a limit on the + nesting level, the growth is still polynomial, unless further + limits are imposed.) + + + Consequently, the processing internal DTD subsets should be + disabled if possible, and only trusted DTDs should be + processed. If a particular XML application does not permit + such restrictions, then application-specific limits are called + for. + +
+ +
+ XInclude processing + + XInclude processing can reference file and network resources + and include them into the document, much like external entity + references. When parsing untrusted XML documents, XInclude + processing should be truned off. + + + XInclude processing is also fairly complex and may pull in + support for the XPointer and XPath specifications, + considerably increasing the amount of code required for XML + processing. + +
+ +
+ Algorithmic complexity of XML validation + + DTD-based XML validation uses regular expressions for content + models. The XML specification requires that content models + are deterministic, which means that efficient validation is + possible. However, some implementations do not enforce + determinism, and require exponential (or just polynomial) + amount of space or time for validating some DTD/document + combinations. + + + XML schemas and RELAX NG (via the xsd: + prefix) directly support textual regular expressions which are + not required to be deterministic. + +
+
+ Using Expat for XML parsing + + By default, Expat does not try to resolve external IDs, so no + steps are required to block them. However, internal entity + declarations are processed. Installing a callback which stops + parsing as soon as such entities are encountered disables + them, see . + Expat does not perform any validation, so there are no + problems related to that. + + + Disabling XML entity processing with Expat + + + + This handler must be installed when the + XML_Parser object is created (). + + + Creating an Expat XML parser + + + + It is also possible to reject internal DTD subsets altogeher, + using a suitable + XML_StartDoctypeDeclHandler handler + installed with XML_SetDoctypeDeclHandler. + +
+ +
+ Using OpenJDK for XML parsing and validation + + OpenJDK contains facilities for DOM-based, SAX-based, and + StAX-based document parsing. Documents can be validated + against DTDs or XML schemas. + + + The approach taken to deal with entity expansion differs from + the general recommendation in . + We enable the the feature flag + javax.xml.XMLConstants.FEATURE_SECURE_PROCESSING, + which enforces heuristic restrictions on the number of entity + expansions. Note that this flag alone does not prevent + resolution of external references (system IDs or public IDs), + so it is slightly misnamed. + + + In the following sections, we use helper classes to prevent + external ID resolution. + + + Helper class to prevent DTD external entity resolution in OpenJDK + + + + Helper class to prevent schema resolution in + OpenJDK + + + + + shows the imports used by the examples. + + + Java imports for OpenJDK XML parsing + + +
+ DOM-based XML parsing and DTD validation in OpenJDK + + This approach produces a + org.w3c.dom.Document object from an input + stream. + use the data from the java.io.InputStream + instance in the inputStream variable. + + + DOM-based XML parsing in OpenJDK + + + + External entity references are prohibited using the + NoEntityResolver class in + . + Because external DTD references are prohibited, DTD validation + (if enabled) will only happen against the internal DTD subset + embedded in the XML document. + + + To validate the document against an external DTD, use a + javax.xml.transform.Transformer class to + add the DTD reference to the document, and an entity + resolver which whitelists this external reference. + +
+ +
+ XML Schema validation in OpenJDK + + + shows how to validate a document against an XML Schema, + using a SAX-based approach. The XML data is read from an + java.io.InputStream in the + inputStream variable. + + + SAX-based validation against an XML schema in + OpenJDK + + + + The NoResourceResolver class is defined + in . + + + If you need to validate a document against an XML schema, + use the code in + to create the document, but do not enable validation at this + point. Then use + + to perform the schema-based validation on the + org.w3c.dom.Document instance + document. + + + Validation of a DOM document against an XML schema in + OpenJDK + + +
+
+
+ +
+ Protocol Encoders + + For protocol encoders, you should write bytes to a buffer which + grows as needed, using an exponential sizing policy. Explicit + lengths can be patched in later, once they are known. + Allocating the required number of bytes upfront typically + requires separate code to compute the final size, which must be + kept in sync with the actual encoding step, or vulnerabilities + may result. In multi-threaded code, parts of the object being + deserialized might change, so that the computed size is out of + date. + + + You should avoid copying data directly from a received packet + during encoding, disregarding the format. Propagating malformed + data could enable attacks on other recipients of that data. + + + When using C or C++ and copying whole data structures directly + into the output, make sure that you do not leak information in + padding bytes between fields or at the end of the + struct. + +
+ +
+ diff --git a/defensive-coding/tmp/en-US/xml_tmp/Tasks/Temporary_Files.xml b/defensive-coding/tmp/en-US/xml_tmp/Tasks/Temporary_Files.xml new file mode 100644 index 0000000..d78bad7 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml_tmp/Tasks/Temporary_Files.xml @@ -0,0 +1,257 @@ + + + + Temporary files + + In this chapter, we describe how to create temporary files and + directories, how to remove them, and how to work with programs + which do not create files in ways that a safe with a shared + directory for temporary files. General file system manipulation + is treated in a separate chapter, . + + + Secure creation of temporary files has four different aspects. + + + + + The location of the directory for temporary files must be + obtained in a secure manner (that is, untrusted environment + variables must be ignored, see ). + + + + + A new file must be created. Reusing an existing file must be + avoided (the /tmp race + condition). This is tricky because traditionally, system-wide + temporary directories shared by all users are used. + + + + + The file must be created in a way that makes it impossible for + other users to open it. + + + + + The descriptor for the temporary file should not leak to + subprocesses. + + + + + All functions mentioned below will take care of these aspects. + + + Traditionally, temporary files are often used to reduce memory + usage of programs. More and more systems use RAM-based file + systems such as tmpfs for storing temporary + files, to increase performance and decrease wear on Flash storage. + As a result, spooling data to temporary files does not result in + any memory savings, and the related complexity can be avoided if + the data is kept in process memory. + + +
+ Obtaining the location of temporary directory + + Some functions below need the location of a directory which + stores temporary files. For C/C++ programs, use the following + steps to obtain that directory: + + + + + Use secure_getenv to obtain the value + of the TMPDIR environment variable. If + it is set, convert the path to a fully-resolved absolute + path, using realpath(path, NULL). Check + if the new path refers to a directory and is writeable. In + this case, use it as the temporary directory. + + + + + Fall back to /tmp. + + + + + In Python, you can use the tempfile.tempdir + variable. + + + Java does not support SUID/SGID programs, so you can use the + java.lang.System.getenv(String) method to + obtain the value of the TMPDIR environment + variable, and follow the two steps described above. (Java's + default directory selection does not honor + TMPDIR.) + +
+ +
+ Named temporary files + + The mkostemp function creates a named + temporary file. You should specify the + O_CLOEXEC flag to avoid file descriptor leaks + to subprocesses. (Applications which do not use multiple threads + can also use mkstemp, but libraries should + use mkostemp.) For determining the + directory part of the file name pattern, see . + + + The file is not removed automatically. It is not safe to rename + or delete the file before processing, or transform the name in + any way (for example, by adding a file extension). If you need + multiple temporary files, call mkostemp + multiple times. Do not create additional file names derived + from the name provided by a previous + mkostemp call. However, it is safe to close + the descriptor returned by mkostemp and + reopen the file using the generated name. + + + The Python class tempfile.NamedTemporaryFile + provides similar functionality, except that the file is deleted + automatically by default. Note that you may have to use the + file attribute to obtain the actual file + object because some programming interfaces cannot deal with + file-like objects. The C function mkostemp + is also available as tempfile.mkstemp. + + + In Java, you can use the + java.io.File.createTempFile(String, String, + File) function, using the temporary file location + determined according to . + Do not use java.io.File.deleteOnExit() to + delete temporary files, and do not register a shutdown hook for + each temporary file you create. In both cases, the deletion + hint cannot be removed from the system if you delete the + temporary file prior to termination of the VM, causing a memory + leak. + +
+ +
+ Temporary files without names + + The tmpfile function creates a temporary + file and immediately deletes it, while keeping the file open. + As a result, the file lacks a name and its space is deallocated + as soon as the file descriptor is closed (including the implicit + close when the process terminates). This avoids cluttering the + temporary directory with orphaned files. + + + Alternatively, if the maximum size of the temporary file is + known beforehand, the fmemopen function can + be used to create a FILE * object which is + backed by memory. + + + In Python, unnamed temporary files are provided by the + tempfile.TemporaryFile class, and the + tempfile.SpooledTemporaryFile class provides + a way to avoid creation of small temporary files. + + + Java does not support unnamed temporary files. + +
+ +
+ Temporary directories + + The mkdtemp function can be used to create + a temporary directory. (For determining the directory part of + the file name pattern, see .) + The directory is not automatically removed. In Python, this + function is available as tempfile.mkdtemp. + In Java 7, temporary directories can be created using the + java.nio.file.Files.createTempDirectory(Path, String, + FileAttribute...) function. + + + When creating files in the temporary directory, use + automatically generated names, e.g., derived from a sequential + counter. Files with externally provided names could be picked + up in unexpected contexts, and crafted names could actually + point outside of the tempoary directory (due to + directory traversal). + + + Removing a directory tree in a completely safe manner is + complicated. Unless there are overriding performance concerns, + the rm program should be used, with + the and options. + +
+ +
+ Compensating for unsafe file creation + + There are two ways to make a function or program which excepts a + file name safe for use with temporary files. See + , + for details on subprocess creation. + + + + + Create a temporary directory and place the file there. If + possible, run the program in a subprocess which uses the + temporary directory as its current directory, with a + restricted environment. + Use generated names for all files in that temporary + directory. (See .) + + + + + Create the temporary file and pass the generated file name + to the function or program. This only works if the function + or program can cope with a zero-length existing file. It is + safe only under additional assumptions: + + + + + The function or program must not create additional files + whose name is derived from the specified file name or + are otherwise predictable. + + + + + The function or program must not delete the file before + processing it. + + + + + It must not access any existing files in the same + directory. + + + + + It is often difficult to check whether these additional + assumptions are matched, therefore this approach is not + recommended. + + + +
+
diff --git a/defensive-coding/tmp/en-US/xml_tmp/Tasks/schemas.xml b/defensive-coding/tmp/en-US/xml_tmp/Tasks/schemas.xml new file mode 100644 index 0000000..8e84245 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml_tmp/Tasks/schemas.xml @@ -0,0 +1,4 @@ + + + + diff --git a/defensive-coding/tmp/en-US/xml_tmp/Tasks/snippets/Serialization-XML-Expat-Create.xml b/defensive-coding/tmp/en-US/xml_tmp/Tasks/snippets/Serialization-XML-Expat-Create.xml new file mode 100644 index 0000000..dd8724d --- /dev/null +++ b/defensive-coding/tmp/en-US/xml_tmp/Tasks/snippets/Serialization-XML-Expat-Create.xml @@ -0,0 +1,17 @@ + + + + +XML_Parser parser = XML_ParserCreate("UTF-8"); +if (parser == NULL) { + fprintf(stderr, "XML_ParserCreate failed\n"); + close(fd); + exit(1); +} +// EntityDeclHandler needs a reference to the parser to stop +// parsing. +XML_SetUserData(parser, parser); +// Disable entity processing, to inhibit entity expansion. +XML_SetEntityDeclHandler(parser, EntityDeclHandler); + diff --git a/defensive-coding/tmp/en-US/xml_tmp/Tasks/snippets/Serialization-XML-Expat-EntityDeclHandler.xml b/defensive-coding/tmp/en-US/xml_tmp/Tasks/snippets/Serialization-XML-Expat-EntityDeclHandler.xml new file mode 100644 index 0000000..2a982f4 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml_tmp/Tasks/snippets/Serialization-XML-Expat-EntityDeclHandler.xml @@ -0,0 +1,16 @@ + + + + +// Stop the parser when an entity declaration is encountered. +static void +EntityDeclHandler(void *userData, + const XML_Char *entityName, int is_parameter_entity, + const XML_Char *value, int value_length, + const XML_Char *base, const XML_Char *systemId, + const XML_Char *publicId, const XML_Char *notationName) +{ + XML_StopParser((XML_Parser)userData, XML_FALSE); +} + diff --git a/defensive-coding/tmp/en-US/xml_tmp/Tasks/snippets/Serialization-XML-OpenJDK-Errors.xml b/defensive-coding/tmp/en-US/xml_tmp/Tasks/snippets/Serialization-XML-OpenJDK-Errors.xml new file mode 100644 index 0000000..928d79b --- /dev/null +++ b/defensive-coding/tmp/en-US/xml_tmp/Tasks/snippets/Serialization-XML-OpenJDK-Errors.xml @@ -0,0 +1,22 @@ + + + + +class Errors implements ErrorHandler { + @Override + public void warning(SAXParseException exception) { + exception.printStackTrace(); + } + + @Override + public void fatalError(SAXParseException exception) { + exception.printStackTrace(); + } + + @Override + public void error(SAXParseException exception) { + exception.printStackTrace(); + } +} + diff --git a/defensive-coding/tmp/en-US/xml_tmp/Tasks/snippets/Serialization-XML-OpenJDK-Imports.xml b/defensive-coding/tmp/en-US/xml_tmp/Tasks/snippets/Serialization-XML-OpenJDK-Imports.xml new file mode 100644 index 0000000..61f0965 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml_tmp/Tasks/snippets/Serialization-XML-OpenJDK-Imports.xml @@ -0,0 +1,27 @@ + + + + +import javax.xml.XMLConstants; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.sax.SAXSource; +import javax.xml.validation.Schema; +import javax.xml.validation.SchemaFactory; +import javax.xml.validation.Validator; + +import org.w3c.dom.Document; +import org.w3c.dom.ls.LSInput; +import org.w3c.dom.ls.LSResourceResolver; +import org.xml.sax.EntityResolver; +import org.xml.sax.ErrorHandler; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.SAXParseException; +import org.xml.sax.XMLReader; + diff --git a/defensive-coding/tmp/en-US/xml_tmp/Tasks/snippets/Serialization-XML-OpenJDK-NoEntityResolver.xml b/defensive-coding/tmp/en-US/xml_tmp/Tasks/snippets/Serialization-XML-OpenJDK-NoEntityResolver.xml new file mode 100644 index 0000000..e1d1049 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml_tmp/Tasks/snippets/Serialization-XML-OpenJDK-NoEntityResolver.xml @@ -0,0 +1,15 @@ + + + + +class NoEntityResolver implements EntityResolver { + @Override + public InputSource resolveEntity(String publicId, String systemId) + throws SAXException, IOException { + // Throwing an exception stops validation. + throw new IOException(String.format( + "attempt to resolve \"%s\" \"%s\"", publicId, systemId)); + } +} + diff --git a/defensive-coding/tmp/en-US/xml_tmp/Tasks/snippets/Serialization-XML-OpenJDK-NoResourceResolver.xml b/defensive-coding/tmp/en-US/xml_tmp/Tasks/snippets/Serialization-XML-OpenJDK-NoResourceResolver.xml new file mode 100644 index 0000000..6eae01a --- /dev/null +++ b/defensive-coding/tmp/en-US/xml_tmp/Tasks/snippets/Serialization-XML-OpenJDK-NoResourceResolver.xml @@ -0,0 +1,17 @@ + + + + +class NoResourceResolver implements LSResourceResolver { + @Override + public LSInput resolveResource(String type, String namespaceURI, + String publicId, String systemId, String baseURI) { + // Throwing an exception stops validation. + throw new RuntimeException(String.format( + "resolution attempt: type=%s namespace=%s " + + "publicId=%s systemId=%s baseURI=%s", + type, namespaceURI, publicId, systemId, baseURI)); + } +} + diff --git a/defensive-coding/tmp/en-US/xml_tmp/Tasks/snippets/Serialization-XML-OpenJDK_Parse-DOM.xml b/defensive-coding/tmp/en-US/xml_tmp/Tasks/snippets/Serialization-XML-OpenJDK_Parse-DOM.xml new file mode 100644 index 0000000..f04a2af --- /dev/null +++ b/defensive-coding/tmp/en-US/xml_tmp/Tasks/snippets/Serialization-XML-OpenJDK_Parse-DOM.xml @@ -0,0 +1,19 @@ + + + + +DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); +// Impose restrictions on the complexity of the DTD. +factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); + +// Turn on validation. +// This step can be omitted if validation is not desired. +factory.setValidating(true); + +// Parse the document. +DocumentBuilder builder = factory.newDocumentBuilder(); +builder.setEntityResolver(new NoEntityResolver()); +builder.setErrorHandler(new Errors()); +Document document = builder.parse(inputStream); + diff --git a/defensive-coding/tmp/en-US/xml_tmp/Tasks/snippets/Serialization-XML-OpenJDK_Parse-XMLSchema_DOM.xml b/defensive-coding/tmp/en-US/xml_tmp/Tasks/snippets/Serialization-XML-OpenJDK_Parse-XMLSchema_DOM.xml new file mode 100644 index 0000000..b4ecf6c --- /dev/null +++ b/defensive-coding/tmp/en-US/xml_tmp/Tasks/snippets/Serialization-XML-OpenJDK_Parse-XMLSchema_DOM.xml @@ -0,0 +1,23 @@ + + + + +SchemaFactory factory = SchemaFactory.newInstance( + XMLConstants.W3C_XML_SCHEMA_NS_URI); + +// This enables restrictions on schema complexity. +factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); + +// The following line prevents resource resolution +// by the schema itself. +factory.setResourceResolver(new NoResourceResolver()); + +Schema schema = factory.newSchema(schemaFile); + +Validator validator = schema.newValidator(); + +// This prevents external resource resolution. +validator.setResourceResolver(new NoResourceResolver()); +validator.validate(new DOMSource(document)); + diff --git a/defensive-coding/tmp/en-US/xml_tmp/Tasks/snippets/Serialization-XML-OpenJDK_Parse-XMLSchema_SAX.xml b/defensive-coding/tmp/en-US/xml_tmp/Tasks/snippets/Serialization-XML-OpenJDK_Parse-XMLSchema_SAX.xml new file mode 100644 index 0000000..2f6c6c9 --- /dev/null +++ b/defensive-coding/tmp/en-US/xml_tmp/Tasks/snippets/Serialization-XML-OpenJDK_Parse-XMLSchema_SAX.xml @@ -0,0 +1,26 @@ + + + + +SchemaFactory factory = SchemaFactory.newInstance( + XMLConstants.W3C_XML_SCHEMA_NS_URI); + +// This enables restrictions on the schema and document +// complexity. +factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); + +// This prevents resource resolution by the schema itself. +// If the schema is trusted and references additional files, +// this line must be omitted, otherwise loading these files +// will fail. +factory.setResourceResolver(new NoResourceResolver()); + +Schema schema = factory.newSchema(schemaFile); +Validator validator = schema.newValidator(); + +// This prevents external resource resolution. +validator.setResourceResolver(new NoResourceResolver()); + +validator.validate(new SAXSource(new InputSource(inputStream))); +

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