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; }
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; }
/* * 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 }
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; }
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; }
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); }
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; }
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,
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; }
/* 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); }
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); }
/* * 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; }