Beispiel #1
0
static void fatalAlert(WAPEvent * event, int description)
{
   WAPEvent *abort;

   abort = wap_event_create(SEC_Terminate_Req);
   abort->u.SEC_Terminate_Req.addr_tuple = wap_addr_tuple_duplicate
       (event->u.T_Unitdata_Ind.addr_tuple);
   abort->u.SEC_Terminate_Req.alert_level = fatal_alert;
   abort->u.SEC_Terminate_Req.alert_desc = description;
   wtls_dispatch_event(abort);
}
Beispiel #2
0
int main(int argc, char **argv) 
{
    int cf_index;
    int restart = 0;
    Msg *msg;
    Cfg *cfg;
    double heartbeat_freq =  DEFAULT_HEARTBEAT;
    
    gwlib_init();
    cf_index = get_and_set_debugs(argc, argv, NULL);
    
    setup_signal_handlers();
    
    if (argv[cf_index] == NULL)
        config_filename = octstr_create("kannel.conf");
    else
        config_filename = octstr_create(argv[cf_index]);
    cfg = cfg_create(config_filename);

    if (cfg_read(cfg) == -1)
        panic(0, "Couldn't read configuration from `%s'.", octstr_get_cstr(config_filename));

    report_versions("wapbox");

    cfg = init_wapbox(cfg);

    info(0, "------------------------------------------------------------");
    info(0, GW_NAME " wapbox version %s starting up.", GW_VERSION);
    
    sequence_counter = counter_create();
    wsp_session_init(&wtp_resp_dispatch_event,
                     &wtp_initiator_dispatch_event,
                     &wap_appl_dispatch,
                     &wap_push_ppg_dispatch_event);
    wsp_unit_init(&dispatch_datagram, &wap_appl_dispatch);
    wsp_push_client_init(&wsp_push_client_dispatch_event, 
                         &wtp_resp_dispatch_event);
    
    if (cfg)
        wtp_initiator_init(&dispatch_datagram, &wsp_session_dispatch_event,
                           timer_freq);

    wtp_resp_init(&dispatch_datagram, &wsp_session_dispatch_event,
                  &wsp_push_client_dispatch_event, timer_freq);
    wap_appl_init(cfg);

#if (HAVE_WTLS_OPENSSL)
    wtls_secmgr_init();
    wtls_init(&write_to_bearerbox);
#endif
    
    if (cfg) {
        wap_push_ota_init(&wsp_session_dispatch_event, 
                          &wsp_unit_dispatch_event);
        wap_push_ppg_init(&wap_push_ota_dispatch_event, &wap_appl_dispatch, 
                          cfg);
    }
		
    wml_init(wml_xml_strict);
    
    if (bearerbox_host == NULL)
    	bearerbox_host = octstr_create(BB_DEFAULT_HOST);
    connect_to_bearerbox(bearerbox_host, bearerbox_port, bearerbox_ssl, NULL
		    /* bearerbox_our_port */);

    if (cfg)
        wap_push_ota_bb_address_set(bearerbox_host);
	    
    program_status = running;
    if (0 > heartbeat_start(write_to_bearerbox, heartbeat_freq, 
    	    	    	    	       wap_appl_get_load)) {
        info(0, GW_NAME "Could not start heartbeat.");
    }

    while (program_status != shutting_down) {
	WAPEvent *dgram;
        int ret;

        /* block infinite for reading messages */
        ret = read_from_bearerbox(&msg, INFINITE_TIME);
        if (ret == -1) {
            error(0, "Bearerbox is gone, restarting");
            program_status = shutting_down;
            restart = 1;
            break;
        } else if (ret == 1) /* timeout */
            continue;
        else if (msg == NULL) /* just to be sure, may not happens */
            break;
	if (msg_type(msg) == admin) {
	    if (msg->admin.command == cmd_shutdown) {
		info(0, "Bearerbox told us to die");
		program_status = shutting_down;
	    } else if (msg->admin.command == cmd_restart) {
		info(0, "Bearerbox told us to restart");
		restart = 1;
		program_status = shutting_down;
	    }
	    /*
	     * XXXX here should be suspend/resume, add RSN
	     */
	} else if (msg_type(msg) == wdp_datagram) {
        switch (msg->wdp_datagram.destination_port) {
        case CONNECTIONLESS_PORT:
        case CONNECTION_ORIENTED_PORT:
	    	dgram = wap_event_create(T_DUnitdata_Ind);
	    	dgram->u.T_DUnitdata_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);
	    	dgram->u.T_DUnitdata_Ind.user_data = msg->wdp_datagram.user_data;
	    	msg->wdp_datagram.user_data = NULL;

          	wap_dispatch_datagram(dgram); 
			break;
        case WTLS_CONNECTIONLESS_PORT:
        case WTLS_CONNECTION_ORIENTED_PORT:
#if (HAVE_WTLS_OPENSSL)
            dgram = wtls_unpack_wdp_datagram(msg);
            if (dgram != NULL)
                wtls_dispatch_event(dgram);
#endif
			break;
        default:
                panic(0,"Bad packet received! This shouldn't happen!");
                break;
        } 
	} else {
	    warning(0, "Received other message than wdp/admin, ignoring!");
	}
	msg_destroy(msg);
    }

    info(0, GW_NAME " wapbox terminating.");
    
    program_status = shutting_down;
    heartbeat_stop(ALL_HEARTBEATS);
    counter_destroy(sequence_counter);

    if (cfg)
        wtp_initiator_shutdown();

    wtp_resp_shutdown();
    wsp_push_client_shutdown();
    wsp_unit_shutdown();
    wsp_session_shutdown();
    wap_appl_shutdown();
    radius_acct_shutdown();

    if (cfg) {
        wap_push_ota_shutdown();
        wap_push_ppg_shutdown();
    }

    wml_shutdown();
    close_connection_to_bearerbox();
    alog_close();
    wap_map_destroy();
    wap_map_user_destroy();
    octstr_destroy(device_home);
    octstr_destroy(bearerbox_host);
    octstr_destroy(config_filename);

    /*
     * Just sleep for a while to get bearerbox chance to restart.
     * Otherwise we will fail while trying to connect to bearerbox!
     */
    if (restart) {
        gwthread_sleep(10.0);
        /* now really restart */
        restart_box(argv);
    }

    log_close_all();
    gwlib_shutdown();

    return 0;
}
Beispiel #3
0
static void serverHello(WAPEvent * event, WTLSMachine * wtls_machine)
{
   WAPEvent *req;
   wtls_PDU *serverHelloPDU;
//   wtls_PDU* certificatePDU;
   Random *tempRandom;
/*   List *certList;
   Certificate *cert;
*/ int randomCounter = 0;

   /* Our serverHello */
   serverHelloPDU = wtls_pdu_create(Handshake_PDU);
   serverHelloPDU->rlen = 1;
   serverHelloPDU->snMode = wtls_machine->sequence_number_mode ? 1 : 0;
   serverHelloPDU->u.handshake.msg_type = server_hello;
   serverHelloPDU->u.handshake.server_hello =
       (ServerHello *) gw_malloc(sizeof(ServerHello));

   /* Set our server version */
   serverHelloPDU->u.handshake.server_hello->serverversion = 1;

   /* Get a suitably random number - store it in both the machine structure and outgoing PDU */
   tempRandom = wtls_get_random();
   wtls_machine->server_random = octstr_create("");
   randomCounter =
       pack_int32(wtls_machine->server_random, 0,
             tempRandom->gmt_unix_time);
   octstr_insert(wtls_machine->server_random, tempRandom->random_bytes,
            octstr_len(wtls_machine->server_random));

   serverHelloPDU->u.handshake.server_hello->random = tempRandom;

   /* At the moment, we don't support session caching, so tell them to forget about caching us */
   serverHelloPDU->u.handshake.server_hello->session_id =
       octstr_format("%llu", wtls_machine->mid);

   /* We need to select an appropriate mechanism here from the ones listed */
   serverHelloPDU->u.handshake.server_hello->client_key_id =
       event->u.SEC_Create_Res.client_key_id;

   /* Get our ciphersuite details */
   serverHelloPDU->u.handshake.server_hello->ciphersuite = (CipherSuite *)
       gw_malloc(sizeof(CipherSuite));
   serverHelloPDU->u.handshake.server_hello->ciphersuite->bulk_cipher_algo
       = event->u.SEC_Create_Res.bulk_cipher_algo;
   serverHelloPDU->u.handshake.server_hello->ciphersuite->mac_algo =
       event->u.SEC_Create_Res.mac_algo;
   serverHelloPDU->u.handshake.server_hello->comp_method = null_comp;

   /* We need to confirm the client's choice, or if they haven't 
    * specified one, select one ourselves 
    */
   serverHelloPDU->u.handshake.server_hello->snmode =
       event->u.SEC_Create_Res.snmode;

   /* We need to either confirm the client's choice of key refresh rate, or choose a lower rate */
   serverHelloPDU->u.handshake.server_hello->krefresh =
       event->u.SEC_Create_Res.krefresh;

   /* Add the PDUsto the server's outgoing list  */
   add_pdu(wtls_machine, serverHelloPDU);
   wtls_pdu_destroy(serverHelloPDU);

   /* Generate and dispatch a SEC_Exchange_Req or maybe a SEC_Commit_Req */
   req = wap_event_create(SEC_Exchange_Req);
   req->u.SEC_Exchange_Req.addr_tuple =
       wap_addr_tuple_duplicate(event->u.T_Unitdata_Ind.addr_tuple);
   wtls_dispatch_event(req);
   debug("wtls", 0, "serverHello ~> Dispatching SEC_Exchange_Req event");
}
Beispiel #4
0
static void clientHello(WAPEvent * event, WTLSMachine * wtls_machine)
{
   /* The Wap event we have to dispatch */
   WAPEvent *res;
   wtls_Payload *tempPayload;
   wtls_PDU *clientHelloPDU;
   CipherSuite *ciphersuite;
   int randomCounter, algo;

   tempPayload =
       (wtls_Payload *) gwlist_search(event->u.T_Unitdata_Ind.pdu_list,
                  (void *)client_hello,
                  match_handshake_type);
   if (!tempPayload) {
      error(0, "Illegal PDU while waiting for a ClientHello");
      fatalAlert(event, unexpected_message);
      return;
   }
   clientHelloPDU = wtls_pdu_unpack(tempPayload, wtls_machine);

   /* Store the client's random value - use pack for simplicity */
   wtls_machine->client_random = octstr_create("");
   randomCounter = pack_int32(wtls_machine->client_random, 0,
               clientHelloPDU->u.handshake.client_hello->
               random->gmt_unix_time);
   octstr_insert(wtls_machine->client_random,
            clientHelloPDU->u.handshake.client_hello->random->
            random_bytes, randomCounter);

   /* Select the ciphersuite from the supplied list */
   ciphersuite =
       wtls_choose_ciphersuite(clientHelloPDU->u.handshake.client_hello->
                ciphersuites);
   if (!ciphersuite) {
      error(0, "Couldn't agree on encryption cipher. Aborting");
      wtls_pdu_destroy(clientHelloPDU);
      fatalAlert(event, handshake_failure);
      return;
   }
   /* Set the relevant values in the wtls_machine and PDU structure */
   wtls_machine->bulk_cipher_algorithm = ciphersuite->bulk_cipher_algo;
   wtls_machine->mac_algorithm = ciphersuite->mac_algo;

   /* Generate a SEC_Create_Res event, and pass it back into the queue */
   res = wap_event_create(SEC_Create_Res);
   res->u.SEC_Create_Res.addr_tuple =
       wap_addr_tuple_duplicate(event->u.T_Unitdata_Ind.addr_tuple);
   res->u.SEC_Create_Res.bulk_cipher_algo = ciphersuite->bulk_cipher_algo;
   res->u.SEC_Create_Res.mac_algo = ciphersuite->mac_algo;
   res->u.SEC_Create_Res.client_key_id = wtls_choose_clientkeyid
       (clientHelloPDU->u.handshake.client_hello->client_key_ids, &algo);
   if (!res->u.SEC_Create_Res.client_key_id) {
      error(0, "Couldn't agree on key exchange protocol. Aborting");
      wtls_pdu_destroy(clientHelloPDU);
      wap_event_destroy(res);
      fatalAlert(event, unknown_key_id);
      return;
   }
   wtls_machine->key_algorithm = algo;

   /* Set the sequence number mode in both the machine and the outgoing packet */
   res->u.SEC_Create_Res.snmode =
       wtls_choose_snmode(clientHelloPDU->u.handshake.client_hello->
                snmode);
   wtls_machine->sequence_number_mode = res->u.SEC_Create_Res.snmode;

   /* Set the key refresh mode in both the machine and the outgoing packet */
   res->u.SEC_Create_Res.krefresh =
       clientHelloPDU->u.handshake.client_hello->krefresh;
   wtls_machine->key_refresh = res->u.SEC_Create_Res.krefresh;
   /* Global refresh variable */
   debug("wtls", 0, "clientHello ~> Accepted refresh = %d, refresh_rate = "
         "%d", wtls_machine->key_refresh, 1 << wtls_machine->key_refresh);

   /* Keep the data so we can send it back in EXCHANGE
    * temporary - needs to delete old one if exists !
    * wtls_machine->handshake_data = octstr_create("");
    */
   if (wtls_machine->handshake_data)
      octstr_destroy(wtls_machine->handshake_data);
   wtls_machine->handshake_data = octstr_create("");
   octstr_append(wtls_machine->handshake_data, tempPayload->data);

   debug("wtls", 0, "clientHello ~> Dispatching SEC_Create_Res event");
   wtls_pdu_destroy(clientHelloPDU);
   wtls_dispatch_event(res);
}