Esempio n. 1
0
int udp_recvfrom(int s, Octstr **datagram, Octstr **addr)
{
    struct sockaddr_in sa;
    socklen_t salen;
    char *buf;
    int bytes;

    buf = gw_malloc(UDP_PACKET_MAX_SIZE);

    salen = sizeof(sa);
    bytes = recvfrom(s, buf, UDP_PACKET_MAX_SIZE, 0, (struct sockaddr *) &sa, &salen);
    if (bytes == -1) {
        if (errno != EAGAIN)
            error(errno, "Couldn't receive UDP packet");
	gw_free(buf);
        return -1;
    }

    *datagram = octstr_create_from_data(buf, bytes);
    *addr = octstr_create_from_data((char *) &sa, salen);

    gw_free(buf);

    return 0;
}
Esempio n. 2
0
Octstr *udp_create_address(Octstr *host_or_ip, int port)
{
    struct sockaddr_in sa;
    struct hostent h;
    char *buff = NULL;
    Octstr *ret;

    sa = empty_sockaddr_in;
    sa.sin_family = AF_INET;
    sa.sin_port = htons(port);

    if (strcmp(octstr_get_cstr(host_or_ip), "*") == 0) {
        sa.sin_addr.s_addr = INADDR_ANY;
    } else {
        if (gw_gethostbyname(&h, octstr_get_cstr(host_or_ip), &buff) == -1) {
            error(0, "Couldn't find the IP number of `%s'",
                  octstr_get_cstr(host_or_ip));
            gw_free(buff);
            return NULL;
        }
        sa.sin_addr = *(struct in_addr *) h.h_addr;
    }

    ret = octstr_create_from_data((char *) &sa, sizeof(sa));
    gw_free(buff);

    return ret;
}
Esempio n. 3
0
/*
 * Calculates a SHA1 hash digest, if openssl library was available
 * on the system, or a less secure MD5 hash digest.
 */
static Octstr *our_hash_func(Octstr *os)
{
#ifdef HAVE_LIBSSL
    /* use openssl's SHA1 */
    EVP_MD_CTX mdctx;
    const EVP_MD *md;
    unsigned char md_value[EVP_MAX_MD_SIZE];
    unsigned int md_len;
    Octstr *ret;

    md = EVP_get_digestbyname("sha1");

    EVP_MD_CTX_init(&mdctx);
    EVP_DigestInit_ex(&mdctx, md, NULL);
    EVP_DigestUpdate(&mdctx, octstr_get_cstr(os), octstr_len(os));
    EVP_DigestFinal_ex(&mdctx, md_value, &md_len);
    EVP_MD_CTX_cleanup(&mdctx);

    ret = octstr_create_from_data((char*) md_value, md_len);
    octstr_binary_to_hex(ret, 0);
    return ret;
#else
    /* fallback to our own MD5 if we don't have openssl available */
    return md5digest(os);
#endif
}
Esempio n. 4
0
static int ois_adjust_originating_address(Msg *msg, const char *raw)
{
    int len;

    SAY(3, "ois_adjust_originating_address");

    len = raw[0] & 0xff;
    msg->sms.sender = octstr_create_from_data(&raw[1+2], len-2);

    return 1 + len;
}
Esempio n. 5
0
int main(int argc, char **argv)
{
    Octstr *data, *filename, *mac, *key;
    unsigned char macbuf[EVP_MAX_MD_SIZE], *p;
    int mac_len;
#ifdef HAVE_LIBSSL
    HMAC_CTX ctx;
#endif

    gwlib_init();

    get_and_set_debugs(argc, argv, NULL);

    if (argc < 3)
        panic(0, "Syntax: %s <key> <file>\n", argv[0]);
  
    key = octstr_create(argv[1]);    
    filename = octstr_create(argv[2]);
    data = octstr_read_file(octstr_get_cstr(filename));

    if (data == NULL)
        panic(0, "Cannot read file.");

    debug("",0,"Dumping file `%s':", octstr_get_cstr(filename));
    octstr_dump(data, 0);

#ifdef HAVE_LIBSSL
    HMAC_Init(&ctx, octstr_get_cstr(key), octstr_len(key), EVP_sha1());
    p = HMAC(EVP_sha1(), octstr_get_cstr(key), octstr_len(key), 
         octstr_get_cstr(data), octstr_len(data), 
         macbuf, &mac_len);
    HMAC_cleanup(&ctx);
#else
    macbuf[0] = 0;
    mac_len = 0;
    p = macbuf;
    warning(0, "No SSL support. Can't calculate HMAC value.");
#endif
    
    mac = octstr_create_from_data(p, mac_len);
    octstr_binary_to_hex(mac, 0);
    
    debug("",0,"HMAC of file `%s' and key `%s' is:", 
          octstr_get_cstr(filename), octstr_get_cstr(key));
    octstr_dump(mac, 0);      

    octstr_destroy(data);
    octstr_destroy(mac);
    octstr_destroy(key);
    gwlib_shutdown();
    return 0;
}
Esempio n. 6
0
static Octstr *our_hash_func(Octstr *os)
{
    /* use openssl's SHA1 */
    EVP_MD_CTX mdctx;
    const EVP_MD *md;
    unsigned char md_value[EVP_MAX_MD_SIZE];
    unsigned int md_len;

    md = EVP_get_digestbyname("sha1");

    EVP_MD_CTX_init(&mdctx);
    EVP_DigestInit_ex(&mdctx, md, NULL);
    EVP_DigestUpdate(&mdctx, octstr_get_cstr(os), octstr_len(os));
    EVP_DigestFinal_ex(&mdctx, md_value, &md_len);
    EVP_MD_CTX_cleanup(&mdctx);

    return octstr_create_from_data((char*) md_value, md_len);
}
/* MAC calculation */
Octstr *wtls_hmac_hash(Octstr * key, Octstr * data, int algo)
{
    static unsigned char final_mac[1024];
    unsigned char *mac, *buffer, *keyString;
   int bufferlen, keylen;
   uint mac_len = 0;
   Octstr *returnOctstr = NULL;
	
   buffer = (unsigned char *)octstr_get_cstr(data);
	bufferlen = octstr_len(data);
   keyString = (unsigned char *)octstr_get_cstr(key);
	keylen = octstr_len(key);
	
	mac = final_mac;
	
   switch (algo) {
		case SHA_0:
      /* Do nothing */
			break;

		case SHA_40:
		case SHA_80:
		case SHA_NOLIMIT:
      HMAC(EVP_sha1(), keyString, keylen, buffer, bufferlen, mac,
           &mac_len);
			break;

		case SHA_XOR_40:
      error(0, "wtls_hmac_hash: SHA_XOR_40 Mac not supported");
			// dunno yet
      *mac = '\0';
			break;

		case MD5_40:
		case MD5_80:
		case MD5_NOLIMIT:
      HMAC(EVP_md5(), keyString, keylen, buffer, bufferlen, mac,
           &mac_len);
			break;
	}
   returnOctstr = octstr_create_from_data((char *)mac, mac_len);
   return (returnOctstr);
}
Esempio n. 8
0
static int oracle_select(void *theconn, const Octstr *sql, List *binds, List **res)
{
    List *row;
    OCIStmt *stmt;
    OCIParam *dparam;
    sword status;
    ub4 columns;
    ub4 i;
    struct data_s {
        text *data;
        ub2 size;
        sb2 ind;
        ub2 type;
    };
    struct data_s *data;
    struct ora_conn *conn = (struct ora_conn*) theconn;
    int binds_len = (binds ? gwlist_len(binds) : 0);

    *res = NULL;

    /* allocate statement handle */
    status = OCIHandleAlloc(conn->envp, (dvoid**)&stmt, OCI_HTYPE_STMT, 0,0);
    if (OCI_SUCCESS != status) {
        oracle_checkerr(conn->errhp, status);
        return -1;
    }
    /* prepare statement */
    status = OCIStmtPrepare(stmt, conn->errhp, (unsigned char*)octstr_get_cstr(sql), 
                            octstr_len(sql), OCI_NTV_SYNTAX, OCI_DEFAULT);
    if (OCI_SUCCESS != status) {
        oracle_checkerr(conn->errhp, status);
        OCIHandleFree(stmt, OCI_HTYPE_STMT);
        return -1;
    }

    /* bind variables */
    for (i = 0; i < binds_len; i++) {
        OCIBind *bndhp = NULL;
        Octstr *bind = gwlist_get(binds, i);
        status = OCIBindByPos(stmt, &bndhp, 
                              conn->errhp, (i+1), (dvoid *) octstr_get_cstr(bind),
                              (sword) octstr_len(bind)+1, SQLT_STR, (dvoid *) 0, (ub2 *)0,
                              (ub2 *)0, (ub4)0, (ub4 *)0, OCI_DEFAULT);
        if (OCI_SUCCESS != status) {
            oracle_checkerr(conn->errhp, status);
            OCIHandleFree(stmt, OCI_HTYPE_STMT);
            return -1;
        }
    }
    /* execute our statement */
    status = OCIStmtExecute(conn->svchp, stmt, conn->errhp, 0, 0, NULL, NULL, 
                            OCI_DEFAULT);
    if (OCI_SUCCESS != status && OCI_NO_DATA != status) {
        oracle_checkerr(conn->errhp, status);
        OCIHandleFree(stmt, OCI_HTYPE_STMT);
        return -1;
    }
    /* receive column count */
    status = OCIAttrGet(stmt, OCI_HTYPE_STMT, &columns, 0, OCI_ATTR_PARAM_COUNT, 
                        conn->errhp);
    if (status != OCI_SUCCESS) {
        oracle_checkerr(conn->errhp, status);
        OCIHandleFree(stmt, OCI_HTYPE_STMT);
        return -1;
    }

    debug("dbpool.oracle",0,"SQL has %d columns", columns);

    /* allocate array of pointers */
    debug("dbpool.oracle",0,"alloc size=%ld",sizeof(text*)*columns);
    data = gw_malloc(sizeof(struct data_s)*columns);

    debug("dbpool.oracle",0,"retrieve data_size");
    /* retrieve data size for every column and allocate it */
    for (i=0 ; i < columns; i++) {
        OCIDefine *defh;

        status = OCIParamGet(stmt, OCI_HTYPE_STMT, conn->errhp, 
                             (dvoid**) &dparam, i+1);
        if (status != OCI_SUCCESS) {
            oracle_checkerr(conn->errhp, status);
            columns = i;
            for (i = 0; i < columns; i++)
                gw_free(data[i].data);
            gw_free(data);
            OCIHandleFree(stmt, OCI_HTYPE_STMT);
            return -1;
        }

        status = OCIAttrGet(dparam, OCI_DTYPE_PARAM, (dvoid*) &data[i].size, 
                            0, OCI_ATTR_DATA_SIZE, conn->errhp);
        if (status != OCI_SUCCESS) {
            oracle_checkerr(conn->errhp, status);
            columns = i;
            for (i = 0; i < columns; i++)
                gw_free(data[i].data);
            gw_free(data);
            OCIHandleFree(stmt, OCI_HTYPE_STMT);
            return -1;
        }

        status = OCIAttrGet(dparam, OCI_DTYPE_PARAM, (dvoid*) &data[i].type, 
                            0, OCI_ATTR_DATA_TYPE, conn->errhp);
        if (status != OCI_SUCCESS) {
            oracle_checkerr(conn->errhp, status);
            columns = i;
            for (i = 0; i < columns; i++)
                gw_free(data[i].data);
            gw_free(data);
            OCIHandleFree(stmt, OCI_HTYPE_STMT);
            return -1;
        }

        /* convert all data types to C-Strings except DATE */
        if (data[i].type != SQLT_DAT) {
            data[i].size++; /* terminating zero */
            data[i].type = SQLT_STR;
        }

        debug("dbpool.oracle",0,"alloc size=%d", data[i].size);
        data[i].data = gw_malloc(data[i].size);

        /* bind allocated values to statement handle */
        status = OCIDefineByPos(stmt, &defh, conn->errhp, i+1, data[i].data, 
                                data[i].size, data[i].type, &data[i].ind, 
                                0, 0, OCI_DEFAULT);
        if (status != OCI_SUCCESS) {
            oracle_checkerr(conn->errhp, status);
            columns = i;
            for (i = 0; i <= columns; i++)
                gw_free(data[i].data);
            gw_free(data);
            OCIHandleFree(stmt, OCI_HTYPE_STMT);
            return -1;
        }
    }

    *res = gwlist_create();
    /* fetch data */
    while ((status = OCIStmtFetch(stmt, conn->errhp, 1, 
                                  OCI_FETCH_NEXT, OCI_DEFAULT)) == OCI_SUCCESS ||
            status == OCI_SUCCESS_WITH_INFO) {

        row = gwlist_create();
        for (i = 0; i < columns; i++) {
            if (data[i].data == NULL || data[i].ind == -1) {
                gwlist_insert(row, i, octstr_create(""));
            } else {
                gwlist_insert(row, i, octstr_create_from_data((const char*)data[i].data, data[i].size));
            }
            /* debug("dbpool.oracle",0,"inserted value = '%s'", 
                     octstr_get_cstr(gwlist_get(row,i))); */
        }
        gwlist_append(*res, row);
    }

    /* ignore OCI_NO_DATA error */
    if (status != OCI_NO_DATA) {
        List *row;
        oracle_checkerr(conn->errhp, status);
        for (i = 0; i < columns; i++)
            gw_free(data[i].data);
        gw_free(data);
        while ((row = gwlist_extract_first(*res)) != NULL)
            gwlist_destroy(row, octstr_destroy_item);
        gwlist_destroy(*res, NULL);
        *res = NULL;
        OCIHandleFree(stmt, OCI_HTYPE_STMT);
        return -1;
    }

    for (i = 0; i < columns; i++)
        gw_free(data[i].data);

    gw_free(data);
    OCIHandleFree(stmt, OCI_HTYPE_STMT);

    return 0;
}
Esempio n. 9
0
		client->wtp_tid++;
}

/* Set the U/P flag on an Invoke PDU */
static void set_user_ack(Octstr *pdu) {
	octstr_set_bits(pdu, 3 * 8 + 3, 1, 1);
}

static Octstr *wtp_invoke_create(int class) {
	Octstr *pdu;
	/* data describes a TR-Invoke PDU, with GTR=1 and TTR=1 (segmentation
	 * not supported), and Transaction class 0 (which we replace below) */
	static unsigned char data[] = { 0x0e, 0x00, 0x00, 0x00 };
	gw_assert(class >= 0);
	gw_assert(class <= 2);
	pdu = octstr_create_from_data(data, sizeof(data));
	octstr_set_char(pdu, 3, class);

	if (user_ack)
		set_user_ack(pdu);

	return pdu;
}

static Octstr *wtp_ack_create(void) {
	static unsigned char data[] = { 0x18, 0x00, 0x00 };
	return octstr_create_from_data(data, sizeof(data));
}

static void add_wsp_connect(Octstr *pdu) {
	static unsigned char data[] = { Connect_PDU, WSP_VERSION, 68, 0x00,
Esempio n. 10
0
static int ois_adjust_sm_text(Msg *msg, const char *raw)
{
    int msglen7, msglen8;
    char buffer[BUFLEN+1];

    SAY(3, "ois_adjust_sm_text");

    /* calculate lengths */

    msglen7 = raw[0] & 0xff;
    msglen8 = raw[1] & 0xff;

    /* copy text, note: flag contains temporarily the raw type description */

    switch ((msg->sms.coding - 1) & 0xff) { 
    case 0x00: /* gsm7 */
	ois_expand_gsm7(buffer, &raw[2], msglen7);
	ois_convert_to_iso88591(buffer, msglen7);
	if (msg->sms.mclass & 0x02) { /* XXX mclass temporarily */
	    msg->sms.msgdata = octstr_create("");
	    msg->sms.udhdata = octstr_create_from_data(buffer, msglen7);
	} else {
	    msg->sms.msgdata = octstr_create_from_data(buffer, msglen7);
	    msg->sms.udhdata = octstr_create("");
	}
	msg->sms.coding = DC_7BIT;
	break;
    case 0x0f: /* ia5 */
	memcpy(buffer, &raw[2], msglen8);
	ois_convert_to_iso88591(buffer, msglen8);
	if (msg->sms.mclass & 0x02) { /* XXX mclass temporarily */
	    msg->sms.msgdata = octstr_create("");
	    msg->sms.udhdata = octstr_create_from_data(buffer, msglen8);
	} else {
	    msg->sms.msgdata = octstr_create_from_data(buffer, msglen8);
	    msg->sms.udhdata = octstr_create("");
	}
	msg->sms.coding = DC_7BIT;
	break;
    default: /* 0xf4, 0xf5, 0xf6, 0xf7; 8bit to disp, mem, sim or term */ 
	if (msg->sms.mclass & 0x02) { /* XXX mclass temporarily */
	    msg->sms.msgdata = octstr_create("");
	    msg->sms.udhdata = octstr_create_from_data(&raw[2], msglen8);
	} else {
	    msg->sms.msgdata = octstr_create_from_data(&raw[2], msglen8);
	    msg->sms.udhdata = octstr_create("");
	}
	msg->sms.coding = DC_8BIT;
	break;
    }
    msg->sms.mclass = MC_UNDEF;

    if (octstr_len(msg->sms.udhdata)) {
	IOTRACE("decoded udh", octstr_get_cstr(msg->sms.udhdata),
		octstr_len(msg->sms.udhdata));
    } else {
	IOTRACE("decoded", octstr_get_cstr(msg->sms.msgdata),
		octstr_len(msg->sms.msgdata));
    }

    return 2 + msglen8;
}
Esempio n. 11
0
/* Not to be confused with octstr_hash, this applies the currently set hashing
   algorithm from wtls_machine to the supplied input data, returning a hashed
   Octstr. If it fails, it will return a NULL pointer */
Octstr *wtls_hash(Octstr * inputData, WTLSMachine * wtls_machine)
{
        int inputDataLength;
        int outputDataLength;
   unsigned char *outputDataTemp;
   unsigned char *inputDataTemp;
   unsigned char *tempPointer = NULL;
   Octstr *outputData;

        inputDataLength = octstr_len(inputData);
        outputDataLength = hash_table[wtls_machine->mac_algorithm].key_size;
        inputDataTemp = gw_malloc(inputDataLength);
        outputDataTemp = gw_malloc(outputDataLength);

        /* Copy the contents of inputData into inputDataTemp, ready for hashing */
   tempPointer = (unsigned char *)octstr_get_cstr(inputData);
   memcpy((void *)inputDataTemp, (void *)tempPointer, inputDataLength);
        
        /* Hash away! */
        // Here's where we need to hash on the selected algorithm, not just the SHA-1 algorithm
		//debug("wtls", 0, "mac algo %d", wtls_machine->mac_algorithm);
        switch (wtls_machine->mac_algorithm) {
			case SHA_0:
      /* Do nothing */
				break;

			case SHA_40:
			case SHA_80:
			case SHA_NOLIMIT:
      tempPointer =
          SHA1(inputDataTemp, inputDataLength, outputDataTemp);
				break;

			case SHA_XOR_40:
				// dunno yet
				break;

			case MD5_40:
			case MD5_80:
			case MD5_NOLIMIT:
      tempPointer = MD5(inputDataTemp, inputDataLength,
              outputDataTemp);
				break;
		}
   if (!tempPointer) {
      if (wtls_machine->mac_algorithm != SHA_0)
         error(0, "wtls_hash: Failed to hash input");
      gw_free(outputDataTemp);
      gw_free(inputDataTemp);
      return (NULL);
        }

        /* Get our output data setup */
   outputData = octstr_create_from_data((char *)outputDataTemp,
                    outputDataLength);
        
		/* some algorithms don't use the full length of H */
   octstr_truncate(outputData,
         hash_table[wtls_machine->mac_algorithm].mac_size);
		
        /* Delete our allocated memory */
        gw_free(outputDataTemp);
        gw_free(inputDataTemp);
        
        /* Return the outputData */
   return (outputData);
}
Esempio n. 12
0
Octstr *wtls_decrypt(wtls_Payload * payload, WTLSMachine * wtls_machine)
{
   int len, padLen = 0, macSize, recordType, block, refresh;
   Octstr *openText, *MAContent, *tempData, *result;
   char cipher[20], *p;

   if (payload->seqNum && wtls_machine->client_seq_num > payload->seqNum) {
      error(0,
            "Out of sequence packet received (p: %d < %d :w). Dropping datagram.",
            payload->seqNum, wtls_machine->client_seq_num);
      return (NULL);
   } else
      wtls_machine->client_seq_num = payload->seqNum;
   refresh = 1 << wtls_machine->key_refresh;
   if (wtls_machine->last_refresh < 0 || (wtls_machine->last_refresh +
                      refresh <=
                      wtls_machine->client_seq_num))
      calculate_client_key_block(wtls_machine);
   switch (wtls_machine->bulk_cipher_algorithm) {
   case NULL_bulk:
      openText = octstr_duplicate(payload->data);
      break;

   case RC5_CBC:
   case RC5_CBC_40:
   case RC5_CBC_56:
      openText = wtls_rc5(payload->data, wtls_machine, RC5_DECRYPT);
      break;

   case DES_CBC:
   case DES_CBC_40:
      openText = wtls_des(payload->data, wtls_machine, DES_DECRYPT);
      break;

   default:
      cipherName(cipher, wtls_machine->bulk_cipher_algorithm);
      error(0,
            "wtls_decrypt: Unsupported bulk cipher algorithm (%s).",
            cipher);
      return (NULL);
      break;
   }
   /* Verify MAC */
   recordType = 1 << 7;
   recordType |= payload->snMode << 6;
   recordType |= payload->cipher << 5;
   recordType |= payload->reserved << 4;
   recordType |= payload->type;
   len = octstr_len(openText);
   p = octstr_get_cstr(openText);
   block = bulk_table[wtls_machine->bulk_cipher_algorithm].block_size;

   padLen = *(p + len - 1);
   if (padLen >= block || padLen != *(p + len - 2))
      padLen = 0;
   padLen++;
   macSize = hash_table[wtls_machine->mac_algorithm].mac_size;

   tempData = octstr_create("");
   pack_int16(tempData, 0, wtls_machine->client_seq_num);
   octstr_append_char(tempData, recordType);
   pack_int16(tempData, 3, len - macSize - padLen);
   octstr_append_data(tempData, p, len - macSize - padLen);
   MAContent = wtls_hmac_hash(wtls_machine->client_write_MAC_secret,
               tempData, wtls_machine->mac_algorithm);
   if (memcmp(octstr_get_cstr(MAContent), p + len - padLen - macSize,
         macSize)) {
      octstr_destroy(MAContent);
      octstr_destroy(tempData);
      octstr_destroy(openText);
      error(0, "wtls_decrypt: Rejected packet due to bad MAC");
      return (NULL);
   }
   octstr_destroy(MAContent);
   octstr_destroy(tempData);
   result = octstr_create_from_data((char *)p, len - padLen - macSize);
   octstr_destroy(openText);
   return (result);
}
Esempio n. 13
0
/*
 * Our WSP headers: Push Id, PDU type, headers, charset.
 */
static int ota_pack_push_headers(Msg **msg, Octstr *mime_type, Octstr *sec, 
                                 Octstr *pin, Octstr *ota_binary)
{    
    (*msg)->sms.msgdata = octstr_create("");
    if (octstr_case_compare(mime_type, octstr_imm("settings")) == 0) {
        
        /* PUSH ID, PDU type, header length, value length */
        octstr_append_from_hex((*msg)->sms.msgdata, "01062C1F2A");
        /* MIME type for settings */
        octstr_format_append((*msg)->sms.msgdata, "%s", 
                             "application/x-wap-prov.browser-settings");
        octstr_append_from_hex((*msg)->sms.msgdata, "00");
        /* charset UTF-8 */
        octstr_append_from_hex((*msg)->sms.msgdata, "81EA");

    } else if (octstr_case_compare(mime_type, octstr_imm("bookmarks")) == 0) {
        
        /* PUSH ID, PDU type, header length, value length */
        octstr_append_from_hex((*msg)->sms.msgdata, "01062D1F2B");
        /* MIME type for bookmarks */
        octstr_format_append((*msg)->sms.msgdata, "%s", 
                             "application/x-wap-prov.browser-bookmarks");
        octstr_append_from_hex((*msg)->sms.msgdata, "00");
        /* charset UTF-8 */
        octstr_append_from_hex((*msg)->sms.msgdata, "81EA");

    } else if (octstr_case_compare(mime_type, octstr_imm("syncsettings")) == 0) {

        octstr_append_from_hex((*msg)->sms.msgdata, "3406060502020b81EA"); 

    } else if (octstr_case_compare(mime_type, octstr_imm("oma-settings")) == 0) {
        Octstr *hdr = octstr_create(""), *mac; 
        unsigned char *p;
        unsigned int mac_len;
#ifdef HAVE_LIBSSL
        unsigned char macbuf[EVP_MAX_MD_SIZE];
#endif

        /* PUSH ID, PDU type, header length, value length */
        octstr_append_from_hex((*msg)->sms.msgdata, "0106");
    
        octstr_append_from_hex(hdr, "1f2db6"); /* Content type + other type + sec param */
        wsp_pack_short_integer(hdr, 0x11);
        if (octstr_case_compare(sec, octstr_imm("netwpin")) == 0)
            wsp_pack_short_integer(hdr, 0x0);       
        else if (octstr_case_compare(sec, octstr_imm("userpin")) == 0)
            wsp_pack_short_integer(hdr, 0x01);          
        else if (octstr_case_compare(sec, octstr_imm("usernetwpin")) == 0)
            wsp_pack_short_integer(hdr, 0x02);          
        else if (octstr_case_compare(sec, octstr_imm("userpinmac")) == 0)
            wsp_pack_short_integer(hdr, 0x03); /* XXXX Although not quite supported now.*/          
        else {
            warning(0, "OMA ProvCont: Unknown SEC pin type '%s'.", octstr_get_cstr(sec));
            wsp_pack_short_integer(hdr, 0x01);          
        }
        wsp_pack_short_integer(hdr, 0x12); /* MAC */

#ifdef HAVE_LIBSSL
        p = HMAC(EVP_sha1(), octstr_get_cstr(pin), octstr_len(pin), 
                 (unsigned char *)octstr_get_cstr(ota_binary), octstr_len(ota_binary), 
                 macbuf, &mac_len);
#else
        mac_len = 0;
        p = "";
        warning(0, "OMA ProvCont: No SSL Support, '%s' not supported!", octstr_get_cstr(mime_type));
#endif
        mac = octstr_create_from_data((char *)p, mac_len);
        octstr_binary_to_hex(mac, 1);
    
        octstr_append(hdr, mac);
        octstr_append_from_hex(hdr, "00");
    
        octstr_append_uintvar((*msg)->sms.msgdata, octstr_len(hdr));
        octstr_append((*msg)->sms.msgdata, hdr);
    
        octstr_destroy(hdr);
        octstr_destroy(mac);
        
    } else {
        warning(0, "Unknown MIME type in OTA request, type '%s' is unsupported.", 
                octstr_get_cstr(mime_type));
        return 0;
    }

    return 1;
}