📄 wtls.c
字号:
/* * wtls.c - WTLS Server-side implementation * * Nick Clarey <nclarey@3glab.com> */#if (HAVE_WTLS_OPENSSL)#include "gwlib/gwlib.h"#include "wtls.h"#include "timers.h"#include "wap_events.h"#include "wtls_pdu.h"#include "wtls_statesupport.h"#include "gw/msg.h"#include "wtp.h"/*********************************************************************** * Internal data structures. * * List of WTLS Server machines. */static List *wtls_machines = NULL;/* * Counter for WTLS Server machine id numbers, to make sure they are unique. */static Counter *wtls_machine_id_counter = NULL;/* * Give the status of wtls server layer: * limbo - not running at all * running - operating normally * terminating - waiting for operations to terminate, returning to limbo */static enum { limbo, running, terminating } wtls_run_status = limbo;/* * Queue of events to be handled by WTLS Server machines. */static List *wtls_queue = NULL;/***************************************************************************** * * Prototypes of internal functions: *//* * Create and destroy an uninitialized wtls server state machine. */static WTLSMachine* wtls_machine_create(WAPAddrTuple *tuple);static void wtls_machine_create_destroy(void *sm);static void wtls_machine_destroy(void * p);/* * Checks whether the list of wlts server machines includes a specific machine. * * The machine in question is identified with with source and destination * address and port. If the machine does not exist and the event is either; * - A SEC-Create-Request.req or * - A T-Unitdata.ind containing a ClientHello packet or * - A T-Unitdata.ind containing an Alert(no_renegotiation) packet * a new machine is created and added in the machines data structure. * * See WTLS 7.2 for details of this check. */static WTLSMachine *wtls_machine_find_or_create(WAPEvent *event);/* * Feed an event to a WTLS Server state machine. Handle all errors by * itself, do not report them to the caller. */static void wtls_event_handle(WTLSMachine *machine, WAPEvent *event);/* * Print a WTLS Server machine state as a string. */static unsigned char *name_wtlser_state(int name);/* * Find a WTLS Server machine from the global list of wtls server * structures that corresponds to the four-tuple of source and destination * addresses and ports. Return a pointer to the machine, or NULL if not found. */static WTLSMachine *wtls_machine_find(WAPAddrTuple *tuple, long mid);static void main_thread(void *);static WTLSMachine *find_wtls_machine_using_mid(long mid);static void add_wtls_address(Msg *msg, WTLSMachine *wtls_machine);/* The match* functions are used for searches through lists */static int match_handshake_type(void* item, void* pattern);static int match_pdu_type(void* item, void* pattern);/*static WAPEvent *create_tr_invoke_ind(WTPRespMachine *sm, Octstr *user_data);static WAPEvent *create_tr_abort_ind(WTPRespMachine *sm, long abort_reason);static WAPEvent *create_tr_result_cnf(WTPRespMachine *sm); *//****************************************************************************** * * EXTERNAL FUNCTIONS: * */WAPEvent *wtls_unpack_wdp_datagram(Msg *msg){ WAPEvent* unitdataIndEvent; List* wtlsPayloadList; /* Dump the Msg */ msg_dump(msg,0); /* Then, stuff it into a T_Unitdata_Ind Event */ unitdataIndEvent = wap_event_create(T_Unitdata_Ind); info(0,"Event created"); /* Firstly, the address */ unitdataIndEvent->u.T_Unitdata_Ind.addr_tuple = wap_addr_tuple_create(msg->wdp_datagram.source_address, msg->wdp_datagram.source_port, msg->wdp_datagram.destination_address, msg->wdp_datagram.destination_port); info(0,"Set address and stuff"); /* Attempt to stuff this baby into a list-of-WTLS-PDUs */ wtlsPayloadList = wtls_unpack_payloadlist (msg->wdp_datagram.user_data); info(0,"Datagram unpacked!"); /* Then, the pdu material */ unitdataIndEvent->u.T_Unitdata_Ind.pdu_list = wtlsPayloadList; /* And return the event */ return unitdataIndEvent;}void wtls_init(void) { /* Initialise our various lists and counters */ wtls_machines = list_create(); wtls_machine_id_counter = counter_create(); wtls_queue = list_create(); list_add_producer(wtls_queue); /* Idiot check - ensure that we are able to start running */ gw_assert(wtls_run_status == limbo); wtls_run_status = running; gwthread_create(main_thread, NULL);}void wtls_shutdown(void) { /* Make sure that we're actually running; if so, then prepare for termination */ gw_assert(wtls_run_status == running); wtls_run_status = terminating; list_remove_producer(wtls_queue); gwthread_join_every(main_thread); /* Print out a friendly message stating that we're going to die */ debug("wap.wtls", 0, "wtls_shutdown: %ld wtls machines left", list_len(wtls_machines)); /* And clean up nicely after ourselves */ list_destroy(wtls_machines, wtls_machine_destroy); list_destroy(wtls_queue, wap_event_destroy_item); counter_destroy(wtls_machine_id_counter);}void wtls_dispatch_event(WAPEvent *event) { /* Stick the event on the incoming events queue */ list_produce(wtls_queue, event);}int wtls_get_address_tuple(long mid, WAPAddrTuple **tuple) { WTLSMachine *sm; sm = find_wtls_machine_using_mid(mid); if (sm == NULL) return -1; *tuple = wap_addr_tuple_duplicate(sm->addr_tuple); return 0;}void send_alert(int alertLevel, int alertDescription, WTLSMachine* wtls_machine) { wtls_Payload* alertPayload; wtls_PDU* alertPDU; Octstr* packedAlert; Msg* msg = NULL; alertPDU = (wtls_PDU*) wtls_pdu_create(Alert_PDU); alertPDU->u.alert.level = alertLevel; alertPDU->u.alert.desc = alertDescription; /* Here's where we should get the current checksum from the wtls_machine */ alertPDU->u.alert.chksum = 0; /* Pack the PDU */ msg = msg_create(wdp_datagram); add_wtls_address(msg, wtls_machine); /* Pack the message */ alertPayload = wtls_pdu_pack(alertPDU, wtls_machine); packedAlert = (Octstr*) wtls_payload_pack(alertPayload); msg->wdp_datagram.user_data = packedAlert; /* And destroy the structure */ wtls_payload_destroy(alertPayload); alertPayload = NULL; /* Send it off */ write_to_bearerbox(msg);}void clear_queuedpdus(WTLSMachine* wtls_machine){}void add_pdu(WTLSMachine* wtls_machine, wtls_PDU* pduToAdd){ int currentLength; wtls_Payload* payloadToAdd; Octstr* packedPDU; /* Check to see if we've already allocated some memory for the list */ if (wtls_machine->packet_to_send == NULL) { wtls_machine->packet_to_send = octstr_create(""); } /* Pack and encrypt the pdu */ payloadToAdd = wtls_pdu_pack(pduToAdd, wtls_machine); /* If the pdu is a Handshake pdu, append the Octstr to our wtls_machine's exchanged_handshakes Octstr */ packedPDU = wtls_payload_pack(payloadToAdd); /* Add it to our list */ currentLength = octstr_len(wtls_machine->packet_to_send); octstr_insert(wtls_machine->packet_to_send, packedPDU, currentLength);}/* * Send the pdu_to_send list to the destination specified by the address in the machine * structure. Don't return anything, handle all errors internally. */void send_queuedpdus(WTLSMachine* wtls_machine){ Msg* msg = NULL; gw_assert(wtls_machine->packet_to_send != NULL); /* Pack the PDU */ msg = msg_create(wdp_datagram); add_wtls_address(msg, wtls_machine); msg->wdp_datagram.user_data = octstr_duplicate(wtls_machine->packet_to_send); /* Send it off */ write_to_bearerbox(msg); /* Destroy our copy of the sent string */ octstr_destroy(wtls_machine->packet_to_send); wtls_machine->packet_to_send = NULL; }/* * Add address from state machine. */void add_wtls_address(Msg *msg, WTLSMachine *wtls_machine){ debug("wap.wtls", 0, "adding address"); msg->wdp_datagram.source_address = octstr_duplicate(wtls_machine->addr_tuple->local->address); msg->wdp_datagram.source_port = wtls_machine->addr_tuple->local->port; msg->wdp_datagram.destination_address = octstr_duplicate(wtls_machine->addr_tuple->remote->address); msg->wdp_datagram.destination_port = wtls_machine->addr_tuple->remote->port;}/***************************************************************************** * * INTERNAL FUNCTIONS: * */static void main_thread(void *arg) { WTLSMachine *sm; WAPEvent *e; while (wtls_run_status == running && (e = list_consume(wtls_queue)) != NULL) { sm = wtls_machine_find_or_create(e); if (sm == NULL) wap_event_destroy(e); else wtls_event_handle(sm, e); }}/* * Give the name of a WTLS Server state in a readable form. */static unsigned char *name_wtls_state(int s){ switch (s){ #define STATE_NAME(state) case state: return #state; #define ROW(state, event, condition, action, new_state) #include "wtls_state-decl.h" default:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -