|
| 1 | +# Message Flow between Application and TLS Pool |
| 2 | + |
| 3 | +> *Especially when using the Asynchronous API, where messages |
| 4 | +> are sent directly, it is useful to have an idea of what to |
| 5 | +> send and what to expect.* |
| 6 | +
|
| 7 | +The most important flow to understand is the `STARTTLS` handling flow. |
| 8 | +This goes through a few stages, and can be captured in a simple |
| 9 | +state diagram. The simplified synchronous API captures most of |
| 10 | +this in its own logic, but with the Asynchronous API you need to |
| 11 | +do it yourself, and so, you need to understand it. |
| 12 | + |
| 13 | + |
| 14 | + |
| 15 | +So what does this mean? |
| 16 | + |
| 17 | + * Arrows are messages; `req:XXX` is short for a request message |
| 18 | + to the TLS Pool, with the command set to `PIOC_XXX_V2` and |
| 19 | + `cb:YYY` is short for a callback in response to a request, |
| 20 | + when the TLS Pool sends an answer or an intermediate query, |
| 21 | + with the command set to `PIOC_YYY_V2`. |
| 22 | + |
| 23 | + * Look at the colors of the traffic light; red makes you wait |
| 24 | + because the TLS Pool is at work; yellow is for the processing |
| 25 | + of a callback in which the TLS Pool asks for additional info; |
| 26 | + green is when you are free to act. Of course the colours only |
| 27 | + reflect the handling of one connection; the Asynchronous API |
| 28 | + and the TLS Pool welcome progress on other connections. |
| 29 | + |
| 30 | + * Not shown are `cb:ERROR` responses. Simply be prepared to |
| 31 | + receive them at any time. You can also send an `ERROR` to |
| 32 | + the TLS Pool. You would do this when you are not willing |
| 33 | + to respond to a callback. Simply abandoning the callback |
| 34 | + without closing the file descriptor would leave a process |
| 35 | + hanging, which could perhaps cause resource contention. |
| 36 | + |
| 37 | +The transitions are described in detail in `<tlspool/commands.h>` |
| 38 | +and will not be repeated here. The states in the diagram can |
| 39 | +be described as follows: |
| 40 | + |
| 41 | + * **Unprotected** are those connections that have not started |
| 42 | + TLS and exchange information in plain view. |
| 43 | + |
| 44 | + * **Identity & Features** is a simple negotiation of your |
| 45 | + application's dependency on the TLS Pool. The interaction |
| 46 | + is optional, and since it always runs in the same manner |
| 47 | + it has no value to do repeatedly. |
| 48 | + |
| 49 | + * **Introduced** is when your application's idea of the |
| 50 | + time-stamped identity (thus version) and desired optional |
| 51 | + features have been negotiated, and your application knows |
| 52 | + if it can move forward. |
| 53 | + |
| 54 | + * **TLS Pool handshake** is when the TLS Pool is exchanging |
| 55 | + the messages to secure a connection. It should not need |
| 56 | + your involvement, since you sent it the socket over which |
| 57 | + it could run the handshake. |
| 58 | + |
| 59 | + * **Local Identity Check** is a callback from the TLS Pool, |
| 60 | + in which it asks your application, which presumably is a |
| 61 | + server, if it will agree with a proposed identity. This |
| 62 | + is taken from the Server Name Indication and it is the |
| 63 | + common mechanism by which a multi-named server can show |
| 64 | + whether a host name has been configured for action. |
| 65 | + |
| 66 | + * **Reconnect** is the point where the former plaintext |
| 67 | + handle, which has become a TLS-protected handle, is |
| 68 | + replaced with a new plaintext handle. This normally |
| 69 | + is constructed with `socketpair(2)`; one end is the |
| 70 | + new plaintext socket for your application and the |
| 71 | + other end is for the TLS Pool. |
| 72 | + |
| 73 | + * **Protected by TLS** may feel like your application is |
| 74 | + still doing plaintext operations, but the TLS Pool sits |
| 75 | + between you and the network. It will silently encrypt |
| 76 | + and decrypt the traffic to and from your peer. |
| 77 | + |
| 78 | +Needless to say that **Unprotected** is the stage before the |
| 79 | +`STARTTLS` operation that is built into many protocols. |
| 80 | +When a separate port has been allocated for a TLS version |
| 81 | +of a protocol, then this stage is departed immediately, |
| 82 | +as if `STARTTLS` was agreed on immediately after the |
| 83 | +connection. |
| 84 | + |
| 85 | + |
| 86 | +## Callbacks and State Diagrams combine well |
| 87 | + |
| 88 | +One might consider callbacks as a moment to quickly |
| 89 | +make a small decision. This is indeed how the TLS Pool |
| 90 | +works. A similar thing might be said about DNS lookups |
| 91 | +in a resolver like Unbound. |
| 92 | + |
| 93 | +An event loop such as libev, libevent or libuv can be |
| 94 | +used to make such callbacks when an event arrives, and |
| 95 | +this the `tlspool_async_process()` call was designed |
| 96 | +for that kind of behaviour. |
| 97 | + |
| 98 | +A source file handling a state diagram of this kind |
| 99 | +may end up being a sequence of callback handlers that |
| 100 | +continue until they have initiated other work that |
| 101 | +can lead to the following callback. All that is needed |
| 102 | +then, is a data structure to share the state between |
| 103 | +these callbacks. |
| 104 | + |
| 105 | +A somewhat extreme example of this idea is our |
| 106 | +[KXOVER](https://github.com/arpa2/kxover) |
| 107 | +project, which migrated to a TLS-based approach and |
| 108 | +for which some of the TLS Pool development is driven |
| 109 | +forward! Specifically look at the files `src/kxover.c` |
| 110 | +and `src/tlspool.c` for examples. |
0 commit comments