(no commit message)
[devwiki.git] / design / tlv.mdwn
1 ## Rationale for the TLV abstraction  
2
3 hartmans: Luke, do you have opinions on what we want to do to the tokens for the target name stuff and SNI?  
4 lukeh: will we be sending a bunch of arbitrary attributes like the acceptor does? like GSS-Asserted-Acceptor-Service-Name  
5 lukeh: what's SNI?  
6 hartmans: I think it means that the first token from initiator to acceptor (which I guess is useless today) probably wants to be a TLV token.  
7 lukeh: yeah, I followed that on the mailing list but didn't implement as I was busy with other stuff  
8 lukeh: that sounds reasonable, I guess it would require some reorganisation  
9 lukeh: why do we want to send the target name?  
10 hartmans: If you're getting a target name back then you probably want a TLV token for the first acceptor to initiator. But today that also includes an eap identity request, right?  
11 lukeh: yes  
12 hartmans: The question is do we want to TLV all the EAP tokens at that point?  
13 lukeh: hmm.  
14 lukeh: well either way I guess has merit  
15 hartmans: The down side of TLVing everything is that then you can have news ways of having mallformed tokens.  
16 lukeh: but I probably need to understand things better  
17 lukeh: why does the acceptor send the target name back?  
18 lukeh: I'm starting from a point of not understanding what is wrong with the existing protocol :)  
19 hartmans: OK, so there are two different usages.  
20 lukeh: as my understanding is we get the acceptor name back anyway in the EAP CB attributes  
21 hartmans: 1) server name indication: the initiator knows the target name, but the acceptor may server multiple names.  
22 hartmans: Here, the acceptor wants to know what name the initiator is calling.  
23 \*\*\*hartmans needs to think through the gss implications of what names the server accepts with Nico  
24 hartmans: The other usage is null target name: the initiator doesn't know the target name but will look at the target name in the established context and see if it likes it.  
25 hartmans: However in our mechanism, the initiator needs to learn the target name early so it can channel bind to it in EAP so it actually can believe the result.  
26 hartmans: No, we don't get the acceptor name back in the eap CB.  
27 hartmans: We \*send\* it in the eap cb and get back an indication about whether the server considered it in the CB result.  
28 lukeh: ah.  
29 hartmans: We don't get the value back.  
30 hartmans: The other thing I'm wondering.  
31 hartmans: Is there any actual information in the eap identity request?  
32 hartmans: Could we just fake that packet and save a round trip?  
33 lukeh: hmm, good point  
34 Josh: we need the realm for routing  
35 lukeh: that's in the response, not the request.  
36 hartmans: That's in the identity response, right?  
37 Josh: oh I mis-read  
38 lukeh: yeah, Sam, that's an interesting point  
39 lukeh: it didn't occur to me to do that  
40 Josh: that would be a violation of the EAP SM, no?  
41 lukeh: possibly  
42 lukeh: I mean, the initiator would generate it itself rather than getting it from the acceptor  
43 lukeh: certainly it's easier to understand in the current protocol  
44 lukeh: but whether it's not worth optimising away is another question.  
45 hartmans: Josh, it all depends on where you draw the layers.  
46 Josh: take your point  
47 hartmans: Note that on the radius server, the EAP SM never generates that packet... The NAS generates that one, right?  
48 Josh: right  
49 hartmans: I'm arguing we're basically doing the same thing. Rather than having the NAs generate that, we're asking the client to generate that and feed it to its own state machine.  
50 hartmans: That only works if the packet is content free.  
51 Josh: what's the advantage to that?  
52 lukeh: save a roundtrip  
53 lukeh: because currently the initiator sends an empty token  
54 lukeh: just to poke things into action  
55 Josh: IIRC, the data field can be used in the EAP-Identity/Request, but rarely is.  
56 lukeh: hmm, if we are optimising something away that might be useful  
57 hartmans: If it is used, what's it used for.  
58 lukeh: then that may be bad.  
59 hartmans: Sadly, Jari is not online. (He's the obvious eap expert in my buddy list)  
60 Josh: I think we have previously floated the idea of using that data field for federation selection  
61 lukeh: heh, can we shove the acceptor name in there  
62 hartmans: Josh, I think that the changes we're talking about for target name null and for sni will give us the rope we need for federation selection.  
63 \*\*\*hartmans will investigate what that's useful for.  
64 lukeh: please define SNI  
65 lukeh: server name indication  
66 lukeh: ?  
67 Josh: True, and cleaner I believe.  
68 hartmans: Luke if you're going to have an opinion on what tokens should be TLVed, please do so preferably before IETF.  
69 hartmans: yes  
70   
71 ## Actual Design of resulting TLV implementation  
72   
73 lukeh: OK, so the TLV code runs on a table of ( input token, output token, valid states, flags, callback )  
74 lukeh: there are still a few too many special cases to be completely in love with it  
75 lukeh: but hopefully after a few more days of hacking it will get there  
76 lukeh: I've added some debug tokens in the initial leg to test that that works  
77 lukeh: the previous extension tokens (GSS CB, reauth) are now just, obviously, TLVs in the last leg  
78 lukeh: there is now only one \*GSS\* token for context establishment, TOK_TYPE_ESTABLISH_CONTEXT  
79 lukeh: and a bunch of "inner" token types  
80 lukeh: #define ITOK_TYPE_CONTEXT_ERR           0x00000001  
81     #define ITOK_TYPE_ACCEPTOR_NAME_REQ     0x00000002  
82     #define ITOK_TYPE_ACCEPTOR_NAME_RESP    0x00000003  
83     #define ITOK_TYPE_EAP_RESP              0x00000004  
84     #define ITOK_TYPE_EAP_REQ               0x00000005  
85     #define ITOK_TYPE_GSS_CHANNEL_BINDINGS  0x00000006  
86     #define ITOK_TYPE_REAUTH_CREDS          0x00000007  
87     #define ITOK_TYPE_REAUTH_REQ            0x00000008  
88     #define ITOK_TYPE_REAUTH_RESP           0x00000009  
89     #define ITOK_TYPE_VERSION_INFO          0x0000000A  
90     #define ITOK_TYPE_VENDOR_INFO           0x0000000B  
91     #define ITOK_FLAG_CRITICAL              0x80000000  /\* critical, wire flag \*/  
92   
93 lukeh: s/last leg/last round trip/  
94 hartmans: What do you mean by token types in the table?  
95 hartmans: Do you mean that a given callback can only produce one output token type, or something more than that?  
96 lukeh: a given callback can only produce one output token type  
97 lukeh: true, a callback could have returned a set of tokens  
98 lukeh: perhaps that would be desirable  
99 lukeh: but as long as the state can be passed through the context or credential object  
100 lukeh: the same effect can be achieved  
101 hartmans: I think that simplicity is good for now.  
102 hartmans: OK, that implementation makes sense.  
103 lukeh: the trunk is simplicity :-)  
104 lukeh: although one nice thing is that the state machine walker is now shared between initiator and acceptor.  
105 lukeh: so I may have reduced the line count actually.  
106 lukeh: meh, about the same.  
107 hartmans: So, can a callback return success and no token?  
108 lukeh: yeah.  
109 hartmans: good.  
110 lukeh: (well, CONTINUE, or COMPLETE)  
111 lukeh: I needed that for a couple of cases.  
112 lukeh: first, if you transit states and don't emit a token  
113 hartmans: and anyone returning continue means overall result is continue?  
114 hartmans: anyone returning error means overall result is error?  
115 lukeh: (hang on)  
116 lukeh: e.g. going from completing the EAP stage (if no token emitted) to the extension stage  
117 hartmans: Does that produce a round-trip or does it simply re-run the packet in the new state combining the output?  
118 lukeh: (I'm going to answer your questions in order asked)  
119 hartmans: That (state transition) was the case that was making me think you'd need the no token logic  
120 lukeh: also, if you have a set of optional tokens (e.g. extensions) you need something to mark the end and transit the state.  
121 hartmans: Yes, answering in order asked is fine.  
122 lukeh: The very final callback that marks the context established returns COMPLETE  
123 lukeh: Others return CONTINUE on success or an error.  
124 lukeh: Returning an error means the overall result is an error and, on the acceptor side, an error token may be generated (this is done at the state machine layer)  
125 lukeh: In case of a state transition when there is no output token, then the next set of callbacks are called with no input token  
126 lukeh: to avoid regurgitating the input token from the previous state  
127 hartmans: OK that last is non-obvious to me (calling nwith no input token)  
128 lukeh: so, basically, tokens are emitted to the peer  
129 hartmans: Can I see the table? It might be more clear there.  
130 lukeh: when we've run out of callbacks or we transit states and have a token to send  
131 lukeh: (more or less, there are a couple of exceptions to handle things like sending no tokens on the initial context token in order to poke the acceptor into sending us an EAP request)  
132 lukeh: (rather than sending an empty EAP response from the initiator, as semantically that did not seem correct)  
133 lukeh: (although perhaps it is, who knows.)  
134 lukeh: if you checkout tlv  
135 lukeh: look for eapGssInitiatorSm in init_sec_context.c  
136 lukeh: and the corresponding one for the acceptor.  
137 lukeh: note: the states are bitmasks.  
138 lukeh: there's some verbose commenting in init_sm.c too.  
139 hartmans: Ah, that makes so much more sense from the table  
140 hartmans: This is quite clever.  
141 lukeh: Hmm, it still doesn't feel \*quite\* right. Too many exceptions. I suspect if that if I was doing it from scratch rather than refactoring it might look different. But, it seems to work for now. Will revise over coming days.  
142 lukeh: I think it is ugly because it collapses the state and token dimensions into a single one.  
143 lukeh: However it does make it easier to have tokens that support multiple states.  
144 lukeh: Although there are some limitations with that (the dispatch table is not retraversed after a state change so it effectively only works for exception tokens; of course, that's easily fixed)  
145 hartmans: So, we depend on the EAP machine keeping us in sync between the initiator and acceptor?  
146 hartmans: Not a problem, just confirming I understand.  
147 hartmans: What do you mean state and token are combined? They are separate columns in the table as far as I can tell  
148 lukeh: it's not a 2 dimensional array.  
149 lukeh: they are separate columns yes  
150 lukeh: re: depending on the EAP machine  
151 hartmans: Ah.  
152 lukeh: yes, I guess we do, what else could one do?  
153 lukeh: it's a black box  
154 lukeh: I don't know what happens yet if the EAP machine emits a token on success, I don't think that's possible though  
155 lukeh: I need to check  
156 \*\*\*hartmans has too much of a relational database mindset to think of that as more than an efficiency issue  
157 lukeh: yeah, I never used relational databases, so I never had that mindset  
158 hartmans: I think depending on EAP to be consistent is fine.  
159 hartmans: We could actually echo the eap state in some sort of market token. That would be far far worse.  
160 lukeh: So, adding a new token that doesn't change the state is fairly easy.  
161 lukeh: You just need to be careful where you put it in the table  :)  
162 lukeh: It needs to be before the state changing entry.  
163 lukeh: You can set the critical/required flags as desired.  
164 lukeh: Some care is likely necessary to avoid colliding with the reauthentication path. But I think that's fairly easy.  
165 lukeh: In my initial implementation I had overloaded the GSS status codes to mean various things, but in the end that got quite ugly.  
166 lukeh: So I went with the callbacks performing the state changes themselves plus a flag to indicate a few exceptional things (e.g. get-out now)  
167 hartmans: Presumably error always means get out now?  
168 lukeh: yes  
169 lukeh: if you want to get out now on CONTINUE, you need to either  
170 lukeh: a) change state and emit a token  
171 lukeh: b) change state and set FORCE_SEND_TOKEN (this is used to handle the initial case where we poke the acceptor without sending an inner token)  
172 lukeh: c) set STOP_EVAL - this is not used yet  
173 lukeh: the above applies to COMPLETE as well as CONTINUE  
174 lukeh: there are some sanity checks to make sure COMPLETE only happens when state becomes ESTABLISHED  
175 lukeh: see SM_ASSERT_VALID  
176 hartmans: OK, and we can remove an exception if we decide it's OK for us to fake the eap request identity  
177 lukeh: ah yes  
178 hartmans: This is really cool.