static void display_socks_v5(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, socks_hash_entry_t *hash_info) { /* Display the protocol tree for the version. This routine uses the */ /* stored conversation information to decide what to do with the row. */ /* Per packet information would have been better to do this, but we */ /* didn't have that when I wrote this. And I didn't expect this to get */ /* so messy. */ unsigned int i, command; guint temp; const char *AuthMethodStr; guint8 auth_status; proto_tree_add_item( tree, hf_socks_ver, tvb, offset, 1, FALSE); ++offset; if (compare_packet( hash_info->connect_row)){ proto_tree *AuthTree; proto_item *ti; temp = tvb_get_guint8(tvb, offset); /* Get Auth method count */ /* build auth tree */ ti = proto_tree_add_text( tree, tvb, offset, -1, "Client Authentication Methods"); AuthTree = proto_item_add_subtree(ti, ett_socks_auth); proto_tree_add_text( AuthTree, tvb, offset, 1, "Count: %u", temp); ++offset; for( i = 0; i < temp; ++i) { AuthMethodStr = get_auth_method_name( tvb_get_guint8( tvb, offset)); proto_tree_add_text( AuthTree, tvb, offset, 1, "Method[%u]: %u (%s)", i, tvb_get_guint8( tvb, offset), AuthMethodStr); ++offset; } proto_item_set_end( ti, tvb, offset); return; } /* Get accepted auth method */ else if (compare_packet( hash_info->auth_method_row)) { proto_tree_add_text( tree, tvb, offset, 1, "Accepted Auth Method: 0x%0x (%s)", tvb_get_guint8( tvb, offset), get_auth_method_name( tvb_get_guint8( tvb, offset))); return; } /* handle user/password auth */ else if (compare_packet( hash_info->user_name_auth_row)) { /* process user name */ offset += display_string( tvb, offset, tree, "User name"); /* process password */ offset += display_string( tvb, offset, tree, "Password"); } /* command to the server */ /* command response from server */ else if (compare_packet( hash_info->auth_version)) { auth_status = tvb_get_guint8(tvb, offset); if(auth_status != 0) proto_tree_add_text( tree, tvb, offset, 1, "Status: %u (failure)", auth_status); else proto_tree_add_text( tree, tvb, offset, 1, "Status: success"); offset ++; } else if (compare_packet( hash_info->gssapi_auth_row)) { guint16 len; proto_tree_add_item( tree, hf_gssapi_command, tvb, offset, 1, FALSE); proto_tree_add_item( tree, hf_gssapi_length, tvb, offset+1, 2, FALSE); len = tvb_get_ntohs(tvb, offset+1); if (len > 0) proto_tree_add_item( tree, hf_gssapi_payload, tvb, offset+3, len, FALSE); } else if (compare_packet( hash_info->gssapi_auth_failure_row)) { proto_tree_add_item( tree, hf_gssapi_command, tvb, offset, 1, FALSE); } else if (compare_packet( hash_info->gssapi_auth_reply_row)) { guint16 len; proto_tree_add_item( tree, hf_gssapi_command, tvb, offset, 1, FALSE); proto_tree_add_item( tree, hf_gssapi_length, tvb, offset+1, 2, FALSE); len = tvb_get_ntohs(tvb, offset+1); if (len > 0) proto_tree_add_item( tree, hf_gssapi_payload, tvb, offset+3, len, FALSE); } else if ((compare_packet( hash_info->command_row)) || (compare_packet( hash_info->cmd_reply_row)) || (compare_packet( hash_info->bind_reply_row))){ command = tvb_get_guint8(tvb, offset); if (compare_packet( hash_info->command_row)) proto_tree_add_uint( tree, hf_socks_cmd, tvb, offset, 1, command); else { proto_item *hidden_item; proto_tree_add_item( tree, hf_socks_results_5, tvb, offset, 1, FALSE); hidden_item = proto_tree_add_item(tree, hf_socks_results, tvb, offset, 1, FALSE); PROTO_ITEM_SET_HIDDEN(hidden_item); } ++offset; proto_tree_add_text( tree, tvb, offset, 1, "Reserved: 0x%0x (should = 0x00)", tvb_get_guint8(tvb, offset)); ++offset; offset = display_address(tvb, offset, tree); /*XXX Add remote port for search somehow */ /* Do remote port */ proto_tree_add_text( tree, tvb, offset, 2, "%sPort: %u", (compare_packet( hash_info->bind_reply_row) ? "Remote Host " : ""), tvb_get_ntohs(tvb, offset)); } }
/** * returns the status of the execution * 0 = normal end * 1 = expect mismatch */ int execute_script(int sockfd, registry_t *script) { // current "pc" pointer to script line int curpos = 0; line_t *line = NULL; int lineno = 0; int err = 0; ssize_t size = 0; line_t *errmsg = NULL; scriptlet_t *scr = NULL; while ( (err == 0) && (line = reg_get(script, curpos)) != NULL) { lineno = line->num; switch (line->cmd) { case CMD_COMMENT: if (!trace) { break; } // fall-through case CMD_MESSAGE: log_info("> %s\n", line->buffer); break; case CMD_ERRMSG: errmsg = line; break; case CMD_SEND: for (int i = 0; (scr = reg_get(&line->scriptlets, i)) != NULL; i++) { if (scr->exec != NULL) { scr->exec(line, scr); } } if (trace) { log_hexdump2(line->buffer, line->length, 0, "Send : "); } size = write(sockfd, line->buffer, line->length); if (size < 0) { log_errno("Error writing to socket at line %d\n", lineno); err = -1; } break; case CMD_EXPECT: line->mask = mem_alloc_c(line->length, "line_mask"); memset(line->mask, 0xff, line->length); for (int i = 0; (scr = reg_get(&line->scriptlets, i)) != NULL; i++) { if (scr->exec != NULL) { scr->exec(line, scr); } } err = compare_packet(sockfd, line->buffer, line->mask, line->length, lineno); mem_free(line->mask); line->mask = NULL; if (err != 0) { if (errmsg != NULL) { log_error("> %d: %s -> %d\n", lineno, errmsg->buffer, err); } return err; } break; case CMD_INIT: send_sync(sockfd); err = compare_packet(sockfd, line->buffer, NULL, line->length, lineno); if (err != 0) { if (errmsg != NULL) { log_error("> %d: %s -> %d\n", lineno, errmsg->buffer, err); } return err; } break; } curpos++; } return 0; }
static void display_socks_v4(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, socks_hash_entry_t *hash_info) { /* Display the protocol tree for the V4 version. This routine uses the */ /* stored conversation information to decide what to do with the row. */ /* Per packet information would have been better to do this, but we */ /* didn't have that when I wrote this. And I didn't expect this to get */ /* so messy. */ proto_item *hidden_item; guint command; unsigned char ipaddr[4]; guint username_len, domainname_len; /* Display command from client */ if (compare_packet( hash_info->connect_row)){ proto_tree_add_text( tree, tvb, offset, 1, "Version: %u", hash_info->version); ++offset; command = tvb_get_guint8(tvb, offset); proto_tree_add_text( tree, tvb, offset, 1, "Command: %u (%s)", command, get_command_name( command)); ++offset; /* Do remote port */ proto_tree_add_item( tree, hf_socks_dstport, tvb, offset, 2, FALSE); offset += 2; /* Do destination address */ tvb_memcpy(tvb, ipaddr, offset, 4); proto_tree_add_item( tree, hf_socks_ip_dst, tvb, offset, 4, FALSE); offset += 4; /*XXX check this, needs to do length checking */ /* Should perhaps do TCP reassembly as well */ if ( tvb_offset_exists(tvb, offset)) { /* display user name */ username_len = tvb_strsize(tvb, offset); proto_tree_add_item( tree, hf_user_name, tvb, offset, username_len, FALSE); offset += username_len; if ( ipaddr[0] == 0 && ipaddr[1] == 0 && ipaddr[2] == 0 && ipaddr[3] != 0) { /* 0.0.0.x , where x!=0 means v4a support */ domainname_len = tvb_strsize(tvb, offset); proto_tree_add_item( tree, hf_v4a_dns_name, tvb, offset, domainname_len, FALSE); } } } /*Display command response from server*/ else if ( compare_packet( hash_info->cmd_reply_row)){ proto_tree_add_item( tree, hf_socks_ver, tvb, offset, 1, FALSE); ++offset; /* Do results code */ proto_tree_add_item( tree, hf_socks_results_4, tvb, offset, 1, FALSE); hidden_item = proto_tree_add_item(tree, hf_socks_results, tvb, offset, 1, FALSE); PROTO_ITEM_SET_HIDDEN(hidden_item); ++offset; /* Do remote port */ proto_tree_add_item( tree, hf_socks_dstport, tvb, offset, 2, FALSE); offset += 2; /* Do remote address */ proto_tree_add_item( tree, hf_socks_ip_dst, tvb, offset, 4, FALSE); } else if ( compare_packet( hash_info->v4_user_name_row)){ /*XXX check this, needs to do length checking */ /* Should perhaps do TCP reassembly as well */ if ( tvb_offset_exists(tvb, offset)) { proto_tree_add_text( tree, tvb, offset, tvb_strsize(tvb, offset), "User Name: %s", tvb_get_ptr(tvb, offset, -1)); } } }
/** * returns the status of the execution * 0 = normal end * 1 = expect mismatch */ int execute_script(int sockfd, int toolsfd, registry_t *script) { // current "pc" pointer to script line int curpos = 0; line_t *line = NULL; int lineno = 0; int err = 0; ssize_t size = 0; line_t *errmsg = NULL; scriptlet_t *scr = NULL; // guaranteed to be valid; toolsfd may be not set (<0) int curfd = sockfd; while ( (err == 0) && (line = reg_get(script, curpos)) != NULL) { lineno = line->num; switch (line->cmd) { case CMD_COMMENT: if (!trace) { break; } // fall-through case CMD_MESSAGE: log_info("> %s\n", line->buffer); break; case CMD_ERRMSG: errmsg = line; break; case CMD_SEND: for (int i = 0; (scr = reg_get(&line->scriptlets, i)) != NULL; i++) { if (scr->exec != NULL) { scr->exec(line, scr); } } if (trace) { log_hexdump2(line->buffer, line->length, 0, "Send : "); } size = write(curfd, line->buffer, line->length); if (size < 0) { log_errno("Error writing to socket at line %d\n", lineno); err = -1; } break; case CMD_EXPECT: line->mask = mem_alloc_c(line->length, "line_mask"); memset(line->mask, 0xff, line->length); for (int i = 0; (scr = reg_get(&line->scriptlets, i)) != NULL; i++) { if (scr->exec != NULL) { scr->exec(line, scr); } } err = compare_packet(curfd, line->buffer, line->mask, line->length, lineno); mem_free(line->mask); line->mask = NULL; if (err != 0) { if (errmsg != NULL) { log_error("> %d: %s -> %d\n", lineno, errmsg->buffer, err); } return 1; } break; case CMD_INIT: send_sync(curfd); err = compare_packet(curfd, line->buffer, NULL, line->length, lineno); if (err != 0) { if (errmsg != NULL) { log_error("> %d: %s -> %d\n", lineno, errmsg->buffer, err); } return 1; } break; case CMD_CHANNEL: if ((!strcmp("tools", line->buffer)) && toolsfd >= 0) { curfd = toolsfd; } else if ((!strcmp("device", line->buffer)) && sockfd >= 0) { curfd = sockfd; } else { log_error("> %d: -> unknown channel name %s\n", lineno, line->buffer); return 1; } break; } curpos++; } return 0; }