int sip_parse_msg_payload(sip_msg_t *msg, const u_char *payload) { regmatch_t pmatch[4]; // From if (regexec(&calls.reg_from, (const char *)payload, 4, pmatch, 0) == 0) { msg->sip_from = sng_malloc((int)pmatch[2].rm_eo - pmatch[2].rm_so + 1); strncpy(msg->sip_from, (const char *)payload + pmatch[2].rm_so, (int)pmatch[2].rm_eo - pmatch[2].rm_so); } else { // Malformed From Header msg->sip_from = sng_malloc(12); strncpy(msg->sip_from, "<malformed>", 11); } // To if (regexec(&calls.reg_to, (const char *)payload, 4, pmatch, 0) == 0) { msg->sip_to = sng_malloc((int)pmatch[2].rm_eo - pmatch[2].rm_so + 1); strncpy(msg->sip_to, (const char *)payload + pmatch[2].rm_so, (int)pmatch[2].rm_eo - pmatch[2].rm_so); } else { // Malformed To Header msg->sip_to = sng_malloc(12); strncpy(msg->sip_to, "<malformed>", 11); } return 0; }
capture_packet_t * capture_packet_create(const struct pcap_pkthdr *header, const u_char *packet, int size) { capture_packet_t *pkt; pkt = sng_malloc(sizeof(capture_packet_t)); pkt->header = sng_malloc(sizeof(struct pcap_pkthdr)); pkt->data = sng_malloc(size); memcpy(pkt->header, header, sizeof(struct pcap_pkthdr)); memcpy(pkt->data, packet, size); pkt->size = size; return pkt; }
int tls_process_record_data(struct SSLConnection *conn, const opaque *fragment, const int len, uint8_t **out, uint32_t *outl) { gcry_cipher_hd_t *evp; unsigned char pad; unsigned char *decoded; size_t dlen = len; if (conn->direction == 0) { evp = &conn->client_cipher_ctx; } else { evp = &conn->server_cipher_ctx; } decoded = sng_malloc(len); gcry_cipher_decrypt(*evp, decoded, dlen, (unsigned char *) fragment, len); // Get padding counter and remove from data pad = decoded[len - 1]; dlen = (len - (pad + 1) - /* Trailing MAC */20); if ((int32_t)dlen > 0 && dlen <= *outl) { memcpy(*out, decoded, dlen); *outl = dlen; } // Clenaup decoded memory sng_free(decoded); return *outl; }
void msg_diff_create(ui_t *ui) { int hwidth; msg_diff_info_t *info; // Create a new panel to fill all the screen ui_panel_create(ui, LINES, COLS); // Initialize panel specific data info = sng_malloc(sizeof(msg_diff_info_t)); // Store it into panel userptr set_panel_userptr(ui->panel, (void*) info); // Calculate subwindows width hwidth = ui->width / 2 - 1; // Create 2 subwindows, one for each message info->one_win = subwin(ui->win, ui->height - 2, hwidth, 1, 0); info->two_win = subwin(ui->win, ui->height - 2, hwidth, 1, hwidth + 1); // Header - Footer - Address // Draw a vertical line to separe both subwindows mvwvline(ui->win, 0, hwidth, ACS_VLINE, ui->height); // Draw title ui_set_title(ui, "sngrep - SIP messages flow viewer"); // Draw keybindings msg_diff_draw_footer(ui); }
sip_call_t * call_create(char *callid, char *xcallid) { sip_call_t *call; // Initialize a new call structure if (!(call = sng_malloc(sizeof(sip_call_t)))) return NULL; // Create a vector to store call messages call->msgs = vector_create(2, 2); vector_set_destroyer(call->msgs, msg_destroyer); // Create an empty vector to store rtp packets if (setting_enabled(SETTING_CAPTURE_RTP)) { call->rtp_packets = vector_create(0, 40); vector_set_destroyer(call->rtp_packets, packet_destroyer); } // Create an empty vector to strore stream data call->streams = vector_create(0, 2); vector_set_destroyer(call->streams, vector_generic_destroyer); // Create an empty vector to store x-calls call->xcalls = vector_create(0, 1); // Initialize call filter status call->filtered = -1; // Set message callid call->callid = strdup(callid); call->xcallid = strdup(xcallid); return call; }
struct SSLConnection * tls_connection_create(struct in_addr caddr, uint16_t cport, struct in_addr saddr, uint16_t sport) { struct SSLConnection *conn = NULL; conn = sng_malloc(sizeof(struct SSLConnection)); memcpy(&conn->client_addr, &caddr, sizeof(struct in_addr)); memcpy(&conn->server_addr, &saddr, sizeof(struct in_addr)); memcpy(&conn->client_port, &cport, sizeof(uint16_t)); memcpy(&conn->server_port, &sport, sizeof(uint16_t)); SSL_library_init(); ERR_load_crypto_strings(); OpenSSL_add_all_algorithms(); if (!(conn->ssl_ctx = SSL_CTX_new(SSLv23_server_method()))) return NULL; SSL_CTX_use_PrivateKey_file(conn->ssl_ctx, capture_get_keyfile(), SSL_FILETYPE_PEM); if (!(conn->ssl = SSL_new(conn->ssl_ctx))) return NULL; conn->server_private_key = SSL_get_privatekey(conn->ssl); // Add this connection to the list conn->next = connections; connections = conn; return conn; }
int vector_append(vector_t *vector, void *item) { // Sanity check if (!item) return vector->count; // Check if the vector has been initializated if (!vector->list) { vector->list = sng_malloc(sizeof(void *) * vector->limit); } // Check if we need to increase vector size if (vector->count == vector->limit) { // Increase vector size vector->limit += vector->step; // Add more memory to the list vector->list = realloc(vector->list, sizeof(void *) * vector->limit); } // Add item to the end of the list vector->list[vector->count++] = item; // Check if vector has a sorter if (vector->sorter) { vector->sorter(vector, item); } return vector->count - 1; }
/** * FIXME Replace this with a tls_load_key function and use it * in tls_connection_create. * * Most probably we only need one context and key for all connections */ int tls_check_keyfile(const char *keyfile) { gnutls_x509_privkey_t key; gnutls_datum_t keycontent = { NULL, 0 }; FILE *keyfp; size_t br; SSL_library_init(); OpenSSL_add_all_algorithms(); if (access(capture_get_keyfile(), R_OK) != 0) return 0; if (!(keyfp = fopen(capture_get_keyfile(), "rb"))) return 0; fseek(keyfp, 0, SEEK_END); keycontent.size = ftell(keyfp); fseek(keyfp, 0, SEEK_SET); keycontent.data = sng_malloc(keycontent.size); br = fread(keycontent.data, 1, keycontent.size, keyfp); fclose(keyfp); gnutls_x509_privkey_init(&key); if (gnutls_x509_privkey_import(key, &keycontent, GNUTLS_X509_FMT_PEM) < 0) return 0; sng_free(keycontent.data); return 1; }
sip_msg_t * msg_create() { sip_msg_t *msg; if (!(msg = sng_malloc(sizeof(sip_msg_t)))) return NULL; return msg; }
struct SSLConnection * tls_connection_create(struct in_addr caddr, uint16_t cport, struct in_addr saddr, uint16_t sport) { struct SSLConnection *conn = NULL; gnutls_datum_t keycontent = { NULL, 0 }; FILE *keyfp; gnutls_x509_privkey_t spkey; size_t br; // Allocate memory for this connection conn = sng_malloc(sizeof(struct SSLConnection)); memcpy(&conn->client_addr, &caddr, sizeof(struct in_addr)); memcpy(&conn->server_addr, &saddr, sizeof(struct in_addr)); memcpy(&conn->client_port, &cport, sizeof(uint16_t)); memcpy(&conn->server_port, &sport, sizeof(uint16_t)); SSL_library_init(); OpenSSL_add_all_algorithms(); if (!(conn->ssl_ctx = SSL_CTX_new(SSLv23_server_method()))) return NULL; if (!(conn->ssl = SSL_new(conn->ssl_ctx))) return NULL; if (!(keyfp = fopen(capture_get_keyfile(), "rb"))) return NULL; fseek(keyfp, 0, SEEK_END); keycontent.size = ftell(keyfp); fseek(keyfp, 0, SEEK_SET); keycontent.data = sng_malloc(keycontent.size); br = fread(keycontent.data, 1, keycontent.size, keyfp); fclose(keyfp); gnutls_x509_privkey_init(&spkey); gnutls_x509_privkey_import(spkey, &keycontent, GNUTLS_X509_FMT_PEM); sng_free(keycontent.data); gnutls_privkey_init(&conn->server_private_key); gnutls_privkey_import_x509(conn->server_private_key, spkey, 0); // Add this connection to the list conn->next = connections; connections = conn; return conn; }
int capture_online(const char *dev, const char *outfile) { capture_info_t *capinfo; //! Error string char errbuf[PCAP_ERRBUF_SIZE]; // Set capture mode capture_cfg.status = CAPTURE_ONLINE; // Create a new structure to handle this capture source if (!(capinfo = sng_malloc(sizeof(capture_info_t)))) { fprintf(stderr, "Can't allocate memory for capture data!\n"); return 1; } // Try to find capture device information if (pcap_lookupnet(dev, &capinfo->net, &capinfo->mask, errbuf) == -1) { fprintf(stderr, "Can't get netmask for device %s\n", dev); capinfo->net = 0; capinfo->mask = 0; return 2; } // Open capture device capinfo->handle = pcap_open_live(dev, BUFSIZ, 1, 1000, errbuf); if (capinfo->handle == NULL) { fprintf(stderr, "Couldn't open device %s: %s\n", dev, errbuf); return 2; } // Store capture device capinfo->device = dev; // Get datalink to parse packets correctly capinfo->link = pcap_datalink(capinfo->handle); // Check linktypes sngrep knowns before start parsing packets if ((capinfo->link_hl = datalink_size(capinfo->link)) == -1) { fprintf(stderr, "Unable to handle linktype %d\n", capinfo->link); return 3; } // Add this capture information as packet source vector_append(capture_cfg.sources, capinfo); // If requested store packets in a dump file if (outfile && !capture_cfg.pd) { if ((capture_cfg.pd = dump_open(outfile)) == NULL) { fprintf(stderr, "Couldn't open output dump file %s: %s\n", outfile, pcap_geterr(capinfo->handle)); return 2; } } return 0; }
sip_call_group_t * call_group_create() { sip_call_group_t *group; if (!(group = sng_malloc(sizeof(sip_call_group_t)))) { return NULL; } group->calls = vector_create(5, 2); return group; }
vector_t * vector_create(int limit, int step) { vector_t *v; // Allocate memory for this vector data if (!(v = sng_malloc(sizeof(vector_t)))) return NULL; v->limit = limit; v->step = step; return v; }
void media_add_format(sdp_media_t *media, uint32_t code, const char *format) { sdp_media_fmt_t *fmt; if (!(fmt = sng_malloc(sizeof(sdp_media_fmt_t)))) return; fmt->id = code; strcpy(fmt->format, format); vector_append(media->formats, fmt); }
int tls_process_record_data(struct SSLConnection *conn, const opaque *fragment, const int len, uint8_t **out, uint32_t *outl) { EVP_CIPHER_CTX *evp; uint8_t pad; size_t flen = len; tls_debug_print_hex("Ciphertext", fragment, len); if (conn->direction == 0) { evp = &conn->client_cipher_ctx; } else { evp = &conn->server_cipher_ctx; } // TLS 1.1 and later extract explicit IV if (conn->version >= 2 && len > 16) { if (conn->direction == 0) { EVP_CipherInit(evp, conn->ciph, conn->key_material.client_write_key, fragment, 0); } else { EVP_CipherInit(evp, conn->ciph, conn->key_material.server_write_key, fragment, 0); } flen -= 16; fragment += 16; } size_t dlen = len; uint8_t *decoded = sng_malloc(dlen); EVP_Cipher(evp, decoded, (unsigned char *) fragment, flen); tls_debug_print_hex("Plaintext", decoded, flen); // Get padding counter and remove from data pad = decoded[flen - 1]; dlen = flen - (pad + 1); tls_debug_print_hex("Mac", decoded + (dlen - 20), 20); if ((int32_t)dlen > 0 && dlen <= *outl) { memcpy(*out, decoded, dlen); *outl = dlen - 20 /* Trailing MAC */; } // Clenaup decoded memory sng_free(decoded); return *outl; }
int capture_offline(const char *infile, const char *outfile) { capture_info_t *capinfo; // Error text (in case of file open error) char errbuf[PCAP_ERRBUF_SIZE]; // Set capture mode capture_cfg.status = CAPTURE_OFFLINE_LOADING; // Create a new structure to handle this capture source if (!(capinfo = sng_malloc(sizeof(capture_info_t)))) { fprintf(stderr, "Can't allocate memory for capture data!\n"); return 1; } // Set capture input file capinfo->infile = infile; // Open PCAP file if ((capinfo->handle = pcap_open_offline(infile, errbuf)) == NULL) { fprintf(stderr, "Couldn't open pcap file %s: %s\n", infile, errbuf); return 1; } // Get datalink to parse packets correctly capinfo->link = pcap_datalink(capinfo->handle); // Check linktypes sngrep knowns before start parsing packets if ((capinfo->link_hl = datalink_size(capinfo->link)) == -1) { fprintf(stderr, "Unable to handle linktype %d\n", capinfo->link); return 3; } // Add this capture information as packet source vector_append(capture_cfg.sources, capinfo); // If requested store packets in a dump file if (outfile && !capture_cfg.pd) { if ((capture_cfg.pd = dump_open(outfile)) == NULL) { fprintf(stderr, "Couldn't open output dump file %s: %s\n", outfile, pcap_geterr(capinfo->handle)); return 2; } } return 0; }
sdp_media_t * media_create(struct sip_msg *msg) { sdp_media_t *media;; // Allocate memory for this media structure if (!(media = sng_malloc(sizeof(sdp_media_t)))) return NULL; // Initialize all fields media->msg = msg; media->formats = vector_create(0, 1); vector_set_destroyer(media->formats, vector_generic_destroyer); return media; }
sip_call_group_t * call_group_clone(sip_call_group_t *original) { sip_call_group_t *clone; if (!original) return NULL; if (!(clone = sng_malloc(sizeof(sip_call_group_t)))) { return NULL; } clone->calls = vector_clone(original->calls); return clone; }
int init_options(int no_config) { // Custom user conf file char *userconf = NULL; char *rcfile; char pwd[MAX_SETTING_LEN]; // Defualt savepath is current directory if (getcwd(pwd, MAX_SETTING_LEN)) { setting_set_value(SETTING_SAVEPATH, pwd); } // Initialize settings setting_set_value(SETTING_FILTER_METHODS, "REGISTER,INVITE,SUBSCRIBE,NOTIFY,OPTIONS,PUBLISH,MESSAGE"); // Add Call list column options set_option_value("cl.column0", "index"); set_option_value("cl.column1", "method"); set_option_value("cl.column2", "sipfrom"); set_option_value("cl.column3", "sipto"); set_option_value("cl.column4", "msgcnt"); set_option_value("cl.column5", "src"); set_option_value("cl.column6", "dst"); set_option_value("cl.column7", "state"); // Done if config file should not be read if(no_config) { return 0; } // Read options from configuration files read_options("/etc/sngreprc"); read_options("/usr/local/etc/sngreprc"); // Get user configuration if ((rcfile = getenv("SNGREPRC"))) { read_options(rcfile); } else if ((rcfile = getenv("HOME"))) { if ((userconf = sng_malloc(strlen(rcfile) + RCFILE_EXTRA_LEN))) { sprintf(userconf, "%s/.sngreprc", rcfile); read_options(userconf); sng_free(userconf); } } return 0; }
void sip_parse_extra_headers(sip_msg_t *msg, const u_char *payload) { regmatch_t pmatch[4]; char warning[10]; // Reason text if (regexec(&calls.reg_reason, (const char *)payload, 2, pmatch, 0) == 0) { msg->call->reasontxt = sng_malloc((int)pmatch[1].rm_eo - pmatch[1].rm_so + 1); strncpy(msg->call->reasontxt, (const char *)payload + pmatch[1].rm_so, (int)pmatch[1].rm_eo - pmatch[1].rm_so); } // Warning code if (regexec(&calls.reg_warning, (const char *)payload, 2, pmatch, 0) == 0) { strncpy(warning, (const char *)payload + pmatch[1].rm_so, (int)pmatch[1].rm_eo - pmatch[1].rm_so); msg->call->warning = atoi(warning); } }
PANEL * call_raw_create() { PANEL *panel; call_raw_info_t *info; // Create a new panel to fill all the screen panel = new_panel(newwin(LINES, COLS, 0, 0)); // Initialize Call List specific data info = sng_malloc(sizeof(call_raw_info_t)); // Store it into panel userptr set_panel_userptr(panel, (void*) info); // Create a initial pad of 1000 lines info->pad = newpad(500, COLS); info->padline = 0; info->scroll = 0; return panel; }
sip_call_t * call_create(char *callid) { sip_call_t *call; // Initialize a new call structure if (!(call = sng_malloc(sizeof(sip_call_t)))) return NULL; // Create a vector to store call messages call->msgs = vector_create(2, 2); vector_set_destroyer(call->msgs, msg_destroyer); // Create a vector to store call attributes call->attrs = vector_create(1, 1); vector_set_destroyer(call->attrs, sip_attr_destroyer); // Initialize call filter status call->filtered = -1; // Set message callid call_set_attribute(call, SIP_ATTR_CALLID, callid); return call; }
int capture_ws_check_packet(packet_t *packet) { int ws_off = 0; u_char ws_fin; u_char ws_opcode; u_char ws_mask; uint8_t ws_len; u_char ws_mask_key[4]; u_char *payload, *newpayload; uint32_t size_payload; int i; /** * WSocket header definition according to RFC 6455 * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-------+-+-------------+-------------------------------+ * |F|R|R|R| opcode|M| Payload len | Extended payload length | * |I|S|S|S| (4) |A| (7) | (16/64) | * |N|V|V|V| |S| | (if payload len==126/127) | * | |1|2|3| |K| | | * +-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - + * | Extended payload length continued, if payload len == 127 | * + - - - - - - - - - - - - - - - +-------------------------------+ * | |Masking-key, if MASK set to 1 | * +-------------------------------+-------------------------------+ * | Masking-key (continued) | Payload Data | * +-------------------------------- - - - - - - - - - - - - - - - + * : Payload Data continued ... : * + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * | Payload Data continued ... | * +---------------------------------------------------------------+ */ // Get payload from packet(s) size_payload = packet_payloadlen(packet); payload = packet_payload(packet); // Check we have payload if (size_payload == 0) return 0; // Flags && Opcode ws_fin = (*payload & WH_FIN) >> 4; ws_opcode = *payload & WH_OPCODE; ws_off++; // Only interested in Ws text packets if (ws_opcode != WS_OPCODE_TEXT) return 0; // Masked flag && Payload len ws_mask = (*(payload + ws_off) & WH_MASK) >> 4; ws_len = (*(payload + ws_off) & WH_LEN); ws_off++; // Skip Payload len switch (ws_len) { // Extended case 126: ws_off += 2; break; case 127: ws_off += 8; break; default: return 0; } // Get Masking key if mask is enabled if (ws_mask) { memcpy(ws_mask_key, (payload + ws_off), 4); ws_off += 4; } // Skip Websocket headers size_payload -= ws_off; if ((int32_t) size_payload <= 0) return 0; newpayload = sng_malloc(size_payload); memcpy(newpayload, payload + ws_off, size_payload); // If mask is enabled, unmask the payload if (ws_mask) { for (i = 0; i < size_payload; i++) newpayload[i] = newpayload[i] ^ ws_mask_key[i % 4]; } // Set new packet payload into the packet packet_set_payload(packet, newpayload, size_payload); // Free the new payload sng_free(newpayload); if (packet->type == PACKET_SIP_TLS) { packet_set_type(packet, PACKET_SIP_WSS); } else { packet_set_type(packet, PACKET_SIP_WS); } return 1; }
int capture_eep_send_v2(capture_packet_t *pkt) { void* buffer; unsigned int buflen = 0, tlen = 0; struct hep_hdr hdr; struct hep_timehdr hep_time; struct hep_iphdr hep_ipheader; #ifdef USE_IPV6 struct hep_ip6hdr hep_ip6header; #endif unsigned char *data = capture_packet_get_payload(pkt); unsigned int len = capture_packet_get_payload_len(pkt); capture_frame_t *frame = vector_first(pkt->frames); /* Version && proto */ hdr.hp_v = 2; hdr.hp_f = pkt->ip_version == 4 ? AF_INET : AF_INET6; hdr.hp_p = pkt->proto; hdr.hp_sport = htons(pkt->sport); hdr.hp_dport = htons(pkt->dport); /* Timestamp */ hep_time.tv_sec = frame->header->ts.tv_sec; hep_time.tv_usec = frame->header->ts.tv_usec; hep_time.captid = eep_cfg.capt_id; /* Calculate initial HEP packet size */ tlen = sizeof(struct hep_hdr) + sizeof(struct hep_timehdr); /* IPv4 */ if (pkt->ip_version == 4) { inet_pton(AF_INET, pkt->ip_src, &hep_ipheader.hp_src); inet_pton(AF_INET, pkt->ip_dst, &hep_ipheader.hp_dst); tlen += sizeof(struct hep_iphdr); hdr.hp_l += sizeof(struct hep_iphdr); } #ifdef USE_IPV6 /* IPv6 */ else if(pkt->ip_version == 6) { inet_pton(AF_INET6, pkt->ip_src, &hep_ip6header.hp6_src); inet_pton(AF_INET6, pkt->ip_dst, &hep_ip6header.hp6_dst); tlen += sizeof(struct hep_ip6hdr); hdr.hp_l += sizeof(struct hep_ip6hdr); } #endif // Add payload size to the final size of HEP packet tlen += len; hdr.hp_l = htons(tlen); // Allocate memory for HEPv2 packet if (!(buffer = sng_malloc(tlen))) return 1; // Copy basic headers buflen = 0; memcpy((void*) buffer + buflen, &hdr, sizeof(struct hep_hdr)); buflen += sizeof(struct hep_hdr); // Copy IP header if (pkt->ip_version == 4) { memcpy((void*) buffer + buflen, &hep_ipheader, sizeof(struct hep_iphdr)); buflen += sizeof(struct hep_iphdr); } #ifdef USE_IPV6 else if(pkt->ip_version == 6) { memcpy((void*) buffer + buflen, &hep_ip6header, sizeof(struct hep_ip6hdr)); buflen += sizeof(struct hep_ip6hdr); } #endif // Copy TImestamp header memcpy((void*) buffer + buflen, &hep_time, sizeof(struct hep_timehdr)); buflen += sizeof(struct hep_timehdr); // Now copy payload itself memcpy((void*) buffer + buflen, data, len); buflen += len; if (send(eep_cfg.client_sock, buffer, buflen, 0) == -1) { return 1; } /* FREE */ sng_free(buffer); return 1; }
int capture_eep_send_v3(capture_packet_t *pkt) { struct hep_generic *hg = NULL; void* buffer; unsigned int buflen = 0, iplen = 0, tlen = 0; hep_chunk_ip4_t src_ip4, dst_ip4; #ifdef USE_IPV6 hep_chunk_ip6_t src_ip6, dst_ip6; #endif hep_chunk_t payload_chunk; hep_chunk_t authkey_chunk; capture_frame_t *frame = vector_first(pkt->frames); unsigned char *data = capture_packet_get_payload(pkt); unsigned int len = capture_packet_get_payload_len(pkt); hg = sng_malloc(sizeof(struct hep_generic)); /* header set "HEP3" */ memcpy(hg->header.id, "\x48\x45\x50\x33", 4); /* IP proto */ hg->ip_family.chunk.vendor_id = htons(0x0000); hg->ip_family.chunk.type_id = htons(0x0001); hg->ip_family.data = pkt->ip_version == 4 ? AF_INET : AF_INET6; hg->ip_family.chunk.length = htons(sizeof(hg->ip_family)); /* Proto ID */ hg->ip_proto.chunk.vendor_id = htons(0x0000); hg->ip_proto.chunk.type_id = htons(0x0002); hg->ip_proto.data = pkt->proto; hg->ip_proto.chunk.length = htons(sizeof(hg->ip_proto)); /* IPv4 */ if (pkt->ip_version == 4) { /* SRC IP */ src_ip4.chunk.vendor_id = htons(0x0000); src_ip4.chunk.type_id = htons(0x0003); inet_pton(AF_INET, pkt->ip_src, &src_ip4.data); src_ip4.chunk.length = htons(sizeof(src_ip4)); /* DST IP */ dst_ip4.chunk.vendor_id = htons(0x0000); dst_ip4.chunk.type_id = htons(0x0004); inet_pton(AF_INET, pkt->ip_dst, &dst_ip4.data); dst_ip4.chunk.length = htons(sizeof(dst_ip4)); iplen = sizeof(dst_ip4) + sizeof(src_ip4); } #ifdef USE_IPV6 /* IPv6 */ else if(pkt->ip_version == 6) { /* SRC IPv6 */ src_ip6.chunk.vendor_id = htons(0x0000); src_ip6.chunk.type_id = htons(0x0005); inet_pton(AF_INET6, pkt->ip_src, &src_ip6.data); src_ip6.chunk.length = htonl(sizeof(src_ip6)); /* DST IPv6 */ dst_ip6.chunk.vendor_id = htons(0x0000); dst_ip6.chunk.type_id = htons(0x0006); inet_pton(AF_INET6, pkt->ip_dst, &dst_ip6.data); dst_ip6.chunk.length = htonl(sizeof(dst_ip6)); iplen = sizeof(dst_ip6) + sizeof(src_ip6); } #endif /* SRC PORT */ hg->src_port.chunk.vendor_id = htons(0x0000); hg->src_port.chunk.type_id = htons(0x0007); hg->src_port.data = htons(pkt->sport); hg->src_port.chunk.length = htons(sizeof(hg->src_port)); /* DST PORT */ hg->dst_port.chunk.vendor_id = htons(0x0000); hg->dst_port.chunk.type_id = htons(0x0008); hg->dst_port.data = htons(pkt->dport); hg->dst_port.chunk.length = htons(sizeof(hg->dst_port)); /* TIMESTAMP SEC */ hg->time_sec.chunk.vendor_id = htons(0x0000); hg->time_sec.chunk.type_id = htons(0x0009); hg->time_sec.data = htonl(frame->header->ts.tv_sec); hg->time_sec.chunk.length = htons(sizeof(hg->time_sec)); /* TIMESTAMP USEC */ hg->time_usec.chunk.vendor_id = htons(0x0000); hg->time_usec.chunk.type_id = htons(0x000a); hg->time_usec.data = htonl(frame->header->ts.tv_usec); hg->time_usec.chunk.length = htons(sizeof(hg->time_usec)); /* Protocol TYPE */ hg->proto_t.chunk.vendor_id = htons(0x0000); hg->proto_t.chunk.type_id = htons(0x000b); hg->proto_t.data = 1; hg->proto_t.chunk.length = htons(sizeof(hg->proto_t)); /* Capture ID */ hg->capt_id.chunk.vendor_id = htons(0x0000); hg->capt_id.chunk.type_id = htons(0x000c); hg->capt_id.data = htons(eep_cfg.capt_id); hg->capt_id.chunk.length = htons(sizeof(hg->capt_id)); /* Payload */ payload_chunk.vendor_id = htons(0x0000); payload_chunk.type_id = htons(0x000f); payload_chunk.length = htons(sizeof(payload_chunk) + len); tlen = sizeof(struct hep_generic) + len + iplen + sizeof(hep_chunk_t); /* auth key */ if (eep_cfg.capt_password != NULL) { tlen += sizeof(hep_chunk_t); /* Auth key */ authkey_chunk.vendor_id = htons(0x0000); authkey_chunk.type_id = htons(0x000e); authkey_chunk.length = htons(sizeof(authkey_chunk) + strlen(eep_cfg.capt_password)); tlen += strlen(eep_cfg.capt_password); } /* total */ hg->header.length = htons(tlen); if (!(buffer = sng_malloc(tlen))) { sng_free(hg); return 1; } memcpy((void*) buffer, hg, sizeof(struct hep_generic)); buflen = sizeof(struct hep_generic); /* IPv4 */ if (pkt->ip_version == 4) { /* SRC IP */ memcpy((void*) buffer + buflen, &src_ip4, sizeof(struct hep_chunk_ip4)); buflen += sizeof(struct hep_chunk_ip4); memcpy((void*) buffer + buflen, &dst_ip4, sizeof(struct hep_chunk_ip4)); buflen += sizeof(struct hep_chunk_ip4); } #ifdef USE_IPV6 /* IPv6 */ else if(pkt->ip_version == 6) { /* SRC IPv6 */ memcpy((void*) buffer+buflen, &src_ip4, sizeof(struct hep_chunk_ip6)); buflen += sizeof(struct hep_chunk_ip6); memcpy((void*) buffer+buflen, &dst_ip6, sizeof(struct hep_chunk_ip6)); buflen += sizeof(struct hep_chunk_ip6); } #endif /* AUTH KEY CHUNK */ if (eep_cfg.capt_password != NULL) { memcpy((void*) buffer + buflen, &authkey_chunk, sizeof(struct hep_chunk)); buflen += sizeof(struct hep_chunk); /* Now copying payload self */ memcpy((void*) buffer + buflen, eep_cfg.capt_password, strlen(eep_cfg.capt_password)); buflen += strlen(eep_cfg.capt_password); } /* PAYLOAD CHUNK */ memcpy((void*) buffer + buflen, &payload_chunk, sizeof(struct hep_chunk)); buflen += sizeof(struct hep_chunk); /* Now copying payload itself */ memcpy((void*) buffer + buflen, data, len); buflen += len; if (send(eep_cfg.client_sock, buffer, buflen, 0) == -1) { return 1; } /* FREE */ sng_free(buffer); sng_free(hg); return 0; }
capture_packet_t * capture_eep_receive_v2() { uint8_t family, proto; unsigned char *payload = 0; unsigned int pos; char buffer[MAX_CAPTURE_LEN] ; //! Source and Destination Address char ip_src[ADDRESSLEN], ip_dst[ADDRESSLEN]; //! Source and Destination Port u_short sport, dport; //! Packet header struct pcap_pkthdr header; //! New created packet pointer capture_packet_t *pkt; //! EEP client data struct sockaddr eep_client; socklen_t eep_client_len; struct hep_hdr hdr; struct hep_timehdr hep_time; struct hep_iphdr hep_ipheader; #ifdef USE_IPV6 struct hep_ip6hdr hep_ip6header; #endif // Initialize buffer memset(buffer, 0, MAX_CAPTURE_LEN); /* Receive EEP generic header */ if (recvfrom(eep_cfg.server_sock, buffer, MAX_CAPTURE_LEN, 0, &eep_client, &eep_client_len) == -1) return NULL; /* Copy initial bytes to HEPv2 header */ memcpy(&hdr, buffer, sizeof(struct hep_hdr)); // Check HEP version if (hdr.hp_v != 2) return NULL; /* IP proto */ family = hdr.hp_f; /* Proto ID */ proto = hdr.hp_p; pos = sizeof(struct hep_hdr); /* IPv4 */ if (family == AF_INET) { memcpy(&hep_ipheader, (void*) buffer + pos, sizeof(struct hep_iphdr)); inet_ntop(AF_INET, &hep_ipheader.hp_src, ip_src, sizeof(ip_src)); inet_ntop(AF_INET, &hep_ipheader.hp_dst, ip_dst, sizeof(ip_dst)); pos += sizeof(struct hep_iphdr); } #ifdef USE_IPV6 /* IPv6 */ else if(family == AF_INET6) { memcpy(&hep_ip6header, (void*) buffer + pos, sizeof(struct hep_ip6hdr)); inet_ntop(AF_INET6, &hep_ip6header.hp6_src, ip_src, sizeof(ip_src)); inet_ntop(AF_INET6, &hep_ip6header.hp6_dst, ip_dst, sizeof(ip_dst)); pos += sizeof(struct hep_ip6hdr); } #endif /* PORTS */ sport = ntohs(hdr.hp_sport); dport = ntohs(hdr.hp_dport); /* TIMESTAMP*/ memcpy(&hep_time, (void*) buffer + pos, sizeof(struct hep_timehdr)); pos += sizeof(struct hep_timehdr); header.ts.tv_sec = hep_time.tv_sec; header.ts.tv_usec = hep_time.tv_usec; /* Protocol TYPE */ /* Capture ID */ // Calculate payload size (Total size - headers size) header.caplen = header.len = ntohs(hdr.hp_l) - pos; // Copy packet payload payload = sng_malloc(header.caplen + 1); memcpy(payload, (void*) buffer + pos, header.caplen); // Create a new packet pkt = capture_packet_create((family == AF_INET) ? 4 : 6, proto, ip_src, ip_dst, 0); capture_packet_add_frame(pkt, &header, payload); capture_packet_set_transport_data(pkt, sport, dport, CAPTURE_PACKET_SIP_UDP); capture_packet_set_payload(pkt, payload, header.caplen); /* FREE */ sng_free(payload); return pkt; }
capture_packet_t * capture_eep_receive_v3() { struct hep_generic hg; hep_chunk_ip4_t src_ip4, dst_ip4; #ifdef USE_IPV6 hep_chunk_ip6_t src_ip6, dst_ip6; #endif hep_chunk_t payload_chunk; hep_chunk_t authkey_chunk; uint8_t family, proto; char password[100]; int password_len; unsigned char *payload = 0; unsigned int len, pos; char buffer[MAX_CAPTURE_LEN] ; //! Source and Destination Address char ip_src[ADDRESSLEN], ip_dst[ADDRESSLEN]; //! EEP client data struct sockaddr eep_client; socklen_t eep_client_len; //! Source and Destination Port u_short sport, dport; //! Packet header struct pcap_pkthdr header; //! New created packet pointer capture_packet_t *pkt; /* Receive EEP generic header */ if (recvfrom(eep_cfg.server_sock, buffer, MAX_CAPTURE_LEN, 0, &eep_client, &eep_client_len) == -1) return NULL; /* Copy initial bytes to EEP Generic header */ memcpy(&hg, buffer, sizeof(struct hep_generic)); /* header check */ if (memcmp(hg.header.id, "\x48\x45\x50\x33", 4) != 0) return NULL; /* IP proto */ family = hg.ip_family.data; /* Proto ID */ proto = hg.ip_proto.data; len = ntohs(hg.header.length) - sizeof(struct hep_generic); pos = sizeof(struct hep_generic); /* IPv4 */ if (family == AF_INET) { /* SRC IP */ memcpy(&src_ip4, (void*) buffer + pos, sizeof(struct hep_chunk_ip4)); inet_ntop(AF_INET, &src_ip4.data, ip_src, sizeof(ip_src)); pos += sizeof(struct hep_chunk_ip4); /* DST IP */ memcpy(&dst_ip4, (void*) buffer + pos, sizeof(struct hep_chunk_ip4)); inet_ntop(AF_INET, &dst_ip4.data, ip_dst, sizeof(ip_dst)); pos += sizeof(struct hep_chunk_ip4); } #ifdef USE_IPV6 /* IPv6 */ else if(family == AF_INET6) { /* SRC IPv6 */ memcpy(&src_ip6, (void*) buffer + pos, sizeof(struct hep_chunk_ip6)); inet_ntop(AF_INET6, &src_ip6.data, ip_src, sizeof(ip_src)); pos += sizeof(struct hep_chunk_ip6); /* DST IP */ memcpy(&src_ip6, (void*) buffer + pos, sizeof(struct hep_chunk_ip6)); inet_ntop(AF_INET6, &dst_ip6.data, ip_dst, sizeof(ip_dst)); pos += sizeof(struct hep_chunk_ip6); } #endif /* SRC PORT */ sport = ntohs(hg.src_port.data); /* DST PORT */ dport = ntohs(hg.dst_port.data); /* TIMESTAMP*/ header.ts.tv_sec = ntohl(hg.time_sec.data); header.ts.tv_usec = ntohl(hg.time_usec.data); /* Protocol TYPE */ /* Capture ID */ /* auth key */ if (eep_cfg.capt_srv_password != NULL) { memcpy(&authkey_chunk, (void*) buffer + pos, sizeof(authkey_chunk)); pos += sizeof(authkey_chunk); password_len = ntohs(authkey_chunk.length) - sizeof(authkey_chunk); memcpy(password, (void*) buffer + pos, password_len); pos += password_len; // Validate the password if (strncmp(password, eep_cfg.capt_srv_password, password_len) != 0) return NULL; } /* Payload */ memcpy(&payload_chunk, (void*) buffer + pos, sizeof(payload_chunk)); pos += sizeof(payload_chunk); // Calculate payload size header.caplen = header.len = ntohs(payload_chunk.length) - sizeof(payload_chunk); // Receive packet payload payload = sng_malloc(header.caplen); memcpy(payload, (void*) buffer + pos, header.caplen); // Create a new packet pkt = capture_packet_create((family == AF_INET)?4:6, proto, ip_src, ip_dst, 0); capture_packet_add_frame(pkt, &header, payload); capture_packet_set_transport_data(pkt, sport, dport, CAPTURE_PACKET_SIP_UDP); capture_packet_set_payload(pkt, payload, header.caplen); /* FREE */ sng_free(payload); return pkt; }
int tls_process_record_handshake(struct SSLConnection *conn, const opaque *fragment) { struct Handshake *handshake; struct ClientHello *clienthello; struct ServerHello *serverhello; struct ClientKeyExchange *clientkeyex; const opaque *body; // Get Handshake data handshake = (struct Handshake *) fragment; if (UINT24_INT(handshake->length) > 0) { // Hanshake body pointer body = fragment + sizeof(struct Handshake); switch (handshake->type) { case hello_request: break; case client_hello: // Store client random clienthello = (struct ClientHello *) body; memcpy(&conn->client_random, &clienthello->random, sizeof(struct Random)); // Check we have a TLS handshake if (!(clienthello->client_version.major == 0x03 && clienthello->client_version.minor == 0x01)) { tls_connection_destroy(conn); return 1; } break; case server_hello: // Store server random serverhello = (struct ServerHello *) body; memcpy(&conn->server_random, &serverhello->random, sizeof(struct Random)); // Get the selected cipher memcpy(&conn->cipher_suite, body + sizeof(struct ServerHello) + serverhello->session_id_length, sizeof(uint16_t)); // Check if we have a handled cipher if (tls_connection_load_cipher(conn) != 0) { tls_connection_destroy(conn); return 1; } break; case certificate: case certificate_request: case server_hello_done: case certificate_verify: break; case client_key_exchange: // Decrypt PreMasterKey clientkeyex = (struct ClientKeyExchange *) body; gnutls_datum_t exkeys, pms; exkeys.size = UINT16_INT(clientkeyex->length); exkeys.data = (unsigned char *)&clientkeyex->exchange_keys; gnutls_privkey_decrypt_data(conn->server_private_key, 0, &exkeys, &pms); memcpy(&conn->pre_master_secret, pms.data, pms.size); // Get MasterSecret unsigned char *seed = sng_malloc(sizeof(struct Random) * 2); memcpy(seed, &conn->client_random, sizeof(struct Random)); memcpy(seed + sizeof(struct Random), &conn->server_random, sizeof(struct Random)); PRF((unsigned char *) &conn->master_secret, sizeof(struct MasterSecret), (unsigned char *) &conn->pre_master_secret, sizeof(struct PreMasterSecret), (unsigned char *) "master secret", seed, sizeof(struct Random) * 2); memcpy(seed, &conn->server_random, sizeof(struct Random)); memcpy(seed + sizeof(struct Random), &conn->client_random, sizeof(struct Random)); // Generate MACs, Write Keys and IVs PRF((unsigned char *) &conn->key_material, sizeof(struct tls_data), (unsigned char *) &conn->master_secret, sizeof(struct MasterSecret), (unsigned char *) "key expansion", seed, sizeof(struct Random) * 2); // Done with the seed sng_free(seed); // Create Client decoder gcry_cipher_open(&conn->client_cipher_ctx, conn->ciph, GCRY_CIPHER_MODE_CBC, 0); gcry_cipher_setkey(conn->client_cipher_ctx, conn->key_material.client_write_key, gcry_cipher_get_algo_keylen(conn->ciph)); gcry_cipher_setiv(conn->client_cipher_ctx, conn->key_material.client_write_IV, gcry_cipher_get_algo_blklen(conn->ciph)); // Create Server decoder gcry_cipher_open(&conn->server_cipher_ctx, conn->ciph, GCRY_CIPHER_MODE_CBC, 0); gcry_cipher_setkey(conn->server_cipher_ctx, conn->key_material.server_write_key, gcry_cipher_get_algo_keylen(conn->ciph)); gcry_cipher_setiv(conn->server_cipher_ctx, conn->key_material.server_write_IV, gcry_cipher_get_algo_blklen(conn->ciph)); break; case finished: break; default: if (conn->encrypted) { // Encrypted Hanshake Message unsigned char *decoded = sng_malloc(48); uint32_t decodedlen; tls_process_record_data(conn, fragment, 48, &decoded, &decodedlen); sng_free(decoded); } break; } } return 0; }
int tls_process_segment(capture_packet_t *packet, struct tcphdr *tcp) { struct SSLConnection *conn; const u_char *payload = capture_packet_get_payload(packet); uint32_t size_payload = capture_packet_get_payload_len(packet); uint8_t *out; uint32_t outl = packet->payload_len; out = sng_malloc(outl); struct in_addr ip_src, ip_dst; uint16_t sport = packet->sport; uint16_t dport = packet->dport; // Convert addresses inet_pton(AF_INET, packet->ip_src, &ip_src); inet_pton(AF_INET, packet->ip_dst, &ip_dst); // Try to find a session for this ip if ((conn = tls_connection_find(ip_src, sport))) { // Update last connection direction conn->direction = tls_connection_dir(conn, ip_src, sport); // Check current connection state switch (conn->state) { case TCP_STATE_SYN: // First SYN received, this package must be SYN/ACK if (tcp->th_flags & TH_SYN & ~TH_ACK) conn->state = TCP_STATE_SYN_ACK; break; case TCP_STATE_SYN_ACK: // We expect an ACK packet here if (tcp->th_flags & ~TH_SYN & TH_ACK) conn->state = TCP_STATE_ESTABLISHED; break; case TCP_STATE_ACK: case TCP_STATE_ESTABLISHED: // Process data segment! if (tls_process_record(conn, payload, size_payload, &out, &outl) == 0) { if ((int32_t) outl > 0) { capture_packet_set_payload(packet, out, outl); capture_packet_set_type(packet, CAPTURE_PACKET_SIP_TLS); return 0; } } break; case TCP_STATE_FIN: case TCP_STATE_CLOSED: // We can delete this connection tls_connection_destroy(conn); break; } } else { if (tcp->th_flags & TH_SYN & ~TH_ACK) { // New connection, store it status and leave tls_connection_create(ip_src, sport, ip_dst, dport); } } sng_free(out); return 0; }
void column_select_create(ui_t *ui) { int attr_id, column; MENU *menu; column_select_info_t *info; // Cerate a new indow for the panel and form ui_panel_create(ui, 20, 60); // Initialize Filter panel specific data info = sng_malloc(sizeof(column_select_info_t)); // Store it into panel userptr set_panel_userptr(ui->panel, (void*) info); // Initialize the fields info->fields[FLD_COLUMNS_ACCEPT] = new_field(1, 10, ui->height - 2, 13, 0, 0); info->fields[FLD_COLUMNS_SAVE] = new_field(1, 10, ui->height - 2, 25, 0, 0); info->fields[FLD_COLUMNS_CANCEL] = new_field(1, 10, ui->height - 2, 37, 0, 0); info->fields[FLD_COLUMNS_COUNT] = NULL; // Field Labels set_field_buffer(info->fields[FLD_COLUMNS_ACCEPT], 0, "[ Accept ]"); set_field_buffer(info->fields[FLD_COLUMNS_SAVE], 0, "[ Save ]"); set_field_buffer(info->fields[FLD_COLUMNS_CANCEL], 0, "[ Cancel ]"); // Create the form and post it info->form = new_form(info->fields); set_form_sub(info->form, ui->win); post_form(info->form); // Create a subwin for the menu area info->menu_win = derwin(ui->win, 10, ui->width - 2, 7, 0); // Initialize one field for each attribute for (attr_id = 0; attr_id < SIP_ATTR_COUNT; attr_id++) { // Create a new field for this column info->items[attr_id] = new_item("[ ]", sip_attr_get_description(attr_id)); set_item_userptr(info->items[attr_id], (void*) sip_attr_get_name(attr_id)); } info->items[SIP_ATTR_COUNT] = NULL; // Create the columns menu and post it info->menu = menu = new_menu(info->items); // Set current enabled fields // FIXME Stealing Call list columns :/ call_list_info_t *list_info = call_list_info(ui_find_by_type(PANEL_CALL_LIST)); // Enable current enabled fields and move them to the top for (column = 0; column < list_info->columncnt; column++) { const char *attr = list_info->columns[column].attr; for (attr_id = 0; attr_id < item_count(menu); attr_id++) { if (!strcmp(item_userptr(info->items[attr_id]), attr)) { column_select_toggle_item(ui, info->items[attr_id]); column_select_move_item(ui, info->items[attr_id], column); break; } } } // Set main window and sub window set_menu_win(menu, ui->win); set_menu_sub(menu, derwin(ui->win, 10, ui->width - 5, 7, 2)); set_menu_format(menu, 10, 1); set_menu_mark(menu, ""); set_menu_fore(menu, COLOR_PAIR(CP_DEF_ON_BLUE)); menu_opts_off(menu, O_ONEVALUE); post_menu(menu); // Draw a scrollbar to the right info->scroll = ui_set_scrollbar(info->menu_win, SB_VERTICAL, SB_RIGHT); info->scroll.max = item_count(menu) - 1; ui_scrollbar_draw(info->scroll); // Set the window title and boxes mvwprintw(ui->win, 1, ui->width / 2 - 14, "Call List columns selection"); wattron(ui->win, COLOR_PAIR(CP_BLUE_ON_DEF)); title_foot_box(ui->panel); mvwhline(ui->win, 6, 1, ACS_HLINE, ui->width - 1); mvwaddch(ui->win, 6, 0, ACS_LTEE); mvwaddch(ui->win, 6, ui->width - 1, ACS_RTEE); wattroff(ui->win, COLOR_PAIR(CP_BLUE_ON_DEF)); // Some brief explanation abotu what window shows wattron(ui->win, COLOR_PAIR(CP_CYAN_ON_DEF)); mvwprintw(ui->win, 3, 2, "This windows show the list of columns displayed on Call"); mvwprintw(ui->win, 4, 2, "List. You can enable/disable using Space Bar and reorder"); mvwprintw(ui->win, 5, 2, "them using + and - keys."); wattroff(ui->win, COLOR_PAIR(CP_CYAN_ON_DEF)); info->form_active = 0; }