📄 wtls_pdu.c
字号:
/* ==================================================================== * The Kannel Software License, Version 1.0 * * Copyright (c) 2001-2004 Kannel Group * Copyright (c) 1998-2001 WapIT Ltd. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Kannel Group (http://www.kannel.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Kannel" and "Kannel Group" must not be used to * endorse or promote products derived from this software without * prior written permission. For written permission, please * contact org@kannel.org. * * 5. Products derived from this software may not be called "Kannel", * nor may "Kannel" appear in their name, without prior written * permission of the Kannel Group. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Kannel Group. For more information on * the Kannel Group, please see <http://www.kannel.org/>. * * Portions of this software are based upon software originally written at * WapIT Ltd., Helsinki, Finland for the Kannel project. */ /* * wtls_pdu.c: pack and unpack WTLS packets * * Generates packing and unpacking code from wtls_pdu.def. * */#include "gwlib/gwlib.h"#if (HAVE_WTLS_OPENSSL)#include "gwlib/octstr.h"#include "wtls_pdu.h"#include "wtls_pdusupport.h"#include "wtls_statesupport.h"KeyExchangeSuite client_key_exchange_algo = rsa_anon;PublicKeyAlgorithm public_key_algo;SignatureAlgorithm signature_algo;int seqnum;wtls_Payload* wtls_payload_unpack_from_offset (Octstr *data, int *offset);wtls_PDU *wtls_pdu_create(int type) { wtls_PDU *pdu; pdu = gw_malloc(sizeof(*pdu)); pdu->type = type; pdu->reserved = 0; pdu->cipher = 0; pdu->seqnum = 0; pdu->rlen = 0; switch (pdu->type) { case ChangeCipher_PDU: pdu->u.cc.change = 1; break; case Alert_PDU: pdu->u.alert.level = 0; pdu->u.alert.desc = 0; pdu->u.alert.chksum = 0; break; case Handshake_PDU: pdu->u.handshake.msg_type = 0; pdu->u.handshake.length = 0; break; case Application_PDU: pdu->u.application.data = NULL; break; default: warning(0, "Cannot create unknown WTLS PDU type %d", pdu->type); break; } return pdu;}void wtls_payload_destroy(wtls_Payload *payload) { octstr_destroy(payload->data); gw_free(payload);}void wtls_pdu_destroy(wtls_PDU *pdu) { if (pdu == NULL) return; switch (pdu->type) { case ChangeCipher_PDU: /* no memory was allocated for ChangeCipher_PDU */ break; case Alert_PDU: octstr_destroy(pdu->u.alert.chksum ); break; case Handshake_PDU: switch (pdu->u.handshake.msg_type) { case hello_request: break; case client_hello: destroy_random(pdu->u.handshake.client_hello->random); octstr_destroy(pdu->u.handshake.client_hello->session_id); destroy_key_list(pdu->u.handshake.client_hello->client_key_ids); destroy_key_list(pdu->u.handshake.client_hello->trusted_key_ids); destroy_ciphersuite_list(pdu->u.handshake.client_hello->ciphersuites); destroy_compression_method_list(pdu->u.handshake.client_hello->comp_methods); /* destroy the client_hello struct */ gw_free(pdu->u.handshake.client_hello); break; case server_hello: destroy_random(pdu->u.handshake.server_hello->random); octstr_destroy(pdu->u.handshake.server_hello->session_id); /* destroy the server_hello struct */ gw_free(pdu->u.handshake.server_hello); break; case certificate: switch (pdu->u.handshake.certificate->certificateformat) { case WTLSCert: destroy_wtls_certificate(pdu->u.handshake.certificate->wtls_certificate); break; case X509Cert: octstr_destroy(pdu->u.handshake.certificate->x509_certificate); break; case X968Cert: octstr_destroy(pdu->u.handshake.certificate->x968_certificate); break; } gw_free(pdu->u.handshake.certificate); break; case server_key_exchange: destroy_param_spec(pdu->u.handshake.server_key_exchange->param_spec); switch (client_key_exchange_algo) { case rsa_anon: destroy_rsa_pubkey(pdu->u.handshake.server_key_exchange->rsa_params); break; case dh_anon: destroy_dh_pubkey(pdu->u.handshake.server_key_exchange->dh_params); break; case ecdh_anon: destroy_ec_pubkey(pdu->u.handshake.server_key_exchange->ecdh_params); break; } gw_free(pdu->u.handshake.server_key_exchange); break; case client_key_exchange: switch (client_key_exchange_algo) { case rsa: case rsa_anon: destroy_rsa_encrypted_secret(pdu->u.handshake.client_key_exchange->rsa_params); break; case dh_anon: destroy_dh_pubkey(pdu->u.handshake.client_key_exchange->dh_anon_params); break; case ecdh_anon: case ecdh_ecdsa: destroy_ec_pubkey(pdu->u.handshake.client_key_exchange->ecdh_params); break; } gw_free(pdu->u.handshake.client_key_exchange); break; case server_hello_done: /* nothing to do here */ break; } break; case Application_PDU: octstr_destroy(pdu->u.application.data); break; } gw_free(pdu);}/* This function will pack a list of WTLS PDUs into a single Octstr, and return that Octstr. */Octstr* wtls_pack_payloadlist (List* payloadlist) { Octstr *returnData=0, *tempData1=0, *tempData2 = 0; wtls_Payload* retrievedPDU; /* Assert that our payloadlist is not NULL */ gw_assert (payloadlist != NULL); /* Initialise our return Octstr */ returnData = octstr_create(""); /* While there are PDUs remaining in our list */ while (list_len(payloadlist) > 0) { /* Retrieve the next payload from the payloadlist */ retrievedPDU = (wtls_Payload*) list_extract_first (payloadlist); /* Pack the PDU */ tempData2 = wtls_payload_pack(retrievedPDU); /* Shift the current stuff in returnData to a temporary pointer */ tempData1 = returnData; /* Tack it onto our Octstr */ returnData = octstr_cat(tempData1, tempData2); /* And now, we can get rid of both tempData1 and tempData2 */ octstr_destroy (tempData1); octstr_destroy (tempData2); } /* Is the Octstr we finish with of length > 0? */ if (octstr_len(returnData) > 0) { /* Return the Octstr */ return returnData; } /* Otherwise, return NULL */ return NULL;}/* This function will unpack an Octstr and return a list of all PDUs contained within that Octstr. If the contents of the packet are garbled in some fashion, and one packet fails to be decoded correctly, we will continue regardless, and a partial list will be returned. NULL is returned if no PDUs can be successfully decoded from the supplied data */List* wtls_unpack_payloadlist (Octstr *data) { List* payloadlist = NULL; int offset = 0; int dataLength = 0; wtls_Payload* tempPayload; /* Has somebody passed in an unpack of a null pointer ? */ gw_assert(data != NULL); /* Initialise our list */ payloadlist = list_create(); dataLength = octstr_len(data); /* While offset is less than the size of the data */ while( offset < dataLength) { debug("wtls:wtls_unpack_payloadlist",0,"Offset is now : %d", offset); /* Unpack from the supplied offset. This will bump up the value of offset */ tempPayload = wtls_payload_unpack_from_offset (data, &offset); /* If the packet returned is not NULL */ if (tempPayload != NULL) { /* Add the returned packet to the current list of packets */ list_append(payloadlist, (void*) tempPayload); } } debug("wtls:wtls_unpack_payloadlist",0,"Finished, found %d PDUs", list_len(payloadlist)); /* If the length of the list is greater than 0 */ if (list_len(payloadlist) > 0) { /* Return the List */ return payloadlist; } /* Otherwise return NULL */ return NULL;}/* This function tries to determine the length of the PDU at the start of the supplied Octstr using (somewhat) intelligent means. If the packet is screwed up in some fashion, returns length -1. Returns an int. */int wtls_payload_guess_length(Octstr* data) { int type = 0, lengthFlag = 0, lengthSize = 0, pdu_length = 0; long lengthOffset = 1; /* Is the fragment length indicator on? */ lengthFlag = octstr_get_bits(data, 0, 1); if (lengthFlag) { lengthSize = 2; } /* Is the sequence number indicator on? */ if (octstr_get_bits(data, 1, 1)) { /* Yes, so hop over two extra bytes when reading the length */ lengthOffset += 2; } /* the message type */ type = octstr_get_bits(data, 4, 4); /* If fragment length is turned on, jump to the necessary spot */ if (lengthFlag == 1) { /* After this, lengthOffset + pdu_length == the total length of the PDU */ pdu_length = unpack_int16(data, &lengthOffset); } /* Oh great, so it's not switched on. How considerate. We'll have to make a reasonable guess as to what it might be. */ else { switch (type) { case ChangeCipher_PDU: /* They're really short */ pdu_length = 1; break; case Alert_PDU: /* They're a bit longer */ pdu_length = 6; break; default: /* Otherwise just give up and play dead */ pdu_length = -1; break; } } /* And that's the length of the contents, now just add the other doodads on */ if (pdu_length == -1) { return -1; } else { /* The pdu length, plus the sequence number, plus the length of the length value, plus the actual header byte */ return (pdu_length + lengthOffset);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -