Adding Defensive Coding book
This commit is contained in:
parent
3623943843
commit
1fbfdb89d1
754 changed files with 60855 additions and 0 deletions
33
defensive-coding/Makefile
Normal file
33
defensive-coding/Makefile
Normal file
|
@ -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
|
||||||
|
|
32
defensive-coding/README
Normal file
32
defensive-coding/README
Normal file
|
@ -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.
|
47
defensive-coding/docbook-schema/.svn/all-wcprops
Normal file
47
defensive-coding/docbook-schema/.svn/all-wcprops
Normal file
|
@ -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
|
266
defensive-coding/docbook-schema/.svn/entries
Normal file
266
defensive-coding/docbook-schema/.svn/entries
Normal file
|
@ -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
|
||||||
|
|
|
@ -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.
|
|
@ -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 .................................
|
||||||
|
|
||||||
|
# ......................................................................
|
1549
defensive-coding/docbook-schema/.svn/text-base/dbhierx.rnc.svn-base
Normal file
1549
defensive-coding/docbook-schema/.svn/text-base/dbhierx.rnc.svn-base
Normal file
File diff suppressed because it is too large
Load diff
|
@ -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:
|
||||||
|
#
|
||||||
|
# <!ENTITY % dbnotn PUBLIC
|
||||||
|
# "-//OASIS//ENTITIES DocBook Notations V4.5//EN"
|
||||||
|
# "dbnotnx.mod">
|
||||||
|
# %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 .................................
|
||||||
|
|
||||||
|
# ......................................................................
|
5785
defensive-coding/docbook-schema/.svn/text-base/dbpoolx.rnc.svn-base
Normal file
5785
defensive-coding/docbook-schema/.svn/text-base/dbpoolx.rnc.svn-base
Normal file
File diff suppressed because it is too large
Load diff
|
@ -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:
|
||||||
|
#
|
||||||
|
# <!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
|
||||||
|
# "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd"
|
||||||
|
# [...]>
|
||||||
|
#
|
||||||
|
# Or, if you have a higher-level driver file that customizes DocBook,
|
||||||
|
# use the FPI in the parameter entity declaration:
|
||||||
|
#
|
||||||
|
# <!ENTITY % DocBookDTD PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
|
||||||
|
# "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
|
||||||
|
# %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 ..........................................
|
||||||
|
|
||||||
|
# ......................................................................
|
|
@ -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:
|
||||||
|
#
|
||||||
|
# <!ENTITY % htmltbl PUBLIC
|
||||||
|
# "-//OASIS//ELEMENTS DocBook XML HTML Tables V4.5//EN"
|
||||||
|
# "htmltblx.mod">
|
||||||
|
# %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 ............................
|
||||||
|
|
||||||
|
# ......................................................................
|
3
defensive-coding/docbook-schema/README
Normal file
3
defensive-coding/docbook-schema/README
Normal file
|
@ -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.
|
164
defensive-coding/docbook-schema/calstblx.rnc
Normal file
164
defensive-coding/docbook-schema/calstblx.rnc
Normal file
|
@ -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 .................................
|
||||||
|
|
||||||
|
# ......................................................................
|
1549
defensive-coding/docbook-schema/dbhierx.rnc
Normal file
1549
defensive-coding/docbook-schema/dbhierx.rnc
Normal file
File diff suppressed because it is too large
Load diff
85
defensive-coding/docbook-schema/dbnotnx.rnc
Normal file
85
defensive-coding/docbook-schema/dbnotnx.rnc
Normal file
|
@ -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:
|
||||||
|
#
|
||||||
|
# <!ENTITY % dbnotn PUBLIC
|
||||||
|
# "-//OASIS//ENTITIES DocBook Notations V4.5//EN"
|
||||||
|
# "dbnotnx.mod">
|
||||||
|
# %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 .................................
|
||||||
|
|
||||||
|
# ......................................................................
|
5785
defensive-coding/docbook-schema/dbpoolx.rnc
Normal file
5785
defensive-coding/docbook-schema/dbpoolx.rnc
Normal file
File diff suppressed because it is too large
Load diff
499
defensive-coding/docbook-schema/docbook.rnc
Normal file
499
defensive-coding/docbook-schema/docbook.rnc
Normal file
|
@ -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:
|
||||||
|
#
|
||||||
|
# <!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
|
||||||
|
# "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd"
|
||||||
|
# [...]>
|
||||||
|
#
|
||||||
|
# Or, if you have a higher-level driver file that customizes DocBook,
|
||||||
|
# use the FPI in the parameter entity declaration:
|
||||||
|
#
|
||||||
|
# <!ENTITY % DocBookDTD PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
|
||||||
|
# "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
|
||||||
|
# %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 ..........................................
|
||||||
|
|
||||||
|
# ......................................................................
|
225
defensive-coding/docbook-schema/htmltblx.rnc
Normal file
225
defensive-coding/docbook-schema/htmltblx.rnc
Normal file
|
@ -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:
|
||||||
|
#
|
||||||
|
# <!ENTITY % htmltbl PUBLIC
|
||||||
|
# "-//OASIS//ELEMENTS DocBook XML HTML Tables V4.5//EN"
|
||||||
|
# "htmltblx.mod">
|
||||||
|
# %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 ............................
|
||||||
|
|
||||||
|
# ......................................................................
|
23
defensive-coding/en-US/.svn/all-wcprops
Normal file
23
defensive-coding/en-US/.svn/all-wcprops
Normal file
|
@ -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
|
145
defensive-coding/en-US/.svn/entries
Normal file
145
defensive-coding/en-US/.svn/entries
Normal file
|
@ -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
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
K 13
|
||||||
|
svn:mime-type
|
||||||
|
V 8
|
||||||
|
text/xml
|
||||||
|
END
|
|
@ -0,0 +1,5 @@
|
||||||
|
K 13
|
||||||
|
svn:mime-type
|
||||||
|
V 8
|
||||||
|
text/xml
|
||||||
|
END
|
29
defensive-coding/en-US/.svn/text-base/Book_Info.xml.svn-base
Normal file
29
defensive-coding/en-US/.svn/text-base/Book_Info.xml.svn-base
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
<?xml version='1.0' encoding='UTF-8' ?>
|
||||||
|
<!DOCTYPE bookinfo PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
|
||||||
|
]>
|
||||||
|
<bookinfo id="book-Defensive_Coding">
|
||||||
|
<title>Defensive Coding</title>
|
||||||
|
<subtitle>A Guide to Improving Software Security</subtitle>
|
||||||
|
<edition>1.0</edition>
|
||||||
|
<issuenum>1.0</issuenum>
|
||||||
|
<pubsnumber>20</pubsnumber>
|
||||||
|
<productname>Internal</productname>
|
||||||
|
<productnumber>6.4</productnumber>
|
||||||
|
<abstract>
|
||||||
|
<para>
|
||||||
|
This document provides guidelines for improving software
|
||||||
|
security through secure coding. It covers common
|
||||||
|
programming languages and libraries, and focuses on
|
||||||
|
concrete recommendations.
|
||||||
|
</para>
|
||||||
|
</abstract>
|
||||||
|
<corpauthor>
|
||||||
|
<inlinemediaobject>
|
||||||
|
<imageobject>
|
||||||
|
<imagedata fileref="Common_Content/images/redhat-logo.svg" format="SVG" />
|
||||||
|
</imageobject>
|
||||||
|
</inlinemediaobject>
|
||||||
|
</corpauthor>
|
||||||
|
<xi:include href="Common_Content/Legal_Notice.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</bookinfo>
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
<!ENTITY YEAR "2012">
|
||||||
|
<!ENTITY HOLDER "Red Hat, Inc">
|
|
@ -0,0 +1,26 @@
|
||||||
|
<?xml version='1.0' encoding='utf-8' ?>
|
||||||
|
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
|
||||||
|
<book>
|
||||||
|
<xi:include href="Book_Info.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
<part>
|
||||||
|
<title>Programming Languages</title>
|
||||||
|
<xi:include href="C/C.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
<xi:include href="CXX/CXX.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
<xi:include href="Python/Language.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</part>
|
||||||
|
<part>
|
||||||
|
<title>Specific Programming Tasks</title>
|
||||||
|
<xi:include href="Tasks/Library_Design.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
<xi:include href="Tasks/Descriptors.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
<xi:include href="Tasks/File_System.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
<xi:include href="Tasks/Temporary_Files.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
<xi:include href="Tasks/Processes.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
<xi:include href="Tasks/Serialization.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
<xi:include href="Tasks/Cryptography.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</part>
|
||||||
|
<part>
|
||||||
|
<title>Implementing Security Features</title>
|
||||||
|
<xi:include href="Features/Authentication.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
<xi:include href="Features/TLS.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</part>
|
||||||
|
</book>
|
17
defensive-coding/en-US/Author_Group.xml
Normal file
17
defensive-coding/en-US/Author_Group.xml
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
<?xml version='1.0' encoding='utf-8' ?>
|
||||||
|
<!DOCTYPE authorgroup PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
|
||||||
|
<!ENTITY % BOOK_ENTITIES SYSTEM "UEFI_Secure_Boot_Guide.ent">
|
||||||
|
%BOOK_ENTITIES;
|
||||||
|
]>
|
||||||
|
<authorgroup>
|
||||||
|
<author>
|
||||||
|
<firstname>Florian</firstname>
|
||||||
|
<surname>Weimer</surname>
|
||||||
|
<affiliation>
|
||||||
|
<orgname>Red Hat</orgname>
|
||||||
|
<orgdiv>Product Security Team</orgdiv>
|
||||||
|
</affiliation>
|
||||||
|
<email>fweimer@redhat.com</email>
|
||||||
|
</author>
|
||||||
|
</authorgroup>
|
||||||
|
|
30
defensive-coding/en-US/Book_Info.xml
Normal file
30
defensive-coding/en-US/Book_Info.xml
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
<?xml version='1.0' encoding='UTF-8' ?>
|
||||||
|
<!DOCTYPE bookinfo PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
|
||||||
|
]>
|
||||||
|
<bookinfo id="book-Defensive_Coding">
|
||||||
|
<title>Defensive Coding</title>
|
||||||
|
<subtitle>A Guide to Improving Software Security</subtitle>
|
||||||
|
<edition>1.0</edition>
|
||||||
|
<issuenum>1.0</issuenum>
|
||||||
|
<pubsnumber></pubsnumber>
|
||||||
|
<productname></productname>
|
||||||
|
<productnumber></productnumber>
|
||||||
|
<abstract>
|
||||||
|
<para>
|
||||||
|
This document provides guidelines for improving software
|
||||||
|
security through secure coding. It covers common
|
||||||
|
programming languages and libraries, and focuses on
|
||||||
|
concrete recommendations.
|
||||||
|
</para>
|
||||||
|
</abstract>
|
||||||
|
<corpauthor>
|
||||||
|
<inlinemediaobject>
|
||||||
|
<imageobject>
|
||||||
|
<imagedata fileref="Common_Content/images/redhat-logo.svg" format="SVG" />
|
||||||
|
</imageobject>
|
||||||
|
</inlinemediaobject>
|
||||||
|
</corpauthor>
|
||||||
|
<xi:include href="Common_Content/Legal_Notice.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
<xi:include href="Author_Group.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</bookinfo>
|
||||||
|
|
35
defensive-coding/en-US/C/.svn/all-wcprops
Normal file
35
defensive-coding/en-US/C/.svn/all-wcprops
Normal file
|
@ -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
|
6
defensive-coding/en-US/C/.svn/dir-prop-base
Normal file
6
defensive-coding/en-US/C/.svn/dir-prop-base
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
K 10
|
||||||
|
svn:ignore
|
||||||
|
V 9
|
||||||
|
snippets
|
||||||
|
|
||||||
|
END
|
198
defensive-coding/en-US/C/.svn/entries
Normal file
198
defensive-coding/en-US/C/.svn/entries
Normal file
|
@ -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
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
K 13
|
||||||
|
svn:mime-type
|
||||||
|
V 8
|
||||||
|
text/xml
|
||||||
|
END
|
5
defensive-coding/en-US/C/.svn/prop-base/C.xml.svn-base
Normal file
5
defensive-coding/en-US/C/.svn/prop-base/C.xml.svn-base
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
K 13
|
||||||
|
svn:mime-type
|
||||||
|
V 8
|
||||||
|
text/xml
|
||||||
|
END
|
|
@ -0,0 +1,5 @@
|
||||||
|
K 13
|
||||||
|
svn:mime-type
|
||||||
|
V 8
|
||||||
|
text/xml
|
||||||
|
END
|
|
@ -0,0 +1,5 @@
|
||||||
|
K 13
|
||||||
|
svn:mime-type
|
||||||
|
V 8
|
||||||
|
text/xml
|
||||||
|
END
|
|
@ -0,0 +1,5 @@
|
||||||
|
K 13
|
||||||
|
svn:mime-type
|
||||||
|
V 8
|
||||||
|
text/xml
|
||||||
|
END
|
207
defensive-coding/en-US/C/.svn/text-base/Allocators.xml.svn-base
Normal file
207
defensive-coding/en-US/C/.svn/text-base/Allocators.xml.svn-base
Normal file
|
@ -0,0 +1,207 @@
|
||||||
|
<?xml version='1.0' encoding='utf-8' ?>
|
||||||
|
<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
|
||||||
|
]>
|
||||||
|
<section id="sect-Defensive_Coding-C-Allocators">
|
||||||
|
<title>Memory allocators</title>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<title><function>malloc</function> and related functions</title>
|
||||||
|
<para>
|
||||||
|
The C library interfaces for memory allocation are provided by
|
||||||
|
<function>malloc</function>, <function>free</function> and
|
||||||
|
<function>realloc</function>, and the
|
||||||
|
<function>calloc</function> function. In addition to these
|
||||||
|
generic functions, there are derived functions such as
|
||||||
|
<function>strdup</function> which perform allocation using
|
||||||
|
<function>malloc</function> internally, but do not return
|
||||||
|
untyped heap memory (which could be used for any object).
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
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 <function>malloc</function>.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
If the allocation fails, <function>realloc</function> does not
|
||||||
|
free the old pointer. Therefore, the idiom <literal>ptr =
|
||||||
|
realloc(ptr, size);</literal> is wrong because the memory
|
||||||
|
pointed to by <literal>ptr</literal> leaks in case of an error.
|
||||||
|
</para>
|
||||||
|
<section>
|
||||||
|
<title>Use-after-free errors</title>
|
||||||
|
<para>
|
||||||
|
After <function>free</function>, the pointer is invalid.
|
||||||
|
Further pointer dereferences are not allowed (and are usually
|
||||||
|
detected by <application>valgrind</application>). Less obvious
|
||||||
|
is that any <emphasis>use</emphasis> 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.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The same rules apply to <function>realloc</function> 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.
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<title>Handling memory allocation errors</title>
|
||||||
|
<para>
|
||||||
|
Recovering from out-of-memory errors is often difficult or even
|
||||||
|
impossible. In these cases, <function>malloc</function> 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.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
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
|
||||||
|
<xref
|
||||||
|
linkend="sect-Defensive_Coding-Tasks-Serialization-Decoders"/>
|
||||||
|
for related memory allocation concerns.
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section id="sect-Defensive_Coding-C-Allocators-alloca">
|
||||||
|
<title><function>alloca</function> and other forms of stack-based
|
||||||
|
allocation</title>
|
||||||
|
<para>
|
||||||
|
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 <literal>SIGSEGV</literal>
|
||||||
|
signal is generated and the program typically terminates.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
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.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
A common source for large stack growth are calls to
|
||||||
|
<function>alloca</function> and related functions such as
|
||||||
|
<function>strdupa</function>. 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 <function>alloca</function> makes it more difficult
|
||||||
|
to reorgnize the code because it is not allowed to use the
|
||||||
|
pointer after the function calling <function>alloca</function>
|
||||||
|
has returned, even if this function has been inlined into its
|
||||||
|
caller.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Similar concerns apply to <emphasis>variable-length
|
||||||
|
arrays</emphasis> (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.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
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.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
If you want to use <function>alloca</function> 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 <function>malloc</function>. When exiting the
|
||||||
|
function, check if <function>malloc</function> had been called,
|
||||||
|
and free the buffer as needed.
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section id="sect-Defensive_Coding-C-Allocators-Arrays">
|
||||||
|
<title>Array allocation</title>
|
||||||
|
<para>
|
||||||
|
When allocating arrays, it is important to check for overflows.
|
||||||
|
The <function>calloc</function> function performs such checks.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
If <function>malloc</function> or <function>realloc</function>
|
||||||
|
is used, the size check must be written manually. For instance,
|
||||||
|
to allocate an array of <literal>n</literal> elements of type
|
||||||
|
<literal>T</literal>, check that the requested size is not
|
||||||
|
greater than <literal>n / sizeof(T)</literal>.
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<title>Custom memory allocators</title>
|
||||||
|
<para>
|
||||||
|
Custom memory allocates come in two forms: replacements for
|
||||||
|
<function>malloc</function>, and completely different interfaces
|
||||||
|
for memory management. Both approaches can reduce the
|
||||||
|
effectiveness of <application>valgrind</application> and similar
|
||||||
|
tools, and the heap corruption detection provided by GNU libc, so
|
||||||
|
they should be avoided.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Memory allocators are difficult to write and contain many
|
||||||
|
performance and security pitfalls.
|
||||||
|
</para>
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
When computing array sizes or rounding up allocation
|
||||||
|
requests (to the next allocation granularity, or for
|
||||||
|
alignment purposes), checks for arithmetic overflow are
|
||||||
|
required.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Size computations for array allocations need overflow
|
||||||
|
checking. See <xref
|
||||||
|
linkend="sect-Defensive_Coding-C-Allocators-Arrays"/>.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
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
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<title>Conservative garbage collection</title>
|
||||||
|
<para>
|
||||||
|
Garbage collection can be an alternative to explicit memory
|
||||||
|
management using <function>malloc</function> and
|
||||||
|
<function>free</function>. The Boehm-Dehmers-Weiser allocator
|
||||||
|
can be used from C programs, with minimal type annotations.
|
||||||
|
Performance is competitive with <function>malloc</function> on
|
||||||
|
64-bit architectures, especially for multi-threaded programs.
|
||||||
|
The stop-the-world pauses may be problematic for some real-time
|
||||||
|
applications, though.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
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.
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
</section>
|
||||||
|
|
11
defensive-coding/en-US/C/.svn/text-base/C.xml.svn-base
Normal file
11
defensive-coding/en-US/C/.svn/text-base/C.xml.svn-base
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
<?xml version='1.0' encoding='utf-8' ?>
|
||||||
|
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
|
||||||
|
]>
|
||||||
|
<chapter id="chap-Defensive_Coding-C">
|
||||||
|
<title>The C Programming Language</title>
|
||||||
|
|
||||||
|
<xi:include href="Language.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
<xi:include href="Libc.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
<xi:include href="Allocators.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</chapter>
|
||||||
|
|
150
defensive-coding/en-US/C/.svn/text-base/Language.xml.svn-base
Normal file
150
defensive-coding/en-US/C/.svn/text-base/Language.xml.svn-base
Normal file
|
@ -0,0 +1,150 @@
|
||||||
|
<?xml version='1.0' encoding='utf-8' ?>
|
||||||
|
<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
|
||||||
|
]>
|
||||||
|
<section id="sect-Defensive_Coding-C-Language">
|
||||||
|
<title>The core language</title>
|
||||||
|
<para>
|
||||||
|
C provides no memory safety. Most recommendations in this section
|
||||||
|
deal with this aspect of the language.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<section id="sect-Defensive_Coding-C-Undefined">
|
||||||
|
<title>Undefined behavior</title>
|
||||||
|
<para>
|
||||||
|
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.)
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Common sources of undefined behavior are:
|
||||||
|
</para>
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem><para>out-of-bounds array accesses</para></listitem>
|
||||||
|
<listitem><para>null pointer dereferences</para></listitem>
|
||||||
|
<listitem><para>overflow in signed integer arithmetic</para></listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section id="sect-Defensive_Coding-C-Pointers">
|
||||||
|
<title>Recommendations for pointers and array handling</title>
|
||||||
|
<para>
|
||||||
|
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.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
<xref linkend="ex-Defensive_Coding-C-Pointers-remaining"/>
|
||||||
|
shows how to extract Pascal-style strings from a character
|
||||||
|
buffer. The two pointers kept for length checks are
|
||||||
|
<varname>inend</varname> and <varname>outend</varname>.
|
||||||
|
<varname>inp</varname> and <varname>outp</varname> are the
|
||||||
|
respective positions.
|
||||||
|
The number of input bytes is checked using the expression
|
||||||
|
<literal>len > (size_t)(inend - inp)</literal>.
|
||||||
|
The cast silences a compiler warning;
|
||||||
|
<varname>inend</varname> is always larger than
|
||||||
|
<varname>inp</varname>.
|
||||||
|
</para>
|
||||||
|
<example id="ex-Defensive_Coding-C-Pointers-remaining">
|
||||||
|
<title>Array processing in C</title>
|
||||||
|
<xi:include href="snippets/Pointers-remaining.xml"
|
||||||
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</example>
|
||||||
|
<para>
|
||||||
|
It is important that the length checks always have the form
|
||||||
|
<literal>len > (size_t)(inend - inp)</literal>, where
|
||||||
|
<varname>len</varname> is a variable of type
|
||||||
|
<type>size_t</type> which denotes the <emphasis>total</emphasis>
|
||||||
|
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 <literal>len1 + len2 > (size_t)(inend - inp)</literal>,
|
||||||
|
because the expression on the left can overflow or wrap around
|
||||||
|
(see <xref linkend="sect-Defensive_Coding-C-Arithmetic"/>), and it
|
||||||
|
no longer reflects the number of bytes to be processed.
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section id="sect-Defensive_Coding-C-Arithmetic">
|
||||||
|
<title>Recommendations for integer arithmetic</title>
|
||||||
|
<para>
|
||||||
|
Overflow in signed integer arithmetic is undefined. This means
|
||||||
|
that it is not possible to check for overflow after it happened,
|
||||||
|
see <xref linkend="ex-Defensive_Coding-C-Arithmetic-bad"/>.
|
||||||
|
</para>
|
||||||
|
<example id="ex-Defensive_Coding-C-Arithmetic-bad">
|
||||||
|
<title>Incorrect overflow detection in C</title>
|
||||||
|
<xi:include href="snippets/Arithmetic-add.xml"
|
||||||
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</example>
|
||||||
|
<para>
|
||||||
|
The following approaches can be used to check for overflow,
|
||||||
|
without actually causing it.
|
||||||
|
</para>
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
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.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Perform the calculation in the corresponding unsigned type
|
||||||
|
and use bit fiddling to detect the overflow.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
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 <xref linkend="ex-Defensive_Coding-C-Arithmetic-mult"/>.
|
||||||
|
<!-- This approach can result in bogus compiler warnings
|
||||||
|
with signed types:
|
||||||
|
http://gcc.gnu.org/bugzilla/post_bug.cgi -->
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
<example id="ex-Defensive_Coding-C-Arithmetic-mult">
|
||||||
|
<title>Overflow checking for unsigned multiplication</title>
|
||||||
|
<xi:include href="snippets/Arithmetic-mult.xml"
|
||||||
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</example>
|
||||||
|
<para>
|
||||||
|
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 <literal>a *
|
||||||
|
b</literal> involving a constant <literal>a</literal>, where the
|
||||||
|
expression is reduced to <literal>b > C</literal> for some
|
||||||
|
constant <literal>C</literal> determined at compile time. The
|
||||||
|
other expression, <literal>b && a > ((unsigned)-1) /
|
||||||
|
b</literal>, is more difficult to optimize at compile time.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
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.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Legacy code should be compiled with the <option>-fwrapv</option>
|
||||||
|
GCC option. As a result, GCC will provide 2's complement
|
||||||
|
semantics for integer arithmetic, including defined behavior on
|
||||||
|
integer overflow.
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
</section>
|
227
defensive-coding/en-US/C/.svn/text-base/Libc.xml.svn-base
Normal file
227
defensive-coding/en-US/C/.svn/text-base/Libc.xml.svn-base
Normal file
|
@ -0,0 +1,227 @@
|
||||||
|
<?xml version='1.0' encoding='utf-8' ?>
|
||||||
|
<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
|
||||||
|
]>
|
||||||
|
<section id="sect-Defensive_Coding-C-Libc">
|
||||||
|
<title>The C standard library</title>
|
||||||
|
<para>
|
||||||
|
Parts of the C standard library (and the UNIX and GNU extensions)
|
||||||
|
are difficult to use, so you shoud avoid them.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Please check the applicable documentation before using the
|
||||||
|
recommended replacements. Many of these functions allocate
|
||||||
|
buffers using <function>malloc</function> which your code must
|
||||||
|
deallocate explicitly using <function>free</function>.
|
||||||
|
</para>
|
||||||
|
<section id="sect-Defensive_Coding-C-Absolutely-Banned">
|
||||||
|
<title>Absolutely banned interfaces</title>
|
||||||
|
<para>
|
||||||
|
The functions listed below must not be used because they are
|
||||||
|
almost always unsafe. Use the indicated replacements instead.
|
||||||
|
</para>
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem><para><function>gets</function>
|
||||||
|
⟶ <function>fgets</function></para></listitem>
|
||||||
|
<listitem><para><function>getwd</function>
|
||||||
|
⟶ <function>getcwd</function>
|
||||||
|
or <function>get_current_dir_name</function></para></listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<function>readdir_r</function> ⟶ <function>readdir</function>
|
||||||
|
<!-- It is quite complicated to allocate a properly-sized
|
||||||
|
buffer for use with readdir_r, and readdir provides
|
||||||
|
sufficient thread safety guarantees. -->
|
||||||
|
<!-- ??? Add File_System cross-reference -->
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<function>realpath</function> (with a non-NULL second parameter)
|
||||||
|
⟶ <function>realpath</function> with NULL as the second parameter,
|
||||||
|
or <function>canonicalize_file_name</function>
|
||||||
|
<!-- It is complicated to allocate a properly-sized buffer
|
||||||
|
for use with realpath. -->
|
||||||
|
<!-- ??? Add File_System cross-reference -->
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
<para>
|
||||||
|
The constants listed below must not be used, either. Instead,
|
||||||
|
code must allocate memory dynamically and use interfaces with
|
||||||
|
length checking.
|
||||||
|
</para>
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<literal>NAME_MAX</literal> (limit not actually enforced by
|
||||||
|
the kernel)
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<literal>PATH_MAX</literal> (limit not actually enforced by
|
||||||
|
the kernel)
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<literal>_PC_NAME_MAX</literal> (This limit, returned by the
|
||||||
|
<function>pathconf</function> function, is not enforced by
|
||||||
|
the kernel.)
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<literal>_PC_PATH_MAX</literal> (This limit, returned by the
|
||||||
|
<function>pathconf</function> function, is not enforced by
|
||||||
|
the kernel.)
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
<para>
|
||||||
|
The following structure members must not be used.
|
||||||
|
</para>
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<literal>f_namemax</literal> in <literal>struct
|
||||||
|
statvfs</literal> (limit not actually enforced by the kernel,
|
||||||
|
see <literal>_PC_NAME_MAX</literal> above)
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
</section>
|
||||||
|
<section id="sect-Defensive_Coding-C-Avoid">
|
||||||
|
<title>Functions to avoid</title>
|
||||||
|
<para>
|
||||||
|
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 <function>asprintf</function> or
|
||||||
|
<function>vasprintf</function>. (For non-GNU targets, these
|
||||||
|
functions are available from Gnulib.) In some cases, the
|
||||||
|
<function>snprintf</function> function might be a suitable
|
||||||
|
replacement, see <xref
|
||||||
|
linkend="sect-Defensive_Coding-C-String-Functions-Length"/>.
|
||||||
|
</para>
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem><para><function>sprintf</function></para></listitem>
|
||||||
|
<listitem><para><function>strcat</function></para></listitem>
|
||||||
|
<listitem><para><function>strcpy</function></para></listitem>
|
||||||
|
<listitem><para><function>vsprintf</function></para></listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
<para>
|
||||||
|
Use the indicated replacements for the functions below.
|
||||||
|
</para>
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<function>alloca</function> ⟶
|
||||||
|
<function>malloc</function> and <function>free</function>
|
||||||
|
(see <xref linkend="sect-Defensive_Coding-C-Allocators-alloca"/>)
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<function>putenv</function> ⟶
|
||||||
|
explicit <varname>envp</varname> argument in process creation
|
||||||
|
(see <xref linkend="sect-Defensive_Coding-Tasks-Processes-environ"/>)
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<function>setenv</function> ⟶
|
||||||
|
explicit <varname>envp</varname> argument in process creation
|
||||||
|
(see <xref linkend="sect-Defensive_Coding-Tasks-Processes-environ"/>)
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<function>strdupa</function> ⟶
|
||||||
|
<function>strdup</function> and <function>free</function>
|
||||||
|
(see <xref linkend="sect-Defensive_Coding-C-Allocators-alloca"/>)
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<function>strndupa</function> ⟶
|
||||||
|
<function>strndup</function> and <function>free</function>
|
||||||
|
(see <xref linkend="sect-Defensive_Coding-C-Allocators-alloca"/>)
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<function>system</function> ⟶
|
||||||
|
<function>posix_spawn</function>
|
||||||
|
or <function>fork</function>/<function>execve</function>/
|
||||||
|
(see <xref linkend="sect-Defensive_Coding-Tasks-Processes-execve"/>)
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<function>unsetenv</function> ⟶
|
||||||
|
explicit <varname>envp</varname> argument in process creation
|
||||||
|
(see <xref linkend="sect-Defensive_Coding-Tasks-Processes-environ"/>)
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
</section>
|
||||||
|
<section id="sect-Defensive_Coding-C-String-Functions-Length">
|
||||||
|
<title>String Functions With Explicit Length Arguments</title>
|
||||||
|
<para>
|
||||||
|
The <function>snprintf</function> function provides a way to
|
||||||
|
construct a string in a statically-sized buffer. (If the buffer
|
||||||
|
size is dynamic, use <function>asprintf</function> instead.)
|
||||||
|
</para>
|
||||||
|
<informalexample>
|
||||||
|
<xi:include href="snippets/String-Functions-snprintf.xml"
|
||||||
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</informalexample>
|
||||||
|
<para>
|
||||||
|
The second argument to the <function>snprintf</function> 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 <function>snprintf</function>. If you need to
|
||||||
|
construct a string iteratively, by repeatedly appending
|
||||||
|
fragments, consider constructing the string on the heap,
|
||||||
|
increasing the buffer with <function>realloc</function> as
|
||||||
|
needed. (<function>snprintf</function> does not support
|
||||||
|
overlapping the result buffer with argument strings.)
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
If you use <function>vsnprintf</function> (or
|
||||||
|
<function>snprintf</function>) with a format string which is not
|
||||||
|
a constant, but a function argument, it is important to annotate
|
||||||
|
the function with a <literal>format</literal> function
|
||||||
|
attribute, so that GCC can warn about misuse of your function
|
||||||
|
(see <xref
|
||||||
|
linkend="ex-Defensive_Coding-C-String-Functions-format-Attribute"/>).
|
||||||
|
</para>
|
||||||
|
<example id="ex-Defensive_Coding-C-String-Functions-format-Attribute">
|
||||||
|
<title>The <literal>format</literal> function attribute</title>
|
||||||
|
<xi:include href="snippets/String-Functions-format.xml"
|
||||||
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</example>
|
||||||
|
<para>
|
||||||
|
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: <function>strncpy</function>,
|
||||||
|
<function>strncat</function>, and <function>stpncpy</function>.
|
||||||
|
These functions do not ensure that the result string is
|
||||||
|
NUL-terminated. For <function>strncpy</function>,
|
||||||
|
NUL termination can be added this way:
|
||||||
|
</para>
|
||||||
|
<informalexample>
|
||||||
|
<xi:include href="snippets/String-Functions-strncpy.xml"
|
||||||
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</informalexample>
|
||||||
|
<para>
|
||||||
|
Some systems support <function>strlcpy</function> and
|
||||||
|
<function>strlcat</function> functions which behave this way,
|
||||||
|
but these functions are not part of GNU libc. Using
|
||||||
|
<function>snprintf</function> with a suitable format string is a
|
||||||
|
simple (albeit slightly slower) replacement.
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
</section>
|
|
@ -0,0 +1,4 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<locatingRules xmlns="http://thaiopensource.com/ns/locating-rules/1.0">
|
||||||
|
<include rules="../../schemas.xml"/>
|
||||||
|
</locatingRules>
|
207
defensive-coding/en-US/C/Allocators.xml
Normal file
207
defensive-coding/en-US/C/Allocators.xml
Normal file
|
@ -0,0 +1,207 @@
|
||||||
|
<?xml version='1.0' encoding='utf-8' ?>
|
||||||
|
<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
|
||||||
|
]>
|
||||||
|
<section id="sect-Defensive_Coding-C-Allocators">
|
||||||
|
<title>Memory allocators</title>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<title><function>malloc</function> and related functions</title>
|
||||||
|
<para>
|
||||||
|
The C library interfaces for memory allocation are provided by
|
||||||
|
<function>malloc</function>, <function>free</function> and
|
||||||
|
<function>realloc</function>, and the
|
||||||
|
<function>calloc</function> function. In addition to these
|
||||||
|
generic functions, there are derived functions such as
|
||||||
|
<function>strdup</function> which perform allocation using
|
||||||
|
<function>malloc</function> internally, but do not return
|
||||||
|
untyped heap memory (which could be used for any object).
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
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 <function>malloc</function>.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
If the allocation fails, <function>realloc</function> does not
|
||||||
|
free the old pointer. Therefore, the idiom <literal>ptr =
|
||||||
|
realloc(ptr, size);</literal> is wrong because the memory
|
||||||
|
pointed to by <literal>ptr</literal> leaks in case of an error.
|
||||||
|
</para>
|
||||||
|
<section>
|
||||||
|
<title>Use-after-free errors</title>
|
||||||
|
<para>
|
||||||
|
After <function>free</function>, the pointer is invalid.
|
||||||
|
Further pointer dereferences are not allowed (and are usually
|
||||||
|
detected by <application>valgrind</application>). Less obvious
|
||||||
|
is that any <emphasis>use</emphasis> 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.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The same rules apply to <function>realloc</function> 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.
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<title>Handling memory allocation errors</title>
|
||||||
|
<para>
|
||||||
|
Recovering from out-of-memory errors is often difficult or even
|
||||||
|
impossible. In these cases, <function>malloc</function> 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.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
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
|
||||||
|
<xref
|
||||||
|
linkend="sect-Defensive_Coding-Tasks-Serialization-Decoders"/>
|
||||||
|
for related memory allocation concerns.
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section id="sect-Defensive_Coding-C-Allocators-alloca">
|
||||||
|
<title><function>alloca</function> and other forms of stack-based
|
||||||
|
allocation</title>
|
||||||
|
<para>
|
||||||
|
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 <literal>SIGSEGV</literal>
|
||||||
|
signal is generated and the program typically terminates.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
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.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
A common source for large stack growth are calls to
|
||||||
|
<function>alloca</function> and related functions such as
|
||||||
|
<function>strdupa</function>. 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 <function>alloca</function> makes it more difficult
|
||||||
|
to reorgnize the code because it is not allowed to use the
|
||||||
|
pointer after the function calling <function>alloca</function>
|
||||||
|
has returned, even if this function has been inlined into its
|
||||||
|
caller.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Similar concerns apply to <emphasis>variable-length
|
||||||
|
arrays</emphasis> (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.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
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.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
If you want to use <function>alloca</function> 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 <function>malloc</function>. When exiting the
|
||||||
|
function, check if <function>malloc</function> had been called,
|
||||||
|
and free the buffer as needed.
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section id="sect-Defensive_Coding-C-Allocators-Arrays">
|
||||||
|
<title>Array allocation</title>
|
||||||
|
<para>
|
||||||
|
When allocating arrays, it is important to check for overflows.
|
||||||
|
The <function>calloc</function> function performs such checks.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
If <function>malloc</function> or <function>realloc</function>
|
||||||
|
is used, the size check must be written manually. For instance,
|
||||||
|
to allocate an array of <literal>n</literal> elements of type
|
||||||
|
<literal>T</literal>, check that the requested size is not
|
||||||
|
greater than <literal>n / sizeof(T)</literal>.
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<title>Custom memory allocators</title>
|
||||||
|
<para>
|
||||||
|
Custom memory allocates come in two forms: replacements for
|
||||||
|
<function>malloc</function>, and completely different interfaces
|
||||||
|
for memory management. Both approaches can reduce the
|
||||||
|
effectiveness of <application>valgrind</application> and similar
|
||||||
|
tools, and the heap corruption detection provided by GNU libc, so
|
||||||
|
they should be avoided.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Memory allocators are difficult to write and contain many
|
||||||
|
performance and security pitfalls.
|
||||||
|
</para>
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
When computing array sizes or rounding up allocation
|
||||||
|
requests (to the next allocation granularity, or for
|
||||||
|
alignment purposes), checks for arithmetic overflow are
|
||||||
|
required.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Size computations for array allocations need overflow
|
||||||
|
checking. See <xref
|
||||||
|
linkend="sect-Defensive_Coding-C-Allocators-Arrays"/>.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
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
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<title>Conservative garbage collection</title>
|
||||||
|
<para>
|
||||||
|
Garbage collection can be an alternative to explicit memory
|
||||||
|
management using <function>malloc</function> and
|
||||||
|
<function>free</function>. The Boehm-Dehmers-Weiser allocator
|
||||||
|
can be used from C programs, with minimal type annotations.
|
||||||
|
Performance is competitive with <function>malloc</function> on
|
||||||
|
64-bit architectures, especially for multi-threaded programs.
|
||||||
|
The stop-the-world pauses may be problematic for some real-time
|
||||||
|
applications, though.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
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.
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
</section>
|
||||||
|
|
11
defensive-coding/en-US/C/C.xml
Normal file
11
defensive-coding/en-US/C/C.xml
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
<?xml version='1.0' encoding='utf-8' ?>
|
||||||
|
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
|
||||||
|
]>
|
||||||
|
<chapter id="chap-Defensive_Coding-C">
|
||||||
|
<title>The C Programming Language</title>
|
||||||
|
|
||||||
|
<xi:include href="Language.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
<xi:include href="Libc.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
<xi:include href="Allocators.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</chapter>
|
||||||
|
|
150
defensive-coding/en-US/C/Language.xml
Normal file
150
defensive-coding/en-US/C/Language.xml
Normal file
|
@ -0,0 +1,150 @@
|
||||||
|
<?xml version='1.0' encoding='utf-8' ?>
|
||||||
|
<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
|
||||||
|
]>
|
||||||
|
<section id="sect-Defensive_Coding-C-Language">
|
||||||
|
<title>The core language</title>
|
||||||
|
<para>
|
||||||
|
C provides no memory safety. Most recommendations in this section
|
||||||
|
deal with this aspect of the language.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<section id="sect-Defensive_Coding-C-Undefined">
|
||||||
|
<title>Undefined behavior</title>
|
||||||
|
<para>
|
||||||
|
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.)
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Common sources of undefined behavior are:
|
||||||
|
</para>
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem><para>out-of-bounds array accesses</para></listitem>
|
||||||
|
<listitem><para>null pointer dereferences</para></listitem>
|
||||||
|
<listitem><para>overflow in signed integer arithmetic</para></listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section id="sect-Defensive_Coding-C-Pointers">
|
||||||
|
<title>Recommendations for pointers and array handling</title>
|
||||||
|
<para>
|
||||||
|
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.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
<xref linkend="ex-Defensive_Coding-C-Pointers-remaining"/>
|
||||||
|
shows how to extract Pascal-style strings from a character
|
||||||
|
buffer. The two pointers kept for length checks are
|
||||||
|
<varname>inend</varname> and <varname>outend</varname>.
|
||||||
|
<varname>inp</varname> and <varname>outp</varname> are the
|
||||||
|
respective positions.
|
||||||
|
The number of input bytes is checked using the expression
|
||||||
|
<literal>len > (size_t)(inend - inp)</literal>.
|
||||||
|
The cast silences a compiler warning;
|
||||||
|
<varname>inend</varname> is always larger than
|
||||||
|
<varname>inp</varname>.
|
||||||
|
</para>
|
||||||
|
<example id="ex-Defensive_Coding-C-Pointers-remaining">
|
||||||
|
<title>Array processing in C</title>
|
||||||
|
<xi:include href="snippets/Pointers-remaining.xml"
|
||||||
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</example>
|
||||||
|
<para>
|
||||||
|
It is important that the length checks always have the form
|
||||||
|
<literal>len > (size_t)(inend - inp)</literal>, where
|
||||||
|
<varname>len</varname> is a variable of type
|
||||||
|
<type>size_t</type> which denotes the <emphasis>total</emphasis>
|
||||||
|
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 <literal>len1 + len2 > (size_t)(inend - inp)</literal>,
|
||||||
|
because the expression on the left can overflow or wrap around
|
||||||
|
(see <xref linkend="sect-Defensive_Coding-C-Arithmetic"/>), and it
|
||||||
|
no longer reflects the number of bytes to be processed.
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section id="sect-Defensive_Coding-C-Arithmetic">
|
||||||
|
<title>Recommendations for integer arithmetic</title>
|
||||||
|
<para>
|
||||||
|
Overflow in signed integer arithmetic is undefined. This means
|
||||||
|
that it is not possible to check for overflow after it happened,
|
||||||
|
see <xref linkend="ex-Defensive_Coding-C-Arithmetic-bad"/>.
|
||||||
|
</para>
|
||||||
|
<example id="ex-Defensive_Coding-C-Arithmetic-bad">
|
||||||
|
<title>Incorrect overflow detection in C</title>
|
||||||
|
<xi:include href="snippets/Arithmetic-add.xml"
|
||||||
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</example>
|
||||||
|
<para>
|
||||||
|
The following approaches can be used to check for overflow,
|
||||||
|
without actually causing it.
|
||||||
|
</para>
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
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.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Perform the calculation in the corresponding unsigned type
|
||||||
|
and use bit fiddling to detect the overflow.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
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 <xref linkend="ex-Defensive_Coding-C-Arithmetic-mult"/>.
|
||||||
|
<!-- This approach can result in bogus compiler warnings
|
||||||
|
with signed types:
|
||||||
|
http://gcc.gnu.org/bugzilla/post_bug.cgi -->
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
<example id="ex-Defensive_Coding-C-Arithmetic-mult">
|
||||||
|
<title>Overflow checking for unsigned multiplication</title>
|
||||||
|
<xi:include href="snippets/Arithmetic-mult.xml"
|
||||||
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</example>
|
||||||
|
<para>
|
||||||
|
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 <literal>a *
|
||||||
|
b</literal> involving a constant <literal>a</literal>, where the
|
||||||
|
expression is reduced to <literal>b > C</literal> for some
|
||||||
|
constant <literal>C</literal> determined at compile time. The
|
||||||
|
other expression, <literal>b && a > ((unsigned)-1) /
|
||||||
|
b</literal>, is more difficult to optimize at compile time.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
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.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Legacy code should be compiled with the <option>-fwrapv</option>
|
||||||
|
GCC option. As a result, GCC will provide 2's complement
|
||||||
|
semantics for integer arithmetic, including defined behavior on
|
||||||
|
integer overflow.
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
</section>
|
227
defensive-coding/en-US/C/Libc.xml
Normal file
227
defensive-coding/en-US/C/Libc.xml
Normal file
|
@ -0,0 +1,227 @@
|
||||||
|
<?xml version='1.0' encoding='utf-8' ?>
|
||||||
|
<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
|
||||||
|
]>
|
||||||
|
<section id="sect-Defensive_Coding-C-Libc">
|
||||||
|
<title>The C standard library</title>
|
||||||
|
<para>
|
||||||
|
Parts of the C standard library (and the UNIX and GNU extensions)
|
||||||
|
are difficult to use, so you shoud avoid them.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Please check the applicable documentation before using the
|
||||||
|
recommended replacements. Many of these functions allocate
|
||||||
|
buffers using <function>malloc</function> which your code must
|
||||||
|
deallocate explicitly using <function>free</function>.
|
||||||
|
</para>
|
||||||
|
<section id="sect-Defensive_Coding-C-Absolutely-Banned">
|
||||||
|
<title>Absolutely banned interfaces</title>
|
||||||
|
<para>
|
||||||
|
The functions listed below must not be used because they are
|
||||||
|
almost always unsafe. Use the indicated replacements instead.
|
||||||
|
</para>
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem><para><function>gets</function>
|
||||||
|
⟶ <function>fgets</function></para></listitem>
|
||||||
|
<listitem><para><function>getwd</function>
|
||||||
|
⟶ <function>getcwd</function>
|
||||||
|
or <function>get_current_dir_name</function></para></listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<function>readdir_r</function> ⟶ <function>readdir</function>
|
||||||
|
<!-- It is quite complicated to allocate a properly-sized
|
||||||
|
buffer for use with readdir_r, and readdir provides
|
||||||
|
sufficient thread safety guarantees. -->
|
||||||
|
<!-- ??? Add File_System cross-reference -->
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<function>realpath</function> (with a non-NULL second parameter)
|
||||||
|
⟶ <function>realpath</function> with NULL as the second parameter,
|
||||||
|
or <function>canonicalize_file_name</function>
|
||||||
|
<!-- It is complicated to allocate a properly-sized buffer
|
||||||
|
for use with realpath. -->
|
||||||
|
<!-- ??? Add File_System cross-reference -->
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
<para>
|
||||||
|
The constants listed below must not be used, either. Instead,
|
||||||
|
code must allocate memory dynamically and use interfaces with
|
||||||
|
length checking.
|
||||||
|
</para>
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<literal>NAME_MAX</literal> (limit not actually enforced by
|
||||||
|
the kernel)
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<literal>PATH_MAX</literal> (limit not actually enforced by
|
||||||
|
the kernel)
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<literal>_PC_NAME_MAX</literal> (This limit, returned by the
|
||||||
|
<function>pathconf</function> function, is not enforced by
|
||||||
|
the kernel.)
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<literal>_PC_PATH_MAX</literal> (This limit, returned by the
|
||||||
|
<function>pathconf</function> function, is not enforced by
|
||||||
|
the kernel.)
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
<para>
|
||||||
|
The following structure members must not be used.
|
||||||
|
</para>
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<literal>f_namemax</literal> in <literal>struct
|
||||||
|
statvfs</literal> (limit not actually enforced by the kernel,
|
||||||
|
see <literal>_PC_NAME_MAX</literal> above)
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
</section>
|
||||||
|
<section id="sect-Defensive_Coding-C-Avoid">
|
||||||
|
<title>Functions to avoid</title>
|
||||||
|
<para>
|
||||||
|
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 <function>asprintf</function> or
|
||||||
|
<function>vasprintf</function>. (For non-GNU targets, these
|
||||||
|
functions are available from Gnulib.) In some cases, the
|
||||||
|
<function>snprintf</function> function might be a suitable
|
||||||
|
replacement, see <xref
|
||||||
|
linkend="sect-Defensive_Coding-C-String-Functions-Length"/>.
|
||||||
|
</para>
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem><para><function>sprintf</function></para></listitem>
|
||||||
|
<listitem><para><function>strcat</function></para></listitem>
|
||||||
|
<listitem><para><function>strcpy</function></para></listitem>
|
||||||
|
<listitem><para><function>vsprintf</function></para></listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
<para>
|
||||||
|
Use the indicated replacements for the functions below.
|
||||||
|
</para>
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<function>alloca</function> ⟶
|
||||||
|
<function>malloc</function> and <function>free</function>
|
||||||
|
(see <xref linkend="sect-Defensive_Coding-C-Allocators-alloca"/>)
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<function>putenv</function> ⟶
|
||||||
|
explicit <varname>envp</varname> argument in process creation
|
||||||
|
(see <xref linkend="sect-Defensive_Coding-Tasks-Processes-environ"/>)
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<function>setenv</function> ⟶
|
||||||
|
explicit <varname>envp</varname> argument in process creation
|
||||||
|
(see <xref linkend="sect-Defensive_Coding-Tasks-Processes-environ"/>)
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<function>strdupa</function> ⟶
|
||||||
|
<function>strdup</function> and <function>free</function>
|
||||||
|
(see <xref linkend="sect-Defensive_Coding-C-Allocators-alloca"/>)
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<function>strndupa</function> ⟶
|
||||||
|
<function>strndup</function> and <function>free</function>
|
||||||
|
(see <xref linkend="sect-Defensive_Coding-C-Allocators-alloca"/>)
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<function>system</function> ⟶
|
||||||
|
<function>posix_spawn</function>
|
||||||
|
or <function>fork</function>/<function>execve</function>/
|
||||||
|
(see <xref linkend="sect-Defensive_Coding-Tasks-Processes-execve"/>)
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<function>unsetenv</function> ⟶
|
||||||
|
explicit <varname>envp</varname> argument in process creation
|
||||||
|
(see <xref linkend="sect-Defensive_Coding-Tasks-Processes-environ"/>)
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
</section>
|
||||||
|
<section id="sect-Defensive_Coding-C-String-Functions-Length">
|
||||||
|
<title>String Functions With Explicit Length Arguments</title>
|
||||||
|
<para>
|
||||||
|
The <function>snprintf</function> function provides a way to
|
||||||
|
construct a string in a statically-sized buffer. (If the buffer
|
||||||
|
size is dynamic, use <function>asprintf</function> instead.)
|
||||||
|
</para>
|
||||||
|
<informalexample>
|
||||||
|
<xi:include href="snippets/String-Functions-snprintf.xml"
|
||||||
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</informalexample>
|
||||||
|
<para>
|
||||||
|
The second argument to the <function>snprintf</function> 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 <function>snprintf</function>. If you need to
|
||||||
|
construct a string iteratively, by repeatedly appending
|
||||||
|
fragments, consider constructing the string on the heap,
|
||||||
|
increasing the buffer with <function>realloc</function> as
|
||||||
|
needed. (<function>snprintf</function> does not support
|
||||||
|
overlapping the result buffer with argument strings.)
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
If you use <function>vsnprintf</function> (or
|
||||||
|
<function>snprintf</function>) with a format string which is not
|
||||||
|
a constant, but a function argument, it is important to annotate
|
||||||
|
the function with a <literal>format</literal> function
|
||||||
|
attribute, so that GCC can warn about misuse of your function
|
||||||
|
(see <xref
|
||||||
|
linkend="ex-Defensive_Coding-C-String-Functions-format-Attribute"/>).
|
||||||
|
</para>
|
||||||
|
<example id="ex-Defensive_Coding-C-String-Functions-format-Attribute">
|
||||||
|
<title>The <literal>format</literal> function attribute</title>
|
||||||
|
<xi:include href="snippets/String-Functions-format.xml"
|
||||||
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</example>
|
||||||
|
<para>
|
||||||
|
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: <function>strncpy</function>,
|
||||||
|
<function>strncat</function>, and <function>stpncpy</function>.
|
||||||
|
These functions do not ensure that the result string is
|
||||||
|
NUL-terminated. For <function>strncpy</function>,
|
||||||
|
NUL termination can be added this way:
|
||||||
|
</para>
|
||||||
|
<informalexample>
|
||||||
|
<xi:include href="snippets/String-Functions-strncpy.xml"
|
||||||
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</informalexample>
|
||||||
|
<para>
|
||||||
|
Some systems support <function>strlcpy</function> and
|
||||||
|
<function>strlcat</function> functions which behave this way,
|
||||||
|
but these functions are not part of GNU libc. Using
|
||||||
|
<function>snprintf</function> with a suitable format string is a
|
||||||
|
simple (albeit slightly slower) replacement.
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
</section>
|
4
defensive-coding/en-US/C/schemas.xml
Normal file
4
defensive-coding/en-US/C/schemas.xml
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<locatingRules xmlns="http://thaiopensource.com/ns/locating-rules/1.0">
|
||||||
|
<include rules="../../schemas.xml"/>
|
||||||
|
</locatingRules>
|
21
defensive-coding/en-US/C/snippets/Arithmetic-add.xml
Normal file
21
defensive-coding/en-US/C/snippets/Arithmetic-add.xml
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
<?xml version='1.0' encoding='utf-8' ?>
|
||||||
|
<!DOCTYPE programlisting PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
|
||||||
|
]>
|
||||||
|
<!-- Automatically generated file. Do not edit. -->
|
||||||
|
<programlisting language="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;
|
||||||
|
}
|
||||||
|
</programlisting>
|
14
defensive-coding/en-US/C/snippets/Arithmetic-mult.xml
Normal file
14
defensive-coding/en-US/C/snippets/Arithmetic-mult.xml
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
<?xml version='1.0' encoding='utf-8' ?>
|
||||||
|
<!DOCTYPE programlisting PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
|
||||||
|
]>
|
||||||
|
<!-- Automatically generated file. Do not edit. -->
|
||||||
|
<programlisting language="C">
|
||||||
|
unsigned
|
||||||
|
mul(unsigned a, unsigned b)
|
||||||
|
{
|
||||||
|
if (b && a > ((unsigned)-1) / b) {
|
||||||
|
report_overflow();
|
||||||
|
}
|
||||||
|
return a * b;
|
||||||
|
}
|
||||||
|
</programlisting>
|
49
defensive-coding/en-US/C/snippets/Pointers-remaining.xml
Normal file
49
defensive-coding/en-US/C/snippets/Pointers-remaining.xml
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
<?xml version='1.0' encoding='utf-8' ?>
|
||||||
|
<!DOCTYPE programlisting PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
|
||||||
|
]>
|
||||||
|
<!-- Automatically generated file. Do not edit. -->
|
||||||
|
<programlisting language="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;
|
||||||
|
}
|
||||||
|
</programlisting>
|
|
@ -0,0 +1,18 @@
|
||||||
|
<?xml version='1.0' encoding='utf-8' ?>
|
||||||
|
<!DOCTYPE programlisting PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
|
||||||
|
]>
|
||||||
|
<!-- Automatically generated file. Do not edit. -->
|
||||||
|
<programlisting language="C">
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
</programlisting>
|
|
@ -0,0 +1,8 @@
|
||||||
|
<?xml version='1.0' encoding='utf-8' ?>
|
||||||
|
<!DOCTYPE programlisting PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
|
||||||
|
]>
|
||||||
|
<!-- Automatically generated file. Do not edit. -->
|
||||||
|
<programlisting language="C">
|
||||||
|
char fraction[30];
|
||||||
|
snprintf(fraction, sizeof(fraction), "%d/%d", numerator, denominator);
|
||||||
|
</programlisting>
|
|
@ -0,0 +1,9 @@
|
||||||
|
<?xml version='1.0' encoding='utf-8' ?>
|
||||||
|
<!DOCTYPE programlisting PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
|
||||||
|
]>
|
||||||
|
<!-- Automatically generated file. Do not edit. -->
|
||||||
|
<programlisting language="C">
|
||||||
|
char buf[10];
|
||||||
|
strncpy(buf, data, sizeof(buf));
|
||||||
|
buf[sizeof(buf) - 1] = '\0';
|
||||||
|
</programlisting>
|
29
defensive-coding/en-US/CXX/.svn/all-wcprops
Normal file
29
defensive-coding/en-US/CXX/.svn/all-wcprops
Normal file
|
@ -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
|
6
defensive-coding/en-US/CXX/.svn/dir-prop-base
Normal file
6
defensive-coding/en-US/CXX/.svn/dir-prop-base
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
K 10
|
||||||
|
svn:ignore
|
||||||
|
V 9
|
||||||
|
snippets
|
||||||
|
|
||||||
|
END
|
164
defensive-coding/en-US/CXX/.svn/entries
Normal file
164
defensive-coding/en-US/CXX/.svn/entries
Normal file
|
@ -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
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
K 13
|
||||||
|
svn:mime-type
|
||||||
|
V 8
|
||||||
|
text/xml
|
||||||
|
END
|
|
@ -0,0 +1,5 @@
|
||||||
|
K 13
|
||||||
|
svn:mime-type
|
||||||
|
V 8
|
||||||
|
text/xml
|
||||||
|
END
|
|
@ -0,0 +1,5 @@
|
||||||
|
K 13
|
||||||
|
svn:mime-type
|
||||||
|
V 8
|
||||||
|
text/xml
|
||||||
|
END
|
|
@ -0,0 +1,5 @@
|
||||||
|
K 13
|
||||||
|
svn:mime-type
|
||||||
|
V 8
|
||||||
|
text/xml
|
||||||
|
END
|
10
defensive-coding/en-US/CXX/.svn/text-base/CXX.xml.svn-base
Normal file
10
defensive-coding/en-US/CXX/.svn/text-base/CXX.xml.svn-base
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
<?xml version='1.0' encoding='utf-8' ?>
|
||||||
|
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
|
||||||
|
]>
|
||||||
|
<chapter id="chap-Defensive_Coding-CXX">
|
||||||
|
<title>The C++ Programming Language</title>
|
||||||
|
|
||||||
|
<xi:include href="Language.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
<xi:include href="Std.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</chapter>
|
||||||
|
|
186
defensive-coding/en-US/CXX/.svn/text-base/Language.xml.svn-base
Normal file
186
defensive-coding/en-US/CXX/.svn/text-base/Language.xml.svn-base
Normal file
|
@ -0,0 +1,186 @@
|
||||||
|
<?xml version='1.0' encoding='utf-8' ?>
|
||||||
|
<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
|
||||||
|
]>
|
||||||
|
<section id="sect-Defensive_Coding-CXX-Language">
|
||||||
|
<title>The core language</title>
|
||||||
|
<para>
|
||||||
|
C++ includes a large subset of the C language. As far as the C
|
||||||
|
subset is used, the recommendations in <xref
|
||||||
|
linkend="chap-Defensive_Coding-C"/> apply.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<title>Array allocation with <literal>operator new[]</literal></title>
|
||||||
|
<para>
|
||||||
|
For very large values of <literal>n</literal>, an expression
|
||||||
|
like <literal>new T[n]</literal> 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 <literal>sizeof(T) * size_t(n) +
|
||||||
|
cookie_size</literal>, where <literal>cookie_size</literal> is
|
||||||
|
currently at most 8. This computation can overflow, and
|
||||||
|
GCC-generated code does not detect this.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The <literal>std::vector</literal> template can be used instead
|
||||||
|
an explicit array allocation. (The GCC implementation detects
|
||||||
|
overflow internally.)
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
If there is no alternative to <literal>operator new[]</literal>,
|
||||||
|
code which allocates arrays with a variable length must check
|
||||||
|
for overflow manually. For the <literal>new T[n]</literal>
|
||||||
|
example, the size check could be <literal>n || (n > 0 &&
|
||||||
|
n > (size_t(-1) - 8) / sizeof(T))</literal>. (See <xref
|
||||||
|
linkend="sect-Defensive_Coding-C-Arithmetic"/>.) If there are
|
||||||
|
additional dimensions (which must be constants according to the
|
||||||
|
C++ standard), these should be included as factors in the
|
||||||
|
divisor.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
These countermeasures prevent out-of-bounds writes and potential
|
||||||
|
code execution. Very large memory allocations can still lead to
|
||||||
|
a denial of service. <xref
|
||||||
|
linkend="sect-Defensive_Coding-Tasks-Serialization-Decoders"/>
|
||||||
|
contains suggestions for mitigating this problem when processing
|
||||||
|
untrusted data.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
See <xref linkend="sect-Defensive_Coding-C-Allocators-Arrays"/>
|
||||||
|
for array allocation advice for C-style memory allocation.
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<title>Overloading</title>
|
||||||
|
<para>
|
||||||
|
Do not overload functions with versions that have different
|
||||||
|
security characteristics. For instance, do not implement a
|
||||||
|
function <function>strcat</function> which works on
|
||||||
|
<type>std::string</type> arguments. Similarly, do not name
|
||||||
|
methods after such functions.
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<title>ABI compatibility and preparing for security updates</title>
|
||||||
|
<para>
|
||||||
|
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.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
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:
|
||||||
|
</para>
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Avoid inline functions.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Use the pointer-to-implementation idiom.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Try to avoid templates. Use them if the increased type
|
||||||
|
safety provides a benefit to the programmer.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Move security-critical code out of templated code, so that
|
||||||
|
it can be patched in a central place if necessary.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
<para>
|
||||||
|
The KDE project publishes a document with more extensive
|
||||||
|
guidelines on ABI-preserving changes to C++ code, <ulink
|
||||||
|
url="http://techbase.kde.org/Policies/Binary_Compatibility_Issues_With_C++">Policies/Binary
|
||||||
|
Compatibility Issues With C++</ulink>
|
||||||
|
(<emphasis>d-pointer</emphasis> refers to the
|
||||||
|
pointer-to-implementation idiom).
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section id="sect-Defensive_Coding-CXX-Language-CXX11">
|
||||||
|
<title>C++0X and C++11 support</title>
|
||||||
|
<para>
|
||||||
|
GCC offers different language compatibility modes:
|
||||||
|
</para>
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<option>-std=c++98</option> for the original 1998 C++
|
||||||
|
standard
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<option>-std=c++03</option> for the 1998 standard with the
|
||||||
|
changes from the TR1 technical report
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<option>-std=c++11</option> for the 2011 C++ standard. This
|
||||||
|
option should not be used.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<option>-std=c++0x</option> for several different versions
|
||||||
|
of C++11 support in development, depending on the GCC
|
||||||
|
version. This option should not be used.
|
||||||
|
<!-- There were two incompatibilies before GCC 4.7.2
|
||||||
|
(std::list and std::pair), but link C++98 and C++11
|
||||||
|
code is still unsupported, although it currently has
|
||||||
|
some chance of working by accident. -->
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
<para>
|
||||||
|
For each of these flags, there are variants which also enable
|
||||||
|
GNU extensions (mostly language features also found in C99 or
|
||||||
|
C11): <option>-std=gnu++98</option>,
|
||||||
|
<option>-std=gnu++03</option>, <option>-std=gnu++11</option>.
|
||||||
|
Again, <option>-std=gnu++11</option> should not be used.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
If you enable C++11 support, the ABI of the standard C++ library
|
||||||
|
<literal>libstdc++</literal> 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).
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
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.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Some C++11 features (or approximations thereof) are available
|
||||||
|
with TR1 support, that is, with <option>-std=c++03</option> or
|
||||||
|
<option>-std=gnu++03</option> and in the
|
||||||
|
<literal><tr1/*></literal> header files. This includes
|
||||||
|
<literal>std::tr1::shared_ptr</literal> (from
|
||||||
|
<literal><tr1/memory></literal>) and
|
||||||
|
<literal>std::tr1::function</literal> (from
|
||||||
|
<literal><tr1/functional></literal>). For other C++11
|
||||||
|
features, the Boost C++ library contains replacements.
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
</section>
|
||||||
|
|
32
defensive-coding/en-US/CXX/.svn/text-base/Std.xml.svn-base
Normal file
32
defensive-coding/en-US/CXX/.svn/text-base/Std.xml.svn-base
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
<?xml version='1.0' encoding='utf-8' ?>
|
||||||
|
<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
|
||||||
|
]>
|
||||||
|
<section id="sect-Defensive_Coding-CXX-Std">
|
||||||
|
<title>The C++ standard library</title>
|
||||||
|
<para>
|
||||||
|
The C++ standard library includes most of its C counterpart
|
||||||
|
by reference, see <xref linkend="sect-Defensive_Coding-C-Libc"/>.
|
||||||
|
</para>
|
||||||
|
<section>
|
||||||
|
<title>Containers and <literal>operator[]</literal></title>
|
||||||
|
<para>
|
||||||
|
Many containers similar to <literal>std::vector</literal>
|
||||||
|
provide both <literal>operator[](size_type)</literal> and a
|
||||||
|
member function <literal>at(size_type)</literal>. This applies
|
||||||
|
to <literal>std::vector</literal> itself,
|
||||||
|
<literal>std::array</literal>, <literal>std::string</literal>
|
||||||
|
and other instances of <literal>std::basic_string</literal>.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
<literal>operator[](size_type)</literal> is not required by the
|
||||||
|
standard to perform bounds checking (and the implementation in
|
||||||
|
GCC does not). In contrast, <literal>at(size_type)</literal>
|
||||||
|
must perform such a check. Therefore, in code which is not
|
||||||
|
performance-critical, you should prefer
|
||||||
|
<literal>at(size_type)</literal> over
|
||||||
|
<literal>operator[](size_type)</literal>, even though it is
|
||||||
|
slightly more verbose.
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
</section>
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<locatingRules xmlns="http://thaiopensource.com/ns/locating-rules/1.0">
|
||||||
|
<include rules="../../schemas.xml"/>
|
||||||
|
</locatingRules>
|
10
defensive-coding/en-US/CXX/CXX.xml
Normal file
10
defensive-coding/en-US/CXX/CXX.xml
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
<?xml version='1.0' encoding='utf-8' ?>
|
||||||
|
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
|
||||||
|
]>
|
||||||
|
<chapter id="chap-Defensive_Coding-CXX">
|
||||||
|
<title>The C++ Programming Language</title>
|
||||||
|
|
||||||
|
<xi:include href="Language.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
<xi:include href="Std.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</chapter>
|
||||||
|
|
186
defensive-coding/en-US/CXX/Language.xml
Normal file
186
defensive-coding/en-US/CXX/Language.xml
Normal file
|
@ -0,0 +1,186 @@
|
||||||
|
<?xml version='1.0' encoding='utf-8' ?>
|
||||||
|
<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
|
||||||
|
]>
|
||||||
|
<section id="sect-Defensive_Coding-CXX-Language">
|
||||||
|
<title>The core language</title>
|
||||||
|
<para>
|
||||||
|
C++ includes a large subset of the C language. As far as the C
|
||||||
|
subset is used, the recommendations in <xref
|
||||||
|
linkend="chap-Defensive_Coding-C"/> apply.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<title>Array allocation with <literal>operator new[]</literal></title>
|
||||||
|
<para>
|
||||||
|
For very large values of <literal>n</literal>, an expression
|
||||||
|
like <literal>new T[n]</literal> 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 <literal>sizeof(T) * size_t(n) +
|
||||||
|
cookie_size</literal>, where <literal>cookie_size</literal> is
|
||||||
|
currently at most 8. This computation can overflow, and
|
||||||
|
GCC-generated code does not detect this.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The <literal>std::vector</literal> template can be used instead
|
||||||
|
an explicit array allocation. (The GCC implementation detects
|
||||||
|
overflow internally.)
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
If there is no alternative to <literal>operator new[]</literal>,
|
||||||
|
code which allocates arrays with a variable length must check
|
||||||
|
for overflow manually. For the <literal>new T[n]</literal>
|
||||||
|
example, the size check could be <literal>n || (n > 0 &&
|
||||||
|
n > (size_t(-1) - 8) / sizeof(T))</literal>. (See <xref
|
||||||
|
linkend="sect-Defensive_Coding-C-Arithmetic"/>.) If there are
|
||||||
|
additional dimensions (which must be constants according to the
|
||||||
|
C++ standard), these should be included as factors in the
|
||||||
|
divisor.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
These countermeasures prevent out-of-bounds writes and potential
|
||||||
|
code execution. Very large memory allocations can still lead to
|
||||||
|
a denial of service. <xref
|
||||||
|
linkend="sect-Defensive_Coding-Tasks-Serialization-Decoders"/>
|
||||||
|
contains suggestions for mitigating this problem when processing
|
||||||
|
untrusted data.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
See <xref linkend="sect-Defensive_Coding-C-Allocators-Arrays"/>
|
||||||
|
for array allocation advice for C-style memory allocation.
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<title>Overloading</title>
|
||||||
|
<para>
|
||||||
|
Do not overload functions with versions that have different
|
||||||
|
security characteristics. For instance, do not implement a
|
||||||
|
function <function>strcat</function> which works on
|
||||||
|
<type>std::string</type> arguments. Similarly, do not name
|
||||||
|
methods after such functions.
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<title>ABI compatibility and preparing for security updates</title>
|
||||||
|
<para>
|
||||||
|
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.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
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:
|
||||||
|
</para>
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Avoid inline functions.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Use the pointer-to-implementation idiom.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Try to avoid templates. Use them if the increased type
|
||||||
|
safety provides a benefit to the programmer.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Move security-critical code out of templated code, so that
|
||||||
|
it can be patched in a central place if necessary.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
<para>
|
||||||
|
The KDE project publishes a document with more extensive
|
||||||
|
guidelines on ABI-preserving changes to C++ code, <ulink
|
||||||
|
url="http://techbase.kde.org/Policies/Binary_Compatibility_Issues_With_C++">Policies/Binary
|
||||||
|
Compatibility Issues With C++</ulink>
|
||||||
|
(<emphasis>d-pointer</emphasis> refers to the
|
||||||
|
pointer-to-implementation idiom).
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section id="sect-Defensive_Coding-CXX-Language-CXX11">
|
||||||
|
<title>C++0X and C++11 support</title>
|
||||||
|
<para>
|
||||||
|
GCC offers different language compatibility modes:
|
||||||
|
</para>
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<option>-std=c++98</option> for the original 1998 C++
|
||||||
|
standard
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<option>-std=c++03</option> for the 1998 standard with the
|
||||||
|
changes from the TR1 technical report
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<option>-std=c++11</option> for the 2011 C++ standard. This
|
||||||
|
option should not be used.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<option>-std=c++0x</option> for several different versions
|
||||||
|
of C++11 support in development, depending on the GCC
|
||||||
|
version. This option should not be used.
|
||||||
|
<!-- There were two incompatibilies before GCC 4.7.2
|
||||||
|
(std::list and std::pair), but link C++98 and C++11
|
||||||
|
code is still unsupported, although it currently has
|
||||||
|
some chance of working by accident. -->
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
<para>
|
||||||
|
For each of these flags, there are variants which also enable
|
||||||
|
GNU extensions (mostly language features also found in C99 or
|
||||||
|
C11): <option>-std=gnu++98</option>,
|
||||||
|
<option>-std=gnu++03</option>, <option>-std=gnu++11</option>.
|
||||||
|
Again, <option>-std=gnu++11</option> should not be used.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
If you enable C++11 support, the ABI of the standard C++ library
|
||||||
|
<literal>libstdc++</literal> 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).
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
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.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Some C++11 features (or approximations thereof) are available
|
||||||
|
with TR1 support, that is, with <option>-std=c++03</option> or
|
||||||
|
<option>-std=gnu++03</option> and in the
|
||||||
|
<literal><tr1/*></literal> header files. This includes
|
||||||
|
<literal>std::tr1::shared_ptr</literal> (from
|
||||||
|
<literal><tr1/memory></literal>) and
|
||||||
|
<literal>std::tr1::function</literal> (from
|
||||||
|
<literal><tr1/functional></literal>). For other C++11
|
||||||
|
features, the Boost C++ library contains replacements.
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
</section>
|
||||||
|
|
32
defensive-coding/en-US/CXX/Std.xml
Normal file
32
defensive-coding/en-US/CXX/Std.xml
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
<?xml version='1.0' encoding='utf-8' ?>
|
||||||
|
<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
|
||||||
|
]>
|
||||||
|
<section id="sect-Defensive_Coding-CXX-Std">
|
||||||
|
<title>The C++ standard library</title>
|
||||||
|
<para>
|
||||||
|
The C++ standard library includes most of its C counterpart
|
||||||
|
by reference, see <xref linkend="sect-Defensive_Coding-C-Libc"/>.
|
||||||
|
</para>
|
||||||
|
<section>
|
||||||
|
<title>Containers and <literal>operator[]</literal></title>
|
||||||
|
<para>
|
||||||
|
Many containers similar to <literal>std::vector</literal>
|
||||||
|
provide both <literal>operator[](size_type)</literal> and a
|
||||||
|
member function <literal>at(size_type)</literal>. This applies
|
||||||
|
to <literal>std::vector</literal> itself,
|
||||||
|
<literal>std::array</literal>, <literal>std::string</literal>
|
||||||
|
and other instances of <literal>std::basic_string</literal>.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
<literal>operator[](size_type)</literal> is not required by the
|
||||||
|
standard to perform bounds checking (and the implementation in
|
||||||
|
GCC does not). In contrast, <literal>at(size_type)</literal>
|
||||||
|
must perform such a check. Therefore, in code which is not
|
||||||
|
performance-critical, you should prefer
|
||||||
|
<literal>at(size_type)</literal> over
|
||||||
|
<literal>operator[](size_type)</literal>, even though it is
|
||||||
|
slightly more verbose.
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
</section>
|
||||||
|
|
4
defensive-coding/en-US/CXX/schemas.xml
Normal file
4
defensive-coding/en-US/CXX/schemas.xml
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<locatingRules xmlns="http://thaiopensource.com/ns/locating-rules/1.0">
|
||||||
|
<include rules="../../schemas.xml"/>
|
||||||
|
</locatingRules>
|
2
defensive-coding/en-US/Defensive_Coding.ent
Normal file
2
defensive-coding/en-US/Defensive_Coding.ent
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
<!ENTITY YEAR "2012">
|
||||||
|
<!ENTITY HOLDER "Red Hat, Inc">
|
27
defensive-coding/en-US/Defensive_Coding.xml
Normal file
27
defensive-coding/en-US/Defensive_Coding.xml
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
<?xml version='1.0' encoding='utf-8' ?>
|
||||||
|
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
|
||||||
|
<book>
|
||||||
|
<xi:include href="Book_Info.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
<part>
|
||||||
|
<title>Programming Languages</title>
|
||||||
|
<xi:include href="C/C.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
<xi:include href="CXX/CXX.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
<xi:include href="Python/Language.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</part>
|
||||||
|
<part>
|
||||||
|
<title>Specific Programming Tasks</title>
|
||||||
|
<xi:include href="Tasks/Library_Design.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
<xi:include href="Tasks/Descriptors.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
<xi:include href="Tasks/File_System.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
<xi:include href="Tasks/Temporary_Files.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
<xi:include href="Tasks/Processes.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
<xi:include href="Tasks/Serialization.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
<xi:include href="Tasks/Cryptography.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</part>
|
||||||
|
<part>
|
||||||
|
<title>Implementing Security Features</title>
|
||||||
|
<xi:include href="Features/Authentication.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
<xi:include href="Features/TLS.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</part>
|
||||||
|
<xi:include href="Revision_History.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</book>
|
23
defensive-coding/en-US/Features/.svn/all-wcprops
Normal file
23
defensive-coding/en-US/Features/.svn/all-wcprops
Normal file
|
@ -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
|
6
defensive-coding/en-US/Features/.svn/dir-prop-base
Normal file
6
defensive-coding/en-US/Features/.svn/dir-prop-base
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
K 10
|
||||||
|
svn:ignore
|
||||||
|
V 9
|
||||||
|
snippets
|
||||||
|
|
||||||
|
END
|
130
defensive-coding/en-US/Features/.svn/entries
Normal file
130
defensive-coding/en-US/Features/.svn/entries
Normal file
|
@ -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
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
K 13
|
||||||
|
svn:mime-type
|
||||||
|
V 8
|
||||||
|
text/xml
|
||||||
|
END
|
|
@ -0,0 +1,5 @@
|
||||||
|
K 13
|
||||||
|
svn:mime-type
|
||||||
|
V 8
|
||||||
|
text/xml
|
||||||
|
END
|
|
@ -0,0 +1,5 @@
|
||||||
|
K 13
|
||||||
|
svn:mime-type
|
||||||
|
V 8
|
||||||
|
text/xml
|
||||||
|
END
|
|
@ -0,0 +1,189 @@
|
||||||
|
<?xml version='1.0' encoding='utf-8' ?>
|
||||||
|
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
|
||||||
|
]>
|
||||||
|
<chapter id="chap-Defensive_Coding-Authentication">
|
||||||
|
<title>Authentication and Authorization</title>
|
||||||
|
|
||||||
|
<section id="sect-Defensive_Coding-Authentication-Server">
|
||||||
|
<title>Authenticating servers</title>
|
||||||
|
<para>
|
||||||
|
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:
|
||||||
|
</para>
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
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.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
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.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
On Linux, UNIX domain sockets (of the
|
||||||
|
<literal>PF_UNIX</literal> protocol family, sometimes called
|
||||||
|
<literal>PF_LOCAL</literal>) are restricted by file system
|
||||||
|
permissions. If the server socket path is not
|
||||||
|
world-writable, the server identity cannot be spoofed by
|
||||||
|
local users.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Port numbers less than 1024 (<emphasis>trusted
|
||||||
|
ports</emphasis>) can only be used by
|
||||||
|
<literal>root</literal>, 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.)
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
<para>
|
||||||
|
TLS (<xref linkend="chap-Defensive_Coding-TLS"/>) is the
|
||||||
|
recommended way for securing connections over untrusted
|
||||||
|
networks.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
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.
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section id="sect-Defensive_Coding-Authentication-Host_based">
|
||||||
|
<title>Host-based authentication</title>
|
||||||
|
<para>
|
||||||
|
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
|
||||||
|
<filename>/etc/hosts</filename>). 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.)
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
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.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The names returned by <function>gethostbyaddr</function> and
|
||||||
|
<function>getnameinfo</function> 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
|
||||||
|
<function>gethostbyaddr</function> or
|
||||||
|
<function>getaddrinfo</function> has to be performed. The name
|
||||||
|
is only valid if the original address is found among the results
|
||||||
|
of the forward lookup (<emphasis>double-reverse
|
||||||
|
lookup</emphasis>).
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
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.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
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.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
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.
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section id="sect-Defensive_Coding-Authentication-UNIX_Domain">
|
||||||
|
<title>UNIX domain socket authentication</title>
|
||||||
|
<para>
|
||||||
|
UNIX domain sockets (with address family
|
||||||
|
<literal>AF_UNIX</literal> or <literal>AF_LOCAL</literal>) are
|
||||||
|
restricted to the local host and offer a special authentication
|
||||||
|
mechanism: credentials passing.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Nowadays, most systems support the
|
||||||
|
<literal>SO_PEERCRED</literal> (Linux) or
|
||||||
|
<literal>LOCAL_PEERCRED</literal> (FreeBSD) socket options, or
|
||||||
|
the <function>getpeereid</function> (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.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Historically, credentials passing was implemented using
|
||||||
|
ancillary data in the <function>sendmsg</function> and
|
||||||
|
<function>recvmsg</function> 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.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
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
|
||||||
|
<function>getpwuid</function> (or
|
||||||
|
<function>getpwuid_r</function>) and
|
||||||
|
<function>getgrouplist</function>. Using the PID and
|
||||||
|
information from <filename>/proc/PID/status</filename> is prone
|
||||||
|
to race conditions and insecure.
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section id="sect-Defensive_Coding-Authentication-Netlink">
|
||||||
|
<title><literal>AF_NETLINK</literal> authentication of origin</title>
|
||||||
|
<!-- ??? kernel change may make this obsolete:
|
||||||
|
https://bugzilla.redhat.com/show_bug.cgi?id=851968 -->
|
||||||
|
<para>
|
||||||
|
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.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
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
|
||||||
|
<literal>nl_pid</literal> in the <literal>sockaddr_nl</literal>
|
||||||
|
structure is <literal>0</literal>. (This structure can be
|
||||||
|
obtained using <function>recvfrom</function> or
|
||||||
|
<function>recvmsg</function>, it is different from the
|
||||||
|
<literal>nlmsghdr</literal> structure.) The kernel does not
|
||||||
|
prevent other processes from sending unicast Netlink messages,
|
||||||
|
but the <literal>nl_pid</literal> field in the sender's socket
|
||||||
|
address will be non-zero in such cases.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Applications should not use <literal>AF_NETLINK</literal>
|
||||||
|
sockets as an IPC mechanism among processes, but prefer UNIX
|
||||||
|
domain sockets for this tasks.
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
</chapter>
|
||||||
|
|
988
defensive-coding/en-US/Features/.svn/text-base/TLS.xml.svn-base
Normal file
988
defensive-coding/en-US/Features/.svn/text-base/TLS.xml.svn-base
Normal file
|
@ -0,0 +1,988 @@
|
||||||
|
<?xml version='1.0' encoding='utf-8' ?>
|
||||||
|
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
|
||||||
|
]>
|
||||||
|
<chapter id="chap-Defensive_Coding-TLS">
|
||||||
|
<title>Transport Layer Security</title>
|
||||||
|
<para>
|
||||||
|
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.
|
||||||
|
</para>
|
||||||
|
<section id="sect-Defensive_Coding-TLS-Pitfalls">
|
||||||
|
<title>Common Pitfalls</title>
|
||||||
|
<para>
|
||||||
|
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.
|
||||||
|
</para>
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
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.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
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.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
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.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
The TLS handshake has very poor performance if the TCP Nagle
|
||||||
|
algorithm is active. You should switch on the
|
||||||
|
<literal>TCP_NODELAY</literal> socket option (at least for the
|
||||||
|
duration of the handshake), or use the Linux-specific
|
||||||
|
<literal>TCP_CORK</literal> option.
|
||||||
|
</para>
|
||||||
|
<example id="ex-Defensive_Coding-TLS-Nagle">
|
||||||
|
<title>Deactivating the TCP Nagle algorithm</title>
|
||||||
|
<xi:include href="snippets/TLS-Nagle.xml"
|
||||||
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</example>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
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).
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Both client and server should work towards an orderly
|
||||||
|
connection shutdown, that is send
|
||||||
|
<literal>close_notify</literal> 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).
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
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 <function>accept</function> 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.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
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 <function>fork</function> function
|
||||||
|
calls (see <xref
|
||||||
|
linkend="sect-Defensive_Coding-Tasks-Processes-Fork-Parallel"/>).
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
<section id="sect-Defensive_Coding-TLS-OpenSSL">
|
||||||
|
<title>OpenSSL Pitfalls</title>
|
||||||
|
<para>
|
||||||
|
Some OpenSSL function use <emphasis>tri-state return
|
||||||
|
values</emphasis>. Correct error checking is extremely
|
||||||
|
important. Several functions return <literal>int</literal>
|
||||||
|
values with the following meaning:
|
||||||
|
</para>
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
The value <literal>1</literal> indicates success (for
|
||||||
|
example, a successful signature verification).
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
The value <literal>0</literal> indicates semantic
|
||||||
|
failure (for example, a signature verification which was
|
||||||
|
unsuccessful because the signing certificate was
|
||||||
|
self-signed).
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
The value <literal>-1</literal> indicates a low-level
|
||||||
|
error in the system, such as failure to allocate memory
|
||||||
|
using <function>malloc</function>.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
<para>
|
||||||
|
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.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Recovering precise error information is difficult.
|
||||||
|
<xref linkend="ex-Defensive_Coding-TLS-OpenSSL-Errors"/>
|
||||||
|
shows how to obtain a more precise error code after a function
|
||||||
|
call on an <literal>SSL</literal> object has failed. However,
|
||||||
|
there are still cases where no detailed error information is
|
||||||
|
available (e.g., if <function>SSL_shutdown</function> fails
|
||||||
|
due to a connection teardown by the other end).
|
||||||
|
</para>
|
||||||
|
<example id="ex-Defensive_Coding-TLS-OpenSSL-Errors">
|
||||||
|
<title>Obtaining OpenSSL error codes</title>
|
||||||
|
<xi:include href="snippets/TLS-OpenSSL-Errors.xml"
|
||||||
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</example>
|
||||||
|
<para>
|
||||||
|
The <function>OPENSSL_config</function> 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.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
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 <literal>d2i_</literal> and end in
|
||||||
|
<literal>_fp</literal> or <literal>_bio</literal> (e.g.,
|
||||||
|
<function>d2i_X509_fp</function> or
|
||||||
|
<function>d2i_X509_bio</function>). These decoders must not
|
||||||
|
be used for parsing data from untrusted sources; instead,
|
||||||
|
the variants without the <literal>_fp</literal> and
|
||||||
|
<literal>_bio</literal> (e.g.,
|
||||||
|
<function>d2i_X509</function>) shall be used. The BIO
|
||||||
|
variants have received considerably less testing and are not
|
||||||
|
very robust.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
For the same reason, the OpenSSL command line tools (such as
|
||||||
|
<command>openssl x509</command>) are generally generally less
|
||||||
|
robust than the actual library code. They use the BIO
|
||||||
|
functions internally, and not the more robust variants.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The command line tools do not always indicate failure in the
|
||||||
|
exit status of the <application>openssl</application> process.
|
||||||
|
For instance, a verification failure in <command>openssl
|
||||||
|
verify</command> result in an exit status of zero.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The OpenSSL server and client applications (<command>openssl
|
||||||
|
s_client</command> and <command>openssl s_server</command>)
|
||||||
|
are debugging tools and should <emphasis>never</emphasis> be
|
||||||
|
used as generic clients. For instance, the
|
||||||
|
<application>s_client</application> tool reacts in a
|
||||||
|
surprisign way to lines starting with <literal>R</literal> and
|
||||||
|
<literal>Q</literal>.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
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.
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
<section id="sect-Defensive_Coding-TLS-Pitfalls-GNUTLS">
|
||||||
|
<title>GNUTLS Pitfalls</title>
|
||||||
|
<para>
|
||||||
|
<filename>libgnutls.so.26</filename> links to
|
||||||
|
<filename>libpthread.so.0</filename>. Loading the threading
|
||||||
|
library too late causes problems, so the main program should
|
||||||
|
be linked with <literal>-lpthread</literal> as well. As a
|
||||||
|
result, it can be difficult to use GNUTLS in a plugin which is
|
||||||
|
loaded with the <function>dlopen</function> 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.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The <function>gnutls_global_init</function> 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.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The <function>gnutls_global_deinit</function> function does
|
||||||
|
not actually deallocate all resources allocated by
|
||||||
|
<function>gnutls_global_init</function>. It is currently not
|
||||||
|
thread-safe. Therefore, it is best to avoid calling it
|
||||||
|
altogether.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
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.
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
<section id="sect-Defensive_Coding-TLS-Pitfalls-OpenJDK">
|
||||||
|
<title>OpenJDK Pitfalls</title>
|
||||||
|
<para>
|
||||||
|
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.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
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 <emphasis>unlimited
|
||||||
|
strength jurisdiction policy files</emphasis>. 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.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Some versions of OpenJDK use <filename>/dev/random</filename>
|
||||||
|
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
|
||||||
|
<filename>/dev/random</filename>.
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
<section id="sect-Defensive_Coding-TLS-Pitfalls-NSS">
|
||||||
|
<title>NSS Pitfalls</title>
|
||||||
|
<para>
|
||||||
|
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.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
If the NSPR descriptor is in an unexpected state, the
|
||||||
|
<function>SSL_ForceHandshake</function> function can succeed,
|
||||||
|
but no TLS handshake takes place, the peer is not
|
||||||
|
authenticated, and subsequent data is exchanged in the clear.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
NSS disables itself if it detects that the process underwent a
|
||||||
|
<function>fork</function> after the library has been
|
||||||
|
initialized. This behavior is required by the PKCS#11 API
|
||||||
|
specification.
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
</section>
|
||||||
|
<section id="sect-Defensive_Coding-TLS-Client">
|
||||||
|
<title>TLS Clients</title>
|
||||||
|
<para>
|
||||||
|
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.)
|
||||||
|
</para>
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
The client must configure the TLS library to use a set of
|
||||||
|
trusted root certificates. These certificates are provided
|
||||||
|
by the system in <filename
|
||||||
|
class="directory">/etc/ssl/certs</filename> or files derived
|
||||||
|
from it.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
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).
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
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.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
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.)
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
The client must check that the configured or user-provided
|
||||||
|
server name matches the peer certificate provided by the
|
||||||
|
server.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
<para>
|
||||||
|
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.
|
||||||
|
</para>
|
||||||
|
<important>
|
||||||
|
<para>
|
||||||
|
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.
|
||||||
|
</para>
|
||||||
|
</important>
|
||||||
|
<section>
|
||||||
|
<title>Implementation TLS Clients With OpenSSL</title>
|
||||||
|
<para>
|
||||||
|
In the following code, the error handling is only exploratory.
|
||||||
|
Proper error handling is required for production use,
|
||||||
|
especially in libraries.
|
||||||
|
<!-- FIXME: Cross-reference event-driven I/O section when it
|
||||||
|
exists and mention that this is really quite complex to
|
||||||
|
implement. -->
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The OpenSSL library needs explicit initialization (see <xref
|
||||||
|
linkend="ex-Defensive_Coding-TLS-OpenSSL-Init"/>).
|
||||||
|
</para>
|
||||||
|
<example id="ex-Defensive_Coding-TLS-OpenSSL-Init">
|
||||||
|
<title>OpenSSL library initialization</title>
|
||||||
|
<xi:include href="snippets/TLS-Client-OpenSSL-Init.xml"
|
||||||
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</example>
|
||||||
|
<para>
|
||||||
|
After that, a context object has to be created, which acts as
|
||||||
|
a factory for connection objects (<xref
|
||||||
|
linkend="ex-Defensive_Coding-TLS-Client-OpenSSL-CTX"/>). 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.
|
||||||
|
</para>
|
||||||
|
<example id="ex-Defensive_Coding-TLS-Client-OpenSSL-CTX">
|
||||||
|
<title>OpenSSL client context creation</title>
|
||||||
|
<xi:include href="snippets/TLS-Client-OpenSSL-CTX.xml"
|
||||||
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</example>
|
||||||
|
<para>
|
||||||
|
A single context object can be used to create multiple
|
||||||
|
connection objects. It is safe to use the same
|
||||||
|
<literal>SSL_CTX</literal> object for creating connections
|
||||||
|
concurrently from multiple threads, provided that the
|
||||||
|
<literal>SSL_CTX</literal> object is not modified (e.g.,
|
||||||
|
callbacks must not be changed).
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
After creating the TCP socket and disabling the Nagle
|
||||||
|
algorithm (per <xref
|
||||||
|
linkend="ex-Defensive_Coding-TLS-Nagle"/>), the actual
|
||||||
|
connection object needs to be created, as show in <xref
|
||||||
|
linkend="ex-Defensive_Coding-TLS-Client-OpenSSL-CTX"/>. If
|
||||||
|
the handshake started by <function>SSL_connect</function>
|
||||||
|
fails, the <function>ssl_print_error_and_exit</function>
|
||||||
|
function from <xref
|
||||||
|
linkend="ex-Defensive_Coding-TLS-OpenSSL-Errors"/> is called.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The <function>certificate_validity_override</function>
|
||||||
|
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.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The host name passed to the functions
|
||||||
|
<function>SSL_set_tlsext_host_name</function> and
|
||||||
|
<function>X509_check_host</function> must be the name that was
|
||||||
|
passed to <function>getaddrinfo</function> or a similar name
|
||||||
|
resolution function. No host name canonicalization must be
|
||||||
|
performed. The <function>X509_check_host</function> 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
|
||||||
|
<function>certificate_host_name_override</function> 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 <emphasis>and</emphasis> the host
|
||||||
|
name.
|
||||||
|
</para>
|
||||||
|
<example id="ex-Defensive_Coding-TLS-Client-OpenSSL-Connect">
|
||||||
|
<title>Creating a client connection using OpenSSL</title>
|
||||||
|
<xi:include href="snippets/TLS-Client-OpenSSL-Connect.xml"
|
||||||
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</example>
|
||||||
|
<para>
|
||||||
|
The connection object can be used for sending and receiving
|
||||||
|
data, as in <xref
|
||||||
|
linkend="ex-Defensive_Coding-TLS-OpenSSL-Connection-Use"/>.
|
||||||
|
It is also possible to create a <literal>BIO</literal> object
|
||||||
|
and use the <literal>SSL</literal> object as the underlying
|
||||||
|
transport, using <function>BIO_set_ssl</function>.
|
||||||
|
</para>
|
||||||
|
<example id="ex-Defensive_Coding-TLS-OpenSSL-Connection-Use">
|
||||||
|
<title>Using an OpenSSL connection to send and receive data</title>
|
||||||
|
<xi:include href="snippets/TLS-Client-OpenSSL-Connection-Use.xml"
|
||||||
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</example>
|
||||||
|
<para>
|
||||||
|
When it is time to close the connection, the
|
||||||
|
<function>SSL_shutdown</function> function needs to be called
|
||||||
|
twice for an orderly, synchronous connection termination
|
||||||
|
(<xref
|
||||||
|
linkend="ex-Defensive_Coding-TLS-OpenSSL-Connection-Close"/>).
|
||||||
|
This exchanges <literal>close_notify</literal> alerts with the
|
||||||
|
server. The additional logic is required to deal with an
|
||||||
|
unexpected <literal>close_notify</literal> from the server.
|
||||||
|
Note that is necessary to explicitly close the underlying
|
||||||
|
socket after the connection object has been freed.
|
||||||
|
</para>
|
||||||
|
<example id="ex-Defensive_Coding-TLS-OpenSSL-Connection-Close">
|
||||||
|
<title>Closing an OpenSSL connection in an orderly fashion</title>
|
||||||
|
<xi:include href="snippets/TLS-OpenSSL-Connection-Close.xml"
|
||||||
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</example>
|
||||||
|
<para>
|
||||||
|
<xref linkend="ex-Defensive_Coding-TLS-OpenSSL-Context-Close"/> shows how
|
||||||
|
to deallocate the context object when it is no longer needed
|
||||||
|
because no further TLS connections will be established.
|
||||||
|
</para>
|
||||||
|
<example id="ex-Defensive_Coding-TLS-OpenSSL-Context-Close">
|
||||||
|
<title>Closing an OpenSSL connection in an orderly fashion</title>
|
||||||
|
<xi:include href="snippets/TLS-OpenSSL-Context-Close.xml"
|
||||||
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</example>
|
||||||
|
</section>
|
||||||
|
<section id="sect-Defensive_Coding-TLS-Client-GNUTLS">
|
||||||
|
<title>Implementation TLS Clients With GNUTLS</title>
|
||||||
|
<para>
|
||||||
|
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.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The GNUTLS library needs explicit initialization:
|
||||||
|
</para>
|
||||||
|
<informalexample id="ex-Defensive_Coding-TLS-GNUTLS-Init">
|
||||||
|
<xi:include href="snippets/TLS-GNUTLS-Init.xml"
|
||||||
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</informalexample>
|
||||||
|
<para>
|
||||||
|
Failing to do so can result in obscure failures in Base64
|
||||||
|
decoding. See <xref
|
||||||
|
linkend="sect-Defensive_Coding-TLS-Pitfalls-GNUTLS"/> for
|
||||||
|
additional aspects of initialization.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Before setting up TLS connections, a credentials objects has
|
||||||
|
to be allocated and initialized with the set of trusted root
|
||||||
|
CAs (<xref
|
||||||
|
linkend="ex-Defensive_Coding-TLS-Client-GNUTLS-Credentials"/>).
|
||||||
|
</para>
|
||||||
|
<example id="ex-Defensive_Coding-TLS-Client-GNUTLS-Credentials">
|
||||||
|
<title>Initializing a GNUTLS credentials structure</title>
|
||||||
|
<xi:include href="snippets/TLS-Client-GNUTLS-Credentials.xml"
|
||||||
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</example>
|
||||||
|
<para>
|
||||||
|
After the last TLS connection has been closed, this credentials
|
||||||
|
object should be freed:
|
||||||
|
</para>
|
||||||
|
<informalexample>
|
||||||
|
<xi:include href="snippets/TLS-GNUTLS-Credentials-Close.xml"
|
||||||
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</informalexample>
|
||||||
|
<para>
|
||||||
|
During its lifetime, the credentials object can be used to
|
||||||
|
initialize TLS session objects from multiple threads, provided
|
||||||
|
that it is not changed.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Once the TCP connection has been established, the Nagle
|
||||||
|
algorithm should be disabled (see <xref
|
||||||
|
linkend="ex-Defensive_Coding-TLS-Nagle"/>). 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 <literal>NORMAL</literal> set of cipher
|
||||||
|
suites and protocols provides a reasonable default. Then the
|
||||||
|
TLS handshake must be initiated. This is shown in <xref
|
||||||
|
linkend="ex-Defensive_Coding-TLS-Client-GNUTLS-Connect"/>.
|
||||||
|
</para>
|
||||||
|
<example id="ex-Defensive_Coding-TLS-Client-GNUTLS-Connect">
|
||||||
|
<title>Establishing a TLS client connection using GNUTLS</title>
|
||||||
|
<xi:include href="snippets/TLS-Client-GNUTLS-Connect.xml"
|
||||||
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</example>
|
||||||
|
<para>
|
||||||
|
After the handshake has been completed, the server certificate
|
||||||
|
needs to be verified (<xref
|
||||||
|
linkend="ex-Defensive_Coding-TLS-Client-GNUTLS-Verify"/>). In
|
||||||
|
the example, the user-defined
|
||||||
|
<function>certificate_validity_override</function> 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.
|
||||||
|
</para>
|
||||||
|
<example id="ex-Defensive_Coding-TLS-Client-GNUTLS-Verify">
|
||||||
|
<title>Verifying a server certificate using GNUTLS</title>
|
||||||
|
<xi:include href="snippets/TLS-Client-GNUTLS-Verify.xml"
|
||||||
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</example>
|
||||||
|
<para>
|
||||||
|
In the next step (<xref
|
||||||
|
linkend="ex-Defensive_Coding-TLS-Client-GNUTLS-Match"/>, the
|
||||||
|
certificate must be matched against the host name (note the
|
||||||
|
unusual return value from
|
||||||
|
<function>gnutls_x509_crt_check_hostname</function>). Again,
|
||||||
|
an override function
|
||||||
|
<function>certificate_host_name_override</function> is called.
|
||||||
|
Note that the override must be keyed to the certificate
|
||||||
|
<emphasis>and</emphasis> the host name. The function call can
|
||||||
|
be omitted if the override is not needed.
|
||||||
|
</para>
|
||||||
|
<example id="ex-Defensive_Coding-TLS-Client-GNUTLS-Match">
|
||||||
|
<title>Matching the server host name and certificate in a
|
||||||
|
GNUTLS client</title>
|
||||||
|
<xi:include href="snippets/TLS-Client-GNUTLS-Match.xml"
|
||||||
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</example>
|
||||||
|
<para>
|
||||||
|
In newer GNUTLS versions, certificate checking and host name
|
||||||
|
validation can be combined using the
|
||||||
|
<function>gnutls_certificate_verify_peers3</function> function.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
An established TLS session can be used for sending and
|
||||||
|
receiving data, as in <xref
|
||||||
|
linkend="ex-Defensive_Coding-TLS-GNUTLS-Use"/>.
|
||||||
|
</para>
|
||||||
|
<example id="ex-Defensive_Coding-TLS-GNUTLS-Use">
|
||||||
|
<title>Using a GNUTLS session</title>
|
||||||
|
<xi:include href="snippets/TLS-GNUTLS-Use.xml"
|
||||||
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</example>
|
||||||
|
<para>
|
||||||
|
In order to shut down a connection in an orderly manner, you
|
||||||
|
should call the <function>gnutls_bye</function> function.
|
||||||
|
Finally, the session object can be deallocated using
|
||||||
|
<function>gnutls_deinit</function> (see <xref
|
||||||
|
linkend="ex-Defensive_Coding-TLS-GNUTLS-Disconnect"/>).
|
||||||
|
</para>
|
||||||
|
<example id="ex-Defensive_Coding-TLS-GNUTLS-Disconnect">
|
||||||
|
<title>Using a GNUTLS session</title>
|
||||||
|
<xi:include href="snippets/TLS-GNUTLS-Disconnect.xml"
|
||||||
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</example>
|
||||||
|
</section>
|
||||||
|
<section id="sect-Defensive_Coding-TLS-Client-OpenJDK">
|
||||||
|
<title>Implementing TLS Clients With OpenJDK</title>
|
||||||
|
<para>
|
||||||
|
The examples below use the following cryptographic-related
|
||||||
|
classes:
|
||||||
|
</para>
|
||||||
|
<informalexample>
|
||||||
|
<xi:include href="snippets/TLS-Client-OpenJDK-Import.xml"
|
||||||
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</informalexample>
|
||||||
|
<para>
|
||||||
|
If compatibility with OpenJDK 6 is required, it is necessary
|
||||||
|
to use the internal class
|
||||||
|
<literal>sun.security.util.HostnameChecker</literal>. (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
|
||||||
|
<function>setEndpointIdentificationAlgorithm</function> method
|
||||||
|
was added to the
|
||||||
|
<literal>javax.net.ssl.SSLParameters</literal> class,
|
||||||
|
providing an official way to implement host name checking.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
TLS connections are established using an
|
||||||
|
<literal>SSLContext</literal> instance. With a properly
|
||||||
|
configured OpenJDK installation, the
|
||||||
|
<literal>SunJSSE</literal> provider uses the system-wide set
|
||||||
|
of trusted root certificate authorities, so no further
|
||||||
|
configuration is necessary. For backwards compatibility with
|
||||||
|
OpenJDK 6, the <literal>TLSv1</literal> provider has to
|
||||||
|
be supported as a fall-back option. This is shown in <xref
|
||||||
|
linkend="ex-Defensive_Coding-TLS-Client-OpenJDK-Context"/>.
|
||||||
|
</para>
|
||||||
|
<example id="ex-Defensive_Coding-TLS-Client-OpenJDK-Context">
|
||||||
|
<title>Setting up an <literal>SSLContext</literal> for OpenJDK TLS
|
||||||
|
clients</title>
|
||||||
|
<xi:include href="snippets/TLS-Client-OpenJDK-Context.xml"
|
||||||
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</example>
|
||||||
|
<para>
|
||||||
|
In addition to the context, a TLS parameter object will be
|
||||||
|
needed which adjusts the cipher suites and protocols (<xref
|
||||||
|
linkend="ex-Defensive_Coding-TLS-OpenJDK-Parameters"/>). Like
|
||||||
|
the context, these parameters can be reused for multiple TLS
|
||||||
|
connections.
|
||||||
|
</para>
|
||||||
|
<example id="ex-Defensive_Coding-TLS-OpenJDK-Parameters">
|
||||||
|
<title>Setting up <literal>SSLParameters</literal> for TLS use
|
||||||
|
with OpenJDK</title>
|
||||||
|
<xi:include href="snippets/TLS-OpenJDK-Parameters.xml"
|
||||||
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</example>
|
||||||
|
<para>
|
||||||
|
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:
|
||||||
|
</para>
|
||||||
|
<informalexample>
|
||||||
|
<xi:include href="snippets/TLS-Client-OpenJDK-Hostname.xml"
|
||||||
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</informalexample>
|
||||||
|
<para>
|
||||||
|
All application protocols can use the
|
||||||
|
<literal>"HTTPS"</literal> algorithm. (The algorithms have
|
||||||
|
minor differences with regard to wildcard handling, which
|
||||||
|
should not matter in practice.)
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
<xref linkend="ex-Defensive_Coding-TLS-Client-OpenJDK-Connect"/>
|
||||||
|
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
|
||||||
|
<literal>params</literal>. (After this point, changes to
|
||||||
|
<literal>params</literal> will not affect this TLS socket.)
|
||||||
|
As mentioned initially, host name checking requires using an
|
||||||
|
internal API on OpenJDK 6.
|
||||||
|
</para>
|
||||||
|
<example id="ex-Defensive_Coding-TLS-Client-OpenJDK-Connect">
|
||||||
|
<title>Establishing a TLS connection with OpenJDK</title>
|
||||||
|
<xi:include href="snippets/TLS-Client-OpenJDK-Connect.xml"
|
||||||
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</example>
|
||||||
|
<para>
|
||||||
|
Starting with OpenJDK 7, the last lines can be omitted,
|
||||||
|
provided that host name verification has been enabled by
|
||||||
|
calling the
|
||||||
|
<function>setEndpointIdentificationAlgorithm</function> method
|
||||||
|
on the <literal>params</literal> object (before it was applied
|
||||||
|
to the socket).
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The TLS socket can be used as a regular socket, as shown in
|
||||||
|
<xref linkend="ex-Defensive_Coding-TLS-Client-OpenJDK-Use"/>.
|
||||||
|
</para>
|
||||||
|
<example id="ex-Defensive_Coding-TLS-Client-OpenJDK-Use">
|
||||||
|
<title>Using a TLS client socket in OpenJDK</title>
|
||||||
|
<xi:include href="snippets/TLS-Client-OpenJDK-Use.xml"
|
||||||
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</example>
|
||||||
|
<section>
|
||||||
|
<title>Overriding server certificate validation with OpenJDK 6</title>
|
||||||
|
<para>
|
||||||
|
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
|
||||||
|
<literal>TrustManager</literal> and
|
||||||
|
<literal>SSLContext</literal> objects have to be used for
|
||||||
|
different servers.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
In the trust manager shown in <xref
|
||||||
|
linkend="ex-Defensive_Coding-TLS-Client-MyTrustManager"/>,
|
||||||
|
the server certificate is identified by its SHA-256 hash.
|
||||||
|
</para>
|
||||||
|
<example id="ex-Defensive_Coding-TLS-Client-MyTrustManager">
|
||||||
|
<title>A customer trust manager for OpenJDK TLS clients</title>
|
||||||
|
<xi:include href="snippets/TLS-Client-OpenJDK-MyTrustManager.xml"
|
||||||
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</example>
|
||||||
|
<para>
|
||||||
|
This trust manager has to be passed to the
|
||||||
|
<literal>init</literal> method of the
|
||||||
|
<literal>SSLContext</literal> object, as show in <xref
|
||||||
|
linkend="ex-Defensive_Coding-TLS-Client-Context_For_Cert"/>.
|
||||||
|
</para>
|
||||||
|
<example id="ex-Defensive_Coding-TLS-Client-Context_For_Cert">
|
||||||
|
<title>Using a custom TLS trust manager with OpenJDK</title>
|
||||||
|
<xi:include href="snippets/TLS-Client-OpenJDK-Context_For_Cert.xml"
|
||||||
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</example>
|
||||||
|
<para>
|
||||||
|
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.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
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
|
||||||
|
<literal>javax.net.ssl.X509ExtendedTrustManager</literal>
|
||||||
|
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.
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
</section>
|
||||||
|
<section id="sect-Defensive_Coding-TLS-Client-NSS">
|
||||||
|
<title>Implementing TLS Clients With NSS</title>
|
||||||
|
<para>
|
||||||
|
The following code shows how to implement a simple TLS client
|
||||||
|
using NSS. Note that the error handling needs replacing
|
||||||
|
before production use.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Using NSS needs several header files, as shown in
|
||||||
|
<xref linkend="ex-Defensive_Coding-TLS-NSS-Includes"/>.
|
||||||
|
</para>
|
||||||
|
<example id="ex-Defensive_Coding-TLS-NSS-Includes">
|
||||||
|
<title>Include files for NSS</title>
|
||||||
|
<xi:include href="snippets/TLS-NSS-Includes.xml"
|
||||||
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</example>
|
||||||
|
<para>
|
||||||
|
Initializing the NSS library is a complex task (<xref
|
||||||
|
linkend="ex-Defensive_Coding-TLS-NSS-Init"/>). It is not
|
||||||
|
thread-safe. By default, the library is in export mode, and
|
||||||
|
all strong ciphers are disabled. Therefore, after creating
|
||||||
|
the <literal>NSSInitCContext</literal> 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
|
||||||
|
<function>NSS_SetDomesticPolicy</function> 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.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The simplest way to configured the trusted root certificates
|
||||||
|
involves loading the <filename>libnssckbi.so</filename> NSS
|
||||||
|
module with a call to the
|
||||||
|
<function>SECMOD_LoadUserModule</function> function. The root
|
||||||
|
certificates are compiled into this module. (The PEM module
|
||||||
|
for NSS, <filename>libnsspem.so</filename>, offers a way to
|
||||||
|
load trusted CA certificates from a file.)
|
||||||
|
</para>
|
||||||
|
<example id="ex-Defensive_Coding-TLS-NSS-Init">
|
||||||
|
<title>Initializing the NSS library</title>
|
||||||
|
<xi:include href="snippets/TLS-NSS-Init.xml"
|
||||||
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</example>
|
||||||
|
<para>
|
||||||
|
Some of the effects of the initialization can be reverted with
|
||||||
|
the following function calls:
|
||||||
|
</para>
|
||||||
|
<informalexample id="ex-Defensive_Coding-TLS-NSS-Close">
|
||||||
|
<xi:include href="snippets/TLS-NSS-Close.xml"
|
||||||
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</informalexample>
|
||||||
|
<para>
|
||||||
|
After NSS has been initialized, the TLS connection can be
|
||||||
|
created (<xref
|
||||||
|
linkend="ex-Defensive_Coding-TLS-Client-NSS-Connect"/>). The
|
||||||
|
internal <function>PR_ImportTCPSocket</function> function is
|
||||||
|
used to turn the POSIX file descriptor
|
||||||
|
<literal>sockfd</literal> 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 <emphasis>model</emphasis> descriptor, which is
|
||||||
|
configured with the desired set of protocols and ciphers.
|
||||||
|
(The <literal>good_ciphers</literal> variable is part of <xref
|
||||||
|
linkend="ex-Defensive_Coding-TLS-NSS-Init"/>.) 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.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The call to <function>SSL_BadCertHook</function> can be
|
||||||
|
omitted if no mechanism to override certificate verification
|
||||||
|
is needed. The <literal>bad_certificate</literal> function
|
||||||
|
must check both the host name specified for the connection and
|
||||||
|
the certificate before granting the override.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Triggering the actual handshake requires three function calls,
|
||||||
|
<function>SSL_ResetHandshake</function>,
|
||||||
|
<function>SSL_SetURL</function>, and
|
||||||
|
<function>SSL_ForceHandshake</function>. (If
|
||||||
|
<function>SSL_ResetHandshake</function> is omitted,
|
||||||
|
<function>SSL_ForceHandshake</function> will succeed, but the
|
||||||
|
data will not be encrypted.) During the handshake, the
|
||||||
|
certificate is verified and matched against the host name.
|
||||||
|
</para>
|
||||||
|
<example id="ex-Defensive_Coding-TLS-Client-NSS-Connect">
|
||||||
|
<title>Creating a TLS connection with NSS</title>
|
||||||
|
<xi:include href="snippets/TLS-Client-NSS-Connect.xml"
|
||||||
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</example>
|
||||||
|
<para>
|
||||||
|
After the connection has been established, <xref
|
||||||
|
linkend="ex-Defensive_Coding-TLS-NSS-Use"/> shows how to use
|
||||||
|
the NSPR descriptor to communicate with the server.
|
||||||
|
</para>
|
||||||
|
<example id="ex-Defensive_Coding-TLS-NSS-Use">
|
||||||
|
<title>Using NSS for sending and receiving data</title>
|
||||||
|
<xi:include href="snippets/TLS-NSS-Use.xml"
|
||||||
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</example>
|
||||||
|
<para>
|
||||||
|
<xref linkend="ex-Defensive_Coding-TLS-Client-NSS-Close"/>
|
||||||
|
shows how to close the connection.
|
||||||
|
</para>
|
||||||
|
<example id="ex-Defensive_Coding-TLS-Client-NSS-Close">
|
||||||
|
<title>Closing NSS client connections</title>
|
||||||
|
<xi:include href="snippets/TLS-Client-NSS-Close.xml"
|
||||||
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</example>
|
||||||
|
</section>
|
||||||
|
<section id="sect-Defensive_Coding-TLS-Client-Python">
|
||||||
|
<title>Implementing TLS Clients With Python</title>
|
||||||
|
<para>
|
||||||
|
The Python distribution provides a TLS implementation in the
|
||||||
|
<literal>ssl</literal> 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 <xref
|
||||||
|
linkend="sect-Defensive_Coding-TLS-OpenSSL"/>.
|
||||||
|
</para>
|
||||||
|
<important>
|
||||||
|
<para>
|
||||||
|
Currently, most Python function which accept
|
||||||
|
<literal>https://</literal> URLs or otherwise implement
|
||||||
|
HTTPS support do not perform certificate validation at all.
|
||||||
|
(For example, this is true for the <literal>httplib</literal>
|
||||||
|
and <literal>xmlrpclib</literal> modules.) If you use
|
||||||
|
HTTPS, you should not use the built-in HTTP clients. The
|
||||||
|
<literal>Curl</literal> class in the <literal>curl</literal>
|
||||||
|
module, as provided by the <literal>python-pycurl</literal>
|
||||||
|
package implements proper certificate validation.
|
||||||
|
</para>
|
||||||
|
</important>
|
||||||
|
<para>
|
||||||
|
The <literal>ssl</literal> module currently does not perform
|
||||||
|
host name checking on the server certificate. <xref
|
||||||
|
linkend="ex-Defensive_Coding-TLS-Client-Python-check_host_name"/>
|
||||||
|
shows how to implement certificate matching, using the parsed
|
||||||
|
certificate returned by <function>getpeercert</function>.
|
||||||
|
</para>
|
||||||
|
<example id="ex-Defensive_Coding-TLS-Client-Python-check_host_name">
|
||||||
|
<title>Implementing TLS host name checking Python (without
|
||||||
|
wildcard support)</title>
|
||||||
|
<xi:include href="snippets/TLS-Client-Python-check_host_name.xml"
|
||||||
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</example>
|
||||||
|
<para>
|
||||||
|
To turn a regular, connected TCP socket into a TLS-enabled
|
||||||
|
socket, use the <function>ssl.wrap_socket</function> function.
|
||||||
|
The function call in <xref
|
||||||
|
linkend="ex-Defensive_Coding-TLS-Client-Python-Connect"/>
|
||||||
|
provides additional arguments to override questionable
|
||||||
|
defaults in OpenSSL and in the Python module.
|
||||||
|
</para>
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<literal>ciphers="HIGH:-aNULL:-eNULL:-PSK:RC4-SHA:RC4-MD5"</literal>
|
||||||
|
selects relatively strong cipher suites with
|
||||||
|
certificate-based authentication. (The call to
|
||||||
|
<function>check_host_name</function> function provides
|
||||||
|
additional protection against anonymous cipher suites.)
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<literal>ssl_version=ssl.PROTOCOL_TLSv1</literal> disables
|
||||||
|
SSL 2.0 support. By default, the <literal>ssl</literal>
|
||||||
|
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.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<literal>cert_reqs=ssl.CERT_REQUIRED</literal> turns on
|
||||||
|
certificate validation.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<literal>ca_certs='/etc/ssl/certs/ca-bundle.crt'</literal>
|
||||||
|
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
|
||||||
|
<literal>ssl</literal> module.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
<para>
|
||||||
|
The <literal>ssl</literal> module (and OpenSSL) perform
|
||||||
|
certificate validation, but the certificate must be compared
|
||||||
|
manually against the host name, by calling the
|
||||||
|
<function>check_host_name</function> defined above.
|
||||||
|
</para>
|
||||||
|
<example id="ex-Defensive_Coding-TLS-Client-Python-Connect">
|
||||||
|
<title>Establishing a TLS client connection with Python</title>
|
||||||
|
<xi:include href="snippets/TLS-Client-Python-Connect.xml"
|
||||||
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</example>
|
||||||
|
<para>
|
||||||
|
After the connection has been established, the TLS socket can
|
||||||
|
be used like a regular socket:
|
||||||
|
</para>
|
||||||
|
<informalexample>
|
||||||
|
<xi:include href="snippets/TLS-Python-Use.xml"
|
||||||
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</informalexample>
|
||||||
|
<para>
|
||||||
|
Closing the TLS socket is straightforward as well:
|
||||||
|
</para>
|
||||||
|
<informalexample>
|
||||||
|
<xi:include href="snippets/TLS-Python-Close.xml"
|
||||||
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</informalexample>
|
||||||
|
</section>
|
||||||
|
</section>
|
||||||
|
</chapter>
|
|
@ -0,0 +1,4 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<locatingRules xmlns="http://thaiopensource.com/ns/locating-rules/1.0">
|
||||||
|
<include rules="../../schemas.xml"/>
|
||||||
|
</locatingRules>
|
189
defensive-coding/en-US/Features/Authentication.xml
Normal file
189
defensive-coding/en-US/Features/Authentication.xml
Normal file
|
@ -0,0 +1,189 @@
|
||||||
|
<?xml version='1.0' encoding='utf-8' ?>
|
||||||
|
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
|
||||||
|
]>
|
||||||
|
<chapter id="chap-Defensive_Coding-Authentication">
|
||||||
|
<title>Authentication and Authorization</title>
|
||||||
|
|
||||||
|
<section id="sect-Defensive_Coding-Authentication-Server">
|
||||||
|
<title>Authenticating servers</title>
|
||||||
|
<para>
|
||||||
|
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:
|
||||||
|
</para>
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
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.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
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.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
On Linux, UNIX domain sockets (of the
|
||||||
|
<literal>PF_UNIX</literal> protocol family, sometimes called
|
||||||
|
<literal>PF_LOCAL</literal>) are restricted by file system
|
||||||
|
permissions. If the server socket path is not
|
||||||
|
world-writable, the server identity cannot be spoofed by
|
||||||
|
local users.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Port numbers less than 1024 (<emphasis>trusted
|
||||||
|
ports</emphasis>) can only be used by
|
||||||
|
<literal>root</literal>, 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.)
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
<para>
|
||||||
|
TLS (<xref linkend="chap-Defensive_Coding-TLS"/>) is the
|
||||||
|
recommended way for securing connections over untrusted
|
||||||
|
networks.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
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.
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section id="sect-Defensive_Coding-Authentication-Host_based">
|
||||||
|
<title>Host-based authentication</title>
|
||||||
|
<para>
|
||||||
|
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
|
||||||
|
<filename>/etc/hosts</filename>). 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.)
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
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.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The names returned by <function>gethostbyaddr</function> and
|
||||||
|
<function>getnameinfo</function> 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
|
||||||
|
<function>gethostbyaddr</function> or
|
||||||
|
<function>getaddrinfo</function> has to be performed. The name
|
||||||
|
is only valid if the original address is found among the results
|
||||||
|
of the forward lookup (<emphasis>double-reverse
|
||||||
|
lookup</emphasis>).
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
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.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
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.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
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.
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section id="sect-Defensive_Coding-Authentication-UNIX_Domain">
|
||||||
|
<title>UNIX domain socket authentication</title>
|
||||||
|
<para>
|
||||||
|
UNIX domain sockets (with address family
|
||||||
|
<literal>AF_UNIX</literal> or <literal>AF_LOCAL</literal>) are
|
||||||
|
restricted to the local host and offer a special authentication
|
||||||
|
mechanism: credentials passing.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Nowadays, most systems support the
|
||||||
|
<literal>SO_PEERCRED</literal> (Linux) or
|
||||||
|
<literal>LOCAL_PEERCRED</literal> (FreeBSD) socket options, or
|
||||||
|
the <function>getpeereid</function> (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.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Historically, credentials passing was implemented using
|
||||||
|
ancillary data in the <function>sendmsg</function> and
|
||||||
|
<function>recvmsg</function> 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.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
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
|
||||||
|
<function>getpwuid</function> (or
|
||||||
|
<function>getpwuid_r</function>) and
|
||||||
|
<function>getgrouplist</function>. Using the PID and
|
||||||
|
information from <filename>/proc/PID/status</filename> is prone
|
||||||
|
to race conditions and insecure.
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section id="sect-Defensive_Coding-Authentication-Netlink">
|
||||||
|
<title><literal>AF_NETLINK</literal> authentication of origin</title>
|
||||||
|
<!-- ??? kernel change may make this obsolete:
|
||||||
|
https://bugzilla.redhat.com/show_bug.cgi?id=851968 -->
|
||||||
|
<para>
|
||||||
|
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.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
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
|
||||||
|
<literal>nl_pid</literal> in the <literal>sockaddr_nl</literal>
|
||||||
|
structure is <literal>0</literal>. (This structure can be
|
||||||
|
obtained using <function>recvfrom</function> or
|
||||||
|
<function>recvmsg</function>, it is different from the
|
||||||
|
<literal>nlmsghdr</literal> structure.) The kernel does not
|
||||||
|
prevent other processes from sending unicast Netlink messages,
|
||||||
|
but the <literal>nl_pid</literal> field in the sender's socket
|
||||||
|
address will be non-zero in such cases.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Applications should not use <literal>AF_NETLINK</literal>
|
||||||
|
sockets as an IPC mechanism among processes, but prefer UNIX
|
||||||
|
domain sockets for this tasks.
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
</chapter>
|
||||||
|
|
988
defensive-coding/en-US/Features/TLS.xml
Normal file
988
defensive-coding/en-US/Features/TLS.xml
Normal file
|
@ -0,0 +1,988 @@
|
||||||
|
<?xml version='1.0' encoding='utf-8' ?>
|
||||||
|
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
|
||||||
|
]>
|
||||||
|
<chapter id="chap-Defensive_Coding-TLS">
|
||||||
|
<title>Transport Layer Security</title>
|
||||||
|
<para>
|
||||||
|
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.
|
||||||
|
</para>
|
||||||
|
<section id="sect-Defensive_Coding-TLS-Pitfalls">
|
||||||
|
<title>Common Pitfalls</title>
|
||||||
|
<para>
|
||||||
|
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.
|
||||||
|
</para>
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
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.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
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.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
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.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
The TLS handshake has very poor performance if the TCP Nagle
|
||||||
|
algorithm is active. You should switch on the
|
||||||
|
<literal>TCP_NODELAY</literal> socket option (at least for the
|
||||||
|
duration of the handshake), or use the Linux-specific
|
||||||
|
<literal>TCP_CORK</literal> option.
|
||||||
|
</para>
|
||||||
|
<example id="ex-Defensive_Coding-TLS-Nagle">
|
||||||
|
<title>Deactivating the TCP Nagle algorithm</title>
|
||||||
|
<xi:include href="snippets/TLS-Nagle.xml"
|
||||||
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</example>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
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).
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Both client and server should work towards an orderly
|
||||||
|
connection shutdown, that is send
|
||||||
|
<literal>close_notify</literal> 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).
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
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 <function>accept</function> 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.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
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 <function>fork</function> function
|
||||||
|
calls (see <xref
|
||||||
|
linkend="sect-Defensive_Coding-Tasks-Processes-Fork-Parallel"/>).
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
<section id="sect-Defensive_Coding-TLS-OpenSSL">
|
||||||
|
<title>OpenSSL Pitfalls</title>
|
||||||
|
<para>
|
||||||
|
Some OpenSSL function use <emphasis>tri-state return
|
||||||
|
values</emphasis>. Correct error checking is extremely
|
||||||
|
important. Several functions return <literal>int</literal>
|
||||||
|
values with the following meaning:
|
||||||
|
</para>
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
The value <literal>1</literal> indicates success (for
|
||||||
|
example, a successful signature verification).
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
The value <literal>0</literal> indicates semantic
|
||||||
|
failure (for example, a signature verification which was
|
||||||
|
unsuccessful because the signing certificate was
|
||||||
|
self-signed).
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
The value <literal>-1</literal> indicates a low-level
|
||||||
|
error in the system, such as failure to allocate memory
|
||||||
|
using <function>malloc</function>.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
<para>
|
||||||
|
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.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Recovering precise error information is difficult.
|
||||||
|
<xref linkend="ex-Defensive_Coding-TLS-OpenSSL-Errors"/>
|
||||||
|
shows how to obtain a more precise error code after a function
|
||||||
|
call on an <literal>SSL</literal> object has failed. However,
|
||||||
|
there are still cases where no detailed error information is
|
||||||
|
available (e.g., if <function>SSL_shutdown</function> fails
|
||||||
|
due to a connection teardown by the other end).
|
||||||
|
</para>
|
||||||
|
<example id="ex-Defensive_Coding-TLS-OpenSSL-Errors">
|
||||||
|
<title>Obtaining OpenSSL error codes</title>
|
||||||
|
<xi:include href="snippets/TLS-OpenSSL-Errors.xml"
|
||||||
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</example>
|
||||||
|
<para>
|
||||||
|
The <function>OPENSSL_config</function> 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.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
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 <literal>d2i_</literal> and end in
|
||||||
|
<literal>_fp</literal> or <literal>_bio</literal> (e.g.,
|
||||||
|
<function>d2i_X509_fp</function> or
|
||||||
|
<function>d2i_X509_bio</function>). These decoders must not
|
||||||
|
be used for parsing data from untrusted sources; instead,
|
||||||
|
the variants without the <literal>_fp</literal> and
|
||||||
|
<literal>_bio</literal> (e.g.,
|
||||||
|
<function>d2i_X509</function>) shall be used. The BIO
|
||||||
|
variants have received considerably less testing and are not
|
||||||
|
very robust.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
For the same reason, the OpenSSL command line tools (such as
|
||||||
|
<command>openssl x509</command>) are generally generally less
|
||||||
|
robust than the actual library code. They use the BIO
|
||||||
|
functions internally, and not the more robust variants.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The command line tools do not always indicate failure in the
|
||||||
|
exit status of the <application>openssl</application> process.
|
||||||
|
For instance, a verification failure in <command>openssl
|
||||||
|
verify</command> result in an exit status of zero.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The OpenSSL server and client applications (<command>openssl
|
||||||
|
s_client</command> and <command>openssl s_server</command>)
|
||||||
|
are debugging tools and should <emphasis>never</emphasis> be
|
||||||
|
used as generic clients. For instance, the
|
||||||
|
<application>s_client</application> tool reacts in a
|
||||||
|
surprisign way to lines starting with <literal>R</literal> and
|
||||||
|
<literal>Q</literal>.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
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.
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
<section id="sect-Defensive_Coding-TLS-Pitfalls-GNUTLS">
|
||||||
|
<title>GNUTLS Pitfalls</title>
|
||||||
|
<para>
|
||||||
|
<filename>libgnutls.so.26</filename> links to
|
||||||
|
<filename>libpthread.so.0</filename>. Loading the threading
|
||||||
|
library too late causes problems, so the main program should
|
||||||
|
be linked with <literal>-lpthread</literal> as well. As a
|
||||||
|
result, it can be difficult to use GNUTLS in a plugin which is
|
||||||
|
loaded with the <function>dlopen</function> 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.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The <function>gnutls_global_init</function> 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.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The <function>gnutls_global_deinit</function> function does
|
||||||
|
not actually deallocate all resources allocated by
|
||||||
|
<function>gnutls_global_init</function>. It is currently not
|
||||||
|
thread-safe. Therefore, it is best to avoid calling it
|
||||||
|
altogether.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
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.
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
<section id="sect-Defensive_Coding-TLS-Pitfalls-OpenJDK">
|
||||||
|
<title>OpenJDK Pitfalls</title>
|
||||||
|
<para>
|
||||||
|
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.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
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 <emphasis>unlimited
|
||||||
|
strength jurisdiction policy files</emphasis>. 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.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Some versions of OpenJDK use <filename>/dev/random</filename>
|
||||||
|
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
|
||||||
|
<filename>/dev/random</filename>.
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
<section id="sect-Defensive_Coding-TLS-Pitfalls-NSS">
|
||||||
|
<title>NSS Pitfalls</title>
|
||||||
|
<para>
|
||||||
|
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.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
If the NSPR descriptor is in an unexpected state, the
|
||||||
|
<function>SSL_ForceHandshake</function> function can succeed,
|
||||||
|
but no TLS handshake takes place, the peer is not
|
||||||
|
authenticated, and subsequent data is exchanged in the clear.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
NSS disables itself if it detects that the process underwent a
|
||||||
|
<function>fork</function> after the library has been
|
||||||
|
initialized. This behavior is required by the PKCS#11 API
|
||||||
|
specification.
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
</section>
|
||||||
|
<section id="sect-Defensive_Coding-TLS-Client">
|
||||||
|
<title>TLS Clients</title>
|
||||||
|
<para>
|
||||||
|
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.)
|
||||||
|
</para>
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
The client must configure the TLS library to use a set of
|
||||||
|
trusted root certificates. These certificates are provided
|
||||||
|
by the system in <filename
|
||||||
|
class="directory">/etc/ssl/certs</filename> or files derived
|
||||||
|
from it.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
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).
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
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.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
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.)
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
The client must check that the configured or user-provided
|
||||||
|
server name matches the peer certificate provided by the
|
||||||
|
server.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
<para>
|
||||||
|
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.
|
||||||
|
</para>
|
||||||
|
<important>
|
||||||
|
<para>
|
||||||
|
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.
|
||||||
|
</para>
|
||||||
|
</important>
|
||||||
|
<section>
|
||||||
|
<title>Implementation TLS Clients With OpenSSL</title>
|
||||||
|
<para>
|
||||||
|
In the following code, the error handling is only exploratory.
|
||||||
|
Proper error handling is required for production use,
|
||||||
|
especially in libraries.
|
||||||
|
<!-- FIXME: Cross-reference event-driven I/O section when it
|
||||||
|
exists and mention that this is really quite complex to
|
||||||
|
implement. -->
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The OpenSSL library needs explicit initialization (see <xref
|
||||||
|
linkend="ex-Defensive_Coding-TLS-OpenSSL-Init"/>).
|
||||||
|
</para>
|
||||||
|
<example id="ex-Defensive_Coding-TLS-OpenSSL-Init">
|
||||||
|
<title>OpenSSL library initialization</title>
|
||||||
|
<xi:include href="snippets/TLS-Client-OpenSSL-Init.xml"
|
||||||
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</example>
|
||||||
|
<para>
|
||||||
|
After that, a context object has to be created, which acts as
|
||||||
|
a factory for connection objects (<xref
|
||||||
|
linkend="ex-Defensive_Coding-TLS-Client-OpenSSL-CTX"/>). 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.
|
||||||
|
</para>
|
||||||
|
<example id="ex-Defensive_Coding-TLS-Client-OpenSSL-CTX">
|
||||||
|
<title>OpenSSL client context creation</title>
|
||||||
|
<xi:include href="snippets/TLS-Client-OpenSSL-CTX.xml"
|
||||||
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</example>
|
||||||
|
<para>
|
||||||
|
A single context object can be used to create multiple
|
||||||
|
connection objects. It is safe to use the same
|
||||||
|
<literal>SSL_CTX</literal> object for creating connections
|
||||||
|
concurrently from multiple threads, provided that the
|
||||||
|
<literal>SSL_CTX</literal> object is not modified (e.g.,
|
||||||
|
callbacks must not be changed).
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
After creating the TCP socket and disabling the Nagle
|
||||||
|
algorithm (per <xref
|
||||||
|
linkend="ex-Defensive_Coding-TLS-Nagle"/>), the actual
|
||||||
|
connection object needs to be created, as show in <xref
|
||||||
|
linkend="ex-Defensive_Coding-TLS-Client-OpenSSL-CTX"/>. If
|
||||||
|
the handshake started by <function>SSL_connect</function>
|
||||||
|
fails, the <function>ssl_print_error_and_exit</function>
|
||||||
|
function from <xref
|
||||||
|
linkend="ex-Defensive_Coding-TLS-OpenSSL-Errors"/> is called.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The <function>certificate_validity_override</function>
|
||||||
|
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.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The host name passed to the functions
|
||||||
|
<function>SSL_set_tlsext_host_name</function> and
|
||||||
|
<function>X509_check_host</function> must be the name that was
|
||||||
|
passed to <function>getaddrinfo</function> or a similar name
|
||||||
|
resolution function. No host name canonicalization must be
|
||||||
|
performed. The <function>X509_check_host</function> 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
|
||||||
|
<function>certificate_host_name_override</function> 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 <emphasis>and</emphasis> the host
|
||||||
|
name.
|
||||||
|
</para>
|
||||||
|
<example id="ex-Defensive_Coding-TLS-Client-OpenSSL-Connect">
|
||||||
|
<title>Creating a client connection using OpenSSL</title>
|
||||||
|
<xi:include href="snippets/TLS-Client-OpenSSL-Connect.xml"
|
||||||
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</example>
|
||||||
|
<para>
|
||||||
|
The connection object can be used for sending and receiving
|
||||||
|
data, as in <xref
|
||||||
|
linkend="ex-Defensive_Coding-TLS-OpenSSL-Connection-Use"/>.
|
||||||
|
It is also possible to create a <literal>BIO</literal> object
|
||||||
|
and use the <literal>SSL</literal> object as the underlying
|
||||||
|
transport, using <function>BIO_set_ssl</function>.
|
||||||
|
</para>
|
||||||
|
<example id="ex-Defensive_Coding-TLS-OpenSSL-Connection-Use">
|
||||||
|
<title>Using an OpenSSL connection to send and receive data</title>
|
||||||
|
<xi:include href="snippets/TLS-Client-OpenSSL-Connection-Use.xml"
|
||||||
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</example>
|
||||||
|
<para>
|
||||||
|
When it is time to close the connection, the
|
||||||
|
<function>SSL_shutdown</function> function needs to be called
|
||||||
|
twice for an orderly, synchronous connection termination
|
||||||
|
(<xref
|
||||||
|
linkend="ex-Defensive_Coding-TLS-OpenSSL-Connection-Close"/>).
|
||||||
|
This exchanges <literal>close_notify</literal> alerts with the
|
||||||
|
server. The additional logic is required to deal with an
|
||||||
|
unexpected <literal>close_notify</literal> from the server.
|
||||||
|
Note that is necessary to explicitly close the underlying
|
||||||
|
socket after the connection object has been freed.
|
||||||
|
</para>
|
||||||
|
<example id="ex-Defensive_Coding-TLS-OpenSSL-Connection-Close">
|
||||||
|
<title>Closing an OpenSSL connection in an orderly fashion</title>
|
||||||
|
<xi:include href="snippets/TLS-OpenSSL-Connection-Close.xml"
|
||||||
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</example>
|
||||||
|
<para>
|
||||||
|
<xref linkend="ex-Defensive_Coding-TLS-OpenSSL-Context-Close"/> shows how
|
||||||
|
to deallocate the context object when it is no longer needed
|
||||||
|
because no further TLS connections will be established.
|
||||||
|
</para>
|
||||||
|
<example id="ex-Defensive_Coding-TLS-OpenSSL-Context-Close">
|
||||||
|
<title>Closing an OpenSSL connection in an orderly fashion</title>
|
||||||
|
<xi:include href="snippets/TLS-OpenSSL-Context-Close.xml"
|
||||||
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</example>
|
||||||
|
</section>
|
||||||
|
<section id="sect-Defensive_Coding-TLS-Client-GNUTLS">
|
||||||
|
<title>Implementation TLS Clients With GNUTLS</title>
|
||||||
|
<para>
|
||||||
|
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.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The GNUTLS library needs explicit initialization:
|
||||||
|
</para>
|
||||||
|
<informalexample id="ex-Defensive_Coding-TLS-GNUTLS-Init">
|
||||||
|
<xi:include href="snippets/TLS-GNUTLS-Init.xml"
|
||||||
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</informalexample>
|
||||||
|
<para>
|
||||||
|
Failing to do so can result in obscure failures in Base64
|
||||||
|
decoding. See <xref
|
||||||
|
linkend="sect-Defensive_Coding-TLS-Pitfalls-GNUTLS"/> for
|
||||||
|
additional aspects of initialization.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Before setting up TLS connections, a credentials objects has
|
||||||
|
to be allocated and initialized with the set of trusted root
|
||||||
|
CAs (<xref
|
||||||
|
linkend="ex-Defensive_Coding-TLS-Client-GNUTLS-Credentials"/>).
|
||||||
|
</para>
|
||||||
|
<example id="ex-Defensive_Coding-TLS-Client-GNUTLS-Credentials">
|
||||||
|
<title>Initializing a GNUTLS credentials structure</title>
|
||||||
|
<xi:include href="snippets/TLS-Client-GNUTLS-Credentials.xml"
|
||||||
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</example>
|
||||||
|
<para>
|
||||||
|
After the last TLS connection has been closed, this credentials
|
||||||
|
object should be freed:
|
||||||
|
</para>
|
||||||
|
<informalexample>
|
||||||
|
<xi:include href="snippets/TLS-GNUTLS-Credentials-Close.xml"
|
||||||
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</informalexample>
|
||||||
|
<para>
|
||||||
|
During its lifetime, the credentials object can be used to
|
||||||
|
initialize TLS session objects from multiple threads, provided
|
||||||
|
that it is not changed.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Once the TCP connection has been established, the Nagle
|
||||||
|
algorithm should be disabled (see <xref
|
||||||
|
linkend="ex-Defensive_Coding-TLS-Nagle"/>). 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 <literal>NORMAL</literal> set of cipher
|
||||||
|
suites and protocols provides a reasonable default. Then the
|
||||||
|
TLS handshake must be initiated. This is shown in <xref
|
||||||
|
linkend="ex-Defensive_Coding-TLS-Client-GNUTLS-Connect"/>.
|
||||||
|
</para>
|
||||||
|
<example id="ex-Defensive_Coding-TLS-Client-GNUTLS-Connect">
|
||||||
|
<title>Establishing a TLS client connection using GNUTLS</title>
|
||||||
|
<xi:include href="snippets/TLS-Client-GNUTLS-Connect.xml"
|
||||||
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</example>
|
||||||
|
<para>
|
||||||
|
After the handshake has been completed, the server certificate
|
||||||
|
needs to be verified (<xref
|
||||||
|
linkend="ex-Defensive_Coding-TLS-Client-GNUTLS-Verify"/>). In
|
||||||
|
the example, the user-defined
|
||||||
|
<function>certificate_validity_override</function> 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.
|
||||||
|
</para>
|
||||||
|
<example id="ex-Defensive_Coding-TLS-Client-GNUTLS-Verify">
|
||||||
|
<title>Verifying a server certificate using GNUTLS</title>
|
||||||
|
<xi:include href="snippets/TLS-Client-GNUTLS-Verify.xml"
|
||||||
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</example>
|
||||||
|
<para>
|
||||||
|
In the next step (<xref
|
||||||
|
linkend="ex-Defensive_Coding-TLS-Client-GNUTLS-Match"/>, the
|
||||||
|
certificate must be matched against the host name (note the
|
||||||
|
unusual return value from
|
||||||
|
<function>gnutls_x509_crt_check_hostname</function>). Again,
|
||||||
|
an override function
|
||||||
|
<function>certificate_host_name_override</function> is called.
|
||||||
|
Note that the override must be keyed to the certificate
|
||||||
|
<emphasis>and</emphasis> the host name. The function call can
|
||||||
|
be omitted if the override is not needed.
|
||||||
|
</para>
|
||||||
|
<example id="ex-Defensive_Coding-TLS-Client-GNUTLS-Match">
|
||||||
|
<title>Matching the server host name and certificate in a
|
||||||
|
GNUTLS client</title>
|
||||||
|
<xi:include href="snippets/TLS-Client-GNUTLS-Match.xml"
|
||||||
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</example>
|
||||||
|
<para>
|
||||||
|
In newer GNUTLS versions, certificate checking and host name
|
||||||
|
validation can be combined using the
|
||||||
|
<function>gnutls_certificate_verify_peers3</function> function.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
An established TLS session can be used for sending and
|
||||||
|
receiving data, as in <xref
|
||||||
|
linkend="ex-Defensive_Coding-TLS-GNUTLS-Use"/>.
|
||||||
|
</para>
|
||||||
|
<example id="ex-Defensive_Coding-TLS-GNUTLS-Use">
|
||||||
|
<title>Using a GNUTLS session</title>
|
||||||
|
<xi:include href="snippets/TLS-GNUTLS-Use.xml"
|
||||||
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</example>
|
||||||
|
<para>
|
||||||
|
In order to shut down a connection in an orderly manner, you
|
||||||
|
should call the <function>gnutls_bye</function> function.
|
||||||
|
Finally, the session object can be deallocated using
|
||||||
|
<function>gnutls_deinit</function> (see <xref
|
||||||
|
linkend="ex-Defensive_Coding-TLS-GNUTLS-Disconnect"/>).
|
||||||
|
</para>
|
||||||
|
<example id="ex-Defensive_Coding-TLS-GNUTLS-Disconnect">
|
||||||
|
<title>Using a GNUTLS session</title>
|
||||||
|
<xi:include href="snippets/TLS-GNUTLS-Disconnect.xml"
|
||||||
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</example>
|
||||||
|
</section>
|
||||||
|
<section id="sect-Defensive_Coding-TLS-Client-OpenJDK">
|
||||||
|
<title>Implementing TLS Clients With OpenJDK</title>
|
||||||
|
<para>
|
||||||
|
The examples below use the following cryptographic-related
|
||||||
|
classes:
|
||||||
|
</para>
|
||||||
|
<informalexample>
|
||||||
|
<xi:include href="snippets/TLS-Client-OpenJDK-Import.xml"
|
||||||
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</informalexample>
|
||||||
|
<para>
|
||||||
|
If compatibility with OpenJDK 6 is required, it is necessary
|
||||||
|
to use the internal class
|
||||||
|
<literal>sun.security.util.HostnameChecker</literal>. (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
|
||||||
|
<function>setEndpointIdentificationAlgorithm</function> method
|
||||||
|
was added to the
|
||||||
|
<literal>javax.net.ssl.SSLParameters</literal> class,
|
||||||
|
providing an official way to implement host name checking.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
TLS connections are established using an
|
||||||
|
<literal>SSLContext</literal> instance. With a properly
|
||||||
|
configured OpenJDK installation, the
|
||||||
|
<literal>SunJSSE</literal> provider uses the system-wide set
|
||||||
|
of trusted root certificate authorities, so no further
|
||||||
|
configuration is necessary. For backwards compatibility with
|
||||||
|
OpenJDK 6, the <literal>TLSv1</literal> provider has to
|
||||||
|
be supported as a fall-back option. This is shown in <xref
|
||||||
|
linkend="ex-Defensive_Coding-TLS-Client-OpenJDK-Context"/>.
|
||||||
|
</para>
|
||||||
|
<example id="ex-Defensive_Coding-TLS-Client-OpenJDK-Context">
|
||||||
|
<title>Setting up an <literal>SSLContext</literal> for OpenJDK TLS
|
||||||
|
clients</title>
|
||||||
|
<xi:include href="snippets/TLS-Client-OpenJDK-Context.xml"
|
||||||
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</example>
|
||||||
|
<para>
|
||||||
|
In addition to the context, a TLS parameter object will be
|
||||||
|
needed which adjusts the cipher suites and protocols (<xref
|
||||||
|
linkend="ex-Defensive_Coding-TLS-OpenJDK-Parameters"/>). Like
|
||||||
|
the context, these parameters can be reused for multiple TLS
|
||||||
|
connections.
|
||||||
|
</para>
|
||||||
|
<example id="ex-Defensive_Coding-TLS-OpenJDK-Parameters">
|
||||||
|
<title>Setting up <literal>SSLParameters</literal> for TLS use
|
||||||
|
with OpenJDK</title>
|
||||||
|
<xi:include href="snippets/TLS-OpenJDK-Parameters.xml"
|
||||||
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</example>
|
||||||
|
<para>
|
||||||
|
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:
|
||||||
|
</para>
|
||||||
|
<informalexample>
|
||||||
|
<xi:include href="snippets/TLS-Client-OpenJDK-Hostname.xml"
|
||||||
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</informalexample>
|
||||||
|
<para>
|
||||||
|
All application protocols can use the
|
||||||
|
<literal>"HTTPS"</literal> algorithm. (The algorithms have
|
||||||
|
minor differences with regard to wildcard handling, which
|
||||||
|
should not matter in practice.)
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
<xref linkend="ex-Defensive_Coding-TLS-Client-OpenJDK-Connect"/>
|
||||||
|
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
|
||||||
|
<literal>params</literal>. (After this point, changes to
|
||||||
|
<literal>params</literal> will not affect this TLS socket.)
|
||||||
|
As mentioned initially, host name checking requires using an
|
||||||
|
internal API on OpenJDK 6.
|
||||||
|
</para>
|
||||||
|
<example id="ex-Defensive_Coding-TLS-Client-OpenJDK-Connect">
|
||||||
|
<title>Establishing a TLS connection with OpenJDK</title>
|
||||||
|
<xi:include href="snippets/TLS-Client-OpenJDK-Connect.xml"
|
||||||
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</example>
|
||||||
|
<para>
|
||||||
|
Starting with OpenJDK 7, the last lines can be omitted,
|
||||||
|
provided that host name verification has been enabled by
|
||||||
|
calling the
|
||||||
|
<function>setEndpointIdentificationAlgorithm</function> method
|
||||||
|
on the <literal>params</literal> object (before it was applied
|
||||||
|
to the socket).
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The TLS socket can be used as a regular socket, as shown in
|
||||||
|
<xref linkend="ex-Defensive_Coding-TLS-Client-OpenJDK-Use"/>.
|
||||||
|
</para>
|
||||||
|
<example id="ex-Defensive_Coding-TLS-Client-OpenJDK-Use">
|
||||||
|
<title>Using a TLS client socket in OpenJDK</title>
|
||||||
|
<xi:include href="snippets/TLS-Client-OpenJDK-Use.xml"
|
||||||
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</example>
|
||||||
|
<section>
|
||||||
|
<title>Overriding server certificate validation with OpenJDK 6</title>
|
||||||
|
<para>
|
||||||
|
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
|
||||||
|
<literal>TrustManager</literal> and
|
||||||
|
<literal>SSLContext</literal> objects have to be used for
|
||||||
|
different servers.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
In the trust manager shown in <xref
|
||||||
|
linkend="ex-Defensive_Coding-TLS-Client-MyTrustManager"/>,
|
||||||
|
the server certificate is identified by its SHA-256 hash.
|
||||||
|
</para>
|
||||||
|
<example id="ex-Defensive_Coding-TLS-Client-MyTrustManager">
|
||||||
|
<title>A customer trust manager for OpenJDK TLS clients</title>
|
||||||
|
<xi:include href="snippets/TLS-Client-OpenJDK-MyTrustManager.xml"
|
||||||
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</example>
|
||||||
|
<para>
|
||||||
|
This trust manager has to be passed to the
|
||||||
|
<literal>init</literal> method of the
|
||||||
|
<literal>SSLContext</literal> object, as show in <xref
|
||||||
|
linkend="ex-Defensive_Coding-TLS-Client-Context_For_Cert"/>.
|
||||||
|
</para>
|
||||||
|
<example id="ex-Defensive_Coding-TLS-Client-Context_For_Cert">
|
||||||
|
<title>Using a custom TLS trust manager with OpenJDK</title>
|
||||||
|
<xi:include href="snippets/TLS-Client-OpenJDK-Context_For_Cert.xml"
|
||||||
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</example>
|
||||||
|
<para>
|
||||||
|
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.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
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
|
||||||
|
<literal>javax.net.ssl.X509ExtendedTrustManager</literal>
|
||||||
|
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.
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
</section>
|
||||||
|
<section id="sect-Defensive_Coding-TLS-Client-NSS">
|
||||||
|
<title>Implementing TLS Clients With NSS</title>
|
||||||
|
<para>
|
||||||
|
The following code shows how to implement a simple TLS client
|
||||||
|
using NSS. Note that the error handling needs replacing
|
||||||
|
before production use.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Using NSS needs several header files, as shown in
|
||||||
|
<xref linkend="ex-Defensive_Coding-TLS-NSS-Includes"/>.
|
||||||
|
</para>
|
||||||
|
<example id="ex-Defensive_Coding-TLS-NSS-Includes">
|
||||||
|
<title>Include files for NSS</title>
|
||||||
|
<xi:include href="snippets/TLS-NSS-Includes.xml"
|
||||||
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</example>
|
||||||
|
<para>
|
||||||
|
Initializing the NSS library is a complex task (<xref
|
||||||
|
linkend="ex-Defensive_Coding-TLS-NSS-Init"/>). It is not
|
||||||
|
thread-safe. By default, the library is in export mode, and
|
||||||
|
all strong ciphers are disabled. Therefore, after creating
|
||||||
|
the <literal>NSSInitCContext</literal> 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
|
||||||
|
<function>NSS_SetDomesticPolicy</function> 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.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The simplest way to configured the trusted root certificates
|
||||||
|
involves loading the <filename>libnssckbi.so</filename> NSS
|
||||||
|
module with a call to the
|
||||||
|
<function>SECMOD_LoadUserModule</function> function. The root
|
||||||
|
certificates are compiled into this module. (The PEM module
|
||||||
|
for NSS, <filename>libnsspem.so</filename>, offers a way to
|
||||||
|
load trusted CA certificates from a file.)
|
||||||
|
</para>
|
||||||
|
<example id="ex-Defensive_Coding-TLS-NSS-Init">
|
||||||
|
<title>Initializing the NSS library</title>
|
||||||
|
<xi:include href="snippets/TLS-NSS-Init.xml"
|
||||||
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</example>
|
||||||
|
<para>
|
||||||
|
Some of the effects of the initialization can be reverted with
|
||||||
|
the following function calls:
|
||||||
|
</para>
|
||||||
|
<informalexample id="ex-Defensive_Coding-TLS-NSS-Close">
|
||||||
|
<xi:include href="snippets/TLS-NSS-Close.xml"
|
||||||
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</informalexample>
|
||||||
|
<para>
|
||||||
|
After NSS has been initialized, the TLS connection can be
|
||||||
|
created (<xref
|
||||||
|
linkend="ex-Defensive_Coding-TLS-Client-NSS-Connect"/>). The
|
||||||
|
internal <function>PR_ImportTCPSocket</function> function is
|
||||||
|
used to turn the POSIX file descriptor
|
||||||
|
<literal>sockfd</literal> 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 <emphasis>model</emphasis> descriptor, which is
|
||||||
|
configured with the desired set of protocols and ciphers.
|
||||||
|
(The <literal>good_ciphers</literal> variable is part of <xref
|
||||||
|
linkend="ex-Defensive_Coding-TLS-NSS-Init"/>.) 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.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The call to <function>SSL_BadCertHook</function> can be
|
||||||
|
omitted if no mechanism to override certificate verification
|
||||||
|
is needed. The <literal>bad_certificate</literal> function
|
||||||
|
must check both the host name specified for the connection and
|
||||||
|
the certificate before granting the override.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Triggering the actual handshake requires three function calls,
|
||||||
|
<function>SSL_ResetHandshake</function>,
|
||||||
|
<function>SSL_SetURL</function>, and
|
||||||
|
<function>SSL_ForceHandshake</function>. (If
|
||||||
|
<function>SSL_ResetHandshake</function> is omitted,
|
||||||
|
<function>SSL_ForceHandshake</function> will succeed, but the
|
||||||
|
data will not be encrypted.) During the handshake, the
|
||||||
|
certificate is verified and matched against the host name.
|
||||||
|
</para>
|
||||||
|
<example id="ex-Defensive_Coding-TLS-Client-NSS-Connect">
|
||||||
|
<title>Creating a TLS connection with NSS</title>
|
||||||
|
<xi:include href="snippets/TLS-Client-NSS-Connect.xml"
|
||||||
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</example>
|
||||||
|
<para>
|
||||||
|
After the connection has been established, <xref
|
||||||
|
linkend="ex-Defensive_Coding-TLS-NSS-Use"/> shows how to use
|
||||||
|
the NSPR descriptor to communicate with the server.
|
||||||
|
</para>
|
||||||
|
<example id="ex-Defensive_Coding-TLS-NSS-Use">
|
||||||
|
<title>Using NSS for sending and receiving data</title>
|
||||||
|
<xi:include href="snippets/TLS-NSS-Use.xml"
|
||||||
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</example>
|
||||||
|
<para>
|
||||||
|
<xref linkend="ex-Defensive_Coding-TLS-Client-NSS-Close"/>
|
||||||
|
shows how to close the connection.
|
||||||
|
</para>
|
||||||
|
<example id="ex-Defensive_Coding-TLS-Client-NSS-Close">
|
||||||
|
<title>Closing NSS client connections</title>
|
||||||
|
<xi:include href="snippets/TLS-Client-NSS-Close.xml"
|
||||||
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</example>
|
||||||
|
</section>
|
||||||
|
<section id="sect-Defensive_Coding-TLS-Client-Python">
|
||||||
|
<title>Implementing TLS Clients With Python</title>
|
||||||
|
<para>
|
||||||
|
The Python distribution provides a TLS implementation in the
|
||||||
|
<literal>ssl</literal> 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 <xref
|
||||||
|
linkend="sect-Defensive_Coding-TLS-OpenSSL"/>.
|
||||||
|
</para>
|
||||||
|
<important>
|
||||||
|
<para>
|
||||||
|
Currently, most Python function which accept
|
||||||
|
<literal>https://</literal> URLs or otherwise implement
|
||||||
|
HTTPS support do not perform certificate validation at all.
|
||||||
|
(For example, this is true for the <literal>httplib</literal>
|
||||||
|
and <literal>xmlrpclib</literal> modules.) If you use
|
||||||
|
HTTPS, you should not use the built-in HTTP clients. The
|
||||||
|
<literal>Curl</literal> class in the <literal>curl</literal>
|
||||||
|
module, as provided by the <literal>python-pycurl</literal>
|
||||||
|
package implements proper certificate validation.
|
||||||
|
</para>
|
||||||
|
</important>
|
||||||
|
<para>
|
||||||
|
The <literal>ssl</literal> module currently does not perform
|
||||||
|
host name checking on the server certificate. <xref
|
||||||
|
linkend="ex-Defensive_Coding-TLS-Client-Python-check_host_name"/>
|
||||||
|
shows how to implement certificate matching, using the parsed
|
||||||
|
certificate returned by <function>getpeercert</function>.
|
||||||
|
</para>
|
||||||
|
<example id="ex-Defensive_Coding-TLS-Client-Python-check_host_name">
|
||||||
|
<title>Implementing TLS host name checking Python (without
|
||||||
|
wildcard support)</title>
|
||||||
|
<xi:include href="snippets/TLS-Client-Python-check_host_name.xml"
|
||||||
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</example>
|
||||||
|
<para>
|
||||||
|
To turn a regular, connected TCP socket into a TLS-enabled
|
||||||
|
socket, use the <function>ssl.wrap_socket</function> function.
|
||||||
|
The function call in <xref
|
||||||
|
linkend="ex-Defensive_Coding-TLS-Client-Python-Connect"/>
|
||||||
|
provides additional arguments to override questionable
|
||||||
|
defaults in OpenSSL and in the Python module.
|
||||||
|
</para>
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<literal>ciphers="HIGH:-aNULL:-eNULL:-PSK:RC4-SHA:RC4-MD5"</literal>
|
||||||
|
selects relatively strong cipher suites with
|
||||||
|
certificate-based authentication. (The call to
|
||||||
|
<function>check_host_name</function> function provides
|
||||||
|
additional protection against anonymous cipher suites.)
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<literal>ssl_version=ssl.PROTOCOL_TLSv1</literal> disables
|
||||||
|
SSL 2.0 support. By default, the <literal>ssl</literal>
|
||||||
|
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.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<literal>cert_reqs=ssl.CERT_REQUIRED</literal> turns on
|
||||||
|
certificate validation.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<literal>ca_certs='/etc/ssl/certs/ca-bundle.crt'</literal>
|
||||||
|
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
|
||||||
|
<literal>ssl</literal> module.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
<para>
|
||||||
|
The <literal>ssl</literal> module (and OpenSSL) perform
|
||||||
|
certificate validation, but the certificate must be compared
|
||||||
|
manually against the host name, by calling the
|
||||||
|
<function>check_host_name</function> defined above.
|
||||||
|
</para>
|
||||||
|
<example id="ex-Defensive_Coding-TLS-Client-Python-Connect">
|
||||||
|
<title>Establishing a TLS client connection with Python</title>
|
||||||
|
<xi:include href="snippets/TLS-Client-Python-Connect.xml"
|
||||||
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</example>
|
||||||
|
<para>
|
||||||
|
After the connection has been established, the TLS socket can
|
||||||
|
be used like a regular socket:
|
||||||
|
</para>
|
||||||
|
<informalexample>
|
||||||
|
<xi:include href="snippets/TLS-Python-Use.xml"
|
||||||
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</informalexample>
|
||||||
|
<para>
|
||||||
|
Closing the TLS socket is straightforward as well:
|
||||||
|
</para>
|
||||||
|
<informalexample>
|
||||||
|
<xi:include href="snippets/TLS-Python-Close.xml"
|
||||||
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||||
|
</informalexample>
|
||||||
|
</section>
|
||||||
|
</section>
|
||||||
|
</chapter>
|
4
defensive-coding/en-US/Features/schemas.xml
Normal file
4
defensive-coding/en-US/Features/schemas.xml
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<locatingRules xmlns="http://thaiopensource.com/ns/locating-rules/1.0">
|
||||||
|
<include rules="../../schemas.xml"/>
|
||||||
|
</locatingRules>
|
|
@ -0,0 +1,50 @@
|
||||||
|
<?xml version='1.0' encoding='utf-8' ?>
|
||||||
|
<!DOCTYPE programlisting PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
|
||||||
|
]>
|
||||||
|
<!-- Automatically generated file. Do not edit. -->
|
||||||
|
<programlisting language="C">
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
</programlisting>
|
|
@ -0,0 +1,29 @@
|
||||||
|
<?xml version='1.0' encoding='utf-8' ?>
|
||||||
|
<!DOCTYPE programlisting PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
|
||||||
|
]>
|
||||||
|
<!-- Automatically generated file. Do not edit. -->
|
||||||
|
<programlisting language="C">
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
</programlisting>
|
|
@ -0,0 +1,30 @@
|
||||||
|
<?xml version='1.0' encoding='utf-8' ?>
|
||||||
|
<!DOCTYPE programlisting PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
|
||||||
|
]>
|
||||||
|
<!-- Automatically generated file. Do not edit. -->
|
||||||
|
<programlisting language="C">
|
||||||
|
// 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);
|
||||||
|
</programlisting>
|
|
@ -0,0 +1,42 @@
|
||||||
|
<?xml version='1.0' encoding='utf-8' ?>
|
||||||
|
<!DOCTYPE programlisting PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
|
||||||
|
]>
|
||||||
|
<!-- Automatically generated file. Do not edit. -->
|
||||||
|
<programlisting language="C">
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</programlisting>
|
|
@ -0,0 +1,15 @@
|
||||||
|
<?xml version='1.0' encoding='utf-8' ?>
|
||||||
|
<!DOCTYPE programlisting PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
|
||||||
|
]>
|
||||||
|
<!-- Automatically generated file. Do not edit. -->
|
||||||
|
<programlisting language="C">
|
||||||
|
// 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);
|
||||||
|
</programlisting>
|
|
@ -0,0 +1,106 @@
|
||||||
|
<?xml version='1.0' encoding='utf-8' ?>
|
||||||
|
<!DOCTYPE programlisting PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
|
||||||
|
]>
|
||||||
|
<!-- Automatically generated file. Do not edit. -->
|
||||||
|
<programlisting language="C">
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
</programlisting>
|
|
@ -0,0 +1,26 @@
|
||||||
|
<?xml version='1.0' encoding='utf-8' ?>
|
||||||
|
<!DOCTYPE programlisting PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
|
||||||
|
]>
|
||||||
|
<!-- Automatically generated file. Do not edit. -->
|
||||||
|
<programlisting language="Java">
|
||||||
|
// 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);
|
||||||
|
</programlisting>
|
|
@ -0,0 +1,26 @@
|
||||||
|
<?xml version='1.0' encoding='utf-8' ?>
|
||||||
|
<!DOCTYPE programlisting PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
|
||||||
|
]>
|
||||||
|
<!-- Automatically generated file. Do not edit. -->
|
||||||
|
<programlisting language="Java">
|
||||||
|
// 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);
|
||||||
|
</programlisting>
|
|
@ -0,0 +1,22 @@
|
||||||
|
<?xml version='1.0' encoding='utf-8' ?>
|
||||||
|
<!DOCTYPE programlisting PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
|
||||||
|
]>
|
||||||
|
<!-- Automatically generated file. Do not edit. -->
|
||||||
|
<programlisting language="Java">
|
||||||
|
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);
|
||||||
|
</programlisting>
|
|
@ -0,0 +1,7 @@
|
||||||
|
<?xml version='1.0' encoding='utf-8' ?>
|
||||||
|
<!DOCTYPE programlisting PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
|
||||||
|
]>
|
||||||
|
<!-- Automatically generated file. Do not edit. -->
|
||||||
|
<programlisting language="Java">
|
||||||
|
params.setEndpointIdentificationAlgorithm("HTTPS");
|
||||||
|
</programlisting>
|
|
@ -0,0 +1,18 @@
|
||||||
|
<?xml version='1.0' encoding='utf-8' ?>
|
||||||
|
<!DOCTYPE programlisting PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
|
||||||
|
]>
|
||||||
|
<!-- Automatically generated file. Do not edit. -->
|
||||||
|
<programlisting language="Java">
|
||||||
|
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;
|
||||||
|
</programlisting>
|
|
@ -0,0 +1,38 @@
|
||||||
|
<?xml version='1.0' encoding='utf-8' ?>
|
||||||
|
<!DOCTYPE programlisting PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
|
||||||
|
]>
|
||||||
|
<!-- Automatically generated file. Do not edit. -->
|
||||||
|
<programlisting language="Java">
|
||||||
|
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];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</programlisting>
|
|
@ -0,0 +1,11 @@
|
||||||
|
<?xml version='1.0' encoding='utf-8' ?>
|
||||||
|
<!DOCTYPE programlisting PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
|
||||||
|
]>
|
||||||
|
<!-- Automatically generated file. Do not edit. -->
|
||||||
|
<programlisting language="Java">
|
||||||
|
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);
|
||||||
|
</programlisting>
|
|
@ -0,0 +1,71 @@
|
||||||
|
<?xml version='1.0' encoding='utf-8' ?>
|
||||||
|
<!DOCTYPE programlisting PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
|
||||||
|
]>
|
||||||
|
<!-- Automatically generated file. Do not edit. -->
|
||||||
|
<programlisting language="C">
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
</programlisting>
|
|
@ -0,0 +1,55 @@
|
||||||
|
<?xml version='1.0' encoding='utf-8' ?>
|
||||||
|
<!DOCTYPE programlisting PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
|
||||||
|
]>
|
||||||
|
<!-- Automatically generated file. Do not edit. -->
|
||||||
|
<programlisting language="C">
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
</programlisting>
|
|
@ -0,0 +1,15 @@
|
||||||
|
<?xml version='1.0' encoding='utf-8' ?>
|
||||||
|
<!DOCTYPE programlisting PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
|
||||||
|
]>
|
||||||
|
<!-- Automatically generated file. Do not edit. -->
|
||||||
|
<programlisting language="C">
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
</programlisting>
|
|
@ -0,0 +1,13 @@
|
||||||
|
<?xml version='1.0' encoding='utf-8' ?>
|
||||||
|
<!DOCTYPE programlisting PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
|
||||||
|
]>
|
||||||
|
<!-- Automatically generated file. Do not edit. -->
|
||||||
|
<programlisting language="C">
|
||||||
|
// 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();
|
||||||
|
</programlisting>
|
|
@ -0,0 +1,14 @@
|
||||||
|
<?xml version='1.0' encoding='utf-8' ?>
|
||||||
|
<!DOCTYPE programlisting PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
|
||||||
|
]>
|
||||||
|
<!-- Automatically generated file. Do not edit. -->
|
||||||
|
<programlisting language="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")
|
||||||
|
</programlisting>
|
|
@ -0,0 +1,29 @@
|
||||||
|
<?xml version='1.0' encoding='utf-8' ?>
|
||||||
|
<!DOCTYPE programlisting PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
|
||||||
|
]>
|
||||||
|
<!-- Automatically generated file. Do not edit. -->
|
||||||
|
<programlisting language="Python">
|
||||||
|
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
|
||||||
|
</programlisting>
|
|
@ -0,0 +1,7 @@
|
||||||
|
<?xml version='1.0' encoding='utf-8' ?>
|
||||||
|
<!DOCTYPE programlisting PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
|
||||||
|
]>
|
||||||
|
<!-- Automatically generated file. Do not edit. -->
|
||||||
|
<programlisting language="C">
|
||||||
|
gnutls_certificate_free_credentials(cred);
|
||||||
|
</programlisting>
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue