Converted to AsciiBinder

This required moving files around in the repository and shifting
from a master.adoc structure to _topic_map.yml, etc.

README and Makefile modified slightly to reflect new build process
This commit is contained in:
Brian (bex) Exelbierd 2018-02-08 13:08:40 +01:00
parent 161b3a786e
commit 2e8934be40
186 changed files with 30936 additions and 372 deletions

View file

@ -1,13 +0,0 @@
:experimental:
[[chap-Defensive_Coding-C]]
=== The C Programming Language
include::C-Language.adoc[]
include::C-Libc.adoc[]
include::C-Allocators.adoc[]
include::C-Other.adoc[]

View file

@ -1,9 +0,0 @@
:experimental:
[[chap-Defensive_Coding-CXX]]
=== The C++ Programming Language
include::CXX-Language.adoc[]
include::CXX-Std.adoc[]

View file

@ -1,8 +1,6 @@
:experimental:
include::../entities.adoc[]
Copyright {YEAR} {HOLDER}.
Copyright {YEAR} {HOLDER}.
The text of and illustrations in this document are licensed by Red Hat under a Creative Commons AttributionShare Alike 3.0 Unported license ("CC-BY-SA"). An explanation of CC-BY-SA is available at link:++http://creativecommons.org/licenses/by-sa/3.0/++[]. The original authors of this document, and Red Hat, designate the Fedora Project as the "Attribution Party" for purposes of CC-BY-SA. In accordance with CC-BY-SA, if you distribute this document or an adaptation of it, you must provide the URL for the original version.
@ -20,4 +18,4 @@ For guidelines on the permitted uses of the Fedora trademarks, refer to link:++h
*MySQL* is a registered trademark of MySQL AB in the United States, the European Union and other countries.
All other trademarks are the property of their respective owners.
All other trademarks are the property of their respective owners.

View file

@ -1,11 +0,0 @@
:experimental:
[[chap-Defensive_Coding-Java]]
=== The Java Programming Language
include::Java-Language.adoc[]
include::Java-LowLevel.adoc[]
include::Java-SecurityManager.adoc[]

View file

@ -2,7 +2,7 @@
:experimental:
[[appe-Defensive_Coding-Revision_History]]
== Revision History
= Revision History
`1.5`:: Fri Dec 1 2017, Mirek Jahoda (mjahoda@redhat.com)
@ -57,4 +57,4 @@
`0-1`:: Thu Mar 7 2013, Eric Christensen (sparks@redhat.com)
* Initial publication.
* Initial publication.

View file

@ -2,10 +2,10 @@
:experimental:
[[chap-Defensive_Coding-Authentication]]
=== Authentication and Authorization
= Authentication and Authorization
[[sect-Defensive_Coding-Authentication-Server]]
==== Authenticating Servers
== Authenticating Servers
When connecting to a server, a client has to make sure that it
is actually talking to the server it expects. There are two
@ -47,7 +47,7 @@ crashing the real server by exploiting a denial-of-service
vulnerability.
[[sect-Defensive_Coding-Authentication-Host_based]]
==== Host-based Authentication
== Host-based Authentication
Host-based authentication uses access control lists (ACLs) to
accept or deny requests from clients. This authentication
@ -92,7 +92,7 @@ universally correct way to deal with this ambiguity. The
behavior of the ACL implementation should be documented.
[[sect-Defensive_Coding-Authentication-UNIX_Domain]]
==== UNIX Domain Socket Authentication
== UNIX Domain Socket Authentication
UNIX domain sockets (with address family
`AF_UNIX` or `AF_LOCAL`) are
@ -127,7 +127,7 @@ information from `/proc/PID/status` is prone
to race conditions and insecure.
[[sect-Defensive_Coding-Authentication-Netlink]]
==== `AF_NETLINK` Authentication of Origin
== `AF_NETLINK` Authentication of Origin
Netlink messages are used as a high-performance data transfer
mechanism between the kernel and the user space. Traditionally,
@ -148,4 +148,4 @@ address will be non-zero in such cases.
Applications should not use `AF_NETLINK`
sockets as an IPC mechanism among processes, but prefer UNIX
domain sockets for this tasks.
domain sockets for this tasks.

View file

@ -2,7 +2,7 @@
:experimental:
[[chap-Defensive_Coding-HSM]]
=== Hardware Security Modules and Smart Cards
= Hardware Security Modules and Smart Cards
Hardware Security Modules (HSMs) are specialized hardware intended
to protect private keys on server systems. They store internally
@ -61,7 +61,7 @@ modules or smart cards. The wrapper PKCS#11 APIs provided by NSS, GnuTLS and
engine_pkcs11 (OpenSSL) handle the reinitialization after fork requirement transparently.
[[sect-Defensive_Coding-HSM-OpenSSL]]
==== OpenSSL HSM Support
== OpenSSL HSM Support
OpenSSL does not have native support for PKCS#11. It can
provide PKCS#11 support through the OpenSC's project
@ -81,13 +81,13 @@ and its usage to sign data.
[source,c]
----
include::snippets/Features-HSM-OpenSSL.adoc[]
include::en-US/snippets/Features-HSM-OpenSSL.adoc[]
----
====
[[sect-Defensive_Coding-HSM-GNUTLS]]
==== GnuTLS HSM Support
== GnuTLS HSM Support
GnuTLS supports PKCS#11 natively. Most of the API functions
accepting certificate files, can also accept PKCS#11 URLs, thus
@ -104,7 +104,7 @@ and its usage to sign data.
[source,c]
----
include::snippets/Features-HSM-GNUTLS.adoc[]
include::en-US/snippets/Features-HSM-GNUTLS.adoc[]
----
====
@ -119,13 +119,13 @@ An example PIN callback function is shown below.
[source,c]
----
include::snippets/Features-HSM-GNUTLS-PIN.adoc[]
include::en-US/snippets/Features-HSM-GNUTLS-PIN.adoc[]
----
====
[[sect-Defensive_Coding-HSM-NSS]]
==== NSS HSM Support
== NSS HSM Support
NSS supports PKCS#11 natively. In fact all NSS crypto operations,
including built-in operations, go through PKCS #11 modules. NSS provides
@ -145,7 +145,7 @@ The following example demonstrates a typical NSS application for signing.
[source,c]
----
include::snippets/Features-HSM-NSS.adoc[]
include::en-US/snippets/Features-HSM-NSS.adoc[]
----
====
@ -164,7 +164,7 @@ $ modutil -list -dbdir .
$ certutil -L -h ${token_name} -d .
# pass the cert to your signing program
$ NSS_Sign_Example "${token_name}:${cert_name}"
----
[[ex-Defensive_Coding-HSM-NSS-PIN]]
@ -173,7 +173,7 @@ $ NSS_Sign_Example "${token_name}:${cert_name}"
[source,c]
----
include::snippets/Features-HSM-NSS-PIN.adoc[]
include::en-US/snippets/Features-HSM-NSS-PIN.adoc[]
----
====

View file

@ -1,9 +1,9 @@
:experimental:
include::entities.adoc[]
include::en-US/entities.adoc[]
[[chap-Defensive_Coding-TLS]]
=== Transport Layer Security (TLS)
= Transport Layer Security (TLS)
Transport Layer Security (TLS, formerly Secure Sockets
Layer/SSL) is the recommended way to to protect integrity and
@ -24,7 +24,7 @@ library' documentation.
* link:++https://docs.oracle.com/javase/8/docs/technotes/guides/security/jsse/JSSERefGuide.html++[OpenJDK documentation]
[[sect-Defensive_Coding-TLS-Pitfalls]]
==== Common Pitfalls
== Common Pitfalls
TLS implementations are difficult to use, and most of them lack
a clean API design. The following sections contain
@ -62,7 +62,7 @@ duration of the handshake), or use the Linux-specific
[source,c]
----
include::snippets/Features-TLS-Nagle.adoc[]
include::en-US/snippets/Features-TLS-Nagle.adoc[]
----
====
@ -94,7 +94,7 @@ cannot be used across `fork` function
calls (see <<sect-Defensive_Coding-Tasks-Processes-Fork-Parallel>>).
[[sect-Defensive_Coding-TLS-OpenSSL]]
===== OpenSSL Pitfalls
=== OpenSSL Pitfalls
Some OpenSSL function use *tri-state return
values*. Correct error checking is extremely
@ -133,7 +133,7 @@ due to a connection teardown by the other end).
[source,c]
----
include::snippets/Features-TLS-OpenSSL-Errors.adoc[]
include::en-US/snippets/Features-TLS-OpenSSL-Errors.adoc[]
----
====
@ -193,14 +193,14 @@ increase the part of the code base which has to undergo
security certification.
[[sect-Defensive_Coding-TLS-Pitfalls-GnuTLS]]
===== GnuTLS Pitfalls
=== GnuTLS Pitfalls
Older versions of GnuTLS had several peculiarities described
in previous versions of this guide; as of GnuTLS 3.3.10, these
issues are no longer applicable.
[[sect-Defensive_Coding-TLS-Pitfalls-OpenJDK]]
===== OpenJDK Pitfalls
=== OpenJDK Pitfalls
The Java cryptographic framework is highly modular. As a
result, when you request an object implementing some
@ -224,7 +224,7 @@ can block, waiting for more bits to become available in
`/dev/random`.
[[sect-Defensive_Coding-TLS-Pitfalls-NSS]]
===== NSS Pitfalls
=== NSS Pitfalls
NSS was not designed to be used by other libraries which can
be linked into applications without modifying them. There is
@ -242,7 +242,7 @@ initialized. This behavior is required by the PKCS#11 API
specification.
[[sect-Defensive_Coding-TLS-Client]]
==== TLS Clients
== TLS Clients
Secure use of TLS in a client generally involves all of the
following steps. (Individual instructions for specific TLS
@ -295,7 +295,7 @@ client. These aspects are not yet covered.
====
===== Implementation TLS Clients With OpenSSL
=== Implementation TLS Clients With OpenSSL
In the following code, the error handling is only exploratory.
Proper error handling is required for production use,
@ -309,7 +309,7 @@ The OpenSSL library needs explicit initialization (see <<ex-Defensive_Coding-TLS
[source,c]
----
include::snippets/Features-TLS-Client-OpenSSL-Init.adoc[]
include::en-US/snippets/Features-TLS-Client-OpenSSL-Init.adoc[]
----
@ -332,7 +332,7 @@ be cumbersome.
[source,c]
----
include::snippets/Features-TLS-Client-OpenSSL-CTX.adoc[]
include::en-US/snippets/Features-TLS-Client-OpenSSL-CTX.adoc[]
----
====
@ -380,7 +380,7 @@ name.
[source,c]
----
include::snippets/Features-TLS-Client-OpenSSL-Connect.adoc[]
include::en-US/snippets/Features-TLS-Client-OpenSSL-Connect.adoc[]
----
====
@ -397,7 +397,7 @@ transport, using `BIO_set_ssl`.
[source,c]
----
include::snippets/Features-TLS-Client-OpenSSL-Connection-Use.adoc[]
include::en-US/snippets/Features-TLS-Client-OpenSSL-Connection-Use.adoc[]
----
====
@ -418,7 +418,7 @@ socket after the connection object has been freed.
[source,c]
----
include::snippets/Features-TLS-OpenSSL-Connection-Close.adoc[]
include::en-US/snippets/Features-TLS-OpenSSL-Connection-Close.adoc[]
----
====
@ -433,13 +433,13 @@ because no further TLS connections will be established.
[source,c]
----
include::snippets/Features-TLS-OpenSSL-Context-Close.adoc[]
include::en-US/snippets/Features-TLS-OpenSSL-Context-Close.adoc[]
----
====
[[sect-Defensive_Coding-TLS-Client-GnuTLS]]
===== Implementation TLS Clients With GnuTLS
=== Implementation TLS Clients With GnuTLS
This section describes how to implement a TLS client with full
certificate validation (but without certificate revocation
@ -456,7 +456,7 @@ CAs (<<ex-Defensive_Coding-TLS-Client-GNUTLS-Credentials>>).
[source,c]
----
include::snippets/Features-TLS-Client-GNUTLS-Credentials.adoc[]
include::en-US/snippets/Features-TLS-Client-GNUTLS-Credentials.adoc[]
----
====
@ -466,7 +466,7 @@ object should be freed:
[source,c]
----
include::snippets/Features-TLS-GNUTLS-Credentials-Close.adoc[]
include::en-US/snippets/Features-TLS-GNUTLS-Credentials-Close.adoc[]
----
During its lifetime, the credentials object can be used to
@ -486,7 +486,7 @@ This is shown in <<ex-Defensive_Coding-TLS-Client-GNUTLS-Connect>>.
[source,c]
----
include::snippets/Features-TLS-Client-GNUTLS-Connect.adoc[]
include::en-US/snippets/Features-TLS-Client-GNUTLS-Connect.adoc[]
----
====
@ -505,7 +505,7 @@ can be omitted if the functionality is not needed.
[source,c]
----
include::snippets/Features-TLS-Client-GNUTLS-Verify.adoc[]
include::en-US/snippets/Features-TLS-Client-GNUTLS-Verify.adoc[]
----
====
@ -519,7 +519,7 @@ receiving data, as in <<ex-Defensive_Coding-TLS-GNUTLS-Use>>.
[source,c]
----
include::snippets/Features-TLS-GNUTLS-Use.adoc[]
include::en-US/snippets/Features-TLS-GNUTLS-Use.adoc[]
----
====
@ -535,20 +535,20 @@ Finally, the session object can be deallocated using
[source,c]
----
include::snippets/Features-TLS-GNUTLS-Disconnect.adoc[]
include::en-US/snippets/Features-TLS-GNUTLS-Disconnect.adoc[]
----
====
[[sect-Defensive_Coding-TLS-Client-OpenJDK]]
===== Implementing TLS Clients With OpenJDK
=== Implementing TLS Clients With OpenJDK
The examples below use the following cryptographic-related
classes:
[source,java]
----
include::snippets/Features-TLS-Client-OpenJDK-Import.adoc[]
include::en-US/snippets/Features-TLS-Client-OpenJDK-Import.adoc[]
----
@ -579,7 +579,7 @@ be supported as a fall-back option. This is shown in <<ex-Defensive_Coding-TLS-C
[source,java]
----
include::snippets/Features-TLS-Client-OpenJDK-Context.adoc[]
include::en-US/snippets/Features-TLS-Client-OpenJDK-Context.adoc[]
----
====
@ -595,7 +595,7 @@ connections.
[source,java]
----
include::snippets/Features-TLS-OpenJDK-Parameters.adoc[]
include::en-US/snippets/Features-TLS-OpenJDK-Parameters.adoc[]
----
====
@ -606,7 +606,7 @@ separately, and this is only supported by OpenJDK 7 and later:
[source,java]
----
include::snippets/Features-TLS-Client-OpenJDK-Hostname.adoc[]
include::en-US/snippets/Features-TLS-Client-OpenJDK-Hostname.adoc[]
----
All application protocols can use the
@ -629,7 +629,7 @@ internal API on OpenJDK 6.
[source,java]
----
include::snippets/Features-TLS-Client-OpenJDK-Connect.adoc[]
include::en-US/snippets/Features-TLS-Client-OpenJDK-Connect.adoc[]
----
====
@ -650,12 +650,12 @@ The TLS socket can be used as a regular socket, as shown in
[source,java]
----
include::snippets/Features-TLS-Client-OpenJDK-Use.adoc[]
include::en-US/snippets/Features-TLS-Client-OpenJDK-Use.adoc[]
----
====
====== Overriding server certificate validation with OpenJDK 6
==== Overriding server certificate validation with OpenJDK 6
Overriding certificate validation requires a custom trust
manager. With OpenJDK 6, the trust manager lacks
@ -675,7 +675,7 @@ the server certificate is identified by its SHA-256 hash.
[source,java]
----
include::snippets/Features-TLS-Client-OpenJDK-MyTrustManager.adoc[]
include::en-US/snippets/Features-TLS-Client-OpenJDK-MyTrustManager.adoc[]
----
====
@ -690,7 +690,7 @@ This trust manager has to be passed to the
[source,java]
----
include::snippets/Features-TLS-Client-OpenJDK-Context_For_Cert.adoc[]
include::en-US/snippets/Features-TLS-Client-OpenJDK-Context_For_Cert.adoc[]
----
====
@ -716,7 +716,7 @@ manager object can be used for multiple servers because the
server address is available to the trust manager.
[[sect-Defensive_Coding-TLS-Client-NSS]]
===== Implementing TLS Clients With NSS
=== Implementing TLS Clients With NSS
The following code shows how to implement a simple TLS client
using NSS. These instructions apply to NSS version 3.14 and
@ -735,7 +735,7 @@ Using NSS needs several header files, as shown in
[source,c]
----
include::snippets/Features-TLS-NSS-Includes.adoc[]
include::en-US/snippets/Features-TLS-NSS-Includes.adoc[]
----
====
@ -761,7 +761,7 @@ load trusted CA certificates from a file.)
[source,c]
----
include::snippets/Features-TLS-NSS-Init.adoc[]
include::en-US/snippets/Features-TLS-NSS-Init.adoc[]
----
@ -772,7 +772,7 @@ the following function calls:
[source,c]
----
include::snippets/Features-TLS-NSS-Close.adoc[]
include::en-US/snippets/Features-TLS-NSS-Close.adoc[]
----
After NSS has been initialized, the TLS connection can be
@ -808,7 +808,7 @@ certificate is verified and matched against the host name.
[source,c]
----
include::snippets/Features-TLS-Client-NSS-Connect.adoc[]
include::en-US/snippets/Features-TLS-Client-NSS-Connect.adoc[]
----
====
@ -822,7 +822,7 @@ the NSPR descriptor to communicate with the server.
[source,c]
----
include::snippets/Features-TLS-NSS-Use.adoc[]
include::en-US/snippets/Features-TLS-NSS-Use.adoc[]
----
====
@ -836,14 +836,14 @@ shows how to close the connection.
[source,c]
----
include::snippets/Features-TLS-Client-NSS-Close.adoc[]
include::en-US/snippets/Features-TLS-Client-NSS-Close.adoc[]
----
====
[[sect-Defensive_Coding-TLS-Client-Python]]
===== Implementing TLS Clients With Python
=== Implementing TLS Clients With Python
The Python distribution provides a TLS implementation in the
`ssl` module (actually a wrapper around
@ -877,7 +877,7 @@ certificate returned by `getpeercert`.
[source,python]
----
include::snippets/Features-TLS-Client-Python-check_host_name.adoc[]
include::en-US/snippets/Features-TLS-Client-Python-check_host_name.adoc[]
----
====
@ -923,7 +923,7 @@ manually against the host name, by calling the
[source,python]
----
include::snippets/Features-TLS-Client-Python-Connect.adoc[]
include::en-US/snippets/Features-TLS-Client-Python-Connect.adoc[]
----
====
@ -933,12 +933,12 @@ be used like a regular socket:
[source,python]
----
include::snippets/Features-TLS-Python-Use.adoc[]
include::en-US/snippets/Features-TLS-Python-Use.adoc[]
----
Closing the TLS socket is straightforward as well:
[source,python]
----
include::snippets/Features-TLS-Python-Close.adoc[]
include::en-US/snippets/Features-TLS-Python-Close.adoc[]
----

View file

Before

Width:  |  Height:  |  Size: 7.6 KiB

After

Width:  |  Height:  |  Size: 7.6 KiB

Before After
Before After

View file

@ -1,5 +1,5 @@
:experimental:
include::en-US/entities.adoc[]
A Guide to Improving Software Security
@ -12,7 +12,7 @@ programming languages and libraries, and focuses on
concrete recommendations.
--
image:Common_Content/images/title_logo.svg[]
include::Common_Content/Legal_Notice.adoc[]
image::title_logo.svg[]
include::en-US/Common_Content/Legal_Notice.adoc[]
include::Author_Group.adoc[]
include::en-US/Author_Group.adoc[]

View file

@ -1,54 +0,0 @@
:doctype: book
:toc: left
:toclevels: 3
:source-highlighter: pygments
:pygments-style: friendly
:pygments-linenums-mode: inline
= Defensive Coding Guide
include::Book_Info.adoc[]
== Programming Languages
include::C.adoc[]
include::CXX.adoc[]
include::Java.adoc[]
include::Python.adoc[]
include::Shell.adoc[]
include::Go.adoc[]
include::Vala.adoc[]
== Specific Programming Tasks
include::Tasks-Library_Design.adoc[]
include::Tasks-Descriptors.adoc[]
include::Tasks-File_System.adoc[]
include::Tasks-Temporary_Files.adoc[]
include::Tasks-Processes.adoc[]
include::Tasks-Serialization.adoc[]
include::Tasks-Cryptography.adoc[]
include::Tasks-Packaging.adoc[]
== Implementing Security Features
include::Features-Authentication.adoc[]
include::Features-TLS.adoc[]
include::Features-HSM.adoc[]
include::Revision_History.adoc[]

View file

@ -2,9 +2,9 @@
:experimental:
[[sect-Defensive_Coding-C-Allocators]]
==== Memory Allocators
== Memory Allocators
===== `malloc` and Related Functions
=== `malloc` and Related Functions
The C library interfaces for memory allocation are provided by
`malloc`, `free` and
@ -27,7 +27,7 @@ realloc(ptr, size);` is wrong because the memory
pointed to by `ptr` leaks in case of an error.
[[sect-Defensive_Coding-C-Use-After-Free]]
====== Use-after-free errors
==== Use-after-free errors
After `free`, the pointer is invalid.
Further pointer dereferences are not allowed (and are usually
@ -43,7 +43,7 @@ compiler may assume that a comparison between the old and new
pointer will always return false, so it is impossible to detect
movement this way.
====== Handling Memory Allocation Errors
==== Handling Memory Allocation Errors
Recovering from out-of-memory errors is often difficult or even
impossible. In these cases, `malloc` and
@ -60,7 +60,7 @@ terminate the process. See
for related memory allocation concerns.
[[sect-Defensive_Coding-C-Allocators-alloca]]
===== `alloca` and Other Forms of Stack-based Allocation
=== `alloca` and Other Forms of Stack-based Allocation
Allocation on the stack is risky because stack overflow checking
is implicit. There is a guard page at the end of the memory
@ -106,7 +106,7 @@ function, check if `malloc` had been called,
and free the buffer as needed.
[[sect-Defensive_Coding-C-Allocators-Arrays]]
===== Array Allocation
=== Array Allocation
When allocating arrays, it is important to check for overflows.
The `calloc` function performs such checks.
@ -119,7 +119,7 @@ greater than `((size_t) -1) / sizeof(T)`. See
<<sect-Defensive_Coding-C-Arithmetic>>.
[[sect-Defensive_Coding-C-Allocators-Custom]]
===== Custom Memory Allocators
=== Custom Memory Allocators
Custom memory allocates come in two forms: replacements for
`malloc`, and completely different interfaces
@ -146,7 +146,7 @@ fragmentation. But often, utilization of individual pools
is poor, and external fragmentation increases the overall
memory usage.
===== Conservative Garbage Collection
=== Conservative Garbage Collection
Garbage collection can be an alternative to explicit memory
management using `malloc` and

View file

@ -2,13 +2,13 @@
:experimental:
[[sect-Defensive_Coding-C-Language]]
==== The Core Language
== The Core Language
C provides no memory safety. Most recommendations in this section
deal with this aspect of the language.
[[sect-Defensive_Coding-C-Undefined]]
===== Undefined Behavior
=== Undefined Behavior
Some C constructs are defined to be undefined by the C standard.
This does not only mean that the standard does not describe
@ -28,7 +28,7 @@ Common sources of undefined behavior are:
* overflow in signed integer arithmetic
[[sect-Defensive_Coding-C-Pointers]]
===== Recommendations for Pointers and Array Handling
=== Recommendations for Pointers and Array Handling
Always keep track of the size of the array you are working with.
Often, code is more obviously correct when you keep a pointer
@ -56,7 +56,7 @@ The cast silences a compiler warning;
[source,c]
----
include::snippets/C-Pointers-remaining.adoc[]
include::../snippets/C-Pointers-remaining.adoc[]
----
@ -74,7 +74,7 @@ because the expression on the left can overflow or wrap around
no longer reflects the number of bytes to be processed.
[[sect-Defensive_Coding-C-Arithmetic]]
===== Recommendations for Integer Arithmetic
=== Recommendations for Integer Arithmetic
Overflow in signed integer arithmetic is undefined. This means
that it is not possible to check for overflow after it happened,
@ -86,7 +86,7 @@ see <<ex-Defensive_Coding-C-Arithmetic-bad>>.
[source,c]
----
include::snippets/C-Arithmetic-add.adoc[]
include::../snippets/C-Arithmetic-add.adoc[]
----
@ -113,7 +113,7 @@ additions have to be checked in this way.
[source,c]
----
include::snippets/C-Arithmetic-add_unsigned.adoc[]
include::../snippets/C-Arithmetic-add_unsigned.adoc[]
----
====
@ -129,7 +129,7 @@ see <<ex-Defensive_Coding-C-Arithmetic-mult>>.
[source,c]
----
include::snippets/C-Arithmetic-mult.adoc[]
include::../snippets/C-Arithmetic-mult.adoc[]
----
====
@ -169,7 +169,7 @@ semantics for integer arithmetic, including defined behavior on
integer overflow.
[[sect-Defensive_Coding-C-Globals]]
===== Global Variables
=== Global Variables
Global variables should be avoided because they usually lead to
thread safety hazards. In any case, they should be declared
@ -189,7 +189,7 @@ after the `*`, and not before it.
[source,c]
----
include::snippets/C-Globals-String_Array.adoc[]
include::../snippets/C-Globals-String_Array.adoc[]
----

View file

@ -1,10 +1,10 @@
:experimental:
include::entities.adoc[]
include::en-US/entities.adoc[]
[[sect-Defensive_Coding-C-Libc]]
==== The C Standard Library
== The C Standard Library
Parts of the C standard library (and the UNIX and GNU extensions)
are difficult to use, so you should avoid them.
@ -15,7 +15,7 @@ buffers using `malloc` which your code must
deallocate explicitly using `free`.
[[sect-Defensive_Coding-C-Absolutely-Banned]]
===== Absolutely Banned Interfaces
=== Absolutely Banned Interfaces
The functions listed below must not be used because they are
almost always unsafe. Use the indicated replacements instead.
@ -58,7 +58,7 @@ statvfs` (limit not actually enforced by the kernel,
see `_PC_NAME_MAX` above)
[[sect-Defensive_Coding-C-Avoid]]
===== Functions to Avoid
=== Functions to Avoid
The following string manipulation functions can be used securely
in principle, but their use should be avoided because they are
@ -109,7 +109,7 @@ explicit `envp` argument in process creation
(see <<sect-Defensive_Coding-Tasks-Processes-environ>>)
[[sect-Defensive_Coding-C-String-Functions-Length]]
===== String Functions with Explicit Length Arguments
=== String Functions with Explicit Length Arguments
The C run-time library provides string manipulation functions
which not just look for NUL characters for string termination,
@ -118,7 +118,7 @@ However, these functions evolved over a long period of time, and
the lengths mean different things depending on the function.
[[sect-Defensive_Coding-C-Libc-snprintf]]
====== `snprintf`
==== `snprintf`
The `snprintf` function provides a way to
construct a string in a statically-sized buffer. (If the buffer
@ -127,7 +127,7 @@ size is allocated on the heap, consider use
[source,c]
----
include::snippets/C-String-Functions-snprintf.adoc[]
include::../snippets/C-String-Functions-snprintf.adoc[]
----
@ -157,7 +157,7 @@ invariant. After the loop, the result string is in the
[source,c]
----
include::snippets/C-String-Functions-snprintf-incremental.adoc[]
include::../snippets/C-String-Functions-snprintf-incremental.adoc[]
----
@ -176,7 +176,7 @@ Note that it is not permitted to use the same buffer both as
the destination and as a source argument.
[[sect-Defensive_Coding-C-Libc-vsnprintf]]
====== `vsnprintf` and Format Strings
==== `vsnprintf` and Format Strings
If you use `vsnprintf` (or
`vasprintf` or even
@ -192,14 +192,14 @@ function (see <<ex-Defensive_Coding-C-String-Functions-format-Attribute>>).
[source,c]
----
include::snippets/C-String-Functions-format.adoc[]
include::../snippets/C-String-Functions-format.adoc[]
----
====
[[sect-Defensive_Coding-C-Libc-strncpy]]
====== `strncpy`
==== `strncpy`
The `strncpy` function does not ensure that
the target buffer is null-terminated. A common idiom for
@ -207,7 +207,7 @@ ensuring NUL termination is:
[source,c]
----
include::snippets/C-String-Functions-strncpy.adoc[]
include::../snippets/C-String-Functions-strncpy.adoc[]
----
@ -216,12 +216,12 @@ function for this purpose:
[source,c]
----
include::snippets/C-String-Functions-strncat-as-strncpy.adoc[]
include::../snippets/C-String-Functions-strncat-as-strncpy.adoc[]
----
[[sect-Defensive_Coding-C-Libc-strncat]]
====== `strncat`
==== `strncat`
The length argument of the `strncat`
function specifies the maximum number of characters copied
@ -239,7 +239,7 @@ approach similar to <<ex-Defensive_Coding-C-String-Functions-snprintf-incrementa
[source,c]
----
include::snippets/C-String-Functions-strncat-emulation.adoc[]
include::../snippets/C-String-Functions-strncat-emulation.adoc[]
----
@ -249,7 +249,7 @@ string:
[source,c]
----
include::snippets/C-String-Functions-strncat-merged.adoc[]
include::../snippets/C-String-Functions-strncat-merged.adoc[]
----
@ -262,7 +262,7 @@ It is not possible to use format strings like
you use separate buffers. `snprintf` does
not support overlapping source and target strings.
====== `strlcpy` and `strlcat`
==== `strlcpy` and `strlcat`
Some systems support `strlcpy` and
`strlcat` functions which behave this way,
@ -275,12 +275,12 @@ related to the `snprintf` return value.
To emulate `strlcat`, use the approach
described in <<sect-Defensive_Coding-C-Libc-strncat>>.
====== ISO C11 Annex K *pass:attributes[{blank}]`_s` functions
==== ISO C11 Annex K *pass:attributes[{blank}]`_s` functions
ISO C11 adds another set of length-checking functions, but GNU
libc currently does not implement them.
====== Other `strn*` and `stpn*` functions
==== Other `strn*` and `stpn*` functions
GNU libc contains additional functions with different variants
of length checking. Consult the documentation before using

View file

@ -2,10 +2,10 @@
:experimental:
[[sect-Defensive_Coding-C-Other]]
==== Other C-related Topics
== Other C-related Topics
[[sect-Defensive_Coding-C-Wrapper-Functions]]
===== Wrapper Functions
=== Wrapper Functions
Some libraries provide wrappers for standard library functions.
Common cases include allocation functions such as
@ -50,4 +50,4 @@ For other attributes (such as `malloc`),
careful analysis and comparison with the compiler documentation
is required to check if propagating the attribute is
appropriate. Incorrectly applied attributes can result in
undesired behavioral changes in the compiled code.
undesired behavioral changes in the compiled code.

View file

@ -0,0 +1,13 @@
:experimental:
[[chap-Defensive_Coding-C]]
= The C Programming Language
include::en-US/programming-languages/C-Language.adoc[]
include::en-US/programming-languages/C-Libc.adoc[]
include::en-US/programming-languages/C-Allocators.adoc[]
include::en-US/programming-languages/C-Other.adoc[]

View file

@ -2,12 +2,12 @@
:experimental:
[[sect-Defensive_Coding-CXX-Language]]
==== The Core Language
== The Core Language
C++ includes a large subset of the C language. As far as the C
subset is used, the recommendations in <<chap-Defensive_Coding-C>> apply.
===== Array Allocation with `operator new[]`
=== Array Allocation with `operator new[]`
For very large values of `n`, an expression
like `new T[n]` can return a pointer to a heap
@ -43,7 +43,7 @@ untrusted data.
See <<sect-Defensive_Coding-C-Allocators-Arrays>>
for array allocation advice for C-style memory allocation.
===== Overloading
=== Overloading
Do not overload functions with versions that have different
security characteristics. For instance, do not implement a
@ -51,7 +51,7 @@ function `strcat` which works on
`std::string` arguments. Similarly, do not name
methods after such functions.
===== ABI compatibility and preparing for security updates
=== ABI compatibility and preparing for security updates
A stable binary interface (ABI) is vastly preferred for security
updates. Without a stable ABI, all reverse dependencies need
@ -81,7 +81,7 @@ Compatibility Issues With {cpp}]
pointer-to-implementation idiom).
[[sect-Defensive_Coding-CXX-Language-CXX11]]
===== {cpp}0X and {cpp}11 Support
=== {cpp}0X and {cpp}11 Support
GCC offers different language compatibility modes:

View file

@ -2,19 +2,19 @@
:experimental:
[[sect-Defensive_Coding-CXX-Std]]
==== The C++ Standard Library
== The C++ Standard Library
The C++ standard library includes most of its C counterpart
by reference, see <<sect-Defensive_Coding-C-Libc>>.
[[sect-Defensive_Coding-CXX-Std-Functions]]
===== Functions That Are Difficult to Use
=== Functions That Are Difficult to Use
This section collects functions and function templates which are
part of the standard library and are difficult to use.
[[sect-Defensive_Coding-CXX-Std-Functions-Unpaired_Iterators]]
====== Unpaired Iterators
==== Unpaired Iterators
Functions which use output operators or iterators which do not
come in pairs (denoting ranges) cannot perform iterator range
@ -69,7 +69,7 @@ read beyond the end of the input range if the caller is not careful:
* `std::mismatch`
[[sect-Defensive_Coding-CXX-Std-String]]
===== String Handling with `std::string`
=== String Handling with `std::string`
The `std::string` class provides a convenient
way to handle strings. Unlike C strings,
@ -142,7 +142,7 @@ does not depend on sharing of the internal character array
object anymore.
[[sect-Defensive_Coding-CXX-Std-Subscript]]
===== Containers and `operator[]`
=== Containers and `operator[]`
Many sequence containers similar to `std::vector`
provide both `operator[](size_type)` and a
@ -169,7 +169,7 @@ defined; it returns an arbitrary pointer, but not necessarily
the NULL pointer.
[[sect-Defensive_Coding-CXX-Std-Iterators]]
===== Iterators
=== Iterators
Iterators do not perform any bounds checking. Therefore, all
functions that work on iterators should accept them in pairs,

View file

@ -0,0 +1,8 @@
:experimental:
[[chap-Defensive_Coding-CXX]]
= The C++ Programming Language
include::en-US/programming-languages/CXX-Language.adoc[]
include::en-US/programming-languages/CXX-Std.adoc[]

View file

@ -2,12 +2,12 @@
:experimental:
[[chap-Defensive_Coding-Go]]
=== The Go Programming Language
= The Go Programming Language
This chapter contains language-specific recommendations for Go.
[[chap-Defensive_Coding-Go-Memory_Safety]]
==== Memory Safety
== Memory Safety
Go provides memory safety, but only if the program is not executed
in parallel (that is, `GOMAXPROCS` is not larger than
@ -28,7 +28,7 @@ finalizers are executed concurrently, potentially interleaved with
the rest of the program.
[[chap-Defensive_Coding-Go-Error_Handling]]
==== Error Handling
== Error Handling
Only a few common operations (such as pointer dereference, integer
division, array subscripting) trigger exceptions in Go, called
@ -53,7 +53,7 @@ details.
[source,go]
----
include::snippets/Go-Error_Handling-Regular.adoc[]
include::../snippets/Go-Error_Handling-Regular.adoc[]
----
@ -73,14 +73,14 @@ returning both data and an error at the same time.
[source,go]
----
include::snippets/Go-Error_Handling-IO.adoc[]
include::../snippets/Go-Error_Handling-IO.adoc[]
----
====
[[chap-Defensive_Coding-Go-Garbage_Collector]]
==== Garbage Collector
== Garbage Collector
Older Go releases (before Go 1.3) use a conservative garbage
collector without blacklisting. This means that data blobs can
@ -92,7 +92,7 @@ may be possible to trigger it deliberately—it is unlikely to occur
spontaneously.
[[chap-Defensive_Coding-Go-Marshaling]]
==== Marshaling and Unmarshaling
== Marshaling and Unmarshaling
Several packages in the `encoding` hierarchy
provide support for serialization and deserialization. The usual

View file

@ -2,7 +2,7 @@
:experimental:
[[sect-Defensive_Coding-Java-Language]]
==== The Core Language
== The Core Language
Implementations of the Java programming language provide strong
memory safety, even in the presence of data races in concurrent
@ -11,7 +11,7 @@ from occurring, unless certain low-level features are used; see
<<sect-Defensive_Coding-Java-LowLevel>>.
[[sect-Defensive_Coding-Java-Language-ReadArray]]
===== Increasing Robustness when Reading Arrays
=== Increasing Robustness when Reading Arrays
External data formats often include arrays, and the data is
stored as an integer indicating the number of array elements,
@ -31,7 +31,7 @@ data, implementing an exponential growth policy. See the
[source,java]
----
include::snippets/Java-Language-ReadArray.adoc[]
include::../snippets/Java-Language-ReadArray.adoc[]
----
@ -42,7 +42,7 @@ default constructor and do not specify a size hint. You can
simply add the elements to the collection as you read them.
[[sect-Defensive_Coding-Java-Language-Resources]]
===== Resource Management
=== Resource Management
Unlike C++, Java does not offer destructors which can deallocate
resources in a predictable fashion. All resource management has
@ -62,7 +62,7 @@ possible and should not throw any exceptions.
[source,java]
----
include::snippets/Java-Finally.adoc[]
include::../snippets/Java-Finally.adoc[]
----
@ -87,7 +87,7 @@ used instead. The Java compiler will automatically insert the
[source,java]
----
include::snippets/Java-TryWithResource.adoc[]
include::../snippets/Java-TryWithResource.adoc[]
----
@ -109,7 +109,7 @@ unchecked) exceptions, but this should not be a reason to ignore
any actual error conditions.
[[sect-Defensive_Coding-Java-Language-Finalizers]]
===== Finalizers
=== Finalizers
Finalizers can be used a last-resort approach to free resources
which would otherwise leak. Finalization is unpredictable,
@ -157,7 +157,7 @@ implemented by overriding the `finalize()`
method, and to custom finalization using reference queues.
[[sect-Defensive_Coding-Java-Language-Exceptions]]
===== Recovering from Exceptions and Errors
=== Recovering from Exceptions and Errors
Java exceptions come in three kinds, all ultimately deriving
from `java.lang.Throwable`:
@ -202,7 +202,7 @@ to predict and can happen at any point and reflect that
something went wrong beyond all expectations.
[[sect-Defensive_Coding-Java-Language-Exceptions-Errors]]
====== The Difficulty of Catching Errors
==== The Difficulty of Catching Errors
Errors (that is, exceptions which do not (indirectly) derive
from `java.lang.Exception`), have the

View file

@ -2,10 +2,10 @@
:experimental:
[[sect-Defensive_Coding-Java-LowLevel]]
==== Low-level Features of the Virtual Machine
== Low-level Features of the Virtual Machine
[[sect-Defensive_Coding-Java-Reflection]]
===== Reflection and Private Parts
=== Reflection and Private Parts
The `setAccessible(boolean)` method of the
`java.lang.reflect.AccessibleObject` class
@ -24,7 +24,7 @@ not happen because all the language-defined checks still apply.)
This feature should be avoided if possible.
[[sect-Defensive_Coding-Java-JNI]]
===== Java Native Interface (JNI)
=== Java Native Interface (JNI)
The Java Native Interface allows calling from Java code
functions specifically written for this purpose, usually in C or
@ -75,7 +75,7 @@ beginning of the array.
[source,java]
----
include::snippets/Java-JNI-Pointers.adoc[]
include::../snippets/Java-JNI-Pointers.adoc[]
----
@ -133,7 +133,7 @@ is defined, but in C/C++ it is not (for the
`jint` and `jlong` types).
[[sect-Defensive_Coding-Java-MiscUnsafe]]
===== `sun.misc.Unsafe`
=== `sun.misc.Unsafe`
The `sun.misc.Unsafe` class is unportable and
contains many functions explicitly designed to break Java memory

View file

@ -2,7 +2,7 @@
:experimental:
[[sect-Defensive_Coding-Java-SecurityManager]]
==== Interacting with the Security Manager
== Interacting with the Security Manager
The Java platform is largely implemented in the Java language
itself. Therefore, within the same JVM, code runs which is part
@ -38,7 +38,7 @@ default (including many classes which are part of the OpenJDK
implementation).
[[sect-Defensive_Coding-Java-SecurityManager-Compatible]]
===== Security Manager Compatibility
=== Security Manager Compatibility
A lot of code can run without any additional permissions at all,
with little changes. The following guidelines should help to
@ -61,7 +61,7 @@ untrusted code (hopefully in a restricted and secure manner),
see <<sect-Defensive_Coding-Java-SecurityManager-Privileged>>.
[[sect-Defensive_Coding-Java-SecurityManager-Activate]]
===== Activating the Security Manager
=== Activating the Security Manager
The usual command to launch a Java application,
[command]`java`, does not activate the security manager.
@ -87,7 +87,7 @@ option).
----
grant {
permission java.security.AllPermission;
permission java.security.AllPermission;
};
----
@ -99,7 +99,7 @@ active, and explicit requests to drop privileges will be
honored.
[[sect-Defensive_Coding-Java-SecurityManager-Unprivileged]]
===== Reducing Trust in Code
=== Reducing Trust in Code
The <<ex-Defensive_Coding-Java-SecurityManager-Unprivileged>> example
shows how to run a piece code of with reduced privileges.
@ -110,7 +110,7 @@ shows how to run a piece code of with reduced privileges.
[source,java]
----
include::snippets/Java-SecurityManager-Unprivileged.adoc[]
include::../snippets/Java-SecurityManager-Unprivileged.adoc[]
----
@ -123,7 +123,7 @@ on all files in the current directory) can be used:
[source,java]
----
include::snippets/Java-SecurityManager-CurrentDirectory.adoc[]
include::../snippets/Java-SecurityManager-CurrentDirectory.adoc[]
----
@ -159,7 +159,7 @@ Unfortunately, this affects the virtual machine as a whole, so
it is not possible to do this from a library.
[[sect-Defensive_Coding-Java-SecurityManager-Privileged]]
===== Re-gaining Privileges
=== Re-gaining Privileges
Ordinarily, when trusted code is called from untrusted code, it
loses its privileges (because of the untrusted stack frames
@ -208,7 +208,7 @@ shows how to request additional privileges.
[source,java]
----
include::snippets/Java-SecurityManager-Privileged.adoc[]
include::../snippets/Java-SecurityManager-Privileged.adoc[]
----
@ -249,7 +249,7 @@ invocation out of the privileged code section, of course.)
[source,java]
----
include::snippets/Java-SecurityManager-Callback.adoc[]
include::../snippets/Java-SecurityManager-Callback.adoc[]
----

View file

@ -0,0 +1,11 @@
:experimental:
[[chap-Defensive_Coding-Java]]
= The Java Programming Language
include::en-US/programming-languages/Java-Language.adoc[]
include::en-US/programming-languages/Java-LowLevel.adoc[]
include::en-US/programming-languages/Java-SecurityManager.adoc[]

View file

@ -2,7 +2,7 @@
:experimental:
[[chap-Defensive_Coding-Python]]
=== The Python Programming Language
= The Python Programming Language
Python provides memory safety by default, so low-level security
vulnerabilities are rare and typically needs fixing the Python
@ -19,14 +19,14 @@ particular <<sect-Defensive_Coding-Tasks-Serialization-Library>>
* <<sect-Defensive_Coding-Tasks-Cryptography-Randomness>>
==== Dangerous Standard Library Features
== Dangerous Standard Library Features
Some areas of the standard library, notably the
`ctypes` module, do not provide memory safety
guarantees comparable to the rest of Python. If such
functionality is used, the advice in <<sect-Defensive_Coding-C-Language>> should be followed.
==== Run-time Compilation and Code Generation
== Run-time Compilation and Code Generation
The following Python functions and statements related to code
execution should be avoided:
@ -44,8 +44,8 @@ If you need to parse integers or floating point values, use the
functions instead of `eval`. Sandboxing
untrusted Python code does not work reliably.
==== Sandboxing
== Sandboxing
The `rexec` Python module cannot safely sandbox
untrusted code and should not be used. The standard CPython
implementation is not suitable for sandboxing.
implementation is not suitable for sandboxing.

View file

@ -1,9 +1,9 @@
:experimental:
include::entities.adoc[]
include::en-US/entities.adoc[]
[[chap-Defensive_Coding-Shell]]
=== Shell Programming and [application]*bash*
= Shell Programming and [application]*bash*
This chapter contains advice about shell programming, specifically
in [application]*bash*. Most of the advice will apply
@ -12,7 +12,7 @@ integer or array variables have been implemented there as well, with
comparable syntax.
[[sect-Defensive_Coding-Shell-Alternatives]]
==== Consider Alternatives
== Consider Alternatives
Once a shell script is so complex that advice in this chapter
applies, it is time to step back and consider the question: Is
@ -25,7 +25,7 @@ offers richer data structures, with less arcane syntax and more
consistent behavior.
[[sect-Defensive_Coding-Shell-Language]]
==== Shell Language Features
== Shell Language Features
The following sections cover subtleties concerning the shell
programming languages. They have been written with the
@ -38,7 +38,7 @@ implementations, so they now have to be considered part of the shell
programming language.
[[sect-Defensive_Coding-Shell-Parameter_Expansion]]
===== Parameter Expansion
=== Parameter Expansion
The mechanism by which named shell variables and parameters are
expanded is called *parameter expansion*. The
@ -53,7 +53,7 @@ double quotation marks `"`pass:attributes[{blank}]…pass:attributes[{blank}]`"`
----
external-program "$arg1" "$arg2"
----
If the double quotation marks are omitted, the value of the
@ -69,7 +69,7 @@ trigger arithmetic evaluation, which can result in code execution.
See <<sect-Defensive_Coding-Shell-Arithmetic>>.
[[sect-Defensive_Coding-Shell-Double_Expansion]]
===== Double Expansion
=== Double Expansion
*Double expansion* occurs when, during the
expansion of a shell variable, not just the variable is expanded,
@ -95,7 +95,7 @@ The following sections give examples of places where implicit
double expansion occurs.
[[sect-Defensive_Coding-Shell-Arithmetic]]
====== Arithmetic Evaluation
==== Arithmetic Evaluation
*Arithmetic evaluation* is a process by which
the shell computes the integer value of an expression specified
@ -179,7 +179,7 @@ If it is impossible to avoid shell arithmetic on untrusted
inputs, refer to <<sect-Defensive_Coding-Shell-Input_Validation>>.
[[sect-Defensive_Coding-Shell-Types]]
====== Type declarations
==== Type declarations
[application]*bash* supports explicit type
declarations for shell variables:
@ -202,7 +202,7 @@ declarations for shell variables:
readonly -i integer_variable
readonly -a array_variable
readonly -A assoc_array_variable
----
Variables can also be declared as arrays by assigning them an
@ -212,7 +212,7 @@ array expression, as in:
----
array_variable=(1 2 3 4)
----
Some built-ins (such as `mapfile`) can
@ -228,7 +228,7 @@ Shell scripts which use integer or array variables should be
rewritten in another, more suitable language. Se <<sect-Defensive_Coding-Shell-Alternatives>>.
[[sect-Defensive_Coding-Shell-Obscure]]
===== Other Obscurities
=== Other Obscurities
Obscure shell language features should not be used. Examples are:
@ -245,7 +245,7 @@ with shell functions.
tokenize strings.
[[sect-Defensive_Coding-Shell-Invoke]]
==== Invoking External Commands
== Invoking External Commands
When passing shell variables as single command line arguments,
they should always be surrounded by double quotes. See
@ -300,7 +300,7 @@ See <<sect-Defensive_Coding-Tasks-Processes-Creation>>
for additional details on creating child processes.
[[sect-Defensive_Coding-Shell-Temporary_Files]]
==== Temporary Files
== Temporary Files
Temporary files should be created with the
`mktemp` command, and temporary directories with
@ -322,17 +322,17 @@ variables.
tmpfile="$(mktemp)"
cleanup () {
rm -f -- "$tmpfile"
rm -f -- "$tmpfile"
}
trap cleanup 0
----
====
[[sect-Defensive_Coding-Shell-Input_Validation]]
==== Performing Input Validation
== Performing Input Validation
In some cases, input validation cannot be avoided. For example,
if arithmetic evaluation is absolutely required, it is imperative
@ -350,7 +350,7 @@ POSIX shells.
[source,bash]
----
include::snippets/Shell-Input_Validation.adoc[]
include::../snippets/Shell-Input_Validation.adoc[]
----
@ -366,7 +366,7 @@ results (e.g., if the value being checked contains operators
itself) and should not be used.
[[sect-Defensive_Coding-Shell-Edit_Guard]]
==== Guarding Shell Scripts Against Changes
== Guarding Shell Scripts Against Changes
[application]*bash* only reads a shell script up to
the point it is needed for executed the next command. This means
@ -387,7 +387,7 @@ this syntax:
----
main "$@" ; exit $?
----
This construct ensures that [application]*bash* will

View file

@ -2,7 +2,7 @@
:experimental:
[[chap-Defensive_Coding-Vala]]
=== The Vala Programming Language
= The Vala Programming Language
Vala is a programming language mainly targeted at GNOME developers.
@ -33,4 +33,4 @@ reference counting) for `GObject` values. For
plain C pointers (such as strings), the programmer has to ensure
that storage is deallocated once it is no longer needed (to
avoid memory leaks), and that storage is not being deallocated
while it is still being used (see <<sect-Defensive_Coding-C-Use-After-Free>>).
while it is still being used (see <<sect-Defensive_Coding-C-Use-After-Free>>).

View file

@ -0,0 +1,17 @@
void report_overflow(void);
int
add(int a, int b)
{
int result = a + b;
if (a < 0 || b < 0) {
return -1;
}
// The compiler can optimize away the following if statement.
if (result < 0) {
report_overflow();
}
return result;
}

View file

@ -0,0 +1,13 @@
void report_overflow(void);
unsigned
add_unsigned(unsigned a, unsigned b)
{
unsigned sum = a + b;
if (sum < a) { // or sum < b
report_overflow();
}
return sum;
}

View file

@ -0,0 +1,10 @@
unsigned
mul(unsigned a, unsigned b)
{
if (b && a > ((unsigned)-1) / b) {
report_overflow();
}
return a * b;
}

View file

@ -0,0 +1,8 @@
static const char *const string_list[] = {
"first",
"second",
"third",
NULL
};

View file

@ -0,0 +1,45 @@
ssize_t
extract_strings(const char *in, size_t inlen, char **out, size_t outlen)
{
const char *inp = in;
const char *inend = in + inlen;
char **outp = out;
char **outend = out + outlen;
while (inp != inend) {
size_t len;
char *s;
if (outp == outend) {
errno = ENOSPC;
goto err;
}
len = (unsigned char)*inp;
++inp;
if (len > (size_t)(inend - inp)) {
errno = EINVAL;
goto err;
}
s = malloc(len + 1);
if (s == NULL) {
goto err;
}
memcpy(s, inp, len);
inp += len;
s[len] = '\0';
*outp = s;
++outp;
}
return outp - out;
err:
{
int errno_old = errno;
while (out != outp) {
free(*out);
++out;
}
errno = errno_old;
}
return -1;
}

View file

@ -0,0 +1,14 @@
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);
}

View file

@ -0,0 +1,10 @@
char buf[512];
char *current = buf;
const char *const end = buf + sizeof(buf);
for (struct item *it = data; it->key; ++it) {
snprintf(current, end - current, "%s%s=%d",
current == buf ? "" : ", ", it->key, it->value);
current += strlen(current);
}

View file

@ -0,0 +1,4 @@
char fraction[30];
snprintf(fraction, sizeof(fraction), "%d/%d", numerator, denominator);

View file

@ -0,0 +1,4 @@
buf[0] = '\0';
strncat(buf, data, sizeof(buf) - 1);

View file

@ -0,0 +1,5 @@
char buf[10];
snprintf(buf, sizeof(buf), "%s", prefix);
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "%s", data);

View file

@ -0,0 +1,3 @@
snprintf(buf, sizeof(buf), "%s%s", prefix, data);

View file

@ -0,0 +1,5 @@
char buf[10];
strncpy(buf, data, sizeof(buf));
buf[sizeof(buf) - 1] = '\0';

View file

@ -0,0 +1,18 @@
int pin_function(void *userdata, int attempt, const char *token_url,
const char *token_label, unsigned flags, char *pin, size_t pin_max)
{
if (flags & GNUTLS_PIN_FINAL_TRY)
printf("This is the final try before locking!\n");
if (flags & GNUTLS_PIN_COUNT_LOW)
printf("Only few tries left before locking!\n");
if (flags & GNUTLS_PIN_WRONG)
printf("Wrong PIN has been provided in the previous attempt\n");
/* userdata is the second value passed to gnutls_pkcs11_set_pin_function()
* in this example we passed the PIN as a null terminated value.
*/
snprintf(pin, pin_max, "%s", (char*)userdata);
return 0;
}

View file

@ -0,0 +1,40 @@
if (module_path) {
ret = gnutls_pkcs11_init(GNUTLS_PKCS11_FLAG_MANUAL, NULL);
if (ret < 0) {
fprintf(stderr, "error in %d: %s\n", __LINE__, gnutls_strerror(ret));
exit(1);
}
ret = gnutls_pkcs11_add_provider(module_path, NULL);
if (ret < 0) {
fprintf(stderr, "error in %d: %s\n", __LINE__, gnutls_strerror(ret));
exit(1);
}
}
if (key_pass)
gnutls_pkcs11_set_pin_function(pin_function, key_pass);
ret = gnutls_privkey_init(&private_key);
if (ret < 0) {
fprintf(stderr, "error in %d: %s\n", __LINE__, gnutls_strerror(ret));
exit(1);
}
ret = gnutls_privkey_import_url(private_key, private_key_name, 0);
if (ret < 0) {
fprintf(stderr, "error in %d: %s\n", __LINE__, gnutls_strerror(ret));
exit(1);
}
ret = gnutls_privkey_sign_data(private_key, GNUTLS_DIG_SHA256, 0,
&testdata, &signature);
if (ret < 0) {
fprintf(stderr, "error in %d: %s\n", __LINE__, gnutls_strerror(ret));
exit(1);
}
gnutls_privkey_deinit(private_key);
gnutls_free(signature.data);

View file

@ -0,0 +1,23 @@
char *passwdcb(PK11SlotInfo * slot, PRBool retry, void *arg)
{
if (!isatty(STDIN_FILENO) && retry) {
/* we're just reading from a file, and the value is known to be wrong,
* don't keep bounding the token with the wrong password. */
return NULL;
}
if (retry) {
printf("Warning: Wrong PIN has been provided in the previous attempt\n");
if (PK11_IsHW(slot)) {
printf
(" NOTE: multiple pin failures could result in locking your device\n");
}
}
if (pin == NULL)
return pin;
else
return strdup(pin);
}

View file

@ -0,0 +1,56 @@
SECStatus rv;
CERTCertificate *cert = NULL;
SECKEYPrivateKey *pvtkey = NULL;
SECItem signature = { siBuffer, NULL, 0 };
SECOidTag algTag;
int r = 1;
unsigned char buf[] = "test data to sign";
const char *cert_name;
unsigned i;
if (argc < 3) {
fprintf(stderr, "usage: %s [cert name] [PIN]\n\n", argv[0]);
exit(1);
}
cert_name = argv[1];
pin = argv[2];
PK11_SetPasswordFunc(passwdcb);
NSS_InitializePRErrorTable();
rv = NSS_Init(".");
if (rv != SECSuccess) {
fprintf(stderr, "NSS initialization failed (err %d)\n", PR_GetError());
goto cleanup;
}
cert = PK11_FindCertFromNickname(cert_name, NULL);
if (cert == NULL) {
fprintf(stderr, "Couldn't find cert %s in NSS db (err %d: %s)\n",
cert_name, PR_GetError(), PORT_ErrorToString(PR_GetError()));
goto cleanup;
}
fprintf(stderr, "Buffer being signed = \n%s\n", buf);
pvtkey = PK11_FindKeyByAnyCert(cert, NULL);
if (pvtkey == NULL) {
fprintf(stderr, "Couldn't find private key for cert %s (err %d: %s)\n",
cert_name, PR_GetError(), PORT_ErrorToString(PR_GetError()));
goto cleanup;
}
/* get the algtag. Pick the default hash algorithm */
algTag = SEC_GetSignatureAlgorithmOidTag(pvtkey->keyType, SEC_OID_UNKNOWN);
fprintf(stderr, "Signing with alg = %s (%d)\n",
SECOID_FindOIDTagDescription(algTag), algTag);
rv = SEC_SignData(&signature, buf, sizeof(buf)-1, pvtkey, algTag);
if (rv != SECSuccess) {
fprintf(stderr, "sign with Private Key failed (err %d: %s)\n",
PR_GetError(), PORT_ErrorToString(PR_GetError()));
goto cleanup;
}

View file

@ -0,0 +1,64 @@
OpenSSL_add_all_algorithms();
ERR_load_crypto_strings();
ERR_clear_error();
ENGINE_load_builtin_engines();
e = ENGINE_by_id("pkcs11");
if (!e) {
display_openssl_errors(__LINE__);
exit(1);
}
if (module_path) {
fprintf(stderr, "loading: %s\n", module_path);
if (!ENGINE_ctrl_cmd_string(e, "MODULE_PATH", module_path, 0)) {
display_openssl_errors(__LINE__);
exit(1);
}
}
if (!ENGINE_init(e)) {
display_openssl_errors(__LINE__);
exit(1);
}
if (key_pass && !ENGINE_ctrl_cmd_string(e, "PIN", key_pass, 0)) {
display_openssl_errors(__LINE__);
exit(1);
}
private_key = ENGINE_load_private_key(e, private_key_name, NULL, NULL);
if (!private_key) {
fprintf(stderr, "cannot load: %s\n", private_key_name);
display_openssl_errors(__LINE__);
exit(1);
}
display_openssl_errors(__LINE__);
digest_algo = EVP_get_digestbyname("sha256");
EVP_MD_CTX_init(&ctx);
if (EVP_DigestInit(&ctx, digest_algo) <= 0) {
display_openssl_errors(__LINE__);
exit(1);
}
EVP_SignInit(&ctx, digest_algo);
#define TEST_DATA "test data"
if (EVP_SignUpdate(&ctx, TEST_DATA, sizeof(TEST_DATA) - 1) <= 0) {
display_openssl_errors(__LINE__);
exit(1);
}
n = sizeof(buf);
if (EVP_SignFinal(&ctx, buf, &n, private_key) <= 0) {
display_openssl_errors(__LINE__);
exit(1);
}
EVP_PKEY_free(private_key);
ENGINE_finish(e);

View file

@ -0,0 +1,46 @@
// Create the session object.
gnutls_session_t session;
ret = gnutls_init(&session, GNUTLS_CLIENT);
if (ret != GNUTLS_E_SUCCESS) {
fprintf(stderr, "error: gnutls_init: %s\n",
gnutls_strerror(ret));
exit(1);
}
// Configure the cipher preferences.
const char *errptr = NULL;
ret = gnutls_priority_set_direct(session, "NORMAL", &errptr);
if (ret != GNUTLS_E_SUCCESS) {
fprintf(stderr, "error: gnutls_priority_set_direct: %s\n"
"error: at: \"%s\"\n", gnutls_strerror(ret), errptr);
exit(1);
}
// Install the trusted certificates.
ret = gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, cred);
if (ret != GNUTLS_E_SUCCESS) {
fprintf(stderr, "error: gnutls_credentials_set: %s\n",
gnutls_strerror(ret));
exit(1);
}
// Associate the socket with the session object and set the server
// name.
gnutls_transport_set_int(session, 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);
}

View file

@ -0,0 +1,21 @@
// Load the trusted CA certificates.
gnutls_certificate_credentials_t cred = NULL;
int ret = gnutls_certificate_allocate_credentials (&cred);
if (ret != GNUTLS_E_SUCCESS) {
fprintf(stderr, "error: gnutls_certificate_allocate_credentials: %s\n",
gnutls_strerror(ret));
exit(1);
}
ret = gnutls_certificate_set_x509_system_trust(cred);
if (ret == 0) {
fprintf(stderr, "error: no certificates found in system trust store\n");
exit(1);
}
if (ret < 0) {
fprintf(stderr, "error: gnutls_certificate_set_x509_system_trust: %s\n",
gnutls_strerror(ret));
exit(1);
}

View file

@ -0,0 +1,38 @@
// Obtain the server certificate chain. The server certificate
// itself is stored in the first element of the array.
unsigned certslen = 0;
const gnutls_datum_t *const certs =
gnutls_certificate_get_peers(session, &certslen);
if (certs == NULL || certslen == 0) {
fprintf(stderr, "error: could not obtain peer certificate\n");
exit(1);
}
// Validate the certificate chain.
unsigned status = (unsigned)-1;
ret = gnutls_certificate_verify_peers3(session, host, &status);
if (ret != GNUTLS_E_SUCCESS) {
fprintf(stderr, "error: gnutls_certificate_verify_peers3: %s\n",
gnutls_strerror(ret));
exit(1);
}
if (status != 0 && !certificate_validity_override(certs[0])) {
gnutls_datum_t msg;
#if GNUTLS_VERSION_AT_LEAST_3_1_4
int type = gnutls_certificate_type_get (session);
ret = gnutls_certificate_verification_status_print(status, type, &out, 0);
#else
ret = -1;
#endif
if (ret == 0) {
fprintf(stderr, "error: %s\n", msg.data);
gnutls_free(msg.data);
exit(1);
} else {
fprintf(stderr, "error: certificate validation failed with code 0x%x\n",
status);
exit(1);
}
}

View file

@ -0,0 +1,11 @@
// 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);

View file

@ -0,0 +1,76 @@
// 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);
}
// 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);
}

View file

@ -0,0 +1,22 @@
// 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);

View file

@ -0,0 +1,22 @@
// 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);

View file

@ -0,0 +1,18 @@
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);

View file

@ -0,0 +1,3 @@
params.setEndpointIdentificationAlgorithm("HTTPS");

View file

@ -0,0 +1,14 @@
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;

View file

@ -0,0 +1,34 @@
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];
}
}

View file

@ -0,0 +1,7 @@
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);

View file

@ -0,0 +1,67 @@
// Configure a client connection context. Send a hendshake for the
// highest supported TLS version, and disable compression.
const SSL_METHOD *const req_method = SSLv23_client_method();
SSL_CTX *const ctx = SSL_CTX_new(req_method);
if (ctx == NULL) {
ERR_print_errors(bio_err);
exit(1);
}
SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_COMPRESSION);
// Adjust the ciphers list based on a whitelist. First enable all
// ciphers of at least medium strength, to get the list which is
// compiled into OpenSSL.
if (SSL_CTX_set_cipher_list(ctx, "HIGH:MEDIUM") != 1) {
ERR_print_errors(bio_err);
exit(1);
}
{
// Create a dummy SSL session to obtain the cipher list.
SSL *ssl = SSL_new(ctx);
if (ssl == NULL) {
ERR_print_errors(bio_err);
exit(1);
}
STACK_OF(SSL_CIPHER) *active_ciphers = SSL_get_ciphers(ssl);
if (active_ciphers == NULL) {
ERR_print_errors(bio_err);
exit(1);
}
// Whitelist of candidate ciphers.
static const char *const candidates[] = {
"AES128-GCM-SHA256", "AES128-SHA256", "AES256-SHA256", // strong ciphers
"AES128-SHA", "AES256-SHA", // strong ciphers, also in older versions
"RC4-SHA", "RC4-MD5", // backwards compatibility, supposed to be weak
"DES-CBC3-SHA", "DES-CBC3-MD5", // more backwards compatibility
NULL
};
// Actually selected ciphers.
char ciphers[300];
ciphers[0] = '\0';
for (const char *const *c = candidates; *c; ++c) {
for (int i = 0; i < sk_SSL_CIPHER_num(active_ciphers); ++i) {
if (strcmp(SSL_CIPHER_get_name(sk_SSL_CIPHER_value(active_ciphers, i)),
*c) == 0) {
if (*ciphers) {
strcat(ciphers, ":");
}
strcat(ciphers, *c);
break;
}
}
}
SSL_free(ssl);
// Apply final cipher list.
if (SSL_CTX_set_cipher_list(ctx, ciphers) != 1) {
ERR_print_errors(bio_err);
exit(1);
}
}
// Load the set of trusted root certificates.
if (!SSL_CTX_set_default_verify_paths(ctx)) {
ERR_print_errors(bio_err);
exit(1);
}

View file

@ -0,0 +1,51 @@
// Create the connection object.
SSL *ssl = SSL_new(ctx);
if (ssl == NULL) {
ERR_print_errors(bio_err);
exit(1);
}
SSL_set_fd(ssl, sockfd);
// Enable the ServerNameIndication extension
if (!SSL_set_tlsext_host_name(ssl, host)) {
ERR_print_errors(bio_err);
exit(1);
}
// Perform the TLS handshake with the server.
ret = SSL_connect(ssl);
if (ret != 1) {
// Error status can be 0 or negative.
ssl_print_error_and_exit(ssl, "SSL_connect", ret);
}
// Obtain the server certificate.
X509 *peercert = SSL_get_peer_certificate(ssl);
if (peercert == NULL) {
fprintf(stderr, "peer certificate missing");
exit(1);
}
// Check the certificate verification result. Allow an explicit
// certificate validation override in case verification fails.
int verifystatus = SSL_get_verify_result(ssl);
if (verifystatus != X509_V_OK && !certificate_validity_override(peercert)) {
fprintf(stderr, "SSL_connect: verify result: %s\n",
X509_verify_cert_error_string(verifystatus));
exit(1);
}
// Check if the server certificate matches the host name used to
// establish the connection.
// FIXME: Currently needs OpenSSL 1.1.
if (X509_check_host(peercert, (const unsigned char *)host, strlen(host),
0) != 1
&& !certificate_host_name_override(peercert, host)) {
fprintf(stderr, "SSL certificate does not match host name\n");
exit(1);
}
X509_free(peercert);

View file

@ -0,0 +1,11 @@
const char *const req = "GET / HTTP/1.0\r\n\r\n";
if (SSL_write(ssl, req, strlen(req)) < 0) {
ssl_print_error_and_exit(ssl, "SSL_write", ret);
}
char buf[4096];
ret = SSL_read(ssl, buf, sizeof(buf));
if (ret < 0) {
ssl_print_error_and_exit(ssl, "SSL_read", ret);
}

View file

@ -0,0 +1,9 @@
// 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();

View file

@ -0,0 +1,10 @@
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")

View file

@ -0,0 +1,25 @@
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

View file

@ -0,0 +1,3 @@
gnutls_certificate_free_credentials(cred);

View file

@ -0,0 +1,10 @@
// Initiate an orderly connection shutdown.
ret = gnutls_bye(session, GNUTLS_SHUT_RDWR);
if (ret < 0) {
fprintf(stderr, "error: gnutls_bye: %s\n", gnutls_strerror(ret));
exit(1);
}
// Free the session object.
gnutls_deinit(session);

View file

@ -0,0 +1,5 @@
// This is only necessary if compatibility with GnuTLS prior to
// 3.3.0 is required.
gnutls_global_init();

View file

@ -0,0 +1,14 @@
char buf[4096];
snprintf(buf, sizeof(buf), "GET / HTTP/1.0\r\nHost: %s\r\n\r\n", host);
ret = gnutls_record_send(session, buf, strlen(buf));
if (ret < 0) {
fprintf(stderr, "error: gnutls_record_send: %s\n", gnutls_strerror(ret));
exit(1);
}
ret = gnutls_record_recv(session, buf, sizeof(buf));
if (ret < 0) {
fprintf(stderr, "error: gnutls_record_recv: %s\n", gnutls_strerror(ret));
exit(1);
}

View file

@ -0,0 +1,4 @@
SECMOD_DestroyModule(module);
NSS_ShutdownContext(ctx);

View file

@ -0,0 +1,16 @@
// NSPR include files
#include <prerror.h>
#include <prinit.h>
// NSS include files
#include <nss.h>
#include <pk11pub.h>
#include <secmod.h>
#include <ssl.h>
#include <sslproto.h>
// Private API, no other way to turn a POSIX file descriptor into an
// NSPR handle.
NSPR_API(PRFileDesc*) PR_ImportTCPSocket(int);

View file

@ -0,0 +1,67 @@
PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
NSSInitContext *const ctx =
NSS_InitContext("sql:/etc/pki/nssdb", "", "", "", NULL,
NSS_INIT_READONLY | NSS_INIT_PK11RELOAD);
if (ctx == NULL) {
const PRErrorCode err = PR_GetError();
fprintf(stderr, "error: NSPR error code %d: %s\n",
err, PR_ErrorToName(err));
exit(1);
}
// Ciphers to enable.
static const PRUint16 good_ciphers[] = {
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
TLS_RSA_WITH_AES_128_GCM_SHA256,
TLS_RSA_WITH_AES_256_GCM_SHA384,
TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
TLS_DHE_RSA_WITH_AES_256_GCM_SHA384,
TLS_RSA_WITH_AES_128_CBC_SHA,
TLS_RSA_WITH_AES_256_CBC_SHA,
SSL_RSA_WITH_3DES_EDE_CBC_SHA,
SSL_NULL_WITH_NULL_NULL // sentinel
};
// Check if the current policy allows any strong ciphers. If it
// doesn't, set the cipher suite policy. This is not thread-safe
// and has global impact. Consequently, we only do it if absolutely
// necessary.
int found_good_cipher = 0;
for (const PRUint16 *p = good_ciphers; *p != SSL_NULL_WITH_NULL_NULL;
++p) {
PRInt32 policy;
if (SSL_CipherPolicyGet(*p, &policy) != SECSuccess) {
const PRErrorCode err = PR_GetError();
fprintf(stderr, "error: policy for cipher %u: error %d: %s\n",
(unsigned)*p, err, PR_ErrorToName(err));
exit(1);
}
if (policy == SSL_ALLOWED) {
fprintf(stderr, "info: found cipher %x\n", (unsigned)*p);
found_good_cipher = 1;
break;
}
}
if (!found_good_cipher) {
if (NSS_SetDomesticPolicy() != SECSuccess) {
const PRErrorCode err = PR_GetError();
fprintf(stderr, "error: NSS_SetDomesticPolicy: error %d: %s\n",
err, PR_ErrorToName(err));
exit(1);
}
}
// Initialize the trusted certificate store.
char module_name[] = "library=libnssckbi.so name=\"Root Certs\"";
SECMODModule *module = SECMOD_LoadUserModule(module_name, NULL, PR_FALSE);
if (module == NULL || !module->loaded) {
const PRErrorCode err = PR_GetError();
fprintf(stderr, "error: NSPR error code %d: %s\n",
err, PR_ErrorToName(err));
exit(1);
}

View file

@ -0,0 +1,18 @@
char buf[4096];
snprintf(buf, sizeof(buf), "GET / HTTP/1.0\r\nHost: %s\r\n\r\n", host);
PRInt32 ret = PR_Write(nspr, buf, strlen(buf));
if (ret < 0) {
const PRErrorCode err = PR_GetError();
fprintf(stderr, "error: PR_Write error %d: %s\n",
err, PR_ErrorToName(err));
exit(1);
}
ret = PR_Read(nspr, buf, sizeof(buf));
if (ret < 0) {
const PRErrorCode err = PR_GetError();
fprintf(stderr, "error: PR_Read error %d: %s\n",
err, PR_ErrorToName(err));
exit(1);
}

View file

@ -0,0 +1,8 @@
const int val = 1;
int ret = setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val));
if (ret < 0) {
perror("setsockopt(TCP_NODELAY)");
exit(1);
}

View file

@ -0,0 +1,23 @@
// Prepare TLS parameters. These have to applied to every TLS
// socket before the handshake is triggered.
SSLParameters params = ctx.getDefaultSSLParameters();
// Do not send an SSL-2.0-compatible Client Hello.
ArrayList<String> protocols = new ArrayList<String>(
Arrays.asList(params.getProtocols()));
protocols.remove("SSLv2Hello");
params.setProtocols(protocols.toArray(new String[protocols.size()]));
// Adjust the supported ciphers.
ArrayList<String> ciphers = new ArrayList<String>(
Arrays.asList(params.getCipherSuites()));
ciphers.retainAll(Arrays.asList(
"TLS_RSA_WITH_AES_128_CBC_SHA256",
"TLS_RSA_WITH_AES_256_CBC_SHA256",
"TLS_RSA_WITH_AES_256_CBC_SHA",
"TLS_RSA_WITH_AES_128_CBC_SHA",
"SSL_RSA_WITH_3DES_EDE_CBC_SHA",
"SSL_RSA_WITH_RC4_128_SHA1",
"SSL_RSA_WITH_RC4_128_MD5",
"TLS_EMPTY_RENEGOTIATION_INFO_SCSV"));
params.setCipherSuites(ciphers.toArray(new String[ciphers.size()]));

View file

@ -0,0 +1,26 @@
// Send the close_notify alert.
ret = SSL_shutdown(ssl);
switch (ret) {
case 1:
// A close_notify alert has already been received.
break;
case 0:
// Wait for the close_notify alert from the peer.
ret = SSL_shutdown(ssl);
switch (ret) {
case 0:
fprintf(stderr, "info: second SSL_shutdown returned zero\n");
break;
case 1:
break;
default:
ssl_print_error_and_exit(ssl, "SSL_shutdown 2", ret);
}
break;
default:
ssl_print_error_and_exit(ssl, "SSL_shutdown 1", ret);
}
SSL_free(ssl);
close(sockfd);

View file

@ -0,0 +1,3 @@
SSL_CTX_free(ctx);

View file

@ -0,0 +1,27 @@
static void __attribute__((noreturn))
ssl_print_error_and_exit(SSL *ssl, const char *op, int ret)
{
int subcode = SSL_get_error(ssl, ret);
switch (subcode) {
case SSL_ERROR_NONE:
fprintf(stderr, "error: %s: no error to report\n", op);
break;
case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_WRITE:
case SSL_ERROR_WANT_X509_LOOKUP:
case SSL_ERROR_WANT_CONNECT:
case SSL_ERROR_WANT_ACCEPT:
fprintf(stderr, "error: %s: invalid blocking state %d\n", op, subcode);
break;
case SSL_ERROR_SSL:
fprintf(stderr, "error: %s: TLS layer problem\n", op);
case SSL_ERROR_SYSCALL:
fprintf(stderr, "error: %s: system call failed: %s\n", op, strerror(errno));
break;
case SSL_ERROR_ZERO_RETURN:
fprintf(stderr, "error: %s: zero return\n", op);
}
exit(1);
}

View file

@ -0,0 +1,3 @@
sock.close()

View file

@ -0,0 +1,4 @@
sock.write("GET / HTTP/1.1\r\nHost: " + host + "\r\n\r\n")
print sock.read()

View file

@ -0,0 +1,21 @@
func IOError(r io.Reader, buf []byte, processor Processor,
handler ErrorHandler) (message string, err error) {
n, err := r.Read(buf)
// First check for available data.
if n > 0 {
message, err = processor.Process(buf[0:n])
// Regular error handling.
if err != nil {
handler.Handle(err)
return "", err
}
}
// Then handle any error.
if err != nil {
handler.Handle(err)
return "", err
}
return
}

View file

@ -0,0 +1,19 @@
type Processor interface {
Process(buf []byte) (message string, err error)
}
type ErrorHandler interface {
Handle(err error)
}
func RegularError(buf []byte, processor Processor,
handler ErrorHandler) (message string, err error) {
message, err = processor.Process(buf)
if err != nil {
handler.Handle(err)
return "", err
}
return
}

View file

@ -0,0 +1,8 @@
InputStream in = new BufferedInputStream(new FileInputStream(path));
try {
readFile(in);
} finally {
in.close();
}

View file

@ -0,0 +1,32 @@
JNIEXPORT jint JNICALL Java_sum
(JNIEnv *jEnv, jclass clazz, jbyteArray buffer, jint offset, jint length)
{
assert(sizeof(jint) == sizeof(unsigned));
if (offset < 0 || length < 0) {
(*jEnv)->ThrowNew(jEnv, arrayIndexOutOfBoundsExceptionClass,
"negative offset/length");
return 0;
}
unsigned uoffset = offset;
unsigned ulength = length;
// This cannot overflow because of the check above.
unsigned totallength = uoffset + ulength;
unsigned actuallength = (*jEnv)->GetArrayLength(jEnv, buffer);
if (totallength > actuallength) {
(*jEnv)->ThrowNew(jEnv, arrayIndexOutOfBoundsExceptionClass,
"offset + length too large");
return 0;
}
unsigned char *ptr = (*jEnv)->GetPrimitiveArrayCritical(jEnv, buffer, 0);
if (ptr == NULL) {
return 0;
}
unsigned long long sum = 0;
for (unsigned char *p = ptr + uoffset, *end = p + ulength; p != end; ++p) {
sum += *p;
}
(*jEnv)->ReleasePrimitiveArrayCritical(jEnv, buffer, ptr, 0);
return sum;
}

View file

@ -0,0 +1,35 @@
static byte[] readBytes(InputStream in, int length) throws IOException {
final int startSize = 65536;
byte[] b = new byte[Math.min(length, startSize)];
int filled = 0;
while (true) {
int remaining = b.length - filled;
readFully(in, b, filled, remaining);
if (b.length == length) {
break;
}
filled = b.length;
if (length - b.length <= b.length) {
// Allocate final length. Condition avoids overflow.
b = Arrays.copyOf(b, length);
} else {
b = Arrays.copyOf(b, b.length * 2);
}
}
return b;
}
static void readFully(InputStream in,byte[] b, int off, int len)
throws IOException {
int startlen = len;
while (len > 0) {
int count = in.read(b, off, len);
if (count < 0) {
throw new EOFException();
}
off += count;
len -= count;
}
}

View file

@ -0,0 +1,36 @@
interface Callback<T> {
T call(boolean flag);
}
class CallbackInvoker<T> {
private final AccessControlContext context;
Callback<T> callback;
CallbackInvoker(Callback<T> callback) {
context = AccessController.getContext();
this.callback = callback;
}
public T invoke() {
// Obtain increased privileges.
return AccessController.doPrivileged(new PrivilegedAction<T>() {
@Override
public T run() {
// This operation would fail without
// additional privileges.
final boolean flag = Boolean.getBoolean("some.property");
// Restore the original privileges.
return AccessController.doPrivileged(
new PrivilegedAction<T>() {
@Override
public T run() {
return callback.call(flag);
}
}, context);
}
});
}
}

View file

@ -0,0 +1,4 @@
permissions.add(new FilePermission(
System.getProperty("user.dir") + "/-", "read"));

View file

@ -0,0 +1,15 @@
// This is expected to fail.
try {
System.out.println(System.getProperty("user.home"));
} catch (SecurityException e) {
e.printStackTrace(System.err);
}
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
// This should work.
System.out.println(System.getProperty("user.home"));
return null;
}
});

View file

@ -0,0 +1,24 @@
Permissions permissions = new Permissions();
ProtectionDomain protectionDomain =
new ProtectionDomain(null, permissions);
AccessControlContext context = new AccessControlContext(
new ProtectionDomain[] { protectionDomain });
// This is expected to succeed.
try (FileInputStream in = new FileInputStream(path)) {
System.out.format("FileInputStream: %s%n", in);
}
AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() {
@Override
public Void run() throws Exception {
// This code runs with reduced privileges and is
// expected to fail.
try (FileInputStream in = new FileInputStream(path)) {
System.out.format("FileInputStream: %s%n", in);
}
return null;
}
}, context);

View file

@ -0,0 +1,5 @@
try (InputStream in = new BufferedInputStream(new FileInputStream(path))) {
readFile(in);
}

View file

@ -0,0 +1,8 @@
if [[ $value =~ ^-?[0-9]+$ ]] ; then
echo value is an integer
else
echo "value is not an integer" 1>&2
exit 1
fi

View file

@ -0,0 +1,13 @@
XML_Parser parser = XML_ParserCreate("UTF-8");
if (parser == NULL) {
fprintf(stderr, "XML_ParserCreate failed\n");
close(fd);
exit(1);
}
// EntityDeclHandler needs a reference to the parser to stop
// parsing.
XML_SetUserData(parser, parser);
// Disable entity processing, to inhibit entity expansion.
XML_SetEntityDeclHandler(parser, EntityDeclHandler);

View file

@ -0,0 +1,12 @@
// Stop the parser when an entity declaration is encountered.
static void
EntityDeclHandler(void *userData,
const XML_Char *entityName, int is_parameter_entity,
const XML_Char *value, int value_length,
const XML_Char *base, const XML_Char *systemId,
const XML_Char *publicId, const XML_Char *notationName)
{
XML_StopParser((XML_Parser)userData, XML_FALSE);
}

View file

@ -0,0 +1,18 @@
class Errors implements ErrorHandler {
@Override
public void warning(SAXParseException exception) {
exception.printStackTrace();
}
@Override
public void fatalError(SAXParseException exception) {
exception.printStackTrace();
}
@Override
public void error(SAXParseException exception) {
exception.printStackTrace();
}
}

View file

@ -0,0 +1,23 @@
import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.sax.SAXSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;
import org.w3c.dom.Document;
import org.w3c.dom.ls.LSInput;
import org.w3c.dom.ls.LSResourceResolver;
import org.xml.sax.EntityResolver;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.XMLReader;

View file

@ -0,0 +1,11 @@
class NoEntityResolver implements EntityResolver {
@Override
public InputSource resolveEntity(String publicId, String systemId)
throws SAXException, IOException {
// Throwing an exception stops validation.
throw new IOException(String.format(
"attempt to resolve \"%s\" \"%s\"", publicId, systemId));
}
}

View file

@ -0,0 +1,13 @@
class NoResourceResolver implements LSResourceResolver {
@Override
public LSInput resolveResource(String type, String namespaceURI,
String publicId, String systemId, String baseURI) {
// Throwing an exception stops validation.
throw new RuntimeException(String.format(
"resolution attempt: type=%s namespace=%s " +
"publicId=%s systemId=%s baseURI=%s",
type, namespaceURI, publicId, systemId, baseURI));
}
}

View file

@ -0,0 +1,15 @@
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
// Impose restrictions on the complexity of the DTD.
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
// Turn on validation.
// This step can be omitted if validation is not desired.
factory.setValidating(true);
// Parse the document.
DocumentBuilder builder = factory.newDocumentBuilder();
builder.setEntityResolver(new NoEntityResolver());
builder.setErrorHandler(new Errors());
Document document = builder.parse(inputStream);

View file

@ -0,0 +1,19 @@
SchemaFactory factory = SchemaFactory.newInstance(
XMLConstants.W3C_XML_SCHEMA_NS_URI);
// This enables restrictions on schema complexity.
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
// The following line prevents resource resolution
// by the schema itself.
factory.setResourceResolver(new NoResourceResolver());
Schema schema = factory.newSchema(schemaFile);
Validator validator = schema.newValidator();
// This prevents external resource resolution.
validator.setResourceResolver(new NoResourceResolver());
validator.validate(new DOMSource(document));

View file

@ -0,0 +1,22 @@
SchemaFactory factory = SchemaFactory.newInstance(
XMLConstants.W3C_XML_SCHEMA_NS_URI);
// This enables restrictions on the schema and document
// complexity.
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
// This prevents resource resolution by the schema itself.
// If the schema is trusted and references additional files,
// this line must be omitted, otherwise loading these files
// will fail.
factory.setResourceResolver(new NoResourceResolver());
Schema schema = factory.newSchema(schemaFile);
Validator validator = schema.newValidator();
// This prevents external resource resolution.
validator.setResourceResolver(new NoResourceResolver());
validator.validate(new SAXSource(new InputSource(inputStream)));

View file

@ -0,0 +1,38 @@
class NoEntityHandler : public QXmlDeclHandler {
public:
bool attributeDecl(const QString&, const QString&, const QString&,
const QString&, const QString&);
bool internalEntityDecl(const QString&, const QString&);
bool externalEntityDecl(const QString&, const QString&,
const QString&);
QString errorString() const;
};
bool
NoEntityHandler::attributeDecl
(const QString&, const QString&, const QString&, const QString&,
const QString&)
{
return false;
}
bool
NoEntityHandler::internalEntityDecl(const QString&, const QString&)
{
return false;
}
bool
NoEntityHandler::externalEntityDecl(const QString&, const QString&, const
QString&)
{
return false;
}
QString
NoEntityHandler::errorString() const
{
return "XML declaration not permitted";
}

View file

@ -0,0 +1,21 @@
class NoEntityReader : public QXmlSimpleReader {
NoEntityHandler handler;
public:
NoEntityReader();
void setDeclHandler(QXmlDeclHandler *);
};
NoEntityReader::NoEntityReader()
{
QXmlSimpleReader::setDeclHandler(&handler);
setFeature("http://xml.org/sax/features/namespaces", true);
setFeature("http://xml.org/sax/features/namespace-prefixes", false);
}
void
NoEntityReader::setDeclHandler(QXmlDeclHandler *)
{
// Ignore the handler which was passed in.
}

View file

@ -0,0 +1,12 @@
NoEntityReader reader;
QBuffer buffer(&data);
buffer.open(QIODevice::ReadOnly);
QXmlInputSource source(&buffer);
QDomDocument doc;
QString errorMsg;
int errorLine;
int errorColumn;
bool okay = doc.setContent
(&source, &reader, &errorMsg, &errorLine, &errorColumn);

Some files were not shown because too many files have changed in this diff Show more