first pass at an Antora conversion
3
.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
build
|
||||
cache
|
||||
public
|
5
Makefile
|
@ -7,11 +7,10 @@ include src/src.mk
|
|||
#build: build-src build-manual
|
||||
|
||||
build-snippets:
|
||||
mkdir -p en-US/snippets
|
||||
mkdir -p modules/ROOT/pages/_partials/snippets
|
||||
python scripts/split-snippets.py . \
|
||||
src/*.c src/*.cpp src/*.java src/*.py src/*.go src/*.sh
|
||||
|
||||
clean: clean-src
|
||||
-rm -rf html
|
||||
-rm -rf en-US/*/snippets
|
||||
-rm -rf modules/ROOT/pages/_partials/snippets
|
||||
|
||||
|
|
77
README.md
|
@ -17,10 +17,79 @@ repository) at:
|
|||
you lack the necessary libraries, the code examples are still
|
||||
included in the manual.
|
||||
|
||||
After this you need to run `asciibinder package` to produce the document.
|
||||
## Local preview
|
||||
|
||||
This repo includes scripts to build and preview the contents of this repository.
|
||||
|
||||
# Dependencies
|
||||
**NOTE**: Please note that if you reference pages from other repositoreis, such links will be broken in this local preview as it only builds this repository. If you want to rebuild the whole Fedora Docs site, please see [the Fedora Docs build repository](https://pagure.io/fedora-docs/docs-fp-o/) for instructions.
|
||||
|
||||
Building the manual pages needs the "publican" and the "publican-fedora"
|
||||
packages.
|
||||
Both scripts use docker, so please make sure you have it installed on your system. Please see below for instructions.
|
||||
|
||||
To build and preview the site, run:
|
||||
|
||||
```
|
||||
$ ./build.sh && ./preview.sh
|
||||
```
|
||||
|
||||
The result will be available at http://localhost:8080
|
||||
|
||||
### Installing docker on Fedora
|
||||
|
||||
```
|
||||
$ sudo dnf install docker
|
||||
$ sudo systemctl start docker && sudo systemctl enable docker
|
||||
```
|
||||
|
||||
### Preview as a part of the whole Fedora Docs site
|
||||
|
||||
You can also build the whole Fedora Docs site locally to see your changes in the whole context.
|
||||
This is especially useful for checking if your `xref` links work properly.
|
||||
|
||||
To do this, you need to clone the main [Fedora Docs build repository](https://pagure.io/fedora-docs/docs-fp-o), modify the `site.yml` file to reference a repo with your changes, and build it.
|
||||
Steps:
|
||||
|
||||
Clone the main repository and cd into it:
|
||||
|
||||
```
|
||||
$ git clone https://pagure.io/fedora-docs/docs-fp-o.git
|
||||
$ cd docs-fp-o
|
||||
```
|
||||
|
||||
Find a reference to the repository you're changing in the `site.yml` file, and change it so it points to your change.
|
||||
So for example, if I made a modification to the Modularity docs, I would find:
|
||||
|
||||
```
|
||||
...
|
||||
- url: https://pagure.io/fedora-docs/modularity.git
|
||||
branches:
|
||||
- master
|
||||
...
|
||||
```
|
||||
|
||||
And replaced it with a pointer to my fork:
|
||||
```
|
||||
...
|
||||
- url: https://pagure.io/forks/asamalik/fedora-docs/modularity.git
|
||||
branches:
|
||||
- master
|
||||
...
|
||||
```
|
||||
|
||||
I could also point to a local repository, using `HEAD` as a branch to preview the what's changed without the need of making a commit.
|
||||
|
||||
**Note:** I would need to move the repository under the `docs-fp-o` directory, because the builder won't see anything above.
|
||||
So I would need to create a `repositories` directory in `docs-fp-o` and copy my repository into it.
|
||||
|
||||
```
|
||||
...
|
||||
- url: ./repositories/modularity
|
||||
branches:
|
||||
- HEAD
|
||||
...
|
||||
```
|
||||
|
||||
To build the whole site, I would run the following in the `docs-fp-o` directory.
|
||||
|
||||
```
|
||||
$ ./build.sh && ./preview.sh
|
||||
```
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
---
|
||||
fedora:
|
||||
name: Defensive Coding Guide
|
||||
author: Fedora Docs <docs@lists.fedoraproject.org>
|
||||
site: main
|
||||
site_name: Home
|
||||
site_url: https://docs.fedoraproject.org/
|
||||
branches:
|
||||
master:
|
||||
name:
|
||||
dir: master
|
135
_images/404.html
|
@ -1,135 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags -->
|
||||
|
||||
<title>Fedora Documentation Website</title>
|
||||
|
||||
<!-- Bootstrap -->
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap-theme.min.css">
|
||||
|
||||
<link rel="stylesheet" href="https://overpass-30e2.kxcdn.com/overpass.css">
|
||||
<link rel="stylesheet" href="_stylesheets/asciibinder.css">
|
||||
|
||||
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
|
||||
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
|
||||
<!--[if lt IE 9]>
|
||||
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
|
||||
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
|
||||
<![endif]-->
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="page-header">
|
||||
<img src="/_images/fedora.svg" class="img-responsive" />
|
||||
<h2><strong>Fedora Documentation Site</strong></h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<h4><strong>Fedora Documentation - 404 Page Not Found :(</strong></h4>
|
||||
<p>Hi! You've arrived at Fedora documentation page which does not actually exist. This may be because you followed a link to an older document which has been retired. For reference, you can find those in our <a href="https://docs-old.fedoraproject.org/">old document archive</a>. Or, you can browse <a href="https://docs.fedoraproject.org/">current docs</a>.</p>
|
||||
<p>It may also be that this page _should_ exist, but sadly does not. If this is the case, and you know what it should say, you can <a href="https://pagure.io/fedora-docs">contribute via the Docs Project</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="bottom" class="text-muted py-3" >
|
||||
<div class="foot">
|
||||
<div class="container">
|
||||
<div class="row footerlinks">
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">About</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Overview">About Fedora</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/sponsors">Sponsors</a></dd>
|
||||
<dd><a href="https://fedoramagazine.org">Fedora Magazine</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Legal:Main#Legal">Legal</a></dd>
|
||||
</dl>
|
||||
<ul class="list-inline">
|
||||
<li>
|
||||
<a href="https:https://www.facebook.com/TheFedoraProject" class="btn-social btn-outline"><i class="fa fa-fw fa-facebook"></i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https:https://plus.google.com/112917221531140868607" class="btn-social btn-outline"><i class="fa fa-fw fa-google-plus"></i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https:https://twitter.com/fedora" class="btn-social btn-outline"><i class="fa fa-fw fa-twitter"></i></a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title uppercase">Download</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://getfedora.org/en/workstation/download">Get Fedora Workstation</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/server/download">Get Fedora Server</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/atomic/download">Get Fedora Atomic</a></dd>
|
||||
<dd><a href="https://spins.fedoraproject.org">Fedora Spins</a></dd>
|
||||
<dd><a href="https://labs.fedoraproject.org">Fedora Labs</a></dd>
|
||||
<dd><a href="https://arm.fedoraproject.org">Fedora ARM<span class="sup">®</span></a></dd>
|
||||
<dd><a href="https://alt.fedoraproject.org/">Alternative Downloads</a></dd>
|
||||
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">Support</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Communicating_and_getting_help">Get Help</a></dd>
|
||||
<dd><a href="https://ask.fedoraproject.org/">Ask Fedora</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Common_F27_bugs">Common Bugs</a></dd>
|
||||
<dd><a href="https://developer.fedoraproject.org/">Fedora Developer Portal</a></dd>
|
||||
<dd><a href="https://docs.fedoraproject.org/f27/install-guide/index.html">Installation Guide</a></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">Join</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Join">Join Fedora</a></dd>
|
||||
<dd><a href="http://fedoraplanet.org">Planet Fedora</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/SIGs">Fedora SIGs</a></dd>
|
||||
<dd><a href="https://admin.fedoraproject.org/accounts/">Fedora Account System</a></dd>
|
||||
<dd><a href="https://fedoracommunity.org/">Fedora Community</a></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- /row of widgets -->
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-2">
|
||||
<div class="widget-body">
|
||||
<a href="https://www.redhat.com/"><img class="rh-logo" src="_images/redhat-logo.png" alt="Red Hat Logo" /></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-7">
|
||||
<div class="widget-body">
|
||||
<p class="sponsor">Fedora is sponsored by Red Hat.</p>
|
||||
<p class="sponsor"><a href="https://www.redhat.com/en/technologies/linux-platforms/articles/relationship-between-fedora-and-rhel">Learn more about the relationship between Red Hat and Fedora »</a></p>
|
||||
<p class="copy">© 2017 Red Hat, Inc. and others. Please send any comments or corrections to the <a href="https://pagure.io/fedora-docs/docs-fp-o">documentation team</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- /row of widgets -->
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
|
||||
<!-- Include all compiled plugins (below), or include individual files as needed -->
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
|
||||
</body>
|
||||
</html>
|
Before Width: | Height: | Size: 5.3 KiB |
Before Width: | Height: | Size: 1.5 KiB |
|
@ -1,61 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
version="1.0"
|
||||
width="220"
|
||||
height="70"
|
||||
id="svg6180">
|
||||
<defs
|
||||
id="defs6182" />
|
||||
<g
|
||||
transform="translate(-266.55899,-345.34488)"
|
||||
id="layer1">
|
||||
<path
|
||||
d="m 316.7736,397.581 c 0,0 0,0 -20.53889,0 0.3327,4.45245 3.92157,7.77609 8.70715,7.77609 3.38983,0 6.31456,-1.39616 8.64094,-3.65507 0.46553,-0.46679 0.99726,-0.59962 1.59519,-0.59962 0.79781,0 1.59561,0.39932 2.12692,1.06388 0.3327,0.46553 0.53216,0.99726 0.53216,1.52857 0,0.73118 -0.3327,1.52857 -0.93106,2.12734 -2.7919,2.99052 -7.51086,4.98503 -12.16403,4.98503 -8.44149,0 -15.22074,-6.77967 -15.22074,-15.22158 0,-8.44149 6.58022,-15.22074 15.02171,-15.22074 8.37529,0 14.62323,6.51317 14.62323,15.08749 0,1.26418 -1.12924,2.12861 -2.39258,2.12861 z m -12.23065,-11.76512 c -4.45329,0 -7.51085,2.92473 -8.17499,7.17731 10.03626,0 16.35083,0 16.35083,0 -0.59836,-4.05355 -3.78874,-7.17731 -8.17584,-7.17731 z"
|
||||
id="path11"
|
||||
style="fill:#3c6eb4" />
|
||||
<path
|
||||
d="m 375.46344,410.80807 c -8.44106,0 -15.22074,-6.77968 -15.22074,-15.22159 0,-8.44149 6.77968,-15.22074 15.22074,-15.22074 8.44234,0 15.22159,6.77925 15.22159,15.22074 -4.2e-4,8.44149 -6.77968,15.22159 -15.22159,15.22159 z m 0,-24.65992 c -5.31688,0 -8.77377,4.25427 -8.77377,9.43833 0,5.18364 3.45689,9.43833 8.77377,9.43833 5.31731,0 8.77504,-4.25469 8.77504,-9.43833 -4.2e-4,-5.18406 -3.45773,-9.43833 -8.77504,-9.43833 z"
|
||||
id="path13"
|
||||
style="fill:#3c6eb4" />
|
||||
<path
|
||||
d="m 412.66183,380.36574 c -4.45963,0 -7.40966,1.319 -10.01391,4.62956 l -0.24036,-1.53995 0,0 c -0.20198,-1.60743 -1.57326,-2.84926 -3.23382,-2.84926 -1.80139,0 -3.26206,1.459 -3.26206,3.26081 0,0.003 0,0.005 0,0.008 l 0,0 0,0.003 0,0 0,23.40712 c 0,1.79464 1.46194,3.25743 3.257,3.25743 1.79465,0 3.25744,-1.46279 3.25744,-3.25743 l 0,-12.56209 c 0,-5.71621 4.98502,-8.57432 10.23613,-8.57432 1.59519,0 2.85726,-1.32953 2.85726,-2.92515 0,-1.59561 -1.26207,-2.85726 -2.85768,-2.85726 z"
|
||||
id="path15"
|
||||
style="fill:#3c6eb4" />
|
||||
<path
|
||||
d="m 447.02614,395.58648 c 0.0666,-8.17541 -5.78326,-15.22074 -15.222,-15.22074 -8.44192,0 -15.28779,6.77925 -15.28779,15.22074 0,8.44191 6.64684,15.22159 14.68985,15.22159 4.01434,0 7.62682,-2.06621 9.23846,-4.22518 l 0.79359,2.01434 0,0 c 0.42589,1.13177 1.5176,1.93717 2.7978,1.93717 1.65001,0 2.98756,-1.33671 2.99009,-2.98545 l 0,0 0,-7.80687 0,0 0,-4.1556 z m -15.222,9.43833 c -5.31773,0 -8.77419,-4.25469 -8.77419,-9.43833 0,-5.18406 3.45604,-9.43833 8.77419,-9.43833 5.3173,0 8.77419,4.25427 8.77419,9.43833 0,5.18364 -3.45689,9.43833 -8.77419,9.43833 z"
|
||||
id="path17"
|
||||
style="fill:#3c6eb4" />
|
||||
<path
|
||||
d="m 355.01479,368.3337 c 0,-1.7938 -1.46194,-3.18997 -3.25659,-3.18997 -1.79422,0 -3.25743,1.39659 -3.25743,3.18997 l 0,17.1499 c -1.66097,-3.05756 -5.25026,-5.11786 -9.50495,-5.11786 -8.64052,0 -14.42336,6.51318 -14.42336,15.22074 0,8.70757 5.98229,15.22159 14.42336,15.22159 3.76555,0 7.03057,-1.55429 8.98587,-4.25554 l 0.72317,1.83428 c 0.44782,1.25912 1.64917,2.16024 3.06051,2.16024 1.78621,0 3.24984,-1.45435 3.24984,-3.24815 0,-0.005 0,-0.009 0,-0.0139 l 0,0 0,-38.95128 -4.2e-4,0 z m -15.22116,36.69111 c -5.31731,0 -8.70715,-4.25469 -8.70715,-9.43833 0,-5.18406 3.38984,-9.43833 8.70715,-9.43833 5.31773,0 8.70714,4.0544 8.70714,9.43833 0,5.38309 -3.38941,9.43833 -8.70714,9.43833 z"
|
||||
id="path19"
|
||||
style="fill:#3c6eb4" />
|
||||
<path
|
||||
d="m 287.21553,365.34023 c -0.59414,-0.0877 -1.19966,-0.13198 -1.80097,-0.13198 -6.73118,0 -12.20746,5.4767 -12.20746,12.20788 l 0,3.8132 -3.98903,0 c -1.46237,0 -2.65908,1.19671 -2.65908,2.65781 0,1.46321 1.19671,2.93738 2.65908,2.93738 l 3.98819,0 0,20.46004 c 0,1.79464 1.46236,3.25743 3.25658,3.25743 1.79507,0 3.25744,-1.46279 3.25744,-3.25743 l 0,-20.46004 4.40986,0 c 1.46194,0 2.65823,-1.47417 2.65823,-2.93738 0,-1.46152 -1.19629,-2.65823 -2.65823,-2.65823 l -4.40733,0 0,-3.8132 c 0,-3.13852 2.55323,-6.11469 5.69175,-6.11469 0.28294,0 0.56757,0.0211 0.84672,0.062 1.78031,0.26355 3.4358,-0.54269 3.70019,-2.32342 0.2627,-1.77904 -0.96606,-3.43538 -2.74594,-3.69935 z"
|
||||
id="path21"
|
||||
style="fill:#3c6eb4" />
|
||||
<path
|
||||
d="m 482.01243,363.57426 c 0,-10.06788 -8.16108,-18.22938 -18.22897,-18.22938 -10.06282,0 -18.22179,8.15475 -18.22854,18.21631 l -4.2e-4,-4.2e-4 0,14.1071 4.2e-4,4.2e-4 c 0.005,2.28463 1.85832,4.13409 4.14463,4.13409 0.007,0 0.0127,-8.4e-4 0.0194,-8.4e-4 l 0.001,8.4e-4 14.07083,0 0,0 c 10.06409,-0.004 18.22138,-8.16276 18.22138,-18.22812 z"
|
||||
id="path25"
|
||||
style="fill:#294172" />
|
||||
<path
|
||||
d="m 469.13577,349.66577 c -4.72528,0 -8.55576,3.83049 -8.55576,8.55577 0,0.002 0,0.004 0,0.006 l 0,4.52836 -4.51444,0 c -8.5e-4,0 -8.5e-4,0 -0.001,0 -4.72528,0 -8.55576,3.81193 -8.55576,8.53678 0,4.72528 3.83048,8.55577 8.55576,8.55577 4.72486,0 8.55534,-3.83049 8.55534,-8.55577 0,-0.002 0,-0.004 0,-0.006 l 0,-4.54733 4.51444,0 c 8.5e-4,0 0.001,0 0.002,0 4.72486,0 8.55534,-3.79296 8.55534,-8.51781 0,-4.72528 -3.83048,-8.55577 -8.55534,-8.55577 z m -8.55576,21.63483 c -0.004,2.48998 -2.02446,4.50811 -4.51571,4.50811 -2.49378,0 -4.53426,-2.02193 -4.53426,-4.5157 0,-2.49421 2.04048,-4.55366 4.53426,-4.55366 0.002,0 0.004,4.2e-4 0.006,4.2e-4 l 3.86971,0 c 0.001,0 0.002,-4.2e-4 0.003,-4.2e-4 0.35209,0 0.63799,0.28505 0.63799,0.63715 0,4.2e-4 -4.2e-4,8.4e-4 -4.2e-4,0.001 l 0,3.92284 -4.2e-4,0 z m 8.55534,-8.5448 c -0.001,0 -0.003,0 -0.004,0 l -3.87223,0 c -8.4e-4,0 -0.002,0 -0.002,0 -0.35252,0 -0.63757,-0.28506 -0.63757,-0.63758 l 0,-4.2e-4 0,-3.90343 c 0.004,-2.49083 2.02446,-4.50854 4.51571,-4.50854 2.49378,0 4.53468,2.02193 4.53468,4.51613 4.2e-4,2.49336 -2.04048,4.53384 -4.53426,4.53384 z"
|
||||
id="path29"
|
||||
style="fill:#3c6eb4" />
|
||||
<path
|
||||
d="m 460.58001,362.7558 0,-4.52836 c 0,-0.002 0,-0.004 0,-0.006 0,-4.72528 3.83048,-8.55577 8.55576,-8.55577 0.71685,0 1.22623,0.0805 1.88952,0.25469 0.96774,0.25385 1.75796,1.04618 1.75838,1.96922 4.2e-4,1.11575 -0.80919,1.92621 -2.0194,1.92621 -0.57642,0 -0.78473,-0.11048 -1.62892,-0.11048 -2.49125,0 -4.51149,2.01771 -4.51571,4.50854 l 0,3.90385 0,4.2e-4 c 0,0.35252 0.28505,0.63758 0.63757,0.63758 4.3e-4,0 0.001,0 0.002,0 l 2.96521,0 c 1.10521,0 1.99747,0.88467 1.99832,1.99283 0,1.10816 -0.89353,1.99114 -1.99832,1.99114 l -3.60489,0 0,4.54733 c 0,0.002 0,0.004 0,0.006 0,4.72485 -3.83048,8.55534 -8.55534,8.55534 -0.71684,0 -1.22623,-0.0805 -1.88952,-0.25469 -0.96774,-0.25343 -1.75838,-1.04618 -1.7588,-1.9688 0,-1.11575 0.80919,-1.92663 2.01982,-1.92663 0.576,0 0.78473,0.11048 1.6285,0.11048 2.49125,0 4.51191,-2.01771 4.51613,-4.50811 0,0 0,-3.92368 0,-3.9241 0,-0.35168 -0.2859,-0.63673 -0.63799,-0.63673 -4.3e-4,0 -8.5e-4,0 -0.002,0 l -2.96521,-4.2e-4 c -1.10521,0 -1.99831,-0.88214 -1.99831,-1.9903 -4.3e-4,-1.11533 0.90238,-1.99367 2.01939,-1.99367 l 3.58339,0 0,0 z"
|
||||
id="path31"
|
||||
style="fill:#ffffff" />
|
||||
<path
|
||||
d="m 477.41661,378.55292 2.81558,0 0,0.37898 -1.18152,0 0,2.94935 -0.45254,0 0,-2.94935 -1.18152,0 0,-0.37898 m 3.26144,0 0.67101,0 0.84937,2.26496 0.85381,-2.26496 0.67102,0 0,3.32833 -0.43917,0 0,-2.9226 -0.85828,2.28279 -0.45255,0 -0.85827,-2.28279 0,2.9226 -0.43694,0 0,-3.32833"
|
||||
id="text6223"
|
||||
style="fill:#294172;enable-background:new" />
|
||||
</g>
|
||||
<path
|
||||
d="m 181.98344,61.675273 2.81558,0 0,0.37898 -1.18152,0 0,2.94935 -0.45254,0 0,-2.94935 -1.18152,0 0,-0.37898 m 3.26144,0 0.67101,0 0.84937,2.26496 0.85381,-2.26496 0.67102,0 0,3.32833 -0.43917,0 0,-2.9226 -0.85828,2.28279 -0.45255,0 -0.85827,-2.28279 0,2.9226 -0.43694,0 0,-3.32833"
|
||||
id="path2391"
|
||||
style="fill:#294172;enable-background:new" />
|
||||
</svg>
|
Before Width: | Height: | Size: 7.6 KiB |
Before Width: | Height: | Size: 3.9 KiB |
6
_javascripts/bootstrap-offcanvas.js
vendored
|
@ -1,6 +0,0 @@
|
|||
$(document).ready(function () {
|
||||
$('[data-toggle="offcanvas"]').click(function () {
|
||||
$('.sidebar').show();
|
||||
$('.row-offcanvas').toggleClass('active');
|
||||
});
|
||||
});
|
|
@ -1,135 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags -->
|
||||
|
||||
<title>Fedora Documentation Website</title>
|
||||
|
||||
<!-- Bootstrap -->
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap-theme.min.css">
|
||||
|
||||
<link rel="stylesheet" href="https://overpass-30e2.kxcdn.com/overpass.css">
|
||||
<link rel="stylesheet" href="_stylesheets/asciibinder.css">
|
||||
|
||||
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
|
||||
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
|
||||
<!--[if lt IE 9]>
|
||||
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
|
||||
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
|
||||
<![endif]-->
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="page-header">
|
||||
<img src="/_images/fedora.svg" class="img-responsive" />
|
||||
<h2><strong>Fedora Documentation Site</strong></h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<h4><strong>Fedora Documentation - 404 Page Not Found :(</strong></h4>
|
||||
<p>Hi! You've arrived at Fedora documentation page which does not actually exist. This may be because you followed a link to an older document which has been retired. For reference, you can find those in our <a href="https://docs-old.fedoraproject.org/">old document archive</a>. Or, you can browse <a href="https://docs.fedoraproject.org/">current docs</a>.</p>
|
||||
<p>It may also be that this page _should_ exist, but sadly does not. If this is the case, and you know what it should say, you can <a href="https://pagure.io/fedora-docs">contribute via the Docs Project</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="bottom" class="text-muted py-3" >
|
||||
<div class="foot">
|
||||
<div class="container">
|
||||
<div class="row footerlinks">
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">About</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Overview">About Fedora</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/sponsors">Sponsors</a></dd>
|
||||
<dd><a href="https://fedoramagazine.org">Fedora Magazine</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Legal:Main#Legal">Legal</a></dd>
|
||||
</dl>
|
||||
<ul class="list-inline">
|
||||
<li>
|
||||
<a href="https:https://www.facebook.com/TheFedoraProject" class="btn-social btn-outline"><i class="fa fa-fw fa-facebook"></i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https:https://plus.google.com/112917221531140868607" class="btn-social btn-outline"><i class="fa fa-fw fa-google-plus"></i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https:https://twitter.com/fedora" class="btn-social btn-outline"><i class="fa fa-fw fa-twitter"></i></a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title uppercase">Download</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://getfedora.org/en/workstation/download">Get Fedora Workstation</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/server/download">Get Fedora Server</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/atomic/download">Get Fedora Atomic</a></dd>
|
||||
<dd><a href="https://spins.fedoraproject.org">Fedora Spins</a></dd>
|
||||
<dd><a href="https://labs.fedoraproject.org">Fedora Labs</a></dd>
|
||||
<dd><a href="https://arm.fedoraproject.org">Fedora ARM<span class="sup">®</span></a></dd>
|
||||
<dd><a href="https://alt.fedoraproject.org/">Alternative Downloads</a></dd>
|
||||
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">Support</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Communicating_and_getting_help">Get Help</a></dd>
|
||||
<dd><a href="https://ask.fedoraproject.org/">Ask Fedora</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Common_F27_bugs">Common Bugs</a></dd>
|
||||
<dd><a href="https://developer.fedoraproject.org/">Fedora Developer Portal</a></dd>
|
||||
<dd><a href="https://docs.fedoraproject.org/f27/install-guide/index.html">Installation Guide</a></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">Join</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Join">Join Fedora</a></dd>
|
||||
<dd><a href="http://fedoraplanet.org">Planet Fedora</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/SIGs">Fedora SIGs</a></dd>
|
||||
<dd><a href="https://admin.fedoraproject.org/accounts/">Fedora Account System</a></dd>
|
||||
<dd><a href="https://fedoracommunity.org/">Fedora Community</a></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- /row of widgets -->
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-2">
|
||||
<div class="widget-body">
|
||||
<a href="https://www.redhat.com/"><img class="rh-logo" src="_images/redhat-logo.png" alt="Red Hat Logo" /></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-7">
|
||||
<div class="widget-body">
|
||||
<p class="sponsor">Fedora is sponsored by Red Hat.</p>
|
||||
<p class="sponsor"><a href="https://www.redhat.com/en/technologies/linux-platforms/articles/relationship-between-fedora-and-rhel">Learn more about the relationship between Red Hat and Fedora »</a></p>
|
||||
<p class="copy">© 2017 Red Hat, Inc. and others. Please send any comments or corrections to the <a href="https://pagure.io/fedora-docs/docs-fp-o">documentation team</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- /row of widgets -->
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
|
||||
<!-- Include all compiled plugins (below), or include individual files as needed -->
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
|
||||
</body>
|
||||
</html>
|
Before Width: | Height: | Size: 5.3 KiB |
Before Width: | Height: | Size: 1.5 KiB |
|
@ -1,61 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
version="1.0"
|
||||
width="220"
|
||||
height="70"
|
||||
id="svg6180">
|
||||
<defs
|
||||
id="defs6182" />
|
||||
<g
|
||||
transform="translate(-266.55899,-345.34488)"
|
||||
id="layer1">
|
||||
<path
|
||||
d="m 316.7736,397.581 c 0,0 0,0 -20.53889,0 0.3327,4.45245 3.92157,7.77609 8.70715,7.77609 3.38983,0 6.31456,-1.39616 8.64094,-3.65507 0.46553,-0.46679 0.99726,-0.59962 1.59519,-0.59962 0.79781,0 1.59561,0.39932 2.12692,1.06388 0.3327,0.46553 0.53216,0.99726 0.53216,1.52857 0,0.73118 -0.3327,1.52857 -0.93106,2.12734 -2.7919,2.99052 -7.51086,4.98503 -12.16403,4.98503 -8.44149,0 -15.22074,-6.77967 -15.22074,-15.22158 0,-8.44149 6.58022,-15.22074 15.02171,-15.22074 8.37529,0 14.62323,6.51317 14.62323,15.08749 0,1.26418 -1.12924,2.12861 -2.39258,2.12861 z m -12.23065,-11.76512 c -4.45329,0 -7.51085,2.92473 -8.17499,7.17731 10.03626,0 16.35083,0 16.35083,0 -0.59836,-4.05355 -3.78874,-7.17731 -8.17584,-7.17731 z"
|
||||
id="path11"
|
||||
style="fill:#3c6eb4" />
|
||||
<path
|
||||
d="m 375.46344,410.80807 c -8.44106,0 -15.22074,-6.77968 -15.22074,-15.22159 0,-8.44149 6.77968,-15.22074 15.22074,-15.22074 8.44234,0 15.22159,6.77925 15.22159,15.22074 -4.2e-4,8.44149 -6.77968,15.22159 -15.22159,15.22159 z m 0,-24.65992 c -5.31688,0 -8.77377,4.25427 -8.77377,9.43833 0,5.18364 3.45689,9.43833 8.77377,9.43833 5.31731,0 8.77504,-4.25469 8.77504,-9.43833 -4.2e-4,-5.18406 -3.45773,-9.43833 -8.77504,-9.43833 z"
|
||||
id="path13"
|
||||
style="fill:#3c6eb4" />
|
||||
<path
|
||||
d="m 412.66183,380.36574 c -4.45963,0 -7.40966,1.319 -10.01391,4.62956 l -0.24036,-1.53995 0,0 c -0.20198,-1.60743 -1.57326,-2.84926 -3.23382,-2.84926 -1.80139,0 -3.26206,1.459 -3.26206,3.26081 0,0.003 0,0.005 0,0.008 l 0,0 0,0.003 0,0 0,23.40712 c 0,1.79464 1.46194,3.25743 3.257,3.25743 1.79465,0 3.25744,-1.46279 3.25744,-3.25743 l 0,-12.56209 c 0,-5.71621 4.98502,-8.57432 10.23613,-8.57432 1.59519,0 2.85726,-1.32953 2.85726,-2.92515 0,-1.59561 -1.26207,-2.85726 -2.85768,-2.85726 z"
|
||||
id="path15"
|
||||
style="fill:#3c6eb4" />
|
||||
<path
|
||||
d="m 447.02614,395.58648 c 0.0666,-8.17541 -5.78326,-15.22074 -15.222,-15.22074 -8.44192,0 -15.28779,6.77925 -15.28779,15.22074 0,8.44191 6.64684,15.22159 14.68985,15.22159 4.01434,0 7.62682,-2.06621 9.23846,-4.22518 l 0.79359,2.01434 0,0 c 0.42589,1.13177 1.5176,1.93717 2.7978,1.93717 1.65001,0 2.98756,-1.33671 2.99009,-2.98545 l 0,0 0,-7.80687 0,0 0,-4.1556 z m -15.222,9.43833 c -5.31773,0 -8.77419,-4.25469 -8.77419,-9.43833 0,-5.18406 3.45604,-9.43833 8.77419,-9.43833 5.3173,0 8.77419,4.25427 8.77419,9.43833 0,5.18364 -3.45689,9.43833 -8.77419,9.43833 z"
|
||||
id="path17"
|
||||
style="fill:#3c6eb4" />
|
||||
<path
|
||||
d="m 355.01479,368.3337 c 0,-1.7938 -1.46194,-3.18997 -3.25659,-3.18997 -1.79422,0 -3.25743,1.39659 -3.25743,3.18997 l 0,17.1499 c -1.66097,-3.05756 -5.25026,-5.11786 -9.50495,-5.11786 -8.64052,0 -14.42336,6.51318 -14.42336,15.22074 0,8.70757 5.98229,15.22159 14.42336,15.22159 3.76555,0 7.03057,-1.55429 8.98587,-4.25554 l 0.72317,1.83428 c 0.44782,1.25912 1.64917,2.16024 3.06051,2.16024 1.78621,0 3.24984,-1.45435 3.24984,-3.24815 0,-0.005 0,-0.009 0,-0.0139 l 0,0 0,-38.95128 -4.2e-4,0 z m -15.22116,36.69111 c -5.31731,0 -8.70715,-4.25469 -8.70715,-9.43833 0,-5.18406 3.38984,-9.43833 8.70715,-9.43833 5.31773,0 8.70714,4.0544 8.70714,9.43833 0,5.38309 -3.38941,9.43833 -8.70714,9.43833 z"
|
||||
id="path19"
|
||||
style="fill:#3c6eb4" />
|
||||
<path
|
||||
d="m 287.21553,365.34023 c -0.59414,-0.0877 -1.19966,-0.13198 -1.80097,-0.13198 -6.73118,0 -12.20746,5.4767 -12.20746,12.20788 l 0,3.8132 -3.98903,0 c -1.46237,0 -2.65908,1.19671 -2.65908,2.65781 0,1.46321 1.19671,2.93738 2.65908,2.93738 l 3.98819,0 0,20.46004 c 0,1.79464 1.46236,3.25743 3.25658,3.25743 1.79507,0 3.25744,-1.46279 3.25744,-3.25743 l 0,-20.46004 4.40986,0 c 1.46194,0 2.65823,-1.47417 2.65823,-2.93738 0,-1.46152 -1.19629,-2.65823 -2.65823,-2.65823 l -4.40733,0 0,-3.8132 c 0,-3.13852 2.55323,-6.11469 5.69175,-6.11469 0.28294,0 0.56757,0.0211 0.84672,0.062 1.78031,0.26355 3.4358,-0.54269 3.70019,-2.32342 0.2627,-1.77904 -0.96606,-3.43538 -2.74594,-3.69935 z"
|
||||
id="path21"
|
||||
style="fill:#3c6eb4" />
|
||||
<path
|
||||
d="m 482.01243,363.57426 c 0,-10.06788 -8.16108,-18.22938 -18.22897,-18.22938 -10.06282,0 -18.22179,8.15475 -18.22854,18.21631 l -4.2e-4,-4.2e-4 0,14.1071 4.2e-4,4.2e-4 c 0.005,2.28463 1.85832,4.13409 4.14463,4.13409 0.007,0 0.0127,-8.4e-4 0.0194,-8.4e-4 l 0.001,8.4e-4 14.07083,0 0,0 c 10.06409,-0.004 18.22138,-8.16276 18.22138,-18.22812 z"
|
||||
id="path25"
|
||||
style="fill:#294172" />
|
||||
<path
|
||||
d="m 469.13577,349.66577 c -4.72528,0 -8.55576,3.83049 -8.55576,8.55577 0,0.002 0,0.004 0,0.006 l 0,4.52836 -4.51444,0 c -8.5e-4,0 -8.5e-4,0 -0.001,0 -4.72528,0 -8.55576,3.81193 -8.55576,8.53678 0,4.72528 3.83048,8.55577 8.55576,8.55577 4.72486,0 8.55534,-3.83049 8.55534,-8.55577 0,-0.002 0,-0.004 0,-0.006 l 0,-4.54733 4.51444,0 c 8.5e-4,0 0.001,0 0.002,0 4.72486,0 8.55534,-3.79296 8.55534,-8.51781 0,-4.72528 -3.83048,-8.55577 -8.55534,-8.55577 z m -8.55576,21.63483 c -0.004,2.48998 -2.02446,4.50811 -4.51571,4.50811 -2.49378,0 -4.53426,-2.02193 -4.53426,-4.5157 0,-2.49421 2.04048,-4.55366 4.53426,-4.55366 0.002,0 0.004,4.2e-4 0.006,4.2e-4 l 3.86971,0 c 0.001,0 0.002,-4.2e-4 0.003,-4.2e-4 0.35209,0 0.63799,0.28505 0.63799,0.63715 0,4.2e-4 -4.2e-4,8.4e-4 -4.2e-4,0.001 l 0,3.92284 -4.2e-4,0 z m 8.55534,-8.5448 c -0.001,0 -0.003,0 -0.004,0 l -3.87223,0 c -8.4e-4,0 -0.002,0 -0.002,0 -0.35252,0 -0.63757,-0.28506 -0.63757,-0.63758 l 0,-4.2e-4 0,-3.90343 c 0.004,-2.49083 2.02446,-4.50854 4.51571,-4.50854 2.49378,0 4.53468,2.02193 4.53468,4.51613 4.2e-4,2.49336 -2.04048,4.53384 -4.53426,4.53384 z"
|
||||
id="path29"
|
||||
style="fill:#3c6eb4" />
|
||||
<path
|
||||
d="m 460.58001,362.7558 0,-4.52836 c 0,-0.002 0,-0.004 0,-0.006 0,-4.72528 3.83048,-8.55577 8.55576,-8.55577 0.71685,0 1.22623,0.0805 1.88952,0.25469 0.96774,0.25385 1.75796,1.04618 1.75838,1.96922 4.2e-4,1.11575 -0.80919,1.92621 -2.0194,1.92621 -0.57642,0 -0.78473,-0.11048 -1.62892,-0.11048 -2.49125,0 -4.51149,2.01771 -4.51571,4.50854 l 0,3.90385 0,4.2e-4 c 0,0.35252 0.28505,0.63758 0.63757,0.63758 4.3e-4,0 0.001,0 0.002,0 l 2.96521,0 c 1.10521,0 1.99747,0.88467 1.99832,1.99283 0,1.10816 -0.89353,1.99114 -1.99832,1.99114 l -3.60489,0 0,4.54733 c 0,0.002 0,0.004 0,0.006 0,4.72485 -3.83048,8.55534 -8.55534,8.55534 -0.71684,0 -1.22623,-0.0805 -1.88952,-0.25469 -0.96774,-0.25343 -1.75838,-1.04618 -1.7588,-1.9688 0,-1.11575 0.80919,-1.92663 2.01982,-1.92663 0.576,0 0.78473,0.11048 1.6285,0.11048 2.49125,0 4.51191,-2.01771 4.51613,-4.50811 0,0 0,-3.92368 0,-3.9241 0,-0.35168 -0.2859,-0.63673 -0.63799,-0.63673 -4.3e-4,0 -8.5e-4,0 -0.002,0 l -2.96521,-4.2e-4 c -1.10521,0 -1.99831,-0.88214 -1.99831,-1.9903 -4.3e-4,-1.11533 0.90238,-1.99367 2.01939,-1.99367 l 3.58339,0 0,0 z"
|
||||
id="path31"
|
||||
style="fill:#ffffff" />
|
||||
<path
|
||||
d="m 477.41661,378.55292 2.81558,0 0,0.37898 -1.18152,0 0,2.94935 -0.45254,0 0,-2.94935 -1.18152,0 0,-0.37898 m 3.26144,0 0.67101,0 0.84937,2.26496 0.85381,-2.26496 0.67102,0 0,3.32833 -0.43917,0 0,-2.9226 -0.85828,2.28279 -0.45255,0 -0.85827,-2.28279 0,2.9226 -0.43694,0 0,-3.32833"
|
||||
id="text6223"
|
||||
style="fill:#294172;enable-background:new" />
|
||||
</g>
|
||||
<path
|
||||
d="m 181.98344,61.675273 2.81558,0 0,0.37898 -1.18152,0 0,2.94935 -0.45254,0 0,-2.94935 -1.18152,0 0,-0.37898 m 3.26144,0 0.67101,0 0.84937,2.26496 0.85381,-2.26496 0.67102,0 0,3.32833 -0.43917,0 0,-2.9226 -0.85828,2.28279 -0.45255,0 -0.85827,-2.28279 0,2.9226 -0.43694,0 0,-3.32833"
|
||||
id="path2391"
|
||||
style="fill:#294172;enable-background:new" />
|
||||
</svg>
|
Before Width: | Height: | Size: 7.6 KiB |
Before Width: | Height: | Size: 3.9 KiB |
|
@ -1,598 +0,0 @@
|
|||
@import url(https://maxcdn.bootstrapcdn.com/font-awesome/4.1.0/css/font-awesome.min.css);
|
||||
/* ------------------------------------------------------------
|
||||
Image: "Spin" https://www.flickr.com/photos/eflon/3655695161/
|
||||
Author: eflon https://www.flickr.com/photos/eflon/
|
||||
License: https://creativecommons.org/licenses/by/2.0/
|
||||
---------------------------------------------------------------*/
|
||||
.attribution {
|
||||
text-align: center;
|
||||
position: relative;
|
||||
bottom: -20px;
|
||||
}
|
||||
.attribution .btn {
|
||||
color: #808080;
|
||||
color: rgba(175,175,175, .65);
|
||||
font-size: 11px;
|
||||
}
|
||||
.attribution .btn:hover {
|
||||
text-decoration: none;
|
||||
color: #aaa;
|
||||
}
|
||||
.popover-content {
|
||||
font-size: 12px;
|
||||
line-height: 1.3;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 980px) {
|
||||
body {
|
||||
margin-bottom: 200px;
|
||||
}
|
||||
footer {
|
||||
text-align: center;
|
||||
}
|
||||
footer .text-right {
|
||||
text-align: center !important;
|
||||
}
|
||||
#footer_social .first {
|
||||
margin-left: 0;
|
||||
}
|
||||
#footer_social > a {
|
||||
top: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
.fa-inverse:hover {
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
.collapse a.active {
|
||||
background-color: #DEEAF4;
|
||||
color: #000;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.collapse a.active:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.collapse a.active:before {
|
||||
background-color: #A0C3E5;
|
||||
content: "";
|
||||
display: inline-block;
|
||||
height: 100%;
|
||||
left: 0;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
width: 3px;
|
||||
}
|
||||
|
||||
.main h2, .main .h2 {
|
||||
border-top: 0px;
|
||||
padding-top: 10px;
|
||||
font-size: 28px;
|
||||
}
|
||||
|
||||
.page-header {
|
||||
height: 100% !important;
|
||||
}
|
||||
.page-header .img-responsive {
|
||||
display: inline;
|
||||
}
|
||||
.page-header h2 {
|
||||
font-size: 32px;
|
||||
display: inline;
|
||||
vertical-align: bottom;
|
||||
}
|
||||
|
||||
.navbar-brand {
|
||||
padding: initial;
|
||||
height: initial;
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
.navbar-header h2 {
|
||||
display: inline;
|
||||
position: absolute;
|
||||
font-weight: bold;
|
||||
margin-top: 50px ;
|
||||
}
|
||||
|
||||
.nav > li > a.hover{
|
||||
background-color: none;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6 {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
h2 > a.anchor, h3 > a.anchor, h4 > a.anchor, h5 > a.anchor, h6 > a.anchor {
|
||||
display: block;
|
||||
font-weight: normal;
|
||||
margin-left: -1.5ex;
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
text-decoration: none !important;
|
||||
visibility: hidden;
|
||||
width: 1.5ex;
|
||||
z-index: 1001;
|
||||
}
|
||||
|
||||
h2 > a.anchor:before, h3 > a.anchor:before, h4 > a.anchor:before, h5 > a.anchor:before, h6 > a.anchor:before {
|
||||
content: "\f0c1";
|
||||
display: block;
|
||||
font-family: FontAwesome;
|
||||
font-size: 0.7em;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
padding-top: 0.2em;
|
||||
}
|
||||
|
||||
h4 > a.anchor:before, h5 > a.anchor:before, h6 > a.anchor:before {
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
h2:hover > a.anchor,
|
||||
h2 > a.anchor:hover,
|
||||
h3:hover > a.anchor,
|
||||
h3 > a.anchor:hover,
|
||||
h4:hover > a.anchor,
|
||||
h4 > a.anchor:hover,
|
||||
h5:hover > a.anchor,
|
||||
h5 > a.anchor:hover,
|
||||
h6:hover > a.anchor,
|
||||
h6 > a.anchor:hover {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.main {
|
||||
border-left: 1px solid #e7e7e7;
|
||||
margin-left: -1px;
|
||||
padding-left: 25px;
|
||||
}
|
||||
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.main {
|
||||
padding-left: 30px;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Sidebar
|
||||
*/
|
||||
|
||||
.nav-header {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.nav-header ul {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.nav-header ul li a {
|
||||
display: block;
|
||||
padding: 5px 20px 5px 25px;
|
||||
font-size: 13px;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.nav-sidebar .fa {
|
||||
text-align: center;
|
||||
top: -1px;
|
||||
width: 14px;
|
||||
}
|
||||
|
||||
.nav-sidebar li a {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.nav-sidebar li a:hover {
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.nav-sidebar ul li ul.nav-tertiary li a {
|
||||
padding-left: 50px;
|
||||
}
|
||||
|
||||
.nav-sidebar > li > a {
|
||||
padding: 7px 0;
|
||||
}
|
||||
|
||||
.nav-sidebar > li > a:focus, .nav-sidebar > li > a:hover {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
font-weight: 300;
|
||||
display: none;
|
||||
padding-top: 13px;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 767px) {
|
||||
.sidebar {
|
||||
padding-left: 30px;
|
||||
padding-right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (min-width: 768px) {
|
||||
.sidebar {
|
||||
border-right: 1px solid #e7e7e7;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Off Canvas
|
||||
* --------------------------------------------------
|
||||
*/
|
||||
|
||||
body, html {
|
||||
overflow-x: hidden; /* Prevent scroll on narrow devices */
|
||||
font-family: "Overpass", sans-serif;
|
||||
}
|
||||
|
||||
.toggle-nav {
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 767px) {
|
||||
.row-offcanvas {
|
||||
position: relative;
|
||||
-webkit-transition: all .25s ease-out;
|
||||
-o-transition: all .25s ease-out;
|
||||
transition: all .25s ease-out;
|
||||
}
|
||||
|
||||
.row-offcanvas-right {
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.row-offcanvas-left {
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.row-offcanvas-right
|
||||
.sidebar-offcanvas {
|
||||
right: -75%; /* 8 columns */
|
||||
}
|
||||
|
||||
.row-offcanvas-left
|
||||
.sidebar-offcanvas {
|
||||
left: -75%; /* 8 columns */
|
||||
}
|
||||
|
||||
.row-offcanvas-right.active {
|
||||
right: 75%; /* 8 columns */
|
||||
}
|
||||
|
||||
.row-offcanvas-left.active {
|
||||
left: 75%; /* 8 columns */
|
||||
}
|
||||
|
||||
.sidebar-offcanvas {
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
width: 75%; /* 8 columns */
|
||||
}
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 0 0 1.6em;
|
||||
}
|
||||
|
||||
/* Remnants of Asciidoctor default stylesheet - remove styles as needed */
|
||||
|
||||
#map_canvas img, #map_canvas embed, #map_canvas object, .map_canvas img, .map_canvas embed, .map_canvas object { max-width: none !important; }
|
||||
.left { float: left !important; }
|
||||
.right { float: right !important; }
|
||||
.text-left { text-align: left !important; }
|
||||
.text-right { text-align: right !important; }
|
||||
.text-center { text-align: center !important; }
|
||||
.text-justify { text-align: justify !important; }
|
||||
.hide { display: none; }
|
||||
.subheader, #content #toctitle, .admonitionblock td.content > .title, .audioblock > .title, .exampleblock > .title, .imageblock > .title, .listingblock > .title, .literalblock > .title, .stemblock > .title, .openblock > .title, .paragraph > .title, .quoteblock > .title, table.tableblock > .title, .verseblock > .title, .videoblock > .title, .dlist > .title, .olist > .title, .ulist > .title, .qlist > .title, .hdlist > .title { line-height: 1.4; color: #7a2518; font-weight: 300; margin-top: 0.2em; margin-bottom: 0.5em; }
|
||||
abbr, acronym { text-transform: uppercase; font-size: 90%; color: #333333; border-bottom: 1px dotted #dddddd; cursor: help; }
|
||||
abbr { text-transform: none; }
|
||||
blockquote { margin: 0 0 1.25em; padding: 0.5625em 1.25em 0 1.1875em; border-left: 3px solid #487c58; }
|
||||
blockquote cite { display: block; font-size: inherit; color: #454545; }
|
||||
blockquote cite:before { content: "\2014 \0020"; }
|
||||
blockquote cite a, blockquote cite a:visited { color: #454545; }
|
||||
blockquote, blockquote p { line-height: 1.6; color: #6e6e6e; }
|
||||
@media only screen and (min-width: 768px) {
|
||||
#toctitle, .sidebarblock > .content > .title { line-height: 1.4; }
|
||||
#toctitle, .sidebarblock > .content > .title { font-size: 1.6875em; }
|
||||
}
|
||||
table { background: white; margin-bottom: 1.25em; border: solid 1px #dddddd; }
|
||||
table thead, table tfoot { background: whitesmoke; font-weight: bold; }
|
||||
table thead tr th, table thead tr td, table tfoot tr th, table tfoot tr td { padding: 0.5em 0.625em 0.625em; font-size: inherit; color: #333333; text-align: left; }
|
||||
table tr th, table tr td { padding: 0.5625em 0.625em; font-size: inherit; color: #333333; }
|
||||
table tr.even, table tr.alt, table tr:nth-of-type(even) { background: #f9f9f9; }
|
||||
table thead tr th, table tfoot tr th, table tbody tr td, table tr td, table tfoot tr td { display: table-cell; line-height: 1.6; }
|
||||
.clearfix:before, .clearfix:after, .float-group:before, .float-group:after { content: " "; display: table; }
|
||||
.clearfix:after, .float-group:after { clear: both; }
|
||||
*:not(pre) > code { font-size: inherit; padding: 0; white-space: nowrap; background-color: inherit; border: 0 solid #dddddd; -webkit-border-radius: 4px; border-radius: 4px; text-shadow: none; line-height: 1; }
|
||||
.keyseq { color: #666666; }
|
||||
kbd:not(.keyseq) { display: inline-block; color: #333333; font-size: 0.75em; line-height: 1.4; background-color: #f7f7f7; border: 1px solid #ccc; -webkit-border-radius: 3px; border-radius: 3px; -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.2), 0 0 0 2px white inset; box-shadow: 0 1px 0 rgba(0, 0, 0, 0.2), 0 0 0 2px white inset; margin: -0.15em 0.15em 0 0.15em; padding: 0.2em 0.6em 0.2em 0.5em; vertical-align: middle; white-space: nowrap; }
|
||||
.keyseq kbd:first-child { margin-left: 0; }
|
||||
.keyseq kbd:last-child { margin-right: 0; }
|
||||
.menuseq, .menu { color: #1a1a1a; }
|
||||
b.button:before, b.button:after { position: relative; top: -1px; font-weight: normal; }
|
||||
b.button:before { content: "["; padding: 0 3px 0 2px; }
|
||||
b.button:after { content: "]"; padding: 0 2px 0 3px; }
|
||||
p a > code:hover { color: #561309; }
|
||||
#header, #content, #footnotes, #footer { width: 100%; margin-left: auto; margin-right: auto; margin-top: 0; margin-bottom: 0; max-width: 62.5em; *zoom: 1; position: relative; padding-left: 0.9375em; padding-right: 0.9375em; }
|
||||
#header:before, #header:after, #content:before, #content:after, #footnotes:before, #footnotes:after, #footer:before, #footer:after { content: " "; display: table; }
|
||||
#header:after, #content:after, #footnotes:after, #footer:after { clear: both; }
|
||||
#content:before { content: none; }
|
||||
#header { margin-bottom: 2.5em; }
|
||||
#header > h1 { color: black; font-weight: 300; border-bottom: 1px solid #d8d8d8; margin-bottom: -28px; padding-bottom: 32px; }
|
||||
#header span { color: #6e6e6e; }
|
||||
#header #revnumber { text-transform: capitalize; }
|
||||
#header br { display: none; }
|
||||
#header br + span { padding-left: 3px; }
|
||||
#header br + span:before { content: "\2013 \0020"; }
|
||||
#header br + span.author { padding-left: 0; }
|
||||
#header br + span.author:before { content: ", "; }
|
||||
#toc { border-bottom: 3px double #e5e5e5; padding-top: 1em; padding-bottom: 1.25em; }
|
||||
#toc > ul { margin-left: 0.25em; }
|
||||
#toc ul.sectlevel0 > li > a { font-style: italic; }
|
||||
#toc ul.sectlevel0 ul.sectlevel1 { margin-left: 0; margin-top: 0.5em; margin-bottom: 0.5em; }
|
||||
#toc ul { font-family: "Open Sans", "DejaVu Sans", "Sans", sans-serif; list-style-type: none; }
|
||||
#toc a { text-decoration: none; }
|
||||
#toc a:active { text-decoration: underline; }
|
||||
#toctitle { color: #7a2518; }
|
||||
@media only screen and (min-width: 768px) { body.toc2 { padding-left: 15em; padding-right: 0; }
|
||||
#toc.toc2 { background-color: #fafaf9; position: fixed; width: 15em; left: 0; top: 0; border-right: 1px solid #e5e5e5; border-bottom: 0; z-index: 1000; padding: 1.25em 1em; height: 100%; overflow: auto; }
|
||||
#toc.toc2 #toctitle { margin-top: 0; font-size: 1.2em; }
|
||||
#toc.toc2 > ul { font-size: .90em; margin-bottom: 0; }
|
||||
#toc.toc2 ul ul { margin-left: 0; padding-left: 1em; }
|
||||
#toc.toc2 ul.sectlevel0 ul.sectlevel1 { padding-left: 0; margin-top: 0.5em; margin-bottom: 0.5em; }
|
||||
body.toc2.toc-right { padding-left: 0; padding-right: 15em; }
|
||||
body.toc2.toc-right #toc.toc2 { border-right: 0; border-left: 1px solid #e5e5e5; left: auto; right: 0; } }
|
||||
@media only screen and (min-width: 1280px) { body.toc2 { padding-left: 20em; padding-right: 0; }
|
||||
#toc.toc2 { width: 20em; }
|
||||
#toc.toc2 #toctitle { font-size: 1.375em; }
|
||||
#toc.toc2 > ul { font-size: 0.95em; }
|
||||
#toc.toc2 ul ul { padding-left: 1.25em; }
|
||||
body.toc2.toc-right { padding-left: 0; padding-right: 20em; } }
|
||||
#content #toc { border-style: solid; border-width: 1px; border-color: #e3e3dd; margin-bottom: 1.25em; padding: 1.25em; background: #fafaf9; border-width: 0; -webkit-border-radius: 4px; border-radius: 4px; }
|
||||
#content #toc > :first-child { margin-top: 0; }
|
||||
#content #toc > :last-child { margin-bottom: 0; }
|
||||
#content #toctitle { font-size: 1.375em; }
|
||||
#footer { max-width: 100%; background-color: #333333; padding: 1.25em; }
|
||||
#footer-text { color: #cccccc; line-height: 1.44; }
|
||||
.audioblock, .imageblock, .literalblock, .listingblock, .stemblock, .verseblock, .videoblock { margin-bottom: 2.5em; }
|
||||
.admonitionblock td.content > .title, .audioblock > .title, .exampleblock > .title, .imageblock > .title, .listingblock > .title, .literalblock > .title, .stemblock > .title, .openblock > .title, .paragraph > .title, .quoteblock > .title, table.tableblock > .title, .verseblock > .title, .videoblock > .title, .dlist > .title, .olist > .title, .ulist > .title, .qlist > .title, .hdlist > .title { text-rendering: optimizeLegibility; text-align: left; font-family: "Noto Serif", "DejaVu Serif", "Serif", serif; font-weight: normal; font-style: italic; }
|
||||
table.tableblock > caption.title { white-space: nowrap; overflow: visible; max-width: 0; }
|
||||
table.tableblock #preamble > .sectionbody > .paragraph:first-of-type p { font-size: inherit; }
|
||||
.admonitionblock > table { border: 0; background: none; width: 100%; }
|
||||
.admonitionblock > table td.icon { text-align: center; width: 80px; }
|
||||
.admonitionblock > table td.icon img { max-width: none; }
|
||||
.admonitionblock > table td.icon .title { font-weight: 300; text-transform: uppercase; }
|
||||
.admonitionblock > table td.content { padding-left: 0; padding-right: 1.25em; color: #6e6e6e; }
|
||||
.admonitionblock > table td.content > :last-child > :last-child { margin-bottom: 0; }
|
||||
.exampleblock > .content { border-style: solid; border-width: 1px; border-color: #e6e6e6; margin-bottom: 1.25em; padding: 1.25em; background: white; -webkit-border-radius: 4px; border-radius: 4px; }
|
||||
.exampleblock > .content > :first-child { margin-top: 0; }
|
||||
.exampleblock > .content > :last-child { margin-bottom: 0; }
|
||||
.exampleblock > .content h1, .exampleblock > .content h2, .exampleblock > .content h3, .exampleblock > .content #toctitle, .sidebarblock.exampleblock > .content > .title, .exampleblock > .content h4, .exampleblock > .content h5, .exampleblock > .content h6, .exampleblock > .content p { color: #333333; }
|
||||
.exampleblock > .content h1, .exampleblock > .content h2, .exampleblock > .content h3, .exampleblock > .content #toctitle, .sidebarblock.exampleblock > .content > .title, .exampleblock > .content h4, .exampleblock > .content h5, .exampleblock > .content h6 { line-height: 1; margin-bottom: 0.625em; }
|
||||
.exampleblock > .content h1.subheader, .exampleblock > .content h2.subheader, .exampleblock > .content h3.subheader, .exampleblock > .content .subheader#toctitle, .sidebarblock.exampleblock > .content > .subheader.title, .exampleblock > .content h4.subheader, .exampleblock > .content h5.subheader, .exampleblock > .content h6.subheader { line-height: 1.4; }
|
||||
.exampleblock.result > .content { -webkit-box-shadow: 0 1px 8px #e3e3dd; box-shadow: 0 1px 8px #e3e3dd; }
|
||||
.sidebarblock { border-style: solid; border-width: 1px; border-color: #e3e3dd; margin-top: -1.0em; margin-bottom: 1.6em; margin-left: 1em; padding: .5em; background: #F1F3F5; -webkit-border-radius: 4px; border-radius: 4px; overflow-x: auto; float: right; width: 40%; }
|
||||
.sidebarblock > :first-child { margin-top: 0; }
|
||||
.sidebarblock > :last-child { margin-bottom: 0; }
|
||||
.sidebarblock h1, .sidebarblock h2, .sidebarblock h3, .sidebarblock #toctitle, .sidebarblock > .content > .title, .sidebarblock h4, .sidebarblock h5, .sidebarblock h6, .sidebarblock p { color: #333333; }
|
||||
.sidebarblock h1, .sidebarblock h2, .sidebarblock h3, .sidebarblock #toctitle, .sidebarblock > .content > .title, .sidebarblock h4, .sidebarblock h5, .sidebarblock h6 { line-height: 1; margin-bottom: 0.625em; }
|
||||
.sidebarblock h1.subheader, .sidebarblock h2.subheader, .sidebarblock h3.subheader, .sidebarblock .subheader#toctitle, .sidebarblock > .content > .subheader.title, .sidebarblock h4.subheader, .sidebarblock h5.subheader, .sidebarblock h6.subheader { line-height: 1.4; }
|
||||
.sidebarblock > .content > .title { color: inherit; font-size: 28px; font-weight: 500; margin-top: 0; line-height: 1.6; }
|
||||
.width50 { width: 50% ! important}
|
||||
.exampleblock > .content > :last-child > :last-child, .exampleblock > .content .olist > ol > li:last-child > :last-child, .exampleblock > .content .ulist > ul > li:last-child > :last-child, .exampleblock > .content .qlist > ol > li:last-child > :last-child, .sidebarblock > .content > :last-child > :last-child, .sidebarblock > .content .olist > ol > li:last-child > :last-child, .sidebarblock > .content .ulist > ul > li:last-child > :last-child, .sidebarblock > .content .qlist > ol > li:last-child > :last-child { margin-bottom: 0; }
|
||||
.literalblock pre, .literalblock pre[class], .listingblock pre, .listingblock pre[class] { border: 0px; background-color: #F0F3F5; -webkit-border-radius: 5px; border-radius: 5px; padding: 1.5em 2.5em; word-wrap: break-word; }
|
||||
.literalblock pre.nowrap, .literalblock pre[class].nowrap, .listingblock pre.nowrap, .listingblock pre[class].nowrap { overflow-x: auto; white-space: pre; word-wrap: normal; }
|
||||
.literalblock pre > code, .literalblock pre[class] > code, .listingblock pre > code, .listingblock pre[class] > code { display: block; }
|
||||
.listingblock > .content { position: relative; }
|
||||
.listingblock:hover code[class*=" language-"]:before { text-transform: uppercase; font-size: 0.9em; color: #999; position: absolute; top: 0.375em; right: 0.375em; }
|
||||
.listingblock:hover code.asciidoc:before { content: "asciidoc"; }
|
||||
.listingblock:hover code.clojure:before { content: "clojure"; }
|
||||
.listingblock:hover code.css:before { content: "css"; }
|
||||
.listingblock:hover code.go:before { content: "go"; }
|
||||
.listingblock:hover code.groovy:before { content: "groovy"; }
|
||||
.listingblock:hover code.html:before { content: "html"; }
|
||||
.listingblock:hover code.java:before { content: "java"; }
|
||||
.listingblock:hover code.javascript:before { content: "javascript"; }
|
||||
.listingblock:hover code.python:before { content: "python"; }
|
||||
.listingblock:hover code.ruby:before { content: "ruby"; }
|
||||
.listingblock:hover code.sass:before { content: "sass"; }
|
||||
.listingblock:hover code.scss:before { content: "scss"; }
|
||||
.listingblock:hover code.xml:before { content: "xml"; }
|
||||
.listingblock:hover code.yaml:before { content: "yaml"; }
|
||||
.listingblock.terminal pre .command:before { content: attr(data-prompt); padding-right: 0.5em; color: #999; }
|
||||
.listingblock.terminal pre .command:not([data-prompt]):before { content: '$'; }
|
||||
table.pyhltable { border: 0; margin-bottom: 0; }
|
||||
table.pyhltable td { vertical-align: top; padding-top: 0; padding-bottom: 0; }
|
||||
table.pyhltable td.code { padding-left: .75em; padding-right: 0; }
|
||||
.highlight.pygments .lineno, table.pyhltable td:not(.code) { color: #999; padding-left: 0; padding-right: .5em; border-right: 1px solid #d8d8d8; }
|
||||
.highlight.pygments .lineno { display: inline-block; margin-right: .25em; }
|
||||
table.pyhltable .linenodiv { background-color: transparent !important; padding-right: 0 !important; }
|
||||
.quoteblock { margin: 0 0 1.25em 0; padding: 0.5625em 1.25em 0 1.1875em; border-left: 3px solid #487c58; }
|
||||
.quoteblock blockquote { margin: 0 0 1.25em 0; padding: 0 0 0.625em 0; border: 0; }
|
||||
.quoteblock blockquote > .paragraph:last-child p { margin-bottom: 0; }
|
||||
.quoteblock .attribution { margin-top: -0.625em; padding-bottom: 0.625em; font-size: inherit; color: #454545; line-height: 1.6; }
|
||||
.quoteblock .attribution br { display: none; }
|
||||
.quoteblock .attribution cite { display: block; }
|
||||
table.tableblock { max-width: 100%; }
|
||||
table.tableblock td .paragraph:last-child p > p:last-child, table.tableblock th > p:last-child, table.tableblock td > p:last-child { margin-bottom: 0; }
|
||||
table.spread { width: 100%; }
|
||||
table.tableblock, th.tableblock, td.tableblock { border: 0 solid #dddddd; }
|
||||
table.grid-all th.tableblock, table.grid-all td.tableblock { border-width: 0 1px 1px 0; }
|
||||
table.grid-all tfoot > tr > th.tableblock, table.grid-all tfoot > tr > td.tableblock { border-width: 1px 1px 0 0; }
|
||||
table.grid-cols th.tableblock, table.grid-cols td.tableblock { border-width: 0 1px 0 0; }
|
||||
table.grid-all * > tr > .tableblock:last-child, table.grid-cols * > tr > .tableblock:last-child { border-right-width: 0; }
|
||||
table.grid-rows th.tableblock, table.grid-rows td.tableblock { border-width: 0 0 1px 0; }
|
||||
table.grid-all tbody > tr:last-child > th.tableblock, table.grid-all tbody > tr:last-child > td.tableblock, table.grid-all thead:last-child > tr > th.tableblock, table.grid-rows tbody > tr:last-child > th.tableblock, table.grid-rows tbody > tr:last-child > td.tableblock, table.grid-rows thead:last-child > tr > th.tableblock { border-bottom-width: 0; }
|
||||
table.grid-rows tfoot > tr > th.tableblock, table.grid-rows tfoot > tr > td.tableblock { border-width: 1px 0 0 0; }
|
||||
table.frame-all { border-width: 1px; }
|
||||
table.frame-sides { border-width: 0 1px; }
|
||||
table.frame-topbot { border-width: 1px 0; }
|
||||
th.halign-left, td.halign-left { text-align: left; }
|
||||
th.halign-right, td.halign-right { text-align: right; }
|
||||
th.halign-center, td.halign-center { text-align: center; }
|
||||
th.valign-top, td.valign-top { vertical-align: top; }
|
||||
th.valign-bottom, td.valign-bottom { vertical-align: bottom; }
|
||||
th.valign-middle, td.valign-middle { vertical-align: middle; }
|
||||
table thead th, table tfoot th { font-weight: bold; }
|
||||
tbody tr th { display: table-cell; line-height: 1.6; background: whitesmoke; }
|
||||
tbody tr th, tbody tr th p, tfoot tr th, tfoot tr th p { color: #333333; font-weight: bold; }
|
||||
td > div.verse { white-space: pre; }
|
||||
ul.unstyled, ol.unnumbered, ul.checklist, ul.none { list-style-type: none; }
|
||||
ul.unstyled, ol.unnumbered, ul.checklist { margin-left: 0.625em; }
|
||||
ul.checklist li > p:first-child > .fa-check-square-o:first-child, ul.checklist li > p:first-child > input[type="checkbox"]:first-child { margin-right: 0.25em; }
|
||||
ul.checklist li > p:first-child > input[type="checkbox"]:first-child { position: relative; top: 1px; }
|
||||
ul.inline { margin: 0 auto 0.625em auto; margin-left: -1.375em; margin-right: 0; padding: 0; list-style: none; overflow: hidden; }
|
||||
ul.inline > li { list-style: none; float: left; margin-left: 1.375em; display: block; }
|
||||
ul.inline > li > * { display: block; }
|
||||
.unstyled dl dt { font-weight: normal; font-style: normal; }
|
||||
ol.arabic { list-style-type: decimal; }
|
||||
ol.decimal { list-style-type: decimal-leading-zero; }
|
||||
ol.loweralpha { list-style-type: lower-alpha; }
|
||||
ol.upperalpha { list-style-type: upper-alpha; }
|
||||
ol.lowerroman { list-style-type: lower-roman; }
|
||||
ol.upperroman { list-style-type: upper-roman; }
|
||||
ol.lowergreek { list-style-type: lower-greek; }
|
||||
.hdlist > table, .colist > table { border: 0; background: none; }
|
||||
.hdlist > table > tbody > tr, .colist > table > tbody > tr { background: none; }
|
||||
td.hdlist1 { padding-right: .75em; font-weight: bold; }
|
||||
td.hdlist1, td.hdlist2 { vertical-align: top; }
|
||||
.literalblock + .colist, .listingblock + .colist { margin-top: -0.5em; }
|
||||
.colist > table tr > td:first-of-type { padding: 0 .75em; line-height: 1; }
|
||||
.colist > table tr > td:last-of-type { padding: 0.25em 0; }
|
||||
.qanda > ol > li > p > em:only-child { color: #1d4b8f; }
|
||||
.thumb, .th { line-height: 0; display: inline-block; border: solid 4px white; -webkit-box-shadow: 0 0 0 1px #dddddd; box-shadow: 0 0 0 1px #dddddd; }
|
||||
.imageblock.left, .imageblock[style*="float: left"] { margin: 0.25em 0.625em 1.25em 0; }
|
||||
.imageblock.right, .imageblock[style*="float: right"] { margin: 0.25em 0 1.25em 0.625em; }
|
||||
.imageblock > .title { margin-bottom: 0; }
|
||||
.imageblock.thumb, .imageblock.th { border-width: 6px; }
|
||||
.imageblock.thumb > .title, .imageblock.th > .title { padding: 0 0.125em; }
|
||||
.image.left, .image.right { margin-top: 0.25em; margin-bottom: 0.25em; display: inline-block; line-height: 0; }
|
||||
.image.left { margin-right: 0.625em; }
|
||||
.image.right { margin-left: 0.625em; }
|
||||
a.image { text-decoration: none; }
|
||||
span.footnote, span.footnoteref { vertical-align: super; font-size: 0.875em; }
|
||||
span.footnote a, span.footnoteref a { text-decoration: none; }
|
||||
span.footnote a:active, span.footnoteref a:active { text-decoration: underline; }
|
||||
#footnotes { padding-top: 0.75em; padding-bottom: 0.75em; margin-bottom: 0.625em; }
|
||||
#footnotes hr { width: 20%; min-width: 6.25em; margin: -.25em 0 .75em 0; border-width: 1px 0 0 0; }
|
||||
#footnotes .footnote { padding: 0 0.375em; line-height: 1.3; font-size: 0.875em; margin-left: 1.2em; text-indent: -1.2em; margin-bottom: .2em; }
|
||||
#footnotes .footnote a:first-of-type { font-weight: bold; text-decoration: none; }
|
||||
#footnotes .footnote:last-of-type { margin-bottom: 0; }
|
||||
#content #footnotes { margin-top: -0.625em; margin-bottom: 0; padding: 0.75em 0; }
|
||||
.gist .file-data > table { border: none; background: #fff; width: 100%; margin-bottom: 0; }
|
||||
.gist .file-data > table td.line-data { width: 99%; }
|
||||
div.unbreakable { page-break-inside: avoid; }
|
||||
.replaceable { font-style: italic; font-color: inherit; font-family: inherit; }
|
||||
.parameter { font-style: italic; font-family: monospace; }
|
||||
.userinput { font-weight: bold; font-family: monospace; }
|
||||
.envar { font-weight: bold; font-family: monospace; font-size: 90%; }
|
||||
.sysitem { font-weight: bold; font-size: 90%; }
|
||||
.package { font-weight: bold; font-size: 90%; }
|
||||
.filename { font-weight: bold; font-style: italic; font-size: 90%; }
|
||||
.big { font-size: larger; }
|
||||
.small { font-size: smaller; }
|
||||
.underline { text-decoration: underline; }
|
||||
.overline { text-decoration: overline; }
|
||||
.line-through { text-decoration: line-through; }
|
||||
.aqua { color: #00bfbf; }
|
||||
.aqua-background { background-color: #00fafa; }
|
||||
.black { color: black; }
|
||||
.black-background { background-color: black; }
|
||||
.blue { color: #0000bf; }
|
||||
.blue-background { background-color: #0000fa; }
|
||||
.fuchsia { color: #bf00bf; }
|
||||
.fuchsia-background { background-color: #fa00fa; }
|
||||
.gray { color: #606060; }
|
||||
.gray-background { background-color: #7d7d7d; }
|
||||
.green { color: #006000; }
|
||||
.green-background { background-color: #007d00; }
|
||||
.lime { color: #00bf00; }
|
||||
.lime-background { background-color: #00fa00; }
|
||||
.maroon { color: #600000; }
|
||||
.maroon-background { background-color: #7d0000; }
|
||||
.navy { color: #000060; }
|
||||
.navy-background { background-color: #00007d; }
|
||||
.olive { color: #606000; }
|
||||
.olive-background { background-color: #7d7d00; }
|
||||
.purple { color: #600060; }
|
||||
.purple-background { background-color: #7d007d; }
|
||||
.red { color: #bf0000; }
|
||||
.red-background { background-color: #fa0000; }
|
||||
.silver { color: #909090; }
|
||||
.silver-background { background-color: #bcbcbc; }
|
||||
.teal { color: #006060; }
|
||||
.teal-background { background-color: #007d7d; }
|
||||
.white { color: #bfbfbf; }
|
||||
.white-background { background-color: #fafafa; }
|
||||
.yellow { color: #bfbf00; }
|
||||
.yellow-background { background-color: #fafa00; }
|
||||
span.icon > .fa { cursor: default; }
|
||||
.admonitionblock td.icon [class^="fa icon-"] { font-size: 2.5em; cursor: default; }
|
||||
.admonitionblock td.icon .icon-note:before { content: "\f05a"; color: #4E9FDD; }
|
||||
.admonitionblock td.icon .icon-tip:before { content: "\f0eb"; color: #2C8596; }
|
||||
.admonitionblock td.icon .icon-warning:before { content: "\f071"; color: #ec7a08; }
|
||||
.admonitionblock td.icon .icon-caution:before { content: "\f06d"; color: #ec7a08; }
|
||||
.admonitionblock td.icon .icon-important:before { content: "\f06a"; color: #c00; }
|
||||
.conum[data-value] { display: inline-block; color: white !important; background-color: #333333; -webkit-border-radius: 100px; border-radius: 100px; text-align: center; width: 20px; height: 20px; font-size: 12px; line-height: 20px; font-family: "Open Sans", "Sans", sans-serif; font-style: normal; font-weight: bold; text-indent: -1px; }
|
||||
.conum[data-value] * { color: white !important; }
|
||||
.conum[data-value] + b { display: none; }
|
||||
.conum[data-value]:after { content: attr(data-value); }
|
||||
pre .conum[data-value] { position: relative; top: -2px; }
|
||||
b.conum * { color: inherit !important; }
|
||||
.conum:not([data-value]):empty { display: none; }
|
||||
.print-only { display: none !important; }
|
||||
@media print { @page { margin: 1.25cm 0.75cm; }
|
||||
* { -webkit-box-shadow: none !important; box-shadow: none !important; text-shadow: none !important; }
|
||||
a, a:visited { color: inherit !important; text-decoration: underline !important; }
|
||||
a[href^="http:"]:after, a[href^="https:"]:after { content: " (" attr(href) ")"; }
|
||||
a[href^="#"], a[href^="#"]:visited, a[href^="mailto:"], a[href^="mailto:"]:visited { text-decoration: none !important; }
|
||||
abbr[title]:after { content: " (" attr(title) ")"; }
|
||||
pre, blockquote { page-break-inside: avoid; }
|
||||
code { color: #191919; }
|
||||
thead { display: table-header-group; }
|
||||
tr, img { page-break-inside: avoid; }
|
||||
img { max-width: 100% !important; }
|
||||
p { orphans: 3; widows: 3; }
|
||||
h2, h3, #toctitle, .sidebarblock > .content > .title, #toctitle, .sidebarblock > .content > .title { page-break-after: avoid; }
|
||||
#toc, .sidebarblock { background: none !important; }
|
||||
#toc { border-bottom: 1px solid #d8d8d8 !important; padding-bottom: 0 !important; }
|
||||
.sect1 { padding-bottom: 0 !important; }
|
||||
.sect1 + .sect1 { border: none !important; }
|
||||
body.book #header { text-align: center; }
|
||||
body.book #header > h1 { border: none !important; margin: 2.5em 0 1em 0; padding: 0; }
|
||||
body.book #header span { line-height: 1.6; }
|
||||
body.book #header br { display: block; }
|
||||
body.book #header br + span { padding-left: 0; }
|
||||
body.book #header br + span:before { content: none !important; }
|
||||
body.book #toc { border: none !important; text-align: left !important; padding: 0 !important; }
|
||||
#footer { background: none !important; }
|
||||
#footer-text { color: #333333 !important; }
|
||||
.hide-on-print { display: none !important; }
|
||||
.print-only { display: block !important; }
|
||||
.hide-for-print { display: none !important; }
|
||||
.show-for-print { display: inherit !important; } }
|
||||
|
||||
.corner-ribbon{
|
||||
width: 16em;
|
||||
background: #3c6eb4 ;
|
||||
position: absolute;
|
||||
top: 3em;
|
||||
right: -4em;
|
||||
text-align: center;
|
||||
line-height: 5ex;
|
||||
color: #dedede;
|
||||
transform: rotate(45deg);
|
||||
-webkit-transform: rotate(45deg);
|
||||
z-index: 999;
|
||||
}
|
||||
.corner-ribbon a { color: #FFFFFF; }
|
|
@ -1,141 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags -->
|
||||
|
||||
<title>Fedora Defensive Coding Guide Docs Website</title>
|
||||
|
||||
<!-- Bootstrap -->
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap-theme.min.css">
|
||||
|
||||
<link rel="stylesheet" href="https://overpass-30e2.kxcdn.com/overpass.css">
|
||||
<link rel="stylesheet" href="_stylesheets/asciibinder.css">
|
||||
|
||||
|
||||
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
|
||||
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
|
||||
<!--[if lt IE 9]>
|
||||
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
|
||||
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
|
||||
<![endif]-->
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="page-header">
|
||||
<img src="_images/fedora.svg" class="img-responsive" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<h4><strong>Fedora Defensive Coding Guide Docs Site</strong></h4>
|
||||
<p>Test Build.</p>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<h5><strong>Fedora Defensive Coding Guide Docs</strong></h5>
|
||||
<div class="list-group">
|
||||
<a href="master/en-US/index.html" class="list-group-item">
|
||||
Documentation
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="bottom" class="text-muted py-3" >
|
||||
<div class="foot">
|
||||
<div class="container">
|
||||
<div class="row footerlinks">
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">About</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Overview">About Fedora</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/sponsors">Sponsors</a></dd>
|
||||
<dd><a href="https://fedoramagazine.org">Fedora Magazine</a></dd>
|
||||
<dd><a href="https:https://fedoraproject.org/wiki/Legal:Main#Legal">Legal</a></dd>
|
||||
</dl>
|
||||
<ul class="list-inline">
|
||||
<li>
|
||||
<a href="https:https://www.facebook.com/TheFedoraProject" class="btn-social btn-outline"><i class="fa fa-fw fa-facebook"></i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https:https://plus.google.com/112917221531140868607" class="btn-social btn-outline"><i class="fa fa-fw fa-google-plus"></i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https:https://twitter.com/fedora" class="btn-social btn-outline"><i class="fa fa-fw fa-twitter"></i></a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title uppercase">Download</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://getfedora.org/en/workstation/download">Get Fedora Workstation</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/server/download">Get Fedora Server</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/atomic/download">Get Fedora Atomic</a></dd>
|
||||
<dd><a href="https://spins.fedoraproject.org">Fedora Spins</a></dd>
|
||||
<dd><a href="https://labs.fedoraproject.org">Fedora Labs</a></dd>
|
||||
<dd><a href="https://arm.fedoraproject.org">Fedora ARM<span class="sup">®</span></a></dd>
|
||||
<dd><a href="https://alt.fedoraproject.org/">Alternative Downloads</a></dd>
|
||||
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">Support</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Communicating_and_getting_help">Get Help</a></dd>
|
||||
<dd><a href="https://ask.fedoraproject.org/">Ask Fedora</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Common_F${global_variables.release['curr_id']}_bugs">Common Bugs</a></dd>
|
||||
<dd><a href="https://developer.fedoraproject.org/">Fedora Developer Portal</a></dd>
|
||||
<dd><a href="https://docs.fedoraproject.org/en-US/Fedora/${global_variables.release['curr_id']}/html/Installation_Guide">Installation Guide</a></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">Join</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Join">Join Fedora</a></dd>
|
||||
<dd><a href="http://fedoraplanet.org">Planet Fedora</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/SIGs">Fedora SIGs</a></dd>
|
||||
<dd><a href="https://admin.fedoraproject.org/accounts/">Fedora Account System</a></dd>
|
||||
<dd><a href="https://fedoracommunity.org/">Fedora Community</a></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- /row of widgets -->
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-2">
|
||||
<div class="widget-body">
|
||||
<a href="https://www.redhat.com/"><img class="rh-logo" src="_images/redhat-logo.png" alt="Red Hat Logo" /></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-7">
|
||||
<div class="widget-body">
|
||||
<p class="sponsor">Fedora is sponsored by Red Hat.</p>
|
||||
<p class="sponsor"><a href="https://www.redhat.com/en/technologies/linux-platforms/articles/relationship-between-fedora-and-rhel">Learn more about the relationship between Red Hat and Fedora »</a></p>
|
||||
<p class="copy">© 2017 Red Hat, Inc. and others. Please send any comments or corrections to the <a href="https://fedorahosted.org/fedora-websites/">websites team</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- /row of widgets -->
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
|
||||
<!-- Include all compiled plugins (below), or include individual files as needed -->
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
|
||||
</body>
|
||||
</html>
|
|
@ -1,135 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags -->
|
||||
|
||||
<title>Fedora Documentation Website</title>
|
||||
|
||||
<!-- Bootstrap -->
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap-theme.min.css">
|
||||
|
||||
<link rel="stylesheet" href="https://overpass-30e2.kxcdn.com/overpass.css">
|
||||
<link rel="stylesheet" href="_stylesheets/asciibinder.css">
|
||||
|
||||
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
|
||||
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
|
||||
<!--[if lt IE 9]>
|
||||
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
|
||||
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
|
||||
<![endif]-->
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="page-header">
|
||||
<img src="/_images/fedora.svg" class="img-responsive" />
|
||||
<h2><strong>Fedora Documentation Site</strong></h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<h4><strong>Fedora Documentation - 404 Page Not Found :(</strong></h4>
|
||||
<p>Hi! You've arrived at Fedora documentation page which does not actually exist. This may be because you followed a link to an older document which has been retired. For reference, you can find those in our <a href="https://docs-old.fedoraproject.org/">old document archive</a>. Or, you can browse <a href="https://docs.fedoraproject.org/">current docs</a>.</p>
|
||||
<p>It may also be that this page _should_ exist, but sadly does not. If this is the case, and you know what it should say, you can <a href="https://pagure.io/fedora-docs">contribute via the Docs Project</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="bottom" class="text-muted py-3" >
|
||||
<div class="foot">
|
||||
<div class="container">
|
||||
<div class="row footerlinks">
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">About</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Overview">About Fedora</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/sponsors">Sponsors</a></dd>
|
||||
<dd><a href="https://fedoramagazine.org">Fedora Magazine</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Legal:Main#Legal">Legal</a></dd>
|
||||
</dl>
|
||||
<ul class="list-inline">
|
||||
<li>
|
||||
<a href="https:https://www.facebook.com/TheFedoraProject" class="btn-social btn-outline"><i class="fa fa-fw fa-facebook"></i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https:https://plus.google.com/112917221531140868607" class="btn-social btn-outline"><i class="fa fa-fw fa-google-plus"></i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https:https://twitter.com/fedora" class="btn-social btn-outline"><i class="fa fa-fw fa-twitter"></i></a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title uppercase">Download</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://getfedora.org/en/workstation/download">Get Fedora Workstation</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/server/download">Get Fedora Server</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/atomic/download">Get Fedora Atomic</a></dd>
|
||||
<dd><a href="https://spins.fedoraproject.org">Fedora Spins</a></dd>
|
||||
<dd><a href="https://labs.fedoraproject.org">Fedora Labs</a></dd>
|
||||
<dd><a href="https://arm.fedoraproject.org">Fedora ARM<span class="sup">®</span></a></dd>
|
||||
<dd><a href="https://alt.fedoraproject.org/">Alternative Downloads</a></dd>
|
||||
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">Support</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Communicating_and_getting_help">Get Help</a></dd>
|
||||
<dd><a href="https://ask.fedoraproject.org/">Ask Fedora</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Common_F27_bugs">Common Bugs</a></dd>
|
||||
<dd><a href="https://developer.fedoraproject.org/">Fedora Developer Portal</a></dd>
|
||||
<dd><a href="https://docs.fedoraproject.org/f27/install-guide/index.html">Installation Guide</a></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">Join</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Join">Join Fedora</a></dd>
|
||||
<dd><a href="http://fedoraplanet.org">Planet Fedora</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/SIGs">Fedora SIGs</a></dd>
|
||||
<dd><a href="https://admin.fedoraproject.org/accounts/">Fedora Account System</a></dd>
|
||||
<dd><a href="https://fedoracommunity.org/">Fedora Community</a></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- /row of widgets -->
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-2">
|
||||
<div class="widget-body">
|
||||
<a href="https://www.redhat.com/"><img class="rh-logo" src="_images/redhat-logo.png" alt="Red Hat Logo" /></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-7">
|
||||
<div class="widget-body">
|
||||
<p class="sponsor">Fedora is sponsored by Red Hat.</p>
|
||||
<p class="sponsor"><a href="https://www.redhat.com/en/technologies/linux-platforms/articles/relationship-between-fedora-and-rhel">Learn more about the relationship between Red Hat and Fedora »</a></p>
|
||||
<p class="copy">© 2017 Red Hat, Inc. and others. Please send any comments or corrections to the <a href="https://pagure.io/fedora-docs/docs-fp-o">documentation team</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- /row of widgets -->
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
|
||||
<!-- Include all compiled plugins (below), or include individual files as needed -->
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
|
||||
</body>
|
||||
</html>
|
Before Width: | Height: | Size: 5.3 KiB |
Before Width: | Height: | Size: 1.5 KiB |
|
@ -1,61 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
version="1.0"
|
||||
width="220"
|
||||
height="70"
|
||||
id="svg6180">
|
||||
<defs
|
||||
id="defs6182" />
|
||||
<g
|
||||
transform="translate(-266.55899,-345.34488)"
|
||||
id="layer1">
|
||||
<path
|
||||
d="m 316.7736,397.581 c 0,0 0,0 -20.53889,0 0.3327,4.45245 3.92157,7.77609 8.70715,7.77609 3.38983,0 6.31456,-1.39616 8.64094,-3.65507 0.46553,-0.46679 0.99726,-0.59962 1.59519,-0.59962 0.79781,0 1.59561,0.39932 2.12692,1.06388 0.3327,0.46553 0.53216,0.99726 0.53216,1.52857 0,0.73118 -0.3327,1.52857 -0.93106,2.12734 -2.7919,2.99052 -7.51086,4.98503 -12.16403,4.98503 -8.44149,0 -15.22074,-6.77967 -15.22074,-15.22158 0,-8.44149 6.58022,-15.22074 15.02171,-15.22074 8.37529,0 14.62323,6.51317 14.62323,15.08749 0,1.26418 -1.12924,2.12861 -2.39258,2.12861 z m -12.23065,-11.76512 c -4.45329,0 -7.51085,2.92473 -8.17499,7.17731 10.03626,0 16.35083,0 16.35083,0 -0.59836,-4.05355 -3.78874,-7.17731 -8.17584,-7.17731 z"
|
||||
id="path11"
|
||||
style="fill:#3c6eb4" />
|
||||
<path
|
||||
d="m 375.46344,410.80807 c -8.44106,0 -15.22074,-6.77968 -15.22074,-15.22159 0,-8.44149 6.77968,-15.22074 15.22074,-15.22074 8.44234,0 15.22159,6.77925 15.22159,15.22074 -4.2e-4,8.44149 -6.77968,15.22159 -15.22159,15.22159 z m 0,-24.65992 c -5.31688,0 -8.77377,4.25427 -8.77377,9.43833 0,5.18364 3.45689,9.43833 8.77377,9.43833 5.31731,0 8.77504,-4.25469 8.77504,-9.43833 -4.2e-4,-5.18406 -3.45773,-9.43833 -8.77504,-9.43833 z"
|
||||
id="path13"
|
||||
style="fill:#3c6eb4" />
|
||||
<path
|
||||
d="m 412.66183,380.36574 c -4.45963,0 -7.40966,1.319 -10.01391,4.62956 l -0.24036,-1.53995 0,0 c -0.20198,-1.60743 -1.57326,-2.84926 -3.23382,-2.84926 -1.80139,0 -3.26206,1.459 -3.26206,3.26081 0,0.003 0,0.005 0,0.008 l 0,0 0,0.003 0,0 0,23.40712 c 0,1.79464 1.46194,3.25743 3.257,3.25743 1.79465,0 3.25744,-1.46279 3.25744,-3.25743 l 0,-12.56209 c 0,-5.71621 4.98502,-8.57432 10.23613,-8.57432 1.59519,0 2.85726,-1.32953 2.85726,-2.92515 0,-1.59561 -1.26207,-2.85726 -2.85768,-2.85726 z"
|
||||
id="path15"
|
||||
style="fill:#3c6eb4" />
|
||||
<path
|
||||
d="m 447.02614,395.58648 c 0.0666,-8.17541 -5.78326,-15.22074 -15.222,-15.22074 -8.44192,0 -15.28779,6.77925 -15.28779,15.22074 0,8.44191 6.64684,15.22159 14.68985,15.22159 4.01434,0 7.62682,-2.06621 9.23846,-4.22518 l 0.79359,2.01434 0,0 c 0.42589,1.13177 1.5176,1.93717 2.7978,1.93717 1.65001,0 2.98756,-1.33671 2.99009,-2.98545 l 0,0 0,-7.80687 0,0 0,-4.1556 z m -15.222,9.43833 c -5.31773,0 -8.77419,-4.25469 -8.77419,-9.43833 0,-5.18406 3.45604,-9.43833 8.77419,-9.43833 5.3173,0 8.77419,4.25427 8.77419,9.43833 0,5.18364 -3.45689,9.43833 -8.77419,9.43833 z"
|
||||
id="path17"
|
||||
style="fill:#3c6eb4" />
|
||||
<path
|
||||
d="m 355.01479,368.3337 c 0,-1.7938 -1.46194,-3.18997 -3.25659,-3.18997 -1.79422,0 -3.25743,1.39659 -3.25743,3.18997 l 0,17.1499 c -1.66097,-3.05756 -5.25026,-5.11786 -9.50495,-5.11786 -8.64052,0 -14.42336,6.51318 -14.42336,15.22074 0,8.70757 5.98229,15.22159 14.42336,15.22159 3.76555,0 7.03057,-1.55429 8.98587,-4.25554 l 0.72317,1.83428 c 0.44782,1.25912 1.64917,2.16024 3.06051,2.16024 1.78621,0 3.24984,-1.45435 3.24984,-3.24815 0,-0.005 0,-0.009 0,-0.0139 l 0,0 0,-38.95128 -4.2e-4,0 z m -15.22116,36.69111 c -5.31731,0 -8.70715,-4.25469 -8.70715,-9.43833 0,-5.18406 3.38984,-9.43833 8.70715,-9.43833 5.31773,0 8.70714,4.0544 8.70714,9.43833 0,5.38309 -3.38941,9.43833 -8.70714,9.43833 z"
|
||||
id="path19"
|
||||
style="fill:#3c6eb4" />
|
||||
<path
|
||||
d="m 287.21553,365.34023 c -0.59414,-0.0877 -1.19966,-0.13198 -1.80097,-0.13198 -6.73118,0 -12.20746,5.4767 -12.20746,12.20788 l 0,3.8132 -3.98903,0 c -1.46237,0 -2.65908,1.19671 -2.65908,2.65781 0,1.46321 1.19671,2.93738 2.65908,2.93738 l 3.98819,0 0,20.46004 c 0,1.79464 1.46236,3.25743 3.25658,3.25743 1.79507,0 3.25744,-1.46279 3.25744,-3.25743 l 0,-20.46004 4.40986,0 c 1.46194,0 2.65823,-1.47417 2.65823,-2.93738 0,-1.46152 -1.19629,-2.65823 -2.65823,-2.65823 l -4.40733,0 0,-3.8132 c 0,-3.13852 2.55323,-6.11469 5.69175,-6.11469 0.28294,0 0.56757,0.0211 0.84672,0.062 1.78031,0.26355 3.4358,-0.54269 3.70019,-2.32342 0.2627,-1.77904 -0.96606,-3.43538 -2.74594,-3.69935 z"
|
||||
id="path21"
|
||||
style="fill:#3c6eb4" />
|
||||
<path
|
||||
d="m 482.01243,363.57426 c 0,-10.06788 -8.16108,-18.22938 -18.22897,-18.22938 -10.06282,0 -18.22179,8.15475 -18.22854,18.21631 l -4.2e-4,-4.2e-4 0,14.1071 4.2e-4,4.2e-4 c 0.005,2.28463 1.85832,4.13409 4.14463,4.13409 0.007,0 0.0127,-8.4e-4 0.0194,-8.4e-4 l 0.001,8.4e-4 14.07083,0 0,0 c 10.06409,-0.004 18.22138,-8.16276 18.22138,-18.22812 z"
|
||||
id="path25"
|
||||
style="fill:#294172" />
|
||||
<path
|
||||
d="m 469.13577,349.66577 c -4.72528,0 -8.55576,3.83049 -8.55576,8.55577 0,0.002 0,0.004 0,0.006 l 0,4.52836 -4.51444,0 c -8.5e-4,0 -8.5e-4,0 -0.001,0 -4.72528,0 -8.55576,3.81193 -8.55576,8.53678 0,4.72528 3.83048,8.55577 8.55576,8.55577 4.72486,0 8.55534,-3.83049 8.55534,-8.55577 0,-0.002 0,-0.004 0,-0.006 l 0,-4.54733 4.51444,0 c 8.5e-4,0 0.001,0 0.002,0 4.72486,0 8.55534,-3.79296 8.55534,-8.51781 0,-4.72528 -3.83048,-8.55577 -8.55534,-8.55577 z m -8.55576,21.63483 c -0.004,2.48998 -2.02446,4.50811 -4.51571,4.50811 -2.49378,0 -4.53426,-2.02193 -4.53426,-4.5157 0,-2.49421 2.04048,-4.55366 4.53426,-4.55366 0.002,0 0.004,4.2e-4 0.006,4.2e-4 l 3.86971,0 c 0.001,0 0.002,-4.2e-4 0.003,-4.2e-4 0.35209,0 0.63799,0.28505 0.63799,0.63715 0,4.2e-4 -4.2e-4,8.4e-4 -4.2e-4,0.001 l 0,3.92284 -4.2e-4,0 z m 8.55534,-8.5448 c -0.001,0 -0.003,0 -0.004,0 l -3.87223,0 c -8.4e-4,0 -0.002,0 -0.002,0 -0.35252,0 -0.63757,-0.28506 -0.63757,-0.63758 l 0,-4.2e-4 0,-3.90343 c 0.004,-2.49083 2.02446,-4.50854 4.51571,-4.50854 2.49378,0 4.53468,2.02193 4.53468,4.51613 4.2e-4,2.49336 -2.04048,4.53384 -4.53426,4.53384 z"
|
||||
id="path29"
|
||||
style="fill:#3c6eb4" />
|
||||
<path
|
||||
d="m 460.58001,362.7558 0,-4.52836 c 0,-0.002 0,-0.004 0,-0.006 0,-4.72528 3.83048,-8.55577 8.55576,-8.55577 0.71685,0 1.22623,0.0805 1.88952,0.25469 0.96774,0.25385 1.75796,1.04618 1.75838,1.96922 4.2e-4,1.11575 -0.80919,1.92621 -2.0194,1.92621 -0.57642,0 -0.78473,-0.11048 -1.62892,-0.11048 -2.49125,0 -4.51149,2.01771 -4.51571,4.50854 l 0,3.90385 0,4.2e-4 c 0,0.35252 0.28505,0.63758 0.63757,0.63758 4.3e-4,0 0.001,0 0.002,0 l 2.96521,0 c 1.10521,0 1.99747,0.88467 1.99832,1.99283 0,1.10816 -0.89353,1.99114 -1.99832,1.99114 l -3.60489,0 0,4.54733 c 0,0.002 0,0.004 0,0.006 0,4.72485 -3.83048,8.55534 -8.55534,8.55534 -0.71684,0 -1.22623,-0.0805 -1.88952,-0.25469 -0.96774,-0.25343 -1.75838,-1.04618 -1.7588,-1.9688 0,-1.11575 0.80919,-1.92663 2.01982,-1.92663 0.576,0 0.78473,0.11048 1.6285,0.11048 2.49125,0 4.51191,-2.01771 4.51613,-4.50811 0,0 0,-3.92368 0,-3.9241 0,-0.35168 -0.2859,-0.63673 -0.63799,-0.63673 -4.3e-4,0 -8.5e-4,0 -0.002,0 l -2.96521,-4.2e-4 c -1.10521,0 -1.99831,-0.88214 -1.99831,-1.9903 -4.3e-4,-1.11533 0.90238,-1.99367 2.01939,-1.99367 l 3.58339,0 0,0 z"
|
||||
id="path31"
|
||||
style="fill:#ffffff" />
|
||||
<path
|
||||
d="m 477.41661,378.55292 2.81558,0 0,0.37898 -1.18152,0 0,2.94935 -0.45254,0 0,-2.94935 -1.18152,0 0,-0.37898 m 3.26144,0 0.67101,0 0.84937,2.26496 0.85381,-2.26496 0.67102,0 0,3.32833 -0.43917,0 0,-2.9226 -0.85828,2.28279 -0.45255,0 -0.85827,-2.28279 0,2.9226 -0.43694,0 0,-3.32833"
|
||||
id="text6223"
|
||||
style="fill:#294172;enable-background:new" />
|
||||
</g>
|
||||
<path
|
||||
d="m 181.98344,61.675273 2.81558,0 0,0.37898 -1.18152,0 0,2.94935 -0.45254,0 0,-2.94935 -1.18152,0 0,-0.37898 m 3.26144,0 0.67101,0 0.84937,2.26496 0.85381,-2.26496 0.67102,0 0,3.32833 -0.43917,0 0,-2.9226 -0.85828,2.28279 -0.45255,0 -0.85827,-2.28279 0,2.9226 -0.43694,0 0,-3.32833"
|
||||
id="path2391"
|
||||
style="fill:#294172;enable-background:new" />
|
||||
</svg>
|
Before Width: | Height: | Size: 7.6 KiB |
Before Width: | Height: | Size: 3.9 KiB |
|
@ -1,6 +0,0 @@
|
|||
$(document).ready(function () {
|
||||
$('[data-toggle="offcanvas"]').click(function () {
|
||||
$('.sidebar').show();
|
||||
$('.row-offcanvas').toggleClass('active');
|
||||
});
|
||||
});
|
|
@ -1,598 +0,0 @@
|
|||
@import url(https://maxcdn.bootstrapcdn.com/font-awesome/4.1.0/css/font-awesome.min.css);
|
||||
/* ------------------------------------------------------------
|
||||
Image: "Spin" https://www.flickr.com/photos/eflon/3655695161/
|
||||
Author: eflon https://www.flickr.com/photos/eflon/
|
||||
License: https://creativecommons.org/licenses/by/2.0/
|
||||
---------------------------------------------------------------*/
|
||||
.attribution {
|
||||
text-align: center;
|
||||
position: relative;
|
||||
bottom: -20px;
|
||||
}
|
||||
.attribution .btn {
|
||||
color: #808080;
|
||||
color: rgba(175,175,175, .65);
|
||||
font-size: 11px;
|
||||
}
|
||||
.attribution .btn:hover {
|
||||
text-decoration: none;
|
||||
color: #aaa;
|
||||
}
|
||||
.popover-content {
|
||||
font-size: 12px;
|
||||
line-height: 1.3;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 980px) {
|
||||
body {
|
||||
margin-bottom: 200px;
|
||||
}
|
||||
footer {
|
||||
text-align: center;
|
||||
}
|
||||
footer .text-right {
|
||||
text-align: center !important;
|
||||
}
|
||||
#footer_social .first {
|
||||
margin-left: 0;
|
||||
}
|
||||
#footer_social > a {
|
||||
top: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
.fa-inverse:hover {
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
.collapse a.active {
|
||||
background-color: #DEEAF4;
|
||||
color: #000;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.collapse a.active:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.collapse a.active:before {
|
||||
background-color: #A0C3E5;
|
||||
content: "";
|
||||
display: inline-block;
|
||||
height: 100%;
|
||||
left: 0;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
width: 3px;
|
||||
}
|
||||
|
||||
.main h2, .main .h2 {
|
||||
border-top: 0px;
|
||||
padding-top: 10px;
|
||||
font-size: 28px;
|
||||
}
|
||||
|
||||
.page-header {
|
||||
height: 100% !important;
|
||||
}
|
||||
.page-header .img-responsive {
|
||||
display: inline;
|
||||
}
|
||||
.page-header h2 {
|
||||
font-size: 32px;
|
||||
display: inline;
|
||||
vertical-align: bottom;
|
||||
}
|
||||
|
||||
.navbar-brand {
|
||||
padding: initial;
|
||||
height: initial;
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
.navbar-header h2 {
|
||||
display: inline;
|
||||
position: absolute;
|
||||
font-weight: bold;
|
||||
margin-top: 50px ;
|
||||
}
|
||||
|
||||
.nav > li > a.hover{
|
||||
background-color: none;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6 {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
h2 > a.anchor, h3 > a.anchor, h4 > a.anchor, h5 > a.anchor, h6 > a.anchor {
|
||||
display: block;
|
||||
font-weight: normal;
|
||||
margin-left: -1.5ex;
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
text-decoration: none !important;
|
||||
visibility: hidden;
|
||||
width: 1.5ex;
|
||||
z-index: 1001;
|
||||
}
|
||||
|
||||
h2 > a.anchor:before, h3 > a.anchor:before, h4 > a.anchor:before, h5 > a.anchor:before, h6 > a.anchor:before {
|
||||
content: "\f0c1";
|
||||
display: block;
|
||||
font-family: FontAwesome;
|
||||
font-size: 0.7em;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
padding-top: 0.2em;
|
||||
}
|
||||
|
||||
h4 > a.anchor:before, h5 > a.anchor:before, h6 > a.anchor:before {
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
h2:hover > a.anchor,
|
||||
h2 > a.anchor:hover,
|
||||
h3:hover > a.anchor,
|
||||
h3 > a.anchor:hover,
|
||||
h4:hover > a.anchor,
|
||||
h4 > a.anchor:hover,
|
||||
h5:hover > a.anchor,
|
||||
h5 > a.anchor:hover,
|
||||
h6:hover > a.anchor,
|
||||
h6 > a.anchor:hover {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.main {
|
||||
border-left: 1px solid #e7e7e7;
|
||||
margin-left: -1px;
|
||||
padding-left: 25px;
|
||||
}
|
||||
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.main {
|
||||
padding-left: 30px;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Sidebar
|
||||
*/
|
||||
|
||||
.nav-header {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.nav-header ul {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.nav-header ul li a {
|
||||
display: block;
|
||||
padding: 5px 20px 5px 25px;
|
||||
font-size: 13px;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.nav-sidebar .fa {
|
||||
text-align: center;
|
||||
top: -1px;
|
||||
width: 14px;
|
||||
}
|
||||
|
||||
.nav-sidebar li a {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.nav-sidebar li a:hover {
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.nav-sidebar ul li ul.nav-tertiary li a {
|
||||
padding-left: 50px;
|
||||
}
|
||||
|
||||
.nav-sidebar > li > a {
|
||||
padding: 7px 0;
|
||||
}
|
||||
|
||||
.nav-sidebar > li > a:focus, .nav-sidebar > li > a:hover {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
font-weight: 300;
|
||||
display: none;
|
||||
padding-top: 13px;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 767px) {
|
||||
.sidebar {
|
||||
padding-left: 30px;
|
||||
padding-right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (min-width: 768px) {
|
||||
.sidebar {
|
||||
border-right: 1px solid #e7e7e7;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Off Canvas
|
||||
* --------------------------------------------------
|
||||
*/
|
||||
|
||||
body, html {
|
||||
overflow-x: hidden; /* Prevent scroll on narrow devices */
|
||||
font-family: "Overpass", sans-serif;
|
||||
}
|
||||
|
||||
.toggle-nav {
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 767px) {
|
||||
.row-offcanvas {
|
||||
position: relative;
|
||||
-webkit-transition: all .25s ease-out;
|
||||
-o-transition: all .25s ease-out;
|
||||
transition: all .25s ease-out;
|
||||
}
|
||||
|
||||
.row-offcanvas-right {
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.row-offcanvas-left {
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.row-offcanvas-right
|
||||
.sidebar-offcanvas {
|
||||
right: -75%; /* 8 columns */
|
||||
}
|
||||
|
||||
.row-offcanvas-left
|
||||
.sidebar-offcanvas {
|
||||
left: -75%; /* 8 columns */
|
||||
}
|
||||
|
||||
.row-offcanvas-right.active {
|
||||
right: 75%; /* 8 columns */
|
||||
}
|
||||
|
||||
.row-offcanvas-left.active {
|
||||
left: 75%; /* 8 columns */
|
||||
}
|
||||
|
||||
.sidebar-offcanvas {
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
width: 75%; /* 8 columns */
|
||||
}
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 0 0 1.6em;
|
||||
}
|
||||
|
||||
/* Remnants of Asciidoctor default stylesheet - remove styles as needed */
|
||||
|
||||
#map_canvas img, #map_canvas embed, #map_canvas object, .map_canvas img, .map_canvas embed, .map_canvas object { max-width: none !important; }
|
||||
.left { float: left !important; }
|
||||
.right { float: right !important; }
|
||||
.text-left { text-align: left !important; }
|
||||
.text-right { text-align: right !important; }
|
||||
.text-center { text-align: center !important; }
|
||||
.text-justify { text-align: justify !important; }
|
||||
.hide { display: none; }
|
||||
.subheader, #content #toctitle, .admonitionblock td.content > .title, .audioblock > .title, .exampleblock > .title, .imageblock > .title, .listingblock > .title, .literalblock > .title, .stemblock > .title, .openblock > .title, .paragraph > .title, .quoteblock > .title, table.tableblock > .title, .verseblock > .title, .videoblock > .title, .dlist > .title, .olist > .title, .ulist > .title, .qlist > .title, .hdlist > .title { line-height: 1.4; color: #7a2518; font-weight: 300; margin-top: 0.2em; margin-bottom: 0.5em; }
|
||||
abbr, acronym { text-transform: uppercase; font-size: 90%; color: #333333; border-bottom: 1px dotted #dddddd; cursor: help; }
|
||||
abbr { text-transform: none; }
|
||||
blockquote { margin: 0 0 1.25em; padding: 0.5625em 1.25em 0 1.1875em; border-left: 3px solid #487c58; }
|
||||
blockquote cite { display: block; font-size: inherit; color: #454545; }
|
||||
blockquote cite:before { content: "\2014 \0020"; }
|
||||
blockquote cite a, blockquote cite a:visited { color: #454545; }
|
||||
blockquote, blockquote p { line-height: 1.6; color: #6e6e6e; }
|
||||
@media only screen and (min-width: 768px) {
|
||||
#toctitle, .sidebarblock > .content > .title { line-height: 1.4; }
|
||||
#toctitle, .sidebarblock > .content > .title { font-size: 1.6875em; }
|
||||
}
|
||||
table { background: white; margin-bottom: 1.25em; border: solid 1px #dddddd; }
|
||||
table thead, table tfoot { background: whitesmoke; font-weight: bold; }
|
||||
table thead tr th, table thead tr td, table tfoot tr th, table tfoot tr td { padding: 0.5em 0.625em 0.625em; font-size: inherit; color: #333333; text-align: left; }
|
||||
table tr th, table tr td { padding: 0.5625em 0.625em; font-size: inherit; color: #333333; }
|
||||
table tr.even, table tr.alt, table tr:nth-of-type(even) { background: #f9f9f9; }
|
||||
table thead tr th, table tfoot tr th, table tbody tr td, table tr td, table tfoot tr td { display: table-cell; line-height: 1.6; }
|
||||
.clearfix:before, .clearfix:after, .float-group:before, .float-group:after { content: " "; display: table; }
|
||||
.clearfix:after, .float-group:after { clear: both; }
|
||||
*:not(pre) > code { font-size: inherit; padding: 0; white-space: nowrap; background-color: inherit; border: 0 solid #dddddd; -webkit-border-radius: 4px; border-radius: 4px; text-shadow: none; line-height: 1; }
|
||||
.keyseq { color: #666666; }
|
||||
kbd:not(.keyseq) { display: inline-block; color: #333333; font-size: 0.75em; line-height: 1.4; background-color: #f7f7f7; border: 1px solid #ccc; -webkit-border-radius: 3px; border-radius: 3px; -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.2), 0 0 0 2px white inset; box-shadow: 0 1px 0 rgba(0, 0, 0, 0.2), 0 0 0 2px white inset; margin: -0.15em 0.15em 0 0.15em; padding: 0.2em 0.6em 0.2em 0.5em; vertical-align: middle; white-space: nowrap; }
|
||||
.keyseq kbd:first-child { margin-left: 0; }
|
||||
.keyseq kbd:last-child { margin-right: 0; }
|
||||
.menuseq, .menu { color: #1a1a1a; }
|
||||
b.button:before, b.button:after { position: relative; top: -1px; font-weight: normal; }
|
||||
b.button:before { content: "["; padding: 0 3px 0 2px; }
|
||||
b.button:after { content: "]"; padding: 0 2px 0 3px; }
|
||||
p a > code:hover { color: #561309; }
|
||||
#header, #content, #footnotes, #footer { width: 100%; margin-left: auto; margin-right: auto; margin-top: 0; margin-bottom: 0; max-width: 62.5em; *zoom: 1; position: relative; padding-left: 0.9375em; padding-right: 0.9375em; }
|
||||
#header:before, #header:after, #content:before, #content:after, #footnotes:before, #footnotes:after, #footer:before, #footer:after { content: " "; display: table; }
|
||||
#header:after, #content:after, #footnotes:after, #footer:after { clear: both; }
|
||||
#content:before { content: none; }
|
||||
#header { margin-bottom: 2.5em; }
|
||||
#header > h1 { color: black; font-weight: 300; border-bottom: 1px solid #d8d8d8; margin-bottom: -28px; padding-bottom: 32px; }
|
||||
#header span { color: #6e6e6e; }
|
||||
#header #revnumber { text-transform: capitalize; }
|
||||
#header br { display: none; }
|
||||
#header br + span { padding-left: 3px; }
|
||||
#header br + span:before { content: "\2013 \0020"; }
|
||||
#header br + span.author { padding-left: 0; }
|
||||
#header br + span.author:before { content: ", "; }
|
||||
#toc { border-bottom: 3px double #e5e5e5; padding-top: 1em; padding-bottom: 1.25em; }
|
||||
#toc > ul { margin-left: 0.25em; }
|
||||
#toc ul.sectlevel0 > li > a { font-style: italic; }
|
||||
#toc ul.sectlevel0 ul.sectlevel1 { margin-left: 0; margin-top: 0.5em; margin-bottom: 0.5em; }
|
||||
#toc ul { font-family: "Open Sans", "DejaVu Sans", "Sans", sans-serif; list-style-type: none; }
|
||||
#toc a { text-decoration: none; }
|
||||
#toc a:active { text-decoration: underline; }
|
||||
#toctitle { color: #7a2518; }
|
||||
@media only screen and (min-width: 768px) { body.toc2 { padding-left: 15em; padding-right: 0; }
|
||||
#toc.toc2 { background-color: #fafaf9; position: fixed; width: 15em; left: 0; top: 0; border-right: 1px solid #e5e5e5; border-bottom: 0; z-index: 1000; padding: 1.25em 1em; height: 100%; overflow: auto; }
|
||||
#toc.toc2 #toctitle { margin-top: 0; font-size: 1.2em; }
|
||||
#toc.toc2 > ul { font-size: .90em; margin-bottom: 0; }
|
||||
#toc.toc2 ul ul { margin-left: 0; padding-left: 1em; }
|
||||
#toc.toc2 ul.sectlevel0 ul.sectlevel1 { padding-left: 0; margin-top: 0.5em; margin-bottom: 0.5em; }
|
||||
body.toc2.toc-right { padding-left: 0; padding-right: 15em; }
|
||||
body.toc2.toc-right #toc.toc2 { border-right: 0; border-left: 1px solid #e5e5e5; left: auto; right: 0; } }
|
||||
@media only screen and (min-width: 1280px) { body.toc2 { padding-left: 20em; padding-right: 0; }
|
||||
#toc.toc2 { width: 20em; }
|
||||
#toc.toc2 #toctitle { font-size: 1.375em; }
|
||||
#toc.toc2 > ul { font-size: 0.95em; }
|
||||
#toc.toc2 ul ul { padding-left: 1.25em; }
|
||||
body.toc2.toc-right { padding-left: 0; padding-right: 20em; } }
|
||||
#content #toc { border-style: solid; border-width: 1px; border-color: #e3e3dd; margin-bottom: 1.25em; padding: 1.25em; background: #fafaf9; border-width: 0; -webkit-border-radius: 4px; border-radius: 4px; }
|
||||
#content #toc > :first-child { margin-top: 0; }
|
||||
#content #toc > :last-child { margin-bottom: 0; }
|
||||
#content #toctitle { font-size: 1.375em; }
|
||||
#footer { max-width: 100%; background-color: #333333; padding: 1.25em; }
|
||||
#footer-text { color: #cccccc; line-height: 1.44; }
|
||||
.audioblock, .imageblock, .literalblock, .listingblock, .stemblock, .verseblock, .videoblock { margin-bottom: 2.5em; }
|
||||
.admonitionblock td.content > .title, .audioblock > .title, .exampleblock > .title, .imageblock > .title, .listingblock > .title, .literalblock > .title, .stemblock > .title, .openblock > .title, .paragraph > .title, .quoteblock > .title, table.tableblock > .title, .verseblock > .title, .videoblock > .title, .dlist > .title, .olist > .title, .ulist > .title, .qlist > .title, .hdlist > .title { text-rendering: optimizeLegibility; text-align: left; font-family: "Noto Serif", "DejaVu Serif", "Serif", serif; font-weight: normal; font-style: italic; }
|
||||
table.tableblock > caption.title { white-space: nowrap; overflow: visible; max-width: 0; }
|
||||
table.tableblock #preamble > .sectionbody > .paragraph:first-of-type p { font-size: inherit; }
|
||||
.admonitionblock > table { border: 0; background: none; width: 100%; }
|
||||
.admonitionblock > table td.icon { text-align: center; width: 80px; }
|
||||
.admonitionblock > table td.icon img { max-width: none; }
|
||||
.admonitionblock > table td.icon .title { font-weight: 300; text-transform: uppercase; }
|
||||
.admonitionblock > table td.content { padding-left: 0; padding-right: 1.25em; color: #6e6e6e; }
|
||||
.admonitionblock > table td.content > :last-child > :last-child { margin-bottom: 0; }
|
||||
.exampleblock > .content { border-style: solid; border-width: 1px; border-color: #e6e6e6; margin-bottom: 1.25em; padding: 1.25em; background: white; -webkit-border-radius: 4px; border-radius: 4px; }
|
||||
.exampleblock > .content > :first-child { margin-top: 0; }
|
||||
.exampleblock > .content > :last-child { margin-bottom: 0; }
|
||||
.exampleblock > .content h1, .exampleblock > .content h2, .exampleblock > .content h3, .exampleblock > .content #toctitle, .sidebarblock.exampleblock > .content > .title, .exampleblock > .content h4, .exampleblock > .content h5, .exampleblock > .content h6, .exampleblock > .content p { color: #333333; }
|
||||
.exampleblock > .content h1, .exampleblock > .content h2, .exampleblock > .content h3, .exampleblock > .content #toctitle, .sidebarblock.exampleblock > .content > .title, .exampleblock > .content h4, .exampleblock > .content h5, .exampleblock > .content h6 { line-height: 1; margin-bottom: 0.625em; }
|
||||
.exampleblock > .content h1.subheader, .exampleblock > .content h2.subheader, .exampleblock > .content h3.subheader, .exampleblock > .content .subheader#toctitle, .sidebarblock.exampleblock > .content > .subheader.title, .exampleblock > .content h4.subheader, .exampleblock > .content h5.subheader, .exampleblock > .content h6.subheader { line-height: 1.4; }
|
||||
.exampleblock.result > .content { -webkit-box-shadow: 0 1px 8px #e3e3dd; box-shadow: 0 1px 8px #e3e3dd; }
|
||||
.sidebarblock { border-style: solid; border-width: 1px; border-color: #e3e3dd; margin-top: -1.0em; margin-bottom: 1.6em; margin-left: 1em; padding: .5em; background: #F1F3F5; -webkit-border-radius: 4px; border-radius: 4px; overflow-x: auto; float: right; width: 40%; }
|
||||
.sidebarblock > :first-child { margin-top: 0; }
|
||||
.sidebarblock > :last-child { margin-bottom: 0; }
|
||||
.sidebarblock h1, .sidebarblock h2, .sidebarblock h3, .sidebarblock #toctitle, .sidebarblock > .content > .title, .sidebarblock h4, .sidebarblock h5, .sidebarblock h6, .sidebarblock p { color: #333333; }
|
||||
.sidebarblock h1, .sidebarblock h2, .sidebarblock h3, .sidebarblock #toctitle, .sidebarblock > .content > .title, .sidebarblock h4, .sidebarblock h5, .sidebarblock h6 { line-height: 1; margin-bottom: 0.625em; }
|
||||
.sidebarblock h1.subheader, .sidebarblock h2.subheader, .sidebarblock h3.subheader, .sidebarblock .subheader#toctitle, .sidebarblock > .content > .subheader.title, .sidebarblock h4.subheader, .sidebarblock h5.subheader, .sidebarblock h6.subheader { line-height: 1.4; }
|
||||
.sidebarblock > .content > .title { color: inherit; font-size: 28px; font-weight: 500; margin-top: 0; line-height: 1.6; }
|
||||
.width50 { width: 50% ! important}
|
||||
.exampleblock > .content > :last-child > :last-child, .exampleblock > .content .olist > ol > li:last-child > :last-child, .exampleblock > .content .ulist > ul > li:last-child > :last-child, .exampleblock > .content .qlist > ol > li:last-child > :last-child, .sidebarblock > .content > :last-child > :last-child, .sidebarblock > .content .olist > ol > li:last-child > :last-child, .sidebarblock > .content .ulist > ul > li:last-child > :last-child, .sidebarblock > .content .qlist > ol > li:last-child > :last-child { margin-bottom: 0; }
|
||||
.literalblock pre, .literalblock pre[class], .listingblock pre, .listingblock pre[class] { border: 0px; background-color: #F0F3F5; -webkit-border-radius: 5px; border-radius: 5px; padding: 1.5em 2.5em; word-wrap: break-word; }
|
||||
.literalblock pre.nowrap, .literalblock pre[class].nowrap, .listingblock pre.nowrap, .listingblock pre[class].nowrap { overflow-x: auto; white-space: pre; word-wrap: normal; }
|
||||
.literalblock pre > code, .literalblock pre[class] > code, .listingblock pre > code, .listingblock pre[class] > code { display: block; }
|
||||
.listingblock > .content { position: relative; }
|
||||
.listingblock:hover code[class*=" language-"]:before { text-transform: uppercase; font-size: 0.9em; color: #999; position: absolute; top: 0.375em; right: 0.375em; }
|
||||
.listingblock:hover code.asciidoc:before { content: "asciidoc"; }
|
||||
.listingblock:hover code.clojure:before { content: "clojure"; }
|
||||
.listingblock:hover code.css:before { content: "css"; }
|
||||
.listingblock:hover code.go:before { content: "go"; }
|
||||
.listingblock:hover code.groovy:before { content: "groovy"; }
|
||||
.listingblock:hover code.html:before { content: "html"; }
|
||||
.listingblock:hover code.java:before { content: "java"; }
|
||||
.listingblock:hover code.javascript:before { content: "javascript"; }
|
||||
.listingblock:hover code.python:before { content: "python"; }
|
||||
.listingblock:hover code.ruby:before { content: "ruby"; }
|
||||
.listingblock:hover code.sass:before { content: "sass"; }
|
||||
.listingblock:hover code.scss:before { content: "scss"; }
|
||||
.listingblock:hover code.xml:before { content: "xml"; }
|
||||
.listingblock:hover code.yaml:before { content: "yaml"; }
|
||||
.listingblock.terminal pre .command:before { content: attr(data-prompt); padding-right: 0.5em; color: #999; }
|
||||
.listingblock.terminal pre .command:not([data-prompt]):before { content: '$'; }
|
||||
table.pyhltable { border: 0; margin-bottom: 0; }
|
||||
table.pyhltable td { vertical-align: top; padding-top: 0; padding-bottom: 0; }
|
||||
table.pyhltable td.code { padding-left: .75em; padding-right: 0; }
|
||||
.highlight.pygments .lineno, table.pyhltable td:not(.code) { color: #999; padding-left: 0; padding-right: .5em; border-right: 1px solid #d8d8d8; }
|
||||
.highlight.pygments .lineno { display: inline-block; margin-right: .25em; }
|
||||
table.pyhltable .linenodiv { background-color: transparent !important; padding-right: 0 !important; }
|
||||
.quoteblock { margin: 0 0 1.25em 0; padding: 0.5625em 1.25em 0 1.1875em; border-left: 3px solid #487c58; }
|
||||
.quoteblock blockquote { margin: 0 0 1.25em 0; padding: 0 0 0.625em 0; border: 0; }
|
||||
.quoteblock blockquote > .paragraph:last-child p { margin-bottom: 0; }
|
||||
.quoteblock .attribution { margin-top: -0.625em; padding-bottom: 0.625em; font-size: inherit; color: #454545; line-height: 1.6; }
|
||||
.quoteblock .attribution br { display: none; }
|
||||
.quoteblock .attribution cite { display: block; }
|
||||
table.tableblock { max-width: 100%; }
|
||||
table.tableblock td .paragraph:last-child p > p:last-child, table.tableblock th > p:last-child, table.tableblock td > p:last-child { margin-bottom: 0; }
|
||||
table.spread { width: 100%; }
|
||||
table.tableblock, th.tableblock, td.tableblock { border: 0 solid #dddddd; }
|
||||
table.grid-all th.tableblock, table.grid-all td.tableblock { border-width: 0 1px 1px 0; }
|
||||
table.grid-all tfoot > tr > th.tableblock, table.grid-all tfoot > tr > td.tableblock { border-width: 1px 1px 0 0; }
|
||||
table.grid-cols th.tableblock, table.grid-cols td.tableblock { border-width: 0 1px 0 0; }
|
||||
table.grid-all * > tr > .tableblock:last-child, table.grid-cols * > tr > .tableblock:last-child { border-right-width: 0; }
|
||||
table.grid-rows th.tableblock, table.grid-rows td.tableblock { border-width: 0 0 1px 0; }
|
||||
table.grid-all tbody > tr:last-child > th.tableblock, table.grid-all tbody > tr:last-child > td.tableblock, table.grid-all thead:last-child > tr > th.tableblock, table.grid-rows tbody > tr:last-child > th.tableblock, table.grid-rows tbody > tr:last-child > td.tableblock, table.grid-rows thead:last-child > tr > th.tableblock { border-bottom-width: 0; }
|
||||
table.grid-rows tfoot > tr > th.tableblock, table.grid-rows tfoot > tr > td.tableblock { border-width: 1px 0 0 0; }
|
||||
table.frame-all { border-width: 1px; }
|
||||
table.frame-sides { border-width: 0 1px; }
|
||||
table.frame-topbot { border-width: 1px 0; }
|
||||
th.halign-left, td.halign-left { text-align: left; }
|
||||
th.halign-right, td.halign-right { text-align: right; }
|
||||
th.halign-center, td.halign-center { text-align: center; }
|
||||
th.valign-top, td.valign-top { vertical-align: top; }
|
||||
th.valign-bottom, td.valign-bottom { vertical-align: bottom; }
|
||||
th.valign-middle, td.valign-middle { vertical-align: middle; }
|
||||
table thead th, table tfoot th { font-weight: bold; }
|
||||
tbody tr th { display: table-cell; line-height: 1.6; background: whitesmoke; }
|
||||
tbody tr th, tbody tr th p, tfoot tr th, tfoot tr th p { color: #333333; font-weight: bold; }
|
||||
td > div.verse { white-space: pre; }
|
||||
ul.unstyled, ol.unnumbered, ul.checklist, ul.none { list-style-type: none; }
|
||||
ul.unstyled, ol.unnumbered, ul.checklist { margin-left: 0.625em; }
|
||||
ul.checklist li > p:first-child > .fa-check-square-o:first-child, ul.checklist li > p:first-child > input[type="checkbox"]:first-child { margin-right: 0.25em; }
|
||||
ul.checklist li > p:first-child > input[type="checkbox"]:first-child { position: relative; top: 1px; }
|
||||
ul.inline { margin: 0 auto 0.625em auto; margin-left: -1.375em; margin-right: 0; padding: 0; list-style: none; overflow: hidden; }
|
||||
ul.inline > li { list-style: none; float: left; margin-left: 1.375em; display: block; }
|
||||
ul.inline > li > * { display: block; }
|
||||
.unstyled dl dt { font-weight: normal; font-style: normal; }
|
||||
ol.arabic { list-style-type: decimal; }
|
||||
ol.decimal { list-style-type: decimal-leading-zero; }
|
||||
ol.loweralpha { list-style-type: lower-alpha; }
|
||||
ol.upperalpha { list-style-type: upper-alpha; }
|
||||
ol.lowerroman { list-style-type: lower-roman; }
|
||||
ol.upperroman { list-style-type: upper-roman; }
|
||||
ol.lowergreek { list-style-type: lower-greek; }
|
||||
.hdlist > table, .colist > table { border: 0; background: none; }
|
||||
.hdlist > table > tbody > tr, .colist > table > tbody > tr { background: none; }
|
||||
td.hdlist1 { padding-right: .75em; font-weight: bold; }
|
||||
td.hdlist1, td.hdlist2 { vertical-align: top; }
|
||||
.literalblock + .colist, .listingblock + .colist { margin-top: -0.5em; }
|
||||
.colist > table tr > td:first-of-type { padding: 0 .75em; line-height: 1; }
|
||||
.colist > table tr > td:last-of-type { padding: 0.25em 0; }
|
||||
.qanda > ol > li > p > em:only-child { color: #1d4b8f; }
|
||||
.thumb, .th { line-height: 0; display: inline-block; border: solid 4px white; -webkit-box-shadow: 0 0 0 1px #dddddd; box-shadow: 0 0 0 1px #dddddd; }
|
||||
.imageblock.left, .imageblock[style*="float: left"] { margin: 0.25em 0.625em 1.25em 0; }
|
||||
.imageblock.right, .imageblock[style*="float: right"] { margin: 0.25em 0 1.25em 0.625em; }
|
||||
.imageblock > .title { margin-bottom: 0; }
|
||||
.imageblock.thumb, .imageblock.th { border-width: 6px; }
|
||||
.imageblock.thumb > .title, .imageblock.th > .title { padding: 0 0.125em; }
|
||||
.image.left, .image.right { margin-top: 0.25em; margin-bottom: 0.25em; display: inline-block; line-height: 0; }
|
||||
.image.left { margin-right: 0.625em; }
|
||||
.image.right { margin-left: 0.625em; }
|
||||
a.image { text-decoration: none; }
|
||||
span.footnote, span.footnoteref { vertical-align: super; font-size: 0.875em; }
|
||||
span.footnote a, span.footnoteref a { text-decoration: none; }
|
||||
span.footnote a:active, span.footnoteref a:active { text-decoration: underline; }
|
||||
#footnotes { padding-top: 0.75em; padding-bottom: 0.75em; margin-bottom: 0.625em; }
|
||||
#footnotes hr { width: 20%; min-width: 6.25em; margin: -.25em 0 .75em 0; border-width: 1px 0 0 0; }
|
||||
#footnotes .footnote { padding: 0 0.375em; line-height: 1.3; font-size: 0.875em; margin-left: 1.2em; text-indent: -1.2em; margin-bottom: .2em; }
|
||||
#footnotes .footnote a:first-of-type { font-weight: bold; text-decoration: none; }
|
||||
#footnotes .footnote:last-of-type { margin-bottom: 0; }
|
||||
#content #footnotes { margin-top: -0.625em; margin-bottom: 0; padding: 0.75em 0; }
|
||||
.gist .file-data > table { border: none; background: #fff; width: 100%; margin-bottom: 0; }
|
||||
.gist .file-data > table td.line-data { width: 99%; }
|
||||
div.unbreakable { page-break-inside: avoid; }
|
||||
.replaceable { font-style: italic; font-color: inherit; font-family: inherit; }
|
||||
.parameter { font-style: italic; font-family: monospace; }
|
||||
.userinput { font-weight: bold; font-family: monospace; }
|
||||
.envar { font-weight: bold; font-family: monospace; font-size: 90%; }
|
||||
.sysitem { font-weight: bold; font-size: 90%; }
|
||||
.package { font-weight: bold; font-size: 90%; }
|
||||
.filename { font-weight: bold; font-style: italic; font-size: 90%; }
|
||||
.big { font-size: larger; }
|
||||
.small { font-size: smaller; }
|
||||
.underline { text-decoration: underline; }
|
||||
.overline { text-decoration: overline; }
|
||||
.line-through { text-decoration: line-through; }
|
||||
.aqua { color: #00bfbf; }
|
||||
.aqua-background { background-color: #00fafa; }
|
||||
.black { color: black; }
|
||||
.black-background { background-color: black; }
|
||||
.blue { color: #0000bf; }
|
||||
.blue-background { background-color: #0000fa; }
|
||||
.fuchsia { color: #bf00bf; }
|
||||
.fuchsia-background { background-color: #fa00fa; }
|
||||
.gray { color: #606060; }
|
||||
.gray-background { background-color: #7d7d7d; }
|
||||
.green { color: #006000; }
|
||||
.green-background { background-color: #007d00; }
|
||||
.lime { color: #00bf00; }
|
||||
.lime-background { background-color: #00fa00; }
|
||||
.maroon { color: #600000; }
|
||||
.maroon-background { background-color: #7d0000; }
|
||||
.navy { color: #000060; }
|
||||
.navy-background { background-color: #00007d; }
|
||||
.olive { color: #606000; }
|
||||
.olive-background { background-color: #7d7d00; }
|
||||
.purple { color: #600060; }
|
||||
.purple-background { background-color: #7d007d; }
|
||||
.red { color: #bf0000; }
|
||||
.red-background { background-color: #fa0000; }
|
||||
.silver { color: #909090; }
|
||||
.silver-background { background-color: #bcbcbc; }
|
||||
.teal { color: #006060; }
|
||||
.teal-background { background-color: #007d7d; }
|
||||
.white { color: #bfbfbf; }
|
||||
.white-background { background-color: #fafafa; }
|
||||
.yellow { color: #bfbf00; }
|
||||
.yellow-background { background-color: #fafa00; }
|
||||
span.icon > .fa { cursor: default; }
|
||||
.admonitionblock td.icon [class^="fa icon-"] { font-size: 2.5em; cursor: default; }
|
||||
.admonitionblock td.icon .icon-note:before { content: "\f05a"; color: #4E9FDD; }
|
||||
.admonitionblock td.icon .icon-tip:before { content: "\f0eb"; color: #2C8596; }
|
||||
.admonitionblock td.icon .icon-warning:before { content: "\f071"; color: #ec7a08; }
|
||||
.admonitionblock td.icon .icon-caution:before { content: "\f06d"; color: #ec7a08; }
|
||||
.admonitionblock td.icon .icon-important:before { content: "\f06a"; color: #c00; }
|
||||
.conum[data-value] { display: inline-block; color: white !important; background-color: #333333; -webkit-border-radius: 100px; border-radius: 100px; text-align: center; width: 20px; height: 20px; font-size: 12px; line-height: 20px; font-family: "Open Sans", "Sans", sans-serif; font-style: normal; font-weight: bold; text-indent: -1px; }
|
||||
.conum[data-value] * { color: white !important; }
|
||||
.conum[data-value] + b { display: none; }
|
||||
.conum[data-value]:after { content: attr(data-value); }
|
||||
pre .conum[data-value] { position: relative; top: -2px; }
|
||||
b.conum * { color: inherit !important; }
|
||||
.conum:not([data-value]):empty { display: none; }
|
||||
.print-only { display: none !important; }
|
||||
@media print { @page { margin: 1.25cm 0.75cm; }
|
||||
* { -webkit-box-shadow: none !important; box-shadow: none !important; text-shadow: none !important; }
|
||||
a, a:visited { color: inherit !important; text-decoration: underline !important; }
|
||||
a[href^="http:"]:after, a[href^="https:"]:after { content: " (" attr(href) ")"; }
|
||||
a[href^="#"], a[href^="#"]:visited, a[href^="mailto:"], a[href^="mailto:"]:visited { text-decoration: none !important; }
|
||||
abbr[title]:after { content: " (" attr(title) ")"; }
|
||||
pre, blockquote { page-break-inside: avoid; }
|
||||
code { color: #191919; }
|
||||
thead { display: table-header-group; }
|
||||
tr, img { page-break-inside: avoid; }
|
||||
img { max-width: 100% !important; }
|
||||
p { orphans: 3; widows: 3; }
|
||||
h2, h3, #toctitle, .sidebarblock > .content > .title, #toctitle, .sidebarblock > .content > .title { page-break-after: avoid; }
|
||||
#toc, .sidebarblock { background: none !important; }
|
||||
#toc { border-bottom: 1px solid #d8d8d8 !important; padding-bottom: 0 !important; }
|
||||
.sect1 { padding-bottom: 0 !important; }
|
||||
.sect1 + .sect1 { border: none !important; }
|
||||
body.book #header { text-align: center; }
|
||||
body.book #header > h1 { border: none !important; margin: 2.5em 0 1em 0; padding: 0; }
|
||||
body.book #header span { line-height: 1.6; }
|
||||
body.book #header br { display: block; }
|
||||
body.book #header br + span { padding-left: 0; }
|
||||
body.book #header br + span:before { content: none !important; }
|
||||
body.book #toc { border: none !important; text-align: left !important; padding: 0 !important; }
|
||||
#footer { background: none !important; }
|
||||
#footer-text { color: #333333 !important; }
|
||||
.hide-on-print { display: none !important; }
|
||||
.print-only { display: block !important; }
|
||||
.hide-for-print { display: none !important; }
|
||||
.show-for-print { display: inherit !important; } }
|
||||
|
||||
.corner-ribbon{
|
||||
width: 16em;
|
||||
background: #3c6eb4 ;
|
||||
position: absolute;
|
||||
top: 3em;
|
||||
right: -4em;
|
||||
text-align: center;
|
||||
line-height: 5ex;
|
||||
color: #dedede;
|
||||
transform: rotate(45deg);
|
||||
-webkit-transform: rotate(45deg);
|
||||
z-index: 999;
|
||||
}
|
||||
.corner-ribbon a { color: #FFFFFF; }
|
|
@ -1,348 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta content="IE=edge" http-equiv="X-UA-Compatible">
|
||||
<meta content="width=device-width, initial-scale=1.0" name="viewport">
|
||||
<title>Defensive Coding Guide | Defensive Coding Guide | Revision History</title>
|
||||
|
||||
<!-- Bootstrap -->
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap-theme.min.css">
|
||||
|
||||
<!-- Overpass Font -->
|
||||
<link rel="stylesheet" href="https://overpass-30e2.kxcdn.com/overpass.css">
|
||||
|
||||
<link href="../../master/_stylesheets/asciibinder.css" rel="stylesheet" />
|
||||
|
||||
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
|
||||
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
|
||||
<!--[if lt IE 9]>
|
||||
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
|
||||
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
|
||||
<![endif]-->
|
||||
|
||||
<link href="../../master/_images/favicon32x32.png" rel="shortcut icon" type="text/css">
|
||||
<!--[if IE]><link rel="shortcut icon" href="../../master/_images/favicon.ico"><![endif]-->
|
||||
<meta content="AsciiBinder" name="application-name">
|
||||
</head>
|
||||
<body>
|
||||
<div class="navbar navbar-default" role="navigation">
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-header">
|
||||
<a class="navbar-brand" href="https://docs.fedoraproject.org/"><img alt="Fedora Documentation" src="../../master/_images/fedora.svg"></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container">
|
||||
<p class="toggle-nav visible-xs pull-left">
|
||||
<button class="btn btn-default btn-sm" type="button" data-toggle="offcanvas">Toggle nav</button>
|
||||
</p>
|
||||
<ol class="breadcrumb">
|
||||
<li class="sitename">
|
||||
<a href="../../index.html">Home</a>
|
||||
</li>
|
||||
<li class="hidden-xs active">
|
||||
<a href="../en-US/index.html">Defensive Coding Guide </a>
|
||||
</li>
|
||||
<li class="hidden-xs active">
|
||||
<a href="../en-US/index.html">Defensive Coding Guide</a>
|
||||
</li>
|
||||
|
||||
<li class="hidden-xs active">
|
||||
Revision History
|
||||
</li>
|
||||
</ol>
|
||||
<div class="row row-offcanvas row-offcanvas-left">
|
||||
<div class="col-xs-8 col-sm-3 col-md-3 sidebar sidebar-offcanvas">
|
||||
<ul class="nav nav-sidebar">
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicGroup0">
|
||||
<span id="tgSpan0" class="fa fa-angle-down"></span>Defensive Coding Guide
|
||||
</a>
|
||||
<ul id="topicGroup0" class="collapse in list-unstyled">
|
||||
<li><a class="" href="../en-US/index.html">Book Information</a></li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-1">
|
||||
<span id="sgSpan-0-1" class="fa fa-caret-right"></span> Programming Languages
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-1" class="nav-tertiary list-unstyled collapse">
|
||||
<li><a class="" href="../en-US/programming-languages/C.html">The C Programming Language</a></li>
|
||||
<li><a class="" href="../en-US/programming-languages/CXX.html">The C++ Programming Language</a></li>
|
||||
<li><a class="" href="../en-US/programming-languages/Java.html">The Java Programming Language</a></li>
|
||||
<li><a class="" href="../en-US/programming-languages/Python.html">The Python Programming Language</a></li>
|
||||
<li><a class="" href="../en-US/programming-languages/Shell.html">Shell Programming and bash</a></li>
|
||||
<li><a class="" href="../en-US/programming-languages/Go.html">The Go Programming Language</a></li>
|
||||
<li><a class="" href="../en-US/programming-languages/Vala.html">The Vala Programming Language</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-2">
|
||||
<span id="sgSpan-0-2" class="fa fa-caret-right"></span> Specific Programming Tasks
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-2" class="nav-tertiary list-unstyled collapse">
|
||||
<li><a class="" href="../en-US/tasks/Tasks-Library_Design.html">Library Design</a></li>
|
||||
<li><a class="" href="../en-US/tasks/Tasks-Descriptors.html">File Descriptor Management</a></li>
|
||||
<li><a class="" href="../en-US/tasks/Tasks-File_System.html">File System Manipulation</a></li>
|
||||
<li><a class="" href="../en-US/tasks/Tasks-Temporary_Files.html">Temporary Files</a></li>
|
||||
<li><a class="" href="../en-US/tasks/Tasks-Processes.html">Processes</a></li>
|
||||
<li><a class="" href="../en-US/tasks/Tasks-Serialization.html">Serialization and Deserialization</a></li>
|
||||
<li><a class="" href="../en-US/tasks/Tasks-Cryptography.html">Cryptography</a></li>
|
||||
<li><a class="" href="../en-US/tasks/Tasks-Packaging.html">RPM Packaging</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-3">
|
||||
<span id="sgSpan-0-3" class="fa fa-caret-right"></span> Implementing Security Features
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-3" class="nav-tertiary list-unstyled collapse">
|
||||
<li><a class="" href="../en-US/features/Features-Authentication.html">Authentication and Authorization</a></li>
|
||||
<li><a class="" href="../en-US/features/Features-TLS.html">Transport Layer Security (TLS)</a></li>
|
||||
<li><a class="" href="../en-US/features/Features-HSM.html">Hardware Security Modules and Smart Cards</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class=" active" href="../en-US/Revision_History.html">Revision History</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-9 col-md-9 main">
|
||||
<div class="page-header">
|
||||
<h2>Revision History</h2>
|
||||
</div>
|
||||
<div class="dlist">
|
||||
<dl>
|
||||
<dt class="hdlist1"><code>1.5</code></dt>
|
||||
<dd>
|
||||
<p>Fri Dec 1 2017, Mirek Jahoda (<a href="mailto:mjahoda@redhat.com">mjahoda@redhat.com</a>)</p>
|
||||
<div class="ulist">
|
||||
<ul>
|
||||
<li>
|
||||
<p>First release in AsciiDoc</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Many updates in the crypto-related sections</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Grammar and typography fixes</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</dd>
|
||||
<dt class="hdlist1"><code>1.3-1</code></dt>
|
||||
<dd>
|
||||
<p>Mon Oct 13 2014, Florian Weimer (<a href="mailto:fweimer@redhat.com">fweimer@redhat.com</a>)</p>
|
||||
<div class="ulist">
|
||||
<ul>
|
||||
<li>
|
||||
<p>Go: Mention default value handling in deserialization</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Shell: New chapter</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</dd>
|
||||
<dt class="hdlist1"><code>1.2-1</code></dt>
|
||||
<dd>
|
||||
<p>Wed Jul 16 2014, Florian Weimer (<a href="mailto:fweimer@redhat.com">fweimer@redhat.com</a>)</p>
|
||||
<div class="ulist">
|
||||
<ul>
|
||||
<li>
|
||||
<p>C: Corrected the <code>strncat</code> example</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>C: Mention mixed signed/unsigned comparisons</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>C: Unsigned overflow checking example</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>C++: <code>operator new[]</code> has been fixed in GCC</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>C++: Additional material on <code>std::string</code>, iterators</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>OpenSSL: Mention <code class="command">openssl genrsa</code> entropy issue</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Packaging: X.509 key generation</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Go, Vala: Add short chapters</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Serialization: Notes on fragmentation and reassembly</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</dd>
|
||||
<dt class="hdlist1"><code>1.1-1</code></dt>
|
||||
<dd>
|
||||
<p>Tue Aug 27 2013, Eric Christensen (<a href="mailto:sparks@redhat.com">sparks@redhat.com</a>)</p>
|
||||
<div class="ulist">
|
||||
<ul>
|
||||
<li>
|
||||
<p>Add a chapter which covers some Java topics.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Deserialization: Warn about Java’s java.beans.XMLDecoder.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>C: Correct the advice on array allocation
|
||||
(<a href="https://bugzilla.redhat.com/show_bug.cgi?id=995595">bug 995595</a>).</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>C: Add material on global variables.</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</dd>
|
||||
<dt class="hdlist1"><code>1.0-1</code></dt>
|
||||
<dd>
|
||||
<p>Thu May 09 2013, Eric Christensen (<a href="mailto:sparks@redhat.com">sparks@redhat.com</a>)</p>
|
||||
<div class="ulist">
|
||||
<ul>
|
||||
<li>
|
||||
<p>Added more C and C++ examples.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>TLS Client NSS: Rely on NSS 3.14 cipher suite defaults.</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</dd>
|
||||
<dt class="hdlist1"><code>0-1</code></dt>
|
||||
<dd>
|
||||
<p>Thu Mar 7 2013, Eric Christensen (<a href="mailto:sparks@redhat.com">sparks@redhat.com</a>)</p>
|
||||
<div class="ulist">
|
||||
<ul>
|
||||
<li>
|
||||
<p>Initial publication.</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="bottom" class="text-muted py-3" >
|
||||
<div class="foot">
|
||||
<div class="container">
|
||||
<div class="row footerlinks">
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">About</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Overview">About Fedora</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/sponsors">Sponsors</a></dd>
|
||||
<dd><a href="https://fedoramagazine.org">Fedora Magazine</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Legal:Main#Legal">Legal</a></dd>
|
||||
</dl>
|
||||
<ul class="list-inline">
|
||||
<li>
|
||||
<a href="https://www.facebook.com/TheFedoraProject" class="btn-social btn-outline"><i class="fa fa-fw fa-facebook"></i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://plus.google.com/112917221531140868607" class="btn-social btn-outline"><i class="fa fa-fw fa-google-plus"></i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://twitter.com/fedora" class="btn-social btn-outline"><i class="fa fa-fw fa-twitter"></i></a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title uppercase">Download</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://getfedora.org/en/workstation/download">Get Fedora Workstation</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/server/download">Get Fedora Server</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/atomic/download">Get Fedora Atomic</a></dd>
|
||||
<dd><a href="https://spins.fedoraproject.org">Fedora Spins</a></dd>
|
||||
<dd><a href="https://labs.fedoraproject.org">Fedora Labs</a></dd>
|
||||
<dd><a href="https://arm.fedoraproject.org">Fedora ARM<span class="sup">®</span></a></dd>
|
||||
<dd><a href="https://alt.fedoraproject.org/">Alternative Downloads</a></dd>
|
||||
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">Support</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Communicating_and_getting_help">Get Help</a></dd>
|
||||
<dd><a href="https://ask.fedoraproject.org/">Ask Fedora</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Common_F27_bugs">Common Bugs</a></dd>
|
||||
<dd><a href="https://developer.fedoraproject.org/">Fedora Developer Portal</a></dd>
|
||||
<dd><a href="https://docs.fedoraproject.org/f27/install-guide/index.html">Installation Guide</a></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">Join</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Join">Join Fedora</a></dd>
|
||||
<dd><a href="http://fedoraplanet.org">Planet Fedora</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/SIGs">Fedora SIGs</a></dd>
|
||||
<dd><a href="https://admin.fedoraproject.org/accounts/">Fedora Account System</a></dd>
|
||||
<dd><a href="https://fedoracommunity.org/">Fedora Community</a></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- /row of widgets -->
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-2">
|
||||
<div class="widget-body">
|
||||
<a href="https://www.redhat.com/"><img class="rh-logo" src="../../master/_images/redhat-logo.png" alt="Red Hat Logo" /></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-7">
|
||||
<div class="widget-body">
|
||||
<p class="sponsor">Fedora is sponsored by Red Hat.</p>
|
||||
<p class="sponsor"><a href="https://www.redhat.com/en/technologies/linux-platforms/articles/relationship-between-fedora-and-rhel">Learn more about the relationship between Red Hat and Fedora »</a></p>
|
||||
<p class="copy">© 2017 Red Hat, Inc. and others. Please send any comments or corrections to the <a href="https://pagure.io/fedora-docs/docs-fp-o">documentation team</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- /row of widgets -->
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
|
||||
<!-- Latest compiled and minified JavaScript -->
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
|
||||
<script src="../../master/_javascripts/bootstrap-offcanvas.js" type="text/javascript"></script>
|
||||
<script type="text/javascript">
|
||||
/*<![CDATA[*/
|
||||
$(document).ready(function() {
|
||||
$("[id^='topicGroup']").on('show.bs.collapse', function (event) {
|
||||
if (!($(event.target).attr('id').match(/^topicSubGroup/))) {
|
||||
$(this).parent().find("[id^='tgSpan']").toggleClass("fa-angle-right fa-angle-down");
|
||||
}
|
||||
});
|
||||
$("[id^='topicGroup']").on('hide.bs.collapse', function (event) {
|
||||
if (!($(event.target).attr('id').match(/^topicSubGroup/))) {
|
||||
$(this).parent().find("[id^='tgSpan']").toggleClass("fa-angle-right fa-angle-down");
|
||||
}
|
||||
});
|
||||
$("[id^='topicSubGroup']").on('show.bs.collapse', function () {
|
||||
$(this).parent().find("[id^='sgSpan']").toggleClass("fa-caret-right fa-caret-down");
|
||||
});
|
||||
$("[id^='topicSubGroup']").on('hide.bs.collapse', function () {
|
||||
$(this).parent().find("[id^='sgSpan']").toggleClass("fa-caret-right fa-caret-down");
|
||||
});
|
||||
});
|
||||
/*]]>*/
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -1,410 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta content="IE=edge" http-equiv="X-UA-Compatible">
|
||||
<meta content="width=device-width, initial-scale=1.0" name="viewport">
|
||||
<title>Defensive Coding Guide | Defensive Coding Guide | Implementing Security Features | Authentication and Authorization</title>
|
||||
|
||||
<!-- Bootstrap -->
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap-theme.min.css">
|
||||
|
||||
<!-- Overpass Font -->
|
||||
<link rel="stylesheet" href="https://overpass-30e2.kxcdn.com/overpass.css">
|
||||
|
||||
<link href="../../../master/_stylesheets/asciibinder.css" rel="stylesheet" />
|
||||
|
||||
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
|
||||
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
|
||||
<!--[if lt IE 9]>
|
||||
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
|
||||
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
|
||||
<![endif]-->
|
||||
|
||||
<link href="../../../master/_images/favicon32x32.png" rel="shortcut icon" type="text/css">
|
||||
<!--[if IE]><link rel="shortcut icon" href="../../../master/_images/favicon.ico"><![endif]-->
|
||||
<meta content="AsciiBinder" name="application-name">
|
||||
</head>
|
||||
<body>
|
||||
<div class="navbar navbar-default" role="navigation">
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-header">
|
||||
<a class="navbar-brand" href="https://docs.fedoraproject.org/"><img alt="Fedora Documentation" src="../../../master/_images/fedora.svg"></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container">
|
||||
<p class="toggle-nav visible-xs pull-left">
|
||||
<button class="btn btn-default btn-sm" type="button" data-toggle="offcanvas">Toggle nav</button>
|
||||
</p>
|
||||
<ol class="breadcrumb">
|
||||
<li class="sitename">
|
||||
<a href="../../../index.html">Home</a>
|
||||
</li>
|
||||
<li class="hidden-xs active">
|
||||
<a href="../../en-US/index.html">Defensive Coding Guide </a>
|
||||
</li>
|
||||
<li class="hidden-xs active">
|
||||
<a href="../../en-US/index.html">Defensive Coding Guide</a>
|
||||
</li>
|
||||
<li class="hidden-xs active"><a href="../../en-US/features/Features-Authentication.html">Implementing Security Features</a></li>
|
||||
<li class="hidden-xs active">
|
||||
Authentication and Authorization
|
||||
</li>
|
||||
</ol>
|
||||
<div class="row row-offcanvas row-offcanvas-left">
|
||||
<div class="col-xs-8 col-sm-3 col-md-3 sidebar sidebar-offcanvas">
|
||||
<ul class="nav nav-sidebar">
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicGroup0">
|
||||
<span id="tgSpan0" class="fa fa-angle-down"></span>Defensive Coding Guide
|
||||
</a>
|
||||
<ul id="topicGroup0" class="collapse in list-unstyled">
|
||||
<li><a class="" href="../../en-US/index.html">Book Information</a></li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-1">
|
||||
<span id="sgSpan-0-1" class="fa fa-caret-right"></span> Programming Languages
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-1" class="nav-tertiary list-unstyled collapse">
|
||||
<li><a class="" href="../../en-US/programming-languages/C.html">The C Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/CXX.html">The C++ Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Java.html">The Java Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Python.html">The Python Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Shell.html">Shell Programming and bash</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Go.html">The Go Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Vala.html">The Vala Programming Language</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-2">
|
||||
<span id="sgSpan-0-2" class="fa fa-caret-right"></span> Specific Programming Tasks
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-2" class="nav-tertiary list-unstyled collapse">
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Library_Design.html">Library Design</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Descriptors.html">File Descriptor Management</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-File_System.html">File System Manipulation</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Temporary_Files.html">Temporary Files</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Processes.html">Processes</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Serialization.html">Serialization and Deserialization</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Cryptography.html">Cryptography</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Packaging.html">RPM Packaging</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-3">
|
||||
<span id="sgSpan-0-3" class="fa fa-caret-down"></span> Implementing Security Features
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-3" class="nav-tertiary list-unstyled collapse in">
|
||||
<li><a class=" active" href="../../en-US/features/Features-Authentication.html">Authentication and Authorization</a></li>
|
||||
<li><a class="" href="../../en-US/features/Features-TLS.html">Transport Layer Security (TLS)</a></li>
|
||||
<li><a class="" href="../../en-US/features/Features-HSM.html">Hardware Security Modules and Smart Cards</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="" href="../../en-US/Revision_History.html">Revision History</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-9 col-md-9 main">
|
||||
<div class="page-header">
|
||||
<h2>Authentication and Authorization</h2>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="sect-Defensive_Coding-Authentication-Server"><a class="anchor" href="#sect-Defensive_Coding-Authentication-Server"></a>Authenticating Servers</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>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:</p>
|
||||
</div>
|
||||
<div class="ulist">
|
||||
<ul>
|
||||
<li>
|
||||
<p>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.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>The server uses a TLS certificate which is expected by the
|
||||
client (perhaps it is stored in a configuration file read by
|
||||
the client). In this case, no host name checking is
|
||||
required.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>On Linux, UNIX domain sockets (of the
|
||||
<code>PF_UNIX</code> protocol family, sometimes called
|
||||
<code>PF_LOCAL</code>) are restricted by file system
|
||||
permissions. If the server socket path is not
|
||||
world-writable, the server identity cannot be spoofed by
|
||||
local users.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Port numbers less than 1024 (<strong>trusted
|
||||
ports</strong>) can only be used by
|
||||
<code>root</code>, 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.)</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>TLS (<a href="#chap-Defensive_Coding-TLS">[chap-Defensive_Coding-TLS]</a>) is the
|
||||
recommended way for securing connections over untrusted
|
||||
networks.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>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.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="sect-Defensive_Coding-Authentication-Host_based"><a class="anchor" href="#sect-Defensive_Coding-Authentication-Host_based"></a>Host-based Authentication</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>Host-based authentication uses access control lists (ACLs) to
|
||||
accept or deny requests from clients. This authentication
|
||||
method comes in two flavors: IP-based (or, more generally,
|
||||
address-based) and name-based (with the name coming from DNS or
|
||||
<code>/etc/hosts</code>). 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.)</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>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.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>The names returned by <code>gethostbyaddr</code> and
|
||||
<code>getnameinfo</code> 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
|
||||
<code>gethostbyaddr</code> or
|
||||
<code>getaddrinfo</code> has to be performed. The name
|
||||
is only valid if the original address is found among the results
|
||||
of the forward lookup (<strong>double-reverse
|
||||
lookup</strong>).</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>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.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>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.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>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.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="sect-Defensive_Coding-Authentication-UNIX_Domain"><a class="anchor" href="#sect-Defensive_Coding-Authentication-UNIX_Domain"></a>UNIX Domain Socket Authentication</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>UNIX domain sockets (with address family
|
||||
<code>AF_UNIX</code> or <code>AF_LOCAL</code>) are
|
||||
restricted to the local host and offer a special authentication
|
||||
mechanism: credentials passing.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Nowadays, most systems support the
|
||||
<code>SO_PEERCRED</code> (Linux) or
|
||||
<code>LOCAL_PEERCRED</code> (FreeBSD) socket options, or
|
||||
the <code>getpeereid</code> (other BSDs, OS 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.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Historically, credentials passing was implemented using
|
||||
ancillary data in the <code>sendmsg</code> and
|
||||
<code>recvmsg</code> 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.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>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
|
||||
<code>getpwuid</code> (or
|
||||
<code>getpwuid_r</code>) and
|
||||
<code>getgrouplist</code>. Using the PID and
|
||||
information from <code>/proc/PID/status</code> is prone
|
||||
to race conditions and insecure.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="sect-Defensive_Coding-Authentication-Netlink"><a class="anchor" href="#sect-Defensive_Coding-Authentication-Netlink"></a><code>AF_NETLINK</code> Authentication of Origin</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>Netlink messages are used as a high-performance data transfer
|
||||
mechanism between the kernel and the user space. Traditionally,
|
||||
they are used to exchange information related to the network
|
||||
stack, such as routing table entries.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>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
|
||||
<code>nl_pid</code> in the <code>sockaddr_nl</code>
|
||||
structure is <code>0</code>. (This structure can be
|
||||
obtained using <code>recvfrom</code> or
|
||||
<code>recvmsg</code>, it is different from the
|
||||
<code>nlmsghdr</code> structure.) The kernel does not
|
||||
prevent other processes from sending unicast Netlink messages,
|
||||
but the <code>nl_pid</code> field in the sender’s socket
|
||||
address will be non-zero in such cases.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Applications should not use <code>AF_NETLINK</code>
|
||||
sockets as an IPC mechanism among processes, but prefer UNIX
|
||||
domain sockets for this tasks.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="bottom" class="text-muted py-3" >
|
||||
<div class="foot">
|
||||
<div class="container">
|
||||
<div class="row footerlinks">
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">About</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Overview">About Fedora</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/sponsors">Sponsors</a></dd>
|
||||
<dd><a href="https://fedoramagazine.org">Fedora Magazine</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Legal:Main#Legal">Legal</a></dd>
|
||||
</dl>
|
||||
<ul class="list-inline">
|
||||
<li>
|
||||
<a href="https://www.facebook.com/TheFedoraProject" class="btn-social btn-outline"><i class="fa fa-fw fa-facebook"></i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://plus.google.com/112917221531140868607" class="btn-social btn-outline"><i class="fa fa-fw fa-google-plus"></i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://twitter.com/fedora" class="btn-social btn-outline"><i class="fa fa-fw fa-twitter"></i></a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title uppercase">Download</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://getfedora.org/en/workstation/download">Get Fedora Workstation</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/server/download">Get Fedora Server</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/atomic/download">Get Fedora Atomic</a></dd>
|
||||
<dd><a href="https://spins.fedoraproject.org">Fedora Spins</a></dd>
|
||||
<dd><a href="https://labs.fedoraproject.org">Fedora Labs</a></dd>
|
||||
<dd><a href="https://arm.fedoraproject.org">Fedora ARM<span class="sup">®</span></a></dd>
|
||||
<dd><a href="https://alt.fedoraproject.org/">Alternative Downloads</a></dd>
|
||||
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">Support</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Communicating_and_getting_help">Get Help</a></dd>
|
||||
<dd><a href="https://ask.fedoraproject.org/">Ask Fedora</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Common_F27_bugs">Common Bugs</a></dd>
|
||||
<dd><a href="https://developer.fedoraproject.org/">Fedora Developer Portal</a></dd>
|
||||
<dd><a href="https://docs.fedoraproject.org/f27/install-guide/index.html">Installation Guide</a></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">Join</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Join">Join Fedora</a></dd>
|
||||
<dd><a href="http://fedoraplanet.org">Planet Fedora</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/SIGs">Fedora SIGs</a></dd>
|
||||
<dd><a href="https://admin.fedoraproject.org/accounts/">Fedora Account System</a></dd>
|
||||
<dd><a href="https://fedoracommunity.org/">Fedora Community</a></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- /row of widgets -->
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-2">
|
||||
<div class="widget-body">
|
||||
<a href="https://www.redhat.com/"><img class="rh-logo" src="../../../master/_images/redhat-logo.png" alt="Red Hat Logo" /></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-7">
|
||||
<div class="widget-body">
|
||||
<p class="sponsor">Fedora is sponsored by Red Hat.</p>
|
||||
<p class="sponsor"><a href="https://www.redhat.com/en/technologies/linux-platforms/articles/relationship-between-fedora-and-rhel">Learn more about the relationship between Red Hat and Fedora »</a></p>
|
||||
<p class="copy">© 2017 Red Hat, Inc. and others. Please send any comments or corrections to the <a href="https://pagure.io/fedora-docs/docs-fp-o">documentation team</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- /row of widgets -->
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
|
||||
<!-- Latest compiled and minified JavaScript -->
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
|
||||
<script src="../../../master/_javascripts/bootstrap-offcanvas.js" type="text/javascript"></script>
|
||||
<script type="text/javascript">
|
||||
/*<![CDATA[*/
|
||||
$(document).ready(function() {
|
||||
$("[id^='topicGroup']").on('show.bs.collapse', function (event) {
|
||||
if (!($(event.target).attr('id').match(/^topicSubGroup/))) {
|
||||
$(this).parent().find("[id^='tgSpan']").toggleClass("fa-angle-right fa-angle-down");
|
||||
}
|
||||
});
|
||||
$("[id^='topicGroup']").on('hide.bs.collapse', function (event) {
|
||||
if (!($(event.target).attr('id').match(/^topicSubGroup/))) {
|
||||
$(this).parent().find("[id^='tgSpan']").toggleClass("fa-angle-right fa-angle-down");
|
||||
}
|
||||
});
|
||||
$("[id^='topicSubGroup']").on('show.bs.collapse', function () {
|
||||
$(this).parent().find("[id^='sgSpan']").toggleClass("fa-caret-right fa-caret-down");
|
||||
});
|
||||
$("[id^='topicSubGroup']").on('hide.bs.collapse', function () {
|
||||
$(this).parent().find("[id^='sgSpan']").toggleClass("fa-caret-right fa-caret-down");
|
||||
});
|
||||
});
|
||||
/*]]>*/
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -1,617 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta content="IE=edge" http-equiv="X-UA-Compatible">
|
||||
<meta content="width=device-width, initial-scale=1.0" name="viewport">
|
||||
<title>Defensive Coding Guide | Defensive Coding Guide | Implementing Security Features | Hardware Security Modules and Smart Cards</title>
|
||||
|
||||
<!-- Bootstrap -->
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap-theme.min.css">
|
||||
|
||||
<!-- Overpass Font -->
|
||||
<link rel="stylesheet" href="https://overpass-30e2.kxcdn.com/overpass.css">
|
||||
|
||||
<link href="../../../master/_stylesheets/asciibinder.css" rel="stylesheet" />
|
||||
|
||||
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
|
||||
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
|
||||
<!--[if lt IE 9]>
|
||||
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
|
||||
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
|
||||
<![endif]-->
|
||||
|
||||
<link href="../../../master/_images/favicon32x32.png" rel="shortcut icon" type="text/css">
|
||||
<!--[if IE]><link rel="shortcut icon" href="../../../master/_images/favicon.ico"><![endif]-->
|
||||
<meta content="AsciiBinder" name="application-name">
|
||||
</head>
|
||||
<body>
|
||||
<div class="navbar navbar-default" role="navigation">
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-header">
|
||||
<a class="navbar-brand" href="https://docs.fedoraproject.org/"><img alt="Fedora Documentation" src="../../../master/_images/fedora.svg"></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container">
|
||||
<p class="toggle-nav visible-xs pull-left">
|
||||
<button class="btn btn-default btn-sm" type="button" data-toggle="offcanvas">Toggle nav</button>
|
||||
</p>
|
||||
<ol class="breadcrumb">
|
||||
<li class="sitename">
|
||||
<a href="../../../index.html">Home</a>
|
||||
</li>
|
||||
<li class="hidden-xs active">
|
||||
<a href="../../en-US/index.html">Defensive Coding Guide </a>
|
||||
</li>
|
||||
<li class="hidden-xs active">
|
||||
<a href="../../en-US/index.html">Defensive Coding Guide</a>
|
||||
</li>
|
||||
<li class="hidden-xs active"><a href="../../en-US/features/Features-Authentication.html">Implementing Security Features</a></li>
|
||||
<li class="hidden-xs active">
|
||||
Hardware Security Modules and Smart Cards
|
||||
</li>
|
||||
</ol>
|
||||
<div class="row row-offcanvas row-offcanvas-left">
|
||||
<div class="col-xs-8 col-sm-3 col-md-3 sidebar sidebar-offcanvas">
|
||||
<ul class="nav nav-sidebar">
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicGroup0">
|
||||
<span id="tgSpan0" class="fa fa-angle-down"></span>Defensive Coding Guide
|
||||
</a>
|
||||
<ul id="topicGroup0" class="collapse in list-unstyled">
|
||||
<li><a class="" href="../../en-US/index.html">Book Information</a></li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-1">
|
||||
<span id="sgSpan-0-1" class="fa fa-caret-right"></span> Programming Languages
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-1" class="nav-tertiary list-unstyled collapse">
|
||||
<li><a class="" href="../../en-US/programming-languages/C.html">The C Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/CXX.html">The C++ Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Java.html">The Java Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Python.html">The Python Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Shell.html">Shell Programming and bash</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Go.html">The Go Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Vala.html">The Vala Programming Language</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-2">
|
||||
<span id="sgSpan-0-2" class="fa fa-caret-right"></span> Specific Programming Tasks
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-2" class="nav-tertiary list-unstyled collapse">
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Library_Design.html">Library Design</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Descriptors.html">File Descriptor Management</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-File_System.html">File System Manipulation</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Temporary_Files.html">Temporary Files</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Processes.html">Processes</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Serialization.html">Serialization and Deserialization</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Cryptography.html">Cryptography</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Packaging.html">RPM Packaging</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-3">
|
||||
<span id="sgSpan-0-3" class="fa fa-caret-down"></span> Implementing Security Features
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-3" class="nav-tertiary list-unstyled collapse in">
|
||||
<li><a class="" href="../../en-US/features/Features-Authentication.html">Authentication and Authorization</a></li>
|
||||
<li><a class="" href="../../en-US/features/Features-TLS.html">Transport Layer Security (TLS)</a></li>
|
||||
<li><a class=" active" href="../../en-US/features/Features-HSM.html">Hardware Security Modules and Smart Cards</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="" href="../../en-US/Revision_History.html">Revision History</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-9 col-md-9 main">
|
||||
<div class="page-header">
|
||||
<h2>Hardware Security Modules and Smart Cards</h2>
|
||||
</div>
|
||||
<div id="preamble">
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>Hardware Security Modules (HSMs) are specialized hardware intended
|
||||
to protect private keys on server systems. They store internally
|
||||
the private keys (e.g., RSA keys), and provide access to operations
|
||||
with the keys without exposing the keys. That access, is provided using
|
||||
a standardized API, which across Fedora is PKCS#11.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Smart cards are small cards with a micro processor, often combined with a
|
||||
USB reader resembling a USB stick. They are very similar in nature with
|
||||
HSMs as they can also be used to protect private keys and are almost
|
||||
universally accessed via the PKCS#11 API. The main distinguishers from HSMs
|
||||
is their inferior performance and often, the available hardware protection mechanisms.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Typically a smart card or HSM relies on a shared library to provide functionality.
|
||||
This shared library follows the PKCS#11 API and thus is often referred to as
|
||||
a PKCS#11 module. In Fedora the <code>opensc</code>
|
||||
shared module (<code>opensc-pkcs11.so</code>) can be used for the majority
|
||||
of smart cards available in the market. By convention these modules are located
|
||||
at <code>/usr/lib64/pkcs11</code>. They can be used directly, or via
|
||||
a higher level library.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>All the major crypto libraries (NSS, GnuTLS and OpenSSL in Fedora) support
|
||||
hardware security modules and smart cards, by providing wrappers over the
|
||||
PKCS#11 API. However, the level of support varies, as well as the ease of
|
||||
use of such modules and its integration to the overall library API.</p>
|
||||
</div>
|
||||
<div class="ulist">
|
||||
<ul>
|
||||
<li>
|
||||
<p>The PKCS#11 API does provide an API to access HSMs or smart cards, but
|
||||
does not provide any method of discovering which HSMs or smart cards are
|
||||
available in the system. In Fedora and modules are registered via <a href="https://p11-glue.freedesktop.org/doc/p11-kit/pkcs11-conf.html">p11-kit
|
||||
configuration files</a>, stored at <code>/etc/pkcs11/modules/</code>. For applications using
|
||||
<code>engine_pkcs11</code> or GnuTLS the registered modules are
|
||||
available without further configuration. Other applications will have to load
|
||||
the <code>p11-kit-proxy.so</code> module.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Most crypto libraries support the <a href="https://tools.ietf.org/html/rfc7512">PKCS#11 URLs scheme</a>
|
||||
to identify objects stored in an HSM, however that support is not yet universal.
|
||||
Some support transparent usage of PKCS#11 objects, e.g., specifying
|
||||
a PKCS#11 object instead of a file, while others require to use
|
||||
specialized APIs for such objects.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Objects stored in an HSM or smart card can be protected with a PIN. As such,
|
||||
libraries typically require to set a PIN handling function for accessing private keys,
|
||||
or the PIN can be passed along with a PKCS#11 URL and the pin-value parameter.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Obtaining a Hardware Security Module, or including it on a continuous integration
|
||||
testing is not always feasible. For testing purposes smart cards supported by the OpenSC
|
||||
project can be used, as well as software modules like <code>softhsm</code> which
|
||||
provides a tool to setup a software HSM, and a PKCS#11 library.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>The PKCS#11 API requires applications that use fork to reinitialize the used PKCS#11
|
||||
modules. This is an uncommon requirement, which has led to several bugs across
|
||||
applications in Fedora which used PKCS#11 directly. To make things more complicated
|
||||
software PKCS#11 module like <code>softhsm</code> do not require this re-initialization
|
||||
leading to applications working against software modules but failing with hardware
|
||||
modules or smart cards. The wrapper PKCS#11 APIs provided by NSS, GnuTLS and
|
||||
engine_pkcs11 (OpenSSL) handle the reinitialization after fork requirement transparently.</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="sect-Defensive_Coding-HSM-OpenSSL"><a class="anchor" href="#sect-Defensive_Coding-HSM-OpenSSL"></a>OpenSSL HSM Support</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>OpenSSL does not have native support for PKCS#11. It can
|
||||
provide PKCS#11 support through the OpenSC’s project
|
||||
<code>pkcs11</code> engine (formerly known as <code>engine_pkcs11</code>).
|
||||
As such software intended to use HSMs, must utilize that engine.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Engine <code>pkcs11</code> supports loading stored objects via PKCS#11 URLs.
|
||||
If no PKCS#11 module is specified the engine will use the system-wide registered
|
||||
modules via <code>p11-kit-proxy.so</code>.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>The following example demonstrates the initialization of the pkcs11 engine
|
||||
and its usage to sign data.</p>
|
||||
</div>
|
||||
<div id="ex-Defensive_Coding-HSM-OpenSSL" class="exampleblock">
|
||||
<div class="title">Example 1. Signing data with HSM and OpenSSL</div>
|
||||
<div class="content">
|
||||
<div class="listingblock">
|
||||
<div class="content">
|
||||
<pre class="CodeRay highlight"><code data-lang="c">OpenSSL_add_all_algorithms();
|
||||
ERR_load_crypto_strings();
|
||||
ERR_clear_error();
|
||||
ENGINE_load_builtin_engines();
|
||||
|
||||
e = ENGINE_by_id(<span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">"</span><span style="color:#D20">pkcs11</span><span style="color:#710">"</span></span>);
|
||||
<span style="color:#080;font-weight:bold">if</span> (!e) {
|
||||
display_openssl_errors(__LINE__);
|
||||
exit(<span style="color:#00D">1</span>);
|
||||
}
|
||||
|
||||
<span style="color:#080;font-weight:bold">if</span> (module_path) {
|
||||
fprintf(stderr, <span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">"</span><span style="color:#D20">loading: %s</span><span style="color:#b0b">\n</span><span style="color:#710">"</span></span>, module_path);
|
||||
<span style="color:#080;font-weight:bold">if</span> (!ENGINE_ctrl_cmd_string(e, <span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">"</span><span style="color:#D20">MODULE_PATH</span><span style="color:#710">"</span></span>, module_path, <span style="color:#00D">0</span>)) {
|
||||
display_openssl_errors(__LINE__);
|
||||
exit(<span style="color:#00D">1</span>);
|
||||
}
|
||||
}
|
||||
|
||||
<span style="color:#080;font-weight:bold">if</span> (!ENGINE_init(e)) {
|
||||
display_openssl_errors(__LINE__);
|
||||
exit(<span style="color:#00D">1</span>);
|
||||
}
|
||||
|
||||
<span style="color:#080;font-weight:bold">if</span> (key_pass && !ENGINE_ctrl_cmd_string(e, <span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">"</span><span style="color:#D20">PIN</span><span style="color:#710">"</span></span>, key_pass, <span style="color:#00D">0</span>)) {
|
||||
display_openssl_errors(__LINE__);
|
||||
exit(<span style="color:#00D">1</span>);
|
||||
}
|
||||
|
||||
private_key = ENGINE_load_private_key(e, private_key_name, <span style="color:#069">NULL</span>, <span style="color:#069">NULL</span>);
|
||||
<span style="color:#080;font-weight:bold">if</span> (!private_key) {
|
||||
fprintf(stderr, <span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">"</span><span style="color:#D20">cannot load: %s</span><span style="color:#b0b">\n</span><span style="color:#710">"</span></span>, private_key_name);
|
||||
display_openssl_errors(__LINE__);
|
||||
exit(<span style="color:#00D">1</span>);
|
||||
}
|
||||
|
||||
display_openssl_errors(__LINE__);
|
||||
|
||||
digest_algo = EVP_get_digestbyname(<span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">"</span><span style="color:#D20">sha256</span><span style="color:#710">"</span></span>);
|
||||
|
||||
EVP_MD_CTX_init(&ctx);
|
||||
<span style="color:#080;font-weight:bold">if</span> (EVP_DigestInit(&ctx, digest_algo) <= <span style="color:#00D">0</span>) {
|
||||
display_openssl_errors(__LINE__);
|
||||
exit(<span style="color:#00D">1</span>);
|
||||
}
|
||||
|
||||
EVP_SignInit(&ctx, digest_algo);
|
||||
|
||||
<span style="color:#579">#define</span> TEST_DATA <span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">"</span><span style="color:#D20">test data</span><span style="color:#710">"</span></span>
|
||||
<span style="color:#080;font-weight:bold">if</span> (EVP_SignUpdate(&ctx, TEST_DATA, <span style="color:#080;font-weight:bold">sizeof</span>(TEST_DATA) - <span style="color:#00D">1</span>) <= <span style="color:#00D">0</span>) {
|
||||
display_openssl_errors(__LINE__);
|
||||
exit(<span style="color:#00D">1</span>);
|
||||
}
|
||||
|
||||
n = <span style="color:#080;font-weight:bold">sizeof</span>(buf);
|
||||
<span style="color:#080;font-weight:bold">if</span> (EVP_SignFinal(&ctx, buf, &n, private_key) <= <span style="color:#00D">0</span>) {
|
||||
display_openssl_errors(__LINE__);
|
||||
exit(<span style="color:#00D">1</span>);
|
||||
}
|
||||
|
||||
EVP_PKEY_free(private_key);
|
||||
ENGINE_finish(e);</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="sect-Defensive_Coding-HSM-GNUTLS"><a class="anchor" href="#sect-Defensive_Coding-HSM-GNUTLS"></a>GnuTLS HSM Support</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>GnuTLS supports PKCS#11 natively. Most of the API functions
|
||||
accepting certificate files, can also accept PKCS#11 URLs, thus
|
||||
requiring minor or no modifications to applications in order
|
||||
to support HSMs. In most cases applications must be modified
|
||||
to install a PIN callback function.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>The following example demonstrates the initialization of the pkcs11 engine
|
||||
and its usage to sign data.</p>
|
||||
</div>
|
||||
<div id="ex-Defensive_Coding-HSM-GNUTLS" class="exampleblock">
|
||||
<div class="title">Example 2. Signing data with HSM and GnuTLS</div>
|
||||
<div class="content">
|
||||
<div class="listingblock">
|
||||
<div class="content">
|
||||
<pre class="CodeRay highlight"><code data-lang="c"><span style="color:#080;font-weight:bold">if</span> (module_path) {
|
||||
ret = gnutls_pkcs11_init(GNUTLS_PKCS11_FLAG_MANUAL, <span style="color:#069">NULL</span>);
|
||||
<span style="color:#080;font-weight:bold">if</span> (ret < <span style="color:#00D">0</span>) {
|
||||
fprintf(stderr, <span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">"</span><span style="color:#D20">error in %d: %s</span><span style="color:#b0b">\n</span><span style="color:#710">"</span></span>, __LINE__, gnutls_strerror(ret));
|
||||
exit(<span style="color:#00D">1</span>);
|
||||
}
|
||||
|
||||
ret = gnutls_pkcs11_add_provider(module_path, <span style="color:#069">NULL</span>);
|
||||
<span style="color:#080;font-weight:bold">if</span> (ret < <span style="color:#00D">0</span>) {
|
||||
fprintf(stderr, <span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">"</span><span style="color:#D20">error in %d: %s</span><span style="color:#b0b">\n</span><span style="color:#710">"</span></span>, __LINE__, gnutls_strerror(ret));
|
||||
exit(<span style="color:#00D">1</span>);
|
||||
}
|
||||
}
|
||||
|
||||
<span style="color:#080;font-weight:bold">if</span> (key_pass)
|
||||
gnutls_pkcs11_set_pin_function(pin_function, key_pass);
|
||||
|
||||
ret = gnutls_privkey_init(&private_key);
|
||||
<span style="color:#080;font-weight:bold">if</span> (ret < <span style="color:#00D">0</span>) {
|
||||
fprintf(stderr, <span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">"</span><span style="color:#D20">error in %d: %s</span><span style="color:#b0b">\n</span><span style="color:#710">"</span></span>, __LINE__, gnutls_strerror(ret));
|
||||
exit(<span style="color:#00D">1</span>);
|
||||
}
|
||||
|
||||
ret = gnutls_privkey_import_url(private_key, private_key_name, <span style="color:#00D">0</span>);
|
||||
<span style="color:#080;font-weight:bold">if</span> (ret < <span style="color:#00D">0</span>) {
|
||||
fprintf(stderr, <span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">"</span><span style="color:#D20">error in %d: %s</span><span style="color:#b0b">\n</span><span style="color:#710">"</span></span>, __LINE__, gnutls_strerror(ret));
|
||||
exit(<span style="color:#00D">1</span>);
|
||||
}
|
||||
|
||||
ret = gnutls_privkey_sign_data(private_key, GNUTLS_DIG_SHA256, <span style="color:#00D">0</span>,
|
||||
&testdata, &signature);
|
||||
<span style="color:#080;font-weight:bold">if</span> (ret < <span style="color:#00D">0</span>) {
|
||||
fprintf(stderr, <span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">"</span><span style="color:#D20">error in %d: %s</span><span style="color:#b0b">\n</span><span style="color:#710">"</span></span>, __LINE__, gnutls_strerror(ret));
|
||||
exit(<span style="color:#00D">1</span>);
|
||||
}
|
||||
|
||||
gnutls_privkey_deinit(private_key);
|
||||
gnutls_free(signature.data);</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>The PIN callback function can be either set globally as in
|
||||
the example above or locally by utilizing functions such as <code>gnutls_privkey_set_pin_function</code>.
|
||||
An example PIN callback function is shown below.</p>
|
||||
</div>
|
||||
<div id="ex-Defensive_Coding-HSM-GNUTLS-PIN" class="exampleblock">
|
||||
<div class="title">Example 3. An example PIN callback with GNUTLS</div>
|
||||
<div class="content">
|
||||
<div class="listingblock">
|
||||
<div class="content">
|
||||
<pre class="CodeRay highlight"><code data-lang="c"><span style="color:#0a8;font-weight:bold">int</span> pin_function(<span style="color:#088;font-weight:bold">void</span> *userdata, <span style="color:#0a8;font-weight:bold">int</span> attempt, <span style="color:#088;font-weight:bold">const</span> <span style="color:#0a8;font-weight:bold">char</span> *token_url,
|
||||
<span style="color:#088;font-weight:bold">const</span> <span style="color:#0a8;font-weight:bold">char</span> *token_label, <span style="color:#0a8;font-weight:bold">unsigned</span> flags, <span style="color:#0a8;font-weight:bold">char</span> *pin, size_t pin_max)
|
||||
{
|
||||
<span style="color:#080;font-weight:bold">if</span> (flags & GNUTLS_PIN_FINAL_TRY)
|
||||
printf(<span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">"</span><span style="color:#D20">This is the final try before locking!</span><span style="color:#b0b">\n</span><span style="color:#710">"</span></span>);
|
||||
<span style="color:#080;font-weight:bold">if</span> (flags & GNUTLS_PIN_COUNT_LOW)
|
||||
printf(<span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">"</span><span style="color:#D20">Only few tries left before locking!</span><span style="color:#b0b">\n</span><span style="color:#710">"</span></span>);
|
||||
<span style="color:#080;font-weight:bold">if</span> (flags & GNUTLS_PIN_WRONG)
|
||||
printf(<span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">"</span><span style="color:#D20">Wrong PIN has been provided in the previous attempt</span><span style="color:#b0b">\n</span><span style="color:#710">"</span></span>);
|
||||
|
||||
<span style="color:#777">/* userdata is the second value passed to gnutls_pkcs11_set_pin_function()
|
||||
* in this example we passed the PIN as a null terminated value.
|
||||
*/</span>
|
||||
snprintf(pin, pin_max, <span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">"</span><span style="color:#D20">%s</span><span style="color:#710">"</span></span>, (<span style="color:#0a8;font-weight:bold">char</span>*)userdata);
|
||||
<span style="color:#080;font-weight:bold">return</span> <span style="color:#00D">0</span>;
|
||||
}</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="sect-Defensive_Coding-HSM-NSS"><a class="anchor" href="#sect-Defensive_Coding-HSM-NSS"></a>NSS HSM Support</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>NSS supports PKCS#11 natively. In fact all NSS crypto operations,
|
||||
including built-in operations, go through PKCS #11 modules. NSS provides
|
||||
its own software PKCS #11 module called softoken. NSS automatically
|
||||
loads any PKCS #11 module specified in its module database, which can
|
||||
be manipulated with the modutil command. NSS uses the PKCS #11 module
|
||||
that contains the requested keys to do the crypto operations. As long as
|
||||
the application opens an NSS database and properly sets a pin callback. If
|
||||
it runs with native NSS, it should be able to use HSMs that provide PKCS #11
|
||||
modules. Modules can also be loaded programatically, though this is less common.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>The following example demonstrates a typical NSS application for signing.</p>
|
||||
</div>
|
||||
<div id="ex-Defensive_Coding-HSM-NSS" class="exampleblock">
|
||||
<div class="title">Example 4. Signing data with HSM and NSS</div>
|
||||
<div class="content">
|
||||
<div class="listingblock">
|
||||
<div class="content">
|
||||
<pre class="CodeRay highlight"><code data-lang="c">SECStatus rv;
|
||||
CERTCertificate *cert = <span style="color:#069">NULL</span>;
|
||||
SECKEYPrivateKey *pvtkey = <span style="color:#069">NULL</span>;
|
||||
SECItem signature = { siBuffer, <span style="color:#069">NULL</span>, <span style="color:#00D">0</span> };
|
||||
SECOidTag algTag;
|
||||
<span style="color:#0a8;font-weight:bold">int</span> r = <span style="color:#00D">1</span>;
|
||||
<span style="color:#0a8;font-weight:bold">unsigned</span> <span style="color:#0a8;font-weight:bold">char</span> buf[] = <span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">"</span><span style="color:#D20">test data to sign</span><span style="color:#710">"</span></span>;
|
||||
<span style="color:#088;font-weight:bold">const</span> <span style="color:#0a8;font-weight:bold">char</span> *cert_name;
|
||||
<span style="color:#0a8;font-weight:bold">unsigned</span> i;
|
||||
|
||||
<span style="color:#080;font-weight:bold">if</span> (argc < <span style="color:#00D">3</span>) {
|
||||
fprintf(stderr, <span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">"</span><span style="color:#D20">usage: %s [cert name] [PIN]</span><span style="color:#b0b">\n</span><span style="color:#b0b">\n</span><span style="color:#710">"</span></span>, argv[<span style="color:#00D">0</span>]);
|
||||
exit(<span style="color:#00D">1</span>);
|
||||
}
|
||||
|
||||
cert_name = argv[<span style="color:#00D">1</span>];
|
||||
pin = argv[<span style="color:#00D">2</span>];
|
||||
|
||||
PK11_SetPasswordFunc(passwdcb);
|
||||
NSS_InitializePRErrorTable();
|
||||
rv = NSS_Init(<span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">"</span><span style="color:#D20">.</span><span style="color:#710">"</span></span>);
|
||||
<span style="color:#080;font-weight:bold">if</span> (rv != SECSuccess) {
|
||||
fprintf(stderr, <span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">"</span><span style="color:#D20">NSS initialization failed (err %d)</span><span style="color:#b0b">\n</span><span style="color:#710">"</span></span>, PR_GetError());
|
||||
<span style="color:#080;font-weight:bold">goto</span> cleanup;
|
||||
}
|
||||
|
||||
cert = PK11_FindCertFromNickname(cert_name, <span style="color:#069">NULL</span>);
|
||||
<span style="color:#080;font-weight:bold">if</span> (cert == <span style="color:#069">NULL</span>) {
|
||||
fprintf(stderr, <span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">"</span><span style="color:#D20">Couldn't find cert %s in NSS db (err %d: %s)</span><span style="color:#b0b">\n</span><span style="color:#710">"</span></span>,
|
||||
cert_name, PR_GetError(), PORT_ErrorToString(PR_GetError()));
|
||||
<span style="color:#080;font-weight:bold">goto</span> cleanup;
|
||||
}
|
||||
|
||||
fprintf(stderr, <span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">"</span><span style="color:#D20">Buffer being signed = </span><span style="color:#b0b">\n</span><span style="color:#D20">%s</span><span style="color:#b0b">\n</span><span style="color:#710">"</span></span>, buf);
|
||||
|
||||
pvtkey = PK11_FindKeyByAnyCert(cert, <span style="color:#069">NULL</span>);
|
||||
<span style="color:#080;font-weight:bold">if</span> (pvtkey == <span style="color:#069">NULL</span>) {
|
||||
fprintf(stderr, <span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">"</span><span style="color:#D20">Couldn't find private key for cert %s (err %d: %s)</span><span style="color:#b0b">\n</span><span style="color:#710">"</span></span>,
|
||||
cert_name, PR_GetError(), PORT_ErrorToString(PR_GetError()));
|
||||
<span style="color:#080;font-weight:bold">goto</span> cleanup;
|
||||
}
|
||||
|
||||
<span style="color:#777">/* get the algtag. Pick the default hash algorithm */</span>
|
||||
algTag = SEC_GetSignatureAlgorithmOidTag(pvtkey->keyType, SEC_OID_UNKNOWN);
|
||||
|
||||
fprintf(stderr, <span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">"</span><span style="color:#D20">Signing with alg = %s (%d)</span><span style="color:#b0b">\n</span><span style="color:#710">"</span></span>,
|
||||
SECOID_FindOIDTagDescription(algTag), algTag);
|
||||
|
||||
rv = SEC_SignData(&signature, buf, <span style="color:#080;font-weight:bold">sizeof</span>(buf)-<span style="color:#00D">1</span>, pvtkey, algTag);
|
||||
<span style="color:#080;font-weight:bold">if</span> (rv != SECSuccess) {
|
||||
fprintf(stderr, <span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">"</span><span style="color:#D20">sign with Private Key failed (err %d: %s)</span><span style="color:#b0b">\n</span><span style="color:#710">"</span></span>,
|
||||
PR_GetError(), PORT_ErrorToString(PR_GetError()));
|
||||
<span style="color:#080;font-weight:bold">goto</span> cleanup;
|
||||
}</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>To use the example above with an HSM or smart card you will need to do the following.</p>
|
||||
</div>
|
||||
<div class="listingblock">
|
||||
<div class="content">
|
||||
<pre class="CodeRay highlight"><code data-lang="bash"># add your HSM or token library to an NSS database (in the sample code the database is
|
||||
# located in the current directory'.')
|
||||
$ modutil -add "My HSM" -libfile ${path_to_pkcs11_file} -dbdir .
|
||||
# Find the token name on your HSM
|
||||
$ modutil -list -dbdir .
|
||||
# find the cert on your token
|
||||
$ certutil -L -h ${token_name} -d .
|
||||
# pass the cert to your signing program
|
||||
$ NSS_Sign_Example "${token_name}:${cert_name}"</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
<div id="ex-Defensive_Coding-HSM-NSS-PIN" class="exampleblock">
|
||||
<div class="title">Example 5. An example PIN callback with NSS</div>
|
||||
<div class="content">
|
||||
<div class="listingblock">
|
||||
<div class="content">
|
||||
<pre class="CodeRay highlight"><code data-lang="c"><span style="color:#0a8;font-weight:bold">char</span> *passwdcb(PK11SlotInfo * slot, PRBool retry, <span style="color:#088;font-weight:bold">void</span> *arg)
|
||||
{
|
||||
<span style="color:#080;font-weight:bold">if</span> (!isatty(STDIN_FILENO) && retry) {
|
||||
<span style="color:#777">/* 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. */</span>
|
||||
<span style="color:#080;font-weight:bold">return</span> <span style="color:#069">NULL</span>;
|
||||
}
|
||||
|
||||
<span style="color:#080;font-weight:bold">if</span> (retry) {
|
||||
printf(<span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">"</span><span style="color:#D20">Warning: Wrong PIN has been provided in the previous attempt</span><span style="color:#b0b">\n</span><span style="color:#710">"</span></span>);
|
||||
<span style="color:#080;font-weight:bold">if</span> (PK11_IsHW(slot)) {
|
||||
printf
|
||||
(<span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">"</span><span style="color:#D20"> NOTE: multiple pin failures could result in locking your device</span><span style="color:#b0b">\n</span><span style="color:#710">"</span></span>);
|
||||
}
|
||||
}
|
||||
|
||||
<span style="color:#080;font-weight:bold">if</span> (pin == <span style="color:#069">NULL</span>)
|
||||
<span style="color:#080;font-weight:bold">return</span> pin;
|
||||
<span style="color:#080;font-weight:bold">else</span>
|
||||
<span style="color:#080;font-weight:bold">return</span> strdup(pin);
|
||||
}</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="bottom" class="text-muted py-3" >
|
||||
<div class="foot">
|
||||
<div class="container">
|
||||
<div class="row footerlinks">
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">About</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Overview">About Fedora</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/sponsors">Sponsors</a></dd>
|
||||
<dd><a href="https://fedoramagazine.org">Fedora Magazine</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Legal:Main#Legal">Legal</a></dd>
|
||||
</dl>
|
||||
<ul class="list-inline">
|
||||
<li>
|
||||
<a href="https://www.facebook.com/TheFedoraProject" class="btn-social btn-outline"><i class="fa fa-fw fa-facebook"></i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://plus.google.com/112917221531140868607" class="btn-social btn-outline"><i class="fa fa-fw fa-google-plus"></i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://twitter.com/fedora" class="btn-social btn-outline"><i class="fa fa-fw fa-twitter"></i></a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title uppercase">Download</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://getfedora.org/en/workstation/download">Get Fedora Workstation</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/server/download">Get Fedora Server</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/atomic/download">Get Fedora Atomic</a></dd>
|
||||
<dd><a href="https://spins.fedoraproject.org">Fedora Spins</a></dd>
|
||||
<dd><a href="https://labs.fedoraproject.org">Fedora Labs</a></dd>
|
||||
<dd><a href="https://arm.fedoraproject.org">Fedora ARM<span class="sup">®</span></a></dd>
|
||||
<dd><a href="https://alt.fedoraproject.org/">Alternative Downloads</a></dd>
|
||||
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">Support</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Communicating_and_getting_help">Get Help</a></dd>
|
||||
<dd><a href="https://ask.fedoraproject.org/">Ask Fedora</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Common_F27_bugs">Common Bugs</a></dd>
|
||||
<dd><a href="https://developer.fedoraproject.org/">Fedora Developer Portal</a></dd>
|
||||
<dd><a href="https://docs.fedoraproject.org/f27/install-guide/index.html">Installation Guide</a></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">Join</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Join">Join Fedora</a></dd>
|
||||
<dd><a href="http://fedoraplanet.org">Planet Fedora</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/SIGs">Fedora SIGs</a></dd>
|
||||
<dd><a href="https://admin.fedoraproject.org/accounts/">Fedora Account System</a></dd>
|
||||
<dd><a href="https://fedoracommunity.org/">Fedora Community</a></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- /row of widgets -->
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-2">
|
||||
<div class="widget-body">
|
||||
<a href="https://www.redhat.com/"><img class="rh-logo" src="../../../master/_images/redhat-logo.png" alt="Red Hat Logo" /></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-7">
|
||||
<div class="widget-body">
|
||||
<p class="sponsor">Fedora is sponsored by Red Hat.</p>
|
||||
<p class="sponsor"><a href="https://www.redhat.com/en/technologies/linux-platforms/articles/relationship-between-fedora-and-rhel">Learn more about the relationship between Red Hat and Fedora »</a></p>
|
||||
<p class="copy">© 2017 Red Hat, Inc. and others. Please send any comments or corrections to the <a href="https://pagure.io/fedora-docs/docs-fp-o">documentation team</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- /row of widgets -->
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
|
||||
<!-- Latest compiled and minified JavaScript -->
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
|
||||
<script src="../../../master/_javascripts/bootstrap-offcanvas.js" type="text/javascript"></script>
|
||||
<script type="text/javascript">
|
||||
/*<![CDATA[*/
|
||||
$(document).ready(function() {
|
||||
$("[id^='topicGroup']").on('show.bs.collapse', function (event) {
|
||||
if (!($(event.target).attr('id').match(/^topicSubGroup/))) {
|
||||
$(this).parent().find("[id^='tgSpan']").toggleClass("fa-angle-right fa-angle-down");
|
||||
}
|
||||
});
|
||||
$("[id^='topicGroup']").on('hide.bs.collapse', function (event) {
|
||||
if (!($(event.target).attr('id').match(/^topicSubGroup/))) {
|
||||
$(this).parent().find("[id^='tgSpan']").toggleClass("fa-angle-right fa-angle-down");
|
||||
}
|
||||
});
|
||||
$("[id^='topicSubGroup']").on('show.bs.collapse', function () {
|
||||
$(this).parent().find("[id^='sgSpan']").toggleClass("fa-caret-right fa-caret-down");
|
||||
});
|
||||
$("[id^='topicSubGroup']").on('hide.bs.collapse', function () {
|
||||
$(this).parent().find("[id^='sgSpan']").toggleClass("fa-caret-right fa-caret-down");
|
||||
});
|
||||
});
|
||||
/*]]>*/
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -1,641 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta content="IE=edge" http-equiv="X-UA-Compatible">
|
||||
<meta content="width=device-width, initial-scale=1.0" name="viewport">
|
||||
<title>Defensive Coding Guide | Defensive Coding Guide | Programming Languages | The C++ Programming Language</title>
|
||||
|
||||
<!-- Bootstrap -->
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap-theme.min.css">
|
||||
|
||||
<!-- Overpass Font -->
|
||||
<link rel="stylesheet" href="https://overpass-30e2.kxcdn.com/overpass.css">
|
||||
|
||||
<link href="../../../master/_stylesheets/asciibinder.css" rel="stylesheet" />
|
||||
|
||||
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
|
||||
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
|
||||
<!--[if lt IE 9]>
|
||||
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
|
||||
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
|
||||
<![endif]-->
|
||||
|
||||
<link href="../../../master/_images/favicon32x32.png" rel="shortcut icon" type="text/css">
|
||||
<!--[if IE]><link rel="shortcut icon" href="../../../master/_images/favicon.ico"><![endif]-->
|
||||
<meta content="AsciiBinder" name="application-name">
|
||||
</head>
|
||||
<body>
|
||||
<div class="navbar navbar-default" role="navigation">
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-header">
|
||||
<a class="navbar-brand" href="https://docs.fedoraproject.org/"><img alt="Fedora Documentation" src="../../../master/_images/fedora.svg"></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container">
|
||||
<p class="toggle-nav visible-xs pull-left">
|
||||
<button class="btn btn-default btn-sm" type="button" data-toggle="offcanvas">Toggle nav</button>
|
||||
</p>
|
||||
<ol class="breadcrumb">
|
||||
<li class="sitename">
|
||||
<a href="../../../index.html">Home</a>
|
||||
</li>
|
||||
<li class="hidden-xs active">
|
||||
<a href="../../en-US/index.html">Defensive Coding Guide </a>
|
||||
</li>
|
||||
<li class="hidden-xs active">
|
||||
<a href="../../en-US/index.html">Defensive Coding Guide</a>
|
||||
</li>
|
||||
<li class="hidden-xs active"><a href="../../en-US/programming-languages/C.html">Programming Languages</a></li>
|
||||
<li class="hidden-xs active">
|
||||
The C++ Programming Language
|
||||
</li>
|
||||
</ol>
|
||||
<div class="row row-offcanvas row-offcanvas-left">
|
||||
<div class="col-xs-8 col-sm-3 col-md-3 sidebar sidebar-offcanvas">
|
||||
<ul class="nav nav-sidebar">
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicGroup0">
|
||||
<span id="tgSpan0" class="fa fa-angle-down"></span>Defensive Coding Guide
|
||||
</a>
|
||||
<ul id="topicGroup0" class="collapse in list-unstyled">
|
||||
<li><a class="" href="../../en-US/index.html">Book Information</a></li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-1">
|
||||
<span id="sgSpan-0-1" class="fa fa-caret-down"></span> Programming Languages
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-1" class="nav-tertiary list-unstyled collapse in">
|
||||
<li><a class="" href="../../en-US/programming-languages/C.html">The C Programming Language</a></li>
|
||||
<li><a class=" active" href="../../en-US/programming-languages/CXX.html">The C++ Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Java.html">The Java Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Python.html">The Python Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Shell.html">Shell Programming and bash</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Go.html">The Go Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Vala.html">The Vala Programming Language</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-2">
|
||||
<span id="sgSpan-0-2" class="fa fa-caret-right"></span> Specific Programming Tasks
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-2" class="nav-tertiary list-unstyled collapse">
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Library_Design.html">Library Design</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Descriptors.html">File Descriptor Management</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-File_System.html">File System Manipulation</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Temporary_Files.html">Temporary Files</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Processes.html">Processes</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Serialization.html">Serialization and Deserialization</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Cryptography.html">Cryptography</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Packaging.html">RPM Packaging</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-3">
|
||||
<span id="sgSpan-0-3" class="fa fa-caret-right"></span> Implementing Security Features
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-3" class="nav-tertiary list-unstyled collapse">
|
||||
<li><a class="" href="../../en-US/features/Features-Authentication.html">Authentication and Authorization</a></li>
|
||||
<li><a class="" href="../../en-US/features/Features-TLS.html">Transport Layer Security (TLS)</a></li>
|
||||
<li><a class="" href="../../en-US/features/Features-HSM.html">Hardware Security Modules and Smart Cards</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="" href="../../en-US/Revision_History.html">Revision History</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-9 col-md-9 main">
|
||||
<div class="page-header">
|
||||
<h2>The C++ Programming Language</h2>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="sect-Defensive_Coding-CXX-Language"><a class="anchor" href="#sect-Defensive_Coding-CXX-Language"></a>The Core Language</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>C++ includes a large subset of the C language. As far as the C
|
||||
subset is used, the recommendations in <a href="#chap-Defensive_Coding-C">[chap-Defensive_Coding-C]</a> apply.</p>
|
||||
</div>
|
||||
<div class="sect2">
|
||||
<h3 id="array-allocation-with-code-operator-new-code"><a class="anchor" href="#array-allocation-with-code-operator-new-code"></a>Array Allocation with <code>operator new[]</code></h3>
|
||||
<div class="paragraph">
|
||||
<p>For very large values of <code>n</code>, an expression
|
||||
like <code>new T[n]</code> 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 <code>sizeof(T) * size_t(n)<br>
|
||||
cookie_size</code>, where <code>cookie_size</code> is
|
||||
currently at most 8. This computation can overflow, and GCC
|
||||
versions prior to 4.8 generated code which did not detect this.
|
||||
(Fedora 18 was the first release which fixed this in GCC.)</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>The <code>std::vector</code> template can be used instead
|
||||
an explicit array allocation. (The GCC implementation detects
|
||||
overflow internally.)</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>If there is no alternative to <code>operator new[]</code>
|
||||
and the sources will be compiled with older GCC versions, code
|
||||
which allocates arrays with a variable length must check for
|
||||
overflow manually. For the <code>new T[n]</code> example,
|
||||
the size check could be <code>n || (n > 0 && n >
|
||||
(size_t(-1) - 8) / sizeof(T))</code>. (See <a href="#sect-Defensive_Coding-C-Arithmetic">[sect-Defensive_Coding-C-Arithmetic]</a>.) If there are
|
||||
additional dimensions (which must be constants according to the
|
||||
C++ standard), these should be included as factors in the
|
||||
divisor.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>These countermeasures prevent out-of-bounds writes and potential
|
||||
code execution. Very large memory allocations can still lead to
|
||||
a denial of service. <a href="#sect-Defensive_Coding-Tasks-Serialization-Decoders">[sect-Defensive_Coding-Tasks-Serialization-Decoders]</a>
|
||||
contains suggestions for mitigating this problem when processing
|
||||
untrusted data.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>See <a href="#sect-Defensive_Coding-C-Allocators-Arrays">[sect-Defensive_Coding-C-Allocators-Arrays]</a>
|
||||
for array allocation advice for C-style memory allocation.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect2">
|
||||
<h3 id="overloading"><a class="anchor" href="#overloading"></a>Overloading</h3>
|
||||
<div class="paragraph">
|
||||
<p>Do not overload functions with versions that have different
|
||||
security characteristics. For instance, do not implement a
|
||||
function <code>strcat</code> which works on
|
||||
<code>std::string</code> arguments. Similarly, do not name
|
||||
methods after such functions.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect2">
|
||||
<h3 id="abi-compatibility-and-preparing-for-security-updates"><a class="anchor" href="#abi-compatibility-and-preparing-for-security-updates"></a>ABI compatibility and preparing for security updates</h3>
|
||||
<div class="paragraph">
|
||||
<p>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.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>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:</p>
|
||||
</div>
|
||||
<div class="ulist">
|
||||
<ul>
|
||||
<li>
|
||||
<p>Avoid inline functions.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Use the pointer-to-implementation idiom.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Try to avoid templates. Use them if the increased type
|
||||
safety provides a benefit to the programmer.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Move security-critical code out of templated code, so that
|
||||
it can be patched in a central place if necessary.</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>The KDE project publishes a document with more extensive
|
||||
guidelines on ABI-preserving changes to C++ code, <a href="https://community.kde.org/Policies/Binary_Compatibility_Issues_With_C%2B%2B">Policies/Binary
|
||||
Compatibility Issues With C++</a>
|
||||
(<strong>d-pointer</strong> refers to the
|
||||
pointer-to-implementation idiom).</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect2">
|
||||
<h3 id="sect-Defensive_Coding-CXX-Language-CXX11"><a class="anchor" href="#sect-Defensive_Coding-CXX-Language-CXX11"></a>C++0X and C++11 Support</h3>
|
||||
<div class="paragraph">
|
||||
<p>GCC offers different language compatibility modes:</p>
|
||||
</div>
|
||||
<div class="ulist">
|
||||
<ul>
|
||||
<li>
|
||||
<p><code class="option">-std=c++98</code> for the original 1998 C++
|
||||
standard</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><code class="option">-std=c++03</code> for the 1998 standard with the
|
||||
changes from the TR1 technical report</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><code class="option">-std=c++11</code> for the 2011 C++ standard. This
|
||||
option should not be used.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><code class="option">-std=c++0x</code> for several different versions
|
||||
of C++11 support in development, depending on the GCC
|
||||
version. This option should not be used.</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>For each of these flags, there are variants which also enable
|
||||
GNU extensions (mostly language features also found in C99 or
|
||||
C11):</p>
|
||||
</div>
|
||||
<div class="ulist">
|
||||
<ul>
|
||||
<li>
|
||||
<p><code class="option">-std=gnu++98</code></p>
|
||||
</li>
|
||||
<li>
|
||||
<p><code class="option">-std=gnu++03</code></p>
|
||||
</li>
|
||||
<li>
|
||||
<p><code class="option">-std=gnu++11</code></p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Again, <code class="option">-std=gnu++11</code> should not be used.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>If you enable C++11 support, the ABI of the standard C++ library
|
||||
<code>libstdc++</code> 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).</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>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.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Some C++11 features (or approximations thereof) are available
|
||||
with TR1 support, that is, with <code class="option">-std=c03` or
|
||||
[option]`-std=gnu03</code> and in the
|
||||
<code><tr1/*></code> header files. This includes
|
||||
<code>std::tr1::shared_ptr</code> (from
|
||||
<code><tr1/memory></code>) and
|
||||
<code>std::tr1::function</code> (from
|
||||
<code><tr1/functional></code>). For other C++11
|
||||
features, the Boost C++ library contains replacements.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="sect-Defensive_Coding-CXX-Std"><a class="anchor" href="#sect-Defensive_Coding-CXX-Std"></a>The C++ Standard Library</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>The C++ standard library includes most of its C counterpart
|
||||
by reference, see <a href="#sect-Defensive_Coding-C-Libc">[sect-Defensive_Coding-C-Libc]</a>.</p>
|
||||
</div>
|
||||
<div class="sect2">
|
||||
<h3 id="sect-Defensive_Coding-CXX-Std-Functions"><a class="anchor" href="#sect-Defensive_Coding-CXX-Std-Functions"></a>Functions That Are Difficult to Use</h3>
|
||||
<div class="paragraph">
|
||||
<p>This section collects functions and function templates which are
|
||||
part of the standard library and are difficult to use.</p>
|
||||
</div>
|
||||
<div class="sect3">
|
||||
<h4 id="sect-Defensive_Coding-CXX-Std-Functions-Unpaired_Iterators"><a class="anchor" href="#sect-Defensive_Coding-CXX-Std-Functions-Unpaired_Iterators"></a>Unpaired Iterators</h4>
|
||||
<div class="paragraph">
|
||||
<p>Functions which use output operators or iterators which do not
|
||||
come in pairs (denoting ranges) cannot perform iterator range
|
||||
checking.
|
||||
(See <a href="#sect-Defensive_Coding-CXX-Std-Iterators">Iterators</a>)
|
||||
Function templates which involve output iterators are
|
||||
particularly dangerous:</p>
|
||||
</div>
|
||||
<div class="ulist">
|
||||
<ul>
|
||||
<li>
|
||||
<p><code>std::copy</code></p>
|
||||
</li>
|
||||
<li>
|
||||
<p><code>std::copy_backward</code></p>
|
||||
</li>
|
||||
<li>
|
||||
<p><code>std::copy_if</code></p>
|
||||
</li>
|
||||
<li>
|
||||
<p><code>std::move</code> (three-argument variant)</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><code>std::move_backward</code></p>
|
||||
</li>
|
||||
<li>
|
||||
<p><code>std::partition_copy_if</code></p>
|
||||
</li>
|
||||
<li>
|
||||
<p><code>std::remove_copy</code></p>
|
||||
</li>
|
||||
<li>
|
||||
<p><code>std::remove_copy_if</code></p>
|
||||
</li>
|
||||
<li>
|
||||
<p><code>std::replace_copy</code></p>
|
||||
</li>
|
||||
<li>
|
||||
<p><code>std::replace_copy_if</code></p>
|
||||
</li>
|
||||
<li>
|
||||
<p><code>std::swap_ranges</code></p>
|
||||
</li>
|
||||
<li>
|
||||
<p><code>std::transform</code></p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>In addition, <code>std::copy_n</code>,
|
||||
<code>std::fill_n</code> and
|
||||
<code>std::generate_n</code> do not perform iterator
|
||||
checking, either, but there is an explicit count which has to be
|
||||
supplied by the caller, as opposed to an implicit length
|
||||
indicator in the form of a pair of forward iterators.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>These output-iterator-expecting functions should only be used
|
||||
with unlimited-range output iterators, such as iterators
|
||||
obtained with the <code>std::back_inserter</code>
|
||||
function.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Other functions use single input or forward iterators, which can
|
||||
read beyond the end of the input range if the caller is not careful:</p>
|
||||
</div>
|
||||
<div class="ulist">
|
||||
<ul>
|
||||
<li>
|
||||
<p><code>std::equal</code></p>
|
||||
</li>
|
||||
<li>
|
||||
<p><code>std::is_permutation</code></p>
|
||||
</li>
|
||||
<li>
|
||||
<p><code>std::mismatch</code></p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect2">
|
||||
<h3 id="sect-Defensive_Coding-CXX-Std-String"><a class="anchor" href="#sect-Defensive_Coding-CXX-Std-String"></a>String Handling with <code>std::string</code></h3>
|
||||
<div class="paragraph">
|
||||
<p>The <code>std::string</code> class provides a convenient
|
||||
way to handle strings. Unlike C strings,
|
||||
<code>std::string</code> objects have an explicit length
|
||||
(and can contain embedded NUL characters), and storage for its
|
||||
characters is managed automatically. This section discusses
|
||||
<code>std::string</code>, but these observations also
|
||||
apply to other instances of the
|
||||
<code>std::basic_string</code> template.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>The pointer returned by the <code>data()</code> member
|
||||
function does not necessarily point to a NUL-terminated string.
|
||||
To obtain a C-compatible string pointer, use
|
||||
<code>c_str()</code> instead, which adds the NUL
|
||||
terminator.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>The pointers returned by the <code>data()</code> and
|
||||
<code>c_str()</code> functions and iterators are only
|
||||
valid until certain events happen. It is required that the
|
||||
exact <code>std::string</code> object still exists (even
|
||||
if it was initially created as a copy of another string object).
|
||||
Pointers and iterators are also invalidated when non-const
|
||||
member functions are called, or functions with a non-const
|
||||
reference parameter. The behavior of the GCC implementation
|
||||
deviates from that required by the C++ standard if multiple
|
||||
threads are present. In general, only the first call to a
|
||||
non-const member function after a structural modification of the
|
||||
string (such as appending a character) is invalidating, but this
|
||||
also applies to member function such as the non-const version of
|
||||
<code>begin()</code>, in violation of the C++ standard.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Particular care is necessary when invoking the
|
||||
<code>c_str()</code> member function on a temporary
|
||||
object. This is convenient for calling C functions, but the
|
||||
pointer will turn invalid as soon as the temporary object is
|
||||
destroyed, which generally happens when the outermost expression
|
||||
enclosing the expression on which <code>c_str()</code>
|
||||
is called completes evaluation. Passing the result of
|
||||
<code>c_str()</code> to a function which does not store
|
||||
or otherwise leak that pointer is safe, though.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Like with <code>std::vector</code> and
|
||||
<code>std::array</code>, subscribing with
|
||||
<code>operator[]</code> does not perform bounds checks.
|
||||
Use the <code>at(size_type)</code> member function
|
||||
instead. See <a href="#sect-Defensive_Coding-CXX-Std-Subscript">Containers and <code>operator[]</code></a>.
|
||||
Furthermore, accessing the terminating NUL character using
|
||||
<code>operator[]</code> is not possible. (In some
|
||||
implementations, the <code>c_str()</code> member function
|
||||
writes the NUL character on demand.)</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Never write to the pointers returned by
|
||||
<code>data()</code> or <code>c_str()</code>
|
||||
after casting away <code>const</code>. If you need a
|
||||
C-style writable string, use a
|
||||
<code>std::vector<char></code> object and its
|
||||
<code>data()</code> member function. In this case, you
|
||||
have to explicitly add the terminating NUL character.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>GCC’s implementation of <code>std::string</code> is
|
||||
currently based on reference counting. It is expected that a
|
||||
future version will remove the reference counting, due to
|
||||
performance and conformance issues. As a result, code that
|
||||
implicitly assumes sharing by holding to pointers or iterators
|
||||
for too long will break, resulting in run-time crashes or worse.
|
||||
On the other hand, non-const iterator-returning functions will
|
||||
no longer give other threads an opportunity for invalidating
|
||||
existing iterators and pointers because iterator invalidation
|
||||
does not depend on sharing of the internal character array
|
||||
object anymore.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect2">
|
||||
<h3 id="sect-Defensive_Coding-CXX-Std-Subscript"><a class="anchor" href="#sect-Defensive_Coding-CXX-Std-Subscript"></a>Containers and <code>operator[]</code></h3>
|
||||
<div class="paragraph">
|
||||
<p>Many sequence containers similar to <code>std::vector</code>
|
||||
provide both <code>operator[](size_type)</code> and a
|
||||
member function <code>at(size_type)</code>. This applies
|
||||
to <code>std::vector</code> itself,
|
||||
<code>std::array</code>, <code>std::string</code>
|
||||
and other instances of <code>std::basic_string</code>.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p><code>operator[](size_type)</code> is not required by the
|
||||
standard to perform bounds checking (and the implementation in
|
||||
GCC does not). In contrast, <code>at(size_type)</code>
|
||||
must perform such a check. Therefore, in code which is not
|
||||
performance-critical, you should prefer
|
||||
<code>at(size_type)</code> over
|
||||
<code>operator[](size_type)</code>, even though it is
|
||||
slightly more verbose.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>The <code>front()</code> and <code>back()</code>
|
||||
member functions are undefined if a vector object is empty. You
|
||||
can use <code>vec.at(0)</code> and
|
||||
<code>vec.at(vec.size() - 1)</code> as checked
|
||||
replacements. For an empty vector, <code>data()</code> is
|
||||
defined; it returns an arbitrary pointer, but not necessarily
|
||||
the NULL pointer.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect2">
|
||||
<h3 id="sect-Defensive_Coding-CXX-Std-Iterators"><a class="anchor" href="#sect-Defensive_Coding-CXX-Std-Iterators"></a>Iterators</h3>
|
||||
<div class="paragraph">
|
||||
<p>Iterators do not perform any bounds checking. Therefore, all
|
||||
functions that work on iterators should accept them in pairs,
|
||||
denoting a range, and make sure that iterators are not moved
|
||||
outside that range. For forward iterators and bidirectional
|
||||
iterators, you need to check for equality before moving the
|
||||
first or last iterator in the range. For random-access
|
||||
iterators, you need to compute the difference before adding or
|
||||
subtracting an offset. It is not possible to perform the
|
||||
operation and check for an invalid operator afterwards.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Output iterators cannot be compared for equality. Therefore, it
|
||||
is impossible to write code that detects that it has been
|
||||
supplied an output area that is too small, and their use should
|
||||
be avoided.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>These issues make some of the standard library functions
|
||||
difficult to use correctly, see <a href="#sect-Defensive_Coding-CXX-Std-Functions-Unpaired_Iterators">Unpaired Iterators</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="bottom" class="text-muted py-3" >
|
||||
<div class="foot">
|
||||
<div class="container">
|
||||
<div class="row footerlinks">
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">About</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Overview">About Fedora</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/sponsors">Sponsors</a></dd>
|
||||
<dd><a href="https://fedoramagazine.org">Fedora Magazine</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Legal:Main#Legal">Legal</a></dd>
|
||||
</dl>
|
||||
<ul class="list-inline">
|
||||
<li>
|
||||
<a href="https://www.facebook.com/TheFedoraProject" class="btn-social btn-outline"><i class="fa fa-fw fa-facebook"></i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://plus.google.com/112917221531140868607" class="btn-social btn-outline"><i class="fa fa-fw fa-google-plus"></i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://twitter.com/fedora" class="btn-social btn-outline"><i class="fa fa-fw fa-twitter"></i></a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title uppercase">Download</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://getfedora.org/en/workstation/download">Get Fedora Workstation</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/server/download">Get Fedora Server</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/atomic/download">Get Fedora Atomic</a></dd>
|
||||
<dd><a href="https://spins.fedoraproject.org">Fedora Spins</a></dd>
|
||||
<dd><a href="https://labs.fedoraproject.org">Fedora Labs</a></dd>
|
||||
<dd><a href="https://arm.fedoraproject.org">Fedora ARM<span class="sup">®</span></a></dd>
|
||||
<dd><a href="https://alt.fedoraproject.org/">Alternative Downloads</a></dd>
|
||||
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">Support</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Communicating_and_getting_help">Get Help</a></dd>
|
||||
<dd><a href="https://ask.fedoraproject.org/">Ask Fedora</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Common_F27_bugs">Common Bugs</a></dd>
|
||||
<dd><a href="https://developer.fedoraproject.org/">Fedora Developer Portal</a></dd>
|
||||
<dd><a href="https://docs.fedoraproject.org/f27/install-guide/index.html">Installation Guide</a></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">Join</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Join">Join Fedora</a></dd>
|
||||
<dd><a href="http://fedoraplanet.org">Planet Fedora</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/SIGs">Fedora SIGs</a></dd>
|
||||
<dd><a href="https://admin.fedoraproject.org/accounts/">Fedora Account System</a></dd>
|
||||
<dd><a href="https://fedoracommunity.org/">Fedora Community</a></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- /row of widgets -->
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-2">
|
||||
<div class="widget-body">
|
||||
<a href="https://www.redhat.com/"><img class="rh-logo" src="../../../master/_images/redhat-logo.png" alt="Red Hat Logo" /></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-7">
|
||||
<div class="widget-body">
|
||||
<p class="sponsor">Fedora is sponsored by Red Hat.</p>
|
||||
<p class="sponsor"><a href="https://www.redhat.com/en/technologies/linux-platforms/articles/relationship-between-fedora-and-rhel">Learn more about the relationship between Red Hat and Fedora »</a></p>
|
||||
<p class="copy">© 2017 Red Hat, Inc. and others. Please send any comments or corrections to the <a href="https://pagure.io/fedora-docs/docs-fp-o">documentation team</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- /row of widgets -->
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
|
||||
<!-- Latest compiled and minified JavaScript -->
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
|
||||
<script src="../../../master/_javascripts/bootstrap-offcanvas.js" type="text/javascript"></script>
|
||||
<script type="text/javascript">
|
||||
/*<![CDATA[*/
|
||||
$(document).ready(function() {
|
||||
$("[id^='topicGroup']").on('show.bs.collapse', function (event) {
|
||||
if (!($(event.target).attr('id').match(/^topicSubGroup/))) {
|
||||
$(this).parent().find("[id^='tgSpan']").toggleClass("fa-angle-right fa-angle-down");
|
||||
}
|
||||
});
|
||||
$("[id^='topicGroup']").on('hide.bs.collapse', function (event) {
|
||||
if (!($(event.target).attr('id').match(/^topicSubGroup/))) {
|
||||
$(this).parent().find("[id^='tgSpan']").toggleClass("fa-angle-right fa-angle-down");
|
||||
}
|
||||
});
|
||||
$("[id^='topicSubGroup']").on('show.bs.collapse', function () {
|
||||
$(this).parent().find("[id^='sgSpan']").toggleClass("fa-caret-right fa-caret-down");
|
||||
});
|
||||
$("[id^='topicSubGroup']").on('hide.bs.collapse', function () {
|
||||
$(this).parent().find("[id^='sgSpan']").toggleClass("fa-caret-right fa-caret-down");
|
||||
});
|
||||
});
|
||||
/*]]>*/
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -1,356 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta content="IE=edge" http-equiv="X-UA-Compatible">
|
||||
<meta content="width=device-width, initial-scale=1.0" name="viewport">
|
||||
<title>Defensive Coding Guide | Defensive Coding Guide | Programming Languages | The Go Programming Language</title>
|
||||
|
||||
<!-- Bootstrap -->
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap-theme.min.css">
|
||||
|
||||
<!-- Overpass Font -->
|
||||
<link rel="stylesheet" href="https://overpass-30e2.kxcdn.com/overpass.css">
|
||||
|
||||
<link href="../../../master/_stylesheets/asciibinder.css" rel="stylesheet" />
|
||||
|
||||
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
|
||||
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
|
||||
<!--[if lt IE 9]>
|
||||
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
|
||||
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
|
||||
<![endif]-->
|
||||
|
||||
<link href="../../../master/_images/favicon32x32.png" rel="shortcut icon" type="text/css">
|
||||
<!--[if IE]><link rel="shortcut icon" href="../../../master/_images/favicon.ico"><![endif]-->
|
||||
<meta content="AsciiBinder" name="application-name">
|
||||
</head>
|
||||
<body>
|
||||
<div class="navbar navbar-default" role="navigation">
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-header">
|
||||
<a class="navbar-brand" href="https://docs.fedoraproject.org/"><img alt="Fedora Documentation" src="../../../master/_images/fedora.svg"></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container">
|
||||
<p class="toggle-nav visible-xs pull-left">
|
||||
<button class="btn btn-default btn-sm" type="button" data-toggle="offcanvas">Toggle nav</button>
|
||||
</p>
|
||||
<ol class="breadcrumb">
|
||||
<li class="sitename">
|
||||
<a href="../../../index.html">Home</a>
|
||||
</li>
|
||||
<li class="hidden-xs active">
|
||||
<a href="../../en-US/index.html">Defensive Coding Guide </a>
|
||||
</li>
|
||||
<li class="hidden-xs active">
|
||||
<a href="../../en-US/index.html">Defensive Coding Guide</a>
|
||||
</li>
|
||||
<li class="hidden-xs active"><a href="../../en-US/programming-languages/C.html">Programming Languages</a></li>
|
||||
<li class="hidden-xs active">
|
||||
The Go Programming Language
|
||||
</li>
|
||||
</ol>
|
||||
<div class="row row-offcanvas row-offcanvas-left">
|
||||
<div class="col-xs-8 col-sm-3 col-md-3 sidebar sidebar-offcanvas">
|
||||
<ul class="nav nav-sidebar">
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicGroup0">
|
||||
<span id="tgSpan0" class="fa fa-angle-down"></span>Defensive Coding Guide
|
||||
</a>
|
||||
<ul id="topicGroup0" class="collapse in list-unstyled">
|
||||
<li><a class="" href="../../en-US/index.html">Book Information</a></li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-1">
|
||||
<span id="sgSpan-0-1" class="fa fa-caret-down"></span> Programming Languages
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-1" class="nav-tertiary list-unstyled collapse in">
|
||||
<li><a class="" href="../../en-US/programming-languages/C.html">The C Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/CXX.html">The C++ Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Java.html">The Java Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Python.html">The Python Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Shell.html">Shell Programming and bash</a></li>
|
||||
<li><a class=" active" href="../../en-US/programming-languages/Go.html">The Go Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Vala.html">The Vala Programming Language</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-2">
|
||||
<span id="sgSpan-0-2" class="fa fa-caret-right"></span> Specific Programming Tasks
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-2" class="nav-tertiary list-unstyled collapse">
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Library_Design.html">Library Design</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Descriptors.html">File Descriptor Management</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-File_System.html">File System Manipulation</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Temporary_Files.html">Temporary Files</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Processes.html">Processes</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Serialization.html">Serialization and Deserialization</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Cryptography.html">Cryptography</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Packaging.html">RPM Packaging</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-3">
|
||||
<span id="sgSpan-0-3" class="fa fa-caret-right"></span> Implementing Security Features
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-3" class="nav-tertiary list-unstyled collapse">
|
||||
<li><a class="" href="../../en-US/features/Features-Authentication.html">Authentication and Authorization</a></li>
|
||||
<li><a class="" href="../../en-US/features/Features-TLS.html">Transport Layer Security (TLS)</a></li>
|
||||
<li><a class="" href="../../en-US/features/Features-HSM.html">Hardware Security Modules and Smart Cards</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="" href="../../en-US/Revision_History.html">Revision History</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-9 col-md-9 main">
|
||||
<div class="page-header">
|
||||
<h2>The Go Programming Language</h2>
|
||||
</div>
|
||||
<div id="preamble">
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>This chapter contains language-specific recommendations for Go.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="chap-Defensive_Coding-Go-Memory_Safety"><a class="anchor" href="#chap-Defensive_Coding-Go-Memory_Safety"></a>Memory Safety</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>Go provides memory safety, but only if the program is not executed
|
||||
in parallel (that is, <code>GOMAXPROCS</code> is not larger than
|
||||
<code>1</code>). The reason is that interface values and
|
||||
slices consist of multiple words are not updated atomically.
|
||||
Another thread of execution can observe an inconsistent pairing
|
||||
between type information and stored value (for interfaces) or
|
||||
pointer and length (for slices), and such inconsistency can lead
|
||||
to a memory safety violation.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Code which does not run in parallel and does not use the
|
||||
<code>unsafe</code> package (or other packages which expose
|
||||
unsafe constructs) is memory-safe. For example, invalid casts and
|
||||
out-of-range subscripting cause panics at run time.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Keep in mind that finalization can introduce parallelism because
|
||||
finalizers are executed concurrently, potentially interleaved with
|
||||
the rest of the program.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="chap-Defensive_Coding-Go-Error_Handling"><a class="anchor" href="#chap-Defensive_Coding-Go-Error_Handling"></a>Error Handling</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>Only a few common operations (such as pointer dereference, integer
|
||||
division, array subscripting) trigger exceptions in Go, called
|
||||
<strong>panics</strong>. Most interfaces in the standard
|
||||
library use a separate return value of type
|
||||
<code>error</code> to signal error.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Not checking error return values can lead to incorrect operation
|
||||
and data loss (especially in the case of writes, using interfaces
|
||||
such as <code>io.Writer</code>).</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>The correct way to check error return values depends on the
|
||||
function or method being called. In the majority of cases, the
|
||||
first step after calling a function should be an error check
|
||||
against the <code>nil</code> value, handling any encountered
|
||||
error. See <a href="#ex-Defensive_Coding-Go-Error_Handling-Regular">Regular error handling in Go</a> for
|
||||
details.</p>
|
||||
</div>
|
||||
<div id="ex-Defensive_Coding-Go-Error_Handling-Regular" class="exampleblock">
|
||||
<div class="title">Example 1. Regular error handling in Go</div>
|
||||
<div class="content">
|
||||
<div class="listingblock">
|
||||
<div class="content">
|
||||
<pre class="CodeRay highlight"><code data-lang="go">Unresolved directive in <stdin> - include::../snippets/Go-Error_Handling-Regular.adoc[]</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>However, with <code>io.Reader</code>,
|
||||
<code>io.ReaderAt</code> and related interfaces, it is
|
||||
necessary to check for a non-zero number of read bytes first, as
|
||||
shown in <a href="#ex-Defensive_Coding-Go-Error_Handling-IO">Read error handling in Go</a>. If this
|
||||
pattern is not followed, data loss may occur. This is due to the
|
||||
fact that the <code>io.Reader</code> interface permits
|
||||
returning both data and an error at the same time.</p>
|
||||
</div>
|
||||
<div id="ex-Defensive_Coding-Go-Error_Handling-IO" class="exampleblock">
|
||||
<div class="title">Example 2. Read error handling in Go</div>
|
||||
<div class="content">
|
||||
<div class="listingblock">
|
||||
<div class="content">
|
||||
<pre class="CodeRay highlight"><code data-lang="go">Unresolved directive in <stdin> - include::../snippets/Go-Error_Handling-IO.adoc[]</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="chap-Defensive_Coding-Go-Garbage_Collector"><a class="anchor" href="#chap-Defensive_Coding-Go-Garbage_Collector"></a>Garbage Collector</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>Older Go releases (before Go 1.3) use a conservative garbage
|
||||
collector without blacklisting. This means that data blobs can
|
||||
cause retention of unrelated data structures because the data is
|
||||
conservatively interpreted as pointers. This phenomenon can be
|
||||
triggered accidentally on 32-bit architectures and is more likely
|
||||
to occur if the heap grows larger. On 64-bit architectures, it
|
||||
may be possible to trigger it deliberately—it is unlikely to occur
|
||||
spontaneously.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="chap-Defensive_Coding-Go-Marshaling"><a class="anchor" href="#chap-Defensive_Coding-Go-Marshaling"></a>Marshaling and Unmarshaling</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>Several packages in the <code>encoding</code> hierarchy
|
||||
provide support for serialization and deserialization. The usual
|
||||
caveats apply (see
|
||||
<a href="#chap-Defensive_Coding-Tasks-Serialization">[chap-Defensive_Coding-Tasks-Serialization]</a>).</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>As an additional precaution, the <code>Unmarshal</code>
|
||||
and <code>Decode</code> functions should only be used with
|
||||
fresh values in the <code>interface{}</code> argument. This
|
||||
is due to the way defaults for missing values are implemented:
|
||||
During deserialization, missing value do not result in an error,
|
||||
but the original value is preserved. Using a fresh value (with
|
||||
suitable default values if necessary) ensures that data from a
|
||||
previous deserialization operation does not leak into the current
|
||||
one. This is especially relevant when structs are deserialized.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="bottom" class="text-muted py-3" >
|
||||
<div class="foot">
|
||||
<div class="container">
|
||||
<div class="row footerlinks">
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">About</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Overview">About Fedora</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/sponsors">Sponsors</a></dd>
|
||||
<dd><a href="https://fedoramagazine.org">Fedora Magazine</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Legal:Main#Legal">Legal</a></dd>
|
||||
</dl>
|
||||
<ul class="list-inline">
|
||||
<li>
|
||||
<a href="https://www.facebook.com/TheFedoraProject" class="btn-social btn-outline"><i class="fa fa-fw fa-facebook"></i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://plus.google.com/112917221531140868607" class="btn-social btn-outline"><i class="fa fa-fw fa-google-plus"></i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://twitter.com/fedora" class="btn-social btn-outline"><i class="fa fa-fw fa-twitter"></i></a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title uppercase">Download</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://getfedora.org/en/workstation/download">Get Fedora Workstation</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/server/download">Get Fedora Server</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/atomic/download">Get Fedora Atomic</a></dd>
|
||||
<dd><a href="https://spins.fedoraproject.org">Fedora Spins</a></dd>
|
||||
<dd><a href="https://labs.fedoraproject.org">Fedora Labs</a></dd>
|
||||
<dd><a href="https://arm.fedoraproject.org">Fedora ARM<span class="sup">®</span></a></dd>
|
||||
<dd><a href="https://alt.fedoraproject.org/">Alternative Downloads</a></dd>
|
||||
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">Support</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Communicating_and_getting_help">Get Help</a></dd>
|
||||
<dd><a href="https://ask.fedoraproject.org/">Ask Fedora</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Common_F27_bugs">Common Bugs</a></dd>
|
||||
<dd><a href="https://developer.fedoraproject.org/">Fedora Developer Portal</a></dd>
|
||||
<dd><a href="https://docs.fedoraproject.org/f27/install-guide/index.html">Installation Guide</a></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">Join</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Join">Join Fedora</a></dd>
|
||||
<dd><a href="http://fedoraplanet.org">Planet Fedora</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/SIGs">Fedora SIGs</a></dd>
|
||||
<dd><a href="https://admin.fedoraproject.org/accounts/">Fedora Account System</a></dd>
|
||||
<dd><a href="https://fedoracommunity.org/">Fedora Community</a></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- /row of widgets -->
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-2">
|
||||
<div class="widget-body">
|
||||
<a href="https://www.redhat.com/"><img class="rh-logo" src="../../../master/_images/redhat-logo.png" alt="Red Hat Logo" /></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-7">
|
||||
<div class="widget-body">
|
||||
<p class="sponsor">Fedora is sponsored by Red Hat.</p>
|
||||
<p class="sponsor"><a href="https://www.redhat.com/en/technologies/linux-platforms/articles/relationship-between-fedora-and-rhel">Learn more about the relationship between Red Hat and Fedora »</a></p>
|
||||
<p class="copy">© 2017 Red Hat, Inc. and others. Please send any comments or corrections to the <a href="https://pagure.io/fedora-docs/docs-fp-o">documentation team</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- /row of widgets -->
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
|
||||
<!-- Latest compiled and minified JavaScript -->
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
|
||||
<script src="../../../master/_javascripts/bootstrap-offcanvas.js" type="text/javascript"></script>
|
||||
<script type="text/javascript">
|
||||
/*<![CDATA[*/
|
||||
$(document).ready(function() {
|
||||
$("[id^='topicGroup']").on('show.bs.collapse', function (event) {
|
||||
if (!($(event.target).attr('id').match(/^topicSubGroup/))) {
|
||||
$(this).parent().find("[id^='tgSpan']").toggleClass("fa-angle-right fa-angle-down");
|
||||
}
|
||||
});
|
||||
$("[id^='topicGroup']").on('hide.bs.collapse', function (event) {
|
||||
if (!($(event.target).attr('id').match(/^topicSubGroup/))) {
|
||||
$(this).parent().find("[id^='tgSpan']").toggleClass("fa-angle-right fa-angle-down");
|
||||
}
|
||||
});
|
||||
$("[id^='topicSubGroup']").on('show.bs.collapse', function () {
|
||||
$(this).parent().find("[id^='sgSpan']").toggleClass("fa-caret-right fa-caret-down");
|
||||
});
|
||||
$("[id^='topicSubGroup']").on('hide.bs.collapse', function () {
|
||||
$(this).parent().find("[id^='sgSpan']").toggleClass("fa-caret-right fa-caret-down");
|
||||
});
|
||||
});
|
||||
/*]]>*/
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -1,313 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta content="IE=edge" http-equiv="X-UA-Compatible">
|
||||
<meta content="width=device-width, initial-scale=1.0" name="viewport">
|
||||
<title>Defensive Coding Guide | Defensive Coding Guide | Programming Languages | The Python Programming Language</title>
|
||||
|
||||
<!-- Bootstrap -->
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap-theme.min.css">
|
||||
|
||||
<!-- Overpass Font -->
|
||||
<link rel="stylesheet" href="https://overpass-30e2.kxcdn.com/overpass.css">
|
||||
|
||||
<link href="../../../master/_stylesheets/asciibinder.css" rel="stylesheet" />
|
||||
|
||||
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
|
||||
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
|
||||
<!--[if lt IE 9]>
|
||||
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
|
||||
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
|
||||
<![endif]-->
|
||||
|
||||
<link href="../../../master/_images/favicon32x32.png" rel="shortcut icon" type="text/css">
|
||||
<!--[if IE]><link rel="shortcut icon" href="../../../master/_images/favicon.ico"><![endif]-->
|
||||
<meta content="AsciiBinder" name="application-name">
|
||||
</head>
|
||||
<body>
|
||||
<div class="navbar navbar-default" role="navigation">
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-header">
|
||||
<a class="navbar-brand" href="https://docs.fedoraproject.org/"><img alt="Fedora Documentation" src="../../../master/_images/fedora.svg"></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container">
|
||||
<p class="toggle-nav visible-xs pull-left">
|
||||
<button class="btn btn-default btn-sm" type="button" data-toggle="offcanvas">Toggle nav</button>
|
||||
</p>
|
||||
<ol class="breadcrumb">
|
||||
<li class="sitename">
|
||||
<a href="../../../index.html">Home</a>
|
||||
</li>
|
||||
<li class="hidden-xs active">
|
||||
<a href="../../en-US/index.html">Defensive Coding Guide </a>
|
||||
</li>
|
||||
<li class="hidden-xs active">
|
||||
<a href="../../en-US/index.html">Defensive Coding Guide</a>
|
||||
</li>
|
||||
<li class="hidden-xs active"><a href="../../en-US/programming-languages/C.html">Programming Languages</a></li>
|
||||
<li class="hidden-xs active">
|
||||
The Python Programming Language
|
||||
</li>
|
||||
</ol>
|
||||
<div class="row row-offcanvas row-offcanvas-left">
|
||||
<div class="col-xs-8 col-sm-3 col-md-3 sidebar sidebar-offcanvas">
|
||||
<ul class="nav nav-sidebar">
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicGroup0">
|
||||
<span id="tgSpan0" class="fa fa-angle-down"></span>Defensive Coding Guide
|
||||
</a>
|
||||
<ul id="topicGroup0" class="collapse in list-unstyled">
|
||||
<li><a class="" href="../../en-US/index.html">Book Information</a></li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-1">
|
||||
<span id="sgSpan-0-1" class="fa fa-caret-down"></span> Programming Languages
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-1" class="nav-tertiary list-unstyled collapse in">
|
||||
<li><a class="" href="../../en-US/programming-languages/C.html">The C Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/CXX.html">The C++ Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Java.html">The Java Programming Language</a></li>
|
||||
<li><a class=" active" href="../../en-US/programming-languages/Python.html">The Python Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Shell.html">Shell Programming and bash</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Go.html">The Go Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Vala.html">The Vala Programming Language</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-2">
|
||||
<span id="sgSpan-0-2" class="fa fa-caret-right"></span> Specific Programming Tasks
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-2" class="nav-tertiary list-unstyled collapse">
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Library_Design.html">Library Design</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Descriptors.html">File Descriptor Management</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-File_System.html">File System Manipulation</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Temporary_Files.html">Temporary Files</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Processes.html">Processes</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Serialization.html">Serialization and Deserialization</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Cryptography.html">Cryptography</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Packaging.html">RPM Packaging</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-3">
|
||||
<span id="sgSpan-0-3" class="fa fa-caret-right"></span> Implementing Security Features
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-3" class="nav-tertiary list-unstyled collapse">
|
||||
<li><a class="" href="../../en-US/features/Features-Authentication.html">Authentication and Authorization</a></li>
|
||||
<li><a class="" href="../../en-US/features/Features-TLS.html">Transport Layer Security (TLS)</a></li>
|
||||
<li><a class="" href="../../en-US/features/Features-HSM.html">Hardware Security Modules and Smart Cards</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="" href="../../en-US/Revision_History.html">Revision History</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-9 col-md-9 main">
|
||||
<div class="page-header">
|
||||
<h2>The Python Programming Language</h2>
|
||||
</div>
|
||||
<div id="preamble">
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>Python provides memory safety by default, so low-level security
|
||||
vulnerabilities are rare and typically needs fixing the Python
|
||||
interpreter or standard library itself.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Other sections with Python-specific advice include:</p>
|
||||
</div>
|
||||
<div class="ulist">
|
||||
<ul>
|
||||
<li>
|
||||
<p><a href="#chap-Defensive_Coding-Tasks-Temporary_Files">[chap-Defensive_Coding-Tasks-Temporary_Files]</a></p>
|
||||
</li>
|
||||
<li>
|
||||
<p><a href="#sect-Defensive_Coding-Tasks-Processes-Creation">[sect-Defensive_Coding-Tasks-Processes-Creation]</a></p>
|
||||
</li>
|
||||
<li>
|
||||
<p><a href="#chap-Defensive_Coding-Tasks-Serialization">[chap-Defensive_Coding-Tasks-Serialization]</a>, in
|
||||
particular <a href="#sect-Defensive_Coding-Tasks-Serialization-Library">[sect-Defensive_Coding-Tasks-Serialization-Library]</a></p>
|
||||
</li>
|
||||
<li>
|
||||
<p><a href="#sect-Defensive_Coding-Tasks-Cryptography-Randomness">[sect-Defensive_Coding-Tasks-Cryptography-Randomness]</a></p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="dangerous-standard-library-features"><a class="anchor" href="#dangerous-standard-library-features"></a>Dangerous Standard Library Features</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>Some areas of the standard library, notably the
|
||||
<code>ctypes</code> module, do not provide memory safety
|
||||
guarantees comparable to the rest of Python. If such
|
||||
functionality is used, the advice in <a href="#sect-Defensive_Coding-C-Language">[sect-Defensive_Coding-C-Language]</a> should be followed.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="run-time-compilation-and-code-generation"><a class="anchor" href="#run-time-compilation-and-code-generation"></a>Run-time Compilation and Code Generation</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>The following Python functions and statements related to code
|
||||
execution should be avoided:</p>
|
||||
</div>
|
||||
<div class="ulist">
|
||||
<ul>
|
||||
<li>
|
||||
<p><code>compile</code></p>
|
||||
</li>
|
||||
<li>
|
||||
<p><code>eval</code></p>
|
||||
</li>
|
||||
<li>
|
||||
<p><code>exec</code></p>
|
||||
</li>
|
||||
<li>
|
||||
<p><code>execfile</code></p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>If you need to parse integers or floating point values, use the
|
||||
<code>int</code> and <code>float</code>
|
||||
functions instead of <code>eval</code>. Sandboxing
|
||||
untrusted Python code does not work reliably.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="sandboxing"><a class="anchor" href="#sandboxing"></a>Sandboxing</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>The <code>rexec</code> Python module cannot safely sandbox
|
||||
untrusted code and should not be used. The standard CPython
|
||||
implementation is not suitable for sandboxing.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="bottom" class="text-muted py-3" >
|
||||
<div class="foot">
|
||||
<div class="container">
|
||||
<div class="row footerlinks">
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">About</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Overview">About Fedora</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/sponsors">Sponsors</a></dd>
|
||||
<dd><a href="https://fedoramagazine.org">Fedora Magazine</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Legal:Main#Legal">Legal</a></dd>
|
||||
</dl>
|
||||
<ul class="list-inline">
|
||||
<li>
|
||||
<a href="https://www.facebook.com/TheFedoraProject" class="btn-social btn-outline"><i class="fa fa-fw fa-facebook"></i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://plus.google.com/112917221531140868607" class="btn-social btn-outline"><i class="fa fa-fw fa-google-plus"></i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://twitter.com/fedora" class="btn-social btn-outline"><i class="fa fa-fw fa-twitter"></i></a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title uppercase">Download</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://getfedora.org/en/workstation/download">Get Fedora Workstation</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/server/download">Get Fedora Server</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/atomic/download">Get Fedora Atomic</a></dd>
|
||||
<dd><a href="https://spins.fedoraproject.org">Fedora Spins</a></dd>
|
||||
<dd><a href="https://labs.fedoraproject.org">Fedora Labs</a></dd>
|
||||
<dd><a href="https://arm.fedoraproject.org">Fedora ARM<span class="sup">®</span></a></dd>
|
||||
<dd><a href="https://alt.fedoraproject.org/">Alternative Downloads</a></dd>
|
||||
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">Support</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Communicating_and_getting_help">Get Help</a></dd>
|
||||
<dd><a href="https://ask.fedoraproject.org/">Ask Fedora</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Common_F27_bugs">Common Bugs</a></dd>
|
||||
<dd><a href="https://developer.fedoraproject.org/">Fedora Developer Portal</a></dd>
|
||||
<dd><a href="https://docs.fedoraproject.org/f27/install-guide/index.html">Installation Guide</a></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">Join</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Join">Join Fedora</a></dd>
|
||||
<dd><a href="http://fedoraplanet.org">Planet Fedora</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/SIGs">Fedora SIGs</a></dd>
|
||||
<dd><a href="https://admin.fedoraproject.org/accounts/">Fedora Account System</a></dd>
|
||||
<dd><a href="https://fedoracommunity.org/">Fedora Community</a></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- /row of widgets -->
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-2">
|
||||
<div class="widget-body">
|
||||
<a href="https://www.redhat.com/"><img class="rh-logo" src="../../../master/_images/redhat-logo.png" alt="Red Hat Logo" /></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-7">
|
||||
<div class="widget-body">
|
||||
<p class="sponsor">Fedora is sponsored by Red Hat.</p>
|
||||
<p class="sponsor"><a href="https://www.redhat.com/en/technologies/linux-platforms/articles/relationship-between-fedora-and-rhel">Learn more about the relationship between Red Hat and Fedora »</a></p>
|
||||
<p class="copy">© 2017 Red Hat, Inc. and others. Please send any comments or corrections to the <a href="https://pagure.io/fedora-docs/docs-fp-o">documentation team</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- /row of widgets -->
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
|
||||
<!-- Latest compiled and minified JavaScript -->
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
|
||||
<script src="../../../master/_javascripts/bootstrap-offcanvas.js" type="text/javascript"></script>
|
||||
<script type="text/javascript">
|
||||
/*<![CDATA[*/
|
||||
$(document).ready(function() {
|
||||
$("[id^='topicGroup']").on('show.bs.collapse', function (event) {
|
||||
if (!($(event.target).attr('id').match(/^topicSubGroup/))) {
|
||||
$(this).parent().find("[id^='tgSpan']").toggleClass("fa-angle-right fa-angle-down");
|
||||
}
|
||||
});
|
||||
$("[id^='topicGroup']").on('hide.bs.collapse', function (event) {
|
||||
if (!($(event.target).attr('id').match(/^topicSubGroup/))) {
|
||||
$(this).parent().find("[id^='tgSpan']").toggleClass("fa-angle-right fa-angle-down");
|
||||
}
|
||||
});
|
||||
$("[id^='topicSubGroup']").on('show.bs.collapse', function () {
|
||||
$(this).parent().find("[id^='sgSpan']").toggleClass("fa-caret-right fa-caret-down");
|
||||
});
|
||||
$("[id^='topicSubGroup']").on('hide.bs.collapse', function () {
|
||||
$(this).parent().find("[id^='sgSpan']").toggleClass("fa-caret-right fa-caret-down");
|
||||
});
|
||||
});
|
||||
/*]]>*/
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -1,699 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta content="IE=edge" http-equiv="X-UA-Compatible">
|
||||
<meta content="width=device-width, initial-scale=1.0" name="viewport">
|
||||
<title>Defensive Coding Guide | Defensive Coding Guide | Programming Languages | Shell Programming and bash</title>
|
||||
|
||||
<!-- Bootstrap -->
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap-theme.min.css">
|
||||
|
||||
<!-- Overpass Font -->
|
||||
<link rel="stylesheet" href="https://overpass-30e2.kxcdn.com/overpass.css">
|
||||
|
||||
<link href="../../../master/_stylesheets/asciibinder.css" rel="stylesheet" />
|
||||
|
||||
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
|
||||
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
|
||||
<!--[if lt IE 9]>
|
||||
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
|
||||
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
|
||||
<![endif]-->
|
||||
|
||||
<link href="../../../master/_images/favicon32x32.png" rel="shortcut icon" type="text/css">
|
||||
<!--[if IE]><link rel="shortcut icon" href="../../../master/_images/favicon.ico"><![endif]-->
|
||||
<meta content="AsciiBinder" name="application-name">
|
||||
</head>
|
||||
<body>
|
||||
<div class="navbar navbar-default" role="navigation">
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-header">
|
||||
<a class="navbar-brand" href="https://docs.fedoraproject.org/"><img alt="Fedora Documentation" src="../../../master/_images/fedora.svg"></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container">
|
||||
<p class="toggle-nav visible-xs pull-left">
|
||||
<button class="btn btn-default btn-sm" type="button" data-toggle="offcanvas">Toggle nav</button>
|
||||
</p>
|
||||
<ol class="breadcrumb">
|
||||
<li class="sitename">
|
||||
<a href="../../../index.html">Home</a>
|
||||
</li>
|
||||
<li class="hidden-xs active">
|
||||
<a href="../../en-US/index.html">Defensive Coding Guide </a>
|
||||
</li>
|
||||
<li class="hidden-xs active">
|
||||
<a href="../../en-US/index.html">Defensive Coding Guide</a>
|
||||
</li>
|
||||
<li class="hidden-xs active"><a href="../../en-US/programming-languages/C.html">Programming Languages</a></li>
|
||||
<li class="hidden-xs active">
|
||||
Shell Programming and bash
|
||||
</li>
|
||||
</ol>
|
||||
<div class="row row-offcanvas row-offcanvas-left">
|
||||
<div class="col-xs-8 col-sm-3 col-md-3 sidebar sidebar-offcanvas">
|
||||
<ul class="nav nav-sidebar">
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicGroup0">
|
||||
<span id="tgSpan0" class="fa fa-angle-down"></span>Defensive Coding Guide
|
||||
</a>
|
||||
<ul id="topicGroup0" class="collapse in list-unstyled">
|
||||
<li><a class="" href="../../en-US/index.html">Book Information</a></li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-1">
|
||||
<span id="sgSpan-0-1" class="fa fa-caret-down"></span> Programming Languages
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-1" class="nav-tertiary list-unstyled collapse in">
|
||||
<li><a class="" href="../../en-US/programming-languages/C.html">The C Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/CXX.html">The C++ Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Java.html">The Java Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Python.html">The Python Programming Language</a></li>
|
||||
<li><a class=" active" href="../../en-US/programming-languages/Shell.html">Shell Programming and bash</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Go.html">The Go Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Vala.html">The Vala Programming Language</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-2">
|
||||
<span id="sgSpan-0-2" class="fa fa-caret-right"></span> Specific Programming Tasks
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-2" class="nav-tertiary list-unstyled collapse">
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Library_Design.html">Library Design</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Descriptors.html">File Descriptor Management</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-File_System.html">File System Manipulation</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Temporary_Files.html">Temporary Files</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Processes.html">Processes</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Serialization.html">Serialization and Deserialization</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Cryptography.html">Cryptography</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Packaging.html">RPM Packaging</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-3">
|
||||
<span id="sgSpan-0-3" class="fa fa-caret-right"></span> Implementing Security Features
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-3" class="nav-tertiary list-unstyled collapse">
|
||||
<li><a class="" href="../../en-US/features/Features-Authentication.html">Authentication and Authorization</a></li>
|
||||
<li><a class="" href="../../en-US/features/Features-TLS.html">Transport Layer Security (TLS)</a></li>
|
||||
<li><a class="" href="../../en-US/features/Features-HSM.html">Hardware Security Modules and Smart Cards</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="" href="../../en-US/Revision_History.html">Revision History</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-9 col-md-9 main">
|
||||
<div class="page-header">
|
||||
<h2>Shell Programming and <strong class="application">bash</strong></h2>
|
||||
</div>
|
||||
<div id="preamble">
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>This chapter contains advice about shell programming, specifically
|
||||
in <strong class="application">bash</strong>. Most of the advice will apply
|
||||
to scripts written for other shells because extensions such as
|
||||
integer or array variables have been implemented there as well, with
|
||||
comparable syntax.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="sect-Defensive_Coding-Shell-Alternatives"><a class="anchor" href="#sect-Defensive_Coding-Shell-Alternatives"></a>Consider Alternatives</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>Once a shell script is so complex that advice in this chapter
|
||||
applies, it is time to step back and consider the question: Is
|
||||
there a more suitable implementation language available?</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>For example, Python with its <code>subprocess</code> module
|
||||
can be used to write scripts which are almost as concise as shell
|
||||
scripts when it comes to invoking external programs, and Python
|
||||
offers richer data structures, with less arcane syntax and more
|
||||
consistent behavior.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="sect-Defensive_Coding-Shell-Language"><a class="anchor" href="#sect-Defensive_Coding-Shell-Language"></a>Shell Language Features</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>The following sections cover subtleties concerning the shell
|
||||
programming languages. They have been written with the
|
||||
<strong class="application">bash</strong> shell in mind, but some of these
|
||||
features apply to other shells as well.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Some of the features described may seem like implementation defects,
|
||||
but these features have been replicated across multiple independent
|
||||
implementations, so they now have to be considered part of the shell
|
||||
programming language.</p>
|
||||
</div>
|
||||
<div class="sect2">
|
||||
<h3 id="sect-Defensive_Coding-Shell-Parameter_Expansion"><a class="anchor" href="#sect-Defensive_Coding-Shell-Parameter_Expansion"></a>Parameter Expansion</h3>
|
||||
<div class="paragraph">
|
||||
<p>The mechanism by which named shell variables and parameters are
|
||||
expanded is called <strong>parameter expansion</strong>. The
|
||||
most basic syntax is
|
||||
“<code>$</code><strong>variable</strong>” or
|
||||
“<code>${</code><strong>variable</strong><code>}</code>”.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>In almost all cases, a parameter expansion should be enclosed in
|
||||
double quotation marks <code>“…”</code>.</p>
|
||||
</div>
|
||||
<div class="listingblock">
|
||||
<div class="content">
|
||||
<pre class="CodeRay highlight"><code data-lang="bash">external-program "$arg1" "$arg2"</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>If the double quotation marks are omitted, the value of the
|
||||
variable will be split according to the current value of the
|
||||
<code>IFS</code> variable. This may allow the injection of
|
||||
additional options which are then processed by
|
||||
<code>external-program</code>.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Parameter expansion can use special syntax for specific features,
|
||||
such as substituting defaults or performing string or array
|
||||
operations. These constructs should not be used because they can
|
||||
trigger arithmetic evaluation, which can result in code execution.
|
||||
See <a href="#sect-Defensive_Coding-Shell-Arithmetic">Arithmetic Evaluation</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect2">
|
||||
<h3 id="sect-Defensive_Coding-Shell-Double_Expansion"><a class="anchor" href="#sect-Defensive_Coding-Shell-Double_Expansion"></a>Double Expansion</h3>
|
||||
<div class="paragraph">
|
||||
<p><strong>Double expansion</strong> occurs when, during the
|
||||
expansion of a shell variable, not just the variable is expanded,
|
||||
replacing it by its value, but the <strong>value</strong> of
|
||||
the variable is itself is expanded as well. This can trigger
|
||||
arbitrary code execution, unless the value of the variable is
|
||||
verified against a restrictive pattern.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>The evaluation process is in fact recursive, so a self-referential
|
||||
expression can cause an out-of-memory condition and a shell crash.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Double expansion may seem like as a defect, but it is implemented
|
||||
by many shells, and has to be considered an integral part of the
|
||||
shell programming language. However, it does make writing robust
|
||||
shell scripts difficult.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Double expansion can be requested explicitly with the
|
||||
<code>eval</code> built-in command, or by invoking a
|
||||
subshell with “<code>bash -c</code>”. These constructs
|
||||
should not be used.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>The following sections give examples of places where implicit
|
||||
double expansion occurs.</p>
|
||||
</div>
|
||||
<div class="sect3">
|
||||
<h4 id="sect-Defensive_Coding-Shell-Arithmetic"><a class="anchor" href="#sect-Defensive_Coding-Shell-Arithmetic"></a>Arithmetic Evaluation</h4>
|
||||
<div class="paragraph">
|
||||
<p><strong>Arithmetic evaluation</strong> is a process by which
|
||||
the shell computes the integer value of an expression specified
|
||||
as a string. It is highly problematic for two reasons: It
|
||||
triggers double expansion (see <a href="#sect-Defensive_Coding-Shell-Double_Expansion">Double Expansion</a>), and the
|
||||
language of arithmetic expressions is not self-contained. Some
|
||||
constructs in arithmetic expressions (notably array subscripts)
|
||||
provide a trapdoor from the restricted language of arithmetic
|
||||
expressions to the full shell language, thus paving the way
|
||||
towards arbitrary code execution. Due to double expansion,
|
||||
input which is (indirectly) referenced from an arithmetic
|
||||
expression can trigger execution of arbitrary code, which is
|
||||
potentially harmful.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Arithmetic evaluation is triggered by the follow constructs:</p>
|
||||
</div>
|
||||
<div class="ulist">
|
||||
<ul>
|
||||
<li>
|
||||
<p>The <strong>expression</strong> in
|
||||
“<code>$</code><strong>expression</strong><code></code>”
|
||||
is evaluated. This construct is called <strong>arithmetic
|
||||
expansion</strong>.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p></p>
|
||||
<div class="paragraph">
|
||||
<p>“<code>$[</code><strong>expression</strong><code>]</code>”
|
||||
is a deprecated syntax with the same effect.</p>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<p>The arguments to the <code>let</code> shell built-in
|
||||
are evaluated.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p></p>
|
||||
<div class="paragraph">
|
||||
<p>“<code></code><strong>expression</strong><code></code>”
|
||||
is an alternative syntax for “<code>let</code> <strong>expression</strong>”.</p>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<p>Conditional expressions surrounded by
|
||||
“<code>[[</code>…<code>]]</code>” can trigger
|
||||
arithmetic evaluation if certain operators such as
|
||||
<code>-eq</code> are used. (The
|
||||
<code>test</code> built-in does not perform arithmetic
|
||||
evaluation, even with integer operators such as
|
||||
<code>-eq</code>.)</p>
|
||||
<div class="paragraph">
|
||||
<p>The conditional expression
|
||||
“<code>[[ $</code><strong>variable</strong> <code>=~</code> <strong>regexp</strong> <code>]]</code>”
|
||||
can be used for input validation, assuming that
|
||||
<strong>regexp</strong> is a constant regular
|
||||
expression.
|
||||
See <a href="#sect-Defensive_Coding-Shell-Input_Validation">Performing Input Validation</a>.</p>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<p>Certain parameter expansions, for example
|
||||
“<code>${</code><strong>variable</strong><code>[</code><strong>expression</strong><code>]}</code>”
|
||||
(array indexing) or
|
||||
“<code>${</code><strong>variable</strong><code>:</code><strong>expression</strong><code>}</code>”
|
||||
(string slicing), trigger arithmetic evaluation of
|
||||
<strong>expression</strong>.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Assignment to array elements using
|
||||
“<strong>array_variable</strong><code>[</code><strong>subscript</strong><code>]=</code><strong>expression</strong>”
|
||||
triggers evaluation of <strong>subscript</strong>, but
|
||||
not <strong>expression</strong>.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>The expressions in the arithmetic <code>for</code>
|
||||
command,
|
||||
“<code>for </code><strong>expression1</strong><code>;</code> <strong>expression2</strong><code>;</code> <strong>expression3</strong><code>; do</code> <strong>commands</strong><code>; done</code>”
|
||||
are evaluated. This does not apply to the regular
|
||||
for command,
|
||||
“<code>for</code> <strong>variable</strong> <code>in</code> <strong>list</strong><code>; do</code> <strong>commands</strong><code>; done</code>”.</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="admonitionblock important">
|
||||
<table>
|
||||
<tr>
|
||||
<td class="icon">
|
||||
<i class="fa icon-important" title="Important"></i>
|
||||
</td>
|
||||
<td class="content">
|
||||
<div class="paragraph">
|
||||
<p>Depending on the <strong class="application">bash</strong> version, the
|
||||
above list may be incomplete.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>If faced with a situation where using such shell features
|
||||
appears necessary, see <a href="#sect-Defensive_Coding-Shell-Alternatives">Consider Alternatives</a>.</p>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>If it is impossible to avoid shell arithmetic on untrusted
|
||||
inputs, refer to <a href="#sect-Defensive_Coding-Shell-Input_Validation">Performing Input Validation</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect3">
|
||||
<h4 id="sect-Defensive_Coding-Shell-Types"><a class="anchor" href="#sect-Defensive_Coding-Shell-Types"></a>Type declarations</h4>
|
||||
<div class="paragraph">
|
||||
<p><strong class="application">bash</strong> supports explicit type
|
||||
declarations for shell variables:</p>
|
||||
</div>
|
||||
<div class="listingblock">
|
||||
<div class="content">
|
||||
<pre class="CodeRay highlight"><code data-lang="bash"> declare -i integer_variable
|
||||
declare -a array_variable
|
||||
declare -A assoc_array_variable
|
||||
|
||||
typeset -i integer_variable
|
||||
typeset -a array_variable
|
||||
typeset -A assoc_array_variable
|
||||
|
||||
local -i integer_variable
|
||||
local -a array_variable
|
||||
local -A assoc_array_variable
|
||||
|
||||
readonly -i integer_variable
|
||||
readonly -a array_variable
|
||||
readonly -A assoc_array_variable</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Variables can also be declared as arrays by assigning them an
|
||||
array expression, as in:</p>
|
||||
</div>
|
||||
<div class="listingblock">
|
||||
<div class="content">
|
||||
<pre class="CodeRay highlight"><code data-lang="bash">array_variable=(1 2 3 4)</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Some built-ins (such as <code>mapfile</code>) can
|
||||
implicitly create array variables.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Such type declarations should not be used because assignment to
|
||||
such variables (independent of the concrete syntax used for the
|
||||
assignment) triggers arithmetic expansion (and thus double
|
||||
expansion) of the right-hand side of the assignment operation.
|
||||
See <a href="#sect-Defensive_Coding-Shell-Arithmetic">Arithmetic Evaluation</a>.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Shell scripts which use integer or array variables should be
|
||||
rewritten in another, more suitable language. Se <a href="#sect-Defensive_Coding-Shell-Alternatives">Consider Alternatives</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect2">
|
||||
<h3 id="sect-Defensive_Coding-Shell-Obscure"><a class="anchor" href="#sect-Defensive_Coding-Shell-Obscure"></a>Other Obscurities</h3>
|
||||
<div class="paragraph">
|
||||
<p>Obscure shell language features should not be used. Examples are:</p>
|
||||
</div>
|
||||
<div class="ulist">
|
||||
<ul>
|
||||
<li>
|
||||
<p>Exported functions (<code>export -f</code> or
|
||||
<code>declare -f</code>).</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Function names which are not valid variable names, such as
|
||||
“<code>module::function</code>”.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>The possibility to override built-ins or external commands
|
||||
with shell functions.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Changing the value of the <code>IFS</code> variable to
|
||||
tokenize strings.</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="sect-Defensive_Coding-Shell-Invoke"><a class="anchor" href="#sect-Defensive_Coding-Shell-Invoke"></a>Invoking External Commands</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>When passing shell variables as single command line arguments,
|
||||
they should always be surrounded by double quotes. See
|
||||
<a href="#sect-Defensive_Coding-Shell-Parameter_Expansion">Parameter Expansion</a>.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Care is required when passing untrusted values as positional
|
||||
parameters to external commands. If the value starts with a hyphen
|
||||
“<code>-</code>”, it may be interpreted by the external
|
||||
command as an option. Depending on the external program, a
|
||||
“<code>--</code>” argument stops option processing and treats
|
||||
all following arguments as positional parameters. (Double quotes
|
||||
are completely invisible to the command being invoked, so they do
|
||||
not prevent variable values from being interpreted as options.)</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Cleaning the environment before invoking child processes is
|
||||
difficult to implement in script. <strong class="application">bash</strong>
|
||||
keeps a hidden list of environment variables which do not correspond
|
||||
to shell variables, and unsetting them from within a
|
||||
<strong class="application">bash</strong> script is not possible. To reset
|
||||
the environment, a script can re-run itself under the “<code>env
|
||||
-i</code>” command with an additional parameter which indicates
|
||||
the environment has been cleared and suppresses a further
|
||||
self-execution. Alternatively, individual commands can be executed
|
||||
with “<code>env -i</code>”.</p>
|
||||
</div>
|
||||
<div class="admonitionblock important">
|
||||
<table>
|
||||
<tr>
|
||||
<td class="icon">
|
||||
<i class="fa icon-important" title="Important"></i>
|
||||
</td>
|
||||
<td class="content">
|
||||
<div class="paragraph">
|
||||
<p>Complete isolation from its original execution environment
|
||||
(which is required when the script is executed after a trust
|
||||
transition, e.g., triggered by the SUID mechanism) is impossible
|
||||
to achieve from within the shell script itself. Instead, the
|
||||
invoking process has to clear the process environment (except for
|
||||
few trusted variables) before running the shell script.</p>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Checking for failures in executed external commands is recommended.
|
||||
If no elaborate error recovery is needed, invoking “<code>set
|
||||
-e</code>” may be sufficient. This causes the script to stop on
|
||||
the first failed command. However, failures in pipes
|
||||
(“<code>command1 | command2</code>”) are only detected for the
|
||||
last command in the pipe, errors in previous commands are ignored.
|
||||
This can be changed by invoking “<code>set -o pipefail</code>”.
|
||||
Due to architectural limitations, only the process that spawned
|
||||
the entire pipe can check for failures in individual commands;
|
||||
it is not possible for a process to tell if the process feeding
|
||||
data (or the process consuming data) exited normally or with
|
||||
an error.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>See <a href="#sect-Defensive_Coding-Tasks-Processes-Creation">[sect-Defensive_Coding-Tasks-Processes-Creation]</a>
|
||||
for additional details on creating child processes.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="sect-Defensive_Coding-Shell-Temporary_Files"><a class="anchor" href="#sect-Defensive_Coding-Shell-Temporary_Files"></a>Temporary Files</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>Temporary files should be created with the
|
||||
<code>mktemp</code> command, and temporary directories with
|
||||
“<code>mktemp -d</code>”.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>To clean up temporary files and directories, write a clean-up
|
||||
shell function and register it as a trap handler, as shown in
|
||||
<a href="#ex-Defensive_Coding-Tasks-Temporary_Files">Creating and Cleaning up Temporary Files</a>.
|
||||
Using a separate function avoids issues with proper quoting of
|
||||
variables.</p>
|
||||
</div>
|
||||
<div id="ex-Defensive_Coding-Tasks-Temporary_Files" class="exampleblock">
|
||||
<div class="title">Example 1. Creating and Cleaning up Temporary Files</div>
|
||||
<div class="content">
|
||||
<div class="listingblock">
|
||||
<div class="content">
|
||||
<pre class="CodeRay highlight"><code data-lang="bash">tmpfile="$(mktemp)"
|
||||
|
||||
cleanup () {
|
||||
rm -f -- "$tmpfile"
|
||||
}
|
||||
|
||||
trap cleanup 0</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="sect-Defensive_Coding-Shell-Input_Validation"><a class="anchor" href="#sect-Defensive_Coding-Shell-Input_Validation"></a>Performing Input Validation</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>In some cases, input validation cannot be avoided. For example,
|
||||
if arithmetic evaluation is absolutely required, it is imperative
|
||||
to check that input values are, in fact, integers. See <a href="#sect-Defensive_Coding-Shell-Arithmetic">Arithmetic Evaluation</a>.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p><a href="#ex-Defensive_Coding-Shell-Input_Validation">Input validation in <strong class="application">bash</strong></a>
|
||||
shows a construct which can be used to check if a string
|
||||
“<code>$value</code>” is an integer. This construct is
|
||||
specific to <strong class="application">bash</strong> and not portable to
|
||||
POSIX shells.</p>
|
||||
</div>
|
||||
<div id="ex-Defensive_Coding-Shell-Input_Validation" class="exampleblock">
|
||||
<div class="title">Example 2. Input validation in <strong class="application">bash</strong></div>
|
||||
<div class="content">
|
||||
<div class="listingblock">
|
||||
<div class="content">
|
||||
<pre class="CodeRay highlight"><code data-lang="bash">Unresolved directive in <stdin> - include::../snippets/Shell-Input_Validation.adoc[]</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Using <code>case</code> statements for input validation is
|
||||
also possible and supported by other (POSIX) shells, but the
|
||||
pattern language is more restrictive, and it can be difficult to
|
||||
write suitable patterns.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>The <code>expr</code> external command can give misleading
|
||||
results (e.g., if the value being checked contains operators
|
||||
itself) and should not be used.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="sect-Defensive_Coding-Shell-Edit_Guard"><a class="anchor" href="#sect-Defensive_Coding-Shell-Edit_Guard"></a>Guarding Shell Scripts Against Changes</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p><strong class="application">bash</strong> only reads a shell script up to
|
||||
the point it is needed for executed the next command. This means
|
||||
that if script is overwritten while it is running, execution can
|
||||
jump to a random part of the script, depending on what is modified
|
||||
in the script and how the file offsets change as a result. (This
|
||||
behavior is needed to support self-extracting shell archives whose
|
||||
script part is followed by a stream of bytes which does not follow
|
||||
the shell language syntax.)</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Therefore, long-running scripts should be guarded against
|
||||
concurrent modification by putting as much of the program logic
|
||||
into a <code>main</code> function, and invoking the
|
||||
<code>main</code> function at the end of the script, using
|
||||
this syntax:</p>
|
||||
</div>
|
||||
<div class="listingblock">
|
||||
<div class="content">
|
||||
<pre class="CodeRay highlight"><code data-lang="bash">main "$@" ; exit $?</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>This construct ensures that <strong class="application">bash</strong> will
|
||||
stop execution after the <code>main</code> function, instead
|
||||
of opening the script file and trying to read more commands.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="bottom" class="text-muted py-3" >
|
||||
<div class="foot">
|
||||
<div class="container">
|
||||
<div class="row footerlinks">
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">About</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Overview">About Fedora</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/sponsors">Sponsors</a></dd>
|
||||
<dd><a href="https://fedoramagazine.org">Fedora Magazine</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Legal:Main#Legal">Legal</a></dd>
|
||||
</dl>
|
||||
<ul class="list-inline">
|
||||
<li>
|
||||
<a href="https://www.facebook.com/TheFedoraProject" class="btn-social btn-outline"><i class="fa fa-fw fa-facebook"></i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://plus.google.com/112917221531140868607" class="btn-social btn-outline"><i class="fa fa-fw fa-google-plus"></i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://twitter.com/fedora" class="btn-social btn-outline"><i class="fa fa-fw fa-twitter"></i></a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title uppercase">Download</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://getfedora.org/en/workstation/download">Get Fedora Workstation</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/server/download">Get Fedora Server</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/atomic/download">Get Fedora Atomic</a></dd>
|
||||
<dd><a href="https://spins.fedoraproject.org">Fedora Spins</a></dd>
|
||||
<dd><a href="https://labs.fedoraproject.org">Fedora Labs</a></dd>
|
||||
<dd><a href="https://arm.fedoraproject.org">Fedora ARM<span class="sup">®</span></a></dd>
|
||||
<dd><a href="https://alt.fedoraproject.org/">Alternative Downloads</a></dd>
|
||||
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">Support</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Communicating_and_getting_help">Get Help</a></dd>
|
||||
<dd><a href="https://ask.fedoraproject.org/">Ask Fedora</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Common_F27_bugs">Common Bugs</a></dd>
|
||||
<dd><a href="https://developer.fedoraproject.org/">Fedora Developer Portal</a></dd>
|
||||
<dd><a href="https://docs.fedoraproject.org/f27/install-guide/index.html">Installation Guide</a></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">Join</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Join">Join Fedora</a></dd>
|
||||
<dd><a href="http://fedoraplanet.org">Planet Fedora</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/SIGs">Fedora SIGs</a></dd>
|
||||
<dd><a href="https://admin.fedoraproject.org/accounts/">Fedora Account System</a></dd>
|
||||
<dd><a href="https://fedoracommunity.org/">Fedora Community</a></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- /row of widgets -->
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-2">
|
||||
<div class="widget-body">
|
||||
<a href="https://www.redhat.com/"><img class="rh-logo" src="../../../master/_images/redhat-logo.png" alt="Red Hat Logo" /></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-7">
|
||||
<div class="widget-body">
|
||||
<p class="sponsor">Fedora is sponsored by Red Hat.</p>
|
||||
<p class="sponsor"><a href="https://www.redhat.com/en/technologies/linux-platforms/articles/relationship-between-fedora-and-rhel">Learn more about the relationship between Red Hat and Fedora »</a></p>
|
||||
<p class="copy">© 2017 Red Hat, Inc. and others. Please send any comments or corrections to the <a href="https://pagure.io/fedora-docs/docs-fp-o">documentation team</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- /row of widgets -->
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
|
||||
<!-- Latest compiled and minified JavaScript -->
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
|
||||
<script src="../../../master/_javascripts/bootstrap-offcanvas.js" type="text/javascript"></script>
|
||||
<script type="text/javascript">
|
||||
/*<![CDATA[*/
|
||||
$(document).ready(function() {
|
||||
$("[id^='topicGroup']").on('show.bs.collapse', function (event) {
|
||||
if (!($(event.target).attr('id').match(/^topicSubGroup/))) {
|
||||
$(this).parent().find("[id^='tgSpan']").toggleClass("fa-angle-right fa-angle-down");
|
||||
}
|
||||
});
|
||||
$("[id^='topicGroup']").on('hide.bs.collapse', function (event) {
|
||||
if (!($(event.target).attr('id').match(/^topicSubGroup/))) {
|
||||
$(this).parent().find("[id^='tgSpan']").toggleClass("fa-angle-right fa-angle-down");
|
||||
}
|
||||
});
|
||||
$("[id^='topicSubGroup']").on('show.bs.collapse', function () {
|
||||
$(this).parent().find("[id^='sgSpan']").toggleClass("fa-caret-right fa-caret-down");
|
||||
});
|
||||
$("[id^='topicSubGroup']").on('hide.bs.collapse', function () {
|
||||
$(this).parent().find("[id^='sgSpan']").toggleClass("fa-caret-right fa-caret-down");
|
||||
});
|
||||
});
|
||||
/*]]>*/
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -1,273 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta content="IE=edge" http-equiv="X-UA-Compatible">
|
||||
<meta content="width=device-width, initial-scale=1.0" name="viewport">
|
||||
<title>Defensive Coding Guide | Defensive Coding Guide | Programming Languages | The Vala Programming Language</title>
|
||||
|
||||
<!-- Bootstrap -->
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap-theme.min.css">
|
||||
|
||||
<!-- Overpass Font -->
|
||||
<link rel="stylesheet" href="https://overpass-30e2.kxcdn.com/overpass.css">
|
||||
|
||||
<link href="../../../master/_stylesheets/asciibinder.css" rel="stylesheet" />
|
||||
|
||||
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
|
||||
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
|
||||
<!--[if lt IE 9]>
|
||||
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
|
||||
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
|
||||
<![endif]-->
|
||||
|
||||
<link href="../../../master/_images/favicon32x32.png" rel="shortcut icon" type="text/css">
|
||||
<!--[if IE]><link rel="shortcut icon" href="../../../master/_images/favicon.ico"><![endif]-->
|
||||
<meta content="AsciiBinder" name="application-name">
|
||||
</head>
|
||||
<body>
|
||||
<div class="navbar navbar-default" role="navigation">
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-header">
|
||||
<a class="navbar-brand" href="https://docs.fedoraproject.org/"><img alt="Fedora Documentation" src="../../../master/_images/fedora.svg"></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container">
|
||||
<p class="toggle-nav visible-xs pull-left">
|
||||
<button class="btn btn-default btn-sm" type="button" data-toggle="offcanvas">Toggle nav</button>
|
||||
</p>
|
||||
<ol class="breadcrumb">
|
||||
<li class="sitename">
|
||||
<a href="../../../index.html">Home</a>
|
||||
</li>
|
||||
<li class="hidden-xs active">
|
||||
<a href="../../en-US/index.html">Defensive Coding Guide </a>
|
||||
</li>
|
||||
<li class="hidden-xs active">
|
||||
<a href="../../en-US/index.html">Defensive Coding Guide</a>
|
||||
</li>
|
||||
<li class="hidden-xs active"><a href="../../en-US/programming-languages/C.html">Programming Languages</a></li>
|
||||
<li class="hidden-xs active">
|
||||
The Vala Programming Language
|
||||
</li>
|
||||
</ol>
|
||||
<div class="row row-offcanvas row-offcanvas-left">
|
||||
<div class="col-xs-8 col-sm-3 col-md-3 sidebar sidebar-offcanvas">
|
||||
<ul class="nav nav-sidebar">
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicGroup0">
|
||||
<span id="tgSpan0" class="fa fa-angle-down"></span>Defensive Coding Guide
|
||||
</a>
|
||||
<ul id="topicGroup0" class="collapse in list-unstyled">
|
||||
<li><a class="" href="../../en-US/index.html">Book Information</a></li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-1">
|
||||
<span id="sgSpan-0-1" class="fa fa-caret-down"></span> Programming Languages
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-1" class="nav-tertiary list-unstyled collapse in">
|
||||
<li><a class="" href="../../en-US/programming-languages/C.html">The C Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/CXX.html">The C++ Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Java.html">The Java Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Python.html">The Python Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Shell.html">Shell Programming and bash</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Go.html">The Go Programming Language</a></li>
|
||||
<li><a class=" active" href="../../en-US/programming-languages/Vala.html">The Vala Programming Language</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-2">
|
||||
<span id="sgSpan-0-2" class="fa fa-caret-right"></span> Specific Programming Tasks
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-2" class="nav-tertiary list-unstyled collapse">
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Library_Design.html">Library Design</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Descriptors.html">File Descriptor Management</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-File_System.html">File System Manipulation</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Temporary_Files.html">Temporary Files</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Processes.html">Processes</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Serialization.html">Serialization and Deserialization</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Cryptography.html">Cryptography</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Packaging.html">RPM Packaging</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-3">
|
||||
<span id="sgSpan-0-3" class="fa fa-caret-right"></span> Implementing Security Features
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-3" class="nav-tertiary list-unstyled collapse">
|
||||
<li><a class="" href="../../en-US/features/Features-Authentication.html">Authentication and Authorization</a></li>
|
||||
<li><a class="" href="../../en-US/features/Features-TLS.html">Transport Layer Security (TLS)</a></li>
|
||||
<li><a class="" href="../../en-US/features/Features-HSM.html">Hardware Security Modules and Smart Cards</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="" href="../../en-US/Revision_History.html">Revision History</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-9 col-md-9 main">
|
||||
<div class="page-header">
|
||||
<h2>The Vala Programming Language</h2>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Vala is a programming language mainly targeted at GNOME developers.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Its syntax is inspired by C# (and thus, indirectly, by Java). But
|
||||
unlike C# and Java, Vala does not attempt to provide memory safety:
|
||||
Vala is compiled to C, and the C code is compiled with GCC using
|
||||
typical compiler flags. Basic operations like integer arithmetic
|
||||
are directly mapped to C constructs. As a results, the
|
||||
recommendations in <a href="#chap-Defensive_Coding-C">[chap-Defensive_Coding-C]</a> apply.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>In particular, the following Vala language constructs can result in
|
||||
undefined behavior at run time:</p>
|
||||
</div>
|
||||
<div class="ulist">
|
||||
<ul>
|
||||
<li>
|
||||
<p>Integer arithmetic, as described in <a href="#sect-Defensive_Coding-C-Arithmetic">[sect-Defensive_Coding-C-Arithmetic]</a>.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Pointer arithmetic, string subscripting and the
|
||||
<code>substring</code> method on strings (the
|
||||
<code>string</code> class in the
|
||||
<code>glib-2.0</code> package) are not range-checked. It
|
||||
is the responsibility of the calling code to ensure that the
|
||||
arguments being passed are valid. This applies even to cases
|
||||
(like <code>substring</code>) where the implementation
|
||||
would have range information to check the validity of indexes.
|
||||
See <a href="#sect-Defensive_Coding-C-Pointers">[sect-Defensive_Coding-C-Pointers]</a>.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Similarly, Vala only performs garbage collection (through
|
||||
reference counting) for <code>GObject</code> 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 <a href="#sect-Defensive_Coding-C-Use-After-Free">[sect-Defensive_Coding-C-Use-After-Free]</a>).</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="bottom" class="text-muted py-3" >
|
||||
<div class="foot">
|
||||
<div class="container">
|
||||
<div class="row footerlinks">
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">About</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Overview">About Fedora</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/sponsors">Sponsors</a></dd>
|
||||
<dd><a href="https://fedoramagazine.org">Fedora Magazine</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Legal:Main#Legal">Legal</a></dd>
|
||||
</dl>
|
||||
<ul class="list-inline">
|
||||
<li>
|
||||
<a href="https://www.facebook.com/TheFedoraProject" class="btn-social btn-outline"><i class="fa fa-fw fa-facebook"></i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://plus.google.com/112917221531140868607" class="btn-social btn-outline"><i class="fa fa-fw fa-google-plus"></i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://twitter.com/fedora" class="btn-social btn-outline"><i class="fa fa-fw fa-twitter"></i></a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title uppercase">Download</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://getfedora.org/en/workstation/download">Get Fedora Workstation</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/server/download">Get Fedora Server</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/atomic/download">Get Fedora Atomic</a></dd>
|
||||
<dd><a href="https://spins.fedoraproject.org">Fedora Spins</a></dd>
|
||||
<dd><a href="https://labs.fedoraproject.org">Fedora Labs</a></dd>
|
||||
<dd><a href="https://arm.fedoraproject.org">Fedora ARM<span class="sup">®</span></a></dd>
|
||||
<dd><a href="https://alt.fedoraproject.org/">Alternative Downloads</a></dd>
|
||||
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">Support</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Communicating_and_getting_help">Get Help</a></dd>
|
||||
<dd><a href="https://ask.fedoraproject.org/">Ask Fedora</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Common_F27_bugs">Common Bugs</a></dd>
|
||||
<dd><a href="https://developer.fedoraproject.org/">Fedora Developer Portal</a></dd>
|
||||
<dd><a href="https://docs.fedoraproject.org/f27/install-guide/index.html">Installation Guide</a></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">Join</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Join">Join Fedora</a></dd>
|
||||
<dd><a href="http://fedoraplanet.org">Planet Fedora</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/SIGs">Fedora SIGs</a></dd>
|
||||
<dd><a href="https://admin.fedoraproject.org/accounts/">Fedora Account System</a></dd>
|
||||
<dd><a href="https://fedoracommunity.org/">Fedora Community</a></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- /row of widgets -->
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-2">
|
||||
<div class="widget-body">
|
||||
<a href="https://www.redhat.com/"><img class="rh-logo" src="../../../master/_images/redhat-logo.png" alt="Red Hat Logo" /></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-7">
|
||||
<div class="widget-body">
|
||||
<p class="sponsor">Fedora is sponsored by Red Hat.</p>
|
||||
<p class="sponsor"><a href="https://www.redhat.com/en/technologies/linux-platforms/articles/relationship-between-fedora-and-rhel">Learn more about the relationship between Red Hat and Fedora »</a></p>
|
||||
<p class="copy">© 2017 Red Hat, Inc. and others. Please send any comments or corrections to the <a href="https://pagure.io/fedora-docs/docs-fp-o">documentation team</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- /row of widgets -->
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
|
||||
<!-- Latest compiled and minified JavaScript -->
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
|
||||
<script src="../../../master/_javascripts/bootstrap-offcanvas.js" type="text/javascript"></script>
|
||||
<script type="text/javascript">
|
||||
/*<![CDATA[*/
|
||||
$(document).ready(function() {
|
||||
$("[id^='topicGroup']").on('show.bs.collapse', function (event) {
|
||||
if (!($(event.target).attr('id').match(/^topicSubGroup/))) {
|
||||
$(this).parent().find("[id^='tgSpan']").toggleClass("fa-angle-right fa-angle-down");
|
||||
}
|
||||
});
|
||||
$("[id^='topicGroup']").on('hide.bs.collapse', function (event) {
|
||||
if (!($(event.target).attr('id').match(/^topicSubGroup/))) {
|
||||
$(this).parent().find("[id^='tgSpan']").toggleClass("fa-angle-right fa-angle-down");
|
||||
}
|
||||
});
|
||||
$("[id^='topicSubGroup']").on('show.bs.collapse', function () {
|
||||
$(this).parent().find("[id^='sgSpan']").toggleClass("fa-caret-right fa-caret-down");
|
||||
});
|
||||
$("[id^='topicSubGroup']").on('hide.bs.collapse', function () {
|
||||
$(this).parent().find("[id^='sgSpan']").toggleClass("fa-caret-right fa-caret-down");
|
||||
});
|
||||
});
|
||||
/*]]>*/
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -1,428 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta content="IE=edge" http-equiv="X-UA-Compatible">
|
||||
<meta content="width=device-width, initial-scale=1.0" name="viewport">
|
||||
<title>Defensive Coding Guide | Defensive Coding Guide | Specific Programming Tasks | Cryptography</title>
|
||||
|
||||
<!-- Bootstrap -->
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap-theme.min.css">
|
||||
|
||||
<!-- Overpass Font -->
|
||||
<link rel="stylesheet" href="https://overpass-30e2.kxcdn.com/overpass.css">
|
||||
|
||||
<link href="../../../master/_stylesheets/asciibinder.css" rel="stylesheet" />
|
||||
|
||||
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
|
||||
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
|
||||
<!--[if lt IE 9]>
|
||||
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
|
||||
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
|
||||
<![endif]-->
|
||||
|
||||
<link href="../../../master/_images/favicon32x32.png" rel="shortcut icon" type="text/css">
|
||||
<!--[if IE]><link rel="shortcut icon" href="../../../master/_images/favicon.ico"><![endif]-->
|
||||
<meta content="AsciiBinder" name="application-name">
|
||||
</head>
|
||||
<body>
|
||||
<div class="navbar navbar-default" role="navigation">
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-header">
|
||||
<a class="navbar-brand" href="https://docs.fedoraproject.org/"><img alt="Fedora Documentation" src="../../../master/_images/fedora.svg"></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container">
|
||||
<p class="toggle-nav visible-xs pull-left">
|
||||
<button class="btn btn-default btn-sm" type="button" data-toggle="offcanvas">Toggle nav</button>
|
||||
</p>
|
||||
<ol class="breadcrumb">
|
||||
<li class="sitename">
|
||||
<a href="../../../index.html">Home</a>
|
||||
</li>
|
||||
<li class="hidden-xs active">
|
||||
<a href="../../en-US/index.html">Defensive Coding Guide </a>
|
||||
</li>
|
||||
<li class="hidden-xs active">
|
||||
<a href="../../en-US/index.html">Defensive Coding Guide</a>
|
||||
</li>
|
||||
<li class="hidden-xs active"><a href="../../en-US/tasks/Tasks-Library_Design.html">Specific Programming Tasks</a></li>
|
||||
<li class="hidden-xs active">
|
||||
Cryptography
|
||||
</li>
|
||||
</ol>
|
||||
<div class="row row-offcanvas row-offcanvas-left">
|
||||
<div class="col-xs-8 col-sm-3 col-md-3 sidebar sidebar-offcanvas">
|
||||
<ul class="nav nav-sidebar">
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicGroup0">
|
||||
<span id="tgSpan0" class="fa fa-angle-down"></span>Defensive Coding Guide
|
||||
</a>
|
||||
<ul id="topicGroup0" class="collapse in list-unstyled">
|
||||
<li><a class="" href="../../en-US/index.html">Book Information</a></li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-1">
|
||||
<span id="sgSpan-0-1" class="fa fa-caret-right"></span> Programming Languages
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-1" class="nav-tertiary list-unstyled collapse">
|
||||
<li><a class="" href="../../en-US/programming-languages/C.html">The C Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/CXX.html">The C++ Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Java.html">The Java Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Python.html">The Python Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Shell.html">Shell Programming and bash</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Go.html">The Go Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Vala.html">The Vala Programming Language</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-2">
|
||||
<span id="sgSpan-0-2" class="fa fa-caret-down"></span> Specific Programming Tasks
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-2" class="nav-tertiary list-unstyled collapse in">
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Library_Design.html">Library Design</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Descriptors.html">File Descriptor Management</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-File_System.html">File System Manipulation</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Temporary_Files.html">Temporary Files</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Processes.html">Processes</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Serialization.html">Serialization and Deserialization</a></li>
|
||||
<li><a class=" active" href="../../en-US/tasks/Tasks-Cryptography.html">Cryptography</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Packaging.html">RPM Packaging</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-3">
|
||||
<span id="sgSpan-0-3" class="fa fa-caret-right"></span> Implementing Security Features
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-3" class="nav-tertiary list-unstyled collapse">
|
||||
<li><a class="" href="../../en-US/features/Features-Authentication.html">Authentication and Authorization</a></li>
|
||||
<li><a class="" href="../../en-US/features/Features-TLS.html">Transport Layer Security (TLS)</a></li>
|
||||
<li><a class="" href="../../en-US/features/Features-HSM.html">Hardware Security Modules and Smart Cards</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="" href="../../en-US/Revision_History.html">Revision History</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-9 col-md-9 main">
|
||||
<div class="page-header">
|
||||
<h2>Cryptography</h2>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="primitives"><a class="anchor" href="#primitives"></a>Primitives</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>Choosing from the following cryptographic primitives is
|
||||
recommended:</p>
|
||||
</div>
|
||||
<div class="ulist">
|
||||
<ul>
|
||||
<li>
|
||||
<p>RSA with 2048-bit keys and OAEP or PSS
|
||||
padding</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>AES-128 in CBC mode</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>AES-128 in GCM mode</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>AES-256 in CBC mode</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>AES-256 in GCM mode</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>SHA-256</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>HMAC-SHA-256</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>HMAC-SHA-1</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Other cryptographic algorithms can be used if they are required
|
||||
for interoperability with existing software:</p>
|
||||
</div>
|
||||
<div class="ulist">
|
||||
<ul>
|
||||
<li>
|
||||
<p>RSA with key sizes larger than 1024
|
||||
and legacy padding</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>AES-192</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>3DES (triple DES, with two or three 56-bit keys),
|
||||
but strongly discouraged</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>RC4 (but very, very strongly discouraged)</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>SHA-1</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>HMAC-MD5</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="admonitionblock important">
|
||||
<table>
|
||||
<tr>
|
||||
<td class="icon">
|
||||
<i class="fa icon-important" title="Important"></i>
|
||||
</td>
|
||||
<td class="content">
|
||||
<div class="title">Important</div>
|
||||
<div class="paragraph">
|
||||
<p>These primitives are difficult to use in a secure way. Custom
|
||||
implementation of security protocols should be avoided. For
|
||||
protecting confidentiality and integrity of network
|
||||
transmissions, TLS should be used (<a href="#chap-Defensive_Coding-TLS">[chap-Defensive_Coding-TLS]</a>).</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>In particular, when using AES in CBC mode, it is necessary to
|
||||
add integrity checking by other means, preferably using
|
||||
HMAC-SHA-256 and <strong>after</strong> encryption (that
|
||||
is, on the encrypted cipher text). For AES in GCM mode,
|
||||
correct construction of nonces is absolutely essential.</p>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="randomness"><a class="anchor" href="#randomness"></a>Randomness</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>The following facilities can be used to generate unpredictable
|
||||
and non-repeating values. When these functions are used without
|
||||
special safeguards, each individual random value should be at
|
||||
least 12 bytes long.</p>
|
||||
</div>
|
||||
<div class="ulist">
|
||||
<ul>
|
||||
<li>
|
||||
<p><code>PK11_GenerateRandom</code> in the NSS library
|
||||
(usable for high data rates)</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><code>RAND_bytes</code> in the OpenSSL library
|
||||
(usable for high data rates)</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><code>gnutls_rnd</code> in GNUTLS, with
|
||||
<code>GNUTLS_RND_RANDOM</code> as the first argument
|
||||
(usable for high data rates)</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><code>java.security.SecureRandom</code> in Java
|
||||
(usable for high data rates)</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><code>os.urandom</code> in Python</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>The <code>getrandom</code> system call since glibc 2.25</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>The <code>getentropy</code> call since glibc 2.25</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Reading from the <code>/dev/urandom</code>
|
||||
character device</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>All these functions should be non-blocking, and they should not
|
||||
wait until physical randomness becomes available. (Some
|
||||
cryptography providers for Java can cause
|
||||
<code>java.security.SecureRandom</code> to block, however.)
|
||||
Those functions which do not obtain all bits directly from
|
||||
<code>/dev/urandom</code> are suitable for high data
|
||||
rates because they do not deplete the system-wide entropy pool.</p>
|
||||
</div>
|
||||
<div class="admonitionblock important">
|
||||
<table>
|
||||
<tr>
|
||||
<td class="icon">
|
||||
<i class="fa icon-important" title="Important"></i>
|
||||
</td>
|
||||
<td class="content">
|
||||
<div class="title">Difficult to use API</div>
|
||||
<div class="paragraph">
|
||||
<p>Both <code>RAND_bytes</code> and
|
||||
<code>PK11_GenerateRandom</code> have three-state
|
||||
return values (with conflicting meanings). Careful error
|
||||
checking is required. Please review the documentation when
|
||||
using these functions.</p>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div class="admonitionblock important">
|
||||
<table>
|
||||
<tr>
|
||||
<td class="icon">
|
||||
<i class="fa icon-important" title="Important"></i>
|
||||
</td>
|
||||
<td class="content">
|
||||
<div class="title">Difficult to use API</div>
|
||||
<div class="paragraph">
|
||||
<p>The <code>getrandom</code> system call has three-state
|
||||
return values, hence requires careful error checking.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>It was introduced in Linux kernel 3.17, but before glibc 2.25 no API wrappers were
|
||||
provided. As such one could only use it via the syscall interface
|
||||
as <code>syscall(SYS_getrandom, (void*)dest, (size_t)size, (unsigned int)0)</code>.
|
||||
For portable code targetting multiple kernel versions one has to check
|
||||
for the function beingavailable on run-time, and switch to another
|
||||
facility if the running kernel does not support this call.</p>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Other sources of randomness should be considered predictable.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Generating randomness for cryptographic keys in long-term use
|
||||
may need different steps and is best left to cryptographic
|
||||
libraries.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="bottom" class="text-muted py-3" >
|
||||
<div class="foot">
|
||||
<div class="container">
|
||||
<div class="row footerlinks">
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">About</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Overview">About Fedora</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/sponsors">Sponsors</a></dd>
|
||||
<dd><a href="https://fedoramagazine.org">Fedora Magazine</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Legal:Main#Legal">Legal</a></dd>
|
||||
</dl>
|
||||
<ul class="list-inline">
|
||||
<li>
|
||||
<a href="https://www.facebook.com/TheFedoraProject" class="btn-social btn-outline"><i class="fa fa-fw fa-facebook"></i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://plus.google.com/112917221531140868607" class="btn-social btn-outline"><i class="fa fa-fw fa-google-plus"></i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://twitter.com/fedora" class="btn-social btn-outline"><i class="fa fa-fw fa-twitter"></i></a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title uppercase">Download</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://getfedora.org/en/workstation/download">Get Fedora Workstation</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/server/download">Get Fedora Server</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/atomic/download">Get Fedora Atomic</a></dd>
|
||||
<dd><a href="https://spins.fedoraproject.org">Fedora Spins</a></dd>
|
||||
<dd><a href="https://labs.fedoraproject.org">Fedora Labs</a></dd>
|
||||
<dd><a href="https://arm.fedoraproject.org">Fedora ARM<span class="sup">®</span></a></dd>
|
||||
<dd><a href="https://alt.fedoraproject.org/">Alternative Downloads</a></dd>
|
||||
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">Support</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Communicating_and_getting_help">Get Help</a></dd>
|
||||
<dd><a href="https://ask.fedoraproject.org/">Ask Fedora</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Common_F27_bugs">Common Bugs</a></dd>
|
||||
<dd><a href="https://developer.fedoraproject.org/">Fedora Developer Portal</a></dd>
|
||||
<dd><a href="https://docs.fedoraproject.org/f27/install-guide/index.html">Installation Guide</a></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">Join</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Join">Join Fedora</a></dd>
|
||||
<dd><a href="http://fedoraplanet.org">Planet Fedora</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/SIGs">Fedora SIGs</a></dd>
|
||||
<dd><a href="https://admin.fedoraproject.org/accounts/">Fedora Account System</a></dd>
|
||||
<dd><a href="https://fedoracommunity.org/">Fedora Community</a></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- /row of widgets -->
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-2">
|
||||
<div class="widget-body">
|
||||
<a href="https://www.redhat.com/"><img class="rh-logo" src="../../../master/_images/redhat-logo.png" alt="Red Hat Logo" /></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-7">
|
||||
<div class="widget-body">
|
||||
<p class="sponsor">Fedora is sponsored by Red Hat.</p>
|
||||
<p class="sponsor"><a href="https://www.redhat.com/en/technologies/linux-platforms/articles/relationship-between-fedora-and-rhel">Learn more about the relationship between Red Hat and Fedora »</a></p>
|
||||
<p class="copy">© 2017 Red Hat, Inc. and others. Please send any comments or corrections to the <a href="https://pagure.io/fedora-docs/docs-fp-o">documentation team</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- /row of widgets -->
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
|
||||
<!-- Latest compiled and minified JavaScript -->
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
|
||||
<script src="../../../master/_javascripts/bootstrap-offcanvas.js" type="text/javascript"></script>
|
||||
<script type="text/javascript">
|
||||
/*<![CDATA[*/
|
||||
$(document).ready(function() {
|
||||
$("[id^='topicGroup']").on('show.bs.collapse', function (event) {
|
||||
if (!($(event.target).attr('id').match(/^topicSubGroup/))) {
|
||||
$(this).parent().find("[id^='tgSpan']").toggleClass("fa-angle-right fa-angle-down");
|
||||
}
|
||||
});
|
||||
$("[id^='topicGroup']").on('hide.bs.collapse', function (event) {
|
||||
if (!($(event.target).attr('id').match(/^topicSubGroup/))) {
|
||||
$(this).parent().find("[id^='tgSpan']").toggleClass("fa-angle-right fa-angle-down");
|
||||
}
|
||||
});
|
||||
$("[id^='topicSubGroup']").on('show.bs.collapse', function () {
|
||||
$(this).parent().find("[id^='sgSpan']").toggleClass("fa-caret-right fa-caret-down");
|
||||
});
|
||||
$("[id^='topicSubGroup']").on('hide.bs.collapse', function () {
|
||||
$(this).parent().find("[id^='sgSpan']").toggleClass("fa-caret-right fa-caret-down");
|
||||
});
|
||||
});
|
||||
/*]]>*/
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -1,497 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta content="IE=edge" http-equiv="X-UA-Compatible">
|
||||
<meta content="width=device-width, initial-scale=1.0" name="viewport">
|
||||
<title>Defensive Coding Guide | Defensive Coding Guide | Specific Programming Tasks | File Descriptor Management</title>
|
||||
|
||||
<!-- Bootstrap -->
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap-theme.min.css">
|
||||
|
||||
<!-- Overpass Font -->
|
||||
<link rel="stylesheet" href="https://overpass-30e2.kxcdn.com/overpass.css">
|
||||
|
||||
<link href="../../../master/_stylesheets/asciibinder.css" rel="stylesheet" />
|
||||
|
||||
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
|
||||
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
|
||||
<!--[if lt IE 9]>
|
||||
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
|
||||
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
|
||||
<![endif]-->
|
||||
|
||||
<link href="../../../master/_images/favicon32x32.png" rel="shortcut icon" type="text/css">
|
||||
<!--[if IE]><link rel="shortcut icon" href="../../../master/_images/favicon.ico"><![endif]-->
|
||||
<meta content="AsciiBinder" name="application-name">
|
||||
</head>
|
||||
<body>
|
||||
<div class="navbar navbar-default" role="navigation">
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-header">
|
||||
<a class="navbar-brand" href="https://docs.fedoraproject.org/"><img alt="Fedora Documentation" src="../../../master/_images/fedora.svg"></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container">
|
||||
<p class="toggle-nav visible-xs pull-left">
|
||||
<button class="btn btn-default btn-sm" type="button" data-toggle="offcanvas">Toggle nav</button>
|
||||
</p>
|
||||
<ol class="breadcrumb">
|
||||
<li class="sitename">
|
||||
<a href="../../../index.html">Home</a>
|
||||
</li>
|
||||
<li class="hidden-xs active">
|
||||
<a href="../../en-US/index.html">Defensive Coding Guide </a>
|
||||
</li>
|
||||
<li class="hidden-xs active">
|
||||
<a href="../../en-US/index.html">Defensive Coding Guide</a>
|
||||
</li>
|
||||
<li class="hidden-xs active"><a href="../../en-US/tasks/Tasks-Library_Design.html">Specific Programming Tasks</a></li>
|
||||
<li class="hidden-xs active">
|
||||
File Descriptor Management
|
||||
</li>
|
||||
</ol>
|
||||
<div class="row row-offcanvas row-offcanvas-left">
|
||||
<div class="col-xs-8 col-sm-3 col-md-3 sidebar sidebar-offcanvas">
|
||||
<ul class="nav nav-sidebar">
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicGroup0">
|
||||
<span id="tgSpan0" class="fa fa-angle-down"></span>Defensive Coding Guide
|
||||
</a>
|
||||
<ul id="topicGroup0" class="collapse in list-unstyled">
|
||||
<li><a class="" href="../../en-US/index.html">Book Information</a></li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-1">
|
||||
<span id="sgSpan-0-1" class="fa fa-caret-right"></span> Programming Languages
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-1" class="nav-tertiary list-unstyled collapse">
|
||||
<li><a class="" href="../../en-US/programming-languages/C.html">The C Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/CXX.html">The C++ Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Java.html">The Java Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Python.html">The Python Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Shell.html">Shell Programming and bash</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Go.html">The Go Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Vala.html">The Vala Programming Language</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-2">
|
||||
<span id="sgSpan-0-2" class="fa fa-caret-down"></span> Specific Programming Tasks
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-2" class="nav-tertiary list-unstyled collapse in">
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Library_Design.html">Library Design</a></li>
|
||||
<li><a class=" active" href="../../en-US/tasks/Tasks-Descriptors.html">File Descriptor Management</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-File_System.html">File System Manipulation</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Temporary_Files.html">Temporary Files</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Processes.html">Processes</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Serialization.html">Serialization and Deserialization</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Cryptography.html">Cryptography</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Packaging.html">RPM Packaging</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-3">
|
||||
<span id="sgSpan-0-3" class="fa fa-caret-right"></span> Implementing Security Features
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-3" class="nav-tertiary list-unstyled collapse">
|
||||
<li><a class="" href="../../en-US/features/Features-Authentication.html">Authentication and Authorization</a></li>
|
||||
<li><a class="" href="../../en-US/features/Features-TLS.html">Transport Layer Security (TLS)</a></li>
|
||||
<li><a class="" href="../../en-US/features/Features-HSM.html">Hardware Security Modules and Smart Cards</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="" href="../../en-US/Revision_History.html">Revision History</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-9 col-md-9 main">
|
||||
<div class="page-header">
|
||||
<h2>File Descriptor Management</h2>
|
||||
</div>
|
||||
<div id="preamble">
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>File descriptors underlie all input/output mechanisms offered by
|
||||
the system. They are used to implementation the <code>FILE
|
||||
*</code>-based functions found in
|
||||
<code><stdio.h></code>, and all the file and network
|
||||
communication facilities provided by the Python and Java
|
||||
environments are eventually implemented in them.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>File descriptors are small, non-negative integers in userspace,
|
||||
and are backed on the kernel side with complicated data structures
|
||||
which can sometimes grow very large.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="closing-descriptors"><a class="anchor" href="#closing-descriptors"></a>Closing Descriptors</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>If a descriptor is no longer used by a program and is not closed
|
||||
explicitly, its number cannot be reused (which is problematic in
|
||||
itself, see <a href="#sect-Defensive_Coding-Tasks-Descriptors-Limit">Dealing with the <code>select</code> Limit</a>), and
|
||||
the kernel resources are not freed. Therefore, it is important
|
||||
to close all descriptors at the earliest point in time
|
||||
possible, but not earlier.</p>
|
||||
</div>
|
||||
<div class="sect2">
|
||||
<h3 id="error-handling-during-descriptor-close"><a class="anchor" href="#error-handling-during-descriptor-close"></a>Error Handling during Descriptor Close</h3>
|
||||
<div class="paragraph">
|
||||
<p>The <code>close</code> system call is always
|
||||
successful in the sense that the passed file descriptor is
|
||||
never valid after the function has been called. However,
|
||||
<code>close</code> still can return an error, for
|
||||
example if there was a file system failure. But this error is
|
||||
not very useful because the absence of an error does not mean
|
||||
that all caches have been emptied and previous writes have
|
||||
been made durable. Programs which need such guarantees must
|
||||
open files with <code>O_SYNC</code> or use
|
||||
<code>fsync</code> or <code>fdatasync</code>, and
|
||||
may also have to <code>fsync</code> the directory
|
||||
containing the file.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect2">
|
||||
<h3 id="closing-descriptors-and-race-conditions"><a class="anchor" href="#closing-descriptors-and-race-conditions"></a>Closing Descriptors and Race Conditions</h3>
|
||||
<div class="paragraph">
|
||||
<p>Unlike process IDs, which are recycle only gradually, the
|
||||
kernel always allocates the lowest unused file descriptor when
|
||||
a new descriptor is created. This means that in a
|
||||
multi-threaded program which constantly opens and closes file
|
||||
descriptors, descriptors are reused very quickly. Unless
|
||||
descriptor closing and other operations on the same file
|
||||
descriptor are synchronized (typically, using a mutex), there
|
||||
will be race conditons and I/O operations will be applied to
|
||||
the wrong file descriptor.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Sometimes, it is necessary to close a file descriptor
|
||||
concurrently, while another thread might be about to use it in
|
||||
a system call. In order to support this, a program needs to
|
||||
create a single special file descriptor, one on which all I/O
|
||||
operations fail. One way to achieve this is to use
|
||||
<code>socketpair</code>, close one of the descriptors,
|
||||
and call <code>shutdown(fd, SHUTRDWR)</code> on the
|
||||
other.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>When a descriptor is closed concurrently, the program does not
|
||||
call <code>close</code> on the descriptor. Instead it
|
||||
program uses <code>dup2</code> to replace the
|
||||
descriptor to be closed with the dummy descriptor created
|
||||
earlier. This way, the kernel will not reuse the descriptor,
|
||||
but it will carry out all other steps associated with calling
|
||||
a descriptor (for instance, if the descriptor refers to a
|
||||
stream socket, the peer will be notified).</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>This is just a sketch, and many details are missing.
|
||||
Additional data structures are needed to determine when it is
|
||||
safe to really close the descriptor, and proper locking is
|
||||
required for that.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect2">
|
||||
<h3 id="lingering-state-after-close"><a class="anchor" href="#lingering-state-after-close"></a>Lingering State after Close</h3>
|
||||
<div class="paragraph">
|
||||
<p>By default, closing a stream socket returns immediately, and
|
||||
the kernel will try to send the data in the background. This
|
||||
means that it is impossible to implement accurate accounting
|
||||
of network-related resource utilization from userspace.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>The <code>SO_LINGER</code> socket option alters the
|
||||
behavior of <code>close</code>, so that it will return
|
||||
only after the lingering data has been processed, either by
|
||||
sending it to the peer successfully, or by discarding it after
|
||||
the configured timeout. However, there is no interface which
|
||||
could perform this operation in the background, so a separate
|
||||
userspace thread is needed for each <code>close</code>
|
||||
call, causing scalability issues.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Currently, there is no application-level countermeasure which
|
||||
applies universally. Mitigation is possible with
|
||||
<strong class="application">iptables</strong> (the
|
||||
<code>connlimit</code> match type in particular) and
|
||||
specialized filtering devices for denial-of-service network
|
||||
traffic.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>These problems are not related to the
|
||||
<code>TIME_WAIT</code> state commonly seen in
|
||||
<strong class="application">netstat</strong> output. The kernel
|
||||
automatically expires such sockets if necessary.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="sect-Defensive_Coding-Tasks-Descriptors-Child_Processes"><a class="anchor" href="#sect-Defensive_Coding-Tasks-Descriptors-Child_Processes"></a>Preventing File Descriptor Leaks to Child Processes</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>Child processes created with <code>fork</code> share
|
||||
the initial set of file descriptors with their parent
|
||||
process. By default, file descriptors are also preserved if
|
||||
a new process image is created with <code>execve</code>
|
||||
(or any of the other functions such as <code>system</code>
|
||||
or <code>posix_spawn</code>).</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Usually, this behavior is not desirable. There are two ways to
|
||||
turn it off, that is, to prevent new process images from
|
||||
inheriting the file descriptors in the parent process:</p>
|
||||
</div>
|
||||
<div class="ulist">
|
||||
<ul>
|
||||
<li>
|
||||
<p>Set the close-on-exec flag on all newly created file
|
||||
descriptors. Traditionally, this flag is controlled by the
|
||||
<code>FD_CLOEXEC</code> flag, using
|
||||
<code>F_GETFD</code> and <code>F_SETFD</code>
|
||||
operations of the <code>fcntl</code> function.</p>
|
||||
<div class="paragraph">
|
||||
<p>However, in a multi-threaded process, there is a race
|
||||
condition: a subprocess could have been created between the
|
||||
time the descriptor was created and the
|
||||
<code>FD_CLOEXEC</code> was set. Therefore, many system
|
||||
calls which create descriptors (such as
|
||||
<code>open</code> and <code>openat</code>)
|
||||
now accept the <code>O_CLOEXEC</code> flag
|
||||
(<code>SOCK_CLOEXEC</code> for
|
||||
<code>socket</code> and
|
||||
<code>socketpair</code>), which cause the
|
||||
<code>FD_CLOEXEC</code> flag to be set for the file
|
||||
descriptor in an atomic fashion. In addition, a few new
|
||||
systems calls were introduced, such as
|
||||
<code>pipe2</code> and <code>dup3</code>.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>The downside of this approach is that every descriptor needs
|
||||
to receive special treatment at the time of creation,
|
||||
otherwise it is not completely effective.</p>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<p>After calling <code>fork</code>, but before creating
|
||||
a new process image with <code>execve</code>, all
|
||||
file descriptors which the child process will not need are
|
||||
closed.</p>
|
||||
<div class="paragraph">
|
||||
<p>Traditionally, this was implemented as a loop over file
|
||||
descriptors ranging from <code>3</code> to
|
||||
<code>255</code> and later <code>1023</code>.
|
||||
But this is only an approximation because it is possible to
|
||||
create file descriptors outside this range easily (see <a href="#sect-Defensive_Coding-Tasks-Descriptors-Limit">Dealing with the <code>select</code> Limit</a>).
|
||||
Another approach reads <code>/proc/self/fd</code>
|
||||
and closes the unexpected descriptors listed there, but this
|
||||
approach is much slower.</p>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>At present, environments which care about file descriptor
|
||||
leakage implement the second approach. OpenJDK 6 and 7
|
||||
are among them.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="sect-Defensive_Coding-Tasks-Descriptors-Limit"><a class="anchor" href="#sect-Defensive_Coding-Tasks-Descriptors-Limit"></a>Dealing with the <code>select</code> Limit</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>By default, a user is allowed to open only 1024 files in a
|
||||
single process, but the system administrator can easily change
|
||||
this limit (which is necessary for busy network servers).
|
||||
However, there is another restriction which is more difficult to
|
||||
overcome.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>The <code>select</code> function only supports a
|
||||
maximum of <code>FD_SETSIZE</code> file descriptors
|
||||
(that is, the maximum permitted value for a file descriptor
|
||||
is <code>FD_SETSIZE - 1</code>, usually 1023.) If a
|
||||
process opens many files, descriptors may exceed such
|
||||
limits. It is impossible to query such descriptors using
|
||||
<code>select</code>.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>If a library which creates many file descriptors is used in
|
||||
the same process as a library which uses
|
||||
<code>select</code>, at least one of them needs to
|
||||
be changed.
|
||||
Calls to <code>select</code> can be replaced with
|
||||
calls to <code>poll</code> or another event handling
|
||||
mechanism. Replacing the <code>select</code> function
|
||||
is the recommended approach.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Alternatively, the library with high descriptor usage can
|
||||
relocate descriptors above the <code>FD_SETSIZE</code>
|
||||
limit using the following procedure.</p>
|
||||
</div>
|
||||
<div class="ulist">
|
||||
<ul>
|
||||
<li>
|
||||
<p>Create the file descriptor <code>fd</code> as
|
||||
usual, preferably with the <code>O_CLOEXEC</code>
|
||||
flag.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Before doing anything else with the descriptor
|
||||
<code>fd</code>, invoke:</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="listingblock">
|
||||
<div class="content">
|
||||
<pre> int newfd = fcntl(fd, F_DUPFD_CLOEXEC, (long)FD_SETSIZE);</pre>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ulist">
|
||||
<ul>
|
||||
<li>
|
||||
<p>Check that <code>newfd</code> result is
|
||||
non-negative, otherwise close <code>fd</code> and
|
||||
report an error, and return.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Close <code>fd</code> and continue to use
|
||||
<code>newfd</code>.</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>The new descriptor has been allocated above the
|
||||
<code>FD_SETSIZE</code>. Even though this algorithm
|
||||
is racy in the sense that the <code>FD_SETSIZE</code>
|
||||
first descriptors could fill up, a very high degree of
|
||||
physical parallelism is required before this becomes a problem.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="bottom" class="text-muted py-3" >
|
||||
<div class="foot">
|
||||
<div class="container">
|
||||
<div class="row footerlinks">
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">About</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Overview">About Fedora</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/sponsors">Sponsors</a></dd>
|
||||
<dd><a href="https://fedoramagazine.org">Fedora Magazine</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Legal:Main#Legal">Legal</a></dd>
|
||||
</dl>
|
||||
<ul class="list-inline">
|
||||
<li>
|
||||
<a href="https://www.facebook.com/TheFedoraProject" class="btn-social btn-outline"><i class="fa fa-fw fa-facebook"></i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://plus.google.com/112917221531140868607" class="btn-social btn-outline"><i class="fa fa-fw fa-google-plus"></i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://twitter.com/fedora" class="btn-social btn-outline"><i class="fa fa-fw fa-twitter"></i></a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title uppercase">Download</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://getfedora.org/en/workstation/download">Get Fedora Workstation</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/server/download">Get Fedora Server</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/atomic/download">Get Fedora Atomic</a></dd>
|
||||
<dd><a href="https://spins.fedoraproject.org">Fedora Spins</a></dd>
|
||||
<dd><a href="https://labs.fedoraproject.org">Fedora Labs</a></dd>
|
||||
<dd><a href="https://arm.fedoraproject.org">Fedora ARM<span class="sup">®</span></a></dd>
|
||||
<dd><a href="https://alt.fedoraproject.org/">Alternative Downloads</a></dd>
|
||||
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">Support</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Communicating_and_getting_help">Get Help</a></dd>
|
||||
<dd><a href="https://ask.fedoraproject.org/">Ask Fedora</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Common_F27_bugs">Common Bugs</a></dd>
|
||||
<dd><a href="https://developer.fedoraproject.org/">Fedora Developer Portal</a></dd>
|
||||
<dd><a href="https://docs.fedoraproject.org/f27/install-guide/index.html">Installation Guide</a></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">Join</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Join">Join Fedora</a></dd>
|
||||
<dd><a href="http://fedoraplanet.org">Planet Fedora</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/SIGs">Fedora SIGs</a></dd>
|
||||
<dd><a href="https://admin.fedoraproject.org/accounts/">Fedora Account System</a></dd>
|
||||
<dd><a href="https://fedoracommunity.org/">Fedora Community</a></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- /row of widgets -->
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-2">
|
||||
<div class="widget-body">
|
||||
<a href="https://www.redhat.com/"><img class="rh-logo" src="../../../master/_images/redhat-logo.png" alt="Red Hat Logo" /></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-7">
|
||||
<div class="widget-body">
|
||||
<p class="sponsor">Fedora is sponsored by Red Hat.</p>
|
||||
<p class="sponsor"><a href="https://www.redhat.com/en/technologies/linux-platforms/articles/relationship-between-fedora-and-rhel">Learn more about the relationship between Red Hat and Fedora »</a></p>
|
||||
<p class="copy">© 2017 Red Hat, Inc. and others. Please send any comments or corrections to the <a href="https://pagure.io/fedora-docs/docs-fp-o">documentation team</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- /row of widgets -->
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
|
||||
<!-- Latest compiled and minified JavaScript -->
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
|
||||
<script src="../../../master/_javascripts/bootstrap-offcanvas.js" type="text/javascript"></script>
|
||||
<script type="text/javascript">
|
||||
/*<![CDATA[*/
|
||||
$(document).ready(function() {
|
||||
$("[id^='topicGroup']").on('show.bs.collapse', function (event) {
|
||||
if (!($(event.target).attr('id').match(/^topicSubGroup/))) {
|
||||
$(this).parent().find("[id^='tgSpan']").toggleClass("fa-angle-right fa-angle-down");
|
||||
}
|
||||
});
|
||||
$("[id^='topicGroup']").on('hide.bs.collapse', function (event) {
|
||||
if (!($(event.target).attr('id').match(/^topicSubGroup/))) {
|
||||
$(this).parent().find("[id^='tgSpan']").toggleClass("fa-angle-right fa-angle-down");
|
||||
}
|
||||
});
|
||||
$("[id^='topicSubGroup']").on('show.bs.collapse', function () {
|
||||
$(this).parent().find("[id^='sgSpan']").toggleClass("fa-caret-right fa-caret-down");
|
||||
});
|
||||
$("[id^='topicSubGroup']").on('hide.bs.collapse', function () {
|
||||
$(this).parent().find("[id^='sgSpan']").toggleClass("fa-caret-right fa-caret-down");
|
||||
});
|
||||
});
|
||||
/*]]>*/
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -1,548 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta content="IE=edge" http-equiv="X-UA-Compatible">
|
||||
<meta content="width=device-width, initial-scale=1.0" name="viewport">
|
||||
<title>Defensive Coding Guide | Defensive Coding Guide | Specific Programming Tasks | File System Manipulation</title>
|
||||
|
||||
<!-- Bootstrap -->
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap-theme.min.css">
|
||||
|
||||
<!-- Overpass Font -->
|
||||
<link rel="stylesheet" href="https://overpass-30e2.kxcdn.com/overpass.css">
|
||||
|
||||
<link href="../../../master/_stylesheets/asciibinder.css" rel="stylesheet" />
|
||||
|
||||
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
|
||||
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
|
||||
<!--[if lt IE 9]>
|
||||
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
|
||||
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
|
||||
<![endif]-->
|
||||
|
||||
<link href="../../../master/_images/favicon32x32.png" rel="shortcut icon" type="text/css">
|
||||
<!--[if IE]><link rel="shortcut icon" href="../../../master/_images/favicon.ico"><![endif]-->
|
||||
<meta content="AsciiBinder" name="application-name">
|
||||
</head>
|
||||
<body>
|
||||
<div class="navbar navbar-default" role="navigation">
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-header">
|
||||
<a class="navbar-brand" href="https://docs.fedoraproject.org/"><img alt="Fedora Documentation" src="../../../master/_images/fedora.svg"></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container">
|
||||
<p class="toggle-nav visible-xs pull-left">
|
||||
<button class="btn btn-default btn-sm" type="button" data-toggle="offcanvas">Toggle nav</button>
|
||||
</p>
|
||||
<ol class="breadcrumb">
|
||||
<li class="sitename">
|
||||
<a href="../../../index.html">Home</a>
|
||||
</li>
|
||||
<li class="hidden-xs active">
|
||||
<a href="../../en-US/index.html">Defensive Coding Guide </a>
|
||||
</li>
|
||||
<li class="hidden-xs active">
|
||||
<a href="../../en-US/index.html">Defensive Coding Guide</a>
|
||||
</li>
|
||||
<li class="hidden-xs active"><a href="../../en-US/tasks/Tasks-Library_Design.html">Specific Programming Tasks</a></li>
|
||||
<li class="hidden-xs active">
|
||||
File System Manipulation
|
||||
</li>
|
||||
</ol>
|
||||
<div class="row row-offcanvas row-offcanvas-left">
|
||||
<div class="col-xs-8 col-sm-3 col-md-3 sidebar sidebar-offcanvas">
|
||||
<ul class="nav nav-sidebar">
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicGroup0">
|
||||
<span id="tgSpan0" class="fa fa-angle-down"></span>Defensive Coding Guide
|
||||
</a>
|
||||
<ul id="topicGroup0" class="collapse in list-unstyled">
|
||||
<li><a class="" href="../../en-US/index.html">Book Information</a></li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-1">
|
||||
<span id="sgSpan-0-1" class="fa fa-caret-right"></span> Programming Languages
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-1" class="nav-tertiary list-unstyled collapse">
|
||||
<li><a class="" href="../../en-US/programming-languages/C.html">The C Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/CXX.html">The C++ Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Java.html">The Java Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Python.html">The Python Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Shell.html">Shell Programming and bash</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Go.html">The Go Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Vala.html">The Vala Programming Language</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-2">
|
||||
<span id="sgSpan-0-2" class="fa fa-caret-down"></span> Specific Programming Tasks
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-2" class="nav-tertiary list-unstyled collapse in">
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Library_Design.html">Library Design</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Descriptors.html">File Descriptor Management</a></li>
|
||||
<li><a class=" active" href="../../en-US/tasks/Tasks-File_System.html">File System Manipulation</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Temporary_Files.html">Temporary Files</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Processes.html">Processes</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Serialization.html">Serialization and Deserialization</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Cryptography.html">Cryptography</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Packaging.html">RPM Packaging</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-3">
|
||||
<span id="sgSpan-0-3" class="fa fa-caret-right"></span> Implementing Security Features
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-3" class="nav-tertiary list-unstyled collapse">
|
||||
<li><a class="" href="../../en-US/features/Features-Authentication.html">Authentication and Authorization</a></li>
|
||||
<li><a class="" href="../../en-US/features/Features-TLS.html">Transport Layer Security (TLS)</a></li>
|
||||
<li><a class="" href="../../en-US/features/Features-HSM.html">Hardware Security Modules and Smart Cards</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="" href="../../en-US/Revision_History.html">Revision History</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-9 col-md-9 main">
|
||||
<div class="page-header">
|
||||
<h2>File System Manipulation</h2>
|
||||
</div>
|
||||
<div id="preamble">
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>In this chapter, we discuss general file system manipulation, with
|
||||
a focus on access files and directories to which an other,
|
||||
potentially untrusted user has write access.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Temporary files are covered in their own chapter, <a href="#chap-Defensive_Coding-Tasks-Temporary_Files">[chap-Defensive_Coding-Tasks-Temporary_Files]</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="sect-Defensive_Coding-Tasks-File_System-Unowned"><a class="anchor" href="#sect-Defensive_Coding-Tasks-File_System-Unowned"></a>Working with Files and Directories Owned by Other Users</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>Sometimes, it is necessary to operate on files and directories
|
||||
owned by other (potentially untrusted) users. For example, a
|
||||
system administrator could remove the home directory of a user,
|
||||
or a package manager could update a file in a directory which is
|
||||
owned by an application-specific user. This differs from
|
||||
accessing the file system as a specific user; see
|
||||
<a href="#sect-Defensive_Coding-Tasks-File_System-Foreign">Accessing the File System as a Different User</a>.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Accessing files across trust boundaries faces several
|
||||
challenges, particularly if an entire directory tree is being
|
||||
traversed:</p>
|
||||
</div>
|
||||
<div class="olist arabic">
|
||||
<ol class="arabic">
|
||||
<li>
|
||||
<p>Another user might add file names to a writable directory at
|
||||
any time. This can interfere with file creation and the
|
||||
order of names returned by <code>readdir</code>.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Merely opening and closing a file can have side effects.
|
||||
For instance, an automounter can be triggered, or a tape
|
||||
device rewound. Opening a file on a local file system can
|
||||
block indefinitely, due to mandatory file locking, unless
|
||||
the <code>O_NONBLOCK</code> flag is specified.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Hard links and symbolic links can redirect the effect of
|
||||
file system operations in unexpected ways. The
|
||||
<code>O_NOFOLLOW</code> and
|
||||
<code>AT_SYMLINK_NOFOLLOW</code> variants of system
|
||||
calls only affected final path name component.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>The structure of a directory tree can change. For example,
|
||||
the parent directory of what used to be a subdirectory
|
||||
within the directory tree being processed could suddenly
|
||||
point outside that directory tree.</p>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Files should always be created with the
|
||||
<code>O_CREAT</code> and <code>O_EXCL</code> flags,
|
||||
so that creating the file will fail if it already exists. This
|
||||
guards against the unexpected appearance of file names, either
|
||||
due to creation of a new file, or hard-linking of an existing
|
||||
file. In multi-threaded programs, rather than manipulating the
|
||||
umask, create the files with mode <code>000</code> if
|
||||
possible, and adjust it afterwards with
|
||||
<code>fchmod</code>.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>To avoid issues related to symbolic links and directory tree
|
||||
restructuring, the “<code>at</code>” variants of system
|
||||
calls have to be used (that is, functions like
|
||||
<code>openat</code>, <code>fchownat</code>,
|
||||
<code>fchmodat</code>, and
|
||||
<code>unlinkat</code>, together with
|
||||
<code>O_NOFOLLOW</code> or
|
||||
<code>AT_SYMLINK_NOFOLLOW</code>). Path names passed to
|
||||
these functions must have just a single component (that is,
|
||||
without a slash). When descending, the descriptors of parent
|
||||
directories must be kept open. The missing
|
||||
<code>opendirat</code> function can be emulated with
|
||||
<code>openat</code> (with an
|
||||
<code>O_DIRECTORY</code> flag, to avoid opening special
|
||||
files with side effects), followed by
|
||||
<code>fdopendir</code>.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>If the “<code>at</code>” functions are not available, it
|
||||
is possible to emulate them by changing the current directory.
|
||||
(Obviously, this only works if the process is not multi-threaded.)
|
||||
<code>fchdir</code> has to be used to change the current
|
||||
directory, and the descriptors of the parent directories have to
|
||||
be kept open, just as with the “<code>at</code>”-based
|
||||
approach. <code>chdir("…​")</code> is unsafe because it
|
||||
might ascend outside the intended directory tree.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>This “<code>at</code>” function emulation is currently
|
||||
required when manipulating extended attributes. In this case,
|
||||
the <code>lsetxattr</code> function can be used, with a
|
||||
relative path name consisting of a single component. This also
|
||||
applies to SELinux contexts and the
|
||||
<code>lsetfilecon</code> function.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Currently, it is not possible to avoid opening special files
|
||||
<strong>and</strong> changes to files with hard links if the
|
||||
directory containing them is owned by an untrusted user.
|
||||
(Device nodes can be hard-linked, just as regular files.)
|
||||
<code>fchmodat</code> and <code>fchownat</code>
|
||||
affect files whose link count is greater than one. But opening
|
||||
the files, checking that the link count is one with
|
||||
<code>fstat</code>, and using
|
||||
<code>fchmod</code> and <code>fchown</code> on
|
||||
the file descriptor may have unwanted side effects, due to item
|
||||
2 above. When creating directories, it is therefore important
|
||||
to change the ownership and permissions only after it has been
|
||||
fully created. Until that point, file names are stable, and no
|
||||
files with unexpected hard links can be introduced.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Similarly, when just reading a directory owned by an untrusted
|
||||
user, it is currently impossible to reliably avoid opening
|
||||
special files.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>There is no workaround against the instability of the file list
|
||||
returned by <code>readdir</code>. Concurrent
|
||||
modification of the directory can result in a list of files
|
||||
being returned which never actually existed on disk.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Hard links and symbolic links can be safely deleted using
|
||||
<code>unlinkat</code> without further checks because
|
||||
deletion only affects the name within the directory tree being
|
||||
processed.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="sect-Defensive_Coding-Tasks-File_System-Foreign"><a class="anchor" href="#sect-Defensive_Coding-Tasks-File_System-Foreign"></a>Accessing the File System as a Different User</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>This section deals with access to the file system as a specific
|
||||
user. This is different from accessing files and directories owned by a
|
||||
different, potentially untrusted user; see <a href="#sect-Defensive_Coding-Tasks-File_System-Foreign">Accessing the File System as a Different User</a>.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>One approach is to spawn a child process which runs under the
|
||||
target user and group IDs (both effective and real IDs). Note
|
||||
that this child process can block indefinitely, even when
|
||||
processing regular files only. For example, a special FUSE file
|
||||
system could cause the process to hang in uninterruptible sleep
|
||||
inside a <code>stat</code> system call.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>An existing process could change its user and group ID using
|
||||
<code>setfsuid</code> and <code>setfsgid</code>.
|
||||
(These functions are preferred over <code>seteuid</code>
|
||||
and <code>setegid</code> because they do not allow the
|
||||
impersonated user to send signals to the process.) These
|
||||
functions are not thread safe. In multi-threaded processes,
|
||||
these operations need to be performed in a single-threaded child
|
||||
process. Unexpected blocking may occur as well.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>It is not recommended to try to reimplement the kernel
|
||||
permission checks in user space because the required checks are
|
||||
complex. It is also very difficult to avoid race conditions
|
||||
during path name resolution.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="sect-Defensive_Coding-Tasks-File_System-Limits"><a class="anchor" href="#sect-Defensive_Coding-Tasks-File_System-Limits"></a>File System Limits</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>For historical reasons, there are preprocessor constants such as
|
||||
<code>PATH_MAX</code>, <code>NAME_MAX</code>.
|
||||
However, on most systems, the length of canonical path names
|
||||
(absolute path names with all symbolic links resolved, as
|
||||
returned by <code>realpath</code> or
|
||||
<code>canonicalize_file_name</code>) can exceed
|
||||
<code>PATH_MAX</code> bytes, and individual file name
|
||||
components can be longer than <code>NAME_MAX</code>. This
|
||||
is also true of the <code>_PC_PATH_MAX</code> and
|
||||
<code>_PC_NAME_MAX</code> values returned by
|
||||
<code>pathconf</code>, and the
|
||||
<code>f_namemax</code> member of <code>struct
|
||||
statvfs</code>. Therefore, these constants should not be
|
||||
used. This is also reason why the
|
||||
<code>readdir_r</code> should never be used (instead,
|
||||
use <code>readdir</code>).</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>You should not write code in a way that assumes that there is an
|
||||
upper limit on the number of subdirectories of a directory, the
|
||||
number of regular files in a directory, or the link count of an
|
||||
inode.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="sect-Defensive_Coding-Tasks-File_System-Features"><a class="anchor" href="#sect-Defensive_Coding-Tasks-File_System-Features"></a>File system features</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>Not all file systems support all features. This makes it very
|
||||
difficult to write general-purpose tools for copying files. For
|
||||
example, a copy operation intending to preserve file permissions
|
||||
will generally fail when copying to a FAT file system.</p>
|
||||
</div>
|
||||
<div class="ulist">
|
||||
<ul>
|
||||
<li>
|
||||
<p>Some file systems are case-insensitive. Most should be
|
||||
case-preserving, though.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Name length limits vary greatly, from eight to thousands of
|
||||
bytes. Path length limits differ as well. Most systems
|
||||
impose an upper bound on path names passed to the kernel,
|
||||
but using relative path names, it is possible to create and
|
||||
access files whose absolute path name is essentially of
|
||||
unbounded length.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Some file systems do not store names as fairly unrestricted
|
||||
byte sequences, as it has been traditionally the case on GNU
|
||||
systems. This means that some byte sequences (outside the
|
||||
POSIX safe character set) are not valid names. Conversely,
|
||||
names of existing files may not be representable as byte
|
||||
sequences, and the files are thus inaccessible on GNU
|
||||
systems. Some file systems perform Unicode canonicalization
|
||||
on file names. These file systems preserve case, but
|
||||
reading the name of a just-created file using
|
||||
<code>readdir</code> might still result in a
|
||||
different byte sequence.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Permissions and owners are not universally supported (and
|
||||
SUID/SGID bits may not be available). For example, FAT file
|
||||
systems assign ownership based on a mount option, and
|
||||
generally mark all files as executable. Any attempt to
|
||||
change permissions would result in an error.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Non-regular files (device nodes, FIFOs) are not generally
|
||||
available.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Only on some file systems, files can have holes, that is,
|
||||
not all of their contents is backed by disk storage.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><code>ioctl</code> support (even fairly generic
|
||||
functionality such as <code>FIEMAP</code> for
|
||||
discovering physical file layout and holes) is
|
||||
file-system-specific.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Not all file systems support extended attributes, ACLs and
|
||||
SELinux metadata. Size and naming restriction on extended
|
||||
attributes vary.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Hard links may not be supported at all (FAT) or only within
|
||||
the same directory (AFS). Symbolic links may not be
|
||||
available, either. Reflinks (hard links with copy-on-write
|
||||
semantics) are still very rare. Recent systems restrict
|
||||
creation of hard links to users which own the target file or
|
||||
have read/write access to it, but older systems do not.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Renaming (or moving) files using <code>rename</code>
|
||||
can fail (even when <code>stat</code> indicates that
|
||||
the source and target directories are located on the same
|
||||
file system). This system call should work if the old and
|
||||
new paths are located in the same directory, though.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Locking semantics vary among file systems. This affects
|
||||
advisory and mandatory locks. For example, some network
|
||||
file systems do not allow deleting files which are opened by
|
||||
any process.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Resolution of time stamps varies from two seconds to
|
||||
nanoseconds. Not all time stamps are available on all file
|
||||
systems. File creation time (<strong>birth
|
||||
time</strong>) is not exposed over the
|
||||
<code>stat</code>/<code>fstat</code>
|
||||
interface, even if stored by the file system.</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="sect-Defensive_Coding-Tasks-File_System-Free_Space"><a class="anchor" href="#sect-Defensive_Coding-Tasks-File_System-Free_Space"></a>Checking Free Space</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>The <code>statvfs</code> and
|
||||
<code>fstatvfs</code> functions allow programs to
|
||||
examine the number of available blocks and inodes, through the
|
||||
members <code>f_bfree</code>, <code>f_bavail</code>,
|
||||
<code>f_ffree</code>, and <code>f_favail</code> of
|
||||
<code>struct statvfs</code>. Some file systems return
|
||||
fictional values in the <code>f_ffree</code> and
|
||||
<code>f_favail</code> fields, so the only reliable way to
|
||||
discover if the file system still has space for a file is to try
|
||||
to create it. The <code>f_bfree</code> field should be
|
||||
reasonably accurate, though.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="bottom" class="text-muted py-3" >
|
||||
<div class="foot">
|
||||
<div class="container">
|
||||
<div class="row footerlinks">
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">About</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Overview">About Fedora</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/sponsors">Sponsors</a></dd>
|
||||
<dd><a href="https://fedoramagazine.org">Fedora Magazine</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Legal:Main#Legal">Legal</a></dd>
|
||||
</dl>
|
||||
<ul class="list-inline">
|
||||
<li>
|
||||
<a href="https://www.facebook.com/TheFedoraProject" class="btn-social btn-outline"><i class="fa fa-fw fa-facebook"></i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://plus.google.com/112917221531140868607" class="btn-social btn-outline"><i class="fa fa-fw fa-google-plus"></i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://twitter.com/fedora" class="btn-social btn-outline"><i class="fa fa-fw fa-twitter"></i></a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title uppercase">Download</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://getfedora.org/en/workstation/download">Get Fedora Workstation</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/server/download">Get Fedora Server</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/atomic/download">Get Fedora Atomic</a></dd>
|
||||
<dd><a href="https://spins.fedoraproject.org">Fedora Spins</a></dd>
|
||||
<dd><a href="https://labs.fedoraproject.org">Fedora Labs</a></dd>
|
||||
<dd><a href="https://arm.fedoraproject.org">Fedora ARM<span class="sup">®</span></a></dd>
|
||||
<dd><a href="https://alt.fedoraproject.org/">Alternative Downloads</a></dd>
|
||||
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">Support</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Communicating_and_getting_help">Get Help</a></dd>
|
||||
<dd><a href="https://ask.fedoraproject.org/">Ask Fedora</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Common_F27_bugs">Common Bugs</a></dd>
|
||||
<dd><a href="https://developer.fedoraproject.org/">Fedora Developer Portal</a></dd>
|
||||
<dd><a href="https://docs.fedoraproject.org/f27/install-guide/index.html">Installation Guide</a></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">Join</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Join">Join Fedora</a></dd>
|
||||
<dd><a href="http://fedoraplanet.org">Planet Fedora</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/SIGs">Fedora SIGs</a></dd>
|
||||
<dd><a href="https://admin.fedoraproject.org/accounts/">Fedora Account System</a></dd>
|
||||
<dd><a href="https://fedoracommunity.org/">Fedora Community</a></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- /row of widgets -->
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-2">
|
||||
<div class="widget-body">
|
||||
<a href="https://www.redhat.com/"><img class="rh-logo" src="../../../master/_images/redhat-logo.png" alt="Red Hat Logo" /></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-7">
|
||||
<div class="widget-body">
|
||||
<p class="sponsor">Fedora is sponsored by Red Hat.</p>
|
||||
<p class="sponsor"><a href="https://www.redhat.com/en/technologies/linux-platforms/articles/relationship-between-fedora-and-rhel">Learn more about the relationship between Red Hat and Fedora »</a></p>
|
||||
<p class="copy">© 2017 Red Hat, Inc. and others. Please send any comments or corrections to the <a href="https://pagure.io/fedora-docs/docs-fp-o">documentation team</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- /row of widgets -->
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
|
||||
<!-- Latest compiled and minified JavaScript -->
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
|
||||
<script src="../../../master/_javascripts/bootstrap-offcanvas.js" type="text/javascript"></script>
|
||||
<script type="text/javascript">
|
||||
/*<![CDATA[*/
|
||||
$(document).ready(function() {
|
||||
$("[id^='topicGroup']").on('show.bs.collapse', function (event) {
|
||||
if (!($(event.target).attr('id').match(/^topicSubGroup/))) {
|
||||
$(this).parent().find("[id^='tgSpan']").toggleClass("fa-angle-right fa-angle-down");
|
||||
}
|
||||
});
|
||||
$("[id^='topicGroup']").on('hide.bs.collapse', function (event) {
|
||||
if (!($(event.target).attr('id').match(/^topicSubGroup/))) {
|
||||
$(this).parent().find("[id^='tgSpan']").toggleClass("fa-angle-right fa-angle-down");
|
||||
}
|
||||
});
|
||||
$("[id^='topicSubGroup']").on('show.bs.collapse', function () {
|
||||
$(this).parent().find("[id^='sgSpan']").toggleClass("fa-caret-right fa-caret-down");
|
||||
});
|
||||
$("[id^='topicSubGroup']").on('hide.bs.collapse', function () {
|
||||
$(this).parent().find("[id^='sgSpan']").toggleClass("fa-caret-right fa-caret-down");
|
||||
});
|
||||
});
|
||||
/*]]>*/
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -1,425 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta content="IE=edge" http-equiv="X-UA-Compatible">
|
||||
<meta content="width=device-width, initial-scale=1.0" name="viewport">
|
||||
<title>Defensive Coding Guide | Defensive Coding Guide | Specific Programming Tasks | Library Design</title>
|
||||
|
||||
<!-- Bootstrap -->
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap-theme.min.css">
|
||||
|
||||
<!-- Overpass Font -->
|
||||
<link rel="stylesheet" href="https://overpass-30e2.kxcdn.com/overpass.css">
|
||||
|
||||
<link href="../../../master/_stylesheets/asciibinder.css" rel="stylesheet" />
|
||||
|
||||
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
|
||||
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
|
||||
<!--[if lt IE 9]>
|
||||
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
|
||||
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
|
||||
<![endif]-->
|
||||
|
||||
<link href="../../../master/_images/favicon32x32.png" rel="shortcut icon" type="text/css">
|
||||
<!--[if IE]><link rel="shortcut icon" href="../../../master/_images/favicon.ico"><![endif]-->
|
||||
<meta content="AsciiBinder" name="application-name">
|
||||
</head>
|
||||
<body>
|
||||
<div class="navbar navbar-default" role="navigation">
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-header">
|
||||
<a class="navbar-brand" href="https://docs.fedoraproject.org/"><img alt="Fedora Documentation" src="../../../master/_images/fedora.svg"></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container">
|
||||
<p class="toggle-nav visible-xs pull-left">
|
||||
<button class="btn btn-default btn-sm" type="button" data-toggle="offcanvas">Toggle nav</button>
|
||||
</p>
|
||||
<ol class="breadcrumb">
|
||||
<li class="sitename">
|
||||
<a href="../../../index.html">Home</a>
|
||||
</li>
|
||||
<li class="hidden-xs active">
|
||||
<a href="../../en-US/index.html">Defensive Coding Guide </a>
|
||||
</li>
|
||||
<li class="hidden-xs active">
|
||||
<a href="../../en-US/index.html">Defensive Coding Guide</a>
|
||||
</li>
|
||||
<li class="hidden-xs active"><a href="../../en-US/tasks/Tasks-Library_Design.html">Specific Programming Tasks</a></li>
|
||||
<li class="hidden-xs active">
|
||||
Library Design
|
||||
</li>
|
||||
</ol>
|
||||
<div class="row row-offcanvas row-offcanvas-left">
|
||||
<div class="col-xs-8 col-sm-3 col-md-3 sidebar sidebar-offcanvas">
|
||||
<ul class="nav nav-sidebar">
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicGroup0">
|
||||
<span id="tgSpan0" class="fa fa-angle-down"></span>Defensive Coding Guide
|
||||
</a>
|
||||
<ul id="topicGroup0" class="collapse in list-unstyled">
|
||||
<li><a class="" href="../../en-US/index.html">Book Information</a></li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-1">
|
||||
<span id="sgSpan-0-1" class="fa fa-caret-right"></span> Programming Languages
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-1" class="nav-tertiary list-unstyled collapse">
|
||||
<li><a class="" href="../../en-US/programming-languages/C.html">The C Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/CXX.html">The C++ Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Java.html">The Java Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Python.html">The Python Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Shell.html">Shell Programming and bash</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Go.html">The Go Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Vala.html">The Vala Programming Language</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-2">
|
||||
<span id="sgSpan-0-2" class="fa fa-caret-down"></span> Specific Programming Tasks
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-2" class="nav-tertiary list-unstyled collapse in">
|
||||
<li><a class=" active" href="../../en-US/tasks/Tasks-Library_Design.html">Library Design</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Descriptors.html">File Descriptor Management</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-File_System.html">File System Manipulation</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Temporary_Files.html">Temporary Files</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Processes.html">Processes</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Serialization.html">Serialization and Deserialization</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Cryptography.html">Cryptography</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Packaging.html">RPM Packaging</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-3">
|
||||
<span id="sgSpan-0-3" class="fa fa-caret-right"></span> Implementing Security Features
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-3" class="nav-tertiary list-unstyled collapse">
|
||||
<li><a class="" href="../../en-US/features/Features-Authentication.html">Authentication and Authorization</a></li>
|
||||
<li><a class="" href="../../en-US/features/Features-TLS.html">Transport Layer Security (TLS)</a></li>
|
||||
<li><a class="" href="../../en-US/features/Features-HSM.html">Hardware Security Modules and Smart Cards</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="" href="../../en-US/Revision_History.html">Revision History</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-9 col-md-9 main">
|
||||
<div class="page-header">
|
||||
<h2>Library Design</h2>
|
||||
</div>
|
||||
<div id="preamble">
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>Through this section, the term <strong>client code</strong>
|
||||
refers to applications and other libraries using the library.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="state-management"><a class="anchor" href="#state-management"></a>State Management</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="sect2">
|
||||
<h3 id="global-state"><a class="anchor" href="#global-state"></a>Global State</h3>
|
||||
<div class="paragraph">
|
||||
<p>Global state should be avoided.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>If this is impossible, the global state must be protected with
|
||||
a lock. For C/C++, you can use the
|
||||
<code>pthread_mutex_lock</code>
|
||||
and <code>pthread_mutex_unlock</code>
|
||||
functions without linking against <code>-lpthread</code>
|
||||
because the system provides stubs for non-threaded processes.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>For compatibility with <code>fork</code>, these locks
|
||||
should be acquired and released in helpers registered with
|
||||
<code>pthread_atfork</code>. This function is not
|
||||
available without <code>-lpthread</code>, so you need to
|
||||
use <code>dlsym</code> or a weak symbol to obtain its
|
||||
address.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>If you need <code>fork</code> protection for other
|
||||
reasons, you should store the process ID and compare it to the
|
||||
value returned by <code>getpid</code> each time you
|
||||
access the global state. (<code>getpid</code> is not
|
||||
implemented as a system call and is fast.) If the value
|
||||
changes, you know that you have to re-create the state object.
|
||||
(This needs to be combined with locking, of course.)</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect2">
|
||||
<h3 id="handles"><a class="anchor" href="#handles"></a>Handles</h3>
|
||||
<div class="paragraph">
|
||||
<p>Library state should be kept behind a curtain. Client code
|
||||
should receive only a handle. In C, the handle can be a
|
||||
pointer to an incomplete <code>struct</code>. In C++,
|
||||
the handle can be a pointer to an abstract base class, or it
|
||||
can be hidden using the pointer-to-implementation idiom.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>The library should provide functions for creating and
|
||||
destroying handles. (In C++, it is possible to use virtual
|
||||
destructors for the latter.) Consistency between creation and
|
||||
destruction of handles is strongly recommended: If the client
|
||||
code created a handle, it is the responsibility of the client
|
||||
code to destroy it. (This is not always possible or
|
||||
convenient, so sometimes, a transfer of ownership has to
|
||||
happen.)</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Using handles ensures that it is possible to change the way
|
||||
the library represents state in a way that is transparent to
|
||||
client code. This is important to facilitate security updates
|
||||
and many other code changes.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>It is not always necessary to protect state behind a handle
|
||||
with a lock. This depends on the level of thread safety
|
||||
the library provides.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="object-orientation"><a class="anchor" href="#object-orientation"></a>Object Orientation</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>Classes should be either designed as base classes, or it should
|
||||
be impossible to use them as base classes (like
|
||||
<code>final</code> classes in Java). Classes which are
|
||||
not designed for inheritance and are used as base classes
|
||||
nevertheless create potential maintenance hazards because it is
|
||||
difficult to predict how client code will react when calls to
|
||||
virtual methods are added, reordered or removed.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Virtual member functions can be used as callbacks. See
|
||||
<a href="#sect-Defensive_Coding-Tasks-Library_Design-Callbacks">Callbacks</a>
|
||||
for some of the challenges involved.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="sect-Defensive_Coding-Tasks-Library_Design-Callbacks"><a class="anchor" href="#sect-Defensive_Coding-Tasks-Library_Design-Callbacks"></a>Callbacks</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>Higher-order code is difficult to analyze for humans and
|
||||
computers alike, so it should be avoided. Often, an
|
||||
iterator-based interface (a library function which is called
|
||||
repeatedly by client code and returns a stream of events) leads
|
||||
to a better design which is easier to document and use.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>If callbacks are unavoidable, some guidelines for them follow.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>In modern C++ code, <code>std::function</code> objects
|
||||
should be used for callbacks.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>In older C++ code and in C code, all callbacks must have an
|
||||
additional closure parameter of type <code>void *</code>,
|
||||
the value of which can be specified by client code. If
|
||||
possible, the value of the closure parameter should be provided
|
||||
by client code at the same time a specific callback is
|
||||
registered (or specified as a function argument). If a single
|
||||
closure parameter is shared by multiple callbacks, flexibility
|
||||
is greatly reduced, and conflicts between different pieces of
|
||||
client code using the same library object could be unresolvable.
|
||||
In some cases, it makes sense to provide a de-registration
|
||||
callback which can be used to destroy the closure parameter when
|
||||
the callback is no longer used.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Callbacks can throw exceptions or call
|
||||
<code>longjmp</code>. If possible, all library objects
|
||||
should remain in a valid state. (All further operations on them
|
||||
can fail, but it should be possible to deallocate them without
|
||||
causing resource leaks.)</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>The presence of callbacks raises the question if functions
|
||||
provided by the library are <strong>reentrant</strong>.
|
||||
Unless a library was designed for such use, bad things will
|
||||
happen if a callback function uses functions in the same library
|
||||
(particularly if they are invoked on the same objects and
|
||||
manipulate the same state). When the callback is invoked, the
|
||||
library can be in an inconsistent state. Reentrant functions
|
||||
are more difficult to write than thread-safe functions (by
|
||||
definition, simple locking would immediately lead to deadlocks).
|
||||
It is also difficult to decide what to do when destruction of an
|
||||
object which is currently processing a callback is requested.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="process-attributes"><a class="anchor" href="#process-attributes"></a>Process Attributes</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>Several attributes are global and affect all code in the
|
||||
process, not just the library that manipulates them.</p>
|
||||
</div>
|
||||
<div class="ulist">
|
||||
<ul>
|
||||
<li>
|
||||
<p>environment variables
|
||||
(see <a href="#sect-Defensive_Coding-Tasks-secure_getenv">[sect-Defensive_Coding-Tasks-secure_getenv]</a>)</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>umask</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>user IDs, group IDs and capabilities</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>current working directory</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>signal handlers, signal masks and signal delivery</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>file locks (especially <code>fcntl</code> locks
|
||||
behave in surprising ways, not just in a multi-threaded
|
||||
environment)</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Library code should avoid manipulating these global process
|
||||
attributes. It should not rely on environment variables, umask,
|
||||
the current working directory and signal masks because these
|
||||
attributes can be inherited from an untrusted source.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>In addition, there are obvious process-wide aspects such as the
|
||||
virtual memory layout, the set of open files and dynamic shared
|
||||
objects, but with the exception of shared objects, these can be
|
||||
manipulated in a relatively isolated way.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="bottom" class="text-muted py-3" >
|
||||
<div class="foot">
|
||||
<div class="container">
|
||||
<div class="row footerlinks">
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">About</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Overview">About Fedora</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/sponsors">Sponsors</a></dd>
|
||||
<dd><a href="https://fedoramagazine.org">Fedora Magazine</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Legal:Main#Legal">Legal</a></dd>
|
||||
</dl>
|
||||
<ul class="list-inline">
|
||||
<li>
|
||||
<a href="https://www.facebook.com/TheFedoraProject" class="btn-social btn-outline"><i class="fa fa-fw fa-facebook"></i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://plus.google.com/112917221531140868607" class="btn-social btn-outline"><i class="fa fa-fw fa-google-plus"></i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://twitter.com/fedora" class="btn-social btn-outline"><i class="fa fa-fw fa-twitter"></i></a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title uppercase">Download</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://getfedora.org/en/workstation/download">Get Fedora Workstation</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/server/download">Get Fedora Server</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/atomic/download">Get Fedora Atomic</a></dd>
|
||||
<dd><a href="https://spins.fedoraproject.org">Fedora Spins</a></dd>
|
||||
<dd><a href="https://labs.fedoraproject.org">Fedora Labs</a></dd>
|
||||
<dd><a href="https://arm.fedoraproject.org">Fedora ARM<span class="sup">®</span></a></dd>
|
||||
<dd><a href="https://alt.fedoraproject.org/">Alternative Downloads</a></dd>
|
||||
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">Support</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Communicating_and_getting_help">Get Help</a></dd>
|
||||
<dd><a href="https://ask.fedoraproject.org/">Ask Fedora</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Common_F27_bugs">Common Bugs</a></dd>
|
||||
<dd><a href="https://developer.fedoraproject.org/">Fedora Developer Portal</a></dd>
|
||||
<dd><a href="https://docs.fedoraproject.org/f27/install-guide/index.html">Installation Guide</a></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">Join</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Join">Join Fedora</a></dd>
|
||||
<dd><a href="http://fedoraplanet.org">Planet Fedora</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/SIGs">Fedora SIGs</a></dd>
|
||||
<dd><a href="https://admin.fedoraproject.org/accounts/">Fedora Account System</a></dd>
|
||||
<dd><a href="https://fedoracommunity.org/">Fedora Community</a></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- /row of widgets -->
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-2">
|
||||
<div class="widget-body">
|
||||
<a href="https://www.redhat.com/"><img class="rh-logo" src="../../../master/_images/redhat-logo.png" alt="Red Hat Logo" /></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-7">
|
||||
<div class="widget-body">
|
||||
<p class="sponsor">Fedora is sponsored by Red Hat.</p>
|
||||
<p class="sponsor"><a href="https://www.redhat.com/en/technologies/linux-platforms/articles/relationship-between-fedora-and-rhel">Learn more about the relationship between Red Hat and Fedora »</a></p>
|
||||
<p class="copy">© 2017 Red Hat, Inc. and others. Please send any comments or corrections to the <a href="https://pagure.io/fedora-docs/docs-fp-o">documentation team</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- /row of widgets -->
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
|
||||
<!-- Latest compiled and minified JavaScript -->
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
|
||||
<script src="../../../master/_javascripts/bootstrap-offcanvas.js" type="text/javascript"></script>
|
||||
<script type="text/javascript">
|
||||
/*<![CDATA[*/
|
||||
$(document).ready(function() {
|
||||
$("[id^='topicGroup']").on('show.bs.collapse', function (event) {
|
||||
if (!($(event.target).attr('id').match(/^topicSubGroup/))) {
|
||||
$(this).parent().find("[id^='tgSpan']").toggleClass("fa-angle-right fa-angle-down");
|
||||
}
|
||||
});
|
||||
$("[id^='topicGroup']").on('hide.bs.collapse', function (event) {
|
||||
if (!($(event.target).attr('id').match(/^topicSubGroup/))) {
|
||||
$(this).parent().find("[id^='tgSpan']").toggleClass("fa-angle-right fa-angle-down");
|
||||
}
|
||||
});
|
||||
$("[id^='topicSubGroup']").on('show.bs.collapse', function () {
|
||||
$(this).parent().find("[id^='sgSpan']").toggleClass("fa-caret-right fa-caret-down");
|
||||
});
|
||||
$("[id^='topicSubGroup']").on('hide.bs.collapse', function () {
|
||||
$(this).parent().find("[id^='sgSpan']").toggleClass("fa-caret-right fa-caret-down");
|
||||
});
|
||||
});
|
||||
/*]]>*/
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -1,438 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta content="IE=edge" http-equiv="X-UA-Compatible">
|
||||
<meta content="width=device-width, initial-scale=1.0" name="viewport">
|
||||
<title>Defensive Coding Guide | Defensive Coding Guide | Specific Programming Tasks | RPM Packaging</title>
|
||||
|
||||
<!-- Bootstrap -->
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap-theme.min.css">
|
||||
|
||||
<!-- Overpass Font -->
|
||||
<link rel="stylesheet" href="https://overpass-30e2.kxcdn.com/overpass.css">
|
||||
|
||||
<link href="../../../master/_stylesheets/asciibinder.css" rel="stylesheet" />
|
||||
|
||||
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
|
||||
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
|
||||
<!--[if lt IE 9]>
|
||||
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
|
||||
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
|
||||
<![endif]-->
|
||||
|
||||
<link href="../../../master/_images/favicon32x32.png" rel="shortcut icon" type="text/css">
|
||||
<!--[if IE]><link rel="shortcut icon" href="../../../master/_images/favicon.ico"><![endif]-->
|
||||
<meta content="AsciiBinder" name="application-name">
|
||||
</head>
|
||||
<body>
|
||||
<div class="navbar navbar-default" role="navigation">
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-header">
|
||||
<a class="navbar-brand" href="https://docs.fedoraproject.org/"><img alt="Fedora Documentation" src="../../../master/_images/fedora.svg"></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container">
|
||||
<p class="toggle-nav visible-xs pull-left">
|
||||
<button class="btn btn-default btn-sm" type="button" data-toggle="offcanvas">Toggle nav</button>
|
||||
</p>
|
||||
<ol class="breadcrumb">
|
||||
<li class="sitename">
|
||||
<a href="../../../index.html">Home</a>
|
||||
</li>
|
||||
<li class="hidden-xs active">
|
||||
<a href="../../en-US/index.html">Defensive Coding Guide </a>
|
||||
</li>
|
||||
<li class="hidden-xs active">
|
||||
<a href="../../en-US/index.html">Defensive Coding Guide</a>
|
||||
</li>
|
||||
<li class="hidden-xs active"><a href="../../en-US/tasks/Tasks-Library_Design.html">Specific Programming Tasks</a></li>
|
||||
<li class="hidden-xs active">
|
||||
RPM Packaging
|
||||
</li>
|
||||
</ol>
|
||||
<div class="row row-offcanvas row-offcanvas-left">
|
||||
<div class="col-xs-8 col-sm-3 col-md-3 sidebar sidebar-offcanvas">
|
||||
<ul class="nav nav-sidebar">
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicGroup0">
|
||||
<span id="tgSpan0" class="fa fa-angle-down"></span>Defensive Coding Guide
|
||||
</a>
|
||||
<ul id="topicGroup0" class="collapse in list-unstyled">
|
||||
<li><a class="" href="../../en-US/index.html">Book Information</a></li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-1">
|
||||
<span id="sgSpan-0-1" class="fa fa-caret-right"></span> Programming Languages
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-1" class="nav-tertiary list-unstyled collapse">
|
||||
<li><a class="" href="../../en-US/programming-languages/C.html">The C Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/CXX.html">The C++ Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Java.html">The Java Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Python.html">The Python Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Shell.html">Shell Programming and bash</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Go.html">The Go Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Vala.html">The Vala Programming Language</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-2">
|
||||
<span id="sgSpan-0-2" class="fa fa-caret-down"></span> Specific Programming Tasks
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-2" class="nav-tertiary list-unstyled collapse in">
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Library_Design.html">Library Design</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Descriptors.html">File Descriptor Management</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-File_System.html">File System Manipulation</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Temporary_Files.html">Temporary Files</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Processes.html">Processes</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Serialization.html">Serialization and Deserialization</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Cryptography.html">Cryptography</a></li>
|
||||
<li><a class=" active" href="../../en-US/tasks/Tasks-Packaging.html">RPM Packaging</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-3">
|
||||
<span id="sgSpan-0-3" class="fa fa-caret-right"></span> Implementing Security Features
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-3" class="nav-tertiary list-unstyled collapse">
|
||||
<li><a class="" href="../../en-US/features/Features-Authentication.html">Authentication and Authorization</a></li>
|
||||
<li><a class="" href="../../en-US/features/Features-TLS.html">Transport Layer Security (TLS)</a></li>
|
||||
<li><a class="" href="../../en-US/features/Features-HSM.html">Hardware Security Modules and Smart Cards</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="" href="../../en-US/Revision_History.html">Revision History</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-9 col-md-9 main">
|
||||
<div class="page-header">
|
||||
<h2>RPM Packaging</h2>
|
||||
</div>
|
||||
<div id="preamble">
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>This chapter deals with security-related concerns around RPM
|
||||
packaging. It has to be read in conjunction with
|
||||
distribution-specific packaging guidelines.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="sect-Defensive_Coding-Tasks-Packaging-Certificates"><a class="anchor" href="#sect-Defensive_Coding-Tasks-Packaging-Certificates"></a>Generating X.509 Self-signed Certificates during Installation</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>Some applications need X.509 certificates for authentication
|
||||
purposes. For example, a single private/public key pair could
|
||||
be used to define cluster membership, enabling authentication
|
||||
and encryption of all intra-cluster communication. (Lack of
|
||||
certification from a CA matters less in such a context.) For
|
||||
such use, generating the key pair at package installation time
|
||||
when preparing system images for use in the cluster is
|
||||
reasonable. For other use cases, it is necessary to generate
|
||||
the key pair before the service is started for the first time,
|
||||
see <a href="#sect-Defensive_Coding-Tasks-Packaging-Certificates-Service">Generating X.509 Self-signed Certificates before Service Start</a>,
|
||||
and <a href="https://fedoraproject.org/wiki/Packaging:Initial_Service_Setup#Generating_Self-Signed_Certificates">Packaging:Initial Service Setup</a>.</p>
|
||||
</div>
|
||||
<div class="admonitionblock important">
|
||||
<table>
|
||||
<tr>
|
||||
<td class="icon">
|
||||
<i class="fa icon-important" title="Important"></i>
|
||||
</td>
|
||||
<td class="content">
|
||||
<div class="paragraph">
|
||||
<p>The way the key is generated may not be suitable for key
|
||||
material of critical value. (<code class="command">openssl
|
||||
genrsa</code> uses, but does not require, entropy from a
|
||||
physical source of randomness, among other things.) Such keys
|
||||
should be stored in a hardware security module if possible,
|
||||
and generated from random bits reserved for this purpose
|
||||
derived from a non-deterministic physical source.</p>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>In the spec file, we define two RPM variables which contain the
|
||||
names of the files used to store the private and public key, and
|
||||
the user name for the service:</p>
|
||||
</div>
|
||||
<div class="listingblock">
|
||||
<div class="content">
|
||||
<pre class="CodeRay highlight"><code data-lang="bash"># Name of the user owning the file with the private key
|
||||
%define tlsuser %{name}
|
||||
# Name of the directory which contains the key and certificate files
|
||||
%define tlsdir %{_sysconfdir}/%{name}
|
||||
%define tlskey %{tlsdir}/%{name}.key
|
||||
%define tlscert %{tlsdir}/%{name}.crt</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>These variables likely need adjustment based on the needs of the
|
||||
package.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Typically, the file with the private key needs to be owned by
|
||||
the system user which needs to read it,
|
||||
<code>%{tlsuser}</code> (not <code>root</code>). In
|
||||
order to avoid races, if the <strong>directory</strong>
|
||||
<code>%{tlsdir}</code> is <strong>owned by the services
|
||||
user</strong>, you should use the code in <a href="#ex-Defensive_Coding-Packaging-Certificates-Owned">Creating a key pair in a user-owned directory</a>.
|
||||
The invocation of <strong class="application">su</strong> with the
|
||||
<code class="option">-s /bin/bash</code> argument is necessary in case the
|
||||
login shell for the user has been disabled.</p>
|
||||
</div>
|
||||
<div id="ex-Defensive_Coding-Packaging-Certificates-Owned" class="exampleblock">
|
||||
<div class="title">Example 1. Creating a key pair in a user-owned directory</div>
|
||||
<div class="content">
|
||||
<div class="listingblock">
|
||||
<div class="content">
|
||||
<pre class="CodeRay highlight"><code data-lang="bash">%post
|
||||
if [ $1 -eq 1 ] ; then
|
||||
if ! test -e %{tlskey} ; then
|
||||
su -s /bin/bash \
|
||||
-c "umask 077 && openssl genrsa -out %{tlskey} 2048 2>/dev/null" \
|
||||
%{tlsuser}
|
||||
fi
|
||||
if ! test -e %{tlscert} ; then
|
||||
cn="Automatically generated certificate for the %{tlsuser} service"
|
||||
req_args="-key %{tlskey} -out %{tlscert} -days 7305 -subj \"/CN=$cn/\""
|
||||
su -s /bin/bash \
|
||||
-c "openssl req -new -x509 -extensions usr_cert $req_args" \
|
||||
%{tlsuser}
|
||||
fi
|
||||
fi
|
||||
|
||||
%files
|
||||
%dir %attr(0755,%{tlsuser},%{tlsuser]) %{tlsdir}
|
||||
%ghost %attr(0600,%{tlsuser},%{tlsuser}) %config(noreplace) %{tlskey}
|
||||
%ghost %attr(0644,%{tlsuser},%{tlsuser}) %config(noreplace) %{tlscert}</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>The files containing the key material are marked as ghost
|
||||
configuration files. This ensures that they are tracked in the
|
||||
RPM database as associated with the package, but RPM will not
|
||||
create them when the package is installed and not verify their
|
||||
contents (the <code>%ghost</code>), or delete the files
|
||||
when the package is uninstalled (the
|
||||
<code>%config(noreplace)</code> part).</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>If the <strong>directory</strong>
|
||||
<code>%{tlsdir}</code> <strong>is owned by</strong>
|
||||
<code>root</code>, use the code in <a href="#ex-Defensive_Coding-Packaging-Certificates-Unowned">Creating a key pair in a <code>root</code>-owned directory</a>.</p>
|
||||
</div>
|
||||
<div id="ex-Defensive_Coding-Packaging-Certificates-Unowned" class="exampleblock">
|
||||
<div class="title">Example 2. Creating a key pair in a <code>root</code>-owned directory</div>
|
||||
<div class="content">
|
||||
<div class="listingblock">
|
||||
<div class="content">
|
||||
<pre class="CodeRay highlight"><code data-lang="bash">%post
|
||||
if [ $1 -eq 1 ] ; then
|
||||
if ! test -e %{tlskey} ; then
|
||||
(umask 077 && openssl genrsa -out %{tlskey} 2048 2>/dev/null)
|
||||
chown %{tlsuser} %{tlskey}
|
||||
fi
|
||||
if ! test -e %{tlscert} ; then
|
||||
cn="Automatically generated certificate for the %{tlsuser} service"
|
||||
openssl req -new -x509 -extensions usr_cert \
|
||||
-key %{tlskey} -out %{tlscert} -days 7305 -subj "/CN=$cn/"
|
||||
fi
|
||||
fi
|
||||
|
||||
%files
|
||||
%dir %attr(0755,root,root]) %{tlsdir}
|
||||
%ghost %attr(0600,%{tlsuser},%{tlsuser}) %config(noreplace) %{tlskey}
|
||||
%ghost %attr(0644,root,root) %config(noreplace) %{tlscert}</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>In order for this to work, the package which generates the keys
|
||||
must require the <strong class="application">openssl</strong> package. If
|
||||
the user which owns the key file is generated by a different
|
||||
package, the package generating the certificate must specify a
|
||||
<code>Requires(pre):</code> on the package which creates
|
||||
the user. This ensures that the user account will exist when it
|
||||
is needed for the <strong class="application">su</strong> or
|
||||
<strong class="application">chmod</strong> invocation.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="sect-Defensive_Coding-Tasks-Packaging-Certificates-Service"><a class="anchor" href="#sect-Defensive_Coding-Tasks-Packaging-Certificates-Service"></a>Generating X.509 Self-signed Certificates before Service Start</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>An alternative way to automatically provide an X.509 key pair is
|
||||
to create it just before the service is started for the first
|
||||
time. This ensures that installation images which are created
|
||||
from installed RPM packages receive different key material.
|
||||
Creating the key pair at package installation time (see <a href="#sect-Defensive_Coding-Tasks-Packaging-Certificates">Generating X.509 Self-signed Certificates during Installation</a>)
|
||||
would put the key into the image, which may or may not make
|
||||
sense.</p>
|
||||
</div>
|
||||
<div class="admonitionblock important">
|
||||
<table>
|
||||
<tr>
|
||||
<td class="icon">
|
||||
<i class="fa icon-important" title="Important"></i>
|
||||
</td>
|
||||
<td class="content">
|
||||
<div class="paragraph">
|
||||
<p>The caveats about the way the key is generated in <a href="#sect-Defensive_Coding-Tasks-Packaging-Certificates">Generating X.509 Self-signed Certificates during Installation</a>
|
||||
apply to this procedure as well.</p>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Generating key material before service start may happen very
|
||||
early during boot, when the kernel randomness pool has not yet
|
||||
been initialized. Currently, the only way to check for the
|
||||
initialization is to look for the kernel message
|
||||
<code>random: nonblocking pool is initialized</code>, or
|
||||
ensure that the application used for generating the keys
|
||||
is utilizing the <code>getrandom()</code> system call.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>In theory, it is also possible to use an application which reads from
|
||||
<code>/dev/random</code> while generating the key
|
||||
material (instead of <code>/dev/urandom</code>), but
|
||||
this can block not just during the boot process, but also much
|
||||
later at run time, and generally results in a poor user
|
||||
experience.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>The requirements for generating such keys is documented at
|
||||
<a href="https://fedoraproject.org/wiki/Packaging:Initial_Service_Setup#Generating_Self-Signed_Certificates">Packaging:Initial Service Setup</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="bottom" class="text-muted py-3" >
|
||||
<div class="foot">
|
||||
<div class="container">
|
||||
<div class="row footerlinks">
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">About</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Overview">About Fedora</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/sponsors">Sponsors</a></dd>
|
||||
<dd><a href="https://fedoramagazine.org">Fedora Magazine</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Legal:Main#Legal">Legal</a></dd>
|
||||
</dl>
|
||||
<ul class="list-inline">
|
||||
<li>
|
||||
<a href="https://www.facebook.com/TheFedoraProject" class="btn-social btn-outline"><i class="fa fa-fw fa-facebook"></i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://plus.google.com/112917221531140868607" class="btn-social btn-outline"><i class="fa fa-fw fa-google-plus"></i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://twitter.com/fedora" class="btn-social btn-outline"><i class="fa fa-fw fa-twitter"></i></a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title uppercase">Download</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://getfedora.org/en/workstation/download">Get Fedora Workstation</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/server/download">Get Fedora Server</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/atomic/download">Get Fedora Atomic</a></dd>
|
||||
<dd><a href="https://spins.fedoraproject.org">Fedora Spins</a></dd>
|
||||
<dd><a href="https://labs.fedoraproject.org">Fedora Labs</a></dd>
|
||||
<dd><a href="https://arm.fedoraproject.org">Fedora ARM<span class="sup">®</span></a></dd>
|
||||
<dd><a href="https://alt.fedoraproject.org/">Alternative Downloads</a></dd>
|
||||
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">Support</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Communicating_and_getting_help">Get Help</a></dd>
|
||||
<dd><a href="https://ask.fedoraproject.org/">Ask Fedora</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Common_F27_bugs">Common Bugs</a></dd>
|
||||
<dd><a href="https://developer.fedoraproject.org/">Fedora Developer Portal</a></dd>
|
||||
<dd><a href="https://docs.fedoraproject.org/f27/install-guide/index.html">Installation Guide</a></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">Join</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Join">Join Fedora</a></dd>
|
||||
<dd><a href="http://fedoraplanet.org">Planet Fedora</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/SIGs">Fedora SIGs</a></dd>
|
||||
<dd><a href="https://admin.fedoraproject.org/accounts/">Fedora Account System</a></dd>
|
||||
<dd><a href="https://fedoracommunity.org/">Fedora Community</a></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- /row of widgets -->
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-2">
|
||||
<div class="widget-body">
|
||||
<a href="https://www.redhat.com/"><img class="rh-logo" src="../../../master/_images/redhat-logo.png" alt="Red Hat Logo" /></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-7">
|
||||
<div class="widget-body">
|
||||
<p class="sponsor">Fedora is sponsored by Red Hat.</p>
|
||||
<p class="sponsor"><a href="https://www.redhat.com/en/technologies/linux-platforms/articles/relationship-between-fedora-and-rhel">Learn more about the relationship between Red Hat and Fedora »</a></p>
|
||||
<p class="copy">© 2017 Red Hat, Inc. and others. Please send any comments or corrections to the <a href="https://pagure.io/fedora-docs/docs-fp-o">documentation team</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- /row of widgets -->
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
|
||||
<!-- Latest compiled and minified JavaScript -->
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
|
||||
<script src="../../../master/_javascripts/bootstrap-offcanvas.js" type="text/javascript"></script>
|
||||
<script type="text/javascript">
|
||||
/*<![CDATA[*/
|
||||
$(document).ready(function() {
|
||||
$("[id^='topicGroup']").on('show.bs.collapse', function (event) {
|
||||
if (!($(event.target).attr('id').match(/^topicSubGroup/))) {
|
||||
$(this).parent().find("[id^='tgSpan']").toggleClass("fa-angle-right fa-angle-down");
|
||||
}
|
||||
});
|
||||
$("[id^='topicGroup']").on('hide.bs.collapse', function (event) {
|
||||
if (!($(event.target).attr('id').match(/^topicSubGroup/))) {
|
||||
$(this).parent().find("[id^='tgSpan']").toggleClass("fa-angle-right fa-angle-down");
|
||||
}
|
||||
});
|
||||
$("[id^='topicSubGroup']").on('show.bs.collapse', function () {
|
||||
$(this).parent().find("[id^='sgSpan']").toggleClass("fa-caret-right fa-caret-down");
|
||||
});
|
||||
$("[id^='topicSubGroup']").on('hide.bs.collapse', function () {
|
||||
$(this).parent().find("[id^='sgSpan']").toggleClass("fa-caret-right fa-caret-down");
|
||||
});
|
||||
});
|
||||
/*]]>*/
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -1,702 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta content="IE=edge" http-equiv="X-UA-Compatible">
|
||||
<meta content="width=device-width, initial-scale=1.0" name="viewport">
|
||||
<title>Defensive Coding Guide | Defensive Coding Guide | Specific Programming Tasks | Processes</title>
|
||||
|
||||
<!-- Bootstrap -->
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap-theme.min.css">
|
||||
|
||||
<!-- Overpass Font -->
|
||||
<link rel="stylesheet" href="https://overpass-30e2.kxcdn.com/overpass.css">
|
||||
|
||||
<link href="../../../master/_stylesheets/asciibinder.css" rel="stylesheet" />
|
||||
|
||||
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
|
||||
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
|
||||
<!--[if lt IE 9]>
|
||||
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
|
||||
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
|
||||
<![endif]-->
|
||||
|
||||
<link href="../../../master/_images/favicon32x32.png" rel="shortcut icon" type="text/css">
|
||||
<!--[if IE]><link rel="shortcut icon" href="../../../master/_images/favicon.ico"><![endif]-->
|
||||
<meta content="AsciiBinder" name="application-name">
|
||||
</head>
|
||||
<body>
|
||||
<div class="navbar navbar-default" role="navigation">
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-header">
|
||||
<a class="navbar-brand" href="https://docs.fedoraproject.org/"><img alt="Fedora Documentation" src="../../../master/_images/fedora.svg"></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container">
|
||||
<p class="toggle-nav visible-xs pull-left">
|
||||
<button class="btn btn-default btn-sm" type="button" data-toggle="offcanvas">Toggle nav</button>
|
||||
</p>
|
||||
<ol class="breadcrumb">
|
||||
<li class="sitename">
|
||||
<a href="../../../index.html">Home</a>
|
||||
</li>
|
||||
<li class="hidden-xs active">
|
||||
<a href="../../en-US/index.html">Defensive Coding Guide </a>
|
||||
</li>
|
||||
<li class="hidden-xs active">
|
||||
<a href="../../en-US/index.html">Defensive Coding Guide</a>
|
||||
</li>
|
||||
<li class="hidden-xs active"><a href="../../en-US/tasks/Tasks-Library_Design.html">Specific Programming Tasks</a></li>
|
||||
<li class="hidden-xs active">
|
||||
Processes
|
||||
</li>
|
||||
</ol>
|
||||
<div class="row row-offcanvas row-offcanvas-left">
|
||||
<div class="col-xs-8 col-sm-3 col-md-3 sidebar sidebar-offcanvas">
|
||||
<ul class="nav nav-sidebar">
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicGroup0">
|
||||
<span id="tgSpan0" class="fa fa-angle-down"></span>Defensive Coding Guide
|
||||
</a>
|
||||
<ul id="topicGroup0" class="collapse in list-unstyled">
|
||||
<li><a class="" href="../../en-US/index.html">Book Information</a></li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-1">
|
||||
<span id="sgSpan-0-1" class="fa fa-caret-right"></span> Programming Languages
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-1" class="nav-tertiary list-unstyled collapse">
|
||||
<li><a class="" href="../../en-US/programming-languages/C.html">The C Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/CXX.html">The C++ Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Java.html">The Java Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Python.html">The Python Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Shell.html">Shell Programming and bash</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Go.html">The Go Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Vala.html">The Vala Programming Language</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-2">
|
||||
<span id="sgSpan-0-2" class="fa fa-caret-down"></span> Specific Programming Tasks
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-2" class="nav-tertiary list-unstyled collapse in">
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Library_Design.html">Library Design</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Descriptors.html">File Descriptor Management</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-File_System.html">File System Manipulation</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Temporary_Files.html">Temporary Files</a></li>
|
||||
<li><a class=" active" href="../../en-US/tasks/Tasks-Processes.html">Processes</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Serialization.html">Serialization and Deserialization</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Cryptography.html">Cryptography</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Packaging.html">RPM Packaging</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-3">
|
||||
<span id="sgSpan-0-3" class="fa fa-caret-right"></span> Implementing Security Features
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-3" class="nav-tertiary list-unstyled collapse">
|
||||
<li><a class="" href="../../en-US/features/Features-Authentication.html">Authentication and Authorization</a></li>
|
||||
<li><a class="" href="../../en-US/features/Features-TLS.html">Transport Layer Security (TLS)</a></li>
|
||||
<li><a class="" href="../../en-US/features/Features-HSM.html">Hardware Security Modules and Smart Cards</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="" href="../../en-US/Revision_History.html">Revision History</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-9 col-md-9 main">
|
||||
<div class="page-header">
|
||||
<h2>Processes</h2>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="sect-Defensive_Coding-Tasks-Processes-Creation"><a class="anchor" href="#sect-Defensive_Coding-Tasks-Processes-Creation"></a>Creating Safe Processes</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>This section describes how to create new child processes in a
|
||||
safe manner. In addition to the concerns addressed below, there
|
||||
is the possibility of file descriptor leaks, see <a href="#sect-Defensive_Coding-Tasks-Descriptors-Child_Processes">[sect-Defensive_Coding-Tasks-Descriptors-Child_Processes]</a>.</p>
|
||||
</div>
|
||||
<div class="sect2">
|
||||
<h3 id="obtaining-the-program-path-and-the-command-line-template"><a class="anchor" href="#obtaining-the-program-path-and-the-command-line-template"></a>Obtaining the Program Path and the Command-line Template</h3>
|
||||
<div class="paragraph">
|
||||
<p>The name and path to the program being invoked should be
|
||||
hard-coded or controlled by a static configuration file stored
|
||||
at a fixed location (at an file system absolute path). The
|
||||
same applies to the template for generating the command line.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>The configured program name should be an absolute path. If it
|
||||
is a relative path, the contents of the <code>PATH</code>
|
||||
must be obtained in a secure manner (see <a href="#sect-Defensive_Coding-Tasks-secure_getenv">Accessing Environment Variables</a>).
|
||||
If the <code>PATH</code> variable is not set or untrusted,
|
||||
the safe default <code>/bin:/usr/bin</code> must be
|
||||
used.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>If too much flexibility is provided here, it may allow
|
||||
invocation of arbitrary programs without proper authorization.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect2">
|
||||
<h3 id="sect-Defensive_Coding-Tasks-Processes-execve"><a class="anchor" href="#sect-Defensive_Coding-Tasks-Processes-execve"></a>Bypassing the Shell</h3>
|
||||
<div class="paragraph">
|
||||
<p>Child processes should be created without involving the system
|
||||
shell.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>For C/C++, <code>system</code> should not be used.
|
||||
The <code>posix_spawn</code> function can be used
|
||||
instead, or a combination <code>fork</code> and
|
||||
<code>execve</code>. (In some cases, it may be
|
||||
preferable to use <code>vfork</code> or the
|
||||
Linux-specific <code>clone</code> system call instead
|
||||
of <code>fork</code>.)</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>In Python, the <code>subprocess</code> module bypasses
|
||||
the shell by default (when the <code>shell</code>
|
||||
keyword argument is not set to true).
|
||||
<code>os.system</code> should not be used.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>The Java class <code>java.lang.ProcessBuilder</code> can be
|
||||
used to create subprocesses without interference from the
|
||||
system shell.</p>
|
||||
</div>
|
||||
<div class="admonitionblock important">
|
||||
<table>
|
||||
<tr>
|
||||
<td class="icon">
|
||||
<i class="fa icon-important" title="Important"></i>
|
||||
</td>
|
||||
<td class="content">
|
||||
<div class="title">Portability notice</div>
|
||||
<div class="paragraph">
|
||||
<p>On Windows, there is no argument vector, only a single
|
||||
argument string. Each application is responsible for parsing
|
||||
this string into an argument vector. There is considerable
|
||||
variance among the quoting style recognized by applications.
|
||||
Some of them expand shell wildcards, others do not. Extensive
|
||||
application-specific testing is required to make this secure.</p>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Note that some common applications (notably
|
||||
<strong class="application">ssh</strong>) unconditionally introduce the
|
||||
use of a shell, even if invoked directly without a shell. It is
|
||||
difficult to use these applications in a secure manner. In this
|
||||
case, untrusted data should be supplied by other means. For
|
||||
example, standard input could be used, instead of the command
|
||||
line.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect2">
|
||||
<h3 id="sect-Defensive_Coding-Tasks-Processes-environ"><a class="anchor" href="#sect-Defensive_Coding-Tasks-Processes-environ"></a>Specifying the Process Environment</h3>
|
||||
<div class="paragraph">
|
||||
<p>Child processes should be created with a minimal set of
|
||||
environment variables. This is absolutely essential if there
|
||||
is a trust transition involved, either when the parent process
|
||||
was created, or during the creation of the child process.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>In C/C++, the environment should be constructed as an array of
|
||||
strings and passed as the <code>envp</code> argument to
|
||||
<code>posix_spawn</code> or <code>execve</code>.
|
||||
The functions <code>setenv</code>,
|
||||
<code>unsetenv</code> and <code>putenv</code>
|
||||
should not be used. They are not thread-safe and suffer from
|
||||
memory leaks.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Python programs need to specify a <code>dict</code> for
|
||||
the the <code>env</code> argument of the
|
||||
<code>subprocess.Popen</code> constructor.
|
||||
The Java class <code>java.lang.ProcessBuilder</code>
|
||||
provides a <code>environment()</code> method,
|
||||
which returns a map that can be manipulated.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>The following list provides guidelines for selecting the set
|
||||
of environment variables passed to the child process.</p>
|
||||
</div>
|
||||
<div class="ulist">
|
||||
<ul>
|
||||
<li>
|
||||
<p><code>PATH</code> should be initialized to
|
||||
<code>/bin:/usr/bin</code>.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><code>USER</code> and <code>HOME</code> can be inhereted
|
||||
from the parent process environment, or they can be
|
||||
initialized from the <code>pwent</code> structure
|
||||
for the user.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>The <code>DISPLAY</code> and <code>XAUTHORITY</code>
|
||||
variables should be passed to the subprocess if it is an X
|
||||
program. Note that this will typically not work across trust
|
||||
boundaries because <code>XAUTHORITY</code> refers to a file
|
||||
with <code>0600</code> permissions.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>The location-related environment variables
|
||||
<code>LANG</code>, <code>LANGUAGE</code>,
|
||||
<code>LC_ADDRESS</code>, <code>LC_ALL</code>,
|
||||
<code>LC_COLLATE</code>, <code>LC_CTYPE</code>,
|
||||
<code>LC_IDENTIFICATION</code>,
|
||||
<code>LC_MEASUREMENT</code>, <code>LC_MESSAGES</code>,
|
||||
<code>LC_MONETARY</code>, <code>LC_NAME</code>,
|
||||
<code>LC_NUMERIC</code>, <code>LC_PAPER</code>,
|
||||
<code>LC_TELEPHONE</code> and <code>LC_TIME</code>
|
||||
can be passed to the subprocess if present.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>The called process may need application-specific
|
||||
environment variables, for example for passing passwords.
|
||||
(See <a href="#sect-Defensive_Coding-Tasks-Processes-Command_Line_Visibility">Passing Secrets to Subprocesses</a>.)</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>All other environment variables should be dropped. Names
|
||||
for new environment variables should not be accepted from
|
||||
untrusted sources.</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect2">
|
||||
<h3 id="robust-argument-list-processing"><a class="anchor" href="#robust-argument-list-processing"></a>Robust Argument List Processing</h3>
|
||||
<div class="paragraph">
|
||||
<p>When invoking a program, it is sometimes necessary to include
|
||||
data from untrusted sources. Such data should be checked
|
||||
against embedded <code>NUL</code> characters because the
|
||||
system APIs will silently truncate argument strings at the first
|
||||
<code>NUL</code> character.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>The following recommendations assume that the program being
|
||||
invoked uses GNU-style option processing using
|
||||
<code>getopt_long</code>. This convention is widely
|
||||
used, but it is just that, and individual programs might
|
||||
interpret a command line in a different way.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>If the untrusted data has to go into an option, use the
|
||||
<code>--option-name=VALUE</code> syntax, placing the
|
||||
option and its value into the same command line argument.
|
||||
This avoids any potential confusion if the data starts with
|
||||
<code>-</code>.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>For positional arguments, terminate the option list with a
|
||||
single <code class="option">--</code> marker after the last option, and
|
||||
include the data at the right position. The
|
||||
<code class="option">--</code> marker terminates option processing, and
|
||||
the data will not be treated as an option even if it starts
|
||||
with a dash.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect2">
|
||||
<h3 id="sect-Defensive_Coding-Tasks-Processes-Command_Line_Visibility"><a class="anchor" href="#sect-Defensive_Coding-Tasks-Processes-Command_Line_Visibility"></a>Passing Secrets to Subprocesses</h3>
|
||||
<div class="paragraph">
|
||||
<p>The command line (the name of the program and its argument) of
|
||||
a running process is traditionally available to all local
|
||||
users. The called program can overwrite this information, but
|
||||
only after it has run for a bit of time, during which the
|
||||
information may have been read by other processes. However,
|
||||
on Linux, the process environment is restricted to the user
|
||||
who runs the process. Therefore, if you need a convenient way
|
||||
to pass a password to a child process, use an environment
|
||||
variable, and not a command line argument. (See <a href="#sect-Defensive_Coding-Tasks-Processes-environ">Specifying the Process Environment</a>.)</p>
|
||||
</div>
|
||||
<div class="admonitionblock important">
|
||||
<table>
|
||||
<tr>
|
||||
<td class="icon">
|
||||
<i class="fa icon-important" title="Important"></i>
|
||||
</td>
|
||||
<td class="content">
|
||||
<div class="title">Portability notice</div>
|
||||
<div class="paragraph">
|
||||
<p>On some UNIX-like systems (notably Solaris), environment
|
||||
variables can be read by any system user, just like command
|
||||
lines.</p>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>If the environment-based approach cannot be used due to
|
||||
portability concerns, the data can be passed on standard
|
||||
input. Some programs (notably <strong class="application">gpg</strong>)
|
||||
use special file descriptors whose numbers are specified on
|
||||
the command line. Temporary files are an option as well, but
|
||||
they might give digital forensics access to sensitive data
|
||||
(such as passphrases) because it is difficult to safely delete
|
||||
them in all cases.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="handling-child-process-termination"><a class="anchor" href="#handling-child-process-termination"></a>Handling Child Process Termination</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>When child processes terminate, the parent process is signalled.
|
||||
A stub of the terminated processes (a
|
||||
<strong>zombie</strong>, shown as
|
||||
<code><defunct></code> by
|
||||
<strong class="application">ps</strong>) is kept around until the status
|
||||
information is collected (<strong>reaped</strong>) by the
|
||||
parent process. Over the years, several interfaces for this
|
||||
have been invented:</p>
|
||||
</div>
|
||||
<div class="ulist">
|
||||
<ul>
|
||||
<li>
|
||||
<p>The parent process calls <code>wait</code>,
|
||||
<code>waitpid</code>, <code>waitid</code>,
|
||||
<code>wait3</code> or <code>wait4</code>,
|
||||
without specifying a process ID. This will deliver any
|
||||
matching process ID. This approach is typically used from
|
||||
within event loops.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>The parent process calls <code>waitpid</code>,
|
||||
<code>waitid</code>, or <code>wait4</code>,
|
||||
with a specific process ID. Only data for the specific
|
||||
process ID is returned. This is typically used in code
|
||||
which spawns a single subprocess in a synchronous manner.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>The parent process installs a handler for the
|
||||
<code>SIGCHLD</code> signal, using
|
||||
<code>sigaction</code>, and specifies to the
|
||||
<code>SA_NOCLDWAIT</code> flag.
|
||||
This approach could be used by event loops as well.</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>None of these approaches can be used to wait for child process
|
||||
terminated in a completely thread-safe manner. The parent
|
||||
process might execute an event loop in another thread, which
|
||||
could pick up the termination signal. This means that libraries
|
||||
typically cannot make free use of child processes (for example,
|
||||
to run problematic code with reduced privileges in a separate
|
||||
address space).</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>At the moment, the parent process should explicitly wait for
|
||||
termination of the child process using
|
||||
<code>waitpid</code> or <code>waitid</code>,
|
||||
and hope that the status is not collected by an event loop
|
||||
first.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="code-suid-code-code-sgid-code-processes"><a class="anchor" href="#code-suid-code-code-sgid-code-processes"></a><code>SUID</code>/<code>SGID</code> processes</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>Programs can be marked in the file system to indicate to the
|
||||
kernel that a trust transition should happen if the program is
|
||||
run. The <code>SUID</code> file permission bit indicates
|
||||
that an executable should run with the effective user ID equal
|
||||
to the owner of the executable file. Similarly, with the
|
||||
<code>SGID</code> bit, the effective group ID is set to
|
||||
the group of the executable file.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Linux supports <strong>fscaps</strong>, which can grant
|
||||
additional capabilities to a process in a finer-grained manner.
|
||||
Additional mechanisms can be provided by loadable security
|
||||
modules.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>When such a trust transition has happened, the process runs in a
|
||||
potentially hostile environment. Additional care is necessary
|
||||
not to rely on any untrusted information. These concerns also
|
||||
apply to libraries which can be linked into such processes.</p>
|
||||
</div>
|
||||
<div class="sect2">
|
||||
<h3 id="sect-Defensive_Coding-Tasks-secure_getenv"><a class="anchor" href="#sect-Defensive_Coding-Tasks-secure_getenv"></a>Accessing Environment Variables</h3>
|
||||
<div class="paragraph">
|
||||
<p>The following steps are required so that a program does not
|
||||
accidentally pick up untrusted data from environment
|
||||
variables.</p>
|
||||
</div>
|
||||
<div class="ulist">
|
||||
<ul>
|
||||
<li>
|
||||
<p>Compile your C/C++ sources with <code>-D_GNU_SOURCE</code>.
|
||||
The Autoconf macro <code>AC_GNU_SOURCE</code> ensures this.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Check for the presence of the <code>secure_getenv</code>
|
||||
and <code><em>secure_getenv</code> function. The Autoconf
|
||||
directive <code>AC_CHECK_FUNCS([</em>secure_getenv secure_getenv])</code>
|
||||
performs these checks.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Arrange for a proper definition of the
|
||||
<code>secure_getenv</code> function. See <a href="#ex-Defensive_Coding-Tasks-secure_getenv">Obtaining a definition for <code>secure_getenv</code></a>.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Use <code>secure_getenv</code> instead of
|
||||
<code>getenv</code> to obtain the value of critical
|
||||
environment variables. <code>secure_getenv</code>
|
||||
will pretend the variable has not bee set if the process
|
||||
environment is not trusted.</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Critical environment variables are debugging flags,
|
||||
configuration file locations, plug-in and log file locations,
|
||||
and anything else that might be used to bypass security
|
||||
restrictions or cause a privileged process to behave in an
|
||||
unexpected way.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Either the <code>secure_getenv</code> function or the
|
||||
<code>__secure_getenv</code> is available from GNU libc.</p>
|
||||
</div>
|
||||
<div id="ex-Defensive_Coding-Tasks-secure_getenv" class="exampleblock">
|
||||
<div class="title">Example 1. Obtaining a definition for <code>secure_getenv</code></div>
|
||||
<div class="content">
|
||||
<div class="listingblock">
|
||||
<div class="content">
|
||||
<pre class="CodeRay highlight"><code data-lang="c"><span style="color:#579">#include</span> <span style="color:#B44;font-weight:bold"><stdlib.h></span>
|
||||
|
||||
<span style="color:#579">#ifndef</span> HAVE_SECURE_GETENV
|
||||
<span style="color:#579"># ifdef</span> HAVE__SECURE_GETENV
|
||||
<span style="color:#579"># define</span> secure_getenv __secure_getenv
|
||||
<span style="color:#579"># else</span>
|
||||
<span style="color:#579"># error</span> neither secure_getenv nor __secure_getenv are available
|
||||
<span style="color:#579"># endif</span>
|
||||
<span style="color:#579">#endif</span></code></pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="sect-Defensive_Coding-Tasks-Processes-Daemons"><a class="anchor" href="#sect-Defensive_Coding-Tasks-Processes-Daemons"></a>Daemons</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>Background processes providing system services
|
||||
(<strong>daemons</strong>) need to decouple themselves from
|
||||
the controlling terminal and the parent process environment:</p>
|
||||
</div>
|
||||
<div class="ulist">
|
||||
<ul>
|
||||
<li>
|
||||
<p>Fork.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>In the child process, call <code>setsid</code>. The
|
||||
parent process can simply exit (using
|
||||
<code>_exit</code>, to avoid running clean-up
|
||||
actions twice).</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>In the child process, fork again. Processing continues in
|
||||
the child process. Again, the parent process should just
|
||||
exit.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Replace the descriptors 0, 1, 2 with a descriptor for
|
||||
<code>/dev/null</code>. Logging should be
|
||||
redirected to <strong class="application">syslog</strong>.</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Older instructions for creating daemon processes recommended a
|
||||
call to <code>umask(0)</code>. This is risky because it
|
||||
often leads to world-writable files and directories, resulting
|
||||
in security vulnerabilities such as arbitrary process
|
||||
termination by untrusted local users, or log file truncation.
|
||||
If the <strong>umask</strong> needs setting, a restrictive
|
||||
value such as <code>027</code> or <code>077</code>
|
||||
is recommended.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Other aspects of the process environment may have to changed as
|
||||
well (environment variables, signal handler disposition).</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>It is increasingly common that server processes do not run as
|
||||
background processes, but as regular foreground process under a
|
||||
supervising master process (such as
|
||||
<strong class="application">systemd</strong>). Server processes should
|
||||
offer a command line option which disables forking and
|
||||
replacement of the standard output and standard error streams.
|
||||
Such an option is also useful for debugging.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="semantics-of-command-line-arguments"><a class="anchor" href="#semantics-of-command-line-arguments"></a>Semantics of Command-line Arguments</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>After process creation and option processing, it is up to the
|
||||
child process to interpret the arguments. Arguments can be
|
||||
file names, host names, or URLs, and many other things. URLs
|
||||
can refer to the local network, some server on the Internet,
|
||||
or to the local file system. Some applications even accept
|
||||
arbitrary code in arguments (for example,
|
||||
<strong class="application">python</strong> with the
|
||||
<code class="option">-c</code> option).</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Similar concerns apply to environment variables, the contents
|
||||
of the current directory and its subdirectories.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Consequently, careful analysis is required if it is safe to
|
||||
pass untrusted data to another program.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="sect-Defensive_Coding-Tasks-Processes-Fork-Parallel"><a class="anchor" href="#sect-Defensive_Coding-Tasks-Processes-Fork-Parallel"></a><code>fork</code> as a Primitive for Parallelism</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>A call to <code>fork</code> which is not immediately
|
||||
followed by a call to <code>execve</code> (perhaps after
|
||||
rearranging and closing file descriptors) is typically unsafe,
|
||||
especially from a library which does not control the state of
|
||||
the entire process. Such use of <code>fork</code>
|
||||
should be replaced with proper child processes or threads.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="bottom" class="text-muted py-3" >
|
||||
<div class="foot">
|
||||
<div class="container">
|
||||
<div class="row footerlinks">
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">About</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Overview">About Fedora</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/sponsors">Sponsors</a></dd>
|
||||
<dd><a href="https://fedoramagazine.org">Fedora Magazine</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Legal:Main#Legal">Legal</a></dd>
|
||||
</dl>
|
||||
<ul class="list-inline">
|
||||
<li>
|
||||
<a href="https://www.facebook.com/TheFedoraProject" class="btn-social btn-outline"><i class="fa fa-fw fa-facebook"></i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://plus.google.com/112917221531140868607" class="btn-social btn-outline"><i class="fa fa-fw fa-google-plus"></i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://twitter.com/fedora" class="btn-social btn-outline"><i class="fa fa-fw fa-twitter"></i></a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title uppercase">Download</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://getfedora.org/en/workstation/download">Get Fedora Workstation</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/server/download">Get Fedora Server</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/atomic/download">Get Fedora Atomic</a></dd>
|
||||
<dd><a href="https://spins.fedoraproject.org">Fedora Spins</a></dd>
|
||||
<dd><a href="https://labs.fedoraproject.org">Fedora Labs</a></dd>
|
||||
<dd><a href="https://arm.fedoraproject.org">Fedora ARM<span class="sup">®</span></a></dd>
|
||||
<dd><a href="https://alt.fedoraproject.org/">Alternative Downloads</a></dd>
|
||||
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">Support</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Communicating_and_getting_help">Get Help</a></dd>
|
||||
<dd><a href="https://ask.fedoraproject.org/">Ask Fedora</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Common_F27_bugs">Common Bugs</a></dd>
|
||||
<dd><a href="https://developer.fedoraproject.org/">Fedora Developer Portal</a></dd>
|
||||
<dd><a href="https://docs.fedoraproject.org/f27/install-guide/index.html">Installation Guide</a></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">Join</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Join">Join Fedora</a></dd>
|
||||
<dd><a href="http://fedoraplanet.org">Planet Fedora</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/SIGs">Fedora SIGs</a></dd>
|
||||
<dd><a href="https://admin.fedoraproject.org/accounts/">Fedora Account System</a></dd>
|
||||
<dd><a href="https://fedoracommunity.org/">Fedora Community</a></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- /row of widgets -->
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-2">
|
||||
<div class="widget-body">
|
||||
<a href="https://www.redhat.com/"><img class="rh-logo" src="../../../master/_images/redhat-logo.png" alt="Red Hat Logo" /></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-7">
|
||||
<div class="widget-body">
|
||||
<p class="sponsor">Fedora is sponsored by Red Hat.</p>
|
||||
<p class="sponsor"><a href="https://www.redhat.com/en/technologies/linux-platforms/articles/relationship-between-fedora-and-rhel">Learn more about the relationship between Red Hat and Fedora »</a></p>
|
||||
<p class="copy">© 2017 Red Hat, Inc. and others. Please send any comments or corrections to the <a href="https://pagure.io/fedora-docs/docs-fp-o">documentation team</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- /row of widgets -->
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
|
||||
<!-- Latest compiled and minified JavaScript -->
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
|
||||
<script src="../../../master/_javascripts/bootstrap-offcanvas.js" type="text/javascript"></script>
|
||||
<script type="text/javascript">
|
||||
/*<![CDATA[*/
|
||||
$(document).ready(function() {
|
||||
$("[id^='topicGroup']").on('show.bs.collapse', function (event) {
|
||||
if (!($(event.target).attr('id').match(/^topicSubGroup/))) {
|
||||
$(this).parent().find("[id^='tgSpan']").toggleClass("fa-angle-right fa-angle-down");
|
||||
}
|
||||
});
|
||||
$("[id^='topicGroup']").on('hide.bs.collapse', function (event) {
|
||||
if (!($(event.target).attr('id').match(/^topicSubGroup/))) {
|
||||
$(this).parent().find("[id^='tgSpan']").toggleClass("fa-angle-right fa-angle-down");
|
||||
}
|
||||
});
|
||||
$("[id^='topicSubGroup']").on('show.bs.collapse', function () {
|
||||
$(this).parent().find("[id^='sgSpan']").toggleClass("fa-caret-right fa-caret-down");
|
||||
});
|
||||
$("[id^='topicSubGroup']").on('hide.bs.collapse', function () {
|
||||
$(this).parent().find("[id^='sgSpan']").toggleClass("fa-caret-right fa-caret-down");
|
||||
});
|
||||
});
|
||||
/*]]>*/
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -1,472 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta content="IE=edge" http-equiv="X-UA-Compatible">
|
||||
<meta content="width=device-width, initial-scale=1.0" name="viewport">
|
||||
<title>Defensive Coding Guide | Defensive Coding Guide | Specific Programming Tasks | Temporary Files</title>
|
||||
|
||||
<!-- Bootstrap -->
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap-theme.min.css">
|
||||
|
||||
<!-- Overpass Font -->
|
||||
<link rel="stylesheet" href="https://overpass-30e2.kxcdn.com/overpass.css">
|
||||
|
||||
<link href="../../../master/_stylesheets/asciibinder.css" rel="stylesheet" />
|
||||
|
||||
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
|
||||
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
|
||||
<!--[if lt IE 9]>
|
||||
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
|
||||
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
|
||||
<![endif]-->
|
||||
|
||||
<link href="../../../master/_images/favicon32x32.png" rel="shortcut icon" type="text/css">
|
||||
<!--[if IE]><link rel="shortcut icon" href="../../../master/_images/favicon.ico"><![endif]-->
|
||||
<meta content="AsciiBinder" name="application-name">
|
||||
</head>
|
||||
<body>
|
||||
<div class="navbar navbar-default" role="navigation">
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-header">
|
||||
<a class="navbar-brand" href="https://docs.fedoraproject.org/"><img alt="Fedora Documentation" src="../../../master/_images/fedora.svg"></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container">
|
||||
<p class="toggle-nav visible-xs pull-left">
|
||||
<button class="btn btn-default btn-sm" type="button" data-toggle="offcanvas">Toggle nav</button>
|
||||
</p>
|
||||
<ol class="breadcrumb">
|
||||
<li class="sitename">
|
||||
<a href="../../../index.html">Home</a>
|
||||
</li>
|
||||
<li class="hidden-xs active">
|
||||
<a href="../../en-US/index.html">Defensive Coding Guide </a>
|
||||
</li>
|
||||
<li class="hidden-xs active">
|
||||
<a href="../../en-US/index.html">Defensive Coding Guide</a>
|
||||
</li>
|
||||
<li class="hidden-xs active"><a href="../../en-US/tasks/Tasks-Library_Design.html">Specific Programming Tasks</a></li>
|
||||
<li class="hidden-xs active">
|
||||
Temporary Files
|
||||
</li>
|
||||
</ol>
|
||||
<div class="row row-offcanvas row-offcanvas-left">
|
||||
<div class="col-xs-8 col-sm-3 col-md-3 sidebar sidebar-offcanvas">
|
||||
<ul class="nav nav-sidebar">
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicGroup0">
|
||||
<span id="tgSpan0" class="fa fa-angle-down"></span>Defensive Coding Guide
|
||||
</a>
|
||||
<ul id="topicGroup0" class="collapse in list-unstyled">
|
||||
<li><a class="" href="../../en-US/index.html">Book Information</a></li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-1">
|
||||
<span id="sgSpan-0-1" class="fa fa-caret-right"></span> Programming Languages
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-1" class="nav-tertiary list-unstyled collapse">
|
||||
<li><a class="" href="../../en-US/programming-languages/C.html">The C Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/CXX.html">The C++ Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Java.html">The Java Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Python.html">The Python Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Shell.html">Shell Programming and bash</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Go.html">The Go Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Vala.html">The Vala Programming Language</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-2">
|
||||
<span id="sgSpan-0-2" class="fa fa-caret-down"></span> Specific Programming Tasks
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-2" class="nav-tertiary list-unstyled collapse in">
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Library_Design.html">Library Design</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Descriptors.html">File Descriptor Management</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-File_System.html">File System Manipulation</a></li>
|
||||
<li><a class=" active" href="../../en-US/tasks/Tasks-Temporary_Files.html">Temporary Files</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Processes.html">Processes</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Serialization.html">Serialization and Deserialization</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Cryptography.html">Cryptography</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Packaging.html">RPM Packaging</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-3">
|
||||
<span id="sgSpan-0-3" class="fa fa-caret-right"></span> Implementing Security Features
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-3" class="nav-tertiary list-unstyled collapse">
|
||||
<li><a class="" href="../../en-US/features/Features-Authentication.html">Authentication and Authorization</a></li>
|
||||
<li><a class="" href="../../en-US/features/Features-TLS.html">Transport Layer Security (TLS)</a></li>
|
||||
<li><a class="" href="../../en-US/features/Features-HSM.html">Hardware Security Modules and Smart Cards</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="" href="../../en-US/Revision_History.html">Revision History</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-9 col-md-9 main">
|
||||
<div class="page-header">
|
||||
<h2>Temporary Files</h2>
|
||||
</div>
|
||||
<div id="preamble">
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>In this chapter, we describe how to create temporary files and
|
||||
directories, how to remove them, and how to work with programs
|
||||
which do not create files in ways that are safe with a shared
|
||||
directory for temporary files. General file system manipulation
|
||||
is treated in a separate chapter, <a href="#chap-Defensive_Coding-Tasks-File_System">[chap-Defensive_Coding-Tasks-File_System]</a>.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Secure creation of temporary files has four different aspects.</p>
|
||||
</div>
|
||||
<div class="ulist">
|
||||
<ul>
|
||||
<li>
|
||||
<p>The location of the directory for temporary files must be
|
||||
obtained in a secure manner (that is, untrusted environment
|
||||
variables must be ignored, see <a href="#sect-Defensive_Coding-Tasks-secure_getenv">[sect-Defensive_Coding-Tasks-secure_getenv]</a>).</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>A new file must be created. Reusing an existing file must be
|
||||
avoided (the <code>/tmp</code> race
|
||||
condition). This is tricky because traditionally, system-wide
|
||||
temporary directories shared by all users are used.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>The file must be created in a way that makes it impossible for
|
||||
other users to open it.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>The descriptor for the temporary file should not leak to
|
||||
subprocesses.</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>All functions mentioned below will take care of these aspects.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Traditionally, temporary files are often used to reduce memory
|
||||
usage of programs. More and more systems use RAM-based file
|
||||
systems such as <code>tmpfs</code> for storing temporary
|
||||
files, to increase performance and decrease wear on Flash storage.
|
||||
As a result, spooling data to temporary files does not result in
|
||||
any memory savings, and the related complexity can be avoided if
|
||||
the data is kept in process memory.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="chap-Defensive_Coding-Tasks-Temporary_Files-Location"><a class="anchor" href="#chap-Defensive_Coding-Tasks-Temporary_Files-Location"></a>Obtaining the Location of Temporary Directory</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>Some functions below need the location of a directory which
|
||||
stores temporary files. For C/C++ programs, use the following
|
||||
steps to obtain that directory:</p>
|
||||
</div>
|
||||
<div class="ulist">
|
||||
<ul>
|
||||
<li>
|
||||
<p>Use <code>secure_getenv</code> to obtain the value
|
||||
of the <code>TMPDIR</code> environment variable. If
|
||||
it is set, convert the path to a fully-resolved absolute
|
||||
path, using <code>realpath(path, NULL)</code>. Check
|
||||
if the new path refers to a directory and is writeable. In
|
||||
this case, use it as the temporary directory.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Fall back to <code>/tmp</code>.</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>In Python, you can use the <code>tempfile.tempdir</code>
|
||||
variable.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Java does not support SUID/SGID programs, so you can use the
|
||||
<code>java.lang.System.getenv(String)</code> method to
|
||||
obtain the value of the <code>TMPDIR</code> environment
|
||||
variable, and follow the two steps described above. (Java’s
|
||||
default directory selection does not honor
|
||||
<code>TMPDIR</code>.)</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="named-temporary-files"><a class="anchor" href="#named-temporary-files"></a>Named Temporary Files</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>The <code>mkostemp</code> function creates a named
|
||||
temporary file. You should specify the
|
||||
<code>O_CLOEXEC</code> flag to avoid file descriptor leaks
|
||||
to subprocesses. (Applications which do not use multiple threads
|
||||
can also use <code>mkstemp</code>, but libraries should
|
||||
use <code>mkostemp</code>.) For determining the
|
||||
directory part of the file name pattern, see <a href="#chap-Defensive_Coding-Tasks-Temporary_Files-Location">Obtaining the Location of Temporary Directory</a>.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>The file is not removed automatically. It is not safe to rename
|
||||
or delete the file before processing, or transform the name in
|
||||
any way (for example, by adding a file extension). If you need
|
||||
multiple temporary files, call <code>mkostemp</code>
|
||||
multiple times. Do not create additional file names derived
|
||||
from the name provided by a previous
|
||||
<code>mkostemp</code> call. However, it is safe to close
|
||||
the descriptor returned by <code>mkostemp</code> and
|
||||
reopen the file using the generated name.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>The Python class <code>tempfile.NamedTemporaryFile</code>
|
||||
provides similar functionality, except that the file is deleted
|
||||
automatically by default. Note that you may have to use the
|
||||
<code>file</code> attribute to obtain the actual file
|
||||
object because some programming interfaces cannot deal with
|
||||
file-like objects. The C function <code>mkostemp</code>
|
||||
is also available as <code>tempfile.mkstemp</code>.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>In Java, you can use the
|
||||
<code>java.io.File.createTempFile(String, String,
|
||||
File)</code> function, using the temporary file location
|
||||
determined according to <a href="#chap-Defensive_Coding-Tasks-Temporary_Files-Location">Obtaining the Location of Temporary Directory</a>.
|
||||
Do not use <code>java.io.File.deleteOnExit()</code> to
|
||||
delete temporary files, and do not register a shutdown hook for
|
||||
each temporary file you create. In both cases, the deletion
|
||||
hint cannot be removed from the system if you delete the
|
||||
temporary file prior to termination of the VM, causing a memory
|
||||
leak.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="temporary-files-without-names"><a class="anchor" href="#temporary-files-without-names"></a>Temporary Files without Names</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>The <code>tmpfile</code> function creates a temporary
|
||||
file and immediately deletes it, while keeping the file open.
|
||||
As a result, the file lacks a name and its space is deallocated
|
||||
as soon as the file descriptor is closed (including the implicit
|
||||
close when the process terminates). This avoids cluttering the
|
||||
temporary directory with orphaned files.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Alternatively, if the maximum size of the temporary file is
|
||||
known beforehand, the <code>fmemopen</code> function can
|
||||
be used to create a <code>FILE *</code> object which is
|
||||
backed by memory.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>In Python, unnamed temporary files are provided by the
|
||||
<code>tempfile.TemporaryFile</code> class, and the
|
||||
<code>tempfile.SpooledTemporaryFile</code> class provides
|
||||
a way to avoid creation of small temporary files.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Java does not support unnamed temporary files.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="chap-Defensive_Coding-Tasks-Temporary_Directory"><a class="anchor" href="#chap-Defensive_Coding-Tasks-Temporary_Directory"></a>Temporary Directories</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>The <code>mkdtemp</code> function can be used to create
|
||||
a temporary directory. (For determining the directory part of
|
||||
the file name pattern, see <a href="#chap-Defensive_Coding-Tasks-Temporary_Files-Location">Obtaining the Location of Temporary Directory</a>.)
|
||||
The directory is not automatically removed. In Python, this
|
||||
function is available as <code>tempfile.mkdtemp</code>.
|
||||
In Java 7, temporary directories can be created using the
|
||||
<code>java.nio.file.Files.createTempDirectory(Path, String,
|
||||
FileAttribute…​)</code> function.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>When creating files in the temporary directory, use
|
||||
automatically generated names, e.g., derived from a sequential
|
||||
counter. Files with externally provided names could be picked
|
||||
up in unexpected contexts, and crafted names could actually
|
||||
point outside of the tempoary directory (due to
|
||||
<strong>directory traversal</strong>).</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Removing a directory tree in a completely safe manner is
|
||||
complicated. Unless there are overriding performance concerns,
|
||||
the <strong class="application">rm</strong> program should be used, with
|
||||
the <code class="option">-rf</code> and <code class="option">--</code> options.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="compensating-for-unsafe-file-creation"><a class="anchor" href="#compensating-for-unsafe-file-creation"></a>Compensating for Unsafe File Creation</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>There are two ways to make a function or program which excepts a
|
||||
file name safe for use with temporary files. See
|
||||
<a href="#sect-Defensive_Coding-Tasks-Processes-Creation">[sect-Defensive_Coding-Tasks-Processes-Creation]</a>,
|
||||
for details on subprocess creation.</p>
|
||||
</div>
|
||||
<div class="ulist">
|
||||
<ul>
|
||||
<li>
|
||||
<p>Create a temporary directory and place the file there. If
|
||||
possible, run the program in a subprocess which uses the
|
||||
temporary directory as its current directory, with a
|
||||
restricted environment.
|
||||
Use generated names for all files in that temporary
|
||||
directory. (See <a href="#chap-Defensive_Coding-Tasks-Temporary_Directory">Temporary Directories</a>.)</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Create the temporary file and pass the generated file name
|
||||
to the function or program. This only works if the function
|
||||
or program can cope with a zero-length existing file. It is
|
||||
safe only under additional assumptions:</p>
|
||||
<div class="ulist">
|
||||
<ul>
|
||||
<li>
|
||||
<p>The function or program must not create additional files
|
||||
whose name is derived from the specified file name or
|
||||
are otherwise predictable.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>The function or program must not delete the file before
|
||||
processing it.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>It must not access any existing files in the same
|
||||
directory.</p>
|
||||
<div class="paragraph">
|
||||
<p>It is often difficult to check whether these additional
|
||||
assumptions are matched, therefore this approach is not
|
||||
recommended.</p>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="bottom" class="text-muted py-3" >
|
||||
<div class="foot">
|
||||
<div class="container">
|
||||
<div class="row footerlinks">
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">About</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Overview">About Fedora</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/sponsors">Sponsors</a></dd>
|
||||
<dd><a href="https://fedoramagazine.org">Fedora Magazine</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Legal:Main#Legal">Legal</a></dd>
|
||||
</dl>
|
||||
<ul class="list-inline">
|
||||
<li>
|
||||
<a href="https://www.facebook.com/TheFedoraProject" class="btn-social btn-outline"><i class="fa fa-fw fa-facebook"></i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://plus.google.com/112917221531140868607" class="btn-social btn-outline"><i class="fa fa-fw fa-google-plus"></i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://twitter.com/fedora" class="btn-social btn-outline"><i class="fa fa-fw fa-twitter"></i></a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title uppercase">Download</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://getfedora.org/en/workstation/download">Get Fedora Workstation</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/server/download">Get Fedora Server</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/atomic/download">Get Fedora Atomic</a></dd>
|
||||
<dd><a href="https://spins.fedoraproject.org">Fedora Spins</a></dd>
|
||||
<dd><a href="https://labs.fedoraproject.org">Fedora Labs</a></dd>
|
||||
<dd><a href="https://arm.fedoraproject.org">Fedora ARM<span class="sup">®</span></a></dd>
|
||||
<dd><a href="https://alt.fedoraproject.org/">Alternative Downloads</a></dd>
|
||||
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">Support</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Communicating_and_getting_help">Get Help</a></dd>
|
||||
<dd><a href="https://ask.fedoraproject.org/">Ask Fedora</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Common_F27_bugs">Common Bugs</a></dd>
|
||||
<dd><a href="https://developer.fedoraproject.org/">Fedora Developer Portal</a></dd>
|
||||
<dd><a href="https://docs.fedoraproject.org/f27/install-guide/index.html">Installation Guide</a></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">Join</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Join">Join Fedora</a></dd>
|
||||
<dd><a href="http://fedoraplanet.org">Planet Fedora</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/SIGs">Fedora SIGs</a></dd>
|
||||
<dd><a href="https://admin.fedoraproject.org/accounts/">Fedora Account System</a></dd>
|
||||
<dd><a href="https://fedoracommunity.org/">Fedora Community</a></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- /row of widgets -->
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-2">
|
||||
<div class="widget-body">
|
||||
<a href="https://www.redhat.com/"><img class="rh-logo" src="../../../master/_images/redhat-logo.png" alt="Red Hat Logo" /></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-7">
|
||||
<div class="widget-body">
|
||||
<p class="sponsor">Fedora is sponsored by Red Hat.</p>
|
||||
<p class="sponsor"><a href="https://www.redhat.com/en/technologies/linux-platforms/articles/relationship-between-fedora-and-rhel">Learn more about the relationship between Red Hat and Fedora »</a></p>
|
||||
<p class="copy">© 2017 Red Hat, Inc. and others. Please send any comments or corrections to the <a href="https://pagure.io/fedora-docs/docs-fp-o">documentation team</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- /row of widgets -->
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
|
||||
<!-- Latest compiled and minified JavaScript -->
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
|
||||
<script src="../../../master/_javascripts/bootstrap-offcanvas.js" type="text/javascript"></script>
|
||||
<script type="text/javascript">
|
||||
/*<![CDATA[*/
|
||||
$(document).ready(function() {
|
||||
$("[id^='topicGroup']").on('show.bs.collapse', function (event) {
|
||||
if (!($(event.target).attr('id').match(/^topicSubGroup/))) {
|
||||
$(this).parent().find("[id^='tgSpan']").toggleClass("fa-angle-right fa-angle-down");
|
||||
}
|
||||
});
|
||||
$("[id^='topicGroup']").on('hide.bs.collapse', function (event) {
|
||||
if (!($(event.target).attr('id').match(/^topicSubGroup/))) {
|
||||
$(this).parent().find("[id^='tgSpan']").toggleClass("fa-angle-right fa-angle-down");
|
||||
}
|
||||
});
|
||||
$("[id^='topicSubGroup']").on('show.bs.collapse', function () {
|
||||
$(this).parent().find("[id^='sgSpan']").toggleClass("fa-caret-right fa-caret-down");
|
||||
});
|
||||
$("[id^='topicSubGroup']").on('hide.bs.collapse', function () {
|
||||
$(this).parent().find("[id^='sgSpan']").toggleClass("fa-caret-right fa-caret-down");
|
||||
});
|
||||
});
|
||||
/*]]>*/
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -1,135 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags -->
|
||||
|
||||
<title>Fedora Documentation Website</title>
|
||||
|
||||
<!-- Bootstrap -->
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap-theme.min.css">
|
||||
|
||||
<link rel="stylesheet" href="https://overpass-30e2.kxcdn.com/overpass.css">
|
||||
<link rel="stylesheet" href="_stylesheets/asciibinder.css">
|
||||
|
||||
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
|
||||
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
|
||||
<!--[if lt IE 9]>
|
||||
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
|
||||
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
|
||||
<![endif]-->
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="page-header">
|
||||
<img src="/_images/fedora.svg" class="img-responsive" />
|
||||
<h2><strong>Fedora Documentation Site</strong></h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<h4><strong>Fedora Documentation - 404 Page Not Found :(</strong></h4>
|
||||
<p>Hi! You've arrived at Fedora documentation page which does not actually exist. This may be because you followed a link to an older document which has been retired. For reference, you can find those in our <a href="https://docs-old.fedoraproject.org/">old document archive</a>. Or, you can browse <a href="https://docs.fedoraproject.org/">current docs</a>.</p>
|
||||
<p>It may also be that this page _should_ exist, but sadly does not. If this is the case, and you know what it should say, you can <a href="https://pagure.io/fedora-docs">contribute via the Docs Project</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="bottom" class="text-muted py-3" >
|
||||
<div class="foot">
|
||||
<div class="container">
|
||||
<div class="row footerlinks">
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">About</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Overview">About Fedora</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/sponsors">Sponsors</a></dd>
|
||||
<dd><a href="https://fedoramagazine.org">Fedora Magazine</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Legal:Main#Legal">Legal</a></dd>
|
||||
</dl>
|
||||
<ul class="list-inline">
|
||||
<li>
|
||||
<a href="https:https://www.facebook.com/TheFedoraProject" class="btn-social btn-outline"><i class="fa fa-fw fa-facebook"></i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https:https://plus.google.com/112917221531140868607" class="btn-social btn-outline"><i class="fa fa-fw fa-google-plus"></i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https:https://twitter.com/fedora" class="btn-social btn-outline"><i class="fa fa-fw fa-twitter"></i></a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title uppercase">Download</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://getfedora.org/en/workstation/download">Get Fedora Workstation</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/server/download">Get Fedora Server</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/atomic/download">Get Fedora Atomic</a></dd>
|
||||
<dd><a href="https://spins.fedoraproject.org">Fedora Spins</a></dd>
|
||||
<dd><a href="https://labs.fedoraproject.org">Fedora Labs</a></dd>
|
||||
<dd><a href="https://arm.fedoraproject.org">Fedora ARM<span class="sup">®</span></a></dd>
|
||||
<dd><a href="https://alt.fedoraproject.org/">Alternative Downloads</a></dd>
|
||||
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">Support</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Communicating_and_getting_help">Get Help</a></dd>
|
||||
<dd><a href="https://ask.fedoraproject.org/">Ask Fedora</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Common_F27_bugs">Common Bugs</a></dd>
|
||||
<dd><a href="https://developer.fedoraproject.org/">Fedora Developer Portal</a></dd>
|
||||
<dd><a href="https://docs.fedoraproject.org/f27/install-guide/index.html">Installation Guide</a></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">Join</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Join">Join Fedora</a></dd>
|
||||
<dd><a href="http://fedoraplanet.org">Planet Fedora</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/SIGs">Fedora SIGs</a></dd>
|
||||
<dd><a href="https://admin.fedoraproject.org/accounts/">Fedora Account System</a></dd>
|
||||
<dd><a href="https://fedoracommunity.org/">Fedora Community</a></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- /row of widgets -->
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-2">
|
||||
<div class="widget-body">
|
||||
<a href="https://www.redhat.com/"><img class="rh-logo" src="_images/redhat-logo.png" alt="Red Hat Logo" /></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-7">
|
||||
<div class="widget-body">
|
||||
<p class="sponsor">Fedora is sponsored by Red Hat.</p>
|
||||
<p class="sponsor"><a href="https://www.redhat.com/en/technologies/linux-platforms/articles/relationship-between-fedora-and-rhel">Learn more about the relationship between Red Hat and Fedora »</a></p>
|
||||
<p class="copy">© 2017 Red Hat, Inc. and others. Please send any comments or corrections to the <a href="https://pagure.io/fedora-docs/docs-fp-o">documentation team</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- /row of widgets -->
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
|
||||
<!-- Include all compiled plugins (below), or include individual files as needed -->
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
|
||||
</body>
|
||||
</html>
|
Before Width: | Height: | Size: 5.3 KiB |
Before Width: | Height: | Size: 1.5 KiB |
|
@ -1,61 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
version="1.0"
|
||||
width="220"
|
||||
height="70"
|
||||
id="svg6180">
|
||||
<defs
|
||||
id="defs6182" />
|
||||
<g
|
||||
transform="translate(-266.55899,-345.34488)"
|
||||
id="layer1">
|
||||
<path
|
||||
d="m 316.7736,397.581 c 0,0 0,0 -20.53889,0 0.3327,4.45245 3.92157,7.77609 8.70715,7.77609 3.38983,0 6.31456,-1.39616 8.64094,-3.65507 0.46553,-0.46679 0.99726,-0.59962 1.59519,-0.59962 0.79781,0 1.59561,0.39932 2.12692,1.06388 0.3327,0.46553 0.53216,0.99726 0.53216,1.52857 0,0.73118 -0.3327,1.52857 -0.93106,2.12734 -2.7919,2.99052 -7.51086,4.98503 -12.16403,4.98503 -8.44149,0 -15.22074,-6.77967 -15.22074,-15.22158 0,-8.44149 6.58022,-15.22074 15.02171,-15.22074 8.37529,0 14.62323,6.51317 14.62323,15.08749 0,1.26418 -1.12924,2.12861 -2.39258,2.12861 z m -12.23065,-11.76512 c -4.45329,0 -7.51085,2.92473 -8.17499,7.17731 10.03626,0 16.35083,0 16.35083,0 -0.59836,-4.05355 -3.78874,-7.17731 -8.17584,-7.17731 z"
|
||||
id="path11"
|
||||
style="fill:#3c6eb4" />
|
||||
<path
|
||||
d="m 375.46344,410.80807 c -8.44106,0 -15.22074,-6.77968 -15.22074,-15.22159 0,-8.44149 6.77968,-15.22074 15.22074,-15.22074 8.44234,0 15.22159,6.77925 15.22159,15.22074 -4.2e-4,8.44149 -6.77968,15.22159 -15.22159,15.22159 z m 0,-24.65992 c -5.31688,0 -8.77377,4.25427 -8.77377,9.43833 0,5.18364 3.45689,9.43833 8.77377,9.43833 5.31731,0 8.77504,-4.25469 8.77504,-9.43833 -4.2e-4,-5.18406 -3.45773,-9.43833 -8.77504,-9.43833 z"
|
||||
id="path13"
|
||||
style="fill:#3c6eb4" />
|
||||
<path
|
||||
d="m 412.66183,380.36574 c -4.45963,0 -7.40966,1.319 -10.01391,4.62956 l -0.24036,-1.53995 0,0 c -0.20198,-1.60743 -1.57326,-2.84926 -3.23382,-2.84926 -1.80139,0 -3.26206,1.459 -3.26206,3.26081 0,0.003 0,0.005 0,0.008 l 0,0 0,0.003 0,0 0,23.40712 c 0,1.79464 1.46194,3.25743 3.257,3.25743 1.79465,0 3.25744,-1.46279 3.25744,-3.25743 l 0,-12.56209 c 0,-5.71621 4.98502,-8.57432 10.23613,-8.57432 1.59519,0 2.85726,-1.32953 2.85726,-2.92515 0,-1.59561 -1.26207,-2.85726 -2.85768,-2.85726 z"
|
||||
id="path15"
|
||||
style="fill:#3c6eb4" />
|
||||
<path
|
||||
d="m 447.02614,395.58648 c 0.0666,-8.17541 -5.78326,-15.22074 -15.222,-15.22074 -8.44192,0 -15.28779,6.77925 -15.28779,15.22074 0,8.44191 6.64684,15.22159 14.68985,15.22159 4.01434,0 7.62682,-2.06621 9.23846,-4.22518 l 0.79359,2.01434 0,0 c 0.42589,1.13177 1.5176,1.93717 2.7978,1.93717 1.65001,0 2.98756,-1.33671 2.99009,-2.98545 l 0,0 0,-7.80687 0,0 0,-4.1556 z m -15.222,9.43833 c -5.31773,0 -8.77419,-4.25469 -8.77419,-9.43833 0,-5.18406 3.45604,-9.43833 8.77419,-9.43833 5.3173,0 8.77419,4.25427 8.77419,9.43833 0,5.18364 -3.45689,9.43833 -8.77419,9.43833 z"
|
||||
id="path17"
|
||||
style="fill:#3c6eb4" />
|
||||
<path
|
||||
d="m 355.01479,368.3337 c 0,-1.7938 -1.46194,-3.18997 -3.25659,-3.18997 -1.79422,0 -3.25743,1.39659 -3.25743,3.18997 l 0,17.1499 c -1.66097,-3.05756 -5.25026,-5.11786 -9.50495,-5.11786 -8.64052,0 -14.42336,6.51318 -14.42336,15.22074 0,8.70757 5.98229,15.22159 14.42336,15.22159 3.76555,0 7.03057,-1.55429 8.98587,-4.25554 l 0.72317,1.83428 c 0.44782,1.25912 1.64917,2.16024 3.06051,2.16024 1.78621,0 3.24984,-1.45435 3.24984,-3.24815 0,-0.005 0,-0.009 0,-0.0139 l 0,0 0,-38.95128 -4.2e-4,0 z m -15.22116,36.69111 c -5.31731,0 -8.70715,-4.25469 -8.70715,-9.43833 0,-5.18406 3.38984,-9.43833 8.70715,-9.43833 5.31773,0 8.70714,4.0544 8.70714,9.43833 0,5.38309 -3.38941,9.43833 -8.70714,9.43833 z"
|
||||
id="path19"
|
||||
style="fill:#3c6eb4" />
|
||||
<path
|
||||
d="m 287.21553,365.34023 c -0.59414,-0.0877 -1.19966,-0.13198 -1.80097,-0.13198 -6.73118,0 -12.20746,5.4767 -12.20746,12.20788 l 0,3.8132 -3.98903,0 c -1.46237,0 -2.65908,1.19671 -2.65908,2.65781 0,1.46321 1.19671,2.93738 2.65908,2.93738 l 3.98819,0 0,20.46004 c 0,1.79464 1.46236,3.25743 3.25658,3.25743 1.79507,0 3.25744,-1.46279 3.25744,-3.25743 l 0,-20.46004 4.40986,0 c 1.46194,0 2.65823,-1.47417 2.65823,-2.93738 0,-1.46152 -1.19629,-2.65823 -2.65823,-2.65823 l -4.40733,0 0,-3.8132 c 0,-3.13852 2.55323,-6.11469 5.69175,-6.11469 0.28294,0 0.56757,0.0211 0.84672,0.062 1.78031,0.26355 3.4358,-0.54269 3.70019,-2.32342 0.2627,-1.77904 -0.96606,-3.43538 -2.74594,-3.69935 z"
|
||||
id="path21"
|
||||
style="fill:#3c6eb4" />
|
||||
<path
|
||||
d="m 482.01243,363.57426 c 0,-10.06788 -8.16108,-18.22938 -18.22897,-18.22938 -10.06282,0 -18.22179,8.15475 -18.22854,18.21631 l -4.2e-4,-4.2e-4 0,14.1071 4.2e-4,4.2e-4 c 0.005,2.28463 1.85832,4.13409 4.14463,4.13409 0.007,0 0.0127,-8.4e-4 0.0194,-8.4e-4 l 0.001,8.4e-4 14.07083,0 0,0 c 10.06409,-0.004 18.22138,-8.16276 18.22138,-18.22812 z"
|
||||
id="path25"
|
||||
style="fill:#294172" />
|
||||
<path
|
||||
d="m 469.13577,349.66577 c -4.72528,0 -8.55576,3.83049 -8.55576,8.55577 0,0.002 0,0.004 0,0.006 l 0,4.52836 -4.51444,0 c -8.5e-4,0 -8.5e-4,0 -0.001,0 -4.72528,0 -8.55576,3.81193 -8.55576,8.53678 0,4.72528 3.83048,8.55577 8.55576,8.55577 4.72486,0 8.55534,-3.83049 8.55534,-8.55577 0,-0.002 0,-0.004 0,-0.006 l 0,-4.54733 4.51444,0 c 8.5e-4,0 0.001,0 0.002,0 4.72486,0 8.55534,-3.79296 8.55534,-8.51781 0,-4.72528 -3.83048,-8.55577 -8.55534,-8.55577 z m -8.55576,21.63483 c -0.004,2.48998 -2.02446,4.50811 -4.51571,4.50811 -2.49378,0 -4.53426,-2.02193 -4.53426,-4.5157 0,-2.49421 2.04048,-4.55366 4.53426,-4.55366 0.002,0 0.004,4.2e-4 0.006,4.2e-4 l 3.86971,0 c 0.001,0 0.002,-4.2e-4 0.003,-4.2e-4 0.35209,0 0.63799,0.28505 0.63799,0.63715 0,4.2e-4 -4.2e-4,8.4e-4 -4.2e-4,0.001 l 0,3.92284 -4.2e-4,0 z m 8.55534,-8.5448 c -0.001,0 -0.003,0 -0.004,0 l -3.87223,0 c -8.4e-4,0 -0.002,0 -0.002,0 -0.35252,0 -0.63757,-0.28506 -0.63757,-0.63758 l 0,-4.2e-4 0,-3.90343 c 0.004,-2.49083 2.02446,-4.50854 4.51571,-4.50854 2.49378,0 4.53468,2.02193 4.53468,4.51613 4.2e-4,2.49336 -2.04048,4.53384 -4.53426,4.53384 z"
|
||||
id="path29"
|
||||
style="fill:#3c6eb4" />
|
||||
<path
|
||||
d="m 460.58001,362.7558 0,-4.52836 c 0,-0.002 0,-0.004 0,-0.006 0,-4.72528 3.83048,-8.55577 8.55576,-8.55577 0.71685,0 1.22623,0.0805 1.88952,0.25469 0.96774,0.25385 1.75796,1.04618 1.75838,1.96922 4.2e-4,1.11575 -0.80919,1.92621 -2.0194,1.92621 -0.57642,0 -0.78473,-0.11048 -1.62892,-0.11048 -2.49125,0 -4.51149,2.01771 -4.51571,4.50854 l 0,3.90385 0,4.2e-4 c 0,0.35252 0.28505,0.63758 0.63757,0.63758 4.3e-4,0 0.001,0 0.002,0 l 2.96521,0 c 1.10521,0 1.99747,0.88467 1.99832,1.99283 0,1.10816 -0.89353,1.99114 -1.99832,1.99114 l -3.60489,0 0,4.54733 c 0,0.002 0,0.004 0,0.006 0,4.72485 -3.83048,8.55534 -8.55534,8.55534 -0.71684,0 -1.22623,-0.0805 -1.88952,-0.25469 -0.96774,-0.25343 -1.75838,-1.04618 -1.7588,-1.9688 0,-1.11575 0.80919,-1.92663 2.01982,-1.92663 0.576,0 0.78473,0.11048 1.6285,0.11048 2.49125,0 4.51191,-2.01771 4.51613,-4.50811 0,0 0,-3.92368 0,-3.9241 0,-0.35168 -0.2859,-0.63673 -0.63799,-0.63673 -4.3e-4,0 -8.5e-4,0 -0.002,0 l -2.96521,-4.2e-4 c -1.10521,0 -1.99831,-0.88214 -1.99831,-1.9903 -4.3e-4,-1.11533 0.90238,-1.99367 2.01939,-1.99367 l 3.58339,0 0,0 z"
|
||||
id="path31"
|
||||
style="fill:#ffffff" />
|
||||
<path
|
||||
d="m 477.41661,378.55292 2.81558,0 0,0.37898 -1.18152,0 0,2.94935 -0.45254,0 0,-2.94935 -1.18152,0 0,-0.37898 m 3.26144,0 0.67101,0 0.84937,2.26496 0.85381,-2.26496 0.67102,0 0,3.32833 -0.43917,0 0,-2.9226 -0.85828,2.28279 -0.45255,0 -0.85827,-2.28279 0,2.9226 -0.43694,0 0,-3.32833"
|
||||
id="text6223"
|
||||
style="fill:#294172;enable-background:new" />
|
||||
</g>
|
||||
<path
|
||||
d="m 181.98344,61.675273 2.81558,0 0,0.37898 -1.18152,0 0,2.94935 -0.45254,0 0,-2.94935 -1.18152,0 0,-0.37898 m 3.26144,0 0.67101,0 0.84937,2.26496 0.85381,-2.26496 0.67102,0 0,3.32833 -0.43917,0 0,-2.9226 -0.85828,2.28279 -0.45255,0 -0.85827,-2.28279 0,2.9226 -0.43694,0 0,-3.32833"
|
||||
id="path2391"
|
||||
style="fill:#294172;enable-background:new" />
|
||||
</svg>
|
Before Width: | Height: | Size: 7.6 KiB |
Before Width: | Height: | Size: 3.9 KiB |
|
@ -1,6 +0,0 @@
|
|||
$(document).ready(function () {
|
||||
$('[data-toggle="offcanvas"]').click(function () {
|
||||
$('.sidebar').show();
|
||||
$('.row-offcanvas').toggleClass('active');
|
||||
});
|
||||
});
|
|
@ -1,598 +0,0 @@
|
|||
@import url(https://maxcdn.bootstrapcdn.com/font-awesome/4.1.0/css/font-awesome.min.css);
|
||||
/* ------------------------------------------------------------
|
||||
Image: "Spin" https://www.flickr.com/photos/eflon/3655695161/
|
||||
Author: eflon https://www.flickr.com/photos/eflon/
|
||||
License: https://creativecommons.org/licenses/by/2.0/
|
||||
---------------------------------------------------------------*/
|
||||
.attribution {
|
||||
text-align: center;
|
||||
position: relative;
|
||||
bottom: -20px;
|
||||
}
|
||||
.attribution .btn {
|
||||
color: #808080;
|
||||
color: rgba(175,175,175, .65);
|
||||
font-size: 11px;
|
||||
}
|
||||
.attribution .btn:hover {
|
||||
text-decoration: none;
|
||||
color: #aaa;
|
||||
}
|
||||
.popover-content {
|
||||
font-size: 12px;
|
||||
line-height: 1.3;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 980px) {
|
||||
body {
|
||||
margin-bottom: 200px;
|
||||
}
|
||||
footer {
|
||||
text-align: center;
|
||||
}
|
||||
footer .text-right {
|
||||
text-align: center !important;
|
||||
}
|
||||
#footer_social .first {
|
||||
margin-left: 0;
|
||||
}
|
||||
#footer_social > a {
|
||||
top: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
.fa-inverse:hover {
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
.collapse a.active {
|
||||
background-color: #DEEAF4;
|
||||
color: #000;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.collapse a.active:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.collapse a.active:before {
|
||||
background-color: #A0C3E5;
|
||||
content: "";
|
||||
display: inline-block;
|
||||
height: 100%;
|
||||
left: 0;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
width: 3px;
|
||||
}
|
||||
|
||||
.main h2, .main .h2 {
|
||||
border-top: 0px;
|
||||
padding-top: 10px;
|
||||
font-size: 28px;
|
||||
}
|
||||
|
||||
.page-header {
|
||||
height: 100% !important;
|
||||
}
|
||||
.page-header .img-responsive {
|
||||
display: inline;
|
||||
}
|
||||
.page-header h2 {
|
||||
font-size: 32px;
|
||||
display: inline;
|
||||
vertical-align: bottom;
|
||||
}
|
||||
|
||||
.navbar-brand {
|
||||
padding: initial;
|
||||
height: initial;
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
.navbar-header h2 {
|
||||
display: inline;
|
||||
position: absolute;
|
||||
font-weight: bold;
|
||||
margin-top: 50px ;
|
||||
}
|
||||
|
||||
.nav > li > a.hover{
|
||||
background-color: none;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6 {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
h2 > a.anchor, h3 > a.anchor, h4 > a.anchor, h5 > a.anchor, h6 > a.anchor {
|
||||
display: block;
|
||||
font-weight: normal;
|
||||
margin-left: -1.5ex;
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
text-decoration: none !important;
|
||||
visibility: hidden;
|
||||
width: 1.5ex;
|
||||
z-index: 1001;
|
||||
}
|
||||
|
||||
h2 > a.anchor:before, h3 > a.anchor:before, h4 > a.anchor:before, h5 > a.anchor:before, h6 > a.anchor:before {
|
||||
content: "\f0c1";
|
||||
display: block;
|
||||
font-family: FontAwesome;
|
||||
font-size: 0.7em;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
padding-top: 0.2em;
|
||||
}
|
||||
|
||||
h4 > a.anchor:before, h5 > a.anchor:before, h6 > a.anchor:before {
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
h2:hover > a.anchor,
|
||||
h2 > a.anchor:hover,
|
||||
h3:hover > a.anchor,
|
||||
h3 > a.anchor:hover,
|
||||
h4:hover > a.anchor,
|
||||
h4 > a.anchor:hover,
|
||||
h5:hover > a.anchor,
|
||||
h5 > a.anchor:hover,
|
||||
h6:hover > a.anchor,
|
||||
h6 > a.anchor:hover {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.main {
|
||||
border-left: 1px solid #e7e7e7;
|
||||
margin-left: -1px;
|
||||
padding-left: 25px;
|
||||
}
|
||||
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.main {
|
||||
padding-left: 30px;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Sidebar
|
||||
*/
|
||||
|
||||
.nav-header {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.nav-header ul {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.nav-header ul li a {
|
||||
display: block;
|
||||
padding: 5px 20px 5px 25px;
|
||||
font-size: 13px;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.nav-sidebar .fa {
|
||||
text-align: center;
|
||||
top: -1px;
|
||||
width: 14px;
|
||||
}
|
||||
|
||||
.nav-sidebar li a {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.nav-sidebar li a:hover {
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.nav-sidebar ul li ul.nav-tertiary li a {
|
||||
padding-left: 50px;
|
||||
}
|
||||
|
||||
.nav-sidebar > li > a {
|
||||
padding: 7px 0;
|
||||
}
|
||||
|
||||
.nav-sidebar > li > a:focus, .nav-sidebar > li > a:hover {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
font-weight: 300;
|
||||
display: none;
|
||||
padding-top: 13px;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 767px) {
|
||||
.sidebar {
|
||||
padding-left: 30px;
|
||||
padding-right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (min-width: 768px) {
|
||||
.sidebar {
|
||||
border-right: 1px solid #e7e7e7;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Off Canvas
|
||||
* --------------------------------------------------
|
||||
*/
|
||||
|
||||
body, html {
|
||||
overflow-x: hidden; /* Prevent scroll on narrow devices */
|
||||
font-family: "Overpass", sans-serif;
|
||||
}
|
||||
|
||||
.toggle-nav {
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 767px) {
|
||||
.row-offcanvas {
|
||||
position: relative;
|
||||
-webkit-transition: all .25s ease-out;
|
||||
-o-transition: all .25s ease-out;
|
||||
transition: all .25s ease-out;
|
||||
}
|
||||
|
||||
.row-offcanvas-right {
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.row-offcanvas-left {
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.row-offcanvas-right
|
||||
.sidebar-offcanvas {
|
||||
right: -75%; /* 8 columns */
|
||||
}
|
||||
|
||||
.row-offcanvas-left
|
||||
.sidebar-offcanvas {
|
||||
left: -75%; /* 8 columns */
|
||||
}
|
||||
|
||||
.row-offcanvas-right.active {
|
||||
right: 75%; /* 8 columns */
|
||||
}
|
||||
|
||||
.row-offcanvas-left.active {
|
||||
left: 75%; /* 8 columns */
|
||||
}
|
||||
|
||||
.sidebar-offcanvas {
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
width: 75%; /* 8 columns */
|
||||
}
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 0 0 1.6em;
|
||||
}
|
||||
|
||||
/* Remnants of Asciidoctor default stylesheet - remove styles as needed */
|
||||
|
||||
#map_canvas img, #map_canvas embed, #map_canvas object, .map_canvas img, .map_canvas embed, .map_canvas object { max-width: none !important; }
|
||||
.left { float: left !important; }
|
||||
.right { float: right !important; }
|
||||
.text-left { text-align: left !important; }
|
||||
.text-right { text-align: right !important; }
|
||||
.text-center { text-align: center !important; }
|
||||
.text-justify { text-align: justify !important; }
|
||||
.hide { display: none; }
|
||||
.subheader, #content #toctitle, .admonitionblock td.content > .title, .audioblock > .title, .exampleblock > .title, .imageblock > .title, .listingblock > .title, .literalblock > .title, .stemblock > .title, .openblock > .title, .paragraph > .title, .quoteblock > .title, table.tableblock > .title, .verseblock > .title, .videoblock > .title, .dlist > .title, .olist > .title, .ulist > .title, .qlist > .title, .hdlist > .title { line-height: 1.4; color: #7a2518; font-weight: 300; margin-top: 0.2em; margin-bottom: 0.5em; }
|
||||
abbr, acronym { text-transform: uppercase; font-size: 90%; color: #333333; border-bottom: 1px dotted #dddddd; cursor: help; }
|
||||
abbr { text-transform: none; }
|
||||
blockquote { margin: 0 0 1.25em; padding: 0.5625em 1.25em 0 1.1875em; border-left: 3px solid #487c58; }
|
||||
blockquote cite { display: block; font-size: inherit; color: #454545; }
|
||||
blockquote cite:before { content: "\2014 \0020"; }
|
||||
blockquote cite a, blockquote cite a:visited { color: #454545; }
|
||||
blockquote, blockquote p { line-height: 1.6; color: #6e6e6e; }
|
||||
@media only screen and (min-width: 768px) {
|
||||
#toctitle, .sidebarblock > .content > .title { line-height: 1.4; }
|
||||
#toctitle, .sidebarblock > .content > .title { font-size: 1.6875em; }
|
||||
}
|
||||
table { background: white; margin-bottom: 1.25em; border: solid 1px #dddddd; }
|
||||
table thead, table tfoot { background: whitesmoke; font-weight: bold; }
|
||||
table thead tr th, table thead tr td, table tfoot tr th, table tfoot tr td { padding: 0.5em 0.625em 0.625em; font-size: inherit; color: #333333; text-align: left; }
|
||||
table tr th, table tr td { padding: 0.5625em 0.625em; font-size: inherit; color: #333333; }
|
||||
table tr.even, table tr.alt, table tr:nth-of-type(even) { background: #f9f9f9; }
|
||||
table thead tr th, table tfoot tr th, table tbody tr td, table tr td, table tfoot tr td { display: table-cell; line-height: 1.6; }
|
||||
.clearfix:before, .clearfix:after, .float-group:before, .float-group:after { content: " "; display: table; }
|
||||
.clearfix:after, .float-group:after { clear: both; }
|
||||
*:not(pre) > code { font-size: inherit; padding: 0; white-space: nowrap; background-color: inherit; border: 0 solid #dddddd; -webkit-border-radius: 4px; border-radius: 4px; text-shadow: none; line-height: 1; }
|
||||
.keyseq { color: #666666; }
|
||||
kbd:not(.keyseq) { display: inline-block; color: #333333; font-size: 0.75em; line-height: 1.4; background-color: #f7f7f7; border: 1px solid #ccc; -webkit-border-radius: 3px; border-radius: 3px; -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.2), 0 0 0 2px white inset; box-shadow: 0 1px 0 rgba(0, 0, 0, 0.2), 0 0 0 2px white inset; margin: -0.15em 0.15em 0 0.15em; padding: 0.2em 0.6em 0.2em 0.5em; vertical-align: middle; white-space: nowrap; }
|
||||
.keyseq kbd:first-child { margin-left: 0; }
|
||||
.keyseq kbd:last-child { margin-right: 0; }
|
||||
.menuseq, .menu { color: #1a1a1a; }
|
||||
b.button:before, b.button:after { position: relative; top: -1px; font-weight: normal; }
|
||||
b.button:before { content: "["; padding: 0 3px 0 2px; }
|
||||
b.button:after { content: "]"; padding: 0 2px 0 3px; }
|
||||
p a > code:hover { color: #561309; }
|
||||
#header, #content, #footnotes, #footer { width: 100%; margin-left: auto; margin-right: auto; margin-top: 0; margin-bottom: 0; max-width: 62.5em; *zoom: 1; position: relative; padding-left: 0.9375em; padding-right: 0.9375em; }
|
||||
#header:before, #header:after, #content:before, #content:after, #footnotes:before, #footnotes:after, #footer:before, #footer:after { content: " "; display: table; }
|
||||
#header:after, #content:after, #footnotes:after, #footer:after { clear: both; }
|
||||
#content:before { content: none; }
|
||||
#header { margin-bottom: 2.5em; }
|
||||
#header > h1 { color: black; font-weight: 300; border-bottom: 1px solid #d8d8d8; margin-bottom: -28px; padding-bottom: 32px; }
|
||||
#header span { color: #6e6e6e; }
|
||||
#header #revnumber { text-transform: capitalize; }
|
||||
#header br { display: none; }
|
||||
#header br + span { padding-left: 3px; }
|
||||
#header br + span:before { content: "\2013 \0020"; }
|
||||
#header br + span.author { padding-left: 0; }
|
||||
#header br + span.author:before { content: ", "; }
|
||||
#toc { border-bottom: 3px double #e5e5e5; padding-top: 1em; padding-bottom: 1.25em; }
|
||||
#toc > ul { margin-left: 0.25em; }
|
||||
#toc ul.sectlevel0 > li > a { font-style: italic; }
|
||||
#toc ul.sectlevel0 ul.sectlevel1 { margin-left: 0; margin-top: 0.5em; margin-bottom: 0.5em; }
|
||||
#toc ul { font-family: "Open Sans", "DejaVu Sans", "Sans", sans-serif; list-style-type: none; }
|
||||
#toc a { text-decoration: none; }
|
||||
#toc a:active { text-decoration: underline; }
|
||||
#toctitle { color: #7a2518; }
|
||||
@media only screen and (min-width: 768px) { body.toc2 { padding-left: 15em; padding-right: 0; }
|
||||
#toc.toc2 { background-color: #fafaf9; position: fixed; width: 15em; left: 0; top: 0; border-right: 1px solid #e5e5e5; border-bottom: 0; z-index: 1000; padding: 1.25em 1em; height: 100%; overflow: auto; }
|
||||
#toc.toc2 #toctitle { margin-top: 0; font-size: 1.2em; }
|
||||
#toc.toc2 > ul { font-size: .90em; margin-bottom: 0; }
|
||||
#toc.toc2 ul ul { margin-left: 0; padding-left: 1em; }
|
||||
#toc.toc2 ul.sectlevel0 ul.sectlevel1 { padding-left: 0; margin-top: 0.5em; margin-bottom: 0.5em; }
|
||||
body.toc2.toc-right { padding-left: 0; padding-right: 15em; }
|
||||
body.toc2.toc-right #toc.toc2 { border-right: 0; border-left: 1px solid #e5e5e5; left: auto; right: 0; } }
|
||||
@media only screen and (min-width: 1280px) { body.toc2 { padding-left: 20em; padding-right: 0; }
|
||||
#toc.toc2 { width: 20em; }
|
||||
#toc.toc2 #toctitle { font-size: 1.375em; }
|
||||
#toc.toc2 > ul { font-size: 0.95em; }
|
||||
#toc.toc2 ul ul { padding-left: 1.25em; }
|
||||
body.toc2.toc-right { padding-left: 0; padding-right: 20em; } }
|
||||
#content #toc { border-style: solid; border-width: 1px; border-color: #e3e3dd; margin-bottom: 1.25em; padding: 1.25em; background: #fafaf9; border-width: 0; -webkit-border-radius: 4px; border-radius: 4px; }
|
||||
#content #toc > :first-child { margin-top: 0; }
|
||||
#content #toc > :last-child { margin-bottom: 0; }
|
||||
#content #toctitle { font-size: 1.375em; }
|
||||
#footer { max-width: 100%; background-color: #333333; padding: 1.25em; }
|
||||
#footer-text { color: #cccccc; line-height: 1.44; }
|
||||
.audioblock, .imageblock, .literalblock, .listingblock, .stemblock, .verseblock, .videoblock { margin-bottom: 2.5em; }
|
||||
.admonitionblock td.content > .title, .audioblock > .title, .exampleblock > .title, .imageblock > .title, .listingblock > .title, .literalblock > .title, .stemblock > .title, .openblock > .title, .paragraph > .title, .quoteblock > .title, table.tableblock > .title, .verseblock > .title, .videoblock > .title, .dlist > .title, .olist > .title, .ulist > .title, .qlist > .title, .hdlist > .title { text-rendering: optimizeLegibility; text-align: left; font-family: "Noto Serif", "DejaVu Serif", "Serif", serif; font-weight: normal; font-style: italic; }
|
||||
table.tableblock > caption.title { white-space: nowrap; overflow: visible; max-width: 0; }
|
||||
table.tableblock #preamble > .sectionbody > .paragraph:first-of-type p { font-size: inherit; }
|
||||
.admonitionblock > table { border: 0; background: none; width: 100%; }
|
||||
.admonitionblock > table td.icon { text-align: center; width: 80px; }
|
||||
.admonitionblock > table td.icon img { max-width: none; }
|
||||
.admonitionblock > table td.icon .title { font-weight: 300; text-transform: uppercase; }
|
||||
.admonitionblock > table td.content { padding-left: 0; padding-right: 1.25em; color: #6e6e6e; }
|
||||
.admonitionblock > table td.content > :last-child > :last-child { margin-bottom: 0; }
|
||||
.exampleblock > .content { border-style: solid; border-width: 1px; border-color: #e6e6e6; margin-bottom: 1.25em; padding: 1.25em; background: white; -webkit-border-radius: 4px; border-radius: 4px; }
|
||||
.exampleblock > .content > :first-child { margin-top: 0; }
|
||||
.exampleblock > .content > :last-child { margin-bottom: 0; }
|
||||
.exampleblock > .content h1, .exampleblock > .content h2, .exampleblock > .content h3, .exampleblock > .content #toctitle, .sidebarblock.exampleblock > .content > .title, .exampleblock > .content h4, .exampleblock > .content h5, .exampleblock > .content h6, .exampleblock > .content p { color: #333333; }
|
||||
.exampleblock > .content h1, .exampleblock > .content h2, .exampleblock > .content h3, .exampleblock > .content #toctitle, .sidebarblock.exampleblock > .content > .title, .exampleblock > .content h4, .exampleblock > .content h5, .exampleblock > .content h6 { line-height: 1; margin-bottom: 0.625em; }
|
||||
.exampleblock > .content h1.subheader, .exampleblock > .content h2.subheader, .exampleblock > .content h3.subheader, .exampleblock > .content .subheader#toctitle, .sidebarblock.exampleblock > .content > .subheader.title, .exampleblock > .content h4.subheader, .exampleblock > .content h5.subheader, .exampleblock > .content h6.subheader { line-height: 1.4; }
|
||||
.exampleblock.result > .content { -webkit-box-shadow: 0 1px 8px #e3e3dd; box-shadow: 0 1px 8px #e3e3dd; }
|
||||
.sidebarblock { border-style: solid; border-width: 1px; border-color: #e3e3dd; margin-top: -1.0em; margin-bottom: 1.6em; margin-left: 1em; padding: .5em; background: #F1F3F5; -webkit-border-radius: 4px; border-radius: 4px; overflow-x: auto; float: right; width: 40%; }
|
||||
.sidebarblock > :first-child { margin-top: 0; }
|
||||
.sidebarblock > :last-child { margin-bottom: 0; }
|
||||
.sidebarblock h1, .sidebarblock h2, .sidebarblock h3, .sidebarblock #toctitle, .sidebarblock > .content > .title, .sidebarblock h4, .sidebarblock h5, .sidebarblock h6, .sidebarblock p { color: #333333; }
|
||||
.sidebarblock h1, .sidebarblock h2, .sidebarblock h3, .sidebarblock #toctitle, .sidebarblock > .content > .title, .sidebarblock h4, .sidebarblock h5, .sidebarblock h6 { line-height: 1; margin-bottom: 0.625em; }
|
||||
.sidebarblock h1.subheader, .sidebarblock h2.subheader, .sidebarblock h3.subheader, .sidebarblock .subheader#toctitle, .sidebarblock > .content > .subheader.title, .sidebarblock h4.subheader, .sidebarblock h5.subheader, .sidebarblock h6.subheader { line-height: 1.4; }
|
||||
.sidebarblock > .content > .title { color: inherit; font-size: 28px; font-weight: 500; margin-top: 0; line-height: 1.6; }
|
||||
.width50 { width: 50% ! important}
|
||||
.exampleblock > .content > :last-child > :last-child, .exampleblock > .content .olist > ol > li:last-child > :last-child, .exampleblock > .content .ulist > ul > li:last-child > :last-child, .exampleblock > .content .qlist > ol > li:last-child > :last-child, .sidebarblock > .content > :last-child > :last-child, .sidebarblock > .content .olist > ol > li:last-child > :last-child, .sidebarblock > .content .ulist > ul > li:last-child > :last-child, .sidebarblock > .content .qlist > ol > li:last-child > :last-child { margin-bottom: 0; }
|
||||
.literalblock pre, .literalblock pre[class], .listingblock pre, .listingblock pre[class] { border: 0px; background-color: #F0F3F5; -webkit-border-radius: 5px; border-radius: 5px; padding: 1.5em 2.5em; word-wrap: break-word; }
|
||||
.literalblock pre.nowrap, .literalblock pre[class].nowrap, .listingblock pre.nowrap, .listingblock pre[class].nowrap { overflow-x: auto; white-space: pre; word-wrap: normal; }
|
||||
.literalblock pre > code, .literalblock pre[class] > code, .listingblock pre > code, .listingblock pre[class] > code { display: block; }
|
||||
.listingblock > .content { position: relative; }
|
||||
.listingblock:hover code[class*=" language-"]:before { text-transform: uppercase; font-size: 0.9em; color: #999; position: absolute; top: 0.375em; right: 0.375em; }
|
||||
.listingblock:hover code.asciidoc:before { content: "asciidoc"; }
|
||||
.listingblock:hover code.clojure:before { content: "clojure"; }
|
||||
.listingblock:hover code.css:before { content: "css"; }
|
||||
.listingblock:hover code.go:before { content: "go"; }
|
||||
.listingblock:hover code.groovy:before { content: "groovy"; }
|
||||
.listingblock:hover code.html:before { content: "html"; }
|
||||
.listingblock:hover code.java:before { content: "java"; }
|
||||
.listingblock:hover code.javascript:before { content: "javascript"; }
|
||||
.listingblock:hover code.python:before { content: "python"; }
|
||||
.listingblock:hover code.ruby:before { content: "ruby"; }
|
||||
.listingblock:hover code.sass:before { content: "sass"; }
|
||||
.listingblock:hover code.scss:before { content: "scss"; }
|
||||
.listingblock:hover code.xml:before { content: "xml"; }
|
||||
.listingblock:hover code.yaml:before { content: "yaml"; }
|
||||
.listingblock.terminal pre .command:before { content: attr(data-prompt); padding-right: 0.5em; color: #999; }
|
||||
.listingblock.terminal pre .command:not([data-prompt]):before { content: '$'; }
|
||||
table.pyhltable { border: 0; margin-bottom: 0; }
|
||||
table.pyhltable td { vertical-align: top; padding-top: 0; padding-bottom: 0; }
|
||||
table.pyhltable td.code { padding-left: .75em; padding-right: 0; }
|
||||
.highlight.pygments .lineno, table.pyhltable td:not(.code) { color: #999; padding-left: 0; padding-right: .5em; border-right: 1px solid #d8d8d8; }
|
||||
.highlight.pygments .lineno { display: inline-block; margin-right: .25em; }
|
||||
table.pyhltable .linenodiv { background-color: transparent !important; padding-right: 0 !important; }
|
||||
.quoteblock { margin: 0 0 1.25em 0; padding: 0.5625em 1.25em 0 1.1875em; border-left: 3px solid #487c58; }
|
||||
.quoteblock blockquote { margin: 0 0 1.25em 0; padding: 0 0 0.625em 0; border: 0; }
|
||||
.quoteblock blockquote > .paragraph:last-child p { margin-bottom: 0; }
|
||||
.quoteblock .attribution { margin-top: -0.625em; padding-bottom: 0.625em; font-size: inherit; color: #454545; line-height: 1.6; }
|
||||
.quoteblock .attribution br { display: none; }
|
||||
.quoteblock .attribution cite { display: block; }
|
||||
table.tableblock { max-width: 100%; }
|
||||
table.tableblock td .paragraph:last-child p > p:last-child, table.tableblock th > p:last-child, table.tableblock td > p:last-child { margin-bottom: 0; }
|
||||
table.spread { width: 100%; }
|
||||
table.tableblock, th.tableblock, td.tableblock { border: 0 solid #dddddd; }
|
||||
table.grid-all th.tableblock, table.grid-all td.tableblock { border-width: 0 1px 1px 0; }
|
||||
table.grid-all tfoot > tr > th.tableblock, table.grid-all tfoot > tr > td.tableblock { border-width: 1px 1px 0 0; }
|
||||
table.grid-cols th.tableblock, table.grid-cols td.tableblock { border-width: 0 1px 0 0; }
|
||||
table.grid-all * > tr > .tableblock:last-child, table.grid-cols * > tr > .tableblock:last-child { border-right-width: 0; }
|
||||
table.grid-rows th.tableblock, table.grid-rows td.tableblock { border-width: 0 0 1px 0; }
|
||||
table.grid-all tbody > tr:last-child > th.tableblock, table.grid-all tbody > tr:last-child > td.tableblock, table.grid-all thead:last-child > tr > th.tableblock, table.grid-rows tbody > tr:last-child > th.tableblock, table.grid-rows tbody > tr:last-child > td.tableblock, table.grid-rows thead:last-child > tr > th.tableblock { border-bottom-width: 0; }
|
||||
table.grid-rows tfoot > tr > th.tableblock, table.grid-rows tfoot > tr > td.tableblock { border-width: 1px 0 0 0; }
|
||||
table.frame-all { border-width: 1px; }
|
||||
table.frame-sides { border-width: 0 1px; }
|
||||
table.frame-topbot { border-width: 1px 0; }
|
||||
th.halign-left, td.halign-left { text-align: left; }
|
||||
th.halign-right, td.halign-right { text-align: right; }
|
||||
th.halign-center, td.halign-center { text-align: center; }
|
||||
th.valign-top, td.valign-top { vertical-align: top; }
|
||||
th.valign-bottom, td.valign-bottom { vertical-align: bottom; }
|
||||
th.valign-middle, td.valign-middle { vertical-align: middle; }
|
||||
table thead th, table tfoot th { font-weight: bold; }
|
||||
tbody tr th { display: table-cell; line-height: 1.6; background: whitesmoke; }
|
||||
tbody tr th, tbody tr th p, tfoot tr th, tfoot tr th p { color: #333333; font-weight: bold; }
|
||||
td > div.verse { white-space: pre; }
|
||||
ul.unstyled, ol.unnumbered, ul.checklist, ul.none { list-style-type: none; }
|
||||
ul.unstyled, ol.unnumbered, ul.checklist { margin-left: 0.625em; }
|
||||
ul.checklist li > p:first-child > .fa-check-square-o:first-child, ul.checklist li > p:first-child > input[type="checkbox"]:first-child { margin-right: 0.25em; }
|
||||
ul.checklist li > p:first-child > input[type="checkbox"]:first-child { position: relative; top: 1px; }
|
||||
ul.inline { margin: 0 auto 0.625em auto; margin-left: -1.375em; margin-right: 0; padding: 0; list-style: none; overflow: hidden; }
|
||||
ul.inline > li { list-style: none; float: left; margin-left: 1.375em; display: block; }
|
||||
ul.inline > li > * { display: block; }
|
||||
.unstyled dl dt { font-weight: normal; font-style: normal; }
|
||||
ol.arabic { list-style-type: decimal; }
|
||||
ol.decimal { list-style-type: decimal-leading-zero; }
|
||||
ol.loweralpha { list-style-type: lower-alpha; }
|
||||
ol.upperalpha { list-style-type: upper-alpha; }
|
||||
ol.lowerroman { list-style-type: lower-roman; }
|
||||
ol.upperroman { list-style-type: upper-roman; }
|
||||
ol.lowergreek { list-style-type: lower-greek; }
|
||||
.hdlist > table, .colist > table { border: 0; background: none; }
|
||||
.hdlist > table > tbody > tr, .colist > table > tbody > tr { background: none; }
|
||||
td.hdlist1 { padding-right: .75em; font-weight: bold; }
|
||||
td.hdlist1, td.hdlist2 { vertical-align: top; }
|
||||
.literalblock + .colist, .listingblock + .colist { margin-top: -0.5em; }
|
||||
.colist > table tr > td:first-of-type { padding: 0 .75em; line-height: 1; }
|
||||
.colist > table tr > td:last-of-type { padding: 0.25em 0; }
|
||||
.qanda > ol > li > p > em:only-child { color: #1d4b8f; }
|
||||
.thumb, .th { line-height: 0; display: inline-block; border: solid 4px white; -webkit-box-shadow: 0 0 0 1px #dddddd; box-shadow: 0 0 0 1px #dddddd; }
|
||||
.imageblock.left, .imageblock[style*="float: left"] { margin: 0.25em 0.625em 1.25em 0; }
|
||||
.imageblock.right, .imageblock[style*="float: right"] { margin: 0.25em 0 1.25em 0.625em; }
|
||||
.imageblock > .title { margin-bottom: 0; }
|
||||
.imageblock.thumb, .imageblock.th { border-width: 6px; }
|
||||
.imageblock.thumb > .title, .imageblock.th > .title { padding: 0 0.125em; }
|
||||
.image.left, .image.right { margin-top: 0.25em; margin-bottom: 0.25em; display: inline-block; line-height: 0; }
|
||||
.image.left { margin-right: 0.625em; }
|
||||
.image.right { margin-left: 0.625em; }
|
||||
a.image { text-decoration: none; }
|
||||
span.footnote, span.footnoteref { vertical-align: super; font-size: 0.875em; }
|
||||
span.footnote a, span.footnoteref a { text-decoration: none; }
|
||||
span.footnote a:active, span.footnoteref a:active { text-decoration: underline; }
|
||||
#footnotes { padding-top: 0.75em; padding-bottom: 0.75em; margin-bottom: 0.625em; }
|
||||
#footnotes hr { width: 20%; min-width: 6.25em; margin: -.25em 0 .75em 0; border-width: 1px 0 0 0; }
|
||||
#footnotes .footnote { padding: 0 0.375em; line-height: 1.3; font-size: 0.875em; margin-left: 1.2em; text-indent: -1.2em; margin-bottom: .2em; }
|
||||
#footnotes .footnote a:first-of-type { font-weight: bold; text-decoration: none; }
|
||||
#footnotes .footnote:last-of-type { margin-bottom: 0; }
|
||||
#content #footnotes { margin-top: -0.625em; margin-bottom: 0; padding: 0.75em 0; }
|
||||
.gist .file-data > table { border: none; background: #fff; width: 100%; margin-bottom: 0; }
|
||||
.gist .file-data > table td.line-data { width: 99%; }
|
||||
div.unbreakable { page-break-inside: avoid; }
|
||||
.replaceable { font-style: italic; font-color: inherit; font-family: inherit; }
|
||||
.parameter { font-style: italic; font-family: monospace; }
|
||||
.userinput { font-weight: bold; font-family: monospace; }
|
||||
.envar { font-weight: bold; font-family: monospace; font-size: 90%; }
|
||||
.sysitem { font-weight: bold; font-size: 90%; }
|
||||
.package { font-weight: bold; font-size: 90%; }
|
||||
.filename { font-weight: bold; font-style: italic; font-size: 90%; }
|
||||
.big { font-size: larger; }
|
||||
.small { font-size: smaller; }
|
||||
.underline { text-decoration: underline; }
|
||||
.overline { text-decoration: overline; }
|
||||
.line-through { text-decoration: line-through; }
|
||||
.aqua { color: #00bfbf; }
|
||||
.aqua-background { background-color: #00fafa; }
|
||||
.black { color: black; }
|
||||
.black-background { background-color: black; }
|
||||
.blue { color: #0000bf; }
|
||||
.blue-background { background-color: #0000fa; }
|
||||
.fuchsia { color: #bf00bf; }
|
||||
.fuchsia-background { background-color: #fa00fa; }
|
||||
.gray { color: #606060; }
|
||||
.gray-background { background-color: #7d7d7d; }
|
||||
.green { color: #006000; }
|
||||
.green-background { background-color: #007d00; }
|
||||
.lime { color: #00bf00; }
|
||||
.lime-background { background-color: #00fa00; }
|
||||
.maroon { color: #600000; }
|
||||
.maroon-background { background-color: #7d0000; }
|
||||
.navy { color: #000060; }
|
||||
.navy-background { background-color: #00007d; }
|
||||
.olive { color: #606000; }
|
||||
.olive-background { background-color: #7d7d00; }
|
||||
.purple { color: #600060; }
|
||||
.purple-background { background-color: #7d007d; }
|
||||
.red { color: #bf0000; }
|
||||
.red-background { background-color: #fa0000; }
|
||||
.silver { color: #909090; }
|
||||
.silver-background { background-color: #bcbcbc; }
|
||||
.teal { color: #006060; }
|
||||
.teal-background { background-color: #007d7d; }
|
||||
.white { color: #bfbfbf; }
|
||||
.white-background { background-color: #fafafa; }
|
||||
.yellow { color: #bfbf00; }
|
||||
.yellow-background { background-color: #fafa00; }
|
||||
span.icon > .fa { cursor: default; }
|
||||
.admonitionblock td.icon [class^="fa icon-"] { font-size: 2.5em; cursor: default; }
|
||||
.admonitionblock td.icon .icon-note:before { content: "\f05a"; color: #4E9FDD; }
|
||||
.admonitionblock td.icon .icon-tip:before { content: "\f0eb"; color: #2C8596; }
|
||||
.admonitionblock td.icon .icon-warning:before { content: "\f071"; color: #ec7a08; }
|
||||
.admonitionblock td.icon .icon-caution:before { content: "\f06d"; color: #ec7a08; }
|
||||
.admonitionblock td.icon .icon-important:before { content: "\f06a"; color: #c00; }
|
||||
.conum[data-value] { display: inline-block; color: white !important; background-color: #333333; -webkit-border-radius: 100px; border-radius: 100px; text-align: center; width: 20px; height: 20px; font-size: 12px; line-height: 20px; font-family: "Open Sans", "Sans", sans-serif; font-style: normal; font-weight: bold; text-indent: -1px; }
|
||||
.conum[data-value] * { color: white !important; }
|
||||
.conum[data-value] + b { display: none; }
|
||||
.conum[data-value]:after { content: attr(data-value); }
|
||||
pre .conum[data-value] { position: relative; top: -2px; }
|
||||
b.conum * { color: inherit !important; }
|
||||
.conum:not([data-value]):empty { display: none; }
|
||||
.print-only { display: none !important; }
|
||||
@media print { @page { margin: 1.25cm 0.75cm; }
|
||||
* { -webkit-box-shadow: none !important; box-shadow: none !important; text-shadow: none !important; }
|
||||
a, a:visited { color: inherit !important; text-decoration: underline !important; }
|
||||
a[href^="http:"]:after, a[href^="https:"]:after { content: " (" attr(href) ")"; }
|
||||
a[href^="#"], a[href^="#"]:visited, a[href^="mailto:"], a[href^="mailto:"]:visited { text-decoration: none !important; }
|
||||
abbr[title]:after { content: " (" attr(title) ")"; }
|
||||
pre, blockquote { page-break-inside: avoid; }
|
||||
code { color: #191919; }
|
||||
thead { display: table-header-group; }
|
||||
tr, img { page-break-inside: avoid; }
|
||||
img { max-width: 100% !important; }
|
||||
p { orphans: 3; widows: 3; }
|
||||
h2, h3, #toctitle, .sidebarblock > .content > .title, #toctitle, .sidebarblock > .content > .title { page-break-after: avoid; }
|
||||
#toc, .sidebarblock { background: none !important; }
|
||||
#toc { border-bottom: 1px solid #d8d8d8 !important; padding-bottom: 0 !important; }
|
||||
.sect1 { padding-bottom: 0 !important; }
|
||||
.sect1 + .sect1 { border: none !important; }
|
||||
body.book #header { text-align: center; }
|
||||
body.book #header > h1 { border: none !important; margin: 2.5em 0 1em 0; padding: 0; }
|
||||
body.book #header span { line-height: 1.6; }
|
||||
body.book #header br { display: block; }
|
||||
body.book #header br + span { padding-left: 0; }
|
||||
body.book #header br + span:before { content: none !important; }
|
||||
body.book #toc { border: none !important; text-align: left !important; padding: 0 !important; }
|
||||
#footer { background: none !important; }
|
||||
#footer-text { color: #333333 !important; }
|
||||
.hide-on-print { display: none !important; }
|
||||
.print-only { display: block !important; }
|
||||
.hide-for-print { display: none !important; }
|
||||
.show-for-print { display: inherit !important; } }
|
||||
|
||||
.corner-ribbon{
|
||||
width: 16em;
|
||||
background: #3c6eb4 ;
|
||||
position: absolute;
|
||||
top: 3em;
|
||||
right: -4em;
|
||||
text-align: center;
|
||||
line-height: 5ex;
|
||||
color: #dedede;
|
||||
transform: rotate(45deg);
|
||||
-webkit-transform: rotate(45deg);
|
||||
z-index: 999;
|
||||
}
|
||||
.corner-ribbon a { color: #FFFFFF; }
|
|
@ -1,348 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta content="IE=edge" http-equiv="X-UA-Compatible">
|
||||
<meta content="width=device-width, initial-scale=1.0" name="viewport">
|
||||
<title>Defensive Coding Guide | Defensive Coding Guide | Revision History</title>
|
||||
|
||||
<!-- Bootstrap -->
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap-theme.min.css">
|
||||
|
||||
<!-- Overpass Font -->
|
||||
<link rel="stylesheet" href="https://overpass-30e2.kxcdn.com/overpass.css">
|
||||
|
||||
<link href="../../master/_stylesheets/asciibinder.css" rel="stylesheet" />
|
||||
|
||||
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
|
||||
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
|
||||
<!--[if lt IE 9]>
|
||||
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
|
||||
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
|
||||
<![endif]-->
|
||||
|
||||
<link href="../../master/_images/favicon32x32.png" rel="shortcut icon" type="text/css">
|
||||
<!--[if IE]><link rel="shortcut icon" href="../../master/_images/favicon.ico"><![endif]-->
|
||||
<meta content="AsciiBinder" name="application-name">
|
||||
</head>
|
||||
<body>
|
||||
<div class="navbar navbar-default" role="navigation">
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-header">
|
||||
<a class="navbar-brand" href="https://docs.fedoraproject.org/"><img alt="Fedora Documentation" src="../../master/_images/fedora.svg"></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container">
|
||||
<p class="toggle-nav visible-xs pull-left">
|
||||
<button class="btn btn-default btn-sm" type="button" data-toggle="offcanvas">Toggle nav</button>
|
||||
</p>
|
||||
<ol class="breadcrumb">
|
||||
<li class="sitename">
|
||||
<a href="../../index.html">Home</a>
|
||||
</li>
|
||||
<li class="hidden-xs active">
|
||||
<a href="../en-US/index.html">Defensive Coding Guide </a>
|
||||
</li>
|
||||
<li class="hidden-xs active">
|
||||
<a href="../en-US/index.html">Defensive Coding Guide</a>
|
||||
</li>
|
||||
|
||||
<li class="hidden-xs active">
|
||||
Revision History
|
||||
</li>
|
||||
</ol>
|
||||
<div class="row row-offcanvas row-offcanvas-left">
|
||||
<div class="col-xs-8 col-sm-3 col-md-3 sidebar sidebar-offcanvas">
|
||||
<ul class="nav nav-sidebar">
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicGroup0">
|
||||
<span id="tgSpan0" class="fa fa-angle-down"></span>Defensive Coding Guide
|
||||
</a>
|
||||
<ul id="topicGroup0" class="collapse in list-unstyled">
|
||||
<li><a class="" href="../en-US/index.html">Book Information</a></li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-1">
|
||||
<span id="sgSpan-0-1" class="fa fa-caret-right"></span> Programming Languages
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-1" class="nav-tertiary list-unstyled collapse">
|
||||
<li><a class="" href="../en-US/programming-languages/C.html">The C Programming Language</a></li>
|
||||
<li><a class="" href="../en-US/programming-languages/CXX.html">The C++ Programming Language</a></li>
|
||||
<li><a class="" href="../en-US/programming-languages/Java.html">The Java Programming Language</a></li>
|
||||
<li><a class="" href="../en-US/programming-languages/Python.html">The Python Programming Language</a></li>
|
||||
<li><a class="" href="../en-US/programming-languages/Shell.html">Shell Programming and bash</a></li>
|
||||
<li><a class="" href="../en-US/programming-languages/Go.html">The Go Programming Language</a></li>
|
||||
<li><a class="" href="../en-US/programming-languages/Vala.html">The Vala Programming Language</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-2">
|
||||
<span id="sgSpan-0-2" class="fa fa-caret-right"></span> Specific Programming Tasks
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-2" class="nav-tertiary list-unstyled collapse">
|
||||
<li><a class="" href="../en-US/tasks/Tasks-Library_Design.html">Library Design</a></li>
|
||||
<li><a class="" href="../en-US/tasks/Tasks-Descriptors.html">File Descriptor Management</a></li>
|
||||
<li><a class="" href="../en-US/tasks/Tasks-File_System.html">File System Manipulation</a></li>
|
||||
<li><a class="" href="../en-US/tasks/Tasks-Temporary_Files.html">Temporary Files</a></li>
|
||||
<li><a class="" href="../en-US/tasks/Tasks-Processes.html">Processes</a></li>
|
||||
<li><a class="" href="../en-US/tasks/Tasks-Serialization.html">Serialization and Deserialization</a></li>
|
||||
<li><a class="" href="../en-US/tasks/Tasks-Cryptography.html">Cryptography</a></li>
|
||||
<li><a class="" href="../en-US/tasks/Tasks-Packaging.html">RPM Packaging</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-3">
|
||||
<span id="sgSpan-0-3" class="fa fa-caret-right"></span> Implementing Security Features
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-3" class="nav-tertiary list-unstyled collapse">
|
||||
<li><a class="" href="../en-US/features/Features-Authentication.html">Authentication and Authorization</a></li>
|
||||
<li><a class="" href="../en-US/features/Features-TLS.html">Transport Layer Security (TLS)</a></li>
|
||||
<li><a class="" href="../en-US/features/Features-HSM.html">Hardware Security Modules and Smart Cards</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class=" active" href="../en-US/Revision_History.html">Revision History</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-9 col-md-9 main">
|
||||
<div class="page-header">
|
||||
<h2>Revision History</h2>
|
||||
</div>
|
||||
<div class="dlist">
|
||||
<dl>
|
||||
<dt class="hdlist1"><code>1.5</code></dt>
|
||||
<dd>
|
||||
<p>Fri Dec 1 2017, Mirek Jahoda (<a href="mailto:mjahoda@redhat.com">mjahoda@redhat.com</a>)</p>
|
||||
<div class="ulist">
|
||||
<ul>
|
||||
<li>
|
||||
<p>First release in AsciiDoc</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Many updates in the crypto-related sections</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Grammar and typography fixes</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</dd>
|
||||
<dt class="hdlist1"><code>1.3-1</code></dt>
|
||||
<dd>
|
||||
<p>Mon Oct 13 2014, Florian Weimer (<a href="mailto:fweimer@redhat.com">fweimer@redhat.com</a>)</p>
|
||||
<div class="ulist">
|
||||
<ul>
|
||||
<li>
|
||||
<p>Go: Mention default value handling in deserialization</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Shell: New chapter</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</dd>
|
||||
<dt class="hdlist1"><code>1.2-1</code></dt>
|
||||
<dd>
|
||||
<p>Wed Jul 16 2014, Florian Weimer (<a href="mailto:fweimer@redhat.com">fweimer@redhat.com</a>)</p>
|
||||
<div class="ulist">
|
||||
<ul>
|
||||
<li>
|
||||
<p>C: Corrected the <code>strncat</code> example</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>C: Mention mixed signed/unsigned comparisons</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>C: Unsigned overflow checking example</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>C++: <code>operator new[]</code> has been fixed in GCC</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>C++: Additional material on <code>std::string</code>, iterators</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>OpenSSL: Mention <code class="command">openssl genrsa</code> entropy issue</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Packaging: X.509 key generation</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Go, Vala: Add short chapters</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Serialization: Notes on fragmentation and reassembly</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</dd>
|
||||
<dt class="hdlist1"><code>1.1-1</code></dt>
|
||||
<dd>
|
||||
<p>Tue Aug 27 2013, Eric Christensen (<a href="mailto:sparks@redhat.com">sparks@redhat.com</a>)</p>
|
||||
<div class="ulist">
|
||||
<ul>
|
||||
<li>
|
||||
<p>Add a chapter which covers some Java topics.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Deserialization: Warn about Java’s java.beans.XMLDecoder.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>C: Correct the advice on array allocation
|
||||
(<a href="https://bugzilla.redhat.com/show_bug.cgi?id=995595">bug 995595</a>).</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>C: Add material on global variables.</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</dd>
|
||||
<dt class="hdlist1"><code>1.0-1</code></dt>
|
||||
<dd>
|
||||
<p>Thu May 09 2013, Eric Christensen (<a href="mailto:sparks@redhat.com">sparks@redhat.com</a>)</p>
|
||||
<div class="ulist">
|
||||
<ul>
|
||||
<li>
|
||||
<p>Added more C and C++ examples.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>TLS Client NSS: Rely on NSS 3.14 cipher suite defaults.</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</dd>
|
||||
<dt class="hdlist1"><code>0-1</code></dt>
|
||||
<dd>
|
||||
<p>Thu Mar 7 2013, Eric Christensen (<a href="mailto:sparks@redhat.com">sparks@redhat.com</a>)</p>
|
||||
<div class="ulist">
|
||||
<ul>
|
||||
<li>
|
||||
<p>Initial publication.</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="bottom" class="text-muted py-3" >
|
||||
<div class="foot">
|
||||
<div class="container">
|
||||
<div class="row footerlinks">
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">About</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Overview">About Fedora</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/sponsors">Sponsors</a></dd>
|
||||
<dd><a href="https://fedoramagazine.org">Fedora Magazine</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Legal:Main#Legal">Legal</a></dd>
|
||||
</dl>
|
||||
<ul class="list-inline">
|
||||
<li>
|
||||
<a href="https://www.facebook.com/TheFedoraProject" class="btn-social btn-outline"><i class="fa fa-fw fa-facebook"></i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://plus.google.com/112917221531140868607" class="btn-social btn-outline"><i class="fa fa-fw fa-google-plus"></i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://twitter.com/fedora" class="btn-social btn-outline"><i class="fa fa-fw fa-twitter"></i></a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title uppercase">Download</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://getfedora.org/en/workstation/download">Get Fedora Workstation</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/server/download">Get Fedora Server</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/atomic/download">Get Fedora Atomic</a></dd>
|
||||
<dd><a href="https://spins.fedoraproject.org">Fedora Spins</a></dd>
|
||||
<dd><a href="https://labs.fedoraproject.org">Fedora Labs</a></dd>
|
||||
<dd><a href="https://arm.fedoraproject.org">Fedora ARM<span class="sup">®</span></a></dd>
|
||||
<dd><a href="https://alt.fedoraproject.org/">Alternative Downloads</a></dd>
|
||||
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">Support</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Communicating_and_getting_help">Get Help</a></dd>
|
||||
<dd><a href="https://ask.fedoraproject.org/">Ask Fedora</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Common_F27_bugs">Common Bugs</a></dd>
|
||||
<dd><a href="https://developer.fedoraproject.org/">Fedora Developer Portal</a></dd>
|
||||
<dd><a href="https://docs.fedoraproject.org/f27/install-guide/index.html">Installation Guide</a></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">Join</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Join">Join Fedora</a></dd>
|
||||
<dd><a href="http://fedoraplanet.org">Planet Fedora</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/SIGs">Fedora SIGs</a></dd>
|
||||
<dd><a href="https://admin.fedoraproject.org/accounts/">Fedora Account System</a></dd>
|
||||
<dd><a href="https://fedoracommunity.org/">Fedora Community</a></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- /row of widgets -->
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-2">
|
||||
<div class="widget-body">
|
||||
<a href="https://www.redhat.com/"><img class="rh-logo" src="../../master/_images/redhat-logo.png" alt="Red Hat Logo" /></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-7">
|
||||
<div class="widget-body">
|
||||
<p class="sponsor">Fedora is sponsored by Red Hat.</p>
|
||||
<p class="sponsor"><a href="https://www.redhat.com/en/technologies/linux-platforms/articles/relationship-between-fedora-and-rhel">Learn more about the relationship between Red Hat and Fedora »</a></p>
|
||||
<p class="copy">© 2017 Red Hat, Inc. and others. Please send any comments or corrections to the <a href="https://pagure.io/fedora-docs/docs-fp-o">documentation team</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- /row of widgets -->
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
|
||||
<!-- Latest compiled and minified JavaScript -->
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
|
||||
<script src="../../master/_javascripts/bootstrap-offcanvas.js" type="text/javascript"></script>
|
||||
<script type="text/javascript">
|
||||
/*<![CDATA[*/
|
||||
$(document).ready(function() {
|
||||
$("[id^='topicGroup']").on('show.bs.collapse', function (event) {
|
||||
if (!($(event.target).attr('id').match(/^topicSubGroup/))) {
|
||||
$(this).parent().find("[id^='tgSpan']").toggleClass("fa-angle-right fa-angle-down");
|
||||
}
|
||||
});
|
||||
$("[id^='topicGroup']").on('hide.bs.collapse', function (event) {
|
||||
if (!($(event.target).attr('id').match(/^topicSubGroup/))) {
|
||||
$(this).parent().find("[id^='tgSpan']").toggleClass("fa-angle-right fa-angle-down");
|
||||
}
|
||||
});
|
||||
$("[id^='topicSubGroup']").on('show.bs.collapse', function () {
|
||||
$(this).parent().find("[id^='sgSpan']").toggleClass("fa-caret-right fa-caret-down");
|
||||
});
|
||||
$("[id^='topicSubGroup']").on('hide.bs.collapse', function () {
|
||||
$(this).parent().find("[id^='sgSpan']").toggleClass("fa-caret-right fa-caret-down");
|
||||
});
|
||||
});
|
||||
/*]]>*/
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -1,410 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta content="IE=edge" http-equiv="X-UA-Compatible">
|
||||
<meta content="width=device-width, initial-scale=1.0" name="viewport">
|
||||
<title>Defensive Coding Guide | Defensive Coding Guide | Implementing Security Features | Authentication and Authorization</title>
|
||||
|
||||
<!-- Bootstrap -->
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap-theme.min.css">
|
||||
|
||||
<!-- Overpass Font -->
|
||||
<link rel="stylesheet" href="https://overpass-30e2.kxcdn.com/overpass.css">
|
||||
|
||||
<link href="../../../master/_stylesheets/asciibinder.css" rel="stylesheet" />
|
||||
|
||||
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
|
||||
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
|
||||
<!--[if lt IE 9]>
|
||||
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
|
||||
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
|
||||
<![endif]-->
|
||||
|
||||
<link href="../../../master/_images/favicon32x32.png" rel="shortcut icon" type="text/css">
|
||||
<!--[if IE]><link rel="shortcut icon" href="../../../master/_images/favicon.ico"><![endif]-->
|
||||
<meta content="AsciiBinder" name="application-name">
|
||||
</head>
|
||||
<body>
|
||||
<div class="navbar navbar-default" role="navigation">
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-header">
|
||||
<a class="navbar-brand" href="https://docs.fedoraproject.org/"><img alt="Fedora Documentation" src="../../../master/_images/fedora.svg"></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container">
|
||||
<p class="toggle-nav visible-xs pull-left">
|
||||
<button class="btn btn-default btn-sm" type="button" data-toggle="offcanvas">Toggle nav</button>
|
||||
</p>
|
||||
<ol class="breadcrumb">
|
||||
<li class="sitename">
|
||||
<a href="../../../index.html">Home</a>
|
||||
</li>
|
||||
<li class="hidden-xs active">
|
||||
<a href="../../en-US/index.html">Defensive Coding Guide </a>
|
||||
</li>
|
||||
<li class="hidden-xs active">
|
||||
<a href="../../en-US/index.html">Defensive Coding Guide</a>
|
||||
</li>
|
||||
<li class="hidden-xs active"><a href="../../en-US/features/Features-Authentication.html">Implementing Security Features</a></li>
|
||||
<li class="hidden-xs active">
|
||||
Authentication and Authorization
|
||||
</li>
|
||||
</ol>
|
||||
<div class="row row-offcanvas row-offcanvas-left">
|
||||
<div class="col-xs-8 col-sm-3 col-md-3 sidebar sidebar-offcanvas">
|
||||
<ul class="nav nav-sidebar">
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicGroup0">
|
||||
<span id="tgSpan0" class="fa fa-angle-down"></span>Defensive Coding Guide
|
||||
</a>
|
||||
<ul id="topicGroup0" class="collapse in list-unstyled">
|
||||
<li><a class="" href="../../en-US/index.html">Book Information</a></li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-1">
|
||||
<span id="sgSpan-0-1" class="fa fa-caret-right"></span> Programming Languages
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-1" class="nav-tertiary list-unstyled collapse">
|
||||
<li><a class="" href="../../en-US/programming-languages/C.html">The C Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/CXX.html">The C++ Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Java.html">The Java Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Python.html">The Python Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Shell.html">Shell Programming and bash</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Go.html">The Go Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Vala.html">The Vala Programming Language</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-2">
|
||||
<span id="sgSpan-0-2" class="fa fa-caret-right"></span> Specific Programming Tasks
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-2" class="nav-tertiary list-unstyled collapse">
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Library_Design.html">Library Design</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Descriptors.html">File Descriptor Management</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-File_System.html">File System Manipulation</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Temporary_Files.html">Temporary Files</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Processes.html">Processes</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Serialization.html">Serialization and Deserialization</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Cryptography.html">Cryptography</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Packaging.html">RPM Packaging</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-3">
|
||||
<span id="sgSpan-0-3" class="fa fa-caret-down"></span> Implementing Security Features
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-3" class="nav-tertiary list-unstyled collapse in">
|
||||
<li><a class=" active" href="../../en-US/features/Features-Authentication.html">Authentication and Authorization</a></li>
|
||||
<li><a class="" href="../../en-US/features/Features-TLS.html">Transport Layer Security (TLS)</a></li>
|
||||
<li><a class="" href="../../en-US/features/Features-HSM.html">Hardware Security Modules and Smart Cards</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="" href="../../en-US/Revision_History.html">Revision History</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-9 col-md-9 main">
|
||||
<div class="page-header">
|
||||
<h2>Authentication and Authorization</h2>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="sect-Defensive_Coding-Authentication-Server"><a class="anchor" href="#sect-Defensive_Coding-Authentication-Server"></a>Authenticating Servers</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>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:</p>
|
||||
</div>
|
||||
<div class="ulist">
|
||||
<ul>
|
||||
<li>
|
||||
<p>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.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>The server uses a TLS certificate which is expected by the
|
||||
client (perhaps it is stored in a configuration file read by
|
||||
the client). In this case, no host name checking is
|
||||
required.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>On Linux, UNIX domain sockets (of the
|
||||
<code>PF_UNIX</code> protocol family, sometimes called
|
||||
<code>PF_LOCAL</code>) are restricted by file system
|
||||
permissions. If the server socket path is not
|
||||
world-writable, the server identity cannot be spoofed by
|
||||
local users.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Port numbers less than 1024 (<strong>trusted
|
||||
ports</strong>) can only be used by
|
||||
<code>root</code>, 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.)</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>TLS (<a href="#chap-Defensive_Coding-TLS">[chap-Defensive_Coding-TLS]</a>) is the
|
||||
recommended way for securing connections over untrusted
|
||||
networks.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>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.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="sect-Defensive_Coding-Authentication-Host_based"><a class="anchor" href="#sect-Defensive_Coding-Authentication-Host_based"></a>Host-based Authentication</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>Host-based authentication uses access control lists (ACLs) to
|
||||
accept or deny requests from clients. This authentication
|
||||
method comes in two flavors: IP-based (or, more generally,
|
||||
address-based) and name-based (with the name coming from DNS or
|
||||
<code>/etc/hosts</code>). 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.)</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>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.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>The names returned by <code>gethostbyaddr</code> and
|
||||
<code>getnameinfo</code> 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
|
||||
<code>gethostbyaddr</code> or
|
||||
<code>getaddrinfo</code> has to be performed. The name
|
||||
is only valid if the original address is found among the results
|
||||
of the forward lookup (<strong>double-reverse
|
||||
lookup</strong>).</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>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.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>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.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>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.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="sect-Defensive_Coding-Authentication-UNIX_Domain"><a class="anchor" href="#sect-Defensive_Coding-Authentication-UNIX_Domain"></a>UNIX Domain Socket Authentication</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>UNIX domain sockets (with address family
|
||||
<code>AF_UNIX</code> or <code>AF_LOCAL</code>) are
|
||||
restricted to the local host and offer a special authentication
|
||||
mechanism: credentials passing.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Nowadays, most systems support the
|
||||
<code>SO_PEERCRED</code> (Linux) or
|
||||
<code>LOCAL_PEERCRED</code> (FreeBSD) socket options, or
|
||||
the <code>getpeereid</code> (other BSDs, OS 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.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Historically, credentials passing was implemented using
|
||||
ancillary data in the <code>sendmsg</code> and
|
||||
<code>recvmsg</code> 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.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>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
|
||||
<code>getpwuid</code> (or
|
||||
<code>getpwuid_r</code>) and
|
||||
<code>getgrouplist</code>. Using the PID and
|
||||
information from <code>/proc/PID/status</code> is prone
|
||||
to race conditions and insecure.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="sect-Defensive_Coding-Authentication-Netlink"><a class="anchor" href="#sect-Defensive_Coding-Authentication-Netlink"></a><code>AF_NETLINK</code> Authentication of Origin</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>Netlink messages are used as a high-performance data transfer
|
||||
mechanism between the kernel and the user space. Traditionally,
|
||||
they are used to exchange information related to the network
|
||||
stack, such as routing table entries.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>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
|
||||
<code>nl_pid</code> in the <code>sockaddr_nl</code>
|
||||
structure is <code>0</code>. (This structure can be
|
||||
obtained using <code>recvfrom</code> or
|
||||
<code>recvmsg</code>, it is different from the
|
||||
<code>nlmsghdr</code> structure.) The kernel does not
|
||||
prevent other processes from sending unicast Netlink messages,
|
||||
but the <code>nl_pid</code> field in the sender’s socket
|
||||
address will be non-zero in such cases.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Applications should not use <code>AF_NETLINK</code>
|
||||
sockets as an IPC mechanism among processes, but prefer UNIX
|
||||
domain sockets for this tasks.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="bottom" class="text-muted py-3" >
|
||||
<div class="foot">
|
||||
<div class="container">
|
||||
<div class="row footerlinks">
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">About</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Overview">About Fedora</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/sponsors">Sponsors</a></dd>
|
||||
<dd><a href="https://fedoramagazine.org">Fedora Magazine</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Legal:Main#Legal">Legal</a></dd>
|
||||
</dl>
|
||||
<ul class="list-inline">
|
||||
<li>
|
||||
<a href="https://www.facebook.com/TheFedoraProject" class="btn-social btn-outline"><i class="fa fa-fw fa-facebook"></i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://plus.google.com/112917221531140868607" class="btn-social btn-outline"><i class="fa fa-fw fa-google-plus"></i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://twitter.com/fedora" class="btn-social btn-outline"><i class="fa fa-fw fa-twitter"></i></a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title uppercase">Download</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://getfedora.org/en/workstation/download">Get Fedora Workstation</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/server/download">Get Fedora Server</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/atomic/download">Get Fedora Atomic</a></dd>
|
||||
<dd><a href="https://spins.fedoraproject.org">Fedora Spins</a></dd>
|
||||
<dd><a href="https://labs.fedoraproject.org">Fedora Labs</a></dd>
|
||||
<dd><a href="https://arm.fedoraproject.org">Fedora ARM<span class="sup">®</span></a></dd>
|
||||
<dd><a href="https://alt.fedoraproject.org/">Alternative Downloads</a></dd>
|
||||
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">Support</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Communicating_and_getting_help">Get Help</a></dd>
|
||||
<dd><a href="https://ask.fedoraproject.org/">Ask Fedora</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Common_F27_bugs">Common Bugs</a></dd>
|
||||
<dd><a href="https://developer.fedoraproject.org/">Fedora Developer Portal</a></dd>
|
||||
<dd><a href="https://docs.fedoraproject.org/f27/install-guide/index.html">Installation Guide</a></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">Join</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Join">Join Fedora</a></dd>
|
||||
<dd><a href="http://fedoraplanet.org">Planet Fedora</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/SIGs">Fedora SIGs</a></dd>
|
||||
<dd><a href="https://admin.fedoraproject.org/accounts/">Fedora Account System</a></dd>
|
||||
<dd><a href="https://fedoracommunity.org/">Fedora Community</a></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- /row of widgets -->
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-2">
|
||||
<div class="widget-body">
|
||||
<a href="https://www.redhat.com/"><img class="rh-logo" src="../../../master/_images/redhat-logo.png" alt="Red Hat Logo" /></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-7">
|
||||
<div class="widget-body">
|
||||
<p class="sponsor">Fedora is sponsored by Red Hat.</p>
|
||||
<p class="sponsor"><a href="https://www.redhat.com/en/technologies/linux-platforms/articles/relationship-between-fedora-and-rhel">Learn more about the relationship between Red Hat and Fedora »</a></p>
|
||||
<p class="copy">© 2017 Red Hat, Inc. and others. Please send any comments or corrections to the <a href="https://pagure.io/fedora-docs/docs-fp-o">documentation team</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- /row of widgets -->
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
|
||||
<!-- Latest compiled and minified JavaScript -->
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
|
||||
<script src="../../../master/_javascripts/bootstrap-offcanvas.js" type="text/javascript"></script>
|
||||
<script type="text/javascript">
|
||||
/*<![CDATA[*/
|
||||
$(document).ready(function() {
|
||||
$("[id^='topicGroup']").on('show.bs.collapse', function (event) {
|
||||
if (!($(event.target).attr('id').match(/^topicSubGroup/))) {
|
||||
$(this).parent().find("[id^='tgSpan']").toggleClass("fa-angle-right fa-angle-down");
|
||||
}
|
||||
});
|
||||
$("[id^='topicGroup']").on('hide.bs.collapse', function (event) {
|
||||
if (!($(event.target).attr('id').match(/^topicSubGroup/))) {
|
||||
$(this).parent().find("[id^='tgSpan']").toggleClass("fa-angle-right fa-angle-down");
|
||||
}
|
||||
});
|
||||
$("[id^='topicSubGroup']").on('show.bs.collapse', function () {
|
||||
$(this).parent().find("[id^='sgSpan']").toggleClass("fa-caret-right fa-caret-down");
|
||||
});
|
||||
$("[id^='topicSubGroup']").on('hide.bs.collapse', function () {
|
||||
$(this).parent().find("[id^='sgSpan']").toggleClass("fa-caret-right fa-caret-down");
|
||||
});
|
||||
});
|
||||
/*]]>*/
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -1,617 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta content="IE=edge" http-equiv="X-UA-Compatible">
|
||||
<meta content="width=device-width, initial-scale=1.0" name="viewport">
|
||||
<title>Defensive Coding Guide | Defensive Coding Guide | Implementing Security Features | Hardware Security Modules and Smart Cards</title>
|
||||
|
||||
<!-- Bootstrap -->
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap-theme.min.css">
|
||||
|
||||
<!-- Overpass Font -->
|
||||
<link rel="stylesheet" href="https://overpass-30e2.kxcdn.com/overpass.css">
|
||||
|
||||
<link href="../../../master/_stylesheets/asciibinder.css" rel="stylesheet" />
|
||||
|
||||
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
|
||||
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
|
||||
<!--[if lt IE 9]>
|
||||
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
|
||||
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
|
||||
<![endif]-->
|
||||
|
||||
<link href="../../../master/_images/favicon32x32.png" rel="shortcut icon" type="text/css">
|
||||
<!--[if IE]><link rel="shortcut icon" href="../../../master/_images/favicon.ico"><![endif]-->
|
||||
<meta content="AsciiBinder" name="application-name">
|
||||
</head>
|
||||
<body>
|
||||
<div class="navbar navbar-default" role="navigation">
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-header">
|
||||
<a class="navbar-brand" href="https://docs.fedoraproject.org/"><img alt="Fedora Documentation" src="../../../master/_images/fedora.svg"></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container">
|
||||
<p class="toggle-nav visible-xs pull-left">
|
||||
<button class="btn btn-default btn-sm" type="button" data-toggle="offcanvas">Toggle nav</button>
|
||||
</p>
|
||||
<ol class="breadcrumb">
|
||||
<li class="sitename">
|
||||
<a href="../../../index.html">Home</a>
|
||||
</li>
|
||||
<li class="hidden-xs active">
|
||||
<a href="../../en-US/index.html">Defensive Coding Guide </a>
|
||||
</li>
|
||||
<li class="hidden-xs active">
|
||||
<a href="../../en-US/index.html">Defensive Coding Guide</a>
|
||||
</li>
|
||||
<li class="hidden-xs active"><a href="../../en-US/features/Features-Authentication.html">Implementing Security Features</a></li>
|
||||
<li class="hidden-xs active">
|
||||
Hardware Security Modules and Smart Cards
|
||||
</li>
|
||||
</ol>
|
||||
<div class="row row-offcanvas row-offcanvas-left">
|
||||
<div class="col-xs-8 col-sm-3 col-md-3 sidebar sidebar-offcanvas">
|
||||
<ul class="nav nav-sidebar">
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicGroup0">
|
||||
<span id="tgSpan0" class="fa fa-angle-down"></span>Defensive Coding Guide
|
||||
</a>
|
||||
<ul id="topicGroup0" class="collapse in list-unstyled">
|
||||
<li><a class="" href="../../en-US/index.html">Book Information</a></li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-1">
|
||||
<span id="sgSpan-0-1" class="fa fa-caret-right"></span> Programming Languages
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-1" class="nav-tertiary list-unstyled collapse">
|
||||
<li><a class="" href="../../en-US/programming-languages/C.html">The C Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/CXX.html">The C++ Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Java.html">The Java Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Python.html">The Python Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Shell.html">Shell Programming and bash</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Go.html">The Go Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Vala.html">The Vala Programming Language</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-2">
|
||||
<span id="sgSpan-0-2" class="fa fa-caret-right"></span> Specific Programming Tasks
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-2" class="nav-tertiary list-unstyled collapse">
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Library_Design.html">Library Design</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Descriptors.html">File Descriptor Management</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-File_System.html">File System Manipulation</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Temporary_Files.html">Temporary Files</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Processes.html">Processes</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Serialization.html">Serialization and Deserialization</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Cryptography.html">Cryptography</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Packaging.html">RPM Packaging</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-3">
|
||||
<span id="sgSpan-0-3" class="fa fa-caret-down"></span> Implementing Security Features
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-3" class="nav-tertiary list-unstyled collapse in">
|
||||
<li><a class="" href="../../en-US/features/Features-Authentication.html">Authentication and Authorization</a></li>
|
||||
<li><a class="" href="../../en-US/features/Features-TLS.html">Transport Layer Security (TLS)</a></li>
|
||||
<li><a class=" active" href="../../en-US/features/Features-HSM.html">Hardware Security Modules and Smart Cards</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="" href="../../en-US/Revision_History.html">Revision History</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-9 col-md-9 main">
|
||||
<div class="page-header">
|
||||
<h2>Hardware Security Modules and Smart Cards</h2>
|
||||
</div>
|
||||
<div id="preamble">
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>Hardware Security Modules (HSMs) are specialized hardware intended
|
||||
to protect private keys on server systems. They store internally
|
||||
the private keys (e.g., RSA keys), and provide access to operations
|
||||
with the keys without exposing the keys. That access, is provided using
|
||||
a standardized API, which across Fedora is PKCS#11.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Smart cards are small cards with a micro processor, often combined with a
|
||||
USB reader resembling a USB stick. They are very similar in nature with
|
||||
HSMs as they can also be used to protect private keys and are almost
|
||||
universally accessed via the PKCS#11 API. The main distinguishers from HSMs
|
||||
is their inferior performance and often, the available hardware protection mechanisms.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Typically a smart card or HSM relies on a shared library to provide functionality.
|
||||
This shared library follows the PKCS#11 API and thus is often referred to as
|
||||
a PKCS#11 module. In Fedora the <code>opensc</code>
|
||||
shared module (<code>opensc-pkcs11.so</code>) can be used for the majority
|
||||
of smart cards available in the market. By convention these modules are located
|
||||
at <code>/usr/lib64/pkcs11</code>. They can be used directly, or via
|
||||
a higher level library.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>All the major crypto libraries (NSS, GnuTLS and OpenSSL in Fedora) support
|
||||
hardware security modules and smart cards, by providing wrappers over the
|
||||
PKCS#11 API. However, the level of support varies, as well as the ease of
|
||||
use of such modules and its integration to the overall library API.</p>
|
||||
</div>
|
||||
<div class="ulist">
|
||||
<ul>
|
||||
<li>
|
||||
<p>The PKCS#11 API does provide an API to access HSMs or smart cards, but
|
||||
does not provide any method of discovering which HSMs or smart cards are
|
||||
available in the system. In Fedora and modules are registered via <a href="https://p11-glue.freedesktop.org/doc/p11-kit/pkcs11-conf.html">p11-kit
|
||||
configuration files</a>, stored at <code>/etc/pkcs11/modules/</code>. For applications using
|
||||
<code>engine_pkcs11</code> or GnuTLS the registered modules are
|
||||
available without further configuration. Other applications will have to load
|
||||
the <code>p11-kit-proxy.so</code> module.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Most crypto libraries support the <a href="https://tools.ietf.org/html/rfc7512">PKCS#11 URLs scheme</a>
|
||||
to identify objects stored in an HSM, however that support is not yet universal.
|
||||
Some support transparent usage of PKCS#11 objects, e.g., specifying
|
||||
a PKCS#11 object instead of a file, while others require to use
|
||||
specialized APIs for such objects.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Objects stored in an HSM or smart card can be protected with a PIN. As such,
|
||||
libraries typically require to set a PIN handling function for accessing private keys,
|
||||
or the PIN can be passed along with a PKCS#11 URL and the pin-value parameter.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Obtaining a Hardware Security Module, or including it on a continuous integration
|
||||
testing is not always feasible. For testing purposes smart cards supported by the OpenSC
|
||||
project can be used, as well as software modules like <code>softhsm</code> which
|
||||
provides a tool to setup a software HSM, and a PKCS#11 library.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>The PKCS#11 API requires applications that use fork to reinitialize the used PKCS#11
|
||||
modules. This is an uncommon requirement, which has led to several bugs across
|
||||
applications in Fedora which used PKCS#11 directly. To make things more complicated
|
||||
software PKCS#11 module like <code>softhsm</code> do not require this re-initialization
|
||||
leading to applications working against software modules but failing with hardware
|
||||
modules or smart cards. The wrapper PKCS#11 APIs provided by NSS, GnuTLS and
|
||||
engine_pkcs11 (OpenSSL) handle the reinitialization after fork requirement transparently.</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="sect-Defensive_Coding-HSM-OpenSSL"><a class="anchor" href="#sect-Defensive_Coding-HSM-OpenSSL"></a>OpenSSL HSM Support</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>OpenSSL does not have native support for PKCS#11. It can
|
||||
provide PKCS#11 support through the OpenSC’s project
|
||||
<code>pkcs11</code> engine (formerly known as <code>engine_pkcs11</code>).
|
||||
As such software intended to use HSMs, must utilize that engine.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Engine <code>pkcs11</code> supports loading stored objects via PKCS#11 URLs.
|
||||
If no PKCS#11 module is specified the engine will use the system-wide registered
|
||||
modules via <code>p11-kit-proxy.so</code>.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>The following example demonstrates the initialization of the pkcs11 engine
|
||||
and its usage to sign data.</p>
|
||||
</div>
|
||||
<div id="ex-Defensive_Coding-HSM-OpenSSL" class="exampleblock">
|
||||
<div class="title">Example 1. Signing data with HSM and OpenSSL</div>
|
||||
<div class="content">
|
||||
<div class="listingblock">
|
||||
<div class="content">
|
||||
<pre class="CodeRay highlight"><code data-lang="c">OpenSSL_add_all_algorithms();
|
||||
ERR_load_crypto_strings();
|
||||
ERR_clear_error();
|
||||
ENGINE_load_builtin_engines();
|
||||
|
||||
e = ENGINE_by_id(<span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">"</span><span style="color:#D20">pkcs11</span><span style="color:#710">"</span></span>);
|
||||
<span style="color:#080;font-weight:bold">if</span> (!e) {
|
||||
display_openssl_errors(__LINE__);
|
||||
exit(<span style="color:#00D">1</span>);
|
||||
}
|
||||
|
||||
<span style="color:#080;font-weight:bold">if</span> (module_path) {
|
||||
fprintf(stderr, <span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">"</span><span style="color:#D20">loading: %s</span><span style="color:#b0b">\n</span><span style="color:#710">"</span></span>, module_path);
|
||||
<span style="color:#080;font-weight:bold">if</span> (!ENGINE_ctrl_cmd_string(e, <span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">"</span><span style="color:#D20">MODULE_PATH</span><span style="color:#710">"</span></span>, module_path, <span style="color:#00D">0</span>)) {
|
||||
display_openssl_errors(__LINE__);
|
||||
exit(<span style="color:#00D">1</span>);
|
||||
}
|
||||
}
|
||||
|
||||
<span style="color:#080;font-weight:bold">if</span> (!ENGINE_init(e)) {
|
||||
display_openssl_errors(__LINE__);
|
||||
exit(<span style="color:#00D">1</span>);
|
||||
}
|
||||
|
||||
<span style="color:#080;font-weight:bold">if</span> (key_pass && !ENGINE_ctrl_cmd_string(e, <span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">"</span><span style="color:#D20">PIN</span><span style="color:#710">"</span></span>, key_pass, <span style="color:#00D">0</span>)) {
|
||||
display_openssl_errors(__LINE__);
|
||||
exit(<span style="color:#00D">1</span>);
|
||||
}
|
||||
|
||||
private_key = ENGINE_load_private_key(e, private_key_name, <span style="color:#069">NULL</span>, <span style="color:#069">NULL</span>);
|
||||
<span style="color:#080;font-weight:bold">if</span> (!private_key) {
|
||||
fprintf(stderr, <span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">"</span><span style="color:#D20">cannot load: %s</span><span style="color:#b0b">\n</span><span style="color:#710">"</span></span>, private_key_name);
|
||||
display_openssl_errors(__LINE__);
|
||||
exit(<span style="color:#00D">1</span>);
|
||||
}
|
||||
|
||||
display_openssl_errors(__LINE__);
|
||||
|
||||
digest_algo = EVP_get_digestbyname(<span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">"</span><span style="color:#D20">sha256</span><span style="color:#710">"</span></span>);
|
||||
|
||||
EVP_MD_CTX_init(&ctx);
|
||||
<span style="color:#080;font-weight:bold">if</span> (EVP_DigestInit(&ctx, digest_algo) <= <span style="color:#00D">0</span>) {
|
||||
display_openssl_errors(__LINE__);
|
||||
exit(<span style="color:#00D">1</span>);
|
||||
}
|
||||
|
||||
EVP_SignInit(&ctx, digest_algo);
|
||||
|
||||
<span style="color:#579">#define</span> TEST_DATA <span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">"</span><span style="color:#D20">test data</span><span style="color:#710">"</span></span>
|
||||
<span style="color:#080;font-weight:bold">if</span> (EVP_SignUpdate(&ctx, TEST_DATA, <span style="color:#080;font-weight:bold">sizeof</span>(TEST_DATA) - <span style="color:#00D">1</span>) <= <span style="color:#00D">0</span>) {
|
||||
display_openssl_errors(__LINE__);
|
||||
exit(<span style="color:#00D">1</span>);
|
||||
}
|
||||
|
||||
n = <span style="color:#080;font-weight:bold">sizeof</span>(buf);
|
||||
<span style="color:#080;font-weight:bold">if</span> (EVP_SignFinal(&ctx, buf, &n, private_key) <= <span style="color:#00D">0</span>) {
|
||||
display_openssl_errors(__LINE__);
|
||||
exit(<span style="color:#00D">1</span>);
|
||||
}
|
||||
|
||||
EVP_PKEY_free(private_key);
|
||||
ENGINE_finish(e);</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="sect-Defensive_Coding-HSM-GNUTLS"><a class="anchor" href="#sect-Defensive_Coding-HSM-GNUTLS"></a>GnuTLS HSM Support</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>GnuTLS supports PKCS#11 natively. Most of the API functions
|
||||
accepting certificate files, can also accept PKCS#11 URLs, thus
|
||||
requiring minor or no modifications to applications in order
|
||||
to support HSMs. In most cases applications must be modified
|
||||
to install a PIN callback function.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>The following example demonstrates the initialization of the pkcs11 engine
|
||||
and its usage to sign data.</p>
|
||||
</div>
|
||||
<div id="ex-Defensive_Coding-HSM-GNUTLS" class="exampleblock">
|
||||
<div class="title">Example 2. Signing data with HSM and GnuTLS</div>
|
||||
<div class="content">
|
||||
<div class="listingblock">
|
||||
<div class="content">
|
||||
<pre class="CodeRay highlight"><code data-lang="c"><span style="color:#080;font-weight:bold">if</span> (module_path) {
|
||||
ret = gnutls_pkcs11_init(GNUTLS_PKCS11_FLAG_MANUAL, <span style="color:#069">NULL</span>);
|
||||
<span style="color:#080;font-weight:bold">if</span> (ret < <span style="color:#00D">0</span>) {
|
||||
fprintf(stderr, <span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">"</span><span style="color:#D20">error in %d: %s</span><span style="color:#b0b">\n</span><span style="color:#710">"</span></span>, __LINE__, gnutls_strerror(ret));
|
||||
exit(<span style="color:#00D">1</span>);
|
||||
}
|
||||
|
||||
ret = gnutls_pkcs11_add_provider(module_path, <span style="color:#069">NULL</span>);
|
||||
<span style="color:#080;font-weight:bold">if</span> (ret < <span style="color:#00D">0</span>) {
|
||||
fprintf(stderr, <span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">"</span><span style="color:#D20">error in %d: %s</span><span style="color:#b0b">\n</span><span style="color:#710">"</span></span>, __LINE__, gnutls_strerror(ret));
|
||||
exit(<span style="color:#00D">1</span>);
|
||||
}
|
||||
}
|
||||
|
||||
<span style="color:#080;font-weight:bold">if</span> (key_pass)
|
||||
gnutls_pkcs11_set_pin_function(pin_function, key_pass);
|
||||
|
||||
ret = gnutls_privkey_init(&private_key);
|
||||
<span style="color:#080;font-weight:bold">if</span> (ret < <span style="color:#00D">0</span>) {
|
||||
fprintf(stderr, <span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">"</span><span style="color:#D20">error in %d: %s</span><span style="color:#b0b">\n</span><span style="color:#710">"</span></span>, __LINE__, gnutls_strerror(ret));
|
||||
exit(<span style="color:#00D">1</span>);
|
||||
}
|
||||
|
||||
ret = gnutls_privkey_import_url(private_key, private_key_name, <span style="color:#00D">0</span>);
|
||||
<span style="color:#080;font-weight:bold">if</span> (ret < <span style="color:#00D">0</span>) {
|
||||
fprintf(stderr, <span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">"</span><span style="color:#D20">error in %d: %s</span><span style="color:#b0b">\n</span><span style="color:#710">"</span></span>, __LINE__, gnutls_strerror(ret));
|
||||
exit(<span style="color:#00D">1</span>);
|
||||
}
|
||||
|
||||
ret = gnutls_privkey_sign_data(private_key, GNUTLS_DIG_SHA256, <span style="color:#00D">0</span>,
|
||||
&testdata, &signature);
|
||||
<span style="color:#080;font-weight:bold">if</span> (ret < <span style="color:#00D">0</span>) {
|
||||
fprintf(stderr, <span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">"</span><span style="color:#D20">error in %d: %s</span><span style="color:#b0b">\n</span><span style="color:#710">"</span></span>, __LINE__, gnutls_strerror(ret));
|
||||
exit(<span style="color:#00D">1</span>);
|
||||
}
|
||||
|
||||
gnutls_privkey_deinit(private_key);
|
||||
gnutls_free(signature.data);</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>The PIN callback function can be either set globally as in
|
||||
the example above or locally by utilizing functions such as <code>gnutls_privkey_set_pin_function</code>.
|
||||
An example PIN callback function is shown below.</p>
|
||||
</div>
|
||||
<div id="ex-Defensive_Coding-HSM-GNUTLS-PIN" class="exampleblock">
|
||||
<div class="title">Example 3. An example PIN callback with GNUTLS</div>
|
||||
<div class="content">
|
||||
<div class="listingblock">
|
||||
<div class="content">
|
||||
<pre class="CodeRay highlight"><code data-lang="c"><span style="color:#0a8;font-weight:bold">int</span> pin_function(<span style="color:#088;font-weight:bold">void</span> *userdata, <span style="color:#0a8;font-weight:bold">int</span> attempt, <span style="color:#088;font-weight:bold">const</span> <span style="color:#0a8;font-weight:bold">char</span> *token_url,
|
||||
<span style="color:#088;font-weight:bold">const</span> <span style="color:#0a8;font-weight:bold">char</span> *token_label, <span style="color:#0a8;font-weight:bold">unsigned</span> flags, <span style="color:#0a8;font-weight:bold">char</span> *pin, size_t pin_max)
|
||||
{
|
||||
<span style="color:#080;font-weight:bold">if</span> (flags & GNUTLS_PIN_FINAL_TRY)
|
||||
printf(<span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">"</span><span style="color:#D20">This is the final try before locking!</span><span style="color:#b0b">\n</span><span style="color:#710">"</span></span>);
|
||||
<span style="color:#080;font-weight:bold">if</span> (flags & GNUTLS_PIN_COUNT_LOW)
|
||||
printf(<span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">"</span><span style="color:#D20">Only few tries left before locking!</span><span style="color:#b0b">\n</span><span style="color:#710">"</span></span>);
|
||||
<span style="color:#080;font-weight:bold">if</span> (flags & GNUTLS_PIN_WRONG)
|
||||
printf(<span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">"</span><span style="color:#D20">Wrong PIN has been provided in the previous attempt</span><span style="color:#b0b">\n</span><span style="color:#710">"</span></span>);
|
||||
|
||||
<span style="color:#777">/* userdata is the second value passed to gnutls_pkcs11_set_pin_function()
|
||||
* in this example we passed the PIN as a null terminated value.
|
||||
*/</span>
|
||||
snprintf(pin, pin_max, <span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">"</span><span style="color:#D20">%s</span><span style="color:#710">"</span></span>, (<span style="color:#0a8;font-weight:bold">char</span>*)userdata);
|
||||
<span style="color:#080;font-weight:bold">return</span> <span style="color:#00D">0</span>;
|
||||
}</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="sect-Defensive_Coding-HSM-NSS"><a class="anchor" href="#sect-Defensive_Coding-HSM-NSS"></a>NSS HSM Support</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>NSS supports PKCS#11 natively. In fact all NSS crypto operations,
|
||||
including built-in operations, go through PKCS #11 modules. NSS provides
|
||||
its own software PKCS #11 module called softoken. NSS automatically
|
||||
loads any PKCS #11 module specified in its module database, which can
|
||||
be manipulated with the modutil command. NSS uses the PKCS #11 module
|
||||
that contains the requested keys to do the crypto operations. As long as
|
||||
the application opens an NSS database and properly sets a pin callback. If
|
||||
it runs with native NSS, it should be able to use HSMs that provide PKCS #11
|
||||
modules. Modules can also be loaded programatically, though this is less common.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>The following example demonstrates a typical NSS application for signing.</p>
|
||||
</div>
|
||||
<div id="ex-Defensive_Coding-HSM-NSS" class="exampleblock">
|
||||
<div class="title">Example 4. Signing data with HSM and NSS</div>
|
||||
<div class="content">
|
||||
<div class="listingblock">
|
||||
<div class="content">
|
||||
<pre class="CodeRay highlight"><code data-lang="c">SECStatus rv;
|
||||
CERTCertificate *cert = <span style="color:#069">NULL</span>;
|
||||
SECKEYPrivateKey *pvtkey = <span style="color:#069">NULL</span>;
|
||||
SECItem signature = { siBuffer, <span style="color:#069">NULL</span>, <span style="color:#00D">0</span> };
|
||||
SECOidTag algTag;
|
||||
<span style="color:#0a8;font-weight:bold">int</span> r = <span style="color:#00D">1</span>;
|
||||
<span style="color:#0a8;font-weight:bold">unsigned</span> <span style="color:#0a8;font-weight:bold">char</span> buf[] = <span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">"</span><span style="color:#D20">test data to sign</span><span style="color:#710">"</span></span>;
|
||||
<span style="color:#088;font-weight:bold">const</span> <span style="color:#0a8;font-weight:bold">char</span> *cert_name;
|
||||
<span style="color:#0a8;font-weight:bold">unsigned</span> i;
|
||||
|
||||
<span style="color:#080;font-weight:bold">if</span> (argc < <span style="color:#00D">3</span>) {
|
||||
fprintf(stderr, <span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">"</span><span style="color:#D20">usage: %s [cert name] [PIN]</span><span style="color:#b0b">\n</span><span style="color:#b0b">\n</span><span style="color:#710">"</span></span>, argv[<span style="color:#00D">0</span>]);
|
||||
exit(<span style="color:#00D">1</span>);
|
||||
}
|
||||
|
||||
cert_name = argv[<span style="color:#00D">1</span>];
|
||||
pin = argv[<span style="color:#00D">2</span>];
|
||||
|
||||
PK11_SetPasswordFunc(passwdcb);
|
||||
NSS_InitializePRErrorTable();
|
||||
rv = NSS_Init(<span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">"</span><span style="color:#D20">.</span><span style="color:#710">"</span></span>);
|
||||
<span style="color:#080;font-weight:bold">if</span> (rv != SECSuccess) {
|
||||
fprintf(stderr, <span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">"</span><span style="color:#D20">NSS initialization failed (err %d)</span><span style="color:#b0b">\n</span><span style="color:#710">"</span></span>, PR_GetError());
|
||||
<span style="color:#080;font-weight:bold">goto</span> cleanup;
|
||||
}
|
||||
|
||||
cert = PK11_FindCertFromNickname(cert_name, <span style="color:#069">NULL</span>);
|
||||
<span style="color:#080;font-weight:bold">if</span> (cert == <span style="color:#069">NULL</span>) {
|
||||
fprintf(stderr, <span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">"</span><span style="color:#D20">Couldn't find cert %s in NSS db (err %d: %s)</span><span style="color:#b0b">\n</span><span style="color:#710">"</span></span>,
|
||||
cert_name, PR_GetError(), PORT_ErrorToString(PR_GetError()));
|
||||
<span style="color:#080;font-weight:bold">goto</span> cleanup;
|
||||
}
|
||||
|
||||
fprintf(stderr, <span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">"</span><span style="color:#D20">Buffer being signed = </span><span style="color:#b0b">\n</span><span style="color:#D20">%s</span><span style="color:#b0b">\n</span><span style="color:#710">"</span></span>, buf);
|
||||
|
||||
pvtkey = PK11_FindKeyByAnyCert(cert, <span style="color:#069">NULL</span>);
|
||||
<span style="color:#080;font-weight:bold">if</span> (pvtkey == <span style="color:#069">NULL</span>) {
|
||||
fprintf(stderr, <span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">"</span><span style="color:#D20">Couldn't find private key for cert %s (err %d: %s)</span><span style="color:#b0b">\n</span><span style="color:#710">"</span></span>,
|
||||
cert_name, PR_GetError(), PORT_ErrorToString(PR_GetError()));
|
||||
<span style="color:#080;font-weight:bold">goto</span> cleanup;
|
||||
}
|
||||
|
||||
<span style="color:#777">/* get the algtag. Pick the default hash algorithm */</span>
|
||||
algTag = SEC_GetSignatureAlgorithmOidTag(pvtkey->keyType, SEC_OID_UNKNOWN);
|
||||
|
||||
fprintf(stderr, <span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">"</span><span style="color:#D20">Signing with alg = %s (%d)</span><span style="color:#b0b">\n</span><span style="color:#710">"</span></span>,
|
||||
SECOID_FindOIDTagDescription(algTag), algTag);
|
||||
|
||||
rv = SEC_SignData(&signature, buf, <span style="color:#080;font-weight:bold">sizeof</span>(buf)-<span style="color:#00D">1</span>, pvtkey, algTag);
|
||||
<span style="color:#080;font-weight:bold">if</span> (rv != SECSuccess) {
|
||||
fprintf(stderr, <span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">"</span><span style="color:#D20">sign with Private Key failed (err %d: %s)</span><span style="color:#b0b">\n</span><span style="color:#710">"</span></span>,
|
||||
PR_GetError(), PORT_ErrorToString(PR_GetError()));
|
||||
<span style="color:#080;font-weight:bold">goto</span> cleanup;
|
||||
}</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>To use the example above with an HSM or smart card you will need to do the following.</p>
|
||||
</div>
|
||||
<div class="listingblock">
|
||||
<div class="content">
|
||||
<pre class="CodeRay highlight"><code data-lang="bash"># add your HSM or token library to an NSS database (in the sample code the database is
|
||||
# located in the current directory'.')
|
||||
$ modutil -add "My HSM" -libfile ${path_to_pkcs11_file} -dbdir .
|
||||
# Find the token name on your HSM
|
||||
$ modutil -list -dbdir .
|
||||
# find the cert on your token
|
||||
$ certutil -L -h ${token_name} -d .
|
||||
# pass the cert to your signing program
|
||||
$ NSS_Sign_Example "${token_name}:${cert_name}"</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
<div id="ex-Defensive_Coding-HSM-NSS-PIN" class="exampleblock">
|
||||
<div class="title">Example 5. An example PIN callback with NSS</div>
|
||||
<div class="content">
|
||||
<div class="listingblock">
|
||||
<div class="content">
|
||||
<pre class="CodeRay highlight"><code data-lang="c"><span style="color:#0a8;font-weight:bold">char</span> *passwdcb(PK11SlotInfo * slot, PRBool retry, <span style="color:#088;font-weight:bold">void</span> *arg)
|
||||
{
|
||||
<span style="color:#080;font-weight:bold">if</span> (!isatty(STDIN_FILENO) && retry) {
|
||||
<span style="color:#777">/* 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. */</span>
|
||||
<span style="color:#080;font-weight:bold">return</span> <span style="color:#069">NULL</span>;
|
||||
}
|
||||
|
||||
<span style="color:#080;font-weight:bold">if</span> (retry) {
|
||||
printf(<span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">"</span><span style="color:#D20">Warning: Wrong PIN has been provided in the previous attempt</span><span style="color:#b0b">\n</span><span style="color:#710">"</span></span>);
|
||||
<span style="color:#080;font-weight:bold">if</span> (PK11_IsHW(slot)) {
|
||||
printf
|
||||
(<span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">"</span><span style="color:#D20"> NOTE: multiple pin failures could result in locking your device</span><span style="color:#b0b">\n</span><span style="color:#710">"</span></span>);
|
||||
}
|
||||
}
|
||||
|
||||
<span style="color:#080;font-weight:bold">if</span> (pin == <span style="color:#069">NULL</span>)
|
||||
<span style="color:#080;font-weight:bold">return</span> pin;
|
||||
<span style="color:#080;font-weight:bold">else</span>
|
||||
<span style="color:#080;font-weight:bold">return</span> strdup(pin);
|
||||
}</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="bottom" class="text-muted py-3" >
|
||||
<div class="foot">
|
||||
<div class="container">
|
||||
<div class="row footerlinks">
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">About</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Overview">About Fedora</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/sponsors">Sponsors</a></dd>
|
||||
<dd><a href="https://fedoramagazine.org">Fedora Magazine</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Legal:Main#Legal">Legal</a></dd>
|
||||
</dl>
|
||||
<ul class="list-inline">
|
||||
<li>
|
||||
<a href="https://www.facebook.com/TheFedoraProject" class="btn-social btn-outline"><i class="fa fa-fw fa-facebook"></i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://plus.google.com/112917221531140868607" class="btn-social btn-outline"><i class="fa fa-fw fa-google-plus"></i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://twitter.com/fedora" class="btn-social btn-outline"><i class="fa fa-fw fa-twitter"></i></a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title uppercase">Download</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://getfedora.org/en/workstation/download">Get Fedora Workstation</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/server/download">Get Fedora Server</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/atomic/download">Get Fedora Atomic</a></dd>
|
||||
<dd><a href="https://spins.fedoraproject.org">Fedora Spins</a></dd>
|
||||
<dd><a href="https://labs.fedoraproject.org">Fedora Labs</a></dd>
|
||||
<dd><a href="https://arm.fedoraproject.org">Fedora ARM<span class="sup">®</span></a></dd>
|
||||
<dd><a href="https://alt.fedoraproject.org/">Alternative Downloads</a></dd>
|
||||
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">Support</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Communicating_and_getting_help">Get Help</a></dd>
|
||||
<dd><a href="https://ask.fedoraproject.org/">Ask Fedora</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Common_F27_bugs">Common Bugs</a></dd>
|
||||
<dd><a href="https://developer.fedoraproject.org/">Fedora Developer Portal</a></dd>
|
||||
<dd><a href="https://docs.fedoraproject.org/f27/install-guide/index.html">Installation Guide</a></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">Join</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Join">Join Fedora</a></dd>
|
||||
<dd><a href="http://fedoraplanet.org">Planet Fedora</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/SIGs">Fedora SIGs</a></dd>
|
||||
<dd><a href="https://admin.fedoraproject.org/accounts/">Fedora Account System</a></dd>
|
||||
<dd><a href="https://fedoracommunity.org/">Fedora Community</a></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- /row of widgets -->
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-2">
|
||||
<div class="widget-body">
|
||||
<a href="https://www.redhat.com/"><img class="rh-logo" src="../../../master/_images/redhat-logo.png" alt="Red Hat Logo" /></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-7">
|
||||
<div class="widget-body">
|
||||
<p class="sponsor">Fedora is sponsored by Red Hat.</p>
|
||||
<p class="sponsor"><a href="https://www.redhat.com/en/technologies/linux-platforms/articles/relationship-between-fedora-and-rhel">Learn more about the relationship between Red Hat and Fedora »</a></p>
|
||||
<p class="copy">© 2017 Red Hat, Inc. and others. Please send any comments or corrections to the <a href="https://pagure.io/fedora-docs/docs-fp-o">documentation team</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- /row of widgets -->
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
|
||||
<!-- Latest compiled and minified JavaScript -->
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
|
||||
<script src="../../../master/_javascripts/bootstrap-offcanvas.js" type="text/javascript"></script>
|
||||
<script type="text/javascript">
|
||||
/*<![CDATA[*/
|
||||
$(document).ready(function() {
|
||||
$("[id^='topicGroup']").on('show.bs.collapse', function (event) {
|
||||
if (!($(event.target).attr('id').match(/^topicSubGroup/))) {
|
||||
$(this).parent().find("[id^='tgSpan']").toggleClass("fa-angle-right fa-angle-down");
|
||||
}
|
||||
});
|
||||
$("[id^='topicGroup']").on('hide.bs.collapse', function (event) {
|
||||
if (!($(event.target).attr('id').match(/^topicSubGroup/))) {
|
||||
$(this).parent().find("[id^='tgSpan']").toggleClass("fa-angle-right fa-angle-down");
|
||||
}
|
||||
});
|
||||
$("[id^='topicSubGroup']").on('show.bs.collapse', function () {
|
||||
$(this).parent().find("[id^='sgSpan']").toggleClass("fa-caret-right fa-caret-down");
|
||||
});
|
||||
$("[id^='topicSubGroup']").on('hide.bs.collapse', function () {
|
||||
$(this).parent().find("[id^='sgSpan']").toggleClass("fa-caret-right fa-caret-down");
|
||||
});
|
||||
});
|
||||
/*]]>*/
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -1,641 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta content="IE=edge" http-equiv="X-UA-Compatible">
|
||||
<meta content="width=device-width, initial-scale=1.0" name="viewport">
|
||||
<title>Defensive Coding Guide | Defensive Coding Guide | Programming Languages | The C++ Programming Language</title>
|
||||
|
||||
<!-- Bootstrap -->
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap-theme.min.css">
|
||||
|
||||
<!-- Overpass Font -->
|
||||
<link rel="stylesheet" href="https://overpass-30e2.kxcdn.com/overpass.css">
|
||||
|
||||
<link href="../../../master/_stylesheets/asciibinder.css" rel="stylesheet" />
|
||||
|
||||
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
|
||||
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
|
||||
<!--[if lt IE 9]>
|
||||
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
|
||||
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
|
||||
<![endif]-->
|
||||
|
||||
<link href="../../../master/_images/favicon32x32.png" rel="shortcut icon" type="text/css">
|
||||
<!--[if IE]><link rel="shortcut icon" href="../../../master/_images/favicon.ico"><![endif]-->
|
||||
<meta content="AsciiBinder" name="application-name">
|
||||
</head>
|
||||
<body>
|
||||
<div class="navbar navbar-default" role="navigation">
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-header">
|
||||
<a class="navbar-brand" href="https://docs.fedoraproject.org/"><img alt="Fedora Documentation" src="../../../master/_images/fedora.svg"></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container">
|
||||
<p class="toggle-nav visible-xs pull-left">
|
||||
<button class="btn btn-default btn-sm" type="button" data-toggle="offcanvas">Toggle nav</button>
|
||||
</p>
|
||||
<ol class="breadcrumb">
|
||||
<li class="sitename">
|
||||
<a href="../../../index.html">Home</a>
|
||||
</li>
|
||||
<li class="hidden-xs active">
|
||||
<a href="../../en-US/index.html">Defensive Coding Guide </a>
|
||||
</li>
|
||||
<li class="hidden-xs active">
|
||||
<a href="../../en-US/index.html">Defensive Coding Guide</a>
|
||||
</li>
|
||||
<li class="hidden-xs active"><a href="../../en-US/programming-languages/C.html">Programming Languages</a></li>
|
||||
<li class="hidden-xs active">
|
||||
The C++ Programming Language
|
||||
</li>
|
||||
</ol>
|
||||
<div class="row row-offcanvas row-offcanvas-left">
|
||||
<div class="col-xs-8 col-sm-3 col-md-3 sidebar sidebar-offcanvas">
|
||||
<ul class="nav nav-sidebar">
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicGroup0">
|
||||
<span id="tgSpan0" class="fa fa-angle-down"></span>Defensive Coding Guide
|
||||
</a>
|
||||
<ul id="topicGroup0" class="collapse in list-unstyled">
|
||||
<li><a class="" href="../../en-US/index.html">Book Information</a></li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-1">
|
||||
<span id="sgSpan-0-1" class="fa fa-caret-down"></span> Programming Languages
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-1" class="nav-tertiary list-unstyled collapse in">
|
||||
<li><a class="" href="../../en-US/programming-languages/C.html">The C Programming Language</a></li>
|
||||
<li><a class=" active" href="../../en-US/programming-languages/CXX.html">The C++ Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Java.html">The Java Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Python.html">The Python Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Shell.html">Shell Programming and bash</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Go.html">The Go Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Vala.html">The Vala Programming Language</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-2">
|
||||
<span id="sgSpan-0-2" class="fa fa-caret-right"></span> Specific Programming Tasks
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-2" class="nav-tertiary list-unstyled collapse">
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Library_Design.html">Library Design</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Descriptors.html">File Descriptor Management</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-File_System.html">File System Manipulation</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Temporary_Files.html">Temporary Files</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Processes.html">Processes</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Serialization.html">Serialization and Deserialization</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Cryptography.html">Cryptography</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Packaging.html">RPM Packaging</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-3">
|
||||
<span id="sgSpan-0-3" class="fa fa-caret-right"></span> Implementing Security Features
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-3" class="nav-tertiary list-unstyled collapse">
|
||||
<li><a class="" href="../../en-US/features/Features-Authentication.html">Authentication and Authorization</a></li>
|
||||
<li><a class="" href="../../en-US/features/Features-TLS.html">Transport Layer Security (TLS)</a></li>
|
||||
<li><a class="" href="../../en-US/features/Features-HSM.html">Hardware Security Modules and Smart Cards</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="" href="../../en-US/Revision_History.html">Revision History</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-9 col-md-9 main">
|
||||
<div class="page-header">
|
||||
<h2>The C++ Programming Language</h2>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="sect-Defensive_Coding-CXX-Language"><a class="anchor" href="#sect-Defensive_Coding-CXX-Language"></a>The Core Language</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>C++ includes a large subset of the C language. As far as the C
|
||||
subset is used, the recommendations in <a href="#chap-Defensive_Coding-C">[chap-Defensive_Coding-C]</a> apply.</p>
|
||||
</div>
|
||||
<div class="sect2">
|
||||
<h3 id="array-allocation-with-code-operator-new-code"><a class="anchor" href="#array-allocation-with-code-operator-new-code"></a>Array Allocation with <code>operator new[]</code></h3>
|
||||
<div class="paragraph">
|
||||
<p>For very large values of <code>n</code>, an expression
|
||||
like <code>new T[n]</code> 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 <code>sizeof(T) * size_t(n)<br>
|
||||
cookie_size</code>, where <code>cookie_size</code> is
|
||||
currently at most 8. This computation can overflow, and GCC
|
||||
versions prior to 4.8 generated code which did not detect this.
|
||||
(Fedora 18 was the first release which fixed this in GCC.)</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>The <code>std::vector</code> template can be used instead
|
||||
an explicit array allocation. (The GCC implementation detects
|
||||
overflow internally.)</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>If there is no alternative to <code>operator new[]</code>
|
||||
and the sources will be compiled with older GCC versions, code
|
||||
which allocates arrays with a variable length must check for
|
||||
overflow manually. For the <code>new T[n]</code> example,
|
||||
the size check could be <code>n || (n > 0 && n >
|
||||
(size_t(-1) - 8) / sizeof(T))</code>. (See <a href="#sect-Defensive_Coding-C-Arithmetic">[sect-Defensive_Coding-C-Arithmetic]</a>.) If there are
|
||||
additional dimensions (which must be constants according to the
|
||||
C++ standard), these should be included as factors in the
|
||||
divisor.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>These countermeasures prevent out-of-bounds writes and potential
|
||||
code execution. Very large memory allocations can still lead to
|
||||
a denial of service. <a href="#sect-Defensive_Coding-Tasks-Serialization-Decoders">[sect-Defensive_Coding-Tasks-Serialization-Decoders]</a>
|
||||
contains suggestions for mitigating this problem when processing
|
||||
untrusted data.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>See <a href="#sect-Defensive_Coding-C-Allocators-Arrays">[sect-Defensive_Coding-C-Allocators-Arrays]</a>
|
||||
for array allocation advice for C-style memory allocation.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect2">
|
||||
<h3 id="overloading"><a class="anchor" href="#overloading"></a>Overloading</h3>
|
||||
<div class="paragraph">
|
||||
<p>Do not overload functions with versions that have different
|
||||
security characteristics. For instance, do not implement a
|
||||
function <code>strcat</code> which works on
|
||||
<code>std::string</code> arguments. Similarly, do not name
|
||||
methods after such functions.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect2">
|
||||
<h3 id="abi-compatibility-and-preparing-for-security-updates"><a class="anchor" href="#abi-compatibility-and-preparing-for-security-updates"></a>ABI compatibility and preparing for security updates</h3>
|
||||
<div class="paragraph">
|
||||
<p>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.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>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:</p>
|
||||
</div>
|
||||
<div class="ulist">
|
||||
<ul>
|
||||
<li>
|
||||
<p>Avoid inline functions.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Use the pointer-to-implementation idiom.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Try to avoid templates. Use them if the increased type
|
||||
safety provides a benefit to the programmer.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Move security-critical code out of templated code, so that
|
||||
it can be patched in a central place if necessary.</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>The KDE project publishes a document with more extensive
|
||||
guidelines on ABI-preserving changes to C++ code, <a href="https://community.kde.org/Policies/Binary_Compatibility_Issues_With_C%2B%2B">Policies/Binary
|
||||
Compatibility Issues With C++</a>
|
||||
(<strong>d-pointer</strong> refers to the
|
||||
pointer-to-implementation idiom).</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect2">
|
||||
<h3 id="sect-Defensive_Coding-CXX-Language-CXX11"><a class="anchor" href="#sect-Defensive_Coding-CXX-Language-CXX11"></a>C++0X and C++11 Support</h3>
|
||||
<div class="paragraph">
|
||||
<p>GCC offers different language compatibility modes:</p>
|
||||
</div>
|
||||
<div class="ulist">
|
||||
<ul>
|
||||
<li>
|
||||
<p><code class="option">-std=c++98</code> for the original 1998 C++
|
||||
standard</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><code class="option">-std=c++03</code> for the 1998 standard with the
|
||||
changes from the TR1 technical report</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><code class="option">-std=c++11</code> for the 2011 C++ standard. This
|
||||
option should not be used.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><code class="option">-std=c++0x</code> for several different versions
|
||||
of C++11 support in development, depending on the GCC
|
||||
version. This option should not be used.</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>For each of these flags, there are variants which also enable
|
||||
GNU extensions (mostly language features also found in C99 or
|
||||
C11):</p>
|
||||
</div>
|
||||
<div class="ulist">
|
||||
<ul>
|
||||
<li>
|
||||
<p><code class="option">-std=gnu++98</code></p>
|
||||
</li>
|
||||
<li>
|
||||
<p><code class="option">-std=gnu++03</code></p>
|
||||
</li>
|
||||
<li>
|
||||
<p><code class="option">-std=gnu++11</code></p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Again, <code class="option">-std=gnu++11</code> should not be used.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>If you enable C++11 support, the ABI of the standard C++ library
|
||||
<code>libstdc++</code> 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).</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>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.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Some C++11 features (or approximations thereof) are available
|
||||
with TR1 support, that is, with <code class="option">-std=c03` or
|
||||
[option]`-std=gnu03</code> and in the
|
||||
<code><tr1/*></code> header files. This includes
|
||||
<code>std::tr1::shared_ptr</code> (from
|
||||
<code><tr1/memory></code>) and
|
||||
<code>std::tr1::function</code> (from
|
||||
<code><tr1/functional></code>). For other C++11
|
||||
features, the Boost C++ library contains replacements.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="sect-Defensive_Coding-CXX-Std"><a class="anchor" href="#sect-Defensive_Coding-CXX-Std"></a>The C++ Standard Library</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>The C++ standard library includes most of its C counterpart
|
||||
by reference, see <a href="#sect-Defensive_Coding-C-Libc">[sect-Defensive_Coding-C-Libc]</a>.</p>
|
||||
</div>
|
||||
<div class="sect2">
|
||||
<h3 id="sect-Defensive_Coding-CXX-Std-Functions"><a class="anchor" href="#sect-Defensive_Coding-CXX-Std-Functions"></a>Functions That Are Difficult to Use</h3>
|
||||
<div class="paragraph">
|
||||
<p>This section collects functions and function templates which are
|
||||
part of the standard library and are difficult to use.</p>
|
||||
</div>
|
||||
<div class="sect3">
|
||||
<h4 id="sect-Defensive_Coding-CXX-Std-Functions-Unpaired_Iterators"><a class="anchor" href="#sect-Defensive_Coding-CXX-Std-Functions-Unpaired_Iterators"></a>Unpaired Iterators</h4>
|
||||
<div class="paragraph">
|
||||
<p>Functions which use output operators or iterators which do not
|
||||
come in pairs (denoting ranges) cannot perform iterator range
|
||||
checking.
|
||||
(See <a href="#sect-Defensive_Coding-CXX-Std-Iterators">Iterators</a>)
|
||||
Function templates which involve output iterators are
|
||||
particularly dangerous:</p>
|
||||
</div>
|
||||
<div class="ulist">
|
||||
<ul>
|
||||
<li>
|
||||
<p><code>std::copy</code></p>
|
||||
</li>
|
||||
<li>
|
||||
<p><code>std::copy_backward</code></p>
|
||||
</li>
|
||||
<li>
|
||||
<p><code>std::copy_if</code></p>
|
||||
</li>
|
||||
<li>
|
||||
<p><code>std::move</code> (three-argument variant)</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><code>std::move_backward</code></p>
|
||||
</li>
|
||||
<li>
|
||||
<p><code>std::partition_copy_if</code></p>
|
||||
</li>
|
||||
<li>
|
||||
<p><code>std::remove_copy</code></p>
|
||||
</li>
|
||||
<li>
|
||||
<p><code>std::remove_copy_if</code></p>
|
||||
</li>
|
||||
<li>
|
||||
<p><code>std::replace_copy</code></p>
|
||||
</li>
|
||||
<li>
|
||||
<p><code>std::replace_copy_if</code></p>
|
||||
</li>
|
||||
<li>
|
||||
<p><code>std::swap_ranges</code></p>
|
||||
</li>
|
||||
<li>
|
||||
<p><code>std::transform</code></p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>In addition, <code>std::copy_n</code>,
|
||||
<code>std::fill_n</code> and
|
||||
<code>std::generate_n</code> do not perform iterator
|
||||
checking, either, but there is an explicit count which has to be
|
||||
supplied by the caller, as opposed to an implicit length
|
||||
indicator in the form of a pair of forward iterators.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>These output-iterator-expecting functions should only be used
|
||||
with unlimited-range output iterators, such as iterators
|
||||
obtained with the <code>std::back_inserter</code>
|
||||
function.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Other functions use single input or forward iterators, which can
|
||||
read beyond the end of the input range if the caller is not careful:</p>
|
||||
</div>
|
||||
<div class="ulist">
|
||||
<ul>
|
||||
<li>
|
||||
<p><code>std::equal</code></p>
|
||||
</li>
|
||||
<li>
|
||||
<p><code>std::is_permutation</code></p>
|
||||
</li>
|
||||
<li>
|
||||
<p><code>std::mismatch</code></p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect2">
|
||||
<h3 id="sect-Defensive_Coding-CXX-Std-String"><a class="anchor" href="#sect-Defensive_Coding-CXX-Std-String"></a>String Handling with <code>std::string</code></h3>
|
||||
<div class="paragraph">
|
||||
<p>The <code>std::string</code> class provides a convenient
|
||||
way to handle strings. Unlike C strings,
|
||||
<code>std::string</code> objects have an explicit length
|
||||
(and can contain embedded NUL characters), and storage for its
|
||||
characters is managed automatically. This section discusses
|
||||
<code>std::string</code>, but these observations also
|
||||
apply to other instances of the
|
||||
<code>std::basic_string</code> template.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>The pointer returned by the <code>data()</code> member
|
||||
function does not necessarily point to a NUL-terminated string.
|
||||
To obtain a C-compatible string pointer, use
|
||||
<code>c_str()</code> instead, which adds the NUL
|
||||
terminator.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>The pointers returned by the <code>data()</code> and
|
||||
<code>c_str()</code> functions and iterators are only
|
||||
valid until certain events happen. It is required that the
|
||||
exact <code>std::string</code> object still exists (even
|
||||
if it was initially created as a copy of another string object).
|
||||
Pointers and iterators are also invalidated when non-const
|
||||
member functions are called, or functions with a non-const
|
||||
reference parameter. The behavior of the GCC implementation
|
||||
deviates from that required by the C++ standard if multiple
|
||||
threads are present. In general, only the first call to a
|
||||
non-const member function after a structural modification of the
|
||||
string (such as appending a character) is invalidating, but this
|
||||
also applies to member function such as the non-const version of
|
||||
<code>begin()</code>, in violation of the C++ standard.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Particular care is necessary when invoking the
|
||||
<code>c_str()</code> member function on a temporary
|
||||
object. This is convenient for calling C functions, but the
|
||||
pointer will turn invalid as soon as the temporary object is
|
||||
destroyed, which generally happens when the outermost expression
|
||||
enclosing the expression on which <code>c_str()</code>
|
||||
is called completes evaluation. Passing the result of
|
||||
<code>c_str()</code> to a function which does not store
|
||||
or otherwise leak that pointer is safe, though.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Like with <code>std::vector</code> and
|
||||
<code>std::array</code>, subscribing with
|
||||
<code>operator[]</code> does not perform bounds checks.
|
||||
Use the <code>at(size_type)</code> member function
|
||||
instead. See <a href="#sect-Defensive_Coding-CXX-Std-Subscript">Containers and <code>operator[]</code></a>.
|
||||
Furthermore, accessing the terminating NUL character using
|
||||
<code>operator[]</code> is not possible. (In some
|
||||
implementations, the <code>c_str()</code> member function
|
||||
writes the NUL character on demand.)</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Never write to the pointers returned by
|
||||
<code>data()</code> or <code>c_str()</code>
|
||||
after casting away <code>const</code>. If you need a
|
||||
C-style writable string, use a
|
||||
<code>std::vector<char></code> object and its
|
||||
<code>data()</code> member function. In this case, you
|
||||
have to explicitly add the terminating NUL character.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>GCC’s implementation of <code>std::string</code> is
|
||||
currently based on reference counting. It is expected that a
|
||||
future version will remove the reference counting, due to
|
||||
performance and conformance issues. As a result, code that
|
||||
implicitly assumes sharing by holding to pointers or iterators
|
||||
for too long will break, resulting in run-time crashes or worse.
|
||||
On the other hand, non-const iterator-returning functions will
|
||||
no longer give other threads an opportunity for invalidating
|
||||
existing iterators and pointers because iterator invalidation
|
||||
does not depend on sharing of the internal character array
|
||||
object anymore.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect2">
|
||||
<h3 id="sect-Defensive_Coding-CXX-Std-Subscript"><a class="anchor" href="#sect-Defensive_Coding-CXX-Std-Subscript"></a>Containers and <code>operator[]</code></h3>
|
||||
<div class="paragraph">
|
||||
<p>Many sequence containers similar to <code>std::vector</code>
|
||||
provide both <code>operator[](size_type)</code> and a
|
||||
member function <code>at(size_type)</code>. This applies
|
||||
to <code>std::vector</code> itself,
|
||||
<code>std::array</code>, <code>std::string</code>
|
||||
and other instances of <code>std::basic_string</code>.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p><code>operator[](size_type)</code> is not required by the
|
||||
standard to perform bounds checking (and the implementation in
|
||||
GCC does not). In contrast, <code>at(size_type)</code>
|
||||
must perform such a check. Therefore, in code which is not
|
||||
performance-critical, you should prefer
|
||||
<code>at(size_type)</code> over
|
||||
<code>operator[](size_type)</code>, even though it is
|
||||
slightly more verbose.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>The <code>front()</code> and <code>back()</code>
|
||||
member functions are undefined if a vector object is empty. You
|
||||
can use <code>vec.at(0)</code> and
|
||||
<code>vec.at(vec.size() - 1)</code> as checked
|
||||
replacements. For an empty vector, <code>data()</code> is
|
||||
defined; it returns an arbitrary pointer, but not necessarily
|
||||
the NULL pointer.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect2">
|
||||
<h3 id="sect-Defensive_Coding-CXX-Std-Iterators"><a class="anchor" href="#sect-Defensive_Coding-CXX-Std-Iterators"></a>Iterators</h3>
|
||||
<div class="paragraph">
|
||||
<p>Iterators do not perform any bounds checking. Therefore, all
|
||||
functions that work on iterators should accept them in pairs,
|
||||
denoting a range, and make sure that iterators are not moved
|
||||
outside that range. For forward iterators and bidirectional
|
||||
iterators, you need to check for equality before moving the
|
||||
first or last iterator in the range. For random-access
|
||||
iterators, you need to compute the difference before adding or
|
||||
subtracting an offset. It is not possible to perform the
|
||||
operation and check for an invalid operator afterwards.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Output iterators cannot be compared for equality. Therefore, it
|
||||
is impossible to write code that detects that it has been
|
||||
supplied an output area that is too small, and their use should
|
||||
be avoided.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>These issues make some of the standard library functions
|
||||
difficult to use correctly, see <a href="#sect-Defensive_Coding-CXX-Std-Functions-Unpaired_Iterators">Unpaired Iterators</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="bottom" class="text-muted py-3" >
|
||||
<div class="foot">
|
||||
<div class="container">
|
||||
<div class="row footerlinks">
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">About</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Overview">About Fedora</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/sponsors">Sponsors</a></dd>
|
||||
<dd><a href="https://fedoramagazine.org">Fedora Magazine</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Legal:Main#Legal">Legal</a></dd>
|
||||
</dl>
|
||||
<ul class="list-inline">
|
||||
<li>
|
||||
<a href="https://www.facebook.com/TheFedoraProject" class="btn-social btn-outline"><i class="fa fa-fw fa-facebook"></i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://plus.google.com/112917221531140868607" class="btn-social btn-outline"><i class="fa fa-fw fa-google-plus"></i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://twitter.com/fedora" class="btn-social btn-outline"><i class="fa fa-fw fa-twitter"></i></a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title uppercase">Download</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://getfedora.org/en/workstation/download">Get Fedora Workstation</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/server/download">Get Fedora Server</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/atomic/download">Get Fedora Atomic</a></dd>
|
||||
<dd><a href="https://spins.fedoraproject.org">Fedora Spins</a></dd>
|
||||
<dd><a href="https://labs.fedoraproject.org">Fedora Labs</a></dd>
|
||||
<dd><a href="https://arm.fedoraproject.org">Fedora ARM<span class="sup">®</span></a></dd>
|
||||
<dd><a href="https://alt.fedoraproject.org/">Alternative Downloads</a></dd>
|
||||
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">Support</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Communicating_and_getting_help">Get Help</a></dd>
|
||||
<dd><a href="https://ask.fedoraproject.org/">Ask Fedora</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Common_F27_bugs">Common Bugs</a></dd>
|
||||
<dd><a href="https://developer.fedoraproject.org/">Fedora Developer Portal</a></dd>
|
||||
<dd><a href="https://docs.fedoraproject.org/f27/install-guide/index.html">Installation Guide</a></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">Join</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Join">Join Fedora</a></dd>
|
||||
<dd><a href="http://fedoraplanet.org">Planet Fedora</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/SIGs">Fedora SIGs</a></dd>
|
||||
<dd><a href="https://admin.fedoraproject.org/accounts/">Fedora Account System</a></dd>
|
||||
<dd><a href="https://fedoracommunity.org/">Fedora Community</a></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- /row of widgets -->
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-2">
|
||||
<div class="widget-body">
|
||||
<a href="https://www.redhat.com/"><img class="rh-logo" src="../../../master/_images/redhat-logo.png" alt="Red Hat Logo" /></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-7">
|
||||
<div class="widget-body">
|
||||
<p class="sponsor">Fedora is sponsored by Red Hat.</p>
|
||||
<p class="sponsor"><a href="https://www.redhat.com/en/technologies/linux-platforms/articles/relationship-between-fedora-and-rhel">Learn more about the relationship between Red Hat and Fedora »</a></p>
|
||||
<p class="copy">© 2017 Red Hat, Inc. and others. Please send any comments or corrections to the <a href="https://pagure.io/fedora-docs/docs-fp-o">documentation team</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- /row of widgets -->
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
|
||||
<!-- Latest compiled and minified JavaScript -->
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
|
||||
<script src="../../../master/_javascripts/bootstrap-offcanvas.js" type="text/javascript"></script>
|
||||
<script type="text/javascript">
|
||||
/*<![CDATA[*/
|
||||
$(document).ready(function() {
|
||||
$("[id^='topicGroup']").on('show.bs.collapse', function (event) {
|
||||
if (!($(event.target).attr('id').match(/^topicSubGroup/))) {
|
||||
$(this).parent().find("[id^='tgSpan']").toggleClass("fa-angle-right fa-angle-down");
|
||||
}
|
||||
});
|
||||
$("[id^='topicGroup']").on('hide.bs.collapse', function (event) {
|
||||
if (!($(event.target).attr('id').match(/^topicSubGroup/))) {
|
||||
$(this).parent().find("[id^='tgSpan']").toggleClass("fa-angle-right fa-angle-down");
|
||||
}
|
||||
});
|
||||
$("[id^='topicSubGroup']").on('show.bs.collapse', function () {
|
||||
$(this).parent().find("[id^='sgSpan']").toggleClass("fa-caret-right fa-caret-down");
|
||||
});
|
||||
$("[id^='topicSubGroup']").on('hide.bs.collapse', function () {
|
||||
$(this).parent().find("[id^='sgSpan']").toggleClass("fa-caret-right fa-caret-down");
|
||||
});
|
||||
});
|
||||
/*]]>*/
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -1,356 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta content="IE=edge" http-equiv="X-UA-Compatible">
|
||||
<meta content="width=device-width, initial-scale=1.0" name="viewport">
|
||||
<title>Defensive Coding Guide | Defensive Coding Guide | Programming Languages | The Go Programming Language</title>
|
||||
|
||||
<!-- Bootstrap -->
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap-theme.min.css">
|
||||
|
||||
<!-- Overpass Font -->
|
||||
<link rel="stylesheet" href="https://overpass-30e2.kxcdn.com/overpass.css">
|
||||
|
||||
<link href="../../../master/_stylesheets/asciibinder.css" rel="stylesheet" />
|
||||
|
||||
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
|
||||
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
|
||||
<!--[if lt IE 9]>
|
||||
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
|
||||
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
|
||||
<![endif]-->
|
||||
|
||||
<link href="../../../master/_images/favicon32x32.png" rel="shortcut icon" type="text/css">
|
||||
<!--[if IE]><link rel="shortcut icon" href="../../../master/_images/favicon.ico"><![endif]-->
|
||||
<meta content="AsciiBinder" name="application-name">
|
||||
</head>
|
||||
<body>
|
||||
<div class="navbar navbar-default" role="navigation">
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-header">
|
||||
<a class="navbar-brand" href="https://docs.fedoraproject.org/"><img alt="Fedora Documentation" src="../../../master/_images/fedora.svg"></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container">
|
||||
<p class="toggle-nav visible-xs pull-left">
|
||||
<button class="btn btn-default btn-sm" type="button" data-toggle="offcanvas">Toggle nav</button>
|
||||
</p>
|
||||
<ol class="breadcrumb">
|
||||
<li class="sitename">
|
||||
<a href="../../../index.html">Home</a>
|
||||
</li>
|
||||
<li class="hidden-xs active">
|
||||
<a href="../../en-US/index.html">Defensive Coding Guide </a>
|
||||
</li>
|
||||
<li class="hidden-xs active">
|
||||
<a href="../../en-US/index.html">Defensive Coding Guide</a>
|
||||
</li>
|
||||
<li class="hidden-xs active"><a href="../../en-US/programming-languages/C.html">Programming Languages</a></li>
|
||||
<li class="hidden-xs active">
|
||||
The Go Programming Language
|
||||
</li>
|
||||
</ol>
|
||||
<div class="row row-offcanvas row-offcanvas-left">
|
||||
<div class="col-xs-8 col-sm-3 col-md-3 sidebar sidebar-offcanvas">
|
||||
<ul class="nav nav-sidebar">
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicGroup0">
|
||||
<span id="tgSpan0" class="fa fa-angle-down"></span>Defensive Coding Guide
|
||||
</a>
|
||||
<ul id="topicGroup0" class="collapse in list-unstyled">
|
||||
<li><a class="" href="../../en-US/index.html">Book Information</a></li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-1">
|
||||
<span id="sgSpan-0-1" class="fa fa-caret-down"></span> Programming Languages
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-1" class="nav-tertiary list-unstyled collapse in">
|
||||
<li><a class="" href="../../en-US/programming-languages/C.html">The C Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/CXX.html">The C++ Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Java.html">The Java Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Python.html">The Python Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Shell.html">Shell Programming and bash</a></li>
|
||||
<li><a class=" active" href="../../en-US/programming-languages/Go.html">The Go Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Vala.html">The Vala Programming Language</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-2">
|
||||
<span id="sgSpan-0-2" class="fa fa-caret-right"></span> Specific Programming Tasks
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-2" class="nav-tertiary list-unstyled collapse">
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Library_Design.html">Library Design</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Descriptors.html">File Descriptor Management</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-File_System.html">File System Manipulation</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Temporary_Files.html">Temporary Files</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Processes.html">Processes</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Serialization.html">Serialization and Deserialization</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Cryptography.html">Cryptography</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Packaging.html">RPM Packaging</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-3">
|
||||
<span id="sgSpan-0-3" class="fa fa-caret-right"></span> Implementing Security Features
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-3" class="nav-tertiary list-unstyled collapse">
|
||||
<li><a class="" href="../../en-US/features/Features-Authentication.html">Authentication and Authorization</a></li>
|
||||
<li><a class="" href="../../en-US/features/Features-TLS.html">Transport Layer Security (TLS)</a></li>
|
||||
<li><a class="" href="../../en-US/features/Features-HSM.html">Hardware Security Modules and Smart Cards</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="" href="../../en-US/Revision_History.html">Revision History</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-9 col-md-9 main">
|
||||
<div class="page-header">
|
||||
<h2>The Go Programming Language</h2>
|
||||
</div>
|
||||
<div id="preamble">
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>This chapter contains language-specific recommendations for Go.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="chap-Defensive_Coding-Go-Memory_Safety"><a class="anchor" href="#chap-Defensive_Coding-Go-Memory_Safety"></a>Memory Safety</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>Go provides memory safety, but only if the program is not executed
|
||||
in parallel (that is, <code>GOMAXPROCS</code> is not larger than
|
||||
<code>1</code>). The reason is that interface values and
|
||||
slices consist of multiple words are not updated atomically.
|
||||
Another thread of execution can observe an inconsistent pairing
|
||||
between type information and stored value (for interfaces) or
|
||||
pointer and length (for slices), and such inconsistency can lead
|
||||
to a memory safety violation.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Code which does not run in parallel and does not use the
|
||||
<code>unsafe</code> package (or other packages which expose
|
||||
unsafe constructs) is memory-safe. For example, invalid casts and
|
||||
out-of-range subscripting cause panics at run time.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Keep in mind that finalization can introduce parallelism because
|
||||
finalizers are executed concurrently, potentially interleaved with
|
||||
the rest of the program.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="chap-Defensive_Coding-Go-Error_Handling"><a class="anchor" href="#chap-Defensive_Coding-Go-Error_Handling"></a>Error Handling</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>Only a few common operations (such as pointer dereference, integer
|
||||
division, array subscripting) trigger exceptions in Go, called
|
||||
<strong>panics</strong>. Most interfaces in the standard
|
||||
library use a separate return value of type
|
||||
<code>error</code> to signal error.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Not checking error return values can lead to incorrect operation
|
||||
and data loss (especially in the case of writes, using interfaces
|
||||
such as <code>io.Writer</code>).</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>The correct way to check error return values depends on the
|
||||
function or method being called. In the majority of cases, the
|
||||
first step after calling a function should be an error check
|
||||
against the <code>nil</code> value, handling any encountered
|
||||
error. See <a href="#ex-Defensive_Coding-Go-Error_Handling-Regular">Regular error handling in Go</a> for
|
||||
details.</p>
|
||||
</div>
|
||||
<div id="ex-Defensive_Coding-Go-Error_Handling-Regular" class="exampleblock">
|
||||
<div class="title">Example 1. Regular error handling in Go</div>
|
||||
<div class="content">
|
||||
<div class="listingblock">
|
||||
<div class="content">
|
||||
<pre class="CodeRay highlight"><code data-lang="go">Unresolved directive in <stdin> - include::../snippets/Go-Error_Handling-Regular.adoc[]</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>However, with <code>io.Reader</code>,
|
||||
<code>io.ReaderAt</code> and related interfaces, it is
|
||||
necessary to check for a non-zero number of read bytes first, as
|
||||
shown in <a href="#ex-Defensive_Coding-Go-Error_Handling-IO">Read error handling in Go</a>. If this
|
||||
pattern is not followed, data loss may occur. This is due to the
|
||||
fact that the <code>io.Reader</code> interface permits
|
||||
returning both data and an error at the same time.</p>
|
||||
</div>
|
||||
<div id="ex-Defensive_Coding-Go-Error_Handling-IO" class="exampleblock">
|
||||
<div class="title">Example 2. Read error handling in Go</div>
|
||||
<div class="content">
|
||||
<div class="listingblock">
|
||||
<div class="content">
|
||||
<pre class="CodeRay highlight"><code data-lang="go">Unresolved directive in <stdin> - include::../snippets/Go-Error_Handling-IO.adoc[]</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="chap-Defensive_Coding-Go-Garbage_Collector"><a class="anchor" href="#chap-Defensive_Coding-Go-Garbage_Collector"></a>Garbage Collector</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>Older Go releases (before Go 1.3) use a conservative garbage
|
||||
collector without blacklisting. This means that data blobs can
|
||||
cause retention of unrelated data structures because the data is
|
||||
conservatively interpreted as pointers. This phenomenon can be
|
||||
triggered accidentally on 32-bit architectures and is more likely
|
||||
to occur if the heap grows larger. On 64-bit architectures, it
|
||||
may be possible to trigger it deliberately—it is unlikely to occur
|
||||
spontaneously.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="chap-Defensive_Coding-Go-Marshaling"><a class="anchor" href="#chap-Defensive_Coding-Go-Marshaling"></a>Marshaling and Unmarshaling</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>Several packages in the <code>encoding</code> hierarchy
|
||||
provide support for serialization and deserialization. The usual
|
||||
caveats apply (see
|
||||
<a href="#chap-Defensive_Coding-Tasks-Serialization">[chap-Defensive_Coding-Tasks-Serialization]</a>).</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>As an additional precaution, the <code>Unmarshal</code>
|
||||
and <code>Decode</code> functions should only be used with
|
||||
fresh values in the <code>interface{}</code> argument. This
|
||||
is due to the way defaults for missing values are implemented:
|
||||
During deserialization, missing value do not result in an error,
|
||||
but the original value is preserved. Using a fresh value (with
|
||||
suitable default values if necessary) ensures that data from a
|
||||
previous deserialization operation does not leak into the current
|
||||
one. This is especially relevant when structs are deserialized.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="bottom" class="text-muted py-3" >
|
||||
<div class="foot">
|
||||
<div class="container">
|
||||
<div class="row footerlinks">
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">About</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Overview">About Fedora</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/sponsors">Sponsors</a></dd>
|
||||
<dd><a href="https://fedoramagazine.org">Fedora Magazine</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Legal:Main#Legal">Legal</a></dd>
|
||||
</dl>
|
||||
<ul class="list-inline">
|
||||
<li>
|
||||
<a href="https://www.facebook.com/TheFedoraProject" class="btn-social btn-outline"><i class="fa fa-fw fa-facebook"></i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://plus.google.com/112917221531140868607" class="btn-social btn-outline"><i class="fa fa-fw fa-google-plus"></i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://twitter.com/fedora" class="btn-social btn-outline"><i class="fa fa-fw fa-twitter"></i></a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title uppercase">Download</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://getfedora.org/en/workstation/download">Get Fedora Workstation</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/server/download">Get Fedora Server</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/atomic/download">Get Fedora Atomic</a></dd>
|
||||
<dd><a href="https://spins.fedoraproject.org">Fedora Spins</a></dd>
|
||||
<dd><a href="https://labs.fedoraproject.org">Fedora Labs</a></dd>
|
||||
<dd><a href="https://arm.fedoraproject.org">Fedora ARM<span class="sup">®</span></a></dd>
|
||||
<dd><a href="https://alt.fedoraproject.org/">Alternative Downloads</a></dd>
|
||||
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">Support</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Communicating_and_getting_help">Get Help</a></dd>
|
||||
<dd><a href="https://ask.fedoraproject.org/">Ask Fedora</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Common_F27_bugs">Common Bugs</a></dd>
|
||||
<dd><a href="https://developer.fedoraproject.org/">Fedora Developer Portal</a></dd>
|
||||
<dd><a href="https://docs.fedoraproject.org/f27/install-guide/index.html">Installation Guide</a></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">Join</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Join">Join Fedora</a></dd>
|
||||
<dd><a href="http://fedoraplanet.org">Planet Fedora</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/SIGs">Fedora SIGs</a></dd>
|
||||
<dd><a href="https://admin.fedoraproject.org/accounts/">Fedora Account System</a></dd>
|
||||
<dd><a href="https://fedoracommunity.org/">Fedora Community</a></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- /row of widgets -->
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-2">
|
||||
<div class="widget-body">
|
||||
<a href="https://www.redhat.com/"><img class="rh-logo" src="../../../master/_images/redhat-logo.png" alt="Red Hat Logo" /></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-7">
|
||||
<div class="widget-body">
|
||||
<p class="sponsor">Fedora is sponsored by Red Hat.</p>
|
||||
<p class="sponsor"><a href="https://www.redhat.com/en/technologies/linux-platforms/articles/relationship-between-fedora-and-rhel">Learn more about the relationship between Red Hat and Fedora »</a></p>
|
||||
<p class="copy">© 2017 Red Hat, Inc. and others. Please send any comments or corrections to the <a href="https://pagure.io/fedora-docs/docs-fp-o">documentation team</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- /row of widgets -->
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
|
||||
<!-- Latest compiled and minified JavaScript -->
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
|
||||
<script src="../../../master/_javascripts/bootstrap-offcanvas.js" type="text/javascript"></script>
|
||||
<script type="text/javascript">
|
||||
/*<![CDATA[*/
|
||||
$(document).ready(function() {
|
||||
$("[id^='topicGroup']").on('show.bs.collapse', function (event) {
|
||||
if (!($(event.target).attr('id').match(/^topicSubGroup/))) {
|
||||
$(this).parent().find("[id^='tgSpan']").toggleClass("fa-angle-right fa-angle-down");
|
||||
}
|
||||
});
|
||||
$("[id^='topicGroup']").on('hide.bs.collapse', function (event) {
|
||||
if (!($(event.target).attr('id').match(/^topicSubGroup/))) {
|
||||
$(this).parent().find("[id^='tgSpan']").toggleClass("fa-angle-right fa-angle-down");
|
||||
}
|
||||
});
|
||||
$("[id^='topicSubGroup']").on('show.bs.collapse', function () {
|
||||
$(this).parent().find("[id^='sgSpan']").toggleClass("fa-caret-right fa-caret-down");
|
||||
});
|
||||
$("[id^='topicSubGroup']").on('hide.bs.collapse', function () {
|
||||
$(this).parent().find("[id^='sgSpan']").toggleClass("fa-caret-right fa-caret-down");
|
||||
});
|
||||
});
|
||||
/*]]>*/
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -1,313 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta content="IE=edge" http-equiv="X-UA-Compatible">
|
||||
<meta content="width=device-width, initial-scale=1.0" name="viewport">
|
||||
<title>Defensive Coding Guide | Defensive Coding Guide | Programming Languages | The Python Programming Language</title>
|
||||
|
||||
<!-- Bootstrap -->
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap-theme.min.css">
|
||||
|
||||
<!-- Overpass Font -->
|
||||
<link rel="stylesheet" href="https://overpass-30e2.kxcdn.com/overpass.css">
|
||||
|
||||
<link href="../../../master/_stylesheets/asciibinder.css" rel="stylesheet" />
|
||||
|
||||
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
|
||||
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
|
||||
<!--[if lt IE 9]>
|
||||
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
|
||||
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
|
||||
<![endif]-->
|
||||
|
||||
<link href="../../../master/_images/favicon32x32.png" rel="shortcut icon" type="text/css">
|
||||
<!--[if IE]><link rel="shortcut icon" href="../../../master/_images/favicon.ico"><![endif]-->
|
||||
<meta content="AsciiBinder" name="application-name">
|
||||
</head>
|
||||
<body>
|
||||
<div class="navbar navbar-default" role="navigation">
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-header">
|
||||
<a class="navbar-brand" href="https://docs.fedoraproject.org/"><img alt="Fedora Documentation" src="../../../master/_images/fedora.svg"></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container">
|
||||
<p class="toggle-nav visible-xs pull-left">
|
||||
<button class="btn btn-default btn-sm" type="button" data-toggle="offcanvas">Toggle nav</button>
|
||||
</p>
|
||||
<ol class="breadcrumb">
|
||||
<li class="sitename">
|
||||
<a href="../../../index.html">Home</a>
|
||||
</li>
|
||||
<li class="hidden-xs active">
|
||||
<a href="../../en-US/index.html">Defensive Coding Guide </a>
|
||||
</li>
|
||||
<li class="hidden-xs active">
|
||||
<a href="../../en-US/index.html">Defensive Coding Guide</a>
|
||||
</li>
|
||||
<li class="hidden-xs active"><a href="../../en-US/programming-languages/C.html">Programming Languages</a></li>
|
||||
<li class="hidden-xs active">
|
||||
The Python Programming Language
|
||||
</li>
|
||||
</ol>
|
||||
<div class="row row-offcanvas row-offcanvas-left">
|
||||
<div class="col-xs-8 col-sm-3 col-md-3 sidebar sidebar-offcanvas">
|
||||
<ul class="nav nav-sidebar">
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicGroup0">
|
||||
<span id="tgSpan0" class="fa fa-angle-down"></span>Defensive Coding Guide
|
||||
</a>
|
||||
<ul id="topicGroup0" class="collapse in list-unstyled">
|
||||
<li><a class="" href="../../en-US/index.html">Book Information</a></li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-1">
|
||||
<span id="sgSpan-0-1" class="fa fa-caret-down"></span> Programming Languages
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-1" class="nav-tertiary list-unstyled collapse in">
|
||||
<li><a class="" href="../../en-US/programming-languages/C.html">The C Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/CXX.html">The C++ Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Java.html">The Java Programming Language</a></li>
|
||||
<li><a class=" active" href="../../en-US/programming-languages/Python.html">The Python Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Shell.html">Shell Programming and bash</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Go.html">The Go Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Vala.html">The Vala Programming Language</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-2">
|
||||
<span id="sgSpan-0-2" class="fa fa-caret-right"></span> Specific Programming Tasks
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-2" class="nav-tertiary list-unstyled collapse">
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Library_Design.html">Library Design</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Descriptors.html">File Descriptor Management</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-File_System.html">File System Manipulation</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Temporary_Files.html">Temporary Files</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Processes.html">Processes</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Serialization.html">Serialization and Deserialization</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Cryptography.html">Cryptography</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Packaging.html">RPM Packaging</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-3">
|
||||
<span id="sgSpan-0-3" class="fa fa-caret-right"></span> Implementing Security Features
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-3" class="nav-tertiary list-unstyled collapse">
|
||||
<li><a class="" href="../../en-US/features/Features-Authentication.html">Authentication and Authorization</a></li>
|
||||
<li><a class="" href="../../en-US/features/Features-TLS.html">Transport Layer Security (TLS)</a></li>
|
||||
<li><a class="" href="../../en-US/features/Features-HSM.html">Hardware Security Modules and Smart Cards</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="" href="../../en-US/Revision_History.html">Revision History</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-9 col-md-9 main">
|
||||
<div class="page-header">
|
||||
<h2>The Python Programming Language</h2>
|
||||
</div>
|
||||
<div id="preamble">
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>Python provides memory safety by default, so low-level security
|
||||
vulnerabilities are rare and typically needs fixing the Python
|
||||
interpreter or standard library itself.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Other sections with Python-specific advice include:</p>
|
||||
</div>
|
||||
<div class="ulist">
|
||||
<ul>
|
||||
<li>
|
||||
<p><a href="#chap-Defensive_Coding-Tasks-Temporary_Files">[chap-Defensive_Coding-Tasks-Temporary_Files]</a></p>
|
||||
</li>
|
||||
<li>
|
||||
<p><a href="#sect-Defensive_Coding-Tasks-Processes-Creation">[sect-Defensive_Coding-Tasks-Processes-Creation]</a></p>
|
||||
</li>
|
||||
<li>
|
||||
<p><a href="#chap-Defensive_Coding-Tasks-Serialization">[chap-Defensive_Coding-Tasks-Serialization]</a>, in
|
||||
particular <a href="#sect-Defensive_Coding-Tasks-Serialization-Library">[sect-Defensive_Coding-Tasks-Serialization-Library]</a></p>
|
||||
</li>
|
||||
<li>
|
||||
<p><a href="#sect-Defensive_Coding-Tasks-Cryptography-Randomness">[sect-Defensive_Coding-Tasks-Cryptography-Randomness]</a></p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="dangerous-standard-library-features"><a class="anchor" href="#dangerous-standard-library-features"></a>Dangerous Standard Library Features</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>Some areas of the standard library, notably the
|
||||
<code>ctypes</code> module, do not provide memory safety
|
||||
guarantees comparable to the rest of Python. If such
|
||||
functionality is used, the advice in <a href="#sect-Defensive_Coding-C-Language">[sect-Defensive_Coding-C-Language]</a> should be followed.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="run-time-compilation-and-code-generation"><a class="anchor" href="#run-time-compilation-and-code-generation"></a>Run-time Compilation and Code Generation</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>The following Python functions and statements related to code
|
||||
execution should be avoided:</p>
|
||||
</div>
|
||||
<div class="ulist">
|
||||
<ul>
|
||||
<li>
|
||||
<p><code>compile</code></p>
|
||||
</li>
|
||||
<li>
|
||||
<p><code>eval</code></p>
|
||||
</li>
|
||||
<li>
|
||||
<p><code>exec</code></p>
|
||||
</li>
|
||||
<li>
|
||||
<p><code>execfile</code></p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>If you need to parse integers or floating point values, use the
|
||||
<code>int</code> and <code>float</code>
|
||||
functions instead of <code>eval</code>. Sandboxing
|
||||
untrusted Python code does not work reliably.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="sandboxing"><a class="anchor" href="#sandboxing"></a>Sandboxing</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>The <code>rexec</code> Python module cannot safely sandbox
|
||||
untrusted code and should not be used. The standard CPython
|
||||
implementation is not suitable for sandboxing.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="bottom" class="text-muted py-3" >
|
||||
<div class="foot">
|
||||
<div class="container">
|
||||
<div class="row footerlinks">
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">About</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Overview">About Fedora</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/sponsors">Sponsors</a></dd>
|
||||
<dd><a href="https://fedoramagazine.org">Fedora Magazine</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Legal:Main#Legal">Legal</a></dd>
|
||||
</dl>
|
||||
<ul class="list-inline">
|
||||
<li>
|
||||
<a href="https://www.facebook.com/TheFedoraProject" class="btn-social btn-outline"><i class="fa fa-fw fa-facebook"></i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://plus.google.com/112917221531140868607" class="btn-social btn-outline"><i class="fa fa-fw fa-google-plus"></i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://twitter.com/fedora" class="btn-social btn-outline"><i class="fa fa-fw fa-twitter"></i></a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title uppercase">Download</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://getfedora.org/en/workstation/download">Get Fedora Workstation</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/server/download">Get Fedora Server</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/atomic/download">Get Fedora Atomic</a></dd>
|
||||
<dd><a href="https://spins.fedoraproject.org">Fedora Spins</a></dd>
|
||||
<dd><a href="https://labs.fedoraproject.org">Fedora Labs</a></dd>
|
||||
<dd><a href="https://arm.fedoraproject.org">Fedora ARM<span class="sup">®</span></a></dd>
|
||||
<dd><a href="https://alt.fedoraproject.org/">Alternative Downloads</a></dd>
|
||||
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">Support</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Communicating_and_getting_help">Get Help</a></dd>
|
||||
<dd><a href="https://ask.fedoraproject.org/">Ask Fedora</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Common_F27_bugs">Common Bugs</a></dd>
|
||||
<dd><a href="https://developer.fedoraproject.org/">Fedora Developer Portal</a></dd>
|
||||
<dd><a href="https://docs.fedoraproject.org/f27/install-guide/index.html">Installation Guide</a></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">Join</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Join">Join Fedora</a></dd>
|
||||
<dd><a href="http://fedoraplanet.org">Planet Fedora</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/SIGs">Fedora SIGs</a></dd>
|
||||
<dd><a href="https://admin.fedoraproject.org/accounts/">Fedora Account System</a></dd>
|
||||
<dd><a href="https://fedoracommunity.org/">Fedora Community</a></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- /row of widgets -->
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-2">
|
||||
<div class="widget-body">
|
||||
<a href="https://www.redhat.com/"><img class="rh-logo" src="../../../master/_images/redhat-logo.png" alt="Red Hat Logo" /></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-7">
|
||||
<div class="widget-body">
|
||||
<p class="sponsor">Fedora is sponsored by Red Hat.</p>
|
||||
<p class="sponsor"><a href="https://www.redhat.com/en/technologies/linux-platforms/articles/relationship-between-fedora-and-rhel">Learn more about the relationship between Red Hat and Fedora »</a></p>
|
||||
<p class="copy">© 2017 Red Hat, Inc. and others. Please send any comments or corrections to the <a href="https://pagure.io/fedora-docs/docs-fp-o">documentation team</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- /row of widgets -->
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
|
||||
<!-- Latest compiled and minified JavaScript -->
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
|
||||
<script src="../../../master/_javascripts/bootstrap-offcanvas.js" type="text/javascript"></script>
|
||||
<script type="text/javascript">
|
||||
/*<![CDATA[*/
|
||||
$(document).ready(function() {
|
||||
$("[id^='topicGroup']").on('show.bs.collapse', function (event) {
|
||||
if (!($(event.target).attr('id').match(/^topicSubGroup/))) {
|
||||
$(this).parent().find("[id^='tgSpan']").toggleClass("fa-angle-right fa-angle-down");
|
||||
}
|
||||
});
|
||||
$("[id^='topicGroup']").on('hide.bs.collapse', function (event) {
|
||||
if (!($(event.target).attr('id').match(/^topicSubGroup/))) {
|
||||
$(this).parent().find("[id^='tgSpan']").toggleClass("fa-angle-right fa-angle-down");
|
||||
}
|
||||
});
|
||||
$("[id^='topicSubGroup']").on('show.bs.collapse', function () {
|
||||
$(this).parent().find("[id^='sgSpan']").toggleClass("fa-caret-right fa-caret-down");
|
||||
});
|
||||
$("[id^='topicSubGroup']").on('hide.bs.collapse', function () {
|
||||
$(this).parent().find("[id^='sgSpan']").toggleClass("fa-caret-right fa-caret-down");
|
||||
});
|
||||
});
|
||||
/*]]>*/
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -1,699 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta content="IE=edge" http-equiv="X-UA-Compatible">
|
||||
<meta content="width=device-width, initial-scale=1.0" name="viewport">
|
||||
<title>Defensive Coding Guide | Defensive Coding Guide | Programming Languages | Shell Programming and bash</title>
|
||||
|
||||
<!-- Bootstrap -->
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap-theme.min.css">
|
||||
|
||||
<!-- Overpass Font -->
|
||||
<link rel="stylesheet" href="https://overpass-30e2.kxcdn.com/overpass.css">
|
||||
|
||||
<link href="../../../master/_stylesheets/asciibinder.css" rel="stylesheet" />
|
||||
|
||||
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
|
||||
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
|
||||
<!--[if lt IE 9]>
|
||||
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
|
||||
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
|
||||
<![endif]-->
|
||||
|
||||
<link href="../../../master/_images/favicon32x32.png" rel="shortcut icon" type="text/css">
|
||||
<!--[if IE]><link rel="shortcut icon" href="../../../master/_images/favicon.ico"><![endif]-->
|
||||
<meta content="AsciiBinder" name="application-name">
|
||||
</head>
|
||||
<body>
|
||||
<div class="navbar navbar-default" role="navigation">
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-header">
|
||||
<a class="navbar-brand" href="https://docs.fedoraproject.org/"><img alt="Fedora Documentation" src="../../../master/_images/fedora.svg"></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container">
|
||||
<p class="toggle-nav visible-xs pull-left">
|
||||
<button class="btn btn-default btn-sm" type="button" data-toggle="offcanvas">Toggle nav</button>
|
||||
</p>
|
||||
<ol class="breadcrumb">
|
||||
<li class="sitename">
|
||||
<a href="../../../index.html">Home</a>
|
||||
</li>
|
||||
<li class="hidden-xs active">
|
||||
<a href="../../en-US/index.html">Defensive Coding Guide </a>
|
||||
</li>
|
||||
<li class="hidden-xs active">
|
||||
<a href="../../en-US/index.html">Defensive Coding Guide</a>
|
||||
</li>
|
||||
<li class="hidden-xs active"><a href="../../en-US/programming-languages/C.html">Programming Languages</a></li>
|
||||
<li class="hidden-xs active">
|
||||
Shell Programming and bash
|
||||
</li>
|
||||
</ol>
|
||||
<div class="row row-offcanvas row-offcanvas-left">
|
||||
<div class="col-xs-8 col-sm-3 col-md-3 sidebar sidebar-offcanvas">
|
||||
<ul class="nav nav-sidebar">
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicGroup0">
|
||||
<span id="tgSpan0" class="fa fa-angle-down"></span>Defensive Coding Guide
|
||||
</a>
|
||||
<ul id="topicGroup0" class="collapse in list-unstyled">
|
||||
<li><a class="" href="../../en-US/index.html">Book Information</a></li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-1">
|
||||
<span id="sgSpan-0-1" class="fa fa-caret-down"></span> Programming Languages
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-1" class="nav-tertiary list-unstyled collapse in">
|
||||
<li><a class="" href="../../en-US/programming-languages/C.html">The C Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/CXX.html">The C++ Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Java.html">The Java Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Python.html">The Python Programming Language</a></li>
|
||||
<li><a class=" active" href="../../en-US/programming-languages/Shell.html">Shell Programming and bash</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Go.html">The Go Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Vala.html">The Vala Programming Language</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-2">
|
||||
<span id="sgSpan-0-2" class="fa fa-caret-right"></span> Specific Programming Tasks
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-2" class="nav-tertiary list-unstyled collapse">
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Library_Design.html">Library Design</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Descriptors.html">File Descriptor Management</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-File_System.html">File System Manipulation</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Temporary_Files.html">Temporary Files</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Processes.html">Processes</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Serialization.html">Serialization and Deserialization</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Cryptography.html">Cryptography</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Packaging.html">RPM Packaging</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-3">
|
||||
<span id="sgSpan-0-3" class="fa fa-caret-right"></span> Implementing Security Features
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-3" class="nav-tertiary list-unstyled collapse">
|
||||
<li><a class="" href="../../en-US/features/Features-Authentication.html">Authentication and Authorization</a></li>
|
||||
<li><a class="" href="../../en-US/features/Features-TLS.html">Transport Layer Security (TLS)</a></li>
|
||||
<li><a class="" href="../../en-US/features/Features-HSM.html">Hardware Security Modules and Smart Cards</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="" href="../../en-US/Revision_History.html">Revision History</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-9 col-md-9 main">
|
||||
<div class="page-header">
|
||||
<h2>Shell Programming and <strong class="application">bash</strong></h2>
|
||||
</div>
|
||||
<div id="preamble">
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>This chapter contains advice about shell programming, specifically
|
||||
in <strong class="application">bash</strong>. Most of the advice will apply
|
||||
to scripts written for other shells because extensions such as
|
||||
integer or array variables have been implemented there as well, with
|
||||
comparable syntax.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="sect-Defensive_Coding-Shell-Alternatives"><a class="anchor" href="#sect-Defensive_Coding-Shell-Alternatives"></a>Consider Alternatives</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>Once a shell script is so complex that advice in this chapter
|
||||
applies, it is time to step back and consider the question: Is
|
||||
there a more suitable implementation language available?</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>For example, Python with its <code>subprocess</code> module
|
||||
can be used to write scripts which are almost as concise as shell
|
||||
scripts when it comes to invoking external programs, and Python
|
||||
offers richer data structures, with less arcane syntax and more
|
||||
consistent behavior.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="sect-Defensive_Coding-Shell-Language"><a class="anchor" href="#sect-Defensive_Coding-Shell-Language"></a>Shell Language Features</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>The following sections cover subtleties concerning the shell
|
||||
programming languages. They have been written with the
|
||||
<strong class="application">bash</strong> shell in mind, but some of these
|
||||
features apply to other shells as well.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Some of the features described may seem like implementation defects,
|
||||
but these features have been replicated across multiple independent
|
||||
implementations, so they now have to be considered part of the shell
|
||||
programming language.</p>
|
||||
</div>
|
||||
<div class="sect2">
|
||||
<h3 id="sect-Defensive_Coding-Shell-Parameter_Expansion"><a class="anchor" href="#sect-Defensive_Coding-Shell-Parameter_Expansion"></a>Parameter Expansion</h3>
|
||||
<div class="paragraph">
|
||||
<p>The mechanism by which named shell variables and parameters are
|
||||
expanded is called <strong>parameter expansion</strong>. The
|
||||
most basic syntax is
|
||||
“<code>$</code><strong>variable</strong>” or
|
||||
“<code>${</code><strong>variable</strong><code>}</code>”.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>In almost all cases, a parameter expansion should be enclosed in
|
||||
double quotation marks <code>“…”</code>.</p>
|
||||
</div>
|
||||
<div class="listingblock">
|
||||
<div class="content">
|
||||
<pre class="CodeRay highlight"><code data-lang="bash">external-program "$arg1" "$arg2"</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>If the double quotation marks are omitted, the value of the
|
||||
variable will be split according to the current value of the
|
||||
<code>IFS</code> variable. This may allow the injection of
|
||||
additional options which are then processed by
|
||||
<code>external-program</code>.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Parameter expansion can use special syntax for specific features,
|
||||
such as substituting defaults or performing string or array
|
||||
operations. These constructs should not be used because they can
|
||||
trigger arithmetic evaluation, which can result in code execution.
|
||||
See <a href="#sect-Defensive_Coding-Shell-Arithmetic">Arithmetic Evaluation</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect2">
|
||||
<h3 id="sect-Defensive_Coding-Shell-Double_Expansion"><a class="anchor" href="#sect-Defensive_Coding-Shell-Double_Expansion"></a>Double Expansion</h3>
|
||||
<div class="paragraph">
|
||||
<p><strong>Double expansion</strong> occurs when, during the
|
||||
expansion of a shell variable, not just the variable is expanded,
|
||||
replacing it by its value, but the <strong>value</strong> of
|
||||
the variable is itself is expanded as well. This can trigger
|
||||
arbitrary code execution, unless the value of the variable is
|
||||
verified against a restrictive pattern.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>The evaluation process is in fact recursive, so a self-referential
|
||||
expression can cause an out-of-memory condition and a shell crash.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Double expansion may seem like as a defect, but it is implemented
|
||||
by many shells, and has to be considered an integral part of the
|
||||
shell programming language. However, it does make writing robust
|
||||
shell scripts difficult.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Double expansion can be requested explicitly with the
|
||||
<code>eval</code> built-in command, or by invoking a
|
||||
subshell with “<code>bash -c</code>”. These constructs
|
||||
should not be used.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>The following sections give examples of places where implicit
|
||||
double expansion occurs.</p>
|
||||
</div>
|
||||
<div class="sect3">
|
||||
<h4 id="sect-Defensive_Coding-Shell-Arithmetic"><a class="anchor" href="#sect-Defensive_Coding-Shell-Arithmetic"></a>Arithmetic Evaluation</h4>
|
||||
<div class="paragraph">
|
||||
<p><strong>Arithmetic evaluation</strong> is a process by which
|
||||
the shell computes the integer value of an expression specified
|
||||
as a string. It is highly problematic for two reasons: It
|
||||
triggers double expansion (see <a href="#sect-Defensive_Coding-Shell-Double_Expansion">Double Expansion</a>), and the
|
||||
language of arithmetic expressions is not self-contained. Some
|
||||
constructs in arithmetic expressions (notably array subscripts)
|
||||
provide a trapdoor from the restricted language of arithmetic
|
||||
expressions to the full shell language, thus paving the way
|
||||
towards arbitrary code execution. Due to double expansion,
|
||||
input which is (indirectly) referenced from an arithmetic
|
||||
expression can trigger execution of arbitrary code, which is
|
||||
potentially harmful.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Arithmetic evaluation is triggered by the follow constructs:</p>
|
||||
</div>
|
||||
<div class="ulist">
|
||||
<ul>
|
||||
<li>
|
||||
<p>The <strong>expression</strong> in
|
||||
“<code>$</code><strong>expression</strong><code></code>”
|
||||
is evaluated. This construct is called <strong>arithmetic
|
||||
expansion</strong>.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p></p>
|
||||
<div class="paragraph">
|
||||
<p>“<code>$[</code><strong>expression</strong><code>]</code>”
|
||||
is a deprecated syntax with the same effect.</p>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<p>The arguments to the <code>let</code> shell built-in
|
||||
are evaluated.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p></p>
|
||||
<div class="paragraph">
|
||||
<p>“<code></code><strong>expression</strong><code></code>”
|
||||
is an alternative syntax for “<code>let</code> <strong>expression</strong>”.</p>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<p>Conditional expressions surrounded by
|
||||
“<code>[[</code>…<code>]]</code>” can trigger
|
||||
arithmetic evaluation if certain operators such as
|
||||
<code>-eq</code> are used. (The
|
||||
<code>test</code> built-in does not perform arithmetic
|
||||
evaluation, even with integer operators such as
|
||||
<code>-eq</code>.)</p>
|
||||
<div class="paragraph">
|
||||
<p>The conditional expression
|
||||
“<code>[[ $</code><strong>variable</strong> <code>=~</code> <strong>regexp</strong> <code>]]</code>”
|
||||
can be used for input validation, assuming that
|
||||
<strong>regexp</strong> is a constant regular
|
||||
expression.
|
||||
See <a href="#sect-Defensive_Coding-Shell-Input_Validation">Performing Input Validation</a>.</p>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<p>Certain parameter expansions, for example
|
||||
“<code>${</code><strong>variable</strong><code>[</code><strong>expression</strong><code>]}</code>”
|
||||
(array indexing) or
|
||||
“<code>${</code><strong>variable</strong><code>:</code><strong>expression</strong><code>}</code>”
|
||||
(string slicing), trigger arithmetic evaluation of
|
||||
<strong>expression</strong>.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Assignment to array elements using
|
||||
“<strong>array_variable</strong><code>[</code><strong>subscript</strong><code>]=</code><strong>expression</strong>”
|
||||
triggers evaluation of <strong>subscript</strong>, but
|
||||
not <strong>expression</strong>.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>The expressions in the arithmetic <code>for</code>
|
||||
command,
|
||||
“<code>for </code><strong>expression1</strong><code>;</code> <strong>expression2</strong><code>;</code> <strong>expression3</strong><code>; do</code> <strong>commands</strong><code>; done</code>”
|
||||
are evaluated. This does not apply to the regular
|
||||
for command,
|
||||
“<code>for</code> <strong>variable</strong> <code>in</code> <strong>list</strong><code>; do</code> <strong>commands</strong><code>; done</code>”.</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="admonitionblock important">
|
||||
<table>
|
||||
<tr>
|
||||
<td class="icon">
|
||||
<i class="fa icon-important" title="Important"></i>
|
||||
</td>
|
||||
<td class="content">
|
||||
<div class="paragraph">
|
||||
<p>Depending on the <strong class="application">bash</strong> version, the
|
||||
above list may be incomplete.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>If faced with a situation where using such shell features
|
||||
appears necessary, see <a href="#sect-Defensive_Coding-Shell-Alternatives">Consider Alternatives</a>.</p>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>If it is impossible to avoid shell arithmetic on untrusted
|
||||
inputs, refer to <a href="#sect-Defensive_Coding-Shell-Input_Validation">Performing Input Validation</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect3">
|
||||
<h4 id="sect-Defensive_Coding-Shell-Types"><a class="anchor" href="#sect-Defensive_Coding-Shell-Types"></a>Type declarations</h4>
|
||||
<div class="paragraph">
|
||||
<p><strong class="application">bash</strong> supports explicit type
|
||||
declarations for shell variables:</p>
|
||||
</div>
|
||||
<div class="listingblock">
|
||||
<div class="content">
|
||||
<pre class="CodeRay highlight"><code data-lang="bash"> declare -i integer_variable
|
||||
declare -a array_variable
|
||||
declare -A assoc_array_variable
|
||||
|
||||
typeset -i integer_variable
|
||||
typeset -a array_variable
|
||||
typeset -A assoc_array_variable
|
||||
|
||||
local -i integer_variable
|
||||
local -a array_variable
|
||||
local -A assoc_array_variable
|
||||
|
||||
readonly -i integer_variable
|
||||
readonly -a array_variable
|
||||
readonly -A assoc_array_variable</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Variables can also be declared as arrays by assigning them an
|
||||
array expression, as in:</p>
|
||||
</div>
|
||||
<div class="listingblock">
|
||||
<div class="content">
|
||||
<pre class="CodeRay highlight"><code data-lang="bash">array_variable=(1 2 3 4)</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Some built-ins (such as <code>mapfile</code>) can
|
||||
implicitly create array variables.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Such type declarations should not be used because assignment to
|
||||
such variables (independent of the concrete syntax used for the
|
||||
assignment) triggers arithmetic expansion (and thus double
|
||||
expansion) of the right-hand side of the assignment operation.
|
||||
See <a href="#sect-Defensive_Coding-Shell-Arithmetic">Arithmetic Evaluation</a>.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Shell scripts which use integer or array variables should be
|
||||
rewritten in another, more suitable language. Se <a href="#sect-Defensive_Coding-Shell-Alternatives">Consider Alternatives</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect2">
|
||||
<h3 id="sect-Defensive_Coding-Shell-Obscure"><a class="anchor" href="#sect-Defensive_Coding-Shell-Obscure"></a>Other Obscurities</h3>
|
||||
<div class="paragraph">
|
||||
<p>Obscure shell language features should not be used. Examples are:</p>
|
||||
</div>
|
||||
<div class="ulist">
|
||||
<ul>
|
||||
<li>
|
||||
<p>Exported functions (<code>export -f</code> or
|
||||
<code>declare -f</code>).</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Function names which are not valid variable names, such as
|
||||
“<code>module::function</code>”.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>The possibility to override built-ins or external commands
|
||||
with shell functions.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Changing the value of the <code>IFS</code> variable to
|
||||
tokenize strings.</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="sect-Defensive_Coding-Shell-Invoke"><a class="anchor" href="#sect-Defensive_Coding-Shell-Invoke"></a>Invoking External Commands</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>When passing shell variables as single command line arguments,
|
||||
they should always be surrounded by double quotes. See
|
||||
<a href="#sect-Defensive_Coding-Shell-Parameter_Expansion">Parameter Expansion</a>.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Care is required when passing untrusted values as positional
|
||||
parameters to external commands. If the value starts with a hyphen
|
||||
“<code>-</code>”, it may be interpreted by the external
|
||||
command as an option. Depending on the external program, a
|
||||
“<code>--</code>” argument stops option processing and treats
|
||||
all following arguments as positional parameters. (Double quotes
|
||||
are completely invisible to the command being invoked, so they do
|
||||
not prevent variable values from being interpreted as options.)</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Cleaning the environment before invoking child processes is
|
||||
difficult to implement in script. <strong class="application">bash</strong>
|
||||
keeps a hidden list of environment variables which do not correspond
|
||||
to shell variables, and unsetting them from within a
|
||||
<strong class="application">bash</strong> script is not possible. To reset
|
||||
the environment, a script can re-run itself under the “<code>env
|
||||
-i</code>” command with an additional parameter which indicates
|
||||
the environment has been cleared and suppresses a further
|
||||
self-execution. Alternatively, individual commands can be executed
|
||||
with “<code>env -i</code>”.</p>
|
||||
</div>
|
||||
<div class="admonitionblock important">
|
||||
<table>
|
||||
<tr>
|
||||
<td class="icon">
|
||||
<i class="fa icon-important" title="Important"></i>
|
||||
</td>
|
||||
<td class="content">
|
||||
<div class="paragraph">
|
||||
<p>Complete isolation from its original execution environment
|
||||
(which is required when the script is executed after a trust
|
||||
transition, e.g., triggered by the SUID mechanism) is impossible
|
||||
to achieve from within the shell script itself. Instead, the
|
||||
invoking process has to clear the process environment (except for
|
||||
few trusted variables) before running the shell script.</p>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Checking for failures in executed external commands is recommended.
|
||||
If no elaborate error recovery is needed, invoking “<code>set
|
||||
-e</code>” may be sufficient. This causes the script to stop on
|
||||
the first failed command. However, failures in pipes
|
||||
(“<code>command1 | command2</code>”) are only detected for the
|
||||
last command in the pipe, errors in previous commands are ignored.
|
||||
This can be changed by invoking “<code>set -o pipefail</code>”.
|
||||
Due to architectural limitations, only the process that spawned
|
||||
the entire pipe can check for failures in individual commands;
|
||||
it is not possible for a process to tell if the process feeding
|
||||
data (or the process consuming data) exited normally or with
|
||||
an error.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>See <a href="#sect-Defensive_Coding-Tasks-Processes-Creation">[sect-Defensive_Coding-Tasks-Processes-Creation]</a>
|
||||
for additional details on creating child processes.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="sect-Defensive_Coding-Shell-Temporary_Files"><a class="anchor" href="#sect-Defensive_Coding-Shell-Temporary_Files"></a>Temporary Files</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>Temporary files should be created with the
|
||||
<code>mktemp</code> command, and temporary directories with
|
||||
“<code>mktemp -d</code>”.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>To clean up temporary files and directories, write a clean-up
|
||||
shell function and register it as a trap handler, as shown in
|
||||
<a href="#ex-Defensive_Coding-Tasks-Temporary_Files">Creating and Cleaning up Temporary Files</a>.
|
||||
Using a separate function avoids issues with proper quoting of
|
||||
variables.</p>
|
||||
</div>
|
||||
<div id="ex-Defensive_Coding-Tasks-Temporary_Files" class="exampleblock">
|
||||
<div class="title">Example 1. Creating and Cleaning up Temporary Files</div>
|
||||
<div class="content">
|
||||
<div class="listingblock">
|
||||
<div class="content">
|
||||
<pre class="CodeRay highlight"><code data-lang="bash">tmpfile="$(mktemp)"
|
||||
|
||||
cleanup () {
|
||||
rm -f -- "$tmpfile"
|
||||
}
|
||||
|
||||
trap cleanup 0</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="sect-Defensive_Coding-Shell-Input_Validation"><a class="anchor" href="#sect-Defensive_Coding-Shell-Input_Validation"></a>Performing Input Validation</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>In some cases, input validation cannot be avoided. For example,
|
||||
if arithmetic evaluation is absolutely required, it is imperative
|
||||
to check that input values are, in fact, integers. See <a href="#sect-Defensive_Coding-Shell-Arithmetic">Arithmetic Evaluation</a>.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p><a href="#ex-Defensive_Coding-Shell-Input_Validation">Input validation in <strong class="application">bash</strong></a>
|
||||
shows a construct which can be used to check if a string
|
||||
“<code>$value</code>” is an integer. This construct is
|
||||
specific to <strong class="application">bash</strong> and not portable to
|
||||
POSIX shells.</p>
|
||||
</div>
|
||||
<div id="ex-Defensive_Coding-Shell-Input_Validation" class="exampleblock">
|
||||
<div class="title">Example 2. Input validation in <strong class="application">bash</strong></div>
|
||||
<div class="content">
|
||||
<div class="listingblock">
|
||||
<div class="content">
|
||||
<pre class="CodeRay highlight"><code data-lang="bash">Unresolved directive in <stdin> - include::../snippets/Shell-Input_Validation.adoc[]</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Using <code>case</code> statements for input validation is
|
||||
also possible and supported by other (POSIX) shells, but the
|
||||
pattern language is more restrictive, and it can be difficult to
|
||||
write suitable patterns.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>The <code>expr</code> external command can give misleading
|
||||
results (e.g., if the value being checked contains operators
|
||||
itself) and should not be used.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="sect-Defensive_Coding-Shell-Edit_Guard"><a class="anchor" href="#sect-Defensive_Coding-Shell-Edit_Guard"></a>Guarding Shell Scripts Against Changes</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p><strong class="application">bash</strong> only reads a shell script up to
|
||||
the point it is needed for executed the next command. This means
|
||||
that if script is overwritten while it is running, execution can
|
||||
jump to a random part of the script, depending on what is modified
|
||||
in the script and how the file offsets change as a result. (This
|
||||
behavior is needed to support self-extracting shell archives whose
|
||||
script part is followed by a stream of bytes which does not follow
|
||||
the shell language syntax.)</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Therefore, long-running scripts should be guarded against
|
||||
concurrent modification by putting as much of the program logic
|
||||
into a <code>main</code> function, and invoking the
|
||||
<code>main</code> function at the end of the script, using
|
||||
this syntax:</p>
|
||||
</div>
|
||||
<div class="listingblock">
|
||||
<div class="content">
|
||||
<pre class="CodeRay highlight"><code data-lang="bash">main "$@" ; exit $?</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>This construct ensures that <strong class="application">bash</strong> will
|
||||
stop execution after the <code>main</code> function, instead
|
||||
of opening the script file and trying to read more commands.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="bottom" class="text-muted py-3" >
|
||||
<div class="foot">
|
||||
<div class="container">
|
||||
<div class="row footerlinks">
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">About</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Overview">About Fedora</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/sponsors">Sponsors</a></dd>
|
||||
<dd><a href="https://fedoramagazine.org">Fedora Magazine</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Legal:Main#Legal">Legal</a></dd>
|
||||
</dl>
|
||||
<ul class="list-inline">
|
||||
<li>
|
||||
<a href="https://www.facebook.com/TheFedoraProject" class="btn-social btn-outline"><i class="fa fa-fw fa-facebook"></i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://plus.google.com/112917221531140868607" class="btn-social btn-outline"><i class="fa fa-fw fa-google-plus"></i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://twitter.com/fedora" class="btn-social btn-outline"><i class="fa fa-fw fa-twitter"></i></a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title uppercase">Download</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://getfedora.org/en/workstation/download">Get Fedora Workstation</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/server/download">Get Fedora Server</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/atomic/download">Get Fedora Atomic</a></dd>
|
||||
<dd><a href="https://spins.fedoraproject.org">Fedora Spins</a></dd>
|
||||
<dd><a href="https://labs.fedoraproject.org">Fedora Labs</a></dd>
|
||||
<dd><a href="https://arm.fedoraproject.org">Fedora ARM<span class="sup">®</span></a></dd>
|
||||
<dd><a href="https://alt.fedoraproject.org/">Alternative Downloads</a></dd>
|
||||
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">Support</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Communicating_and_getting_help">Get Help</a></dd>
|
||||
<dd><a href="https://ask.fedoraproject.org/">Ask Fedora</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Common_F27_bugs">Common Bugs</a></dd>
|
||||
<dd><a href="https://developer.fedoraproject.org/">Fedora Developer Portal</a></dd>
|
||||
<dd><a href="https://docs.fedoraproject.org/f27/install-guide/index.html">Installation Guide</a></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">Join</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Join">Join Fedora</a></dd>
|
||||
<dd><a href="http://fedoraplanet.org">Planet Fedora</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/SIGs">Fedora SIGs</a></dd>
|
||||
<dd><a href="https://admin.fedoraproject.org/accounts/">Fedora Account System</a></dd>
|
||||
<dd><a href="https://fedoracommunity.org/">Fedora Community</a></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- /row of widgets -->
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-2">
|
||||
<div class="widget-body">
|
||||
<a href="https://www.redhat.com/"><img class="rh-logo" src="../../../master/_images/redhat-logo.png" alt="Red Hat Logo" /></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-7">
|
||||
<div class="widget-body">
|
||||
<p class="sponsor">Fedora is sponsored by Red Hat.</p>
|
||||
<p class="sponsor"><a href="https://www.redhat.com/en/technologies/linux-platforms/articles/relationship-between-fedora-and-rhel">Learn more about the relationship between Red Hat and Fedora »</a></p>
|
||||
<p class="copy">© 2017 Red Hat, Inc. and others. Please send any comments or corrections to the <a href="https://pagure.io/fedora-docs/docs-fp-o">documentation team</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- /row of widgets -->
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
|
||||
<!-- Latest compiled and minified JavaScript -->
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
|
||||
<script src="../../../master/_javascripts/bootstrap-offcanvas.js" type="text/javascript"></script>
|
||||
<script type="text/javascript">
|
||||
/*<![CDATA[*/
|
||||
$(document).ready(function() {
|
||||
$("[id^='topicGroup']").on('show.bs.collapse', function (event) {
|
||||
if (!($(event.target).attr('id').match(/^topicSubGroup/))) {
|
||||
$(this).parent().find("[id^='tgSpan']").toggleClass("fa-angle-right fa-angle-down");
|
||||
}
|
||||
});
|
||||
$("[id^='topicGroup']").on('hide.bs.collapse', function (event) {
|
||||
if (!($(event.target).attr('id').match(/^topicSubGroup/))) {
|
||||
$(this).parent().find("[id^='tgSpan']").toggleClass("fa-angle-right fa-angle-down");
|
||||
}
|
||||
});
|
||||
$("[id^='topicSubGroup']").on('show.bs.collapse', function () {
|
||||
$(this).parent().find("[id^='sgSpan']").toggleClass("fa-caret-right fa-caret-down");
|
||||
});
|
||||
$("[id^='topicSubGroup']").on('hide.bs.collapse', function () {
|
||||
$(this).parent().find("[id^='sgSpan']").toggleClass("fa-caret-right fa-caret-down");
|
||||
});
|
||||
});
|
||||
/*]]>*/
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -1,273 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta content="IE=edge" http-equiv="X-UA-Compatible">
|
||||
<meta content="width=device-width, initial-scale=1.0" name="viewport">
|
||||
<title>Defensive Coding Guide | Defensive Coding Guide | Programming Languages | The Vala Programming Language</title>
|
||||
|
||||
<!-- Bootstrap -->
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap-theme.min.css">
|
||||
|
||||
<!-- Overpass Font -->
|
||||
<link rel="stylesheet" href="https://overpass-30e2.kxcdn.com/overpass.css">
|
||||
|
||||
<link href="../../../master/_stylesheets/asciibinder.css" rel="stylesheet" />
|
||||
|
||||
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
|
||||
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
|
||||
<!--[if lt IE 9]>
|
||||
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
|
||||
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
|
||||
<![endif]-->
|
||||
|
||||
<link href="../../../master/_images/favicon32x32.png" rel="shortcut icon" type="text/css">
|
||||
<!--[if IE]><link rel="shortcut icon" href="../../../master/_images/favicon.ico"><![endif]-->
|
||||
<meta content="AsciiBinder" name="application-name">
|
||||
</head>
|
||||
<body>
|
||||
<div class="navbar navbar-default" role="navigation">
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-header">
|
||||
<a class="navbar-brand" href="https://docs.fedoraproject.org/"><img alt="Fedora Documentation" src="../../../master/_images/fedora.svg"></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container">
|
||||
<p class="toggle-nav visible-xs pull-left">
|
||||
<button class="btn btn-default btn-sm" type="button" data-toggle="offcanvas">Toggle nav</button>
|
||||
</p>
|
||||
<ol class="breadcrumb">
|
||||
<li class="sitename">
|
||||
<a href="../../../index.html">Home</a>
|
||||
</li>
|
||||
<li class="hidden-xs active">
|
||||
<a href="../../en-US/index.html">Defensive Coding Guide </a>
|
||||
</li>
|
||||
<li class="hidden-xs active">
|
||||
<a href="../../en-US/index.html">Defensive Coding Guide</a>
|
||||
</li>
|
||||
<li class="hidden-xs active"><a href="../../en-US/programming-languages/C.html">Programming Languages</a></li>
|
||||
<li class="hidden-xs active">
|
||||
The Vala Programming Language
|
||||
</li>
|
||||
</ol>
|
||||
<div class="row row-offcanvas row-offcanvas-left">
|
||||
<div class="col-xs-8 col-sm-3 col-md-3 sidebar sidebar-offcanvas">
|
||||
<ul class="nav nav-sidebar">
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicGroup0">
|
||||
<span id="tgSpan0" class="fa fa-angle-down"></span>Defensive Coding Guide
|
||||
</a>
|
||||
<ul id="topicGroup0" class="collapse in list-unstyled">
|
||||
<li><a class="" href="../../en-US/index.html">Book Information</a></li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-1">
|
||||
<span id="sgSpan-0-1" class="fa fa-caret-down"></span> Programming Languages
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-1" class="nav-tertiary list-unstyled collapse in">
|
||||
<li><a class="" href="../../en-US/programming-languages/C.html">The C Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/CXX.html">The C++ Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Java.html">The Java Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Python.html">The Python Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Shell.html">Shell Programming and bash</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Go.html">The Go Programming Language</a></li>
|
||||
<li><a class=" active" href="../../en-US/programming-languages/Vala.html">The Vala Programming Language</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-2">
|
||||
<span id="sgSpan-0-2" class="fa fa-caret-right"></span> Specific Programming Tasks
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-2" class="nav-tertiary list-unstyled collapse">
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Library_Design.html">Library Design</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Descriptors.html">File Descriptor Management</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-File_System.html">File System Manipulation</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Temporary_Files.html">Temporary Files</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Processes.html">Processes</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Serialization.html">Serialization and Deserialization</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Cryptography.html">Cryptography</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Packaging.html">RPM Packaging</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-3">
|
||||
<span id="sgSpan-0-3" class="fa fa-caret-right"></span> Implementing Security Features
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-3" class="nav-tertiary list-unstyled collapse">
|
||||
<li><a class="" href="../../en-US/features/Features-Authentication.html">Authentication and Authorization</a></li>
|
||||
<li><a class="" href="../../en-US/features/Features-TLS.html">Transport Layer Security (TLS)</a></li>
|
||||
<li><a class="" href="../../en-US/features/Features-HSM.html">Hardware Security Modules and Smart Cards</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="" href="../../en-US/Revision_History.html">Revision History</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-9 col-md-9 main">
|
||||
<div class="page-header">
|
||||
<h2>The Vala Programming Language</h2>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Vala is a programming language mainly targeted at GNOME developers.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Its syntax is inspired by C# (and thus, indirectly, by Java). But
|
||||
unlike C# and Java, Vala does not attempt to provide memory safety:
|
||||
Vala is compiled to C, and the C code is compiled with GCC using
|
||||
typical compiler flags. Basic operations like integer arithmetic
|
||||
are directly mapped to C constructs. As a results, the
|
||||
recommendations in <a href="#chap-Defensive_Coding-C">[chap-Defensive_Coding-C]</a> apply.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>In particular, the following Vala language constructs can result in
|
||||
undefined behavior at run time:</p>
|
||||
</div>
|
||||
<div class="ulist">
|
||||
<ul>
|
||||
<li>
|
||||
<p>Integer arithmetic, as described in <a href="#sect-Defensive_Coding-C-Arithmetic">[sect-Defensive_Coding-C-Arithmetic]</a>.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Pointer arithmetic, string subscripting and the
|
||||
<code>substring</code> method on strings (the
|
||||
<code>string</code> class in the
|
||||
<code>glib-2.0</code> package) are not range-checked. It
|
||||
is the responsibility of the calling code to ensure that the
|
||||
arguments being passed are valid. This applies even to cases
|
||||
(like <code>substring</code>) where the implementation
|
||||
would have range information to check the validity of indexes.
|
||||
See <a href="#sect-Defensive_Coding-C-Pointers">[sect-Defensive_Coding-C-Pointers]</a>.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Similarly, Vala only performs garbage collection (through
|
||||
reference counting) for <code>GObject</code> 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 <a href="#sect-Defensive_Coding-C-Use-After-Free">[sect-Defensive_Coding-C-Use-After-Free]</a>).</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="bottom" class="text-muted py-3" >
|
||||
<div class="foot">
|
||||
<div class="container">
|
||||
<div class="row footerlinks">
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">About</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Overview">About Fedora</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/sponsors">Sponsors</a></dd>
|
||||
<dd><a href="https://fedoramagazine.org">Fedora Magazine</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Legal:Main#Legal">Legal</a></dd>
|
||||
</dl>
|
||||
<ul class="list-inline">
|
||||
<li>
|
||||
<a href="https://www.facebook.com/TheFedoraProject" class="btn-social btn-outline"><i class="fa fa-fw fa-facebook"></i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://plus.google.com/112917221531140868607" class="btn-social btn-outline"><i class="fa fa-fw fa-google-plus"></i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://twitter.com/fedora" class="btn-social btn-outline"><i class="fa fa-fw fa-twitter"></i></a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title uppercase">Download</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://getfedora.org/en/workstation/download">Get Fedora Workstation</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/server/download">Get Fedora Server</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/atomic/download">Get Fedora Atomic</a></dd>
|
||||
<dd><a href="https://spins.fedoraproject.org">Fedora Spins</a></dd>
|
||||
<dd><a href="https://labs.fedoraproject.org">Fedora Labs</a></dd>
|
||||
<dd><a href="https://arm.fedoraproject.org">Fedora ARM<span class="sup">®</span></a></dd>
|
||||
<dd><a href="https://alt.fedoraproject.org/">Alternative Downloads</a></dd>
|
||||
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">Support</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Communicating_and_getting_help">Get Help</a></dd>
|
||||
<dd><a href="https://ask.fedoraproject.org/">Ask Fedora</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Common_F27_bugs">Common Bugs</a></dd>
|
||||
<dd><a href="https://developer.fedoraproject.org/">Fedora Developer Portal</a></dd>
|
||||
<dd><a href="https://docs.fedoraproject.org/f27/install-guide/index.html">Installation Guide</a></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">Join</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Join">Join Fedora</a></dd>
|
||||
<dd><a href="http://fedoraplanet.org">Planet Fedora</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/SIGs">Fedora SIGs</a></dd>
|
||||
<dd><a href="https://admin.fedoraproject.org/accounts/">Fedora Account System</a></dd>
|
||||
<dd><a href="https://fedoracommunity.org/">Fedora Community</a></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- /row of widgets -->
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-2">
|
||||
<div class="widget-body">
|
||||
<a href="https://www.redhat.com/"><img class="rh-logo" src="../../../master/_images/redhat-logo.png" alt="Red Hat Logo" /></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-7">
|
||||
<div class="widget-body">
|
||||
<p class="sponsor">Fedora is sponsored by Red Hat.</p>
|
||||
<p class="sponsor"><a href="https://www.redhat.com/en/technologies/linux-platforms/articles/relationship-between-fedora-and-rhel">Learn more about the relationship between Red Hat and Fedora »</a></p>
|
||||
<p class="copy">© 2017 Red Hat, Inc. and others. Please send any comments or corrections to the <a href="https://pagure.io/fedora-docs/docs-fp-o">documentation team</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- /row of widgets -->
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
|
||||
<!-- Latest compiled and minified JavaScript -->
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
|
||||
<script src="../../../master/_javascripts/bootstrap-offcanvas.js" type="text/javascript"></script>
|
||||
<script type="text/javascript">
|
||||
/*<![CDATA[*/
|
||||
$(document).ready(function() {
|
||||
$("[id^='topicGroup']").on('show.bs.collapse', function (event) {
|
||||
if (!($(event.target).attr('id').match(/^topicSubGroup/))) {
|
||||
$(this).parent().find("[id^='tgSpan']").toggleClass("fa-angle-right fa-angle-down");
|
||||
}
|
||||
});
|
||||
$("[id^='topicGroup']").on('hide.bs.collapse', function (event) {
|
||||
if (!($(event.target).attr('id').match(/^topicSubGroup/))) {
|
||||
$(this).parent().find("[id^='tgSpan']").toggleClass("fa-angle-right fa-angle-down");
|
||||
}
|
||||
});
|
||||
$("[id^='topicSubGroup']").on('show.bs.collapse', function () {
|
||||
$(this).parent().find("[id^='sgSpan']").toggleClass("fa-caret-right fa-caret-down");
|
||||
});
|
||||
$("[id^='topicSubGroup']").on('hide.bs.collapse', function () {
|
||||
$(this).parent().find("[id^='sgSpan']").toggleClass("fa-caret-right fa-caret-down");
|
||||
});
|
||||
});
|
||||
/*]]>*/
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -1,428 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta content="IE=edge" http-equiv="X-UA-Compatible">
|
||||
<meta content="width=device-width, initial-scale=1.0" name="viewport">
|
||||
<title>Defensive Coding Guide | Defensive Coding Guide | Specific Programming Tasks | Cryptography</title>
|
||||
|
||||
<!-- Bootstrap -->
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap-theme.min.css">
|
||||
|
||||
<!-- Overpass Font -->
|
||||
<link rel="stylesheet" href="https://overpass-30e2.kxcdn.com/overpass.css">
|
||||
|
||||
<link href="../../../master/_stylesheets/asciibinder.css" rel="stylesheet" />
|
||||
|
||||
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
|
||||
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
|
||||
<!--[if lt IE 9]>
|
||||
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
|
||||
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
|
||||
<![endif]-->
|
||||
|
||||
<link href="../../../master/_images/favicon32x32.png" rel="shortcut icon" type="text/css">
|
||||
<!--[if IE]><link rel="shortcut icon" href="../../../master/_images/favicon.ico"><![endif]-->
|
||||
<meta content="AsciiBinder" name="application-name">
|
||||
</head>
|
||||
<body>
|
||||
<div class="navbar navbar-default" role="navigation">
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-header">
|
||||
<a class="navbar-brand" href="https://docs.fedoraproject.org/"><img alt="Fedora Documentation" src="../../../master/_images/fedora.svg"></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container">
|
||||
<p class="toggle-nav visible-xs pull-left">
|
||||
<button class="btn btn-default btn-sm" type="button" data-toggle="offcanvas">Toggle nav</button>
|
||||
</p>
|
||||
<ol class="breadcrumb">
|
||||
<li class="sitename">
|
||||
<a href="../../../index.html">Home</a>
|
||||
</li>
|
||||
<li class="hidden-xs active">
|
||||
<a href="../../en-US/index.html">Defensive Coding Guide </a>
|
||||
</li>
|
||||
<li class="hidden-xs active">
|
||||
<a href="../../en-US/index.html">Defensive Coding Guide</a>
|
||||
</li>
|
||||
<li class="hidden-xs active"><a href="../../en-US/tasks/Tasks-Library_Design.html">Specific Programming Tasks</a></li>
|
||||
<li class="hidden-xs active">
|
||||
Cryptography
|
||||
</li>
|
||||
</ol>
|
||||
<div class="row row-offcanvas row-offcanvas-left">
|
||||
<div class="col-xs-8 col-sm-3 col-md-3 sidebar sidebar-offcanvas">
|
||||
<ul class="nav nav-sidebar">
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicGroup0">
|
||||
<span id="tgSpan0" class="fa fa-angle-down"></span>Defensive Coding Guide
|
||||
</a>
|
||||
<ul id="topicGroup0" class="collapse in list-unstyled">
|
||||
<li><a class="" href="../../en-US/index.html">Book Information</a></li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-1">
|
||||
<span id="sgSpan-0-1" class="fa fa-caret-right"></span> Programming Languages
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-1" class="nav-tertiary list-unstyled collapse">
|
||||
<li><a class="" href="../../en-US/programming-languages/C.html">The C Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/CXX.html">The C++ Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Java.html">The Java Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Python.html">The Python Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Shell.html">Shell Programming and bash</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Go.html">The Go Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Vala.html">The Vala Programming Language</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-2">
|
||||
<span id="sgSpan-0-2" class="fa fa-caret-down"></span> Specific Programming Tasks
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-2" class="nav-tertiary list-unstyled collapse in">
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Library_Design.html">Library Design</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Descriptors.html">File Descriptor Management</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-File_System.html">File System Manipulation</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Temporary_Files.html">Temporary Files</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Processes.html">Processes</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Serialization.html">Serialization and Deserialization</a></li>
|
||||
<li><a class=" active" href="../../en-US/tasks/Tasks-Cryptography.html">Cryptography</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Packaging.html">RPM Packaging</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-3">
|
||||
<span id="sgSpan-0-3" class="fa fa-caret-right"></span> Implementing Security Features
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-3" class="nav-tertiary list-unstyled collapse">
|
||||
<li><a class="" href="../../en-US/features/Features-Authentication.html">Authentication and Authorization</a></li>
|
||||
<li><a class="" href="../../en-US/features/Features-TLS.html">Transport Layer Security (TLS)</a></li>
|
||||
<li><a class="" href="../../en-US/features/Features-HSM.html">Hardware Security Modules and Smart Cards</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="" href="../../en-US/Revision_History.html">Revision History</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-9 col-md-9 main">
|
||||
<div class="page-header">
|
||||
<h2>Cryptography</h2>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="primitives"><a class="anchor" href="#primitives"></a>Primitives</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>Choosing from the following cryptographic primitives is
|
||||
recommended:</p>
|
||||
</div>
|
||||
<div class="ulist">
|
||||
<ul>
|
||||
<li>
|
||||
<p>RSA with 2048-bit keys and OAEP or PSS
|
||||
padding</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>AES-128 in CBC mode</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>AES-128 in GCM mode</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>AES-256 in CBC mode</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>AES-256 in GCM mode</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>SHA-256</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>HMAC-SHA-256</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>HMAC-SHA-1</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Other cryptographic algorithms can be used if they are required
|
||||
for interoperability with existing software:</p>
|
||||
</div>
|
||||
<div class="ulist">
|
||||
<ul>
|
||||
<li>
|
||||
<p>RSA with key sizes larger than 1024
|
||||
and legacy padding</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>AES-192</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>3DES (triple DES, with two or three 56-bit keys),
|
||||
but strongly discouraged</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>RC4 (but very, very strongly discouraged)</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>SHA-1</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>HMAC-MD5</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="admonitionblock important">
|
||||
<table>
|
||||
<tr>
|
||||
<td class="icon">
|
||||
<i class="fa icon-important" title="Important"></i>
|
||||
</td>
|
||||
<td class="content">
|
||||
<div class="title">Important</div>
|
||||
<div class="paragraph">
|
||||
<p>These primitives are difficult to use in a secure way. Custom
|
||||
implementation of security protocols should be avoided. For
|
||||
protecting confidentiality and integrity of network
|
||||
transmissions, TLS should be used (<a href="#chap-Defensive_Coding-TLS">[chap-Defensive_Coding-TLS]</a>).</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>In particular, when using AES in CBC mode, it is necessary to
|
||||
add integrity checking by other means, preferably using
|
||||
HMAC-SHA-256 and <strong>after</strong> encryption (that
|
||||
is, on the encrypted cipher text). For AES in GCM mode,
|
||||
correct construction of nonces is absolutely essential.</p>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="randomness"><a class="anchor" href="#randomness"></a>Randomness</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>The following facilities can be used to generate unpredictable
|
||||
and non-repeating values. When these functions are used without
|
||||
special safeguards, each individual random value should be at
|
||||
least 12 bytes long.</p>
|
||||
</div>
|
||||
<div class="ulist">
|
||||
<ul>
|
||||
<li>
|
||||
<p><code>PK11_GenerateRandom</code> in the NSS library
|
||||
(usable for high data rates)</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><code>RAND_bytes</code> in the OpenSSL library
|
||||
(usable for high data rates)</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><code>gnutls_rnd</code> in GNUTLS, with
|
||||
<code>GNUTLS_RND_RANDOM</code> as the first argument
|
||||
(usable for high data rates)</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><code>java.security.SecureRandom</code> in Java
|
||||
(usable for high data rates)</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><code>os.urandom</code> in Python</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>The <code>getrandom</code> system call since glibc 2.25</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>The <code>getentropy</code> call since glibc 2.25</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Reading from the <code>/dev/urandom</code>
|
||||
character device</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>All these functions should be non-blocking, and they should not
|
||||
wait until physical randomness becomes available. (Some
|
||||
cryptography providers for Java can cause
|
||||
<code>java.security.SecureRandom</code> to block, however.)
|
||||
Those functions which do not obtain all bits directly from
|
||||
<code>/dev/urandom</code> are suitable for high data
|
||||
rates because they do not deplete the system-wide entropy pool.</p>
|
||||
</div>
|
||||
<div class="admonitionblock important">
|
||||
<table>
|
||||
<tr>
|
||||
<td class="icon">
|
||||
<i class="fa icon-important" title="Important"></i>
|
||||
</td>
|
||||
<td class="content">
|
||||
<div class="title">Difficult to use API</div>
|
||||
<div class="paragraph">
|
||||
<p>Both <code>RAND_bytes</code> and
|
||||
<code>PK11_GenerateRandom</code> have three-state
|
||||
return values (with conflicting meanings). Careful error
|
||||
checking is required. Please review the documentation when
|
||||
using these functions.</p>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div class="admonitionblock important">
|
||||
<table>
|
||||
<tr>
|
||||
<td class="icon">
|
||||
<i class="fa icon-important" title="Important"></i>
|
||||
</td>
|
||||
<td class="content">
|
||||
<div class="title">Difficult to use API</div>
|
||||
<div class="paragraph">
|
||||
<p>The <code>getrandom</code> system call has three-state
|
||||
return values, hence requires careful error checking.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>It was introduced in Linux kernel 3.17, but before glibc 2.25 no API wrappers were
|
||||
provided. As such one could only use it via the syscall interface
|
||||
as <code>syscall(SYS_getrandom, (void*)dest, (size_t)size, (unsigned int)0)</code>.
|
||||
For portable code targetting multiple kernel versions one has to check
|
||||
for the function beingavailable on run-time, and switch to another
|
||||
facility if the running kernel does not support this call.</p>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Other sources of randomness should be considered predictable.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Generating randomness for cryptographic keys in long-term use
|
||||
may need different steps and is best left to cryptographic
|
||||
libraries.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="bottom" class="text-muted py-3" >
|
||||
<div class="foot">
|
||||
<div class="container">
|
||||
<div class="row footerlinks">
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">About</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Overview">About Fedora</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/sponsors">Sponsors</a></dd>
|
||||
<dd><a href="https://fedoramagazine.org">Fedora Magazine</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Legal:Main#Legal">Legal</a></dd>
|
||||
</dl>
|
||||
<ul class="list-inline">
|
||||
<li>
|
||||
<a href="https://www.facebook.com/TheFedoraProject" class="btn-social btn-outline"><i class="fa fa-fw fa-facebook"></i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://plus.google.com/112917221531140868607" class="btn-social btn-outline"><i class="fa fa-fw fa-google-plus"></i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://twitter.com/fedora" class="btn-social btn-outline"><i class="fa fa-fw fa-twitter"></i></a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title uppercase">Download</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://getfedora.org/en/workstation/download">Get Fedora Workstation</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/server/download">Get Fedora Server</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/atomic/download">Get Fedora Atomic</a></dd>
|
||||
<dd><a href="https://spins.fedoraproject.org">Fedora Spins</a></dd>
|
||||
<dd><a href="https://labs.fedoraproject.org">Fedora Labs</a></dd>
|
||||
<dd><a href="https://arm.fedoraproject.org">Fedora ARM<span class="sup">®</span></a></dd>
|
||||
<dd><a href="https://alt.fedoraproject.org/">Alternative Downloads</a></dd>
|
||||
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">Support</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Communicating_and_getting_help">Get Help</a></dd>
|
||||
<dd><a href="https://ask.fedoraproject.org/">Ask Fedora</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Common_F27_bugs">Common Bugs</a></dd>
|
||||
<dd><a href="https://developer.fedoraproject.org/">Fedora Developer Portal</a></dd>
|
||||
<dd><a href="https://docs.fedoraproject.org/f27/install-guide/index.html">Installation Guide</a></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">Join</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Join">Join Fedora</a></dd>
|
||||
<dd><a href="http://fedoraplanet.org">Planet Fedora</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/SIGs">Fedora SIGs</a></dd>
|
||||
<dd><a href="https://admin.fedoraproject.org/accounts/">Fedora Account System</a></dd>
|
||||
<dd><a href="https://fedoracommunity.org/">Fedora Community</a></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- /row of widgets -->
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-2">
|
||||
<div class="widget-body">
|
||||
<a href="https://www.redhat.com/"><img class="rh-logo" src="../../../master/_images/redhat-logo.png" alt="Red Hat Logo" /></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-7">
|
||||
<div class="widget-body">
|
||||
<p class="sponsor">Fedora is sponsored by Red Hat.</p>
|
||||
<p class="sponsor"><a href="https://www.redhat.com/en/technologies/linux-platforms/articles/relationship-between-fedora-and-rhel">Learn more about the relationship between Red Hat and Fedora »</a></p>
|
||||
<p class="copy">© 2017 Red Hat, Inc. and others. Please send any comments or corrections to the <a href="https://pagure.io/fedora-docs/docs-fp-o">documentation team</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- /row of widgets -->
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
|
||||
<!-- Latest compiled and minified JavaScript -->
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
|
||||
<script src="../../../master/_javascripts/bootstrap-offcanvas.js" type="text/javascript"></script>
|
||||
<script type="text/javascript">
|
||||
/*<![CDATA[*/
|
||||
$(document).ready(function() {
|
||||
$("[id^='topicGroup']").on('show.bs.collapse', function (event) {
|
||||
if (!($(event.target).attr('id').match(/^topicSubGroup/))) {
|
||||
$(this).parent().find("[id^='tgSpan']").toggleClass("fa-angle-right fa-angle-down");
|
||||
}
|
||||
});
|
||||
$("[id^='topicGroup']").on('hide.bs.collapse', function (event) {
|
||||
if (!($(event.target).attr('id').match(/^topicSubGroup/))) {
|
||||
$(this).parent().find("[id^='tgSpan']").toggleClass("fa-angle-right fa-angle-down");
|
||||
}
|
||||
});
|
||||
$("[id^='topicSubGroup']").on('show.bs.collapse', function () {
|
||||
$(this).parent().find("[id^='sgSpan']").toggleClass("fa-caret-right fa-caret-down");
|
||||
});
|
||||
$("[id^='topicSubGroup']").on('hide.bs.collapse', function () {
|
||||
$(this).parent().find("[id^='sgSpan']").toggleClass("fa-caret-right fa-caret-down");
|
||||
});
|
||||
});
|
||||
/*]]>*/
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -1,497 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta content="IE=edge" http-equiv="X-UA-Compatible">
|
||||
<meta content="width=device-width, initial-scale=1.0" name="viewport">
|
||||
<title>Defensive Coding Guide | Defensive Coding Guide | Specific Programming Tasks | File Descriptor Management</title>
|
||||
|
||||
<!-- Bootstrap -->
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap-theme.min.css">
|
||||
|
||||
<!-- Overpass Font -->
|
||||
<link rel="stylesheet" href="https://overpass-30e2.kxcdn.com/overpass.css">
|
||||
|
||||
<link href="../../../master/_stylesheets/asciibinder.css" rel="stylesheet" />
|
||||
|
||||
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
|
||||
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
|
||||
<!--[if lt IE 9]>
|
||||
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
|
||||
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
|
||||
<![endif]-->
|
||||
|
||||
<link href="../../../master/_images/favicon32x32.png" rel="shortcut icon" type="text/css">
|
||||
<!--[if IE]><link rel="shortcut icon" href="../../../master/_images/favicon.ico"><![endif]-->
|
||||
<meta content="AsciiBinder" name="application-name">
|
||||
</head>
|
||||
<body>
|
||||
<div class="navbar navbar-default" role="navigation">
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-header">
|
||||
<a class="navbar-brand" href="https://docs.fedoraproject.org/"><img alt="Fedora Documentation" src="../../../master/_images/fedora.svg"></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container">
|
||||
<p class="toggle-nav visible-xs pull-left">
|
||||
<button class="btn btn-default btn-sm" type="button" data-toggle="offcanvas">Toggle nav</button>
|
||||
</p>
|
||||
<ol class="breadcrumb">
|
||||
<li class="sitename">
|
||||
<a href="../../../index.html">Home</a>
|
||||
</li>
|
||||
<li class="hidden-xs active">
|
||||
<a href="../../en-US/index.html">Defensive Coding Guide </a>
|
||||
</li>
|
||||
<li class="hidden-xs active">
|
||||
<a href="../../en-US/index.html">Defensive Coding Guide</a>
|
||||
</li>
|
||||
<li class="hidden-xs active"><a href="../../en-US/tasks/Tasks-Library_Design.html">Specific Programming Tasks</a></li>
|
||||
<li class="hidden-xs active">
|
||||
File Descriptor Management
|
||||
</li>
|
||||
</ol>
|
||||
<div class="row row-offcanvas row-offcanvas-left">
|
||||
<div class="col-xs-8 col-sm-3 col-md-3 sidebar sidebar-offcanvas">
|
||||
<ul class="nav nav-sidebar">
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicGroup0">
|
||||
<span id="tgSpan0" class="fa fa-angle-down"></span>Defensive Coding Guide
|
||||
</a>
|
||||
<ul id="topicGroup0" class="collapse in list-unstyled">
|
||||
<li><a class="" href="../../en-US/index.html">Book Information</a></li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-1">
|
||||
<span id="sgSpan-0-1" class="fa fa-caret-right"></span> Programming Languages
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-1" class="nav-tertiary list-unstyled collapse">
|
||||
<li><a class="" href="../../en-US/programming-languages/C.html">The C Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/CXX.html">The C++ Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Java.html">The Java Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Python.html">The Python Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Shell.html">Shell Programming and bash</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Go.html">The Go Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Vala.html">The Vala Programming Language</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-2">
|
||||
<span id="sgSpan-0-2" class="fa fa-caret-down"></span> Specific Programming Tasks
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-2" class="nav-tertiary list-unstyled collapse in">
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Library_Design.html">Library Design</a></li>
|
||||
<li><a class=" active" href="../../en-US/tasks/Tasks-Descriptors.html">File Descriptor Management</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-File_System.html">File System Manipulation</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Temporary_Files.html">Temporary Files</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Processes.html">Processes</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Serialization.html">Serialization and Deserialization</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Cryptography.html">Cryptography</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Packaging.html">RPM Packaging</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-3">
|
||||
<span id="sgSpan-0-3" class="fa fa-caret-right"></span> Implementing Security Features
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-3" class="nav-tertiary list-unstyled collapse">
|
||||
<li><a class="" href="../../en-US/features/Features-Authentication.html">Authentication and Authorization</a></li>
|
||||
<li><a class="" href="../../en-US/features/Features-TLS.html">Transport Layer Security (TLS)</a></li>
|
||||
<li><a class="" href="../../en-US/features/Features-HSM.html">Hardware Security Modules and Smart Cards</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="" href="../../en-US/Revision_History.html">Revision History</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-9 col-md-9 main">
|
||||
<div class="page-header">
|
||||
<h2>File Descriptor Management</h2>
|
||||
</div>
|
||||
<div id="preamble">
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>File descriptors underlie all input/output mechanisms offered by
|
||||
the system. They are used to implementation the <code>FILE
|
||||
*</code>-based functions found in
|
||||
<code><stdio.h></code>, and all the file and network
|
||||
communication facilities provided by the Python and Java
|
||||
environments are eventually implemented in them.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>File descriptors are small, non-negative integers in userspace,
|
||||
and are backed on the kernel side with complicated data structures
|
||||
which can sometimes grow very large.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="closing-descriptors"><a class="anchor" href="#closing-descriptors"></a>Closing Descriptors</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>If a descriptor is no longer used by a program and is not closed
|
||||
explicitly, its number cannot be reused (which is problematic in
|
||||
itself, see <a href="#sect-Defensive_Coding-Tasks-Descriptors-Limit">Dealing with the <code>select</code> Limit</a>), and
|
||||
the kernel resources are not freed. Therefore, it is important
|
||||
to close all descriptors at the earliest point in time
|
||||
possible, but not earlier.</p>
|
||||
</div>
|
||||
<div class="sect2">
|
||||
<h3 id="error-handling-during-descriptor-close"><a class="anchor" href="#error-handling-during-descriptor-close"></a>Error Handling during Descriptor Close</h3>
|
||||
<div class="paragraph">
|
||||
<p>The <code>close</code> system call is always
|
||||
successful in the sense that the passed file descriptor is
|
||||
never valid after the function has been called. However,
|
||||
<code>close</code> still can return an error, for
|
||||
example if there was a file system failure. But this error is
|
||||
not very useful because the absence of an error does not mean
|
||||
that all caches have been emptied and previous writes have
|
||||
been made durable. Programs which need such guarantees must
|
||||
open files with <code>O_SYNC</code> or use
|
||||
<code>fsync</code> or <code>fdatasync</code>, and
|
||||
may also have to <code>fsync</code> the directory
|
||||
containing the file.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect2">
|
||||
<h3 id="closing-descriptors-and-race-conditions"><a class="anchor" href="#closing-descriptors-and-race-conditions"></a>Closing Descriptors and Race Conditions</h3>
|
||||
<div class="paragraph">
|
||||
<p>Unlike process IDs, which are recycle only gradually, the
|
||||
kernel always allocates the lowest unused file descriptor when
|
||||
a new descriptor is created. This means that in a
|
||||
multi-threaded program which constantly opens and closes file
|
||||
descriptors, descriptors are reused very quickly. Unless
|
||||
descriptor closing and other operations on the same file
|
||||
descriptor are synchronized (typically, using a mutex), there
|
||||
will be race conditons and I/O operations will be applied to
|
||||
the wrong file descriptor.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Sometimes, it is necessary to close a file descriptor
|
||||
concurrently, while another thread might be about to use it in
|
||||
a system call. In order to support this, a program needs to
|
||||
create a single special file descriptor, one on which all I/O
|
||||
operations fail. One way to achieve this is to use
|
||||
<code>socketpair</code>, close one of the descriptors,
|
||||
and call <code>shutdown(fd, SHUTRDWR)</code> on the
|
||||
other.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>When a descriptor is closed concurrently, the program does not
|
||||
call <code>close</code> on the descriptor. Instead it
|
||||
program uses <code>dup2</code> to replace the
|
||||
descriptor to be closed with the dummy descriptor created
|
||||
earlier. This way, the kernel will not reuse the descriptor,
|
||||
but it will carry out all other steps associated with calling
|
||||
a descriptor (for instance, if the descriptor refers to a
|
||||
stream socket, the peer will be notified).</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>This is just a sketch, and many details are missing.
|
||||
Additional data structures are needed to determine when it is
|
||||
safe to really close the descriptor, and proper locking is
|
||||
required for that.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect2">
|
||||
<h3 id="lingering-state-after-close"><a class="anchor" href="#lingering-state-after-close"></a>Lingering State after Close</h3>
|
||||
<div class="paragraph">
|
||||
<p>By default, closing a stream socket returns immediately, and
|
||||
the kernel will try to send the data in the background. This
|
||||
means that it is impossible to implement accurate accounting
|
||||
of network-related resource utilization from userspace.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>The <code>SO_LINGER</code> socket option alters the
|
||||
behavior of <code>close</code>, so that it will return
|
||||
only after the lingering data has been processed, either by
|
||||
sending it to the peer successfully, or by discarding it after
|
||||
the configured timeout. However, there is no interface which
|
||||
could perform this operation in the background, so a separate
|
||||
userspace thread is needed for each <code>close</code>
|
||||
call, causing scalability issues.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Currently, there is no application-level countermeasure which
|
||||
applies universally. Mitigation is possible with
|
||||
<strong class="application">iptables</strong> (the
|
||||
<code>connlimit</code> match type in particular) and
|
||||
specialized filtering devices for denial-of-service network
|
||||
traffic.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>These problems are not related to the
|
||||
<code>TIME_WAIT</code> state commonly seen in
|
||||
<strong class="application">netstat</strong> output. The kernel
|
||||
automatically expires such sockets if necessary.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="sect-Defensive_Coding-Tasks-Descriptors-Child_Processes"><a class="anchor" href="#sect-Defensive_Coding-Tasks-Descriptors-Child_Processes"></a>Preventing File Descriptor Leaks to Child Processes</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>Child processes created with <code>fork</code> share
|
||||
the initial set of file descriptors with their parent
|
||||
process. By default, file descriptors are also preserved if
|
||||
a new process image is created with <code>execve</code>
|
||||
(or any of the other functions such as <code>system</code>
|
||||
or <code>posix_spawn</code>).</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Usually, this behavior is not desirable. There are two ways to
|
||||
turn it off, that is, to prevent new process images from
|
||||
inheriting the file descriptors in the parent process:</p>
|
||||
</div>
|
||||
<div class="ulist">
|
||||
<ul>
|
||||
<li>
|
||||
<p>Set the close-on-exec flag on all newly created file
|
||||
descriptors. Traditionally, this flag is controlled by the
|
||||
<code>FD_CLOEXEC</code> flag, using
|
||||
<code>F_GETFD</code> and <code>F_SETFD</code>
|
||||
operations of the <code>fcntl</code> function.</p>
|
||||
<div class="paragraph">
|
||||
<p>However, in a multi-threaded process, there is a race
|
||||
condition: a subprocess could have been created between the
|
||||
time the descriptor was created and the
|
||||
<code>FD_CLOEXEC</code> was set. Therefore, many system
|
||||
calls which create descriptors (such as
|
||||
<code>open</code> and <code>openat</code>)
|
||||
now accept the <code>O_CLOEXEC</code> flag
|
||||
(<code>SOCK_CLOEXEC</code> for
|
||||
<code>socket</code> and
|
||||
<code>socketpair</code>), which cause the
|
||||
<code>FD_CLOEXEC</code> flag to be set for the file
|
||||
descriptor in an atomic fashion. In addition, a few new
|
||||
systems calls were introduced, such as
|
||||
<code>pipe2</code> and <code>dup3</code>.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>The downside of this approach is that every descriptor needs
|
||||
to receive special treatment at the time of creation,
|
||||
otherwise it is not completely effective.</p>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<p>After calling <code>fork</code>, but before creating
|
||||
a new process image with <code>execve</code>, all
|
||||
file descriptors which the child process will not need are
|
||||
closed.</p>
|
||||
<div class="paragraph">
|
||||
<p>Traditionally, this was implemented as a loop over file
|
||||
descriptors ranging from <code>3</code> to
|
||||
<code>255</code> and later <code>1023</code>.
|
||||
But this is only an approximation because it is possible to
|
||||
create file descriptors outside this range easily (see <a href="#sect-Defensive_Coding-Tasks-Descriptors-Limit">Dealing with the <code>select</code> Limit</a>).
|
||||
Another approach reads <code>/proc/self/fd</code>
|
||||
and closes the unexpected descriptors listed there, but this
|
||||
approach is much slower.</p>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>At present, environments which care about file descriptor
|
||||
leakage implement the second approach. OpenJDK 6 and 7
|
||||
are among them.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="sect-Defensive_Coding-Tasks-Descriptors-Limit"><a class="anchor" href="#sect-Defensive_Coding-Tasks-Descriptors-Limit"></a>Dealing with the <code>select</code> Limit</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>By default, a user is allowed to open only 1024 files in a
|
||||
single process, but the system administrator can easily change
|
||||
this limit (which is necessary for busy network servers).
|
||||
However, there is another restriction which is more difficult to
|
||||
overcome.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>The <code>select</code> function only supports a
|
||||
maximum of <code>FD_SETSIZE</code> file descriptors
|
||||
(that is, the maximum permitted value for a file descriptor
|
||||
is <code>FD_SETSIZE - 1</code>, usually 1023.) If a
|
||||
process opens many files, descriptors may exceed such
|
||||
limits. It is impossible to query such descriptors using
|
||||
<code>select</code>.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>If a library which creates many file descriptors is used in
|
||||
the same process as a library which uses
|
||||
<code>select</code>, at least one of them needs to
|
||||
be changed.
|
||||
Calls to <code>select</code> can be replaced with
|
||||
calls to <code>poll</code> or another event handling
|
||||
mechanism. Replacing the <code>select</code> function
|
||||
is the recommended approach.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Alternatively, the library with high descriptor usage can
|
||||
relocate descriptors above the <code>FD_SETSIZE</code>
|
||||
limit using the following procedure.</p>
|
||||
</div>
|
||||
<div class="ulist">
|
||||
<ul>
|
||||
<li>
|
||||
<p>Create the file descriptor <code>fd</code> as
|
||||
usual, preferably with the <code>O_CLOEXEC</code>
|
||||
flag.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Before doing anything else with the descriptor
|
||||
<code>fd</code>, invoke:</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="listingblock">
|
||||
<div class="content">
|
||||
<pre> int newfd = fcntl(fd, F_DUPFD_CLOEXEC, (long)FD_SETSIZE);</pre>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ulist">
|
||||
<ul>
|
||||
<li>
|
||||
<p>Check that <code>newfd</code> result is
|
||||
non-negative, otherwise close <code>fd</code> and
|
||||
report an error, and return.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Close <code>fd</code> and continue to use
|
||||
<code>newfd</code>.</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>The new descriptor has been allocated above the
|
||||
<code>FD_SETSIZE</code>. Even though this algorithm
|
||||
is racy in the sense that the <code>FD_SETSIZE</code>
|
||||
first descriptors could fill up, a very high degree of
|
||||
physical parallelism is required before this becomes a problem.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="bottom" class="text-muted py-3" >
|
||||
<div class="foot">
|
||||
<div class="container">
|
||||
<div class="row footerlinks">
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">About</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Overview">About Fedora</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/sponsors">Sponsors</a></dd>
|
||||
<dd><a href="https://fedoramagazine.org">Fedora Magazine</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Legal:Main#Legal">Legal</a></dd>
|
||||
</dl>
|
||||
<ul class="list-inline">
|
||||
<li>
|
||||
<a href="https://www.facebook.com/TheFedoraProject" class="btn-social btn-outline"><i class="fa fa-fw fa-facebook"></i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://plus.google.com/112917221531140868607" class="btn-social btn-outline"><i class="fa fa-fw fa-google-plus"></i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://twitter.com/fedora" class="btn-social btn-outline"><i class="fa fa-fw fa-twitter"></i></a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title uppercase">Download</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://getfedora.org/en/workstation/download">Get Fedora Workstation</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/server/download">Get Fedora Server</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/atomic/download">Get Fedora Atomic</a></dd>
|
||||
<dd><a href="https://spins.fedoraproject.org">Fedora Spins</a></dd>
|
||||
<dd><a href="https://labs.fedoraproject.org">Fedora Labs</a></dd>
|
||||
<dd><a href="https://arm.fedoraproject.org">Fedora ARM<span class="sup">®</span></a></dd>
|
||||
<dd><a href="https://alt.fedoraproject.org/">Alternative Downloads</a></dd>
|
||||
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">Support</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Communicating_and_getting_help">Get Help</a></dd>
|
||||
<dd><a href="https://ask.fedoraproject.org/">Ask Fedora</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Common_F27_bugs">Common Bugs</a></dd>
|
||||
<dd><a href="https://developer.fedoraproject.org/">Fedora Developer Portal</a></dd>
|
||||
<dd><a href="https://docs.fedoraproject.org/f27/install-guide/index.html">Installation Guide</a></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">Join</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Join">Join Fedora</a></dd>
|
||||
<dd><a href="http://fedoraplanet.org">Planet Fedora</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/SIGs">Fedora SIGs</a></dd>
|
||||
<dd><a href="https://admin.fedoraproject.org/accounts/">Fedora Account System</a></dd>
|
||||
<dd><a href="https://fedoracommunity.org/">Fedora Community</a></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- /row of widgets -->
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-2">
|
||||
<div class="widget-body">
|
||||
<a href="https://www.redhat.com/"><img class="rh-logo" src="../../../master/_images/redhat-logo.png" alt="Red Hat Logo" /></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-7">
|
||||
<div class="widget-body">
|
||||
<p class="sponsor">Fedora is sponsored by Red Hat.</p>
|
||||
<p class="sponsor"><a href="https://www.redhat.com/en/technologies/linux-platforms/articles/relationship-between-fedora-and-rhel">Learn more about the relationship between Red Hat and Fedora »</a></p>
|
||||
<p class="copy">© 2017 Red Hat, Inc. and others. Please send any comments or corrections to the <a href="https://pagure.io/fedora-docs/docs-fp-o">documentation team</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- /row of widgets -->
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
|
||||
<!-- Latest compiled and minified JavaScript -->
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
|
||||
<script src="../../../master/_javascripts/bootstrap-offcanvas.js" type="text/javascript"></script>
|
||||
<script type="text/javascript">
|
||||
/*<![CDATA[*/
|
||||
$(document).ready(function() {
|
||||
$("[id^='topicGroup']").on('show.bs.collapse', function (event) {
|
||||
if (!($(event.target).attr('id').match(/^topicSubGroup/))) {
|
||||
$(this).parent().find("[id^='tgSpan']").toggleClass("fa-angle-right fa-angle-down");
|
||||
}
|
||||
});
|
||||
$("[id^='topicGroup']").on('hide.bs.collapse', function (event) {
|
||||
if (!($(event.target).attr('id').match(/^topicSubGroup/))) {
|
||||
$(this).parent().find("[id^='tgSpan']").toggleClass("fa-angle-right fa-angle-down");
|
||||
}
|
||||
});
|
||||
$("[id^='topicSubGroup']").on('show.bs.collapse', function () {
|
||||
$(this).parent().find("[id^='sgSpan']").toggleClass("fa-caret-right fa-caret-down");
|
||||
});
|
||||
$("[id^='topicSubGroup']").on('hide.bs.collapse', function () {
|
||||
$(this).parent().find("[id^='sgSpan']").toggleClass("fa-caret-right fa-caret-down");
|
||||
});
|
||||
});
|
||||
/*]]>*/
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -1,548 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta content="IE=edge" http-equiv="X-UA-Compatible">
|
||||
<meta content="width=device-width, initial-scale=1.0" name="viewport">
|
||||
<title>Defensive Coding Guide | Defensive Coding Guide | Specific Programming Tasks | File System Manipulation</title>
|
||||
|
||||
<!-- Bootstrap -->
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap-theme.min.css">
|
||||
|
||||
<!-- Overpass Font -->
|
||||
<link rel="stylesheet" href="https://overpass-30e2.kxcdn.com/overpass.css">
|
||||
|
||||
<link href="../../../master/_stylesheets/asciibinder.css" rel="stylesheet" />
|
||||
|
||||
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
|
||||
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
|
||||
<!--[if lt IE 9]>
|
||||
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
|
||||
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
|
||||
<![endif]-->
|
||||
|
||||
<link href="../../../master/_images/favicon32x32.png" rel="shortcut icon" type="text/css">
|
||||
<!--[if IE]><link rel="shortcut icon" href="../../../master/_images/favicon.ico"><![endif]-->
|
||||
<meta content="AsciiBinder" name="application-name">
|
||||
</head>
|
||||
<body>
|
||||
<div class="navbar navbar-default" role="navigation">
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-header">
|
||||
<a class="navbar-brand" href="https://docs.fedoraproject.org/"><img alt="Fedora Documentation" src="../../../master/_images/fedora.svg"></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container">
|
||||
<p class="toggle-nav visible-xs pull-left">
|
||||
<button class="btn btn-default btn-sm" type="button" data-toggle="offcanvas">Toggle nav</button>
|
||||
</p>
|
||||
<ol class="breadcrumb">
|
||||
<li class="sitename">
|
||||
<a href="../../../index.html">Home</a>
|
||||
</li>
|
||||
<li class="hidden-xs active">
|
||||
<a href="../../en-US/index.html">Defensive Coding Guide </a>
|
||||
</li>
|
||||
<li class="hidden-xs active">
|
||||
<a href="../../en-US/index.html">Defensive Coding Guide</a>
|
||||
</li>
|
||||
<li class="hidden-xs active"><a href="../../en-US/tasks/Tasks-Library_Design.html">Specific Programming Tasks</a></li>
|
||||
<li class="hidden-xs active">
|
||||
File System Manipulation
|
||||
</li>
|
||||
</ol>
|
||||
<div class="row row-offcanvas row-offcanvas-left">
|
||||
<div class="col-xs-8 col-sm-3 col-md-3 sidebar sidebar-offcanvas">
|
||||
<ul class="nav nav-sidebar">
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicGroup0">
|
||||
<span id="tgSpan0" class="fa fa-angle-down"></span>Defensive Coding Guide
|
||||
</a>
|
||||
<ul id="topicGroup0" class="collapse in list-unstyled">
|
||||
<li><a class="" href="../../en-US/index.html">Book Information</a></li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-1">
|
||||
<span id="sgSpan-0-1" class="fa fa-caret-right"></span> Programming Languages
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-1" class="nav-tertiary list-unstyled collapse">
|
||||
<li><a class="" href="../../en-US/programming-languages/C.html">The C Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/CXX.html">The C++ Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Java.html">The Java Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Python.html">The Python Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Shell.html">Shell Programming and bash</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Go.html">The Go Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Vala.html">The Vala Programming Language</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-2">
|
||||
<span id="sgSpan-0-2" class="fa fa-caret-down"></span> Specific Programming Tasks
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-2" class="nav-tertiary list-unstyled collapse in">
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Library_Design.html">Library Design</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Descriptors.html">File Descriptor Management</a></li>
|
||||
<li><a class=" active" href="../../en-US/tasks/Tasks-File_System.html">File System Manipulation</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Temporary_Files.html">Temporary Files</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Processes.html">Processes</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Serialization.html">Serialization and Deserialization</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Cryptography.html">Cryptography</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Packaging.html">RPM Packaging</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-3">
|
||||
<span id="sgSpan-0-3" class="fa fa-caret-right"></span> Implementing Security Features
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-3" class="nav-tertiary list-unstyled collapse">
|
||||
<li><a class="" href="../../en-US/features/Features-Authentication.html">Authentication and Authorization</a></li>
|
||||
<li><a class="" href="../../en-US/features/Features-TLS.html">Transport Layer Security (TLS)</a></li>
|
||||
<li><a class="" href="../../en-US/features/Features-HSM.html">Hardware Security Modules and Smart Cards</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="" href="../../en-US/Revision_History.html">Revision History</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-9 col-md-9 main">
|
||||
<div class="page-header">
|
||||
<h2>File System Manipulation</h2>
|
||||
</div>
|
||||
<div id="preamble">
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>In this chapter, we discuss general file system manipulation, with
|
||||
a focus on access files and directories to which an other,
|
||||
potentially untrusted user has write access.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Temporary files are covered in their own chapter, <a href="#chap-Defensive_Coding-Tasks-Temporary_Files">[chap-Defensive_Coding-Tasks-Temporary_Files]</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="sect-Defensive_Coding-Tasks-File_System-Unowned"><a class="anchor" href="#sect-Defensive_Coding-Tasks-File_System-Unowned"></a>Working with Files and Directories Owned by Other Users</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>Sometimes, it is necessary to operate on files and directories
|
||||
owned by other (potentially untrusted) users. For example, a
|
||||
system administrator could remove the home directory of a user,
|
||||
or a package manager could update a file in a directory which is
|
||||
owned by an application-specific user. This differs from
|
||||
accessing the file system as a specific user; see
|
||||
<a href="#sect-Defensive_Coding-Tasks-File_System-Foreign">Accessing the File System as a Different User</a>.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Accessing files across trust boundaries faces several
|
||||
challenges, particularly if an entire directory tree is being
|
||||
traversed:</p>
|
||||
</div>
|
||||
<div class="olist arabic">
|
||||
<ol class="arabic">
|
||||
<li>
|
||||
<p>Another user might add file names to a writable directory at
|
||||
any time. This can interfere with file creation and the
|
||||
order of names returned by <code>readdir</code>.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Merely opening and closing a file can have side effects.
|
||||
For instance, an automounter can be triggered, or a tape
|
||||
device rewound. Opening a file on a local file system can
|
||||
block indefinitely, due to mandatory file locking, unless
|
||||
the <code>O_NONBLOCK</code> flag is specified.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Hard links and symbolic links can redirect the effect of
|
||||
file system operations in unexpected ways. The
|
||||
<code>O_NOFOLLOW</code> and
|
||||
<code>AT_SYMLINK_NOFOLLOW</code> variants of system
|
||||
calls only affected final path name component.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>The structure of a directory tree can change. For example,
|
||||
the parent directory of what used to be a subdirectory
|
||||
within the directory tree being processed could suddenly
|
||||
point outside that directory tree.</p>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Files should always be created with the
|
||||
<code>O_CREAT</code> and <code>O_EXCL</code> flags,
|
||||
so that creating the file will fail if it already exists. This
|
||||
guards against the unexpected appearance of file names, either
|
||||
due to creation of a new file, or hard-linking of an existing
|
||||
file. In multi-threaded programs, rather than manipulating the
|
||||
umask, create the files with mode <code>000</code> if
|
||||
possible, and adjust it afterwards with
|
||||
<code>fchmod</code>.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>To avoid issues related to symbolic links and directory tree
|
||||
restructuring, the “<code>at</code>” variants of system
|
||||
calls have to be used (that is, functions like
|
||||
<code>openat</code>, <code>fchownat</code>,
|
||||
<code>fchmodat</code>, and
|
||||
<code>unlinkat</code>, together with
|
||||
<code>O_NOFOLLOW</code> or
|
||||
<code>AT_SYMLINK_NOFOLLOW</code>). Path names passed to
|
||||
these functions must have just a single component (that is,
|
||||
without a slash). When descending, the descriptors of parent
|
||||
directories must be kept open. The missing
|
||||
<code>opendirat</code> function can be emulated with
|
||||
<code>openat</code> (with an
|
||||
<code>O_DIRECTORY</code> flag, to avoid opening special
|
||||
files with side effects), followed by
|
||||
<code>fdopendir</code>.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>If the “<code>at</code>” functions are not available, it
|
||||
is possible to emulate them by changing the current directory.
|
||||
(Obviously, this only works if the process is not multi-threaded.)
|
||||
<code>fchdir</code> has to be used to change the current
|
||||
directory, and the descriptors of the parent directories have to
|
||||
be kept open, just as with the “<code>at</code>”-based
|
||||
approach. <code>chdir("…​")</code> is unsafe because it
|
||||
might ascend outside the intended directory tree.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>This “<code>at</code>” function emulation is currently
|
||||
required when manipulating extended attributes. In this case,
|
||||
the <code>lsetxattr</code> function can be used, with a
|
||||
relative path name consisting of a single component. This also
|
||||
applies to SELinux contexts and the
|
||||
<code>lsetfilecon</code> function.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Currently, it is not possible to avoid opening special files
|
||||
<strong>and</strong> changes to files with hard links if the
|
||||
directory containing them is owned by an untrusted user.
|
||||
(Device nodes can be hard-linked, just as regular files.)
|
||||
<code>fchmodat</code> and <code>fchownat</code>
|
||||
affect files whose link count is greater than one. But opening
|
||||
the files, checking that the link count is one with
|
||||
<code>fstat</code>, and using
|
||||
<code>fchmod</code> and <code>fchown</code> on
|
||||
the file descriptor may have unwanted side effects, due to item
|
||||
2 above. When creating directories, it is therefore important
|
||||
to change the ownership and permissions only after it has been
|
||||
fully created. Until that point, file names are stable, and no
|
||||
files with unexpected hard links can be introduced.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Similarly, when just reading a directory owned by an untrusted
|
||||
user, it is currently impossible to reliably avoid opening
|
||||
special files.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>There is no workaround against the instability of the file list
|
||||
returned by <code>readdir</code>. Concurrent
|
||||
modification of the directory can result in a list of files
|
||||
being returned which never actually existed on disk.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Hard links and symbolic links can be safely deleted using
|
||||
<code>unlinkat</code> without further checks because
|
||||
deletion only affects the name within the directory tree being
|
||||
processed.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="sect-Defensive_Coding-Tasks-File_System-Foreign"><a class="anchor" href="#sect-Defensive_Coding-Tasks-File_System-Foreign"></a>Accessing the File System as a Different User</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>This section deals with access to the file system as a specific
|
||||
user. This is different from accessing files and directories owned by a
|
||||
different, potentially untrusted user; see <a href="#sect-Defensive_Coding-Tasks-File_System-Foreign">Accessing the File System as a Different User</a>.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>One approach is to spawn a child process which runs under the
|
||||
target user and group IDs (both effective and real IDs). Note
|
||||
that this child process can block indefinitely, even when
|
||||
processing regular files only. For example, a special FUSE file
|
||||
system could cause the process to hang in uninterruptible sleep
|
||||
inside a <code>stat</code> system call.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>An existing process could change its user and group ID using
|
||||
<code>setfsuid</code> and <code>setfsgid</code>.
|
||||
(These functions are preferred over <code>seteuid</code>
|
||||
and <code>setegid</code> because they do not allow the
|
||||
impersonated user to send signals to the process.) These
|
||||
functions are not thread safe. In multi-threaded processes,
|
||||
these operations need to be performed in a single-threaded child
|
||||
process. Unexpected blocking may occur as well.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>It is not recommended to try to reimplement the kernel
|
||||
permission checks in user space because the required checks are
|
||||
complex. It is also very difficult to avoid race conditions
|
||||
during path name resolution.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="sect-Defensive_Coding-Tasks-File_System-Limits"><a class="anchor" href="#sect-Defensive_Coding-Tasks-File_System-Limits"></a>File System Limits</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>For historical reasons, there are preprocessor constants such as
|
||||
<code>PATH_MAX</code>, <code>NAME_MAX</code>.
|
||||
However, on most systems, the length of canonical path names
|
||||
(absolute path names with all symbolic links resolved, as
|
||||
returned by <code>realpath</code> or
|
||||
<code>canonicalize_file_name</code>) can exceed
|
||||
<code>PATH_MAX</code> bytes, and individual file name
|
||||
components can be longer than <code>NAME_MAX</code>. This
|
||||
is also true of the <code>_PC_PATH_MAX</code> and
|
||||
<code>_PC_NAME_MAX</code> values returned by
|
||||
<code>pathconf</code>, and the
|
||||
<code>f_namemax</code> member of <code>struct
|
||||
statvfs</code>. Therefore, these constants should not be
|
||||
used. This is also reason why the
|
||||
<code>readdir_r</code> should never be used (instead,
|
||||
use <code>readdir</code>).</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>You should not write code in a way that assumes that there is an
|
||||
upper limit on the number of subdirectories of a directory, the
|
||||
number of regular files in a directory, or the link count of an
|
||||
inode.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="sect-Defensive_Coding-Tasks-File_System-Features"><a class="anchor" href="#sect-Defensive_Coding-Tasks-File_System-Features"></a>File system features</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>Not all file systems support all features. This makes it very
|
||||
difficult to write general-purpose tools for copying files. For
|
||||
example, a copy operation intending to preserve file permissions
|
||||
will generally fail when copying to a FAT file system.</p>
|
||||
</div>
|
||||
<div class="ulist">
|
||||
<ul>
|
||||
<li>
|
||||
<p>Some file systems are case-insensitive. Most should be
|
||||
case-preserving, though.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Name length limits vary greatly, from eight to thousands of
|
||||
bytes. Path length limits differ as well. Most systems
|
||||
impose an upper bound on path names passed to the kernel,
|
||||
but using relative path names, it is possible to create and
|
||||
access files whose absolute path name is essentially of
|
||||
unbounded length.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Some file systems do not store names as fairly unrestricted
|
||||
byte sequences, as it has been traditionally the case on GNU
|
||||
systems. This means that some byte sequences (outside the
|
||||
POSIX safe character set) are not valid names. Conversely,
|
||||
names of existing files may not be representable as byte
|
||||
sequences, and the files are thus inaccessible on GNU
|
||||
systems. Some file systems perform Unicode canonicalization
|
||||
on file names. These file systems preserve case, but
|
||||
reading the name of a just-created file using
|
||||
<code>readdir</code> might still result in a
|
||||
different byte sequence.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Permissions and owners are not universally supported (and
|
||||
SUID/SGID bits may not be available). For example, FAT file
|
||||
systems assign ownership based on a mount option, and
|
||||
generally mark all files as executable. Any attempt to
|
||||
change permissions would result in an error.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Non-regular files (device nodes, FIFOs) are not generally
|
||||
available.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Only on some file systems, files can have holes, that is,
|
||||
not all of their contents is backed by disk storage.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><code>ioctl</code> support (even fairly generic
|
||||
functionality such as <code>FIEMAP</code> for
|
||||
discovering physical file layout and holes) is
|
||||
file-system-specific.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Not all file systems support extended attributes, ACLs and
|
||||
SELinux metadata. Size and naming restriction on extended
|
||||
attributes vary.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Hard links may not be supported at all (FAT) or only within
|
||||
the same directory (AFS). Symbolic links may not be
|
||||
available, either. Reflinks (hard links with copy-on-write
|
||||
semantics) are still very rare. Recent systems restrict
|
||||
creation of hard links to users which own the target file or
|
||||
have read/write access to it, but older systems do not.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Renaming (or moving) files using <code>rename</code>
|
||||
can fail (even when <code>stat</code> indicates that
|
||||
the source and target directories are located on the same
|
||||
file system). This system call should work if the old and
|
||||
new paths are located in the same directory, though.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Locking semantics vary among file systems. This affects
|
||||
advisory and mandatory locks. For example, some network
|
||||
file systems do not allow deleting files which are opened by
|
||||
any process.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Resolution of time stamps varies from two seconds to
|
||||
nanoseconds. Not all time stamps are available on all file
|
||||
systems. File creation time (<strong>birth
|
||||
time</strong>) is not exposed over the
|
||||
<code>stat</code>/<code>fstat</code>
|
||||
interface, even if stored by the file system.</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="sect-Defensive_Coding-Tasks-File_System-Free_Space"><a class="anchor" href="#sect-Defensive_Coding-Tasks-File_System-Free_Space"></a>Checking Free Space</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>The <code>statvfs</code> and
|
||||
<code>fstatvfs</code> functions allow programs to
|
||||
examine the number of available blocks and inodes, through the
|
||||
members <code>f_bfree</code>, <code>f_bavail</code>,
|
||||
<code>f_ffree</code>, and <code>f_favail</code> of
|
||||
<code>struct statvfs</code>. Some file systems return
|
||||
fictional values in the <code>f_ffree</code> and
|
||||
<code>f_favail</code> fields, so the only reliable way to
|
||||
discover if the file system still has space for a file is to try
|
||||
to create it. The <code>f_bfree</code> field should be
|
||||
reasonably accurate, though.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="bottom" class="text-muted py-3" >
|
||||
<div class="foot">
|
||||
<div class="container">
|
||||
<div class="row footerlinks">
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">About</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Overview">About Fedora</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/sponsors">Sponsors</a></dd>
|
||||
<dd><a href="https://fedoramagazine.org">Fedora Magazine</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Legal:Main#Legal">Legal</a></dd>
|
||||
</dl>
|
||||
<ul class="list-inline">
|
||||
<li>
|
||||
<a href="https://www.facebook.com/TheFedoraProject" class="btn-social btn-outline"><i class="fa fa-fw fa-facebook"></i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://plus.google.com/112917221531140868607" class="btn-social btn-outline"><i class="fa fa-fw fa-google-plus"></i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://twitter.com/fedora" class="btn-social btn-outline"><i class="fa fa-fw fa-twitter"></i></a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title uppercase">Download</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://getfedora.org/en/workstation/download">Get Fedora Workstation</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/server/download">Get Fedora Server</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/atomic/download">Get Fedora Atomic</a></dd>
|
||||
<dd><a href="https://spins.fedoraproject.org">Fedora Spins</a></dd>
|
||||
<dd><a href="https://labs.fedoraproject.org">Fedora Labs</a></dd>
|
||||
<dd><a href="https://arm.fedoraproject.org">Fedora ARM<span class="sup">®</span></a></dd>
|
||||
<dd><a href="https://alt.fedoraproject.org/">Alternative Downloads</a></dd>
|
||||
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">Support</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Communicating_and_getting_help">Get Help</a></dd>
|
||||
<dd><a href="https://ask.fedoraproject.org/">Ask Fedora</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Common_F27_bugs">Common Bugs</a></dd>
|
||||
<dd><a href="https://developer.fedoraproject.org/">Fedora Developer Portal</a></dd>
|
||||
<dd><a href="https://docs.fedoraproject.org/f27/install-guide/index.html">Installation Guide</a></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">Join</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Join">Join Fedora</a></dd>
|
||||
<dd><a href="http://fedoraplanet.org">Planet Fedora</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/SIGs">Fedora SIGs</a></dd>
|
||||
<dd><a href="https://admin.fedoraproject.org/accounts/">Fedora Account System</a></dd>
|
||||
<dd><a href="https://fedoracommunity.org/">Fedora Community</a></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- /row of widgets -->
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-2">
|
||||
<div class="widget-body">
|
||||
<a href="https://www.redhat.com/"><img class="rh-logo" src="../../../master/_images/redhat-logo.png" alt="Red Hat Logo" /></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-7">
|
||||
<div class="widget-body">
|
||||
<p class="sponsor">Fedora is sponsored by Red Hat.</p>
|
||||
<p class="sponsor"><a href="https://www.redhat.com/en/technologies/linux-platforms/articles/relationship-between-fedora-and-rhel">Learn more about the relationship between Red Hat and Fedora »</a></p>
|
||||
<p class="copy">© 2017 Red Hat, Inc. and others. Please send any comments or corrections to the <a href="https://pagure.io/fedora-docs/docs-fp-o">documentation team</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- /row of widgets -->
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
|
||||
<!-- Latest compiled and minified JavaScript -->
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
|
||||
<script src="../../../master/_javascripts/bootstrap-offcanvas.js" type="text/javascript"></script>
|
||||
<script type="text/javascript">
|
||||
/*<![CDATA[*/
|
||||
$(document).ready(function() {
|
||||
$("[id^='topicGroup']").on('show.bs.collapse', function (event) {
|
||||
if (!($(event.target).attr('id').match(/^topicSubGroup/))) {
|
||||
$(this).parent().find("[id^='tgSpan']").toggleClass("fa-angle-right fa-angle-down");
|
||||
}
|
||||
});
|
||||
$("[id^='topicGroup']").on('hide.bs.collapse', function (event) {
|
||||
if (!($(event.target).attr('id').match(/^topicSubGroup/))) {
|
||||
$(this).parent().find("[id^='tgSpan']").toggleClass("fa-angle-right fa-angle-down");
|
||||
}
|
||||
});
|
||||
$("[id^='topicSubGroup']").on('show.bs.collapse', function () {
|
||||
$(this).parent().find("[id^='sgSpan']").toggleClass("fa-caret-right fa-caret-down");
|
||||
});
|
||||
$("[id^='topicSubGroup']").on('hide.bs.collapse', function () {
|
||||
$(this).parent().find("[id^='sgSpan']").toggleClass("fa-caret-right fa-caret-down");
|
||||
});
|
||||
});
|
||||
/*]]>*/
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -1,425 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta content="IE=edge" http-equiv="X-UA-Compatible">
|
||||
<meta content="width=device-width, initial-scale=1.0" name="viewport">
|
||||
<title>Defensive Coding Guide | Defensive Coding Guide | Specific Programming Tasks | Library Design</title>
|
||||
|
||||
<!-- Bootstrap -->
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap-theme.min.css">
|
||||
|
||||
<!-- Overpass Font -->
|
||||
<link rel="stylesheet" href="https://overpass-30e2.kxcdn.com/overpass.css">
|
||||
|
||||
<link href="../../../master/_stylesheets/asciibinder.css" rel="stylesheet" />
|
||||
|
||||
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
|
||||
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
|
||||
<!--[if lt IE 9]>
|
||||
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
|
||||
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
|
||||
<![endif]-->
|
||||
|
||||
<link href="../../../master/_images/favicon32x32.png" rel="shortcut icon" type="text/css">
|
||||
<!--[if IE]><link rel="shortcut icon" href="../../../master/_images/favicon.ico"><![endif]-->
|
||||
<meta content="AsciiBinder" name="application-name">
|
||||
</head>
|
||||
<body>
|
||||
<div class="navbar navbar-default" role="navigation">
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-header">
|
||||
<a class="navbar-brand" href="https://docs.fedoraproject.org/"><img alt="Fedora Documentation" src="../../../master/_images/fedora.svg"></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container">
|
||||
<p class="toggle-nav visible-xs pull-left">
|
||||
<button class="btn btn-default btn-sm" type="button" data-toggle="offcanvas">Toggle nav</button>
|
||||
</p>
|
||||
<ol class="breadcrumb">
|
||||
<li class="sitename">
|
||||
<a href="../../../index.html">Home</a>
|
||||
</li>
|
||||
<li class="hidden-xs active">
|
||||
<a href="../../en-US/index.html">Defensive Coding Guide </a>
|
||||
</li>
|
||||
<li class="hidden-xs active">
|
||||
<a href="../../en-US/index.html">Defensive Coding Guide</a>
|
||||
</li>
|
||||
<li class="hidden-xs active"><a href="../../en-US/tasks/Tasks-Library_Design.html">Specific Programming Tasks</a></li>
|
||||
<li class="hidden-xs active">
|
||||
Library Design
|
||||
</li>
|
||||
</ol>
|
||||
<div class="row row-offcanvas row-offcanvas-left">
|
||||
<div class="col-xs-8 col-sm-3 col-md-3 sidebar sidebar-offcanvas">
|
||||
<ul class="nav nav-sidebar">
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicGroup0">
|
||||
<span id="tgSpan0" class="fa fa-angle-down"></span>Defensive Coding Guide
|
||||
</a>
|
||||
<ul id="topicGroup0" class="collapse in list-unstyled">
|
||||
<li><a class="" href="../../en-US/index.html">Book Information</a></li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-1">
|
||||
<span id="sgSpan-0-1" class="fa fa-caret-right"></span> Programming Languages
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-1" class="nav-tertiary list-unstyled collapse">
|
||||
<li><a class="" href="../../en-US/programming-languages/C.html">The C Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/CXX.html">The C++ Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Java.html">The Java Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Python.html">The Python Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Shell.html">Shell Programming and bash</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Go.html">The Go Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Vala.html">The Vala Programming Language</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-2">
|
||||
<span id="sgSpan-0-2" class="fa fa-caret-down"></span> Specific Programming Tasks
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-2" class="nav-tertiary list-unstyled collapse in">
|
||||
<li><a class=" active" href="../../en-US/tasks/Tasks-Library_Design.html">Library Design</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Descriptors.html">File Descriptor Management</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-File_System.html">File System Manipulation</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Temporary_Files.html">Temporary Files</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Processes.html">Processes</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Serialization.html">Serialization and Deserialization</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Cryptography.html">Cryptography</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Packaging.html">RPM Packaging</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-3">
|
||||
<span id="sgSpan-0-3" class="fa fa-caret-right"></span> Implementing Security Features
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-3" class="nav-tertiary list-unstyled collapse">
|
||||
<li><a class="" href="../../en-US/features/Features-Authentication.html">Authentication and Authorization</a></li>
|
||||
<li><a class="" href="../../en-US/features/Features-TLS.html">Transport Layer Security (TLS)</a></li>
|
||||
<li><a class="" href="../../en-US/features/Features-HSM.html">Hardware Security Modules and Smart Cards</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="" href="../../en-US/Revision_History.html">Revision History</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-9 col-md-9 main">
|
||||
<div class="page-header">
|
||||
<h2>Library Design</h2>
|
||||
</div>
|
||||
<div id="preamble">
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>Through this section, the term <strong>client code</strong>
|
||||
refers to applications and other libraries using the library.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="state-management"><a class="anchor" href="#state-management"></a>State Management</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="sect2">
|
||||
<h3 id="global-state"><a class="anchor" href="#global-state"></a>Global State</h3>
|
||||
<div class="paragraph">
|
||||
<p>Global state should be avoided.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>If this is impossible, the global state must be protected with
|
||||
a lock. For C/C++, you can use the
|
||||
<code>pthread_mutex_lock</code>
|
||||
and <code>pthread_mutex_unlock</code>
|
||||
functions without linking against <code>-lpthread</code>
|
||||
because the system provides stubs for non-threaded processes.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>For compatibility with <code>fork</code>, these locks
|
||||
should be acquired and released in helpers registered with
|
||||
<code>pthread_atfork</code>. This function is not
|
||||
available without <code>-lpthread</code>, so you need to
|
||||
use <code>dlsym</code> or a weak symbol to obtain its
|
||||
address.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>If you need <code>fork</code> protection for other
|
||||
reasons, you should store the process ID and compare it to the
|
||||
value returned by <code>getpid</code> each time you
|
||||
access the global state. (<code>getpid</code> is not
|
||||
implemented as a system call and is fast.) If the value
|
||||
changes, you know that you have to re-create the state object.
|
||||
(This needs to be combined with locking, of course.)</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect2">
|
||||
<h3 id="handles"><a class="anchor" href="#handles"></a>Handles</h3>
|
||||
<div class="paragraph">
|
||||
<p>Library state should be kept behind a curtain. Client code
|
||||
should receive only a handle. In C, the handle can be a
|
||||
pointer to an incomplete <code>struct</code>. In C++,
|
||||
the handle can be a pointer to an abstract base class, or it
|
||||
can be hidden using the pointer-to-implementation idiom.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>The library should provide functions for creating and
|
||||
destroying handles. (In C++, it is possible to use virtual
|
||||
destructors for the latter.) Consistency between creation and
|
||||
destruction of handles is strongly recommended: If the client
|
||||
code created a handle, it is the responsibility of the client
|
||||
code to destroy it. (This is not always possible or
|
||||
convenient, so sometimes, a transfer of ownership has to
|
||||
happen.)</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Using handles ensures that it is possible to change the way
|
||||
the library represents state in a way that is transparent to
|
||||
client code. This is important to facilitate security updates
|
||||
and many other code changes.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>It is not always necessary to protect state behind a handle
|
||||
with a lock. This depends on the level of thread safety
|
||||
the library provides.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="object-orientation"><a class="anchor" href="#object-orientation"></a>Object Orientation</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>Classes should be either designed as base classes, or it should
|
||||
be impossible to use them as base classes (like
|
||||
<code>final</code> classes in Java). Classes which are
|
||||
not designed for inheritance and are used as base classes
|
||||
nevertheless create potential maintenance hazards because it is
|
||||
difficult to predict how client code will react when calls to
|
||||
virtual methods are added, reordered or removed.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Virtual member functions can be used as callbacks. See
|
||||
<a href="#sect-Defensive_Coding-Tasks-Library_Design-Callbacks">Callbacks</a>
|
||||
for some of the challenges involved.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="sect-Defensive_Coding-Tasks-Library_Design-Callbacks"><a class="anchor" href="#sect-Defensive_Coding-Tasks-Library_Design-Callbacks"></a>Callbacks</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>Higher-order code is difficult to analyze for humans and
|
||||
computers alike, so it should be avoided. Often, an
|
||||
iterator-based interface (a library function which is called
|
||||
repeatedly by client code and returns a stream of events) leads
|
||||
to a better design which is easier to document and use.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>If callbacks are unavoidable, some guidelines for them follow.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>In modern C++ code, <code>std::function</code> objects
|
||||
should be used for callbacks.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>In older C++ code and in C code, all callbacks must have an
|
||||
additional closure parameter of type <code>void *</code>,
|
||||
the value of which can be specified by client code. If
|
||||
possible, the value of the closure parameter should be provided
|
||||
by client code at the same time a specific callback is
|
||||
registered (or specified as a function argument). If a single
|
||||
closure parameter is shared by multiple callbacks, flexibility
|
||||
is greatly reduced, and conflicts between different pieces of
|
||||
client code using the same library object could be unresolvable.
|
||||
In some cases, it makes sense to provide a de-registration
|
||||
callback which can be used to destroy the closure parameter when
|
||||
the callback is no longer used.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Callbacks can throw exceptions or call
|
||||
<code>longjmp</code>. If possible, all library objects
|
||||
should remain in a valid state. (All further operations on them
|
||||
can fail, but it should be possible to deallocate them without
|
||||
causing resource leaks.)</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>The presence of callbacks raises the question if functions
|
||||
provided by the library are <strong>reentrant</strong>.
|
||||
Unless a library was designed for such use, bad things will
|
||||
happen if a callback function uses functions in the same library
|
||||
(particularly if they are invoked on the same objects and
|
||||
manipulate the same state). When the callback is invoked, the
|
||||
library can be in an inconsistent state. Reentrant functions
|
||||
are more difficult to write than thread-safe functions (by
|
||||
definition, simple locking would immediately lead to deadlocks).
|
||||
It is also difficult to decide what to do when destruction of an
|
||||
object which is currently processing a callback is requested.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="process-attributes"><a class="anchor" href="#process-attributes"></a>Process Attributes</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>Several attributes are global and affect all code in the
|
||||
process, not just the library that manipulates them.</p>
|
||||
</div>
|
||||
<div class="ulist">
|
||||
<ul>
|
||||
<li>
|
||||
<p>environment variables
|
||||
(see <a href="#sect-Defensive_Coding-Tasks-secure_getenv">[sect-Defensive_Coding-Tasks-secure_getenv]</a>)</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>umask</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>user IDs, group IDs and capabilities</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>current working directory</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>signal handlers, signal masks and signal delivery</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>file locks (especially <code>fcntl</code> locks
|
||||
behave in surprising ways, not just in a multi-threaded
|
||||
environment)</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Library code should avoid manipulating these global process
|
||||
attributes. It should not rely on environment variables, umask,
|
||||
the current working directory and signal masks because these
|
||||
attributes can be inherited from an untrusted source.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>In addition, there are obvious process-wide aspects such as the
|
||||
virtual memory layout, the set of open files and dynamic shared
|
||||
objects, but with the exception of shared objects, these can be
|
||||
manipulated in a relatively isolated way.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="bottom" class="text-muted py-3" >
|
||||
<div class="foot">
|
||||
<div class="container">
|
||||
<div class="row footerlinks">
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">About</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Overview">About Fedora</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/sponsors">Sponsors</a></dd>
|
||||
<dd><a href="https://fedoramagazine.org">Fedora Magazine</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Legal:Main#Legal">Legal</a></dd>
|
||||
</dl>
|
||||
<ul class="list-inline">
|
||||
<li>
|
||||
<a href="https://www.facebook.com/TheFedoraProject" class="btn-social btn-outline"><i class="fa fa-fw fa-facebook"></i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://plus.google.com/112917221531140868607" class="btn-social btn-outline"><i class="fa fa-fw fa-google-plus"></i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://twitter.com/fedora" class="btn-social btn-outline"><i class="fa fa-fw fa-twitter"></i></a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title uppercase">Download</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://getfedora.org/en/workstation/download">Get Fedora Workstation</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/server/download">Get Fedora Server</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/atomic/download">Get Fedora Atomic</a></dd>
|
||||
<dd><a href="https://spins.fedoraproject.org">Fedora Spins</a></dd>
|
||||
<dd><a href="https://labs.fedoraproject.org">Fedora Labs</a></dd>
|
||||
<dd><a href="https://arm.fedoraproject.org">Fedora ARM<span class="sup">®</span></a></dd>
|
||||
<dd><a href="https://alt.fedoraproject.org/">Alternative Downloads</a></dd>
|
||||
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">Support</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Communicating_and_getting_help">Get Help</a></dd>
|
||||
<dd><a href="https://ask.fedoraproject.org/">Ask Fedora</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Common_F27_bugs">Common Bugs</a></dd>
|
||||
<dd><a href="https://developer.fedoraproject.org/">Fedora Developer Portal</a></dd>
|
||||
<dd><a href="https://docs.fedoraproject.org/f27/install-guide/index.html">Installation Guide</a></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">Join</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Join">Join Fedora</a></dd>
|
||||
<dd><a href="http://fedoraplanet.org">Planet Fedora</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/SIGs">Fedora SIGs</a></dd>
|
||||
<dd><a href="https://admin.fedoraproject.org/accounts/">Fedora Account System</a></dd>
|
||||
<dd><a href="https://fedoracommunity.org/">Fedora Community</a></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- /row of widgets -->
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-2">
|
||||
<div class="widget-body">
|
||||
<a href="https://www.redhat.com/"><img class="rh-logo" src="../../../master/_images/redhat-logo.png" alt="Red Hat Logo" /></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-7">
|
||||
<div class="widget-body">
|
||||
<p class="sponsor">Fedora is sponsored by Red Hat.</p>
|
||||
<p class="sponsor"><a href="https://www.redhat.com/en/technologies/linux-platforms/articles/relationship-between-fedora-and-rhel">Learn more about the relationship between Red Hat and Fedora »</a></p>
|
||||
<p class="copy">© 2017 Red Hat, Inc. and others. Please send any comments or corrections to the <a href="https://pagure.io/fedora-docs/docs-fp-o">documentation team</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- /row of widgets -->
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
|
||||
<!-- Latest compiled and minified JavaScript -->
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
|
||||
<script src="../../../master/_javascripts/bootstrap-offcanvas.js" type="text/javascript"></script>
|
||||
<script type="text/javascript">
|
||||
/*<![CDATA[*/
|
||||
$(document).ready(function() {
|
||||
$("[id^='topicGroup']").on('show.bs.collapse', function (event) {
|
||||
if (!($(event.target).attr('id').match(/^topicSubGroup/))) {
|
||||
$(this).parent().find("[id^='tgSpan']").toggleClass("fa-angle-right fa-angle-down");
|
||||
}
|
||||
});
|
||||
$("[id^='topicGroup']").on('hide.bs.collapse', function (event) {
|
||||
if (!($(event.target).attr('id').match(/^topicSubGroup/))) {
|
||||
$(this).parent().find("[id^='tgSpan']").toggleClass("fa-angle-right fa-angle-down");
|
||||
}
|
||||
});
|
||||
$("[id^='topicSubGroup']").on('show.bs.collapse', function () {
|
||||
$(this).parent().find("[id^='sgSpan']").toggleClass("fa-caret-right fa-caret-down");
|
||||
});
|
||||
$("[id^='topicSubGroup']").on('hide.bs.collapse', function () {
|
||||
$(this).parent().find("[id^='sgSpan']").toggleClass("fa-caret-right fa-caret-down");
|
||||
});
|
||||
});
|
||||
/*]]>*/
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -1,438 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta content="IE=edge" http-equiv="X-UA-Compatible">
|
||||
<meta content="width=device-width, initial-scale=1.0" name="viewport">
|
||||
<title>Defensive Coding Guide | Defensive Coding Guide | Specific Programming Tasks | RPM Packaging</title>
|
||||
|
||||
<!-- Bootstrap -->
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap-theme.min.css">
|
||||
|
||||
<!-- Overpass Font -->
|
||||
<link rel="stylesheet" href="https://overpass-30e2.kxcdn.com/overpass.css">
|
||||
|
||||
<link href="../../../master/_stylesheets/asciibinder.css" rel="stylesheet" />
|
||||
|
||||
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
|
||||
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
|
||||
<!--[if lt IE 9]>
|
||||
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
|
||||
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
|
||||
<![endif]-->
|
||||
|
||||
<link href="../../../master/_images/favicon32x32.png" rel="shortcut icon" type="text/css">
|
||||
<!--[if IE]><link rel="shortcut icon" href="../../../master/_images/favicon.ico"><![endif]-->
|
||||
<meta content="AsciiBinder" name="application-name">
|
||||
</head>
|
||||
<body>
|
||||
<div class="navbar navbar-default" role="navigation">
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-header">
|
||||
<a class="navbar-brand" href="https://docs.fedoraproject.org/"><img alt="Fedora Documentation" src="../../../master/_images/fedora.svg"></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container">
|
||||
<p class="toggle-nav visible-xs pull-left">
|
||||
<button class="btn btn-default btn-sm" type="button" data-toggle="offcanvas">Toggle nav</button>
|
||||
</p>
|
||||
<ol class="breadcrumb">
|
||||
<li class="sitename">
|
||||
<a href="../../../index.html">Home</a>
|
||||
</li>
|
||||
<li class="hidden-xs active">
|
||||
<a href="../../en-US/index.html">Defensive Coding Guide </a>
|
||||
</li>
|
||||
<li class="hidden-xs active">
|
||||
<a href="../../en-US/index.html">Defensive Coding Guide</a>
|
||||
</li>
|
||||
<li class="hidden-xs active"><a href="../../en-US/tasks/Tasks-Library_Design.html">Specific Programming Tasks</a></li>
|
||||
<li class="hidden-xs active">
|
||||
RPM Packaging
|
||||
</li>
|
||||
</ol>
|
||||
<div class="row row-offcanvas row-offcanvas-left">
|
||||
<div class="col-xs-8 col-sm-3 col-md-3 sidebar sidebar-offcanvas">
|
||||
<ul class="nav nav-sidebar">
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicGroup0">
|
||||
<span id="tgSpan0" class="fa fa-angle-down"></span>Defensive Coding Guide
|
||||
</a>
|
||||
<ul id="topicGroup0" class="collapse in list-unstyled">
|
||||
<li><a class="" href="../../en-US/index.html">Book Information</a></li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-1">
|
||||
<span id="sgSpan-0-1" class="fa fa-caret-right"></span> Programming Languages
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-1" class="nav-tertiary list-unstyled collapse">
|
||||
<li><a class="" href="../../en-US/programming-languages/C.html">The C Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/CXX.html">The C++ Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Java.html">The Java Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Python.html">The Python Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Shell.html">Shell Programming and bash</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Go.html">The Go Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Vala.html">The Vala Programming Language</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-2">
|
||||
<span id="sgSpan-0-2" class="fa fa-caret-down"></span> Specific Programming Tasks
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-2" class="nav-tertiary list-unstyled collapse in">
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Library_Design.html">Library Design</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Descriptors.html">File Descriptor Management</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-File_System.html">File System Manipulation</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Temporary_Files.html">Temporary Files</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Processes.html">Processes</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Serialization.html">Serialization and Deserialization</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Cryptography.html">Cryptography</a></li>
|
||||
<li><a class=" active" href="../../en-US/tasks/Tasks-Packaging.html">RPM Packaging</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-3">
|
||||
<span id="sgSpan-0-3" class="fa fa-caret-right"></span> Implementing Security Features
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-3" class="nav-tertiary list-unstyled collapse">
|
||||
<li><a class="" href="../../en-US/features/Features-Authentication.html">Authentication and Authorization</a></li>
|
||||
<li><a class="" href="../../en-US/features/Features-TLS.html">Transport Layer Security (TLS)</a></li>
|
||||
<li><a class="" href="../../en-US/features/Features-HSM.html">Hardware Security Modules and Smart Cards</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="" href="../../en-US/Revision_History.html">Revision History</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-9 col-md-9 main">
|
||||
<div class="page-header">
|
||||
<h2>RPM Packaging</h2>
|
||||
</div>
|
||||
<div id="preamble">
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>This chapter deals with security-related concerns around RPM
|
||||
packaging. It has to be read in conjunction with
|
||||
distribution-specific packaging guidelines.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="sect-Defensive_Coding-Tasks-Packaging-Certificates"><a class="anchor" href="#sect-Defensive_Coding-Tasks-Packaging-Certificates"></a>Generating X.509 Self-signed Certificates during Installation</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>Some applications need X.509 certificates for authentication
|
||||
purposes. For example, a single private/public key pair could
|
||||
be used to define cluster membership, enabling authentication
|
||||
and encryption of all intra-cluster communication. (Lack of
|
||||
certification from a CA matters less in such a context.) For
|
||||
such use, generating the key pair at package installation time
|
||||
when preparing system images for use in the cluster is
|
||||
reasonable. For other use cases, it is necessary to generate
|
||||
the key pair before the service is started for the first time,
|
||||
see <a href="#sect-Defensive_Coding-Tasks-Packaging-Certificates-Service">Generating X.509 Self-signed Certificates before Service Start</a>,
|
||||
and <a href="https://fedoraproject.org/wiki/Packaging:Initial_Service_Setup#Generating_Self-Signed_Certificates">Packaging:Initial Service Setup</a>.</p>
|
||||
</div>
|
||||
<div class="admonitionblock important">
|
||||
<table>
|
||||
<tr>
|
||||
<td class="icon">
|
||||
<i class="fa icon-important" title="Important"></i>
|
||||
</td>
|
||||
<td class="content">
|
||||
<div class="paragraph">
|
||||
<p>The way the key is generated may not be suitable for key
|
||||
material of critical value. (<code class="command">openssl
|
||||
genrsa</code> uses, but does not require, entropy from a
|
||||
physical source of randomness, among other things.) Such keys
|
||||
should be stored in a hardware security module if possible,
|
||||
and generated from random bits reserved for this purpose
|
||||
derived from a non-deterministic physical source.</p>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>In the spec file, we define two RPM variables which contain the
|
||||
names of the files used to store the private and public key, and
|
||||
the user name for the service:</p>
|
||||
</div>
|
||||
<div class="listingblock">
|
||||
<div class="content">
|
||||
<pre class="CodeRay highlight"><code data-lang="bash"># Name of the user owning the file with the private key
|
||||
%define tlsuser %{name}
|
||||
# Name of the directory which contains the key and certificate files
|
||||
%define tlsdir %{_sysconfdir}/%{name}
|
||||
%define tlskey %{tlsdir}/%{name}.key
|
||||
%define tlscert %{tlsdir}/%{name}.crt</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>These variables likely need adjustment based on the needs of the
|
||||
package.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Typically, the file with the private key needs to be owned by
|
||||
the system user which needs to read it,
|
||||
<code>%{tlsuser}</code> (not <code>root</code>). In
|
||||
order to avoid races, if the <strong>directory</strong>
|
||||
<code>%{tlsdir}</code> is <strong>owned by the services
|
||||
user</strong>, you should use the code in <a href="#ex-Defensive_Coding-Packaging-Certificates-Owned">Creating a key pair in a user-owned directory</a>.
|
||||
The invocation of <strong class="application">su</strong> with the
|
||||
<code class="option">-s /bin/bash</code> argument is necessary in case the
|
||||
login shell for the user has been disabled.</p>
|
||||
</div>
|
||||
<div id="ex-Defensive_Coding-Packaging-Certificates-Owned" class="exampleblock">
|
||||
<div class="title">Example 1. Creating a key pair in a user-owned directory</div>
|
||||
<div class="content">
|
||||
<div class="listingblock">
|
||||
<div class="content">
|
||||
<pre class="CodeRay highlight"><code data-lang="bash">%post
|
||||
if [ $1 -eq 1 ] ; then
|
||||
if ! test -e %{tlskey} ; then
|
||||
su -s /bin/bash \
|
||||
-c "umask 077 && openssl genrsa -out %{tlskey} 2048 2>/dev/null" \
|
||||
%{tlsuser}
|
||||
fi
|
||||
if ! test -e %{tlscert} ; then
|
||||
cn="Automatically generated certificate for the %{tlsuser} service"
|
||||
req_args="-key %{tlskey} -out %{tlscert} -days 7305 -subj \"/CN=$cn/\""
|
||||
su -s /bin/bash \
|
||||
-c "openssl req -new -x509 -extensions usr_cert $req_args" \
|
||||
%{tlsuser}
|
||||
fi
|
||||
fi
|
||||
|
||||
%files
|
||||
%dir %attr(0755,%{tlsuser},%{tlsuser]) %{tlsdir}
|
||||
%ghost %attr(0600,%{tlsuser},%{tlsuser}) %config(noreplace) %{tlskey}
|
||||
%ghost %attr(0644,%{tlsuser},%{tlsuser}) %config(noreplace) %{tlscert}</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>The files containing the key material are marked as ghost
|
||||
configuration files. This ensures that they are tracked in the
|
||||
RPM database as associated with the package, but RPM will not
|
||||
create them when the package is installed and not verify their
|
||||
contents (the <code>%ghost</code>), or delete the files
|
||||
when the package is uninstalled (the
|
||||
<code>%config(noreplace)</code> part).</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>If the <strong>directory</strong>
|
||||
<code>%{tlsdir}</code> <strong>is owned by</strong>
|
||||
<code>root</code>, use the code in <a href="#ex-Defensive_Coding-Packaging-Certificates-Unowned">Creating a key pair in a <code>root</code>-owned directory</a>.</p>
|
||||
</div>
|
||||
<div id="ex-Defensive_Coding-Packaging-Certificates-Unowned" class="exampleblock">
|
||||
<div class="title">Example 2. Creating a key pair in a <code>root</code>-owned directory</div>
|
||||
<div class="content">
|
||||
<div class="listingblock">
|
||||
<div class="content">
|
||||
<pre class="CodeRay highlight"><code data-lang="bash">%post
|
||||
if [ $1 -eq 1 ] ; then
|
||||
if ! test -e %{tlskey} ; then
|
||||
(umask 077 && openssl genrsa -out %{tlskey} 2048 2>/dev/null)
|
||||
chown %{tlsuser} %{tlskey}
|
||||
fi
|
||||
if ! test -e %{tlscert} ; then
|
||||
cn="Automatically generated certificate for the %{tlsuser} service"
|
||||
openssl req -new -x509 -extensions usr_cert \
|
||||
-key %{tlskey} -out %{tlscert} -days 7305 -subj "/CN=$cn/"
|
||||
fi
|
||||
fi
|
||||
|
||||
%files
|
||||
%dir %attr(0755,root,root]) %{tlsdir}
|
||||
%ghost %attr(0600,%{tlsuser},%{tlsuser}) %config(noreplace) %{tlskey}
|
||||
%ghost %attr(0644,root,root) %config(noreplace) %{tlscert}</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>In order for this to work, the package which generates the keys
|
||||
must require the <strong class="application">openssl</strong> package. If
|
||||
the user which owns the key file is generated by a different
|
||||
package, the package generating the certificate must specify a
|
||||
<code>Requires(pre):</code> on the package which creates
|
||||
the user. This ensures that the user account will exist when it
|
||||
is needed for the <strong class="application">su</strong> or
|
||||
<strong class="application">chmod</strong> invocation.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="sect-Defensive_Coding-Tasks-Packaging-Certificates-Service"><a class="anchor" href="#sect-Defensive_Coding-Tasks-Packaging-Certificates-Service"></a>Generating X.509 Self-signed Certificates before Service Start</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>An alternative way to automatically provide an X.509 key pair is
|
||||
to create it just before the service is started for the first
|
||||
time. This ensures that installation images which are created
|
||||
from installed RPM packages receive different key material.
|
||||
Creating the key pair at package installation time (see <a href="#sect-Defensive_Coding-Tasks-Packaging-Certificates">Generating X.509 Self-signed Certificates during Installation</a>)
|
||||
would put the key into the image, which may or may not make
|
||||
sense.</p>
|
||||
</div>
|
||||
<div class="admonitionblock important">
|
||||
<table>
|
||||
<tr>
|
||||
<td class="icon">
|
||||
<i class="fa icon-important" title="Important"></i>
|
||||
</td>
|
||||
<td class="content">
|
||||
<div class="paragraph">
|
||||
<p>The caveats about the way the key is generated in <a href="#sect-Defensive_Coding-Tasks-Packaging-Certificates">Generating X.509 Self-signed Certificates during Installation</a>
|
||||
apply to this procedure as well.</p>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Generating key material before service start may happen very
|
||||
early during boot, when the kernel randomness pool has not yet
|
||||
been initialized. Currently, the only way to check for the
|
||||
initialization is to look for the kernel message
|
||||
<code>random: nonblocking pool is initialized</code>, or
|
||||
ensure that the application used for generating the keys
|
||||
is utilizing the <code>getrandom()</code> system call.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>In theory, it is also possible to use an application which reads from
|
||||
<code>/dev/random</code> while generating the key
|
||||
material (instead of <code>/dev/urandom</code>), but
|
||||
this can block not just during the boot process, but also much
|
||||
later at run time, and generally results in a poor user
|
||||
experience.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>The requirements for generating such keys is documented at
|
||||
<a href="https://fedoraproject.org/wiki/Packaging:Initial_Service_Setup#Generating_Self-Signed_Certificates">Packaging:Initial Service Setup</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="bottom" class="text-muted py-3" >
|
||||
<div class="foot">
|
||||
<div class="container">
|
||||
<div class="row footerlinks">
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">About</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Overview">About Fedora</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/sponsors">Sponsors</a></dd>
|
||||
<dd><a href="https://fedoramagazine.org">Fedora Magazine</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Legal:Main#Legal">Legal</a></dd>
|
||||
</dl>
|
||||
<ul class="list-inline">
|
||||
<li>
|
||||
<a href="https://www.facebook.com/TheFedoraProject" class="btn-social btn-outline"><i class="fa fa-fw fa-facebook"></i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://plus.google.com/112917221531140868607" class="btn-social btn-outline"><i class="fa fa-fw fa-google-plus"></i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://twitter.com/fedora" class="btn-social btn-outline"><i class="fa fa-fw fa-twitter"></i></a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title uppercase">Download</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://getfedora.org/en/workstation/download">Get Fedora Workstation</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/server/download">Get Fedora Server</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/atomic/download">Get Fedora Atomic</a></dd>
|
||||
<dd><a href="https://spins.fedoraproject.org">Fedora Spins</a></dd>
|
||||
<dd><a href="https://labs.fedoraproject.org">Fedora Labs</a></dd>
|
||||
<dd><a href="https://arm.fedoraproject.org">Fedora ARM<span class="sup">®</span></a></dd>
|
||||
<dd><a href="https://alt.fedoraproject.org/">Alternative Downloads</a></dd>
|
||||
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">Support</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Communicating_and_getting_help">Get Help</a></dd>
|
||||
<dd><a href="https://ask.fedoraproject.org/">Ask Fedora</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Common_F27_bugs">Common Bugs</a></dd>
|
||||
<dd><a href="https://developer.fedoraproject.org/">Fedora Developer Portal</a></dd>
|
||||
<dd><a href="https://docs.fedoraproject.org/f27/install-guide/index.html">Installation Guide</a></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">Join</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Join">Join Fedora</a></dd>
|
||||
<dd><a href="http://fedoraplanet.org">Planet Fedora</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/SIGs">Fedora SIGs</a></dd>
|
||||
<dd><a href="https://admin.fedoraproject.org/accounts/">Fedora Account System</a></dd>
|
||||
<dd><a href="https://fedoracommunity.org/">Fedora Community</a></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- /row of widgets -->
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-2">
|
||||
<div class="widget-body">
|
||||
<a href="https://www.redhat.com/"><img class="rh-logo" src="../../../master/_images/redhat-logo.png" alt="Red Hat Logo" /></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-7">
|
||||
<div class="widget-body">
|
||||
<p class="sponsor">Fedora is sponsored by Red Hat.</p>
|
||||
<p class="sponsor"><a href="https://www.redhat.com/en/technologies/linux-platforms/articles/relationship-between-fedora-and-rhel">Learn more about the relationship between Red Hat and Fedora »</a></p>
|
||||
<p class="copy">© 2017 Red Hat, Inc. and others. Please send any comments or corrections to the <a href="https://pagure.io/fedora-docs/docs-fp-o">documentation team</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- /row of widgets -->
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
|
||||
<!-- Latest compiled and minified JavaScript -->
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
|
||||
<script src="../../../master/_javascripts/bootstrap-offcanvas.js" type="text/javascript"></script>
|
||||
<script type="text/javascript">
|
||||
/*<![CDATA[*/
|
||||
$(document).ready(function() {
|
||||
$("[id^='topicGroup']").on('show.bs.collapse', function (event) {
|
||||
if (!($(event.target).attr('id').match(/^topicSubGroup/))) {
|
||||
$(this).parent().find("[id^='tgSpan']").toggleClass("fa-angle-right fa-angle-down");
|
||||
}
|
||||
});
|
||||
$("[id^='topicGroup']").on('hide.bs.collapse', function (event) {
|
||||
if (!($(event.target).attr('id').match(/^topicSubGroup/))) {
|
||||
$(this).parent().find("[id^='tgSpan']").toggleClass("fa-angle-right fa-angle-down");
|
||||
}
|
||||
});
|
||||
$("[id^='topicSubGroup']").on('show.bs.collapse', function () {
|
||||
$(this).parent().find("[id^='sgSpan']").toggleClass("fa-caret-right fa-caret-down");
|
||||
});
|
||||
$("[id^='topicSubGroup']").on('hide.bs.collapse', function () {
|
||||
$(this).parent().find("[id^='sgSpan']").toggleClass("fa-caret-right fa-caret-down");
|
||||
});
|
||||
});
|
||||
/*]]>*/
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -1,702 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta content="IE=edge" http-equiv="X-UA-Compatible">
|
||||
<meta content="width=device-width, initial-scale=1.0" name="viewport">
|
||||
<title>Defensive Coding Guide | Defensive Coding Guide | Specific Programming Tasks | Processes</title>
|
||||
|
||||
<!-- Bootstrap -->
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap-theme.min.css">
|
||||
|
||||
<!-- Overpass Font -->
|
||||
<link rel="stylesheet" href="https://overpass-30e2.kxcdn.com/overpass.css">
|
||||
|
||||
<link href="../../../master/_stylesheets/asciibinder.css" rel="stylesheet" />
|
||||
|
||||
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
|
||||
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
|
||||
<!--[if lt IE 9]>
|
||||
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
|
||||
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
|
||||
<![endif]-->
|
||||
|
||||
<link href="../../../master/_images/favicon32x32.png" rel="shortcut icon" type="text/css">
|
||||
<!--[if IE]><link rel="shortcut icon" href="../../../master/_images/favicon.ico"><![endif]-->
|
||||
<meta content="AsciiBinder" name="application-name">
|
||||
</head>
|
||||
<body>
|
||||
<div class="navbar navbar-default" role="navigation">
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-header">
|
||||
<a class="navbar-brand" href="https://docs.fedoraproject.org/"><img alt="Fedora Documentation" src="../../../master/_images/fedora.svg"></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container">
|
||||
<p class="toggle-nav visible-xs pull-left">
|
||||
<button class="btn btn-default btn-sm" type="button" data-toggle="offcanvas">Toggle nav</button>
|
||||
</p>
|
||||
<ol class="breadcrumb">
|
||||
<li class="sitename">
|
||||
<a href="../../../index.html">Home</a>
|
||||
</li>
|
||||
<li class="hidden-xs active">
|
||||
<a href="../../en-US/index.html">Defensive Coding Guide </a>
|
||||
</li>
|
||||
<li class="hidden-xs active">
|
||||
<a href="../../en-US/index.html">Defensive Coding Guide</a>
|
||||
</li>
|
||||
<li class="hidden-xs active"><a href="../../en-US/tasks/Tasks-Library_Design.html">Specific Programming Tasks</a></li>
|
||||
<li class="hidden-xs active">
|
||||
Processes
|
||||
</li>
|
||||
</ol>
|
||||
<div class="row row-offcanvas row-offcanvas-left">
|
||||
<div class="col-xs-8 col-sm-3 col-md-3 sidebar sidebar-offcanvas">
|
||||
<ul class="nav nav-sidebar">
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicGroup0">
|
||||
<span id="tgSpan0" class="fa fa-angle-down"></span>Defensive Coding Guide
|
||||
</a>
|
||||
<ul id="topicGroup0" class="collapse in list-unstyled">
|
||||
<li><a class="" href="../../en-US/index.html">Book Information</a></li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-1">
|
||||
<span id="sgSpan-0-1" class="fa fa-caret-right"></span> Programming Languages
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-1" class="nav-tertiary list-unstyled collapse">
|
||||
<li><a class="" href="../../en-US/programming-languages/C.html">The C Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/CXX.html">The C++ Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Java.html">The Java Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Python.html">The Python Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Shell.html">Shell Programming and bash</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Go.html">The Go Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Vala.html">The Vala Programming Language</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-2">
|
||||
<span id="sgSpan-0-2" class="fa fa-caret-down"></span> Specific Programming Tasks
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-2" class="nav-tertiary list-unstyled collapse in">
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Library_Design.html">Library Design</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Descriptors.html">File Descriptor Management</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-File_System.html">File System Manipulation</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Temporary_Files.html">Temporary Files</a></li>
|
||||
<li><a class=" active" href="../../en-US/tasks/Tasks-Processes.html">Processes</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Serialization.html">Serialization and Deserialization</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Cryptography.html">Cryptography</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Packaging.html">RPM Packaging</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-3">
|
||||
<span id="sgSpan-0-3" class="fa fa-caret-right"></span> Implementing Security Features
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-3" class="nav-tertiary list-unstyled collapse">
|
||||
<li><a class="" href="../../en-US/features/Features-Authentication.html">Authentication and Authorization</a></li>
|
||||
<li><a class="" href="../../en-US/features/Features-TLS.html">Transport Layer Security (TLS)</a></li>
|
||||
<li><a class="" href="../../en-US/features/Features-HSM.html">Hardware Security Modules and Smart Cards</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="" href="../../en-US/Revision_History.html">Revision History</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-9 col-md-9 main">
|
||||
<div class="page-header">
|
||||
<h2>Processes</h2>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="sect-Defensive_Coding-Tasks-Processes-Creation"><a class="anchor" href="#sect-Defensive_Coding-Tasks-Processes-Creation"></a>Creating Safe Processes</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>This section describes how to create new child processes in a
|
||||
safe manner. In addition to the concerns addressed below, there
|
||||
is the possibility of file descriptor leaks, see <a href="#sect-Defensive_Coding-Tasks-Descriptors-Child_Processes">[sect-Defensive_Coding-Tasks-Descriptors-Child_Processes]</a>.</p>
|
||||
</div>
|
||||
<div class="sect2">
|
||||
<h3 id="obtaining-the-program-path-and-the-command-line-template"><a class="anchor" href="#obtaining-the-program-path-and-the-command-line-template"></a>Obtaining the Program Path and the Command-line Template</h3>
|
||||
<div class="paragraph">
|
||||
<p>The name and path to the program being invoked should be
|
||||
hard-coded or controlled by a static configuration file stored
|
||||
at a fixed location (at an file system absolute path). The
|
||||
same applies to the template for generating the command line.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>The configured program name should be an absolute path. If it
|
||||
is a relative path, the contents of the <code>PATH</code>
|
||||
must be obtained in a secure manner (see <a href="#sect-Defensive_Coding-Tasks-secure_getenv">Accessing Environment Variables</a>).
|
||||
If the <code>PATH</code> variable is not set or untrusted,
|
||||
the safe default <code>/bin:/usr/bin</code> must be
|
||||
used.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>If too much flexibility is provided here, it may allow
|
||||
invocation of arbitrary programs without proper authorization.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect2">
|
||||
<h3 id="sect-Defensive_Coding-Tasks-Processes-execve"><a class="anchor" href="#sect-Defensive_Coding-Tasks-Processes-execve"></a>Bypassing the Shell</h3>
|
||||
<div class="paragraph">
|
||||
<p>Child processes should be created without involving the system
|
||||
shell.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>For C/C++, <code>system</code> should not be used.
|
||||
The <code>posix_spawn</code> function can be used
|
||||
instead, or a combination <code>fork</code> and
|
||||
<code>execve</code>. (In some cases, it may be
|
||||
preferable to use <code>vfork</code> or the
|
||||
Linux-specific <code>clone</code> system call instead
|
||||
of <code>fork</code>.)</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>In Python, the <code>subprocess</code> module bypasses
|
||||
the shell by default (when the <code>shell</code>
|
||||
keyword argument is not set to true).
|
||||
<code>os.system</code> should not be used.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>The Java class <code>java.lang.ProcessBuilder</code> can be
|
||||
used to create subprocesses without interference from the
|
||||
system shell.</p>
|
||||
</div>
|
||||
<div class="admonitionblock important">
|
||||
<table>
|
||||
<tr>
|
||||
<td class="icon">
|
||||
<i class="fa icon-important" title="Important"></i>
|
||||
</td>
|
||||
<td class="content">
|
||||
<div class="title">Portability notice</div>
|
||||
<div class="paragraph">
|
||||
<p>On Windows, there is no argument vector, only a single
|
||||
argument string. Each application is responsible for parsing
|
||||
this string into an argument vector. There is considerable
|
||||
variance among the quoting style recognized by applications.
|
||||
Some of them expand shell wildcards, others do not. Extensive
|
||||
application-specific testing is required to make this secure.</p>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Note that some common applications (notably
|
||||
<strong class="application">ssh</strong>) unconditionally introduce the
|
||||
use of a shell, even if invoked directly without a shell. It is
|
||||
difficult to use these applications in a secure manner. In this
|
||||
case, untrusted data should be supplied by other means. For
|
||||
example, standard input could be used, instead of the command
|
||||
line.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect2">
|
||||
<h3 id="sect-Defensive_Coding-Tasks-Processes-environ"><a class="anchor" href="#sect-Defensive_Coding-Tasks-Processes-environ"></a>Specifying the Process Environment</h3>
|
||||
<div class="paragraph">
|
||||
<p>Child processes should be created with a minimal set of
|
||||
environment variables. This is absolutely essential if there
|
||||
is a trust transition involved, either when the parent process
|
||||
was created, or during the creation of the child process.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>In C/C++, the environment should be constructed as an array of
|
||||
strings and passed as the <code>envp</code> argument to
|
||||
<code>posix_spawn</code> or <code>execve</code>.
|
||||
The functions <code>setenv</code>,
|
||||
<code>unsetenv</code> and <code>putenv</code>
|
||||
should not be used. They are not thread-safe and suffer from
|
||||
memory leaks.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Python programs need to specify a <code>dict</code> for
|
||||
the the <code>env</code> argument of the
|
||||
<code>subprocess.Popen</code> constructor.
|
||||
The Java class <code>java.lang.ProcessBuilder</code>
|
||||
provides a <code>environment()</code> method,
|
||||
which returns a map that can be manipulated.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>The following list provides guidelines for selecting the set
|
||||
of environment variables passed to the child process.</p>
|
||||
</div>
|
||||
<div class="ulist">
|
||||
<ul>
|
||||
<li>
|
||||
<p><code>PATH</code> should be initialized to
|
||||
<code>/bin:/usr/bin</code>.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><code>USER</code> and <code>HOME</code> can be inhereted
|
||||
from the parent process environment, or they can be
|
||||
initialized from the <code>pwent</code> structure
|
||||
for the user.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>The <code>DISPLAY</code> and <code>XAUTHORITY</code>
|
||||
variables should be passed to the subprocess if it is an X
|
||||
program. Note that this will typically not work across trust
|
||||
boundaries because <code>XAUTHORITY</code> refers to a file
|
||||
with <code>0600</code> permissions.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>The location-related environment variables
|
||||
<code>LANG</code>, <code>LANGUAGE</code>,
|
||||
<code>LC_ADDRESS</code>, <code>LC_ALL</code>,
|
||||
<code>LC_COLLATE</code>, <code>LC_CTYPE</code>,
|
||||
<code>LC_IDENTIFICATION</code>,
|
||||
<code>LC_MEASUREMENT</code>, <code>LC_MESSAGES</code>,
|
||||
<code>LC_MONETARY</code>, <code>LC_NAME</code>,
|
||||
<code>LC_NUMERIC</code>, <code>LC_PAPER</code>,
|
||||
<code>LC_TELEPHONE</code> and <code>LC_TIME</code>
|
||||
can be passed to the subprocess if present.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>The called process may need application-specific
|
||||
environment variables, for example for passing passwords.
|
||||
(See <a href="#sect-Defensive_Coding-Tasks-Processes-Command_Line_Visibility">Passing Secrets to Subprocesses</a>.)</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>All other environment variables should be dropped. Names
|
||||
for new environment variables should not be accepted from
|
||||
untrusted sources.</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect2">
|
||||
<h3 id="robust-argument-list-processing"><a class="anchor" href="#robust-argument-list-processing"></a>Robust Argument List Processing</h3>
|
||||
<div class="paragraph">
|
||||
<p>When invoking a program, it is sometimes necessary to include
|
||||
data from untrusted sources. Such data should be checked
|
||||
against embedded <code>NUL</code> characters because the
|
||||
system APIs will silently truncate argument strings at the first
|
||||
<code>NUL</code> character.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>The following recommendations assume that the program being
|
||||
invoked uses GNU-style option processing using
|
||||
<code>getopt_long</code>. This convention is widely
|
||||
used, but it is just that, and individual programs might
|
||||
interpret a command line in a different way.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>If the untrusted data has to go into an option, use the
|
||||
<code>--option-name=VALUE</code> syntax, placing the
|
||||
option and its value into the same command line argument.
|
||||
This avoids any potential confusion if the data starts with
|
||||
<code>-</code>.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>For positional arguments, terminate the option list with a
|
||||
single <code class="option">--</code> marker after the last option, and
|
||||
include the data at the right position. The
|
||||
<code class="option">--</code> marker terminates option processing, and
|
||||
the data will not be treated as an option even if it starts
|
||||
with a dash.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect2">
|
||||
<h3 id="sect-Defensive_Coding-Tasks-Processes-Command_Line_Visibility"><a class="anchor" href="#sect-Defensive_Coding-Tasks-Processes-Command_Line_Visibility"></a>Passing Secrets to Subprocesses</h3>
|
||||
<div class="paragraph">
|
||||
<p>The command line (the name of the program and its argument) of
|
||||
a running process is traditionally available to all local
|
||||
users. The called program can overwrite this information, but
|
||||
only after it has run for a bit of time, during which the
|
||||
information may have been read by other processes. However,
|
||||
on Linux, the process environment is restricted to the user
|
||||
who runs the process. Therefore, if you need a convenient way
|
||||
to pass a password to a child process, use an environment
|
||||
variable, and not a command line argument. (See <a href="#sect-Defensive_Coding-Tasks-Processes-environ">Specifying the Process Environment</a>.)</p>
|
||||
</div>
|
||||
<div class="admonitionblock important">
|
||||
<table>
|
||||
<tr>
|
||||
<td class="icon">
|
||||
<i class="fa icon-important" title="Important"></i>
|
||||
</td>
|
||||
<td class="content">
|
||||
<div class="title">Portability notice</div>
|
||||
<div class="paragraph">
|
||||
<p>On some UNIX-like systems (notably Solaris), environment
|
||||
variables can be read by any system user, just like command
|
||||
lines.</p>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>If the environment-based approach cannot be used due to
|
||||
portability concerns, the data can be passed on standard
|
||||
input. Some programs (notably <strong class="application">gpg</strong>)
|
||||
use special file descriptors whose numbers are specified on
|
||||
the command line. Temporary files are an option as well, but
|
||||
they might give digital forensics access to sensitive data
|
||||
(such as passphrases) because it is difficult to safely delete
|
||||
them in all cases.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="handling-child-process-termination"><a class="anchor" href="#handling-child-process-termination"></a>Handling Child Process Termination</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>When child processes terminate, the parent process is signalled.
|
||||
A stub of the terminated processes (a
|
||||
<strong>zombie</strong>, shown as
|
||||
<code><defunct></code> by
|
||||
<strong class="application">ps</strong>) is kept around until the status
|
||||
information is collected (<strong>reaped</strong>) by the
|
||||
parent process. Over the years, several interfaces for this
|
||||
have been invented:</p>
|
||||
</div>
|
||||
<div class="ulist">
|
||||
<ul>
|
||||
<li>
|
||||
<p>The parent process calls <code>wait</code>,
|
||||
<code>waitpid</code>, <code>waitid</code>,
|
||||
<code>wait3</code> or <code>wait4</code>,
|
||||
without specifying a process ID. This will deliver any
|
||||
matching process ID. This approach is typically used from
|
||||
within event loops.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>The parent process calls <code>waitpid</code>,
|
||||
<code>waitid</code>, or <code>wait4</code>,
|
||||
with a specific process ID. Only data for the specific
|
||||
process ID is returned. This is typically used in code
|
||||
which spawns a single subprocess in a synchronous manner.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>The parent process installs a handler for the
|
||||
<code>SIGCHLD</code> signal, using
|
||||
<code>sigaction</code>, and specifies to the
|
||||
<code>SA_NOCLDWAIT</code> flag.
|
||||
This approach could be used by event loops as well.</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>None of these approaches can be used to wait for child process
|
||||
terminated in a completely thread-safe manner. The parent
|
||||
process might execute an event loop in another thread, which
|
||||
could pick up the termination signal. This means that libraries
|
||||
typically cannot make free use of child processes (for example,
|
||||
to run problematic code with reduced privileges in a separate
|
||||
address space).</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>At the moment, the parent process should explicitly wait for
|
||||
termination of the child process using
|
||||
<code>waitpid</code> or <code>waitid</code>,
|
||||
and hope that the status is not collected by an event loop
|
||||
first.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="code-suid-code-code-sgid-code-processes"><a class="anchor" href="#code-suid-code-code-sgid-code-processes"></a><code>SUID</code>/<code>SGID</code> processes</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>Programs can be marked in the file system to indicate to the
|
||||
kernel that a trust transition should happen if the program is
|
||||
run. The <code>SUID</code> file permission bit indicates
|
||||
that an executable should run with the effective user ID equal
|
||||
to the owner of the executable file. Similarly, with the
|
||||
<code>SGID</code> bit, the effective group ID is set to
|
||||
the group of the executable file.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Linux supports <strong>fscaps</strong>, which can grant
|
||||
additional capabilities to a process in a finer-grained manner.
|
||||
Additional mechanisms can be provided by loadable security
|
||||
modules.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>When such a trust transition has happened, the process runs in a
|
||||
potentially hostile environment. Additional care is necessary
|
||||
not to rely on any untrusted information. These concerns also
|
||||
apply to libraries which can be linked into such processes.</p>
|
||||
</div>
|
||||
<div class="sect2">
|
||||
<h3 id="sect-Defensive_Coding-Tasks-secure_getenv"><a class="anchor" href="#sect-Defensive_Coding-Tasks-secure_getenv"></a>Accessing Environment Variables</h3>
|
||||
<div class="paragraph">
|
||||
<p>The following steps are required so that a program does not
|
||||
accidentally pick up untrusted data from environment
|
||||
variables.</p>
|
||||
</div>
|
||||
<div class="ulist">
|
||||
<ul>
|
||||
<li>
|
||||
<p>Compile your C/C++ sources with <code>-D_GNU_SOURCE</code>.
|
||||
The Autoconf macro <code>AC_GNU_SOURCE</code> ensures this.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Check for the presence of the <code>secure_getenv</code>
|
||||
and <code><em>secure_getenv</code> function. The Autoconf
|
||||
directive <code>AC_CHECK_FUNCS([</em>secure_getenv secure_getenv])</code>
|
||||
performs these checks.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Arrange for a proper definition of the
|
||||
<code>secure_getenv</code> function. See <a href="#ex-Defensive_Coding-Tasks-secure_getenv">Obtaining a definition for <code>secure_getenv</code></a>.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Use <code>secure_getenv</code> instead of
|
||||
<code>getenv</code> to obtain the value of critical
|
||||
environment variables. <code>secure_getenv</code>
|
||||
will pretend the variable has not bee set if the process
|
||||
environment is not trusted.</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Critical environment variables are debugging flags,
|
||||
configuration file locations, plug-in and log file locations,
|
||||
and anything else that might be used to bypass security
|
||||
restrictions or cause a privileged process to behave in an
|
||||
unexpected way.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Either the <code>secure_getenv</code> function or the
|
||||
<code>__secure_getenv</code> is available from GNU libc.</p>
|
||||
</div>
|
||||
<div id="ex-Defensive_Coding-Tasks-secure_getenv" class="exampleblock">
|
||||
<div class="title">Example 1. Obtaining a definition for <code>secure_getenv</code></div>
|
||||
<div class="content">
|
||||
<div class="listingblock">
|
||||
<div class="content">
|
||||
<pre class="CodeRay highlight"><code data-lang="c"><span style="color:#579">#include</span> <span style="color:#B44;font-weight:bold"><stdlib.h></span>
|
||||
|
||||
<span style="color:#579">#ifndef</span> HAVE_SECURE_GETENV
|
||||
<span style="color:#579"># ifdef</span> HAVE__SECURE_GETENV
|
||||
<span style="color:#579"># define</span> secure_getenv __secure_getenv
|
||||
<span style="color:#579"># else</span>
|
||||
<span style="color:#579"># error</span> neither secure_getenv nor __secure_getenv are available
|
||||
<span style="color:#579"># endif</span>
|
||||
<span style="color:#579">#endif</span></code></pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="sect-Defensive_Coding-Tasks-Processes-Daemons"><a class="anchor" href="#sect-Defensive_Coding-Tasks-Processes-Daemons"></a>Daemons</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>Background processes providing system services
|
||||
(<strong>daemons</strong>) need to decouple themselves from
|
||||
the controlling terminal and the parent process environment:</p>
|
||||
</div>
|
||||
<div class="ulist">
|
||||
<ul>
|
||||
<li>
|
||||
<p>Fork.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>In the child process, call <code>setsid</code>. The
|
||||
parent process can simply exit (using
|
||||
<code>_exit</code>, to avoid running clean-up
|
||||
actions twice).</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>In the child process, fork again. Processing continues in
|
||||
the child process. Again, the parent process should just
|
||||
exit.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Replace the descriptors 0, 1, 2 with a descriptor for
|
||||
<code>/dev/null</code>. Logging should be
|
||||
redirected to <strong class="application">syslog</strong>.</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Older instructions for creating daemon processes recommended a
|
||||
call to <code>umask(0)</code>. This is risky because it
|
||||
often leads to world-writable files and directories, resulting
|
||||
in security vulnerabilities such as arbitrary process
|
||||
termination by untrusted local users, or log file truncation.
|
||||
If the <strong>umask</strong> needs setting, a restrictive
|
||||
value such as <code>027</code> or <code>077</code>
|
||||
is recommended.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Other aspects of the process environment may have to changed as
|
||||
well (environment variables, signal handler disposition).</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>It is increasingly common that server processes do not run as
|
||||
background processes, but as regular foreground process under a
|
||||
supervising master process (such as
|
||||
<strong class="application">systemd</strong>). Server processes should
|
||||
offer a command line option which disables forking and
|
||||
replacement of the standard output and standard error streams.
|
||||
Such an option is also useful for debugging.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="semantics-of-command-line-arguments"><a class="anchor" href="#semantics-of-command-line-arguments"></a>Semantics of Command-line Arguments</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>After process creation and option processing, it is up to the
|
||||
child process to interpret the arguments. Arguments can be
|
||||
file names, host names, or URLs, and many other things. URLs
|
||||
can refer to the local network, some server on the Internet,
|
||||
or to the local file system. Some applications even accept
|
||||
arbitrary code in arguments (for example,
|
||||
<strong class="application">python</strong> with the
|
||||
<code class="option">-c</code> option).</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Similar concerns apply to environment variables, the contents
|
||||
of the current directory and its subdirectories.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Consequently, careful analysis is required if it is safe to
|
||||
pass untrusted data to another program.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="sect-Defensive_Coding-Tasks-Processes-Fork-Parallel"><a class="anchor" href="#sect-Defensive_Coding-Tasks-Processes-Fork-Parallel"></a><code>fork</code> as a Primitive for Parallelism</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>A call to <code>fork</code> which is not immediately
|
||||
followed by a call to <code>execve</code> (perhaps after
|
||||
rearranging and closing file descriptors) is typically unsafe,
|
||||
especially from a library which does not control the state of
|
||||
the entire process. Such use of <code>fork</code>
|
||||
should be replaced with proper child processes or threads.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="bottom" class="text-muted py-3" >
|
||||
<div class="foot">
|
||||
<div class="container">
|
||||
<div class="row footerlinks">
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">About</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Overview">About Fedora</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/sponsors">Sponsors</a></dd>
|
||||
<dd><a href="https://fedoramagazine.org">Fedora Magazine</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Legal:Main#Legal">Legal</a></dd>
|
||||
</dl>
|
||||
<ul class="list-inline">
|
||||
<li>
|
||||
<a href="https://www.facebook.com/TheFedoraProject" class="btn-social btn-outline"><i class="fa fa-fw fa-facebook"></i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://plus.google.com/112917221531140868607" class="btn-social btn-outline"><i class="fa fa-fw fa-google-plus"></i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://twitter.com/fedora" class="btn-social btn-outline"><i class="fa fa-fw fa-twitter"></i></a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title uppercase">Download</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://getfedora.org/en/workstation/download">Get Fedora Workstation</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/server/download">Get Fedora Server</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/atomic/download">Get Fedora Atomic</a></dd>
|
||||
<dd><a href="https://spins.fedoraproject.org">Fedora Spins</a></dd>
|
||||
<dd><a href="https://labs.fedoraproject.org">Fedora Labs</a></dd>
|
||||
<dd><a href="https://arm.fedoraproject.org">Fedora ARM<span class="sup">®</span></a></dd>
|
||||
<dd><a href="https://alt.fedoraproject.org/">Alternative Downloads</a></dd>
|
||||
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">Support</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Communicating_and_getting_help">Get Help</a></dd>
|
||||
<dd><a href="https://ask.fedoraproject.org/">Ask Fedora</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Common_F27_bugs">Common Bugs</a></dd>
|
||||
<dd><a href="https://developer.fedoraproject.org/">Fedora Developer Portal</a></dd>
|
||||
<dd><a href="https://docs.fedoraproject.org/f27/install-guide/index.html">Installation Guide</a></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">Join</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Join">Join Fedora</a></dd>
|
||||
<dd><a href="http://fedoraplanet.org">Planet Fedora</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/SIGs">Fedora SIGs</a></dd>
|
||||
<dd><a href="https://admin.fedoraproject.org/accounts/">Fedora Account System</a></dd>
|
||||
<dd><a href="https://fedoracommunity.org/">Fedora Community</a></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- /row of widgets -->
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-2">
|
||||
<div class="widget-body">
|
||||
<a href="https://www.redhat.com/"><img class="rh-logo" src="../../../master/_images/redhat-logo.png" alt="Red Hat Logo" /></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-7">
|
||||
<div class="widget-body">
|
||||
<p class="sponsor">Fedora is sponsored by Red Hat.</p>
|
||||
<p class="sponsor"><a href="https://www.redhat.com/en/technologies/linux-platforms/articles/relationship-between-fedora-and-rhel">Learn more about the relationship between Red Hat and Fedora »</a></p>
|
||||
<p class="copy">© 2017 Red Hat, Inc. and others. Please send any comments or corrections to the <a href="https://pagure.io/fedora-docs/docs-fp-o">documentation team</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- /row of widgets -->
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
|
||||
<!-- Latest compiled and minified JavaScript -->
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
|
||||
<script src="../../../master/_javascripts/bootstrap-offcanvas.js" type="text/javascript"></script>
|
||||
<script type="text/javascript">
|
||||
/*<![CDATA[*/
|
||||
$(document).ready(function() {
|
||||
$("[id^='topicGroup']").on('show.bs.collapse', function (event) {
|
||||
if (!($(event.target).attr('id').match(/^topicSubGroup/))) {
|
||||
$(this).parent().find("[id^='tgSpan']").toggleClass("fa-angle-right fa-angle-down");
|
||||
}
|
||||
});
|
||||
$("[id^='topicGroup']").on('hide.bs.collapse', function (event) {
|
||||
if (!($(event.target).attr('id').match(/^topicSubGroup/))) {
|
||||
$(this).parent().find("[id^='tgSpan']").toggleClass("fa-angle-right fa-angle-down");
|
||||
}
|
||||
});
|
||||
$("[id^='topicSubGroup']").on('show.bs.collapse', function () {
|
||||
$(this).parent().find("[id^='sgSpan']").toggleClass("fa-caret-right fa-caret-down");
|
||||
});
|
||||
$("[id^='topicSubGroup']").on('hide.bs.collapse', function () {
|
||||
$(this).parent().find("[id^='sgSpan']").toggleClass("fa-caret-right fa-caret-down");
|
||||
});
|
||||
});
|
||||
/*]]>*/
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -1,472 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta content="IE=edge" http-equiv="X-UA-Compatible">
|
||||
<meta content="width=device-width, initial-scale=1.0" name="viewport">
|
||||
<title>Defensive Coding Guide | Defensive Coding Guide | Specific Programming Tasks | Temporary Files</title>
|
||||
|
||||
<!-- Bootstrap -->
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap-theme.min.css">
|
||||
|
||||
<!-- Overpass Font -->
|
||||
<link rel="stylesheet" href="https://overpass-30e2.kxcdn.com/overpass.css">
|
||||
|
||||
<link href="../../../master/_stylesheets/asciibinder.css" rel="stylesheet" />
|
||||
|
||||
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
|
||||
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
|
||||
<!--[if lt IE 9]>
|
||||
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
|
||||
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
|
||||
<![endif]-->
|
||||
|
||||
<link href="../../../master/_images/favicon32x32.png" rel="shortcut icon" type="text/css">
|
||||
<!--[if IE]><link rel="shortcut icon" href="../../../master/_images/favicon.ico"><![endif]-->
|
||||
<meta content="AsciiBinder" name="application-name">
|
||||
</head>
|
||||
<body>
|
||||
<div class="navbar navbar-default" role="navigation">
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-header">
|
||||
<a class="navbar-brand" href="https://docs.fedoraproject.org/"><img alt="Fedora Documentation" src="../../../master/_images/fedora.svg"></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container">
|
||||
<p class="toggle-nav visible-xs pull-left">
|
||||
<button class="btn btn-default btn-sm" type="button" data-toggle="offcanvas">Toggle nav</button>
|
||||
</p>
|
||||
<ol class="breadcrumb">
|
||||
<li class="sitename">
|
||||
<a href="../../../index.html">Home</a>
|
||||
</li>
|
||||
<li class="hidden-xs active">
|
||||
<a href="../../en-US/index.html">Defensive Coding Guide </a>
|
||||
</li>
|
||||
<li class="hidden-xs active">
|
||||
<a href="../../en-US/index.html">Defensive Coding Guide</a>
|
||||
</li>
|
||||
<li class="hidden-xs active"><a href="../../en-US/tasks/Tasks-Library_Design.html">Specific Programming Tasks</a></li>
|
||||
<li class="hidden-xs active">
|
||||
Temporary Files
|
||||
</li>
|
||||
</ol>
|
||||
<div class="row row-offcanvas row-offcanvas-left">
|
||||
<div class="col-xs-8 col-sm-3 col-md-3 sidebar sidebar-offcanvas">
|
||||
<ul class="nav nav-sidebar">
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicGroup0">
|
||||
<span id="tgSpan0" class="fa fa-angle-down"></span>Defensive Coding Guide
|
||||
</a>
|
||||
<ul id="topicGroup0" class="collapse in list-unstyled">
|
||||
<li><a class="" href="../../en-US/index.html">Book Information</a></li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-1">
|
||||
<span id="sgSpan-0-1" class="fa fa-caret-right"></span> Programming Languages
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-1" class="nav-tertiary list-unstyled collapse">
|
||||
<li><a class="" href="../../en-US/programming-languages/C.html">The C Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/CXX.html">The C++ Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Java.html">The Java Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Python.html">The Python Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Shell.html">Shell Programming and bash</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Go.html">The Go Programming Language</a></li>
|
||||
<li><a class="" href="../../en-US/programming-languages/Vala.html">The Vala Programming Language</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-2">
|
||||
<span id="sgSpan-0-2" class="fa fa-caret-down"></span> Specific Programming Tasks
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-2" class="nav-tertiary list-unstyled collapse in">
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Library_Design.html">Library Design</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Descriptors.html">File Descriptor Management</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-File_System.html">File System Manipulation</a></li>
|
||||
<li><a class=" active" href="../../en-US/tasks/Tasks-Temporary_Files.html">Temporary Files</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Processes.html">Processes</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Serialization.html">Serialization and Deserialization</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Cryptography.html">Cryptography</a></li>
|
||||
<li><a class="" href="../../en-US/tasks/Tasks-Packaging.html">RPM Packaging</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-3">
|
||||
<span id="sgSpan-0-3" class="fa fa-caret-right"></span> Implementing Security Features
|
||||
</a>
|
||||
<ul id="topicSubGroup-0-3" class="nav-tertiary list-unstyled collapse">
|
||||
<li><a class="" href="../../en-US/features/Features-Authentication.html">Authentication and Authorization</a></li>
|
||||
<li><a class="" href="../../en-US/features/Features-TLS.html">Transport Layer Security (TLS)</a></li>
|
||||
<li><a class="" href="../../en-US/features/Features-HSM.html">Hardware Security Modules and Smart Cards</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="" href="../../en-US/Revision_History.html">Revision History</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-9 col-md-9 main">
|
||||
<div class="page-header">
|
||||
<h2>Temporary Files</h2>
|
||||
</div>
|
||||
<div id="preamble">
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>In this chapter, we describe how to create temporary files and
|
||||
directories, how to remove them, and how to work with programs
|
||||
which do not create files in ways that are safe with a shared
|
||||
directory for temporary files. General file system manipulation
|
||||
is treated in a separate chapter, <a href="#chap-Defensive_Coding-Tasks-File_System">[chap-Defensive_Coding-Tasks-File_System]</a>.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Secure creation of temporary files has four different aspects.</p>
|
||||
</div>
|
||||
<div class="ulist">
|
||||
<ul>
|
||||
<li>
|
||||
<p>The location of the directory for temporary files must be
|
||||
obtained in a secure manner (that is, untrusted environment
|
||||
variables must be ignored, see <a href="#sect-Defensive_Coding-Tasks-secure_getenv">[sect-Defensive_Coding-Tasks-secure_getenv]</a>).</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>A new file must be created. Reusing an existing file must be
|
||||
avoided (the <code>/tmp</code> race
|
||||
condition). This is tricky because traditionally, system-wide
|
||||
temporary directories shared by all users are used.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>The file must be created in a way that makes it impossible for
|
||||
other users to open it.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>The descriptor for the temporary file should not leak to
|
||||
subprocesses.</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>All functions mentioned below will take care of these aspects.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Traditionally, temporary files are often used to reduce memory
|
||||
usage of programs. More and more systems use RAM-based file
|
||||
systems such as <code>tmpfs</code> for storing temporary
|
||||
files, to increase performance and decrease wear on Flash storage.
|
||||
As a result, spooling data to temporary files does not result in
|
||||
any memory savings, and the related complexity can be avoided if
|
||||
the data is kept in process memory.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="chap-Defensive_Coding-Tasks-Temporary_Files-Location"><a class="anchor" href="#chap-Defensive_Coding-Tasks-Temporary_Files-Location"></a>Obtaining the Location of Temporary Directory</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>Some functions below need the location of a directory which
|
||||
stores temporary files. For C/C++ programs, use the following
|
||||
steps to obtain that directory:</p>
|
||||
</div>
|
||||
<div class="ulist">
|
||||
<ul>
|
||||
<li>
|
||||
<p>Use <code>secure_getenv</code> to obtain the value
|
||||
of the <code>TMPDIR</code> environment variable. If
|
||||
it is set, convert the path to a fully-resolved absolute
|
||||
path, using <code>realpath(path, NULL)</code>. Check
|
||||
if the new path refers to a directory and is writeable. In
|
||||
this case, use it as the temporary directory.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Fall back to <code>/tmp</code>.</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>In Python, you can use the <code>tempfile.tempdir</code>
|
||||
variable.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Java does not support SUID/SGID programs, so you can use the
|
||||
<code>java.lang.System.getenv(String)</code> method to
|
||||
obtain the value of the <code>TMPDIR</code> environment
|
||||
variable, and follow the two steps described above. (Java’s
|
||||
default directory selection does not honor
|
||||
<code>TMPDIR</code>.)</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="named-temporary-files"><a class="anchor" href="#named-temporary-files"></a>Named Temporary Files</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>The <code>mkostemp</code> function creates a named
|
||||
temporary file. You should specify the
|
||||
<code>O_CLOEXEC</code> flag to avoid file descriptor leaks
|
||||
to subprocesses. (Applications which do not use multiple threads
|
||||
can also use <code>mkstemp</code>, but libraries should
|
||||
use <code>mkostemp</code>.) For determining the
|
||||
directory part of the file name pattern, see <a href="#chap-Defensive_Coding-Tasks-Temporary_Files-Location">Obtaining the Location of Temporary Directory</a>.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>The file is not removed automatically. It is not safe to rename
|
||||
or delete the file before processing, or transform the name in
|
||||
any way (for example, by adding a file extension). If you need
|
||||
multiple temporary files, call <code>mkostemp</code>
|
||||
multiple times. Do not create additional file names derived
|
||||
from the name provided by a previous
|
||||
<code>mkostemp</code> call. However, it is safe to close
|
||||
the descriptor returned by <code>mkostemp</code> and
|
||||
reopen the file using the generated name.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>The Python class <code>tempfile.NamedTemporaryFile</code>
|
||||
provides similar functionality, except that the file is deleted
|
||||
automatically by default. Note that you may have to use the
|
||||
<code>file</code> attribute to obtain the actual file
|
||||
object because some programming interfaces cannot deal with
|
||||
file-like objects. The C function <code>mkostemp</code>
|
||||
is also available as <code>tempfile.mkstemp</code>.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>In Java, you can use the
|
||||
<code>java.io.File.createTempFile(String, String,
|
||||
File)</code> function, using the temporary file location
|
||||
determined according to <a href="#chap-Defensive_Coding-Tasks-Temporary_Files-Location">Obtaining the Location of Temporary Directory</a>.
|
||||
Do not use <code>java.io.File.deleteOnExit()</code> to
|
||||
delete temporary files, and do not register a shutdown hook for
|
||||
each temporary file you create. In both cases, the deletion
|
||||
hint cannot be removed from the system if you delete the
|
||||
temporary file prior to termination of the VM, causing a memory
|
||||
leak.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="temporary-files-without-names"><a class="anchor" href="#temporary-files-without-names"></a>Temporary Files without Names</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>The <code>tmpfile</code> function creates a temporary
|
||||
file and immediately deletes it, while keeping the file open.
|
||||
As a result, the file lacks a name and its space is deallocated
|
||||
as soon as the file descriptor is closed (including the implicit
|
||||
close when the process terminates). This avoids cluttering the
|
||||
temporary directory with orphaned files.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Alternatively, if the maximum size of the temporary file is
|
||||
known beforehand, the <code>fmemopen</code> function can
|
||||
be used to create a <code>FILE *</code> object which is
|
||||
backed by memory.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>In Python, unnamed temporary files are provided by the
|
||||
<code>tempfile.TemporaryFile</code> class, and the
|
||||
<code>tempfile.SpooledTemporaryFile</code> class provides
|
||||
a way to avoid creation of small temporary files.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Java does not support unnamed temporary files.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="chap-Defensive_Coding-Tasks-Temporary_Directory"><a class="anchor" href="#chap-Defensive_Coding-Tasks-Temporary_Directory"></a>Temporary Directories</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>The <code>mkdtemp</code> function can be used to create
|
||||
a temporary directory. (For determining the directory part of
|
||||
the file name pattern, see <a href="#chap-Defensive_Coding-Tasks-Temporary_Files-Location">Obtaining the Location of Temporary Directory</a>.)
|
||||
The directory is not automatically removed. In Python, this
|
||||
function is available as <code>tempfile.mkdtemp</code>.
|
||||
In Java 7, temporary directories can be created using the
|
||||
<code>java.nio.file.Files.createTempDirectory(Path, String,
|
||||
FileAttribute…​)</code> function.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>When creating files in the temporary directory, use
|
||||
automatically generated names, e.g., derived from a sequential
|
||||
counter. Files with externally provided names could be picked
|
||||
up in unexpected contexts, and crafted names could actually
|
||||
point outside of the tempoary directory (due to
|
||||
<strong>directory traversal</strong>).</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Removing a directory tree in a completely safe manner is
|
||||
complicated. Unless there are overriding performance concerns,
|
||||
the <strong class="application">rm</strong> program should be used, with
|
||||
the <code class="option">-rf</code> and <code class="option">--</code> options.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sect1">
|
||||
<h2 id="compensating-for-unsafe-file-creation"><a class="anchor" href="#compensating-for-unsafe-file-creation"></a>Compensating for Unsafe File Creation</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph">
|
||||
<p>There are two ways to make a function or program which excepts a
|
||||
file name safe for use with temporary files. See
|
||||
<a href="#sect-Defensive_Coding-Tasks-Processes-Creation">[sect-Defensive_Coding-Tasks-Processes-Creation]</a>,
|
||||
for details on subprocess creation.</p>
|
||||
</div>
|
||||
<div class="ulist">
|
||||
<ul>
|
||||
<li>
|
||||
<p>Create a temporary directory and place the file there. If
|
||||
possible, run the program in a subprocess which uses the
|
||||
temporary directory as its current directory, with a
|
||||
restricted environment.
|
||||
Use generated names for all files in that temporary
|
||||
directory. (See <a href="#chap-Defensive_Coding-Tasks-Temporary_Directory">Temporary Directories</a>.)</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Create the temporary file and pass the generated file name
|
||||
to the function or program. This only works if the function
|
||||
or program can cope with a zero-length existing file. It is
|
||||
safe only under additional assumptions:</p>
|
||||
<div class="ulist">
|
||||
<ul>
|
||||
<li>
|
||||
<p>The function or program must not create additional files
|
||||
whose name is derived from the specified file name or
|
||||
are otherwise predictable.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>The function or program must not delete the file before
|
||||
processing it.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>It must not access any existing files in the same
|
||||
directory.</p>
|
||||
<div class="paragraph">
|
||||
<p>It is often difficult to check whether these additional
|
||||
assumptions are matched, therefore this approach is not
|
||||
recommended.</p>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="bottom" class="text-muted py-3" >
|
||||
<div class="foot">
|
||||
<div class="container">
|
||||
<div class="row footerlinks">
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">About</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Overview">About Fedora</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/sponsors">Sponsors</a></dd>
|
||||
<dd><a href="https://fedoramagazine.org">Fedora Magazine</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Legal:Main#Legal">Legal</a></dd>
|
||||
</dl>
|
||||
<ul class="list-inline">
|
||||
<li>
|
||||
<a href="https://www.facebook.com/TheFedoraProject" class="btn-social btn-outline"><i class="fa fa-fw fa-facebook"></i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://plus.google.com/112917221531140868607" class="btn-social btn-outline"><i class="fa fa-fw fa-google-plus"></i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://twitter.com/fedora" class="btn-social btn-outline"><i class="fa fa-fw fa-twitter"></i></a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title uppercase">Download</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://getfedora.org/en/workstation/download">Get Fedora Workstation</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/server/download">Get Fedora Server</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/atomic/download">Get Fedora Atomic</a></dd>
|
||||
<dd><a href="https://spins.fedoraproject.org">Fedora Spins</a></dd>
|
||||
<dd><a href="https://labs.fedoraproject.org">Fedora Labs</a></dd>
|
||||
<dd><a href="https://arm.fedoraproject.org">Fedora ARM<span class="sup">®</span></a></dd>
|
||||
<dd><a href="https://alt.fedoraproject.org/">Alternative Downloads</a></dd>
|
||||
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">Support</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Communicating_and_getting_help">Get Help</a></dd>
|
||||
<dd><a href="https://ask.fedoraproject.org/">Ask Fedora</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Common_F27_bugs">Common Bugs</a></dd>
|
||||
<dd><a href="https://developer.fedoraproject.org/">Fedora Developer Portal</a></dd>
|
||||
<dd><a href="https://docs.fedoraproject.org/f27/install-guide/index.html">Installation Guide</a></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">Join</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Join">Join Fedora</a></dd>
|
||||
<dd><a href="http://fedoraplanet.org">Planet Fedora</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/SIGs">Fedora SIGs</a></dd>
|
||||
<dd><a href="https://admin.fedoraproject.org/accounts/">Fedora Account System</a></dd>
|
||||
<dd><a href="https://fedoracommunity.org/">Fedora Community</a></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- /row of widgets -->
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-2">
|
||||
<div class="widget-body">
|
||||
<a href="https://www.redhat.com/"><img class="rh-logo" src="../../../master/_images/redhat-logo.png" alt="Red Hat Logo" /></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-7">
|
||||
<div class="widget-body">
|
||||
<p class="sponsor">Fedora is sponsored by Red Hat.</p>
|
||||
<p class="sponsor"><a href="https://www.redhat.com/en/technologies/linux-platforms/articles/relationship-between-fedora-and-rhel">Learn more about the relationship between Red Hat and Fedora »</a></p>
|
||||
<p class="copy">© 2017 Red Hat, Inc. and others. Please send any comments or corrections to the <a href="https://pagure.io/fedora-docs/docs-fp-o">documentation team</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- /row of widgets -->
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
|
||||
<!-- Latest compiled and minified JavaScript -->
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
|
||||
<script src="../../../master/_javascripts/bootstrap-offcanvas.js" type="text/javascript"></script>
|
||||
<script type="text/javascript">
|
||||
/*<![CDATA[*/
|
||||
$(document).ready(function() {
|
||||
$("[id^='topicGroup']").on('show.bs.collapse', function (event) {
|
||||
if (!($(event.target).attr('id').match(/^topicSubGroup/))) {
|
||||
$(this).parent().find("[id^='tgSpan']").toggleClass("fa-angle-right fa-angle-down");
|
||||
}
|
||||
});
|
||||
$("[id^='topicGroup']").on('hide.bs.collapse', function (event) {
|
||||
if (!($(event.target).attr('id').match(/^topicSubGroup/))) {
|
||||
$(this).parent().find("[id^='tgSpan']").toggleClass("fa-angle-right fa-angle-down");
|
||||
}
|
||||
});
|
||||
$("[id^='topicSubGroup']").on('show.bs.collapse', function () {
|
||||
$(this).parent().find("[id^='sgSpan']").toggleClass("fa-caret-right fa-caret-down");
|
||||
});
|
||||
$("[id^='topicSubGroup']").on('hide.bs.collapse', function () {
|
||||
$(this).parent().find("[id^='sgSpan']").toggleClass("fa-caret-right fa-caret-down");
|
||||
});
|
||||
});
|
||||
/*]]>*/
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -1,598 +0,0 @@
|
|||
@import url(https://maxcdn.bootstrapcdn.com/font-awesome/4.1.0/css/font-awesome.min.css);
|
||||
/* ------------------------------------------------------------
|
||||
Image: "Spin" https://www.flickr.com/photos/eflon/3655695161/
|
||||
Author: eflon https://www.flickr.com/photos/eflon/
|
||||
License: https://creativecommons.org/licenses/by/2.0/
|
||||
---------------------------------------------------------------*/
|
||||
.attribution {
|
||||
text-align: center;
|
||||
position: relative;
|
||||
bottom: -20px;
|
||||
}
|
||||
.attribution .btn {
|
||||
color: #808080;
|
||||
color: rgba(175,175,175, .65);
|
||||
font-size: 11px;
|
||||
}
|
||||
.attribution .btn:hover {
|
||||
text-decoration: none;
|
||||
color: #aaa;
|
||||
}
|
||||
.popover-content {
|
||||
font-size: 12px;
|
||||
line-height: 1.3;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 980px) {
|
||||
body {
|
||||
margin-bottom: 200px;
|
||||
}
|
||||
footer {
|
||||
text-align: center;
|
||||
}
|
||||
footer .text-right {
|
||||
text-align: center !important;
|
||||
}
|
||||
#footer_social .first {
|
||||
margin-left: 0;
|
||||
}
|
||||
#footer_social > a {
|
||||
top: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
.fa-inverse:hover {
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
.collapse a.active {
|
||||
background-color: #DEEAF4;
|
||||
color: #000;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.collapse a.active:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.collapse a.active:before {
|
||||
background-color: #A0C3E5;
|
||||
content: "";
|
||||
display: inline-block;
|
||||
height: 100%;
|
||||
left: 0;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
width: 3px;
|
||||
}
|
||||
|
||||
.main h2, .main .h2 {
|
||||
border-top: 0px;
|
||||
padding-top: 10px;
|
||||
font-size: 28px;
|
||||
}
|
||||
|
||||
.page-header {
|
||||
height: 100% !important;
|
||||
}
|
||||
.page-header .img-responsive {
|
||||
display: inline;
|
||||
}
|
||||
.page-header h2 {
|
||||
font-size: 32px;
|
||||
display: inline;
|
||||
vertical-align: bottom;
|
||||
}
|
||||
|
||||
.navbar-brand {
|
||||
padding: initial;
|
||||
height: initial;
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
.navbar-header h2 {
|
||||
display: inline;
|
||||
position: absolute;
|
||||
font-weight: bold;
|
||||
margin-top: 50px ;
|
||||
}
|
||||
|
||||
.nav > li > a.hover{
|
||||
background-color: none;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6 {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
h2 > a.anchor, h3 > a.anchor, h4 > a.anchor, h5 > a.anchor, h6 > a.anchor {
|
||||
display: block;
|
||||
font-weight: normal;
|
||||
margin-left: -1.5ex;
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
text-decoration: none !important;
|
||||
visibility: hidden;
|
||||
width: 1.5ex;
|
||||
z-index: 1001;
|
||||
}
|
||||
|
||||
h2 > a.anchor:before, h3 > a.anchor:before, h4 > a.anchor:before, h5 > a.anchor:before, h6 > a.anchor:before {
|
||||
content: "\f0c1";
|
||||
display: block;
|
||||
font-family: FontAwesome;
|
||||
font-size: 0.7em;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
padding-top: 0.2em;
|
||||
}
|
||||
|
||||
h4 > a.anchor:before, h5 > a.anchor:before, h6 > a.anchor:before {
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
h2:hover > a.anchor,
|
||||
h2 > a.anchor:hover,
|
||||
h3:hover > a.anchor,
|
||||
h3 > a.anchor:hover,
|
||||
h4:hover > a.anchor,
|
||||
h4 > a.anchor:hover,
|
||||
h5:hover > a.anchor,
|
||||
h5 > a.anchor:hover,
|
||||
h6:hover > a.anchor,
|
||||
h6 > a.anchor:hover {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.main {
|
||||
border-left: 1px solid #e7e7e7;
|
||||
margin-left: -1px;
|
||||
padding-left: 25px;
|
||||
}
|
||||
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.main {
|
||||
padding-left: 30px;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Sidebar
|
||||
*/
|
||||
|
||||
.nav-header {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.nav-header ul {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.nav-header ul li a {
|
||||
display: block;
|
||||
padding: 5px 20px 5px 25px;
|
||||
font-size: 13px;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.nav-sidebar .fa {
|
||||
text-align: center;
|
||||
top: -1px;
|
||||
width: 14px;
|
||||
}
|
||||
|
||||
.nav-sidebar li a {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.nav-sidebar li a:hover {
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.nav-sidebar ul li ul.nav-tertiary li a {
|
||||
padding-left: 50px;
|
||||
}
|
||||
|
||||
.nav-sidebar > li > a {
|
||||
padding: 7px 0;
|
||||
}
|
||||
|
||||
.nav-sidebar > li > a:focus, .nav-sidebar > li > a:hover {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
font-weight: 300;
|
||||
display: none;
|
||||
padding-top: 13px;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 767px) {
|
||||
.sidebar {
|
||||
padding-left: 30px;
|
||||
padding-right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (min-width: 768px) {
|
||||
.sidebar {
|
||||
border-right: 1px solid #e7e7e7;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Off Canvas
|
||||
* --------------------------------------------------
|
||||
*/
|
||||
|
||||
body, html {
|
||||
overflow-x: hidden; /* Prevent scroll on narrow devices */
|
||||
font-family: "Overpass", sans-serif;
|
||||
}
|
||||
|
||||
.toggle-nav {
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 767px) {
|
||||
.row-offcanvas {
|
||||
position: relative;
|
||||
-webkit-transition: all .25s ease-out;
|
||||
-o-transition: all .25s ease-out;
|
||||
transition: all .25s ease-out;
|
||||
}
|
||||
|
||||
.row-offcanvas-right {
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.row-offcanvas-left {
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.row-offcanvas-right
|
||||
.sidebar-offcanvas {
|
||||
right: -75%; /* 8 columns */
|
||||
}
|
||||
|
||||
.row-offcanvas-left
|
||||
.sidebar-offcanvas {
|
||||
left: -75%; /* 8 columns */
|
||||
}
|
||||
|
||||
.row-offcanvas-right.active {
|
||||
right: 75%; /* 8 columns */
|
||||
}
|
||||
|
||||
.row-offcanvas-left.active {
|
||||
left: 75%; /* 8 columns */
|
||||
}
|
||||
|
||||
.sidebar-offcanvas {
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
width: 75%; /* 8 columns */
|
||||
}
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 0 0 1.6em;
|
||||
}
|
||||
|
||||
/* Remnants of Asciidoctor default stylesheet - remove styles as needed */
|
||||
|
||||
#map_canvas img, #map_canvas embed, #map_canvas object, .map_canvas img, .map_canvas embed, .map_canvas object { max-width: none !important; }
|
||||
.left { float: left !important; }
|
||||
.right { float: right !important; }
|
||||
.text-left { text-align: left !important; }
|
||||
.text-right { text-align: right !important; }
|
||||
.text-center { text-align: center !important; }
|
||||
.text-justify { text-align: justify !important; }
|
||||
.hide { display: none; }
|
||||
.subheader, #content #toctitle, .admonitionblock td.content > .title, .audioblock > .title, .exampleblock > .title, .imageblock > .title, .listingblock > .title, .literalblock > .title, .stemblock > .title, .openblock > .title, .paragraph > .title, .quoteblock > .title, table.tableblock > .title, .verseblock > .title, .videoblock > .title, .dlist > .title, .olist > .title, .ulist > .title, .qlist > .title, .hdlist > .title { line-height: 1.4; color: #7a2518; font-weight: 300; margin-top: 0.2em; margin-bottom: 0.5em; }
|
||||
abbr, acronym { text-transform: uppercase; font-size: 90%; color: #333333; border-bottom: 1px dotted #dddddd; cursor: help; }
|
||||
abbr { text-transform: none; }
|
||||
blockquote { margin: 0 0 1.25em; padding: 0.5625em 1.25em 0 1.1875em; border-left: 3px solid #487c58; }
|
||||
blockquote cite { display: block; font-size: inherit; color: #454545; }
|
||||
blockquote cite:before { content: "\2014 \0020"; }
|
||||
blockquote cite a, blockquote cite a:visited { color: #454545; }
|
||||
blockquote, blockquote p { line-height: 1.6; color: #6e6e6e; }
|
||||
@media only screen and (min-width: 768px) {
|
||||
#toctitle, .sidebarblock > .content > .title { line-height: 1.4; }
|
||||
#toctitle, .sidebarblock > .content > .title { font-size: 1.6875em; }
|
||||
}
|
||||
table { background: white; margin-bottom: 1.25em; border: solid 1px #dddddd; }
|
||||
table thead, table tfoot { background: whitesmoke; font-weight: bold; }
|
||||
table thead tr th, table thead tr td, table tfoot tr th, table tfoot tr td { padding: 0.5em 0.625em 0.625em; font-size: inherit; color: #333333; text-align: left; }
|
||||
table tr th, table tr td { padding: 0.5625em 0.625em; font-size: inherit; color: #333333; }
|
||||
table tr.even, table tr.alt, table tr:nth-of-type(even) { background: #f9f9f9; }
|
||||
table thead tr th, table tfoot tr th, table tbody tr td, table tr td, table tfoot tr td { display: table-cell; line-height: 1.6; }
|
||||
.clearfix:before, .clearfix:after, .float-group:before, .float-group:after { content: " "; display: table; }
|
||||
.clearfix:after, .float-group:after { clear: both; }
|
||||
*:not(pre) > code { font-size: inherit; padding: 0; white-space: nowrap; background-color: inherit; border: 0 solid #dddddd; -webkit-border-radius: 4px; border-radius: 4px; text-shadow: none; line-height: 1; }
|
||||
.keyseq { color: #666666; }
|
||||
kbd:not(.keyseq) { display: inline-block; color: #333333; font-size: 0.75em; line-height: 1.4; background-color: #f7f7f7; border: 1px solid #ccc; -webkit-border-radius: 3px; border-radius: 3px; -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.2), 0 0 0 2px white inset; box-shadow: 0 1px 0 rgba(0, 0, 0, 0.2), 0 0 0 2px white inset; margin: -0.15em 0.15em 0 0.15em; padding: 0.2em 0.6em 0.2em 0.5em; vertical-align: middle; white-space: nowrap; }
|
||||
.keyseq kbd:first-child { margin-left: 0; }
|
||||
.keyseq kbd:last-child { margin-right: 0; }
|
||||
.menuseq, .menu { color: #1a1a1a; }
|
||||
b.button:before, b.button:after { position: relative; top: -1px; font-weight: normal; }
|
||||
b.button:before { content: "["; padding: 0 3px 0 2px; }
|
||||
b.button:after { content: "]"; padding: 0 2px 0 3px; }
|
||||
p a > code:hover { color: #561309; }
|
||||
#header, #content, #footnotes, #footer { width: 100%; margin-left: auto; margin-right: auto; margin-top: 0; margin-bottom: 0; max-width: 62.5em; *zoom: 1; position: relative; padding-left: 0.9375em; padding-right: 0.9375em; }
|
||||
#header:before, #header:after, #content:before, #content:after, #footnotes:before, #footnotes:after, #footer:before, #footer:after { content: " "; display: table; }
|
||||
#header:after, #content:after, #footnotes:after, #footer:after { clear: both; }
|
||||
#content:before { content: none; }
|
||||
#header { margin-bottom: 2.5em; }
|
||||
#header > h1 { color: black; font-weight: 300; border-bottom: 1px solid #d8d8d8; margin-bottom: -28px; padding-bottom: 32px; }
|
||||
#header span { color: #6e6e6e; }
|
||||
#header #revnumber { text-transform: capitalize; }
|
||||
#header br { display: none; }
|
||||
#header br + span { padding-left: 3px; }
|
||||
#header br + span:before { content: "\2013 \0020"; }
|
||||
#header br + span.author { padding-left: 0; }
|
||||
#header br + span.author:before { content: ", "; }
|
||||
#toc { border-bottom: 3px double #e5e5e5; padding-top: 1em; padding-bottom: 1.25em; }
|
||||
#toc > ul { margin-left: 0.25em; }
|
||||
#toc ul.sectlevel0 > li > a { font-style: italic; }
|
||||
#toc ul.sectlevel0 ul.sectlevel1 { margin-left: 0; margin-top: 0.5em; margin-bottom: 0.5em; }
|
||||
#toc ul { font-family: "Open Sans", "DejaVu Sans", "Sans", sans-serif; list-style-type: none; }
|
||||
#toc a { text-decoration: none; }
|
||||
#toc a:active { text-decoration: underline; }
|
||||
#toctitle { color: #7a2518; }
|
||||
@media only screen and (min-width: 768px) { body.toc2 { padding-left: 15em; padding-right: 0; }
|
||||
#toc.toc2 { background-color: #fafaf9; position: fixed; width: 15em; left: 0; top: 0; border-right: 1px solid #e5e5e5; border-bottom: 0; z-index: 1000; padding: 1.25em 1em; height: 100%; overflow: auto; }
|
||||
#toc.toc2 #toctitle { margin-top: 0; font-size: 1.2em; }
|
||||
#toc.toc2 > ul { font-size: .90em; margin-bottom: 0; }
|
||||
#toc.toc2 ul ul { margin-left: 0; padding-left: 1em; }
|
||||
#toc.toc2 ul.sectlevel0 ul.sectlevel1 { padding-left: 0; margin-top: 0.5em; margin-bottom: 0.5em; }
|
||||
body.toc2.toc-right { padding-left: 0; padding-right: 15em; }
|
||||
body.toc2.toc-right #toc.toc2 { border-right: 0; border-left: 1px solid #e5e5e5; left: auto; right: 0; } }
|
||||
@media only screen and (min-width: 1280px) { body.toc2 { padding-left: 20em; padding-right: 0; }
|
||||
#toc.toc2 { width: 20em; }
|
||||
#toc.toc2 #toctitle { font-size: 1.375em; }
|
||||
#toc.toc2 > ul { font-size: 0.95em; }
|
||||
#toc.toc2 ul ul { padding-left: 1.25em; }
|
||||
body.toc2.toc-right { padding-left: 0; padding-right: 20em; } }
|
||||
#content #toc { border-style: solid; border-width: 1px; border-color: #e3e3dd; margin-bottom: 1.25em; padding: 1.25em; background: #fafaf9; border-width: 0; -webkit-border-radius: 4px; border-radius: 4px; }
|
||||
#content #toc > :first-child { margin-top: 0; }
|
||||
#content #toc > :last-child { margin-bottom: 0; }
|
||||
#content #toctitle { font-size: 1.375em; }
|
||||
#footer { max-width: 100%; background-color: #333333; padding: 1.25em; }
|
||||
#footer-text { color: #cccccc; line-height: 1.44; }
|
||||
.audioblock, .imageblock, .literalblock, .listingblock, .stemblock, .verseblock, .videoblock { margin-bottom: 2.5em; }
|
||||
.admonitionblock td.content > .title, .audioblock > .title, .exampleblock > .title, .imageblock > .title, .listingblock > .title, .literalblock > .title, .stemblock > .title, .openblock > .title, .paragraph > .title, .quoteblock > .title, table.tableblock > .title, .verseblock > .title, .videoblock > .title, .dlist > .title, .olist > .title, .ulist > .title, .qlist > .title, .hdlist > .title { text-rendering: optimizeLegibility; text-align: left; font-family: "Noto Serif", "DejaVu Serif", "Serif", serif; font-weight: normal; font-style: italic; }
|
||||
table.tableblock > caption.title { white-space: nowrap; overflow: visible; max-width: 0; }
|
||||
table.tableblock #preamble > .sectionbody > .paragraph:first-of-type p { font-size: inherit; }
|
||||
.admonitionblock > table { border: 0; background: none; width: 100%; }
|
||||
.admonitionblock > table td.icon { text-align: center; width: 80px; }
|
||||
.admonitionblock > table td.icon img { max-width: none; }
|
||||
.admonitionblock > table td.icon .title { font-weight: 300; text-transform: uppercase; }
|
||||
.admonitionblock > table td.content { padding-left: 0; padding-right: 1.25em; color: #6e6e6e; }
|
||||
.admonitionblock > table td.content > :last-child > :last-child { margin-bottom: 0; }
|
||||
.exampleblock > .content { border-style: solid; border-width: 1px; border-color: #e6e6e6; margin-bottom: 1.25em; padding: 1.25em; background: white; -webkit-border-radius: 4px; border-radius: 4px; }
|
||||
.exampleblock > .content > :first-child { margin-top: 0; }
|
||||
.exampleblock > .content > :last-child { margin-bottom: 0; }
|
||||
.exampleblock > .content h1, .exampleblock > .content h2, .exampleblock > .content h3, .exampleblock > .content #toctitle, .sidebarblock.exampleblock > .content > .title, .exampleblock > .content h4, .exampleblock > .content h5, .exampleblock > .content h6, .exampleblock > .content p { color: #333333; }
|
||||
.exampleblock > .content h1, .exampleblock > .content h2, .exampleblock > .content h3, .exampleblock > .content #toctitle, .sidebarblock.exampleblock > .content > .title, .exampleblock > .content h4, .exampleblock > .content h5, .exampleblock > .content h6 { line-height: 1; margin-bottom: 0.625em; }
|
||||
.exampleblock > .content h1.subheader, .exampleblock > .content h2.subheader, .exampleblock > .content h3.subheader, .exampleblock > .content .subheader#toctitle, .sidebarblock.exampleblock > .content > .subheader.title, .exampleblock > .content h4.subheader, .exampleblock > .content h5.subheader, .exampleblock > .content h6.subheader { line-height: 1.4; }
|
||||
.exampleblock.result > .content { -webkit-box-shadow: 0 1px 8px #e3e3dd; box-shadow: 0 1px 8px #e3e3dd; }
|
||||
.sidebarblock { border-style: solid; border-width: 1px; border-color: #e3e3dd; margin-top: -1.0em; margin-bottom: 1.6em; margin-left: 1em; padding: .5em; background: #F1F3F5; -webkit-border-radius: 4px; border-radius: 4px; overflow-x: auto; float: right; width: 40%; }
|
||||
.sidebarblock > :first-child { margin-top: 0; }
|
||||
.sidebarblock > :last-child { margin-bottom: 0; }
|
||||
.sidebarblock h1, .sidebarblock h2, .sidebarblock h3, .sidebarblock #toctitle, .sidebarblock > .content > .title, .sidebarblock h4, .sidebarblock h5, .sidebarblock h6, .sidebarblock p { color: #333333; }
|
||||
.sidebarblock h1, .sidebarblock h2, .sidebarblock h3, .sidebarblock #toctitle, .sidebarblock > .content > .title, .sidebarblock h4, .sidebarblock h5, .sidebarblock h6 { line-height: 1; margin-bottom: 0.625em; }
|
||||
.sidebarblock h1.subheader, .sidebarblock h2.subheader, .sidebarblock h3.subheader, .sidebarblock .subheader#toctitle, .sidebarblock > .content > .subheader.title, .sidebarblock h4.subheader, .sidebarblock h5.subheader, .sidebarblock h6.subheader { line-height: 1.4; }
|
||||
.sidebarblock > .content > .title { color: inherit; font-size: 28px; font-weight: 500; margin-top: 0; line-height: 1.6; }
|
||||
.width50 { width: 50% ! important}
|
||||
.exampleblock > .content > :last-child > :last-child, .exampleblock > .content .olist > ol > li:last-child > :last-child, .exampleblock > .content .ulist > ul > li:last-child > :last-child, .exampleblock > .content .qlist > ol > li:last-child > :last-child, .sidebarblock > .content > :last-child > :last-child, .sidebarblock > .content .olist > ol > li:last-child > :last-child, .sidebarblock > .content .ulist > ul > li:last-child > :last-child, .sidebarblock > .content .qlist > ol > li:last-child > :last-child { margin-bottom: 0; }
|
||||
.literalblock pre, .literalblock pre[class], .listingblock pre, .listingblock pre[class] { border: 0px; background-color: #F0F3F5; -webkit-border-radius: 5px; border-radius: 5px; padding: 1.5em 2.5em; word-wrap: break-word; }
|
||||
.literalblock pre.nowrap, .literalblock pre[class].nowrap, .listingblock pre.nowrap, .listingblock pre[class].nowrap { overflow-x: auto; white-space: pre; word-wrap: normal; }
|
||||
.literalblock pre > code, .literalblock pre[class] > code, .listingblock pre > code, .listingblock pre[class] > code { display: block; }
|
||||
.listingblock > .content { position: relative; }
|
||||
.listingblock:hover code[class*=" language-"]:before { text-transform: uppercase; font-size: 0.9em; color: #999; position: absolute; top: 0.375em; right: 0.375em; }
|
||||
.listingblock:hover code.asciidoc:before { content: "asciidoc"; }
|
||||
.listingblock:hover code.clojure:before { content: "clojure"; }
|
||||
.listingblock:hover code.css:before { content: "css"; }
|
||||
.listingblock:hover code.go:before { content: "go"; }
|
||||
.listingblock:hover code.groovy:before { content: "groovy"; }
|
||||
.listingblock:hover code.html:before { content: "html"; }
|
||||
.listingblock:hover code.java:before { content: "java"; }
|
||||
.listingblock:hover code.javascript:before { content: "javascript"; }
|
||||
.listingblock:hover code.python:before { content: "python"; }
|
||||
.listingblock:hover code.ruby:before { content: "ruby"; }
|
||||
.listingblock:hover code.sass:before { content: "sass"; }
|
||||
.listingblock:hover code.scss:before { content: "scss"; }
|
||||
.listingblock:hover code.xml:before { content: "xml"; }
|
||||
.listingblock:hover code.yaml:before { content: "yaml"; }
|
||||
.listingblock.terminal pre .command:before { content: attr(data-prompt); padding-right: 0.5em; color: #999; }
|
||||
.listingblock.terminal pre .command:not([data-prompt]):before { content: '$'; }
|
||||
table.pyhltable { border: 0; margin-bottom: 0; }
|
||||
table.pyhltable td { vertical-align: top; padding-top: 0; padding-bottom: 0; }
|
||||
table.pyhltable td.code { padding-left: .75em; padding-right: 0; }
|
||||
.highlight.pygments .lineno, table.pyhltable td:not(.code) { color: #999; padding-left: 0; padding-right: .5em; border-right: 1px solid #d8d8d8; }
|
||||
.highlight.pygments .lineno { display: inline-block; margin-right: .25em; }
|
||||
table.pyhltable .linenodiv { background-color: transparent !important; padding-right: 0 !important; }
|
||||
.quoteblock { margin: 0 0 1.25em 0; padding: 0.5625em 1.25em 0 1.1875em; border-left: 3px solid #487c58; }
|
||||
.quoteblock blockquote { margin: 0 0 1.25em 0; padding: 0 0 0.625em 0; border: 0; }
|
||||
.quoteblock blockquote > .paragraph:last-child p { margin-bottom: 0; }
|
||||
.quoteblock .attribution { margin-top: -0.625em; padding-bottom: 0.625em; font-size: inherit; color: #454545; line-height: 1.6; }
|
||||
.quoteblock .attribution br { display: none; }
|
||||
.quoteblock .attribution cite { display: block; }
|
||||
table.tableblock { max-width: 100%; }
|
||||
table.tableblock td .paragraph:last-child p > p:last-child, table.tableblock th > p:last-child, table.tableblock td > p:last-child { margin-bottom: 0; }
|
||||
table.spread { width: 100%; }
|
||||
table.tableblock, th.tableblock, td.tableblock { border: 0 solid #dddddd; }
|
||||
table.grid-all th.tableblock, table.grid-all td.tableblock { border-width: 0 1px 1px 0; }
|
||||
table.grid-all tfoot > tr > th.tableblock, table.grid-all tfoot > tr > td.tableblock { border-width: 1px 1px 0 0; }
|
||||
table.grid-cols th.tableblock, table.grid-cols td.tableblock { border-width: 0 1px 0 0; }
|
||||
table.grid-all * > tr > .tableblock:last-child, table.grid-cols * > tr > .tableblock:last-child { border-right-width: 0; }
|
||||
table.grid-rows th.tableblock, table.grid-rows td.tableblock { border-width: 0 0 1px 0; }
|
||||
table.grid-all tbody > tr:last-child > th.tableblock, table.grid-all tbody > tr:last-child > td.tableblock, table.grid-all thead:last-child > tr > th.tableblock, table.grid-rows tbody > tr:last-child > th.tableblock, table.grid-rows tbody > tr:last-child > td.tableblock, table.grid-rows thead:last-child > tr > th.tableblock { border-bottom-width: 0; }
|
||||
table.grid-rows tfoot > tr > th.tableblock, table.grid-rows tfoot > tr > td.tableblock { border-width: 1px 0 0 0; }
|
||||
table.frame-all { border-width: 1px; }
|
||||
table.frame-sides { border-width: 0 1px; }
|
||||
table.frame-topbot { border-width: 1px 0; }
|
||||
th.halign-left, td.halign-left { text-align: left; }
|
||||
th.halign-right, td.halign-right { text-align: right; }
|
||||
th.halign-center, td.halign-center { text-align: center; }
|
||||
th.valign-top, td.valign-top { vertical-align: top; }
|
||||
th.valign-bottom, td.valign-bottom { vertical-align: bottom; }
|
||||
th.valign-middle, td.valign-middle { vertical-align: middle; }
|
||||
table thead th, table tfoot th { font-weight: bold; }
|
||||
tbody tr th { display: table-cell; line-height: 1.6; background: whitesmoke; }
|
||||
tbody tr th, tbody tr th p, tfoot tr th, tfoot tr th p { color: #333333; font-weight: bold; }
|
||||
td > div.verse { white-space: pre; }
|
||||
ul.unstyled, ol.unnumbered, ul.checklist, ul.none { list-style-type: none; }
|
||||
ul.unstyled, ol.unnumbered, ul.checklist { margin-left: 0.625em; }
|
||||
ul.checklist li > p:first-child > .fa-check-square-o:first-child, ul.checklist li > p:first-child > input[type="checkbox"]:first-child { margin-right: 0.25em; }
|
||||
ul.checklist li > p:first-child > input[type="checkbox"]:first-child { position: relative; top: 1px; }
|
||||
ul.inline { margin: 0 auto 0.625em auto; margin-left: -1.375em; margin-right: 0; padding: 0; list-style: none; overflow: hidden; }
|
||||
ul.inline > li { list-style: none; float: left; margin-left: 1.375em; display: block; }
|
||||
ul.inline > li > * { display: block; }
|
||||
.unstyled dl dt { font-weight: normal; font-style: normal; }
|
||||
ol.arabic { list-style-type: decimal; }
|
||||
ol.decimal { list-style-type: decimal-leading-zero; }
|
||||
ol.loweralpha { list-style-type: lower-alpha; }
|
||||
ol.upperalpha { list-style-type: upper-alpha; }
|
||||
ol.lowerroman { list-style-type: lower-roman; }
|
||||
ol.upperroman { list-style-type: upper-roman; }
|
||||
ol.lowergreek { list-style-type: lower-greek; }
|
||||
.hdlist > table, .colist > table { border: 0; background: none; }
|
||||
.hdlist > table > tbody > tr, .colist > table > tbody > tr { background: none; }
|
||||
td.hdlist1 { padding-right: .75em; font-weight: bold; }
|
||||
td.hdlist1, td.hdlist2 { vertical-align: top; }
|
||||
.literalblock + .colist, .listingblock + .colist { margin-top: -0.5em; }
|
||||
.colist > table tr > td:first-of-type { padding: 0 .75em; line-height: 1; }
|
||||
.colist > table tr > td:last-of-type { padding: 0.25em 0; }
|
||||
.qanda > ol > li > p > em:only-child { color: #1d4b8f; }
|
||||
.thumb, .th { line-height: 0; display: inline-block; border: solid 4px white; -webkit-box-shadow: 0 0 0 1px #dddddd; box-shadow: 0 0 0 1px #dddddd; }
|
||||
.imageblock.left, .imageblock[style*="float: left"] { margin: 0.25em 0.625em 1.25em 0; }
|
||||
.imageblock.right, .imageblock[style*="float: right"] { margin: 0.25em 0 1.25em 0.625em; }
|
||||
.imageblock > .title { margin-bottom: 0; }
|
||||
.imageblock.thumb, .imageblock.th { border-width: 6px; }
|
||||
.imageblock.thumb > .title, .imageblock.th > .title { padding: 0 0.125em; }
|
||||
.image.left, .image.right { margin-top: 0.25em; margin-bottom: 0.25em; display: inline-block; line-height: 0; }
|
||||
.image.left { margin-right: 0.625em; }
|
||||
.image.right { margin-left: 0.625em; }
|
||||
a.image { text-decoration: none; }
|
||||
span.footnote, span.footnoteref { vertical-align: super; font-size: 0.875em; }
|
||||
span.footnote a, span.footnoteref a { text-decoration: none; }
|
||||
span.footnote a:active, span.footnoteref a:active { text-decoration: underline; }
|
||||
#footnotes { padding-top: 0.75em; padding-bottom: 0.75em; margin-bottom: 0.625em; }
|
||||
#footnotes hr { width: 20%; min-width: 6.25em; margin: -.25em 0 .75em 0; border-width: 1px 0 0 0; }
|
||||
#footnotes .footnote { padding: 0 0.375em; line-height: 1.3; font-size: 0.875em; margin-left: 1.2em; text-indent: -1.2em; margin-bottom: .2em; }
|
||||
#footnotes .footnote a:first-of-type { font-weight: bold; text-decoration: none; }
|
||||
#footnotes .footnote:last-of-type { margin-bottom: 0; }
|
||||
#content #footnotes { margin-top: -0.625em; margin-bottom: 0; padding: 0.75em 0; }
|
||||
.gist .file-data > table { border: none; background: #fff; width: 100%; margin-bottom: 0; }
|
||||
.gist .file-data > table td.line-data { width: 99%; }
|
||||
div.unbreakable { page-break-inside: avoid; }
|
||||
.replaceable { font-style: italic; font-color: inherit; font-family: inherit; }
|
||||
.parameter { font-style: italic; font-family: monospace; }
|
||||
.userinput { font-weight: bold; font-family: monospace; }
|
||||
.envar { font-weight: bold; font-family: monospace; font-size: 90%; }
|
||||
.sysitem { font-weight: bold; font-size: 90%; }
|
||||
.package { font-weight: bold; font-size: 90%; }
|
||||
.filename { font-weight: bold; font-style: italic; font-size: 90%; }
|
||||
.big { font-size: larger; }
|
||||
.small { font-size: smaller; }
|
||||
.underline { text-decoration: underline; }
|
||||
.overline { text-decoration: overline; }
|
||||
.line-through { text-decoration: line-through; }
|
||||
.aqua { color: #00bfbf; }
|
||||
.aqua-background { background-color: #00fafa; }
|
||||
.black { color: black; }
|
||||
.black-background { background-color: black; }
|
||||
.blue { color: #0000bf; }
|
||||
.blue-background { background-color: #0000fa; }
|
||||
.fuchsia { color: #bf00bf; }
|
||||
.fuchsia-background { background-color: #fa00fa; }
|
||||
.gray { color: #606060; }
|
||||
.gray-background { background-color: #7d7d7d; }
|
||||
.green { color: #006000; }
|
||||
.green-background { background-color: #007d00; }
|
||||
.lime { color: #00bf00; }
|
||||
.lime-background { background-color: #00fa00; }
|
||||
.maroon { color: #600000; }
|
||||
.maroon-background { background-color: #7d0000; }
|
||||
.navy { color: #000060; }
|
||||
.navy-background { background-color: #00007d; }
|
||||
.olive { color: #606000; }
|
||||
.olive-background { background-color: #7d7d00; }
|
||||
.purple { color: #600060; }
|
||||
.purple-background { background-color: #7d007d; }
|
||||
.red { color: #bf0000; }
|
||||
.red-background { background-color: #fa0000; }
|
||||
.silver { color: #909090; }
|
||||
.silver-background { background-color: #bcbcbc; }
|
||||
.teal { color: #006060; }
|
||||
.teal-background { background-color: #007d7d; }
|
||||
.white { color: #bfbfbf; }
|
||||
.white-background { background-color: #fafafa; }
|
||||
.yellow { color: #bfbf00; }
|
||||
.yellow-background { background-color: #fafa00; }
|
||||
span.icon > .fa { cursor: default; }
|
||||
.admonitionblock td.icon [class^="fa icon-"] { font-size: 2.5em; cursor: default; }
|
||||
.admonitionblock td.icon .icon-note:before { content: "\f05a"; color: #4E9FDD; }
|
||||
.admonitionblock td.icon .icon-tip:before { content: "\f0eb"; color: #2C8596; }
|
||||
.admonitionblock td.icon .icon-warning:before { content: "\f071"; color: #ec7a08; }
|
||||
.admonitionblock td.icon .icon-caution:before { content: "\f06d"; color: #ec7a08; }
|
||||
.admonitionblock td.icon .icon-important:before { content: "\f06a"; color: #c00; }
|
||||
.conum[data-value] { display: inline-block; color: white !important; background-color: #333333; -webkit-border-radius: 100px; border-radius: 100px; text-align: center; width: 20px; height: 20px; font-size: 12px; line-height: 20px; font-family: "Open Sans", "Sans", sans-serif; font-style: normal; font-weight: bold; text-indent: -1px; }
|
||||
.conum[data-value] * { color: white !important; }
|
||||
.conum[data-value] + b { display: none; }
|
||||
.conum[data-value]:after { content: attr(data-value); }
|
||||
pre .conum[data-value] { position: relative; top: -2px; }
|
||||
b.conum * { color: inherit !important; }
|
||||
.conum:not([data-value]):empty { display: none; }
|
||||
.print-only { display: none !important; }
|
||||
@media print { @page { margin: 1.25cm 0.75cm; }
|
||||
* { -webkit-box-shadow: none !important; box-shadow: none !important; text-shadow: none !important; }
|
||||
a, a:visited { color: inherit !important; text-decoration: underline !important; }
|
||||
a[href^="http:"]:after, a[href^="https:"]:after { content: " (" attr(href) ")"; }
|
||||
a[href^="#"], a[href^="#"]:visited, a[href^="mailto:"], a[href^="mailto:"]:visited { text-decoration: none !important; }
|
||||
abbr[title]:after { content: " (" attr(title) ")"; }
|
||||
pre, blockquote { page-break-inside: avoid; }
|
||||
code { color: #191919; }
|
||||
thead { display: table-header-group; }
|
||||
tr, img { page-break-inside: avoid; }
|
||||
img { max-width: 100% !important; }
|
||||
p { orphans: 3; widows: 3; }
|
||||
h2, h3, #toctitle, .sidebarblock > .content > .title, #toctitle, .sidebarblock > .content > .title { page-break-after: avoid; }
|
||||
#toc, .sidebarblock { background: none !important; }
|
||||
#toc { border-bottom: 1px solid #d8d8d8 !important; padding-bottom: 0 !important; }
|
||||
.sect1 { padding-bottom: 0 !important; }
|
||||
.sect1 + .sect1 { border: none !important; }
|
||||
body.book #header { text-align: center; }
|
||||
body.book #header > h1 { border: none !important; margin: 2.5em 0 1em 0; padding: 0; }
|
||||
body.book #header span { line-height: 1.6; }
|
||||
body.book #header br { display: block; }
|
||||
body.book #header br + span { padding-left: 0; }
|
||||
body.book #header br + span:before { content: none !important; }
|
||||
body.book #toc { border: none !important; text-align: left !important; padding: 0 !important; }
|
||||
#footer { background: none !important; }
|
||||
#footer-text { color: #333333 !important; }
|
||||
.hide-on-print { display: none !important; }
|
||||
.print-only { display: block !important; }
|
||||
.hide-for-print { display: none !important; }
|
||||
.show-for-print { display: inherit !important; } }
|
||||
|
||||
.corner-ribbon{
|
||||
width: 16em;
|
||||
background: #3c6eb4 ;
|
||||
position: absolute;
|
||||
top: 3em;
|
||||
right: -4em;
|
||||
text-align: center;
|
||||
line-height: 5ex;
|
||||
color: #dedede;
|
||||
transform: rotate(45deg);
|
||||
-webkit-transform: rotate(45deg);
|
||||
z-index: 999;
|
||||
}
|
||||
.corner-ribbon a { color: #FFFFFF; }
|
|
@ -1,3 +0,0 @@
|
|||
<%- Dir.glob("_stylesheets/*").sort.each do |sheet| -%>
|
||||
<link href="<%= File.join(css_path, File.basename(sheet)) %>" rel="stylesheet" />
|
||||
<%- end -%>
|
|
@ -1,31 +0,0 @@
|
|||
<ul class="nav nav-sidebar">
|
||||
<%- navigation.each.with_index do |topic_group, groupidx| -%>
|
||||
<%- current_group = topic_group[:id] == group_id -%>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicGroup<%= groupidx %>">
|
||||
<span id="tgSpan<%= groupidx %>" class="fa <%= current_group ? 'fa-angle-down' : 'fa-angle-right' %>"></span><%= topic_group[:name] %>
|
||||
</a>
|
||||
<ul id="topicGroup<%= groupidx %>" class="collapse <%= current_group ? 'in' : '' %> list-unstyled">
|
||||
<%- topic_group[:topics].each.with_index do |topic, topicidx| -%>
|
||||
<%- if not topic.has_key?(:topics) -%>
|
||||
<%- current_topic = current_group && (topic[:id] == topic_id) -%>
|
||||
<li><a class="<%= current_topic ? ' active' : '' %>" href="<%= subtopic_shim %><%= topic[:path] %>"><%= topic[:name] %></a></li>
|
||||
<%- else -%>
|
||||
<%- current_subgroup = topic[:id] == subgroup_id -%>
|
||||
<li class="nav-header">
|
||||
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-<%= groupidx %>-<%= topicidx %>">
|
||||
<span id="sgSpan-<%= groupidx %>-<%= topicidx %>" class="fa <%= current_subgroup ? 'fa-caret-down' : 'fa-caret-right' %>"></span> <%= topic[:name] %>
|
||||
</a>
|
||||
<ul id="topicSubGroup-<%= groupidx %>-<%= topicidx %>" class="nav-tertiary list-unstyled collapse<%= current_subgroup ? ' in' : '' %>">
|
||||
<%- topic[:topics].each do |subtopic| -%>
|
||||
<%- current_subtopic = current_group && current_subgroup && (subtopic[:id] == topic_id) %>
|
||||
<li><a class="<%= current_subtopic ? ' active' : '' %>" href="<%= subtopic_shim %><%= subtopic[:path] %>"><%= subtopic[:name] %></a></li>
|
||||
<%- end -%>
|
||||
</ul>
|
||||
</li>
|
||||
<%- end -%>
|
||||
<%- end -%>
|
||||
</ul>
|
||||
</li>
|
||||
<%- end -%>
|
||||
</ul>
|
|
@ -1,187 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta content="IE=edge" http-equiv="X-UA-Compatible">
|
||||
<meta content="width=device-width, initial-scale=1.0" name="viewport">
|
||||
<title><%= distro %> <%= version %> | <%= [group_title, subgroup_title, topic_title].compact.join(' | ') %></title>
|
||||
|
||||
<!-- Bootstrap -->
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap-theme.min.css">
|
||||
|
||||
<!-- Overpass Font -->
|
||||
<link rel="stylesheet" href="https://overpass-30e2.kxcdn.com/overpass.css">
|
||||
|
||||
<%= render("_templates/_css.html.erb", :css_path => css_path) %>
|
||||
|
||||
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
|
||||
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
|
||||
<!--[if lt IE 9]>
|
||||
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
|
||||
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
|
||||
<![endif]-->
|
||||
|
||||
<link href="<%= File.join(images_path, "favicon32x32.png") %>" rel="shortcut icon" type="text/css">
|
||||
<!--[if IE]><link rel="shortcut icon" href="<%= File.join(images_path, "favicon.ico") %>"><![endif]-->
|
||||
<meta content="AsciiBinder" name="application-name">
|
||||
</head>
|
||||
<body>
|
||||
<%- if version == "Rawhide" %>
|
||||
<div class="corner-ribbon"><a href="https://pagure.io/fedora-docs/<%= repo_path.sub('/') {|s| "/blob/#{branch}/f/en-US/"} %>">Improve this Page</a></div>
|
||||
<%- end %>
|
||||
<div class="navbar navbar-default" role="navigation">
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-header">
|
||||
<a class="navbar-brand" href="https://docs.fedoraproject.org/"><img alt="Fedora Documentation" src="<%= File.join(images_path, "fedora.svg") %>"></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container">
|
||||
<p class="toggle-nav visible-xs pull-left">
|
||||
<button class="btn btn-default btn-sm" type="button" data-toggle="offcanvas">Toggle nav</button>
|
||||
</p>
|
||||
<ol class="breadcrumb">
|
||||
<li class="sitename">
|
||||
<a href="<%= site_home_path %>"><%= site_name %></a>
|
||||
</li>
|
||||
<li class="hidden-xs active">
|
||||
<%= breadcrumb_root %>
|
||||
</li>
|
||||
<li class="hidden-xs active">
|
||||
<%= breadcrumb_group %>
|
||||
</li>
|
||||
<%= breadcrumb_subgroup_block %>
|
||||
<li class="hidden-xs active">
|
||||
<%= breadcrumb_topic %>
|
||||
</li>
|
||||
</ol>
|
||||
<div class="row row-offcanvas row-offcanvas-left">
|
||||
<div class="col-xs-8 col-sm-3 col-md-3 sidebar sidebar-offcanvas">
|
||||
<%= render("_templates/_nav.html.erb", :navigation => navigation, :group_id => group_id, :topic_id => topic_id, :subgroup_id => subgroup_id, :subtopic_shim => subtopic_shim) %>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-9 col-md-9 main">
|
||||
<div class="page-header">
|
||||
<h2><%= article_title %></h2>
|
||||
</div>
|
||||
<%= content %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="bottom" class="text-muted py-3" >
|
||||
<div class="foot">
|
||||
<div class="container">
|
||||
<div class="row footerlinks">
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">About</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Overview">About Fedora</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/sponsors">Sponsors</a></dd>
|
||||
<dd><a href="https://fedoramagazine.org">Fedora Magazine</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Legal:Main#Legal">Legal</a></dd>
|
||||
</dl>
|
||||
<ul class="list-inline">
|
||||
<li>
|
||||
<a href="https://www.facebook.com/TheFedoraProject" class="btn-social btn-outline"><i class="fa fa-fw fa-facebook"></i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://plus.google.com/112917221531140868607" class="btn-social btn-outline"><i class="fa fa-fw fa-google-plus"></i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://twitter.com/fedora" class="btn-social btn-outline"><i class="fa fa-fw fa-twitter"></i></a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title uppercase">Download</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://getfedora.org/en/workstation/download">Get Fedora Workstation</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/server/download">Get Fedora Server</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/atomic/download">Get Fedora Atomic</a></dd>
|
||||
<dd><a href="https://spins.fedoraproject.org">Fedora Spins</a></dd>
|
||||
<dd><a href="https://labs.fedoraproject.org">Fedora Labs</a></dd>
|
||||
<dd><a href="https://arm.fedoraproject.org">Fedora ARM<span class="sup">®</span></a></dd>
|
||||
<dd><a href="https://alt.fedoraproject.org/">Alternative Downloads</a></dd>
|
||||
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">Support</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Communicating_and_getting_help">Get Help</a></dd>
|
||||
<dd><a href="https://ask.fedoraproject.org/">Ask Fedora</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Common_F27_bugs">Common Bugs</a></dd>
|
||||
<dd><a href="https://developer.fedoraproject.org/">Fedora Developer Portal</a></dd>
|
||||
<dd><a href="https://docs.fedoraproject.org/f27/install-guide/index.html">Installation Guide</a></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">Join</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Join">Join Fedora</a></dd>
|
||||
<dd><a href="http://fedoraplanet.org">Planet Fedora</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/SIGs">Fedora SIGs</a></dd>
|
||||
<dd><a href="https://admin.fedoraproject.org/accounts/">Fedora Account System</a></dd>
|
||||
<dd><a href="https://fedoracommunity.org/">Fedora Community</a></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- /row of widgets -->
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-2">
|
||||
<div class="widget-body">
|
||||
<a href="https://www.redhat.com/"><img class="rh-logo" src="<%= File.join(images_path, "redhat-logo.png") %>" alt="Red Hat Logo" /></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-7">
|
||||
<div class="widget-body">
|
||||
<p class="sponsor">Fedora is sponsored by Red Hat.</p>
|
||||
<p class="sponsor"><a href="https://www.redhat.com/en/technologies/linux-platforms/articles/relationship-between-fedora-and-rhel">Learn more about the relationship between Red Hat and Fedora »</a></p>
|
||||
<p class="copy">© 2017 Red Hat, Inc. and others. Please send any comments or corrections to the <a href="https://pagure.io/fedora-docs/docs-fp-o">documentation team</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- /row of widgets -->
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
|
||||
<!-- Latest compiled and minified JavaScript -->
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
|
||||
<script src="<%= File.join(javascripts_path, "bootstrap-offcanvas.js") %>" type="text/javascript"></script>
|
||||
<script type="text/javascript">
|
||||
/*<![CDATA[*/
|
||||
$(document).ready(function() {
|
||||
$("[id^='topicGroup']").on('show.bs.collapse', function (event) {
|
||||
if (!($(event.target).attr('id').match(/^topicSubGroup/))) {
|
||||
$(this).parent().find("[id^='tgSpan']").toggleClass("fa-angle-right fa-angle-down");
|
||||
}
|
||||
});
|
||||
$("[id^='topicGroup']").on('hide.bs.collapse', function (event) {
|
||||
if (!($(event.target).attr('id').match(/^topicSubGroup/))) {
|
||||
$(this).parent().find("[id^='tgSpan']").toggleClass("fa-angle-right fa-angle-down");
|
||||
}
|
||||
});
|
||||
$("[id^='topicSubGroup']").on('show.bs.collapse', function () {
|
||||
$(this).parent().find("[id^='sgSpan']").toggleClass("fa-caret-right fa-caret-down");
|
||||
});
|
||||
$("[id^='topicSubGroup']").on('hide.bs.collapse', function () {
|
||||
$(this).parent().find("[id^='sgSpan']").toggleClass("fa-caret-right fa-caret-down");
|
||||
});
|
||||
});
|
||||
/*]]>*/
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -1,75 +0,0 @@
|
|||
# This configuration file dictates the organization of the topic groups and
|
||||
# topics on the main page of the doc site for this branch. Each record
|
||||
# consists of the following:
|
||||
#
|
||||
# --- <= Record delimiter
|
||||
# Name: Origin of the Species <= Display name of topic group
|
||||
# Dir: origin_of_the_species <= Directory name of topic group
|
||||
# Topics:
|
||||
# - Name: The Majestic Marmoset <= Topic name
|
||||
# File: the_majestic_marmoset <= Topic file under group dir +/-
|
||||
# - Name: The Curious Crocodile <= Topic 2 name
|
||||
# File: the_curious_crocodile <= Topic 2 file
|
||||
# - Name: The Numerous Nematodes <= Sub-topic group name
|
||||
# Dir: the_numerous_nematodes <= Sub-topic group dir
|
||||
# Topics:
|
||||
# - Name: The Wily Worm <= Sub-topic name
|
||||
# File: the_wily_worm <= Sub-topic file under <group dir>/<subtopic dir>
|
||||
# - Name: The Acrobatic Ascarid <= Sub-topic 2 name
|
||||
# File: the_acrobatic_ascarid <= Sub-topic 2 file under <group dir>/<subtopic dir>
|
||||
#
|
||||
# The ordering of the records in this document determines the ordering of the
|
||||
# topic groups and topics on the main page.
|
||||
---
|
||||
Name: Defensive Coding Guide
|
||||
Dir: en-US
|
||||
Topics:
|
||||
- Name: Book Information
|
||||
File: index
|
||||
- Name: Programming Languages
|
||||
Dir: programming-languages
|
||||
Topics:
|
||||
- Name: The C Programming Language
|
||||
File: C
|
||||
- Name: The C++ Programming Language
|
||||
File: CXX
|
||||
- Name: The Java Programming Language
|
||||
File: Java
|
||||
- Name: The Python Programming Language
|
||||
File: Python
|
||||
- Name: Shell Programming and bash
|
||||
File: Shell
|
||||
- Name: The Go Programming Language
|
||||
File: Go
|
||||
- Name: The Vala Programming Language
|
||||
File: Vala
|
||||
- Name: Specific Programming Tasks
|
||||
Dir: tasks
|
||||
Topics:
|
||||
- Name: Library Design
|
||||
File: Tasks-Library_Design
|
||||
- Name: File Descriptor Management
|
||||
File: Tasks-Descriptors
|
||||
- Name: File System Manipulation
|
||||
File: Tasks-File_System
|
||||
- Name: Temporary Files
|
||||
File: Tasks-Temporary_Files
|
||||
- Name: Processes
|
||||
File: Tasks-Processes
|
||||
- Name: Serialization and Deserialization
|
||||
File: Tasks-Serialization
|
||||
- Name: Cryptography
|
||||
File: Tasks-Cryptography
|
||||
- Name: RPM Packaging
|
||||
File: Tasks-Packaging
|
||||
- Name: Implementing Security Features
|
||||
Dir: features
|
||||
Topics:
|
||||
- Name: Authentication and Authorization
|
||||
File: Features-Authentication
|
||||
- Name: Transport Layer Security (TLS)
|
||||
File: Features-TLS
|
||||
- Name: Hardware Security Modules and Smart Cards
|
||||
File: Features-HSM
|
||||
- Name: Revision History
|
||||
File: Revision_History
|
16
antora.yml
Normal file
|
@ -0,0 +1,16 @@
|
|||
# Name will be mostly visible in the URL. Treat it as an indentifier.
|
||||
# Tip: If you want to use the local preview scripts that come with this repository, please change this value in the site.yml file as well. (under site/start_page)
|
||||
name: defensive-coding
|
||||
|
||||
# Title will be visible on the page.
|
||||
title: Defensive Coding Guide
|
||||
|
||||
# If you don't plan to have multiple versions of the docs (for example, to document multiple versions of some software), you can ignore this field. Otherwise, change "master" to a specific version.
|
||||
version: master
|
||||
|
||||
# We encourage you to name the index page as "index.adoc". If you absolutely have to use a different name, please reflect it here. You can ignore this field otherwise.
|
||||
start_page: ROOT:index
|
||||
|
||||
# This lists all the menu definitions of your component.
|
||||
nav:
|
||||
- modules/ROOT/nav.adoc
|
16
build.sh
Executable file
|
@ -0,0 +1,16 @@
|
|||
#!/bin/sh
|
||||
|
||||
if [ "$(uname)" == "Darwin" ]; then
|
||||
# Running on macOS.
|
||||
# Let's assume that the user has the Docker CE installed
|
||||
# which doesn't require a root password.
|
||||
docker run --rm -it -v $(pwd):/antora antora/antora --html-url-extension-style=indexify site.yml
|
||||
|
||||
elif [ "$(expr substr $(uname -s) 1 5)" == "Linux" ]; then
|
||||
# Running on Linux.
|
||||
# Let's assume that it's running the Docker deamon
|
||||
# which requires root.
|
||||
echo ""
|
||||
echo "This build script is using Docker to run the build in an isolated environment. You might be asked for a root password in order to start it."
|
||||
sudo docker run --rm -it -v $(pwd):/antora:z antora/antora --html-url-extension-style=indexify site.yml
|
||||
fi
|
141
index-main.html
|
@ -1,141 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags -->
|
||||
|
||||
<title>Fedora Defensive Coding Guide Docs Website</title>
|
||||
|
||||
<!-- Bootstrap -->
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap-theme.min.css">
|
||||
|
||||
<link rel="stylesheet" href="https://overpass-30e2.kxcdn.com/overpass.css">
|
||||
<link rel="stylesheet" href="_stylesheets/asciibinder.css">
|
||||
|
||||
|
||||
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
|
||||
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
|
||||
<!--[if lt IE 9]>
|
||||
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
|
||||
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
|
||||
<![endif]-->
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="page-header">
|
||||
<img src="_images/fedora.svg" class="img-responsive" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<h4><strong>Fedora Defensive Coding Guide Docs Site</strong></h4>
|
||||
<p>Test Build.</p>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<h5><strong>Fedora Defensive Coding Guide Docs</strong></h5>
|
||||
<div class="list-group">
|
||||
<a href="master/en-US/index.html" class="list-group-item">
|
||||
Documentation
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="bottom" class="text-muted py-3" >
|
||||
<div class="foot">
|
||||
<div class="container">
|
||||
<div class="row footerlinks">
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">About</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Overview">About Fedora</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/sponsors">Sponsors</a></dd>
|
||||
<dd><a href="https://fedoramagazine.org">Fedora Magazine</a></dd>
|
||||
<dd><a href="https:https://fedoraproject.org/wiki/Legal:Main#Legal">Legal</a></dd>
|
||||
</dl>
|
||||
<ul class="list-inline">
|
||||
<li>
|
||||
<a href="https:https://www.facebook.com/TheFedoraProject" class="btn-social btn-outline"><i class="fa fa-fw fa-facebook"></i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https:https://plus.google.com/112917221531140868607" class="btn-social btn-outline"><i class="fa fa-fw fa-google-plus"></i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https:https://twitter.com/fedora" class="btn-social btn-outline"><i class="fa fa-fw fa-twitter"></i></a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title uppercase">Download</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://getfedora.org/en/workstation/download">Get Fedora Workstation</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/server/download">Get Fedora Server</a></dd>
|
||||
<dd><a href="https://getfedora.org/en/atomic/download">Get Fedora Atomic</a></dd>
|
||||
<dd><a href="https://spins.fedoraproject.org">Fedora Spins</a></dd>
|
||||
<dd><a href="https://labs.fedoraproject.org">Fedora Labs</a></dd>
|
||||
<dd><a href="https://arm.fedoraproject.org">Fedora ARM<span class="sup">®</span></a></dd>
|
||||
<dd><a href="https://alt.fedoraproject.org/">Alternative Downloads</a></dd>
|
||||
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">Support</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Communicating_and_getting_help">Get Help</a></dd>
|
||||
<dd><a href="https://ask.fedoraproject.org/">Ask Fedora</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Common_F${global_variables.release['curr_id']}_bugs">Common Bugs</a></dd>
|
||||
<dd><a href="https://developer.fedoraproject.org/">Fedora Developer Portal</a></dd>
|
||||
<dd><a href="https://docs.fedoraproject.org/en-US/Fedora/${global_variables.release['curr_id']}/html/Installation_Guide">Installation Guide</a></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 col-xs-6 widget">
|
||||
<h3 class="widget-title">Join</h3>
|
||||
<div class="widget-body">
|
||||
<dl>
|
||||
<dd><a href="https://fedoraproject.org/wiki/Join">Join Fedora</a></dd>
|
||||
<dd><a href="http://fedoraplanet.org">Planet Fedora</a></dd>
|
||||
<dd><a href="https://fedoraproject.org/wiki/SIGs">Fedora SIGs</a></dd>
|
||||
<dd><a href="https://admin.fedoraproject.org/accounts/">Fedora Account System</a></dd>
|
||||
<dd><a href="https://fedoracommunity.org/">Fedora Community</a></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- /row of widgets -->
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-2">
|
||||
<div class="widget-body">
|
||||
<a href="https://www.redhat.com/"><img class="rh-logo" src="_images/redhat-logo.png" alt="Red Hat Logo" /></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-7">
|
||||
<div class="widget-body">
|
||||
<p class="sponsor">Fedora is sponsored by Red Hat.</p>
|
||||
<p class="sponsor"><a href="https://www.redhat.com/en/technologies/linux-platforms/articles/relationship-between-fedora-and-rhel">Learn more about the relationship between Red Hat and Fedora »</a></p>
|
||||
<p class="copy">© 2017 Red Hat, Inc. and others. Please send any comments or corrections to the <a href="https://fedorahosted.org/fedora-websites/">websites team</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- /row of widgets -->
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
|
||||
<!-- Include all compiled plugins (below), or include individual files as needed -->
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
|
||||
</body>
|
||||
</html>
|
Before Width: | Height: | Size: 7.6 KiB After Width: | Height: | Size: 7.6 KiB |
23
modules/ROOT/nav.adoc
Normal file
|
@ -0,0 +1,23 @@
|
|||
* xref:index.adoc[Book Information]
|
||||
* Programming Languages
|
||||
** xref:programming-languages/C.adoc[The C Programming Language]
|
||||
** xref:programming-languages/CXX.adoc[The C++ Programming Language]
|
||||
** xref:programming-languages/Java.adoc[The Java Programming Language]
|
||||
** xref:programming-languages/Python.adoc[The Python Programming Language]
|
||||
** xref:programming-languages/Shell.adoc[Shell Programming and bash]
|
||||
** xref:programming-languages/Go.adoc[The Go Programming Language]
|
||||
** xref:programming-languages/Vala.adoc[The Vala Programming Language]
|
||||
* Specific Programming Tasks
|
||||
** xref:tasks/Tasks-Library_Design.adoc[Library Design]
|
||||
** xref:tasks/Tasks-Descriptors.adoc[File Descriptor Management]
|
||||
** xref:tasks/Tasks-File_System.adoc[File System Manipulation]
|
||||
** xref:tasks/Tasks-Temporary_Files.adoc[Temporary Files]
|
||||
** xref:tasks/Tasks-Processes.adoc[Processes]
|
||||
** xref:tasks/Tasks-Serialization.adoc[Serialization and Deserialization]
|
||||
** xref:tasks/Tasks-Cryptography.adoc[Cryptography]
|
||||
** xref:tasks/Tasks-Packaging.adoc[RPM Packaging]
|
||||
* Implementing Security Features
|
||||
** xref:features/Features-Authentication.adoc[Authentication and Authorization]
|
||||
** xref:features/Features-TLS.adoc[Transport Layer Security (TLS)]
|
||||
** xref:features/Features-HSM.adoc[Hardware Security Modules and Smart Cards]
|
||||
* xref:Revision_History.adoc[Revision History]
|