wtls.c
上传用户:gzpyjq
上传日期:2013-01-31
资源大小:1852k
文件大小:19k
源码类别:

手机WAP编程

开发平台:

WINDOWS

  1. /*
  2.  * wtls.c: WTLS server-side implementation
  3.  *
  4.  * Nick Clarey <nclarey@3glab.com>
  5.  */
  6. #include "gwlib/gwlib.h"
  7. #if (HAVE_WTLS_OPENSSL)
  8. #include "wtls.h"
  9. #include "timers.h"
  10. #include "wap_events.h"
  11. #include "wtls_pdu.h"
  12. #include "wtls_statesupport.h"
  13. #include "gw/msg.h"
  14. #include "wtp.h"
  15. /***********************************************************************
  16.  * Internal data structures.
  17.  *
  18.  * List of WTLS Server machines.
  19.  */
  20. static List *wtls_machines = NULL;
  21. /*
  22.  * Counter for WTLS Server machine id numbers, to make sure they are unique.
  23.  */
  24. static Counter *wtls_machine_id_counter = NULL;
  25. /*
  26.  * Give the status of wtls server layer:
  27.  * limbo - not running at all
  28.  * running - operating normally
  29.  * terminating - waiting for operations to terminate, returning to limbo
  30.  */
  31. static enum { limbo, running, terminating } wtls_run_status = limbo;
  32. /*
  33.  * Queue of events to be handled by WTLS Server machines.
  34.  */
  35. static List *wtls_queue = NULL;
  36. /*****************************************************************************
  37.  *
  38.  * Prototypes of internal functions:
  39.  */
  40. /*
  41.  * Create and destroy an uninitialized wtls server state machine.
  42.  */
  43. static WTLSMachine* wtls_machine_create(WAPAddrTuple *tuple);
  44. static void wtls_machine_create_destroy(void *sm);
  45. static void wtls_machine_destroy(void * p);
  46. /*
  47.  * Checks whether the list of wlts server machines includes a specific machine.
  48.  *
  49.  * The machine in question is identified with with source and destination
  50.  * address and port. If the machine does not exist and the event is either;
  51.  * - A SEC-Create-Request.req or
  52.  * - A T-Unitdata.ind containing a ClientHello packet or
  53.  * - A T-Unitdata.ind containing an Alert(no_renegotiation) packet
  54.  * a new machine is created and added in the machines data structure. 
  55.  *
  56.  * See WTLS 7.2 for details of this check.
  57.  */
  58. static WTLSMachine *wtls_machine_find_or_create(WAPEvent *event);
  59. /*
  60.  * Feed an event to a WTLS Server state machine. Handle all errors by 
  61.  * itself, do not report them to the caller.
  62.  */
  63. static void wtls_event_handle(WTLSMachine *machine, WAPEvent *event);
  64. /*
  65.  * Print a WTLS Server machine state as a string.
  66.  */
  67. static unsigned char *name_wtlser_state(int name);
  68. /*
  69.  * Find a WTLS Server machine from the global list of wtls server 
  70.  * structures that corresponds to the four-tuple of source and destination 
  71.  * addresses and ports. Return a pointer to the machine, or NULL if not found.
  72.  */
  73. static WTLSMachine *wtls_machine_find(WAPAddrTuple *tuple, long mid);
  74. static void main_thread(void *);
  75. static WTLSMachine *find_wtls_machine_using_mid(long mid);
  76. static void add_wtls_address(Msg *msg, WTLSMachine *wtls_machine);
  77. /* The match* functions are used for searches through lists */
  78. static int match_handshake_type(void* item, void* pattern);
  79. static int match_pdu_type(void* item, void* pattern);
  80. /*static WAPEvent *create_tr_invoke_ind(WTPRespMachine *sm, Octstr *user_data);
  81. static WAPEvent *create_tr_abort_ind(WTPRespMachine *sm, long abort_reason);
  82. static WAPEvent *create_tr_result_cnf(WTPRespMachine *sm); */
  83. /******************************************************************************
  84.  *
  85.  * EXTERNAL FUNCTIONS:
  86.  *
  87.  */
  88. WAPEvent *wtls_unpack_wdp_datagram(Msg *msg)
  89. {
  90.         WAPEvent* unitdataIndEvent;
  91.         List* wtlsPayloadList;
  92.         /* Dump the Msg */
  93.         msg_dump(msg,0);
  94.         
  95.         /* Then, stuff it into a T_Unitdata_Ind Event */
  96.         unitdataIndEvent = wap_event_create(T_Unitdata_Ind);
  97.         info(0,"Event created");
  98.         
  99.         /* Firstly, the address */ 
  100.         unitdataIndEvent->u.T_Unitdata_Ind.addr_tuple =
  101.                 wap_addr_tuple_create(msg->wdp_datagram.source_address,
  102.                                       msg->wdp_datagram.source_port,
  103.                                       msg->wdp_datagram.destination_address,
  104.                                       msg->wdp_datagram.destination_port);
  105.         info(0,"Set address and stuff");
  106.         /* Attempt to stuff this baby into a list-of-WTLS-PDUs */
  107.         wtlsPayloadList = wtls_unpack_payloadlist (msg->wdp_datagram.user_data);
  108.         info(0,"Datagram unpacked!");
  109.         
  110.         /* Then, the pdu material */
  111.         unitdataIndEvent->u.T_Unitdata_Ind.pdu_list = wtlsPayloadList;
  112.         /* And return the event */
  113.         return unitdataIndEvent;
  114. }
  115. void wtls_init(void) {
  116.         /* Initialise our various lists and counters */
  117.         wtls_machines = list_create();
  118.         wtls_machine_id_counter = counter_create();
  119.         
  120.         wtls_queue = list_create();
  121.         list_add_producer(wtls_queue);
  122.         /* Idiot check - ensure that we are able to start running */
  123.         gw_assert(wtls_run_status == limbo);
  124.         wtls_run_status = running;
  125.         gwthread_create(main_thread, NULL);
  126. }
  127. void wtls_shutdown(void) {
  128.         /* Make sure that we're actually running; if so, then
  129.            prepare for termination */
  130.         gw_assert(wtls_run_status == running);
  131.         wtls_run_status = terminating;
  132.         list_remove_producer(wtls_queue);
  133.         gwthread_join_every(main_thread);
  134.         /* Print out a friendly message stating that we're going to die */
  135.         debug("wap.wtls", 0, "wtls_shutdown: %ld wtls machines left",
  136.               list_len(wtls_machines));
  137.         /* And clean up nicely after ourselves */
  138.         list_destroy(wtls_machines, wtls_machine_destroy);
  139.         list_destroy(wtls_queue, wap_event_destroy_item);     
  140.         counter_destroy(wtls_machine_id_counter);
  141. }
  142. void wtls_dispatch_event(WAPEvent *event) {
  143.         /* Stick the event on the incoming events queue */
  144.         list_produce(wtls_queue, event);
  145. }
  146. int wtls_get_address_tuple(long mid, WAPAddrTuple **tuple) {
  147. WTLSMachine *sm;
  148. sm = find_wtls_machine_using_mid(mid);
  149. if (sm == NULL)
  150. return -1;
  151. *tuple = wap_addr_tuple_duplicate(sm->addr_tuple);
  152. return 0;
  153. }
  154. void send_alert(int alertLevel, int alertDescription, WTLSMachine* wtls_machine) {
  155.         wtls_Payload* alertPayload;
  156.         wtls_PDU* alertPDU;
  157.         
  158.         Octstr* packedAlert;
  159.         Msg* msg = NULL;
  160.         
  161.         alertPDU = (wtls_PDU*) wtls_pdu_create(Alert_PDU);
  162.         alertPDU->u.alert.level = alertLevel;
  163.         alertPDU->u.alert.desc = alertDescription;
  164.         /* Here's where we should get the current checksum from the wtls_machine */
  165.         alertPDU->u.alert.chksum = 0;
  166.         /* Pack the PDU */
  167.         msg = msg_create(wdp_datagram);
  168.         add_wtls_address(msg, wtls_machine);
  169.         /* Pack the message */
  170.         alertPayload = wtls_pdu_pack(alertPDU, wtls_machine);
  171.         packedAlert = (Octstr*) wtls_payload_pack(alertPayload);
  172.         msg->wdp_datagram.user_data = packedAlert;
  173.         /* And destroy the structure */
  174.         wtls_payload_destroy(alertPayload);
  175.         alertPayload = NULL;
  176.         
  177.         /* Send it off */
  178.         write_to_bearerbox(msg);
  179. }
  180. void clear_queuedpdus(WTLSMachine* wtls_machine)
  181. {
  182. }
  183. void add_pdu(WTLSMachine* wtls_machine, wtls_PDU* pduToAdd)
  184. {
  185.         int currentLength;
  186.         wtls_Payload* payloadToAdd;
  187.         Octstr* packedPDU;
  188.         /* Check to see if we've already allocated some memory for the list */
  189.         if (wtls_machine->packet_to_send == NULL) {
  190.                 wtls_machine->packet_to_send = octstr_create("");
  191.         }
  192.         /* Pack and encrypt the pdu */
  193.         payloadToAdd = wtls_pdu_pack(pduToAdd, wtls_machine);
  194.         /* If the pdu is a Handshake pdu, append the Octstr to our wtls_machine's
  195.            exchanged_handshakes Octstr */
  196.         packedPDU = wtls_payload_pack(payloadToAdd);
  197.         /* Add it to our list */
  198.         currentLength = octstr_len(wtls_machine->packet_to_send);
  199.         octstr_insert(wtls_machine->packet_to_send, packedPDU, currentLength);
  200. }
  201. /*
  202.  * Send the pdu_to_send list to the destination specified by the address in the machine
  203.  * structure. Don't return anything, handle all errors internally.
  204.  */
  205. void send_queuedpdus(WTLSMachine* wtls_machine)
  206. {
  207.         Msg* msg = NULL;
  208.         gw_assert(wtls_machine->packet_to_send != NULL);
  209.         
  210.         /* Pack the PDU */
  211.         msg = msg_create(wdp_datagram);
  212.         add_wtls_address(msg, wtls_machine);
  213.         msg->wdp_datagram.user_data = octstr_duplicate(wtls_machine->packet_to_send);
  214.         /* Send it off */
  215.         write_to_bearerbox(msg);
  216.         /* Destroy our copy of the sent string */
  217.         octstr_destroy(wtls_machine->packet_to_send);
  218.         wtls_machine->packet_to_send = NULL;
  219.         
  220. }
  221. /* 
  222.  * Add address from  state machine.
  223.  */
  224. void add_wtls_address(Msg *msg, WTLSMachine *wtls_machine){
  225.        debug("wap.wtls", 0, "adding address");
  226.        msg->wdp_datagram.source_address = 
  227.          octstr_duplicate(wtls_machine->addr_tuple->local->address);
  228.        msg->wdp_datagram.source_port = wtls_machine->addr_tuple->local->port;
  229.        msg->wdp_datagram.destination_address = 
  230.          octstr_duplicate(wtls_machine->addr_tuple->remote->address);
  231.        msg->wdp_datagram.destination_port = 
  232.             wtls_machine->addr_tuple->remote->port;
  233. }
  234. /*****************************************************************************
  235.  *
  236.  * INTERNAL FUNCTIONS:
  237.  *
  238.  */
  239. static void main_thread(void *arg) {
  240. WTLSMachine *sm;
  241. WAPEvent *e;
  242.         
  243. while (wtls_run_status == running && 
  244.                (e = list_consume(wtls_queue)) != NULL) {
  245. sm = wtls_machine_find_or_create(e);
  246. if (sm == NULL)
  247. wap_event_destroy(e);
  248. else
  249. wtls_event_handle(sm, e);
  250.                 }
  251. }
  252. /*
  253.  * Give the name of a WTLS Server state in a readable form. 
  254.  */
  255. static unsigned char *name_wtls_state(int s){
  256.        switch (s){
  257.               #define STATE_NAME(state) case state: return #state;
  258.               #define ROW(state, event, condition, action, new_state)
  259.               #include "wtls_state-decl.h"
  260.               default:
  261.                       return "unknown state";
  262.        }
  263. }
  264. /*
  265.  * Feed an event to a WTP responder state machine. Handle all errors yourself,
  266.  * do not report them to the caller. Note: Do not put {}s of the else block 
  267.  * inside the macro definition. 
  268.  */
  269. static void wtls_event_handle(WTLSMachine *wtls_machine, WAPEvent *event){
  270.      debug("wap.wtls", 0, "WTLS: wtls_machine %ld, state %s, event %s.", 
  271.    wtls_machine->mid, 
  272.    name_wtls_state(wtls_machine->state), 
  273.    wap_event_name(event->type));
  274. /* for T_Unitdata_Ind PDUs */
  275. if(event->type == T_Unitdata_Ind) {
  276. /* if encryption: decrypt all pdus in the list */
  277. if( wtls_machine->encrypted ) {
  278. wtls_decrypt_pdu_list(wtls_machine, event->u.T_Unitdata_Ind.pdu_list);
  279. }
  280. /* add all handshake data to wtls_machine->handshake_data */
  281. //add_all_handshake_data(wtls_machine, event->u.T_Unitdata_Ind.pdu_list);
  282. }
  283.      #define STATE_NAME(state)
  284.      #define ROW(wtls_state, event_type, condition, action, next_state) 
  285.      if (wtls_machine->state == wtls_state && 
  286. event->type == event_type && 
  287. (condition)) { 
  288. action 
  289. wtls_machine->state = next_state; 
  290. debug("wap.wtls", 0, "WTLS %ld: New state %s", wtls_machine->mid, #next_state); 
  291.      } else 
  292.      #include "wtls_state-decl.h"
  293.      {
  294. error(0, "WTLS: handle_event: unhandled event!");
  295. debug("wap.wtls", 0, "WTLS: handle_event: Unhandled event was:");
  296. wap_event_destroy(event);
  297. return;
  298.      }
  299.      if (event != NULL) {
  300. wap_event_destroy(event);  
  301.      }
  302.      if (wtls_machine->state == NULL_STATE)
  303.       wtls_machine_destroy(wtls_machine);
  304. }
  305. /*
  306.  * Checks whether wtls machines data structure includes a specific machine.
  307.  * The machine in question is identified with with source and destination
  308.  * address and port.
  309.  */
  310. static WTLSMachine *wtls_machine_find_or_create(WAPEvent *event) {
  311.           WTLSMachine *wtls_machine = NULL;
  312.           long mid;
  313.           WAPAddrTuple *tuple;
  314.           tuple = NULL;
  315.           mid = -1;
  316.   debug("wap.wtls",0, "event->type = %d", event->type);
  317.   
  318.           /* Get the address that this PDU came in from */
  319.           switch (event->type) {
  320.           case T_Unitdata_Ind:
  321.           case T_DUnitdata_Ind:
  322.                   tuple = event->u.T_Unitdata_Ind.addr_tuple;
  323.                   break;
  324.           case SEC_Create_Request_Req:
  325.           case SEC_Terminate_Req:
  326.           case SEC_Exception_Req:
  327.           case SEC_Create_Res:
  328.           case SEC_Exchange_Req:
  329.           case SEC_Commit_Req:
  330.           case SEC_Unitdata_Req:
  331.                   tuple = event->u.T_Unitdata_Ind.addr_tuple;
  332.                   break;
  333.           default:
  334.                   debug("wap.wtls", 0, "WTLS: wtls_machine_find_or_create:"
  335.                         "unhandled event (1)"); 
  336.                   wap_event_dump(event);
  337.                   return NULL;
  338.           }
  339.           /* Either the address or the machine id must be available at this point */
  340.           gw_assert(tuple != NULL || mid != -1);
  341.           /* Look for the machine owning this address */
  342.           wtls_machine = wtls_machine_find(tuple, mid);
  343.           /* Oh well, we didn't find one. We'll create one instead, provided
  344.              it meets certain criteria */
  345.           if (wtls_machine == NULL){
  346.                   switch (event->type){
  347.                   case SEC_Create_Request_Req:
  348.                           /* State NULL, case 1 */
  349.                           debug("wap.wtls",0,"WTLS: received a SEC_Create_Request_Req, and don't know what to do with it...");
  350.                           /* Create and dispatch a T_Unitdata_Req containing a HelloRequest */
  351.                           /* And there's no need to do anything else, 'cause we return to state NULL */
  352.                           break;
  353.                   case T_Unitdata_Ind:
  354.                   case T_DUnitdata_Ind:
  355.                           /* State NULL, case 3 */
  356. /*                           if (wtls_event_type(event) == Alert_No_Renegotiation) { */
  357.                                   /* Create and dispatch a SEC_Exception_Ind event */
  358. /*                                   debug("wap.wtls",0,"WTLS: received an Alert_no_Renegotiation; just dropped it."); */
  359.                                   /* And there's no need to do anything else, 'cause we return to state NULL */
  360. /*                                   break; */
  361. /*                           } else */
  362. /*                           if (event->u.T_Unitdata_Ind == ClientHello) { */
  363.                                   /* State NULL, case 2 */
  364.                           wtls_machine = wtls_machine_create(tuple);
  365.                           /* And stick said event into machine, which should push us into state
  366.                              CREATING after a SEC_Create_Ind */
  367. /*                           } */
  368.                           break;
  369.                   default:
  370.                           error(0, "WTLS: wtls_machine_find_or_create:"
  371.                                 " unhandled event (2)");
  372.                           wap_event_dump(event);
  373.                           break;
  374.                   }
  375.           }
  376.           return wtls_machine;
  377. }
  378. static int is_wanted_wtls_machine(void *a, void *b) {
  379. machine_pattern *pat;
  380. WTLSMachine *m;
  381. m = a;
  382. pat = b;
  383. if (m->mid == pat->mid)
  384. return 1;
  385. if (pat->mid != -1)
  386. return 0;
  387. return wap_addr_tuple_same(m->addr_tuple, pat->tuple);
  388. }
  389. static WTLSMachine *wtls_machine_find(WAPAddrTuple *tuple, 
  390.                                          long mid) {
  391. machine_pattern pat;
  392. WTLSMachine *m;
  393. pat.tuple = tuple;
  394. pat.mid = mid;
  395. m = list_search(wtls_machines, &pat, is_wanted_wtls_machine);
  396. return m;
  397. }
  398. static WTLSMachine *wtls_machine_create(WAPAddrTuple *tuple) {
  399.         WTLSMachine *wtls_machine;
  400.         wtls_machine = gw_malloc(sizeof(WTLSMachine)); 
  401.         
  402.         #define MACHINE(field) field
  403.         #define ENUM(name) wtls_machine->name = NULL_STATE;
  404.         #define ADDRTUPLE(name) wtls_machine->name = NULL; 
  405.         #define INTEGER(name) wtls_machine->name = 0; 
  406.         #define OCTSTR(name) wtls_machine->name = NULL;
  407.         #define PDULIST(name) wtls_machine->name = NULL;
  408.         #include "wtls_machine-decl.h"
  409.         
  410.         list_append(wtls_machines, wtls_machine);
  411.         wtls_machine->mid = counter_increase(wtls_machine_id_counter);
  412.         wtls_machine->addr_tuple = wap_addr_tuple_duplicate(tuple);
  413. wtls_machine->handshake_data = octstr_create("");
  414.         debug("wap.wtls", 0, "WTLS: Created WTLSMachine %p (%ld)",
  415.               (void *) wtls_machine, wtls_machine->mid);
  416.         return wtls_machine;
  417. }
  418. /*
  419.  * Destroys a WTLSMachine. Assumes it is safe to do so. Assumes it has 
  420.  * already been deleted from the machines list.
  421.  */
  422. static void wtls_machine_destroy(void * p) {
  423.        WTLSMachine *wtls_machine;
  424.        wtls_machine = p;
  425.        debug("wap.wtls", 0, "WTLS: Destroying WTLSMachine %p (%ld)",
  426.              (void *) wtls_machine, wtls_machine->mid);
  427.        list_delete_equal(wtls_machines, wtls_machine);        
  428.         
  429.        #define MACHINE(field) field
  430.        #define ENUM(name) wtls_machine->name = NULL_STATE;
  431.        #define ADDRTUPLE(name) wap_addr_tuple_destroy(wtls_machine->name); 
  432.        #define INTEGER(name) wtls_machine->name = 0; 
  433.        #define OCTSTR(name) octstr_destroy(wtls_machine->name);
  434.        #define PDULIST(name) wtls_machine->name = NULL;
  435.        #include "wtls_machine-decl.h"
  436.         gw_free(wtls_machine);
  437. }
  438. /*
  439.  * Create a TR-Invoke.ind event.
  440. static WAPEvent *create_tr_invoke_ind(WTPRespMachine *sm, Octstr *user_data) {
  441. WAPEvent *event;
  442. event = wap_event_create(TR_Invoke_Ind);
  443. event->u.TR_Invoke_Ind.ack_type = sm->u_ack;
  444. event->u.TR_Invoke_Ind.user_data = octstr_duplicate(user_data);
  445. event->u.TR_Invoke_Ind.tcl = sm->tcl;
  446. event->u.TR_Invoke_Ind.addr_tuple = 
  447. wap_addr_tuple_duplicate(sm->addr_tuple);
  448. event->u.TR_Invoke_Ind.handle = sm->mid;
  449. return event;
  450. }
  451. */
  452. /*
  453.  * Create a TR-Result.cnf event.
  454. static WAPEvent *create_tr_result_cnf(WTPRespMachine *sm) {
  455. WAPEvent *event;
  456. event = wap_event_create(TR_Result_Cnf);
  457. event->u.TR_Result_Cnf.addr_tuple = 
  458. wap_addr_tuple_duplicate(sm->addr_tuple);
  459. event->u.TR_Result_Cnf.handle = sm->mid;
  460. return event;
  461. }
  462. */
  463. /*
  464.  * Creates TR-Abort.ind event from a responder state machine. 
  465.  
  466. static WAPEvent *create_tr_abort_ind(WTPRespMachine *sm, long abort_reason) {
  467. WAPEvent *event;
  468. event = wap_event_create(TR_Abort_Ind);
  469. event->u.TR_Abort_Ind.abort_code = abort_reason;
  470. event->u.TR_Abort_Ind.addr_tuple = 
  471. wap_addr_tuple_duplicate(sm->addr_tuple);
  472. event->u.TR_Abort_Ind.handle = sm->mid;
  473. return event;
  474. }
  475. */
  476. static int wtls_machine_has_mid(void *a, void *b) {
  477. WTLSMachine *sm;
  478. long mid;
  479. sm = a;
  480. mid = *(long *) b;
  481. return sm->mid == mid;
  482. }
  483. static WTLSMachine *find_wtls_machine_using_mid(long mid) {
  484.        return list_search(wtls_machines, &mid, wtls_machine_has_mid);
  485. }
  486. /* Used for list searches */
  487. static int match_handshake_type(void* item, void* pattern)
  488. {
  489.         wtls_Payload* matchingPayload;
  490.         int type;
  491.         int retrievedType;
  492.         
  493.         matchingPayload = (wtls_Payload*) item;
  494.         type = (int) pattern;
  495.         
  496.         retrievedType = octstr_get_char(matchingPayload->data, 0);
  497.         
  498.         if (matchingPayload->type == Handshake_PDU && retrievedType == type)
  499.         {
  500.                 return 1;
  501.         }
  502.         else
  503.         {
  504.                 return 0;
  505.         }        
  506. }
  507. static int match_pdu_type(void* item, void* pattern)
  508. {
  509.         wtls_Payload* matchingPayload;
  510.         int type;
  511.         
  512.         matchingPayload = (wtls_Payload*) item;
  513.         type = (int) pattern;
  514.         
  515.         
  516.         if (matchingPayload->type == type)
  517.         {
  518.                 return 1;
  519.         }
  520.         else
  521.         {
  522.                 return 0;
  523.         }        
  524. }
  525. #endif