Kannel: Open Source WAP and SMS gateway  $Revision: 5037 $
wtls_state-decl.h
Go to the documentation of this file.
1 /* ====================================================================
2  * The Kannel Software License, Version 1.0
3  *
4  * Copyright (c) 2001-2016 Kannel Group
5  * Copyright (c) 1998-2001 WapIT Ltd.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in
17  * the documentation and/or other materials provided with the
18  * distribution.
19  *
20  * 3. The end-user documentation included with the redistribution,
21  * if any, must include the following acknowledgment:
22  * "This product includes software developed by the
23  * Kannel Group (http://www.kannel.org/)."
24  * Alternately, this acknowledgment may appear in the software itself,
25  * if and wherever such third-party acknowledgments normally appear.
26  *
27  * 4. The names "Kannel" and "Kannel Group" must not be used to
28  * endorse or promote products derived from this software without
29  * prior written permission. For written permission, please
30  * contact org@kannel.org.
31  *
32  * 5. Products derived from this software may not be called "Kannel",
33  * nor may "Kannel" appear in their name, without prior written
34  * permission of the Kannel Group.
35  *
36  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39  * DISCLAIMED. IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS
40  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
41  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
42  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
43  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
44  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
45  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
46  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
47  * ====================================================================
48  *
49  * This software consists of voluntary contributions made by many
50  * individuals on behalf of the Kannel Group. For more information on
51  * the Kannel Group, please see <http://www.kannel.org/>.
52  *
53  * Portions of this software are based upon software originally written at
54  * WapIT Ltd., Helsinki, Finland for the Kannel project.
55  */
56 
57 /*
58  * Macro calls to generate rows of the state table. See the documentation for
59  * guidance how to use and update these.
60  *
61  * by Nick Clarey <nclarey@3glab.com>
62  * Nikos Balkanas, Inaccess Networks (2009)
63  */
64 
65 STATE_NAME(NULL_STATE)
66 STATE_NAME(CREATING)
67 STATE_NAME(CREATED)
68 STATE_NAME(EXCHANGE)
69 STATE_NAME(COMMIT)
70 STATE_NAME(OPENING)
71 STATE_NAME(OPEN)
72 
73 /* If the packet is a ClientHello */
74 /* We only include this case in state NULL; the others are handled by the
75  wtls_find_or_create function */
76 
77 ROW(NULL_STATE,
79  packet_contains_clienthello (event->u.T_Unitdata_Ind.pdu_list),
80  {
81  clientHello(event, wtls_machine);
82  },
83  CREATING)
84 
85 ROW(NULL_STATE,
87  1,
88  {
89  WAPEvent *alert;
90 
91  error(0, "send_alert ~> Critical alert (unexpected_message), while waiting for client hello.");
93  alert->u.SEC_Terminate_Req.addr_tuple = wap_addr_tuple_duplicate(event->u.T_Unitdata_Ind.addr_tuple);
94  alert->u.SEC_Terminate_Req.alert_desc = unexpected_message;
95  alert->u.SEC_Terminate_Req.alert_level = critical_alert;
96  wtls_dispatch_event(alert);
97  },
98  CREATING)
99 
100 /* Creating State */
101 /* Termination */
102 ROW(CREATING,
104  1,
105  {
106 /* Send off a T_Unitdata_Req containing an alert as specified */
107  send_alert(event, wtls_machine);
108  },
109  NULL_STATE)
110 
111 /* Exception */
112 ROW(CREATING,
114  1,
115  {
116  /* Send off a T_Unitdata_Req containing an exception as specified */
117  send_alert(event, wtls_machine);
118  },
119  CREATING)
120 
121 /* Create Response - create a buffer with a "ServerHello" and possibly a Certificate or something else */
122 ROW(CREATING,
123  SEC_Create_Res,
124  1,
125  {
126  serverHello(event, wtls_machine);
127  },
128  CREATED)
129 
130 /* Created State */
131 /* Exchange Request - Full Handshake will be performed */
132 ROW(CREATED,
134  1,
135  {
138 
139  /* Assert that the PDU list is valid */
140  gw_assert(wtls_machine->packet_to_send != NULL);
141 
142  /* We'll also need a Server Key Exchange message */
143  serverKeyXchgPDU = wtls_pdu_create(Handshake_PDU);
144  serverKeyXchgPDU->rlen = 1;
145  serverKeyXchgPDU->snMode = wtls_machine->sequence_number_mode? 1: 0;
147  serverKeyXchgPDU->u.handshake.server_key_exchange =
148  (ServerKeyExchange*) gw_malloc(sizeof(ServerKeyExchange));
149  serverKeyXchgPDU->u.handshake.server_key_exchange->param_spec = NULL;
150 
151  /* Allocate memory for the RSA component */
152  debug("wtls: ", 0,"Going to get the RSA public key...");
155  debug("wtls: ", 0,"...got it.");
156  add_pdu(wtls_machine, serverKeyXchgPDU);
157  wtls_pdu_destroy(serverKeyXchgPDU);
158  debug("wtls: ", 0,"in CREATED - just added pdu...");
159 
160  /* Add some more PDUs to the List - potentially a ServerKeyExchange,
161  a CertificateRequest and a ServerHelloDone */
162  /* Just a ServerHelloDone for now */
163  serverHelloDonePDU = wtls_pdu_create(Handshake_PDU);
164  serverHelloDonePDU->rlen = 1;
165  serverHelloDonePDU->snMode = wtls_machine->sequence_number_mode? 1: 0;
166  serverHelloDonePDU->u.handshake.msg_type = server_hello_done;
167  add_pdu(wtls_machine, serverHelloDonePDU);
168  wtls_pdu_destroy(serverHelloDonePDU);
169 
170  /* Translate the buffer and address details into a T_Unitdata_Req
171  * and send it winging it's way across the network */
172  send_queuedpdus(wtls_machine);
173  },
174  EXCHANGE)
175 
176 /* Commit Request - Abbreviated Handshake will be performed */
177 ROW(CREATED,
178  SEC_Commit_Req,
179  1,
180  {
181  /* Assert that the PDU list is valid */
182  /* Add some more PDUs to the List - a ChangeCipherSpec and a Finished */
183  /* Translate the buffer and address details into a T_Unitdata_Req */
184  /* And send it winging it's way across the network */
185  },
186  COMMIT)
187 
188 /* Terminate Request */
189 ROW(CREATED,
191  1,
192  {
193  /* Send off a T_Unitdata_Req containing an alert as specified */
194  send_alert(event, wtls_machine);
195  },
196  NULL_STATE)
197 
198 /* Exception Request */
199 ROW(CREATED,
201  1,
202  {
203  /* Send off a T_Unitdata_Req containing an exception as specified */
204  send_alert(event, wtls_machine);
205  },
206  CREATED)
207 
208 /* Exchange State */
209 /* Unitdata arrival - identical ClientHello record */
210 ROW(EXCHANGE,
212  clienthellos_are_identical(event->u.T_Unitdata_Ind.pdu_list, wtls_machine->last_received_packet) == 1,
213  {
214  /* It appears as though someone has sent us an identical ClientHello to the last one */
215  /* Make ourselves a T_Unitdata_Req with the last_transmitted_packet */
216  /* And send it on it's merry */
217  },
218  EXCHANGE)
219 
220 /* Unitdata arrival - non-identical ClientHello record */
221 //ROW(EXCHANGE,
222 // T_Unitdata_Ind,
223 // clienthellos_are_identical(event->u.T_Unitdata_Ind.pdu_list, wtls_machine->last_received_packet) != 1,
224 // {
225 /* So, this one's different. They must have changed their mind about something, so try a CREATING again */
226 /* Do the necessary SEC_Create_Ind stuff */
227 // },
228 // CREATING)
229 
230 /* Unitdata arrival - warning alert */
231 ROW(EXCHANGE,
233  is_warning_alert(event->u.T_Unitdata_Ind.pdu_list, wtls_machine),
234  {
235 /* Do the necessary SEC_Exception_Ind stuff */
236  },
237  EXCHANGE)
238 
239 /* Unitdata arrival - critical/fatal alert */
240 ROW(EXCHANGE,
242  is_critical_alert(event->u.T_Unitdata_Ind.pdu_list, wtls_machine),
243  {
244 /* Do the necessary SEC_Terminate_Ind stuff */
245 /* And we're dead :-< */
246  },
247  NULL_STATE)
248 
249 /* Terminate */
250 ROW(EXCHANGE,
252  1,
253  {
254 /* Send off a T_Unitdata_Req containing an alert as specified */
255  send_alert(event, wtls_machine);
256  },
257  NULL_STATE)
258 
259 /* Unitdata arrival - good packet */
260 ROW(EXCHANGE,
262  1,
263  {
264  exchange_keys(event, wtls_machine);
265  },
266  OPENING)
267 
268 
269 /* Exception */
270 ROW(EXCHANGE,
272  1,
273  {
274 /* Send off a T_Unitdata_Req containing an exception as specified */
275  send_alert(event, wtls_machine);
276  },
277  EXCHANGE)
278 
279 /* Commit State */
280 /* Unitdata arrival - identical ClientHello record */
281 ROW(COMMIT,
283  clienthellos_are_identical(event->u.T_Unitdata_Ind.pdu_list, wtls_machine->last_received_packet),
284  {
285 /* It appears as though someone has sent us an identical ClientHello to the last one */
286 /* Make ourselves a T_Unitdata_Req with the last_transmitted_packet */
287 /* And send it on it's merry way */
288 },
289  COMMIT)
290 
291 /* Unitdata arrival - non-identical ClientHello record */
292 ROW(COMMIT,
294  clienthellos_are_identical(event->u.T_Unitdata_Ind.pdu_list, wtls_machine->last_received_packet) != 1,
295  {
296 /* So, this one's different. They must have changed their mind about something, so try a CREATING again */
297 /* Do the necessary SEC_Create_Ind stuff */
298 },
299  CREATING)
300 
301 /* Unitdata arrival - good packet with ChangeCipherSpec and Finished */
302 ROW(COMMIT,
304  packet_contains_changecipherspec (event->u.T_Unitdata_Ind.pdu_list) &&
305  packet_contains_finished (event->u.T_Unitdata_Ind.pdu_list) &&
306  packet_contains_userdata (event->u.T_Unitdata_Ind.pdu_list),
307  {
308 /* Create ourselves a SEC_Commit_Cnf packet to send off */
309 /* Send it off */
310 },
311  OPEN)
312 
313 /* Unitdata arrival - good packet with ChangeCipherSpec, Finished and UD */
314 ROW(COMMIT,
316  packet_contains_changecipherspec (event->u.T_Unitdata_Ind.pdu_list) &&
317  packet_contains_finished (event->u.T_Unitdata_Ind.pdu_list) &&
318  packet_contains_userdata (event->u.T_Unitdata_Ind.pdu_list),
319  {
320 /* Create a SEC_Commit_Cnf packet to send off */
321 /* Send it off */
322 /* Relay the contents of the packets up to the WTP or WSP layers,
323  depending on the destination port */
324 },
325  OPEN)
326 
327 /* Unitdata arrival - critical/fatal alert */
328 ROW(COMMIT,
330  is_critical_alert(event->u.T_Unitdata_Ind.pdu_list, wtls_machine),
331  {
332 /* Do the necessary SEC_Terminate_Ind stuff */
333 /* And we're dead :-< */
334 },
335  NULL_STATE)
336 
337 /* Unitdata arrival - warning alert */
338 ROW(COMMIT,
340  is_warning_alert(event->u.T_Unitdata_Ind.pdu_list, wtls_machine),
341  {
342 /* Do the necessary SEC_Exception_Ind stuff */
343 },
344  COMMIT)
345 
346 /* Terminate */
347 ROW(COMMIT,
349  1,
350  {
351 /* Send off a T_Unitdata_Req containing an alert as specified */
352  send_alert(event, wtls_machine);
353  },
354  NULL_STATE)
355 
356 /* Exception */
357 ROW(COMMIT,
359  1,
360  {
361 /* Send off a T_Unitdata_Req containing an exception as specified */
362  send_alert(event, wtls_machine);
363  },
364  COMMIT)
365 
366 /* Opening State */
367 /* Create Request */
368 ROW(OPENING,
370  1,
371  {
372 /* Send off a T_Unitdata_Req containing a HelloRequest */
373  },
374  OPENING)
375 
376 /* Send out UnitData */
377 ROW(OPENING,
378  SEC_Unitdata_Req,
379  1,
380  {
381 /* Apply the negotiated security "stuff" to the received packet */
382 /* Send out the packet to the destination port/address requested */
383  },
384  OPENING)
385 
386 /* Unitdata received - ClientHello */
387 //ROW(OPENING,
388 // T_Unitdata_Ind,
389 // packet_contains_clienthello (event->u.T_Unitdata_Ind.pdu_list) == 0,
390 // {
393 //},
394 // CREATING)
395 
396 /* Unitdata received */
397 ROW(OPENING,
399  packet_is_application_data(event->u.T_Unitdata_Ind.pdu_list),
400  {
401  wtls_application(event, wtls_machine);
402  },
403  OPEN)
404 
405 /* Unitdata arrival - Certificate, ClientKeyExchange ... Finished */
406 ROW(OPENING,
408  certificates_are_identical(event->u.T_Unitdata_Ind.pdu_list, wtls_machine->last_received_packet) == 1 &&
409 clientkeyexchanges_are_identical(event->u.T_Unitdata_Ind.pdu_list, wtls_machine->last_received_packet) == 1 &&
410 certifcateverifys_are_identical(event->u.T_Unitdata_Ind.pdu_list, wtls_machine->last_received_packet) == 1 &&
411 changecipherspecs_are_identical(event->u.T_Unitdata_Ind.pdu_list, wtls_machine->last_received_packet) == 1 &&
412 finishes_are_indentical(event->u.T_Unitdata_Ind.pdu_list, wtls_machine->last_received_packet) == 1,
413  {
414 /* It appears as though someone has sent us an identical ClientHello to the last one */
415 /* Make ourselves a T_Unitdata_Req with the last_transmitted_packet */
416 /* And send it on it's merry way */
417 },
418  OPENING)
419 
420 /* Unitdata arrival - critical/fatal alert */
421 ROW(OPENING,
423  is_critical_alert(event->u.T_Unitdata_Ind.pdu_list, wtls_machine),
424  {
425 /* Do the necessary SEC_Terminate_Ind stuff */
426 /* And we're dead :-< */
427 },
428  NULL_STATE)
429 
430 /* Unitdata arrival - warning alert */
431 ROW(OPENING,
433  is_warning_alert(event->u.T_Unitdata_Ind.pdu_list, wtls_machine),
434  {
435 /* Do the necessary SEC_Exception_Ind stuff */
436 },
437  OPENING)
438 
439 /* Terminate */
440 ROW(OPENING,
442  1,
443  {
444 /* Send off a T_Unitdata_Req containing an alert as specified */
445  send_alert(event, wtls_machine);
446  },
447  NULL_STATE)
448 
449 /* Exception */
450 ROW(OPENING,
452  1,
453  {
454 /* Send off a T_Unitdata_Req containing an exception as specified */
455  send_alert(event, wtls_machine);
456  },
457  OPENING)
458 
459 /* Open State */
460 /* Create Request */
461 ROW(OPEN,
463  1,
464  {
465 /* Send off a T_Unitdata_Req with a HelloRequest */
466  },
467  OPEN)
468 
469 /* Send out UnitData */
470 ROW(OPEN,
471  SEC_Unitdata_Req,
472  1,
473  {
474 /* Apply the negotiated security "stuff" to the received packet */
475 /* Send out the packet to the destination port/address requested */
476  },
477  OPEN)
478 
479 /* Unitdata received - ClientHello */
480 ROW(OPEN,
482  packet_contains_clienthello (event->u.T_Unitdata_Ind.pdu_list),
483  {
484 /* Hmm, they're obviously not happy with something we discussed, so let's head back to creating */
485 /* Do the necessary SEC_Create_Ind stuff */
486  wtls_machine->encrypted = 0;
487  wtls_machine->last_refresh = -1;
488  clientHello(event, wtls_machine);
489  },
490  CREATING)
491 
492 /* Unitdata received */
493 ROW(OPEN,
495  packet_is_application_data(event->u.T_Unitdata_Ind.pdu_list),
496  {
497  wtls_application(event, wtls_machine);
498  },
499  OPEN)
500 
501 /* Unitdata arrival - ChangeCipherSpec, Finished */
502 ROW(OPEN,
504  packet_contains_changecipherspec (event->u.T_Unitdata_Ind.pdu_list) == 1 &&
505 packet_contains_finished (event->u.T_Unitdata_Ind.pdu_list) == 1 &&
506 packet_contains_userdata(event->u.T_Unitdata_Ind.pdu_list) != 1 &&
507 finishes_are_indentical(event->u.T_Unitdata_Ind.pdu_list, wtls_machine->last_received_packet) == 1,
508  {
509 /* Just send out a T_Unitdata_Req with an Alert(duplicate_finished_received) */
510 },
511  OPEN)
512 
513 /* Unitdata arrival - ChangeCipherSpec, Finished and UD */
514 ROW(OPEN,
516  packet_contains_changecipherspec (event->u.T_Unitdata_Ind.pdu_list) == 1 &&
517 packet_contains_finished (event->u.T_Unitdata_Ind.pdu_list) == 1 &&
518 packet_contains_userdata(event->u.T_Unitdata_Ind.pdu_list) == 1 &&
519 finishes_are_indentical(event->u.T_Unitdata_Ind.pdu_list, wtls_machine->last_received_packet) == 1,
520  {
521 /* Apply the negotiated decryption/decoding/MAC check to the received data */
522 /* Take the userdata and pass it on up to the WTP/WSP, depending on the destination port */
523 /* Send out a T_Unitdata_Req with an Alert(duplicate_finished_received) */
524 },
525  OPEN)
526 
527 /* Unitdata arrival - critical/fatal alert */
528 ROW(OPEN,
530  is_critical_alert(event->u.T_Unitdata_Ind.pdu_list, wtls_machine),
531  {
532 /* Do the necessary SEC_Terminate_Ind stuff */
533 /* And we're dead :-< */
534 },
535  NULL_STATE)
536 
537 /* Unitdata arrival - warning alert */
538 ROW(OPEN,
540  is_warning_alert(event->u.T_Unitdata_Ind.pdu_list, wtls_machine),
541  {
542 /* Do the necessary SEC_Terminate_Ind stuff */
543 },
544  OPEN)
545 
546 /* Terminate */
547 ROW(OPEN,
549  1,
550  {
551 /* Send off a T_Unitdata_Req containing an alert as specified */
552  send_alert(event, wtls_machine);
553  },
554  NULL_STATE)
555 
556 /* Exception */
557 ROW(OPEN,
559  1,
560  {
561 /* Send off a T_Unitdata_Req containing an exception as specified */
562  send_alert(event, wtls_machine);
563  },
564  OPEN)
565 
566 #undef ROW
567 #undef STATE_NAME
CREATING CREATING wtls_PDU * serverHelloDonePDU
OPEN NULL_STATE NULL_STATE OPENING packet_is_application_data(event->u.T_Unitdata_Ind.pdu_list)
EXCHANGE NULL_STATE EXCHANGE NULL_STATE OPENING COMMIT packet_contains_changecipherspec(event->u.T_Unitdata_Ind.pdu_list)&&packet_contains_finished(event-> u.T_Unitdata_Ind.pdu_list)&& packet_contains_userdata(event->u.T_Unitdata_Ind.pdu_list),
wtls_PDU * wtls_pdu_create(int type)
EXCHANGE SEC_Terminate_Req
#define STATE_NAME(name)
Definition: wsp_session.c:80
add_pdu(wtls_machine, serverKeyXchgPDU)
ROW(NULL_STATE, T_Unitdata_Ind, packet_contains_clienthello(event->u.T_Unitdata_Ind.pdu_list),{clientHello(event, wtls_machine);}, CREATING) ROW(NULL_STATE
T_Unitdata_Ind
int certificates_are_identical(List *pdu_list, List *last_received_packet)
int changecipherspecs_are_identical(List *pdu_list, List *last_received_packet)
EXCHANGE NULL_STATE EXCHANGE is_critical_alert(event->u.T_Unitdata_Ind.pdu_list, wtls_machine)
int snMode
Definition: wtls_pdu.h:449
WAPAddrTuple * wap_addr_tuple_duplicate(WAPAddrTuple *tuple)
Definition: wap_addr.c:125
int is_warning_alert(List *pdu_list, WTLSMachine *wtls_machine)
alert
union wtls_pdu::@93 u
ParameterSpecifier * param_spec
Definition: wtls_pdu.h:335
int packet_contains_userdata(List *pdu_list)
ServerKeyExchange * server_key_exchange
Definition: wtls_pdu.h:428
int packet_contains_finished(List *pdu_list)
wtls_pdu_destroy(serverKeyXchgPDU)
clientHello(event, wtls_machine)
#define wap_event_create(type)
Definition: wap_events.h:107
RSAPublicKey * wtls_get_rsapublickey(void)
int certifcateverifys_are_identical(List *pdu_list, List *last_received_packet)
wtls_dispatch_event(alert)
debug("wtls: ", 0,"Going to get the RSA public key...")
gw_assert(wtls_machine->packet_to_send!=NULL)
EXCHANGE NULL_STATE clienthellos_are_identical(event->u.T_Unitdata_Ind.pdu_list, wtls_machine->last_received_packet)
RSAPublicKey * rsa_params
Definition: wtls_pdu.h:337
OPEN NULL_STATE NULL_STATE SEC_Create_Request_Req
CREATING CREATING SEC_Exchange_Req
OPEN NULL_STATE NULL_STATE OPENING OPEN NULL_STATE NULL_STATE OPEN packet_contains_clienthello(event->u.T_Unitdata_Ind.pdu_list)
int finishes_are_indentical(List *pdu_list, List *last_received_packet)
Handshake handshake
Definition: wtls_pdu.h:456
HandshakeType msg_type
Definition: wtls_pdu.h:417
CREATING SEC_Exception_Req
int rlen
Definition: wtls_pdu.h:451
union WAPEvent::@87 u
send_queuedpdus(wtls_machine)
int clientkeyexchanges_are_identical(List *pdu_list, List *last_received_packet)
serverKeyXchgPDU u handshake server_key_exchange
error(0,"send_alert ~> Critical alert (unexpected_message), while waiting for client hello.")
serverKeyXchgPDU
See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.