Adding Defensive Coding book

This commit is contained in:
Eric Christensen 2013-03-11 18:11:16 -04:00
parent 3623943843
commit 1fbfdb89d1
754 changed files with 60855 additions and 0 deletions

33
defensive-coding/Makefile Normal file
View 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
View 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.

View 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

View 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

View 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.

View 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 .................................
# ......................................................................

File diff suppressed because it is too large Load diff

View 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 .................................
# ......................................................................

File diff suppressed because it is too large Load diff

View 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 ..........................................
# ......................................................................

View 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 ............................
# ......................................................................

View 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.

View 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 .................................
# ......................................................................

File diff suppressed because it is too large Load diff

View 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 .................................
# ......................................................................

File diff suppressed because it is too large Load diff

View 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 ..........................................
# ......................................................................

View 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 ............................
# ......................................................................

View 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

View 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

View file

@ -0,0 +1,5 @@
K 13
svn:mime-type
V 8
text/xml
END

View file

@ -0,0 +1,5 @@
K 13
svn:mime-type
V 8
text/xml
END

View 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>

View file

@ -0,0 +1,2 @@
<!ENTITY YEAR "2012">
<!ENTITY HOLDER "Red Hat, Inc">

View file

@ -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>

View 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>

View 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>

View 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

View file

@ -0,0 +1,6 @@
K 10
svn:ignore
V 9
snippets
END

View 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

View file

@ -0,0 +1,5 @@
K 13
svn:mime-type
V 8
text/xml
END

View file

@ -0,0 +1,5 @@
K 13
svn:mime-type
V 8
text/xml
END

View file

@ -0,0 +1,5 @@
K 13
svn:mime-type
V 8
text/xml
END

View file

@ -0,0 +1,5 @@
K 13
svn:mime-type
V 8
text/xml
END

View file

@ -0,0 +1,5 @@
K 13
svn:mime-type
V 8
text/xml
END

View 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>

View 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>

View 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 &gt; C</literal> for some
constant <literal>C</literal> determined at compile time. The
other expression, <literal>b &amp;&amp; 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>

View 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>

View file

@ -0,0 +1,4 @@
<?xml version="1.0"?>
<locatingRules xmlns="http://thaiopensource.com/ns/locating-rules/1.0">
<include rules="../../schemas.xml"/>
</locatingRules>

View 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>

View 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>

View 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 &gt; C</literal> for some
constant <literal>C</literal> determined at compile time. The
other expression, <literal>b &amp;&amp; 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>

View 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>

View file

@ -0,0 +1,4 @@
<?xml version="1.0"?>
<locatingRules xmlns="http://thaiopensource.com/ns/locating-rules/1.0">
<include rules="../../schemas.xml"/>
</locatingRules>

View 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 &#60; 0 || b &#60; 0) {
return -1;
}
// The compiler can optimize away the following if statement.
if (result &#60; 0) {
report_overflow();
}
return result;
}
</programlisting>

View 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 &#38;&#38; a &#62; ((unsigned)-1) / b) {
report_overflow();
}
return a * b;
}
</programlisting>

View 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 &#62; (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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View 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

View file

@ -0,0 +1,6 @@
K 10
svn:ignore
V 9
snippets
END

View 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

View file

@ -0,0 +1,5 @@
K 13
svn:mime-type
V 8
text/xml
END

View file

@ -0,0 +1,5 @@
K 13
svn:mime-type
V 8
text/xml
END

View file

@ -0,0 +1,5 @@
K 13
svn:mime-type
V 8
text/xml
END

View file

@ -0,0 +1,5 @@
K 13
svn:mime-type
V 8
text/xml
END

View 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>

View 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 &amp;&amp;
n &gt; (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>&lt;tr1/*&gt;</literal> header files. This includes
<literal>std::tr1::shared_ptr</literal> (from
<literal>&lt;tr1/memory&gt;</literal>) and
<literal>std::tr1::function</literal> (from
<literal>&lt;tr1/functional&gt;</literal>). For other C++11
features, the Boost C++ library contains replacements.
</para>
</section>
</section>

View 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>

View file

@ -0,0 +1,4 @@
<?xml version="1.0"?>
<locatingRules xmlns="http://thaiopensource.com/ns/locating-rules/1.0">
<include rules="../../schemas.xml"/>
</locatingRules>

View 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>

View 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 &amp;&amp;
n &gt; (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>&lt;tr1/*&gt;</literal> header files. This includes
<literal>std::tr1::shared_ptr</literal> (from
<literal>&lt;tr1/memory&gt;</literal>) and
<literal>std::tr1::function</literal> (from
<literal>&lt;tr1/functional&gt;</literal>). For other C++11
features, the Boost C++ library contains replacements.
</para>
</section>
</section>

View 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>

View file

@ -0,0 +1,4 @@
<?xml version="1.0"?>
<locatingRules xmlns="http://thaiopensource.com/ns/locating-rules/1.0">
<include rules="../../schemas.xml"/>
</locatingRules>

View file

@ -0,0 +1,2 @@
<!ENTITY YEAR "2012">
<!ENTITY HOLDER "Red Hat, Inc">

View 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>

View 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

View file

@ -0,0 +1,6 @@
K 10
svn:ignore
V 9
snippets
END

View 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

View file

@ -0,0 +1,5 @@
K 13
svn:mime-type
V 8
text/xml
END

View file

@ -0,0 +1,5 @@
K 13
svn:mime-type
V 8
text/xml
END

View file

@ -0,0 +1,5 @@
K 13
svn:mime-type
V 8
text/xml
END

View 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>

View 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&nbsp;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&nbsp;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>

View file

@ -0,0 +1,4 @@
<?xml version="1.0"?>
<locatingRules xmlns="http://thaiopensource.com/ns/locating-rules/1.0">
<include rules="../../schemas.xml"/>
</locatingRules>

View 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>

View 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&nbsp;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&nbsp;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>

View file

@ -0,0 +1,4 @@
<?xml version="1.0"?>
<locatingRules xmlns="http://thaiopensource.com/ns/locating-rules/1.0">
<include rules="../../schemas.xml"/>
</locatingRules>

View file

@ -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(&#38;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", &#38;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>

View file

@ -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 (&#38;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 &#60; 0) {
fprintf(stderr, "error: gnutls_certificate_set_x509_trust_files(%s): %s\n",
ca_bundle, gnutls_strerror(ret));
exit(1);
}
</programlisting>

View file

@ -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(&#38;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 &#38;&#38; !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>

View file

@ -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, &#38;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, &#38;status);
if (ret != GNUTLS_E_SUCCESS) {
fprintf(stderr, "error: gnutls_certificate_verify_peers2: %s\n",
gnutls_strerror(ret));
exit(1);
}
if (status != 0 &#38;&#38; !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, &#38;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>

View file

@ -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>

View file

@ -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 &#60; SSL_GetNumImplementedCiphers(); i++) {
if (ciphers[i] != SSL_RSA_WITH_RC4_128_SHA
&#38;&#38; 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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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 &#60; 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>

View file

@ -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 &#38;&#38; !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
&#38;&#38; !certificate_host_name_override(peercert, host)) {
fprintf(stderr, "SSL certificate does not match host name\n");
exit(1);
}
X509_free(peercert);
</programlisting>

View file

@ -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)) &#60; 0) {
ssl_print_error_and_exit(ssl, "SSL_write", ret);
}
char buf[4096];
ret = SSL_read(ssl, buf, sizeof(buf));
if (ret &#60; 0) {
ssl_print_error_and_exit(ssl, "SSL_read", ret);
}
</programlisting>

View file

@ -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>

View 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="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>

View file

@ -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>

View file

@ -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