Skip to content

Commit

Permalink
Release 2.0.3
Browse files Browse the repository at this point in the history
  • Loading branch information
beitler committed Mar 14, 2019
1 parent f8417ee commit c29b850
Show file tree
Hide file tree
Showing 35 changed files with 1,125 additions and 327 deletions.
25 changes: 25 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Changelog

## 2.0.3 - 2019-03-14

* sys_linux: Fixed stdout/stderr redirection for logging
* sys_linux: Added detection of implicit no-cups mode by uri files
* net: Fixed authtoken cleanup in http close
* cups: Fixed skipping credentials during rotation
* ral: Changed pipe read strategy in ral_master to allow partial reads
* tc: Fixed last-resort CUPS triggering from TC backoff
* lgwsim: Changed socket read strategy in lgwsim
* examples: Added CUPS example

## 2.0.2 - 2019-01-30

* cups: Fixed CUPS HTTP POST request. Now contains `Hosts` header.
* tc: Changed backoff strategy of LNS connection.
* ral: Fixed FSK parameters for TX
* ral: Added starvation prevention measure in lgw1 rxpolling loop.
* net: Fixed large file delivery in httpd/web.
* net: Fixed gzip detection heuristic in httpd/web

## 2.0.1 - 2019-01-07

* Initial public release.
25 changes: 14 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,13 @@ The following is a three-step quick start guide on how to build and run Station.
#### Step 1: Cloning the Station Repository

``` sourceCode
git clone https://github.com/lorabasics/station.git $STATION_REPO
git clone https://github.com/lorabasics/basicstation.git
```

#### Step 2: Compiling the Station Binary

``` sourceCode
cd $STATION_REPO
cd basicstation
make platform=rpi variant=std
```

Expand All @@ -62,7 +62,7 @@ The build process consists of the following steps:
#### Step 3: Running the Example Configuration on a Raspberry Pi

``` sourceCode
cd $STATION_REPO/examples/live-s2.sm.tc
cd examples/live-s2.sm.tc
RADIODEV=/dev/spidev0.0 ../../build-rpi-std/bin/station
```

Expand All @@ -76,12 +76,14 @@ Next,

* consult the help menu of Station via `station --help`,
* inspect the `station.conf` and `cups-boot.*` [example configuration files](/examples/live-s2.sm.tc),
* tune your local [configuration](https://doc.sm.tc/station/conf.html).
* tune your local [configuration](https://doc.sm.tc/station/conf.html),
* learn how to [compile Station](https://doc.sm.tc/station/compile.html) for your target platform.

Check out the other examples:

* [Simulation Example](/examples/simulation)
* [Station to Pkfwd Protocol Bridge Example](/examples/station2pkfwd)
* [Simulation Example](/examples/simulation) - An introduction to the simulation environment.
* [CUPS Example](/examples/cups) - Demonstration of the CUPS protocol within the simulation environment.
* [Station to Pkfwd Protocol Bridge Example](/examples/station2pkfwd) - Connect Basic Station to LNS supporting the legacy protocol.

## Usage

Expand Down Expand Up @@ -113,16 +115,17 @@ Usage: station [OPTION...]
then keep only FILE. If ROT is 1 then keep one
more old log file around. Overrides environment
STATION_LOGFILE.
-N, --no-tc Do not connect to a LNS. Only run CUPS functionality.
-N, --no-tc Do not connect to a LNS. Only run CUPS
functionality.
-p, --params Print current parameter settings.
-t, --temp=DIR Temp directory for frequently written files.
Default is /tmp. Overrides environment
STATION_TEMPDIR.
-x, --eui-prefix=id6 Turn MAC address into EUI by adding this prefix.
If the argument has value ff:fe00:0 then the EUI is
formed by inserting FFFE in the middle. If absent
use MAC or routerid as is. Overrides environment
STATION_EUIPREFIX.
If the argument has value ff:fe00:0 then the EUI
is formed by inserting FFFE in the middle. If
absent use MAC or routerid as is. Overrides
environment STATION_EUIPREFIX.
-?, --help Give this help list
--usage Give a short usage message
-v, --version Print station version.
Expand Down
2 changes: 1 addition & 1 deletion VERSION.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2.0.2
2.0.3
268 changes: 268 additions & 0 deletions examples/cups/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,268 @@
# CUPS Protocol Example

Station implements a gateway management protocol for managing credentials and firmware updates. Read more about it [here](https://doc.sm.tc/station/cupsproto.html).

This example demonstrates the common scenario of credentials bootstrapping: In the factory, a set of gateways are personalized with initial credentials to a central CUPS server instance (say `cups-0`). Their final destination is not yet known at the time of manufacturing. After one of these gateways is deployed and powered-on the first time, it has to be pointed to and provided credentials for its final LNS (say `tc-0`) in a secure way. Since `cups-0` is operated by an independent third party, it does not have access to the credentials needed to connect to `tc-0`. Therefore, the gateway is first redirected to the CUPS server (`cups-1`) which is operated by the owner of `tc-0` and can therefore provide the final credentials and potentially the latest firmware update.

Using the Station simulation environment, this example implements the two CUPS servers `cups-0` and `cups-1`, as well as the LNS server `tc-0` and configures them to perform the credentials bootstrapping procedure described above. For the purpose of this example, the identities of the three entities are rooted each in a different CA. Client and server credentials are signed by the same CA.

```
CUPS "A" CA
+- cups-0.{crt,key} server auth
+- cups-router-1.{crt,key} client auth
CUPS "B" CA
+- cups-1.{crt,key} server auth
+- cups-router-1.{crt,key} client auth
TC CA
+- muxs-0.{crt,key} server auth
+- infos-0.{crt,key} server auth
+- tc-router-1.{crt,key} client auth
```

**Disclaimer:** The focus of this example is to demonstrate the capabilities of the CUPS protocol based on a common usage scenario for gateway management. For this purpose and the sake of simplicity, the PKI employed in this example is setup in very simple way and does not resemble a production grade PKI.

## Relevant Files

* `sim.py`: Mockup server-side implementations of the CUPS and LNS Station protocols.
* `prep.sh`: Setup script for generating keys, certificates and configuration files for the credentials bootstrapping scenario.
* `emulate.sh`: A script containing a sequence of cURL requests to CUPS, emulating the behavior of Station under this scenario. This can be used to investigate the exact payloads exchanged during the call sequence.
* `makefile`: Top level makefile which can be used to setup and run the simulation.

## Prerequisites

The simulation example requires

* Python 3.5+
* Python packages according to `requirements.txt`
* make, bash, curl, openssl, gzip, xxd
* Optional: tmux

A possible way to setup a compatible python environment is using `virtualenv` and `pip`:

```
virtualenv -p python3.6 pyenv
. pyenv/bin/activate
pip install -r requirements.txt
```

## Usage

The CUPS example is controlled via a makefile with multiple targets:

* `make station`: Build the `testsim` station variant.
* `make prep`: Setup the expected directory structure (keys, certificates, config) without executing the simulation.
* `make sim`: Run the simulation in a single process. Log output of all components is interleaved in one terminal
* `make tmux`: Run the simulation in multiple processes inside different panes of a tmux split window.
* `make emulate`: Execute the call sequence via a set of cURL commands, emulating the behavior of Station in this scenario.
* `make clean`: Bring local directory into initial state.

## Explanation

In order to understand what is going on, let's dissect the log output produced by the `emulate` target. For the sake of clarity the log output shown here has slightly reduced verbosity.

### Startup
```
# make emulate
./prep.sh
== Build PKI ==
cups-0/cups-0.crt: OK
cups-0/cups-router-1.crt: OK
cups-1/cups-1.crt: OK
cups-1/cups-router-1.crt: OK
tc-0/muxs-0.crt: OK
tc-0/infos-0.crt: OK
tc-0/tc-router-1.crt: OK
== Prepare FW Update 1.0.0 -> 2.0.0 ==
```

The `emulate` target first executes the `prep.sh` script which sets up the folder structure as expected by the simulation. First, the three self-signed CA certificates are generated and used to sign the certificates of all our server entities `cups-0`, `cups-1`, `tc-0`, as well as the client certificates for `router-1` expected by each of them. A signing key pair is generated and a signed updated is placed in `cups-1`. The public part of the signing key is copied to the Station home directory `./shome`. The final directory structure will look like this:

```
.
├── cups-0
│ ├── cups-0.crt
│ ├── cups-0.key
│ ├── cups-0.trust
│ ├── cups.ca
│ ├── cups-router-1.cfg
│ ├── cups-router-1.crt
│ ├── cups-router-1.key
│ └── cups-router-1.trust
├── cups-1
│ ├── 2.0.0.bin
│ ├── 2.0.0.bin.sig-0
│ ├── cups-1.crt
│ ├── cups-1.key
│ ├── cups-1.trust
│ ├── cups.ca
│ ├── cups-router-1.cfg
│ ├── cups-router-1.crt
│ ├── cups-router-1.key
│ ├── cups-router-1.trust
│ └── sig-0.key
├── shome
│ ├── cups.crt
│ ├── cups.key
│ ├── cups.trust
│ ├── cups.uri
│ ├── sig-0.key
│ ├── station.conf
│ └── version.txt
├── tc-0
│ ├── infos-0.crt
│ ├── infos-0.key
│ ├── infos-0.trust
│ ├── muxs-0.crt
│ ├── muxs-0.key
│ ├── muxs-0.trust
│ ├── tc.ca
│ ├── tc-router-1.crt
│ ├── tc-router-1.key
│ └── tc-router-1.trust
└── upd-sig
├── sig-0.prime256v1.pem
└── sig-0.prime256v1.pub
```

Once the `prep.sh` script completed, the `emulate.sh` script will start the server simulation if no running CUPS services were detected on localhost.

```
./emulate.sh
Starting CUPS.
LgwSimServer starting...
Starting INFOS (tc-0/infos-0) on Port 6038 (muxsuri=wss://localhost:6039/router)
Starting MUXS (tc-0/muxs-0) on Port 6039
Starting CUPS (cups-0/cups-0) on Port 6040
Starting CUPS (cups-1/cups-1) on Port 6041
```

Before the initial request, a list of client credentials and their CRC32 hashes is shown. These CRC32 hashes serve as identifiers for the credentials sets in the CUPS protocol. Since all keys are generated by `prep.sh`, these hashes will differ in your case:

```
CRC32 0xF13E8FC2 (4047409090) shome/sig-0.key
CRC32 0xAFC40ED3 (2948861651) cups-0/cups-router-1.{trust,crt,key}
CRC32 0x22220992 (572656018) cups-1/cups-router-1.{trust,crt,key}
CRC32 0xE0F91F83 (3774422915) tc-0/tc-router-1.{trust,crt,key}
```

An empty credentials set corresponds to a zero-byte sequence of length 12, which yields a non-zero CRC32.

```
CRC32 0x7BD5C66F (2077607535) _empty_set_
```

### Request 1: CUPS Redirection

```
==== #1 [CUPS-0] REQUEST ===================
{
"router": "::1",
"model": "linux",
"package": "1.0.0",
"station": "Emulated Station",
"cupsUri": "https://localhost:6040",
"tcUri": "",
"cupsCredCrc": 2948861651,
"tcCredCrc": 2077607535,
"keys": [ 4047409090 ]
}
==== #1 [CUPS-0] RESPONSE ===================
CUPS: No target version configured for this router. No update.
CUPS: No fw update required
< CUPS Response:
cupsUri : b'https://localhost:6041' <- [https://localhost:6040]
tcUri : b'' -- []
cupsCred: 911 bytes -- [22220992] <- [AFC40ED3]
tcCred : 0 bytes -- [7BD5C66F]
sigCrc : 00000000
sig : 0 bytes
fw : 0 bytes -- [1.0.0]
HTTP/1.1 200 OK
Content-Length: 947
Content-Type: application/octet-stream
Server: Python/3.6 aiohttp/2.3.9
[ Binary dump of response body ]
```

In the first request to `cups-0`, Station receives a new CUPS URI and new CUPS credentials for connecting to `cups-1`.

### Request 2: LNS Credentials and Firmware Update

```
==== #2 [CUPS-1] REQUEST ===================
{
"router": "::1",
"model": "linux",
"package": "1.0.0",
"station": "Emulated Station",
"cupsUri": "https://localhost:6041",
"tcUri": "",
"cupsCredCrc": 572656018,
"tcCredCrc": 2077607535,
"keys": [ 4047409090 ]
}
==== #2 [CUPS-1] RESPONSE ===================
CUPS: Target version: 2.0.0 (cups-1/2.0.0.bin)
CUPS: Found signing key cups-1/sig-0.key -> CRC F13E8FC2
CUPS: Found signature cups-1/2.0.0.bin.sig-0
CUPS: Found matching signing key with CRC F13E8FC2
< CUPS Response:
cupsUri : b'' -- [https://localhost:6041]
tcUri : b'wss://localhost:6038' <- []
cupsCred: 0 bytes -- [22220992]
tcCred : 900 bytes -- [E0F91F83] <- [7BD5C66F]
sigCrc : F13E8FC2
sig : 74 bytes
fw : 83 bytes -- [2.0.0] <- [1.0.0]
HTTP/1.1 200 OK
Content-Length: 1091
Content-Type: application/octet-stream
Server: Python/3.6 aiohttp/2.3.9
[ Binary dump of response body ]
```

The second request is directed to `cups-1`. The response contains a firmware update (in this case a bash script) together with a signature. The signature originates from the private key which corresponds to the one of the public keys identified by the key CRCs in the `keys` list of the request. This mechanism allows the server to choose out of multiple signatures the one which can be verified by the gateway. The response also contains the URI and credentials of the LNS endpoint (`tcUri` and `tcCred`).

### Request 3: Steady State

```
==== #3 [CUPS-1] REQUEST ===================
{
"router": "::1",
"model": "linux",
"package": "2.0.0",
"station": "Emulated Station",
"cupsUri": "https://localhost:6041",
"tcUri": "wss://localhost:6038",
"cupsCredCrc": 572656018,
"tcCredCrc": 3774422915,
"keys": [ 4047409090 ]
}
==== #3 [CUPS-1] RESPONSE ===================
CUPS: Target version: 2.0.0 (cups-1/2.0.0.bin)
CUPS: Found signing key cups-1/sig-0.key -> CRC F13E8FC2
CUPS: Found signature cups-1/2.0.0.bin.sig-0
CUPS: No fw update required
< CUPS Response:
cupsUri : b'' -- [https://localhost:6041]
tcUri : b'' -- [wss://localhost:6038]
cupsCred: 0 bytes -- [22220992]
tcCred : 0 bytes -- [E0F91F83]
sigCrc : 00000000
sig : 0 bytes
fw : 0 bytes -- [2.0.0]
HTTP/1.1 200 OK
Content-Length: 14
Content-Type: application/octet-stream
Server: Python/3.6 aiohttp/2.3.9
00000000: 0000 0000 0000 0000 0000 0000 0000 ..............
```

The third request is answered with an all-zero response, meaning that the condition of the gateway corresponds to the target state expected by the CUPS server. The all-zero response puts Station into a low-dutycycle re-sync mode.
Loading

0 comments on commit c29b850

Please sign in to comment.