diff --git a/nselib/bittorrent.lua b/nselib/bittorrent.lua index 48491a8ab..d57ae02e8 100644 --- a/nselib/bittorrent.lua +++ b/nselib/bittorrent.lua @@ -152,6 +152,7 @@ bdecode = function(buf) cur.ref = t table.insert(stack, cur) cur.ref.type="list" + cur.ref.start = pos while true do if pos == len or (len-pos)==-1 then break end @@ -180,6 +181,7 @@ bdecode = function(buf) cur = {} cur.type = "list" cur.ref = new_list + cur.ref.start = pos table.insert(stack, cur) pos = pos+1 @@ -192,11 +194,13 @@ bdecode = function(buf) cur = {} cur.type = "dict" cur.ref = new_dict + cur.ref.start = pos table.insert(stack, cur) pos = pos+1 --escape from the list elseif "e" == string.char(buf:byte(pos)) then + stack[#stack].ref.endpos = pos table.remove(stack, #stack) cur = stack[#stack] if not cur then return nil, "Problem with list closure:", pos end @@ -218,6 +222,7 @@ bdecode = function(buf) if not str then return nil, "Error parsing string.", pos end item.key = str elseif "e" == string.char(buf:byte(pos)) then + stack[#stack].ref.endpos = pos table.remove(stack, #stack) cur = stack[#stack] if not cur then return nil, "Problem with list closure:", pos end @@ -256,6 +261,7 @@ bdecode = function(buf) cur = {} cur.type = "list" cur.ref = item.value + cur.ref.start = pos table.insert(stack, cur) pos = pos+1 @@ -269,12 +275,14 @@ bdecode = function(buf) cur = {} cur.type = "dict" cur.ref = item.value + cur.ref.start = pos table.insert(stack, cur) pos = pos+1 --escape from the dict elseif "e" == string.char(buf:byte(pos)) then + stack[#stack].ref.endpos = pos table.remove(stack, #stack) cur = stack[#stack] if not cur then return false, "Problem with dict closure", pos end @@ -752,200 +760,18 @@ Torrent = -- This function is similar to the bdecode function but it has a few -- additions for calculating torrent file specific fields parse_buffer = function(self) - local buf = self.buffer - - local len = #buf - - -- the main table - local t = {} - self.tor_struct = t - local stack = {} - - local pos = 1 - local cur = {} - cur.type = "list" - cur.ref = t - table.insert(stack, cur) - cur.ref.type="list" - - -- starting and ending position of the info dict - local info_pos_start, info_pos_end, info_buf_count = nil, nil, 0 - - while true do - if pos == len or (len-pos)==-1 then break end - - if cur.type == "list" then - -- next element is a string - if tonumber( string.char( buf:byte(pos) ) ) then - local str - str, pos = bdec_string(buf, pos) - if not str then return nil, "Error parsing string", pos end - table.insert(cur.ref, str) - - -- next element is a number - elseif "i" == string.char(buf:byte(pos)) then - local num - num, pos = bdec_number(buf, pos) - if not num then return nil, "Error parsing number", pos end - table.insert(cur.ref, num) - - -- next element is a list - elseif "l" == string.char(buf:byte(pos)) then - if info_pos_start and (not info_pos_end) then - info_buf_count = info_buf_count +1 - end - - local new_list = {} - new_list.type="list" - table.insert(cur.ref, new_list) - - cur = {} - cur.type = "list" - cur.ref = new_list - table.insert(stack, cur) - pos = pos+1 - - --next element is a dict - elseif "d" == string.char(buf:byte(pos)) then - if info_pos_start and (not info_pos_end) then - info_buf_count = info_buf_count +1 - end - - local new_dict = {} - new_dict.type = "dict" - table.insert(cur.ref, new_dict) - - cur = {} - cur.type = "dict" - cur.ref = new_dict - table.insert(stack, cur) - pos = pos+1 - - --escape from the list - elseif "e" == string.char(buf:byte(pos)) then - if info_buf_count == 0 then - info_pos_end = pos-1 - end - if info_pos_start and (not info_pos_end) then - info_buf_count = info_buf_count -1 - end - - table.remove(stack, #stack) - cur = stack[#stack] - if not cur then return nil, "Problem with list closure:", pos end - pos = pos+1 - else - return nil, "Unknown type found.", pos - end - - elseif cur.type == "dict" then - local item = {} -- {key = , value = <.*>} - -- key - if tonumber( string.char( buf:byte(pos) ) ) then - local str - local tmp_pos = pos - str, pos = bdec_string(buf, pos) - if not str then return nil, "Error parsing string.", pos end - item.key = str - -- fill the info_pos_start - if item.key == "info" and not info_pos_start then info_pos_start = pos end - - elseif "e" == string.char(buf:byte(pos)) then - if info_buf_count == 0 then - info_pos_end = pos-1 - end - if info_pos_start and (not info_pos_end) then - info_buf_count = info_buf_count -1 - end - - table.remove(stack, #stack) - cur = stack[#stack] - if not cur then return nil, "Problem with list closure:", pos end - pos = pos+1 - - else - return nil, "A dict key has to be a string or escape.", pos - end - - -- value - -- next element is a string - if tonumber( string.char( buf:byte(pos) ) ) then - local str - str, pos = bdec_string(buf, pos) - if not str then return nil, "Error parsing string.", pos end - item.value = str - table.insert(cur.ref, item) - - --next element is a number - elseif "i" == string.char(buf:byte(pos)) then - local num - num, pos = bdec_number(buf, pos) - if not num then return nil, "Error parsing number.", pos end - item.value = num - table.insert(cur.ref, item) - - -- next element is a list - elseif "l" == string.char(buf:byte(pos)) then - if info_pos_start and (not info_pos_end) then - info_buf_count = info_buf_count +1 - end - - item.value = {} - item.value.type = "list" - table.insert(cur.ref, item) - - cur = {} - cur.type = "list" - cur.ref = item.value - - table.insert(stack, cur) - pos = pos+1 - - --next element is a dict - elseif "d" == string.char(buf:byte(pos)) then - if info_pos_start and (not info_pos_end) then - info_buf_count = info_buf_count +1 - end - - item.value = {} - item.value.type = "dict" - table.insert(cur.ref, item) - - cur = {} - cur.type = "dict" - cur.ref = item.value - - table.insert(stack, cur) - pos = pos+1 - - --escape from the dict - elseif "e" == string.char(buf:byte(pos)) then - if info_buf_count == 0 then - info_pos_end = pos-1 - end - if info_pos_start and (not info_pos_end) then - info_buf_count = info_buf_count -1 - end - - table.remove(stack, #stack) - cur = stack[#stack] - if not cur then return false, "Problem with dict closure", pos end - pos = pos+1 - else - return false, "Error parsing file, unknown type found", pos - end - else - return false, "Invalid type of structure. Fix the code." - end - end -- while(true) - - -- next(stack) is never gonna be nil because we're always in the main list - -- next(stack, next(stack)) should be nil if we're in the main list - if next(stack, next(stack)) then - return false, "Probably file incorrect format" + local status, t = bdecode(self.buffer) + if not status then + return status, t end + self.tor_struct = t - self.info_buf = buf:sub(info_pos_start, info_pos_end) + for _, i in ipairs(t[1]) do + if i.key == "info" then + self.info_buf = self.buffer:sub(i.value.start, i.value.endpos) + break + end + end return true end,